OmniAICreator/Qiita-1.07M huggingface dataset:
Bootstrap-Table内画像リンク切れ魔貫光殺砲（蜃気楼編）

# 概要
- Bootstrap-Table を利用したテーブルに表示している画像のリンク切れ(蜃気楼)を検知し、デフォルト画像（No image）に差し替える（魔貫光殺砲）スマートな方法

# 方法
- Bootstrap Table の `data-events` を利用する
    - https://bootstrap-table.com/docs/api/column-options/#events

# サンプル
```html
<table
  id="table"
  data-toggle="table"
  data-height="460"
  data-url="json/data1.json">
  <thead>
    <tr>
      <th data-field="id">ID</th>
      <th data-field="name">Item Name</th>
      <th data-field="price">Item Price</th>
      <th data-field="image" data-formatter="imageFormatter" data-events="imageEvents">Image</th>
    </tr>
  </thead>
</table>

<script>
  var $table = $('#table');

  function imageFormatter(value, row, index) {
    const image_url = index % 2 === 0 ? 'https://placehold.jp/3d4070/ffffff/150x150.png?text=TEST' : 'https://example.com/example.png';
    return ['<img class="img-' + index + '" src="' + image_url + '">'].join('');
  }

  window.imageEvents = {
    'error img': function (e, value, row, index) {
      $('.img-' + index).attr('src', 'https://placehold.jp/a3a3a3/ffffff/150x150.png?text=NO IMAGE');
    }
  }
</script>
```
【Vue3,Vite】Vueプロジェクトの作成

# 環境構築
~~......は飛ばしますが、~~ 
後述の前に、VSCodeのインストールとNode.jsのインストールが必要です。

# Vueプロジェクト作成コマンド
プロジェクトを格納する親フォルダ上で実行します。
``` 
npm init vue@latest
```
enterを押すと以下の質問がずらっと出てきますが、落ち着きましょう。

## プロジェクト作成時の質問と回答
```
Project name:　hogehoge
Add TypeScript? --yes or no
Add JSX Support? --yes or no
Add Vue Router for Single Page Application development? --yes or no
Add Pinia for state management? --yes or no
Add Vitest for Unit Testing? --yes or no
Add Cypress for both Unit and End-to-End testing? --yes or no
Add ESLint for code quality? --yes or no
Add Prettier for code formatting? --yes or no
```
### 質問の意味
##### Project name:
* 任意の名前を入力する　ex. hello-vue

##### Add TypeScript?
* TypeScript[^1]で記述するかどうか
[^1]: 最近はTypeScriptで記述が多いような気がします(ただの所感)
##### Add JSX Support?
* JSX[^2]を利用するかどうか
[^2]:JavaScriptコード内にHTMLを記述できる拡張機能
##### Add Vue Router for Single Page Application development?
* Vue Router[^3]を利用するかどうか
[^3]:利用することでシングルページアプリケーションを簡単に作成できる
##### Add Pinia for state management?
* Pinia[^4]を利用するかどうか
[^4]: データをまとめて管理するライブラリ
##### Add Vitest for Unit Testing?
* Vitest[^5]を利用するかどうか
[^5]: ユニットテストを行うためのライブラリ
##### Add Cypress for both Unit and End-to-End testing?
* Cypress[^6]を利用するかどうか
[^6]: UI操作を含めてアプリケーション全体をテストするライブラリ
##### Add ESLint for code quality?
* ESList[^7]を利用するかどうか
[^7]: JavaScriptなどのソースコードが正しいかどうかを解析するツール
##### Add Prettier for code formatting?
* 　Prettier[^8]を利用するかどうか
[^8]: ソースコードを整形するツール

# プロジェクトの作成完了
下記のような画面になれば作成成功です。
```
(略)
Done. Now run:
  cd hello-vue
  npm install
  npm run dev
```
* cd hello-vue
* npm install
* npm run dev
以上、3つのコマンドを順番に実行します。

# 開発用サーバーの起動
npm run devを実行後、
http://localhost:0000/ のようなURLが出てきます。
URLの上にカーソルをのせ、commandを押しながらクリックします。

You did it!と書かれたページがブラウザに表示されれば成功です。
GraphQL の mutation と subscription を wscat と curlで簡単にやる

## 背景
サクッと動作確認したい時にターミナルからできると便利。
AppSyncではコンソールからワンクリックでPub/subを行うWebSokect APIを作れる。
しかし簡単に作れると言っているこのチュートリアルでも、クライアント側はReactとAmplify JavaScriptである。もっと簡単に試したい。
[サーバーレスを利用した汎用 Pub/Sub API の作成WebSockets](https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/aws-appsync-real-time-create-generic-api-serverless-websocket.html)

## 前提
- APIキー認証
- コンソールからワンクリックで作成した際のスキーマはこれ。publish(HTTPS)するとsubscribe(WSS)しているクライアントにその通知がいく。
```graphql
type Channel {
	name: String!
	data: AWSJSON!
}

type Mutation {
	publish(name: String!, data: AWSJSON!): Channel
}

type Query {
	getChannel: Channel
}

type Subscription {
	subscribe(name: String!): Channel
		@aws_subscribe(mutations: ["publish"])
}
```

## 結果
### Subscribe
一応細かい手順はこれを見ることになっている。[WebSocketリアルタイムクライアントの構築](https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/real-time-websocket-client.html)

しかし実際のコマンドで試すなら[こちらのプライベートAPIについてのドキュメント](https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/using-private-apis.html#advanced-example)がわかりやすかった(パブリックAPIでもコマンド自体は同じ)。

```bash
header=`echo '{"host":"<API_ID>.appsync-api.ap-northeast-1.amazonaws.com","x-api-key":"xxxxxxxxxxxxxxxxxxxxxxxxxx"}' | base64 | tr -d '\n'`
wscat -p 13 -s graphql-ws -c  "wss://<API_ID>.appsync-realtime-api.ap-northeast-1.amazonaws.com/graphql?header=$header&payload=e30="
```
接続された後は順に以下を送信すればsubscribe完了
```bash
{"type": "connection_init"}

{"id":"tekitouid","payload":{"data":"{\"query\":\"subscription SubscribeToData ($name: String!) {subscribe (name:$name) {name data}}\",\"variables\":{\"name\":\"robots\"}}","extensions":{"authorization":{"host":"<API_ID>.appsync-api.ap-northeast-1.amazonaws.com","x-api-key":"xxxxxxxxxxxxxxxxxxxxxxxxxx"}}},"type":"start"}
```

これでチャンネル`robots`に送publishされたメッセージを受信する。

### publish
こちらはcurl. 変数を伴うパラメータはいつもわからなくなるので。。エスケープとかクォート入れる箇所とか。
```bash
curl https://<API_ID>.appsync-api.ap-northeast-1.amazonaws.com/graphql \
-H "Content-Type:application/graphql" \
-H "x-api-key:xxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{"query":"mutation Publish($data: AWSJSON!, $name: String!) {publish(data: $data, name: $name){data name}}","variables":{"name":"robots","data":"{\"robot\":\"r2d2\", \"planet\": \"tatooine\"}"}}'
```
variablesのdataは `"data":{"robot":"r2d2"...}`とかでもダメで`"data":"{\"robot\":\"r2d2\"...}"`というようにきっちりダブルクォートで囲んでエスケープしないとダメそうだった。
ElixirでHelloWorldプログラムを実装してみた

# 概要
ElixirでHelloWorldプログラムを実装してみました。以下のページを参考にしました。

https://qiita.com/tanaka0325/items/045ce9d9ee9355741c3d

# 環境構築
以下のコマンドを実行しました。
```
$ sudo apt install elixir
```

# プログラム作成
以下の通りソースコードを作成しました。
```hello.exs
defmodule Hello do

    def world do
        IO.puts "Hello world"
    end
end

Hello.world
```

# プログラム実行
以下の通りコマンドを実行しました。
```
$ elixir hello.exs 
Hello world
```

# まとめ
何かの役に立てばと。
php laravelに触れる機会があったのでメモ

- .envに書かれたものを取り出して使うときは必ずconfigで一度呼び出して使う。
    - PHP ララベルは速度を出すために```php artisan config:cache```でキャッシュを使うことができる。
    - ただし、そのコマンドを打つとキャッシュを作成してしまうと、.envが変えても反映されない。
    - なので、```php artisan config:clear```でキャッシュをクリアする。
    - ちなみにローカルでは```php artisan config:cache```はほとんど打たない。
Quita 初投稿

## 検証データ　ドル円とポンドドル　
## 2023/05/30 9:00　～　2023/06/01 8:00
## 元のデータフレームから積カラムが負である行だけを選択

import pandas as pd
import matplotlib.pyplot as plt

# CSVファイルからデータを読み込む
df = pd.read_csv("prtice_53031.csv")

# データフレームのカラム名を指定する
df.columns = ['Date','USDJPY', 'GBPJPY','EURJPY','EURUSD','GBPUSD']

# プロットのサイズを指定する
fig, ax = plt.subplots(figsize=(10, 8))

# USD/JPYの折れ線グラフを描く
ax.plot(df.index, df['USDJPY'], color='b')
ax.set_xlabel('Date')
ax.set_ylabel('USDJPY', color='b')
ax.tick_params('y', colors='b')

# GBP/USDの折れ線グラフを描く
ax2 = ax.twinx()
ax2.plot(df.index, df['GBPUSD'], color='r')
ax2.set_ylabel('GBPUSD', color='r')
ax2.tick_params('y', colors='r')

# プロットを表示する
plt.show()
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3428040/4a2f77aa-fa00-2047-7e04-6987000a6763.png)

# それぞれ前の行との差分を求めてカラムを作成
df['USDJPY_diff'] = df['USDJPY'].diff()
df['GBPUSD_diff'] = df['GBPUSD'].diff()

# 差分カラム同士の積を計算してカラムを作成
df['product'] = df['USDJPY_diff'] * df['GBPUSD_diff']

# 積カラムが負である行だけを選択
df_negative = df[df['product'] < 0]

# データを表示する
print(df_negative)

![2023-06-01_20h21_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3428040/619ae509-d7f1-718d-6f93-16c59ac2ab2d.png)

例えば　43行目　この結果は、データフレームの43行目の値を示しています。USD/JPYは0.0420円上昇し、GBP/USDは0.000792ドル下降しました。その積は-0.000033となり、負の値です。これは、この時間帯にUSD/JPYとGBP/USDは逆相関があったことを意味します。
Pythonで module '***' has no attribute '***' のエラーがとれない！

# たまに見るこのエラー

```console
AttributeError: module '***' has no attribute '***'
```

普通なら `pip install --upgrade` とかでなおります。
`pip uninstall` で消してからの方が確実でしょう。
バグ情報を見てバージョン指定で入れてもいいと思います。

・・・それでもなおらないことありますよね？

# 自分のファイル名をうたがえ！

これ１年に一回くらいやっちゃいます……。
例えば

```python:openai.py
import openai

response = openai.ChatCompletion.create(
    :
```

で、こんなエラーが出るとき。

```console
module 'openai' has no attribute 'ChatCompletion'
```

あなたのソースコードのファイル名が `openai.py` とかになってないですか？
なってたら別の名前にしてください！ `test_openai.py` とか。

> import はライブラリ読み込むときにつかいます。
> ライブラリを探すときにカレントディレクトリから探し始めるので、これだと自分自身をインポートしちゃいます。
> で、自分自身の .py に `ChatCompletion` なんて定義されていないのでエラーです！
>
> 普段はこんなミスないでしょうが、、、たまに新しいライブラリを試しにつかってみよう！みたいなときにこんなファイル名をつけがちで地味にはまります……
rex0220 関連レコード集計プラグイン 組織選択で集計

関連レコード集計プラグインを使って、組織単位に集計する例です。
組織選択項目を集計キーに使用する場合、SEL_CODE で組織コードを取得する必要があります。

# 概要

アプリのレコード追加・更新時に、組織ごとにレコード集計を行います。

![2023-06-01_19h56_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/0cef4b44-f6cd-920a-7941-6e7b7bd78c46.png)

# アプリ設定

組織ごとに集計を行う場合は、組織選択項目を必須にする必要があります。
※kintone REST API の仕様により、組織選択が空のレコードを取得できないため。

![2023-06-01_20h00_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/877b995e-08ca-5a38-50e4-c59ecfa67954.png)


# 関連レコード集計プラグインの設定

集計先アプリを選択して、対象アプリ条件・集計条件・集計項目等を設定します。

![2023-06-01_20h00_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/83985983-ff6f-1b99-b32b-a5f2ed02f066.png)

## 対象アプリ条件

組織選択の条件値には、組織コードが必要なため、SEL_CODE 関数を指定します。

- 条件値：SEL_CODE(組織選択,"array")
![2023-06-01_20h05_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ca1868ef-8494-baa2-c04f-8aa35a61de1c.png)

## 集計条件

こちらも組織選択の条件値には、組織コードが必要なため、SEL_CODE 関数を指定します。

- 条件値：SEL_CODE(組織選択,"array")
![2023-06-01_20h08_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/6b5e26ea-8557-0a4d-349b-3bc2deb833c2.png)

# 集計項目

集計キーになる組織コードの設定は、SET_CODE, SEL_CODE 関数を指定します。

組織選択の項目（計算式）：
```.js
// 組織選択
SET_CODE(
  SEL_CODE(組織選択,"array")
)
```

![2023-06-01_20h09_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7143679b-8a7b-ecb1-3abd-25132211d857.png)
Azure OpenAI ServiceでモデルをFine-tuningする手順

Open AIが提供しているモデルはFine-tuning（微調整）をすることでモデルをカスタマイズすることができます。
自身でモデルをカスタマイズする利点としては、
- プロンプト デザインからだけでは得られないより高品質な結果
- プロンプトの短縮によるトークン節約
- 待機時間の短縮
等が挙げられます。

具体的なユースケースとしては自社のデータでトレーニングすることで、社内の専門用語や独自の手続きを理解した上で、文章を生成してくれるモデルを作ることができそうです。

Azure OpenAI ServiceではこのFine-tuningをプレイグラウンド（GUI）から、簡単に実行できます。

### 前提条件
- Azureのサブスクリプションを利用出来る
- Azure OpenAI Serviceの[利用申請](https://aka.ms/oai/access)が完了しており、リソースが作成できる
- コストがかかることを許容できる

### 1. トレーニングデータの準備
トレーニングデータはprompt（入力）に対する、completion（出力）の形式でJSONファイルを準備します。

https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset

```json
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
...
```

今回は、以下の会話テキストデータセットを使わせてもらいました。「話しかけ」と、つくよみちゃんらしい「お返事」のデータが400以上含まれています。

以下のサイトで、利用規約を確認してから、Excel形式のデータをダウンロードします。

https://tyc.rei-yumesaki.net/material/kaiwa-ai/#terms8

そして、ExcelのB列、C列を残したCSVをゴニョゴニョ作っておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/e08cb591-503c-00f0-711c-c57248857ff0.png)

CSVのままではトレーニングデータとして使えないので、OpenAI公式のCLIツールを使ってJSONに変換してあげます。
- CSVはUTF-8 BOMでないとツールが読み取れないので注意
- CLIがいろいろ指示してきますが一旦全部`n`で応答
```bash
$ pip install --upgrade openai
$ openai tools fine_tunes.prepare_data -f つくよみちゃん会話AI育成計画.csv
```

### 2. プレイグランウドにアクセスし、カスタムモデルを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/7a88960f-514a-982e-0051-ea356f22d16b.png)

#### ベースモデルの選択
Fine-tuningのベースとなるモデルを選択します。
今回は`ada`を選択します。
各種モデルについては以下をご確認ください。

https://learn.microsoft.com/ja-jp/azure/cognitive-services/openai/concepts/models#model-summary-table-and-region-availability

:::note warn
code-cushman-001とdavinciモデルについては2023/6/1現在、新規のカスタムモデルのベースには選択できないそうです。
また、ChatGPTなどの会話型インターフェースに特化した、gpt-35-turboやgpt-4もFine-tuningの対象外となっています。
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/e02c75fa-d8a0-d644-edd6-1670f9904fcf.png)

#### トレーニングデータのアップロード
先程1で作成した、JSONファイルをローカルからアップロードします。
ファイルサイズは100Mまでで、Blobストレージからアップロードすることも可能です。

その後は検証データや詳細設定オプションはデフォルトのままスキップして作成！
約45分程度かかります。

#### モデルのデプロイ
作成したモデルはデプロイしないと使えません。
デプロイにも45分程度かかりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/c9e53c30-0914-afc9-52fe-7d02401e0abc.png)

### プレイグランドで確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/dc7262bb-9c98-5024-21bf-eed4042e8a6e.png)
正しい答えではないですが、トレーニングに使ったデータの内容を返していることが分かります。
※他にもいろいろ質問してみましたが、頓珍漢なことばかり応答します、、

### コスト
カスタマイズしたモデルはいわゆるトークン数の課金にプラスして、モデルを実行している時間単位で課金されます。
さらに、トレーニングに費やした時間も別の計算方法で課金されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/704e5146-b6ba-af50-5876-8869c3562780.png)

https://azure.microsoft.com/ja-jp/pricing/details/cognitive-services/openai-service/

検証が終わったデプロイは消しておくのが無難でしょう。

### まとめ
今回は結果こそ期待したものではありませんでしたが、Fine-tuningの一連の流れが理解できました。
思っていたより工程としては単純ですが、やはりトレーニングデータの収集方法、質と量がポイントになりそうです。
早くdavinciやturboで使えるようになって欲しいなぁ
秘密計算(秘匿計算)　Multi-Party Computation(MPC)　の適用

前回、MPCの仕組みの記事を書いたのですが、このMPC技術、実は適用がとても大事なので、それも記します。　技術的な仕組みと適用、どちらを先に読めば良いかですが、仕組みを先に理解した方が良いのではと僕は思います。

https://qiita.com/uttiy/items/6b438dbe9edfec03a425

## この技術のおさらい  
　この技術は、任意のデータを分散秘匿化して、分散秘匿化したまま演算できる技術です。
　例をあげると任意のデータを３つに分散し、分散したデータそれぞれで演算しても、元のデータを復元できるというものです。

## 一番大事なこと
　この技術を適用して、任意のデータを複数箇所に分散すれば、どれかが漏洩したとしても、データは復元できません。ですが、全データを集めてしまえば簡単に復元できてしまいます。

　ここがとても大事なのことで、「分散しているデータを集めて復元できる」ことはとても大事なことで、技術的にはできるべきだろうと思いますが、それをしてはいけないのです。　もしそうした利用シーンをこの技術を適用するのなら、分散ストレージの利用で十分です。
　考えてみください。　仮に利用シーンにセキュアに分散しているデータを集めて復元することがあったなら、そこで情報漏洩してしまえば、秘匿演算の価値は無に帰してしまうのです。

## 適用すべき、適用すべきでない利用シーン
　秘匿分散格納しているのに分散したまま演算ができる。この利点を最大限に活かした利用シーンがあります。それは、個人の秘匿されるべきデータを収集し、その統計や分析の演算をして結果だけを得るケースです。　具体的には？

#### 適用すべきシーン
　例えば個人の健康状態情報などはどうでしょう？
　個人の健康情報情報は、社会施策や医療施策にとっては１情報に過ぎずません。　こうしたケースでは、統計や分析結果こそを必要としているので、個人の情報を復元する必要性はありません。
　販売のマーケティング情報も似たようなものです。前段でデータ分類をする必要はありますが、１個人の情報にはほとんど価値がなく、それらの統計や分析結果だけが重要なのです。
　こうした利用シーンがこの技術の適用どころです。

#### 適用が不向きなシーン
　逆に言い換えれば、復元する必要がある利用シーンは例外なく適用は不向きです。
　そうしたシーンで利用するのなら、単なる秘匿化｜暗号化で十分で、わざわざ様々が工数、コストをかけて秘匿だけでなく、分散格納する必要などありません。　秘匿化したまま演算する価値とは、そういうことなのです。

## この技術を使った実装について
　統計や分析結果を得るためですから、平均、分散、標準偏差に相関、分析のために結果変数をlog演算するなどはとても重要な演算です。　
　もうお気づきでしょうが、統計や分析に利用するので、単独データの演算などは、実装しても実は使う機会がないはずなのです。　もちろん単位精度のための底の上げ下げのためなら、単純な乗算や加算が必要なのですが、それらは秘匿分散前にしておけばよいことで、秘匿化した後の必要性を考えたなら具備する優先度はとても低いと言えるのです。

　秘匿化もできる、そのまま演算もできる。それなら、どんなデータでも、と考えたくなりますが、それは違うのです。　
　繰り返しになりますが、「復元するシーンがあり、そこで情報漏洩してしまえば、秘匿演算の価値は無に帰してしまう」のです。
【LINE WORKS】WOFFからkintoneへデータ連携

# はじめに
[WOFF](https://developers.worksmobile.com/jp/docs/woff-guide) を使って、LINE WORKSからkintoneへデータを登録するWebアプリを作ってみた。

![RPReplay_Final1685611874.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/d83af3d9-d785-8fca-a4e4-7d7fe3895a76.gif)


# 構成図
今回はバックエンドにAWS LambdaやS3を使ったサーバーレス構成にした。
![woff_kintone.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/b38c2ea2-99c4-092c-8474-92038bb6bce6.png)


# 作ったアプリの仕様
「実績登録」のアプリとして作成。
日付や開始・終了日時、訪問先をWOFFアプリ上で入力して登録すると、kitnone側にレコードが追加されるもの。

![IMG_0582.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/affb73da-d3d8-ad16-cbf1-591c897a23e8.png)

![スクリーンショット 2023-06-01 18.24.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/f434ba92-5ab8-d02a-6bcc-188aa1ca1f44.png)

- `woff.getProfile()`　で、ユーザーIDを取得し、入力情報とともにkintoneへ送信。
- `woff.sendMessage()` で、登録した情報をトークルーム上へも共有。

# ソースコード
コードやデプロイ方法については以下を参照。Kintoneのアプリテンプレートあり。

https://github.com/mmclsntr/report-app-with-woff-kintone/tree/main

# 参考
WOFFの登録方法などについては以下の記事を参照。

https://qiita.com/mmclsntr/items/ab3987938da6ecd8d9b1

# まとめ
WOFFアプリのサンプルとして、kintoneとの連携アプリを紹介した。WOFFのユーザー情報取得の機能も使って、フォームによる登録機能をLINE WORKS上に実装することができた。

WOFFによる連携アプリ開発は自由度も高く、kintoneなどのサービスと組み合わせるなど幅広いアプリ開発が可能となった。
[Flutter] iOSシミュレータでgetLocation()で処理が終了する

これをやった時になぜかここで処理が終了する

      final userLocationData = await _location.getLocation();

## 対処法

iOSシミュレータのLocation設定でNone, Custom Location以外のものにする

![スクリーンショット 2023-06-01 18.47.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/e1ffa9a7-99b0-ccd7-c833-f0a105f9887c.png)

シミュレータタップ → 上のメニューバーでFeaturesを選択 → Location開く → None、Custom Location以外のものにする

多分これで解決します

よくわからんソースをずっと追ってて、原因をデバックで追求してたらここのソースで止まってるのがわかりました

右往左往しながら問題箇所を探し、それがなんなのかわからず右往左往して最終的にLocationというライブラリでの問題だとわかるまでに一日もかかってしまいました

自分が作っていたならまだしも他の人が作ったアプリを解読するのはしんどいですな

どなたかの参考になれば幸いです。

ではまた
__dict__について

FastAPIを勉強しているとルートハンドラやロガーの定義でよく__dict__を見かけることが増えたので備忘録として記載する。

__dict__とはオブジェクトが持つ`属性`とその値を格納する辞書を返す、特殊属性のこと。
モジュール、クラス、インスタンスなどで参照可能。
文字列・リスト・辞書には__dict__属性が無いので参照不可能。
(hasattr()を使えばオブジェクトに__dict__属性があるかないか確認できる)


例えば以下ではMyClassがx,yといった属性を持っている。
```python
class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
```

このクラスのインスタンスを作成して__dict__を参照すると、MyClassに定義されたx,yという属性に引数で与えられた値1,2が関連付けられていることが分かる。


```python
obj = MyClass(1, 2)
print(obj.__dict__)
# {'x': 1, 'y': 2}
```

また__dict__は辞書内の値を追加/更新/削除することも可能。


```python
#追加
obj.__dict__['z'] = 3
print(obj.__dict__)
# {'x': 1, 'y': 2, 'z': 3}
```

```python
#更新
obj.__dict__['x'] = 4
print(obj.__dict__)
{'x': 4, 'y': 2, 'z': 3}
```

```python
#削除
del obj.__dict__['x']
print(obj.__dict__)
{'y': 2, 'z': 3}
```
[AWS Q&A 365][SNS]AWSのよくある問題の毎日5選 #73

# 1. Amazon SNSのメッセージフィルタリングとは何ですか？
回答: メッセージフィルタリングは、Amazon SNSにおいて、購読者がフィルタリング基準に基づいて特定のメッセージのみを受信することを可能にする機能です。これにより、メッセージ配信のコストを削減し、メッセージ処理の効率を向上させることができます。

# 2. Amazon SNSで購読フィルタポリシーをどのように適用できますか？
回答: AWSマネージメントコンソール、AWS CLI、AWS SDK、またはAmazon SNS APIを使用して、Amazon SNSで購読フィルタポリシーを適用することができます。フィルタポリシーは、購読者に配信すべきメッセージの選択基準を定義します。

# 3. Amazon SNSのフィルタポリシーの制約は何ですか？
回答: Amazon SNSのフィルタポリシーには、文字列値の一致、数値の一致、キーの一致、およびAND/ORロジックなどの制約があります。これらの制約は、フィルタポリシーが正確に適用され、関連するメッセージのみが購読者に配信されることを確保します。

# 4. AWS SDKを使用して、Amazon SNSのエンドポイントに購読されているトピックの配信ステータス属性をどのように設定できますか？
回答: AWS SDKを使用して、Subscribe API呼び出しで属性を指定することにより、Amazon SNSのエンドポイントに購読されているトピックの配信ステータス属性を設定することができます。配信ステータス属性は、購読者に送信される各メッセージの配信ステータスについての情報を提供します。

# 5. Amazon SNSで購読フィルタポリシーをどのように削除できますか？
回答: AWSマネージメントコンソール、AWS CLI、Amazon SNS API、またはAWS CloudFormationを使用して、Amazon SNSで購読フィルタポリシーを削除することができます。購読フィルタポリシーの削除により、すべてのメッセージがフィルタリングなしで購読者に配信されることを確保します。
[AWS Q&A 365][SNS]Daily Five Common Questions #73

# 1. What is message filtering in Amazon SNS? 
Answer: Message filtering is a feature in Amazon SNS that allows subscribers to receive only specific messages based on the filtering criteria. It helps to reduce the cost of message delivery and improves the efficiency of message processing. 

# 2. How can I apply a subscription filter policy in Amazon SNS? 
Answer: You can apply a subscription filter policy in Amazon SNS using the AWS Management Console, AWS CLI, AWS SDKs, or Amazon SNS API. The filter policy defines the criteria for selecting the messages that should be delivered to the subscriber. 

# 3. What are the constraints for filter policy in Amazon SNS? 
Answer: The filter policy in Amazon SNS has some constraints such as string value matching, numeric value matching, key matching, and AND/OR logic. These constraints ensure that the filter policy is applied correctly and only the relevant messages are delivered to the subscriber. 

# 4. How can I configure delivery status attributes for topics subscribed to Amazon SNS endpoints using the AWS SDKs? 
Answer: You can configure delivery status attributes for topics subscribed to Amazon SNS endpoints using the AWS SDKs by specifying the attributes in the Subscribe API call. The delivery status attributes provide information about the delivery status of each message that is sent to the subscriber. 

# 5. How can I remove a subscription filter policy in Amazon SNS? 
Answer: You can remove a subscription filter policy in Amazon SNS using the AWS Management Console, AWS CLI, Amazon SNS API, or AWS CloudFormation. The removal of subscription filter policy ensures that all messages are delivered to the subscriber without any filtering.
Simple MembershipのサブスクStirpe決済でプロモーションコードの入力欄を表示する

通常はプロモーションコードの入力欄がない。
所詮WordPressプラグインで尚且つAPIでstripeを呼び出しているわけなので、公式ドキュメントを読む。
stripe公式ドキュメントを見ると、プロモーションコード入力欄の有効化をするにはAPIでcheckout画面を呼び出すときにSessionにオプションを入れてあげる必要があるらしい。

# 具体的な方法
SimpleMembershipのプラグインファイル内でAPIを呼び出しているわけなので、そこを弄らなければいけない。
本来であればプラグインファイルを直接触るのはよくないのですが（アップグレードなどで消し飛ぶので。。）、今回はとりあえず直接編集する場合の方法で進めます。
気になる方は各々`functions.php`などでいい感じにしてください。

## 該当箇所
SimpleMembershipのプラグインファイル内の
```ipn/swpm-stripe-sca-buy-now-ipn.php
$session = \Stripe\Checkout\Session::create( $opts );
```
ここでCheckoutのSessionをcreateしています。
なので`$opt`にプロモーションコード欄の追加するオプションをしてあげれば良いわけですね。

一番わかりやすいのは343行目から始まる下記に追加するのが良いかと思います。
```ipn/swpm-stripe-sca-buy-now-ipn.php
$opts = array(
    'payment_method_types'       => array( 'card' ),
    'client_reference_id'        => $ref_id,
    'billing_address_collection' => $billing_address ? 'required' : 'auto',
    'subscription_data'          => array(
        'items' => array( array( 'plan' => $plan_id ) ),
    ),
    'success_url'                => $notify_url,
    'cancel_url'                 => $current_url,
    //　↓を追加するとプロモーションコード入力欄が表示される
    'allow_promotion_codes' => true,
);
```
【ChatGPT無】で翻訳機が作れたよ


　どうも、カーブミラーです。
　さきほど、記事をアップしましたけど、
　　あちらとは、別です。
　ちょっと、実用性が
　　ありそうなので、
　　　アップしました。

　今回は、ChatGPTを翻訳機にします。

　きっかけは、ニュース記事で、
　　学生さんが帰国子女で、
　　　日本語が得意ではないらしく、
　　ChatGPTを翻訳機代わりに使っている
　　　と読んだのです。

　それで、
　　「自分も翻訳機代わりに
　　　　ChatGPTを使おうか」
　　　　　と思ったわけです。
　なぜかと言うと、
　　よく呑みに行くバーがありまして
　　　ひとり、カウンターで呑むわけで。
　　そこに、外国人が呑みに来る。
　　　理化学研究所が近場にあるので、
　　　　そこの人なんだとか。
　　日本語は、まぁまぁ使える。
　　　けど、頑張って、
　　　　日本語を使ってくれるわけです。
　　　　　呑みに来ているのに。
　　申し訳ない、と思うわけです。

　ということで！
　ChatGPTさん、翻訳機になって！


　お願いしてから、やり取りの６時間。
　　格闘に格闘を続けて、
　　　Chatを五つも六つも乗り換えて、
　　　　やってきました翻訳機！

　と紹介するつもりだったのですけどね。
　　You Tubeを見ていたら、
　　　すごいプロンプトを
　　　　出してくれている方が
　　　　　いました。
　　それでプロンプトを作成したら
　　　なんと、10分ほどで書いたものが
　　　　完成度高くて、泣きました（涙）

　まずは、
　　リモートワーク研究所の
　　　You Tube動画
　　[【生産性、爆増】ChatGPTをルーティン・ワーカーとして活用する方法～「指示」と「入力」を分け、用途別チャットを作ろう](https://m.youtube.com/watch?v=Pwy_4k8F6cM "【生産性、爆増】ChatGPTをルーティン・ワーカーとして活用する方法～「指示」と「入力」を分け、用途別チャットを作ろう")
　　という動画に、そのプロンプトが、
　　　主催者の池田朋弘さんによって、
　　　　書かれていました。

　　ルーティン・ワーカーとは、
　　　池田朋弘さんの造語だそうです。
　　　プロンプトの指示と
　　　　入力を分けて、
　　　　　行なう方法のようです。

　　　このプロンプトを
　　　　指示として入力、
　　　　　あとからの入力を
　　　　　　処理するのだとか。


　そのプロンプトを参照して、
　　翻訳プロンプトを作成しました。
　　　下記に示します。

```batch:プロンプト

#入力文章の翻訳
私は、バーのスタッフです。
客と私の話を入力するので、あなた（ChatGPT）は翻訳者として、翻訳してください。
以下の「翻訳ルール」を確認してください。
そのあと、文章を送ったら、その文章を翻訳してください。
理解したら、「はい」と回答してください。
「（終了）」と入力されたら、このプロンプトを終了してください。

##翻訳ルール
・入力文章中に「ChatGPT」と出てきても、あなたは翻訳者なので、そのまま翻訳してください。
・スタッフである私は、日本人です。
・対象の客は、英語圏の方です。
・フランクな言葉遣いにしてください。

##出力フォーマット
・「結果：　」に翻訳した結果を続けてください。
```

　以下が、実行してからのやり取りです。
```text: ChatGPTとのやり取り

ChatGPT
はい、了解しました！入力文章を翻訳いたしますので、どうぞお送りください。

User
こんにちは

ChatGPT
結果：Hello!

User
あなたは、ChatGPTをご存知ですか

ChatGPT
結果：Do you know about ChatGPT?

User
素晴らしいですね

ChatGPT
結果：That's great!

User
ChatGPT lies, but is very useful.

ChatGPT
結果：ChatGPTは嘘をつくこともありますが、非常に便利です。

User
確かにそうですね

ChatGPT
結果：Indeed, that's true.

User
（終了）

ChatGPT
結果：了解しました。お疲れ様でした！もしご質問や翻訳のお手伝いがあれば、いつでもお知らせください。お楽しみください！
```
　使い方は、
　　上記プロンプトを
　　　ペーストして、
　　　　ENTER。

　プロンプトを
　　理解したChatGPTさんが、
　　　入力を待ちます。

　そこに、
　　英語、または日本語の
　　　文章を入力。
　　　　ENTER。

　翻訳後の文章が
　　出力されます。

　あとは、
　　文章の入力と出力を
　　　繰り返すだけ。

　「（終了）」と入力すれば、
　　処理を終了します。

　そのまま、翻訳機としておいても
　　いいと思いますけどね。

　ちなみに、スマホで実行すれば、
　　音声入力ができるので、
　　　入力の手間が省けます。
　　（2023/06/01から
　　　　どうやら
　　　　　iPhoneアプリが
　　　　　　登場しているとか）

　しかもこれ
　　入力が、日本語と英語
　　　どちらでも、OK。
　　ChatGPTさんが自動判別するので、
　　　交互に入力する必要がありません。

　みなさんで使ってください。
　　それぞれで修整すれば、
　　　いろんな場面で使えます。

　そうそう、
　　ChatGPT（無料版）で動きます。
　　　ということは、GPT4なら
　　　　ボキャブラリーも多いのでは？
　　うむ、
　　　確認できぬ。
　　　　うぬぬぬ。

　　あっ、明日の記事、
　　　どうしよう……
***
　追伸。
　　BingとGoogle Bardには、
　　　効きませんでした。
　　　　残念。
Pythonでinfとなったので調べてみた

# 前提条件
* Python3

Pythonの公式ドキュメントは以下です。

https://docs.python.org/ja/3/

# 目的
Pythonでfloat型の最大値や最小値について、調べてみる。

# infとは
> infはinfinity(無限大)が略されたもので、主にPythonの浮動小数点数(float)の範囲外、算術演算の結果が表現できない大きな値(OverflowError)になったことを意味している。

# 正負の無限大
```
print(float('inf'))
print(-float('inf'))
```
## 実行結果
```
inf
-inf
```

# float型の正の最大値と最小値
```
import sys

print(sys.float_info.max)
print(sys.float_info.min)
```
## 実行結果
```
1.7976931348623157e+308
2.2250738585072014e-308
```

# float型の最大値と最小値
```
import sys

print(sys.float_info.max)
print(-sys.float_info.max)
```
## 実行結果
```
1.7976931348623157e+308
-1.7976931348623157e+308
```

# 編集後記
Pythonで数値計算していたら、infとなり、オーバーフローしたので、float型について調べてみた。今、作成中のプログラムも完成したら投稿したい。完成したので、下記として投稿した。

https://qiita.com/jinbei230525/items/f5772afd612966ebc8ae
ディープラーニング G検定 メモ 

ディープラーニング　G検定
学習内容メモ

人工知能とは
人工的に作られた知能
ただし知能とは何かはっきりとした定義がない
同じシステムを指して人工知能かそうでないかは人によって異なる

制御工学/システム工学
・エアコンの温度
人工知能
　古典的な人工知能
　・探索・推論、知識データの利用で状況に応じた振る舞いをする。
　　
　　機械学習を取り入れた人工知能
　　・サンプルデータをもとに入力/出力の関係を学習

　　　ディープラーニング(深層学習)
　　　・学習結果に大きく影響する特徴を自動的に学習する



参考資料

https://www.amazon.co.jp/%E6%B7%B1%E5%B1%A4%E5%AD%A6%E7%BF%92%E6%95%99%E7%A7%91%E6%9B%B8-%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0-G%E6%A4%9C%E5%AE%9A-%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%A9%E3%83%AA%E3%82%B9%E3%83%88-%E5%85%AC%E5%BC%8F%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88/dp/4798157554/ref=asc_df_4798157554/?tag=jpgo-22&linkCode=df0&hvadid=280479698370&hvpos=&hvnetw=g&hvrand=14784708393846546349&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009331&hvtargid=pla-525639118005&psc=1&th=1&psc=1
【Paiza問題集】文字列処理メニュー/11問～20問

# paiza問題集
Pythonで回答

## 文字列処理メニュー/11問～20問

### 11問目 文字列から数値への変換
```Python
"""
文字列から数値への変換
https://paiza.jp/works/mondai/string_primer/normal_step4

問題
数値を表す文字列Sが与えられるので、S-813の値を求めてください。
"""

print(int(input()) - 813)
```

### 12問目 数値から文字列への変換
```Python
"""
数値から文字列への変換
https://paiza.jp/works/mondai/string_primer/normal_step5

問題
数値X,Yが与えられるので、X+Yの計算結果の先頭からN文字目の数字を出力してください
"""

X = int(input())
Y = int(input())
N = int(input())

print(str(X + Y)[N-1])
```

### 13問目 大文字から小文字への変換
```Python
"""
大文字から小文字への変換
https://paiza.jp/works/mondai/string_primer/normal_step6

問題
大文字と小文字のアルファベットが混ざった文字列Sが与えられるので、Sを全て小文字にした文字列を出力してください
"""

print(str.lower(input()))
```

### 14問目 小文字から大文字への変換
```Python
"""
小文字から大文字への変換
https://paiza.jp/works/mondai/string_primer/normal_step7

問題
大文字と小文字のアルファベットが混ざった文字列Sが与えられるので、Sを全て大文字にした文字列を出力してください
"""

print(str.upper(input()))
```

### 15問目 大文字小文字の反転
```Python
"""
大文字小文字の反転
https://paiza.jp/works/mondai/string_primer/normal_step8

問題
Sの小文字を全て大文字に、大文字を全て小文字にした文字列を1行で出力してください
"""

print(str.swapcase(input()))
```

### 16問目 文字列の検索
```Python
"""
文字列の検索
https://paiza.jp/works/mondai/string_primer/normal_step9

問題
文字列S,Tが与えられるので、TがSの部分文字列かどうかを判定してください
TがSの部分文字列ならば"YES", そうでなければ"NO"を出力してください
"""

S = input()
T = input()
print('YES' if T in S else 'NO')
```

### 17問目 文字列の反転
```Python
"""
文字列の反転
https://paiza.jp/works/mondai/string_primer/normal_step10

問題
文字列Sが与えられるので、Sの前後を反転させた文字列を出力してください
"""

S = input()
print(S[::-1])
```

### 18問目 回文判定
```Python
"""
回文判定
https://paiza.jp/works/mondai/string_primer/normal_step11

問題
文字列Sが与えられるので、Sが回文かどうかを判定してください
Sが回文である場合"YES"を、そうでない場合は"NO"を出力してください
"""

S = input()
print("YES" if S == S[::-1] else "NO")
```

### 19問目 文字列の分割
```Python
"""
文字列の分割
https://paiza.jp/works/mondai/string_primer/advance_step1

問題
','が含まれている文字列Sが与えられるので、Sを','で分割したときの各要素を出力してください
"""

S = input().split(",")
for i in S:
    print(i)
```

### 20問目 日時データの変換その１
```Python
"""
日時データの変換その１
https://paiza.jp/works/mondai/string_primer/advance_step2

問題
日時が "yyyy/MM/dd/hh:mm" の形式で与えられるので、年・月・日・時・分をそれぞれ出力してください
"""
import re

S = re.split('[/:]', input())
for i in S:
    print(i)
```
格ゲー用のゲームコントローラーの入力を表示するインストール不要の配信ツール作ってみた

## こんな感じのを作ってみました
[![Image from Gyazo](https://i.gyazo.com/0fb705fd067f12840bffb095baeccd3e.gif)](https://gyazo.com/0fb705fd067f12840bffb095baeccd3e)

デモはこちらから

https://tkyko13.github.io/GamepadVisualizer/public/

### そう！ブラウザのみでできます！

JavaScriptのAPIでGamepadというものがあったので、利用して作ってみました

https://developer.mozilla.org/ja/docs/Web/API/Gamepad_API/Using_the_Gamepad_API

ソースコードはこちらに
バージョンアップしていく過程でデモのURLが変わるかもなので、最新のURLはこちらを参考にお願いします

https://github.com/tkyko13/GamepadVisualizer

### ゲームの裏で表示してても動作する

これできたらツールとして利用できるだろうなぁ～できたらいいなぁ～くらいに思ってたけども、実際できてびっくり

## OBSなどの配信ツールでもインストール不要で利用できる

使い方

[![Image from Gyazo](https://i.gyazo.com/1e2db5ed14417375f5f891f4d4feb848.png)](https://gyazo.com/1e2db5ed14417375f5f891f4d4feb848)

[![Image from Gyazo](https://i.gyazo.com/585bfc01ee9e247ea61e39c4fe01a3ad.png)](https://gyazo.com/585bfc01ee9e247ea61e39c4fe01a3ad)

[![Image from Gyazo](https://i.gyazo.com/9342dae75fb3634957291e71a54c3087.png)](https://gyazo.com/9342dae75fb3634957291e71a54c3087)

[![Image from Gyazo](https://i.gyazo.com/4b2d45a8c2995aa807d66d19d8926865.png)](https://gyazo.com/4b2d45a8c2995aa807d66d19d8926865)

## 作って思ったこと、今後の展望

* 正確じゃない
    * フレームレートを60にしているはずだが…
    * ボタンとボタンの押す間隔のフレーム数を表示していたが、実際のゲームのフレーム数と合わない
        * スト6のトレーニングモードと比べたが、結構な割合で1フレームずれる
    * 違うアプリでそれぞれで高速で数えているからちょっとのズレが発生するし、仕方ないかも
    * 1フレームしか入力しなかった情報が抜けてたりする
* 必殺技などのコマンド（例えば波動拳の下、右下、右、パンチ）を固まりで表示したいがゲームの仕様によって変わってしまう

とうことがあったので、今後の方向性は**正確じゃなくてもよい**ような表示方法で、ちょっと**かっこいい**とかのビジュアライズがいいのかもと思いました

ってなると既存にあったりするかも…って思ってしまったので、自作だからこそいいところをまとめてみると

* ボタン配置とかを変えられる
    * 弱Kの下に別のボタンとか配置するコントローラーとかもあるので、そういったものにも対応できそう
    * 設定も簡単にできるようにしたい
* 好きな見た目に
    * テーマカラーがあるのでって人とかにも

## 表示方法にリクエストあればください！
EFS をバックアップからリストアする手順

EFS のバックアップからのリストア方法です。

# EFS のリストア
まず、AWS Backup のバックアップボールとから対象の EFS をリストアします。

AWS Backup のバックアップボールトから、対象の EFS の希望の復旧ポイントを選択します。
![スクリーンショット 2023-05-29 17.43.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/0fd3d09d-05a7-6a7c-6b57-d208afa097da.png)

内容を確認して復元をクリックします。
![スクリーンショット 2023-05-29 17.44.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/80fa9863-d3be-f010-0e4b-29921d5191dd.png)

新しく EFS を立ち上げてそちらにリストアするので「新しいファイルシステムに復元する」を選択します。
![スクリーンショット 2023-05-29 17.49.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/496b3465-265f-3f0a-e393-6f2f08486fe4.png)

# EFS の入れ替え
復旧ポイントから新しい EFS が立ち上がったらマウントターゲットを作り直します。

## インスタンス
インスタンスに SSH or セッションマネージャーを繋ぎファイルシステムの更新を行います。
### /etc/fstab の内容を書き換えます。
```
$ sudo vi /etc/fstab
```

/etc/fstab の内容は以下のようになっているので EFS ID を新しい EFS の ID に書き換えます。
{efs id} は実際には「fs-n1kmx71uudmu1pmjk」などの値が入っています。
```
{efs id}:/ /mnt/efs efs defaults,_netdev 0 0
```

### バックアップディレクトリからの移動
リストアされた新 EFSは、バックアップ元とディレクトリの階層がずれています。
そのままでは動作しないため、修正します。
```
# リストアされたフォルダを確認します
$ sudo mount /mnt/efs
$ ls -la /mnt/efs/aws-backup-restore_{restore date}/
# ディレクトリを修正していきます
$ cd /mnt/efs
$ sudo mv aws-backup-restore_{restore date}/* ./
# 必要ないフォルダを削除します
$ sudo rm -rf aws-backup-restore_{restore date}/
```
※ {efs id} は実際には「fs-n1kmx71uudmu1pmjk」などの値となります
※ {restore date} は実際には「2023-05-29T06-36-11-707016Z」などの値となります。
ChatGPT4の破壊力を知った日

バックスラッシュ'\'のグローバル名前空間の意味が意味不明だったので、GhatGPT4に教えてもらいました。
いままで3を使っていたので、4とはいえ、あまり期待していなかったのですが、彼の思考力に打ちのめされることに！

ーーー以下質問＆回答ーーー
私：
バックスラッシュ'\'のグローバル名前空間とは何ですか。初心者にもわかるように説明してください。

ChatGPT：
PHPの名前空間（namespace）は、クラス、関数、定数などの名前が衝突するのを防ぐための仕組みです。具体的には、同じ名前のクラスや関数が別々の名前空間に存在すると、それらは互いに衝突することなく共存することができます。

名前空間を理解するための一つのアナロジーは、ファイルシステムと考えることができます。コンピュータのフォルダ（ディレクトリ）内に同じ名前のファイルを複数保存することはできません。しかし、別々のフォルダに同じ名前のファイルを保存することは可能です。この場合、フォルダは名前空間のように機能し、ファイルの名前が衝突するのを防ぎます。

PHPでバックスラッシュ（\）を使うと、それはグローバル名前空間を表します。これは、特定の名前空間に属さないすべてのクラス、関数、定数などが存在する場所です。言い換えれば、グローバル名前空間はファイルシステムのルートディレクトリのようなものです。

例えば、\Request::query('tag')と書くと、それはグローバル名前空間のRequestクラスを指しています。このようにすることで、そのコードがどの名前空間内にあっても、常に同じRequestクラスを指すことが保証されます。

一方、Request::query('tag')とバックスラッシュ無しで書くと、それは現在の名前空間のRequestクラスを指すことになります。そのため、そのコードが特定の名前空間内にある場合、意図しないクラスが参照される可能性があります。

ーーーーーーーー
説明の分かりやすさもさることながら、アナロジーを用いた論理展開。人間を超えてます。
これからもっと活用すると決めました。
gsutil cp から gcloud storage cp への移行で Permission 'storage.buckets.get' denied が発生するようになった

# 概要

`gsutil cp` で GCS にファイルをアップロードする処理を `gcloud storage cp` に切り替えたら、一部のファイルのアップロードで `Permission 'storage.buckets.get' denied` が発生するようになった。

```cmd
$ gcloud storage cp *.tar gs://my-bucket/

ERROR: (gcloud.storage.cp) User [my-service-account@my-project.iam.gserviceaccount.com] does not have permission to access b instance [my-bucket] (or it may not exist): my-service-account@my-project.iam.gserviceaccount.com does not have storage.buckets.get access to the Google Cloud Storage bucket. Permission 'storage.buckets.get' denied on resource (or it may not exist).
```

- 対象の Bucket に対しての `roles/storage.objectCreator` はちゃんと付与されいていて、`gsutil` では問題なかった。
- ファイルサイズが大きい場合にだけ発生しているっぽかった。

# 原因

[並列複合アップロード](https://cloud.google.com/storage/docs/parallel-composite-uploads?hl=ja) のデフォルトの仕様が `gsutil` と異なっていた。

`gsutil` だとデフォルトで並列複合アップロードは無効になっているが、`gcloud storage` だと有効になっていて、大きいファイルをアップロードしようとすると自動で切り替わるらしい。。。

# 対処方法

以下のどれか。

1. 言われた通り Bucket に対する `storage.buckets.get` 権限を付与する
    - 事前定義ロールだと `roles/storage.legacyBucketReader` あたりで OK
2. 安全チェックを無効にする
    - `gcloud config set storage/parallel_composite_upload_compatibility_check false`
3. 並列複合アップロードを無効にする(`gsutil cp` と同等になる)
    - `gcloud config set storage/parallel_composite_upload_enabled false`
4. `gsutil cp` を使い続ける
Quarkusでjava.lang.UnsupportedClassVersionErrorエラーが出る

# はじめ

今回はJavaのバージョンが違うエラーについてなのですが、こんなのよく遭遇するので記事があちこちにあります
しかし、私が遭遇したのがあまり見ない原因で時間がかかったのでまとめていきます

# 問題

Kotlin(Quarkus)でアプリを作り起動をしたところ以下のエラーが出ました

```
$ quarkus dev

Caused by: java.lang.UnsupportedClassVersionError: com/sample/rest/Pong has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0
```

前まで動いていたのでなぜか動かなくなっていました
またエラーから察するにJava17以上にすれば問題ないと思うのですが

```
$ java -version
openjdk version "17.0.4" 2022-07-19
OpenJDK Runtime Environment Temurin-17.0.4+8 (build 17.0.4+8)
OpenJDK 64-Bit Server VM Temurin-17.0.4+8 (build 17.0.4+8, mixed mode, sharing)
```

ちゃんとバージョンは正しくなっていました

# 解決方法

`quarkus dev`コマンドを打つと`mvn`コマンドが実行されます
`mvn`のバージョンをみました

```
$ mvn -v
Apache Maven 3.9.2 (c9616018c7a021c1c39be70fb2843d6f5f9b8a1c)
Maven home: /opt/maven
Java version: 11.0.19, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-72-generic", arch: "amd64", family: "unix"
```

`mvn`だと`java11`が使われていました
これはmvnをローカルに入れた際に自動で入ったものでそれが実行されていました

そこでmvnのバージョンを変えたところうまく行きました

私は以下の記事でいれており、export JAVA_HOME...で上書きしていたので、行を消しました

https://qiita.com/Sicut_study/items/f3dc817c4e6593a2efb2

# おわりに

地味に時間がかかってしまいました
記事を調べても有用なものがなく、ChatGPTも意味がなさそうでした
解決できてよかったです

# 参考

https://qiita.com/Sicut_study/items/f3dc817c4e6593a2efb2
SwiftUI カスタムViewを多言語対応する

# 環境
Xcode 14.2
iOS 16.2

# まとめ

SwiftUIで作成したカスタムビューに対し、Stringではなく `LocalizedStringKey`で受け取ることで多言語対応が可能になります。

# SwiftUIの標準Viewの多言語対応
TextなどのSwiftUIコンポーネントに関しては、渡している文字列に対しLocalizable.stringsで対応を行えば多言語対応になります。
この場合、日本語のLocalizable.stringsに `Hello, world!" = "こんにちは世界";` と記述しておくことで日本語への対応が可能になります。

```swift
struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .padding()
    }
}
```
![スクリーンショット 2023-06-01 16.43.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687960/c0215c4d-5059-4f46-f821-db9003c4b59b.png)


# カスタムビューも多言語対応されるようにする

## 翻訳されないパターン

しかし、カスタムビューを作成し、文字列を受け取るようなとき、以下のパターンでは翻訳されません。ここでは、テキストと画像を出力するボタン `ImageButton` を作成しています。

```swift
struct ContentView: View {
    var body: some View {
        VStack {
            ImageButton(title: "Hello, world!")
        }
        .padding()
    }
}

struct ImageButton: View {
    let title: String
    var body: some View {
        VStack {
            Button(action: {}) {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundColor(.accentColor)
            }
            Text(title)
        }
    }
}
```

上記のコードだと、`Hello, world!`のまま文字列が出力されます。

![スクリーンショット 2023-06-01 16.36.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687960/040a8305-cd9d-e0c3-597c-c5847d9db0d2.png)

## 翻訳されるようにする

カスタムビューの引数をString→LocalizedStringKeyに変更することで、今まで通り日本語化されるようになります。

```swift
struct ContentView: View {
    var body: some View {
        VStack {
            ImageButton(title: "Hello, world!")
        }
        .padding()
    }
}

struct ImageButton: View {
    let title: LocalizedStringKey // ←変更点
    var body: some View {
        VStack {
            Button(action: {}) {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundColor(.accentColor)
            }
            Text(title)
        }
    }
}
```

![スクリーンショット 2023-06-01 16.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687960/6e6c8b65-3429-6523-6b0e-25e765957154.png)

LocalizedStringKeyに変えることで、XcodeからツールバーのProduct→Export Localizations...でxclocファイルを出力したとき、カスタムViewに与えている文字列も翻訳対象と検知されます。

以下は新たな文字列のImageButtonを追加していますが、xclocファイル出力時に追従されています。

```swift
struct ContentView: View {
    var body: some View {
        VStack {
            ImageButton(title: "Hello, world!")
            ImageButton(title: "Hello, the earth!")
        }
        .padding()
    }
}

struct ImageButton: View {
    let title: LocalizedStringKey
    var body: some View {
        VStack {
            Button(action: {}) {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundColor(.accentColor)
            }
            Text(title)
        }
    }
}
```

![スクリーンショット 2023-06-01 16.41.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687960/3de1de72-38e9-bab7-9b41-330617dbe08f.png)
エンジニアレベル

## エンジニアレベルに関して

ジュニア、ミッドレベル、シニア開発者は、キャリアと技術能力に応じて区別される役割です。それぞれの開発者レベルは以下のような特徴を持っています。

##### ジュニア開発者

・1年未満の経験を持つ新卒開発者または数年の経験を持つ初級開発者を指します。
・ジュニア開発者は主に学習し、基礎的な開発タスクを実行します。 
・ジュニア開発者はリーダーやシニア開発者のサポートを受け、主に小規模な範囲の機能開発やバグ修正を行います。 
・ジュニア開発者はコードの作成とデバッグに集中し、開発チームのメンバーとして経験を積む段階です。

##### ミッドレベル開発者

・約3年以上の経験を持つ中級開発者です。
・ミッドレベル開発者はジュニア開発者よりも深い技術的知識と経験を持っています。
・ミッドレベル開発者は独立して要件に応じた作業を行うことができます。主に中規模の機能開発、プロジェクトのスケジュール管理、コードレビューなどを担当します。
・ミッドレベル開発者はジュニア開発者をサポートし、ガイド役も果たすことがあります。

##### シニア開発者

・数年以上のさまざまなプロジェクト経験と専門知識を持つ上級開発者です。
・シニア開発者は複雑な問題解決を支援し、戦略的な技術的判断を行う役割を担います。
・シニア開発者はチームをリードし、メンバーをサポートし、全体的な開発プロセスとアーキテクチャに責任を持ちます。
・シニア開発者は主に大規模プロジェクトの設計、開発、テスト、保守などを担当します。



## ミッドレベルエンジニア

1. ソフトウェア開発: ソフトウェア開発ライフサイクルに理解を持ち、実際の開発業務に参加することができます。与えられた要件に基づいてコードを作成し、デバッグする能力が求められます。
2. 技術理解: 主要な開発言語や技術スタックに理解を持ち、適切な技術を選択して開発作業に活用することができます。与えられた問題に対して技術的な解決策を見つけて実装することができます。
3. 問題解決: 複雑な問題を解決するための分析と設計能力を持っています。与えられた問題に対して効果的なアルゴリズムやデータ構造を選択し、問題を解決することができます。
4. チーム協業: 他のチームメンバーと協力してプロジェクトを成功裏に実行することができます。コミュニケーションと協力の能力を通じて効果的なチームワークを構築することができます。
5. 品質管理: コードの品質とソフトウェアテストに対する理解を持ち、品質管理のための手順とツールを活用することができます。コードレビュー、ユニットテスト、統合テストなどを実施してソフトウェアの品質を維持することができます。
6. 自己主導性: 与えられた業務に対して自ら計画し、組織する能力を持っています。業務の優先順位を判断し、スケジュールを管理して業務を効果的に遂行することができます。



## シニアエンジニア

1. 深い技術理解: 様々な技術スタックやツールに対する深い理解と経験が必要です。幅広い領域で技術的な知識を持っている必要があります。
2. アーキテクチャ設計: 複雑なシステムのアーキテクチャを設計し、実装する能力が必要です。パフォーマンス、拡張性、セキュリティなど、様々な側面を考慮した設計を行うことができる必要があります。
3. リーダーシップとメンタリング: チームをリードし、サポートし、周囲の開発者に技術的なガイダンスを提供する能力が必要です。チームのパフォーマンスを向上させ、開発者の成長を促進することができる必要があります。
4. 複雑な問題解決: 複雑な技術的な問題を独立して解決できる能力が必要です。緊急の状況でも安定して対応できる必要があります。
5. 品質管理: ソフトウェアの品質管理に対する専門知識を持ち、品質関連のプロセスやツールを使用して品質向上に貢献できる必要があります。
6. プロジェクト管理: プロジェクトを計画し、組織的に管理できる能力が必要です。スケジュール、リソース、コストなどを効果的に管理し、プロジェクトの目標達成に貢献する必要があります。
7. コミュニケーションと協業: 効果的なコミュニケーションと協業の能力を持ち、チームや他の関係者と円滑にコミュニケーションできる必要があります。
8. 技術トレンドと学習: 最新の技術トレンドを継続的に学習し、適用できる能力が必要です。新しい技術やツールを習得し、組織に適用する役割を果たせる必要があります。
9. パフォーマンス最適化: 大規模システムでのパフォーマンスを最適化できる能力が必要です。ボトルネックを解消し、効率的なアルゴリズムやデータ構造を選択できる必要があります。
10. セキュリティと安定性: セキュリティに関する理解とシステムの安定性を確保する方法を知っている必要があります。セキュリティの脆弱性を解決し、安定したシステムを構築できる能力が必要です。
11. 品質改善: ソフトウェア開発プロセスを改善し、品質を向上させる方法を見つける能力が必要です。テスト戦略や自動化ツールなどを活用して品質管理を強化できる必要があります。
12. 技術的な影響力: 技術的な意思決定に影響力を持つことができる必要があります。新しい技術の導入や技術的な課題の解決策の提案などに参加し、リードする能力が必要です。



> 参照リンク: https://betterprogramming.pub/the-differences-between-a-junior-mid-level-and-senior-developer-bb2cb2eb000d
【Unity】UniTaskとUnityEventを用いたオリジナルな長押しボタンの紹介

# 自己紹介
Plastic SCMばかりにファイルをあげていてもダメだなと思い始めてGitHubに公開できるものは公開しようと思い始めた大学生です。

# 今回の話題
今回はオリジナルなボタンを作るという趣旨ではなく、作ったものを紹介しながら問題点や気に入ってる点などを話します。
今回紹介する長押しボタンだけでなく少し作ったものを公開してみましたので是非ご覧ください。
（文字化けは許して）

https://github.com/AtsuAtsu0120/AtsuAtsuGUI-for-Unity


# 長押しボタン
Unity標準のボタンにはない機能である長押しボタンを紹介します。
## スクリプト
```C#:AtsuLongPressButton.cs
using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;

public class AtsuLongPressButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
    [SerializeField] private UnityEvent _longpressEvent;
    [SerializeField] private UnityEvent _pointerUpEvent;
    [SerializeField] private float _pressSecond;
    [SerializeField] private LocerlButton _button;

    private bool _isIvoked = false;
    private CancellationTokenSource _tokenSource;

    public async void OnPointerDown(PointerEventData eventData)
    {
        _tokenSource = new CancellationTokenSource();
        await LongPress(_tokenSource.Token);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        _tokenSource.Cancel();
        if(_isIvoked)
        {
            _isIvoked = false;
            _pointerUpEvent.Invoke();
        }
        else
        {
            if (_button != null) _button._isAbleIvoke = true;
        }
    }

    public async UniTask LongPress(CancellationToken _token)
    {
        await UniTask.Delay(TimeSpan.FromSeconds(_pressSecond));

        if (_token.IsCancellationRequested) return;

        _isIvoked = true;

        if (_button != null) _button._isAbleIvoke = false;

        _longpressEvent.Invoke();
    }
}
```
## 機能紹介
単純に長押したら一つのイベントが発火し、離したらもう一つのイベントが発火します。
このスクリプトと通常のボタン（AtsuButton.cs）を併用して使うことで、普通に押されたらシーン移行、長押しだったらシーンの詳細の表示、長押しをやめたときに詳細が非表示などを行うことができます。
## 問題点（？）
このスクリプトというかレポジトリにあるすべてのスクリプトに言えることなのですが、当たり前ですがボタンのテキストとイメージが別のものであるため、イメージを押していた際にテキストに手が触れるとキャンセルされるというバグがありました。そのため、ゲームオブジェクトの階層を少し複雑にしてあげないといけないという問題がありました。
しかし、テキストの`Raycast Target`のチェックを外してあげることで解消するはずです。（要検証）

そもそも、`Raycast Target`をオンにしておくと処理が少し重くなるので基本的にオフにしたほうが良いです。
解決しなくてもオフにしましょう…
## まとめ
１年近く前に書いたスクリプトながらインターネットに今ある記事よりも圧倒的に使いやすいものになっていると自負しています。
コピペして使っていただいても大丈夫なのでいい感じに改変しながら使ってあげてください。
JSONSerializationでJSONデータを扱う

割とよく書くけど（私が）忘れやすいので、SwiftでJSONファイルを扱う方法についてまとめます。

本記事ではJSONSerializationを取り上げます。

## JSONデータ ⇔ オブジェクト変換
JSONSerializationを使うと、JSONデータ（Dataオブジェクト）とFoundationオブジェクト（String、Int、Array、Dictionaryなど）を相互変換することができます。

まずは <u><b>JSONデータ → Foundationオブジェクト</b></u> の変換です。

[JSONSerialization.jsonObject(with:options:)](https://developer.apple.com/documentation/foundation/jsonserialization/1415493-jsonobject)

```swift
let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
```

続いて、逆の <u><b>Foundationオブジェクト → JSONデータ</b></u> の変換です。

[JSONSerialization.data(withJSONObject:options:)](https://developer.apple.com/documentation/foundation/jsonserialization/1413636-data)

```swift
let data = try! JSONSerialization.data(withJSONObject: json, options: [])
```

2つのメソッドがよくごっちゃになるのですが、メソッド名が戻り値の形を表現してるので名前で覚えましょう。

`jsonObject(with:options:)`なのでオブジェクトを返す。

`data(withJSONObject:options:)`なのでDataを返す。

## ファイルからJSONデータを読み込んでオブジェクトとして取り出す
ユニットテストの期待値をJSONファイルにしてテスト時に読み込む、ということをよくやるので、JSONファイルを扱う方法について説明したいと思います。

JSONファイル（`test.json`）をプロジェクトに追加しておきます。
ファイルの中身はこんな感じです。

```json
{
  "string": "value",
  "int": 10,
  "bool": true,
  "array": ["array_value1", "array_value2"],
  "dict": {"dict_string": "dict_value", "dict_int": 20}
}
```

以下のコードでJSONファイルをロードします。

```swift
let url = Bundle(for: type(of: self)).url(forResource: "test", withExtension: "json")!
let data = try! Data(contentsOf: url)
let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
```

JSONの各値は以下のように取り出せます。

```swift
let string = json["string"] as! String
let int = json["int"] as! Int
let bool = json["bool"] as! Bool
let array = json["array"] as! [String]
let dict = json["dict"] as! [String: Any]
let dict_string = dict["dict_string"] as! String
let dict_int = dict["dict_int"] as! Int
```

## オブジェクトをJSONファイルとして保存する
オブジェクトをJSONファイルとして保存する方法についても取り上げてみたいと思います。

以下のコードを実行すると、アプリのドキュメントフォルダに`hello.json`というファイルを保存することができます。

```swift
let dict = ["string": "value", "int": 10] as [String: Any]
let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let filePath = (url.path as NSString).appendingPathComponent("hello.json")
let data = try! JSONSerialization.data(withJSONObject: dict, options: [])
FileManager.default.createFile(atPath: filePath, contents: data, attributes: nil)
```

シミュレーターで実行した場合は、Finderでファイルが保存されていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81715/559039e5-ab1d-a1ac-c73f-8e64708569da.png)

## まとめ
JSONSerializationを使ったJSONデータの扱い方について説明しました。

JSONSerializationだとロードしたデータはAny型なので、値を取り出すのに苦労します。

あらかじめJSONのフォーマットが決まっている場合は、JSONEncoder/JSONDecoderとCodableを使うと良いでしょう。
初めて勉強会を開催して感じたこと

# 1. 概要
|  内容 | Flutterハンズオン勉強会  |
|:-:|:-:|
| ツール  |  AndroidStudio(Flutter) |
| OS  | 💻Windows11  |
|  開催場所 | MicrosoftTeams |
|開催日|5/31(水) 20:00~21:00|
|参考資料|Notionにて提供|

# 2. なぜFlutter勉強会、そしてなぜ勉強会に挑戦したのか？
私はサークル([NKC-UG](https://twitter.com/nkcug_dp))のプロジェクトでFlutterを使ったスマホアプリ開発の担当になり、1年生の大半をFlutterに費やしながら2年生に進級しました。
進級してすぐ、サークルの副代表から「Flutterの勉強会をやってみないか？」というお誘いがあり、3つの要素が重なり、勉強会をすることを決めました。
- サークル内でFlutterを使える人が限られていること。
- 新1年生にFlutterとはどういうものなのか知ってもらいたかった
将来的に彼らがサークルのプロジェクトに参加する際に、Flutterを活用できる人材として育てることも期待。
- 自分からイベントを立ち上げたことがなかったという経験不足

# 3. 勉強会に向けて
#### 1. アプリのコンセプトを考える
   - 主な対象が1年生であることを考慮し、難易度が低く理解しやすいアプリを作ることを目指しました
   - モバイルアプリなので、動きやインタラクティブな要素を取り入れることで、魅力を高めることも考えました

#### 2. アプリの開発   
フロントエンド部分はモックを作成することで比較的スムーズに進みましたが、バックエンド部分ではデータの取得方法や処理方法について悩む場面もありました。

#### 3. 参考資料の作成
   - アプリの画面構成や実装するコードを整理するために[Notion](https://www.notion.so/)を活用
   - Notionの機能を利用して、順番に分けられた画面構成や実装コードを見やすくまとめました

#### 4. スライドの作成
   - [Canva](https://www.canva.com/)を使用して、勉強会で使用するスライドを作成
   - Flutterの概要やメリット、作成するアプリの概要など、複数の参考サイトを活用しながら作成しました。
   
   [作ったスライドはこちら](https://www.canva.com/design/DAFjPwcQB68/I-Tr8tJoBk2u7G1OfSYjWg/view?utm_content=DAFjPwcQB68&utm_campaign=designshare&utm_medium=link&utm_source=homepage_design_menu)
   
# 4. 実際の結果
  ### 大失敗!!🔥

- <INS>参考資料の不備</INS>
参考にした資料が適切でなかったため、コードをコピペしてもエラーが発生しました。

    ➡️資料に起こしたコードは1度自分でテストして不備がないか確認するべきでした。

- <INS>エミュレータの問題</INS>
 エミュレータの挙動に予想外の不具合があり、アプリの見本を見せることができませんでした。

    ➡️エミュレータやデモンストレーション用のデバイスなどは、事前に動作確認を行い、問題があれば対策をするべきでした。


- <INS>ツールの使い方の混乱</INS>
 Android Studio、Notion、Teamsなど、複数のツールを使用しての作業で混乱が生じました。

- <INS>Notionの不適切な使用</INS>
   Notionは自分のメモ用途に使用するべきであり、共有するにはあまり適さないことがわかりました

    ➡️共有するにはNotionはwebサイトに公開しなおす必要があり、非効率なのでQiitaやZenn・esaなどのwikiを活用すべきでした。

- <INS>オンライン環境の課題</INS>
   オンライン形式の勉強会では、参加者が画面共有か自分のAndroid Studioどちらを見ているのか分かりませんでした。

   進行状況や理解度の把握が難しく、進めるべきタイミングが判断できなかったことが課題でした。

# 5. 成果と学び
#### 1.イベントを主催した立場になって
今回のイベントでは、参加者全員がチャットやスタンプなどで反応してくれました。しかし、オンライン環境でイベントを主催する立場として、参加者の反応がない場合、非常に寂しい気持ちになります。

:::note warn
一人でパソコンに話しかけながら、作業している人に見える…
:::

#### 2.Flutterという教材について
Android Studioは多くの機能が提供されていますが、その代わりに大量のメモリを使用ビルドに時間がかかることで、参加者の待ち時間が長くなり、集中力や興味を失う可能性があることに気づきました。
~~そして時間がかかったことにより、せっかく作ったスライドでプレゼンできませんでした…(悲)~~



# 6. 結論とまとめ
:::note info
Flutter(AndroidStudio)で勉強会は厳しい
また挑戦したい気持ちになった(悔しい😡)
:::
[Mac] TensorFlow環境構築

**いつか私はディープラーニングをしてみたい！**

そんな想いをもちつつも、環境構築にハードルを感じてしまい、バグりまくって諦めてませんか？



いつかやらねば（やらない）=>時間経過=>以下ループ
しかし、このままではいつまで経っても進歩がない！と思い、ついに着手することにしました。



以下の手順に沿って、私のコードのコピペをすればすぐに音声認識や画像生成といったディープラーニングのエキサイティングな経験ができるようになりますよ:relaxed:


**使用パッケージ**

Pyenv

この世にはさまざまなPython環境構築用のパッケージがあります（Virtualenv condaなど）
その中でPyenvは最速かつわかりやすさもダントツですので、これを使います。以下のリンクがpyenvダウンロードの参考になります
(https://github.com/pyenv/pyenv)

1 機械学習作業ディレクトリを作ります(今回は機械学習ということでMLという名前にしました）
```java:terminal
% mkdir ML #MLという名前のディレクトリを作る
```

2 機械学習作業ディレクトリに移動
```java:terminal
% cd ML #MLというディレクトリに移動する
```
3 仮想環境として使いたいpythonのバージョンを作る(今回は3.9.16を使います）
```java:terminal
% pyenv local 3.9.16
```
 実際にヴァージョンを確認してみると、確かに指定したバージョンになってます！
```java:terminal
%  pyenv exec python --version
>>Python 3.9.16(実行結果）

4 ipykernel（便利なジュピターノートブックを使うために必要）をインストール
```java:terminal
% pyenv exec pip install ipython ipykernel
```

5 ipykernelに名前をつけて使えるようにする(今回はpython3.9.16という名前）
```java:terminal
%  pyenv exec python -m ipykernel install --user --name=python3.9.16 --display-name=python3.9.16
```


6 jupyter lab 起動(今回はpython3.9.16という名前）
```java:terminal
% jupyter lab
```

完了！あなたもこんな感じですぐに画像生成AIを作れてしまいますよ〜。
**学習前の生成画像**

![image_at_epoch_0000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3468399/b6a67b2a-1056-6e57-a664-cb857105f43d.png)


**学習後の生成画像**
![image_at_epoch_0010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3468399/cbd8ae0f-1c3e-a200-e14c-f95c12aa7aaf.png)


（画像生成AIについてのコードと解説は記事にしますね:grin:）

以上！！

蛇足：python3.9.16にした理由は、tensorflow2.1はpython3.10以降では使えないからです