OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScriptでアプリを作成しました【5】【4択クイズ①】【随時更新】

##はじめに

####学習するに至った経緯

2020年より、未経験からエンジニアへの転職を目指し、某プログラミングスクールへ通う。入学後、『Ruby』を未経験から学ぶ人が多いのと『Ruby』の求人が思っていた以上に少ないので、卒業後、フロントエンドのエンジニアを目指す事に。
Javascriptの学習した事を言語化し、認識の深化による備忘録として記載。

##【仕様】
- 開始ボタンを押すと、問題が始まる。
- 回答する度に次の問題へ移行する。
- 10回問題が終わると、正答数が表示される。
- 最初に戻るボタンを押すと、最初の画面に戻る。

##【作成にあたり学習した事】
- API
- fetch
- 非同期処理
- async/await

##APIとは
『API』とは「アプリケーション・プログラミング・インターフェース（Application Programming Interface）」の略称。一言で表すと、ソフトウェアやプログラム、Webサービスの間をつなぐインターフェースのことを指す。具体的には、「機能を公開しているソフトウェア」と「その機能を使いたいソフトウェア」をつなげる窓口のようなもの。

##API連携の仕組み
APIを通して機能を連携することは『API連携』といい、「自らのソフトウェアにほかのソフトウェアの機能を埋め込む」ということ。APIの基本的なプロセスは「リクエスト（要求）」と「レスポンス（応答）」で構成され、リクエストをするのがAPI利用者で、レスポンスをするのがAPIの提供者。リクエストとレスポンスに関するルールはAPIの提供者が定め、何のリクエストに対してどんなレスポンスを返すかということを提供者がAPIの設計段階で考え、実装し、利用可能な状態にする。API連携を行えばすでにある同様の機能をそのまま連携できるため、手間なく理想を実現させることができる。

##インターフェースとは
『インターフェイス』とは、何かしらの「境界面」「接点」のことを指し、異なる２つの事物の間をつなぐという意味を持つ。例えばキーボードやマウス、ディスプレイは人間とコンピューターの境界上で使われる「ユーザーインターフェース」の1つとして知られ、USBやHDMIといった、機械と機械をつなぐコネクターは「ハードウェアインターフェース」と呼ばれる。

##WebAPIとは
『WebAPI』とは「ネットワーク越しに利用できる関数でAPIにWebサービスを付与したもの」で「Webアプリケーションの情報を取得することができる仕組み」。

##WebAPIの仕組み
『WebAPI』は、HTTPリクエスト情報を内部のプログラムで受取り、処理をして所定の形式で結果をレスポンスとして返す仕組み。

##WebAPIを利用するメリット
複雑なシステムを構築することなく、簡単に必要な情報が取得でき、自身のWebサービスに導入できること。

##WebAPIを利用するデメリット
自身のWebサービスはAPIの提供元に依存することになるため、提供が終了してしまうと、自身のWebサービスにも影響を受けることになる。

##fetch
データとプログラムを繋いでくれるメソッド。リクエストやレスポンスといった HTTP のパイプラインを構成する要素を操作できるようになある。また fetch() メソッドを利用することで、非同期のネットワーク通信を簡単にわかりやすく記述できる。

##非同期処理

####Promise
『Promise』は非同期処理をより簡単に可読性が上がるように書けるようにしたもの。

####async/await
そのPromiseを更に簡単に書けるように新しく追加されたのが『async(エーシンク)とawait(アウェイト)』で、asyncとawaitを用いることで、複雑な非同期の処理をより簡潔に効率よく記述することが出来る。Promiseを用いたときの処理を、より直感的に、より同期的に書けるという特徴がある。asyncとawaitは2つでセットみたいなものなので、awaitを使用するときは必ずasyncが必要。

##1. クイズで扱うAPIのURLを定義
####① 今回のクイズで扱うAPIのURLを定義する。
※ URLの先にたくさんのクイズのデータ(情報)が入っている

```main.js
const API_URL = 'https://opentdb.com/api.php?amount=10&type=multiple';
```
####② fetch()で、クイズデータとプログラムを繋ぐ。
※ 引数の部分にURLを入れる。

```main.js
fetch(API_URL);
```

####③ thenで繋ぐ
※ thenで繋げば、Promiseオブジェクトの中身が渡ってくる。

```main.js
fetch(API_URL)
  .then((Response) => {
    console.log(Response)
  })
```
####④ 渡ってきたデータをJSON形式にして返す

```main.js
fetch(API_URL)
  .then((res) => {
    return res.json();
  })
  .then((data) => {
    console.log(data.results);
  })
```

####⑤ console.logとブラウザに表示で確認
※ dataの中にはクイズのデータが入っている為、それをconsole.logとブラウザに表示で確認する。



##参考サイト
[【JavaScript: クイズアプリ】fetchAPIと非同期処理を用いてクイズデータを表示する方法]
(https://ina-yona-mochiko.com/programming/javascript/quiz-fetchapi-ansynchronous/)
[APIとは何か？API連携ってどういうこと？図解で仕組みをやさしく解説]
(https://www.sbbit.jp/article/cont1/62752)
[【初心者必見】APIって何？概要や必要性について徹底解説]
(https://www.jbat.co.jp/dx_blog_1/)
[WebAPIとは～WebAPIの仕組みと具体例についてご紹介～]
(https://it-rpa.hatenablog.com/entry/WebAPI_%E4%BB%95%E7%B5%84%E3%81%BF)
[非同期処理の完了を待つ方法！Promise＆async/await【分かりすぎて怖いJavaScript入門】]
(https://www.youtube.com/watch?v=Vhnz1V-v1cU&t=919s)
[JavaScriptの非同期処理を同期させる方法【初心者向け】]
(https://www.otwo.jp/blog/asynchronous-processing/)
[Fetch の使用]
(https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch)
Git command

<h2>機能ごとに新しくブランチ作成する</h2>
```
git checkout develop(:統合ブランチ)
git checkout -b 新規ブランチ名　　#ブランチを新規作成、そのまま切り替える
```
<h2>「完璧な完成品」をgit hubにアップする</h2>
<p>コミットメッセージ: Start Finish Add Update Remove Fix</p>
```
git status
git add *
git commit -m "メッセージ"
git push origin (統合させたい/挙げたいブランチ)
→→プルリク作る
```
<h2>プルリク時、compareing changesで base:develop 統合ブランチ選択</h2>

![スクリーンショット 2021-08-17 17.00.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1801328/f945fe9e-dc1f-a166-0c24-8043126e2853.png)

<h2>プルリク承認後に　メンバー・本人がローカルに落とし込む</h2>

```
git checkout develop(:統合ブランチ)
git branch
git pull origin develop(:統合ブランチ)
```


<h2>コンフリクト修正/プルリク承認後　メンバー・本人がローカルに落とし込む</h2>

```
git checkout develop(:統合ブランチ)
git branch
git pull origin develop(:統合ブランチ)
git checkout 自分の作業ブランチ
git merge origin/develop(:統合ブランチ)
git push origin 自分の作業ブランチ
```

<h2>変更履歴を残す準備 (git add)</h2>
```ruby:
$ git add *   # 変更があったファイルをすべて索引に追加
$ git add [file名] # file名のみ
$ git add -A # git add . + git add -u = 新規作成/編集/削除したファイルをaddする
$ git add -p # 対話モードになり、コード単位でadd指定ができる、addしたいならy（yes）,したくないならn(no),コードの塊を分割したいならs(split)でEnterを押していく

$ git add . # すべてのファイル・ディレクトリ
$ git add *.css # すべてのCSSファイル
$ git add -n # 追加されるファイルを調べる
$ git add -u # 変更されたファイルを追加する
$ git rm --cached # addしてしまったファイルを除外（要確認）
```
<h2>変更履歴を保存する (git commit)</h2>
```
$ git commit 
$ git commit -m "Initial commit 1" # メッセージを加える場合
$ git commit --allow-empty -m "empty commit" # 空コミット

$ git commit -a # 変更のあったファイルすべて
$ git
```

<h2>自分のブランチ確認</h2>
```
git branch
```
<h2>ブランチ移動</h2>
```
git checkout 行きたいブランチ名
```

 

<h2></h2>
```
```
<h2></h2>
```
```
RubyのGemについてのまとめ

#今回のテーマ
今回は、RubyのGemについて学んだことを投稿していきたいと思います。主に、gem,bundler,gemfileについて書いていきたいと思います。

#gem
gemは、ログイン機能や検索機能など、便利な機能がパッケージ化されたRubyの外部ライブラリである。使用するには、インストールと読み込みが必要である。コマンドで以下を実行すると、gemをインストールすることができる。また、インストールしているgemの一覧を表示するには、gem listを使う。

```
gem install インストールしたいgem名
```
実際にgem listを実行すると、以下のように自分のPCにインストールされているgemが表示される。

```
$ gem list
*** LOCAL GEMS ***

actioncable (6.1.4, 6.1.3.2)
actionmailbox (6.1.4, 6.1.3.2)
actionmailer (6.1.4, 6.1.3.2)
actionpack (6.1.4, 6.1.3.2)
actiontext (6.1.4, 6.1.3.2)
actionview (6.1.4, 6.1.3.2)
activejob (6.1.4, 6.1.3.2)
activemodel (6.1.4, 6.1.3.2)
///
省略
///
xmlrpc (0.3.0)
xpath (3.2.0)
zeitwerk (2.4.2)
zlib (default: 1.0.0)
```
※用語の解説

- パッケージ =>プログラムの部品で便利な機能を一まとめにしたもの。
- ライブラリ =>汎用性の高い機能を、他のプログラムを呼び出して使えるように部品化して集めたファイル
- 外部ライブラリ =>開発者が他の開発者にも使えるように開発したライブラリ


#bundler
gem同士の依存関係やgemのバージョンを管理するgemの一種である。
例えば、あるgemのバージョンを使うために、別のgemのバージョンが必要だったとする。この時、この二つのgemは依存関係にある。という。ただ、正しいバージョンの組み合わせでインストールしないと、意図しない動作をする恐れがある。
->bundlerを使うことで、このような依存関係にあるgemの一括インストールを行うことができる。
gemのバージョンを確認するには、以下のコマンドを打てば良い。

```
$ bundler -v
Bundler version バージョンの数
```

#Gemfile
bundlerによってインストールされたgemの一覧を管理するファイルである。インストールされているgemとそのバージョン一覧が記述されている。railsのgemをインストールすると、gemfileが生成されるが、その時のgemfileの例を以下にあげる。

```
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.6'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'
gem 'rails', '~> 6.1.4'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4'
# Use Puma as the app server
gem 'puma', '~> 5.0'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker

///
省略
///

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

```

#まとめ
以上のことをまとめると以下になる。

- gem:様々な機能がパッケージされたRubyの外部ライブラリのこと
- bundler:gem同士の依存関係を管理する。
- gemfile:bundlerによってインストールされたgemとバージョンが記述されたファイル

まだまだ勉強中ですが、見ていただきありがとうございました。
alphafold2インストールの補足的な情報

基本は@Ag_smithさんの記事で良いと思うのですが、つまづく方もいると思うので補足的な情報を書きます。

https://qiita.com/Ag_smith/items/7c76438906b3f665af38


#新しいGPUを使用する場合はDockerfileの修正が必要？

https://github.com/deepmind/alphafold/issues/55

A10や、RTX A6000や、GeForce RTX 3090などCompute Capabilityが8.6のものはCUDA11.0によりサポートされていないので、Dockerfile中のCUDAのバージョン等を変更する必要があるそうです。

上記リンク中の修正内容をDockerfileに反映させればOKです。
なお、Compute Capabilityの値は下記リンクから確認できます。

https://developer.nvidia.com/cuda-gpus

#プロキシ環境の場合

事情があってプロキシを使う必要がある人は以下を実行すると良いのではないでしょうか。

##dockerのプロキシ設定

https://qiita.com/dkoide/items/ca1f4549dc426eaf3735

↑の記事の
1. systemdに環境変数を設定する
2. Dockerクライアントを設定する
を実行します。

##データベースのダウンロード

https://blogger.tempus.org/2009/11/firewall-macports.html

download_pdb_mmcif.shの実行時にrsyncを実行しますが、プロキシの設定が必要です。

```bash
export RSYNC_PROXY=proxy.example.com:8080
```

http://や最後に/をつけないよう注意しましょう
ChromeからMacのアプリを開くリンク

自分用のメモです。
Chromeでページを開いたときに

```
[アプリ]を開きますか?
https://~~ がこのアプリケーションを開く許可を求めています。
```
という画面が出てくるので、これをどうやっているのか調べました。

結論としては

```
スキーム名://content
```
といった風に記述すればよいだけでした。
スキーム名はアプリのInfo.plistファイルに

```xml
<key>CFBundleURLSchemes</key>
　　　<array>
        <string>myapp</string>
     </array>
```
のような形で書かれています。開きたいアプリがあったらInfo.plistを覗いてみるとよさそうです。

対応表

アプリ名|スキーム
| ---- | ---- |
App Store|macappstore
Slack|slack
zoom | zoommtg
vscode| vscode
Line|line
Word|word
Excel|excel

ブラウザからアプリを開きたいときにリンクを登録しておけばブックマークから直接アプリが開けたりなんかできるなと思いました。
Raspberry Pi 4B 8G に FreeBSD 13.0 ARM64を入れて zfs raidz (SSDを４個）からブート

Raspberry Pi 4B 8G で zfs raidz を構築してみました
実験段階なので、多少手抜きしています

１．準備したもの
　　Raspberry Pi 4B 8G 本体
　　コンセントから電源供給できる４ポートのUSBハブ
　　USB接続できるSSD４個、４個とも同一サイズが理想ですが、２５６GB２個と２４０GB２個でやってみました
　　zfs環境を構築するためのSDカード１個、１２８GBが余っていたので、FreeBSDがインストールできればOKです

２．イメージファイルの書き込み
　　FreeBSD-13.0-RELEASE-arm64-aarch64-RPI.img.xzをSDカードとSSD４個に書き込みます
　　私は Raspberry Pi Imager を使いました

３．ブート確認
　　SDカードと４個のSSDを順番に１つだけセットしてブートするか確認します
　　次に、SDカードとSSD１個を接続してSDカードからブートするか確認します
　　ファームウェアのの起動順序の設定を変更していなければ、SDカードからブートすると思います

３．環境構築
　　SDカードと４個のSSDを接続して、SDカードから起動します
　　/etc/rc.conf に設定を追加します
　　powerd_enable="YES"
　　ntpdate_enable="YES"
　　keymap="jp"

　　/boot/loader.conf の内容を zfs_load="YES" だけにします

　　再起動し、無事ブートするか確認します
　　アップデートします
　　freebsd-update fetch
　　freebsd-update install

４．ストレージプールの作成
　　zpool create -f zroot raidz da0s2a da1s2a da2s2a da3s2a

　　ファイルシステムの作成
　　zroot/F1 が実際の / になります
　　zfs set mountpoint=legacy zroot
　　zfs set atime=off zroot
　　zfs create zroot/F1
　　zfs create zroot/F1/usr
　　zfs create zroot/F1/usr/src
　　zfs create zroot/F1/usr/obj
　　zfs create zroot/F1/usr/ports
　　zfs create zroot/F1/tmp
　　zfs create zroot/F1/var　　

　　システムのコピー
　　zfs set mountpoint=/mnt zroot/F1
　　tar cf - --one-file-system / |(cd /mnt;tar xvf -)
　　ブートするファイルシステムを設定します
　　zpool set bootfs=zroot/F1 zroot

　　/mnt/etc/fstab の内容を以下のように変更します
　　zroot/F1		/		zfs	rw	0	0
　　zroot/F1/usr		/usr		zfs	rw	0	0
　　zroot/F1/usr/src	/usr/src	zfs	rw	0	0
　　zroot/F1/usr/ports	/usr/ports	zfs	rw	0	0
　　zroot/F1/usr/obj	/usr/obj	zfs	rw	0	0
　　zroot/F1/tmp		/tmp		zfs	rw	0	0
　　zroot/F1/var		/var		zfs	rw	0	0
　　/dev/da0s1          /boot/msdos      msdosfs rw,noatime 0    0
　　tmpfs                 /tmp              tmpfs   rw,mode=1777,size=50m 0 0

　　/mnt/boot/loader.conf に　vfs.root.mountfrom="zfs:zroot/F1" を追加します

５．zfsファイルシステムから起動する準備
　　	zfs set mountpoint=legacy zroot/F1
　　zpool export zroot

　　シャットダウンします
　　poweroff

　　ラズパイを電源OFF
　　SDカード取り出し

６．zfsからブート
　　ラズパイの電源ON

　　無事、起動しましたでしょうか
　　以上です
マイクロソフトがヘルスケアにおけるプレゼンスを急速に拡大している方法

過去数年間で、ヘルスケア業界は大幅に成長しました。一部の巨人の業界への参入は、この成長に貢献してきました。これらのビジネスの巨人の1つは、ヘルスケアセクターを含む多くのセクターに現在投資している多国籍コングロマリットであるマイクロソフトです。

最近、さまざまな医療オプションがマイクロソフトから何らかの投資を受けています。この会社と他の多くのビジネスの巨人は、世界中のさまざまな場所でヘルスケアセクターを改善するために必要な効果を高める役割を果たしています。

マイクロソフトは、クラウドプロバイダーを改善して、医療専門家により包括的なサービスを提供しています。マイクロソフトの拡張されたクラウドサービスを通じて、医療機関は次のメリットを享受できます。

患者の健康情報を改善された方法で処理する

運用の推進、ケアの調整、専門知識の向上のプロセスを容易にします
健康情報の相互運用性、コンプライアンス、安全性を支援します

上記の利点に加えて、マイクロソフトは、医療機関がデジタルウェルビーイングを保証し、患者を監視できるように、24時間体制で取り組んでいます。これは、8つの新しい言語で利用できるようになります。

更新の適時性

もちろん、マイクロソフトからの更新は、コロナウイルスの大流行に対してすでにある程度の勝利を収めている今よりも良い時期に来ることはできませんでした。過去12か月で、医療制度は世界中のさまざまな国で大きく混乱しました。これにより、デジタルヘルスケアオプションとテレヘルスプロバイダーにより重点が置かれるようになりました。多くの健康産業の巨人は、この素晴らしい市場の大部分を占める方法を探しています。
マイクロソフトが提供するインフラストラクチャは、これを可能にするのに大いに役立ちます。会社の副社長であるトム・マクギネスは、これにもっと光を当てるために時間をかけました。彼は、Microsoft Dynamics 365は、物理的な予定を予約する際の柔軟性を高めるため、患者のデジタル専門知識を容易にすることを説明しました。この新しいプログラムは、患者のポータルを考慮し、デジタルヘルスアシスタントが関与します。プログラムの助けを借りて、トリアージ、スケジューリング、およびヘルスケアのニーズのフォローアップがこれまでになく簡単になりました。

これらのプロバイダーは、他の統合ツールと組み合わせることができるため、単独では機能しない可能性があることに注意してください。ウェアラブル、フィットネス、カーディオマシン、およびその他の分析ツールは、さまざまなグループ間のコラボレーションを促進するのに役立ちます。

このデバイスが提供することを約束する利点の大きな可能性は、今後数年間でこの企業体に期待されることを垣間見せてくれました。

マイクロソフトからの他の貢献

ただし、ヘルスケア分野におけるマイクロソフトの貢献は、このプログラムに限定されません。企業はまた、業界のための他の強力なツールを作成しました。たとえば、MicrosoftはHololensを提供しています。これは、<a href="https://www.bangbangcasino.com/ja/">オンラインカジノ</a>アプリや、さまざまなグループが共同作業を行えるようにするその他のものとの、束縛されていないブレンドツールです。ヘルスケア業界でのこのツールの使用に制限はありません。
現在、多くの外科医がHololensヘッドセットを利用して、世界中の他の人と協力して手術を行っています。このツールを使用すると、さまざまな大陸の外科医が協力してさまざまな外科手術を行うことができます。

さらに、この企業が投資している新しいパスに言及することが重要です。これらの新しいパスには、人工知能（AI）の使用が含まれます。 AIの使用は、次のようなさまざまな側面で大きな違いを生む可能性があります。

医療分析の機能を改善する
医療従事者間のコラボレーションの改善
セクターで得られる幸福の公平性を高める

時間の経過とともに、AIが提供するさまざまな可能性を探求できるようになるため、すべての医療機関に多くの変化をもたらすことができます。ヘルスケア業界でAIを最適なレベルで楽しむためにやるべきことがまだたくさんあることに注意する価値があります。それにもかかわらず、可能性は無限大です。

間違いなく、より大規模で経験豊富な組織や投資家は、ヘルスケアセクターに参入し続けるでしょう。これにより、マイクロソフトは、その膨大な専門知識、無数の情報源、および卓越した知識ベースを使用して、ヘルスケア業界を革新するための中心的な舞台に立つ機会を増やすことができます。過去40年間のこの企業体の大成功を考えると、近い将来、ヘルスケアセクターに大幅な改善をもたらすためにマイクロソフトに依存することは合理的です。
Flutterでヒュベニの公式を使い距離を計測した...

#2点間の距離を計測したい

###はじめに
この記事ではFlutterで緯度経度を利用して自分と対象地の距離を計測したい時に、自分で作った関数の失敗と公式関数の有用性を語っています。


###Flutter公式提供の関数
```dart
Future<void> getLocation() async {
    // 現在の位置を返す
    Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best);
    print("緯度: " + position.latitude.toString());
    print("経度: " + position.longitude.toString());

    // 距離をメートルで返す
    double distanceInMeters = Geolocator.distanceBetween(35.68, 139.76, -23.61, -46.40);
    
  }

```
LocationAccuracy.bestの.bestを.hightや.lowにすることで計測精度を変えることができます。


###ヒュベニの公式を利用して実装した関数
```dart
double CalculateDisntance(double lat1, double lon1, double lat2, double lon2){

    // 緯度経度をラジアンに変換
    double radLat1 = lat1*(pi/180);
    double radLon1 = lon1*(pi/180);
    double radLat2 = lat2*(pi/180);
    double radLon2 = lon2*(pi/180);

    // 緯度差
    double radratDiff = (radLat1 - radLat2);
    // 経度差
    double radlonDiff = (radLon1 - radLon2);
    // 平均緯度
    double radLatAverage = (radLat1 + radLat2);
    // 赤道半径
    double horizontal = 6377397.155;
    // 離心率の2乗
    double e2 = 0.00667436061028297;

    double sinLat = radLatAverage.sign;
    double w2 = 1.0 - e2 *(sinLat * sinLat);
    // 子午曲半径M
    double M = horizontal*(1-e2) / (sqrt(w2*w2*w2));
    // 卯酉線曲率半径
    double N = horizontal / (sqrt(w2));

    double t1 = M * radratDiff;
    double t2 = N * cos(radLatAverage) * radlonDiff;

    double dist = sqrt((t1*t1)+(t2*t2));
    return dist;
  }

```

##計測結果
Flutter公式提供のGeolocator関数と私の作ったCalculateDisntance関数では計測値に大きな違いが出ました。
公式提供では誤差は5m以下だったのに対し私の距離計測関数は倍以上の誤差が生じてしまった。
緯度経度から自分と対象との距離を求めたい時は素直に公式関数を利用することを勧める。

##終わりに
今回私が距離を計測するために利用した関数はヒュベニの公式というもので、下記のサイトでは比較的誤差が小さくなっている。しかし、私が作成したものは大きな誤差がある。おそらくどこか見落としなどがあるのだろう。式が違う所などあればご教示願いたい。
また、公式関数は非常に正確だが、aync/awaitを利用する非同期処理なので、注意して利用して欲しい。


###参考リンク
ヒュベニの公式:https://komoriss.com/calculate-distance-between-two-points-from-latitude-and-longitude/
Flutter Package：https://pub.dev/packages/geolocator
【PHP学習_備忘録】 PHPとは？変数の型とは？

#はじめに
ワードプレスに関わってくるPHPの勉強をしようと思い、
書籍からインプットしたものをQiitaでアウトプットしていく。

# PHPとは？
まずここからですよね。
PHPの正式名称は`ハイパーテキストプリプロセッサ`といいます。
PHPとは動的にWebページを生成することができるサーバーサイドのスクリプト言語です。

参考サイト

https://www.kagoya.jp/howto/wordpress/php/

#### 特徴1 HTML埋込み型のプログラミング言語
Webブラウザ上に表示される基本となるものがHTMLですが、PHPのプログラミングは
HTML文書の中に部分的に記載する。

#### 特徴２ サーバサイドスクリプト言語
スクリプト言語は、可読性が高く比較的簡単に書きやすい言語の総称です。

#### 特徴３ オープンソースである
PHP本体の元になるソースコードが公開されているので、誰でも機能を改良したり、拡張できたりします。

#### 特徴4 多くの機能が用意されている。
WEBアプリケーションの開発に必要な多くの機能が拡張モジュールという形式で用意されています。

#実際にコードを書いてみる
```php

<?php header('Content - type: text/html; charset=UTF-8') ?>

<html>
<body>
  <?php 
   echo 'はじめてのPHP';
  ?>
</body>
</html>
```

#### ポイント
①PHPファイルは phpの拡張子をつける
②<?php   ?>で囲んだ中にPHPコードの記述をする
③命令文の終わりには セミコロンを実施 ；（セミコロン）
④Webブラウザに表示させるには、echoやprintを使う。

Rubyをやっていたので、理解がしやすいです！！

#### 変数
$変数名 = 変数に代入する値;

※文字列を入れる場合は、シングルかダブルクォーテーションで文字を挟む。

#### データ型
【整数】
$hensu = 1234;
$hensu = -123;

【文字列型】
$aaa = 'PHPの勉強';
$bbb = 'PHPの勉強';

【論理型】
$aaa = TRUE;
$bbb = FALSE;

【ヌル型】
&aaa = NULL;

#### 型変換
型の自動的に変換を`型変換`という。
明示的に型変換を行うことを`キャスト`という。


| No |    書き方     |  意味       |
|---:|-------------|------------|
| 1  | (int)または(interger)  | 整数型に変換する           |
| 2  | (float)            | 浮動小数点型に変換する           |
| 3  | (boolean)            | 論理型に変換する           |
| 4  | (string)            | 文字列型に変換する           |

#### エスケープシーケンス
| No |    書き方     |  意味       |
|---:|-------------|------------|
| 1  | ¥n  | ラインフィード(LF)          |
| 2  | ¥r |キャリッジ・リターン(CR)            | 
| 3  | ¥t| 水平タブ(HT)           | 
| 4  | ¥¥| ¥(バックスラッシュ) |
| 5  | ¥$| $（ダラー） |

```
 echo "ただいま¥"外出中です¥" ;

出力
➩ ただいま"外出中"です。
¥"で囲むと文字の"として出力扱われます。
```

#今日はここまで。




## 参考文献
・ゼロからわかるPHP超入門
プレゼン大革命? おじさんたちに言いたいことを伝えるには。

# 内容
[1.言いたいことはセクション1つにつき3つまでにする。](#1-言いたいことはセクション1つにつき3つまでにする)
[2.セクションタイトルで内容が掴めるようにする。](#2-セクションタイトルで内容が掴めるようにする)
[3.前提から先に説明する。](#3-前提から先に説明する)

#1. 言いたいことはセクション1つにつき3つまでにする。
　人間は3つまでのことは瞬時に把握できるという性質に基づいたテクニックで、資料において3要素以上の塊を作らないようにするというものです。プレゼン全体で言いたいことは章3つまで、それぞれの章の中でも内容の並列分岐は3つまで、といった具合に3つ以下の塊に伝えたいことをまとめあげます。例えばこんな感じ。

- タイトル
    - 章1
        - 節1-1
        - 節1-2
    - 章2
        - 節2-1
        - 節2-2
        - 節2-3
    - 章3
        - 節3-1

　これはよくプレゼンの教科書みたいなものに紹介されているテクニックですが、先日「[ゆる言語学ラジオ](https://www.youtube.com/watch?v=jrNc7fmtTNE)」というYouTubeを見ていて、人間の本能に基づいたテクニックなんだと確信しました。詳しくは動画をご覧ください。

#2. セクションタイトルで内容が掴めるようにする。
　ここからは僕独自の工夫です。よくプレゼン資料にあるセクションタイトルは「〇〇の結果」とか「××の特性」とかだと思います。ふと思い立ってこれを「△の性能は〇〇において優位」とか「□は周波数特性が緩やか」とかに変えてみたところ、周りの評判が非常によくなりました。そのページで言いたいこと1つをそのままタイトルにすることで、スライドの内容を細かくみなくても良くなるので、マネージャーたちには評判が良いのでしょう。
　できることならタイトルに「〇〇は」を使って主題提示をしてあげると良いです。そうするとどれを注目してみていれば良いのかがしっかり伝わります。「〇〇が」を使うと主格の影響範囲が狭いので好ましくありません。詳しくは[エンジニアこそ知っておくべき日本語の作文](https://qiita.com/tommyecguitar/items/7ef11f5a2097f2383b06)をご覧ください。

#3. 前提から先に説明する。
　説明する際には大枠から説明しましょう。当然ながらこれを怠ると論理構成をうまく伝えられないので大失敗します。

# まとめ
　まとめみたいなものは正直意味をなさないことも多いので、上記のことがしっかりできていれば必要ないと思います。
C# で in 句 ： The "IN" operator in C#

## はじめに

ネットで、`C#` `in句` で検索すると、以下のものが見つかります。
しかし満足できなかったので自分用のスニペットを作成しました。

- https://takap-tech.com/entry/2019/11/21/235109
- https://dk521123.hatenablog.com/entry/30276314
- https://mk.hatenablog.jp/entry/20100706/1278379175
- https://www.kazukiio.com/entry/2019/01/29/000919

## サンプルコード

サンプルコードを見ていただければ一目瞭然ですが、`Contains()` があれば別に `In()` など要らない気がします。

まあ、でも可読性のために欲しくなるケースもあるでしょう。

```csharp
using System;
using System.Linq;

namespace InTest
{
    static class Ext
    {
        public static bool In<T>(this T source, params T[] list)
        {
            return list.Contains(source);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            if (5.In(1, 2, 3, 4, 5)) Console.WriteLine("Match!");

            var productName = "Macbook Air";
            var appleProducts = new string[] { "Macbook Air", "Macbook Pro", "Mac mini", "iMac" };

            if (productName.In(appleProducts)) Console.WriteLine("Match!");
        }
    }
}

// #error version -> コンパイラ バージョン: '3.7.0-6.20371.12 (917b9dfa)'。言語バージョン: default。
// いや、default ってなんや。
```

## 正規表現版

正規表現と組み合わせると、存在意義が少し向上するような気がします。

```csharp
using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace InByRegexTest
{
    static class Ext
    {
        public static bool In(this string source, params string[] patterns)
        {
            return patterns.Any(pattern => Regex.IsMatch(source, pattern));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string productName = "Macbook Air";
            string[] appleProductPatterns = new string[] {
                "[m|M]ac.*",
                "iPhone[0-9]*",
                "Apple TV [4K|HD]",
            };

            if (productName.In(appleProductPatterns)) Console.WriteLine("Match!");
            if ("iPhone12".In(appleProductPatterns)) Console.WriteLine("Match!");
            if ("Apple TV 4K".In(appleProductPatterns)) Console.WriteLine("Match!");
        }
    }
}
```
KerasのPermuteレイヤーの挙動確認


こんにちは。つんあーです。

[KerasのPermuteレイヤー](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Permute?hl=ja)なのですが、
「たぶん転置的な動きをしてくれるんだよなぁ」とふんわり理解しているものの、
実際の挙動をちゃんと把握していなかったので、簡単に試してみました。


## さくっと構築

（モデルっていうようなものではないですけどね）


`shape=[10, 2]`のTensorを、Permuteレイヤーを通すことで`shape=[2, 10]`に変換する
という想定で定義しました。

```
import tensorflow as tf
from tensorflow.keras import layers, models

model = models.Sequential(name='Permute_sample')
model.add(layers.Permute(input_shape=(10, 2), dims=(2, 1)))

model.compile(optimizer='adam', loss='binary_crossentropy', metrics='acc')
model.summary()


# 出力
# Model: "Permute_sample"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# permute_1 (Permute)         (None, 2, 10)             0         
# =================================================================
# Total params: 0
# Trainable params: 0
# Non-trainable params: 0
# _________________________________________________________________
```

ご存知のことかと思いますが、暗黙に追加されている`Output Shape`の`None`にはバッチサイズが入ります。


`[10, 2]`形式の入力データを用意します。
バッチサイズとして頭に1次元追加して`shape=[1, 20, 2]`となるようにしました。

```
array = np.arange(20).reshape(10, 2)
input = array.reshape((1, 10, 2))
print(input)


# 出力
# [[[ 0  1]
#   [ 2  3]
#   [ 4  5]
#   [ 6  7]
#   [ 8  9]
#   [10 11]
#   [12 13]
#   [14 15]
#   [16 17]
#   [18 19]]]
```


これをモデルに入力してみます。

```
result = model.predict(input)
print(result)

# [[[ 0.  2.  4.  6.  8. 10. 12. 14. 16. 18.]
#   [ 1.  3.  5.  7.  9. 11. 13. 15. 17. 19.]]]
```


2階と3階 が転置されたTensorが出力されました。
shapeとしては、バッチサイズを含め`[1, 2, 10]`となります。


結果的に、普通に転置した状態になりましたね。
（dtypeを特に指定しなかったので、floatになっている点だけ注意が必要かもしれませんね）


## ちなみに

`numpy.transpose`の場合はこんな感じ。
明示的にしたかったのでわざわざ`axes`引数を付けていますが、指定なしでも同様の結果になります。

```
transposed = np.transpose(array, axes=(1, 0))
print(transposed)


# 出力
# [[ 0  2  4  6  8 10 12 14 16 18]
#  [ 1  3  5  7  9 11 13 15 17 19]]
```

`numpy.reshape`だとこう。

```
reshaped = np.reshape(array, newshape=(2,10))
print(reshaped)


# 出力
# [[ 0  1  2  3  4  5  6  7  8  9]
#  [10 11 12 13 14 15 16 17 18 19]]
```

出力shape自体は`[2, 10]`で一致しますが、
中身は全然別物にですね。
[Reshapeレイヤー](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Reshape)でも、もちろんこの結果になります。




## 余談

Weblioによると、それぞれ意味は

>transpose
> => 置き換える、入れ替える、転置する、言い直す、移調する、移項する、変換する
>
> permute
> => (…を)変更する、交換する、(…を)並べ換える、順列する


とのことです。
大体同じことを言っていたのですね。


転置行列のことは *transposed matrix* とか言ったりすることもあるのでなんとなくtransposeの方が馴染みがあるような気がするのですが、
意味的にも挙動的にも同じ概念を指しているということがわかったので今後は安心して使えそうですね。



おしまい。
C# で Between 

## はじめに

ネットを探すとすぐに見つかるのですが、念のため自分用のスニペットを。

- https://www.it-mure.jp.net/ja/c%23/c＃に「between」関数はありますか？/971771777/
- [【C#】あるとちょっと便利な拡張メソッド紹介 - Qiita](https://qiita.com/s_mino_ri/items/0fd2e2b3cebb7a62ad46)

## 追記

From ... To がそれぞれ「含む」「含まない」が指定できないため、指定できるものをつくりました。

[C# で Between（やりすぎバージョン） - Qiita](https://qiita.com/Tachy_Pochy/items/19adf2a373a99f6cccca)

## サンプルコード

```csharp
using System;

namespace BetweenTest
{
    static class Ext
    {
        public static bool Between<T>(this T source, T low, T high) where T : IComparable
        {
            if (low.CompareTo(high) > 0) { throw new ArgumentException(); }
            return source.CompareTo(low) >= 0 && source.CompareTo(high) <= 0;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            if (5.Between(0, 9))
            {
                Console.WriteLine("Hello World!");
            }

            if ("5".Between("0", "9"))
            {
                Console.WriteLine("Hello World!");
            }
        }
    }
}
```

## 使い所

VB では問題なくできるのですが、C# では以下のように書くとエラーになります。

```csharp
if ("0" <= val && val <= "9")
{
    // ...
}
```

文字列の比較に `<=` とか書けないのです[^1]。こんな時に Between があると次のように書けるので助かります。

[^1]: しかもこの時の業務は `val` に英字記号も入ってきていたので `int.Parse` も許されなかったのです。

```csharp
if (val.Between("0", "9"))
{
    // ...
}
```
javascript  random, floor 使い方メモ 

# javascript   -- random, floor 使い方メモ --, 



Math.random()

０以上１未満の浮動小数点の乱数を返す。





Math.floor()

引数に与えた数字以下の最大の整数を返す。



参考サイト元
> https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/random

> https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/floor
jQueryの.find()はIE対応でJavaScriptの.find()は非対応

jQueryには、要素の子要素を取得する方法に`.children()`と`.find()`があります。

`.children()`は子までを取得してくれるのに対して、
`.find()`は子と孫まで取得してくれます。便利ですね。

しかし、`.find()`を使ったページをIEで表示すると稀に「オブジェクトは 'find' プロパティまたはメソッドをサポートしていません。」というコンソールエラーが表示されます。なぜでしょうか。
それは**JavaScriptの`.find()`はIE非対応だから**です。
このコンソールエラーが表示されるということは、`.find()`がjQueryではなくVanilla JSと解釈されています。
## .find()の対象が配列の場合、IEでコンソールエラーが発生する
その条件は、**`.find()`の検索対象がjQueryオブジェクトか配列かの違い**です。
つまり、jQueryが`$("任意の値").find()`で
Vanilla JSが`Array.prototype.find()`と書き分けられる必要があります。
## コンソールエラーが発生した箇所は.some()に置きかえる
本当は上記の条件にあわせてコードを書き換えるべきですが、応急処置として
`.find()`をBooleanとして利用している場合、そして検索対象が配列の場合（要は`.find()`をVanilla JSとして使う場合）`.some()`で置き換えると意図した動きをしてくれるので参考にしてみてください。
MQTT over WebSocket に対応した mosquitto の設定

次のシステムを構築するために必要な MQTT ブローカーです。
[Grove IoT スターターキット for SORACOM で作るリモートカメラシステム](https://qiita.com/ekzemplaro/items/541b82908cec46f6aa7b)

設定ファイルを次のように変更します。

```text:/etc/mosquitto/mosquitto.conf
（省略）
listener 1883
allow_anonymous true
listener 8080
protocol websockets
```

mosquitto の再起動

```bash
sudo systemctl restart mosquitto
```

mosquitto のバージョン

```text
$ mosquitto -h
mosquitto version 2.0.10

mosquitto is an MQTT v5.0/v3.1.1/v3.1 broker.
```

ブローカーの検証については、次のプログラムが使えます。
[MQTT Subscribe で受け取った温度と湿度をブラウザーに表示する](https://qiita.com/ekzemplaro/items/7af584b418a05f9da7d0)
>broker と topic は自分の環境に合わせて下さい。
undotree.vimはdiffに依存している

https://github.com/mbbill/undotree
>Undotree is written in pure Vim script and doesn't rely on any third-party tools.

SoftwareDesignにも取り上げられていたので、vimプラグインであるundotreeをインストールしてみたが、Windowsのデフォルトでは動作しなかった。

調べてみたところ、Linux等の他のOSではデフォルトで入っているdiffコマンドが、Windowsにはデフォルトでは入っていないためにエラー判定をしている模様。
https://github.com/mbbill/undotree/blob/1cc3b9069e4356efd4ce1c3c4bdbb227fb54e1e5/autoload/undotree.vim#L1200

試しにDiffUtils for Windowsをインストールしてみたところ、エラーは出なくなり起動した。
http://gnuwin32.sourceforge.net/packages/diffutils.htm
トリムで改行コード削除

# はじめに
https://qiita.com/etoootak/items/01fd09e8f5b802c29053
の流れで、Automation Anywhere V11とAutomation 360の微妙な違いシリーズです。

# 「文字列：トリム」でデータ末尾の改行を除去
タイトルだけで終わる内容ですが、Automation360では文字列末尾の改行コードを
「文字列：トリム」アクションで除去できます。

業務システムからデータを変数に入れた場合に末尾に改行コードが入っていて、それが邪魔になる事があります。そういったときにトリムが使えます。

Automation Anywhere V11のトリムは改行コード除去ができなかったので
String Before-Afterの「Remove Enter from the extended text」を使うとか、
String Replaceの正規表現を使うとか、
ひと工夫必要でした。

トリムでできるのはシンプルで嬉しい変更です。

# おまけ

・JavaのString trim()は、確か改行文字も対象にするのでその影響かな？
・「文字列：トリム」は「文字列：削除」に名前が変わりました。個人的にはトリムの方が好き！！
Flutter と React Native: 現在、どちらが最良でしょうか。(第三部）

<!-- wp:paragraph -->
<p><a href="https://qiita.com/ints/items/a4f9149fc285cdef954d">第二部はこちら</a></p>
<!-- /wp:paragraph -->
**2.クロスプラットフォームアプリ開発とは何ですか？なぜそれを選択するのですか？**

  現在、ソフトウェア市場ではクロスプラットフォームアプリがいっぱいあります。それはなぜ多くの企業がクロスプラットフォームアプリを選んでいるのですかという質問を挙げられます。それで、この記事を詳しく説明する前に、必要な概念を明確にしましょう。

 各プラットフォーム（AndroidおよびiOS）には、開発者がアプリを作成するために使用される特定の言語があります。AndroidにはJavaであり、iOSにはSwiftとObjective-Cです。各プラットフォームには、ネイティブ開発でも使用される特定のAPIとSDKのセットがあります。一般に、これらの言語で開発されたアプリケーション、プログラミングインターフェイス、および開発ツールキットはすべてネイティブです。

  ネイティブアプリ開発の必然的な結果は、特定のオペレーティングシステムでのみ実行できるアプリケーションを取得することです。それはアプリケーションの保守と更新に困難を引き起こします。さらに、企業がAndroidとiOSのネイティブアプリを作成したい場合は、作成の作業を2回行う必要があります。つまり、両方の全体のシステム用にアプリを別々に開発する必要があります。このプロセスが大幅に開発コストの増加につながることになります。

 次に、クロスプラットフォームソリューションを見ていきましょう。ネイティブの中間層を介してオペレーティングシステムの機能にアクセスするためのモジュールがある多くのクロスプラットフォームフレームワークを見ることができます。クロスプラットフォームアプリは、基本的にWebとネイティブソリューションの中間です。Webアプリケーションはすべて、プラットフォームに依存しないソフトウェアの作成を向けていますが、次のような2つの欠点があります。

  *デバイスがインタネットに接続されている場合にのみアクセスできます。

*レスポンシブWebアプリは、モバイルアプリの同じ機能と利便性を提供できません。

 クロスプラットフォームアプリは、プラットフォームに依存せず、デバイスの機能へ同時アクセス権を提供するために、次世代のアプリです。さらに、オフラインで効果的に実行し、ネイティブアプリと同じようにアプリマーケットプレイスにアップロードできます。状況は、FlutterやReact Nativeなどの最高のクロスプラットフォームフレームワークで実現できます。

 ここまで、クロスプラットフォームアプローチとネイティブアプローチの違い点が分かると、それらの長所と短所について説明します。
![Flutter-Vs.-React-Native_sl3-1024x534.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1762420/77033172-e318-178c-33c9-fa04dc9fbc9e.png)


**クロスプラットフォームの長所**

 客観的には、ネイティブアプリの構造がプラットフォームで作成されるために、ネイティブアプリはスムーズに実行されいて、クロスプラットフォームアプリよりも直感的です。これらは顕著な利点ですが、多くの欠点もあります。特に企業がiOSとAndroidで動作するアプリを必要としている場合、それらの開発にはクロスプラットフォームソリューションよりも多くの時間とお金がかかります。開発者は2つの独立したアプリを構築する必要があります。これにより、開発、サポート、メンテナンス、および新機能の追加のコストが2倍になります。また、開発者がSwift、Objective-C、Javaなどのような特殊な言語を習得するには多くの作業が必要です。

 クロスプラットフォームアプリは、ネイティブアプリよりも遅く、オペレーティングシステムとの相互運用性が低いですが、Flutterフレームワークを使用すると、これらの問題がほぼ完全に解消されます。React Nativeアプリの開発は、これらの障害を克服し、クロスプラットフォームアプリを市場のトップの位置に導くのにも役立ちます。 利点として、クロスプラットフォームソリューションの方が安価で、高速で、開発が容易です。すべてのプラットフォームに単一の共通アプリが必要なため、更新プログラムの配信もそれほど複雑ではありません。クロスプラットフォームのアプリ開発自体がどんな効果を上げるのかが見えますが、2020年に最適なフレームワークを選択することも必要です。それは「FlutterとReact Nativeの間で、どちらの言語がより良いですか？」という質問が現在の傾向に非常に関連するようになる理由です。

<!-- wp:paragraph -->
<p><a href="https://qiita.com/ints/items/a4f9149fc285cdef954d">第二部はこちら</a></p>
<!-- /wp:paragraph -->


<!-- wp:paragraph -->
<p><a href="https://ints.vn/">株式会社INTS</a>   開発部   レー・ジャン</p>
<!-- /wp:paragraph -->
Jenkinsのジョブが動かない時の対処法

##経緯
Jenkinsでジョブを作成し実行したところ、エラーが発生してジョブが上手く動かなかった。
本記事はその備忘録として記す

##前提
サーバAからサーバBへ接続し、ジョブを実行させたいと思っている。
しかしJenkinsでの実行ログを見ると、どうもサーバAとサーバBの接続が上手くいっていないようだ。
その対処法としていくつか試している状況である。
初めに遭遇したエラーは以下だった。

```
# ssh danbo@ServerB.co.jp
Host key verification failed.
```

##試したこと
###その①
サーバBにknown_hosts情報の削除

```
# ssh keygen -R danbo@ServerB.co.jp
```
[-R]オプションは、「指定したホストに属する鍵を全て取り除く」と資料にあり、サーバBに接続する際のknown_hostsに指定された鍵を一度削除するのに有効だと考え、実行。しかし、上手くいかない。しかも別エラーが発生

```
##発生したエラー文
Pseudo-terminal will not be allocated because stdin is not a terminal.
```

###その②
更に変なエラーが出てきてしまったので、そちらの対処をすることにした。
以下参考資料にもあるように、オプションを付与することでの接続を試みた

```
# ssh -t -t danbo@ServerB.co.jp
```
しかし、付随して発生したエラーは解消されても、本来詰まっていたエラーへの対処にはならなかった。

###その③
以下コマンドにて実施

```
# ssh -o StrictHostKeyChecking=no danbo@ServerB.co.jp
```

ホストキーの認証をしない設定をオプションとして指定し、実行することでログインすることが出来ました！
参考資料にはファイルに記載するとありましたが、sshの場合オプションで指定してホストキー認証を飛ばすことも可能でした。
※上記オプションの場合、ホストキーが無い場合でもsshによる接続を行うことが出来ます。


##まとめ
ホストキー認証で詰まったら、一度認証を飛ばす設定をすると、接続ができる。
また、一度接続さえ出来てしまえば２回目からはホストキーを無視する設定を入れなくてもセッションが出来ているので
２回目以降はオプションを外して接続することも可能だった。

##参考資料
[ssh-keygen コマンドーーSSHの公開鍵と秘密鍵を作成する](https://atmarkit.itmedia.co.jp/ait/articles/1908/02/news015.html)
[Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/)
[JenkinsJobでssh接続先でコマンドを実行する方法](https://c-taquna.hatenablog.com/entry/2019/05/01/153235)
[[Linux] 特定SSHホストのフィンガープリントのチェックを省略する](https://qiita.com/suzutsuki0220/items/7864ad8cfd5c83fe4367)
URP移行時にハマったポイントと対処方法

# はじめに
ビルトインレンダリングパイプラインからURPに切り替えた際のハマりポイントの対処方法を記録します。

# ソフトシャドウが表示されない
Assets直下のUniversalRenderPipelineAssetのShadows > Softshadows のチェックボックスをONする。

# オブジェクトにライトを照らしても光が貫通し、影が表示されない。
Assets直下のUniversalRenderPipelineAssetのShadows > Lighting > AdditionalLights をPerPixelに設定し、表示された項目を任意の値に設定する。

# その他
こちらも参照のこと

https://qiita.com/kazuki_kuriyama/items/c98aa6e8fa2e32a4d20b
Julia Interact でブラウザで動くUIアプリをつくる

# Julia Interact

[Julia Interact](https://juliagizmos.github.io/Interact.jl/latest/)は、さまざまなUIウィジェットを提供しているパッケージ。Jupyterからならその場にUIが表示できてとても便利。でも開発環境をJupyterからVS codeにうつしてしまったので、Jupyterに依存するのはちょっと困る。

Interactはもともと様々な環境をサポートしていて、Junoだといい感じに統合されるようだ。そのうちvs codeにも来るような気がするが、独立したアプリとしても使いたいので、直接ブラウザで見られると嬉しい。と思ったら`Mux`でできるようになっていた。

## Mux

MuxはWebサービスフレームワークで、Webアプリを書くためのもの。
これで使うには次のようにすればいい。

``` julia
sing Interact, Mux, WebIO

function uitest()
    b = button("click me")
    text = textarea()
    on(b) do val
        text[] = "Clicked $val times"
    end
    Widget(["button" => b, "text" => text])
end

ui = uitest()
WebIO.webio_serve(page("/", req -> ui), 8000)
```
`click me`と書いたボタンと、テキストエリアを作り、ボタンがクリックされるとクリックされた回数をテキストエリアに書くUIを作って、'WebIO.webio_serve'で公開する。後は、ブラウザで`localhost:8000`を見に行けばいい。下のようなUIが表示されるはず。`req`を全く使わないところで混乱した。ウィジェットとサーバの間はWebSocketで通信されるので、通常のHTTPリクエストなどは最初の一回しか使わないようだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412142/538eabb6-de32-597f-2915-5ebc1dbd375a.png)


## Interactのウィジェットについて備忘録

Interactのウィジェットがちょっとわかりにくいのは、イベントの考え方が普通と少し違うからだろう。たとえばボタンがあったら、ボタンからいくつかイベントが出てくる(例えばpressed, releasedなど)ので、それにたいしてコールバックを定義するのがよくある考え方。

Interactの場合は、Observableというものがベースにあり、`on`でコールバック関数を定義する。Observableは状態が変化した際にコールバック関数を呼び出す。ウィジェットで発生したイベントに対してなにか行うというよりは、ウィジェットの変化がトリガになる。何が起こったのかは、コールバック関数の引数を見て、関数側で判断しなければならないようだ。

## Muxのサーバポート
Muxで立てたサーバの止め方がよくわからない。もちろんプロセスごと殺せば死ぬのだが、vs codeの中から起動した場合には、バックグラウンドタスクで動いているので、止めようが無い。すると、そのタスクがポートを握ったままになるので、コードを修正して同じポートのまま再実行すると、ポートが使えなくて落ちる。

これだといちいちコードを書き換えなければならなくてデバッグが大変面倒なので、次のような空きポートを順に探すコードを使う。

``` julia
import Sockets

function find_any_vacant_port(port, trial_count)
    error = nothing
    for i in 1:trial_count
        try 
            s = Sockets.listen(Sockets.ip"0.0.0.0", port + i - 1)
            close(s)
            return port + i - 1
        catch e
            error = e
            continue
        end
    end
    throw(error)
end
```
下のように使う。

``` julia
port = find_any_vacant_port(8000,20)
WebIO.webio_serve(page("/", req -> ui), port)
println("localhost:$port")
```
github actions で外部ファイルの変数を展開する

## 概要

業務の中で、github actions のワークフローから外部ファイルを読み込み、外部ファイル中の変数を展開して、利用したいという要望が生まれた。

github actions のワークフロー（テンプレートファイル内）では[ワークフロー構文](https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions)を用いて、ワークフロー中で定義した変数や各ステップの変数などを展開して利用することが可能である。 

一方で、読み込んだファイルに対しての操作が定義されいてないので、sed コマンドを用いて実装した。

## sed コマンド

man コマンドで sed を調べると、以下のように定義されている。

> The **sed** utility reads the specified files, or the standard input if no files are specified, modifying the input as specified by a list of commands. 

要するに、指定したファイルや、標準出力に対して修正を行えるコマンドである。

sed コマンドの具体的な使用方法は下記の記事が参考になります。

https://qiita.com/hirohiro77/items/7fe2f68781c41777e507

## json ファイル内に独自に定義した変数を sed コマンドで展開する

上記で説明した sed コマンドを使って、json ファイル内に定義した独自の変数を展開する。

まずは、json ファイルを用意する。

```json:hello.json
{
  "hello": "${hello}"
}
```

-e オプションを用いて、正規表現を使った置換を行う。

```sh
❯ sed -e 's/${hello}/HelloWorld/g' hello.json
{
  "hello": "HelloWorld"
}
```

`${hello}` が `HelloWorld` に変換されている。

今回は、正規表現を用いて返還したため、変数と判定しやすいように`${ 変数名 }`という形を取ったが`< 変数名 >`など、変数と判定できればなんでも良い。また、-e オプションの代わりに -i オプションをつけることでファイルを直接変更することもできる。

## github actions で json ファイルを読み込み変数を sed コマンドで展開する

いよいよここから本題です。と言っても、上記で説明した内容を github actions のワークフローに適用するだけである。

先ほどと同様に、json ファイルを用意する。

```json:hello.json
{
  "hello": "${hello}"
}
```

次にワークフローを定義する。

```yml:.github/workflows/hello.yml
name: hello

on:
  push:
    branches:
      - main

env:
  HELLO_WORLD: HelloWorld

jobs:
  hello:
    name: HelloWorld sample
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      # json ファイル出力
      - name: before modify json file
        run: cat hello.json
          
      # sed コマンドで json ファイルの変数展開
      - name: modify json file
        run: sed -i 's/${hello}/${{ env.HELLO_WORLD }}/g' hello.json

      # json ファイル出力
      - name: after modify json file
        run: cat hello.json
```

以下のようなディレクトリ構造になっていればOK。

```sh
❯ tree -a -I .git
.
├── .github
│   └── workflows
│       └── hello.yml
└── hello.json
```

この状態で main branch にプッシュすると github action が走る。以下が実行結果である。

![スクリーンショット 2021-08-17 17.34.08（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582722/bbe58a69-c116-550f-9d79-3723288c7ab2.png)


ワークフロー中で外部ファイルを読み込み、外部ファイル中の変数を展開することができた。
Scrapy+Cloudsearchでサイト横断検索機能を作る 

仕事でサイト横断検索機能を開発することがあったので、その構成や出来上がるまでの過程について触れていきます。

# 前提条件
- 自社ECサイトを複数出店している
- 各ECサイトはDBと連動した動的なものではなく、商品情報ベタ書きの静的サイト

# 社内からの要望
１つのサイトから別サイトの商品への誘導もスムーズに行いたいので、自社ECサイトの商品の横断的に検索できる機能が欲しい

# 技術選択
- CloudSearch
    - 検索DBが必要
    - サイト内検索機能などで調べているとCloudSearch/ElasticSearchが良さそう
    - 今回はCloudSearchの機能で十分かつ使いやすかったのでこちらを採択
- Scrapy
    - CloudSearchにインプットする辞書データが必要
    - 静的サイトなのでWebスクレイピングで収集したものを加工すれば辞書データができそう
    - WebスクレイピングにはPythonフレームワークの[Scrapy](https://scrapy.org/)が便利そう
- AWS Batch
    - 自動で商品情報を最新化していきたいので、日次でスクレイピングとCloudSearchへのデータ登録をしたい
    - 専用サーバーにプログラムを常駐させるのは実行頻度的にコストに無駄が多い
    - 一時的に実行環境リソースを作成し、その後削除してくれる/cronの指定方法でバッチ実行のできるAWS Batchを使うことにした


最終的な全体構成はこんな感じになりました。
![サイト横断検索構成 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257806/dca0d120-18cd-da87-bc72-f12f9eee6bcc.png)

開発期間は大体１ヶ月程度でした。
それぞれの箇所について下記で触れていきます。

# Webスクレイピング(Scrapy)
Scrapyは簡単に言うと、Webサイトを巡回するプログラム（Spider）を簡単に作成できるPythonフレームワークです。私はPython初心者でしたが、フレームワークがしっかりしているので割とスムーズに作成できました。Scrapyに関しては[こちらの記事](https://qiita.com/Chanmoro/items/f4df85eb73b18d902739)などを参考にさせて頂きました。
Webスクレイピングの特性上、対象ページ(html)のid/class属性の構造に依存するため、各サイトの構造に合わせてSpiderを作成することが実は一番時間がかかったと思います。
このプログラムでは以下のことをしています。

- 各サイトごとのSpiderを作成してWebスクレイピング
- スクレイピングの結果を加工して、CloudSearchに登録するための辞書データ（jsonファイル）を生成
- 生成したjsonデータをCloudSearchにアップロード
- S3にjsonをバックアップとして保存（いざと言うときに手動でCloudSearchに辞書データを登録するため）

3~4個目の機能はAWSのサービスへの操作なので、Python用のAWS SDKである[boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html)をインポートして開発しています。

[CloudSearchのドキュメントバッチの形式](https://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/preparing-data.html)を参考に、アップロードするjsonを生成しています。CloudSearchについては後述します。

```json
[
  {"type": "add",
   "id": "商品ページのURL（一意であれば何でも良いのでURLにしています）",
   "fields":{
     "url": "商品ページのURL",
     "img_path": "商品ページのメイン画像のURL（検索結果での画像表示用）",
     "title": "商品ページhtml内のtitleタグ（検索用）",
     "description": "商品ページhtml内のdescriptionタグ（検索用）"
    }
  },
︙
]
```

# ECR
Scrapyで作ったコードを登録しておきます。弊社ではGitlabを使っているので、pushした時にGitlab Runnerで自動ビルド→ECRにイメージ登録するようにしています。

# AWS Batch
バッチの設定を行なっています。
ECRに登録したコンテナイメージを元に実行環境を自動作成し、実行後は自動でリソースを消すのでコスト効率が良いです。

# CloudWatch Events
バッチの日次実行のスケジューリングを行なっています。
cron形式で指定できます。負荷の影響を抑えるため、自社ECサイトへのアクセスの少ない時間帯に実行するようにしています。

# CloudSearch
AWS Batchで配備された環境から実行されたScrapyプログラムから生成したjsonの辞書データをアップロードして各項目(titleやdescriptionなど)の検索設定を行うと、検索DBを生成してくれます。提供されるエンドポイントに対しクエリパラメータで絞り込み条件などを付加できます。詳しくは[こちら](https://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/searching.html)。

# S3
スクレイピングプログラムで生成したjsonデータをバックアップとして置いておきます。
検索データに異状が起きたときに手動でリストア(CloudSearchにデータ登録)する場合などに使います。

# API Gateway
検索機能を設置するWebサイトからCloudSearchのエンドポイントを直接叩くことも可能と言えば可能ですが、それだと何のサービスを使っているか丸見えなのでAPI Gatewayで隠蔽します。また、社内の事情で一部のサイトを一時的に除外してほしいなどの調整もあり得るので、Lambdaと連携させてそちらにサイトの絞り込みなどを担当させています。

# Lambda
API Gatewayからhttpリクエストをルーティングして実行されます。
CloudSearchはクエリパラメータに絞り込み条件を付加できるので、ユーザーに意識させたくない内部的な絞り込みをLambda関数にさせています。
Angular でプライベート変数とかを呼び出してテストするには？


Angularでプライベート変数とかを呼び出してテストするときどうするんだろう？

## private変数のテストコード

``` typescript
import { Component } from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {

 constructor(){}

private book = 'book1'

 private test1(){
   return "test is passed."
 }
}
```

``` typescript
const fixture = TestBed.createComponent(AppComponent);
const component = fixture.componentInstance;
expect(component['book']).toEqual('book1'));
expect(component['test1']()).toEqual('test is passed.'));
```

基本的に👇みたいな形にすれば呼び出せるっぽい

- component['テストしたいプライベート変数']  
- component['テストしたいプライベートメソッド']　()  

## まとめ

そもそもprivateなものはテストしないというのがあるらしい。
もう少し調べてユニットテスト無双したい。
【PHP】組み込み関数で数か月前の日にちを取得する

PHPの日付を求める組み込み関数はバグが存在するので単純にstrtotime()で"-1 month"の様に
フォーマットを指定するだけではうまくいかない

そのため、以下の手順で求めていく
例として今日から３ヵ月前を求める場合

①今日の月初の日にちを求める(1日)
②月初の日を元に、３ヵ月前の月を取得
③３ヵ月前の月の日を今日の日にする。
③ー２　３ヵ月前末日と今月末日の日にちが一致しない場合(ex:05-31と02-28など)３ヵ月前末日を代入

例：３ヵ月前の場合

```PHP
//3ヵ月以上経過しているかチェックする
function chkThreeMonth($targetDate) {
  // 本日の日付を比較日の日付に仮設定
  $comparedDate = date("d", strtotime("today"));
  // 今月の月初
  $firstDate = date("Y-m-d", strtotime('first day of this month'));
  // 比較月の年月
  $comparedYearMonth = date("Y-m", strtotime($firstDate . '-3 month')); 
  // 比較月の末日
  $comparedLastDate = date('d', strtotime('last day of ' . $comparedYearMonth));

  // 比較月の末日が本日より小さいなら末日を比較日に設定
  if($comparedLastDate < $comparedDate){
    $comparedDate = $comparedLastDate;
  }
  // 比較結果
  return strtotime(sprintf('%s-%02d', $comparedYearMonth, $comparedDate)) > strtotime($targetDate);
}

// もしくは
// strtotime(sprintf('%s-%02d', $comparedYearMonth, $comparedDate)) >= strtotime($targetDate)と同等
function chkPassedThreeMonth(DateTime $targetDate) {
  $baseDate = new DateTime();
  return $baseDate->diff($targetDate)->format('%m') > 2;
}

// strtotime(sprintf('%s-%02d', $comparedYearMonth, $comparedDate)) > strtotime($targetDate)と同等
function chkPassedThreeMonth(DateTime $targetDate) {
  $baseDate = new DateTime('yesterday');
  return $baseDate->diff($targetDate)->format('%m') > 2;
}
```
[Vuetify]v-alertを使用してモーダルでアラート機能を実装する方法


# はじめに
アラート機能を``Nuxt.js＋Vuetify``で実装しようと思いました。
アラートはコンポーネントで管理して、本体ページにアラートが必要な際に表示、数秒後
には消えるといった実装にしたかったのですが、分からずに困ってしまいました。
というのも、Vueに関しては非同期でコンポーネントを読み込むという説明が公式であったのですが、Nuxtでは見つけられなかったからです。

参照： [Vue.js非同期でコンポーネント読み込む](https://jp.vuejs.org/v2/guide/components-dynamic-async.html)


# 実装
``page``に``alert``コンポーネントを読み込ませて表示させてから４秒後に消します。
(alertはエラー用のコンポーネントも用意しています)

**page**

```vue
<template>
  <v-app>
    <div
      class="teal lighten-1 background pa-10"
    >
 // レスポンスの値で条件分岐

　　　　　　　　//成功した時
      <div v-if="responseBook === 'OK'">
        <AlertSuccess />
      </div>
　　　　　　//失敗した時
      <div v-else-if="responseBook === 'ERROR'">
        <AlertError />
      </div>
    </div>
  </v-app>
</template>
<script>
export default {
  computed: {
    responseBook () {
      return this.$store.state.book.responseBook
    }
  }
}
</script>

```
``page``の方は通常通りコンポーネントを読み込ませているだけです。
サーバーの応答によって処理を変えています。サーバー側の処理は``store``で``axios``を使用していますが、今回は割愛します。


**components/alert** 

```vue

<template>
  <v-alert
    type="success"
    :value="alert"
    dense
    class="alert"
  >
    登録しました。
  </v-alert>
</template>
<script>
export default {
  data () {
    return {
      alert: true
    }
  },
  created () {
    setTimeout(() => {
      this.alert = false
    }, 4000)
  }
}
</script>

```
``template``や``script``は``Vuetify``の``v-alert``のテンプレートをそのまま引用しています。
scriptでは``setTimeout``を使用して``alert``を``true→false`` にしています。
工夫した点は``created``を使用して``setTimeout``を使用することでコンポーネント自体を非同期で読み込むのではなく、コンポーネントの中身を非同期で処理して表示を調節するというところです。
AWS認定ソリューションアーキテクト-アソシエイト-合格体験記

#はじめに
この度、AWS 認定ソリューションアーキテクト – アソシエイトに合格することができました。

* 学習前の自分のレベルは？
* 学習教材は何を使って、どのように勉強したのか？
* 学習時間はどのぐらいかけたのか？

等を書いた、合格体験記になっています。
これから、AWS SAA合格を目指している方に役立つ情報になれば幸いです。

#学習前の自分のレベル
* 実務で使ったことのあるAWSサービスはLambda、EC2、Athena、SESのみ（それぞれ少し利用したことがある程度）
* AWS　クラウドプラクティショナー合格済

#学習教材
書籍
[AWS認定資格試験テキスト AWS認定 ソリューションアーキテクト-アソシエイト](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/479739739X)
過去問
[【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/)

#勉強の仕方
まずは、書籍を通勤時間に読みました。
電車で片道20分の職場なので、1日40分程度読んでいました。
読み進める中で理解ができない部分もありましたが、とにかく一周読み切ることを目標に毎日継続していました。
厳密には覚えていませんが、たしか1.5ヶ月ぐらいで読み終わったと思います。

書籍を読み終えたあとは、Udemyで過去問に取り組みました。
間違えたところは教材の解説だけでなく、[AWS サービス別資料](https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/)のPDFも確認しました。
全部で6回分ありましたが、2回分を終えた時点で、本試験を受けることにしました。
なぜなら一回目不合格でも二回目の受験料が無料になるキャンペーンをやっていたため、落ちても2回目で受かればノーダメージだなと思い、プレテスト気分で受験しました。

結果、7割強の点数でぎりぎり合格できました。
所感としては、書籍の過去問やUdemyの過去問よりも難しく感じました。
やはり問題文が独特で、問われていることがスッと頭に入ってきませんでした。
試験後に予定があったため、十分に解答時間が確保できなかったことも焦りに繋がりました。

#学習時間
結果的に学習時間は、書籍1.5ヶ月、過去問0.5ヶ月の合計2ヶ月ぐらいでした。

#まとめ
* 私は勉強とか試験とか本当に苦手なタイプな人間なのですが、2ヶ月程度勉強することで7割強の点数でなんとか合格できました。
* 最低限の学習教材は、書籍、過去問、公式資料。これらを一通りやっておけば6−7割はいけると思います。
* 自宅で受験できるピアソンVUEは、とても楽。このご時世だから有り難かったです。テクノロジーの力すごい。
Julia imagesで1枚の絵に別の絵を張り込む

# Julia Images

Julia ImagesはJuliaの画像操作ライブラリ。画像に線を引いたりする関数(draw!)をはあるのだけど、画像に画像を張り込む関数が見当たらない。

よく考えてみたら、実はImageの画像はRGB型(もしくはRGBA型)の2次元配列にすぎない。なので、普通にスライスで書いてやればいいのだった。
こんな関数を書いてやればいい。ピクセルのタイプが違うと破綻するので、本当はそのあたりをチェックしたり、バウンダリのチェックとかもしないといけない。

``` julia
function put!(target, src, p::Point)
    x = size(src)[1]
    y = size(src)[2]
    target[p.x:p.x+x - 1, p.y:p.y+y - 1] = src
    target
end
```

## ブランクイメージを作る

ブランクイメージは`zeros`で作れる。RGBAの透過属性ありでつくる。

``` julia
using Plots, Images, ImageDraw

blank = zeros(RGBA{N0f8}, (300, 300))
```

## 画像を読みこんで小さくする

30x30にする。

``` julia
img = load("pet_robot_dog.png")
img2 = imresize(img, (30,30))
```

## 適当な場所に張り込んでみる。

``` julia
for i in 1:30:300
    putImage!(blank, img2, Point(i,i))
end
blank
```
こんなかんじになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412142/96f65b48-b55e-5d2d-39c2-1199b8922177.png)
macのpowerpointにショートカットを登録する。

# やること
macのpowerpointにショートカット登録をする。

# 説明の前に
microsoftの公式のヘルプに追加で手順例を説明していきます。
microsoft の説明でうまいくいかなかったら本記事を読んでください。
基本上手くいかない時はショートカットキーが被っているのだと思います。

https://support.microsoft.com/ja-jp/office/office-for-mac-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0-%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88-%E3%82%AD%E3%83%BC%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B-6bbeb90e-96d9-4e03-b199-fc026ebdc321

# 登録方法例
## 数式を``^M``で登録する
テキスト選択時、controlキー(^)とmの同時押しで数式モードにする。

### 1. ヘルプで数式っぽいコマンド名を検索し、コマンドの正式名称を見る。

今回は「数式」らしい。

![スクリーンショット 2021-08-17 16.35.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548975/ab67fde0-c150-1aa4-1530-f3c8a96ff173.png)

### 2. システム環境設定 > キーボード　> ショートカット > アプリケーションを選択し以下のような画面にする。

![スクリーンショット 2021-08-17 16.37.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548975/4b4ef116-a694-5a42-fe9c-a9612a20bdd6.png)

### 3.中央左下のプラスボタンを押し、メニュータイトルに「数式」、キーボードショートカット欄で「control m」を同時押しする。そして追加
![スクリーンショット 2021-08-17 16.38.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548975/0d1247fb-9184-566e-6311-7742aee21469.png)

これで、テキストボックス選択時に^mを押すと数式モードとなる。

## 整列コマンドのショートカットを``^u``, ``^l``で登録する。
オブジェクトを複数選択して``^u``を押すと上揃え、``^l``を押すと左揃えになるようにする。

### 1. ヘルプで整列っぽいコマンド名を検索し、コマンドの正式名称を見る。
「上揃え」、「左揃え」というらしい。
![スクリーンショット 2021-08-17 16.44.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548975/20c1c856-a623-4662-2934-eeae33c8f4e0.png)
![スクリーンショット 2021-08-17 16.45.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548975/ef9f81a3-d54b-1a6b-728f-a34082b928e3.png)

###  2. システム環境設定 > キーボード　> ショートカット > アプリケーションを選択
![スクリーンショット 2021-08-17 16.47.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548975/70450104-2bcb-7db7-cae1-6c053c6bfeb9.png)

### 3.中央左下のプラスボタンを押し、メニュータイトルに「上揃え」、キーボードショートカット欄で「control u」を同時押しする。そして追加


![スクリーンショット 2021-08-17 16.48.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548975/33fe837b-fe25-644f-89d5-35e5851fdf57.png)

### 3.中央左下のプラスボタンを押し、メニュータイトルに「左揃え」、キーボードショートカット欄で「control l」を同時押しする。そして追加


![スクリーンショット 2021-08-17 16.47.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548975/79ccfe12-6e53-4d69-5005-dc3e088cbf44.png)
[Next.js] Incremental Static Regeneration 時の getStaticPaths で渡すパスについて

Next.js + Vercelの組み合わせで Incremental Static Regeneration（以後ISRとします) したら、なんか思ったとおりにいかなかったというお話。
完全にドキュメントを読んでいなかった自分の責任だけど、ハマったので他の人がはまらないように

# Next.jsのISRとは？
Next.jsのISRについては

https://vercel.com/docs/next.js/incremental-static-regeneration
https://zenn.dev/ria/articles/b709ae94e919c76f814a

によくまとまってます

# 結論
結論から先に書きます。
`getStaticPathｓ` を使って動的ルートを利用するページ（ `[id].tsx` みたいなページ）で `ISR` をする場合は、
オンデマンドでビルドしたいページのパスを `getStaticPathｓ` で返さないようにします。

```typescript
export const getStaticPaths: GetStaticPaths = async () => {
  return {
    paths: [],
    fallback: 'blocking',
  };
};

export const getStaticProps: GetStaticProps = async ({ params }: PathParams) => {
  const article = await getArticleById(params.id);
  return {
    props: {
      article
    },
    revalidate: 1,
  };
};
```

こんなかんじで、すべてのページをオンデマンドでビルドする場合は `paths:[]` みたいに空の配列を返します。
 
# ハマったこと
## ISRしているハズなのに全ページビルドされている！！

ISRの特徴だと、「ページはアクセス時にオンデマンドでビルドされるよ」って書いてあります。
それなら、5000件の記事があってもビルドはめっちゃ短くなる！ オーすげー

でどうやってやるかみてたら、 getStaticPropsで `revalidate: 1` って書くだけと。
なーるほどじゃ、

```typescript
export const getStaticPaths: GetStaticPaths = async () => {
  const ids = await getArticleIds();
  const params = ids.map(id => { return { params: {id} });

  return {
    paths: params, // 各記事のパスを渡したまま
    fallback: 'blocking',
  };
};

export const getStaticProps: GetStaticProps = async ({ params }: PathParams) => {
  const article = await getArticleById(params.id);
  return {
    props: {
      article
    },
    revalidate: 1, // 　←ここにrevalidateだけ追記
  };
};
```
こーですかね

記事はHeadlessCMSで管理していましたので、コンテンツ更新時にwebhookを設定して終わりです。

## どうなった
ビルド時に毎回5000件すべての記事がビルドされてました。えーー。話が違います。
コンテンツ更新して保存したときもwebhook経由で全件ビルドされるんで、、、これじゃSSGじゃん。
ってことで、とりあえず、webhookの設定をはずします。

すると、CMSでコンテンツ更新のときは当然ビルドは走らない。
コンテンツ更新後ビルドしなくても、2回目にアクセスしたときにページは更新されるてました。

これがISRかぁ〜と妙な納得をしていました。

# いや、違うぞ
ええ、完全な勘違いです。

## ISR でも getStaticPaths で渡されたパスに対しては SSG される
`getStaticProps` に `revalidate` を設定したとしても、 `getStaticPaths` で渡されたパスに対しては SSG されるので、ビルド時にページが生成されます。

冒頭でいったようにオンデマンドでビルドするページのパスを渡さないようにしましょう。

https://vercel.com/docs/next.js/incremental-static-regeneration
でも 「100,000件のプロダクトがあるような場合に、もっとも人気のある1000件分のプロダクトのパスをわたして、そこだけ事前にビルド。あとはオンデマンドでビルドする」みたいなケーススタディが書いてありました。
全然読んでませんでした（笑

# まとめ
ドキュメントはよく読みましょう。

https://github.com/lfades/static-tweet/blob/master/pages/%5Btweet%5D.js
こんなサンプルもあるので、それも読んどけば〜〜〜

っていうお話でした。