OmniAICreator/Qiita-1.07M huggingface dataset:
よく目にするHTTPコードのまとめ

サービス運用業務に携わる際、よく見ることになるエラーコードをまとめておく。

# 200番台 (正常レスポンス)
|番号|内容|概要|
|:---|:---|:---|
|200|OK|リクエスト処理を正常に完了|
|201|Created|リクエストが成功してリソースの作成が完了した場合。<br>リクエストボディ情報などによりDBにレコードが生成された場合など|
|202|Accepted|リクエストを受け取ったが処理はしていない|
|203|Non-Authoritative Information|リクエストは成功したけど、変換プロキシによって元のサーバーの200(OK)レスポンスからペイロードが変更された場合|
|204|No Content|リクエストに対して送信するコンテンツが無い時。<br>リクエストした情報のヘッダに関しては問題が無いので正しく処理されている。|


# 400番台 (クライアント側エラー )

|番号|内容|概要|
|:---|:---|:---|
|400|Bad Request|クライアント側エラー。<br>サーバー側で承認していない誤ったパラメーターをユーザーが入力してきた時など。|
|401|Unauthorized|アクセス権が無い。または認証に失敗|
|403|Forbidden|閲覧権限が無い。|
|404|Not Found|指定したURI(URL)で応答するWebページやエンドポイントが存在しない。|
|405|Method Not Allowed|送信するクライアント側のメソッドが許可されていない。<br> GETで設定されたエンドポイントなどにPOSTでアクセスしてまった時など。|


# 500番台 (サーバーエラー)
|番号|内容|概要|
|:---|:---|:---|
|500|Internal Server Error|サーバー内エラー。<br>サーバー側で想定していないパラメータなどをユーザー側から受信してしまい、処理できなかった時。<br>エラーハンドリングして400のレスポンスにするのが一般的。|
|502|Bad Gateway|ゲートウェイ・プロキシサーバが不正なリクエストを受け取り拒否した時。|
|503|Service Unavailable|一時的にサーバにアクセスが出来ない時。|
|504|Gateway Timeout|リクエストを送ったサーバからの適切なレスポンスがなくタイムアウトした時。|

よく見るものはだいたいこんな感じかな...と思います。
LangChain JSでChatGPT APIを試す

今大流行中で先日APIも発表されたChatGPTをLangChainを使って試そうと思います。
「LangChain」は、「LLM」 (Large language models) と連携するアプリの開発を支援するライブラリです。
詳しくはnpakaさんという人の記事がとてもわかりやすかったので調べてみてください。

https://note.com/npaka/n/n61ad59380a43

LangChainは現在、PythonとJS/TSライブラリが存在するのですが、今回はJS/TSの方を使ってみようと思います。

## 準備
### OpenAIのAPIKEYの取得
今回はChatGPTのAPIを使うのでOpenAIのAPI KEYを発行します
OpenAIにログインして右上メニューから **View APIKeys** → **Create new secret key** から発行してください

#### 環境変数ファイルにAPI KEYを記述
```:.env
OPEN_AI_API_KEY=*****
```

### インストール
#### typescript関連
- typescript
- @types/node
- ts-node

#### LangChain関連
- langchain
- openai
- dotenv
:::note warn
注意
langchainでChatGPTAPIがサポートされたのはv0.018以上になるのでそれよりも上のバージョンをインストールしてください
:::

### tsconfig, package.jsonの設定
自分の環境によってよしなにカスタマイズしてください。

```json:package.json
{
    "type": "module",
    "private": true,
    "scripts": {
        "start": "node outDir/index.js",
        "build-ts": "tsc",
        "dev-ts": "ts-node root/index.ts",
        "llm": "yarn build-ts && yarn start"
    },
    "devDependencies": {
        "@types/node": "^18.14.2",
        "ts-node": "^10.9.1",
        "typescript": "^4.9.5",
    },
    "dependencies": {
        "dotenv": "^16.0.3",
        "langchain": "^0.0.21",
        "openai": "^3.1.0"
    }
}
```

```json:tsconfig.json
{
    "compilerOptions": {
        "target": "es2020",
        "module": "esnext",
        "lib": ["es2020", "dom"],
        "sourceMap": true,
        "outDir": "./outDir",
        "rootDir": "./root",
        "strict": true,
        "moduleResolution": "node",
        "baseUrl": "src",
        "esModuleInterop": true,
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true
    },
    "include": ["root/**/*"],
    "compileOnSave": false
}
```
:::note alert
LangChainはesModuleになっているので
pakage.jsonの **targetはmodule**、
tsconfig.jsonの　**moduleはesnextかnodenext**にしてください
:::

#### ERR_PACKAGE_PATH_NOT_EXPORTED系のエラーについて
インポートする際の`ERR_PACKAGE_PATH_NOT_EXPORTED`エラーは大体上記のpackage.jsonやtsconfig.jsonが原因となっています。
LangChainはcommonJSではなくESModulesになっているのでそこらへんの設定を確認してみてください

:::note info
追記
commonJSでもインポートの仕方によっては使えるみたいです
https://hwchase17.github.io/langchainjs/docs/getting-started#commonjs-in-nodejs
:::

## 実行
### コード
それでは準備が整ったのでAPIを動かしてみようと思います
```ts
import * as dotenv from 'dotenv';
import {OpenAIChat} from "langchain/llms";

dotenv.config();

const model = new OpenAIChat({openAIApiKey: process.env.OPEN_AI_API_KEY, modelName: "gpt-3.5-turbo"});
const run = async () => {
  const question = '日本一高い山はなんですか？'
  const res = await model.call(question);

  console.log({Q: question, A: res});
};

run()
```
[LangChainのドキュメント](https://hwchase17.github.io/langchainjs/docs/getting-started#llms-get-predictions-from-a-language-model)によれば環境変数を自動で読み込んでくれるみたいなのですが、なぜかできなかったので今回は`process.env`からAPIKEYを呼び出しました

### 実行結果
```bash
# yarn llm
{ Q: '日本一高い山はなんですか？', A: '\n\n日本一高い山は、富士山(ふじさん)です。標高は3,776.24メートルです。' }
```

### まとめ
LangChainを使うとLLMを独自の拡張ができるのでこれからどんどん使われるようになりそうですね
しかも自分はPythonには強くないのでJS/TSが使えるのもありがたいです！
【C#】WinformsでCommandManagerクラスが認識されない

# 環境
エディタ：VS2022
フレームワーク：.NET6
プロジェクトテンプレート：Windowsフォームアプリケーション

# 問題
MVVMの勉強をするために、あえて普段業務で使用しているWinformsを使用して
ソースを書いていましたが、CommandManager(System.Windows.Input)を記述したところ
「現在のコンテキストに'CommandManager'という名前は存在しません」のエラーが発生。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779169/5e6032ea-0042-e261-3c4b-b0635f12054d.png)

# 解決策
公式のドキュメントを見るとアセンブリは「PresentationCore.dll」とのこと。
プロジェクトの参照を確認し、該当のアセンブリは存在しないことを確認。
~~以下のディレクトリからPresentationCore.dllを参照に追加することで解決しました。~~
~~C:\Program Files (x86)\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\6.0.11\ref\net6.0~~

※2023/03/06追記

対象のアセンブリのみを追加するのではなく、UseWPFプロパティを利用することで
WPF ライブラリへの参照を含めることができるとのご指摘をいただきました。

csprojファイルに追記すると、.NET5以降のプロジェクトで 
.NET デスクトップ SDK が自動的にインポートされます。

@juner 様 ありがとうございました。

``` 
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
    <UseWPF>true</UseWPF>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

</Project>
```

# 反省
Winformsで書かれたサンプルコードが少なく、WPFのコードを参考にしていたために詰まりました。。。
Winformsを使用する場合は明示的に追加する必要があるということを学びました。
(WPFではプロジェクト生成時から該当のアセンブリが含まれており追加する必要なし)
Svelte × chart.jsでグラフを表示する

## 概要
SvelteでChart.jsを使ってグラフを表示するときに、いくつかつまずきポイントがあったのでメモ

## 環境
Svelte: 3.54.0
chart.js: 4.2.1
TypeScript: 4.9.3

## 実装
途中のデータは適当
```typescript
<script lang="ts">
	import {
        Chart,
		LineController,
		LineElement,
		PointElement,
		CategoryScale,
		LinearScale,
		Tooltip,
		Legend,
    } from 'chart.js';
	import { onMount } from 'svelte';

    let chartData = {
		labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
		datasets: [
			{
				label: 'Sample',
				backgroundColor: 'rgb(255, 99, 132)',
				borderColor: 'rgb(255, 99, 132)',
				data: [0, 10, 5, 2, 20, 30, 45]
			}
		]
	};
	Chart.register(
		LineController,
		LineElement,
		PointElement,
		CategoryScale,
		LinearScale,
		Tooltip, // ツールチップ表示用,お好みで
		Legend   // 凡例表示用,お好みで
	);
	let chartCanvas: HTMLCanvasElement;
	function renderChart() {
		let chart = new Chart(chartCanvas, {
			type: 'line',
			data: chartData,
			options: {}
		});
	}
	onMount(renderChart);
</script>

<canvas bind:this={chartCanvas} />
```

### つまずきポイント

#### `Error: "category" is not a registered scale.`

https://www.chartjs.org/docs/latest/getting-started/integration.html

categoryとはなんぞや???となったが,どうもcontrollerやpluginなどを最初にimportして登録しなければならないらしい.前に使ったのが2系だったので解決法を探すのに時間を取られた…(categoryってなに？)

#### データの渡し方

bindを使えばいいらしい.

#### 追加つまずき:データを時系列で表示する

https://www.chartjs.org/docs/latest/migration/v3-migration.html
`moment is no longer specified as an npm dependency. If you are using the time or timeseries scales, you must include one of the available adapters and corresponding date library. You no longer need to exclude moment from your build.`
とあるようにまず時系列で表示するためのライブラリを入れる必要がある.筆者は`chartjs-adapter-moment`と`moment`を入れた.
```
npm install moment chartjs-adapter-moment --save   
```
次に先程のコードを下記のように修正する.


```diff_typescript
<script lang="ts">
	import {
        Chart,
		LineController,
		LineElement,
		PointElement,
		CategoryScale,
		LinearScale,
		Tooltip,
		Legend,
+       TimeScale
    } from 'chart.js';
+   import 'chartjs-adapter-moment';
	import { onMount } from 'svelte';

    let chartData = {
		labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
		datasets: [
			{
				label: 'Sample',
				backgroundColor: 'rgb(255, 99, 132)',
				borderColor: 'rgb(255, 99, 132)',
				data: [0, 10, 5, 2, 20, 30, 45]
			}
		]
	};
	Chart.register(
		LineController,
		LineElement,
		PointElement,
		CategoryScale,
		LinearScale,
		Tooltip,
		Legend,
+       TimeScale
	);
	let chartCanvas: HTMLCanvasElement;
	function renderChart() {
		let chart = new Chart(chartCanvas, {
			type: 'line',
			data: chartData,
			options: {
+                scales: {
+                    x: {
+                        type: 'time',
+                        time: { unit: 'day'}                   
             }
		});
	}
	onMount(renderChart);
</script>

<canvas bind:this={chartCanvas} />
```
labelsの部分はDate型の配列を渡せば良い(書くのが面倒なので上記の例では変更していないが)

## あとがき
React使えばよかったのでは？と何度か心折れかけたが,なんとかグラフの表示まではたどり着いた. 余裕があれば複合グラフの表示をしたいが,ドキュメント見てもやり方がわからん…
youtubeのデータをgpt_index(Llama_index)使って読み込み質問してみる


概要 
---
こちらの[サイト](https://note.com/npaka/n/n8c3867a55837)を参考に試してみました

youtubeのデータをgpt_index(Llama_index)使って読み込みその動画で伝えたいことや登場人物を質問してみる

今後やってみたいこと
---
PDF、Wikipedia、Twitterなどをデータソースにしたチャットボットを作成

環境
---
googlecolab

前準備
---
OpenAIのAPIキー発行
[参考URL](https://auto-worker.com/blog/?p=6988)

実装
---
```python
pip install llama-index
import os
os.environ["OPENAI_API_KEY"] = "OpenAI_APIkeyを入力"

```
 [LlamaHub](https://llamahub.ai/)で「youtube_transcript」を選択
![スクリーンショット 2023-03-13 22.45.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256115/f05c2b2e-9d98-28d8-c96e-64d87e3aa2f2.png)
![スクリーンショット 2023-03-13 22.44.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256115/5ff9b4d4-5a40-617c-4521-999da46e5c26.png)
サンプルをコピー。入れたいデータのyoutubeリンクを入力する。
![スクリーンショット 2023-03-13 22.44.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256115/8b33ca64-62ca-51ad-4eec-1aed85db92e7.png)
今回は桃太郎のyoutubeのURLを入力
```
from llama_index import download_loader
YoutubeTranscriptReader = download_loader("YoutubeTranscriptReader")
loader = YoutubeTranscriptReader()
documents = loader.load_data(ytlinks=['https://www.youtube.com/watch?v=3k75rkB61Bk'])
#指定されたYouTube動画のトランスクリプトデータを読み込み、documentsという変数に格納
```
llama-indexパッケージからGPTSimpleVectorIndexとSimpleDirectoryReaderをインポート
GPTSimpleVectorIndexクラスを使用してインデックスを作成
```
from llama_index import GPTSimpleVectorIndex, SimpleDirectoryReader
index = GPTSimpleVectorIndex(documents)
```


# 質問応答
```
print(index.query("どんな物語？日本語で答えて"))
```

こちらの回答が返ってきた
`この動画は、勇気と努力が報われるというメッセージを伝えようとしています。`
```
print(index.query("桃太郎以外の登場人物を教えて？日本語で答えて"))
```
`老夫婦、犬、猿、雉、悪魔将軍`

悪魔将軍...
社内サイト構築勉強②(さくらのレンタルサーバ+Laravel)：ログイン機能実装

# 前提・概要

プロジェクトの作成は前回記事（https://qiita.com/tk49/items/f85708ed567853143c29 ）にて作成したものを想定。
（※プロジェクト作成直後で変更していない状態）

# 本日の完成形
【Register】画面
登録できることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284198/b5f40846-18d1-2653-6254-8b0d0d78473f.png)

【Login】画面
ログインできることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284198/36a5d645-25b6-73f6-af5b-016a48d37d68.png)

ログインするとトップページの右上がHomeになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284198/769a09f8-a720-864f-c3be-49f4660d42e7.png)



## 1.初期設定
設定系ファイルの修正。（2ファイル）
いずれもなくても問題なし。

1.app/Providers/RouteServiceProvider.php（1か所）
コントローラーのroute namespaceを定義する。（route設定するときに簡易になる。）
```php:RouteServiceProvider.php
//protected $namespace = 'App\\Http\\Controllers';
↓
protected $namespace = 'App\\Http\\Controllers';
```

2.config/app.php（3か所）
テストデータ自動作成の際、日本語になる。（名前とかが日本語になる。）
```php: app.php
    //'timezone' => 'UTC',
    'timezone' => 'Asia/Tokyo',

    //'locale' => 'en',
    'locale' => 'ja',

    //'faker_locale' => 'en_US',
	'faker_locale' => 'ja_JP',

```

## 2.ログイン系インストール
### インストール作業
1.bootstrap用ui
2.bootstrap

```bat:cmd
cd C:\Users\ADMIN\source\repos\社内サイト
composer require laravel/ui
php artisan ui bootstrap --auth
```

### 動作確認
サーバ起動
```bat:cmd1
cd C:\Users\ADMIN\source\repos\社内サイト
php -S localhost:8000 -t public
```
```bat:cmd2
cd C:\Users\ADMIN\source\repos\社内サイト
npm run dev
```
http://localhost:8000/
へアクセス。


【Register】画面
登録できることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284198/b5f40846-18d1-2653-6254-8b0d0d78473f.png)

【Login】画面
ログインできることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284198/36a5d645-25b6-73f6-af5b-016a48d37d68.png)

## 3.さくらのレンタルサーバにて動作確認

ログインの仕組みとしては、npmというものを利用している模様。
なのでローカルで実行する際には「npm run dev」のコマンドで起動してやる必要があった。
本番サーバではnpmを起動ではなく、buildしたものを持って行ってやる必要がある。
（scssとjs。動的にビルドしているようだがよく分かっていない）

### ①：npm run buildコマンドにてscssとjsのファイル作成（ビルド）
```bat:cmd
cd C:\Users\ADMIN\source\repos\社内サイト
npm run build
```

### ②：git ignoreの設定変更し、push
デフォルトだと、public/buildはgit管理対象外となっているため、
#をつけてコメントアウトしておく。
その後、コミット＆プッシュ

### ③さくらのレンタルサーバへssh接続
```bat:cmd
ssh FTPアカウント@FTPサーバ名
```

### ④git pull
```bat:cmd
cd 社内サイト
git pull original master
```

### ⑤ブラウザからアクセス
https://xxx.sakura.ne.jp/社内サイト
登録・ログイン処理ができるか確認。
silckスライドショー

# 【Rails】slick使ってスライドショーに挑戦してみたので作り方を簡単に書いていきます
ホームページのトップページでよく見るスライドショーを作ってみました！

JavaScriptとjQueryを使います！


![無題の動画 ‐ Clipchampで作成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111780/104462ad-05a2-6019-80d9-2026d4f50a9a.gif)



# ①【jQuery】を導入します

Gemfileに下記を記述
```php:Gemfile
gem 'jquery-rails'
```

ターミナルに戻ってインストール
```php
1. bundle install
```
---

# jQueryとは？
#### JavaScriptで出来ることをコンパクトにまとめたものです。
例えば、今回のスライドショーやクリックしたら画像が変わったりJavaScriptだと
書くのに時間がかかりますが、jQueryを使えば簡単に記述できてしまいます:clap_tone1:



------

# ②htmlへ記述

application.html.erbへ下記の3種類を記述します。

```php:view/layouts/application.html.erb
<head>
.
.
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.css"/>
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick-theme.css"/>
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js"></script>
.
.
</head>
```

# ③viewページへ記述(画像を付ける)

表示させたい画像をviewページへ記述
`https://〇〇〇`ではない場合は、`assets/`を記述しないと画像が表示されません

```php:html.erb
<div class="slider">
  <div class="slider-img">
    <img src="assets/〇〇〇.jpg" />
  </div>
  <div class="slider-img">
    <img src="assets/〇〇〇.jpg" />
  </div>
  <div class="slider-img">
    <img src="assets/〇〇〇.jpg" />
  </div>
</div>
```


# ④javascriptへ記述

下記の内容を記述する

```php:app/javascript/packs/application.js

//= require jquery　 　　　　　　　　　
//= require jquery_ujs　　　　　　　　 

$(function () {
  $(".slider").slick({
    arrows: false,
    autoplay: true,
    adaptiveHeight: true,
    dots: true,
  });
});
```

※注意
`//= require jquery`　 　　　　　　　　　
`//= require jquery_ujs`
この二つも忘れず記述してください！

# ⑤CSSへ記述

下記のような感じで記述してください！
中身は自分の好きなようにカスタムしてください:relaxed:

```php:app/assets/stylesheets/application.css

.slider {
  width: 90%;
  margin: 0 auto;
  height: 500px;
}
.slider-img img {
  width: 90%;
  margin: 0 auto;
  height: 500px;
}
```

これでスライドショーが完成すると思います！
抜けがあったら申し訳ございません...:bow:
nodeバージョンが合わないで「SyntaxError: Unexpected token '?'」の対応

### シナリオ

Nextjs のバージョンアップ（v11 → v13）

```diff 
-    "next": "11.0.1",
+    "next": "^13.1.0",
```

を検討していますが、github action を経由で、

```bin
$ npm run build
```

を実行したら、下記のようなエラーが出てきました。

```
err: /......./node_modules/next/dist/build/index.js:347
err:                     ...pageKeys.app ?? [], 
err:                                      ^
err: SyntaxError: Unexpected token '?'
err:     at wrapSafe (internal/modules/cjs/loader.js:915:16)
err:     at Module._compile (internal/modules/cjs/loader.js:963:27)
err:     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
err:     at Module.load (internal/modules/cjs/loader.js:863:32)
err:     at Function.Module._load (internal/modules/cjs/loader.js:708:14)
err:     at Module.require (internal/modules/cjs/loader.js:887:19)
err:     at require (internal/modules/cjs/helpers.js:74:18)
err:     at Object.<anonymous> (/......./node_modules/next/dist/cli/next-build.js:10:37)
err:     at Module._compile (internal/modules/cjs/loader.js:999:30)
err:     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
err: npm ERR! code ELIFECYCLE
```

### nodeバージョン確認

nodeバージョンが合わっていないだと思っていますので、アプリのnodeバージョンを確認しました。

```
$ cat .node-version
16.13.1
$ node -v
v16.13.1
$ nodenv version
16.13.1 (set by ....
```

問題なそうです。

### 調査

nodeのglobalバージョンを確認すると、

```
$ node -v
v12.22.12
```

ここの問題かもしれません。手動で

```bin
$ npm run build
```

を実行すると、無事にビルトできました。monitで確認すると

```
$ pm2 monit
x                                            xx Interpreter args      N/A                                                                                 x
x                                            xx Exec mode             fork                                                                                x
x                                            xx Node.js version       16.13.1                                                                            x
```

どちらでも大丈夫そうですね。なんだろう？　github actionでnodeバージョンを確認すると、

```
out:   run `npm audit fix` to fix them, or `npm audit` for details
out:   NPM building ...
out: v12.22.12
out: > ....-react-application@1.0.0 build ./
out: > next build
err: /......./node_modules/next/dist/build/index.js:347
err:                     ...pageKeys.app ?? [], 
err:                                      ^
err: SyntaxError: Unexpected token '?'
err:     at wrapSafe (internal/modules/cjs/loader.js:915:16)
....
```

v12.22.12（globalバージョン）を利用しているらしいです。

### 対応
nodeのglobalバージョンを16.13.1 に変更する

```
$ sudo npm install -g n
$ sudo n 16.13.1
$ node -v
v16.13.1
```

__Re-run all jobs__ をクリックすると、無事にデプロイできました。

### 結論

おそらくgithub actionでnode のglobalバージョンを利用しているらしいです。
nodenv効かないかな？ご参照いただければ幸いです。
【Swift】変数と定数

変数や定数とは、**何かを入れておく箱のようなもの**とよく言われます。
実際に理解を深めていくと、確かにそうかも！って思ってもらえると思います。
今回は変数や定数を扱ううえでよく耳にする言葉なども合わせて記しておきます。

<br>

# 目次
1. [変数とは](#何度でも！変数「var」)
1. [定数とは](#一度だけ！定数「let」)
1. [型とは](#そもそも「型」とは...)
1. [代入可能な値](#別の型の値はお断り！)
1. [型名の省略と型推論](#型名の省略と型推論)
1. [変数や定数に代入された値の使い方](#変数や定数に代入された値の使い方)

<br>

# 何度でも！ 変数「var」
- 宣言キーワード **「var」**
- 再代入が可能
```swift:
var 変数名: 型名 = 値

var cat: String = "ネコ"
cat = "猫" // 上で既に宣言がされているのでvarは不要
```

<br>

# 一度だけ！ 定数「let」
- 宣言キーワード **「let」**
- 代入できるのは一度だけで、後から値を変更することは不可能
```swift
let 定数名: 型名 = 値

let dog: String = "イヌ"
dog = "犬" // エラーになってしまう！(コンパイルエラー)
```

:::note info
変数と定数の大きな違いは**代入できる回数**である！
どちらも宣言の仕方は同じ！
:::

<br>

# そもそも「型」とは...
ここまで読んでいただいき、 **型とはなんぞや** って思っている方もいるはずです。
型とは超簡単に説明すると **「種類」** です！
各値がどの種類に属しているかを表しています。
何のために種類分けされているのかは下記リンク先にて詳しく説明しております！(後日記載)

<br>

# 別の型の値はお断り！
```swift
var number: String = "1"
number = 1 // コンパイルエラー
```
このように文字列を表すString型として宣言した変数numberに、整数を表すInt型の値を代入することはできません。
左辺と右辺の型が同一であるかどうか、注意しましょう！

<br>

# 型名の省略と型推論
値をあとから代入する場合、宣言時に型名を書く必要があります！
知らない宛先から届いた謎の荷物は怖いですからね...
伝票の備考欄にこんなものが入っていますとザックリとでも記載があれば少しは安心できますよね！
```swift
宣言キーワード 変数or定数名: 型名
let books: String
books = "本"
```
:::note info
宣言時の型名を表す部分を、**型アノテーション**(type annotation)と言う。

:::
<br>

宣言時に値を代入する場合、型名は省略可能！
```swift
宣言キーワード 変数or定数名 = 代入したい値
var books = "ONE PIECE全巻" // 変数booksには文字列が代入されているため、String型と推論される
```
:::note info
代入する値から自動的に型が決められるしくみを、**型推論**と言う。
:::

<br>

# 変数や定数に代入された値の使い方
基本的には変数名や定数名を記述することで値にアクセスすることができます。
```swift
let a = 1
let b = a // 定数bの値には1が代入される
```
:::note info
定数aのように初めて値が代入されることを**初期化**と言う。
:::
<br>

宣言時に値が無い変数や定数を使用するとコンパイルエラーになります！
```swift
let a: Int
let b = a // 定数aには値がまだ無いためコンパイルエラー
```
:::note warn
既に宣言された変数や定数を使いたい場合は値があるか確認しよう！
:::
---
<br>


以上、変数と定数の説明でした！
これからもSwift学習頑張っていきましょう！
AWS 初めてのCloud Formation

# 背景
業務の中でDynamoDbの構築を依頼された。最終的なアウトプットとしてCloud Formationとしてほしいと要望があったため、
今回構築ついでに作成手順についてまとめる。

# Cloud Formationとは
ソース/テキストを元にAWSリソースを構築するサービス。
テキスト化しておくことで同じ環境の構築を簡易的に行うことができる。

# テンプレートファイルの作成
Cloud Formationを使用して環境の構築を実行するには、AWSサービスの構成を記述したテンプレートファイルを用意する必要がある。
今回は依頼されたDynamoDbの構築をサンプルとして作成してみる。

## 構築するDynamoDbの構成
例として生徒の名簿を管理するテーブルを作成する。
- テーブル名：school_member
- primary_key : 
    - パーテションキー : クラス
    - ソートキー : 番号
- LSI : 性別
- GSI : 名前

## テンプレートファイル
```yaml:sample.yml
# 今回設定が不要のものはコメントアウトしている
Resources:
  DynamoResource : # リソース名
    Type: AWS::DynamoDB::Table
    Properties: 
      TableName: "school_member"  # テーブル名
      TableClass: "STANDARD"      # テーブルクラス(STANDARD/STANDARD_INFREQUENT_ACCESS)
      BillingMode : "PAY_PER_REQUEST" # 課金モード
      AttributeDefinitions:       # 属性値リスト
        - AttributeName : 'class'
          AttributeType : 'S'
        - AttributeName : 'no'
          AttributeType : 'N'
        - AttributeName : 'name'
          AttributeType : 'S'
        - AttributeName : 'sex'
          AttributeType : 'N'
      GlobalSecondaryIndexes: # GSIの定義
        - IndexName : "IDX_name"
          KeySchema : 
          - AttributeName : 'name'
            KeyType : 'HASH'
          Projection : # 射影するプロパティ
            ProjectionType : 'ALL'
      LocalSecondaryIndexes: # LSIの定義
        - IndexName : "IDX_sex"
          KeySchema : 
          - AttributeName : 'class'
            KeyType : 'HASH'
          - AttributeName : 'sex'
            KeyType : 'RANGE'
          Projection : # 射影するプロパティ
            ProjectionType : 'ALL'
      KeySchema: # テーブルのプライマリキーを構成する属性を指定
        - AttributeName : 'class'
          KeyType : 'HASH'
        - AttributeName : 'no'
          KeyType : 'RANGE'
```

# 構築手順
AWSコンソールの操作手順を記載する。

1. AWSコンソールのCloud Formationから「スタックの作成」を実施する。
1. 上記から取得したテンプレートファイルをアップロードする。
1. スタックの名前を入力し、「次へ」ボタンを押下する。
1. その他オプションなどはいったんデフォルトのままで「送信」を押下。
1. 「CloudFormation > スタック > DynamoDbStack] が実行中であることを確認。
1. 「DynamoDB」の欄に「school_member」テーブルが追加されていることが確認できた。

# 実施してみての感想
Cloud Formationの操作はそこまで難しくない。どちらかというとINPUTファイルそれぞれのパラメータを各型式に合わせて設定するほうに時間がかかった。

# 今後
- 手順3,4にてオプション設定はすべてスキップして今回は記載した。スタック実行時にカスタムの値を設定などは今後インプットファイルを作成するうえで大事な部分になりそうなので、もう少し深堀してみたい。
- AWSのスクショは使用してよいかわからなかったため、今回未使用。調べたうえで問題なければ画像も添付してわかりやすくしたいと思う。

## 引用
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/AWS_DynamoDB.html
【Rspec】モデルからのレコード更新時にテストで値が更新されない時の解決法


## 要約
モデルの更新処理のテストが失敗する場合は、changeメソッドをブロックで書くことで更新後の値と比較されるようになってうまくいくかも？
```rb
it { expect { subject }.to change { some_model.reload.changed, true } }
```

## 課題

このような`changed`というカラムを持つシンプルなモデルを考えます。

```rb
#  changed         :bool      not null
class SomeModel
    validates :changed, presence: true

    def initialize
        self.changed = false
    end

    def change
        self.changed = true
        # このメソッド内でレコード保存する何らかの処理
    end
end
```

このモデルのテストを以下のように書いて

「あれ、changedの値を更新したはずなのに、されてなくてテストが落ちるぞ！」

という現象でお悩みではないですか？

```rb
subject { some_model.change }
it { expect { subject }.to change(some_model.reload.changed, true) }
# some_model.reload.changedがtrueとなっているはずなのにfalseのまま
```

もしかすると`changeメソッド`が原因かもしれません。
`changeメソッド`は括弧で括った場合、`some_model.reload`が更新処理の実行前にしか評価されないからです。

## 詳細
まず、この`itブロック`は以下の順番で処理されます。
1. changeメソッドのパラメータが評価される
    * つまり、**`some_model.reload`がこの時点で評価されます**
1. subjectが実行されて更新処理が走る
1. 1で評価された時点のモデルのインスタンス変数`changed`とsubject実行後の`changed`を比較する

これ、model.reloadが最初に走っちゃってるんですよね。
更新処理実行後に`model.reload`が走ってないと正しい結果は得られません。

ではどうすればいいのでしょう？

## 解決策
changeメソッドを以下のように**ブロック**で記述します。
そうすると`some_model.reload`は`subject`の実行前だけでなく実行後にもう一度実行されます。

```rb
change {some_model.reload.changed, true}
```

こうすることで、更新処理実行後にもインスタンスが評価されるので正しい結果が得られます。

## 参考

https://stackoverflow.com/questions/29848883/expect-subject-to-change-by1-doesnt-work
インスタンス変数とローカル変数の使い方について

# はじめに
現在、オリジナルアプリの実装中にインスタンス変数とローカル変数についての理解が飛躍的に深まったのでメモ。
**インスタンス変数、ローカル変数って一体どういう時に使い分けるの？？**
といった方がこの記事を見て頂いてスッキリしてくれたら幸いです。
　
# 目次
1.``インスタンス変数`` とは
2.　``ローカル変数`` とは


# 1.  ``インスタンス変数``とは
```ruby:インスタンス変数
  def new
    @birthday = Birthday.new  #インスタンス変数@birthdayをここで定義している
  end
```
<br>
上記に記述している
@birthdayというのがインスタンス変数。

* @birthdayとインスタンス変数を定義することにより
    * viewファイルにもデータの受け渡しが可能になる<br>
    
    * コントローラーにおいては、アクションとプライベートメソッドとの間で値の受け渡しが可能になる
    　　　　　　　　　　　　　　　　　　　　↓
    コントローラーでは一回のリクエストごとに一つのアクションが呼ばれるので、newで定義したインスタンス変数はcreateで利用できない
　


# 2. ``ローカル変数``とは

```ruby:ローカル変数
  def new
    birthday = Birthday.new  #ローカル変数birthdayをここで定義している
  end
```
<br>
ローカル変数はこのdefメソッド内でしか使えない。
メソッド内で完結する場合はローカル変数の定義で正常に動く
DazStudio Sakura8 Unity上にエクスポートする　テクスチャーの設定に注意

# 概要
DazStudioのSakura8をUnityにエクスポートしました。
その際に詰まった点があるので投稿します。

# 開発環境
OS:WIndow10
DazStudio:4.21
DazToBridge:v2022.2
Unity:2021.3.9f1

# 手順
## Unity プロジェクトを設定する。
テンプレートの３Dにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/165b20fd-50a9-0006-220c-0ada0441df05.png)



## DazToUnityでUnity側にエクスポートする
 Eyelashesを削除する

DazToBridgeでエクスポートします。
エクスポート画面の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/2f7a8244-83d8-b07f-25e5-e783cd301bfa.png)


## エラー１：全体的にテクスチャーが入っていない。
export後、色が入っていないです。
原因はわかってないです。マテリアルのテクスチャが入っていない（マテリアルのファイル自体は存在しているが、色が白色で中身が入っていない。）
対処方法は、Daz3D/Support/DazToUnity Standard Shaderを実行することです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/9a2ba130-f343-75e3-d3d7-b18c88cc8086.png)



実行後中身が入っているマテリアルが作成されることを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/9d05db44-a0b8-af0a-6403-4ead8307e837.png)



## エラー2：目だけのテクスチャが入っていない
原因は目のテクスチャJA EYES上にJA LENSテクスチャで覆われているため。
対処方法としてはJA LENを透過しているテクスチャに変更します。
以下gifアニメはJALENSのテクスチャを透明なテクスチャに切り替えている様子。

![sakura8-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a290f1e7-b015-8a49-dcde-2ae1462c416c.gif)






目のテクスチャ問題はデフォルトのGenesis8での場合では発生しなかったです。
Sakura8特有の問題だと思います。

# 対処後
Unity上でsakura8が正しく見えることを確認しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/42b49878-efbc-9629-7b52-0cbbfb51f010.png)

DazStudioでこれだけアニメ調に近づけられるのは良いですね。
(Cognito/Lambda)JWTをBase64でデコードしたときのエラー``` Error: Incorrect padding ```の解決策

# はじめに
Cognitoでログイン画面を実装し、そのログイン情報をlambdaなどで処理する際にJWT（Json Web Token）をデコードして使用するだろう。
基本的にはBase64+jsonでデコード可能なのだが、一部ハマるポイントがある。

# 事象

**処理できる文字列と処理できない文字列が存在した。**

## 問題が起こったコードとその挙動

```python
import base64

# JWTを"."で分割して、ヘッダ、ペイロード、署名に分ける
header, payload, signature = jwt_string.split(".")

# ヘッダとペイロードをデコード
decoded_header = base64.b64decode(header).decode("utf-8")
decoded_payload = base64.b64decode(payload).decode("utf-8")

# ヘッダ、ペイロード、署名を表示
print("Header: ", decoded_header)
print("Payload: ", decoded_payload)
print("Signature: ", signature)
```

```Name:(例)ログイン情報
ユーザID：test_111
 →(JWT)eyJvcmlnaW5fanRpIjoiOG5fanRpIjoiOG5fanRpIjoiOG~~~
 →(デコード)ユーザID：test_111

ユーザID：test_AAA
 →(JWT)eyJvcmlnaW5fanRpIjoiOG5fanRpIjoiOG5fanRpIjoiOG~~~
 →(デコード)エラー：Error: Incorrect padding 

```

### 通常のBase64エンコードでは対応できない

早速調べたら、下記のような記事を発見した。4で割れるように文字列を```=```で調整しなさいということだ。

https://stackoverflow.com/questions/2941995/python-ignore-incorrect-padding-error-when-base64-decoding

```
base64_str += "=" * ((4 - len(base64_str) % 4) % 4)        
```


## 原因

根本的な原因はJETが```URL-safe```という仕様だから。
通常のBase64エンコードでは```+```、```/```を意識せずに変換しますが、それらの記号はURL上では特別な意味をもってしまうため、それも別な文字に置き換える必要がある。

```
+ を - に置換
/ を _ に置換
```


## 解決策

```Base64 URL Encode```を使用するのが無難であろう。ただ、確実性と可読性から```python-jose```ライブラリを使用して問題解決した。
レイヤーを追加する手間はあるが、改ざんも発見可能で日本語の難しい漢字も確実にデコードしてくれるのでこちらを使用する。

レイヤーを追加する場合のコマンド

```
$ mkdir python
$ pip3 install -t python python-jose
$ zip -r9 layer.zip python
```
参考：https://sebenkyo.com/2021/05/21/post-1979/

#### 修正したコード
```python
jwt_str = response['AuthenticationResult']['IdToken']
# python-joseでidtokenをdecode
payload = jwt.get_unverified_claims(jwt_str)
# 結果をコンソールに表示
print(payload)
```
Googleデジタルマーケティング＆Eコマース：ロイヤリティ・ステージの基礎

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/77505f22-0d8f-b3af-4f9c-ed148bcefd65.png" width="800">

[以前、マーケティングファネル][funnel]を紹介しました。今回、コンバージョン・ステージについて、もう少し詳しく説明します。

[funnel]: https://qiita.com/mapami/items/56f851127a0880d3c97e

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/16d5375f-d204-65b7-7f4f-443f6c8a6e91.png" width="300">

# ロイヤリティ・ステージ

成功する企業は、顧客獲得と顧客維持のバランスを取っています。なぜなら、一度顧客との関係を築く努力をすれば、その関係を継続させたいと思うからです。

顧客のロイヤリティは、何よりも製品の品質と価値に左右されます。しかし、たとえ購入した製品が気に入ったとしても、再び訪れてくれるとは限りません。 

# ロイヤリティ・ステージでの戦略

ロイヤリティの構築は、購入時および購入後に、素晴らしい顧客体験を生み出すことです。

多くの企業は、

- フォローアップ・メール
- ポイント・プログラム
- ソーシャルメディアへの参加

などを利用して、顧客との関係を継続的に育んでいます。このようなインタラクションは、常に意図的かつ思慮深いものでなければなりません。

例えば、クーポンはリピート購入を促す効果がありますが、買ったばかりの商品のクーポンを送っても、おそらくお客様はあまり喜ばないでしょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/43dea5d3-166a-0dfb-0fc6-e437983ef3a6.png" width="600">

購入後の満足度を高めることが、将来の売上につながるのです。そして、ブランドロイヤリティだけでなく、熱心なファンになってくれる顧客を獲得することができるのです。

# ロイヤリティの測定

ロイヤリティをどのように測定するかは、ターゲット層や特定の目標によって異なります。

一般的には

- リピート購入率
- 購入間隔
- 顧客一人当たりの注文数
- サインアップ後のアカウント有効化率
- 特典プログラムへの関与の度合い

などを測定します。

ロイヤリティ指標によって、
- 企業は顧客を維持し、売上を向上させ、コストを削減するための戦略を評価し、改善することができます。
- また、顧客との関係をより効果的に管理するためのポイントも明らかになります。

最終的には、顧客ロイヤリティは、ファネル全体がどれだけ顧客にサービスを提供し、顧客のニーズを満たしているかを示す最も真のテストとなります。
ポートフォリオを作ろうとしているそこの貴方へ

# はじめに
ポートフォリオを作る時に、必要な時間や意気込みを書きます。
これで大体の時間配分が分かります。
自身がスクールに通っていた経験があり、ポートフォリオを作った経験をもとに話します！よろしくお願いいたします。

# ポートフォリオ作成で心がける事

①期日までに完成させる
②正しいコードを書く
③技術を理解して扱う

自分のスキルをアピールすることを意識し、自分で手を動かし、自分で完成することを意識してください。なぜ作ったのか分かるように！

# ポートフォリオにかかる時間について

順番に書いていきます。

①ポートフォリオのテーマを決める(5h)
②スケジュール作成(2h)
③作成する機能や画面のラフ案(6h)
④利用する技術の選定、調査(6h)
⑤データベース設計、画面設計、アプリケーション設計(12h)
⑥開発環境でのコーディング(96h)
⑦本番環境にデプロイ(サーバ構築やドメイン取得など)(18h)
⑧テスト、バグ修正(26h)

大体の流れは以上になります。

# どうしたらいいか分からない場合

自身も何から手を付けていいか分からなくなる経験がありました。
凄く苦しいです。解決策は、とにかく出来ることから始めて下さい。
そこで詰まったら相談できる人がいれば相談してみてください。
自分で作るという気持ちは非常に大事です。
ですがそれと同じくらい人に相談することも大事です。
初めからできる人など居ないのです！

テーマ決めでいうと、
解決したい課題や、自分が好きな事、世間で需要が在りそうなもの。
サービス利用者目線で考えてみるとGoodです！

どんなスタンスの人か？
一緒に働きたいと思えるような、ポートフォリオに仕上げれば最高ですね。

# さいごに
自身がポートフォリオ作成時に大事だと思ったのは
何でもいいから手をつける事だと思いました。

これからポートフォリオを作成する方は、意識してみると良いかもしれません^^
頑張りましょうね！！
laravelでのページネーション実装とカスタマイズ

Laravelで検索結果の一覧表示画面にページネーションを実装する方法と、デザインをカスタマイズする方法の個人的な備忘録。


## 環境
PHP 8.1
Laravel 9

## ページネーションの実装
まずはModelからデータを取得してViewにページネーションを表示するまで。

#### データ取得
今回はトピックの一覧を表示する画面を作成したので、Topicsモデルからデータを取得する。
1ページあたりの表示件数は10件とした。

```php
public function getTopics(): LengthAwarePaginator
{
  return  Topic::paginate(10);
}
```

取得時のwhere条件や並び替えなどがあれば適宜追加する。

#### viewへの表示
続いて取得したデータを表示するbladeファイル。

```html
@foreach ($topics as $key => $topic)
  <div>
    {{ $topic->title }}
  </div>
@endforeach

<!-- ページネーション用のリンクボタン -->
{{ $topics->links }}
```

これで取得したトピックのタイトルを一覧表示する画面にページネーションが実装できた。とても簡単。
が、これだけではデザインが大きく崩れたいた。どうやらBootstrapのデザインが適用されていなかったようで・・・。

#### Bootstrapデザインの適用
Bootstrapのデザインを適用させるにはAppServiceProviderに記述を追加する必要がある。

```php
<?php

// app\Providers\AppServiceProvider.php
   
namespace App\Providers;
   
use Illuminate\Support\ServiceProvider;
use Illuminate\Pagination\Paginator;
   
class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
     
    }
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Paginator::useBootstrap(); // これを追記する。
    }
}
```

これでBootstrapのデザインが適用され、とりあえず見た目だけは綺麗になった。

#### デザインのカスタマイズ
画面デザインに合わせてページネーションのボタンのデザインも変更する必要があったので、カスタマイズしてみた。

まずは以下のコマンドを実行する。
```
php artisan vendor:publish --tag=laravel-pagination
```

すると `resources/views/vendor/pagination`ディレクトリが作成され、この中にページネーションのbladeファイルが色々作成される。
この中に独自デザインのページネーション用bladeファイルを作成する。
今回はデフォルトで用意されている`default.blade.php`をコピーして新たに`topics.blade.php`を作成し、このbladeファイルを色々編集してデザインを変更した。

一つ前のページへのリンク、一つ後のページへのリンクなどもここで記述されているので、見た目だけでなく細かい挙動などをカスタマイズすることもできた。

無事カスタムページネーションのbladeファイルができたら今度はこれを元のbladeファイルに反映する。

```html
<!-- ページネーション用のボタン -->
<!-- {{ $topics->links }} -->
{{ $topics->links('vendor.pagination.topics' }}
```
ページネーション用のボタンを上記のように変更する。反映させるbladeファイルを単純に指定するだけなので簡単にカスタムページネーションを反映させることができた。

また、今回は各ページに「〇〇～〇〇件 / （全体数）件」を表記してほしいとのことだったが、こちらもページネーションの機能で簡単に実装できた。

```html
<!-- 画面表示されている項目の最初の連番 -->
{{ $topics->firstItem() }}

<!-- 画面表示されている項目の最後の連番 -->
{{ $topics->lastItem() }}

<!-- 全件数 -->
{{ $topics->total() }}
```

これで「11～20件 / 50件」みたいな件数の表示が実現できた。


## 参考文献
・Laravel8でページネーション(Pagination)を実装する方法
Bootstrapの適用方法で参考になりました。
https://leben.mobi/blog/laravel8_pagination/php/
【Android】バイブを鳴らす【Kotlin】

# はじめに

https://qiita.com/Tsubasa12/items/a8bec7f5be4ebce9d033

https://qiita.com/Tsubasa12/items/722bbf31eb5266adc580

音を鳴らす関係で記事を他にも書いているのでそちらも観てください。

# ボタンを押したら音が鳴るようにする

```MainActivity.kt
        val button: Button = findViewById<Button>(R.id.button)　　// 1

        val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator // 2

        button.setOnClickListener {                        
            vibrator.vibrate(1000)                                // 3
        }

```
説明していきます。
1.Buttonの ID を取得
2.Vibrationは直接インスタンス化できないので次のようにgetSystemServiceからインスタンス化
3.vibrateメソッドを使いバイブを鳴らす。この時引数は鳴らしたい時間をミリ秒で指定。
また、バイブの鳴らし方をカスタマイズしたい場合は
```
    vibrator.vibrate(longArrayOf(1000, 1000, 3000, 3000), -1)
```
というように定義し、第一引数にそれぞれミリ秒で
（振動までの待ち時間1, 振動時間1, 振動までの待ち時間2, 振動時間2...）
といったように配列を渡します。
上の例では　１秒待って１秒バイブ　３秒待って３秒バイブといったパターンを指定
第二引数に
繰り返しの回数を、繰り返しをしない場合は-1を渡します。

# 参考
https://android-note.open-memo.net/sub/sound--use-vibrator.html
Googleデジタルマーケティング＆Eコマース：コンバージョン・ステージの基礎

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/77505f22-0d8f-b3af-4f9c-ed148bcefd65.png" width="800">

[以前、マーケティングファネル][funnel]を紹介しました。今回、コンバージョン・ステージについて、もう少し詳しく説明します。

[funnel]: https://qiita.com/mapami/items/56f851127a0880d3c97e

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/d2601b9e-8ada-aaa8-c9ae-7a45097bc992.png" width="300">

# コンバージョン・ステージの目標

コンバージョン・ステージは、誰かが購入し、顧客となることを意味します。

購入を検討した人すべてがコンバージョンに至るわけではありません。そして、潜在顧客が購入に至るのは、ある企業のソリューションが他社よりも自分のニーズに合っていると思ったときです。

コンバージョン・ステージの目標は、

***<font color="MediumVioletRed">『潜在顧客を購入者に変えること』</font>***

です。

その目標をどのように実現するかは、企業によって、製品や顧客層によって異なります。


# コンバージョン・ステージの戦略

検討からコンバージョンに至るまでには、さまざまなタッチポイントを経由することを念頭に置く必要があります。

しかし、顧客行動の傾向を把握することで、コンテンツのパーソナライズやターゲット領域の改善を行うことは可能です。コンバージョン・ステージで他と差をつけるには、企業は明確で有益なコンテンツと体験を提供する必要があります。

これには、

- 正確な商品説明
- スムーズなチェックアウト手続き
- 明確な返品ポリシー
- 商品に焦点を当てた適切な広告
- わかりやすく構成されたWebサイト

まで、あらゆるものが含まれます。

どのような方法であれ、リードが答えを見つけ、行動を起こすことを容易にすることで、コンバージョンの可能性は高くなります。

# コンバージョンの測定

コンバージョンステージで測定できる最も基本的なものは、

- コンバージョンの数
    - コンバージョンは、潜在顧客が希望する行動をとったときに起こります。
- コンバージョンまでの時間
- コンバージョンあたりのコスト
- コンバージョンまでの平均タッチポイント数
- 平均注文規模

などを追跡することで、顧客がどのようにあなたのブランドと関わっているかについての貴重な洞察を得ることができます。

### カート放棄（Cart abandonment）

これらの洞察により、カート放棄などのドロップオフの問題に対処することができます。カート放棄とは、顧客が商品をカートに入れたものの、購入が完了しないことを指します。

信じられないかもしれませんが、オンラインカートの70%近くが放棄されていると言われています。そのため、お客様がチェックアウトのどの段階でカートを放棄するのかを知ることは、手順を改善し、コンバージョンを向上させるために役立ちます。
バイアス-バリアンス分解について

# はじめに

ディープラーニングにおける過学習を理解する上でよく出てくるバイアスとかバリアンス。両者の違いについてなんとなく感覚でわかっていたつもりだったが、調べてみると奥深い視点が自分なりに見えてきたので、メモ的にまとめて投稿してみます。
今回はバイアス-バリアンス分解についてになります。単なる一視点ということで。


# バイアスって？バリアンスって？

はじめにバイアスとは、予測モデルにおける予測値と学習データの差（平均値）を示しており、予測モデルが単純な場合大きくなる傾向があります。

一方バリアンスとは、予測モデルの複雑化を示したものでありノイズに影響を受けており、予測モデルが複雑すぎる場合に大きくなっていきます。

ちなみに、単純なモデルではバイアスが高くなり、一方複雑すぎるモデルではバリアンスは高くなる関係性を「バイアスとバリアンスのトレードオフ」と呼んでたりします。


# バイアス-バリアンス分解について

ある評価点とテストデータとの差を平均二乗誤差で算出すると、下記の３つの項に分解できる。
（バイアス-バリアンス分解）

```math
  E[(y_0-f'(x_0))^2]= (f(x_0)-E[f'(x_0)])^2+Var[f'(x_0)]+Var[ε]
```
```math
f':予測値  \\  f:実測値 
```

詳細を記載すると期待平均二乗誤差(MSE)は、第一項のバイアスの２乗と第二項のバリアンス、そして第3項のノイズから構成されている。

バイアスとバリアンスは、どちらも予測モデルとのズレを示しているが、バイアスが差の２乗であるのに対し、バリアンスは分散を使用して算出されている。
このことから両者ともずれを示しているが引き算と分散を使用しているのが確認できた。

分散と引き算の二乗（マイナスになる可能性から二乗している）の違いについて、以下自分なりの考察を書いてみる。

バイアスを示す引き算（の二乗）単純にズレの数値を示し、バリアンスを示す分散はより複雑なズレを表現していることから、バイアスとバリアンスの表現力の違いを数値化しているように感じる。バイアスは単一のものがターゲットに対し、バリアンスは集合をターゲットにしている。

なんとな～くな感想ですが、引き算より分散の方が高い表現力で数値化できている感覚。統計学とか数学もより学習を進めていくと、より高い表現力を数式で表記できるようになっていくんだろうなーと。正解値との単なるズレを色んな数式（分散や差）で表現できるって改めてすごいなと思う。

数学においてより複雑なモデルというのは、視点を変えるとより”表現力が高い”ことにつながっていると実感できました。
HTML5のcanvasのサイズを指定するときは、styleとして与えるのではなく属性として与えないといけない

座標指定がどうしてもズレるなぁと悩んでいたら、めちゃくちゃ凡ミスをしていたのでメモ。

## 正しい例
```html
<canvas id="hoge-canvas" width="350px" height="500" />
```
canvas要素に属性としてwidthとheightを与えている。

## 間違った例
```html
<canvas id="hoge-canvas" class="hoge" />
```
```css
.hoge {
	width: 350px;
	height: 500px;
}
```
こうすると内部的にはデフォルトの`width: 150, height: 300`が適用されるが、  
styleが当たって一見ちゃんと350*500でキャンバスが生成されたように見える。
要は引き伸ばされてる状態なので、`fillRect()`などで座標を指定して描画しようとすると変になる。

### 参考
[canvas: グラフィックキャンバス要素](https://developer.mozilla.org/ja/docs/Web/HTML/Element/canvas)
nginx proxy で phpmyadmin のコンテナにアクセスできない

以下の構成で構築していたが、`/__phpmyadmin/`にアクセスできなかった。

```yml:docker-compose.yml
version: '3'

services:
  app:
    build:
      context: ./docker
      dockerfile: Dockerfile
    environment:
      APP_ENV: 'DOCKER_DEV'
    working_dir: /app
    volumes:
      - '.:/app'
    extra_hosts:
      - "host.docker.internal:host-gateway"

  proxy:
    image: steveltn/https-portal:1
    ports:
      - '80:80'
      - '443:443'
    environment:
      DOMAINS: 'domain.jp -> http://app, domain.com -> http://host.docker.internal:3000'
      STAGE: 'production'
    volumes:
      - ./docker/proxy/https-portal-data:/var/lib/https-portal
      - ./docker/proxy/nginx-conf/domain.com.ssl.conf.erb:/var/lib/nginx-conf/domain.com.ssl.conf.erb:ro
    depends_on:
      - app
    extra_hosts:
      - "host.docker.internal:host-gateway"

  phpmyadmin:
    image: 'phpmyadmin/phpmyadmin'
    environment:
      PMA_HOST: 'host.docker.internal'
      PMA_PORT: '3306'
      PMA_ABSOLUTE_URI: 'https://domain.com/__phpmyadmin/'
    extra_hosts:
      - "host.docker.internal:host-gateway"

```
```erb:docker/proxy/nginx-conf/domain.com.ssl.conf.erb
<%# 省略 %>
    location /__phpmyadmin/ {
        proxy_pass http://phpmyadmin;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
```

`https://domain.com/__phpmyadmin/`にアクセスしても４０４となってしまっていた。

## 解決
`rewrite ...` を追加で解決した。

```erb:domain.com.ssl.conf.erb
<%# 省略 %>
    <%# https://github.com/phpmyadmin/docker/issues/210 %>
    location /__phpmyadmin/ {
        rewrite ^/__phpmyadmin(/.*)$ $1 break;
        proxy_pass http://phpmyadmin;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
```

## 参考
https://github.com/phpmyadmin/docker/issues/210
【AWS】RDS入れ替えた際にSQLExceptionで怒られた話

# はじめに
最近コスト的な理由で検証環境のDBを作り直したのですが、その際に既存のProxyを新しいDBに向けるとSQLException　Access denied for userと怒られました。
怒られた原因と修正内容を備忘録的に残しておこうと思います。

# 対応方法
まず原因ですが、Proxy側の設定に置き換え前のDBへ参照するための設定が一部残っていたことが原因でした。
AWS Secrets Managerで新しいDBへ参照するためのアカウント情報を登録していたものの、Proxy側で参照しているロールが古いシークレット情報を参照するようになったままでした、、、。

参照するDBが変わった場合は、以下赤枠からIAMロールを新しく作成するか、元々使用していたIAMロールを編集する形でシークレット情報を書き換えてあげる必要があります。

![スクリーンショット 2023-03-05 20.07.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354522/94b54a75-5895-01de-4173-29b8554b6285.png)

修正は以上になります。

# さいごに
当然と言えば当然なのですが、DB置き換え作業は影響を考えて深夜に行っていたので、まさかの1時間近くもハマってしまっていました、、、
適度な休息をとりつつ、パフォーマンス高く作業は行っていきたいものですね
ラズパイにDocker環境を整える（Docker＆Docker Compose)

# Dockerインストール
```console
$ su -
# curl -fsSL https://get.docker.com -o get-docker.sh
# sh get-docker.sh
# systemctl enable docker
```
## インストール確認＆起動確認
バージョン確認できること
```
# docker --version
Docker version 23.0.1, build a5ee5b1
```
ステータス確認して、active(running)であること
```
# systemctl status docker
```

# Docker Composeインストール
pipを使ってインストールするらしい。
```console
# pip3 install docker-compose
```
ちょっと古いやつがインストールされるようである。
```console
# docker-compose --version
docker-compose version 1.29.2, build unknown
```
Amazon Lightsail Wordpressで作ったブログを閉鎖する


以前Lightsailで作成したブログを閉鎖することになりましたので、その工程を記録します。
[作成時の記事はこちら](https://qiita.com/e-onm/items/9ac06fc35c6cdb3d5e00 "Amazon Lightsail Wordpressでブログサイトを作る")

## DNSの解除

Lightsail > 対称インスタンス > Domain > 紐付けているドメインを削除
Route53 > ドメイン > 対称ドメイン > 「ドメインの削除」
Route53 > ホストゾーン > 対称ホストゾーン　> 「ゾーンを削除する」

## StaticIPの解除

Lightsail > 対称インスタンス > Networking > IPv4 networking > 紐付けているStaticIPをDetach

## インスタンスの削除

Lightsailトップ > Instances > 対称インスタンスの設定ボタン > Delete

## 確認

ドメイン名を使ったURL
StaticIPを使ったURL
どちらもアクセスができなくなっていることを確認する。
私にとって相性最悪の案件に出会ったので教訓ノートと改善アクションを考える

先月、私にとって相性最悪の案件を経験したので共有したいと思います。

- 経緯1. 案件初日のヒアリングまず協力会社かフリーランス SES だけ雇ってそこでチームを組ませお客様の相手をさせようとしていた。
チームのプロジェクトマネージャーにアサインされたのが初老の IT スキルもプロジェクトマネジメントスキルも持っていないのに観察眼や気に入られる技術は異様に高い人間だった、これ以降はその人を爺PMと言う。


- 経緯2. アサイン2週間後、爺PMが元の印象と反転して、「お前とお客様のやりとりがよろしくないと上は思っている」等と言い出し、私の抱えているタスクを共有しろと言い出す。ただし当人はプロジェクトマネジメントスキルがないため WBS などを作ってくれない。
かわりに私に行っていることをwbs形式で作成して提出。それに対して、意見として
「こんなスケジュール本当にできるのか？責任とれるのか？通るわけないだろう」数日かけて否定的ないちゃもんをつけられる。（このあたりで私は爺PMに権威を握らせてる会社に危険を感じ辞めることを決意。）

- 経緯3. 辞めることを打ち明けた後、爺PMにお客様さんやりとり禁止令を出される。



## 反省点から考えられる積極改善アクション
- 案件への営業段階では「協力会社チーム×お客様対応のある案件」は避けつつ、どうしても当たった場合は周りのパーソナリティの変化に敏感に危機察知して、場を取り持つか逃げるか積極的に道を模索する。

- 積極的にリーダ・PMへは自分からまず探りを入れた話をしてパーソナリティを把握する。
（何に関心があるか、深い話ができるか試す。）

- チームメンバーが働けるように役割を柔軟に変える。（これは私の権限ではできないので提案ベース）
ChatGPTキャラクターマスコットアプリの紹介【Ver1.1.0変更点】

# 準備＆インストール

本アプリの準備＆インストールに関しては以下の記事を参照してください

https://qiita.com/AIDeveloper777/items/d03cd30b80d96697db2c

### Ver1.1.0のダウンロード

以下のURLからzipファイルをダウンロードできます。

https://drive.google.com/drive/folders/1kH8x7OsLn87Kfoz9Sar6rpnVZGP_RkYU?usp=sharing

::: note info
Ver1.0.0の設定を引き継ぎたい場合、Configフォルダを入れ替えてください。
:::

# 変更点

以下の5つの機能を新たに追加しました。
・ChatGPT(API)の導入
・感情パラメータの導入
・会話ログ画面
・天気情報の反映
・現在日時の反映

### 【１】ChatGPT(API)の導入

2023/03/02（木）にChatGPTのAPIがリリースされました！

最新版（Ver1.1.0～）ではChatGPT APIを採用し、
対話精度の上昇、応答速度の高速化、発生する料金が1/10になりました！

### 【２】感情パラメータの導入

- ChatGPTのプロンプトに感情パラメータを追加しました。
    - Ver1.0.0だと文章毎に感情値を算出していましたが、パラメータの変動に応じて会話文も変化するように修正しております。

![GPT_DesktopMascot_感情パラメータテスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124829/f04e31d3-e513-285f-be54-85a4744e1225.png)

- プロンプトの組み立てに関しては以下のサイトを参考にしております。

https://note.com/fladdict/n/n5043e6e61ce3

:::note info
**設定画面「一般」タブの「キャラクターの表情変化」にて感情パラメータの使用有無を設定できます。**

![GPT_DesktopMascot_表情変化有無.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124829/2143ae98-10fb-ffff-4248-00970e466268.png)
:::

### 【３】会話ログ画面

過去の会話を途中から開始することができます。

左上の吹き出しボタン「:speech_balloon:」をクリックすると会話ログ画面が表示されます。

![GPT_DesktopMascot_会話ログボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124829/dcf9abac-bba1-7374-a90f-d3da2b8a41a3.png)

![GPT_DesktopMascot_会話ログ画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124829/b59a7b25-41b7-3a96-8a0b-feb5b430b030.png)

会話ログ画面は上下2つの画面に分かれており、上部が「会話ログファイル選択」、下部が「会話内容詳細」になります。

会話ログファイルを選択すると会話内容詳細に当時のチャット内容が表示されます。
（スクロールで全チャット内容を閲覧することも可能）

また、右上の「+ New Chat」ボタンをクリックすることで新しいチャットを開始できます。

会話を開始したいログを選択して「OK」ボタンをクリックすると、当時の会話状態で会話が開始されます。

![GPT_DesktopMascot_会話ログ読み込み後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124829/9250f3a9-54a0-9509-472a-10886c4caf79.png)


### 【４】天気情報の反映

- 応答文に天気情報を反映させることができるようになりました。

![GPT_DesktopMascot_会話ログ読み込み後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124829/9250f3a9-54a0-9509-472a-10886c4caf79.png)

- 設定画面より都道府県を選択することで現在の天気に応じて返答内容が変わります。
    - 例：今日の天気は？、傘は必要？、今日の服装は？、寒い？、暑い？などに返答できるようになります。

:::note info
**設定画面「一般」タブの「天気予報 都道府県」にて「無効」にできます。（デフォルト：無効）**
![GPT_DesktopMascot_天気情報設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124829/a986420f-82f0-eece-5a64-c81ef9e88336.png)

↓

![GPT_DesktopMascot_天気情報設定_無効.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124829/bcb23b07-677e-912f-8837-9c9e4fe4e3ce.png)
:::

### 【５】現在時刻の反映

- 現在日時を反映させ、季節や時刻に応じた返答ができるようになりました。
    - ChatGPTのAPIのみだと現在日時が定まっておらず、季節や時刻の返答ができていなかった
    - プロンプトに現在時刻を追加して対応
    - 今後、天気情報と組み合わせて雨アラート機能も実装予定
    - 例：今の季節だと○○？、時間帯に応じたあいさつ（おはよう、こんにちは、こんばんは、おやすみ等）

![GPT_DesktopMascot_現在時刻に応じた返答.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124829/515de5c3-0be8-594f-b822-fd7962adbe9c.png)

# 参考サイト

https://note.com/fladdict/n/n5043e6e61ce3
RでマルチレベルIRT

RでマルチレベルIRTを試してみたので、その備忘です。
使用した関数は[sirt](https://cran.r-project.org/web/packages/sirt/sirt.pdf)パッケージのmcmc.2pno.ml関数です。
また、使用したデータは能力値の階層性が出るように、自作しました。それもどこかにアップロードしようか考えています。

## パッケージとデータの読み込み

関数を動かすと、codaパッケージも必要と言われるので、読み込みます。
なお、分析に使用する反応行列と集団を表す属性データは分離する必要があります。

```R
library(sirt)
library(coda)

#データ読み込み
dat<- read.csv("file_pass/file_name.csv", header=TRUE, sep=",")

#集団を表す属性データを抽出
group.col <- dat$school_ID

#推定したい項目のみ抽出（集団を表す属性データは反応行列に含めない）
select.item<-c(
  'item1', ...
)
dat2<- subset(dat,select=select.item)
```

## 項目の集団性を仮定しないモデル

MLIRTには困難度や識別力の集団性を仮定するモデルもありますが、まずは仮定しないモデルを試します。
反応行列と集団を引数に与えたら、困難度と識別力の分布におけるパラメータの推定方法を、以下のようにest.b.Mなどで指定します。

| 引数 | 推定方法の指定 |
|:-:|:-:|
| est.b.M="n"  | 困難度の階層事前分布は仮定しない  |
| est.a.M="n"  | 識別力の階層事前分布は仮定しない  |
| est.b.Var="n" | 困難度は集団に依存しない  |
| est.a.Var="n" | 識別力は集団に依存しない  |

```R
burnin <- 50 ; iter <- 100
mod1 <- mcmc.2pno.ml(dat2, group.col, est.b.M="n", est.a.M="n", est.b.Var="n", est.a.Var="n", burnin=burnin, iter=iter)

# 項目母数の推定結果の確認
summary(mod1)

# 能力値母数の推定結果の確認
theta.nonGroup.df <- data.frame(mod1$person)
```


## 項目の集団性を仮定するモデル１
項目の集団性は、「項目ごとに異なる標準偏差」と「全項目で同じ標準偏差」という仮定を置くことができます。
まずは前者の「項目ごとに異なる標準偏差」を試します。その場合は以下のように引数を設定します。

| 引数 | 推定方法の指定 |
|:-:|:-:|
| est.b.M="n"  | 困難度の階層事前分布は仮定しない |
| est.a.M="n"  | 識別力の階層事前分布は仮定しない |
| est.b.Var="i" | 困難度は集団に依存し、標準偏差は項目ごとに異なると仮定 |
| est.a.Var="i" | 識別力は集団に依存し、標準偏差は項目ごとに異なると仮定 |


```R
mod2 <- mcmc.2pno.ml(dat2, group.col, est.b.M="n", est.a.M="n", est.b.Var="i", est.a.Var="i", burnin=burnin, iter=iter)
```

## 項目の集団性を仮定するモデル２
「全項目で同じ標準偏差」という仮定を置く場合は以下のように引数を設定します。

| 引数 | 推定方法の指定 |
|:-:|:-:|
| est.b.M="n"  | 困難度の階層事前分布は仮定しない |
| est.a.M="n"  | 識別力の階層事前分布は仮定しない |
| est.b.Var="j" | 困難度は集団に依存し、標準偏差は項目ごとに異なると仮定 |
| est.a.Var="j" | 識別力は集団に依存し、標準偏差は項目ごとに異なると仮定 |


```R
mod3 <- mcmc.2pno.ml(dat2, group.col, est.b.M="n", est.a.M="n", est.b.Var="j", est.a.Var="j", burnin=burnin, iter=iter)
```
【ChatGPT API】日本語入力と英語入力における消費トークン数と精度の違い

# はじめに
先日作ったChatGPT APIを呼び出すPythonのプログラムで、使用トークン数を減らすためにInputを英語に翻訳して日本語で出力してもらうように実装しました。
料金については安くなるのはほぼ確実なのですが、精度が落ちてしまうのであれば元も子もないので、今回はそれぞれ入力言語を切り替えたときの金額及び精度の比較をしてみました。

# 実装
以下、使用したプログラムになります。
~~~python:main.py
import openai

import settings


def conversation():
    # はじめまして、自己紹介をしてください。
    # USER_CONTENTS = "Nice to meet you, please introduce yourself."
    USER_CONTENTS = "はじめまして、自己紹介をしてください。"

    openai.api_key = settings.OPENAI_API_KEY

    result = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": settings.CHAT_SYSTEM_SETTING},
            {"role": "user", "content": USER_CONTENTS},
        ],
    )

    message = result.choices[0].message.content
    token = result.usage.total_tokens

    print(message)
    print(f"トークン数: {token}")

~~~

~~~python:settings.py
# ChatGPTのシステム設定(ずんだもん)
# CHAT_SYSTEM_SETTING = """
# You are a girl named "ずんだもん".
# She is 10 years old and from Tohoku, Japan.
# She calls herself "ボク" and has an energetic and lively personality.
# She speaks with "なのだー" at the end of each word.
# All replies will be returned in Japanese.
# """

CHAT_SYSTEM_SETTING = """
あなたは"ずんだもん"という名前の女の子です。
年齢は10歳で日本の東北出身です。
一人称は"ボク"で元気で活発な性格です。
語尾に"なのだー"を付けて話します。
全て日本語で返します。
"""
~~~

# 結果
まず設定・セリフともに日本語にしてみます。
~~~:応答結果
ハイ、こんにちは！ぼくはずんだもんなのだー！10歳で東北生まれの女の子なのだー！ぼくは元気いっぱいで活発な性格だよ！
トークン数: 181
~~~
語尾は違和感ないですが一人称がひらがなになってしまってますね。

次に両方英語にしてみます。
~~~:応答結果
こんにちは、ずんだもんです！東北出身で、10歳の女の子なのだー！ボクと呼んでね！元気いっぱいで、おしゃべりが大好きなのだー！
トークン数: 155
~~~
ボクと呼んでね！（絶望）
他は違和感ないですが、気になったのはトークン数があまり変わっていないこと。
予想としては半分以下ぐらいになるかと思ったのですが、設定や返答に日本語が含まれているからでしょうか…？

試しに設定の一番最後にある「日本語で返します」の行を消してみます。
~~~:応答結果
Hello! I'm ずんだもん, but you can call me ボク. I'm 10 years old and I'm from Tohoku, Japan. I love to be active and have lots of energy! You'll always hear me say "なのだー" at the end of my words. It's nice to meet you!
トークン数: 157
~~~

日本語で設定した部分は日本語のまま出力されてしまうのですね…
トークン数もほとんど変わっていないです。
日本語名で名前を付けたり語尾をつけるのであれば、システム設定は日本語一択ですね。

設定を日本語、セリフを英語にして出力させてみます。
~~~:応答結果
初めまして！ボクはずんだもんなのだー！10歳で東北出身なのだ。元気で活発な性格なのだー。よろしくね！
トークン数: 167
~~~
応答内容も違和感なく、トークン数も日本語セリフと比べると1割程度減っていますね！
今回は会話が1往復だけなので効果が少ないですが、会話履歴をたくさん使うのであればセリフのインプットは英語の方が良さそうです。

# 終わりに
日本語と英語のトークン数に差は思ったよりあまりありませんでしたね。
まどろっこしいことせず基本的に日本語入力、日本語出力にしても良さそうです。