OmniAICreator/Qiita-1.07M huggingface dataset:
電話番号の必須入力

# 電話番号の必須入力
## Webアプリの認証機能
Webアプリ（に限らずシステム全般）を作る際に認証機能の有無は重要な要件である。
これはシステムに認証機能がなかった場合の話。
認証機能がないシステムでも身分証の提示が条件だったり、メールアドレス入力が必須だったり、固有の一意なIDが必須だったりする。
そのうちの一つに「電話番号の入力を必須条件とする」というものもある。

## 性善説に基づいたサービス
認証機能がないということは個人を特定する力が弱い（一人が複数人として利用することができてしまう）
Twitterやフリーメールなどもともと個人が複数アカウントを使用することが認められているサービスもあるが、
1アカウント限定のサービス、例えば初回登録クーポンや倍率の高いチケットの予約などは複数アカウントを所持することでサービス提供側が望まない形で利益を得られてしまう。

## メールアドレスの一意性は弱い
同システムにて予約する際にユーザーはメールアドレスの入力も求められるが、
GmailやYahooメールなどフリーのメールアドレスを個人が複数持つことは難しくない。
反対に、一個人が複数アカウントを使用することが前提のシステムではメールアドレスの登録くらいがちょうどよかったりする。

## 電話番号の一意性
メールアドレスに比べて電話番号はどうだろうか。
電話番号の取得はメールアドレスほど手続きなど容易でなく、費用が掛かる場合がほとんどだ。
個人を特定するまでには至らないかもしれないが、サービスの不正利用に使うにはハードルが高い。
※実際には他人の電話番号を入力することなどもできてしまうため、電話番号を使用したSMS認証などが必要な場合もあります。


## 電話番号に等しい一意性
電話番号そのものを必須入力とするのではなく、外部アカウントを利用した認証を行うパターンもある。
LINEなどそもそも電話番号が必須となる外部のアカウントを使用した認証も電話番号の必須入力と同等かそれ以上の特定力があると思う。

## まとめ
- サービス・システムによって必須入力となる項目は異なる。
- 場合によってはガチガチに個人を特定する必要があるパターンもある。
- どの程度自由に使わせたいかによって何を必須項目とするか決めよう。
（自分用）react lazyと react-router-domを利用した時のエラー解決


問題
React v18にアップデートしたついでに、React.lazyのimportを実装した際、エラーが起きてしまった。


エラー文
>react_devtools_backend.js:4012 The above error occurred in the <Route.Provider> component: ＊＊＊


-- --

https://stackoverflow.com/questions/69949256/lazy-loading-in-react-router-dom-v6-0-2


Reactの`<Suspense>`で react-router-domの`<Route />`を挟む必要があった。
未経験からの転職

#  前提として

-  現職：専門学校の事務員
-  2021年にプログラミングスクール卒業
-  IT業界への転職を希望していたが具体的な成果物なし

## 　面接活動

ソフトウェア開発をされている地元の企業へ面接に行きました。
その会社は、「理念」を大切にしていて、理念に共感してくれる人と働きたいと
会社説明会で仰っていました。
また、作りやすいものを作るのではなく、使いやすいものを作るとも。
私は人に寄り添うことを大切にしていきたいと思っていたので、
この考え方に感動しました。

面接で、「あなたはこれからどんなことをしていきたいか」と問われ、
私は「昔はまちの電気屋さんがあったように、これからはまちのソフトウェア屋さんがあればいいと思います。」と答えました。
**まちのソフトウェア屋さん**はとても良い言葉だと褒めてくださり、いいキャッチコピーをもらったとも仰ってくださいました。

##  教訓として
1. 味方（助けてくれる人）を増やす
1. 色々なことに興味を示す
1. たくさん話を聞く
1. タイミングや運、巡り合わせ
止まっているよりは、動いてみる
1. 百聞は一見にしかず
1. 想いは言葉にする


まだスタートラインに立ったばかりですが、
３年後には夢が現実になっているように頑張ります！
paizaラーニング「【二次元配列の入出力】i番目の出力 Boss Python3編」

https://paiza.jp/works/mondai/array_primer/array_primer__2dmatrix_i-thoutput_boss
#### 私の解答
```Python3
values = input().split()
N = int(values[0])
M = int(values[1])
K = int(values[2])
L = int(values[3])

A = [[0] * M for _ in range(N)]
for i in range(N):
    values = input().split()
    for j in range(M):
        A[i][j] = int(values[j])

print(A[K - 1][L - 1])
```
前の問題の解答例を参考にしたので、同じになりました！
#### 解答例
```Python3
values = input().split()
N = int(values[0])
M = int(values[1])
K = int(values[2])
L = int(values[3])

A = [[0] * M for _ in range(N)]
for i in range(N):
    values = input().split()
    for j in range(M):
        A[i][j] = int(values[j])

print(A[K - 1][L - 1])
```
よく使う文字列の切り出し、チェック、変換方法まとめ

## 目次
　[1.文字列の切り出し編](#1-文字列の切り出し編)
　[2.文字列のチェック編](#2-文字列のチェック編)
　[3.文字列の変換編](#3-文字列の変換編)

## 1. 文字列の切り出し編
### Stringクラスのsubstringメソッド

```java
String str = "ABCD/12345";
System.out.println(str.substring(5));
```
引数を1つ指定する場合、引数で指定した位置から最後までの文字列を返す。※位置はAの前から0から数える
出力結果は12345

```java
String str = "ABCD/12345";
System.out.println(str.substring(5, 8));
```
引数を2つ指定する場合、引数で指定した開始位置から終了位置までの文字列を返す。※位置はAの前から0から数える
出力結果は123

### StringクラスのindexOfメソッドと併用して切り出す方法

```java
String str = "ABCD/12345";
int index = str.indexOf("/") + 1;
System.out.println(str.substring(index));
```
indexOfの位置の数え方は、subStringと異なり1から数えるため、subStringで使用する際+1が必要。
出力結果は12345（+1しない場合は「/12345」が返る）

## 2. 文字列のチェック編
### StringクラスのstartsWithメソッドで先頭文字のチェック
```java
String str = "ABCD/12345";
System.out.println(str.startsWith("ABC"));
```
"ABCD/12345"がstartsWithに指定された文字列で始まるかどうかをチェック。
出力結果はtrue

### StringクラスのendsWithメソッドで末尾文字のチェック
```java
String str = "ABCD/12345";
System.out.println(str.endsWith("345"));
```
"ABCD/12345"がendsWithに指定された文字列で終わるかどうかをチェック。
出力結果はtrue

### Stringクラスのmatchesメソッドと正規表現で文字列が数字かどうかのチェック
```java
String str = "ABCD/12345";
System.out.println(str.substring(5, 6).matches("[0-9]"));
```
str.substring(5, 6)で切り出されるのは文字列の1。
"[0-9]"は、正規表現で「1文字の数字」を表します。
出力結果はtrue

※その他正規表現は下記記事が分かりやすかったため、参考としてこちらに記載させていただきます。

https://www-creators.com/archives/4241


### DoubleクラスのparseDoubleメソッドで文字列が数字かどうかのチェック
```java
String str = "ABCD/12345";

try {
    Double.parseDouble(str.substring(5));
    System.out.println("この文字列は数字です");
} catch (NumberFormatException e) {
    System.out.println("この文字列は数字ではりません");
}
```
str.substring(5)で切り出されるのは文字列12345。
これをDoubleクラスのparseDoubleメソッドで、数値のDouble型に変換します。
変換できない場合は例外をスローします。（数字でない文字列やnullは変換不可）
出力結果はこの文字列は数字です

### 正規表現で数字の桁数チェック
```java
String str = "ABCD/12345";
System.out.println(str.substring(5).matches("[0-9]{5}")); 
```
str.substring(5)で切り出されるのは文字列12345。
"[0-9]{5}"は、正規表現で「5桁の数字」を表します。
出力結果はtrue

### Stringクラスのlengthメソッドで数字の桁数チェック
```java
String str = "ABCD/12345";
System.out.println(str.substring(5).length());
```
str.substring(5)で切り出されるのは文字列12345。
Stringクラスのlengthメソッドで、文字列の長さを取得し桁数確認をおこないます。
出力結果は5

## 3. 文字列の変換編
### IntegerクラスのparseIntメソッド
```java
String str = "ABCD/12345";
System.out.println(Integer.parseInt(str.substring(5, 8)));
```
str.substring(5, 8)で切り出されるのは文字列123。
この123は文字列のため、parseIntで数値に変換します。
出力結果は123

### 数値を文字列に変換する際はStringクラスのvalueOfメソッドを使用

```java
int num = 12345;
System.out.println(String.valueOf(num));
```
今度はint型からString型への変換です。
valueOfで12345を、数値から文字列に変換しています。
出力結果は12345
【GAS】スプレットシートのメニューから関数を実行する

# スクリプト
```javascript
function onOpen() {
  var ui = SpreadsheetApp.getUi()
  
  var menu = ui.createMenu("追加したニュー");
  menu.addItem("関数1を実行", test1);
  menu.addItem("関数2を実行", test2);
  
  //スプレッドシートに反映
  menu.addToUi();
}

function test1() {
  // 関数1
}
function test2() {
  // 関数2
}
```

# 実行後！
![スクリーンショット_2022-12-13_18_41_30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136275/221bad03-37ca-a219-0328-b20b4fca9f0e.jpeg)
kicad6の interactive html bom がランチャーから起動できない時の対処

### interactive html bom とは

- [参考](https://www.youtube.com/watch?v=lu3cDsuPIEA&ab_channel=CliffBrake)
- kicadの追加プラグインで、上の参考リンクのように画面左のbomリストにカーソルを合わせると、画面右のボード図上で、該当部品がハイライトされる。
- 手実装で便利。

### ubuntuでランチャーからプラグインのインストールを試みるも、上手く行かない

-ubuntu18.04でkicad6を開き、ランチャーの「Plugin and Content Manager」からインストールを試みる

![Unsaved Image 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691828/c5b7eeea-e77f-879d-9f86-300d58a806c2.jpeg)

- しかし、インストールしてもランチャーから起動メニューが見えないまま。
- windowsや、kicad6の他のリリースバージョンなら、上手く行くのかもしれないが、とりあえず手元のubuntuでは起動しないのでなんとかしたい
- 仕方がないので、下図のダウンロードからスクリプトをダウンロードし、コンソールからの起動を試みる

![Unsaved Image 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691828/8fbf16ba-a001-c020-058b-3b19220b6628.jpeg)

- ダウンロードをして、「plugin」フォルダの中に入っているgenerate_interactive_bom.pyがあることを確認する。（interactive html bomのコマンドの本体）

![Unsaved Image 3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691828/6318407a-87f2-8d2e-076a-c134aeaf2dd7.jpeg)

- 以下のコマンドで、実行

```bash
python3 generate_interactive_bom.py <表示したいプロジェクトのボードファイルへのパス>.kicad_pcb 
```

- コンソール上の結果及び、ブラウザに表示される interactive html bom

```bash
tomiyuichi@tyxps:~/Desktop/org.openscopeproject.InteractiveHtmlBom_v2.5.0/plugins$ python3 generate_interactive_bom.py ~/pcb_ty/atsamd09_test/atsamd09_test.kicad_pcb 
/tmp/pip-build-ilg63vj3/wxPython/ext/wxWidgets/src/common/platinfo.cpp(180): assert ""Assert failure"" failed in InitForCurrentPlatform(): failed to initialize wxPlatformInfo
/tmp/pip-build-ilg63vj3/wxPython/ext/wxWidgets/src/common/platinfo.cpp(107): assert ""value"" failed in wxGetIndexFromEnumValue(): invalid enum value
/tmp/pip-build-ilg63vj3/wxPython/ext/wxWidgets/src/common/platinfo.cpp(262): assert ""idx < (sizeof(wxPortIdNames)/sizeof(wxPortIdNames[0]))"" failed in GetPortIdName(): invalid port id
fatal: not a git repository (or any of the parent directories): .git
Git version check failed: Command '['git', 'describe', '--tags', '--abbrev=4', '--dirty=-*']' returned non-zero exit status 128.
Loading /home/tomiyuichi/pcb_ty/atsamd09_test/atsamd09_test.kicad_pcb
2022-12-13 18:20:42,828 INFO Compressing pcb data
2022-12-13 18:20:42,888 INFO Dumping pcb data
2022-12-13 18:20:42,889 INFO Created file /home/tomiyuichi/pcb_ty/atsamd09_test/bom/ibom.html
2022-12-13 18:20:42,889 INFO Opening file in browser

```

![Unsaved Image 4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691828/a67be959-63d6-f0f9-7bd7-afa4cbaed5ac.jpeg)

- 写真のファイルはいつ取ってきたのか、忘れてしまったけれどネットから取ってきたatsamd9のブレークアウトボードのようです。勝手に晒例示して、作者に申し訳ない。
- 以上


最近やってるアニメのlegend of mana見て、そういやこのソフトの開発スタッフが、当時のスクウェアを大量退社したんだっけと、思い出した。FFシフトだとかなんだとかで。それももう2２年くらい前の話か、我ながら年取ったもんだと思いました。

2022年12月13日
勉強会イベントへの軌跡 Ver.2022

Googleカレンダーに登録した勉強会イベントの回数を調べたところ、今年は268回のイベントに参加できました。
オンライン開催は移動のロスがないので個人的には大変ありがたい状況です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150628/9be351d8-e3b5-a29e-fc0e-0a20ff5d1e34.png)

今まで参加して出会った人ややってきたことをふりかえって
リスナーとして心掛けていることをまとめてみました。

1. 一番聞きたい登壇者や知りたい情報を決めておく
1. 質問するつもりで聞く
1. 感じたことはtwitterやチャット欄にてなるはやで言葉にする
1. 終了後にイベントをふりかえる

## 1.聞きたい登壇者や知りたいことを最低１つ決めておく

イベントに申し込む際、登壇者が埋まっていないまたはタイムテーブルやコンテンツが決まっていない場合が
ありますので、イベント直前にイベントページを確認して一番のおかずを最低１つは決めておきます。
複数ある場合はなお◎
そうすることでモチベーションが上がりイベントにより集中できるようになります。

## 2.質問するつもりで聞く

限られた時間で登壇者の話を少しでも長く聞きたい多くのことを知りたい
私はなんかしながら耳だけ参加する器用なことが性格的に苦手なので、
前のめりで聞きながら質問事項を作っています。
質疑応答の時間は、私にとってのアンコールステージ
質問は登壇者へのフィードバックにもなり、実際に喜ばれることが多いと思います。

イベントに参加して得た情報は後日いきなりデジャビュすることがあります。
これはイベント参加での効果が発揮できていると思いますので、
イベント後にデジャビュできるような準備も心掛けています。

## 3.感じたことはtwitterやチャット欄にてなるはやで言葉にする

言葉にすることはアウトプットの効果があります。
言葉にすることは登壇者へリアクションにもなり、
イベントが盛り上がります。

しかし言葉にすることへの注意は必要です。
主張や批判となりすぎないようこのように配慮しています。

* よかったことは感じたままの言葉で
* よくなかったことは自分に問いかけるような言葉で

## 4.終了後にイベントをふりかえる

鉄は熱いうちに打つべきで、イベントのふりかえりをします。
一緒に参加した人同士で話すのはもなお◎

* 聞けたこと・聞けなかったこと・さらに聞きたいこと
* 印象に残ったＴＯＰ３

# 最後に

最後まで読んでいただきありがとうございます。

この内容は12/23(金)にRPACommunityにて発表します。
ほかにも有意義な登壇が聞けるので、どしどしご参加ください！

https://rpacommunity.connpass.com/event/268690/
新卒1年目が現場で意識していること

# はじめに

社会人1年目・未経験エンジニアの岡本です。
現場に配属されてから半年が経ちました。

今回の記事を書くにあたって、技術に関してはまだまだわからないことが多いため
現場業務を行う中で意識していることを2点書いていこうと思います。




# 現場で意識していること

## 1. 周囲との認識を合わせる
個人的にはこれがすべてだと思います。
チームで動いている以上、個人プレーはNGです。
作業方針・進捗状況の共有ができていない場合、
大幅に作業の手戻りが発生する可能性があります。
ミスを最小限に抑えるためにも必要不可欠なことだと思います。

現場に配属されてから報連相が本当に大事だと実感しました。



## 2. メモをとる
とにかくメモをとる。
紙のメモ帳・ノート・PCのメモ帳でもなんでもいいのでメモをとる。

メモをとることで後から打合せ内容などを振り返ることができる上に、
頭の中を整理することもできます。
最近だと紙よりPCでメモをとることが多くなってきた気がします。
紙だとどうしても書く動作に時間が掛かってしまい、
聞き漏らしが発生する可能性が高くなるからです。

個人的に物事の整理には紙に書くことが一番だと思うのでうまく使い分けていきたいです。


# おわりに
現場で意識していることと書いていますが、正直難しいです。

自分が何を理解していて、何を理解していないのか
これらを相手に伝えるためには現状を客観的に把握する必要があります。
メモをとり現状を整理してから、相手との認識合わせを行っていく。
まずは、この流れをスムーズに行えるよう頑張っていきたいと思います。

閲覧いただきありがとうございました。
ArrayListに格納、取り出し、サンプル

```sample.java
    public static void main(String[] args) {
        List<String> li = new ArrayList();
        li.add("a1");
        System.out.println(li.getClass());
        for (String l:li) {
            System.out.println(l);
        }
```
実行結果
```
class java.util.ArrayList
a1
```
[powershell]CSVの列を配列にする

powershellでCSVを操作するとき、特定の列の情報を配列として取得していろいろやりたい時がある。
そんな時に一行で取得してくるやり方があるのでご参考まで。

例えばこんなCSVがあったとする。
```text:sample.csv
    no,name
    1,alexa
    2,google
    3,pepper
```

このCSVのname列のみを配列として取得したいときに下記のように記述すると１行で取得できる
```powershell:sample.ps1
    $namelist = Import-Csv .\test.csv -Encoding Default | Select-Object -ExpandProperty name
    $namelist
```
Select-Object の -ExpandProperty の引数に、取得したい列名を指定すればよい。

```text:出力結果
    alexa
    google
    pepper
```
デプロイ後最初に行うべきこと - 日本語を利用するためのセットアップ

こんにちは！

この記事ではTeradata Vantageをデプロイした直後にデータベースを利用するためにまず行うべき内容について記述します。

# セッションキャラクターセット
Teradata Vantageではデプロイ後のデフォルト状態でASCII、UTF-8、UTF-16の各キャラクターセットのクライアントからのログインが許可されています。
「各キャラクターセットのクライアント」とはそのクライアントがVantageに投げるクエリーが指定したキャラクターセットで書かれているということです。

Teradata Vantageは内部的にはデータをUnicodeで管理していますが、このセッションキャラクターセットにより文字リテラル等のコード変換を行います。したがってキャラクターセットが誤った設定となっているとデータを利用する際に文字化けが発生する可能性があるのです。

日本語環境でデータウェアハウスシステムを使用する際には特にある程度古いシステムをソースとするデータではShift-JISコードで書かれたデータが連携されることがよくあります。

デプロイ直後のデフォルト状態ではそのようなデータを正しく取り込むためのセッションを張れないということになりますので、Teradata Vantageで利用できるキャラクターセットを拡張する必要があるのです。

# セッションキャラクターセットの拡張方法
Teradata Vantageをデプロイしたら、Teradata StudioのようなSQL実行ツールを使用しデフォルトのキャラクターセットを使用してスーパーユーザー”DBC"でログインしてみてください。
そして下記のクエリーを実行してみてください。

```SQL:Charset.sql
SELECT CharSetName,CharSetId,InstallFlag FROM DBC.CharTranslationsV ORDER BY CharSetId;
```
このような結果が返るはずです。

| CharSetName | CharSetId | InstallFlag |
|:-:|:-:|:-:|
|EBCDIC037_0E|96|N|
|EBCDIC273_0E|97|N|
|…|…|…|
|KANJIEUC_0U|118|N|
|KANJISJIS_0S|119|N|
|…|…|…|
|LATIN9_0A|125|N|
|LATIN1_0A|126|N|

全部で29行の結果が返るはずですが、途中を端折らせていただきました。
この表にをご覧いただくとわかる通り例えばShift-JISのためのキャラクターセット”KANJISJIS_0S”のInstallFlagは”N"となっています。

使用できるキャラクターセットの拡張はこのInstallFlgを”Y"に更新することで行うことができます。
したがって、

```SQL:UpdateCharSet.sql
UPDATE DBC.CharTranslationsV SET InstallFlag = 'Y' WHERE CharSetId = 119;
```

というクエリーを実行すればよいことになります。
更新結果を確認すると

```SQL:ConfCharset.sql
SELECT CharSetName,CharSetId,InstallFlag FROM DBC.CharTranslationsV WHERE CharSetId = 119;
```

| CharSetName | CharSetId | InstallFlag |
|:-:|:-:|:-:|
|KANJISJIS_0S|119|Y|

とInstallFlgが変化していることでしょう。
このように、使用が考えられるキャラクターセットについてはInstallFlagを”Y”に更新してください。

# データベースのリブート
このキャラクターセットの変更は実はデータベースを再起動するまで有効とはなりません。
したがってテーブル設定値の変更を行ったのちには、VaaSをご利用の場合はコンソールからデータベースの再起動を実施してください。

これでデプロイされたTeradata VantageにShift-JISコードで書かれたファイルをロードする準備が整いました。
この後はデータベース（ユーザー）を作成し、データの取り込みを開始しましょう！

では、次の機会にまたお会いしましょう！

:::note info
インフォメーション
このスタートアップガイドはWEB上で公開されております[Teradata Vantageドキュメンテーション](https://docs.teradata.com/)よりトピックに必要な情報を抜粋したものです。
:::

#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
インスタンスのクラスを確認する

・インスタンスについてgetClass()をとると、Class名を取得できる
・instanceofで、Class名を比較
```Sample.java
    public static void main(String[] args) {
        System.out.println(Integer.valueOf("1").getClass());
        System.out.println(Integer.valueOf("1") instanceof Integer);
    }
```
```実行結果
class java.lang.Integer
true
```
Djangoでよく使うコマンド一覧

自分用にメモ。

## 基本的なコマンド

```
#サーバー起動
python3 manage.py runserver
```

### データの読み込み（loaddata）

```
//ファイルを読み込む
python3 manage.py loaddata ファイル名

//特定アプリ以外のファイルを読み込む
python3 manage.py loaddata --exclude アプリ名 ファイル名
```

> ダンプファイルは以下の順に探しに行きます。
・settingsのINSTALLED_APPSに指定したすべてのアプリケーションのディレクトリ直下の引数値のディレクトリ
・settingsのINSTALLED_APPSのアプリケーションのFIXTURE_DIRSに指定したディレクトリ
・引数値を相対パスとした場所
[参考](https://marsquai.com/745ca65e-e38b-4a8e-8d59-55421be50f7e/05f253f8-c11b-4c91-8091-989eb2600a7b/229d6ef3-1ba3-4e16-bdd7-c5f01c6dfb12/)

### データコピー（dump）

```
//アプリ全体
python3 manage.py dumpdata アプリ名

//出力ファイル名オプション
python3 manage.py dumpdata アプリ名 -o ファイル名

//特定のテーブルのみ
python3 manage.py dumpdata アプリ名.テーブル名
```

参考：[【Django】データベースのダンプファイル取り扱い方解説](https://marsquai.com/745ca65e-e38b-4a8e-8d59-55421be50f7e/05f253f8-c11b-4c91-8091-989eb2600a7b/229d6ef3-1ba3-4e16-bdd7-c5f01c6dfb12/)

### マイグレーション関係

```
# マイグレーションファイルを作成
python3 manage.py makemigrations [app名]

# マイグレーションを実行
python3 manage.py migrate

# 過去マイグレーションの確認
python3 manage.py showmigrations

# マイグレーション履歴の全削除（ロールバック）
python3 manage.py migrate --fake app（アプリ名） zero

# マイグレーション履歴の一部削除（ロールバック）
python3 manage.py migrate app（アプリ名） 0001_initial（マイグーション番号）
```

## データベース系のシェル関係

```
# シェル起動
python3 manage.py dbshell

# テーブル一覧を表示
.tables

# テーブル削除
drop table hogehoge（テーブル名）

# 終了
controlキー + cキー
```
Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その１）

# ロボットを作ろう！

## まえがき
2022年10月頃からコツコツとロボット作りをしてきたのですが、ある程度形になってきたので、記録がてら作成手順を（振り返りながら）書いていこうと思います。


### 作りたいもの
世の中的には、二足ロボや四足ロボがメジャーな感じなのですが、どうせ作るなら自分の好み（ロマン）を詰め込んだものを作りたい。

### というわけで
これ作ります。
クローラー式2脚ロボ、クローラーの動力はクローラー内部に入れることで省スペース化し、関節をもたせることで立ち上がる（？）ことも可能。
足関節として、8軸のサーボを使っているので、多少の悪路も移動可能（だといいな）。
また、バッテリーはラズパイ用とは別に18650x3のカートリッジを換装可能（フロント側面の丸いデザイン部分）
フロントはモニター＋超音波センサーを搭載してリアルタイムで状況確認可能
フロント左右にはフルカラーLEDを搭載してゲーミングロボットとしても活躍可能（違
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51900/8711021a-abf4-8e30-8ffc-a887ca7aa7d9.png)

### そして
形になりました♪（上のデザインは古いため、一部見た目違いますが）

左右の空気孔っぽいのはスピーカーを搭載。最終的にはAIによる音声認識＆対話ができると面白いな。
内部には、9軸のIMUや温度・湿度・CO2センサーなども色々突っ込みました。
![2022-12-13 17.12.44.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51900/7bed8d83-0386-0bf9-425d-57e6d19a8196.jpeg)


### ということで
ハードはほぼできたので（中身はユニバーサル基板＆配線だらけなので基板設計もしたいところですが）、ソフトの方の導入手順など忘れないように記事にして行こうと思います。

## OSの選定基準

### ラズパイでROS2
ラズパイでROS2を使ったロボット製作の場合、OSをRaspidianにするか、Ubuntuにするか、またROS2のバージョンをどうするか色々試行錯誤しました。

たとえば、Raspidian（64bit）を使った場合 ROS2の実装がちょっと難しい＆カメラのコントロールができないという問題がありました。

Ubuntuも最新の22.10だと、最新すぎるためかちょこちょこと問題があったため、最終的にはタイトル通り、Ubuntu22.04 + ROS2 Humble で実装することにしました。


## 目次

* Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その１）
* [開発環境づくり１::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その２）](https://qiita.com/shoichi4411/items/40af18ce4e11254aef61)
* [開発環境づくり２::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その３）](https://qiita.com/shoichi4411/items/c775d3c3c040742e9925)
* [ROS2導入::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その４）](https://qiita.com/shoichi4411/items/694a45314cbfe704d20d)
* [ROS2とWebの連携::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その５）](https://qiita.com/shoichi4411/items/fcbe4b0fc2d98c72b55e)
* [Webでカメラ表示::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その６）](https://qiita.com/shoichi4411/items/e0aa33d9ce286485c5a8)
* [WebでIMU取得::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その７）](https://qiita.com/shoichi4411/items/bb9e792a0dfb600c90ad)
* [バッテリー監視::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その８）](https://qiita.com/shoichi4411/items/a38261c921746c5d71d5)
* [スマホカメラとSSLとWSS::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その９）](https://qiita.com/shoichi4411/items/caa67154b833e28eda26)
* [足回りの制作::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（ハードウェア編その１）](https://qiita.com/shoichi4411/items/75966efb74bcbf6d78c4)
* [Webでクローラーの制御::Raspberry Pi4 + Ubuntu22.04 + ROS2 Humble でロボット作り（その１０）](https://qiita.com/shoichi4411/items/3f4ff9166783aa9b63c8)
SessionとCookie

## はじめに
Railsでは```devise```という、それはそれは便利な認証機能用の```gem```がありまして、それに頼り切ってしまっていたため```cookie```がどうとか```session```がどうとかという根本的な理解ができていませんでした。
それが最近バレてしまったので、この機会に```session```と```cookie```についてまとめたいと思います。

## Cookie
```cookie```は、ステートレスな```HTTPプロトコル```をステートフルにすることができる代物です。

元来、HTTPリクエストはステートレスであるため、前後のリクエストとの関係を持つことはなく独立したものです。
なので、1つ前のリクエストの内容を引き継ぐみたいなことができません。

これを解決するのが```cookie```です。
サーバーはリクエストがあると、以後同じ相手からのリクエストを特定するために```set-cookie```ヘッダーを付与してレスポンスを返します。
その後のリクエストでは、その```set-cookie```ヘッダーに指定された値を```cookie```ヘッダーに付与してリクエストを送ることでステートフルを実現します。

ブラウザは優秀なので、レスポンスのset-cookieヘッダーで指定された値をリクエストの```cookie```ヘッダーに自動で指定してくれますが、curlコマンドなどを使うときはオプションを指定する必要があります。
```terminal
    curl -b "key=value" http://example.com/
```

https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies

https://policies.google.com/technologies/cookies?hl=en-US

## Session
```session```はユーザーに固有のステートを維持するためのデータ貯蔵庫です。
バックエンド側は、各ユーザーにセッションオブジェクトを割り当てることによって、どのユーザーからのリクエストかを識別できるようにしています。
```ruby
    session[:user_id] = @user.id
```
sessionは```ActionDispatch::Request::Session```クラスのインスタンスで、```[:user_id]```はインスタンスメソッドです。
sessionが呼ばれるたびに新しいインスタンスが生成されるので、上書きされることはありません。(```session[:user_id]```だったら同じ```key```に値を代入してるから上書きされるだろ！と思ってました...）

Railsでは[ActionDispatch::Session::CookieStore](https://edgeapi.rubyonrails.org/classes/ActionDispatch/Session/CookieStore.html)をデフォルトのストレージ(貯蔵庫)にしています。**※ ここがcookieとsessionが交わる地点**
```cookie store```では、生成されたsessionをいい感じに暗号化してくれて、それをレスポンスに乗っけてくれます。
また、```cookie store```だけでなくデータベースやキャッシュもセッションストレージとして使用することができます。


https://www.justinweiss.com/articles/how-rails-sessions-work/

https://railsguides.jp/security.html#%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3

https://www.theodinproject.com/lessons/ruby-on-rails-sessions-cookies-and-authentication

https://qiita.com/zettaittenani/items/a75f0da8f44cfe0f85c0

## まとめ
```リクエスト```
↓
```sessionオブジェクトの作成```
↓
```cookieStoreに保存される```
↓
```set-cookieヘッダーで指定してレスポンスを返す```
↓
```set-cookieで指定されたハッシュをcookieヘッダーに含めて、リクエストすることによってステートフルを実現```
Webスクレイピングで、"Src"のデータを適切に取得する方法

#生じた問題
Pythonを用いて、Webスクレイピングを実行していた。
Imgタグの、src属性の値を習得しようとしたが、上手く習得できなかった。
下記に、異常な内容を示します。
![srcのコードがおかしい.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2963171/c7859000-1dc4-070b-2cb4-0bbfee375218.png)

使用したコードは、下記の通りです。
```
for soup in atriclesoup:
    img = soup.find('img').get('src')
    print(img)
```
#解決策
1.	print関数で、習得していたデータを確認する
2.	srcの他に、習得できるデータがあることを確認する
3.	data-src のタグを用いて、データを取得する
print関数を用いて、データを確認してみると、
![全部の要素印刷.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2963171/0b199b7d-deec-3947-b0db-d7576b23e6d6.png)
srcの値が異常なのは変わらず。
でも、その他に[data-src]の存在を確認できました。
え、Srcだと思ってたけど、実は[data-src]が正しかった…？
HTMLを確認してみると、
![元々のHTML.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2963171/d9398848-5512-9ee9-d6d9-fb65be4f06bd.png)
そして、[data-src]のデータを取得すると、無事取得できました。
![上手く引っ張れたデータ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2963171/4e2c6166-9586-5c6a-dcc5-ae1d8f934267.png)

これは予想だけど、画像などはバイナリデータ（0と1で作られているデータ）だから、上手く文字として反映されていないのだろうと、スクレイピングしながら気づきました。

#おわりに
もし、コード自体に間違いはないと確信がある。
その場合は、一度Print関数を用いて、目視で確認するといいかも
実は、別のデータでも求めているものが引っ張れたりする。
と勉強になりました！
Workato：Feedback機能で機能要望や改善要望を出していきましょう

# はじめに
Workatoをお使いの方は、右下のアイコンを見たことがあると思います。（常に表示されていて鬱陶しいと感じている方もいるかもしれません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/0ab23455-dc18-2313-3874-7d163774255b.png)

このアイコン（Resource hub）は、ドキュメントやトレーニング、プロダクトアワー等の製品の理解や活用に役立つコンテンツへのショートカットや、ライブチャットによるWorkatoのサポート等、Workatoを活用する上で便利な機能が揃っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/9b5b1952-ff19-d842-b509-f6ccd39fb318.png)

# Share your feedback

この中で「Share your feedback」というリンクがあります。これは、Workatoに機能要望を行うための機能になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/8c6dd7bb-5854-793c-45b8-71d3e9e5c124.png)


「Share your feedback」をクリックすると、以下のような画面が表示され、最近リリースされた機能や、要望をあげた、または「いいね」した内容、他のユーザーが投稿した機能要望が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/324a16b0-7efb-1c87-f177-f038b178c204.png)

## 一覧表示

赤丸で示したボタンをクリックすると、それらを別画面で見やすい形で一覧表示することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/5471df2b-2e2d-6953-8f70-11b040f6717b.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/8e89a2f0-bbe5-7098-a05e-84863d49d665.png)

## 機能要望を行う

「Make a suggestion」をクリックすると、機能要望を行うことができます。
なお、日本語に対応していないため、機能要望の内容は英語で入力する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/9aacf1e8-6af8-1a7b-4d37-24d7ab9d5450.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/07d0fcb4-1b74-5ee5-e628-ead203f7856e.png)


## 投稿済の機能要望を確認する

リストより投稿済の機能要望をクリックすると、その詳細を確認することが出来ます。
また、右側にはWorkato側の対応状況（Request Status）や、他のユーザーの「いいね」の数を確認することができます。
もちろん、この画面で「いいね」することも可能です。
「いいね」の数が多ければ、追加機能や機能改善の優先順位が高くなるかもしれません。
是非気になるものがあれば「いいね」してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/1ab8ddd9-1f03-0dec-a8b7-5f88234caf8a.png)


# 最後に

Workatoを使いやすくするために、またもっと活用していくために、この機能やこの製品・サービスのコネクタが欲しい、この機能がもっと使いやすくなればいいな等、Workatoに実現してほしい、あるいは改善してほしい機能など、どんどん要望を出していきましょう！
PHP Laravel CarbonImmutableのインスタンスの時間情報を1時間追加する

:::note info
この記事は[miriwoお一人様 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/miriwo)の13日目の記事です
:::

# 概要

- CarbonImmutableのインスタンスの時間情報を1時間追加する方法をまとめる

# 方法

- インスタンスに`addHour()`メソッドで1時間追加する。

    ```php
    use Carbon\CarbonImmutable;

    $dateTime = new CarbonImmutable('2023-01-01');
    echo $dateTime; // 2023-01-01 00:00:00

    $dateTimeAddOneHour = $dateTime->addHour();
    echo $dateTimeAddOneHour;// 2023-01-01 01:00:00
    ```

- ちなみに`subHour()`を使うことで1時間引く事ができる。

    ```php
    use Carbon\CarbonImmutable;

    $dateTime = new CarbonImmutable('2023-01-01');
    echo $dateTime; // 2023-01-01 00:00:00

    $dateTimeSubOneHour = $dateTime->subHour();
    echo $dateTimeSubOneHour;// 2022-12-31 23:00:00
    ```
リモートでチームでワークすること

こんにちは。
この記事は、[ソフトウェアテストの小ネタ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/software-testing-koneta)　14 日目の記事です。

リモートワークが珍しくなくなったことで、働き方の選択肢が増え、皆さん働き方に応じたコミュニケーションの取り方をされているかと思います。

個人的には、第2子出産とほぼ同時期にコロナ禍が幕開けしたため、
リモートワークが普及した時流は、幼児を子育て中の私にとってメリットが多かったです。

また、テスト界隈のオンラインイベントが増えたことで、圧倒的に勉強会に参加がしやすくなりました。
手を動かすといった作業が出来なくとも、育児しながらも耳からインプットしてもらえるイベントにはいつも感謝しています。

さて、現在私は東北でほぼフルリモートで業務を行っていますが、自身の部下も上長も同僚も、東京をはじめとした他地域にいます。

自チームのメンバーだけではなく、各地に散らばるエンジニアたちと仕事を進める上でやってみたことをポエムとして書いてみます。

### モニタリングの手段
　コントロールするには進行状況のモニタリング方法を最初に決める事と、メンバーがそれを常に確認できることがまずはじめの一歩だと思っています。
　~~(分かっていながら、色々な理由でコレを怠った際にはすぐに関係者もろとも迷子になり、不穏な空気が流れ出し‥というのも経験しました。)~~

　進捗管理をするような便利なツールは沢山あるようですが、デイリーで数字の管理が必要ではないようなタスクを管理したい場合、私は社内で導入されているNotionのタスク管理機能を使いました。
　Notionはテンプレートが多く初心者にとっかかりやすいのと、ちょっとしたwikiにも使いやすいので個人的に重宝しています。
　社内でABD読書会をやった際にも、流石に付箋代わりにはならないかなあと思いましたが、DBが代替えで使えたりもしました。

　また、見える所で情報共有した上でですが、関係者を集めたディスカッションも、物理出社しているメンバーと在宅メインのメンバーとの間に生まれがちな情報格差を縮めること、文面では察しづらい疲労の度合いやモチベを把握することにも一役買ってくれていたと思います。


### 画面共有と画面キャプチャ最強
　環境構築で手間取っている場合や、分かりづらい不具合を説明する場合等、実際に実物を見た方が早いケースは多々あります。
　開発とテストの部隊が離れている時は特に、不具合報告時の画面キャプチャやログは必須なので役割的に慣れていると言えば慣れているのですが、不具合報告以外のシーンでも同様でした。
　物理的に同じ画面をみるのと同様にGWS上の資料を画面共有して複数人で編集しながらテスト方針を相談したり、状況を伝えるための画面キャプチャや不具合再現動画を上手く使うことで、報告する側もされる側も所謂「意思疎通をしやすいのと手っ取り早い」のは間違いないと改めて思いました。

### 漠然と考えていることをシェアする
　各自が後回しにしがち(でも必要)なタスクを行う場として、もくもく会？という名のモブワークをする場を作ってみたのですが、気づいたらそこで交わされる何気ない会話で方針が決まったり、各自が漠然と思っていたことが形になるということがありました。

　これは副次的効果として、コミュニケーションの量が増えるために発言の敷居が下がるという面があったような気がしています。

　また、対面で集まってテストをしていると他の人が見つけた不具合情報が耳から入り続けてくるもので、そこでヒントを得て自分もやってみた結果別の不具合が‥のようなシーンをリモートでも再現できるといいのかなあと考えています。

### さいごに
ソフトウェアテストに関係なくなってしまいましたが、小ネタならギリ許されるのでは…と考え書いてみました。おわりです。
axiosでPUTしたらPHPの$_POSTが空になる件

PHPではPUTメソッドの時は標準入力からデータを取る。
[PHP: PUT メソッドのサポート - Manual](https://www.php.net/manual/ja/features.file-upload.put-method.php)

いやどう考えても面倒くさい。

## axios側で対応

POSTで送信して`X-HTTP-Method-Override`ヘッダでPUTを指定すれば良いぞ。

```js:axios v1.2.1
axios.interceptors.request.use((config) => {
  const method = config.method?.toLowerCase();

  if (method === 'put') {
    config.method = 'post';
    config.headers = { 
      ...config?.headers,
      'X-HTTP-Method-Override': 'PUT'
    };
  }

  return config;
});
```
Db2 : SQLで正規表現(1)正規表現サポートのための関数一覧

Db2 LUW（Linux,Unix and Windows版）ではV11.1から正規表現をSQL内で使うことができるようになっており、Oracle互換機能の一環として、Oracleと互換性のある以下の関数が使用できます。

# Db2の正規表現サポートのための関数一覧

|関数名|機能概要|
|:---|:---|
|REGEXP_LIKE|探索結果（マッチの有無）をTRUE (1)またはFALSE(0)で返す|
|REGEXP_COUNT<br>(別名: REGEXP_MATCH_COUNT)|第一引数の文字列値に対して第二引数のパターンがマッチした回数を返す|
|REGEXP_INSTR|マッチした箇所の位置（最初にマッチした場所が先頭から何文字目か)を返す|
|REGEXP_REPLACE|マッチ箇所を置換パターンで置換した文字列を返す|
|REGEXP_SUBSTR<br>(別名:REGEXP_EXTRACT)|マッチ箇所の文字部分列を返す|


 

# 参考資料


- [Db2 11.5 Knowledge Center](https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_11.5.0/com.ibm.db2.luw.welcome.doc/doc/welcome.html)

    - [正規表現の制御文字](https://www.ibm.com/docs/ja/db2/11.5?topic=sql-regular-expression-control-characters)
    - [正規表現スカラー関数](https://www.ibm.com/docs/ja/db2/11.5?topic=sql-built-in-functions#r0011043__t11043-regexs)
    



- Db2 11.1 Knowledge Center
    - [新機能：SQL の互換性の機能拡張：スカラー関数での正規表現サポート](https://www.ibm.com/docs/ja/db2/11.1?topic=ga-sql-compatibility-enhancements)
SpringBootでのテストコードの簡単導入（UTの書き方の記憶を呼び覚ましたい人向け）

## 前提

SpringBoot 2.7.6 準拠。

## 起動

テストクラスに `@SpringBootTest` を付ける。

サーバとして起動させてテストしたい時は、
```Java
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
```

上手く起動しない場合、`classes`でSpringBootの起動クラス（`@SpringBootApplication`が付いてるクラス）を指定する。
```Java
@SpringBootTest(classes = TopazBackendApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
```

## 実行

### テスト実行

実行させたいメソッドには `@Test`を付ける。

### SQL実行

SQLを実行したい場合、 `@Sql("classpath:ファイル名")` を付ける

### モック化

`@MockBean` or `@SpyBean`

検索すると良く引っかかる↓は不要（SpringBootのverupで要らなくなってると思われる）
` @InjectMocks`, `MockitoAnnotations.initMocks(this);`

### 標準出力、エラーが欲しい場合

テストクラスに `@ExtendWith(OutputCaptureExtension.class)`
関数の引数に `CapturedOutput output`

### モックされたインスタンスメソッドに渡された引数値を見たい場合

```Java
// モックの宣言
@MockBean
HogeService hogeService;

// ...略...

// 以下、テストコード内（String は HogeService#mockedMethod(String arg) の引数型）
final ArgumentCaptor<String> capture = ArgumentCaptor.forClass(String.class);
doNothing().when(hogeService).mockedMethod(capture.capture());

// 値の取得は
capture.getValue();
```

## メモ

* [テスト機能の公式](https://spring.pleiades.io/spring-boot/docs/current/reference/html/features.html#features.testing)
「Ruby on Rails」Sidekiqジェムを紹介する


# 1. 概要


・Sidekiq は、Rails アプリケーションでバックグラウンド ジョブを実行するための gem です。
・Sidekiq は、マルチスレッドと Redis を使用して複数のジョブを同時に処理します。
・Redis は、ジョブをキューに格納するためのデータベース ストアとして理解されます。

# 2. コンフィギュレーション
### Sidekiq：
`Gemfile` に次の行を追加します: `gem "sidekiq"`

次に、`bundle install` を実行します

### Redis:
次のリンクに従って Redis をインストールします: https://redis.io/topics/quickstart

ファイル `config/initializers/sidekiq.rb` で Redis に接続するように Sidekiq を構成します。

    Sidekiq.configure_server do |config|
      config.redis = {
        url: "redis://127.0.0.1:6379/12"
      }
    end

    Sidekiq.configure_client do |config|
      config.redis = {
        url: "redis://127.0.0.1:6379/12"
      }
    end

 # 3. 活動の流れ
Sidekiq は、**sidekiq クライアント**、**sidekiq サーバー**、**redis** の 3 つの主要部分で構成されています。

### sidekiq クライアント:
・Redis のキューにジョブをプッシュする責任があります。

・`JSON.dump` 関数を使用して、データをハッシュに変換します。

・注意: 渡される引数は、`string、integer、boolean、float、null(nil)、hash、array` などの単純な json 型である必要があります

### sidekiq サーバー:
・処理のために Redis のキューからジョブを取得する責任があります。

・Worker を開始し、渡されたパラメーターを使用して perform 関数を呼び出します。

### redis: ジョブを保存するところです

# 4. ジョブのライフサイクル
![jobcyclelife.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2991099/dec3ad04-03a4-2832-0efd-32e20c90dc3c.png)
##### 1.Scheduled:実行待ちのジョブ一覧
##### 2.Enqueued: キュー内のジョブを実行中
##### 3.Busy：ジョブ実行中
##### 4.Failed カウンター:
 ジョブが実行されたものの、失敗して完了しなかった回数。
デフォルトでは、ジョブが破棄されるまでに失敗できる回数は 25 回です。
回数を超えると、ジョブはデッド キューに移動されます。
ジョブを作成するとき、次のようにカスタマイズできます: `sidekiq_options :retry => 5`
##### 5.Processed: ジョブが完了しました
##### 6.Retries:
 ジョブが失敗した場合、失敗カウンターが許可された失敗回数を超えていなければ、ジョブは常に再試行キューに含まれます。
##### 7.デッドキュー: 
許容回数を超えなかったジョブは、デッドキューにプッシュされます

# 5. 使い方
**Sidekiq** と **Redis** を構成したら、**Sidekiq** を使用する準備が整いました。

次のコマンドを実行します: `rails g sidekiq:worker Hard`

その後、ファイル `app/workers/hard_worker.rb` が自動的に作成されます。 または、そのファイルを手動で作成することもできます。

    class HardWorker
      include Sidekiq::Worker

      def perform(*args)
        # do something
      end
    end
その中で、 **perform** はバックグラウンドで実行されているタスクを実行する関数になります。

`*args` は渡される引数です。 入力引数は、string、`integer、boolean、float、null(nil)、hash、array` などの単純な `json` 型でなければならず、`symbol, name parameter、Date、Time` などの ruby​​ オブジェクトを使用しないでください。

バックグラウンドで実行するジョブを作成します。

・非同期処理用のジョブを作成します。

    HardWorker.perform_async('bob', 5)
デフォルトでは、sidekiq スケジューラーは **5 秒**ごと (**sidekiq < 5.1 の場合は 15 秒**) に**スケジュール ジョブ**をチェックし、`config/initializers/sidekiq.rb` ファイルでその値をリセットできます。
    
    Sidekiq.configure_server do |config|
      config.average_scheduled_poll_interval = 15
    end

**テスト実行**: 実行するには、3 つのタブを開く必要があります

・タブ 1: redis-server `redis-server` を実行する

・タブ 2: sidekiq `bundle exec sidekiq` を実行する

・タブ 3: `rails s` サーバーを実行する

実行するジョブを作成して結果を確認する
![1148e952-458f-4399-bca5-279259fa0578.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2991099/4eb4bca2-51b5-7bdc-1ec1-797b215478de.png)

# 6. 参考
##### https://github.com/mperham/sidekiq
Outputで助かるのは誰？

この記事は、[Qiita史上最多記録をつくろう！アウトプットはいいぞカレンダー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/output)のエントリー記事になります。

アウトプット、プログラミングをしている人であればみんなやっているのかと思えば意外とそうでない界隈で仕事をしています。
あと、企業ポリシー的に個人の意見が述べづらいというのもあるかもしれませんが、幸運なことに私はフリーランスなのでどこにも気にせずアウトプットをしています。

# 誰得？
今回は、「Outputで助かるのは誰？」というタイトルです。
誰得ってところです。
誰？
自分に決まってるじゃないですか。
自得ですよ。
しかも将来の自分が得するようにアウトプットしています。

この記事では、自得ポイントを紹介します。

# 辞書になる
「あれってどう書くんだっけかな？」とURLバーにそれっぽいわからないことを入力すると、自分の記事がヒットすることがよくあります。
ネットに漂う自分の記事が辞書になるのです。

# 綺麗な字で読める
物理的なノートのように「これは本当に自分の字か！？解読できん！」と声を荒げることもありません。

# 図解で見える化
ついでに、図なども挿入して見える化しておくと、最低限の文章を読むだけで、自分がやりたいことがなんだったのか思い出せます。
時短ですね。
文章だけを再生速度標準とした場合、図を見て解決できることがあるならば、それは1.5〜2倍速で読んでいることに匹敵します（当社比）。

図解については、公式のページが文字だらけで（よくある）一見すると枕が友達になってしまいそうな瞬間がきますが、それを紐解いて図解して記事に貼っておくと、なんてことでしょう。
公式よりも自分の記事を見た方がわかりやすい、ということがある（かも）のです。
学生時代に先生の板書よりもわかりやすいノートを目指し、友達に貸す（いくらで貸す？）などしていた人は、この意味がわかるのではないでしょうか？
また、自分の読解力も増すという利点もあります。

# 英語も問題なし
昨今ではブラウザに翻訳が標準実装されていることも多くなりました。
このおかげで「うわ、英語だ」とページを閉じることなく翻訳をポチると自国の言語で表示してくれます。
ちょっと変な翻訳だなと思っても、技術内容は小説のように細かいニュアンスがなくても意味が通じればOK的なところがあるので、大体理解できます。
英語で読むとしても、IT関連で使われている定型文のようなものがあるので、何度か英語のページをそのまま読んでいくと大体わかります。
次からは同じような定型文が出てきたらなんとなく理解できてしまいます。
読むだけなら英語もどんとこいです。

# 思いのほか、人様も助かっている（模様）
たまに、書いた記事にいいねがついたりストックされます。
なんか、役に立っているようです。
ただ、残念なことに、私の書いている技術記事を読んでいるのはQiitaにアカウントを持っていない人の割合が多いようで、いいねもストックもほんの少ししかつきません。

人は、承認欲求が溜まると、たまにどこかのツボに吐き出したくなりますが、そういう悶々とした気持ちでカンファレンスなどをウロウロすると「Qiita記事読んでます！」とたまに声をかけられます。
神です。
拝みます。

# アウトプットはいいぞぅに共感
今回のQiitaネタに共感して、一気に書き上げました。

# 始まりはここから
ちなみに、私のQiitaでの最初のアウトプットは、2014年12月01日、まさにAdvent Calendarへの投稿から現在に至っています。

https://qiita.com/tyuma/items/f87d7e8dd6c2a31d9c82

まさかこんなに記事を書くとは思っていませんでしたが、ものすごく自得になっています。
これからも自得、そして誰かのためになる（かもしれない）記事を書き続けていきたいです。
webhookURLでGoogleSpreadSheetsに自動書き込みしてみる

## はじめに：webhookURL とは
サービス同士の連携に使うもの。webhookURLを発行したり設定できるサービスは色々ある。
今回は、「backlog」と「GoogleSpreadSheets」を連携させて、backlogでタスクが登録されたときにGoogleSpreadSheetsに自動で書き込みできるようにする手順を例に紹介します。


## 用意するもの
* backlogのプロジェクト（できればプロジェクト管理者権限以上）
* GASが使えるGoogleSpreadSheets

## 01.GoogleSpreadSheetsを作成
backlogのデータをインサートしていくGoogleSpreadSheetsを用意します。


## 02.GASでwebhookURLを作成
GoogleSpreadSheetsで「ツール」＞「スクリプトエディタ」をクリック！
deploy（公開）してwebhookURLを生成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1138631/808102b8-d890-74cc-33a4-b24026bea1a0.png)

deployをクリックして表示される`Current web app URL:`をコピーしてください。


## 03.backlogにWebHookURLを設定する
##### 場所：backlogの「プロジェクト設定」＞「インテグレーション」＞Webhookの「設定」＞「Webhookを追加する」

- `WebHook URL`のフォームに、GASで生成したURLを登録する。
- `通知するイベント`で、webhookのトリガーを設定する。
今回は「課題の追加」を選択しています。

実行テストをして、送信履歴でjsonが飛ばせていることを確認できればOK！

## 04.GoogleSpreadSheetsに自動書き込みする
GASにコードを書いていきます。
backlogで発行されたjsonをGAS側で成形して、シートに書きこみする処理。jsonで届くデータの中で、シートに書き込みしたいカラムを`data.content`で指定してください。

**(sample)backlog→GoogleSpreadSheets**
```js
// backlogで課題の追加をした時にGoogleSpreadSheetsに書き込みする処理
function doPost(e) {
    let ss = SpreadsheetApp.getActive()
    let sheet = ss.getActiveSheet();
    let data = JSON.parse(e.postData.contents);
    sheet.appendRow([
        data.content.key_id,
        data.content.issueType.id,
        data.content.issueType.name,
        data.content.summary,
        data.content.description
    ]);
    return data;
}
```
backlogで課題の追加をした時にシートに行追加されるようになりました！！！
webhookURLを設定できるいろんなサービスで使えます、機会があればぜひお試しください！
TeraTermで起動と同時に自動ログイン（またはパスワード入力待ちの状態で起動）

# やり方（起動と同時に自動ログイン）

TeraTermには接続先情報を覚えておくような機能は無い。

そのかわり、引数ありの『ttermpro.exe』へのショートカットで自動ログインができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/fd5f2a53-60f1-5183-dd72-6d982694f190.png)


```:ショートカットのリンク先
"C:\Program Files (x86)\teraterm\ttermpro.exe" 接続先IPアドレス /auth=password /user=ユーザー名 /passwd=パスワード
```

# やり方（パスワード入力待ち状態での起動）

自動ログインの方法だと、ショートカットのリンク先でパスワードが平文で見れてしまう。
それだと都合悪い時もある。

そういった時向けに『接続先IPアドレス』と『ユーザー名』までセットされた状態での起動もできる。

```:ショートカットのリンク先
"C:\Program Files (x86)\teraterm\ttermpro.exe" 接続先IPアドレス /user=ユーザー名
```

 ↓ こんな状態で起動。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4d1693bb-10b1-f8e2-3d7e-69bd105a08d4.png)

```/passwd``` だけでなく ```/auth``` も外す必要があるので注意。
```/auth```を外さないと接続失敗でTeraTerm自体が起動しない。

# 参考サイトさん

http://www.oshiete-kun.net/archives/2014/11/teraterm.html

# バージョン

Windows 10 Pro 21H2 OSビルド 19045.2311
TeraTerm 4.106
マッピングデータフローで csv ファイルを Delta 形式に変換してみた

# はじめに
この記事は株式会社ナレッジコミュニケーションが運営する クラウドAI by ナレコム Advent Calendar 2022 の 13日目にあたる記事になります。
本記事では Azure Data Factory のマッピングデータフローを使用して、csv 形式のファイルを Delta 形式に変換します。


# マッピングデータフローとは
マッピングデータフローとは Azure Data Factory 上で使うことができるデータ変換機能です。
GUI ベースでデータ変換のフローを作成することができます。
作成したデータフローは Azure Data Factory のパイプライン内のアクティビティとして使用可能です。
# Delta とは
Delta は Data bricks 社が提供するオープンソースのフォーマットです。 Delta で構築されたテーブルは Delta テーブルと呼ばれ、以下のような優れた機能があります。
- ACID トランザクション
    - データの信頼が担保される
        - 操作が中断された場合でも一貫性が保たれるためデータ破損が防がれる
        - 複数の操作が同時実行されても互いに影響を与えることができない
- ストリーミングとバッチ処理の統合
    - ストリーミング処理とバッチ処理を同一環境上で行うことができる
- タイムトラベル機能
    - テーブルに対して何か変更があった際にバージョン管理を行うため、変更前の任意のタイミングに戻ることが可能
- スキーマ強制
    - テーブルスキーマに合致しないテーブルへの書き込みは拒否されるため、データの品質を維持できる
# 操作手順
では実際にマッピングデータフローを操作してみます。
今回使用するデータは以下のようなデータを持つ CSV ファイルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699921/0fab935c-bdec-0b97-e413-aa8bfcdd95bf.png)

まず Data Factoty で新規でパイプラインを作成し、データフローのオブジェクトを配置します。
配置したら、設定のところから[ 開く]を選択し、データフローを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699921/e4fd7331-b138-fc27-1683-de1f2fd6a026.png)

使用するソースの種類や参照先などを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699921/5ec8fa6c-936e-be29-59de-007b4f698760.png)
次に日付データを年、月、日に分けて、カラムとしてそれらを追加する処理を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699921/54d99f4f-cf03-edc0-f85f-b0072ba1e534.png)
式ビルダーを利用することで簡単に変換をすることが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699921/247591e7-cdac-5a96-719e-c3a77127c2b7.png)

最後に書き込み先の設定をします。今回は Delta 形式に変換するので[ インラインデータセットの種類 ]のところで Delta を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699921/23b5643e-20af-59ff-28c4-777cc4b15298.png)
パイプラインの画面に戻り、[ デバック ]を選択します。[ 出力 ]の[ 状態 ]の部分が成功となれば、正しく構築できています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699921/d7a7da3c-3a86-b45f-06b5-81039510a9af.png)
書き込み先を見てみると、たしかにログファイルと Parquet ファイルが出力されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699921/03073fc7-1e2a-5432-1f92-01da54202975.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699921/20375c70-d13d-46a6-4505-245980b9d818.png)

# おわりに
マッピングデータフローを使用してデータの変換を行うことができました。GUI ベースで行うことができるので、エンジニアではない方でもとっつきやすいツールかと思います。ぜひ取り入れてみてください。
# 参考資料
https://learn.microsoft.com/ja-jp/azure/data-factory/concepts-data-flow-overview

https://learn.microsoft.com/ja-jp/azure/databricks/delta/
Jest React TypeScript でボタン押下の挙動をテストする

# 概要
jest でボタンを押したときの動作をテストします。

# テストする対象
ボタンはクリックされると赤色から青色に変化します。
色の変化とボタン上の文字をテストします。
![chapter15product.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/967e3000-8fb9-4e6c-a778-4062db5c8195.gif)





# 開発環境
IDE:GitHub CodeSpaces
OS:windows10
言語：TypeScript

├── @testing-library/jest-dom@5.16.5
├── @testing-library/react@13.4.0
├── @testing-library/user-event@13.5.0
├── @types/jest@29.2.3
├── @types/node@16.18.4
├── @types/react-dom@18.0.9
├── @types/react@18.0.25
├── jest@29.3.1
├── react-dom@18.2.0
├── react-scripts@5.0.1
├── react@18.2.0
├── UNMET DEPENDENCY test@jest
├── ts-jest@29.0.3
├── typescript@4.9.3
└── web-vitals@2.1.4

# 実装

## プロダクトコード
``` App.tsx
import {useState} from 'react';
import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
	const [buttonColor, setButtonColor] = useState('red');
	const newButtonColor = buttonColor === 'red'? 'blue' : 'red';

  return (
    <div >
    <button 
		style={{backgroundColor: buttonColor}} 
		onClick={() => setButtonColor(newButtonColor)}>
		Change to {newButtonColor}
		</button>
	</div>
  );
}

export default App;


```

## テストコード



``` App.test.tsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import App from './App';


test('button has correct initial color', () => {
	render(<App />);
    // find an element with a role of button and text of 'Change to blue'
   const colorButton = screen.getByRole('button',{ name:'Change to blue' });

   //　ボタンの初期色が赤色であることを確認
    expect(colorButton).toHaveStyle({backgroundColor: 'red'})

	// ボタンを押す
	fireEvent.click(colorButton);

	// クリック後ボタンは青色になる
	expect(colorButton).toHaveStyle({ backgroundColor:'blue'});

	// クリック後ボタンのテキストは「Change to red」になる。
	expect(colorButton).toHaveTextContent('Change to red');
	
	// ボタンを押す
	fireEvent.click(colorButton);

	// クリック後ボタンは赤色になる
	expect(colorButton).toHaveStyle({ backgroundColor:'red'});

	// クリック後ボタンのテキストは「Change to blue」になる。
	expect(colorButton).toHaveTextContent('Change to blue');


});

test('button turns blue when clicked', () => {
	render(<App />);
	const colorButton = screen.getByRole('button',{ name:'Change to blue'});



});
```
## 実行時の様子
下のアニメはテストを実行時の様子です。
最初にAllGreenの場合を確認して　ボタンの初期色を青に変えてFailにしています。

![chapter15productTestPattern.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a4a9b0ca-7325-4eba-684f-a22aec0cbe13.gif)





# 感想
jest-domのドキュメントが良いです。
プロダクトコードとテストコードが載っており、使い方をイメージしやすいです。



# 参考
toHaveTextContent

https://github.com/testing-library/jest-dom#tohavetextcontent

udemy
section2 15 16

https://www.udemy.com/course/react-testing-library/learn/lecture/24450630#overview
WSL2でzshが遅い件を解決する

# 事象

WSL2でzshを使っていると、terminalで改行しまくるとカーソルが改行操作に追いつかないくらい激遅になっている。

# 原因

WSL2側でコマンドを叩くときに、毎回Windows側のパスも含めて調べ、激遅になっているらしい。

# 対策

`/etc/wsl.conf`を以下のように書き換える。

```/etc/wsl.conf
[interop]
appendWindowsPath = false
```

こうすることで、Windows側のパスをWSL2側では無視する。

ただ、これによって通常のWSL2側で実行できるはずのWindows側のアプリケーションが使用できなくなる。

対策として、`/etc/wsl.conf`を設定する前に(もしくは`appendWindowsPath = true`として設定した際に)、自分の使用したいアプリケーションのパスを調べておいて、ソフトリンクを作成したり、エイリアスを作成することができる。

- アプリケーションのパスを調べる

```
$ which explorer.exe                                                                                                                                                             [16:14:42]
/mnt/c/Windows/explorer.exe
/mnt/c/WINDOWS/explorer.exe
/mnt/c/WINDOWS/explorer.exe
```

```
$ which code                                                                                                                                                                     [16:14:50]
/mnt/c/Users/***/AppData/Local/Programs/Microsoft VS Code/bin/code
```

私の場合は、以下のAlias設定を`.zshrc`に書いておくことで実行できるようにしておく

```
alias code="/mnt/c/Users/***/AppData/Local/Programs/Microsoft\ VS\ Code/bin/code"
```
DockerでMySQL構築&ホストのLaravelから接続

## コマンドまとめ
```
// dockerコンテナのリスト
$ docker container ls

// dockerコンテナに接続
$ docker exec -it mysql-container bash
(mysql-containerはコンテナ名)

// dockerコンテナ内に接続
# mysql -u root -p

// TCP/IP接続でmysqlに接続
# mysql -u myusername -h 127.0.0.1 -p

// dockerネットワークの一覧
$ docker network ls
mysql_defaultがあるのを確認

// mysql_defaultのネットワーク・ブリッジを取得
$ docker network inspect mysql_default
```

## 環境
* Mac macOS Monterey

## 経緯
もともとHomebrewで昔にMySQLをインストールしていたけど、パスワード忘れたり、何入れてたか忘れた。

* MySQLに接続できない
* 再構築にもいろいろ手間取った
    * パスワードのポリシー変更
    * 構文エラー？（5系と8系の違いですかね？）

このあたりもじっくり調べたいところではありますが、やりたいことはそこではないので、、、

他にも学習用に簡単に作って壊してができるDockerが良いかと思い、調べました。

## 手順
以下のサイトを参考にしました。
下記手順でそのまま行けると思います。

- Docker Desktopのインストール
    - https://matsuand.github.io/docs.docker.jp.onthefly/desktop/mac/install/
- MySQLの構築
    - https://zenn.dev/ryo7/articles/create-mysql-on-docker
- DBeaverのダウンロード（クライアントツール）
    - https://dbeaver.io/download/
- ターミナルからDockerの中のMySQLに接続
    - https://hacknote.jp/archives/27791/

## 注意
**ターミナルからDockerの中のMySQLに接続**
ターミナルからは
```bash
// これはダメ
mysql -u root -p

// これはOK。
// TCP/IP接続するにはlocalhostではなく127.0.0.1とする必要あり。
mysql -h 127.0.0.1 -u root -p

// これでもOK
// localhostでも、--protocol=TCP オプションを使用してトランスポートプロトコルを明示的に指定することも可。
mysql -h localhost --protocol=TCP -u root -p
```

`-h`はホスト名を指定するオプション。リモートサーバに接続するときに使うやつ。
`127.0.0.1`はホストを指定。今回は自分自身。

参考
https://dev.mysql.com/doc/refman/8.0/ja/connecting.html

## Laravelから接続する
TCPの設定を書かないといけないのかなと思ったのですが、必要ありませんでした。


```:.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mydatabase
DB_USERNAME=myusername　// あらかじめmysqlに接続して作成しておく
DB_PASSWORD=mypassword　// あらかじめmysqlに接続して作成しておく
```

```bash:マイグレーションの実行
php artisan migrate

// 下記のようなエラーが出る。
SQLSTATE[HY000] [1045] Access denied for user 'myusername'@'172.18.0.1'
```

`127.0.0.1`じゃなく、`172.18.0.1`になっています。
どうやらLaravelからアクセスすると、ホストは172.18.0.1のようですので、あらためてmysqlで
'myusername'@'172.18.0.1'のユーザーを登録します。

**20221230追記(127.18.0.1の正体)**
参考:https://qiita.com/johejo/items/83cb83a885b8ac996ec9

ネットワークの知識が乏しく、ちゃんと理解してはいませんが、調べ方がわかりました。

ホスト側のターミナル上で、
```
$ docker network inspect mysql_default | grep -i gateway
```
を実行する以下のようにGatewayのIPアドレスが取得できます。
```
"Gateway": "172.18.0.1"
```
ホスト側のアプリからアクセスする場合、このIPアドレスがホストになるようです。

なので、
```
// ホストのIPアドレスを調べる
$ docker network inspec mysql_default | grep -i gateway

"Gateway": "172.18.0.1" // （例）

// コンテナ内のMySQLに接続し、"172.18.0.1"をホストとするユーザーを追加
$ docker exec -it mysql-container bash // コンテナに接続
# mysql -u root -p // MySQLに接続
mysql > CREATE USER 'myusername'@'172.18.0.1' IDENTIFIED BY 'secret'; // ユーザーを追加
```

これでホストのLaravelからDockerコンテナ内のMySQLに接続する設定ができる流れになります。

いまいち理解していないことは、
```
Laravelの.envの
DB_HOST=127.0.0.1
はそのままでいいの？？？
```
ってことです。

Dockerは同じマシンに入っているから127.0.0.1になるのはいいのかな？？

このあたりはネットワークの知識ですかね。ちょっと勉強しないとわからないです、現状。（わかる方教えてください！！）

また明確になり次第更新します。





そうするとマイグレーションが実行できるようになります。

ちなみに、

`DB_HOST=127.0.0.1` : うまくいく
`DB_HOST=localhost` : エラーが発生する

なんで？？

どうやら接続方法が違うということですかね。
ターミナルからmysqlに接続する際、127.0.0.1ならうまくいって、localhostならTCPの接続方法をオプションで指定する必要がありました。

なので、

127.0.0.1 -> TCP/IP
localhost -> ソケット

ということらしい。
一般的に、というか、mysqlの接続方法が、デフォルトではホストを指定しない場合、
- localhostをホスト名に使用
- ソケット通信

という使用のため、上記のような違いが出てくるようです。
【Laravel】ページングで検索結果が破棄される問題

# 初めに
条件検索した時にページングで次のページに行くと、

検索結果が破棄されていたエラーの解決方法です。


## 状況
ユーザーを一覧表示して名前や部署で検索する画面

```php:ページング実装部分のhtml
<div>
    {{$users->links()}}
</div>
```
検索した時のURL
`search?name=&department=2`
検索状態でページ遷移した時のURL
`search?page=2`
期待していたURL
`search?name=&department=2&page=2`

問題は<strong>`{{$users->links()}}`で自動的に作られたページネイションに、
`name`や`department`のパラメーターが含まれていないこと。</strong>

# 解決方法
```php:ページング実装部分のhtml
<div>
    {{$users->appends([
    'name' => $name,
    'department' => $department,
    ])->links()}}
</div>
```

HTMLでページリンクを自動生成しているところに、送りたいパラメーターを指定してあげることで

想定していた挙動になりました。
AWS勉強内容

# AWSの勉強内容と自分なりの解釈

# AWSとは
Amazonの提供するクラウドサービスのこと。
非常に多くのサービスが提供されているが、AWSの勉強を始めると登竜門(？)としてインフラ構築サービスをメインに扱うことになるため、本記事もこれを中心に扱う。

# ネットワーク関連

## リージョンについて
AWS初学において、おそらく最初の「？」ポイント。

### そもそもリージョンとは
AWSの各サービスが提供されているデータセンターの所在地の事。
例えば、日本国内には東京リージョン(アジアパシフィック (東京))と大阪リージョンがあり、東京リージョンの方がサービス数が多い。

### リージョンを選択する理由
リージョン＝データセンターの所在地であり、例えばWebサービスをAWSを使って提供する場合、利用場所(クライアント)に物理的に近いリージョンに接続し、この近いリージョンが混雑しているときは別のリージョンに接続するという運用ができる。
また、これを「**冗長化する**」などと表現する。
（ex.北の将軍は自分自身を冗長化している。）

### アベイラビリティゾーン
リージョンを更に細分化した概念。大学がリージョン、キャンパスがアベイラビリティゾーンというイメージ。
これもリージョンの冗長構成と同様に、アベイラビリティゾーンにも複数存在し、このおかげで自然災害などで1つのAZが停止しても別のゾーンが稼働している、という状況を作り出す事ができる。

ちなみに、リージョンやアベイラビリティゾーンをそれぞれ複数用意する事で「**可用性が高まる**」。
「**可用性**」とは「普通に使える状態を、どれだけ維持してるか」という意味の表現であり、ネットワーク関連の勉強をしているとよく出てくるので注意。
【React】useState, useEffectの無限ループエラー

# 無限ループになったコード例
useStateで定義した変数をuseEffectで監視する場合に起こった。
```React
import React, { useState, useEffect } from "react";

export const CountUpComponent = () => {
    const [count, setCount] = useState(0);
    useEffect(() => {
        setCount(Math.random());
    }, [count]);

    return <div>{count}</div>;
};

export default CountUpComponent;
```

# 解説

|現象  |countの具体例  |
|-----|-----------|
|最初のレンダーの際、countは初期値である 0 でレンダーされる。  |0  |
|その後、useEffectによりcountの値が変化する。  |5  |
|値が変化したので、コンポーネントの再レンダーが走る。  |5  |
|再レンダー後、再度useEffectが呼ばれてcountの値が変化する。 |2  |
|値が変化したので、コンポーネントの再レンダーが走る。  |2  |
|再レンダー後、再度useEffectが呼ばれてcountの値が変化する。  |9  |
・|・  |
・|・  |
・|・  |

というように、無限ループが発生してしまう。
<font color="Red">useStateは、**値が変われば再レンダー**</font>する特性があることをしっかり理解しておこう。

# 解決策
①監視を止める(空配列にする)
```React
import React, { useState, useEffect } from "react";

export const CountUpComponent = () => {
    const [count, setCount] = useState(0);
    useEffect(() => {
        setCount(Math.random());
    }, []); //←countを削除して空配列にする

    return <div>{count}</div>;
};

export default CountUpComponent;
```

②useStateを使わない
```React
import React, { useEffect } from "react";

export const CountUpComponent = () => {
    let count = 0;
    count = Math.random();

    return <div>{count}</div>;
};

export default CountUpComponent;

```
長い条件式に改行を入れるときの細かいTips

# 総論

論理演算子(`&&`とか`||`)で条件式をつなげる時、長くなって改行を入れることはあると思います。

そのときに、論理演算子を前につけるように書くと、条件の増減があったときに変更がその行だけで済むのでお勧めです。

# 例
```
  return hogehogeFoo == "foo" && hogehogeBar == "bar" && hogehogeBaz == "baz"
```

は横に長いので

```
  return hogehogeFoo == "foo"
    && hogehogeBar == "bar"
    && hogehogeBaz == "baz"
```
とします。条件が増減した場合、
```
  return hogehogeFoo == "foo"
    && hogehogeBar == "bar"
    && hogehogeBaz == "baz"
    && hogehoge == "hoge"   // この行だけ追加
```

```
  return hogehogeFoo == "foo"
    && hogehogeBar == "bar"
```
のように行の追加や削除だけで済むので、diffが見やすくなります。

後ろにつけるパターンだと、
```
  return hogehogeFoo == "foo" &&
    hogehogeBar == "bar" &&
    hogehogeBaz == "baz"
```
増減があったときに前の行も編集する必要が出てきてdiffが増えます
```
  return hogehogeFoo == "foo" &&
    hogehogeBar == "bar" &&
    hogehogeBaz == "baz" && // この行も編集
    hogehoge == "hoge"      // この行を追加
```

```
return hogehogeFoo == "foo" &&
    hogehogeBar == "bar"  // この行も編集
```

# 付随効果

読むときに「条件1、かつ条件2、かつ条件3」のように読んで「条件1かつ、条件2かつ、条件3」のようには読まないと思うので、前に論理演算子を置いたほうが自然に読めるのではないか、というのもお勧めする理由の一つです。