OmniAICreator/Qiita-1.07M huggingface dataset:
PlayFabでのプッシュ通知設定が難しすぎた

UnityのバックエンドをPlayFabに任せてみようと試みていたのですが、iOSのプッシュ通知設定が難しすぎたので備忘録です。

# pemファイルのアップロードができない
PlayFabのプッシュ通知設定手順については、公式や紹介ブログがあるので詳細は割愛しますが、pemファイルをアップロードする段階で以下のようなエラーが発生してしまいます。

> Invalid parameter: Reason: cannot be empty

<img width="553" alt="スクリーンショット 2020-06-04 1.54.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201336/7d8337a9-0894-43d9-0a1c-49531803dc55.png">

pemの発行には問題無さそうで、まるでエラーの検討がつきません。

# 解決策
ぐぐってみると以下のフォーラムを発見。
https://community.playfab.com/questions/36895/instruction-on-using-admin-api-to-set-up-ios-push.html

一言で言うと、「管理画面のUIはバグってて使い物にならないから、AdminAPIを使え」とのことでした。

そしてこのAdmin API、pemファイルの中身をいい感じに整形してリクエストパラメータに乗っける、という癖の強い仕様になっています。

## リクエストパラメータの設定方法

以下フォーラム記事を翻訳したリクエストパラメータの設定手順です。

1. テキストエディタを使ってPEMファイルを開きます。2つの文字列のセクションがあり、1つは証明書、もう1つは秘密鍵です。

2. 証明書のテキストを別の空のテキストファイルにコピーします。また、"-----BEGIN CERTIFICATE-----"と"-----END CERTIFICATE-----"のマーカーも必ずコピーしてください。そして、テキストエディタのreplaceメソッドを使って、すべての改行を「\n」に正確に変換して、1行の文字列にしてください。これはどのPlayFab公式ドキュメントにも記載されていません(えっ)

3. 秘密鍵部分も同様に繰り返します。鍵のテキストの改行をすべて変換します。

4. PlayFab APIを呼び出すことができる環境（Postman、.NET Coreのコンソールアプリ、またはUnityのEditorスクリプト）で、SetupPushNotificationを呼び出します。

5 リクエストの "Key "プロパティに証明書の文字列を設定します。

6 Credentialプロパティに秘密鍵の文字列を設定します。


APIのインタフェースは公式を参照。
https://docs.microsoft.com/ja-jp/rest/api/playfab/admin/title-wide-data-management/setuppushnotification?view=playfab-rest


# 分からなさすぎる
この人はどうやってこの解決策にたどり着けたのか謎です。すごい。。。
おかげで無事にiOSのプッシュ通知設定ができました。
コーディング規約チェッカーを運用してみた使用感 (C#(Unity) JavaScript(CocosCreator), PHP(FuelPHP))


#はじめに

コーディング規約を自動的にチェックしてくれるコーディング規約チェッカーは、
複数人で開発する際の可読性向上や各人の書き方の癖を平準化できる便利なものです。

コードレビュー等で生産性のない指摘をし合わないよう、
チェックはシステムにやってもらうというのはとても合理的。

一方で、規約に縛られた書き方を窮屈に感じたりすることもあると思います。
そこで、各開発環境における規約チェッカーを使ってみた所感を書き残します。

#C# (Visual Studio)

規約チェッカーであるStyleCopは、
・プロジェクトにNuGetパッケージとしてインストール
・Visual Studioの拡張機能としてインストール

という2種類の方法があります。
前者が適用できるならそちらのほうがベターなようです。

・プロジェクトにNuGetパッケージとしてインストール

NuGetでインストールするとプロジェクト内に管理される形となり、
自動でチェックが走るため扱いやすいです。

また、NuGetではStyleCopの後継であるStyleCop.Analyzersが使用できるため、
その点でもオススメできる方法です。

規約のカスタマイズはソリューションにファイルを追加することで可能です。
https://anderson02.com/cs/cs-rules/cs-rules19/

・Visual Studioの拡張機能としてインストール

拡張機能としてインストールした場合はVisualStuioの右クリックメニューから、
「Run StyleCop」を選択することでファイルのチェックを走らせることができます。

規約のルール設定は右クリックメニューの「StyleCop Settings」からGUIで行うことができ、
編集結果はXMLファイル「Settings.StyleCop」として保存されるため、
このファイルをGitで共有するなどすれば、
チームでカスタマイズされたルールを共有できます。

##Unityでの利用

Unityのプロジェクトで利用する場合、NuGetによる導入はやや煩雑です。
https://t-tutiya.hatenablog.com/entry/2019/11/07/200330

拡張機能のほうはテキストファイルを検査するだけなので、
Unityプロジェクトであっても、通常のC#プロジェクトと同様の使い方ができます。

Unityの場合は、とりあえず拡張機能のほうを使うのが現状は無難かと思います。

#JavaScript (Visual Studio Code)

C#と違ってフレームワーク等により様々な書き方の流儀が存在するJavaScriptにおいては、
チェッカーもいくつかあり、それを適用するIDEも選択肢が多いため、
今回はVisual Studio Code + ESLintという組み合わせを選択しました。

npmでESLintパッケージをプロジェクトにインストールし、
Visual Studio Codeの拡張機能としてのESLintをインストールする、という流れです。
https://qiita.com/yohei_nakamura/items/4cf4876b3e36a46f3750

設定は「.eslintrc.json」というファイルに記述します。
npmのパッケージ設定とルールファイルをGitで共有することでチーム内でルールが共通化できる点については、StyleCopとほぼ同じです。

チェッカー本体とIDEの連携機能を別々にインストールする必要がある、という点がStyleCopとは異なります。
上手く動作しないときの原因切り分けが少々厄介です。

##Cocos Creatorでの利用

Cocos Creatorで利用する場合であっても、C#のようにプログラム側にプロジェクトの概念がないため（単なるJavaScriptファイル群）、
Webサービス等でJavaScriptを使用する場合と同じ使い方ができます。

ただし、Cocos Creatorの形式（クラス定義型とか）とルールがマッチしない部分もあるので、
必要に応じてルールをカスタマイズする等の対応は必要になります。

#PHP (Visual Studio Code)

PHPの場合もJavaScriptのように、複数のポリシーとIDEの組み合わせが想定されます。
今回はPHPの標準っぽさがあるPSR-2を使ってみました。

導入等は他記事を参照してください。
https://mseeeen.msen.jp/php-codesniffer-with-vscode/

PHPの場合、使用するフレームワークそのものが規約のような縛りがあったりするので、
ルールを調整して運用する必要がありそうです。

##FuelPHPでの利用

FuelPHPでも、フレームワークでクラスの書き方（スネークケースで書くなど）等が決まっているので、パスカルケースを使うようなルールになっているとそれだけで正しくかけないといった問題が発生します。

FuelPHP準拠のルールを使用するか、PSR-2のようなルールをベースにフレームワークに合わせてカスタマイズしていくか、

いずれにしろ運用に工夫が必要になります。

# おわりに 複数言語の比較

複数言語を比較してみると、言語やチェッカーの特性などが見えてきます。

C#は.NET Frameworkの統一感があるため、規約チェッカーを導入する場合もあれこれ悩む必要が
少なかったです。

Unityで公式に使えるようになると、もっといいですね。

JavaScriptとPHPは言語仕様が緩いことに加え、フレームワーク毎にまったく違う書き方があり、またエディタのデファクトも決定打がないため、様々な選択肢を試行錯誤する必要がありました。

カッコで改行するかどうか、など、細かいところも差異がでてくるため、しっかりと統一したルールを策定し、共有し、運用することが重要だと思います。
AWS EC2 perlbrew で perl環境作るときの No patch utility found

### 背景
- AWS EC2(CentOS7)でperl環境作る際にperlbrew使った。
- `perlbrew install perl-5.28.2` を実行した際にエラーで止まった。

### 原因
**patch コマンド**が使えなかった。

- perlbrewのログをcatしたら `No patch utility found` を確認した。
- どうやら patch がインストールされていないため処理が止まったらしい（参考文献を参照)

### 解決方法
- 参考文献に従って、 `yum install -y patch` を実行する。
- 上記実行後に再度perlbrewでインストールを実施する。

### 参考文献
- [WEB上からapacheの生ログをリアルタイム？で見ることが出来るようにするWEBアプリ - @OMAKASE](http://www.omakase.org/perl/web_apache_log.html)
電子メールについて無知だったので調べた

電子メールについて無知でなんとなく使っていたので、使われているプロトコルについて少し調べた。

## メールの配送
電子メールの配送は以下の3つのパートに分けることができる。

1. 送信者の端末 ~ 送信者のアカウントがあるメールサーバ
2. 送信者のアカウントがあるメールサーバ ~ 受信者のアカウントがあるメールサーバ
3. 送信者のアカウントがあるメールサーバ ~ 受信者の端末

## メールの配送に利用されるプロトコル

上記の1,2のパートでは、SMTP(Simple Mail Transfer Protocol)というプロトコルが利用される。
3にはPOP3(Post Office Protocol Version 3)や、IMAP4(Internet Message Access Protocol Version 4)が使われる。

### POP3
メールボックスに届いたメールをまとめて読み出すことを主な目的としたプロトコル。読み出したメールは端末に保存するため通信が途切れてもメッセージを読むことができる。また、メールを読み出した後はサーバーから消去するので、サーバーの容量を心配しなくて済む。

### IMAP4
サーバー上のメールボックスにメールを入れたままにして、それを読むことを目的としたプロトコル。ただし、IMAP4を利用したメールソフトでは一度読んだメールは端末に保存するなどの工夫が行われている。


#### POP3とIMAP4の使い分け

POP3とIMAP4の使い分けとしては、一台の端末でメールを読むだけで良いならPOP3、複数台の端末で同じメールを読みたいのならIMAP4を使うことが自然。最近では、複数の端末からメールを読むことも多いため、これまではIMAP4に対応していなかったメールサービスがIMAP4に対応するようなことも見受けられる。

### SMTP
SMTPでのやりとりは全てテキストで行われ、サーバに対してコマンドを送ると、それに対するリプライがサーバから返ってくる。このようなやりとりをメールの送信が行われるまで何度も行う。

ますはメールを送ろうとする側がサーバーに対して、グリーディングを送りセッションの開始を告げる。続いて、差出人のメールアドレスを、次に宛先のメールアドレスを指定、ここでメールの本文を送り、通信を終了する。

#### SMTPで送信されるコマンドの例
* HELO: サーバーへのセッションの開始を伝える
* MAIL FROM: 差出人のメールアドレスを指定
* RCPT TO: 宛先のメールアドレスを指定
* DATA：　メール本体
* QUIT：終了

コマンドを送信するとサーバーから数字3桁のリプライコードが返ってくる。

#### リプライコードの例
* 220: サービス準備OK
* 221: チャネルクローズ
* 250：リクエスト正常終了
* 354: メール入力開始指定
* 500: コマンド構文エラー

POP3やIMAP4もSMTPと同様にやりとりはテキストで行う。ただし、SMTPとは異なる点として利用の最初の段階で、ユーザーがサーバーにログインするためのやりとりを行う。

### 迷惑メールを防ぐために

SMTPの基本的なやりとりにはログインは不要。しかし、これでは迷惑メールなどの送信に不正利用される。

#### OP25B(Outbound Port 25 Blocking)
ISP(Internet Service Provider)内から外部のサーバの25番ポート(SMTPが利用するポート)への接続を禁止する。しかし、正当なメールの送信は問題なく行うことができるように、メールサーバに587番ポート(サブミッションポート)を用意し、このポートにはSMTP-AUTH(メール送信時にIDとパスワードを必要とする仕組み)を設定して、サーバを利用する権限がある人のみメールを送ることができるよにしている。
設計能力の大切さ

以前から感じていたことをちょっとポエムにしてみようと思う。

言語の構文は覚えた。
開発環境はインストールした。
サンプルプログラムをビルドして実行できる。
ライブラリの使い方もわかる。
作ってみたいアプリケーションのイメージがある。

で・・・
# 最初に何をすればいいんだっけ？

これは常々自分が感じてきた、処女作を作ったことのない開発者が最初にぶちあたる壁ではないかと考えている。アプリケーションを作りたい欲求はある。作ってみたいアプリケーションのイメージもできている。開発に必要なものはそろっている。しかし最初の一歩が踏み出せない。何をしたらいいのかわからない。

これはひとえに「設計の領域」の経験不足からくるものだと思うのだ。今回の例に挙げているGUIアプリケーションは一例に過ぎないのだが、開発対象を概要から詳細に向けて設計していくという経験がないせいで、

###最初になすべきことは何か
###そのために何を考えねばならないか
###その考えに従って設計をどうやってまとめるか
###まとめた設計に沿ってどうやって実装するか

という一連の作業が最初の一歩で躓いて、文字通り一歩も進まない。設計なんかどうでもいいから動けばいいや！という方針で、思うがままに実装していけるバイタリティのある人なら、情熱に任せて次々に現れる障害を克服していけるだろう。だが、最初に何をすべきかの見当がつかず、目の前の課題に圧倒されてしまうタイプの人にとっては、課題の克服ができなければ一歩たりとも踏み出せない。結果、アプリケーションを作る前準備だけがそろった状態であきらめてしまう。

開発環境とか開発言語とかライブラリの使い方とか、そういった情報は世の中にあふれているし、書籍もあるし、検索すればかなりの情報が出てくる。だが、アイデアを抽象化して機能として設計し、その設計にそって開発環境を使いこなし、実装を進めていくという一連の動作を教育する情報は極端に少ない。皆無と言ってもいい。

趣味のブログを書き溜めた著者が、猫でもわかるシリーズで書籍化に成功したように、最初の一歩を踏み出すために何が障害になるのか、その障害をどうやって克服していけばいいのか、そういうノウハウの領域が圧倒的に不足している。また、概要から抽象設計、詳細設計へと進めていくためには、文書作成能力も問われるし、思考を整理して明文化する推敲能力も必要になる。そういう経験は普通の人はほとんどしたことがないだろう。

そういう、何というか「設計から実装に必要になる人間的なノウハウの集大成」みたいな書籍なり情報なりをまとめたもの（書籍でもWebでも何でもいい）が存在してくれたら、もっとプログラミングに足を踏み入れる人も増えてくれるのではないだろうか。

などと書き連ねてみたが、取り止めがないのでこのへんにしておく。
単刀直入にgit rebaseのsquash

備忘録です。

###git rebase -i for squash
1. `git rebase -i HEAD~N` or `git rebase -i [commitHash]`
	指定した数字によってHEADコミットから古い順で選ばれたコミットの数が決まります。直にコミットのハッシュを指定することも可能です。指定した一番古いコミットが選ばれたコミットに含まれます。

2. そうしたらこのようなまとめたコミットのVIMのファイルが出てくる。

	```
	pick d94e78 Prepare the workbench for feature Z     --- older commit
	pick 4e9baa Cool implementation 
	pick afb581 Fix this and that  
	pick 643d0e Code cleanup
	pick 87871a I'm ready! 
	pick 0c3317 Whoops, not yet... 
	pick 871adf OK, feature Z is fully implemented      --- newer commit
	```
3. そこで一番古いコミットを選択し（PICK）、他のコミットをその一番古いコミットにまとめるわけです。
	
	```
	pick d94e78 Prepare the workbench for feature Z     --- older commit
	squash 4e9baa Cool implementation 
	squash afb581 Fix this and that  
	squash 643d0e Code cleanup
	squash 87871a I'm ready! 
	squash 0c3317 Whoops, not yet... 
	squash 871adf OK, feature Z is fully implemented      --- newer commit
	```
4. 次に出てくるテキストファイルでコミットのメッセージを編集することができます。（僕の場合一番新しいコミットのメッセージを残すだけ）
5. 成功するためには必ずコミット履歴を書き換える必要になってくるのでここで`git push --force`を使います。（originに）
6. 以上です。
pythonでソートアルゴリズム -バブルソート

#はじめに
プログラミング初心者がソートアルゴリズムを自分なりに理解し、コーディングしてみたものの忘備録になります。
間違いもあるかもしれませんがご了承ください＆ご指摘いただけると助かります…。
ここでは、**バブルソート**を扱います。
参考にした本と記事はこちら
→https://www.codereading.com/algo_and_ds/algo/
→https://book.impress.co.jp/books/1118101057

#バブルソート
基本となるソート。値の比較の様子が泡が上がっていくように見えるのでバブルソートという。
隣同士の要素を比較し、大きい値を配列の最後に押しやるイメージ。

##手順
![バブルソート.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614239/4af60a67-f75b-0d44-b71b-0d9c4616cd0c.jpeg)



ここで青字で書いている数字(1-1, 1-2, 1-3, …)は、第1段階の1回目の比較、第2段階の2回目の比較、といった意味になる。

##比較回数
比較回数は、第1段階で6回(配列の大きさ7より1少ない)、第2段階で5回、…と段階を重ねるごとに減っていくので、
配列の大きさをnとすると、

```math
(n-1)+(n-2)+(n-3)+...+2+1 = \sum_{k=1}^{n-1} k = \frac{1}{2}n(n-1)
```

となる。※高校数学！！

##プログラム

```python:bubble_sort.py
a = [4,6,1,2,3,8,5]

# 段階ごとにfor文を回す
for i in range(len(a)-1):
    # 各段階の中で、順番に比較を行う
    for j in range(0, len(a)-1-i):
        if a[j] > a[j+1]:
            a[j], a[j+1] = a[j+1], a[j]

print(a)
```
##出力結果
```console
$ python3 bubble_sort.py
[1, 2, 3, 4, 5, 6, 8]
```


##計算量
プログラムからわかるとおり、for文を2回まわすのでO(n^2)となる。

参考：計算量の大きさ

```math
O(1) < O(log_2 n) < O(n) < O(n log_2 n) < O(n^2) < O(n^3) < O(2^n) < O(3^n) < O(n!)
```

※それぞれグラフを書いてみたらわかる！！


# おわりに
初めて記事を投稿するので、練習がてら書きました。
思ったより書くのに時間がかかることがわかったので、残りのソートはサクサクと書いていきたいです。
findとfind_byの違い

両者の違い
-

``find``
-検索条件として指定できるのは『id』のみ
-データを複数取得できる
-検索結果が無い場合は例外を発生させて処理を中断
``find_by``
-検索時に複数の条件を指定できる。また、『id』以外ののカラムでも検索できる
-取得できるデータは最初にマッチした１件のみ
-検索結果が無い場合nilを返すため処理を中断されない

使い方(find)
---
基本形はモデル名にfindを繋げて引数を指定。
それによって該当するモデルのテーブルからデータを検索できる。

```ruby
モデル名.find(引数)
```
指定できる引数は
『数値型』、『文字列の数字』、『数字のリスト』、『数字の配列』
該当する『id』のデータが見つからない場合は**例外（RecordNotFound)**が発生する

【例】Userモデルからidが１のデータを返す

```ruby

User.find(1)
```
【例】Userモデルからidが1,3,5のデータを配列で返す

```ruby

User.find(1, 3, 5)
```

使い方(find_by)
---
モデル名に引数を繋げて条件を1つ以上指定する。
検索できる条件は『カラム名』、『検索条件』
**データが見つからない場合nilを返す。**

【例】Userモデルからnameカラムが"佐藤"とマッチした最初のデータを取得

```ruby

User.find_by(name: "佐藤")
```

【例】Userモデルからnameカラムが"佐藤"で且つadminカラム(管理者)がtrueの最初のデータを取得

```ruby

User.find_by(name: "佐藤", admin: true)
```

【例】Userテーブルから作成日が1週間以内のデータを1件取得

```ruby

User.find_by("created_at > ?", 1.weeks.ago)
```
初学者が躓くreturnの概念

#プログラミング初心者が躓くreturn(返り値)

なんとか理解することができたので
忘れないようにアウトプットも兼ねて投稿しておく

returnの意味は大きく２つ

・処理を終わらせる

・値を返す

値を返すという概念はなかなか理解しづらいですが
私は関数で処理して得た値を使いまわしたい時はretrunで返り値を持たせる！と覚えている

試しに２パターン関数を書いてみる

```php:returnなし

$num = 10;
function a($i) {
     $i * $i;
}

echo a($num);

//結果は出力なし

```


```php:returnあり
$num = 10;
function a($i) {
     return $i * $i;
}

echo a($num);

//100

```



結果returnをつけてやらないと、全く使いまわすことのできない関数となってしまう

```php:

$num = 10;
function a($i) {
     echo $i * $i;
}

a($num);

//100

```

上記の場合は関数内で処理が完結しているため、そのまま出力しても問題ないが

処理結果を別の処理では使いまわせないため使い方は限定的だ

##なぜreturnで躓くか

これは私の勝手な妄想である

プログラミングを勉強する方々はまずはじめにHTML・CSSを勉強するとおもう
そこからJavaScriptやphpを学習する人がほとんどのため、どの教材でも

「HTMLに出力してみよう」

ここからプログラミングを試していることがほとんどである
HTMLに出力するこということは、出力して終わりである
関数の値を他で使いまわさないのだ

実際にプログラミングを使って開発をする場合、ほとんどの関数には返り値をもたし他で使いまわせるようにするらしい

**まとめ**

WEB制作からプログラミングを勉強した方は躓きやすい
プログラミング言語から勉強した方は、理解しやすい

私は最初WEB制作を勉強したのでガッツリ躓いた:joy:
ソフトウェア・アーキテクチャ、アプリケーション・アーキテクチャって、何を指すの？何か違うの？

そもそもアーキテクチャってなんなの？ということを、前の記事[「アーキテクチャ」って、何を指すの？](https://qiita.com/nappyon/items/06cb24c4769a42d13e9b)で少し整理しました。
このポストでは、アーキテクチャについて調べている時に違いがよくわからなかったこの2つの単語について整理します。

前の記事で記載したように（私の理解になりますが）、アーキテクチャという単語は**「ある程度複雑な物事を指す単語と組み合わせて、それらの「構成方式」を意味」**します。

ということで、ソフトウェア・アーキテクチャ、アプリケーション・アーキテクチャというのは、それぞれソフトウェア、アプリケーションの構成方式（具体的な物ではなく、組み合わせ方、組み立て方というような抽象的なもの）を指すということになります。

ソフトウェア、アプリケーションってそもそも何だっけ…ということを考えつつ、それぞれの言葉が何を指すのか、違うものなのかを考えたいと思います。
# ソフトウェア、アプリケーションって何だっけ
## ソフトウェア
前の記事に続き、大辞林 第4版を参照します。
> ①コンピューター-システムに関係するプログラム。システムの運用に関する文書化された情報を含めることもある。ソフト。
> ②映像・音楽・マルチメディアなどの作品
> ③特にハードウェアに対して、知識や思考による産物を集積したもの。

ソフトウェアエンジニアリングの文脈で語られるときは、およそ①の前半の意味として捉えてよいのではないかと思います。

また、『Clean Architecture 達人に学ぶソフトウェアの構造と設計』にはこのような記述があります。
> ソフトウェアの1つ目の価値は「振る舞い」だ。プログラマは、マシンがステークホルダーのためにお金を生み出したり節約できるように、マシンに振る舞いを与えるために雇用されている。
> （中略）
> ソフトウェアの2つ目の価値は「ソフトウェア」という言葉に関係している。この言葉は「ソフト」と「ウェア」の複合語だ。「ウェア」は「プロダクト」を意味する。「ソフト」は……そう、ここに2つ目の価値がある。
> 　ソフトウェアは「ソフト」になるように考案されたものだ。マシンの振る舞いを簡単に変更する手段になることを目的としたものである。マシンの振る舞いを簡単に変更したくないときは、それを「ハード」ウェアと呼んだ。
> 　上記の目的を達成するには、ソフトウェアはソフトでなければいけない。つまり、簡単に変更できなければいけない。

2つ引用しましたが、内容をまとめると、**「ソフトウェアは、コンピューターシステムに関係するプログラム。マシンに振る舞いを与えるもので、振る舞いを簡単に変更するためのもの」**ということになるでしょうか。
（個人的な話になりますが、引用部の最後の「ソフトウェアはソフトでなければいけない。つまり、簡単に変更できなければいけない。」という部分は、普段仕事している時にもよく浮かぶ一文です。シンプルでかっこいい一文だなと思います）

ソフトウェア・アーキテクチャというと、そうしたプログラムの構成方式ということになります。
## アプリケーション
コトバンクのASCII.jpデジタル用語辞典から引用します。[アプリケーション](https://kotobank.jp/word/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-491)の項目には、`ワープロ・ソフト、表計算ソフト、画像編集ソフトなど、作業の目的に応じて使うソフトウェア`とあります。
`OS、ドライバー、ファームウェアなど、コンピューターの制御に使われるソフトウェアをシステム・ソフトウェアという`とあるように、コンピューターの制御をシステム・ソフトウェアが行い、その上でやりたいことをするために"応用"（＝アプリケーション）するのがアプリケーション（・ソフトウェア）ということになります。
なので、アプリケーションは、ソフトウェアをより狭めた概念です。

アプリケーション・アーキテクチャは、ソフトウェアの中でも、特にアプリケーション・ソフトウェアのアーキテクチャということになります。
# ソフトウェア・アーキテクチャ、アプリケーション・アーキテクチャの違い
ソフトウェアは、マシンを動かすためのプログラム全般。アプリケーションは、ソフトウェアの中でもより作業の目的に特化した、応用的なソフトウェアという違いがありました。

もちろんソフトウェア・アーキテクチャとアプリケーション・アーキテクチャと言った時に、それを言う人ごとに指すものは異なるでしょうけれど、ソフトウェアとアプリケーションの違いから、大まかにこうした違いがありそうです。

- ソフトウェア・アーキテクチャはソフトウェア全般の構成方式。アプリケーション・アーキテクチャはソフトウェアの中でもユーザーが利用するソフトウェアについての構成方式。

ソフトウェア・アーキテクチャと言った時の方が、より抽象的にソフトウェア全般のアーキテクチャについて語っていて、アプリケーション・アーキテクチャと言った時には少し具体的な、ユーザーインターフェースなんかも含んだアーキテクチャ（つまり、ユーザーインターフェース等も含めてソフトウェアをどう構成するか）について語っている…という感じでしょうか。
前述の通り、その文章を書いた人、その言葉を発した人が何をイメージしているか、意図しているかというのは文脈や人によって異なりますが、このように一度イメージを持つことで、その文章や会話への理解は深まるのではないかと思います。
obniz を使って A のアイデンティティ を見つけるサイトを作った。

<b>手元の様子↓</b>
![MVI_9981_1b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603301/849aa540-3220-0b9c-c5eb-92c41e506ba5.gif)

<b>サイトの様子↓</b>

<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/e2qBzOQtWW">pic.twitter.com/e2qBzOQtWW</a></p>&mdash; caz(ドライブ) (@cazu_PR) <a href="https://twitter.com/cazu_PR/status/1268206769102176257?ref_src=twsrc%5Etfw">June 3, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

---
ふー。obniz で サイトのオブジェクトを動かせるのは楽しいですね。
ちなみにサイトのURLは->https://a-identity.ml/ になりますが、html に obniz_id を入力しないと動かせないので、obniz を所持している方のみ遊べます。obniz を持っていない方は、これを機会に購入ましょう。(製品詳細:https://obniz.io/ja/products/obnizboard/)

<b>今回記述した html はこちらです。</b>
Obniz_ID 記述を、自分の所持している Obniz_ID に書き直しましょう。

```html:index.html
| <!DOCTYPE html> |
|:--|
| <html> |
|  |
| <head> |
|   <meta charset="utf-8"> |
|   <title>A←→</title> |
|   <meta name="description" content="Hello, WebVR! • A-Frame"> |
|   <script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script> |
|   <script src="https://unpkg.com/obniz@2.3.0/obniz.js" crossorigin="anonymous"></script> |
| </head> |
|  |
| <body> |
|   <a-scene background="color: #FAFAFA"> |
|     |
|     <a-text id="cylinder" position="0.5 1 -2" color="#000000" value="A"></a-text> |

|     <a-text position="-2 1 -2" color="#000000" value="pple"></a-text> |
|     <a-text position="-5 1 -2" color="#000000" value="ndroid"></a-text> |
|     <a-text position="-8 1 -2" color="#000000" value="ction"></a-text> |
|     <a-text position="-11 1 -2" color="#000000" value="rt"></a-text> |
|      |
|   </a-scene> |
|  |
|   <script> |
|     var sceneEl = document.querySelector('a-scene'); |
|     var cylinder = sceneEl.querySelector('#cylinder'); |
|  |
|     // 初期位置の記録 |
|     let defaultX = cylinder.object3D.position.x; |
|  |
|     var obniz = new Obniz("Obniz_ID");  // 自分のObniz_IDをいれましょう。 |
|  |
|     obniz.onconnect = async function () { |
|       obniz.display.clear(); |
|       obniz.display.print("3D A-Frame"); |
|       obniz.display.print("　↑↓"); |
|       obniz.display.print("obniz"); |
|       obniz.switch.onchange = function (state) { |
|         if (state === "push") { |
|           obniz.display.print("push"); |
|           cylinder.object3D.position.x = defaultX; |
|         } else if (state === "right") { |
|           obniz.display.print("right"); |
|           cylinder.object3D.position.x += 0.3; |
|         } else if (state === "left") { |
|           obniz.display.print("left"); |
|           cylinder.object3D.position.x -= 0.3; |
|         } else { |
|           obniz.display.clear(); |
|         } |
|       } |
|     } |
|  |
|   </script> |
| </body> |
|  |
| </html> |
```
ローカル環境でも遊べますが、デプロイしたい方は下記サイトを参考にするといいと思います。
https://qiita.com/oganyanATF/items/7fb681e863d8681c9039

最後までご覧いただきありがとうございました。
[JavaScript] window.を省略してはいけない場面に注意しよう

## windowオブジェクト

ブラウザでJavaScriptを実行する場合、`window`がグローバルオブジェクトとして存在します。

みなさんご存知のとおり、windowオブジェクトのプロパティにアクセスする際の `window.` は省略できます。

```javascript
// OK
window.alert('Hello world')
// 省略してもOK
alert('Hello world')
```

しかし、省略してはいけない場面があります。

## 省略してはいけない場面

省略してはいけない場面、それはプロパティの存在チェック時です。

一部ブラウザにしか実装されていない実験的な機能を使う場面や、古いブラウザに対応させるために、windowオブジェクトにその実装が存在するかチェックするコードを書くことがあると思います。

このとき、`window.`を省略してしまうと思わぬエラーに遭遇します。

### 省略時に発生するエラー

windowオブジェクトにチェック対象のプロパティが存在しない場合、`ReferenceError`となってしまいます。

これは、宣言していない変数への参照とみなされてしまうためです。

```javascript
// ====== NG! ======
// window.xxxxが存在するかチェックする意図だけど…
// 宣言していない変数を参照してしまい、ReferenceErrorとなる
if (xxxx) {
   xxxx()
}

// ====== OK! ======
// windowオブジェクトのプロパティの存在チェック時には明示的にwindow.を付与する必要がある
// windowオブジェクトにxxxxプロパティが存在しなくてもundefinedが返り、エラーにはならない
if (window.xxxx) {
   xxxx()
}
```

これの厄介なところは、対象の機能の実装がないブラウザで確認しないと、この問題に気づけない点です。

やはり、クロスブラウザのテストが大事ですね…
【Laravel】外部制約キーを設定しているデータを論理削除してみた

# はじめに
外部制約キーを設定しているデータは、通常テーブルから削除する事ができない。 
ただ、DBのテーブルからデータを削除には__論理削除__と__物理削除__の２種類ある。 
先ほど挙げた通常の削除とは__物理削除__の事を指します。 
では、__物理削除__の場合はどうなるのか、検証していくぅ！

# マイグレーション作成
外部制約キーを使用するために、まずテーブルを２つ用意しましょう。 
親テーブルには論理削除の為に、__deleted_at__カラムを用意しましょう。

```php:CreateSchoolsTable
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('schools', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->softDeletes('deleted_at', 0);
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('parent');
    }
```

子テーブルには__ForeignKey__を指定しましょう。

```php:CreateStudentsTable
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('students', function (Blueprint $table) {
            $table->id();
            $table->foreignId('school_id')->constrained();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('child');
    }
```

はいこれでおけい。

# Model作成
はい次ぃー、Modelの作成をしていきましょう。
親テーブルのモデルは論理削除を行いたいので、__SoftDelete__を使用します。

```php:School
use Illuminate\Database\Eloquent\SoftDeletes;

class School extends Model
{
    use SoftDeletes;
}

```

次に子テーブルのモデルのカラムは親のテーブルのIDだけですので、これだけ。

```php:Student
class Student extends Model
{
    protected $fillable = [
        'school_id'
    ];
}
```

# 削除してみる
まずは、外部制約キーが動いているか確認する為に物理削除してみる。
まずはSchoolモデルの__SoftDelete__をコメントアウトして、削除してみた。
<img width="1204" alt="スクリーンショット 2020-06-03 23.53.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647624/2de33360-7104-84d8-903c-744032d053e0.png">
英語で何て書いてあるかよく分かりませんが、外部制約キーの関係で削除できませんと書いてあるのでしょう。

次にSchoolモデルの__SoftDelete__をコメントアウトを解錠して論理削除して見ましょう。

```php:School
{
    "id":1,
    "created_at":null,
    "updated_at":"2020-06-03T14:59:17.000000Z",
    "deleted_at":"2020-06-03T14:59:17.000000Z"
}
```

__deleted_at__に論理削除された時刻が挿入されています、論理削除成功ですね。
ちなみに、Schoolのidが1のデータはDB上には残っていますが、取得をしようとするとnullで返ってきます。
しっかりしていますね。

# 結果
DBからデータが無くなっている訳ではないんだから論理削除できて当たり前だよね。
また気になることがあれば検証していきますぅ！
ではまた。
文字列を操作する時に使用するメソッド一覧


Yuheiです。

文字列内容を変えたり、動かしたりするときに使用する各メソッドの一覧です。

# equals
文字列の変数の中身が等しいかどうかを調べる為に、使用するメソッドです。

基本データ型の整数比較とは異なり、equalsを使用する際は、参照データ型の文字列比較になる点が異なります。


# equalslgnoreCase

大文字小文字を区別せずに中身が等しいかどうかを調べる為に、使用するメソッドです。

equalsメソッドでは、中身を調べる時に大文字か小文字かどうかも区別しますが、このメソッドの場合は、区別しないで、調べることができます。

# lengh

文字列の長さを調べます。

長さはバイト数ではなく、文字数にです。

例えば、下記の場合、結果は9になります。

```java
String rong= new String("おはようございます");

System.out.println(rong.length());

```

# isEmpty

文字列が空かどうかを調べます。

先ほどのlengthでは、文字数を調べるのに対し、こちらのメソッドでは文字列変数の中身が空かどうかを調べます。

空の状態」とは、文字列に何もない状態。つまり、文字列=”” の状態です。


```java
String str = "";
 
if(str.isEmpty()){
　  System.out.println("strメソッドの中身は空です");
  } else {
    System.out.println("strメソッドの中身は空ではありません");
}

```

上記のコードは、変数strの中身がからかどうかを調べ、if文を使って結果がどうなるかを分けています。



# まとめ

文字列を操作したり、調べたりするメソッドは、駆け出しの方にとっては、あまり使う機会はないですが、

覚えておくと、後々勉強する時に便利です。

以上。
Reactでstateの変更が反映されない

# 起こったこと
Reactで親コンポーネントでー行った、stateの変更が子コンポーネントで反映されません。
具体的には親コンポーネントは子コンポーネント１と子コンポーネント２を持っています。
子コンポーネント１で親のstateを変更し、その結果を子コンポーネント２で表示させています。
# 解決策
[公式ドキュメント](https://ja.reactjs.org/docs/react-component.html)にちゃんと書いてありました。
> 補足

> props を state にコピーしないでください。これはよくある間違いです。

> constructor(props) {
>  super(props);
>  // してはいけません
>  this.state = { color: props.color };
> }
> この問題はそれが不要(代わりに this.props.color を直接使用することができるため)であり、バグの作成につながる(color プロパティの更新は state に反映されないため)ことです。

>意図的にプロパティの更新を無視したい場合にのみ、このパターンを使用してください。その場合は、プロパティの名前を initialColor または defaultColor に変更してください。その後、必要に応じてキーを変更することで、コンポーネントにその内部の state を「リセット」させることができます。

>もしあなたが props に依存する何らかの state が必要だと思うなら、どうすればいいのか学ぶために私達の派生 state を避けることについてのブログ記事を読んでください。

propsの値をconstructorの中で初期値として与えると、子コンポーネントは親のstateの変更を感知できないようです。
多くのサイトでこのような書き方をしていたので、結構間違えている人も多いと思います。

結局、

```
constructor(props) {
  super(props);
  this.state = {postUser: props.postUser};
}
```
としているのをやめて、直接子コンポーネント内で`props.postUser`を使えば解決です。
`super(props);`を消すと子コンポーネントで`props`が使えなくなるので、これは残しておきます。

# 教訓
結局、公式が一番強い。
Javaで作る年齢当てゲーム

# とあるテレビ番組を見ていて
BSで「プロスタ」というScratchを題材にした子供向けプログラミング教育番組が
放送されているのを拝見。
私が見た回の中で、安藤先生という方の年齢を少ない質問数で当ててみようという
コーナーがあったのでその部分を参考にJavaで年齢当てゲームを作ってみました。

```java:Main.java
package andouteacher;

import java.util.Random;
import java.util.Scanner;

// 安藤先生の年齢を当てるゲームです
// 指定された回答数の中で年齢を当てましょう
// コツは２分探索です
// 効率の良い答え方で候補を絞っていきましょう

public class Main {
	public static void main(String[] args) {
		Random rnd = new Random();
		int age = rnd.nextInt(80);
		int limit = 5;

		Scanner sc = new Scanner(System.in);
		System.out.println("安藤先生は何歳に見えますか？");
		System.out.println("回答するチャンスは"+ limit +"回までです");
		for(int i = 0; i < limit; i++) {
			int answer = sc.nextInt();
			if(answer == age) {
				System.out.println("正解です");
				break;
			} else if(answer > age){
				System.out.println("それよりも年下です");
			} else {
				System.out.println("それよりも年上です");
			}
		}
		System.out.println("正解は" + age + "歳でした");
	}
}

```
番組内では質問できる回数に制限はありませんでしたが、このプログラムでは
回数を５回までに制限しています。int型のlimitという変数がそれにあたります。
すごくシンプルなゲームですがプレイしてみると意外に楽しめます。
興味を持たれた方は是非、このコードを実行して遊んでみてください（^-^）

#追記
ちなみにですが安藤先生は「70歳以上ですか？」と質問されると少しションボリします。
（これは番組内であったやりとりの話であって、このプログラムには一切関係ありません・・・）
三角関数の合成（WolframAlphaで）

環境は、win7&firefoxです。win7&ie11は、終了しませんでした。

(オリジナルポスト)三角関数の合成
https://qiita.com/nizu708/items/105d61ea69a40aeeb437
### 1
sqrt(2)*sin(x+pi/4)
https://www.wolframalpha.com/input/?i=sqrt%282%29*sin%28x%2Bpi%2F4%29&lang=ja
別の形:
sin(x) + cos(x)
### 2
sqrt(2)*cos(x-pi/4)
https://www.wolframalpha.com/input/?i=sqrt%282%29*cos%28x-pi%2F4%29&lang=ja
別の形:
sin(x) + cos(x)
### 3
sin(x) + cos(x)
https://www.wolframalpha.com/input/?i=sin%28x%29+%2B+cos%28x%29&lang=ja
別の形:
sqrt(2) sin(x + π/4)
Rustでクエリパラメータを含むURLを生成したい時

# 環境

- rustc 1.43.0

# やりたいこと

`https://example.com?q=rust&order=asc` みたいなURLのクエリ部分を動的に生成したい場合。

```rust
let url = format!("https://example.com?q={}&order={}", "rust", "desc");
```

このような文字列操作でもなんとかなるが、あまりイケてるとは言えないし、例えば `q` の値が空の場合は `https://example.com?&order=asc` みたいにキーごと含めないといった要件が出てくるとキツくなってくる。

# urlクレート

https://docs.rs/url/1.7.2/url/struct.Url.html

というわけでurlクレートの `Url::parse_with_params` を使う。

## Tuple

パラメータをタプルで渡す場合。

```rust
use url::Url;

fn main() {
    let tuples = vec![("q", "rust"), ("order", "desc")];
    let url = Url::parse_with_params("https://example.com", tuples).unwrap();
    println!("{}", url);  // output: https://example.com/?q=rust&order=desc
}
```

## HashMap

HashMapで渡す場合。

```rust
use std::collections::HashMap;
use url::Url;

struct Params {
    q: String,
    order: String,
}

fn main() {
    let mut map = HashMap::new();
    map.insert("q", "rust");
    map.insert("order", "desc");
    let url = Url::parse_with_params("https://example.com", map).unwrap();
    println!("{}", url); // output: https://example.com/?q=rust&order=desc
}
```
VScodeでDraw.ioを使ったアンパンマンの描画

VScodeに素敵なExtensionがリリースされたので嬉しくてやってみた🥺ぴえん

## 成果物

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/19ac3794-1648-263b-a0eb-8bfd6d8d27a6.png)


## 使ったコンポーネント

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/02b29321-46e5-5f58-0b01-93b0f051dbc9.png)


## 感想
まゆげに角度をつけるのが難しかった
パーツの配色はお好みで


## ひとこと
ちょっと顔がはらたつ
[Ruby on rails] Docker & Travis CIを使ってHerokuデプロイしたときのエラーまとめ

# 概要
初めてDockerやTravis CIを使ってデプロイしたので流れとエラーをまとめておきます。
誰かの参考に慣れば・・・
Dockerの勉強はUdemyの[こちら](https://www.udemy.com/course/aidocker/)の動画で勉強しました。
初心者にもかなりわかりやすく説明されているのでお勧めです。
※この動画ではpostgesqlを使う方法が紹介されていますが、僕は開発環境も含めmysqlを使ってので違いなどもメモしておきます。
# 環境設定
・Docker
・rails 5.2

#　大まかなデプロイ時の流れ
1. TravisCIに登録し、GitHubと連携
2. .tarvis.yml ファイルを書く
3. Travis CIにビルド
4. Herokuでアプリ作成
5. Heroku　と　Travis CI　に環境変数を設定する。

#　2つのエラー
##　mysql2が読み込まれない
Herokuにデプロイした際に、Build failedとなってしまいました。
ブラウザからHerokuのリポシトリーのActivityにあるBuild　log を見ると以下のところでエラーになっているようでした。

```
LoadError: Could not load the 'mysql' Active Record adapter. Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary adapter gem to your Gemfile.
```

これはブラウザのHerokuのリポジトリーのsettingsのConfig Varsを開き、

```
CLEARDB_DATABASE_URL : mysql://~~
```
となっているところを

```
CLEARDB_DATABASE_URL : mysql2://~~
```
と変更すると直ります。デフォルトではmysqlが書かれてしまうんですかね？

##　DBがない！？
Herokuのアプリの画面に移動した際、```We're sorry, but something went wrong.```というエラー表示がされてしまいました。

これはローカルからHerokuへとアクセスし

```
$ heroku logs -t
```
でログを見てみると

```
ActiveRecord::StatementInvalid (Mysql2::Error: Table 'heroku_067b02b8d8fb0b9.users' doesn't exist: SHOW FULL FIELDS FROM `users`):
```
となっていて、DBができていないようなので、マイグレーションして解決しました。

```
$ heroku run rails db:migrate
```
※　travis.yml ファイルにデプロイの際に、マイグレーションするように書いたはずなんだけどなー。なぜかうまく行っていなかったですね。
細菌種が任意の遺伝子を持っているかKEGGで確認する

# 背景
KEGGは代謝パスウェイ解析のためのデータベースというイメージが強いですが、ある細菌種が特定の遺伝子を持っているかweb上で簡易に検索することもできます。[NCBIのgeneデータベース](https://www.ncbi.nlm.nih.gov/gene/)でも行えるのですが、注目していない細菌種や株もヒットするため、さっと調べるだけならKEGGの方が使いやすいように思います（僕がNCBI geneの使い方分かってないだけかも）。

# 方法
1. [KEGG](https://www.kegg.jp/)のサイトに行き細菌種名を入れて検索します。ここでは「Escherichia coli」とします。
<img width="776" alt="貼り付けた画像_2020_06_23_23_28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/ceff77de-1184-5d84-77f9-3d413e15fe2e.png">

2. 「KEGG GENOME」に株名が表示されるので見たい株名をクリックします。ここではk-12 MG1655にします。
<img width="642" alt="DBGET_Search_Result__KEGG_Escherichia_coli.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/9aaa69b1-bce8-c85f-e77e-095100a749a9.png">

3. 「Annotation」の「Show organism」をクリックします。
<img width="889" alt="KEGG_GENOME__Escherichia_coli_K-12_MG1655.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/8b0f072f-765a-3c49-1089-0c7521c71f5c.png">


4. Search genesの欄に検索したい遺伝子名を入力します。ここではyjhEとします。[Ensembl Bacteria](http://bacteria.ensembl.org/Escherichia_coli_str_k_12_substr_mg1655/Gene/Summary?db=core;g=b4282;r=Chromosome:4483301-4530690;t=EBT00001514522)のゲノムブラウザで確認すると、この遺伝子はpseudo geneとして登録されています。
<img width="862" alt="KEGG_GENOME__Escherichia_coli_K-12_MG1655-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/5e950e4f-1804-9b9e-e736-892033421f3f.png">
![Escherichiacolistr_K_12substr_MG1655_yjhE_pdf（1ページ）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/10f702e4-8539-68ea-ccf6-ffd294abf85a.png)

5. 検索の結果、pseudogeneであるとの表示が出ます。「b4282」をクリックすると詳細な情報が得られます。
<img width="574" alt="DBGET_Search_Result__T00007_yjhE.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/cb456dd8-b145-cce2-cc6d-06e3f9d8ab13.png">
<img width="852" alt="KEGG_T00007__b4282.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/68deb881-acab-d2e0-355f-6ad666d9cedc.png">

6. 試しにyjhE上流にあるyjhC（ゲノムブラウザ上で機能遺伝子と表示されています）を検索するとpseudo geneではなく遺伝子機能が表示されます。
<img width="572" alt="DBGET_Search_Result__T00007_yjhC.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/f0d595f3-3ec1-05b5-1503-f5b31a123e5c.png">
<img width="852" alt="KEGG_T00007__b4282.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/c4f39557-5093-4587-5163-c6788fc2ca20.png">
AWS CLI で EKS クラスターの IAM OIDC ID プロバイダーを作成

```
$ CLUSTER_NAME=example-eks-cluster
$ ISSUER_URL=$(aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text)
$ JWKS_FQDN=$(curl -sS $ISSUER_URL/.well-known/openid-configuration | jq -r '.jwks_uri' | perl -pe 's/^https:\/\/(.+?)\/.+$/${1}/')
$ CERTIFICATE_BODY=$(openssl s_client -servername $JWKS_FQDN -showcerts -connect $JWKS_FQDN:443 < /dev/null)
$ CERTIFICATE_START=$(echo $CERTIFICATE_BODY | grep -n 'BEGIN CERTIFICATE' | sed -e 's/:.*//g' | tail -n 1)
$ CERTIFICATE_END=$(echo $CERTIFICATE_BODY | grep -n 'END CERTIFICATE' | sed -e 's/:.*//g' | tail -n 1)
$ echo $CERTIFICATE_BODY | head -$CERTIFICATE_END | tail -$(expr $CERTIFICATE_END - $CERTIFICATE_START + 1) > /tmp/certificate.crt
$ ROOT_CA_FINGERPRINT=$(openssl x509 -in /tmp/certificate.crt -fingerprint -noout | perl -pe 's/^SHA1 Fingerprint=(.+)$/${1}/' | perl -pe 's/\://g')
$ rm -f /tmp/certificate.crt 
$ aws iam create-open-id-connect-provider --url $ISSUER_URL --thumbprint-list $ROOT_CA_FINGERPRINT --client-id-list sts.amazonaws.com
{
    "OpenIDConnectProviderArn": "arn:aws:iam::999999999999:oidc-provider/oidc.eks.ap-northeast-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
```
Repositoryの高速化について

#レポジトリ内部にキャッシュを設けよう。
エンティティの生成コストが高い場合や、レポジトリへのアクセス頻度が高い場合、その都度、エンティティを再構築、DBアクセスしては、パフォーマンスに問題が出てきます。
そこで、レポジトリクラスの内部に一度取得したエンティティを保持するキャッシュを設けることで、パフォーマンスを改善しましょう。

#例1（レポジトリへのアクセスが頻繁に発生する場合）
マスタを参照するなど、レポジトリへの頻繁なアクセスが考えられる場合、初回アクセス時に全マスタを取得し、キャッシュ化する方法があります。
パフォーマンスは良くなりますが、その分メモリを使用する点には注意が必要です。

```csharp
public class Repository
{
   private readonly HashSet<Entity> _cache = new HashSet<Entity>();

   public Entity GetPrimaryEntity(Key primaryKey)
   {
     if(_cache.Count() == 0)
        Read();

     return _cache.SingleOrDefault(x => x.Equlas(key));
   }

   private void Read()
   { 
     var entities = /* selectとか */;
    
     _cache.Clear();
     foreach(var entity in entities)
        _cache.Add(entity);
   }
```

#例2（キャッシュ内のエンティティと永続先との同期が重要視される場合）
トランザクションデータのエンティティの場合、永続化した先(DBなど)とキャッシュとの整合性が気になります。
その場合、永続化を行った直後はエンティティを再構築するようにします。
永続化の直後に再構築を行うので、エンティティは常に最新の状態になります。

```csharp
public class Repository
{
  private readonly HashSet<Entity> _cache = new HashSet<Entity>();

  private bool _reset = false;

  public Entity GetPrimaryEntity(Key primary Key)
  {
    if(_cache.Count == 0 || _reset)
       {
          Read(Key);
          _reset = false;
       }     
   ...
  }

  public void Read(Key primaryKey) { ... } 

  private void Save(Entity entity)
  {
     /* update, insertとか */
     _reset = true;
  }     
```

#まとめ
どちらにおいてもそうですが、レポジトリ内にキャッシュを設けることで、クライアント側からDBにいつアクセスしているかを隠ぺいすることができます。
よくレガシープログラムでは、画面起動時にいろんなマスタの読み込みメソッドが記述されていたりしますが、レポジトリパターンを使用することで、マスタ読み込みを明示的に記述しなくてよくなります。
本当に必要とされるときに初めてDBアクセスが行われるため、処理の分散にもなります。
update_attributes is deprecated and will be removed from rails 6.1

##備忘録です。


題名のとおりのwarningが出ました。

```terminal:railsconsole
DEPRECATION WARNING: update_attributes is deprecated and will be removed from Rails 6.1 (please, use update instead)
```


***Rails6.1からupdate_attributes***ではなく```update```に置き換わる（すでに使える）そうなので、書き換えたら***warning***がなくなりました。
joinToStringがとても便利だったので今更紹介する


## 概要

今回は単発＆短めです

SQLのqueryやAPIリクエスト時のURLパラメータなど、とあるデータから配列からカンマ区切りで要素をStringにしたものを使ったり、そこにprefixをつけたりだとかするときに皆さんはどうするでしょうか
(自分はyoutubeAPIにカンマ区切りで複数のパラメータを渡す際にどうしようかと思っていました)

`StringBuilder`を作って`append`したり、配列をそのまま文字列に変換して`replace`したり色々やり方はありそうですね

ただ今回は、標準実装されている<b>joinToString</b>がとても便利だなと思ったので今更ですが紹介＆解説させていただきたいと思います

## 解説

元コードはこちらです

```_Collections.kt
/**
 * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied.
 * 
 * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit]
 * elements will be appended, followed by the [truncated] string (which defaults to "...").
 * 
 * @sample samples.collections.Collections.Transformations.joinToString
 */
public fun <T> Iterable<T>.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String {
    return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString()
}

```

`collection`, `sequence`に対して使うことができます
※上記のコードはIterableのものです

引数がかなり豊富で取り回しがききます

* `separator` -> 要素をそのままつなげるわけではなく、それぞれにseparatorを指定できます
    * `|` でも `-` でも `,` でも。空白であればそのままです

* `prefix` -> 文字通り連結したものの先頭に加えたいものを指定できます
* `postfix` -> 最後に加えたいものを指定できます
* `limit` -> 連結する際、何個の要素まで使うか指定できます
    * defaultは`-1`つまりlimitをかけないということですが、これが２だった場合は連結する要素は2つまでということになります
* `truncated` -> `limit`と合わせて使うものになります。`limit`によって配列の要素が全て使われず省略されてしまう場合に、ここで指定した文字列を追加することができます
    * 例えば `...` としておくと文字列の最後に`...`が付与されて省略された形を表現できます
    * ただし、上述した`postfix`が設定されている場合はそれが最後にくることに注意してください
* `transform` -> 関数から値の変換ができます `map`のようなものですね

## 実装

試しにかんたんな例を実装してみます

```kotlin
fun main() {
    val records = listOf(Record("Hoge", "Huga", 20000),
                         Record("A", "B", 2500),
                         Record("B", "C", 1200)
                         )
    val result = records.joinToString(limit=2, truncated="...", prefix="---*** ", postfix=" ***---", separator = ", ", transform = {
            record -> "${record.from} -> ${record.to} (${record.price})"
        })
    println(result)
}

data class Record(val from: String, val to: String, val price: Int)
```

誰が誰あてにどれほどのお金を振り込んだかを表すレコードとでも思ってください
実際にこのような形で実行すると

```
---*** Hoge -> Huga (20000), A -> B (2500), ... ***---
```

とてもきれいな出力が得られました 便利です

競技プログラミングでも使えそうですね

上記コードは[こちらのKotlin Playground](https://pl.kotl.in/fd1BoUD64)でお試しできます

## ref
* https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/join-to-string.html
* https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/join-to-string.html
コマンドラインからカラー画像をグレースケールに変換する


環境：Mac

```
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
```

# ffmpegを使う場合

```
ffmpeg -i lena-color.png -vf colorchannelmixer=.299:.587:.114:0:.299:.587:.114:0:.299:.587:.114:0 lena-gray.png 
```

# imagemagickを使う場合

```
sudo apt-get -y install imagemagick
```

```
convert lena-color.png -type GrayScale lena-gray.png
```

# 参考
[FFMPEG でグレースケールを扱う](https://nico-lab.net/grayscale_with_ffmpeg/)
[UbuntuにImageMagickをインストールする](https://pcl.solima.net/archives/716)
[Python でグレースケール(grayscale)化](https://qiita.com/yoya/items/dba7c40b31f832e9bc2a)
[Bitmapファイルフォーマット](http://www.umekkii.jp/data/computer/file_format/bitmap.cgi)
[BMP ファイルフォーマット](http://uno036.starfree.jp/PRGmanual/ImageFormatBmp2/index.html)
[【Python】BMP画像ファイルのヘッダ情報解析](https://algorithm.joho.info/programming/python/bitmap-file-header-read/)
[[Python] BMP(ビットマップ)データを読み込む方法](https://www.tutimogura.com/python-bitmap-read/)
3大害悪コード

「見たらわかる素晴らしいコードやん！！！」
そんなセリフを僕は言いたい。
ただ実際は、害悪なコードでありふれている。
そんな害悪なコードを紹介しようと思います。

## 名前が統一されていない
こっちのコードとあっちのコードが違うから、探しづらいなんてことがあります。

例えばこんなコード

```css:CSS
.blue-btn{}
.bl_button{}
```

これは完全に命名規則が疎かになっている弊害です。
本当に害悪で最悪で名前の把握がつrあくなるYo！

## インデントがない
これは普通に意識しない人も多いけど、インデントはやっておかないと後々大変すぎます。

例えばこんなコード

```html:HTML
<body>
<div class=“container”>
<div class”wrapper”>
<div class”inner”>
<p>Hello</p>
</div>
 </div> 
</div> 
</body>
```

これは意識してインデントするか、Prettierなどの自動整形ツールを使うことによって、解決できます。
本当に害悪で最悪で名前の把握がつrあくなるYo！(何がHelloじゃい！)

## 同じようなコードをコンポーネント化していない
同じようなコードだから、これはコピペして使っていけば良いや。
そんな甘い考えでコードを書いていくと、思わぬ害悪なコードを書いてしまいます。
上司A:「この部分変更あったから、書き換えといて」
コーダー: 「この部分って色々なところで使われてた気が…しかも一気に置換出来なさそう…オワタ」
って感じに変更に弱い、後々管理する人が大変な害悪なコードに気をつけましょう。

静的サイトを作るなら静的サイトジェネレータなどを使う。
動的サイトなら、それを生かしたコードを書いていく。
たとえ見出し一つであっても、見出しはたくさん使うので、コンポーネント化しておくと後々の変更に対応しやすいです。
本当に害悪で最悪で名前の把握がつrあくなるYo！

## まとめ
この記事が良いと思った方は、LGTMをしていただければ嬉しいです！
フォローも是非お願い致します(^^)

今日まで40日間毎日Qiitaを更新してきました。
今日で一旦毎日更新を一区切りさせます。
今まで読んでいただいた方には大変感謝しております。

ネタとしては、腐るほどあるのですが、
記事の執筆にかかる時間が、本業に差し支えつつあったので、やめます。
ただ、今後は別の形で情報発信していけたらと思います。
なので、僕のTwitterをフォローして欲しいです！

たまにQiitaも更新するつもりです(^^)
音楽データからボーカルと楽器を分離できる「spleeter」について

#開発環境 

OS:Windows10
コマンド:Git Bushを使用


#spletterとは 
ボーカルや複数の楽器で構成された音楽データを、機械学習を用いてそれぞれの音に分類したファイルとして出力できるものらしい
[詳細] 
(https://gigazine.net/news/20191107spleeter/#group=nogroup&photo=9)

#書いてある通りにするとうまくいかない:frowning2: 
![bbjspobrgbop.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597518/bc4e4f0f-b744-84b4-2753-d8e35182c16c.png)
[参考リンク] 
(https://gigazine.net/news/20191107spleeter/#group=nogroup&photo=9)

この通りにすると、「conda env create -f spleeter/conda/spleeter-cpu.yaml」を実行した段階でエラーが起きる

#原因 
そもそもgit cloneした[リンク](https://github.com/deezer/spleeter)に
conda/spleeter-cpu.yamlというパスが存在しないため

#解決策 
spletterのgitHubの[修正リンク](https://github.com/sigsep/spleeter-musdb)があった！

しかし、 README.mdのQuick startに書かれている内容ではうまくいかないため
下に修正版を乗せる

```
git clone https://github.com/sigsep/spleeter-musdb

conda env create -f spleeter-musdb/conda/spleeter-cpu.yaml

conda activate spleeter-cpu または　source activate spleeter-cpu

cd spleeter-musdb

spleeter separate -i spleeter-musdb/audio_example.mp3 -p spleeter:2stems -o output
```
「spleeter separate -i spleeter-musdb/audio_example.mp3 -p spleeter:2stems -o output」では、-i 音源のパス -o 出力先のパス -p spleeter:2(ボーカルと伴奏の分離)という意味

詳しくは[こちら](https://gigazine.net/news/20191107spleeter/#group=nogroup&photo=9)

なお、windowsでの、コマンドプロンプトやPowerShellでは4つ目のsepleenerが使えないので、python -m spleeter separate～　と書くとうまくいくはず、、たぶん


だいぶ端折った説明になっているので、間違いや質問があれば、下のコメント欄からよろしくお願いしまーす:point_down:
MaixCubeでSPIFFSを使ってみる

# はじめに

MaixCubeは初期ファームウェアにMaixPyが入っていて、SPIFFSにデモアプリが書き込まれています。このSPIFFS領域にArduino開発環境（Maixduino）でアクセスしてみます。

# SPIFFS

MaixCubeを含むMaixシリーズのフラッシュメモリは16Mバイトです。MaixPyのデフォルトでは0xD00000〜0xFFFFFFの3MバイトがSPIFFS領域になっています。

今回はESP8266のSPIFFS実装を参考に、MaixCube用のSPIFFSを実装してみました。SPIFFSライブラリーのソースは[こちら](https://github.com/fukuen/Maixduino_SPIFFS)

# サンプル

[デモアプリ](https://github.com/fukuen/maixcube-spiffs-demo)

- SPIFFS情報
- ファイル一覧
- ファイル読み込み

```c++:main.cpp
#include <Arduino.h>
#include <FS.h>

void setup() {
  Serial.begin(115200);

  bool res = SPIFFS.begin();
  if (!res) {
    Serial.printf("SPIFFS error \n");
    while (true) {};
  }

  // 1. SPIFFS info
  FSInfo fs_info;
  SPIFFS.info(fs_info);
  Serial.println("SPIFFS info");
  Serial.println("totalBytes:" + String(fs_info.totalBytes));
  Serial.println("usedBytes:" + String(fs_info.usedBytes));
  Serial.println("blockSize:" + String(fs_info.blockSize));
  Serial.println("pageSize:" + String(fs_info.pageSize));
  Serial.println("maxOpenFiles:" + String(fs_info.maxOpenFiles));
  Serial.println("maxPathLength:" + String(fs_info.maxPathLength));

  // 2. SPIFFS File list
  Serial.println("");
  Serial.println("File list");
  Dir dir = SPIFFS.openDir("/");
  while( dir.next()) {
    String fn, fs;
    fn = dir.fileName();
    fn.remove(0, 1);
    fs = String(dir.fileSize());
    Serial.printf("<%s> size=%s\n", fn.c_str(), fs.c_str());
  }

  // 3. SPIFFS File read
  Serial.println("");
  Serial.println("File read");
  File fd = SPIFFS.open("/main.py", "r");
  int len = fd.available();
  Serial.printf("file size=%d\n", len);
  String str = fd.readString();
  Serial.println(str);
  fd.close();
}

void loop() {
}

```

# 最後に

Maixシリーズは16Mバイトのフラッシュが搭載されているので、十分にSPIFFS領域を確保することができます。また、MaixCube以外のMaixシリーズ、M5StickVでも使えそうです。
【ReactNative】画面遷移の流れ

##①ReactNavigationをインストール
以下記事を参考に。
https://reactnavigation.org/docs/getting-started

##②必要なコンポーネントをApp.jsにインポートする。
```
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
```

##③Stack NavigatorをApp.jsに記述する。
```react

const Stack = createStackNavigator();

-----コンポーネント内に記述------
<NavigationContainer>
    <Stack.Navigator>
        <Stack.Screen name="画面の名前" component={コンポーネント名} />
        <Stack.Screen name="画面の名前" component={コンポーネント名} />
    </Stack.Navigator>
</NavigationContainer>
```
##④遷移元からonPressを指定する。
```react

// クラスコンポーネントVer.(propsでnavigationを受け取る)
onPress={() => this.props.navigation.navigate(‘遷移先画面の名前')}
```
「数GBのdumpいつ終わるんやろか」

## TL;DR
- プログレスバー表示するには `pv`使ったらいいよ
- `brew install pv`でインストールできるよ
- `mysqldump <parameters> | pv --progress --size 100m > dumpfile.sql`

## さあdumpだ

「よーし、mysqldump叩くぞー」
「userとhost、databaseとport指定して、と」

```bash
MYSQL_PWD=$DUMP_DB_PASSWORD mysqldump -u $DUMP_DB_USER -h $DUMP_DB_HOST -P $DUMP_DB_PORT --set-gtid-purged=OFF --column-statistics=0 > $DUMP_FILE
```

「そんでもってこいつを.shファイルにして、」
「よし、これでいつでもdumpし放題や！」

「よっしゃ、叩くでー」

```
$  sh dump.sh

```
「楽しみやな」

「…」

```
$  sh dump.sh

```

「…」

「そういや、このDBって確か数GBのサイズやったな・・・」

「…」

```
$  sh dump.sh

```

「（果たしていつ頃終わるんやろか・・・・）」

## せや！

「せや！プログレスバーを表示したればええんや！」

「`mysql dump progressbar`で、検索っと」

[mysql - Does mysqldump support a progress bar? - Stack Overflow](https://stackoverflow.com/questions/4852933/does-mysqldump-support-a-progress-bar)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/7d653710-a068-0d29-a9ce-c46742816fd4.png)

「ほう、`pv`ってのを使ってやればええんか」

「macはbrewでインストールできるんやな。 `brew install pv`でインストールして、っと！」

「あとはこいつに組み込んでやるだけ・・・」

「どうやら、大体のファイルサイズを指定するとそいつを100%で表示してくれるみたいや」

「確か２GBくらいあったはずや」

```bash
MYSQL_PWD=$DUMP_DB_PASSWORD mysqldump -u $DUMP_DB_USER -h $DUMP_DB_HOST -P $DUMP_DB_PORT --set-gtid-purged=OFF --column-statistics=0 $DUMP_DATABASE | pv --progress --size 2000m  > $DUMP_FILE
```

「よし、こいつを実行や！」

```bash
$ sh dump.sh
[>                                                                              ]  0%
```

「く、長い・・・。でもプログレスバーを得たワイなら待てる。待てるはずや。」

```bash
$ sh dump.sh
[=====================================================================>         ] 95%
```

「終わる、終わるぞーーー！」

```bash
[================================================================================] 109%
```

「あ、あれ、、、」

```bash
[================================================================================] 149%
```

「（こいつ一体なんGBのデータ持ってるんや・・・！？）」
Enum

```py
import enum


#@enum.unique
class Status(enum.Enum):
    ACTIVE = 1
    RENAME_ACTIVE = 1 #デコレーターをつけている場合はエラー出る
    #ACTIVE = 2 エラー出る
    INACTIVE =2
    RUNNING = 3


print(Status.ACTIVE)
#print(Status.STOPPING) エラー出る
print(Status.RENAME_ACTIVE) #ACTIVEが返ってくる
print(repr(Status.ACTIVE))
print(Status.ACTIVE.name) #ACTIVE
print(Status.ACTIVE.value) #1

for s in Status:
    print(s)
    print(type(s))

print(Status(1)) #Status.ACTIVE
```
実行結果：

```txt
Status.ACTIVE
Status.ACTIVE
<Status.ACTIVE: 1>
ACTIVE
1
Status.ACTIVE
<enum 'Status'>
Status.INACTIVE
<enum 'Status'>
Status.RUNNING
<enum 'Status'>
Status.ACTIVE
```
```py
import enum


class Status(enum.IntEnum):
    ACTIVE = 1
    INACTIVE =2
    RUNNING = 3


print(Status.ACTIVE)  # Status.ACTIVE
print(type(Status.ACTIVE))  # <enum 'Status'>
print(Status.ACTIVE == 1)  # True 判定の時だけ数値に置き換えてくれる
```
```py
import enum


class Perm(enum.IntFlag):
    R = 4
    W = 2
    X = 1


print(Perm.R | Perm.W)  # Perm.R|W
print(repr(Perm.R | Perm.W | Perm.X))  # <Perm.R|W|X: 7>
RWX = Perm.R | Perm.W | Perm.X
print(Perm.W in RWX)  # True
```
【AWS】AmazonLinuxのyumができない場合の対処

# はじめに
AmazonLinux構築中に`yum update`ができない事象が発生しました。
この場合の原因と対処についてアウトプットしていきたいと思います。

# 事象

AmazonLinuxにて`yum update`を実施したところ、下記画面にて止まることを確認。

```bash
[root@ip-192-168-5-129 ec2-user]# yum -y update
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
```

# 環境

## 自宅環境

|  項目  |  説明  |
| ---- | ---- |
|  自宅PC　|  Windows10  |
|  ターミナル  |  TeraTerm  |

## クラウド環境

|  項目  |  説明  |
| ---- | ---- |
|  PublicCloud　|  AWS  |
|  OS  |  Amazon Linux 2 AMI (HVM), SSD Volume Type  |

**※自宅PC→構築したEC2に接続できるようにVPC設定済み**

# 原因
**「DNSホスト名」**と**「DNS解決」**が有効化されていない。

# 対策
**「DNSホスト名」**と**「DNS解決」**の有効化

# 手順

## DNS解決の編集

- 対象VPCを右クリックし、「DNS解決の編集」をクリック

![DNS解決.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/6661aea3-98fc-2e12-d162-0a0e6f667cd9.jpeg)

- 「DNS解決」の有効化に☑を入れ、OKをクリック

![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/f2c45f8f-78f0-dd9e-4646-395959f1f728.jpeg)


- 「DNS解決が更新されました」と表示されることを確認

![3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/bc21ad9b-1258-ef4d-ba1b-e75e53722136.jpeg)

## DNSホスト名の編集

- 対象VPCを右クリックし、「DNSホスト名の編集」をクリック

![DNSホスト名.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/89981a99-1fd4-06d2-c0d8-6ea9df086cf2.jpeg)

-「DNSホスト名」の有効化に☑を入れ、OKをクリック

![4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/eca50f22-0b1f-7c0e-9c15-1d10df105f99.jpeg)


-「DNSホスト名が更新されました」と表示されることを確認

![5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/32d186b7-a7e3-f634-1eff-728e93035e9a.jpeg)

## AmazonLinuxにて`yum update`実施

実行できることを確認。

```bash
[root@ip-192-168-5-129 ec2-user]# yum -y update
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                               | 3.7 kB     00:00
amzn2extra-docker                                        | 3.0 kB     00:00
(1/5): amzn2-core/2/x86_64/group_gz                        | 2.5 kB   00:00
(2/5): amzn2-core/2/x86_64/updateinfo                      | 218 kB   00:00
(3/5): amzn2extra-docker/2/x86_64/updateinfo               |   69 B   00:00
(4/5): amzn2extra-docker/2/x86_64/primary_db               |  68 kB   00:00
(5/5): amzn2-core/2/x86_64/primary_db                      |  41 MB   00:01
Resolving Dependencies
--> Running transaction check
---> Package amazon-linux-extras.noarch 0:1.6.10-1.amzn2 will be updated
---> Package amazon-linux-extras.noarch 0:1.6.11-1.amzn2 will be an update
---> Package amazon-linux-extras-yum-plugin.noarch 0:1.6.10-1.amzn2 will be updated
```
Tello eduで編隊飛行入門（Python）

#はじめに
時代に乗り遅れた感ありますが、telloで編隊飛行やってみました。いろんな人がやっていますが、Pythonでやったのまとめてる人あんま見なかったんで、半分自分用でまとめときます。

#参考サイト
以下の記事/サイトに大変お世話になりました。
ありがとうございます。
[Tello Eduを子機にしてwifiアクセスポイントに接続する【python】](https://qiita.com/kei31/items/b3417e084f2d75999f6f)
[DJI の教育用トイドローン TELLO EDU で編隊飛行に挑戦（２）](https://tarosky.co.jp/tarog/4420)

#Telloの設定
前項で提示した[Tello Eduを子機にしてwifiアクセスポイントに接続する【python】](https://qiita.com/kei31/items/b3417e084f2d75999f6f)様を参考にさせていただきました。
皆さんもこちらをご覧ください。

#ipアドレスの確認
自分だけかもしれませんがipに対する理解が浅くここではまりました。自分は192.168.10.1にとりあえず命令投げ解けばいいだろとか思ってましたが違いました。

まず、telloの接続先を自分のPCのホットスポットにします。そうすると<img width="205" alt="qiita.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228792/362d5476-d3eb-e899-74aa-41ea75ee344b.png">
みたいな感じでIPアドレスが表示されるので、確認しておきましょう。winキー押してMobileHotspotで調べれば出てきます。

#実際のプログラム
```python
import socket
import time

drone1 = '192.168.137.125'
drone2 = '192.168.137.17'

tello_port = 8889

#udpソケット
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
drone1_address = (drone1 , tello_port)
drone2_address = (drone2 , tello_port)

#コマンドモードに入る
socket.sendto('command'.encode('utf-8'),drone1_address)
socket.sendto('command'.encode('utf-8'),drone2_address)


time.sleep(3)

#離陸
socket.sendto('takeoff'.encode('utf-8'),drone1_address)
socket.sendto('takeoff'.encode('utf-8'),drone2_address)

time.sleep(0.1)

#着陸
socket.sendto('land'.encode('utf-8'),drone1_address)
socket.sendto('land'.encode('utf-8'),drone2_address)
```
非常にシンプルな形に落ち着きます。
これなら任意の数のドローンに対応することができます。
注意点として先ほども申し上げましたが、ドローンのipは皆さん異なると思うので（違ったらすみません）きちんとご自分でお調べください。お願いします。
課題として、ドローンの数が増えるとコードがきもくなってしまいます。今後の課題として、ブロードキャストでできたらかっこいいかな？？なんて思っています。
cocoapodsでsdwebimageをinstallしたのにNo such moduleって出るときの対処法

#症状
cocoapodsでライブラリ（sdwebimage）をインストールしたのに，importしようとするとNo such moduleとエラーが表示される
#対処法
よくあるエラーらしい．いくつか対処法があるらしいが，
私は以下で解決した
##ステップ1
ワークスペース（拡張子が.xcworkspaceのやつ）を消す
##ステップ2
ターミナルでワークスペースがあった階層まで行き```pod install```を実行する
これで治るはず
参考
https://stackoverflow.com/questions/54683959/no-such-module-sdwebimage-using-pod
##私は治らなかった対処法
https://qiita.com/sukkuuuuu/items/47574f1a4dd3f92aa0bb