OmniAICreator/Qiita-1.07M huggingface dataset:
機械翻訳と人力翻訳の是非について

この課題について、世間にはその論争が益々加熱しています。
保守系翻訳会社の見解はご参考ください。

```perl:uniq.pl
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
say uniq(1, 1, 2, 3, 3);
```

（「機械翻訳とは？ 人力翻訳との違いとメリット・デメリット」は https://www.fukudai-trans.jp/column/translation/machine-translation.html より引用）

```ruby:uniq.rb
p [1, 1, 2, 3, 3].uniq
```
Gridsome+Netlify CMS環境のブログ記事へのリンクが"slug"となってしまう

勉強不足でタイトルをどう書いていいのかわからない、ほげほげ事案なので、要件を箇条書きで。

* Gridsomeを使っている
* ヘッドレス管理画面にNetlify CMSを使っている
* ブログ記事（でなくても良いけど）のために、[Content Type Collection](https://gridsome.org/docs/data-store-api/#add-a-content-type-collection)（ワードプレスで言うところの「カスタム投稿タイプ」）を使っている
* gridsome.config.js内のプラグイン設定で、@gridsome/source-filesystemを使用して、Content Type Collectionの宣言からrouteまでを任せている。routeプロパティには、例えば'/blog/:slug'を指定。
* サイトのページテンプレ内でpageまたはstatic queryを使って、記事一覧を表示させている（ワードプレスで言うところの「ループ」）
* 記事一覧内の各々の記事へのリンクを、"path"値を頼って出力している
* すべての投稿記事へのリンクが"slug"となってしまう。

相変わらず、いかにも出来なさそうな頭悪さ全壊な前置きで恐縮です。

仕事用のプロジェクトを実例として出すわけにもまいりませんので、[GridsomeのNetlify CMSスターターテンプレ](https://github.com/mittalyashu/gridsome-starter-netlifycms/blob/master/gridsome.config.js)を例に解決方法をメモします。

解決方法というか、嵌ってしまった原因は、netlifycmsの設定ファイル[config.yml](https://github.com/mittalyashu/gridsome-starter-netlifycms/blob/master/static/admin/config.yml)の20行目（2019年7月14日現在）にありました。

```
- { label: "slug", name: "slug", widget: "string" }
```

この一線を足すだけ。こいつが無いと、なぜかページでのstaticまたはpage-query出力時のpath値にはslugが入るべきところに"slug"が代入されてしまい、記事へのリンクが正しく行えません。

この"slug"フィールドがあれば、Netlify-cms上で、ファイル名とは違ったページのURLに変更できるようになります。

今回の問題は、":slug"の代わりに":id"を使う事で回避していました。記事URLが数字の羅列のidだと、SEO的・UX的にまずいんじゃないかと思っていたんです。別に時間を無駄にしたというわけでは無いですが、疑問だった事が解決したのでスッキリしました。
Kubernetes について要点まとめメモ

# はじめに
この記事は徐々に追記するような形にしようと思っています。
最初から全てともいかないので、要点だけまとめて学ぶ機会があれば徐々に追記していこうと思います。

# Kubernetes とは？
元々 +Docker が前提だったため、とにかく kubernetes 上で Docker を扱うためだけの知識しか入ってないです…
**以下参考文献**
kubernetes だけではないですが、使うだけだったらとてもわかり易かったです。
[【登壇レポート】新卒一年目のSREがコンテナをデプロイできるようになるまでの道のり【JAWS DAYS 2019】](https://medium.com/eureka-engineering/deploy-docker-kubernetes-newgrad-sre-journey-1fb3f017eed7)

ここらへん良さそう
[今さら人に聞けない Kubernetes とは？](https://qiita.com/MahoTakara/items/85096f8b2632c802ab22)
[数時間で完全理解！わりとゴツいKubernetesハンズオン！！](https://qiita.com/Kta-M/items/ce475c0063d3d3f36d5d)
今の所の知識だと以下ぐらいの認識…
**Kubernetes とは、コンテナ技術を活かすための土台となるもの。**
こんな感じ↓
<img width="555" alt="スクリーンショット 2019-07-12 12.37.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269525/cfd08aa1-ea9c-117a-2fba-0494c947d221.png">
**※pod に対し container は 1 対 N でも可能**
Cluster や namespace は色々意味合いがあるようですが、ざっくりといえば**区切り**だと思ってもらえれば。タグ付けみたいな感じ。

そして分かる範囲での kubernetes の利点とはこんな感じ…
**・設定ファイル一つで pod（Container） を即作成することが可能。
・pod が何らかの原因で kill されても自動で再起動してくれる。**

現時点だと要点って感じでもないですね…

## kubectl 
kubernetes + control で kubectl（予想です）
一言で言えば kubernetes を動かすコマンドですね。
使えるようになるまでは以下
1. kubectl をインストール（homebrew が入っていれば `brew install kubectl`）
2. /home に `.kube` というディレクトリを作成
3. その中に `config` というファイルを作成
4. その中に操作を行う対象となる kubernetes のパラメータを記載、保存

これで準備は完了です。
※現場では **Alibaba Cloud** を使っていたのですが、4. のパラメータは Cloud 上にありました。
 多分ものによりけりだと思うので、その時々で要確認

sample
`pod 一覧の取得`

```
$ kubectl get pods -n [namespace]
```
`各 yml 一覧の取得`

```
$ kubectl get deployment -n [namespace]
```
`yml の詳細取得`

```
$ kubectl get service -n [namespace] -o yaml
```

`yml の投入`

```
$ kubectl apply -f [filename.yml]
```

※ [apply 周りのコマンド](https://qiita.com/tkusumi/items/0bf5417c865ef716b221)

## yml yaml とは
先に単語が出てしまいましたが、yml(yaml) とは？
ざっくり言えば、kubernetes を基軸にしたものの各設定値が記載されたファイル(拡張子)のこと
ファイル内の kind に記載したものにより、役割が変わります。
私が把握しているものでは以下
**・deploymennt（pod の作成からコンテナ生成まで）
・service（pod へアクセスを行うための設定）
・configmap（環境変数定義）
・ingress（外部からのアクセス操作） ..etc**
詳しくは前述したリンクの[ハンズオン](https://qiita.com/Kta-M/items/ce475c0063d3d3f36d5d)を読んでみると良いです。

### yml と yaml の違いは？
**ないです。**
呼称の違いなだけで洗わずものは同じだそうです。
前述のコマンドを見ていただくと分かる通り、公式的には **yaml** が推されているようですが、
多く使われているのは **yml** のようです。
こんなやり取りもあったり。
[yamlの拡張子が yaml と yml で揺れている](https://github.com/kmuto/review/issues/244)
このやりとりのように、各現場で使う呼称とかを決めるのも良いかもしれませんね。

# 〆
正直全容はまったく理解できていないし、見えていない。
深掘りすると闇が深そうなので、インフラがメインとなるわけではないのであれば多少触れる程度で良さげ…
学んだことがあれば追々追加予定
Carrierwaveの導入で手間取ったので忘備録。

##1.まずは公式ページを。
https://github.com/carrierwaveuploader/carrierwave#installation

##2.Imagemagickのインストール
```
$ brew install imagemagick
```

##3.Gemのインストール
```
$ gem install carrierwave
```

##4.Gemfileの編集
```
gem 'carrierwave'
gem 'mini_magick'
```
からの、、bundel install


##5.postsテーブルに image column を追加
```
$ rails g migration add_image_to_posts image:string
```
##6.uploader ファイルを作成
```
$ rails g uploader image
```

##7.models/post.rb を編集
以下を追加

```
mount_uploader :image, ImageUploader
```

##8.posts_controller  のストロングパラムズを編集
:image,:image_cache　を追加

```
def post_params
   params.require(:post).permit(:title,:content,:image,:image_cache)
end
```

##9.image_uploader の編集
```
include CarrierWave::MiniMagick

  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
  
# 画像の上限を700pxにする
  process :resize_to_limit => [700, 700]

# jpg,jpeg,gif,pngしか受け付けない
  def extension_white_list
    %w(jpg jpeg gif png)
  end
```

##10.new page
注意：image_tagの前にfが付くとエラーになるので気をつけて！！

```
<div>
    <%= f.label :image %>
    <%= image_tag @post.image.url if @post.image? %>
    <%= f.file_field :image %>
    <%= f.hidden_field :image_cache %>
</div>
```

##11.confirm page
```
<h1>Are you ok?</h1>
<%=form_with(model:@post,url:posts_path,local:true)do |f|%>
  <%=f.hidden_field :title%>
  <%=f.hidden_field :content%>
  <%=f.hidden_field :image_cache%>

  <p>Title:<%=@post.title%></p>
  <p>Content:<%=@post.content%></p>
  <p>Image:<%=@post.image.url %></p>
  <%=f.submit 'OK!'%>
<% end %>

<%=form_with(model:@post,url:new_post_path,local:true,method:'get')do |f|%>
  <%=f.hidden_field :title%>
  <%=f.hidden_field :content%>
  <%=f.hidden_field :image_cache%>
  <%=f.submit 'Back!',name:'back'%>
<% end %>
```

##12.index page
```
<div>
        <% if post.image? %>
        <%= image_tag post.image.url %>
        <% else %>
        <p>No Image</p>
        <% end %>
 </div>
```

##13.show page
```
<div>
	<% if @post.image? %>
	<%= image_tag @post.image.url %>
	<% else %>
	<p>No Image</p>
	<% end %>
</div>
```
以上です。
##注意点）
当初、以下のようなサムネイル作成メソッドをimage_uploaderに入れていたが、それが原因で日本語名の画像ファイルが文字化けしてエラーとなっていた。
これを削除すると日本語名の画像ファイルも正常にアップロードできるようになった。

```
version :thumb do
    process :resize_to_limit => [300, 300]
  end
```
OpenCV(4.1.0) + Visual Studio 2019の設定忘備録

久しぶりにVisual Studioを開いて、OpenCVの設定を行ったので忘れないようにメモしました。

## 参考にしたサイト

https://qiita.com/h-adachi/items/aad3401b8900438b2acd

https://qiita.com/mental_hell/items/4a19ae450f5909d099ed

## ダウンロード

openCVのgithubのリリースバージョンがexeファイルをダウンロードします。

https://github.com/opencv/opencv/releases

exeファイルを実行して、展開します。
`C:\OpenCV\opencv410`に展開しました。


## パスの設定

ユーザ環境変数に`C:\OpenCV\opencv410\build\x64\vc15\bin`を追加しました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15925/a2a28fd4-aca3-657b-8984-9a5ce200792f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15925/ac1b7cf9-8ca8-6fd6-0b2c-2b364d8edd61.png)

環境変数について参考にされる方は下を確認してください。

### Windows10でTempやPathなどの環境変数を設定する方法
https://proengineer.internous.co.jp/content/columnfeature/5205

**※注意**

最初は環境変数を設定せず、サンプルコードを実行したら、not foundと実行できませんでした。パスの設定は大事でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15925/07ef8671-8582-70ac-0123-b9875b818a64.png)


## Visual Studioのプロパティの設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15925/2a6b5352-168d-0cfa-2db1-21e7aab2eb69.png)


VC++ Directories上で以下の設定を追加します。

Include Directories: `C:\OpenCV\opencv410\build\include`

Library Directories: `C:\OpenCV\opencv410\build\x64\vc15\lib`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15925/6a32d261-359f-ba43-7efb-6d040c997462.png)

Linker/Inputで以下を設定を追加します

Additional Dependencies: `opencv_world410d.lib`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15925/0613f2b5-26ab-25bc-efb9-56f467cd7fe4.png)

以上で設定が完了です。

## デモ

こちらのデモを実行しました。

https://qiita.com/h-adachi/items/aad3401b8900438b2acd#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15925/5030d258-75ec-a24b-4a69-9313a793ad45.png)

小さなwindowが生成されたら設定成功です。
Azureの仮想マシンで作ったDockerコンテナをラズパイに入れたい(失敗)

#高速な仮想マシンでコンテナを作って楽がしたい
DonkeyCarをやり始めて、早くも半年、インストールやコンパイルを繰り返していますが、
低速なラズパイでインストールに時間をかけるのが苦痛になってきました。

人間はもっと生産的な仕事をするべきと、今更ながら思いました。

使ったことのないMicrosoft Azureをあれこれしていて、不毛に時間を使いました。
でも、やりたいことは、

「仮想ラズパイマシンでDocker動かしてイメージ作れたらOKでしょ？」

これだけです。

#仮想マシンを作る。
メモを書きながら実際にやってみます。

参考にしたのはこちら。
https://note.mu/kikuzokikuzo/n/na2e82c1c8835

先達に感謝！

作成する仮想ラズパイマシンは

+ 64bit ARM8プロセッサで動かす
+ 32bit RaspbianOS (Stretch). BurstはDonkeyCarが不安定らしい
dockerを動かしてイメージビルド（qemuによるエミュレーションを利用）


私はAzureで仮想マシンを作ってみます。
チュートリアルに従って、粛々と作ることとします。（コマンドラインでやるのは面倒なのでポータルでやります）
https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/quick-create-portal

あっさり出来上がり。Azure Cloud Shellでsshで接続。

#色々入れてみるも、決め手に欠く
なぜか、インストールでパスがないなどの異常が出ますね。

この辺りも参考にしてみたけど、RaspberryPi仮想マシン作るの実は需要なのか？
というか、そもそも難しく考えすぎか？
要はARM64の環境を作って、Raspbianのstretchをインストールしたら良いのでは？

http://matsujirushi.hatenablog.jp/entry/2018/04/15/214721
http://matsujirushi.hatenablog.jp/entry/2018/05/13/113219

ちょっと方針変換。

http://innossh.hatenablog.com/entry/2018/06/22/170734

仮想マシン上で、ラズパイ仮想マシンを作り、その中でDockerを動かせばよろしいのでは？

#Donkey CarにはDockerfileが入っていた

ハッカーばかりでドキュメントが（一部）不親切なDonkeyCarのリポジトリにDokerfileが入っていました。
浜松のunagi.piでDonkeyCarソースコードを読む勉強会に参加したところ、これを実際に動かすことに成功した人がいました。

buildやcmakeの環境を色々考えると面倒ですが、Dockerfileからコンテナを作るだけなら行けそうです。

#クラウドでインストールしても早くならない

https://www.slideshare.net/ShunsukeKikuchi1/raspberry-pi-147400803?from_m_app=ios

調べながらやっているうちに、実際にやって見た人発見。
どうやら浮動小数点演算をハードウェアでやっていないためと思われるスローダウンで、クラウドでやってもあまり高速にはならないそうだ。

#ちょっと目先を変える

64bitのラズパイ4とburstが出るまで待ってから、実際にやってみよう。
JETSONの方がクラウドコンパイルとは相性が良さそう。

なので、raspberrypi4 + Azure　を置いて、
JETSON nano + AWS で今から環境のセットアップをやってみることとします。
JFreeChart-上限線、下限線の設定


目次 ⇒ [JFreeChartサンプル](https://qiita.com/artery/items/3e9c63e5c14a9e965c97)

```java
package jp.avaj.lib.chart;

import java.awt.Color;

import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.Marker;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
■ JFreeChart-上限線、下限線の設定

・測定値などの場合、許容範囲の上限と下限を示すために、グラフの中に線を引くと分かりやすい.

 */
public class Chart18_03 {

  public static void main(String[] args) {
    // 表示データを生成
    XYDataset dataset = createDataset();
    // 軸を生成
    ValueAxis xAxis = new NumberAxis();
    ValueAxis yAxis = new NumberAxis();
    // レンダラ ⇒ これが全体のレンダラになる
    XYItemRenderer renderer = new StandardXYItemRenderer();
    // Plotを生成してチャートを表示する
    XYPlot xyPlot = new XYPlot(dataset,xAxis,yAxis,renderer);
    JFreeChart jfreeChart = new JFreeChart("limit-line",(Plot)xyPlot);
    ChartFrame cFrame = new ChartFrame("limit-line",(JFreeChart)jfreeChart);
    cFrame.pack();
    cFrame.setVisible(true);

    // 上限線、下限線を引く
    {
      Marker marker = new ValueMarker(10);
      marker.setPaint(Color.red);
      xyPlot.addRangeMarker(marker);
      //
      marker = new ValueMarker(2);
      marker.setPaint(Color.blue);
      xyPlot.addRangeMarker(marker);
    }
  }

  private static XYDataset createDataset() {
    XYSeriesCollection dataset = new XYSeriesCollection();
    // 一本目
    XYSeries xySeries = new XYSeries("data-0");
    for (int j=0; j<10; j++) {
    xySeries.add(j,j+Math.random()*4.0D);
    }
    dataset.addSeries(xySeries);
    // 二本目
    xySeries = new XYSeries("data-1");
    for (int j=0; j<10; j++) {
    xySeries.add(j,9-j+Math.random()*4.0D);
    }
    dataset.addSeries(xySeries);
    return dataset;
  }
}

```


![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278568/22d182e6-115c-f370-c4a1-e5dc050c007d.png)
JFreeChart-グリッドの色と太さを変える


目次 ⇒ [JFreeChartサンプル](https://qiita.com/artery/items/3e9c63e5c14a9e965c97)

```java
package jp.avaj.lib.chart;

import java.awt.BasicStroke;
import java.awt.Color;

import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import jp.avaj.lib.algo.ArUtil;

/**
■ JFreeChart-グリッドの色と太さを変える

 */
public class Chart18_02 {

  public static void main(String[] args) {
    // 表示データを生成
    XYDataset dataset = createDataset();
    // 軸を生成
    ValueAxis xAxis = new NumberAxis();
    ValueAxis yAxis = new NumberAxis();
    // レンダラ ⇒ これが全体のレンダラになる
    XYItemRenderer renderer = new StandardXYItemRenderer();
    // Plotを生成してチャートを表示する
    XYPlot xyPlot = new XYPlot(dataset,xAxis,yAxis,renderer);
    JFreeChart jfreeChart = new JFreeChart("Grid-Line",(Plot)xyPlot);
    ChartFrame cFrame = new ChartFrame("Grid-Line",(JFreeChart)jfreeChart);
    cFrame.pack();
    cFrame.setVisible(true);

    // 目で確認するために少し休む
    ArUtil.sleep(4000);

    // グリッドの色と太さを変更する
    xyPlot.setDomainGridlinePaint(Color.red); // X軸
    xyPlot.setDomainGridlineStroke(new BasicStroke(2.0F)); // X軸
    xyPlot.setRangeGridlinePaint(Color.red);  // Y軸
    xyPlot.setRangeGridlineStroke(new BasicStroke(2.0F)); // Y軸
  }

  private static XYDataset createDataset() {
    XYSeriesCollection dataset = new XYSeriesCollection();
    // 一本目
    XYSeries xySeries = new XYSeries("data-0");
    for (int j=0; j<10; j++) {
    xySeries.add(j,j+Math.random()*4.0D);
    }
    dataset.addSeries(xySeries);
    // 二本目
    xySeries = new XYSeries("data-1");
    for (int j=0; j<10; j++) {
    xySeries.add(j,9-j+Math.random()*4.0D);
    }
    dataset.addSeries(xySeries);
    return dataset;
  }
}

```

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278568/f9b73b4a-8b93-05ed-c87c-f46270857ecc.png)
JFreeChart-グリッドを表示しないようにする


目次 ⇒ [JFreeChartサンプル](https://qiita.com/artery/items/3e9c63e5c14a9e965c97)

```java
package jp.avaj.lib.chart;

import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import jp.avaj.lib.algo.ArUtil;

/**
■ JFreeChart-グリッドを表示しないようにする

 */
public class Chart18_01 {

  public static void main(String[] args) {
    // 表示データを生成
    XYDataset dataset = createDataset();
    // 軸を生成
    ValueAxis xAxis = new NumberAxis();
    ValueAxis yAxis = new NumberAxis();
    // レンダラ ⇒ これが全体のレンダラになる
    XYItemRenderer renderer = new StandardXYItemRenderer();
    // Plotを生成してチャートを表示する
    XYPlot xyPlot = new XYPlot(dataset,xAxis,yAxis,renderer);
    JFreeChart jfreeChart = new JFreeChart("Grid-Line",(Plot)xyPlot);
    ChartFrame cFrame = new ChartFrame("Grid-Line",(JFreeChart)jfreeChart);
    cFrame.pack();
    cFrame.setVisible(true);

    // 目で確認するために少し休む
    ArUtil.sleep(4000);

    // グリッドを表示しないようにする
    xyPlot.setDomainGridlinesVisible(false);
    xyPlot.setRangeGridlinesVisible(false);
  }

  private static XYDataset createDataset() {
    XYSeriesCollection dataset = new XYSeriesCollection();
    // 一本目
    XYSeries xySeries = new XYSeries("data-0");
    for (int j=0; j<10; j++) {
    xySeries.add(j,j+Math.random()*4.0D);
    }
    dataset.addSeries(xySeries);
    // 二本目
    xySeries = new XYSeries("data-1");
    for (int j=0; j<10; j++) {
    xySeries.add(j,9-j+Math.random()*4.0D);
    }
    dataset.addSeries(xySeries);
    return dataset;
  }
}

```


![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278568/1e1a24e5-17ee-9f4c-59b1-2c9e52056359.png)
JFreeChart-NumberAxis-目盛りの間隔の設定


目次 ⇒ [JFreeChartサンプル](https://qiita.com/artery/items/3e9c63e5c14a9e965c97)

```java
package jp.avaj.lib.chart;

import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.axis.TickUnits;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import jp.avaj.lib.algo.ArUtil;

/**
■ JFreeChart-NumberAxis-目盛りの間隔の設定

 */
public class Chart18_00 {

  public static void main(String[] args) {
    // 表示データを生成
    XYDataset dataset = createDataset();
    // 軸を生成
    ValueAxis xAxis = new NumberAxis();
    ValueAxis yAxis = new NumberAxis();
    // レンダラ ⇒ これが全体のレンダラになる
    XYItemRenderer renderer = new StandardXYItemRenderer();
    // Plotを生成してチャートを表示する
    XYPlot xyPlot = new XYPlot(dataset,xAxis,yAxis,renderer);
    JFreeChart jfreeChart = new JFreeChart("Unit-Tick",(Plot)xyPlot);
    ChartFrame cFrame = new ChartFrame("Unit-Tick",(JFreeChart)jfreeChart);
    cFrame.pack();
    cFrame.setVisible(true);



    // y軸の目盛りを設定する
    {
      // 目で確認するために少し休む
      ArUtil.sleep(4000);
      // y軸の目盛りを設定する
      // 複数個設定できる⇒拡大した時は、細かいものが使用される
      TickUnits ty = new TickUnits();
      ty.add(new NumberTickUnit(2.0));
      ty.add(new NumberTickUnit(0.5));
      yAxis.setStandardTickUnits(ty);
    }
  }

  private static XYDataset createDataset() {
    XYSeriesCollection dataset = new XYSeriesCollection();
    // 一本目
    XYSeries xySeries = new XYSeries("data-0");
    for (int j=0; j<10; j++) {
    	xySeries.add(j,j+Math.random()*4.0D);
    }
    dataset.addSeries(xySeries);
    // 二本目
    xySeries = new XYSeries("data-1");
    for (int j=0; j<10; j++) {
    	xySeries.add(j,9-j+Math.random()*4.0D);
    }
    dataset.addSeries(xySeries);
    return dataset;
  }
}

```

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278568/85b1ceec-a1fa-86c1-dadd-9290ccc7e5b0.png)
AWSの勉強

Alexaを買ってアプリを作っているうちにAWSについても勉強しようと思ったので、そのメモ。

１．IAM(あいあむ)ユーザーの設定
２．CloudWatch機能を使って料金アラートを設定する
３．見積方法
http://calculator.s3.amazonaws.com/index.html?lng=ja_JP

# ネットワーク
## 基本
東京リージョンの中に、アベイラビリティゾーン(AZ)が3つある。
サブネットはAZに紐付く。
ルートテーブルはサブネット単位に設定する。

## 使用できるIPアドレス
0,1,2,3,最後の5個はAWSが予約しているため使用できない

## Elastic IPアドレス
IPアドレスを固定。
基本は無料だが、サーバが止まっている場合は料金がかかるので注意

## S3(Simple Storage Service)

# サービス一覧

|No|サービス名|説明|重要度|
|:--:|:--|:--:|:--:|
|1|VPC||〇|
|2|EC2|Elastic Compute Cloud。クラウド内の仮想サーバ|〇|
|3|RDS||〇|
|4|ELB|ロードバランサ|
|5|S3||〇|
|6|Route 53||
|7|IAM||
|8|SES|Mail|

## 1.VPC
### 1-1.作成順序

1.リージョンを決める。(東京リージョンにする)
2.VPCは複数のAZにまたがって作成
3.サブネットはAZ毎に作成する(マルチAZ構成にすると)

### 1-2.VPCの作成
VPCダッシュボード上で、「VPCウィザードの起動」ボタンをクリック。
これでサブネットやルートテーブルも自動で作成される。

### 1-3.サブネットの作成
自分で追加作成したサブネットはルートテーブルの設定が外に出ない設定になっているので、ウィザードで作ったものと同じように設定する。

### 1-4.ルートテーブルについて
ウィザードで作成すると自動で作られる。


## 2.EC2
サーバを利用できる
### 2-1.ポイント
- OS / Imageの選択
- インスタンスタイプの選択
- ストレージの選択
- セキュリティグループの設定
- SSHキーペアの設定

### 2-2.SSHでの接続
IPアドレス："IPv4 パブリック IP"の値
ユーザー名：ec2-user
パスワード：ダウンロードしたSSHキーファイルを指定

#4.ELB

EC2の中に設定するロードバランサ。

- ALB Application Load Balancer 
- NLB Network Load Balancer 
- CLB Classic Load Balancer

ALBはL7レベルで、NLBはL4レベルでの振り分けが可能。

## ALB

# 5.S3
## 5-1.S3がよく使われるシーン

- 静的コンテンツの配信
- ログなどのエクスポート先
- バッチ連携用のファイル置き場
- 静的Webホスティング


# 99.おまけ
## 99-1.Teraterm
### Beep音を止める
INIファイルに「Beep=on」となっている個所があるので、offにする。

### SSH接続のユーザ名を自動入力
「SSH認証」画面で設定する。

## 99-2.Linuxの設定

### ホスト名の変更
以下を参照
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/set-hostname.html
https://www.opensourcetech.tokyo/entry/2018/05/08/CentOS7_%E3%81%AE%E3%83%9B%E3%82%B9%E3%83%88%E5%90%8D%E8%A8%AD%E5%AE%9A%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%EF%BC%88hostname_/_nmcli_/_nmtui_/_hostnamectl_/_uname%EF%BC%89

### OS の言語設定

sudo vi /etc/sysconfig/i18n

====

前）LANG=en_US.UTF-8

後）LANG=ja_JP.UTF-8

====

### OS の時刻設定

sudo cp /usr/share/zoneinfo/Japan /etc/localtime

sudo vim /etc/sysconfig/clock

====

ZONE="Asia/Tokyo”

====

### ミドルウェアのインストール
MySQL
https://qiita.com/himatani/items/e1e650992dbc12b8a9b3
PHPでRARファイルの解凍をする

# はじめに
RARファイルの解凍をやりたかったけど、公式ではZipArchiveしかないみたい。
PECLの方にRarArchiveというのがあるみたいなので、これを使う。

# 環境
 - Windows 7
 - PHP 7.1

# RarArchiveのダウンロードと設定
[ここ](https://pecl.php.net/package/rar)からダウンロード。
僕はWinなのでVer.4.0.0 の「DLL」 -> 「7.1 Non Thread Safe (NTS) x86」をダウンロードしました。
ダウンロードしたやつの中身に「php_rar.dll」があるので、それを php の ext フォルダに配置。
`php.ini`に以下追記。

```php.ini
[PHP]
extension=php_rar.dll
```
追記後、サーバー再起動。

# 解凍
```php
$archive = RarArchive::open("dir/");
$entries = $archive->getEntries();
foreach ($entries as $entry) {
    $entry->extract($to_dir);
}
$archive->close();
```
ZipArchive との違いは、一度`getEntries`しないと中身がとれない。

ついでに、パスに日本語が含まれていると Failed to open になるっぽいです。

# さいごに
公式で扱える形式増やして(懇願
「SPAらしさ」について考える(メモ)

ここ最近Reactを使ったSPAの開発に勤しんでいたところ

やればやるほどSPAってなんなんだとなった。
単一ページ？いやでも複数ページあるけど。
ゲシュタルト崩壊を起こした。

エスピーエー　ワカラナイ　ググル
ググッタ　メイカク　テイギ　ナイ

SPAというのはなんとなく定義されているものの明確な定義はないらしい。

というわけでどういうものが**「SPA」**だと感じるのか
ひいては**「SPAらしさ」**とはなにかについて考察してみた。

# 結論

あらかじめ結論を書いてしまうと
この記事を書いた結果以下の結論に行き着いた(あくまで個人の見解)

**SPAらしさ＝ネイティブっぽいかどうか**

以下は**SPAらしさ**ってなんだとか
なんかもういろいろごちゃごちゃ語っています。



# SSRはどうか

SSRってそもそもサーバーでHTML作ってるし
普通に通信発生してるし

バックエンドとフロントエンドのソースコードを共通化できる
アイソモーフィックではあるものの
SPAらしくない。

結局通信してURLに対し異なるHTMLを返すというのは
先祖返りというか、それSPAで作る意味あったの。。。

という疑惑を抱いてしまうので「SPAらしくない」と判断。

(でも検索ロボットに対してのみSSRするならSPAらしいと思う)

# SPAの利点？

> 通常のWebページではできないUXができる
> 高速なページ遷移
> 読み込みが早い

など、色々言われてはいるものの
正直そこまでメリットと言えるレベルか？という思いもあり
SPA自体にはさほどメリットはないと思っている。

# SPAは副産物的なものでは？

SPAがトレンドっぽくなっているのは
SPAにメリットがあるのではなく

バックエンド側をシンプルなAPIの実装のみにすることにメリットがあった
と言う方が正しいと思っている。

JSONを返すだけのAPIは
ネイティブからもウェブからも利用できる

じゃぁ次はネイティブもフロントも同じコードで書けたらいいよね
とアイソモーフィックを目指した結果のSPA

と考えた方がしっくりくる。

# SPAは早い？

SPAは読み込みが早いと言われることもあるが
JSが肥大化して実はそんな早くないということも珍しくないと思うし

パフォーマンスチューニングによって
最終的に従来のウェブサイトより早くできるとは思うものの

それがすごいメリットと言えるほどかというと微妙なラインでは？

# jQueryでは限界がある？

よく複雑なDOM操作をjQueryでやるのは大変と説明されることもあるが

DOM操作だけで考えた場合、jQueryの方が優れていると感じる面もある。
従来のウェブサイトらしいサイトであればjQueryのがはるかに簡単だし
十分なケースも多いと思われる。

ただDOM生成やネイティブアプリレベルのDOM操作
という観点で考えた場合はやはりReactの方が優れていると感じる。
(あとVDOMによる差分更新もメリットか)

ネストされたDOM構造をjQueryで頑張って作っていくというのは
不可能ではないがあまり書きたいとは思えない。(好みの問題)

# Reactを使う理由

個人的になぜReactを使うかという事を改めて考えた場合

①バックエンドはAPIだけにしたい
②DOM生成をjQueryでやるのはつらい
③VDOMによる差分レンダリングだから無駄が少ない

という3点からReactを採用しているようだ。
(なんとなく利点は感じていたものの、改めて自覚した)

将来的にネイティブにも横展開できるかどうかという点はさほど考えていない。
(簡単にできるなら嬉しいなー程度)

# 個人的な悩みの解決

従来のWebサイトのようなSPAっぽくないサイトを
Reactで作る意味はあるのかというもやもやがあったのだが

今持てる知識の中で
バックエンドはAPIのみにしたいとなった場合

フロントは以下の２択を迫られる

①静的なhtmlでサイトを作るか
②SPAで作るか

SPAで作るメリットあるのかと思っていたが
バックエンドをAPIだけにできるじゃんと考えるとスッキリできた。


# 主となるのがフロントなのかバックエンドなのか

これは個人的な感覚が強い部分だが
APIからデータを取得する頻度は少ない方がSPAらしく感じる。

ゲームなんかでは、基本的にプレイ中は常にオンメモリでデータが管理され
セーブ時に必要なデータをまとめてHDD等に保存する

この作りに近いほどSPAらしさを感じる。

SPAらしくないと感じる例としては
何かしらデータを更新するたびに最新のデータをAPIから取得しなおして
画面を全更新かけるような作りである。

基本的にフロント側でデータを管理し
バックエンドはデータの保管場所程度
というくらいがSPAらしいのではないかと感じる。

# まとめ

上記を踏まえたまとめ

## SPAのメリット

①バックエンドをAPIだけにできる
②ネイティブの作りっぽくなるほど恩恵が得られやすい

## Reactのメリット

①DOM生成楽
②ある程度規模が大きくなっても管理しやすい(実力次第でもある)

## SPAらしさ

ネイティブに近いほどSPAらしさが出る

## SPAらしさを損なう要因

- SSR
- APIに頼りすぎるDOM更新


# あとがき

五月雨に書きなぐった事で
今までもやもやしていた事が自分なりに整理されました。

そしてSPAは難しいと言う事も再確認できました。

SPAを開発するとなった場合、多くはReactかVueを使うことになると思いますが

そもそもjQueryだけでもそこそこ複雑なアプリケーションを作る事は可能です。

にも関わらずReactやVueという新しいフレームワークが誕生したのは
jQueryで作るのが難しいくらい複雑なものを作ろうとしているからだと思いました。

いくらReactを使えばSPAが作れるといったところで
そもそもSPAが難しいジャンルであり
(特にReactはあくまでViewライブラリ、Store管理は別途知識が必要ですし)

それなりの技術力、設計力、経験値がなければ
ReactやVueを使ったところでカオスになってしまう。

でも、だからこそ挑戦しがいがあり、面白く感じる自分がいる
そうも思いました。

終わり。
Laravel vs Symfony（DDDの場合）

PHP で DDD（ドメイン駆動設計）をする案件でウェブフレームワークの選定を行いました。

フレームワーク選定にあたり、以下の方針を立てました。

- 実績のあるフレームワークから選定（Laravel か Symfony の２択としました）
- DDD が提唱している不変条件をモデルに実装出来ること
- フレームワークと戦わない（目的達成の為に Hack 等の小細工をしない）
- 人がレビュー等で注意するといった回避策で妥協しない
- なるべくシンプルにフレームワークを使う

本来、フレームワークはドメイン層に関心がなく DDD に制約を与えないはずです。
一方で DDD はドメイン層以外には具体的な実装方法を提示していません。
DDD をやるのにどのフレームワークを使ってもいいのでは？と思うのですが、実際にはそうではありませんでした。

フレームワークが採用している ORM によって DDD しやすいものと困難なものがあります。

FW|ORM|パターン|調査結果
---|---|---|---
Laravel|Eloquant|Active Record|設定が無く簡単<br>モデルで constructor や public, private といったアクセス修飾子が自由に使えない<br>モデルに不変条件の実装ができずDDDに不向き
Symfony|Doctrine|Data Mapper|DBのテーブルカラムとモデル属性のマッピング設定が必要<br>モデルで constructor や public, private といったアクセス修飾子が自由に使える<br>モデルに不変条件の実装ができてDDDに向いている

上記表の結果から PHP での DDD 案件では Symfony を採用することに決定しました。

我々は Laravel をとても気に入っていたので、なかなか Laravel をあきらめる気にはなれませんでした。しかし、色々と調べたのですが良い方法は見つかりませんでした。Active Record でもうまくDDDやっているという方がいましたら、ぜひ、知見をお聞かせください。

#### 参考情報

[モデルでドメイン知識を表現するとは何か](https://qiita.com/little_hand_s/items/69ccbb9915d75ad09ad5)・・・不変条件について、とても分かりやすい記事です
Kotlin/JSでobjectの中身を確認するときはJSON.stringifyが便利

Kotlin/JS開発の小ネタです。
Kotlin/JSでフロントエンド開発していると、往々にしてJavaScriptのobjectの中身を確認したくなります。

```kotlin
package example

fun main() {
    val obj: dynamic = js("({key: 'value'})")
    println(obj)
}
```

しかし、上記のコードは`[object Object]`と出力します。

そこで便利なのが`JSON.stringify`です。

```kotlin
package example

fun main() {
    val obj: dynamic = js("({key: 'value'})")
    println(JSON.stringify(obj))
}
```

上記のコードの出力は`{"key":"value"}`となり、期待通りの結果が得られました。
もちろんこれはstringとして出力されるので、開発者ツールで開いたり閉じたりできるアレは使えません。

たぶん`toString()`の兼ね合いでこうなっていると思うんですが、よしなに出来るようになるといいですねえ
論文まとめ：Towards Accurate Multi-person Pose Estimation in the Wild

# はじめに

CVPR2017 から以下の論文
[1] G. Papandreou, et. al. "Towards Accurate Multi-person Pose Estimation in the Wild"
のまとめ

ちょっと古いが、その後にPersonLabやPifPafに与えた影響を考慮して、decoderのロジック部分を中心にまとめ

arXiv：
https://arxiv.org/abs/1701.01779

# 概要
1. top-down 方式で姿勢推定を行うモデル
2. これまでのheatmap方式を２つのstageに分解し、１つをkeypoints周辺領域の推定、他の１つを近傍のkeypointsの位置を推定されるようにした。
3. 以上の手法を用いることで、2017年初頭あたりで COCO keypoints dataset でSOTAを達成。

# アーキテクチャの全体像
以下の図が全体像。

<img width="591" alt="toward_accu_img00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/df5dfcb7-54d0-5915-f840-42c44715f477.png">

top-down形式なので、上手のように２段階に分かれる。

1段階目で画像から各人のbounding box を切り取る。

2段階目で切り取った人の画像から姿勢を推定する。

この論文では1段階目のベース・モデルはFaster-RCNN、2段階目のベース・モデルはResNet。

# 姿勢推定アーキテクチャ  
2段階目の姿勢推定の詳細。

## 従来の keypoints の推定方法
まず従来の keypoints の推定方法をおさらい。主に以下の２つ。

(1) DeepPose [2] によって提案された手法で、画像を入力して、各 keypoints の相対座標を数値として出力させる。つまり回帰問題として解く手法。

この手法では、画像に２人以上が入った場合、同じ keypoints が２つ以上となり、正しい相対座標が推定されない。

(2) [3] により提案された手法で、各keypointsのheatmap的なものを出力する。つまり各pixelはkeypointsか否かの分類をしてるようなもの。

これにより２つ以上の keypoints が存在する場合に対応できるようになったが、mapが特徴量の大きさに依存するため粗くなる。例えば、通常畳み込んで畳み込んで、出力の時点では特徴量が8x8とか20x20のようになるが、これで画像上の正確な位置を示すのは困難。

## 提案手法の概要 
本論文の提案手法は上記（２）の問題を解決するもの。 

モデルからは以下の２種類を出力する。  
1. 各keypoint から 半径 R ピクセルにあるか否かを表す heatmap（１チャンネル）
2. 近傍にある各keypoint の位置を表すベクトル（２チャンネル）

この３チャンネルをcoco dataset だと 17 keypoints に対して出力するので、出力チャンネルは $ 3 \times 17 = 51$ 。

例えば以下の図では

<img width="462" alt="toward_accu_img01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/287be617-50b7-e1bf-44af-d03b60814820.png">

フェデラ〜？の左肘に対して一定の半径となるheatmap（中央）を推定するのと同時に、その半径内のピクセルは肘の正確な位置をベクトルで推定する（右）

## 提案手法の詳細  

まず　　
$h\_k (x\_i)$ ：画像 $x$ 中のピクセル $x\_i$ における $k$ 番目のkeypintのheatmap
$l\_k$ ：keypoint $k$ の正確な位置
として、あるピクセル $x\_i$ が keypointの正確な位置から半径 $R$ 以内ならそのピクセルの heatmap を１とする。つまり

```math
h_k (x_i) = 1 \ \ if \ \| x_i - l_k \| \leq R
```

またkeypointsの正確な位置を指すベクトル (offset vector) は

```math
F_k(x_i) = l_k - x_i
```

とする。これらheatmap、および offset vector から正確なkeypointの位置を計算する。

これはより正確なheatmap・・・highly localized activation map $f\_k (x\_i)$ は以下で求める。

```math
f_k(x_i) = \sum_j \frac{1}{\pi R^2} G( x_j + F_k(x_j) - x_i) h_k (x_j)
```

ここで $G$ は bilinear interpolation kernel。

$G$ のカッコの中は $x\_j + F\_k(x\_j) - x\_i = l\_k - x\_j$ なので任意点 $x\_j$ から keypoint推定位置 $l\_k$ へのベクトル。これに対して bilinear interpolation kernel をとっている。

これに $h\_k(x\_j)$ をかけてるので、keypointから半径 $R$ の円（と推定された位置）のみを対象としている。

この円は正確に推定されると $\pi R^2$ の面積があるので、それで割って正規化している。

これを全ての $j$ に対して足し合わせることで、$x\_j$ における highly localized activation map $f\_k (x\_i)$ を算出している。

これを図で表すと以下。

<img width="484" alt="toward_accu_img02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/db594239-729c-70a1-4ece-5926bd3edcdd.png">






# reference
[2] A. Toshev and C. Szegedy. Deeppose: Human pose estima- tion via deep neural networks. In CVPR, 2014.

[3] A.Jain,J.Tompson,M.Andriluka,G.Taylor,andC.Bregler. Learning human pose estimation features with convolutional networks. In ICLR, 2014.
エンジニアだけど読めば考え方が少しだけ世の中の見え方が変わるかもしれない本

# はじめに
どうして読書をするようになったかが書いてあるだけなので、時間の無い方は読み飛ばして大丈夫です。

私はこれまでエンジニアはコードが書ければいいのではないかと思っていました。
ですが、年齢を重ねて色々な失敗をして次はどうすれば失敗しないで済むかと考えた結果たどり着いたのが読書でした。

著者たちの経験や苦労した事をいかに解決したか等々、私の知らない事を短時間で学べるのです。
それを知ってからエンジニアリング以外の本も積極的に読むようになり考え方の幅がとても広がりました。

その中でも特に影響の大きかった本を紹介したいと思います。

# 読むとどうなる
今回紹介する本を読むと、不確実性が増し動きの速い時代に、リーダーシップを発揮してチームで課題を解決するためにはどうすれば良いのか、ってのが少しわかるようになるかも・・・

# 書籍
## 東大読書（西岡 壱誠）
まずは、本の読み方を知っておいたほうが効率良く学習できると思いこの本を先頭に持ってきています。
私は、本はただ読めば良い（受動的）と思っていました。ですが受動的でなく能動的に読む事が大事だと言うこととどうすれば能動的に本を読めるかが書いてあります。
この全てを実践するのは中々難しいけど自分にヒットする方法から試して本を読むだけでも大分効果が違うと思います。

## チーズはどこへ消えた？（スペンサー ジョンソン）
この本を読んで思ったのは、世の中は理不尽だ！ ではどうするべきか、変わるしかない！！

本の中では、考え方が異なる４つのタイプのキャラが登場します。
そのキャラ達が置かれた状況が変化した場合、どういう行動をとりその結果どうなったかが描かれています。

変わらない事が良いのか、変わることが良いのか色々と考えさせられます。

## 迷路の外には何があるの？（スペンサー ジョンソン）
チーズはどこへ消えた？の続編
何が妨げとなって変われないのか、変わるにはどうすれば良いのか、変わると結果どうなるのかが描かれています。
ただ、変わる過程でのキャラたちの葛藤やサポートの必要性なども理解できます。

## 採用基準（伊賀 泰代）
リーダーシップとは何か、その必要性とどういう行動をとれば良いのかが簡潔に書かれています。
ですが、とても大事な事なのでこの本に書いてあることを意識して行動するだけで今までとは考え方が変わります。そして、行動が変わります。

## THE TEAM 5つの法則（麻野 耕司）
個人で解決できる事に限界もあるし解決までの時間もかかるのでチームで問題に取り組む事が基本となっています。
チームで最高のパフォーマンスを出すための法則がまとめてあります。
学術的に難しい事を具体例をだしながら理解しやすい形でまとめてあるのでとても読みやすいし分かりやすいです。
採用基準でも書いてあるんですが、ビジョンや目的や目標がとても大切で各自が考えながら自立して動ける事が大事なんだと感じました。

## 地頭力を鍛える（細谷 功）
ビジョンや目的や目標など世の中色々と考えることが多すぎる！！
そんな時どうやって考えていけばいいのかという事でこの本を読んでみてください。

フェルミ推定というアプローチがあり、それにはどのような考え方が必要なのか等が書いてあります。
簡単に書いてあるけど、実際に行うと難しいと思う。でも、そういう考え方があると知っていれば問題解決のヒントになる。考え方の幅を広げるには良いと思います。

## イシューからはじめよ（安宅和人）
問題や課題はいっぱいあるのでそれらを全て解決することはできません。
では、どの問題や課題を解決することが最善なのかを見つけるにはどうすれば良いかが書かれています。

解決する問題や課題って、短い時間で高い効果が出るものを解決していけば最高な結果がでる訳で、それを見極めればパフォーマンス高い人材って事になるんです。

# 最後に
エンジニアはコードを書いていれば幸せなんですが、技術的な事ではない事が見えてくるとコードを書くことがもっと楽しくなると思ったからです。
そして、書くコードもきっと変わると思います。
何故なら、自分が書きたいコードを書く事が幸せな事でなくなるからです。（そうなって欲しいな）
コードは何のために書くのか、そのコードの先に何があるのかを見つけて欲しいなと思います。
その助けになってくれる書籍だと思い紹介しました。
また、経営的な事を考えるためにも基礎になってくるものだとも思っています。

ちなみにここに紹介している本は結構古い本が多いです。
それが今でも売れているという事は、日本ではまだまだこういう考え方が不足しているという事だとも思います。
これが少しでも日本に浸透していけば、さらに日本は成長できるのかなとも思っています。
最後は何だか壮大になってしまいましたが・・・（半年後に読んだら恥ずかしいやつだな）

世の中の見え方が変わるきっかけになれば嬉しいなと思います。
Fortran で stack を作ってみた

## 動機

前回の queue と同様です (前回記事 [Fortran で queue を作ってみた](https://qiita.com/ue1221/items/e29cd6c70d532b44e0b0)) 。 stack と queue は取り出す順番が違うだけで他はほぼ同じなので、実装が簡単だと思い作成しました。

## stack とは

stack はデータ構造のひとつであり、後入れ先出し (LIFO) でデータを保持します。つまり、データを取り出すときは、後に入れたデータから取り出されます。 stack にデータを入れることを push 、 stack からデータを取り出すことを pop と言います。

## 環境

macOS Sierra (10.12.6)
GNU Fortran (GCC) 6.3.0

## プログラム

実際に実装したのが以下のものです。

```fortran:stack.f08
module mod_stack

  type t_node
    integer :: item
    type(t_node), pointer :: prev => null()
    type(t_node), pointer :: next => null()
  end type t_node

  type t_stack
    integer :: num = 0
    type(t_node), pointer :: head => null()
    type(t_node), pointer :: tail => null()
  end type t_stack

contains

  function new_node(item) result(node)
    implicit none
    integer, intent(in) :: item
    type(t_node), pointer :: node
    
    allocate(node)
    node%item = item
    return
  end function new_node

  subroutine push(stack,item)
    implicit none
    type(t_stack), intent(inout) :: stack
    integer, intent(in) :: item
    type(t_node), pointer :: node

    node => new_node(item)
    if (associated(stack%head)) then
      node%prev => stack%tail
      stack%tail%next => node
    else
      stack%head => node
    end if
    stack%tail => node
    stack%num = stack%num+1
    return
  end subroutine push

  function pop(stack) result(item)
    implicit none
    type(t_stack), intent(inout) :: stack
    integer :: item
    type(t_node), pointer :: node

    item = stack%tail%item
    node => stack%tail%prev
    deallocate(stack%tail)
    stack%tail => node
    if (associated(node)) then
      node%next => null()
    else
      stack%head => null()
    end if
    stack%num = stack%num-1
    return
  end function pop

end module mod_stack
```

また、実装できているか確認するために以下のプログラムも書きました。

```fortran:test_stack.f08
program test_stack
  use mod_stack
  implicit none
  type(t_stack) :: stack
  integer :: i, n = 5

  do i = 1, n
    call push(stack,i)
    write(*,'("push: ",i0," size: ",i0)') i, stack%num
  end do

  do while (stack%num > 0)
    write(*,'("pop: ",i0," size: ",i0)') pop(stack), stack%num
  end do

  stop
end program test_stack
```

実行結果は以下のとおりです。

```
push: 1 size: 1
push: 2 size: 2
push: 3 size: 3
push: 4 size: 4
push: 5 size: 5
pop: 5 size: 4
pop: 4 size: 3
pop: 3 size: 2
pop: 2 size: 1
pop: 1 size: 0
```

stack も問題なく実装できていると思います。

## 追記 2019/08/11

不必要な部分を削り、よりオブジェクト指向な書き方に変更しました ([ソースコード](https://github.com/ue1221/fortran-utilities/blob/master/fortran08/stack.f08)) 。
なるはや Vue SPA入門：単一ファイルコンポーネント

Vue CLI3 で作成した SPA（Single Page Application）プロジェクト上で、段階的に Vue.js を学んで行きましょう。

[目次はこちら](https://qiita.com/tsubo/items/24df49ef2f1ba87984d1)

今回は 単一ファイルコンポーネント編です。

## 前提事項

[Vue Router 編](https://qiita.com/tsubo/items/fe91e95e52ee82e05681) が完了していること。 

## 単一ファイルコンポーネント

[Vue CLI3 で生成したプロジェクト](https://qiita.com/tsubo/items/50ec81ffdfb26b8bc15d)では単一ファイルコンポーネントに対して Vue のコーディングを行っていきます。単一ファイルコンポーネントとは *.vue 拡張子を持つファイルのことです。

`src/views/SandBox.vue` を以下のように修正してみましょう。

```vue:src/views/SandBox.vue
<template>
  <div class="sandbox">
    <!-- ここにこのコンポーネントの HTML を書きます -->
    <h1>SandBox</h1>

    <p>{{ msg }}</p>
    <p>{{ now() }}</p>
  </div>
</template>

<script>
// ここに JavaScript を書きます

// このコンポーネントで使用する Vue オブジェクト
export default {
  // データ
  data() {
    return {
      msg: "Hello, World!"
    };
  },

  // メソッド
  methods: {
    now() {
      return new Date();
    }
  }
};
</script>

<style>
/* ここに、このコンポーネントに適用する CSS を書きます */
.sandbox {
  color: red;
}
</style>
```
単一ファイルコンポーネントは以下の３つの要素で構成されています。
HTML, JS, CSS が１つのファイル内に書かれているので、生産性、保守性に優れています。

|構成要素|内容|
|---|---|
|template タグ|HTMLを記述します。<br>自分が作成したコンポーネントもHTMLタグとして使えます。|
|script タグ|JavaScriptを記述します。<br>主に Vue オブジェクトを定義します。<br>Vue オブジェクトでは data や methods 等を定義します。|
|style タグ|CSSを記述します。|

## 動作確認

画面トップのメニューの`Sandbox`をクリックします。以下の条件を満たしていればOKです。

- ページ内の文字が赤色
- `Hello, World!`が表示されている
- 現在の時刻が表示されている

## 次回

[Vue の基本](https://qiita.com/tsubo/items/02a18b1899128505682e)
C# でgRPC サーバーの開発環境を作る

# 概要
C# でgRPC サーバーの開発環境を作成するための手順です。
Visual Studio 2019 を使ってます。
だいたいこれの通りです。
https://docs.microsoft.com/ja-jp/aspnet/core/grpc/basics?view=aspnetcore-3.0
https://grpc.io/docs/quickstart/csharp/

# C# のプロジェクトを作成する
「コンソールアプリ（.NET Core）」のプロジェクトを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218865/0c244308-442e-db86-24e4-a0434cfceeb5.png)

# パッケージをインストールする
NuGet で以下のパッケージをインストールします。
* Grpc.Core
* Grpc.Tools
* Google.Protobuf

# プロジェクトファイルを編集する
プロジェクトファイルに、次のコードを追加します。
proto ファイルからC# のソースコードを生成するための設定です。

```xml
  <ItemGroup>
    <Protobuf Include="**/*.proto" OutputDir="%(RelativePath)" CompileOutputs="false" GrpcServices="Server" />
  </ItemGroup>
```

上記はサーバーサイドのファイルを生成する場合です。クライアントサイドの場合は`GrpcServices` を`Client` にします。
サーバー・クライアント両方のファイルを生成する場合は、`Both` にします。

# proto ファイルを追加する
例として次のようなproto ファイルを追加します。

```protobuf:helloworld.proto
syntax = "proto3";

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}
```

追加すると、自動的にC# のファイルが生成されます。

# サーバー起動
下のようなコードでサーバーが動きます。

```c#
using Grpc.Core;
using System;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class GreeterImpl : Greeter.GreeterBase
    {
        // Server side handler of the SayHello RPC
        public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
        {
            return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
        }
    }

    class Program
    {
        const int Port = 50051;

        public static void Main(string[] args)
        {
            Server server = new Server
            {
                Services = { Greeter.BindService(new GreeterImpl()) },
                Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
            };
            server.Start();

            Console.WriteLine("Greeter server listening on port " + Port);
            Console.WriteLine("Press any key to stop the server...");
            Console.ReadKey();

            server.ShutdownAsync().Wait();
        }
    }
}
```

おわり。
herokuにアップする画像を永続的に表示させる方法【Rails】

heroku に画像をアップできるアプリケーションをデプロイしたとしても、アップした画像は数時間で消えるかデプロイするたびに消えてしまいます。
しかし、画像が消えるということを回避できる方法があります。

**それは、画像をデータベースに格納するときに`バイナリデータ`として保存する方法です。**

ですが、この記事の方法は**「モックアップ用の簡易なアプリケーション」**や**「アクセスがなく自分しか使わないアプリケーション」**といったケースでやるのが好ましいです。
下記の注意点を読んでから、アプリケーションの状況に応じて実施を決断するようにしてください。

## 注意点
以下のサイトの回答者の方の答えが非常にわかりやすくて、**画像をデータベースに保存するデメリット**（とメリット）についてまとめられているので、参考にしてみてください。

[データベースに画像を保存するのはありでしょうか？ - teratail](https://teratail.com/questions/81233)

## テーブルを作成
今回は、既存の`Postテーブル`に紐付けした`Photoテーブル`のなかに画像を保存していくとします。
`Postテーブル`と`Photoテーブル`の関係は、**１対多**です。

まずは、画像を保存するためのテーブルの作成から行います。
画像を保存するためのカラムは、`bynary型`にします。
コンソールに下記のコマンドを打ち込み実行します。

```console
$ rails g model Photo
```

そうすることで、マイグレーションファイルが生成されるので下記のように編集します。

```ruby:xxxxxxxxxxxxxx_create_photos.rb
class CreateUsers < ActiveRecord::Migration

  def change
    create_table : photos do |t|
      t.bynary :image,　nill: false
      t.references :post, foreign_key: true, null: false

      t.timestamps null: false
    end
  end
end
```

マイグレーションファイルを編集したら、下記のコマンドを実行してテーブルを作成しましょう。

```console
$ rails db:migrate
```

作成した全てのテーブル情報は「*schema.rb*」ファイルでも確認することができます。

## コントローラを編集
コントーラファイルには、「画像をデータベースに保存する」と「画像をデータベースから取り出す」といった２つの動きを追加していきます。

### 画像をデータベースに保存する
画像をデータベースに保存するには、`read`というメソッドが重要になります。
「*photos_controller.rb*」ファイルを作成して、下記を追加します。

```ruby:photos_controller.rb
def create
  @post = Post.new(post_params)

  # バイナリ化した画像の呼び出し
  params[:post][:photos_attributes]["0"][:image].each_with_index do |item, i|

    if i != 0
      @post.photos.build
    end

    @post.photos[i].image = item.read
  end
end

private
  def post_params
    params.require(:post).permit(photos_attributes: [:image])
  end
```

### 画像をデータベースから取り出す
画像をデータベースから取り出すには、`send_data`というメソッドが重要です。

```ruby:photos_controller.rb
def send_img
  tmpbin = Photo.find(params[:id])
  send_data(tmpbin.image, :type => 'image/jpeg', :disposition => 'inline')
end
```

## ビューを編集
ビューには、「画像のアップロード」と「画像の表示」とこれまた２つの動きを追加していきます。

### 画像のアップロード
画像をアップできるようにフォームを設置します。

```ruby:new.html.erb
<%= form_with model: @post, multipart: true do |f| %>
  <%= f.field_for :photos do |i| %>
    <%= i.file_field :image, type: :file %>
  <% end %>

  <%= f.submit "投稿する" %>
<% end %>
```

### 画像の表示
次に、データベースに保存した画像が表示されるように下記を追加します。

```ruby:index.html.erb
<% @post.photos.each do |photos| %>
  <%= image_tag url_for(:controller => 'photos', :action => 'send_img', id => photos.id %>
<% end %>
```

## ルートの設定を追加
最後の仕上げとして、「*routes.rb*」に下記を追加します。

```ruby:routes.rb
get '/photos/send_img/:id', to: 'photos#send_img'
```

これでバイナリデータとした画像の保存から表示までを終わらせることができました。
heroku にデプロイするアプリケーションで画像投稿機能が付いているものでも、永続的に画像を表示させ続けられることでしょう！

## 参考にさせてもらった記事
[rails で画像ファイルを DB に保存する](http://www.ckazu.info/blog/2013/12/04/image_upload_to_ar_db/)
AWS Windowsサーバでファイル共有接続できなかった問題

[Windows サーバーを利用したファイルサーバーの構築方法](https://aws.amazon.com/jp/getting-started/projects/fileserver/)
「フェーズ3-2 ファイルサーバーの設定と接続」で詰まった件についてメモ

結論としては、セキュリティグループで445ポートを解放すれば解決した。

# EC2作成までは順調
####フェーズ １-１：コンソールへのサインインと VPC の作成 ≫ 
問題なし

####フェーズ １-２：サブネットを追加作成 ≫
問題なし

####フェーズ ２-１：Amazon EC2 インスタンスの作成 ≫
以下のエラーが出たが、時間を置いたら解決したので問題なし
> Your request for accessing resources in this region is being validated, and you will not be able to launch additional resources in this region until the validation is complete. We will notify you by email once your request has been validated. While normally resolved within minutes, please allow up to 4 hours for this process to complete. If the issue still persists, please let us know by writing to aws-verification@amazon.com for further assistance.

####フェーズ ２-２：Elastic IP（固定 IP）の割り当て ≫
問題なし

####フェーズ ３-１：Windows サーバーへのリモートデスクトップ接続 ≫
問題なし

# 問題のフェーズ3-2
####フェーズ ３-２：ファイルサーバーの設定と接続 ≫
c直下に/Shareを作成し、右クリックから共有設定
準備が完了したので、クライアントPCからファイル共有接続を試みると、ネットワークエラー（エラーコード：0x80070035）になった。
セキュリティソフトのせいかな？と別PCから試みるも同様のエラー。

他にもコントロールパネルから共有設定（サーバー、クライアント）を変更したが、これでも効果なし。
なんでだろう？と思いつつ、サーバーに対してping飛ばしてみると、これも反応なし。
→GUI接続できていて、pingが届かないのはおかしいので、調べてみると以下の記事がヒット。
[罠】AWSのEC2インスタンスにPingが通らない原因と解決方法【瞬殺】](https://blogenist.jp/2018/06/20/4805/)

ありがてえ。pingは通った！

この辺りでなんかAWS側の設定が怪しそうだなーと思いつつも、Windows共有について調査・・・
そういえば、ネットワークエラーのトラブルシューティングの詳細見てなかったな～と思い、詳細を覗いてみると良さげなヒントが書いてあった。

> ファイルとプリンターの共有リソース(192.168.1.2)はオンラインですが、接続試行に応答しません。
リモートコンピュータはポート４４５での接続に応答していません。ファイアウォールなたはセキュリティポリシーの設定、あるいはリモートコンピュータが一時的に利用できないことが原因である可能性があります。コンピュータ上のファイアウォールには何の問題も見つかりませんでした。

`リモートコンピュータはポート４４５での接続に応答していません。`

これっぽい？と思い、セキュリティグループでポート445を許可すると...ようやく繋がった。

#反省点
ここのファイル共有接続の部分で2時間近く躓いていた。
主な原因としては、以下の2点だと思う。
1. ハンズオン資料（ステップ 1: ファイル共有の設定（Windowsサーバー））に「※Windows の操作になりますので、詳細設定ついては記載しておりません。」とあったので、自分のWindows共有設定の知識不足が原因だと思い込んでいた。
2. Windowsのトラブルシューティング機能を重要視していなかった。

###感想・まとめ
とりあえずできてよかった。
ちなみに445ポート（SMB)はファイル共有やプリンタ共有辺りの設定になるらしい。開けないとだめよね。
なかなかハンズオン資料通りには行かないなあ。
（資料ではセキュリティグループ設定デフォルトだったし、ポートを開ける必要があるとか書いてなかったじゃん！（言い訳））
ssh(sftp)サーバーをLaravelのストレージとして利用する

# はじめに
[Laravelのファイルストレージ](https://readouble.com/laravel/5.5/ja/filesystem.html)で外部のサーバーのファイルを取り扱いたい場面に遭遇して解決方法が見つかったのでメモとして残します。

ファイルストレージは標準ではローカル ディスクとAmazon S3、Rackspace、ftp用のアダプタが組み込まれています。調べてみると[Flysystem](https://flysystem.thephpleague.com/docs/)というライブラリの機能で実現されていて、アダプタを追加すれば様々なデバイスをストレージとして利用できる仕組みになっています。

Laravelには入っていませんがFlysystemには標準で[sftpのアダプタ](https://flysystem.thephpleague.com/docs/adapter/sftp/)が用意されています。これを利用すると任意のsshサーバーをsftp経由でLaravelのストレージとして利用可能です。

# 手順
1. composer で sftp アダプタのモジュールをインストール

    ```shell-session
    composer require league/flysystem-sftp
    ```

2. サービスプロバイダでアダプタを追加する。
    
    ```php
    <?php

    namespace App\Providers;

    use Storage;
    use League\Flysystem\Filesystem;
    use League\Flysystem\Sftp\SftpAdapter;
    use Illuminate\Support\ServiceProvider;

    class AppServiceProvider extends ServiceProvider
    {
        ...
        public function boot()
        {
            /**
              * flysystem に sftp 用のアダプタを追加する
              * @see https://flysystem.thephpleague.com/docs/adapter/sftp/
              * @see https://readouble.com/laravel/5.5/ja/filesystem.html#custom-filesystems
              */
            Storage::extend('sftp', function ($app, $config) {
                return new Filesystem(new SftpAdapter($config));
            });
        }
    }
    ```

    ※ [サービスプロバイダの詳細は readouble のドキュメント](https://readouble.com/laravel/5.5/ja/providers.html#the-boot-method)を参照してください。ちなみに `AppServiceProvider` は[最初から存在し自由に記述していいサービスプロバイダ](https://readouble.com/laravel/5.5/ja/lifecycle.html#focus-on-service-providers)となっています。

3. `config/filesystems.php` にディスクを追加する。

    ```php
    <?php

    return [
        ...
         /**
          * sftp アダプタで ssh サーバーを disk として登録する
          *
          * @see https://flysystem.thephpleague.com/docs/adapter/sftp/
          */
        'rpx' => [
            'driver' => 'sftp',
            'host' => '192.168.10.11',
            'port' => 22,
            'username' => 'vagrant',
            // 'password' => 'vagrant',
            'privateKey' => '/home/vagrant/.ssh/id_rsa',
            'root' => 'rpx',
            'timeout' => 10,
        ],
    ];
    ```

    接続先サーバーには対応する公開鍵を登録する。

4. ストレージで利用する

    ```php
    Storage::disk('rpx')->put('./a/test.txt', "hello rpx\n");
    ```
VHDLでの乗算

会社でVHDLは乗算が使えるか聞かれ即答できなかったので調べた

# 更新履歴

* 2019/07/17 : コメントを受けunsignedとsignedの乗算について修正

# VHDLでの乗算の書き方

基本的には、下記の書き方で乗算になる。
これはVerilogHDLでも同じ。

```vhdl
-- yのビット幅はaとbのビット幅を足し合わせたものになる
y <= a * b;
```

# 演算パッケージによる違い

## IEEE.STD_LOGIC_ARITH

注意する点は利用するパッケージによって、符号が変わることである。

```vhdl
use IEEE.STD_LOGIC_ARITH.ALL;

-- 内部のstd_logic_vectorがunsignedになる
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- 内部のstd_logic_vectorがsignedになる
use IEEE.STD_LOGIC_SIGNED.ALL;
```

例えば`IEEE.STD_LOGIC_SIGNED`を利用している場合、
上位コンポーネント(モジュール)からunsignedな信号を入力されても、内部的にはsignedとして扱われる。逆も然り

明示的に符号の有無を示したい場合には、`unsigned()`と`signed()`関数を利用する。

```vhdl
Y <= unsigned(A) * unsigned(B);
-- または
Y <= signed(A) * signed(B);
```

ただしsignedとunsignedの乗算の場合は、
unsigned同士の乗算を行い最後に2の補数に変換されるため、更に1bit幅をもたせる必要がある。
(修正：コメントにて@ryo_i6さんに指摘をいただけましたので引用しています)

> ieee.std_logic_arithは内部のコードを見る限りは
> 絶対値の乗算 -> 符号拡張ではなく
> unsignedをsignedに符号拡張 -> signedの乗算になっているようです
> 
> ```vhdl:vhdl:ieee.std_logic_arith
> function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is
>     -- pragma label_applies_to plus
>     begin
>     return      mult(CONV_SIGNED(L, L'length),
>                  CONV_SIGNED(R, R'length+1)); -- pragma label mult
>     end;
> ```

## IEEE.NUMERIC_STD

`IEEE.NUMERIC_STD`パッケージではstd_logic_vectorは整数として扱われる。
また演算の際には、符号を指定する必要がある。

```vhdl:IEEE.NUMERIC_STDでの乗算
Y <= std_logic_vector(unsigned(A) * unsigned(B));
-- または
Y <= std_logic_vector(signed(A) * signed(B));
```

`IEEE.NUMERIC_STD`ではsignedとunsigned同士の演算が定義されていない。
一応unsigned側をintergerに変換すればできないこともないが、
signedな信号と乗算する際にsignedとして扱われるらしく正直微妙な結果になった。
ならばと思いunsigned側を符号1bit拡張したがsigned側と幅を合わせろ的なエラーになってしまった。
もう少し調べたほうがいいかもしれない。

正直`IEEE.NUMERIC_STD`を使った経験がなさすぎてよくわからない。助けて詳しい人
(追記：こちらの件も@ryo_i6さんよりコメントいただきましたので引用させていただきます)

> numeric_stdではsigned * unsignedは定義されていないので
> std_logic_arithと同じ結果を得たい場合は
> 以下のような自作関数を用意することになると思います

> ```vhdl:numeric_std_sample_0
> library ieee;
> use ieee.std_logic_1164.all;
> use ieee.numeric_std.all;
> 
> function "*" (l: signed; r: unsigned) return signed is
> begin
>     return l * signed(resize(r, r'length + 1));
> end;
> ```
> ただし、上記の関数では
> 例えばsigned 4bit * unsigned 4bitとすると結果がsigned 9bitになります
> 
> signed 4bit * unsigned 4bitは必ずsigned 8bitに収まるはずなので
> 結果の上位1bitは不要ということになります
> このことを加味すると以下のような関数のほうが実用上は便利かと思います
> 
> ```vhdl:numeric_std_sample_1
> library ieee;
> use ieee.std_logic_1164.all;
> use ieee.numeric_std.all;
> 
> function "*" (l: signed; r: unsigned) return signed is
>     variable p : signed(l'length + r'length downto 0);
> begin
>     p := l * signed(resize(r, r'length + 1));
>     return signed(p(p'length - 2 downto 0));
> end;
> ```
Ubuntuをインストールしたらとりあえずやること

Ubuntuいいですよね、軽いし。
というわけで、今日はubuntuを入れたら最初にとりあえずやっておくといいことを紹介します。
お役に立てたら幸いです。

# マウスホイールでのスクロール速度を早くする
UbuntuにChromeを入れてブラウジングすると、あることに気づきます。
__マウスホイールでのスクロールが超絶遅いんです。__
Ubuntuには標準でマウスホイール速度を調整する機能が存在しません。
そのため__imwheel__というソフトをインストールして、
マウスホイールの速度を調整できるようにします。

```bash
sudo apt-get install -y imwheel
```
インストールしたらimwheelrcという設定ファイルを作成・編集します。
このファイルにマウスホイールのスクロール速度の設定を書きます。

```bash
vim ~/.imwheelrc
```
設定ファイルの中身はこんな感じ

```text
".*"
None,      Up,   Button4, 3
None,      Down, Button5, 3
```

更新したら下記コマンドでimwheelを起動します。
```bash
imwheel
```


最後にimwheelをubuntu起動時に自動で起動しておくようにします。

```bash
gnome-session-properties
```
上記コマンドでGUIツールを開き、追加をクリック。
コマンドに「imwheel」と下記保存します。



# fishを入れる
標準のbashでもいいんですが、個人的にfishを入れたいのでfishを入れます。

```bash
sudo apt-add-repository ppa:fish-shell/release-3
sudo apt-get update
sudo apt-get install -y fish
```
こんな感じで入れます。
素のfishでは物足りないので、fishermanを入れましょう。
fishermanとは、fishのパッケージマネージャです。
ちょっと前まではoh-my-fishというパッケージマネージャが有名だったそうですが、
最近はfishermanが流行っています。

```bash
curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
```
そんでもっていい感じにおしゃれでgitのブランチを表示できるテーマも入れちゃいます。

```bash
fisher add oh-my-fish/theme-bobthefish
```
はい、おしゃれなターミナルのできあがりです。
と言いたいところですが、powerline対応のfontがないと文字化けます。
powerline fontを入れましょう。

```bash
sudo apt-get install fonts-powerline
```
んで、「端末」アプリの編集->Preferencesからフォントをpowerline対応のものに切り替えます。

# anyenvを入れる
node.jsやrubyを使っていると、アプリごとの対応バージョンに悩まされるときがあります。
そこで、○○envといったアプリを使ってバージョン管理をすることがありますが、
さらにその○○envを管理するマネージャがanyenvです。
というわけでそんなanyenvを入れていきましょう。

```bash
git clone https://github.com/anyenv/anyenv ~/.anyenv
set -Ux fish_user_paths $HOME/.anyenv/bin $fish_user_paths
anyenv init - fish | source
```

# 終わりに
完全に個人的な防備録になってしまいましたが、誰かのお役に立てれば幸いです。