OmniAICreator/Qiita-1.07M huggingface dataset:
動画編集で映像と音声を別撮りしたときにズレが起きるときの対処

音楽系の動画をとっていると、
やはり良い音質でとりたくなります。

そこで使われる手段が、動画と音声の別撮りです。
しかしこの手法を**一発撮り**で使うと、
機器によっては、動画と音声を合わせたときに**ズレ**が発生します。
以下、このズレを解消する方法を書きます。

※ちゃんとエンジニアっぽい内容もあるよ！

## 2022/5/10追記 事象解決しました
動画編集ソフトFinalCut側の問題でした。
動画作成時にビデオのレートを動画のレート29.97（60なら59.94）に
合わせてあげることで改善しました。これで音声とのズレもなくなっています。

![スクリーンショット 2022-05-10 22.13.43.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/963e986f-22b9-bc16-d24e-530767594476.jpeg)

以下は元記事の内容として、参考程度にお読みください。


## 結論
動画と音声で**フレームレート(fps)** を合わせる。

方法1：動画もしくは音声を変換する。
方法2：はじめからfpsが合う機器を使う。

## 事象
https://youtu.be/Yh7-oICzeeA

私の弾き語り動画です！
少しわかりにくいかもしれませんが、動画後半になると
ギターのストロークや口元が音声に対して若干**速く**なっているのがわかります。

## 原因
結論にかいた通り、**fps**でした。
kHzやbitでズレるという記事をよくみかけたので、
最初はこれら疑ったのですが、原因はfpsでした。

**事象が発生した撮影環境**
動画：ZV-1（sony）:48hhz 16bit/24bit（たぶん）
音声：R8（ZOOM）/ iRig Mic HD2 & iphone+GrageBand:44.1khz~48Khz 16bit/24bit

最初はR8で録っていて、ズレがおこったので、KHzとbitの問題かなぁと思い、
iRigとGarageBandを使っていろんな形式でためしたのですが、ＮＧでした。
ファイル形式もmp4やらwavでもNG。ちなみに撮った直後の音声書き出しをする前の状態では、
動画と音声は一致してました。どうやら書き出すタイミング、
もしくは動画編集ソフトに取り込むタイミングでズレが起こるようです。

上記の事象はこの記事でわかりやすく記載されています。
https://blog.socialcast.jp/03/post-519/

が、よく考えると私の環境の場合、音の方が後ろにズレるという現象でした。

途方にくれ、もう分けるのはあきらめるしかないのかと思っていたところ、
動画編集ソフト(**Final Cut**)上にこんな表記が！！

![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/10255b95-ec24-f112-140b-ab07af5c80c5.png)

！？　全てを悟った瞬間です。

60pだとおもっていたものが**59.94p**。音声データはFinalCutにとりこむと60p。
そりゃズレるよね、という話です。音声の方が長くなる理由も納得です。

これも上でのせた記事同様に、業界では有名な話のようです。
https://mossan99.hatenablog.com/entry/2013/03/28/160907
https://ameblo.jp/holycater/entry-12647617264.html


## 対処
**方法1：動画もしくは音声を変換する。**
こいつからいきます。こいつは２パターンあります。

パターン１：ffmpegを使う
Macerはターミナルつかってこいつでいけます！！

1、Homebrewのインストール（ない人）
開発やってる人とかなら大体はいってると思いますが、
ない人は https://brew.sh/index_ja から**「インストール」**
のすぐ下のコマンドコピーしてきて実行。

２、ffmpegのインストール

```
brew install ffmpeg
```
※私のMacだと10~20分くらいかかりました

３、変換
比率とフレームレートは適宜変更

```
ffmpeg -i 変換前ファイル名 -filter:v scale=1080:1920 -r 30 編集後ファイル名.mov
```
変換なので、もちろんここも時間かかります。
2GBのファイルだと30分近くかかったと思います。

※参考（より細かい内容記載してくれてます。感謝。）
https://rils-k.hatenablog.com/entry/2021/02/03/192030

※コマンドオプション詳細（気になる人用）
https://techblog.morphoinc.com/entry/2020/07/20/100009
https://nico-lab.net/about-ffmpeg/

パターン②
**iMovie**等動画編集ソフトを使って変換する。
こっちのほうが早いかもしれません。

**方法2：はじめからfpsが合う機器を使う。**
そのままです。私はこっちに倒れました。

というのも、変換にかかる手間とZV-1をそこまでして使いたいかという天秤にかけると、
そこまでではありませんでした。ZV-1はたしかに綺麗にとれますが、長く撮影を繰り返してると
熱で落ちたり、電池がなくなったりで、あまり長時間撮影には向いていないです。

**タイムコードの設定に関して（2022/2/27追記）**
カメラ側の設定によってタイムコードの設定というものがありますが、
これは変更しても実際のfpsはかわりませんでした。

私が使用しているZV-1の場合
>MENU→（セットアップ）→［TC/UB設定］→［TC Format］→NDF（ノンドロップフレーム）
https://helpguide.sony.net/dc/1910/v1/ja/contents/TP0002861656.html

この設定はかえてもズレ自体は改善しないよという話
https://ameblo.jp/holycater/entry-12647617264.html

## さいごに
**別撮りで一発撮りをする人**は一定数いそうなので、これにハマる人も
それなりにいるんじゃないかと思います。別撮りの一発撮り、
という意味だとあの有名な**FIRST TAKE**もそうなんじゃないでしょうか。
（そうだと信じてます）

せっかく**ZV-1**買ったのにあんまり活躍してくれなくて悲しい気持ちですが、
勉強になりました。今後も変わらずYouTubeライフも努めていきます。

是非、私のYouTubeチャンネルも登録よろしくお願いします！

**hiyanger**
https://www.youtube.com/channel/UCqJU3_HoCVaknKDepM3ONNA
【Rails】macのrailsサーバーに他の端末からアクセスする方法

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

## macのrailsサーバーにiPad等でアクセスする方法

macローカルでrailsウェブサービスを作ってて、スマホ実機でテストしたいとき。
エミュレータでもいいけど、実機じゃないとテスト出来ないときってありますよね...

### macと他の端末を同じWi-Fiに繋げる
macと他の端末を同じWi-Fiに繋げます。

### macのローカルIPアドレスを確認する
#### GUIで確認する方法
アップルメニューから「システム環境設定」を選択。
![スクリーンショット 2022-02-24 2.11.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/b53c4860-d0a6-b64b-d517-f6c1a39a23dd.png)

「ネットワーク」を選択。
![スクリーンショット 2022-02-24 2.01.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/18691bdf-2b3f-9791-6e31-4a74c788e91b.png)

ローカルIPアドレスを確認
画面左側から選択して、IPアドレスを確認します。
右側の赤枠の箇所に表示されているのがローカルIPアドレスです。
![スクリーンショット 2022-02-24 2.00.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/5f6fd41b-a335-34db-d34a-94270dda3286.png)

#### CLIで確認する方法
ターミナルにで以下のどちらかを実行します。

```:ターミナル
$ ifconfig | grep inet 

又は

$ ifconfig | grep broadcast
```
表示された結果のinetの後の数字がローカルIPアドレスになります。

### IPアドレスを指定してrailsサーバーを立ち上げる
以下の通りターミナルで実行し、上記で確認したローカルIPアドレスを指定してrailsサーバーを立ち上げます。
デフォルトでは、127.0.0.1で立ち上がります。

```:ターミナル
rails s -b 192.168.10.105
```
上記を実行することで、IPアドレス192.168.10.105、ポート番号3000で立ち上がります。
ポートも指定したい場合には`-p 3001`等を上記のコマンドの後ろにつけ実行してください。



### 他の端末のブラウザからアクセスする
ブラウザのアドレスバーに以下のような形でURLを入力しすると他の端末からアクセスすることができます。
`http://192.168.10.105:3000/`

URLはターミナルに出力されるのでそれをコピー＆ペーストする等してください。
一致する値の検索語にその位置を返す


一致する行を探すのはMATCH関数を
セル範囲にある値のセル参照を返すのはINDEX関数を
最終的に位置を取得するのはCELL関数を利用します。

```
MATCH($A4,$I$4:$I$3000,0)
```


A4には一致して欲しい値のセル
I4:I3000には検索して欲しい範囲を指定して
0のものは完全一致のことを指しています。


```
INDEX($I$4:$I$3000,MATCH($A4,$I$4:$I$3000,0))
```

INDEXのI4:I3000は検索する範囲の指定なので、
MATCH関数と同範囲にします。

最終的にはこのような感じですね。

```
CELL("address",INDEX($I$4:$I$3000,MATCH($A4,$I$4:$I$3000,0)))
```

:::note info
CELL("address",INDEX(検索範囲,MATCH(一致対象,検索範囲,一致タイプ)))

:::

そこで、探した結果の横の文字を表示してリンクを付ける内容は下記のものになります。
A2にはシート名が記載されています。

```
=HYPERLINK("#"&$A$2&"!"&CELL("address",INDEX($I$4:$I$3000,MATCH($A5,$I$4:$I$3000,0))), VLOOKUP($A5,$I$4:$J$3000, 2, FALSE))
```
辞書(dict)型データを、Spreadsheetに取り込む。SmartHRのデータを想定

# この記事は何？
SmartHRデータ加工入門として作った記事の第3弾であり、最後の記事です。
https://qiita.com/piyoSakai/items/2982fb7511331e56f8fb
https://qiita.com/piyoSakai/items/21efd055635b92d14a7a

# サンプルコード
[こちらの記事](https://qiita.com/piyoSakai/items/21efd055635b92d14a7a)で加工したデータを、Spreadsheetに突っ込む。

```javascript
const LOADING_SHEET_NAME = 'Crews'; //ここは各自のシート名に合わせる

function crews_to_list(crews){
  let col = []
  for(let c of crews){
    let row = [
      c['email'],
      c['last_name'],
      c['first_name'],
      c['position'],
      c['is_corporate'],
      c['is_hr'],
      c['is_ms'],
      c['is_cp'],
    ];
    col.push(row);
  }
  return col;
}

function clear(sheet){
    // ざっくりクリアする。なのでLOADING_SHEETにはメモ等残せない。
    sheet.getRange(2, 1, 999, 100);
}

function load(sheet, data){
    sheet.getRange(2, 1, data.length,  data[0].length).setValues(data); //ヘッダ行を残す
};

function load_smarthr_data(){
    let crews = extract('crews'); //1つ目の記事の処理
    let summarized_crews = translate(crews); //2つ目の記事の処理
    let data_to_load = crews_to_list(summarized_crews);
    const spreadsheet = SpreadsheetApp.openById(SHEET_ID);
    let sheet = spreadsheet.getSheetByName(LOADING_SHEET_NAME);
    clear(sheet);
    load(sheet, data_to_load);
}

```

# 解説
- load_smarthr_data()で、これまでのデータ抽出(Extract)、加工(Translate)を行っている
- その後、辞書(dict)データを、Spreadsheetに追加しやすい配列(list)に変換ている
- 最後に、シートをクリアし、データを突っ込んでいる

もう少しエレガントに書ける気もするが、一旦このくらいがわかりやすいかもしれない。

ちなみに、著者は最初これらをPythonで書いていたのだが、

- 定期実行が容易であること
- GoogleSpreadsheetへの吐き出しが容易であること

から、GASにわざわざ移植した。
一方で、型アノテーションができないなど一長一短はあるので、身近な環境から使う言語を選定するのがおすすめ。

# 発展編
このデータを活用して、Googleのユーザーグループを編集することができる。
このようにGoogleSpreadsheetを中間データベース兼UIとして活用することで、非エンジニアでも視覚的に理解しやすいUIでコーポレートエンジニアリングを行うことが出来る。
https://qiita.com/piyoSakai/items/e0e517c090ab061936a2
ginのリダイレクトで詰まったお話。

# 参考
https://qiita.com/unsoluble_sugar/items/b080a16701946fcfce70

# 問題
* 概要
 * サインアップ後の画面遷移がうまくいかない。
* いつ起きるのか
 * POSTリクエストをリダイレクトしたとき
* 何が起きるのか
 * 移動先にPOSTでのリクエスト

# 原因
ログイン後のリダイレクトにhttp.statusPermenentRedirectを使っていたから。
なぜhttp.statusPermenentRedirectではダメかというと、上記の定数の値は307であり、また307を使った場合ににエージェントはメソッドの変更をしてはならないという決まりがあったため。

# 解決法
302のハードコーディングで対応。

# 最後に
もし何かもっといい方法があれば教えてもらいたいです。
yukicoder contest 332 不参戦記

# yukicoder contest 332 不参戦記

## [A 1841 Long Long](https://yukicoder.me/problems/no/1841)

Python だと乗算一発.

```python
N = int(input())

print('Long' * N)
```

## [B 1842 Decimal Point](https://yukicoder.me/problems/no/1842)

Aに10<sup>C</sup>をかけて、Bで割った商を10で割ったあまりが答えだけど、10<sup>C</sup>が大きすぎて計算できない. ここで10×BをBで割った商を10で割ったあまりが常に0になるという事実に気づくと計算可能になる.

```python
T = int(input())

for _ in range(T):
    A, B, C = map(int, input().split())
    print((A * pow(10, C, B * 10)) // B % 10)
```
SmartHRのデータをGASで引っ張ってくるサンプル

# 前提
[公式ドキュメント](https://developer.smarthr.jp/api/index.html#!/%E5%BE%93%E6%A5%AD%E5%93%A1/putV1CrewsIdInvite)を見るのが一番いいですが、初心者向けに。

# サンプルコード
従業員全員の情報を引っ張ってくるサンプル

```javascript
const TENANT_ID = 'YOUR_COMPANIYS_TENANT_ID';
const ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN';
const STAY_SECOND = 1;

function is_last_page(headers){
    try{
        links = headers['link']; //nextのURL表記が最終ページで無くなる
        if('next' in links){
            return false;
        }else{
            return true;
        }
    }catch(e){
        if(e instanceof TypeError){  // 1ページで完結する場合はそもそもlink要素が無い
          return true;
        }else{
          throw e;
        }
    }
}

function object_to_param(obj){
  return Object.keys(obj).map(function(key){ return key+"="+ obj[key] }).join("&")
}

function extract(){
    let HEADERS = {
        'Authorization': 'Bearer '+ ACCESS_TOKEN
    };
    result = []
    // 安全のため上限を100回に設定
    for(let i = 1; i < 100; i++){
        let url = 'https://' + TENANT_ID + '.smarthr.jp/api/v1/crews?';
        let payload = {
            'page': i,
            'per_page': 100,
            'emp_status': 'employed', //ここらへんはご自身のやりたいことに合せて追加・削除してください。
        }
        let options = {
            'method'  : 'GET',
            'headers' : HEADERS,
        }
        let response = UrlFetchApp.fetch(url + object_to_param(payload), options);
        let result = result.concat(JSON.parse(response));
        if(is_last_page(response.getHeaders())){
            break;
        }else{
            Utilities.sleep(STAY_SECOND * 1000);
        }
    }
    return result;
}

function main(){
    Logger.log(extract());
}
```

# 解説
- APIを叩いているextract()では、ページ遷移が発生するためループ構造になっている。
- is_last_page()でページ遷移における最終ページかの判定をしている。もっとエレガントな方法もあるかも。
- object_to_param()は、オブジェクトをGETメソッドのパラメタ文字列に変換している。GASのGETではoptionsにpayloadとして追加することはできないっぽい。

# 次回はその後の加工について記載する。
https://qiita.com/piyoSakai/items/21efd055635b92d14a7a
AdminRespondToAuthChallenge operation: Invalid attributes given, name is missing


Amazon Cognito のユーザープールの設定で `name` などのカスタム属性を必須にしている場合、AWS CLIではそれも指定しなければならないのでその指定方法。

`name` がないと言われた

> An error occurred (InvalidParameterException) when calling the AdminRespondToAuthChallenge operation: Invalid attributes given, name is missing


うん、確かにそう書いてあるよね。

> `NEW_PASSWORD_REQUIRED` : `NEW_PASSWORD` , any other required attributes, `USERNAME` .

[respond\-to\-auth\-challenge — AWS CLI 2\.4\.20 Command Reference](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cognito-idp/respond-to-auth-challenge.html)

でも、 `NEW_PASSWORD="${new_password}",NAME=${name},USERNAME=${username}` って指定しても同じ結果ですし。

というわけで正しい指定方法は `userAttributes.name=${name}` でしたよということでメモとして残しておこう。

```shell-session
$ aws cognito-idp admin-respond-to-auth-challenge \
  --user-pool-id ${user_pool_id} \
  --client-id ${app_client_id} \
  --challenge-name NEW_PASSWORD_REQUIRED \
  --challenge-responses NEW_PASSWORD="${new_password}",userAttributes.name=${name},USERNAME=${username} \
  --session "${session}"
```
見逃しがちな信用できるエンジニアの特徴

## まえがき

組織に属している人には基本的に他者との協業がついてまわる。

エンジニアの振る舞いに関して、古い日本の価値観で測ると「和を乱す」、「空気が読めない」、「有害」などと見られがちな振る舞いが、本当は「信用できる」人間の振る舞いであることがたまにある。

逆に「印象が良い」、「優しい」と評価される振る舞いも「信用していいのか？」と疑いをもつ指標になるものもある。

今回はエンジニアとして働いていくなかで、凝り固まった古い価値観で、信用すべきエンジニアを見誤らないためにも、**信用できるかもしれない**と思えるエンジニアの特徴を書き記す。

## 実は信用できるかもしれないエンジニアの特徴

### 小さな問題に対しても熱議論ができる

社会人は同僚や上司と意見が割れることは少なくない。

特にエンジニアという職業に関しては、コードの実装方法や設計（モジュールの分け方や名前等）と普通の社会人ならそこまで気にしないようなことで言い合いレベルの議論に発展することもある。

そんなことで言い合いになるような人間は、上述した古い価値観で図ると「和を乱すエンジニア」と見られることもあるだろう。

しかし、エンジニアの世界ではたかが名前の一つや数十行あるファイルの中のたった1行をどう書くかの議論をおろそかにすることで、後で大きな問題に発展することもある。

流石にいちいち怒りが沸点に達するような議論の仕方をする人間は問題があるように思うが、
とりあげることが「たかがお名前」、「たかが1行のプログラム」とどんなに小さなことでもそれを話しの俎上に上げ、あるべき姿に向かって熱議論ができるエンジニアは十分に「信用できるエンジニア」であると考えられる。

### 最後までやらせる

エンジニアをしていると自分の技術力では作りきれない（期限内に終わらない）タスクに当たるといったことが度々ある。
そういったことがあると、スキルの高い別のエンジニアによってタスクを巻き取られてしまうということが発生する。

もちろんこれはビジネスとして、「価値のあるものを決まった期限内に生み出す」といった面でまちがった選択では決してない。

しかし、その決断に至るまで「スケジュールを後ろに調整できないか」、「適切なフォローを行えばやりきれるのではないか」といった点を考えなかったことは間違いである。

とくにエンジニアという職業は、上司や同僚にタスクを巻き取られてしまうと自分のスキルの低さに罪悪感を覚えたり、遅延したタスクを巻き取り続けるエンジニアを生み出してしまうといったことを発生させてしまう。

こういったときにたとえマネジメント層から言葉槍を刺されようとも、タスクをアサインしたエンジニアを信じて最後までやらせてあげるといった判断ができるエンジニアは、ヒトに投資ができるエンジニアだと思っていいだろう。

もちろんただやらせるだけで放置していては意味はないし、本当に巻き取るべきときにはそういう判断もしっかりできるという前提ありきだが。

### 話をひっくり返せる

ここで言う「ひっくり返す」は事実を捻じ曲げるだったり嘘を言うといったニュアンスの言葉ではない。
エンジニアは時として、実際の作業に入ってみると設計や要件といった、「過去に決まった/合意したこと」に対して違和感を覚えることもある。

一度決まったことをひっくり返すのは社会人として割と心理的なハードルが高いし、それに従っておいたほうが楽なケースも多い。

しかし、エンジニアが覚える違和感の中にはユーザの使い勝手やソフトウェアの生み出す利益に直結するものもある。

そういった際に、どんなフェーズでも決まったことをひっくり返しに行けるようなパワーのあるエンジニアは、そのタスクの先にあるものをしっかり見据えていて真摯に向き合ってる人だと思っていいだろう。

### 会議に出ない

年次やキャリアがあがってくると、一日のほとんどが会議で埋まってしまうということも度々あるだろう。

だが、そのような人こそ同僚や部下のフォローを行えるスキル水準ににあることがあったり、難しい作業を抱えていることが多い。
例えば、チームのタスクの進捗が芳しくなときに、脳死で参加依頼が来ている会議に参加するのではなく、あえて参加せずにチームメンバーとの時間や自身の作業時間を確保するといったことを優先することがある。

会議に出席しないということは、他の出席者の目線からするとあまり心象がよくないことだったりする。
「なぜ呼ばれているのに出てこない？」、「議論に関心がない？」、「怠慢か？」などと思われることもあるだろう。

しかし、そもそもすべての会議に主席する必要がそもそもあるのだろうか？決定事項がわかればとかったり、そもそも自分が呼ばれた背景すらわからないような会議も存在する。

そういったものをしっかり判断でき、そのときに本当に時間をかけるべきことに向き合う人は、自分のやるべきことを真に理解している人なのかもしれない。

## おわりに

今回このような記事を書こうと思ったのは、筆者が若手の頃からよく一緒に働くいていた上司のエンジニアがきっかけでした。

その方は上述したような特徴を持つ方で、これらの振る舞いによってマネジメント層の方や他のチームのエンジニアから不名誉な評価を度々受けているような話を聞きました。

しかし、筆者としてはこの方のこれらの振る舞いによって、ここまで成長してこれたと思っており、こういうエンジニアがマイナスの評価を受けのは悔しいと思って筆を取りました。

これら以外でも、自分の上司や同僚で「ん？」となるような特徴をもつ方がいた際に、目に見える事実だけでその人を嫌厭したりせず「もしかしたらこっちのことを思ってくださっているのかも…」考えてるきっかけになれば幸いです。
（結果的に本当に害な場合ももちろんありますが）

筆が進んだらこの記事の逆パターンである、「いい人そうだけど信用してはいけないかもしれないエンジニア」も書こうかなと思います。
[C#]DictionaryのKeyをカスタムクラス、ValueをListにする

# 概要
業務にて、タイトルの通りカスタムクラスとLINQを組み合わせたDictionaryを使った実装が必要になったため、勉強と記録がてら記事作成します。

# やりたいこと
ざっくり、以下のような感じです。
(実際は全然違う内容ですが、便宜上置き換えています)

- 社員がノートに1行ずつ起票をしていく運用のノートがある。
- ノートでは、同じ社員が複数行起票することがある。
- このノートにおいて、各社員が何行目に起票したかを整理し、表示する。

上記において、 社員情報-記入した行のリスト という形のDictionayを使用することで対応しました。

# ポイント
Dictionaryにおいて、Keyを同一とみなすためには以下を満たす必要があるようです。

- GetHashCodeの結果が同じであること
- Equalsの結果がtrueであること

したがって、Keyに独自のクラスを使用する場合は、上記2つの関数を適切にオーバーライドする必要があります。

# 実装例
以下のような感じにしました。  
※とりいそぎで書いているので、最後のコンソール出力はソートせずにdictionaryに入れた順で出しちゃってます。 
※foreachのループの中でループカウンタをとってくる方法は、もっといいやり方があるかも…

## 社員クラス
``` C#
public class Employee
{
    public string id { get; set; }
    public string name { get; set; }

    // コンストラクタ
    public Employee(string id, string name)
    {
        this.id = id;
        this.name = name;
    }

    // Equalsをオーバーライド(※VisualStudioで自動生成)
    public override bool Equals(object obj)
    {
        return obj is Employee employee &&
                id == employee.id &&
                name == employee.name;
    }

    // GetHashCodeをオーバーライド(※VisualStudioで自動生成)
    public override int GetHashCode()
    {
        int hashCode = -48284730;
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(id);
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(name);
        return hashCode;
    }
}
```

## Main
``` C#
// 結果の格納先
Dictionary<Employee, List<int>> dictionary = new Dictionary<Employee, List<int>>();

// 社員群
Employee john1 = new Employee("A0001", "John");
Employee tom = new Employee("A0002", "Tom");
Employee john2 = new Employee("A0003", "John");
Employee emily = new Employee("A0004", "Emily");
Employee alex = new Employee("A0005", "Alex");

// 記帳順のリスト
List<Employee> entryList = new List<Employee>()
{
    john1,
    tom,
    john1,
    emily,
    alex,
    john2,
    john1,
    john2,
    alex
};

List<int> valueList;
int i = 0;

Console.WriteLine("--- 記帳順 ---");

// 記帳順を格納していく
foreach (Employee employee in entryList)
{
    i++;
    // dictionaryに登録済かを判定しつつ、登録済の場合はリストを取得
    if (dictionary.TryGetValue(employee, out valueList))
    {
        // 登録済の場合、リストに値を追加して更新
        valueList.Add(i);
        dictionary[employee] = valueList;
    }
    else
    {
        // 初出の場合、登録
        dictionary.Add(employee, new List<int> { i });
    }
    Console.WriteLine(string.Format("i={0}, {1}:{2}", i, employee.id, employee.name));
}

Console.WriteLine("--- 社員ごとの記録 ---");

// 結果を出力
foreach (Employee employee in dictionary.Keys)
{
    Console.WriteLine(string.Format("{0}:{1} - {2}", employee.id, employee.name, string.Join(", ", dictionary[employee])));
}
```

## 結果
```
--- 記帳順 ---
i=1, A0001:John
i=2, A0002:Tom
i=3, A0001:John
i=4, A0004:Emily
i=5, A0005:Alex
i=6, A0003:John
i=7, A0001:John
i=8, A0003:John
i=9, A0005:Alex
--- 社員ごとの記録 ---
A0001:John - 1, 3, 7
A0002:Tom - 2
A0004:Emily - 4
A0005:Alex - 5, 9
A0003:John - 6, 8
```

# 参考リンク
[C#で自作クラス(カスタムクラス)をキーにする方法(Dictionary,HashSet)](https://mocotan.hatenablog.com/entry/2017/10/31/064738)
distutils の廃止予定（Python 3.12）

こんにちは。
Python 3.12 では ```distutils``` が廃止される予定とのことです。```pip install``` すると現在警告が表示されます（homebrew/linuxbrew による Python 利用の場合。下記例）。

参考情報として（Homebrew/homebrew-core (GitHub)内）

* "[Python is deprecating distutils.cfg #76621](https://github.com/Homebrew/homebrew-core/issues/76621)"
* "[pybind11 2.9.1 #94696](https://github.com/Homebrew/homebrew-core/pull/94696)"

```console
$ brew install python3
$ brew info python3 | head -n1
python@3.9: stable 3.9.10 (bottled)
$ python3 -m pip install ...
DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
```
Jetson Nano JetPack 4.6 (L4T 32.6.1) のカーネルビルド

# はじめに

JetsonHacksの<a href="https://github.com/JetsonHacksNano/buildKernelAndModules">buildKernelAndModules</a>ツールがJetPack4.6(L4T 32.6.1)まで対応していました。
JetPack4.6でカーネルビルドを行ってみました。

# 1. buildKernelAndModulesツールのダウンロード

```bash
$ git clone https://github.com/JetsonHacksNano/buildKernelAndModules
```

# 2. カーネルソースのダウンロード

```bash
$ cd buildKernelAndModules/
$ ./getKernelSources.sh
```

# 3. カーネルコンフィグの編集

### viで編集した.configファイルはカーネルビルドの時にバックアップ(.config.oldとして退避)されてしまう事象が発生。

```bash
$ sudo vi /usr/src/kernel/kernel-4.9/.config 
```

```bash
Proposed source path: /usr/src/kernel/kernel-4.9
Source Target: /usr/src/
scripts/kconfig/conf  --silentoldconfig Kconfig
#
# configuration written to .config
#
```

editConfig.shコマンドを使用してCUIでカーネルコンフィグを編集します。

```bash
$ ./editConfig.sh
```

# 4. カーネルビルド

```bash
$ ./makeKernel.sh 
```

### 掛かった時間

```bash
real	30m8.400s
user	75m12.976s
sys	7m7.280s
```

# 5. モジュールのビルド

```bash
$ ./makeModules.sh
```

### 掛かった時間

```bash
real	43m19.288s
user	109m35.752s
sys	11m24.728s
```

# 6. イメージのコピー

```bash
$ ./copyImage.sh
```

# 7. 再起動

```bash
$ sudo reboot
```

# (参考)

https://qiita.com/kitazaki/items/5fc6b2e8df2bfe03e9b5

https://qiita.com/kitazaki/items/fe3b2446a434da52551e

https://qiita.com/kitazaki/items/b1870b8836dc369f8ae8
セレクトボックスで選択したテキスト情報を出力する

このようなセレクトボックスとテキストボックスがあったとする
![スクリーンショット 2022-02-24 0.43.15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532816/ac7f0448-295c-73e0-533b-b889ca6d9454.jpeg)
セレクトボックスの中身はこう
![スクリーンショット 2022-02-24 0.44.13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532816/02487cbd-8de0-8d3a-e92d-abf3c704e495.jpeg)


htmlソースは以下

```hanninsagashi.html
<div>犯人
	<select name='hannin' id='hannin'>
		<option value="1">本人</option>
		<option value="2">夫</option>
		<option value="3">娘</option>
		<option value="4">その他家族</option>
		<option value="5">該当なし</option>
  </select>
</div>
<div>
	<td>
    <textarea name="memo" id="memo" style="height: 50px; width: 150px"></textarea>
	</td>
</div>
```

セレクトボックスで選択した結果のテキスト情報をtextareaに出力させたい場合、
セレクトボックスで選択したvalueのindex値をselectedIndexを使用して取得した上で
textContentで出力するという方法でいける

```purintabetadaro.js
const shinhannin = () => {
	const hannin = document.getElementById("hannin");
	const memo = document.getElementById("memo");
	const hanninIndex = hannin.selectedIndex;
	memo.value = hannin.options[hanninIndex].textContent;
}
document.getElementById("hannin").onchange = shinhannin;
```

このようにセレクトボックスのプルダウンのテキストがそのまま出てくれる
![スクリーンショット 2022-02-24 0.48.20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532816/849917bf-7528-44ee-f62b-0db906254b1e.jpeg)


セレクトボックスをJavascriptのオブジェクト的に表現した場合、以下になるということを
念頭に置いたらわかりやすいかもしれない

{value : 1 , name : "本人"}, //index : 0
{value : 2 , name : "夫"}, //index : 1
{value : 3 , name : "娘"}, //index : 2
{value : 4 , name : "その他家族"}, //index : 3
{value : 5 , name : "該当なし"} //index :4

つまり、夫(index値:1)を選択した場合、「document.getElementById("hannin").selectedIndex = 1」
ということになる
よって、「document.getElementById("hannin").options[1].textContent = 夫」
という結果になる

なお、「Cannot set property 'onchange' of null」が出た場合、
Javascriptの記述をHtmlの後に記述するなどの対処が必要
Root CAとサーバ証明書、クライアント証明書を作る

オレオレ証明書を作るときのメモ書き。
途中の入力項目は省略。（あちこちのサイトに書いてあるので、気になる方はそちらでお探しください）

## 準備

各種作業ディレクトリを作る。

```bash
mkdir ca server client
```

## Root CA

```bash
$ cd ca
$ mkdir -p demoCA/{certs,newcerts}
$ touch demoCA/index.txt
$ echo '00' > demoCA/serial
$ find .
ca/
ca/demoCA
ca/demoCA/newcerts
ca/demoCA/serial
ca/demoCA/index.txt
ca/demoCA/certs
```

```bash
$ openssl genrsa 2048 > ca.key
$ openssl req -new -key ./ca.key -sha256 -out ca.csr
$ openssl x509 -days 3650 -in ca.csr -req -signkey ca.key -out ca.crt
```

`ca/ca.key` がCAの秘密鍵、 `ca/ca.crt` がオレオレRoot証明書になる。

## サーバ証明書

```bash
$ cd server
$ openssl genrsa 2048 > server.key
$ openssl req -new -key server.key -sha256 -out server.csr
$ cd ../ca
$ openssl x509 -req -in ../server/server.csr -out ../server/server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -sha256
```

`server/server.key` がサーバの秘密鍵、`server/server.crt` がサーバ証明書になる。
Common Name(CN)に対象のDNSドメインを記載すること。

## クライアント証明書

```bash
$ cd client
$ openssl genrsa 2048 > client.key
$ openssl req -new -key client.key -out client.csr
$ cd ../ca
$ openssl x509 -req -in ../client/client.csr -out ../client/client.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -sha256
```

`client/client.key` がクライアントの秘密鍵、`client/client.crt` がクライアント証明書になる。
サーバ証明書の作成手順と同じ。

## その他

### PKCS #12にまとめる

クライアントの証明書 + 秘密鍵をローカル環境に導入するときに使ったりする。

```bash
$ openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12
```

### つぶやき

本当は openssl.cnf をちゃんと書くべき。証明書作成は難しい。
フルスクラッチでWebアプリの開発を行いデザインを少し変更してみた

# ログイン画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542047/9eef6376-f0e7-c058-bfcd-b6ea8f0697a5.png)

# サインアップ画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542047/37ace0f9-baee-7730-0462-a1beeb3e03a6.png)

# メイン画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542047/81098b02-f8da-6cc1-7be6-237a9f5cbdc7.png)

# タスク登録画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542047/9bd1a0f7-ebd1-cedc-43cb-0b4fdc2db59c.png)

# タスク検索画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542047/49d24cf3-3eae-345c-b188-8c5d76222f9c.png)

# ブログ作成ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542047/618db396-0ef1-9f54-4586-b72c4d4f1e86.png)

ここから登録したブログ記事の表示処理を実装するのと、カレンダー機能を開発します。
Ubuntu 20.04でpyenv, Vimを使うための準備作業の備忘録

# 必要なライブラリの追加
以下のコマンドを実行し、必要なライブラリを追加します。この行程を実行せずに、`pyenv install`コマンドを実行すると、python-buildがエラー終了し、所望のPythonの環境が構築出来ません。

```bash
sudo apt install -y zlib1g-dev libffi-dev libbz2-dev libreadline-dev libssl-dev libsqlite3-dev liblzma-dev tk-dev
```

<details><summary>Red Hatの場合</summary><div>

```bash
sudo yum install -y openssl-devel gdbm-devel readline-devel libffi-devel sqlite-devel
```

</div></details>

# Vim関連の準備
VimのPluginでPythonがベースとなっている物が時々有りますが、そのインストールにCMakeが必要な場合が有ります。よってインストールしておきます。

```bash
sudo apt install -y cmake
```

python-buildの`--enable-shared`オプションを有効化します。.bash_profileに以下を追加します。このオプションを有効化しておかないとYouCompleteMeというVimのプラグインがインストール出来ません。

```bash
echo 'export PYTHON_CONFIGURE_OPTS="--enable-shared"' >> .bash_profile
```

```bash
source .bash_profile
```

# Reference
https://websetnet.net/ja/how-to-install-zlib-on-ubuntu-linux/

https://askubuntu.com/questions/1269492/ffi-h-no-such-file-or-directory-while-trying-to-install-docker-compose-on-ras

https://zoomadmin.com/HowToInstall/UbuntuPackage/libbz2-dev

https://ubuntu.perlzemi.com/blog/20200412174004.html

https://zoomadmin.com/HowToInstall/UbuntuPackage/libsqlite3-dev

https://qiita.com/barutou/items/80c31a7cdef930c75e90
[snyk-docs] 日本語版ドキュメント

**Snyk 日本語版ドキュメント**
**最終更新:** 2022-05-12

# Snyk User Documentation
#### Introducing Snyk
#### Getting started
#### Snyk CLI
● [Snyk CLI のインストールとアップデート](https://qiita.com/ToshiAizawa/items/c090cbd525e45cc5ae51) (Install or update the Snyk CLI)
#### Snyk API
#### Snyk Integrations

## PRODUCTS
#### Snyk Open Source
#### Snyk Code
#### Snyk Container
#### Snyk Infrastructure as Code

## USING SNYK
#### Snyk Broker
#### User and group management
● Authentication
● Setting up SSO for authentication
● Managing users & permissions
　○ [オーガニゼーションのユーザー管理](https://qiita.com/ToshiAizawa/items/eda9940dba419637725e) (Managing users in your organizations)
● Managing groups & organizations
● Notifications
● Managing settings
#### Fixing and prioritizing issues
#### Reports
#### Other tools
#### CLI Tool: Snyk-SCM-Contributors-Count

## SNYK INFO
#### Disclosing vulnerabilities
#### Product language support list
#### [Snyk における顧客所有データの管理](https://qiita.com/ToshiAizawa/items/e42665a6b50f464aae62) (How Snyk handles your data)

## SNYK TUTORIALS
● Getting Started
● Amazon Web Services
● Atlassian
● CircleCI
● Docker
● Dynatrace
● GCP
● GitHub
● Microsoft Azure
● Oracle Cloud Infrastructure
● Red Hat
● Snyk Apps
● SpringOne

:::note warn
【おことわり】 翻訳には十分な注意を払っていますが、個人として翻訳したもので、内容についての責任は負いません。最新の情報については原文をご確認ください。原文や訳文にある誤りの指摘やご質問は大歓迎です。
最終更新: 2022年5月12日
:::
サブルーチン。プロシージャ(手続き)・ファンクション(関数)。クラス・メソッド。たぶん、きっかけは変数をバグらせない進化

プログラミング言語の関数は「返却値の有無、引数の有無」の４種類。

ですが、僕自身の中では「関数」とは「数学の関数 y=f(x) 」と同義あり、返却値のないものを「関数」と呼ぶことに違和感を抱いていました。

:::note info
なぜそんな違和感を抱くのか？
それは僕がMSX BASICのサブルーチン生まれの、VB6/VBAのSub/Functionや、Delphiのprocedure/functionでも育ったこともあるからだったようです。
明確に「関数 y=f(x) じゃないものは、プロシージャや！！」と・・・
それはさておき・・・
:::

JavaScriptでいうところの関数を人に教えることになって、冒頭の「関数の４種類」を教えれば良いとは思いつつも、その後、オブジェクト指向にも展開していくだろうし、その時に関数とメソッドの違いをどう説明するんよ・・・と思いました。
そういえば、人に教える話として **サブルーチン。プロシージャ(手続き)・ファンクション(関数)。クラス・メソッド。の違い** を明確に意識できていなかったので、それらが生まれた **「変数を如何にバグらせないか」** のプログラミング言語の歴史的経緯を軸に、頭の整理をしてみたメモです。

---

# グローバル変数だけの世界：どこでもどんな処理でも変数触り放題

### サブルーチン：
同じ処理（ルーチン、ルーティーン）をするだけ。引数を渡すとかの考えはない。
処理の中で変数を変更するとすれば、その変数はグローバル的なもの。（関数でいうところの「副作用」）
（ぶっきらぼうにいうと、変数＝メモリ管理でいうと、アセンブラでやれることと変わらない。）

↓

:::note alert
なんでもグローバルやばい。人のところ勝手に触れちゃった
:::

↓

# 処理の単位で変数のスコープを限定させよう・・・処理（手続き・関数）の中の変数は、その外側への影響なくせるわ

### プロシージャ：手続き
処理の塊、処理結果の返却はしない
引数も取りうる。（引数なしの場合はサブルーチンと言える？）
副作用が生じるかどうかは、内容次第

### ファンクション：関数
関数、処理結果の返却をする
引数も取りうる
副作用が生じるかどうかは、内容次第

↓

:::note alert
処理途中の変数とか無くなったな。変数も構造体とかで「データの塊」はできてるけど・・・
・・・うーん、誰かがどっかで勝手に処理を呼び出したりして、まだ勝手に触れちゃう・・・
:::

↓

# そや、見えへんようにしたろ。触ってほしい処理だけ公開したろ

### クラスとメソッド：
変数とプロシージャとファンクションを隠蔽して塊にして、その塊の外側からは、変数の変更や処理を呼び出せないようにした。意図している公開した処理を呼び出してもらうことだけはできる。

---

# 言いながら・・・
やっぱり処理が遅くなったりするし、致し方ないこともあるから、 **やっぱ外から見たり変更できる変数も作れるようにしとこ** というのがあります。
それはそれで必要です。

ですが、ここまでの言語の進化（**変数を守れ！**）を理解せずに、変数を守るための手法を使わずに、簡単に見えちゃう・触れちゃうもので「お！手っ取り早いやん・・・」って使ってしまって、バグ・バグりやすいプログラムを作ってしまったり・・・

---

(これ以降のプログラミング言語の進化は勉強不足・・・)
(これらそれぞれで例となるプログラムがあると良いけどry)
Windows の SSH ターミナルといえば RLogin でしょ

# RLogin とは

Windows 用のターミナルソフト。
SSH だけではなく、telnet なども対応しています。
https://kmiya-culti.github.io/RLogin/

個人的におすすめなので、良いところを紹介しようと思います。

なお、筆者は他のターミナルソフトは Teraterm くらいしか知りません…。
しかもここ数年は全く使ってないです…。※RLogin で事足りるので
なのでその前提でお読みください。

## 複数サーバのログイン設定をタブごとに分けて登録できる
Teraterm では、複数サーバにログインする際には下記あたりの方法があるかと思います。

- 都度ホスト名 or IP アドレス、ポート番号、公開鍵、パスワードなどを入力する
- ホストごとに Teraterm マクロを記述

どちらもそれなりにめんどくさく、管理対象のサーバが増えるほど面倒くささが増大するかと思います。
しかし RLogin はデフォルトで下記のように複数のサーバ設定を登録できる仕組みがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531097/eb094316-1e99-e49e-779e-e68e4fddf9c8.png)

サーバのログイン情報をタブごとに分類しつつ事前登録することで、ログイン時は対象の設定をダブルクリックするだけでログインすることができます。
もちろん、踏み台サーバを経由した内部サーバへのログインも可能です。
その際は、踏み台サーバの設定を事前に登録した上で、踏み台を経由するサーバ設定時に下記の設定箇所から、踏み台サーバを選択する形になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531097/dc9306b3-cc61-4281-9bfa-63660b9d0d5d.png)

## 複数の公開鍵を登録できる
SSH 接続する際は公開鍵認証が一般的ですが、鍵の管理はめんどくさいですよね。
開発/ステージング/本番、オンプレ/クラウド で公開鍵を分けているけど、このサーバはどの鍵ペアでログインできるんだっけ？といった場合は、１つずつ試さなきゃいけなかったり、加えてパスフレーズもいくつかあると更にめんどくさかったりします。

そんなときに便利な機能として、<font color="Red">**サーバ設定に複数の鍵を登録しておき、登録した順序で一通りログインを試してくれる**</font>、なんていう素晴らしい機能があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531097/5f4ee0d2-0457-017d-2d5a-10fab4a1ea22.png)

認証キーリストの Type 列のチェックボックスで一時的に有効・無効を切り替えたり、Name 欄にわかりやすく名前を付けることができます。

## 複数タブを開ける＆任意タブへの同時送信機能がある
Screen や Tmux のように複数タブを分けて並べる機能があります。
Screen や Tmux だとログがぐちゃぐちゃになってしまいますが、この機能を使えばタブごとにそれぞれログを分けて保存できるので、とても良いです。
加えて、複数開いたタブのうちチェックボックスで指定したタブだけにコマンドを同時送信することが可能です。
これを利用することで、複数サーバへの同時オペレーションが効率化できます。
※もちろん対象サーバ間違いのリスクがあるので、十分注意して利用してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531097/ba54f5de-466a-2a40-f582-f1e5523b86de.png)

## ログイン設定の継承が可能
これが個人的に最も素晴らしい機能かと思うのですが、ログイン設定を継承しつつ一部を変更したログイン設定を作ることが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531097/baeb840f-36ca-ed8b-c7da-e3e311a7ddea.png)

上の図のように、継承する側で固有の設定のみ設定した上で、"その他オプションを継承" のプルダウンで継承される側のサーバ設定を選択できます。
サーバ設定を継承した場合は、その他設定箇所などでは下記のように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531097/bfca4d6d-e43b-a8de-7d5f-5d4332aeda35.png)

この機能を利用することで、例えばベースとなる環境ごと(開発/ステージング/本番) でターミナルの背景色を分け、サーバの環境ごとに継承するサーバ設定を分けることで、<font color="Red">**背景色でサーバ環境を分けて注意喚起しつつオペミスのリスクを下げる**</font>、といった使い方が可能となります。

## まとめ
RLogin を紹介させていただきました。
その他、Terraterm にあるだいたいの機能(ログ自動保存含む) は RLogin でもカバーできるので、試してみてはいかがでしょうか？

なお筆者はその他ターミナルソフトに詳しくないため、別でもっと良いターミナルソフトなどがあれば教えていただけると嬉しいです！

読んでいただきありがとうございました。
PRML式(6.13)~(6.22)

# 新たなカーネルを構築するための方法の式
PRMLの式(6.13)~(6.22)が成立することを確認
## (6.13)
```math
\begin{align}
ck_1(\boldsymbol{x},\boldsymbol{x}') &= c\phi_1(\boldsymbol{x})^T \phi_1(\boldsymbol{x}')\\
&= \sqrt{c}\phi_1(\boldsymbol{x})^T \sqrt{c} \phi_1(\boldsymbol{x}')\\
\end{align}
```
$\phi(\boldsymbol{x})=\sqrt{c}\phi_1(\boldsymbol{x})$とおけば新たなカーネルを構築できる。

## (6.14)
```math
\begin{align}
f(\boldsymbol{x})k_1(\boldsymbol{x},\boldsymbol{x}')f(\boldsymbol{x}') = f(\boldsymbol{x})\phi_1(\boldsymbol{x})^T\phi_1(\boldsymbol{x}')f(\boldsymbol{x}')
\end{align}
```
$\phi(\boldsymbol{x})=f(\boldsymbol{x})\phi_1(\boldsymbol{x})$とおけばよい。

## (6.15)
```math
\begin{align}
q(k_1(\boldsymbol{x},\boldsymbol{x}')) &= q(\phi_1(\boldsymbol{x})^T \phi_1(\boldsymbol{x}'))\\
&= \sum_{i} \alpha_i (\phi_1(\boldsymbol{x})^T \phi_1(\boldsymbol{x}'))^i \\
&= \alpha_1 \phi_1 (\boldsymbol{x})^T \phi_1(\boldsymbol{x})+...+\alpha_N \phi_1(\boldsymbol{x})^{(N)T} \phi_1(\boldsymbol{x})^{(N)}
\end{align}
```
ただし$\phi_1(\boldsymbol{x})^{i}$で$\phi_1(\boldsymbol{x})$の各要素を$i$乗したベクトルを表す。また$\alpha_i$は係数。$\phi(\boldsymbol{x})=(\sqrt{\alpha_1}\phi_1(\boldsymbol{x})^T ... \sqrt{\alpha_N}\phi_1(\boldsymbol{x})^{(N)T})^T$とすればよい。

## (6.16)
$k_1(.,.)$のグラム行列を$K_1$としたとき$k(.,.)$のグラム行列$K=\exp(K_1)$も半正定値となるからカーネルの条件を満たす。
参考：https://math.stackexchange.com/questions/73126/if-a-is-symmetric-then-the-matrix-exponential-ea-is-positive-definite

## (6.17)
$k_1(.,.),k_2(.,.)$のグラム行列をそれぞれ$K_1, K_2$として$k(.,.)$のグラム行列$K=K_1+K_2$である。$\boldsymbol{x}^T K_1\boldsymbol{x} \geq 0, \boldsymbol{x}^T K_2\boldsymbol{x} \geq 0$ より$\boldsymbol{x}^T (K_1 + K_2) \boldsymbol{x} \geq 0$も成立するので$K$は半正定値行列であり、カーネルの条件を満たす。

## (6.18)
$k_1(.,.),k_2(.,.)$のグラム行列をそれぞれ$K_1, K_2$として$k(.,.)$のグラム行列$K=K_1\otimes K_2$である。したがって$K$も半正定値行列であり、カーネルの条件を満たす。
$\otimes$はアダマール積、半正定値行列同士のアダマール積も半正定値となる。
参考：http://sigmagic.net/math/hadamard-prod/

## (6.19)
$\phi_{new}(\boldsymbol{x})=\phi_3(\phi(\boldsymbol{x}))$とすればよい。

## (6.20)
Aは対称な半正定値行列のためグラム行列である。
参考：https://mathlandscape.com/positive-definite-matrix/#toc5

## (6.21),(6.22)
(6.17),(6.18)とほぼ同じなので省略。
[Swift] .filter{ }.firstのパフォーマンスについて


## 背景

最近、データを取得してきて、その中で``条件に合う要素を取り出したい``みたいなことがよくあり、実際にやり方をググってみるとfilter{}.firstという構文を見つけました。
しかし、SwiftLintを導入しているプロジェクトでしたので、下記の警告が吐かれてしまいました。

![スクリーンショット 2022-03-15 3.42.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552896/922f87ca-ef58-ae59-2622-ce6c28fb6fd1.png)


```
First Where Violation: Prefer using `.first(where:)` over `.filter { }.first` in collections. (first_where)
```
これは警告文のところだけ訳すと、
`` `.filter { }.first` よりも `.first(where:)` を使用することを推奨します。``

まさに、直接的にfilter{}.firstはよくないからfirst(where:)を使ってねと教えてくれます。（SwiftLintは優秀ですね。。）

どうやらfilter{}.firstは条件に合致するデータを見つけても配列を最後までなめてしまうようです。
これはコーディング上パフォーマンスがあまりいいコードとは言えません。


## 処方箋

ではどのようにして実装すれば良いのでしょう。
警告でもあるように推奨してくれている``first(where:)``という構文を使用します。

実際に実装してみます。

### before
```swift
let hoge: [String] = ["aaa",　"bbb",　"ccc", "ddd"]

let foo = hoge.filter({ $0.hasPrefix("b") }).first // foo == "bbb"
```



### after
```swift
let foo = hoge.first(where: { $0.hasPrefix("b") }) // foo == "bbb"
```

beforeの方がコードの読みやすさを感じる方もいるかもしれませんが、
afterの方が何よりパフォーマンスが良いので積極的に使っていきましょう。
Atcoderサンプルテストを自動化～Pythonバージョン～

## 概要
テストの自動化をこの記事を参考にpython用に作成してみました。
便利…。

https://qiita.com/akidon0000/items/f5bf68511e594d9be60d

ターミナルで打つと
```bash
rn a
```

```bash
---------------情報----------------------
パス : /c/Programming/python/atcoder/abc/191
大会レベル : abc
大会番号 : 191
問題番号 : a
URL : https://atcoder.jp/contests/abc191/tasks/abc191_a

[INFO] online-judge-tools 11.5.1 (+ online-judge-api-client 10.10.0)
[INFO] 2 cases found
[WARNING] GNU time is not available: time

[INFO] sample-1
[INFO] time: 0.035234 sec
[SUCCESS] AC

[INFO] sample-2
[INFO] time: 0.033582 sec
[SUCCESS] AC

[INFO] slowest: 0.035234 sec  (for sample-1)
[SUCCESS] test success: 2 cases
```

ただし自分用のテストケースはまだ非対応なので今後対応予定

詳細は元記事を参照してほしいのでこちらでは実際のコードだけ記載します。

### script.sh
```script.sh
#!/bin/sh
# 第一引数 問題番号
#  cd abc/190

# 現在のパスを取得
path=$(cd $(dirname $0); pwd)

# コンテストレベル
contestLevel=${path##*atcoder/}
contestLevel=${contestLevel%/*}

# コンテスト番号
contestNumber=$(echo "$path" | sed -e 's/.*\/\([^\/]*\)$/\1/')

# 問題番号
questionNumber="$1"

# AtCoderのURL
URL="https://atcoder.jp/contests/${contestLevel}${contestNumber}/tasks/${contestLevel}${contestNumber}_${questionNumber}"

# サンプルデータダウンロード
oj login "${URL}"
oj dl "${URL}"


echo ""
echo "---------------情報----------------------"

echo "パス : "${path}
echo "大会レベル : "${contestLevel}
echo "大会番号 : "${contestNumber}
echo "問題番号 : "${questionNumber}
echo "URL : "${URL}
echo ""

# サンプルテスト
oj t -c "python ${questionNumber}.py"

# 新しくできたファイルを削除
rm -f a.out
rm -rf test
```

### coppy.sh
```coppy.sh
#!/bin/sh

# 第一引数 コンテストレベル
# 第二引数 コンテスト番号
# sh coppy.sh abc 191

# 引数が正しく入力されていない場合
if [ ! $# -eq 2 ];then
  echo """
  -------ERROR-------
  コンテストレベルもしくは番号が正しく入力されていません
  AtCoder ABC 第190回コンテストなら
  sh coppy.sh abc 190
  と入力してください
  """
  exit
fi

# 現在のパスを取得 
path=$(cd $(dirname $0); pwd)

# コンテストレベル
contestLevel="$1"

# コンテスト番号
contestNumber="$2"

# コピー 上書き時警告表示
if [ -e ${path}"/"${contestLevel}"/"${contestNumber} ];then
  echo "同じ名前のファイルが以下のパスで見つかりました"
  echo ${path}"/"${contestLevel}"/"${contestNumber}
  read -p "上書きしますか？ (y/N): " yn
  case "$yn" in
    [yY]*) rm -rf ${path}"/"${contestLevel}"/"${contestNumber}
              cp -r coppy ${contestNumber}
              mv ${contestNumber} ${contestLevel}
              echo "完了しました";;
    *) echo "キャンセルしました";;
  esac
else
  cp -r -i coppy ${contestNumber}
  mv ${contestNumber} ${contestLevel}
  echo "完了しました"
fi
```

## 最後に
あとはエイリアスの設定とかして終わり
```bash
vi ~/.bashrc
# 追加
alias rn='sh script.sh'

# 反映
source ~/.bashrc
```
便利なのでぜひ使ってみてください。
(個人共有用)vbaで他のbookに値だけ張り付けるコード

#vbaで他のbookに値だけ張り付けるコード

```copyBook
Option Explicit
 
Sub copyBook()
   Dim objSheet As Worksheet
   Dim wb As Workbook
   Dim ws As Worksheet

   ' 貼り付け先ワークブックを作成
   Set wb = Workbooks.Add
   ' 貼り付け元ブックの全シートを 1 つずつループして処理する
  For Each objSheet In ThisWorkbook.Worksheets
      Set ws = wb.Sheets(wb.Sheets.Count)
      '名前同じにしたいなら以下の'外す
      ' ws.Name = objSheet.Name
      
      ' 貼り付け元の全ての値を貼り付け先ワークシートに張り付ける(値だけ)
      ws.Range(objSheet.UsedRange.Address).Value = objSheet.UsedRange.Value
      Set ws = Nothing
      
      If ThisWorkbook.Sheets.Count <> wb.Sheets.Count Then
          ' 貼り付け先ワークシートを作成
          wb.Sheets.Add After:=wb.Sheets(wb.Sheets.Count)
      End If
  Next
End Sub

```
Railsの開発環境でAWSサービスを使うとminioの設定とAws.configの競合が発生する

# まとめ

ローカルの開発環境でminioを使いながらAWSのcredentialを同時に扱うことは難しそう

なので、各サービスのクライアント生成時にcredential情報を渡すことになるかも

`config/initializers/aws.rb`

```rb
creds = Aws::Credentials.new(
  Rails.application.credentials[:aws][:access_key_id],
  Rails.application.credentials[:aws][:secret_access_key]
)

region = Rails.application.credentials[:aws][:region]

Aws.config.update(
  region: region,
  credentials: creds
)
```

と宣言しておき

```rb
    def client
      conf = Aws.config
      access_key_id_sym = Rails.env.development? ? :cog_access_key_id : :access_key_id
      secret_access_key_sym = Rails.env.development? ? :cog_secret_access_key : :secret_access_key

      creds = Aws::Credentials.new(
        Rails.application.credentials.dig(:aws, access_key_id_sym),
        Rails.application.credentials.dig(:aws, secret_access_key_sym)
      )

      @cognito_client ||= Aws::CognitoIdentityProvider::Client.new(
        credentials: creds,
        region: conf[:region],
        http_wire_trace: Rails.env.development?
      )
    end
```

こんな感じ？

`credentials.yml.enc` とかで、 `cog_access_key_id` などを宣言しておき、それを直接クライアント生成時に突っ込むと言う流れ

もっといい方法があるかもしれない

# 何が起きた？

`storage.yml` で設定していた minioを利用するための設定、特にcredentials部分がうまく動作しなかった。

```yml
minio:
  service: S3
  access_key_id: minio
  secret_access_key: minio123
  endpoint: "http://minio:9000"
  region: ap-northeast-1
  bucket: test
  force_path_style: true
```

access_key_idを直接設定していたはずなのに、なぜか `Rails.application.credentials[:aws][:access_key_id]` を参照して、minioに接続ができない。

`docker-compose.yml` でminioのcredentialsを設定しているので、そちらを変更することも考えたが、キーを平文で入れることになるため断念。

仕方なく、それぞれのAWSクライアント側で開発環境は対応することとした。

これしか思いつかなかったなぁ
minioのクライアント生成部分に手を加える方法があるなら、それが一番簡単かもしれないのだけどね。
javascriptで@アットマークなどの特殊文字を含む場合のデータ参照でエラーが出る時の備忘録

ニッチな事例ですいませんが、忘れててすごくハマってしまったので、同じように困った方のために残しておきます。入れ子としては良くあると思いつつ、何度か表現を忘れてしまう事がありましたので。

Javascriptで、例えばJSONデータを取得する際に、
「@」などの特殊な記号を含むデータ項目があった際に、
どういった表現（エスケープ的な方法）があるかを記載しておきます。

例えばjsonデータで、下記のようなネスト（階層化）されたものを
参照した際に、最下層のデータ項目にアクセスする際に
【親.子.孫】といった記載をする場合があると思います。（ドットでつなぐ）

## 【課題の例】
`・大カテゴリー`
`・子カテゴリー`
`・孫（値）`　★ここのデータにアクセスしたい
　　　　データ項目名に「@が含まれている」`@time`　など

### 【失敗例】

```

//パターン1
json.oya.ko.@mago;

//パターン2
json.oya.ko.[@]mago;

json.oya.ko.["@"]mago;

```
上記では、「@」は文字列扱いしてくれず、エラーになります。

### エラーが出ない例（ドットを使わない）

```
json.oya.ko["@mago"];
```

**上記であれば、文字列としてみてくれます。**

しくじりポイントとしては、最終階層の中でどうにか表現しようとして、
失敗したことです。また、ドットで参照ばかりしていたので、
この入れ子的記載を忘れてしまった事です。

ちなみに、こちらは実際に、
「アットマークを含むデータ項目名」に出会い、
困っていたのですが、良い検索方法(Google)も思いつかず・・・

※政府が出しているオープンデータ（統計データ）にも
　こうした特殊文字があります。

JSベテランからしたら当たり前ではあると思いますので、
是非同じ悩みにあったJS初級～中級位の方のお役に立てたらと！


``
for文について

## はじめに
JavaScriptの復習をしていました。
自分用のメモとして投稿します。
## for文とは
JSで繰り返し処理を行う際に使う構文です。
回数が決まった繰り返し処理に向いています。

書き方は以下のように
```javascript
for( 初期化; 継続条件; 最終式; ){
  // 繰り返す処理の内容
}
```

for文のカッコには３つの式を;(セミコロン)で区切って書きます。
繰り返し処理が始まる前に「初期化」が１回だけ実行されます。
「継続条件」が真の間繰り返し処理が実行されます。
「最終式」は処理が終わった後に毎回実行されます。
## 例

```javascript
for( let cnt = 1; cnt <= 10; cnt++) {
  console.log('ハロー');
}
```

まずletを用いて変数cntを定義しています。
そして変数cntを用いてループする条件を指定。
cnt++は変数cntを1増やすという意味です。
「++」は変数の値を１増やすという意味のインクリメント演算子といいます。
この最終式のcnt++は処理が１回終わるごとに呼び出されます。
つまり、変数cntは処理が１回実行されると１増えるということです。

継続条件に　cnt　<= 10　と記述があるので、cntが１０になるまでループ処理が続きます。つまり10回処理が行われます。

以下の記述で処理を実行すると

```javascript
let count = 1
for (let cnt = 1; cnt <= 10; cnt++) {
  console.log(`${count}回目の出力`)
  count +=  1
}
```
![for output1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199242/39b0d68c-8d0c-ab80-b82e-3e2b58cdecdf.png)

上記の結果が表示されました。

## おわりに
間違いなどがありましたらコメントいただけると幸いです。
よろしくお願い致します。
ASP.NET Core開発者ロードマップを日本語訳しました

# はじめに
[Moien Tajik](https://github.com/MoienTajik)さんという[.NET Foundation](https://github.com/dotnet-foundation)のメンバーであるすごいお方が書かれた**AspNetCore-Developer-Roadmap**というものがあります。
要は、ASP.NET Coreの開発者が学ぶべき道を示したロードマップです(そのまま)。

# 日本語化しました
こちらです！
![aspnetcore-developer-roadmap.ja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529362/78c33b47-2ecf-72dd-8f51-ec18bff7db32.png)

こう眺めてみると、自分自身が知らない知識も多々あって身の引き締まる思いです・・・。
是非勉強の指針などにお役立てください！


# 本家はこちら
是非本家のリポジトリも覗いてみてください。

https://github.com/MoienTajik/AspNetCore-Developer-Roadmap


# 補足
もし、日本語訳などで不自然なところがありましたら、コメントなどで教えていただけると幸いです。
[OutSystems]Professional DevOps Engineerのサンプル問題について解説 1/2(#1-#5)

Professional DevOps Engineerは2022/3に追加された試験。名前通り、OutSystemsでCI/CDを始めとするDevOpsを実践するための知識が問われる。

試験情報のPDFと一緒にダウンロードできるサンプル問題を解説する。
全部で10問で、この記事では1問目-5問目が対象。

6問目-10問目の記事: [Professional DevOps Engineerのサンプル問題について解説 2/2(#6-#10)](https://qiita.com/jyunji_watanabe/items/3767f1a8bad2bf64eabe)

サンプル問題は、
https://www.outsystems.com/learn/certifications/
の、「Professional DevOps Engineer」項目のリンク「Exam Details」でダウンロードできる資料から。「Sample Exam」がついている方のファイルが該当する。

# 1 IT Team
ITユーザーのTeamについての問題。
ITユーザーは開発者・運用者のアカウント。Service StudioやService Centerへのログインに使う。
Teamというのは、いくつかのアプリケーションに対してまとめてITユーザーの権限を設定するもの。

各選択肢を見ていくと、

A: ○（IT Teamは、開発者や運用者のITユーザーのグループに対して、複数のアプリケーションに対してまとめて権限を与えるもの）
B: ○（IT ユーザーは複数のTeamに所属できる）
C: ×（アプリケーションは複数のTeamに所属できない）
D: ○（Aと同じ理由）

設問は正しくないものを聞いているので、Cが正解。

# 2 ITユーザーの権限レベル
OutSystemsの監視データにアクセスするには、「Monitor and Add Dependencies（監視と依存関係の追加）」が必要。

[環境に対する権限レベル](https://success.outsystems.com/ja-jp/Documentation/11/Managing_the_Applications_Lifecycle/Manage_IT_Users/Understand_the_Permission_Model_for_IT_Users#.E7.92.B0.E5.A2.83.E3.81.AB.E5.AF.BE.E3.81.99.E3.82.8B.E6.A8.A9.E9.99.90.E3.83.AC.E3.83.99.E3.83.AB)の「Monitor and Add Dependencies（監視と依存関係の追加）」の項を参照。

というわけで選択肢Bが正解。

# 3 Consume REST APIのURL設定
Consume REST APIは、外部のREST APIをOutSystemsのServer Actionのように呼び出すことができる機能。
問題は、環境（開発・QA・本番のようなOutSystemsの環境）ごとに、テスト目的で異なるURLにアクセスさせたいが、どうすればいいか？　というもの。

こういうときは、Service Centerを使い、環境別にホスト部分を上書きする。

具体的には、以下のようなConsume REST APIがあるとすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/c205454a-0254-78e4-dc69-7e3c1802fca7.png)

Service Centerで該当モジュールのページを開き、Integrationsタブ下のConsumed REST APIsに表示されるREST APIのURL部分（下図の黒く塗りつぶした部分）を上書きできる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/583c3b6e-7117-a38b-a1d6-9d2a60074c99.png)

Service Studioで定義したBase URLは、URLのデフォルト値として扱われる。環境内でService Centerで上書きするときに設定する項目名はEffective URLと呼ぶ。

上記の説明に対応する選択肢はA。

# 4 デプロイ計画の再利用
デプロイ計画は、LifeTimeで、アプリケーションをある環境から別の環境にリリースするために作るアプリケーションの一定バージョンのセット。
デプロイはデプロイ計画に従って行われる。

[デプロイ計画を再利用する](https://success.outsystems.com/ja-jp/Documentation/11/Managing_the_Applications_Lifecycle/Deploy_Applications/Deployment_Plans#.E3.83.87.E3.83.97.E3.83.AD.E3.82.A4.E8.A8.88.E7.94.BB.E3.82.92.E5.86.8D.E5.88.A9.E7.94.A8.E3.81.99.E3.82.8B)に記述がある。

手順説明の中で、デプロイ計画を再利用する操作の過程で

> ポップアップウィンドウで、新しい計画のソース環境とターゲット環境を選択します。

とあるので、ソース環境とターゲット環境は変更できる。同じであるときのみ可能とする選択肢Bは×。

> ［Reuse Plan］操作は、中止されていない完了済みのデプロイ計画に対してのみ実行できます。中止された計画に対しては、［Retry Plan］操作を使用してください。

とあるため、中止された計画に対して実行できるとしている選択肢Aも不可。

> 任意のソース環境とターゲット環境を選択できますが、ソース計画に含まれるアプリケーションが1つ以上ソース環境に含まれている必要があります。

とあるため、ソース環境に「全ての」アプリケーションが含まれていなければならない、とする選択肢Cも誤り。

というわけで残ったDが正解。

# 5 CI/CD パイプラインの環境構成
[OutSystemsによる継続的デリバリーパイプラインの構築](https://success.outsystems.com/ja-jp/Documentation/How-to_Guides/DevOps/How_to_build_an_OutSystems_continuous_delivery_pipeline)に、OutSystemsが推奨するパイプライン構成（なんと5環境構成。随分贅沢な構成）がある。

Acceptance環境では、

> 通常のローコード開発インフラのQuality Assurance環境と同じように、この環境でリリース候補版の手動テストや探索的テストを行うことができます。

とあるように、手動のテストを行うので、選択肢Aが正解。
【Oracle Cloud】ボリュームグループ単位でのクロスリージョン・レプリケーションの設定


# 1. はじめに
これまでOracle Cloud Infrastructure(以下OCI)ではクロスリージョン・レプリケーションはボリューム単位のみ設定可能でしたが、2022年1月18日よりボリュームグループ単位で他のリージョンへの自動非同期レプリケーションの設定が可能になりました。本稿ではOCI でのボリュームグループ単位でのクロスリージョン・レプリケーションの設定方法について記載します。
# 2. ボリュームグループレプリケーションとは
ボリュームグループレプリケーションを有効にすると、設定したボリュームグループレプリカがターゲットリージョンに自動的に作成されます。このボリュームグループのレプリカは、Point in Timeで一貫性のあるソースボリューム内のブロック及びブートボリュームのレプリカになります。また、このレプリカは非同期の自動レプリケーションとなり、各レプリケーションの更新時間の間隔はソースグループの変更率によって異なりますが、通常では30分以内となります。
また、複製されたレプリカは、そのままの状態では使用できず、アクティベーションプロセスが必要になります。アクティベーションにより、ターゲットのディスク領域に1分以内でディープクローンが作成され利用可能な状態になります。

**- ボリュームグループとは**
https://docs.oracle.com/ja-jp/iaas/Content/Block/Concepts/volumegroups.htm
**- クロスリージョン・レプリケーションとは**
https://docs.oracle.com/ja-jp/iaas/Content/Block/Concepts/volumereplication.htm
# 3. 設定手順
以下3-1-1 or 3-1-2のいずれかでボリュームグループレプリケーションを有効化します。

**3-1-1. 新規ボリュームグループの作成時にボリュームグループレプリケーションを有効化する**

[ストレージ]->[ボリュームグループ]->[ボリュームグループの作成]を選択し、[クロス・リージョン・レプリケーション]のセクションで[非同期クロス・リージョン・ボリュームレプリケーションを有効にします]で[オン]を選択、[ターゲット・リージョン]、[非同期ドメイン]をそれぞれ選択し、[ボリューム・グループ・レプリカ名]を入力します。
コストに関連する注意事項の箇所で[確認]をチェックし、サマリ画面で[作成]をクリックします。
ボリュームグループが作成されて使用可能になると、すぐにレプリケーションが開始されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2592805/a49413c6-af25-438c-5707-582d6012b5df.png)
**3-1-2. 既に作成してあるボリュームグループに対して、ボリュームグループレプリケーションを有効化する**

[ストレージ]->[ボリュームグループ]->編集したいボリュームグループをクリックし、[ボリュームグループの詳細]画面から[編集]をクリックします。
[クロス・リージョン・レプリケーション]のセクションで[非同期クロス・リージョン・ボリュームレプリケーションを有効にします。]を[オン]を選択、[ターゲット・リージョン]、[非同期ドメイン]をそれぞれ選択し、[ボリューム・グループ・レプリカ名]を入力します。コストに関連する注意事項の箇所で[確認]をチェックし、サマリ画面で[変更の保存]をクリックします。
ボリュームグループが作成されて使用可能になると、すぐにレプリケーションが開始されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2592805/a6018243-9ac9-912e-eed9-129855c80434.png)

**3-2-1. ターゲット領域でレプリカボリュームグループをアクティブ化する**
ターゲットリージョンに移動し、[ブロックストレージ]->[ボリューム・グループ・レプリカ]のアクティブ化したいレプリカの三点ボタンをクリックし、[アクティブ化]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2592805/e14e11a4-1949-9773-382f-54d1f4dbe68a.png)
3-2-2. 確認画面がでますので[確認]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2592805/98933219-31ca-734e-8c7b-e1567e9c8ca8.png)
3-2-3. ボリューム・グループ・レプリカのアクティブ化画面でコンパートメントを選択し、[ボリューム・グループ名]を入力し、アクティブ化をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2592805/87e004cc-80a0-dbf6-fb35-5d87354f20b5.png)
3-2-4. 該当のボリュームグループレプリカは、約1分以内に[使用可能]になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2592805/328c28c8-36a2-ea4c-c4bd-13d3f3ea2c68.png)
以上、ボリュームグループのレプリカ作成からアクティブ化までの流れとなります。
# 4.その他情報
その他、ボリュームグループレプリケーション概要、制限事項、考慮事項等の情報に関しては以下のマニュアルを参照ください。
https://docs.oracle.com/ja-jp/iaas/Content/Block/Concepts/volumegroupreplication.htm
aptコマンドによるパッケージ更新メモ

# はじめに
__■2022/03/16修正
　元々```dist-upgrade```を使用していましたが、```full-upgrade```の方が新しいので変更しました。
　併せてコマンドの解説も修正しました。__

筆者の環境は以下のとおりです。
　・Windows10にてWSL2でUbuntu20.04LTSを使用(ロケールはja_JP.utf8)
　・Windows Terminalを使用

上記環境での```apt```コマンド実行メモです。
あくまで筆者が通常実行しているコマンドのみの記載になります。

その他のコマンドや詳細情報については```man apt```や以下の公式ドキュメントを参照ください。

https://ubuntu.com/server/docs

もしくは、以下のWikiを参照ください。

https://ja.wikipedia.org/wiki/APT

## aptコマンド実行編
結論から書きます。
以下が実行しているコマンドになります。
__※各コマンドの意味が分からない方はコピペで実行しないでください。__
(実行した結果について責任を負いかねます)

```bash
 sudo apt update && sudo apt upgrade -y && sudo apt full-upgrade -y && sudo apt autoremove -y && sudo apt autoclean -y
```

## 解説編
### apt以外のLinuxコマンド共通基礎的な部分
* ```sudo```について
　スーパーユーザー（rootユーザー）の権限でコマンドを実行します。
　普段Windowsをそのまま使っていると意識しないかもしれませんが、
　Linuxだと色々なもの(例えばコマンドの実行など)に「権限」が関係してきます。
　別の記事を書くレベルになるので大幅に省略しますが、
　「管理者権限を持つ一番偉いユーザでコマンドを実行しますよ」ということだと思ってください。

* ```&&```について
　「AND制御演算子」と呼ばれる演算子で
　「&&で繋ぐ前のコマンドが成功したら次を実行」します。
　コマンドを連結するモノだと思ってください。

* ```-y```について
　Linuxではコマンド実行中に「本当に実行しますか？」と問われることが度々あります。
　```続行しますか? [Y/n]```みたいなやつです。
　```-y```オプションを付けて実行することで全て「yes」で実行します。

* おさらい
　最初に「コピペで実行しないでください」と書いた理由は
　「よく分からないコマンド」「複数」を「管理者」が「はいはい」言いながら
　実行することになるからなんですね。(~~職場風景でもありそうで怖いですね~~)
　「よく分からないコマンド」の部分については次で解説します。

### aptコマンドの部分
> aptコマンド実行編

に記述したコマンドは以下の5つを実行しています。
1. apt update
 インストール可能なすべてのパッケージに関する詳細情報を表示します。
 (ここまでなら実際にインストールされません、ただ表示されるだけです)

2. apt upgrade
 パッケージを更新します。
 (上記で一覧を確認し、実際にインストールするフェーズになります)

3. apt full-upgrade
　ディストリビューションのアップグレードを行います。
　アップグレード時に依存関係を解析してシステムに必要なパッケージを
　追加インストールし、不要なパッケージを削除します。
　(ディストリビューション自体のアップグレードになるため、
　構築している環境に不安がある場合は安易に実行しないでください)

4. apt autoremove
　パッケージの更新に伴い必要なくなったパッケージを削除します。

5. apt autoclean
　キャッシュされているが、インストールはされていないdebファイルを削除します。
　
　まず、「deb」ファイルとは何かと言う話ですが、
　Windowsではexe形式のファイルで何かをインストールするように
　.deb(Debian系)や.rpm(RedHat系)形式でインストールすることができます。
　つまり、パッケージをインストールする時に
  　```sudo apt install -y ◯◯.deb```というようにインストールできます。
　
　そして、パッケージをインストールすると
　APTキャッシュとしてパッケージの情報が記録されていきます。
　
　この情報はファイルが削除された後も残ります。
　(アプリを削除しても情報が残るようなイメージ)
　蓄積されると当然、ディスク容量を圧迫します。
　
　なのでこのコマンドを実行すると
　上記の領域を開放することができます。

## 補足
更新した後はOSの再起動をしないと基本的に更新完了しません。
ですので、各自の環境に合ったコマンドを実行してください。
(ここは、コマンドなど正確に調べてください)

```bash
# 例：Linuxの本番環境の場合(夜中の2:30に再起動をかける)
$ sudo shutdown -r 02:30

# 例：wslの再起動をする場合
$ wsl -t Ubuntu◯◯
```
wslの基本的なコマンドについては以下を参照してください。

https://docs.microsoft.com/ja-jp/windows/wsl/basic-commands

__また、本記事ではコマンドを繋いで全て「yes」で実行するようにしていますが、
本番環境で実行する場合は、意味を理解した上で必ず1コマンドずつ実行し、
目視確認しながら「yes」も手入力するようにすることを強く推奨します。__

## 備考
```apt```はAdvanced Package Tool (アドバンスド パッケージ ツール)の略らしいです。