OmniAICreator/Qiita-1.07M huggingface dataset:
【Blender】メッシュのボロノイ分割

# 概要
Blenderを使って、メッシュ（基本形状）をボロノイ分割する方法についてまとめました。

応用すると、以下のような表現ができるようになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/674c8038-3320-962e-dbd4-fa2fcd3c5394.png" width="500" />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/6eead4b0-6bcc-21a7-c770-0619dace60b2.png" width="500" />

# 準備
Blenderは、3.0.0を使用してます。
Preferenceで、Add-onの**Cell Fracture**をインポートします。
![スクリーンショット 2022-02-15 233705.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/74c50217-a9e4-33d9-4797-269d0dce62c8.png)

# 手順
### Meshの準備
Meshは、ある程度細分化されている必要があります。例えば、Cubeの場合5×5×5くらいに細分化します。

［Edit Mode］で、右クリックから`Subdivide`を選択して、分割数を`5`にします。
![スクリーンショット 2022-02-15 234248.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/0b304932-b857-c382-508d-0bb312575bdc.png)
![スクリーンショット 2022-02-15 234521.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/95e5442e-0969-9903-2727-b7b66b288157.png)

#### Smoothをかける場合
球体などの表面を`Smooth Shade`したい場合は、分割前にかけておきます。

### Materialの設定
分割した後に、表面と内部の面のMaterialを分けたい場合は、あらかじめ内部の面のMaterialをMeshに追加しておきます。

![スクリーンショット 2022-02-15 235001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/fb38363a-acad-f8f0-6f26-6da598e4c7c4.png)
![スクリーンショット 2022-02-15 235159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/fe8fbdf9-c130-61dd-378a-5094af485fbc.png)

### 分割する
［Object］→［Quick Effects］→［Cell Fracture］を選択します。
![スクリーンショット 2022-02-15 235351.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/333d66b6-a639-948c-d36e-57c4c1a3eb07.png)

設定画面では、以下のように設定し、［OK］を押します。
![スクリーンショット 2022-02-15 235849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/35dcd5be-a2f3-09cb-d4d6-8892c9353334.png)

* Noise：seed値で、分割した形が気に入らなければ調整します。
* Material：内部の面に使うMaterialのインデックスを設定します。表面のMaterial（Outer）が「0」で、内部の面のMaterial（Inner）が「1」。
* その他：☑が入っているプロパティを設定することで、`Inner`が適用されます。


![スクリーンショット 2022-02-16 000827.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/a6e893f7-359b-4dec-b2ee-1e20c15a0516.png)

# 分割がうまくいかない
メッシュの形状が閉じていない場合や、メッシュが薄すぎる場合は、分割がうまく行かない場合があります。

生成過程を見るとわかりますが、面の法線（の逆向き）とその直線上にあるFaceの裏面とのあたり判定で、形状を認識している挙動をしています。
なので、部分的に面がなかったり、法線の向きがおかしいと正常に分割できません。
![スクリーンショット 2022-02-18 205508.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/bb9d233f-39e6-4542-ba6c-02326f0e4919.png)

法線の修正方法

https://bluebirdofoz.hatenablog.com/entry/2019/12/10/090822
MacでM5StickVを触ってみる (備忘録)

## SDカード
相性問題あり。
SDカードをMacのSD Card Formatterでフォーマット。

### OK
![SD_OK_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/0374a5cb-ebb0-f300-3b65-2a2a9c2d37c5.jpeg)

![SD_OK_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/11b4ad03-9443-2e88-c093-9a0cf194f446.jpeg)

### NG
![SD_NG_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/b016cb95-d1c2-d376-133f-30054d0cb08f.jpeg)

![SD_NG_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/38184b70-e255-8514-99eb-55a1d64a142d.jpeg)

## 書き込みツール
https://github.com/Sipeed/kflash_gui/releases
kflash_gui_v1.6.7_macOS.dmg

## ファームウェア
https://docs.m5stack.com/en/quick_start/m5stickv/maixpy
M5StickV_Firmware_v5.1.2.kfpkg

![スクリーンショット 2021-12-20 17.03.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/bd6c3ede-851b-d5b7-44f2-953dd379091b.png)

## 電源が入らない
M5StickVの起動方法　→2秒長押し
→ダブルクリック(2回クリック)　→OK

## 電源が落ちない
M5StickVの終了方法　→6秒間長押し
→USBケーブルを抜く
→SDカードを抜く
→デフォルト起動動作で6秒間長押し　→OK

## MaixPy IDE
http://dl.sipeed.com/shareURL/MAIX/MaixPy/ide
maixpy-ide-mac-0.2.5_2.dmg (v0.2.5を使用)

## Brownie
https://github.com/ksasao/brownie

```bash
git clone https://github.com/ksasao/brownie
```

### brownie
src/brownieディレクトリの内容をSDカードへコピー。
M5StickVを起動して動作OK。

### brownie 1000
src/brownie_1000ディレクトリの内容をSDカードへコピー。
Out_of_memoryエラーで起動せず。
![brownie_1000_error.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/cd38134a-32bc-e9d5-2ab0-c87c04fd622c.jpeg)

### brownie learn
src/brownie_learn/M5StickVディレクトリの内容をSDカードへコピー。
M5StickVを起動して動作OK。

## カメカメラ
https://github.com/ryotaikeuchi/kamekamera

```bash
git clone https://github.com/ryotaikeuchi/kamekamera
```

SDカードへコピー。

起動画面(カメカメラ表示)で止まる事象。(brownieとカメカメラのSDカードを入れ替えて使用)
→MaixPy IDEでターミナル接続したところ、エラーが出力された。

![kamekamera_error.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4db89d45-2f1b-bd1f-ba79-7c723b763e32.jpeg)

```bash
MemoryError: Out of normal MicroPython Heap Memory! Please reduce the resolution of the image you are running this algorithm on to bypass this issue!
```

→kflash_guiでファームウェア(M5StickV_Firmware_v5.1.2.kfpkg)をもう一度書き込んだらエラーが出なくなった。

## ファームウェアのバージョン
Sipeedのホームページからダウンロードできる。

http://dl.sipeed.com/MAIX/MaixPy/release/master/

kflash_guiでmaixpy_v0.6.2_72_g22a8555b5_m5stickv.binを書き込んだ。→ファームウェアのバージョンが上がり過ぎて正常に動作しなかった。

## デフォルトの起動音が大きい
screenコマンドだとMicropython-Editorでキー入力がうまくいかないため、cuコマンドで接続する。

```bash
$ sudo cu -s 115200 -l /dev/cu.usbserial-A1562E8A95 
```

Micropython-Editorを起動してboot.pyを修正

```bash
>>> pye("boot.py")
```

修正箇所

```python
player.volume(100)
↓
player.volume(10)
```

コマンド操作
矢印キー　→カーソル移動
DEL　→削除
Ctrl+S　→保存
Ctrl+Q　→終了

cuコマンドの終了
~.　→しばらくすると切断される
ExcelからWordに対するHyperlinkについて

# 2つの方法
## ファイル自体
### 1.関数を使う方法

`=HYPERLINK("C:\hoge\testWord.docx")`

### 2.挿入、ブックマークから挿入。
これは関数ではなく、セルのプロパティでリンクしている。

### 効果
ファイルが開く

この2つの方法は以下でも有効。
そして、ファイルの特定の位置にさらにリンクする。

## 特定の文字にリンク
最初に出現した位置にフォーカスする。
`=HYPERLINK("C:\hoge\testWord.docx#し")`

<font color="red"> 1.</font>	レベル1の見出<b>|</b>し
<font color="red"> 2.</font>	レベル1の見出し2
ParaBM
`　段落についてブックマークを設定したものを作ってみます。この段落の文章は2行程度にわたって続いています。最初に空白があります。この空白を含めてブックマークをします。タイトルはParaBMとします。`

しにリンクすると、最初の「し」の前に来る

## 自動で段落番号が出るときには、段落番号にリンクしない

以下で使う文章がこちら。

<font color="red"> 1.</font>	レベル<b>|</b>1の見出し
<font color="red"> 2.</font>	レベル1の見出し2
ParaBM
`　段落についてブックマークを設定したものを作ってみます。この段落の文章は2行程度にわたって続いています。最初に空白があります。この空白を含めてブックマークをします。タイトルはParaBMとします。`

赤い1、2は段落番号で見出し1のスタイルである。ParaBMは単なる文字列、さらにハイライトされている部分はParaBMというブックマークが挿入されている。

ここで次の関数

`=HYPERLINK("C:\hoge\testWord.docx#1")`

は

<font color="red"> 1.</font>	レベル<b>|</b>1の見出し
<font color="red"> 2.</font>	レベル1の見出し2
ParaBM
`　段落についてブックマークを設定したものを作ってみます。この段落の文章は2行程度にわたって続いています。最初に空白があります。この空白を含めてブックマークをします。タイトルはParaBMとします。`

上記の文章で赤い1は段落番号で自動的に付されている。
最初に出てくる1にはリンクしない。


## 文字列よりBookMarkが優先される

上記の文章はParaBMというブックマークが存在している。
しかし、最初に、ただの文字列のParaBMがある。
ブックマークと最初の文字列ではどちらが優先するか。


`=HYPERLINK("C:\hoge\testWord.docx#ParaBM")`
とする。
これは最初の文字列とBookMarkがある
BookMarkの名前はParaBMとする。網掛けの部分がBookMarkである。
この場合、ブックマークの名前が優先される。
# まとめ
つまり<b>段落番号やブックマークについては、最初に出現した文字列にリンクするとはいえない</b>ということになる。
また、確実にリンクさせるには、BookMarkをWord側で挿入しておいたほうがよいということがわかった。
40 代おっさん 制御構文について学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## if文

構文

```javascript
function myFunction() {
  if(条件式1) {
    //条件式1がtrueの場合に実行
  }else if(条件式2) {
    //条件式2がtrueの場合に実行
  }else{
    //すべての条件がfalseだった場合に実行
  }
}
```

＊一つ注意条件式で使う == はオブジェクトと配列は参照値比較になるので注意
また === は左辺と右辺のデータ型が異なっていることを厳密に判断する

## switch文

構文

```javascript
function myFunction() {
  switch(式) {
    case 値1:
      //式 == 値1だった時の処理
      break
    case 値2:
      //式 == 値2だった時の処理
      break
    …
    default:
      //式がすべての値に合致しなかったときの処理
  }
}
```

＊注意
breakを忘れるとその下の処理もしてしまう。

## while文

ループ文

構文

```javascript
function myFunction() {
  while(条件式) {
    //条件式がtrueの間、実行される処理
  }
}
```

＊注意
ループを抜けるように作らないと無限ループになる。

## for文

繰り返し回数が決められているループ文

構文

```javascript
function myFunction() {
  for ( 初期値; 条件式; 増減式){
    //条件式がtrueの間、実行される処理
  }
}
```

## for...of文

配列や文字列といった反復可能オブジェクトに含まれるすべての要素について繰り返し処理が行える。

構文

```javascript
for ( 変数 of 反復可能オブジェクト){
  //ループ内で実行する処理
}
```

お試しコード

```javascript
function myFunction() {
  const family = ['パパ', 'ママ', '利樹'];

  for ( person of family){
    console.log(person);
  }

  for ( const char of 'としき'){
    console.log(char);
  }
}
```

## for...in文

オブジェクトのすべてのプロパティについて栗菓子をすることができる。

構文

```javascript
for ( 変数 in オブジェクト){
  //ループ内で実行する処理
}
```

変数として取り出すのは、値でなく、プロパティ事態である。

お試しコード

```javascript
function myFunction() {
  const	personals = { 'パパ': '男', 'ママ': '女', '利樹': '男'}
  for ( personal in personals){
    console.log(`${personal}の性別: ${personals[personal]}`);
  }
}
```

＊注意
for...inではプロパティを取り出す順序は保証されていない。

## break文

while,for,for...of,for...inで使用可能

## continue文

ループをスキップするときに使う。

お試しコード

```javascript
function myFunction() {
  const	personals = { 'パパ': '男', 'ママ': '女', '利樹': '男'}
  for ( personal in personals){
    if(personal === 'ママ'){
      continue;
    }
    console.log(`${personal}の性別: ${personals[personal]}`);
  }
}
```

## ループにラベルを付与

構文

```javascript
ラベル:
```

指定したループを中断、またはスキップする場合は

```javascript
break ラベル
continue ラベル
```

お試し構文

```javascript
function myFunction() {
  outerLoop:
  for (let i = 1; i <= 3; i++){
    for (let j = 1; j <= 3; j++){
      if( i === 2 && j === 2){
        break outerLoop;
      }
      console.log(`iの値: ${i}, jの値: ${j}`);
    }
  }
}
```

## try...catch文

発生するエラーを例外と言う。
例外が発生した時の処理

構文

```javascript
function myFunction() {
  try {
    //例外を検知する対象となる処理
  } catch {
    //例外が発生した時に実行する処理
  } finally {
    //例外の有無にかかわらず実行する処理
  }
}
```

## throw文

例外を発生させるときに使う。
例外をスローするとも言う。

構文

```javascript
throw new Error(エラーメッセージ)
```

## 参考資料

<https://www.amazon.co.jp/s?k=google+apps+script+%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80&adgrpid=110264232688&gclid=CjwKCAiA9aKQBhBREiwAyGP5lSl7AJJLCvOEHb4wQgMlyqW1fll5X8GDTT_Rkd1_soUAyIPMXQr26hoClHEQAvD_BwE&hvadid=553833563682&hvdev=c&hvlocphy=1009076&hvnetw=g&hvqmt=b&hvrand=4378489642044417389&hvtargid=kwd-594191211348&hydadcr=4106_13159878&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2x1owglv0s_b_p52>
GASでyoutubeの項目を表示する方法

# 1.環境

ブラウザ　：　Google Chrom
言語　　　：　GoogleAppsScript

# ２.YouTube Data API v3 を追加する
GoogleAppsScriptのエディタでサービスを追加する。

やり方
![スクリーンショット 2022-02-15 23.31.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2509814/ff8e6353-32d4-bdf7-2c72-2e7f4008ca73.png)
↓
![スクリーンショット 2022-02-15 23.31.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2509814/476c578e-537a-de72-b6e0-dfbfd489e9ca.png)

# 3.コードを実行
サービスを追加したら以下のコードを入れて実行する

```sample.gs
function sample1(){
  // 取得したデータの入れ物
  var c = [];
  // パラメータを入れる
  var results = YouTube.Search.list('id,snippet', {
    //検索ワード
    q: '猫', 
    // 取得数
    maxResults: 10,
    // 検索する対象の国
    regionCode: 'jp',
    // ソート
    order: 'date',
    //検索する対象、「チャンネル,再生リスト,ビデオ」
    type: 'video',
    // 指定した日付より後のデータを対象する
    publishedAfter: '2022-01-15T00:00:00Z'
  });
  // 取得した分だけcに入れる
  for(var i = 0; i < results.items.length; i++){
    c.push([
      results.items[i].snippet.channelTitle,
      results.items[i].snippet.title,
      results.items[i].snippet.publishedAt
    ])
  }
  // 取得した分だけログに表示する
  // チャンネル名	動画タイトル	登校日
  for(var i = 0; i < c.length; i++){
    Logger.log(c[i])
  }
}
```
ログに「チャンネル名、動画タイトル、登校日」を出ます。

# ４.スプレッドシートに反映
以下の動画でスプレッドシートに反映した状況を配信しています。
よければ見てください！
https://www.youtube.com/watch?v=pyT-LyEtX_8
区間選択アルゴリズム

#何を書いているか
区間選択アルゴリズムの備忘録。
C++とGoで記述。
プログラミングスキルチェックの問題で選択アルゴリズムを使って解く問題に出会ったので。

#コード
ここでは終わりと次の始まりがつながらない区間を選択するパターン。
つながった場合も選択可能とする場合はコードの示した箇所を等比較にすればよい。

C++版

```C++
#include <bits/stdc++.h>
using namespace std;
int main() {
    // cin.tie(0);
    // ios::sync_with_stdio(false);

    int N;
    cin >> N;
    vector<int> X(N), L(N);
    for (int i = 0; i < N; i++) {
        cin >> X.at(i) >> L.at(i);
    }

    vector<pair<int, int>> p(N);
    for (int i = 0; i < N; i++) {
        p[i].first = X[i] + L[i]; // 終端を先に入れておく
        p[i].second = X[i];// - L[i];
    }

    sort(p.begin(), p.end()); // 終端を優先にソート
    
    int ans = 1;
    int t = p[0].first; // t:=現在までに選択した区間の中で一番後ろの点
    for (int i = 1; i < N; i++) {
        if (t < p[i].second) { //ここを等記号にすれば区間がつながっていてもOKとする。
            ans++;
            t = p[i].first;
        }
    }

    cout << ans << endl;

    return 0;
}
```


Go版

```go
package main
import (
    "fmt"
    "sort"
    )

type Pair struct {
    start int
    length int
    end int
}
func main(){
    var N int
    fmt.Scan(&N)
    
    kukan:=make([]Pair,0)
    for i:=0;i<N;i++ {
        var start,length int
        fmt.Scan(&start)
        fmt.Scan(&length)
        kukan=append(kukan, Pair{start, length, start+length})
    }
    
    sort.Slice(kukan, func(i, j int) bool { return kukan[i].end < kukan[j].end })
    
    ans:= 1;
    t:= kukan[0].end; // t:=現在までに選択した区間の中で一番後ろの点
    for i:=1;i<N;i++ {
        if (t < kukan[i].start) {
            ans++
            t=kukan[i].end
        }
    }
    
    fmt.Println(ans)
}
```
【MATLAB】から定期ツイート

#はじめに
どうも@MATLAB_Otterことカワウソです．
某MWJのinoueさんやAnswersでお馴染みのイッヌさんにオススメされてqiitaにもやってきました．
せっかくMATLABを用いて自己研鑽しているので，成果物を記事にした方が同志MATLABユーザ増加に貢献できますし，何より自分の備忘録にもなるのでこの度初投稿することにしました．

想定する読者はもちろん生粋のMATLABユーザさまです．(とはいえとても基礎的な内容です)
今回はそんなMATLAB大好きな皆さんにThingSpeakを用いたMATLAB✖️Twitter芸を紹介したいと思います．


#この記事でできること
苦労せず自動tweet実装できます．

MATLAB homeからもtwitterのAPIさえ取得すればtweet可能です．
個人的にAPI通すのに結構苦労したこと，またThingSpeakから呟く方が遥かにハードルが低かったため今回は後者で実装することにします．(MATLABスクリプトの定期実行ならThingSpeakが便利です)

※twitter関数
https://jp.mathworks.com/help/datafeed/twitter.html

#ThingSpeakって？
我らがMathWorksさまが提供するIoTプラットフォームです．(説明サボります)



詳細はコチラ
https://thingspeak.com/

https://jp.mathworks.com/help/thingspeak/index.html?s_tid=CRUX_lftnav





#APIを取得しよう
取得方法は非常に簡単で下記リンクに飛んでいただき, AppsタブからThingTweetを選択してください．
Link Twitter Account(緑ボタン)からアカウント連携を行うと下図のように即日API keyが発行されます．(本家twitter API取得には目的等を詳細に英語で説明しなければならず手間もかかり苦労しました)
https://thingspeak.com/apps/thingtweets


![スクリーンショット 2022-02-15 22.21.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654274/82fbf93f-8808-2846-5830-308df09a78c5.png)

#実装
ThingSpeakには色々機能はあるのですが今回はAPPの①MATLAB Analysisと②TimeControlを使って定期ツイートを実装してみましょう．

###①MATLAB Analysis
本来は名前の通りThingSpeakチャネルに格納されているデータを解析したりするのでしょうが・・
今回は贅沢にもツイートさせるためだけに使いましょう．
Apps/MATLAB Analysisを選択しNEW(緑ボタン)から下図のページへ．


https://jp.mathworks.com/help/thingspeak/matlab-analysis-app.html


![スクリーンショット 2022-02-15 22.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654274/f2510229-b4a7-682c-5844-b9d364f4b247.png)

皆様お待たせ致しました．やっとMATLAB Codeの出番です．(とはいえとても簡単！)
取得したAPI keyを入れて下記を入力し(Save and Run)してみてください．




    url ='https://api.thingspeak.com/apps/thingtweet/1/statuses/update';
    api_key = 'XXXXXXXXXXXX';%上で取得したAPI keyを入れてください

    message = 'MATLABからツイート';

    message = ['api_key=',api_key,'&status=',message];

    response = webwrite(url,message);
おめでとうございます！
あなたの連携したTwitterアカウントはmessageを呟いていることでしょう．
     
ちなみに・・
        

     at=char'@');
     name='MATLAB_Otter'%任意のアカウント名
     comment='MATLABからツイート'任意のメッセージ
     message = horzcat(at,name,comment);

とすればリプライを飛ばすことも・・(悪用注意)
           

###②TimeControl
次はTimeControlにて①で実装したスクリプトを定期実行します．
Apps/TimeControlを選択しNEW TimeControl(緑ボタン)から詳細設定を行います．

デフォルトでUSタイムゾーンになっているので，お住まいの地域に変更してください．
そのままだと14時間のずれが生じてしまいます．(挨拶botで盛大なミスを犯しました)
また定期実行したいのでFrequencyをRecurringに設定ください．実行タイミングはお好きな時間に・・

またActionとしてMATLAB Analysisと先ほど作成したCodeを選択ください．

実はActionタブからThingTweetを選択すると，ツイート内容をそこにベタ書きすることもできます．
今回はMATLABスクリプトでカスタマイズしたい人向けにあえてMATLAB Analysisを選びました．
(たとえば天候に応じてツイート内容を変えたい,ランダムツイート等)

![スクリーンショット 2022-02-15 23.13.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654274/d622bf32-33b1-7113-ec1d-263cfc2efe1f.png)

#効果の確認
無事ツイートされている模様です．(ThingTweetからの発信になります)
非常に駆け足でしたが，いかがでしたでしょうか．

皆さまもThingSpeakを利用してbot作成等されてはいかがですか？

![IMG_3706.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654274/8a6a1c91-de93-5c62-e76a-521282cb3cc6.jpeg)
ChromeのNo 'Access-Control-Allow-Origin'エラーをデバッグした時の話

ある日、お客さんに納品したWebアプリに一部の人がアクセスできない事象が発生した。
ChromeのDevToolsのログを見ると、APIサーバへの一部のリクエストで、`No 'Access-Control-Allow-Origin' header`エラーになっていた。

ただ、APIサーバ側のアクセスコントロール関連の設定には問題がなく、また、アクセスできる人のDevToolsのログには、問題のヘッダーが正しく含まれていた。
Chromeの拡張機能を全て無効にしても変わらず。他のブラウザでも同じエラーになったため、
どうもアプリケーションレイヤーの問題ではなさそうな気がしていた。

そこで`chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security`で起動して再度アクセスすると、今度は`403 Forbidden`エラーになった。
しかも、レスポンスボディに`Zscaler`という見慣れない単語が表示されていた。

調べてみると、Zscalerはクラウド向けのセキュリティ製品を扱ってる会社で、`Zscaler Internet Access`というWebゲートウェイのサービスも提供していた。怪しい。
しかもこのサービスは、個人単位でのポリシー設定もできるらしく、なおさら怪しかった。

翌日、お客さんのシステム部門に問い合わせてもらい、Zscaler側の設定を見直してもらったところ、無事、アクセスできるようになった。
一部の人のアクセスポリシーが、他の人とは違っていたとのことだった。

お客さんのネットワーク環境に関することなので、あまり詳細なことは書けず、面白みに欠けると思いますが。
今回の事象は、リモートデバックだったことと、非システム部門のお客さんとのコミュニケーションが必要だったこともあり、何だかんだで解決に２週間かかりました。
この記事はそんな苦労を、読んだ人がしなくて済むようになることを願って書いたものなので、その辺は大目に見てください。
VSCodeのRemote ContainersがSSHした先から使えるよ

Windows →　LinuxにSSH接続　→　Linux内のdocker container利用

これができるようになってました。素晴らしい。

Windowsの場合、Docker desktopが必須で、WSLと連携して使う必要がありましたが、Remote-SSHからも使えるようになりました。

# 使い方

1. LinuxサーバでDockerを使えるようにしておく。
1. Windows PCからパスワードなしでssh接続できるようにする
1. VSCodeにremote DevelopmentのPluginをインストール
1. LinuxサーバにVSCodeのRemote-SSHで接続
1. コマンドパレットで、`Remote-Containers: Reopen in Container` でフォルダーを開く

[Container用の設定を追加する方法](https://qiita.com/GeekMasahiro/items/a87ccc925324e756a84b)

# Remote-Containerのドキュメント

https://code.visualstudio.com/docs/remote/containers
ラムダでconcept

今さらですが最近c++20の機能を色々触っています。
そしたらいつの間にかラムダ式が少し強化されていたので今回はそれに関する小ネタを。
# decltype([]{})できるやん
c++17までラムダ式のdecltypeを取るにはいったんラムダを変数に格納した後その変数をdecltypeする必要がありました。

```c++
auto something = []{ cout << "hello" << endl; };
auto func = std::make_shared<decltype(something)>();
(*func)();
```
しかし、c++20では直接ラムダを渡すことができます。

```c++
auto func = std::make_shared<decltype([]{ cout << "hello" << endl; })>();
(*func)();

```
もちろんラムダは定義するたびに別の型となりますのでシグネチャが同じでも代入はできません。

```c++
auto func = std::make_shared<decltype([]{})>();
func = std::make_shared<decltype([]{})>();       // ラムダの型が違うのでfuncには代入できない

```

# 関数クラステンプレートパラメータにラムダを記述する
ラムダをテンプレートパラメータに記述できるようになってよく見かけるのがstlの関数クラスパラメータをラムダ化したものでしょうか

```c++
	// mapの比較クラスをラムダに置き換えたもの（less<int>相当）
	map<int, int, decltype([](int a, int b) {return a < b; }) > { {0, 1}, { 1, 2 } };
	// unique_ptr の削除子クラスをラムダにしたもの（削除直前に標準出力付き）
	unique_ptr<string, decltype([](string* s) {cout << *s << endl; delete s; })> ptr(new string("hoge"));

```
見づらいですがこのようにワンライナーで指定できています。
# ラムダでコンセプト
以上を踏まえてある型Tに対してラムダで定義したコードがパスするかどうかを判定する処理をワンライナーで作ってみます。

```c++
int main() {
	// stringのメンバ関数c_str() constがあるかをチェックする
	static_assert(is_invocable_v<decltype([](const auto& _) -> decltype(_.c_str()) {}), string>);
	return 0;
}
```
やってることはそんな新しいことじゃないですけどテンプレートパラメータだけでコンセプトのようなものが実現できるようになってます。
とはいえラムダの記述性はコンセプトに及ばないんで所詮劣化コンセプトなんですが、ちょっとした記述が必要なところでラムダで書けるのは非常に便利なのではないでしょうか？
これで以前書いた記事[【再考】メンバの存在を調べる](https://qiita.com/z0ero/items/3f104eb42ad3fa69b777)でできなかった事前定義不要の完全なメタプログラミング向けメンバ判定ができるようになりました。
# ちなみに
c++17でラムダを直接テンプレートパラメータに書けなかったのはラムダをコンセプトのように乱用されることを懸念してのことでした。
なのでこの記事は思いっきりよろしくないことを言っているので黒魔術の一種だと思ってくださいｗ
CSS flex-direction, 主軸＆交差軸

# flex-directionの軸
Flexboxには主軸と交差軸がある。
主軸 = justify-content
交差軸 = align-items

* flex-directionがrowの場合水平方向の軸が**主軸(justify-content)**、垂直方向が**交差軸(align-items)**となる。
* flex-directionがcolumnの場合は水平方向が**交差軸(align-items)**、垂直方向が**主軸(justify-content)**となる


### flex-direction: row
![スクリーンショット 2022-02-15 22.24.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524167/94fdd65b-56d7-f481-4ba9-7c4b2e6631cf.png)
### flex-direction: column
![スクリーンショット 2022-02-15 22.24.01 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524167/07fb2129-acc9-7f61-611d-756e62aedd2a.png)
Gtk3アプリ Gtk.Scaleを利用する

###Gtk.Scaleを利用する
<img width="400" alt="Screenshot from 2022-02-15 22-40-13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/57a22415-bc24-3515-6df1-d5e1b45c3b25.png">
Gtk.Scaleを利用するにはGtk.Adjustmentを追加しないといけない。

####GladeからGtk.Adjustmentを追加する
<img width="400" alt="Screenshot from 2022-02-15 22-40-47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/d0b0ae3b-3900-4609-dbdd-e7ffb09b7226.png">
追加されると左のツリーにAdjustmentが追加されます。
<img width="250" alt="Screenshot from 2022-02-15 22-40-56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/5ce0de20-c47f-6dac-49a7-e6435c8174bc.png">
####Adjustmentのパラメーターを設定する
初期値　増減値などが設定できる
<img width="400" alt="Screenshot from 2022-02-15 22-41-41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/bc588c1c-112b-4355-9cbc-97db7c8546f5.png">
####プログラムからAdjustmentを追加する

```cs
scale1.Adjustment = new Adjustment (0, 0.0, 100.0, 1, 10, 0);
scale1.Adjustment.ValueChanged += delegate(object? o, EventArgs args)
{
	Console.WriteLine( ((Gtk.Adjustment)sender).Value );
};
```

####値が変わったら起きるイベントハンドラを追加する
#####Gtk.Scaleでイベントを取得する場合
シグナルはchange-valueを使う
<img width="400" alt="Screenshot from 2022-02-15 22-41-12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/daa38c9e-87a2-cc59-db35-bf9409972f06.png">
#####Gtk.Adjustmentでイベントを取得する場合
シグナルはvalue-changedを使う
<img width="400" alt="Screenshot from 2022-02-15 22-41-22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/90eeb504-5710-6ecb-3ed5-aecafa9b7f26.png">

####値を取得する
adjustment1のValueから取得できます。

```cs
private void on_scale1_change_value(object sender , Gtk.ChangeValueArgs e){
			
	Console.WriteLine( adjustment1.Value);		
}
```

#####イベント関数を自動で生成するにはこのツールが便利
Gtk.Adjustmentにも対応しています。

https://qiita.com/iota_11/items/4e4d77e91ca3e2223cfe

[Gtk3アプリ 画像を表示する](https://qiita.com/iota_11/items/3bbf8f6959c5965498c2)へ続く
Reactでemitする方法

### はじめに
vueだと、$emitで親コンポーネントのイベントを発火します。
今回は、Reactで子コンポーネントのイベントを親コンポーネントに伝える方法を紹介したいと思います。

親コンポーネント

```
import React from 'react'
import Layout from '../components/Layout'
import { Button } from '@material-ui/core'
import ChildComponentDialog from 'src/components/diagnose/ChildComponentDialog'

const IndexPage = () => {
  const [open, setOpen] = React.useState(false)

  const openDialog = () => {
    setOpen(true)
  }
　　　　// 子コンポーネントのイベントハンドラに渡す用の関数
  const closeDialog = () => {
    setOpen(false)
  }

  return (
    <div>
      <h1>診断アプリです。</h1>
      <div>
        <Button variant='outlined' onClick={openDialog}>
          診断する
        </Button>
      </div>
      <ChildComponentDialog open={open} onClose={closeDialog} /> // 子コンポーネント
    </div>
  )
}

export default IndexPage
```

子コンポーネント

```
import React from 'react'
import {
  Dialog,
  withMobileDialog,
  DialogTitle,
  makeStyles,
  DialogActions,
  Button,
} from '@material-ui/core'

type ChildComponentDialogProps = {
  open: boolean
  onClose: () => void
  onSubmit?: () => void
}
const ChildComponentDialog: React.FC<ChildComponentDialogProps> = props => {
  const { open, onClose, onSubmit } = props
  return (
    <BasicDialog
      open={open}
      //　親コンポーネントからpropsで渡された関数
      onClose={onClose}
      onSubmit={onSubmit}
      title='診断コンテンツ'
    >
      <div/>
    </BasicDialog>
  )
}

export default ChildComponentDialog
```

親コンポーネントから子コンポーネントにpropsで子コンポーネントのイベントハンドラに受け渡すことで、イベントが発火したタイミングで親イベントを発火することができます。

イベントハンドラ
https://ja.reactjs.org/docs/handling-events.html

ちなみに、子コンポーネントのデータをemitを通して親コンポーネントに渡すこともできます。

親コンポーネントのイベント用の関数

```
const openDialog = (args) => {
  setOpen(args)
}

```

親コンポーネント

```
const ChildComponentDialog: React.FC<ChildComponentDialogProps> = props => {
  const { open, onClose, onSubmit } = props
  return (
    <BasicDialog
      open={open}
      onClose={onClose}
      // 引数を指定
      onSubmit={() => onSubmit(true)}
      title='診断コンテンツ'
    >
      <div/>
    </BasicDialog>
  )
}

export default ChildComponentDialog
```

() => onSubmit(true)
↑
引数を渡すことが可能です。ちなみに、onSubmit(true)だと動かないです。
colaboratoryでgfortranを使う

環境構築がうまくできない，或いは趣味，その他，様々向け。
強いて言うならスマホやタブレットから簡単に同一のファイルを編集できてコンパイル・実行できる。
!を使えばコマンドは一通り(apt-getでさえ！)できそうなのでcppとか任意言語にも応用が利くだろう。
この記事は学科民のために作成されている。

#まずはColabortoryを開く
開いてください。新規ファイルでよいです。

#サンプルコード

```python:sample.ipynb
!ls -la
#出力例
#total 16
#drwxr-xr-x 1 root root 4096 Feb  1 14:32 .
#drwxr-xr-x 1 root root 4096 Feb 15 13:20 ..
#drwxr-xr-x 4 root root 4096 Feb  1 14:31 .config
#drwxr-xr-x 1 root root 4096 Feb  1 14:32 sample_data

!touch sample.f90
f = open("sample.f90","w") #appendしたいなら"a"を指定，wは中身がすでにあれば全消去して上書きする
f.write( \
"""program sample
  implicit none
  write (*,*) "Hello! This is sample f90 code."
end program sample
""")
f.close()

!cat sample.f90
#program sample
#  implicit none
#  write (*,*) "Hello! This is sample f90 code."
#end program sample
```

ファイルの書き込み部は以下のマジックコマンドを用いたほうが見やすいかもしれない。同じセル内のものが書き込まれるため他のセルと分ける必要あり。

>def def writefile(line, cell)
%writefile [-a] filename
Write the contents of the cell to a file.
>
>The file will be overwritten unless the -a (--append) flag is specified.
>
>positional arguments:
  filename file to write
>
>optional arguments:
  -a, --append Append contents of the cell to an existing file. The file will be created if it does not exist.

```python:sample.ipynb
%%writefile sample.f90 #appendしたいなら%%writefile -a sample.f90
program sample
  implicit none
  write (*,*) "Hello! This is sample f90 code."
end program sample
```
```python:sample.ipynb
!gfortran sample.f90 -o sample.o
!./sample.o
#Hello! This is sample f90 code.
```
Oracleの予約語が含まれていた場合

忘れがちなのでメモ
#予約語とは
システム側で用意しているコマンドや句のこと

例えば「SELECT」という、列があった場合、
Oracleでは、SELECT文と認識します。
そのため、その文法使い方間違ってますと怒られます。
そういうときは、列名として認識させたいので、
SELECT "SELECT"FROM "SELECT"のように
ダブルクォート(")で囲ってあげると列として使用できます。
AWSにEC2, RDS, S3のインスタンスを立ててみた

昨年、「AWS 認定ソリューションアーキテクト – アソシエイト」に合格したものの、
実際にAWSに環境構築したりする機会がほとんどないなかったため、
AWS上でWebアプリ環境を構築すべく、EC2、S3、RDSのインスタンスを作成してみました。
無料枠を使えるのもは使うようにしています。

S3にフロントを配置し、EC2にバックエンドのAPIサーバを構築、RDSはデータベースとし、
S3に配置したWebページよりAPIを実行し、データの読み書きを行うWebアプリを想定しています。

その前段階として、それぞれのインスタンスを立ててみました。

# EC2
コンソールトップより`仮想マシンの起動`を選択して始めます。

### AMIの選択
`Amazon Linux 2 AMI（HVM）`を選択します。
無料利用枠のみチェックで無料枠を絞れます。

### インスタンスタイプの選択
`t2.micro`を選択します。
t2.microのみ無料利用枠の対象のようです。（ラベルが表示されている）
ちなみに、t2.microの性能は次のようです。

### インスタンスの詳細の設定
変更なしです。
なお、VPCはEC2作成時に作成されるようです。
サブネットはアベイラビリティゾーンのデフォルトが設定されます。
自動割り当てパブリックIPはサブネット設定を使用（有効）としました。

### ストレージの追加
追加なしです。
初期では汎用SSDが作成されます。

### タグの追加
設定なしです。

### セキュリティグループの設定
新しいセキュリティグループが作成されます。
なお、`0.0.0.0/0`にすると全てのIPアドレスからインスタンスにアクセスすることができるので、既知のIPアドレスからのみアクセスできるようにしたほうがいいようです。
ここでは以下を追加しました。
  * SSH: 22
  * HTTP: 8080
  * HTTPS: 8443

### インスタンス作成の確認
ここで最終確認できます。
`起動`ボタンで作成&起動されます。
そのまえに…キーペアの作成ダイアログが表示されます。
既存のキーペアを選択するか、新しいキーペアを作成します。
キーペア名を入力して、キーペアのダウンロードで.pemがダウンロードされます。
`インスタンスの作成`ボタンを押すとインスタンスの作成が開始されます。

### SSH接続
起動したEC2インスタンスは以下のコマンドにてSSH接続できます。

```bash
ssh -i [ダウンロードしたキーペア] ec2-user@[IPv4パブリックIP]
```

実行すると以下のエラーがでました。

```
Permissions 0644 for '~/.ssh/xxxxx.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
```

要するに権限をつけすぎと言われるのでchmod 600で所有者だけに権限を与えるようにしました。

# RDS
AWSのRDSから`データベースの作成`を実行を選択します。

### データベースの作成
##### データベースの作成方法
標準作成を選択を選択します。

##### エンジンのオプション
今回はPostgresSQLを選択しました。

##### テンプレート
無料利用枠を選択する（バージョンによっては選べないみたい）

##### 設定
インスタンス識別子: 任意のインスタンス識別子を入力します。（一意である必要あり） 
認証情報の設定: DBの認証情報を入力します

##### DBインスタンスクラス
db.ts.microを選択（バースト可能クラス）を選択しました。

##### ストレージ
以下を選択しました。
　ストレージタイプ: 汎用SSD
　ストレージ割り当て: 20

##### 接続
以下を選択しました。
　VPC: デフォルト
　サブネットグループ: デフォルト
　パブリックアクセス: なし（VPC内部のEC2のみ）
　VPCセキュリティグループ: EC2で作成したグループを選択

##### データベース認証
パスワード認証を選択しました。


最後に、`データベースの作成`をクリックで作成されます。

### インバウンドルール追加
セキュリティグループでインバウンドルールを追加します。
　タイプ: PostgresSQL

### RDSへの接続
PostgresSQLの場合は、以下にて接続できます。

```bash
psql --host=[RDSのエンドポイント] --port=[ポート番号(デフォルト:5432)] --username=[記入した認証情報] --password
```

# S3
AWSのS3にて`バケットを作成`をクリックして始めます。

##### 一般的な設定
バケット名: 任意のバケット名を入力します（一意である必要あり）
AWSリージョン: リージョンを選択します

##### オブジェクト所有者
ACL無効を選択しました。
有効にすると他のAWSアカウントがバケット内のオブジェクトの所有者になることができます。

##### このバケットのブロックパブリックアクセス設定
一旦、パブリックアクセスをすべて ブロックのままとしました。

##### バケットのバージョニング
無効にしました。

##### デフォルトの暗号化
サーバ側の暗号化: 無効にしました。


上記でEC2、RDS、S3のインスタンスを作成できました。
Webアプリ構築時に、セキュリティ設定など更新していきたいと思います。
rails 自動整形ツールRubocopの導入

# はじめに
rubyの自動整形ツールであるrubocopの導入方法をまとめる。

# 環境
- rails 6.0.4.4
- ruby 2.6.5
- rubocop 1.25.1

# Rubocopとは
Rubyのコード解析ツール。
自身で決めた規定通りにコードを書けているか解析、かつ、自動で修正してくれるツール。
インデントを揃えたり、余分な改行・スペースを削除したりできる。
[RubyStyleGuide](https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md)に基づいて指摘を行う。

公式 https://rubocop.org/

# Rubocopの導入方法
Gemファイルに記載

```Gemfile.
groupdevelopment do
   gem 'rubocop', require: false
end
```

インストール

```ターミナル.
bundle install
```

Rubocopの設定ファイルを新規作成

```ターミナル.
touch .rubocop.yml
```

.rubocop.ymlを編集して設定を作成

```.rubocop.yml
AllCops:
# 除外するディレクトリ（自動生成されたファイル）
# デフォルト設定にある"vendor/**/*"が無効化されないように記述
 Exclude:
   - "vendor/**/*" # rubocop config/default.yml
   - "db/**/*"
   - "config/**/*"
   - "bin/*"
   - "node_modules/**/*"
   - "Gemfile"


# 1行あたりの文字数をチェックする
Layout/LineLength:
 Max: 130
# 下記ファイルはチェックの対象から外す
 Exclude:
   - "Rakefile"
   - "spec/rails_helper.rb"
   - "spec/spec_helper.rb"

# RSpecは1つのブロックあたりの行数が多くなるため、チェックの除外から外す
# ブロック内の行数をチェックする
Metrics/BlockLength:
 Exclude:
   - "spec/**/*"

# Assignment: 変数への代入
# Branch: メソッド呼び出し
# Condition: 条件文
# 上記項目をRubocopが計算して基準値を超えると警告を出す（上記頭文字をとって'Abc'）
Metrics/AbcSize:
 Max: 50

# メソッドの中身が複雑になっていないか、Rubocopが計算して基準値を超えると警告を出す
Metrics/PerceivedComplexity:
 Max: 8

# 循環的複雑度が高すぎないかをチェック（ifやforなどを1メソッド内で使いすぎている）
Metrics/CyclomaticComplexity:
 Max: 10

# メソッドの行数が多すぎないかをチェック
Metrics/MethodLength:
 Max: 30

# ネストが深すぎないかをチェック（if文のネストもチェック）
Metrics/BlockNesting:
 Max: 5

# クラスの行数をチェック（無効）
Metrics/ClassLength:
 Enabled: false

# 空メソッドの場合に、1行のスタイルにしない　NG例：def style1; end
Style/EmptyMethod:
 EnforcedStyle: expanded

# クラス内にクラスが定義されていないかチェック（無効）
Style/ClassAndModuleChildren:
 Enabled: false

# 日本語でのコメントを許可
Style/AsciiComments:
 Enabled: false

# クラスやモジュール定義前に、それらの説明書きがあるかをチェック（無効）
Style/Documentation:
 Enabled: false

# ％i（）構文を使用していないシンボルで構成される配列リテラルをチェック（無効）
Style/SymbolArray:
 Enabled: false

# 文字列に値が代入されて変わっていないかチェック（無効）
Style/FrozenStringLiteralComment:
 Enabled: false

# メソッドパラメータ名の最小文字数を設定
Naming/MethodParameterName:
 MinNameLength: 1
```
設定は任意で作成することが可能。

# Rubocopの実行

```ターミナル.
bundle exec rubocop -a
```
「-a」を付けることでチェック内容を自動修正する。

# おわりに
実行後はコードがすごく読みやすくなる。間違いが見つけやすくなり、修正もしやすくなるので、一区切りごとにやっていく。
バージョンの違いによって、動作に違いがあるようなので、確認する必要がある。


# 参考
[【Rails】RuboCopの基本的な使用方法と出力の見方](https://qiita.com/terufumi1122/items/ad55bf8713c0df053f58)
Google検索テクニック

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

## Google検索テクニック

### 完全一致検索
検索ワードを`""`で括ることで完全一致検索をすることが出来ます。

　**"Mac"**
　　→「Mac」に完全一致する検索結果が得られる

### NOT検索（マイナス検索）
キーワードの前に`-`を入力することで`-`の後ろのキーワードを含まないWebページを検索することが出来ます。

　**Mac　-Windows**
　　→「Mac」の検索結果から「Windows」の検索結果を除いた結果が得られる

### OR検索
２つの検索ワードの間に`OR`を入力することでOR検索をすることができます。

　**Mac　OR　Windows**
　　→「Mac」か「Windows」に合致する結果を得ることができる

### あいまい検索
検索ワード内不明な箇所に*（アスタリスク）を入力することであいまい検索をすることができます。

　**M*c　Windo*s**
　　→「M（何らかの文字）c」と「Windo（何らかの文字）s」に合致する結果を得ることができる

### タイトル検索
検索ワードの前に`intitle:`を入力することでタイトルに検索ワードを含むWebページを検索することができます。

　**intitle:Mac**
　　→「Mac」がタイトルに含まれる結果を得ることができる

複数キーワードを指定する際には`allintitle:`を検索結果の前に入力します。
　
　**allintitle:Mac　Windows**
　　→「Mac」と「Windows」がタイトルに含まれる結果を得ることができる

### サイト内検索
`site:<URL>`を入力することでサイト内検索をすることがでできます。
　**Mac site:https://example.jp**
　　→<https://example.com>内の「Mac」に合致する結果を得ることができる

### 類似サイト検索
`related:<URL>`を入力することで類似サイトを検索することができます。
**related:https://example.jp**
　　→<https://example.com>の類似サイトの検索結果を得ることができる

### 期間指定
Google検索バーの下にある「ツール」クリックし、「期間指定」から期間を選ぶことで、期間を指定することができます。
![スクリーンショット 2022-02-15 22.10.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/ac571d23-09dd-95fd-1d1b-4e4488d41294.png)
更に Ruby の Matrix と Numo::NArray で pagepank をやってみた

# はじめに
https://qiita.com/superrino130/items/42ac760b0f202cefe6bc

前回の記事を投稿後、Rubyの元標準ライブラリの`Matrix`と外部ライブラリの`Numo::NArray`があったので、更にやってみた。
# 問題の整理[再掲]
ノード数`N`の有向グラフがある。
高橋くんはノード1からスタートして100回ランダムな遷移を行います。
遷移後、高橋くんがどのノードにいるかを答えてください。

```
入力
N M
A1 B1
.
.
.
Am Bm
```
```
入力例
5 7
1 2
1 3
2 4
3 4
3 5
4 5
5 1
```
# Ruby Matrix版
```ruby:matrix.rb
require 'matrix'

n, x = gets.split.map(&:to_i)
m = Matrix.zero(n)
x.times do
  a, b = gets.split.map(&:to_i)
  m[b - 1, a - 1] += 1
end
s = m.column_vectors.map{ _1.sum.to_f }
n.times do |i|
  n.times do |j|
    m[i, j] /= s[j]
  end
end
v = Matrix.column_vector([1.0 / n] * n)
100.times do
  v = m * v * 0.85
  v += Matrix.column_vector([(1 - 0.85) / n] * n)
end
puts v

# output
Matrix[[0.2541917802460697], [0.13803150660856423], [0.13803150660856423], [0.20599017093683208], [0.2637550355999698]]
```
普段`Matrix`を使用していないので、もう少しきれいに書きたかったです。

https://docs.ruby-lang.org/ja/latest/class/Matrix.html
# Numo::NArray
```ruby:narray.rb
require 'numo/narray'

n, x = gets.split.map(&:to_i)
m = Numo::DFloat.zeros(n, n)
x.times do
  a, b = gets.split.map(&:to_i)
  m[b - 1, a - 1] += 1
end
n.times do |i|
  s = m[true, i].sum
  n.times do |j|
    m[j, i] /= s
  end
end
v = Numo::DFloat.new(n).fill 1.0 / n
100.times do
  v = m.dot v * 0.85
  v += Numo::DFloat.new(n).fill (1 - 0.85) / n
end
p v

# output
[0.254192, 0.138032, 0.138032, 0.20599, 0.263755]
```
はじめて？使用したので、怪しいところがあるかもしれませんが。

https://rubygems.org/gems/numo-narray/versions/0.9.1.4?locale=ja
# benchmark
```ruby:benchmark.rb
require 'numo/narray'
require 'benchmark'
require_relative 'lib/networkx'
require 'matrix'

@n = 300
Benchmark.bm 10 do |r|
  r.report "networkX" do
    g = NetworkX::DiGraph.new
    @n.times do |i|
      g.add_edge(i, (i + 1) % @n)
    end
    NetworkX.pagerank(g)
  end

  r.report "matrix" do
    m = Matrix.zero(@n)
    @n.times do |i|
      m[(i + 1) % @n, i] += 1
    end
    s = m.column_vectors.map{ _1.sum.to_f }
    @n.times do |i|
      @n.times do |j|
        m[i, j] /= s[j]
      end
    end
    v = Matrix.column_vector([1.0/@n] * @n)
    @n.times do
      v = m * v * 0.85
      v += Matrix.column_vector([(1 - 0.85) / @n] * @n)
    end
  end

  r.report "narray" do
    m = Numo::DFloat.zeros(@n, @n)
    @n.times do |i|
      m[(i + 1) % @n, i] += 1
    end
    @n.times do |i|
      s = m[true, i].sum
      @n.times do |j|
        m[j, i] /= s
      end
    end
    v = Numo::DFloat.new(@n).fill 1.0 / @n
    @n.times do
      v = m.dot v * 0.85
      v += Numo::DFloat.new(@n).fill (1 - 0.85) / @n
    end
  end
end

# output
                 user     system      total        real
networkX   107.812000   0.046000 107.858000 (108.873295)
matrix       2.282000   0.000000   2.282000 (  2.311542)
narray       0.062000   0.000000   0.062000 (  0.058779)
```
とりあえず、ベンチマークを取ってみました。
`networkX`より、即席で作成した`Matrix`版の方が成績が良くて、困ったものです。

それにしても、`Numo::NArray`は爆速ですね。
# まとめ
+ pegerank に更に詳しくなった
[React] Recoilの簡単な使い方

#Recoilで何ができる？
ざっくり言うと、簡単にReactでグローバルなStateの管理ができる。

# Recoilに触れてみる
何はともあれ触れてみよう

## install
とりあえずnpmでinstall。

```javascript:
npm install recoil
```


## 参照範囲を決める
```javascript:App.js
export default function App() {
  return (
    <RecoilRoot> //RecoilRootで囲む
      <exComponent />
    </RecoilRoot>
  );
}
```
設定するState参照範囲はRecoilRootで囲んだ部分に限定される。
今回はグローバルに設定したいので、App.jsの外枠にRecoilRoot。

## State定義用のfileの作成
src配下にstoreというフォルダを作って格納するのがわかりやすいかもしれない。
State定義のみなので、jsファイルで可。今回はexState.jsを配置した。

## Stateの定義
```javascript:exState.js
import {atom} from "recoil"

export const exState = atom ({ //atom で囲む必要がある
 key: "exState" //参照時に必要なキー
 default: {flag: true} //default値
})
```
定義するStateはまずatomで囲む（atomic designとは関係ない）。
初期値としてState参照時に必要なkey,default値として持っておくdefaultを格納しておく。


## 使用する
実際に使用してみる。

### Stateの値、更新関数を参照する場合

```javascript:
[exState, setExState] = useRecoilState(exState)
```

### Stateの値のみを参照する場合

```javascript:
exState = useRecoilValue(exState)
```

### Stateの更新関数のみ参照する場合

```javascript:
setExState = useSetRecoilState(exState)
```

##まとめ
グローバルなState管理はContextを使用しても良いが、Recoilのほうが直感的でおすすめかもしれない。
【Kotlin】Sleep FizzBuzz

https://zenn.dev/mattn/articles/37fc825cba8fd2

↑の記事にある Sleep FizzBuzz を Kotlin Coroutines でやってみた。


## 単純版

素直にやるとこんな感じ。

```Kotlin
fun main() = runBlocking<Unit> {
    launch {
        for (i in 1..Int.MAX_VALUE) {
            delay(1_000)
            print("\n$i\r")
        }
    }
    launch {
        delay(100)
        while (true) {
            delay(3_000)
            print("Fizz\u001b[K")
        }
    }
    launch {
        delay(200)
        while (true) {
            delay(5_000)
            print("Buzz\u001b[K")
        }
    }
}
```

（元記事の方法とは少し変えて、
　出力され始めるまで1秒待つが
　その分読みやすいコードにした。）

結果。

```
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
```

うまくいっているように見える。

しかし 100 くらいまで来るともうグダグダ。

```
FizzBuzz
90
91
Fizz
93
Buzz
Fizz
96
97
Fizz
Buzz
100
```

`print` 関数の呼び出し、その引数とする文字列の構築、それにスレッドの切り替えなどに時間が掛かって、
誤差が出てくるのだろう。


## `SharedFlow` で Ticker を作る

お題の趣旨からは少し離れてしまうが、
`SharedFlow` を使っていわゆる Ticker を作り、
ズレが出ないようにしてみた。

```Kotlin
fun main() = runBlocking<Unit> {
    val ticker =
        flow {
            for (sec in 1..Int.MAX_VALUE) {
                emit(sec)
                delay(1_000)
            }
        }.shareIn(this, SharingStarted.Lazily)

    ticker
        .onEach {
            print("\n$it\r")
        }.launchIn(this)
    ticker
        .filter { it % 3 == 0 }
        .onEach {
            delay(1)
            print("Fizz\u001b[K")
        }.launchIn(this)
    ticker
        .filter { it % 5 == 0 }
        .onEach {
            delay(2)
            print("Buzz\u001b[K");
        }.launchIn(this)
}
```

これはうまくいった。

```
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
```

1000付近でも大丈夫。

```
FizzBuzz
991
992
Fizz
994
Buzz
Fizz
997
998
Fizz
Buzz
```


## 【Kotlin/JVM】 `ScheduledThreadPoolExecutor.scheduleAtFixedRate` を使う

Java の [`ScheduledThreadPoolExecutor.scheduleAtFixedRate`](https://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html#scheduleAtFixedRate-java.lang.Runnable-long-long-java.util.concurrent.TimeUnit-) を使うと次のようになる。

```Kotlin
fun main() = runBlocking<Unit> {
    var i = 1
    ScheduledThreadPoolExecutor(1)
        .scheduleAtFixedRate(
            { print("\n${i++}\r") },
            1_000 + 0,
            1_000,
            TimeUnit.MILLISECONDS,
        )
    ScheduledThreadPoolExecutor(1)
        .scheduleAtFixedRate(
            { print("Fizz\u001b[K") },
            3_000 + 1,
            3_000,
            TimeUnit.MILLISECONDS,
        )
    ScheduledThreadPoolExecutor(1)
        .scheduleAtFixedRate(
            { print("Buzz\u001b[K") },
            5_000 + 2,
            5_000,
            TimeUnit.MILLISECONDS,
        )
}
```

これはお題の趣旨にも合っているし、
正しい結果が得られる。
（Kotlin らしさはほとんどないが。）


／以上
Babelのプリセット

# プリセットの作成

作成方法は至って簡単。
プラグインの配列を返すjsスクリプトを作成するだけ。

```javascript
module.exports = function() {
  return {
    plugins: ["pluginA", "pluginB", "pluginC"],
  };
};
```
また他のプリセットを含ませたり、プラグインにオプションを追加することもできる。

```javascript
module.exports = () => ({
  presets: [require("@babel/preset-env")],
  plugins: [
    [require("@babel/plugin-proposal-class-properties"), { loose: true }],
    require("@babel/plugin-proposal-object-rest-spread"),
  ],
});
```

#プリセットの実行順

```javascript
{
  "presets": ["a", "b", "c"]
}
```

上記のようなコンフィグファイルがあるときの実行順序はc, b, aとなる。

# オプションの定義

オプションの定義は下記のように配列を利用して作成する。１つ目の要素にプリセット名、第二要素にオプションオブジェクトを定義する。

```javascript
{
  "presets": [
    [
      "presets-A",
      {
        "var": "hoge",
        "boolean": true
      }
    ],
    [
      "@presets-B",
      {
        "var": "hoge",
        "boolean": true
      }
    ],
    [
      "presets-C",
      {
        "var": "hoge",
        "boolean": true
      }
    ]
  ]
}
```


```javascript
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "loose": true,
        "modules": false
      }
    ]
  ]
}
```

以上
Gravatarでアイコンを統一してみる

### 概要

自分のアイコンの画像を各サービス横断しても、
いい感じに統一したいなと思って登録したWebサービス

### クイックスタート

1. こちらのWebサービスを開く
https://ja.gravatar.com/

2. あと登録をすすめて登録する。反映に時間かかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/02ddaa6f-fbc9-d75b-9c5e-9ffc6056c73b.png)

### 統一できたアプリ

・ Slack
・ Github
・ Qiita
・ Jira
・ GitLab
・ Redmine

### 統一できなかったアプリ

・ Backlog
terraformのimportを超快適にしてみた件【v4の破壊的変更のお供に！】

# いつものアレ

**「リソース作っておいたから後はよろしくねー」**

開発チームから期日の無いチケットが切られる。やれやれだぜいつものimport作業発生かよ・・
importするリソースを公式ドキュメントで調べていると次のメンションが

**「先週importしてもらったの差分出てるよ。調査してみてくれない？」**

ええ？誰か手作業で変更した？？tfstateのバックアップ探さないと・・、とさらに追撃のメンション

**「この前importしたやつ、importするリソースが足りてないと思います！」**

もはやインフラ屋じゃなくてimport屋か？？IaC化は別のトイルを産んでいる

# そもそもimportの仕組みがよろしくないのよね

ググリが前提なんだよね。リソース名とかargsの指定方法とか。
そこまではどんなツールでも変わらないけど、main.tfファイルの生成は手動とかは違うんじゃねー？って思う。
あとターゲットリソースの指定は事前に調査してってのもなぁ。**そんな理由でマネコン入るのってどうなの？？**
aws2tfとか一気にブッコ抜くツールも良いんだけど、もっとコンパクトに分かりやすく動くものって無いしなァ

# 作ったわ！

[![yasutakatou/tfimport - GitHub](https://gh-card.dev/repos/yasutakatou/tfimport.svg)](https://github.com/yasutakatou/tfimport)

詳しくはリポジトリで。Bashベースのエコシステムに乗っかったツールです。対応import数増えてくと良いなぁ(他力本願

## v1.1 - v1.4

コンフィグの追加で以下のimportをサポートしました

- WAF v2
- CloudFront
- WAF Classic
- IAM Policy
- IAM Role

あと**リージョン指定**と**バージョン固定**のオプションもいれました

## v1.5 - v2.0

選択用のpecoを任意で呼び出せるモードと、一度に複数リソースをimport出来るモードを追加しました

コンフィグの追加で以下のimportをサポートしました

- ListenerRule
- secretsmanager
- ECS Autoscale

## v3.0 - v3.1

Mac OSでも動くようにしたのと、datadogのモニターも抜き出せるよう複数コンフィグを扱えるようにしました

- Mac OS対応
- Terraform AWS Provider v4でS3のリソースが細分化されたので一気に抜き出せるようにした
- datadogのモニターに対応

# どんなん？

このツールを使うと・・

- **インタラクティブにimportするリソースを指定できます**
- **バッチ処理っぽくスナップショット的にtfstateを抜き出せます**
- **複数リソースを一度に抜き出せます**

pecoで検索性バッチリでリソース指定できーの、

![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/c9e15f88-d997-7159-1640-40efda65f0ce.gif)

バッチ処理ぽくtfstateを抜き出せーの

![2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/a706d5c3-486a-dbe5-af9a-775b47cf78e2.gif)

複数リソースを一度に抜き出せるのでimport漏れも解消！

といったかんじでimportに関わるめんどくさいエトセトラが解決できます！

# あとがき
いまだかつてない抽象化の高い・・・というかほぼコンフィグに任せっぱなしのツールですｗ
階層的に抜き出したものを後に引き継ぐだけなんだけど立派なツールなような気がする。
コンフィグを充実させることで組織のノウハウも拡充できる気がするので成長性Aってことで良いんじゃないかなｗ

[TerraformのAWS Provider v4メジャーアップデートは破壊的変更あり](https://qiita.com/Shoyu_N/items/871ebf0c1d41493c22ac)

こういう、どーしょーもない変更喰らってもとりあえずIaC出来るので是非是非に
SourceTreeがなぜかgithubのログインを要求してきて操作できなくなる現象について

#概要
SourceTreeでgithubとやり取りする際にたまに起こるこんな症状がある
* pull/push... など、とにかくなんでもいいけどgithubにアクセス
* プログレスバーが走って”アクセスしてるなー感”出してる途中で突然githubにログインしてください的ポップアップが現れる！
* 認証確認してみるも何ら問題がない
* でもポップアップが出る　仕方なくログインしてみてもエラーがでて操作が完了しない…
* githubのアカウントページを確認してももちろん問題がない

#原因
わからない
だいたい忘れたころに起こる

#解決策
1. メインメニュー ツール>オプション　を開く
2. 認証タブ　を開く
3. ログインを要求されるアカウントを削除する
4. 再度認証する

これでなおる
dockerでの環境構築時に出てきた、PHP message: Xdebug: [Log Files] File '/tmp/xdebug.log' could not be opened.PHP message: Xdebug: [Step Debug] Could not connect to debugging client. の解決方法

皆様こんにちは。
先日入社した会社でdockerを用いた開発環境の構築を行なっていたのですが、その際にエラーが出て詰まってしまったので、備忘録を兼ねて記事を書こうと思います。

## エラー文

```
PHP message: Xdebug: [Log Files] File '/tmp/xdebug.log' could not be opened.PHP message: Xdebug: [Step Debug] Could not connect to debugging client
```

## エラー文の意味

/tmp/xdebug.logが開けず、Xdebugがdebug出来ていない。

## 解決策

project直下に、launch.jsonを用意する。

```json
{
    "version": "0.2.0",
    "configurations": [
      {
        "name": "Listen for XDebug",
        "type": "php",
        "request": "launch",
        "port": ポート番号（デフォルトは9000番）,
        "pathMappings": {
          "/var/www": "${workspaceFolder}/www" // Dockerのドキュメントルート:ローカルのドキュメントルート
        }
      }
    ]
  }
```
【jest】モック化したuseRecoilValueの戻り値がundefinedになる【react】

# はじめに

タイトルどおりですが、モック化した`useRecoilValue`や`useRecoilState`の戻り値が`undefined`になってしまう現象に遭遇し、小一時間ハマってしまいました。
jest 初心者なので勉強がてらメモを残します。

# 解決策

後に再現コードを記載しますが、先に結果を知りたい人用に解決策を記載します。
結論としては、以下の 2 点が解決策となります。

- 各テストケースごとに`mockImplementation`を書く
- `beforeEach`に`mockImplementation`を書く

`beforeEach`と似た関数に`beforeAll`がありますが、こちらはうまく動作しませんでした。
公式ドキュメント：[beforeAll(fn, timeout)](https://jestjs.io/ja/docs/api#beforeallfn-timeout)、[beforeEach(fn, timeout)](https://jestjs.io/ja/docs/api#beforeeachfn-timeout)

# 再現コード

テスト対象のコンポーネントは成功、失敗に関わらず同一です。

```jsx:テスト対象
import { atom, useRecoilValue } from "recoil";

const store = atom({
  key: "store",
  default: "default value",
});

function App() {
  const state = useRecoilValue(store);

  return (
    <div>
      <p id="test-element-1">{state}</p>
    </div>
  );
}

export default App;
```

## うまくいったケース

```jsx:テストコード
import { useRecoilValue } from "recoil";
import { shallow } from "enzyme";
import App from "./App";

jest.mock("recoil");

describe("各テストケースごとに mockImplementation を書く", () => {
  test("recoilテスト", () => {
    useRecoilValue.mockImplementation(() => "test value");

    const result = shallow(<App />);
    expect(result.find("#test-element-1").text()).toEqual("test value");
  });
});

describe("beforeEach に mockImplementation を書く", () => {
  beforeEach(() => {
    useRecoilValue.mockImplementation(() => "test value");
  });

  test("recoilテスト", () => {
    const result = shallow(<App />);
    expect(result.find("#test-element-1").text()).toEqual("test value");
  });
});
```

## うまくいかなかったケース

いずれも`state`の中身が`undefined`になっています。

### ケース① - `jest.mock`で`useRecoilValue`をモック化する

```jsx:テストコード
import { shallow } from "enzyme";
import App from "./App";

jest.mock("recoil", () => ({
  ...jest.requireActual("recoil"),
  useRecoilValue: jest.fn(() => "test value"),
}));

describe("jest.mock で useRecoilValue をモック化する", () => {
  test("recoilテスト", () => {
    const result = shallow(<App />);
    expect(result.find("#test-element-1").text()).toEqual("test value");
  });
});
```

### ケース② - `beforeAll`に`mockImplementation`を書く

```jsx:テストコード
import { useRecoilValue } from "recoil";
import { shallow } from "enzyme";
import App from "./App";

jest.mock("recoil");

describe("beforeAll に mockImplementation を書く", () => {
  beforeAll(() => {
    useRecoilValue.mockImplementation(() => "test value");
  });

  test("recoilテスト", () => {
    const result = shallow(<App />);
    expect(result.find("#test-element-1").text()).toEqual("test value");
  });
});
```
Javaのインクリメント・デクリメントについてまとめてみた

Javaのインクリメントとデクリメントについて学習したのでまとめてみたいと思います。

# Javaのインクリメントとデクリメントの書き方とそれぞれについて

|  |処理内容  |構文  |
|---|---|---|
|インクリメント  |一つ加算される  |変数++、もしくは、++変数  |
|デクリメント  |一つ減産される  |変数--、もしくは、--変数  |

インクリメントに関しては見たことがあると思います。

```main.java
public class main {
    public static void main (String[] args) {
		for (int increment = 0; increment < 2; increment++){
			System.out.println("increment=" + increment);
		  }
    }
}
```

このようにJavaでfor文を使ったことがある人であれば、変数++でインクリメントしているところを見たことがあると思います。

ただ、インクリメントもデクリメントには、前置と後置のに種類があります。
それによって挙動がマジで変わるので覚えておきましょう。

前置?後置?何だそれ
ってなったあなた。

これから説明します。

# インクリメントとデクリメントの前置と後置について

前置と後置の違いは値が足されるタイミングが違います。

後置と前置はそれ単体で使うときは同じ結果を返します。

```
int num = 5;

// 後置
num++;
num--;

// 前置
++num;
--num;
```

ただ、インクリメントした値を別の変数に格納したいときは前置と後置挙動が変わります。

これからそれについて紹介します。


例えば

```main.java
public class main {
    public static void main (String[] args) {
		int x = 10;
        int y = x++;
		System.out.println(y);
    }
}

```

このように、変数xの値絵をインクリメントした値を変数yに代入したら変数yはどのように出力されるでしょう。

答えは

```
10
```

です。

なぜかというと、インクリメントされるのと変数に格納されるタイミングがあるからです。

今回の場合は、変数xがインクリメントされる前の値が変数yに代入されてから変数xの値がインクリメントされて変数xの値が更新されます。なので、インクリメントしても変数yの値が11にならないわけです。
では、変数yの値を11にするにはどうしたらいいでしょうか。
それは

```main.java
public class main {
    public static void main (String[] args) {
		int x = 10;
        int y = ++x;
		System.out.println(y);
    }
}

```

このように、++x(後置)にすれば大丈夫です。
こうすることで、変数 x の値を 1 増やしたあとで増えたあとの値が変数 y に代入されます。

では、この声性質を応用して少し練習問題をしましょう。

```main.java
public class main {
    public static void main (String[] args) {
		int x = 10;
        int y = x++ - x--;

		System.out.println(y);
    }
}
```

この場合h、変数yの値はどうなるでしょうか。


### 正解は

```
-1
```

です。

解説をしましょう。
最初のx++では、値は10です。しかし、それが`- x--`の段階になる時に、x++でインクリメントされた数が一時変数として残り、その値がx--に代入されるからです。
あれ、じゃあデクリメントされたｘ−−の値はどうなるんだよってなると思いますが、この場合はその値はこの先の四季で代入される値がないので、今回の場合は使われません。

ちなみに、x--を--xとした場合は値は

```
0
```

になります。
以上になります。
ありがとうございました。
gitコマンドが使えなくなったのを、元通り使えるようにしたい。（原因は、macOS のアップデートを実行したため）

原因は、macOS のアップデートだったから、これからも同様のことがあるだろうけど、その度に忘れて、その度に簡単に解決するやん、となることでしょう。（今回も既に２回目だった）

## 1. **やりたいことを確認する。**

- `git`コマンドが使えなくなったのを、元通り使えるようにしたい。

## 2. **課題（エラーの状況、不明点、エラーログ）を確認する。**

⚠️ `git clone`しようとしたら失敗した。

```bash
$ git clone https://github.com/xxx/xxx.git
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
```
⚠️ そのほかの`git`コマンドも使えない。

## 3. **調査する（ググる、ドキュメントを読む）**

> macOS High SierraからMojaveにアップデート後、gitコマンドを利用しようとしたら以下のエラーが出ました。
> 
> 
> ```bash
> xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
> ```
> 
> 以下のコマンドを実行し、xcodeをインストールすれば解決できます。
> 
> ```bash
> xcode-select --install
> ```
> 

https://qiita.com/nishina555/items/e23d73067a5cac182a63

https://qiita.com/Takao_/items/6a58a3a169e5594f51e9

そういえば最近macOSアップデートを実行したなぁ…。

## 4. **調査結果からの考察、対策を実行する**

🧑🏻‍💻 調べたコマンドを実行する。

```bash
$ xcode-select --install
xcode-select: note: install requested for command line developer tools
```

🧑🏻‍💻 ソフトウェアをインストールする。

🧑🏻‍💻 使えることを確認する。（解決！）

```bash
$ git status
On branch feature-xxx
Your branch is up to date with 'origin/feature-xxx'.

nothing to commit, working tree clean
```