OmniAICreator/Qiita-1.07M huggingface dataset:
【Java】Spring DI ④ - ライフサイクル管理

# DIのライフサイクル管理とは
* DIでは、インスタンスのスコープを設定できる
* スコープは、@Scopeアノテーションで設定
* デフォルトではsingletonになり、インスタンスが１つしか作られない
* スコープが異なるインスタンスをフィールドに持つ場合注意

## ライフサイクル管理て何？
* インスタンスの生成（new）と破棄を管理
* newして生成したインスタンスを破棄するには、変数にnullを入れメモリを解放
* しかし！**@Autowiredを付けたフィールドではnullしなくてもSpringが自動でやってくれるのです！**
* しかもサーブレットを使う時に**インスタンスのスコープ登録もSpringがやってくれます！** (サーブレットはインスタンスをSessionスコープやRequestスコープに登録する機能)
* 注：インスタンスがいつ破棄されるのかをちゃんと把握しておくこと


####スコープとは 
* インスタンスの有効期限
    * 例：Javaのローカル変数でif文の中で宣言した変数は、if文の中がスコープなので、if文の外では使えない
* Sessionスコープ
    * ユーザーがログインしてからログアウトするまでが有効期限
* Requestスコープ
    * HTTPの1リクエストが有効期限
    * 例：ユーザー登録画面から登録結果画面までがRequestスコープの範囲

###Scopeの使い方
* 以下のように@Scopeアノテーションで、そのアノテーションにどのスコープに登録するか指定
* @Component以外にも、@Beanや@Controllerなどにも@Scopeアノテーションは利用可能
* **簡単にインスタンスの生成と廃棄ができる**

```java
@Component
@Scope("prototype")
public class SampleComponent{

}
```

#### @Scopeで指定するScope
* **singleton**
    * デフォルト設定
    * Spring起動時にインスタンスを１つだけ生成,
    * 生成後１つのインスタンスを共有して使う
* **prototype**
    * Beanを取得する度に、毎回インスタンスが生成
* **session**
    * HTTPのセッション単位でインスタンスが生成。Webアプリケーションの場合のみ使用
* **request**
    * HTTPのリクエスト単位でインスタンスが生成。Webアプリケーションの場合のみ使用
* **globalSession**
    * ポートレット環境におけるGrobalSession単位でインスタンスが生成
    * ポートレットに対応したWebアプリケーションの場合のみ使用
* **application**
    * サーブレットのコンテキスト単位でインスタンスが生成。Webアプリケーションの場合のみ使用できます。

##注意1：デフォルトはsingleton
* @Scopeを付けないと、インスタンスがsingletonで作成
* singletonだと、オブジェクトのインスタンスは１つしか作られず2個目以上のインスタンスを作ることすらできない
* ※@Controller、@Service、@Repositoryのスコープは通常singletonで十分

##注意2：スコープが異なるインスタンスをフィールドに持つ場合
* singletonスコープのインスタンスが、prototypeスコープのオブジェクトを持っている場合、**prototypeスコープを設定したBean(以下PrototypeComponent)が、singletonスコープになってしまう**

```java
//singletonスコープになってしまう
@Component
@Scope("prototype")
public class PrototypeComponent{

}
```

```java
@Component
public class SingletonComponent{	
    @Autowired
    private PrototypeComponent component;
}
```
【WIP】API学習

参考資料（いつもありがとうございます）
---

[REST APIを「叩く」って何？ツール使ったら初心者でも簡単だった
](https://kintone-blog.cybozu.co.jp/developer/000270.html)


[APIからREST-APIまで理解しよう
](https://qiita.com/oh_yeah_sayryo/items/aa870a1f761068a7b41d)
composer require時に起きたメモリー制限エラーとその解決策

# はじめに
画像投稿機能を実装する際に、AWSのS3に画像を保存するため
`league/flysystem-aws-s3-v3`をインストールしようとした際にこちらのエラーが出ました。

# エラー文
```
Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar://C:/ProgramData/ComposerSetup/bin/composer.phar/src/Compose
r/DependencyResolver/RuleSetGenerator.php on line 129
```

***メモリーが使い果たされて足りない***とのこと。

# 解決策
インストール時にメモリーを一時的に解放してあげることで解決できる。
まず、現在割り当てられているメモリーを下記コマンドで確認してみる

```
$ php -r "echo ini_get('memory_limit').PHP_EOL;"
```

結果、`512M`であった。
実際に、メモリ設定の制限を解除するために以下のコマンドを実行。


```
COMPOSER_MEMORY_LIMIT=-1 composer require 入れたいパッケージ名
```

`COMPOSER_MEMORY_LIMIT=-1`でメモリの制限を解除しているとのこと。
あくまでも一時的なものなので、メモリーが足りない際はその都度解放してあげればできる。

自分の場合、環境変数周りの設定が原因でコマンドが使用できず、解決できなかった。

```
[上記コマンド実行時]
'COMPOSER_MEMORY_LIMIT' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
```

別のやり方でもできるため、こちらのやり方についても紹介します。
やることは、php.iniファイルにて`memory limit=-1`とするだけ。

```php.ini
; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
memory_limit=-1 
```

しかし、自分は***「php.iniファイルはどこだっけ？」***と困りました。
こちらのコマンドで確認できます。

```
$ php --ini | grep "php.ini"
```

参考
・[Laravel composer ライブラリインストール時のメモリエラー](https://qiita.com/miriwo/items/a5fa25c1d36d00f40ec9)
・[php.iniファイルの場所をターミナルで確認する](https://qiita.com/miriwo/items/acb49b0a97b5d5fa47fd)

# 本番環境
本番環境でインストールする際にも、同様にエラーがでました。
同じ設定を行ったが別のエラーがでました。

```
mmap() failed: [12] Cannot allocate memory
```

メモリーが足りないと。調べてみるとスワップの設定をすることで解決できる。
やり方は下記サイトを参考にしました。

参考：[Amazon Linux2のswap領域を拡張する](https://webree.jp/article/amazon-linux2-swap/)

スワップとは？
> メモリの中身をハードディスクに移す機能。メモリが足りないときに行われる。
参考：[swap](https://wa3.i-3-i.info/word1718.html)

# まとめ
今回は、composer require時に起きたメモリー制限エラーとその解決策について紹介しました。

以上
【Java】Spring DI③

# DIで何ををやってるんですか？
* **DIの管理対象クラスを探す（コンポーネントスキャン）**
* **インスタンスの生成と注入**

##コンポーネントスキャン
* Springを起動時にDIで管理する対象のアノテーションが付けられているクラスを探す処理が走り、DIコンテナに登録する
* DIコンテナ上で管理するクラスを**Bean**という

【スキャン対象のアノテーション】

* @Component
* @Controller
* @Service
* @Repository
* @Configuration
* @RestController
* @ControllAdvice
* @ManagedBean
* @Named

##インスタンス生成と注入
* **DIコンテナにBeanのインスタンス生成し、注入する**
* DI対象のクラス（Bean）を集め、それらのインスタンスをDIが生成（new）
* 生成したインスタンスを以下の**@Autowiredアノテーション**が付けられるフィールドに注入
    * フィールド変数
    * コンストラクタの引数
    * setterの引数
* コンストラクタの前に@Autowiredを付けることで、引数にインスタンスが渡せる
* イメージは”DIコンテナの中で、各クラスのインスタンスを生成しておいて、そのインスタンスをgetterで取得、@Autowiredが付いているフィールドなどでは、DIコンテナのgetterを呼び出す”

```java
//イメージ
public class DependencyInjection{
    //各クラスのインスタンスを生成
    private SampleComponent component = new SampleComponent();
    private SampleService service = new SampleService();
    //SampleComponentインスタンスのgetter
    public static SampleComponent getSampleComponent(){
        return component;
    }
    //SampleServiceインスタンスのgetter
    public static SampleService getSampleService(){
        return service;
    }
}
```

* **@Componentなどのアノテーションを付けるだけで、いちいちFactoryクラスを作る手間が省ける！**


# じゃあどうやって実装するんですか？
* アノテーションベース
* JavaConfig
* xml
* JavaConfig＋アノテーション
* xml＋アノテーション

##アノテーションベース
* @Componentや@Controllerなどがついたクラスを、Springが自動的にDIコンテナに登録

##JavaConfig
* @Configurationアノテーションを付けたクラスを用意
* そのクラス中に、@Beanアノテーションが付いたgetterメソッドを用意
* getterの戻り値がBeanとしてDIコンテナに登録される
* DIコンテナの中で、JavaConfigクラス、Beanのインスタンスを用意しておいて、@Autowired箇所で各インスタンスをgetterで取得できる
* アノテーションベースと違い、@Beanアノテーションが付いたgetterの戻り値をDIコンテナで管理
* つまりDIコンテナで管理するインスタンス分のメソッドを用意する必要
* 細かい設定や切り替えができる

##JavaConfig＋アノテーション
* DIで管理したいクラスに@Controllerなどのアノテーションを付ける
* 細かい設定などをしたいインスタンスだけ、JavaConfigで設定
* 小規模なアプリケーションはアノテーションベースで作って規模が大きくなったり、設定の切り替えなどを行いたい場合にJavaConfig＋アノテーションで実装

## xmlベース
* JavaConfigで設定するのと同じ内容をxmlで行う
【Python】安定したソートを実装してみたのでメモ

# 問題
下記サイト参照
* http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_2_C

# 私の回答
```py
import collections

def chk_before_tranp_bigger(now, before):
    return int(before[1]) > int(now[1])


def is_stable(inputs: list, sort_: list) -> str:
    """
    条件
    ・同じ数字のカード
    ・入力に出現する順序と同じ

    いったん、入力データのリストを数字をキーにグループ分けをする
    例)
        {
            '4': ['H4', 'S4'],
            '9': ['C9'],
            '3': ['C3']
        }
    """
    judge = 'Not stable'
    loop = True
    set_num = collections.defaultdict(list)
    for input_ in inputs:
        set_num[input_[1]].append(input_)

    for g, dl in set_num.items():
        if len(dl) <= 1:
            continue
        min_index = -1
        for d in dl:
            if min_index > sort_.index(d):
                loop = False
                break
            min_index = sort_.index(d)
        if not loop:
            break
    else:
        judge = 'Stable'

    return judge


def bubble_sort(n: int, a: list) -> (list, str):
    dl = a.copy()
    for i in range(n):
        for j in range(n-1, i, -1):
            if chk_before_tranp_bigger(dl[j], dl[j-1]):
                dl[j], dl[j-1] = dl[j-1], dl[j]
    return dl, is_stable(a,  dl)


def selected_sort(n: int, a: list) -> (list, str):
    dl = a.copy()
    for i in range(n):
        mini = i
        for j in range(i, n):
            if chk_before_tranp_bigger(dl[j], dl[mini]):
                mini = j
        if mini != i:
            dl[i], dl[mini] = dl[mini], dl[i]

    return dl, is_stable(a, dl)


n = int(input())
a = input().split()

sort_, judge = bubble_sort(n, a)
print(*sort_)
print(judge)

sort_, judge = selected_sort(n, a)
print(*sort_)
print(judge)
```
認定Sales Cloudコンサルタントを受けてみた

#始めに
会社よりSalesforceのパートナー企業に認定されるためにに認定Sales Cloudコンサルタントと認定Platformデベロッパーの資格を取る事になりました。
私自身は2017年頃から分社前の会社でSalesforceでの開発に触れていたため、ある程度Salesforceの開発経験があります。
#前提
Salesforceの認定Sales Cloudコンサルタントを受験するためには認定アドミニストレーターの資格の取得が条件となっています。
私は2017年に受験し認定アドミニストレーターの資格の方を取得しておりました。

#学習方法
今回は以下の学習方法を取りました。

1. 認定アドミニストレーターの復習
2. 認定アドミニストレーターのウェビナーの受講
1. 認定Sales Cloudコンサルタントの学習
2. ポイントスタディなどの資料を読む
2. Web上の想定問題を解く

##認定アドミニストレータの復習
認定アドミニストレーターの復習ではSalesforceの無料で学習が行えるTrailheadで、講座などをまとめた以下のTrailmixを使用して復習を行いました。
[【パートナー向け】認定アドミニストレーター資格 対策](https://trailhead.salesforce.com/users/jpartners/trailmixes/prepare-for-your-salesforce-administrator-credential-partner)

##認定アドミニストレーターのウェビナーの受講
Salesforceでは定期的に無料の資格試験対策のウェビナーを実施しています。

https://www.salesforce.com/jp/campaign/trailhead-academy/certification-days/

ウェビナーを受講し、ユーザー管理についてはTrailheadよりももっと細かい説明があり、認定Sales Cloudでもユーザーの使用率について問われる問題が出ることがあるため、受講し良かったと感じています。
また期間限定かもしれませんが、私が受けた際は2万円の試験の受験料が半額になるクーポンを終了時に配布していたため、試験を安く受けることもできました。

##認定Sales Cloudコンサルタントの学習
認定Sales Cloudコンサルタントの学習では以下の二つのTrailmixを行いました。
[Prepare for Your Salesforce Sales Cloud Consultant Credential](https://trailhead.salesforce.com/users/strailhead/trailmixes/prepare-for-your-salesforce-sales-cloud-consultant-credential)
[【Salesforce公式】認定 Sales Cloud コンサルタント 対策](https://trailhead.salesforce.com/users/welcome4/trailmixes/certified-sales-cloud-consultant-ja)

##ポイントスタディなどの資料を読む
Saelsforceでは有料で資格対策のコースを受講することができます。
今回私は受講しませんでしたが、2017年にパートナー企業になる際に同僚が認定Sales Cloudコンサルタントの講座を受講していました。
その時の資料が残っていたためそちらにも目を通しました。
試験対策向けの情報がたくさん含まれているため、金銭的に余裕があればぜひ受けることをお勧めします。
Salesforceは更新が年3回あるため機能がどんどん変わります。
そのため3年前のものだと若干今の機能と違う部分もありましたが、十分参考になりました。
またポイントスタディには想定問題もついてくるため、そちらを解いて理解度を確認することも大切です。

##Web上の想定問題を解く
今回の受験にあたり以下のサイトの想定問題に取り組みました。
[Salesforceの一番星](https://keneloper.com/salesforce-certified-sales-cloud-consultant-exam-questions/)
[セーブポイントが見つからない](https://savepo.com/salesforce_sales_cloud_exam_top)
特に「セーブポイントが見つからない」の方は試験問題が300問あり、実際に出題されたであろう問題も含まれています。
また試験対策の記事や試験を受けての所感も書かれているので、ぜひ参考にしてみてください。

#試験の所感
##1回目(不合格)
テリトリーや取引先階層の細かい仕様など、Trailmixで学んだことの細かい仕様などについて聞かれます。
そのためTrailmixを消化すると同時に、リソースの部分のヘルプを読み、わからない部分はさらにヘルプで検索するなどして、重箱のすみを突くように学習できると良いと思います。

また、試験問題は公開されていません。
そのため模擬問題や想定問題は実際の試験の内容より簡単な問題が多いと感じます。
知識の確認にはちょうど良いですが、模擬問題を完璧に解けるからと言って実際の試験に合格できるわけではないことに注意しましょう。

最後にSalesforce公式の受験ガイドは必ず読み、試験範囲について必ず確認しわからない部分は確実に学習しましょう。
![1回目SalesCloud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331410/6b48270d-cc6c-2ef1-dfcb-cbd0a376fc39.png)


##2回目(合格)
1回目の経験から各機能の細かいところを聞かれると感じました。そのためTrailheadを再度読み、付随するヘルプへも目を通しました。その過程でわからない単語などが出てきた際はその名前を調べました。

試験を受けての感想は、前回に比べて答えばわかる問題が増えたと感じたことと、消去法で答えが導き出せるようになっていました。しかし、実際の画面でどう言う名称で表示されているボタンかを問う問題もあり、機能を実際に触っていないとわからない問題も多かったと感じています。
![2回目SalesCloud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331410/402ce724-93f8-1759-f9d5-eb364b6ef2cf.png)
トップページ制作の時、画像の扱いで詰まったこと(超初心者)

タイトルの通り。
OSはmacで、rubyとrailsを勉強しているので.html.erbと.scssで書きました。

画像ファイルを読み込もうと思った時

```erb:home.html.erb
<%= image_tag “Hogehogeホゲホゲ.jpg” %>
```
↑と記述したら、ブラウザで表示されない！
sprockets::rails::helper::assetnotfound エラー

＜解決した方法＞

```erb:home.html.erb
<%= image_tag “Hogehogehogehoge.jpg” %>
```

にすることで表示された。つまり名前をすべてアルファベットにしたら解決した。

背景に画像を使いたいとき

```scss:custom.scss
background-image: url(../images/hogehoge.jpg);
```

↑だと表示されず、

＜解決した方法＞

```scss:custom.scss
background-image: url(hogehoge.jpg);
```

にすると表示されるようになった。

どちらも原因がよく分かりませんがメモ程度に。。

はじめて自分の手で作り始めましたが、教材やるより難しいですね。。でもその分楽しかったです。
自分のペースで頑張ります。
IBMCloud CIS WAF注意点

##WAFルールの追加について
IBM Cloud Internet Services(CIS)ではCloudflare社のCDNを利用している。
CISではWAFルールを追加する場合、事前アナウンスする事もあれば、<font color="red">アナウンスなしでやることもある。</font>

計画された変更はこちらで確認できる
また、過去の変更履歴も確認可能
[Change log for managed rulesets](https://developers.cloudflare.com/waf/change-log)


##なぜアナウンスなしで追加するのか？
セキュリティの脆弱情報がインターネットに公開される前に、先手を打って防ぐ必要がある。
このため、ルールの追加をアナウンスする前に脆弱性を調査し、対処する為、アナウンスなしで実施する。
ルール追加により、思わぬ影響を受ける場合もあるが、<font color="red">適切にセキュリティの脆弱性に対処する為実施される。</font>
その後、関連するベンダーやセキュリティ研究者によって脆弱性が開示されると、Webページも更新される。

全ての変更が[ここ](https://developers.cloudflare.com/waf/change-log)に記載されているわけではないので、必要に応じてサポートに確認しましょう。
Windows10 でRubyOnRails 4でindex.html.erb作成中の問題、解決方法

# Windows10 でRubyOnRails 4でindex.html.erb作成中の問題、解決方法

bin/rails ...コマンドでviews内にindex.html.erbファイルを作成する際に、
「このファイルを開く方法を選んでください」というウィンドウが開かれ、index.html.erbファイルが作成されない時の解決方法を共有します。

##環境
- システムの種類：Windows10 Home　64ビットオペレーティングシステム、x64ベースプロセッサ
- Rails version 4系

##現象
1.bin/rails generate controller welcome index コマンドを実施する。

2.「このファイルを開く方法を選んでください」というウィンドウが開かれる。
![スクリーンショット 2020-10-30 130959.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/5c8e45eb-aae4-0264-27ae-9f494c7340a7.png)


##解決方法
1.bin/rails ... の代わりに、rails ... コマンドを実施する。
例：rails generate controller welcome index
＊ちなみに rails server コマンドでlocalhost:3000 も起動される。

ーーー

index.html.erbファイルが作成されていることが確認できる。
![スクリーンショット 2020-10-30 140026.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/26626bb9-4c50-5828-eb30-37fd6acb8ab2.png)

OK
[Python][Windows]画面のスクリーンショットを画像として保存する

###初めに
拡張画面のスクリーンショットを保存する必要が出てきたためシンプルに書いてみました。

###方針
１．スクショと言えばPrtScキー押し（PyAutoGUI)
２．クリップボードの内容を保存（PIL）


```prtsc.py
import pyautogui
from PIL import ImageGrab

# 保存したい場所とファイル名を指定
fo = r"C:\Users\hoge\Pictures\Screenshots\desktop.png"

pyautogui.press('printscreen')

im = ImageGrab.grabclipboard()
im.save(fo)

```

###補足

使用モジュールPyAutoGUIとPILのインストールはググってください。
覚えてないです・・・
ネガポジ分析1　テキスト分析の応用

[Aidemy](https://aidemy.net/)　2020/10/30
#はじめに
　こんにちは、んがょぺです！バリバリの文系ですが、AIの可能性に興味を持ったのがきっかけで、AI特化型スクール「Aidemy」に通い、勉強しています。ここで得られた知識を皆さんと共有したいと思い、Qiitaでまとめています。以前のまとめ記事も多くの方に読んでいただけてとても嬉しいです。ありがとうございます！
　今回は、ネガポジ分析の1つ目の投稿になります。どうぞよろしくお願いします。

＊本記事は「Aidemy」での学習内容を「自分の言葉で」まとめたものになります。表現の間違いや勘違いを含む可能性があります。ご了承ください。

今回学ぶこと
・ネガポジ分析とは
・極性辞書を使ったネガポジ分析の実行

#ネガポジ分析とは
・__ネガポジ分析__とは、人の発言や発想が__ポジティブかネガティブかを判断するもの__である。実際には、文章などに含まれる評価、感情に関する表現を抽出して、文章中の感情を解析するという手法が取られる。

##極性辞書について
・「ネガ/ポジ」のことを__「極性」__とよび、__極性辞書__は__単語ごとの極性をまとめたもの__である。単語には__「-1~+1」__までの値が与えられており、値が大きいほどポジティブ、値が小さいほどネガティブな意味であることを表す。

##形態素解析
・（復習）__形態素解析__とは、__文章を単語という最小単位に分割すること__である。単語にすることで、__極性辞書を参照することが可能になる__。__MeCab__などを使って形態素解析を行うことができる。また、以下も復習の内容が多いが、全て今回行っていくものである。

・MeCabによる形態素解析は__MeCab.Tagger('')__でインスタンスを作成したあと、__mecab.parse(ファイル)__で行える。__一行につき一単語__なので、単語ずつに区切るために、__split('\n')__で改行ごとに「lines」に格納していく。また、後ろ二行は__'EOS（EndOfSplit?）'__という記述と__空行__なので__削除する__。また、作成したlinesについて、単語ごとに「__タブ__と__,__」で分割し、__{'BaseForm':word}__となるようにそれぞれ「diclist」に格納する。

・コード![スクリーンショット 2020-10-26 22.01.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/3ad8f2b5-00a1-f482-5257-2dc44407ead5.png)

##単語を極性辞書で参照し、PN値を取得
・前項で作成した形態素解析の関数「get_diclist()」から返される単語のリスト（wordlist）の__単語を極性辞書でさがし__、存在すればその極性値を抽出するという役割を持つ関数__「add_pnvalue()」__を作成する。
・関数作成にあたり、まずは__極性辞書（pn_df）を「単語がキー、PN値が値」である辞書に変換__する。pn_dfの['Word']と['PN']をそれぞれリスト化し、「pn_dict」として一つの辞書にまとめる。
・add_pnvalue()については、渡された単語リストの各要素の中の'BaseForm'がキーの各単語について、__pn_dictにその単語があれば__、単語リストにキー'PN'を追加して__その単語のPN値を値とし__、空のリスト「diclist_new」に格納して返すように作成する。ちなみに、pn_dictにある単語のPN値が知りたい時は「pn_dict[word]」とすれば良い。

・コード
![スクリーンショット 2020-10-26 23.38.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/226983db-2843-0a79-ff89-7823027345f0.png)

#まとめ
・__ネガポジ分析__とは、__人の発言や発想がポジティブかネガティブかを判断するもの__である。ネガポジ分析は__極性辞書を使って行う__。
・極性辞書でネガポジ分析を行うためには、極性辞書を参照できるように、文章を__形態素解析する必要がある__。

今回は以上です。最後まで読んでいただき、ありがとうございました。
JavaScript Promiseオブジェクト

初学者なので学習した内容をまとめていく。
今回は、promiseオブジェクトについて

##promiseオブジェクト
JavaScriptはプログラムのコードを同期的に上から処理していくのではなく非同期で（１つの部分で処理に時間がかかったら次の処理をする）プログラムが走る。そのため、同期的に処理したいならば、コールバック関数を使用していた。
しかし、処理が多くなる場合、このコールバック関数はネストが深くなる、コールバック地獄になってしまう。

そこで！PromiseオブジェクトがES2015にて標準化された。

```javascript
//　Promiseコンストラクター
 new Promise((resolve,reject) => {statement})
```
resolve:　処理の成功を通知するための関数
reject:　処理の失敗を通知するための関数
statement:　処理本体

```javascript
// thenメソッド
 promise.thne(success, failure)
```
promise: Promiseオブジェクト
success:　成功コールバック関数
failure:　失敗コールバック関数

###非同期処理の連結
```javascript
function asyncProcess(value){
  return new Promise((resolve,reject) => {
    setTimeout(() => {
      if(value){
        resolve(`入力値：　${value}`);
      } else {
        reject('入力はからです。');
    },500);
  });
}

asyncProcess('A')
  .then(
    response => {
      console.log(response);
      return asyncProcess('B');
    }
).
then(
    response => {
      console.log(response);
    },
    error => {
      console.log(error);
    }
);
```

Aの処理が終わり、エラーがなければBの処理へうつる。もし途中でエラーがあると、error処理にうつり、そこで終わる。
これであたかも、thenによって処理が１本の道のようになる。

###全ての非同期処理が成功した場合にコールバックする allメソッド
Promise.allメソッドを使うと、その中に書かれた非同期処理が全て成功した場合に処理を実行する。

```javascript
 Promise.all(promises)
```
promises：　監視するPromisep部ジェクト群（配列）

```javascript
 Promise.all([
  asyncProcess('A'),
  asyncProcess('B')
]).then(
  response => {
    console.log('成功しました');
  },
  error => {
    console.log('失敗しました');
  }
);
```

###非同期処理のある１つが完了したところでコールバック　raceメソッド
並行して処理していた内、１つが最初に完了したところで成功コールバックを呼び出す。
書き方はPromise.allと同じ。

そして、進化版もあった！
[async/await 入門（JavaScript）](https://qiita.com/soarflat/items/1a9613e023200bbebcb3)

@soarflat　様の記事がわかりやすかったのでここに。
Rで混合ガウスモデル.1

# 記事の目的
1次元の混合ガウスモデルのパラメータ推定をEMアルゴリズムで行います。
個人的にはPRMLの解説が分かりやすかったです。
参考1：[しくみがわかるベイズ統計と機械学習](https://www.amazon.co.jp/%E3%81%97%E3%81%8F%E3%81%BF%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B%E3%83%99%E3%82%A4%E3%82%BA%E7%B5%B1%E8%A8%88%E3%81%A8%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92-%E6%89%8B%E5%A1%9A-%E5%A4%AA%E9%83%8E/dp/425412239X/ref=asc_df_425412239X/?tag=jpgo-22&linkCode=df0&hvadid=342653193298&hvpos=&hvnetw=g&hvrand=7722199587683300720&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009329&hvtargid=pla-837747653679&psc=1&th=1&psc=1)
参考2 ：[PRML下] (https://www.amazon.co.jp/パターン認識と機械学習-下-ベイズ理論による統計的予測-C-M-ビショップ/dp/4621061240/ref=pd_bxgy_img_2/358-0979251-6826126?_encoding=UTF8&pd_rd_i=4621061240&pd_rd_r=2d3fdac6-bc15-44fc-bbb7-2f912b059365&pd_rd_w=LVErD&pd_rd_wg=QOmz6&pf_rd_p=e64b0a81-ca1b-4802-bd2c-a4b65bccc76e&pf_rd_r=EP4VHHZ9R2230G5C5R8H&psc=1&refRID=EP4VHHZ9R2230G5C5R8H)

# 目次

[1. モデルの説明](#1-モデルの説明)
[2. 使用データ](#2-使用データ)
[3. EMアルゴリズム実装](#3-emアルゴリズム実装)
[4. 結果](#4-結果)


#1. モデルの説明
![IMG_0168.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/e2a0a54b-d7a1-d7eb-169e-eacf0e849340.jpeg)


#2. 使用データ
10歳の100人分の身長のデータと、20歳の200人分の身長のデータを誤って同時に計測してしまった。

```R:
library(dplyr)
set.seed(100)
age10 <- rnorm(100, 140, 5)
age20 <- rnorm(200, 170, 7)
X <- append(age10, age20) 
N <- length(X)
X %>% hist()
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/01c3217c-4751-5cfe-5eeb-9a637c6dbc87.png)



#3. EMアルゴリズム実装
```R:
# (1)
K <- 2
pi <- rep(1/K, K)
u <- rnorm(K, mean(X), sd=10)
sigma <- rep(sd(age)/2, K)

# EMアルゴリズムの計算途中で使用する変数
max_iter <-30
pi.N <- matrix(NA, N, K)
r <- matrix(NA, N, K)
R <- {}

for(s in 1:max_iter){
  # (2) E-step
  for(i in 1:N){
    for(k in 1:K){
      pi.N[i, k] <- pi[k]*dnorm(X[i], u[k], sqrt(sigma[k]))
    }
    r[i, ] <- pi.N[i, ]/sum(pi.N[i,])
  }
  # (3) M-step
  R <- apply(r, 2, sum)
  pi <- R/sum(R)
  for(k in 1:K){
    u[k] <- sum(r[,k]*X)/R[k]
    sigma[k] <- sum(r[, k]*(X-u[k])^2)/R[k]
  }
}
```

#4. 結果
```R:
z <- apply(r, 1, which.max)
par(mfrow=c(1,1))
hist(X[z==1], xlim = c(120,200), col = "red")
hist(X[z==2], col = "blue", add=T)
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/a363aa75-ca73-1619-961e-b8d22aab2b33.png)
【GoogleMapsAPI】Mapが表示されず空白になる問題【Rails】

個人開発アプリを製作しており、備忘録かつ同じようなエラーが発生している方の参考になればと思い、記します。
#エラー内容
Railsで個人開発アプリを制作している。
店舗情報を投稿すると、住所(address)から緯度経度(latitude,longitude)を取得し、マップ表示する機能。

下記の写真のように、本来表示されるはずの位置に地図(Google Maps)が表示されず、空欄となる。数日前までは正常に表示できていた。

そして、数日前までに投稿した店舗情報については地図は表示されている。つまり、新規投稿すると住所情報から緯度経度を正しく取得できず、地図を表示することができないと言うことになる。
![スクリーンショット 2020-10-30 9.50.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620533/ce98dc0b-db68-5540-5349-d306413409d9.png)

#エラーに対するTRY
Google Cloud Platformを確認すると、Geocodeing APIで100%エラーになっていることが確認できた。
![スクリーンショット 2020-10-30 10.07.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620533/fcbbce3a-aab7-e84c-a93b-6ed9ff09625c.png)

Chromeによる検証ツール等を利用して調べるも、原因が不明。
上記Geocodingのエラーから、住所情報(address)から正しく緯度経度を取得できないと推測できる。

エラーを調べていくと、APIキーの設定ミスやJavaScriptの記載ミスなどが出てくるが、数日前までは普通に見ることができたし、前述の通り、過去の投稿についてはどれも地図が正しく表示されている。つまり、JavaScriptのタイポなどでは無いはず。

地図を表示させるためにどれも正しく設定しているはずで、数日前までは普通に表示されていたので、他に何か原因があると考えたが、数時間何を行っても直らず。GitHubで関係のありそうなファイルの過去と比べても何かを修正したところはない。

#解決法
StackOverFlow等、海外サイトを調べていくも決定打が見つからず。
途方に暮れていたところ、**自分は環境構築でDockerを使用していることから、一度Dockerを落とし、再度ビルドすることにした。**

```ruby:local
$ docker-compose down
$ docker-compose build
$ docker-compose up -d
$ docker-compose run web rails db:create
$ docker-compose run web rails db:migrate
```
もう一度、テスト環境でローカルホストにアクセスすると、無事地図が表示されたことを確認。
住所を変更しても、ちゃんと変更した先の住所情報から緯度経度を取得して地図を表示していることを確認した。
正常動作を確認したため、本番環境にも反映させた(CircleCI導入済みのためgit push)。
無事本番でも正常動作を確認し、解決！

#学び
Docker再起動が時に有効打となることを学んだ。AWSデプロイ時もEC2の再起動でエラーが一気に解決したことがあるため、手を尽くす際には一度環境を再起動した方が良いと再確認できた。RailsでDockerを使用しGoogleMapsAPIを導入している方で、同じように空白表示される場合は、是非一度Dockerを再起動させてみてください。
[gitトラブルシューティング]誤ってresetとpushをしてしまったときの対処法

# はじめに
みなさん、こんにちは。[profsend](https://profsend.ga)開発者のぐみぃです。
みなさんはこんな経験がありますか？
 **「作業中に誤ってresetして、更にpushもしてしまった！もう大ピンチ...」**
僕も一度そうなったことがあります。
でも、この方法をすれば、簡単に戻せます。

# reflogで作業履歴を確認する

    git reflog
このコマンドは、作業履歴を確認するコマンドで、

    git log

との違いは、
**resetなどのコマンドの履歴も含まれる**
ということです。
戻し方は、

    git reset --hard HEAD@{数字}
数字の確認は下記の通りになります。

    $ git reflog
    作業ID HEAD@{数字}: 作業内容
                  ↑ここ

ただ、reflogでは表示できる数に限りがあるので、
**間違えたらすぐに対処しましょう！**

# もしsubmoduleがあった場合
gitには、別のリポジトリを取り込める、
**submodule**という機能があります。
その場合は更に簡単にできます。

まず、submoduleがあるリポジトリのgithubページへアクセスしてください。
そして、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381881/b7174235-e49b-918d-732b-7c5c2af8157e.png)
コミット名の部分をクリックし、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381881/468718f3-16d8-0b66-04ca-96d17cd7e274.png)
commitの右の英数字がコミットIDです。それを

    git merge コミットID
    もしくは、
    git cherry-pick コミットID
でリポジトリに取り込めば、リポジトリを復旧できます。
あとはpushすれば完全に復旧できます！

# 参考
https://qiita.com/yaotti/items/e37c707938847aee671b
文系未経験が１ヶ月Ruby Silver合格出来たまとめ

<h2>はじめに</h2>
入社した会社に資格の祝金制度があったため、まずはRuby Silverを取得しようと勉強開始。

勉強期間約１ヶ月弱ほどで無事合格出来たので、これから受ける人の助けになればと思いまとめます。（Goldもこれから勉強予定）

ちなみに８２点合格でした。

<h2>勉強開始時の状態</h2>
・文系未経験
・Rubyでの開発経験はもちろんなし
・自学習でProgateとRailsチュートリアルを３ヶ月ほどで一通り

Rails チュートリアル に出てくるコードもRubyのコードなのか、Rails特有のコードなのか区別がつかない状況でした。

<h2>勉強期間</h2>
約３週間

入社研修を受けながらの勉強だったので、
・平日　約２時間
・週末　２日合わせて約５時間　
トータル約４０時間程

という感じで、もちろん疲れて全く勉強をしない日も数日はありました。

<h2>勉強方法と使用教材</h2>
簡単に私が行った学習方法を紹介します。

<h3>まずは一通り教本をさらっと読む</h3>
<a target="_blank" href="https://www.amazon.co.jp/gp/product/4774191949/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4774191949&linkCode=as2&tag=sueno101909-22&linkId=c0d13aab67ba5c63f26d870d99b31a83">[改訂2版]Ruby技術者認定試験合格教本(Silver/Gold対応) Ruby公式資格教科書</a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=sueno101909-22&l=am2&o=9&a=4774191949" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />

まずは公式合格教本を１周読みます。

それぞれの章の初めにSilverの範囲の節が記してあるので、まずは範囲内だけを読みます。

この教本は基礎知識をある程度理解しているのを前提で書かれているので、基本文法（ifとかforとか）もまだ知らないという方はProgateをやってから戻ってくると良いと思います。

基礎が理解できている方は、細かいとこはすっ飛ばしてさらっと一読してください。

<h2>問題集を少し解いてみる</h2>
教本でRubyの大まかな知識を得たら、ネットの問題を少し解いてみると良いでしょう。

ここではまだ教本内の模擬試験を受けるのではなく、以下のサイトで無料で問題を受けれるので、こちらをやりましょう。

Rex
https://rex.libertyfish.co.jp

最初はおそらく全く解けないと思いますが（私も２０点とかでした）、解説を読んで解き直すのを繰り返してください。

同じ問題が多く出てくるので徐々に問題の傾向が見えてくると思います。

<h2>合格者のブログを読む</h2>

Rexが６,７割程度取れるようになったら、Qiitaなどで合格者のブログを読み直してみましょう。

この時点で、よく出る分野はArrayクラスだとか同じ動作をするメソッド問題だとかの意味が理解でき始めて、知識を整理しやすくなってきます。

以下は私が参考にしたブログです。
試験内容の細かい点については以下を参考ください。

Ruby Silverに合格したので、勉強方法をまとめてみた(2019年2月版）
https://qiita.com/jonakp/items/7f7550eeea78973a0a7f

実務経験なしからRuby Silver合格したので、勉強方法をまとめてみた
https://qiita.com/pisa-kun/items/9a85be30d1aaa556c943


<h2>あとは問題を解きまくる</h2>

ここからは問題を解いて、解説を読んでまた解くのを繰り返しましょう。

上のRexに加えて以下のサイトも利用しました。

ミニツク
http://www.minituku.net/courses/1049510743/contents/775230600.html

模擬問題集
https://gist.github.com/sean2121/945035ef2341f0c39bf40762cd8531e0


試験１週間前の時点で全ての問題集で９０点以上を安定して取れる様にしておきます。

私個人的には上の模擬問題集もしくは教本内の模擬問題のうち１つは解かずに置いておき、試験前最後の週に力試しで解いてみるのが良いと思います。

<h2>気をつけること</h2>
ここまでやっていれば万全！　というわけにもいかず、本番の試験にはどの問題集にも出てこなかった問題が３,４割程出てきます、

しかも重箱の隅を突く様な問題が多く私は感じました（私の勉強不足。。。）


そのため、わからない問題や疑問点は実際にコードを書いてみるのが大切です。

メソッドの返り値は何かとか、繰り返し判定するか最初の値だけ返すのかとか。
<br>


試験前の最終復習としてこちらのブログも利用させて頂きました。

Ruby Silver試験前に見直すと幸せになれるメモ
http://tamata78.hatenablog.com/entry/2015/08/07/200454
AWSのVPC Lambdaからエンドポイント経由でSQSにアクセスする際の注意

# 結論
AWSでLambdaをVPCに配置して、エンドポイント経由でboto3 SQSを使用する際にはendpoint_urlオプションが必要。

```python
import boto3
sqs = boto3.client("sqs", endpoint_url="https://sqs.ap-northeast-1.amazonaws.com")
sqs.send_message(...)
```

このオプションを付けないと、接続できなくてタイムアウトします。

# 詳細
AWSでLambaをVPCに配置してプライベート接続でSQSを使用する際にめちゃはまったので注意点をメモします。
詳細は以下のサイトが詳しいのでそちらを参照して下さい。私が試した時はLambda上でboto3を使用した際にのみ現象が発生しました。

私の発生条件ではLambdaのboto3はバージョン1.14.48でした。また、EC2を立てて試したバージョンは1.16.8でしたが、こちらでも同様の現象が発生しました。

1. AWS CLI等でSQS VPC Endpointを利用するときの注意点 -- https://blog.serverworks.co.jp/tech/2019/03/18/sqsvpcendpoint/
2. Unable Connect do SQS if using a VPC -- https://github.com/boto/boto3/issues/1900

1.の記事によると、AWS CLI(今回の現象をみるにboto3も含む)では**SQSに接続する際にQueueUrlを指定していても、レガシーエンドポイントに接続しようとする**というのが問題になっているようです。
VPCでSQSのエンドポイントを作成すると、sqs.ap-northeast-1.amazonaws.com (現行エンドポイント)はプライベートIPが割り当てられるのですが、ap-northeast-1.queue.amazonaws.com (レガシーエンドポイント)はパブリックIPのままとなります。
その状態で、boto3でSQSを使用しようとすると、接続する際にレガシーエンドポイントを使用しようとして、接続できずにタイムアウト、というのが原因のようです。

2.のGitHubの中ではSessionを使った解決方法が示されていますが、`boto3.client()`を実行する際に上記のように`endpoint_url`オプションに現行エンドポイントを指定すれば問題は解決しました。
参考までにGitHubの記事中のSessionによる解決コードは以下です。

```python
import boto3
session = boto3.Session()
sqs_client = session.client(
    service_name='sqs',
    endpoint_url='https://sqs.ap-northeast-1.amazonaws.com',
)
sqs_client.send_message(...)
```

…2時間ぐらいはまりました。
【Java】Spring DI ②

#Javaにおける注入って何？
*  インターフェース型の変数に、インスタンスを入れること
* newしたインスタンスを、そのままEngineインターフェース型の変数に入れる

```java
//Mainクラスでエンジンの生成
Engine hondaEngine1 = new HondaEngine();
Engine mitsubishiEngine1 = new MitsubishiEngine();
//車の生成
Car car1 = new Car(hondaEngine1);
Car car2 = new Car( MitsubishiEngine1);
```

#クラスを変更する
* 新しくこれまでのエンジンクラスを継承した、Ver2のエンジンを作成した場合
* Mainクラスの生成部分でで再度Ver２のエンジンに変更する必要がある。。（たくさんあると面倒）
* →次の章のFactoryクラスを使おう！

```java
//HondaEngine継承したHondaEngineVer2作成
public class HondaEngineVer2 extends HondaEngine{

//コンストラクタ
public　HondaEngineVer2(){
    super();
    }
    //エンジン起動
    @Override
    public void boot(){
        System.out.println("ホンダエンジン起動（Ver2）");
    }
    //エンジン停止
    @Override
    public void stop(){
        System.out.println("ホンダエンジン停止（Ver2）");
    }
}
```

```java
//Mainクラスでエンジンの生成
Engine hondaEngine1 = new HondaEngineVer2();
//車の生成
Car car1 = new Car(hondaEngine1);
```

#Factoryクラス
* インスタンスを生成するクラスのこと🏭
* newするクラスが変わった場合、メソッドの中身だけを変えるだけで済む
    * 以下の例ではFactoryクラスでVer2に変更するのみ！
* →**変更に強いアプリケーション**になる！！


```java
//Factoryクラス
//メソッドをstaticにすることで、Factoyクラスを生成しなくてもメソッドを呼び出せる
public class EngineFactory{
    //ホンダエンジンクラスを生成して返す
    public static Engine createHondaEngine(){
    //新しいエンジンに変更
        return new HondaEngineVer2();
    }
    //三菱エンジンクラスを生成して返す
    public static Engine createMutsubishiEngine(){
        return new MutsubishiEngine();
    }
}
```

```java
//mainクラス
public class Main{ 
    public static void main(String[]args){
    //エンジンの生成 
    Engine hondaEngine1 = EngineFactory.createHondaEngine();
    Engine hondaEngine2 = EngineFactory.createHondaEngine();
    Engine mitsubishiEngine1 = EngineFactory.createMutsubishiEngine();
    //車の生成
    Car car1 = new Car(hondaEngine1);
    Car car2 = new Car(hondaEngine2);
    Car car3 = new Car(mutsubishiEngine1);
    }
}
```
AWS(Singapor) <=> Tencent(Beijing)でPingを1,000 Packetずつ打ち合った結果

# はじめに
しばらく前(2020/2頃?)ですが、中国向けのWebサイトを構築する必要があったため、GFW(Great Fire Wall)を回避するためにTencent Cloudを用いて北京リージョンにWebサーバを構築しました。
その際、GFWを超えるTrafficの挙動を調査するために、AWSのサーバとの間でPingを1000 Packets打ち合ってみた結果です。
# 結果
## Tencent(北京) => AWS(Singapore)

```
# ping -c 1000 -q 52.***.***.***
PING 52.***.***.*** (52.***.***.***) 56(84) bytes of data.

--- 52.***.***.*** ping statistics ---
1000 packets transmitted, 760 received, 24% packet loss, time 999471ms
rtt min/avg/max/mdev = 90.962/91.194/92.538/0.121 ms
```
## AWS(Singapore) => Tencent(北京)

```
# ping -c 1000 -q 49.***.***.***
PING 49.***.***.*** (49.***.***.***) 56(84) bytes of data.

--- 49.***.***.*** ping statistics ---
1000 packets transmitted, 772 received, 22% packet loss, time 999321ms
rtt min/avg/max/mdev = 90.970/91.170/92.365/0.245 ms
```
#まとめ
双方向とも概ね20-25%ものLoss.
どうにかならないものか?
カーネルモジュールってなに？

## 勉強前のイメージ

カーネルのデフォルトだけでは動かんから、
モジュールを読み込んで改造していくイメージ。

## 調査

### カーネルモジュールとは

カーネルの機能を拡張するためのバイナリファイルです。
例としては、ディスク・ネットワークカード等をLinuxカーネルで使用可能にするためのデバイスドライバなどがあります。
デバイスドライバは各ハードウェアベンダーから提供されることが多いです。

初期のUNIX系OSでは新しいハードウェアを使うにはカーネルの再構築が必要でしたが、
現在のLinuxカーネルは、必要ありません。
起動時に常駐カーネルがメモリにロードされ、必要に応じてロード・アンロードが出来るようになっています。

### サーバ内のモジュールを確認

`lsmod` コマンドを使用します

```
# lsmod
Module                  Size  Used by
vboxsf                 81052  1 
vboxvideo              35867  0 
ip6t_rpfilter          12595  1 
ip6t_REJECT            12625  2 
nf_reject_ipv6         13717  1 ip6t_REJECT
ipt_REJECT             12541  2 
nf_reject_ipv4         13373  1 ipt_REJECT
xt_conntrack           12760  11 
ebtable_nat            12807  1 
```

- Module : ロードされているカーネルモジュール
- Size : カーネルモジュールのサイズ
- Used by : 使用カウント数・参照しているモジュールの一覧

### モジュールのロード

- 依存関係を考慮する場合
	- `modprobe` コマンド
- 依存関係は考慮しない場合
	- `insmod` コマンド

上記コマンドの違いは、
`modprobe` コマンドでは、依存関係があるモジュールがあれば事前にロードを行います。
`insmod` コマンドでは、指定されたモジュールのみをロードします。

### モジュールのアンロード

`rmmod` コマンドを使用
`-r` オプションを付けることによって、依存するモジュールも削除します。
削除する際にモジュールが使用されている場合はエラーになります。

### モジュールの依存関係リストを更新

基本的には実行しないのですが、モジュールファイルの追加や削除入れ替えなどで依存関係がおかしくなっている可能性がある場合に使用されることが多いです。
`depmod` コマンドでモジュールの依存関係リストを更新することが出来ます。


## 勉強後のイメージ

カーネル(心臓部のイメージ)の増築みたいな感じだから、再起動したりせんとあかんのかなって思ってたけど、コマンドでいけるのね。
昔はプログラムをコンパイルとか必要だったみたい。
なんか簡単そうな感じ。

## 参考

- [Linux技術トレーニング　基本管理コース II](https://users.miraclelinux.com/technet/document/linux/training/2_1_1.html)
- [【 depmod 】コマンド――カーネルモジュールの依存関係リストを更新する](https://www.atmarkit.co.jp/ait/articles/1812/28/news028.html)
- [第25章 カーネルモジュールでの作業](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/deployment_guide/ch-working_with_kernel_modules)
気象庁の震源データを3Dで展開

注意：Safariは仕様変更があったため現在閲覧できません。
気象庁は観測した震源情報を公開しており、この震源データの3D表示を試みた。

* [気象庁 | 震源データ](https://www.data.jma.go.jp/svd/eqev/data/bulletin/hypo.html)

#はじめに

気象庁はウェブページ上で1919年以降の震源データを公開している。震源データはASCIIで1行1震源、固有フォーマットで表現され、1983年以降はほぼ1年分1ファイルで提供される。東北地方太平洋沖地震が発生した2011年のファイルにはは約30万件のデータが含まれ、その容量は約30MBである（元データの総容量は約370MB）。予めファイル形式「点群PNG」でデータを整理した上で、Three.jsを用いて震源位置を3Dでプロットすることを試みた。

#開発したアプリケーション

![スクリーンショット 2020-10-30 12.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731876/91953860-799a-be1e-48e5-652544a60092.png)

* [気象庁震源データ3Dプロット](https://kitao.net/works/earthquake/)

3Dモデルはマウス操作で自由に視点位置を変更することができる。赤枠内の操作ボタンにより表示に関する各種設定を変更することが出来る。

##機能

* 3Dモデルの視点を操作：Three.js標準
* 表示するマグニチュードの大きさの範囲を指定
* マグニチュードの大きさで色分け：小（緑）←→（赤）大
* 標高（深度）強調
* 地図の不透明度変更
* 任意の日付の震源を表示
* 日付テキストボックス左右のアイコンクリックで日付移動
* 日付指定のクリア
* 大きい地震の日付のプルダウン選択
* 日付を自動ですすめる機能（2020.10.31）

#注意

自分が所持するスマホ、タブレットでは動作しなかった。

#データ

* 震源データは前述の通り[気象庁](https://www.data.jma.go.jp/svd/eqev/data/bulletin/hypo.html)が公開しているデータを使用
* 地形は産業技術総合研究所が公開する[シームレス標高タイル](https://gbank.gsj.jp/seamless/elev/tile.html)のうち、日本周辺250mメッシュとGEBCO_2020 Gridを重ねて使用
* 地形に貼り付けた地図は国土地理院の[地理院タイル標準地図](https://maps.gsi.go.jp/development/ichiran.html)

震源データは点群PNGの形式で事前に作成する。点群PNGに含めた値は各震源のピクセル座標、深度、マグニチュード、発生日である。全てASCIIのファイルから適切に変換し、ピクセルのRGB値として格納する。
古いデータは、観測機器の精度の関係で収集されたデータ量が少ない。今回は1980年から2018年のデータを使用した。その間の地震データの件数は3,688,834。

#プログラム詳細

プログラムは3D描画ライブラリであるThree.jsを用いて開発している。Three.jsには独自のシェーダを容易に適用可能なShaderMaterialが用意されており、震源の描画にはこれを使用した（ジオメトリはBufferGeometryでメッシュはPoints）。地形（地図）の描画にはPlaneBufferGeometryとMeshPhongMaterialを使用した。

```
実際のプログラムについてはおいおい記載する予定。
```

#興味深く感じた点

* 太平洋プレート沈み込みの様子がよくわかる（プレート境界に震源がたくさんある）
* 熊本地震（2016.04.16）の震源が断層に沿って位置している
* 気象庁のデータなので日本周辺だけかと思ったが、観測できた地震が全て含まれているらしい（日本からはるか遠方の地震もある）

#参考文献

* 地質調査総合センター (2020) シームレス標高タイル. [https://gbank.gsj.jp/seamless/elev/](https://gbank.gsj.jp/seamless/elev/) (確認日：2020.10.30).
* 気象庁 (2020) 気象庁 | 震源データ. [https://www.data.jma.go.jp/svd/eqev/data/bulletin/hypo.html](https://www.data.jma.go.jp/svd/eqev/data/bulletin/hypo.html) (確認日：2020.10.30).
* 西岡芳晴・長津樹理 (2015) PNG標高タイル - Web利用に適した標高ファイルフォーマットの考案と実装 -. 情報地質, 第26巻, 第4号, 155-163頁. DOI: [https://doi.org/10.6010/geoinformatics.26.4.155](https://doi.org/10.6010/geoinformatics.26.4.155).
* シームレス地質図ラボ (2020) 点群PNG. [https://gsj-seamless.jp/labs/pcpng/](https://gsj-seamless.jp/labs/pcpng/) (確認日：2020.10.30).
【postgreSQL】superuser権限をもつユーザ（ロール）が０の状態で、superuser権限を付与する方法

メモとして残します。


#やり方
私はpostgres10であることが前提条件として記述します。
基本的には後述に記述するバージョンを含むパスを変更することで、できると思います。
また、デフォルトユーザをpostgresであることが前提です。
##postgresをストップする。
```shell
sudo service postgresql stop
```

##2.postgresをシングルユーザモードで起動
###postgresユーザに切り替える。
```shell
sudo su - postgres
```
###postgresを限定起動
```shell
/usr/lib/postgresql/10/bin/postgres --single -D /etc/postgresql/10/main/
```
※ここは環境によってパスが変わる。

##3.sqlで任意のroleにsuperuser権限を付与する。
```shell
alter user postgres with superuser;
#完了したらctrl+Dで抜ける。
```

##4.postgresをスタートする。
※その前にsudoができるユーザまでもどってから、下記を実行。

```shell
sudo service postgresql start
```


以上。
[TEST] 非機能テスト

ソフトウェア開発時に機能のほかに非機能用要件というものがあります。文字通り機能以外の要件を定義するものです。

非機能テストとは作成したソフトウェアの**ユーザービリティ**や**パフォーマンス**・**セキュリティ**を定義してテストを行うことになります。


# ユーザビリティ

ユーザービリティを定義する際には**対象となるユーザー及び環境**を明確に定義する必要があります。テストも同じく、その対象となるユーザーと環境から見て下記のテストが満たされているか確認をします。

## 有効性

各ページ各要素の有効性を指定の環境でテストします。約束された環境、例えばIE, Chrome, Safariなどで動くか確認をします。

## 効率性

効率性に関してあらかじめ明確に定義されていないケースは多く、効率性をテストしPass, Failをつけるのは難しいです。ただ、ここは納品直前にクライアントから変更依頼などが来やすいポイントなので、あらかじめ定義しておき、テストケースが明確にあることをお勧めします。　

例えば、3クリック以内にマイページに遷移できること、などなど。

# パフォーマンス・セキュリティー

## 性能テスト

定義された通りの処理時間内に処理が行われているかどうか確認します。各動作を一覧にし、かかった時間を調べます。

## ロードテスト

長時間にわたり同じ処理を繰り返し、処理速度が一定範囲内であることを確認します。

## ストレステスト

指定の負荷以上の状態で正常に処理が行われるか確認を行います。

## ボリュームテスト

限界レベル以上の容量をリクエストし処理されるか確認します。

## 高頻度テスト

データを連続して処理させ、正常に処理されるか確認します。

## 障害対応テスト

致命的な障害が発生したときのリカバリープランが用意されているか、そのプランが実行できるか確認をします。

## セキュリティテスト

作成したソフトウェアが指定した機密保護レベルをクリアしているか確認をします。
ApplicationServiceをアクターで分ける

![アクターとユースケース.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/829617/f3b64b74-312b-aaf4-6d56-55a4973af0e1.png)

ユーザーストーリー「管理者としてレポートのレビューがしたい」を実装して、ApplicationServiceを作ったとします。
ファイルは`app/services/review_report_service.rb`としました。

# 誰のためのApplicationServiceかわからない
ちょっとまってください。レポートのレビューは管理者しか行わないのに、グローバルに展開してしまうのはまずくないでしょうか。
事情を知らないと報告者がこのApplicationServiceを呼び出してしまったり、報告者を考慮した処理を組み込んでしまいそうです。

# アクターごとにディレクトリを分ける
なので、アクターごとにディレクトリを分けた方がよさそうです。
`app/services/manager_actor/review_report_service.rb`
こうすれば、`review_report_service.rb`は管理者の場合だけを考えればよく、報告者が使っていたら間違っていることが明らかになります。

# 複数のアクターが連携してストーリーを構築する場合
稟議書のフローのように、複数のアクターが関わるストーリーもあります。その場合、アクターごとにディレクトリを作ると関連する処理なのに、アクターによって断片化してしまいます。

 * app/services/kacho_actor/ringi_service.rb
 * app/services/bucho_actor/ringi_service.rb
 * app/services/shacho_actor/ringi_service.rb

こういう場合は、Service名とアクターを入れ替えることで、断片化を防いでなおかつどのアクターが関係しているのかがわかりやすくなります。

 * app/services/ringi_service/kacho_actor.rb
 * app/services/ringi_service/bucho_actor.rb
 * app/services/ringi_service/shacho_actor.rb


他に、マイクロサービスでオーケストレーションベースのサーガパターンのようにいろんなアクターが連携するケースは、ApplicationServiceをディレクトリ名にして各マイクロサービスごとにクラスを作ると関連する処理がまとまってよいかもしれません[^1]。

 * app/services/hoge_service/current_service_actor.rb
 * app/services/hoge_service/another_service1_actor.rb
 * app/services/hoge_service/another_service2_actor.rb

[^1]: マイクロサービスは経験がないので、実際にはこんなことは必要ないかも

***
このエントリは[要求分析駆動設計](https://linyclar.github.io/software_development/requirements_analysis_driven_desgin/)の[ユースケース(ユーザーストーリー）、スイムレーン](https://linyclar.github.io/software_development/requirements_analysis_driven_desgin/#%E3%83%A6%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%82%B9%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AA%E3%83%BC%E3%82%B9%E3%82%A4%E3%83%A0%E3%83%AC%E3%83%BC%E3%83%B3)を再編し汎用的な内容に書き換えたものです。
めっちゃ長いけど、RailsでDDDっぽいことする話です。
Windows10 でRubyのバージョンをアップグレード、切替え

# Windows10 でRubyのバージョンをアップグレード、切替え

新しいRubyonrailsプロジェクトを始めようと
rails（バージョン）new （プロジェクト名） コマンドを打ち込んだところ、
gem install byebug -v '11.1.3' コマンドを実行してね
とのエラーが発生、コマンドを打ち込んだところ、
Rubyバージョンをアップしてね
とのエラーが発生。
ここでwindowsでのRubyのバージョンをアップする方法、管理するツールを共有します。

##今回Rubyバージョンの変更前後
変更前：ruby 2.2.6p396
![スクリーンショット 2020-10-30 114317.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/47a75dde-09d4-579b-44c8-e4d2af6d98cb.png)
変更後：ruby 2.4.10p364
![スクリーンショット 2020-10-30 114332.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/58d5179b-ba71-cc73-6e90-caf4d6a73668.png)


##OS環境
- システムの種類：Windows10 Home　64ビットオペレーティングシステム、x64ベースプロセッサ

##WindowsでRubyバージョンをアップするために必要なモノ
- uru：ruby バージョン管理ツール（Macだとrbenvに該当する）
- 今回設定したいrubyのversionファイル（https://rubyinstaller.org/downloads/）

##方法
1. [Rubyダウンロードページ](https://rubyinstaller.org/downloads/)にアクセスして、
WITHOUT DEVKIT下層の Ruby 2.4.10-1 (x64)をダウンロードする。

2.解凍してインストールする。終わると、C:直下にRubyフォルダが生成される。（例：C:Ruby24-x64）

3.[uru](https://bitbucket.org/jonforums/uru/wiki/Downloads)をダウンロードする。
![スクリーンショット 2020-10-30 121826.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/f0ef3c58-ec1f-9171-f2e0-7d919b5a0043.png)

4.解凍し、uru_rt.exeファイルをC:直下のtoolsディレクトリに格納する。
（toolsディレクトリが無かったら、新たに作成する。）

5.PowerShellまたはコマンドプロンプトを開き、C:toolsをカレントディレクトリに指定する。その後、uru_rt.exe admin install コマンドを実行する。
![スクリーンショット 2020-10-30 120652.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/b638369c-ed4e-68c3-b1bc-87fc1a9d83db.png)

6.uru admin add C:Ruby24-x64/bin コマンドを実行し、uruにrubyを登録する。
![スクリーンショット 2020-10-30 120800.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/2c5ba814-7c29-5238-c252-e095727e901b.png)

7.uru ls コマンドを実行し、uruにrubyが登録されていることを確認する。
![スクリーンショット 2020-10-30 121246.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/fdf4d719-7f3d-aeb5-c11b-2de697a38661.png)

8.uru 2410p364 コマンドを実行し、今回のruby2.4.10に切り替える。
![スクリーンショット 2020-10-30 121359.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/02917670-f046-981a-e098-96ff0ec1ce9f.png)

9.ruby -v コマンドを実行し、rubyバージョンが変更されたか確認する。
![スクリーンショット 2020-10-30 114332.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/48599030-18fc-83e4-16d2-72f6e0ef92ca.png)


ーーー

そもそも問題だった gem install byebug -v '11.1.3' コマンドで正常インストールされるか、動作確認。
![スクリーンショット 2020-10-30 122135.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676239/4051c09a-2ac1-beac-ca23-12c353b6a30b.png)
OK
select属性にclass名を付与したい

railsでアプリケーション作成中にセレクトボックス関連でつまづいたため記録として残しておきます。

環境は以下のとおりです。
ruby 2.6.5
Ruby on Rails 6.0.3.
##行いたいこと
もともと営業時間のセレクトボックスは実装済み。
24時間営業のボタンを追加＋Javascriptを使ってボタンをクリックしたときに全てのセレクトボックスに'00'が入るようにしたい。(以下写真のイメージ)
<クリック前>
![f1d0dc39dd28504edcd3be06647cbad1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700117/98e209d7-4280-fb3e-5a5d-c85d19541ca2.png)
<クリック後>
![95f4366f509951f98ab68ff151686fa3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700117/c83b2b23-f1e7-3ece-3713-9cfc6ae94bbe.png)

##つまづいた点
select属性にclass名が付与されない！
以下の順序で進めようと考えていましが見事に出鼻を挫かれました。
1.該当のselect属性に同じクラス名を付与
2.Javascriptで対象のclass名を持った要素をまとめて取得
3.forEach関数で取得したフィールドの値を'00'に変更


とりあえずクラス名をつけるために以下のようなコードに書き換えました。({}の一番最後に``class: "opening-hour"``を記述する)

```javascript

<%= f.time_select :open_time, {prompt: true, ignore_date: true, minute_step: 15, class: "opening-hour"} %> 〜
<%= f.time_select :close_time, {prompt: true, ignore_date: true, minute_step: 15, class: "opening-hour"} %>

```

再読み込みをし検証ツールで確認してみたところ・・・
![c0feeff4834008d06bcb50ce6cfb9a04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700117/8cdf7288-6093-339d-a7f8-9d1d63cf29f0.png)

class名が付与されていませんでした。

##結論
###ヘルパーのオプションとhtmlのオプションは分けて記述する必要がある。

以下のブログ記事を参考にさせていただきました。
[date_selectの使い方【Rails】](https://www.y-hakopro.com/entry/2019/07/26/215350
)

[time_field レファレンス](https://railsdoc.com/page/time_select
)　をみるとヘルパーのオプションとHTML属性がそれぞれ記載されています。この２つは同じ{ }に入れるのではなく分ける必要があるということでした。
私のコードも以下のように書き換えることで無事クラス名が付与されました！

```js
<%= f.time_select :open_time, {prompt: true, ignore_date: true, minute_step: 15}, {class: "opening-hour"} %> 〜
<%= f.time_select :close_time, {prompt: true, ignore_date: true, minute_step: 15}, {class: "opening-hour"} %>
```
![acd7910429ca8c88fa52e24ca09fc460.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700117/27b6af43-b283-694b-5207-e108f70ce323.png)

クラス名が付与されたのでそのあとは、順序の２.３と行い無事思っていた実装を行うことができました！
JavaScript : 配列内の重複した要素を数える

# はじめに
JavaScriptの配列内に、どんな要素が何個あるのか、重複している値の個数をカウント。
その結果をオブジェクト（連想配列）に格納します。

`for`・`forEach`・`reduce`の三種類の方法で書いてみます。

## 処理パターン


### for でカウント
```javascript:for

var arr = [0, 1, 1, 1, 1, 3, 3, 5, 0, 7];
var count = {};

for (var i = 0; i < arr.length; i++) {
  var elm = arr[i];
  count[elm] = (count[elm] || 0) + 1;
}

console.log(count);

// 出力結果
// {0: 2, 1: 4, 3: 2, 5: 1, 7: 1}

// 0 -> 2個
// 1 -> 4個
// 3 -> 2個
// 5 -> 1個
// 7 -> 1個
```

カウント部分の`(count[elm] = count[elm] || 0) + 1;`の記述は、論理演算子の短絡評価を利用して、以下のよう処理しています。

- count[elm]がある => count[elm]の現在値+1を格納。（既にカウントを開始している要素）
- count[elm]がない => count[elm]に1（0+1）を格納。（初めてカウントする要素：値は`undefined`）

以下のように三項演算子で書いても結果は同じになります。

```javascript:カウントの部分

// 論理演算子を使う
count[elm] = (count[elm] || 0) + 1;

// 三項演算子を使う
count[elm] = count[elm] ? count[elm] + 1 : 1;
```

### forEach でカウント
```javascript:forEach

var arr = [0, 1, 1, 1, 1, 3, 3, 5, 0, 7];
var count = {};

arr.forEach(function(i) {
  count[i] = (count[i] || 0) + 1;
});

console.log(count);

// 出力結果
// {0: 2, 1: 4, 3: 2, 5: 1, 7: 1}
```

### reduce でカウント
```javascript:reduce

var arr = [0, 1, 1, 1, 1, 3, 3, 5, 0, 7];

var count = arr.reduce(function(prev, current) {
  prev[current] = (prev[current] || 0) + 1;
  return prev;
}, {});

console.log(count);

// 出力結果
// {0: 2, 1: 4, 3: 2, 5: 1, 7: 1}
```

# おわりに
JavaScriptのループ処理速度は便利な`forEach`より、ループの基本である`for`の方が速いようです。シンプル・イズ・ベスト？と言ったところでしょうか。
カウントしたい配列の要素数が数万個あると言ったケースに遭遇することもあります。要素数が多いときは、速度重視の`for`で処理することも検討してみましょう。
Gitの基本3

<font color="Red">インデックスとは</font>
インデックスとは、コミットをするファイルを登録するための場所。
ファイルをコミットすると、インデックスに登録されているファイル群の変更が記録される。

<font color="Red">インデックスのメリット</font>
一度に多くのファイルを変更した際に、どのファイル単位でコミットするかを選択するために使用する。
インデックスに登録したファイル単位が一つのコミットとなるために、どのファイルをインデックスに登録するのかを決める必要がある。

<font color="Red">コミット</font>
ディレクトリやファイルの状態を記録するための操作。
コミットすることで現在の状態が、日時や変更を加えた人の情報を含めて一緒に保存することができる。


<font color="Red">コミットメッセージを書く目的</font>
コミットメッセージとは、一つのコミットに対してつけるコメントのこと。
そのコミットでどのような実装をしたのかということを記録しておくための記述する。

<font color="Red">コミットをする際に気をつけるべきポイント</font>
コミットはなるべく細かく行う。一つの機能に対して一コミットするのがベター。
なぜなら、基本的にファイルを元に戻したいと思った時には、コミットごとでしかファイルを元に戻すことができないため。
Lambda×Laravel で Imagick を使う

Lambdaで Laravel を使えるようにするには bref を使うと簡単。

<a target="_blank" href="https://qiita.com/x002dc/items/e0f59415f6db1d151852">LambdaでLaravelを動作させようと思ったけど、少しコケたのでメモしとく</a>

Imagick を利用したい場合は php.ini に extention を追加すれば良いだけです。

<a target="_blank" href="https://bref.sh/docs/environment/php.html">Configuring PHP - Bref</a>

## 環境

- Windows 10 Home
- <a target="_blank" href="https://docs.docker.com/toolbox/overview/">Docker Toolbox</a>
- PHP7.4
- Laravel 8
- bref


### php.ini の追加

プロジェクトディレクトリ配下に `php/conf.d/php.ini` を作成。

```ini:php/conf.d/php.ini
extension=imagick
```

上記を追加した上で、 `serverless deploy` すれば、それだけ反映されます。

![PHP-7-4-10-phpinfo-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28494/5a1847a4-9c5a-136c-687d-ba46e7012992.png)

Lambda上 でPHPを利用した画像処理のツールなんて、簡単に作れそうですね。
Lambda@Edge で wwwあり・なしをどちらか一方にリダイレクトで寄せる対処を行う

# モチベーション

サイトを公開する場合、 `www.example.com` と `example.com` の両方でアクセス可能とすることがある (いわゆる、wwwのあり・なし設定)。 ただし、両方のFQDNが有効な場合であっても、SEO効果などの理由から、サーバー側でリダイレクトを行い、1つのFQDNを正としてサイトを運営する方が良い。
これを nginx で「wwwありに寄せる」書く場合は以下のように書く。 なお、現時点でサイトを運営するならば https にすべきだとは思うが、単なる例なのでここでは触れないこととする。

```nginx
# www ありに寄せる例
server {
    listen      80;
    server_name www.example.com;
    # 以下サイトの設定を記述
}

server {
    listen      80;
    server_name example.com;

    location / {
        return 301 http://www.example.com$request_uri;
    }
}
```

これと同様のことを CloudFront で行う方法の１つとして、Lambda@Edge を利用した方法を紹介する。


## 追加モチベーション

これが必要なもう一つの理由としては `CloudFront -> API Gateway -> Lambda` という構成を採っているのだが、デフォルト設定のままだと Lambda でアクセスしてきたホストを取得できないという問題がある。 そのため、ホスト毎に処理を切り替えたい場合に困ってしまった。
そこで、今回は上記のように、そもそもどちらか一方のみを正とすることで、Lambdaで利用するホスト名を固定値で参照可能とした。

なお Lambda@Edge を使えば上記の構成でも Lambda にホスト名を渡すことはできる。 具体的には以下の記事を参照。

- [Cloudfront -> API Gateway -> Lambdaの構成でアクセス元のHostをLambdaで取得する](https://qiita.com/shoma2da/items/e9c8abc23f7fbeafa275) 


# Lambda@Edge でのリダイレクト

どうすればリダイレクトできるかの具体例は公式ページに書いてある。

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-examples.html#lambda-examples-http-redirect

今回は同じCloudFront ディストリビューションで `www.example.com` と `example.com` の両方を受け付け、**`www.example.com` 以外** を `www.example.com` にリダイレクトする例 (先述の nginx と同じ例) を示す。 nginxと異なり、こちらではディストリビューションで "http -> https リダイレクト" 設定が行われているものとする。


```python:Python3.8ランタイムでの実行を想定
#!/usr/bin/python
# -*- coding: utf-8 -*-

REDIRECT_HOST = 'www.example.com'


def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    if headers['host'][0]['value'] == REDIRECT_HOST:
        # ホスト名が指定したものであればリダイレクトしない
        return request

    uri = request['uri']
    redirect_response = {
        'status': '301',
        'statusDescription': 'Moved Permanently',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': f'https://{REDIRECT_HOST}{uri}'
            }]
        }
    }

    return redirect_response
```

これをビュワーリクエストに設定すればよい。 Lambda@Edge の設定方法は [前のベーシック認証を設定する記事](https://qiita.com/t-kigi/items/582b36e76b35c278eb96) を参照のこと。


# 別解

今回は１つの CloudFront ディストリビューションで複数の FQDN が有効になっている場合の対処を示した。 一方、１つのFQDNごとに１つのディストリビューションを用意できるのであれば、用意したディストリビューションへの通信の全てをリダイレクトする設定を書けば対処可能である。

具体的には、「Cloudfront ディストリビューションを Web Hosting してリダイレクトルールを記載した S3 バケットに流してリダイレクトさせる」「空のS3に流すが、Lambda@Edgeをビュワーリクエストに記載してここで固定のリダイレクトを行う」などである。
gRPCとFirebase Authenticationで認証処理

# はじめに
gRPCとFirebase Authenticationを使用したGoサーバでの認証処理のやり方を紹介します。認可処理についてはまた別記事で書く予定です。

# Firebase Authentication
SDKの追加は以下のコマンドからできます。

```shell
go get firebase.google.com/go
```

Firebase Admin SDK for Go の初期化は以下を参考にします。
[サーバーに Firebase Admin SDK を追加する](https://firebase.google.com/docs/admin/setup?hl=ja#initialize_the_sdk)

従来は```option.WithCredentialsFile()```を使用した初期化が一般的だったようですが、GOOGLE_APPLICATION_CREDENTIALS 環境変数を使用する初期化を強くお勧めしているようです。

```go:firebase.go
package middleware

import (
	"context"
	firebase "firebase.google.com/go"
	"firebase.google.com/go/auth"
)

type Firebase struct {
	Auth *auth.Client
}

func NewFirebase() (inst *Firebase, err error) {
	inst = new(Firebase)
	// GOOGLE_APPLICATION_CREDENTIALSで指定した認証情報ファイルを暗黙的に読み込む
	app, err := firebase.NewApp(context.Background(), nil)
	if err != nil {
		return
	}
	authInst, err := app.Auth(context.Background())
	if err != nil {
		return
	}

	inst.Auth = authInst
	return
}
```

# 認証処理
これは後から説明する```grpc_auth.UnaryServerInterceptor```で引数に使用する認証メソッドを持つレシーバの定義です。先ほどのFirebaseをフィールドに持ちます。

```go
package middleware

import (
	"context"
	grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
)

type Authentication struct {
	firebase Firebase
}

func NewAuthentication(firebase Firebase) *Authentication {
	authInst := new(Authentication)
	authInst.firebase = firebase
	return authInst
}

func (au *Authentication) Authenticate(ctx context.Context) (newCtx context.Context, err error) {

	idToken, err := grpc_auth.AuthFromMD(ctx, "bearer")

	// JWT の検証
	token, err := au.firebase.Auth.VerifyIDToken(context.Background(), idToken)
	if err != nil {
		return
	}
	// 引数のコンテキストにtokenというキーにJWTの情報を入れて返す
	newCtx = context.WithValue(ctx, "token", token.Claims)
	return
}
```

ちなみに、こちらの記事がわかりやすかったので参考として共有しておきます。Interceptorに関しての説明を読んでおくとこの後の処理の内容がスムーズにわかると思います。
[gRPC-GoのMiddleware (Inerceptor) で認証／認可してみる](https://qiita.com/arenahito/items/d96e437e5e13ef800ee0)

認証で使用するミドルウェアは[Go gRPC Middleware](https://github.com/grpc-ecosystem/go-grpc-middleware)に定義してあるgrpc_authを使用します。

```go:main.go
package main

import (
	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
	grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"log"
	pb "my-project/grpc"
	"my-project/middleware"
	"net"
)

func main() {

	listenPort, err := net.Listen("tcp", ":800")
	if err != nil {
		log.Fatalln(err)
	}

	// Firebaseインスタンスを生成
	firebase, err := NewFirebase()
	if err != nil {
		log.Fatalln(err)
	}
	// Authenticationインスタンスを生成
	auth = *NewAuthentication(*firebase)

	// serverに認証設定を追加
	server := grpc.NewServer(
		grpc_middleware.WithUnaryServerChain(
			grpc_auth.UnaryServerInterceptor(auth),
		),
		// Streamingを使用する場合は必要
		grpc_middleware.WithStreamServerChain(
			grpc_auth.StreamServerInterceptor(auth),
		))

	pb.MyProjectServer(server, &handler)

	reflection.Register(server)

	if err := server.Serve(listenPort); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

```

# まとめ
簡単なgRPCとFirebase Authenticationを使用したGoサーバでの認証処理のやり方でした。認可についても似たようにInterceptorで実装できるので、また別の記事で描こうと思います。