OmniAICreator/Qiita-1.07M huggingface dataset:
DXのカギを握る「SRE」の役割　※現状と考察

経済産業省は2022年12月に公表した「DX推進 スキル標準」で、インフラ運用を担うエンジニアのロールに「SRE」(サイト信頼性エンジニアリング)を加えたようですね。

ちなみに、SREとは、グーグルが提唱するシステム管理とサービス運用の方法論となります。
新たなサービスの投入とその信頼性の維持を両立するために、運用業務の環境 整備、システムの自動化、問題発生時の対応といった全般的な役割を担います。

例えば、ログ取得の自動化ツールを作成したり、リリース前に細かなバグを修正したりすることで、開発チームが新機能開発に集中できるようにすることもSREの役割となります。

従来の開発現場では、ユーザの求める新しい機能を次々と追加したい開発側と、可能な限りリスクを避けてシステムの安定性を維持したり運用側との対立が見られたりしていました。

SREが舵取り役となり、開発・運用業務の環境整備やシステム管理の自動化などを進めることで、異なる目的やスキルを持つ開発チームと運用チームの縦割りの弊害が回避できるようになります。

その結果としてシステムの迅速なリリースや信頼性の向上、運用コストの削減も可能になっていくでしょう。

そのため、益々SREを担当するエンジニアには、クラウドインフラの構築 ・運用スキルはもちろん、開発側と連携していくために必要なソフトウェア開発スキルが求められるのでないかと思います。

合わせてセキュリティーに関する知識、また連携を円滑に進めるためのコミュニケーションスキルも求められる、そんな感じでしょうか。

ちなみにSREは、アマゾンやネットフリックスなど大規模なシステムを運用する海外企業が導入しています。日本でもメルカリが15年にSREチームを立ち上げ、プロダクトのスケーラビリティー向上に大きな役割を果たした。

今後、DX推進においてシステムの信頼性の確保などがより一層求められるのに伴い、SREの重要性はさらに高まっていくと考えられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2233790/0cc2623d-b141-e212-2ee5-8b12406e9c10.png)
■カジュアル面談受付中
下記からスケジュール設定可能となります。
https://t.co/91lhm0x2JE
～・～・～・～・～・～・～・～・～・～・～
LinkedIn
https://www.linkedin.com/in/akkodis-okada/
Twitter(X)
https://twitter.com/edamamecook
[Node.js] npmとはなんだろう

# 目的
アプリケーションを開発するにあたり、npmコマンドが多く使われているのでどのようなものか、その使い方をまとめる。

# npmとは
- nodeのパッケージを管理するためのツール
	- node
		サーバー上(ブラウザ外で)でJavascriptを動かせるプラットフォーム。
- パッケージのインストールやアンイストール、アップデートなどできる
- パッケージの依存関係を解決できる

# コマンド
#### 現在のバージョン確認
```
npm -v
```
#### 初期化
```
npm init
```
プロジェクトの作成。packeage.json作成。
- packeage.json
	プロジェクトの詳細が書かれたファイル
    インストールしたいパッケージなどを記載する


#### インストール
``` 
npm install パッケージ名
npm i パッケージ名

# パッケージのバージョン指定
npm i パッケージ名@x.y.z
``` 

```
npm ci
```

npm i はpackage.jsonに基づいてパッケージをインストール。
npm ci はpackage-lock.jsonに基づいてパッケージをインストール 
- packeage-lock.json 
    実際にインストールしたモジュールの詳細情報(バージョンなど)が書かれているファイル

npm i はpackeage.json, packeage-lock.jsonを変えてしまう可能性あるので、git cloneしたときなどグループでパッケージのバージョンを固定したい時はnpm ci する。
インストールしたパッケージはカレントリディレクトリ配下のnode_muduleに配置される。

種類
```
＃ ローカルインストール
npm install パッケージ名

＃ グローバルインストール
npm i -g パッケージ名

＃ devDevpenciesにインストール
npm i --save-dev パッケージ名

＃ devDevpenciesにインストールの省略形
npm i -D パッケージ名
```
- ローカルインストール
    現在いるディレクトリのプロジェクトへのインストール
- グローバルインストール
    PC自体にインストール
- devdDevpencies
    開発やテストに使用するパッケージ（本番で使わないパッケージ）を設定
    本番で使うのはdependencies

#### アップデート
```
# インストールしたパッケージにアップデートがあるかの確認
npm outdated

# パッケージ指定してアップデート
npm update　パッケージ名

# packeage.jsonに記述されたすべてのパッケージをアップデート
npm update
```

####  アンインストール
```
npm uninstall パッケージ名
npm remove パッケージ名
npm r パッケージ名

# アンインストール時にpackage.jsonのdependenciesの記述も削除
npm uninstall --save パッケージ名

# アンインストール時にpackeage.jsonのdevDependenciesの記述も削除
npm uninstall --save-dev　パッケージ名
```

#### パッケージの実行
```
# パスを指定して実行
./node_modules/.bin/パッケージ名

# npxを利用して実行
npx react パッケージ名
```
- npxはローカルに実行可能なコマンドを探しに行き、該当するパッケージがない時は一時的にパッケージをインストールして実行できるコマンド


#### パッケージインストールリスト

```
# カレントディレクトリにインストールされているパッケージの一覧を出力
npm list

# グローバルインストールしたパッケージの一覧を出力
npm list -g
```


## 参考にさせていただいた記事
[npmよく使うコマンドまとめ](https://qiita.com/standard-software/items/2ac49a409688733c90e7)
[npm i vs npm ci](https://qiita.com/yutoun/items/e580bcad5e73ccc81390)
【AWS】CloudWatch と EventBridge

## 主な用途

**Amazon CloudWatch: CloudWatch**
監視、メトリクス収集、アラーム設定、ログの収集と分析など、AWSリソースとアプリケーションの監視・管理に焦点を当てたサービスです。パフォーマンスの監視やトラブルシューティングに使用されます。

**AWS EventBridge: EventBridge**
 EventBridgeとは、AWSで発生する様々なイベントや外部のSaaSから発生するイベントをトリガーにして、さらに様々なAWSサービスと動作させることができるAWSリソース間をブリッジ（架け橋となるサービス）するサービス。イベントに基づいた連携やアプリケーションの自動化に適しています。

## 対象となるデータ:
**Amazon CloudWatch**
主に`数値データ（メトリクス）やログデータ`に焦点を当てています。リソースのパフォーマンスメトリクスやログ情報を収集し、可視化・分析・アラートを行います。

**AWS EventBridge: EventBridge**
`イベントに関する情報`を扱います。アプリケーション内でのアクション、状態の変更、外部サービスからの通知などのイベントを収集、処理、ルーティングします。

## イベント処理のスタイル:
**Amazon CloudWatch**
`リアルタイムでの監視`、メトリクスの収集とアラートが主な機能です。データの変更や状態のトリガリングには、主に他のサービスと連携することになります。

**AWS EventBridge**
`イベントドリブン`なアプリケーションを構築するためのサービスです。イベントの収集、ルーティング、変換、ターゲットへの配信などを行います。異なるアプリケーション間での連携に向いています。

## イベントの共有
**Amazon CloudWatch**
主にAWSリソースの監視やアプリケーションのメトリクスに関する情報を集中的に監視するためのサービスです。他のアプリケーションとの連携よりも、内部のリソースやシステムを監視するためのツールです。

**AWS EventBridge**
異なるサービス間やアプリケーション間でのイベントの共有と連携を重視しています。イベントの送受信とルーティングを通じて、システム全体でのデータフローと自動化を実現します。

## まとめ
CloudWatchは監視とメトリクスの収集に特化し、EventBridgeはイベント駆動型のアプリケーションの連携と自動化に特化しています。どちらも異なる用途に向いており、適切な場面で組み合わせて使用することで、より効果的な監視とアプリケーションの連携を実現できます。
【Flutter】Google AdMob のバナー広告のウィジェットの実装と注意点

# 概要

この記事は、Flutterを用いてAdMobバナー広告を組み込む方法について解説するものです。AdMobの登録と基本設定が完了しているFlutter開発者を対象としています。

この記事で学べること：
Google AdMobを使用してFlutterアプリにバナー広告を表示するウィジェットの実装方法
この記事では扱わないこと：
AdMobのアカウント設定や具体的な初期設定手順

# 必要なパッケージの追加

以下のコマンドを実行してください
``` bash
flutter pub add google_mobile_ads
```

https://pub.dev/packages/google_mobile_ads

# メタデータの設定

AdMobを利用するためには、プラットフォームごとにメタデータを設定する必要があります。

参考: https://codelabs.developers.google.com/codelabs/admob-ads-in-flutter?hl=ja#3



## Android

android/app/main/AndroidManifest.xmlに以下のメタデータを追加します。
``` android/app/main/AndroidManifest.xml
<manifest>
    ...
    <application>
       ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="YOUR_ADMOB_APP_ID"/>
    </application>

</manifest>
```


## iOS

info.plistに以下を追加します。

``` info.plist
<key>GADApplicationIdentifier</key>
<string>YOUR_ADMOB_APP_ID</string>
<key>io.flutter.embedded_views_preview</key>
<true/>
```

# バナー広告の実装

以下のコードは、プラットフォームに応じて適切なAdMobユニットIDを取得する関数です。

``` dart
import 'dart:io';

import 'package:flutter/foundation.dart';

String getAdBannerUnitId() {
  String bannerUnitId = "";
  if (Platform.isAndroid) {
    // Android のとき
    bannerUnitId = kDebugMode ?
        "ca-app-pub-3940256099942544/6300978111"  // Androidのデモ用バナー広告ID
: "YOUR_ADMOB_ANDROID_UNIT_ID";
  } else if (Platform.isIOS) {
    // iOSのとき
     bannerUnitId = kDebugMode
        ? "ca-app-pub-3940256099942544/2934735716"  // iOSのデモ用バナー広告ID
        : "YOUR_ADMOB_IOS_UNIT_ID";
  }
  return bannerUnitId;
}
```


- 呼び出し側
``` dart
    final bannerId = getAdBannerUnitId();
    BannerAd myBanner = BannerAd(
        adUnitId: bannerId,
        size: AdSize.banner,
        request: const AdRequest(),
        listener: const BannerAdListener());
    myBanner.load();
```

- ウィジェットの描画

``` dart
            Container(
              width: myBanner.size.width.toDouble(),
              height: myBanner.size.height.toDouble(),
              alignment: Alignment.center,
              child: AdWidget(ad: myBanner),
            ),
```

## UXと不正クリックの考慮
iPhone X以降のモデルでは、SafeAreaと広告が重なる可能性があり、誤タップを引き起こす恐れがあります。

このような場合、AdMobは無効なトラフィックと判断する可能性があります。これを防ぐために、広告の下にSafeAreaを設定するか、全体のウィジェットをSafeAreaで囲むことを推奨します。
私はおそらくこれが原因で１ヶ月ほど広告を止められていました…

このとき、自身のコンテンツにはかぶらないように注意してください。

例：

``` dart
   Container(
              width: myBanner.size.width.toDouble(),
              height: myBanner.size.height.toDouble(),
              alignment: Alignment.center,
              child: AdWidget(ad: myBanner),
            ),
            const SafeArea(child: SizedBox.shrink()),
          ],
```

|SafeAreaなし|下部SafeArea|
|-|-|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262578/cfa43a0a-310c-27ce-c73c-6129e9ac4335.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262578/d3215d92-8b08-dd5f-fc31-0008383f751a.png)|


アプリは[さわやか待ち時間](https://sawayakawaittime.page.link/6RQi)

なお、シミュレーター起動のデモモード（kDebugMode=true）で表示されるバナーが使われています。
QNAP NASのdockerでホストと同じNWの別IPでコンテナを追加する話

# はじめに
QNAPのDockerコンテナをホストと同じネットワークに追加し、ホストとは別のIPとしてアクセスしたいという欲望を解消する。

# 条件
* SSHができること
* Dockerが動いていること
* NASのネットワークが死んでも泣かない心

# やることは？
MACVLANを使います。
基本的に以下の方が書いてくださったことをそのままコピー。
ただ、QNAPのInterface指定方法による違いを吸収するのと、ルート設定がそのままではうまくいかなかったので修正。
https://qiita.com/pochy9n/items/8c175db18da4a44ae2d2

# 設定
## 設定条件
以下のような設定条件で構築します。

### ホスト(QNAP自体)
|項目|内容|
|--|--|
|Interface名|qvs0|
|IPアドレス |192.168.0.2/24|
|Gateway    |192.168.0.1|
|追加する仮想IF|htoc0|
|htoc0のIP|192.168.0.5|

### コンテナ
#### コンテナ1
|項目|内容|
|--|--|
|ホスト名|container1|
|IPアドレス |192.168.0.41|

#### コンテナ2
|項目|内容|
|--|--|
|ホスト名|container1|
|IPアドレス |192.168.0.42|

#### docker network
|項目|内容|
|--|--|
|ネットワーク名|dlocal|



## 設定手順

### 1. docker networkを作成
```
$ sudo docker network create -d macvlan --subnet=192.168.0.0/24 --gateway=192.168.0.1 -o parent=qvs0 dlocal
$ docker network ls
NETWORK ID     NAME                      DRIVER    SCOPE
f6557d923fdb   bridge                    bridge    local
3a47ec73a64a   host                      host      local
af79cdd95e38   none                      null      local
9ba521c1a1a1   dlocal                    macvlan   local
9382478e8ea9   qnet-dhcp-eth0-6d6da6     qnet      local
52312798037b   qnet-static-eth0-79e6cc   qnet      local
```

### 2. dockerコンテナを起動

```
$ sudo docker run -d -it --network dlocal --ip 192.168.0.41 --name conte1 ubuntu:latest /bin/bash
$ sudo docker run -d -it --network dlocal --ip 192.168.0.42 --name conte2 ubuntu:latest /bin/bash
$ docker ps -a
CONTAINER ID   IMAGE          COMMAND      CREATED          STATUS         PORTS  NAMES
bc8730bf2a81   ubuntu:latest  "/bin/bash"  36 minutes ago   Up 36 minutes         container1
d6eef7ae8903   ubuntu:latest  "/bin/bash"  36 minutes ago   Up 36 minutes         container2
```

### 3. 仮想IFの設定

QNAP自体から dlocal に接続するための仮想IFを設定。
また、dlocal内のIPへの経路情報も設定する
```
sudo ip link add htoc0 link qvs0 type macvlan mode bridge
sudo ip addr add 192.168.0.5/32 dev htoc0
sudo ip link set htoc0 up
sudo ip route add 192.168.0.41/32 dev htoc0
sudo ip route add 192.168.0.42/32 dev htoc0
```
元記事では/24で設定してあったが、`RTNETLINK answers: File exists` が出てしまうので/32でルートを設定した。
もしコンテナを追加する場合は対象IPへのルートを都度設定すること。

# 大事なこと
「3. 仮想IFの設定」については、QNAP自体への設定になるがこの設定は永続的なものにはならず、再起動する都度実行する必要があるので注意。
以下のAutrun.shの対応をしておくといいかもしれません。
https://www.qnap.com/ja-jp/how-to/faq/article/running-your-own-application-at-startup
独学エンジニアとはなんぞや

　　　　ハロー未経験エンジニア！！　
ZERO0000ですね。今日は、初心者エンジニア
必見の独学エンジニアというサービスについて
詳しく紹介しまする。　

　　　　　独学エンジニアとは？　
Udemy受講生14万人, YouTube8万人の山浦清透さんが行っている月1080円でweb会社に就職するために必須なスキル（バックエンジニアになるためのスキル）を身に付けることが出来るという画期的なサービスです！！　　

　　　　　　　
　　　　　　　良いとこ

・値段が良心的←月間1080円

・身につくスキルが高レベル　
→実務が1人で行えるようになる　
→つまり自走できるエンジニアになる　

・何より分かりやすい　
→Udemy受講生14万人, YouTube8万人の
山浦清透さんが教えてくれるかつてない　
分かりやすいアドバイス　　

・まだ世に出てひがたってないサービスなので
ポートフォリオが自分オリジナルってこと　
にできる
→情弱大好きなマ○ナリ社長が立ち上げた
プログラミングスクール
ではぜーーーーーーったいムリ
→基本的に知られているプログラミングスクールでは絶対ムリ


　　　　　　　悪いとこ　

・分かんないところは誰も教えてくれない　
→自走できるエンジニアを目指しているので　
当然だがまるっきりの初心者では多分完走　
はムリ。僕ももう挫折しましたwww 

・質問できない　
→さっきのと重複しますが質問できないので
どうしても手取り足取りがいい人には向いて　
いない　
→手取り足取りがいい人にはプログラミングスクール通ったほうがいい　
（情弱大好きなマ○ナリ社長が立ち上げた
プログラミングスクールはやめとけ）

・プログラミングって何って人には向かない　
→このサービスがそもそも、HTML,CSS, 
JavaScriptの基本的なことは出来る
前提としているのでその辺りは本なり　
Udemyなりで独学しないといけない

→僕はそれを知っていたのでまず無料の　
プログラミングスクールであるプログラマカレッジを終了させておきました〜っす
　
では次回は独学エンジニアでの具体的な　
勉強をお伝えしまーきの（痛いな〜）
iOS App Dev Tutorialsを読んで実際にやってみた。その10

## 前回の記事
[iOS App Dev Tutorialsを読んでみた。その9](https://qiita.com/shomiya181210/items/307b2ccc46a02dab55e6)
前回の記事を読んだ後に、この記事をご覧ください。
## 今回の範囲
#### [Responding to events（イベントへの対応)](https://developer.apple.com/tutorials/app-dev-training/making-classes-observable)
第10回はSwiftUIアプリとビューのライフサイクルについて学びます。
## 内容の要約
### 1.シーンアーキテクチャ
　SwiftUIにおいて、アプリの状態を探索する前に、シーンの概念を理解することが重要です。また、シーンは、アプリのユーザーインターフェースの一部であり、システムが管理するライフサイクルが付属しています。
- アプリ作成には、Appプロトコルに準拠した構造体を定義します。@main属性を付けることで、これが唯一のエントリポイントであることがシステムに伝わります。データのリスト表示時には、Scrumdingerアプリの構造を操作するために、ルートビューをScrumsViewに設定します。
- App構造体の本体には、1つ以上のSceneプロトコルに準拠したシーンを追加します。シーンは、表示されるビュー階層を包括するコンテナであり、iOSやwatchOSでは1つのシーンが表示され、一方でmacOSやiPadOSでは複数のシーンが表示されるようにアプリを設計することがあります。
- SwiftUIではスクラムディンガーが使うWindowGroupのような具体的なシーンを提供します。システムはプラットフォームとコンテキストに適したビュー階層を表示することが可能です。例えば、iPadOSのマルチタスクでは、同じアプリの複数の小さなインスタンスを同時に表示できます。
### 2.シーンのフェーズとトランジション
アプリの実行中、シーンは3つのフェーズの間を移行することができます。
- activeシーンはフォアグラウンドにあり、ユーザーはそれと対話することができます。
- inactiveシーンは表示されているが、システムはシーンとのインタラクションを無効にしている。例えば、マルチタスク・モードでは、アプリのパネルが他のパネルと並んで見えますが、アクティブなパネルではありません。
- backgroundアプリは実行中ですが、シーンはユーザーインターフェースに表示されていません。シーンはアプリ終了前にこのフェーズに入ります。

scenePhaseを使用すると、現在のシーンの状態を知ることができ、アプリ内で特定のアクションを実行したい場合、シーンが別のフェーズに移行した場合にトリガすることができます。

Scrumdingerの例では、onChange(of:perform:)修飾子を使用して、アプリの状態を複数回の起動にわたって保存します。この修飾子を使って、シーンが非アクティブになったときにアプリデータを保存するアクションを実行します。

これにより、SwiftUIアプリのシーンとシーンフェーズの詳細に関する情報も提供されます。
### 3.イベントと状態
　SwiftUIは宣言的なプログラミングパターンを使用して、状態の変化に応じて自動的にビューを更新します。ユーザーの操作や通知などのイベントが発生すると、それに対応するクロージャが実行され、状態が変更されることがあります。変更が検出されると、SwiftUIはビューをレンダリングしてユーザーインターフェースを同期します。

### 4.ライフサイクルのイベントを見る
SwiftUIでは、ビューが表示される時や表示されなくなる時にアプリの状態を変更する必要がある場合があります。これには3つの修飾子があります：

- onAppear(perform:)はビューが表示される際にアクションを実行します。
- onDisappear(perform:)はビューが画面から消える際にアクションを実行します。
- task(priority:_:)は非同期でビューが表示される前にアクションを実行します。

これらを利用して、ビューの表示や非表示に合わせてアプリの状態を変更するアクションを実行できます。SwiftUIはビューの階層を管理し、状態の変更に応じて自動的にユーザーインターフェースを更新します。この機能を活用する例として、スクラムタイマーの制御やオーディオビジュアルプレーヤーの管理、音声認識器の制御、スクラムの履歴の追加などがあります。ビューのライフサイクルを通じて、ユーザー主導のイベントと同じように状態の変更に応答できます。
### 5.まとめ
次回は状態とライフサイクルの管理を行います。
次の記事は、このアプリの重要な機能を構築するために、スクラムの状態を管理するモデルを制御するライフサイクルメソッドを使います。
Nuxt+Amplifyで"global is not defined"が発生する場合の対処法

# まずは対処法

`nuxt.config.ts`にこちらの設定を追加してください。

```ts:nuxt.config.ts
export default defineNuxtConfig({
  // ...,
  vite: {
    define: {
      "window.global": {},
    },
  },
});
```
これにてエラーが解消されるはずです。ここまで読んでくださりありがとうございました！

・・・以下は全ておまけです。
# どうしてエラーが発生するのか
原因は`aws-amplify`の依存モジュール`buffer`にあるこちらの処理です。
```js
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
  ? global.TYPED_ARRAY_SUPPORT
  : typedArraySupport()
```

Nuxtでviteを使用している場合、`npm run dev`等で開発サーバーを起動すると、node_modulesはバンドルされずにそのまま使われるようです。
それにもかかわらず、ブラウザでは未定義の`global`を使おうとするため`global is not defined`となってしまいます。

# OSSコミュニティに直接聞いてみた
エラーの原因となっている`buffer`モジュールのこのバグは、最新バージョンでは解消されています。しかし、`aws-amplify`の依存モジュール`amazon-cognito-identity-js`では、古いバージョンの`4.9.2`を使い続けていました。こちらをバージョンアップするためのPRをリポジトリで見つけたのですが、マージされずに放置されていたので質問してみました。

https://github.com/aws-amplify/amplify-js/pull/11064

回答がこちら。
> this issue will cause some breaking changes, and it will be fixed as part of our next major version bump of our library. We do not have an exact ETA, but we will provide an update when we do!

どうやら、次のメジャーバージョンのリリースで解消されるようです。（予定は未定）

# 結論
とりあえずは、viteの設定にて`global`を空のオブジェクトとして定義することでエラーを解消することができます。
いずれは、`amazon-cognito-identity-js`のアップデートでその設定が不要になるはずです。
【ChatGPT】には英語で指示、Oxford大学検証

:::note info
本記事は、ChatGPT（無料版）で
行なっております。GPT4での確認
はできておりません。あしからず。
:::

　どうも、カーブミラーです。

　今回は、記事紹介です。
　　ちょっと前の記事ですけどw
　　　……あっ、二週間前だった。
***
　かねてから、
　　言われてきた
　　　「ChatGPTには
　　　　英語で指示した方がいい」
　　　　　という通説が、

　　オックスフォード大学で
　　　検証されました。

　以下は、その記事です。

[大規模言語モデルは英語で使用するのが安価で有利になる傾向。オックスフォード大学](https://www.msn.com/ja-JP/news/scienceandtechnology/a/ar-AA1ezFCm?ocid=sapphireappshare)

　コストや処理時間を
　　調べたようです。

　方法は、
　　OpenAIのトークナイザで
　　　確認したとか。
***
　まぁ、
　　私の過去の記事
[【ChatGPT無】日本語Promptを英訳して実行して結果を和訳するPromptです](https://qiita.com/kabumira/items/243b06bcf4cd8955c59c)
　　　でも

　　日本語Promptを
　　　英語Promptにして
　　　　処理したところ、
　　　　　いい結果が、
　　　　　　得られました。
　　　　　　　速かったし。
***
　記事とは違いますけど、
　　ChatGPTさんに、
　　　処理に対する負担を
　　　　聞いてみました。

User
>あなたが処理することで、一番処理負担があるものは、なんですか？

ChatGPT
>私にとって、長い文章の生成や複雑な文章の理解と返答の処理が比較的処理負担が高いタスクとされています。これは、文章の生成や理解には多くの計算や推論が必要であり、特に複雑な文脈や意味の解析に時間とリソースがかかるためです。ただし、私は効率的に訓練されており、多くの種類のタスクに対応できるよう設計されています。


User
>では、逆に、処理負担が軽いものは、なんですか？

ChatGPT
>短い文や簡単な質問に対する返答の生成や、一般的な情報提供など、比較的単純なタスクは処理負担が軽いとされます。また、特定のテキストの要約や簡易な言語変換なども、処理が比較的迅速に行えるタスクとされています。ただし、私は幅広いタスクに対応することができるため、さまざまな複雑度のタスクに対応する準備が整っています。


User
>複雑度の低いものから高いものの順番で、箇条書き（説明不要）でお願いします。

ChatGPT
>複雑度の低いものから高いものの順番で、以下に示します：
>
>1. 簡単な質問への短い返答の生成
>2. 一般的な情報の提供
>3. 特定のテキストの要約
>4. 簡易な言語変換
>5. 長い文章の生成
>6. 複雑な文章の理解と返答の処理
***
　なんとなく、
　　わかりますね。

　まぁ、利用側からは、
　　そのときそのときで、
　　　アクセス量が違うので、
　　　　処理が重いとなったりも
　　　　　するわけですが。
***
　DeepL（翻訳アプリ）は
　　いまだに手放せません。

　別に、英語に翻訳して、
　　ChatGPTさんに
　　　渡しているわけでは
　　　　ないんですけどね。

　ChatGPTさんの
　　エラーメッセージが
　　　ときより読めなくて
　　　　頼っています。
　　　　　苦手で読めないのでw

　みなさんは、
　　どうですか？
wslでelixir その39

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題、やってみた。

# 練習問題
ectoで、todoアプリを作れ。

# 方針

- インタープリター方式
- コマンドは、4つ
insert メモ
delete id
update id メモ
list
- Repoは、person使う。

# サンプルコード

```

defmodule Todo do
	def insert(v) do
		p = %Friends.Person{name: v, age: 0}
		Friends.Repo.insert(p)
	end
	def update(n, v) do
		{id, _} = Integer.parse(n)
		p = Friends.Repo.get(Friends.Person, id)
		c = Ecto.Changeset.change(p, %{name: v})
		Friends.Repo.update(c)
	end
	def delete(n) do
		{id, _} = Integer.parse(n)
		p = Friends.Repo.get(Friends.Person, id)
		Friends.Repo.delete(p)
	end
	def list() do
		IO.puts(" id  todo")
		Friends.Repo.all(Friends.Person)
		|> Enum.map(fn v ->
    		IO.puts(" #{v.id}  #{v.name}")
  		end)
	end
	def run() do
		l = IO.gets("> ")
		l = String.replace(l, "\n", "")
		s = String.split(l, " ")
		|> IO.inspect
		cond do
		Enum.at(s, 0) == "insert" ->
			Todo.insert(Enum.at(s, 1))
		Enum.at(s, 0) == "delete" ->
			Todo.delete(Enum.at(s, 1))
		Enum.at(s, 0) == "update" ->
			Todo.update(Enum.at(s, 1), Enum.at(s, 2))
		Enum.at(s, 0) == "list" ->
			Todo.list()
		true ->
			IO.inspect(l)
		end
		run()
	end
end





```

以上。
Janomeによる「わかち書き」

## 早速ですがわかち書きをchatGPTへ質問
【結論】
わかち書き（分かち書き）は、テキストや文章を単語やフレーズに分割する処理を指します。この処理は、日本語のような連続した文字列の言語において、文や単語の区切りを明確にするために重要です。機械翻訳やOCRなどの自然言語処理技術において、わかち書きはテキストの正確な解析と処理を支援する役割を果たします。

【詳細説明】
わかち書きは、テキストや文章を単語や文に分割するプロセスを指します。日本語などのアジア言語では、単語間に明確なスペースがなく、連続した文字列で表現されるため、テキスト全体を適切に理解するためには、単語や文の区切りを認識する必要があります。

例えば、次のような日本語の文章を考えてみましょう：「私は学校へ行きました。」

この文章は、スペースがないためにコンピュータが「私は」「学校へ」「行きました。」といった単語に分割することが難しいです。ここでわかち書きが登場し、文章を「私 は 学校 へ 行きました 。」といった単語ごとに分割します。このような分割を行うことで、テキスト解析や翻訳などの処理が正確に行えるようになります。

機械翻訳においては、わかち書きは特に重要です。翻訳エンジンは単語単位でテキストを解析し、それぞれの単語の意味や文脈を考慮して翻訳を行います。わかち書きされたテキストは、単語や文の区切りが明確になるため、正確な翻訳が可能となります。

また、OCRにおいてもわかち書きは有用です。OCRは画像からテキストを認識する技術であり、テキストが連続した文字列として認識されるため、わかち書きを行わないと正確なテキスト抽出が難しくなります。わかち書きを行うことで、テキストの単語や文の境界を正しく抽出し、OCRの結果を改善することができます。

最新の展開として、深層学習技術がわかち書きにも応用されています。日本語の形態素解析やセグメンテーション（テキストを文や単語に分割する処理）は、深層学習モデルによって高度に精緻化されています。これにより、従来よりも複雑な文法構造や表現を持つテキストの解析が向上し、機械翻訳やOCRの品質も向上する可能性があります。

だそうです。興味があれば一読ください。

## 環境
Windows11
Python3.11.4
envにて仮想環境下
ipykernelにてカーネル設定
jupyter lab

## 形態素解析
サンプル文書をわかち書きへの前のテスト

```sample.ipynb
from janome.tokenizer import Tokenizer
t1 = Tokenizer()
t1
```

OUTPUT
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448426/f9f1f2c6-520f-de9f-76c4-d6f77bf652e9.png)

```sample2.ipynb
text = '「カーネル」は、プログラム実行環境の一部であり、特に対話型のプログラムやスクリプトの実行に関連しています。IPythonカーネルは、IPythonと呼ばれる対話型のPythonシェルを裏で支えるコンポーネントです。'
tokens = t.tokenize(text)
token_list2 = list(tokens)
len(token_list2)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448426/1683c378-eb16-325b-6dc5-64fcd8457e16.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448426/58760e9c-38c5-529c-430f-992e83d44800.png)
上記切れてますが、うまく分類できています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448426/76989600-48bb-8e30-052c-dac0862bc68e.png)
最終、わかち書きへ

とりあえずここまで！
次へ続きます。。
JavaServletってどうも分からないのでまとめてみた

# この記事が有用だと思われる方

この記事はJava初級者の自分の覚書のために書いています。

私はJavaの基本文法を何とか勉強し、次にServlet＆JSPに進みました。
しかし、どうも楽しくありません。それはなぜかと言うと、Javaでコードを書いていた時には実行すればeclipsがすぐに結果を表示してくれました。自分のやったことの結果をすぐに目にすることができ、勉強とアウトプットの短いサイクルに満足できていたのです。
　
アウトプットが有効だと分かっているのですが、Servlet＆JSPの勉強を始めたばかりなので、まだアウトプットに至らず、いったい何をどう使うためにこれを勉強しているのかいまだ見えてこず、只今勉強意欲が萎んでおります。

それを打破するために、記事でアウトプットすることにしました。
出来得る限り、端的に少ない言葉数で説明するよう心掛けて書きました。

同じ境遇の諸氏に参考となれば幸いです。




# JavaServletとTomcatとJSP

### JavaServlet
Servletとは、いわば部品です。Webアプリ開発プログラムの単なるパーツです。
当然、部品オンリーでは動かせないので、それを動かすアプリケーションと一緒に合わせて開発していきます。それに私はTomcatを使用しています。

### Tomcat
アプリケーションサーバのアプリ（Apache社）。
Webページをネット経由で見ようとするなら、Webサーバかアプリケーションサーバにあげる必要があります。
このアプリで自分のパソコンをアプリケーションサーバ化することができます。

静的コンテンツ（変化なし）であれば、WebサーバのみでOkですが、動的コンテンツ（クライアントのリクエストにより変化する）であればアプリケーションサーバが必要です。
多機能の求められる現在のWebページを表現するために、Webサーバとアプリケーションサーバが連携して処理する場合が多くなっています。

### JSP
JSPはファイルと呼ばれ、Servletはクラスと呼ばれる違いはあるものの、実現できることはほぼ同じです。ServletとJSPは同時に勉強するもののようですが、この記事ではJSPにはこれ以上触れていません。




# Servletの動作の流れ

・Webプラウザ使用者（クライアント）からの要求（リクエスト→URL入力）。
・要求をWebサーバが受け取り、アプリケーションサーバ（Apche Tomcat）へ渡す。
・Servletコンテナ（Tomcatが作るServletが動く環境）に渡され、Servletが動く。
・同じ経由を逆に辿ってクライアントへ動的コンテンツ（レスポンス）が表示される。
・このリクエストとレスポンスは、ServletではGETメソッドとPOSTメソッドとしてやり取りされる。

さらに詳しく、Servletコンテナの中の動きを表現をしますと……
・クライアントからのリクエストがServletコンテナに届く。
・呼び出されたServletはインスタンス化され、実体となる。
・Servletが呼び出されるときに、クライアント固有のスレッド（あるメモリ領域）を割り当てる。
・リクエスト処理が終わるまで、この固有のスレッドがそのクライアントとの窓口になる。
・処理終了までは、以降のリクエスト受け取りもレスポンス返しも、割り当てられたスレッドから行う。
・スレッドは複数あるが、インスタンスは一つである。
・それぞれのスレッドでは、インスタンスフィールド（変数）を共有している。

### Servlet　ライフサイクル
・インスタンスの生と死である。
・インスタンス生成 → init()で初期化 → doGet()あるいはdoPost()で入出力（つまり、クライアントからの要求に対する出力とクライアントから送られたデータ取得） → destroy()でインスタンス消滅。

（実際には、自分が要求する以前に別クライアントが要求しているので、インスタンスはすでに生成されいてる状態。消滅も特に必要がなければ起こらないので、インスタンスはいつでも生成済み）


# おわりに
まだまだ、勉強中です。
RecoilのgetCallbackを利用する

# Recoilの最新情報を取得、判定

### 例.Recoilの状態をイベントのコールバック内で見たいとき
イベントに登録されている関数内でRecoilの最新情報を取得・ハンドリングしたい場合は、少し工夫が必要

こんな形でselectorのgetCallbackを利用してsnapshotから最新情報を取得、引数をとれるようにカリー化して関数をreturnさせる
```ts
export const isLoginUserSelector = selector({
  key: "isLoginUserSelector",
  get: ({ getCallback }) => {
    const isUserLogin = getCallback(({ snapshot }) => (user: string) => {
      const loginUser = snapshot.getLoadable(loginUserAtom).getValue();
      return user === loginUser;
    });
    return { isUserLogin };
  },
});
```

利用する側はuseRecoilValueでisUserLogin関数を取り出し、関数実行する
```tsx
import { useRecoilState, useRecoilValue } from "recoil";
import { isLoginAtom, isLoginUserSelector, loginUserAtom } from "./state";
import { useEffect } from "react";

export const Test: React.FC = () => {
  const [isLogin, setIsLogin] = useRecoilState(isLoginAtom);
  const [loginUser, setLoginUser] = useRecoilState(loginUserAtom);
  const { isUserLogin } = useRecoilValue(isLoginUserSelector);

  const resizeEvent = (_e: Event) => {
    console.log("loginUser:", loginUser);
    console.log("isUserLogin:", isUserLogin("A"));
  };

  useEffect(() => {
    window.addEventListener("resize", resizeEvent);
    return () => {
      window.removeEventListener("resize", resizeEvent);
    };
  }, []);

  const onClickLogin = (user: string) => () => {
    setIsLogin(true);
    setLoginUser(user);
  };

  return (
    <>
      <div>{loginUser}</div>
      <button onClick={onClickLogin("A")}>LOGIN A</button>
      <button onClick={onClickLogin("B")}>LOGIN B</button>
    </>
  );
};

```

### 結果
すると以下のようになり、loginUserはイベント登録時情報を表示するため空、isUserLoginは最新情報を比較するため結果がちゃんと取れている。

- Aをクリックしてリサイズした時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476893/14decb0c-4104-4ba1-0555-a42e7f31ecb8.png)

- Bをクリックしてリサイズした時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476893/a1092e48-295d-f790-9bc4-047f412c4e3d.png)
インターン体験記(株式会社エイチーム)

# はじめに
2023年8月14日~18日に行われた株式会社エイチームでのインターン体験記をまとめます。
予定としては平日5日間であったが8月15日は台風の影響で休みになり4日間となった。

# インターン概要
内容：株式会社エイチームのグループ企業の**株式会社エイチームライフデザイン**にアサイン。
場所：大名古屋ビルヂング31、32階
時間：10:00~19:00
使用言語・FW：Ruby on Rails
※アプリ自体はPHP,Symfony,Next.jsなども使われている。

## 1日目
- 事業説明
- 次週作業定例会
- メンバーへ自己紹介
- 目標設定
- 環境構築
- Issueにアサイン

初日で社員とは気軽に話せて食堂でも業務に関していろいろ話したり、業務をしていく中でフローは大まかに理解できた。
Issueの内容としてはナビクルのサイトの中古車販売店の検索に店舗のキーワード検索機能を追加するというもの。
Issueでやることは明確にしてコードリーディングも大体終えたが午後に2日目は台風によってお休み連絡を受けインターン期間内Issueをリリースし終えるか不安を感じた。
インターン生はコードは社内のPCからでしか閲覧できないため自宅に持ち帰りはできない。

## 2日目
台風のためお休み

## 3日目
- 新Issue説明
- Issueアサイン
- 1on1面談

担当の上司の方が台風で休みの間に残り時間でリリースまで間に合いそうなIssueを考えていただだき、当初のIssueか新しいIssueか選択の機会をいただきリリースまでやりたいということで新しいIssueに変更した。
新Issueはナビクルのサイトの管理者画面で記事投稿をする際に記載した画像URLの画像がデータベースにアップロードされていないときにバリデーションエラーを表示されて保存させず公開にはできないようにするというもの。
管理者画面に入れないというトラブルも起きたりしたがなんとか対応していただき業務ができた。

## 4日目
- Issueのプルリク、レビューコメント対応
- スライド作成(インターンで得たことなど)

Rubocopという静的検証ツールでコードの品質チェックや上司のレビューでコードの最適化などを行なった。

## 5日目
- Issueの動作テスト、CI/CDでのテスト、リリース
- スライド発表
- 自由時間
- 飲み会(お疲れ様会)

テストは通ってくれ！という祈りを捧げドキドキしながらも成功できて嬉しかった。
本来金曜日のリリースは私が所属したチームの方針としてはタブーではあるが管理者画面というエンドユーザーに影響がないIssueでかつ私に対して台風などの影響も考慮し、もしなにか起きたら上司が直すということでリリースの許可が得られた。
スライド発表ではインターンで得られたこと、参加してみて印象が変わったこと、質疑応答を行なった。
自由時間では話したいことや聞きたいことのある社員のところに行って自由に会話するというものでCI/CD、SEO、React、学校、エイチームをどう思っているのか、など色々なことについて話した。

業務終わりに飲み会があり社員の仕事とは違う一面を見れたりして楽しく最後を終えました。

## 全体を通して

### 社員との交流
上司が期間中昼休憩の時に食堂に他の部署のエンジニアやマーケやデザイナーといった新しい人を連れてきていただき多くのいろんな方と交流できたのは非常によかった。(おそらくインターン期間中に業務含めて20人以上の社員と交流した気がする)

人の良さがにじみでてるのが伝わり、特に人を集める力やそこの流れに乗ることのできる社員が集まっているというのを実感した。(あとめっちゃ挨拶した気がする...)

### 得られたもの
課題に対してなぜやるのかを考えて納得してアサインしておりその結果としてデザイナーやマーケの人との相互理解につながると感じた。また納期や能力を見て時間内にここまで機能としてやりきる力やサポートの入れるタイミングが最適で目標設定や1on1面談なども含め目指すべき目標を得られた。

またSEOやリリース日を意識するということは普段の開発だとそこまでなくWEB開発の開発背景を知れた。

# さいごに
インターンに参加してみて成長でき、成長しやすく長期的に働きたい職場と思いました。
この記事を読んで少しでもエイチームに興味を持っていただいたり、マッチしてるかもと思えた学生はインターンや本選考にぜひ挑戦してみてください！
Ruby ループ処理に対する     break,retrun,nextの挙動

## 調べた経緯
ワークにて、ループ処理をネスト（入れ子）にすることがあり、各制御構造について調べたのでここに記しておきます。
特に悩んだのはnextってなんだ？　という疑問で、調べたのですが、検索結果はeach文に対するものが多く、理解するのに苦労しました。

あまり使用する機会はないかと思いますが、while文のループのネストで説明したいと思います。
これが理解できたことで、自分はeach文でのnextもなんとなく理解が深まりました。

## 各制御構造
- break
公式リファレンス
　　　break はもっとも内側のループを脱出

- return
公式リファレンス
　　　メソッド自体から抜ける。

- next
公式リファレンス　
　　nextはもっとも内側のループの次の繰り返しにジャンプします。？？
　　

## 実際の挙動
この**もっとも内側のループの次の繰り返しにジャンプ**が上手く理解できず色々と挙動を確認した。
※冒頭で述べたがeach文での説明が多い。

```ruby:Ruby
#ループ１
while true
  puts "ループ１"
  #ループ２
  while true
    puts "ループ２"
    #ループ３
    while true
      puts "ループ３"
      n = gets.to_i
      if n == 1
        puts "続いてからループするよ"
      elsif n == 2
        puts "このループ内の残りの処理をスキップしてループ(３の頭に戻る）するよ"
        next
      elsif n == 3
        puts "このループからは抜けるよ"
        break
      else
        puts "すべてのループ（メソッド）を終わりにするよ"
        return
      end
      puts "ループ3の終わり"
    end

    puts "ループ２の終わり"
    break
  end

  puts "ループ１の終わり"
  return
end
```

前提として、起動すると、一番内側のループ３まで行きます。

- １を実行　　処理なし
```
続いてからループするよ
ループ3の終わり
ループ３
```
if文を抜けて、ループ３の終端まで実行されたあと、while文のループが継続し、元の位置に戻ります。

- 2を実行　next
```
このループ内の残りの処理をスキップしてループ(3の頭に戻る）するよ
ループ３
```
ループ３の終端までいかず、即座に３のループを再開しました。

- 3を実行　break
```
このループからは抜けるよ
ループ２の終わり
ループ１の終わり
```
３のループを抜け、２の終端まで行き、２の終端にあるbreak文でさらに抜け、１の終わりまで到達しています。

- ４（１と２と３以外）　return
```
全てのループ（このメソッド）を終わりにするよ
```
３のループ内にいながら、２と１のループも全て実行されずに終了されました。

## 結論

breakはそのループのみから抜ける
> ネスト（入れ子）なら内側のループから抜け,外のループに出る。

returnは、メソッド内の処理から抜ける
> そのメソッド内で、ループの入れ子であろうが、処理は終了する


nextはそのループ内の残りの処理をスキップして現在のループ内の頭に戻る
> その中の処理をスキップする、ループ自体は継続する


どうでしょうか？　初学者なりにまとめてみたつもりですが、誰かの参考に少しでもなれたなら幸いです。
プチ話 友達と喧嘩したとき、if文であやまった話。

# プチ話書く
友達とちょっとした喧嘩をしたときに、if文であやまった話をします。
ちなみに友達から記事を書く許可もらってます。

# 本題
友達と喧嘩したときにLineにこんなメッセージ送った。
```javascript
if(you == "angry"){
  console.log("sorry");
}
```
そしたら友達から
```javascript
console.log("I'm sorry too");
```
って帰ってきた。

# 以上
今日はそれだけ。
つまんないけど見てくれると嬉しい。
皆もif文で会話してみてねー
Elixir File関連の関数に渡すPath.t型


[Elixir]の[File]関連の関数の多くは[Path.t]型の値を引数にとります。しかしながら、サンプルコード見ると全て`"mix.exs"`のようになんの変哲もない普通の文字列でパスが表現されています。[Path.t]型とは一体何なのか気になります。

これから[Elixir]を始める方にはこのサイトがおすすめです。

https://elixir-lang.info/

[Elixir]とコミュニティの雰囲気をゆるく味わいたい方は「先端ピアちゃん」さんの動画が超オススメです。

https://www.youtube.com/@piacerex

## 結論

- [Path.t]は、[IO.chardata]でした。
- [IO.chardata]は、[String.t]もしくは[maybe_improper_list]とのことです。

## File関連の関数

File関連の関数は[File]モジュールにあります。例として、[File.exists?/2]を用いて、ファイルの存在の有無を確認することができます。ファイルへのパスはこのように文字列で渡すことがほとんどだと思います。

```elixir
File.exists?("mix.exs")
```

[File.exists?/2]型はこのようになっています。

```elixir
@spec exists?(Path.t(), [exists_option]) :: boolean() when exists_option: :raw
```

引数が文字列を表す[String.t]や`binary`ではなく[Path.t]となっています。

## Path.t型

ドキュメントのリンクをポチポチ押して確認すると[Path.t]が[IO.chardata]であることがわかります。さらに、[IO.chardata]は`String.t() | maybe_improper_list(char() | chardata(), String.t() | [])`となっています。ざっくりとリストも渡せるということがわかりました。試してみます。

```elixir
File.exists?("mix.exs")
File.exists?(["mix.exs"])
File.exists?(["mix", ".exs"])
File.exists?([?m, ?i, ?x, ?., ?e, ?x, ?s])
```

文字列や文字のリストにしても問題なくイゴきます。

## ちゃんとしたリスト

[Elixir]の[List]は連結リストですので、`[1, 2, 3]`というリストは`[1 | [2 | [3]]]`のように頭部と尾部で成り立つリストが連結された構造をしています。

```elixir
[1, 2, 3] = [1 | [2 | [3 | []]]]
```

[文字リスト]もいろんな形で表現できます。

```elixir
~c"mix.exs" = 'mix.exs'
~c"mix.exs" = [109, 105, 120, 46, 101, 120, 115]
~c"mix.exs" = [?m | [?i | [?x | [?. | [?e | [ ?x | [?s]]]]]]]
```

## ちゃんとしていないリスト

通常[List]はちゃんとした連結リストじゃないとダメなのですが、文字列連結の場合は変な構造のリストでも許されるようです。

[List]がちゃんとしたものかどうかの判定は[List.improper?/1]でできます。正直言うと何がちゃんとしているのかよくわかりませんが、適当に[List]に文字や文字列を放り込むだけで連結された文字列のように扱ってくれるようです。

```elixir
true = List.improper?(["mix" | ".exs"])
false = List.improper?(["mix" , ".exs"])
```

```elixir
File.exists?(["mix" | ".exs"])
File.exists?(["mix", ".exs"])
```

余談ですが、文字列を何度も何度も生成すると効率が悪いので[List]をビルダーとして活用するパターンが性能向上に有効との噂もあります。どの程度効果があるのかは知りません。

https://nathanmlong.com/2021/05/what-is-an-iolist/

https://bignerdranch.com/blog/elixir-and-io-lists-part-2-io-lists-in-phoenix/

https://www.youtube.com/watch?v=Y83p_VsvRFA&t=1104s

https://qiita.com/mnishiguchi/items/1f9288139fdb8828134d

[Elixir]: https://elixir-lang.org/
[List]: https://hexdocs.pm/elixir/List.html
[File]: https://hexdocs.pm/elixir/File.html
[File.exists?/2]: https://hexdocs.pm/elixir/File.html#exists?/2
[Path.t]: https://hexdocs.pm/elixir/Path.html#t:t/0
[IO.chardata]: https://hexdocs.pm/elixir/IO.html#t:chardata/0
[List.improper?/1]: https://hexdocs.pm/elixir/List.html#improper?/1
[maybe_improper_list]: https://hexdocs.pm/elixir/typespecs.html#built-in-types
[String.t]: https://hexdocs.pm/elixir/String.html#t:t/0
[文字リスト]: https://elixirschool.com/ja/lessons/basics/strings#%E6%96%87%E5%AD%97%E3%83%AA%E3%82%B9%E3%83%88-1
Jupyter labでJanome実行トラブル(no module)の対応備忘録

## はじめに
python、GPT、ソフトからハードまで勉強中です。

## さっそく本題
PythonでJanomeインストール時トラブル対応の備忘録

## 問題点
仮想環境下で、

        pip intall janome

実行し、Jupyter labを用いて作業をすると以下トラブった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448426/fbfd795a-56f9-bd41-549b-4338e45c01ca.png)

## 調査、対応策
まずpip install janomeのときに以下のようなdependency informationが、、（何か悪い気がしていた。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448426/691c49b2-e945-8c4d-87c8-e9138ee39f5c.png)


1. 管理者権限で再度インストール　→　変わらず。
2. カーネル制御実行　→　OK!!!!
        
        pip install ipykernel
        ipython kernel install --user --name=<仮想環境名＞
        jupyter notebook

※以下ブロクが大変参考になりました。感謝致します。

https://sinyblog.com/python/%E3%80%90jupyter-notebook%E3%80%91no-module-named-janome%E3%81%A7%E4%BD%BF%E3%81%88%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AE%E5%AF%BE%E5%87%A6%E6%B3%95/

## 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448426/99ca3488-afe4-7603-b91b-eb540f07ba63.png)

ちなみにせっかくなので

        ipython kernel install --user --name=<仮想環境名＞

ここを深掘りします。（chatGPTが

## IPythonカーネル
プログラム実行環境の一部特に対話型のプログラムやスクリプトの実行に関連しています。
IPythonカーネルは、IPythonと呼ばれる対話型のPythonシェルを裏で支えるコンポーネントです。

IPythonカーネルを特定の仮想環境にインストールすることで、その仮想環境内でのPythonプログラムの実行環境を構築することができます。具体的には、以下の理由からプログラムを実行できるようになります。

分離された環境: 仮想環境は、プロジェクトごとに独立したPython実行環境を提供します。プロジェクトごとに必要なライブラリや依存関係を独自に管理できるため、異なるプロジェクトでの競合や混乱を防ぐことができます。

ライブラリ管理: 各仮想環境は、そのプロジェクトに必要なライブラリやパッケージのインストールを行えるため、特定のプロジェクトに必要なツールやライブラリを簡単にセットアップできます。

環境の再現性: 仮想環境を使用することで、特定のプロジェクトの環境を簡単に再現できます。他の人が同じプロジェクトに参加する際にも、同じ環境を構築して共同作業が行いやすくなります。

カーネルの切り替え: IPythonカーネルを特定の仮想環境にインストールすることで、その仮想環境に対して独自のIPythonセッションを持つことができます。異なる仮想環境間で切り替えてプログラムを実行できます。

要するに、IPythonカーネルを特定の仮想環境にインストールすることは、プログラムの実行をより管理しやすく、環境を整理し、プロジェクトごとに適切な設定を行うための手段となります。

## Pythonでのカーネル設定の重要性とその意義
プログラムを書く際、適切な環境設定は大きな影響を与えます。特にPythonの場合、プロジェクトごとに環境を管理することが重要です。ここでは、Pythonでのカーネル設定の重要性とその意義について簡潔に説明します。

**1. 依存関係の管理**: Pythonプログラムは様々な外部ライブラリやパッケージに依存しています。しかし、異なるプロジェクトで異なるバージョンのライブラリが必要な場合、うまく管理しないと問題が発生します。カーネルを設定することで、プロジェクトごとに依存関係を独立して管理し、競合や混乱を避けることができます。

**2. 環境の再現性と共有性**: プロジェクトを他の人と共有したり、将来的に同じ結果を再現したい場合、実行環境の一貫性が必要です。カーネルを使用してプロジェクトごとの環境を構築することで、他の人とも同じ環境を再現でき、共同作業がスムーズに進みます。

**3. 名前空間の分離**: カーネルを設定することで、仮想環境ごとに異なる名前空間が作成されます。これにより、各プロジェクト内で定義された変数や関数が他のプロジェクトに影響を及ぼすことがありません。名前空間の分離はコードの安定性を保つために不可欠です。

**4. カーネルの切り替え**: カーネルを使用することで、異なるプロジェクトごとに異なるIPythonセッションを使い分けることができます。これにより、各プロジェクトごとに独自の設定や変数を持つことができ、コードの実行やテストが簡単に行えます。

Pythonでカーネルを設定することは、プログラムの品質と管理性を向上させるための鍵です。依存関係の管理、環境の再現性、名前空間の分離、カーネルの切り替えといった側面が、プロジェクトの成功に大きく貢献します。正しいカーネル設定は、プロジェクトをより効果的に進めるための一歩と言えるでしょう。

まさに1.の依存関係の管理に該当したのでは？
いい学びになった。

## 最後に
今回もお付き合いいただきありがとうございました。
今後ともよろしくお願いいたします。
Docker Desktop起動時にUnexpected WSL errorが起きる

# TL;DR

- `wsl.exe --list`を確認して、WSLの一覧を確認する。
- 既定が`docker-desktop-data` でない場合は、`wsl.exe --set-default docker-desktop-data` を実行する。

# 実行環境

- Windows 10
- Docker Desktop 4.22.0

# 発生した問題

Docker Desktopを起動を試みた時、Docker Desktopが起動・表示されると同時に、「Docker Desktop - Unexpected WSL error」というエラーダイアログが出た。画像は下。 ![スクリーンショット 2023-08-19 11.08.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368897/b67aa1d6-a3be-2eec-6d5d-329a9d50e4ce.png)
　その後、`docker-compose up`などのコマンドを実行するとエラー`docker daemon is not running`が起きた。（起動は中断されたらしい。）

# 試したこと（解決しなかった）

上述のダイアログに記載された対応のうち、下記を試した。解決しなかった。
- `wsl --shutdown`
- PC再起動
- Docker Desktopのアンインストール・再インストール

# 解決

- コマンドプロンプトでWSL一覧を確認した。
```
>wsl --list
Linux 用 Windows サブシステム ディストリビューション:
rancher-desktop-data (既定)
docker-desktop
rancher-desktop
docker-desktop-data
```
- `wsl --set-default docker-desktop-data` を実行した。
- `wsl --list`を再度実行して、`docker-desktop-data`が(既定)に変わったことを確認した。
- Docker Desktopを起動した。上述の問題は再発しなかった。
Next.js13 学習メモ

# 参考にしたサイトなど
https://reffect.co.jp/react/next-js-13/


# Next.13 のディレクトリ構造の特徴
- Next.js 13 は、12以前とはかなり仕様が異なっている
- 具体的には、これまでは `Pages Directory` だったものが `App Directory` になった。単に `Next.js` で検索すると、古い仕様の記事がヒットしてしまうため要注意。

| 関連ワード | page.tsxの配置 | Path | 備考 | 公式 |
|:-|:-|:-|:-|:-|
| App Directory  | app/tasks/page.tsx  | /tasks  | page.tsxというファイル名は固定。  |-|
| ~~※Pages Directory~~  | ~~pages/tasks.tsx~~  | ~~/tasks~~  | ~~Next.jsでも使用できるが、非推奨。~~  |-|
| Route Group  | app/tasks/[id]/(group1)/(group2)/page.tsx  | tasks/6ge49mrk  | `()` を使ったディレクトリを間に含めて作成した場合、 そのディレクトリ名はパスに反映されない。基本的に、ディレクトリ名がそのままパスに反映されるため、大規模アプリケーションではグループ化しないとごちゃごちゃしてしまうので、その対応策 |-|
| Dynamic Routes  | app/tasks/[id]/page.tsx  | tasks/6ge49mrk  | ・`[]` を使ったディレクトリを間に含めて作成した場合、その部分のパスは任意の文字列を指定することができる。<br>・ 例えば`Link` のtoオプションに `tasks/${task.id}`を指定し、作成するコンポーネントで`router.query.id`などの形式で利用できる。 |https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes|


# Next.jsのFetchとSSG・SSR
[公式によるDataFetchingの解説](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating)

- SSGは、静的なページ（変更の少ないページ）に対して適用
- SSRは、静的なページ（変更が頻繁なページ）に対して適用
- Next.js 12以前は、 SSGならば`getStaticProps + getStaticPaths`、SSRならば、`getServerSideProps`で取得していたが、13以降は、単に`fetch`メソッドにオプションを追加するだけで、SSG・SSRを区分できるようになった。

| 区分 | コード例 | 解説 |
|:-|:-|:-|
| SSG  | `fetch('http:sample.com/tasks', { cache: "force-cache", next: {revalidate: 60 } })`  | ・force-cache（=必ずcacheを利用する）から連想する通り、最初にレンダリングしてしまい、以降はcache値を参照する。<br>・force-cacheは省略可能<br>・revalidateは、再度リクエストするまでの秒数。  |
| SSR  | `fetch('http:sample.com/tasks', { cache: "no-store" })`  | ・no-store（=保存しない）から連想する通り、保存しない代わりに、都度レンダリングする。  |


# VSCodeのスニペット
| 入力 | 内容 |
|:-|:-|
| rafce  | ファイル名と一致するComponentのひな型を作成してくれる  |
| tab  | インポートされていないComponentにカーソルを合わせて押すと、自動でimportしてくれる  |
|   |   |

# 周辺知識
### 型安全（TypeScript対応）なライブラリ
```
$ npm i --save-dev @types/uuid
```

### Jamstack
- JavaScript API Markup の略
- 通常は Client→WebServer→AppServer→DB or CMS→AppServer→WebServer→Client
- Jamstackは Client⇄CDN, MicroServices
ブラウザキャッシュのせいでvuetifyが反映されない

## 概要

vue2にvuetifyを導入し、コード修正後にページを更新したが、console.logに以下のメッセージ。

```bash
[Vue warn]: Unknown custom element: <v-text-field> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
```

vuetifyが機能していない。

## 解決したい課題

vuetifyを機能させること。

## 課題の原因

npmのキャッシュが原因だった。

`npm run serve` を止めて、`npm cache clean --force` を実行し、再度`npm run serve`で解決。

## 課題解決手順

### scriptタグにnameオプションを追記

```bash
<template>
  <v-app>
    <v-card>
      <v-card-title>
        <h1 class="">ログイン</h1>
      </v-card-title>
    </v-card>
    <v-card-text>
      <v-form>
        <v-text-field label="ユーザ名" />
        <v-text-field label="パスワード" />
      </v-form>
    </v-card-text>
  </v-app>
</template>

<script lang="ts">
export default {
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
	name:LoginView
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
</script>
```

上記を追加しても、同様のエラーメッセージが表示される。

そもそも、nameオプションの存在意義はデバッグのためでしかない。

参考：

[【Vue】export defaultのnameとは何か？いつどこで何に使い、なぜ必要なのか？意味と役割を実例で解説（Vue.js devtoolsでのデバッグ方法）](https://prograshi.com/language/vue-js/purpose-of-name-in-export-default/)

### ブラウザキャッシュの問題

vuetifyの依存関係の可能性もあったけど、vue2とvuetify2であれば問題ない可能性が高いと見て、キャッシュに焦点を当てた。

参考：

[npm | キャッシュのクリア方法 | 修ちゃんの技術資料](https://prettytabby.com/npm-cache/)

ということで解決。

定期的にキャッシュはクリアしていくべき。
【勝手に】Spring Security公式のチュートリアルで紹介されたページをWebMvcConfigurerなしで作る【補足してみた】

## 概要
Spring Securityの公式サイトに掲載されている、下記のソースが一般に知られているものではないと思ったので、勝手に補足してみました。

一応、初心者向けの説明のつもりです。

~~~Java:src/main/java/com/example/securingweb/MvcConfig.java
package com.example.securingweb;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/home").setViewName("home");
		registry.addViewController("/").setViewName("home");
		registry.addViewController("/hello").setViewName("hello");
		registry.addViewController("/login").setViewName("login");
	}

}
~~~
## 要はこういうこと
先に書いておきますが、上記のコードは下記のコードと同じものと思っていただいて結構です。(実際はチョット違う)

~~~Java:src/main/java/com/example/securingweb/Controllers.java
package com.example.securingweb;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Controllers {

    @RequestMapping({"/home","/"})
    public String requestHome(){
        return "home";
    }

    @RequestMapping("/hello")
    public String requestHello(){
        return "hello";
    }

    @RequestMapping("/login")
    public String requestLogin(){
        return "login";
    }

}
~~~
::: note info
公式サイトのコードに`WebMvcConfigurer`とか`addViewController`とか`setViewName`とか、色々知らないメソッドやインターフェースがあります。気にしなくて良いです。実際の開発で、エンドポイントがテンプレートを返すだけということは、あり得ないからです。
:::

`@Configuration`アノテーションが公式サイトのソースについているので、Springを起動した際に`MvcConfig`は実行されます。
一方で、`@Controller`アノテーションをつける一般的なやり方では、クライアントからリクエストが飛んできた際に実行されます。ここが違いの１つ。

`@Configuration`アノテーションを使うコードと、`@Controller`アノテーションを使うコード両方を組み込むと、`@Controller`アノテーションの方が優先されます。
これは単純に先ほど説明した通り、Springを起動した際に`MvcConfig`は実行され、クライアントからリクエストが飛んできた際に実行されるからです。
つまり両方書いても、ちゃんと動きます。コード的には無駄がありますが。

## 参考情報
- [Spring Boot ログイン画面 - 公式サンプルコード](https://spring.pleiades.io/guides/gs/securing-web/)
GPUのメモリ確認

GPUのメモリを確認する方法を説明します。

# インストール

```bash
pip install nvidia-ml-py3
 ```

# 確認

```python
import nvidia_smi

nvidia_smi.nvmlInit()

deviceCount = nvidia_smi.nvmlDeviceGetCount()
for i in range(deviceCount):
    handle = nvidia_smi.nvmlDeviceGetHandleByIndex(i)
    info = nvidia_smi.nvmlDeviceGetMemoryInfo(handle)
    print("Device {}: {}, Memory : ({:.2f}% free): {}(total), {} (free), {} (used)".format(i, nvidia_smi.nvmlDeviceGetName(handle), 100*info.free/info.total, info.total, info.free, info.used))

nvidia_smi.nvmlShutdown()
```


```bash
Device 0: b'Tesla T4', Memory : (98.32% free): 16106127360(total), 15835267072 (free), 270860288 (used)

```

# 参考

https://pypi.org/project/nvidia-ml-py3/
pandas-datareaderで株価取得してsqliteに保存とbacktestingする方法

# 自己紹介
　初めて投稿します。
　普段は生産技術/生産システム/調達エンジニアとして働いています。
　機械と電気とITを融合したメカトロニクスこそ日本の強みと思っています。
　本業とはまったく別の趣味をアウトプットしてみようと思います。

# 株取引について
　趣味です。
　自己流では勝つことはできないようです。
　統計分析が必要なようです。
　何事も、計測⇒分析⇒対策⇒実行のPDCAサイクルが必要なのでしょうね。

# 株価取得について
　無料でデータ取得するのにpandas-datareaderを採用しました。
　なぜかポーランドのstooqという情報源です。最新データが一日遅れくらいです。
　有料ならj-quantsがよいと思います。

# データベースについて
　将来的にデータ管理が必要と思い、pythonの個人利用ならsqliteという選択です。
　
# バックテストについて
　なにがよいのかわかりません。
　とりあえずbacktesting.pyを選定しました。
　tradingviewのpinescrptもやっていますが、無料枠の限界あり。

# サンプルコード
```py
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
from backtesting.test import SMA
from pandas_datareader import data
import pandas as pd
import numpy as np
import datetime as dt
import sqlite3

# 変更する部分：複数の銘柄コードをリストで指定
codes = ['6927', '6752', '3607', '7014']
start = '2021/01/01'
end = dt.date.today()  # 取得終了日

# SQLiteデータベースに接続
conn = sqlite3.connect('stock_data.db')

# 変更する部分：各銘柄コードに対して繰り返し処理
for code in codes:
    df = data.DataReader(code+'.JP', 'stooq', start, end)

    # DataFrameをSQLiteデータベースに保存
    df.to_sql('stock_data_' + code, conn, if_exists='replace', index=True)

# データベース接続を閉じる
conn.close()


class SmaCross(Strategy):
    n1 = 10
    n2 = 20

    def init(self):  # 初期設定
        price = self.data.Close
        self.ma1 = self.I(SMA, price, self.n1)
        self.ma2 = self.I(SMA, price, self.n2)

    def next(self):  # 売買条件
        if crossover(self.ma1, self.ma2):
            self.buy()
        elif crossover(self.ma2, self.ma1):
            self.sell()
            # self.position.close(): 保有ポジションの手仕舞


# 変更する部分：各銘柄コードに対して繰り返し処理
for code in codes:
    # SQLiteデータベースからデータを読み込む
    conn = sqlite3.connect('stock_data.db')
    query = f"SELECT * FROM stock_data_{code}"
    df = pd.read_sql_query(query, conn)
    conn.close()

    # Backtestを使用して戦略を実行
    bt = Backtest(df, SmaCross, cash=200000, commission=.002,
                  exclusive_orders=True)
    stats = bt.run()
    bt.plot()

    print(stats)

    # 最適化
    output2 = bt.optimize(n1=range(10, 70, 5), n2=range(10, 70, 5))
    print(output2)
    bt.plot()
    print(output2._strategy)

```
　
# 結言
　日々、勉強して参ります。
　皆様のご指導いただけると深甚です。
ISUCON対策まとめ

ISUCONの時にやってみたらいいと思ったこと・過去の経験をまとめていきます。
リアルタイムで随時更新していきます。

# 基本事項（前回参加から学んだこと。）

ISUCON12に参加して学んだこと。

## 結局Goでいいと思う

他の言語に切り替えも可能だが、Go言語が一番点数高くなる気がする。切り替えにも時間を要するので、Goにしてしまえばいいと思う。

自分はGo勉強して望むという選択肢を取る予定。

## 役割分担を明確にしておく

振り分けられそうと思ったのは、

- Webサーバの設定変更の担当者
- デプロイコードや自動化担当者
- コードの修正担当者

ただ、これは適材適所

# Webサーバの対策

TODO

# アプリケーションの対策

### デプロイ（ほぼ）自動化コードを書く

```bash:deploy.sh
git pull
make build
cp ./project ~/webapp
```
みたいな、コマンドを作っておく。コードの修正担当者が
```sh
deploy.sh
```
を実行すればデプロイできるところぐらいまでできたらベストかなと感じた。
本当はベンチ実行もできたらいいのだが、isucon12ではサイト上から実行できるという形式に変わったので、そこは次回もそうなるのではないかと見ている。

### SQL構文 EXPLAIN

https://thinkit.co.jp/article/9658

SQLの実行計画（SQL実行したときにインデックスがきちんと動作するかとか、どれくらい時間かかるか）を見ることができる。

```sql
-- `EXPLAIN {特定のSQL}`みたいな使い方ができる
EXPLAIN SELECT * FROM HOGE_TABLE WHARE any_column = 'xxx';

```
ストワで始めるLua 第11回 まっぷ

タッチしたらそこにマップが移動するやつ

```lua:map

isTouching=false
centerPosition={}
touchPosition={}
function onTick()
	local rangeScale,height,width,touchX,touchY,isTouch
	
	rangeScale=input.getNumber(8)
	zoom=rangeScale/1000 --display range
	gpsPosition={x=input.getNumber(9),y=input.getNumber(10)} --position of vehicle
	
	--touch screen
	isTouch=input.getBool(1) 
	if isTouch and not(isTouching) then
		width=input.getNumber(1)
		height=input.getNumber(2)
		touchX=input.getNumber(3)
		touchY=input.getNumber(4)
		isTouching=true
		touchPosition.x,touchPosition.y=map.screenToMap(centerPosition.x, centerPosition.y, zoom, width, height, touchX, touchY) --world position of touch
	end

	--Center coordinates
	if next(touchPosition) then
		centerPosition=touchPosition
	else
		centerPosition=gpsPosition
	end

	--flag
	if not(isTouch) and isTouching then
		isTouching=false
	end

	isReset=input.getBool(2)
	if isReset then
		touchPosition={}
	end
end

function onDraw()
    --position = World XY , pixel = Display XY
	local width,height
	local gpsPixel={}

	width=screen.getWidth()
	height=screen.getHeight()
	screen.drawMap(centerPosition.x, centerPosition.y, zoom) --drawring map

	gpsPixel.x,gpsPixel.y=map.mapToScreen(centerPosition.x, centerPosition.y, zoom, width, height, gpsPosition.x, gpsPosition.y) --Location of the vehicle
	screen.drawCircle(gpsPixel.x,gpsPixel.y,5)
end
```
【SwiftUI】taskモディファイアのドキュメントを読む

# この記事は何？

SwiftUIフレームワークの`task`モディファイアについて、[開発者向けドキュメント](https://developer.apple.com/documentation/realitykit/model3d/task(priority:_:)/)を独自に解説。

# task(priority:_:)メソッド

「対象のビューが表示される前」に実行したい非同期タスクを追加できる。

```swift:宣言
func task(
    priority: TaskPriority = .userInitiated,
    _ action: @escaping () async -> Void
) -> some View
```

**パラメータ**

- *priority*
追加する非同期タスクの優先順位。デフォルトの優先度は`userInitiated`。

- *action*
ビューの表示直前に、SwiftUIが非同期タスクとして呼び出すクロージャ。
`action`のクロージャが完了する前にビューが消えると、SwiftUIはある時点で自動的にタスクをキャンセルする。

**返り値**

ビューが表示される前に`action`クロージャを非同期に実行するビュー。

# Discussion

このモディファイアを使用して、適用したビューのライフタイムに一致する非同期タスクを実行できる。
SwiftUIがビューを削除するか、ビューの身元が変更される前にタスクが終了しない場合、SwiftUIはタスクをキャンセルします。

タスク内で`await`キーワードを使用すると、非同期呼び出しの完了を待つか、あるいは`AsyncSequence`型インスタンスの値を待つ。
以下の例では、`Text`ビューにtaskモディファイアが適用されており、その際に`priority`パラメータは省略されている。
メッセージが変更されると「WEBリソースからコンテンツを読み込む」というタスクを非同期的に開始でき、モディファイアが返すTextビューで画面が更新される。

```swift:
let url = URL(string: "https://example.com")!
@State private var message = "Loading..."

var body: some View {
    Text(message)
        .task {
            do {
                var receivedLines = [String]()
                for try await line in url.lines {
                    receivedLines.append(line)
                    message = "Received \(receivedLines.count) lines"
                }
            } catch {
                message = "Failed to load"
            }
        }
}
```

上の例では、`lines`を使用して、指定のURLに格納されたコンテンツを文字列の非同期シーケンスとして取得する。
新しい行に到達するたびに、`for-await-in`ループのボディはその行を配列に格納する。
そして、Textビューの内容を更新して最新の行数を報告する。

なお、`URL`型インスタンスの`lins`プロパティは指定URLのリソースデータ（実際は、テキスト行の非同期シーケンス）。
詳細は[開発者向けドキュメント](https://developer.apple.com/documentation/realitykit/model3d/task(priority:_:)/)を参照。
Pythonが嫌いなのでC++版のPytorchで画像認識をやってみる 15日目 C++でYolov8

# YoloV8
15日目とか書きつつ既に1年経ってしまった。オジサンの一生は短い。
もたもたしているうちにYoloがバージョンアップしてYoloV8が出てしまった。
性能的にガツンと上がったわけでは無さそうだけどCLIが用意され、普通のアプリケーションのようになってきた。次はGUIになっていよいよ「アプリ」になっていくのだろうか。

# C++でYoloV8を動かす
C++とYolov8の組合せについて、日本語で調べてもあまり情報が無い。というか皆無。ChatGPT先生に聞いても「最近のことは分かりません」とツレナイ返事。何かいろいろ調べていたら、何のことは無い、公式にサンプルがあった。
ここ↓
[ultralytics/examples/YOLOv8-CPP-Inference/inference.cpp
](https://github.com/ultralytics/ultralytics/blob/main/examples/YOLOv8-CPP-Inference/inference.cpp#L30C1-L30C1)
公式にあるんじゃ調べても出てこないわけだ。

# 動かし方
基本的にはyolov8のptファイルをonnxに変換し、opencvのdnnで動かせばいい。yolov5と同じである。注意点は下記の3点。
* Onnx convert はyolov8のCLIを使う。こんな感じ。
```
yolo export model=yolov8m.pt format=onnx opset=12
```
* OpenCV 4.8.0を使う
CPUバージョンだと4.8.0でないと動かなかった。自分でコンパイルとしたGPUバージョンだと4.7.0でも動いた。余談だが、4.8.0だとGPUバージョンを自分でビルドしなくてもGPUに対応しているような気がするけどどうなのか。⇒ダメでした。
* 出力のサイズが違う
公式のコードを見れば分かる。

# 手順
別につまづきポイントが有ったわけではないけど、ptファイルのダウンロードするまでをサラッと手順をメモる。公式に手順が出ているので困ることは無いと思うが一応。
1. yolov8用の作業フォルダを作る。
2. pythonまたはcondaでyolov8の環境を作る。
3. その環境をアクティベーション。
4. 下記のコマンドでyolov8をインストール。
```
pip install ultralytics
```
5. pip install requiement.txt は**しなくていい**
6. pythonを起動
7. pythonのプロンプトで、下記コードでptファイルをダウンロードする。
```
>>>from ultralytics import YOLO
>>> model = YOLO("yolov8s.pt")
>>> model = YOLO("yolov8s.pt")
>>> model = YOLO("yolov8m.pt")
>>> model = YOLO("yolov8l.pt")
>>> model = YOLO("yolov8x.pt")
```
これで作業フォルダにcocoの学習済みのptファイルが保存されている。別に自分でリンクを探して落としてもそんなもんだと思うけど。

次はいよいよソースを載せたいが･･･
つづく
Ubuntu20.04LTSに開発用Winodws11を入れてみた話

## Microsoft公式サイトでWindows11の仮想イメージを配布
MicrosfotからいろんなタイプのWindows11仮想イメージが配布されています。
下記サイトからダウンロード可能です。
https://developer.microsoft.com/ja-jp/windows/downloads/virtual-machines/


### VirtualBoxのイメージをダウンロードしてみた
このサイト内の各仮想環境名が書かれた青色のボタンのようなリンクを押すとダウンロードが始まります。
容量はVirtaulBoxで23GBほどあるのでそれなりにダウンロード時間が必要です。

### Ubuntu20.04の環境でVirtaulBoxにインポートする
ダウンロードしたZipファイルはWinDev230BEval.ovaというファイルに展開される。
.ovaファイルはツールメニューのインポートから開くことができる環境で仮想環境名や動作環境が初めから入った状態になっている。
ちなみにインポート直後はvCPU４のメモリ8Gでになっているので今使ってる環境ではオーバースペックだったためvCPU2のメモリ4Gに変更してインポートしてみました。

### 動くのか？
とりあえず、起動するところまでは確認が取れた。
VS2022とWSL2がもとからインストールされた状態でローケールは英語になっている。
とりあえずは動作しそう・・・