OmniAICreator/Qiita-1.07M huggingface dataset:
paizaラーニング レベルアップ問題集 ソートメニュー応用編 JavaScript 辞書順

辞書順 (paizaランク C 相当)

https://paiza.jp/works/mondai/sort_advanced/sort_advanced__problems_speedup_step2

JavaScriptで解いてみました。

問題文の例で、abc, aa, a, abの四つが出てきていますが、アルファベット小文字 3 文字で作れる文字列なので、aaやa,abは考える必要はありません。辞書順で最初はaaaから、最後はzzzまでを考えれば良いです。

アルファベット小文字 3 文字で作れる文字列を全パターン作成し、辞書順にソートしてから k 番目の文字列を出力します。
```javascript:JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const k = Number(lines[0]);
const alphabet = "abcdefghijklmnopqrstuvwxyz";
let words = [];
  for (let c1 = 0; c1 < alphabet.length; c1++) {
    for (let c2 = 0; c2 < alphabet.length; c2++) {
      for (let c3 = 0; c3 < alphabet.length; c3++) {
        let word = "";
        word += alphabet[c1];
        word += alphabet[c2];
        word += alphabet[c3];
        words.push(word);
      }
    }
  }
words.sort();
console.log(words[k - 1]);
```
***
別解ですが、法則を見つけ、ソートなしで解きました。
二十六進法として考えました。

kの二十六進法のそれぞれの位の値を、
アルファベット３文字の左の位、真ん中の位、右の位として、
それぞれの値を、アルファベット配列のインデックスとすれば、
求めたいアルファベットが得られます。
```javascript:別解
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const k = Number(lines[0]);
const k26 = k.toString(26);//二十六進法に変換

const alphabet ="abcdefghijklmnopqrstuvwxyz";

//それぞれの位の値を十進法に戻し、アルファベット配列のインデックスにする

//左の文字
const left = alphabet[parseInt(k26[0], 26)];

//真ん中の文字
const center = alphabet[parseInt(k26[1], 26)];

//右の文字
const right = alphabet[parseInt(k26[2], 26) - 1];

console.log(left + center + right);
```

***
別解2

`.toString(26)`や`parseInt(k26[0], 26)`を使わずに解きました。
十進法が、百の位、十の位、一の位が0~9の値をとり、10で繰り上がるように、
二十六進法として、アルファベット小文字 3 文字を、左の文字の位、真ん中の文字の位、右の文字の位が0~25の値を取り、26で繰り上がる、と考えます。
```javascript:別解2
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const k = Number(lines[0]);
const alphabet ="abcdefghijklmnopqrstuvwxyz";

//右の文字
const right = alphabet[k % alphabet.length - 1];//アルファベット文字数26ごと -1

//真ん中の文字
const centerPlace = Math.trunc(k / alphabet.length);//真ん中の文字の位の値
const center = alphabet[centerPlace % alphabet.length];//アルファベット文字数26ごと

//左の文字
const leftPlace = Math.trunc(centerPlace / alphabet.length);//左の文字の位の値
const left = alphabet[leftPlace];//商だけ、余りは必要ない。k<=26^3より。

console.log(left + center + right);
```
右の文字の位は、1からはじまり25まで、26になったら繰り上がるので0になります。以降、0~25を繰り返します。
kをアルファベット26文字で割ったあまりを、アルファベット配列のインデックスで考えるので-1すれば求められます。

真ん中の文字の位は、0からはじまり、右の文字の位から26ごとに繰り上がって来ます。まず"kをアルファベット26文字で割った商"で、右の文字の位の繰り上がり回数を求めます。この商も、26ごとに繰り上がるので、さらにアルファベット26文字で割った余りで求められます。0からはじまっているので、そのままアルファベット配列のインデックスとして考えられます。

左の文字の位は、0からはじまり、真ん中の位から26ごとに繰り上がってくるので、
真ん中の位の"kをアルファベット26文字で割った商"が、何回繰り上がってきたか、アルファベット２６文字で割った商で求められます。
左の文字の位の値は,kの条件(1 ≦ k ≦ 17,576 (= 26^3 ))より、最大で25なので、繰り上がりはありませんから、余りを求める必要はなく、商だけで大丈夫です。
git push heroku masterで失敗後heroku loginでも失敗した場合

# エラー内容
Railsチュートリアル第9章の最後でgitにpush後、herokuにデプロイしようとしたら以下のようなエラーが発生。
```
$ git push heroku master
Username for 'https://git.heroku.com': ~~~
Password for 'https://~~~@git.heroku.com': 
remote: !       WARNING:
remote: !       Do not authenticate with username and password using git.
remote: !       Run `heroku login` to update your credentials, then retry the git command.
remote: !       See documentation for details: https://devcenter.heroku.com/articles/git#http-git-authentication
fatal: Authentication failed for 'https://git.heroku.com/~~~.git/'
```
エラー文に`heroku login`を実行して下さいと書いてあるので
```
$ heroku login
```
を実行したがherokuにログインできない。
# 解決
調べてみると、`heroku login --interactive`を実行してみると解決できるかも。
```
$ heroku login --interactive
```
ログイン情報を打ち込んで無事ログイン！その後
```
$ git push heroku master
```
で無事デプロイ完了！
# 参考記事
https://qiita.com/yuichisan65/items/230f8946aa5f819e7c76

https://qiita.com/yadon/items/db3ec786ec410990cec6
【Swift】初心者による優しいデリゲート

# はじめに
:::note warn
間違いがあるかもしれないです。
間違っていたらコメントください
:::

delegateを使ってViewに通知する方法を学んだので記録しておきます。

# 実装
```swift:ViewController
import UIKit

class ViewController: UIViewController, SampleModelDelegate {

    private let sampleModel = SampleModel()

    override func viewDidLoad() {
        super.viewDidLoad()

        sampleModel.delegate = self
        
        // ここでリクエスト
        sampleModel.fetchAPI()
    }

    func sampleModel(_ sampleModel: SampleModel) {
        print("レスポンスが返ってきました")
    }
}
```

```swift:SampleModel
import Foundation

protocol SampleModelDelegate: AnyObject {
    func sampleModel(_ sampleModel: SampleModel)
}

class SampleModel {
    weak var delegate: SampleModel?

    func fetchAPI() {
        // APIリクエスト...
        // レスポンスが返ってきたら通知
        // ↓ API待ってる代わり
        Thread.sleep(forTimeInterval: 5)

        // ここでView側にあるsampleModelが実行される
        delegate?.sampleModel(self)
    }
}
```

# おわり
どのようにデリゲートが実行されているのか知らなかったので勉強になりました。
[Rust] | エラー | Blocking waiting for file lock on build directory

# [エラー] Blocking waiting for file lock on build directory

```bash
cargo run
```
でRustプログラムをデバグ実行してみると、以下のエラーが、、、

![エラー画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840950/2d5414e8-2a23-6b18-7b6a-f8dd5f5b419a.png)

以下のコマンドでクリーンしましょう♪

```bash
cargo clean
```
コマンドライン基本まとめ

# はじめに
コマンドラインについて自分なりにまとめてみました。


## 1.ファイルの作成
```
$ touch ファイル名
```

## 2.ファイルの中身を表示する

```
$ cat ファイル名
```
補完機能　入力途中でTabキー

# ファイル構造について
## 3.ディレクトリの作成

```
$ mkdir ディレクトリ名
```

## 4.ディレクトリの移動
ファイル構造のイメージ大事
今いるディレクトリ：カレントディレクトリ
```
カレントディレクトリ $ cd ディレクトリ名
```
## 5.カレントディレクトリの確認

ルートディレクトリ(一番親):/

```
$ pwd
```

## 6.ディレクトリの中身を表示する

```
$ ls
```
listの略

## 7.1つ親のディレクトリ
```
$ cd ..
```

## 8.ホームディレクトリ
```
$ cd
```
ホームディレクトリに移動 ~で表す

# ファイル・ディレクトリを操作
ファイルやディレクトリの移動、コピー、削除など

## 9.ファイル・ディレクトリを移動させる

ファイルの移動
```
$ mv 移動させたいファイル名　移動先のディレクトリ名
```
moveの略

ディレクトリごと移動
```
$ mv 移動させたいディレクトリ名　移動先のディレクトリ名
```

## 10.ファイル・ディレクトリ名の変更
```
$ mv ファイル名　新しいファイル名
```

## 11.ファイル・ディレクトリのコピー

ファイルをコピー
```
$ cp コピーするファイル名　新しいファイル名
```
ディレクトリごとコピー
```
$ cp -r コピーするディレクトリ名　新しいディレクトリ名
```
-rがないとエラーになる。

## 12.ファイル・ディレクトリの削除
ファイルの削除
```
$ rm 削除するファイル名
```
removeの略

ディレクトリの削除
```
$ rm -r 削除するファイル名
```
-rがないとエラーになる。

# コマンド履歴

 ↑↓や
```
$ history
```
で、コマンドの履歴が出せる。
Ubuntuでフォルダー作成コマンド

# やり方

```sh:『うにゅ』という名前のフォルダーを作成
mkdir うにゅ
```

# 相対パスで指定したらどこにフォルダーが作成されるか

『/home/ログインしているユーザー名』フォルダー内に作成される。
（ダウンロードとかデスクトップとかがあるフォルダー内）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a20ecd23-5284-c6ec-26c9-738d26dd2609.png)

# すでにフォルダーが存在する場合どうなるか

下記エラー文言で作成不可。

> ディレクトリ \`フォルダー名` を作成できません: ファイルが存在します

『ファイルが存在します』という文言だが、既存 **フォルダーの中身が空であっても** 上記エラー。
中にファイルがあるかどうかではなく、あくまで **フォルダーが存在するか** をチェックしている。


# 『許可がありません』のエラーでフォルダーが作成できない時

特殊なフォルダー内に作成する場合はsudo付けて実行。
（root権限で実行）

```sh
sudo mkdir /mnt/unyu
```

ただし、sudo付けると作成されたフォルダーのアクセス権が下記のようにrootになるので注意。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/866a971d-4dfe-c4bc-3f16-ced0979515dd.png)

# 参考サイトさん

https://eng-entrance.com/linux-command-mkdir

# バージョン

Ubuntu 20.04.5 LTS

TODO:フォルダーが存在しない場合のみ作成を行う/pのオプションについてまとめる
【VScode】【拡張機能なし】全角の空白を表示させる方法

[こちらの記事](https://qiita.com/MPrg2011/items/50c9374e728f0b80f260)で全角の空白を表示させるZenkakuという拡張機能をご紹介しました。

https://qiita.com/MPrg2011/items/50c9374e728f0b80f260

実は拡張機能を導入しなくてもVScodeの設定を変更して全角の空白を表示することも可能です。
VScodeの設定を触るのは不安かもしれませんが、個人的にはZenkakuよりも目視で確認しやすいのでおすすめ(vscode.devでも使用可能です)。

やり方
1.index.htmlファイルを作成し全角の空白を入れて保存。
2.右上の設定→基本設定→設定の検索バーにfontと入力。
![スクリーンショット-2022-04-11-20.38.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/24de3f73-d1f5-ed3d-0c6f-7137ac12ec38.png)
![スクリーンショット-2022-04-11-20.38.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/8504f560-a403-ccbd-def8-8453fe488200.png)

3.Editor: Font Family内を次の内容に書き換えます 。
```
'Ricty Diminished', Menlo, Monaco, 'Courier New', monospace
```
※‘Ricty Diminished’が一番先頭に来るようにして、元の設定の前に追加する感じです。
![変更前設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/df0eab1f-9b11-3abc-7862-e76e4ca7c46e.png)
![変更後設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/43f2caef-6477-6135-696f-039e08be39ad.png)

4.VScodeを再起動してファイルを確認します。
**Before**
![変更前空白.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/4d03bf0c-a1cc-b5c7-2a99-d7a5a9197799.png)
**After**
![変更後空白.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/92ba878c-06e2-e04b-f130-31c10fd74b4f.png)
【インストール不要】vscode.devでVisual Studio Codeを体験

### Visual Studio Codeとは
![Group-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/7b18bbf4-4cd4-9d29-fa2c-652048b12fba.png)

>Visual Studio CodeはMicrosoftが開発しているWindows、Linux、macOS、web用のソースコードエディタである。
– 中略
カスタマイズ性が高く、テーマやキーボードショートカット、環境設定を変更できたり、機能を追加する拡張機能をインストールすることができる。
[Visual Studio Code – Wikipedia](https://ja.wikipedia.org/wiki/Visual_Studio_Code)

### vscode.devとは
2021年10月よりインストール不要のコードエディタとしてリリースされ、機能に制限はあるものの、気軽にコードを書くことができるようになりました。

※現在は英語版のみです。
また 画像のようにMarkdownファイル(`.md`)も編集・表示可能です。
![markdown.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/7cd91dc3-cad7-f60d-a1bd-a72e31ccd441.jpeg)


### さっそく動かしてみる
まずはデスクトップにフォルダを作成し、左カラムの`Open Folder`でフォルダを開きます。この時ブラウザによっては画像のような警告がでますが、`ファイルを表示する`をクリック。
![allow_read_files.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/e20227b8-c75d-7e4f-f276-1be52d89f6c6.jpeg)


左カラムの＋をクリックしてindex.htmlを作成します。なにか文字を入力して保存しておきます。
![ask_change.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/c5ea2b56-500e-8774-2639-57361b920d92.jpeg)


### 書いたコードをブラウザで表示させる
Visual Studio CodeではLive ServerやOpen with Browserといったワンクリックでブラウザで表示させる拡張機能が利用できるのですが、vscode.devには対応していません。以下の手順で表示させます。

1.Finderで作成したhtmlファイルが入ったフォルダを開き、ブラウザの検索バーにドラッグします。
![preview.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/b921a494-6566-1cfd-363d-b8f1231e969c.jpeg)

2.ブラウザの再読み込み🔃をクリックします。
![preview_in_browser.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/43022095-a1fe-f880-f701-3357162d0a06.jpeg)
ブラウザで表示させることができました。
### その他vscode.devでできること
HTMLにCSSを読み込ませると反映されるのはもちろん
![css.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/3a875686-701f-c9ba-ad52-4e487f1084c0.jpeg)

コマンドパレットによるコードの差分表示も可能なので、模写の際の答え合わせなどにも使えます。
![compare.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/138e5821-2fe1-c7c1-e379-e2e511336fd6.jpeg)


#### vscode.devでできないこと
- 利用できる拡張機能が非常に少ない
前述の通り、使える拡張機能が制限されています。
検索をかけて白文字になっているものは使用可能です。
![extension.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/1062696d-830d-fc40-693d-c71f44e5eacb.jpeg)

- デバッグ・ターミナルの使用が不可
機能としては用意はされていますが現在の所(2022年4月)使用できません。
その為ターミナルでサーバーを立ち上げてブラウザに表示させることはできないようです。
![terminal_open.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/24a0c985-2844-295a-7c37-b787e3bed348.jpeg)
メニューアイコン⇒View⇒Terminalで選択はできるが…
![terminal.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/3b788dee-241f-a145-aeae-5c5cb768bab2.jpeg)

not availableとなっている
### まとめ
今回はあまり知られていないVisual Studio CodeのWeb版・vscode.devをご紹介しました。
今後はダウンロード版に関する記事を作成しますので参考にして頂けると幸いです。

最後までご覧いただきありがとうございました。
PHPのバージョン切り替え【※phpenv未使用】

![WP-eye-catch(1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/993e7408-9751-9594-43f0-6cf9ad74151e.png)

### はじめに
PHP(Laravel)で自分の環境と開発環境のバージョンが違うのが原因で、本番環境でデプロイする際にエラーが出てしまい、原因解明に時間がかかってしまいました。
そこで今回はターミナルだけでPHPのバージョンを変更できる方法をご紹介します。
### 下準備
①ターミナルを立ち上げ以下のコマンドを打つ
```
php -v
```
こんな風に返ってきます。PHPのバージョンは7.4です。
```
PHP 7.4.30 (cli) (built: Jun  9 2022 09:31:00) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.30, Copyright (c), by Zend
Technologies
```
②Homebrewを更新
```
brew update
```
※Homebrewの更新はとても時間がかかるのと、完了後PHPのバージョンが変更されている可能性があるので注意
③インストールできるPHPのバージョンを確認
```
brew search php
```
インストール可能はPHPのバージョンが表示されます。
✓は現在インストール(使用)されているPHPのバージョンです。
```
brew-php-switcher   php@7.2           phplint             pcp
php                 php@7.3           phpmd               pup
php-code-sniffer    php@7.4 ✔         phpmyadmin ✔
php-cs-fixer        php@8.0           phpstan
php-cs-fixer@2      phpbrew           phpunit
```
### バージョン切り替えを行う
①切り替えたいバージョンのPHPをインストール
※下準備②でHomebrewの更新をしたときに変更されたバージョンから元のバージョンに戻すだけであればこの作業は不要です。
```
brew install php@バージョンの数字
```
※今回必要だった7.2は以下のようなエラーが返ってくるので、
```
Error: php@7.2 has been disabled because it is deprecated upstream!
```
別のコマンドでインストール
```
brew install shivammathur/php/php@7.2
```

こちらのGitHubを利用させて頂きました。

https://github.com/shivammathur/homebrew-php

②現在設定されているバージョンのシンボリックリンクを外す
必ずバージョン指定をすること
```
brew unlink php@バージョン
```
③設定したいバージョンのシンボリックリンクを通す
```
brew link php@バージョン
```
上記②③の作業の間は必ずバージョン確認(php -v)を行うこと！
### バージョン切り替えをもとに戻す
基本はバージョン切り替えを行うの②③で逆のバージョンを指定するだけです。
例：PHP7.2→PHP7.4にする場合
①
```
brew unlink php@7.2
```
②
```
brew link php@7.4
```
例の場合、`php -v`でバージョンが7.4に戻っているか確認すること
【エラー解決方法】yarn「info There appears to be trouble with your network connection. Retrying...」

# 事象
パッケージを再インストールしようと`yarn`コマンドを実行したら以下のエラーに遭遇した
```
$ yarn 
...
info There appears to be trouble with your network connection. Retrying...
```

# 原因
ネットワークが遅いためタイムアウトエラーが発生している

# 解決方法
タイムアウト時間を延ばすことで対処する
```
yarn config set network-timeout 600000
```

# その他
以下のコマンドでも解決できる
```
 yarn install --network-timeout 600000
```
私がよく使うGitのコマンド【まとめ】

![Git-Icon-1788C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051129/64825a0b-1e30-4b70-7994-e3a4cfd1ba57.png)
出典:https://git-scm.com/
### 私とGit
初めてGitを使ったときは、GitはGitHubでしか使えないものだと勘違いしてました笑
Gitはソースコードのバージョン管理システムのことを指しており、GitHubはあくまでGitの管理のホスティングサービスの一つです。
現在の職場ではGitHub,Bitbusket.Backlogを使用しています。
#### Gitの管理のホスティングサービス
- GitHub：エンジニア大好きな猫のマークでおなじみ。１番有名
- BitBusket：Gitの分散管理アプリSourceTreeが提供
- Backlog：Issueの作成、管理が上記２つより使いやすい
仕事中・学習中によく使うものをまとめました

学習開始したては目視でブランチが確認できるSourcetree+GitHubでコードの管理をしていましたが、VScodeのGit管理機能も充実してきており、コマンドをターミナルで打ち込んで確認を拡張機能のGitLensですませることが増えました。(こちらに関しては後日別記事であげます。)

#### よく使うGitコマンド一覧

::::note info
**開発環境**
- MacBook Pro 13-inch
- OS: macOS Big Sur 11.6.6
- チップ: Intel Core i5 2.3GHz
- メモリ: 8 GB
- ストレージ：500GB
::::

※基本Windowsでも使用できるかと思います。

**リポジトリを新規作成、初めてファイルを上げるとき**
※GitHub上でリポジトリを作成するところまで完了したとして進めます。
※コマンド内に出てくるリポジトリ名はブランチ名は適宣置き換えておくこと

1\. READMEがない場合はまずローカルのディレクトリ内で作成

```
echo "# リポジトリ名" >> README.md
```
2\. リポジトリを新規作成する、または既存のリポジトリを初期化する

```
git init
```
※既存のリポジトリを初期化したときはこんなメッセージが出ます
```
Reinitialized existing Git repository in ローカルのディレクトリ/.git/
```
3\. 1で作成したREADMEを追加
```
git add README.md
```
4\. ローカルのファイルをコミット(コメント付)

```
git commit -m "first commit"
```
5\. masterブランチ名をmainに変更
```
git branch -M main
```
6.リモートリポジトリにファイルをプッシュ
```
git push -u origin main
```
**ローカルブランチの変更をリモートブランチに反映させる**
ステージング(全て)
```
git add -A .
```
コミット(コメント付き)
```
git commit -m "コメント"
```
コミットの取り消し(プッシュ前)
```
git reset --soft HEAD^
```
プッシュ
```
git push origin ブランチ名 
```
**現在のブランチから新しいブランチを作成&移動(ローカル)**
例：mainまたはmasterブランチを元に新しくブランチを作成し、移動
```
git switch -c ブランチ名
```
**現在のブランチから新しいブランチを作成(リモート)**
Visual Studio Codeでいうブランチの発行
```
git push -u origin ブランチ名
```
**現在のブランチを確認**
```
git branch
```
**ブランチを新しい順に並べる**
```
git branch --sort=-authordate
```
結果

```
  master
* sec06_A
  sec05_C
  sec05_B
  sec05_A
  sec04_A
  sec03_B
  sec03_A
  sec02_A
```
**ブランチの名前を変更する**
```
git branch -m 旧ブランチ名 新ブランチ名
```
**名前を変更したいブランチにいる状態の場合**
```
git branch -m 新ブランチ名
```
AWS Solutions Architect Associate (SAA-C03)に合格するまでの話

# はじめに
![スクリーンショット 2022-09-17 19.54.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407666/fcd82bf3-acdf-cf8b-f7d3-52b2dfcf7350.png)

AWS Solutions Architect Associate (SAA-C03)に2022/09/17に受験し、合格しました。
試験勉強をしていた時は、[試験が改定されること](https://aws.amazon.com/jp/certification/coming-soon/)を途中まで知らず、結構ヤバいと感じてたものの、試験改定が実施されてから半月での試験日だったので、SAA-C03の情報が不足していたため、これからC03を受ける人のために、記録して残しておきたいと思います。

# 結論
**SAA-C02（旧来試験）とほぼ変わりません**。ただし、変更点にもあるようにウェイトがC02から少し変更されているので(セキュリティ周りのウェイトが増加)、問題演習を多めにやることを推奨されます。
対象のサービスは、SAA-C02から大きく増えていますが、基本的にはEC2、RDS、VPC等などが問われることは変わらないので、あまり心配はいらないかと思います。
それよりも、どんなに演習問題をこなしても本番に同じ問題は出ないので、**なぜ正解か不正解か理解して知識として習得すること**が大事かと思います（普通の試験と一緒ですね）。

# 勉強方法
ということで、僕がSAA-C03に合格するために使用した教材を紹介します。前述したようにとにかく問題をいっぱい解きました。
1.【おすすめ度 ☆】 [改訂新版 徹底攻略 AWS認定 ソリューションアーキテクト − アソシエイト教科書［SAA-C02］対応 徹底攻略シリーズ](https://www.amazon.co.jp/dp/B08SGSD479?tag=booklogjp-item-22&linkCode=ogi&th=1&psc=1)
教科書・問題集としてレベルが優しすぎて、この程度だとSAAの合格は難しいと思いました。そのため、この教本は必要ないと思いますし、次からでいいと思います。

2.【おすすめ度 ☆☆☆】 [【SAA-C03版】これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座](https://www.udemy.com/course/aws-associate/)
試験に必要な知識をハンズオン形式で学ぶことができます。僕自身は一部ハンズオンで勉強しましたが、基本流し見です。**試験勉強を通じて最大の後悔は、この動画を見ることにちんたら時間を使いすぎました**。この動画自体はササッと見終わって問題演習に行くべきでした。

3.【おすすめ度 ☆☆】 [AWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト 改訂第2版](https://www.amazon.co.jp/dp/4815607389?tag=booklogjp-item-22&linkCode=ogi&th=1&psc=1)
上記の動画を見ているので、テキストベースで不足しているところを改めて読み理解しました。また、巻末の模擬問題もあるので、こちらはSAAの合格基準である７２％をクリアするまで解きました（ちなみに２週しましたが、３週しても良かったなぁと思いました）。

4.【おすすめ度 ☆☆☆】 [AWS認定ソリューションアーキテクト-アソシエイト問題集](https://www.amazon.co.jp/dp/486594303X?tag=booklogjp-item-22&linkCode=ogi&th=1&psc=1)
SAAの試験自体、書籍化されている問題集は少ないのですが、こちらを使用して７２％をクリアするまで解きました（ちなみに２週しましたが、こちらも３週しても良かったなぁと思いました）。

5.【おすすめ度 ☆☆☆】 模擬試験＆公式サンプル問題
SAA-C02, SAA-C03の公式サンプル問題と模擬試験を解きました。ここまでの段階である程度の知識はついていると感じたので、実際の試験に即した問題・レベルに対してどうか？という視点で受けました。結論として、まぁまぁ大丈夫だろうがもっと多種の問題に触れたいと感じました。

6.【おすすめ度 ☆☆】 [【C03版へと更新中】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/)
最後の追い込みとして、使いました。結局全部できませんでしたが、総仕上げとしてこれの効果は大きかったと思います。

以上が僕が使用した参考書・問題集です。やりすぎな気もしなくはないですが、何回も受験料を払いたくなかったので、結構準備して取り組みました。尚、いずれの参考書・問題集もC02対応なので、C03試験を受験するのであれば、これぐらいやってもいい気がしました。
pbcopyコマンドはデータ内容によってコピペできないことがあるっぽい

# きっかけ
```
$ cat file | pbcopy
$ pbpaste
=> 反応なし。。
```

対象ファイルは、10MB 程の CSV
ちなみに、対象ファイルをエディタで開いて、`Command+c + Command+v`でコピペできる

ちょっと気になったので調べてみた

# 前提
```
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.7
BuildVersion:	19H15
```

`pbcopy`のバージョンの調べ方は分からなかった。。

# サマリー
- 一定のデータサイズを超えるとコピペできなくなる
- ただ、上記の閾値未満において、データサイズの大小と関係なくコピペできる/できないケースがある
- また、データ内容によって、上記の閾値、コピペ可否は変わる

# 調査
まずはマニュアルを見てみる

```
$ man pbcopy
```

特に気になるものはない

1MB だとどうなるか試してみる
```
$ dd if=file of=test_1m bs=1024 count=1024
$ cat test_1m | pbcopy
$ pbpaste
=> 反応なし。。
```

データサイズの閾値があるのだろうか、見てみる

```
"0kb: ng"
"10kb: ok"
"20kb: ok"
"30kb: ok"
"40kb: ok"
"50kb: ok"
"60kb: ok"
"70kb: ok"
"80kb: ng"
"90kb: ng"
"100kb: ok"
"110kb: ok"
"120kb: ok"
"130kb: ok"
"140kb: ok"
"150kb: ok"
"160kb: ok"
"170kb: ok"
"180kb: ok"
"190kb: ok"
"200kb: ok"
"210kb: ng"
"220kb: ok"
"230kb: ok"
"240kb: ok"
"250kb: ng"
"260kb: ng"
"270kb: ok"
"280kb: ng"
"290kb: ok"
"300kb: ok"
"310kb: ok"
"320kb: ok"
"330kb: ng"
"340kb: ok"
"350kb: ok"
"360kb: ng"
"370kb: ok"
"380kb: ok"
"390kb: ok"
"400kb: ok"
"410kb: ok"
"420kb: ng"
"430kb: ok"
"440kb: ng"
"450kb: ng"
"460kb: ok"
"470kb: ng"
...
"10000kb: ng"
```

データサイズの大小に関わらず、コピペできる/できないケースがある
また、470KB を境にコピペできなくなっている
ちなみに、複数回試したが、同じ結果となった

今度はデータ内容を変えてみる
具体的には、大量のNULL文字（`/dev/zero`）と一文字（`a`）

```
"0kb: ok"
"10000kb: ok"
"20000kb: ok"
"30000kb: ok"
...
"260000kb: ok"
"270000kb: ng"
...
"1000000kb: ng"
```

データ内容によって、コピペ可否の閾値が異なることが分かる
この結果自体は直感通り

コマンド内部で何が起きているのだろう。。

## ※ 検証スクリプト
- 前提
    - ruby 2.7.4
    -  rails (6.1.6.1)

### 初回
```ruby
def exec_command(cmd)
  result = `#{cmd}`

  raise RuntimeError if $?.exitstatus == 1

  result
end

def make_file(src_file, output_file, file_size)
  block_size = 1.kilobytes

  exec_command("dd if=#{src_file} of=#{output_file} bs=#{block_size} count=#{file_size/block_size} > /dev/null 2>&1")
end

def check_copy?(file)
  exec_command("cat #{file} | pbcopy")

  result = exec_command('pbpaste')

  result.present?
end

def remove_file(file)
  exec_command("rm #{file}")
end



# main

src_file = 'file' # 絶対パス

0.step(10000, 10) do |n|
  output_file = "test_#{n}"
  file_size = n.kilobytes

  make_file(src_file, output_file, file_size)

  p "#{n}kb: #{check_copy?(output_file) ? 'ok' : 'ng'}"

  remove_file(output_file)
end
```

### 次回
基本的には、↑と同じだが、一部内容を変更している

```ruby
...

def make_file(src_file, output_file, file_size)
  block_size = 1.kilobytes

  exec_command("dd if=#{src_file} of=#{output_file} bs=#{block_size} count=#{file_size/block_size} > /dev/null 2>&1")
  exec_command("echo 'a' >> #{output_file}") # 変更（src_fileが/dev/zeroの場合は出力内容がないので追記）
end

...



# main

src_file = '/dev/zero' # 変更（NULL文字で埋める）

0.step(1000000, 10000) do |n| # 変更（閾値の拡大に伴い、処理時間削減のため間隔を広げる）
  output_file = "test_#{n}"
  file_size = n.kilobytes

  make_file(src_file, output_file, file_size)

  p "#{n}kb: #{check_copy?(output_file) ? 'ok' : 'ng'}"

  remove_file(output_file)
end
```
【エラー解決方法】react-router-dom:v6「A <Route> is only ever to be used as the child of <Routes> element・・・」

# 概要
- React+TypeScriptでログイン中かどうかを判別し、ログイン時は Home コンポーネント、非ログイン時は SignUp、SignIn コンポーネントにを表示するように実装していく際にreact-router-domのバージョン(v5→v6)で遭遇したエラーの解決手順を紹介するものです。
- Router.tsxでそれぞれのコンポーネントのルーティングを作成して、そのルーティングをログイン時と非ログイン時で切り分けていきます。

# 参考記事
以下の記事を参考にログイン判定の機能をuseContextを使って実装しました。

[https://qiita.com/kazama1209/items/caa387bb857194759dc5](https://qiita.com/kazama1209/items/caa387bb857194759dc5)

# 実装前


```Router.tsx
export const Router: FC = memo(() => {
  return (
    <Routes>
      <Route path="signup" element={<SignUp />} />
      <Route path="signin" element={<SignIn />} />
      <Route path="home/user_management" element={<UserManagement />} />
      <Route path="home/user_management/:userId/list" element={<Lists />} />
      <Route path="*" element={<Page404 />} />
    </Routes>
  )
})
```

# 実装後
```Router.tsx
export const Router: FC = memo(() => {
  const auth = useContext(AuthContext);
  const Private = ({ children }: { children: React.ReactElement }) => {
    if (!auth.loading) {
      if (auth.isSignedIn) {
        return children
      } else {
        return <Navigate to="/signin" />
      }
    } else {
      return <></>
    }
  }
  return (
    <Routes>
      <Route path="signup" element={<SignUp />} />
      <Route path="signin" element={<SignIn />} />
        <Private>
		  <Route path="home/*" element={<Home />}/>
        </Private>
      <Route path="home/user_management" element={<UserManagement />} />
      <Route path="home/user_management/:userId/list" element={<Lists />} />
      <Route path="*" element={<Page404 />} />
    </Routes>
  )
}
```

# エラー
```
A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.
```
上記のエラーを日本語訳すると
> Routeは要素の子としてのみ使用され、直接レンダリングされることはありません。RouteはRoutesでラップしてください。

Routesコンポーネントの子要素はRouteコンポーネントのみ使えるという意味です。

# 修正後
```Router.tsx
export const Router: FC = memo(() => {
  const auth = useContext(AuthContext);
  const Private = ({ children }: { children: React.ReactElement }) => {
    if (!auth.loading) {
      if (auth.isSignedIn) {
        return children
      } else {
        return <Navigate to="/signin" />
      }
    } else {
      return <></>
    }
  }
  return (
    <Routes>
      <Route path="signup" element={<SignUp />} />
      <Route path="signin" element={<SignIn />} />
	   <Route path="home" element={
        <Private>
          <Home />
        </Private>
      } />
    </Routes>
  )
})
```

# その他
react-router-domバージョン6の詳しい情報はhttps://remix.run/blog/react-router-v6
を参照してください。
MySQLで中央値を取得するおそらく最も簡単な方法

今回は目次なしで一気に―――

MySQLには中央値を算出するための集約関数が存在しないということを、驚きをもってひしひしと受け止めた後は、
1\. [MariaDBの10.3.3以上を使う](https://mariadb.com/kb/en/median/)
2\. [ユーザー定義変数を使って自前で真ん中の行を取得する](https://sebhastian.com/mysql-median/)
3\. [先人の遺したカスタム集約関数でmedianをgcc経由でデプロイする](https://www.mooreds.com/wordpress/archives/376)
等で対策していくことになりますが、
* 1は、medianが使いたいからアップグレードする、というような条件反射が効くプロトタイプやスタートアップならともかく、普通はセキュリティポリシーやリプレース等での計画が先にあって、その中でエンジニアは頑張るのかと思います。
* 2は、すでにあちこちにSQLが存在する既存システムではマイグレーションが大変です。
* 3は、残念ながらもう15年以上前の化石的遺産なので、パッチ充てどころかデグレードまで必要になってきます。

というわけで、これらを踏まえて今 **MySQLで中央値を取得するおそらく最も簡単な方法** は、以下になるのではないかと思います。

[infusion/udf_infusion: A MySQL functionality enhancement UDF](https://github.com/infusion/udf_infusion)
```bash
cd /usr/local/src/
git clone https://github.com/infusion/udf_infusion.git
cd udf_infusion
./configure --enable-functions="median"
make
sudo make install
cat ./load.sql
    DROP FUNCTION IF EXISTS median;
    CREATE AGGREGATE FUNCTION median RETURNS real SONAME 'udf_infusion.so';

sudo find /usr/lib* -name udf_infusion.so
    /usr/lib64/mysql/plugin/udf_infusion.so

mysql testdb -u testuser -p < ./load.sql

mysql testdb -u testuser -p
    SELECT MEDIAN(cnt), AVG(cnt) FROM (
      SELECT 0 AS cnt
      UNION ALL
      SELECT 0 AS cnt
      UNION ALL
      SELECT 1 AS cnt
      UNION ALL
      SELECT 2 AS cnt
      UNION ALL
      SELECT 8 AS cnt
      UNION ALL
      SELECT 9 AS cnt
      UNION ALL
      SELECT 9 AS cnt
    ) mix;
        +-------------+----------+
        | MEDIAN(cnt) | AVG(cnt) |
        +-------------+----------+
        |           2 |   4.1429 |
        +-------------+----------+
```
_確認環境: CentOS7.4 + MySQL5.7.36_

簡単ですね。
まだQiitaで拾われていないようなのでご紹介まで。

ここでは --enable-functions="median" と、中央値を取得するための関数しか入れていませんが、他にも最頻値を取得したり、文字列操作用の関数があったりと、いろいろと楽しく頑張れそうです。
【Spring】@Controllerと@RestControllerの違い

<h1>@Controllerと@RestContollerの違い(備忘)</h1> 
<p>@Contorollerは戻り値にHTML(View)を返却するためのアノテーション。</p>
<p>@RestControllerはJSONやXMLを返却するためのアノテーション。</p>

<h2>参考</h2>
<a href="http://memento-mori-blog.com/spring-controller-restcontroller/">【Spring】@Controllerと@RestControllerの違い</a>
Amazon Lex とは

## 勉強前イメージ

んーみたことあるようなないような・・・・

## 調査

### Amazon Lex とは

音声やテキストを使った会話形のインタフェースを構築できるサービスになります。
Amazon LexはAlexaと同じ技術を採用しています。
音声→テキストの変換に自動音声認識(ARS)を使用しており、テキストの認識には自然言語理解(NLU)という技術が使われています。

### Amazon Lex のメリット

- すぐにチャットボットを構築できる

いくつか設定を行うだけで簡単にチャットボットを作成できます。
すでに学習がされている人工知能を活用しているので、ディープラーニングなど機械学習の知識は必要ないです。

- AWSの他のサービスと連携できる

もちろんAWSの他のサービスと連携できます。
lambdaやcloudwatchを組み込んでデータの取得などを行うことができます。

## 勉強後イメージ

LINEとかと組み合わせてLINE Bot作れるとか？

## 参考

- [ディープラーニングを利用した対話型アプリを構築できるAmazon Lexを解説](https://business.ntt-east.co.jp/content/cloudsolution/column-179.html)
- [AWS IoT 再入門ブログリレー Amazon Lex編](https://dev.classmethod.jp/articles/amazon-lex-reintroduction/)
Visual StudioでVSCodeと同じように、Shift + Alt + Arrowに行のコピーを割り当てる方法

# 対象
Visual StudioでVSCodeのキーボードショートカットを使えるように設定したが、``Shift+Alt+Arrow``で「行を上（下）にコピー」のショートカットが使えなくて困っている方。

※Visual StudioでVSCodeのショートカットを使用する方法は、[こちらの記事](https://kashiwaba-yuki.com/note-visualstudio-keybind)をご参照ください。

## 環境
- Windows11
- Visual Studio 2022(17.3.4)


# 原因
Visual Studio側に「行を上（下）にコピー」というコマンドが組み込まれていないことが原因だと考えられます。

# 解決策
代わりに「複製」というコマンドを``Shift+Alt+Arrow``に割り当てましょう。
※「複製」はVSCodeの「行を下にコピー」に当たる機能です。「行を上にコピー」に当たる機能は見つからなかったので、今回は``Shift+Alt+↓``だけではなく``Shift+Alt+↑``にも「複製」を割り当てることとします。


1. ``ツール`` → ``オプション``を開きます。
1. ダイヤログ左のツリーにて``環境`` → ``キーボード``を開きます。
1. 「以下の文字列を含むコマンドを表示」に``複製``と入力してコマンドを検索します。
![スクリーンショット 2022-09-17 185607.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2581126/26ea237e-225c-c0f9-ef7f-82d7e92e04d1.png)
1. ``編集,複製``コマンドを選択し、ショートカットキーを追加していきます。まず「使用する場所」を``テキスト エディター``に変更します。そして「ショートカット キー」に``Shift+Alt+↓``を入力し、「割り当て」をクリックします。同様に``Shift+Alt+↑``も割り当てましょう。

「選択したコマンドへのショートカット」が以下のようになっていれば、割り当てはうまくいっています。「OK」を押してダイアログを閉じましょう。
![スクリーンショット 2022-09-17 185646.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2581126/e4a61913-0d18-3423-b0be-486b96af01a1.png)


以上の操作によって設定は完了です。お疲れさまでした。


# あとがき
更に良い方法をご存じの方がいらっしゃいましたら、ぜひコメントで教えてください。

# 参考記事
[VisualStudioのキーバインド設定をVSCodeの設定と同じにしてストレスフリーになりたい](https://kashiwaba-yuki.com/note-visualstudio-keybind)
Githubでssh接続

```
ssh-keygen    
```

```
pbcopy < ~/.ssh/id_rsa.pub
```
でキーをクリップボードにコピー。


あとは、Githubの設定で
sshキーの項目にこれを追加する。

```
ssh -T git@github.com
```
を実行して、Hiと返ってくれば問題ない。


これでgit remote addとかする際、
sshの方を使える。

```
git remote add origin git@github.com:example/test.git
```
コントラスト比を求める

ウェブコンテンツアクセシビリティガイドライン(WCAG) によれば、文字と背景の間に一定以上のコントラスト比が必要らしい。

このコントラスト比を計算するための方法をC# で書く

## 相対輝度を求める

```csharp
private double Luminance(Color color){
    Func<double, double> linear = v => (v / 255) < 0.003928  ? (v / 255) / 12.92 : Math.Pow((((v / 255) + 0.055) / 1.055), 2.4F);

    var luminanceR = linear((double)color.R);
    var luminanceG = linear((double)color.G);
    var luminanceB = linear((double)color.B);

    var l = 0.2126 * luminanceR + 0.7152 * luminanceG + 0.0722 * luminanceB;
return l;
}
```

## コントラスト比を求める

```csharp
private double Contrast(Color color1, Color color2)
{
    var l1 = Luminance(color1);
    var l2 = Luminance(color2);
    return l1 > l2 ? (l1 + 0.05) / (l2 + 0.05) : (l2 + 0.05) / (l1 + 0.05);
}
```

## 参考

ウェブコンテンツアクセシビリティガイドライン(WCAG)
https://waic.jp/docs/WCAG20/Overview.html

G17: Ensuring that a contrast ratio of at least 7:1 exists between text (and images of text) and background behind the text
https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
STM32G071とI2Cを使い0x40(8ビット表記0x80)に「hello...」と出力する。(Arduino)



x NUCLEO-G071RB



目的
I2Cのテスト
I2C->USART9600bps->USBのテスト


![o_con759.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a7b940c6-51c1-2f68-6ba7-b77482307f62.jpeg)




STM32G031とVSCode+STM32CubeでI2Cスレーブの受信文字をシリアル出力(受信)(STM32-I2C-USART)(CH340N)



https://qiita.com/caa45040/items/5032e6905c9425f41495




```c++



//I2C_HELLO_071_1

#include <Arduino.h>
#include <Wire.h>

#define D_LED1     PA5

#define ADDR1  0x40


//文字の表示 nana_seg
int ns_putc(char str1)
{

  //I2Cに送信
  Wire.beginTransmission(ADDR1);
  Wire.write( str1 );
  Wire.endTransmission();

  delay(1);//連続送信防止の為に1ms待つ

  //戻り値
  return (0);

}//ns_putc


//文字列の表示 nana_seg
int ns_puts(char *str1)
{

  //文字の中身がゼロか
  while (*str1) {

    ns_putc( *str1 ++  );

  } //while

  //戻り値
  return (0);

}//ns_puts


//初期化
void setup() {

  //GPIOの初期化
  pinMode(D_LED1, OUTPUT);

  //i2cの初期化
  Wire.begin(); //071

}//setup


//メインループ
void loop() {

  digitalWrite(D_LED1, 1); //LED ON debug

  //I2Cに文字列を出力
  ns_puts("hello world\r\n");

  delay(500);//0.5秒待つ


  digitalWrite(D_LED1, 0); //LED OFF debug
  delay(500);//0.5秒待つ

}//loop






```
Markdown基本文法一覧

# 1.見だし (headline) - 大きく表示


## コード

```
#一番大きい

or 

一番大きい
===================

##二番目大きい

or

二番目大きい
----------------------

###三番目大きい

####四番目大きい
```



## 結果

# 一番大きい

## 二番目大きい

### 三番目大きい

#### 四番目大きい



# 2.強調 (Emphasize) - 太字・斜体

### 説明：斜体は強調、太字は強い強調



## コード

```
**太字**
or
__太字__

*斜体*
or
_斜体_
```



## 結果

**太字**
or
__太字__

*斜体*
or
_斜体_



# 3.コード (code) - そのまま表示



## コード

````
```
#include<stdio.h>

int main(void)
{
    printf("hello markdown!");
    return 0;
}
```
````



## 結果

```
#include<stdio.h>

int main(void)
{
    printf("hello markdown!");
    return 0;
}
```



# 4.リスト (list) - 箇条書き



## コード

```
- part1
- part2
	- part2.1
		- part2.1.1

or

* part1
* part2
	* part2.1
		* part2.1.1
```



## 結果

- part1
- part2
  - part2.1
    - part2.1.1

or

* part1
* part2
  * part2.1
    * part2.1.1



# 5.引用 (Quotation)



## コード

```
>Markdown（マークダウン）は、文書を記述するための軽量マークアップ言語のひとつである。本来はプレーンテキスト形式で手軽に書いた文書からHTMLを生成するために開発されたものである。しかし、現在ではHTMLのほかパワーポイント形式やLATEX形式のファイルへ変換するソフトウェア（コンバータ）も開発されている。各コンバータの開発者によって多様な拡張が施されるため、各種の方言が存在する。
```



## 結果

> Markdown（マークダウン）は、文書を記述するための軽量マークアップ言語のひとつである。本来はプレーンテキスト形式で手軽に書いた文書からHTMLを生成するために開発されたものである。しかし、現在ではHTMLのほかパワーポイント形式やLATEX形式のファイルへ変換するソフトウェア（コンバータ）も開発されている。各コンバータの開発者によって多様な拡張が施されるため、各種の方言が存在する。

(https://ja.wikipedia.org/wiki/Markdownより引用)



# 6.リンク (link)



## コード

```
[表示したい文字](address "title")
or
[表示したい文字](address)
```



## 結果

[表示したい文字](address "title")

or

[表示したい文字](address)



# 7.イメージ (Image)



## コード

```
![表示したい文字](address "title")
or
![表示したい文字](address)
```



## 結果

![表示したい文字](address "title")
or
![表示したい文字](address)



# 8.水平線 (Horizontal rules) - 分割



## コード

```
* * *
or
***
or
*****
or
- - -
or(強調になる)
---------------------------------------
```



## 結果


para1
* * *
para2



# 9.注釈 (Annotations)



## コード

```
テキスト[^1]
...
...
[^1]: 注釈テキスト
```



## 結果

テキスト[^1]
...
...

[^1]: 注釈テキスト
コンテナ環境でReactユニットテストを実行する際のタイムゾーン設定にハマった話（Jest）

# 目的
Reactの開発環境をDockerに移行した際、jestでのユニットテストが通らなくなりました。
Dockerで特に何も設定せずにUbuntuを使用していたためb、タイムゾーンがUTCとなっていたことが原因でした。
なので、今回は**コンテナ自体のタイムゾーンは変えずに、テスト実行時のタイムゾーンを固定する方法**の備忘録になります。

# 手順
ここでは3つの方法を記載します。
どれをとっても結果は同じなので、お好みで大丈夫です。

### 方法1. Jest実行環境の設定ファイルにタイムゾーンを指定する

https://qiita.com/Tsuyoshi84/items/e3d79d9842280549723c

こちらの記事を参考にします。

`package.json`と同階層にJestの設定ファイル`jest-global-setup.js`を作成し、タイムゾーンを記述します。

```react:jest-global-setup.js
module.exports = async () => {
  process.env.TZ = 'Asia/Tokyo';
};
```

`package.json`のjest定義に以下を追加します。
```react:package.json
{
  "jest": {
    "globalSetup": "./jest-global-setup.js"
  }
}
```

### 方法2. テスト実行時にタイムゾーンを指定する
`yarn test`を行う際に明示的にタイムゾーンを指定します。

```console
# TZ=Asia/Tokyo yarn test
```

### 方法3. package.jsonのtest定義にタイムゾーンを指定する
`yarn test`によって実行されるスクリプトコマンドに明示的にタイムゾーンを指定します。

```react:package.json
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "TZ=Asia/Tokyo react-scripts test", // タイムゾーンを指定
```

# まとめ
開発環境をDockerに移す際にはここら辺も気を付けないといけませんね。。
個人的には3番目の方法がサクッとできて、かつ一度設定してやれば済むのでオススメかなと思います。
Rack 3.0 で Rack::Server が消えた

とある Ruby のプロジェクトで依存 gem のバージョンを上げたらエラーが出たのでその原因を探った。

# 起こったこと

ある種のウェブアプリ機能を持った gem を開発し，長らく多数のプロジェクトで使っていた。

この gem は [rack](https://rubygems.org/gems/rack) という gem を利用している[^rack]。rack への依存はとくにバージョンを指定していない。

[^rack]: rack を一言で言えばウェブアプリとウェブサーバーの仲立ちをするライブラリー。ウェブサーバーの差異を吸収する働きがあり，ウェブサーバーの取り替えが簡単になる。

ある日，`bundle update` で gem たちのバージョンを上げたところ，rack もバージョン 2.2.4 から 3.0.0 に上がった。
メジャーバージョンが上がったので何かしら非互換性があるかとは予想したが，起動しようとしたら案の定

```
cannot load such file -- rack/server (LoadError)
```

が出て死んだ。

rack/server って何だっけ？

# 最小再現コード

今回発生したのと同じ問題を最小再現コードで示すと以下のようになる。

まず Gemfile。rack と webrick のみを使う。webrick はウェブサーバー。

```rb:Gemfile
source "https://rubygems.org"

gem "rack"
gem "webrick"
```

次に，ウェブアプリ。現在時刻を text/plain（つまり HTML じゃなくてただのテキスト）で返すだけの簡単なもの。

```rb
require "bundler"
Bundler.require

class App
  def call(env) # 引数は使ってない

    # レスポンスボディー（配列の形にする）
    body = ["Now #{ Time.now }"] 

    # ステータス，ヘッダー，ボディーの三つ組を返す
    [200, {"Conent-Type" => "text/plain"}, body]
  end
end

Rack::Server.new(app: App.new).start
```

最終行で `Rack::Server` を動かしている。
`Rack::Server` を生成するとき，`app` として「`call` に反応するオブジェクト」を渡してやる。

この単純なスクリプトを動かし，ブラウザーで http://localhost:8080 にアクセスすると，画面に

```
Now 2022-09-17 18:00:57 +0900
```

みたいなものが表示される。

ところが，2022 年 9 月 6 日に rack 3.0.0 がリリースされ，このバージョンを使うと

```rb
Rack::Server.new(app: App.new).start
```

のところで件の LoadError が出るようになった。

# 原因と対策

rack のアップデートに伴う現象なので，もちろん

```rb:Gemfile（抜粋）
gem "rack", "< 3"
```

のようにバージョンを 3 未満に抑えてやればいちおう解決するわけだが，ここはきちんと原因を調べて最新の rack で動くようにしておきたい。

rack の [CHANGELOG](https://github.com/rack/rack/blob/main/CHANGELOG.md) を見に行くと，[\[3.0.0.beta1\] - 2022-08-08](https://github.com/rack/rack/blob/main/CHANGELOG.md#300beta1---2022-08-08) の「Removed」のところに，「`Rack::Server` 等を別 gem に分離した」というようなことが書いてある。

その別 gem というのは，調べたところ [rackup](https://rubygems.org/gems/rackup) であるらしい（CHANGELOG に具体的な gem 名も書いておいてほしかった）。
ではこれを使おう。

# rackup gem を使う

まずは Gemfile を以下のように変更してみた。

```rb:Gemfile
source "https://rubygems.org"

gem "rackup"
gem "webrick"
```

rackup は rack に依存しているので Gemfile に rack を書く必要はないはず。

これで `bundle install` する。

rack gem はバージョン 3 未満で `rackup` というコマンドを持っていた。rackup gem も同名のコマンドを持っているので，こいつをシステムにインストールするとコマンドを上書きしてしまう。一抹の不安がよぎるが，まあ今後，全プロジェクトで rack 2 系から 3 系に移行していくので，もし問題が生じてもどうにかできるかな。

さて，この状態で件のスクリプトを動かすと，今度は

```
uninitialized constant Rack::Server (NameError)
```

が出た。
おぅ！　rackup gem には Rack::Server が無いんかいっ。

調べたところ，`Rack::Server` を単純に `Rackup::Server` に書き換えればよいことが分かった。
予想よりずっと簡単な修正で解決した。めでたしめでたし。

修正後のスクリプトも載せておく：

```rb
require "bundler"
Bundler.require

class App
  def call(env)
    body = ["Now #{ Time.now }"]
    [200, {"Conent-Type" => "text/plain"}, body]
  end
end

Rackup::Server.new(app: App.new).start
```

## 追記

Gemfile に rackup と rack を両方書いた状態で `Rack::Server` を使うと NameError が出ずにアプリが動くが，

```
Rack::Server is deprecated and replaced by Rackup::Server
```

と警告が出る。


# まとめ

今まで `Rack::Server` を使っていたプロジェクトは，これからは rackup gem の `Rackup::Server` を使うべし。
PHPで先月の1日を出力する方法

## この記事を作成しようと思った理由
バッチ処理で月初に先月の1日から末日までの集計データを出力する必要があり下記のコードを見たが、これがどういう風な処理をしているのか理解できていなかったので、今回まとめることにしました。


```
# 今回理解したいコード
$start_date = date("Y/m/01 00:00:00", strtotime(date('Y/m/01') . " - 1 day"));
```

## 処理についての説明
前提として今日の日付を「2022年9月15日」として話をしていきます。
まず、この処理で行っていることを分解していきます。
<br><br>



ここで行われている処理について説明します。
```
strtotime(date('Y/m/01') . " - 1 day")
```
この処理は、今日の日付（2022年9月15日）から−1日しているという処理になります。
Y(今日の日付の年）、m(今日の日付の月）、d（今日の日付の日）となるので、
echo date("Y/m/d" strtotime(date('Y/m/d') . " - 1 day")));
と出力すると、2022/09/15から1日過去の2022/09/14という値が出力されます。
<br><br>


では、今回の処理strtotime(date('Y/m/01') . " - 1 day")に戻します。
この処理はどうなっているかというと
date('Y/m/01')は、Y(今日の日付の年）、m(今日の日付の月）、01日となるので、
strtotime(date('Y-m-01')." - 1 day")は、2022/09/01 -1 day　となるので
```
echo date("Y/m/d, strtotime(date('Y/m/01') . " - 1 day"));
#出力される値　2022/08/31
```
となります。
<br><br>

ここまでの分解を整理してみましょう。
```
$start_date = date("Y/m/01", strtotime(date('Y/m/01') . " - 1 day"));

$start_date = date("Y/m/01", strtotime('2022/08/31'))
```
と分解することができました。
<br><br>

ここまでくると、あと1歩です。

date("Y/m/01", strtotime('2022/08/31'))という処理が行っていることは、2022/08/31という値を"Y/m/01 00:00:00"　という形に成形することです。
すると、Y=2022, m=08, という値になり、日付は01で固定されているのでd=01となります。
```
echo date("Y/m/01", strtotime('2022/08/31'))
#出力される値　2022/08/01
```
これで2022年9月15日に、先月の1日である2022/08/01の値を出力することが可能になりました。


## まとめ
理解しづらかったコードも処理を分解してみることで理解しやすくなりました。
日付に関しては、月末の日数が31日・30日とか閏年とか気をつけないといけない処理が多そうなので今後も勉強をしていきたいです。
STM32G071のシリアルでHello Worldと出力


x NUCLEO-G071RB


目的
シリアルのテスト


![o_con758.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/1c06da12-ec95-5f3b-bec1-330004b2fab6.jpeg)



```c++



void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}//setup

// the loop routine runs over and over again forever:
void loop() {
  // print out the value you read:
  Serial.println("Hello World !");
  delay(1000);        // delay in between reads for stability
}//loop


```
Microsoft Certified: Azure AI Fundamentals（AI-900）資格勉強方法

AzureのMicrosoft Certified: Azure AI Fundamentalsに2022年7月に合格したので、勉強方法を共有します。

# 試験概要
概要まとめとしては以下3つがわかりやすくまとまっている

https://qiita.com/gomasa/items/08e6a6c8fb2698901cbb

https://nainaistar.hatenablog.com/entry/2021/06/28/120000

https://qiita.com/abemaki29/items/8b72f35d5580d10585bd

# 勉強方法
日本語ベースで学習できる教材は公式のもののみ。
AZ-900（Azure Fundamentals）を取得後だとベース知識が活かせる。
また、人工知能（AI）の一般的な知識があるとテスト対策となる。

## Microsoft Learn
公式にて無料で学習できる

https://docs.microsoft.com/ja-jp/learn/certifications/azure-ai-fundamentals/

上記Learnの内容を半日で凝縮したウェビナー
参加すると試験1回分の無料バウチャーがもらえる

https://www.microsoft.com/ja-jp/events/top/training-days/azure?activetab=a1:primaryr5

無料でウェビナー形式の問題集解説
問題も多く試験範囲を網羅しているので問われる内容を理解できていれば大丈夫

https://info.microsoft.com/JA-AzureApp-WBNR-FY21-04Apr-07-MKTOFY21AI900PrepSessionOndemandWebinar-SRDEM70306_LP02OnDemandRegistration-ForminBody.html
RockyLinux8 vps環境設定7) コマンドのインストール

RockyLinux8 vps環境設定6) httpdの設定
https://qiita.com/naga_kt/items/cd58bb4cd4001a2fb553
の続き。WebArena Indigo(RockyLinux8.4)及びKagoya(RockyLinux8.5)での環境設定について述べる。

　httpd以外のよく使うコマンドについてインストールの仕方を記載した。

## screen

【WebArena Indigo / Kagoya両方で必要】
~~~linux
$ sudo dnf install epel-release

$ sudo dnf --enablerepo=epel install screen

~~~


## lockfile

【WebArena Indigo / Kagoya両方で必要】
~~~linux
$ sudo yum install procmail

~~~

## sqlite

【WebArena Indigo / Kagoya両方で必要】
~~~linux
$ sudo yum install sqlite

~~~

## jq

【WebArena Indigo / Kagoya両方で必要】
~~~linux
$ sudo yum install epel-release

$ sudo yum install jq --enablerepo=epel

~~~

## make

【WebArena Indigo / Kagoya両方で必要】
~~~linux
$ sudo yum install make

$ sudo dnf group install 'Development Tools'

~~~

## mail

【WebArena Indigo / Kagoya両方で必要】
~~~linux
$ sudo yum install mailx

~~~

## ifconfig

【WebArena Indigoで必要】
~~~linux
$ sudo yum install net-tools

~~~

## rsync

【Kagoyaで必要】
~~~linux
$ sudo dnf install rsync

~~~

## tar

【Kagoyaで必要】
~~~linux
$ sudo yum install tar

~~~


---

RockyLinux8 vps環境設定8) ファイアウォールのポート設定
https://qiita.com/naga_kt/items/a93913d4c4aec4ff7eeb
に続く。

---

## 参考記事

(screen)
CentOS8で困ったこと　
https://qiita.com/scheveningen/items/f163093281d71bef6436

(jq)
CentOS7に15秒でjqコマンドをインストールする
https://www.setouchino.cloud/blogs/73

(make)
CentOS 8の"Development Tools"パッケージグループの中身を確認する
https://qiita.com/charon/items/f2b368cccbac95fc6489
ffmpegで動画を無音（+別の音源を加える）して、logoも付与する際の備忘録

ffmpegで動画を無音（+別の音源を加える）して、ロゴを付与する際の備忘録


無音化

> サウンド付きの動画を無音化する。
> -an disable audio

```sh
ffmpeg -i input.mp4 -an output.mp4
```

> ２つの音声ファイル(`file1,file2`)を結合する

```
ffmpeg -i file1.mp4 -i file2.mp4 -filter_complex 'concat=n=2:v=0:a=1' file3.mp3
```

> ffmpegを使って映像と音声を結合して一つの動画ファイルにする

```sh
ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4
```

音声を結合した場合は、動画の尺が長くなるかもしれないので以下を参考に尺を意図通りの長さにする。
https://nico-lab.net/cutting_ffmpeg/

ロゴを付与する

> ポイントは「logo.png -filter_complex overlay=10:10」の部分で、まずは重ねたい画像を「logo.png」のところに指定した上で、Overlayフィルタというものを使ってロゴを動画に重ねます。
> 「overlay=10:10」は、重ねる位置を示していて、動画の左上の座標を(0,0)としたときに、右下に向かって(10,10)の位置にロゴが重なります。

```sh
ffmpeg -i input.mp4 -i logo.png -filter_complex overlay=10:10 output1.mp4
```

例えば、添付の`challenge_club.png`のような画像を重ねたい場合は以下のようにすればOK

```sh
ffmpeg -i input.mp4 -i challenge_club.png -filter_complex overlay=1350:00 output4.mp4
```

`challenge_club.png`
![challenge_club.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344880/e2b9c0b5-4ad8-c374-9d4b-0f3311717795.png)

結合する場合は[こちら](https://qiita.com/niusounds/items/c386e02ab8e67030bdc0)を参照
（ubuntuだと意図通り結合できず、macだと意図通り結合できることがあった。謎。。）

# 参考

https://www.84kure.com/blog/2018/07/24/ffmpeg-%E5%8B%95%E7%94%BB%E3%82%92%E7%84%A1%E9%9F%B3%E5%8C%96%E3%81%99%E3%82%8B-an%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3/

http://fftest33.blog.fc2.com/blog-entry-80.html

http://tecsingularity.com/ffmpeg/logo/

https://qiita.com/niusounds/items/f69a4438f52fbf81f0bd
Find AC Spare Parts & Tools in UAE

Do you know which are some of the best <a href="https://www.yellowpages.ae/subcategory/ac-&-refrigeration/ac-parts-&-tools/5ec7ba71ebee8a73796798a5">AC Spare Parts & Tools</a> in UAE? Etisalat Yellow Pages provide the list of verified companies that offer the top quality air conditioner spare parts in UAE. Through the whole details, go to our portal yellowpages.ae and get your requirements and contact these <a href="https://www.yellowpages.ae/subcategory/ac-&-refrigeration/ac-parts-&-tools/5ec7ba71ebee8a73796798a5">AC Spare Parts & Tools</a> in UAE.

![AC Parts & Tools (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2848862/5b489863-7aa5-f824-0592-0d9e7dab0d5e.png)
RockyLinux8 vps環境設定5) Swapの設定

RockyLinux8 vps環境設定4) 時間設定の変更
https://qiita.com/naga_kt/items/5b175dd606b459e92ebd
の続き。WebArena Indigo(RockyLinux8.4)及びKagoya(RockyLinux8.5)での環境設定について述べる。

　デフォルトではSwapが全く設定されていなかった。

~~~linux
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           991M         83M        766M         18M        142M        747M
Swap:            0B          0B          0B
$ swapon -s
~~~

　容量を確認したところ余裕があった。

~~~linux
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        20G  5.4G   15G  27% /
devtmpfs        474M     0  474M   0% /dev
tmpfs           496M     0  496M   0% /dev/shm
tmpfs           496M   13M  484M   3% /run
tmpfs           496M     0  496M   0% /sys/fs/cgroup
tmpfs           100M     0  100M   0% /run/user/1001
~~~


　4GのSwapを設定することにした。

## Swap領域に割り当てるファイルの作成

　以下のコマンドでSwap領域に割り当てるファイル/swapfileを作成した。

~~~linux
$ sudo dd if=/dev/zero of=/swapfile bs=4M count=1024
1024+0 records in
1024+0 records out
4294967296 bytes (4.3 GB) copied, 39.3812 s, 109 MB/s
~~~

## パーミッションの変更

　パーミッションを変更してrootのみが参照できるファイルにする。

~~~linux
$ ls -lh /swapfile
-rw-r--r-- 1 root root 4.0G Apr 26 14:55 /swapfile
$ sudo chmod 600 /swapfile
$ ls -lh /swapfile
-rw------- 1 root root 4.0G Apr 26 14:55 /swapfile
~~~

## Swap領域の割り当て

~~~linux
$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 4194300 KiB
no label, UUID=………
~~~

## Swapの有効化

~~~linux
$ sudo swapon /swapfile
~~~

## Swap領域の状態確認

　以下のようにして4GのSwapが割り当てられていることが確認できる。

~~~linux
$ swapon -s
Filename                                Type    Size    Used    Priority
/swapfile                               file    4194300 0       -1
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           991M         79M         73M         18M        838M        721M
Swap:          4.0G          0B        4.0G
~~~

## Swap設定の永続化

　OS再起動時もSwap設定を行なうようにするために/etc/fstabを編集して下記一行を追記する。バックアップは取っておくようにする。

~~~linux
/swapfile     swap    swap    defaults        0       0
~~~


---

RockyLinux8 vps環境設定6) httpdの設定
https://qiita.com/naga_kt/items/cd58bb4cd4001a2fb553
に続く

---

### 参考記事

CentOS
Linux Swap設定方法（CentOS 7）
https://oji-cloud.net/2019/07/01/post-2242/
Pythonの関数デコレータに入門する

## 概要

Pythonを使っていると`def`の上部に@がくっついていることがありますよね。

```python

@main.result_callback()
def run(a, b):
    ....  
```

これ、関数デコレータ(以下、デコレータ)と呼ばれるものらしいのですが、調べてみてもよくわからないし、使い道もサッパリだったので無視してました。

だがしかし。

大量にデコレータがついているソースコードに遭遇してしまい、どうしても理解しないといけない状況になりました。

仕方なく重い腰をあげて勉強してみます。

## デコレータの基本の「き」

デコレータの最低限の動きを確認するために次のコードを実行してみます。

```python
def decorator(f):
  def inner():
    print('before')
    retval = f()
    print('after')
    return retval
  return inner
  
@decorator
def example():
  print('inside')

example()
```

実行結果

```
before
inside
after
```

デコレータを少しでも調べたことがある人は、**デコレータ`decorator`を付与した状態でexample()を実行することはdecorator(example)を実行することと同じである**という説明をみたことがあると思います。そのため、decoratorの引数`f`をexample関数として読み替えれば最低限の動きは理解できるかと思います。

```python
print('before')
retval = example()
print('after')
```

ちなみにexample関数は`retval = example()`と代入しているだけですが、これで関数が実行されます。

例えば下記のように書いてみるとhoge関数は実行されてhelloが表示されます。


```python
def hoge():
  print('hello')

f = hoge
x = f()
```

実行結果

```
hello
```

デコレータを使うことで、ある関数(example関数)の処理を変更せずにその前後に別の処理を入れることができることがわかりました。


## これだけじゃ使い物にならない

#### 実行関数に引数を伴う場合

`example()`関数に引数を伴う場合はエラーになってしまいます。

```python
def decorator(f):
  def inner():
    print('before')
    retval = f()
    print('after')
    return retval
  return inner
  
@decorator
def example(x):
  print(x)
  print('inside')

example('hello')
```

```
TypeError: inner() takes 0 positional arguments but 1 was given
```

この場合は次のように`decorator()`, `inner()`に可変長引数`*args, **kwargs`を指定すればOKです。
```python
def decorator(f, *args, **kwargs):
  def inner(*args, **kwargs):
    print('before')
    retval = f(*args, **kwargs)
    print('after')
    return retval
  return inner
  
@decorator
def example(x):
  print(x)
  print('inside')

example('hello')
```
実行結果
```
before
hello
inside
after
```

#### デコレータに引数を指定したい場合

デコレータ`decorator()`に引数を指定したい場合は次のように書くことで実現できます。

```python
def decorator(start, end):
  def _time_args(f):
    def inner(*args, **kwargs):
        print(start)
        print('before')
        retval = f(*args, **kwargs)
        print('after')
        print(end)
        return retval
    return inner
  return _time_args 

@decorator('開始', '終了')
def example(x):
  print(x)
  print('inside')

example('hello')
```
実行結果
```
開始
before
hello
inside
after
終了
```

うーん、どんどん入れ子になって混乱してきた。

## さいごに

デコレータの理解を深めるにはPythonの理解をもっと深めていく必要があるなあーと感じました。

## 参考文献

https://python-reference.readthedocs.io/en/latest/docs/operators/decorator.html

https://techblog.recochoku.jp/2407