OmniAICreator/Qiita-1.07M huggingface dataset:
【JavaScript】onClick= () => hoge()とonClick={hoge}の違い

業務の中で、以下の2つの書き方の違いに疑問を感じたので調べてみた。

```javascript
onClick= () => openDialog();

onClick={openDialog};
```

## 2つの違い
#### 新しい関数の作成
|onClick= () => openDialog()|onClick={openDialog}|
|:-|:-|
|コンポーネントが再レンダリングされるたびに新しい関数を作成する。|新しい関数は作成されない。openDialogへの直接の参照が渡される。|


#### 関数の引数
|onClick= () => openDialog()|onClick={openDialog}|
|:-|:-|
|openDialog関数イベントオブジェクトを受け取らないことが保証される。|openDialog関数はクリックイベントオブジェクトを引数として受け取る。|


#### パフォーマンス
|onClick= () => openDialog()|onClick={openDialog}|
|:-|:-|
|新しい関数が再レンダリングの度に作成されるので、特に大きなリストや頻繁な再レンダリングが発生する場面ではパフォーマンスの問題が起きる可能性がある。|左のようなパフォーマンスの懸念はない。|

#### 可読性と拡張性
|onClick= () => openDialog()|onClick={openDialog}|
|:-|:-|
|将来的にこの関数呼び出しに引数を追加したり、このクリックハンドラ内で複数の操作を行いたくなった場合、この書き方の方が変更しやすい.|シンプルで直接的です。ただし、上記のような変更を行う場合は、関数定義自体を変更するか、新しいラッパー関数を作成する必要がある。|
linux系OSで設定されているタイムゾーンをコマンドで確認する

## 概要

- タイムゾーンを確認するコマンドをメモ的にまとめる。

## 方法

- 下記コマンドを実行し出力された内容を確認する。

    ```bash
    date
    ```

- 上記コマンドにより、現在時刻と、タイムゾーンが出力される。
- 出力の例

    ```
    $ date
    2023年 10月18日 水曜日 23時24分57秒 JST
    ```
チェンジマネジメントテンプレート

## チェンジマネジメントとは

チェンジマネジメントは、組織やシステムの変更を効果的に管理し、実施するプロセスのことを指します。これは、変更に関連するリスクを最小限に抑えるため、変更の影響を評価し、関連するすべてのステークホルダーに変更をコミュニケートし、変更の実施と確認を行うための手順や手法を含んでいます。目的は、変更をスムーズかつ効果的に実施し、目標の達成と組織の継続的な成功をサポートすることです。

---

## 1. Release Date and Time
- **概要**: チェンジやアップデートを行う具体的な日付と時間。
- **詳細**: 明確な日時を指定し、必要に応じて作業所要時間も記載する。
- **サンプル**: 
    ``` 
    Release Date and Time: 
    2023-01-19, 10:00 AM - 12:00 PM (2 hours)
    ```

## 2. Personnel & Responsibility
- **概要**: リリースや変更作業を担当する人物やチーム。
- **詳細**: 担当者の氏名や役職、連絡先を明確に記述する。
- **サンプル**:
    ```
    Personnel & Responsibility:
    リリース担当: 山田太郎
    連絡先: yamada@example.com
    ```

## 3. Pre Activity Plan
- **概要**: 本作業実行前に行う必要のある作業のプラン。
- **詳細**: 事前の作業手順や確認事項を明確にリストアップする。
- **サンプル**:
    ```
    Pre Activity Plan:
    - menusテーブルの設定変更。
    - バッチ処理の設定確認。
    ```

## 4. Activity Plan
- **概要**: 本作業の実施内容や手順。
- **詳細**: 作業の具体的な手順や期待される結果を詳細に記載する。
- **サンプル**:
    ```
    Activity Plan:
    - バッチ処理の起動。
    - 設定の変更を保存。
    ```

## 5. Post Activity Plan
- **概要**: 本作業実行後に行う必要のある作業や確認事項。
- **詳細**: 作業終了後の確認手順や次のステップを明確にリストアップする。
- **サンプル**:
    ```
    Post Activity Plan:
    - ログの確認。
    - DBの状態確認。
    ```

## 6. Rollback Plan
- **概要**: 作業の失敗や不具合が発生した際の巻き戻しプラン。
- **詳細**: エラー回避のための手順や対処法を明確に記載する。
- **サンプル**:
    ```
    Rollback Plan:
    - DBのバックアップを復元。
    - 設定を前の状態に戻す。
    ```

--- 

### 記入するうえでの注意点

1. **明確性**: 各手順やタスクは具体的かつ明確に記述すること。他の担当者がそれを読んで理解できるレベルの詳細さが求められる。
2. **再確認**: 手順やクエリは誤りがないか再確認すること。特にデータベースの変更など、取り返しのつかない操作には注意が必要。
3. **通知**: 作業完了後の通知先や方法を明記し、関連するチームや部署に情報共有を怠らないこと。
4. **ドキュメンテーション**: 変更内容や手順、使用したクエリなどは後から参照するためのドキュメンテーションとして保存しておくこと。
5. **リンクの検証**: 提供されたリンクや参照先は正しいか確認する。必要に応じてバージョン情報も明記する。

--- 

### まとめ

上記のテンプレートは、チェンジマネジメントを行う際の基本的なフレームワークとして役立つ。明確性、正確性、情報共有の重要性を念頭に置きながら、計画的かつ慎重に作業を進めることが求められる。

---
Flutter TextFieldの備忘録

# FlutterのTextFieldの備忘録
[参考サイト](https://api.flutter.dev/flutter/material/TextField-class.html)
## 目次
1. [最大文字数を設定する](#最大文字数を設定する)
1. [カーソルを非表示にする](#カーソルを非表示にする)
1. [中央揃えにする](#中央揃えにする)
1. [下線を消す](#下線を消す)
# 最大文字数を設定する
最大文字数を設定する方法は2つあるようである。
1つ目はmaxLengthを直接指定する方法である。
```dart:
TextField(
    maxLength: 10,
)
```
こちらの場合は現在の文字の入力数と最大数が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121536/52285aab-ce42-a1b5-ed3d-23162a4a3deb.png)
いや表示してほしくないんだがな...という方は次のinputFormattersを指定する方法が有効である。
```dart:
TextField(
    inputFormatters: [
        LengthLimitingTextInputFormatter(1),
      ],
)
```
こちらの場合は現在の文字数と最大文字数が表示されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121536/2df208dd-80b8-9d2f-537a-41e0d8d26973.png)

# カーソルを非表示にする
テキストを入力しようとすると出てくる縦線のカーソルを消す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121536/c1ce50d2-5163-9443-7258-c92cde36153d.png)
TextFieldのshowCursorをfalseにする。
```
TextField(
    showCursor: false,
)
```
# 中央揃えにする
testAlignにTextAlign.centerを入力すればよい。
```
TextField(
    textAlign: TextAlign.center
)
```
そのほかにもleft, right, justify, start, endが指定できそうである。
leftが左揃え、rightが右揃え、justifyが両端揃えというのは分かったが、start, endってなんだ？と思ったので調べた。
startは、言語の始まりに合わせるという意味らしい（そのままやな...)。
日本語の場合は左から右に読む言語なので、左揃えになるが、世界には右から左に読んでいく言語もあるらしい。その場合は右揃えにしてくれるらしい。
へぇ～便利な時代やねぇ。

# 下線を消す
テキストの周り（枠の部分とかかな？）の処理はTextFieldのdecorationにInputDecorationクラスのインスタンスを入れることで、指定できるようである。
今回は下線を消したいので、InputBorder.noneを指定した。
```
TextField(
    decoration: InputDecoration(
        border: InputBorder.none
    )
)
```
他にも[UnderlineInputBorder()](https://api.flutter.dev/flutter/material/UnderlineInputBorder-class.html)や[OutlineInputBorder()](https://api.flutter.dev/flutter/material/OutlineInputBorder-class.html)を指定できるようである。
Underlineは初期の下線だと思われる。Outlineの方はテキストフィールドを囲う四角形を書くことができる。
```
TextField(
    decoration: InputDecoration(
        border: OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(10.0))
        )
    )
)
```
OutlineInputBorderには、引数を指定することでいろいろ境界線を変えれそうである。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121536/b32fc32e-f964-9d3b-fc01-0b38c9da29f5.png)
丸いテキストフィールドがたくさんwww。
ただ、半径の指定をするためだけに、かなりたくさんのクラスを見る必要があって、なんか面倒だなぁ...と感じてしまった。Border.Radius.allは四隅全部を指定するために必要。左上のみを指定するなどができるっぽい。Radius.circular(radius)も別メソッドとして、Radius.elliptical(x,y)が用意されている。こちらはx,yを指定することで、楕円にすることができるらしい。
【Ruby on rails】Rails7でslickを導入する（bootstrap併用可）

# はじめに
プログラミングを勉強して2か月半ほどです。
私事ですが、先日プログラミングスクールを卒業しました。
毎日会っていた同期や仲間たちと会えなくて寂しいですが、引き続き学習を進めます。
そして、就職活動を頑張って、人や世の中の役に立つシステムやアプリの開発に携わりたいです。

前置きが長くなりましたが、今回はrails7でslickの導入をしたいと思います。
作成中のオリジナルアプリの使い方ページをslickで実装したかったので挑戦しました。
rails7での導入方法があまりサイトに載っておらず大苦戦しました。
なんとか導入出来たので、みなさんに共有したいと思います。


※初心者なので間違っているところがあれば、ご指摘いただけると幸いです。

# slickとは
slickはjQueryの、スライダーを作成するためのプラグインです。 レスポンシブにも対応可能で、カスタマイズの幅も広いため、世界的に利用されています。

こんな感じの機能です↓
[![Image from Gyazo](https://i.gyazo.com/6aa2fcbcaaf9691cd1850a43b4ac28f1.gif)](https://gyazo.com/6aa2fcbcaaf9691cd1850a43b4ac28f1)

それでは、rails7環境下でのslick導入をしていきます！

# Let's start!!!

## ①jQueryの導入

```config/importmap.rb
pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.6.3/dist/jquery.js"
```

## ②slickの導入

```app/views/layouts/application.html
<!DOCTYPE html>
<html>
  <head>
    <title>Qiita</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>
    
    <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.css"/>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
    <script type="text/javascript" src="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js"></script>
  </head>

  <body>
 <%= yield %>
  </body>
  
</html>
```
jQueryを導入した後にslickを読み込ませる必要があるので上記の順番で記述しましょう。

## ③application.jsへの記述
```app/javascript/application.js
import "slick"
```

## ④importmap.rbへの記述
```config/importmap.rb
pin "slick", to: "slick.js"
```
上記の③、④の記述で`slick.js`を読み込むことができます。

## ⑤viewへの記述
```app/views/welcomes/index.html.erb
<div class="container">
    <h3 class="ml-3 my-4">使い方</h3>
  <div class="slider">
    <%= image_tag 'sample1.png' %>
    <%= image_tag 'sample2.png' %>
    <%= image_tag 'sample3.png' %>
    <%= image_tag 'sample4.png' %>
  </div>
</div>
```
※このviewの記述は冒頭に載せているslickを導入したオリジナルアプリのものとは異なります。

## ⑥jsファイルにslickの記述を記入
```app/javascript/slick.js
document.addEventListener('turbo:load', function () {
	$('.クラス名').slick({
	    
	    });
 
});
```
`$('.クラス名').slick({`
クラス名のところは、今回の場合は`slider`になります。
みなさんがつけたクラス名に合わせて記述してください。

slickは様々なカスタムができるので調べてカスタムしてみてください！

以上でrails7環境下でのslick導入は完了です。


# bootstrapを導入している方へ
私はslick導入前にbootstrap導入していたために、上記の手順のみではslickを読み込むことができませんでした。

ここからはbootstrap導入済みで上記の手順では上手くいかなかった方へ説明していきます。

## ①Gemfileを確認
```:Gemfile
# 中略
gem 'jquery-rails'
```
`Gemfile`に`gem 'jquery-rails'`の記述があれば削除しましょう。

## ②application.jsを確認
```app/javascript/application.js
// 中略
//= require jquery3
```
`application.js`に`//= require jquery3`の記述があれば削除しましょう。

以上でbootstrap導入した状態でもslickが導入出来ました。

おそらく、bootstrap導入時に上記の方法でjQueryを導入したため、jQueryを読み込ませる記述が重複していたことが原因と思われます。

# 終わりに
rails7環境下でのslick導入はこれにて終了です！
みなさん実装お疲れ様でした！！
解説が不足している部分が多く、申し訳ございません。
解説ができるように学習を進めていきますので、引き続きよろしくお願いします！

※この記事を読んで参考になったという方は、ぜひ`いいね`をお願いします！
投稿者が喜びます。
SQLの実行計画とは？

## 先に結論
> クエリー実行計画 (つまり、MySQL がクエリーをどのように実行するかの説明) を取得するために使用されます。

一言で言うと、**クエリの中で何が行われているかがわかる**ということ。
 `EXPLAIN`を使うと抽出するレコード数、インデックスの使用、JOINの条件などが記載された表が出力されます。
簡単なクエリしか使用しないならば、特に実行計画を行う必要はありません。
しかし、実務の中で複雑なクエリを投げることは往々にしてあります。
そんな時に便利なのがこの`EXPLAIN`です。

## EXPLAINって？
こんな形式で書く
```
EXPLAIN SELECT *
FROM HOGE
INNER JOIN FUGA
ON HOGE.HO = FUGA.FU
WHERE = ...
```
`SELECT`, `DELETE`, `INSERT`, `REPLACE` および `UPDATE`の前に`EXPLAIN` を付けて実行するだけ。
これによって、テーブルがどのように、どんな順番で結合されているかに関する情報や、処理する方法を教えてくれます。

## 出力カラム
|カラム|JSON名|意味|
| ---- | ---- | ---- |
|id|select_id|SELECT識別子|
|select_type|なし|SELECT 型|
|table|table_name|出力行のテーブル|
|partitions|partitions|一致するパーティション|
|type|access_type|結合型|
|possible_keys|possible_keys|選択可能なインデックス|
|key|key|実際に選択されたインデックス|
|key_len|key_length|選択されたキーの長さ|
|ref|ref|インデックスと比較されるカラム|
|rows|rows|調査される行の見積もり|
|filtered|filtered|テーブル条件によってフィルタ処理される行の割合|
|Extra|なし|追加情報|

重要なのは`type`です。ここにはテーブルの結合方法が示されます。
適切なものから、不適切なものまで存在し、ここを修正することで処理効率が改善される可能性が高いです。

https://dev.mysql.com/doc/refman/8.0/ja/explain-output.html

詳しくはMySQL公式を見た方がわかりやすいので割愛。

## 参考
https://dev.mysql.com/doc/refman/8.0/ja/explain.html#explain-table-structure

https://zenn.dev/yuulab/articles/f415920220acf9
vue3で table表示用のラッパーコンポーネントを作成してみた

自分用のメモです。
個人開発してみようと思い立ち
作業しているとテーブルを表示したくなったが

daisyUIに見てくれをよくするものはあったが
扱いやすくする処理はなかった


以前、テーブルを表示するときにag-grid好んで使っていたが
今回の使用用途ではそこまでのものは必要なかったため
自分で軽く書いてみた

機能は最低限のもので正直きれいではないと思う。

vue3 
tailwind
https://daisyui.com/
https://www.ag-grid.com/




DataTable
``` vue
<script setup>
const props=defineProps({
  id: {
    type: String,
    required: true
  },
  columDefs: {
    type: Array,
    required: false
  },
  rowData: {
    type: Array,
    required: false
  },
})

</script>
<template>
  <div class="rounded-lg border-2">
    <table :id="id" class="table">
      <!-- head -->
      <thead>
        <tr>
          <td v-for="(col,colIndex) in props.columDefs" :key="'col-head-' + colIndex">
            {{ col['headerName'] }}
          </td>
        </tr>
      </thead>
      <!-- tbody -->
      <tbody>
        <tr v-for="(row,rowIndex) in rowData" :key="'row-'+rowIndex">
          <template v-for="(col,colIndex) in props. columDefs" :key="'col-body-' + colIndex">
            <td>{{ row[col.fild] }}</td>
          </template>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<style lang="">

</style>

```

呼び出し
``` vue
<script setup>

const columDefs= [
  { headerName: 'Row ID', field: 'id' },
  { headerName: 'Row make', field: 'make' },
  { headerName: 'Row model', field: 'model' },
  { headerName: 'Row price', field: 'price' },
]
const rowData = [
  { id: 'c1', make: 'Toyota', model: 'Celica', price: 35000 },
  { id: 'c2', make: 'Ford', model: 'Mondeo', price: 32000 },
  { id: 'c8', make: 'Porsche', model: 'Boxster', price: 72000 },
  { id: 'c4', make: 'BMW', model: 'M50', price: 60000 },
  { id: 'c14', make: 'Aston Martin', model: 'DBX', price: 190000 },
]
</script>

<template>
    <DataTable :columDefs="columDefs" :row-data="rowData" />
</template>

```


表示結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3486455/81678898-9cf3-daee-4d04-b2279368dc92.png)
Apple Watch 公式チュートリアルでビルドが通らないとき

https://developer.apple.com/tutorials/swiftui/creating-a-watchos-app

Appleの公式SwiftUI Tutorialsは品質が高くて俄然やる気が出ます。
ただし今回はビルドができない問題に引っかかったので、その対処法を紹介します。

# 課題
上記サンプルアプリの完成版プロジェクトを開いて署名し実機テストしようとすると以下のエラーメッセージが出た。

###### Error Message
> WatchKit App doesn't contain any WatchKit Extensions whose WKAppBundleIdentifier matches "com.example.apple-samplecode.LandmarksXXXXXXXXXX.watchkitapp". Verify that the value of WKAppBundleIdentifier in your WatchKit Extension's Info.plist matches the value of CFBundleIdentifier in your WatchKit App's Info.plist.

`WatchKit Extensions`の`WKAppBundleIdentifier`と
`WatchKit App`の`CFBundleIdentifier`が一致していないことが問題のよう。

# 原因

各TargetのBundle Identifierは以下の通り。
![Screenshot 2023-10-18 at 22.33.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/65f15901-8fc5-3472-9058-9bd8a41a1a27.png)
*Bundle Identifierは上記画像のように各Targetの`Sining &Capabilities`から確認可能。

1. Landmarks (iOS App): `com.example.apple-samplecode.Landmarks${SAMPLE_CODE_DISAMBIGUATOR}`
1. WatchLandmarks(WatchOS APP): `com.example.apple-samplecode.Landmarks${SAMPLE_CODE_DISAMBIGUATOR}.watchkitapp`
1. WatchLandmarks Extension: `com.example.apple-samplecode.Landmarks${SAMPLE_CODE_DISAMBIGUATOR}.watchkitapp.watchkitextension`



唐突に出てくる`${SAMPLE_CODE_DISAMBIGUATOR}`って誰だよ。![Screenshot 2023-10-18 at 22.42.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/f259d0e4-d250-29e1-8af7-e876ec1a991b.png)

（自分の理解では）AppleのTutorialのような公開プロジェクトは配布時にBundle Identifierに初期値を与えるとみんなで衝突しちゃうから、それを回避するために、Development TeamのID?を加えてユニークな値になるようにしている。

なのに、下記画像のようにInfoタブから確認できるプロパティリストの方ではBundle IdentifierにDevelopment Teamに関連する値が追加されていない。
![Screenshot 2023-10-18 at 22.49.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/b3f42370-91ae-7596-48ab-da6489b7b0c0.png)
![Screenshot 2023-10-18 at 22.56.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/751e4632-db4d-ed27-9d94-31ede8d63510.png)


# 解決法

![Screenshot 2023-10-18 at 22.55.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/e72a497e-804c-f236-f931-deafec9597eb.png)


![Screenshot 2023-10-18 at 22.51.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2361573/ffc0ee62-b43c-9a52-1dfb-91886f5a5ddc.png)

1. WatchLandmarks(WatchOS APP)の`WKCompanionAppBundleIdentifier`に`com.example.apple-samplecode.Landmarks${DEVELOPMENT_TEAM}`と設定。
1. WatchLandmarks Extensionの `NSExtension` > `NSExtensionAttributes` > `WKAppBundleIdentifier`に`com.example.apple-samplecode.Landmarks${DEVELOPMENT_TEAM}.watchkitapp`と設定。

これでいける。
laravel cronとタスクスケジューラーとlaravelコマンドと

## 概要

- OS側のジョブスケジューラーであるcronとlaravelのタスクスケジューラーとlaravelコマンドについてまとめる。

## 登場人物の説明

### laravelコマンド

- 「決まった処理」をartisanコマンドで実行することができるよ。
- ただし人間かシステムが実行してくれないと永遠に動作することはないよ。
- もちろんコード上で記載してほとんどの場合Git管理されるよ。

### laravelのタスクスケジューラー

- 「この条件」で「このコマンドを実行します」を管理するよ。
- あくまでコマンドの実行タイミングを保持しているだけだよ。実行トリガーの仕組みは無いよ。
- これもコード上で記載して殆どの場合Git管理されるよ。

### cron

- OS側の仕組みだよ。
- 設定された時間に指定されたコマンドを実行するよ。

## 重要な事実

- 「laravelのコマンド（バッチ）を決まった時間に実行したい」場合、基本的に「laravelコマンド」「laravelのタスクスケジューラー」「cron」をすべて設定する必要がある。
- ※`基本的に`と書いたのはcronで直接laravelコマンドを指定して定期実行する方法もあるため。ただしこの方法は基本的に取らない。（せっかくタスクスケジューラーがlaravelて提供されているのにわざわざcronで定期実行の設定をする必要はないため）

## コマンド定期実行の仕組み

- 「laravelコマンド」「laravelのタスクスケジューラー」「cron」が全て定義されているものと仮定する。
- 下記のような流れでコマンドは定期実行される。
    1. cronで`php artisan schedule:run`（laravelのタスクスケジューラーの起動コマンド）が毎分実行されるように設定する。
    1. 上記のcronの実行によりlaravelのタスクスケジューラーが起動し、現在の時刻の条件に合う設定が記載されているか探索する。
    1. ヒットした場合、紐づいているコマンドを実行する。

- cronの設定はOS側で行う。
- laravelのタスクスケジューラーのスケジュールとコマンドの紐づけ設定は`app/Console/Kernel.php`のscheduleメソッドで行う。
JavaScript+CSS/アニメーション実装方法


Javascriptの勉強。
カーソルを動かすたびにカラフルで可愛いハート💛が現れるアニメーションの実装方法を模写して学習しました！
カラフルで本当にかわいい…！

勉強に使用した動画：https://www.youtube.com/watch?v=I0R0T7p5oR8

記述したコードはこちら。

①index.html
```
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Colorful Hearts On Mousemove</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <script type="text/javascript">
    document.addEventListener("mousemove", function(e){
      let body = document.querySelector('body');
      let heart = document.createElement("span");
      let x = e.offsetX;
      let y = e.offsetY;
      heart.style.left = x + 'px';
      heart.style.top = y + 'px';
      let size = Math.random() * 100;
      heart.style.width = 20 + size + 'px';
      heart.style.height = 20 + size + 'px';
      body.appendChild(heart);

      setTimeout(function(){
        heart.remove();
      },2000);
    })
  </script>
</body>
</html>
```

②style.css
```
* {
  margin: 0;
  padding: 0;
}

body {
  overflow: hidden;
  background: #000;
  height: 100vh;
}

span{
  position: absolute;
  background: url(heart.png);
  pointer-events: none;
  width: 50px;
  height: 50px;
  background-size: cover;
  transform: translate(-50%,-50%);
  animation: animate 2s linear infinite;
}
@keyframes animate {
  0% {
   transform: translate(-50%,-50%);
   opacity: 1;
   filter: hue-rotate(0deg);
  }
  100% {
    transform: tranlate(-50%, -1000%);
    opacity: 0;
    filter: hue-rotate(720deg);
  }
}
```

### addEventListenerとは？
→指定した対象について、特定のイベントが実行される度に関数の呼び出しや処理の設定ができる。

```
指定したターゲット.addEventListener("イベントの種別",function(){})
```

今回の場合は…
```
 document.addEventListener("mousemove", function(e){
```

なので、mousemove（マウスカーソルが移動）した時にイベントが発火。　

### document.querySelector()とは？
→documentオブジェクトの（）内に記述された要素を取得。

今回の場合は、

```
let body = document.querySelector('body');
```

なので、「body」という要素を取得してbodyに代入している。

### document.createElement()とは？
→　()内のタグ名をもつ要素を生成して、メモリに保存する。


なので、
```
let heart = document.createElement("span");
```
「span」のタグ名を持つ要素を生成→heartに代入。


### offsetとは？
event.offsetX　→　要素内でのカーソル座標Xを取得
event.offsetY　→　要素内でのカーソル座標Yを取得

eventをeと省略。
```
let x = e.offsetX;
let y = e.offsetY;
```

### Math.random()とは？
→　0以上1未満の乱数を表示。

なので、
```
let size = Math.random() * 100;
```
0以上1未満の乱数を表示させsizeに代入。100倍する。

### appendChildとは？
→ 特定の親要素の中に要素を追加する。
要素を指定してその要素の子要素としてHTMLタグを追加する。
※追加される場所は親要素の閉じタグの直前。

### setTimeoutとは？
→　待ち時間後にfunctionを一度だけ実行するメソッド。

```
setTimeout(ファンクション、待ち時間)
```

なので、
```
setTimeout(function(){
        heart.remove();
},2000);
```

2秒後にハートを消去する。
PHPでファイルの最後の1行だけほしい

雑にぐぐるだけで、file() で全部読み込んでcountして最後の1行とりにいくような残念なブログが平気で出てきて困るわね
```
exec('tail -n 1 hoge.txt', $output);
print $output[0];
```

身も蓋もないんじゃよ
【Salesforce Marketing Cloud Tips】 クエリアクティビティの「*」の利用注意

## クエリの最適化・注意事項
先日リファレンスを読んでいて、驚いたことがあったので共有します。

https://help.salesforce.com/s/articleView?id=sf.mc_as_optimize_the_query_activity.htm&type=5

上記より引用
> SELECT * を使用するのではなく、列を名前で指定します。SELECT * を使用すると、クエリアクティビティパーサーでクエリが保存されるときに存在する列がキャッシュされます。将来、別の列を追加しても、その列は自動的には含まれません。

一度、SELECT * FROM hoge　でクエリを作成後、インプットDEにカラム追加をした場合は当該クエリを再度保存し直す必要があると言うことですね。
SQLのパフォーマンス観点でも「*」の利用は避けたい場合が多いですが、この仕様を知らなかったが故にAutomationが想定通りに動かないことがないように注意しましょう。

## 一言
SARGalbeなクエリについても記載がありますので、後で追記しようと思います。
取り急ぎ忘れないうちにアウトプット、と言うところでの記事でした。
Prismを使ってみた感想

# Prismとは
[Prism](https://github.com/ruby/prism)とは最近できたRubyのソースコードパーサです。ソースコードを渡すとAST(抽象構文木)を作ります。そして、それぞれのノードには便利なメソッドが備わってあります。

```ruby
require "prism"

code = <<~CODE
  "foo"
CODE

prism_result = Prism.parse(code)
p prism_result.value
#=> @ ProgramNode (location: (1,0)-(1,5))
#=> ├── locals: []
#=> └── statements:
#=>     @ StatementsNode (location: (1,0)-(1,5))
#=>     └── body: (length: 1)
#=>         └── @ StringNode (location: (1,0)-(1,5))
#=>             ├── flags: ∅
#=>             ├── opening_loc: (1,0)-(1,1) = "\""
#=>             ├── content_loc: (1,1)-(1,4) = "foo"
#=>             ├── closing_loc: (1,4)-(1,5) = "\""
#=>             └── unescaped: "foo"
```

対象のノードの位置を簡単に取得できます。
```ruby
# "foo"文字列を取得する
string_node = prism_result.value.child_nodes.first.child_nodes.first

# 位置の取得
string_node.location
#=> (1,0)-(1,5)
string_node.location.start_line
#=> 1
string_node.location.start_column
#=> 0
string_node.location.end_column
#=> 5
```

特にこの位置の取得が結構すごいだと思って、なぜかというと、普通のRipperの出力を見ると`(1,0)`の情報しか含まれていません(下記では`[1, 1]`という風に表現されています)。

```ruby
require "ripper"

p Ripper.sexp(code)
#=> [:program,
#=>   [
#=>     [:string_literal,
#=>       [:string_content,
#=>         [:@tstring_content, "foo", [1, 1]]
#=>       ]
#=>     ]
#=>   ]
#=> ]
```

Prismではそのノードがどこで始まるかだけじゃなくて、どこで終わるかも取得できます。ifやwhileなどのブロックの場合、そのブロックがどこで終わっているかを探し出せるということです！かなりすごい。

# Masamune
筆者はなぜその位置情報がそんなにほしいかと言ったら、[Bullet Train](https://bullettrain.co/)で[Masamune](https://github.com/gazayas/masamune-ast)というツールを使っているからです。Bullet Trainの`config/routes.rb`では`namespace`や`resource`のブロックをたくさん修正することがあります。Masamuneを使うと、そのブロックの始まりと終わりがどこなのか分かります。

ただし、v2.0.0までは生のRipperを使っていました。かなりハードな作業でした...

それで、生のRipperのままだけで上手く行っていたけど、その実装自体がちょっと複雑でした。
Prismを使ったらいいんじゃない？と上司からのアドバイスをいただきました。

それでPrismにアップデートしましたが、Prismの作者であるKevinさんもその実装についてアドバイスを与えてくれたので、興味があれば[プルリクエスト](https://github.com/gazayas/masamune-ast/pull/60)の方を読んでみてください。

内容としては下記の通りです。

# `Visitor`クラスを使おう
Masamuneで実現したいこと：
1. 例えば文字列がほしいなら`strings`というメソッドを呼ぶだけで、適切なノードを見つけたい
2. 見つけたノードを配列に格納して返したい

Prismを使う前は、筆者は再帰的にRipperの出力を分割してそれぞれのノードを解析していました。ただし、Prismでは、`Visitor`というクラスがあります。これは何をするクラスかというと、作られた抽象構文木に対して探したいノードを簡単なメソッドでアクセスできるようにするクラスです。

```ruby
module Masamune
  class AbstractSyntaxTree
    class StringsVisitor < Prism::Visitor
      attr_reader :token_value, :results

      def initialize(token_value)
        @token_value = token_value
        @results = []
      end

      def visit_string_node(node)
        results << node if token_value.nil? || token_value == node.content
        super
      end
    end
  end
end
```

ここで注目してほしいのは`visit_string_node`です。もし`StringNode`の中身をみたいなら`visit_string_node`、`DefNode`(関数宣言)のノードなら`visit_def_node`という具合に、こういったメソッドをオーバーライドするだけで中身を見ることができ、自由自在に扱うことができます。そして、`super`を呼ぶと、ASTの残りのノードを探してくれます。

筆者の場合は、`results`という配列に文字列のノードを格納して返しています。

## 感想
以上！とまあ、Ripperを直接使うより遥かに楽ですね。本当にいろんなメソッドがPrismのノードに準備してありますが、これは結構役に立つし、もっと使いたいなと思います。もし読者も使ったことがあるなら、是非下でコメントを残してください！

お読みいただきありがとうございます。
フィブリンシーラント市場：数多くの種類の手術における世界的 な普及で成長するとResearch Nesterが分析 2023年～2033年

リサーチ・ネスターは次のタイトルのレポートを発表した「フィブリンシー ラント市場世界の需要分析と機会展望2033年"この調査レポートは、世界のフィブリンシーラント市場をタイプ別、用途別、技術別、エンドユーザー別、地域別に分類し、その概要を詳細に掲載しています。さらに、詳細な分析のために、市場の成長に関連する現在と将来の市場動向に関する詳細な議論とともに、業界の成長指標、阻害要因、需給リスクを網羅しています。

レポートのサンプルPDFを入手する
https://www.researchnester.jp/sample-request-4466

世界のフィブリンシーラント市場は、予測期間（2023年〜2033年）のCA GRが〜10％で成長する。市場は用途別に、一般外科、心臓血管外科、胸部外科、整形外科、移植外科、神経外科、歯科外科、創傷管理、その他に区分される。このうち、心臓血管外科分野は、世界中で実施されている心臓血管外科手術件数の増加とともに、心臓血管疾患の有病率が上昇していることから、予測期間中に最も高い成長率を示すと予測されている。
世界のフィブリンシーラント市場は、血友病患者の有病率の増加や、筋骨格系の治療が整形外科手術の主な焦点であることから整形外科手術の継続的な増加により、広範に成長すると推定されている。このほか、世界的な高齢者人口の増加、世界的な医療費の高騰などが、予測期間中の市場成長を促進すると予想される主な要因のいくつかである。
![Fibrin-Sealants-market-overview.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491677/892f3823-7243-834d-d648-f276edc28f84.jpeg)

このレポートの詳細については、こちらをご覧ください：
https://www.researchnester.jp/reports/fibrin-sealants-market/4466

地域的には、世界のフィブリンシーラント市場は、北米、欧州、アジア太平洋、中南米、中東＆アフリカの5つの主要地域にセグメント化されている。北米地域の市場は、心血管疾患の有病率の増加、高度な医療構造の存在、同地域における外科手術プロセスの急増により、予測期間中に大きな成長を目撃すると推定されている。
この調査はグローバルな性質を持ち、以下の国の市場に関する詳細な分析をカバーしている North America (U.S., Canada), Europe (U.K., Germany, France, Italy, Spain, Hungary, Belgium, Netherlands & Luxembourg, NORDIC [Finland, Sweden, Norway, Denmark], Poland, Turkey, Russia, Rest of Europe), Latin America (Brazil, Mexico, Argentina, Rest of Latin America), Asia-Pacific (China, India, Japan, South Korea, Indonesia, Singapore, Malaysia, Australia, New Zealand, Rest of Asia-Pacific), Middle East and Africa (Israel, GCC [Saudi Arabia, UAE, Bahrain, Kuwait, Qatar, Oman], North Africa, South Africa, Rest of Middle East and Africa). さらに、市場規模、前年比成長率および機会分析、市場プレイヤーの競争調査、投資機会、将来の展望に対する需要などを含む分析も、調査報告書の中で取り上げられ、表示されている。

外科手術プロセスの世界的増加が市場成長を牽引

世界保健機関（WHO）の報告によると、毎年何百万人もの人々が外科的治療を受けており、世界全体の障害調整生存年数（DALYs）の約13％を外科的治療が占めている。
手術の根底にある概念は、診断または治療目的のために、臓器、臓器系、組織に物理的な介入を行うことである。一般に、人の組織を切開したり、すでにある切開創を縫合したりするような手技は、外科手術と呼ばれる。手術は、障害を和らげ、蔓延する病気で死亡する確率を下げる唯一の治療法である。そのため、重傷や慢性疾患の増加傾向は、外科手術の比率を非常に高めている。このように、手術プロセスの増加は、世界のフィブリンシーラント市場の成長を加速させている。
しかし、シーラントを承認するための各国政府の厳格な規制、COVID-19の制約による外科手術の延期、低侵襲手術におけるフィブリンシーラントの使用に関する制限は、予測期間中、世界のフィブリンシーラント市場の成長の主な抑制要因として作用すると予想される。
本レポートはまた、フィブリンシーラントの世界市場における主要企業の既存の競争シナリオを提供します	Takeda	Pharmaceutical	Company Limited, Grifols S.A., Stryker Corporation, Hemarus Therapeutics Limited, CSL Limited, Baxter International, Inc., Pfizer	Inc.,	Asahi	Kasei Corporation, Vivostat A/S, Octapharma AG, and others.The profiling enfolds key information of the companies which  encompasses business overview, products and services, key financials and recent news and developments.当レポートは、フィブリンシーラントの世界市場に関する詳細な概要をまとめており、業界コンサルタント、装置メーカー、事業拡大の機会を模索している既存企業、可能性を模索している新規企業、その他の関係者が、現在進行中および今後予想される動向に従って市場中心戦略を策定する際に役立つものと思われます。

について Research Nester
リサーチ・ネスターは戦略的市場調査とコンサルティングのリーディング・サービス・プロバイダーです。業界、コングロマリット、エグゼクティブが将来のマーケティング戦略、事業拡大、投資などのために賢明な決断を下せるよう、偏りのない比類のない市場洞察と業界分析を提供することを目指しています。私たちは、戦略的思考を通じて適切なタイミングで適切なガイダンスを得ることができれば、あらゆるビジネスが新たな地平へと拡大できると信じています。私たちの既成概念にとらわれない思考は、お客様が将来の不確実性を回避するために賢明な決断を下すことを支援します。

【お問い合わせ先】
ナオミ コスギ
Eメール: info@researchnester.jp
米国の電話番号: +81 505 050 8480
日本語の単語や文法を自然な英語で説明できるLLM「JPNSensei」をfinetuningで作りました。

## ①背景
海外の方、特に英語圏の人々は日本語を学ぶ時に、単語や文法の微妙なニュアンスを正確に理解するのは結構難しいではないかと思います。
そこで、これらの方々に向けて、わかりやすい英語で日本語の難しい単語や文法を解説できるモデルを作ろうと考えました。特に周りに聞けるネイティブな日本人がいない方には役に立てると思います。モデルの名前は「JPNSensei」と考えてます。

## ②学習データについて
StackExchangeという「海外の知恵袋」みたいなサイトの日本語スレのデータを使いました。

https://japanese.stackexchange.com/

以下のような質問は毎日数十件ほど投げられています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/b2953742-6d04-2ec5-1318-00aa04709b6e.png)

回答は基本「英語に詳しい日本人」や「日本語に詳しい外国人」の方が書いてます。
こちらのサイトから22000件くらいのデータをとりあえずInternet Archive上で取りました。
前処理はシンプルで、未回答のデータとtokenが長すぎる（2000token以上）データを除外し、約20,000件のデータに絞り込みました。処理後のデータは以下の形となります。

![123123123123.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/0faa52a2-3914-49ac-e16b-81be95e7e1c3.png)

## ③ベースモデルの選定
今回は、最近一番人気なMistralでトレーニングしました。

*Preferred　Networksという日本会社が先月公開された「英語と日本語のバランスが最強」と誇るLLama2ベースのfinetuningモデル「PLaMo-13B」も最近試してみたいと思います。

トレーニング時間はかなり長くて（試行錯誤を含めて約100時間かかりました）、lossの推移は以下のようになりました。
![5667.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/3abe835c-bb49-923c-3588-60c95b2d8753.png)

紫は１回目で、安定して1.9から1.1まで下がりました。
赤は２回目で、１回目の引き続きでトレーニングしてみたら、1.0くらいから不安定な状態になったので、こちらのデータセットに対しては多分1.0くらいはベストの収束だと思います。（20000件はまだ比較的に少ないので、データの量を増やせば変えると思います。）



## ④結果検証
モデルのアーキテクチャは以下の二つの質問を聞いてから回答するように設計しました。
①Chatbot: What's the topic or context of your question
②Chatbot: Please specify your question:

質問はこちらにしました:
①What does よろしくおねがいします mean when departing?
②When on business in Japan last year, a Japanese colleague said よろしくおねがいします to me as the group were leaving after dinner. I'm aware of its usage in initial greetings, as is usually taught in textbooks, but what is its English meaning in this context?
「よろしくお願いします。」はどんな気持ちを伝えているのかに関する質問ですね。

まずトレーニング前のモデルの回答は以下となります。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/e6357616-3a58-d709-bf2e-b304de7e4e50.png)
意味わからない回答してますね。

次はトレーニング後のモデルの回答です。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/4f5dd855-81dc-cf48-803e-433749a3ced6.png)
複数の状況で「よろしくお願いします。」を使う例を挙げて説明してます。
トレーニングが効いたのがわかりますね。

もちろん、一番強いchatgpt4にも聞いてみます。
![12345678.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/f2e351db-6c8f-c898-4cc0-995c7bdaf174.png)

やはりChatgpt4の方がより詳しく説明してますね。
ですが、まだ改善できるところいっぱいありますので、chatgpt4を超える可能性は高いと思います。

## 5.今後の改善点

①RAGで学習データと連携する
①学習データを増やす:目安としては5万件くらい
③StackExchangeからのデータ取得方法を見直す：最高評価の回答のみを取るのではなく、5点、8点以上の回答も取得し、モデルの回答の多様性を強化する
④ChatGPTを使って学習データを作る(同じ質問に対して、ChatGPTの回答の良いところを学習させる）
⑤他のモデルに変わってみる:Plamoとか
⑥「自分の回答を評価する」という機能を出力に反映させるように設計する

v2からはhuggingfaceへ公開したいと思います。

END
railsで誕生日入力フォームを作る

## はじめに
年、月、日を別々のセレクトボックスで入力するようなフォームを作成します。
難しいところは年と月の値によって日数が変わることでした。
様々な方法を考えたのですが、JavaScriptを使って対応することにしました。

## 環境
`rails 6.1.7.6`
`ruby 3.0.6`

## 実装
html.erbの下にscriptタグを設けてそこにJSのコードを書いていきます。

```erb
<%= form_for(hoge, url: hoge_path) do |f| %>
  <div class="field">
    <%= 
      f.select :birthdate_year,
      (1900..Date.today.year).reverse_each.to_a,
      { prompt: '' },
      { id: 'birthdate_year' } 
    %>
  </div>

  <div class="field">
    <%=
      f.select :birthdate_month,
      (1..12).to_a,
      { prompt: '' },
      { id: 'birthdate_month' }
    %>
  </div>

  <div class="field">
    <%=
      f.select :birthdate_day,
      (1..31).to_a,
      { prompt: '' },
      { id: 'birthdate_day' }
    %>
  </div> 
<% end %>

<script>
document.addEventListener('DOMContentLoaded', () => {
  const yearSelect = document.getElementById('birthdate_year')
  const monthSelect = document.getElementById('birthdate_month')
  const daySelect = document.getElementById('birthdate_day')

  function updateDayOptions() {
    const year = yearSelect.value
    const month = monthSelect.value
    const daysInMonth = new Date(year, month, 0).getDate()

    while (daySelect.firstChild) {
      daySelect.removeChild(daySelect.firstChild);
    }

    for (var i = 1; i <= daysInMonth; i++) {
      var option = document.createElement('option');
      option.value = i;
      option.text = i;
      daySelect.appendChild(option);
    }
  }

  updateDayOptions()

  yearSelect.addEventListener('change', updateDayOptions);
  monthSelect.addEventListener('change', updateDayOptions);
})
</script>
```

以上で動的に日数の変わるフォームを作ることができました。
railsにはdate_pickerというヘルパーもあったのですがカスタマイズが難しく今回の方法を見つけました。
カスタマイズが求められるアプリケーションでは参考にしていただけると嬉しいです。
Javascriptによるレコーディングアプリ

Javascriptによるレコーディングアプリです。

<!DOCTYPE html>
<html>
<head>
    <title>録音アプリケーション</title>
</head>
<body>
    <h1>録音アプリケーション</h1>
    <button id="startRecord">録音開始</button>
    <button id="stopRecord" disabled>録音停止</button>
    <button id="playRecord" disabled>再生</button>
    <a id="downloadLink" style="display: none">ダウンロード</a>

    <script>
        // 録音用変数
        let audioContext;
        let audioStream;
        let audioRecorder;

        // レコーディング開始ボタンのクリックハンドラ
        document.getElementById('startRecord').addEventListener('click', () => {
            navigator.mediaDevices.getUserMedia({ audio: true })
                .then(stream => {
                    audioStream = stream;
                    audioContext = new AudioContext();
                    audioRecorder = new MediaRecorder(audioStream);

                    const chunks = [];
                    audioRecorder.ondataavailable = event => chunks.push(event.data);

                    audioRecorder.onstop = () => {
                        const audioBlob = new Blob(chunks, { type: 'audio/wav' });
                        const audioUrl = URL.createObjectURL(audioBlob);
                        const audioDownloadLink = document.getElementById('downloadLink');
                        audioDownloadLink.href = audioUrl;
                        audioDownloadLink.download = 'recorded.wav';
                        audioDownloadLink.style.display = 'block';
                    };

                    audioRecorder.start();
                    document.getElementById('startRecord').disabled = true;
                    document.getElementById('stopRecord').disabled = false;
                    document.getElementById('playRecord').disabled = true;
                })
                .catch(error => {
                    console.error('録音の許可が拒否されました: ' + error);
                });
        });

        // 録音停止ボタンのクリックハンドラ
        document.getElementById('stopRecord').addEventListener('click', () => {
            audioRecorder.stop();
            audioStream.getTracks()[0].stop();
            document.getElementById('startRecord').disabled = false;
            document.getElementById('stopRecord').disabled = true;
            document.getElementById('playRecord').disabled = false;
        });

        // 再生ボタンのクリックハンドラ
        document.getElementById('playRecord').addEventListener('click', () => {
            const audioUrl = URL.createObjectURL(new Blob(audioRecorder.recordedChunks, { type: 'audio/wav' }));
            const audioElement = new Audio(audioUrl);
            audioElement.play();
        });
    </script>
</body>
</html>
このコードの概要:

ユーザーにマイクのアクセス許可を要求するためにgetUserMediaを使用して録音ストリームを取得します。
MediaRecorderを使用して録音を開始、停止し、録音したデータをバッファに保存します。
レコーディングが終了すると、録音データをBlobに変換し、ダウンロードリンクを表示します。
録音、停止、再生ボタンのクリックハンドラを設定して、それぞれのアクションを実行します。
このコードはシンプルな例であり、録音アプリケーションをカスタマイズおよび拡張する際にはセキュリティとユーザー体験を考慮する必要があります。録音の品質やフォーマット、エラーハンドリング、UI/UXの向上などを追加することができます。
Javascriptによる雪のアニメーション

Javascriptによる雪が降るアニメーションです。

<!DOCTYPE html>
<html>
<head>
  <style>
    body {
      margin: 0;
      overflow: hidden; /* 画面外の要素は非表示にする */
      background-color: black; /* 背景色を黒に設定 */
    }
  </style>
</head>
<body>
  <canvas id="snowCanvas"></canvas>
  <script>
    // キャンバス要素とコンテキストを取得
    const canvas = document.getElementById('snowCanvas');
    const ctx = canvas.getContext('2d');

    // キャンバスのサイズをウィンドウサイズに合わせる
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    // 雪のフレークを格納する配列
    const snowflakes = [];

    // 雪のフレークを生成する関数
    function createSnowflake() {
      const size = Math.random() * 5 + 2; // ランダムなサイズ
      const x = Math.random() * canvas.width; // ランダムなX座標
      const y = 0; // 画面上部からスタート
      const speed = Math.random() * 3 + 1; // ランダムな落下速度
      const opacity = Math.random() * 0.5 + 0.2; // ランダムな透明度

      snowflakes.push({ x, y, size, speed, opacity });
    }

    // 雪のフレークを描画する関数
    function drawSnowflakes() {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // キャンバスをクリア

      for (let i = 0; i < snowflakes.length; i++) {
        const flake = snowflakes[i];

        ctx.fillStyle = `rgba(255, 255, 255, ${flake.opacity})`; // 白色の雪
        ctx.beginPath();
        ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2);
        ctx.fill();

        // 雪の位置を更新
        flake.y += flake.speed;

        // 画面下端に達したら雪を配列から削除
        if (flake.y > canvas.height) {
          snowflakes.splice(i, 1);
          i--;
        }
      }
    }

    // 定期的に雪を生成してアニメーションする関数
    function animate() {
      createSnowflake();
      drawSnowflakes();
      requestAnimationFrame(animate);
    }

    // アニメーションを開始
    animate();
  </script>
</body>
</html>
リスト、スタック、キュー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/8feba480-9554-1630-5f33-78ecc61506c8.png)
　リストは、Webページをリンクで繋ぐのと同様の考え方でデータを管理します。自分のページに友達のページへリンクを張ると、自分のページから友達のページへたどることができます。リストは、データとデータをリンクで接続して、順番にデータを辿れるようにしたものです。
　スタックは、直近のデータから古い順にさかのぼってデータを取り出していきたいときに利用します。直近（最後）に入れたデータを最初に取り出せるので、後入先出（Last In First Out:LIFO）のデータ構造であると言います。
　キューは、データを格納した順に取り出したいときに利用します。最初に入れたデータを最初に取り出せるので、先入先出し（First IN First Out：FIFO）のデータ構造であると言います。

１：リスト（線形リスト）
　リストを構成する一つ一つのデータをリストの要素と言います。
　リストの要素は、レコード型の変数です。データを入れる項目と、自分の次の要素のアドレスを入れる項目を持っています。基本情報技術者試験では、要素のアドレスとして配列の要素番号が使われることが多いです。CやJavaなどのプログラムでは、要素のアドレスとしてメモリの番地やオブジェクトへの参照を使うこともあります。なお、リストの末尾要素の.next部分には、NULL(未定義の値)や−１を入れ、次がないことを表します。
　リストでデータを扱うと、リンクの繋ぎ換えをするだけで、途中にデータを挿入したり、途中からデータを削除したりすることができ、多くのデータがある時でも少ない手間で挿入・削除処理を行えます。

２：スタック
　スタックは、データを積み重ねて管理するイメージです。積み重ねてある部分が「スタック」です。スタックにデータを格納することをプッシュ（PUSH）、スタックからデータを取り出すことをポップ（POP）と言います。データをPUSHすると、スタックの一番上に置かれます。POPすると、スタックの一番上からデータを取り出します。スタックの途中からデータを取り出すことはできません。

３：キュー
　キューは、データを行列に並べて管理するイメージです。キューにデータを格納することをエンキュー（ENQUEUE）、キューからデータを取り出すことをでキュー（DEQUEUE）と言います。エンキューをENQ、でキューをDEQと省略して書くことも多いです。データをENQすると、行列の最後尾に置かれます。DEQすると、行列のセントからデータを取り出します。キューの途中からデータを取り出すことができません。
法が素数の時のn乗根を求める

## 結論
$\mod p$における整数$s$の$q$乗根は計算量$O(\sqrt{q})$で求められる。この記事では、Johnston氏による[A Generalized qth Root Algorithm](https://dl.acm.org/doi/pdf/10.5555/314500.315094)で説明されている方法について解説する。

## 注意事項
[A Generalized qth Root Algorithm](https://dl.acm.org/doi/pdf/10.5555/314500.315094)の内容を私が読解し、日本語で書いただけの記事である。したがって、情報が完全に正確であるとは保証しない。

## きっかけ
この項はアルゴリズムの内容とは関係ないので、必要ない人は読み飛ばしてもよい。

きっかけは以下の問題に出会ったことである。

### babyRSA([ISITDTU CTF 2023](https://ctftime.org/event/2080/))
```python3
from Crypto.Util.number import bytes_to_long
from FLAG import flag

p1 = 401327687854144602104262478345650053155149834850813791388612732559616436344229998525081674131271
p2 = 500233813775302774885494989064149819654733094475237733501199023993441312997760959607567274704359
p3 = 969568679903672924738597736880903133415133378800072135853678043226600595571519034043189730269981
e1 = 398119
e2 = 283609
e3 = 272383

c = bytes_to_long(flag)
c = pow(c, e1, p1)
c = pow(c, e2, p2)
c = pow(c, e3, p3)

print(f"{c = }")
# c = 104229015434394780017196823454597012062804737684103834919430099907512793339407667578022877402970
```

この問題の解法の1つは、$\mod p$で$c$の$e$乗根を総当たりすることである。そこで、[SageMath](https://doc.sagemath.org/html/en/reference/finite_rings/sage/rings/finite_rings/integer_mod.html#sage.rings.finite_rings.integer_mod.IntegerMod_abstract.nth_root)に`nth_root`というn乗根を求める関数が存在し、仕組みが気になって調べてみた。

## 理論の説明
元のpaperに書いてあることを日本語で説明するだけなので、英語を読めるならばそちらを参照した方が正確である。

### 文字の定義
$G$を位数$p-1$の乗法群とし、$s \in G$を、$q$乗根を求めたい元とする。簡単のため、$q$を素数とし、$|G|$は$q$で割り切れるものとする。また、$g$を$G$の生成元とする。

ここで「$|G|$は$q$で割り切れる」という仮定に違和感を覚えた方もいるかもしれないが、もし$\gcd(|G|, q)=1$ならば、次のようにして簡単に$\sqrt[q]{s}$を求められるからである。

---

Eulerの$\phi$関数を用いて$d = q^{-1} \mod \phi(p)$とする。また、$dq = 1 \mod \phi(p)$であるから、適当な整数$k$を用いて、$dq = 1 + k\phi(p)$と表せる。

Eulerの定理より、$(\sqrt[q]{s})^{\phi(p)}=1 \mod p$なので、

$s^d = ((\sqrt[q]{s})^q)^d = (\sqrt[q]{s})^{dq} = (\sqrt[q]{s})^{1 + k\phi(p)} = \sqrt[q]{s} \cdot ((\sqrt[q]{s})^{\phi(p)})^k = \sqrt[q]{s}$より、求める値を得る。

---

$|G|$が$q$で割り切れない場合、$d = q^{-1} \mod \phi(p)$の存在が保証され、しかもそれが高速に計算できるため、このように高速に解を求めることができる。

### 近似
$g^t$が$s$の$q$乗根と考えれば、ある整数$t$を用いて
$$
s = g^{qt}
$$
と表せる。

ここで、近似するための整数$x$、$z$を考え、
$$
s^x = g^t(g^z)^t
$$

とする。

ここで、底を$g$としたときの指数を比較して

$$
qtx = t(1+z)
$$

したがって

$$
x = \frac{1+z}{q}
$$

この式から、
- $(1+z)$は$q$で割り切れる必要がある。
- $z \equiv -1\mod q$である必要がある。
- $z$と$q$は互いに素である必要がある。
ことが分かる。

よって、$(p-1)$の最も大きな約数であって、$q$と互いに素であるものは、
$$
\frac{p-1}{q^k}
$$
と表される。ただし$k$は$q^k$が$(p-1)$を割り切る最大の指数。

よって、
$$
z = \frac{p-1}{q^k}
$$

また、
$$
x = \frac{1+z}{q}
$$

とできる。

## 誤差項の修正

$$
s^x = g^t(g^z)^t
$$

において、誤差項は$(g^z)^t$である。

ここで、元$g^z$の位数は$q^k$である。ちなみに、もし$k=1$ならば、この近似はすでに$q$乗根となっている。

底を$g^{\frac{p-1}{q^{k-1}}}$として、$s^{\frac{p-1}{q^k}}$の離散対数を求めると、$t \mod q^{k-1}$が求められる。($s=g^{qt}$を考えると理解できると思う)

よって、$s^x = g^t(g^z)^t$より誤差項を排除して、求める$q$乗根$u$は

$$
u = s^x(g^z)^{-t}
$$

となる。

## 実装
アルゴリズムの手順は以下のようになる。

---

1. もし $s^{\frac{p-1}{q}} \mod p \not\equiv 1$ならば終了する。$q$乗根は存在しない。(フェルマーの小定理を考えればよい)
2. $h = \frac{p-1}{q}$とする。
3. $h \mod q = 0$である間、$h$の値を$h=\frac{h}{q}$と更新する。
4. $z=h$, $x=\frac{1+z}{q}$とする。
5. $v \equiv s^x \mod p$とする。
6. 何らかの離散対数問題を解くアルゴリズムを用いて、$(g^{hq})^t = s^h$となる$t$を求める。
7. $\sqrt[q]{s} \equiv vg^{-xt}である。$
---
X(旧Twitter)のCommunityNotesについて軽く調べてみためも

# 参考資料

参考にしたのはこちら.

### 公式のコード、レポジトリ

https://github.com/twitter/communitynotes/tree/main/sourcecode

### Twitterの公式解説(英語)

https://communitynotes.twitter.com/guide/en/under-the-hood/ranking-notes

(日本語だと出てきていない気がする)

### CommunityNotesの論文(英語)

https://arxiv.org/pdf/2210.15723.pdf

### Gigazineの解説記事(日本語)

https://gigazine.net/news/20230818-x-twitter-community-note-algorithm/

### Youtubeの解説動画(日本語)

https://youtu.be/jhl6UR4_58E?si=a9zifrFLp9yyYL7N

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

### 他解説記事(英語)

https://vitalik.ca/general/2023/08/16/communitynotes.html


# 仕組みのまとめ

簡単には下記の流れの様子.

1. まず条件を満たしたノートとユーザでノートの価値を決める
2. 一度推定した価値を元に大きく評価を外しているユーザを除外し、再度ノートの価値を決定
3. 偽のユーザを元に評価の信頼区間を評価し、"有用"、"有用ではない"、"もっと評価が必要"を割り振る

各ステップにおけるノート評価の方法はMatrixFactorizationを使用する.

# 技術詳細とポイント

ソフトウェアの全体の構成なども実際はポイントがあるかもしれないが(とんでもないユーザ数とノート数になるので)、ここではアルゴリズムにフォーカス.

大事なのは下記のMatrixFactorization. 詳細な技術解説は他のQiita記事がたくさんあるので、ここでは簡単な紹介のみ.

## MatrixFactorization

### 目的と効果
行列の分解を行い、潜在的な特徴量を取得する技術(今回ならノートの潜在特徴量とユーザの潜在特徴量)。以前は特異値分解が主流だったが、データが欠損しているマスを0として組み込まなくてはならないことなどで特徴量の推測に影響を与えてしまうことなどが課題だった.
ところがこのMatrixFactorizationでは、データがない箇所は無視して扱える点において優れている.

そもそもはKaggleで開催されたNetflixのおすすめ映画を決めるコンペで、各ユーザにおすすめする映画を決めるアルゴリズムとして生まれたが、今回のCommunityNotesではユーザ固有のおすすめ度合いが高いものを除去する方向で活用している。

### 手法

1. 行列のN(mxk),U(kxn)が行列M(nxm)を構成するとして各要素をランダムな値で初期化.kは決めとく.
1. NとUを掛け合わせる
1. 行列Mのうちデータが欠損していないデータでのみ、掛け合わせた値と比較した誤差の合計から勾配法でNとUの要素を更新
1. 条件が満たされるまで、2~を繰り返す

# 良いノートの決まり方

上記のMatrixFactorizationを実行すると下記の式の$\mu$,$i_u$,$i_n$,$f_u$,$f_n$が定まっていく. $\mu$は全体的な評価のズレる方向(みんないい方に評価しやすいかや悪い方向に評価しやすいかを吸収)、$i_u$はユーザの評価のズレる方向(常に良い評価をつけがちか、常に悪い方につけがちかを吸収)、$i_n$が今回最も欲しいノートの価値、$f_u \cdot f_n $がユーザとノートの相性.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920854/eeb1625e-16dd-25de-6ad2-359d980ad0fb.png)
画像は
https://vitalik.ca/general/2023/08/16/communitynotes.html
より引用

$\mu$は全体のずれ方なので一旦置いておく.

通常は$f_u \cdot f_n $を求めたい.なぜならユーザにおすすめできる具合の評価値なので、この値が高いノートがおすすめできるノートだからだ。
しかし、コミュニティノートでは、全ユーザが良いというものほど良いノートとされる。

今回のポイントは$f_u \cdot f_n $が小さいノートほど、他の値が大きくなれるということ。
つまり、ユーザの嗜好に反応しやすいノートは$f_u \cdot f_n $が大きく、$i_n$, $i_u$が小さくなり、
逆にユーザの嗜好に関係ないのに評価が高い場合は、$f_u \cdot f_n $の値が小さく、$i_n$, $i_u$が大きくなるということ. このうちユーザが高くしやすいかどうかに依存しないなら、$i_n$つまりノート自体がそもそも評価されやすく、価値のあるものということがわかる。

# 分布

論文によれば$f_n,f_u$は1次元を使った評価をして、特に指定していないのに、自然と政治的な嗜好性と結びついた様子。
実運用上、何次元にしているかはコードを見る必要があり。

![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920854/16df2aa9-f7aa-1289-43fc-e0654fa0cf09.png)
画像は https://arxiv.org/abs/2210.15723 より引用
縦軸は$i_n$、横軸は$f_n$. 縦軸は高いほどよい.

この画像で、両端は$f_n$の絶対値が高い状況.真ん中の部分は多くのユーザに良いとされるノートたち、逆に下側は広いユーザに悪い評価がつけられている品質の低いノートということ。

論文では、実際にノートを導入したことで効果があったか、抑えられたかなどの評価も実施している.
実際に運用でコミュニティーノートが付与されることで、比較対象のグループと比べて25%~34%のいいねやリツイートが抑制されたとのこと.

![ss2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920854/254d6619-891e-34b1-8c8b-3852a8a20a71.png)
画像は https://arxiv.org/abs/2210.15723 より引用
ローカルでGitのベアリポジトリを運用する

# ベアリポジトリの作成
```bash
git init -bare
```

# ベアリポジトリ側の初期ブランチ名の変更
ベアリポジトリの初期ブランチ名はmasterのため、VScode(mainブランチ)でpushするとブランチ名のずれが発生する。
ベアリポジトリ側の変更は以下のコマンド。
```bash
git config --global init.defaultBranch main
```
参考
https://parashuto.com/rriver/tools/change-git-default-branch-name
https://yuki.world/git-clone-nonexistent-ref-error/
DBのパフォーマンスチューニングでせっかく貼ったインデックスが効かないパターン７選

## インデックスとSQL
パフォーマンスチューニングでまず思い浮かべられるインデックス
正しく使えば効果が大きいが、使い方を間違えると全く意味がなくなってしまう
インデックスが効かないパターンをご紹介します
### インデックス列に演算を行っている

```visual-basic
SELECT *
FROM SomeTable
WHERE column * 1.1 > 100;
```

インデックスを作成した列はSQLにおいて「裸」で用いるのが原則。
インデックスの中で保持されているデータはあくまで「column」に対してであって「column*1.1」ではない。

回避するためには
```visual-basic
WHERE column > 100/1.1
```
とする
### 索引列に対してSQL関数を適用している

```visual-basic
SELECT *
FROM SomeTable
WHERE SUBSTR(column, 1, 1) = 'word';
```

理由は同じで、インデックスの中に存在する値は「column」であって「SUBSTR(column, 1, 1)」の値ではないから。

### IS NULL述語を使っている

```visual-basic
SELECT *
FROM SomeTable
WHERE column IS NULL
```

B-treeインデックスは一般的にNULLについてはデータの値とはみなさず、保持していない。
なのでIS NULLやIN NOT NULL述語に対しては有効ではない。

### 否定系を使っている

```visual-basic
SELECT *
FROM SomeTable
WHERE column <> 100;
```

否定系はインデックスを利用できない

### ORを用いている

```visual-basic
SELECT *
FROM SomeTable
WHERE column = 99 OR column = 100;
```

ORを用いた場合はインデックスが利用されない。

INで書き換えることで回避できる

```visual-basic
WHERE column IN (99, 100);
```

### 後方一致、または中間一致のLIKE述語を用いている

```visual-basic
SELECT *
FROM SomeTable 
WHERE column 
LIKE '%word';
```

や

```visual-basic
SELECT *
FROM SomeTable 
WHERE column 
LIKE '%word%';
```

はインデックスが効かない

↓のように前方一致はOK。

```visual-basic
SELECT *
FROM SomeTable 
WHERE column 
LIKE 'word%';
```

### 暗黙の型変換を行なっている

columnが文字列で定義されているとする

```visual-basic
SELECT *
FROM SomeTable 
WHERE column = 10;
```

は、データ型が異なるのでNG

↓ならOK

```visual-basic
SELECT *
FROM SomeTable 
WHERE column = '10'
```

```visual-basic
SELECT *
FROM SomeTable 
WHERE column = CAST(10, AS CHAR(2));
```

## インデックスに関する注意事項

### 主キーおよび一意制約の列には作成不要

DBMSは主キー制約や一意制約を作成する際、内部的にはB-treeインデックスを作成している。

二重にインデックスを作成する必要はない。

### インデックスは更新性能を劣化させる

インデックスはテーブルとは独立したオブジェクトとしてDBMS内部に保持されている

そのため、インデックスが作成されている対象の列値が変更されると、インデックス内に保持している値も変更する必要がある。

インデックスを作成すればするほど、当該テーブルに対する更新性能が劣化していく。

無駄なインデックスは作成しないようにする。
### 定期的なメンテナンスを行うことが望ましい

テーブルのデータが更新されていくt、長期的には構造が崩れて性能が劣化していく。

そのため運用において定期的なメンテナンスを行う、具体的にはインデックスの再構築を行うことが性能を維持するためには望ましい。
## まとめ
インデックスが効かないパターンをご紹介しました。
ルールとマナーを守って正しくインデックスを貼りましょう。
【AWS】「置き換えタスクセットのデプロイ」で一向に終わらない時は環境変数をチェックすべし

# エラー内容
AWS Codedeployを実施したところ、「置き換えタスクセットのデプロイ」が33%のところで止まってしまい一向に進まなくなりました。本記事ではどのような解決したか記載します。

# 原因
半年ほど前にも、別の原因でこの現象に陥りました。エラーのログが見当たらないのでなかなか苦戦します。。
そのときにいろいろ原因は調査し記載したのですが、いずれでもなかったです。ご参考までに。
[【AWS】Codedeployのタイムアウトエラーにより「置き換えタスクセットのデプロイ」が一向に終わらない件の対応方法](https://qiita.com/Ryo-0131/items/fac616e4889f19643b62)

今回の原因は、`env`ファイルでした。
デプロイが失敗するとついELBやデプロイグループなどAWSリソースの問題かと気にしてしまうのですが、がっつりソースコードに問題がありました。

ビルドしたソースはFASTAPIのコード。以下`config.py`がありました。


```config.py
from pydantic import BaseSettings


class Settings(BaseSettings):
    db_user: str
    db_password: str
    db_host: str
    db_port: Union[int, str] = 3306
    db_name: str

    class Config:
         env_file = ".env"

    @sample
    def SQLALCHEMY_DATABASE_URI(self) -> str:
        SQLALCHEMY_DATABASE_URI: str = (f'mysql://{self.db_user}:{self.db_password}@{self.db_host}:'
                                        f'{self.db_port}/{self.db_dbname}')
        return SQLALCHEMY_DATABASE_URI
```

`config.py`についての公式ドキュメントはこちら：[Settings in another module](https://fastapi.tiangolo.com/advanced/settings/#settings-in-another-module)

FastAPIアプリケーション内で環境設定や設定情報を管理するためのPythonモジュールです。アプリケーションの設定情報を一元管理するもので、環境変数や`.env`ファイルなどから設定情報を読み込みます。

ビルド時に`buildspec.yaml`で`.env`からDB環境変数が渡るようになっていたのですが、その`.env`に`db_user`たちを書いていなかったのです...（一旦使わなくなり`.env`から消してしまっていたため）。

`Settings`クラスの`db_user`や`db_password`などの属性は`.env`ファイルから環境変数を読み込んで設定されるため、`.env`ファイルに必要な環境変数が設定されていない場合、これらの属性には値が設定されず、デプロイが失敗してしまったのです。アプリケーションが正しく動作せず、デプロイプロセスが途中で停止してしまうんですね。

# 解決方法
`.env`ファイルに必要な環境変数を設定することで、デプロイが正常に完了しました。
仮に使用しない環境変数だとしても、`Settings`クラスに書いたままの状態で`.env`から消すとこうなるんですね。AWS CodeDeployが「置き換えタスクセットのデプロイ」中に途中で停止する問題に遭遇した時は、一度環境変数が正しく設定されているか確認するのも大事、、ということですな。
GitLab / GitHubのSSH接続方法

# TL;DR
1. `ssh-keygen`で秘密鍵・公開鍵を生成
2. 公開鍵をGitLab / GitHubに登録する
3. ssh接続用設定ファイル(~/.ssh/config)を作成し、SSH接続できるか検証する


## 環境
WSL(Ubuntu 22.04) on Windows11 home

# 1. 秘密鍵・公開鍵の生成
```bash
$ mkdir ~/.ssh
$ cd ~/.ssh
$ ssh-keygen -t rsa -b 4096
```
この後パスワードの入力を求められるがENTERでもOK（パスワードなしの鍵が生成される）
`ls`コマンドでフォルダ内を見てみると`id_rsa`（秘密鍵）と`id_rsa.pub`（公開鍵）ができている。

# 2. keychainへ登録
※GitLabへの接続には必須。
`keychain`がUbuntuにインストールされていない場合、以下を実行。
```bash
$ sudo apt-get install keychain
```
生成した秘密鍵`id_rsa`を`keychain`に登録する。
```
$ /usr/bin/keychain -q --nogui ~/.ssh/id_rsa
$ source $HOME/.keychain/$(ls $HOME/.keychain/*-sh)
```



# 3. Git Lab / Git Hubへの公開鍵の登録
### Git Labの場合

1. 左上の自分のアイコンをクリック
1. 「preference」をクリック
1. 左スライダーバーを開き、「SSH key」を開く
1. 「Add new key」を押下、公開鍵を張り付ける

![gitlab_preference.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293943/124de3b0-c862-983b-6709-9fa6472fc2bb.png)
↓
![gitlab_preference.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293943/22d2bff5-f1f4-7df8-4635-2eaa215bcb05.png)
↓
![gitlab_sshkey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293943/5fa680d8-633e-a545-cb11-7c8c775e82a5.png)

### GitHubの場合
1. 右上の自分のアイコンからサイドバーを開く
1. 「Settings」をクリック
1. 左スライダーバーから、「SSH and GPG keys」を開く
1. 「New SSH key」を押下、公開鍵を張り付ける

![hub.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293943/71e6893c-aa4b-7698-3210-5115898f3ddf.png)
↓
![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293943/00b77ba8-9c75-4600-0337-e7fb77845932.png)


# 4. テスト接続
`~/.ssh/config`へ記載。
```
Host gitlab.com
        Hostname gitlab.com
        User git
        IdentityFile ~/.ssh/id_rsa
        TCPKeepAlive yes
        IdentitiesOnly yes

Host github.com
        Hostname github.com
        User git
        IdentityFile ~/.ssh/id_rsa
        TCPKeepAlive yes
        IdentitiesOnly yes
```
### テスト接続
GitLabへの接続
```bash
$ ssh gitlab.com
```
以下のレスポンスが返ってこれば成功。
```
PTY allocation request failed on channel 0
Welcome to GitLab, @(ユーザ名)!
Connection to gitlab.com closed.
```
同じくGitHubへの接続
```bash
# GitHubへの接続
$ ssh github.com
```
以下のレスポンスが返ってこれば成功。
```
PTY allocation request failed on channel 0
Hi (ユーザ名)! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
```