OmniAICreator/Qiita-1.07M huggingface dataset:
Python 3.11@Windows の pdb における文字コードエラー

# あらまし
Python 3.11 で pdb でデバッグしようとしたところ、文字コードに関する問題が発生したので備忘。
※コンソール出力からは、パス情報を除去しています。

# 環境
Python 3.10, 3.11, 3.12
Windows 10

# テストコード
文字コードは UTF-8 で保存していた。

~~~ python
#!/usr/bin/env python

def main():
    print ('こんにちは、世界！')

if __name__ == '__main__':
    main()
~~~

# 普通に実行 ⇒ 問題なし
~~~
PS > py -3.10 .\test.py
こんにちは、世界！
PS > py -3.11 .\test.py
こんにちは、世界！
PS > py -3.12 .\test.py
こんにちは、世界！
~~~

# pdb で実行
## 3.10 ⇒ 問題なし
~~~
PS > py -3.10 -m pdb .\test.py
> test.py(3)<module>()
-> def main():
(Pdb) c
こんにちは、世界！
The program finished and will be restarted
> test.py(3)<module>()
-> def main():
(Pdb)
~~~
## 3.11 ⇒ UnicodeDecodeError
~~~
PS > py -3.11 -m pdb .\test.py
Traceback (most recent call last):
  File "Python\Python311\Lib\pdb.py", line 1774, in main
    pdb._run(target)
  File "Python\Python311\Lib\pdb.py", line 1652, in _run
    self.run(target.code)
             ^^^^^^^^^^^
  File "Python\Python311\Lib\pdb.py", line 167, in code
    return f"exec(compile({fp.read()!r}, {self!r}, 'exec'))"
                           ^^^^^^^^^
UnicodeDecodeError: 'cp932' codec can't decode byte 0xef in position 74: illegal multibyte sequence
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> python\python311\lib\pdb.py(167)code()
-> return f"exec(compile({fp.read()!r}, {self!r}, 'exec'))"
(Pdb)
~~~
## 3.12 ⇒ UnicodeDecodeError
~~~
PS > py -3.12 -m pdb .\test.py
Traceback (most recent call last):
  File "Python\Python312\Lib\pdb.py", line 1813, in main
    pdb._run(target)
  File "Python\Python312\Lib\pdb.py", line 1652, in _run
    self.run(target.code)
             ^^^^^^^^^^^
  File "Python\Python312\Lib\pdb.py", line 167, in code
    return f"exec(compile({fp.read()!r}, {self!r}, 'exec'))"
                           ^^^^^^^^^
UnicodeDecodeError: 'cp932' codec can't decode byte 0xef in position 74: illegal multibyte sequence
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> python\python312\lib\pdb.py(167)code()
-> return f"exec(compile({fp.read()!r}, {self!r}, 'exec'))"
(Pdb)
~~~

# 原因
3.11から、pdbがソースコードを読み込むときの方法が変わったようだ。
3.10では `io.open_code` で開いていたが、3.11では `io.open` で読み込んでいる。(たぶん。)

3.10
https://github.com/python/cpython/commit/2c2055884420f22afb4d2045bbdab7aa1394cb63#diff-98d47941a1bfadcfdfe02973122c83be2940ca6f3b1c32ca8898e7f594d2669dL1580

3.11
https://github.com/python/cpython/commit/2c2055884420f22afb4d2045bbdab7aa1394cb63#diff-98d47941a1bfadcfdfe02973122c83be2940ca6f3b1c32ca8898e7f594d2669dR166

`io.open_code` についてはこちら。
https://docs.python.org/ja/3/library/io.html#io.open_code

なので、3.10ではバイナリモードで読み込んでいたため、文字コードエラーは起きていなかったが、
3.11で通常のテキストモードで読み込んでいるため、
デフォルトエンコードがSJIS(CP932?)であるWindowsでは文字コードエラーが発生しているようだ。

# 対策
## UTF-8モードを有効にする
Pythonは原則環境依存の文字コードを採用するが、これを強制的にUTF-8を標準とする方法がある。
https://docs.python.org/ja/3/using/windows.html#win-utf8-mode

環境変数 `PYTHONUTF8` に `1` をすればOK。

## ソースコードをShift-JISにする
文字通り。

# 疑問
自分の中ではpdbのソースコード読み込み方法を変更する議論が見つけられなかったのだが(よわよわ英語力)、どのような経緯でこの仕様が変更されたのだろうか？
このプルリクでは議論されてないっぽい？ https://github.com/python/cpython/pull/26992
Unity 個人メモ

・スクリプトがアタッチされたGameObjectを探す方法。
スクリプト名.cs.metaからguidを見て、*prefabからguidを検索する。

・StateMachineBehaviourを継承してAnimatorのStateにアタッチすると状態開始終了タイミングで処理を書ける。

・Animatorの状態変化に合わせてGameObjectを移動したりできる。
例えば攻撃を受けた状態に合わせて吹っ飛ばしするなど。

・ProjectからAnimatorを探す方法
ProjectウィンドウからOpenInSearchを開いてanimatorで検索。
（Search by typeにAnimatorがないのでこれで探しています。）
Mac OS Ventura 13.1にアップデート後、 ExpoでiOSシミュレーターを開けないエラーが発生。

<h1>エラー状況</h1>
Mac OS Ventura 13.1にアップデートしたところ、
ExpoでiOSシミュレーターを開けないエラーが発生。

```
› Opening on iOS...
Started Metro Bundler

xcrun exited with non-zero code: 2
An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=2):
Unable to boot device because we cannot determine the runtime bundle.
No such file or directory
```

<h1>解決方法</h1>
Xcodeを立ち上げ

-> Xcode メニュー
-> Open Developer Tool
-> Simulator　でシミュレータを立ち上げ

シミュレータメニューの Device
-> Erase all content and settingsでセッティングをクリア

これで解決できました。

```
› Opening on iOS...
Started Metro Bundler
› Opening exp://10.11.165.242:19000 on iPhone 14 Pro Max
```

<h1>参考</h1>
https://www.ok-data.com/entry/xcode%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%97%E3%81%9F%E3%82%89expo%E3%81%A7ios%E3%82%B7%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF%E3%81%8C%E8%B5%B7%E5%8B%95/
PHPのビルトインサーバでXdebugを使いVSCodeでデバッグする

# Install
- [phpインストール](https://qiita.com/yuki777/items/c8e33ca3290b55862c6a)済みであることを前提としています
- [VSCode拡張のPHP Debug](https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug)をインストールする。

# php.ini
```
; php --ini でphp.iniもしくはxdebug.iniを探してください

zend_extension = "xdebug.so"
xdebug.client_host = 127.0.0.1
xdebug.client_port = "9003"
xdebug.mode = debug
xdebug.idekey = "PHPSTORM"
xdebug.start_with_request = yes
```

# PHPビルトインサーバを起動する
- プロジェクトによりけりだと思いますが、下記のようなphpコマンドで起動します。
  - `-S` でビルトインサーバを起動します
  - `-t` でドキュメントルートを指定します
  - 引数でルーティングファイルを指定します
```bash
# 例
php -S 127.0.0.1:8081 -t public router.php

# もしくは某弊社のよくあるパターンならこんな感じです
php -S 127.0.0.1:8081 -t public bin/content.php
```

# VSCode設定 launch.json
- VSCodeの`実行とデバッグ`で、設定ファイルを作成するか、既存の設定があるならそれを編集します。
- `runtimeExecutable`でphpのpathを設定します。
- `program`でphpunitのpathを設定します

```json
{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Listen for Xdebug(PHPビルトインサーバ)",
      "type": "php",
      "request": "launch",
      "port": 9003
    },
    {
      "name": "Launch currently open script(PHP CLI)",
      "type": "php",
      "request": "launch",
      "cwd": "${fileDirname}",
      "runtimeExecutable": "${userHome}/.phpenv/shims/php",
      "runtimeArgs": [
        "-dzend_extension=xdebug.so"
      ],
      "program": "${workspaceRoot}/vendor/bin/phpunit",
      "args": [
        "${file}"
      ],
      "port": 9003,
      "log": false,
      "env": {
        "XDEBUG_MODE": "debug,develop",
        "XDEBUG_CONFIG": "client_port=${port}"
      }
    }
  ]
}
```

# VSCodeでXdebugと接続する
- VSCodeで、`Listen for Xdebug(PHPビルトインサーバ)`を選択して、 ▶️ で実行します。

![Screenshot 2023-01-21 at 15.34.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8352/528fcce0-8fd0-ddbd-7f7a-4a4df91f7bdf.png)

# VSCodeでデバッグしたいファイルにブレークポイントを設定します
- たとえばTOPページをデバッグしたいならindex.phpなどのphpファイルをVSCodeで開き、ブレークポイントを設定します。

![Screenshot 2023-01-21 at 15.53.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8352/b72fea88-237e-27b7-987d-4a6f27c0f176.png)

# ブラウザでデバッグしたいページにアクセスする
- ここで今回の例であれば、TOPページPHPファイルをホストしているのが、上で設定したPHPビルトインサーバです。
- 一連の設定がうまく行っていれば、ブラウザでアクセスするとフォーカスがブラウザからVSCodeに移り、ブレークポイントを設定したindex.phpファイルで処理が止まります。
- ブレークポイントで、変数をウォッチしたり、出力したり、関数を実行したり、処理の中へステップインしたりといったデバッグが可能です。

![Screenshot 2023-01-21 at 15.47.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8352/1706404f-3a5a-c50f-9fda-f463b1a52abe.png)

# 常時Xdebug onでも遅くはないですね
- off:778ms => on:1.59s くらいでした。
- 個人的にはこれくらいなら常時xdebug onでも我慢できそうです。

![Screenshot 2023-01-21 at 16.25.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8352/fdb8c102-8001-2ea5-99fa-bc8eeb2eeb5c.png)
Docker 概要


1. DockerHub（Docker イメージのレジストリの一つ）などのレジストリからイメージ（コンテナの設計図）をPullする。
2. pull したイメージをもとにDockerfile（イメージの定義書）でコンテナの設計図を作成する。
3. Docker Compose で Dockerfile をビルドすることで Docker イメージ（コンテナの設計図）が作られ、そのイメージを起動することでコンテナが起動する。




docker run docker/whalesay cowsay Hello!
                           -------------
                              ↑ コンテナ内で呼び出すコマンド

docker images 
イメージ一覧

docker tag A B
イメージにタグ付けするコマンド
AとBをタグづけする
例
docker tag docker/whalesay my_whalesay
イメージにタグ付けするコマンド

docker inspect A
イメージの詳細情報を表示するコマンド
Aはイメージ名もしくはイメージID
JavaScript　スコープ編

<h4>・スコープとは</h4>

　<b>スコープ</b>とは、コードが他のコードを使うことの（参照）できる範囲のことである。基本的に`{}`内の中でのみ参照することができる。

![screenshot.2023-01-20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850098/d3b64355-4865-c263-386d-de5840d8261a.jpeg)

上の図のように`scFun()`と`scFunction`は`ScopeA`を参照することができるが、`scFun`内の変数`scopeB`は`scFun`内でしか、参照することができない。（scFunctionも同じである）

<h5>・JavaScriptのスコープの種類</h5>

|種類|説明|
|:-------|:---|
|グローバルスコープ|HTMLの<b>トップレベル</b>（関数やブロックに入っていない変数）にある、「<b>var</b>を使って宣言された変数や関数」や「関数宣言によって定義された関数」が属するスコープ|
|スクリプトスコープ|グローバルスコープの<b>let</b>、<b>const</b>バージョン|
|関数スコープ|関数内で宣言された変数や関数が属する範囲|
|ブロックスコープ|if文やwhile文などのブロック内で<b>let</b>、<b>const</b>で宣言された変数や関数が属するスコープ|

<h4>・スコープの特徴</h4>
<h5>・関数スコープ</h5>
　<b>関数スコープ</b>とは、関数内で宣言された変数や関数のこと。関数スコープは関数ごとに作成されるので、関数スコープ内にある変数や関数は、その関数スコープ外から参照することができない。

![screenshot.2023-01-21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850098/a7ffb0ab-f938-37e1-9efb-29f0bb934ae5.jpeg)

<h5>・ブロックスコープ</h5>

　<b>ブロックスコープ</b>とは、`{ }`ブロック内で<b>let</b>や<b>const</b>で宣言された変数や、関数のこと。ただし、<b>var</b>で宣言された変数や、<b>関数宣言</b>で定義された関数はブロックスコープを無視して、<b>外側</b>のスコープに属することになる。(varや関数宣言で定義された変数や関数は、グローバルスコープとなってどこからも参照することができる。)

```JavaScript:ブロックスコープ
{
    let letStr = "letStrです";
    const constFunc = function() { console.log("constFunctionです")};
    var varStr = "varStrです";
    function Func() { console.log("関数宣言")};
}

{
    //letStrはブロック内かつletで宣言された変数なのでエラーが起きる。
    console.log(letStr);
    //constFuncはブロック内かつconstで宣言された関数なのでエラーが起きる。
    constFunc();
    //varStrはvarで宣言された変数なので実行することができる。
    console.log(varStr);
    //Funcは関数宣言で宣言された関数なので実行することができる。
    Func();
}
```
ライブラリで簡単に無限スクロールを実現 JS/jQuery/PHP/PDO/MySQLを使用して

jQueryライブラリの infinite-scroll を利用します。

https://infinite-scroll.com/

## HTML, JS
まずはHTMLおよびJavaScriptの部分。

注意点としてはloadNext.phpと記述する部分で追加部分を読み込むわけだが、ここにpage=1のような数値が必須である点。その数字を読み込むごとに増やしていく前提でこのライブラリは作られている。ここは自動で増えていく。

そのため、この例のようにpage=1としておけば勝手に次はpage=2として自動で読み込んでくれる。便利なんだが不便なんだか分からんが。
```timeline.html
<div class="container">
    <!--ここには既存のコンテンツ（最初に表示されるコンテンツ）-->
    <div>すでに読み込まれているコンテンツ</div>
    <div>すでに読み込まれているコンテンツ</div>
    <div>すでに読み込まれているコンテンツ</div>

    <!-- 無限スクロールで読み込みたいところ -->
    <div>
      <a class="pagination__next" href="loadNext.php?page=1"></a>
    </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://unpkg.com/infinite-scroll@4/dist/infinite-scroll.pkgd.min.js"></script>
<script>
$('.container').infiniteScroll({ //.containerはHTML側で指定しているwrapper的なところ。
  // options
  path: '.pagination__next', //必須。ここにスクロールしてきたら読み込まれるようにするため。
  append: '.loaded-contents', //必須。これはloadNext.phpで出力するHTMLのクラス名。表示したいところにこのクラスを記述
  debug: true, //任意。
});
</script>
```

## PHP
次はphp
```loadNext.php
// DBとの接続
// PDO
$host = "hoge";
$db = "hoge";
$user = "hoge";
$password = "hoge";
try {
$pdo = new PDO("mysql:host=$host;dbname=$db", $user, $password);
} catch (PDOException $pe) {
  die("Could not connect to the database $db :" . $pe->getMessage());
}
// SQL
$sql =  "SELECT *
         FROM hoge_table
         LIMIT 10";
$stmt = $pdo->prepare("{$sql}");
$stmt->execute();
$response_array = $stmt->fetchAll(PDO::FETCH_ASSOC);

//表示
echo "<div class='loaded-contents'>";
foreach ($response_array as $each_response) {
  echo "<p>{$each_response}</p>";
}
echo "<div class='pagination__next'>
        <a href='loadNext.php?page=2'></a> //本来はこのpageの数値は適宜変える必要あり
      </div>";
echo "</div>";
```

## 注意点
- script部分のoptionsとHTMLやPHPでの対応を確認しないとミスる
- page=1とかの数値を動かしていく部分はこの記事では書いていないので適宜書いてください。PHPではpageパラメータの数値を受け取ってからDBから取得すればOK
- その他optionsはこちらを参照

https://infinite-scroll.com/options.html


感想。
使いづらい。ドキュメント適当すぎる。クラス名を変えないと意味不明。他にメンテナンスされている無限スクロール系のライブラリが無いから仕方なくこれを使った。
FreeBSD 13.1 + KDE Plasma　インストール手順(2023年)

#### そもそものきっかけ
twitter を眺めていたら、twm のスクリーンショット投稿を目にし、もう一度見たくなってしまったのがきっかけ

### FreeBSDのインストールイメージ
USBメモリーから起動したいので、下記名称のUSBメモリー起動用イメージをダウンロードしてWindows の rufus で書き込みして作成
FreeBSD-13.1-RELEASE-amd64-memstick.img

### コンソールモードのインストール
は、ものの5分もしないうちに完了してしまう。これはいつものこと。以下のパッケージを、pkg install コマンドでインストールする。
 doas: sudo の代わり、doas.conf は、permit :wheel の一行
 neofetch: お遊び
 lftp: 自宅ftpサーバーに接続するため。過去の設定ファイルをget するため
 nano: エディター
 xorg:　X Window System
 ja-font-mplus-ipa: xterm上の日本語表示
 sddm: Xディスプレイマネージャー
 nvidia-driver-470:　INTEL Core i5-10400 に内蔵の UHD graphics 630 では、ディスプレイ標準の解像度が得られず、古いグラフィックカード nVidia GT710 を代わりに使う。nvidia-driver の最新版は、510 という表示であったが、GT710 には既に対応しておらず、 470 を使ってくれというメッセージが出たので入れ替えた。
　firefox: ウェブブラウザー、twm上でも起動できる。上の日本語フォントを入れていないと文字化けする。
```
$ cat /usr/local/etc/X11/xorg.conf.d/driver-nvidia.conf
Section "Device"
　　　　        Identifier "NVIDIA Card"
        　　　　VendorName "NVIDIA Corporation"
        　　　　Driver     "nvidia"
EndSection
```

を記述する。
```
$ cat /etc/rc.conf
hostname="○○○○"
keymap="jp.kbd"
ifconfig_re0="DHCP"
sshd_enable="YES"
dumpdev="AUTO"
kld_list="nvidia.ko nvidia-modeset.ko"
linux_enable="YES"
dbus_enable="YES"
hald_enable="YES"
sddm_enable="YES" <--- plasma インストール後に追加する
```

### 次は、X　に何を入れるか?
pkg install コマンドで、
 kde5: plasma上のアプリ群です。
 plasma: ウィンドウマネージャー
 ja-fcitx5-anthy: 日本語入力変換
 fcitx5-configtool: 日本語入力の設定ツール
```
$ cat .xprofile
export LANG=ja_JP.UTF-8
export LC_ALL=ja_JP.UTF-8
export LC_CTYPE=ja_JP.UTF-8
export GTK_IM_MODULE=fcitx5
export QT_IM_MODULE=fcitx5
export XMODIFIERS=@im=fcitx5
export DefaultIMModule=fcitx5
```

#### そして、LibreOffice を入れよう
さあて、ここからがです。pkg群に libreoffice が、まだ含まれていませんでした。ということは、ports からのインストールになります。初期のインストールでは、portsコレクションをインストールしていませんでした。下記サイトを復習も兼ねて参考にさせていただきました。LibreOfficeのインストールには時間がかかりました。
![Libreoffice7.4.4.2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561584/69362983-8da6-1ace-a7a6-47f637995284.png)



https://kt-hiro.hatenablog.com/entry/20120811/1344677276


以上
【python】OpenAIのDALL-E 2を利用する

# TODO

Pythonにて

1. DALL-E 2を利用して画像を自動生成する
1. 作成した画像をローカルにダウンロードする
1. 複数の画像を作成＆ダウンロード

# Environmet

- MSYS2 MinGW x64
- Python 3.8.13 (Miniconda) >= 3.7.1

Pythonバージョンは3.7.1が必須
MSYS2 MinGWはWindowsでBash環境を整えるためのソフトウェア

# Using Library

- [openai](https://github.com/openai/openai-python) (Python >= 3.7.1)
- urllib

`pip install openai`
urllibはPythonに内蔵されているライブラリ

# 1. Write code creating a image with dall・E 2

```python
import openai
openai.api_key = 'Your API Key'
def generate_image_with_dalle2(prompt):
    # Official API Reference: https://beta.openai.com/docs/api-reference/images
    response = openai.Image.create(
        prompt=prompt,
        n=1,
        size='{}x{}'.format(str(256), str(256))
    )
    image_url = response['data'][0]['url']
    return image_url

image_url = generate_image_with_dalle2('a white cat')
print(image_url)
```

`openai.Image.create()`でDALL・E 2のAPIを利用して画像を生成する。`response`には画像URLがある。画像そのものはローカルには保存されないため注意。

パラメタについては下記の通り。

- prompt: 画像の説明文
- n: 生成する画像数
- size: 画像サイズ（256x256, 512x512, 1024x1024）

生成する画像数と画像サイズにより、AIモデル利用料が変化するので注意。

そのほか、`response_format`で`url`か`b64_json`で取得するか選択可能。

# 2. Download a image with urllib.request

```python
import openai
import urllib.request
openai.api_key = 'Your API Key'

def generate_image_with_dalle2(prompt):
    # Official API Reference: https://beta.openai.com/docs/api-reference/images
    response = openai.Image.create(
        prompt=prompt,
        n=1,
        size='{}x{}'.format(str(256), str(256))
    )
    image_url = response['data'][0]['url']
    return image_url

def download_dall2_image(image):
    with urllib.request.urlopen(image) as web_file:
        data = web_file.read()
        with open('./dall2.png', mode='wb') as local_file:
            local_file.write(data)

image = generate_image_with_dalle2('a white cat')
download_dall2_image(image)
```

DALL・E 2で作成した画像をローカルへDLするコード。`urllib`でWeb上の画像をopenできるので、openしたファイルをローカルファイルに書き込めばDLできる。

# 3. Create some images, and download.

```python
import openai
import urllib.request
openai.api_key = 'Your API Key'

def generate_image_with_dalle2(prompt, n, size):
    size = str(size)
    response = openai.Image.create(
        prompt=prompt,
        n=n,
        size='{}x{}'.format(size, size)
    )
    datas = response['data']
    images = []
    for data in datas:
        print(data['url'])
        images.append(data['url'])
    return images

def download_dall2_image(image, n):
    with urllib.request.urlopen(image) as web_file:
        data = web_file.read()
        with open('./dall2_{}.png'.format(n), mode='wb') as local_file:
            local_file.write(data)

images = generate_image_with_dalle2('a white cat', 3, 256)
i = 0
for image in images:
    download_dall2_image(image, i)
    i = i + 1
```

一回の実行で複数の画像を生成するコード。ベースは#2のコード。`generate_image_with_dalle2`で生成した画像URLの配列を返し、`download_dall2_image`で各画像URLをDLする。

以上。
WooCommerce で注文を検索する関数に項目を追加する方法

## WooCommerce の注文検索でのデフォルト仕様
![woocommerce_shop_order_search_fields.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106374/1f832587-289a-8676-ae64-430b2c0660eb.png)

注文を検索したい時に、WooCommerce 注文一覧からフリーワードで検索が出来るのですが、もちろん、全て情報から検索するわけではなく、特定の部分からキーワード検索するようになっています。まずは、そのデフォルトの仕様を確認するために、そこで使われている関数を知る必要があります。
その関数は [search_orders](https://woocommerce.github.io/code-reference/classes/WC-Order-Data-Store-CPT.html#method_search_orders) です。
この関数を読んでいけば分かるのですが、検索対象となっている項目は以下です。

* _billing_address_index(注文者住所)
* _shipping_address_index(発送先住所)
* _billing_last_name(注文者の姓)
* _billing_email(注文者のメールアドレス)

あと、数字のみの場合は注文 ID で検索が可能です。

もちろん、**部分検索に対応**しているので郵便番号などで検索する事も可能です。
ただ、一致しないといけないので、その点は注意が必要です。例えば、郵便番号で検索したくて、「123-4567」で検索したとしても、登録が「1234567(ハイフンなし)」だった場合は検索結果に出てきません。
ちなみに住所情報には注文者と発送者の姓名が入っているので、姓名で検索することは可能ですが、半角スペースで区切られているので片方だけでの絞り込みとなります。

## 検索項目を追加するフィルター

今回利用するフィルターは [woocommerce_shop_order_search_fields](https://woocommerce.github.io/code-reference/files/woocommerce-includes-data-stores-class-wc-order-data-store-cpt.html#source-view.527) です。
先に説明した４項目が登録されています。

基本的に検索項目は注文メタデータとなります。なので、カスタマイズをゴリゴリにして検索対応を広げる場合にはまず検索する対象の情報を注文メタの中に入れ込まないといけません。これは別途注文作成時などのフックを利用して登録するようにしてください。

**ここまで書いて今気がついたのですが、この関数、現時点で [HPOS](https://woocommerce.com/document/high-performance-order-storage/) に対応していないですね。。。**
なので、将来的に修正が必要かもです。

例えば、「注文の合計金額」と「注文者の電話番号」でも検索をできるようにしたい場合は以下のように対応します。
```php
add_filter( 'woocommerce_shop_order_search_fields', 'add_search_fields' );
function add_search_fields( $search_fields ){
	$search_fields[] = '_order_total';
	$search_fields[] = '_billing_phone';
	return $search_fields;
}
```

## REST API にも対応

ちなみに REST API の [List all orders](https://woocommerce.github.io/woocommerce-rest-api-docs/#list-all-orders) のフリーワード検索にも対応しています。
多分、こちらの開発をしていると外部から登録されている注文データの検索をしたい場合などに非常に使えるのではないかなと思っています。ちなみに私もこれでよく使っています。
Linuxのショートカットコマンド（エイリアス）を設定するショートリファレンス

## はじめに
たとえばシェルからSSHをする場合、
```
ssh -l pythonista 192.168.0.18
```
のような感じで入力すると思いますし、よく使うファイルを毎回こんな感じで
```
source env/bin/activate
cd files
python3 batch.py
```
みたいな感じで毎回毎行入力していたら面倒も面倒ですよね。

ただ矢印キーやctrl+p,nを押すと「以前入力したコマンド」が順番に出てくるので、それに頼っている場合も多いハズ。
そんななかで、複数行の命令も一発で実行できるような、独自のショートカットコマンドがあれば楽だなあ、と感じませんか。

そこでいろいろ調べると、Linuxの場合それはエイリアスという形で実現しているようです。
Linuxの入門書は通読しましたが、Linuxを実践（簡易サーバー化）するまでラグがあって、仮にエイリアスの項目は見ていたとしてもすっかり忘れていたか、そもそも概念として「使う」→「なんとなく把握する」→「疑問」というステップを踏まなければわからないような内容だったので、無意識的にスルーしていたのかもしれません。

いずれにしましても、コマンドのショートカットはエイリアスといい、数行まとめた形でも順番に、あるいは&&などの論理実行も可能ですと。

そもそも[ls]や[cd]もエイリアスだったんですね。そういうショートカットコマンドというか。

以下、そのエイリアスを設定するためのショートリファレンスです。

## 1. まず自分のログインシェルを知る
```
grep $USER /etc/passwd | cut -d: -f7
```
これで、bashかzshかわかります。なんなら先頭が$か%かでもわかるっぽいですが。

そして、bashの場合。

## 2. bashrcは登録ファイル
```
nano ~/.bashrc
```
viでもいいですがnano派なので。
.bashrcの下の方とか一番下に記述。
```
alias ●●='XXX'
```
●が好きなショートカット名、XXXがコマンド。パイプも&&も有効。
パイプ（|）は出力を受け渡しつつ次のコマンドを実行、&&は論理積実行。論理積実行とかいうと難しく感じるが、単にコマンドが無事実行できたら次のコマンドを実行するというだけ。実行結果がどうであれ実行してくれるやつもあります。普通は&&でよかろうと思います。

## 3. エイリアス登録しただけではだめ
```
nano ~/.bash_profile
```
でbashのプロファイルを開いて、
```
source ~/.bashrc
```
これを貼り付けてrcをプロファイルに登録。これでもまだだめ。

## 4. プロファイルを書いただけや更新しただけではすぐに実行はしてくれない
システム再起動すればOKらしいですが、面倒です。
```
source ~/.bash_profile
```
ターミナルでこれを打ち込めば、即座にプロファイルが反映されて、晴れてすぐにエイリアスが使えるようになります。

## おわりに
いくらでも出てくる情報とはいえ、「エイリアス」というキーワードを知らずに手持ちのキーワードで調べる人がたどり着きやすいように作った感じです。ここで得たキーワードをもとにクモの巣状に知識を広げて補完していくことに役立てれば幸いです。
AWS初心者向けサイト

# AWS初心者向けサイト

AWS Builders Online Series
T5-4: 目的別！アプリ開発者が AWS を使いこなすための最初の学習ロードマップ！
で紹介があった公式サイトのうち、「最初に学ぶ」にフィーチャーしたサイト３つのリンクメモ。

## AWS 初心者向け資料
まずはドキュメントや動画
https://aws.amazon.com/jp/events/aws-event-resource/beginner/

## AWSハンズオン資料
とりあえず触ってみたい場合
https://aws.amazon.com/jp/events/aws-event-resource/hands-on/

## AWS デベロッパーセンター
アーキテクチャや言語別についての情報
https://aws.amazon.com/jp/developer/

## AWS Builders Online Series
https://aws.amazon.com/jp/events/builders-online-series/
【Go】古い記法で書いたbuild constraintsは後方互換するのか調べてみた

# はじめに
build constraintsのための記法は、ver1.17以上で新しい書き方になっていたことを最近知りました。

https://go.dev/doc/go1.17#gofmt

古い記法
```go
// +build ignore
```

現在の記法
```go
//go:build ignore
```

そこでふと「Goは後方互換が保たれた言語だけど、ビルドタグも同様に後方互換されるんだろうか？」という疑問が浮かびました。
今回は、build constraintsの後方互換（？）について調べてみた内容を書いてみます。

# 調べた結果
`go fmt`コマンドを使えば、ver1.16以下で使用されていた古い表現を検知して、自動的に現行の表現を追加してくれるみたいです。

>Go versions 1.16 and earlier used a different syntax for build constraints, with a "// +build" prefix. The gofmt command will add an equivalent //go:build constraint when encountering the older syntax.

# 実際に動作を確認してみた
私の環境は以下になります。
```shell-session
$ go version
go version go1.18 darwin/arm64
```

今回は以下のソースコードを実行してみたいと思います。
```go:main.go
package main

import (
	"fmt"

	"github.com/be3751/old_bc/sub"
)

func main() {
	fmt.Println("Hello, World!")
	sub.Sub()
}
```
```go:sub.go
// +build ignore

package sub

import "fmt"

func Sub() {
	fmt.Println("sub")
}

```

実行結果は以下の通りでした。
go run, go build で共通して、sub.goがビルド対象から除外されていることが分かります。
また、現行の記法を用いてbuild constraintsを設定した場合においても、同様の出力となります。
```shell-session
$ go run main.go
package command-line-arguments
        imports github.com/be3751/old_bc/sub: build constraints exclude all Go files in /Users/be3751/Desktop/old_bc/sub
```

```shell-session
$ go build main.go
package command-line-arguments
        imports github.com/be3751/old_bc/sub: build constraints exclude all Go files in /Users/be3751/Desktop/old_bc/sub
```

余談ですが、GoogleのGoチームが提供しているVSCode 拡張機能を入れていると、go fmtが自動的に作用するので、古い記法を使用しても保存時に自動で現行の記法を追記してくれます。

https://marketplace.visualstudio.com/items?itemName=golang.Go


# 結論
- 古い記法で書いたbuild constraintsも機能する
- go fmtは現行の記法を追記してくれるだけ

# 参考
Build constraintsという節に引用した文の記載があります。

https://pkg.go.dev/cmd/go#hdr-Build_constraints
TypeScriptの型

TypeScriptを学び始めたので備忘録として残します。

# TypeScriptの基本的な型
|型  |例  |説明  |
|---|---|---|
|`number`  |`1`,`5.3`,`-10`  |整数や浮動小数点を含む全ての数値  |
|`string`  |`'Hi'`,`"Hi"` |全ての文字列  |
|`boolean`  |`true`,`false`  |trueまたはfalse  |
|`object`  |`{age: 30}`  |JavaScriptの全てのobject <br> objectの型よりも明確に定義することが可能  |
|`Array`  |`[1, 2, 3]`  |JavaScriptの全てのArray <br> 要素の型は、柔軟にも厳格にも指定できる  |
|`Tuple`  |`[1, 2]`  |**TypeScript独自の型: 長さ固定の配列**  |
|`Enum`  |`enum { NEW, OLD }`  |**TypeScript独自の型: 列挙型** |
|`Any`  |`*`  |どんな値を入れてもいい、型を指定しない|
Rock64ハンドブック

# Rock64ハンドブック

### rock64とは

[ROCK64-2GB Single Board Computer - PINE STORE](https://pine64.com/product/rock64-2gb-single-board-computer/)

ラズパイサイズのSBC \
Rockchip RK3328 1.5GHz搭載 \
1GB/2GB/4GB版がある \
自分のは以前秋月で売っていた1GB版 \
 \
なおwifiはついておらずネットワーク接続はLAN又はusbトングを用いる

質問スレ

[【PINE64】パイン64 part2【ROCK64】](https://mao.5ch.net/test/read.cgi/linux/1513583078)

電源が特殊でDC jackがtype H 3.5mm/1.35mm となっている \
テスターでDC jackのGND,5Vを調べて無理やり半田付けした \
usbへの接続はusbケーブルを分解したものを使った \
この方法では電力不足を気にしなくてよいので気に入った \

秋月ではGPIOピンを使った専用のアダプタがあったらしい \
あるいはamazonでCamon 3.5 mm(3.4 mm) 1.3mm <-> usbのケーブルが売っているのでそれを買う(400円くらい)
 \
なおGPIOはラズパイ互換である
 \
起動するとledがピカピカするのですぐに分かるだろう

http://akizukidenshi.com/download/ds/akizuki/Rock64_power_supp_20170919.pdf

[mieki256's diary - DCプラグを探していたり](http://blawat2015.no-ip.com/~mieki256/diary/201710021.html)

### armbian

[Rock64 – Armbian](https://www.armbian.com/rock64/)

armbianをダウンロードして以下でsdに書き込み

```sh
xz -dc -T0 ~/Downloads/Armbian_22.11.1_Rock64_jammy_current_5.15.80.img.xz | dd of=/dev/mmcblk0 status=progress bs=1M
```

wifiがついていないので WDC-150SU2MBK [無線LAN子機 11n/g/b 150Mbps USB2.0用 ブラック] を買った(1000円くらい 安い)
 \
起動してarmbianの設定をしたら

[lwfinger/rtl8188eu: Repository for stand-alone RTL8188EU driver.](https://github.com/lwfinger/rtl8188eu)

以上をあらかじめ他のPCでcloneしておいてsdのホームディレクトリに書き込む \
そして以下を実行

```sh
make
sudo make install
```

これでwifiトングが使える用になる \
電力を食うらしくusb3.0の方に接続した
 \
正しく接続されていれば

```sh
nmcli device show
```

で見えるはず \
そうしたら

```sh
nmcli device wifi connect *SSID* password *pass*
```

で接続する

[linuxbeanにWDC-150SU2MBKを取り付けと設定: PCでハイレゾ音楽](https://birochan-metal.cocolog-nifty.com/blog/2016/08/dellmini9elecom.html)

[Linux 5.15 Staging Replaces Its Realtek RTL8188EU WiFi Driver - Phoronix](https://www.phoronix.com/news/Linux-5.15-Staging)

### arch

[Rock64 | Arch Linux ARM](https://archlinuxarm.org/platforms/armv8/rockchip/rock64)

以上を参考に rksd_loader.img と u-boot.itb 、パーティションを書き込む \
内部は以下の様になっている
 \
Hint:
0x40=64
0x4000=16384
16384\*512=8MiB
0x8000=32768
32768\*512=16MiB

[Boot option - Rockchip open source Document](https://opensource.rock-chips.com/wiki_Boot_option)

以下のarmv8(arm64)である

[Downloads | Arch Linux ARM](https://archlinuxarm.org/about/downloads)

### 補記

少し古いがメモリの周波数を下げて安定性を上げる

[ayufan-rock64/rkbin: Firmware and Tool Binarys](https://github.com/ayufan-rock64/rkbin)

[rock64, compile problems "illegal instruction", "memory fault" -> ddr_333Mhz?](https://forum.pine64.org/showthread.php?tid=7387)
[備忘録][TypeScript] ランダム文字列をちょっと生成したい時には

# おことわり

ちょっとほしいな、くらいな気持ちの時にしか使わない前提です。
絶対に競合を避けたいのであれば、UUIDなどを使用してください。

# コード

```ts
const generateRandomString = (charCount = 7): string => {
  const str = Math.random().toString(36).substring(2).slice(-charCount)
  return str.length < charCount ? str + 'a'.repeat(charCount - str.length) : str
}
```

## 説明

`Math.random().toString(36).substring(2)`で生成した文字列が、引数`charCount`で指定した文字数を満たさない場合`a`で埋める。e.g. `u9bw7nr2a3caaaa`

## 実行例

`// {文字数} {生成された文字列}`

```ts
generateRandomString()
// 7 u85f9kc

generateRandomString(0)
// 11 3a2sgdmamx2 
// Math.random().toString(36).substring(2)が生成した文字列が返される

generateRandomString(1)
// 1 e

generateRandomString(20)
// 20 kq32frq5uslaaaaaaaaa
```

# ランダム部分は何文字になる？

`Math.random().toString(36).substring(2)`部分が生成する文字数をカウントするためのコードを用意。
100万回実行して、文字数の分布を調べる。

```ts
const obj: Record<string, number> = {}

for (let i = 0; i < 1_000_000; i++) {
  const rs = Math.random().toString(36).substring(2).length
  if (typeof obj[rs] === 'number') {
    obj[rs] += 1
  } else {
    obj[rs] = 1
  }
}

console.log(obj)
```

結果は以下の通り

```json
{
  "7": 6,
  "8": 193,
  "9": 7288,
  "10": 263166,
  "11": 704859,
  "12": 23804,
  "13": 668,
  "14": 14,
  "15": 2
} 
```

`a`が連続した文字列を絶対に避けたい場合、統計上、7文字を指定するのがbetter
【忘備録】期間内に特定のカラムが複数回登録されているレコードを抽出する(SQL、Rails、Pandas)

簡単だろうと勝手にたかを括っていたら時間が掛かってしまったため、
忘備録としてメモ。

Booksテーブルから次の条件を満たしたレコードを抽出するSQL文を作成する。

・2022年中に3回以上同じcategoryが登録されているbookレコード

（Booksテーブル）

存在するカラム：category,tag1,tag2,created_at,updated_at

created_atが2022年内なら登録されているとする。

## SQL

```sql:books.sql
SELECT * 
FROM books
WHERE category in (
SELECT category
FROM books
WHERE created_at BETWEEN '2022-01-01 00:00:00' AND '2022-12-31 23:59:59'
GROUP by category
HAVING count(category) >= 3
);

```

## Rails
目的は達成したが、気になったのでついでに考えてみる。

```ruby:books.rb
category_list = Book.where(created_at: '2022-01-01 00:00:00'..'2022-12-31 23:59:59')
                    .group(:category)
                    .having("count(category) >= ?", 3)
                    .pluck(:category)

Book.where(category: category_list)
```

## Pandas
Pandasだとこうなる。
dfはBookテーブルをデータテーブルにしたもの。

```python:books.py
period = df[(df['created_at'] >= "2022-01-01 00:00:00") & (df['created_at']<= '2022-12-31 23:59:59')]

category_list = period.groupby("category")["category"].filter(lambda x: len(x) >= 3)

df[df['category'].isin(category_list)]
```
【python,pytorch】表形式データをpytorchでテンソルにする

後で自分が振り返る用の記事。表形式データをテンソルに変換し、NNで訓練できる形にすることが目標。

import
-
```python
import numpy as np
import pandas as pd
import torch
torch.set_printoptions(edgeitems=2, threshold=50)
```

表形式データの準備
-
```python
a = np.arange(1,10)
b = np.arange(11,20)
c = np.arange(21,30)
d = np.arange(1,10)
target = np.random.rand(9)
target = [round(x) for x in target]

d = d.astype('str')
d[:4] = 'a'
d[4:] = 'b'

data = pd.DataFrame([a,b,c,d,target]).T
data.columns = ['A','B','C','D','target']

data
```
出力結果

||A|B|C|D|target|
|-|-|-|-|-|-|
|0|	1|	11|	21|	a|	1
|1|	2|	12|	22|	a|	0
|2|	3|	13|	23|	a|	0
|3|	4|	14|	24|	a|	0
|4|	5|	15|	25|	b|	1
|5|	6|	16|	26|	b|	0
|6|	7|	17|	27|	b|	0
|7|	8|	18|	28|	b|	0
|8|	9|	19|	29|	b|	0

one-hot-encoding
-
テンソルは数値型しか受け付けないのでDカラムを数値に変換する
```python
data.D = pd.get_dummies(data.D, drop_first=True)
```

データ型を変更
-
データの型を整えないと後ほど、エラーが出る。
```python
data[['A','B','C','target']] = data[['A','B','C','target']].astype('float32')
```

```python:エラー内容
# can't convert np.ndarray of type numpy.object_. The only supported types are: float64, float32, float16, complex64, complex128, int64, int32, int16, int8, uint8, and bool.
```

テンソルに変換する２つの方法
-

numpy配列からテンソルを作る方法
```python
# numpyからテンソルを作る方法
torch.from_numpy(data.to_numpy())
```
データフレームからテンソルを作る方法
```python
test_tensor = torch.tensor(data.values)
test_tensor.shape, test_tensor.dtype
```

目的変数と説明変数を切り分け
-
今回は２次元テンソルなので、場所を特定するには２つの値の指定が必要。
```python
# 説明変数
train = test_tensor[:,:-1]
print(train, train.shape)
# 目的変数
target_tensor = test_tensor[:,-1]
print(target_tensor, target_tensor.shape)
```

目的変数を整形
-

```python
# 目的変数をint型に変換
target_tensor = target_tensor.long()
target_tensor.shape
# サイズを出力用の形に整える
target_tensor_unsq = target_tensor.unsqueeze(1)
target_tensor_unsq.shape
# 出力結果　torch.Size([9, 1])
```

説明変数を標準化
-
```python
# trainの標準化
train_mean = torch.mean(train)
train_sd = torch.std(train)
train_n = (train - train_mean)/train_sd
train_n
```
UnityにMixamoのキャラクターを使用し、色（テクスチャ）付けする方法

[mixamo]: http://qiita.com/
# 概要
Unityでゲームを作るとき、キャラクターは既存のものを使いたいときがあると思います。
その際、[Mixamo][mixamo]からキャラクターをダウンロードし、そのまま使用すると色が真っ白になってしまうことがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274752/18975221-0fa1-b3ee-7a76-8bfee4b8b4bf.png)

そのため、Mixamo画面上のように、色がついた状態にする方法を紹介します。
イメージはこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274752/6ba89296-138f-9e23-b4b5-cb8c019a1dfe.png)

# Mixamoからダウンロード・インポート
## ダウンロード
画像のように、キャラクターを選んだあと、ダウンロードします。
![コメント 2023-01-21 110215.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274752/58456a26-dda8-3a33-35cb-3aaf7531dabc.png)

## インポート
ダウンロードしたFBXファイルを**UnityのProject>Assets**にドラッグ＆ドロップします。

:::note warn
この時点では、まだ画面に表示されません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274752/b2861396-58c2-7fd2-914a-3cb756045245.png)
:::


# 色（テクスチャ）を付けて、画面に表示
## 色データの出力
Project>Assetsにインポートしたキャラクターをクリックし、Inspectorを開き、InspectorのMaterailsタブを開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274752/e565f26f-6322-a775-86f0-75a7dc93255d.png)

そして、Extract　Texturesを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274752/57d96621-e028-5b0b-7316-5a6b6e6e9295.png)

ポップアップで表示された画面で、フォルダー選択ボタンをクリックします。

:::note warn
**最初に選択されているフォルダで基本的に問題ないです**が、変更したい場合は適切なフォルダを選択してからフォルダー選択ボタンをクリックしてください。
また、**色データ（テクスチャ）は後で移動できます。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274752/0766bffa-9a35-636a-863e-065f895b3eed.png)
:::

Project>Assetsのキャラクターに色がつき、色データ（テクスチャ）が表示されたことを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274752/6138e0ae-7f8b-346e-80d8-13e9669a9080.png)

## 画面表示
最後に画面に表示するためにHierarchyにドラッグ＆ドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274752/01bb954d-ab9a-153e-0096-f8c948551f23.png)
CloudBuildからCloudRunデプロイ時に出た権限エラーと解決策

# 背景

GitHub Actionsを使いCloudBuild経由でCloudRunへ継続的デプロイさせようとした時に、想定外の権限エラーが出てつまづいたので、同じことに遭遇した人の助けになればと思い書きました。

# エラー内容

デプロイステップで下記のエラーが出た。（CloudLoggingから抜粋）

```
ERROR: (gcloud.run.deploy) PERMISSION_DENIED: Permission 'iam.serviceaccounts.actAs' 
denied on service account {CloudRunサービスアカウント名}@{GCPプロジェクト名}.iam.gserviceaccount.com
```

一見すると、CloudRunのサービスアカウントに`iam.serviceaccounts.actAs`の権限が足りていないように見えたので、この権限が含まれているサービスアカウントユーザー（`roles/iam.serviceAccountUser`）　ロールを追加してみたが、再度デプロイしてもエラー。。

# 解決策

**CloudRunのサービスアカウント自体に権限が足りていないのではなく、CloudRunサービスアカウントをCloudBuildが借用する権限が無いのが原因だった。**

- 誤：CloudRunサービスアカウントに`roles/iam.serviceAccountUser`を追加
- 正：**CloudRunサービスアカウントへのアクセス権限**に`roles/iam.serviceAccountUser`ロールでCloudBuildプリンシパルを追加

ドキュメントでは、下記のように書かれている

> Cloud Run にデプロイするには、Cloud Run 管理者とサービス アカウント ユーザーのロールを Cloud Build サービス アカウントに付与します。

https://cloud.google.com/build/docs/deploying-builds/deploy-cloud-run?hl=ja#required_iam_permissions

# 権限付与の手順

### GCPコンソール画面からの場合
この権限を付与する場合であれば、下記ドキュメントに沿って簡単に設定可能。

https://cloud.google.com/build/docs/deploying-builds/deploy-cloud-run?hl=ja#continuous-iam

### terraformからの場合

下記でOK

```tf
resource "google_service_account" "cloud_run_sa" {
  project      = var.project-name
  account_id   = "sample-sa"
  display_name = "sample-sa"
  description  = "CloudRunに紐づけるサービスアカウント"
}

# CloudBuild が Cloud Runサービスアカウントの権限借用するのを許可する設定
resource "google_service_account_iam_member" "by_cloudbuild" {
  service_account_id = google_service_account.cloud_run_sa.name
  role               = "roles/iam.serviceAccountUser"
  member             = "serviceAccount:${var.project-number}@cloudbuild.gserviceaccount.com"
}
```

しかしながら、「これをapplyするとCloudRunサービスアカウントへの既存のアクセス権限が失われるんじゃないか」と思い、検証してみましたが、apply後も既存は削除されずcloudbuild分だけ追加されるだけでした。
よかったよかった

（下記どうしてもマスクだらけになり、すみません）

- apply前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577028/c267d2f7-ab63-65e4-d6c9-9595320b3e13.png)

- apply後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577028/be160fe8-6373-4678-adcb-eb38443ebd32.png)




# 参考
- [（ドキュメント）GCP IAMロール一覧](https://cloud.google.com/iam/docs/understanding-roles?hl=ja#iam.serviceAccountUser)
- [（ドキュメント）Cloud Build を使用した Cloud Run へのデプロイ - 最小限の IAM 権限の使用](https://cloud.google.com/build/docs/deploying-builds/deploy-cloud-run?hl=ja#continuous-iam)
- [新しい権限で Cloud Build から Cloud Run へデプロイする](https://scrapbox.io/pokutuna/%E6%96%B0%E3%81%97%E3%81%84%E6%A8%A9%E9%99%90%E3%81%A7_Cloud_Build_%E3%81%8B%E3%82%89_Cloud_Run_%E3%81%B8%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B)
【Hugo】wowchemyテーマで静的サイトを生成する際 fatal: 'origin' does not appear to be a git repository... が発生した時の対応

静的サイトジェネレータ Hugo でハマった問題に対応した内容の忘備録です。

## 環境
- MacOS Ventura
- Hugo (Theme: wowchemy)


## 問題
初めてHugoを導入しようと頑張って作成したサイトをいざ生成しようと、`hugo` コマンドを実行すると、下記のエラーが発生。リポジトリが読めないとのことなので、URLが変わったのかと思いましたがそんなことはなく。。
ちなみに昨日までは問題なく動作していました。まさに「なにもしてないのに壊れました」っていうアレです。

```
go: github.com/wowchemy/wowchemy-hugo-themes/modules/wowchemy/v5@v5.7.1-0.20221127215619-58b270a3e103: invalid version: git ls-remote -q origin in /var/folders/pd/jt86y4cj2kbdw_k5rwjjt_dr0000gn/T/hugo_cache/modules/filecache/modules/pkg/mod/cache/vcs/0c88995f39c54fe356dd74460b6359b56b0fb376c52289c9656c86270b2c006d: exit status 128:
	fatal: 'origin' does not appear to be a git repository
	fatal: Could not read from remote repository.
	
	Please make sure you have the correct access rights
	and the repository exists.
 *errors.errorString
```

## 原因
Hugoのキャッシュが悪さをしていたようでした。

## 解決策
なんとも基本的な解決策ですが、Hugoのキャッシュを削除すると直りました..。

下記のHugoのキャッシュディレクトリの中身を削除します。
`$TMPDIR/hugo_cache/`

(ここまでにGoやHugoをバージョンを変えながら入れ直したり、かなり時間を溶かしてしまった・・・)


## 参考
wowchemy公式のテトラブルシューティングが参考になりました
https://wowchemy.com/docs/hugo-tutorials/troubleshooting/
Nuxt3 / Vue – datalistで選んだ項目を元に 外部APIにfetchリクエストする例 ( @change イベントを検知する )

# 例

`example.vue`

```vue
<template>
  <div class="main">
    <h1>Todo</h1>
    <div>
      <input v-model="text" list="item" @change="selectTodo(text)" />
      <datalist id="item">
        <div v-for="todo in todoList" :key="todo.value">
          <option :value="todo.value">{{ todo.name }}</option>
        </div>

      </datalist>
    </div>
    <h2>Todo</h2>
    {{ todoItem.title }}
  </div>
</template>
<script>

export default {
  data() {
    return {
      todoList: [{ name: "TODO1", value: 1 }, { name: "TODO2", value: 2 }, { name: "TODO3", value: 3 }],
      todoItem: {}
    }
  },

  methods: {
    async selectTodo(selectedTodo) {
      console.log(selectedTodo);
      const data = await fetch(`https://jsonplaceholder.typicode.com/todos/${selectedTodo}`)
      const json = await data.json()
      this.todoItem = json
    },
  },
}
</script>
```

# 動作例
![image](https://user-images.githubusercontent.com/13635059/213841489-0b3cca07-0a76-4d45-8e5b-6fbd9835ef33.png)
![image](https://user-images.githubusercontent.com/13635059/213841491-a6e49e47-26f7-43e7-9276-ca31a49b6977.png)



# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
【C#】こんなコメントアウトの使い方あるんだ...って思ったやつ【小技？】

# 結論

### コメントアウトでif文の行を消すだけで中括弧({})は消さなくてもビルドできるみたいです。(知らなかった)

~~~c#

using System;

namespace QiitaCommentOut
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var flg = false;

            //if (flg)
            {
                Console.WriteLine("IF文の中です。");
            }

            Console.WriteLine("IF文の外です。");
            
            Console.Read();
            //出力：
            //IF文の中です。
            //IF文の外です。
        }
    }
}

~~~

# 環境

IDE
→VisualStudio 2022

フレームワーク
→.Net FrameWork4.7.2

プロジェクト
→コマンドライン

# 感想
いままでif文をコメントアウトするときは中括弧まで削除していましたが、中括弧は無視されるみたいなのでif文だけをコメントアウトするだけで問題なくビルドできるみたいです。ただ、インデントが深くなってしまうので私は中括弧もコメントアウトしますかね～。そもそも、バージョン管理しているソースであればコメントアウトせずに行自体を削除しますね。

# 小ネタ

ということで中括弧は無視されるのでこんなコードを書くこともできますね！

![qiita.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/ce4d1d25-43a3-4cad-7186-d662a47bfac9.png)

# 追記

@albireo さんからコメントにて教えていただきました。

>正確には「無視される」わけではなく「if (true){ ... }と同じ条件なしのコードブロック」という扱いになります。
何が違うのかというと、ローカル変数のスコープの違いですね。

常に実行される`if(true){ ... }`と同じ扱いのようです。念のため、内部実装がどうなっているのか調べたのですが、調べ方がよくないのか見つかりませんでした。ただ、私も`if(true){ ... }`と同じ扱いと考えて問題ないと思います。@albireoさんの引用の通り一番の違いは変数のスコープです。

```c#

using System;

namespace QiitaCommentOut
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            //変数名が同じでも中括弧のお陰でエラーにならない！
            {
                var scope = "first scope";
                Console.WriteLine(scope);
            }

            {
                var scope = "second scope";
                Console.WriteLine(scope);
            }

            Console.Read();
        }
    }
}

```

>「ひとつのメソッド内によく似た処理が繰り返し出てくるとき、コピペしてもローカル変数名が衝突しない」なんて使い方もしますが、これが重要になるのはラムダ式を使う時でしょうね。
クロージャに取り込む変数を選ぶのに使ったりします。

`ひとつのメソッド内によく似た処理が繰り返し出てくるとき、コピペしてもローカル変数名が衝突しない」なんて使い方もしますが、これが重要になるのはラムダ式を使う時でしょうね。`の部分に関して私の中では下記ソースと捉えています。

```c#

using System;

namespace QiitaCommentOut
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            //内容がほぼ同じラムダ式をコピペしても変数名ダブりエラーが発生しない！
            Action action1 = () =>
            {
                var scope = "first scope";
                Console.WriteLine(scope);
            };

            Action action2 = () =>
            {
                var scope = "second scope";
                Console.WriteLine(scope);
            };

            Console.Read();
        }
    }
}

```

`クロージャに取り込む変数を選ぶのに使ったりします。`の`クロージャ`に関しては初めて聞く単語で調べたのですが`取り込む変数を選ぶ`という部分は分かりませんでした。クロージャを使用したソース例は下記と考えます。

```c#

using System;

namespace QiitaCommentOut
{
    internal class Program
    {
        private static Func<int, int> Sum(int n)
        {
            return x => n + x;
        }

        private static void Main(string[] args)
        {
            var sum10 = Sum(10);

            var sum20 = Sum(20);

            Console.WriteLine($"{sum10(100)}");

            Console.WriteLine($"{sum20(200)}");

            Console.Read();
        }
    }
}

```
「暗号技術入門　秘密の国のアリス」のまとめ2




# 学習内容


## メッセージ認証コード

メッセージ認証コードとは、なりすましと改竄を検出するための技術です。








### 手順

step1. 事前に受信者ボブと送信者アリスで秘密鍵を共有しておきます。鍵の共有方法に関しては、別の記事で解説してます。

step2. アリスは送信したいメッセージと鍵をハッシュ関数の入力としてMAC値という値を計算します。

step3. アリスはボブに送りたいメッセージとMAC値の両方を送信します。

step4. ボブは受信したメッセージと事前に共有した鍵をハッシュ関数の入力としてMAC値を計算します。

step5. ボブはアリスから送られたMAC値と自身が計算したMAC値を比較します。

step6. MAC値が一致すれば認証成功、そうでなければ認証失敗となります。






### 疑問点


自分が学んだ際に疑問に思ったことと回答をまとめます。


Q1. そもそもメッセージ自体を共通鍵暗号を利用して暗号化すれば良いのでは？秘密鍵を共有していない第三者がなりすまし、改竄した場合には、正当な受信者（ボブ）がメッセージを復号してもランダムなビット列となり、すぐに気づくのでは？



A1. アリスからランダムなビット列が送られてきたのか、なりすましや改竄された結果ランダムなビット列が送られてきたのかを判断できないから。




Q2. メッセージだけでなくMAC値も改ざんされた場合には意味がないのでは？



A2. 考えればすぐ分かることですが、送信者アリスと受信者ボブが共有している鍵を攻撃者は知りません。そのため、ボブがメッセージと共有鍵から算出するMAC値を攻撃者は知らないので、MAC値をどのような値に書き換えればよいのかを知ることができません。



## メッセージ認証に対する攻撃



簡単にどんな攻撃が可能なのかを紹介します。

### リプレイ攻撃

攻撃者はアリスとボブの通信を盗聴しておき、送信されたメッセージとMAC値を自分のPCに保存しておきます。この保存したメッセージとMAC値のペアを利用することで、認証を突破します。


対策としてはシーケンス番号、ノンス、タイムスタンプの利用などがあります。






# まとめ

メッセージ認証コードで解決できない問題として否認防止があります。これに関しては別の記事でまとめます。
正規表現に使うメタ文字

# 目的
メールアドレスの正規表現を理解できるようになる。
時間の無駄かもしれなけど
一応勉強しておく。

### ```/d```
「```1個の半角数字（0123456789）```」を意味するメタ文字

# 出典
https://qiita.com/jnchito/items/893c887fbf19e17d3ff9#:~:text=%5Cd%20%E3%81%AF%E3%80%8C1%E5%80%8B%E3%81%AE%E5%8D%8A%E8%A7%92%E6%95%B0%E5%AD%97%EF%BC%880123456789%EF%BC%89%E3%80%8D%E3%82%92%E6%84%8F%E5%91%B3%E3%81%99%E3%82%8B%E3%83%A1%E3%82%BF%E6%96%87%E5%AD%97

### ```{n,m}```、```{n}```
```文字の個数を限定```するときは {n,m} や {n} というメタ文字を使います（文字量を指定するので、特に 「量指定子」 と呼ばれます）。

{n,m} は「```直前の文字が n 個以上、m 個以下```」の意味です。
また、 {n} とすれば「```ちょうど n 文字```」の意味になります

# 出典
https://qiita.com/jnchito/items/893c887fbf19e17d3ff9#:~:text=%E3%80%8C%E5%8D%8A%E8%A7%92%E6%95%B0%E5%AD%97%E3%81%8C2%E5%80%8B%EF%BD%9E5%E5%80%8B,n%20%E6%96%87%E5%AD%97%E3%80%8D%E3%81%AE%E6%84%8F%E5%91%B3%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82

### パターンを見つけ出す
```正規表現を使うときは、最初に検索対象文字列の 「法則（パターン）」 をうまく見つけだすのが大切```です。

### 出典
https://qiita.com/jnchito/items/893c887fbf19e17d3ff9#:~:text=%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E3%82%92%E4%BD%BF%E3%81%86%E3%81%A8%E3%81%8D%E3%81%AF%E3%80%81%E6%9C%80%E5%88%9D%E3%81%AB%E6%A4%9C%E7%B4%A2%E5%AF%BE%E8%B1%A1%E6%96%87%E5%AD%97%E5%88%97%E3%81%AE%20%E3%80%8C%E6%B3%95%E5%89%87%EF%BC%88%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%EF%BC%89%E3%80%8D%20%E3%82%92%E3%81%86%E3%81%BE%E3%81%8F%E8%A6%8B%E3%81%A4%E3%81%91%E3%81%A0%E3%81%99%E3%81%AE%E3%81%8C%E5%A4%A7%E5%88%87%E3%81%A7%E3%81%99%E3%80%82

### 気づき
-(ハイフン)や()（カッコ）も加えてパターンを検索できるのか。

### []
```「AまたはBのいずれか1文字」```表す場合は```[AB]```と書きます（文字の集合を表すので、これも 文字クラス の一種です）。
[ ]の中の```文字数に制限はありません```。
```[ABC]```と書けば、```「AまたはBまたはCのいずれか1文字」```の意味になります。

### 出典
https://qiita.com/jnchito/items/893c887fbf19e17d3ff9#:~:text=%E3%80%8CA%E3%81%BE%E3%81%9F%E3%81%AFB%E3%81%AE%E3%81%84%E3%81%9A%E3%82%8C%E3%81%8B1%E6%96%87%E5%AD%97%E3%80%8D%E8%A1%A8%E3%81%99%E5%A0%B4%E5%90%88%E3%81%AF%20%5BAB%5D%20%E3%81%A8%E6%9B%B8%E3%81%8D%E3%81%BE%E3%81%99%EF%BC%88%E6%96%87%E5%AD%97%E3%81%AE%E9%9B%86%E5%90%88%E3%82%92%E8%A1%A8%E3%81%99%E3%81%AE%E3%81%A7%E3%80%81%E3%81%93%E3%82%8C%E3%82%82%20%E6%96%87%E5%AD%97%E3%82%AF%E3%83%A9%E3%82%B9%20%E3%81%AE%E4%B8%80%E7%A8%AE%E3%81%A7%E3%81%99%EF%BC%89%E3%80%82%0A%5B%20%5D%E3%81%AE%E4%B8%AD%E3%81%AE%E6%96%87%E5%AD%97%E6%95%B0%E3%81%AB%E5%88%B6%E9%99%90%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82%0A%5BABC%5D%20%E3%81%A8%E6%9B%B8%E3%81%91%E3%81%B0%E3%80%81%E3%80%8CA%E3%81%BE%E3%81%9F%E3%81%AFB%E3%81%BE%E3%81%9F%E3%81%AFC%E3%81%AE%E3%81%84%E3%81%9A%E3%82%8C%E3%81%8B1%E6%96%87%E5%AD%97%E3%80%8D%E3%81%AE%E6%84%8F%E5%91%B3%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82

### [a-z]
```[a-z]``` と書くと、```「aまたはbまたはcまたは・・・yまたはz」```の意味になるのです。
「aまたはハイフンまたはz」ではありません！
同様に、```[a-zA-Z0-9]``` であれば```「aまたはbまたは・・・z、AまたはBまたは・・・Z、0または1または・・・9」```の意味になります。（端的に言うと、これは「半角英数字1文字」の意味です）

つまり、[a-z] のようなのハイフンは```「文字の範囲」```を意味します

### 出典
https://qiita.com/jnchito/items/893c887fbf19e17d3ff9#:~:text=%5Ba%2Dz%5D%20%E3%81%A8,%E3%82%92%E6%84%8F%E5%91%B3%E3%81%97%E3%81%BE%E3%81%99

# 感想
これだけでも理解できたような感じかした。
参考書までは使うかわからないが、この講座を一応やってみる。
まぁ理解して無駄はないからやっておこう

# 関連書籍
https://gihyo.jp/book/2017/978-4-7741-9397-7
【webアプリ・Java・jsp/servlet】index.jsp

## webアプリ作成で詰まった！

#### 人生で2度目となるwebアプリ作成
イチから全てを作成するのが2度目になるのですがほとんど1度目と言って良いくらい**何もかも**忘れていました。
#### 【問題】CSSのレイアウトが反映されない！！
---環境---
webアプリ作成環境としては
・Eclipse
・java11
・jsp/servlet
・Apache（アプリケーションサーバ）

サーバーサイドのコーディングをしている時はアプリケーションは一見正常に作動しているように見えたのですが、サーバーサイドのコーディングがひと段落ついたのでフロント部分をコーディングし、作動してみるとcssが全く反映されませんでした。
。。。。

#### 気づくのに２日（作業8時間）
正直諦めかけました。色々と試行錯誤する上でなんとか辿り着きました。

### ウェルカムページの設定が間違っていた。
ウェルカムページとはTopServletなど最初のページに指定しているURLパターン（リンクみたいな）の事を言います。
https://www.yahoo.co.jp/
上記のyahooのtopページですが「jp/」以降何も指定がないと思います。このリンクを押してtopページに飛ぶ前に経由しているのが**TopServlet**です。そしてそこで設定しているウェルカムページが　https://www.yahoo.co.jp/
です。

☆一連の流れ
yahooのリンクを押す
↓
TopServletに飛ぶ
↓
設定してあるウェルカムページ（yahooトップなど）に飛ぶ
↓
yahooトップページが開く

-----------------
ウェルカムページの設定が「**index.jsp**」となっていなければいけないものを「/」などと書いていたのでcssが全く反映されなかったようです。


#### ではなぜindex.jspと指定しなければいけないのか、なぜ指定するとcssが反映されるようになるのか
　　
⇨それは「**web.xml**というファイルでデフォルトで指定されているから」です。

【web.xmlとは】
・htmlやサーブレットクラスの設定、webアプリの設定をできるものです。

TopServletのURLパターンとweb.xmlの設定を合わせてあげないとうまく動作しないようです。今回に関して言えば私はURLパターンを「/」のように全ての範囲を対象にしていたのでweb.xmlのデフォルト設定とは違ったのでcssの反映もされなかったようです。web.xmlの設定はアプリケーションのエラーにかなり直結しているみたいなので何かエラーがあれば一度見てみるのも手だなと思いました。


　　

## まとめ
今回2度目のアプリケーションを作っていて思ったのはまだまだ経験が足りないと感じた事です。今回のエラーなんて手慣れたエンジニアさんに聞けばすぐに解決できた気がします。エンジニアはコーディングしているよりもエラーに対応する時間のほうが長いと感じていますので、エラーが出た時の検索力であったり、思考の切り替えというのがエラー解決に繋がってくるなと染み染み感じました。
Googleプロジェクト管理：顧客とのコミュニケーション

# はじめに

わたしが [Google プロジェクト管理:プロフェッショナル認定証で得られた素晴らしい体験][google]を、要点をまとめ小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ ***"Google プロジェクト管理:プロフェッショナル認定証"*** を受講してみてください。

[google]: https://qiita.com/mapami/items/317ae776a2268fd54c8f

https://jp.coursera.org/professional-certificates/google-project-management

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/dc97f9d2-8c30-5310-a190-3fb484c9c091.png" width="800">

# コミュニケーションの重要性

***<font color="MediumVioletRed">『プロジェクトが成功するためには、コミュニケーションが最も重要であり、プロジェクト全体の生命線である』</font>***

コミュニケーションは、プロジェクトが始まる前から始まり、プロジェクト期間中、ずっと続いていきます。

プロジェクトマネージャーは、自分の組織のメンバーだけでなく、顧客やベンダーに対しても、機転を利かせてコミュニケーションをとることが得策です。顧客や取引先との戦略的なコミュニケーションは、うまくいけば、「自分はいい仕事をしている」「信頼できるパートナーだ」という自信を植え付けることができる。

:::note info
Project Management Instituteによると、プロジェクトマネージャーは約90％の時間をコミュニケーションに費やしているにもかかわらず、ほとんどのプロジェクトで何らかのコミュニケーション不全を経験していることが分かっています。
:::


# ソフトスキル

では、プロジェクトマネージャーはどのように顧客とのコミュニケーションに臨めばよいのでしょうか。

- ***<font color="MediumVioletRed">交渉術</font>***
- ***<font color="MediumVioletRed">共感的傾聴</font>***
- ***<font color="MediumVioletRed">信頼構築</font>***

などのソフトスキルを駆使すれば、顧客との間に良好な関係を築くことができます。

優れたプロジェクトマネージャーは、これらのスキルをいつ、どのように適用すればよいかを知っているのです。

交渉、共感的な聞き方、信頼関係の構築のための重要な練習は、 ***<font color="MediumBlue">質問をする</font>*** ことです。顧客の現状と希望する状態を理解するために、自由な質問をし、積極的に耳を傾けることが重要です。オープンエンドな質問をすれば、お客様がより安心できる場所が見つかります。両者のニーズが満たされるように交渉することができ、成功するパートナーシップに必要な信頼を築くことができるのです。

高い業績を上げているプロジェクトマネージャーは、特定の事柄をいつ顧客に伝えるかについて、明確な期待値を設定しています。

例えば、

- ***<font color="MediumBlue">顧客から質問されることを期待するのではなく</font>***、毎週進捗状況を報告し、顧客に情報を提供する。
- 製品のトラブルシューティングを行う場合、***<font color="MediumBlue">結果に影響を与えない問題については、顧客への説明をスキップする</font>***。
- チームのデザイナーが辞めてしまい、その代わりをしなければならなくなった場合、そのデザイナーを新しいデザイナーにかなり早く交代させることができ、プロジェクトの進行に影響を与えることもありません。お客様に余計な心配をさせることなく、目の前のタスクを完了させることができるのです。

### ユースケース

プランターが破損した問題のトラブルシューティングを考えてみましょう。

品質基準を作成する際に、サプライヤの誤差を考慮し、プランターの破損を考慮したことがあったかもしれません。ここでは、プランターの破損は50個に2個までが許容範囲としました。しかし、仮にお客さまが出荷されたとき、プランターの破損が5個あったとしましょう。

このとき、私たちはお客様にお会いして、重要な交渉事項をお伺いする必要があります。50個に5個のプランターが壊れることが許容範囲なのか、それとももっと壊れにくい上位のプランターに投資することを検討するのかを判断する必要があります。より頑丈なプランターを使うなどの解決策を提示すると、予算に影響が出るので、それに合わせて調整する必要があります。

- お客様はその変更に納得されますか？
- その場合、別のトレードオフが発生しないか？

交渉のプロセスを通じてお客様に満足していただくことを第一に考え、お客様の気持ちや限界に配慮することが必要です。そのためには、***<font color="MediumBlue">相手の不満を理解し、それに対処し、双方にとって有益な解決策を見出すという、共感</font>*** を示すことが大切です。

## お客様からのフィードバック

今後のプロジェクトでより良い結果を出すためには、お客様からのフィードバックが必要です。このフィードバックは、プロジェクト開始時の計画によって、途中で来ることもあれば、完成してから来ることもある。フィードバックを受けるタイミングは、プロジェクトで実際に何を達成したいかによるでしょう。

- もしあなたのビジネスがEコマースサイトを立ち上げるのであれば、顧客のショッピング体験を最適化するための調整を行うために、ユーザーからのフィードバックが必要でしょう。
- オンデマンドのクッキー配送サービスであれば、クッキーを配送した後に、クッキーや配送体験全体についてお客様がどう感じたかを知るために、ユーザーからのフィードバックを得たいと考えるかもしれません。

お客様からのフィードバックは、お客様の期待とプロジェクトのニーズとの間にあるギャップや理解を深めるのに役立ちます。

:::note info
交渉力、共感的な聞き方、信頼関係の構築などのソフトスキルは、あなたとお客様の間に良い関係を築くのに役立ち、そのお客様からフィードバックを得ることは、製品やサービスを繰り返し改良するのに役立つということです。
:::