OmniAICreator/Qiita-1.07M huggingface dataset:
TrueNAS Core 13.0 で shutdown が reboot になる問題

# 何が起きたか
- TrueNAS Core を 12 から 13 に update した
- GUI からの shutdown、もしくは `shutdown -p` が変な挙動をするようになった
    - shutdown 自体はするが、落ちた直後に再度電源が入ってしまう
    - `shutdown -r` みたいな挙動をする
- マザーボードの配線ミスったか？と思ったが、問題無し
- UEFI の問題か？と思い、WoL などの無効化も試したが、効果なし

# 解決
- Tunable で `hw.efi.poweroff=0` に設定する
- 左メニュー / System / Tunables
    - ADD
    - Variable: `hw.efi.poweroff`
    - Value: `0`
    - Type: `sysctl`
- 設定反映のため reboot

# 原因
- TrueNAS 自体じゃなく、FreeBSD の問題らしい
    - https://www.truenas.com/community/threads/shutdown-causes-reboot-on-truenas-core-13-0-u1.102752/
Dockerコマンドの補完 (completion) を設定する方法

## 設定方法
Docker Dekstop から Rancher Desktopに乗り換えた時にコマンドの補完の設定方法がわからなくなったので調べた時の備忘録です。 (Dockerのドキュメントも古い)

以下は zshですが、「bash」「fish」「powershell」でも同じような操作で設定可能っぽいです

```zsh
$ docker --version
Docker version 23.0.1-rd, build 393499b

$ docker completion zsh > ~/.zsh/completions/_docker
```

## 参考
* Command-line completion? https://github.com/docker/compose/issues/8550
エクセルマクロからAPI接続でChatGPTを使ってAIチャットボットを作成してみた！

# はじめに
今、話題のChatGPTをExcelマクロ(VBA)から使えるようにしましたので、ご紹介します。
# 環境
Windows10
Excel(Microsoft365バージョン）

# 流れ
・完成イメージ
・APIキーの取得方法
・基本構造作成
・JSON形式のデータ取得
・2回目以降の質問実装
・エンディング

# 最終画面イメージ
最終的に、以下のようなChatGPTを組み込んだAIチャットボットを作成しました。
![完成イメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1361368/60333ff9-d859-dc14-242a-33060fd4e81a.jpeg)


# YouTubeでの解説：
上記の作業の流れをYoutubeで詳しく解説していますので、ぜひ、ご覧ください。
<iframe width="560" height="315" src="https://www.youtube.com/embed/nsrg40kdFuM" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

# サンプルソース
YouTubeで紹介している処理の初期版プログラムソースです。
```vb
Sub ChatGPT_API()
 
    Dim APIKey As String
    Dim strModel As String
    Dim strQuestion As String
    
    Dim Url As String
    Dim http As Object
    Dim strMessages  As String
    Dim strResponse As String
 
    '*** 初期値設定 *****
    APIKey = "APIキーを貼り付けてください"
    strModel = "gpt-3.5-turbo"  'モデル名
    
    strQuestion = Range("B2").text '**質問を変数にセット
        
    '*** API処理 ****
    Url = "https://api.openai.com/v1/chat/completions"
    
    Set http = CreateObject("MSXML2.XMLHTTP")

    'リクエストヘッダー
    http.Open "POST", Url, False
    http.setRequestHeader "Content-Type", "application/json"
    http.setRequestHeader "Authorization", "Bearer " & APIKey
    
    'メッセージ作成
    strMessages = "{""model"": """ & strModel & """," & _
                  """messages"": [{""role"": ""user"", ""content"": """ & strQuestion & """}]}"

    'リクエスト送信
    http.send strMessages
    
    strResponse = http.responseText         '結果を変数に代入
    
    Range("B5") = strResponse
 
End Sub
```

# 最終プログラム
YouTubeで紹介している最終プログラムソースは、YouTube動画の概要欄に、限定公開のQIITAのURLを掲載していますので、Youtube動画経由でご覧ください。
https://youtu.be/nsrg40kdFuM


# 最後に：
今回は、ChatGPTに対してエクセルマクロでAPI接続するプログラムを作成しました。
意外と簡単に出来ましたが、このプログラム作成もChatGPTやBing-AIを使って作成しました。
もう、ChatGPTなしには、プログラムが作成できません！
今後も、良さそうなプログラムが出来たら、ご紹介したいと思います。
Djangoプロジェクトをexe化する方法

#### はじめに
こんにちわ。hinaateです。Djangoプロジェクトをexe化して第三者に提供したくなったので、参考文献を列挙しておきます。基本的にはPyinstallerでexe化できます。稀に必要なライブラリが入っていないエラーがでることがあるので、その場合は、.specの「hiddenimport」に必要なライブラリを入力して再度exe化すればよいみたいです。

#### おわりに
今回はただのメモです。只今こちらはGWなので、この程度で許してください。🦛
#### 参考文献
https://di-acc2.com/programming/python/21052/#index_id3
https://ssrv.net/tech/python-pyinstaller-no-module/
Elixir で WEB スクレイピング

# 概要
Chromedriver を使って WEB スクレイピングします。


# 環境設定
事前に、Chrome と Chromedriver をインストールする必要があります。

Docker を使う場合は以下です。
```dockerfile:Dockerfile
FROM elixir:1.14.4
  
ENV LANG C.UTF-8

WORKDIR /api

ARG CHROME_VERSION="112.0.5615.165-1"
ARG CHROMEDRIVER_VERSION="112.0.5615.49"

RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \
    && apt-get update -qq \
    && apt-get install -y --no-install-recommends \
    google-chrome-stable=${CHROME_VERSION} \
    && mix local.hex --force \
    && mix local.rebar \
    && mix archive.install hex phx_new 1.7.2

ADD https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_VERSION}/chromedriver_linux64.zip /usr/local/bin
RUN cd /usr/local/bin && unzip chromedriver_linux64.zip
```

Chrome と Chromedrive のバージョンを合わせる必要があるため、変数に指定しています。
https://chromedriver.chromium.org/downloads

# アプリケーション設定
※アプリケーションの新規作成の仕方は省略。

```elixir:mix.exs
  defp deps do
    [
      ...,
      {:hound, "~> 1.0"},
      {:floki, "~> 0.34"}
    ]
```
 
[hound](https://github.com/HashNuke/hound) と [floki](https://github.com/philss/floki) を使います。
hound は、headless ブラウザのアクセス制御で、flokiは、HTML パーサーです。

```elixir:config/config.exs
config :hound, driver: "chrome_driver"
```
houndからは、Chromedirver を使うように設定します。

# スクレイピング実行
事前にインストール済みの chromedriver を起動しておいてください。
ポート番号はデフォルトで問題ありません。
その後、次のように hound で、セッションを開始し、ページ情報を取得してください。

```elixir:iex
proc = fn ->
  url = "https://books.toscrape.com/"
  selector = "title"

  Hound.start_session(
    browser: "chrome",
    user_agent: :chrome,
    driver: %{
      chromeOptions: %{
        args: [
          "--headless",
          "--no-sandbox"
        ]
      }
    }
  )

  navigate_to(url)

  result =
    page_source()
    |> Floki.find(selector)
    |> Floki.text(sep: " ")
    |> String.replace(~r/　/, "")
    |> IO.inspect

  Hound.end_session()
end

proc.()
```

# 注意
同時に多数のセッションを接続しての評価はしていません。
AWS: SQSの可視性タイムアウトを設定する

AWS SQSの可視性タイムアウト(Visibility Timeout)を調整する話です。

ここではAWS SQSの概要は言及しません。ことわりがない限り、SQSはFIFOを利用しているものとします。

# 原因と対策

## 発端

可視性タイムアウトを1minに設定したキューで、メッセージを削除できない事案が発生していました。具体的にはアプリケーションでSQSからエラーメッセージを受け取っています。

> ReceiptHandle is invalid. Reason: The receipt handle has expired
> 

受信した際に確保した受信ハンドルを使ってメッセージを削除しようとすると、「ハンドルの期限が切れている」と言われます。

## 受信ハンドルと可視性タイムアウト

SQSは、メッセージを受信するとレスポンスとして受信ハンドルを受け取れます。受信ハンドルは、メッセージに対する一意のキー情報のようなもので、有効期限が設けられるものです。
受信ハンドルはキューに設定された可視性タイムアウトの範囲を超えると有効期限切れとなり、削除ができません。

メッセージキューを利用するようなユースケースでは、ただ一度だけ受信することをアーキテクチャ上厳密に管理したいことがあります。
AWS SQSでは、そのような重複処理を排除する仕組みとして、一度受信リクエストを受け付けたメッセージを一定期間コンシューマから見えないようにする期間が設けられています。これをSQSの仕組みで「可視性タイムアウト」と呼んでいます。

「メッセージを見えなくする」イメージについては、下記記事がとても具体的でわかりやすいのでご参考ください。
[https://dev.classmethod.jp/articles/sqs-visibility-timeout/](https://dev.classmethod.jp/articles/sqs-visibility-timeout/)

受信者であるコンシューマから、メッセージが見えない期間を設定することでメッセージの重複処理を避けられるようになるのですが、受信ハンドルが有効な期間にメッセージの削除までできなければ「メッセージをただしく処理できた」とは言えない、ということでもあります。
[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)でも次のように紹介されています:

> コンシューマーがキューからメッセージを受信して処理しても、そのメッセージはキューに保留されたままです。Amazon SQSでは、メッセージが自動的に削除されません。Amazon SQSは分散システムであり、接続の問題やコンシューマーアプリケーションの問題などが原因で、コンシューマーが実際にメッセージを受信するという保証がありません。そのため、コンシューマーはメッセージを受信して処理した後、キューからメッセージを削除する必要があります。

この概要からわかるように、受信と削除は別の概念に位置づけられています。そのため、受信ハンドルを使って明示的に削除する必要があります、もし可視性タイムアウトの期間内に削除できなければ受信ハンドルを無効化、削除リクエストを受け付けない仕様としています。

# 対策

頻繁に可視性タイムアウトを超えてしまう場合、削除までの処理が長すぎる、ないしは可視性タイムアウトが要件に対して短すぎる、などの可能性がありえます。

プロジェクトの要件次第ですが、3つほどの対策が考えられます:

1. 可視性タイムアウトを引き伸ばす
2. トランザクション単位を受信〜処理にまとめる
3. 処理の性能を改善する

1.はたしかに簡単な選択肢ですが、可視性タイムアウトがながければ長いほど、キュー内で削除を待つ期間が長くなります。したがって、キューを受信してからの処理でエラーが一定量想定される場合には、削除を待つ時間が長くなり、結果キューの長さを長くしてしまいます。可視性タイムアウトを長くすることはトレードオフが発生します。

安直に可視性タイムアウトを伸ばすのが要件に合わない、ないしは設計上不都合が生じる場合は1トランザクションで受信 -> 処理 -> 削除をできるよう、アプリケーションの修正を試みるのも有効です。

3は、当たり前といえば当たり前ですが、キューのコンシューマになるアプリケーションを、キューを利用する前提でチューニングするということです。2と被る部分もありますが、結局一定の速度で処理し続けられるような可用性・性能をアプリケーションで実装できれば、可視性タイムアウトにまつわるトラブルも少ないはずです。

# おわりに
他のメッセージキューイングシステムを事細かに調べたわけではないので断言はできないですが、SQSの可視性タイムアウトは概念以上に用語がわかりづらかったです。

重複処理させない仕組みであること、設定は柔軟にできるがトレードオフが存在することを念頭に運用することで、アーキテクチャにあった設定を選択できるかと思います。


# 参考

[AWS SQS DeleteMessage API を呼び出すときに、ReceipthHandleisInvalid エラーおよび InvalidParameterValue エラーのトラブルシューティングを行う](https://aws.amazon.com/jp/premiumsupport/knowledge-center/sqs-receipt-handle-error/)

[Deleting AWS SQS messages using Java sdk](https://stackoverflow.com/questions/43542746/deleting-aws-sqs-messages-using-java-sdk)

[Amazon SQS可視性タイムアウト](https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)

[Amazon Simple Queue Service の可視性タイムアウトってなぁに? | DevelopersIO](https://dev.classmethod.jp/articles/sqs-visibility-timeout/)
RustでExcelの行の高さと列の幅を変更する

現在フリーランスエンジニアとして活動していて、今今携わっている案件ではRustとTauriを使ってExcelファイルを出力するデスクトップアプリを開発しています。

プログラムからExcelファイルを操作する際に金額の桁数が大きかったり文字数が多かったりした場合、「#####」になったり見切れたりすることがあったので、Excelの行の高さと列の幅を変更する方法を調べました。

[前回の記事](https://qiita.com/masuda401/items/c7ce591f6d0250b016a6)から引き続き、今回もExcelファイルを書き込むためのライブラリとして`rust_xlsxwriter`を使用します。

rust_xlsxwriterで行の高さを変更するには`set_row_height_pixels`メソッドを使用します。第一引数に行番号、第二引数には行の高さ（ピクセル）を渡します。

```Rust:Rust
pub fn set_row_height_pixels(
    &mut self,
    row: RowNum,
    height: u16
) -> Result<&mut Worksheet, XlsxError>
Set the height for a row of cells, in pixels.

The set_row_height_pixels() method is used to change the default height of a row. The height is specified in pixels, where the default height is 20.

To specify the height in Excel’s character units use the set_row_height() method.

Arguments
  row - The zero indexed row number.
  height - The row height in pixels.

Errors
  XlsxError::RowColumnLimitError - Row exceeds Excel’s worksheet limits.
```

https://docs.rs/rust_xlsxwriter/0.37.0/rust_xlsxwriter/struct.Worksheet.html#method.set_row_height_pixels

同様に列の幅を変更するには`set_column_width_pixels`メソッドを使用します。第一引数に行番号、第二引数には列の幅（ピクセル）を渡します。

```Rust:Rust
pub fn set_column_width_pixels(
    &mut self,
    col: ColNum,
    width: u16
) -> Result<&mut Worksheet, XlsxError>
Set the width for a worksheet column in pixels.

The set_column_width() method is used to change the default width of a worksheet column.

To set the width in Excel character units use the set_column_width() method.

See also the autofit() method.

Arguments
  col - The zero indexed column number.
  width - The row width in pixels.

Errors
  XlsxError::RowColumnLimitError - Column exceeds Excel’s worksheet limits.
```

https://docs.rs/rust_xlsxwriter/0.37.0/rust_xlsxwriter/struct.Worksheet.html#method.set_column_width_pixels

行の高さを100px、列の幅を200pxに変更するサンプルコードを載せます。

```Rust:Rust
let mut book = Workbook::new();
let sheet = book.add_worksheet();
let currency_format = Format::new().set_num_format("€#,##0.00");

sheet.write_number_with_format(0, 0, 1234.5, &currency_format)?;
// 行の高さを100pxに設定
sheet.set_row_height_pixels(0, 100)?;
// 列の幅を200pxに設定
sheet.set_column_width_pixels(0, 200)?;

book.save(Path::new("test.xlsx"))?;
```

![スクリーンショット 2023-05-01 19.33.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/d8e795b6-e047-2b26-604b-289e1a808e1b.png)

無事RustでもExcelで行の高さと列の幅を変更することができました。
chrubyとruby-installのご紹介

## この記事について

Ruby記事投稿キャンペーンということで、ちょっとした記事を書こうと思います。

## rbenvとruby-buildについて

この記事を読んでいる方の大部分はRubyのバージョン管理やインストールに[rbenv](https://github.com/rbenv/rbenv)と[ruby-build](https://github.com/rbenv/ruby-build)を使っていることと思います。最初に明言しておくと、これらのツールから乗り換える必要は全くありません。

その上で、同じようなことをする別のツール、chrubyとruby-installを紹介しようと思います。なお、どちらも同じ方（[postmodern氏](https://github.com/postmodern)）の作品です。

## chruby

[chruby](https://github.com/postmodern/chruby)はRubyのバージョンを切り替えるためのツールです。特徴としては、ディレクトリを切り替えたときのRubyバージョンの自動切り替えがオプションの機能であることなどが挙げられます（https://github.com/postmodern/chruby#auto-switching）。

`rbenv global`のような機能はないのですが、自動バージョン切り替えを有効にしておけば、`~/.ruby-version`を置いておけばよいだけなので問題なく、結果としてシンプルな実装の良さを享受できるといったところです。

また、`shims`の概念がなく、`~/.gems`にインストール済みgemが配置されます。

## ruby-install

[ruby-install](https://github.com/postmodern/ruby-install)はRubyをインストールするためのツールです（ググラビリティが低い）。特徴としてはインストール可能なRubyのバージョンを[別に管理している](https://github.com/postmodern/ruby-versions)ため、Rubyの新しいバージョンがリリースされても本体の更新が不要なことが挙げられます。

今挙げた特徴は実際割と便利で、例えば`ruby-install ruby 3.2.2`を実行すると、「Ruby3.2.2があるはずの場所」にダウンロードしに行くのでメタデータの更新をしなくてもダウンロードからインストールまでできてしまいます（それがいいことなのかはさておき）。

インストール時に`brew install`系のコマンドが自動で走るのも、依存関係のことをあまり気にしなくて良くなるので便利です。

## まとめ

というわけで、chrubyとruby-installのご紹介でした。この手のツールとしては他に[rvm](https://rvm.io/)がありますが、それらの中でも軽量なものとなっていると思います。コードを読んでみるとRubyのインストールについて理解が深まるかもしれません。
タワーデフェンスゲーム　Unity タレット機能　まとめ

# 説明

Unity でタワーデフェンスゲームのクローンを作ってます。
タレット機能の実装について後で確認しやすくするため、記事のリンクと実装後のUnityの画面(gifアニメ)をまとめます。

# 参考にしたUdemy講座

https://www.udemy.com/course/learn-how-to-create-a-2d-tower-defense-game-in-unity-2020/learn/lecture/23145718#content

チャプター毎にプロジェクトフォルダが有るから　処理が追いやすく理解しやすいからおすすめ

# 一覧

## 1/10　23.タレットの半径を設定できるように実装

![TurretRange.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/296f032f-474e-cad5-d2e1-24361ea46907.gif)

https://qiita.com/RYA234/items/fbace3c0671725ba50a1

## 2/10　24 タレットのCollidar内に入ったEnemyを取得する

![CollidarEnter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/d5c02e46-0476-8108-c3f8-0a3c44200c5c.gif)

https://qiita.com/RYA234/items/606c830a2bba9b74dd5a

## 3/10　24 タレットが取得したEnemy方向を向くようにする

![rotate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/c6e2f604-a211-f1dd-9752-a558db5dd43e.gif)

https://qiita.com/RYA234/items/23f030a5929cf46abcd6

## 4/10　25 　Gボタンを押すとタレット上に弾が生成される機能を実装

![1zfcgfddfsfdsag.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/fd5a564a-6d1e-4d22-7db0-6f971a6138b6.gif)

https://qiita.com/RYA234/items/62e25a13a47a19884038

## 5/10 25 弾が敵に向かうように実装

![ASAAAA.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/5804dc32-52fe-d0d4-d848-ef45d4987993.gif)

https://qiita.com/RYA234/items/4c142feea046fe4fc838

## 6/10 タレットの弾が敵に対して正面にする

改善前


![before1111.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/15909d2a-5702-f147-ce64-0b0966c39638.gif)


改善後

![after1111.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/db6cc0cc-cca4-fd83-1270-9ea1fcbf7288.gif)

https://qiita.com/RYA234/items/633046d985ec1c8c0084

## 7/10 敵に弾が着弾した時にHPが減少するよう実装

![attack.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/9edeeb22-4dbf-2f86-1b43-600347760024.gif)

https://qiita.com/RYA234/items/5cbbcbcf0604152556ef

## 8/10　26 一定間隔毎に弾が出てEnemyにダメージを与える

![autoatack.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/56e334af-bd6b-c6c0-672b-cbd06865063f.gif)

https://qiita.com/RYA234/items/cf4c10ac30038872f266

## 9/10　ダメージ被弾時ダメージ量を表示する

![animationresult.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/69a48caf-db18-a8bd-96a3-a6272626d458.gif)

https://qiita.com/RYA234/items/495af0f9d942e4a1361d

## 10/1○　Singletonクラスを作成して置き換える
スクリプトを変更しただけなのでgifは無し
SwiftUIで液体っぽいアニメーションを作る

![画面収録_2023-05-01_19_46_17_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648522/b7357b1e-174c-b4f0-8903-1ed4c4bd1b67.gif)

```swift
struct HogeView: View {
    @State var show = false
    
    var body: some View {
        Canvas { context, size in
            context.addFilter(.alphaThreshold(min: 0.8))
            context.addFilter(.blur(radius: 10))
            context.drawLayer { ctx in
                for index in 1...2 {
                    if let symbol = context.resolveSymbol(id: index) {
                        ctx.draw(symbol, at: CGPoint(x: size.width / 2, y: size.height / 2))
                    }
                }
            }
        } symbols: {
            Circle()
                .frame(width: 100)
                .offset(x: show ? 55 : 0)
                .tag(1)
            Circle()
                .frame(width: 100)
                .offset(x: show ? -55 : 0)
                .tag(2)
        }
        .onTapGesture {
            withAnimation(.spring(response: 0.8, dampingFraction: 0.3)) {
                show.toggle()
            }
        }
    }
}
```
タワーデフェンスゲーム　Unity タレット機能 10/10　Singletonクラスを作成して置き換える

# 概要
目次

https://qiita.com/RYA234/items/c9925ce07d6afe64be7e

前回の続きです。
今回Singletonクラスを作って置き換えます。


# 開発環境
IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定
無し。スクリプトの変更のみ

# 実装のポイント
新規クラスSingletonを作成します。
DamageTextManageのリファクタリングを行います。



# コード部分
## Singleton
```diff_c_sharp:Singleton.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Singleton<T> : MonoBehaviour where T : Component
{
    private static T instance;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<T>();
                if (instance == null)
                {
                    GameObject newInstance = new GameObject();
                    instance = newInstance.AddComponent<T>();
                }
            }

            return instance;
        }
    }

}


```

## DamageTextManager
```diff_c_sharp:DamageTextManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

- public class DamageTextManager : MonoBehaviour
public class DamageTextManager : Singleton<DamageTextManager>
{
    
    public ObjectPooler Pooler { get; set; }

-    public static DamageTextManager Instance;

-    private void Awake()
-    {
-        Instance = this;
-    }
    
    // Start is called before the first frame update
    void Start()
    {
        Pooler = GetComponent<ObjectPooler>();
    }
    
}


```


# 参考






Section5 28

https://www.udemy.com/course/learn-how-to-create-a-2d-tower-defense-game-in-unity-2020/learn/lecture/23145498#overview


github コミット分

https://github.com/RYA234/2DTowerDeffenceMyLearning/commit/711b49fb4d12727f42e2dd1d32fa73b5c8b96b09
タワーデフェンスゲーム　Unity タレット機能 7/10 敵に弾が着弾した時にHPが減少するよう実装

# 概要

目次

https://qiita.com/RYA234/items/c9925ce07d6afe64be7e

今回は敵に弾が着弾した時にHPが減少するよう実装します。
以下gifアニメはその時の様子です。Gボタンを連打しています。

![attack.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/9edeeb22-4dbf-2f86-1b43-600347760024.gif)


# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定
特に変化無いです。

# 実装のポイント
ProjectileクラスのMoveProjectileメソッド内に着弾時の処理を加えます。
着弾時にEnemyHealthクラスから処理を実行します。
着弾の判定は弾と敵オブジェクトの距離が近くなった時とします。

下記事の応用ですね。
ダメージ減少処理がaボタンの押下からProjectileクラスのMoveProjectileメソッドに切り替わっただけです。

https://qiita.com/RYA234/items/b1f54272c1d63d95d859

# コード部分
```diff_c_sharp:Projectile.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Projectile : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 10f;
    private Enemy _enemyTarget;
+    [SerializeField] private float damage = 2f;
+    [SerializeField] private float minDistanceToDealDamage = 0.1f;
    
    public 
    
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (_enemyTarget != null)
        {
            MoveProjecttile();
            RotateProjetile();
        }
    }

    private void MoveProjecttile()
    {
        transform.position = Vector2.MoveTowards(transform.position,_enemyTarget.transform.position,moveSpeed * Time.deltaTime);
+        float distanceToTarget = (_enemyTarget.transform.position - transform.position).magnitude;
+        if (distanceToTarget < minDistanceToDealDamage)
+        {
+            _enemyTarget.EnemyHealth.DealDamage(damage);
+            ObjectPooler.ReturnToPool(gameObject);
+            
+        }
    }

    private void RotateProjetile()
    {
        Vector3 enemyPos = _enemyTarget.transform.position - transform.position;
        float angle = Vector3.SignedAngle(transform.up, enemyPos, transform.forward);
        transform.Rotate(0f,0f,angle);
    }

    public void SetEnemy(Enemy enemy)
    {
        _enemyTarget = enemy;
        
    }
}



```


# 参考


Section5 26

https://www.udemy.com/course/learn-how-to-create-a-2d-tower-defense-game-in-unity-2020/learn/lecture/23141872#content


github コミット分


https://github.com/RYA234/2DTowerDeffenceMyLearning/commit/c1aee686046c383a630c4666bd0e1105c0216e84
タワーデフェンスゲーム　Unity タレット機能 6/10 タレットの弾が敵に対して正面にする

# 概要

目次

https://qiita.com/RYA234/items/c9925ce07d6afe64be7e


今回はをタレットの弾が敵に対して正面になるように実装します。
以下gifアニメは改善前、改善後の様子です
改善後において、弾と敵は直角になっていることを確認できます。

改善前


![before1111.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/15909d2a-5702-f147-ce64-0b0966c39638.gif)


改善後

![after1111.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/db6cc0cc-cca4-fd83-1270-9ea1fcbf7288.gif)


# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定
前回と変わらないです。変更したのはスクリプトだけです。

# 実装のポイント
ProjectileクラスにRotateProjetileメソッドを追加します。
RotateProjectileメソッドは角度をイジる処理です。



# コード部分



```diff_c_sharp:Projectile.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Projectile : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 10f;
    private Enemy _enemyTarget;
    
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (_enemyTarget != null)
        {
            MoveProjecttile();
+            RotateProjetile();
        }
    }

    private void MoveProjecttile()
    {
        transform.position = Vector2.MoveTowards(transform.position,_enemyTarget.transform.position,moveSpeed * Time.deltaTime);
    }

+    private void RotateProjetile()
+    {
+        Vector3 enemyPos = _enemyTarget.transform.position - transform.position;
+        float angle = Vector3.SignedAngle(transform.up, enemyPos, transform.forward);
+        transform.Rotate(0f,0f,angle);
+    }

    public void SetEnemy(Enemy enemy)
    {
        _enemyTarget = enemy;
        
    }
}

```

# 参考

Section5 25

https://www.udemy.com/course/learn-how-to-create-a-2d-tower-defense-game-in-unity-2020/learn/lecture/23140518#content

github コミット分

https://github.com/RYA234/2DTowerDeffenceMyLearning/commit/16cce061efa83352ce7d4f2a70c21bc8246c6823
【React学習 #2】環境構築

# はじめに
この記事はReact初心者の筆者が学習のために書いている記事です。
間違っていたら温かくご指摘いただけるとありがたいです。

# 動作環境
* PC：Macbook
* CPU：Intel
* OS：MacOS Ventura 13.3.1

# Homebrewをインストール
まず、パッケージマネージャーのHomebrewが入っていない場合は、インストールする必要があります。
インストール済みかどうかは、以下のコマンドで確認できます。

```
brew -v
```

<br>

[Homebrewのサイト](https://brew.sh/index_ja)の「インストール」の下にあるコマンドをコピーし、ターミナルに貼り付け実行します。

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

バージョン確認のコマンドを実行し、インストールされていることを確認します。
```
brew -v
> Homebrew 4.0.15
```

# nodebrewをインストール
nodebrewは、node.js(npm)のバージョン管理ツールです。
コマンドひとつで特定バージョンのnodeのインストールや、バージョンの切り替えを行えるようになります。

以下のコマンドを実行し、インストールします。

```
brew install nodebrew
```

インストールが完了したら、セットアップを行います。

```
nodebrew setup
```

セットアップ完了後、PATH情報が出力されるので、PATH情報を.zshrcに反映させます。

```
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
```

# node.jsをインストール
[node.jsの公式サイト](https://nodejs.org/ja)からLTS版のバージョンを調べます。
以下のコマンドを実行して、node.jsのLTS版をインストールします。

```
nodebrew install v18.16.0
```

インストールが完了したら、以下のコマンドでnode.jsを有効化します。

```
nodebrew use v18.16.0
```

最後に、以下のコマンドでnode.jsの動作確認をします。

```
node -v
npm -n
```

# Reactのプロジェクトを作成
Reactのプロジェクトを作成するには以下のコマンドを実行します。

```
cd [プロジェクトを作成する場所]
npx create-react-app [プロジェクト名]
```

完了したら、[プロジェクト名]で指定したフォルダが作成され、その直下に様々なファイル等が格納されます。


# Reactアプリケーションを実行する
以下のコマンドを実行して、Reactのアプリケーションを実行します。

```
cd [プロジェクトの場所]
npm start
```

このコマンドを実行すると、Webブラウザが開かれ、「 http://localhost:3000/ 」にアクセスします。
動作を確認できたら、ターミナル上で「Ctrl+C」を押して終了します。
タワーデフェンスゲーム　Unity タレット機能4/10　25 　Gボタンを押すとタレット上に弾が生成される機能を実装

# 概要
目次

https://qiita.com/RYA234/items/c9925ce07d6afe64be7e

今回は,タレットが発射する弾を生成する機能を実装します。
以下gifアニメはGボタンを押すとタレット上に弾が生成している様子です。

![1zfcgfddfsfdsag.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/fd5a564a-6d1e-4d22-7db0-6f971a6138b6.gif)


# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定
タレットのオブジェクトにObjectPoolerとTurretProjecttileスクリプトをアタッチします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/68e2b197-6da9-95bb-8985-621a6f4dbe7f.png)


# 実装のポイント
新規クラスにTurretProjecttileを作成します。
ObjectPoolerを使って弾をタレット上に表示するメソッドを追加します。
Updateメソッド内にGボタンを押すと上のメソッドを実行するようにします。

# コード部分

```diff_c_sharp:ProjecTile.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TurretProjectTile : MonoBehaviour
{

    [SerializeField] private Transform projecttileSpawnPosition;
    private ObjectPooler _pooler;
    private Turrets _turret;


    private void Start()
    {
        _pooler = GetComponent<ObjectPooler>();
        _turret = GetComponent<Turrets>();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.G))
        {
            LoadProjecttile();
        }


    }

    private void LoadProjecttile()
    {
        GameObject newInstance = _pooler.GetInstanceFromPool();
        newInstance.transform.position = projecttileSpawnPosition.position;
        newInstance.transform.SetParent(projecttileSpawnPosition);
        newInstance.SetActive(true);


    }
}


```






# 参考




Section5 25

https://www.udemy.com/course/learn-how-to-create-a-2d-tower-defense-game-in-unity-2020/learn/lecture/23140518#content



github コミット分

https://github.com/RYA234/2DTowerDeffenceMyLearning/commit/908348f17d642cf5d36acde855079f4fd4c69fd2#diff-7c8a024e038c36bc46e2b3758038c8bfbc930e53e04b2fc4fd504463978feef3
タワーデフェンスゲーム　Unity タレット機能2/10　24 タレットのCollidar内に入ったEnemyを取得する

# 概要
目次

https://qiita.com/RYA234/items/c9925ce07d6afe64be7e


前回の続きです。
今回はタレットのCollidar内に入ったEnemyを取得する処理を実装します。
下gif画像は、敵がTurretの攻撃範囲に入った時にTurretクラス側の追加されるときの様子です。（赤枠部分）
インスペクターをデバッグモードにして確認しています。

![CollidarEnter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/d5c02e46-0476-8108-c3f8-0a3c44200c5c.gif)




# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定
## Enemyオブジェクト
Enemyオブジェクトのタグを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/e535d9c2-2dd9-fba4-dcf1-7bca81b2b807.png)

Colliderのコンポーネントを追加

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/01546d26-a94f-f019-9e62-63536dd3c9a2.png)



## Turretオブジェクト

TurretオブジェクトにアタッチされているCollidarのIs Triggerをオンにするぐらい
オフだと実装した関数が実行されないです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/e67a64d6-9885-e205-1887-1218723bf998.png)


# 実装のポイント

TurretsクラスにOnTriggerEnter2Dメソッドを追加します。
OnTriggerEnter2DメソッドはUnityイベント関数で、Colliderに接触したら実行されます。
接触したオブジェクトがEnemyタグを持っていた場合に処理を実行します。


# コード部分
## Turrets

```diff_c_sharp:Turrets.cs
+ using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Turrets : MonoBehaviour
{
    [SerializeField] private float attackRange = 3f;
+    public Enemy CurrentEnemyTarget { get; set; }
    private bool _gameStarted;

+    private List<Enemy> _enemies;
    
    private void Start()
    {
        _gameStarted = true;
+        _enemies = new List<Enemy>();
    }

    private void Update()
    {
        
    }

+    private void GetCurrentEnemyTarget()
+    {
+        if (_enemies.Count <= 0)
+        {
+            CurrentEnemyTarget = null;
+            return;
+        }
+    }
+    private void OnTriggerEnter2D(Collider2D other)
+    {
+        if (other.CompareTag("Enemy"))
+        {
+            Enemy newEnemy = other.GetComponent<Enemy>();
+            _enemies.Add(newEnemy);
+        }
+
+        CurrentEnemyTarget = _enemies[0];
+        
+    }

    private void OnDrawGizmos()
    {
        if (!_gameStarted)
        {
            GetComponent<CircleCollider2D>().radius = attackRange;
        }
        
        Gizmos.DrawWireSphere(transform.position, attackRange);
    }
}

```


# 参考
OnTriggerEnter2D

https://docs.unity3d.com/ja/2021.1/ScriptReference/MonoBehaviour.OnTriggerEnter2D.html


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/ce378f58-ffc9-b1e2-56a2-d6c890ebe3cc.png)


Component.CompareTag

https://docs.unity3d.com/ja/2018.4/ScriptReference/Component.CompareTag.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/c583416d-f8d8-410d-1ce4-3980958aeb32.png)



Section5 23

https://www.udemy.com/course/learn-how-to-create-a-2d-tower-defense-game-in-unity-2020/learn/lecture/23137448#content


github コミット分

https://github.com/RYA234/2DTowerDeffenceMyLearning/commit/2e12436323211d226237393445b85d235b836197#diff-e3060f0a28a3723ed32a1bb592698a46c11714fa26d8106305e7d270f8cb1282
Google Apps Scriptでメール送信API作成【爆速GAS Mail】

# つくりかた

### 新しいプロジェクトを作る
作る
https://script.google.com/

```javascript
function doPost(e) {
  const { recipient, subject, body, ...options } = JSON.parse(e.postData.getDataAsString())
  GmailApp.sendEmail(recipient, subject, body, options)
  Logger.log('REMAINING_DAILY_QUOTA: ' + MailApp.getRemainingDailyQuota())
  return ContentService.createTextOutput()
}
```

### Gmail APIを有効にする
サービス からGmail APIを追加にしてください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/580693e6-8b98-c89f-2364-45d2257acf1b.png)

### ビクロイ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/eb155d2a-5e7e-91d2-dc46-c49a14a9a178.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/a2c8bc82-e362-bd19-92d7-93805ecca09e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/105a1a22-ac52-d642-0ac2-ff414827642b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/df1c5098-0622-7b77-4c0c-8def242abbfa.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/131aaefb-db02-89d2-8e62-3f1d7d0ad6d4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/d82b8ee8-057a-57b7-2e27-54fa736bad21.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/bd1d322e-2e8f-8cb6-de7a-dce2e03aa8c4.png)


### 実行

上記のURLに置き換えてね

```bash
curl -d '{"recipient":"your_name@gmail.com","subject":"タイトル","body":"本文"}' https://script.google.com/macros/s/Deployment_ID/exec
```
【Swift】省略語の変数名について

# はじめに
チーム開発を始めて、ちゃんとした命名をできるように心がけるようになりました。
省略語のパスカルケースやキャメルケースはどのようにすればいいのか気になったので調べてみました。

# 省略語の例
- URL → Uniform Resource Locator
- ID → Identification
- API → Application Programming Interface
- UTF8 → UCS Transformation Format 8

# 結論
⭕️: 全て大文字 or 全て小文字
例) URL, ID, API, UTF8, url, id, api, utf8

❌: 先頭だけ大文字 or 先頭だけ小文字
例) Url, Id, Api, Utf8, uRL, iD, aPI, uTF8

# API Design Guidelines(Naming)
https://www.swift.org/documentation/api-design-guidelines/#conventions

![IMG_2782.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d0beb2f1-c358-0d1e-0f70-9b1fbd44abc1.jpeg)

# おわり
認識が間違っていればコメントで教えて欲しいです
Terraform：element、lookup関数の使い方

# はじめに
Terraformのelementおよびlookup関数は、リストやマップから値を取得するために利用できます。使いこなすことで、コード量が少なくなり、管理がしやすくなります！

# element(list, index)
element関数は、指定されたインデックスにあるリスト内の要素を返します。主にリストから値を取得する際に使用されます。この関数を空のリストで使用すると、エラーが発生します。
```
variable "example_list" {
  default = ["a", "b", "c"]
}

output "example_element" {
  value = element(var.example_list, 1)
}
```
この例では、example_elementの出力はbになります。

## 引数

### list (必須)
要素を検索する対象のリストです。リストは、順序付けされた値のコレクションです。

### index (必須)
list から取得したい要素のインデックス（0から始まる整数）です。もし、このインデックスがリストの範囲外の場合、エラーが発生します。

# lookup(map, key, [default])
lookup関数は、指定されたキーに対応するマップ内の値を返します。キーがマップに存在しない場合、オプションで指定されたデフォルト値を返します。デフォルト値が指定されておらず、キーが存在しない場合、エラーが発生します。この関数は主にマップから値を取得する際に使用されます。

```
variable "example_map" {
  default = {
    "a" = "apple"
    "b" = "banana"
    "c" = "cherry"
  }
}

output "example_lookup" {
  value = lookup(var.example_map, "b", "default_value")
}
```
この例では、example_lookupの出力はbananaになります。キーが存在しない場合（例: "d"）、出力はデフォルト値（この場合はdefault_value）になります。

これらの関数を組み合わせることで、リストやマップから効果的に値を取得し、Terraform設定の柔軟性を向上させることができます。

## 引数

### map (必須)
検索対象のマップ（またはオブジェクト）です。キーと値のペアが含まれているデータ構造です。

### key (必須)
map から取得したい値に関連付けられたキーです。もし、このキーがマップに存在しない場合、default 引数が指定されていればそれが返されます。default 引数が指定されていない場合、エラーが発生します。

### [default] (オプション)
オプションの引数で、key が map に存在しない場合に返すデフォルト値です。この引数が指定されていない場合、キーが見つからないとエラーが発生します。
Pyvista の StructuredGrid  をわかりやすく初期化する方法

TL;DR  `np.meshgrid`  を呼び出すときにオプション `indexing='ij'` を指定するのが良いです。



## 状況

Pyvista で、RectilinearGrid や StructuredGrid を初期化するときに、奇妙な振る舞いを見つけました。
ちなみに Windows11, Python 3.9, Pyvista 0.37, Numpy 1.14 で確認しました。

以下のコードを実行したときの `RectilinearGrid` と `StructuredGrid` の Dimension  を見てみます。

```
import numpy as np
import pyvista as pv
xrng = np.arange(-10, 10, 2, dtype=np.float32)
yrng = np.arange(-10, 10, 5, dtype=np.float32)
zrng = np.arange(-10, 10, 1, dtype=np.float32)

grid_rl = pv.RectilinearGrid(xrng, yrng, zrng)

x, y, z = np.meshgrid(xrng, yrng, zrng)
grid_st = pv.StructuredGrid(x, y, z)
```

このコードは、https://docs.pyvista.org/version/stable/api/core/_autosummary/pyvista.StructuredGrid.html を参照して書きました。

RectilinearGrid `grid_rl` は 10 x 4 x 20 になります。

```
In [2]: grid_rl 
Out[2]: RectilinearGrid (0x1e7a21991c0)
N Cells:      513
N Points:     800
X Bounds:     -1.000e+01, 8.000e+00
Y Bounds:     -1.000e+01, 5.000e+00
Z Bounds:     -1.000e+01, 9.000e+00
Dimensions:   10, 4, 20
N Arrays:     0
```

StructuredGrid `grid_st` は  4 x 10 x 20 です。

```
In [3]: grid_st 
Out[3]: StructuredGrid (0x1e7a21b1760)
N Cells:      513
N Points:     800
X Bounds:     -1.000e+01, 8.000e+00
Y Bounds:     -1.000e+01, 5.000e+00
Z Bounds:     -1.000e+01, 9.000e+00
Dimensions:   4, 10, 20
N Arrays:     0
```

 cell_data の先頭に値を入れて plot で様子を見ます。

```
grid_st.cell_data["idx"] = np.zeros(grid_st.n_cells)
grid_st.cell_data["idx"][:3] = np.arange(3)
grid_st.plot(show_edges=True)
```

![StructuredGrid_y_first.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38979/5f56d459-0ce1-e71b-73d9-d1b6e0fad81d.png)


最初に y 軸方向に変化するようになっていることがわかります。この状況は「わかりやすくない」ので、初に x 軸方向に変化するようにしたくなります。
RectilinearGrid の場合は、x軸、y軸、z軸の順に変化します。こちらのほうが「わかりやすく」て使い勝手の良いふるまいです。
## どうしてこうなるのか

少し調べてみると、これは `pyvista` の問題ではなくて、`numpy` の `mesh_grid` の挙動に沿ったものです。https://numpy.org/doc/stable/reference/generated/numpy.meshgrid.html Returns: のところを見ると

> For vectors *x1*, *x2*,…, *xn* with lengths `Ni=len(xi)`, returns `(N1, N2, N3,..., Nn)` shaped arrays if indexing=’ij’ or `(N2, N1, N3,..., Nn)` shaped arrays if indexing=’xy’ with the elements of *xi* repeated to fill the matrix along the first dimension for *x1*, the second for *x2* and so on.

と書いてあります。つまり、デフォルトの  indexing = 'xy' だと、`(N2, N1, N3)`  の配列を返すと書いてあります。それで、y-x-z の並び順になるようです。

## 対応法

```
x, y, z = np.meshgrid(xrng, yrng, zrng, indexing='ij')
grid_st = pv.StructuredGrid(x, y, z)
```

とします。

```
In [18]: grid_st
Out[18]:
StructuredGrid (0x1edb3031340)
  N Cells:      513
  N Points:     800
  X Bounds:     -1.000e+01, 8.000e+00
  Y Bounds:     -1.000e+01, 5.000e+00
  Z Bounds:     -1.000e+01, 9.000e+00
  Dimensions:   10, 4, 20
  N Arrays:     0
```

StructuredGrid `grid_st` も  10 x 4 x 20 となり、x 軸方向が最初の変化方向になっていることが確かめられました。
![StructuredGrid_x_first.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38979/b4f95c29-a644-86a0-bf2c-bae5848a49e9.png)

## 今後

Pyvista の StructuredGrid の説明ページを修正するようプルリクを書きました。
poetryについて

# Q: poetryとは

# A: poetryはpythonの仮想環境を作成するツールの１つです。

# Q: 他にたくさんある仮想環境との違いは？

他の仮想環境のツールとの違いに触れる前に、poetry以外にも多くの仮想環境があるため、それらについてあらましを説明します。


# pythonの仮想環境ツール一覧


## virtualenv
PyPIの歴史は古く、2007年にIan Bickingという人が開発したものです。
その後も改良が重ねられ、直近では2023年4月28日にバージョンアップが行われています。
virtualenvはPython2の環境との互換性があるため、レガシーなPython環境と新しいPython環境が入り交じるような場面で現在でも使用されています。

## venv
venvはPython3.3以降で標準ライブラリの一部として導入された仮想環境ツールです。
venv自体はvirtualenvの影響を大きく受けて、Pythonの標準ライブラリの一部として採用されたものになります。
Python環境の分離のための軽量なツールという位置づけられ、手軽に仮想環境の作成や管理が可能になりました。
ただPython3.3以降に実装だれている事から分かるようにPython2系との互換性はありません。

## conda
condaは、Anacondaで有名でご存じの方も多いかと思います。
AnacondaナビゲーターのようなGUIを提供していたりと特徴的なツールです。
元々データサイエンス、機械学習、大規模データ処理、予測分析・・etcのために作られたPython・R言語向けのツールです。
ただ、利用規約の改定により個人でも商用での利用は有償となっているいるようで、最近利用者が離れつつある印象です。（非商用であれば個人でも無償で利用出来ます）

## pipenv
pipenvは2017年頃、Kenneth Reitzという人が開発した仮想環境のツールです。ただ、現在PyPIを参照すると、作者が「Pipenv maintainer team」となっているため、何らかの理由で作者の座からおりたのかも知れません。
pipenvは、依存関係の管理や仮想環境の機能を"Pipfile"によって一元化することで、Pythonプロジェクトの開発プロセスを簡単にしようというコンセプトで開発されたものです。

## poetry
今回取り扱う”poetry”ですが、こちらは2018年頃に”Sébastien Eustace”という人により開発された仮想環境ツールです。Pythonプロジェクトの依存関係管理、仮想環境の作成、パッケージのインストールとアップデート、そしてパッケージ化と配布を一元化して行う機能を提供し、Pythonプロジェクトの開発・配布を容易にするというコンセプトで開発されたものです。

## pyenv
pyenvをここで取り上げていいかどうかは微妙ですが、説明の都合もあるため取り上げます。
pyenvは2012年にYamashita, Yukiという人によって開発されたもので、本来はPythonのバージョン管理ツールです。ですが、pyenv-virtualenvというプラグインを利用することで仮想環境の管理も行えるようにもなります。複数のPythonのバージョンをシステムにインストールし、プロジェクトごとに使用するPythonのバージョンを切り替えることができます。pyenvのバージョン管理機能の特徴は、システムにインスールされてないバージョンのpythonであってもpythonの公式サイトからダウンロードして自動的にインストールしてくれる点です。

追記：pyenv自体はmacOSとLinuxに対応するのみで、WSL（Windows SubSystem For Linux）で使用する事は出来ますが、Linuxの仮想環境の中で動作するのみ為、Windows固有の機能にアクセス出来ません。
Windows環境で同様の機能を使用する場合は、pyenv-winというpyenvからフォークしたリポジトリを使用します。僕はWinodws環境で開発をすることが多いので、次回以降投稿する記事ではWindowsに対応したpyenv-winが中心になります（一応pyenvでの動作についてもフォローはするつもりです）。


# 結局なにが何だって？
poetryとその他の仮想環境のツールを比較する上で、パッケージ管理システムとして何が使われているかで分けるには1つの視点になります。

現在pythonでモジュール（パッケージ）インストールしたりアンインストールするさいpipを利用する方は多いのではないでしょうか？
逆にpip使わなくてどうやってモジュールなんてインストールするの？と思われるかも知れません。
ただ、モジュール管理に使用されるのは決してpipだけではないありません。
pipを使用してモジュール（パッケージ）の管理を**行う**、または**行う事が出来る**のは以下の仮想環境ツールです。

1. virtualenv
2. venv
3. pipenv
4. poetry
5. pyenv

上記のうちpipコマンドを使うことは出来るものの、pipコマンド使用すると本来その仮想環境ツールが想定している使用方法の趣旨から外れるため、pipコマンドの利用が推奨されていないものは以下になります。
3. pipenv
4. poetry

この2つの仮想環境ツールは元来非常に似通ったもので、pipenvとpoetryの大きな違いは以下の２点です。
1. 依存関係の解決速度
2. 当該仮想環境ツールに、パッケージのビルドとリポジトリへの公開を行う機能が含まれるかどうか。

1. の依存関係の解決速度については、poetryの方が早いとも言われますがあまり大きな差があるかどうかは微妙なようです。
2. の仮想環境ツールに、パッケージのビルドとリポジトリへの公開を行う機能が含まれるかどうかですが、これはpoetryにはその機能があり、pipenvにはその機能がありません。

# 総論

自分はパッケージのビルドとか公開なんかしないから関係ない、という方も多いと思いますが、使用する側から見て関係なくとも、Githubなどでリポジトリを公開する立場からすると大きな違いになります。

昨今、大規模言語モデルや自然言語処理の分野の様々なGithubリポジトリを目にすることが多くなりました。
それらのリポジトリの多くはpoetryが使用されています。
頻繁にパッケージをビルドしたりリポジトリを公開する側の手間を考えるとこの差は大きいためです。

また、頻繁に公開または更新されるリポジトリでは、Pythonのバージョンとの兼ね合いも問題化する事が多くあります。
そのためpythonのバージョンそのものを管理できるpyenvとpoetryの組み合わせた使用方法を知っていることで、昨今のリポジトリや、公開されているソースコードがPythonのバージョンや、モジュールの依存関係の問題で動作しない、という悩ましさから解放される点は多いと思います。

念のため本記事では、***どの仮想環境ツールが優れているといった優劣のお話しは一切しません***が、poetryやpyenvの基本的な使用方法について、今後の記事で、自分が覚えたことの備忘録もかねて、少しずつ公開していこうと思います。
Could not connect to Kotlin compile daemon

# 概要
以下のように怒られたのでメモ。

```
e: Daemon compilation failed: Could not connect to Kotlin compile daemon
```

# 原因
以下で説明されているように、Compose Compiler と kotlin のバージョンに互換性が無かった。

```
exception: error: this version (1.3.2) of the Compose Compiler requires Kotlin version 1.7.20 but you appear to be using Kotlin version 1.8.20 which is not known to be compatible.  Please fix your configuration (or `suppressKotlinVersionCompatibilityCheck` but don't say I didn't warn you!).
```

# 対応
[Compose to Kotlin Compatibility Map](https://developer.android.com/jetpack/androidx/releases/compose-kotlin) を参照して **Compose Compiler Version** と **Kotlin Version** の組み合わせを一致させる。

上記の場合、Compose Compiler Version と Kotlin Version の 1.3.2 と 1.7.20 という組み合わせに互換性がなかったわけなので、以下のように Compose Compiler Version を 1.4.6 に上げるか、kotlin のバージョンを 1.7.20 に変更する必要がある。

```kotlin:kotlinCompilerExtensionVersionの設定例
android {
    composeOptions {
        kotlinCompilerExtensionVersion = "1.4.6"
    }
}
```
弾性棒に係る不静定系の力学P45 発展例題2.23「材料力学演習(20221021)」をsympyでやってみた。

教えて下さい。
solveを2回で実行しています。(3回)
**solveを1回で実行できますか？**

# オリジナル
発展例題2.23 P45 ページの下の方です。
http://zairikiweb.starfree.jp/zai_enshuh/zai_enshuh_ver.3.3.pdf#page=50
＜「材料力学演習(20221021)一括(ver.3.3)」を勉強したい。
https://qiita.com/mrrclb48z/items/c3274daf5f7a99cfe027

# sympyで
＞具体的な数値が与えられているとき，解答の式に当てはめて計算するのはかなり厄介である．
＞いずれにしても，正しい式を立てることが大切．
勉強中

```python
from sympy import *
RA     =symbols('RA'     ,real=True)
N1,N2  =symbols('N1  N2' ,real=True)
L1,L2  =symbols('L1  L2' ,real=True)
d1,d2  =symbols('d1  d2' ,real=True)
l1,l2  =symbols('l1  l2' ,real=True)
A1,A2  =symbols('A1  A2' ,real=True)
EE1,EE2=symbols('EE1 EE2',real=True)
a1,a2  =symbols('a1  a2' ,real=True)
dT1,dT2=symbols('dT1 dT2',real=True)
my0=Eq(N1-N2+RA   ,0)
my1=Eq(N1*L1-N2*L2,0)
my2=Eq(d1         ,(N1*l1)/(A1*EE1)+a1*dT1*l1)
my3=Eq(d2         ,(N2*l2)/(A2*EE2)+a2*dT2*l2)
my4=Eq(d1/L1      ,-d2/L2)
N2_ans=solve(my1,N2)[0]
N1_ans=solve([my2,my3.subs({N2:N2_ans}),my4],[d1,d2,N1])[N1]
print("#N1=",numer(N1_ans)*L1*L2/(denom(N1_ans)*L1*L2).expand() )
print("#N2=",N2_ans)
N2_ans=solve([my0,my1],[RA,N2])[N2]
RA_ans=solve([my0.subs({N2:N2_ans})],[RA])[RA].simplify()
print("#RA=",RA_ans)
mySubs={L1:250,EE1: 90,l1:300,a1:20*10**(-6),A1:500,dT1:-25,
        L2:600,EE2:200,l2:250,a2:12*10**(-6),A2:250,dT2: 25
       }
N1_ans=N1_ans.subs(mySubs)
N2_ans=N2_ans.subs(mySubs).subs({N1:N1_ans})
print("#N1=",round(N1_ans,2),"#N2=",round(N2_ans,3)) 
#N1= L1*L2*(-A1*A2*EE1*EE2*L1*L2*a2*dT2*l2 - A1*A2*EE1*EE2*L2**2*a1*dT1*l1)/(A1*EE1*L1**3*L2*l2 + A2*EE2*L1*L2**3*l1)
#N2= L1*N1/L2
#RA= N1*(L1 - L2)/L2
#N1= 15.76 #N2= 6.567
```


`
①私の環境は,pycharmです。
②よく聞くのは、Jupyterです。
③web上で、上記のソースを「SymPy Live shell」に、コピー貼り付けでもできました。
黒背景の右上に、マウスを移動すると、コピーマークが発生します。
???　タブレット環境で、コピー貼り付けが実行できませんでした。???



https://live.sympy.org/


# Mathematicaで
勉強中

# 作図
勉強中
VSCodeのJupyter（.py）でマジックコマンドを使うと、Pylanceからエラーをくらう場合の解決策

※ VSCodeの`.py`をJupyter形式で使っていることを前提としています。


この形式でマジックコマンドを使うと、以下のようにエラーが出てしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194534/b0dfa41d-a91a-904a-bf02-500eaa2002c0.png)

元々`.py`ファイルはJupyter形式で扱うことは想定していないのでこのエラーは当然ですし、ブログラム実行時は問題なく動作します。
なのでこのエラーは無視して構わないのですが、エラーが出ている状態は気持ちが良くないので何とかしたいです。
あとこの状態だとフォーマッタによっては動作しないという問題も起こります。

そこで調べてみたところ、すでにこの問題への解決策がVSCode上に実装されていました。

https://github.com/microsoft/vscode-jupyter/issues/3263

# 解決策

1. VSCodeの「設定」を開く
1. 検索欄に「Magic Commands As Comments」と入力
1. 出てきた設定にチェックを入れる

設定の説明にはこう書いてあります。

> コード セルの解析時にシェル割り当て (#!)、行マジック (#!%) およびセル マジック (#!%%) のコメントを解除します。

この説明でなんとなくわかると思いますが、指定された形式のコメントをマジックコマンドとして実行時に解釈するというものです。

例えば、以下のようなコードでマジックコマンドが使えます。

```python
# %%
# !%%time
# 上のコメントがマジックコマンドとして解釈される。
print("Hello")
```

こうするとマジックコマンドは実行時以外はコメントとして認識されるため、エラーが出ることはありません。
【AWS】CloudFrontを使用しているアプリケーションでエラーが発生した場合の対処法

# 概要
CloudFrontを使ったアプリケーションを構築する中で、設定は正しいのに"Failed to load resource: the server responded with a status of 403"や404エラーが返却される場合がある。

# 対処法
CloudFrontのエッジサーバにあるキャッシュが古い可能性がある。
CloudFrontの「キャッシュ削除」から「キャッシュ削除を作成」を選択し、全てのファイル「/*」を対象にてキャッシュ更新を強制させるとエラーが出なくなる。

# その他の可能性
1. CloudFrontからS3のファイルにアクセス出来ていない。
・CloudFront側でOAIないしOACを作成し、S3のバケットポリシーにs3:GetObject権限を追加する。
・S3側のパブリックアクセス許可を有効にしてアクセスをフルオープンにする。
1. CloudFrontのデフォルトルートオブジェクトが設定されていない
・CloudFrontの「一般」にある設定の「編集」を選択し、「index.html」を指定する。
1. React等を使用している場合、適したディレクトリをアップロードしていない。
・(例えばReactの場合) `npm run build`を行った上で、「build」フォルダの中身を全てS3にアップロードする。
Azure VMでSSL対応のWebサーバを構築する①

<p>今回はAzure VMを契約してSSHで接続するとこまでやります。</p>
<p>Azureのアカウントとクレジットはある前提で進めます。</p>
<p>クレジットがない方はMicrosoft公式のお試し無料的なキャンペーンを使うといいかもしれません。</p>
<h1>背景</h1>
<h5>自作Webサーバがつくりたくなったけど、自分の端末はセキュリティ的に不安だし、AzureのクレジットがあったのでAzure VMでWebサーバを構築してみました。</h5>
<h1>このシリーズの概要</h1>
<p>①Azure VMを契約，SSHで接続</p>
<p>②VMに基本機能をインストール</p>
<p>③SSLに対応させる</p>
<h1>さっそく、Azure VMを契約する</h1>
<p>・Azure portal https://portal.azure.com/ にアクセスする。</p>
<p>・"Virtual Machines"を見つけてクリック</p>
<p>・Azure仮想マシンを作成（事前設定されたやつも選択肢に出てきますが無視しましょう）</p>
<h1>基本</h1>
<p>・リソースグループ:作成、適当に命名。</p>
<p>　仮想マシン名:適当に命名。</p>
<p>　地域はJapan East/West自分の方を選ぶ。</p>
<p>　可用性オプション:可用性ゾーンを選択。</p>
<p>　可用性ゾーン:Zone 1</p>
<p>　セキュリティの種類:Standard</p>
<p>　イメージ:CentOS-based 7.7 -64 Gen1</p>
<p>　VM アーキテクチャ:x64</p>
<p>　Azure Spot 割引で実行する:突然マシンが止まってもOKな人はオンに</p>
<p>　サイズ:すべてのサイズを表示、シリーズのグループ化を解除、B1ls
を選択　（ゴリゴリに使いまわす人、余裕が欲しい人はほかの方がよき）</p>
<p>　認証の種類:SSH 公開キー</p>
<p>　ユーザ名:命名（ログインするときに使うから控える）</p>
<p>　SSH公開キーのソース:新しいキーの組の作成/p>
<p>　キーの組名:命名</p>
<p>　パブリック受信ポート:選択したポートを許可する</p>
<p>　受信ポートを選択:HTTP(80)/HTTPS(443)/SSH(22)すべて選択</p>

<h1>ディスク</h1>
<p>　ホストでの暗号化:できないはず</p>
<p>　OSディスクサイズ:31GB</p>
<p>　OSディスクの種類:Standard HDD 他でもいいけどお値段が高い</p>
<p>　VMとともに削除:どちらでもOK消すときのことを考えよう</p>
<p>　Ultra Disk の互換性を有効にする:選択しなくていい</p>

<h1>ネットワーク</h1>
<p>・仮想ネットワーク:なければ新規作成、適当に命名</p>
<p>　サブネット:default</p>
<p>　パブリックIP:新規</p>
<p>　NIC ネットワーク セキュリティ グループ:Basic</p>
<p>　パブリック受信ポート:選択したポートを許可</p>
<p>　受信ポート:HTTP(80)/HTTPS(443)/SSH(22)すべて選択</p>
<p>　VM が削除されたときにパブリック IP と NIC を削除する:どちらでもOK消すときのことを考えよう</p>
<p>　高速ネットワークを有効にする:できないはず</p>
<p>　負荷分散のオプション:なし</p>
<h1>管理</h1>
<p>・システム割り当てマネージド ID の有効化:選択</p>
<p>　Azure AD でログインする:できないはず</p>
<p>　自動シャットダウンを有効にする:しないほうがいい（すると安くなる）</p>
<p>　バックアップの有効化:選択</p>
<p>　Recovery Serviceコンテナ:defaultvault（なかったら新規作成）</p>
<p>　ポリシーのサブタイプ:Standard(拡張は高い)</p>
<p>　バックアップポリシー:Default Policy</p>
<p>　バッチオーケストレーション:イメージの既定値</p>

<h1>監視</h1>
<p>いじらない</p>
<h1>詳細</h1>
<p>いじらない</p>
<h1>タグ</h1>
<p>いじらない</p>
<h1>確認・作成</h1>
<p>秘密鍵をダウンロード※超重要なくすな</p>

<h1>SSHログインツールのダウンロード</h1>
<p>私はTeraTermを使ったのでのっけます。ほかでもいいです。Windows向け</p>
<p>https://forest.watch.impress.co.jp/library/software/utf8teraterm/</p>
<p>普通通りのインストールでOKです。</p>
<p>Azure portal/VMを選択/今回作ったマシンを選択/パブリックIPアドレスをコピー</p>
<p>TeraTermを立ち上げてTCP/IPにペースト、SSHを選択</p>
<p>ユーザ名:マシンを作ったときに控えたやつ</p>
<p>認証方式 "RSA/DSA/ECDSA/ED25519を使う"を選択、参照し、さっきの秘密鍵を選択、接続</p>
<p>[ユーザ名@サーバ名]$ が表示されたらOK</p>

<h1>まとめ</h1>
<p>初心者からすると専門用語も多いし難しい。この辺りはネットにいくらでも上がっているので、わからなかったら調べてください。</p>
Linuxの確認コマンド

**Zennに新しい記事を投稿しました。
リンク先の記事をご覧ください。**

https://zenn.dev/log4cat/articles/linux-reference-commands

---

Linuxの仮想サーバーを引き渡された時にスペックなどを確認するために使ったコマンドのメモです。
(Fedora特有のもの含む)

AlmaLinux 9.1とCentOS 7.3で実行しました。

# スペックや構成の確認
```bash
lscpu #CPUの情報
cat /proc/cpuinfo #CPUの情報(コア数が多いと見づらい)
free -h #メモリの情報
df -hl #ストレージの情報
ip addr show #IPアドレス

cat /etc/os-release #ディストリビューション
uname -a #Linuxカーネルの情報
cat /proc/version #Linuxカーネルの情報
arch #マシンのアーキテクチャ (64ビットならx86_64とか表示される)
uname -m #archと同じ
echo $LANG #言語と文字コード

ls -l / #ルートディレクトリ直下の確認
cat /etc/group #存在するグループの確認
```

# パッケージの確認(RPM)
ここはFedora系のもの。
```bash
yum list installed #インストール済のパッケージ
yum list #インストール可能／済のパッケージ
```

# 運用状況の確認に使えそう
```bash
uptime #起動時間
last #ログイン履歴
top #システムのリソース使用状況
```
pandas.to_datetime: ミリ秒のフォーマットが異なる日時を変換する際、pandas 1.5.3と2.0.1で動作が異なる

# 環境
* Python 3.11.2
* pandas 2.0.1


# やりたいこと
文字列で表記された日時を、[pandas.to_datetime](https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html)関数でpandasのdatetimeオブジェクトに変換したいです。
ミリ秒のフォーマットは揃っていません。

```python
data = [
    "2023-01-01T15:58:12+09:00",
    "2023-01-01T15:58:12.345+09:00",
]
```

# 起きたこと
pandas 1.5.3では以下のコードで、pandasのdatetimeオブジェクトに変換できました。

```
In [9]: pandas.to_datetime(data)
Out[9]: DatetimeIndex(['2023-01-01 15:58:12+09:00', '2023-01-01 15:58:12.345000+09:00'], dtype='datetime64[ns, pytz.FixedOffset(540)]', freq=None)
```

しかし、pandas 2.0.1では`ValueError`が発生しました。

```
In [74]: pandas.to_datetime(data)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

File ~/.pyenv/versions/3.11.2/lib/python3.11/site-packages/pandas/_libs/tslibs/strptime.pyx:351, in pandas._libs.tslibs.strptime.array_strptime()

ValueError: time data "2023-01-01T15:58:12.345+09:00" doesn't match format "%Y-%m-%dT%H:%M:%S%z", at position 1. You might want to try:
    - passing `format` if your strings have a consistent format;
    - passing `format='ISO8601'` if your strings are all ISO8601 but not necessarily in exactly the same format;
    - passing `format='mixed'`, and the format will be inferred for each element individually. You might want to use `dayfirst` alongside this.

```

# 原因
当然ではありますが、変数`data`内の日時のフォーマットが異なるからです。
エラーメッセージを見ると、`data[0]`から日時フォーマットを`%Y-%m-%dT%H:%M:%S%z`だと推測して、`date[1]`の`2023-01-01T15:58:12.345+09:00`をパースしたことが分かります。

つまり、pandas2.0.1では以下のコードでも`ValueError`が発生します。

```
In [75]: pandas.to_datetime("2023-01-01T15:58:12.345+09:00", format="%Y-%m-%dT%H:%M:%S%z")
--------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

```

しかし、pandas 1.5.3ではエラーは発生しません。

```
In [15]: pandas.to_datetime("2023-01-01T15:58:12.345+09:00",format= "%Y-%m-%dT%H:%M:%S%z")
Out[15]: Timestamp('2023-01-01 15:58:12.345000+0900', tz='pytz.FixedOffset(540)')
```

この動きはpandas1.5.3のバグのようです。[^1]

[^1]: https://github.com/pandas-dev/pandas/issues/53016#issuecomment-1529473807

なお、Pythonの[datetime](https://docs.python.org/ja/3/library/datetime.html)モジュールではpandas2.0.1と同じ動きになります。


```
In [21]: datetime.datetime.strptime("2023-01-01T15:58:12.345+09:00",  "%Y-%m-%dT%H:%M:%S%z")
---------------------------------------------------------------------------
ValueError: time data '2023-01-01T15:58:12.345+09:00' does not match format '%Y-%m-%dT%H:%M:%S%z'
```

# 解決策
pandas 2.0.0 からは`fomat`引数に`ISO8601`を指定できます。

>“ISO8601”, to parse any ISO8601 time string (not necessarily in exactly the same format);


`format="ISO8601"`を指定すれば、ミリ秒のフォーマットが異なっていても（ミリ秒以外のフォーマットが異なっていても）pandasのdatetimeオブジェクトに変換できます。

```
In [78]: pandas.to_datetime(data, format="ISO8601")
Out[78]: DatetimeIndex(['2023-01-01 15:58:12+09:00', '2023-01-01 15:58:12.345000+09:00'], dtype='datetime64[ns, UTC+09:00]', freq=None)
```