OmniAICreator/Qiita-1.07M huggingface dataset:
サイバーエージェントのインターンがマジ神だったので紹介してみる

こんにちは．
大学二年　伊地知（いぢち）です．
先日　CyberAgentの3weeks インターン　（サーバーサイド）に参加しました．
このインターンの選考や得られた体験や学びなどを紹介します．
# 選考に関して
## 私の経験
事前情報として，私はこれまでインターンに参加したことがありませんでした.  
一年からハッカソンには積極的に参加しており，過去に一度だけ，受賞したことがあります．  
今回のインターンの軸であるサーバーサイドについてはハッカソン，趣味で書いていただけです．

しかし，登録している[サポーターズ](https://talent.supporterz.jp/)から，招待が来ていたので，参加を決意しました．

## 選考の流れ
選考は，ES->面接->インターン参加決定の流れです．
エントリーシートにはこれまでの開発経験やつまずいたことなど，「開発していたらよくあること」について訊かれていたので，正直に答えました．  
最初はインターン経験もなく，ES落ちだろうと思っていましたが，なんとか通過．面接もESで書いたことを掘り下げられましたが，盛っていなかったので会話をする感覚で答えていました．
そんな感じで面接は通過．参加が決定しました．

# インターンで得られたもの
架空のスマホゲームのＡＰＩ（Userデータ管理やランキング機能）について実装していき，学習します．
その中で得られた学びと体験について書いていきます．

## 体験
## メンターさんやそのほか社員さんによるLT会  

メンターさんも普段からバリバリ開発しているエンジニアなので，実務での話やサービスの裏側，エンジニアキャリアなどの話を訊くことができます！！のエンジニアへの憧れをさらに引き出し，今後のエンジニアとしてキャリアを考える上で参考になります．

## メンターさんによる実務レベルのコードレビュー
コードレビューというのは簡単に説明すると他者に自分が書いたコードに対して，”このコードはこういう風に実装したほうがいい”など指摘をする（受ける）ことです．  
いままで，趣味でコードを書いていただけだったので，命名規則やアーキテクチャについて深く学んでいませんでしたが，このレビューでアドバイスをいただき，実務レベルのコードの書き方を覚えることができます！

## 学び
これについては，多すぎるので後日Qiita，Blogで別記事とします．
【HTML】mailto:の使い方

#プログラミング勉強日記
2021年3月5日

#mailto:とは
　mailtoはaタグに含ませることができて、指定したアドレスに向けたメールを作成する画面が開く。その画面は、自分のパソコンにインストールされているメーラーあ開いて、そこに本文を書くことでメールを送信することができる。mailtoではWebサイト上ではサーバーとのやり取りをせずに済むので、簡単なお問い合わせのページとしても使える。

#mailto:の使い方
　自分のパソコンにインストールされているメーラーを起動する。

```html
<a href="mailto:example.com">メールを開く</a>
```

　subject(題名)とbody(本文)を加えると、以下のようにメーラーが開く。メールアドレスの後に続く情報は、`?`で区切って、以降の情報は`&`で区切る。

```html
<a href="mailto:example.com?subject=Hello&body=Hello World">メールを開く</a>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/e21c9850-c7a8-107b-c07f-2328f482a555.png)

#mailtoは推奨されてない
　mailtoはあまり推奨されていない。これは、HTML上に書かれたメールアドレスを勝手に収集されてスパムの標的にされる恐れがある。そのため、現在ではSSLの技術を使ったフォーム(SSLフォーム)で個人情報を扱うことが標準になってきている。

　他にも、mailtoは文字化けが発生しやすかったり、メーラーがインストールされていないPCは使えなかったりする。

#参考文献
[HTMLのmailtoでメールを送る方法と使い所について解説！](https://www.sejuku.net/blog/81882)
[HTMLでメール📩を送る「mailto:」の使い方と注意点まとめ👈](https://webliker.info/99276/)
ContentType書き換えでImageMagickのリサイズを成功させる

## はじめに

先日、[「オブジェクト名の変更」でアップロード済み画像のサムネイル生成を簡単に](https://qiita.com/oYuu/items/2bb6e1a381a65758bfa5)という記事を書きました。
その作業の中で、ContentTypeの問題によって一部の画像でImageMagickのリサイズ（サムネイル生成）に失敗していることが分かりました。
今回はなぜそうなったのか、どう対処したのかについてご紹介します。

## リサイズに失敗する原因

### ContentTypeを指定しないと、application/octet-streamになる

FirebaseのCloud Storageにファイルをアップロードする時にContentTypeが指定されていないと、判別できない場合はアップロード方法に応じて`application/octet-stream`または`application/x-www-form-urlencoded`に設定されます。
実際、一部の画像が`application/octet-stream`になってしまっていました。

### application/octet-streamではImageMagickで画像のリサイズができない

画像のリサイズはImageMagickを利用しています。
ImageMagickでContentTypeが`application/octet-stream`だと、画像のリサイズができません。

## サムネイル生成できるようにする対処法

### ContentTypeを書き換える

ContentTypeが`application/octet-stream`の画像が存在することでImageMagickのリサイズが失敗していることが分かりました。
そこでContentTypeを以下のように書き換えましょう。

```js
// ファイルからメタデータを取得する
const file = await bucket.file(imagePath)
await file.getMetadata()

if (file.metadata.contentType == 'application/octet-stream') {
    // octet-streamだったら、image/jpegなどcontentTypeを書き換える
    const contentType = 'image/jpeg'
    await file.setMetadata({
        contentType: contentType,
    })
}
```

サンプルでは簡単なソースコードをご紹介するために、application/octet-streamだったらimage/jpegに決め打ちで置き換えるようにしています。
実際のソースコードはjpg, jpeg, png, gifなど、必要なContentTypeを拡張子で判定してセットしています。

このようなcontentTypeの書き換えを行ったところ、無事にImageMagickで画像のリサイズができるようになりました。

### 最後に

このようなContentTypeの書き換えが発生しないように、本来はアップロード時にきちんと指定するのが良いと思います。
とはいえアップロード済みの画像のContentTypeを書き換える場面もあるかもしれません。
そんな時はこちらの方法を試してみてください。
AddressablesとCloud Content Delivery

# Unity謹製のCDN

個人で使うには十分だと感じました。
当たり前ですがUnityとの相性が抜群です。

# 導入手順

はりきって書こうと思ったら、ダッシュボードにすべてが書かれていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703909/3aac1703-7cef-135c-586b-2d3a8a6afb9a.png)


# エディタ拡張から実行するために

以下のようなコマンドをucd.exeと同階層に置きました。

```
ucd auth login [ログインID]
ucd config set bucket [Bucket ID]
ucd entries sync [同期させるターゲットパス]
echo n | ucd releases create -b [Bucket ID]
```

# バンドルのビルドスクリプトを書く

## 新規の場合

```
AddressableAssetSettings.BuildPlayerContent();
```

## Updateの場合

```
        var aaSettings = AddressableAssetSettingsDefaultObject.Settings;

        if (aaSettings != null && aaSettings.BuildRemoteCatalog)
        {
            var id = aaSettings.profileSettings.GetProfileId("Default");
            aaSettings.activeProfileId = id;

            string path = ContentUpdateScript.GetContentStateDataPath(false);
            if (System.IO.File.Exists(path))
            {
                ContentUpdateScript.BuildContentUpdate(aaSettings, path);
            }
        }
```

上記を組み合わせれば、ビルド後にバッチを走らせることができます。
【Rails】Bootstrap 4 Tag Input Plugin With jQueryを使ってタグの見た目をよくする

# タグ入力後の見た目をよくしよう

題名通りBootstrap 4 Tag Input Plugin With jQueryを用いてタグ入力後の見た目をよくしていきます。
（２回目の）初投稿なので誤字や脱字など至らない点はあると思いますが、よろしくお願いいたします。
##  完成形
現在のタグ入力機能は下のような感じですが、このままだと殺風景なので
[![Image from Gyazo](https://i.gyazo.com/0dbdcc0c5861ee47e66a158bfe39f045.gif)](https://gyazo.com/0dbdcc0c5861ee47e66a158bfe39f045)
***

↓のように入力後にきれいに装飾されるようにしてみましょう。
またエンターキーでもタグの登録ができるようになります
[![Image from Gyazo](https://i.gyazo.com/2ca5933b53fca2be5758b4d4721b3019.gif)](https://gyazo.com/2ca5933b53fca2be5758b4d4721b3019)



##前提
Rails 6.0.3.5
Bootstrap 4.5
jQuery導入済み
タグ機能を実装済み

##Bootstrap 4 Tag Input Plugin With jQueryの導入

[Bootstrap 4 Tag Input Plugin With jQueryの公式サイト](http://www.jqueryscript.net/form/Bootstrap-4-Tag-Input-Plugin-jQuery.html)

上の公式ページからダウンロードしてきましょう。
***
解凍すると
Bootstrap-4-Tag-Input-Plugin-jQueryというディレクトリができます。
ディレクトリ内の
tagsinput.js
を
app/javascripts
に
tagsinput.css
を
tagsinput.scss
に名前を変えて
app/javascripts/stylesheets
にいれましょう。
***
tagsinput.jsを読み込めるように記述します。

```js:application.js
require('jquery')
require('tagsinput') //←これを追加します
```

tagsinput.scssを読み込むための記述もします。

```scss:application.scss
@import '~bootstrap/scss/bootstrap';
@import '~@fortawesome/fontawesome-free/scss/fontawesome';
@import 'tagsinput'; //←これを追加します。
```

導入はこれで終わりです。

## データをdata-roleで送ってtagsinputを起動させよう。

タグの入力フォームにdata-roleを追加します。

```ruby:new.html.erb

<div class="tags">
  <%= f.label :tag_list %>
  <%= text_field_tag 'post[tag_list]', @post.tag_list, data: {role: "tagsinput"} %>   # ←を追加  
</div>
```

これで
[![Image from Gyazo](https://i.gyazo.com/025fa1d9306c809fe20f7a4308f0919e.gif)](https://gyazo.com/025fa1d9306c809fe20f7a4308f0919e)
のようにタグ入力後に装飾されるようになりました！

## 少し設定を変えてみましょう
現状だとタグが無限に登録できてしまします。

追加できるタグの数と最大文字数を設定しましょう。
tagsinput.jsの中身を少しみてみましょう。


```js:tagsinput.js
    maxTags: undefined,
    maxChars: undefined,
```

こちらを見るとタグの文字数の縛りもないことがわかりますね！！！
こちらを変えていきましょう。

```js:tagsinput.js
    maxTags: 4,
    maxChars: 8,
```

タグの最大数４と最大文字数８と設定できました。
***
[![Image from Gyazo](https://i.gyazo.com/b4dfef4b843719dde096da7cc27d6bb2.gif)](https://gyazo.com/b4dfef4b843719dde096da7cc27d6bb2)

↑半角英数ならいいのですが、全角入力時に入力画面にずれがでてしまいます。
こちらを直していきましょう。

```js:tagsinput.js
    this.inputSize = Math.max(1, this.placeholderText.length);
```

こちらを

```js:tagsinput.js
    this.inputSize = Math.max(20, this.placeholderText.length);
```

にかえてみましょう。
[![Image from Gyazo](https://i.gyazo.com/62900b6c54153686bd6de9f0b8039ad9.gif)](https://gyazo.com/62900b6c54153686bd6de9f0b8039ad9)

いい感じになりましたね！！！

## 最後に
導入にするにあたっていろいろなエラーと戦いましたorz
[bootstrap-tagsinput]
(https://github.com/bootstrap-tagsinput/bootstrap-tagsinput)

最初はこちらを導入しようとしたのですが、古いためかなかなかうまく行かずorz
またTag itの導入もうまくいかずorz
いろいろ探し求めてこちらにたどり着きました。

またBootstrap 4 Tag Input Plugin With jQueryについての日本語の文献がなく、オプションなどについて英語の公式を参考にしました。
英語だからといって苦手意識を持たない。しっかりと読むことの大切さを知りました（遅い）
ついでにgifのマークダウン記法があるのを初めて知りました（遅い）
***
以上となります。拙い文章ですがご拝読いただきありがとうございました。
bigqueryでstring型のUTC日付をJSTに変換する方法


bigqueryで **string型のUTCをJST変換する手順** を調べてて結構手こずったのでメモを残します。

## UTC→JST変換

```sql

SELECT
  id
  , created_at  -- ①元データ：これをJSTに変換したい
  , SUBSTR(created_at, 1, 19) as UTC_string  -- ②UTCのstring型で時刻の情報を抽出
  , TIMESTAMP(SUBSTR(created_at, 1, 19)) as UTC_timestamp  -- ③UTCのTIMESTAMP型に変換
  , FORMAT_TIMESTAMP('%Y-%m-%d %H:%M:%S',TIMESTAMP(SUBSTR(created_at, 1, 19)), 'Asia/Tokyo') as JST_timestamp  -- ④JSTのTIMESTAMP型に変換
  FROM
    `dataset.table` 

```

### 出力イメージ

|  id | ①created_at | ②UTC_string | ③UTC_timestamp | ④JST_timestamp | 
|:-----------:|:------------:|:------------:|:------------:|:------------:|
| 123456       | 2021-03-02 06:59:04.322000 +00:00        | 2021-03-02 06:59:04         | 2021-03-02 06:59:04 UTC         | 2021-03-02 15:59:04         |

①の元データがstring型
②で、SUBSTRを利用して時刻情報までを抽出する（これをやらないで直接③を行うとエラーになる）
③でUTCのTIMESTAMP型に変換する
④でJSTのTIMESTAMP型に変換する
[メモ] VSCodeテーマ

# 環境

* Windows 10
* Visual Studio Code 1.54.1

# 拡張機能

* `Fluent Icons`（`miguelsolorio.fluent-icons`）
* `Vibrancy`（`eyhn.vscode-vibrancy`）

# 適用後

![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/1664f955-1b03-50cf-bb4e-909abe927f93.png)

# 注意点

タイトルバーに「サポート対象外」と表示される。
![img3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/7e8ce435-9520-aaf5-3dea-912c870a50c1.png)

「Codeインストールが壊れている可能性～」警告は「今後表示しない」を選べば表示されなくなる。
![img2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/bda5e342-17cd-ee80-f74b-dd94d1b201c3.png)

* [Visual Studio Code Frequently Asked Questions](https://code.visualstudio.com/docs/supporting/faq#_installation-appears-to-be-corrupt-unsupported)

> インストールが壊れている可能性があります [サポートされていません]
VS Code は、インストールがディスク上で変更されたかどうかを検出するバックグラウンド チェックを行い、変更された場合は、タイトル バーに[サポートされていません] というテキストが表示されます。これは、一部の拡張機能が VS Code 製品を直接変更 (パッチ) して、半永久的な方法 (次の更新まで) を行うため、問題の再現が困難になる可能性があります。VS Code の修正プログラムをブロックするわけではありませんが、VS Code の修正プログラムを適用すると、サポートされていないバージョンが実行されていることを示す認識を高めたいと考えています。VS Code を再インストールすると、変更されたファイルが置き換えられます。
【超速】AWS EC2インスタンスにpostgresql client 12をインストールする

EC2のリポジトリが古いっぽいので、ちょっと困った。
調べると詳しく書いてあるサイトは色々ありますので、意味とかはそちらで調べたほうが良いです。

さっさとpsql12を使いたい時、一行づつコピペしてください。（ec2-userでの実行を想定してます。）

```
wget https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo rpm -Uvh --nodeps pgdg-redhat-repo-latest.noarch.rpm
sudo sed --in-place -e "s/\$releasever/7/g" /etc/yum.repos.d/pgdg-redhat-all.repo
sudo yum update
sudo yum search postgres
sudo yum install postgresql12
psql --version
```

確認コマンド含めて書いてあるので、インストールには影響しないものもあります。
Set-CookieのSameSite属性のエラーについて


# SameSiteエラーまとめ
GoogleChromeの開発ツールで表示されるSameSiteのエラーについてまとめました（これ以外にもあると思います）

```
This Set-Cookie was blocked because it had the "Secure" attribute but was not received over a secure conenection.
``` 
_翻訳：_ 「このセットクッキーは、"Secure "属性を持っていますが、セキュアな接続で受信されなかったため、ブロックされました」。

_対処：_ 対象のcross-siteがhttps対応しているか確認する。


```
This Set-Cookie was blocked because it had the "SameSite=None" attribute but did not have the "Secure" attribute, which is required in order to user "SameSite=None".
```
_翻訳：_ 「このSet-Cookieは、"SameSite=None "属性を持ちながら、"SameSite=None "を利用するために必要な "Secure "属性を持っていなかったため、ブロックされました。」

_対処：_ Cookieをセットする際、 `secure` を付与しているか。例. `Set-Cookie: hoge=fuga; Secure`

```
This Set-Cookie was blocked because it had the "SameSite=Lax" attribute but came from a cross-site response which was not the response to a top-level navigation.
```
_翻訳：_「このセットクッキーは、"SameSite=Lax "属性を持っていたが、トップレベルのナビゲーションへの応答ではないクロスサイトの応答から来ていたため、ブロックされました。」

_対処：_ Laxの場合、cross-siteに対してページ内遷移以外のGETリクエストはCookieが送信されない。HTML内部で画像をcross-siteから読み込んだり、JSでcross-siteから読み込んだりすることは出来ない。

# 用語の意味合い
#### top-level navigation
いわゆるブラウザのURLバーに表示されているURLのこと
#### cross-site
上記以外のURLのこと。サブドメインは違ってもOK
例えば、`http://www.hoge.com` がtop-levelだとすると、
`http://blog.hoge.com` はcross-siteにはあたらない。同じサイト(same-site)として扱われる。
`http://www.fuga.com` はcross-siteにあたる。
#### same-site
top-level のサイトのこと。

下記サイトが詳しいです。
https://web.dev/same-site-same-origin/
環境統計学  鈴木栄一先生　地人書館

```{r}

#環境統計学 p.79 鈴木栄一著　（作成中）

library(dummies);library(dplyr)

data(iris)

data=iris

species=unique(data$Species)[1:2]

data=iris%>%filter(Species %in% species)

X=data[,!(colnames(data) %in% "Species")]

for(i in 1:ncol(X)){
  
X[,i]=ifelse(X[,i]>mean(X[,i]),1,0)  
  
}

Y=dummy(data$Species)[,1]

#2dim_freq

#XX_A 相関

XX_cor_A=array(0,dim=c(ncol(X),ncol(X)))

X1=X[Y==1,]

for(j in 1:ncol(X)){
for(i in 1:ncol(X)){
  
if(j!=i){  
  
XX_vec=cbind(X1[,j],X1[,i])

colnames(XX_vec)=c("x1","x2")

XX_vec=data.frame(XX_vec)

box=array(0,dim=c(2,2))

colnames(box)=c("x1","x2")

rownames(box)=c("0","1")

for(k in 0:1){
for(l in 0:1){  
  
XX_vec_sub=XX_vec%>%filter(x1==k & x2==l)  
  
box[(k+1),(l+1)]=nrow(XX_vec_sub)  
  
}}

if((box[1,1]*box[2,2]-box[1,2]*box[2,1])!=0){
  
XX_cor_A[j,i]=(box[1,1]*box[2,2]-box[1,2]*box[2,1])/sqrt(prod(c(apply(box,1,sum),apply(box,2,sum))))
  
}else{
  
XX_cor_A[j,i]=0  
  
}

}
  
}}

#XX_B 相関

XX_cor_B=array(0,dim=c(ncol(X),ncol(X)))

X2=X[Y==0,]

for(j in 1:ncol(X)){
for(i in 1:ncol(X)){
  
if(j!=i){  
  
XX_vec=cbind(X2[,j],X2[,i])

colnames(XX_vec)=c("x1","x2")

XX_vec=data.frame(XX_vec)

box=array(0,dim=c(2,2))

colnames(box)=c("x1","x2")

rownames(box)=c("0","1")

for(k in 0:1){
for(l in 0:1){  
  
XX_vec_sub=XX_vec%>%filter(x1==k & x2==l)  
  
box[(k+1),(l+1)]=nrow(XX_vec_sub)  
  
}}
  
if((box[1,1]*box[2,2]-box[1,2]*box[2,1])!=0){

XX_cor_B[j,i]=(box[1,1]*box[2,2]-box[1,2]*box[2,1])/sqrt(prod(c(apply(box,1,sum),apply(box,2,sum))))
  
}else{
  
XX_cor_B[j,i]=0  
  
}

}
  
}}


#YX

YX_p=array(0,dim=c(2,ncol(X)))

#YX 相関

YX_cor=c()

for(j in 1:ncol(X)){
  
X_vec=X[,j];Y_vec=Y

XY_vec=cbind(X_vec,Y_vec)

colnames(XY_vec)=c("x","y")

XY_vec=data.frame(XY_vec)

box=array(0,dim=c(2,2))

colnames(box)=c("x","y")

rownames(box)=c("0","1")

for(k in 0:1){
for(l in 0:1){  
  
XY_vec_sub=XY_vec%>%filter(x==k & y==l)  
  
box[(k+1),(l+1)]=nrow(XY_vec_sub)  
  
}}
  
YX_p[,j]=box[,2]/apply(box,1,sum)

YX_cor=c(YX_cor,(box[1,1]*box[2,2]-box[1,2]*box[2,1])/sqrt(prod(c(apply(box,1,sum),apply(box,2,sum)))))
  
}

n=length(Y);nA=sum(Y);nB=sum(abs(Y-1))

pi=c(nA,nB)/n





```
Awesome Backgammon AI

バックギャモン AI 開発で調べたことをまとめるページ。

# TD-Gammon 実装

- [Implementing TD-Gammon with Keras] (http://andrewdunstall.com/2021/01/24/implementing-td-gammon-with-keras/) 2021年
    - [レポジトリ](https://github.com/dunstall/td-gammon)
- [Before AlphaGo there was TD-Gammon](https://medium.com/jim-fleming/before-alphago-there-was-td-gammon-13deff866197)
    - [レポジトリ](https://github.com/fomorians/td-gammon) - TensorFlowによる実装 2016年頃
- [dellalibera/td-gammon](https://github.com/dellalibera/td-gammon) - PyTorchによる実装 2019年頃
    - [fork](https://github.com/mkisono/td-gammon-1)
    - [TD-Gammon でお試し](https://qiita.com/mkisono/items/77c238c8121d79cb7622)
    - [TD-Gammon でお試し結果](https://qiita.com/mkisono/items/d4ea0c71a13ecb06d8a9)

# TD-Gammon 以外の実装

- [ardabbour/amca](https://github.com/ardabbour/amca) - Stable Baselinesを使った実装(動くのだろうか？) 2019年頃

# Gym

- [dellalibera/gym-backgammon](https://github.com/dellalibera/gym-backgammon)
- [PettingZoo-Team/PettingZoo](https://github.com/PettingZoo-Team/PettingZoo)
- [edusta/gym-backgammon](https://github.com/edusta/gym-backgammon)

# GNU Backgammon

- [GNU Backgammon](https://www.gnu.org/software/gnubg/)
- [GNU Backgammon Manual](https://www.gnu.org/software/gnubg/manual/gnubg.html)

# Blog

- [Computational Backgammon](http://compgammon.blogspot.com/)
    - [How to build a backgammon bot](http://compgammon.blogspot.com/p/how-to-make-backgammon-bot.html)

# Tools

- [OpenSpiel: A Framework for Reinforcement Learning in Games](https://github.com/deepmind/open_spiel)
    - [Available games](https://github.com/deepmind/open_spiel/blob/master/docs/games.md#backgammon) - バックギャモンが実装されている
    - [arXiv](https://arxiv.org/abs/1908.09453)
- [Coach](https://intellabs.github.io/coach/index.html)
- [Ray](https://docs.ray.io/en/latest/index.html)
- [OpenAI Spinning Up](https://spinningup.openai.com/en/latest/index.html)

# 書籍

- [強化学習アルゴリズム入門: 「平均」からはじめる基礎と応用](https://www.amazon.co.jp/%E5%BC%B7%E5%8C%96%E5%AD%A6%E7%BF%92%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E5%85%A5%E9%96%80-%E3%80%8C%E5%B9%B3%E5%9D%87%E3%80%8D%E3%81%8B%E3%82%89%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E5%9F%BA%E7%A4%8E%E3%81%A8%E5%BF%9C%E7%94%A8-%E6%9B%BD%E6%88%91%E9%83%A8-%E6%9D%B1%E9%A6%AC/dp/427422371X) - お友達のオヌヌメ(私は読んでいない)
- [Reinforcement Learning: An Introduction](http://incompleteideas.net/book/the-book-2nd.html) - TD-Gammonがアプリケーションの例として紹介されている
- [Deep Reinforcement Learning with Python - Second Edition](https://www.packtpub.com/product/deep-reinforcement-learning-with-python-second-edition/9781839210686)
    - [レポジトリ](https://github.com/PacktPublishing/Deep-Reinforcement-Learning-with-Python)
- [Mastering Reinforcement Learning with Python](https://www.packtpub.com/product/mastering-reinforcement-learning-with-python/9781838644147)
    - [レポジトリ](https://github.com/PacktPublishing/Mastering-Reinforcement-Learning-with-Python)
- [Deep Learning and the Game of Go](https://www.manning.com/books/deep-learning-and-the-game-of-go)
    - [レポジトリ](https://github.com/maxpumperla/deep_learning_and_the_game_of_go)
STM32F103C8のArduinoでOLED,OLED096UNO-AでABC defgを表示


X何らかの方法でArduinoを起動出来る様にしておく。
X PA6(SCL),PA7(SDA)を接続

1.u8g2ライブラリーをインストール

2.ソースの例から16x16Fontを選択

3.まるまるを選択

4.コンパイル

5.ABC defgが表示される

6.おわり

注意　大幅に省略


![l_ay_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/83732d5e-c771-229e-e28c-16ccea286aa8.jpeg)

![l_ay_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/81530d19-abdd-5db9-ee98-af1c1be15d89.jpeg)

![103_oled_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/06f31ef1-61bc-6fb3-0db6-9e5f2cfa301d.jpeg)

![103_oled_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f530f98e-a521-1d58-7edb-5e0903e1b3c9.jpeg)

![103_oled_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/2a04c518-a7ab-07a4-9ccf-fe80463e84fb.jpeg)
filterの使い方について簡単にまとめる


filterは配列のデータでいらないものを除去したりする際に使います。

使い方としてはこんな感じ

配列を取得

配列をfilterする

プログラムだとこんな感じ

let data: [テーブル名]　= テーブルを取得する関数

data.filter({$0.レコード名 == 値})

$0　←　これはなんだと思う人が多いと思うんですが、

簡単に言うとテーブル名です。

なのでdata.filter({$0.レコード名 == 値})は日本語で伝えると

データ.フィルター({テーブル名のレコード = 値})

ループで回してifで値を追加していくみたいな処理も全然ありなんですけど、結構ソースも見づらいしループだらけで結構処理も重くなってしまうんですよね。

なんでfilterを使いこなせるようになると割と便利かもです。

とはいえ、いきなり初学者が覚えられるかと言われると割と難しいので、実践などを通してあーこういうことね

なんて思えるようになればいいかなと思います。
関数結果をキャッシュして使う(functools.lru_cached)(Python)

#概要
関数結果をキャッシュしたい時に、functools.lru_cachedを使えば良い。

自前で作らなくても大丈夫かもしれない。
#内容
##環境
macOS Catalina
Python 3.7.0
##全体像
```Python:fibo.py
import functools

@functools.lru_cache(maxsize=None)
def factorial(n):
    print('in', n)
    return n * factorial(n-1) if n else 1


print('fac 5', factorial(5))
print('fac 3', factorial(3))
print('fac 12', factorial(12))
```
```:output
in 5
in 4
in 3
in 2
in 1
in 0
fac 5 120
fac 3 6
in 12
in 11
in 10
in 9
in 8
in 7
in 6
fac 12 479001600
```
同じ引数は2度評価されていないことが分かる。
##解説
> lru: least recently used

最近使ったものだけを`maxsize`までキャッシュする。
`maxsize=None`とすると、全てキャッシュされる。

##蛇足
wrapにより、以下のメソッド・属性が追加される。
- `factorial.cache_info()`：maxsizeやcache済数などを示す
- `factorial.__wrapped__`：wrap前の関数。cache回避や別のwrapに有用。
- `factorial.cache_clear()`：cacheを削除する
- `factorial.cache_parameters()`：3.9以降で使用可能。dictで返す。

#参考にさせていただいた本・頁
- https://docs.python.org/3/library/functools.html#functools.lru_cache
- https://docs.python.org/ja/3/library/functools.html

#感想
便利！使えそう。
#今後
使っていきたい。
ngrokの代わりに「tunnelto」を使ってローカルのHTTPサーバに外からアクセスする

:::note warn
2022/7/22現在、公式のホスティングサービスでは無料版がなくなり$2のプランのみになっているようです。
:::

私は普段、LINEのbotを開発したりもしていますが、ローカルで動いている開発中のWebアプリで外部サービスからのWebhookを受け取りたい場面がよくあります。そういうときに使われる有名なツールに [ngrok](https://ngrok.com/) があり、HTTPSも使えて大変助かるのですが、私が使っていて不満を感じていたのは、

- 動作が重い
  - リージョン指定すると多少マシにはなりますが、それでも重い…
  - 最近は改善されているかも？
- 無料版ではサブドメインを指定できない
  - お金払えば済む話ではありますが、それだけのために月$5払うのはちょっと…

といった点です。他のツールだと [serveo](https://serveo.net/)（2021/03/05現在使えなくなっちゃったんですかね？）や [localhost.run](https://localhost.run/) を使ったことがありますが、少し前に [tunnelto](https://tunnelto.dev/) というツールに乗り換えました。

https://tunnelto.dev/

私が使っていて良いと感じるのは、

- 気にならない程度に動作が軽い
- 2021/3/5現在、無料版でもサブドメインを指定できる
  - __サインアップが必要です__
  - 他の人に予約されているドメインは指定できません
  - 月$2払えば、50個のサブドメインを予約できます

といった点です。簡単に導入できるので、早速インストールして使ってみましょう🏃‍♂️💨

# インストール

[公式サイト](https://tunnelto.dev/#download)にインストール方法が載っています。Macを使っている方はHomebrewでインストールできます。

```
$ brew install agrinman/tap/tunnelto
```

# アクセスキー登録

サインアップするとアクセスキーが発行されます。そのアクセスキーをローカルに設定します。

```
$ tunnelto set-auth --key YOUR_ACCESS_KEY
```

```:実行結果
Authentication key stored successfully!
```

アクセスキーは `~/.tunnelto/key.token` に保存されます。

# 実行

例として、ローカルのHTTPサーバが8080番ポートを使っていてmokichidevというサブドメインを使いたい場合、以下のコマンドを実行します。

```
$ tunnelto -p 8080 -s mokichidev
```

```:実行結果
(省略)

⣷ Success! Remote tunnel created on: https://mokichidev.tunnelto.dev
=> Forwarding to localhost:8080
```

表示されている通り、 https://mokichidev.tunnelto.dev で外部からローカルのHTTPサーバにアクセスすることができます。HTTPSにも対応していて良いですね✨

# 最後に

今回は公式のホスティングサービスを使いましたが、tunneltoはRust製のOSSで、サーバも自分でホスティングできます。私は今のところ公式のものを使っていますが、READMEに方法が載っているので、社内の制約等で必要な方は自分でホスティングしてみてください。

https://github.com/agrinman/tunnelto
GitHubActionsのデフォルトのPHPバージョンが8なの知らなくてテスト落ちまくった話

## 使用したライブラリ

こちらのライブラリを使用しました。

https://github.com/facebookarchive/php-graph-sdk


## `composer require facebook/graph-sdk`して、色々処理を書いてGitHubにpushすると、GitHubActionsでテスト落ちた...

静的解析とかテストとか全部同じエラーが出ていました。

```
Run composer install --prefer-dist -q --no-ansi --no-interaction --no-scripts --no-progress
composer install --prefer-dist -q --no-ansi --no-interaction --no-scripts --no-progress shell: /usr/bin/bash -e {0}

Your lock file does not contain a compatible set of packages. Please run composer update.
Error: Process completed with exit code 2.
```

`composer install`する所でエラー出ているようです。

```yml:.github/laravel.yml
 - name: Install Dependencies
        run: composer install --prefer-dist -q --no-ansi --no-interaction --no-scripts --no-progress
```

一度、`composer.lock`を削除して`composer update`しましたが、直りません...涙


## そもそもGitHubActions内のPHPのバージョンは？？

PHP8でした...!

https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md#php

手元のプロジェクトではPHP7.4を使用していました。
手元のPHPのバージョンをPHP8にあげてみて、`composer install`を実行してみるとGitHubActionsのエラーを再現することができました。

## このライブラリはPHP8をサポートしていなかったよ..

最終更新されたのが2年前で、PHP8のサポートもされていないことが原因でした。

https://github.com/facebookarchive/php-graph-sdk/issues/1217

## GitHubActions内で使用するPHPバージョンを指定すると、通りました！

```yml:.github/laravel.yml
runs-on: ubuntu-latest
steps:
  - name: Checkout
    uses: actions/checkout@v2

# PHP7.4を使うように指定
  - name: Setup PHP 7.4
    run: sudo update-alternatives --set php /usr/bin/php7.4
```

## 参考文献

https://zenn.dev/306/articles/e71ba4c8b2dcfa
Tableau Publicで曜日別折れ線グラフを作る（新型コロナ集計）

**Tableau Public**（フリーで利用可能）は、まだ使い慣れていませんが、機能を見たところ、保存したファイルからのデータをインポートする使い方が主体となります。
Googleスプレッドシートを使えるので、スプレッドシート経由でWeb上のデータにアクセする手段は取れるでしょう。
[有償版](https://www.tableau.com/ja-jp/products/desktop)だと、より多くのデータソースと接続できたり、ローカルに作業ファイルを保存できたりします。

まず、以前準備した[データ](https://qiita.com/text_owleyes_0214/items/5f8a12a25638fecfeae0)を**Power Query（Excel）**を使って更新します。
取り込みに使ったデータは、[NHKが公開している新型コロナウイルスの陽性者と死亡者数推移のデータ](https://www3.nhk.or.jp/news/special/coronavirus/data-widget/)です。

<img width="500" alt="Tableau Public1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/648be547-9fba-5a0b-dccb-ceb1a64d6423.png">

保存して閉じます。
（開いたままだとTableauからインポートできないようです）

##Tableauからインポートします

Tableau Publicを立ち上げます。
Excelデータをインポートします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/a32abe81-d45b-d6d8-a157-397468e6a00f.png)


ワークシートに移動します。

<img width="500" alt="Tableau Public3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/8dbb8616-c3b7-ba65-76bd-7d3ee9641213.png">

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/9ad1be7c-449b-01a8-8f0d-c4348fc44aa0.png)


##Tableauで折れ線グラフを作ります
左パネルの**「日付」**を右上の**「列」**にドラッグします。

<img width="500" alt="Tableau Public5" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/e9f6bb66-0872-a855-0964-a35f84fd2cda.png">

同様に**「国内の感染者数・・・」**をドラッグします。

<img width="500" alt="Tableau Public6" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/7ec5c7c9-7c95-c911-738a-fe09fa24621d.png">

自動的に折れ線グラフが選択されますが、x軸に**「2020」「2021」**しか表示されません。
画面上**「列」**の右側をクリックします。

<img width="500" alt="Tableau Public7" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/8e6cb185-f9fd-a9e3-8f79-5add87994867.png">

<img width="500" alt="Tableau Public8" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/2b370d5e-4817-df40-9c86-edc235647776.png">

**「日」（2015年5月1日）**を選択します。

<img width="500" alt="Tableau Public9" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/d9a3c43a-4fd4-e22a-dfbe-79a55a966099.png">

x軸の粒度が変わります。

<img width="700" alt="Tableau Public10" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/57b5517f-bda9-04d7-7ff7-23d2e295c9dd.png">

##曜日別にグラフを分けます
左パネルの**「曜日」**フィールドを、隣の四角が並んだI/Fの下部分にドラッグします。

<img width="300" alt="Tableau Public11" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/f75d74d8-c4e5-ac32-179f-62f5a23f4f67.png">

曜日ごとの折れ線グラフに変わります。

<img width="800" alt="Tableau Public12" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/ad487033-d3bd-ed44-adb2-ffe4441f0f32.png">

先ほどドラッグした項目の左側をクリックします。

<img width="500" alt="Tableau Public13" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/69c6e81d-515e-9063-dc9a-347d617f54f3.png">

**「色」**を選択すると、曜日ごとに色が分かれます。

<img width="800" alt="Tableau Public14" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/2b71d4c8-d3e4-af0a-1078-f973a898efd0.png">

**「ファイル」→「Tableau Publicに保存」**をします。
Tableau Publicの場合、データはクラウド上に保存されます。

**了**
Djangoでmigrationsができないときの解決策

# 前提

Djangoを使っていると、DBに変更を反映するため
``python manage.py makemigrations``
``python manage.py migrate``
が必要になります。

そんなとき、``python manage.py makemigrations``はできたけど
<b>DBにマイグレーションができない！！！</b>
なんてことがあるのではないかと思います。

そんな時の解決策


#状況
Herokuを使っていた時のこと。
まずは、gitを使ってherokuにpushしました。
``git push heroku master``
ここまでは、**成功**。

続いて、localでは``migration``ができたのでHerokuでも同じように実施しようとしました。
（herokuでは``（makemigrtationsを行った際に生成される）migration ファイル``は既にherokuに送られているため）

しかし、はじかれてしまう。
僕の場合は、ターミナル（コマンドプロンプト上で）
``ValuEerror: invalid literal for int() with base 10: ''”``
もしくは、サイトにアクセスして新規のmodelにアクセスしようするときは、
``relation "****" does not exist LINE 1: SELECT COUNT(*) AS "__count" FROM "Atlus_predicts"``
が出てきました。

DBはpostgreSQLです。

んで、どうすればいいかわからずdbをリセットしてしまう方もいましたが、今回は諸事情によりそれは絶対にできない。。

#対処方法

migrationは、各アプリごとに管理されています。
<b>まずどこまでがすでに``migrate``されているのか明確にしましょう</b>

コマンドとしては、

```
python manage.py showmigrations
```
（heroku上のファイル操作であれば、``heroku run``は先頭につける必要がある。）
そうすると

```terminal
 [X] 0001_initial
 [X] 0002_introduction_privacy
 [X] 0003_introduction_privacy
 [X] 0004_statement
```
こんな感じのが表示されると思います。

この時、``[X]``がついてる場所はマイグレーションができています。
どこかでエラーが出ているのか、まず明確にしましょう。

んで、例えば

```
 [X] 0001_initial
 [X] 0002_introduction_privacy
 [] 0003_introduction_privacy
 [] 0004_statement
```

``0003_introduction_privacy``が原因だとしましょう。

そうしたら、僕は、まず``0001_initial``にマイグレーションをした状態に戻したいと思います。

コマンドとしては、

````
python manage.py migrate <アプリケーション名> 0001_initial
```

です。そして改めて``python manage.py showmigrations``をします。
そうすると

```
 [X] 0001_initial
 [] 0002_introduction_privacy
 [] 0003_introduction_privacy
 [] 0004_statement
```

マイグレーションが戻されることが確認できました。（ロールバックと言うそうです。）

んで、原因は``0003_introduction_privacy``でした。
一度、**それに対応するマイグレーションファイルと.pycファイルを削除しました。**
ここでは、``0002_introduction_privacy``から``0004_statement``まで全部削除しました。

そうして、もう一度

```
python manage.py makemigrations
```
からの

```
python manage.py migrate
```
後は、これをコミットしてheroku上でマイグレーションするだけです。


#おさらい
コマンドベースでおさらいします。

```
python manage.py showmigrations #エラーファイルを明確化
python manage.py migrate <アプリケーション名> <マイグレーションファイル名>　#マイグレーションファイルをロールバック
*******   関係するマイグレーションファイルを削除（マイグレーションファイルを適用していないファイル）  *******
python manage.py makemigrations　#改めてマイグレーションファイルを作成
python manage.py migrate　#今度こそマイグレーションさせる
```


#原因
なぜ、このようなことが起こりこの手の手法でよくなったのかは正直わかりません。
しかし、こまめにmigrateしたりしているうちに依存関係に問題が出たりしたのではないかと考えています。
一度、問題が出る直前まで戻りこまめに変更していたマイグレーションファイルを一気通貫で行うことで修正できたのかな？
ex.
変更①->変更②->変更③
から
変更①->変更③
(実質的に②はいらないし、エラーの原因だから？)

的なイメージ？？
shell変更の仕方

# ターミナルからshellを変更するやり方

## 起動シェルを確認

```
echo $SHELL
```
### 結果

```
/usr/local/bin/fish
```

この場合fishを使っていることがわかる


## シェル一覧を呼び出す
```
cat /etc/shells
```
### 結果

現在このPCに入っているshellの一覧が表示される

```
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/usr/local/bin/fish
```


## 起動シェルの変更
シェル一覧の中から起動したいshellをコピペする.
下記はbashに変更したい時の場合

```
chsh -s /bin/bash
```
Amazon EC2 Macインスタンスを開発環境として使用したときのメモ

1週間ほど数十人が使用するためのmacOSの開発環境を、
Amazon EC2 Macインスタンスで構築運用したときのメモ


#### 環境
- リージョン：オハイオ
- Macインスタンス数：8台
- 専有ホストのインスタンスファミリー：mac1

#### 感想
##### オペレーション関連
- Macインスタンスを停止もしくは終了すると、その専有ホストが最高3時間ほどpendingになる  
pending中は専有ホストのリリースはできない
- Macインスタンスを再起動すると、正常に接続できるようになるまで10~30分ほど要する
- イメージ(AMI)の作成、復元は通常のLinux, Windowsと同様に可能
- VNC接続のログイン画面で固まる場合は、"sudo plikk loginwindow"のコマンドを実行すると治る
- EBSボリュームの拡張時は[こちら](https://qiita.com/mugmug/items/afff12409112b3e742af)の記事が参考になった

##### パフォーマンス・仕様等
- WindowsクライアントからMacインスタンスへのVNC接続(画面共有)が重く、SSH接続せざるを得なかった
- 当初シンガポールリージョンでの構築を予定していたが、当リージョンでのMacインスタンスのクォータが1台⇒5台までしか緩和されなかった  
理由としてはMacインスタンスの使用実績が少なかったため、とのこと  
そのためクォータが10台まで緩和されたオハイオリージョンで構築した
- VNC接続のためのクライアントツール VNC ViewerでVNC接続する際に、全画面モードにする方法がわからず操作しづらかった
- (Macインスタンスに限った話でないが)距離的に離れているため、SSH接続時のコマンド入力等でレイテンシが感じられた
Ubuntuの自動アップグレードをOFFにする設定

いつも検索してしまうのでメモ。。

参考元
https://linuxconfig.org/disable-automatic-updates-on-ubuntu-20-04-focal-fossa-linux

このファイルの値を1->0に書き換える

```/etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Unattended-Upgrade "0";
```

コマンドでの設定方法
`dpkg-reconfigure unattended-upgrades`
PHP 配列の扱い、foreachについて

#PHPの配列についてのメモ


```php


$arr = ['算数','国語','社会'];
// var_dump($arr);
// $arr['理系'] = '政治';

// var_dump($arr);
$arr[]= 'hoge';//インデックスに追加出来るpushみたいな感じ
// var_dump($arr);

foreach($arr as $key){//出力：算数国語社会hoge
  echo $key;
}

foreach($arr as $key =>$value){//出力：{0算数1国語2社会3hoge
  echo $key;
  echo $value;
}

foreach($arr as $key =>$value){//出力：{0123
  echo $key;
}
```


##上記の説明

配列は```$arr = [];```や```$arr = ['算数','国語','社会'];```のように定義した後
```$arr[] = 'hoge';```とするとJSでいうpushしたようにインデックスの３番目にhogeを入れられる。

##forecachの説明
配列のkeyを設定している時は```foreach($arr as $key =>$value){}```の$keyでキーの値を出力し、valueで値を出力出来る。
$valueを設定しない場合asの後に設定した変数で($key)で値を出力出来る。
Docker Compose ECSデプロイを試す

## はじめに

この記事の環境は以下のGitHubにあります。
https://github.com/bocci-farm/docker-rails

## AWSにテスト環境を構築

テスト環境用のVPC, パブリックネットワーク, ECRリポジトリを作成します。 

```console
% cd terraform
% terraform init
% terraform plan
% terraform apply
% cd -
```

## ECR用のdocker-compose.ecr.ymlを作成

envsubstを使ってテンプレートから実ファイルを作成します。
ここではECRを使っていますが、通常のDockerHubでもECSデプロイは可能です。

```console
% export AWS_ACCOUNT_ID=$(aws sts get-caller-identity | jq -r '.Account')
% export AWS_VPC_ID=$(aws ec2 describe-vpcs --filters 'Name=tag:Name,Values=example' | jq -r '.Vpcs[].VpcId')
% envsubst < docker-compose.ecr.yml.envsubst > docker-compose.ecr.yml 
```

## Dockerイメージをビルド

```console
% DOCKER_BUILDKIT=1 COMPOSE_DOCKER_CLI_BUILD=1 docker-compose -f docker-compose.ecr.yml build --build-arg RAILS_MASTER_KEY=<RAILS_MASTER_KEY>
```

## DockerイメージをECRへプッシュ

```console
% aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
% docker-compose -f docker-compose.ecr.yml push
```

## Docker Contextを作成

context名、プロファイルは環境に合わせて指定してください。

```console
% docker context create ecs bocci-ecs --profile bocci-farm
```

## ECSへデプロイ

```console
% docker compose --context bocci-ecs up -f docker-compose.ecr.yml  # しばらく待ちます
```

## 確認

すべてのサービスのSTATEがRunningになっていることを確認。

```console
% docker compose --context bocci-ecs ps
NAME                                                 SERVICE             STATE               PORTS
task/docker-rails/19ce049d7e8f48b499200544ea94c5d4   app                 Running
task/docker-rails/2cdc1ad531744f1b8070e851f896347a   web                 Running             docke-LoadB-1W7QCVZLGWYJX-630195466.ap-northeast-1.elb.amazonaws.com:80->80/http
task/docker-rails/97497a911a0247cfba86e3fe7278ece4   db                  Running
```

ブラウザから確認します。(URLは上記コマンドのwebサービスのPORTS欄にあります)
50xエラーになる場合は、LBの設定がまだ終わっていないかもしれないのでAWSコンソールより確認する。
大体はしばらく待てば解消されると思います。

http://docke-loadb-1w7qcvzlgwyjx-630195466.ap-northeast-1.elb.amazonaws.com
![スクリーンショット 2021-03-05 18.10.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177074/2689bf01-66ef-c77e-682b-68e378cf005f.png)

## 後片付け

```
% docker compose --context bocci-ecs down
% terraform -chdir=terraform destroy
```

以上
Windows PCでGit管理(git init --bare)

私がGitだ。

# やりたかったこと
チームで使ってるちょっとしたスクリプトってあると思います。
気軽にRepositoryを作れるGitHub環境や共有サーバにGitBucket等が立っている方はそこで管理できますが、
そうでもないときに、本当にちょっとしたツールを管理したいと思ったのでごにょごにょすることにしました。

Dockerあるじゃん。
その通りです。
GitBucketやGitLabを立てれば、ブラウザで開いてREADMEを読んだりすることもできます。
（本記事の手順ではCLI(GitBash等)でしか見れません）
ただ、ディスクの永続化を考えたり、(想像ですが)メモリ・CPUをなるべく食ったりしない方が嬉しいなと思いこれもアリかなと思いました。

正直推奨はしません。手段の１つです。

# 免責事項
本記事の手順に関するトラブルについては一切の責任を取りません。
特に途中で、Windows PC上のフォルダを共有化する手順がありますが、共有範囲は十分に検討した上で各自の自己責任で設定してください。

# 環境
* Windows10
* GitBash

# 構築手順
## Repositoryを作る
Repositoryとなる任意のフォルダ(例: `C:¥¥git¥XXX_team¥repository` )を新規作成します。
この時、フォルダ名に `.git` をつけると情緒を感じることができます。

```GitBash.
$ mkdir /c/git/XXX_team/repository
```

次に、作成したフォルダをエクスプローラで開いてプロパティから共有化してください。（チームメンバが参照できるようにする）
【★免責事項をご確認ください！！】

そして、そのフォルダをGitのRepository化します。

```GitBash.
$ cd /c/git/XXX_team/repository
$ git init --bare --shared=true
Initialized empty shared Git repository in C:/git/XXX_team/repository/
```

## 資材をRepositoryに入れる
既にある資材(例: `C:¥¥work¥benri-tool` )を作ったRepositoryに格納します。

```GitBash.
$ cd /c/work/benri-tool
$ git init
$ git add .
$ git commit -m "first commit" // 任意のコメントをつけてください。
$ git remote add origin "C:¥git¥XXX_team¥repository" // ダブルクォーテーションを忘れずに
# git push -u origin master
(前略)
To C:¥¥git¥XXX_team¥repository
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
```

# みんなで使う
チームメンバのPCからCloneしましょう。

```GitBash.
$ git clone file://${PC名}/git/XXX_team/repository
```
【CodePipeline】エラー対処法: unexpected error: The container <container-name> does not exist in the task definition. 

CodePipelineで以下のようなエラーがでた場合の対処法について。

>The ECS service cannot be updated due to an unexpected error: The container <container-name> does not exist in the task definition. 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/0c1facb5-87ca-9bfd-c5de-7316b98c0d1e.png)


##エラー内容
問題が発生してECSをアップデートできない。taskdefinitionの中に指定されたコンテナ名がないとの指摘。


##原因
appspec.ymlファイルで指定したcontainer nameが間違っている（stgのコンテナ名を指していた。）


##対処法
appspec.ymlのcontainer nameを修正して完了。

下記の`ContainerName: "sample-website"`の部分。

```yml:appspec.yml
version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          ContainerName: "sample-website"
          ContainerPort: 80
```
Nginx のリバースプロキシーで、WebSocket を通す設定

こちらのページに書いてあることです。
[NGINX as a WebSocket Proxy](https://www.nginx.com/blog/websocket-nginx/)

```text
server {
(省略)
#
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
#
(省略)
}
```

Ubuntu で確認しました。
【Ruby】変数と定数のあれこれ

<h2>Rubyの変数や定数とは？</h2>
Ruby学習をしている中で、変数や定数の書き分けに混乱したのでまとめてみた。

【ポイント】
・変数や定数は以下のように<b>宣言</b>と<b>代入</b>を同時に行う。
・変数名はスネークケースで書くことが一般的とされる。
・宣言された変数(定数)をスコープ内で呼び出して使用する。

```Ruby
# 数値
変数(定数)名 = 数値

変数(定数)名 = 数値 + 数値

# 文字列
変数(定数)名 = '文字列'

# 呼び出す
puts 変数名
puts "文字列#{変数名}文字列"

```

上記のように代入された変数を呼び出して使用する。

<h2>変数の種類と使い方</h2>
Rubyでは<b>変数名の最初の一文字によって以下の変数/定数に区別</b>される。

・ローカル変数
・インスタンス変数
・クラス変数
・グローバル変数
・定数

*上記以外にも疑似変数などがあるが、今回は割愛。

各変数の主な違いは<b>「変数名の最初の一文字」</b>と<b>「スコープ*」</b>である。
*スコープ … 変数の有効範囲のこと。スコープ外では変数を参照できない。


<h2>ローカル変数</h2>
小文字もしくは'_'(アンダーバー)で始まる変数を「<b>ローカル変数</b>」と呼ぶ。 (*ASCII2の範囲外では変数名に漢字などを使える）
有効範囲(<b>スコープ</b>)は　宣言されたブロック、メソッド内、クラス/モジュール内のみ。一度有効範囲を抜けると消滅する。

```Ruby
# 「name」という変数に"Taro"という文字列を代入して変数を宣言
name = "Taro"

# 変数nameの呼び出し
puts name
#=> Taro

# 式展開*
puts "私は#{name}です。"
#=> 私はTaroです。
```
*式展開: #{変数名}という形で、ダブルコーテーションに囲まれた文字列の中に記述することで変数に格納されている値が文字列の中で展開される。


<h2>インスタンス変数</h2>
@で始まる変数を「<b>インスタンス変数</b>」と呼ぶ。
インスタンス変数は特定のオブジェクト(クラス)に所属している。
有効範囲は基本的に<b>所属しているオブジェクト内部のみ</b>だが、<b>ゲッター/セッターメソッド</b>を使うことで外部から読み書きすることができるようになる。

```Ruby
class Menu #~~~~~インスタンス変数のスコープ~~~~~
  
  # 外部から @food を呼び出せるようにする
  attr_reader :food
  
  # インスタンスを初期化するときに使う(ことが多い)initializeメソッド
  def initialize(food)
    # メソッド内でインスタンス変数を宣言/代入
    @food = food
  end

  def order
    puts "#{@food}食べたい"
  end
end #~~~~~インスタンス変数のスコープ~~~~~


# インスタンスの作成
menu = Menu.new('そば')

# orderはクラス内で定義されているメソッドなのでゲッターがなくても呼び出せる
menu.order
#=> "そば食べたい"

# ゲッターメソッドを使ってスコープ外からインスタンス変数 "@food" を呼び出す
menu.food
#=> "そば"

```


<h2>クラス変数</h2>
@@で始まる変数を「<b>クラス変数</b>」と呼ぶ。
クラス内で定義する。
有効範囲は<b>定義したクラス内のメソッドと継承したサブクラス、インスタンス</b>である。
主にインスタンスに番号をつけたいときに使ってます。
＊正直それ以外に思い浮かばなかった。。

```Ruby
class Menu 
  # クラス内のメソッド外で宣言/代入
  @@count = 0

  def initialize(food)
    @food = food
    # 1つインスタンスが作成される毎に@@countには+1代入される
    @@count += 1
  end

  def get_count
    @@count
  end
end

# インスタンス作成
menu1 = Menu.new('そば')
menu2 = Menu.new('うどん')

print("作成されたメニューの数:", menu1.get_count)
#=> "作成されたメニューの数: 2"
```

<h2>グローバル変数</h2>
$で始まる変数を「<b>グローバル変数</b>」と呼ぶ。
*$で始まる特殊変数(いわゆる組込変数)の場合もあるので注意

有効範囲はプログラム全体。
どこからでも読み書きが可能 → 知らない間に変数が書き換わっている可能性があるため、扱いには注意が必要。

```Ruby
$food = "そば"

puts $food
```


<h2>定数</h2>
アルファベット大文字で始まる識別子
(例: Xxx, XXx XXX)
・メソッド内での定義ができない
・一度定義した定数に再び代入を行おうとすると警告メッセージが出る（更新はされる）


```Ruby
# 軽減税率8%を定数に代入
REDUCED_TAX_RATE = 1.08

def calculation(price)
  puts (price * REDUCED_TAX_RATE).floor
end

# 引数：1,000円の
calculation(1000)
#=> 1080
```

<h2>まとめ</h2>
・各変数の違いは記述方法と有効範囲（スコープ）
・インスタンス変数をクラス外で呼び出したい場合はゲッターメソッドを使う
・変数/定数を効果的に使うことで柔軟かつスッキリした見た目にできるが、変数名選びがすごく重要。

<h2>参考</h2>
・Rubyリファレンスマニュアル
https://docs.ruby-lang.org/ja/latest/doc/index.html
M1 MacでVidual Studio Codeが重い問題の解消

# M1 MacBook ProでのVidual Studio Codeがどうにも重い
## 結論
Apple Siliconに最適化されたVidual Studio Code Insidersをインストールすれば解決した。

どうやら、MicrosoftがApple Siliconに対応したversionをリリースしたそうだ。

https://code.visualstudio.com/insiders/

## 追記 (2021/3/05)
こちらの記事にコメントして下さった方が以下の記事を教えてくださいました。
ありがとうございます！
https://applech2.com/archives/20210305-visual-studio-code-v1-54-now-support-apple-silicon.html

`
Microsoftは現地時間2021年03月04日、オープンソースのコードエディタ「Visual Studio Code (以下、VS Code)」の最新バージョンとなるv1.54をリリースし、同バージョンでApple M1チップ搭載のMacでネイティブ動作するApple Silicon Buildが安定版となったと発表しています。
`

2021/03/04に正式版がリリースされたそうですね💦
お騒がせしました。
WSLからファイルをWindows側のブラウザで開く (cargo doc --openする)

#動機
wslで`cargo doc --open`したときにブラウザで開くようにしたかった。

#試行錯誤

https://doc.rust-lang.org/cargo/commands/cargo-doc.html#documentation-options

ここからBROWSER環境変数にいれてやればいいとわかる。

https://superuser.com/questions/1262977/open-browser-in-host-system-from-windows-subsystem-for-linux

wslって.exe開けるのを初めて知った。これで./bashrcを書き換えて終わり..ではなかった。
firefoxは起動するが、対象のページを開いてくれなかった。これは、firefoxに送られるpathがlinux側のものなのでwindows用に変換しなければならない。ただ頭にubuntuの場合は`file://///wsl$//Ubuntu`を足せばいい。BROWSER環境変数にshellファイルを入れてそれを経由して呼び出した。

#やり方
```shell:open_browser.sh
#! /bin/bash
#firefox
/mnt/c/Program\ Files/Mozilla\ Firefox/firefox.exe $(wslpath -w ${1})
#chrome
#/mnt/c/Program\ Files\ \(x86\)/Google/Chrome/Application/chrome.exe $(wslpath -w ${1})
```
```shell:~/.bashrc
# xxxにshellスクリプトのディレクトリを入れる
export BROWSER='xxx/open_browser.sh'
```
これでwslから`cargo doc --open`したときにブラウザでdocが開くようになった。
~~chromeの場合開いている間cargo docが終わらないのが少し気になったが…~~
最初からブラウザを開いていると終わってくれるようだ

# 追記1
wslpathコマンドというものがあるようなので修正
ブラウザが閉じないことに対する追記

# 追記2
いつの間にかcargo docでは解消されていた。
https://github.com/rust-lang/cargo/issues/7557
attr_readerについて

　以下のコードにつき、rubocop -aを実行したところ、修正を頂戴しました。

```ruby:app/helpers/question_helper.rb
class AddQuestion
    
  def initialize(a,b)
    @text = "#{a} + #{b}" 
    @answer = a + b
  end

# rubocop -a 実行前 -------------------------------   
  def text # ゲッター
    @text
  end
  
  def answer # ゲッター
    @answer 
  end
# rubocop -a 実行前 -------------------------------

# rubocop -a 実行後 -------------------------------
  attr_reader :text, :answer
# rubocop -a 実行後 -------------------------------  

end
```
　attr_readerとはなんだろうかと思い調べてみました。

クラスに設定したインスタンス変数の値を、インスタンスから読み取って表示するためだけに定義するメソッドを`ゲッター`といい、`attr_reader`を用いてこれに代えることができるとのこと。
　
　なお、ここでは登場しないが、あるインスタンスが持つインスタンス変数の値を更新するためだけのメソッドのことを`セッター`といい、これは`attr_writer`で記述することができる。
　さらには、`attr_accessor`は両者を兼ねる。

　　
　rubocop実行前後を見比べると勉強になります。
gcloud 事始め

## いざgcloudの世界へ


まず、どこのプロジェクトを使っているのかを調べることが重要です

```
gcloud auth list
```

でどこのプロジェクトがアクティブになっているか確認してください。

次は、サービスアカウントでログインします。個別でログインする`gcloud auth login`でログインする方法もありますが、プロジェクトで複数人で開発するかつ、自分でサービス権限を制御できる環境であれば、サービスアカウント推奨です。ちなみにサービスのjsonキーを取得するには、
「左メニュー>APIとサービス>認証情報>サービスアカウント」より発行できます。

```
gcloud auth activate-service-account <サービスアカウント> --key-file=<サービスのキー>.json
```

もう一度 `gcloud auth list`を入力して、設定したサービス名に「*」がついていれば、対象のアカウントに入れたことになります。

次にプロジェクトです

```
gcloud config set project <プロジェクト名>
```
で設定できます。

設定後は、設定以下で確認しましょう

```
gcloud config configurations list
```


bigqueryなどにアクセスする場合(macなどの場合)

```
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json"
```
LaravelのデフォルトログインフォームにreCaptcha v3を付ける

以下の組み合わせの情報が中々見つからなかったので。

* Laravelのデフォルトのログインフォーム
* [ARCANEDEV/noCAPTCHA](https://github.com/ARCANEDEV/noCAPTCHA/blob/master/README.md)
* reCaptcha v3
* 2分間でトークンの有効期限が切れる問題の回避

使用しているのはLaravel8です。

ARCANEDEV/noCAPTCHAインストールなどは他のサイトにも情報があるため割愛し、ここではLaravelのファイルにどう記述するかだけを簡潔に記します。

# .envにキーを設定
NOCAPTCHA_SECRET=your secret
NOCAPTCHA_SITEKEY=your site key

#View
form内に{!! no_captcha()->input() !!}を入れ、ログインボタンにIDを付けておきます。

```/resources/views/auth/login.blade.php
           <button type="button" class="btn btn-primary" id="login_button">
                ログイン
            </button>
        </div>
    </div>
    {!! no_captcha()->input() !!}
</form>
```

同じlogin.blade.php内に以下を記述。

```/resources/views/auth/login.blade.php
{!! no_captcha()->script() !!}
{!! no_captcha()->getApiScript() !!}
<script>
$('#login_button').on('click', function (e) {
    e.preventDefault();grecaptcha.ready(function() {
        grecaptcha.execute('{{config('no-captcha.sitekey')}}', {action: 'submit'}).then(function (token) {
            $('#g-recaptcha-response').val(token)
            $('#login_form').submit()
        });
    });
});
</script>
```

#Controller
validateLoginをオーバーライドしてCaptchaのバリデーションを入れます。

```/app/Http/Controllers/Auth/LoginController.php
public function validateLogin(Request $request)
{
    $request->validate([
        $this->username() => 'required|string',
        'password' => 'required|string',
        'g-recaptcha-response' => ['required', new CaptchaRule]
    ], [
        'g-recaptcha-response.captcha'  => 'ロボットと判断されました',
    ]);
}
```

以上で動くはずです。何か記述漏れがありましたらご指摘ください。
Couchbaseコマンドラインツール couchbase-cli 解説

# はじめに

以前に、[Couchbase Server管理者が理解すべきこと](https://qiita.com/yoshiyuki_kono/items/9e41ce9d60bc2e1c1ea9)という記事を発表しましたが、その中に挙げられているような、初期構築・運用管理を実施するにあたっては、コマンドラインツールや管理用Rest APIを理解・利用し、再現性を担保することが重要です。本記事では、その手始めとして、`couchbase-cli`を使って、どのようなことが可能かを紹介します。

# 概要

`couchbase-cli`はCouchbaseのクラスタ管理のため提供されている、中心となるコマンド・ライン・インターフェースです。

基本的な構文は以下の通りです。

```
couchbase-cli <command> [options]
```

### 基本オプション
- --version
バージョン情報を出力します。

- --help (-h)
ヘルプメッセージを出力します。

## コマンド一覧

|コマンド|内容|
|---|---|
|admin-role-manage|LDAPユーザーロールを管理します。|
|bucket-compact|Couchbaseデータバケットを圧縮します。|
|bucket-create|新しいCouchbaseデータバケットを作成します。|
|bucket-delete|Couchbaseデータバケットを削除します。|
|bucket-edit|Couchbaseデータバケット設定を編集します。|
|bucket-flush|Couchbaseデータバケットのデータをフラッシュします。|
|bucket-list|すべてのCouchbaseデータバケットを一覧表示します。|
|cluster-edit|クラスター設定を編集します。|
|node-to-node-encryption|ノード間暗号化の有効化/無効化を設定します。|
|cluster-init|Couchbaseクラスターを初期化します。|
|ip-family|Couchbaseクラスターを初期化します。|
|collect-logs-start|ログ収集を開始します。|
|collect-logs-status|ログ収集ステータスを取得します。|
|collect-logs-stop|現在のログ収集タスクを停止します。|
|eventing-function-setup|Eventingサービス機能を管理します。|
|failover|クラスター内のサーバーをフェイルオーバーします。|
|group-manage|サーバーグループを管理します。|
|host-list|クラスター内のすべてのホストを一覧表示します。|
|node-init|ノードを初期化します。|
|rebalance|クラスター内のノード間でデータのリバランスを行います。|
|rebalance-status|現在のリバランスステータスを表示します。|
|rebalance-stop|現在のリバランスタスクを停止します。|
|recovery|以前にフェイルオーバーしたノードを回復します。|
|reset-admin-password|管理者パスワードをリセットします。|
|reset-cipher-suites|暗号スイートをデフォルトにリセットします。|
|server-add|サーバーをクラスターに追加します。|
|server-info|サーバーレベルの情報と統計を表示します。|
|server-list|クラスター内のすべてのサーバーを一覧表示します。|
|server-readd|フェイルオーバー後にサーバーをクラスターに追加し直します。|
|setting-alert|アラート設定を変更します。|
|setting-audit|監査ログの設定を変更します。|
|setting-autofailover|自動フェイルオーバー設定を変更します。|
|setting-autoreprovision|自動再プロビジョニングの設定を変更します。|
|setting-cluster|クラスター設定を変更します。|
|setting-compaction|圧縮設定を変更します。|
|setting-index|インデックス設定を変更します。|
|setting-ldap|LDAP設定を変更します。|
|setting-notification|通知設定を変更します。|
|setting-password-policy|パスワードポリシーを変更します。|
|setting-query|クエリ設定を変更します。|
|setting-rebalance|リバランス設定を変更します。|
|setting-security|セキュリティポリシーを変更します。|
|setting-xdcr|クロスデータセンターレプリケーション（XDCR）設定を変更します。|
|ssl-manage|SSL証明書を管理します。|
|user-manage|RBACユーザーを管理します。|
|xdcr-replicate|XDCRクラスター参照を管理します。|
|xdcr-setup|XDCRレプリケーションを管理します。|
|setting-saslauthd|saslauth設定を管理します。|
|enable-developer-preview|開発者プレビューを有効にします。|
|collection-manage|コレクションを管理します。|

# 最後に

本記事では、`couchbase-cli`を使って出来ることを把握するために、（サブ）コマンドの一覧を整理しました。今後適宜、重要性の高いものから、より詳細な内容について、紹介していきたいと考えています。

# 関連情報

https://docs.couchbase.com/server/current/cli/cbcli/couchbase-cli.html
VPCの全体像⓶(AWS)

#ルートテーブル
ルートテーブルとは、

・サブネット１つにつき１個
・サブネットから外に出る通信をどこに向けて発信するかを決めるルール
・ルートと呼ばれるルールで構成されている
・最も明確なルートが優先されて適用
(狭いIPアドレスに範囲にマッチしたルールほど、優先的に適応される)

ルートと呼ばれる１つのルールの集合体を、ルートテーブルといいます。



##ローカルルート(local route)

ローカルルートの特徴は、

・VPCの内部を示しており、VPC内の全てのリソースの通信を可能にする
・最初はlocalルートのみ格納されている
・localルートは削除できない

#インターネットゲートウェイ

続いては、VPCをインターネットと接続するためにインターネットゲートウェイを設定していきます。

インターネットゲートウェイとは、

・VPC内のAWSリソースとインターネットを繋げるもの
・自動でスケールし、可用性が高い
(アクセスが集まりすぎても、AWSが自動で分散処理をしてくれる)
・サブネットのルートテーブルで設定して使用する

##パブリックサブネット(Public subnet)

・ルートテーブルに、インターネットゲートウェイへのルーティング有
(EC2インスタンスからインターネットゲートウェイに直接アクセスできる)

・外部公開しても大丈夫なAWSリソースを置く。

##プライベートサブネット(Private subnet)

・ルートテーブルに、インターネットゲートウェイへのルーティング無
(EC2インスタンスからインターネットゲートウェイに直接アクセスできない)

・ルートテーブルに、(パブリックサブネットにある)NAT gatewayへのルーティング有

・セキュリティレベルが高いデータベースなどを置く。



##NAT

NAT gatewayとは、

・プライベートサブネットからインターネット接続を可能にする

・アウトバウンド(発信)はできるが、インバウンド(受信）はできない
(セキュリティレベルがだいぶ高まる)

NAT gatewayはインターネットゲートウェイと同様に、負荷が高まるとAWS側で自動でスケールしてくれるので、可用性が高まる。

#まとめ

パブリックサブネットのEC2インスタンスは、EC2→インターネットゲートウェイに接続。

プライベートサブネットのEC2インスタンスは、EC2→(パブリックサブネット内の)NAT→インターネットゲートウェイに接続。

*ちなみにプライベートサブネットのEC2にログインするには、一旦パブリックサブネットのEC2にログインしてから再度プライベートサブネットのEC2にログインする２段階の踏み台の形をとっています。