OmniAICreator/Qiita-1.07M huggingface dataset:
Lifecycleについて

React.Component を継承したclass componentは処理の過程の特定の時点でコードを実行するためにいくつかの
「ライフサイクルメソッド」があり、勉強したのでmemo。

##まず基本的な描画の流れ
componentが作成され、マウントされる前、マウント時、マウントされた後、それぞれにメソッドがコールバックされます。

**レンダリング** = 表示用のデータをもとに、内容を整形して表示すること
**マウント** = コンポーネントが画面にレンダリングされること

1.constructor()
2.static getDerivedStateFromProps()　
3.render()
4.componentDidMount() 

##更新される時
 props や state が変更された時にcomponentが再レンがリングされる時に呼ばれます。

1.static getDerivedStateFromProps()
2.shouldComponentUpdate()
3.render()
4.getSnapshotBeforeUpdate
5.componentDidUpdate()

**アンマウント**(コンポーネントが DOM から削除されるときに呼び出されます。)
・componentWillUnmount()

##使わない方が良いメソッド
・componentWillUpdate()
・componentWillReceiveProps()

##実際書いてみた!

```js
class Test extends Componentes<Props, State> {

// state の初期化もメソッドのバインドもしないのであれば、React コンポーネントのコンストラクタを実装する必要はないメソッドです。
  constructor() {
    console.log('constructor');
  }

// getDerivedStateFromProps は、初期マウント時とその後の更新時の両方で、render() メソッドを呼び出す直前に呼び出されます。
// state を更新するためにオブジェクトを返すか、何も更新しないために null を返すべきです。
  static getDerivedStateFromProps(props, state) {
    console.log('getDerivedStateFromProps');
  }


// 新しい props または state が受け取られると、レンダーする前に shouldComponentUpdate() が呼び出されます。
// デフォルトは trueですが、shouldComponentUpdate() が false を返した場合、render() は呼び出されません。
  shouldComponentUpdate() {
    console.log('shouldComponentUpdate');
// 注意：shouldComponentUpdateはprops または state が更新されない場合falseを返すので値が変わらない場合呼ばれないです。どこで呼ばれるかの確認のためにtrueを返してみる
    return true
  }


// 最後にレンダーされた出力が、たとえば DOM にコミットされる直前に呼び出されます。
// このライフサイクルによって返された値はすべて、componentDidUpdate() へのパラメータとして渡されます。
  getSnapshotBeforeUpdate() {
    console.log('getSnapshotBeforeUpdate');
  }


// 更新が行われた直後に componentDidUpdate() が呼び出されます。
// このメソッドは最初のレンダーでは呼び出されません。
  componentDidUpdate() {
    console.log('componentDidUpdate');
  }


// コンポーネントがマウントされた直後に呼び出されます。
// コンポーネントが変更される可能性があるときに、変更される前に DOM からある情報（たとえば、スクロール位置）を取得することを可能にします。
  componentDidMount() {
    console.log('componentDidMount');
  }


// render() メソッドは、クラスコンポーネントで必ず定義しなければならない唯一のメソッドです。
// 呼び出されると、this.props と this.state を調べて、次のいずれかの型を返します。
 render() {
    console.log('render')
  return ();
 }
}

```

##実行結果
<img width="613" alt="スクリーンショット 2019-12-22 3.01.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394411/5d0be311-1c4a-dbce-6d3d-f851f4b13048.png">

**props や state が変更され、更新された時**
<img width="575" alt="スクリーンショット 2019-12-23 11.58.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394411/53731074-4e1a-e1fa-1391-e000622e32cc.png">


参考
https://ja.reactjs.org/docs/react-component.html
https://react.keicode.com/basics/life-cycle-events.php
dotnet-install スクリプト、使ってます？

# はじめに

　この記事は[C# Advent Calendar 2019](https://qiita.com/advent-calendar/2019/c-sharp)の22日目の記事となります。
　C#というより.NET Coreの話となりそうですが……。

# dotnet-install スクリプト、使っていますか？

　皆さんは.NET Core SDKをどのようにインストールしていますか？
　[Microsoftのダウンロードページ](https://dotnet.microsoft.com/download)からインストーラーをダウンロードして実行しますか？
　Visual Studio Installerからインストールしていますか？
　管理者権限のない方はzipで適当な場所に配置しますか？
　Windows以外の方はどうですか？
　macOSでもインストーラーを使っていますか？
　Linuxではパッケージマネージャー？

　dotnet-install スクリプトという選択肢、そもそも知っていましたか？

# 前提条件

　以降の内容は以下の環境で行われています。

- CentOS 7.6.1810

# dotnet-install スクリプトとは

　dotnet-install スクリプトは.NET Core CLI ツールと共有ランタイムをインストールするために使うスクリプトです。詳細については[Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/core/tools/dotnet-install-script)を参照ください。
　ただ、「詳細は別ページで確認して下さい」だけでは本記事がここで終わってしまうので、まずは**「これがわかれば使える」**という使い方を紹介いたします。

## dotnet-install スクリプトのダウンロード

　dotnet-install スクリプトは環境に合わせて2種類用意されています。ご自身の環境に合わせてダウンロードしてください。

- Windows
    - [https://dot.net/v1/dotnet-install.ps1](https://dot.net/v1/dotnet-install.ps1)
- macOS/Linux/WSL
    - [https://dot.net/v1/dotnet-install.sh](https://dot.net/v1/dotnet-install.sh)

## dotnet SDKのインストール

### 最新のSDKをインストールしたい

　ためしに、現在の最新のSDKをインストールしてみましょう。`--version`で`latest`を指定することで最新のSDKをダウンロードします。`--install-dir`ではdotnet CLIのパスを通したい場所を指定してください。

```shell-session
$ sh dotnet-install.sh --version latest --install-dir /path/to/cli
$ cd /path/to/cli
$ dotnet --version
3.1.100
```

　実行後は下記のような構造になります。

```shell-session
/path/to/cli
 |-- LICENSE.txt
 |-- ThirdPartyNotices.txt
 |-- dotnet
 |-- host
 |-- packs
 |-- sdk
 |   `-- 3.1.100
 |-- shared
 `-- templates
```

　この`/path/to/cli/sdk`の中に指定したバージョンのSDKが追加されていきます。ですので、基本的に`--install-dir`の指定はバージョン指定ごとに変える必要はありません。

### LTSのみ対象としてインストールしたい

　`--version`を`latest`と指定することで最新のSDKをインストールしましたが、場合によってはLTSのみをインストール対象としたいというケースもありえるかと思います。そのような場合は`--channel`で`LTS`と指定しましょう。

```shell-session
$ sh dotnet-install.sh --channel LTS --install-dir /path/to/cli
```

　こちらの`--channel`ではブランチ名や`X.Y`（たとえば `2.2`や`3.0`）といった指定も可能です。「.NET Coreの2.2系をインストールしたいけど2.2系の詳細なバージョン覚えてないや」といった場合も安心ですね。

### インストール済みのSDKバージョンを把握したい

　当然、インストールしてあるSDKのバージョンを知りたいときもありますよね。`--install-dir`で指定したパスの`sdk`の中身を見ても判断できますが、こちらはdotnet CLIの標準のオプションで確認できます。

```shell-session
$ dotnet --list-sdks
2.2.402 [/path/to/cli/sdk]
3.0.100 [/path/to/cli/sdk]
3.1.100 [/path/to/cli/sdk]
```

### 実行したいだけだからSDKじゃなくてruntimeをインストールしたい

　「.NET Coreで作ったプログラムを動かしたいだけだから実行環境だけあればいい」なんてこともありますよね。その場合は`--runtime`を指定しましょう。

```shell-session:実行環境だけあればいい場合
$ sh dotnet-install.sh --channel LTS --install-dir /path/to/cli --runtime dotnet
```

　「ASP.NET CoreでWebアプリを動かしたいだけだからSDKをインストールするのは無駄」なんて場合は`aspnetcore`と指定しましょう。

```shell-session:Webアプリが動けばいい場合
$ sh dotnet-install.sh --channel LTS --install-dir /path/to/cli --runtime aspnetcore
```

# まとめ

　PythonやNode.js、Goといった言語ではpyenvやgoenvといった容易な環境構築とバージョン管理を行えるツールがあります。
　ターゲットフレームワークという仕組みがある.NETでも、dotnet-install スクリプトによって容易に環境構築を行えることがお分かりいただけたかと思います。
　もちろん「私はインストーラー派なんだ」という方を否定するわけではありませんが、環境構築の一手段としてこのようなツールが存在するということを知っていただければと……。
　~~C#のコード一文字も書いてないけど許してください。~~
No route matches [GET] "/posts"エラーの解決例

![スクリーンショット 2019-12-22 3.16.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555157/600044d9-29ca-b809-7214-6d2e063deb5c.png)

学習初期段階のこういったエラーは見るだけでやる気無くなりますよね...

というわけでこれまで筆者が経験で見つけたエラー原因を羅列します！

（筆者のようにあまり他人に聞けない性格の初学者の方に向けて記載しています。そんなの当たり前だなどのツッコミはご容赦いただきたいです^^;）

# 例１）~/railsのファイル名/config/routes.rbの記入漏れ（読込先の記入漏れ）
このファイルの中のroot to:'posts#index'が書かれていなかった
→下記のテンプレートを使ってください

```
Rails.application.routes.draw do
  root to: 'posts#index'
end
```

# 例２）~/railsのファイル名/assets/viwes/posts/index.htmlファイルがないまたは内容がない~~（部品ファイルのみ作成し、取りまとめて実行するファイルを作成していない）~~ 2020/10/03この部分修正しました
→ファイルを右クリックで作りましょう。（エディター上でもいいしファインダーからファイルの箇所に潜ってもよいです。）名前をつけるときはフォルダ名が'posts#index'の＃より前、ファイル名＃より後とぴったり同じようになるようにしてください

例１)でindexファイル（実行する部品名を取りまとめたファイル）を読み込みますよという記述を作ったのですが、そのファイルがないとこのようなエラーとなります。

~~実行するコードが小さく１種類にまとめられるなら、indexへつながずposts#ファイル名で直接ファイルにつないでしまえばOKです。
下記はindexファイルの記載例ですが、部品が「詳細」「編集」「削除」の３種類あるため今回はindexが必要という状態でした。~~ ﾏﾁｶﾞｲﾊｽﾞｶｼｲ…ﾊｽﾞｶｼｲ…
↑railsの決まりでフォルダ名とファイル名を合わせないと作ったhtmlページを表示させない仕組みになっているので、その名前のファイルを作る必要がありました。
つまり、urlを元にrailsがviewファイルを探そうとして、「postsなんてフォルダねぇよ！」ってエラー文を吐いてるという状態でした( ；∀；)

※補足（寄り道）
ルーティングを` root to: 'posts#test'`としたら`~/railsのファイル名/assets/viwes/posts/test.html`とすれば読み込まれまれるので、このようにファイル名を自在に変えてもらえればオッケーです！
メルカリのあたりでいろんなviewファイル作るときにこの考え方が必要になります！

```
<div class="contents row">
<% @tweets.each do |tweet| %>
<div class="content_post" style="background-image: url(<%= tweet.image %>);">
<div class="more">
<span><%= image_tag 'arrow_top.png' %></span>
<ul class="more_list">
<li>
<%= link_to '詳細', "/tweets/#{tweet.id}", method: :get %>
</li>
<% if user_signed_in? && current_user.id == tweet.user_id %>
<li>
<%= link_to '編集', "/tweets/#{tweet.id}/edit", method: :get %>
</li>
<li>
<%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %>
</li>
<% end %>
</ul>
</div>
<%= simple_format(tweet.text) %>
<span class="name">
<a href="/users/<%= tweet.user.id %>">
<span>投稿者</span><%= tweet.user.nickname %>
</a>
</span>
</div>
<% end %>
</div>
```


# 例３）誘導式の教材（問題）を解いていた時に、localhost3000につなげれば正常に接続できる（問題が解けている）状態だったのに、localhost3000/postsで接続してしまったためエラーが起きてしまっていた

![スクリーンショット 2019-12-22 3.50.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555157/eeb76b20-56a5-40df-3682-4fa4449fd252.png)


https://localhost:3000 でlocalserver（公開していない自分のパソコン内のウェブページ）に接続できるのですが、筆者はそのURLがわからず、教材のちょっと前に使ったURLをそのまま打ち込んでいたためこういった間違いを犯しました。
教材が想定していたミスの箇所ではないミスであると気づけなければ永遠に彷徨えます。なのでこういったミスを犯すこともあると知っておこうというお話です。


エラー発見問題では芋づる式になっていることが多いため、接続先を間違えるとその問いを解くことができず、そのことによりその先の問題が全て解けなくなってしまうことがよく起きます。（これで筆者は丸３日間悩んでました。笑）

とりあえずこの記事は例３）を一番主張したくて書きました

何かの参考になればと思います
condaのupdateでRemoveErrorが出た時の対処

#はじめに
windows10のAnaconda Promptから```conda update --all```を実行した際に、
```RemoveError: 'setuptools' is a dependency of conda and cannot be removed from conda's operating environment.```
というエラーが出た時に、うまくいった対処方法を紹介します。

ことの経緯としては、Anaconda Navigatorのアップデートが終わらなかったのが発端です。[Anaconda Navigatorも含めて諸々アップデートする方法](http://coffeebreakscript.hatenablog.com/entry/2018/06/27/133028)というのを見て上記のコマンドを試した結果、このRemoveErrorが出ました。

解決した方法、解決しなかった方法の順に書いていきます。

#解決した方法
```conda update --force conda```を実行する

その後、Anaconda Navigatorを開いてポップアップからAnaconda Navigatorをアップデートしたところ、さっきまで終わる気配のなかったアプデがすぐに完了しました。
参考：https://stackoverflow.com/questions/54392995/removeerror-requests-is-a-dependency-of-conda-and-cannot-be-removed-from-cond

#解決しなかった方法
* ```conda update conda```の実行
* ```conda install -c anaconda setuptools```の実行
* ```conda update anaconda-navigator```の実行

どれも同じようにRemoveErrorが出てupdateできませんでした。

#まとめ
結局、```--force```オプションを付けるとなんとかなったのですが、はたして正しい方法だったのかは分かりません。あと、setuptoolsがなんなのかよく分からないままの解決です。
forceオプションで実行した際、プロンプト画面にforce optionが近々なくなるというような内容が出てきたので、もしそうなったら別の対処が必要になるのかも？
「JWT」の読み方は？ジェット？ジョット？ジェーダブルリュティー?

# はじめに
この記事は[認証認可技術アドベントカレンダー2019](https://qiita.com/advent-calendar/2019/identity)の13日目の記事です。

初投稿なのでお手柔らかにお願いします。

## 注意

この記事は答えを出していません。
というか答えが分かりません。
質問したいため投稿しています。

# JWTとは

この記事が[「JWT について調べた内容をまとめました。」](https://qiita.com/t-toyota/items/8d0ffb265845ab8cc87c)分かりやすかったです。

以下引用

>JWT（ジョット）とは JSON Web Token の略で、電子署名付きの URL-safe（URLとして利用出来る文字だけ構成される）な JSONのことです。
電子署名により、JSON の改ざんをチェックできるようになっています。
ざっくり言うと、改ざんできない JSON ということになります。

# JWTの読み方

さてここで問題です。
先ほどの記事や他のWebページを見たら、
「JWT」のことを「ジェット」
と書いている方が多いです。

しかし、IETF Toolsの[JWTに関する記事](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-13)では、

>  The suggested pronunciation of JWT is the same as the English word "jot".

と書いていました。
つまり推奨している発音は、`jot`、「ジョット」です。

どちらが正しいのでしょうか。

ちなみに私は最初、「ジェーダブルリュティー」と読んでいました。

# さいごに
「JWT」の読み方をどうぞみなさん教えてください。
Parallelクラスでお手軽な並列処理

会社の人にParallelクラスの存在を教えてもらったのでメモ。
.NET Framework 4で追加されたかなり前から存在する機能なのでありふれた内容です。

# 概要
Parallelクラスを利用することでループ内を手軽に並列化できる。

# メリット
- 通常のfor, foreachと書き方が殆ど変わらない点が非常にお手軽。
- Thread, Task, await, asyncを使わずに並列処理を実現できる。

# 注意点
当然ではあるが並列処理なので同じファイルへのアクセスなどは気をつける必要がある。Lockをかけるとか。

# 通常のforeach
```csharp
List<int> list = new List<int>()
{
    1, 2, 3, 4, 5, 6, 7, 8, 9
};

foreach (int value in list)
{
    Console.Write(value);
}
```
```console:実行結果
123456789
```
逐次処理なので1~9まで順番にコンソール出力されます。

# Parallel.ForEachで並列化
```csharp
List<int> list = new List<int>()
{
    1, 2, 3, 4, 5, 6, 7, 8, 9
};

// 並列処理オプションの設定
ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = 4;

// 並列処理実行
Parallel.ForEach(list, parallelOptions, (value) =>
{
    Console.Write(value);
});
```
```console:実行結果
156894723
```
並列処理なので実行毎に結果が変わります。
順番を気にする必要のない処理であれば非常に手軽に高速化できます。
「MaxDegreeOfParallelism」の設定は実行環境のCPU性能や負荷状況による。
今のコンシューマ向けCPUなら4で良いと思う。

# あとがき
お手軽すぎる。C#好き。
Windows10でVTを有効にしようとしたら予想以上に詰まった

#はじめに
最近エンジニアに転職したずぶの素人です。
今回は、研修の予習ために家に仮想環境を建てようとしたら予想の*5,000倍*詰まったため、備忘録的役割も兼ねて投稿しておきます。

#仮想環境が利用できない
研修を行っているうちに家にも仮想環境を作りたくなり、VMwareを意気揚々とダウンロードしてきました。
しかしいざ利用とすると、vt-xという機能が有効になっていないから仮想環境は作れないとのこと。

#BIOSが立ち上がらない
*『そういえば会社の貸与PCも最初に有効化したなぁ・・・』*などとぼんやり考えながらBIOSを立ち上げようと再起動をかけましたが、待てど暮らせど一向にBIOSが立ち上がらず真っ暗な画面だけがあるのみ。
F2もF8もDelも効きません。

####なんで？(殺意)

#UEFIに縋る
どうも私の知らない間にUEFIなるものが新しく出てきたらしい。
BIOSの設定をGUIで行わせてくれる優れものであり、しかも立ち上げの際にキー入力も不要。
#####これなら絶対できるやん？
などと思いながらBIOSからUEFIにしようとするも、どうもSSDのパーティション形式をGPTというものに変える必要があるらしい。

PowerShellから
```mbr2gpt /validate /disk:0 /allowFullOS #変換可能か確認
mbr2gpt /convert /disk:0 /allowFullOS #変更の実行```
でパーティション形式の変更までは実現できました。

これで念願のUEFAいが使用できますね・・・！

#UEFIも起動されない
出来ないのかよ(半ギレ)

でもここまで来るとそろそろ原因もわかってきました。
おそらくはマザボ側に原因があるはずです。
ということで、マザボが原因でUEFIあるいはBIOSが起動しないという内容について調べたところ、CMOSをクリアしていないと起動しない場合があるとのこと。

いやそんな簡単なことで・・・などと思いながら試してみたところUEFIが無事に起動しました。
#####キレそう

#今回の反省点
パーティションの変更や度重なる再起動など、時間のかかる内容から原因解明に取り掛かってしまった。
やはり、まずは簡単に触れる部分から調べるのが常套手段だろう。
コストをかけてもいい結果が返ってくるとは限らないことは世の常だが、その典型的な例となってしまった。

#参考
[データを保持したままMBRからGPTに変換する
](https://scratchpad.jp/convert-mbr-to-gpt/)
1セグメント全断の土曜日

## 1セグメント全断の土曜日

これは [本番環境でやらかしちゃった人 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/yarakashi-production) 22日目です。昨日は rluisr さんによる遠い目になってしまう四コマ漫画でした。

### tl;dr 兼 原因と対策
機器交換する際にはファームウェアバージョンを揃えましょう。
現在値だけでなくキャパシティも計測管理しましょう。  

### 経過
#### 予兆
10年以上前のお話です。たぶんフィクションです。
木曜日にお客様から「週末ちょっとトラフィック増えるかも」というご連絡がありました。

#### 発生
何事も無く始まった土曜日... 昼過ぎになって出かけていた私の携帯電話が鳴りました。
「第2セグメントのサーバー2台の監視が断続的にエラーになっています。」

確かに接続しにくい状態になっていたのでオンサイトの準備を始めた時に再び電話が鳴ります。
「第1セグメントのサーバーすべての監視が通りません！」

#### 調査
急いで駆けつけたもののとにかくネットワーク通信が重く調査が捗りません。状況的にネットワークトラブルだろうと目星は付くのですが...
管理運用に用いる内部セグメントは使用できたので、予告のあったお客様のサーバー群でHTTP/HTTPS通信が急増して影響していることまでは特定できました。

#### 原因特定
セグメントが全断するほどの通信量ではないような。しかし現実にFirewallはリスタート後しばらくすると反応が無くなります。
ん、Firewall？
ログを調べたところ数週間前にFirewallを1台ずつ機器交換した際に、古いファームウェアバージョンのまま投入してしまい最大接続数のキャパシティが激減していたことが原因でした。

ないわーー  

#### 対応
予備機を持ってきてファームウェアアップデートを確認した上で投入し、第1セグメントの通信は復旧しました。

#### できていなかった対策、行った対策
そもそも数週間前のFirewall交換作業が失敗していたと言えます。
Firewallルールだけでなくファームウェアバージョンも確認しましょう。
また、設計値に余裕を持たせてあっても現在のセッション使用量だけでなくキャパシティ最大量も確認ないしモニタリングしましょう。この時のFirewallは、帯域やメモリにセッション数といった項目について最大数を示すEnterprise mibsが提供されていたのでSNMP経由で監視を行いました。
最大値というメトリクスを取得可能になっていますか？

加えるなら、普段そういうことを伝えてこないお客様が「"ちょっと"トラフィック増えるかも」とわざわざ伝えてくださった場合には話を大きめに受け止めて備えておきましょう。

#### 補足
発生 のところでお気づきの方もいらっしゃると思いますが、この日最初のエスカレーション対象である「監視が不安定な2台」はこのFirewallとは異なる第2セグメントに存在していてこの時点でまだ復旧していません。

そう、この日はあと2つのセグメントが全断していくのですが
それを記すには余白とSAN値が足りません――
MathJax(Qiitaの数式表示)で立体(upright)のギリシャ小文字を表示してみたい

ISO 80000-2(JISだとZ 8201 ??)では値が一般に与えられる定数の記号は立体(ローマン体)でタイプセットするように定められているそうです(あまり守られてない気がしますが…)。数学定数の超有名所といえば自然対数の底$\mathrm{e}$と円周率$\large\unicode[0.5,0.05][times]{x3c0}$でしょう。私でも知っています。

記号がデフォルトで斜体表示される(ギリシャ大文字は例外で、立体)$\def\uptex{\mathrm{\TeX}}\def\uplatex{\mathrm{\LaTeX}} \uptex$記法の場合、どうすればこの国際標準に準拠できるでしょうか。$\mathrm{e}$の方は簡単です。お馴染みの憎っくき`mathrm{}`ですね。

```latex:アルファベットの立体化
$e \mathrm{e}$
```
結果
$e \, \mathrm{e}$

では$\large\unicode{x3c0}$はどうでしょうか。

```latex:ギリシャ小文字の立体化??
$\pi \mathrm{\pi}$
```
結果
$\pi \, \mathrm{\pi}$

はい。やったことがある人も多いと思いますが、普通`mathrm{}`ではギリシャ小文字は立体になってくれません。$\uplatex$の場合は外部パッケージを利用して立体化させます。いくつか方法がありますが、その一つは[upgreek](https://www.ctan.org/pkg/upgreek)です。プリアンブルで`\usepackage{upgreek}`した後、数式で`\upalpha`、`\upbeta`…のように書くと立体(upright)のギリシャ小文字を入力できます。

```latex:upgreek使用例
%~~
\usepackage{upgreek}
%~~
\begin{equation}
    \pi \uppi
\end{equation}
```
結果(5倍くらい拡大)
![pi_uppi](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205942/c710bfe6-95a0-92bf-523e-d0a5856e3955.png)

フォントにもよりますが、$\large\unicode{x3c0}$は両者の違いがわかりづらいので、せっかく立体にしてもそのことに気づいてもらえないかもしれません。


## MathJaxで立体ギリシャ小文字を表示する
何も考えず書いていたら前置きのほうが長くなってしまいました。ここから本題です。Qiitaや[Typora](https://www.typora.io/)では$\uptex$記法の数式を表示するのにMathJaxというJavaScriptライブラリを使用しています。残念ながら現在MathJaxにはギリシャ文字を立体化するコマンドや拡張機能はありません。更にいうと、デフォルトフォント(MathJax TeX)には立体のギリシャ小文字がそもそも存在しません[^1] [^2]。

そこで、MathJaxが対応している拡張機能の一つである`\unicode[height,depth][font]{charref}`で直接文字を指定する方法を利用します。フォントを閲覧者任せにしてしまおうという~~荒~~裏技です。オプションはページ内で一度指定すれば以降`\unicode{}`コマンドを呼び出すときには省略できます。最初からオプションなしにすると、高さは8 em、深さ2 emになります。フォントは`times`にしておけばそれっぽい感じになりますし、大抵のPCにはインストールされているでしょう。times系フォントがない環境では**ブラウザのデフォルトフォントで表示される**ことになります。

```latex:\unicode{}使用例
ˋˋˋmath
\mathrm{e}^{\mathrm{i} \large\unicode[0.5,0.05][times]{x3c0}} = -1
ˋˋˋ
```

結果

```math
\mathrm{e}^{\mathrm{i} \large\unicode{x3c0}} = -1
```

### ちょっと一言
[Boostnote](https://boostnote.io/)や[StackEdit](https://stackedit.io/)で採用されているKaTeXではこのような方法は使えません。似た?コマンドである`\u`は数式モードでは使用不可なようです。

## 結論
MathJaxで変にこだわろうとするのは面倒で実用的ではなく、なおかつフォント警察の魔の手からも逃れられない。



[^1]: MathJax Font Support - https://docs.mathjax.org/en/latest/output/fonts.html
[^2]: https://github.com/mathjax/mathjax-docs/wiki/Non-italic-(upright)-greek-letters
あなたの好きなCSSプロパティは何ですか？

次の中から選んでね

- transform: translate
- margin: 0 auto
- position: absolute

# transformが好きなあなた

普通の人。みんな大好きtransform。
要素を変形するには万能なCSSプロパティ。

```html
<div class="box"></div>
<div class="box box--move"></div>
```

```css
.box {
  width: 100px;
  height: 100px;
  border: 1px solid red;
  box-sizing: border-box;
}

.box--move {
  transform: translate(100px, 0);
}
```
![スクリーンショット 2019-12-22 2.46.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124296/fc52f414-7f1b-7b5c-1b8e-c007d769e3a7.png)

まあこうなる。

## では、これは？

```html
<div class="box box--move-large"></div>
<div class="box box--large-move"></div>
```

```css
.box--move-large {
  transform: translate(100px, 0) scale(2);
}

.box--large-move {
  transform: scale(2) translate(100px, 0);
}
```

![スクリーンショット 2019-12-22 2.46.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124296/bb965fb9-003c-ee89-4dd4-a4aea2ab94e5.png)

順番を変えただけで見え方が変わってしまった。
これには理由がある。

> 適用される 1 つ以上の CSS 変形関数です。変形関数は、左から右へ順に重ねられ、つまり右から左の順に変形の混合の効果が適用されます。
> https://developer.mozilla.org/ja/docs/Web/CSS/transform

つまり、 2倍大きくなってからの `translate(100px, 0)` は `200px` 移動することになる。

# margin: 0 auto が好きなあなた

安定志向。
昔ながらの伝統的な中央寄せ。

```haml
<div class="box box--center"></div>
```

```css

.box {
  width: 100px;
  height: 100px;
  border: 1px solid red;
}

.box--center {
  margin: 0 auto;
}
```

## コンポーネント指向が浸透した昨今は

レイアウトは親要素に任せる方が適切なシーンが多い。
※ `.box` はどこに配置さるかを気にしない

```html
<div class="container">
  <div class="box"></div>
</div>
```

```css
.container {
  display: flex;
  justify-content: center;
}
```

# position: absoluteが好きなあなた

きっと、すいも甘いも知った人。
`absolute` の従順さに惚れ惚れする。

```html
<div class="container">
  <div class="box box--bottom"></div>  
</div>
```

```css
.box--bottom {
  position: absolute;
  bottom: 10px;
  right: 10px;
}

.container {
  width: 80%;
  height: 300px;
  border: 1px solid blue;
  margin: 20px auto;
}
```

![スクリーンショット-2019-12-22-3.02.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124296/f8963e26-c9b9-b442-853c-297a35c1a9be.png)

## 親要素をたどって起点を探す

absoluteの `bottom, right` が基準となるのは `position: relative` がついている親要素。

つまり、 `.container` に `position: relative` を設定すれば
`.container` を基準としたポジションとなる。

```css
.container {
  position: relative;
}
```

![スクリーンショット-2019-12-22-3.03.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124296/9c91979b-b1fb-711d-3b37-606b7991c751.png)

従順なやつだなと思う。

※動画解説版
https://www.youtube.com/watch?v=VFkwIGoKATo
Raspberry PiをRADIUSサーバにしてWi-FiアクセスポイントにWPA2エンタープライズによるユーザ認証をさせる

# 経緯

Wi-Fi接続にてユーザ単位の認証を行い、端末側もネットワークの正当性を確認できるようにするため、WPA2エンタープライズ(WPA2-EAP)の環境を整備した際の記録です。

WPA2-EAPの認証方式には複数ありますが、ここでは普及度の高いPEAPを用いました。認証方式について詳しくは、以下のページが参考になります。

* [EAPのはなし](https://www.silex.jp/blog/wireless/2013/10/eap2.html)

# 筆者の環境

* Raspberry Pi
  * Raspberry Pi 3 Model B Rev 1.2
  * Raspbian GNU/Linux 9.4 (stretch)
* Wi-Fiアクセスポイント
  * TP-LINK Archer C9 (ブリッジモード)
* Wi-Fiクライアント
  * macOS Catalina
  * iOS 13
  * Android 10

# freeradius の設定

Raspberry PI の Wi-Fi をオフにする場合は、以下のコマンドを実行します。

```sh
sudo iwconfig wlan0 txpower off
```

RADIUSサーバのfreeradiusをインストールします。

```sh
sudo apt-get install freeradius
sudo systemctl enable freeradius
```

EAPで用いるプロトコルを、以下の通り設定します。
 

```conf:/etc/freeradius/3.0/mods-available/eap
eap {
  ...
  default_eap_type = peap
  ...
}
```

ログ(`/var/log/freeradius/radius.log`)に認証の結果が表示されるように、以下の通り設定します。

```conf:/etc/freeradius/3.0/radiusd.conf
log {
  ...
  auth = yes
  ...
}
```

RADIUSクライアント（ここではWi-Fiアクセスポイント）からのアクセスを許可するため、設定ファイルに以下を追加します。

```conf:/etc/freeradius/3.0/clients.conf
client private-network {
        ipaddr = 192.168.0.0/24 # RADIUSクライアントのアドレス、もしくはネットワーク
        secret = somerandomtext # 任意のランダムな文字列
}
```

認証するユーザアカウントを、以下のように設定します。`DEFAULT`より上に記載するよう注意してください。`Cleartext-Password` は平文による記載となるので望ましくはありませんが、取り急ぎ動作確認のために指定しています。

```conf:/etc/freeradius/3.0/mods-available/files
yourusername  Cleartext-Password := "yourpassword"
```

freeradiusを再起動します。

```sh
sudo systemctl restart freeradius
```

# Wi-Fiアクセスポイントの設定

Wi-Fiアクセスポイントに以下の設定をします。

* セキュリティ
  * WPA2-エンタープライズ AES
* RADIUSサーバIP
  * Raspberry PiのIPアドレス
* RADIUSポート
  * 1812
* RADIUSパスワード
  * `/etc/freeradius/3.0/clients.conf`に設定した`secret`

以上で、WPA2エンタープライズによるWi-Fi接続ができるようになりました。

# MACアドレスによる認証を行いたい場合

以下のページに参考になる情報があります。

* https://wiki.freeradius.org/guide/Mac-Auth
リモートのデバイスをメンテナンスする(有償)

# はじめに

enebularは無料で利用できるサービスですが、一部の機能は有償機能として提供しています。
最近リリースした有償機能の一つ、リモートメンテナンス機能についてご紹介しようと思います。

# リモートメンテナンス機能でできること

RaspberryPI等のデバイスにPCからSSHログインしてデバイスに対する操作ができます。
これだけだと普通にRaspberryPIを買っただけでもできるので、わざわざenebularを使うまでもないと思われるかもしれませんが、enebularを使うとデバイスがFirewallの中にあったり、グローバルIPを振られていなかったりした場合もSSHで接続できるようになるのです(当然、ネットに接続は必要ですが(^.^))。

従来は、SSHでデバイスのメンテナンスをするにはご家庭内のWiFiやセンシングのためにあちこちで稼働するデバイスと同じネットワークに入ったり、デバイスにグローバルIPを付与して外からアクセスできるようにしたりする必要があり大変だったと思いますが、enebularを使えばこれが簡単にできるようになるのです。

# リモートメンテナンス機能の利用準備

上で簡単にできると書いたのですが、準備は少々面倒です。
リモートメンテナンス機能では以下の図に示すように中継サーバを使ったSSHポートフォワード環境を作る必要があります。
SSHポートフォワード環境について以下に図示しました。

<img width="1176" alt="スクリーンショット 2019-12-20 21.21.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/f310f30d-ea55-f31e-2103-2fe2e454e00a.png">

中継サーバはグローバルIPを持つSSHが稼働するサーバであり、ユーザご自身で準備頂く必要があります。

①では中継サーバの特定のポート（ここでは10022番ポート)に接続があったらデバイスの22番ポートにフォワードする準備のための接続を行います。
これにより②のトンネルが開通します。
トンネルが開通後に、ユーザPCから中継サーバの10022番ポートに接続するとデバイスの22番ポートにSSH接続できるという仕組みです(③)。

環境構築手順の詳細は[マニュアル](https://docs.enebular.com/ja/Device/RemoteMaintenance.html)をご参照ください。

また、準備の際にenebularの画面から鍵をダウンロードするのですが、この鍵は二種類ありちょっと分かりづらいため以下の図で補足します。

<img width="1583" alt="スクリーンショット 2019-12-20 21.45.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/5ea1df34-5905-9b3c-b923-f108f9ee3b14.png">

ユーザはenebularの画面からRelayServerPublicKeyとDevicePrivateKeyをダウンロードできます。
RelayServerPublicKeyは`①SSHポートフォワードの準備のための接続`で利用する鍵であり、ユーザが中継サーバに配置する必要があります。
DevicePrivateKeyは`③デバイスにSSH接続`で利用する鍵であり、ユーザが自分のPCに配置する必要があります。

# リモートメンテナンスの接続

予め上記の利用準備をしておけば、enebularの画面からデバイスのリモートメンテナンスのオン/オフの切り替えを行えるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380472/6df3e153-4fcb-e9f0-92e3-b0fb6428a818.png)

ユーザは、画面から以下を入力して切り替えボタンを押すだけです。

* 中継サーバのホスト名(Relay server host)
* 中継サーバのポート番号(Relay server port number)
* 中継サーバにログインする際に利用するユーザ名(Relay server username)

トグルスイッチがオンに切り替わったらSSHポートフォワードの準備が整ったのでご自分のPCから中継サーバの上記で指定したポート番号にSSH接続すればデバイスにログインすることができます。

```
ssh -i ~/device-<id>.key enebular-remote-admin@<中継サーバのホスト名> -p <中継サーバのポート番号>
```
上記で`~/device-<id>.key`はenebularからダウンロードしたDevicePrivateKeyです。また`enebular-remote-admin`はデバイスにSSH接続するためにenebular-agentが用意した固定のユーザ名です。

# おわりに

複数のデバイスを利用してIoTシステムを構築することも多いかと思いますが、このような場合にも一つの中継サーバさえ準備しておけば別ポートを使って複数のデバイスをメンテナンスできますので便利です。
有償機能をご利用頂くと、リモートメンテナンス以外にもスケジュールデプロイ機能や、デバイス起動状態/デバイスログをenebularの画面から確認する機能などが使えるようになります。

ぜひenebularの有償機能の利用をご検討頂ければ幸いです。

すごく宣伝みたいになってしまいましたが以上です(´ㅁ`;)
一般的な方法で犬の年齢を人間換算したらそんな歳じゃないワン!!って怒られそうなので正しい年齢を算出してみた

今までワンコの年齢を人の年齢換算するときは、犬の年齢を7倍する方法を取られていたようですが、
DNAを調べて新たに計算式が作られたようです。
https://www.akc.org/expert-advice/health/how-to-calculate-dog-years-to-human-years/

その計算機をGoで作ってみました。
ついでなので、今までの計算方法のものも作って比較してみました。

つくったやつ
https://github.com/usk81/animal-age-to-human-year

計算式の結果を表にまとめるとこんな感じです。

| 犬の年齢 | 人の年齢換算（数式） | 人の年齢換算（一般的） |
| -------- | -------------------- | ---------------------- |
| 0        | 0                    | 0                      |
| 1        | 31                   | 7                      |
| 2        | 42                   | 14                     |
| 3        | 48                   | 21                     |
| 4        | 53                   | 28                     |
| 5        | 56                   | 35                     |
| 6        | 59                   | 42                     |
| 7        | 62                   | 49                     |
| 8        | 64                   | 56                     |
| 9        | 66                   | 63                     |
| 10       | 67                   | 70                     |
| 11       | 69                   | 77                     |
| 12       | 70                   | 84                     |
| 13       | 72                   | 91                     |
| 14       | 73                   | 98                     |
| 15       | 74                   | 105                    |
| 16       | 75                   | 112                    |
| 17       | 76                   | 119                    |
| 18       | 77                   | 126                    |
| 19       | 78                   | 133                    |
| 20       | 78                   | 140                    |

7倍してる方やばいですね、20歳になると人間超越しています。

新しい計算式の方は、1歳でもういいおっさんになってます。
３１歳超えてない人は1歳以上のワンコを見たら、犬パイセンと呼ばないといけないかもしれません。
20歳はいい感じのご老人ですね。

勉強がてら、go-chartを使って年齢をプロットしてみました。
青いほうが今回の計算式のものです
![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9094/adcf29b7-d2e3-05f0-6e8a-b2e0d6b70d62.png)

go-chart
https://github.com/wcharczuk/go-chart

go-chart使い方わかると便利です。
例見てもよくわからなかったので試行錯誤が大変でしたが...
OSS初心者がOSSにプルリクエストを送るまでに意識してやったこと

この記事は [くふうカンパニーのアドベントカレンダー](https://qiita.com/advent-calendar/2019/kufu) の22日目の記事です。

みなさんこんばんは。
突然ですが、OSSにコミットしたことはありますか？僕は先日初めてOSSに[プルリクエスト](https://github.com/rubocop-hq/rubocop-rake/pull/21)を送りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215444/5b6ce3f8-2a26-f589-a89a-ac0312fede98.png)
(最近githubのアカウントを整理したのでプルリク作成者がよく分からなくなってます…)



ただ、OSSに貢献するのって、やったことない人からすると「なんだかよく分からないし難しそう」「強強エンジニアがやること」のように思っている人も多いのではないでしょうか？僕自身も実際にプルリクを送ってみるまでは「本当に大丈夫かなぁ…迷惑じゃないかなぁ…」とか思っていました。

__全くそんなことはありません！__

というわけで、__OSS初心者がOSSにプルリクエストを送るまでに意識してやったこと__について、簡単にまとめようと思います。

# そもそもなぜOSSに貢献しようと思ったのか
ライブラリを作る側に回りたいと思ったからです。
これまでの僕は、誰かが開発した便利なライブラリを何も考えずにありがたく使っているだけでした。とはいえ便利なライブラリも勝手に湧いてくるわけではなく、世界のどこかにいる知らない誰かが開発してくれているからこそ使えているという事実があります。
そう思うと自分も使ってばかりではなく、作る側に回って__世界のどこかの誰かに貢献できるようになりたいな__と思いました。

# OSSの開発をするのにハードルになったこと
自分にとっては

- 自分の今の技術レベルでプルリクエストを送っても迷惑にならないかどうか
- 英語でのやり取り

の２点がハードルに感じていました。
特に__自分の今の技術レベルでプルリクエストを送っても迷惑にならないかどうか__の方が心理的に大きな障壁になっていたような気がします。

# ハードルを越えるために意識してやったこと
上記であげたハードルを乗り越える為に

1. プルリクエストを送りやすそうなリポジトリを選定する
2. OSSにコミットしてる人の話を聞きに行く

の2点に意識して取り組みました

## 1. プルリクエストを送りやすそうなリポジトリを選定する
選定する際には

- リポジトリの規模が小さい
- 自分が普段利用している

の2つを軸に選定しました。
リポジトリの規模が小さいと__コードを追いやすく理解しやすい__ので、変更を加える障壁が少なかったです。
また、自分が普段利用しているライブラリへの貢献だと、自分にもダイレクトにメリットがあるので、モチベーションが続きやすいかなと思いました。

## 2. OSSにコミットしてる人の話を聞きに行く
勉強会などに参加して、実際に普段からOSSにコミットしている人の話を聞きに行きました。何人かの人からお話を伺ったところ

- タイポ直すとか、バグの原因を特定するとか、自分ができそうなことから始めればいい
- 細かいことは気にせず、とりあえずプルリク出してみたらだいたい何とかなる
- 英語でのやり取りはgoogle翻訳で何とかなる
- プルリク大歓迎

などのお言葉をいただきました。つまりは__とりあえず何とかなるからやってみたらいい__ということが分かったのでとりあえずプルリクを送ってみようと思いました。
実際にプルリクを送ってみたところ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215444/c9ced533-349d-35e9-ef14-c6763251eb0c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215444/f1059e8b-af20-b057-fd25-56762fe7582b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215444/ca569ee0-a745-30db-a531-8d9c5c56658f.png)

レビューでコメントをいただく度に__Thank you__って言ってもらえました。これが想像以上に嬉しくて、勇気を出して送ってみて本当によかったなあと思いました。そして、自分も誰かのプルリクにレビューをする時は、もっと感謝の気持ちを持ってレビューしようと思いました。

また、英語でのやり取りもgoogle翻訳を使えば何とかなりました(高校の時の英語の偏差値40でした)

## まとめ
- OSSにプルリクを送るとめっちゃ感謝される
- リポジトリの規模は小さい方が変更を加えやすい
- 英語でのやり取りはgoogle翻訳で何とかなる

これからもどんどんOSSにプルリクを送っていきたいなと思います！
日本の緯度経度の情報を全取得するダウンローダを作った

Google Mapを頼らずに住所から位置情報を自力で取得できないか調べてみたら簡単にできそうだった。
国土交通省国土政策局が公開しているので、そこから取得したらよさそうです。

GIS
http://nlftp.mlit.go.jp/cgi-bin/isj/dls/_choose_method.cgi

こんな感じ

<img width="731" alt="スクリーンショット 2019-12-22 2.05.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9094/4449cd3f-49c4-f2f8-cc98-a2e052d519c9.png">

面倒そうなので、ダウンローダを作ってみた。
上記のスクリーンショットの版数（赤枠のところ）だけ覚えておいてください

以下で、全国の位置情報をダウンロードできるようにしました。

```shell
go run main.go 版数 保存先
```

コードは以下の通り。
ref. https://github.com/usk81/til/tree/master/go/download-japan-gis-data

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

const urlTemplate = "http://nlftp.mlit.go.jp/isj/dls/data/%s/%02d000-%s.zip"

// e.g. go run main.go 17.0a /home/xxx/gis
func main() {
	args := os.Args[1:]
	if len(args) <= 1 {
		panic(fmt.Errorf("arguments are not enough"))
	}
	if err := bulkDownload(args[0], args[1]); err != nil {
		panic(err)
	}
	fmt.Println("download finished")
}

func bulkDownload(ver, p string) (err error) {
	if ver == "" {
		return fmt.Errorf("version is empty")
	}
	if p == "" {
		return fmt.Errorf("download path is empty")
	}

	for i := 1; i <= 47; i++ {
		u := getURL(ver, i)
		fp := filepath.Join(p, fmt.Sprintf("%02d000-%s.zip", i, ver))
		if err = downloadFile(u, fp); err != nil {
			return fmt.Errorf("fail to request : %s", u)
		}
	}
	return nil
}

func downloadFile(u, p string) (err error) {
	// Create the file
	out, err := os.Create(p)
	if err != nil {
		return err
	}
	defer out.Close()

	// Get the data
	resp, err := http.Get(u)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Write the body to file
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		return err
	}

	return nil
}

func getURL(ver string, no int) string {
	return fmt.Sprintf(urlTemplate, ver, no, ver)
}
```
Ubuntuのランチャ(タスクバー)に登録しても起動できないときの対処法

よく使うアプリはランチャ（Windowsでいうタスクバー）に登録しておくと便利です。
Windowsでは、アプリを開いているときにタスクバーにあるアイコンを右クリックして「タスクバーにピン止めする」をすれば簡単にタスクバーに登録できます。Ubuntuで同じことをすると登録はされますが、それをクリックしてもうまく起動しないことがあります。(もちろん起動するアプリもあります。)
例えばMATLABは端末(terminal)で

```
matlab
```
と打ち込めば起動しますが、それをランチャに登録してもクリックによって起動しませんでした。
Anacondaのanaconda-navigatorでも同様のことがあったのでよくあることのように思います。

#解決方法
ランチャでの起動を設定するものとして、デスクトップエントリファイルというものがあるようです。
これはホームフォルダの中の隠しファイル内（~/.local/share/applications/）の中に存在し、ランチャに登録すると生成されるようです。
テキストエディタで開くと、設定内容が編集できます。
「Exec=」の後がアイコンをクリックしたときに実行される端末でのコマンドです。
MATLABの場合はここを「matlab -desktop」にすれば起動できました。
他にもアイコンやパスを指定することができるので、このデスクトップエントリファイルは様々な使い方ができそうです。
Linuxユーザーの方にとっては当たり前のことなのかもしれませんが、勉強になりました。
kiesisからkinesisへ

気がついたら仕事納めまであと約１週間
上京して仕事をしている皆様、新幹線の指定席は取れましたでしょうか？
私は取れなかったのでデッキで立ちながら帰ることになりました。orz
それではパーソンリンクアドベントカレンダー22日目になります。

#はじめに
今回、私が書くのは業務で扱ったシステムの流れ図、苦労した点などを書きたいと思います。
各サービスの説明をしているといくら時間があっても足らないので詳しい仕様などは省いていきたいと思います。
なおこれから説明していくものは全てAWSのEC２上にインストールしているものです。


#システムの流れ図

<img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416620/7cbda2fd-5338-c850-0854-7d0e3a77b622.png" width=10%><img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416620/5d743e48-c36e-62b7-be80-7d05b7ebcba0.jpeg" width=10%><img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416620/aa0ea20d-0dee-6ea5-9b19-fc737759f8d1.png" width=20%><img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416620/5d743e48-c36e-62b7-be80-7d05b7ebcba0.jpeg" width=10%><img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416620/ec3791d0-5e76-a549-50dd-5434c989efc9.png" width=15%><img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416620/5d743e48-c36e-62b7-be80-7d05b7ebcba0.jpeg" width=10%><img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416620/aa0ea20d-0dee-6ea5-9b19-fc737759f8d1.png" width=20%>
<img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416620/5d743e48-c36e-62b7-be80-7d05b7ebcba0.jpeg" width=10%><img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416620/7cbda2fd-5338-c850-0854-7d0e3a77b622.png" width=10%>

上記の流れ図を業務で実装しました。全て苦労しましたがその中でも特に苦労したfluentdについての実際に使用したプラグインの説明と苦労した点、良かった点を書いていこうと思います。

#実際に書いた処理の説明
　fluentdへの入力は[fluent-plugin-in-kinesis](https://github.com/yusukeyamatani/fluent-plugin-in-kinesis)を使用しました。こちらは名前の通りkinesisにデータの投入があった場合にそれを入力として受け取ることができます。
　次にfluentdの出力先なんですが今回はkinesisのデータが圧縮されているとのことだったのでfluentdのデータを外部のプログラムに渡すことができるexecという標準のプラグインを使用しました。こちらはデータをファイルとして
外部のプログラムに渡すことで引数として任意の処理で扱うことができます。今回はこれで圧縮されていたデータを解凍することができました。

#fluentdで苦労した点

##　fluetdの理解
　業務で扱う前まで「fluentd? 何それ　おいしいの？」ってレベルでしたが調べていくうちになんとか分かるレベルになることができました。学習コストは高いほうだと思うので業務で触ることができ自分の武器にすることができてよかったと思います。
##　バージョンによっては動かないプラグイン
　今回、使用したプラグインは
・fluent-plugin-in-kiesis
の他に標準プラグインである
・exec
なのですが、バージョンが違うとどれか１つが動かなかったりしたので全てが動くバージョンを見つけるのが大変でした。
最終的にはnpmが保管されているサイトがあったのでそこからインストールすることで解決することができました。

#fluentdのよかった点
## 管理が楽
そのままの意味です。本当に楽でした。

## プラグインが豊富
　仕様の中で　ここはこうして欲しい　があったのですが、プラグインが豊富なおかげで１度も無理ということはありませんでした。プラグインを作っていただいた方には感謝しかありません。

#終わりに
　今回の業務ではプログラムを書くというよりも環境構築の色が強く出ていました。プログラムを書くのも楽しいのですが
私はクラウドサービスをいじっている方が楽しいと感じたのでクラウドサービスを自分の武器にしていきたいと思います。
ひん
EtherCATについて語る Advent Calendar 2019 21日目


この記事は EtherCATについて語る Advent Calendar 2019 の21日目です。
昨日は@nonnoiseさんの[宅内EtherCATのすゝめ](https://qiita.com/nonNoise/items/a5e2d960e47fcc52e1cd)でした。

#はじめに
このニッチなアドベントカレンダーもほぼほぼ埋まってきました。
ちょっと欠番っぽいので、埋め合わせ記事を残しておきます！
（遅れて21日目が出来たら教えてね！）

#何処まで作ったら良い?

まず、EtherCATのスレーブは**何処まで作ったら良いか**問題です。

マイコン開発をされている方なら、**アレもコレも実装して**と思いがちですよね。

自分もそう思う人でした。
ここは一つ失敗談を・・・（失敗談が多いな自分）

## 絶縁IO-2Aボード

![スクリーンショット_2019-12-22_01-13-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12499/d2dd29b3-ecbb-79b0-2761-2e7523a2cad7.png)
![スクリーンショット_2019-12-22_01-14-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12499/d809597e-a0c6-f8c9-a69f-50922e4f8981.png)

EtherCATでGPIOが手軽に試せたので、LED以外に何か作らねば！と思い、パッと思いついたのが**絶縁IO**です。

今回話したい内容は絶縁IOではなく、**絶縁IOに加え２A流れせるトランジスタアレーも付け、更に１６ポート分用意し、コネクタも付ける**という、てんこ盛り基板を作ってしまったことの話です。

何でこんな基板を作ってしまったのだろうか・・・

よく考えて見よう。**16ポートの絶縁IOを使う場面**というのがあるだろうか。
勿論、**絶縁IO**は電圧差があったりモーター駆動であったりで必要に成る場合があるが、それを**１６ポート**必要だったのか。

ここでEtherCATらしい開発手法がある。

EtherCATでは、**必要最小限の機能で実装したほうが良い。**

この馬鹿げた基板を考えると、16ポートは**8ポート**に減らしたほうが良いだろう。
基板を小さくし、部品単価も減らし、値段を安くしたほうが良い。
逆に、２Aの出力が必要であれば、基板サイズの小ささと部品単価の安さを考慮しつつ、**2ポート**でも十分である。

EtherCATでは、**基板を小さく、部品単価を減らしつつ、必須条件である機能を確実に実装していく**スタイルが最も良いと思われる。

ただ、ケースとしては**2A出力出来る絶縁IOが12ポート必要**というイレギュラーな場面があるとしましょう。

いつもなら、**あぁ！作っておけば良かった！失敗だぁ！**と嘆くのですが、EtherCATなら大丈夫。

何と、**2ポート**の物を**6個**繋げてしまえば**12ポート**となるんです！！

**２ポートEtherCATスレーブ x6**　です。

さて、先程言いましたよね。**基板を小さく、部品単価を減らしつつ、必須条件である機能を確実に実装していく**

もし**２ポートEtherCATスレーブ**が上記の通りであれば、**安く**なっているはずですよね。
まぁ、メーカーサポート料やブランド料で安くなってない可能性もありますが。

ニッチな**12ポート分**をカスタムで作るよりも、**2ポート分**を６台繋げたほうが、安くなります。

なので、**EtherCATを使えば、トータルのシステム開発費は安くなる**はずです。

ただ、自分みたいに多く失敗を重ねると、その分の損失が出ますのでね、そこは腕の差が出てきます。

#実際の現場では？
正直自分は現場を見たことがありません。
なので井の中の蛙かも知れませんが、この間ロボット博で見た所、
以下の様な構成に出会いました。

**サーボモータ３２個使用の製造ラインデモ。**

奥さん！サーボモータが３２台ですよ？！凄くないですか？？
カスタムで作ったんですか？制御ユニットだけでも滅茶苦茶大きくなるでしょ？？

**え？EtherCATスレーブ　３２台分繋げただけですって？？？！！！**

そう、３２台のEtherCATスレーブを連携し、３２台のステッピングモータを自在に扱っていたんです。
それぞれのスレーブは１個のサーボモータを的確に制御するように特化していました。

自分のミスの様に、折角だから**サーボモータ2個分やろうぜ！**とかせずに、１台動かすことに集中し、技術を安定させたんです。

#機能のコンポーネント化

余り産業界隈では聞き慣れない言葉かも知れませんが、WEBやソフトウェアではよく使われる**コンポーネント化**。
所謂、**機能の部品化**です。

今までは、**A+B+C**で動いていた機能を、そのままにせず**Aだけ**や**Bだけ**と行った切り分けをし、新規に**A+D+Q**の様な設計に過去の**A**を利用することが出来るという考え方です。

これを行うことで、**Aを再び開発するコスト**が削減出来るばかりじゃなく、**Aを作り置き**することが出来る為、再利用が可能となります。

あ〜まぁ、この辺を深く語りたいのが山々ですが、**自分が最もEtehrCATが気に入っている**ポイントが、この機能を部品化出来る点です。

勿論、他の通信仕様でも出来ると思いますが、**EtherCATはこの機能に意識が強い規格**と思っています。

#おわりに

え？ここで終わるの？！

ハイ、すみません。ここでおわります。
あまり書きすぎると、**同人誌第２巻**のネタが減ってしまいますし、
本来はこの辺りのコンサルを成り合いにして行こうかと思ったりしていますので、この辺で一旦お開きに。

それでは、また！
北神(@nonnoise)
kitagami @ artifactnoise.com
【mongoose】mongoDBに大量のdataをSeedする【seedgoose】

# seedgooseについて
最近ポケモン関連のアプリを作成していて、ポケモン達の画像のurlをmongodbに保存しています。
なので、手軽に大量のデータをseedできるプラグインないかなーって探してたらこのプラグインを見つけて
簡単に実現できたので、備忘録として書きます。

設定より規約の思想で作られているため、多少注意点などありますのでそれも説明していきます。

git 
[seedgoose](https://github.com/zhangkaiyulw/seedgoose)

執筆時点では星は9個しかついてないです。
ですが、かなりお手軽にできるのでおすすめです。

# 導入
```
npm i seedgoose
```
package.jsonにnpm scriptを追加します。
``npm run seed`` でseedを流す事ができるようになります。

``` package.json
  "scripts": {
    "seed": "seedgoose seed"
  }
```

# ディレクトリ構成
※必ず、以下のようにmongooseで定義したmodelの名前を複数形にしたjsonファイルをdataフォルダの配下に作成する必要があります。
 
```
─ data
　　├── pokemons.json 
```
```pokemons.json 
[
  {
    "_id": "11111111111",
    "pokedex" : "1",
    "imageUrl": "https://hogehoge.1.png",
    "name": ""
  },
  {
    "_id": "22222222222222",
    "pokedex": "865",
    "imageUrl": "https://hogehoge.865.png",
    "name": ""
  }
]
```
```models/Pokemon.js
const mongoose = require("mongoose");

const Pokemon = mongoose.model(
  "Pokemon",
  new mongoose.Schema({
    name: {
      type: String
    },
    pokedex: {
      type: String
    },
    imageUrl: {
      type: String
    }
  })
);
module.exports = { Pokemon };

```

つづいて設定ファイルを作成します。
※必ずファイル名は``.seedgooserc.js``として下さい。

```.seedgooserc.js
require("dotenv").config({ path: ".env" });

module.exports = {
  modelBaseDirectory: "./models", 
  models: "*.js",
  data: "data",
  db: process.env.MONGO_URI 
};
```

# seed実行

上記のファイルの作成が終わったら以下のコマンドでseedを実行します。

```
npm run seed
```

以下のように表示されていれば正常にデータが生成されています。

```
  create 11111111111 in pokemons
```

seedをやり直したい場合や、削除したい場合は、npm scriptに以下のように書けばいけるようです。

```package.json
"scripts": {
  "seed": "seedgoose seed",
  "reseed": "seedgoose reseed",
  "unseed": "seedgoose unseed"
}
```

ここまで読んでくださりありがとうございます。
すごくシンプルで使いやすいプラグインだと思いますのでぜひ使ってみてください。

それでは！
ssh-agent転送のトラブルシューティング

ssh-agent転送（Agent Forwarding）がうまく動かない、というトラブルにたまに遭遇しては毎回悩んでいる気がしたのでまとめてみます。

## ssh-agent転送の概要

ssh-agent転送というのは、ローカルサーバのssh-agentがリモートサーバでも使えるようになる仕組みです。いちいちパスフレーズを打たなくていい環境がリモートでも使えて便利、という奴ですね。

```
$ ssh -A [リモートホスト名]
```

上記のようにリモートサーバにログインすると、リモートサーバからSSHアクセスする場合にローカルのssh-agentを使って認証してくれます（`$HOME/.ssh/config`で設定することもできます）。

上のざっくり説明で通じない人はこの記事に辿り着かないと思うんですが、それでもわからんという場合は「[ssh agent forwarding](https://www.google.com/search?q=ssh+agent+forwarding)」でググってください。

## ssh-agent転送の状態は`ssh-add -L`で確認できる

さて、ssh-agent転送の設定をしているのになぜかSSH認証が失敗する、という状況になったとしましょう。

この場合、リモートサーバ上で`ssh-add -L`と打つとssh-agent転送がうまくいっているか確認できます。

### ssh-agent転送自体がうまくできていないとき

ssh-agent転送がうまくできておらず、ssh-agentにアクセスできないときは次のように表示されます。

```
$ ssh-add -L
Could not open a connection to your authentication agent.
```

この場合は一度ログオフして、`.ssh/config`に`ForwardAgent Yes `を追加するなり、`ssh -A [リモートホスト名]` でログインし直すなりしてみてください。

### 鍵が登録されていないとき

リモートサーバ上でssh-agentが見つかったものの、鍵が登録されていないときは次のように表示されます。

```
$ ssh-add -L
The agent has no identities.
```

この場合、ローカルサーバで`ssh-add`して鍵を登録しましょう。

ただし、ローカルサーバがmacOSの場合は注意が必要です。macOSでは手元のssh-agentは何も仕事をしていません。普段同等の仕事をしているのはkeychainという別のプロセスなのです。`ssh-add -K`とすることで、keychainの持っている情報をssh-agentに連携できます。

### 鍵が登録されているとき

ssh-agentに鍵が登録されている場合は次のように表示されます。

```
$ ssh-add -L
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDi（中略）K6CmI7kEsQxkBmZ1/nSAOiOgu3eTNkDF hnw@example.com
```

登録されている鍵ペアの公開鍵が表示されます。この鍵が期待通りかどうか、手元の公開鍵と見比べてみてください。

## 補足: ssh-agent転送を共用サーバで使ってはいけない

指摘している人はあまり多くないのですが、ssh-agent転送は状況によってはセキュアではありません。

> 以上のように、ForwardAgent は大変便利な機能であるが、 ログインした先のマシンの root 権限を持っている人が自分以外にもいる場合は、 注意が必要である。
>
> （略）
>
>  つまり、その人は senri 上で動いている私の ssh-agent すなわち私の ssh 秘密鍵を (passphrase 無しで) 利用することができてしまう。
>
> 出典： [仙石浩明の日記: ssh\-agent ＆ ForwardAgent を、より安全にしてみる](https://www.gcd.org/blog/2007/07/123/)

上記の記事でも指摘されているように、攻撃者がssh-agentの利用するUNIXドメインソケットにアクセスできた場合、パスフレーズ無しで自分の鍵ペアを使われてしまうのです。

とはいえ、ssh-agent転送より良い選択肢はあるのでしょうか。

実は多段でSSHするのが目的であればssh-agent転送は必須ではありません。`ProxyCommand` / `ProxyJump` を使えば同等の状況が実現できる上にセキュアなのでオススメです[^proxycommand]。

[^proxycommand]: 「[多段SSH ProxyCommand](https://www.google.com/search?q=%E5%A4%9A%E6%AE%B5SSH+ProxyCommand&rlz=1C5CHFA_enJP838JP838&oq=%E5%A4%9A%E6%AE%B5SSH+ProxyCommand&aqs=chrome..69i57j0l3.189j0j9&sourceid=chrome&ie=UTF-8)」でググってください

また、デプロイ時などリモートサーバ上でSSH経由で`git pull`したいような用途であれば[デプロイキーの利用](https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys)も検討すべきでしょう。

もちろん、ssh-agent転送が一番良いという場合もあります。ssh-agent転送は用法・用量を守って正しくお使いください。
CloudFormation内のDynamoDBリソース更新でハマった話

# 背景
AWS使ってサーバーレスで自分用の家計簿的なwebサービスを勉強も兼ねて開発中。基本的にAWSリソースはCloudFormationで管理中。AWS Amplify使えばいいんじゃね？という話もあるけど、AWSの勉強兼ねてるので、はい。

# やりたかった事
**既存テーブルにレンジキーを追加したい。** はい、普通でもテーブル削除＆再作成が必要な処理です。この時、このテーブルにデータは存在していないので新規キーに対する値不整合問題は無し。

# とりあえずやってみた。

```console:出たエラー
CloudFormation cannot update a stack when a custom-named resource requires replacing. Rename {対象テーブル名} and update the stack again.
```

カスタム名があるスタックで（更新でなく）交換が必要なリソースはCloudFormationでは更新できないという事ですね。
リネームせよと言ってるけど、DynamoDBのテーブル名は後から変えられない。

**一旦手動でテーブル消してみる。**

こうすれば再作成されるだろう、と期待。が、同じエラー。
真面目に対応すべく、検索して出てきた公式ページが以下リンク。
[AWS CloudFormation の「Cannot update a stack when a custom-named resource requires replacing」エラーを解決する方法を教えてください。](https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudformation-custom-name/)

カスタム名を変える必要があるらしい。上記リンクから辿った以下リンクによると、DynamoDBのカスタム名はTableNameプロパティらしい。ってそこ変えられないんですが。すでに実リソースは削除してるし。
[Name タイプ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-name.html)
※CloudFormationで作成されたリソースはAWSコンソールで変更しちゃ駄目って書いてありますね。でもCloudFormationで更新できなかったのですYo。

## 考察
CloudFormationで識別に使われてそうな名前らしき所は、CloudFormation内スタック識別子（というのか？ yamlだと第二インデント部分。）。

```yaml:CloudFormation抜粋
Resources:
# 中略 #
  {ここで指定している名称}:
    Type: "AWS::DynamoDB::Table"
    Properties:
      TableName: "hogehoge_table"
      AttributeDefinitions:
        - AttributeName: "tgt_date"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "tgt_date"
          KeyType: HASH
      BillingMode: PAY_PER_REQUEST
# 後略 #
```

ここを適当に別名にしてCloudFormation更新してみる。AWSでのコンソール更新時に表示される変更セットのプレビューでは、先ほど変更した箇所で、新しいの追加＋古いの削除の動作をする様子。が、テーブル名は変えてなかったので、新しいのを追加する部分で失敗。

ダミーの別テーブル作るのも微妙。追加で失敗するなら、一旦該当ブロックを消した状態で更新してみる。対象テーブル削除した状態だし、現状と一致してる。更新しようとした時の変更セットのプレビューでは、古いのを削除のみ。そして更新成功。実テーブルが削除されてるが、それに関わるエラーは無かった模様。

そして、本来更新したかった元のCloudFormationで実行。無事に新テーブルとして作成されました。

# まとめ

DynamoDBのキー構造変更のような、本来でも再作成が必要なリソース更新の場合、手動でやるのと同様にしましょう。公式ページに書かれている、**CloudFormationで作成されたリソースはCloudFormationで更新して** というのはこういう意味だったのだと思います。

 - CloudFormationのTemplateからそのリソース定義を一旦消す
 - （もしそのリソースIDを別の所で使用していたら、一旦現状固定値指定。多分。※未検証）
 - CloudFormationを一時変更Templateで更新
 - CloudFormationのTemplateに新規設定のリソース定義追加
 - CloudFormationを新Templateで更新
VNCでraspberry pi4のGUIが表示されないときに

# デフォルトでラズパイ４にVNCで接続
業務でラズパイを触ることが多かったので、最近ラズパイ４を購入しました。VNCで接続しようとしたら![VNC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441037/24181ea6-7847-11b6-ac0c-a1cf59abe1fa.png)

？？
表示されない。
ディスプレイに表示させるとVNCで表示される。。。ディスプレイに表示させて、VNCで表示させてもそんなに意味がない。。。

調べるとラズパイの解像度の問題のようですので、ラズパイ側で設定しましょう。

```terminal
sudo raspi-config
```

configuration toolの画面に行くと思うので、```Advanced Options```→```Resolution```を選択することで解像度を設定できると思います。設定は様々ありますが、私は```DMT Mode 85```を選択したところ、ディスプレイに表示しなくても、VNCでGUIが表示されるようになりました。これで快適にラズパイで開発することができそうです。
ところで、ラズパイ4にはUSB3.0があるのでついでにcoralも買いました。そのうちラズパイ4とcoralを使って何か作ろうと思います。
ESP Programmerを作ったよ

ESP-32を使う際に最大の問題となるのが電流です。
突入電流として８００ｍA以上が必要なのです。
このために高出力のレギュレーターが必要になります。

ESP-32の基板を製作した際に大問題となったのがこの電流でした。
このために、作ったのがESP Programmerです。
イチロヲさんなどが作られているものと同等のものです。
イチロヲさんFLINT ESP Programmer（ESPプログラマ） 
http://ichirowo.com/flint-esp-programmer/

一つ違うのは、ケースに入ると言う事です。
###全体写真
![DSC_0070 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/e794f5d6-b410-6d5f-7c39-7eab6cd6f7b9.jpeg)

###回路図
回路図を見るとわかりますが、M5Stackに近い構成となっています。
USBシリアル変換チップは、FTDIにしたりとちょっとこだわっていますが
ピンヘッダーを使用しようとすると、削れば入ります、通常だとケース当たってしまいます。
このため、ピンヘッダーを使用する場合は、ケース無で使用することになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/b2d3af91-a13c-e3c9-8adf-74c50c7120be.png)

###ケースイメージ
![DSC_0072 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/c909b7c3-331d-e9ca-ad45-81dcf58bef62.jpeg)

先の通り、ケースに入れるとピンヘッダーが使えないのが残念ですね・・・
（削れば使えます）
React Native ことはじめ

業務でReactNativeに強くなる必要があったので環境構築からメモ

いちいちググったりしなくていいようにここ見れば解決するような記事のつもり

画面のキャプチャなどは載せない予定

expoを使うと依存関係などまとめてくれるから楽らしい

expoはじめて使った感想としては、
・ライブプレビューすげえ！！
・(AndroidStudioと比較して)QRコード読み込むだけで(expoアプリのインストールは必要かな？)実機プレビューできんのヤバすぎでしょ！！
・各所での説明が初心者に優しいな

#コード書き始めるまでにやったこと
まずはwindowsで環境構築した手順のメモ
#expo
[GetStartWithExpo](https://expo.io/learn)
に従う
以降は従ってやったこと


##Node.js
まずはNode.jsをインストール

インストーラーの指示の通りでOK

##Node.jsインストール後
cmdで
`npm install expo-cli --global`
を実行

プロジェクト作成したいディレクトリに移動し、
`expo init my-new-project`
my-new-projectはそのままプロジェクト名になるので任意の名前に変更可能

##プロジェクト作成後
プロジェクトのディレクトリに移動
`cd my-new-project`
し、
`npm start`

ここはやってみた感じ
`expo start`
の方がいいかもしれない
この
`expo start`
はライブプレビュー起動するコマンドなので、作業するたび実行する必要があるコマンドかと

#ここでエラー発生
エラーメッセージは、
`Metro  'Bundler' process exited with code 1`


[stackoverflow](https://stackoverflow.com/questions/58760712/how-to-fix-metro-bundler-process-exited-with-code-1)を参照。

プロジェクト内の\node_modules\metro-config\src\defaults\blacklist.js
の

```
var sharedBlacklist = [
  /node_modules[/\\]react[/\\]dist[/\\].*/,
  /website\/node_modules\/.*/,
  /heapCapture\/bundle\.js/,
  /.*\/__tests__\/.*/
];
```
を

```
var sharedBlacklist = [
  /node_modules[\/\\]react[\/\\]dist[\/\\].*/,
  /website\/node_modules\/.*/,
  /heapCapture\/bundle\.js/,
  /.*\/__tests__\/.*/
];

```

に書き換えることで解決。

個人的にはエスケープシーケンスあたりが関係していそうかな、と思った。

#これで初期環境構築はできた
ここからはApp.jsを中心にゴリゴリにコード書いていく

#初期構築から2〜3時間触ってみた感想
1. (どの言語、フレームワークでも当たり前のことかもしれないけど、)公式ドキュメント読み込まなきゃ
特に、ググって出てくる情報が少ないような気がする

2. レイアウトなど、スタイルの考え方はCSSの考え方が使えそう
React Nativeで使うスタイル記述は、CSSの記述をケバブケースからキャメルケースに直したものっぽい

3. いままで使ってきたPythonみたいなスクリプト言語とは作りが違うので、慣れるのに時間がかかりそう
特にコンポーネントの考え方とかは頭リセットして考えないとこんがらがりそう



この後は画面遷移中心に、がっつりアプリの形を作っていくので、react-navigationを含めて勉強していきます
java 繰り返し処理

今日はjavaの繰り返し処理について書きます。

# 繰り返し文とは
一定の指示を与えた命令を繰り返す処理のこと


実行結果をこう出す場合

[1]
[2]
[3]
[4]
[5]

通常だと

```java:通常処理
 public class PrintFiveStars { |
      public static void main (String[] args){ |
          System.out.println("[1]"); 
          System.out.println("[2]"); 
          System.out.println("[3]"); 
          System.out.println("[4]"); 
          System.out.println("[5]"); 
      } 
 } 
```

繰り返し構文を使用した場合
5行ほどで済みます。
これを応用すれば、100でも1000行でも
編集するだけで処理を行うことができます。

```java:繰り返し処理

public class Print100Stars {
    public static void main (String[] args) {
     int sum = 0;
     for (int i = 1; i <= 5; i++){
          sum += 1;
          System.out.println(sum);
      }
  }
}
```
SOMで巡回セールスマン問題を解きたかった話

この記事は[近畿大学 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/kindai)の21日目の記事です．

## SOMってどんなもの？
[古河研究室のホームページ](http://www.brain.kyutech.ac.jp/~furukawa/data/som.html)では
> SOMはニューラルネットワークの一種で与えられた入力情報の類似度をマップ上での距離で表現するモデルです．

と紹介されています．つまり入力データ（大抵は高次元データ）を低次元（大抵2次元）に写像することによって類似度をマップ上の距離で表現するニューラルネットワークです．SOMについてより詳しくしりたい方は先ほどのホームページで公開されている[pdf](http://www.brain.kyutech.ac.jp/~furukawa/data/SOMtext.pdf)をお読みください．

## Somocluを使ってみる
SomocluとはSOMのライブラリです．なかなかSOMのライブラリがない中でしっかりしたライブラリだと思います．
### 3次元データを表現する
[公式ページ](https://somoclu.readthedocs.io/en/stable/example.html)にしたがって3次元データを分類分けしてみようと思います．

```python:exsample.py
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import somoclu

c1 = np . random . rand ( 50 , 3 ) / 5
c2 = ( 0.6 , 0.1 , 0.05 ) + np . random . rand ( 50 , 3 ) / 5
c3 = ( 0.4 , 0.1 , 0.7 ) + np . random . rand ( 50 , 3 ) / 5
data = np . float32 ( np . concatenate (( c1 , c2 , c3 )))
colors = [ "red" ] * 50
colors . extend ([ "green" ] * 50 )
colors . extend ([ "blue" ] * 50 )
fig = plt . figure ()
ax = Axes3D ( fig )
ax . scatter ( data [:, 0 ], data [:, 1 ], data [:, 2 ], c = colors )
labels = range ( 150 )

n_rows , n_columns = 100 , 160
som = somoclu . Somoclu ( n_columns , n_rows , compactsupport = False )
som . train ( data )

som . view_umatrix ( bestmatches = True , bestmatchcolors = colors , labels = labels )
```

上記のコードで生成した3次元データがこちらで
![スクリーンショット 2019-12-21 23.57.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326071/7f62255a-1f77-c32f-149f-8dbe541cc735.png)
学習後の画像はこちらです．
![スクリーンショット 2019-12-22 0.03.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326071/7b26a768-d41b-d80f-69d1-d71f7eae4e2a.png)
2次元空間に写像してもうまく似たデータ（3次元空間上で同じ郡に属していたもの）で固まっているのがわかると思います．

## 巡回セールスマン問題を解きたい！
そもそも巡回セールスマン問題とはなんでしょうか．[wiki]で調べてみると(https://ja.wikipedia.org/wiki/%E5%B7%A1%E5%9B%9E%E3%82%BB%E3%83%BC%E3%83%AB%E3%82%B9%E3%83%9E%E3%83%B3%E5%95%8F%E9%A1%8C)では
>巡回セールスマン問題（じゅんかいセールスマンもんだい、英: traveling salesman problem、TSP）は、都市の集合と各2都市間の移動コスト（たとえば距離）が与えられたとき、全ての都市をちょうど一度ずつ巡り出発地に戻る巡回路のうちで総移動コストが最小のものを求める（セールスマンが所定の複数の都市を1回だけ巡回する場合の最短経路を求める）組合せ最適化問題である。

と紹介されています．巡回セールスマン問題は都市の数Nに対して計算量がO(N!)とNP困難な問題なので、通常近似解を求めていきます．
### 方針
今回はSOMの近い性質を持つものは潜在空間上の近い位置に写像される性質を利用して、1次元に写像するといい感じ（アホがバレる）に解が出てきそうだと考えました．
### 終わらなかった実装と他力本願な結末
はい、実装出来ませんでした．
ただ他の方が今年のアドカレで[SOMで巡回セールスマン問題を解かれていた](https://qiita.com/syusyumk2/items/ec2e321b99d379d09eda)のを見ると1次元に写像する考えは間違って無さそう・・・．

## 最後に
流石にこのまま終わりたくないので自分で実装出来次第追記します．