OmniAICreator/Qiita-1.07M huggingface dataset:
【React】useCallbackの使い方

## 関数式による再レンダリング問題
再レンダリングのタイミングには以下の２つがある
1. stateの更新
2. propsの更新

（以下ではAコンポーネントの中でBコンポーネントが呼び出されている）
ここで、Aコンポーネント内のstateが更新されたとする。
すると再レンダリングが起きてAコンポーネント内を上から再度読み込んでいく。
このとき、Aコンポーネント内に関数式があれば再代入される。
再代入された関数式は以前の関数式と処理の内容は変わらないものの、Reactは全く新しい関数として判断する。
このとき、関数式をBコンポーネントにpropsとして渡しているとする。以前のものと異なる関数式がBコンポーネントのpropsとして渡されるので、Bコンポーネントで再レンダリングが起きてしまう。

上記のようにAコンポーネント内のstateが更新されただけなのに、Bコンポーネントまでもが再レンダリングされていることを「関数式による再レンダリング問題」と定義する

## Bコンポーネントのmemo化による解決
memo化では解決できない

## useCallbackによる解決
関数式をuseCallbackの引数に渡すことで再レンダリングを操作することができる。
第1引数には関数式、第2引数には配列を設定する

```ts
const test = useCallback(()=>{}, [])
```
第2引数の配列を依存配列といい、依存配列の値が更新された場合のみ関数が再定義されるようになる。
下記の場合は、hogeが更新されたときのみ、関数式の再代入が起きてBコンポーネントが再レンダリングされる。

```ts
const [hoge,setHoge] = useState();
const test = useCallback(()=>{}, [hoge])
```
## useCallbackの注意点
useCallbackは依存配列が更新されない限り、初回レンダリングの状態が維持される。
以下のように依存配列にflgを設定していないとflgがfalseのままになってしまい
「flgはfalse」というアラートしか表示されなくなる

```ts
const [flg,setFlg] = useState(false);
const test = useCallback(()=>{flg === true ? alert("flgはtrue": alert("flgはfalse"))}, [])
```
以下のようにすればOK。基本的に関数式の中で利用する変数や関数を依存配列に入れておけば問題はなさそう。

```ts
const [flg,setFlg] = useState(false);
const test = useCallback(()=>{flg === true ? alert("flgはtrue": alert("flgはfalse"))}, [flg])
```
[Cinema4D]S24以降の新しい言語変更方法

# はじめに
S24以降、C4Dの言語変更の方法が変わりました。
これはその覚書きです。

# 変更方法
### Preferencesを開く
1. ヘッダにあるメニューから**Edit**を選択
1. **Preferences**をクリックするとPreferencesのポップアップウィンドウが開く
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/766eacf5-5062-b701-6ea4-3e7ff0e7d4f8.png)


### 言語をインストールする
1. **Interface**の**Language**を開くと出てくる**Install Language…**をクリック
![A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/1cbc55f9-831b-4e64-c066-eb602af729c4.png)

1. 任意の言語を選択　日本語の場合は **Japanese(ja-JP)**
![C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152366/aacf4592-ca03-11a1-41c3-ecda060d180d.png)

1. 言語がダウンロードされる

### 言語を選択して再起動する
1. **Interface**の**Language**のセレクトタブで言語選択
1. C4D再起動
1. 言語が切り替わっている


以上
EC2インスタンスの自動割当パブリックIP（Auto-assign Public IP）について

## EC2インスタンスを新規作成時に設定するパラメータ　自動割当パブリックIP（Auto-assign Public IP）について。

2021年現在、AWSマネージメントコンソール上だとEC2インスタンス起動時（作成時）に下記のように設定できる箇所となっています。
※`aws-cli`では`run-instances`コマンド`--network-interfaces`の`AssociatePublicIpAddress`で指定。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/0953f15d-e061-187f-de85-cc538563435c.png)

こちらの設定はEC2インスタンス起動時にPublicIPアドレスを自動的に割り当てるかどうかを決定するパラメータになりますが。

この設定については今現在はあとから参照したり変更したりできない項目になるようです。
（AWSマネージメントコンソール上には表示されないし、AWS-CLIでも項目はなし）

実際にEC2インスタンスを起動すれば、PublicIPアドレスの割当があるかどうかで判別はできますが。
EC2インスタンスを起動しない状態で判断する方法はなさそうです。

EIPを明示的に割当られていると、一旦外して起動してみないと多分知るすべはない？

※ただしCloudtrail の[RunInstances](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/APIReference/API_RunInstances.html)には記載があるので、こちらのログを残していればあとから判別はできそうです。

## あとから自動割当パブリックIP（Auto-assign Public IP）を変更したい場合

こちらの項目を変更したい場合は、2021年現在はEC2インスタンスの作り直しが必要となるかと思います。

実際にそんなケースがあるかどうかは別として、下記のようなケースでは困ることがあるかもしれません。

- NAT経由でインターネット接続しているプライベートサブネットを途中からパブリックサブネットに変更したいケース

この場合、EC2インスタンスが直接インターネットにでるには、パブリックIPアドレスが必要となり。
既存EC2インスタンスの自動割当パブリックIP（Auto-assign Public IP）が無効となっている場合。

- EC2インスタンス起動時にインターネット接続用にPublicIPアドレスをEIPとして割り当ててあげる
- EC2インスタンスを作り直して、自動割当パブリックIP（Auto-assign Public IP）を有効にする

必要があるかと思います。

こんなケースは少なそう（なさそう？）　に思いますが。
AWS SAM の使いかた

参考ページ
[チュートリアル: Hello World アプリケーションのデプロイ](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html)

次の環境で確認しました。

```text
$ python --version
Python 3.9.7
$ sam --version
SAM CLI, version 1.31.0
```

プログラムの作成

```bash
sam init --name sample-sam-app --runtime python3.9 --dependency-manager pip -
-app-template hello-world
```

ビルド

```bash
cd sample-sam-app
sam build
```

デプロイ

```bash
sam deploy --stack-name sample-sam-app \
	--region ap-northeast-1 \
	--guided
```

次のようなメッセージが出てきます。

```text
Value               https://123456o4of.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
```

テスト

```text
$ curl https://123456o4of.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}
```

```bash
http https://123456o4of.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
```

API Gateway が出来ていることを確認する方法

```bash
aws apigateway get-rest-apis | grep \"name\"
```
エラー：Cannot start service db: Ports are not available: listen tcp 0.0.0.0:3306: bind: address already in use

##環境
Docker version 20.10.7
docker-compose version 1.29.2

##状況

```$ docker-compose up```した際に「すでにport3306は使われている」というエラーを吐いた

```
$ docker-compose up
Creating XXXXXX_db_1    ... error
Creating XXXXXX_redis_1 ... 

Creating XXXXXX_redis_1 ... done
Creating XXXXXX_worker_1 ... done

ERROR: for db  Cannot start service db: Ports are not available: listen tcp 0.0.0.0:3306: bind: address already in use
ERROR: Encountered errors while bringing up the project.
```

##解決方法
port3306が開いてるDBを確認してkill

```
$ sudo lsof -i -P | grep "LISTEN"
mysqld     122    _mysql   24u  IPv6 0x4f20f24da9e855fb      0t0    TCP *:3306 (LISTEN)

$ sudo kill 122
```
いいねした投稿の表示


# いいねした投稿を表示させる方法

ポートフォリオにブックマーク機能を追加するにあたり、
どのユーザーがどの投稿をブックマークしたかを表示させるので悩んだので投稿したいと思います。
かなり初学者向けの内容です。

## ロジック

以前にいいねした投稿を表示させていたので、それを使い復習したいと思います。

ユーザーの詳細ページで自分がいいねした投稿を表示させる

```users_controller.rb
def show
  @user = User.find(params[:id])
  @like_posts = Post.where(id: @user.favorites.pluck(:post_id))
end
```

### まずuser_idを取得

```.rb
@user = User.find(params[:id])
```
### pluckを使う

pluckとは・・指定したカラムのレコードの配列を取得できるメソッド

ドキュメント参照
https://railsdoc.com/page/model_pluck

@userで取得したidのユーザーがいいねした投稿のPost_idをpluckで取得

```.rb
@user.favorites.pluck(:post_id)
```

### whereで検索する

pluckで取得したpost_idをPostモデルの中から検索する。
findやfind_byだと１レコードしか返ってこないので注意。

```.rb
@like_posts = Post.where(id: @user.favorites.pluck(:post_id))
```

後は格納した@like_postsを使い、each文等で表示させることができると思います。
最後までご覧いただきありがとうございました！！
throwしないでrejectしよう

## thenの中でエラーを投げるには？（onRejectedな状態にするには？）

* このような処理の時、もしかしたらthen(onFullfilledな状態)の中で例外を飛ばしたい場合があるかもしれません。

```JavaScript
const fn = () => {
  return new Promise((resolve) => {
  	setTimeout(() => {
  		console.log('setTimeout done');
      resolve();
  	}, 500);
  });
};

fn().then(() => {
  console.log('fn done');
});

// 実行結果
// setTimeout done
// fn done
```

* そういう時どうするのって話です。



## 方法としては二つ

### throw

```JavaScript
const fn = () => {
  return new Promise((resolve) => {
  	setTimeout(() => {
  		console.log('setTimeout done');
      resolve();
  	}, 500);
  });
};

fn().then(() => {
  console.log('fn done');
  throw new Error('error message');
}).catch(err => {
  console.log(err.message);
});

// setTimeout done
// fn done
// error message
```

### reject

```JavaScript
const fn = () => {
  return new Promise((resolve) => {
  	setTimeout(() => {
  		console.log('setTimeout done');
      resolve();
  	}, 500);
  });
};

fn().then(() => {
  console.log('fn done');
  return Promise.reject(new Error('error message'));
}).catch(err => {
  console.log(err);
});

// setTimeout done
// fn done
// error message
```

* thenの中で `throw `するか新たな `Promise` を返すかというだけの変更です。
* では、どちらの方がいいのでしょうか。
* ちなみに `Promise.reject` は `new Promise((reject) => { reject() });` の省略記法です。


## 結論: rejectしよう

* rejectしましょう。

### なぜか

* 理由としては、
* **それが意図して投げられた例外か本当に発生した例外かわからないから** です。
* Google開発者ツールのデバッグ機能で確認すると、
* 意図的か本当の例外か関係なく `break` してしまいます。
* つまり、**不要なところ**で `break` が発生し、
* 後続の処理が追えなくなります。
* こうなるとデバッガーの意味を成さなくなりますよね。
* **意図を明確にする**ためにも、
* **デバッグ機能をうまく使いこなす**ためにも
* `then` の中で `エラーを投げたい` 時は
* `reject`しましょう。


## 参考資料
[4.3. throwしないで、rejectしよう](https://azu.github.io/promises-book/#not-throw-use-reject)
python2のunicodeエラーについて（jinja2絡み）

最近python2の運用案件も触るようになりました。

python2環境で、jinaj2にasciiではない文字列（utf8)を渡そうとした時にエラーが起きた。

UnicodeDecodeError： 'ascii'コーデックは位置0のバイト0xe5をデコードできません
https://stackoverflow.com/questions/21393758/unicodedecodeerror-ascii-codec-cant-decode-byte-0xe5-in-position-0-ordinal

対策として、なんだか怪しい方法がコメントで推奨されているが、なぜそれがどうして怪しくて危険なのか雰囲気でしか理解できていない。（システム全体のエンコーディングの設定を変更した場合、影響範囲がかなり大きい...？

```
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
```

上記の対策について、下記のコメントがあった

```
@raxacoricofallapatorius：sys.setdefaultencoding（ 'utf-8'）の危険性を参照してください 
– 
idbrii
 2015年12月19日15:45
 ```

sys.setdefaultencoding（ 'utf-8'）の危険性
https://stackoverflow.com/questions/28657010/dangers-of-sys-setdefaultencodingutf-8

上記のエントリの中で納得した説明があったので以下、自動翻訳した内容で抜粋

```
ソースコードもUTF-8にエンコードされていると想定しています。または、すべてのバイト文字列がUTF-8でエンコードされていること。UnicodeからUTF-8への暗黙的なエンコーディング、次にそのデータを任意のエンコーディングを使用して他のバイト文字列と連結することは大きなバグであり、デフォルトのエンコーディングを設定してマスクしました。 

もう1つの問題は、コードがタイプの違いを通知するためにエンコードまたはデコードエラーに依存する可能性があることです。これにはサードパーティのライブラリが含まれます。ASCII以外のデフォルトのエンコーディングを設定すると、UTF-8バイト-> UnicodeおよびUnicode->バイトの暗黙的なエンコーディングを実際に明示的なエンコーディングを使用することを意図して検出できなくなります。 

いずれにせよ、エンコーディングを正しく処理するよりもデフォルトのエンコーディングを設定する方が良いというユースケースはまだありません。グローバルを使用するのと同じですが、実際にはバグの可能性が大幅に高まるため、グローバルは使用しません。 

したがって、テストによってコードが非ASCIIデータで正しく機能することが確認された場合は、追加の手順を実行してエンコードとデコードを正しく処理し、型を任意に混在させないでください。なぜsetdefaultencoding()松葉杖に頼るのですか？ 

全体として、私はあなたがこの答えでどこに向かっているのか実際にはわかりません。はい、Unicodeの比較には問題がありますが、実際には、なぜsys.setdefaultencoding()避けるべきかについて明確なことは何も言っていません。
```

```
したがって、デフォルトのエンコーディングを変更すると、あらゆる種類の互換性のない問題が発生します。例えば：

# coding: utf-8
import sys

print "你好" == u"你好"
# False

reload(sys)
sys.setdefaultencoding("utf-8")

print "你好" == u"你好"
# True
その他の例：

https://pythonhosted.org/kitchen/unicode-frustrations.html
とは言うものの、可能な限りユニコードを使用し、I / Oを処理するときはビット文字列のみを使用することを提案しているブログがあることを覚えています。この慣習に従えば、人生はずっと楽になると思います。より多くの解決策を見つけることができます：

https://pythonhosted.org/kitchen/unicode-frustrations.html#a-few-solutions
```

骨折に対してスティックをストラップで巻き付けてそのまま歩くようなものだと揶揄されていた表現が良かった
擦り傷の治療に包帯とギプスを装着して全身麻酔して抗生物質を投与するようなものかと認識した


本題のjinja2の対策としては、下記の記事を参考にして解決した。
https://stackoverflow.com/questions/22181944/using-utf-8-characters-in-a-jinja2-template

```py
test = 'テストだよ'.decode('utf-8')
context = {'test': test}
return TemplateResponse(request, template_name, current_app=current_app, context=context)
```

```jinja
<div class="panel panel-default">
  <div class="panel-body">
  {{ _(test) }}
  </div>
</div>
```

上記の形が良いと思いますが、他に良い方法を知っている方は記事自体編集してもらって大丈夫です。

最初はこんな~~クソ~~コードを書きそうになったけどこれですっきりした。

```jinja
<div class="panel panel-default">
  <div class="panel-body">
  {% if res == 'not_member' %}
    {{ _('未登録のメールアドレスです。管理者に連絡してください。') }}
  {% endif %}
  {% if res == 'error' %}
    {{ _('パスワードをリセットするためのリンクを送信しましたがメールの送信に失敗しました。') }}
  {% endif %}
  </div>
</div>
```
ただこれはこれでviewを見なくてもテンプレートを見ればどういうメッセージが表示されるので処理を追わなくてもテンプレートにどういう表示がされるのか把握はしやすいと思う（賛否両論あると思います。

UIの構造は変わらないけど表示するメッセージのパターンが多いケースのベストプラクティスが知りたいです。
「array.findの返り値がundefindeになって怒られる」現象を回避する方法

## 原因
以下の様な処理で怒られる

```ts
// profile変数の型定義
  type Profile = {
    id: number;
    name: string;
    age: string;
  };

// 変数profilesの初期化
  const profiles: Profile[] = [
    {
      id: 1,
      name: "yamada",
      age: "24",
    },
  ];

// profiles配列からidが1のprofileを取得してtargetProfileへ代入
  const targetProfile = profiles.find((profile) => profile.id === 1);

// 適当にnullとProfile型を受け入れるselectProfile変数を初期化
  let selectProfile: Profile | null = null;

// ここで怒られる!!
  selectProfile = targetProfile;
```
find関数は１つも一致しない場合は**undefinde**が返ってくるため、型推論によって「もしかしたらundefindeかもしれない」となるのが原因。。。

## 解決策
簡単に解決できる。
**Null合体演算子を使うだけ**で他の書き換えは不要。（**??** <=コレ。クエスチョンマークが2つ並んだやつ）

```ts
  // profile変数の型定義
  type Profile = {
    id: number;
    name: string;
    age: string;
  };

  // 変数profilesの初期化
  const profiles: Profile[] = [
    {
      id: 1,
      name: "yamada",
      age: "24",
    },
  ];

  // profiles配列からidが1のprofileを取得してtargetProfileへ代入
  const targetProfile = profiles.find((profile) => profile.id === 1);

  // 適当にnullとProfile型を受け入れるselectProfile変数を初期化
  let selectProfile: Profile | null = null;

  // 怒られなくなった★
  selectProfile = targetProfile ?? null;
```
## Null合体演算子
**左辺がnullまたはundefindeのとき右辺を返し、左辺がnullまたはundefindeでなければ左辺を返す。**
以前はif文で回避していたのでインラインで書けるNull合体演算子は革命でした。。。

## おまけ回避術
怒られる変数の末尾に「!」を付けると回避できる。
TypeScriptを無視することになるので、100%undefindeが入らないときのみ利用したほうが良さそう。

```ts
selectProfile = targetProfile!;
```
Material-UI 5 で Button のリップルエフェクトと AppBar の影を消す

## 背景

Material-UI 5 になって Theme の書き方が変わりました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31477/2b9e8668-fb2a-b94c-17bd-bc5333dbe6cb.png)

## 修正後

```ts
import { createTheme } from "@mui/material"

export const theme = createTheme({
  components: {
    MuiButtonBase: {
      defaultProps: {
        disableRipple: true
      },
    },
    MuiAppBar: {
      defaultProps: {
        elevation: 0
      },
    },
  },
})
```

- props から components 内の defaultProps に変わりました
- elevation を 0 にすると影を消せます

参考: https://mui.com/getting-started/faq/#heading-how-can-i-disable-the-ripple-effect-globally

## おまけ

### AppBar の下に罫線をつける

罫線にはパレットの divider の色を使いたいので、一度 palette だけで createTheme に渡してテーマを生成し、そのテーマを参照する形で再び createTheme でテーマを作成します。

![スクリーンショット 2021-09-24 12.00.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31477/1de612ae-0035-3d3e-6f34-cadd3a094119.png)

```ts
import { createTheme } from "@mui/material"

const baseTheme = createTheme({
  palette: {
    primary: {
      main: "#4f54f9",
    },
    secondary: {
      main: "#f50016",
    },
    background: {
      default: "#ffffff",
    },
  },
})

export const theme = createTheme(baseTheme, {
  components: {
    MuiButtonBase: {
      defaultProps: {
        disableRipple: true,
      },
    },
    MuiAppBar: {
      defaultProps: {
        color: "transparent",
        elevation: 0,
      },
      styleOverrides: {
        root: {
          borderBottom: `1px solid ${baseTheme.palette.divider}`,
        },
      },
    },
  },
})
```
googlespreadsheetのシートを並べなおすGASを書いた

google spreadsheetは実に至らないアプリでいろいろ腹が立つことがあるのだけど、中でも**仕様書として使わざるを得なくなった時、どうしてもシートが増えていく**のだけど、**シートの並べ替え**が苦痛でしょうがなかった。
で、あまりに腹が立ったので仕様書用のGASで目次を作ると同時にシートを目次の順に従って並べ直すスクリプトを書いたのだけど、それを単純化して切り出したのがこのGAS。
前に公開した目次と組み合わせるのはコード屋なら簡単だと思うのでバラしたままにしておく。
機能的には実行すると
![gas_sample1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96586/cd1bef03-c3bd-088c-0a0a-eccdfc2f7884.jpeg)
が
![gas_sample3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96586/d0f60837-a330-ea6f-13e1-21e1972207cc.jpeg)
のように並べ直される。
以下、コード。

```javascript:sortsheet.gs
function myFunction() {
  const ss = SpreadsheetApp.getActiveSpreadsheet(); // ともかくspreadsheetを取得する。
  const contSheet = ss.getActiveSheet();
  const sheets = ss.getSheets();

  let narray=[];
  sheets.forEach(item=>{
    narray.push(item.getSheetName());
  });

  console.log(narray);
  narray.sort();   // sortはお好みで。
  console.log(narray);

  let i=1;
  narray.forEach(item=>{
    ss.getSheetByName(item).activate();  // アクティブにしないと動かせない。
    ss.moveActiveSheet(i);
    i++;
  });
  contSheet.activate(); // 最後にactiveだったシートに戻る。
}

```

なお、ちょっとだけ書いておくと**moveActiveSheet**を実行するためにはシートをアクティブにしなければならない制約があるので、ボタンなどでシート側から起動すると、バタバタシートが切り替わって、実にキモい挙動をするので注意。

前の目次生成用と組み合わせると結構幸せになれるかも知れない。
CCNA　EIGRP

では、今回はEIGRPについて記述していきます。
EIGRP(Enhanced Interior Gateway Routing Protocol)は
ディスタンスベクタ型とリンクステート型を取り入れている拡張ディスタンスベクタ型です。
Cisco独自のプロトコルで、他社のルータでは使用できません。
クラスレスルーティングプロトコルなので、自動集約が可能になっています。
メトリックが等しくない経路でも負荷分散が可能になっています。
これを不等コストバランシングと言います。

ネイバー関係を作るときはOSPFと同じですが、
ルート情報を交換し合う時はUpdateパケットを送ります。
この情報を利用してトポロジテーブルが作成されます。
また、定期更新はせずにトポロジ変更時に変更点のみマルチキャストでアップデートします。
これを差分アップデートと言います。
トポロジテーブルに保存されたルート情報はDUALアルゴリズムによって
最適ルートのみがルーティングテーブルに登録されます。

では、どのように最適なルートを決定するかと言うと
複合メトリックを使って決めます。
これは帯域幅、遅延、信頼性、負荷、MTUを指します。
最適ルートのネクストホップをサクセサと言いますが、これは
トポロジテーブルで最小のFD(Feasible Distance:自身からネットワークまでの
メトリック値)を持つものが選ばれます。
このサクセサがダメになった時のためにバックアップルートが
決定されます。このルータをフィージブルサクセサと言って、
FD>RDとなるネイバーが選ばれます。
RD（Reported Distance)とはネイバールータから宛先ネットワークまでの
メトリック値を表します。これはAD(Advertised Distance)とも言います。
GitHubにPushできない！？GitHubアクセストークン作成を画像で分かりやすく解説

##はじめに
GitHubでは2021年8月13日にパスワード認証が廃止されました。
https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/
よって今回はパスワードではなくアクセストークン認証によってGitHubへプッシュする方法を記載します。

##HTTPS通信でGitHubにプッシュしようとしたらこんなエラーが、、。
![スクリーンショット 2021-09-24 10.57.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/b541d859-3b29-0cc2-2503-cb9fd1c37e6d.png)

```bash:エラー内容
Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
```
上記で記載した通りアクセストークンを作成し、パスワードの代わりにアクセストークン認証を使用しpushする必要があるみたい。

#個人アクセストークン

参考ドキュメント
https://docs.github.com/ja/github/authenticating-to-github/creating-a-personal-access-token

##アクセストークン作成手順
GitHubにログインした状態で、以下を実施します。

・設定画面( https://github.com/settings/tokens )を開く
・[Generate new token]をクリック
・noteに任意の名前を記入
・権限を設定
・[Generate token] をクリック
・トークンをコピー　(ページを離れると参照不可になる)
・パスワードの代わりに使用する

注意：、権限設定で[repo] を選択します。
→これやらないとターミナルからpushする際、アクセスできないエラー403が吐かれる。


##アクセストークン作成画面
###設定画面トップ
![スクリーンショット 2021-09-24 11.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/51a1b72c-aaaa-4939-757c-70be2cb898bf.png)
https://github.com/settings/tokens へ接続、右上の[Generate token] をクリック。
###作成画面
![スクリーンショット 2021-09-24 11.26.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/c80ba901-60de-c503-5961-7391d6010e6f.png)
Noteに任意の名前(実際にコマンドに入力しないので分かりやすい名前を設定)
Expirationはトークンの有効期間なのでなるべく残したければ有効期限を長期に設定(最大1年間)
<font color="red">Select Scopes(権限付与)において「repo」にチェックを入れないとターミナルからpushする際アクセス権限エラー403が発生するのでチェックを忘れずに。</font>

![スクリーンショット 2021-09-24 11.33.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/faf39004-4c8b-2c6b-3003-d0be745024ee.png)
下までスクロールし「Generate token」をクリック
###アクセストークン発行画面
![スクリーンショット 2021-09-24 11.35.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/6915be5d-1c96-23e1-d7fa-0134de750870.png)
作成後個人アクセストークンが発行されるので必ずコピーしてメモに残しておく。

##実際にPushしてみる
```bash:使用例
$ git push -u origin main
Username for 'https://github.com': GitHubユーザー名
Password for 'https://'GitHubユーザー名'@github.com': ここでメモしておいた個人アクセストークンを入力
```

```bash:ターミナル
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 13.43 KiB | 3.36 MiB/s, done.
Total 9 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/GitHubユーザー名/リポジトリ名.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.
```

プッシュできました:fist:！！
Slack 비디오 및 오디오 클립 기능

![slack_video_audio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/7038a406-af81-4146-7dad-05728bd50c80.png)

## TL;DR
> Slack 비디오 및 오디오 클립 기능이 추가되었는데요.
> 비디오 또는 오디오를 선택하여 녹화/녹음 한 후 메시지 클립으로 전달할 수 있습니다.
> 모바일도 (AOS/iOS) 지원합니다.
> ※ 아쉽지만 현재는 Slack **유료버전**에서만 지원됩니다.

## 비디오 클립 기본 동작
최대 녹화시간은 3분 입니다.

1) 비디오 아이콘 선택
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/5aca4a6b-5c16-bdec-4252-625f10d2691e.png)
2) 카메라 On/Off 선택 + 공유화면 선택(옵션)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/2f8cc123-fe67-3241-cdbd-3e7a53c4aa35.png)
3) 녹화 진행
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/b414b724-d721-e3b0-dbad-b42f81826625.png)
4) Stop or 3분 만료 시 녹화본 확인
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/fe78236c-a2de-4ef9-1330-6822b2fcc3a7.png)
5) 다운로드 (`.webm` 으로 저장) or Next
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/6471d5ba-fdb3-4da1-2950-cc351fc7d917.png)
6) 메시지로 공유
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/60f5b29e-52a6-65ee-3702-556d19ee305c.png)
참고) View transcript 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/1acc2d8a-be08-a785-b278-611e4fa66e77.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/17f45c66-dad6-cf5b-0104-404c496284ca.png)

## 오디오 클립 기본 동작
1) 마이크 아이콘 선택
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/3f5c6dac-20bc-131e-8479-6b0e40abd4ad.png)
2) (바로) 녹음 시작
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/714fb85a-de99-f130-5b44-ccddd4231511.png)
3) 녹음 종료
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/abb7e36b-6126-ad3c-8037-9a125c614aca.png)
4) 메시지로 공유
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/402bfa10-7d61-ffab-6fbd-7e1961627b18.png)
참고) View transcript
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/ea23aae5-0c19-ac17-ced4-e8de0f8a6fd0.png)

## 참고
- https://slack.com/help/articles/4406235165587-Record-audio-and-video-clips-in-Slack
【合格体験記】E資格合格までの道のりとやったこと

#はじめに
JDLEのE資格試験2021#2を受験し見事一発合格したので、合格までに何をしたかについてや受験までの道のりについてなどを記事にまとめようと思います！一人でも参考になる方がいらっしゃれば幸いです。

#誰向けの記事？？
この記事の想定として以下を想定しています。

1. E資格を受験しようと悩んでいる方や今現在認定資格を受験している方
2. JDLEのG検定を取得済みの方
3. データサイエンティストを目指そうとしている学生や別領域からの転職をしたいと思っている方 
4. 最近はやりのディープラーニングを1から知りたい方

上記のように想定対象者を示しましたが、要約するとズバリ「**AIやディープラーニングを知りたい・やってみたい方**」向けといった感じです！！！
私自身も今年新卒でデータサイエンティストの道に入って約半年といった新米データサイエンティストで、ディープラーニングの基礎を学ぶきっかけになればと思い受験しようと思いました！
G検定を取得してからのほうがスンナリとイメージが掴めるかもですが、一気にE資格でもどちらでもいいと思います！すべてはやる気次第かと。

#そもそもE資格とは？？

[公式HP](https://www.jdla.org/certificate/engineer/)
E資格とは、ディープラーニングの様々な分野の理論や手法を問いてくる試験を解くので、それぞれの分野における代表的な手法の名前や理論はマスターできると思います。ビジネス活用において考えると、「どのような場面の時につかうか」がわかるため戦略練る時の幅が広がったり、きっかけ作りになるかなと思います！

[E資格出題範囲]
**E資格は過去問の公開はなく、設問内容は他言禁止のため、設問内容の具体的な内容に関しては避けています。予めご了承ください。**

(https://www.jdla.org/certificate/engineer/#engineer_No03)
E資格の出題範囲あディープラーニングの進歩や利活用の傾向の移り変わりが早いことから、1~2年程度でシラバスが変更し出題範囲も変更するという特徴があります。
現時点で2022#1までは現行の出題範囲ですが、2022#2～新シラバスでの出題になると発表がされています。ディープラーニングの世界らしいなと思います！

ざっくりと変わらないこととして大きく分けて4分野があり
- 応用数学
統計学や情報理論
- 機械学習
予測やクラスタリングなどの手法について
- 深層学習
画像・音声・自然言語・生成・強化学習の代表的な手法などの特徴について
- 開発・運用環境
ディープラーニングを扱うときのより良く使うための開発や運用環境について
の4分野があります。

見てわかる通り単にディープラーニングの分野だけでなくディープラーニングで使われる数学(統計)の知識や機械学習も含まれているので、幅広い知識を習得することが必要であるため、駆け出しエンジニアにとって**覚えながらスキルアップができる**ためとても良い機会だと感じます！

とはいっても、ディープラーニングの資格のため、深層学習の分野が「一番出題が多いな～」と当日実際の試験問題を解いていて感じました。

#受験するためには・・
受験するためにはJDLAが認定している「認定プログラム」を受験・修了し修了証をgetしないと受験することができません。「認定プログラム」にも別途お金がかかるため、手が伸び辛い資格なのかもしれません。。ただ今ならまだ転職につかえるのかなと思っています。人があまり手を出していないということなので！
(大学生の時にE資格取得した友達が外資の大手ITコンサルに就職していました。スゴイ。。)

#合格率
今回の合格率は75%前後とのことでした。
前回の合格率は2021#1は78.44%で比較的高いということが見てわかると思います。
高い理由として、「認定プログラム」があるためベースができているからと予想しています。難易度としては実際にディープラーニングを扱っているなら「認定プログラム」がなくても大丈夫だと思います。普段全く扱っていないなら時間かかるかもですね。

#勉強までの道のり
まず「認定プログラム」の講座を受講し始めたのが、2021/3で受験日の5か月前くらいでした。
「認定プログラム」の講座はAVILENさんでした。[AVILEN](https://avilen.co.jp/)

最初はビデオ講座での受講とnumpyを使用したコーディング演習や自由に何かAIを実装しプロジェクトを作成するというプロダクト課題などコンテンツはとても充実していました。
このコード類や資料はE資格に合格した今でも見返して使えると感じているほど充実していました！！

合格に必要な修了試験に合格して、修了証をいただいたのが2か月前で、受験日まではコンテンツの中に含まれている問題集を解いたり、コーディング演習で作ったコードを見返したりなど進めていました。
(E資格受験者が2~3周するという[黒本](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0E%E8%B3%87%E6%A0%BC%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E5%95%8F%E9%A1%8C%E9%9B%86-%E3%82%B9%E3%82%AD%E3%83%AB%E3%82%A2%E3%83%83%E3%83%97AI%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE-%E5%B0%8F%E7%B8%A3-%E4%BF%A1%E4%B9%9F/dp/4295009180)は私は使いませんでした。それよりも[ゼロから作るDeep Learning
――Pythonで学ぶディープラーニングの理論と実装](https://www.oreilly.co.jp/books/9784873117584/)を使って今した！←私に取ったらバイブルです！)

#試験を受けた感想
試験は合格したのは、とてもうれしかったのですが各分野別の得点率が思っていたよりも得点が伸びていなかったのが悔しいなと感想を持ちました。
手法の名前をたくさん覚えたので、今後の経験やコンペなどに参加して名前や特徴だけでなく「どうやって使うか」を知ることが大事だなと今思っています。
「合格したから終わり」ではなく「合格したのを通過点にしてどうするか？」を考えてこれから頑張りたいなと思います。


#さいごに
長文になりましたが最後まで読んでいただきありがとうございました！E資格を受けてお金は高くつきましたが良かったなと思います！乾燥に書きましたが「通過点」で頑張ろうと思います。

LGTMやフォローをよろしくお願いいたします。時間に余裕ができたのでこれから発信を頑張っていきます！！
【2021年9月版】Apple製品のLiDAR搭載状況

皆さん3次元スキャンしたいですよね！！

LiDARが搭載されている、という理由だけで、にわかにApple製品に注目しつつある私です。
~~スマホが水没したから探し始めたのは秘密~~

<details><summary>LiDARの搭載状況(発売日順)</summary>2021年版は 今日(2021/09/24)が発売日なので不完全ですが、分かり次第追記します。</details>


|名称||発売年月|
|---|---|---|---|
|iPad Pro (11/12.9)| 2020|2020年3月|
|iPhone 12| Pro / Pro Max|2020年11月|
|iPhone 13| Pro / Pro Max|2021年9月|
|iPad Pro (11/12.9)| 2021|2021年9月|

※ なお、
前面カメラはTrueDepthカメラであり、方式が異なる！
（Structured Light方式。後述）


# LiDARとTrueDepthの違い

### LiDARカメラ(dToF: direct Time of Flight)
数百個のレーザー光線を投射して、個々の反射時間を計測

### TrueDepthカメラ(Structured Light方式)
数万個ものドット・パターンを投影して、その歪みから形状を推定


#### まとめ
LiDARは離隔的かつ動的、TrueDepthは近接的かつ静的。

|種別| 方式 | 遠 | 近 | 動 | 静 |
|---|---|---|---|---|---|
|LiDAR| dToF | ○ | ○ | ○ | ○ |
|TrueDepth| Structured Light | × | ○ | × | ○ |



#### 参考記事
http://criticalcycling.com/2020/08/ipad-pro-lidar-scan/


####以上です！
MySQLでパスワードなしでログイン

テストしたいだけなのに、MySQLでパスワードを求められたりして大変だったので、パスワードなしでログインできるようにするためのメモ。

環境
Amazon Web Service Lightsail
AmazonLinux2


インストールされていることを確認。
```
mysql --version
```

Macなどで、MySQLをインストールした場合は、よく`mysql.server start`コマンドで起動するようですが、私の環境ではmysqldをインストールしたので、systemdで起動します。

```bash
$ sudo systemctl start mysqld.service
```

起動確認

```bash
$ sudo systemctl status mysqld.service

● mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2021-09-23 07:54:39 UTC; 18h ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 6219 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS (code=e
xited, status=0/SUCCESS)
  Process: 6169 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
 Main PID: 6223 (mysqld)
   CGroup: /system.slice/mysqld.service
           └─6223 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid

Sep 23 07:54:33 ip-172-26-12-127.ap-northeast-1.compute.internal systemd[1]: Starting MySQL Server...
Sep 23 07:54:39 ip-172-26-12-127.ap-northeast-1.compute.internal systemd[1]: Started MySQL Server.
```

activeになっていることが確認ができたので、初期パスワードを確認していきます。

```bash
$ sudo vi /var/log/mysqld.log
```

viのコマンドモードでログファイルが開かれるので、
`/password`と入力して
パスワードを検索します。

```
[Note] A temporary password is generated for root@localhost: jiY9><-Y)/w:
```

初期設定のパスワードが`jiY9><-Y)/w:`だと分かったので、コピーしておいてMySQLの初期設定を行います。

```
$ sudo mysql_secure_installation
```

新しいパスワードを入力していきます。

```
Enter password for user root: jiY9><-Y)/w:
New password: Pa66wo+d
Re-enter new password: Pa66wo+d
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) :y
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
Reload privilege tables now? (Press y|Y for Yes, any other key for No) :y
```

rootをパスワードなしでログインできるようにする

```
$ sudo vi /etc/my.cnf
```

最終行あたりに`skip-grant-tables`を追加して、パスワードなしでログインできるようにします。

```
[mysqld]
.
.
skip-grant-tables
.
.
```

MySQLを再起動

```
$ sudo systemctl restart mysqld.service
```

パスワードなしでログインできることを確認

```
$ mysql -u root

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.35 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> quit
```



#### 参考
https://weblabo.oscasierra.net/mysql-57-init-setup/
https://qiita.com/ksugawara61/items/d8d69b7d57a3afcef980
Terraform Cloud の Variables 設定 (認証情報)

## [AWS](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#environment-variables)

- `AWS_ACCESS_KEY_ID`
- `AWS_SECRET_ACCESS_KEY`

![AWS](https://github.com/s-myk/terraform-cloud-variables/raw/main/images/TerraformCloud_AwsVariables.png)

## [Azure](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret#configuring-the-service-principal-in-terraform)

👉 [Azure Provider: Authenticating using a Service Principal with a Client Secret](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret)

```console
az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/SUBSCRIPTION_ID"
```

- `ARM_TENANT_ID`
- `ARM_SUBSCRIPTION_ID`
- `ARM_CLIENT_ID`
- `ARM_CLIENT_SECRET`

![Azure](https://github.com/s-myk/terraform-cloud-variables/raw/main/images/TerraformCloud_AzureVariables.png)

# [GCP](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#full-reference)

- `GOOGLE_CREDENTIALS`

![GCP](https://github.com/s-myk/terraform-cloud-variables/raw/main/images/TerraformCloud_GcloudVariables.png)

# [OCI (Oracle Cloud Infrastructure)](https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformproviderconfiguration.htm#environmentVariables__settingenvironmentvariablesinlinux)

- `tenancy_ocid`
- `user_ocid`
- `fingerprint`
- `private_key`

![OCI](https://github.com/s-myk/terraform-cloud-variables/raw/main/images/TerraformCloud_OCIVariables.png)
React.js + Laravel SPA開発チュートリアル（動画版）

React.jsとLaravelを使用してSPAなToDoアプリを開発する講座を動画（Youtube）で作成しました。
よろしかったらぜひ！

# 第1回 アプリケーションのデモ
この講座で開発するアプリケーションの動作デモです。

[![第1回 アプリケーションのデモ](http://img.youtube.com/vi/hPjcbKtpTjY/0.jpg)](https://youtu.be/hPjcbKtpTjY)

# 第2回 Laravel8のインストールと初期設定
バックエンドから作るので最初はLaravelのインストールです。

[![第2回 Laravel8のインストールと初期設定](http://img.youtube.com/vi/qoFYXNb0TEw/0.jpg)](https://youtu.be/qoFYXNb0TEw)

# 第3回 データベースの設計と構築
Migrationでデータベースの作成と、Factory/Seederという機能を使用してダミーデータの登録を行います。

[![第3回 データベースの設計と構築](http://img.youtube.com/vi/5wPkqdNgGt4/0.jpg)](https://youtu.be/5wPkqdNgGt4)

# 第4回 ToDoリスト一覧APIの作成
Laravelのコントローラーとルーターの設定してToDoリスト一覧APIの表示するところまで。

[![第4回 ToDoリスト一覧APIの作成](http://img.youtube.com/vi/edKdwqQk7xA/0.jpg)](https://youtu.be/edKdwqQk7xA)

# 第5回 ユニットテスト（UnitTest）の設定と実行
Laravelのユニットテスト（UnitTest）の設定と実行方法について解説をしてます。
ターミナルからの実行とPhpStormというIDEからでも実行できるように設定します。

[![第5回 ユニットテスト（UnitTest）の設定と実行](http://img.youtube.com/vi/Un3MAWph64M/0.jpg)](https://youtu.be/Un3MAWph64M)

# 第6回 LaravelでCRUD APIの作成
CRUD（登録・編集・削除）機能のAPIを実装して、ユニットテストでテストまで行っています。

[![第6回 LaravelでCRUD APIの作成](http://img.youtube.com/vi/5EhiulTUn74/0.jpg)](https://youtu.be/5EhiulTUn74)

# 第7回 バリデーションで入力データ制限する
ユーザーの入力を制限するバリデーションの設定を行います。

[![第7回 バリデーションで入力データ制限する](http://img.youtube.com/vi/Wx0WHlGtcWE/0.jpg)](https://youtu.be/Wx0WHlGtcWE)

# 第8回 LaravelにReact.jsとTypeScriptをインストール
この回からフロントの開発です。
最初は、LaravelにTypeScript+React.jsの開発環境を構築します。

[![第8回 LaravelにReact.jsとTypeScriptをインストール](http://img.youtube.com/vi/GzbyHZTLSIU/0.jpg)](https://youtu.be/GzbyHZTLSIU)

# 第9回 ReactRouterでページを分ける
ReactRouterというライブラリを使用して、ページの切り分けを行います。

[![第9回 ReactRouterでページを分ける](http://img.youtube.com/vi/f_U43f3QERM/0.jpg)](https://youtu.be/f_U43f3QERM)

# 第10回 AxiosとReactQueryでAPIからデータを取得する
AxiosとReactQueryというライブラリを使って、Laravelで作成したAPIからデータの取得と表示を行います。

[![第10回 AxiosとReactQueryでAPIからデータを取得する](http://img.youtube.com/vi/bqctWoscPgE/0.jpg)](https://youtu.be/bqctWoscPgE)

# 第11回 コンポーネントとロジックの分割
今後拡張しやすいようにコンポーネントの分割やAPIの取得ロジックの切り分けを行います。

[![第11回 コンポーネントとロジックの分割](http://img.youtube.com/vi/jwDiLu19dxU/0.jpg)](https://youtu.be/jwDiLu19dxU)

# 第12回 ToDoのチェック機能の実装
ToDoのチェック機能を作ってます。

[![第12回 ToDoのチェック機能の実装](http://img.youtube.com/vi/WmnGzgOB3VM/0.jpg)](https://youtu.be/WmnGzgOB3VM)

# 第13回 ToDoの登録機能の実装
ToDoの登録機能を作ってます。

[![第13回 ToDoの登録機能の実装](http://img.youtube.com/vi/2u3sfR0U4JA/0.jpg)](https://youtu.be/2u3sfR0U4JA)

# 第14回 ToDoの編集・削除機能の実装
ToDoの編集・削除機能を作ってます。

[![第14回 ToDoの編集・削除機能の実装](http://img.youtube.com/vi/pklEEDlSt4I/0.jpg)](https://youtu.be/pklEEDlSt4I)

# 第15回 Laravel Sanctumでユーザー認証機能を作る
Laravel Sanctumというライブラリを使用してAPIの認証機能を作ります。

[![第15回 Laravel Sanctumでユーザー認証機能を作る](http://img.youtube.com/vi/YCQqERndPQI/0.jpg)](https://youtu.be/YCQqERndPQI)

# 第16回 ログイン機能の作成
Laravelで作った認証APIを使用してReactでログインできるように作っていきます。

[![第16回 ログイン機能の作成](http://img.youtube.com/vi/2Q9BJZflbHI/0.jpg)](https://youtu.be/2Q9BJZflbHI)

# 第17回 ユーザー毎のToDoの取得とポリシーの設定
ユーザー毎のToDoの取得と他のユーザーのタスクを編集できないようにするポリシー（認可）の実装します。

[![第17回 ユーザー毎のToDoの取得とポリシーの設定](http://img.youtube.com/vi/2Q9BJZflbHI/0.jpg)](https://youtu.be/2Q9BJZflbHI)
awk コマンドで特定の箇所の値を取り出す（行と列で指定）


(ファイル名)
test.txt

(ファイルの中身)

```
G:              A:              F:              A:              M: 
google          amazon          facebook        apple           microsoft
```

(やりたいこと)
"apple"の値だけ取り出したい。

(コマンド)

```
awk 'NR==2 {print $4}' test.txt
```


(結果)
apple

(補足)
NRで行指定
$で列指定
[メモ]Windowsで.onionサイトをホストする。

## ステップ1

1.Tor ブラウザをダウンロードし、起動する。
2.PHP をインストールする。

## ステップ2

1.PHP でウェブサイトをホストする。
`D:\Website\index.php` と `D:\Website\run.bat` を作成する。
`D:\Website\index.php` に以下のテキストを追加する。

```php
<?php echo "Hello, World!"; ?>
```

`D:\Website\run.bat` に以下のテキストを追加する。

```batch
php -S 127.0.0.1:80
```

## ステップ3
1.ファイル(拡張子なし) `.\Tor Browser\Browser\TorBrowser\Data\Tor\torrc` に以下のテキストを追加する。

```
HiddenServiceDir D:\privatekey
HiddenServicePort 80 127.0.0.1:80
```

(HiddenServiceDir はサイトが存在する場所ではなく、秘密鍵が保存される場所を設定する)

## ステップ4

1.Tor ブラウザを再起動する。
(`D:\privatekey\hostname` は自動的に生成して、.onionドメインはそこにある)

## ステップ5

1.`D:\Website\run.bat` を実行する。
2.Tor ブラウザで `D:\Website\hostname` にある.onionドメインにアクセスする。

<!--https://www.youtube.com/watch?v=jbAUq4fVxHo-->
【SQL】複数テーブルの結合 -集計テーブルを作成し結合-

#概要
自社の従業員が各顧客のためにどのくらいの時間を費やしたかを表示するためのクエリを例示します。
実際には顧客情報の集計を行ったわけではなく、テーブル構造もより複雑でしたが、
備忘録も含め簡単な例で残しておきます。

#テーブル構造
**顧客情報(顧客番号、顧客名)**
テーブル名：customer

|c_id|c_name|
|:---|:---|
|100|(株)みかん商事|
|101|(株)りんご電気|
|102|バナナ銀行(株)|

**顧客訪問情報(訪問番号(シーケンス)、顧客訪問日時、顧客番号)**
テーブル名：visit

v_no|v_date|c_id|
|:---|:---|:---|
|1|2021-09-01|100|
|2|2021-09-01|101|
|3|2021-09-02|102|
|4|2021-09-10|103|

**顧客対応情報(訪問番号、対応者、対応時間(分))**
テーブル名：service

v_no|s_name|s_min|
|:---|:---|---:|
|1|鈴木|50|
|1|佐藤|10|
|1|田中|100|
|2|松本|20|
|2|松尾|30|
|3|斉藤|200|
|4|橋本|70|
|4|青木|70|

上記の場合、例えば2021-09-01は鈴木さんが50分、佐藤さんが10分、田中さんが100分、
(株)みかん商事のために対応したという形です。
これを各顧客にそれぞれどのくらい時間を費やしているかを表示するクエリの発行を例示します。

#クエリ
```sql:psql.exe
SELECT 
    A.c_id AS id, 
    A.c_name AS name, 
    B.time AS time
FROM 
    customer A 

    LEFT JOIN ( 
--      顧客訪問情報と顧客対応情報を基に、各顧客にどのぐらいの時間を費やしているか集計テーブルを作成
        SELECT 
            BB.c_id AS c_id, 
            sum(CC.s_min) AS time 
        FROM 
            visit BB, 
            service CC 
        WHERE 
            BB.v_no = CC.v_no 
--          この部分は、日付範囲を指定して検索したい場合にコメントアウトしてください
--          AND '2021-09-01' <= BB.v_date 
--          AND BB.v_date <='2021-09-30' 
        GROUP BY 1 
        ORDER BY 2 desc 
    ) 
    B ON A.c_id = B.c_id 

GROUP BY 
    1, 2, 3 
ORDER BY 
    3 desc;
```
イメージとしては、実績の集計テーブルを作成し、これを顧客マスタと結合させるような形です。

#クエリ実行結果
id|name|time|
|:---|:---|---:|
|100|(株)みかん商事|300|
|101|(株)りんご電気|200|
|102|バナナ銀行(株)|50|
Unity DoTweenによるFade


### #0000 <-> #000f
```C#
    public async Task FadeIn()
    {
        //using DG.Tweening;
        //#0000 -> #000f
        bool flg = true;
        DOTween
         .ToAlpha(() => panel.color = new Color(0, 0, 0, 0), c => panel.color = c, 1f, 0.3f)
         .OnComplete(() => flg = false)
         ;
        while (flg) await Task.Delay(5);
    }
    public async Task FadeOut()
    {
        //using DG.Tweening;
        //#000f -> #0000
        bool flg = true;
        DOTween
         .ToAlpha(() => panel.color = new Color(0, 0, 0, 1f), c => panel.color = c, 0f, 0.3f)
         .OnComplete(() => flg = false)
         ;
        while (flg) await Task.Delay(5);
    }

```
Microsoft Teamsで現在ゲストユーザーがいるチームをPowerShellを使ってCSVに出力する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357828/864f2bf5-1f0b-03d0-50fc-15c0319e8dcb.png)
Microsoft Teamsで組織外のユーザーをテナントに招待して一緒に仕事をする際に、どうやって定期的にゲストユーザーを棚卸するかがひとつの課題になります。

解決方法のひとつとして、テナント内のすべてのチームのうち現在ゲストユーザーが含まれているチームをCSVに出力するPowerShellを作りました。
外部共有が有効かつ、ゲストユーザーがいないチームはこのスクリプトでは出力の対象外にしています。

https://github.com/wataruf01/Microsoft365/blob/main/PowerShell/InventoryTheTeamsThatCurrentlyHaveGuestUsers/InventoryTeams.ps1

#使い方
スクリプトを実行するために必要なモジュールをPCにインストールします。管理者権限で下記コマンドを実行してください。

```powershell:モジュールのインストールコマンド
Install-Module -Name ExchangeOnlineManagement
Install-Module -Name MicrosoftTeams
```

スクリプトは以下の通りです。
実行アカウントはお使いのテナントのアカウントに置き換えてください。

<font color="Red">実行アカウントには「全体管理者」または「Teams 管理者」の役割を割り当ててください。</font>「Teams 管理者」の役割を持つアカウントが Get-Teamを実行すると、そのアカウントがメンバーに含まれるかどうかに関わらずテナント内のすべてのチームの情報が取得できます。「全体管理者」は「Teams 管理者」の役割を包含しています。

```powershell:ゲストユーザーがいるチームをCSVに出力する
#-------------------------------------------------
#実行アカウント
#-------------------------------------------------
$user     = "XXX@XXX.onmicrosoft.com"
$password = "XXX" | ConvertTo-SecureString -AsPlainText -Force

$credential = New-Object System.Management.Automation.PSCredential($user,$password)

#-------------------------------------------------
#変数の設定
#-------------------------------------------------
#出力するCSVのパス
$now = (Get-Date).ToString("yyyyMMdd_HHmm")
$CSVFilePath = ".\InventoryTeams_" + $now + ".csv"

#-------------------------------------------------
#主処理
#-------------------------------------------------
#Exchange Onlineに接続する
Connect-ExchangeOnline -Credential $credential

#Microsoft Teamsに接続する
Connect-MicrosoftTeams -Credential $credential

#Microsoft365グループをすべて取得する
$groups = Get-UnifiedGroup -ResultSize Unlimited

#チームをすべて取得する
$teams = Get-Team

#ゲストユーザーがいるチームをCSVに出力する
foreach($team in $teams)
{
    #チームに紐づくMicrosoft365グループを取得する
    $targetGroup =  $groups | where ExternalDirectoryObjectId -EQ $team.GroupId

    #外部共有がオフの場合はスキップする
    if($targetGroup.AllowAddGuests -eq $false)
    {
        continue
    }

    #ゲストユーザーがいない場合はスキップする
    $teamUser = Get-TeamUser -GroupId $team.GroupId
    $guests = $teamUser | Where-Object "Role" -EQ "guest" | Select-Object -ExpandProperty User
    if($guests.Count -ne 0)
    {
        continue
    }

    $obj = New-Object PSObject
    $obj | Add-Member -MemberType NoteProperty -Name DisplayName        -Value $team.DisplayName
    $obj | Add-Member -MemberType NoteProperty -Name PrimarySmtpAddress -Value $targetGroup.PrimarySmtpAddress
    $obj | Add-Member -MemberType NoteProperty -Name GroupID            -Value $team.GroupId

    $obj | Export-Csv -Path $CSVFilePath -Encoding UTF8 -NoTypeInformation -Append -force
}
```

以上です。
【さくらのクラウドAPI】Basic認証でREST API叩いてみた（サーバー一覧取得）

## 概要

curlのサンプルでサーバー一覧を取得できたけど、他の言語で使うためのBasic認証でアクセスするサンプルをまとめました。
例としてサーバー一覧を取得してみます。

## さくらのクラウドAPIはBasic認証、Digest認証

ちゃんと読んでおらずこの内容を見つけるのに時間がかかりました（はじめにのところにちゃんと書いてありました）

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/901444/c4eb89af-8944-cd37-448f-68641f133169.png)|
|:-:|

https://developer.sakura.ad.jp/cloud/api/1.1/

つまり、公式にも記載しているcurlサンプルと同じようにBasic認証で他言語でも対応すればいいわけです。

```terminal:curlサンプル
curl --user "Access Token":"Access Token Secret" \
    https://secure.sakura.ad.jp/cloud/zone/is1a/api/cloud/1.1/server/
```

## REST APIをBasic認証でアクセス

Basic認証でアクセスするには`アクセストークン`と`アクセストークンシークレット`を`:`コロンでつないでBase64にエンコードして`Authorization`ヘッダーに付与すればアクセスできるみたいです。

### Base64エンコードの例

Access TokenとAccess Token Secretを:コロンでつないでBase64エンコードします。
今回は株式会社エン・ＰＣサービスさんの[base64エンコード/デコードツール
](https://www.en-pc.jp/tech/base64.php)を使って変換してます。

```
Access Token:Access Token Secret

↓ Base64でエンコード

QWNjZXNzIFRva2VuOkFjY2VzcyBUb2tlbiBTZWNyZXQ=

↓ AuthorizationヘッダーにBasicの文字列とエンコードしたやつを付与

Authorization:Basic　QWNjZXNzIFRva2VuOkFjY2VzcyBUb2tlbiBTZWNyZXQ=
```

[Advanced REST Client](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo?hl=ja)の場合はこうなりますね。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/901444/8b573ece-e839-6c39-f599-66d7a03f36c4.png)|
|:-:|

Base64の変換は【Base64 変換ツール】とかでググれば出てくると思います。

どの言語でもだいたいBase64エンコードの機能はあるはずなので、スマホアプリでもWebでも同じようにアクセスできます。

## 実行結果

[Advanced REST Client](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo?hl=ja)で実行してみると無事にサーバー一覧を取得できました。

|![スクリーンショット 2021-09-24 10.20.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/901444/73f92525-f1f1-7c4d-b849-61be7c5940e1.png)|
|:-:|

## まとめ

他の言語で対応するときも同じようにBase64に変換したものを`Authorization`ヘッダーに付与してあげればアクセスできそうですね。
Windows 10のPowerToysのFancyZones利用時に画面がちらつく場合の対応方法

Windows 10のPowerToysには、FancyZonesというウインドウの配置レイアウトを管理する機能がありますが、この機能を使用する際に一部の環境では画面のちらつきが発生する場合があります。もし画面のちらつきが発生した場合は、以下の手順で事象を解消できる場合があります。

# 手順
## １．「ディスプレイの詳細設定」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/bebffb25-2b44-dbd4-6d77-55c22ffbf95f.png)

## ２．各ディスプレイのリフレッシュレートを「60.000 Hz」に変更する（あるいは接続されているディスプレイが対応するリフレッシュレートに合わせる）
### 変更前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/b15d2d37-da88-f76e-5728-9cc2c10021f8.png)

### 変更後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/3ffb3e4b-300a-eab2-ad6c-17769255eae2.png)
【ラズパイ】ラズパイとmacOS間でファイル共有してみた

#はじめに
昨日、ラズパイにOSを入れ起動しました。
これからラズパイにPython実行環境を構築し、これまで作成したPythonプログラムを実行してみたいと思います。

そこでSMBを使って、ラズパイとmacOS間でファイル共有する方法を記事にします。
SMBとはServer Message Block の略で主にWindowsを中心とした環境でLANを通じてファイル共有やプリンタ共有などに使用される通信プロトコルの総称です。Linux環境でも利用可能です。

#環境
・macOS Catalina 10.15.7
・Sanoov Raspberry Pi 3 Model b+
　購入したものはAmazonで以下になりますのでご参考ください。

https://www.amazon.co.jp/gp/product/B07XQ6FLD5?ie=UTF8&psc=1&linkCode=ll1&tag=hirockio2206-22&linkId=731a53fd8a7cc7151463b10b33466884&language=ja_JP&ref_=as_li_ss_tl


#手順
####【macOS側】
1.デスクトップに[share]フォルダを作ります。
![スクリーンショット 2021-09-24 9.15.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/3036541a-597e-712e-d5b7-78c657467b95.png)
2.Macでアップルメニュー  ＞「システム環境設定」と選択し、「共有」をクリックします。
![スクリーンショット 2021-09-24 9.02.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/712fa005-191e-783c-0d3e-ef8c2a160173.png)
3.ファイル共有にチェックを入れ、[+]をクリックします。
![スクリーンショット 2021-09-24 9.16.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/ce159310-1d55-d14f-a507-f25563f9f03e.png)
4.デスクトップ　＞　share  ＞　追加　をクリックします。
![スクリーンショット 2021-09-24 9.20.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/2a574a73-4c29-b57f-c637-596941739a56.png)

5.macOSのIPアドレスが192.168.10.11であることを確認します。
　share フォルダを選択し、オプション　をクリックします。
![スクリーンショット 2021-09-24 9.47.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/caa30be3-6ec9-a0d5-c939-9fec5fac6e8c.png)
6.[SMBを使用してファイルやフォルダを共有]にチェックを入れ、そのアカウントでアクセスするか選択します。
　いつもmacOSにログインしているアカウントを選択してください。
![スクリーンショット 2021-09-24 9.41.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/65cac5f8-a90c-cf59-0140-bd7405e167c1.png)
7.macOSにログインする際と同じパスワードを入れてOKをクリックします。前画面に戻ったら完了をクリックしてください。これでmacOS側の設定は終わりです。
![スクリーンショット 2021-09-24 9.41.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/61d8bcaa-0a27-f34d-9cc2-31736bcba476.png)

####【ラズパイ側】
8.ファイルマネージャをクリックし、検索バーに手順5で確認したIPアドレスを以下の形式で入力します。

```
smb://IPアドレス/share
```
![2021-09-24-095704_1824x984_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/b642536e-bc7b-cf9e-c1c4-7b65769761a0.png)

9.ユーザを指定するにチェックを入れ、macOSのユーザ名とパスワードを入れて接続します。
![2021-09-24-095722_1824x984_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/5fce314e-73e1-bf97-5c3d-2d7943c6da92.png)

10.macOS側で適当なファイルを入れておき、それが確認できたら成功です。なお、ラズパイ側からもmacOSへファイル共有ができますので画面ショットなどを送ることができます。
![2021-09-24-095838_1824x984_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/2731f8ea-f3f6-4a25-19a6-36553e2b5d16.png)

#最後に
いかがでしたでしょうか。無事ラズパイとmacOS間でファイル共有はできましたでしょうか。
pythonファイルのやり取りをするのに非常に便利かと思います。
参考になれば幸いです。
Pythonの小技２

### CSVファイル読み込み
```python
import pandas as pd
df_data = pd.read_csv('file_name.csv')
```
### CSVファイル列指定（ヘッダーありの場合）
```python
df_data = pd.read_csv('file_name.csv')['column_name']
# 複数の場合
df_data = pd.read_csv('file_name.csv')[['column_name_1','column_name_2']]
```
### 列を削除する場合
```python
df_data = pd.read_csv('file_name.csv')
re = df_data.drop(columns=['column_name'])
```
### 列計算
```python
# 四捨五入
df_data['column_name'] = round(df_data['column_name'])
```
### 列にNanが含まれた場合のみ削除する場合 
```
# delete nan in B
df.dropna(subset=['B', 'C'])
```
Summarize Pandas Data Frames Better and on the Fly

#### Introduction
When we need to get an overview or summary of the data frame, the first panda's function we will try is 'describe.' It gives us a simple overview of our data. But we want more we need do some task manually. 

**So how can we do this better and on the fly?**
Skimpy is the answer. It gives an extended report in one line of code. 

**Why Skimpy when we got 'pandas-profiling' ?**
Most of us know that pandas-profiling is doing a great job when we need more dataset details. It's an excellent library for data science tasks. But, what if we need a more straightforward edition? A simple one. I think skimpy is helpful in that case.

#### Demo
Without discussing much, let's move to the demonstration part. First, you need to install the skimpy library.

```skim.ipynb
!pip install skimpy
```

Now, let us use skimpy toy data generate function to make the data set for our demo.

```skim.ipynb
from skimpy import skim, generate_test_data

df = generate_test_data()
df.head()
```
![head.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579376/d9a83f4a-4c0b-c42e-b98e-c190bda490ce.jpeg)

Generally, after creating the data frame, I used to run two functions, head() and describe(). So we can get an overview. describe() gives us a charming view of essential values.

```skim.ipynb
df.describe()
```
![desc.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579376/ca7dfdf6-fa18-5ce9-4cdf-5713464ca028.jpeg)

Usually, after that, we need to look into the insight of the data. We need to EDA, create histograms, etc...

Let us see how skimpy help us to generate an extended summary.

```skim.ipynb
skim(df)
```
![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579376/c85b48d0-4f4c-4f09-6489-af45ab3d56d8.jpeg)

![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579376/7554dec0-f60b-8442-0e00-a10a992bcc1f.jpeg)

Isn't that great? the skim function returns extended summary details. It includes histograms, missing data, basic statistics info, and also it produces data types and etc..

This is a new library. But seems very useful, so I wanted to share it with you.

You can get more details from https://github.com/aeturrell/skimpy

Have a nice day ...!!!

*本記事は @qualitia_cdevの中の一人、@nuwanさんが書いてくれました。
*This article is written by @nuwan a member of @qualitia_cdev.
act_as_paranoidで論理削除された子/親要素にアクセスできない時の対処方法

## 概要
掲題の通りハマったので自分のためのメモも兼ねて記載しておきます。


## 前提
店舗とそこに紐づく店員を表現するアプリを作るとします。
親をshop,子をclerkというテーブル名で作成します。
そして子要素経由で、親要素の名前やIDにアクセスする際にはactive recordのjoinやreferencesではデータが取得できません。
なので以下のように別のリレーションとして設定してあげて取得できるようにしてあげてください。

親クラス shop

```ruby
class Shop < ActiveRecord
  acts_as_paranoid

end
```

子クラス clerk

```ruby
class Clerk < ActiveRecord
  acts_as_paranoid

  belongs_to :shop
  belongs_to :with_deleted_shop, -> { with_deleted }, class_name: 'Shop', foreign_key: :shop_id, inverse_of: :Shop

end
```

上記のように論理削除を含めたら親/子要素とのリレーションを指定してあげる事で、情報が取得できるようになります。

そもそも論理削除の導入にはかなり慎重になった方がいいと思います、、、
wemosでアセンブラ その2

#概要

wemos　d1でアセンブラやってみた。
Lチカ、やってみた。

#サンプルコード

```
int v = 0;

void led_off(void) {
	asm volatile (
		"movi	a2, 0x60000304;"
		"movi	a3, 0x60000308;"
		"movi	a4, 0x00000004;"
		"s32i	a4, a3, 0;"
		"memw;"
		:
		:
		: "a2", "a3", "a4", "memory"
	);
}
void led_on(void) {
	asm volatile (
		"movi	a2, 0x60000304;"
		"movi	a3, 0x60000308;"
		"movi	a4, 0x00000004;"
		"s32i	a4, a2, 0;"
		"memw;"
		:
		:
		: "a2", "a3", "a4", "memory"
	);
}


void setup() {
	int i;
	Serial.begin(9600);
	while (!Serial)
	{
		;
	}
	Serial.println("start");
	pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
	if (v == 0)
	{
		led_off();
		v = 1;
	}
	else
	{
		led_on();
		v = 0;
	}
	delay(800);
}





```

以上。
yarn ではなく npm install を叩いたらエラーを出したいを実現する方法が簡単だった

## やりたいこと

`yarn` ではなく `npm install` を叩いたらエラーを出す仕組みを作りたい

## 実現方法

- npmrc に `engine-strict=true` を記載する
- npmrc とは npmの設定ファイル のことである

```js
// .npmrc
engine-strict=true
```

- package.jsonの `engines` を設定する

```package.json
"engines": {
  "npm": "npmではなくyarnを使用してください"
}
```

2つの設定を完了させた上で`npm install`と叩いてみる

| npm install コマンドを叩いた結果 |
| --- |
| ![npm-error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508390/a61e1dd7-ed97-37e5-35e6-cd8260784848.png) |

これで`yarn`を使用しているプロジェクトで
間違って`npm install`を叩いてしまっても大丈夫ですね！

## 参考文献

- [package.jsonに"engines"を設定すると「このバージョンのNode.jsでしか動かない」を表明](https://qiita.com/suin/items/994458418c737cc9c3e8)
- [npmまとめ | .npmrc](https://zenn.dev/thao_0108/articles/10bb038982eff3#.npmrc)