OmniAICreator/Qiita-1.07M huggingface dataset:
WEBフロントエンドを学びたいけど迷子になっている人へ英語講座のすすめ

WEBフロントって、興味があるけどどう勉強すればいいかわからない。HTML、CSSをなぞってみたけどその先のチャートが立てられない。そういう悩みがあると思います。

今回はWebフロントのさわりはやってみたけど、その後どうすればいいかわからないかつ動画講座に興味がある人に向けて「英語のUdemy講座をつまみ食いしてみる」という勉強方法を紹介していこうと思います。

## 英語のUdemy講座のメリット
- 英語での言い回しが身につく
- メンテナンス頻度が高い
- おしゃれな見た目の講座が多い

検索をする上で英語での言い回しがわかると便利な場面は多くあります。また、日本語記事が少なく英語で調べるケースというのはプログラミングにおいてはかなりよくあることなので、今のうちに覚悟を決めて英語を学ぶぞと自分を鼓舞するためにも英語の講座を受けるのも良いかもしれません。

## 自分が買ってみてよかったコース

- [Complete React Developer in 2023](https://www.udemy.com/course/complete-react-developer-zero-to-mastery/learn/lecture/29209634?start=0#overview)
Reactについてのモダンな話も含めて行なっている講座です。毎年改訂をおこなっているらしく、また表面的なことをなぞるだけではなくパフォーマンスについての言及もあり体系的にReactを学びたいかつ動画で講座を受けたい場合にはおすすめです。
Reactの公式Documentなどで迷子になってしまった方におすすめです。

- [Advanced CSS and Sass: Flexbox, Grid, Animations and More!](https://www.udemy.com/course/advanced-css-and-sass/)
SASSのおしゃれなページ作りたい時にざっくりとみる時に使っています。CSS　Grids　、FlexboxなどCSS3で追加された要素も含めて丁寧に解説されている講座です。
演習のアプリケーションもおしゃれなのも勉強のモチベーションが上がる一つの要因で、CSS学びたいという人にはぜひと勧めたくなる講座です。

- [JavaScript Web Projects: 20 Projects to Build Your Portfolio](udemy.com/course/javascript-web-projects-to-build-your-portfolio-resume/)
JSだけでこんなこともできるのか！！と驚いた講座です。プレビューを見て作ってみたい！というものがいくつかあれば受けてみる価値はあるのではないでしょうか。JSのDOMAPIについてより深く知れるのかなという印象はあります。

上記以外にもAdobeのXDの講座やAWSなどの有料ソフトの講座に関してはかなりUdemyを活用する機会が多く、英語講座に対するハードルが低いだけでグッと受けられる講座の幅やコスパが広がると筆者は考えております。英語力も一種のスキルと思いフロントエンドだけではなく英語の検索力も鍛えてみてはいかがでしょうか？
【Playdate】入力ハンドラを使う

Playdate には playdate.InputHandlers オブジェクトを使うことでキー入力の制御をまとめて管理することができます。
例えばフィールド画面では十字キー操作でプレイヤーを移動するように、メニュー画面ではメニューUIの操作をするように InputHandler オブジェクトを切り替えるといった感じです。

[こちらの記事](https://qiita.com/sada_lp1/items/1751040555361bae33b7)の`main.lua`のplaydate.update内のキー入力をInputHandlerに変更してみます。

```main.lua
import "CoreLibs/object"
import "CoreLibs/graphics"
import "CoreLibs/sprites"
import "CoreLibs/timer"

local gfx <const> = playdate.graphics

local playerSprite = nil

local playerMoveX = 0 -- playerのX移動距離
local playerMoveY = 0 -- playerのY移動距離

-- 入力ハンドラオブジェクト
local myInputHandlers = {
	upButtonDown = function()
		playerMoveY = -2
	end,
	upButtonUp = function()
		playerMoveY = 0
	end,
	
	rightButtonDown = function()
		playerMoveX = 2
	end,
	rightButtonUp = function()
		playerMoveX = 0
	end,
	
	downButtonDown = function ()
		playerMoveY = 2
	end,
	downButtonUp = function ()
		playerMoveY = 0
	end,
	
	leftButtonDown = function ()
		playerMoveX = -2
	end,
	leftButtonUp = function ()
		playerMoveX = 0
	end,
}

function myGameSetUp()

    local playerImage = gfx.image.new("Images/playerImage")
    assert( playerImage )

    playerSprite = gfx.sprite.new( playerImage )
    playerSprite:moveTo( 200, 120 )
    playerSprite:add()

    local backgroundImage = gfx.image.new( "Images/background" )
    assert( backgroundImage )

    playdate.inputHandlers.push(myInputHandlers) -- 入力ハンドラを追加

    gfx.sprite.setBackgroundDrawingCallback(
        function( x, y, width, height )
            backgroundImage:draw( 0, 0 )
        end
    )

end

myGameSetUp()

function playdate.update()

    playerSprite:moveBy( playerMoveX, playerMoveY ) -- playerを移動

    gfx.sprite.update()
    playdate.timer.updateTimers()

end
```

InputHandlersオブジェクト内で使える関数は以下が扱えます。
- AButtonDown()
- AButtonHeld() ※Aボタンを一秒間押したあとに実行される
- AButtonUp()
- BButtonDown()
- BButtonHeld() ※Bボタンを一秒間押したあとに実行される
- BButtonUp()
- downButtonDown()
- downButtonUp()
- leftButtonDown()
- leftButtonUp()
- rightButtonDown()
- rightButtonUp()
- upButtonDown()
- upButtonUp()
- cranked(change, acceleratedChange)
～快適な配線のために～ワイヤリングペンを自作する

# はじめに

鈴鹿高専アドベントカレンダー4日目の記事です。

https://qiita.com/advent-calendar/2022/snct

時間がないので省力化仕様にしよう(殴

# 背景

プロト基板を作る際によくお世話になるUEWですが、流石に0.16mmとなると手でもって配線するのはしんどいですよね。

そこで、今回は市販のシャーペンを改造してワイヤリングペンを自作してみることにしました。

# 必要なもの

- 3Dプリンタ
- 安いシャーペン(今回は0.3mm)
- ボビン巻きのUEW(秋月で売ってる)

![8B288739-E933-4748-BECC-53494B46E92C.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/65eb8671-a3b3-c760-701b-990b5097ef09.jpeg)

シャーペンは某驚安の殿堂で買ってきました。300円しないくらいだったかな。

今回のために3Dプリンタ買いました、思ったより安くてクオリティも高かったです。

# つくりかた

写真撮ってないんですが、まずシャーペンの送り出す部分をペンチでねじ切ります。あとクリップも邪魔なので外します。

次に適当に採寸して適当にボビンを保持する部分を作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/541f4c73-d906-227c-aba3-1d8fd5196d26.png)


設計したら刷ります。

![5750C0C0-373F-4F6F-B6EB-69C8411E7F0C.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/46e6714a-af92-adac-1b5f-2c4833042d42.jpeg)

左は最初に設計したものですが、思った以上にキツキツにボビンを固定していて回らなかったので真ん中のようにちょっと緩くしました。ついでに意味もなくフィレットをつけてみたり。

右の奴はもっと小さくしてみたものですが、脆すぎてすぐに崩壊しました。

で、実際シャーペンに取り付けるとこんな感じ。

![A4FF30DD-ABC2-4684-B17B-DBDD190A581A.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/a5daf994-12ee-c85e-78ea-8f20f2c7d90c.jpeg)

0.3mmのシャーペンに0.16mmのUEWを通すのは実は結構大変で、神経を使います。

気分は裁縫の糸通し、通るように祈りましょう。

一回中に入ってしまうともう一回通すのに5分くらい時間を食います。

# 使ってみる

![B0DF3C62-E783-4A94-B045-88681D888E1C.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/a70af8bd-cbce-1e0f-f3c9-1eb2e437e6ac.jpeg)

手で配線するより圧倒的に楽ですが、手がプルプルして狙いが定まりません。慣れの問題でしょうか。

次にこれは適当に作ったアケコンの変換基板。

![IMG_2078.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545164/e468487a-4eaf-0b3b-6e87-34f62671409c.jpeg)

ピンの間を通しやすくなったので密度を上げての実装もできそうです。

# 感想

はじめて3Dプリンタ使って実用的なものを作ってみましたが、3Dプリンタの出力精度に驚きました。これが3万以下で手に入るってマジ？、って感じです。

皆さんも、3Dプリンタを買って自分の作業を効率化してみませんか？

おわり
Googleフォームの回答を雑にSlackに通知する

# この記事は?

:::note
[ことみん Advent Calendar 2022](https://qiita.com/advent-calendar/2022/kotomin_m) 4日目の記事です!
:::

Googleフォームに送信された回答をSlackに通知するGASのコードを雑に書きました。誰かの参考になるかもしれません。

# フォームの内容

名前とメッセージをテキストで回答出来るフォームを作りました。
![スクリーンショット 2022-12-04 22.42.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326600/1dba0450-d831-3994-3aed-a884b53d4366.png)


# GASのコード

Slackに通知するためのWebhook URLを取得しておいてください。

```javascript
function onOpen(e) {
  var itemResponses = e.response.getItemResponses();
  
  message = "メッセージが来たよ！\n";
  
  var itemResponseName = itemResponses[0];
  var qName = itemResponseName.getItem().getTitle();
  var aName = itemResponseName.getResponse();
  message = message + qName + "\n";
  message = message + aName + "\n";

  message = message + "\n";

  var itemResponseOuen = itemResponses[1];
  var qOuen = itemResponseOuen.getItem().getTitle();
  var aOuen = itemResponseOuen.getResponse();
  message = message + qOuen + "\n";
  message = message + aOuen + "\n";

  sendToSlack(message);
}

// Slackに通知する
function sendToSlack(message) {
  const channel  = "#hogehoge"; // チャンネル名
  const hookURL = "https://hooks.slack.com/services/hogehoge"; // Webhook URL

  let jsonData = {
    "channel" : channel,
    "text" : message
  }
  let payload = JSON.stringify(jsonData)
  let options =
  {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : payload
  };

  UrlFetchApp.fetch(hookURL, options);
}
```

### こんな感じで通知されます

![スクリーンショット 2022-12-04 22.50.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326600/610a7391-e4a2-9155-c14d-c495e42bbf33.png)


# GASのトリガーを設定

イベントの種類を「フォーム送信時」に設定してください。

![スクリーンショット 2022-12-04 22.50.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326600/00a35058-008b-9bec-4ca6-85069a1732ff.png)


# おわりに

雑なコードですが、SlackAppでWebhook URLを取得しておけばコピペで動くはずです。
【AWS】VSCode Remote-SSH＋EC2な開発環境を安く安全に作る〜4. VSCodeで接続〜

[前回](https://qiita.com/soujiroy/items/1005f34c82a01bc8139b)で作成したスポットインスタンスにローカルのVSCodeからRemote-SSHで接続していきたいと思います。今回実施するのは以下の内容です。

1. 各種ツールのインストール
1. AWSCLIの設定
1. ssh_configの設定
1. VSCodeで接続

# 各種ツールのインストール
接続に使用する各ツールをインストールします。接続に使用するOSに合わせてそれぞれインストールしてください。

* [AWS CLI](https://docs.aws.amazon.com/ja_jp/cli/v1/userguide/cli-chap-install.html)
* [AWS SSM セッションマネージャプラグイン](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)
* [VSCode](https://code.visualstudio.com)

# AWSCLIの設定
AWSCLIを呼び出すためにIAMユーザを作成してアクセスキーを作成およびプロファイルの作成を行います。アクセスキーは漏洩すると不正利用される可能性があるため以下の手順などを参考になるべく安全に利用しましょう。

https://qiita.com/soujiroy/items/b296fe496c7f7eefb2b3#最初にログインするiamユーザを作成する

# ssh_configの設定
VSCode Remote-SSHで接続に使うsshの設定ファイルを作成・編集していきます。OSによりますが、ホームディレクトリ/.sshなどに置かれているconfigファイルに以下のようなエントリを追加します。
注意事項は __~/.ssh/configのHostNameに記載するインスタンスIDをスポットインスタンスが起動され直すたびに書き換える必要がある__ という点です。

```
Host i-1x2x3ccccc
    ProxyCommand sh -c "aws --profile hogefuga ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
    User $user
    HostName i-1x2x3ccccc #スポットインスタンスのインスタンスIDに書き換える
    IdentityFile ~/.ssh/hoge.pem #前々回に作成した起動テンプレートで指定したキーペア

```

# VSCodeで接続
VSCodeに以下の拡張機能をインストールし、前述の手順で作成したssh設定を使いスポットインスタンスへ接続します。
https://code.visualstudio.com/docs/remote/ssh

# 利用時の注意点
以上でスポットインスタンスに対してVSCode Remote-SSHを使った開発環境を構築することができましたが注意点として以下があります。

* スポットインスタンスで作成したデータは、スポットインスタンス中断時にデータ保存用EBSのファイルシステム以外は全て消えてしまう。
* ssh_configのHostNameはスポットインスタンス中断のたびに新しいインスタンスIDへ書き換えないといけない

2番目はどうしようもないですが、1番目はツール等を事前にAMIにインストールしておいて、それ以外のデータをデータ保存用EBSに保存しておくなどで対処することが可能だと思います。
まだまだ改善できる点はあると思うのでなにか思いついたら追記していきたいと思います。
8. Adaboost

# Adaboost
　つぎはAdaboostです。昨日のGradientBoostingでは、各段階ではずれのみを学習していました。Adaboost系統では各段階で間違ったサンプルは重みを大きくし、その後に続くモデルでのそれらのサンプルの寄与を大きくすることで精度が改善されます。

# アルゴリズム
　また、回帰から見てみます。

## Regression
　論文は[こちら](https://www.researchgate.net/publication/2424244_Improving_Regressors_Using_Boosting_Techniques)です。3ページ目から記載があります。もともとは分類のアルゴリズムが提案されその後に回帰用のアルゴリズムが提案されました。

### 学習
1. 各サンプルの重み$w_i$でN個サンプル（のインデックス）を取得（初期化は同じ値）
1. 抽出したサンプルでモデルを学習
1. 学習済みモデルに全サンプルを適用し、予測値$\tilde{y}_i$をすべて取得
1. 損失$L_i$を計算。
    1. $L_i = |\tilde{y}_i - y_i|^2 /D$ ここで、$D = max|\tilde{y}_i - y_i|^2 \hspace{10pt} i=1,\cdots, N$
1. 平均損失を計算 $\bar{L} = \sum_{i=1}^N L_i p_i$
1. 信頼度を計算（大きいほど現在学習しているモデルは予測を外している）$\beta = \bar{L} / (1 - \bar{L})$
1. 各サンプルの重みを更新 $w_i = w_i \beta^{1-L_i}$
1. M回繰り返していなければ最初に戻る。

### 予測
　予測時には$\beta$も用います。各モデルの重みを$\log (1/\beta)$とした時の重み付き中央値を予測値として用います。

## Classification
　次に分類です。重みを用いる点は同じですが、サンプリングは実施されず分割を計算する際にのみ用いられます。

### 学習
1. 重みを初期化。$w_i = 1/N$
1. 重みとともに学習
1. エラーを計算。 $err = (予測が正解した時の重みの総和)/重みの総和$
1. 重みの更新具合を計算。$\alpha = (1-err)/err$
1. 各サンプルの重みを更新。$w_i = w_i \exp(\alpha * （不正解の場合１、それ以外０）)$
1. 重みの総和を１にスケール
1. ２～６をM回繰り返す

### 予測
　２値分類でラベルを予測する場合は、
```math
\tilde{y}_i =  \text{sign} \left( \sum^M_{i=1} \alpha_i H_i(x_i) \right)
```
を計算し、その符号が予測ラベルです。ここでは$\pm 1$を正解として与えます。ただしこの時$H_i$はラベルそのものを返します。一方、ラベルの確率は回帰と同じように計算することができるようですが、もう一度確認して追記します。

分類は実装が間に合いませんでした。

上記のものは最初期に提案されたもので現在は非常に様々な派生アルゴリズムが存在します。Adaboost自体もScikit-learnではオリジナルではなくSAMME.Rというもののようです。


以上
デジタルツインレーシング in 仙台

11月12日、13日に開催された**PLATEAU Hack Challenge 2022 in enspace（仙台）**
において、デジタルツインレーシングチームとして作成した**AI搭載ラジコンカーと連動！仙台市街デジタルツインレース**とその作品において、自分が担当した部分についてまとめます。

# AI搭載ラジコンカーと連動！仙台市街デジタルツインレースとは

**AI搭載ラジコンカーと連動！仙台市街デジタルツインレース**は、AI搭載ラジコンカーとUnity上の車が連携して走行することで、PLATEAUの仙台市のモデルを載せたUnity上の仮想空間での走行と現実での走行をつなげたデジタルツインを目指すプロジェクトでした。本プロジェクトによって、PLATEAUを使ったバーチャル空間を大画面に映した、RCカーレースで地域の活性化につながるイベントになればと考え、チームで作成いたしました。

![スクリーンショット 2022-12-04 221755.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698432/3f42927e-625d-8350-8efe-d7ff281af924.png)

本プロジェクトにおいて、自分は、右側のUnity上の仮想空間上の走行を担当しました。

# Unity側のシステムについて
自分は今回においては、Unityの仮想空間上の車の走行について、実装を行いました。Unity上に、先行提供された仙台市のPLATEAUモデルを空間上に置き、そこを車が走行するようにいたしました。

![スクリーンショット 2022-11-13 14.22.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698432/6418f857-c09b-9287-4472-6fe71fbebd75.png)

上の画像のように仙台駅前の1ブロックを車が走行するものとなっています。
この車が走行する動きを現実のAI車と連携することでデジタルツインを目指しました。

![スクリーンショット 2022-11-13 14.22.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698432/920b6764-a8ef-a9e5-25e8-649d0c670dcd.png)

視点切り替えも行えるようにしたため、このように、実際の車からどう見えるのかも体験することができます。

車の走行は**Cinemachine**を使用して特定コースを走行するようにしています。
![スクリーンショット 2022-12-04 225129.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698432/e5280d84-cf87-6bd1-de61-eae59237d35e.png "cinemachineのルート")



実際に車を走らせている様子は下部に↓

https://youtu.be/Wi_SeYXz86w

今回のハッカソンでは、現実のAIカーとの連携まで、実装できませんでしたが、今後実装できるようにしていきたいです。

# まとめ
今回の PLATEAU Hack Challenge 2022 in enspace（仙台）にて、デジタルツインレーシングのUnity部分を作成しました。今後も、継続して開発を続け、現実の車と仮想世界の車が連携して走るようにして行きたいと思います。今回のハッカソン、最高に楽しい体験になりました。また、頑張っていきます!!


# 本作品関係URL
### Protopedia
https://protopedia.net/prototype/3552

### 当日の動画

https://youtu.be/M8ltSBAjsiU
Bigqueryで定数作りたいよ


Bigqueryを使っていると、パーティションの日付等、定数化して管理したい値が結構でてきます。
という事でやってみました。**ChatGPT**。
この記事は[PTA](https://twitter.com/PTA_CyberAgent)の[アドベントカレンダー4日目](https://adventar.org/calendars/7539)の記事です。
ChatGPTについては2日目の[こちらの記事](https://ameblo.jp/oekun/entry-12777387617.html)で詳しく？解説されています！
![ChatGPT](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553/6d5c336e-03ca-fece-dd99-f2e3e35e77c8.png)
ムムム・・・
なんかおしい？　`DECLARE`は使えそうですが、`CREATE CONSTANT`はBigqueryにないような？

ともあれ、Bigqueryではクエリの再利用を目的とした定数のようなものを定義する方法は、実はいくつかあります。
用途によっては別の方法のほうが便利な場合もあるので、いくつか紹介します。

##  Google標準SQL 手続き型言語のDECLAREを使用する
こちらがChatGPTで出てきた手法(`DECLARE`)です。

``` sql
DECLARE START_DATE DATE DEFAULT DATE(
  '2022-11-19' 
);
DECLARE END_DATE DATE DEFAULT DATE(
  '2022-11-25' 
);

SELECT * FROM example WHERE _PARTITIONDATE BETWEEN START_DATE AND END_DATE
```

DECLAREは、まさに変数です。
`SET`句を使うとあとから値を代入することも可能です。
かなり柔軟なので複雑なこともできます。
しかし、定数が増えてくると、煩雑になる事もあります。

## ユーザー定義関数を使う
ユーザー定義関数を使うことでスッキリ書くこともできます。
``` sql
CREATE TEMPORARY FUNCTION const() AS (
  STRUCT(
    DATE("2022-03-15") AS start_date,
    DATE("2022-03-15") AS end_date
  )
);

SELECT * FROM example WHERE _PARTITIONDATE BETWEEN const().start_date AND const().end_date
```
まー好みの問題もあると思いますが、`STRUCT`の中にガンガン値を詰め込めるのは便利です。

しかし、これらの方法はTableauやGoogleスプレッドシート等のBIツールから呼び出したいときに使えないケースが多いです。
BIツールがこれらのステートメントに対応していない事が多いのです。
## 仮想テーブルを使う
そこでオススメなのがこの仮想テーブルを使う方法です。
``` sql
WITH const AS
(
    SELECT
    DATE("2022-11-01") as start_day,
    DATE("2022-11-30") as end_day,
)

SELECT * FROM example WHERE _PARTITIONDATE BETWEEN (SELECT const FROM start_day) AND (SELECT const FROM end_day)
```
WITHは多くのSQL実行環境に対応しているのでBIツールからの利用もできる可能性が高いです。
ただ、この書き方だと値の取り出しがやや冗長なので、`CROSS JOIN`を活用します。
``` sql
WITH const AS
(
    SELECT
    DATE("2022-11-01") as start_day,
    DATE("2022-11-30") as end_day,
)

SELECT * FROM example, const WHERE _PARTITIONDATE BETWEEN start_day AND end_day
```
取り出したいテーブルの後ろに `, テーブル名`　でカンマクロス結合になり大幅に記述を省略できます。
BIツールでの活用を見越しているクエリの場合はこの記述方法がおすすめです。

## おまけ　複数の値を詰め込みたい

``` sql
WITH const AS
(
    SELECT
    DATE("2022-11-01") as start_day,
    DATE("2022-11-30") as end_day,
    ['iOS', 'Android', 'PC'] as target_os,
)
create temporary function target_os() as (
    ['iOS', 'Android', 'PC']
);

SELECT * FROM example, const WHERE os IN UNNEST(target_os)
```
配列で詰め込んで`UNNEST`を使えば取り出せます。

みなさんも、定数を使って快適なSQLLifeを送って頂けたら幸いです。
webpack TS

# Webpack '
webpack TSをbundleするだけ

`npm i -D webpcak webpack-cli webpack-dev-server`

`npm i -D ts-loader typescript`

`webpack.config.js` *設定ファイル*

## それぞれの意味
```js
// webpackコマンドを叩いた際に下記を利用するので、exportする
module.exports = {
};

// outputのfilenameの書き方
// ファイル内容に応じたハッシュ値を頭につけられる
// キャッシュによる変更の適応不備を回避する
filename: "[contenthash]bundle.js",
```
```js
// nodeJS上にあるgolobal変数
// 現在いるpathまでの絶対PATHを参照できる
console.log(__dirname)

// path module (引数を繋げてPATHを作れる)
const path = require("path");

// current/dist/main.jsになる
// シンプルに書ける && 区切りが/じゃないwindows等にも対応
path.resolve(__dirname, 'dist', 'main.js')
```
```ts
// type="module"はwebpack使用時は必要ない
// deferは必要
<script defer></script>
```

## 最小構成
```js
const path = require("path");

module.exports = {
  mode: "development",
  
  entry: "./dist/main.js", // 起点 (bundle後のjs)
  
  output: { // 出力先と名前
    filename: "[contenthash]bundle.ts",
    path: path.resolve(__dirname, "dist"),
  },
};
```

## TS対応
```ts
const path = require("path");

module.exports = {
  mode: "development",
  devtool: "inline-source-map",
  
  // TSも含めてbundleするので起点の(TS)を指定
  entry: "./src/food-app/main.ts",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
    
    // webpack-dev-severが内部的に保持するbundle.jsの位置を決める
    // 開発時と本番時で合わせるためにディレクトリ構成と同じにすると良い
    publicPath: "/dist/",
  },

  module: {
    // JS以外のmoduleの処理方法を記述
    rules: [
    
      {
        test: /\.ts$/,
        use: "ts-loader",
        exclude: /node_modules/,
      },
      
    ],
  },
  
  resolve: {
    // TSでimport時に拡張子を補完する
    // 左から優先度が高い
    extensions: [".ts", ".js"],
  },
};

```

## タスク
```json
"scripts": {
  "start": "webpack-dev-server",
  "build": "webpack"
}
```


## ポイント
```ts
// (webpackでTSを処理する際のts.config.jsonに関して)
// ディレクトリ系の指定は無視される
// コメント消したりするするやつは適応される


// webpack-dev-severを使う場合publicPathの位置に注意する
// publicPathの指定がない場合 src="bundle.jsになる"
<script src="dist/bundle.js" defer></script>


// webpack-dev-severは内部的にbundleしたjsを持つ
// work treeにはbundleした結果を出力しない
```
```ts
// 本番環境時に耐える方法は？
// configファイルを下記のように2つ作る
webpack.dev.js
webpack.prod.js

// タスクでそれぞれのconfigを使うように指定する
"start": "webpack-dev-server --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
```
```ts
// webpack.prod.js
// devtoolがいらない
// publicPathもいらない

// Clean Pluginを入れると良い
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = { 
  entry: "..."
  output: {
    
  },
  module: {

  },
  plugins: [ // 配列の中に入れる
    new CleanWebpackPlugin()
  ]
}
```
macでシェルのメタキー(option alt)を有効化する方法を各種ターミナルまとめ

Bashやzshなど一般的なシェルではaltキーを使った便利なショートカットが存在します。
macではaltキーに該当するのがoption（⌥）キーなのですが、他のショートカットキーとかぶるためかmacの各種ターミナルではデフォルト無効にされている場合があります。そのため各種ターミナルで有効化する方法をまとめました。

便利なメタキー(altキー)ショートカットは数多ありますが自分は下記をよく使用しています。

```
alt + f  # forward 単語単位で進む
alt + b  # backward 単語単位で戻る
```

# Terminal (Macの標準で入っているもの)

環境設定 -> プロファイル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189239/5f825d3d-37ba-ce2b-c90c-3d6137dbdba4.png)

`メタキーとしてOptionキーを使用`のチェックボックスを有効化します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189239/9d3537cd-c427-7b10-cd1c-e63970cbea70.png)



# iTerm2

Preferences -> Profiles -> Keysと進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189239/089ab124-bf9d-fc46-3451-82d6938db78d.png)

ここで`Left Option Key`を**Esc+** に設定します。
右側にOptionキーが存在するキーボードを使用していてこちらでもメタキーを使いたい場合は`Right Option Key`も同様の設定を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189239/4c0ef752-43ef-9942-3f6d-82e96aa9a9e9.png)

# IntelliJ IDEA

Preferences -> Tools -> Terminalと進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189239/2daac3b8-68b7-4949-6a65-31233cecab4d.png)

`Use Option as Meta key`のチェックボックスを有効化します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189239/f7348820-2a6d-960f-723c-c00d50a19f28.png)

# Visual Studio Code

Preferences -> Settingsにアクセスします。

検索ボックスに`terminal.integrated.macOptionIsMeta`を入力します。
それかFeatures -> Terminalに進みます。

`Integrated: Mac Option Is Meta`のチェックボックスを有効化します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189239/f559f0a8-9834-b6f9-b0b5-66d0a1a3f238.png)
Markdownを強力に変換するNodeJSライブラリーremarkを使ってみた2


これは　yuriacats アドベントカレンダー4日目の記事です

---

## 実装編２

（参考リポジトリ:https://github.com/yuriacats/remark-howto/pull/new/1204Remark　）
[前回](https://qiita.com/yuriacats/items/746f1d54a3d438606fdd)まででHTML要素をテキストとして返せる部分まで作れているので、次はそれをReactのDOMとして返すような形にしたい。
前回はText型を返していたが、今回はReact.Element型を返したいので、`rehype-react`というライブラリーを`rehypeStringify`の代わりに使えば良いということがわかる。
よって、`rehype-stringify`を利用していた部分に`rehype-react`を導入し、OptionとしてReactのcreateElement関数を渡してやれば良い。

```jsx
import React, { useEffect, useState, Fragment, createElement } from "react";
import { unified } from "unified";
import remarkParse from "remark-parse/lib";
import remarkRehype from "remark-rehype";
import rehypeReact from "rehype-react/lib";


function App() {
    const [testText, setTestText] = useState("")
    const [resultText, setResultText] = useState(Fragment)
    useEffect(() => {
        unified()
            .use(remarkParse)
            .use(remarkRehype)
            .use(rehypeReact, { createElement })
            .process(testText)
            .then((res) => {
                console.log(res)
                setResultText(res.result)
            })

    }, [testText])
    return (
        <div>
            <p>Markdownを入力すると下にHTML変換したものを表示するよ！</p>
            <textarea
                rows={10}
                onChange={(event) => setTestText(event.target.value)}
            />
            <p>
                {resultText}
            </p>
        </div>
    );
}

export default App;
```
すると以下のようにMarkdownを打った側からHTMLに変換してプレビュー画面を作ることができる。

![スクリーンショット 2022-12-04 22.25.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163357/9ceffb3b-3d13-6e8e-932f-02c719fb0485.png)

---

参考文献：
https://qiita.com/masato_makino/items/ef35e6687a71ded7b35a
https://zenn.dev/januswel/articles/e4f979b875298e372070

https://github.com/unifiedjs/unified/
gem install mecab を実行する時に「fatal error: 'mecab.h' file not found」エラーの対処

# 概要
M1 MaxのMacBookを買ってから環境構築をした時、`bundle install`を実行したら`mecab_wrap.cpp:1855:10: fatal error: 'mecab.h' file not found`エラーが出ました。今まではずっとIntelチップのMacを使っていたが、このエラーはありませんでした。

- Mac OS X Ventura
- ruby 3.1.3p185 (rbenv)
- mecab of 0.996 (homebrewによるインストール済み)

# 解決策
```
gem i mecab -- --with-cppflags=-I/opt/homebrew/Cellar/mecab/0.996/include
```
なぜ自分はテストコードを書くのか

## はじめに
自分がエンジニアになった頃から担当しているプロジェクトではテストコードが当たり前に書かれていました
あまりなぜ書いているか意識せずなんとなく書いていたので、なんのために書いているのか自分なりに考えてみました

## 1. 不具合を未然に防ぐため
開発時にテストが回るため不具合を未然に防げる可能性が高まります
コードの変更によって意図していない箇所に影響があった場合もテストによって防ぐことができます

## 2. リファクタリングやバージョンアップの難易度が下がる
テストによってコードの振る舞いが保証されているので、リファクタリングやバージョンアップによって壊れることを防げます
テストコードがないプロジェクトでのリファクタやバージョンアップはリスクが大きくあまりやりたくないです

## 3. テストコード自体が仕様書として残る
ほとんどの場合にはテストコードにはテストケースと期待する振る舞いを書きます
これによってテストコードを見ることで、実装の仕様を確認することできます
テストのないプロジェクトでは実際に書かれている内容から動作を推測する必要があるので、テストがあるだけで開発自体がやりやすくなると思っています

## 4. 人間によるテストを減らすことができる
機能の実装時に人間によるテストを行いますが、テストコードがないと改修した箇所以外も時間をかけて人間が確認する必要が出てきます
テストコードがあれば、テストコードに任せてしまうことができるので人間によるテストは最小限で済むと思います

## 5. コードの品質自体を上げる
テストを書こうと思うとどうしてもテストし易いコードを書く必要が出てきます
テストし易いようにモジュールを分割するなど設計面でもテストを意識することでコード自体の品質が上がるのかなと思っています

## いつテストを書くのか
- 人間がテストするよりもテストコードに任してしまったほうが早いところ
- 複雑なロジックになってしまったことろ
- セキュリティ上重要なところ
- 不具合を呼ぶ予感がするところ

## テストを書かない場所
- バリデーションなどのフレームワークの設定で済む場合
- 自動生成されており手を加えていない場合
- すでに別のテストで信頼できる場所
- テストカバレッジを上げるためだけに書く場所

## まとめ
当たり前のことが多くなってしまいましたが、自分はこのような理由があってテストを書いています
こういったメリットも理解して今後もテストを書いていきたいと思います
TypeScriptでGASの開発を行うための環境構築

[Ateam Group U-30 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ateam-group-u30)の5日目は、 @zumi0 が担当します！

https://qiita.com/advent-calendar/2022/ateam-group-u30

## はじめに
claspという、Google Apps Script（GAS）をローカルで開発することを可能にするCLIツールがあります。そのツールを使うと、ローカルで開発をできるようになるだけでなく、TypeScriptを使って開発できるようになります。

今回は、TypeScriptでGASの開発をするために行なった環境構築の内容を備忘録としてまとめていきたいと思います。

## TypeScriptでGASの開発を行うための環境構築
### TypeScript周りの諸々を準備する
まずはGASの開発を行うディレクトリを作成し、 TypeScriptや型などをインストールしていきます。TypeScriptはclaspが対応しているものをインストールし[^1]、コードを整えるためにTSLintとPrettierもインストールします。

[^1]:https://github.com/google/clasp/blob/master/docs/typescript.md#typescript-support

```zsh
$ mkdir -p clasp_project_sample/src && cd clasp_project_sample
$ npm init -y
$ npm i -S typescript@3.8.2 @types/google-apps-script @types/node
$ npm i -D tslint prettier tslint-config-prettier tslint-plugin-prettier
```

インストールが完了したら、以下のコマンドを実行して`tsconfig.json`と`tslint.json`を作成します。
```zsh
$ npx tslint --init
$ npx tsc --init
```

`tsconfig.json`　を作成したら、ドキュメントに従ってファイルを編集します[^2][^3]。

[^2]:https://github.com/google/clasp/blob/master/docs/typescript.md#prerequisites
[^3]:https://github.com/google/clasp/blob/master/docs/typescript.md#typescript-configuration

```json:tsconfig.json
{
  "compilerOptions": {
      "isolatedModules": true,
      "noLib": true,
      "noResolve": true,
      "target": "ES2019",
      "lib": ["esnext"],
      "module": "None",
      "noImplicitUseStrict": true,
      "experimentalDecorators": true,
      "types": ["google-apps-script", "node"]
  }
}
```

### claspを導入する
まずはclaspをインストールしていきます。

:::note warn
TypeScriptでGASを開発する場合`clasp`のバージョンは1.5.0のものを利用してください
:::

```zsh
$ npm i -g @google/clasp
```

claspのインストールが完了したら、claspを使ってGASのプロジェクトを作成します。以下のコマンドで作成します。

```zsh
$ clasp login
$ clasp create --type standalone --title "clasp project sample" --rootDir ./src
```

詳しい説明は省きますが、気になる方や不明なところがあった方はこちらの記事を参照してください。

https://qiita.com/zumi0/items/85ca400d57f60728a7c7

GASのプロジェクトを作成すると、`./src`に`.clasp.json`が作成されます。このファイルは`tsconfig.json`と同じディレクトリにある必要があるので移動させます[^2]。また、`"fileExtension": "ts"`を追加することで、ローカルプロジェクトの拡張子を指定することができます。

```diff_json:.clasp.json
{
    "scriptId": "YOUR_SCRIPT_ID",
    "rootDir": "./src",
+   "fileExtension": "ts"
}
```


```
clasp_project_sample/
├── .clasp.json
├── node_modules/
├── package-lock.json
├── package.json
├── src
│   ├── appsscript.json
│   └── main.ts
├── tslint.json
└── tsconfig.json
```

最後になりますが、必要に応じてGitで管理できるようにすれば完了です！

## さいごに
今回は、TypeScriptでGASの開発を行うための環境構築の方法をまとめました。ご活用いただけたら嬉しいです。

[Ateam Group U-30 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ateam-group-u30)はまだまだ続きます！ぜひ購読登録して、明日以降の記事もチェックしてみてください！
空間図形「21年 東京電機大 工・未来・理工・システム 1(3)」をsympyとFreeCADでやってみた。

containsでした。sympyのsegmentのprojection?

オリジナル

https://kamelink.com/blog/2022/12/04/6-4-21-tokyodenkidai-kou-mirai-rikou-shisutemu-1-3/


上と同じです。大学入試数学問題集成＞
未登録


# sympyで(オリジナルのやり方)
勉強中

# sympyで(projection)
containsでした。
```python
from sympy import *
A=Point3D(1,3, 2)
B=Point3D(4,0,-1)
C=Point3D(4,3, 2)
s=Segment(A,B)
P=s.projection(C)
print("#"     ,P,s.contains(P))
print("# test",s.contains(Point(0,0,0)))
# Point3D(2, 2, 1) True
# test False
```

on line sympyで、上記のソースコードを貼り付けて実行できました。私の環境は,pycharmです。　

https://live.sympy.org/

# FreeCADのマクロで
マクロからsympyを使っています。
test行を削除しています。
CADで,線分AB上の点Pが確認できました。

an Isometric view:どの方向からみればわかりやすいのか、わかりませんでした。

![png1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/7ad1a912-99e4-055f-f88b-6de7ed70c4bf.png)

![png2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/718cb4a2-7ee4-35d1-b18b-e8e573766443.png)

```python
import FreeCAD
import Part
import Draft
import Mesh
#########################################################################################################
from sympy import *
A=Point3D(1,3, 2)
B=Point3D(4,0,-1)
C=Point3D(4,3, 2)
s=Segment(A,B)
P=s.projection(C)
print("#"     ,P,s.contains(P))
#########################################################################################################
# 3D作図
def myXYZ2Txt(A):
    return '(' + str(A.x) + ',' + str(A.y) + ',' + str(A.z) + ')'
def myTxtXYZ(A,myWedgei):
    P5x=float(A.x)
    P5y=float(A.y)
    P5z=float(A.z)
    p5 = FreeCAD.Vector(P5x, P5y, P5z)
    myText = Draft.makeText(myWedgei, p5)
    myText.Label = myWedgei
    FreeCADGui.ActiveDocument.ActiveObject.FontSize = '0.2 mm'
def myTxtXYZ_S(*xy_tx):
    for i in range(1,int(len(xy_tx)/2)+1):
        myTxtXYZ(xy_tx[2*i-2],xy_tx[2*i-1]+myXYZ2Txt(xy_tx[2*i-2]) )
def myLine(A,B):
    Ax,Ay,Az=float(A.x),float(A.y),float(A.z)
    Bx,By,Bz=float(B.x),float(B.y),float(B.z)
    pl = FreeCAD.Placement()
    pl.Rotation.Q = (0.4247081540122249, 0.17592004639554645, 0.33985110062924484, 0.8204732460821097)
    pl.Base = FreeCAD.Vector(-3.9166066876399563, -2.1670824762243774, 1.7495260956243028)
    points = [FreeCAD.Vector(Ax,Ay,Az), FreeCAD.Vector(Bx,By,Bz)]
    line = Draft.make_wire(points, placement=pl, closed=False, face=True, support=None)
    Draft.autogroup(line)
myTxtXYZ_S(A,"A",B,"B",C,"C",P,"P")
myLine(A,B)
myLine(C,P)
doc = App.activeDocument()
App.ActiveDocument.addObject("App::Origin", "Origin")
App.ActiveDocument.getObject('Origin').Visibility = True
App.ActiveDocument.recompute()
Gui.activeDocument().activeView().viewAxonometric()
Gui.SendMsgToActiveView("ViewFit")
![png1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/ce62b674-02bc-1041-618e-a7a0f5f06aa5.png)
![png1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/12616266-97bf-4806-99ff-7c70263829bd.png)
```

# 参考
Is the other GeometryEntity contained within this Segment?＜

https://docs.sympy.org/latest/modules/geometry/lines.html#sympy.geometry.line.Segment.contains
【Kintone】VSCodeでEslintを設定

参考
https://developer.cybozu.io/hc/ja/articles/360000098886

インストールの手順３は2022年12月時点でTypeScriptとPrettierをインストールしてもエラーは発生しない。

.eslintrc.jsに書き込む内容は
「様々なルールセットを利用する」の「ES2017でのkintoneカスタマイズ」を反映させる。
~~~
module.exports = {
  extends: ["@cybozu", "@cybozu/eslint-config/globals/kintone"]
};
~~~

VSCodeの拡張機能をインストール後、再度.eslintrc.jsを編集。
~~~
module.exports = {
	"extends": ["@cybozu", "@cybozu/eslint-config/globals/kintone"]

	"rules": {
		"indent": [2, 4],
		"linebreak-style": ["error", "windows"],
	}
};
~~~
"indent" はインデントをスペース2個か4個のいずれかにする。
"linebreak-style"は改行コードをWindows(CRLF)にする。
という設定。
postman mock serverの利用方法

postman mock serverを利用方法（個人ノート）

Abstract：
Flutter開発はフロントエンドなので、APIテストが必要になる。
そのため、Postmanのmock server機能を活用して、簡単にget/post requestが実現できる。以下の内容はmock serverに基づくrequestの方法を説明する。

手順の詳細：
インストールや新規作成などの手順はホームページに掲載されているため、こちらで省略する。

１．mock serverの立ち上がり：
    ①server nameとEnvironmentは必須項目です。「新規のEnvironment」をチェックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/9c9b205b-6af6-111b-3d62-0dea321260bc.png)
②Request bodyにチェック入りの場合は、Bodyの情報と一致すれば、serverは情報を返却する。チェック外しの場合は、どんなBodyに対しても情報を返却する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/dece8577-8892-293f-b7fa-8bf49fb80a78.png)
    ②serverのurlをコピーして、Environmens設定の「INITIAL VALUE」に貼り付ける。VARIABLEは「baseUrl」でも、そのまま「url」でも大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/38a7cb7a-cf86-f02f-6ba1-6c27200c7e95.png)


２．get requestについて：
       ①getはサーバ情報を取得することです。getのテストはブラウザにも検証できる。

３．post requestについて：
①postは様々な情報を送信できるため、リクエストの返却情報はpostmanに確認できるが、ブラウザに検証できない。

４．リクエストの作成
    ①get/postのパスは「serverのパス」＋「リクエスト名」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/b25afb77-82c9-4c38-28d3-27007de34b1a.png)
②必ず右上の三つの点をクリックして、「Add example」を実行する。中身のparams情報と下の返却Bodyを編集する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/69a63f2b-c591-f087-da80-798d30cccbcb.png)

   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/15e78524-6caa-974d-e7e1-1068739ed2ab.png)
（※そうしなければ、mock serverは返却情報を知らないので、リクエストが失敗になる）

③普通のjson結果を返却させたい場合は、「Add example」にjson形式の返却内容を追加していいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/eb1b50c1-cf85-2f03-db86-f0a26989ba42.png)

④x-www-form-urlencodedの結果を返却したい場合は、
    まずはBodyに「"Key":"value"」を入力する。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/1a6bfd10-2966-31d4-caeb-be4836380c92.png)
    その時、Headersに「Content-Type」のVALUEは自動的に「application/x-www-form-urlencoded」になった（なってない場合は手で入力しても大丈夫です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/53628489-d0b8-2da2-f33f-04070b586ea8.png)
    次に、「Add example」をしましょう。
    Bodyに「"Key":"value"」を入力する。
    ▲必ず下の返却Bodyにurl形式の結果を記入する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/d6d86217-9c46-4f64-e168-f3e1bff93074.png)
③post requestを送信する
Bodyの送信情報を設定する（mock serverがrequest bodyの場合は、必ずexampleの「"Key":"value"」を一致させる）。下記の結果が返却された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3016669/4e780402-07a0-96b0-1274-9f65c5acd07e.png)
今でも彼がメガやビットの海を泳いでいるのかを自分の目で確かめてみたくなって、その海に飛び込むことにした。

# はじめに

毎年開催されている　ジーズアカデミー　Advent Calenderに新参者ながら、
北の国から手をあげて、12月6日で参加させて頂きます！

皆さま、お初にお目にかかります、田川　宗慶と申します。
お見知りおきを（なんて偉そうにすみません。）
名前だけでも覚えてくださいませ。

わたくしはG's ACADEMY UNIT_SAPPORO　DEV５期に2022年10月に入学しました。

ちなみにG’sではイソノカツオと呼ばれております。
（自分で名付けたんですけどね・・・。）
（某国民的アニメにして、シンドロームにまでなってしまうくらい
有名な彼女の弟の名前を拝借しております。）

では、サクサクっとわたくしが
なぜ、ジーズアカデミーに入学することにしたのか？
入学をして何をしたいのか？について
これから書いていこうと思います。


## パソコンがなくてもセカイは変えられる

単語の頭につけることによって、その単語を強調する表現である『ド』。
（おそらく弩級のドなんだと思うんですが）
その『ド』を使って表現するとしたら、田川は『ド』が10個・・・
いやいや100個はついていてもおかしくないようなめちゃくちゃアナログ人間でした。

それに今の時代はスマホがあればだいたいのことは出来ますし、
超アナログ人間であってもスマホの基本機能くらいは使えるので
それでいいなぁ～と考えていました。

パソコンがなくてもなんとかなると思っていましたし、
今回のようにジーズアカデミーに出会っていなければ
パソコンを買うことなかったでしょうし、
持とうということもなかったと思います。

それこそパソコンがなくてもセカイは変えられる！
とすら思っていたくらいです。

## じゃあ、なんでジーズに入学したのか

そんなことを思っていた超アナログ人間である田川が
なんで、ジーズアカデミーに入学したのか。

それは人生の転機が訪れたからです。
その転機についてはまた別な機会にお話ししたいと思います
（やや重たい話になるため）が、その転機を迎えたタイミングで、
『一緒にジーズアカデミーに入りませんか？』と誘われたんです。

人生には岐路というか、節目という出来事が起きることがあって、
田川はおおよそ20年周期で訪れています。
0歳から二十歳までがファーストステージ、
二十歳から四十路までがセカンドステージと考えたときに
40歳から還暦60歳という大きな節目のサードステージとしたんです。


今まで逃げ続けてきたデジタルの世界、苦手で避け続けてきたパソコン・・・。

ただ、何かを変えるためには今までと同じことをやっていても前には進めないですし、軽くとはいえ幾度となく誘ってくれていたので、ジーズアカデミーに入学することにしたんです。

## プログラミングを始めてわかったこと

入学するにあたりパソコンを買い、タイピングの練習をしたり、
家にWi-Fiを飛ばしたり、プログラミングを始めるって大変だなぁ～と
思っていたんですが、いざ入学してプログラミングに触れてわかったことは、
プログラミングってめちゃくちゃ大変だーーーーーーーー！ということです。

自分が思っている数倍、数万倍・・数京倍くらい大変でした。
初めて触れたプログラミングの課題は、
ジーズアカデミー入学がもれなく苦しむ課題にして、最恐の課題が
チーズアカデミーだといわれているそうで、
これを乗り越えられることがジーズアカデミーの仲間入りのパスポートとなるくらいの素人泣かせの課題でした。


初めて授業から課題提出までの二週間は、本当にしんどかったです。
（課題提出までの道のりは今も四苦八苦ですが）

そして、わかったことがありました。プログラミングってすげーーーーー！！！ってことと、プログラミングってめちゃくちゃ楽し～～～～～！！！！！ということです。

コードを書いている最中は理解できていないので、
どうなるかわからないでやっていたんです。
（今もそんなにはわかっていませんが（笑））


自分の書いたコードがちゃんと動いた、反映された時には、
今まで感じたことのないタイプの嬉しさに出会えました。

それをまた味わいたい、もっと色々なことをやっていきたいと感じることができたことでこれからもプログラミングに携わっていきたいという気持ちになれました。

そして、ジーズアカデミーに入学したからこそ、
自分がやってみたいこと、作ってみたいものを考えることが
出来ています。

『prologue note』で大切な人との初めての約束みたいなものを、
『epilogue note』で大切な人との終わりの約束みたいなものを
思い出フォルダーやライフログ、タイムカプセルなどを組み合わせて、
二人にしか迎えられない素敵な思い出を記録していきながら、
最終的には『最期の言葉』が形として残していけるようなものを
作りたいと思っています。何かとご相談させていただくと思いますので、
よろしくお願いいたします。


## さいごに

今回の記事のタイトルは、あるアーティストの曲の歌詞のフレーズで、
なんだか頭に残る印象的なフレーズであるとともに、
まだメガやビットを知らなかった田川にとってデジタルの世界というのは
こんなイメージだったことからタイトルにしました。

今もメガやビットの海を泳いでいるのかを自分の目で確かめてみたくなって、
その海に飛び込むことにしました。

その歌詞に出ている生き物がまだそこにいるのか、田川自身がこのデジタルの海で生活をしていればそれに出会えるのか、などの絵空事は置いておいて（笑）

ジーズアカデミーに入学して、約二か月。
未だにプログラミングが出来るとか、
パソコンが使えますなんて声を大にしていうことは出来ませんが、
プログラミングに触れられたからこそ考えられたこと、
そして同じ想いを持つ仲間に出会えたことがこの二か月で
自分の人生において起きた素敵な時間だったと振り返りながら
この記事を書いていて思ったことです。

ジーズアカデミーでは学校ではない。と聞いていましたが、
その通りだと思います。ジーズアカデミーはモンスターファクトリーです。

児玉ファウンダーをはじめとして、山崎学校長やそのほかで
授業に携わってくれている先生たちやスタッフと接している間に
その情熱にほだされていって、自分も何かできる！やってやんぞ！って
スイッチが入ってしまうんですよね。

その結果は皆さまのご存じのとおり、
幾多のモンスターたちが世に放たれています。

今もモンスターになるべくその卵たちが今日もキーボードを叩き、
嘆き苦しみながらも、やめられない止まらないかっぱえびせん状態の喜びのために日々頑張っていますので、今後もジーズアカデミーからは目が離せませんよ！

と段々とまとまりがなくなって煽り始めてきて、酔っ払いみたいになって
参りましたので以上です。

支離滅裂の乱文でお目汚しになってしまったうえ
、コードなどのプログラミング要素ゼロになってしまってすみませんm(__)m
それでも最後の最後まで読んでくださった皆様ご精読ありがとうございます！


ちなみにこの記事を書いているのは、PHPの授業の一回目を受けたあとで、
サーバーサイドのプログラミングはこれまでとひと味も、
ふた味も違うプログラミングで、これまでとは違う苦しみ方に
悩んでいる間に書いています💦

ということで、課題に戻ります。

田川宗慶でした。
読み・発音を持つ辞書のデータを得る

個人的に日本語の「読み」「発音」が載っており、[ポリゴンショック](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%82%B1%E3%83%A2%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%82%AF)が起こる前の語彙であると好ましいという条件の単語集を欲しているので作りました。
日本語のNLPでは定番のMeCab[^mecab]、その[IPA辞書](https://taku910.github.io/mecab/#download)から作ろうと思います。[（github）](https://github.com/taku910/mecab/tree/master/mecab-ipadic)

# 中身を見る
まずはダウンロードしてきたcsvファイルの中身を見ます。

## 文字コードを直す
Numbers(Macの表計算ソフト)でcsvを開くと文字化けしていました。文字コードがEUC-JPだったようなのでUTF-8にします。また、品詞別にCSVが分かれていますが今回はあまり意識しないので統合します。

```bash:(bash)文字コードをUTF-8にして1ファイルに統合
# convert.sh
NEW_FILE="utf8-dic.csv"
touch $NEW_FILE
for file in $( ls $1 | grep csv$ ); do
  iconv -f EUC-JP -t UTF-8 "${1}/${file}" >> $NEW_FILE
done

# 実行したコマンド(辞書データの一個上の階層で実行)
# bash convert.sh mecab-ipadic-2.7.0-20070801
```

`utf8-dic.csv`はこんな感じの内容になりました（行頭は分かりやすさのために追記したもの）。

|1|2|3|4|5|6|7|8|9|10|11|12|13|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|もの凄まじゅう|49|49|6956|形容詞|自立|*|*|形容詞・イ段|連用ゴザイ接続|もの凄まじい|モノスサマジュウ|モノスサマジュー|
|もの凄まじゅぅ|49|49|6956|形容詞|自立|*|*|形容詞・イ段|連用ゴザイ接続|もの凄まじい|モノスサマジュゥ|モノスサマジュー|
|もの凄まじき|44|44|6956|形容詞|自立|*|*|形容詞・イ段|体言接続|もの凄まじい|モノスサマジキ|モノスサマジキ|

12,13列目が読みと発音ですね。

## 読みと発音を抜き取る

```bash:ワンライナーで12,13行目を抜き取る
awk -F ',' -v 'OFS=,' '{print $12,$13}' "utf8-dic.csv" > "phonetic-dic.csv"

# wc phonetic-dic.csv 曰く、392126単語/約12MB
```

`phonetic-dic.csv`はこんな感じの内容になりました（行頭は分かりやすさのために追記したもの）。
| 読み | 発音 |
|:-:|:-:|
| モノスサマジュウ | モノスサマジュー |
| モノスサマジュゥ | モノスサマジュー |
| モノスサマジキ  | モノスサマジキ |

# 使ってみる

```bash:ピカチュウが喋れる言葉
grep -E '^[ピカチュウー]+,.+$|^.+,[ピカチュウー]+$' "phonetic-dic.csv" | sort | uniq > "pika-say.csv"

# 234単語の発話ができる
#   grep -E '^[ピカチュウー]+,.+$|^.+,[ピカチュウー]+$' "phonetic-dic.csv" | wc
# 同音異義語をまとめると、44単語分の発話ができる
#   wc "pika-say.csv"

# 正規表現のテストデータ "pikachu-test.csv"
  #ピカチュウ,ピカチュー
  #ポリゴンショックハンニン,ピカチュウ
  #ピカチュウ,ポリゴン
  #アピカピカ,アピカピカ
  #ウカ,ウカ
  #ア,ア

# テストコマンド: 
#   grep -E '^[ピカチュウー]+,.+$|^.+,[ピカチュウー]+$' pikachu-test.csv
# 結果:
  #ピカチュウ,ピカチュー
  #ポリゴンショックハンニン,ピカチュウ
  #ピカチュウ,ポリゴン
  #ウカ,ウカ
```

<details><summary>マル秘単語44連発</summary>

|読み|発音|
|---|---|
|ウ|ウ|
|カ|カ|
|チ|チ|
|ウゥ|ウー|
|ウウ|ウー|
|ウカ|ウカ|
|ウチ|ウチ|
|ウー|ウー|
|カァ|カー|
|カウ|カウ|
|カカ|カカ|
|カチ|カチ|
|カー|カー|
|チウ|チウ|
|チカ|チカ|
|チチ|チチ|
|チー|チー|
|ピカ|ピカ|
|ピー|ピー|
|カカア|カカー|
|カカウ|カカー|
|チカゥ|チカー|
|チカウ|チカウ|
|チカウ|チカー|
|チチカ|チチカ|
|チュウ|チュー|
|ピーチ|ピーチ|
|ウカウカ|ウカウカ|
|ウチウチ|ウチウチ|
|ウチカチ|ウチカチ|
|ウチュウ|ウチュー|
|カチカチ|カチカチ|
|カチュウ|カチュー|
|カチュー|カチュー|
|チカウチ|チカウチ|
|チカチカ|チカチカ|
|チチュウ|チチュー|
|チュウウ|チューウ|
|チュウカ|チューカ|
|チュウチ|チューチ|
|ピイピイ|ピーピー|
|ピカピカ|ピカピカ|
|ピチピチ|ピチピチ|
|ピーピー|ピーピー|

PP切れを指摘することができる、渦中にあることを訴えることができる、といったことがデータから読み取れます。
</details>

[^mecab]:[MeCab](https://taku910.github.io/mecab/)はフリーソフトウェアの形態素解析エンジンです。GPL, LGPL, または BSD ライセンスに従って本ソフトウェアを使用,再配布することができます。「京都大学情報学研究科−日本電信電話株式会社コミュニケーション科学基礎研究所 共同研究ユニットプロジェクト」を通じて開発されています。
Deno Deploy + Fresh で production 環境か preview 環境かを判定する

# 結論

できない。

# やり方

完璧にはできないけど、URL でおおむね正確に判定することはできる。Deno Deploy が production 用には短い URL を発行し、Preview 用には長い URL を発行してくれることを利用する。

# 判定するコード
_middleware で、着信したリクエストの URL がどの環境に当たるかを表現で検査して、`ctx.state.target` にセットする。
判定方法は、何でもいいけど、ここでは泥臭い正規を使う。

```routes/_middleware.ts
import { MiddlewareHandlerContext } from "$fresh/server.ts";

type Target = "local" | "preview" | "production" | undefined;

const {
  TARGET_PRODUCTION_REGEX = "^my-great-project[.]deno[.]dev$",
  TARGET_PREVIEW_REGEX = "^my-great-project-(.+)[.]deno[.]dev$",
  TARGET_LOCAL_REGEX = "^localhost$",
} = Deno.env.toObject();

function targetEnv(req): Target {
  const { hostname } = new URL(req.url);
  if (hostname.match(TARGET_PRODUCTION_REGEX)) {
    return "production";
  } else if (hostname.match(TARGET_PREVIEW_REGEX)) {
    return "preview";
  } else if (hostname.match(TARGET_LOCAL_REGEX)) {
    return "local";
  } else {
    console.log(`No target matched for ${hostname}`);
    return undefined;
  }
}

interface State {
  target: Target;
}

export async function handler(
  req: Request,
  ctx: MiddlewareHandlerContext<State>,
) {
  ctx.state.target = targetEnv(req);
  const resp = await ctx.next();
  return resp;
}
```

`Deno.env` に何も指定がなければ、デフォルトの正規表現を使う。環境変数を設定していたら、デフォルトは使わずに、そこから読み込む。

# 判定結果を使ってみる

`index.tsx` で、`ctx.state.target` を読み込む。handler 内での条件分岐に使うだけなら、そのまま if や switch で分岐して、最後に `ctx.render()` を忘れずに返す。

```routes/index.tsx
import { Handlers } from "$fresh/server.ts";

export const handler: Handlers = {
  GET(_req, ctx) {
    const { target } = ctx.state;
    switch (target) {
        case "production":
            ...
    }
    return ctx.render();
  },
};
```

ページに渡す必要があるならば、`Data` を定義して、`ctx.render()` でページに渡す。

```routes/index.tsx
import { Handlers } from "$fresh/server.ts";

interface Data {
  target: string;
}

export const handler: Handlers = {
  GET(_req, ctx) {
    const { target } = ctx.state;
    const data: Data = { target };
    return ctx.render(data);
  },
};

export default function Page({ data }: PageProps<Data>) {
  const { target } = data;
  return (
    <>
      <p>Welcome to `fresh`.</p>
      <div>env target: {target}</div>
    </>
  );
}
```

# 期待される出力

ローカル:

```
<p>Welcome to `fresh`.</p>
<div>env target: local</div>
```

プレビュー用の長い URL:

```
<p>Welcome to `fresh`.</p>
<div>env target: preview</div>
```

本番用の短い URL:

```
<p>Welcome to `fresh`.</p>
<div>env target: production</div>
```

せいこう

# ダメなところ

Deno Deploy では、本番環境用に短い URL に加えて、長い URL も発行される。
わざわざそれにアクセスすると、


```
<p>Welcome to `fresh`.</p>
<div>env target: preview</div>
```

こうなる。

リクエストごとにどちらの環境になるのか予測不能なので、起動時にどちらなのか固定化することはできない。判定は、リクエストごとに必要になる。

キャッシュ的な動きをする変数があるなら、誤動作しないように注意する必要がある。本番環境なのにプレビュー用のAPI呼び出しを取りに行ったり、プレビューなのに本番用DBから取ったデータを返したり、というのがないように。

わざわざ長い URL にアクセスすることは稀と考えて、だいたい OK。

# 宣伝
宣伝: Fresh のドキュメントを https://fresh-ja.deno.dev/ で勝手に日本語化しています。協力者を募集中。
社内 LAN の IP アドレス空間で困った話 (1)

謎のアドベントカレンダー、第 7 話です。

本日から別の話になります。

## 180 人の会社にクラス C のネットワークが 1 つ

[初回の記事](https://qiita.com/hmatsu47/items/f9aaa4ab25b080bf2b26)で触れたとおり筆者の勤務先に社内 LAN が導入されたのは 1990 年代の中盤でした。

まだ Windows 95 も発売前で、[RFC1918](https://www.nic.ad.jp/ja/translation/rfc/1918.html) の前身の [RFC1597](https://www.nic.ad.jp/ja/translation/rfc/1597.html) が出たかどうかぐらいの時期だったようです。

（入社前の話なので詳しくは知りません）

入社時点ではクラスフルアドレッシング前提の機器は存在しなかったので事情がよく分からないのですが（RIPv1 を喋っているルーターは居ませんでしたし）、

- 社内 LAN 導入時の社員規模はおそらく 150 人前後
- 「（正社員）1 人 1 台のパソコンを配布・貸与」をすでに決めて実行していた

にもかかわらず、**なぜか社内 LAN の IP アドレス空間は /24 が 1 つだけ** 設定されていました。

そして、筆者が入社した時点で 180 人規模になっていました。

…人間以外の機器、例えばネットワーク機器やサーバー、プリンタ（当初はネットワークに接続されていませんでしたが）などの台数を考えると、すぐに足りなくなるのは分かりきっていました。

実際、筆者が入社した時点で足りていませんでした。

## どう対処していたのか？（ワークアラウンド）

ずばり、**手作業で DHCP プールを確認して、もう使われていなさそうなリースをひたすら削除していました。**

というか、新人である筆者がその作業をやらされていました。

当時の情シスの上司は「プログラムで自動的に切れるようになるまで頑張れ」と言っていましたが、その日は結局やって来ませんでした。

---

筆者が新人ではなくもう少し仕事に慣れた状態だったら、DHCP サーバーを Windows に任せず Linux で立てることでリースの自動解放を実装したかもしれません。

おそらく、それをしていたら別の問題が生じ、後々困っていたことでしょう。

（フラグ？）

## 一方、グローバルアドレスは

同じようにクラス C が 1 つ丸ごと与えられていました。

ただし、実際に使っていたのはそのうちのごくわずかでした。

（この話は後日別記事で触れます）

今から考えるととんでもない話ですが、おそらく筆者の勤務先（の関連会社）がグローバルアドレスを取得したタイミングでは、まだクラスフルな割り当てをしていたのでしょうね。

その後、新事業で協業することになった某大手製造業の工場・オフィスでは、協業当時、末端のパソコン 1 台 1 台に対してグローバル IP アドレスが付与されていたのを覚えています。

太っ腹。

---

8 日目の記事に続きます。

- **[社内 LAN の IP アドレス空間で困った話 (2)](https://qiita.com/hmatsu47/items/a9dedc3781bfc13c5f74)**

https://qiita.com/hmatsu47/items/a9dedc3781bfc13c5f74
アジャイル[Agile]コンフリクトマネジメント



アジャイル（agile）の名詞形アジリティ（agility）は、敏捷、機敏という意味。
IT業界では、激しく変化する外部環境に対して、常にあるべき姿に向けて改善、進化しつづるための手段である。

反復 (イテレーション) を繰り返す開発手法である。

設計、開発、製造、テストという流れを着実にこなしていくというものではなく、
まず、作ってみる。それを見てもらう。作り直してもらう。を繰り返して精度を高めていく柔軟な手法である。

この繰り返すプロセスの中で、何度も「意思決定」を行っていくことになる。。が。。
そもそも、「意思決定」の認識が、チームの中で、ズレる事がある。。

__◆◆◆「意思決定」のプロセス◆◆◆__
①意思決定の対象となる問題を識別し情報収集する。
②問題解決の代替案を列挙し、設計する。
③ある程度の基準によって代替案の中から最適なものを選択する。
④選択した代替案の実行結果を分析、評価、検討する。

__☛チームで仕事をしていて、そんなに綺麗に意思決定出来きるのか？__


__チームで仕事をすると、各自、温度感が違うので、認識がズレたり、コンフリクト(葛藤)が発生します。__

人間、集団内、集団間、組織間などあらゆるレベルで発生するのは、当たり前です。
コンフリクトというと否定的な側面のみに目が行きがちですが、組織内のさまざまな見解は、
__☛組織の活性化や新しい価値の創造に貢献することがあるため、積極的に活用するような管理が望まれる。__


__それは、何故か？__

__☛コンフリクトの発生要因__
① 　限られたリソース配分について関係者間での合意がとれない場合
② 　互いが自立性を求めたり、ある個人や集団に何かをさせたり、何かをさせない権力を確保したりしようと意図した場合
③ 　組織内の個人や作業集団間で共通の目標を確立できず、協力関係が成立しない場合
④ 　互いが相互依存的過ぎる場合
⑤ 　タスクが、不確実性な場合

__☛コンフリクトマネジメントの方向性__
コンフリクトの解消には限界があるが、次のようなマネジメントの方向性が示されることとなる。
① 　競争し続ける事！　自らの利得にこだわり、競い合う。
② 　和解してみる！　自らの利得を捨て、相手に譲る。
③ 　回避して、逃げる！　自らや相手の利得が表立つのを止める。
④ 　妥協して、譲る。。　自らも譲るが、相手も譲るように仕向ける。適当なところで折り合いをつける。
__上記の選択肢は、現状維持したいのならば、最適解なのでしょう。。__
<font color="red">上記は、陥りがちなコンフリクトマネジメント例となります。


<font color="rgb(107, 142, 35)">__最適解は、わからない。。とはいえ。。コンフリクトは、活かさないと、
☛炎上か、鎮火にとどまる。。という最適解です。__
まあ、それもありでしょうけれど

    チームのマネジメントなのか?　グループのマネジメントなのか？
☛課題は、どちらなのか？正解は、どちらなのか？

良く考えて、見ましょう！
<font color="#006400">__☛もう一つ、最適解があると、思いませんか？__

<font color="red">__⑤ 　協力する！　自分の利得も相手の利得も大きくなるような方法を一緒に見つけようと働きかける。__





__グループで、Agileに取り組むと。。__
グループでは、分担が決まっています。グループ内で、任された責任の範囲で、情報を共有し、タスクをこなします。
みんな、任された範囲のタスクを一生懸命こなします。
<font color="red">しかし、グループとしての業績は？
☛個々のメンバーの貢献の単純な総和によるものにすぎない。つまり、足し算の結果にとどまる。

__それに対して、__

<font color="#006400">__チームで、Agileに取り組むと！！__
<font color="#006400">__協調を通して相乗効果（シナジー）を生み出す！！__

<font color="#006400">__☛個々のメンバーの貢献の単純な総和によるものよりも、高い業績水準をもたらす！！！
☛掛け算で、何かを生み出す事が出来る！！！__

<font color="#1e90ff">___☛チームとは、協調を通して相乗効果（シナジー）を生み出すものです！!__</font>

<font color="red">__グループでの、Agile タスク管理　にならないように、気を付けましょう！__</font>

<font color="#006400">__Let's Agile!!!!__
scoopでインストールしたアプリを既定のアプリにする際の注意

## 結論

あるファイルを[scoop](https://scoop.sh/)でインストールしたアプリケーションを選び、「常にこのアプリを使って」にチェックを入れて開く場合、`$HOME/scoop/shims/`や`$HOME/scoop/apps/notepadplusplus/8.4.7`（Notepad++ の場合の例）でもなく、**$HOME/scoop/apps/notepadplusplus/current**（Notepad++ の場合の例）にある exe ファイルなどを選択する。

<img width="250" alt="「常にこのアプリを使って」開くの例" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273742/23202e29-9c94-39e6-928d-28563d0f8d3e.png">

## 補足

### 公式ドキュメント

この結論は scoop のリポジトリの wiki の[Open With Icons](https://github.com/ScoopInstaller/Scoop/wiki/Open-With-Icons)というページに記載されているので、ここを読めば詳細が記載されています。  
ただ、私はしばしば忘れてしまうのでここにいちばん重要なポイントをメモしました。（windows についてよく理解できている人にとっては常識かもしれませんが……）

### 間違えるとどうなるか

私が経験した範囲だと、ファイルを希望のアプリで開くこと自体はできましたが、

- ファイルのアイコンが正しく表示されなくなる
- ファイルを開いたときにコマンドプロンプトのようなウィンドウが開く

などの問題が発生しました。

### 修正方法

もし shims を指定してしまった場合、単純にもう一度正しく指定し直しても修正されません。  
前述の wiki によると、

- package をアンインストールする。
- アンインストールした package でファイルを開こうとする。開けないので、それを契機に windows は登録を削除するらしい。
- package をインストールして正しく設定する。

という手順を取る必要があるようです。  
ただ、私個人の経験としてはこれでもなぜかうまくいかず、レジストリを直接修正したこともあります。
React環境をVercelにデプロイしてみた

ふと、自分のポートフォリオを作ろうかなと思い立って
「どうせ作るなら、世の中に公開したくね？」ってことで
Vercelにデプロイしてみたので備忘録がてら記事にしようと思います。

CentOSと迷いましたが初心者により優しいということで
今回はVercelを採用しました。
（個人利用のホビープランなら無料っていうのも大きいですね）

※今回はReact-appを用いていますが、開発環境はこれでなくてもVue.jsでもNext.jsでもなんでも大丈夫です 


### Reactの環境作成
注意 : Node.js と npm は予め使える前提で進めます

方法はいろいろあるんですが、今回は一番簡単なCRAを用います！
まず、以下のバージョンよりも新しいか確認してください
```bash
バージョンの最低基準
npm   v5.6
node  v10.16
```
それぞれ以下のように入力すると確認できます。
```bash
$ npm --version
$ node --version
```
確認出来たら、以下のコマンドを叩いてみてください！
```react
$ npx create-react-app myapp
```
みるみるうちにReact環境が構築されていきます
```Happy hacking!```と表示されたら完了です！

ほら、簡単でしょう？

### Githubの設定
次にGithubとの連携を行います。
まずは、ディレクトリを移動しましょう
```
$ cd myapp
```
つづいて、[Github](https://github.com/)でリポジトリを作りましょう！
```https://github.com/user/myapp.git```としておきます。
そして、このReactの環境をGitHubにアップロードします

以下のコードを一行ずつ順番に入力していってください。
```bash
$ git init
$ git add .
$ git commit -m "First Commit"
$ git remote add origin https://github.com/user/myapp.git
$ git push -u origin main
```
これでGithubにアップロードできました。

### Vercelの設定
[Vercel](https://vercel.com)にGitHubアカウントを用いてログインしましょう！
ダッシュボードの画面に来たら、「New Project」をクリックしてください。

次に、「Import Git Repository」から、 ```https://github.com/user/myapp.git``` を入力します。

そしたら、GitHubとVercelの連携について聞かれるので、承認します。
すると、「FRAMEWORK PRESET」の項目が表示されると思うので、「Create React App」を選択して「Deploy」をクリック。

これで、時間を待てばデプロイ完了です。以上です。
これだけで、React アプリを世界中に公開することができましたぁ。

## おまけ
コードを更新した場合は、以下のコマンドを打ってください！
```react
$ npm run build
```
そして、GitHubのmainブランチにpushするだけで、更新が反映されたものが
勝手にデプロイされます。　便利ですねぇ