OmniAICreator/Qiita-1.07M huggingface dataset:
ロジックサマナー ランクC「ログの結合」を解いた

# はじめに
ロジックサマナーの問題をまた解きました。
少し AtCoder の問題解いたんですが、時間制限内に解けなくて悔しかったです。（B問題で終わりました...）

今回も正答したソースコードを下に載せます。


# 問題の概要
[問題のリンクです。](https://paiza.jp/logic_summoner/challenges/logics_skill_4004)

```
入力：
8
0 thequickbr
0 ownfoxjump
0 soverthela
0 zydog
1 jackdawslo
1 vemybigsph
1 inxofquart
1 z
出力：
0 thequickbrownfoxjumpsoverthelazydog
1 jackdawslovemybigsphinxofquartz
```
問題の概要を要約すると、入力されるのがチャットのログです。
左がチャットのIDで、右がチャットの内容として、同じIDであれば末字に結合して出力する。
といった感じです。


# 正答したソースコード
```python3
# 入力
n = int(input())
input_dic = {}
for _ in range(n):
    (id, string) = input().split()
    id = int(id)
    if (id in input_dic):
        input_dic[id] += string  # 文字列の連結
    else :
        input_dic.update({id : string})

# 出力
for id in input_dic:
    print(id, input_dic[id])
```
入力されるチャットを辞書型で管理して、新しいIDがあれば新しく辞書型のデータを作成する。
既に存在するIDであれば、文字列の末尾に加えていく。
最後に、IDごとに作成したディクショナリを出力して、終了。


# 終わりに
最近辞書型使ってなかったので、使い方とか再確認できました。
ちなみに、for文で辞書型のデータを一つずつ取り出したかったんですが、keyの部分が取り出されるようです。
てっきり、リストとか同じように取り出せると思ってました。

以上、
laravel 9 ローカルでメール送信ができなくなったときの解決方法


Laravel6からLaravel9へアップグレード対応しました。
mailtrapでも良いのですが、私はdockerでmaildevイメージからコンテナ立ててます。
メール送信できなくなったので、あれ？と思い、とりあえずマニュアル探してその通りにしていった。

https://reffect.co.jp/laravel/laravel-send-email

logにはでてるよーOKだよう。

```log
[2022-03-08 01:26:44] local.DEBUG: From: Laravel <xxx@gild.co.jp>
To: Test <abc987@example.com>
Subject: This is a test mail
MIME-Version: 1.0
Date: Tue, 08 Mar 2022 01:26:44 +0900
Message-ID: <29aba2d91dbc8133538510e01160cfe4@gild.co.jp>
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<p>=E3=83=86=E3=82=B9=E3=83=88=E3=83=A1=E3=83=BC=E3=83=AB=E3=81=AE=E9=80=
=81=E4=BF=A1=E3=81=A7=E3=81=99=E3=80=82</p>
```

じゃあdriverをsmtpに戻してmailコンテナに疎通するようにしてみるよーう。
/mailでgetアクセスしてみると...ヒーハー！

![スクリーンショット 2022-03-08 2.15.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125469/20df93cc-46d3-98a7-0e15-5deb2f3b1399.png)

まじか。
laravel6では問題なかった気がするんだけどなぁ...
ということでdockerのマウント先に、laravel6のときのリソースを参照するように、laravel9の入ってるディレクトリ名を退避させて、laravel6の入ってるディレクトリ名を変更。
で、実行してみるとmailコンテナで受信してることを確認したわけさ。

![スクリーンショット 2022-03-08 2.18.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125469/f481de7c-a0e6-39ba-c968-4efce0b537d2.png)

ってことはdockerには問題ないことがわかったので一安心。
laravel6とkaravel9とでmail周りのなにかが変わったなとそれらしいキーワードで探っていく。
そしたら、こんな記事に辿り着き、こんなんがconfig/mail.phpに必要なんだとか。

https://stackoverflow.com/questions/30556773/how-to-fix-stream-socket-enable-crypto-ssl-operation-failed-with-code-1

```
'stream' => [
   'ssl' => [
      'allow_self_signed' => true,
      'verify_peer' => false,
      'verify_peer_name' => false,
   ],
],
```

とりあえず、laravel6と9のconfig/mail.php見比べてみたけど、どっちにも上記のような記述はない。
とりあえず、まぁここらへんに記述して/mailでgetアクセスしてみるも、変わらず。

```
    'mailers' => [
        'smtp' => [
            'transport'  => 'smtp',
            'host'       => env('MAIL_HOST', 'smtp.mailgun.org'),
            'port'       => env('MAIL_PORT', 587),
            'encryption' => env('MAIL_ENCRYPTION', 'tls'),
            'username'   => env('MAIL_USERNAME'),
            'password'   => env('MAIL_PASSWORD'),
            'timeout'    => null,
            'stream' => [
                'ssl' => [
                    'allow_self_signed' => true,
                    'verify_peer' => false,
                    'verify_peer_name' => false,
                ],
            ],
        ],
```

で、最終的にこれ。

https://zenn.dev/at_yasu/articles/65a4d11ae73f27#smtp-stream-options


いや、解決の線はあってたけど配列構造が違ったみたい。
だから以下にしたらあっさり送信できたよ。

```
    'mailers' => [
        'smtp' => [
            'transport'  => 'smtp',
            'host'       => env('MAIL_HOST', 'smtp.mailgun.org'),
            'port'       => env('MAIL_PORT', 587),
            'encryption' => env('MAIL_ENCRYPTION', 'tls'),
            'username'   => env('MAIL_USERNAME'),
            'password'   => env('MAIL_PASSWORD'),
            'timeout'    => null,
            'verify_peer' => false,
        ],
```

https://laravel.com/ の方に書いてたみたいだけど、英文はわかりづらいですなぁというか見つけられん。
【Google Apps Script】初回実行時の承認画面 (2022年3月版)

# 背景

Google spreadsheet等で利用できるスクリプト、**Google Apps Script**を初めて実行する際に、承認作業が必要となる。

少し分かりにくいので、手順で整理しておく。

<font color="red">※</font> スクリプト作成者が不明・信頼できない場合は承認しないことをお奨めします。。。


# 手順

1. 「続行」をクリック。


    <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704144/a79124f7-a8ab-63bd-0696-602c5424ffda.png">



1. 実行するアカウントを選択。
    <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704144/251fc820-e0e7-1b9b-b054-5bab89f8b5fc.png">

1. 「詳細」をクリック。

    <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704144/c7935095-c4d8-9707-9ea4-e4075e5c498e.png">

1. 「〇〇〇〇（安全ではないページ）へ移動」をクリック。

    <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704144/ddec208d-0f8f-bccc-c72d-7985240f7a0a.png">


1. 求められている権限を確認し、「許可」をクリック。
    <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704144/70ea0275-7760-a3fa-165c-7403d1a026af.png">

1. スクリプトが使用可能になる。

<font color="red">※</font> 許可した直後の実行はうまく行かないことが多いので、再度実行すると良いです。
UiPathで英語表記の日時を数字表記に変換する

# やりたいこと
英語表記の日時 **"Tue, Mar 15, 2022 8:00 PM"** を
数字表記の日時 **"2022/3/15(火) 20:00"** に変換する。

# 実装方法
![フローの画面イメージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1851170/dd4b63a3-8313-ee05-b4d9-bfd547649fc8.png "英語表記の日時を数字表記に変換.png")
![変数一覧](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1851170/989c9edf-537b-f28d-6e09-66723e49a4bf.png "英語表記の日時を数字表記に変換_変数一覧.png")

## 英語表記の日時を代入
**en_text = "Tue, Mar 15, 2022 8:00 PM"**

普通にString型変数に文字列を代入しています。
実際の業務ならアプリケーション画面から「テキストを取得」で引っ張ってくるパターンとかが考えられそう。

## DateTime型に変換して代入
**dt = DateTime.ParseExact(en_text, "ddd, MMM d, yyyy h:mm tt", System.Globalization.CultureInfo.InvariantCulture)**

DateTime型のメソッド*ParseExact*を使用しています。

https://docs.microsoft.com/ja-jp/dotnet/api/system.datetime.parseexact?view=net-6.0#system-datetime-parseexact(system-string-system-string-system-iformatprovider)

第1引数には変換したい文字列、第2引数には変換したい文字列の形式を設定します。
形式の設定は以下のMicrosoftのドキュメントページが参考になるかもしれません。
他にも「vb.net 日時 形式」などで検索すればわかりやすくまとめられたページがたくさん見つかります。

https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/custom-date-and-time-format-strings

第3引数には形式のカルチャを設定します。(どの国/地域の言語使ってますか？みたいな設定です。)
今回は*System.Globalization.CultureInfo.InvariantCulture*というカルチャ依存しない設定にしています。
依存しないといっても英語に関連付けられているので、英語表記の日時をちゃんと読み取ってDateTime型に変換してくれます。

https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo.invariantculture?view=net-6.0

## 数字表記の日本語形式にして代入
**num_text = dt.ToString("yyyy/M/d(ddd) H:mm", System.Globalization.CultureInfo.GetCultureInfo("ja-JP"))**

1つ前の処理でDateTime型に変換した変数の値に対して、それを今度は数字表記の文字列にします。
*ToString*メソッドの第1引数には表示形式を設定します。前述の日時形式の設定方法と同様です。

ただ曜日に関して、今はカルチャ依存しない(=英語)の設定になっているので、そのまま"ddd"を出力すると"Tue"になってしまいます。
なので第2引数でカルチャを日本語指定にします。それが*System.Globalization.CultureInfo.GetCultureInfo("ja-JP")* です。

https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo.getcultureinfo?view=net-6.0#system-globalization-cultureinfo-getcultureinfo(system-string)

言語タグ *"ja-JP"* が日本語設定という意味です。ほかにアメリカ英語だと *en-US* などがあります。
日本語指定にしたので曜日が"火"と出力されます。

## メッセージ ボックスに数字表記で表示
![結果表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1851170/a91de072-2518-aff7-b92a-96f8bb68d5bd.png "英語表記の日時を数字表記に変換_結果.png")

しっかり変換されました。


# 補足
曜日を出力しないのであれば、最後の代入は
**num_text = dt.ToString("yyyy/M/d H:mm")**
→"2022/3/15 20:00"
で十分かと思います。
IBM Cloud CLIとOpenshift Origin CLIのインストール方法

## 本記事の目的
本記事では、Mac/Linuxにて、IBM Cloud® コマンド・ライン・インターフェース、およびオプションで一般的なプラグインとツールをインストールします。

Red Hat® OpenShift® on IBM Cloud™ コマンド・ライン・インターフェース (CLI) プラグイン (`ibmcloud oc`) を使用して、OpenShift クラスター・インフラストラクチャーの作成と管理 (クラスターやワーカー・ノードの作成など) を行うことができます。 その後、OpenShift CLI (`oc`) を使用して、OpenShift クラスター内のリソース (プロジェクト、ポッド、デプロイメントなど) を管理できます。

そのために、
1. IBM Cloud CLIのインストール
2. OpenShift Origin CLIのインストール

を実施します。
## 前提条件
IBM Cloud アカウントを取得していること
Dockerのバージョン 1.13.1 以上

## IBM Cloud CLIインストール方法
#### インストールするツール
`Homebrew` (Mac のみ)
`Git`
`Docker`
`Helm`
`kubectl`
`curl `(Linux™ のみ)
IBM Cloud Functions プラグイン
IBM Cloud Object Storage プラグイン
IBM Cloud Container Registry プラグイン
IBM Cloud Kubernetes Service プラグイン

#### インストール方法
上記のツールをインストールするために以下のコマンドを実行します。
**MacおよびLinux環境の場合**
```
curl -sL https://ibm.biz/idt-installer | bash
```

参考リソースは[こちら。](https://cloud.ibm.com/docs/cli?topic=cli-getting-started&cm_mc_uid=99911192173715659206015&cm_mc_sid_50200000=19363221565920601520&cm_mc_sid_52640000=15564161565920601531#overview)



## OpenShift Origin CLI (`oc`) のインストール方法

OpenShift Origin CLI (`oc`) をインストールするために、
1.OpenShift CLIのダウンロード
2.Kubernetes CLIのダウンロード
の大きく2点を実施します。

#### OpenShift CLIのダウンロード
使用しているローカル・オペレーティング・システムおよび OpenShiftバージョン用の最新のOpenShift CLI をダウンロードします。 

バージョン 4 のクラスターでは、
1.クラスターから oc CLI をダウンロードする方法
2.サイトから手動で oc CLI をダウンロードする方法
の２通りがあります。
本記事では一般的なクラスターからダウンロードする方法を実施します。

##### クラスターからダウンロードする方法 
1. [OpenShift クラスター・コンソール](https://cloud.ibm.com/kubernetes/clusters?platformType=openshift)で、クラスターを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/93ac9acc-5e2c-e1dc-a4a2-0058d77a468d.png)
2. 「OpenShift Web コンソール」をクリックします。
3. メニュー・バーから、情報 (疑問符) アイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/46733d3d-6e42-3ce7-bddd-3d27e8c9bc43.png)
4. 「コマンド・ライン・ツール (Command Line Tools)」をクリックします。
5. オペレーティング・システムに対応するダウンロード・リンクをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/ade9bb9a-8f96-571e-1409-8f9e3b95c190.png)

6. ダウンロードしたのちに圧縮ファイルを開きます。 
ダウンロード・フォルダー内の圧縮ファイルをダブルクリックするか、`tar -xvf oc.tar`などのコマンドを実行します。
Mac OS または Linux を使用している場合は、解凍したファイルを、コマンド行またはターミナル・ウィンドウから実行できるように`PATH`システム変数に追加します。
7. `oc`実行可能ファイルを`/usr/local/bin`ディレクトリーに移動します。
```
mv /<filepath>/oc /usr/local/bin/oc
```


続いて、OpenShift クラスターに合った Kubernetes CLI (kubectl) をダウンロードします。
#### Kubernetes CLI (kubectl)のダウンロード

**MacおよびLinux環境の場合**
1. 下記のコマンドを実行します。
```
curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
```
特定のバージョンをダウンロードする場合、コマンドの
`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`の部分を特定のバージョンに書き換えてください。
2. kubectlバイナリを実行可能にしてください
```
chmod +x ./kubectl
```
3.バイナリをPATHの中に移動させてください。
```
mv ./kubectl /usr/local/bin/kubectl
```

以上でOCコマンドが使えるようになります。

## 終わりに
本記事では、
1. IBM Cloud CLI
2. OpenShift Origin CLI

のインストール方法について記載をしました。
ecosia で邪魔なサイトを結果から除外するスクリプト


tampermonkyを入れて, スクリプトを追加する.

https://www.tampermonkey.net

``` javascript
// ==UserScript==
// @name         Block Noisy Site on Ecosia
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  remove noisy sites from search result of Ecosia
// @match        https://www.ecosia.org/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
// @grant        none
// @require    http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js
// ==/UserScript==

(function() {
    'use strict';
    $(document).ready(function(){
      let blocklist = [
        //ここに邪魔なサイトのURLの正規表現を列挙する ,
      ];
      $(".mainline")
          .find(".mainline__result-wrapper")
          .find("article")
          .toArray().forEach( e => {
              let reg = RegExp('<a.+?</a>');
              if(reg.exec(e.innerHTML) !== null){
              e.innerHTML.match('<a.+?</a>').forEach( v => {
                  let link_url = v.match('"https?://.*?"');
                  blocklist.forEach( b => {
                      let block_reg = new RegExp(b);
                      let result = block_reg.exec(link_url);
                      if (result !== null) {
                        e.remove();
                      }
                  });
              })
            }
    });
  });
})();
```
ユーザー詳細ページで  params[:id] が取得できない

自作でグループ内で共有できるカレンダーアプリの作成中。

【やりたい事】
①ユーザー登録
②マイページに遷移（root_path）
③参加中のグループを表示
④グループ名をクリックすると、該当グループのカレンダーへ遷移

ユーザー登録は無事に完了。
本日はマイページの作成に取り掛かる。

以下各コード。


```ruby:user_controller
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
  end
end
```

```erb: show.html.erb
<div class="mypage">
  <div class="left-contents">
    <div class="image">
    <%= image_tag @user.image.variant(resize: '300x300'), class: 'profile-image' if current_user.image.attached? %>
    </div>
    <% if user_signed_in? && current_user %>
    <%= link_to "マイページ編集",edit_user_path(:id), class: "compilation" %>
    <% end %>
  </div>
  <div class="right-contents">
    <div class="user-name2">
      <p><%= @user.name %>のマイページ</p>
    </div>
    <div class="user-department">
      <p>部署名：<%= @user.department_name %></p>
    </div>
    <div class="group_name">
      <p>参加中のグループ</p>
    </div>
  </div>
</div>
```

上記２箇所を記述し、いざ`rails s`を実行。

が、エラー発生

```:エラー文
Couldn't find User without an ID
```

意味は「IDが見つからない」とのこと。

**記述でもミスったかな？**

まずはSequel ProでDBを確認。

__？？？__

ちゃんと保存されている。
意味がわからない・・・

``show.html.erb``の``@user``を``current_user``に変更してみる。
すると問題なく、ページが表示。
ページ内のユーザー名、部署名、画像もきちんと表示されている。
ますます意味がわからない・・・

2時間以上調べて、一つの記事を発見。
``root_pathは普通、直接アクセスしてくるものなので任意のパラメータを付け加えるのが難しい``

__これか！__
たしかに今回、showアクションをroot_pathに設定している。
過去にオンライン学習で作ったアプリのコードを見ても確かにroot_pathを設定したページにパラメーターの記述がない。

各ユーザーのマイページを表示させたいので、 ``@user = User.find(params[:id])``は変えたくない。
となるとroot_pathを他のページに設定するしかない。

う〜ん、カレンダーをトップページに持ってくるか。
また設計の練り直し・・・
AAAI2022のモデル軽量化論文

# 概要

この記事では、AAAI2022のニューラルネットワークのモデル軽量化論文をまとめます。[^1]
[^1]: 画像や数式は論文から引用しています。 

# Improved Gradient based Adversarial Attacks for Quantized Networks

https://arxiv.org/abs/2003.13511

概要：量子化ネットワークへの敵対的攻撃
研究機関：Amazon
新規性：従来のFGSMやPGDよりも攻撃の精度が高い。
キモ：計算する時のLogitsにスケーリング係数$\beta$を掛けて、勾配をこのように計算する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/3b9b6852-6fa2-ab01-7e6c-247c100d0136.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/d90997fc-5b91-ce89-9276-4925580d9541.png)
NJS (Network Jacobian Scaling) では、$\beta$はヤコビアンの特異値の逆数とする。
HNS (Hessian Norm Scaling) での$\beta$の決め方は
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/d3928e07-cbcf-e3ac-68e0-528c7a741688.png)
評価：ResNet, VGG等で、従来のFGSMやPGDと比較した。


# From Dense to Sparse: Contrastive Pruning for Better Pre-trained Language Model Compression

https://arxiv.org/abs/2112.07198

概要：CAP (ContrAstive Pruning). タスク非依存の知識も入れながら枝刈りする方法。
研究機関：Alibaba
新規性：従来の枝刈りは特定タスクで解いていたので、catastrophic forgettingの課題があるのに対して、task-agonisticな知識も入れて学習することで、汎化性能を上げる。
キモ：学習済みモデル、枝刈り途中のスナップショット、ファインチューニングしたモデルそれぞれに対して、contrastive lossを求め（それぞれPrC, SnC, FiC）、全体を合算したロスを使う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/ee09b42a-f0ce-6735-5de5-bbecaa67dec9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/9c408604-f392-cd5e-0376-7e75654fda49.png)
評価：BERTから刈ってMNLIで評価した。


# Prune and Tune Ensembles: Low-Cost Ensemble Learning With Sparse Independent Subnetworks

https://arxiv.org/abs/2202.11782

概要：低コストアンサンブル学習で、1つの親ネットワークから刈って、子ネットワークを作る方法。
新規性：他の低コストアンサンブル学習よりも精度が良い。
キモ：Anti-Random Sampling. 1つの枝刈り結果からの距離が最大のネットワークを選ぶ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/0055a831-a434-4467-86ca-c20f35f5177b.png)
評価：Wide-ResNetベースのアンサンブルで、他の枝刈り手法と比較した。


# Prior Gradient Mask Guided Pruning-Aware Fine-Tuning

https://aaai-2022.virtualchair.net/poster_aaai1708

概要：PGMPF。枝刈りしながらFine-tuningする方法。
新規性：Fine-tuningしながら枝刈りする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/3f9cc6e1-0c10-4aca-b644-cbbc8fcbaac8.png)
キモ：枝刈りを連続マスクとみなして、勾配法でマスクを適用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/8dd9ba5e-c94a-2ca6-f52e-ea75c0f4b3d8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/a6b9dceb-13cb-1170-df70-79ac4d74576a.png)
評価：VGGやResNetに適用して実験した。
Yolov5で標識認識を作る

# TL;DR
Yolov5を転移学習させて道路標識の検出器を作った、それだけの記録です。
![output2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420844/b484a484-7ed6-f664-976c-b7bb33c77d85.gif)

# Yolov5
下のリンク先の実装を使いました。
COCOを使った重みだったり、学習の時には最適なアンカーボックスの設定、YouTubeのurlを指定しての推論など、至れり尽くせりな感じです。転移学習をする場合も、もともと備わっている関数を呼び出すだけで実行できました。

https://github.com/ultralytics/yolov5

# Dataset
色々調べたところ、Mapillaryのデータセットが標識の種類、画像の枚数共に良さそう。
割合は少ないですが、日本の標識も含まれていました。

https://www.mapillary.com/dataset/trafficsign

中身はこんな感じのよくあるObjectDetectionのアノテーションがついたデータセットで、
<div style="text-align: center;">
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420844/3ab53119-c726-71a0-e617-7ec9eb1d6d1b.png" width="500">
</div>

学習データに含まれる標識はこんな感じ。
全て合わせると401種類の標識のラベルがありますが、3(other-sign)のみ、いろんなタイプの標識を含んだものになっているようです。
![Screen Shot 2022-02-22 at 23.55.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420844/e99f69d4-82f1-5ed8-9cce-3b63c3a59493.png)

全てのラベルとサンプルの対応は下のリンク先にまとめてあります。

https://github.com/takekbys/TrafficSignDetection_yolov5/blob/trafficsign_detection/data/Mapillary/src/show_traffic_sign_sample.ipynb

# 学習
```./data/hyps/hyp.scratch-low.yaml```を使って200epoch学習したところで、左右の反転により特定のラベルの学習がうまくいっていないことに気づき、左右反転をOFFにしてさらに50epoch学習させました。

学習結果はこんな感じ。
![val_batch1_pred.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420844/72c9fce4-54ee-0396-aeae-a11030a64b4e.jpeg)

かなりサイズの小さいラベルが多いためか、mAPはなかなか上がり切らなかった印象でした。
![results.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420844/dd8c51b9-5594-a108-c952-b1b55680da09.png)

# トラッキング
せっかくなので、検出した標識をトラッキングさせてみました。
検出した標識を表示/消去させるタイミングにヒステリシスをつけていますが、ほとんどPytorch実装のDeepSORTをそのまま使っています。
![output2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420844/b484a484-7ed6-f664-976c-b7bb33c77d85.gif)

元にしているのはこちらの実装。

https://github.com/mikel-brostrom/Yolov5_DeepSort_Pytorch

以上
HTMLの基本〜part1〜

■HTMLの構造について
HTMLは大きく分けて、『head要素』と『body要素』の2つの要素で構成される

①head（ヘッド）要素
ウェブサイトの情報や、装飾用のCSSファイルの情報を記載する部分。
ここに記述した情報は画面上に表示されない。

（例）
・Webページのタイトル
・装飾のためのCSSファイルの指定
・外部のファイルの読み込み
・SNSなどでシェアされたときの表示の仕方

②body（ボディ）要素
画面上に表示したい情報を記載する部分。
ブラウザ上に表示したい情報は、body要素の中に記述する。


■HTMLを記述するときに必ず記述するコードとは
①` <DOCTYPE HTML>`
この文章がHTML文章であることを宣言する要素。コードの先頭に記述し、終了タグはなし。
記載する理由⇨レイアウトが崩れ、正しく表示されないことを防ぐため。

②` <html> </html>`
HTML文章の始まりと終わりを示す要素。
【Azure】Bastion後続の同時接続セッションについて理解しましょう

# はじめに
Azure上で１台Bastionを立てて、後ろに何台のVMと接続できるかを、みなさん気にしたことがありますか？
例えば、ちょうどVMは１０台ありますが、それを１つのBastionで接続したら、接続に大丈夫なのか、を少し調査してみました。

# 結論
先に結論から申し上げますと、 Bastionはあくまで画面転送用の踏み台サービスです。
つまり、Bastionの背後における同時接続数の上限は、Bastionの性能に依存しており、
ライセンスやセッション数についての明確が上限が存在していないことになります。

Bastionはあくまで、画面転送が行なってくれるだけです。

これを少し詳しく説明してみると、例えば高解析度の画面よりも、低解析度の画面のほうが、
Bastionがより多くのVM画面を転送してくれるので、同時接続数もそれなりに増加することができます。

例えば１０台のVMに対し、１０セッションでBasitonの性能上限に達していないのであれば、
１１セッション目の接続が可能となります。

なので、明確な同時接続上限は存在しておらず、データ転送の処理量に応じて決まることとなります。

なお、BastionはVMのデータ転送に対し、どれぐらいのデータ転送パフォーマンスだったら、
耐えられるかについて、下記公式サイト上では目安のセッション上限数は記載しています。

>|ワークロードの種類*             |	上限* *   |
>|:------------------|:------------------|
>|白|100|
>|Medium|50|
>|ヘビー|5|
>
> *これらの種類のワークロードは、[「リモート デスクトップのワークロード」](https://docs.microsoft.com/ja-JP/windows-server/remote/remote-desktop-services/remote-desktop-workloads)に定義されています。
> **これらの上限は、Azure Bastion の RDP パフォーマンス テストに基づいています。 他の実行中 RDP セッションや、他の実行中 SSH セッションによって値は異なる場合があります。

https://docs.microsoft.com/ja-jp/azure/bastion/bastion-overview#host-scaling

# ホストのスケーリングとは
よくホストスケーリングの意味を、最初ドキュメントを読む時に理解できていなかったが、
こちら結論から申し上げますと、BastionのSKUはStandardの場合は、
Bastionのインスタンスを増やすことで、踏み台として利用できる仮想マシンの数が増加されるため、結果としては、Bastion全体の性能が上がることとなります。

https://docs.microsoft.com/ja-jp/azure/bastion/bastion-overview#host-scaling
CentOS7でRadiusサーバを自動構築するテラタームマクロ作成bat

radiousの認証テストを行うことがあり
構築に手間取ったので、自動構築できれば楽なのにと思って作ってみました。

# 使用環境
・VMware：VMware Workstation Player16
・OS：CentOS7.6,7.9(仮想で構築)
・radious：Free radious

# 前提条件
・WindowsPCからCentOSへSSHできること。
　※環境によってはIP設定等にOSインストール後に手動設定が必要です。

・インターネットアクセスが可能なこと
　※インターネットからアップデート等を行うため

・.ttlがTeratarmに関連付けされていること。

# zipファイル
<p><a href="https://github.com/yyoshizu/CENTOS7_FreeRadious_Automatic_bat/releases/download/teratarmmacro/CENTOS7_FreeRadious_Automatic_bat.zip"download="https://github.com/yyoshizu/CENTOS7_FreeRadious_Automatic_bat/releases/download/teratarmmacro/CENTOS7_FreeRadious_Automatic_bat.zip">zipファイルをダウンロード</a></p>

# 手順
①VMwareへCentOSをインストールする

②インストール完了後。IPを確認する。
　※手動設定の場合はIPを設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475419/57b38850-ded6-8609-6ae0-b8dbea9f1720.png)


③[load_ssh_radius.csv]を開き設定値を入力し保存する。
　　※変更が必要な箇所だけ以下に抜粋

A列：ホスト名(ファイル名に利用)
B列：IPアドレス(接続先)
I列：CentOSのログインユーザ名(基本はrootのままでいいです)
K列：CentOSのログインパスワード
M列：wait key(テラターム接続時のプロンプトを参照)※1
N列：認証ネットワーク名(任意名称)
O列：radious認証するネットワークセグメント
P列：sercret
Q列：認証ユーザ名
R列：認証パスワード

ファイル名：load_ssh_radius.csv
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475419/e8137ca5-9c25-76db-08b9-efdf33c1f141.png)


※1 wait key
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475419/734cb5a1-c277-0cca-9215-cf212fed0dba.png)

④[shh_Make_Teratermmacro_Free_radius.bat]を実行する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475419/eaa33217-9548-7dca-c0d2-c131dee8d265.png)

⑤ ④のフォルダ配下にoutputフォルダに.ttlが生成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475419/654d7ff9-a3f0-d4d8-6e0d-2e5e127b852f.png)

⑥ [xxx.xxx.xxx.xxx_SV名.ttl]を実行する。
　※今回は[192.168.109.138_test-sv.ttl]

⑦初回のSSH接続時はセキュリティ警告が表示されるので
　　赤枠のチェックをつけ続行を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475419/f78bb95c-b36c-49fc-22d7-7e1e3eedaef2.png)

⑧テラタームマクロが起動し、radiousサーバの構築を開始する。

⑨構築が完了したらセッションを切断するのでTeratarmが切れるまで待つ

以上

# 認証テストするときの注意点
自分の環境でテストしたときにハマった部分ですが
NIC設定が[NAT]の状態だと認証サーバとして機能しないようですので
[ブリッジ設定]への変更と関連するアダプタを選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475419/a4747057-9c89-a446-eab9-dd3bb1c80710.png)
【SPA】ローカルでの挙動を本番環境に近づけ動作確認を行う【React】【Rails API】

## はじめに
　本記事は、プログラミング初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## ローカルでの挙動を本番環境に近づけ動作確認を行う
ローカルでは、サーバーサイドからフロントエンドにデータがすぐに届いてしまい、そのままだとスケルトンスクリーン等の動作確認をすることが難しいことがあります。
そこで、サーバーサイドからデータが届くのを遅らせる方法について調べてみました。
結果、以下2点の方法が見つかりました。

### ディベロッパーツールでスロットリングを設定する
１つ目は、デベロッパーツールで設定する方法です。
手順は以下の通りです。


デベロッパーツールの「ネットワーク」を選択

![スクリーンショット 2022-03-07 23.29.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/60b101fa-90f9-c49c-92e7-6dc5f5e4e209.png)

「スロットリングなし」をクリック

![スクリーンショット 2022-03-07 23.31.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/b64519cb-a318-050d-8a62-5d619d4d8213.png)


「低速3G」を選択
![スクリーンショット 2022-03-07 22.52.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/b12f146c-4878-8771-2792-0e5e3d56bb54.png)

上記の設置を行うとローディングに時間がかかるようになります。
スケルトンスクリーンを設置したページで確認したところ、スケルトンスクリーンを確認することができました。

### サーバーサイドにローディング時間を伸ばす処理を記述する
Railsの場合には`application_controller.rb`に以下の通り記述することで、ApplicationControllerを継承している全てのコントローラーの処理を遅らせることができます。

```application_controller.rb
class ApplicationController < ActionController::API
  # --- 本番環境では不要な記述であるため動作確認で必要な場合にのみ記述 ---
  before_action :fake_load

  def fake_load
    sleep(2)
  end

end
```

上記の処理は、当然、本番環境では不要なものですので、記述するとしても動作確認の際のみにする等本番のコードに入らないようご注意ください。
【Windowsフリーソフト】新PCに入れたいフリーソフト

Windows 11では使えない，必要ないものも含まれるかも．
「これは絶対に入れるべきなのに挙げられてないよ」ってソフトがあれば教えていただけるとても嬉しいです．

:::note info
随時更新
:::

## 目次
- [本編](#本編)
  - [常時稼働ソフト](#常時稼働ソフト)
  - [テキストエディタ](#テキストエディタ)
  - [ツール系](#ツール系)
    - [画像・動画関連](#画像動画関連)
    - [ファイル・フォルダ関連](#ファイルフォルダ関連)
  - [英語関連](#英語関連)
  - [Chrome拡張機能](#chrome拡張機能)

## 常時稼働ソフト
* **VoiceMeeter Banana**：音声ミキサー？
    * macroボタン：付属ソフト。ミキサー本体の操作をマクロ化してGUIボタンに割り当てることができる。さらに、これらのマクロにキーボードショートカットを割り当てることもできる。私はこれで音声出力先をイヤホン、スピーカー、画面に切り替えるボタンを実装している。ゲーム用、動画視聴用に音声プロファイルを切り替えるボタンなども作った。
* **AutoHotkey/MouseGestureL**：PC操作の自動化/マウスの動作にマクロを割り当てるソフト
* **7+ Taskbar Tweaker**：タスクバー改造
* ~~**Sylphyhorn**：仮想デスクトプそれぞれで別の背景~~　←なんか使えなくなった

## テキストエディタ
* **LaTeX**：論文、きっちりした文章を書くためのツール
    * **Strawberry perl**：latexmkで必要
    * **TeX2img**：TeX数式画像の作成
* **VSCode**
### VSCode拡張機能
:::note info
更新予定
:::

## ツール系
### 画像・動画関連
* **IrfanView**：画像閲覧・簡単な編集
* **ImageMagick**：画像形式編集(CUI)
* **OBS studio**：画面録画など
* **briss-0.9**：PDFクロッピング
* **CubePDF Utility**：PDF編集
* **Inkscape**：2次元作図
* **GIMP**：画像編集
* **Fusion，blender**：3次元作図
* **DaVinci Resolve**：動画編集
* **VLC**：動画再生など

### ファイル・フォルダ関連
* **DiskInfo3**：ファイル，フォルダの解析
* **FlexRena84J**：ファイル名変更
* **QuickLook**：エクスプローラ内で，ファイル選択時スペースキーで画像，動画などプレビュー
* **QTTabBar**：エクスプローラでタブが使える
* **Listary**：プログラムランチャー・ファイルブラウザ
* **Everything**：ファイル・フォルダ検索。エクスプローラで検索するより断然速い。
* **Git**：テキストファイルの履歴管理
  * ~~**Github**：Gitで管理する履歴をインターネット上にアップできる．すごく砕くとソースコード用SNSとも言える？~~　←WebアプリだからPCに入れるものではないね

## 英語関連
* **DeepL翻訳**：違和感のない言語翻訳
* **Anki**：単語帳

## Chrome拡張機能

* **Charset**：エンコーディングを変える．古いサイトでたまに使う．
* **Keepa - Amazon Price Tracker**：アマゾン商品の過去の値段がわかる．
* **OneTab**：複数タブをまとめて保存できる．
* **SearchPreview**：サイトのプレビューが表示される．
* **uBlock Origin**：広告ブロッカー
* **Weblioポップアップ英和辞典**：英単語の意味知りたい時に使える．
* **素晴らしいスクリーンショットとスクリーンレコーダー**：ページ全体のスクリーンショットが取れる．いちいちスクショ，スクロールを繰り返さずに済む．
4bitCPU(TD4)を回路シミュレータLogisimで自作した話  「CPUの創りかた」

今更ですがいつかやろうやろうと思っていたCPU自作に挑戦しました。

ただ実際にHWを作成するのはパーツ調達がめんどくさかったりハンダ付が苦手だったりでどうしても手が出なかったので、GUIの回路シミュレータでできないかな〜と探していたところちょうど良いものを見つけました。
それがLogisimです。
回路の0−1が一目でわかるUIと階層構造、ICライブラリがあることからこちらを選びました。
半田付けだと作業工程自体のミスとロジックのミスと切り分けるのが難しそうで、純粋にロジックと動作原理のみ勉強したかった私にとってこのチョイスは結果的に正解でした。

こちらの記事を参考にさせていただきました。
http://yoshi-s.cocolog-nifty.com/cpu/2014/08/logisim.html

デフォルトだと74系ICが入っていなかったのでライブラリを落としてきて、あとは書籍の回路図と睨めっこしながらせっせと配線をしました。（ROMは結局妥協しました。）

![gamen_test２.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2380862/b0084c45-cfb7-bf69-8975-6db9b0be524c.gif)
ラーメンタイマーを動かしている様子（GIFを圧縮したらカクカクしちゃいました）

つまづいたのは、Logisim環境構築でMACだと結局うまく動かなかったこと、283のキャリーフラグがどうやっても不定で１を出力してくれなかったこと（→内蔵のFAに変更して解決）、
74のプリセットピンが不論理じゃないことにいつまでも気づけなかったこと、くらいで作業自体は2日くらいで完了しました。

いや〜完成させると達成感がありますね。やってよかったです。

CPUの動作というのは全てレジスタ間でのMOV命令に還元できるということ、操作の肝はデコーダが命令をデータセレクタへの指示ビットへ変更していること、など基本的ですがやってみないと分からない、でもものすごく大事な気づきが得られてとても勉強になりました。


おまけ
CPU自作の方法論はこんな感じで分布していそうです。
HW自作
・FPGA
・ブレッドボード
・プリント基盤
SW自作
・VHDL
・回路シミュレータ（GUI）
・エミュレータ

さらにおまけ
TD4はクロックの立ち上がりで命令フェッチ、デコード、演算、書き戻し、プログラムカウンタインクリメントを全て行うようです。つまり１サイクル(クロック)で１命令。
ただ大抵のCPUアーキテクチャの本には１命令を４サイクルに分けてパイプライン処理をしていたりします。
この１命令を数サイクルに分けるというのが構造上必然的に生まれるものなのか、パイプライン処理を行えるようにデザインされているものなのかがよく分かりませんでした。
調べてみたのですが全然回答に辿り着けなかったのでこの辺りの知見をお持ちの方はコメントでひっそり教えていただけると泣いて喜びます。
Addressable Asset でリモートコンテンツを正しく更新する方法

addressableでリモートコンテンツのアップデートをどのように行うかについてのざっとしたメモ書き。

ともかく、日本のサイトにはAddressableをどのようにして導入するかについての記事はやたらとあるのだけど **リモートコンテンツをどのように更新するか** についての記事がさっぱりなかったので、メモ書きとして残しておくことにした。

記事の読者の対象としては **Addressableは導入して、ちゃんと読めるようになった（これはめっちゃ簡単だと思う）が、なんだかサーバーに置かれるリモートコンテンツのアップデート方法が良く分からないぞ？**　という人である。

最大のポイントは **Addressable_contents_state.bin** の使い方。
知る限りでは日本語の情報は全くない。
unityの英語のマニュアルがあるだけで、しかもこれもメッチャいい加減なのだけど、これを読まないとわからない。ついでに書くと、このマニュアルは熟読した方がいい。

https://docs.unity3d.com/Packages/com.unity.addressables@1.19/manual/ContentUpdateWorkflow.html#group-update-restriction-settings

基本Addressableのセットアップは出来ている。サーバーにデータも置いた。サーバーから正しく読めている。
ところで **コンテンツの更新** をしたいとき、どうするの？　というときに、上のマニュアルを読めばいいのだけど、ともかくわかりにくいので以下にザックリとしたプロセスを書いておく。

1. 一番最初にアドレサブルのコンテンツデータを作るとき、"New Build"からアドレサブルビルドを生成する（これはローカルでやる必要がある）
1. 出来上がった **Addressable_contents_state.bin** を例えば "ver_2022_03_09_master.bin"というような確実に100%、何者か分かる名前をつけて、大事に保存する。これ、 **スーパーウルトラ大事**。
1. リソースアップデートが出来て、新しいリソースをサーバーに置かなければいけないとき、Toolsの"Check for Content Update Restrictions"を実行して、問題を解決しておく。めんどいのでここは説明しない。
1. Buildから **"Update A Previous Build"** をすると、どこにContents.binがあるんだよと聞かれるので、大事に保存したstate.binを指定する。
1. 差分情報を持ったカタログとリモートコンテンツが出来上がるので、これをサーバーにアップロードすればよい。

これで実行環境側ではカタログをアップデートした後、 **アップデートされていないコンテンツは読み込まずスキップしてくれる** ようになる。
わかってしまえば、これだけなのだけど、ともかく日本の情報ではわからないのでメモ書きとして残しておく。

以下は、英語のマニュアルに書いていない恐怖の情報

* **Addressable_contents_state.binはターゲット毎、クライアントごとの生成が必須**
どこにも書いていないうえに、素直にマニュアルを読むと Addressable_contents_state.bin にはコードに依存するようなデータは一切含まれていないように思えるのだけど、実は違う。
このファイルには **どこ(URL)から読むのかの情報が含まれている** 。そして、update buildをするときは、それが一致していないと、エラーでビルド出来ない。
要はremote_pathが一致しなければならない。
だから例えば"Master"と"Staging"と"Develop"でそれぞれサーバーが違ってremote_pathが設定されている時（普通はそうだ）、別にcontent_state.binを生成しなければならない。これを知らないと、基礎になるバージョンに戻って慌てて全部のcontent.binを生成するハメになる（やった）。
また、これはプラットフォームごとに分かれているので、プラットフォームごとにビルド必須。

* **いつまで同じカタログを使えるのか？**
-> 基本はずっと使えるらしい。

* **カタログの内容が変動してきて、最初から読ませたい場合もあるときはどうするか？**
→catalogのバージョンを変えて、new buildする。
すると新しいカタログなので、今までのキャッシングされたデータは全て破棄されることになる。

* **うっかり同じ名前でnew buildをしたらどうなるのか？**
catalogのバージョンは変わっていないのにnew build = 差分情報ではないので、全部読もうとして、しかもイロイロ同じなもので衝突し、謎のキャッシュ状態になって、いろいろなものがブチ壊れる。やったら大変だよ！
どうしてunityのデフォルトの設定が日付使ってるのかの理由がコレだと理解するまでひどい目にあった。

* **"Unity Cloud Build"ではどうするの？**
ちゃんとcontent.binを指定できる。ただし、unity cloud buildのマニュアルには全く書いていないし、どうなるのかもわからないのだけど、 ~~別のcontent.binを指定してビルドしてもビルドは通ってしまう。
中身をチェックしたら、とても怪しかったのでやらない方がいい~~。
まさに今日、新しいターゲットのセットアップで間違ってやってしまったので、情報更新。
ちゃんとビルドは通らない。でもエラーが出るまでは全然わからない。事前に調べてほしい。

と、こんな感じ。

はっきり書いて、unityさん、addressableに移行したいなら、マニュアルをもっと充実させてください。
ともかくマニュアルの出来に問題があり、マニュアルに書いていない **やってはいけないコト** がてんこ盛りで、ワナを踏みまくることになる（なったし、今でも踏んでいる）。
Next.jsでbuildすると、AmplifyのAuth.configureがnullになるとき

# 結論

```diff
Amplify.configure({...awsconfig})
+ Auth.configure({...authconfig})
- Amplify.Auth.configure({...authconfig}) // Amplify.Auth is null
```

# 概要

納期が迫っているのでギリギリで書いていますのでサクッと

Next.js + Amplifyの構成でCognitoへのログインなどを実装している場合に
`yarn dev` では動くのに `yarn build && yarn start` では突然大量のエラーが出て絶望していた

Amplifyの中身をログ出力すると、いろんなものがnullになっており、より怖い
ファイルの場所変えたりとか色々試してみるも、結局は `Auth.configure` を直接呼ぶ形にすることで解決できた
Nuxt.jsにてcommit時に自動でESLintを実行させる方法

## 概要
ポートフォリオでフロントエンドの開発をしている際、
pushする前に都度Lintツールを実行するのが面倒なのでcommit時に自動で動作するようにしてみました。

## 環境
|/|バーション|
|:--:|:--:|
|nuxt|2.15.8|
|yarn|1.22.15|
|husky|7.0.4|

## 前提
まず、LintツールであるESLintは設定済みと仮定します。
説明のためpackage.jsonの一部の例だけ載せておきます。

```package.json
 "scripts": {
   "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
   "lintfix": "eslint --fix --ext .js,.vue --ignore-path .gitignore .",
 },
```

## 方法
### Step 1 ライブラリのインストール
まず、`husky`をインストールします。

```
yarn add --dev husky
```

### Step 2 Git hooksの有効化
下記コマンドにてGit hooksを有効にします。

```
yarn husky install
```

### Step 3 package.jsonを編集
package.jsonの`script`を下記のように編集します。

```package.json
"scripts": {
  "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
  "lintfix": "eslint --fix --ext .js,.vue --ignore-path .gitignore .",
  "prepare": "husky install",  // 追加
},
```

### Step 4 .husky/pre-commitを作成する
`.husky`ディレクトリを作成し、そのディレクトリ内に`pre-commit`ファイルを作成する。
この作成したファイルに**commit時に実行するコマンドが記載される**。

### Step 5 pre-commitにコマンドを追加
下記コマンドを実行して`pre-commit`ファイルにコマンドを追加する。

```
yarn husky add .husky/pre-commit "lintfix"
```
今回はESLintを自動で実行したいので、上記コマンドを登録してる。
もし他の実行したいコマンドがあれば同様に登録すればよい。

## まとめ
上記手順でESLintは自動で実行される。詳しく知りたい場合はドキュメントを参照してください。

https://typicode.github.io/husky/#/?id=usage
PythonからVaporettoを呼び出して使ってみた話

# 2022/07/05 追記
Vaporetto の開発者の方がPythonラッパーをリリースしてくださりました。

https://github.com/daac-tools/python-vaporetto

# 概要
PythonからRustで書かれたトークナイザであるVaporettoを呼び出して使用するクラスを作成しました。
バインディングで動作させている訳ではなく、今回はsubprocessを用いてビルドした実行ファイルを呼び出す形で使用しました。（どっちかっていうと、ラッパー？）
RustはPythonから比較的移行しやすい言語だと思うので（~~個人の感想です~~）、バインディング用意しなくてもsubprocessで十分なんじゃないかなぁと思って書いてみました。

# 環境
windows10
Python 3.8.10

# 今回作成したコード
```Python
import subprocess
from typing import List

class Vaporetto:
    def __init__(
        self, 
        exe_path:str,               # 実行ファイルへのパス
        model_path:str,             # モデルへのパス
        option:List[str]=[],        # 追加のオプション(要らない？)
        display=True                # Vaporettoから出力される標準エラー出力の表示の有無. 最後に出る速度とかの辺
        ) -> None:

        options = ["--model {}".format(model_path)]     # コマンド実行時のオプションを指定
        option.extend(option)

        cmd = exe_path + " " + " ".join(options)        # 実行するコマンドを指定

        # 子プロセスを起動
        if display:
            self.proc = subprocess.Popen(cmd, bufsize=5242880 ,  stdin=subprocess.PIPE, stdout=subprocess.PIPE)
        else:
            self.proc = subprocess.Popen(cmd, bufsize=5242880 ,  stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
    
    # 形態素解析
    def parse(self, text:str):
        text = text.split("\n")
        res = []

        for row in text:
            if row == "":
                continue    
            self.proc.stdin.write((row + "\n").encode())        # バッファに1行分のデータをutf-8でエンコードして書き込む
            self.proc.stdin.flush()                             # バッファの内容を子プロセスに流す

            x = self.proc.stdout.readline().decode().strip()    # 子プロセスから標準出力に出力された内容を読み取る
            res.append(x)

        return res

    def exit(self):             # 子プロセスの終了
        self.proc.stdin.close()

    def __del__(self):          # デストラクタ
        self.proc.kill()

```
バッファの値は色々試行錯誤してた際に決めたので適当です。最終的に1行ごとに入力する形式になったのでラインバッファでも良い気もします。


# 使い方
実行ファイルのパスと使用するモデルへのパスを指定してオブジェクトを作成して、parseメソッドでトークナイズできます。
そのまま終了した場合や、exitメソッドで終了した場合は最後に表示される速度等の情報が表示されますが、デストラクタで終了した場合は、子プロセスが強制終了されるためそれらは表示されません。
空行は入力しても無視される仕様になっています。困る場合はparseメソッドを良い感じに書き換えてください。


# MeCabと比較して速いのか
Vaporettoの起動に若干の時間がかかる為, 起動に十分な時間をsleepして時間を計測しました。
青空文庫から100個分のテキストを結合したデータを用いました。文字数は2230627文字です。
時間計測はtime.perf_counter()で行いました。

## そのまま入力した場合
MeCab:1.571 sec
Vaporetto:1.481 sec
上記の通り、Vaporettoの方が若干早いという結果でした。

## 行ごとに分割して入力した場合
MeCab:1.239 sec
Vaporetto:1.490 sec
MeCabの方が速いという結果でした。

# まとめ
データをエンコードしてパイプでやり取りする必要がある分サブプロセスは不利なのかなぁという印象でした。
Vaporettoの方は行ごとに分割する処理をPythonが行ってから引き渡しているので、そこもRustで書けばもう少し早くなるのかな？とも思いましたが、そこまでするなら普通にRustで書いたほうが楽ですよね。

バインディングなら、もう少し早くなるのかなぁ。（書く予定はないです）
AtCoder ABC242D ABC Transform

https://atcoder.jp/contests/abc242/tasks/abc242_d

# こう考えた
まず最初にこの問題のA,B,Cをそれぞれ0,1,2と呼ぶことにします。一般性を失いません。
また、次の節で述べる通り、$t=0,1,2,3...$のことを上から積み重ねた"段"と呼ぶことにします。

## k文字目の段を降りたときの周期性
最初にシミュレーションしてみます。 
```Python
s = "A"
s = s.replace("A", "0").replace("B", "1").replace("C", "2")
for i in range(6):
    print(i, s)
    s = s.replace("0", "x").replace("1", "y").replace("2", "z")
    s = s.replace("x", "12").replace("y", "20").replace("z", "01")
print(" ", s)
```
実行します。
```text
0 0
1 12
2 2001
3 01121220
4 1220200120010112
5 20010112011212200112122012202001
  01121220122020011220200120010112122....
```
この時、ぱっとみて気が付くのは、
- ある文字が決まると、段(t)を重ねるごとに`0->1->2`と進む

この特性は後で利用します。

次に上記のforループの値を大きくすると、
- 段数を増やしていくと、`1文字 -> 2文字 -> 4文字 -> 8文字`のように文字数が2の累乗で変化

つまり、$t$段目の文字数は$0$段目の文字数を$n$とすると、$n \times 2^t $文字であることが分かります。
今回の問題では、$k \leq 10^{18}$なので、高々60段目でk文字目は必ず存在します。($2^{60}$は大体$1.1 \times 10^{18}$です)

## 60段目までにおけるk文字目を求める
さて、上の実行例は左寄せでprintしましたが、これを木のように書いてみることにしましょう。つまり、以下のようにします。そして、じっと睨みます。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30938/f1a1d9c2-530e-98c5-c2e6-942d55109954.png width=70%>
<font color=red><b>指摘いただきましたが最後の段のind3 は2です。直しますが、今元画像がないので取り急ぎ文章にて。</b></font>

すると、以下のことが分かります。

- あるノードはその親のノードの値に対して、自分が左なら+1, 右なら+2して$mod3$したもの
    - 少しにらむと、ノード番号$i$が偶数なら親から見て左のノード、奇数なら右のノードであることが分かります
- この木のノードは(葉を除き)ちょうど2つのノードを持つ。(つまりセグメントツリーのように)上の段の親のノード番号はそのノード番号を$i$としたとき、$i//2$(切り捨て)となる。

つまり、ある$0 < t$段目のノードind=$i$の値を$f(t, i)$とすると、
- iが偶数の時: $f(t-1, i//2) + 1$の$mod3$
- iが奇数の時: $f(t-1, i//2) + 2$の$mod3$
- $t=0$というのは与えられた入力(を0,1,2にしたもの)そのもの

## 60段目よりも先を求める

この式を求めることで解けました...と言いたいですが、今回は$t \leq 10^{18}$と大きいので再帰すると非常に大きな回数のループを回すため計算が間に合いません。そこで最初に気が付いた、ある$k$文字目をそのまま1段下がると`+1`してmod3した値になる。という気付きを使います。つまり、$t$段$k$文字目の数が$val$とわかっているなら、$t+a$段目の$k$文字目は$val + a$のmod3であることが分かります。

次のようにします。
- $t \leq 60$ならシミュレーションします
- $t > 60$のとき、$t=60$での$k$文字目を調べた後、ほしい文字は$t-60$段下にあるのですから、`+(t-60)`して、mod3します。

これで、$t$が非常に大きい時にも、60回程度のループで答えを求めることができました。

# 実装

```Python
s = input() # ABCを
s = s.replace("A", "0").replace("B", "1").replace("C", "2") # 012にして
s = list(s) # ["0", "1", "2"]にしてから
s = list(map(int, s)) # [0, 1, 2]にする

def f(t, i):
    if t == 0: return s[i]
    if t<=60:
        if i % 2 == 0: return (f(t-1, i//2) + 1) % 3
        else: return (f(t-1, i//2) + 2) % 3
    else:
        return (f(60, i) + (t-60)) % 3

q = int(input())
ansdict = {0:"A", 1:"B", 2:"C"} # 0,1,2をA,B,Cに戻す
for _ in range(q):
    t, k = map(int, input().split())
    k -= 1 # 1-indexed -> 0-indexed
    print(ansdict[f(t, k)])
```

https://atcoder.jp/contests/abc242/submissions/29942258
OutSystemsの資格試験を受験しました

OutSystemsの認定試験（Associate Reactive Developer）を受験したのでその体験を書いてみようと思います

# 認定試験について
## 試験の内容
OutSystemsの認定試験一覧は以下のようになっています

![certificate2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137987/6d6544f9-ef59-f3eb-dc95-6e0eb41ef3f7.png)

Traditionalは.netのアプリを作るための認定試験でReactiveはSPAアプリを作るための試験です
Reactiveは最近出たばかりのためかAssociateしかありません
Associateって名前からわかるとおりそんなに難しい試験ではありません

試験のレベル感としてはこちらのテスト問題と同じくらいの難易度の問題が出題される感じです

https://www.outsystems.com/ja-jp/training/paths/18/becoming-a-reactive-web-developer/



## 受験方法
大きく分けると２つの方法があります

https://www.outsystems.com/ja-jp/certifications/home.aspx

https://www.bluememe.jp/outsystems/outsystems_support/exam-qualify.html

OutSystemsに直接申し込む方法とBlueMeme（代理店）に申し込む形です
ちょっとわかりにくいですがBlueMemeで開催してるBootCampに申し込むのは受験のバウチャーがもらえるでだけで必須ではありません
BootCampの値段を考えるとほぼ受けなくていい気がします
またWEBの無料トレーニングもアカウントの受講状況を見てるわけではないので受講完了しないと受けられないと言うわけではありません
ただ理解度的にサンプル問題で合格点を取れないと本試験も合格は厳しいかもしれません
BlueMemeは月に1回開催されて試験日の1ヶ月前までにメールで申し込みが必要になります

OutSystemsに申し込む場合は試験方法が2つあり、テストセンターとリモートで家で受験できます
リモートで受験するほうがスケジュールの都合は付きやすい印象でした
しかし試験官の方が外国人で英語でコミュニケーションを取らないといけないということで断念しました（英語できないマン）
テストセンターは都内在住の方は御茶ノ水になるようです
多くはないですが土日も開催していて数日前くらいまでは受験日の変更も出来て割と柔軟に受験できました
OutSystemsに直接申し込む場合は$200になるので為替によって多少受験料が変わります
BlueMemeの場合は22,770円固定で受験できます。

# 私のOutSystems歴
仕事のプロジェクトで数ヶ月程度開発を経験しました
そこまで高度なことはしてないですが、Associate Reactive Developerで出題されるような範囲は一通り経験していたくらいの感じです
試験勉強は前日に数時間程度勉強して受験しました

# 試験結果
76点で**合格**でした！！！
合格が70点以上なので結構ギリギリの合格でした・・・！

危ない危ない・・・
私はプロジェクトで使ったときあまりBlockを作ったりモジュール分割したりしてなかったのでそこらへんが弱かった感じです
Developer向けの試験なのでこのプロパティを変更したらどうなるか？みたいな細かい内容が出題されるのでなんとなくの理解だと引っ掛けに引っかかってしまいます

試験時間は2時間でぱっぱと答えていけば1時間もあれば終わる感じです
でも日本語がところどころおかしい場合もあるので慎重に進めると2時間程度は必要かと思います

# 最後に
他の試験を今後も受けるかはわかりませんが、久しぶりに試験を受けて緊張しました
Bitbucketを使った初めてのプルリクエスト

## 概要
会社に入って初めてコードを修正し、プルリクエストを行ったので備忘録として書きます。
## そもそも「プルリクエスト」とは？
僕　「コード修正したので見てください！」
上司「わかったよ、見ておくね。問題なければリポジトリに取り込んでおくよ」
平たく言うとこんな感じです。
つまり、自分が修正したコードをリポジトリに取り込んでもらえるように依頼すること。

## 大まかな手順
①変更したファイルをリモートリポジトリへpushする。
②bitbucket上でプルリクエストを送る。

## 詳細
### 変更したファイルをgit add します。
```gitbash
git add <ファイル名>または<ディレクトリ名>
```
※思考停止で"git add ."としないように！前のブランチのコードとの差分が分からなくなってしまいます。

### 変更内容を確認
  `git status`というコマンドでは以下の３つを確認することができます。
　・git add されているけどまだ git commit されていないファイルの一覧
　・編集・変更・削除されているが、まだ git add されていないファイルの一覧
　・Git管理されていない、かつ .gitignore で管理除外対象にもされていないものの一覧
参考：https://qiita.com/tommy_aka_jps/items/af536a7c20747f99aa42

### コミットする。
```
git commit -m 'コミットメッセージ'
```
### リモートリポジトリにpushする。
今回は新しくブランチを作成してからのpushだったのでこのようにpushしました。
```
git push <ブランチ名>
```
※上のコマンドを実行することでbitbucket上にブランチを作成することなくpushされました。

### bitbucket上でプルリクエストを実行
対象のブランチへ移動し、「プルリクエストを作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301963/8251d1bf-2e91-adb0-5977-ae93e6ae22f3.png)

①～⑤までを記入します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301963/8d4713b3-ea21-5a74-497f-8adb76e2d3b5.png)
①自分が修正したブランチ
②とりこんでもらうブランチ(master)
③変更のタイトル
④変更の詳細
⑤レビュー担当者(今回は上司に送りました。)

画像の下部分が切れていて見えませんが、「プルリクエストを作成」というボタンを押して完了です。

### 最後に
早く仕事覚えたいです。
light sailでサクッとnginx、Laravelでアプリケーションをデプロイする

light sailはEC2やRDS、VPCのコンパクト版。
１つずつ使うとコスト高なので軽いシステムとかデータの少ないホームページとかであればlight sailで十分な気がしてます。


light sailを選択するとまずこんな画面が出てきます。
![7A5E17DB-7E77-482B-960E-020EB0E9BAAB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522723/63c9ae42-8d90-cbfd-897d-42ce2a8811a5.png)

# Webサーバインストール
まずはOSとwebサーバをインストールします。
これが選択するだけでできるのでとてもラクです。


![E611E454-BF1C-4A5A-A5A4-47AA71E5BB25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522723/95d40c5b-4066-1f99-cd41-46b895485d1e.png)
Linux/Unixとnginxを選択しました。
次にメモリに応じたプランを選んで作成完了。僕は512MBの最小スペックを選択しました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522723/16a377d1-36e1-270e-f973-256c6c1ae509.png)
こんな感じでIPアドレスが振られます。
URLでip入力するとnginxの画面が表示されればOK。
これでnginxのインストールは完成

# Laravelプロジェクトのインストール
まずはssh接続します。

~~keyがあるはずなので任意のディレクトリにダウンロードします。
usernameとか注意してくださいね。ec2-userじゃないです。
ssh -i /Users/y.onodera/.ssh/tenjin_company.pem bitnami@13.125.116.248~~

``Connect using SSH`` のボタンを押せばブラウザ上で接続してくれます。便利。


stack/nginx/html/に移動します。(たぶんlight sailはstackフォルダに諸々打ち込まれてると思われ）
``$cd stack/nginx/html/``

laravelプロジェクト作成
``$composer create-project --prefer-dist laravel/laravel laravel``
これでLaravelはインストールできました。

# nginxの設定変更
nginxをLaravel/public/index.phpを見に行くために設定変更します。

``$cd /home/bitnami/stack/nginx/conf``
``$vim nginx.conf``

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522723/780fa8ee-8e97-b20c-3189-a3ca1ce16c36.png)
rootとindexを追記します。（index.htmlとindex.htmは不要ですが書いちゃってました）

# nginxを再起動する
最後にnginxを再起動しましょう。
``$sudo /opt/bitnami/ctlscript.sh restart nginx``　

※仮想サーバーだからなのか、sudo nginx -s reloadは実行できないです

Laravelはなぜかstorage配下のlog,view,sessionディレクトリが読み込めないのでchmodで権限変更してあげてください。

これでLaravelの準備ができたので、URLにip入れるとLaravelのトップページが表示されるはず

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2522723/50b0e61c-7a08-19df-1a22-3f4097d6ffd9.png)

おわり。
Kotlin KoansでKotlin入門　第３回：Default arguments

# はじめに
公式の問題集[「Kotlin Koans」](https://play.kotlinlang.org/koans/overview)を解きながらKotlinを学習します。

過去記事はこちら
- [第０回：Kotlin Koansについて](https://qiita.com/kosuke1/items/41d192af63485bfc8cb8)
- [第１回：Simple Functions](https://qiita.com/kosuke1/items/5862a3ece96082a62e67)
- [第２回：Named arguments](https://qiita.com/kosuke1/items/2af11262852ee41b5da7)

# 問題
[Default arguments](https://play.kotlinlang.org/koans/Introduction/Default%20arguments/Task.kt)

Javaで foo() のオーバーロードがいくつかあるとします。
```Java
public String foo(String name, int number, boolean toUpperCase) {
    return (toUpperCase ? name.toUpperCase() : name) + number;
}
public String foo(String name, int number) {
    return foo(name, number, false);
}
public String foo(String name, boolean toUpperCase) {
    return foo(name, 42, toUpperCase);
}
public String foo(String name) {
    return foo(name, 42);
}
```

これらのJavaのオーバーロードをすべてKotlinの1つの関数に置き換えることができます。
foo関数の宣言を、fooを使ったコードがコンパイルできるように変更します。
デフォルト引数と名前付き引数を使います。

```Kotlin
fun foo(name: String, number: Int, toUpperCase: Boolean) =
        (if (toUpperCase) name.uppercase() else name) + number

fun useFoo() = listOf(
        foo("a"),
        foo("b", number = 1),
        foo("c", toUpperCase = true),
        foo(name = "d", number = 2, toUpperCase = true)
)
```

上記の修正前コードを実行すると以下のエラーが発生します。
```
No value passed for parameter 'number'
No value passed for parameter 'toUpperCase'
No value passed for parameter 'toUpperCase'
No value passed for parameter 'number'
```
引数 'number' 'toUpperCase' に渡された値がないというエラーですね。


# 問題のポイント
Javaだと関数fooが４つに分かれているのを、デフォルト引数を使って１つの関数で定義します。
引数 'number' 'toUpperCase' を指定しなくても関数fooが呼び出せるように修正します。


# 解答例
引数 'number' 'toUpperCase' に初期設定を追加しました。
初期設定を追加することで関数fooを呼び出すときに、引数nameだけを指定して`foo("a")`のような関数呼び出しができるようになります。

```Kotlin
fun foo(
    name: String, 
    number: Int = 42, 
    toUpperCase: Boolean = false
) = (if (toUpperCase) name.uppercase() else name) + number
```
データサイエンス100本ノック回答メモ（SQL編）【1-20】

# 始めに
筆者がデータサイエンス100本ノックSQL編を実施するにあたって、学んだことをメモ書きしたものです。
あくまで筆者の学習履歴を残すものになります。

# 本編
## 1
- 特になし
## 2
- 特になし
## 3
- 特になし
## 4
- WHEREの使い方を覚えよう
## 5
- ANDの使い方を覚えよう
## 6
- 複数の条件式を覚えよう。
- 数学と同様に（）を使って条件式は整備するのがポイント
## 7
- 数値の範囲指定をする時はBERWEENを使おう
## 8
- 条件の否定は"!="で表現
- "<>"でもうまくいくっぽいけど。
## 9
- ベンズを思い出せ。
## 10
- 部分一致での検索は'LIKE'を使う。
- かつ、'%'も併用しよう。
## 11
- 特になし
## 12
- '%'で文字列囲めば部分一致検索可能。
- 特定の言葉を含む文字列の検索が出来る。
- '%'はワイルドカード的な位置づけ。
## 13
- '~':の使い方を覚えよう。正規表現を使ったパターン一致の時に使うらしい。LIKEではないので注意。
- '^':文字列の先頭を意味するらしい。初めて見た。
- '[A:F]':これでA～Fまでを意味するらしい。数学で似たようなの見たことあるの以来の出会い。覚えよう。
- ↓結果こうなるらしい
```
%%sql
SELECT *
FROM customer
WHERE status_cd ~ '^[A:F]'
LIMIT 10
;
```
## 14
- 13の数値・文字末尾検索パターン。
- $：文字列の末尾を意味する。^じゃない。
```
%%sql
SELECT *
FROM customer
WHERE status_cd ~ '[1:9]$'
LIMIT 10
;
```
## 15
- これはわからん。初めてみた。
- '.'：任意の一文字
- '*'：0回以上の繰り返し
- 要するに「A:Fで始まる & ワイルドカード（=.) がX回(=*) & 1:9で終わる」を探すSQLになる。難しくなってきた。

```
%%sql
SELECT *
FROM customer
WHERE status_cd ~ '[A:F].*[1:9]$'
limit 10
;
```
## 16
- これも初めてみた。
- {数字}：指定された数字の回数の繰り返し
- 要するに、電話番号が数値3桁-3桁-4桁で構成されている電話番号を探すSQLを作れる。
- 問題文が自分には理解できなかった。3,3,4桁以外の電話番号もデータベースにあるんかな？
- →テーブルみたら、2桁、4桁、3桁とかあった。つまり、これらを省くことができる
```
%%sql
SELECT *
FROM store
WHERE tel_no ~ '^[0-9]{3}-[0-9]{3}-[0-9]{4}$'
;
```
## 17
- 'ORDER BY'と'ASC'を覚えればOK。
- LIMITつけ忘れてPCフリーズした注意。
- これは簡単。
## 18
- 17の降順版。
- DESC：降順を覚えればOK
## 19
- 初めてみた。
- RANKで順位を表示できる。
- OVERはOVER句らしい
- 難しい。OVER句が何かよくわからん。RANKにかかっている窓関数なるものらしい。
```
%%sql
SELECT customer_id, amount, 
　RANK() 
　　OVER(ORDER BY amount DESC) AS ranking
FROM receipt
Limit 10
;
```
## 20
- 19の同一順位は別順位を表示するバージョン
-  ROW_NUMBER()をRANKの代わりに使うこと
```
%%sql
SELECT customer_id, amount, 
    ROW_NUMBER() OVER(ORDER BY amount DESC) AS ranking
FROM receipt
LIMIT 10
;
```
# 回答にあたって参照・引用させて頂いた記事
https://qiita.com/Strix9289/items/9dfe4c911f6c206ff215
【Rails】HerokuのストレージにAWS S3を設定

### 本番アプリケーションでクラウドストレージを使う設定
aws-sdk-s3 gemを追加する。

```:Gemfile
・
・
gem 'rails',                   '6.0.4'
gem 'aws-sdk-s3',              '1.46.0', require: false
・
・
・
```

```
$ bundle install
```




### AWSでS3でバケットの作成

##### AWSのIAM（Identity and Access Management）サービスでユーザーを作成

I AMユーザー画面
↓
左側のユーザー選択
↓
ユーザーを追加
↓
ユーザー名には使う目的に近い名前などを設定、AWS 認証情報タイプを選択はアクセスキー - プログラムによるアクセスにチェック
↓
一番右の既存のポリシーに直接アタッチクリック
ポリシーのところは一番上にあるAdministratorAccessにチェック
↓
タグの追加 (オプション)は空のまま進む
↓
ユーザー作成
↓
アクセスキー IDとシークレットアクセスキーが表示されるのでコピー時て保存しておく（csvがダウンロードできるのでそれを保存しておくなど）
↓
バケット作成をクリックして重複のない一意の名前をつけて作成（設定はデフォルト）

### Herokuに変数の設定

```
$ heroku config:set AWS_ACCESS_KEY="accessキー"
$ heroku config:set AWS_SECRET_KEY="secretキー"
$ heroku config:set AWS_REGION="リージョン名"
$ heroku config:set AWS_BUCKET="bucket名"
```
リージョン名はS3のホーム画面の作成したバケットのところに表示されている。


### RailsでストレージオプションにAWSを追加する

```config/storage.yml
・
・
amazon:
  service: S3
  access_key_id:     <%= ENV['AWS_ACCESS_KEY'] %>
  secret_access_key: <%= ENV['AWS_SECRET_KEY'] %>
  region:            <%= ENV['AWS_REGION'] %>
  bucket:            <%= ENV['AWS_BUCKET'] %>
・
・
・
```

### Active Storageサービス設定パラメータを変更

```config/environments/production.rb
・
・
・
config.active_storage.service = :amazon
#　localに戻したくなったら
# config.active_storage.service = :local
・
・
・
```

でデプロイして終わりです
IoTとはなんぞや

# IoTを一言でまとめると
モノをインターネット経由で通信することです。

# 概要
IoTとは、Internet Of Thingsの略でよく __モノのインターネット__ と訳されます。
別々に動いていたモノをオンライン上で接続することでより便利にしよう。っていう考え方です。

# 背景
IoTという言葉をTVやCMでよく聞くようになりましたが、それには次のような理由があります。
__・理由1：センサーや機器が安価になってきた__
　スマホのような電子端末の普及率の上昇 →　センサーや機器の需要増加 →　大量生産の技術が発展 → 1台あたりの単価が下落
__・理由2：ネットの普及率の上昇__
　→モノをネットに接続するためには、ネットが普及していることが必須です。昨今は大半の家庭が家庭内LANを持つようになったためにIoTが普及しやすい環境になりました。

他にもいろんな要因がありますが上記の2点が主な要因です。
つまり、IoTの考え方は以前からありましたが、それを実現できる環境が整ってきたことで、急速にIoT対応の端末が広がったのです。

# モノをオンライン上で接続することでどうなる？
__・例①：エアコン__
従来は、人が寒い(または暑い)と感じた時にリモコンで電源をONにして、だいたい心地いいであろう温度に人が設定していました。
　　↓
IoT機能搭載のエアコンは、天気予報と連動して自動で温度を調整したり、スマホと連動して住人が家に近づいたタイミングで自動で電源を入れたり、使用者のデータを蓄積して分析することで最適な設定にしたりといったことができます。

※ちなみに最後に挙げた機能はIoTとAIの融合です。
別の記事で説明しますが、 __新三種の神器__ と呼ばれる「IoT×[AI](https://qiita.com/7_inai_/items/095f95279a7257eaa01b)×[ビッグデータ](https://qiita.com/7_inai_/items/0bbce95823ca7ae9ae2e)」は密接に関わっているため、関係性も理解した方がわかりやすいと思います。

__・例②：工場__
工場でもIoT対応の設備を導入することで多くのことが実現できます。
・設備が壊れてからの対応 
　→ 設備が壊れる予兆を察知して壊れる前に対応（予知保全）
・稼働データを作業員が手動で取得
　→　設備から自動でデータを抽出
・設備のところまで作業員が行ってから作業
　→ PC上で設備を遠隔操作

# 終わりに
いままでオフラインで動いていたモノでも、オンラインに接続することで可能性が無限大に広がるところがIoTのおもしろいところだと私は思います。
最後までお付き合いくださりありがとうございました。
AWSのSQS(FIFO)でContentBasedDeduplicationで怒られたときの解決方法

# 環境
AWS SQSでFIFOタイプを使用

# エラーメッセージ
```
The queue should either have ContentBasedDeduplication enabled or MessageDeduplicationId provided explicitly
```

# 解決方法
1. AWSのコンソールにログイン
1. キューを選択
1. 画像の赤枠の「編集」をクリック
![スクリーンショット 2022-03-07 22.34.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199988/a1241b03-0137-e7d4-d22a-32ded4b39260.png)
1. 「コンテンツに基づく重複排除」にチェックを入れる
![スクリーンショット 2022-03-07 22.39.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199988/43520a4e-9dc0-2bef-a81b-1a2554c7c1c5.png)

# おわりに
以上。割と時間をかけてしまったので、お役に立つと幸いです！