OmniAICreator/Qiita-1.07M huggingface dataset:
JUnit 単体テストの概要

# はじめに
業務で使用しているJUnitについて備忘録も兼ね、まとめていきたいと思います。
内容が多いため、何章かに分けてまとめていく予定です。
今回は、まずJUuitの内容に入る前に単体テストについてまとめていきたいと思います。

# JUnitシリーズ 項目表

| NO 　　　　| タイトル               |
| ---- | ------------------- |
| その1 | [JUnit 単体テストの概要](https://qiita.com/ryo0527/items/70550e0a556975a593f5)|
| その2 | [JUnit 環境の準備](https://qiita.com/ryo0527/items/135c2104a9af0eb795e9)|
| その3 | [JUnit テストの記述方法](https://qiita.com/ryo0527/items/7e85b3444fa9c975eecb)|

※ 新しい記事が作成できましたら、表は更新します。

# 単体テストとは
テストには、単体テストや結合テスト、総合テストなど様々なフェーズがあります。
各テストにおいて、目的や役割がそれぞれ定められています。
今回は、その中でも単体テストに焦点を当て、まとめていきたいと思います。

単体テストとは、モジュール(部品)単位でプログラムが正常に動作するかを検証するテストです。
テスト工程の中で、始めの方に実施されるテストのため、その後のテストの礎となる重要な役割を担っています。

# テストコードとは
テストコードとは、アプリの挙動を確認するためのコードのことです。
テストコードを記述することで、コマンド一つで実装した機能が想定通りに動作するかをチェックすることができます。
Javaでは、標準機能としてJUnit(テスティングフレームワーク)が用意されています。

### 例) テストコード
簡単なテストコードを紹介します。

#### テスト対象クラス
```java
public class HelloWorld {
  public static String join(String name) {
    return "Hello " + name;
  }
}
```
#### テストクラス
```java
@Test
public void testJoin() {
  String result = HelloWorld.join("Taro");
  assertEquals(result, "Hello Taro");
}
```
assertEqualsは、第一引数と第二引数が同一であればテスト成功とみなします。

# テストコードを書く意義
テストコードを書くことにより、機能のクオリティが担保できます。

### テストコードのメリット
テストコードのメリットについて3つ紹介します。

- 人為的なミスを防げる
実装した機能をブラウザなどで一つずつ確認する方法では、抜けが生じるリスクがある。
テストコードを書くことにより、このような問題を防止することができる。

- 機能追加などの際に、コマンド一つで確認できる
テストコードは、実装する手間こそありますが、一度実装したらコマンド一つで全てのテストが実行できる。
機能追加など仕様の変更があった際に、テスト工程の工数を削減できる。

- テストをおこなった記録が残る
テストをおこなった記録がコードとして残る。

# テストケースの作成
テストの手法として、「ブラックボックステスト」と「ホワイトボックステスト」があります。
それぞれの手法を組み合わせてテストケースを作成することが望ましいです。

テストケースを作成する際は、以下の内容をもとに考えていきます。

### 正常系と異常系 
テストコードでは、正常系と異常系をそれぞれテストする必要があります。

#### 正常系
正常系では、「開発者の意図する操作(入力値)などに対して、期待する結果を返すか」を確認します。

#### 異常系
異常系では、「開発者の意図しない操作(入力値)などに対して、エラーハンドリングが行われるか」を確認します。
例えば、必須項目を入力せずにフォームを送信した際は、「必須項目を入力してください」とアラートメッセージが表示されるかを確認するなどがあります。

### 同値分割と境界値分析
テストを作成する際に、考えられる入力を全て試そうと思うと莫大なテストパターンが必要になります。
無駄なテストケースの作成を防ぐために、「同値分割」と「境界値分析」という考え方があります。
具体的な説明に関しては、割愛させていただきます。
「同値分割」や「境界値分析」と検索すると、図を用いて説明されている記事が出てくると思います。

#### 同値分割
同値分割とは、仕様に応じて、各範囲から代表値をひとつ抽出し、テスト用の値とする手法です。

#### 境界値分析
プログラムを書く上で、最もバグが発生しやすい値が境界値です。
境界値分析とは、同値クラス間の境界の値をテスト用の値とする手法です。
　
# JUnitとは
JUnitとは、Javaで開発されたテスティングフレームワークです。
JUnitを使用することにより、誰が書いても同じようなテストコードとなり、他の人からでもテスト結果がすぐ理解できるなどのメリットがあります。

# おわりに
単体テストの概要は以上となります。
文章ベースでの説明となり、イメージできない箇所もあると思いますが、記事内にあるキーワードで検索すると、図を用いて説明されている記事も出てくると思います。

次はJUnitでのテストを実施するための環境を準備していきます。
[その2 JUnit 環境の準備](https://qiita.com/ryo0527/items/135c2104a9af0eb795e9)
【rails】遷移元のページの種類によって処理を変える

遷移元ページが違うなら処理を変えたい。そんな時に利用するメソッドを紹介。
```ruby
request.referer
#中身
"http://localhost:3000/〜（略）"
```
これで遷移元のリクエストパラメーターを取得できます。中身はurlとなっています。個人的なおすすめは正規表現で利用するmatchを使い、条件分岐させることです。
```ruby
if request.referer.match(/issue/)
  処理①
else
  処理②
end
```
上記の場合だと、urlに”issue”が含まれている場合は処理①を実行し、それ以外は処理②を実行します。これで、ある特定のページから来た場合には、他のページと違った処理をすることができます。
### 参考サイト
https://railsdoc.com/page/request

https://docs.ruby-lang.org/ja/latest/doc/spec=2fregexp.html
commit時にESlintとPrettierを実行する【Lefthook】

## パッケージのインストール
以下のコマンドを実行して`Lefthook`をインストールします。
```:ターミナル
$ yarn add -D lefthook
```

## Lefthookの設定
Lefthookの設定をします。
`lefthook.yml`を作成し、以下のように記述します。
```lefthook.yml
pre-commit:
  parallel: true
  commands:
    linter:
      files: git diff --name-only @{push}
      glob: "*.{js,ts,jsx,tsx}"
      run: npx eslint {files}
    formatter:
      files: git diff --name-only @{push}
      glob: "**/*"
      run: npx prettier --write --ignore-unknown {files}
```

## 動作確認
以下のコマンドを実行し、正常に動作するか確認します。
```:ターミナル
＄ npx lefthook install && npx lefthook run pre-commit
```
nvim-cmpで、タブ補完が必要ない時にEnterを押したらそのまま改行するようにしたい

タイトルの通り。最近エディタをnvimに移行して、色々設定をしていたが、補完が必要なくて改行したいのに、Enterを押すと第一候補の補完が効いてしまうから、それを避けたかった。

nvim-cmp-config.luaの中身に次のものを追加すれば良い。
```
cmp.setup({
    mapping = cmp.mapping.preset.insert({
                  ['<CR>'] = cmp.mapping.confirm({ select = false }),
              }),
})
```
【unity】canvasがアホみたいにくそデカい件について

# はじめに
ゲーム中、画面の左上に常にHPを表示させようとcanvasを作成したところ、タイトルの通りくそデカcanvasになってしまった。
このcanvasをどうにかしたため、メモ。

# 内容
canvasのレンダーモードを変更するだけ。

# 詳細
canvasにはレンダーモードというプロパティがある。これはつまりcanvasをどのように描画するかを表している。

- スクリーンスペース - オーバーレイ
  - canvasを画面に直接描画する。カメラにぴったり張り付いているイメージ。なので、どのオブジェクトよりも前面に表示される。

- スクリーンスペース - カメラ
  - canvasが、カメラに対して垂直になるように描画する。distanceを設定し、カメラとの距離を設定することができる。
  - この場合、位置次第でcanvasよりも前面にオブジェクトが来てしまうことがあるので、注意。

- ワールド空間
  - canvasをオブジェクトとして描画する。空間に透明な平面（向きは自由）があり、そこに描画されているイメージ。

# まとめ
初期は「スクリーンスペース - オーバーレイ」に設定されているが、「スクリーンスペース - カメラ」に設定すると、注意は必要だが大きさがちょうどよくなる。

本当に、ちょうどよくなる。

# 参考文献
- [【Unity】Canvasについて理解してみよう](https://qiita.com/4_mio_11/items/a65e929ae64a018a24b0)
Mybatisの特徴を短く

### Mybatisは

1. SQL Mapping Frameworkである：JavaコードとSQL（Standard Query Language）をマッピングする
2. JavaコードからSQL文をXMLファイルに分離して管理
3. Parameter設定とQuery結果を読み込むコードを削除する
こうすることによって作成するコードが減り、効率性向上、メンテナンスが容易になる
4. XML内の特殊文字（≺、≻、＆....）は＆lt; ＆gr;に変換して使用するか、特殊文字を含むQueryを
```
<![CDATA[ 特殊文字 [[>
```
することで表示される
Ansible で ターゲットノードにおける python の locale としてutf-8を指定する(2025/03更新)

レアケースとおもえるが必要になったので備忘

# 2025/03追記: 

ansible-core 2.18.3環境においても、playbookにおいて以下の様にenvironmentを設定することで、接続先のロケールを上書きして接続できることが確認できました。

```yaml
- hosts: all
  environment:
    LANG: JA_JP.UTF-8
    LC_ALL: JA_JP.UTF-8
  tasks:
...
```




# 2024/11追記: Ansible 2.17.1以降ではこの対応方法が使えない可能性
以下の修正の影響
https://github.com/ansible/ansible/issues/83476
GitHubGitHub
ansible_python_interpreter="/usr/bin/env python3" doesn't work anymore · Issue #83476 · ansible/ansible

playbook側で、play や task に environment: { LANG: C } などを付けて、環境変数 LANG や LC_ALL などを設定することで対応できる可能性がある。




# Ansible で ターゲットノードにおける python の locale を指定する

ターゲットノードにおける python のロケールは、接続に使用するユーザーのロケールが通常は使用されることになるが、それとは異なったロケールを使用したい場合の指定方法。

ターゲットノードにおける python は、変数では ansible_python_interpreter、ansible.cfg では interpreter_python によって指定する。

つまりこれらで ロケール を設定しつつ pythonを実行できればよい。


## Cロケールでpython3を利用する例

### ansible-playbookコマンドへの引数による指定例

```
$ ansible-playbook ...  -e 'ansible_python_interpreter="/usr/bin/env LANG=Ja_JP.UTF-8 LC_ALL=Ja_JP.UTF-8 /usr/bin/python3"' ...
```

### play varsにおける指定例

```yaml
− hosts: all
  vars:
    ansible_python_interpreter: "/usr/bin/env LANG=Ja_JP.UTF-8 LC_ALL=Ja_JP.UTF-8 /usr/bin/python3"
  tasks:
  ...
```


### inventory varsにおける指定例
inventory.yml
```:yaml
all:
  vars:
    ansible_python_interpreter: "/usr/bin/env LANG=Ja_JP.UTF-8 LC_ALL=Ja_JP.UTF-8 /usr/bin/python3"
  children:
    ungrouped:
      hosts:
        node1:
```


### ansible.cfgによる指定例 (Ansible 2.17.1以降では使えない可能性)

```ini:ansible.cfg
[defaults]
interpreter_python="/usr/bin/env LANG=Ja_JP.UTF-8 LC_ALL=Ja_JP.UTF-8 /usr/bin/python3"
```
CodeMirror 6のExtensionの分類まとめ

CodeMirrorについては先日、こちらの記事を投稿しました。

https://qiita.com/kyntk/items/348ea3d07b4ac3a2eccc

CodeMirrorでは、自分の好きなようにエディタを拡張することができ、独自の機能も追加することが可能です。
この役割を担っているのが、Extensionです。

CodeMirrorにおいて重要なExtensionですが、色々な種類のExtensionがあるので、調べてまとめてみました。

:::note warn
この記事は[System Guide](https://codemirror.net/docs/guide/)や[Reference Manual](https://codemirror.net/docs/ref/)を元にまとめたものになります。
正しい情報はドキュメントをご確認ください。
:::

## Extensionとは

https://codemirror.net/docs/guide/#extension

Extensionとはエディタを拡張するもので、イメージしやすいのは、何らかのDOMイベントをフックに、エディタのstateを変化させるものです。

[System Guide](https://codemirror.net/docs/guide/)に載っている図を用いると、DOM eventからtransactionを作成、dispatchしてstateを更新する機能です。
それ以外に、タブサイズなどの設定値を保持したり、keymapや、エディタのテーマを設定したりできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/3d5b4773-8358-31ba-408e-8191e5409189.png)

いくつか説明していきます。

### [domEventHandlers](https://codemirror.net/docs/ref/#view.EditorView^domEventHandlers)

domEventHandlersはドラッグイベントなどのDOMのイベントにハンドラを設定することができます。

#### [Command](https://codemirror.net/docs/guide/#commands)について

domEventHandlersではCommandを使います。keymapなどでも使うのですが、副作用を発生させる処理です。
イベントやキー入力をフックに、実行するかを判断し、transactionをdispatchします。

[@codemirror/commands](https://codemirror.net/docs/ref/#commands)に様々なコマンドが存在しています。例えばカーソルを操作したり、選択範囲を操作したり、文字を挿入、削除したりと、これを見ればどんなことができるのかイメージがつかみやすいと思います。

### [keymap](https://codemirror.net/docs/ref/#view.keymap)

任意のキーマップのハンドラーを設定できます。これを使って、特定のcommandを実行することができます。

もともと用意されているものとして[emacsStyleKeymap](https://codemirror.net/docs/ref/#commands.emacsStyleKeymap)などがあり、簡単に拡張することができます。


### [Facet](https://codemirror.net/docs/guide/#facets)

Facetは設定の値などを保存するために使います。静的な値や、関数などを保持することが多いようで、他のExtensionなどから呼び出して使用することができます。

使用例として挙げられているのは、タブサイズ、エディター属性、アップデートリスナーです。

### その他

その他にも、[theme](https://codemirror.net/docs/ref/#view.EditorView^theme)でエディタのスタイルやテーマを管理したり、historyなどでstateの追加情報を管理する[StateField](https://codemirror.net/docs/guide/#state-fields)や、エディタのサイズなどといったその場のviewportに依存する状態を管理する[View Plugin](https://codemirror.net/docs/ref/#view.ViewPlugin)などがあります。
言語ごとにシンタックスハイライトなども用意されているものもあります。

もっと詳しく知りたい方は、Examplesを見ると色々な拡張が用意されているのでご覧ください！

https://codemirror.net/examples/

自分でExtensionを実装するときにこれらを参考にできそうです。

## 参考

- [CodeMirror Reference Manual](https://codemirror.net/docs/ref/)
- [CodeMirror System Guide](https://codemirror.net/docs/guide/)
- [Facets as Composable Extension Points](https://marijnhaverbeke.nl/blog/facets.html)
- [Extensible Extension Mechanisms](https://marijnhaverbeke.nl/blog/extensibility.html)
Service layerの分離（ビジネスロジックの分離）ー＠Service、@Transactional

＠Serviceと@Transactionalについて勉強しましたので書きます。

---

### ＠Service
Service layerで使用されるAnnotationで、これを使用することで、該当のクラスがService layerクラスであることを明確にする

---

### @Transaction
クラスやメソッドに貼り付け、該当範囲内のメソッドがTxになることを意味する
<br>
属性
1. propagation：Txの境界（Boundary）を設定する方法を指定
① REQUIRED - Txが実行中であれば参加、実行中でなければ「新しいTx」を開始
② REQUIRES_NEW - Txが実行しているかどうかにかかわらず「新しいTx」を開始
③ NESTED - Txが実行中であればそのTxの内部に「subTx」を開始  
　　　　　　新しいTxの開始ではないことが① 、②との違い
④ MANDATORY - 必ず実行中のTx内でのみ実行可能で、そうでなければ例外発生
⑤ SUPPORTS - Txが実行中であるかどうかにかかわらず実行
⑥ NOT_SUPPORTED - Txなしで処理。Txが実行中の場合、しばらく中断（suspend）
⑦ NEVER - Txなしの処理。Txが実行中の場合、例外発生

2. isolation：Txのisolation levelを指定
3. readOnly：Txがデータを読み取るのみの場合、trueに指定するとパフォーマンスが向上
4. rollbackFor：指定された例外が発生したときにTxをrollback。
　　　　　例外的に、RuntimeExceptionとErrorは自動ロールバック
5. norollbackFor：指定された例外が発生してもTxをrollbackしない
6. timeout：指定された時間(秒)以内にTxが終了しない場合、Txを強制終了させる
Arudino MIDIライブラリ Control-Surfaceの使い方メモ

## はじめに
ArduinoのMIDIライブラリ自体は結構色々あるのですが、色々使ってみてControl-Surfaceというライブラリが使いやすく機能も豊富だったので、自分が使える範囲でメモ書き程度に使い方を書いていこうと思います。あまり理解できてない部分も多いのでちゃんとした解説にはならなそうですが、、、

## 簡易的な説明
とりあえず特徴的なことを挙げると、他のライブラリだとsetup()やloop()などの中には色々処理を書く必要のあったのですが、Control-Surfaceはそれぞれの中には下記のものを書くだけでセットアップが完了になるところです。

```c++
void setup() { Control_Surface.begin(); }
void loop() { Control_Surface.loop(); }
```

そして機能を追加するのには、その機能をインスタンスを生成してあげるだけで良さそうです。（ここの表現が正しいのかは謎）
例えばノート信号(60, C4)を送る機能を追加する場合の全体的なコードは以下のようになります。

```例.ino
#include <Control_Surface.h>

USBMIDI_Interface midi;

NoteButton button { 
   4,              // pin番号
   {60, CHANNEL_1} // ノート番号、チャンネル
};

void setup() { Control_Surface.begin(); }
void loop() { Control_Surface.loop(); }
```

というような感じで記述すれば、４番のpinに入力があった場合にCh1,60番のMIDI情報を送信することができる感じになっています。
このようにシンプルな機能を作るのにも役立ち、あとは同様にCCButonやCCPotentiometer(コントロールチェンジメッセージを送る機能)、Bank(Chや送信番号の切り替え)などを組み合わせることで多彩な機能を持つMIDIコントローラーをクリーンなコードで製作することができるようになっています。


## 各機能の説明
とりあえずここでは自分が使ってみたことがある機能を軽く解説してみようと思います。
まぁ説明自体はドキュメントからのコピペですが。

**NoteButton**
瞬間的なプッシュボタンまたはスイッチの入力を読み取り、 MIDIノートイベントを送信するクラス
書き方は上述の通り

**CCButton**
瞬間的なプッシュボタンまたはスイッチの入力を読み取り、 MIDIコントロールチェンジイベントを送信するクラス
```CCButton.ino
CCButton ccButton { 
   5,              // pin番号
   {74, CHANNEL_1} // アドレス番号、チャンネル
};
```

**CCPotentiometer**
ポテンショメータまたはフェーダーからアナログ入力を読み取り、 7ビットのMIDIコントロールチェンジイベントを送信するクラス
```CCPotentiometer.ino
CCPotentiometer potentiometers { 
    0,              // アナログpin番号
    {71, CHANNEL_1}　// 　アドレス番号、チャンネル
};
```

**SwitchSelector**
トグルまたはモーメンタリスイッチの状態に基づいて、2つの設定のいずれかを選択するセレクタ。
ちょっとここら辺から説明に自身がないですが、自分の現時点での解釈で言うと後述で説明するBank(chやアドレス番号の切り替え)機能を使用する場合などにこれを使うことで、実現できるものと解釈しています。Bankのところと一緒に書ければと思います。
```SwitchSelector.ino
SwitchSelector switchSelector = {
      bank,      //　　バンク名
      8          // pin番号
};
```

**Bank**
上述などで設定した機能をグループ化し、これらの要素のアドレスを変更できるクラス
とりあえず書き方的には以下の感じになります。
```Bank.ino
Bank<2> bank(1);
//Bank<2> → <>の中に入れる数値があまり理解できていない、
//bank(1)　　→ chやアドレス番号を（）内の数値分切り替える
```

使い方は適当な機能にBankable::というものを記述し、先ほど説明したSwitchSelectorとBankType(何を切り替えるか)を定義します。
書き方の例は以下になります。
```Bankable例.ino
Bank<2> bank(1);
SwitchSelector selector = {bank, 8};

Bankable::CCButton bankButton {
   {bank, BankType::CHANGE_CHANNEL}, //バンク名、　切り替えるタイプ(この場合チャンネル)
　　　　　　　１,                               // pin番号
　　　　　　　{71, CHANNEL_1}                  // アドレス番号, チャンネル
};
```
これで8pinに接続したトグルスイッチなどを使い、ONになればch設定が２chになり、オフにすることで1chに切り替わるような動きを作れます。
もしBankTypeをCHANGE_ADDRESSにすると、ONで72、OFFで７１になるといった感じです。
うまく説明できてるかわかりませんが、こんな解釈です。


## 終わりに
一応これらを使えばある程度の機能を持ったMIDIコントローラーを自作できると思います。
機能自体はまだまだ豊富にあるのですが、如何せん電子工作や言語になれていないのとあまり記事もなさそうなので駆使するのは難しそうです。。。
が、もしお役に立てれば幸いです。

自分が自作したやつの解説もNoteに書いてみてたりするのでもしよかったらこちらもどうぞ。
https://note.com/paraixo/n/n0edbc0eaf45f
[three.js]Webフォントを表示したい

three.js で3dなアニメーション作りたいですよね〜
「geometoryを表示」に関しては情報が多いですが、文字の表示[特にwebfont]がよくわからなかったのでまとめます。

# STEP1
フォントを表示するためにTextGeometoryとFontLoaderのモジュールをthree.jsと別で読み込む必要があります。
それぞれ公式のgitにあがっているのでダウンロードして適当なディレクトリに配置してください。
[TextGeometory](https://github.com/mrdoob/three.js/blob/dev/examples/jsm/geometries/TextGeometry.js)
[FontLoader](https://github.com/mrdoob/three.js/blob/dev/examples/jsm/loaders/FontLoader.js)

# STEP2
①フォントをダウンロード。
特になんでもよければ[公式](https://github.com/mrdoob/three.js/tree/dev/examples/fonts)のjsonファイルをダウンロードで問題ないです。その場合はSTEP3へ

今回はWebフォントを表示したいので、、
安定のNotoSansJpをダウンロード
https://fonts.google.com/noto/specimen/Noto+Sans+JP
![notosansjp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787586/5b11978f-275a-be32-e272-af94bb672579.png)

②jsonに変換
フォントデータは`.ttf`の形式になっていることが多いですが、FontLoaderがjson形式のデータしか受け付けてくれないので変換する必要があります。

[Facetype.js](http://gero3.github.io/facetype.js/)
こちらでjsonを選択して変換！

# STEP3
あとはcoding

```js
import { TextGeometry } from "<任意のpath>/TextGeometry";
import { FontLoader } from "<任意のpath>/FontLoader";

// ...

fontLoader.load("[任意のファイル].json", (font: object) => {
  const geometry: TextGeometry = new TextGeometry("表示したい文字", {
    font: font,
    size: 4,
    height: 0.1,
    curveSegments: 12,
    bevelEnabled: true,
    bevelThickness: 0.4,
    bevelSize: 0.02,
    bevelOffset: 0,
    bevelSegments: 10,
  });

  geometry.center(); // 中央寄せ
  const material = new THREE.MeshLambertMaterial({
    color: 0xffffff,
  });
  const mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);
```

表示されない場合はparamaterとかpositionいじってみれば良さそう！
Transactionとは

## Transaction（Tx）

1. データベースのロジック単位で、それ以上分離できない作業の最小単位

2. insert、update、selectコマンドなどがTx

3. 主要特徴（ACID）
(1) 原子性（Atomicity）：複数の作業を1つの作業のように動作させる必要がある。
　　　　　　　　　　　 Txに関連することは、すべて実行されるか、すべて実行されないかの
　　　　　　　　　　　 １つ。All or nothingという。
(2) 一貫性（Consistency）：Txは実行の前後に一貫した状態を維持する。
(3) 孤立性（Isolation）：各Txは独立的に実行する。記事の最後にIsolation levelについて記述。
(4) 永続性（Durability）：成功したTxの結果は維持されなければならない。

<br><br>
- Isolation level (各Txを分離させる程度)
(1) Read uncommited：Commitされていないデータも読み取り可能。
　　　　　　　　　　 ①最初の作業、Tx1完了後Commit
　　　　　　　　　　 ②2番目の作業、Tx2完了後はUncommit
　　　　　　　　　　 ③この状態でTx1からデータを読み込むと、Tx2作業のデータも表示される
(2) Read commited：Commitされたデータのみ読み取り可能。
(3) Repeatable read：Txが開始されてからの変更は無視される。
　　　　　　　　　 CommitされたTx1以降CommitされたTx2はTx1に影響を与えられない。
　　　　　　　　　 孤立性の定義と一致するので、Repeatable readがDefault。
(4) Serializable：1度に1つのTxのみ独立して実行することで、孤立性が最も高い。
AWS Lambdaの用語要点まとめ（自分用メモ

・AWS Lambda
サーバーレスでプログラムのコードを実行できるサービス。
サーバーレスとはAmazon EC2などのサーバーを必要とせず、リクエスト発生時にだけプログラムが実行されるアーキテクチャのこと。
Lambdaを利用すると次のようなメリットがあります。
・プログラム実行環境の構築や運用が必要なくなる
・プログラムはリージョン内の複数のAZに分散して配置される（耐障害性・可用性の向上）
・プログラムへのリクエスト数に応じたスケーリングが自動的に行われる（拡張性の向上）
以上のメリットから、開発者はプログラムの開発に集中できるようになります。

Lambdaで実行されるコードを「Lambda関数」といいます。Lambda関数はJava、Node.js 、Pythonなど様々な開発言語に対応しています。
Lambda関数の実行時間は1回につき最長15分で、実行時間と選択したメモリの容量に対して課金されます。そのため実行時間が15分以上になる処理や、常時稼働が必要なアプリケーションには向いていません。

【Lambda関数のトリガー】
Lambda関数実行の起点となるイベントを「トリガー」といいます。以下はトリガーとして設定できるイベントの一例。
・Amazon S3バケットにオブジェクトが作成された時
・Amazon DynamoDBのテーブルに変更があった時
・Amazon SQSのキューにメッセージが追加された時

例えば、クライアントからS3バケットに画像ファイルがアップロードされた時、画像ファイルの情報をDynamoDBに書き込むという利用方法があります。クライアントからS3に画像をアップロードするだけで、DynamoDBを参照するWebアプリケーションがすぐに画像を利用できるようになります。

・Lambda関数のアクセス権限
Lambda関数には実行ログを出力するために、CloudWatch Logsへのアクセス権限が割り当てられています。デフォルトではCloudWatch Logs以外へのアクセス権限はないので、Lambda関数から他のAWSサービスへアクセスさせたい場合はアクセス権限の設定が必要です。Lambda関数のアクセス権限は、他のAWSサービスへのアクセス権限を持つIAMロールによって付与します。その際、Well-Architected Frameworkの「最小権限の原則」に基づき、コード実行に必要な最低限の権限のみ割り当てることが推奨されています。



・Lambda関数のVPCアクセス
作成したLambda関数はLambda専用のセキュアなVPCに配置されます。このLambda専用のVPCからは、インターネットや、インターネットを経由してパブリックサブネット内のAWSリソースにはアクセスできますが、プライベートサブネット内のAWSリソースへはアクセスできません。
Lambda関数からプライベートサブネット内のAWSリソースへアクセスさせたい場合は「VPCアクセス」の設定をします。VPCアクセスではアクセスしたいAWSリソースのあるVPCやサブネットの選択と、Lambda関数のセキュリティグループを設定します。VPCアクセスを設定するとLambda関数がサブネット毎に接続用のENI（Elastic Network Interface）を作成して、プライベートサブネット内のAWSリソースへアクセスします。
VPCアクセスを設定したLambda関数は、ENIを作成したサブネットへアクセスできるようになる代わりに、インターネットへアクセスできなくなります。

VPCアクセスを設定したLambda関数からインターネットへアクセスしたい場合は、プライベートサブネットからインターネットへアクセスする方法と同様に、NATゲートウェイまたはNATインスタンスを経由します。また、インターネットを経由せずにパブリックなAWSリソースへアクセスしたい場合は、VPCエンドポイントを経由します。

・Amazon API Gateway
Amazon API GatewayはAWSサービスと連携するAPIの作成や管理ができる機能です。API（Application Programming Interface）とは、クライアントからのリクエストをアプリケーションサーバーに送り、アプリケーションサーバーからのレスポンスをクライアントへ返す接続口（インターフェイス）のことです。
下記はAPI Gatewayで作成したHTTP APIの実行例です。クライアントからHTTP(HTTPS)などでAPIを呼び出して、テキストやJSONなどの形式で得たい情報を取得します。

API Gatewayはマネージドサービスなので、Lambdaと組み合わせることで完全にサーバーレスでWebアプリケーションを実行できます。
例えばクライアントからのHTTPリクエストをAPI Gatewayで受信し、それをトリガーとしてLambda関数を実行させ、レスポンスをAPI Gateway経由で返すことができます。

API Gatewayで作成できるAPIは、クライアントとサーバー間の接続方法や機能によって以下の3種類があります。

■REST API（RESTful API）
クライアントからのリクエストに対してレスポンスを返す形式のAPIです。サーバーが扱う情報はURI(URL)で定義されており、クライアントはHTTP（HTTPS）でリクエストを送信することでレスポンスを得ます。
データベースの検索など、クライアントからのリクエストに応答するアプリケーションで使われます。
なお、REST API（RESTful API）とはREST（REpresentational State Transfer）という原則にのっとったAPIのことです。通信の状態が管理されない「ステートレス」な接続方式です。


■HTTP API
REST APIよりも低遅延かつコスト効率を高くする目的で設計されたAPIです。REST APIと同じ形式のAPIですが、APIキャッシュ（後述）を利用できないなど細かな差異があります。

■WebSocket API
クライアントとサーバー間でリアルタイムな情報のやり取りを目的とするAPIです。REST APIとは違い、継続的なデータの送受信を行えます。
チャットや株価情報のような常に情報をモニタリングするようなアプリケーションで使われます。
なお、WebSocket APIとはサーバー・クライアント間で双方向のセッションを確立できる技術を利用したAPIのことです。通信の状態を管理される「ステートフル」な接続方式です。


・API キャッシュ
Amazon API Gatewayにはクライアントへ送信したデータを保存する「API キャッシュ」機能があります。REST APIではどのクライアントからでも同一のリクエストであれば同一のレスポンスになります。API キャッシュではクライアントに送ったレスポンスをAPI Gatewayでキャッシュし、再度同一のリクエストを受け取るとキャッシュからデータを返します。API キャッシュから応答を返すことにより、Lambda関数の実行を省略できるのでレスポンス速度が向上します。
FirestoreのTimestamp型をStartAfterするときの注意点

# FirestoreのTimestamp型について
## 記事の内容
今回は業務中に詰まったFirestoreのtimestamp型の取得について書いていきます。
結論を言っておくと、取得の際はnanoSecondまで意識したほうがいいです。
※Firestoreに直接データを追加したからかもしれません、原因検証は不十分です。

## 環境
| Laravel 9 | Mysql 8 | Ubuntu |
|-----|----|-----|

## Timestamp型の中身
FirestoreのdocumentからTimestamp型の中身を取り出すと以下のような形になっています。
```
Google\Cloud\Core\Timestamp ^{
-value: DateTimeImmutable @1657260000 {
  date: 2022-07-08 06:00:00.651 +00:00
}
-nanoSeconds: 651000000
```
上記のデータは日本時間の「2022年7月8日 14:00:00」です。
取得の際は日本時間でひっかけて取得できますが、手元に来るときにUTCに変換されます。(設定でどうにかなるんですかね?)

ここでの注目ポイントはdateが「Y-m-d H : i : s .u」とFirestoreで設定していないnanoSecondが付いていることです。
Firestoreに直接テストデータを作成したからかは不明ですが、「2022-07-08 14:00:00」と設定したにも関わらず、nanoSecondが付いていました。

## nanoSecondがあると何がまずいのか
これがあるとstartAfterではじくことができない場合があります。
MySqlを使用してditetimeに「Y-m-d H:i:s」形式で時間を保存していました。
ここでDB内の最新データ以降のものをFirestoreから取得しようとすると重複が発生する可能性があります。

とりあえずFirestore上にtimestamp型のcreated_atが保存されているとします。
DB内の最新データを$latest = 2022-07-08 14:00:00;とした場合、以下のような感じで取得すると思います。

```
$docRef = $this->firestore->database()->collection('test');
$datetime = new Datetime($latest , new DateTimeZone('Asia/Tokyo'));
$query = $docRef->orderBy('created_at')->startAfter([$latest])
$documents = $query->get()
```
この時、Firestoreに保存されている「2022年7月8日 14:00:00」のデータは取得したくないですが、謎のnanoSecondによって「$latest <= Firestore上のデータ」になるので取得できてしまいます。

## 解決策
1. DiteTime型のカラムにnanoSecondを3桁分格納できるように変更。
2. Firestoreのtimestamp型には__toString()という関数が使用できるので、Carbon::create($firestore_time->__toString())としてそのままDBに保存する
※__toString()はnanoSecondも含めて時間を返してくれます。
## まとめ
Firestoreのtimestamp型はnanoSecondがあるので注意しましょう。
もしかしたらLaravelやアプリ側から登録する際はnanoSecondがないのかもしれませんが、詳しくはまだ未検証です。
documentSnapshotのcreateTime()やupdateTime()はnanosecond持ちですがwhereなどはかけられないので、fieldの値には警戒しておいたほうがいいと思います。
Singularityを使ってみた

# 1. Singularity？
コンテナ技術の一種だそうで、Dockerと比較してroot権限が不要な点に特徴があるようです。
とりあえず使ってみた点を雑にメモしておきます。(個人用です)

* 参考
    * https://docs.sylabs.io/guides/3.10/user-guide/
    * https://github.com/sylabs/singularity/blob/release-3.10/INSTALL.md
    * https://qiita.com/mkt3/items/b9f86f5ddf9eb0f43608
    * http://www.hpc.cmc.osaka-u.ac.jp/wp-content/uploads/2021/09/20211021.pdf
    * https://abci.ai/ja/how_to_use/data/ABCI-MiniCamp_Singularity_202105.pdf

# 2. インストール
環境は下記。
```
$ cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)
```
パッケージ類をインストール。
```
$ sudo yum groupinstall -y 'Development Tools'
$ sudo yum install -y \
    libseccomp-devel \
    glib2-devel \
    squashfs-tools \
    cryptsetup \
    runc
```
Goをインストール。
```
$ export VERSION=1.18.2 OS=linux ARCH=amd64
# /tmpにダウンロード
$ wget -O /tmp/go${VERSION}.${OS}-${ARCH}.tar.gz https://dl.google.com/go/go${VERSION}.${OS}-${ARCH}.tar.gz
# /usr/localに解凍
$ sudo tar -C /usr/local -xzf /tmp/go${VERSION}.${OS}-${ARCH}.tar.gz
# 環境変数に追加
$ echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
$ source ~/.bashrc
```
Singularityのインストール。
```
# リポジトリをclone
$ git clone --recurse-submodules https://github.com/sylabs/singularity.git
$ cd singularity
# コンパイル
$ ./mconfig
$ make -C builddir
$ sudo make -C builddir install
# バージョン確認
$ singularity --version
WARN[0000] Failed to decode the keys ["storage.options.override_kernel_check"] from "/etc/containers/storage.conf". 
singularity-ce version 3.10.0+65-gbf1afa7
```
WARNINGは不明だがインストールはされている模様。

# 3. コンテナのビルド
Singularity Hub/Docker Hubからコンテナを指定してビルドすることもできるそうだが、カスタマイズしやすそうなSingularity定義ファイルからのビルドを試してみる。Singularity定義ファイル(*.def)はDockerでいうDockerfileのようなものらしい。Bootstrapにdockerと指定するとdockerイメージを使用できるとのこと。

```singularity_centos7.def
Bootstrap: docker
From:centos:centos7

%post
    yum update -y
```
以下のようにビルド。(ビルド時にはroot権限が必要なようだがfakerootというオプションもあるようだ)
```
$ sudo -s
# singularity build singularity_centos7.sif singularity_centos7.def
```

# 4. コンテナに入ってみる

```
$ singularity shell singularity_centos7.sif
```
ホームディレクトリがマウントされるのか...

dockerとの違いは以下も参考になりそう。
https://tmyoda.hatenablog.com/entry/20200817/1597663325
【Salesforce】【VSCode】Debug Testが表示されなくなったときの最短解決法

Salesforce開発にかかせないVSCodeのDebug Test機能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/069d6f70-cf1c-0c4a-eede-cbc0d35dbede.png)
`@isTest`アノテーションの下に出てくるぽちっとしたらデバッグできるやつです。

こいつが出なくなっちゃった！ときの最短解決法まとめました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/7798b691-9a44-fba0-d46c-2e32134df30e.png)

VSCode環境構築の手順は以下の記事をご参考ください☆

https://qiita.com/piepie1231/items/def2e6b0f8e5d16f63f7

# Java11のインストール

以下のページで 「Java 11 (LTS)」をダウンロードします。

https://www.azul.com/downloads/?package=jdk#download-openjdk

下の方にスクロールするとあります。
ご使用のOSに合わせてzipファイルを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/2dc837ad-0a7b-0f77-7a7a-98d14cbf8448.png)

zipファイルを展開します。
Windowsなら無難に`C:\Program Files`下でいいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/b32cd26a-5751-6116-9208-21bfa50047f8.png)

展開したファルダのパスをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/865232b7-1197-0bb9-f2fd-46a9aae5c1e9.png)

# Java Home を設定する

VSCodeを開き、左下の歯車マーク→設定をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/e7451d21-606f-defc-bf8a-4d31896cc452.png)

`apex`で検索し　`Salesforcedx-vscode-apex > Java:Home`の欄にフォルダのパスを貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/6d71cacb-2258-cd8c-9dab-cd110e96c33d.png)

Ctrl + Shift + P で開いた窓に`reload`と入力し
開発者:ウィンドウの再読み込み をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/38f4a59b-57bc-3682-1e34-34427ee96abf.png)

テストクラスを開いて出てきたら成功です( * 'ω' * )
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/ef578139-46ec-e5fc-a085-f6dd7e097c65.png)

# 参考

https://developer.salesforce.com/tools/vscode/ja/getting-started/java-setup

https://qiita.com/piepie1231/items/def2e6b0f8e5d16f63f7
ULIDをヒットさせる正規表現

## 概要

- ULIDをヒットさせるための正規表現をメモ的に記載しておく。

## ULIDのフォーマット

- 下記のようなタイムスタンプ部10桁とランダム部16桁を合体した26桁
- 0~9の数字とA~Z（I, L, Oを除く）を使用しており大文字小文字を区別しない。

    ```
    TTTTTTTTTTXXXXXXXXXXXXXXXX
    ```

## ヒットさせる正規表現

- `I, L, Oを除く`の条件をあえて無視して簡単に済ませたい時

    ```
    [0-9a-zA-Z]{26}
    ```

- `I, L, Oを除く`の条件を含めしっかり表現したい時

    ```
    [0-9a-hjkmnp-zA-HJKMNP-Z]{26}
    ```
フォルダからファイル名を取得＋縦にcsv出力（Python）

以前やったけど、すぐ忘れてしまうので何処かに書かないと、
と危機感を覚えたのでメモ的に（下に参考URLを記載しています。）

環境：MacOS Monterey＋Anaconda3 Jupyternotebook

フォルダ内には、PDFファイルしかなくて（1000ほど）、このリストを作りたいってコトです。

```python
#　リストに出力
import os
p = os.listdir('ディレクトリのパス')
p

# 内包表記で、pの中にある文字を全て置換（ここでは".pdf"を全て""に置換して除いてます）
replaced_p = [s.replace(".pdf","") for s in p]
replaced_p

# 降順に並び替える
new_p = sorted(replaced_p)
new_p

# 作ったリストをcsvに出力 縦に出力する
import csv

with open('new_p.csv', 'wt', encoding='utf-8') as po:
    
    for name in new_p:
        po.write(name+'\n')
```

久しぶりだと、どうしても忘れてしまいますよね。
Jupyternotebookとかで、一つ一つ確認できるように書いてますので、
フォルダ内のファイル一覧をcsv出力したい場合は、是非どうぞ！

【参考URL】
・listdirでフォルダ内リストを取得
https://pg-chain.com/python-listdir

・replaceを使ったリスト内の文字置換
https://www.fenet.jp/dotnet/column/language/7276/

・リスト内を順番に並び替える
https://www.javadrive.jp/python/list/index11.html

・CSVに縦で出力
https://qiita.com/elecho1/items/3bc56ca55a600c2e2abc

・コードの埋め込み方法
https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1

有り難う御座います！
intをint型のまま１文字づつリストに保存するやり方

stringに直してsplit関数等を使わずに、int型はint型のまま１文字づつリストに格納するやり方になります。
1. ０になるまでループを回す。
2. 空リストに受け取った数値を10で割った余りを詰める。
3. 受け取った数値を10で割る。
4. 1.に戻る。

```c++

int main()
{
    int n;
    cin >> n;
    vector<int> a;
    // 0になったらfalseになる。
    while (n)
    {
        // n%10で1桁目を取得する
        a.push_back(n%10);
        
        // 1桁目を削除する。
        n /= 10;
    }
    return 0;
}

```
ULIDあれこれ

# 概要

- ULIDについてメモ的にまとめる　。

# ULID

- フォーマットは異なるがUUIDにタイムスタンプ情報を付与してソートできるようにしたもの。
- 辞書式順序でソートが可能である。
- 下記のようなフォーマットを用いる

    ```
    TTTTTTTTTXXXXXXXXXXXXXXXX
    ```

- 10桁のタイムスタンプ部 + 16桁のランダム部分で構成され合計26桁の文字列で表現する。
- 構成文字は0~9の数字とA~Z（I, L, 0は除く）を使用する
- 大文字小文字を区別せず特殊文字は使わない。

# 参考文献

- [https://github.com/ulid/spec](https://github.com/ulid/spec)
Spring AOP

## AOP(Aspect Oriented Programming)

1. 定義 
AOP（Aspect Oriented Programming）の略で、**複数のオブジェクト（Core concern）に共通に適用できる機能（Advice）を別々に定義・分離してコードの再利用性を高める**プログラミング技術である。つまり、別に定義した共通機能を他のオブジェクトに挿入すること。

2. 特徴
(1) 共通の関心をコアの関心から分離することで、コアロジックをきれいに保つことができる。
(2) これにより、コードの読みやすさ、安定性などを高めることができる。
(3) 各モジュールに変更が必要な場合は、共通の関心を変更するだけで済むのでメインテナンスが容易になる。

3. 関連用語
(1) target：adviceが追加されるオブジェクト
(2) advice：targetに追加される共通の関心
(3) proxy：targetにadviceが動的に追加されて生成されたオブジェクト
(4) weaving：targetにadviceを追加してproxyを生成する行為
(5) join point：Adviceを適用可能なポイント（Springでjoin pointはメソッドのみ）
(6) pointcut：実際にAdviceが適用されるjoin point
deno で puppeteerを使う

## chromiumのインストール
```shell
PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@14.1.1/install.ts
```

## puppeteerの実行ファイルを作成

```javascript
import puppeteer from "https://deno.land/x/puppeteer@14.1.1/mod.ts";

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://deno.land", { waitUntil: "domcontentloaded" });
const h1 = await page.$("h1");
const h1Text = await h1.evaluate((e: any) => e.innerText);
console.log(h1Text);
await browser.close();
```
UUIDをヒットさせる正規表現

## 概要

- UUIDをヒットさせるための正規表現をメモ的に記載しておく。

## UUIDのフォーマット

- UUIDのフォーマットは下記である。

    ```
    XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
    ```

- `-`で区切られ`8桁-4桁-4桁-4桁-12桁`の0~9とa~fの英数字で表現される。

## ヒットさせる正規表現

- 下記のようになる

    ```
    ([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})
    ```

- 3フィールド目の最初の一文字がUUIDのバージョンを指定しているのでUUIDのバージョンを指定してヒットさせたい場合下記のようになる。

    | バージョン | 正規表現 |
    |---|---|
    | 指定なし | ([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12}) |
    | 1 | ([0-9a-f]{8})-([0-9a-f]{4})-(1[0-9a-f]{3})-([0-9a-f]{4})-([0-9a-f]{12}) |
    | 2 | ([0-9a-f]{8})-([0-9a-f]{4})-(2[0-9a-f]{3})-([0-9a-f]{4})-([0-9a-f]{12}) |
    | 3 | ([0-9a-f]{8})-([0-9a-f]{4})-(3[0-9a-f]{3})-([0-9a-f]{4})-([0-9a-f]{12}) |
    | 4 | ([0-9a-f]{8})-([0-9a-f]{4})-(4[0-9a-f]{3})-([0-9a-f]{4})-([0-9a-f]{12}) |
    | 5 | ([0-9a-f]{8})-([0-9a-f]{4})-(5[0-9a-f]{3})-([0-9a-f]{4})-([0-9a-f]{12}) |
C/C++ で最低限のテスト

最低限やっておく具体的なテストのメモ

# gcc

## 静的
|オプションなど|説明|
|:-|:-|
|-Wall -Wextra -Werror|警告を出しエラーにする|
|-fanalyzer|静的解析してくれる|

## 動的
|オプションなど|説明|
|:-|:-|
|-fsanitize=lead -fsanitize=address|メモリアクセス違反・メモリリークを検出する|
|-fsanitize=undefined|未定義動作の検出|
|||
アルファベット3文字を使って色彩を表現する

## やったこと
アルファベット3文字を使って色を表現した.
アルファベットをASCIIコードに変換して, RGBの値0から255で正規化.
最終的に16進数のカラーコードに直して使用した.

## 実際のコード
```TS:colormap.ts
const getColor = (uid: string) => {
    //アルファベットから色を決める関数
    let changeAscii: string[] = [];
    let ascii10: number[] = [];
    let ascii16: string[] = [];
    //asciiの最小値(Aのコード)が65
    let minascii: number = 65;
    //colorcodeの変数に16進数に変換された文字列を継ぎ足していく
    let colorcode: string = '#';
    for (let i = 0; i < 3; i++) {
      //changeAsciiには1文字目と2文字目と3文字目が入る(別に配列じゃなくてもいいやん…)
      changeAscii[i] = uid.slice(i, i + 1);
      //ascii10はchangeAsciiを10進数のコードに変換. Numberで囲んでやって型を落ち着かす.
      ascii10[i] = Number(changeAscii[i].codePointAt(0));
      //ここで正規化&小数点以下切り捨て
      ascii10[i] = Math.floor((255 * (ascii10[i] - minascii)) / 57);
      //ascii16は正規化後のascii10をストリングにしたやつ
      ascii16[i] = ascii10[i].toString(16);
      colorcode += ascii16[i];
    }
    console.log(colorcode);
    return colorcode;
  };

```
## 苦労
```TS
ascii10[i] = Number(changeAscii[i].codePointAt(0));
```
の部分がNumber()で囲まないと number|undefinedになってしまうので上の方で変数の型宣言変えたりしながらうんうん唸ったが, 関数とかで呼び出した型はこういうふうにコントロールすればいいんだと勉強になった気がする. たぶんこの問題にあたってこうやって解決したのは初めてじゃないのでちゃんと書いとく.
React Nativeでアプリの画面を作ろう（画像貼る）

# はじめに
React Nativeのローカル環境ができたばかりで何していいかわからないから
とにかく触ってみよう。
画像を貼ってみる。

# おさらい。Expoを起動する
プロンプトを起動。
アプリ（MyApp）を保管しているディレクトリ（C:\Users\watya\myApp）へ移動して、expo起動

```
cd C:\Users\watya\myApp
expo start
```

# 画像を貼るならImageタグ
imageタグを使いたいならまずは、importにimageを追記。

```
import { StyleSheet, Text, View, Image } from 'react-native';
```

で、Imageタグを使う。

https://runebook.dev/ja/docs/react_native/images

を参考に。

```
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, Image } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
        <View style={styles.itemContainer}>
          <View style={styles.leftContainer}>
            <Image
              style={{ width: 100, height: 100}}
              source={{uri: 'https://1.bp.blogspot.com/-ZOg0qAG4ewU/Xub_uw6q0DI/AAAAAAABZio/MshyuVBpHUgaOKJtL47LmVkCf5Vge6MQQCNcBGAsYHQ/s1600/pose_pien_uruuru_woman.png'}} />
          </View>
          <View style={styles.rightContainer} />
        </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  itemContainer: {
    height: 100,
    width: "100%",
    borderColor: "gray",
    borderWidth: 1,
    flexDirection: "row"
  },
  leftContainer: {
    backgroundColor: "red",
    width: 100
  },
  leftContainer: {
    backgroundColor: "blue",
    flex:1
  },
});
```

できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/0780b90c-8979-b20e-8eb1-ef278961d3a5.png)
Terraform を使ってAWSにデプロイする時はaws-vaultが便利という話 

# 本記事について
最近、Terraformのデプロイを2段階認証ありで行うと手間だったので、簡単にできる方法はないかと調べたところ、aws-vaultを見つけた。aws-vaultを使ってデプロイするとアクセスキーを毎回取ってくる必要はないので非常に楽にデプロイできる。

# 前提
- 以下インストールされている環境
    - `brew`
    - `terraform`
    - `aws cli`

# 実行環境
```
% aws --version
aw-cli/2.7.13 Python/3.10.5 Darwin/21.4.0 source/arm64 prompt/off

% terraform --version
Terraform v1.2.4
on darwin_arm64

% sw_vers
ProductName:	macOS
ProductVersion:	12.3.1/
```

# AWS側の設定
#### デプロイをするためのIAMロールを作成する
デプロイ時に必要な権限を付与したIAMロールを作成しましょう。
選択するのは、「AWSアカウント」 > 「このアカウント」 > 「次へ」
![スクリーンショット 2022-07-08 18.22.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326068/4b082fe3-00b2-7b83-e69e-564b12dae3d2.png)

必要な権限を追加し、名前をつけた後に信頼されたエンティティを設定します。
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<account_id>:user/<user_id>"
            },
            "Action": "sts:AssumeRole",
            "Condition": {}
        }
    ]
}
```

ロールが作成できたら、前準備は完了です。

# aws-vault実行まで
#### aws-vaultインストール
```
% brew install aws-vault
```

#### configを設定する
```
mkdir ~/.aws
vi ~/.aws/config
```
configを以下のように記載(環境が一個でいい場合はdefaultだけでも大丈夫)
```
[default]
region=ap-northeast-1
output=json
mfa_serial=arn:aws:iam::<account_id>:mfa/<account_id>
role_arn=arn:aws:iam::<account_id>:role/<AWS側の設定で作成したロール>

[profile test]
region=ap-northeast-1
output=json
mfa_serial=arn:aws:iam::<account_id>:mfa/<account_id>
role_arn=arn:aws:iam::<account_id>:role/<AWS側の設定で作成したロール２>
```
#### aws-vaultの設定を行う
上記のようにconfigを記載した後に`aws-vault list`コマンドでプロファイルがあるか確認する。
```
% aws-vault list
Profile                  Credentials              Sessions
=======                  ===========              ========
default                  -                        -
test                     -                        -
```
今回はdefaultに設定を反映させたいので以下のコマンドを打ってアクセスキーとシークレットアクセスきーを設定する
```
% aws-vault add default
Enter Access Key Id: <access_key>
Enter Secret Key: <secret_access_key>
```
再度`aws-vault list`で実行して、Credentialsにdefaultの記載があれば設定完了です。
```
% aws-vault list
Profile                  Credentials              Sessions
=======                  ===========              ========
default                  default                  -
test                     -                        -
```
#### aws-vaultでs3 listを表示してみる
Terraformコマンド実行の前に`s3 ls`でちゃんと動くか確認して見ましょう。
下記コマンドを実行して、エラーが出なければ成功です。
```
% aws-vault exec default -- aws s3 ls
Enter MFA code for arn:aws:iam::<account_id>:mfa/<user_id>: 
```
# Terraformの実行
上記までの手順があればあとは、Terraformのある場所で以下のようにTerraformのinitやapplyができます。
```
aws-vault exec default -- terraform init
aws-vault exec default -- terraform apply
```

# 最後に
まだまだ初学者ですので、間違っていることがあればコメントで教えて下さると大変助かります。
ありがとうございました。
vba sheetデータ纏める

自分の覚書


```vb
Sub TEST4()
  
  Dim row, ws, wb
  Set ws = ThisWorkbook.Worksheets("Sheet1")
  'フォルダ内のブック名を取得
  wb = Dir("C:\Users\Wataru.VAIO\Desktop\プログラミング" & "\*.xlsx")
  Debug.Print wb
  '"C:\Users\Wataru.VAIO\Desktop\プログラミング"
  
  
  
  Do While wb <> ""
    'ブックを開く
    Workbooks.Open "C:\Users\Wataru.VAIO\Desktop\プログラミング\" & wb
    'データ部分を取得
    With ActiveWorkbook.Worksheets("Sheet1").Range("A1").CurrentRegion
      row = .Rows("2:" & .Rows.Count)
    End With
    'データを入力
    ws.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Resize(UBound(row, 1), 10) = row
    ActiveWorkbook.Close False 'ブックを閉じる
    wb = Dir() '次のブック名を取得
  Loop
  
End Sub

```
discord.js v13 もくもくログbot作成

discord.js 初挑戦。
もくもく会のサーバーで使うログ用のbotを作りました。


- npm v8.11.0
- Node.js v16.15.1
- discord.js v13.8.1


## 導入
こちらの記事をガッツリ参考に、というかマルパクしました。
ありがとうございます。

https://qiita.com/hitori_yuu/items/02eae8b14dc6a9c91c0d

が、clientインスタンスは下記に書き換えないと動かなかったので注意。
```js
const client = new Client({intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES]}); 
```

## .gitignoreを設定
.gitignoreに入れておく。
```
node_modules
config.json
.env
```
config.json は Github なんかでコード管理したいときにトークン置き場として使う。詳しくは Discord.js Japan User Group のページを参照。

[jsonファイルを使用してトークンを管理する（安全に）](https://scrapbox.io/discordjs-japan/json%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E7%AE%A1%E7%90%86%E3%81%99%E3%82%8B%EF%BC%88%E5%AE%89%E5%85%A8%E3%81%AB%EF%BC%89)

## Discord API 公式Doc
APIの仕様はこちら参考↓

https://discord.com/developers/docs/resources/application

## 実装

まずはjsonファイルにIDもろもろを書いておく。

```config.json
{
  "token": "トークン",
  "guildId": "サーバーID",
  "logsId": "ログ投稿用チャンネルのID"
}
```

index.jsにこれらを書く。

```index.js
const { Client, Intents } = require("discord.js");
const config = require("./config.json"); //トークン格納用

const client = new Client({
  intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES],
});

const guildId = config.guildId;
const logsId = config.logsId;

client.once("ready", () => {
  console.log(`${client.user.tag} 起動完了`); 
});

client.on("messageCreate", (message) => {
  if (message.author.bot) {
    return;
  }
  if (
    message.content.startsWith("■今日やること") ||
    message.content.startsWith("■今日の成果") //もくもく会参加時のテンプレを拾う
  ) {
    client.channels.cache.get(logsId).send({ //指定したチャンネルIDに下記内容を転記
      content: `${message.author} \n ${message.content}`, //@投稿者<改行>投稿内容
    });
  }
});

client.on("messageCreate", async (message) => {
  if (message.content.startsWith("■今日の成果")) {
    message.react("🍵"); //お疲れ様の意
  }
});

client.login(config.token); //ログイン
```


## 起動
package.jsonに以下を追記しておく。
```package.json
"start": "node ."
```

プロジェクトディレクトリ（index.jsのルート）で「node .」と打ち込めば起動する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630447/62187df7-8532-f3da-c54e-0502099aa3c1.png)

こんな感じで指定チャンネルに投稿してくれる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630447/972c5dc2-e1fb-2304-5b4d-083014bbe707.png)
UUIDあれこれ

# 概要

- UUIDについてざっくり調べたのでまとめる。

# UUIDとは

- 重複する可能性が極めて低い値
- 極めて一意に近いIDのこと
- 複数のバージョンが存在する
- 下記のフォーマットが用いる

    ```
    XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
    ```

- `8桁-4桁-4桁-4桁-12桁`の英数字（0~9とa~f）で生成される
- 3フィールド目の4桁の頭にUUIDのバージョンが入る（1~5の間）
- 複数のバージョンが存在し、生成の方法がそれぞれ異なる。
【.NET 6, .NET Core】デスクトップアプリで既定のブラウザを使ってURLを開く

## .NET Framework時代
URLをブラウザで開くとき、以下のコードを良く使っていました。
```CSharp
private void btn_Click(object sender, EventArgs e)
{
    Process.Start("https://qiita.com/");
}
```

## .NET Core以降
しかし、.NET Core以降で同じコードを実行すると、ファイルが無いと言われてエラーになってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224096/f2755849-09e7-ce4b-4b13-eca40a27c8b7.png)
実行するためには、`ProcessStartInfo`の`UseShellExecute`を`true`に設定する必要があります。

```CSharp
private void btn_Click(object sender, EventArgs e)
{
    Process.Start(new ProcessStartInfo("https://qiita.com/") { UseShellExecute = true });
    // Process.Start(new ProcessStartInfo { FileName = "https://qiita.com/", UseShellExecute = true }); // これでもOK
}
```

## 原因
`ProcessStartInfo.UseShellExecute`プロパティの既定値が.NET Frameworkでは`true`、.NET Core以降では`false`となっているため。
> The default is true on .NET Framework apps and false on .NET Core apps.

https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.useshellexecute?view=net-6.0#property-value
SpringBootのお勉強

# 概要

以前、業務でSpring Bootを触る機会があったため、社内wikiに備忘録的にメモを残していました。
オープンな場に残しておこうと思い、ここに書いておきます。

## Spring Bootとは

* Spring Framework一族のひとり
* 簡単な設定で使えるSpring
* Webコンテナを内包する
  * Webコンテナをjarに含めるので、jar単体でWebアプリとして成立する(スタンドアロン)

## 環境構築

* Eclipse or IntelliJ IDEA Community EditionにSTS(Spring tool suite)のプラグインを入れる
* Spring Starter Projectを作成する
  * ウィザードに従う
    * とりあえずweb -> Spring webを入れておけばおk

## 実践

### AutoConfigure

* Bean定義自動設定
    * `@SpringBootApplication`
        * ↑のアノテーションに`@SpringBootConfiguration`が付与、それに`@Configuration`が付与されている
  * `@Configuration` + `@EnableAutoConfiguration` + `@ComponentScan`
  * `@EnableAutoConfiguration`を付与することで自動設定が動く
    * org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector.classの設定による

### Unit Test
* `@SpringBootTest`
  * ApplicationContextを簡単操作
  
 * `@TestConfiguration`
    * カスタムコンフィグ
  
 *  `@MockBean`
    * MockをDIできる
  
 * Web Environment test
    * Web環境を構成した上でテスト可能になる
  
* SpringBootTestの使用について
  * 遅いからUnit Testに向かない
    * -> テスト実行時の都度Spring Bootの起動が必要だから
    * Mockitoを使おう
    * ロジックのテストではなくユースケースのテストを書くなら有用

### Actuator
* システムの状態を監視
* HTTPエンドポイントで管理できる

### WebAPI用のControllerクラスを作成
* `@RestController`をつける
  * `@Controller` + `@ResponseBody`
    * JSONやXML等を返す
  * `@RequestMapping`でUrlを設定

* パラメーター
  * `@PathVariable`を使用
  * `@RequetstMapping`に{xxx}で`@PathVariable`でアノテートしたパラメータにバインドする

* JavaBeanの返却
  * `@RestController`ではJavaBeanをJSONにして返却する
  * HashMapも同じでJSONにして返却する

* APIの呼び出し
  * RequestEntity(リクエストオブジェクト)
  * ResponseEntity(レスポンスオブジェクト)
  * RequestEntityをRestTemplateでJOSN化し、JSONで返ってきたデータをRestTemplateでオブジェクトに戻す
  * RestTemplate内にMessageConvertorがある

* ファイル
  * org.springframework.core.io.FileSystemResourceを使用する

* 例外ハンドラ
  * クラスに`@RestControllerAdvice`
    * `@RestControllerAdvice`->ResponseBodyを返却、`@ControllerAdvice`->パスを返却
  * ↑は例外ハンドラではなく、共通処理の実装方法
  * メソッドに`@ExceptionHandler`、引数は対象となる例外

* Singleton
  * `@Scope`でスコープを指定できる
  * 基本的にSingletonでOKなのかは疑問

## セキュリティ

* ErrorAttribute
  * DefaultErrorAttributesを継承してカスタムする

## SpringBootのデメリット

* 設定が楽＝設定部分が隠蔽されているということだから、いざ自分でカスタムする必要が出た時のコストが高め？
  * 初学者はSpring MVCを先に学んだ方が良い
  * 自分で設定、制御したいマンには向かない
* スタンドアローンだからモノリシックなシステムに合わない
* 設計をミスると依存モジュールが膨大な数になる→起動時間の増加に繋がる(Spring MVCでも同じか)
* 大部分は設定が楽になることに対するデメリット

## 参考
https://spring.io/projects/spring-boot
https://spring.pleiades.io/
https://qiita.com/sugaryo/items/5695bfcc21365f429767
https://qiita.com/kazuki43zoo/items/8645d9765edd11c6f1dd
https://dev.classmethod.jp/articles/spring-boot/
https://meetup-jp.toast.com/452
https://dawaan.com/mockbean-vs-mock/
https://www.springboottutorial.com/spring-boot-projects-with-code-examples
https://www.javaguides.net/2018/10/free-open-source-projects-using-spring-boot.html
https://dzone.com/articles/top-5-spring-boot-features-java-developers-should
https://www.educba.com/what-is-spring-boot/
https://stackoverflow.com/tags/spring-boot/info
https://www.java2novice.com/java_interview_questions/spring-boot-pros-and-cons/
NATGWでセッションマネージャー接続する方法

<h1>やりたいこと</h1>
 プライベートサブネットにあるEC2からセッションマネージャーで接続する<br><br>
使用サービス<br>
 NATGW,EC2,INGW,VPC,VPCエンドポイント<br><br>

参考構成図
https://dev.classmethod.jp/articles/patterns-about-access-ec2-on-private-subnet/

NATとかVPCとかの設定方法
https://qiita.com/fkooo/items/a474db0f3c2e72448d36
https://qiita.com/TK1989/items/5d9bd5d49708c02dff3f

RHEL8 ユーザーデータ
https://aws.amazon.com/jp/premiumsupport/knowledge-center/install-ssm-agent-ec2-linux/

<h1>EC2インスタンス</h1>
OS:RHEL8

<h1>EC2インスタンス セキュリティグループ</h1>
 インバウンド
 SSH,HTTPS,HTTPのCIDRをVPCと同じで追加

 アウトバウンド(フルオープン)
 すべてのトラフィック	0.0.0.0/0

<h1>EC2インスタンス IAMロール</h1>
AmazonSSMManagedInstanceCore<br>
AmazonEC2RoleforSSM

<h1>VPCエンドポイント</h1>
<ol>
<li>com.amazonaws.ap-northeast-1.ssm</li>
<li>com.amazonaws.ap-northeast-1.ec2messages</li>
<li>com.amazonaws.ap-northeast-1.ssmmessages</li>
<li>com.amazonaws.ap-northeast-1.s3</li>
</ol>

エンドポイントのサブネットはEC2のサブネットを指定する

 S3エンドポイントのルートテーブルは、EC2インスタンスを作成したサブネットのルートテーブルと同じにする。エンドポイント設定後にルートテーブルをみるとS3エンドポイントのルートが追記されている。

<h1>ルートテーブル</h1>
 サブネット二つの設定が必要<br>
 1.EC2がたっているサブネットのルートテーブルが最終的に、3つのルートがあること<br>
  S3エンドポイント作成時のルート<br>
  NATGWへのルート<br>
  デフォルトで入っているlocalのルート<br>
<br>
 2.NATGWが入っているパブリックサブネットのルートテーブルが最終的に、2つのルートがあること
  インターネットゲートウェイとデフォルトで入っているlocalのルート
pythonでリスト中の数値を文字列に変換する際は`print("".join(list(map(str, ans))))`のようにした方が処理が早そうな印象

pythonでリスト中の数値を文字列に変換する際は`print("".join(list(map(str, ans))))`のようにした方が処理が早そうな印象

例えば、数値を含むリスト(`ans = [1]*100000`)を連結した１つ文字列として出力したい場合
以下のように`*10`を足すような処理した場合は、、1secほど掛かる

```py:test.py
ans = [1]*100000
val = 0
for ii in range(len(ans)):
    val = val*10 + ans[ii]
print(val)
```

```sh
$ python test.py
real	0m1.147s
user	0m1.124s
sys	0m0.013s
```

以下のように`.join`により処理した場合は、、0.02secほど掛かる

```py:test.py
ans = [1]*10000000
print("".join(list(map(str, ans))))
```

```sh
$ python test.py
real	0m0.027s
user	0m0.020s
sys	0m0.010s
```

`print("".join(list(map(str, ans))))`が使えると便利そうな印象
SpringのDB、h2 console

最近勉強しているSpring Projectでh2というDBをつなげてみたので記録。

## 1. 接続

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662678/bd1a09d7-89d3-5363-d2a5-5125839d3839.png)
1．Projectのresources→application.propertiesに **spring.h2.console.enabled = true**の入力で準備OK

---

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662678/5b3c5cb4-7289-3d9a-2e63-6b8da367461b.png)
2．Application.javaをShift＋f10の入力または赤い四角内のボタンで起動させる

---

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662678/3b52c3d7-b8df-060e-ad3a-556215dc5b5c.png)
3. 下でh2を検索、赤い四角のようにjdbcで始まるjdbc urlを探してコピーしておく。
　このIDはSpringが起動するたび変わるものなので注意！

---

![44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662678/f98aaa71-6dfd-030f-10fd-bc27c07a116b.png)
4．[http://localhost:8080/h2-console](http://localhost:8080/h2-console)に接続、3でコピーしたjdbc urlをPasteしてConnect

---

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662678/26c5f37a-ab0c-d750-6ce9-c4520520de4b.png)
5．接続に成功した！

---

<br><br><br>

## 2. CRUD（Insert, Select, Update, Delete)
Springで作成したEntityファイルにはLong id, String title, String content項目があることを前提に
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662678/05ba2efb-a89c-daa3-a35c-0e612e349b06.png)
**1. InsertとSelect**：まずはCreate（Insert）とRead（Select）文の作成とその意味
（1）Insert：INSERT INTO article(id, title, content) VALUES (1, 'title1', 'content1');
　　　　　　→DBテーブルのarticleの項目id, title, contentにそれぞれ1、title1、content1を付与
（2）Select：SELECT * FROM article; 
　　　　　　→articleに入れた値をすべて出力
　Insertを5回、Selectを入れ、Runすると、ちゃんとデータがテーブルに入ってることが確認できた

---

![77.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662678/fcd05c92-5be2-e6cc-a711-bc60d1085894.png)
**2. Update**：Update文の作成と意味
　（1）Update：UPDATE article SET id=10 WHERE id=5; 
　　　　　　　 →DBテーブルのID5の値を10に変更。結果、5だったID値が10になった

---

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662678/5a63c328-615f-347a-ece1-7388518d66cc.png)
**3. Delete**：Delete文の作成と意味
　（1）Delete：DELETE FROM article WHERE id=10;
　　　　　　　 →DBテーブルのID10の値を削除。結果、ID10の行がなくなった

---

DBでの直接なCRUDは、いちいちコードを書かないといけないのが面倒なところもあるが、自分の入力したコードの結果がすぐに見えて意外と楽しい
Spotify APIで完全ランダムなプレイリストを生成する(Python)

# 背景
Spotifyでは, おすすめの曲や似た曲を永遠に聴くことができる.
しかし全く無関係な曲の羅列を聞く方法がないのかと思い立った.似た曲ばかりを勧めてくるSpotifyに少々嫌気がさしたためである．
標準のプレイリストでは，特定のシーンに一致する曲を集めたものはたくさんあるものの，完全にランダムに選んだ曲を集めたものは見当たらない．

# 参考
Webを検索すると，試みている記事がいくつか．コチラを参考にした．

* [Pythonを用いてSpotifyのプレイリストを作成＆再生してみる](https://tori114.hatenablog.com/entry/2018/10/14/090525)
  * このPython側の準備をやっておく.
* [Getting random tracks using the Spotify API.
](https://perryjanssen.medium.com/getting-random-tracks-using-the-spotify-api-61889b0c0c27)
  * こちらの記事と同様，ジャンルをランダムで選んで・・・というのを最初考えたが，完全ランダムにはならないらしい．そこでこの記事のように，searchを使うことにしたのだが，この通りにやると[a-z]が入った曲しか引っかからないのでは，ということで，以下のようにした．

# APIのリファレンスとか
* https://developer.spotify.com/documentation/web-api/reference/#/operations/search
* https://spotipy.readthedocs.io/en/master/?highlight=genres

# 実装
* python3.Xで動作確認済み

```python:main.py
# 2022/07/08 v1.0

import spotipy
import spotipy.util as util
import sys
import random
import subprocess
import requests
import json
import string

# 検索キーワードを生成
def getRandomSearch():

    rand_char=''
    randlst='A'
    while rand_char=='':
        # [1]と[2]の確率を設定
        if random.randint(0, 3) == 0:
            # [1] A-Z,0-9から選ぶ
            randlst = [random.choice(string.ascii_letters + string.digits) for i in range(1)]
            rand_char=''.join(randlst)

        else:
            # [2] A-Z,0-9だとタイ語や日本語のみの曲が引っかからないので,文字全体から選ぶ
            randlst=random.randint(0, 1114111)
            rand_char=chr(randlst)

    randomSearch = ''
    # %はワイルドカード
    if random.randint(0, 1) == 0:
        randomSearch = rand_char + '%'
    else:
        randomSearch = '%' + rand_char + '%'

    return randomSearch



# ****** main ******
# ******************
username = "XXXXXXXXXXXXXX"
scope = 'playlist-read-private,playlist-modify-public'

token = util.prompt_for_user_token(username, scope)

sp = spotipy.Spotify(auth=token)
header = {'Authorization': 'Bearer {}'.format(token)}

# プレイリストを作成する場合はコメントイン
# playlist = sp.user_playlist_create(username,"NewPlaylist")
# playlist_id = playlist['id']

# 既存のプレイリストIDを指定
playlist_id = 'XXXXXXXXXXXXXXX'

# 国コード一覧を取得
country_codes = sp.country_codes
# 国コードの総数
country_num = len(country_codes)

track_ids = []

# 100曲追加
while len(track_ids) < 100:
    # 国コード一覧の中からランダムで一つ選ぶ
    random_market = country_codes[random.randint(0, country_num - 1)]

    # 検索クエリ
    query = getRandomSearch()
    # オフセット値の最大は999
    randomOffset = random.randint(0, 999)

    #検索を実行し1曲取得
    results = sp.search(type = 'track', offset = randomOffset, limit = 1, q = query, market = [random_market])

    if results is None:
        print('NoneType')

    else:
        # 曲を取得できた場合
        if len(results['tracks']['items']) >= 1:
            # idを格納
            track_ids.append((results['tracks']['items'][0]['id']))
            print(results)

        else:
            print('No Results...')


    print(len(track_ids))

# プレイリストに追加
sp.user_playlist_add_tracks(username, playlist_id, track_ids)

```

# 後記
こうして生成されたランダムなプレイリストを聴いていても，特に楽しくない．ソースをいじっている時が一番楽しかった．むしろ，興味のない曲を聴いていても苦痛である．
ある程度のジャンルの制約や，シーンに合わせたプレイリスト，お気に入りの曲に合ったおすすめというのは必要だとわかった．