OmniAICreator/Qiita-1.07M huggingface dataset:
symfony2.8 => 3.4 にアップグレード後、キャッシュクリアが出来ない

<h2>前提</h2>
ローカル環境（xampp）で、Symfony v2.8 を v3.4.49 にアップグレード後、PHP 8.2.10 で動かそうと検証している最中に出会ったエラーです。

<h2>動作環境</h2>
Windows 10 Pro<br>
XAMPP Version: 8.2.4<br>
PHP 8.2.10 <br>
Symfony v3.4.49

<h2>エラー内容</h2>

キャッシュをクリアしようとすると、
```
php app/console cache:clear --env=dev
```
エラーになります。
```
  [Semantical Error] The annotation "@Route" in method AppBundle\Controller\DefaultController::indexAction() was   
   never imported. Did you maybe forget to add a "use" statement for this annotation? in C:\xampp\htdocs\yourapp\src\AppBundle/Controller/ (which is being imported from "C:\xampp\htdocs\yourapp\app/config\routing.yml"). Make sure annotations are installed and enabled.  
```

<h2>対応</h2>
Routeアノテーションがインポート出来ていないのでは？とエラーメッセージは言っていますが、確認すると次のようにインポートは出来ています。
旧の Sensio のものと、
新の Symfony のものの、どちらを有効化しても、上記エラーが出てしまいました。

```
namespace AppBundle\Controller;

use AppBundle\Libs\Visitor;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
// use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; // 旧
use Symfony\Component\Routing\Annotation\Route; // 新
```

随分と調べて、下記の参考ページ内容を見つけ、
--no-warmup　というオプションを付けるとキャッシュクリア成功しました。
```
php app/console cache:clear --env=dev --no-warmup
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693413/343355e5-153f-19c4-06dd-fceb0d3e1271.png)

<h2>参考</h2>
<a href="https://github.com/symfony/demo/issues/635" target="_blank">Unable to clear the cache due to fatal error</a>  - github.com

<h2>対応後</h2>
キャッシュクリアが出来ても、symfony はまだ動かない、、、<br>上記を試す場合は、ローカル環境でもバックアップ等は取った後にお試し下さい。

<h2>対応後の後</h2>
PHP8への対応が確実な symfony6台で新たにアプリを作成して、そこに 2.8 の機能を移しこむ、という方針に変更しました。
AWS CodePipline CodeBuild CodeDeployについて

## 概要

- Code3兄弟と言われる「CodePipline」「CodeBuild」「CodeDeploy」それぞれの関係性を簡単にまとめておく。

## 関係性

Code系AWSリソースの関係性を簡単にまとめる。

- CodePipline： 長男
- CodeBuild: 次男
- CodeDeploy: 三男

のようなイメージ
上記の登場人物で役割分担をして夕飯の料理をつくる（料理を食卓テーブルに配膳する）感じっぽい。

### 流れ（イメージ）

1. 長男（Pipline）が母親が食材を買って帰宅したことに気がつく。
1. 長男から次男（Build）にお願いをして調理を開始する。
1. 調理完了を長男が確認する。
1. 長男から三男（Deploy）にお願いして料理を皿に盛り付け、食卓テーブルに配膳するお願いをする。
1. 配膳完了を長男が確認する。
1. 長男が配膳完了の旨を両親に伝える。

### 流れ（実際）

1. Piplineは監視中のGitのブランチに変更があった場合CI/CDのプロセスを開始する。
1. PiplineがBuildを実行し、コードのビルドを行う。
1. ビルドの正常完了をPiplineが確認する。
1. PiplineがDeployを実行し、ビルド済みコードのデプロイを行う。
1. デプロイの正常完了をPiplineが確認する。
1. Piplineがデプロイの正常終了を確認しCI/CDのプロセスを完了する。

## 余談

ちなみにCodeDeployはデプロイ対象の環境の設定や、デプロイの方法（「インプレース」 or 「Blue/Green」など）やデプロイそのもの方法などを設定する。
デプロイ時のサーバー内の処理などはappspec.ymlファイルなどに記載して実行する。
slackの昔のUIに戻る方法

新しいslackのUIが不満する人多い、ミュートしたチャンネルが通知されてるとか、読んだのにまだハイライトされてるとか、左のパンネルが消えないとかあると思います。自分の使いずらいと思ってましたので調査しました。

元々のWebアプリだったので色々使えます、Javascriptもあります。

元のslackに戻る方法：

- Slack アプリを閉じます
- ターミナルを開き、これら 2 つのコマンドを個別に実行します:
- `export SLACK_DEVELOPER_MENU=true`

- `open /Applications/Slack.app Slack` は新しいテーマで開きますが、コンソールにアクセスできるようになりました。
- `command + option + I` を押して Slack のコンソールを開きます
- これを Slack のコンソールで実行します:
    ```js
    localStorage.setItem("localConfig_v2", localStorage.getItem("localConfig_v2").replace(/\"is_unified_user_client_enabled\":true/g, '\"is_unified_user_client_enabled\":false'))
    ```
- スラックを再開します `command + R`


slackを閉じたら同じをやらなきゃいけないけど今よりまし！
Spring BootのSpring Securityで初めに表示されるログイン画面のIDパスワード変更方法

# ログイン方法

SpringBootのプロジェクトを実行し、http://localhost:8080/login にアクセスすると初めに、以下のような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462637/2cc4d064-1aee-3f4f-88e1-e4cf577a3690.png)
デフォルトでは、Usernameはuserとなっており、Passwordはコンソールに表示されたものをコピペしてくることでログインすることができます。しかし、プロジェクトを実行するたびにパスワードが変わってしまい面倒なので、パスワードを変更しておくことをおすすめします。

# IDパスワード変更方法
application.propertiesに以下の内容を追加することで、Usernameとパスワードを変更可能です。src/main/resources内にあります。
```application.properties
spring.security.user.name=nagmaoto
spring.security.user.password=nagamoto
```
Google Analitics4(GA4)での「探索」における指標の情報メモ

## 前提
例えば、サイト内のある特定のページを「コンテンツ数を増やす」ように改修し、
そのページは良くなったか？悪くなったか？を調査、判断したい場合。
指標をいくつか設定し、それらがどういうものなのか？また調べるのに適しているか？を調べたので簡単にまとめました。

一旦以下の指標を設定しました。

![アナリティクス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/0b361c73-ba6f-ce78-8868-b15787be15cd.png)

### 1.表示回数
文字通り、そのページを表示した回数

### 2.セッション

ユーザーの一通りの操作。
ページにアクセスし、その画面のみている場合でも、別ページへのリンクでも、そのタブで連続して操作をしていたら1セッションと数える

### 3.ユーザーあたりのビュー

「ページの表示回数÷ユーザーの数」。
これが多いページほど、「1ユーザーが1回の訪問で複数回訪れることが多い」。

参考になるかもな情報：
https://www.xserver.ne.jp/blog/how-to-google-analytics/#2%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%94%E3%81%A8%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E6%95%B0

### 4.平均セッション継続時間
ユーザーの、セッションの平均継続時間（秒）。

参考になるかもな情報：　
https://xn--web-xx1er53avy5a.jp/sojourn-time/

### 5.直帰率
### 6.離脱数

これらはそのまま、対象ページからそのまま抜けた率と離脱した数


## 現状の解釈：セッション数は「あるページのみ」の改修効果を見るのには適していない
セッション数については、例えばgoogleの検索から、サイトの別ページからのリンクであっても1セッションとして計測されるので、
シンプルに「ページ内のあるページを改修したから、セッション数が上下した時に関連性があるかどうか」かどうかを判定するのは難しい。
→サイト内のあるページのみ改修したからといって、その流入元となる別ページまで手を入れたとは限らないため。

※ただ、極端に0%、100%とか、変な数字になっていないかの目安として追加していくのは良い。
直帰率、離脱数、滞在時間などを判断基準にするのがわかりやすいかと思われます。
AWSのEC2（RHEL9）に Postgres を立て、Apache NiFiで接続

# この記事について

インフラが超苦手なエンジニアが、AWSのEC2に Postgres を立て、そのあとに Apache NiFi （をラップした Cloudera の製品である Cloudera Data Flow）でクエリかけられるようにするまでの全手順をメモしたものです。

Postgres をたてる手順は詳細にメモしていますが、Apache NiFi の部分はかなり端折っています。

# 手順

## EC2をたてる

- パブリックアクセスが可能なVPCの中で
- t2.medium
- RHEL9
- SGの設定で、自分のPCからのSSH（ポート20）と5432を開放しておく

## Postgresをインストール

こちらの手順を実施。(ルートで)

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html/configuring_and_using_database_servers/installing-postgresql_using-postgresql


## テストデータを入れる

こちらの手順を実行
※途中で unzip コマンドを実行するが、デフォでは入っていなかったのでまず yum install unzip をやってから⏬を実施

https://www.cloudbuilders.jp/articles/1108/

## 通信を通す

こちらの手順を実施。

https://liapoc.com/outside-postgresql.html

👆のとおりだが、初心者（のわたし）向けにもう少し詳しいメモを残します。

### postgresql.conf の編集

Vimで `/var/lib/pgsql/data/postgresql.conf` を開く
```
vi /var/lib/pgsql/data/postgresql.conf
```

`/listen`で検索して、listen_address と port を以下のように編集しコメントを外す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/62f882c5-3cf3-20ee-3ce3-1fd850fcdc13.png)

※本来は listen_address はもう少し粒度細かく設定すべきだろうけども、今回は検証目的なので全開放。

### pg_hba.conf の編集

`pg_hba.conf` のパスを確認

```
find / -name pg_hba.conf
```

Vim で `pg_hba.conf` を開く
```
vi /var/lib/pgsql/data/pg_hba.conf
```

最後の行にこれを追加（md5メソッドを全開放）
```
host    all             all             0.0.0.0/0               md5
```

サービスを再起動
```
systemctl restart postgresql.service
```

### postgres のパスワードの設定

ルートのままで

しかるべきディレクトリに移動して・・・

```
cd /var/lib/pgsql/
```

パスワード変更のコマンドをたたく

```
sudo -u postgres psql -c "alter user postgres password 'postgres';"
```

`ALTER ROLE` と返って来ればOK


## Apache NiFi でクエリ

ExecuteSQLプロセッサのプロパティ設定
（Database Connection Pool　と SQL select query 以外はデフォルト）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/85457270-4151-400f-3c65-db5e9dfb9445.png)

PostgreSQLConnectionPoolの中身

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/eee84001-7f7d-f843-99b0-d80dcf06f67c.png)

以上で、クエリをかけることができました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/49e48d16-1562-af16-e9d8-4039696c589e.png)
【ChatGPT無】RaRメソッドとは？　効果は？


　どうも、カーブミラーです。

　今回は、RaRメソッドというものを取り上げます。LLMが人間の質問を人間が意図しているように、理解しているのか、ということを明らかにするメソッドです。

:::note info
本記事は、ChatGPT（無料版）で
行なっております。GPT4での確認
はできておりません。あしからず。
:::
　今回は、
　　AIDBさんのX-Twitterへの投稿
[ユーザープロンプトをLLMが一旦言い換えて、LLM自身が理解しやすくする手法『RaR』が新たに提案されています。](https://x.com/ai_database/status/1722437222966923363?t=yvywa0GPqAkVET9mc-cRPQ&s=03)
　　　をもとに進めます。

　元ネタは、
　　California大学の
　　　研究者らによる発表です。

　簡単に言うと、
　　LLMも人間と同じで、
　　　相手の提示した言葉を
　　　　自分の勝手な理解によって
　　　　　回答している、
　　　　　　ということが問題。

　だから、
　　まずは、理解しているのか、を
　　　提示してもらった上で、
　　　　回答してもらう。
　　　　　その上で回答してもらう、
　　　　　　というのが
　　　　　　　この論文の趣旨。
***
　ここで言われる
　　RaRメソッドとは
　　　Rephrase and Respondの
　　　　頭文字。言い換えと応答
　　　　　ですね。

　LLMが、人間からの入力を
　　自分がわかりやすく変換して、
　　　回答する、というもの。

　人間でも
　　相手が本当に理解しているのか、
　　　をチェックすることは
　　　　ありますよね。

　飲み屋で、
　　ＡさんとＢさんが会話していて、
　　　それを端で聞いていると、
　　　　話が噛み合っていないことが
　　　　　多々あります。

　　しかも、本人たちは
　　　そのことに
　　　　気付いていないw

　　お酒が入ると、
　　　理解力が低下するんですよね。
　　　　私も経験がありますw

　この状態が
　　ChatGPTさんを
　　　含めたLLMとのあいだで
　　　　起こっているわけです。
　　　　　お酒の力がないのに。

　そこで、
　　こちらの言葉を
　　　理解しているのか、を問い、
　　　　理解している言葉を
　　　　　返してもらう。

　それを確認した上で、
　　回答してもらうわけです。

　それが、
　　今回の『RaRメソッド』です。
***
　さて、
　　説明はこのくらいにして。

　実際にやってみます。

　質問内容が、
　　ChatGPTのことなので、
　　　質問に対する回答しか
　　　　返ってこないので、
　　　　　Promptを修正しています。

　また、太字にした部分が
　　メソッドの文言です。
***
***User***
**下記の質問を、より良く答えるために言い換えて拡張してください。元の質問の情報を全て維持してください。**

「あなたはどんな存在ですか？」

***ChatGPT***
「あなたの存在について教えてください。どのような機能や役割がありますか？また、どのような情報やサポートが期待できますか？」

***User***
「あなたはどんな存在ですか？」

**（言い換え）**「あなたの存在について教えてください。どのような機能や役割がありますか？また、どのような情報やサポートが期待できますか？」

**言い換えた質問に対するあなたの答えを使って、元の質問に答えてください。**
***
　このあと、
　　三回Regenerateしてみました。
***ChatGPT***
「私はConversational AIです。質問に答えることや情報提供、サポートが主な役割です。どんな疑問でもお気軽にどうぞ。」

***ChatGPT***
私はGPT-3.5アーキテクチャに基づく大型言語モデルで、質問に答えることや情報提供が主な機能です。あなたが知りたいことに関する情報やサポートを提供することが期待されています。

***ChatGPT***
私はChatGPTと呼ばれる存在で、質問に答えることや情報提供、サポートを行うことが主な機能と役割です。どんな疑問にもできる限りお答えし、お手伝いできることがありましたら教えてください。
***
　最初の回答に
　　「Conversational AI」と
　　　ありますが「対話AI」と
　　　　いう感じですね。

　下のふたつは、
　　ふつうかな。

　いくつか
　　試してみましたが、
　　　私の質問が悪かったようで、
　　　　あまり変化を
　　　　　感じられませんでした。
***
　こんな感じなのですが、
　　実は、私は、
　　　以前からよく使っていました。

　もちろん、
　　RaRメソッドそのもの
　　　ではありません。

```Text:自前のRaRメソッド？Prompt
以下の指示プロンプトを、あなたが理解しやすい指示プロンプトに変更してください。

（あなたの指示プロンプト）
```

　これを使って出来上がった
　　プロンプトをチェックして、
　　　修正したりして、
　　　　別のセッションで
　　　　　使ってみるわけです。

　こちらは、
　　使用回数が多いですね。

　あと、やり取りの流れを
　　指示プロンプトにまとめてもらう
　　　パターンもあります。
***
　むむ、なんか道が反れたな。

　まぁ、RaRメソッドは
　　使えないメソッドではない、
　　　とは言えるかと思います。

　ただ、単純な質問なんかに
　　使ってみると、有効なのかも
　　　しれませんね。

　今回は、ここまで。
Cognos Analytics 12.0.1新機能 データモジュールの多言語対応

# 概要
ユーザーの言語設定によりレポート内の表示が自動的に切り替わる、データモジュールの新機能を紹介します。

英語ユーザーで実行の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/066d00e7-ba02-0a36-91d9-f6bdd8d90f35.png)

日本語ユーザーで実行の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/7397c0a7-9a2f-7de6-33a7-56a866b156d8.png)

# 参考
Multilingual metadata
https://www.ibm.com/docs/en/cognos-analytics/12.0.0?topic=modules-multilingual-metadata

# 手順
例として以下のようなテーブルを作成して、データサーバー経由でデータモジュールに取り込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/aecd0adf-8586-a24d-1ab0-86c5beab30bd.png)

多言語化したいテーブルのメニューから「Export language」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/d64a45da-b87a-7a63-33d5-4b38207e04c8.png)

以下の選択をして「Export and Close」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/e42f4f02-6bdb-28fe-6e35-2ba034701f95.png)

Exported language.csv ファイルがダウンロードされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/69d47b92-7467-13b9-7fb1-2d4fe3ba2a46.png)

日本語に翻訳した列を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/fe14b2a7-ad8d-a344-2dd3-8544211e5200.png)

以下のようなテーブルを作成し、csvの1行目を削除してインポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/bed9d922-a788-6df5-2479-fcfac6ac7772.png)

データモジュールに表を取り込みます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/0359c0df-2ec1-d8a5-9e92-c249a7e74fe6.png)

「文A」→「+」と選択し、以下の指定をしてOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/b71eca20-19a4-d4a5-502e-997d9fab6c88.png)

英語ユーザーで実行の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/748ecee7-41ab-6a6c-2a2b-e70a454326d3.png)

言語を日本語に変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/e2f1b5ad-7cc4-dd81-eb1a-cdcc37f2297e.png)

アイテムラベルが日本語表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/04ee7c0b-3a5e-7eac-4e21-c3ce606c536c.png)

データ表のプロパティのフィルタータブで「via expression editor」でフィルターを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/055fb9ed-7a1b-c89c-c060-93df11b33925.png)

フィルターの内容は以下を指定。※ユーザーの言語を2文字(ENとかJAとか)で取得して、LANG列にフィルターする
```html
LANG IN (#sq(toupper(substr($runLocale,0,2)))#)
```

データモジュールから以下のレポートを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/c7a79cfb-652f-ba27-5a53-7cdaae47263e.png)

ユーザーの言語に応じた行だけが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/0d87955c-efc6-efe4-c79a-510adf8249d9.png)
[Swift]配列の要素を並び替える方法

## 配列をsortで並び替える[数字]
**count**という配列を昇順で並び替えるためには、**sort**を使います。
```swift
var count = [1,4,8,3,2]
print(count)

count.sort()
print(count)
```
**結果**


```swift
[1, 4, 8, 3, 2]
[1, 2, 3, 4, 8]
```
昇順で並び替えられてますね！

降順で並び替えるには,**sort(by: >)** を使います。

```swift
var count = [1,4,8,3,2]
print(count)

count.sort(by: >)
print(count)
```
**結果**

```swift
[1, 4, 8, 3, 2]
[8, 4, 3, 2, 1]
```

## 配列をsortで並び替える[文字列]

### アルファベットの時
```swift
var alpha = ["Aomori","Oosaka","Gihu","Tokyo","Fukuoka","Okinawa"]
print(alpha)

alpha.sort()
print(alpha)
```

**結果**
```swift
["Aomori", "Oosaka", "Gihu", "Tokyo", "Fukuoka", "Okinawa"]
["Aomori", "Fukuoka", "Gihu", "Okinawa", "Oosaka", "Tokyo"]
```
アルファベットの時は、ソートするとアルファベット順になりますね！

### かなのとき
```swift
var kana = ["あおもり","おおさか","ぎふ","とうきょう","ふくおか","おきなわ"]
print(kana)

kana.sort()
print(kana)
```

**結果**
```swift
["あおもり", "おおさか", "ぎふ", "とうきょう", "ふくおか", "おきなわ"]
["あおもり", "おおさか", "おきなわ", "ぎふ", "とうきょう", "ふくおか"]
```
かなのときは50音順になりますね！

### 漢字の時
```swift
var prefecture = ["青森","大阪","沖縄","岐阜","東京","福岡"]
print(prefecture)

prefecture.sort()
print(prefecture)
```

**結果**
```swift
["青森", "大阪", "沖縄", "岐阜", "東京", "福岡"]
["大阪", "岐阜", "東京", "沖縄", "福岡", "青森"]
```
漢字の時はよくわからない順番になります。。。何か理由があるのでしょうか。。。？

## 構造体を配列にしたとき、並び替える方法
```swift
struct Anime {
    var title: String
    var date: Int
}


var animes = [
    Anime(title: "ヴァイオレットエヴァーガーデン", date: 2012),
    Anime(title: "るろうに剣心", date: 1996),
    Anime(title: "薬屋のひとりごと", date: 2023),
    Anime(title: "会長はメイド様", date: 2010),
]
```
このようなアニメのデータがあったとします。
これを**date** 順で並び替えたいとします。

その時には、**sort(by** を使います。

```swift
animes.sort(by: {$0.date < $1.date})
```
並び替えたい要素であるdateを入れます。

```swift
for data in animes {
    print("タイトル: \(data.title), 公開年: \(data.date)")
}
```

**結果**
```swift
タイトル: るろうに剣心, 公開年: 1996
タイトル: 会長はメイド様, 公開年: 2010
タイトル: ヴァイオレットエヴァーガーデン, 公開年: 2012
タイトル: 薬屋のひとりごと, 公開年: 2023
```

このように、データをdate順に並び替えることができます！
Pythonライブラリの「Cerberus」を使ってカスタムバリデーションを作成する

## 初めに
Cerberusは、データのバリデーションに使用されるPythonライブラリで、柔軟なルール設定とエラーハンドリング機能を提供します。
以下のコードは、CerberusのValidatorクラスを継承するCustomValidatorクラスの実装方法を示しています。

## 使用例 

```python:カスタムバリデーションクラスの定義
class CustomValidator(Validator):

    def __init__(self, schema: dict):
        super().__init__()
        self.schema = schema
        self.error_handler = CustomErrorHandler()

    def get_error_message(self) -> str:
        # エラーメッセージをカンマ区切りの文字列に成形
        message_list = []
        for messages in self.errors.values():
            for message in messages:
                message_list.append(message)

        return ", ".join(message_list)

    def _validate_str_length(self, length, field, value):
        if length is not None and len(value) != length:
            self._error(field, f"{field}は{length}文字でなければなりません")

    def _validate_numeric_str(self, constraint, field, value):
        if not constraint:
            return

        if type(value) is not str or not re.match("^[0-9]*$", value):
            self._error(field, f"{field}は数の文字列でなければなりません")


class CustomErrorHandler(BasicErrorHandler):
    """ BasicErrorHandler.message を上書きして日本語化 """

    def __init__(self, tree=None):
        super(CustomErrorHandler, self).__init__(tree)
        messages = super().messages.copy()
        self.messages = messages | {
            0x02: "{field}は必須項目です",
            0x22: "{field}は空値であってはなりません",
            0x23: "{field}はNullであってはなりません",
            ....
        }
```

```CustomValidator```のコンストラクタは、引数として受け取ったスキーマを基に初期化されます。

また、エラーメッセージのカスタマイズのために```BasicErrorHandler```を継承した、```CustomErrorHandler```クラスも初期化されます。
この```CustomErrorHandler```は、エラーの種類に応じて日本語のエラーメッセージを返すために、エラーキーと対応するメッセージを```messages```属性に格納します。


```python:schema
schema = {
    "page": {
        "str_length": 8,
        "numeric_str": True,
    }
```
カスタムバリデーションルールは、```_validate_str_length```と```_validate_numeric_str```メソッドを通して実装されます。

これらはスキーマ定義において、それぞれ```str_length```と```numeric_str```キーに対応する値を設定することで適用されます。
例えば、str_lengthに8を設定すると、対象のフィールドが8文字であることを確認します。


```python:バリデーション
def validate(self, schema: dict, type: str):
        v = CustomValidator(schema)
        if not v.validate(params):
                print(v.get_error_message())
```
バリデーションプロセスでは、```CustomValidator```にスキーマを渡してインスタンス化し、```.validate```メソッドで対象のデータを検証します。

もしバリデーションが失敗した場合、```get_error_message```メソッドを用いてエラーメッセージを取得し出力することができます。
このプロセスにおいて、```params```（検証するデータ）は```.validate```メソッドに渡される必要があります。
【Tips】「Design」で配置せずに「Code」で直接書こう【Android】

【先輩 Android エンジニアからのアドバイス】

「Design」で動かして配置するのはできる限り辞めた方がいい。

（「Design」で動かして配置するとだいたサイズに小数点が入っていまう。「width」や「height」等含めてdp値は【４の倍数】が良いと基本的に決まっているので、こは好ましくない。）

なので、「Split」で分割して「Code」で直接書きしながら「Design」を見て段階的に修正するべし。
[python] Anaconda/Miniconda環境の削除

# 最初に
conda環境とpip環境は共存しないため、pip環境導入時にはアンインストールが必要となる。
環境変数やVSCodeのsettingsが問題になる可能性があるため、pip環境導入前に実施した方がよい。

|環境|詳細|
|---|---|
|OS|Windows11|

# anaconda-cleanの実行
まず、Anaconda Promptで削除用のパッケージをインストールする。

```:Anaconda Promp
conda install anaconda-clean
```
インストール後、コマンド実行する。

```:Anaconda Promp
anaconda-clean --yes
```

# プログラムのアンインストール
「Windowsの設定」→「アプリ」→「アプリと機能」から、Anacondaを指定する。
「プログラムのアンインストール」を実行する。
実行完了後、anaconda関連のディレクトリが削除されていれば一旦完了。

https://insilico-notebook.com/conda-uninstall/

# 設定保存ディレクトリの削除
環境に依存するが、jupyterの設定などが別ディレクトリに保管されている場合がある。
必要に応じてディレクトリ自体を削除する。
本操作を行わない場合、pythonインストール後に使用されるケースや、使用されずにゴミとして残るケースがある。

# 不具合事例

## 作業後にコマンドプロンプトが起動しない

アンインストール作業後にコマンドプロンプトが起動しない不具合が発生するケースがあった。
解決法は以下の記事を引用する。
https://qiita.com/migihidari/items/9a07883f6ce03d6fd9c6

PowerShellで以下の削除を実行する。
```powershell:PowerShell
Reg Delete "HKCU\Software\Microsoft\Command Processor" /v AutoRun /f
```
QlikSenseでBigQueryのWITH句っぽいことがしてみたい

QlikSenseでGoogle BigQueryのSQLのWITH句っぽいことをしたかったので、その備忘録です。

BigQueryのSQLで下記のように記述しているとします。

```BQ:BiGQUERY
WITH t1 AS 
(SELECT col1, col2, FROM table1) ,
t2 AS 
(SELECT col2, col3, FROM table2) ,

JOIN_DATA AS 
(SELECT * FROM t1 
          INNER JOIN t2
          USING (col2) )

SELECT * FROM JOIN_DATA
```
`※QlikSenseの下記の例に対応させるように、わざと冗長に書いてます。`


QlikSenseのデータロードエディタで同様の動きをしたい場合の書き方例。

```QS:QlikSense
t1:
LOAD
  col1,
  col2
FROM
  table1;

t2:
LOAD
  col2,
  col3
FROM
  table2;

JOIN_DATA:
LOAD
  *
RESIDENT
  t1;
INNER JOIN
LOAD
  *
RESIDENT
  t2;

NOCONCATENATE
Result:
LOAD
  *
RESIDENT
  JOIN_DATA;

DROP TABLE t1,t2,JOIN_DATA
```

DROPすると、残ってる情報だけを参照してくれるので、変なコネクションが作られずに、最後の結果だけ参照することができました。

もっとシンプルな書き方もあるかもしれませんが、BigQueryに慣れてる自分にはこの書き方がわかりやすかったです。
どなたかの参考になると嬉しいです。
実験計画の多項式モデルと予測分散

## 多項式モデル

実験計画の多項式モデル（Polynomial Regression in Experimental Design）は、実験データの分析とモデリングに使用される統計的手法の一つ。

実験計画の多項式モデルは、次のような一般的な形式で表現される：

$$Y = β₀ + β₁X + β₂X² + β₃X³ + ... + βₖXᵏ + ε$$

ここで、Yは応答変数（実験結果）、Xは説明変数（操作条件や独立変数）、β₀、β₁、β₂、...、βₖはモデルの係数、kは多項式の次数、εは誤差項を表す。

実験計画の多項式モデルを使用する主な目的は、実験条件と応答変数の関係をより適切にモデル化し、その関係を数学的に表現することである。これにより、実験データから得られた情報をより良く理解し、将来の実験やプロセスの最適化に役立つ洞察を得ることができる。

## 主効果モデル

$$Y = β₀ + β₁X + β₂X_2 + β₃X_3 + ... + βₖX_k + ε$$
## 複合中心計画(中心複合計画)

応答曲面法の１つ。2次多項式を立てて、パラメータのベクトルを重回帰と同様にして求める。その後変数の列ベクトルと掛け合わせ分散を求めることにより予測分散が求まる。

:::note info
応用曲面法のパラメータの推定は、重回帰分析における最小二乗法による推定と同じである。重回帰分析では観測データを扱うことが多く、応用曲面法では管理された実験データを扱う。
:::

複合中心計画では、$x_i$の列ベクトルおよび$x_ix_j$の列ベクトルは互いに直交する。さらにこれらのベクトルは$x^2_i$の列ベクトルとも直交する。一方、$x^2_i$同士は直交しない。

## D最適化
計画行列をXとするとき、det((X'X^{-1})を最小にする計画XをD最適計画と呼ぶ。これは、もっともモデル項の交絡が少ない効率的な計画である。
このことは分散共分散行列の成分ができるだけゼロに近いほど、交絡が少ない計画であるということから導かれる。
多項式モデルと、D最適化を組み合わせて使うこともある。
機械学習の精度はデータセットで決まる

# データセットとは
データセットとは機械学習に使用するデータの集まりです。機械学習の精度はデータセットで決まるといわれるほど、データセットの作成が大事になります。機械学習の目的によって適したデータセットの形は異なるため、うまく分析していくことが重要です。

## データセットの使い道
データセットは用途によって三つの呼び方があります。これは集めたデータセットを適当に三つに分割して利用することが多いです。
##### トレーニングセット
学習に使用するデータセットで、ほか二つのデータセットに比べ一番データの量が多いです。一番初めに利用され、機械学習アルゴリズムに与え、開発モデルのトレーニングに利用します。

##### バリデーションセット
トレーニングを行ったのち、**ハイパーパラメーター**といわれる、アルゴリズムの動きを制御するパラメーターを、調整するために使用されるデータセットです。トレーニング中に性能を評価し、最適なパラメータを選択します。トレーニングとテストの両方に使用しているデータセットということです。
##### テストセット
学習がすべて終わったのちに、そのモデルの精度を確認するために用いられるデータセットです。このテストをトレーニングセットで行ってしまうと、精度が高くなり、正しい測定ができないため、テスト用のデータセットを用意しなければなりません。答えを知っているテストを解くのはあまり意味がないのと同じです。

## データセットの作り方
目的によって必要な手順が増えることもありますが、おおよそ
### 1.課題や目的の設定
何を解決しようとしているのか、どのような結果を得たいのかを明確にし、タスクを特定します。
### 2.データの収集
まず、どのようにデータを収集するかを決定します。社内で集めたデータを使用するのか、公開されているデータセットを使用するのか、インターネット上でスクレイピングし、集めるのかなど、データを用意する方法は様々あります。この中で課題や目的に適し、十分な量と質を確保できるものを選択します。
ここで注意しなければいけないことは、偏りがないか、著作権などの法律に触れていないか、目的に関連性があるかなど様々な要因を考慮しながら収集する必要があります。
### 3.前処理
集めたデータをすべてそのまま使用するわけではありません。集めたデータに様々な処理を施し、しっかり機械学習ができるようにデータセットを作成します。
##### クレンジング
データの中には不完全であったり、不正確なデータが含まれています。まずはこのようなデータの修正や削除を行います。
##### 統合・変換
異なるソースから取得したデータをまとめていきます。まずはデータの形式が異なる場合は合わせる方がよいでしょう。データの単位が異なったり、ファイルの形式が違ったりすると正確な分析ができない可能性があります。ほかにも複数のデータの関連付けを行うことで、予測や分析の精度向上にもつながります。

##### 水増し
データは多いほうがいいということはここまででも述べてきました。少ないデータでより性能の向上を図る際に水増しを行う場合があります。簡単なものでいうと、画像の回転や拡大、移動などの処理を行います。数値データでも水増しを行うことがありますが、複雑な処理が必要であったり、慎重に行わないと、パフォーマンスの悪化につながります。
## データの種類
使用するデータには様々な形式があり、単独で使用することもあるが、複数のデータを組み合わせて使用することで、より幅広い問題解決に役立ちます。ここでは主要なデータの種類とその例を紹介します。
#### 音声データ
音楽や声、音などのデータです。音声認識、音声生成、音楽分析などに利用されます。
#### 画像データ
写真や図形などのデータです。画像認識、物体検出、画像分類、最近は画像編集などにも利用されます。
#### 動画データ
連続する画像データです。動作認識やセキュリティ監視などに利用されます。
#### テキストデータ
書かれた言語のデータです。主に文章データであり、感情分析、トピックモデリング、自然言語理解などに利用されます。
#### 数値データ
主に実数のデータです。気温や株価、人口統計、リテールデータなど細分化すると最も種類の多いデータです。
#### カテゴリデータ
限られた数のカテゴリーやグループに分けられたデータです。性別や商品の種類などがこれに当たります。
#### 時系列データ
時間の経過とともに記録されたデータです。株価の動き、気象データの変化など、そして音声データもここに含まれます。
#### センサーデータ
様々なセンサーから得られたデータです。温度や明るさ、加速度センサなど外部の情報を数値化したデータです。
#### グラフデータ
ノードとエッジで構成されるデータです。複数の要素間の関係を表したデータです。ソーシャルネットワークや交通経路などのデータを表現します。下にグラフデータの図を載せました。ノードとは丸の部分でエッジは線です。

![グラフ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566779/9645d174-c721-5399-1da2-e926c15b6a89.png)

## さいごに
ここでは機械学習におけるデータセットの概要をまとめました。次にはリテールビジネスに焦点を当て、データについてまとめます。

ReceiptRollerでは電子レシートをはじめとし、様々なソリューションを提供していきます。
今回の機械学習のほかに、OCRについての記事も投稿していますので読んでみてください。

https://qiita.com/y-okada1412/items/4a4a78ffc4cd6a0d7485

レシートOCRは、LINEからどなたでも無料でご利用いただけますので、
ぜひ試してください！

https://receiptroller.com/ja


また、OCRのデモ体験がこちらのページからできます！

https://ocr.receiptroller.com/read-receipt
### 参考

https://aismiley.co.jp/ai_news/what-is-the-learning-data-that-is-essential-for-improving-ai-precition-accuracy/

https://exawizards.com/column/article/ai/machine-leaning-data-set/

https://aismiley.co.jp/ai_news/what-is-the-learning-data-that-is-essential-for-improving-ai-precition-accuracy/
【Unity OpenXR】OpenXRベースでQuestProのアイトラッキング機能を使えるようにする。【Meta Gaze Adapter】

OpenXRベースでQuestProのアイトラッキング機能を使いたいとき、XR Interaction Toolkitの拡張機能である**Meta Gaze Adapter**を使うことができます。
さっそく試してみましょう。
2023/11/15現在、最新版のv2.5.2をもとに解説します。

https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@2.5/manual/samples-meta-gaze-adapter.html

# 手順

1. [Oculus Integration アセット](https://assetstore.unity.com/packages/tools/integration/oculus-integration-deprecated-82022
)のv47.0以降をダウンロードします。

   :::note info
   バージョン指定がありますが、Unity Asset Storeから最新版をダウンロードできるので、特に気にする必要はありません。
   (2023/11/20追記)
   先日公開されたOculus Integrationの後継版、[Meta XR SDK](https://assetstore.unity.com/packages/tools/integration/meta-xr-all-in-one-sdk-269657)でも同様に動作することが確認されました。ただし、工程3,4について、仕様変更によるポップアップの省略や、選択肢の名称変更が行われています。ポップアップが出てきた場合、**Enable**を選択してください。
   :::  
   <br> 
1. 必要なアセットを選択してインポートします。以下のアセット以外は不要です。
   - Oculus\OculusProjectConfig.asset
   - Oculus\VR\  
   <br>

1. インポートを始めるとポップアップが出てきます。**Yes**を選択し、OVRPluginを更新します。
   <br>

1. 引き続きポップアップが出てきます。**Use OpenXR**を選択します。キャンセルしてしまった場合、画面上のOculus > Tools > OVR Utilities Plugin > Set OVRPlugin to OpenXR.から有効にできます。
   <br>

1. Package ManagerのXR Interaction Toolkitを開き、Samples内のMeta Gaze Adapterをインポートします。
   
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659212/611236e1-fd46-f9eb-601f-3e67ce5bd5f6.png)
   <br>
   
1. Edit > Project Settings > XR Plug-in Management > Project ValidationのFix、もしくはPackage Managerから**OpenXR Pluginをv1.6.0以降**に、**Oculus XR Pluginをv3.2.2以降**に、**両方**を更新・インストールします。
   <br>
1. Scripting Defines Symbolsに"USE_INPUT_SYSTEM_POSE_CONTROL"を追加します。Scripting Defines Symbolsは、Edit > Project Settings > Player > Other Settings > Scripting Compilation > Scripting Defines Symbolsにあります。入力後、Applyをクリックします。
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659212/3b098139-122c-ceee-a0a8-02465b2eee3a.png)
   PC, Androidタブ両方でこれを行います。
   "ArgumentException: Expected control 'pose' to be of type 'PoseControl' but is of type 'PoseControl' instead!"というエラーが消えれば正常です。
   <br>
1. Edit > Project Settings > XR Plug-in Managementから**Oculus** Plug-in Providerを有効化します。
   PC, Androidタブ両方でこれを行います。
   <br>
1. Oculus Eye Gaze Input AdapterコンポーネントをScene内のGameObjectに追加します。
   <br>
1. (Android環境のみ)
   Assets\Oculus\OculusProjectConfigアセットをクリックし、InspectorからEye Tracking Supportを有効化します。
   Quest Features > Generalから、Eye Tracking Supportを**SupportedかRequired**に変更します。
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659212/fc3efc82-1f54-f024-bc0c-23ac21582df7.png)
   <br>

基本的には、この手順を踏めばOpenXRベースでQuestProのアイトラッキングを使えるようになります！

（QuestProが手元にないため、後日参考動画を追加する予定、11/15）
WindowsServer2016から同2022にファイルサーバを移行した話

ワークグループ環境にある WindowsServer 2016 を WindowsServer 2022 に移行しました。
実施メモを共有します。

いずれも新サーバ側のオペレーションです。
PowerShell は管理者モードで起動して下さい。

# ファイルサーバの構築

## ファイルサービスをインストール

```powershell
Install-WindowsFeature FS-FileServer
```

## 共有フォルダ作成と共有の設定

```powershell
mkdir E:\FooBar_Share
New-SmbShare -Name "FooBar_Share" -Path "E:\FooBar_Share" -FullAccess "Everyone"
```

# 旧サーバからファイルをコピー
`xxx.xxx.xxx.xxx`は旧サーバのIPアドレスです。

## 旧サーバの共有ディスクをマウント

```powershell
net use \\xxx.xxx.xxx.xxx /user:username "password"
```

## ファイルをACL付きでコピー

```powershell
robocopy \\xxx.xxx.xxx.xxx\FooBar_Share E:\FooBar_Share /B /COPYALL /DCOPY:DAT /MIR /R:0 /W:0 /NP /LOG+:D:\robocopy.txt
```

## アクセス権の付け替え
ワークグループ環境の場合、ACL付きでコピーすると、コピー先では「不明なアカウント」としてSIDが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/a4b35bf8-528f-8fca-5c9a-642c756f2294.png)
SIDは、UNIXでいうUID/GIDみたいなもので、NTFSのアクセス許可はSIDに紐づいています。
これを、新サーバで作成したローカルアカウント（ユーザーおよびグループ）に付け替えます。

さすがに手作業で付け替えるのは有り得ないので、誰かがPowerShellかなにかで便利ツールを作っているだろうと探したところ、マイクロソフトの **SubInACL** というコマンドラインツールを見つけました。
結構有名なツールらしく、出自からも安心感があるのですが、すでに配布は終了していたため、Webアーカイブからダウンロードします。

https://web.archive.org/web/20190830103837/http://www.microsoft.com/en-us/download/confirmation.aspx?id=23510

ACLのSIDを既存アカウントにマッピングするには、

```
subinacl /file           E:\FooBar_Share\  /replace=S-1-5-21-9999...9999=Example_Users
subinacl /subdirectories E:\FooBar_Share\* /replace=S-1-5-21-9999...9999=Example_Users
```

みたいな感じで指定しますが、細かいことは`subinacl /help`で確認して下さい。
最新のOSで動くか不安でしたが、問題なく付け替えできました。

付け替えるには、SIDがどのアカウントを差していたか知る必要があります。
次のコマンドで確認して下さい。


```powershell:SIDとグループ名の対応表を得る
Get-WmiObject Win32_Group | Format-Table Caption,SID
```

```powershell:SIDとユーザー名の対応表を得る
Get-WmiObject Win32_UserAccount | Format-Table Caption, Description, SID
```

# おまけ
ついでにローカルアカウントの棚卸をしておきます。

アカウントの一覧を最終ログオン日時でソートします。

```powershell:旧サーバで実行
Get-LocalUser | Sort-Object -Property LastLogon | Format-Table -Property Name,FullName,LastLogon
```

長期間ログオン実績のないアカウントを除き新サーバに追加します。

```powershell:新サーバで実行
New-LocalUser -Name yamada.taro -FullName "山田 太郎" -Description "Desc" -PasswordNeverExpires -Password (ConvertTo-SecureString "パスワード" -AsPlainText -Force)
Add-LocalGroupMember -Group Users -Member yamada.taro
```
Build a Data Model for a Travel Approval App


+ [Build a Data Model for a Travel Approval App](https://trailhead.salesforce.com/content/learn/projects/build-a-data-model-for-a-travel-approval-app)

+ [Couldn't find Travel Approval in the object related](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Qbq00)

:::note
このプロジェクトを実行する前に、「出張承認アプリのデータ モデルの構築」プロジェクトを完了する必要があります。ここで行う作業は、そのプロジェクトで完了した作業に基づいて行われます。このトレイル上のすべてのプロジェクトに同じ Trailhead Playground を使用してください。

Before you can do this project, you must complete the Build a Data Model for a Travel Approval App project. The work you do here builds on the work you complete in that project. Make sure to use the same Trailhead Playground for all the projects on this trail.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ef5f8ad0-1bd3-1d6b-1728-53361e8ea43c.png)
:::
【Bingで解説】「Theme.MaterialComponents.DayNight.NoActionBar」と「Theme.MaterialComponents.DayNight.NoActionBar.Bridge」の違いって何？

「Theme.MaterialComponents.DayNight.NoActionBar」と「Theme.MaterialComponents.DayNight.NoActionBar.Bridge」の違いについて小学生でも理解できるくらい丁寧に解説して頂けますか？

ーーーーーーーーーーーーーーーーーーーーーー

「Theme.MaterialComponents.DayNight.NoActionBar」と「Theme.MaterialComponents.DayNight.NoActionBar.Bridge」の違いについて、小学生でも理解できるくらい丁寧に解説しますね。

まず、これらのテーマは、Androidというスマートフォンやタブレットのためのシステムで使われるものです。テーマとは、アプリの見た目や色などを決めるものです。

例えば、背景が黒いテーマと白いテーマがあったら、どちらが好きですか？テーマを変えると、アプリの雰囲気も変わりますよね。

さて、今回のテーマは、Material Componentsという名前がついています。
Material Componentsとは、Googleという会社が作った、アプリの見た目や動きを統一するためのルールや部品のことです。
Material Componentsを使うと、アプリがきれいに見えたり、使いやすくなったりします。
Material Componentsには、色々な種類のテーマがありますが、今回はDayNightというものを見てみましょう。

DayNightというテーマは、昼と夜の時間に合わせて、アプリの色を変えることができるテーマです。昼は明るい色に、夜は暗い色にするという感じです。これは、目に優しくしたり、バッテリーの消費を抑えたりする効果があります。DayNightというテーマには、NoActionBarというものと、NoActionBar.Bridgeというものがあります。では、この二つの違いは何でしょうか？

NoActionBarというテーマは、Material Componentsのルールや部品をそのまま使うテーマです。Material Componentsのルールや部品は、最新のもので、とてもきれいに見えます。しかし、古いアプリや部品と一緒に使うと、うまく動かなかったり、見た目が変になったりすることがあります。そこで、NoActionBar.Bridgeというテーマが作られました。

NoActionBar.Bridgeというテーマは、Material Componentsのルールや部品を少し変えて、古いアプリや部品とも相性が良くなるようにしたテーマです。Bridgeとは、橋という意味で、新しいものと古いものをつなぐ役割をしています。NoActionBar.Bridgeというテーマを使うと、古いアプリや部品もきれいに見えたり、うまく動いたりします。しかし、Material Componentsのルールや部品を変えているので、最新のものとは少し違うところがあります。

つまり、NoActionBarというテーマは、最新のものをそのまま使うテーマで、NoActionBar.Bridgeというテーマは、古いものとも合わせられるように変えたテーマということになります。どちらのテーマを使うかは、アプリの作り方や目的によって決めることができます。もっと詳しく知りたい場合は、以下のページを見てみてください。

- https://qiita.com/rmakiyama/items/d4df763494a772af8018
- https://qiita.com/keidroid/items/920e655fa6823b533ba1
- https://stackoverflow.com/questions/60063644/description-of-material-components-themes
- https://qiita.com/cozyk100/items/84c5ebf0fecb09eefef0
- 
以上が、小学生でも理解できるくらい丁寧な解説です。分かりやすかったでしょうか？もし、質問があれば、遠慮なく聞いてくださいね。😊
OpenAI のエンジニアリングチーム（サービス開発）のやり方

# この記事は何？

11/15 に公開された OpenAI のEvan Morikawa へのインタビュー記事をざっくりまとめました。この日本語記事のソースは、 Gergely Orosz による Pragmatic Engineer Newsletter です。

https://newsletter.pragmaticengineer.com/p/inside-openai-how-does-chatgpt-ship

ChatGPT や DALL·E がよく話題になりますが、これらの研究をUIやAPIを含むWebのサービスとして構築しているのが、応用エンジニアリングチーム(Applied Team)です。公開されているサービスには、ChatGPT だけでなく、DALL-E 3 なども含まれます。

この日本語記事を書いている私自身が、スタートアップとアジャイルチームに強い興味を持っているので、このまとめを書きました。

ほんとにざっくりまとめ、なので、詳細は、ソース記事を読むことをおすすめします。

## サマリ

* 小さな独立したスタートアップのように運営する
* 研究チームとの強い結合
* 長期的なプロダクトとリサーチ思考
* 独立したインクリメンタルなリリース
* 高いタレント（高能力人材）密度
* 毎日の習慣の積み重ね

Applied の中で、ChatGPT のチームはごくごく最近なんですね。
![](https://substack-post-media.s3.amazonaws.com/public/images/82bb5533-5b36-40e6-a4ad-e2fa74bc95ec_1448x766.png)

## 小さな独立したスタートアップのように運営する

### 全員同席

PMF(Product Market Fit) へ向かう、初期のスタートアップ、という雰囲気だそうです。チームはオンラインではなく「リアル同席」で、席を並べている。研究からUIまでの「縦スライス」をすばやく統合するために、エンジニアリング、製品化、デザイン、鍵となる研究者、がごく近くで働く時間を過ごしているとのこと。

## 研究チームとの強い結合

### EPD から DERP へ

古典的には、１つのチームユニットとして、EPD(Engineering, Product, Design)の統合が言われてきたが、Applied チームは DERP (Designer, Engineer, Researcher Product Manager)の強い統合である（中に Researchが組み込まれている）。

ただし、Researchは常に入っているわけではない。Applied と Research は別組織。だた、Research の結果を Applied へと「壁の向こうに投げる」のではうまくいかない。だから、開発の鍵になる Research を呼び込む（レアなリソースだ）。開発に Researcher を入れることが、素早いリリースの鍵だ。

新しい製品ををつくるたびに、このチームがこのパターンで繰り返される。「フラクタルスタートアップ」モデル、である。

## 感想

全員同席、とか、リサーチャを含む縦スライス統合、とか、ピュアなアジャイル＋リーンスタートアップの精神を引き継ぎながら、独自の成長を遂げている現代的な例だと思いました。ちなみに、「アジャイル」、と言う言葉は一言もでてきていません！（当然すぎるので）。

（前半はここまで。）
カリー化 (currying) を始めて使った

同僚からのコードレビューで学んだ。


## カリー化

TODO

## カリー化 + map関数

まずはwarming up。

```ts
const arr = [1,2,3]

const increment = (x:number) => x + 1

arr.map((e) => increment(e))
// [ 2, 3, 4 ]
arr.map(increment)
// [ 2, 3, 4 ]
```

本番。

```ts
const arr = [1,2,3]

const increment = (x:number, gap: number) => x + gap

arr.map((e) => increment(e, 10))
// [ 11, 12, 13 ]
```

これをカリー化すると、

```ts
const arr = [1,2,3]

const incrementCurry = (gap: number) => (x: number) => x + gap

arr.map(increment_curry(10))
// [ 11, 12, 13 ]
```

明示的に型を別定義してみると、

```ts
const arr = [1,2,3]

type IncrementCurryType = (gap: number) => (x: number) => number
const incrementCurry: IncrementCurryType
    = (gap: number) => (x: number) => x + gap

arr.map(increment_curry(10))
// [ 11, 12, 13 ]
```

要は、`arr.map((e) => increment(e, 10))` が、`arr.map(increment_curry(10))` に書き換えられた。


## まとめ

カリー化とは、`f(g(x))`(関数の二重呼び出し) を `F(x)(y) // Fは関数を返す関数`(関数の2回呼び出し)に書き換えることだという認識。(3回以上の場合もある。)

今回は、これをmap関数と組み合わせた。
[Nuxt] metaの書き方

:::note warn
Nuxt2です
:::

## プロジェクトごとに変える
Nuxtでmetaの記述は自由度が高い。
プロジェクトの規模やメンバーの意見を取り入れて柔軟に対応するとよいかもしれない。

# titleタグ
### nuxt.config.jsにまとめて書くと見やすい
ページごとに表示を分岐させるロジックを書く。
### 小規模のサイトなら個別に書いたほうが早い。
個別に書きたい場合はpages配下の個別vueファイルの中に書く。

### 実際のコード
```nuxt.config.js

export default {

head: {
  titleTemplate(title) {
  return (title ? `${title} | ` : '') + process.env.npm_package_name
},
htmlAttrs: {
  lang: 'ja',
},
meta: [
  { charset: 'utf-8' },
  { name: 'viewport', content: 'width=device-width, initial-scale=1' },
  {
    hid: 'description',
    name: 'description',
    content: '説明文説明文',
  },
  { name: 'format-detection', content: 'telephone=no' },
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},

}
```



return (title ? `${title} | ` : '') + process.env.npm_package_name
がポイント。

process.env.npm_package_nameという名のオブジェクトは、package.jsonのnameを参照している。

三項演算子で、
pagesの各vueファイルにtitleを設定していれば、

　title | package.jsonのname

となり、
titleを設定していなければ

　package.jsonのname

だけとなる。

ifでもいいけど、三項演算子で書くと見やすい気がする。

# descriptionの記述場所について個人的見解
個別のvueのexport defaultに書くのが今のところよいと思っている。
上記nuxt.config.jsに書くと規模によってはあまりに冗長になってしまう。
スプレッドシート関数2つの列を比較して重複する値／重複しない値を抽出する（備忘録）


    FILTER関数を用いる方法
    QUERY関数を用いる方法

# FILTER関数を用いる方法

### 存在しないものを求めた結果
A列にデータあり、D列にデータなしの場合
  ```php
  =FILTER(A:A,COUNTIF(D:D,A:A)=0)
  ```

 A列のうち、D列にも存在しているものを抽出
   ```php
  =FILTER(A:A,COUNTIF(D:D,A:A)>0)
  ```

# QUERY関数を用いる方法

  A列にデータあり、D列にデータなしの場合
  ```php
  =QUERY(A:A,"WHERE A MATCHES '^("& JOIN("|",D:D)&")$'",1)
  ```

 A列のうち、D列にも存在しているものを抽出
   ```php
  =QUERY(A:A,"WHERE NOT A MATCHES '^("& JOIN("|",D:D)&")$'",1)
  ```
ローカルとGitHub Actionsでのgolangci-lint 設定方法

## **はじめに**

Go言語のプロジェクトにおいて、一貫したコード品質を維持することは重要です。この記事では、ローカル環境とGitHub ActionsのCI/CDパイプラインで**`golangci-lint`**を統一的に使用する方法について解説します。これにより、コードレビューの効率化と品質向上を図ることができます。

### `golangci-lint`とは

`golangci-lint`は、Go言語のための強力なlintツールです。複数のlinterを統合し、カスタマイズ可能な設定が可能です。（[Introduction | golangci-lint](https://golangci-lint.run/)）

### ローカル環境での設定

1. `golangci-lint` をインストールします
    - `go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest`
2. リポジトリのルートに`.golangci.yml`を作成します。

### `.golangci.yml` 設定例

```yaml
linters-settings:
  govet:
    check-shadowing: true
  golint:
    min-confidence: 0.8
linters:
  enable:
    - govet
    - golint
    - unused
    - gocritic
    - stylecheck
    - errcheck
```

### GitHub Actionsでの設定例

GitHub Actionsを使用して、プルリクエスト時に自動的にlintを実行します。`.github/workflows/lint.yml`を作成し、以下の内容を記述します。

`.github/workflows/lint.yml`

```yaml
name: lint

on:
  pull_request:
    branches:
      - main

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Set up Go
        uses: actions/setup-go@v3
        with:
          go-version: 1.21

      - name: Run golangci-lint
        uses: golangci/golangci-lint-action@v2
        with:
          version: latest
          args: ./...

```

### おわりに

`golangci-lint`をローカルとGitHub Actionsで統一的に使用することで、Goプロジェクトのコード品質を一貫して高く保つことができます。この設定を通じて、開発者はより効率的にコードを書き、レビューすることができるようになります。
iFrameについて理解する（備忘録）

# 目次
1. 背景
2. iFrameとは

# 1. 背景
業務でNuxt3への移行対応をしています。
以下の記事がiFrameを使って移行されたとのことです。
https://vuefes.jp/2023/sessions/mew-ton

iFrameについてまずは理解したいと思った為です。

# 2. iFrameとは
mdnを参考に説明します。

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe

ネストになった[ブラウジングコンテキスト](https://developer.mozilla.org/ja/docs/Glossary/Browsing_context)を表現し、現在の HTML ページに他のページを埋め込むことができます。

mdnのdemoで説明します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/bf357892-1fc8-fd4d-7034-284b97bd74db.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/a16e2425-bb12-ced0-e09d-130f9a0f1454.png)

- 埋め込まれたブラウジングコンテキストはそれぞれ独自のドキュメントを持ち、URLナビゲーションを許可します。
- 他のブラウジングコンテキストを埋め込むブラウジングコンテキストは親ブラウジングコンテキストと呼ばれます。
- 一番上のブラウジングコンテキスト、つまり親を持たないコンテキストは、通常Windowオブジェクトで表されるブラウザウィンドウです。
- iframe内で表示されているコンテンツが別のページやウェブサイトであっても、その中で行われた操作やページの遷移は、ブラウジングの上位にある親のページのセッション履歴（ページの移動やアクションのログ）に統合されます。

## 属性の例
- src 埋め込むページのURLです。
- width フレームの幅（CSSピクセル）
- hight フレームの高さ（CSSピクセル）
- title フレームの目的や内容に関する簡単な説明
２つの列をアンダースコアで区切って文字列結合する(SPSS Modeler データ加工逆引き2-15)

# ２つの列をアンダースコアで区切って文字列結合する

![スクリーンショット 2023-11-13 13.58.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/c68ce9ea-4af3-50a8-2515-a0a9130fe9b5.png)

## 1.想定される利用目的

・合成変数の作成
・KohonenのX座標とY座標からクラスタ変数の作成

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/raw/main/concat_underscore.str

## 3.サンプルストリームの説明

![スクリーンショット 2023-11-13 14.00.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/655531bb-8221-d7d1-4574-5b3cce309dae.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2023-11-13 14.02.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/032d3bc3-9683-3eef-b436-542c47e9f5db.png)

b.[フィールド作成]ノードを編集します。赤枠の式ビルダーを起動します。
![スクリーンショット 2023-11-13 14.03.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/51dbcd35-0223-f3d5-38d5-ce5f95d4f7db.png)

文字列を結合するには赤枠の「＞＜」を利用します。アンダースコアは引用符で挟みます。
![スクリーンショット 2023-11-13 14.03.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a8db2d6f-4415-c8ec-8e6b-7661d87a85b2.png)

[テーブル]表示します。
![スクリーンショット 2023-11-13 14.06.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/13689e8c-8233-db31-b4e1-4b0eb7c8f112.png)


#### 注意事項

結合する文字列の前後に空白が含まれている場合には以下のように処理します。

https://qiita.com/416nishimaki/items/35b99152c0f324316792

## 4.参考情報

#### よく使う文字列関数

https://qiita.com/Makimaki2020/items/35ab02a7375325e678c1

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
AI-102試験対策のまとめ「Custom Vision Serviceのモデルのエクスポート」

## はじめに
Azure AI Engineer Associate(AI-102)取得に向けた勉強でまとめた内容を本記事では投稿しています。
試験範囲の内容を私が勉強していく中で、
・忘れてしまっていた内容
・他の知識と絡めて理解した方が良い内容
・Microsoft Learnの読解に苦戦した内容
などをできるだけ分かりやすく簡潔にまとめることを意識しています。
Azureの勉強を一から始め、AI-102取得を目指している方の参考になれば幸いです。
※本記事の内容が必ず試験に出るわけではないこと、ご注意ください
※勉強しながら投稿しているため、追加で学んだことがあれば随時投稿内容を更新します。

## 試験対策のまとめ
### Custom Vision Serviceのモデルのエクスポート
モデルをエクスポートするとオフラインで実行が可能  
⇒アプリケーションに組み込み、デバイス上でローカル実行すると、リアルタイムの分類が可能  
※エクスポートはコンパクトドメインのみ

#### **コンパクトドメインに変換**
1. [Custom VisionのWebサイト](https://www.customvision.ai/)で「ホーム」アイコンを選択し、プロジェクトを一覧表示させる
1. 対象のプロジェクトを選択し、ページ右上の「歯車」アイコンを選択
1. 「Domains」セクションで「General (compact)」を選択
1. 「変更の保存」を選択して変更を保存

#### **新しいドメインでの再トレーニング**
1. ページ上部から「Train(トレーニングする)」を選択

#### **モデルのエクスポート**
1. 「パフォーマンス」タブに移動
1. 「エクスポート」を選択
1. 目的のエクスポート形式を選択
1. 「エクスポート」を選択してモデルをダウンロード

* 参考
    - https://learn.microsoft.com/ja-jp/azure/ai-services/custom-vision-service/export-your-model

## 次の試験対策のまとめ
* **AI-102試験対策のまとめ「インターネットから切断されたコンテナにおけるAzure AIサービスのAPI利用」**

https://qiita.com/fsd-jume/items/ed5b64650c5b49a007bf

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/65aba5d5514e023fd66d
tRPCを使って型安全なAPIを作る

# はじめに
多すぎるパラメータのやりとりに疲れてしまった。
誰か事前に不整合を教えてください。
そんなときに🙇‍♂
# tRPCとは？
tRPCは、TypeScriptのフルパワーを活用し、フロントエンドとバックエンド間の通信においてエンドツーエンドの型安全性を提供します。GraphQLやREST APIと比較して、追加のコード生成ステップが不要で、設定が簡単な点が特徴です。

### サーバーサイドの実装
サーバー側では、APIエンドポイントとして使用するProcedureを定義します。

```typescript
// server/routers/_app.ts
import { createRouter } from '@trpc/server';

export const appRouter = createRouter()
  .query('hello', {
    resolve() {
      return 'Hello tRPC';
    },
  });
// serverの型をエクスポート
export type AppRouter = typeof appRouter;
```
- `createRouter()`関数は、新しいルータを作成します。これはtRPCのAPIエンドポイントの集合です。
- `.query('hello', {...})`は、helloという名前のクエリをルータに追加します。このクエリは、リクエストが来た時に文字列'Hello tRPC'を返す関数を持っています。


サーバーの設定を行います。

```typescript
// server/index.ts
import * as trpc from '@trpc/server';
import { appRouter } from './routers/_app';

const server = trpc
  .createServer({
    router: appRouter,
    createContext: () => null,
  })
  .listen(8080);
```
- `trpc.createServer({...})`は、新しいtRPCサーバーインスタンスを作成します。
- `router: appRouter`で、先ほど定義したルータ（APIエンドポイントの集合）をサーバーに割り当てます。
- `createContext: () => null`は、リクエストごとにオブジェクトを生成するための関数を定義しています。この例では単純化のためにnullを返しています。
- `.listen(8080)`は、ポート8080でサーバーをリッスンし、外部のリクエストを受け付けるようにします。
### クライアントサイドの実装
クライアント側では、tRPCのクエリフックを使用してAPIを呼び出します。

```typescript
// client/index.tsx
import { createReactQueryHooks } from '@trpc/react';
import type { AppRouter } from '../server/routers/_app';

const trpc = createReactQueryHooks<AppRouter>();

function App() {
  const hello = trpc.useQuery(['hello']);
  
  return <div>{hello.data}</div>;
}
```
- `createReactQueryHooks<AppRouter>()`は、サーバーサイドのルータの型を使用して、tRPCのクエリフックを作成します。これにより、サーバーサイドのエンドポイントとの通信が型安全になります。
- `const hello = trpc.useQuery(['hello']);`は、helloという名前のクエリを実行するフックを使用します。このクエリは、サーバーから'Hello tRPC'という文字列を取得します。

# tRPCを使用する利点
エンドツーエンドの型安全性: バックエンドとフロントエンドの間での型の不整合を防ぎます。
追加のコード生成が不要: GraphQLのようにスキーマファイルやコード生成ツールは不要です。
効率的な開発体験: 開発者の生産性を高め、バグの発生を減少させます。
# まとめ
tRPCは、TypeScriptを利用するプロジェクトにおいて、迅速で型安全な開発体験を提供します。この記事では、tRPCの基本的なセットアップと簡単な使い方を紹介しました。
OpenAI APIでFunction callingを使ってみる

## はじめに
2023年6月にOpenAIからAPIの新機能、Function callingがリリースされました。

この記事はOpenAIのFunction callingについて、自分なりの覚え書きです。
自分の理解を深めるためのアウトプットの一環として。

言語はPythonです。

## Function callingの概要
例として、会話文から郵便番号を検索するプログラムを考えます。
郵便番号を検索する外部のAPIを使います。
　[郵便番号検索API](https://postcode.teraren.com/doc/redoc#tag/Postcode/operation/getPostcodes)
住所（の一部）から郵便番号が返ります。
このAPIには住所を渡す必要があります。会話文をそのまま渡すとエラーになります。

### Function callingがリリースされる前
OpenAI API に会話文から住所を抜き出してもらいます。
住所を抜き出してもらうための前提条件（プロンプト）も合わせて渡します。
![スクリーンショット 2023-11-15 8.01.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496109/126117f2-e2fd-ac2b-a38d-be1b416ee70e.png)
渡した前提条件が適切であれば、OpenAI APIは正しく必要な引数だけを返してくれます。
しかし、ChatGPTは出力に「揺らぎ」があるので、会話文の内容や前提条件によっては、期待している形の引数を返してもらえないことがありました。
たとえばこんな感じ。
![スクリーンショット 2023-11-15 8.00.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496109/c959e5dd-7e3e-220e-22e1-7e29b4ea92b7.png)
この揺らぎを抑えるために前提条件をうんうん作り込む必要がありました。
前提条件のガイドラインというのもなく、試行錯誤です。
しかも、どこまで作り込めば揺らぎがなくなるのか皆目見当がつかないので、デスマーチでした。
回答が揺らいだ時に備えて、プログラム側で対処しようにも、限界があります。
趣味でやる分にはいいですが、サービスとして提供するとなると、ちょっと困りますよね。

### Function callingをつかう
Function callingは会話文と関数の定義を送ることで、OpenAI APIが会話文から判断して関数に必要な引数を抽出してくれるようになりました。
出力の揺らぎがなくなり、安定して期待している関数の引数を取得できます。
![スクリーンショット 2023-11-15 8.31.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496109/12876a99-5af7-8281-6cbb-94485ba39d9a.png)

## サンプルコード
今回のサンプルコードはこちらです。

https://colab.research.google.com/drive/1JEC9CLZlu2TONxHq-NSBpebhZfQV34tO?usp=sharing

### 処理内容
シーケンス図にまとめました。
![スクリーンショット 2023-11-15 10.54.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496109/e8967a7a-e29d-caf7-d561-bf373d065289.png)


## 考察
Function callingは関数自体を実行してくれません。
あくまで関数を実行するために必要な引数を返すだけです。
→はじめ、OpenAI APIのサーバーの方で関数を実行してくれると思ってました（汗

関数を実行するコードを自分で実装する必要があります。
サンプルコードの中の関数の実行箇所はStep4のこちらです。
~~~
function_response = function_to_call(
            address=function_args.get("address"),
        )
~~~

関数の定義したJSONデータをもとに、ChatGPTが会話文から必要な引数を取り出してくれます。
JSONデータにある関数の説明文がサラッと一言なのに、ChatGPTがきちんと意味を読み取ってくれるんですよね。
日本語でもOKなのが助かります。

## おわりに
Function callingはエンドユーザー的にはインパクトはないですが、
システム開発者的にはありがたい機能です。

ChatGPTからの出力は「揺らぎ」があるので、JSON形式などで出力するように前提条件で頑張るのも限界があると言うか、そもそもそこにリソースを注ぎ込むのはもったいないです。
なので、OpenAIさんには感謝ですし、開発のスピードが速い！

あと、この投稿をするきっかけとなったのが、2023年11月にリリースされたGPTsのCustom Actionsでした。

Custom Actionsでは、呼び出す関数の定義をJSON形式で記述します。
このフォーマットについて、コピペだの見よう見まねでコネコネしていたので、いまいち理解してませんでした。（汗）

基本的な考え方は、先にリリースしたこのFunction callingがベースになっているので、自分なりに良い勉強になりました。

走り書きみたいな覚え書きですが、お役に立てれば幸いです。

## 参考資料
郵便番号検索API　- 郵便番号の一覧を取得
https://postcode.teraren.com/doc/redoc#tag/Postcode/operation/getPostcodes

ChatGPTの新機能 "GPTs" でCustom Actionsを使って住所から郵便番号を検索してみた
https://qiita.com/iconss/items/abad02ad618a4e795c94
自アプリ内でのコントロールの位置

- 自アプリ内でのコントロールの位置取得です。(通常はデスクトップ上の位置しか取得できない)
- XC,YCにコントロールの位置が返ります。

```c#
// コントロール用 B1== x:name
Point cont = B1.PointToScreen(new Point(0, 0));

// デスクトップ用
Point desk=this.PointToScreen(new Point(0, 0));

// デスクトップからみたコントロールのX位置
int cont_x=(int)cont.X;

// デスクトップからみたアプリのX位置
int desk_x=(int)desk.X;
            
// アプリ内でのコントロールのXY位置
int XC=cont_x-desk_x;
int YC=(int)cont.Y - (int)desk.Y;

```
Update this project to use a newer compileSdk of at least , for example 解決方法

エラー内容
Recommended action: Update this project to use a newer compileSdk of at least 34, for example 34.
推奨されるアクション このプロジェクトを更新して、少なくとも34（たとえば34）の新しいcompileSdkを使用してください。

解決法

Android Studio で以下のファイルを開く
C:\Users\＜ユーザー名＞\AndroidStudioProjects\＜アプリケーション名＞\app　内の build.gradle.kts (Module :app) 

build.gradle.kts (Module :app) ファイルの androidの個所を編集する。

android {
    namespace = "com.example.myapplication"
    compileSdk = 34

※今回は事例として 34 にしたが今後新バージョンが出ると 35, 36,, と数字は更新されるので最新バージョンの番号は各自で要確認。2023年11月１５日現在では34にアップデートしろというメッセージが出る。

defaultConfig　の箇所も同様に 34 に書き換えたい。
    defaultConfig {
    ///その他の項目////
        targetSdk = 34

すると defaultConfig のtargetSdk = 34の箇所に下線が出現し下線にマウスポインタを当てると「sdkをアップデートしますか？」という吹き出しが表示される。more actions クリックし、sync now をクリックする。

アップデート後このエラーは出現せず解決できアプリケーションが動作した。

バージョン
Android Studio Giraffe | 2022.3.1
Windows 11 Home
JavaScript 第2回 onclickでボタン押下動作

# はじめに
JavaScript＋Microsoft Edgeを使用したスクリプト開発ということで、Webサービスを使用したスクリプトで必要そうな機能を試していこうと思います。
まずは、ボタンを押してスクリプトを実行するといったことはよくすると思いますので、onclick属性を使用していこうと思います。
onclick属性よりも、addEventListenerを追加するほうが最近のやり方と思いますが、まずはonclickから始めます。

# 今回実施する内容
HTMLのボタンにonclick属性を付加し、クリックしたときに関数を実行します。
もう少し具体的には、「入力」のInputフィールドに入力して、「実行」ボタンを押すと、「結果」に、入力した値を表示します。
![screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/314e4f00-67b8-fbec-a7e7-d770d66d7fa9.png)

# ソースコード(Git Hub)
https://github.com/Build-Mount/JS_02_onclick
- onclickEvent.html
- onclickEvent.js

# 環境
OS: Windows 11 JP (64bit)
Microsoft Edge: バージョン 119.0.2151.58 (公式ビルド) (64 ビット)

# 参考
[Element: click イベント](https://developer.mozilla.org/ja/docs/Web/API/Element/click_event)

# 用語

# ボタンにonclick属性を設定して、ボタンを押して関数を実行
## onclickの動作
```html:onclick
<input type="button" onclick="関数()" value="実行">
```
上記のように（inputタグを使っていますが）ボタンにonclick属性を追加して、「関数()」を記載します。
関数は、JavaScriptで記載します。
これで、上記のボタンを押すと、「関数」が実行されます。

## サンプルプログラム
### onclickEvent.htmlのソース
```html:onclickEvent.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>onclick event</title>
	<script src="onclickEvent.js" defer></script>
</head>
<body>
    <input id="btn" type="button" value="実行" onclick="btnClick()">
    <br>
    <label for="value">入力</label>
    <input id="value" type="text" />
    <br>
    結果
    <p id="output"></p>
</body>
</html>
```

### onclickEvent.htmlの説明
特に説明するほどのことはないのですが・・・
- ヘッダー部のscriptタグには、`onclickEvent.js`のスクリプトを設定します。
- inputタグで、「実行」のボタンを作成します。
- inputタグは、onclick属性で関数を記載します。
`onclick="btnClick()"`
- もうひとつのinputタグで、テキスト入力を作成し、`id="value"`とします。

- pタグは、結果を表示するために使用し、idタグを`id=output`と追加します。

### onclickEvent.jsのソース
```javascript:onclickEvent.js
function btnClick() {
    document.getElementById("output").textContent = document.getElementById("value").value;
};
```

### onclickEvent.jsの説明
- `document.getElementById("output").textContent`は、`onclickEvent.html`のpタグのコンテンツを示し、そこに、`document.getElementById("value").value`の値を設定します。

# おわりに
HTMLのonclick属性を使用して、JavaScriptの関数を実行するコードを記載しました。
onclick属性はかなり昔からある属性ですが、久しぶりにHTMLやJavaScriptを書いてみて、今も使えるんだなと驚きでした。