OmniAICreator/Qiita-1.07M huggingface dataset:
Prismaを使用したデータベース変更に伴う既存データの移行 ~スクリプト編~

## はじめに
Prismaを使用したデータベースのスキーマ変更やデータの再構築を行う際に効果的なデータ移行の方法についてご紹介します。今回ではスクリプトを使用した方法に焦点を当てて説明します。

## スクリプトファイルを使用したデータ移行
今回はUserテーブルの内容を新しくAccountテーブルに移行させ、関連付けするようにします。
```:schema.prisma
// 変更前 
model User {
  id       String     @id
  email    String     @unique
  name     String
}

```
```:schema.prisma
// 変更後 
model User {
  id          String   @id
  account     Account  @relation(fields: [accountId], references: [id], onDelete: Cascade)
  accountId   tring    @unique
}

// 新たに追加
model Account {
  id       String     @id
  email    String     @unique
  name     String
  user     User?
}
```
新しくマイグレイトしたファイル下にスクリプトファイルを作成し、PrismaClientを使用してデータ移行を行っていきます。
### 1. ライブラリのインポート
必要なライブラリをインポートします。次に、Prisma Clientのインスタンスを作成します。

```typescript:script.ts
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
```
このインスタンスを使用してデータベースにクエリを発行します。


### 2. メインの処理関数の定義
メインの処理を行う非同期関数を定義します。

```typescript:script.ts
async function main() {
  // 処理内容
}
```
この関数内で、データベースからデータを取得し、処理を行います。

#### 2.1. トランザクションの使用
メイン処理では、トランザクションを使用して複数の操作をまとめます。

```typescript:script.ts
await prisma.$transaction(async (tx) => {
  // トランザクション内での処理
});
```
トランザクションを使用することで、複数のデータベース操作をまとめて、データの整合性を保ちます。

#### 2.2. データの取得と操作
トランザクション内で、データベースから必要なデータを取得し、操作を行います。

```typescript:script.ts
const users = await tx.user.findMany();
for (const user of users) {
  // データの操作
}
```
ここでは、既存のユーザー情報を全て取得し、それぞれのユーザーに対して操作を行います。

#### 2.3. データの作成と更新
取得したデータを元に、新しいデータを作成したり、既存のデータを更新します。

```typescript:script.ts
const accountId = ulid()
await tx.account.create({
  data: {
    id: accountId,
    email: user.email,
    name: user.name,
  },
});

await tx.user.update({
  where: {
    id: user.id,
  },
  data: {
    accountId: accountId,
  },
});
```
ここでは、新しいアカウントを作成し、ユーザー情報を更新して関連付けます。

### 3. スクリプトの実行と後処理
最後に、メイン処理を実行し、エラー処理とPrisma Clientの切断処理を行います。

```typescript:script.ts
main()
  .catch(async (e) => {
    console.error(e);
    process.exit(1);
  })
  .finally(async () => await prisma.$disconnect());
  ```
メイン処理の実行後には、エラーが発生した場合の処理やPrisma Clientの切断を行います。











#### 3.1. スクリプトの実行
package.jsonのscriptsに実行用のコマンドを追加します。

```json:package.json
"scripts": {
  "data-migration:script": "tsx ./prisma/migrations/script.ts"
}
```
#### 3.2 デプロイ時の実行
デプロイ時に上記のコマンドを実行することで、データ移行を完了させます。

## スクリプトを使用したデータ移行のメリット

#### 柔軟性
スクリプトを使用すると、必要に応じてデータの再定義や操作を行うことができます。例えば、新しいデータフィールドを追加したり、特定の条件を持つデータのみを移行することが可能です。

#### データ再定義
スクリプトを使用すると、データの再定義を行うことができます。例えば、既存のデータを新しい形式に変換したり、関連付けを調整したりすることができます。

## スクリプトを使用したデータ移行のデメリット
#### デプロイとスクリプト実行の同時性
スクリプトはデプロイと同時に実行する必要があります。これにより、デプロイのタイミングやスクリプトの自動実行を制御する必要があります。

#### 手動実行の可能性
自動実行されない場合は、デプロイ時にスクリプトを手動で実行する必要があります。これにより、手動作業やデプロイの段階分けが必要になる場合があります。

#### スクリプトの管理
スクリプトを適切に管理し、バージョン管理や適切な環境で実行する必要があります。また、スクリプトの複雑性が増すと管理が難しくなる可能性があります。

## 終わりに
データ移行は、データの消失や破損の危険性を伴う重要な作業です。そのため、慎重な実行方針を立てることが不可欠です。適切なバックアップ戦略やテスト環境での検証を行うことで、データ移行に伴うリスクを最小限に抑えることができます。また、スクリプトやクエリの検証、トランザクションの確保なども重要な要素です。データの安全性と正確性を確保しながら、効果的なデータ移行を行うためには、事前の計画と慎重な実行を心がけましょう！
Alienwareを有線LAN接続したときにアップロードだけ異常に遅いときの対処方メモ

Alienwareを有線LAN接続したときに、アップロードだけ異常に遅いときの対処方メモ

1. `Windows + R`
2. `services.msc`を実行
3. `Killer Network Service`をダブルクリック
4. `Stop`でサービスを停止

参考
https://www.intel.co.jp/content/www/jp/ja/support/articles/000058995/ethernet-products/intel-killer-ethernet-products.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237839/53e8306d-501f-ddf6-fe20-605fba0f9d0d.png)
GCP(Google Cloud Platform)のプロジェクトでサービスアカウントを作成する　

## 概要　

[GCP](https://console.cloud.google.com/)のプロジェクトで新規サービスアカウントを作成して、キーJSONをダウンロードする手順をまとめました。
プロジェクトの作成方法は[こちら](https://cloud.google.com/resource-manager/docs/creating-managing-projects?hl=ja)を参照してください。　

## 手順

[プロジェクト](https://console.cloud.google.com/)のナビゲーションメニューから「IAMと管理/サービスアカウント」を選択します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61849/e9155abd-b393-d385-d3c5-538bed3e2d77.png" width=500>

上部メニューから「+サービスアカウントを作成」をクリックします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61849/06d30648-8ae0-d556-5de0-3f5abd300f6c.png" width=500>

サービスアカウント名を設定します。
ここでは例として「my-google-api-tool-box-sa」としています。
省略可の項目は、特に設定せず完了を押してしまっても問題ありません。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61849/7f500d39-facd-e763-6324-35457733ef57.png" width=500>

サービスアカウントのページに作成したアカウントが追加されました。
次に、「メール」のリンクをクリックします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61849/69a4ff1a-ee93-a20c-a7e8-229ccfcd2745.png" width=500>

サービスアカウントの詳細の「キー」タブをクリックします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61849/3cffc569-71ce-2e06-e182-e4e068ea5302.png" width=500>

鍵の追加から、「新しい鍵を作成」をクリックします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61849/20c2ddf8-c849-3242-daf4-8c667cf9ef25.png" width=500>

キータイプはJSONを選択してください。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61849/6b4cc3dd-f757-1dc8-6c77-059e9456003a.png" width=500>

以下ダイアログが表示されると、手元の端末にjsonファイルがダウンロードされます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61849/5fa66eee-e12a-f631-975b-3b76b24aa334.png" width=500>

以上で完了です！
ダウンロードしたファイルは誤って公開したりすることがないように、厳重に保管してください。
npm ERR! enoent ENOENT: no such file or directory, lstat 'C:\Users\username\AppData\Roaming\npm'のエラーを解決する。

## 解決方法
npmを最新化する。

### バージョン
node: v20.11.1
npm: 10.2.4 -> 10.5.0
windows: Windows 11 Home 23H2

### 具体的手順
Windowsの環境で実施します。

(1) 下記を実施し、node, npmが正しくインストールされているか、PATHが通っているかを確認。
```bash
node -v
npm -v
```

(2) PATHが通っていたら、npmを最新化。
```bash
npm install -g npm
```

(3) 一応cacheも消す。
```bash
npm cache clean -f
```

(4) 再度npm installすると同エラーは出なくなる。

<br>
引用元：

https://stackoverflow.com/questions/77152589/cannot-find-npm-on-appdata-roaming

## 問題
npm installで下記エラーが起きた。
```
npm ERR! code ENOENT
npm ERR! syscall lstat
npm ERR! path C:\Users\username\AppData\Roaming\npm
npm ERR! errno -4058
npm ERR! enoent ENOENT: no such file or directory, lstat 'C:\Users\username\AppData\Roaming\npm'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent
```

詳細なログを見てみると、以下のようになっていた。
```
...
35 http fetch GET 200 https://registry.npmjs.org/cmake-js 111ms (cache revalidated)
36 timing arborist:ctor Completed in 0ms
37 timing command:exec Completed in 150ms
38 verbose stack Error: ENOENT: no such file or directory, lstat 'C:\Users\username\AppData\Roaming\npm'
39 verbose cwd C:\Users\username\Documents\Programing\JavaScript\talk\whisper.cpp
40 verbose Windows_NT 10.0.22631
41 verbose node v20.11.1
42 verbose npm  v10.2.4
43 error code ENOENT
44 error syscall lstat
45 error path C:\Users\username\AppData\Roaming\npm
46 error errno -4058
47 error enoent ENOENT: no such file or directory, lstat 'C:\Users\username\AppData\Roaming\npm'
48 error enoent This is related to npm not being able to find a file.
48 error enoent
49 verbose exit -4058
50 timing npm Completed in 450ms
51 verbose code -4058
52 error A complete log of this run can be found in: C:\Users\username\AppData\Local\npm-cache\_logs\2024-03-23T06_10_20_138Z-debug-0.log
```

どうやら、AppData/Roaming配下のnpmが見つからない。
```
47 error enoent ENOENT: no such file or directory, lstat 'C:\Users\username\AppData\Roaming\npm'
```

これを、先述の方法で解決した。
Promptアップグレード

以前の2つのPromptに関する記事は、それぞれ提示語のルールの提案と具体的なフレームワークの観点からPromptの使用テクニックを説明しました。今回はフレームワークスタイルの提示語をさらにアップグレードすることになります——構造化提示語です。

構造化の定義:
情報を組織化し、特定のパターンとルールに従って、情報を効果的に理解しやすくすること。

構造化提示語の文法:
この構造は、Markdown文法とYAML文法をサポートしており、さらにはプレーンテキストで手動でスペースや改行を入れることも可能です。Markdown文法の使用を推奨します。一方で、様々なノートアプリに統合して表示しやすく、またChatGPTのトレーニングコーパスにこのタイプの素材がより多いことを考慮するためです。

構造化提示語の構造:
以下の情報は、自分の必要に応じて追加または削除できます。一般的なモジュールには以下が含まれます:
```markdown
# Role: <name> : 特定の役割を指定することで、GPTが対応する分野で情報を出力することに集中します
## Profile: author/version/description : Creditとバージョン履歴の記録
## Goals: Promptの目標を一言で述べ、GPTがAttentionを集中させます
## Constrains: 制約条件を記述します。これは実際にはGPTに枝刈りをさせ、不必要な枝の計算を減らすのに役立ちます
## Skills: スキル項目を記述し、対応する分野の情報の重みを強化します
## Workflows: 重要な部分の中でも最も重要な部分、あなたがPromptにどのように対話し出力してほしいかです
# Initialization: 冷やかしスタート時の対話、また重要なポイントに注意を促す機会です
構造化提示語の例:
# Role: 軟件技術翻訳専門家
## Profile:
### Author: gsw
### Version: 1.0
### Language: 日本語
### Description: 私は、中国語の技術記事をLanguageに指定された技術記事に翻訳するAIロールです。
## Goals: 中国語の技術記事をLanguageに正確に翻訳します。
## Constrains:
1. コード、URLアドレスなどの非中国語コンテンツは翻訳しないでください
2. コードを専用のコードブロックで表示します
4. 翻訳時に自分の見解を加えることはありません。ただし原文を翻訳します
5. 原文の内容を省略せず
6. 翻訳後、他の質問はしません
7. 翻訳完了後、最後の行に「(Translated by GPT)」と追加します
## Skills:
1. 強力なソフトウェア技術知識の取得と統合能力を持つ
2. 広範なプログラミング言語の知識ベースを有し、質問と回答の技術をマスターしている
3. 美的なレイアウトを有し、番号、インデント、区切り線、改行などを使用して情報のレイアウトを美しくします
4. 比喩を使用してユーザーに知識を理解させるのが得意
5. 文字を大切にし、無駄なことは言わない
## Workflows:
1. ユーザーに「タイトル：[]」形式で翻訳するタイトルを指定させます
2. ユーザーに「内容：[]」形式で翻訳する内容を指定させます
3. ユーザーが指定したタイトルと内容に基づいて翻訳を行います
## Initialization: <Role>として、<Skills>を持ち、<Constrains>に厳密に従い、<Language>を使用し、<Workflows>に基づいて結果を出力します。
次に、SemanticKernelを組み合わせて構造化されたプロンプトを使用した翻訳ツールです。これにより、中国語のブログを簡単に様々な言語に翻訳できます。次のブログでは、この部分のコードを共有します。
```
![alt 画像](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRCW6ztMH9hjp2DUMM0q8Mr83UoiaWwWCnsiapMZibZSakpWdRha6asN5OW1qDibmnsLk46MfDYTjaXGFw/640?wx_fmt=png&from=appmsg)

(Translated by GPT)

元のリンク：https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247487942&idx=1&sn=47517c7e0c0264318876c8c3fd23d2fd&chksm=9f004eeca877c7fa00c0105578aaf2d34daf19a6e9ae2f00ff29580c4b3647b350985a01758d&token=1081887653&lang=zh_CN#rd&wt.mc_id=MVP_325642
【Flutter】画像をボタンみたく動作させる

## imagesディレクトリを作成

プロジェクトファイルの直下にimagesディレクトリを作成して、画像を置いておきます。 

## pubspec.yamlに設定を追記

`pubspec.yaml`
```
flutter:
  assets:
   - images/
```

upgradeします。
```
$ flutter pub upgrade
```

## 画像を配置する

画像をボタンのように動作させる方法は2種類。
`GestureDetactor`か`Inkwell`を使用します。
どちらもタップした際の動作を設定できるので、ボタンのように動作するが、個人的にはスプラッシュ効果がある`Inkwell`の方がボタンとしてはいい感じ。
詳しくは[こちらのサイト](https://migisanblog.com/flutter-inkwell-gesturedetector/)を見るとわかりやすく書いていただいてます。

`GestureDetector`
```
GestureDetactor(
  onTap: () {
    // タップ時の動き
  },
  child: Image.asset('imageディレクトリに置いた画像のパス'),
)
```

`Inkwell`
```
Ink.image(  
  width: 100,  
  height: 30,  
  image: const AssetImage('imageディレクトリに置いた画像のパス'),  
  child: InkWell(  
    borderRadius: BorderRadius.circular(5),  
    onTap: () {},  
    splashColor: const Color(0xff000000).withAlpha(30) 
  ),  
)
```

## 完成
例としてLINEのログインボタンを使用しました。
![スクリーンショット 2024-03-06 16.05.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669888/31b8d093-819a-71b6-667b-22c3613cdca0.png)



参考
https://migisanblog.com/flutter-inkwell-gesturedetector/

https://kawaedomain.com/2024/01/26/【flutter】アイコン・画像・テキストをボタンにした/
HTML: onloadを連発するとどうなるか

以下のhtmlでは何が起こるのでしょうか?
```html
<body onload="document.write(0)">
<img onload="write(1)" src=data:image/gif;base64,R0lGODdhAQABAAAAAAA>
<svg onload="write(2)"></svg>
<script>
window.onload=a=>document.write(3)
</script>
<iframe onload="outerHTML=4"></iframe>
<object onload="write(5)" data="data:,"></object>
<input onload="write(6)" type=image src=data:image/gif;base64,R0lGODdhAQABAAAAAAA>
<script src="data:," onload="write(7)"></script>
```
`01234567`が表示されると思ったら大間違いです。本当です信じて下さい。**発動順はBrowserによって**変わります。配置場所は無関係っぽいです。body要素のonloadはscript要素により書き換わっています。逆にhead要素にscript要素を記述している場合はbody要素のonloadがそのまま発動します。
さて、そうなると発動順に数字が表示されるのでしょうか? あいにくとそういう訳にはいきません。
何と最終的に1文字のみ表示されます。何でもしませんから信じて下さい。
どうして1文字のみになるかと考察してみると、`document.write`(略して`write`)を実行すると実質htmlが全て書き替えられるせいで、他のonloadが消し飛んでいると結論付けられます。発動順の検証例は以下の通り。
```html
<body onload="console.log(0)">
<img onload="console.log(1)" src=data:image/gif;base64,R0lGODdhAQABAAAAAAA>
<svg onload="console.log(2)"></svg>
<script>
window.onload=a=>console.log(3)
</script>
<iframe onload="console.log(4)"></iframe>
<object onload="console.log(5)" data="data:,"></object>
<input onload="console.log(6)"type=image src=data:image/gif;base64,R0lGODdhAQABAAAAAAA>
<script src="data:," onload="console.log(7)"></script>
```
ではimg要素のみを複数並べるとどうなるのでしょうか?
```html
<img onload="write(1)" src=data:image/gif;base64,R0lGODdhAQABAAAAAAA>
<img onload="write(2)" src=data:image/gif;base64,R0lGODdhAQABAAAAAAA>
<img onload="write(3)" src=data:image/gif;base64,R0lGODdhAQABAAAAAAA>
```
先頭のimg要素のonloadから処理されていきます。最終的に1のみが表示されます。input要素の場合も同様っぽい臭いです。
ではsvg要素を連発すると…
```html
<svg onload="write(0)"></svg>
<svg onload="write(1)"></svg>
<svg onload="write(2)"></svg>
```
何と毎回結果が異なります。1文字だけなのは変わりませんが、どの文字になるかは不確定です。object要素でも同様の結果でした。
iframeの連発ですか? そんなもの知ってどうするんですか? いやらしいですね…。別に面白い事は何もありませんよ…ウヒヒヒ。
## 余談
img要素に埋め込む画像次第で結果は変わるかもしれません。svg要素についても中身次第で結果が変わるかもしれません。
ちなみに前述の**img要素の画像はイカサマ仕込みの胡散臭いインチキ画像なのでonload不発**になる可能性があります。臭くない画像は以下の通り。
```html
<img src=data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAA>
<img src=data:image/gif;base64,R0lGODdhAQABAPAAAP///wAAACwAAAAAAQABAAA>
```
これらのonloadの特性を利用して何か面白い活用法を編み出してみて下さい。個人的にはsvg要素によるJavaScript召喚でshort codingするが面白いですね
## 実験環境
窓s 10、偶狂苦労夢 最新版
Server-Side Rendering(SSR)とは? 何が改善するの？

## Server-Side Rendering(SSR)とは? 何が改善するの？

昨今Server-Side Renderingが主流になりつつあるので、ここでまとめようと思います。

<div style="display: flex; justify-content: space-around;">
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618478/b21e7143-c515-3d90-2429-715429c8b3ad.png" alt="Server Heavy Lifting">
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618478/52ddfb2f-a48a-3118-ec4c-6848c4b2c3ca.png" alt="Lazy Browser" style="width:250px;height:300px;">
</div>


従来では、JS、CSS、HTMLをブラウザー側に送っていましたが、SSRはサーバー側でこれらを元にHTMLの全体を作成し、ブラウザーへ送リます。従って、ブラウザー側で行なっていた処理をサーバー側で事前に完了させてしまうため、これまでよりも素早くページが表示される事になります。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618478/f7dc75ee-7de2-479b-10ae-899b8add2f4b.png">


また、SSRにより検索結果に出やすくなるというメリットもあります。従来のClient-Side Renderingをベースにしたサイトが仮にサーバーから送られてくるコンテンツを使って実際のページを表示する仕組みであった場合、サーチエンジンCrawlerは、Webページが最も見せたいはずの中身がない状態でIndex付をしてしまう可能性があります。つまり、本当は料理の紹介をするWebpageなのに、一般的な情報サイトとして認識されてしまう可能性すらあります（Google等はそうならないよう、サーチエンジン自体の質を高めていますが）。

簡単な言葉でまとめると、Webサイトのコンテンツが進化するのに伴い、扱う情報量が昨今増えているため、サーバー側に重労働させる事により、ブラウザー側での仕事が少なくなたっため、どんなブラウザーでも遅延の少ない、使いやすいWebsiteが増えてきているという事です。
クエリの最適化技術の覚え書き


# はじめに
クエリの最適化技術は、ユーザーの問いかけをより効果的に検索エンジンへ渡す方法を提供します。これには、クエリの分解、拡張、構造化などの技術が含まれます。

本記事では、RAGの応答精度を高めるための技術の選択について整理を目指します。

## 関連用語まとめ

| 用語                     | 説明                                                 |
|------------------------|----------------------------------------------------|
| 検索クエリ               | ユーザーからの入力を検索エンジンが解釈するための文字列や命令                 |
| クエリ構造化             | ユーザーの入力から特定の検索・フィルタリング属性を推測する技術               |
| クエリ分解               | 複数の質問を含む入力を、個別のクエリに分割する技術                           |
| クエリ拡張               | クエリの表現を変えることで、関連する結果の取得確率を高める技術               |
| クエリルーティング       | 複数のインデックスから、関連性の高いものにクエリを送る技術                 |
| ステップバックプロンプト  | より抽象的な質問を生成して、検索の質を向上させる技術                       |

# クエリ分析 (Query analysis)

クエリ分析は、検索クエリの最適化に役立ちます。以下のようなケースに有効です

- データの特定のフィールドに対して検索やフィルタをサポートするリトリーバーを使用する場合
- ユーザー入力に複数の異なる質問が含まれている場合
- 関連情報を取得するために複数のクエリが必要な場合
- 検索品質が表現方法に敏感な場合
- 複数のリトリーバーを検索する可能性があり、ユーザー入力がそれらのいずれかを指している可能性がある場合

| 問題                      | アプローチ                                                                       | クエリ例                                                                |
|-------------------------|--------------------------------------------------------------------------------|-----------------------------------------------------------------------|
| 特定フィールドへのフィルタリング | ユーザーの質問からキーワードやフレーズを抽出し、特定のフィールドに関連付ける。                | 「Javaに関する記事」→ `field:programming_language "Java"`               |
| 複数の質問の分解           | ユーザー入力を個別のクエリに分解し、それぞれに対して検索を行う。                              | 「JavaとPythonの最新トレンドは？」→ `query1:"Java 最新トレンド", query2:"Python 最新トレンド"` |
| 複数クエリの使用           | 異なるキーワードやフレーズを使った複数のクエリを生成し、それぞれに対して検索を行う。                    | 「機械学習の基本」→ `query1:"機械学習 入門", query2:"機械学習 基本"`       |
| 表現の最適化               | 検索クエリの言い回しを最適化する（同義語の使用、関連性の高いキーワードへの置き換えなど）。               | 「自動運転車」→ `query:"自動運転車 OR 自動車 運転支援システム"`            |
| リトリーバーの選択         | ユーザー入力からリトリーバーごとの専門分野に関連するキーワードを識別し、適切なリトリーバーを選択する。 | 「金融市場の最新動向」→ `retriever:financial_data "最新動向"`            |


## 実装アプローチ

| 問題解決のアプローチ          | 実装方法                                                                                         |
|--------------------------|--------------------------------------------------------------------------------------------------|
| 特定フィールドへのフィルタリング | 1. ユーザーの質問を解析して主要なキーワードを識別する<br>2. 識別されたキーワードを基に、検索すべき特定のフィールドを決定<br>3. SQLやElasticsearchのクエリ言語を使用して、選択したフィールドに対するフィルタを適用する |
| 複数の質問の分解           | 1. 自然言語処理技術を用いて、入力された質問を複数の質問に分解<br>2. 分解された各質問に対して独立した検索を行う<br>3. 各検索から得られた結果を集約し、ユーザーに提示                 |
| 複数クエリの使用           | 1. 入力されたクエリの同義語や関連語を生成します。<br>2. 生成された各クエリを用いて検索を行います。<br>3. 各検索結果を統合して最終的な結果セットを作成します。                             |
| 表現の最適化               | 1. クエリに含まれる主要なキーワードに対して同義語や類似の表現を検索<br>2. 元のクエリをこれらの同義語や類似表現を含む複数のクエリに拡張<br>3. 拡張されたクエリを使用して検索を行う|
| リトリーバーの選択         | 1. ユーザーの質問からキーワードを抽出し、それらがどのドメインに属するかを分析<br>2. 分析結果に基づき、最も適切なリトリーバーを選択<br>3. 選択されたリトリーバーを用いて、クエリを実行し結果を取得  |
TypeScript とJavaScriptがブラウザーに現れるまで

### イントロ

TypeScriptやJavaScriptを実装した際、ブラウザーに表示されるまでに背景で起きていることをまとめます。


### プロセス

1. **Transpilation(TypeScriptのみ）**：TSは実装前に、TypeScript Compiler(tsc)でJSへと変換（Transpile)される
1. **Bundling**：WebpackやRollupを使って、１つのファイルに統合（Bundle)される。そうすることで、HTTPリクセストの回数を減らせる
1. **Minification**:コメントや空白などの余計な部分をコードから取り除き、コードのサイズを最適化する。これにより、ブラウザでのダウンロードを早くする。
1. **Execution & Compilation**: 最後に、Just-In-Time (JIT) などのエンジンが上記で最適化されたJSコードをブラウザーで実走する。並行して、JSコードはByteCodeというMahcine言語よりもAbstractなフォーマットへ変換している。より頻繁に使われるコード（Hot Path)は、より最適なMachine言語（Bytecode=>Binary)に変換され、Interpreterで実装するよりも高いパフォーマンスを出すことができる。

**Sourcemaps Generation**: これらの他に、TranspileやMinificationの過程で、Sourcemapが構成され、ブラウザーでのDebugが可能になる。このSourcemapは、TranspileやMinificationされたコードと元のコードへと復元したもの（簡単に言えば、オリジナルコードから無駄を省いたもの）

### JIT Compiler


## Bundlingとフレームワーク
BundlingはHTTPリクエストを減らすことができるという点で需要なステップである。Bundlingをせずに、JSコードを実装すると、ファイスの数だけHTTPリクエストが必要となり、ネットワークコミュニケーションやサーバーサイドでのプロセスが追加される（Latencyが追加される）。

イメージとしては、車を使わず人力でモノを運ぶため、何度も往復し、モノを渡す側が何度も同じような作業を繰り返さなければいけない現象に類似する。

従って、Bundlingにより、Webサイト（Webアプリ）のローディングが素早くなり、全体としてパフォーマンスが向上する。


**React.js**は裏でWebpackがBundleツールとして使われているため、Create React App(CRA)で作成されたWebアプリは自動的にWebpackでBundleされる事になる。
```
npx create-react-app my-app
```

勿論、<i>eject</i>でこのデフォルト設定を上書きすることもできるが、一度このコマンドを使うとConfigファイルやWebpackの設定をプロジェクトにコピーし、以降デフォルト設定を無視する事になるので、注意点としては、一度<i>eject</i>を使ったら元に戻れないということです。

```
npm run eject
```

代替策としては、<a href="https://www.npmjs.com/package/react-app-rewired">react-app-rewired</a>がある。
classとextendsで組み込みクラスを拡張させる

ES6からArrayのような組み込みクラスに足して堅牢なサブクラスを作成でき、classとextendsを使用します。

```js
class EZArray extends Array {
  get first() { return this[0] }
  get last() { return this[this.length - 1] }
}

let e = new EZArray(1, 2, 3)
let f = e.map(x => x * x)
e.last  // => 3
f.last  // => 9
```

Arrayにはcontact()、filter()、map()、slice()、splice()というメソッドが定義されています。ES6の仕様では、この5つの配列を返すメソッドはサブクラスのインスタンスを返すとされています。仕組みは以下の通りです。

- ES6以降では、Array()コンスラクタはSynbol.spaciesというSymbol名のプロパティを持つ
- extendsを使ってサブラクスを作るときに、結果として得られるサブクラスのコンストラクタは、スーパークラスのコンストラクタからプロパティを継承する
- map()やslice()のように、新しい配列を作成して、この配列を返すメソッドは、ES6以降では通常のArrayを作成するのではなく、新しい配列を作成するためにnew this.constructor[Symbol.species] ()を呼び出す


#### 参考
https://www.oreilly.co.jp/books/9784873119700/
【備忘録】C++ のg++

CPPコードを実装するにはg++コマンドを使ってcompileしMachine言語（0と1）に変換しますが、そのプロセス背景で起きていることを備忘録としてまとめます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618478/43923d0d-ba54-b4ed-4750-b236a6a880b7.png)


**1）Preprocessing:** Preprocessorが#includeや#defineで定義されたLibraryのソースコードを準備
Command: 'gcc -E main.cpp -o main.i'

**2) Compilation:** Compilerが書いたCPPコードとPreprocessされたコードをAssembly言語へ変換する（Processor Architectureに応じる）
Command: 'gcc -S main.i -o main.s'

**3) Assembly:** AssemblerがAssembly言語化されたコードをMachine言語へ変換する（.oや.objのオブジェクトファイル）このファイルは単独実装一歩手前
Command: 'gcc -c main.s -o main.o'

**4）Linking:** Linkerがオブジェクトファイルと上述のLibraryを繋げ、Executable（Windowsなら.exe、MacやLinuxならa.out）を作る
Command: 'gcc main.o -o hello_world'


このプロセスは、CMakeLists .txtで簡素化・代替でき、

・まず、現在のDirに’CMakeLists.txt’を作る

```
cmake_minimum_required(VERSION 3.10)
project(HelloWorld)
set(CMAKE_CXX_STANDARD 11)
add_executable(hello_world main.cpp)
```

・'mkdir build & cd build'で’build' dirを作り移動

・'cmake ..'で先のCMakeLists.txtを元に、Makefileをbuild内に作成
```
all: hello_world

hello_world: main.o
	g++ main.o -o hello_world

main.o: main.cpp
	g++ -c main.cpp -o main.o
```

・最後に`make`で以下４ステップを実装：
ーPreprocessing: g++ -E main.cpp -o main.i (handled internally)
ーCompilation: g++ -c main.cpp -o main.o
ーAssembly: Part of the compilation step
ーLinking: g++ main.o -o hello_world
Cloud ShellからOCI Functionsをデプロイする時はコンピュート・アーキテクチャを揃えないとエラーが出る

# はじめに
OCI FunctionsをCloud Shellからデプロイしようとしたところエラーが発生したので対処法をまとめてみました。
原因はFunctionsアプリケーション作成時に指定したコンピュート・アーキテクチャとCloud Shellのアーキテクチャが異なっていたためでした。

# 発生したエラー
```shell
# テンプレートから生成
$ fn init --runtime java hello-java

$ cd hello-java

# Functionをデプロイ、ここでエラー発生
$ fn deploy --app helloworld-app
Deploying helloworld-func to app: helloworld-app
Bumped to version 0.0.4
Using Container engine docker
Building image nrt.ocir.io/<namespace割愛>/functionsdemo/helloworld-func:0.0.4 TargetedPlatform:  amd64HostPlatform:  arm64

Error during build. Run with `--verbose` flag to see what went wrong. eg: `fn --verbose CMD`

Fn: error running docker build: Cannot create/use builder instance docker for oci_fn_builder : exit status 125

See 'fn <command> --help' for more information. Client version: 0.6.29
```

# 対処法
エラーメッセージで検索した結果、以下の記事を発見しました。
コンピュート・アーキテクチャが異なっているためエラーが発生していました。
Functionsアプリケーションは GENERIC_X86 で作成していたのですが、Cloud SHell側が ARM になっていたみたいです。

https://medium.com/@anthonyong.tst/resolution-oracle-function-deployment-error-exit-status-125-611339aa8504

Cloud Shellの左上、[アクション] > [アーキテクチャ]からFunctionsアプリケーションで指定した X86-64 に設定を変更したところ、デプロイが正常に完了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2357379/c5415832-4493-2f17-926e-1f9bff870690.png)

# ドキュメントも確認してみる
Cloud Shellのデフォルト・アーキテクチャは以下の通り。どちらが選択されるかはリージョンのリソース次第ということですかね。
>デフォルトでは、アーキテクチャ・プリファレンスは「プリファレンスなし」に設定されています。これを選択すると、クラウド・シェル・セッションは、リージョンで使用可能なハードウェアに応じて、x86_64またはARM (aarch64)アーキテクチャに基づきます。

https://docs.oracle.com/ja-jp/iaas/Content/API/Concepts/cloudshellintro.htm

OCI Functionsを実行するコンピュート・アーキテクチャの指定についてはこちらのドキュメントに記載がありました。
作成したイメージ基づいて適切なシェイプ（アーキテクチャ）でFunctionを作成するように記載されていました。

>OCI Functionsにファンクションをデプロイする場合、ファンクションを実行するコンピュート・インスタンスのプロセッサ・アーキテクチャを指定できます。ファンクションを単一のアーキテクチャ(Armなど)で実行するように制限することも、ファンクションを複数のアーキテクチャ(Armとx86の両方など)で実行できるようにすることもできます。

>関数を実行するプロセッサアーキテクチャーを指定するには、3つの手順があります。

>- アプリケーションを作成し、ファンクションを実行するアーキテクチャをサポートするアプリケーションのシェイプを選択します。ファンクションを実行する単一のアーキテクチャまたは複数アーキテクチャのアプリケーション・シェイプの選択を参照してください。
>- 関数を実行するアーキテクチャに必要な依存関係(子イメージ)を含むイメージを構築します。マルチアーキテクチャ(マルチアーカイブ)イメージの構築および単一アーキテクチャ・イメージの構築を参照してください。
>- 作成したイメージに基づいて、適切なシェイプでアプリケーションにファンクションを作成します。ファンクションの作成を参照してください。

https://docs.oracle.com/ja-jp/iaas/Content/Functions/Tasks/functionsspecifyingcomputearchitectures.htm

# 参考情報

https://medium.com/@anthonyong.tst/resolution-oracle-function-deployment-error-exit-status-125-611339aa8504

https://docs.oracle.com/ja-jp/iaas/Content/Functions/Tasks/functionsspecifyingcomputearchitectures.htm

https://docs.oracle.com/ja-jp/iaas/Content/API/Concepts/cloudshellintro.htm
DjangoでValueObjectを使いたい

# はじめに
以前、:point_down:こんな記事を書きました。
このクラスをDjangoでいい感じに使用できないかを検討したところ、
いい方法を見つけたのでこちらに残しておきます。

https://qiita.com/team7_403_poppin/items/1899c4a2dd0fccb11eed


<!-- 
# Djangoでうまく使うにはどうしたらいいんだろうか
## Repositoryパターンがベター
ValueObjectを頻繁に利用するDDDでは、RepositoryパターンでDBからデータを取得して値オブジェクトに変換してを返すように実装することが一般的だと思います。
今回私の記事ではこのRepositoryパターンで実装する方法は説明しません。

## Djangoのフレームワークに則って作る方が利便性が高い場合
-->

# 何も考えずMoneyクラスを使う場合
私含め、多くの方は以下のようになるのではないでしょうか。
この場合だと、いちいちWalletモデルのamountをMoneyクラスに詰め替えなければいけないため、だいぶ面倒だと思います。

この記事では、詰替えの手間を省く方法を説明します。
```Python:models.py
class Wallet(models.Model):
    amount = models.IntegerField()
  
wallet = Wallet.objects.create(amount=100)
money = Money(wallet.amount) + Money(200)

wallet.amount = money.amount
wallet.save()
```

# 実装方法
今回説明する実装方法はDjango公式の以下のページに記載がありました。
詳しく知りたい方はこちらをご参照ください。
https://docs.djangoproject.com/en/5.0/howto/custom-model-fields/#converting-values-to-python-objects

# Model編
まずは、Moneyクラスをフィールドとして定義します。
書き方は:point_down:こんな感じです。

```Python:models.py
from django.db import models
from django.core.exceptions import ValidationError

class MoneyField(models.IntegerField):
    description = 'お金クラスのフィールド'

    def __init__(self, *args, **kwargs):
        kwargs['validators'] = [self.validate_amount]
        kwargs['blank'] = kwargs.get('blank', False)
        kwargs['null'] = kwargs.get('null', False)
        super().__init__(*args, **kwargs)

    def validate_amount(self, value):
        ''' この部分はMoneyクラスのバリデーションと重複しているので、やり方を検討中 '''
        if value is not None and value < 0:
            raise ValidationError('金額が0以上ではありません。')

    def to_python(self, value):
        if isinstance(value, Money):
            return value
        return Money(value)

    def from_db_value(self, value, expression, connection):
        ''' DBからPythonのオブジェクトに変換する部分 '''
        if value is None:
            return None
        return Money(value)

    def get_prep_value(self, value):
        ''' PythonのオブジェクトからDBに変換する部分 '''
        if value is None:
            return None
        if isinstance(value, Money):
            return value.amount
        return super().get_prep_value(value)
```

実際にModelに定義するときは普通のフィールドと同じ使い方をします。
```Python:models.py
class Wallet(models.Model):
    amount = MoneyField()
```

あとはMoneyクラスと同じ要領で使用できます。
``` Python
wallet = Wallet.objects.create(amount=Money(100))
print(wallet.amount) # -> 100 JPY

wallet.amount = wallet.amount + Money(200)
print(wallet.amount) # -> 300 JPY
wallet.save()
```

# Forms
準備中...

ModelFormsを使えばForm側の定義は不要かもしれません。

# 最後に
DDDではORマッパーを使わないほうがいいと言われていますが、ValueObjectパターンだけを取り入れたいときには便利な機能だと思います。

DBの定義とかドメインモデルやエンティティなど色々複雑な要素が出てきたら、Reposiotryパターンに移行するかを検討する必要があるかもしれませんね。:angel_tone2::angel_tone2:
拡張したEBSボリュームがOS上で認識されない

# 近況
先日発売されたFF7 Rebirthをずっとプレイしています。
まだストーリーが80%くらいで、終わる気配がありません。終わらないでほしい。
2週目のハードモードクリアやトロコンまでやる予定なので、4月に入ってもまだまだ楽しみます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494465/83a5eba1-85c9-1fee-fc2e-57a3ef2511dc.png)
↑
原作
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494465/bb589e11-72e8-d443-b37e-d56351ed6070.png)
↑
今作

デートイベントはユフィでした...
2週目はティファの好感度を上げに行かねば...

# 経緯
お客さんのAWS環境を運用・保守しているチームの方から「拡張したEBSのボリュームが認識されないんですけど、何か情報ありますか？」と投稿があったので、調べてみた際の話になります。

# 起こった事象と環境

起こった事象は記事の題名の通り、「拡張したEBSボリュームがOS上で認識されない」です。
詳しく書くと、AWS上に起動しているEC2インスタンスにくっついているEBSボリュームを拡張した際、AWSコンソール上では問題なく完了したけど、Windowsにログインし、[ディスクの管理]から見ても反映されていなかった...そうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494465/e29883ee-6e58-07ad-10c6-c8c25710677f.png)

なお、EC2作成時にくっついているボリュームをCドライブ、別のEBSボリュームをくっつけてDドライブとしているようです。(今回はDドライブの拡張時にうまくいかなかった)

また、環境としてはm6i.xlargeのインスタンスタイプで、古いインスタンスファミリーというわけでもありませんでした。OSはWindows Server 2016です。

# 調べたこと
AWSのEBS拡張手順に従っているか確認していきました。
↓EBS拡張手順↓
https://docs.aws.amazon.com/ja_jp/ebs/latest/userguide/recognize-expanded-volume-linux.html

また、[ディスクの管理]でディスクの再スキャンを実行しても特に状況は変わらずでした。
(普通の場合はこれで認識される)

いろんな記事を見ていくと、「EC2にちゃんとNVMeドライバー入っていますか?」といった内容がヒットしました。
https://repost.aws/ja/knowledge-center/ec2-windows-volumes-not-showing
なので、下記のコマンドを打ってもらいました。
(コマンドの内容は、 EC2に入っているENAとNVMeドライバーの一覧とバージョンを見るものです)
`Get-WmiObject Win32_PnpSignedDriver | Select-Object DeviceName, DriverVersion, InfName | Where-Object {$_.DeviceName -like "*AWS*" -OR $_.DeviceName -like "*Amazon*"}`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494465/60ddf4c5-9f69-ff91-9647-a439c6a9ff0d.png)

するとどうやら、ENAしか入っていないようでした。
なので、NVMeドライバーが認識されていないことが原因だとわかりました。

# 原因と解決法

【原因】
まずは事象が起きた原因ですが、おそらくこのEC2はオンプレからAWS MGNで移行してきた仮想マシンでした。
なので、NVMeドライバーがもともと入っていませんでした。

【解決法】
ずばりEC2の再起動です。AWSのドキュメントにもしっかり記載されていました。
以下抜粋です。
> AWS NVMe ドライバーがないインスタンスで NVMe ボリュームのサイズを増やす場合、インスタンスを再起動して Windows を有効にし、新規のボリュームサイズを表示する必要があります。

再起動を試せなかった原因としては、お客さんの本番環境のEC2であることから、無許可に再起動できなかったためです。
幸い、このEC2はEventBridgeのスケジュール機能で毎日再起動するように設定してあったので、次の日には拡張したディスクが認識されていました。
(NVMeドライバーも認識されていました)

念のため、NVMeドライバーに関するAWSのドキュメントURLも置いておきます。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/aws-nvme-drivers.html

# さいごに
最近AWSに触れていなかったので、また触っていこうかと思います。
(早くControl Towerの記事も書かねば...)
それではまだどこかで。
AWS勉強備忘録21 - AWSのVirtual Private Cloud (VPC) 

## 徹底解説

AWSのVirtual Private Cloud（VPC）は、クラウド上にプライベートネットワークを構築するための強力なサービスです。ここでは、VPCの基礎から応用まで、具体例を交えながら詳しく解説します。

### VPCの基本

AWS VPCを使うことで、AWSクラウド内に閉じた仮想ネットワークを作成できます。このネットワーク内では、AWSリソース（EC2インスタンスやRDSデータベースなど）を自由にデプロイし、管理することができます。

### VPCの構成要素とその役割

- **CIDRブロック**: VPC内で使用するIPアドレス範囲を定義。例えば、「10.0.0.0/16」では、65,536個のIPアドレスが利用可能です。また、例えば「192.168.1.0/24」は、192.168.1.0から192.168.1.255までの256個のIPアドレスが利用可能です。
- **サブネットマスク**: IPアドレスをネットワーク部分とホスト部分に分割するためのもの。CIDR表記でスラッシュの後ろにくる数のことです。
- **サブネット**: CIDRブロック（ネットワーク）をさらに細かく分割したネットワーク。異なるアベイラビリティゾーン（AZ）に配置すれば高い可用性を確保できます。
- **インターネットゲートウェイ (IGW)**: VPCをインターネットに接続します。このゲートウェイを介して、VPC内のリソースが外部と通信できるようになります。
- **ルートテーブル**: ネットワークトラフィックの送り先を決めるルールを持つ。特定のサブネットがインターネットや他のサブネットとどうやって通信するかを定義します。
- **セキュリティグループ**: リソースへのアクセスを細かく制御するためのツール。インスタンスレベルでのファイアウォール設定。入力と出力のトラフィックを制御するルールを設定可能。
- **ネットワークACL**: サブネットレベルで機能します（サブネットレベルでのファイアウォール設定）。セキュリティグループよりも広い範囲で、入出力トラフィックのルールを設定できる

### 通常のネットワークとの比較

| 特徴 | Amazon VPC | 通常のネットワーク |
|---|---|---|
| 構成の柔軟性 | 高い（仮想で自由に設定） | 物理的制約あり |
| セキュリティ | セキュリティグループ、ネットワークACLによる細かな設定可能 | 物理的セキュリティ、ファイアウォールなど |
| スケーラビリティ | 容易に拡張可能 | 物理的な追加が必要 |
| コスト | 使用量に応じて変動 | 初期投資と維持費が高い |
| 管理のしやすさ | AWSコンソールで一元管理 | 複数のツールや手動での管理が必要 |

**メリット:**
- **VPC**: カスタマイズ性が高く、セキュリティが強固。拡張性に富んでおり、コストも使用量に応じて調整できる。
- **通常のネットワーク**: 物理的な制御が可能で、一部の用途ではより高速な接続が実現可能。

**デメリット:**
- **VPC**: 設定が複雑になる場合がある。全てが仮想なので、物理的なハードウェアの制御は不可能。
- **通常のネットワーク**: 初期設定や維持にコストがかかる。拡張性が限られている。

### サブネットとサブネットマスクとの違い

「サブネット」と「サブネットマスク」は、密接に関連しているが、役割は異なります。

- **サブネット**:
    - これはネットワークをより小さなネットワークに分割したものです。例えば、大きなオフィスビルが1つのネットワークだとすると、その中の各フロアをサブネットと考えることができます。サブネットを使うと、ネットワークを管理しやすくなるほか、セキュリティも向上します。
    - たとえば、`192.168.1.0/24`というCIDRブロックがある場合、これは`192.168.1.0`というネットワークアドレスを持つサブネットを示していて、`/24`がサブネットマスクです。
    - この場合、サブネットマスクは最後の8ビット（32ビットのアドレスのうち）がホスト部で、残りの24ビットがネットワーク部を示しています。このサブネットマスクによって、このサブネットが持つことができるIPアドレスは`192.168.1.1`から`192.168.1.254`まで、つまり254個のホスト（デバイス）を持つことができるということになります。また、`192.168.0.1`はネットワークアドレス、`192.168.0.255`はブロードキャストアドレスになります。
    - `192.168.1.0/24`というCIDRブロックを2つのサブネットに分ける方法としては`192.168.1.0/25`と`192.168.1.128/25`などがある。

- **サブネットマスク**:
    - サブネットマスクは、そのサブネットがどれだけの大きさか、つまりどれだけのIPアドレス範囲を持っているかを示すために使われます。サブネットマスクによって、ネットワークアドレスとホストアドレスの部分がどこで分かれているかが定義されています。

### ネットワークアドレスとブロードキャストアドレス

サブネット内で最初のIPアドレスは**ネットワークアドレス**として使用され、サブネットを識別するために予約されています。最後のIPアドレスは**ブロードキャストアドレス**として使用され、サブネット内の全てのデバイスに一斉にデータを送信するために予約されています。たとえば、「192.168.1.0/24」のサブネットでは、「192.168.1.0」がネットワークアドレス、「192.168.1.255」がブロードキャストアドレスとなります。

### サブネット間の通信

通常、異なるネットワーク間での通信にはルーターが必要ですが、AWS VPC内ではサブネット間での通信がよりシンプルに行われます。VPC内のルートテーブル設定によって、サブネット間で直接通信が可能となっています。これはAWSが提供する仮想ネットワーキングレイヤーが、自動でルーティングの処理を行ってくれるためです。

### サブネット間の通信の仕組み

AWS VPC内で、異なるサブネット間の通信は、ルートテーブルの設定によってコントロールされます。例えば、サブネットAのインスタンスがサブネットBのインスタンスに通信したい場合、ルートテーブルはサブネットAからサブネットBへのルートを持っている必要があります。VPCでは、これらのルート設定を通じて、サブネット間での通信が容易に設定できます。

### VPC内での通信の特徴

AWS VPCの強力な特徴の一つは、VPC内のリソースがデフォルトで相互に通信できるように設計されている点です。しかし、セキュリティやトラフィックの管理をより細かくコントロールしたい場合は、セキュリティグループやネットワークACLを適用して、通信ルールをさらにカスタマイズできます。
Local StorageでユーザIDを扱う

## はじめに
今回は、Reactプロジェクトにおいて、Local Storageを用いてWebサイトにアクセスするユーザのIDを扱う方法を紹介します。なお、後述するとおり、Local Storageはセキュリティ面でのリスクが高いため、機密性の高い情報を保存することには向いていません。今回はあくまでユーザの識別にのみ利用可能であり、他に悪用することができないIDの管理について紹介します。
よりセキュアにユーザID等を管理する必要がある場合は、セキュリティ対策や認証管理を行うことができるCookieを使用する方が適切かもしれません。
## Local Storageとは？
Local Storageは、JavaScriptを使用してブラウザにデータを永続的に保持するためのAPIです。
セッションストレージとは異なり、Local Storageに保存されたデータはブラウザを閉じても保持されたままとなります。ブラウザの設定からキャッシュやCookieを含むデータを削除したり、アプリケーションにて明示的に`localStorage.clear()`を呼び出したりしない限り、Local Storage上のデータは削除されません。そのため、Webサイトを訪れるユーザの識別情報をLocal Storageで管理することで、そのユーザの操作内容の履歴等を確認することができそうです（同一人物が、たとえばChromeとEdgeでWebサイトにアクセスするとIDは2つ付与されてしまいますが、、）。
Local Storageは簡単に使用することが可能ですが、以下のようなセキュリティ上のリスクがあります。
- データが暗号化されない
- JavaScriptから自由にアクセスできる

データの盗聴が容易であり、クロスサイトスクリプティング（XSS）攻撃のリスクが高いなどの理由から、機密性の高い情報を保存するべきではありません。
## 実装内容
実装のポイントは、createContextとuseContextを使用してユーザID（uid）をコンテキスト化し、子コンポーネントからアクセスできるようにしている点です。これによって、どのユーザが、どの画面で、どのような操作を行ったか、というレベルのログを取得することが可能となります。
```react:App.js
import React, {createContext, useContext, useState, useEffect} from 'react'
// 一意の識別子を生成するための関数をインポート
import {v4 as uuidv4} from 'uuid'

// コンテキストオブジェクトを作成
const UserContext = createContext()

// localStorageでユニークユーザIDを保存するためのキー
const UID_LOCAL_STORAGE_KEY = 'uid'

export default function App({children}) {
  const [uid, _] = useState(() => {
    // クライアントサイドでのみlocalStorageを利用する
    if (typeof window !== 'undefined') {
      // 初回レンダリング時にlocalStorageからuidを取得
      const storedUid = localStorage.getItem(UID_LOCAL_STORAGE_KEY)
      // uidがない場合は新しいuidを生成
      return storedUid ? storedUid : uuidv4()
    } else {
      return uuidv4()
    }
  })

  // ユーザIDが更新されるたびにLocal Storageに新しい値をセットする
  useEffect(() => {
    localStorage.setItem(UID_LOCAL_STORAGE_KEY, uid)
  }, [uid])

  return (
    <html lang="ja">
      <head>
        ・・・
      </head>
      <body>
        <UserContext.Provider value={uid}>
          <div>{children}</div>
        </UserContext.Provider>
      </body>
    </html>
  )
}

// カスタムフックを作成してコンテキストにアクセスできるようにする
export const useUserContext = () => useContext(UserContext)
```
子コンポーネントからは以下のようにコンテキストにアクセスすることが可能です。
```react:ChildComponent.js
import React from 'react'
import {useUserContext} from './App'

const ChildComponent = () => {
  const uid = useUserContext()

  // 他の処理

  return (
    <div>
      ・・・
    </div>
  )
}

export default ChildComponent
```
scrollbar-color について

# scrollbar-color について

Android のブラウザで画像のような表示を確認 (画像自体は PC の Windows にて再現)

- `タイムライン` の下部に部分的な緑色の表示が行われている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/62c2e37c-fa63-b105-8ba2-943e874a5d96.png)

表示の結果の主な理由としては以下のような実装が候補として挙がる。

```css
scrollbar-color: var(--color-surface-variant) transparent
```

## 想像される期待された挙動

期待される表示は以下のようにスクロールバーが重ならずタブの選択が表示されることであると考えられる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/1d9e1e9a-7827-2184-3de9-77fd77677af1.png)

実装を確認したところスクロールを行うと透明となる挙動である模様
想定される挙動は以下の通り

- スクロール可能であることを示すため初期表示ではスクロールバーを表示
- スクロールされた後、ユーザはスクロール可能であると認識したとみなしスクロールバーを透明化

## 対応案

### padding-bottom 指定

既存の実装を尊重する場合、重なりが発生しないようにすることとなるため、
padding などで表示位置を調整する対応となる。

レイアウトは変更されるがスクロールバーが表示されていても選択中タブとの重なりは発生しない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/55c05ec8-df24-99fc-67bd-9f68d2554c60.png)

```css
padding-bottom: {任意のスクロールバーの高さ}px
```

### scrollbar-color の指定変更

初期表示に transparent を指定することで重なっていることを明示する形となる。

```css
scrollbar-color: transparent var(--color-surface-variant) transparent
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/c0173fff-05d8-ced5-3a8d-ce4645e9f360.png)

- デザインなどでは問題があるかもしれないがユーザにスクローラブルであると訴求する表示にはなっている。
Outesystems Associate Reactive Developer試験を受けた話

こんにちは！EnsnOkiです。

会社の方針でOutsystemsの資格を取得することを推奨しているので、
その試験を受けたお話です。

## Outsystemsとは
高度なプログラミング知識を必要とせず、直感的にアプリケーション開発が行える
ローコード開発プラットフォームです。

ただ、誰でもとはいうものの、開発規模が大きくなってくると
保守性や拡張性が重要になってくるのでその辺を考慮できるエンジニアは必須であると考えます。
また、コーディング自体はビジュアル開発できるものの、細かい部分ではSQLなど使う必要があります。というか必須です。ライセンス料は安くないので要求レベルも上がり単純作業では満たせない可能性大です！

Outsystems自体は開発やデプロイなど誰がやってもほぼ一貫性を持った作業ができますが、何せライセンス料は安くないのでおのずと要求レベルも上がってくると考えられるので、やはり以下の経験を持った人間が必要となります。
1. 要件定義
1. 設計
1. プログラミング
1. テスト
1. 保守

特に2,3が適当になると後の拡張性や保守性に大きく影響を及ぼすのでやはりエンジニアは必須！

逆に競合のローコードと比べると柔軟性は高いので、使いこなすことで高速開発＆高品質は実現可能です。

## Associate Reactive Developer

試験方法は以下から選べます
1. オンライン受験
1. 試験センター

試験センターは東京・大阪のみで実施しており、
私は沖縄在住なので1.オンライン受験を選択しました。

試験まで流れ
1. Outsystemsサイトで申し込み
    https://www.outsystems.com/ja-jp/certifications/home.aspx  
    
2.試験アプリのインストール
3.試験アプリの動作確認
4. 試験実施

試験時の流れ
1. 試験アプリの起動
1. 試験監督者による試験環境の確認
1. 試験開始

[2. 試験監督者による試験環境の確認]は山場です。
なぜなら、試験監督者と口頭で自分の試験環境を確認する言語が
**英語**だからです！

以下主な聞かれる内容
・試験監督者は私でよいか
・本人確認証を見せてください
・帆人確認証はどこが発行したか・なんの確認証か
・室内には試験する人以外いないか
・試験名を答えてください。
・PCはデスクトップか・ラップトップか
・カメラは内臓か外付けか
・机の上、机の下、天井、椅子の裏、椅子の下をカメラに映せ
・眼鏡をカメラに映せ
・マウスをカメラに映せ
・ポケットの中身を映せ
・耳の裏を映せ
・肘から手まで表、裏を映せ

上記確認が終わったあとチャット（英語）で再度誰もいないかの確認をされます。

私は英語に応えられずサポートに連絡してください的な指摘を受けたが、
アプリを終了した後、再度起動し試験を受けることができました（４回ぐらいチャレンジしましたが。）

環境確認後は試験に移行します。
解答終了後すぐに合否の画面が表示されます。

終了後の感想としては
難易度的にはエンジニア経験があると１週間程度で受かるのではという感覚です。
Outsystems自体にも試験対策の動画（日本語）もあるのでそれを真面目に受講していればよいと思います。
それよりも、試験監督による英語の対応がキツイですね。
WSLにdockerをインストール

# はじめに
はじめに、wslでdockerを扱いたかったので、導入手順を備忘録として残す。

# Dockerインストール
参考サイトをもとにインストールを行なった。

はじめにWSL内のパッケージを最新の状態にする。
```
sudo apt-get update
sudo apt-get upgrade -y
```

次にdockerリポジトリを設定する。
```
# Add Docker's official GPG key:

#ca-certificateパッケージのインストール
sudo apt-get install ca-certificates curl

#指定したディレクトリにファイルをコピー
sudo install -m 0755 -d /etc/apt/keyrings

#複合化のためのキーをダウンロード
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc

#全ての変更対象に読み取りのみの権限を付与
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

実際のインストールコマンドは以下
```
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```

以下コマンドでインストールされたdockerのバージョンを確認し、出力されればインストール完了
```
docker -v
```


# 参考サイト
[Docker公式](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)
[Zenn:WSL(Ubuntu)にDocker環境を構築する](https://zenn.dev/thyt_lab/articles/fee07c278fcaa8)
OV証明書とEV証明書の見分け方

# 当記事の概要
当記事では、Webサイトで使用されているSSL/TLS証明書がOV証明書（Organization Validation）とEV証明書（Extended Validation）のどちらであるかを見分ける方法を記載しています。

SSL/TLS証明書では、DV証明書（Domain Validation）、OV証明書、EV証明書が主に使用されます。このうち、DV証明書は証明書に組織情報が含まれないことで容易に区別できるのですが、OV証明書とEV証明書はどうやって見分ければよいのかがすぐに分からなかったので、備忘録として見分け方を書いておこうと思います。

# 前提環境
Chrome バージョン: 122.0.6261.129（Official Build）（arm64）を使用して確認しています。バージョンによって表示が異なる場合があるのでご注意ください。


# OV証明書の場合
OV証明書を利用しているサイトとして、IBM Cloud（https://cloud.ibm.com/ ）を対象に確認します。

上記URLにアクセスし、アドレスバーの左側のアイコン（以下画像の赤枠）をクリックします。

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/a4393376-4f23-d8db-8a26-6a683840c770.png">

以下のポップアップが表示されるので、赤枠部分をクリックします。

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/06e654f1-26f7-fb76-ef6a-234e1c6e2503.png">

赤枠部分が「証明書は有効です」とだけ表示されています。さらに赤枠部分をクリックします。

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/c58e4ef0-3770-9805-c62b-b85b464a748b.png">

すると、証明書ビューアーが表示されます。「詳細」タブで「件名」を選択し、フィールド値を確認すると、「O(組織)」が設定されています。DV証明書では「O(組織)」は設定されていません。また、EV証明書に該当する項目(serialNumber)も存在していません。そのため、この証明書は**OV証明書**となります。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/a42c00b5-2147-7380-5a3b-531d671fa7c4.png">


# EV証明書の場合
EV証明書を利用しているサイトとして、Red Hat社のサイト（https://www.redhat.com/ ）を対象に確認します。

先ほどと同じ手順で証明書の有効性確認のポップアップまで進むと、赤枠部分が「証明書は有効です」に加えて、「発行先」に関する情報が表示されています。この場合は**EV証明書**になります。
さらに赤枠部分をクリックします。

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/c0d33608-d76c-c0d0-b11a-58e9fcc85fcc.png">

証明書ビューアーで「件名」を表示すると、フィールド値として「O(組織)」、および、「serialNumber」が設定されています。この場合**EV証明書**になります。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386149/6bf08af2-db8f-fc9b-ed0d-ac3f65458f5c.png">

# まとめ
見分け方のまとめです。

|証明書種類 |「件名(Subject)」の「O(組織)」  |「件名(Subject)」の「serialNumber」 |
|:-|:-|:-|
|OV証明書   | 値あり  | 値なし  |
|EV証明書   | 値あり  | 値あり  |
|(ついでに)DV証明書   | 値なし  | 値なし  |
【React】最初っから下端にスクロールされている状態にする方法(アニメーションなし)

# はじめに
今回は、タイトルにある通り画面表示時、つまり任意のコンポーネントが表示された時にはすでに下端にスクロールされている状態にする方法について紹介していきたいと思います。

# 問題
LINEやDiscodeなどのチャット画面では、ページ表示時に一番下までスクロールされている状態が当たり前になっています。これをReactでやりたいというのが今回の目的です。

ここで試しに「React スクロール位置 下端」などで調べると、`useRef`と`useEffect`を使用して、最下部にスクロールさせる方法がよく紹介されています。
しかしこの方法だと、下までスクロールするアニメーションが表示されてしまいます。

LINEやDiscodeにそんなアニメーションはないですよね。
最下部にスクロールされた状態で画面表示をしたいのです。

以下にだいぶ無理やりにそれを実現した方法を紹介します。
もっといい方法を本当に知りたいので、知っている方はコメントで教えてください🙇🏻‍♂️

# 解決方法
一言で言えば、スクロール中はdiv自体を非表示にしてあたかもスクロールアニメーションをないように見せる、とういだけのゴリ押し戦法です。

今回はデータフェッチに`SWR`を使用しています。

```tsx
const Chat: React.FC = () => {
    // この部分はSWRを使用したカスタムフックなので関係はなし。
    const {
        data,
        error,
        isLoading,
    } = useChat();

    const endDiv = useRef<HTMLDivElement>(null);

    const [isVisibility, setIsVisibility] = useState(false);

    useEffect(() => {
        // refがnullの時はスキップ
        if (endDiv.current) {
            endDiv.current.scrollIntoView();
            setIsVisibility(true);
        }
    }, [data]);

    return (
        <>
            <div
                style={{
                    visibility: isVisibility ? "visible" : "hidden",
                }}
            >
                // ここにチャットを展開
            </div>
            <div ref={endDiv} />
        </>
    );
};
```

各部の解説をしていきます。

```ts
const endDiv = useRef<HTMLDivElement>(null);
```
refはコンポーネントのDOMノードへの参照を持つオブジェクトです。
これを` <div ref={endDiv} />`のようにdivに指定することでこのdivのDOMを参照することができます。

```ts
const [isVisibility, setIsVisibility] = useState(false);
```
こちらはdivの表示非表示を動的に切り替えるために用意します。
デフォルト値はfalse、つまり非表示です。

```ts
useEffect(() => {
    // refがnullの時はスキップ
    if (endDiv.current) {
        endDiv.current.scrollIntoView();
        setIsVisibility(true);
    }
}, [data]);
```
useEffectでendDivのrefを持つdivまでスクロールさせます。
その後` setIsVisibility(true)`でdivを表示状態に更新します。
また、これはapiからのフェッチを行うのが前提なので`data`を第二引数に指定し、`data`がかわったタイミングで再レンダリングを行います。

今回は`SWR`を使用しているので、定期的に再検証させているとしても、レスポンスのdataが変わっている(新しいチャットがあった場合)時のみ最下部まで自動でスクロールしてくれます。

```tsx
<div
    style={{
        visibility: isVisibility ? "visible" : "hidden",
    }}
>
    {/*ここにチャットを展開*/}
</ div>
<div ref={endDiv} />

```
`visibility: isVisibility ? "visible" : "hidden",`でisVisibilityによって表示非表示を切り替えます。

# おわりに
かなり無理やりな実装ですが、とりあえずやりたかったことはできたので満足です。
もっといいやり方がみつかればまた更新したいと思います。
別なやり方等ありましたら是非コメントにお願いします🙏

では、最後までお読みいただきありがとうございました！
【Unity】Animationをブレンドすると首が１回転するバグの記録

# 概要
タイトルにもある通り、特定のアニメーションAとBをブレンドすると、ブレンド中に首が１回転するバグに遭遇。
この問題を解決したので記録に残す。

# バグの内容
![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/40b036d5-4fbe-1600-b464-49503c088c37.gif)
こんな感じでブレンドすると首がクルっと１回転するようなバグに遭遇。
ブレンドはTimelineで行って、Animtorで行っても同じ結果になる。

# 結論
今回のバグの原因は、アニメーションFBXのインポート方法に問題があった。

↓これはアニメーションFBXのRigタブの一部
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/0400b992-019f-96ee-3a24-3df6e502669a.png)
`Avatar Definition` が、`Create From This Model` となっている。
ここを、`Copy From Other Avatar` にし、アニメーション生成に使用したメッシュのアバターを設定することで解決した。

# 詳細
`Avatar Definition`について、Unityのドキュメントでは、

:::note info
デフォルトでは、Avatar Definition プロパティは Create From This Model に設定されています。この設定では、Unity はファイル内で定義された一揃いのボーンをヒューマノイドアバターにマップしようと試みます。　
:::

とある。つまり、AvatarをUnityが自力で作というわけだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/5ea27370-e20d-d364-2697-7c5c28f019af.png)
↑①Unityが自力で作成したアバター、`neck_01` のノードの向きが、緑が前方を向いている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/2b83a212-5ff3-1e82-165b-90a2314c5189.png)
↑②Animation生成時に使用したメッシュのアバター、見てわかるとおり、首ノードの向きが逆を向いている。

このようなアバターのノードのズレがある状態のまま、アニメーションをブレンドしても当然うまく動かない。なので、ちゃんとアニメーションを生成した時に利用したメッシュのアバターを使って、アニメーションFBXをインポートしましょう。というお話でした。

以上
Githubで草を生やす習慣作り

## Githubで草を生やすとは
### Githubにソースコードをコミットしている状態のこと

![2024-03-23 23.12の画像.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179042/9ae7132b-43c9-fe42-a673-3d67847f91ef.jpeg)
上記は私のGithubのContributionの状況が表示されているグラフです。
（Contributionとは、要するにその人のGithubでの活動状況）

プログラミングを始めたての方にわかりやすく言うと、**草を生やすと言うのは、Contributionの状況のグラフが緑色で芝生のように見えるため、Githubにコードをコミットし、緑色を増やすことを言う。**
普段からGithubを利用している人は見てもらえればわかると思いますが、正直に言うと今までほとんどGithubを利用しておらず、ほったらかしにしていました。。。

しかし、2024年3月19日から毎日草を生やすよう習慣作りを頑張っています。
なぜこの習慣づくりを頑張るのかと言いますと、
1. Githubにソースコードを何もコミットしない状態（草が生えていない）が長く続くと、プロフィールを見た人（例：採用活動をしている際に、企業側から見られるなど）から「学習意欲が低い」と判断されてしまう恐れがあるから
2. Gitのコマンドや仕組みを学習し、理解できるようになるから

こちらが主な理由です。
一つ目の理由は、以下の書籍でも著者の方が言及しています。
[引用した書籍（タイトル：21世紀最強の職業 Web系エンジニアになろう）](7ocFvEN4yAKgp51ewnidYjc&dib_tag=se&keywords=web系エンジニアになろう&qid=1711204572&sprefix=web系%2Caps%2C171&sr=8-1)(p.134)
その人のGithub上の活動履歴が表示されているため、草が生えていないと、企業側の方々からの印象が悪くなってしまうことがあるからです。

二つ目の理由は、きちんと操作方法を理解できていることを示せるからです。プログラミング初学者からすると、GitやGithubの仕組みを学んでも、それを複雑だと感じてしまうことがあると思います。実際、私もそう感じていました。しかし、ちゃんと自分でコミットをしたりすることで、ちゃんとGithubの扱いには慣れることができるので、　初学者の人は複雑だと感じたとしても、恐れず自分で草を生やすようにすることがオススメです！

## 最後に
今回の記事では、Gihubで草を生やすとは何なのか？ということ、それを行う理由について述べました。
この記事がお役に立てることができたのなら、本当に嬉しく感じます。
ここまで読んでいただき、ありがとうございます。
Lambdaのランタイムを更新する

# はじめに

ずいぶん前に作って放置したままだったLambda関数を久々に見たら、Lambdaのランタイムが古いもの（Ruby-2.7）でした。
そこでランタイムをGUI（管理コンソール）で更新するついでに、その手順を記事としてまとめてみました。

# 更新手順

* Lambda関数の詳細ページに入り、画面を下の方にスクロールさせると［ランタイム設定］という項目があります。
* ここで［編集］を押してランタイム設定の編集画面に入ります。

![lambda_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/f00255bd-fe31-d2c0-72d9-cad8c5055ecd.png)

* ［ランタイム設定を編集］画面では、現在サポート対象のランタイムがリスト表示されるため、その中から所望のランタイムを選択します。
* ランタイムを選択したら、画面下部の［保存］を押します。

![lambda_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/efc7fe58-7da3-2eda-5fce-93753cf41a3e.png)

* ランタイム設定の変更後に［ランタイム設定］という項目を見ると、ランタイムのバージョンが変更されていることが確認できます。

![lambda_003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/fdf8f4a5-608e-0762-51e2-b1c6f4ba9b6a.png)
実践ベイズモデリング　ー解析技法と認知モデルー　朝倉出版　豊田秀樹先生等

```r

#ガンベル分布の最尤推定

#表1.2のデータ
x=c(8.95,8.68,8.7,8.74,8.71,8.58,8.63,8.48,8.6,8.65,8.41,8.52,8.53,8.6,8.6,8.56,8.66,8.73,8.74,8.47,8.54,8.35,8.56,8.51,8.52)
n=length(x)

#loglik=function(s){
#val=-log(sqrt(s[2]^2))-(x-s[1])/sqrt(s[2]^2)-exp(-(x-s[1])/sqrt(s[2]^2))  
#return(sum(val))
#}

#pre-Broyden Algorithm p.211
#最尤方程式
f=function(s){
f1=n-sum(((x-s[1])/sqrt(s[2]^2))*(1-exp(-(x-s[1])/sqrt(s[2]^2))))
f2=n-sum(exp(-(x-s[1])/sqrt(s[2]^2)))
return(c(f2,f1))
}


X=c(mean(x),sd(x))
ite=10^2
B=diag((f(X+h)-f(X))/h)
h=0.01

for(l in 1:ite){
if(sum(abs(f(X)))>10^(-9)){  
X_pre=X
X=X-solve(B)%*%f(X)
s=X-X_pre
y=f(X)-f(X_pre)
B=B+((y-B%*%s)/as.numeric(t(s)%*%s))%*%t(s)
print(sum(abs(f(X))))
#print(loglik(X))
}}

param=X

#期待値
param[1]+0.577*(param[2])

#中央値
param[1]+log(log(2))

#分散
(pi*sqrt(param[2]))^2/6

#標本から%を計算
p=exp(-exp((param[1]-x)/(param[2])))

#再現期間r
1/(1-p)



```
TwitterBOTを無料でやる方法？PythonでTwitterアカウントを動かそう!【Python Twitter ボット Twikit】

## 最初に
この記事は、**Pythonやpipのインストール等については既に済んでいる前提**で書いています。
Pythonやpip等のインストールにつきましては、他記事を参考にしてください

全体的に中級者向けの記事になっています。
ご理解いただけますと幸いです。

**※この記事はTwitterのアカウントをボットのように機能させるための記事です。ボット自体を無料にするものではありません**

## 1: ライブラリインストール
まずライブラリをインストールしましょう
```console
$ pip install twikit
```

## 2: アカウントを用意する
まず[こちら](https://twitter.com/i/flow/signup)にアクセスして、Twitterアカウントを作成しましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2676619/9b32c12e-99d7-9c46-df1a-fd715954f0b8.png)

この時ユーザー名、パスワード、メールアドレス等は、どこかにメモしておきましょう。

## 3: 実際にコードを書く
実際にコードを書いていきましょう

```py
from twikit import Client

USERNAME = 'ユーザーID'
EMAIL = 'メールアドレス'
PASSWORD = 'パスワード'

# クライアントを宣言
client = Client('ja')

# これでログイン
client.login(
    auth_info_1=USERNAME ,
    auth_info_2=EMAIL,
    password=PASSWORD
)
```

なんと、これだけでログインが出来てしまうんです。

### ツイートをする

```py
# 先ほどのコードをここに張り付ける
TWEET_TEXT = 'ツイート本文'
MEDIA_IDS = [
    client.upload_media('./media1.png'),
    client.upload_media('./media2.png'),
    client.upload_media('./media3.png')
]

client.create_tweet(TWEET_TEXT, MEDIA_IDS)
```
このように画像を張り付けるのも簡単にできます。
画像無しでツイートする場合はMEDIA_IDSの部分を消してもらえば大丈夫です！

## 最後に
今回紹介したのはごく一部の為、より詳しく知りたい方は引用元に書いてあるGitHub等を見ていただけると幸いです。examplesなどでより詳しく説明されていますので、見てみるといいと思います。

Pythonはそこまで詳しくないので不備がございましたら優しく教えていただけると幸いです。

普段はPython以外にもJS/TS等の記事も書いていますので、見ていただけると幸いです。

## 引用元
https://github.com/d60/twikit

https://twikit.readthedocs.io/en/latest/twikit.html