OmniAICreator/Qiita-1.07M huggingface dataset:
GA4のサンプルデータからエンゲージメント指標 アクティブ率を出してみる

## アクティブ率とは？
アクティブ率とは、その名の通り、ユーザーがどれだけアクティブにサービスを利用しているかを示す指標です。
今回は下記のような定義をし、指標を算出してみます。

- 指標1： DAU / MAU
- 指標2： DAU / WAU
- 指標3： WAU / MAU

これは分母を基準として分子の数がどれだけ多いか比率を表す指標ですが、例えば指標1においては、MAUに対してDAUがどれ程の基準か、つまりユーザーの起動日数がどれだけ多いか＝どれだけ使われているかを示すものになります。平均して20%ほどあると良いサービスと呼ばれるそうです。
ただし、サービスによっては週1回起動を目指したいアプリである等、それぞれの特性があることから、実態に即した調整をすることもありかと思います。
※参考になる記事：[Facebookが使い出したことで有名になったエンゲージメントを測るKPI — DAU/MAU比率](https://qiita.com/IkuyaM/items/6a0fdd7f6dbbea093b6b)

また、DAU、WAU、MAUは下記のように定義しています。
| 指標名 | 定義 |
|:-----------|:------------|
|DAU|基準日に起動をしたユニークユーザー数|
|WAU|基準日を含めた過去7日間に起動したユニークユーザー数|
|MAU|基準日を含めた過去30日間に起動したユニークユーザー数|


## 今回使用するデータ
BigQueryのサンプルデータにある[パズルゲーム「Flood-It!」のGA4アクセスログデータセット](https://developers.google.com/analytics/bigquery/app-gaming-demo-dataset)を用いて、フラグ別のMAUとその翌月継続率を算出し、フラグによって継続率に差があるかを見てみる。

※過去に同データセットを用いて書いた記事
[GA4のサンプルデータから成長指数を算出してみる](https://qiita.com/NS007/items/33a7a80aedf16d7fabe3)
[GA4のサンプルデータからMAUに占めるユーザータイプ別に指標を作ってみる](https://qiita.com/NS007/items/a16f9cb254b0d9a48ace)
[GA4のサンプルデータからタイプ別＆定着度合い別に継続率を出してみる](https://qiita.com/NS007/items/b2c75f4ce27b64dbd89c)

## クエリ
サンプルデータの期間は2018/06/12 ~ 2018/10/03であり、継続ユーザーを出すには30日前までの起動歴が必要なため、切れ良く2018/07/01以降のデータを用いて、2018/08/01以降の期間を抽出する。
```sql
WITH tmp AS (
  SELECT DISTINCT
    PARSE_DATE('%Y%m%d', event_date) AS event_date
    , user_pseudo_id
  FROM `firebase-public-project.analytics_153293282.events_*`
  WHERE _TABLE_SUFFIX BETWEEN '20180701' AND '20180931'
  AND event_name IN ('session_start', 'first_open')
)
, mst_dau AS (
  SELECT
    event_date
    , COUNT(DISTINCT user_pseudo_id) AS dau
  FROM tmp
  GROUP BY 1
)
, mst_wau AS (
  SELECT
    A.event_date
    , COUNT(DISTINCT B.user_pseudo_id) AS wau
  FROM tmp AS A
  INNER JOIN tmp AS B
      ON DATE_DIFF(A.event_date, B.event_date, DAY) BETWEEN 0 AND 6 #当日を含めた過去7日間
  GROUP BY 1
)
, mst_mau AS (
  SELECT
    A.event_date
    , COUNT(DISTINCT B.user_pseudo_id) AS mau
  FROM tmp AS A
  INNER JOIN tmp AS B
      ON DATE_DIFF(A.event_date, B.event_date, DAY) BETWEEN 0 AND 29 #当日を含めた過去30日間
  GROUP BY 1
)
SELECT
  A.event_date
  , A.dau
  , B.wau
  , C.mau
  , A.dau / C.mau AS ar_dau_mau
  , A.dau / B.wau AS ar_dau_wau
  , B.wau / C.mau AS ar_wau_mau
FROM mst_dau AS A
LEFT JOIN mst_wau AS B
  USING(event_date)
LEFT JOIN mst_mau AS C
  USING(event_date)
WHERE A.event_date >= '2018-08-01'
ORDER BY 1
```

## アウトプット
![DAU、WAU、MAU.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233689/72a6112f-8fa2-9d42-f278-1944745aa588.png)
![アクティブ率.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233689/90158d47-d7f0-4e9c-e92b-eade6cb81389.png)


## ここから言えること
まずDAUはほぼ一定ですが、9月あたりからMAUの水準が上がり始めました。
それに合わせて、少しですが徐々にアクティブ率が下がり始めているのが分かります。

おそらくですが、継続が悪い新規ユーザーが増えたためMAUは上がりましたが、継続はしないためDAUはほぼ変わらなかったと考えられます。
仮定が正とすると、質の悪い獲得によってアクティブ率は低下するケースがあることを示しています。
また、DAU / WAUを見ても同様のことが言えるでしょう。
新人でも出来る！ペアプロのコツ

こんにちは！
私は開発歴もうすぐ1年になりますが、最近ペアプロをすることが多く、こうすればペアプロが円滑にすすむな〜というのが分かってきたので、メモしておきます。
新人でも出来るちょっとしたことばかりなので、ちょちょっと読んで、実践してみてください。


## ドライバ編
ペアプロでドライバをする時に私が一番大切だと思うことは、ペアが安心感を持ってナビゲーションできるように、また、無駄なところに気を使わないで済むように作業することです。ドライバは単なるタイピストではなく、ナビゲータがナビゲートしやすいように作業をする人だと思っています。
そんなドライバで気を付けたいことは以下の4点です。

#### 1. 実況する
自分が何を打とうとしているか、なぜそれをやろうとしているか、など、考えていることを垂れ流しましょう。「〜をしたいので、ここでは、〜する感じにしたいですね〜」といった具合です。
また、「いけるかわからないですけど、一旦書いてみますね。」と言うように、お気持ちも一緒に表明すると、なお良いと思います。お気持ちを表明することで、ナビゲータの人は、書かれているコードを注意深く見れば良いのか、次の段取りについて考えても良いのかという判断ができるようになります。ナビゲータが無駄なく動けるように、ドライバの頭の中を8割くらいオープンにしましょう。「疲れてきたな〜」と言うのも、休憩の合図になるので良いですね。

#### 2. 作業の順番・やり方で心配させない
作業において順序はとても重要です。作業がちぐはぐなドライバだと、ナビゲータは画面から目が離せません。例えば、ブロックのendを書かずに中の処理を書き始めるとか、変数名を変える時に、リファクタ機能を使わず手で全部書き換えようとするとか。ミスが起こりそうで、ナビゲータは安心できません。ソロプログラミングだと独自のやり方で良いかもしれません（おすすめはしません）が、ペアプロのときには、特に、ナビゲータに作業を見せるという意識で、誤解と疑念を生まないように手を動かすように心がけたいです。

#### 3. TODOコメントを使う
実装をしていると、「ここは後で書こう」という場面もあると思います。ソロでは「後でしよう」で問題ないかもしれませんが、ペアプロでは、ドライバが想定していなかったことが起こる可能性が高い（ナビゲータが「ちょっとさっきのところ見せて」といったり、休憩が入ったりする）ため、「後でしよう」と思ってたことを忘れる危険も高くなります。その場合、「後で〇〇しよう」とナビゲータに言葉で共有するのは1つの手ですが、ナビゲータのワーキングメモリを奪ってしまいます。そのため、「後で」が出てきたら、TODOコメントを書くようにすると良いのではないかと思います。「# TODO: ここに〇〇の処理を書く」という簡単なコメントでいいので、残しておくと、安心ですね。

#### 4. beforeのコードはコメントアウトでとっておく
コードの修正を行う中で、既存のコードを消したり、上書いたりする場面があると思います。ソロで作業するときは既存コードに直接手を加えて上書きする人も多いと思いますが、ペアプロのときは、既存のコードをコメントアウトで残しておいて、その下に新しいコードを書いておくのが親切です。既存のコードはどんなことをしていて、新しいコードは何が変わったのかを常に見える形にしておくことで思考の整理ができます。特に先輩プログラマーがドライバで、ナビゲータが若手（もしくは、その辺のコードが初見の人）の場合、既存コードを残しておいてくれるととても助かることがあります。気になるところは人それぞれなので、ナビゲータが気になった時に考える材料を残しておくのはとても親切だと思います。

## ナビゲータ編
ナビゲータは、ドライバのミスに気付いたり、先回りして調査や処理を考えておいて、ドライバをナビゲートする人です。新人の場合、最初は先回りしてナビゲートすることが難しくて、ドライバの発言に相槌を打ちながら、画面を見ているだけになってしまうこともあるかもしれません。しかし、新人であっても、出来ることはあります。そして、それを続けていくと、ナビゲート力も上がっていきます。
そんなナビゲータをしているときに気を付けたいことは以下の3点です。

#### 1. テーブル名やファイル名はすぐ参照出来るようにしておく
プログラムを書いていると、データベース名、テーブル名、カラム名、ファイル名、クラス名、変数名などなど、色んな名前が出てきます。ドライバはエディタの補完機能を使ったり、事前にコピーしたものを使う場合は安心してコードをかけますが、手でベタ書きするときは常にタイポを恐れています。そのため、実装中に出てくるテーブル名やカラム名、参照のために開く可能性のあるファイル名などはいつでもナビゲートできるようにしておきましょう。

#### 2. 休憩を取る。時間を測る
ペアプロでよくあるのが、時間を忘れて作業してしまうことです。時間を測ってドライバとナビゲータを交代したり、休憩を取ることは重要です。ナビゲータが時間を測って、ペアプロのリズムを整えるように声掛けを行うようにしましょう。

#### 3. 検索方法をナビする
ドライバが「書き方どうだったっけな〜」という発言をしたらナビのチャンスです。キーワードで検索し、書き方をナビゲートしましょう。まずは、同プロダクト内に似たような処理をしている箇所はないかを調べ、ヒットしなければ、公式ドキュメントも見ておきましょう。検索はショートカットでパッと出来るように準備しておきましょう。

## その他
ペアプロの役割に関わらず、ペアプロをしている時にマストでやっておきたいことが1つあるので、書いておきます。

#### 1. コードを書く前に進め方を共有しておく
「テストファーストで実装しましょう」とか「リファクタは後でしましょう」のように、どういう手順で実装していくかを最初に決めておきましょう。そうしないと、ドライバの作業とナビゲータの想定していた作業がずれて、ペアプロがうまく機能しなくなります。また、事前に進め方を共有しておくことで、自分たちの作業の進捗具合も把握できますし、あとどれくらいかかるかもだいたい分かると思います。

## 最後に
今回は、ペアプロで心がけてきたことをメモ程度に書き留めました。うまく機能しているペアプロはとても楽しいですし、ペアプロでドライバやナビゲータがうまくなると、必然的に開発力が伸びます。
今後もペアプロに関して思う所があれば、アップデートしていきたいです。
LINEでアカウントを知られずにメッセージ交換っぽい事をしたい

# ご近所さんと簡単に連絡が取りたかったんです…

このツールを思いついたきっかけは、ご近所トラブルからでした。
住んでいるマンションの部屋の並びが

［私］［Aさん］［Bさん］

という並びなんですが、この真ん中のAさんが10月に引っ越してきてから、ヘビースモーカーでも臭いと言う位の強烈なタバコ臭が部屋に侵入したり、深夜～明け方にかけてマイクで喋っているような声が響く日々・・。
同じ状況だったBさんから昨年末にお手紙をもらってから、手紙でお互いの状況や管理会社・大家とのやり取り内容を共有しているのですが・・・・


毎回手書きでお手紙を書くのはシンドイ！！

サクっと手間をかけずに情報交換したい！でもなるべく連絡先等の情報は公開したくない・・・という思いからLINE Botを使って ~~強引に~~ メッセージを交換するツールを作成しました。



# 使用ツール
* LINEmessagingAPI
* GoogleAppsScript

# 処理イメージ
https://twitter.com/momoiku3/status/1638333084742619136

ちなみに、他の人から動画が届くと、下の図の黄色マーカー部分のような表示になります。
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122228/ba50b7b6-48b8-a504-a9a9-4215ed3b6dcd.png">

## 処理の流れ
![qiitaImg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122228/97832369-b878-ead9-c63a-dc0127d0fc1f.png)

# 作成方法
## LINE側の準備
こちらの公式マニュアルを参考に、LINE Developersにログインし、チャネルの作成とBotの作成を行ってください。
[Messaging APIを始めよう](https://developers.line.biz/ja/docs/messaging-api/getting-started/)
[ボットを作成する](https://developers.line.biz/ja/docs/messaging-api/building-bot/)

## プログラム
GoogleAppsScriptに以下プログラムを書いていきます。

```javascript
const CHANNEL_ACCESS_TOKEN = "チャネルアクセストークン";

function doPost(e) {

    handleMessage(e);
}


function handleMessage(e) {
  const replyToken = JSON.parse(e.postData.contents).events[0].replyToken;
  const lineType = JSON.parse(e.postData.contents).events[0].type
  if (typeof replyToken === "undefined" || lineType === "follow") {
    return;
  }
  let userMessage = JSON.parse(e.postData.contents).events[0].message.text;

  return push(userMessage);

}

//実際にメッセージを送信。
function push(text) {
  const url = "https://api.line.me/v2/bot/message/broadcast";
  const headers = {
    "Content-Type" : "application/json; charset=UTF-8",
    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
  };

  let postData = {
    "messages" : [
      {
        'type':'text',
        'text':text,
      }
    ]
  };

  let options = {
    "method" : "post",
    "headers" : headers,
    "payload" : JSON.stringify(postData)
  };

  return UrlFetchApp.fetch(url, options);
}

```
今回自分のアカウントを知られたくないという事なので、オウム返しのLINE Botを参考にして、全員にメッセージを送るブロードキャストメッセージを使ってBotを登録している人全員にオウム返しされるようにしました。

:::note warn
アカウント名を伏せるため、受信するメッセージはすべてBotからのメッセージになります。
:::

# その後
連絡を取りたかったBさんがLINEを使わない人だったので、使わずに終了・・・・。
それもあったので、Qiitaに記念投稿しました。
ちなみに、強烈タバコ臭と夜間騒音は、管理会社は何もしない（というか他人事状態）。その代わり、情報を知った大家がお怒りモードで動いている感じです。
MacからEC2にHTMLファイルを送信して、Webで公開してみた


MAMPで作成したWebページをEC２上で公開したい。
MAMPのhdocフォルダに保存されているindex.htmlファイルをEC2上で公開してみようと思う。

## Macのターミナルを起動
1. EC2にssh接続する。（このターミナルウィンドウを以後、EC2と呼ぶ。）

https://qiita.com/kaiyo_yume/items/d6542b95a26a79b392e4

2. ターミナルの新規ウィンドウを立ち上げる。（以後、ターミナルと呼ぶ。）
この２つのターミナル画面から操作していく。

## EC2のホームディレクトリにhdocフォルダを作る。
```zsh
mkdir hdoc
```
## EC２のhdocフォルダにファイルをコピーするシェルスクリプトを作る。
- VSCodeで、ec2_scp.shという名前のファイルを作成して、Macのホームディレクトリに保存する。

ec2_scp.shのコード
```zsh
scp -i "キーペアのフルパス" $1 ec2-user@EC２のパブリック IPv4 DNS:/home/ec2-user/hdoc
```
$1は引数で、シェルスクリプトの実行時に送りたいファイルのパスを指定する。
※キーペアとシェルスクリプトが同じフォルダにないので、キーペアはフルパスで書く。

## ターミナルのホームディレクトリで、以下のコマンドを実行。
```zsh
sh ec2_scp.sh /Applications/MAMP/htdocs/index.html
```
MAMPのhtdocsフォルダにあるindex.htmlファイルがEC2のhtdocフォルダに送信される。

## EC2上で、ディレクトリからドキュメントルートへファイルをコピー
EC2のhdocディレクトリのindex.htmlをEC2のドキュメントルートへコピーする。

EC2のホームディレクトリで、以下のコマンドを実行。
```zsh
sudo cp hdoc/index.html /var/www/html
```
EC２のパブリックIPv4DNSをコピーしてchromeで検索すると、index.htmlファイルが表示される。
AWS上にWebサーバを作成した

## EC2を立てる。
- Amazon マシンイメージはAmazon linux 2　AMI（無料枠）を選択。
- キーペアを作成。
- セキュリティグループは、
インバウンドルールはhttp、httpsはすべてのIPアドレスを許可、sshは自分のIPを許可した。
アウトバンドルールは全面的に許可した
- 他の設定はデフォルトのままにした。

## Elastic IPアドレスをEC2に割り当てる
検索すれば記事がたくさんあるので説明は省略。

## Macからssh接続
参照：

https://qiita.com/kaiyo_yume/items/d6542b95a26a79b392e4

## LAMP構成のwebサーバをEC2にインストール
AWSのチュートリアルに従ってインストールする。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-lamp-amazon-linux-2.html

これで、Webサーバの構築終了。
いつもHTMLのevent型がわからず、any型を使って逃げていた。

# はじめに
ReactをTypescriptで学んでいて
いつも`onclick`とかのevent型の型がわからずany型を使ってとりあえずtypeエラーを回避していました。
「あっこれ調べて型指定できるんだ」と知ったので方法を共有したいと思います。

## 再現
この引数の**型**って何なのかわからない。。。
![type error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819639/2b78ac7b-61f5-8b34-7c02-c8225d7a73db.png)
この型がわからずany型でこんな感じに解決していました。
![any.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819639/16868668-1078-3f47-4014-434c4325ecd2.png)

## 型を指定する
どうやって調べるか？
VScodeの型情報を使うことで調べることができます。
`onSubmit`や`onChange`になにもしない関数を実装することで型推論から型情報を見れます。![fun.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819639/798764d9-0091-4556-042d-4559ada2889d.png)
`e`をホバーすると
![type s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819639/e9ce1eb3-8ceb-d897-ca44-df959ff6d159.png)
こちらの型情報が型になります。
型を指定しちゃいましょう。
`React.`を前につけて引数に型を指定。
同じように`onChange`も引数に型を指定。
![type c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819639/6aff74fe-d6e4-07f1-04cf-2ceae7db155a.png)
関数をもとに戻して
![comp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819639/3f0d1aaf-37b4-b1f1-2f6e-44acdf6e64ef.png)
ハイ！きちんと型を指定することができました。
## まとめ
「型推論を使うこんな方法もあるんだ！」と目から鱗だったので記事にしてみました。おしまい。

参考

https://qiita.com/Takepepe/items/f1ba99a7ca7e66290f24

https://reffect.co.jp/react/react-typescript-event
ローカル環境からdockerのmysqlへ接続

1. コンテナを動かす
```
docker run \
--name mydb \
-itd \
--hostname my-mysql \
-e MYSQL_ROOT_PASSWORD=mypassword \
-e BIND-ADDRESS=0.0.0.0 \
-p 3305:3306 \
public.ecr.aws/docker/library/mysql:8.0
```
※portは3305に設定

2.mysqlへ接続、DB＆ユーザー＆権限作成
```
docker exec -it <コンテナ名> mysql -u <ユーザ名> -p
```
3.ローカルでmysqlにログイン
```
mysql -u ＜ユーザー名＞ -h 127.0.0.1 -p --port=3305
```
エラーがでてしまう
```
ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded: 指定されたモジュールが見つかりません。 Library path is 'caching_sha2_password.dll'
```
ローカルのmysqlクライアントツールでcaching_sha2_password がサポートされていないため起こる。
4.認証方法の変更
```
mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'new_root_password';
Query OK, 0 rows affected (0.01 sec)
```
再度接続してみたが、
```
Error 1045 (28000): Access denied for user ~~
```
5.userのホストを'localhost'から'%'に変更
```
RENAME USER 'ユーザー名'@'ホスト名' to '新ユーザー名'@'新ホスト名';
```
6.再度接続
```
mysql -u ＜ユーザー名＞ -h 127.0.0.1 -p --port=3305

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 8.0.32 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>
```
接続完了！
Furigana

https://apps.apple.com/jp/app/furigana/id1149116590
![6mMfkmBJhzTeFUzqrRoA8J4KaAY2/sZEDUWAzYRYmWLBq.jpg](https://firebasestorage.googleapis.com:443/v0/b/type-c1c71.appspot.com/o/6mMfkmBJhzTeFUzqrRoA8J4KaAY2%2FsZEDUWAzYRYmWLBq.jpg?alt=media&token=c22b762a-3179-46f4-9777-fd0f0f242efb)

日本語の勉強APP（iOS版）

好評をいただいております。
![6mMfkmBJhzTeFUzqrRoA8J4KaAY2/XsOc2kcVxYLkIz2W.jpg](https://firebasestorage.googleapis.com:443/v0/b/type-c1c71.appspot.com/o/6mMfkmBJhzTeFUzqrRoA8J4KaAY2%2FXsOc2kcVxYLkIz2W.jpg?alt=media&token=e833a675-9316-45c7-9393-e95039d39397)
![6mMfkmBJhzTeFUzqrRoA8J4KaAY2/8H7W8ZdbKUSQYtMx.jpg](https://firebasestorage.googleapis.com:443/v0/b/type-c1c71.appspot.com/o/6mMfkmBJhzTeFUzqrRoA8J4KaAY2%2F8H7W8ZdbKUSQYtMx.jpg?alt=media&token=e5ae8f84-542c-41d4-85b4-1c7e9be80874)

**外国人だけでなく、漢字が苦手な日本人でも気に入るでしょう。**
ReactでChrome拡張機能を実装できるPlasmoを使用してスクレイピングを自動化

## 背景
毎回ブックマークをクリックしてスクレイピングを実行のが手間だった。
Plasmoで自動で実行したいと思った🙄

## Plasmoとは
簡単にいうとChrome拡張機能の開発プラットフォーム
Chrome拡張機能を簡単に作成・テスト・公開できる
React、Preact、Svelte、Vue、Typescriptに対応しているらしい
[document](https://www.plasmo.com/)

※スクレイピングを実行するだけのChrome拡張機能を作成するだけ！
※Chrome Web Storeに公開はしないです。あくまで個人で使用する用途
※今回は[Content Scripts](https://docs.plasmo.com/framework/content-scripts)のみ使用します

## 実装

### setup
今回はpnpmを使用します（pnpmが推奨されていた為）
※フォルダ名はappとします
```typescript
pnpm create plasmo
// or
yarn create plasmo
// or
npm create plasmo
```

### 開発サーバーを起動
```typescript
pnpm dev
```

[Chrome拡張機能](chrome://extensions/)のデベロッパーモードを有効にする
上記画面にある**パッケージ化されていない拡張機能を読み込む**をクリックし、app/build/chrome-mv3-devを選択
すると**DEV | app**という拡張機能が追加される

### コードを書く
ルートディレクトリにcontent.tsを作成
```typescript
touch content.ts
```
※ `contents/scraping.ts`でも可能

content.tsはwebページのデータ取得や、逆にUIを表示したりできる
[Content Scripts](https://docs.plasmo.com/framework/content-scripts)

```typescript:content.ts
export {}
// ロジックを書く
```
※ `export {}`はtypescriptのコンパイルチェックを無視する為に追加。他ファイルからロジックをimportすれば不要
```typescript:content.ts
import scraping from "scraping"
scraping()
```

### 注意点
srcフォルダを作成するとうまく機能しなかったので、その場合はtsconfig.jsonの**compilerOptions**を変更する
```typescript:tsconfig.json
{
  "extends": "plasmo/templates/tsconfig.base",
  "exclude": ["node_modules"],
  "include": [".plasmo/index.d.ts", "./**/*.ts", "./**/*.tsx"],
  "compilerOptions": {
    "paths": {
    // srcを指定する
      "~*": ["./src/*"]
    },
    "baseUrl": "."
  }
}
```
この場合、`src/content.ts` or `contents/scraping.ts`のようにできます

## ローカルで拡張機能を使用する
最後は、作成したChrome拡張機能の**Dev | app**を有効にしておくだけで終わり！

## 終わり
これでタブを開くと自動で実行されるようになったので生産性UP！🎉
お母さんでもわかるJavaScript「const、分割代入、デフォルト値、スプレッド構文」

## constについて
constは基本、**再宣言・代入**ができない！
がしかし！**代入や追加**ができてしまうケースがある。それが「オブジェクト・配列・関数(他にも多分ある)」の時です。

※厳密には「その中身」を変えたり追加したりできる。変数自体を再代入することはできない。
（テキストノードやsrc、さらには要素も追加できる）

## 分割代入について

①分割代入を使用しない場合
```index.js
const profile = {
    name:"清水",
    age:24,
};
const message = `私の名前は${profile.name}です。年齢は${profile.age}歳です。`;
console.log(message);
```

②分割代入を使用した場合
```index.js
const {name,age} = profile;
const message = `私の名前は${name}です。年齢は${age}歳です。`;
console.log(message);
```

`私の名前は${name}です。年齢は${age}歳です。`
このように値を使うときに`〇〇.〇〇`と記述しなくていいから効率が良い！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782070/a48d963f-1a6d-cff2-d14b-bd1bcaed26e1.jpeg" width=100%>

## デフォルト値の設定

デフォルト値とは引数などでよく使われる「もし指定したものがなかったら」のようなものです。
例えば、下記のように使用します！
```index.js
//引数と指定した場合
const hello = (name) => console.log(`こんにちは${name}さん`);
hello("清水");//こんにちは清水さん

//引数と指定しなかった場合
const hello = (name) => console.log(`こんにちは${name}さん`);
hello();//こんにちはundefinedさん

//undefinedを防ぐために
const hello = (name = "ゲスト") => console.log(`こんにちは${name}さん`);
hello();//こんにちはゲストさん
hello("清水");//こんにちは清水さん
```

これを**分割代入**でも使えてしまうらしい！
```index.js
const profile = {
    age:24,
};

//ダメなパターン
const{name} = profile;
const message = `こんにちは${name}さん`;
console.log(message);//こんにちはundefinedさん

//いいパターン
const{name = "ゲスト"} = profile;
const message = `こんにちは${name}さん`;
console.log(message);//こんにちはゲストさん
```

## スプレッド構文
**①要素の展開**　各要素を個別の引数として関数に渡す。配列そのものではない。
**②要素をまとめる**
**③要素のコピー、結合**

```index.js
const arr2 = [1, 2, 3, 4, 5];
const arr4 = [1, 2, 3, 4, 5];

//ノーマル
console.log(arr2);//[1, 2, 3, 4, 5]

//①
console.log(...arr2);//1 2 3 4 5

//②
const [num1 , num2 , ...arr3] = arr2;
console.log(num1);//1
console.log(num2);//2
console.log(...arr3);//3 4 5

//③
const arr3 = [...arr2];
console.log(arr3);//[1, 2, 3, 4, 5]

const arr4 = [...arr2,...arr4];
console.log(arr4);//[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
```
③の`const arr3 = [...arr2];`は`const arr3 = arr2;`でも実現可能ですが、予期せぬ挙動が出る場合があるので注意です。
どういうことかというと
```index.js
//シンプルに代入する場合
const arr2 = [1, 2, 3, 4, 5];
const arr4 = arr2;

arr4[0] = 800;
console.log(arr2);//[800, 2, 3, 4, 5]→　あれ？arr2の中身も変わってる、、、
console.log(arr4);//[800, 2, 3, 4, 5]


//スプレッド構文で代入する場合
const arr2 = [1, 2, 3, 4, 5];
const arr4 = [...arr2];

arr4[0] = 800;
console.log(arr2);//[1, 2, 3, 4, 5]　→　こっちは影響されてない！
console.log(arr4);//[800, 2, 3, 4, 5]
```
なぜかというと`const arr4 = arr2;`は**値**を代入しているわけではなく、「**arr2はここに格納されてますよ〜**」という情報のみが代入される仕組みになっているから。
つまり値が格納されているのは`arr4`ではなく`arr2`ってこと。
（むずかし、、、）

あとなんか適当にやってみた動き！
```js
const numbers = [1,2,3];
console.log(numbers);//[1, 2, 3]

const [...newNumbers] = numbers;
console.log(newNumbers);//[1, 2, 3]

const {...NewNumbers} = numbers; 
console.log(NewNumbers);//{0: 1, 1: 2, 2: 3}
```
Powershellのコンストラクタ

***Powershell***のコンストラクタの実装例です。

```Powershell
class Hinatazaka{
    [int] $id
    [String] $name 
    #コンストラクタ
    Hinatazaka([int] $id,[String] $name) {
        $this.id = $id 
        $this.name = $name    
    }
    #メソッド
    [void] Disp() {
         Write-Host( $this.name + "のid番号は" + $this.id + "です")  
    }
}

#インスタンス化
$rei1 = New-Object Hinatazaka(1,"佐々木久美")
#呼び出し
$rei1.Disp()

#インスタンス化
$rei2 = New-Object Hinatazaka(2,"加藤史帆")
#呼び出し
$rei2.Disp()

$rei3 = New-Object Hinatazaka(3,"影山優佳")
$rei3.Disp()


```
受動意識仮説は思考停止の呪文だ

# 
**ChatGPTが意識を持ってるかどうかより、我々の意識はイリュージョンだって？**

今回はちょっと軽め。

# 受動意識仮説と言う怪しげな仮説

最近ChatGPTで色々書いてたりする中で、ある方とQuoraでちょっと話になって、その中でその方が出してきた、「受動意識仮説」。

ああ、そんなのあったなって。

なんか意識はイリュージョンだとか意識は何も自分の動きは制御もしてないし、ただ脳の物理を見てるだけって？

なんか最近自分が意識仮説出してるけど、基本今の最先端物理を合わせれば色々説明付いてきてるつもりなので、古いなあ、って感じなんだけど、改めて少し批判というか、確認してみるよ。

# 仮説の元になった実験を確認する

とても簡単に言うと、この話の元になった実験は、意識で何かをすると決めた、と言う時間の「前に」大脳が動いてる、だから、意識は意思決定には関与してないだろうって話。

その図がこんなの。

![Screenshot_2023-03-22-04-47-05-121_com.google.android.youtube.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2974126/029d5cd7-f0e4-163e-b14b-310b78de4b29.jpeg)

えー？？でもこんな不思議な話になんか実は結構支持者がいたんだな、と思って。

この実験なんだけど、前野氏のYoutubeとか見てても、その前に、別の実験では視覚で測った時間が実時間と実際に大きくズレてるって話をしてて。

そのすぐ後で、いや実験者の報告で測ったらこの時間になったから、意識の方が脳内の処理より後だ、とかやっててさ。

いや、さっき意識の時間ば物理時間とめちゃズレてるって言ってたばかりじゃん、と。

そもそもそこで数百ミリ秒ずれると明確に言ってるのに、なぜ急にそれが正確として大脳の信号が先だと言い出したのか？？

そして受動意識仮説と言いながら、その前から「意識して動かしてね」と指示を出してるわけだから、ずっと大脳には意識が関与してるじゃん。要はプレッシャーを大脳にかけてる状態。その中で動いたものが、意識が動かしたと認識して何が悪いのか？意識的な関与は **最初から** あったんだよ。何が意識が後なのかちっとも分からない。

# 意識がイリュージョンって、何が言いたいの？

で意識がイリュージョンだとか言うんだけど。

そもそもじゃああんたはゾンビかな？？見えてないと？イリュージョンとは何？あなたがイリュージョンなら、では他のものはなんなの？あなたしかいないでしょ？あなた「 **しか** 」いなくても、あなたの見てるものは仮想で存在してなくても不思議では無いが、あなたがいなければ大元の観測者がいないのでそこで話なんにもなくなるじゃん。

いやさすがに意識がイリュージョンと言うのは何も言ってない。意識の存在はまず科学の前の存在の前提だろ？？って。まあこういう議論が昔はあったんだから本気で恐ろしいとしか🥺😳

# 前野隆司氏のYoutubeを見る

で、この「受動意識仮説」の日本の祖みたいな人がこの「前野隆司」氏なんだけどね。

今もYoutube見れるから見て見たの。

そしたら昔はともかく、最近の動画見てると、自分の本の紹介はしてても「仏教とか」の話しかしてない。内容全然言ってない。

という訳でご本人がそもそも科学であることを放棄してしまった風なんだ。なんか辛いことあったんだろうね？？

# あれ？茂木健一郎氏も？

でさ、実はこの理論をあの茂木健一郎御大もなんか少し支持してるっぽくて。そのYoutubeも見て見たのさ。1年ぐらい前の動画。

そうしたら「そう考えると気が楽だ」とか言ってる。いや気が楽なのはまあ、自分の決定に関しての責任感を減らせるから楽な感じがするのはいいと思うんだよ？でもそれはこの理論の何かを補強するわけでは全くないんだ。科学な話してくれてないな。

で、最近の茂木さんの動をみたら、もっと凄いこと言ってたよ。


https://youtu.be/hW68XZcHbLg


「意識については考えないのがいい適応だよね」
とか、言ってんの。え？？？と思ったけど。なんであんたが言うねん。意識の問題を言い出したあなたが。

最近茂木さんはネトウヨという事が同じになってたり、色々あれれ？と思うことも多いんだけど、意識の話をこのChatGPTが出てる今になって「しない方がいい」だって？？なんともはや。

# これはあれだね、「計算しろ！！」だ

で、思ったんだよね。これは言わば量子力学でずっと言われてきた、「 **考えるな！計算しろ！！** 」だなと。

要は思考停止して働こうよ、儲かるために、みたいな話をこの御大自らやってるんだろなと。

受動意識仮説は多分そういうものだよね。意識のことなんか幻だ、考えるな、と。

そんな事して日本人をどこに連れてくつもりなのか。ちょっと残念だ。いやすごい残念。前野氏の動画みてても、受動意識仮説は明確に既にトンデモに仲間入りしたのかも？意識も自由意志も今の科学で仮説とはいえ説明つくなら、この後ろ向きの仮説はもう要らないよね？😊😋
React開発Part3～useState編～

## はじめに
　おはようございます、Tunです。
今回は、前回の最後に記述した通り`State`について記載していきます。
## State(useState)
　hookはReact16.8で追加された新機能です。`state`などのReactの機能をクラスを書かずに使用できるようになりました。`React.Component`から`extends`したクラスを使用せず、また、`this`の起債も必要なくなり、コード自体もスッキリをスマートに書くことができます。

:::note warn
なぜReactにhookを新機能として追加したのかの背景は[こちら(動機)](https://ja.reactjs.org/docs/hooks-intro.html#motivation)へ
:::

　まずは例を見てみましょう。
```react:useState
import React, { useState } from 'react';

function Example(){
  const [count, setCount] = useState(0);

  return( 
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
```
　このコードは、ボタンをクリックすると、カウンターの値が増加する仕組みになっています。この中の`useState`が**フック(hook)** にあたります。関数コンポーネントのスコープ内でローカルな`state`を使うために呼び出しており、この`state`は以降の再レンダーの間も保持されます。
　`[count, setCount] = useState(0);`の部分の`count`は、**現在**の`state`変数の状態の値を、`setCount`はstateの状態を更新するための関数を持っており、`useState`がこれらをペアにして返しています。また、`useState`はstateの初期値を唯一引数にとります。この引数として渡されたstateの初期値は最初のレンダー時のみに使用されます。

:::note info
 **フック(hook)とは何ぞや**:thinking:
フックとは、関数コンポーネントstateやライフサイクルといったReactの機能を**接続する(hook into)** ための関数のこと。
フックはReactをクラスなしに使うための機能です。ですので、クラス内で使用することはできません。
以前まではクラスコンポーネント(`React.Component`)を使ってReact開発していましたが、2018年よりコードの**削減・可読性の向上など**の理由から、関数コンポーネントに移行していきました。その流れで、クラスコンポーネントしか使えない機能があり、いちいち関数からクラスへ書き換えを行うのは面倒だったためフックという機能が生まれました。
:::
　上記の例をもっと詳しく見てみましょう

- **useStateを呼ぶと何が起こるのか？**
　上記の例では変数を`count`と名付けましたが、なんでも好きな名前を設定することができます。この変数に関数コールの間で値を保持しておきます。通常であれば、関数が終了すると変数は**消えて**しまいますが、state変数はReactによって保持されます。
- **useStateは何を返すのか？**
　現在の`state`と、それを更新するために関数のペアを返します。これが`[count, setCount] = useState();`という書き方にした理由です。

`count`という名前のstate変数を宣言しており、それを初期値`0`でセットしています。再レンダー間でReactはその変数の現在値を記憶しており、最新の値を関数に提供しています。現在の`count`の値を更新したい場合は、`setCount`を呼ぶことで可能になります。
***
### stateの読み出し
　また、関数内では直接`count`を使うことができます。
※クラスだと`this`が必要になる。
```react:
<p>You clicked {count} times</p>
```
***
### stateの更新
　関数内では、すでに`setCount`と`count`を変数として受けとっているので、ここも`this`は必要はありません。
```react:
<button onClick={() => setCount(count + 1)}>
 Click me
</button>
```

　これまでを振り返ると
1. `useState`フックをReactからインポートし、関数コンポーネント内でローカル`state`を使えるようにする。
2. Exampleコンポーネント内で`useState`を呼び出すことで新しい`state`変数を宣言します。変数と関数のペアが返されるので、任意の名前を付けます。`useState`唯一の引数として`0`を渡すことで、変数をゼロへと初期化します。`setCount`はcount を更新する関数になります。
3. ユーザがクリックした時に、新しい値で`setCount`を呼びます。ReactはExampleコンポーネントを再レンダーして新たなcountの値を渡します。

次回は副作用についてです！

## 参考
- [React公式](https://ja.reactjs.org/docs/hooks-state.html)
GUIループを使って列でグラフを出し分ける(SPSS Modeler データ加工逆引き9-11)

# グラフを列で出し分ける（GUIループ）

![スクリーンショット 2023-03-17 18.01.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/30358673-6d88-717a-3af0-535f788b25b6.png)


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

・47都道府県別のグラフを作る際に、ストリームを何度も複製したり、スクリプトでループ処理したりすることなくGUI（マウス操作）で出し分ける

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

https://github.com/yoichiro0903n/blue/blob/main/GUIhist.str?raw=true

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

![スクリーンショット 2023-03-13 14.51.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/39fced9a-52c4-d855-16d6-20f20cfeb1be.png)

a.入力するデータは以下の通りです。

![スクリーンショット 2023-03-13 14.53.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/03c154e3-7b7f-e349-444b-be38d5578e38.png)

[データ型]タブの　[値の読み込み]ボタンを押してデータの型を確定しておきます。
![スクリーンショット 2023-03-13 14.54.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b42a55e9-aaca-9703-8654-f9c06f785927.png)
　
b.[ヒストグラム]ノードを編集します。[値]を対象にして確定します。
![スクリーンショット 2023-03-13 14.54.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/bf9d8929-5d0e-2285-d02b-97ceb65e2567.png)

ノードを右クリックして[ループ/条件付き実行]＞[反復キーの定義（フィールド）]を選択します。
![スクリーンショット 2023-03-13 14.55.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2f610bea-fe81-240d-2826-fb59481a7f84.png)

以下の通りに設定します。
![スクリーンショット 2023-03-13 14.57.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/699365ea-2cef-d741-ca5f-98cbc9078429.png)

ストリームのプロパティ画面の　[実行]タブが定義されました。ヒストグラムノードの[color_filed]に３つのフィールドがループされる設定です。
![スクリーンショット 2023-03-13 14.57.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/5728b447-cc8a-d679-a27c-f92de7f56e62.png)

画面上の再生ボタン▶︎を押すと３つの種類のグラフがループ実行されます。
![スクリーンショット 2023-03-13 15.00.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/7103f910-4584-d77f-549f-cc021f1fe958.png)


#### 注意事項

250種類以上のカテゴリを同時に扱う場合には以下を参考にしてください。

https://qiita.com/416nishimaki/items/0522f72e897fcb222a61#%E5%B0%BA%E5%BA%A6%E4%B8%8D%E6%98%8E%E3%82%92%E5%90%8D%E7%BE%A9%E5%9E%8B%E3%81%AB%E3%81%99%E3%82%8B

## 4.参考情報

#### GUIループについて解説した記事

https://qiita.com/Makimaki2020/items/30ee2ce06cdba477edc8

https://www.ibm.com/blogs/solutions/jp-ja/modeler-tips-23/

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

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

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

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
Javaのオブジェクト指向プログラミング入門：初心者でもわかる基本の書き方

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回は具体的なオブジェクト指向Javaについて更に詳しく調べてみましょう！
![インスタスライド_202303061.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/aa1a3759-70c2-617d-4120-51a2d96beb63.gif)


# オブジェクト指向をJavaで書く

```java
// 人間をクラス化
public abstract class 人間{

                 String name;

	void 挨拶ｽﾙ(）｛
		System.out.println("こんにちは、"country + "人です。" );
}
```

```java
// 人間クラスを継承した日本人クラス
public class 日本人 extends 人間{

	String country ="日本";

}
```

```java
// 人間クラスを継承したアメリカ人クラス
public class アメリカ人 extends 人間{

	String country ="アメリカ";

}
```
```java
// 日本人、アメリカ人クラスをインスタンス化

///日本人をインスタンス化
人間 森川  = new 日本人();

///アメリカ人をインスタンス化
人間 ケント = new アメリカ人();

森川.挨拶ｽﾙ();
ケント.挨拶ｽﾙ();
```
# まとめ
ーJava版でオブジェクト指向を理解しよう

ー人間をクラス化

ー人間クラスを継承した日本人クラス

ー人間クラスを継承したアメリカ人クラス

ー日本人、アメリカ人クラスをインスタンス化

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
Apple Silicon Dockr 上での Failed to initialize inotify (Errno::ENOSYS) を根本的に回避する方法


Rails に限らず、 Ruby 製の WebFreamwork を Apple Silicon の Docker 上で使っていると下記のエラーに遭遇することがあります。

```bash
/var/www/bundle/ruby/3.0.0/gems/rb-inotify-0.10.1/lib/rb-inotify/notifier.rb:69:in `initialize': Function not implemented - Failed to initialize inotify (Errno::ENOSYS)
```

私の場合 M2 MacBook Air 上の Docker で middleman を使おうとしてこのエラーに遭遇しました。
だいぶ悩まされましたが、多分これで根本解決だという方法を見つけたので、メモとして残しておきます。
おそらくですが、 Rosetta2 がない環境でもこれで動くと思います。

#### 追記

一晩明けて、上記エラーが出ない最小条件を探っていたのですが、どうも Ruby のイメージを arm64/v8 にするだけでいい様です（gem のインストール場所だけ解決する必要があります）。
でもまぁ一応調べたことは調べたことなので、削除はせずに残しておきます。

### Ruby のイメージを arm64/v8 にする

https://hub.docker.com/r/arm64v8/ruby/

上記からダウンロードした Ruby のイメージを使いましょう。

### docker-compose.yml に platform を追加する

```docker-compose.yml
version: "3.9"

services:
  middleman:
    build: .
    platform: linux/arm64/v8
    command: bundle exec middleman server
    volumes:
      - ./:/var/www
    ports:
      - "4567:4567"
```

のように、 `platform: linux/arm64/v8` を付け足しましょう。

### rb-fsevent という gem のバージョンを 0.11.2 以上にする

この rb-fsevent という gem はバイナリを含んだ gem なのですが、そのバイナリが arm64 に対応するようにコンパイルされ直したのが 0.11.0 以上のようです。

https://github.com/guard/rb-fsevent/pull/88

だから多分 0.11.0 でも動くとは思うのですが、私が動作確認しているのは 0.11.2 なので章タイトルはそう書かせていただきました。

### Bundle を arm64 用に設定する

```bash
$ bundle lock --add-platform aarch64-linux
```

このコマンドを実行すると、 Gemfile.lock に「今使ってるのは arm64 だよー」と書き込んでくれます。

https://zenn.dev/fuuukeee3/articles/df15e32cf3706407a0a6

### Docker 上の bundle_path を永続化する

普段 rubylang/ruby の Docke Image を使っていると気づかないハマりどころなのですが、先ほど紹介した arm64/v8 をはじめとした Docker 公式をベースにした Docker Image は BUNDLE_PATH が `/usr/local/bundle` に固定されている様です。
この設定を外すのも悪くはないのですが、個人的にはこういう設定をわざわざ入れてきているのならそれに沿った方がいいだろうと思ったので、パスの設定はそのまま永続化だけすることにしました。
方法は以下の通りです。

```docker-compose.yml
version: "3.9"

services:
  middleman:
    build: .
    platform: linux/arm64/v8
    command: bundle exec middleman server
    volumes:
      - ./:/var/www
      - installed_gem:/usr/local/bundle
    ports:
      - "4567:4567"
volumes:
  installed_gem:
```

上記のように volumes の設定を追加しましょう。

https://qiita.com/frozenbonito/items/0c515929aba4093e7c47

### まとめ

ここまでやって、ちゃんと `docker compose run --rm container_name bundle install` をしてからフレームワークを動かしてみると、冒頭のエラーは出なくなっているかと思います。

そもそもの Ruby のイメージを arm64/v8 にするというところが1番のキモだと思っています。

このメモが誰か他の人のお役に立てば幸いです。
フロントを触って詰まったところメモ

ヘッダー、ホームとあと1ページくらい作るところまでやってみてから、バックエンドの導入に行きたいなと思い軽く触っていきます。
その中で、詰まったところなどをメモしていくようです。（コード自体にはあまり触れないかも）
## TypeScriptのスタイル
初めにヘッダーを編集していこうと思ったら、参考にしたサイトのTypeScriptの書き方が、普段の業務と違い、よく分からなかった、、、
（って思ったけど、よく見たらJavaScriptで書かれてたw）

どうやら普段書いているスタイルはClassComponent(ClassAPI)というclassスタイルで、結構広く使われているもののよう。
vue2までは、ほかにOptionAPIというobjectスタイルがあるようで、僕が参考にしたのはこちらのよう（←JSだよ）

また、Vue3からはCompositionAPIが登場し、こちらが推奨されているよう

調べたことを軽くまとめると
Vue2までは、ClassComponentとOptionAPIがあり、OptionAPIのほうがJavaScriptと近い書き方で、今までJavaScriptで開発していた人はこちらのほうが慣れやすいとのこと
ただClassComponentのほうがすっきりかけ、利用者も多いことから、採用されることが多かったらしい
ただ、そもそもVue2の標準言語がJavaScriptだったため、TypeScriptの型推論があまり本領発揮できていなかった、、、

それがVue3では、標準言語がTypeScriptになったことにより、CompositionAPIが登場し、型推論等にも対応できるようになったらしい。
書き方的には、OptionAPIに近そうでClassComponentで書いていた自分としては、慣れるのに少し時間が必要そう、、、
ただせっかくの機会だし、Vue3で推奨されているのもCompositionAPIのようなので、こちらで進めていこうと思う！！
## おわり
終わりとしていますが、適時開発しながら、詰まったところをメモって行きます
マクロ（L&S）

今回もレイアウトマクロを紹介していく。
今回は以下の様なL&Sのパターンを描画するマクロを作成した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039522/8b09f632-33bc-bd36-7c87-206581ccb3c2.png)

以下のマクロを実行すればL&Sを描画できる
```
#!/usr/bin/layout
#name=donut array
#help=an array of donut with different parameter


int main(){
  int w=100000;                       //短辺の長さ
  int p=500000;                       //ピッチの長さ
  int l=1000000;                      //長辺の長さ
  int n=5;                             //繰り返しの回数
  int x=0;

  for(x=0;x<n;x++){
 
  //矩形を作成
  layout->drawing->point(0 + x*p, 0);
  layout->drawing->point(w + x*p, 0);
  layout->drawing->point(w + x*p, l);
  layout->drawing->point(0 + x*p, l);
  layout->drawing->polygon();
  layout->drawing->currentCell->firstElement->thisElement->selectAll();
  
  }
                 }
```
今日はここまで
位置情報アプリwhat3words無料Public APIキーの発行手順

<h1>what3wordsとは？</h1>
世界を57兆個の3メートル四方の区画に分割し、それぞれのマス目に三単語からなる住所の付与。

これにより住所が存在しない大規模な施設の入り口や、広い公園の敷地内、人里離れた場所でもピンポイントで住所を伝える事が可能になります。
>what3wordsの従来の位置エンコードシステム（符号化方式）との違いは、地理的座標を長い文字列（住所など）や数字（経緯度など）ではなく、3つの単語で簡潔に表せる点にある。すなわち、住所が存在する場所ならばより詳細な地点を明確に、住所が存在しない場所であっても、冗長な緯経度を用いないで容易に伝達ができる。
例えば、東京・渋谷のスクランブル交差点の中心部は緯経度で表せば「北緯35.659457度、東経139.700488度」となるが、what3wordsでは同座標を「///のばす。めうえ。しゅうり」の3語で表せる。

一般ユーザー向けのアプリがある一方、個人・企業向けのAPIを提供しており、個人・団体関わらず無料で発行できます。
（活用法などに関しては別途紹介します）


まずはアカウントの作成をします
------------------------------------------------

**①下記リンクにアクセスし、サインアップオプションを選びます**
https://accounts.what3words.com/login
<img width="800" alt"Screenshot 2023-03-17 at 17.24.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289659/0181b579-ff91-a7ac-b1fb-866f7df5e4fb.png">

**②名前、メールアドレスやパスワードを設定します**
<img width="800" alt"Screenshot 2023-03-17 at 17.26.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289659/a5ebd8d4-774c-a8fc-0cd5-b60f98525491.png">
下にチェックボックスがいくつかあります。順番に：
*□ 利用規約・プラバシーポリシーの同意<font color="Red">（必須）</font>
□ 新着記事やティップスの受け取り
□ デベロッパー向けメルマガの受けとり*

以上でアカウントの作成完了です！

**次にライセンスキーの発行をします**
--------
**③下記リンク「Get an API Key」からライセンスキーの発行**
https://developer.what3words.com/
<img width="800" alt"Screenshot 2023-03-20 at 16.35.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289659/742beedf-46c1-344d-56da-713e3a7bb121.png">

**④「STARTER」プランの「Get Started」を選択**
<img width="800" alt"Screenshot 2023-03-20 at 16.25.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289659/dbeb146d-f4c1-9566-79ef-5aedeba3fdeb.png">

:::note warn
特段の事情がない限り、無料の「Starter」プランからのご利用開始をおすすめします。
:::

「STARTER」プランは毎月1000件までのコール（三単語→座標）が上限となってます。
APIで主に下記機能をご利用頂けます（2023年3月）：
→ what3wordsアドレス（三単語）から緯度経度への座標変換
→ 緯度経度からwhat3wordsaアドレスへの変換
→ 50ヶ国語以上に対応
→ 地図上にグリッドの表示



**⑤ チェックボックスにて利用規約の同意**
<img width="800" alt"Screenshot 2023-03-20 at 16.23.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289659/260f3787-f7ba-1e95-ba5a-bbb680ef68ad.png">

**⑥ 会社名・業種の入力（任意）**
<img width="800" alt"Screenshot 2023-03-17 at 17.32.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289659/149b3675-1352-7f24-0824-ef822887bc90.png">


**⑦ プロジェクト名・詳細の入力<font color="Red">（必須）</font>**
<img width="800" alt"Screenshot 2023-03-17 at 17.32.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289659/e3964de8-0199-0f3d-f187-458cd2e1f0fa.png">

:::note warn
プロジェクト名 (Project name) や詳細 (Please tell us a bit more about your project) を入力できない場合、「test」などと入力ください
:::
 □ この時点でキーに制限をかけることができますが、後からもかけられます。

**⑧ これで以上となります！キーは画面中央に表示されます。**
<img width="800" alt"Screenshot 2023-03-20 at 17.09.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289659/f0e687a4-0cfb-100a-9d71-5a831f804431.png">


<strong>まとめ</strong>
・キーの発行にはまずアカウントの作成（https://accounts.what3words.com/login）
・アカウント作成後、キー発行画面で利用規約に同意（https://developer.what3words.com/）
・無料ティアーでの月間のコール上限（what3wordsアドレス→緯度経度・座標への変換）は1000件まで
・1つのアカウントで複数のキーを発行可能

如何でしたでしょうか。オンライン利用規約に同意するだけでキーを発行でき、連携を簡単にできます。
具体的な活用法などは追ってご紹介できればと思います。
WSUSで承認、あるいは拒否した更新プログラムを未承認に戻したかった

見出しのようなことは滅多にないかと思われますが、GUIではできるのであればPowerShellからも操作できるのではと思い調べてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667945/4d03eec5-1a26-5e20-6940-ba36d747fa6e.png)

# サンプル
更新プログラムを1つ、`すべてのコンピューター` に対して `NotApproved` (未承認) にしてみましょう。

```PowerShell
$Update = @(Get-WsusUpdate -UpdateServer (Get-WsusServer))[0]
Approve-WsusUpdate -Update $Update -Action NotApproved -TargetGroupName "すべてのコンピューター"
```
```PowerShell
$WsusServer = Get-WsusServer
$Updates = @($WsusServer.GetUpdates())[0]
$ComputerTargetGroup = $WsusServer.GetComputerTargetGroup([Microsoft.UpdateServices.Administration.ComputerTargetGroupId]::AllComputers)
$Update.Approve([Microsoft.UpdateServices.Administration.UpdateApprovalAction]::NotApproved,$ComputerTargetGroup)
```

`$Update` には、サンプルなのでとりあえずなんでもいいので1つ目の更新プログラムを取得しています。
本番環境での更新プログラムの抽出に、こんな乱暴な書き方をしてはいけません。
関数によって返ってくる1つ目の更新プログラムは異なりますが、結果は同じためサンプルとして掲載しました。

# 結果
すると、いずれも `InvalidOperationException` となります。
なぜか"すべてのコンピューター"に対してはできないようになっているようです。

```
希望された更新プログラムの承認は、指定されたコンピューター ターゲット グループに対して無効です。
The desired update approval is not valid for the specified computer target group.
```

## InvalidOperationException
(中略)
- You cannot create a block approval to the All Computers target group.
- The desired action cannot be used because a dependency has been approved for the opposite action.

https://learn.microsoft.com/ja-jp/previous-versions/windows/desktop/ms747134(v=vs.85) 引用

## NotApproved
- (中略) This value can be used in a simple targeting ComputerTargetGroup to "override" a UpdateApproval made to the "All Computers" ComputerTargetGroup.

https://learn.microsoft.com/ja-jp/previous-versions/windows/desktop/ms752788(v=vs.85) 引用


# メモ
ちなみにですが、"すべてのコンピューター"でなければ可能なようです。
GitHub Copilot for CLI があればコマンドなんてもう覚えなくていいのでは？

# GitHub Copilot for CLI があればコマンドなんてもう覚えなくていいのでは？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905557/e370e49d-7f97-32a3-8b21-64fa87ef9298.png)

どうも @ekusiadadus です。
なぜか、ウェイティングリストの最初をもらうことが多いです <- 本当に謎
OpenAI の GPT-4 とか 今回の GitHub Copilot とか
その分、レビューして貢献していこうと思います

今回は、GitHub Copilot for CLI に関してです
[公式](https://githubnext.com/projects/copilot-cli/) によると

> シェルのコマンドやフラグを覚えるのに苦労したことはないだろうか。シェルにやってほしいことをそのまま言えたらいいのに、と思ったことは？GitHub Copilot のアシスタンスをターミナルに組み込むことで、そんな心配はもういらない。 (意訳)

ということで、CLI で GitHub Copilot を使えるようになりました。

GitHub Copilot for CLI は、GitHub Copilot と同じく、AI がコマンドを生成してくれるものです。

コマンドは、**3 つ**です

## 使い方

1. `??`
2. `git?`
3. `gh?`

## `??`

このコマンドは、**シェルの任意のコマンドを AI に聞くこと**ができます。

**公式**

1. TypeScript のファイルを検索したい
1. node_modules の中身は無視したい
1. サイズでソートをかけたい

![copilotcli1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905557/8d281c26-cb0a-5f7c-b979-8b5e0e59b5a2.gif)

**やってみた**

1. Go 言語をインストールしたい
1. Go 言語のバージョンは、1.21 にしたい
1. apt-get でなく、wget を使いたい

![copilotcli4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905557/4d085c2f-95ad-5c48-fcc7-0eb92a059bdb.gif)

少し意地悪をして、まだリリースされていない`go1.21` をインストールしたいというコマンドを AI に聞いてみました。

上の gif をみると、go1.16.3 を進めてきたり、apt-get を使わないでという指示を無視するので、まだ完全ではありませんが、言語やアプリをインストールする際に、Google に聞く必要はなくなりそうです。

## `git?`

`git?`は、git の起動に特化した検索に使用されます。`git?`と比べると、git コマンドを生成する能力が高く、git のコンテキストであることを説明する必要がない場合は、クエリーをより簡潔にすることができます。

とのことです。
おそらく内部的には、`??` と同じで事前に git コマンドであるという学習をさせているのではないかと思います。
もしかしたら、学習データを git コマンドに特化させているのかもしれません。(未確認)

**公式**

1. ブランチを削除したい
2. `test-branch-1`を削除したい

![copilotcli2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905557/5ae05c33-8af1-631f-33ba-89275b754ed1.gif)

**やってみた**

1. main ブランチ を deploy ブランチにマージしたい
2. main ブランチのいくつかのコミットのみをマージしたい

![copilotcli5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905557/8829b528-0d8b-819b-1b09-d93783c3cefd.gif)

上のような感じで、日本語でも答えてくれますが前後の文脈を読んでくれているのかは微妙だと思います。
単純にプロンプトをつなげているだけのようにも見えます。

## `gh?`

`gh`は、GitHub CLI のコマンドとクエリのインターフェイスのパワーと、AI が複雑なフラグと `jq` を生成してくれる便利さを兼ね備えています。

**公式**

1. vercel/next.js のリポジトリの issue を開きたい
2. shell 上で開きますか？

![copilotcli3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905557/ef796c36-8585-809a-2905-90495cb83ccb.gif)

**やってみた**

1. GitHub で assign されている PR を全て列挙する
2. GitHub の PR ページを開く

![copilotcli6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905557/3dc57eb6-c8a0-37b6-c4f5-26404bb5cdc1.gif)

WSL からやったので、WSL GUI　が出てしまいましたが、良さげ

ただ、ちゃんと聞かないとたまにやばいコマンドを打ち出すことがあるので気を付けてください。

![copilotcli7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905557/04301bc3-235c-d56c-12ff-ee885910ccf3.gif)


## インストールはこちらから

https://www.npmjs.com/package/@githubnext/github-copilot-cli
Go net/httpサーバーのホットリロードにAirを使ってみた

# はじめに
Goのnet/httpを使ったAPIプロジェクトを開発しています。デバッグの際、都度ビルドし直すのが面倒なので、いい感じにホットリロードできるという[Air](https://github.com/cosmtrek/air)を導入したくなりました。

## 開発環境
- Windows10
- VSCode

## 調べてみた
Docker-composeを使った事例 (参考参照)が多く出てきました。ただ、docker-composeで実行するのは若干面倒なので、それ以外の方法は無いのかと探してみることにしました。

# 見つけた いい感じの方法
- Devcontainerに airをインストールして、DevContainer上で実行する。
  - Windows10でdocker-composeで実行するとAirでファイル変更が検知されない? 場合があると知り合いに聞いたが特に問題なく上手くいった。(筆者環境では) 

## 方法
- リポジトリ直下に `.devcontainer` フォルダ作成
- .devcontainerフォルダ内に 下記内容のdevcontainer.json を作成

```
{
	"name": "Go",
	"image": "mcr.microsoft.com/devcontainers/go:0-1-bullseye",
	"features": {
		"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
			"moby": true,
			"installDockerBuildx": true,
			"version": "latest",
			"dockerDashComposeVersion": "v2"
		}
	},
	"postCreateCommand": "go install github.com/cosmtrek/air@latest"
}
```
- 保存し、プロジェクトを再度開き直す
- DevContainerを開くかどうかVSCodeに確認されるので、DevContainerとして開き直す
- インストール完了後 プロンプト上で `air` と打って Airを立ち上げる
- 以後 コードの変更に応じて ホットリロードが行われる

# できた感想
- Windowsで導入するのめんどくさそうと思っていたけれど、かなりあっさり導入できた...

# 参考
- https://qiita.com/abemaru/items/b322e606343ffd99af9c
- https://github.com/cosmtrek/air
- https://github.com/cosmtrek/air/issues/274
  - WSL領域にリポジトリをまるごと配置し、その中で実行することでもファイルの変更が検知できるらしい
ベータ分布に従う2つの確率変数の差の分布を数値積分により算出する方法

　ベイジアンABテストなどで、ベータ分布に従う2つの確率変数の差の分布を知りたくなることがあります。しかし、これは解析的には導出できないため、サンプリングにより近似することが多いと思います。ただ、例えば滑らかな確率密度関数を得ようとすると、大量のサンプリングが必要になり使い勝手が悪いです．

　そこで、本ページでは、scipyの数値積分のための関数であるintegrateを使って、ベータ分布に従う2つの確率変数の差の確率密度関数や累積分布関数を計算する方法について記載します．

　以下では、実装方法を記載し、その使い方について記載します．

# 実装方法

　まず、実装は以下においています．

https://github.com/uduwudu2/beta_diff/blob/main/beta_diff/beta_diff.py

例えば，確率密度関数を計算する箇所は以下です．

```python
    def pdf(self, t):
        betaln1 = betaln(self.alpha1, self.beta1)
        betaln2 = betaln(self.alpha2, self.beta2)
        if t <= -1 or t >= 1:
            return 0
        elif t <= 0:
            val = integrate.quad(
                beta_diff.jnt_dst,
                -t,
                1,
                args=(t, self.alpha1, self.beta1, self.alpha2, self.beta2, betaln1, betaln2),
            )[0]
            return val
        else:
            val = integrate.quad(
                beta_diff.jnt_dst,
                0,
                1 - t,
                args=(t, self.alpha1, self.beta1, self.alpha2, self.beta2, betaln1, betaln2),
            )[0]
            return val
```

 次に使い方について説明します。使い方はscipy.statsの各種分布のための関数ライクに使うことを想定しています。試しに$Beta(11, 11)$と$Beta(16, 6)$に従う確率変数の差の分布を出してみます．下記のように、まず、2つのベータ分布のパラメータを指定して、その後、確率密度関数や累積分布関数を算出します。平均と分散、標準偏差も一応実装しています。

```python
beta_diff_test = beta_diff(11, 11, 16, 6)
print('差が0となるときの確率密度関数:', beta_diff_test.pdf(0))
print('差が0以下になるときの累積分布関数:', beta_diff_test.cdf(0))
print('平均値:', beta_diff_test.mean())
print('分散:', beta_diff_test.var())
print('標準偏差:', beta_diff_test.std())
```

```
差が0となるときの確率密度関数: 0.7659444329930765
差が0以下になるときの累積分布関数: 0.9445509291914406
平均値: -0.2272727272717359
分散: 0.019493352488142934
標準偏差: 0.1396185964982564
```

　100000個サンプリングした場合のヒストグラムと比較したものが以下です。精度良く確率密度関数が計算できていることが分かります。

![beta_diff_pdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670764/d854958e-93fc-d8e0-3b1b-db92d1aa3d55.png)

　また、下記のように差が0となる点での確率密度を算出するための実行時間を計測すると、google colaboratory pro上で29 µsとかなり高速であることが分かります。

```python
%timeit beta_diff_test.pdf(0)
```

```
29 µs ± 821 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
```
AIでゲームのキャラクターを生成する【MacでStable Diffusion】

![スクリーンショット 2023-03-21 23.34.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/4d8fc2e9-3cbc-5b25-850c-f7a4d8a147ef.png)

# ゲームのキャラ絵をAIで作る

ゲームのキャラ絵は価値があります。ユーザーはキャラ絵のためにガチャを回し課金します。
今回はAIでキャラ絵を一発で作ってみます。Macでできます。

### モデルをダウンロード

ゲーム／アニメ風のキャラを生成できるAIはいくつかありますが、今回はOrangeMixというStableDiffusionモデルを使います。
モデルは[CoreML-Models](https://github.com/john-rocky/CoreML-Models)からダウンロードできます。

https://github.com/john-rocky/CoreML-Models

### Macアプリをダウンロード

アプリは[MochiDiffusion](https://github.com/godly-devotion/MochiDiffusion)を使います。
以下からダウンロードします。

https://github.com/godly-devotion/MochiDiffusion

MochiDiffusionアプリを立ち上げるとMacのDocumentsフォルダにdocuments/MochiDiffusion/modelsディレクトリが作成されるので、そこにCoreML-Modelsからダウンロードしたモデルを置きます。

![スクリーンショット 2023-03-22 0.11.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/c0b40f9a-6cee-c115-0da2-27a6f66e5eba.png)

### 実行
アプリのモデルでOrangeMixを選び、欲しいキャラを表すテキストを入れて実行します。
「青い髪」や「勇者」など欲しいキャラの属性で生成できます。

![スクリーンショット 2023-03-21 23.34.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/4d8fc2e9-3cbc-5b25-850c-f7a4d8a147ef.png)

🐣
****
フリーランスエンジニアです。
もし以下のようなご要望をお持ちでしたらお気軽にご相談ください。
AIサービスを開発したい、ビジネスにAIを組み込んで効率化したい、AIを使ったスマホアプリを開発したい、
ARを使ったアプリケーションを作りたい、スマホアプリを作りたいけどどこに相談したらいいかわからない…

いずれも中間コストを省いたリーズナブルな価格でお請けできます。

お仕事のご相談はこちらまで
rockyshikoku@gmail.com

機械学習やAR技術を使ったアプリケーションを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
squidclientコマンド

●squidclientコマンド
Squidの動作を確認するためのコマンドラインツール。Squidのキャッシュや管理情報にアクセスしたり、WebクライアントとしてHTTPリクエストを送信し、Webサーバやプロキシサーバのテストを行う

書式：
squidclient　オプション　URL

squidclientコマンドの主なオプション

・-h　ホスト　URLを検索するプロキシのホスト名/IPを指定
・-p　ポート番号　プロキシのポート番号を指定(デフォルト:3128)
・-m　メソッド　HTTPリクエストのメソッドを指定(デフォルト:GET)
・-u　ユーザ名　プロキシ認証のユーザを指定
・-w　パスワード　プロキシ認証のパスワードを指定
ChatGPTでの開発に役立つソースコード

```python

import os
import fnmatch

# Define the pattern to match
pattern = "*.go"

# Find all files that match the pattern
for root, dirs, files in os.walk(".", topdown=False):
    for filename in files:
        if fnmatch.fnmatch(filename, pattern):
            # Print the file name with its path
            print("```"+os.path.join(root, filename))
            
            # Print the source code
            with open(os.path.join(root, filename), "r") as f:
                print(f.read())
            print("```\n")
```

```
python dirshown.py >> code
.txt
```

## ディレクトリツリー追加版

```python
import os
import fnmatch

def print_directory_tree(start_path):
    for root, dirs, files in os.walk(start_path, topdown=True):
        # Exclude .git directory
        if '.git' in dirs:
            dirs.remove('.git')
        
        level = root.replace(start_path, '').count(os.sep)
        indent = ' ' * 4 * level
        print('{}{}/'.format(indent, os.path.basename(root)))
        sub_indent = ' ' * 4 * (level + 1)
        for f in files:
            print('{}{}'.format(sub_indent, f))

# Print the directory tree
start_path = "."
print("```DirectoryTree")
print_directory_tree(start_path)
print("```\n")
# Define the pattern to match
pattern = "*.go"

# Find all files that match the pattern
for root, dirs, files in os.walk(".", topdown=False):
    for filename in files:
        if fnmatch.fnmatch(filename, pattern):
            # Print the file name with its path
            print("```"+os.path.join(root, filename))
            
            # Print the source code
            with open(os.path.join(root, filename), "r") as f:
                print(f.read())
            print("```\n")
```
Freshの備忘録 Part1 ~ GETとPOSTメソッドの使い方 ~

基本的な内容ですが、Freshを学んでいるときに地味に時間を要してしまったので、残しておきます。

## 内容
GETとPOSTでのデータの受け渡し方法について

### ■GETでのデータ受け渡し
データ送信用のページ
```typescript:routes/get-send.tsx
import { Handlers, PageProps } from "$fresh/server.ts";

export default function GetSendPage() {
  return (
    <div>
      <form method="GET" action="/get-reception">
        <input type="text" name="userName" />
        <button type="submit">Submit</button>
      </form>
    </div>
  );
}
```
データ受信用のページ
```typescript:routes/post-reception.tsx
import { Handlers, PageProps } from "$fresh/server.ts";

interface Data {
  userName: string;
}

export const handler: Handlers<Data> = {
  async GET(req, ctx) {
    const url = new URL(req.url);
    const userName = url.searchParams.get("userName") || "";
    return ctx.render({ userName });
  },
};

export default function PostReceptionPage({ data }: PageProps<Data | null>) {
  if (!data?.userName) {
    return <h1>そんなユーザーはいないでござる</h1>;
  }

  return (
    <div>
      <h1>{data.userName} です </h1>
    </div>
  );
}

```

### ■POSTでのデータ受け渡し
データ送信用のページ
```typescript:routes/post-send.tsx
import { Handlers, PageProps } from "$fresh/server.ts";

export default function PostSendPage() {
  return (
    <div>
      <form method="POST" action="/post-reception">
        <input type="text" name="userName" />
        <button type="submit">Submit</button>
      </form>
    </div>
  );
}
```
データ受信用のページ
```typescript:routes/post-reception.tsx
import { Handlers, PageProps } from "$fresh/server.ts";

interface Data {
  userName: string;
}

export const handler: Handlers<Data> = {
  async POST(req, ctx) {
    const formData = await req.formData();
    const userName = formData.get("userName")?.toString() || "";
    return ctx.render({ userName });
  },
};

export default function PostReceptionPage({ data }: PageProps<Data | null>) {
  if (!data?.userName) {
    return <h1>そんなユーザーはいないでござる</h1>;
  }

  return (
    <div>
      <h1>{data.userName} です </h1>
    </div>
  );
}

```


## 参考資料
https://fresh.deno.dev/docs/getting-started/form-submissions
【シェルスクリプト】一時的にユーザーを変更してコマンドを実行する

## 実行方法

次のようにコマンドを実行すると一時的にユーザーを変更してコマンドを実行できます。  

```terminal
su ユーザー名 -c "コマンド"
```

```terminal
root $ su sample -c "whoami"
sample
```

以下のようにも記述できます。  

```zsh
su ユーザー名 <<-EOF
コマンド
EOF
```

```test.sh
su sample <<-EOF
whoami
EOF

whoami

```

```terminal
root $ bash test.sh
sample
root
```