OmniAICreator/Qiita-1.07M huggingface dataset:
AWSクラウドプラクティショナーを勉強期間３日で受験した話

掲題の通りです。

# なぜ3日
4月の第2週、IPAの試験が終わり、次の勉強は何にしようかな…と考えていたところ、クラウドプラクティショナーが目に止まった。
ちらちらと情報収集してみると、短い人で一週間程度で取得している人がいるらしい。
週末に受験するか〜と思ったら、空いてる会場がない。
ギリギリ妥協できる会場で４日後。マァ良いかと思い予約。
書籍を買い、よし勉強するか〜と思った時には3日前。

# バックグラウンド
プログラマ4年目。AWSは仕事に使う一部の機能を触り始めて2ヶ月ほど。(仕事で使ってる部分は今回の試験ではほぼ出なかった…)
インフラの知識はあまりない。水平スケール垂直スケールくらいはわかる程度。

# 結果
合格しました。
ギリギリのスコアで、当日もハラハラしましたが結果よければなんとやら…
![C256093B-2BE4-4281-873F-D4E6D93BE98B.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409578/a7701d75-363e-617a-4b1d-e31a651f072c.jpeg)

# 勉強方法
いろんなところでおススメと見かける2つをやりました。
・[AWS認定資格試験テキスト AWS認定 クラウドプラクティショナー](https://www.amazon.co.jp/dp/4797397403/ref=cm_sw_r_awdo_619VTAF3H5A4KC3K54BZ):4時間
通読する。読まなくても良いか〜と思って飛ばした請求の箇所が得点率が低かったので、やっぱり一度は読んだほうがいいと思う。読んだのは一度だけ。
![45C8C366-1B19-4DC8-B852-78BF501AD79D.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409578/68538c95-4655-0b32-4545-6e39980a8c85.jpeg)

・[【2022年版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（7回分455問）](https://www.udemy.com/course/aws-4260/) 所要時間:6時間程度
　レビューにもある通り、応用部分は過剰な知識と思いました。しかし短時間で合格を狙いたい人は目を通すべきかもしれません。応用の問題に類似した内容は数問しかでませんが、浅い知識で挑む場合はその一問で助かる場合もあるからです。
　基本的には、
初見で解く(20分くらい)
→答え合わせ(解説を読む,30分〜1時間弱くらい)
→もう一回解く(正答率85%超,20分くらい)
のように一周し、その後(日数に余裕があれば)試験日まで記憶維持程度で良いです。応用情報②までやった。

# 当日
夕方から試験だったので13時頃までudemy詰め込み。
その後は諦めて精神統一に努めました。


# 所感
いざ問題を目にして、なんじゃこりゃ！わからん！というのはあまりなかったです。
でも問題を解いて、合格だと確信できなかったので2回見直しをしました。本来こんな短期間で準備するでもなく、身についたかといえばあまり自信はない…という感じなので、オススメはできません。
何かしらの理由で短期間で受験を迫られた際は10時間程度で合格できるんだな、程度のご参考までに。
PowerQuery: 全角のひらがな・カタカナを半角ﾋﾗｶﾞﾅ・ｶﾀｶﾅへ

# 背景
特殊な用途下で、全角のかなを半角にする必要があったので用意した記録

# 動作例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/db2b95e4-b8ba-a746-bbed-960a089919d7.png)

こんな感じで、全角の文字を半角へ変換します。

# 説明
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e6502aff-a51c-120b-9692-d42fa16e8ca2.png)

Unicode 表をみるとわかるんですが・・Ascii のように文字コードの範囲を指定して対応したものを List で渡すことが出来ない。
ってことで・・全部置換リスト作るしかないかなって感じで作ってみた

https://en.wikipedia.org/wiki/Hiragana_(Unicode_block)

カタカナも同じ

https://en.wikipedia.org/wiki/Katakana_(Unicode_block)

# Power Query

以下を Query Editor で貼り付けたら使うだけ。

```C#:全角かなカナを半角へ
// かなカナを半角へ
(originalText as text) as text =>
let
    kanaList = List.Zip(
        {   // 全角カナ　を　半角カナ　に変換する。[ひらがな](https://en.wikipedia.org/wiki/Hiragana_(Unicode_block)) [カタカナ](https://en.wikipedia.org/wiki/Katakana_(Unicode_block))
            {"ぁ","あ","ぃ","い","ぅ","う","ぇ","え","ぉ","お","か","が","き","ぎ","く","ぐ","け","げ","こ","ご","さ","ざ","し","じ","す","ず","せ","ぜ","そ","ぞ","た","だ","ち","ぢ","っ","つ","づ","て","で","と","ど","な","に","ぬ","ね","の","は","ば","ぱ","ひ","び","ぴ","ふ","ぶ","ぷ","へ","べ","ぺ","ほ","ぼ","ぽ","ま","み","む","め","も","ゃ","や","ゅ","ゆ","ょ","よ","ら","り","る","れ","ろ","ゎ","わ","ゐ","ゑ","を","ん","ゔ","ゕ","ゖ","ァ","ア","ィ","イ","ゥ","ウ","ェ","エ","ォ","オ","カ","ガ","キ","ギ","ク","グ","ケ","ゲ","コ","ゴ","サ","ザ","シ","ジ","ス","ズ","セ","ゼ","ソ","ゾ","タ","ダ","チ","ヂ","ッ","ツ","ヅ","テ","デ","ト","ド","ナ","ニ","ヌ","ネ","ノ","ハ","バ","パ","ヒ","ビ","ピ","フ","ブ","プ","ヘ","ベ","ペ","ホ","ボ","ポ","マ","ミ","ム","メ","モ","ャ","ヤ","ュ","ユ","ョ","ヨ","ラ","リ","ル","レ","ロ","ヮ","ワ","ヰ","ヱ","ヲ","ン","ヴ","ヵ","ヶ"},
            {"ｱ","ｱ","ｲ","ｲ","ｳ","ｳ","ｴ","ｴ","ｵ","ｵ","ｶ","ｶﾞ","ｷ","ｷﾞ","ｸ","ｸﾞ","ｹ","ｹﾞ","ｺ","ｺﾞ","ｻ","ｻﾞ","ｼ","ｼﾞ","ｽ","ｽﾞ","ｾ","ｾﾞ","ｿ","ｿﾞ","ﾀ","ﾀﾞ","ﾁ","ﾁﾞ","ﾂ","ﾂ","ﾂﾞ","ﾃ","ﾃﾞ","ﾄ","ﾄﾞ","ﾅ","ﾆ","ﾇ","ﾈ","ﾉ","ﾊ","ﾊﾞ","ﾊﾟ","ﾋ","ﾋﾞ","ﾋﾟ","ﾌ","ﾌﾞ","ﾌﾟ","ﾍ","ﾍﾞ","ﾍﾟ","ﾎ","ﾎﾞ","ﾎﾟ","ﾏ","ﾐ","ﾑ","ﾒ","ﾓ","ﾔ","ﾔ","ﾕ","ﾕ","ﾖ","ﾖ","ﾗ","ﾘ","ﾙ","ﾚ","ﾛ","ﾜ","ﾜ","ｲ","ｴ","ｦ","ﾝ","ｳﾞ","ｶ","ｹ","ｱ","ｱ","ｲ","ｲ","ｳ","ｳ","ｴ","ｴ","ｵ","ｵ","ｶ","ｶﾞ","ｷ","ｷﾞ","ｸ","ｸﾞ","ｹ","ｹﾞ","ｺ","ｺﾞ","ｻ","ｻﾞ","ｼ","ｼﾞ","ｽ","ｽﾞ","ｾ","ｾﾞ","ｿ","ｿﾞ","ﾀ","ﾀﾞ","ﾁ","ﾁﾞ","ﾂ","ﾂ","ﾂﾞ","ﾃ","ﾃﾞ","ﾄ","ﾄﾞ","ﾅ","ﾆ","ﾇ","ﾈ","ﾉ","ﾊ","ﾊﾞ","ﾊﾟ","ﾋ","ﾋﾞ","ﾋﾟ","ﾌ","ﾌﾞ","ﾌﾟ","ﾍ","ﾍﾞ","ﾍﾟ","ﾎ","ﾎﾞ","ﾎﾟ","ﾏ","ﾐ","ﾑ","ﾒ","ﾓ","ﾔ","ﾔ","ﾕ","ﾕ","ﾖ","ﾖ","ﾗ","ﾘ","ﾙ","ﾚ","ﾛ","ﾜ","ﾜ","ｲ","ｴ","ｦ","ﾝ","ｳﾞ","ｶ","ｹ"}     
        }
    ),
    result = List.ReplaceMatchingItems(Text.ToList(originalText), kanaList)
in
    Text.Combine(result)
```

# あとがき
恐らく二度と使うことはないだろうなぁというレベル・・
年月日時分などの秒数／分数／時間／日数

# 単位変換表

| 単位 | 秒 | 分 | 時間 | 日 |
|:--|--:|--:|--:|--:|
| 分 | 60 | 1 | | |
| 時間 | 3600 | 60 | 1 | |
| 日 | 86400 | 1440 | 24 | 1 |
| 週 | 604800 | 10080 | 168 | 7 |
| 月(28日) | 2419200 | 40320 | 672 | 28 |
| 月(29日) | 2505600 | 41760 | 696 | 29 |
| 月(30日) | 2592000 | 43200 | 720 | 30 |
| 月(31日) | 2678400 | 44640 | 744 | 31 |
| 年(閏なし) | 31536000 | 525600 | 8760 | 365 |
| 年(閏あり) | 31622400 | 527040 | 8784 | 366 |
| 4年 | 126230400 | 2103840 | 35064 | 1461 |
| 100年(閏なし) | 3155673600 | 52594560 | 876576 | 36524 |
| 100年(閏あり) | 3155760000 | 52596000 | 876600 | 36525 |
| 400年 | 12622780800 | 210379680 | 3506328 | 146097 |

※ 閏年は、4年間隔だが、100年間隔は「なし」で、400年間隔は「あり」となっている。

| 年 | 日 | 計算 |
|--:|--:|:--|
| 4 | 1461 | 365 × 3 ＋ 366 |
| 100 | 36524 | 1461 × 24 + 1460 |
| 400 | 146097 | 36524 × 3 + 36525 |


# 2<sup>n</sup> 秒の変換表

| n | 秒 | 年 | 日 | 時 | 分 | 秒 |
|--:|--:|--:|--:|--:|--:|--:|
|  6 |         64 |    0 |   0 |  0 |  1 |  4 |
|  7 |        128 |    0 |   0 |  0 |  2 |  8 |
|  8 |        256 |    0 |   0 |  0 |  4 | 16 |
|  9 |        512 |    0 |   0 |  0 |  8 | 32 |
| 10 |       1024 |    0 |   0 |  0 | 17 |  4 |
| 11 |       2048 |    0 |   0 |  0 | 34 |  8 |
| 12 |       4096 |    0 |   0 |  1 |  8 | 16 |
| 13 |       8192 |    0 |   0 |  2 | 16 | 32 |
| 14 |      16384 |    0 |   0 |  4 | 33 |  4 |
| 15 |      32768 |    0 |   0 |  9 |  6 |  8 |
| 16 |      65536 |    0 |   0 | 18 | 12 | 16 |
| 17 |     131072 |    0 |   1 | 12 | 24 | 32 |
| 18 |     262144 |    0 |   3 |  0 | 49 |  4 |
| 19 |     524288 |    0 |   6 |  1 | 38 |  8 |
| 20 |    1048576 |    0 |  12 |  3 | 16 | 16 |
| 21 |    2097152 |    0 |  24 |  6 | 32 | 32 |
| 22 |    4194304 |    0 |  48 | 13 |  5 |  4 |
| 23 |    8388608 |    0 |  97 |  2 | 10 |  8 |
| 24 |   16777216 |    0 | 194 |  4 | 20 | 16 |
| 25 |   33554432 |    1 |  23 |  8 | 40 | 32 |
| 26 |   67108864 |    2 |  46 | 17 | 21 |  4 |
| 27 |  134217728 |    4 |  92 | 10 | 42 |  8 |
| 28 |  268435456 |    8 | 184 | 21 | 24 | 16 |
| 29 |  536870912 |   17 |   4 | 18 | 48 | 32 |
| 30 | 1073741824 |   34 |   9 | 13 | 37 |  4 |
| 31 | 2147483648 |   68 |  18 |  3 | 14 |  8 |
| 32 | 4294967296 |  136 |  37 |  6 | 28 | 16 |
xeory_baseのfont-awesomeをバージョン更新する


# 概要
WordPressのテンプレート「xeory_base」にて、デフォルトでfont-awesomeが組み込まれてるが、バージョン4.5.0なので古い。

バージョン6.1.1のCDNを使うように修正する。

# 修正箇所

```lib/functions/asset.php
add_action('wp_enqueue_scripts', 'bzb_add_awesome_style', 9);
function register_awesome_font(){
//   wp_register_style( 'font-awesome', get_template_directory_uri() . '/lib/fonts/font-awesome-4.5.0/css/font-awesome.min.css');
  wp_register_style( 'font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css');
}
```

# リンク
バズ部のテンプレート「xeory_base」
https://xeory.jp/
P2P とは

## 勉強前イメージ

見たことあるけど、何だっけ。。。
直つなぎ？

## 調査

### P2P とは

peer-to-peerの略で、サーバを介さずに端末同士で通信のやり取りを行う技術のことを指します。
ピアツーピア だったり、 ピーツーピー と呼ばれています。
P2PのPeerには対等な立場での情報通信を行うという意味があり、
対等な立場で端末同士がやり取りを行うネットワークを `P2Pネットワーク` といいます。

P2Pネットワークの対義？はクライアントとサーバという立場で情報を交換する クライアント・サーバシステム です。

### P2Pの種類

P2Pにはいくつか種類と通信方式があるので記載します。

- ピュアP2P

従来のP2P通信で、上記に記載している通りの
クライアント同士で通信を行っているものになります。

- ハイブリッドP2P

P2Pにサーバを使用しているネットワークになります。
クライアント・サーバシステムと違うのはクライアント同士が通信を行っているが、サーバにはデータが保存されている点になります。

- スーパーノード型P2P

ネットワークの中からいくつかスーパーノードが選定されてノードの情報を管理。
他のスーパーノードと負荷分散してノードの管理を行います。

### P2Pの特徴

- データを分散して管理が可能

クライアントでデータを持ってるので負荷分散が可能です。

- ダウンタイムの時間を少なくできる

P2Pではサーバ・クライアントシステムより回線が軽く分散されているため
ダウンタイムを少なく出来ます。

- 拡張性がある

すべての処理がサーバに集中するサーバ・クライアントシステムに比べて
拡張性があり、対障害性が高いです。

## 勉強後イメージ

雰囲気知ってたけど、、ってかんじ。
ちゃんと見といてよかった。

## 参考

- [P2P(ピアツーピア)とは？仕組みから活用例まで詳しく解説](https://udemy.benesse.co.jp/development/blockchain/p2p.html)
- [P2P 【Peer to Peer】 PtoP / ピアツーピア / ピアトゥピア](https://e-words.jp/w/P2P.html)
データフレームのある列をインデックスに設定する　df.set_index()

ある列をインデックスに設定したい！
そんな時に、用いるのが`set_index()`です
df = df.set_index("インデックスに設定したいカラム名")

例えば、３列目くらいに`age`というカラムがあったとします。
年齢ごとにデータをまとめたいとき、一番左の列（インデックス列）にあればとてもデータとして
見やすいですよね。
是非使ってみてください！
北大生のための電脳空間チートシート2022

# 北大生のための電脳空間チートシート
北大では入学することでメールアドレスやgoogleドライブなどの様々な電脳資源やerudoamなどのネットワークへのアクセス権限が付与される.
が, これらの説明がほとんどない！！！！！
北大生であることを利用していろいろ電脳空間で遊ぶためのチートシートを作ってみようということでDovahaの知る限りの情報をまとめてみます！！

これを見た皆さんも便利そうなことがあったらコメントにて教えてください.

## eduroamへのアクセス権限
北大生はELMS ID及びそのパスワードを利用してWifi:HINES LANへと接続が可能だが, ほぼ同一のプロファイルを利用してeduroamを敷設している機関にてwifi:eduroamにもアクセスができる.
[Eduroam 利用者向け情報](https://www.eduroam.jp/for_users)
利用時は
|ID|[ELMS ID]@hokudai.ac.jp|
|:--:|:--|
|Password|ELMSのパスワードで接続すること.|

[Eduroam利用可能地点マップ](https://monitor.eduroam.org/eduroam_map.php?type=jp)より国内での利用場所を確認できる.
他大学での学会などの際に利用できるかも？

## サブメールアドレスの取得

正直, 今の北大の標準メールアドレスはダサい.

何で Familyname.Firstname.Checkdigit@elms.hokudai.ac.jp なんて味気のないメールアドレスなのか.

これを解決する方法はあって, 北大のメールアドレスはエイリアス設定というものがある為, 受信用のアドレスを生成できる.

1. ELMSにログインする.
1. 左側のhelpをクリックする.
1. 設定に移動する.
1. メールエイリアス設定をクリック.
1. 左側のエイリアス管理をクリック.
1. 下の新しいエイリアスに入力し, OKを押す.

これで新しい受信用メールアドレスが生成される.

ただし, これだけだと送信時に相手に表示されるメールアドレスは 氏名.チェックデジット@で始まるメールアドレスになるので注意.

送信用のメールアドレスもエイリアスアドレスにするには以下の設定をする必要がある.

1. gmailの右上の設定アイコン(⚙マーク)から全ての設定
1. アカウントタブをクリック
1. 名前: から他のメールアドレスを追加をクリック
1. 出てきた別ウインドウのメールアドレスにエイリアス設定したメールアドレスを追加.(エイリアスとして扱いますにチェック)
1. 次のステップをクリック

そうすると名前のところにエイリアスアドレスが追加される.

この状態でメールの作成を押すと差出人のところにプルダウンタグが作成されるのでここからエイリアス名義でメールが送れる.

メーラーを利用したい場合, 少なくともThunderbirdから正しく設定するとエイリアス名義でメールを送れることを発見した.

1. 左側のメールアドレス一覧でメールアドレスを右クリックして設定を押す
1. 右下に出てくる差出人情報を管理をクリック
1. 出てきたウインドウで追加をクリック
1. 設定の名前に自分の名前を, メールアドレスにエイリアスアドレスを入力. 送信サーバーが北大のモノになっているかチェックしてOKを押す.

この状態でメールを作成すると, 送信時にエイリアスアドレスを選べるようになる.

これらの設定を行うとクソダサアドレスじゃないアドレスとしてメールが送れるようになる.

## Adobe Creative cloud 半年4000円

大学生協経由で契約するとAdobe Creative cloudが半年4000円で契約できる.
[Adobe Creative Cloud　包括ライセンスB　6か月間](https://www.hok-univ.com/hokudai/products/detail.php?product_id=471)
年間8000円のプランもあるので異常に安い.
普通は学割でも年40000なので本当に安い.

## 学生向けMicrosoft azure

[学生向けMicrosoft azure](https://azureforeducation.microsoft.com/ja-jp/institutions)より, windowsのEducation版のOSを無料で入手できる.

自作PCを作る際にOS代が浮くのは非常にメリットがでかい.そのほかにもいろいろなソフトウェアが入手できるので使ってみるのは有りだと思う.

### 7/12追記
4/26段階ではedcucationのシリアルコードが入手できたが, 現在入手不可.
以前も入手不可になってからまた入手可能になったことがあったため, また入手できるようになることを期待する.
### 2024/04/08 追記
今年は無事入手できた.


## Microsoft office 365
ELMSのトップページより大学提供ソフトウェア利用申請を行うことでMocrosoft officeが無料で利用できる.
学生の間だけのメリットだが, パソコンを増やしてもオフィスを買わずに済むのはでかいよね.
~~アップデートの仕方は不明.~~
Terraform 学習資料


## 書籍

基礎から学ぶ Terraform
https://amzn.to/3vhVTFe
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18351/0c4a3534-54b7-c0c4-e570-56c5c1a7faf4.png)


実践Terraform　AWSにおけるシステム設計とベストプラクティス
https://amzn.to/3ELuZZy
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18351/ae4b183e-4ef6-4ffc-7ed4-63fe8771c990.png)

Software Design (ソフトウェアデザイン) 2022年01月号 [雑誌]
https://amzn.to/3LgIXoT
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18351/030b72a5-c059-d529-6956-8780593b595a.png)


その他
[TerraformでFargateを構築してGitHub Actionsでデプロイ！Laravel編](https://amzn.to/3vgyEeU)
[はじめての人のための Terraform for AWS](https://amzn.to/38qnHhJ)
[AWSとTerraformで学ぶプロダクションレディなKubernetes](https://amzn.to/3kaYIBM)

## 動画学習資料（Udemy）

[米シリコンバレーDevOps監修！超Terraform完全入門(0.14) + AWS DevOps IaCをマスター！ | Udemy](https://www.udemy.com/course/hashicorp-terraform-aws-devops-iac)

[AWS と Terraformで実現するInfrastructure as Code | Udemy](https://www.udemy.com/course/iac-with-terraform)


## ハンズオン学習資料（有料）

[【現役エンジニア向け】AWSでシングル構成の環境からスケーラブルな環境を構築するノウハウを学ぼう with Terraform | Techpit](https://www.techpit.jp/courses/119)


## 公式学習資料（英語）

[Terraform Tutorials - HashiCorp Learn](https://learn.hashicorp.com/terraform)
Railsに簡単な検索フォームを作ってみた(Ransack）

自分の作成している掲示板サイトに簡単な検索フォームを作りたいと考え、Ransackというgemを使い、記事を参考にしながら作成しました。

参考記事
https://www.sejuku.net/blog/100824

環境とver
ruby '2.7.5'
rails '6.1.4'
Docker

github
https://github.com/takoyan33/railsdock4


まず最初に
```Ruby:Gemfile
gem 'ransack'
#ransackを追加
```

```Ruby:ターミナル
bundle install
#dockerの場合、docker-compose run web bundle install
```
これでransackを入れることができました。
次にコントローラーに記述します。
自分の場合、kaminariのgemを入れているのと、降順に表示したいので、
色々後ろについています。
普通に追加する場合は、.page(params[:page]).per(8).all.order(id: "DESC")の後ろは消して大丈夫です。
（良い書き方があれば教えてほしいです。）

```Ruby:boards_controller.rb
 def index
    @boards = params[:tag_id].present? ? Tag.find(params[:tag_id]).boards : Board.all.order(id: "DESC") 
    @boards_count = Board.all.count
    @today_count = Board.created_today.count
    @lastmonth_count = Board.created_last_month.count
    @month_count = Board.created_month.count

    @q = Board.ransack(params[:q])#追加
    @boards = @q.result(distinct: true).page(params[:page]).per(8).all.order(id: "DESC") #追加
  end
```

そして、viewに表示していきます。
ここでポイントは検索したい値を書くことです。
自分の場合は、掲示板（board)のタイトルを検索したいので、
:title_count　にしています！(contは部分一致で表示してくれます。）
そのため、例えば投稿(post)の名前(name)で検索したい場合は、name_contなどにしましょう。

```Ruby:index.html.erb
    <%= search_form_for @q do |f| %>
        <%= f.search_field :title_cont %>
        <%= f.submit %>
    <% end %>
```

これで完成です。
※デザインは雑です。

![スクリーンショット 2022-04-26 20.23.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569989/3357b73b-5a4a-bcb2-cfc0-ab1390912c8a.png)
![スクリーンショット 2022-04-26 20.23.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569989/926ff047-fb0a-f418-c9b3-3bfc3204bf34.png)


慣れると使いやすいGemなどでぜひ一度使ってみてください。
赤文字検索ダイアログを表示するWordVBAの作成＋アドイン化

## WordVBAの作成
Wordの新規作成からVisual Basicを開き、以下のコマンドを張り付ける

```vb:Module1
Sub my_addin()
  Selection.Find.ClearFormatting
  Selection.Find.Font.Color = wdColorRed

  With Selection.Find
    .Text = ""
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindContinue
    .Format = True
    .MatchCase = False  
    .MatchWholeWord = False
    .MatchByte = False
    .MatchAllWordForms = False
    .MatchSoundsLike = False
    .MatchWildcards = False
    .MatchFuzzy = True
  End With

  Application.CommandBars.FindControl(ID:=141).Execute
End Sub
```

## アドイン化
Wordファイルをマクロテンプレート(*.dotm)形式で保存任意のフォルダに保存する
Wordメニューの[ファイル]→[オプション]→[詳細設定]→[全般]から[スタートアップ]を確認する
保存任意のフォルダに作成したテンプレートファイルをスタートアップに格納する
セルをA1に揃えるExcelVBAの作成＋アドイン化

## ExcelVBAの作成
Excelを新規作成しVisual Basicを開き、以下のコマンドを張り付ける

```vb:Module1
Sub　my_addin()
    Dim left_sheet As Worksheet
    Dim all_sheet As Worksheet
    Set left_sheet = Worksheets(1)
    For Each all_sheet In Worksheets
        all_sheet.Select
        all_sheet.Range("A1").Select
    Next
    left_sheet.Select
End Sub
```

## アドイン化
### 保存場所
ExcelファイルをExcelアドイン(*.xlam)形式で以下ののフォルダに保存する
%userprofile%\AppData\Roaming\Microsoft\AddIns\
※ファイル形式を選択するとフォルダは自動的に選択される

### 信頼できる場所の追加
Excelメニューの[ファイル]→[オプション]→[トラストセンター]→[信頼できる場所]に移動する
[新しい場所の追加]からアドインの保存場を追加する

### アドインの追加
Excelメニューの[開発]→[Excelアドイン]に移動する
作成したアドインに☑を入れ[OK]をクリックする
Pymongo4.0以降で[Errno 11001] getaddrinfo failed.になる問題

参考：
https://pymongo.readthedocs.io/en/stable/migrate-to-pymongo4.html
https://pymongo.readthedocs.io/en/stable/changelog.html

1.pythonとmongoDBのバージョンを確認する。
```
Warning PyMongo 4.0 drops support for Python 2.7, 3.4, and 3.5.
Warning PyMongo 4.0 drops support for MongoDB 2.6, 3.0, 3.2, and 3.4.
```

2.uriが正しく記述できているか確認する。
```
uri = "xxx"
client = pymongo.MongoClient(uri)
```

3.directConnection = True　を引数で渡しているか確認する。
```
uri = "xxx"
client = pymongo.MongoClient(uri, directConnection=True)
```
フォルダ内の全Wordファイルから文字列を検索するExcelVBA

## 作成するVBAの要件
sheet1のB4セルに入力された文字列を検索する
検索対象のフォルダはマクロ実行時に選択する
検索単語と、検索単語以降で同じ行に記載された文字列を取得する

## ExcelVBAの作成
Excelを新規作成しVisual Basicを開き、以下のコマンドを張り付ける
```vb:VBAのソースコード
Sub WordGet()

    Dim wdApp As Object
    Dim wDoc As Object
    Dim wDNext As Object
    
    
    Dim fdPath As String, keyWord As String
    Dim objFso As Object
    Dim objFolder As Object
    Dim objSelection As Object
    Dim r As Long
    Dim i As Long
    Dim j As Long
    r = 0
    i = 0


    Set wdApp = CreateObject("Word.Application")
    Application.FileDialog(msoFileDialogFolderPicker).Show
    fdPath = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1)
    keyWord = ThisWorkbook.Sheets("sheet1").Range("B4")

    Set objFso = CreateObject("Scripting.FileSystemObject")
    Set objFolder = objFso.GetFolder(fdPath)


    For Each f In objFolder.Files

        sxx = Right(f.Name, 5)
        If 0 < InStr(sxx, ".doc") Then
            sxx = Left(f.Name, 1)
            If 0 = InStr(sxx, "~") Then
                r = r + 1
                ThisWorkbook.Sheets("sheet1").Cells(r + 4 + i, 2) = f.Name
                i = i + 1

                Set wDoc = wdApp.documents.Open(fdPath & "\" & f.Name, True) '読み取りモードで開く
                Set objSelection = wdApp.Selection
                objSelection.Find.Text = keyWord
                objSelection.Find.Forward = True

                Do While (1)
                    If objSelection.Find.Execute Then
                        i = i + 1
                            ThisWorkbook.Sheets("sheet1").Cells(r + 3 + i, 3) = objSelection.Paragraphs.first.Range.Text
                            j = 0
                        On Error Resume Next
                        Do While (1)
                            j = j + 1
                            ThisWorkbook.Sheets("sheet1").Cells(r + 3 + i, 4) = objSelection.Paragraphs(j).Next.Range.Text
                            If Err.Number <> 0 Then
                                Err.Clear
                                Exit Do
                            End If
                        Loop
                        On Error GoTo 0
                    Else
                        Exit Do
                    End If
                Loop
                wDoc.Close

            End If
        End If
     Next f

     Set objFso = Nothing
     Set objFolder = Nothing
     Set wdApp = Nothing

End Sub
```


参考：https://teratail.com/questions/153936
UnityのCinemachineを使用した際に発生したGC Alloc(0.7KBまたは368bytes)2つのケースについて解決したときのメモ

### 環境
Unity2020.3.11f1から2021.3.0f1にバージョンアップしたプロジェクトファイル
他の環境でも同様のケースが起きるかは未確認です
# CinemachineBrainから約0.7KBのGC Allocが発生していた
似ているケースかどうかの情報を求められていると思うのでその辺りを先に記します。
ProfilerでGC Allocの数値に気付いたタイミングが微妙なのでいつから発生していたかは分かりません。
## 導入の経路
- 2020の環境で初期のStarter Assetsをインポート
- このアセットではCinemachineを使用しているので同じタイミングでCinemachineもインポートしていた
- Unity バージョン2021のLTSが発表されたのでプロジェクトをバージョンアップ
- その後にCinemachineもStarterAssetsもアップデートがきたのでGC解決時点で最新にしています(4/26)
## GC Allocは2ヵ所で発生していた
Profilerで確認すると、
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2642974/411955bf-342a-dd20-5d35-6194d29ed306.png)
1. <font color="red">**CinemachineBrain.LateUpdate()**</font> …赤枠の部分
2. <font color="blue">**GUI.Repaint**</font> …青色の部分

この2パターンから発生していました。どちらもCinemachineBrainから呼ばれていますが連動している訳ではないようです。

1つ目から順に説明します。
## CinemachinePostProcessing (336B)
赤枠で囲った方のGC Allocです。CinemachineBrainのLateUpdate関数からCinemachinePostProcessingクラスのstatic関数を参照しています。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2642974/4f36d46d-92ae-44e3-51b3-51b3f41efe33.png)
この青い選択範囲の処理がGCの原因でした。UnityEventへの操作で無駄なゴミを生成しています。

赤枠で囲ったディレクティブでポストプロセスが2018以降であれば必ずこの辺りを通るはずです。なのでローカルのlayerがnullにならないようにすることで対処します[^1]。
### 対処方法
![03_a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2642974/b97b031b-29be-701d-9612-087f88b5280a.png)
CinemachineBrainを持つGameObjectに、"**Post-process Layer**"コンポーネントをアタッチします。インスペクターとGCサイズに注目してください。
![03_b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2642974/765e8cb0-c28c-aa5f-1b83-4ac55a35f37e.png)
これで多分OKです。コンポーネントさえ付いていればOffにしても問題ありません。
## GUI.Repaint
青色の方のGC Allocです。こっちは実害がないので放置しても問題ないようです。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2642974/accc91b9-93d9-237b-4704-6dc2e88d7c82.png)
OnGUIの処理がGCを発生させています。ですが、エディター上でしか処理されないので、ゲームとして世に出せばGCは発生しません。ここでGCが発生していても軽微な場合放置した方が管理面でも良いかもしれません。

気になるので消したい場合、方法はいくつかありますが、一例としてシンプルな方法を紹介します。
### 対処方法
あえて放置しない場合、このようなスクリプトを用意してください。
```Csharp
using UnityEngine;
public class Example : MonoBehaviour {
    void Start() {
        if (TryGetComponent(out Cinemachine.CinemachineBrain brain) {
            brain.useGUILayout = false;
        }
    }
}
```
これをCinemachineBrainを持つGameObjectにアタッチすると、
![05_a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2642974/37d81d7f-1a9e-b3d0-dc39-ff7f1e26accc.png)
※ GCサイズに注目
![05_b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2642974/1224552b-44bc-fb94-9d23-f660de7120da.png)
これでOKです。<font Color="gray">"WorkMono"は上で用意したExampleスクリプトです</font>
## 動画バージョンもあります
この記事の画像は動画の方から切り取ってきました。
もしよろしければ、動画の方も見ていただけたら嬉しいです。
[YouTube Link](https://youtu.be/JsBnAF9lWuY)

[^1]: <font color="gray">ただ、ポストプロセスを使用しない場合とか結構簡単にこのケースを踏みそうに思うんですけど、私が何か根本的に勘違いしている気がしてます。教えてください。</font>
---
**感想**
初めてQiitaで記事を書きましたが、とても疲れました……
HTMLでも行けそうだったのでごり押しで行こうと思ったんですが、画像とか注釈とか色々うまく行かなくて逆に手間と時間が増えました。
今回は記事内容についてより、QiitaやYouTube、Twitter等で情報発信の作業を一通り確認することが目的だったので、そういう意味では良い勉強になりました。
WindowsでUbuntu 22.04を操作する【リモートデスクトップ】

### 設定を開く
![Screenshot from 2022-04-26 13-35-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/fd0e7b4b-0901-3c25-360b-9cc5905247f9.png)

### 共有からリモートデスクトップを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/046a2594-cc44-5c24-8b06-53256e5dc163.png)

### リモートコントロール を有効にする
*リモートデスクトップアドレス*と*ユーザ名*と*パスワード*をメモする。リモートデスクトップのトグルを二回押す(再起動)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/1057dade-de03-8535-89d7-55261bfcd3f8.png)


### リモートデスクトップ接続を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/b4e0ffba-59d0-8b31-83f2-fd8da2bbd203.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/0c2e9a48-dbc4-1245-1108-de20f3f8ca06.png)

### リモートデスクトップアドレスを入力し、接続を押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/0a144273-6162-2b31-8bec-f9685831c605.png)


### ユーザー名とパスワードを入力し、OKを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/78a91cb8-d4ce-2737-a0bd-75d4cbf57c5d.png)



### はいを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/72ff790f-f437-1415-55f3-f90a2847d416.png)



### 接続完了🎉

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/7dcf3a17-9a67-1e85-cd4e-c92aacec6732.png)

![ezgif-2-4618672824.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/8a2db43f-bace-315a-9095-cb8731a5b1e2.gif)




# 参考
https://forest.watch.impress.co.jp/docs/serial/yajiuma/1405100.html
三角形内の線形補間

三角形の各頂点が値を持つときに、三角形内の任意の位置でその値を線形補間します。



三角形の各頂点位置を$\boldsymbol{p}_0, \boldsymbol{p}_1, \boldsymbol{p}_2$とすると 、三角形内の任意の位置$\boldsymbol{p}$は次のように表現できます。

```math
\boldsymbol{e}_u = \boldsymbol{p}_1 - \boldsymbol{p}_0 \\
\boldsymbol{e}_v = \boldsymbol{p}_2 - \boldsymbol{p}_0 \\
\boldsymbol{p} = \boldsymbol{p}_{0} + u\boldsymbol{e}_u + v\boldsymbol{e}_v\\
(u\geqq0,v\geqq0, u+v\leqq1)
```

ここで各頂点の補間したい値を$C_0,C_1,C_2$とすると、位置$\boldsymbol{p}$における補間値$C$は次のようになります。
```math
C = C_0+u(C_1-C_0)+v(C_2-C_0)
```

ということで、$\boldsymbol{p}$に関して$u,v$が求まれば、補間値$C$が求まります。


先ほどの$\boldsymbol{p}$を各要素ごとに展開すると次のようになります(ここでは2次元の場合を考えますが、3次元でも同じだと思います)。

```math
\boldsymbol{p}_0 = \left(\begin{array}{cc} p_{0x} \\ p_{0y}\\ \end{array} \right),
\boldsymbol{e}_u = \left(\begin{array}{cc} e_{ux} \\ e_{uy}\\ \end{array} \right),
\boldsymbol{e}_v = \left(\begin{array}{cc} e_{vx} \\ e_{vy}\\ \end{array} \right) \\

\boldsymbol{p} = \left(\begin{array}{cc} p_{x} \\ p_{y}\\ \end{array} \right) = \left(\begin{array}{cc} p_{0x}+ue_{ux}+ve_{vx} \\ p_{0y}+ue_{uy}+ve_{vy}\\ \end{array} \right)
```

これを$u,v$についての整理すると次のようになり、$u,v$に関する連立方程式となります。

```math
\left\{
\begin{array}{l}
e_{ux}u+e_{vx}v = p_x - p_{0x} \\
e_{uy}u+e_{vy}v = p_y - p_{0y}
\end{array}
\right.
```

この連立方程式を解くと、$u,v$は次のように求まります。

```math
\left\{
\begin{array}{l}
u=\frac{-e_{vx}(p_y-p_{0y})+e_{vy}(p_x-p_{0x})}{e_{ux}e_{vy}-e_{vx}e_{uy}} \\
v=\frac{e_{ux}(p_y-p_{0y})-e_{uy}(p_x-p_{0x})}{e_{ux}e_{vy}-e_{vx}e_{uy}}
\end{array}
\right.
```

これをGLSLで実装すると、以下のようになります。ここでは補間する値を三次元ベクトルにしています。

```glsl
vec3 lerpTriangle(vec2 p, vec2 p0, vec2 p1, vec2 p2, vec3 c0, vec3 c1, vec3 c2) {
    vec2 eu = p1 - p0;
    vec2 ev = p2 - p0;
    
    float d = eu.x * ev.y - ev.x * eu.y;
    float a = p.y - p0.y;
    float b = p.x - p0.x;
    
    float u = (-ev.x * a + ev.y * b) / d;
    float v = (eu.x * a - eu.y * b) / d;
    
    return c0 + u * (c1 - c0) + v * (c2 - c0);
}
```

三角形の各頂点に赤、緑、青の値を持たせると次のように補間されます。
![KodeLife 2022-04-26 at 19.31.06 0000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/21f9b328-731c-4452-40a9-5f13976c8f00.png)



---

以下の記事を参考にしました。

- [要素内補間 \- Wikipedia](https://ja.wikipedia.org/wiki/%E8%A6%81%E7%B4%A0%E5%86%85%E8%A3%9C%E9%96%93#3%E8%A7%92%E5%BD%A2%E8%A6%81%E7%B4%A0%E5%86%85%E3%81%AE%E8%A3%9C%E9%96%93)
新規マシンのUbuntuに.net 5をインストールしアプリを実行する

### Ubuntuに.Net5をインストールする

最新は.net6ですが5を指定してインストールします。

#### Ubuntuに.netをインストールするやり方

- Snapでインストール
- マイクロソフトから提供されたスクリプトでインストール
- 手動でランタイムやSDKをインストール

スクリプトが一番簡単でした。

#### スクリプトでインストールする

このページから**dotnet-install.sh**をダウンロードします。

https://docs.microsoft.com/ja-jp/dotnet/core/install/linux-scripted-manual#scripted-install

バージョンを指定します。

```sh
$ bash ./dotnet-install.sh -c 5.0
```

##### 環境変数DOTNET_ROOTを設定する

Vimをインストール

```sh
sudo apt-get install vim
```

##### 環境変数ファイルを編集する

~/.profileよりも.bashrcのほうが必ず読み込まれためここに追加します。

```sh
vim ~/.bashrc
```

最後に追加する

```sh
export DOTNET_ROOT=$HOME/.dotnet 
```

反映させる

```sh
source ~/.bashrc
```

DOTNET_ROOTが設定されたか確認する

```sh
env
```
変数が設定されていると以下のように出ます

```
DOTNET_ROOT=/home/user/.dotnet
```

DOTNET_ROOTにパスが通ってなかったりすると以下のようなエラーが出ます。

```
A fatal error occurred. The required library libhostfxr.so could not be found.
If this is a self-contained application, that library should exist in [].
If this is a framework-dependent application, install the runtime in the global location [/usr/share/dotnet] or use the DOTNET_ROOT environment variable to specify the runtime location or register the runtime location in [/etc/dotnet/install_location].

```

#### 参考情報引用

>環境変数の読み込み順番
>1. /etc/profile
>2. ~/.bash_profile　
>  上のファイルがなければ
>   2-1. ~/.bash_login
>   2-2. ~/.profile
>3. ~/.bashrc
>4. /etc/bashrc
>5. bash実行
>1. /etc/profile
>このファイルはログイン時に読み込む全てのユーザ共通の設定が書いています。
>
>    ~/.bash_profile　
>    その後ユーザの[home]ディレクトリにある「.bash_profile　」を
>    読み込みます。
>      上のファイルがなければ下の順に読み込めます。
>       2-1. ~/.bash_login
>       2-2. ~/.profile
>    ログインの時一回だけ読み込みます。
>
>    **~/.bashrc**
>    **このファイルはbashが読みこまれる度に更新されます。**
>    **設定を変更する時は[bash]とコマンドを打って設定ファイルへの更新が反映されます。**
>
>    /etc/bashrc
>    このファイルはシステム全体の関数とエイリアスに関する設定が記録されています。ここでデフォルトのプロンプトを決める「PS1」の設定などをしています。

https://qiita.com/yunzeroin/items/480a3a677f78a57ac52f

[GateIoライブラリを使ってみる](https://qiita.com/iota_11/items/37c96821d41c8a2fc0ac)に続く
Blenderでシェーダーのノード位置の調整

## 概要

Pythonでマテリアルのシェーダーのノード位置を調整してみます。
シェーダーのノード自体をPythonで作成したときに使えるかもしれません（下図は実行例）。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/40987fc2-117d-3588-36ed-5e8d868ad356.png" width="500">

## ロジック

[NetworkX](https://networkx.org/)で有向グラフを作り、マテリアル出力ノードまでの距離ごとにレイヤーを作り、上から配置していきます。

## 実行してみる

対象のマテリアルの名前を`Material`としたとき、下記を実行すると位置を調整します。
NetworkXのインストールが必要です。

```py
import bpy
import networkx as nx
from collections import defaultdict

# 有向グラフの作成
g = nx.DiGraph()
m = bpy.data.materials["Material"]
for link in m.node_tree.links:
    g.add_edge(link.from_node, link.to_node)

# 出力までの距離を算出
mo = m.node_tree.nodes["Material Output"]
dist = nx.shortest_path_length(g, None, mo)

posy = defaultdict(int)  # 現在のY座標
for nd in m.node_tree.nodes:
    d = dist[nd]  # ノードの距離（レイヤー）
    nd.location = -d * 300, posy[d]
    posy[d] -= 300
```

ノードの幅と高さの属性が（有効な値として）使えなかったので固定値にしています。

参考：[BlenderでPythonを実行する方法](https://qiita.com/SaitoTsutomu/items/cec67381a8789b40e377)

以上
【BigQuery】文字列を集計関数(array_agg)で扱い、特定の1つを抜き出す 

## 背景
集計関数で文字列を扱えるととても便利だなあと思ったので、備忘録としてここに記しておきます。

## 今回使用するデータ
下記の 人の名前、教科、点数のテーブルを使用します。

|  name  |  subject  |  score  |
| ---- | ---- | ---- |
|  A  |  math  |  60  |
|  B  |  math  |43|
|  C  |  math  |97|
|  A  |  english  |  75  |
|  B  |  english  |  56  |
|  C  |  english  |  74  |
|  A  |  science  |  68  |
|  B  |  science  |  62  |
|  C  |  science  |  31  |

- データセット名は `test`
- テーブル名は `sample_score_data` 

## 今回やりたいこと

これを人、その人の得意教科(一番得点の高い教科)、合計得点 という結果に集計するとします。

## Answer

合計得点が `sum(score)` なのは誰でも容易に想像がつくと思いますが、subjectは文字列で集計できないためどう処理するかは好みの分かれるところです。

様々やり方はあるのですが、一発でスマートに出せるやり方があります。

それは、 **『文字列を配列にする集計関数 array_agg で順序を定めて(order by)配列を作成した後、配列内の特定の要素を取り出す』** です。

### クエリ
```SQL
select
  name,
  array_agg(subject order by score desc limit 1)[offset(0)] as favorite_subject,
  sum(score) as total_acore

from test.sample_score_data
group by 1
order by 1
```
### 結果

|  name  |  favorite_subject  |  total_score  |
| ---- | ---- | ---- |
|  A  |  english  |  203  |
|  B  |  science  |161|
|  C  |  math  |202|

となります。

文字列columnを使って、「最も〜な○○」を抽出したい時におすすめです。
オブジェクト間通信にUDPを使う


# オブジェクトの参照が面倒

オブジェクトが多くなってくるとオブジェクト同士の通信が億劫になってきます。親とか子とかパスとか、も～めんどくさい！ たまには違うプログラムとやり取りなんかも発生して本当に大変。

**ならばネットワークだ！** 昔から利用されていた方法だから間違いはない。（はず）



## お手軽通信、UDP

やっぱりこういう目的ならUDPでしょう。Open Sound Controlもちらっと考えたのですがモジュールとか導入したり諸々面倒なのでPythonで何も考えずに使えるudpで済ますことにしました。

受信を待つとかブロッキングで他の処理が止まるとかそういうのは使いづらくて困るのでデータが受信されたらコールバックが呼ばれるって感じで。

うん、なんか良さそうな気がしてきたぞ。



## コード

そんな感じでとりあえずでっち上げました。行儀悪いところがあったりするけど細かいツッコミは必要ないので気になるなら直して使うなり自由にすると良いです。

比較的簡単に使える、気をつけなきゃいけないのはIPアドレスが被らないようにすることくらい。

**udpnet.py**

```python
import socket
import threading


def thread(func):
    def run(*args, **kwargs):
        t = threading.Thread(target=func, args=args, kwargs=kwargs)
        t.start()
    return run

class UDP:
    def __init__(self, ADDR):
        self.addr = ADDR
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(self.addr)
        self.running = True
        self.callback = None

    def messageRecieved(self, callback=None):
        self.callback = callback
        
    @thread
    def mainloop(self):
        while self.running:
            try:
                data, addr = self.sock.recvfrom(8192)
            except:
                continue

            if data.decode() == "quit_request":
                break
            
            if self.callback:
                self.callback({"data": data.decode(),
                               "address": addr,
                               "sock": self})

    def send(self, msg, ADDR):     
        self.sock.sendto(msg.encode(), ADDR)

    def close(self):
        self.running = False
        self.send("quit_request", self.addr)
        self.sock.close()
        self.sock = None
```



## 使い方。

dict型のデータがやり取り出来れば不自由ないだろうということでそういうデモ。

二つのホストがやり取りするような内容。

つくった **udpnet.py** はあまり高速通信を得意とするような構造をしていないのでリアルタイムでだらだらデータストリーミングするような目的では使わない方が良いと思います。あくまでなにやらの処理のときにリクエスト → データを受け取って次の処理を呼ぶ。みたいな感じがよろしいかと。

```python
import udpnet
import time
import json

# UDPホストその1 用のコールバック
# データの内容を表示して送信元へ返信を行う
def sevRcv(x):
    dat = json.loads(x["data"])
    for key in dat.keys():
        print(key, dat[key])
    x["sock"].send("welcome", x["address"]) 

#
# UDPホストその1
#
s0 = udpnet.UDP(("127.0.0.1", 49200))
s0.messageRecieved(sevRcv)
s0.mainloop()

#
# udpホストその2
#
s1 = udpnet.UDP(("127.0.0.2", 49200))
s1.mainloop()
# ホストその2 はコールバックをラムダで処理してみる
s1.messageRecieved(lambda x: print("recieved!:", x["data"]))

#
# 1秒おきに10回ほどホストその2から1へ送信をする
#
for i in range(10):
    dat = {"a": 123, "b": "hello"}
    s1.send(json.dumps(dat), ("127.0.0.1", 49200))
    time.sleep(1)

# ホストを閉じて終わり
s0.close()
s1.close()
```



## 〆

まだ実戦投入してませんがヒエラルキーをガン無視できて大分自由に楽々になるんじゃないかと期待度高めです。

Pythonだとこういうのも簡単に書けていいですね。

さらなる展望としてはデータクラスと融合させて変数にアクセスするようなノリで通信が出来たらいいですねー。
Dockerのmysqlコンテナ、Debianでlessコマンドを使う

Dockerのmysqlのコンテナでlessを使おうとしたが`bash: less: command not found`と出てしまった。
lessをインストールしようと`yum install less`をしたがこれも`bash: yum: command not found`。
yumは、Fedora、RedHat、CentOSなどのディストリビューションで標準として利用されるパッケージ管理ソフト。
当該コンテナのOSを確認。
```
cat /etc/issue
Debian GNU/Linux 10 \n \l
```
Debianだった。
Debian、Ubuntuなどのディストリビューションのパッケージ管理ソフトはyumではなくapt。
なので、一応アップデートしたあと
`apt-get update`
以下でlessをインストール
`apt-get install less -y`
lessが使えるようになった

# 参考記事
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13207829133
https://eng-entrance.com/linux-os-version
https://qiita.com/toshihirock/items/6f46c36c9b567c915d84
AWS SNS HTTP/HTTPSのサブスクリプションを確認する方法 on Laravel

# AWS SNS HTTP/HTTPSのサブスクリプションを確認する方法 on Laravel

追加した、サブスクリプションが「保留中の確認」になったあと
「確認済み」にする方法の情報が非常に少なかったのでメモ
Laravelで記載しますが、他の言語でも同じだと思います。

## エンドポイントは以下を設定したとする

`https://sns.test.com/sns/notification`
	
## Laravel側

CSRF対策が設定されていると、HTTP 419などになるので
サブスクリプションを確認する場合は、認証なしで受け付ける必要があります。

### apiでもwebでもどちらでも良いですが、認証なしで！
下記の例では、webの方は、VerifyCsrfTokenが効いているので、apiの方を使う必要がある

```App\Http\Kernel.php
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:24000,1',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

```

### POST通信で来ます！

```routes/api.php
Route::post('/notification', 'SNSNotificationController@notification');
```

### リクエストを解析して、SubscribeURLへリクエストを投げます！
サブスクリプションを確認するリクエストと、運用後の通知で処理を分岐させます。

SubscribeURLのURLにアクセスすると、サブスクリプションを確認することができます。
もしくは、SubscribeURLをブラウザで開いてもOKです。

ちなみに、SubscribeURLは以下のような形です。

`https://sns.us-east-1.amazonaws.com/?Action=ConfirmSubscription&TopicArn={$payload->TopicArn}&Token={$payload->Token}`

```App\Http\Controllers\SNSNotificationController.php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class SNSNotificationController extends Controller
{
    public function notification(Request $request)
    {
        // SNSからのリクエストを受信
        $payload = json_decode($request->getContent());
        if(property_exists($payload, 'Type')){
          if($payload->Type === "SubscriptionConfirmation")
          {
              // このエンドポイントでの通知サブスクリプションを確認
              // 初めての場合は、SubscribeURLのURLにアクセスしてサブスクリプションを確認します。
              $confirmation_url = curl_init($payload->SubscribeURL);
              curl_exec($confirmation_url);
          } elseif($payload->Type === 'Notification'){
                // SNSからの通知が来た時の処理
          }
        }
    }
}
```

## 管理コンソールで確認すれば、「確認済み」となっているはずです！

# それでは、素晴らしいAWSライフを！　おしまい
荒い写真を高画質化する方法

# 保存した荒い写真を高画質化する方法
皆さんこんにちは！
最近、古い携帯電話から画質の荒い昔の写真を見つけました。
そのあとは荒い写真の画質を上げる方法を探していました。 
今回は、私が見つけた古い写真を復元できるツールを紹介します。




## 事前準備
編集したい画像
PicWishという画像高画質化ツール(無料・オンライン)
このソフトは完全無料ですので、ご興味のある方はお試しください。
（この前、透明png画像を作成するためにこのツールを使用したことがあり、かなり使いやすいと思います。偶然に荒い写真の修復することにも使えると発見しました。）



## 使う手順
1.[PicWishの公式サイト](https://picwish.com/jp/unblur-image-portrait?apptype=qiita)を開きます。
2.編集したい写真を選択し、アップロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/3064c43c-ef84-52cd-311e-eb310c2dc90d.png)

3.数秒待つと、自動的に画像の復元が行われます。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/6261a4c5-b7b4-bd5a-98ae-2f951c241eee.png)
画像の修復する効果はここです。
元画像：500x721
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/040320ed-426e-8e96-032d-aa72ad3c93fe.png)
強化後：1000x1442
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/914e1392-0ae3-0c05-1a01-44b33381cc85.png)

4.[ダウンロード]をクリックすれば、修復された画像をダウンロードできます。
【Rails/minitest】パーシャルを出し分けるビューヘルパーの自動テストを書いてみる

# はじめに
こんにちは、この記事を書いている現在が夕方なので、お腹が減ってきてしまったk__mです。
この現場では、Railsのプログラムでビューヘルパーの自動テストが書かれていませんでした。
そこで今回、パーシャルを出し分けるヘルパーメソッドの自動テストを書こうとするものの、あまり参考になる記事も見つけられず、少し詰まってしまいました。。。
結局少しずるい方法で乗り越えてしまったのですが、備忘録代わりに記事を書いていきます。
# 自動テストの概要
今回自動テストを導入したかったのは、パーシャルの出し分けをする役割のビューヘルパーです。
具体的にはこんな感じです。

ApplicationControllerで定義されているインスタンス変数haraheriでパーシャルを出し分けるようにしています。
```ruby:app/helpers/application_helper.rb
module ApplicationHelper
  def render_partial
    if @is_haraheri
      render(partial: 'shared/haraheri')
    else
      render(partial: 'shared/not-haraheri')  
    end
  end
end
```

出力したいパーシャルは下の2つです。
```erb:app/views/shared/_haraheri.html.erb
<div>
    <% if @shushoku == 'gohan' %>
        ごはん食べる
    <% else %>
        パン食べる
　　　　　　　　<% end %>
</div>
```
```erb:app/views/shared/_not-haraheri.html.erb
<div>おなかいっぱい</div>
```
# 実際に書いた自動テスト
実際に書いた自動テストのコードはこちらです。
```rb:test/helpers/application_helper_test.rb
class ApplicationHelperTest < ActionView::TestCase
  test "腹減りの時、１つ目のパーシャルを出力" do
    # インスタンス変数をセット
    instance_variable_set("@is_haraheri", true)
    instance_variable_set("@shushoku", 'gohan')
    # メソッド実行
    render_partial
    # パーシャル1が出力される
    assert_template partial: "shared/_haraheri"
  end

  test "腹いっぱいの時、2つ目のパーシャルを出力" do
    # インスタンス変数をセット
    instance_variable_set("@is_haraheri", false)
    # メソッド実行
    render_partial
    # パーシャル2が出力される
    assert_template partial: "shared/_not-haraheri"
  end
end
```
## 具体的な説明
```ruby
# インスタンス変数をセット
instance_variable_set("@is_haraheri", true) # instance_variable_set("代入したいインスタンス変数", 代入したい値
```
インスタンス変数haraheriに、trueを代入します。

```ruby
# メソッド実行
render_partial
```
実行したいヘルパーのメソッドをポンと書くだけで、そのメソッドを実行できます。お手軽です。

```ruby
# パーシャルを出力
assert_template partial: "shared/_partial1"
```
指定したパーシャルが出力されているかのアサーションをしています。
partialオプションを付けることで、パーシャルの出力かどうかをみることができるのは便利ですね。
# ハマりポイント
「パーシャル全部のアサーションてどうやるの？？」で１時間ほど持っていかれました。
最初はRailsの公式ガイド（下にリンクを貼っておきます）を漁り、
```ruby
# erbファイルを直接取得
file = File.read(Rails.root.join('app', 'views', 'shared', '_partial.html.erb'))
# アサーション
assert_dom_equal(file, render_partial)
```
を使おうとしましたが、erbファイルのrubyのコード（\<% %>で囲った部分）の処理がうまくいかず、断念しました。
fileの中には\<% %>がそのまま残る一方、render_partialを通って出力されたファイルからは\<% %>が消えるからです（よく考えたら当たり前。。。）。

https://railsguides.jp/testing.html#%E3%83%98%E3%83%AB%E3%83%91%E3%83%BC%E3%82%92%E3%83%86%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B

その後七転八倒した挙句、今の形に落ち着きました。
# 注意点
assert_templateですが、Rails4くらいまでは標準で使えたのに、Rails5以降でgemに切り離されてしまったテストヘルパーです。今でも下記リンクのgemを導入すれば使えますが、いかんせんこのgem、作られたのもだいぶ昔な上に、メンテナンスもほぼされていません。
今回書いた自動テストは、１ヶ月程度で消す一時的なものなのでこのgemを使うことにしましたが、本当に使うかどうかは場合に応じて考えてください。
例えば、下のような簡単なhtmlタグを出し分けるヘルパーをテストしたいなら、上でリンクを貼った公式ドキュメントに書いてある方法を使うのが確実だと思います。
```html
<a href="haraheri">はらへり</a>
```

https://rubygems.org/gems/rails-controller-testing/versions/0.1.1?locale=ja

# さいごに
今回はちょっとずるい方法で乗り越えてしまいましたが、わたしが探しきれなかっただけでもっとうまくやる方法がある気がしています。
もし何かいい方法をご存知の方、他にツッコミポイントなどを見つけてしまった方、ぜひ情報をお願いしたいです。
それでは、最後までお読みいただきありがとうございました！
OpenShiftクラスターに他の人をアクセスさせたいときに必要なこと


[こちら](https://qiita.com/loftkun/items/044b6302d734d7f94587)のようにベアメタル環境にOpenShiftクラスターを構築した場合、踏み台サーバーを作業マシンとして、そこからOpenShiftクラスターにログインして作業することが多いかと思います。
一方で、他の人に（踏み台サーバーを使わせずに）そのOpenShiftクラスターにアクセスさせたい場面もあるでしょう。そのような場合に必要なことをまとめてみました。
OpenShift 4.6で確認しました。


## 1. ユーザー追加 - OpenShiftクラスターでの作業
アクセスさせたい人が使うためのユーザーを追加します。
具体的な手順は、Red Hatのマニュアルや以下の参考記事をご参照ください。

参考）
- [How to configure an HTPasswd identity provider in OpenShift Container Platform 4.x?](https://access.redhat.com/solutions/4039941)
- [[OpenShift]ユーザ認証について確認する](https://qiita.com/dingtianhongjie/items/de782eaa27dca498fd3b)

## 2. 名前解決 - アクセス元マシンでの作業

クラスターへのアクセスに必要な次の2つが、踏み台サーバーの外側のIPアドレスに対応していることを、アクセス元のマシンがわかっている必要があります。

 - api
 - oauth-openshift

必要な名前解決のため、アクセス元のマシンのhostsに次の情報を登録します。
（DNSでそれらの名前解決ができている環境であれば、必要ありません。）

例）install-config.yamlで次のように指定して構築した環境の場合：
   - ドメイン名: example.com
   - クラスター名：lab

設定例は次のようになります：
```
<踏み台サーバーのIPアドレス>     api.lab.example.com oauth-openshift.apps.lab.example.com
```

これで、次のOpenShiftクラスターへのログインコマンドが成功するはずです。
```
oc login -u <userid> -p <password> https://api.lab.example.com:6443
```


OpenShift webコンソールでのアクセスが必要な場合は、追加で以下の設定も必要です。
```
<踏み台サーバーのIPアドレス>     console-openshift-console.apps.lab.example.com
```



## 参考：OpenShiftクラスターへのログイン状況の確認方法

- 現在クラスターにログインしているユーザーの確認
```
oc get oauthaccesstokens
```

- ログイン履歴の確認
[How to check user login history in OpenShift? ](https://access.redhat.com/solutions/5357001)
（自分自身では未検証です。また、リンク先の閲覧にはRed Hat subscriptionが必要です。）
【Flutter + Widgetテスト】非同期処理を特定タイミングまで待機させる

# 非同期処理中に表示するUIを確認したい

みなさんはテスト書いてますか？私はあまり書いていませんので、意識的に書くよう心がけています。今回は非同期処理が絡むUIテストのお話。

APIを叩いて結果を取得するなど非同期処理を行なっている間、プログレスバーを表示してユーザ体験を損なわないような工夫は常套手段です。非同期処理の例として、次のようなインターフェイスで定義される処理を考えます。

```dart:hoge_api.dart
abstract class HogeAPI {
  Future<Hoge> fetch();
}
```

UIの変化と非同期処理の流れは、

1. UIをあるボタンを押下すると
2. プログレスバーを表示
3. 非同期処理`HogeAPI#fetch`を呼び出す
4. 非同期処理が終わったらプログレスバーを非表示＆UIへデータ反映


このプログレスバーの表示を確認するテストを書きます。`HogeAPI`は`mockito`でモックして、状態管理に使用している`flutter_riverpod`のProviderScopeで差し替えています。

```dart:hoge_page_test.dart
@GenerateMocks([HogeAPI])
void main() {
  testWidgets("プログレスバーの確認", (tester) async {
    // setup
    final api = MockHogeAPI();
    await tester.pumpWidget(ProviderScope(
      overrides: [
        hogeAPIProvider.overrideWithValue(api),
      ],
      child: const MaterialApp(
        title: title,
        home: HogePage(),
      ),
    ));

    when(api.fetch(any)).thenAnswer((_) async {
      return mockValue;
    });

    // test
    await tester.tap(find.byKey(buttonKey));
    await tester.pump();

    // check
    expect(
      find.byWidgetPredicate((widget) => widget is CircularProgressIndicator),
      findsOneWidget,
    );
  }
}
```

## 問題
プログレスバーが表示される前に非同期処理が終わってしまうので`expect`が失敗する。解決策として、非同期処理で適当な時間だけ遅延させる手が思いつきます。
```diff:hoge_page_test.dart
    when(api.fetch(any)).thenAnswer((_) async {
+     await Future.delayed(Duration(milliseconds: 500));
      return mockValue;
    });
```
しかし適当な遅延時間とは？短すぎると遅い実行環境ではまた失敗するし、長すぎるとテストの実行に要する全体時間が長くなってしまいます。

# 非同期処理を任意のタイミングまで待機させる
要はプログレスバーの表示を確認する`expect`が終了するまで非同期処理`HogeAPI#fetch`が終わらないよう保証する必要があります。そこで`Future.delayed`に代わり、任意のタイミングで終了できるような`Future`を返すクラスを自作します。
```dart:latch.dart
class Latch {
  /// period: 終了条件を監視する時間幅
  Latch({Duration? period})
      : _period = period ?? const Duration(milliseconds: 100);

  final Duration _period;
  var _waiting = true;

  /// このlatchが`#complete`で終了されるまで待機するFuture
  ///
  /// すでに`#complete`で終了済みの場合は即座に完了するFutureを返す
  Future<void> get wait => _waiting
      ? Future.sync(() async {
          while (_waiting) {
            await Future.delayed(_period);
          }
        })
      : Future.value();

  /// `#wait`で返したFutureを終了する
  ///
  /// **注意** Futureは即座に終了しない
  /// 指定した時間間隔でこの終了呼び出しを監視して`#complete`が呼ばれた以降のタイミングでFutureを終了させる
  void complete() {
    _waiting = false;
  }
}
```

`Latch#wait`が返す`Future`は`Latch#complete`の呼び出しで終了できます。テストで使うには、`expect`で確認してから`Latch#complete`を呼び出し非同期処理`HogeAPI#fetch`を終了させます。

```diff:hoge_page_test.dart
+   final latch = Latch();
    when(api.fetch(any)).thenAnswer((_) async {
+     await latch.wait;
      return mockValue;
    });
...
    expect(
      find.byWidgetPredicate((widget) => widget is CircularProgressIndicator),
      findsOneWidget,
    );
+   latch.complete();
```
GoogleDriveで従業員のスキルシートを管理しやすくした話

## 始めに

株式会社ココロファン - エンジニアリング事業部所属の Sassy です。 

最近はエンジニア育成と受託事業の事業開発をメインでやっており、検討や調査などしています。

弊社では受託事業は別にSES事業も行っております。

先月は社内で管理している従業員のスキルシート管理方法の改善を行いました。

弊社ではGoogleWorkspaceを契約しており、GoogleDriveを活用して様々な資料を管理しています。

そこで、従業員のスキルシートを当初はバックオフィス、営業関係者しか見れない場所に配置されていたのですが、ある従業員から「自分の現在のスキルシートを確認したい」というような形で相談を受けました。

この時、私も以前から自分のスキルシートを営業とエンジニア間でスムーズにやり取りしたいと感じていたため、スキルシートの管理について見直そうと思いました。

そこで私がどのように考え、解決したかをまとめたいと思います。

ある程度の企業様であれば、別の手法で効率よく管理されているかと思います。
しかし、弊社のようにまだまだ管理の体制が未熟だったり、管理方法に迷っていたりする管理者様に対して何かの参考になれば幸いです。

## 当初のスキルシート管理方法についての課題

まず現状弊社で起きていた事象を整理してみます。（自分の体験も含めます）

- 従業員のスキルシートが会社や営業サイドで管理されており、従業員が参照することができなかった。
- 従業員が更新したい場合には手元にあるスキルシートを更新して営業に送付するか、営業に連絡を取ってスキルシートの原本をもらってから更新をかけて営業に送付していた。

次に、これらの事象から発生する課題を整理します。

- 従業員が自分のスキルシートにアクセスすることができない。
- 従業員が気軽にスキルシートを更新することができない。（上記と多少類似していますが…）
- 従業員が持っているスキルシートが最新なのか、営業が持っているスキルシートが最新なのかわからない。
- 従業員と営業間のファイルの受け渡しがめんどくさい。

## ゴール設定

いくつか課題が挙がりましたが、課題を解決するために達成したいことを大きくまとめると以下になるかと思います。

- 最新のスキルシートが参照できるようにする（エンジニア、営業双方）
- 営業はエンジニア全員に、エンジニアは自分自身のスキルシートへアクセスできるようにしたい。

## 検討した内容

共有ドライブを作成し、ドライブの権限を管理者や営業のみに設定します。

こうすることで 各従業員のフォルダが配置されているドライブへは【管理者や営業のみ】しかアクセスできないようにしています。

更に、その中に従業員毎にフォルダを作成し、フォルダの共有設定で対象の従業員を追加します。

こうすることで従業員のは設定された個人のフォルダにしかアクセスできないようになります。

しかし、これでは従業員からしたらスキルシートが管理された共有ドライブへはどのようにアクセスすればよいか疑問が湧くかもしれません。

問題ありません。各従業員のGoogleドライブ上の「共有アイテム」から個人フォルダへの項目が追加されていますのでそちらからアクセスすることが可能です。

文字だけではイメージが付きにくいかと思いますので図を載せます。

![スクリーンショット 2022-04-26 173733.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1128033/9438c1db-a182-bfd1-1673-6bad7d900e6d.png)

このようにすることで営業は取引先への従業員のスキルシート送付時にエンジニアからのメールを待たなくてよくなりますし、エンジニアも自身のスキルシートを気軽に更新かけることができます。

またメールでの送付は誤送信により、関係ない人に送られてしまうリスクがあるので、この仕組みを使うことでメールやチャット等でURLを共有するだけで良くなります。

そして、関係ない人に送られてしまった場合でもアクセス権無いためアクセスできず中を見られてしまうリスクも無くなります。

![スクリーンショット 2022-04-27 093343.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1128033/136f7008-aa28-048a-17d8-37cff0280c11.png)


## 実際に変更してみて

実際に使用してみてのエンジニアの意見まではうかがえてないですが、前よりかは良い管理になったかなと感じています。

GoogleDriveで管理することでエンジニアや営業双方でスキルシートを管理する必要が無くなりますし、Googleアカウントを持っていれば端末が変わってもログインすることで参照することができるので色々な負担は削減できたのではないかと考えています。

ただエンジニアと営業双方で扱うため、運用方針はしっかり策定しました。

まだしっかり運用が回っているかなどの心配はありますが、今後このやり方で進めていけるように不都合あればルールの見直し、徹底に力を入れていきたいと思います。


## 最後に

株式会社ココロファンでは受託や自社プロダクトの開発も行なっており、やってよかったこと、やってわかったこと、便利なノウハウを皆さんに共有できるように、これからも積極的に技術記事をアップしていきたいと思います。

https://cocolofun.co.jp/
DeFi用仮想通貨bot【PancakeSwap&UniSwap対応】

## DeFiで使用できる仮想通貨bot

DEX、魔界を使用している仮想通貨トレーダーの方に必須級のツールをご紹介します:relaxed:

DEXに上場したばかりの通貨やまだCEXに上場していない通貨で価格の上下が激しい通貨がよくあります。

そんな通貨を目視・リアルタイム・手作業で取引するのは大変ですよね:sweat:
スワップするたびにMetaMaskでトランザクション確認で失敗したりします。

今回紹介するツールは**あらかじめ設定した**情報を元に自動で売買してくれるbotとなっております✨

### botの機能

1. 指値注文
2. ストップロス設定
3. 逆指値注文（決済注文）
4. スリッページ
5. 成行注文
6. ガス設定

## botのデモ

![v2gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641705/34a22983-8178-c3cf-1069-299da679e849.gif)

## どう使うといいか

・DEXに上場予定の通貨をあらかじめbotに情報を入力しておき、上場する瞬間に稼働させると手動のユーザーより早く注文できます。

・ボラティリティが高い通貨をbotで設定しておき、24時間利益を狙います。

・売買価格を決めて指値注文を設定し、24時間利益を狙います。

## botの利用

botの詳細ページは[こちら](https://bitex.comyu.org/index.html)

現在（2022/4/26時点）キャンペーン実施中で、SNSでシェアしていただけた方には無料でbotをお渡ししています。お問い合わせ時にシェアしたURLを記載してください。
締め切りは予告なく終了します。
laravel: command not found

この記事を参考にcentos7上にLaravel環境を作ろうと試みた。

https://qiita.com/youki39/items/aaf11853baf36f4fcfe5

だがしかし・・・

### laravel: command not found
phpとcomposerまではうまくいった。
パスもうまくいった。
しかし、

**Laravelのインストール**という部分でつまづいた。
```
composer global require laravel/installer
```

エラーは出なかったが、
```
$ laravel -v
laravel: command not found
```

なんでやねん。

### パスの違っていた
```
export PATH=$PATH:$HOME/.composer/vendor/bin
```
との説明だったけど、なぜか違った。

`$HOME/.composer/vendor/bin`の部分が、なぜかディレクトリが変わっていたのだ！！

実際のパスは
```
// すでに設定済みのためwhichで確認
$ which laravel
/root/.config/composer/vendor/bin/laravel
```

なのでexportで記述する場合は次のようにすればよかったのかな。
```
export PATH=$PATH:$HOME/.config/composer/vendor/bin
```

### どうやって見つけた？
ホームディレクトリで検索

```
$ cd // ホームディレクトリに移動
$ find .composer .
（略）
./.config/composer/vendor/bin/laravel
（略）
```

これかなって思ってパスを登録したら確認できたので、合ってるかな。


パスは通したのに、`laravel: command not found`で悩んでいる人がいたらひょっとしたら上記のようなパスに変わっているかもしれないので参考にしてください。
VSCodeでTabのインデントがspace2つ分になる時の対処法

# はじめに
![スクリーンショット 2022-04-26 17.32.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2225948/975acec8-60c6-985f-cf46-fc7fd59690e7.png)
いつもは，Tabを押したらインデントがspace4つ分なのに
今回人からもらったファイルをいじっていたらインデントがspace2つ分になったので，どんな時もTabでspace4つになるようにしました．

# 設定
左下の歯車 → 設定 → Editor: Tab Sizeを4に (デフォルトは4) 
![スクリーンショット 2022-04-26 17.17.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2225948/bf0412ab-0231-4cf3-31c2-5aea326fb37d.png)
これだけだと，Tabがspace2つ分になっているファイルを編集しようとしたらspace2つになるっぽいです．
そこで，Editor: Detect Indentation をオフにします．

青文字の「Editor: Detect Indentation」をクリック → チェックを外す
![スクリーンショット 2022-04-26 17.24.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2225948/1c0381cc-a2a4-a1b4-dba2-e9fb6ff69c62.png)

これでTab押したらspace4つになりました！
![スクリーンショット 2022-04-26 17.33.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2225948/c505e782-abba-f00a-cfb2-11c8dc01ced6.png)

### おわりに
インデントはspace2つか4つどちらが良いのでしょうか？
私は4つ派です．

## 参考文献
- VSCodeでタブ数が勝手に変更されないようにする (https://otomizu.work/2020/10/30/vscode-tab-size/)