OmniAICreator/Qiita-1.07M huggingface dataset:
マイクラ - アイテムスタックのLoreでDB - 統合版マインクラフト 備忘録

`2023/5/15更新`
`Minecraft BE -v1.19.81`
`{
      "module_name": "@minecraft/server",
      "version": "1.2.0-beta"
    }`
# 概要
統合版マインクラフトのscript APIを使って作っていきます。
言語はjavascriptです。
今回は変数をJSON文字列に変換してLoreに保存していきます。
Loreはどうやら文字数制限がないようなのでとても便利なDatabaseが作れそうです。


### 用語確認
Lore: アイテムの説明の文章 デフォルトで紫色
DB: データベース ゲームのデータを保存

# コードと説明
チェストを設置してその中のアイテムを取得して、そのアイテムにLoreをつけていきます。
```js
import {world } from "@minecraft/server";
const overworld_dimension = world.getDimension('overworld');

 let DataBaseContainer = overworld_dimension.getBlock({ x: 1024, y: 100, z: 1024 }).getComponent("inventory").container;
 let IS_DB = DataBaseContainer.getItem(0);
 IS_DB.setLore(["Line 1", "Line 2", "Line 3"]);
 let DATA_BASE = IS_DB.getLore()[0];
 DataBaseContainer.setItem(0, IS_DB);
 overworld_dimension.runCommandAsync('say ' + DATA_BASE);
```
どうせ文章で説明しても難しいだけなのでコードを上げます。

1. overworld_dimensionの定義
2. getBlock(3Vector)でブロックを取得 今回はこの座標にチェストがあります。
3. getComponent()でインベントリの情報を取得
4. containerを取得
5. getItem(0)で1番目のスロットのアイテムスタックを取得 1番目→0, 2番目→1, 3番目→2

### setLore()で配列を入れる Loreは基本的に配列を入れることができる
```js
let data = [{"key1":"text1"},{"key2":["text2","text3"]}];
IS_DB.setLore([JSON.stringify(data)])
//このような形でJSON文字列を入れることができる
```
### getLore()でデータを取得する Loreから出てくるデータは配列
```js
let data = JSON.parse(IS_DB.getLore()[0]);
//合ってるかは試していないがおそらくこの形でLoreから取得したJSON文字列を変数に変えることができる
```
### 最後に保存する
```js
DataBaseContainer.setItem(0, IS_DB);
```
Containerのスロット`0`にアイテムスタック`IS_DB`を上書きする
という処理をしています。

## 最後に
これにてアイテムスタックのLoreを使用したデータベースの説明を終わります。
Loreに文字数制限がついたら詰みだけど、それまでは便利なものだからありがたく
使わせていただきましょう。
Streamlit & LangChain & ConversationalRetrievalChain でメモリの内容を覚える

LangChain & ConversationalRetrievalChain & langchain.memory を使うと、簡単に過去の会話を覚えてくれているチャットボット的なものを作れるのですが、Streamlitを使用した場合、submitを押すとメモリの中身を忘れて、想定していた動きになりません。

すぐに風化してしまいそうな気もしますが、これの対応方法がネット見ても見当たらなかったので書いておきます。

## 元のコード
CLI等で下記のように動かすと、問題なくchat_historyをつけて自動的に過去に送信したメッセージを付けてくれます（下記の例はFAISSに独自のデータを入れていますが、違うものを使っていれば、その辺りは適宜読み替えてください）。いやぁ簡単。

が、これをそのままStreamlitで実装すると、POSTを押すたびにmemoryが初期化されて思ったように動いてくれません。。

```python
def chat_chain(query):
    embeddings = OpenAIEmbeddings()
    db = FAISS.load_local("faiss_index", embeddings)
    memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
    qa = ConversationalRetrievalChain.from_llm(
        ChatOpenAI(temperature=0), db.as_retriever(), memory=memory
    )
    chat = qa({"question": query})
    return chat

def main():
    while True:
        query = input("質問を入力してください: ")
        chat = chat_chain(query)
        print(chat)
```

公式ドキュメント
https://python.langchain.com/en/latest/modules/chains/index_examples/chat_vector_db.html



## こんな風にすると動く
`@st.cache_resource`(ver 1.18.1以上で使えます)がポイントぽいのは検索してすぐに分かったのですが、
```python
@st.cache_resource
def chat_chain(query):
   ...
```
とすると、queryを含んだものをキャッシュするのでqueryが毎回違う今回の用途では動いてくれません。

下記のようにすれば思ったように動いてくれました。

```python
@st.cache_resource
def save_memory()
    memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
    return memory

def chat_chain(query):
    embeddings = OpenAIEmbeddings()
    db = FAISS.load_local("faiss_index", embeddings)

    # キャッシュされたメモリに保存する
    memory = save_memory()

    qa = ConversationalRetrievalChain.from_llm(
        ChatOpenAI(temperature=0), db.as_retriever(), memory=memory
    )
    chat = qa({"question": query})
    return chat

def main():
    query = st.text_input("質問を入力してください: ")
    submit_btn = st.button("送信")
    if submit_btn:
        chat = chat_chain(query)
        st.write(chat)
```

下記は試していませんが、上記の場合は複数ユーザで使用した場合も一律覚えてしまうので、実際にはユーザIDやセッションID単位などでキャッシュさせると良い気がします。
```python
@st.cache_resource
def save_memory(userid)
    memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
    return memory

def chat_chain(query):
    ....

    userid = 123

    # userid単位でキャッシュされたメモリに保存する
    memory = save_memory(userid)

    ....
```

## st.session_stateを使う?
おそらく、st.session_stateを使ってhistoryをためていく方法もありそうなのですが、どうやれば良いかが分かりませんでした（挑戦はしてみたのですが、上記と同じ動きにならない）。上記の例で、具体的にどう書けば良いか分かる方いらっしゃいましたら、コメントください。
laravel10 vue3 element plus upload 419 csrf エラー

csrf 対策が非常に面倒臭い。

テスト環境でも、相対パスにしたらいけた
```photo.vue
    <el-upload
        v-model:file-list="fileList"
        action="/hoges/test/"//相対パス
        list-type="picture-card"
        :on-preview="handlePictureCardPreview"
        :on-remove="handleRemove"
        :with-credentials="true"
        :headers="{ 'X-CSRF-TOKEN': csrf }"
    >
        <el-icon><Plus /></el-icon>
    </el-upload>

    <el-dialog v-model="dialogVisible">
        <img w-full :src="dialogImageUrl" alt="Preview Image" />
    </el-dialog>

```



vue.blade.php の ヘッダに csrf を書いて
computed で csrf を取得して、一緒に送るって感じ。

element plus の upload 使いたいやんか
https://element-plus.org/en-US/component/upload.html

でも、エラーでるやん

ということで、

```vue.blade.php
  <meta name="csrf-token" content="{{ csrf_token() }}">
```


action に アップロードしたいurlを指定。


```photo.vue

<template>

    csrf : {{csrf}}

    <el-upload
        v-model:file-list="fileList"
        action="[https://hoge.com/hoges/test]"
        :headers="{ 'X-CSRF-TOKEN': csrf }"
    >
        <el-icon><Plus /></el-icon>
    </el-upload>

</template>

<script lang="ts" setup>
import { ref , computed , onMounted ,inject } from 'vue';
import { Plus } from '@element-plus/icons-vue'
import type { UploadProps, UploadUserFile } from 'element-plus'

const fileList = ref<UploadUserFile[]>([
])

const csrf = computed(() => document.querySelector('meta[name="csrf-token"]').getAttribute('content'))

</script>


```

これで、以下の感じでアップロードされる。
引数を”とすると、アップロードファイルはstorage/app直下に保存される

```

[2023-05-15 08:23:30] local.DEBUG: array (
  'file' => 
  \Illuminate\Http\UploadedFile::__set_state(array(
     'test' => false,

     'originalName' => '00006-3135271734.jpeg',

     'mimeType' => 'image/jpeg',

     'error' => 0,

     'hashName' => NULL,

  )),

)  
```

以上
【API Gateway】フロントからパラメータを送ると401が返ってくる

# はじめに
ローカル環境ではPostmanとバックエンド間でパラメータの受け渡しに成功していたのですが、デプロイ環境ではフロントとAPI Gateway間でパラメータの受け渡しに失敗していました。

# 原因と解決方法

Cloud Watchでログを確認するとform-dataでが送信されていました

```
  Parameters: {"------WebKitFormBoundary \r\nContent-Disposition: form-data; hogehoge }
```

フロント側でパラメータを送信する処理を確認したところ、パラメータをばっちりform-data形式で送っていました…。

```tsx:
    const data = new FormData();
```

JSON形式に直すことで解決できました

```tsx:
    const data = {
      name: email,
      password: password
    }
```

また、リクエストにContent-Typeヘッダーがない場合はAPI Gateway側でapplication/jsonとみなされるようです。

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/request-response-data-mappings.html

# おわりに
JSON形式で送っているだろうと思い込んでいたのでうっかりでした。
AWS CDK Ver.2 PythonでCloudFrontとS3による静的サイトホスティングを作ってみた

今回の記事では、下の構成図のように、CloudFrontとS3を使って静的サイトをホスティングするリソースをCDK Ver.2 pythonを使って作成していきます。

全コードはGithubを参照してください。
[Githubはここ](https://github.com/ShinyaT1994/cdk-static-site-cf.git)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660703/8b84de29-bf62-0803-d846-326432d1d1d0.png)

## 前提条件

- AWS CDK v.2 がインストールされていること
- Python 3.x がインストールされていること
- AWSアカウントがあり、AWS CLIが設定されていること

※Cloud9を使うとこの辺りがPassできるため、Cloud9を使って今回の記事の内容は作成しています。

## 構築手順
### 1.CDKアプリの初期化
先ずはCDKアプリの初期化を行います。

```bash
$ mkdir cdk-lambda-rds-proxy
$ cd cdk-lambda-rds-proxy
$ cdk init --language python
```

### 2. 必要なパッケージをインストール
ここでは、CDKアプリを初期化した際に作成された.venvを有効化しています。

```bash
$ source .venv/bin/activate
$ pip install -r requirements.txt
```

### 3. スタックの作成

```python
from aws_cdk import (
    Stack,
    aws_s3 as s3,
    aws_cloudfront as cf,
    aws_cloudfront_origins as cf_origins,
    aws_s3_deployment as s3deploy,
)
from constructs import Construct


class CdkStaticSiteCfStack(Stack):

    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # S3 Bucket
        bucket = s3.Bucket(
            self, 
            "MyStaticSiteBucket"
        )

        # CloudFront
        distribution = cf.Distribution(
            self,
            'Distribution',
            default_behavior=cf.BehaviorOptions(
                origin=cf_origins.S3Origin(bucket)
            ),
            default_root_object='index.html',
        )

        # Deploy site contents to S3 Bucket
        s3deploy.BucketDeployment(
            self, 
            "BucketDeployment",
            sources=[s3deploy.Source.asset("./website")],
            destination_bucket=bucket,
            distribution=distribution,
            distribution_paths=["/*"]
        )
```

### 4. HTMLファイルの作成
websiteフォルダを作成し、その中にindex.htmlを作成して以下の内容を記述します。

```html
<h1>Hello CDK!</h1>
```

### 5. CDKアプリをデプロイ
Stackの準備が完了したため、デプロイします。

```bash
$ cdk deploy
```

デプロイ完了後にCloudFrontのディストリビューションを確認すると、以下のように「cloudfront.net」のドメイン名が表示されていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660703/4af19f0c-0e39-65ee-b8f9-a3eb4e044d0b.png)

アクセスすると以下のような表示となり、HTMLファイルが表示されていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660703/2262fdf9-257d-7829-2631-e57ec1e3ec94.png)

## まとめ
この記事では、LambdaのCloudFrontとS3を使って静的ウェブサイトをホスティングするリソースをCDKで作成する方法について紹介しました。基本的なサーバレス構成においてよく使われる構成だと思いますので、参考になれば幸いです。
JSで文字列が数字か判断する

``` Javascript
let string = "aaa";
let number = "123";
let stringContainingNumber = "aaa123";

//A
let checkIfNumber = /^[0-9]+$/; //正規表現、終始半角数字で1文字以上の文字列を示す

checkIfNumber.test(string); //false 
checkIfNumber.test(number);//true
checkIfNumber.test(stringContainingNumber);//false

//B
let checkIfNaN = /[^0-9]/; //正規表現、半角数字以外のある1文字を示す

checkIfNaN.test(string); //true 
checkIfNaN.test(number);//false
checkIfNaN.test(stringContainingNumber);//true
```

正規表現.test(文字列)は
正規表現と文字列の間に一致するものがあった場合は、true、そうでない場合は、false。
Aは最初から最後まで数字、という正規表現に一致したらtrue、Bは数字以外の何らかの文字がひとつでも入っていたらtrue、なので両方同じ。
deviseでのユーザー名でログインできるようにする！[Rails]

# 目次
[目標](#目標)
[環境](#環境)
[実装](#実装)
[最後に](#最後に)

# 目標
deviseにおいてのログイン機能で、名前とパスワードでログインできるようにする。

:::note warn
deviseを導入したデフォルトではEメールとパスワードでログインできるようになっています。
:::

# 環境
mac OS Ventura 13.3
cloud9
Rails 6.1.7
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
git version 2.39.2
devise導入

# 実装
※deviseは導入済みの前提です！
モデル名は任意ですが、例えば「User」の場合、Userテーブルに「name」のカラムを追加するか、すでに追加しているか確認してください。
1. deviseのviewページの作成
```
rails g devise:views
```
このコマンドでログインページやその他のページが作成できます。

2.　ログインページに名前を入力するフォームを追加
```app/views/devise/sessions/new.html.erb
<div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
</div>
```
この際に、Eメールを入力するフォームは削除しておいてください！

3.　コントローラにて「name」を保存できるように許可を与える
```app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?
  #deviseの機能が行われる前にconfigure_permitted_parametersメソッドを実行

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:email,:name])#nameを追加
  end
end
```
::: note
初期状態の devise は、サインアップ、ログイン時に「email」と「パスワード」しか受け取ることを許可されてないため、現状では name を入力しても、データとして保存することはできません。
なので、指定したデータは保存できるよう、許可を与える必要があります！
:::

４. 認証キーの設定
```config/initializers/devise.rb
#config.authentication_keys = [:email]
```
最後に、devise.rbファイルの上記コードを探します！
```config/initializers/devise.rb
config.authentication_keys = [:name]
```
上記のようにコメントアウトを外して、「:email」を「:name」に変更します！
環境や実装内容によって異なるかもしれませんが、49行目付近に記述があると思います！
**以上で実装は完了です！**
※もし、実装してもログインできない場合は「rails s」をし直してサーバーを再度起動してみてください。

# 最後に
今回はdeviseにおけるログイン方法の変更をしました。
私自身も悩んだ点だったのでアウトプットさせていただきました、、、！
今、学習している方の参考になれば幸いです。
Babylon.js 6 と HavokEngine を Vite 4 で動作させるサンプル

https://stackblitz.com/edit/vitejs-vite-np5zng?embed=1&file=src/main.ts

Babylon.js 6 で搭載された HavokEngine の WebAssembly を、 Vite で読み込めるようにしたプロジェクトのサンプルです。

ついでに WebGPU が動作するならそっちを優先するようにしています。

## 各バージョン

- `@babylonjs/core: ^6.0.0` 
- `@babylonjs/havok: ^1.0.1`
- `typescript: ^5.0.0`
- `vite: ^4.0.0`

## npm install 後に自動実行

```json:package.json
{
  "scripts": {
    "postinstall": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./assets/HavokPhysics.wasm"
  }
}
```

この記述を追加することで、ローカルに依存パッケージとして導入された wasm ファイルを Vite が読み込み可能な場所に移動させました。

[vite-wasm-plugin](https://www.npmjs.com/package/vite-plugin-wasm) は期待通り動作しませんでした。

[Vite に WebAssembly の import サポートはある](https://ja.vitejs.dev/guide/features.html#webassembly)んですが、期待通り動作しませんでした(多分 ESM に非対応だからではないでしょうか)。

## wasm ファイルの URL をインポート

```ts
import HavokPhysics from "@babylonjs/havok";
import havokWasmUrl from "../assets/HavokPhysics.wasm?url";
```

このように `?url` サフィックスを付けることで、そのファイルへのアクセス URL を取得することが出来ます。

```ts
const havok = await HavokPhysics({
    locateFile: () => havokWasmUrl,
});
```

として wasm を初期化することで、指定した URL のファイルを取得するように出来ます。

## HavokPlugin の初期化

```ts
const scene = new Scene(this.engine);
const havokPlugin = new HavokPlugin(true, havok);
scene.enablePhysics(new Vector3(0, -9.8, 0), havokPlugin);
```

上記で HavokPlugin の初期化が完了です。

```ts
const sphere = CreateSphere("Sphere", {}, scene);
sphere.position = new Vector3(0, 10, 0);
new PhysicsAggregate(sphere, PhysicsShapeType.SPHERE, {
    mass: 1.0, // 質量(kg?)
    restitution: 0.75, // 反発力
}, scene);
```

`PhysicsAggregate` を追加することで、対象の Mesh に対して物理演算をかけるようになります。

## 参考資料

- [Using Vite with Babylon.js | Babylon.js Documentation](https://doc.babylonjs.com/guidedLearning/usingVite)
- [Using Havok and the Havok Plugin | Babylon.js Documentation](https://doc.babylonjs.com/features/featuresDeepDive/physics/havokPlugin)
- [Babylon.js ES6 support with Tree Shaking | Babylon.js Documentation](https://doc.babylonjs.com/setup/frameworkPackages/es6Support)
- [WebGPU Support | Babylon.js Documentation](https://doc.babylonjs.com/setup/support/webGPU)
EC2 Amazon Linux2にVoltaをインストールして使えるようにする

# 概要

- AmazonLinux2（以降AL2）でのAMIで起動したEC2インスタンスにVoltaを導入し、使えるようにする方法をまとめる。

# 前提

- 当該のEC2インスタンスにssh接続できること。

# 方法

1. EC2にssh接続する。
1. 下記コマンドを実行してVoltaをインストールする。

    ```shell
    curl https://get.volta.sh | bash
    ```

1. 下記コマンドを実行してcommand not foundにならなければVoltaの導入は成功している。

    ```shell
    volta
    ```

1. 後はバージョンを指定してnodeをインストールするだけである。

    ```shell
    volta install node@17
    ```

1. 筆者は`/home/ec2-user/lambda_layer/axios_bcrypt/nodejs`にディレクトリを作成し、当該ディレクトリまで移動した後に`$ volta install node@17`を実行した。
1. `$ node -v`を実行したところ問題なくnodeのバージョン情報が出力された。

    ```shell
    $ node -v
    v17.9.1
    ```

# 参考文献

https://volta.sh/

https://docs.volta.sh/guide/getting-started
AlfredからRaycastに乗り換えたらアプリがスッキリして作業効率も上がった話

## Raycastとは
非常に高速な動作かつ拡張性に富んだMacのランチャーアプリです。有料プランもありますが無料の範囲でもかなりのことができます。公式ドキュメントは[こちら](https://www.raycast.com/)。

## Raycastにしたら不要になったアプリ
AlfredからRaycastに乗り換えたことで個人的に最もメリットを感じたのは今まで個別にインストールしていたいくつかのアプリをRaycastの機能によって置き換えることができ、不要になったことです。

### Alfred（ランチャーアプリ）
そもそも私はAlfredをアプリの起動とファイルの検索ぐらいでしか使ってなかったのでAlfredからRaycastに乗り換えるデメリットは全くありませんでした。
### Clipy（クリップボード管理アプリ）
コード書くにも調べ事にも必須のアプリでしたがなんとRaycastにはクリップボードの管理機能がデフォルトで備わっておりClipyが不要になりました。Clipyで利用していた以下のような機能がRaycastにも備わっています。
- クリップボード履歴呼び出し
履歴は最大256エントリが保持され、画像をコピペした時はUIにプレビューも表示されます。
- スニペット登録／呼び出し
![2023-03-27_21.40.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3396242/42ebcaae-c205-273e-665d-bc8f03fa27fc.png)
### ShiftIt（ウィンドウマネジメントアプリ）
Hotkeyを登録しておくことでウィンドウの分割や画面への左右上下寄せなどができます。これは完全に性格だと思いますが私はウィンドウをきれいに画面分割して使いたい派なので重宝してました。ただ結構古い&もうメンテナンスされてなさそうだったので今回Raycastに置き換えられて個人的に有り難かったです。
![スクリーンショット 2023-05-15 16.55.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3396242/1d516bcd-2476-1c09-73d2-250048e03621.png)


## Raycastの便利機能
### 拡張機能
[Store](https://www.raycast.com/store)にはコミュニティによって開発されたいろいろな便利拡張機能があります。私がとりあえず入れてみてよかったのは[TinyPNGの拡張機能](https://www.raycast.com/kawamataryo/tinypng)です。
今までTinyPNGを使うときはCLIツールを入れたりブラウザのアプリを使っていましたがこの拡張機能を使うと圧縮したい画像をfinderで選択してRaycastから呼び出すだけで画像を圧縮してくれます。
（※TinyPNGのAPIキー取得にはメールアドレスの登録が必要になります。無料枠では月500ファイルまでの圧縮が可能です。[Developer API](https://tinypng.com/developers)）
![2023-03-27_22.02.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3396242/64cca4c2-0513-60dd-7a52-16f79c6873dd.png)
### 簡単なメモが書ける
テキストエディットのような簡単なメモが使えるのですが地味に便利でした。今までは何かさっとメモりたいものがあると常に出しっぱなしにしてるMacデフォルトのテキストエディットにメモしていましたがRaycastにもメモがあります。Hotkeyを登録できるので使いたい時だけキーボードショートカットで呼び出して使うことができます。
![2023-03-27_22.10.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3396242/9c6d8405-917e-cbc8-cf35-074f1ded2f7a.png)
### 開発フォルダをエディタで一発で開く
これはRaycast特有の機能ではないかもですが普段開発に使っているフォルダをブックマークとして登録しそれを任意のアプリ（VS Code）で開けるようにしておくと一瞬で作業環境を立ち上げられます。
![スクリーンショット 2023-05-15 17.06.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3396242/5c0c9b92-4867-7993-1468-370430a03f58.png)


## その他の細かい設定など
### 起動時に英語に設定
Raycastを開いた時にキーボードの言語が日本語になっているといちいち英語に変える必要がありますが、開いた時の言語を英語に予め設定しておくことができます。
![スクリーンショット 2023-03-27 22.19.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3396242/f0e8c857-3116-750c-05d9-cf586546b29a.png)
### 設定のエクスポート／インポート
設定はエクスポートして別のデバイスからインポートできます。
![スクリーンショット 2023-03-27 22.19.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3396242/e5a51d49-c02e-ae51-4203-f0ff48f8f9c1.png)
ChatGPTを始めてみよう！！

この記事では、入門者向けに「ChatGPTの始め方」を解説しています。
ChatGPTをまだ使ったことのない方は、難しいかなと思いますが、実際は簡単です！


~セットアップの流れは次のとおりです~

1.アカウント登録（メールでサインアップ）
2.メールアドレス認証
3.プロフィール入力
4.電話番号認証

1. アカウント登録（メールでサインアップ）
   ChatGPTの公式サイト (https://openai.com/blog/chatgpt)
へアクセスし、"Try ChatGPT"をクリックします。
"Sign up" をクリックします。
既にアカウントを持っている方は、"Log in"を押して、ログインしてください。

    メールアドレスを入力し、"Continue"をクリックします。
手順が少なくなるため、GoogleかMicrosoftの認証（SSO）の方法を推奨します。
    
    パスワードを入力し、"Continue"をクリックします。
最低8文字のパスワードである必要があります。

2.メールアドレス認証
    GoogleやMicrosoftによる認証を用いている場合は、メールアドレス認証の工程はありません。
メールアプリを開き、"Verify email address"をクリックします。

3.プロフィール入力
    ブラウザの「再読み込みのボタン」をクリックします。
もしもブラウザを消してしまった場合、再度ログインの画面に戻り、先ほど登録したメールアドレスとパスワードでログインしてください。

名前（First name）と名字（Last name）を入力し、以下の2点が問題なければ、"Continue" をクリックします。
1.利用規約に同意する人
2.18歳以上の人


4.電話番号認証
電話番号を入力し、"Send code" をクリックします。
電話にSMS等で送られた認証の番号（PINコード）を取得し、ChatGPT画面で入力したら、セットアップ完了です。
再度ChatGPTの公式サイトへアクセスし、"Try ChatGPT"をクリックし、ログインしてみましょう。
Nvidiaドライバが消えたけどインストールできない場合

# プログラムが謎に動かない

* 別な記事に補足で書いたのですが、Ubuntu22.04になってから軒並みこの現象がでています・・・
    * 参考に開発環境はAnaconda使っています。
    * プログラムが動かないので「nvidia-smi」をたたくとFailed to initialize NVML: Driver/library version mismatch。（今回）
    * 別にドライバーの一覧が直接出る事例もありました。
## 参考記事
@ell さんの記事を参考に修復を試みます。

https://qiita.com/ell/items/be3d3527b723f70f888d


## な、直らない・・・

```Ubuntu:ターミナル

lsmod | grep nvidia

#ここはOK

sudo rmmod nvidia_drm
sudo rmmod nvidia_modeset
sudo rmmod nvidia_uvm

```   


* 私の場合、最初のアンロードは成功 or Errorで実行不可
* nvidia_modesetで起動中画面に移行し、フリーズでした。

 # 試したこと
1. ”そのまま”ドライバの再インストール
2. ドライバの削除

１は再起動後、直っていない事を確認しました。
で、２をすると・・・

```Ubuntu:ターミナル

sudo apt remove nvidia* -y
sudo apt autoremove -y

```       
## 起動は成功するも画面は真っ黄色に・・・

* おそらく、CLI画面だせば苦行ではなかったとおもいますが・・・
* 黄色い画面で以下のコマンドを入力して、再インストール


```Ubuntu:ターミナル

ubuntu-drivers devices
sudo apt install nvidia-"適切なドライバ"

```   

# 結果は復活しました！

## 画面黄色の原因

:::note alert
教訓
バージョンに合わないドライバをインストールしないこと！
:::

**これに限ります**

* uname -a で22.04.xとあるxが肝だったようです。
* 最新ならいいやと思って入れたものの、今回のUbuntuは22.04.1、私を地獄におとしたのは末尾2でした。
* 基本的にはたくさんのいいねがついている@ell さんの記事で改善すると思われます。
超初心者向け VSCode の使い方

この記事では、これからHTML、CSSなどウェブデザインやプログラミングを勉強する人に便利な動画を紹介します。今まで、vscodeを使っていた人でも知らない便利な設定や使い方など、発見があると思うので、みてみるといいと思います。

下記で挙げている動画は、少し内容が重複しているものもありますが、一つの動画で全てを網羅できるわけでは、ないので、理想としては、全て一通り見ることをお勧めします。逆にこれを全て一通りみると基本的なvscodeの使い方は、十分理解できていると思います。

# HTML/CSSについて
[HTML・CSSってなに？学習の始め方解説 2021年最新版](https://www.youtube.com/watch?v=m4AOfxB6XR0)
 
# YouTube 動画
[Visual Studio Codeの使い方・便利機能解説！ショートカット/日本語化/Emmet](https://www.youtube.com/watch?v=pQ7tmTx5Zbk)
[VS Codeの使い方講座！日本語化する拡張機能のインストール](https://www.youtube.com/watch?v=csOaPNMDEwg)
[最低限知っておきたいVSCodeのUserとWorkspaceの概念](https://www.youtube.com/watch?v=xju_vOdbKFk)
[VS Code ショートカット](https://www.youtube.com/watch?v=cNyvefTJOcM)
[Visual Studio Code 拡張機能5選 インストールするだけ簡単](https://www.youtube.com/watch?v=taMpuUuFqIs)
[Emmet（エメット）の使い方解説！初心者でも簡単](https://www.youtube.com/watch?v=CSrq4qeiHrg)

# ドットインストール｜dotinstall
[Web制作の準備をしよう macOS編](https://dotinstall.com/lessons/basic_pcsetup_mac_v4)
[Visual Studio Code入門](https://dotinstall.com/lessons/basic_vscode)

# お勧め学習サイトとYouTubeチャンネル
[プロゲート｜Progate](https://prog-8.com)
[ドットインストール｜dotinstall](https://dotinstall.com)
[Webの神様](https://www.youtube.com/@webgodweb)
[しまぶーのIT大学](https://www.youtube.com/@shimabu_it)
vscode の個人的に追加,修正した shortcut(フロントエンド編)

## はじめに
​
vscode で自分の中でこれおすすめ！！っていうものを紹介します！
​
割と設定しない人が多いですが、覚えたら明らかに効率がいいので是非試してみてください！！
​
## タスク: タスクの実行
​
実行するタスクを選択で npm run dev 等のタスクを出せる物です。
​
僕は大体 npm コマンドを入力またはクリックなどがめんどくさいので、ショートカットにして、やります。
​
最近使用したものから出るので、よく使う `npm run dev` が上に来るので結構いいです。
​
あくまで個人的なおすすめのショートカットが下記です。
​
```
Ctrl + R
```
​
## Git: 変更を開く
​
差分を開くショートカットです。
​
差分を見るためにマウスを動かすのが大変って方にお勧めです。
​
あくまで個人的なおすすめのショートカットが下記です。
​
```
Shift + RightArrow
```
​
## 表示: エディターを閉じる
​
開いているエディターを閉じる
基本的に `Git: 変更を開く`の差分を開いて閉じる時に僕は使ってます。
​
そのため、`Git: 変更を開く`の対になるようなショートカットにしてます。
​
あくまで個人的なおすすめのショートカットが下記です。
​
```
Shift + LeftArrow
```
​
## 表示: パネルの表示/非表示の切り替え
​
ターミナルを表示、または非表示にするショートカットです。
​
ターミナル出し入れとかは結構めんどくさいので設定した方がいいです。
​
下 2 つのおすすめなショートカットを合わせて利用すると、ターミナルの位置が自由に出来ます。
​
あくまで個人的なおすすめのショートカットが下記です。
​
```
Ctrl + LeftArrow
```
​
## 表示: パネルを右に移動
​
ターミナルを右にしたいときに使用します。
​
僕で言うと、テストとかは縦長がいいので、このショートカットを使用することが多いです。
​
上下のおすすめなショートカットを合わせて利用すると、ターミナルの位置が自由に出来ます。
​
あくまで個人的なおすすめのショートカットが下記です。
​
```
Ctrl + RightArrow
```
​
## 表示: パネルを下に移動
​
ターミナルを下にしたいときに使用します。
​
上の 2 つのおすすめなショートカットを合わせて利用すると、ターミナルの位置が自由に出来ます。
​
あくまで個人的なおすすめのショートカットが下記です。
​
```
Ctrl + DownArrow
```
​
## さいごに
​
今回は windows の人が完璧におすすめ出来ますが、mac だと違うので mac のコマンドに合わせて修正してください。
​
また、これをおすすめなどがあれば教えてくれるとうれしいです。
gitの使い方(自分用)

# 初期化

```
git init
```

採取にリポジトリを作るとき以外は実行してはいけない。

# githubから共有されたリポジトリをとってくる

```
git clone https://github.com/XXXX/XXXXXX.git

```

"https://github.com/XXXX/XXXXXX.git" はリポジトリのURL

# ローカルで新しいブランチを作る

```
git checkout -b ブランチ名
```

# 別のブランチに移動する

```
git checkout ブランチ名
```

# ブランチの確認

```
git branch
```

### 注意

ブランチ毎に内容は独立しているので、１つのブランチで作業しても別のブランチは元のままなので注意すること

# ブランチ名の変更

```
git branch -m 古い名前　新しい名前
```

# ローカルのブランチをgithub上の共有されたリポジトリのコードで上書きする

```
git pull origin ブランチ名
```

# Pull repositoryをアップロードする

```
git add .
git commit -m "リクエストのタイトル(コメント)"
git push origin ブランチ名
```
### 注意

```
git push origin main
```

とするとpull requestを出さずに直接教諭されたリポジトリが上書きされてしまうので、やってはいけない！

何か更新をするときは

1. ローカルのmainにpull (git pull)
1. git checkout -b 新しいブランチ
1. コード実装
1. アップロード

の手順でやること！

# 過去の更新履歴を見る

```
git log
```

q (小文字)で終了できる

# リモートの共有リポジトリをひとつ前の状態に戻す

```
git revert 更新履歴のurl
```

# すでにローカルにあるフォルダをリモートにアップしたいとき

```bash
git init
git remote add origin  https://github.com/XXXX/XXXXXX.git
git add .
git commit -m "コメント"
git push origin master
```

# 参考記事

https://qiita.com/kohga/items/dccf135b0af395f69144
【Tableau】DATASaber:HandsOn - Fundamental(Ord1) Q7 解説

tableau datasaberになるための技術力に関する問題を解いていきたいと思います。
こちらの問題はtableauを始める方にぴったりだと思いますので、ぜひチャレンジしてみてください！
使用するデータは、「サンプル - スーパーストア.xls」を使用する。:arrow_down:
https://drive.google.com/drive/u/0/folders/1kXSb3fqPTt3VcPjGUSgOmrztlRfvvpMH

:white_check_mark:ord1-Q7
Excelで作っているグラフと同じようなレイアウトでグラフを作って欲しいと頼まれました。
サブカテゴリごとに、売上と利益に加え、数量も同時に見せてくれますか？（以下の図と同じグラフを作成して下さい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/a2983cb2-ff57-f87f-bd86-e0a8dcbb630e.png)


まず、サブカテゴリごとに数量、売上、利益を出したいので、
サブカテゴリと数量をビューに入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/045fad1c-73c0-0766-61b6-dd3bbed75793.png)
その次に、売上、利益も行に追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/e1c8f477-69dc-1b9f-4e16-fd9e2984e295.png)

次に、利益を売上の軸にドラッグ＆ドロップして、複合グラフにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/b4441d4c-ebc7-171c-4c83-ea5050af1853.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/81bca890-6be8-d43a-7803-40c582fbe2de.png)

メジャーバリューと数量を二重軸にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/ae334e16-bea7-087c-18e1-1e5616ff83d3.png)

メジャーネームをとって、数量を棒グラフに、メジャーバリューを線に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/68ccb2ae-44a4-235a-44d1-0ae2cae33f1e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/a7f835bb-48c1-9cd3-9a43-2a49d06fee0c.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/26f46c72-bd28-eb3b-39fb-c8a99bc23104.png)

最後に、見本のグラフは、棒グラフ（数量）の降順になっているので、
数量の降順に変更すると、見本のグラフの完成になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/2a2cab18-9b17-cf84-5dd1-262f2f9bdca6.png)

解説は以上になります！
最後まで読んでいただきありがとうございました！
もしよろしければ「いいね👍」お願いいたします！
jetpack compose&navigationを使って値付きで遷移する方法

# 初めに
今回は、`jetpack compose`と`navigation`を使った値付きの画面遷移実装方法を紹介していこうと思います
### 本文
スラッシュ以降は引数として認識をするので複数個渡したい時はスラッシュで区切っていけば渡すことができます
ただし、複雑な型は渡せないので取得するために必要な情報のみ、または`Json`に変換して`String`で渡す必要があります
```kotlin
val hoge = intent.getStringExtra(ARG_HOGE)
setContent {
            val navController = rememberNavController()
            TokubaiTheme {
                NavHost(
                    navController = navController,
                    startDestination = HogeRoute.HogeScreen.route,
                ) {
                    composable(
                        route = HogeRoute.HogeScreen.route,
                        arguments = listOf(
                            navArgument(ARG_HOGE) {
                                type = NavType.StringType
                                defaultValue = hoge
                                nullable = true
                            },
                        ),
                    ) {
                        HogeScreen()
                    }

                    composable(
                        route = "${HogeRoute.FugaScreen.route}/{${HogeRoute.FugaScreen.KEY_FUGA}}",
                        arguments = listOf(
                            navArgument(HogeRoute.FugaScreen.KEY_FUGA) {
                                type = NavType.StringType
                            },
                        ),
                    ) { backStackEntry ->
                        val fuga =
                            checkNotNull(backStackEntry.arguments).getString(HogeRoute.FugaScreen.KEY_FUGA)
                        FugaScreen()
                    }
                }
            }
        }
```
### 最後に
今回は自分が詰まった値付き繊維の方法を紹介していきました
どなたかのお役に立てれば幸いです
Google Cloud Professional Cloud Security Engineer を取得しました

# Google Cloud Professional Cloud Security Engineer を取得しました
2023/05 に Professional Cloud Security Engineer 認定資格を取得したので、そのとき実施した学習方法をまとめます。

https://cloud.google.com/certification/cloud-security-engineer?hl=ja

## 前提
Google Cloud 認定資格は Cloud Architect と Data Engineer を取得済みです。

https://qiita.com/ysmmb12/items/5327480781f28416685f

https://qiita.com/ysmmb12/items/a041a499106ad0df2754

この一年は BigQuery を中心に Google Cloud 学習中です。

## 学習方法
### Coursera
Cloud Architect と Data Engineer のときと同様に、基礎知識は Coursera で学習しました。

https://www.coursera.org/professional-certificates/google-cloud-security

このコースリストでは「Preparing for Your Professional Cloud Security Engineer Journey」が一つ目ですが、このコースの内容は試験対策用のまとめだったので、わたしは一番最後に受講しました。
また、「Hands-On Labs in Google Cloud for Security Engineers」以外は同名の日本語コースが用意されているので、そちらを使用しました。Coursera 内検索でコース名を指定すると出てきます。

### 模擬問題
試験概要ページから受験できる模擬試験や Udemy の対策試験を2回ずつ受けました。

https://www.udemy.com/course/google-cloud-professional-cloud-security-engineer-exam-a/

見直しに時間をかけ、不正解だったり正解でも不安が残る問題は公式ドキュメントを確認しました。


### ドキュメント
試験対策に G-gen 様のブログを参考にさせていただいたのですが、その中で紹介されている Google 公式ドキュメントや G-gen 様の技術記事も一通り目を通しました。

https://blog.g-gen.co.jp/entry/professional-cloud-security-engineer

## 受験
テストセンターで受験しました。
受験形式は以前の試験から変更なく、受験直後に仮合格がわかり、4日後に正式な合格通知がきました。

## 受験した感想
全体的に難しく、手ごたえはなかったです。落ちたと思いました。
G-gen 様のブログや模擬試験の中で調べたドキュメントをもっと時間をとってじっくり読めばよかったと思いました。
また、試験範囲のサービスは Coursera のハンズオンで触った程度だったので、ドキュメントや模擬試験に沿って実際に動かす機会を作ってもよかったと思ってます。


以上です。
どなたかの参考になれば幸いです。
<作成予定>React、Fluent UIを使ってみよう

Reactとは、、、
>Metaとコミュニティによって開発されているユーザインタフェース構築のためのJavaScriptライブラリである。
>React.jsまたはReactJSの名称でも知られている。 
>Reactはシングルページアプリケーションやモバイルアプリケーションの開発におけるベースとして使用することができる。

Fluent UIとは、、、
>エンタープライズ製品を開発する企業で支持されているオープンソースのデザインシステムです。 
>包括的なコンポーネントライブラリを使うことで、マイクロソフトのエコシステムに対応したアプリケーションを構築できるとともに、あらゆる製品のテーマ設定による完全なカスタマイズと柔軟性を実現します。


作成予定
【Python】連想配列とは

## 連想配列とは
連想配列とは、キーと値をペアとして格納するデータ構造のこと。
Pythonでは辞書(dictionary)が連想配列に相当する。

## 連想配列の特徴
連想配列の特徴的な機能は、**キーを使った値の高速な検索**。
例えば次のように辞書を作成し、キーを指定して値を取り出すことができる。
```Python
my_dict = {'name': 'Alice', 'age': 25, 'job': 'Engineer'}
print(my_dict['name'])  # 出力: Alice
```

また、キーと値のペアは追加や更新も容易で、次のように新たなペアを追加したり、既存の値を更新することが可能。

```Python
my_dict['hobby'] = 'Reading'  # 新たなペアの追加
my_dict['age'] = 26  # 既存の値の更新
```

辞書は**順序を保持しない**という特徴もある。
⇨データが追加された順序ではなく、キーに基づいてデータが管理される。
(ただし、Python 3.7以降では、辞書はデータが追加された順序を保持するようになった)

## 連想配列を使う場面

連想配列は、**キーに対応する値を効率的に検索したいとき**に特に有用。
例えば、人の名前をキーとし、その人の情報を値とする辞書を作成すれば、名前から迅速に情報を引き出すことができる。

また、**頻度カウント**のような処理も連想配列を使えば効率的に行える。
文字列やリストなどの要素の出現頻度をカウントするとき、要素をキーとし、その出現回数を値とする辞書を作成すると、カウントの操作が容易になる。

## まとめ

連想配列は、キーと値のペアを効率的に管理するためのデータ構造であり、Pythonの辞書はその代表例である。データの追加、更新、検索を高速に行うことができる。
ブラウザのストレージを全く使わないクロスドメインで使えるストレージサービスを作った

# 背景
昨今、ITP規制などによって3rd parth cookieがどんどん排除されたり、有効期間が短くなったりとbrowserからアクセスできるユーザーのstorageはどんどん使いにくくなっている。
そこで、browserのストレージを全く使わずに保持できるstoreがあればいいなと思い、OSSライクなライブラリを作成した。

https://github.com/araj-dev/linkchain

# 使い道
Globalなsession storeだと思っていただければほぼその通りです。
ただのsession storeと違うところは、指定のaタグに対して自動的にuuidをクエリに付加するため、クロスドメインでの遷移に対応している部分です。

# **注意**
現在、experimentalなので、使用は自己責任でお願いします。
storageは一度networkの共有KVに送られるため、uuidv4が衝突した場合、データが露出する可能性があります。
**絶対にsecureなデータを使用しないでください。**

# 使い方
githubのREADMEにも書いているが、基本的にはheadでscriptを読み込ませた後、指定のsnippetを挿入することでリンク遷移先のアドレスでも、遷移前にsetしたデータが使用可能になる。


1. SETするページのexample
```html
~~~
<!-- headでsdkを読み込み -->

<head>
  <script async src="https://lc.araj.jp/lc.min.js"></script>
</head>
~~~

<!-- 共有したいリンク先のaタグにdata-lcのattributeを付与する -->
<a href="https://example.com" data-lc="true">external link</a>

~~~

<!--　共有したいデータをsetしておく -->

<script>
  linkchain = window.linkchain || {}
  linkchain.ready = function (lc) {
    lc.set({ test: "test" }) // objectをそのまま渡す
  }
</script>

```

2. GETするページのexample

```html
~~~
<!-- headでsdkを読み込み -->

<head>
  <script async src="https://lc.araj.jp/lc.min.js"></script>
</head>
~~~

~~~

<!--　共有したいデータにアクセスする -->

<script>
  linkchain = window.linkchain || {}
  linkchain.ready = function (lc) {
    console.log(lc.data)
    // { test: "test" }
  }
</script>

```

# 今後
現在、vercelのhobbyプランを使用しているため通信回数などにグローバルな制限があり、安定動作はしていません。
もし需要があれば、namespaceで区切られたデータ領域や、指定ドメインの制限などの機能を追加する予定です。
現状の最優先の目標はjwtトークンを利用したone-time authを実現し、secureなデータでも安心して使えるようにすることです
トンネリングって分かりづらいよね

# 初めに
リモートワークが普及した現在、必須と言っても過言ではないのがVPN。「暗号化」とか「トンネリング」等断片的な情報は見聞きするものの、仕組みがイマイチわからない。そんなあなたへ、VPNについて説明します。VPNの「暗号化」部分は想像しやすいので、この記事は「トンネリング」について説明します。

# なんでVPNが必要なの?
**離れた拠点間でも安全にLAN内の機器と通信したい**というのが主な目的となります。元々拠点間で通信するためには専用線を設けることがありましたが、これはコストがかかります。そのため、通常のインターネット回線を介しても**専用線のように通信できるような技術が必要でした。** 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/929fdf78-a3b5-4f50-e8e5-4f33e65cdc73.png)

インターネットを介す通信の場合、以下の問題があります。

- 自宅/会社はプライベートIPアドレス、インターネットはグローバルIPなので疎通させるためには工夫が必要
- インターネットを介す場合盗聴などの危険がある

盗聴は「暗号化」によってある程度は対応できますが、プライベートIP/グローバルIPアドレスは厄介です。プライベートIP/グローバルIPの変換ならNATがありますが

- グローバルIPアドレスと対応付けられた機器は公開されることとなり、セキュリティ上問題となる
- アクセスしたい機器が大量にある場合、NATだと限界がある

上記で記載したような問題があります。またできれば社内ネットワークに接続できるユーザは制限したいですね。これらを解決する際に利用されるのが「トンネリング」と呼ばれる技術です。このトンネリングの肝は「カプセル化」です。

# そもそもデータ&カプセル化とは

カプセル化の説明をする前に、ネットワーク上に流れるデータの構造を理解する必要があります。詳しくはこちらの記事を見てください。

https://qiita.com/na-777/private/d656f720709de2ca4ec4

# トンネリング
トンネリング用のプロトコルとして代表的なものでGREというものがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/27d2bf44-d71e-f6fb-b7b0-d4996560c67d.png)
[GRE（Generic Routing Encapsulation）とは](https://www.infraexpert.com/study/rp8gre.htm)

Q. 冒頭で話をした、プライベートIPアドレスのネットワークから、グローバルIPアドレスのネットワークを介してアクセスするにはどうすればいいか？
A. L3(プライベートIPアドレス)のパケットをL3(グローバルIPアドレス)でカプセル化する。

これだけではわからないので、もう少し詳しく説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149438/4bcaf783-5c5f-b937-d0ea-b56f0aefd400.png)
[GRE（Generic Routing Encapsulation）とは](https://www.infraexpert.com/study/rp8gre.htm)

R2(192.168.2.0/24)のLANからR1(192.168.1.0/24)のLANへ通信したい場合、パケットは以下のような動きをします。

- R2のLAN内の機器(192.168.2.X)から、R1のLAN内の機器(192.168.1.X)へを送信する。この時点のパケットの宛先/送信元は下記の通り。
    - 宛先がR1のLAN側のプライベートIPアドレス(192.168.1.X)
    - 送信元がR2のLAN側のプライベートIPアドレス(192.168.2.X)
- R2は受け取ったパケットをGREパケットとしてカプセル化する。GREパケットの宛先/送信元は下記の通り。
    - 宛先がR1のWAN側のグローバルIPアドレス(1.1.1.1)
    - 送信元がR2のWAN側のグローバルIPアドレス(2.2.2.2)
- R1は受け取ったGREパケットのカプセル化を解除する。解除後のパケットの宛先/送信元は下記の通り。
    - 宛先がR1のLAN側のプライベートIPアドレス(192.168.1.X)
    - 送信元がR2のLAN側のプライベートIPアドレス(192.168.2.X)

最終的にR1のLAN内に届くパケットは、あたかも隣接するプライベートネットワークから送られてきたデータのように見えます。またトンネリングという呼称をされていますが、イメージ的には、

- 送りたい商品(パケット)に宛名を書く
- 梱包箱(GREパケット)に入れ、住所を記載して発送

というのが実際の動きに近いです。ネットワーク的な疎通を解決するためにカプセル化は頻繁に使用されます。例えばFWでHTTPの通信のみ許可されている環境でFTPを使ってファイル転送をしたい場合、FTPデータをHTTPデータでカプセル化する方式(FTP over HTTP)もあります。

トンネリングはネットワーク的な疎通は解決できますが、暗号化されているわけではないので、盗聴のリスクが残ります。そのためIPsecのような暗号化と組み合わせます。トンネリングとIPsecを使ったVPNは、IPsec-VPNと呼ばれます。

# まとめ
- VPNはトンネリングと暗号化の組み合わせで実現される
- トンネリングは異なるネットワーク間で疎通ができるように、データをカプセル化する仕組みを指している
- トンネリングと呼称されているものの、「送りたい物(パケット)を別容器(GREパケット)に梱包する」というのが実際の動きに近い
<作成予定>ABAP on Exercism を確認してみる。

Exercismとは、

>オンラインでオープンソースの無料のコーディング プラットフォームであり、62 の異なるプログラミング言語でコードの練習と指導を提供。

とのことで、要は、オンラインでの学習サイトのことのようです。

Qiitaの以下記事をもとにやってみる。
https://qiita.com/SAITO_Keita/items/75fb47fd00c832269a81

ざっくりの流れだと、
①Exercismを利用するためのユーザー登録
必要な情報は
接続URL：https://exercism.org/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118752/ff436175-f612-6edd-742a-c1e73dbba420.png)
USERNAME：半角英数字記号でユニークになるユーザー名が必要
EMAIL：有効なメールアドレスが必要（この後にメールがくる）
PASSWORD：パスワード
PASSWORD CONFIRMATION：パスワードの確認
CONFIRM YOU'RE NOT A BOT：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118752/06ed998c-2934-ce7d-4d71-310c5cc7f9e8.png)

②ABAPのコースの登録
　①が済むと無事ログイン完了
　TracksからABAPの登録に進む
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118752/8a8f09f8-2bb9-4824-4855-a4460faca7a1.png)
検索エリアにABAPを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118752/8099cc02-80fd-482c-a4e6-f54cd3f94b28.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118752/6daefb5b-9720-c3cd-255f-51fff9cec471.png)
　Join the ABAP Trackをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118752/e8c91de4-d174-5da3-f23d-0532a3b6e953.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118752/bbe94ea7-e2f2-6aab-3fda-a699191b266c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118752/58a3a3da-c632-1d09-90c8-4d8da28ab00f.png)

③コースを始める。
　Start in editorで開始する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118752/26d2c675-92c5-98cb-5919-2adb66b752c0.png)

作成予定
vue3 provide と inject

親から子にデータを渡すのに使う。
App.vue → Home.vue にデータを渡したい。

provide で 格納
inject で 取り出し

```App.vue
<template>
    <router-view></router-view>
</template>

<script lang="ts" setup>
import {provide, ref, onMounted, inject, reactive, computed} from 'vue';

const data = reactive({
    age: '99'
})

provide('age',computed(() => data.age))
</script>
```


```Home.vue

<template>
    年齢テスト {{userAge}}
</template>

<script lang="ts" setup>
import { ref , onMounted ,inject } from 'vue';
const userAge = inject('age')
</script>

```

これで 99 と表示される。
[自分用]polars移行メモ

# 概要

polarsが早いと噂なので（遅すぎるが）移行したいので自分用メモ。

##### 参考
+ https://pola-rs.github.io/polars-book/user-guide/
+ https://qiita.com/nkay/items/9cfb2776156dc7e054c8

# 環境

+ google colaboratory

# sample

## データ入出力

### csv読み込み

```python
import polars as pl

df = pl.read_csv("iris.csv")
```
 + csv読み込みはpandasと同様
 + オプションのキーワードが違うので注意

### csv出力

```python
df.write_csv("iris2.csv")
```
+ csv出力は`write_csv`を使用する
    + pandasの場合は`to_csv`

## データ可視化

### 先頭、末尾

```python 
df.head()
df.tail()
```
+ デフォルトで5行出力

### サマリー

```python 
df.describe()

""" 出力サンプル
describe	sepal_length	sepal_width	petal_length	petal_width	species
str	f64	f64	f64	f64	str
"count"	150.0	150.0	150.0	150.0	"150"
"null_count"	0.0	0.0	0.0	0.0	"0"
"mean"	5.843333	3.054	3.758667	1.198667	null
"std"	0.828066	0.433594	1.76442	0.763161	null
"min"	4.3	2.0	1.0	0.1	"setosa"
"max"	7.9	4.4	6.9	2.5	"virginica"
"median"	5.8	3.0	4.35	1.3	null
"25%"	5.1	2.8	1.6	0.3	null
"75%"	6.4	3.3	5.1	1.8	null
"""
```

+ describeも同様に使用できる
    + null_countが見えるのが偉い

## データフレームに対する処理

### フィルタリング処理（pandasと使い勝手が大きく違うので注意）

例: irisデータセットからsepal_lengthが7cm以上の行を抽出する

```python 
df.filter(7 <= pl.col("sepal_length"))
```

+ polarsでは条件を満たす行の抽出には`filter`を使う
    + filterの引数にEXPRESSIONを渡す
        + https://pola-rs.github.io/polars-book/user-guide/concepts/expressions/
+ pandasみたいに`df[df["sepal_length"] > 7]`と書けない

### 列の追加（pandasと使い勝手が大きく違うので注意）

例: irisデータセットからsepal_lengthのサイズに応じて["S", "M", "L"]のラベルを新たな列を作成し付与する

```python 
# applyを使用する場合
df.with_columns(
    df["sepal_length"].apply(lambda x: "S" if x < 5 else ("M" if x < 7 else "L")).alias("SML")
)
# EXPRESSIONを使う場合
df.with_columns(
    pl.when(pl.col("sepal_length") < 5).then("S")
    .when(pl.col("sepal_length") < 7).then("M")
    .otherwise("L")
    .alias("SML")
)
```

+ 列の追加には`with_columns`を使用する
    + applyはpandas同様に使用できる
    + expressionを使うことも可能
+ 追加する列のcolumn名は`alias`で指定する
   
### データフレームのソート

例:`sepal_length`で降順にソート後`sepal_width`で昇順にソートする

```python 
df.sort(["sepal_length", "sepal_width"], descending=[True, False])
```

+ pandasのsort_valuesとほぼ同じ
    + オプションの向きが違うので注意(pandasは`ascending`)

## 遅延評価（pandasと使い勝手が大きく違うので注意）

```python 
# csv読み出しの時から遅延評価する
df = (
    pl.scan_csv("iris.csv")
    .filter(5 <= pl.col("sepal_length"))
    .with_columns((pl.col("sepal_length") / pl.col("sepal_width")).alias("sepal_ratio"))
    .groupby("species").agg(
        [
            pl.col("sepal_length", "sepal_width", "sepal_ratio").mean().suffix("_mean")
        ]
    )
    .collect()
)

# 特定の処理を遅延評価する
df = (
    df
    .lazy()
    .filter(5 <= pl.col("sepal_length"))
    .with_columns((pl.col("sepal_length") / pl.col("sepal_width")).alias("sepal_ratio"))
    .groupby("species").agg(
        [
            pl.col("sepal_length", "sepal_width", "sepal_ratio").mean().suffix("_mean")
        ]
    )
    .collect()
)
```
+ pandasにない概念
+ `scan_csv()`~`collect()`で挟んだ箇所はpolarsが最適化してまとめて実行する
+ 公式は遅延評価を推奨している
Next.js - Firebase 環境における functions/src/index ファイルの扱いについて

## 以下の手順を踏む
ルートディレクトリ直下でそのまま
``$ npm run build``
を実行するだけでは、functions/src/index の変更は反映されない。
TypeScript の場合は、
``$ cd functions`` // functions 下で npm コマンドを回す必要がある
``$ npm install``  // package.json の変更を反映させる
``$ npm run build``
``$ firebase deploy --only functions``
を実行することで初めて変更が反映される。
Firebase 上の Functions にデプロイが反映されたことを確認する

![スクリーンショット 2023-05-15 13.53.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984875/57109cf2-5291-fc49-24f5-144156c5d5ca.png)
blocklyでverilog

# 概要
blocklyでverilog、やってみた。

# 参考にしたページ。

https://github.com/MarwanYoussef/Visual-Verilog


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3b1c63a2-6c93-2ac4-5cc2-093a4857063b.png)


# 成果物

https://plnkr.co/plunk/JQKdLX20IWWienRN


以上。
Ubuntu 22.04 でRISC-V向けClang 16をビルドする

Clang 16ではRVV向けAuto-vectorizationができるらしいというのを聞いて，ここ最近Clang16をビルドしようと四苦八苦していました．

基本的には下記公式ドキュメントをもとにしています．

https://llvm.org/docs/GettingStarted.html

バージョンは16.0.3となります．また，`apt`で足りないツール類は適宜インストールしてください．

下記の2つの記事のインストールは完了させてください．

https://qiita.com/zacky1972/items/0cbfdf4e400e0205aa7b

https://qiita.com/zacky1972/items/6d433bdbef737d1e300f

あらかじめ，次の作業をしたのでした．

```bash
sudo ln --symbolic /usr/include/* /usr/local/riscv/include
```

(すでに存在する`/usr/local/riscv/include/gdb`のみエラーになると思います)


ではビルドするスクリプトを紹介します．

```bash
git clone https://github.com/llvm/llvm-project.git
cd llvm-project
git checkout llvmorg-16.0.3
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local/riscv -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DLLVM_BUILD_TESTS=False -DLLVM_DEFAULT_TARGET_TRIPLE="riscv64-unknown-elf" -DDEFAULT_SYSROOT=/usr/local/riscv/riscv64-unknown-elf -DLLVM_TARGETS_TO_BUILD="RISCV" -G Ninja ../llvm
ninja
sudo ninja install
```

`cmake`で指定しているオプションについて解説します．

* `-DCMAKE_BUILD_TYPE=Release` リリース版をビルドします．
* `-DCMAKE_INSTALL_PREFIX=/usr/local/riscv` インストール先を`/usr/local/riscv`にします．
* `-DLLVM_ENABLE_PROJECTS="clang"` Clangをビルドします．
* `-DCMAKE_C_COMPILER=/usr/bin/gcc` ビルドで用いるCコンパイラを指定します．ここでは`/usr/bin/gcc`を用います．
* `-DCMAKE_CXX_COMPILER=/usr/bin/g++` ビルドで用いるC++コンパイラを指定します．ここでは`/usr/bin/g++`を用います．
* `-DLLVM_BUILD_TESTS=False` テストスクリプトをビルドしないようにします．テストスクリプトのビルドのためには`#include`を処理できる必要があるのですが，今回確立した方法ではヘッダファイルを含めることに失敗しているので，ビルドしないようにする必要があります．
* `-DLLVM_DEFAULT_TARGET_TRIPLE="riscv64-unknown-elf"` `target`オプションなしでコンパイルした時のターゲットを`riscv64-unknown-elf`にします．
* `-DDEFAULT_SYSROOT=/usr/local/riscv/riscv64-unknown-elf` ビルドしたコンパイラが参照するライブラリやヘッダファイル類を定義する`SYSROOT`を`/usr/local/riscv/riscv64-unknown-elf`にします．
* `-DLLVM_TARGETS_TO_BUILD="RISCV"` RISC-Vをターゲットにできるようにします．
* `-G Ninja` この後，Ninjaでビルドできるようにします．

# 検証方法

次のようなCプログラムがコンパイルできることを確認します．

```c:hello.c
int main()
{
    return 0;
}
```

```bash
clang -march=rv64g hello.c 
spike /usr/local/riscv/riscv64-unknown-elf/bin/pk a.out 
```

同様に次のようなCプログラムもコンパイルできます．

```c:hello.c
#include <stdint.h>

int main()
{
    int64_t a = 0;
    return (int)a;
}
```

次のようなプログラムもできました．macOSではできなくて苦労していました！


```c:hello.c
#include <stdio.h>

int main()
{
	printf("hello, world.\n");
}
```
ChatGPTのAPIを3ヶ月使ってわかってきた、良い出力を得るための指針

ChatGPT APIリリースの衝撃から(およそ)3ヶ月。

私が所属する旅行系スタートアップのAVA Intelligenceでは、APIリリース以降、ミッション"Discover the Best For You"を実現するための重要技術と位置付け、様々に活用してきました。

https://www.ava-intel.com/

中でも、自然言語で旅行について聞くことができるLINEボットがご好評をいただいています。

https://prtimes.jp/main/html/rd/p/000000006.000047676.html

▼AVA Travelの公式LINE
![S_gainfriends_2dbarcodes_GW.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214534/dfe80c5e-43ba-5134-e1f8-0c23725382e4.png)

https://lin.ee/hcbVSAK


3ヶ月間、ChatGPTのAPIを使って目的を達成する方法を模索する中で、重要だと考えることを整理しました。

## 指針1.分割して各個撃破する

あなたはAIでどのような問題を解決しようとしていますか？
大抵の解くべき問題は、複雑で難しいです。
大きくて難しい問題を分割し、解けるサイズに分けて、扱いやすくすることは、ChatGPTを使う開発において大きな効果を発揮します。

課題を分割することで、AIではなくルールベースで解くべき課題を抽出できた場合、パフォーマンスの向上や良質な出力につながる場合があります。

- テキストの抽出タスクは正規表現の方が早く、性能が高いかもしれない
- 固有名詞の抽出は、形態素解析ライブラリの方が早く、性能が良いかもしれない
- 提案対象の生成を検索システムに切り出すことで、事実に根差した回答ができる（ReAct 後述します）

私はAVA Travelチャットを実装する上で、 AIが解くべき問題は以下の二つと位置付けています。

- ユーザーが、何を求めているかを特定すること
- 理由付きで、ユーザーに寄り添った提案を生成すること

提案内容を決定することは、AIが解くべきタスクとはせず、検索システムと協力します。これによって、素のChatGPTでは不可避な嘘の対策を行いました。

LLMに検索システム等で知識を与えることで、良い出力を目指す構成は"ReAct"と呼ばれ、私たちも"ReAct"を参考にした設計としました。

- ReAct参考スライド(実装を行う上で何度もお世話になりました)
https://speakerdeck.com/hirosatogamo/da-gui-mo-yan-yu-moderudebian-warumlsisutemukai-fa?slide=27

この指針は、「分割統治法」「Devide and Conquer」と呼ばれる指針に近いと思います。
これらは「ゆるコンピュータ科学ラジオ」というポッドキャストで知りました。以来AI開発以外でも、エンジニアリングを行う上で重要な指針だと考えています。

https://www.youtube.com/watch?v=5RZK9D_EU4U

## 指針2.首尾一貫した目的を与える

課題（を解決するためのプロンプト）を分割するアプローチを紹介しました。

課題を分割した際に重要なのが、「首尾一貫した目的」です。

一貫して良質なアウトプットを担保するためには、各個のコンポーネントが、最終目的を意識する必要があります。

同じ矢印を向いた組織は強いですよね。それ以外にも、現実社会の似た状況を考えてみましょう。

- 組織の目標と個人の目標を関連づけることで、効率的な目標達成と高い従業員エンゲージメントを目指すOKR
- ユーザーストーリーに集中することで、顧客にとっての価値を最大化するためのアジャイル開発

何だかAIに向き合っていると、マネジメントの勉強になっているような気がします。この辺りからもシンギュラリティを感じます。

例えば、「大量の観光スポットの旅行記事を作る」というタスクを、下記のタスクに分解したとしましょう。

- 検索エンジンに投げるクエリを生成する
- 大量に収集した検索結果のスニペットを要約する
- 中間生成物の要約から記事を生成する

この時、中間生成物の質が成果物の質に大きな影響を及ぼします。

具体的には、以下のような調整を行うことで、アウトプットの質が向上します。

- 検索エンジンは、旅行にフォーカスした記事を返すべきだから、検索ワードに「旅行」「観光」等のキーワードを入れる
- 検索結果のスニペットを要約する際のプロンプトでは、「旅行者目線での要約」を依頼する

## 指針3.良質な例を与える

当初、目的の出力を得るために大量の詳細な条件を指定しました。
ところが、与える条件が増えるにつれ、出力に指示が反映されなくなりました。

それを解決してくれたのが例を与えるアプローチ。Few-shot learningを採用し、いくつかの出力例を与えることで、期待する回答にグッと近づきました。

▼ OpenAIが提供するFew-shot learningの説明
https://github.com/openai/openai-cookbook/blob/main/techniques_to_improve_reliability.md#few-shot-examples

大量の詳細な指示よりも、良質な出力例と、一貫した目的。もし僕がAIだったとしても、そんな指示の方が良いアウトプットを目指して楽しく仕事できそう。

## まとめ

ここまで、現時点で重要だと感じることを書きましたが、日々模索と改善を続けています。
LLMとシステムを組み合わせることは、まだ確立しきっていない技術ですし、今後も良質な出力を求める過程で新たな発見や、技術の進歩に伴う変化があるはずです。

今後もユーザーの要望を満たすために真摯に開発を続けていきたいと思っています。
Matzさんのスピーチに引用された言葉を胸に秘めつつ。

> The best way to predict feature is to invent it. 
(@RubyKaigi2023)
NEC VersaProにUbuntuをインストールしようとしたら、Secure Bootって知らん人に怒られました

# Ubuntuのインストールが開始されないんだが
職場でWindowsPCとして利用していた端末にUbntuを入れることになりました。
<b>が、</b>「OSインストールなんてオンプレでも、自宅でも何度もやったことあるぜ!」とたかを括っていたら、想定外なところでハマりました。

状況としては、Ubuntuのインストールメディア化させたUSBメモリを接続して、BIOSから起動優先順位を1位にした後に起動しようとしても、BIOSの画面から抜けることができませんでした。なんてこったい。


# 環境
NEC VersaPRo
UEFI BIOS version:N1YET57(1.35)
Ubuntu20.04 LTS

Ubuntuインストールメディアは既に作成済みとします。
今回はダウンロードしたUbuntuのISOファイルをRufusでUSBメモリに焼きました。


# 原因
<b>BIOSのSecure BootがEnabledになってました。</b>
浅学なもので、この項目を見るのは初めてです。
知らない人に怒られるのって結構メンタルにダメージきますよね。

# 対処法
<b>Secure BootをDisabledにします。</b>
手順は以下のような具合です。

1.PC起動後、NECのロゴが表示されたらF2を連打してBIOSに入る
2.「Security」タブから「Secure Boot」を選択し「Disabled」にする
3.「Startup」タブから「UEFI/Legacy Boot」を選択、「UEFI only」を「Legacy only」へ変更
4.「Boot」タブからubuntuを入れたUSBメモリを「Boot Priority」の1位にする
5. 設定を保存して、再起動

再起動後、Ubuntuインストールの開始画面が表示されれば解決です。

# ところでSecure Bootって何？
https://learn.microsoft.com/ja-jp/mem/intune/user-help/you-need-to-enable-secure-boot-windows

要はUEFI(BIOSの後継システム)といったハードのファームウェア側が署名を所持し、その署名とWindowsOSをはじめとしたブート用ソフトウェアと適合するかを確認するという仕組みです。
署名が適合してはじめてWindowsOSが起動するので、もちろんUbuntuの起動は禁止されますよね。

ちなみにUbuntuのインストール作業を終えた後、BIOSの設定をデフォルトに戻したら、やっぱりUbuntuは起動しませんでした。

# おわりに
所属部署でLinuxを運用できるのが自分しかおらず、また自分もLinux運用経験をウリに今の職場にやってきましたので、周りの人がもの珍しそうにちらちら覗いてくる中でハマってちょっと冷や汗をかきました。
C# の XUnit で private static method をテストする

private method をテストするには Reflection で！というのは良く出てくる。
では private <strong>static</strong> method は？ということで書いてみる。
ついでに Exception もテストする。

## テスト対象コード
こんな感じのファイルパスを受け取ってディレクトリ名を返すシンプルな private static method があるとする。

```c#
using System;
using System.IO;

public class FileUtil
{
    /// <summary>
    /// ファイルパスからディレクトリ名を取得
    /// </summary>
    /// <param name="filePath">ファイルパス</param>
    /// <returns>ディレクトリ名</returns>
    private static string GetDirectoryName(string filePath)
    {
        if (string.IsNullOrEmpty(filePath))
        {
            throw new ArgumentException("File path が null または 空です。", nameof(filePath));
        }
    
        return Path.GetDirectoryName(filePath);
    }
}
```

## テストコード
こんな感じでメソッドを実行できる。Invoke した method は Exception を投げられた時に「TargetInvocationException」が返されるため、ex.InnerException を再度 throw する。

```c#
using System;
using System.Reflection;
using Xunit;

public class FileUtil_GetDirectoryNameTest
{
        /// <summary>
        ///  private static method の GetDirectoryName テスト用 Reflection
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private string Reflection_GetDirectoryName(string filePath)
        {
            var method = typeof(FileUtil).GetMethod("GetDirectoryName", BindingFlags.NonPublic | BindingFlags.Static);
            try
            {
                return (string)method.Invoke("GetDirectoryName", new object[] { filePath });
            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
        }

        [Fact]
        public void ValidInput_ReturnsGetDirectoryName()
        {
            // Arrange
            string filePath = @"C:\example\test.xml";
            string expected = @"C:\example";

            // Act
            string result = Reflection_GetDirectoryName(filePath);

            // Assert
            Assert.Equal(expected, result);
        }

        [Theory]
        [InlineData(null)]
        [InlineData("")]
        public void InvalidFilePath_ThrowsArgumentException(string filePath)
        {
            // Act and Assert
            var exception = Assert.Throws<ArgumentException>(() => Reflection_GetDirectoryName(filePath, newExtension));
            Assert.Equal("File path が null または 空です。 (Parameter 'filePath')", exception.Message);
        }
}
```