OmniAICreator/Qiita-1.07M huggingface dataset:
2023/1/25主にITとかセキュリティの記事

「Git」にアップデート、複数の深刻な脆弱性に対処
https://www.security-next.com/143027

2022年4Qの脆弱性届出 - ソフトとサイトいずれも減少
https://www.security-next.com/143031

「静岡銀行」装うフィッシング攻撃 - 取引目的の確認などと誘導
https://www.security-next.com/143055

「Drupal」のコアやモジュールに脆弱性 - 情報漏洩のおそれ
https://www.security-next.com/143023

マルウェア感染でなりすましメールが送信 - 不動産仲介会社
https://www.security-next.com/143042

『GTAオンライン』PC版でアカウント削除に繋がる脆弱性発見か？過去には『DARK SOULS』シリーズでも同様の事態(1/23)
https://news.yahoo.co.jp/articles/46f565cb02a39d63a8b484f447341c3554b47d4a?source=rss

ハードコードされた機密情報も漏洩するリスクがある、要注意(1/23)
https://news.mynavi.jp/techplus/article/20230123-2563967/

Riot Gamesがハッキング被害。ValorantやLoLなどコンテンツやパッチのリリースに影響(1/23)
https://news.yahoo.co.jp/articles/aad839d4852d0e39dbb193d70bc2f1fe2e4819ee?source=rss

2023年は家族の個人情報を守れ！　プライバシーはあなたがコントロールする時代へ(1/23)
https://ascii.jp/elem/000/004/120/4120560/

「Windows 10 Home/Pro」のダウンロード販売、1月31日に終了へ(1/23)
https://japan.cnet.com/article/35198934/

Apache HTTP Server 2.4に複数の脆弱性(1/23)
https://gunosy.com/articles/e5a2y

エージェント型のセキュリティがクラウドで通用しなくなり、コスト増でビジネスを阻害する理由(1/23)
https://atmarkit.itmedia.co.jp/ait/articles/2301/05/news001.html

コスモスDEX「Osmosis（OSMO）」、Neonでクロスチェーン取引が効率化(1/23)
https://www.neweconomy.jp/posts/290422

IoT製品のサイバー防衛、日本電産や楽天系が専門部署(1/23)
https://www.nikkei.com/article/DGXZQOUC07DFS0X01C22A2000000/

タカミヤがLockBitに感染、ベトナム拠点が不正アクセス受ける(1/23)
https://xtech.nikkei.com/atcl/nxt/news/18/14498/

職業としてのセキュリティ--日本企業のIT分業を覆した「黒船来航」(1/23)
https://japan.zdnet.com/article/35198663/

米Tモバイル、顧客情報が流出(1/21)
https://www.nikkei.com/article/DGKKZO67784440R20C23A1NNE000/

間違っていても自信たっぷりに書くAI執筆記事…広がる懸念(1/23)
https://www.epochtimes.jp/2023/01/133273.html

東京理科大学、従来より低コストで高速な秘密計算法を開発(1/23)
https://news.yahoo.co.jp/articles/5f062cf08c64a96729282dd7c1dbeabce14f2e4f?source=rss

メールの「Cc」や「Bcc」って何の略？「違いの分かる人」になれる電子メールの豆知識(1/23)
https://news.allabout.co.jp/articles/o/55781/

第十四回情報リテラシー論 セキュリティとクラウド化(1/23)
https://note.com/trophy0927/n/na6e5f2b2e67b

4月の「義務化」前に知っておきたい！ペナルティあり？どこがお得？プロが答える「マイナ保険証」の素朴な疑問(1/23)
https://news.infoseek.co.jp/article/taishu_106625/

加藤厚労相のメアド流出　　ツイッター、複数省庁も(1/23)
https://mf.jiho.jp/article/236652

パナソニックなど、自動車へのサイバー攻撃対応ソリューションの有効性を実証(1/23)
https://news.mynavi.jp/techplus/article/20230123-2572794/

ソフトウェア内製化推進の企業が過半数、業務時間外の「つながらない権利」への支持、ほか(1/23)
https://news.nicovideo.jp/watch/nw11995516

知人女性のファッション通販サイトのアカウントに不正アクセス　洋服など虚偽注文して送りつけた疑い　４２歳の男逮捕　《新潟》(1/23)
https://news.yahoo.co.jp/articles/d0717f91aa9211c0266ccfdd1f26f3f2adcb08e1?source=rss
https://news.yahoo.co.jp/articles/5268b74e41a2f436fb605efd4641c4ac19c51978?source=rss

SUBARUのディーラーがシステム障害で発注できない状態に、直前の改修が影響か(1/24)
https://xtech.nikkei.com/atcl/nxt/column/18/00598/070100199/
Jupyter Notebookのテーマを変えるコマンド備忘

デフォルトだとフォントサイズが小さかったので大きくしたかった。

jupyterthemes でテーマを変える。

https://github.com/dunovank/jupyter-themes

## jupyterthemes のインストール
```
$ pip install jupyterthemes
```

## jupyter notebookを開いて以下を実行
```
!jt -t grade3 -kl -fs 15 -f inconsolata -ofs 12 -tfs 12 -nfs 10 -mathfs 120 -lineh 200 -cellw 90%
```
いろいろオプションがある。
細かい微修正をするのに以前流したコマンドがわからず、メモを残すの大事だと気づいたのでいま書いている。

テーマをデフォルトにリセットするには以下を流す
```
!jt -r
```

## before
![スクリーンショット 2023-01-25 3.08.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914/afe72b7a-af47-b6b9-acf3-c7fc640f70e5.png)

## after
![スクリーンショット 2023-01-25 3.08.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914/b597aba4-d38b-1178-d934-7354a9cf8d8a.png)
コメントを書け！ VS. コメントを書くな！を発端に色々と悟った話

# はじめに

発言は個人の責任であり、所属する組織の見解を代表するものではありません。
とは言え実話でありタイトルの通りの議論になって結果的に色々と悟ったのでつらつら書いてみます。

# 登場人物

私・・・ 役割：エンジニア兼プロダクトマネージャ
Aさん・・・ 役割：エンジニア

エンジニアはインフラ・ミドルウェア・バックエンド・フロントエンド全ての領域を担当。

# 発端

Aさん「Pull Requestを送りました。レビューよろしくお願いします」
私「見ました。コードの根拠（なぜそうしたか）が分かるコメントがあるといいな、と思います」
Aさん「そんなの必要ですかね？なぜそうしたかよりも、どう動くかが大事であり、それはコードを読めば分かりますよね」

私「（う～ん、そうなのかな・・・）」

# 発展（その後）

私「例えば半年後に そのコードがなぜそうなっているか分かった方が後々 楽だと思います」
Aさん「**コードを見れば連鎖的に思い出せる**はずです。そのために今もこうして双方でやりとりしていますよね？」

私「それはそうですね、とは言えどこか（例えばドキュメント等）に記載しておいてほしいですね。私はAさんのように記憶できないですし、自分が誤った記憶を作り出す場合があると認識しておりそれを危惧しています」
Aさん「先程も言いましたが、**コードの根拠やどう設計したかよりも実際の動作が正**です。それに自分の業務知識くらい正確に記憶してください」

私「私たちはドメイン駆動設計等を通して設計の大切さについて学んだはずです。それらの**思考の過程はどこかに残すべき**ではないですか。また私は自身の記憶を信用していないので記憶に頼る進め方はしないポリシーです」
Aさん「残すべきと考えるのであれば、またあなた自身がそのポリシーを持っているのであれば、あなたがドキュメントやコメントに残せば良いでしょう。実際 今までもそうしていたでしょう？そもそも私達2人のプロダクトなのだから私達だけが記憶していれば済む話です。わたしはコードから当時の考えを呼び起こすことができますから」

私「コードは設計（ドメイン知識や設計の微妙なニュアンス等）を正確に反映できないと考えています（設計書からコードを自動生成でもしない限り）」
Aさん「何度も言いますが、正しいのは実際に動くコードです。設計と食い違いがあっても実際の動作が正です。そもそもドメイン設計をやった後でコードに落とし込みテストまでやっているので食い違いは無いと思います」
私「（本当にそうだろうか）・・・」

私「しかし、一部はコードが先行し設計がドキュメントとして残っていないケースがあります」
私「今は2人ですが、ゆくゆくはスケール（開発者を含むステークホルダーを増や）したいと思っています。そのためにもステークホルダーが読み取れる形で情報を残したいのです」
Aさん「本当にスケールするんでしょうか。私は1年ほどでこのプロダクトはEOLを迎えると想定しています。だからそのようなステークホルダーは存在し得ないのです。**存在しないステークホルダーのために無駄な作業はしたくありません**」

私「なぜそう思う（スケールしないと思う）のですか」
Aさん「この半年間2人から増えていないからです。何度か人数を増やして欲しいと言ったはずです」
私「私はまだ増やすべきでないと考えています。まだユーザもいないですし、それに人を集めるならこのプロダクトに共感してくれる人に参画してほしいと思っています。**ただ人員を募集するやり方は見た目上のスケールにしかならないと考えています**。まずは自分たちでMVP(Minimum Viable Product)を作るべきです」

Aさん「では（早くMVPを完成できるように）あなたは**もっとコミット・PRをしてください**。ほとんどわたしのコミットとPRしかないじゃないですか！」
私「そうですね...Aさんよりもコミット数・PR数が少ないのは事実です。言い訳として、私は将来のためのコメントやドキュメントを残したり、プロダクトの方向性を決めるためのユーザインタビュー等も計画しており、同様の時間を開発に割り当てることができないのです。もちろんコミットやPRをしようとは思っています。しかし私はAさんよりも素早くコーディングできないのです・・・」

Aさん「では時間を作ってください。業務時間以外も割り当てれば時間が増えますよ」
私「・・・そうですね...」

# まとめ：会話を通して思ったこと

* 社会人になってからAさんと10年弱色々やってきたが、何も理解できてなかった
* アジャイル、クリーンアーキテクチャ、DDD（ドメイン駆動設計）等をともに学習したが、それでも認識の齟齬は発生すると理解した
* 自分ができていないと言えば、それまでな話
* 双方で上記のようなやりとりでストレスを溜めてしまうのは良くないので、もしこのままなら最終的には自分が去るべきだろうな（Aさんは自分よりも優秀なので）
* とは言え可能な限りやってみよう
MobileNet v3を用いた類似画像検索

# はじめに
この記事ではMobileNet v3を用いた類似画像検索について記載します。

# 問題設定
クエリ画像と分類対象画像集合が与えられたときに、画像集合を類似画像と非類似画像の２種類に分類します。

# 手法
* MobileNetを用いて画像の特徴量を計算
    * Tensor hubで公開されている学習済みモデルを使用。出力1024次元の特徴量。
    * https://tfhub.dev/google/imagenet/mobilenet_v3_small_100_224/feature_vector/5
* 特徴量に重みをかける
* 特徴空間上のユークリッド距離で画像間の距離を計算し、距離が閾値以上の画像を類似画像と判断

# 評価方法
* [SUN Database](https://vision.princeton.edu/projects/2010/SUN/)（シーン画像分類のベンチマーク）の部分データセットを使用（２０クラス、各クラス１００画像をランダムに選択）
* ある画像をクエリ画像として選択したときに、同じクラスの画像を類似画像、他のクラスの画像を非類似画像と分類する分類問題と考え、ROC AUCの値で評価
* これを、クエリ画像を様々に変えたときの平均値を求める

# 評価結果
特徴量の重みの計算方法について、何パターンか試してみました。

## 重み一定の場合
```python
def calc_score(f1, f2):
    ```
        クエリ画像の特徴量f1と比較画像の特徴量f2の類似度スコアを、特徴量のユークリッド距離で計算
    ```
    dist = np.linalg.norm(((f1 - f2)))
    return 1 / (dist + 0.000001)
```
MobileNetが出力する特徴量をそのまま使用した場合は下記結果になりました。
これは、各クラスの画像１枚をクエリ画像としたときのROC AUCの分布です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119450/2d1488ce-5d25-b875-66a0-1d87616ca41b.png)

全体の平均値は**0.847**です。
クエリ画像の選択によっては0.5付近のあまり良くない結果になるものもありますが、全体的にそれなりの結果になっているのではないかと思います。

最も悪い結果（ROC AUCが0.5に最も近い場合）のクエリ画像と、そのときに類似画像と誤って判断した画像は下の組み合わせです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119450/6ac6e916-8400-d635-890d-48cc9c762ce3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119450/c526e09b-8ef2-3fb4-d141-ebf8ba5b15a9.png)

officeクラスの画像をクエリ画像にしたときに、wet_barクラス他の画像を類似画像として判定しています。
（見た感じ類似画像といっても良い気もします）

## 特徴量の標準偏差で重み付け
```python
def calc_score(f1, f2):
    ```
        特徴量を標準偏差で重み付け（特徴量ごとの標準偏差features_stdは事前に計算）
    ```
    dist = np.linalg.norm(((f1 - f2) / features_std))
    #dist = np.linalg.norm(((f1 - f2) ))
    return 1 / (dist + 0.000001)
```
画像集合全体の標準偏差で特徴量を重み付けした結果です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119450/6477d2ba-8c79-ea38-038e-3637b744a756.png)

全体の平均値は**0.834**で、重み付けなしよりもやや悪い（誤差の範囲？）結果となりました。
偏差が小さい特徴量ほど重要視すべきという仮説でしたが、あたっていなかったようです。
全画像集合の分布を見たのが良くなかったのかもしれません。
クエリ画像の類似画像の集合の偏差を使えば良くなるのかもしれませんが、類似画像集合はわからないので実現不可能です。

## クエリ画像の特徴量の大きさで重み付け
```python
def calc_score(f1, f2):
    ```
        クエリ画像の特徴量f1の大きさで重み付け
    ```
    weight = np.maximum(f1, 0.5)
    dist = np.linalg.norm(((f1 - f2) * weight))
    return 1 / (dist + 0.000001)
```
クエリ画像の特徴量の大きさで重み付けした結果です。
（値の大きい特徴量ほど、その画像にとって重要な特徴量だという仮説）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119450/433dc8ba-add9-bd75-6522-c971416ea9dd.png)

全体の平均値は**0.897**となりました。
重みなしの結果に比べて5ポイントほど上昇しています。
また、waveやwindmillなど、重みなしでは分類困難だったクラスのスコアが大きく向上しています。
少なくとも今回使用したデータでは、値の大きい特徴量ほど重要だという仮説があたっていたということではないかと思います。

# まとめ
* MobileNetを用いた特徴量を用いることで、それなりに類似画像の判断が可能
* 特徴量の重み付けで精度向上の可能性あり
* 特徴量の値が大きい特徴ほど重要

# 補足
この記事で紹介した方法は、AndroidTV用フォトフレームアプリ開発時に検討したものです。アプリのソースコードは下記で公開しています。

https://github.com/satohk/fjphoto/

* Google photoの写真、動画を閲覧、スライドショーにするAndroidTVアプリ
* 類似画像検索機能を実装

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119450/949419d0-01d1-0da9-7f97-13e865398c99.png)

また、このアプリは[富士もくもく会](https://fujimokumokukai.connpass.com/)の活動の一環で開発したものです。
ご興味のある方はぜひご参加ください。
Rubyのversion変更ができない時

## はじめに
- 今日から転職活動をしながら毎日（できれば）学習している記事の備忘録や、情報発信として投稿していきたいと思います。
 よかったら見ていってくださいね！！

## Rubyのversionが変更できなかった！

### Rubyのインストール可能なversionを調べる
```
rbenv install -l
```
- まずインストールの-l オプションを使用してインストール可能なRubyのバージョンを調べます。

### Rubyをインストールする
今回はRubyの2.7.0をインストールします。

```
rbenv install 2.7.0
```
数分待っているとここでエラーが！

```
BUILD FAILED (macOS 12.6 using ruby-build 20220630)
Inspect or clean up the working tree at 
/var/folders/h5/8fx53bl54993kvjncc96zwsm0000gn/T/ruby-build.20230125010939.78815.SWRN63
Results logged to /var/folders/h5/8fx53bl54993kvjncc96zwsm0000gn/T/ruby-build.20230125010939.78815.log
```

### 解決法
どのように解決したかと言いますと、rbenvの前に`RUBY_CFLAGS="-w"`を足すだけでした！

```
RUBY_CFLAGS="-w" rbenv install 2.7.0
```
これでインストールできました！
M1チップ搭載のMacbookでは環境変数の設定を事前に行わなければならないといけないため、
今回は`RUBY_CFLAGS="-w"`がこれに当たるということでした。

## まとめ
初投稿をやってみて、Markdownの投稿方式や他の方の投稿の仕方を参考にさせていただきながら、作成してみました。
もし、間違っている部分があったら教えていただきたいです！
ありがとうございました！！
Pythonのゲームライブラリ Python Arcade Libraryの紹介

# Python Arcade Libraryの概要

Python Arcade LibraryはPythonで2Dゲームを作るためのライブラリである．
有名なライブラリだと，[pygame](https://github.com/pygame/pygame)がある．ただ，Windowsの環境でpipを使ったインストールをしようとすると，*raise DistutilsPlatformError("Unable to find vcvarsall.bat")* というエラーを吐いてしまう．このエラーの解決方法が気に入らない人はPython Arcade Libraryを使うと良いだろう．
Python Arcade Libraryは[pyglet](https://pyglet.readthedocs.io/en/latest/)というOpenGLを使ったライブラリをゲームで使いやすくするために，[pymunk](https://pyglet.readthedocs.io/en/latest/)や[Tiled](https://pyglet.readthedocs.io/en/latest/)などを上手く組み合わせたものとなっている．物体の当たり判定やマップの読み込みを用意してくれているので，2Dゲームを作りたい人は試してみる価値はあるだろう．

# Python Arcade Libraryのチュートリアル

Python Arcade Libraryのチュートリアルは[Simple Platformer](https://api.arcade.academy/en/latest/examples/platform_tutorial/index.html)を読むと良い．
Python Arcade Libraryのチュートリアルは英語のみしかないが，難しい単語や文法はでてこない．英語の勉強にもなると思って頑張って読んでみよう．もちろん，deeplなどを使っても良い．
Step1から11までは，解説がついているので，ゲームを作ったことがない人にとってやさしくなっているが，Step12から解説がなくなっている．ソースコードの写経だけでなく，どの変数はどんな処理をさせるために必要なのか，といったことを考えながら読む必要がでてくる．

# Python Arcade Libraryのサンプルコード

Python Arcade Libraryの公式ページに[How-To Exsample Code](https://api.arcade.academy/en/latest/examples/index.html)がある．チュートリアルだけでは消化しきれなかったことや，作ってみたいゲームの実装方法がわからなくなったときは少し探してみると良いと思う．
SpritesやCamera Use，View Managementを見てみると，チュートリアルでは消化しきれなかったPython Arcade Libraryの使い方を学べるだろう．

# Python Arcade Libraryで作られたゲーム

[Games Made With Arcade](https://api.arcade.academy/en/latest/sample_games.html)にまとめられている．githubからダウンロードして遊べるようになっている．ゲームの実装方法が気になった人は他人のコードを読んで，勉強してみるのも一つの手かもしれない．
rails 学習備忘録その2 ~道場レッスンIIまで~

# はじめに
マジでただのメモ 読んでもらうために書いてないので悪しからず...
第一回↓
https://qiita.com/menma_at_here/items/fe207f4a4241c11d504e

# 内容
progate の rails入門を進めていく
4章~5章まで


## rails IV

### 編集
- updateとかcreateするときは、ルーティングを `get` ではなく `post` にする必要がある
    - `post "posts/:id/update" => "@posts#update"` みたいな感じでupdateアクションに飛ばして、その中で `redirect_to("~~")` をする、みたいな流れ
- form を使うときは、以下みたいな感じで `form_tag` を使う
```erb
<%= form_tag("/posts/#{@post.id}/update") do %>
  <div class="form">
    <div class="form-body">
      <!-- <textarea>タグのname属性をcontentに指定してください -->
      <textarea name="content"><%= @post.content %></textarea>
      <input type="submit" value="保存">
    </div>
  </div>
<% end %>
```
このとき、div に指定した属性 (上のコードであれば `name`) に入っている値がハッシュ値として格納され、controller の中で `params[:content]` みたいな感じで取り出せるようになる
- `post`と`get` は以下の使い分けらしい
    - `get`: データベースを変更しないアクション
    - `post`: データベースを変更するアクション
    - (GETとPOSTメソッドに対応している、って認識でいいのか...？)

### 削除
- `link_to`で`post`メソッドを使いたいときは、`<%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %>`とする

## rails V

### バリデーション
- バリデーションは **models/~~.rb** に付け加える
```rb
  validates :content, {presence: true, length:{maximum: true}}
  #validates 検証するカラム名, {validationの内容}
```
- saveメソッドは
    - バリデーションに成功 → true を返す
    - バリデーションに失敗 → false を返す (ロールバックが起きる)
- `render("posts/edit")` でposts/edit.html.erb に直接飛ばせる
    - この`posts/edit`はviewファイル
- バリデーションに失敗すると、`@post.errors.full_messages` の中にエラー内容が自動的に入る (なんだこの微妙に便利な機能...)

### flash
- `flash[:notice]` に文字列を代入すると、「成功しました」みたいなメッセージを一時的に出す「フラッシュ」を出すことが出来る
- 共通で使うので、`application.html.erb` で編集すると良い
HarperDBを使ってみた

# はじめに
Twitterのタイムラインで「今年勉強した方が良い技術スタック」の中の1つで紹介されていた。
なのでどんなものなのか試そうと思う。

# 他のデータベースとの比較 
https://harperdb.io/product/
- HarperDBはMongoDB(ドキュメント指向DB)よりも**37.9倍**速い
- HarperDBはInfluxDB(時系列DB)より**6.8倍**速い
- HarperDBはSQLiteより**581**%速い
- SQLもNoSQLもCSVもいける

# インスタンスの作成
- AWS
  - US East(Ohiom or N.Virginia)、US West(N.California or Oregon)選択可能
- Verizon Wavelength
  - アメリカ国内19拠点選択可能だが、先に進むとクレジットカード登録が必要
 
# ユーザー作成インスタンスへの接続
インスタンス情報の作成＋ホスト名、ポート、SSLの有無の情報を入力

https://harperdb.io/docs/install-harperdb/
- Linux
- Docker
- Mac
- Windows(WSL2)
- Offline

# 使用感
- テーブル作成時にハッシュ名(プライマリーキー)を設定するだけ。
- テーブル作成後、CSVをアップロードするとインポートできる。
- 日本語のデータもOK。
- カラムの追加も容易に可能で、カラム追加前のデータにはNullが入る。

外部からのデータ操作も簡単。
SELECTが圧倒的に速いので、色々と使えそう。

![Harper.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083101/7341954a-4422-94bf-210b-6f9673820381.png)

# 説明動画
https://www.youtube.com/watch?v=fAKZxK-XamM&ab_channel=HarperDB
$250ドルのクーポンがついてました。

# 不明点
- joinは可能だがjoinの種類？
- 1テーブル容量の限度？
LuaSnipでコーディングを高速化

## LuaSnipとは

LuaSnipは，vimで使用するスニペットを管理するためのプラグインです．
開発者が常用するコードのフレーズを保存し、簡単に呼び出すことができるようにすることで、開発効率を向上させることができます。

https://github.com/L3MON4D3/LuaSnip

## 使用例
私がスニペットの導入を行なったのは，競技プログラミングのコンテストに参加する際に常用するコードを保存しておき，コーディング時間を可能な限り減らすことで，思考する時間を増やすことを目的としていました．

例えば，これまで私は以下のコードを問題ごとに毎回打ち込んでいました．

```cpp
#include <bits/stdc++.h>
using nameplace std;
```

これを，"std"と打ち込むことで呼び出されるように設定しておけば，一瞬で記述することが可能になります．

## インストール

コードのみを見たい場合は，以下のリポジトリを参照してください．

https://github.com/fightingsou/dotfiles

LuaSnipとcmp_luasnipをインストールします．
私はPackerを使って，プラグインの管理を行なっているため，以下のように記述しました．

```lua
-- LuaSnip
use({ 'L3MON4D3/LuaSnip' })

-- cmpでLuaSnipを使うためのプラグイン
use({ 'saadparwaiz1/cmp_luasnip' })

```

## 設定

補完ソースにLuaSnipで設定したスニペットを追加し，<Ctrl+k>でLuaSnipのジャンプ機能を使えるようにnvim-cmpの設定ファイルに記述します．

```lua
local cmp = require('cmp')
local luasnip = require('luasnip')

cmp.setup({
  snippet = {
    expand = function(args)
      luasnip.lsp_expand(args.body)
    end,
  },
  mapping = cmp.mapping.preset.insert({
            :
           省略
            :
    -- Keymapを設定
    ['<C-k>'] = cmp.mapping(function(fallback)
      if luasnip.expand_or_jumpable() then
        luasnip.expand_or_jump()
      else
        fallback()
      end
    end, { 'i', 's' })
  }),
  sources = {
    { name = 'nvim_lsp' },
    -- LuaSnipを追加
    { name = 'luasnip' },
    { name = 'buffer' },
  },
})

vim.cmd [[
  set completeopt=menuone,noinsert,noselect
  highlight! default link CmpItemKind CmpItemMenuDefault
]]

```

そして，LuaSnipの設定ファイルを作り，使いたいスニペットを書いていきます．
今回はC++用のスニペットを記述していますが，”cpp”の部分を"all"に変えれば，全てのファイルに適用されるスニペットに，"py"に変えれば，Pythonファイル用のスニペットを記述できます．

```lua
local ls = require('luasnip')
local snip = ls.snippet
local text = ls.text_node
local insert = ls.insert_node

ls.add_snippets(nil, {
  cpp = {
    snip({
      trig = 'std',
      }, {
      text({'#include <bits/stdc++.h>', 'using namespace std;', ''}),
      insert(0),
    }),
  },
})
```
cppファイルでを開き，"std"と打ち込むことで，設定したスニペットが表示されているはずです．
[Next.js]middlewareでリダイレクトさせた際エラーになる

環境
Next13

# 問題
認証機能を実装した際、認証がまだのユーザーはmiddleware.tsでログインページにリダイレクトさせるみたいな処理を書いた時に遭遇したエラー
```ts:middleware.ts

  if (!session && !req.nextUrl.pathname.startsWith('/login')) {
    const redirectUrl = req.nextUrl.clone()
    redirectUrl.pathname = '/login'
    return NextResponse.redirect(redirectUrl)
  }

  return res
```

```bash:error内容
✖︎_next/static/chunks/webpack.js:1 Uncaught SyntaxError: Unexpected token '<'

✖︎main-app.js:1 Uncaught SyntaxError: Unexpected token '<'
```

なんかうまくコンパイルできてない？

# 解決
middleware.tsでconfigをexportしてください。
```ts:middleware.ts
// ...
// 追加
export const config = {
  matcher: [
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
}
```

正規表現は[公式](https://nextjs.org/docs/advanced-features/middleware)から取ってきました。
これは「次のパスから来たアクセスはmiddlewareを通さない」という意味ですが、nextが何らかのリクエストを/next/*で行なっているのでその邪魔をしないようにするということみたいです。そんなん知らん。
```    
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
```


# 参考
https://stackoverflow.com/questions/73229148/uncaught-syntaxerror-expected-expression-got-while-using-next-js-middlewar
最近読んだ記事で、参考になったと感じるもの📗

# この記事を書こうと思ったきっかけ
未経験からフロントエンドエンジニアになるべく勉強を初めて、早2ヶ月。Qiita初めての投稿で、これまでのインプットを一度アウトプットしてみようと思います。

# 参考にさせていただいた記事　-３選-

https://zenn.dev/praha/articles/prepare-book#%E6%9C%AC%E3%81%AE%E4%BA%88%E7%BF%92%E3%81%A8%E5%BE%A9%E7%BF%92

分からないことが分からない時の対処法
理解できていることとできていないこと、それぞれはっきりさせること。
特に新しいことを学ぶことしかない初学者の私にとって、学習の指標になっています。

***

https://qiita.com/Yametaro/items/f9e449b9335051acebf3

このような記事の書き方もあるよ、という感じ
この記事見ていると、アウトプットはやはり自身が楽しくないと続かないなと思う。
楽しくなるような書き方を模索していきます

***

https://qiita.com/degudegu2510/items/a8085951e3322eec9ce8

ポケモン懐かしすぎた。
自分もこれから技術を身につけ、こんなWebサイト作ってみたい



# 最後に
楽しく投稿できるような内容を考えていきます。
あと普通に学習していて躓いた内容とかも残していきたい。
アウトプットすることが大事！！！ですが、アップデートも大事
機械学習コンペで初めて金メダルを獲った話

皆さんおはこんばんにちは。
[AcademiX](https://www.academix.jp/)というAIコミュニティに所属しているほきと申します。
今回Nishikaのコンペにチームで参加し、結果として**8位になり金メダル:military_medal:を獲得**できました！
参加してみてよかったことうまくいかなかったことなどを書いておくのでこれから参加する方の参考になれば幸いです。

:::note warn
自己紹介にもありますがコンペに2回しか参加したことのないひよっこが書いている記事という点をご理解いただきたいと思います。つよつよの方アドバイス等ありましたら是非コメント欄にお願いします！
:::
![スクリーンショット 2023-01-24 22.29.17（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2736924/cb938347-db90-3acb-33e9-9f51c98ca6a3.png)

# 自己紹介
- 理系国立大学学部3年生
- 生体信号情報学の研究室に所属 ~~といっても配属されたばっかなので何もしてない~~
- コンペへの参加は2回目
  - 1回目は [Kaggleのfb3](https://www.kaggle.com/competitions/feedback-prize-english-language-learning/overview) で結果は上位51%（適当なノートをフォークして出しただけ）
  - SIGNATEのBeginner限定コンペで7位になったことはあるけどあれは練習用なのでノーカウント
# コンペ概要
- プラットフォーム : Nishika
- コンペティション名 : 睡眠段階の判定 〜”睡眠の深さを判別しよう”〜
- 利用データ : Sleep-EDF Database Expanded
- 評価指標 : Accuracy
- リンク : https://www.nishika.com/competitions/sleep/summary
# コンペの流れ
1. 参加登録＆データをダウンロード
2. チュートリアルの実行
3. EDA
4. baselineの作成
5. チームマージ
6. ディスカッションをしながらモデルのブラッシュアップ
7. モデルが出揃ったらアンサンブル
8. 最終サブミッションを決定

# うまくいったこと
今回のソリューションはチームメンバーがまとめてくれたものがあるので[こちら](https://www.nishika.com/competitions/sleep/topics/445)をご覧ください。

- こまめにお互いの進捗を確認しながらの進行
  - 基本的には**Slack**を使ってやり取りをし、沼った時や重要な決定をするときは**oVice**を使ってミーティングをした
  - **Notion**をつかって手法やスコアの管理をした（カラムはCV、LB、ベースモデルなど）
  - 忙しい人はアイデア出し→余力のある人が実装など**役割分担**できていたのもよかった
- 多様なモデルの作成
  - 5人いたので様々なモデルを作る事ができた→アンサンブルで活きた
  - 1人では思いつかないものも多くあったのでチームのメリットをうまく享受できた
- アンサンブルの活用
  - seed averagingと複数のモデルとのアンサンブルを試した
  - 最終スコアがよかったのはアンサンブルしたものだったので重要性を改めて実感
- 最終サブミッションの適切な選択
  - CVとLBの乖離や安心度など様々な項目からベストな選択をする事ができた
# うまくいかなかったこと
- 論文のリサーチ
  - **SOTA論文**のモデルを使わなかった
  - 今回は上位がこぞって同じ論文を使っていたのでもっとリサーチすべきだった
- モデルの管理
  - pyファイルでやっている人とipynbを使っている人が混在しており**他の人のコードが実行しづらかった**
  - ソースコードを個人のGoogleDriveやGitHubで管理をしており**どこに何があるかわからなかった**
  - 人が読むことを考慮せずに書いたのでお互いコードの理解に時間がかかった
- コーディング力の不足
  - コーディングができず論文からの実装を諦めたモデルがあった
  - バグを出さずコーディングできたらもっと色々なことを試せた
- 適切な睡眠
  - 深夜にコーディング→朝に結果確認を繰り返しており、**睡眠コンペにも関わらず睡眠が犠牲になった()**
# まとめ
暫定4位からshake downしたり専門分野なのに入賞できなかったりと悔しい思いもありますが、**コンペはとても楽しかったです！**
最初はチームでの参加はタスクが分散できていいなくらいにしか思っていませんでした。
しかし、実際参加してみると色々な考え方を知る事ができてとても勉強になりました。
**「自分の無知さに気づいてもっと勉強して強くならなければ」と思えたのでチームで参加してよかったと思います。**

今回のチームメンバーは最初に紹介した**AcademiX**のメンバーです。
**AcademiX**ではコンペへの参加はもちろん、**勉強会や企業実践**にも取り組んでいます。
興味のある方はぜひ参加してみてください！

また、コンペに出たり機械学習を勉強してみたいけど何から勉強したらいいかわからない方には、自分の記事で恐縮ですがこちらの記事が参考になると思います。

https://qiita.com/hokkey621/items/404e04d6057b98128971

今後もコンペには参加していこうと思います。
当面の目標は**KaggleでExpert**になる事です。
最後になりますが、チームを組んでくれた皆さんありがとうございました！！
アダプティブカードのチェックボックス×SharePointリストのBoolean値を扱う

# 概要
タイトルが長くなってしまいましたが、
PowerAutomateにてSharePointリストのBoolean値を取得する際の話になります。

具体的にはBoolean値がFalseだと出力されないという仕様なようなので、
その際にどのように乗り越えた備忘録になります。

## 今回の問題
PowerAutomateにて、SharePointリストから取得したBoolean値をアダプティブカードに挿入しようとしたらエラーになりました。

### SharePointリストから取得したデータを確認したら・・・
リスト設定が種類が「チェックボックス」の場合、
- Trueだと取得可能
- Falseだと出力されない
という結果になりました。

インプット
![202301250035.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130969/b921051e-4431-24c0-1b45-d7beb733bec4.png)

アウトプット（Flaseの場合の結果・エラー）
→ 「データが格納されてないよ」ということみたいですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130969/a3a38c1a-168f-ffeb-016a-b5c681fd873e.png)

# 解決方法
今回はエラー処理をして切り抜けました。
具体的には、
**SharePointリストを取得
→ リストの結果を変数に格納
→「リストの結果を変数に格納」がエラーであれば「False」を格納**

## 実際の設定
下記のように変数を設定・格納しました。
※あらかじめ変数を定義・初期化しておいてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130969/1fa7283a-ffff-40bc-de75-08253a67ac4c.png)

【重要】
特に「変数の設定 4」の実行構成から実行タイミングを前の処理に**失敗したら実行する**ようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130969/e7bc7053-18d6-4de7-fa67-5b4ec958f92c.png)

## これにより
問題なく実行された場合：変数に「**True**」が格納
エラーの場合：変数に「**Flase**」が格納
されるようになります。

# 最後に
今後もハマった箇所については、なるべく備忘録として残していく予定です。
また、間違っていた場合などはコメントください。
メールアドレスの正規表現を作成する

# メールアドレスのルール
メールアドレスに使用できる文字や文字数
* 半角英小文字、数字、「－」（ハイフン）、「．」（ドット）、「＿」（アンダーバー）のみ
* 文字数は、3文字以上30文字以内
* ひとつ目の文字は、アルファベットまたは数字のみ

### 出典
https://www.softbank.jp/support/faq/view/10544
### 気づき
これを参考にする。

# 一つ目の文字は、アルファベットまたは数字のみ
最初を表す文字があったようなので探す。

### ```^```
文字列の先頭がマッチ

#### 出典
https://qiita.com/str32/items/a692073af32757618042#:~:text=%5E-,%E6%96%87%E5%AD%97%E5%88%97%E3%81%AE%E5%85%88%E9%A0%AD%E3%81%8C%E3%83%9E%E3%83%83%E3%83%81,-%5ESEIKI

### rubyでは```/A```を使う
Rubyの正規表現でよくある落とし穴は、より安全な\Aや\zがあることを知らずに危険な^や$を使ってしまうことです。
#### 出典
https://qiita.com/masatom86650860/items/9ff7539bcf7de52bb14c

```
\A[a-zA-Z1-9]
```
### 気づき
これで一文字目が英語の小文字、大文字、数字にすることができた。

# 一文字目を指定した後に「－」（ハイフン）、「．」（ドット）、「＿」（アンダーバー）を含んだ文字列を表現する
### ```{n}```
直前の文字をn回繰り返したものにマッチ
#### 出典
https://qiita.com/str32/items/a692073af32757618042#:~:text=%7Bn%7D,%E3%82%82%E3%81%AE%E3%81%AB%E3%83%9E%E3%83%83%E3%83%81

```
\A[a-zA-Z1-9]+[a-zA-Z1-9\._-]{5}
```

# eメールみたいな正規表現を行った。
```
\A[a-zA-Z1-9]+[a-zA-Z1-9\._-]{5}+@+[a-zA-Z1-9\._-]{5}+\.+[a-zA-Z]{5}+\z
```
```abc@i.softbank.jp```を擦り合わせてみると
```\A[a-zA-Z1-9]+[a-zA-Z1-9\._-]{5}```は```abc```
```@+[a-zA-Z1-9\._-]{5}```は```@i.softbank```
```\.+[a-zA-Z]{5}+\z```は```.jp```
に対応させた。

# eメールの正規表現の紹介がされていたものを見る。
```
[\w\-\._]+@[\w\-\._]+\.[A-Za-z]+
```
### 出典
https://qiita.com/str32/items/a692073af32757618042#%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E3%81%A8%E3%81%AF:~:text=z%5D%2B%0A%E4%BF%AE%E6%AD%A3%E5%BE%8C%E2%91%A1%EF%BC%9A-,%5B%5Cw%5C%2D%5C._%5D%2B%40%5B%5Cw%5C%2D%5C._%5D%2B%5C.%5BA%2DZa%2Dz%5D%2B,-URL%E3%81%AE%E6%AD%A3%E8%A6%8F

### 気づき
自分のものと全然違う
また長さの制限なども書かれていなかった。
そんな気にしなくてもいいのかな。

ドキュメントを読みながらできるだけ近づけていく。

# 正規表現を省略していく。
https://qiita.com/masatom86650860/items/4b892f821fefabc55f4c

https://qiita.com/masatom86650860/items/57be76434ab40620f70d

### 気づき
トップレベルドメインの正規表現の```[a-zA-Z]```は紹介されていた正規表現を真似しました。
一応調べましたが、数字が入っていないようなので入れませんでした。(国名がほとんどなので)

#### 関連記事
https://www.nic.ad.jp/ja/dom/system.html

# 編集する
日本語の正規表現
```
ぁ-んァ-ン一-龥
```
日本語を含めた正規表現
```
\A[\wぁ-んァ-ン一-龥\.\*\+\/\?\{\|\}~!#$%&'-=^_`]+@[\wぁ-んァ-ン一-龥\-\.]+\.[a-zA-Z]+\z
```
### 出典
https://qiita.com/masatom86650860/items/41cbeb755c0d7ed8092d

https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9#:~:text=%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%AB%E4%BD%BF%E7%94%A8%E3%81%A7%E3%81%8D%E3%82%8B%E6%96%87%E5%AD%97%5B,%E2%80%9D%E3%81%A7%E3%81%A4%E3%81%AA%E3%81%84%E3%81%A0%E5%BD%A2%E5%BC%8F

# 感想
僕も参考のものに少し近づいた気がします。
あっているかどうか別として正規表現の勉強ができてよかった。
勉強する前は正規表現がどのような内容が書かれているかは理解できなかったけど、
今は少し理解できるようになったと思っている。
またプログラミング言語で正規表現が違うことを知れたのはよかった。
正規表現もまだ深そうだ。
Python で Amazon S3 の MultiPartUpload を扱う

Amazon S3 に巨大ファイルを置きたいときに MultiPartUpload を使いたくなることが多々あるが、Python + boto3 からそのまま扱おうとするとややこしいので自分が使いやすいようなクラスを実装した。

## 実装
``` python
class AmazonS3MultipartUploader:
    """Amazon S3 に巨大なオブジェクトに少しずつ書き込んでいくためのクラス"""

    def __init__(self, s3, *, part_size_threshold: int = 5 * 1024 * 1024, **kwargs):
        self.s3 = s3
        self.mpu = self.s3.create_multipart_upload(**kwargs)
        self.kwargs = {
            "Bucket": self.mpu["Bucket"],
            "Key": self.mpu["Key"],
            "UploadId": self.mpu["UploadId"],
        }
        self.threshold = part_size_threshold
        self.parts = []
        self._init_part()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_value:
            self.abort()
            raise exc_value
        self.complete()

    def _init_part(self):
        self.buf = b""

    def _upload_part(self):
        part_number = len(self.parts) + 1
        response = self.s3.upload_part(PartNumber=part_number, Body=self.buf, **self.kwargs)
        self.parts.append(
            {
                "PartNumber": part_number,
                "ETag": response["ETag"],
            }
        )

    def complete(self):
        if len(self.buf) > 0:
            self._upload_part()
        if len(self.parts) == 0:
            self.abort()
            return
        self.s3.complete_multipart_upload(MultipartUpload={"Parts": self.parts}, **self.kwargs)

    def abort(self):
        self.s3.abort_multipart_upload(**self.kwargs)

    def write(self, b: bytes):
        self.buf += b
        if len(self.buf) > self.threshold:
            self._upload_part()
            self._init_part()
```

## 使用例
以下は、 `s3://foo/parts/` 内にある大量の `.csv.gz` ファイル (ヘッダ行なし) をすべて結合して `s3://foo/concatenated.csv.gz` に保存したい、という場合のサンプルコード。

Linux コマンドでいえば `cat parts/* > concatenated.csv.gz` で実現できるような操作を、Amazon S3 オブジェクトに対してやりたい、というイメージ。データ量が少なければ全ファイル読み込んで結合して PutObject すればよいが、メモリに乗り切らない場合は MultiPartUpload を用いて読み込みながらアップロードしていく必要がある。

``` python
import boto3

s3 = boto3.client("s3")
bucket = "foo"

with AmazonS3MultipartUploader(s3, Bucket=bucket, Key="concatenated.csv.gz") as mpu:
    for obj in list_all_objects(s3, Bucket=bucket, Prefix="parts/"):
        b = s3.get_object(Bucket=bucket, Key=obj["Key"])["Body"].read()
        mpu.write(b)
```



ここで使用している `list_all_objects` ジェネレータについては以下の記事を参照。

https://qiita.com/hoto17296/items/d3f01162ef959a0d2f04

コンテキストマネージャとして実装して `with` 文で使えるようにすることで、使う側で complete や abort などの操作を不要にした。

あとは `mpu.write` に bytes データを放り込んでいけばいいだけなのだが、 bytes 型でさえあればいいのでかなり自由になんでもできる。(例えば `BytesIO` と組み合わせて Pandas DataFrame を `.to_csv()` したものを放り込んだり。)
ralis学習備忘録その1 ~progate 道場レッスンIまで~

# はじめに
マジでただのメモ 読んでもらうために書いてないので悪しからず...

# 内容
progate の rails入門を進めていく
1章~3章まで

## rails I 
view / controller / routing についてざっくりと理解

### view を作る
以下のコマンドで、view下に `home` フォルダと `top.html.erb` が作成される
```
rails generate controller home top
```

### controller って何？
- ページを表示する時、ralisの中では「controller」を経由してブラウザにviewを返している
- `rails generate controller home top` を打った時、以下が起こる
    - controllerの中に「home_controller.rb」が作成される
    - この中に `top` メソッドが生成される
        - このメソッドを **アクション** という
- controllerと同じ名前のviewフォルダからアクションと同じ名前のHTMLファイルを探してブラウザに返す
- 用途ごとにcontrollerを作り分けるのがいいらしい

### ルーティングって何？
- urlとコントローラを紐づけるもの
- `config/routers.rb`に定義
-  `get "URL" => "コントローラー名#アクション名"` って感じで書く

### view は？
- css ファイルは `app/assets/stylesheets` にある
- 画像は `app/public` 下に配置することで、絶対パスで読み出せる

## rails II
データベースとの接続をやっていく

### 変数宣言
- `<% posts="hogehoge" %>` みたいな感じで宣言
- 配列とかも宣言できる
- `<%= posts %>` みたいに変数を使う
- `<% posts.each do |post| %> ~~ <% end %>` みたいな感じで for文みたいなのを書ける
- Controller 内に `@posts = [~~]` みたいな感じで宣言して、これをview の中で使う

### データベースの作り方

- `rails g model Post context:text` で、モデルファイルとマイグレーションファイルを作成出来る
    - context = カラム名
    - text = データ型
    - Post ~ モデル名
※ このコマンドは migrationファイルを作るだけ (=datamodelを作るだけ) で、dbに反映してくれるわけではない
- マイグレーションファイルは、`db/migrate` 下に出来る
- `rails db:migrate` をすることで実際のデータベースの反映される

### 「モデル」について

- ApplicationRecordを継承したクラスをモデルと呼ぶ
- `rails g model` コマンドから `app/models/~~.rb` に作成される

### 共通のレイアウトをまとめる

- `views/layouts/application.html.erb` 内の `<%= yield %>` の部分に各viewファイルが代入され、application.html.erb の一部としてブラウザに表示されていた
    - ので、ここに共通のヘッダーとかは入れてあげるのが良い

## rails III

### URLParams の取得
- routes の中で、`get "posts/:id"` の `:id` の部分が `params` という変数に入る
- `@post = Post.find_by(id: params[:id])` みたいな感じで、特定のidの何かを取ってくることが出来る
- controller 内で 以下のようにして取得可能
```rb
  def show
    @id=params[:id]
    @post = Post.find_by(id: @id)
  end    
```
- viewの中で以下のように変数展開
```erb
<% @posts.each do |post| %>
  <div class="posts-index-item">
    <%= link_to(post.content, "/posts/#{post.id}") %>
  </div>
<% end %>
```

### データの作成

- view 内で、`<%= form_tag("hogeURL") do%> ~~ <% end %>` を用いることで、submitしたデータを指定したURL に送る
    - 例えば `form_tag("create")` とすれば、routes内で `create` で指定されたアクションを起こす
- `redirect_to("fugaURL")` をcontroller 内に書くことで、リダイレクトする
- `<textarea name="content">` として submit すると、rails側で `params[:content]` で取得できる
rubyの正規表現 繰り返し アンカー

# rubyのバージョンは3.1.1です。
詳しくはrubyの公式ドキュメントを見てください。

# 繰り返し
以下のメタ文字列は繰り返しを表現します。直前の部分式を何回繰り返すかを指定します。このような繰り返しを表すメタ文字列を量指定子(quantifier)と呼びます。

```*``` 0回以上
```+``` 1回以上
```?``` 0回もしくは1回
```{n}``` ちょうどn回(nは数字)
```{n,}``` n回以上(nは数字)
```{,m}``` m回以下(mは数字)
```{n,m}``` n回以上m回以下(n,mは数字)

### 出典
https://docs.ruby-lang.org/ja/3.1/doc/spec=2fregexp.html#:~:text=r%5Cn%22)%20%23%20%3D%3E%20nil-,%E7%B9%B0%E3%82%8A%E8%BF%94%E3%81%97,m%7D%20n%E5%9B%9E%E4%BB%A5%E4%B8%8Am%E5%9B%9E%E4%BB%A5%E4%B8%8B(n%2Cm%E3%81%AF%E6%95%B0%E5%AD%97),-%E4%BB%A5%E4%B8%8B%E3%81%AE%E4%BE%8B

### 気づき
```+```は計算式の漢字のようにみてしまうとダメなんだな。
直前のものが何回繰り返すかを表現している。
条件の塊なんだな。
# アンカー
アンカーは幅0の文字列にマッチするメタ文字列です。幅0とは```文字と文字の間```、```文字列の先頭```、```文字列の末尾```、などを意味します。```ある特定の条件を満たす「位置」```にマッチします。

```^``` 行頭にマッチします。行頭とは、文字列の先頭もしくは改行の次を 意味します。
```$``` 行末にマッチします。 行末とは文字列の末尾もしくは改行の手前を意味します。
```\A``` 文字列の先頭にマッチします。
```\Z``` 文字列の末尾にマッチします。 ただし文字列の最後の文字が改行ならばそれの手前にマッチします。
```\z``` 文字列の末尾にマッチします。
```\b``` 単語境界にマッチします。 単語を成す文字と単語を成さない文字の間にマッチします。 文字列の先頭の文字が単語成す文字であれば、文字列の先頭 の位置にマッチします。
```\B``` 非単語境界にマッチします。 \bでマッチしない位置にマッチします。

### 出典
https://docs.ruby-lang.org/ja/3.1/doc/spec=2fregexp.html#:~:text=%E3%81%B0%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82-,%E3%82%A2%E3%83%B3%E3%82%AB%E3%83%BC,%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%20%5Cb%E3%81%A7%E3%83%9E%E3%83%83%E3%83%81%E3%81%97%E3%81%AA%E3%81%84%E4%BD%8D%E7%BD%AE%E3%81%AB%E3%83%9E%E3%83%83%E3%83%81%E3%81%97%E3%81%BE%E3%81%99%E3%80%82,-%23%20%E6%96%87%E5%AD%97%E5%88%97%E4%B8%AD

### 気づき
```\Z```と```\z```は違うのか。
いろいろあるな。
SQLによるデータベース操作　DDL編

スクール時代ではあまり文法を用いての操作をしていなかったため、
カリキュラムで学んだことと、調べた情報をアウトプットしていこうと思います。
今回はDDL編です！

# SQLとは
RDB[^1]の操作を行うための言語で、ActiveRecordなどのORM[^2]のメソッドは、
SQLに変換されるためテーブル操作が可能になる。

# SQLでできること
大きく分けて3つに分類される。

1. データ定義(DDL)・・・データベースやテーブルを作成・削除する
2. データ操作(DML)・・・データを探す・登録・更新
3. データ制御(DCL)・・・変更を確定する・取り消す

# SQLの使用
ターミナルもしくはGUIツールでも操作が可能。
（スクールではSequelProを使用）
```
# ホームディレクトリに戻る
% cd

# MySQLに接続
% mysql -u root
```

# DDL
Data Definition Language(データデフィニションランゲージ)の略。

| 主な命令　　| 機能 　                  |
| ------ | ---------------------- |
|CREATE  | データベースやテーブルの作成 |
|ALTER   | データベースやテーブルの更新 |
|DROP    | データベースやテーブルの削除 |

# SQL文について
SQL文は小文字でも動作するが、SQL文と他の文字列が混ざると読みづらくなるため大文字で記述する。
また、SQL文の文末には必ず`;`をつける必要がある。
`;`を忘れるとまだ操作が続くものだと見なされ、期待した動きをしない。

# CREATE文
データベースやテーブル作成ができる。
```sql
# データベースの作成
CREATE DATABASE データベース名 ;

# テーブルとカラムを同時に作成することも可能。
CREATE TABLE テーブル名 (カラム名1 カラム名1の型, カラム名2 カラム名2の型, …);
```
##### 使用例
```sql
# sqltestというデータベースを作成
CREATE DATABASE sqltest;

# itemテーブルと、idカラムを同時に作成
CREATE TABLE item id INT;
```

# SHOW文
データベースやテーブルを一覧表示できるSQL文
```sql
SHOW DATABASES;
```
上記にて作成したデータベースが表示されます。
```sql
mysql> SHOW DATABASES;
+------------------------+
| Database               |
+------------------------+
| 省略                    |
| sqltest  　　             |
| 省略                    |
+------------------------+

```
# USE文
どのデータベースを使用するのかを指定するSQL文。
```sql
USE データベース名
```
```sql
USE sqltest;
```

# DROP文
データベースやデータを削除できる。
```sql
# データの削除
ALTER TABLE テーブル名 DROP カラム名;

# データベースの削除
DROP DATABASE データベース名;
```
##### 使用例
```sql
# itemテーブルのidカラムを削除
ALTER TABLE item DROP id; 

# sqltestデータベースを削除
DROP DATABASE sqltest;
```

# ALTER文
データベースやテーブルを編集できる。

```sql
ALTER TABLE テーブル名 操作内容;
```
##### 使用例
```Sql
# itemテーブルにnameカラムを追加
ALTER TABLE item ADD name VARCHAR(20); 
```

書きたい記事が多いけど、何をどこまで書こうかなと時間がかかって下書きばかりが増えていく・・・
続けられるよう頑張ります！





[^1]:RDB
表形式でデータを管理するデータベース。
行と列を持っており、データベースにおいて行を「レコード」、列を「カラム」と言う。

[^2]:ORM
RDBのデータをオブジェクト指向のプログラミング言語で、オブジェクトとして使用するために変換する技術のこと。
Nuxt3の開発をしていてVSCodeのTailwind CSS IntelliSense拡張機能が動かなくなったとき

## この記事の立ち位置

突然拡張機能による補完が効かなくなったため、私の場合これで解消したという共有で、
Nuxt3はまだ技術記事も少ないため、一時のバグかも知れませんが参考になれば幸いです。

## 環境

- MacOS
- VSCode: 1.74.3
- Tailwind CSS IntelliSense: v0.9.6

## 事象

ある日VSCodeのバージョンアップを行うために再起動を行ったところ、以下の画像のようにTailwind CSS IntelliSenseによる補完機能が効かない状態になっていた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498497/894364c5-dea1-6e8c-7794-78338d4610a9.png)

## 結論

拡張機能を有効にするフォルダに関して、`.nuxt`フォルダを除外することで正常に動作する状態に戻った。
[関連するGitHubのIssue](https://github.com/tailwindlabs/tailwindcss-intellisense/issues/663#issuecomment-1316788128)

拡張機能の設定にアクセスするには、他にも方法はあると思うが以下の画像の設定マーク→「拡張機能の設定」→「Files: Exclude」に追加した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498497/c3b040ea-fead-1823-5e50-f09a11e708c6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498497/ceed73e2-9047-0b12-b50f-bdad30d872e3.png)

## アプローチ方法

ありきたりだが、ターミナルなどのタブがある「出力」→「Tailwind CSS IntelliSense」を選択するとエラーが出ていたため、エラー内容でググった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498497/78f6c625-5412-30ca-9866-0c0639114f22.png)

## 今回は当てはまらなかったもの

1. `tailwind.config.js`ファイルが存在しない→今回はちゃんとファイルがあったが、ワークスペースの直下に無い場合は作成する
1. setting.jsonの設定→以下の設定を施すことで直る場合もある様子

```
{
  "editor.quickSuggestions": {
    "strings": true
  }
}
```

2.の参考記事

https://kossy-web-engineer.hatenablog.com/entry/2021/03/20/154014

## まとめ

今回はNuxt由来だったので記事タイトルも絞ったが、汎用的には今回当てはまらなかったパターンでの解決例が多そう。
あとはエラーログは大事。（今回この拡張機能のエラーが出ている箇所を初めて知った）
以上。
options ステートメントで設定する主なオプション

●options ステートメントで設定する主なオプション
・directory namedの作業ディレクトリ。/etc/named.conf内に書いた相対パスはここを起点とする
・recursion[yes|no] 再起的問い合わせを受け付けるかの設定。yesの場合はキャッシュサーバーとしての役割をはたす
・forwarders 自信が保持しないドメイン情報の問い合わせを転送するDNSサーバのアドレスを指定
・forward [first|only] 問い合わせ転送の失敗時の動作を設定。first→失敗時に自分で問い合わせをする。only→十杯時に自分で問い合わせをしない。
・allow-query 問い合わせをうけつけるホストを指定
・allow-recursion 再起的問い合わせを受け付けるホストを指定
・allow-transfer ゾーン転送を許可するホストを指定。マスターDNSサーバにおいて、スレーブDNSサーバのアドレスを指定する。
・blackhole 問い合わせを受け付けないホストを指定
・version BINDのバージョンの問い合わせに対し、出力される文字数を設定

※BINDの設定ファイルは、ステートメントはセミコロンで終わる。ステートメント内のサブステートメントもセミコロンで終わる。
さまざまな場面で使う三項演算子

## 目次
　[1.基本構文](#1-基本構文)
　[2.条件によって出力の内容が異なる場合](#2-条件によって出力の内容が異なる場合)
　[3.条件によって代入する値が異なる場合](#3-条件によって代入する値が異なる場合)
　[4.return文に記載する場合](#4-return文に記載する場合)
　[5.応用編](#5-応用編)


## 1. 基本構文
```java
条件 ? trueの場合 : falseの場合
```
三項演算子を使用することで、コードの記述量を減らし実装を簡潔にすることができます。
また、if文のネストが深くなりすぎるのを防ぐこともできます。

では実際の実装例を見ていきましょう。
※実装例に記載の魚リストの要素数はさいごまで2のままです。


## 2. 条件によって出力の内容が異なる場合
### if文ver.
```java
// 魚リスト
List<String> fishList = new ArrayList<String>();
fishList.add("まぐろ");
fishList.add("かつお");

// if文ver.
if (fishList.size() >= 3) {
    System.out.println("要素数は3以上です");

} else {
    System.out.println("要素数は3以上ではありません");
}
```

### 三項演算子ver.
```java
// 魚リスト
List<String> fishList = new ArrayList<String>();
fishList.add("まぐろ");
fishList.add("かつお");

// 三項演算子ver.
System.out.println(fishList.size() >= 3 ? "要素数は3以上です" : "要素数は3以上ではありません");
```
出力結果は、if文ver、三項演算子ver、どちらも「要素数は3以上ではありません」。


## 3. 条件によって代入する値が異なる場合
### if文ver.
```java
// 魚リスト
List<String> fishList = new ArrayList<String>();
fishList.add("まぐろ");
fishList.add("かつお");

// if文ver.
String str1 = "";
if (fishList.size() >= 3) {
    str1 = "要素数は3以上です";
    System.out.println(str1);

} else {
    str1 = "要素数は3以上ではありません";
    System.out.println(str1);
}
```

### 三項演算子ver.
```java
// 魚リスト
List<String> fishList = new ArrayList<String>();
fishList.add("まぐろ");
fishList.add("かつお");

// 三項演算子ver.
String str2 = fishList.size() >= 3 ? "要素数は3以上です" : "要素数は3以上ではありません";
System.out.println(str2);
```
出力結果はどちらも「要素数は3以上ではありません」。


## 4. return文に記載する場合
### if文ver.
```java
public static void main (String args[]) {
		
    // 魚リスト
    List<String> fishList = new ArrayList<String>();
    fishList.add("まぐろ");
    fishList.add("かつお");
    
    // 判定メソッド呼び出し
    System.out.println(isTrue(fishList));
}

// 判定メソッド
// リストの要素数が3以上の場合true、3より少ない場合falseを返却
private static boolean isTrue(List<String> list) {
    
    if (list.size() >= 3) {
        return true;
    }
    
    return false;
}
```

### 三項演算子ver.

```java
public static void main (String args[]) {
		
    // 魚リスト
    List<String> fishList = new ArrayList<String>();
    fishList.add("まぐろ");
    fishList.add("かつお");
    
    // 判定メソッド呼び出し
    System.out.println(isTrue(fishList));
}

// 判定メソッド
// リストの要素数が3以上の場合true、3より少ない場合falseを返却
private static boolean isTrue(List<String> list) {

    return (list.size() >= 3 ? true : false);
}
```
出力結果はどちらも「false」。


## 5. 三項演算子の応用
### if文ver.
```java
// 魚リスト
List<String> fishList = new ArrayList<String>();
fishList.add("まぐろ");
fishList.add("かつお");

// if文ver.
if (fishList.size() == 0) {
    System.out.println("要素数は0です");

} else if (fishList.size() >= 3) {
    System.out.println("要素数は3以上です");

} else {
    System.out.println("要素数は3以上ではありません");
}
```

### 三項演算子ver.

```java
// 魚リスト
List<String> fishList = new ArrayList<String>();
fishList.add("まぐろ");
fishList.add("かつお");

// 三項演算子ver.
System.out.println(fishList.size() == 0 ? "要素数は0です" : (fishList.size() >= 3 ? "要素数は3以上です" : "要素数は3以上ではありません"));
```
魚リストの要素数が0でない場合、コロン右の（）内の処理が行われます。
要素数は3より少ないため、２つ目のコロン右の文字列が出力されます。
応用としてこちらの記事に記載しましたが、こちらはコードが難解になるためおすすめしません。

出力結果はどちらも「要素数は3以上ではありません」。
ATOM S3とOMRON製非接触温度センサをつなげてみた

# はじめに

- M5Stack ATOMS3とOMRON製非接触センサのD6T-44L-06をつなげてみたよ。
- サーモグラフィーを表示してみたよ。

# 先に結論から

こちらの記事のプログラムのほぼほぼコピペです。感謝です。
恐れ多いので、プログラム全文は載せないです。。。

[M5Stackにサーマルカメラをつなぐ](https://ambidata.io/samples/m5stack/thermalcamera/)

### 変更点
- 液晶サイズを128 x 128として設定

```cpp:変更後
#define WIDTH (128 / 4)
#define HEIGHT (128 / 4)
```

- 液晶がBGRになったため、heat関数の`r`と`b`をスワップ

```cpp:変更後
  float b = sigmoid(x, gain, -1 * offset_x);
  float r = 1.0 - sigmoid(x, gain, offset_x);
  float g = sigmoid(x, gain, offset_green) + (1.0 - sigmoid(x, gain, -1 * offset_green)) - 1;

```

- `#include <M5AtomS3.h>`を冒頭に追加

# つかったもの

| メーカー | 名前 | 入手先 |
|:-:|:-:|:-:|
| M5Stack | ATOM S3  | 　https://www.switch-science.com/products/8670  |
| OMRON | D6T-44L-06  | https://www.digikey.jp/short/f35tb8j2  |
|  TECHNOALTA | 4×4非接触温度センサD6T 変換基板 | https://www.switch-science.com/products/5331  |

非接触温度センサの詳細はこちらを参照。

https://www.fa.omron.co.jp/products/family/3706/specification.html

そのほか、Groveケーブル一本とオスーオスジャンパ（GROVEとATOM S3をつなげるなにか）があればOK。

ちなみに変換基板については生産が終わっているため、入手出来ていない場合は自分で回路を組む必要があります。幸いにも販売ページの`資料`から回路図を参照することができます。

https://www.switch-science.com/products/5331

# 接続

| ATOM S3 | d6T-44L-06 |
|:-:|:-:|
| G39  | SCL  |
| G38  | SDA  |
| 5V  | VCC  |
| Gnd  | GND  |

# 動作

<iframe width="560" height="315" src="https://www.youtube.com/embed/sMPICAqh2sc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# おわりに

- wifi使って温度を何処かに飛ばしたいなぁ。
rubyの正規表現 \w,メタ文字の "."

# ```\w```
\w 単語構成文字 [a-zA-Z0-9_]

### 出典
https://docs.ruby-lang.org/ja/3.1/doc/spec=2fregexp.html#:~:text=%E5%AD%98%E5%9C%A8%E3%81%97%E3%81%BE%E3%81%99%E3%80%82-,%5Cw%20%E5%8D%98%E8%AA%9E%E6%A7%8B%E6%88%90%E6%96%87%E5%AD%97%20%5Ba%2DzA%2DZ0%2D9_%5D,-%5CW%20%E9%9D%9E%E5%8D%98%E8%AA%9E

### 気づき
英数字（大文字含む)と_（アンダーバー)を含むのか。

# メタ文字列とリテラル、メタ文字とエスケープ
正規表現の文法には、正規表現内で特別な働きをする文字列と、それ以外のその文字列そのものにマッチするような文字列があります。```前者をメタ文字列(meta string)```、```後者をリテラル(文字列)(literal string)```と呼びます。

>/京都|大阪|神戸/
/京都|大阪|神戸/

という正規表現においては、```「京都」「大阪」「神戸」がリテラル```で、 2つの```「|」がメタ文字列```です。

以下の文字は「メタ文字」(meta character) と呼ばれる、正規表現内で特殊な働きをする文字です。

>( ) [ ] { } . ? + * | \

```これらの文字をリテラルのようにその文字としてマッチさせるためには、バックスラッシュ「\」を前に付けます。```「\\」はバックスラッシュ1文字にマッチします。

### 出典
https://docs.ruby-lang.org/ja/3.1/doc/spec=2fregexp.html#:~:text=%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82-,%E3%83%A1%E3%82%BF%E6%96%87%E5%AD%97%E5%88%97%E3%81%A8%E3%83%AA%E3%83%86%E3%83%A9%E3%83%AB%E3%80%81%E3%83%A1%E3%82%BF%E6%96%87%E5%AD%97%E3%81%A8%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97,%E4%BB%98%E3%81%91%E3%81%BE%E3%81%99%E3%80%82%E3%80%8C%5C%5C%E3%80%8D%E3%81%AF%E3%83%90%E3%83%83%E3%82%AF%E3%82%B9%E3%83%A9%E3%83%83%E3%82%B7%E3%83%A51%E6%96%87%E5%AD%97%E3%81%AB%E3%83%9E%E3%83%83%E3%83%81%E3%81%97%E3%81%BE%E3%81%99%E3%80%82,-%E3%83%A1%E3%82%BF%E6%96%87%E5%AD%97%E4%BB%A5%E5%A4%96

### 気づき
```.```をしたい時は```\.```とするのか。

# 感想
プログラミング言語の違いで正規表現にも違いがあるのか。知らなかった。
公式のドキュメントを読むことが重要だ。
【Linux】ディレクトリの一覧を取得する方法

## `ls`コマンド

```zsh
ls -F [パス] | grep /
```
隠しファイルも含めて表示
```zsh
ls -aF [パス] | grep /
```
```zsh:サンプル
$ ls -F path/to/sample | grep /
app/
bin/
config/
db/
lib/
log/
public/
spec/
storage/
templates/
test/
tmp/
vendor/

$ ls -aF path/to/sample | grep /
./
../
.devcontainer/
.docker/
.git/
.vscode/
app/
bin/
config/
db/
lib/
log/
public/
spec/
storage/
templates/
test/
tmp/
vendor/
```

または次のように実行します。

```
$ ls -lR ./ | grep ^d
drwxr-xr-x 2 root root 44 12月  6 20:48 dir1
drwxr-xr-x 2 root root 44 12月  6 21:33 dir2
drwxr-xr-x 2 root root 6 12月  6 21:36 dir1-1
drwxr-xr-x 2 root root 6 12月  6 21:36 dir1-2
drwxr-xr-x 2 root root 6 12月  6 21:36 dir2-1
drwxr-xr-x 2 root root 6 12月  6 21:36 dir2-2

```

## `find`コマンド

`find`コマンドでディレクトリのみの一覧を取得するには次のように実行します。

```terminal
$ find ./ -mindepth 1 -type d
./app
./bin
./config
./db
./lib
./log
./public
./spec
./storage
./templates
./test
./tmp
./vendor
```
【PostgreSQL】timestamp指定でテーブルをCSV出力



 ・postgresqlでテーブルデータをローカルにCSV出力する
 ・日次(timestamp)指定での取得



▼CSV出力コマンド（通常・カンマ区切り）
```sql
COPY (テーブル名) TO '(ファイルパス)' WITH CSV DELIMITER ',';
COPY Sample_table TO '/temp/sample.csv' WITH CSV DELIMITER ',';
```


しかし COPY はDBサーバ上でファイルを入出力するコマンドなので、このままファイルパスにクライアントのファイルパスを指定して実行してもエラーになる。

クライアント側に読み書き対象ファイルを配置する場合は [ ¥COPY ] を使用。

▼CSV出力コマンド（クライアント側に読み書き対象ファイルを配置する場合・カンマ区切り）
```sql
¥COPY (テーブル名) TO '(ファイルパス)' WITH CSV DELIMITER ',';
¥COPY Sample_table TO 'C:/work/temp/sample.csv' WITH CSV DELIMITER ',';
```

とりあえずこれでクライアント端末にテーブルデータのCSV出力が出来る。
SELECT句を入れる場合は下記の形式。

```sql
¥COPY (SELECT * FROM テーブル名 WHERE 条件 ) TO '(ファイルパス)' WITH CSV DELIMITER ',';
```

PostgreSQLでtimestamp型を指定すると通常はミリ秒まで含むため、ミリ秒混みのBETWEEN-ANDで日次指定を行う。

```sql
¥COPY (SELECT * FROM テーブル名 WHERE 日次カラム名 BETWEEN 'yyyy-mm-dd hh:mm:ss.fff' AND 'yyyy-mm-dd hh:mm:ss.fff') TO '(ファイルパス)' WITH CSV DELIMITER ',';

¥COPY (SELECT * FROM sample_data WHERE ins_date BETWEEN '1999-04-01 00:00:00.000' AND '1999-04-01 23:59:59.999') TO 'C:/work/temp/sample.csv' WITH CSV DELIMITER ',';
```

これで一日分(1999/04/01)のデータを、クライアント側PCにCSVで出力出来る。

---
> ※他DBでのCSV出力について
・MySQLはファイルの出力先が指定されている
・SQLServerはツール使えば一発
React18でuseEffectが2回走っちゃう件

# 結論
クリーンアップ処理が欠けている場合がほとんどのため、クリーンアップ処理を追加すると直る。
例：
```diff_typescript
  useEffect(() => {
    const connection = createConnection();
    connection.connect();
+   return () => {
+     connection.disconnect();
+   };
  }, []);
```

## なぜこういう動きになっている？
React18では、開発チームが意図的にコンポーネントを2度、マウントしている。（Strictモードの開発環境のみ）
つまり、初回マウント→アンマウント→マウントの流れになる。
具体的な理由については、以下の記事で詳しく書かれているのでここでの説明は省きます。
[React18でのStrictモードとuseEffectの挙動](https://www.sunapro.com/react18-strict-mode/#index_id3)

Strictモードを解除したり、useRefなどで一回だけ発火させたりすることで、この問題は見かけ上解消されます。
ただ、望ましい解消案は、「useEffectを一回だけ走らせる」ではなく、「2回のマウントでもちゃんと正しく動くコードを書く」ことである。


公式にも関連のことが書かれている。
[my-effect-runs-twice-when-the-component-mounts](https://beta.reactjs.org/reference/react/useEffect#my-effect-runs-twice-when-the-component-mounts)

## さいごに
こういう挙動になっていることで、クリーンアップ処理の書き忘れとか、コードのアラに気づけるので個人的にはありがたいです。
解消方法に困っているどなたかの役に立てれば幸いです。
【30分でやる（改）】GPT3とGoogle Spread Sheetで管理するLINE BOTの作り方

# 概要
にわかに騒がれているGPTChatやGPT-3について、ご多分に漏れず興味関心を向けてみた結果、むかーし作った「誰でも30分で作れる」をコンセプトにしたLINEBotをカスタマイズするに至りましたのでご参考まで。

## 元記事
もうカレコレ4年ほど前に作成した記事になりまして、「スプレッドシートに予め登録したQAのみを返すLINEボット」を作るという仕様でございました。
今回はこちらのボットに「回答が見つからなかったときはAIに変わりに返事をしてもらう」という仕様を追加したいと思います。

https://qiita.com/WdknWdkn/items/b78ae572e7cb5c9dfdca

## 参考元
なお、こちらにGPT-3とのGASを用いた簡単な連携方法が記載されていたので参考にさせていただきました。
GPT-3上でのアカウント発行からトークン取得までの流れはこちらを参考いただけると良いかと思います。

https://liquidjumper.com/google-sheets/googlespreadsheet_connect_to_gpt_3

## 追加する仕様

* 投げた単語に対してスプレッドシート上に部分一致するQAが「ない」場合に、GPT-3に同様のキーワードを投げて、返ってきた値をメッセージで返す。

## アップデート前の状態

こんな感じで、予定したキーワードには返答しますが、想定にないものは返答しません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/7b6131e0-f5e4-040f-829f-fd67fa90ba90.png)

# 作業内容

## 以下のfunctionをGASに追加

※前の記事でGASのスクリプトを作成している前提になります。
連携用の処理を1つのfunctionにまとめてしまいました。

```js
/**
 * GPT連携関数
 */
function GPT(prompt) {

  const SECRET_KEY = "（ここにGPT-3で発行したトークンを貼る）";
  const MAX_TOKENS = 300; // 返信文字列の最大数
  const MODEL_NAME = "text-davinci-003";
  const MODEL_TEMP = 0.3;

  const url = "https://api.openai.com/v1/completions";
  const payload = {
    model: MODEL_NAME,
    prompt: prompt,
    temperature: MODEL_TEMP,
    max_tokens: MAX_TOKENS,
  };

  const options = {
    contentType: "application/json",
    headers: { Authorization: "Bearer " + SECRET_KEY },
    payload: JSON.stringify(payload),
  };

  const res = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
  return res.choices[0].text.trim();
}
```

## 追加したfunctionを、回答がない場合の処理に追記

今までは定型文で「答えが見つかりませんでした。別のキーワードで質問してみてください。」とだけ返答するよう記載していた箇所を変更します。

### before

```js
// 回答がない場合の定型文
sendMessage(replyToken, '答えが見つかりませんでした。別のキーワードで質問してみてください。');        
```

### after

```js
let AIReplyText = '答えが見つかりませんでした。AIに回答をおまかせします。';
AIReplyText = AIReplyText + "\n\n＝＝＝＝＝＝＝＝＝＝＝＝＝\n\n" + "A：" + GPT(postMsg);
// 回答がない場合の定型文
sendMessage(replyToken, AIReplyText);
```

## デプロイしましょう

スクリプト画面上の「デプロイ＞新しいデプロイ」から、デプロイを登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/c41f3049-0d38-0eff-652f-297f5f1c39e3.png)

ウェブアプリのしたの「URL」の内容をコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/6bd557a1-4164-0a79-863b-427717545c9f.png)

## LINEのWEBhookを更新

LINE画面上での設定変更もお忘れなく。先程コピーしたWebhookURLを更新します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/8093eb61-e4fd-2a1d-744a-5a4d95282b7c.png)

# できたらこんな感じ
AIの精度は今後に期待。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/5f135fd9-7ea4-1481-b109-438bd9fb30c0.png)

# 感想
AIってやっぱり面白いですね。精度を上手く考慮して使い所を見極めるアイディア勝負なところというのが今回の感想です。面白い活用方法とかがあればぜひどなたでも教えていただきたいです。
複数のUSB-HDDを dockerコンテナで bind mount するときの注意

大量のデータを 使いたくなった時 USB-HDD を docker ホストに 追加して bind mount したくなったとき 注意することがある。

# 横着せずに ひとつづつ 直接 mount しよう。

20TBくらい 必要に なったので 8TB の USB-HDD を Dockerホストに 追加するとき
ストライビングするまでもないので ひとつづつ mount したとする。

例えば docker ホストで
mkdir /USB
mount -t ntfs /dev/sdd1 /USB/USB_d
mount -t ntfs /dev/sde1 /USB/USB_e
mount -t ntfs /dev/sdf1 /USB/USB_f

と マウントしたとして
touch /USB/USB_d/mytest.txt
と USB-HDD に ファイルを 作成しておいても

docker run -it -v /USB:/USB ubuntu /bin/bash

と コンテナを 起動したときに 

コンテナ上で ファイルを 参照しようとすると

＞ ls /USB/USB_d/mytest.txt
ls: cannot access '/USB/USB_d/mytest.txt': No such file or directory

と エラーする

bind mount が  参照しているストレージを超えて ホスト上で mount されている その先へ アクセスできないんだ（と 思う）

なので

docker run -it -v /USB/USB_d:/USB/USB_d -v /USB/USB_e:/USB/USB_e -v /USB/USB_f:/USB/USB_f ubuntu /bin/bash

それぞれ bind mount しなければならない