OmniAICreator/Qiita-1.07M huggingface dataset:
時間経過によるDockerfileの再現性の劣化に対してどうするか


# あらすじ
最近、大学の卒業課題でDockefileを弄っている。
実験とかに使うDockerfile達はなんとなくGithubから持ってきている。その際に、一部のDockerfileがビルドに失敗し、実験が成立しない事態に直面した経験が何度かある。
Dockerを使う利点の１つに、どんな環境で実行しても出力結果は同じになるというものがある。だけど実際には、どんな環境で実行してもビルドエラーを吐く、再現性に対して中指立ててる悪夢のようなDockerfileが巷に点在している模様。
私の場合は経験からなんとなく、下手な書き方をすると、主にアップデートなどでDockerfileが本来意図していたビルドに失敗してしまうことは理解していた。
で、ここ最近[この論文](https://ieeexplore.ieee.org/abstract/document/9402069)と[この論文](https://ieeexplore.ieee.org/document/7962382)を読んだことで事態の深刻さを知ります。前者の論文ではGithubにて★10を超えるリポジトリに絞り、かつ少なく見ても約26%のDockerfileがビルドに失敗。後者の論文では560の代表的なリポジトリのうち34%はビルドに失敗するという報告がありました。
……マーフィーの法則よろしく、ビルド失敗の印象が強く残るからビルドに失敗するDockerfileが多いように感じているんだろうな～と思っていたんですけど、マジで多かったんですね……
# 本題
そんなこんなで、アップロードされてるのにいざ実行しようとするとビルドに失敗するDockerfile、いわゆる「壊れた」Dockerfileのせいで何度も痛い目に遭ったので、壊れないDockerfileを書くのに意識するべき点を書きなぐっていこうと思い、現在に至ります。
自分なりにDockerfileの再現性を保つために気を付けるべきことを纏めたみました。
#### 壊れる原因
主にこの4つに分けられます
①ファイル更新・追加・削除で、Dockerfileに修正が必要になったのに修正していない
②バージョン固定しないせいで、Dockerfileが意図しないバージョンを使用しようとしている
③Dockerfile更新した時にミスって、ビルド成立しない状態にしてしまった事に気付かない
④ビルド時に使ってたURLが壊れた

ファイルの更新によって破損するケースは、更新時にDockerfileをちゃんと保守してもらうしかないです。
ですが、最新バージョン・URL使用の2つを行った場合、時間経過によって、気づかない間にDockerfileは壊れます。この場合は、Dockerfileは時限爆弾を抱えているのと同じだと思った方がいいです。
Githubの約1/4を占めている破損したDockerfileの多くは、壊れた事に気付かないでDockerfileをアップロードした事が原因では無く、意図しない時限爆弾を仕込んだまま保守を忘れて廃墟と化した事が原因だと思われます。

#### 対処方法
それぞれこんな感じです
①実行環境を変える時は必ずDockerfileも編集する。
②むやみやたらにに最新版を使わない。ベースイメージ決定やインストールの際に、自分のプロジェクトがどのバージョンを必要しているのか把握する。
③Dockerfileを編集したらテストビルドして下さい。
④安易にURLを使用しない。そのURLは誰かが保守してるから使える訳です。

バージョン固定とURL封印だけで時間経過による破損の大多数は未然に防げます。ただ、バージョン固定はともかくURLは使わないといけないシーンとかもあるので、URLの方に関してはこういったリスクがある事を承知の上で使って下さい。
個人的shopifyで仕事している時にタブに置いておくリンク

# はじめに

shopify cliを使ったサイトの構築も2回目経験して開発時、タブに常時置いておくサイトも固まってきたので共有していきます。（おすすめあったら教えてください🙇‍♀️


# 環境構築時

### https://qiita.com/Zakime/items/c89d778b23bccce70ad0

- cliのversionが2系でちょっと古いけど初めて環境を構築する時にはわかりやすい

### https://shopify.dev/docs/themes/tools/cli

- 結局公式ドキュメントがいちばんいい

---

余談だけど、開発中cliで使用するコマンドは2つくらいしか使用してなかった。。。
```sh
shopify theme dev

shopify theme push
```

# 開発時

### https://shopify.dev/docs/api/liquid/objects/

- liquidのObjectがまとまっている
- collectionsの商品名の参照方法何だっけとか、ページのURLの出し方とかなんかあるたびに見ている

### https://www.shopify.com/partners/shopify-cheat-sheet

- shopifyが提供しているliquidのチートシート
- Objectについてもあるけど基本的にfilterとかtagを調べる時に使ってる

### https://shopify.github.io/liquid-code-examples/

- shopifyの基本的なコードのサンプルがある
- よくあるコードがあるから初期段階で組む時にコピペで使用したりする

### https://help.shopify.com/ja/manual/checkout-settings/refund-privacy-tos

- ポリシー関連のURL確認に使用する
- 特定商取引法に基づく表記
    - policies/legal-notice

### https://help.shopify.com/ja/partners/dashboard/managing-stores/test-orders-in-dev-stores

- テスト決済時のクレジットカードの入力内容確認に使用する

### https://help.shopify.com/ja/manual/payments/shopify-payments/testing-shopify-payments

- お問い合わせフォーム作成時に書き方確認する


# その他

### https://chat.openai.com/

- まあエンジニア的な立ち位置の人なら使ってると思うけどchatGPT
- shopifyについては情報が古くてあんまり役立つ機会が少ないし、間違うことも多々あるから使う機会は多くない
- どうしたらいいかわからない時など聞いていると解決の糸口になるからどうのようにググったらいいかわからない時やググっても解決しない時に使用している

### https://github.com/Shopify/dawn

- 初期テーマのDawn
- gitで見るというより、初期インストールしたコードで見ることが多いけど、初期テーマでやっているやり方とかを参考にする


# さいごに

個人的にはshopifyの記事をググってもcliを使って開発している人向けの記事は少ないから、公式ドキュメントを読むのがいいと思う

今後も良さげなサイトがあったら増やしていく予定です
iOS app を外注するときの設定について

# context
- iOS アプリの開発を外注する
- ソースでの納品ではなく app/binary での納品とする
- 外注先のエンジニアは少数
- Xcode 14以降を想定

# 方法
- Apple ID は当然shareしない
- Apple Distribution certificate/private key とかもshareしない
- Organization には Developer として入ってもらう。
    - このときアクセス可能なAppは当該appだけの設定にする
    - Access to Certificates, Identifiers & Profiles.はチェックする
        - これで Apple Delevelopment certificate は自動で設定される
        - これで 必要な provisioning profile は自動で設定される
- この開発者はArchiveビルドしたときの成果物は 外注元Team になっている (sign は Developmentのもの)

# 外部開発者にuploadまでやってもらう場合
Testflight ready までやってもらうということ
- `Access to Cloud Managed Distribution Certificate`をcheck

### リスクはあるか？
- appを制限しているし、別に問題ないと思えるが、どうか。
- adhoc distribution とかかなぁ。勝手に配ることができてしまうかも。
- いずれにしろ、submit する権限はない

# 外部開発者にuploadまでやってもらわない場合
- `Access to Cloud Managed Distribution Certificate`の checkはしない
- xcarchive をもらって、それを upload できる権限のひとの、Organizer に import (import っていうか double clickすればよい
- で、AppStoreに upload する

これでよいのかしら

# メモ
今日日 adhoc distribution とかしないなら Apple Distribution certificate ってどのタイミングでも必要はない、のだろうか
Ruby Gold 3.1のテストに2回落ちました

Ruby Gold 3.1の資格を受験して、2回落ちて3回目で合格できました。
rubyのバージョンが3に上がってからの、受験記録の記事はあまり数が多くないと感じたため、受験した中で、回答に迷った問題をまとめます。
点数の履歴は、70点、68点、80点でした。

なお、バージョン3の参考記事としては、下記が非常に参考になりました。
https://qiita.com/heysan/items/82bdfb7af4325f05e0e5

# 1問目
```ruby
a = _(1)_ # ここを問う問題
    Ruby Gold
    version 3
  EOS
puts a

(実行結果)
Ruby Gold
version 3
```
選択肢として、以下のようなものがでました。
1. <<~EOS
1. <<EOS.gsub(/ /, "")<<EOS.gsub(/ /, "")
1. <<-EOS.gsub(/ /, "")
1. <<-EOS.gsub(/^*/, "")
1. <<-EOS

# 2問目
```ruby
require 'forwardable'

class List
  extend Forwardable

  def initialize
    @contents = []
  end

  def_delegator :@contents, :push
end
begin
  list = List.new
  list.push("b")
  p list[0]
rescue
  puts "er"
end

[実行結果]
"er"# ここを問う問題
```
エラーが出るのか、出ないのかで迷いました。
extend Forwardableじゃなくて、includeだったっけ?
def_delegatorの定義が足りないか?など。

# 3問目
```ruby
def add(x:, y:, **params)
  p params
end

add(x: 3.75, y: 3, round: true)

[実行結果]
{:round=>true} # ここを問う問題
```
選択肢として、以下の用な感じのものがでました。
1. {:round=>true}
1. {round=>true}

# 4問目
```ruby
#　コード1
[1,2,3].each do |n|
  num = n
end
p num

#　コード2
num = 0
[1,2,3].each do |n|
  num = n
end
p num
```
コード1とコード2の実行結果を問う問題が出ました。

# 5問目
```ruby
class A
  def foo
    "foo"
  end
  private
  def bar
    "bar"
  end
end
obj=A.new
p　# ここを問う問題

エラーが出る選択肢を選ぶ
1. obj.send(:bar)
2. obj.public_send(:foo)
3. obj.private_send(:bar)
4. obj.__send__(:bar)
```
# 6問目
```ruby
class A
  @a=1
end
p A.instance_variables
```
結果の選択肢として以下のような感じで出ました。
1. [:@a]
1. [:a]
1. [@a]
1. [a]

# 7問目
```ruby
array=[1,2,3]
p array.lazy.take(3).force
p array.first(3)
p array.last(3)
```
詳しく覚えてないのですが、このような雰囲気の問題がでました。
【Rails API】「v1」とは何を表しているの？

Rails APIについて学習しています。

URL：`http://localhost:3000/api/v1/articles`や、
RL：`http://localhost:3000/api/v1/articles/[:id]`に、
アクセスした時のレスポンスとしてJSONを返すようなプログラムを実装しています。

その際、URLに指定する「v1」というワードが気になったので、調べてみました。

# 使用環境
- Ruby 2.6.6
- Rails 6.0.2.1
- jsonのserializer は fast_jsonapi を使用。

# テーブル
以下、モデル・テーブルを事前に準備していることを前提にしています。

- Userテーブル
- Profileテーブル
- Articleテーブル
- Commentテーブル


# 【本題】v1とは何を表しているの？

- それは一般的にAPIのバージョンを表している。
- APIの設計においては、後方互換性を壊さないように新しいバージョンを作ることがある。
- そのときに、v1やv2といった形でバージョンをURLに含めることが多い。


#### web APIのバージョンを管理する方法について

> いくつかバージョンの管理方法があるようなのですがURIにバージョンを埋め込むのがよく利用される方法のようです。


引用：[Rails APIのルーティングnamespaceってなんで使うの?](https://qiita.com/morioka1206/items/6a33885aed483bf46373 "Qiita")


#### 後方互換性とは
> 後方互換性は、言い換えれば、旧製品に対して互換性を持っている新製品の性質である。例えば、CDが再生できるDVDドライブは、CDの規格に対して後方互換性がある。

引用：[後方互換性とは？わかりやすく解説 Weblio辞書](https://www.weblio.jp/content/%E5%BE%8C%E6%96%B9%E4%BA%92%E6%8F%9B%E6%80%A7 "Weblio辞書")


# 最後に

全く別の例えですが、プレステ５でも、プレステ４のソフトが遊べます。

Rails APIにおいても、複数のバージョンを持っている事がわかりました。
複数のバージョンを提供する事で、不足の事態に備えるなどのリスク管理をしているわけですね。



# 参考サイト

https://www.weblio.jp/content/%E5%BE%8C%E6%96%B9%E4%BA%92%E6%8F%9B%E6%80%A7

https://qiita.com/morioka1206/items/6a33885aed483bf46373
SeleniumでChromeのバージョンがおかしくてSessionNotCreatedExceptionが出た件

# 発生事象

Macのローカル環境でSeleniumを使ってChromeを操作しようとしていたところ、以下のエラーが出ました。

```
SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 114
Current browser version is 66.0.3359.170 with binary path /Users/Toshiki/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
Stacktrace:
```

エラーの内容としては、ドライバーのバージョンがChromeの114にしか対応していないが、Chromeのバージョンが66.0.3359.170だといっています。
しかし、Chromeのバージョンをいくら確認しても、114でした。

# 結論
Chromeを再インストールしたら治りました。
再インストールの方法はこちらを参照ください。
https://estudiopersonal.com/archives/2948
Oracle Analytics Cloud：データセットで行レベルセキュリティを実現

# はじめに
行レベルセキュリティとは、データレベルセキュリティとも呼ばれ、データにアクセスするユーザやユーザグループに対して、個別に参照可能な行を制限することです。
Oracle Analytic Cloud（**OAC**）では、セマンティックモデルを使用して高度な行レベルセキュリティを設定できますが、セマンティックモデルを使用しないデータセットに対しても同種の定義が可能です。

# アプリケーションロールの確認
OACにログインし、「コンソール」メニューの「ユーザーとロール」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/592d5253-2aca-9e4e-77bb-33aa116d9b03.png)
「アプリケーション・ロール」タブを表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/9d34b406-4c14-24c2-2a8d-7bb495b251ab.png)
ここで表示されている3つのアプリケーション・ロールは、カスタムで追加したものです。
Role1とRole2に対してフィルタを設定します。

# データセットの用意
Excelからアップロードしたデータセットを使用します。
データセットを右クリックして「開く」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/53d87a86-085e-b514-9e42-05ed1a0f580d.png)

# 行制限を追加
データセットを開き、「結果ダイアグラム」タブからフィルタアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/b64916bb-cd6d-da8f-03b5-d3add3a7c879.png)
「ロールの追加」の「＋」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/ab65530f-6be9-2b52-3d64-0e225e88383f.png)
「Role1」をクリックして選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/2440c73b-5eed-5fa0-cd51-85bfa5145011.png)
フィルタの式を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/de6b9a4c-5c2e-951e-b992-eb45d15eade9.png)
「都道府県 in ('東京','神奈川')」と入力し、「適用」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/665812a6-6274-4257-5551-574739bb6aee.png)
もう一つ、フィルタを追加し「Role2」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/53f28b87-7877-33b9-7d1f-bb4d9189eb20.png)
Role2に対しては、「大阪」のみ検索できるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/528e1208-0db0-07a6-e7a6-ed318d4a4d47.png)
データセットを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/f91f6665-e6f3-88a7-3c3d-66ab298dec9b.png)
必要に応じて、データセットのアクセス権を適切なアプリケーションロールに設定します。

# 動作確認
アプリケーションロール「Role1」に所属するユーザでログインし、行レベルセキュリティを設定したデータセットを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/4c763a17-5ce1-d1ad-6e3a-7b92d0cbc760.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/7744dd62-69cd-0fa9-cbb0-ba8c4b34ed4e.png)
東京と神奈川だけのデータで可視化されました。
一度、OACからログアウトして「Role2」に所属するユーザでログインし、同じことをしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/5f87830d-3728-e775-3f16-c04cc7b11ccb.png)
所属するアプリケーションロールの違いによって、データセットの別の場所を参照するように設定できました。
paiza.ioでelixir その243

# 概要
paiza.ioでelixirやってみた。
Bump使ってみた。

# 参考にしたページ

https://github.com/evanfarrar/ex_bump

# サンプルコード

```

pixel_data = [[[0xFF, 0xFF, 0xFF], [0x00, 0x00, 0x00]], [[0x00, 0x00, 0x00], [0xFF, 0xFF, 0xFF]]]
Bump.write(filename: "file.bmp", pixel_data: pixel_data)
pixel_data0 = Bump.pixel_data("file.bmp")
|> IO.inspect

defmodule Run do
    canvas = Canvas.size(%Size{ height: 400, width: 400 }) 
        |> Canvas.fill(color: Color.named(:red))
    |> IO.inspect
    Bump.write(filename: "red.bmp", canvas: canvas)
    canvas2 = Canvas.fill(canvas, color: Color.named(:blue), rect: %Rect{ size: %Size{height: 200, width: 200}, origin: %Point{x: 100, y: 100}})
    |> IO.inspect
    Bump.write(filename: "redblue.bmp", canvas: canvas2)
end


```

# 実行結果

```
[[[255, 255, 255], [0, 0, 0]], [[0, 0, 0], [255, 255, 255]]]
%Canvas<pixels: PIXEL_DATA>
%Canvas<pixels: PIXEL_DATA>

```

# 成果物

https://paiza.io/projects/uJdYVovXA6tm1FSJ4MQIAQ

以上。
Salesforce 会社設定について分かりやすく解説してみた

こんにちは
本橋孝昭です


今回はSalesforceの会社設定について分かりやすく説明します

https://youtu.be/1jpwALKMxuA

<iframe width="560" height="315" src="https://www.youtube.com/embed/1jpwALKMxuA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


# Salesforce会社設定を覚えたら何ができるの？

これらを設定すれば自分の会社にあった会計年度や言語設定、営業時間の変更をすることが可能です

基本的には
・毎日変更する設定
ではないかと思いますが、Salesforceを最初に導入する際は、ぜひ貴社の会計年度の設定や営業時間の設定などしてください

そして、数年に１度は
・会計年度
の変更などあると思いますので、現在のSalesforceシステム管理者は
「こんな設定もあるんだね」と思っていただければと思います
そして、現状の会社の設定はきちんと設定されているのか？を確認いただけらばと思います

会社の設定をする部分はいくつかに分かれているので、まずは設定部分を解説します


## 主に「組織情報」　からできること

### ユーザライセンス数の閲覧
### 会計年度期首月	の閲覧（設定変更は「会計年度」から）
### マスタ通貨　の設定(マルチ通貨が有効でない場合)
### マルチ通貨の有効化
### 地域のデフォルト値
### 言語のデフォルト値

## 主に「通貨管理」　からできること（マルチ通貨有効の場合）
### マスタ通貨　の設定


## 主に「営業時間」からできること

### 営業時間の設定


## 主に「会計年度」からできること

### 会計年度期首月の変更

それぞれできることを解説します

## 主に「組織情報」　からできること

### ユーザライセンス数の閲覧
現状使用できる（Salesforceと契約している）Salesforceライセンスの確認が可能です
もしもライセンス数の増減希望があればSalesforceの営業にお問い合わせください

### 会計年度期首月	の閲覧（設定変更は「会計年度」から）
会計年度の期首月の閲覧のみができます。会計年度の期首月の変更を希望する場合後述の「会計年度」から設定変更してください

### マスタ通貨　の設定(マルチ通貨が有効でない場合)
マルチ通貨が有効でない場合、マスタ通貨の管理が可能

### マルチ通貨の有効化
　マルチ通貨の有効が可能。なお、マルチ通貨を有効にしたら無効にすることはできない設定なので有効前にはPlaygroundなどデモ環境で要確認がおすすめです

### 地域のデフォルト値

### 言語のデフォルト値



## 主に「通貨管理」　からできること（マルチ通貨有効の場合）
### マスタ通貨　の設定
マスタ通貨が有効の場合、「通貨管理」からマスタ設定が可能です


## 主に「営業時間」からできること

### 営業時間の設定
営業時間の設定は「営業時間」からです
もしも営業時間を設定すればエスカレーションルールで営業時間を考慮したエスカレーションが可能です

そのほかの営業時間の詳細についてはこちらのリンクからご確認お願いします

営業時間の設定
https://help.salesforce.com/s/articleView?id=sf.customize_supporthours.htm&type=5

ケースのエスカレーションルールの解説はこちらの動画から

https://youtu.be/0HXmr2H1VOI


## 主に「会計年度」からできること

### 会計年度期首月の変更

会計年度はレポートの「今年度」「四半期」などで使われます
デフォルトは「1月」になってますが多くの会社の期首月は１月ではないはずなので、まだデフォルトの設定のままの会社は要変更を検討してみてください

# まとめ

会社設定について、あまり確認したことが無いと思いますのでぜひこの機会にご確認ください

なお、会社設定についてもっと深く知りたい方はこちらのTrailehadをお勧めします

https://trailhead.salesforce.com/ja/content/learn/modules/company_wide_org_settings/org_settings_regional
NDVI（植生指数）を求める際になぜ赤色光が必要なのか

### NDVIってそもそも何？
NDVI（Normalized Difference Vegetation Index）は緑植生の茂り具合を示す指標のことです。主にリモートセンシング、衛星画像解析などをする際に使われるものです。

NDVIについては宙畑さんがわかりやすく説明していたので、詳しくは以下の記事を参考にしてみてください。

https://sorabatake.jp/5192/

### 疑問に思ったこと
近赤外線の反射量だけ調べれば、植生指数って求めれられるのでは？赤色光って計測する必要ってあるのか？


### 疑問を持った背景
NDVIは緑植生の茂り具合を示す指標。つまり、どこに植物が生い茂っているのか、またそうでないのかを示すものという理解していました。であれば、近赤外線だけを計測すればNDVIって求まるのでは？と思いました。なぜ、NDVIを求める際に赤色光が必要になるのかを理解できませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467847/88ee0a7c-a206-1693-29a9-fe6767de2c69.png)
引用画像：[宇畑「課題に応じて変幻自在？ 衛星データをブレンドして見えるモノ・コト #マンガでわかる衛星データ」](https://sorabatake.jp/5192/)

### ChatGPTに聞いてみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467847/df97fba2-fade-7d4b-5492-702856978d45.png)

なるほど。健康な植物（=光合成を行っている）の量を計測するために、赤色光の計測が必要なわけですね。緑植生が近赤外線を反射するという特性と、光合成の際に赤色光を吸収する特性を活用することで、健康状態である緑植生の茂り具合を判定できるんですね。

NDVIはただ単に植物の茂り具合だけでなく、植物の状態をも反映している指標ということがわかりました。
Javaの修飾子まとめ

## はじめに

Javaの修飾子(modifiers)は、クラス、メソッド、または変数の振る舞いを変更するために使われます。修飾子を理解することは、Javaコードを読み、書く際に役立つでしょう。今回は、Javaの主要な修飾子とその使用例を解説します。

## アクセス修飾子

Javaには4つのアクセス修飾子があります。

1. **public**: どのクラスからでもアクセス可能です。
2. **private**: 同じクラス内からのみアクセス可能です。
3. **protected**: 同じパッケージ内、またはサブクラスからのみアクセス可能です。
4. デフォルト (指定なし): 同じパッケージ内からのみアクセス可能です。

```java
public class MyClass {
    public int publicVar = 1;
    private int privateVar = 2;
    protected int protectedVar = 3;
    int defaultVar = 4;
}
```

## 非アクセス修飾子

### クラス修飾子

1. **final**: サブクラスを作成できません。
2. **abstract**: インスタンス化できず、1つ以上の抽象メソッドを持たなければなりません。
3. **strictfp**: そのクラスの中の全てのメソッドと内部クラスで浮動小数点の精度が一定であることを保証します。

```java
public final class MyFinalClass { }
public abstract class MyAbstractClass {
    public abstract void myMethod();
}
public strictfp class MyStrictfpClass { }
```

### メソッド修飾子

1. **final**: メソッドのオーバーライドを禁止します。
2. **static**: インスタンスではなく、クラス自体に属するメソッドにします。
3. **abstract**: メソッドの本体がなく、サブクラスでオーバーライドする必要があります。
4. **synchronized**: 同時に複数のスレッドがアクセスできないようにします。
5. **native**: Java以外の言語で書かれたコードを使用します。
6. **strictfp**: メソッド内で浮動小数点の精度が一定であることを保証します。

```java
public class MyClass {
    public final void finalMethod() { }
    public static void staticMethod() { }
    public abstract void abstractMethod();
    public synchronized void syncMethod() { }
    public native void nativeMethod();
    public strictfp void strictMethod() { }
}
```

### フィールド（変数）修飾子

1. **final**: 値が一度だけ設定できます。再割り当ては不可能です。
2. **static**: インスタンスではなく、クラス自体に属するフィールドにします。
3. **transient**: オブジェクトのシリアル化時に、このフィールドは無視されます。
4. **volatile**: このフィールドは常にメインメモリから読まれ、スレッド間での同期が保証されます。

```java
public class MyClass {
    public final int finalVar = 1;
    public static int staticVar = 2;
    public transient int transientVar = 3;
    public volatile int volatileVar = 4;
}
```
PythonのFastAPIをCloudRunにデプロイするときにはまった

かなりはまったので、雑にメモする。

## 環境
- python3.10.12
- poetry1.5.1

## やりたかったこと
PythonのFastapiで作ったサンプルアプリケーションを、gcpのCloud Runにデプロイしたかった。  
以下のようなDockerfileを作った。

```dockerfile
# python3.10のイメージをダウンロード
FROM python:3.10.12-slim-bullseye AS base
..
..

FROM base as production
RUN poetry config virtualenvs.in-project false
..
..
# uvicornのサーバーを立ち上げる
CMD poetry run uvicorn app.main:app --host 0.0.0.0 --port $PORT
```

ローカルでdocker runしたときはこれで問題なくサーバー起動していたし、gcpにアップされたイメージをpullして、docker runしても、問題なくサーバーが起動していた。

## 実際に起こったこと
Cloud Runにデプロイすると、起動エラーになってしまい、メッセージは指定されたポート番号でサーバーが起動しない、というようなもの

## 修正した箇所1
なぜだめなのかは正直まだよくわかっていないのだが、サーバー起動時にpoetryを指定するのではなくて、直接uvicornをたたかないとダメっぽい。

```
CMD uvicorn app.main:app --host 0.0.0.0 --port $PORT # poetry runは不要
```

## 修正した箇所2
これは自分のミスで、docker内は自由に使えるのでpoetryが作成する仮想環境はグローバルにいれればよかったのだが、`virtualenvs.in--roject`と`virtualenvs.create`を取り違えており、poetryがグローバルに入っていなかった。

```
# docker内は自由に使えるのでpoetryが作成する仮想環境はグローバルにいれる
RUN poetry config virtualenvs.create false
```
16章 重回帰分析

# 重回帰分析
$X^{\top}X $が可逆であることから、$X^{\top}X $が正定値行列である。このとき、すべての$x{\in}\mathbb{R}^N$に対して、$x{\neq}0$であれば$xX^{\top}Xx^{\top}>0$であり、$x=0$のとき$xX^{\top}Xx^{\top}$が最小(0)となる。

## 射影行列による理解
$P^2=P$かつ$P^{\top}=P$を満たす正方行列$P$を射影行列という
${P_X}^2=X(X^{\top}X)^{-1}X^{\top}X(X^{\top}X)^{-1}X^{\top}=X(X^{\top}X)^{-1}X^{\top} ={P_X} $

$X$の像$Im(X)$への射影になっている
https://qiita.com/takseki/items/e0de89ab82d4d287a0d7#fn3


>行列$A$の列ベクトルたちの張る空間を列空間と呼ぶことにする
このとき、$A$の列空間への射影行列は $ A (A^T A)^{-1} A^T $ であることが知られている

https://qiita.com/takseki/items/8114eb537a7fe78ca8f8

![pKi5AMY-.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567074/dcb787b3-a68c-17b3-2d37-6f308f20337e.jpeg)


# 例題16.1
(1)
- 自由度調整済み決定係数（Adjusted R-squared）の値が出力されているので、その値を比較する。

(2)
- 0.05以上の場合、棄却域に入っているのはGENとAMTの二つ。

 ## 重回帰分析の検定
$\beta_k$がゼロか非ゼロかを検定することにより、変数$x_k$が有意に影響しているかどうかを判定することができる。one-hotベクトルのような行列$A$を導入することで帰無仮説・対立仮説を定式化できる。

ある$\beta$がゼロである場合の最小二乗推定値を${R_0}^2$、すべての$\beta$が非ゼロである場合の最小二乗推定値を${R_1}^2$とし、統計検定量$T$=(省略)を考えると、これは自由度$（q,n-d-1）$の$F$分布に従う、この$T$を$F$統計量という。
詳しくはwikiを参照

# 例題16.2
(1)
p130の真ん中あたりに記載の性質を使う。
変数$\beta_5=0$を帰無仮説とすると、この仮定の下で$\frac{\hat{\beta}_5}{\hat{\beta}_5の標準偏差の推定量}$が自由度111-5-1=105のt分布に従う統計量となる。(p130の真ん中あたり参照)
$\beta_5$(Day)の推定値は、モデル2の出力を読み取ると$0.27388$
$\beta_5$(Day)のt統計量は、$0.27388/0.22967\approx1.1925$
p320のt分布の確率表を見ても、p値は0.1を上回っており有意とは言えず、帰無仮説を棄却できない

(2)
- 決定係数の観点では、モデル2のほうが優れている。
- F統計量の観点では、モデル1のほうが優れている。
-- p323の表から、自由度（5,105）の上側確率5％内に入るには、F統計量が2.5以上あれば十分。
- AICはモデル1が優れている。
-- AICはp288に記載されている通り、小さいほうが優れている。

# 例題16.3
(1)
平均二乗誤差が一番小さくなるのは、$e^{-6}$だが、交差検証の結果を見ると1のときが最も誤差の値が低く汎用的である。バランスをとって$\lambda=1$が最適

(2)
$\lambda=0$(正則化なし)の場合は、モデルがデータに過剰に適合しようとして$\beta$の値のばらつきが大きくなる。
αが大きいほど、$L_1$正則化の影響が強くなる。$L_1$正則化の性質として、$\beta$の値が厳密に0になるという（スパース性）があるので、$\alpha=1$、$alpha=0.5$の順に、係数がゼロとなっているグラフが多いものを選べばよい


(3)
回答のとおり
Flutter + Laravel + ngrok

### 【ngrokとは】
ローカルホストに展開されたWebサーバーやデータベース、APIを一時的なURLを通じてインターネットに公開するためのツールです。
これはトンネリングソフトウェアと呼ばれ、インターネット上の他のマシンから自身のローカルで実行されているアプリやサーバーに外部からアクセスすることが可能になります。
リアルタイムのデバッグやテスト、デモンストレーションなどにとても便利です。

一部の基本機能を無料で提供していますが、追加機能を利用するためには有料プランにアップグレードする必要があります。



ngrok公式サイトはこちら
https://ngrok.com/


### 【開発環境】
Flutter 3.7.7
Dart 2.19.4
Laravel 8.70.2
ngrok 3.3.1

今回はFlutterとLaravelでのAPI通信に使用しました。
スマホアプリを開発していると、API通信でローカルサーバーまでのネットワーク経路を作る必要があると思います。
私自身、仕事でローカルサーバーにアクセスをして開発をしていたのですが、困った事が発生した為、同僚に相談をしたところngrokを紹介して頂きました。
初めて使ってみて凄く便利でしたしサクッとできるので紹介したいと思います。

ngrokの導入手順はここでは紹介しません。

### 【API通信方法】
1. ngrokを外部公開する
2. Flutterでngrokで発行されたURLを指定する
3. Laravelで通信が来ているか確認する



#### １.ngrokを外部公開する
###### ①コマンドラインを開きます。
 WindowsではCommand PromptやPowerShellを、MacではTerminalを開きます。


###### ②ngrokを実行します。 
ローカルネットワーク上のアプリを公開するには、そのアプリケーションが稼働しているポートを指定する必要があります。例えば、アプリケーションがlocalhostのポート8080で稼働しているとすれば、以下のコマンドを実行します：
```bash
./ngrok http 8080
```
ngrokを実行すると、以下のような出力が表示されます：
```css
Session Status                online
Account                       your_email@example.com (Plan: Free)
Version                       3.3.1
Region                        Japan (jp)
Web Interface                 http://127.0.0.1:4040
Forwarding                    https://your-random-subdomain.ngrok-free.app -> http://localhost:8080

```
API通信で利用するURLは   Forwarding  のhttps://xxxxxxxxx.app までになります。


#### 2.Flutterでngrokで発行されたURLを指定する
```dart
http.get(Uri.parse(https://xxxxxxxxx.app/laravel/api);
```


一点注意が必要です。
ngrokは一時的に外部へ公開しているだけなので、ngrokが稼働している間だけ有効となります。
ngrokを再起動すると新たなURLが生成されるのでForwarding のURLが変更されます。
ですので、その都度Flutterで指定したURLを変更しないとAPI通信ができません。
もし、通信できないなどの時はURLも疑ってみてください。


#### 3.Laravelで通信が来ているか確認する 
```public/index.php
if (file_exists(__DIR__.'/../storage/framework/maintenance.php')) {
    require __DIR__.'/../storage/framework/maintenance.php';
}
```
上記のコードの部分にブレークポイントをはる。
FlutterでAPIを叩いて、ブレークが止まれば通信が来ているので成功です。



#### 【最後に】
ngrokはローカルネットワーク上のアプリケーションを公開することができますが、セキュリティには十分注意する必要があります。しかし、今回紹介をしていませんがngrokは簡単に導入する事がき、時間や費用の削減ができる事、発行したURLは停止しない限り時間無制限でアクセスできる事も魅力の一つだと思います。お時間あれば一度使用してみてください。
[ERC5192] NFTを送付できなくする『SBT』について理解しよう！

# はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回の記事では、**ERC721**規格のNFTをSBT（Soul Binding Token）化するための企画である、**ERC5192**についてまとめていきます！

:::note info
以下を参考にまとめていきます！
:::

https://eips.ethereum.org/EIPS/eip-5192

:::note info
ERC721については以下の記事を参考にしてください！
:::

https://chaldene.net/erc721

# 要約

この規格はEEC721規格のNFTの拡張で、EIP165のチェック機能を用いてNFTをソウルバウンドにする提案しています。
SBT（ソウルバウンドトークン）は、1つのアドレスに紐づけられたNFTで、他のアドレスに送ることができなくなります。

:::note warn
この記事では、**SBT ≒ 送付できないNFT**として用語を使用します。
:::

# 動機

Ethereumコミュニティでは、非譲渡性（送れない）、非代替性（交換できない）、社会的価格設定のトークンに対するニーズがあると考えられています。
しかし、特定の規格がないため、多くの開発者がNFTの送付機能の呼び出しに対してエラーを発生させるだけになっています。
この問題は長期的に見ると、機能の断片化と組み合わせ可能性の低下をもたらします。

この提案では、**EIP165**を使用したウォレットの実装者が、コントラクトに対してSBT対応しているかを確認できるように、**ERC721**に最小限の追加提案します。

# インターフェースの実装
uint256のtokenIdを持つトークンは、関数locked(...)がtrueを返す場合、受け取りアカウントに結びつけられることがあります。この場合、契約のすべてのEIP-721関数は、トークンを一つのアカウントから別のアカウントへ転送する機能がスローされなければなりません。

```javascript
interface IERC5192 {
  event Locked(uint256 tokenId);

  event Unlocked(uint256 tokenId);

  function locked(uint256 tokenId) external view returns (bool);
}

```

### Locked

Lockステータスが『**Locted**』に変更されたときにログに記録します。
NFTがMintされたあと、ステータスが『**Locted**』に変更されるときに発行されます。

### Unlocked

Lockステータスが『**UnLocted**』（ロック解除）に変更されたときにログに記録します。
NFTがMintされたあと、ステータスが『**UnLocted**』（ロック解除）に変更されるときに発行されます。

### locked

SBTのロックステータスを返す関数。
`0アドレス`が所有者となっているNFTは無効とみなされ、エラーなどを起こさせるようにする。

**引数**
- `tokenId`
    - 確認したSBTのトークンID。

### その他

**ERC721**内の関数`supportsInterface(bytes4 interfaceID)`が`interfaceID=0xb45a3c0e`の時、**ERC721**トークンがSBT対応していることを認識するために、`true`を返さなければならない。


# 最後に

今回はNFTをSBTにする**ERC5192**についてまとめてきました。
実装については今後追記していきます！
いかがだったでしょうか？
質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

# 採用強化中！

CryptoGamesでは一緒に働く仲間を大募集中です。

https://www.wantedly.com/companies/cryptogames

この記事で書いた自分の経験からもわかるように、裁量権を持って働くことができて一気に成長できる環境です。
「ブロックチェーンやWeb3、NFTに興味がある」、「スマートコントラクトの開発に携わりたい」など、少しでも興味を持っている方はまずはお話ししましょう！
androidのapkをapksignerでverifyする


apksignerと署名スキームのページが若干ばらついているのとv4の検証コマンドがサイトにないためまとめる<br>

# apksignerとは

https://developer.android.com/studio/command-line/apksigner<br>
Android SDK Build Toolsに含まれており、apkの署名と署名の検証ができる<br>

# apk署名スキーム
v1からv4まで存在する

| version | 特徴 | リンク |
| --- | --- | --- |
| v1 | JARベースの署名スキーム | https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Signed_JAR_File |
| v2 | **android7**から使用可能<br>apkの無許可変更を許容しない | https://source.android.com/docs/security/features/apksigning/v2 |
| v3 | **android9**から使用可能<br>鍵のrotationが可能になった | https://source.android.com/docs/security/features/apksigning/v3 |
| v3.1 | **android13**から使用可能<br>v3のバグ修正パッチが当たっている | https://source.android.com/docs/security/features/apksigning/v3-1 |
| v4 | **android11**から使用可能<br>apkの全バイトに対して署名計算を行う<br>互換性の高めるためにv2もしくはv3での署名も必要 | https://source.android.com/docs/security/features/apksigning/v4 |

# 署名する
## Gradle
build.gradleからMin SDKとTarget SDKを読み取って署名スキームを良しなに使い分けてくれる<br>
signingConfigs内の各keyにフラグを設定することで有効化できる<br>

```groovy:app/build.gradle
android.signingConfigs {
    release {
        storeFile = rootProject.file("release.keystore")
        enableV1Signing = true
        enableV2Signing = true
        enableV3Signing = true
        enableV4Signing = true
    }
}
```

## コマンドライン
apkファイルからMin SDKとTarget SDKを読み取って署名スキームを良しなに使い分けてくれる<br>
オプションで指定することも可能<br>

v2, v3を有効化する例

```shell
apksigner sign --ks <jks|keystore file> --v2-signing-enabled true --v3-signing-enabled true <apk file>
```

:::note info
署名時のオプションはサイトにちゃんとまとまっている<br>
https://developer.android.com/studio/command-line/apksigner#options<br>
:::

# 検証する
:::note info
v1 ~ v3.1はapkファイルのみで検証が可能
:::

## v1 ~ v3.1

```shell
apksigner verify -v <apk file>
```

```shell
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Verified using v3.1 scheme (APK Signature Scheme v3.1): false
Verified using v4 scheme (APK Signature Scheme v4): false
Verified for SourceStamp: false
Number of signers: 1
```

## v4
:::note info
v4は署名時に生成されるidsigファイル(signature file)が必要
:::

```shell
apksigner verify -v -v4-signature-file <idsig file> <apk file>
```

```shell
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Verified using v3.1 scheme (APK Signature Scheme v3.1): false
Verified using v4 scheme (APK Signature Scheme v4): true
Verified for SourceStamp: false
Number of signers: 1
```

:::note warn
v4で署名していてもsignature fileをapksignerに渡さない場合はv4での**検証ができない**ことに注意<br>
渡さなかった場合はv3.1までの検証が実行される
:::
【Flutter】Sizeの指定がなくてエラーになる時

Flutter開発していていっつも忘れてしまうので、備忘録。

```
constraints: BoxConstraints(unconstrained)
size: MISSING
```

↑のようにSizeが指定されてないことで、エラーになる場合。
```dart
SizedBox(
    width: 200,
    child: child
);
```
のようにwidth指定すれば解消されるのだけれど、数値をベタ打ちしたくない。。

```dart
SizedBox(
    width: double.infinity,
    child: child
);
```
のように指定しても、そもそも幅がわかってないよ！ってことでエラーになるみたい。

結論
```dart
Expanded(
    child: child
);
```
にて幅いっぱいまで広げてあげることで解消できる。
Flutterは、CSS感覚で実装しているとハマってしまう部分多いな。。
ESP32-S3でLinuxを動かしてみる

## はじめに
[olimexにESP32-S3でLinuxが動くという記事があったので。](https://olimex.wordpress.com/2023/06/27/running-linux-with-kernel-6-3-on-open-source-hardware-board-with-esp32-s3/)


## 必要なもの
- ESP32-S3 (RAM 8MB以上、FLASH 8MB以上)
- Ubuntu22 (HDD 100GB以上)

## 1. ESP-IDF インストール
[本家のドキュメントを参考に](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/linux-macos-setup.html)

### 1-1. Install Prerequisities (for Ubuntu)
```
sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
```

### 1-2. Get ESP-IDF
```
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
```

### 1-3. Set up the tools
```
cd ~/esp/esp-idf
./install.sh esp32s3
```

### 1-4. Set up the environment variables
```
. $HOME/esp/esp-idf/export.sh
```

### 1-5. First Steps on ESP-IDF
#### Start a Project
```
cd ~/esp
cp -r $IDF_PATH/examples/get-started/hello_world .
```

#### Connect Your Device
ここで /dev/ttyUSB0　が出てこないので、[この記事を参照](https://zenn.dev/hidenori3/articles/7ec70f3633ad41)して修正

```
sudo apt remove brltty
sudo udevadm control --reload
```

書き込み権限もあるか確認。ない場合には[この記事を参照](https://qiita.com/kiyonaga/items/182db6b8fc9afb33751c)して
/etc/udev/rules.d/99-usb-serial.rules を作る。

```99-usb-serial.rules
SUBSYSTEM=="tty",ENV{ID_SERIAL_SHORT}="デバイスのID_SERIAL_SHORTの値",MODE="0666"
```

#### Configure Your Project
```
cd ~/esp/hello_world
idf.py set-target esp32s3
idf.py menuconfig
```


#### Build Project
```
idf.py build
```

#### Flash onto the Device
```
idf.py -p /dev/ttyUSB0　flash  
```


#### Monitor the Output
```
idf.py -p /dev/ttyUSB0 monitor
```




## 2. Linux インストール
[bashスクリプト作ってくれている人がいるのでありがたく使う](https://gist.github.com/jcmvbkbc/316e6da728021c8ff670a24e674a35e6)

```
sudo apt-get install autoconf flex texinfo help2man gawk libtool-bin bison libncurses5-dev

mkdir ~/esp32
cd ~/esp32
wget https://gist.githubusercontent.com/jcmvbkbc/316e6da728021c8ff670a24e674a35e6/raw/eec0e4f144a5b6ff83620e4c14d3f69eceb62aba/rebuild-esp32s3-linux.sh

bash rebuild-esp32s3-linux.sh
```


これでESP32-S3でLinuxが動いてるのを確認。


## その他

https://github.com/ESP32DE/Boot-Linux-ESP32S3-Playground

http://wiki.osll.ru/doku.php/etc:users:jcmvbkbc:linux-xtensa:esp32s3
AIがハルシネーション（Hallucination）を起こす最大の理由【AGIの未来】

# ハルシネーション（Hallucination）とは？

もっともらしいウソ（＝事実とは異なる内容や、文脈と無関係な内容）の出力が生成されることである。人間が現実の知覚ではなく脳内の想像で「幻覚」を見る現象と同様に、まるでAIが「幻覚」を見て出力しているみたいなので、このように呼ばれる。

# なぜハルシネーションを起こすのか？

AIに掛け算をさせてみよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/bdfe443a-e112-4873-3550-78496a0f1601.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/baf22c8b-ad0f-0b9a-5a8e-4efeaaa2dbfe.png)
`5x5=`は正解できたが、`438890x819471=`は不正解である。なぜならAIは掛け算を理解しておらず、人間が九九を暗記しているにすぎないのである。

ではどうすれば、`438890x819471=`を正解できるのであろうか？それは、簡単だ。RNNのように時系列の次元をTransformerに追加することで正解に導くことができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/611a67d7-3ad4-4d74-c792-a1acd5c7f97d.png)

これは一体何を意味するのだろうか。GPT-4はまさにマルチモーダル(画像)を扱えるが、GPT-5で動画。
つまり、時系列を追加することで自己検証が可能となりハルシネーションがなくなるだろう。自己検証が可能となれば、RLHFのような人間のフィードバックも必要ではなくなるだろう

# まとめ

AIからハルシネーションをなくすには、transformerにMLMではなく時系列の次元を追加したモデルを開発すべきである
AGIは近い
jupyterの作業を一旦中断して後から再開する方法

別記事で悩んでいたことを違うアプローチで解決する方法です。

https://qiita.com/homunet/items/ad14a740aab9b313b9f3

一言で言うと、
・機械学習の勉強本の長くて一度に読み切れないノートブックの学習を、
・途中から再開するときに、
・最初から実行し直す時間を削減する方法
です。

bashの一般論ですので、コマンドになれている人なら当たり前のことかもしれませんが、自分的には結構感動したので。

```console
[I 2023-07-11 06:06:37.535 ServerApp] Connecting to kernel xxxx
^Z
zsh: suspended  jupyter lab
```

ターミナル(私はMacです)でcontrol+zでJupyterがサスペンドされます。この時点でブラウザからは当然アクセスできなくなります。

```console
% jobs
[1]  + suspended  jupyter lab
```

jobsを実行してサスペンドされているジョブの番号を確認します。

```console
% fg %1
[1]  + continued  jupyter lab
```

fgの%xのxに番号を指定して実行します。これでブラウザからJupyterに再度アクセスできるようになります。

Macならサスペンド中はウィンドウを黄色ボタンで最小化してDockにしまっておけば、気になることもないと思います。存在を忘れてしまいそうですが。

まぁそもそも論的には、起動しているJupyterのプロセス消費量なんて大したことないので、気にしないという手もあるのですが、私的にはどうにも精神衛生上よろしくなく、PowerNapが余計なことをしてOSのサスペンドを邪魔していたらどうしようと悩んでいたものですから、結構助かりました。

ここでさらにサスペンドしたジョブのイメージをディスクに書けたりすると良いのですが、ざっと調べた限りでは、そういう方法は見当たりませんでした。何か情報お持ちの方は教えてください。

今回の参考記事はこちらです。
https://stackoverflow.com/questions/20649783/pause-a-running-script-in-mac-terminal-and-then-resume-later
ffmpeg & youtube-dl ダウンロード方法とPathの通し方

タイトル: **FFmpegとyoutube-dlのダウンロードとPATHの設定方法**

## 1. FFmpegとyoutube-dlのダウンロード

まず、以下の公式サイトからそれぞれのソフトウェアをダウンロードします。

- FFmpeg: [https://ffmpeg.org/](https://ffmpeg.org/)
- youtube-dl: [https://github.com/ytdl-org/youtube-dl/releases](https://github.com/ytdl-org/youtube-dl/releases)

FFmpegは`zip`ファイル、youtube-dlは`exe`ファイルとして提供されています。自分の環境や好みに応じて適切なバージョンを選択してダウンロードしてください。

## 2. ダウンロードしたファイルの保存

ダウンロードしたファイルの保存先はどこでも構いませんが、後でPATHを設定するためにそのフォルダの場所のパスが必要となります。ここでは例として、Cドライブ直下にある`zoomDL`というディレクトリの中に`bin`というディレクトリを作成し、その中にダウンロードしたファイルを保存するとします。

したがって、FFmpegの`zip`ファイルは解凍した後、`ffmpeg.exe`は`C:\zoomDL\bin\`ディレクトリに、youtube-dlの`exe`ファイルは同じく`C:\zoomDL\bin\`ディレクトリに保存します。

## 3. PATHの設定

次に、ダウンロードしたソフトウェアをコマンドラインから利用できるように、PATHを設定します。

まず、`ffmpeg.exe`と`youtube-dl.exe`が置いてあるフォルダのパスを確認します。これはエクスプローラーでファイルを右クリックし、「プロパティ」から確認できます。

次に、WindowsのPowerShell（管理者権限で実行）を開き、以下のコマンドを実行します。

```powershell
[Environment]::SetEnvironmentVariable("Path", "$env:Path;C:\zoomDL\bin", "Machine")
```

これにより、`ffmpeg.exe`と`youtube-dl.exe`が存在する`C:\zoomDL\bin`がシステムのPATHに追加され、これらのソフトウェアがコマンドラインから利用できるようになります。

以上で、FFmpegとyoutube-dlのダウンロードとPATHの設定は完了です。

> 注意：この操作を行うとシステムのPATHが変更されます。必ず自身が何をしているか理解した上で操作してください。PATHを間違えて設定すると、他のソフトウェアが正常に動作しなくなる可能性があります。
pyenv で python-dev がいるとき

(venv 使えよっていうツッコミ is たぶん正しいです…)

## 状況

[instant-ngp](https://github.com/NVlabs/instant-ngp) を入れようとして、`cmake` してたら以下のエラー

```shell
CMake Error at /root/.pyenv/versions/3.9.17/envs/insngp/lib/python3.9/site-packages/cmake/data/share/cmake-3.26/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find PythonLibs (missing: PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS)
Call Stack (most recent call first):
  /root/.pyenv/versions/3.9.17/envs/insngp/lib/python3.9/site-packages/cmake/data/share/cmake-3.26/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE)
  /root/.pyenv/versions/3.9.17/envs/insngp/lib/python3.9/site-packages/cmake/data/share/cmake-3.26/Modules/FindPythonLibs.cmake:310 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  CMakeLists.txt:232 (find_package)
```

見に行ってみると、`CMakeLists.txt` の `find_package` でエラーが出ていた。

```CMakeList.txt
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
```

調べてると、

```shell
Could NOT find PythonLibs (missing: PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS)
```

このエラーは、`python-dev` が入っていないことが原因っぽい。
普通に `apt install python-3.9 python3.9-dev` とかで python を入れてたらこのエラーには出くわさないんだけど、pyenv を使ってたために出くわしてしまった…

ここで適当に `apt install python-dev` をすると、pyenv の python に関係ない python-dev が入る気がした
実際、`CMakeList.txt` で ↓ で print デバッグしてみると、 (GPTに教えてもらった)

```CMakeList.txt
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
message(STATUS "Python libraries: ${PYTHON_LIBRARIES}")
message(STATUS "Python include directories: ${PYTHON_INCLUDE_DIRS}")
```

```shell
-- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython2.7.so (found version "2.7.18")
-- Python libraries: /usr/lib/x86_64-linux-gnu/libpython2.7.so
```

と、python3.9 を使ってるのに見つかった `PYTHON_LIBRARIES` と `PYTHON_INCLUDE_DIRS` は python2.7 云々言ってて、ダメです！

ちなみに、いま使っている python 環境が使ってる header とか library の場所は以下で調べられるらしい (by GPT)

```python
import distutils.sysconfig

print("Header files:", distutils.sysconfig.get_python_inc())
print("Library files:", distutils.sysconfig.get_config_var('LIBDIR'))
```

出力

```
Header files: /root/.pyenv/versions/3.9.17/include/python3.9
Library files: /root/.pyenv/versions/3.9.17/lib
```

## pyenv で dev ぽいことする？

どうやら pyenv 環境を作るときの option で dev っぽいことができるらしい？(あんまよくわかってないす)

```shell
env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv virtualenv 3.9.17 insngp
```

で、 `cmake` のときにオプションを渡す

```shell
cmake . -B build \
-D PYTHON_LIBRARIES=/root/.pyenv/versions/3.9.17/lib \
-D PYTHON_INCLUDE_DIRS=/root/.pyenv/versions/3.9.17/include/python3.9
```

＆、CMakeList.txt の `find_package` を消す

```CMakeList.txt
# find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
```

で通った

## 以上！
生成ＡＩ時代の組織を考える：人間による会議の終焉ー

https://note.com/z_wara/n/ndf05fa0f9610

こんな記事を書いてみました。このテーマに関連した技術的事項や、望ましいあり方など
については、Qiitaの記事などを参考に学んでいきたいと思います。

人間が考えて、咀嚼した情報を最も重んじている会議という場。この会議の形が組織の基本を形作っています。しかしこれは、改革が可能なはずで、生成ＡＩによって、人間以上に情報の集約や整理あるいは測定・予測を行うことで、意思決定のために人間同士の認識を擦り合わさなくても、ＡＩが作成したデータから多くのことを速やかに、それぞれのメンバーがそれぞれの意見を形成して意思決定ができるはずですね。
初投稿、よろしくお願いします!!

# 初投稿、よろしくお願いします!!
初めまして、ゲームクリエイターを目指しているモノです。
気付いたことや、発見などをきままに投稿していきます。
拙い文章となりますが、これからよろしくお願いします!!

## 参考資料
https://help.qiita.com/ja/articles/qiita-community-guideline
2023/7/11主にITとかセキュリティの記事

Androidデバイスの脆弱性、サイバー攻撃への悪用確認 - アップデートを(7/9)
https://news.mynavi.jp/techplus/article/20230709-2722951/

シスコ製品に重要な脆弱性、アップデートを
https://news.nicovideo.jp/watch/nw12944920

Linuxカーネルに重大な脆弱性「StackRot」、ただちに確認を(7/9)
https://news.mynavi.jp/techplus/article/20230709-2722429/

Androidのアップデートを、Googleが2023年7月セキュリティパッチ公開(7/7)
https://news.biglobe.ne.jp/it/0707/mnn_230707_8891659667.html

マイナンバーカード自主返納6月は30件…5月の4倍以上　理由は「信用できない」「個人情報漏洩が心配」　静岡市(7/9)
https://news.yahoo.co.jp/articles/2eafa2f4e41b4da6f39e8d7a8740a3f4ef94753e

混乱広がるツイッター 今後は？スレッズは？米専門家が解説(7/9)
https://www3.nhk.or.jp/news/html/20230709/k10014123311000.html

南海電鉄に不正アクセス＝シェアオフィス予約サイト(7/7)
https://www.risktaisaku.com/articles/-/80996

SCSK、生成AIを活用した質疑応答支援システムの概念検証を実施(7/7)
https://cloud.watch.impress.co.jp/docs/news/1514433.html

暗号資産を始める前に！ トラブルを回避する3つのチェックポイント(7/9)
https://news.yahoo.co.jp/articles/967d38180938bf116e7f2e7e6685e745c4501c56

プログラマーに向いている人の特徴8つ！向かない性格も紹介(7/8)
https://sejuku.net/blog/212730

悩ましい生成AIのリスク管理、ガイドライン策定と環境構築が肝に(7/10)
https://xtech.nikkei.com/atcl/nxt/column/18/02513/070600004/

厳冬の暗号資産市場、ビットコインが孤高の存在感を放つ理由(7/10)
https://xtech.nikkei.com/atcl/nxt/column/18/01115/070600048/

OpenAIが訪韓、AIチップ共同開発検討 需要高まるメモリ半導体の生産増にも期待(7/10)
https://xtech.nikkei.com/atcl/nxt/mag/rob/18/00006/00128/

ロボットとエレベータの連携(7/10)
https://xtech.nikkei.com/atcl/nxt/mag/rob/18/00014/00002/
gocsvで読み込んだデータに手を加えて構造体に入れたい

## やりたいこと
タグでcsvを読み取りたいのを大前提として、
csvの行としては分けられているデータを加工して(結合するなど)csvを読み込みたい
例として以下のようなcsvの姓と名を結合して構造体に持ちたいことがあった。
```
姓,名,年齢,職業
山田,太郎,30,エンジニア
佐藤,花子,25,デザイナー
田中,一郎,35,医師
渡辺,和子,28,教師
高橋,健二,32,自由業
```

## 実現手段
github.com/gocarina/gocsvの[UnmarshalBytesToCallback](https://pkg.go.dev/github.com/gocarina/gocsv#UnmarshalBytesToCallback)を使用する。
CSVの列に対応する構造体を定義しておいて、一度その形式でデータを受け取ってから欲しい形式に加工する形。

思ったよりは簡単に実装できるが実装サンプルが見つけられなかったので備忘録として。


## コード例
ヘッダ部分の諸々は省略
```
type (
	Person struct {
		Name string
		Age  int
		Job  string
	}
	// 大文字にしないとgocsvから見えない
    // csvの形式の構造体を定義しておく
	PersonCSV struct {
		FirstName  string `csv:"名"`
		SecondName string `csv:"姓"`
		Age        int    `csv:"年齢"`
		Job        string `csv:"職業"`
	}
)

func main() {
	test := `姓,名,年齢,職業
	山田,太郎,30,エンジニア
	佐藤,花子,25,デザイナー
	田中,一郎,35,医師
	渡辺,和子,28,教師
	高橋,健二,32,自由業`

	var p []Person
	if err := gocsv.UnmarshalBytesToCallback([]byte(test), func(pc PersonCSV) {
		p = append(p, Person{
			Name: pc.FirstName + pc.SecondName,
			Age:  pc.Age,
			Job:  pc.Job,
		})
	}); err != nil {
		log.Fatalln(err)
	}
	for _, v := range p {
		fmt.Println(v)
	}
}

func (p Person) String() string {
	return fmt.Sprintf("%s(%d) %s", p.Name, p.Age, p.Job)
}
```

## コールバック関数が複雑になるとき
コールバック関数が複雑になるときは以下の対処法がありそう
1. globalに[]Personを持たせる(あまりイケてなさそう)
2. コールバック用の関数を返す関数を別で定義
2. 無名関数で呼ぶための関数を定義

### 2の実装
```
// 処理が複雑な場合は関数を返すようにする
func ComplexProcess(person *[]Person) func(PersonCSV) {
	return func(pc PersonCSV) {
		*person = append(*person, Person{
			Name: pc.FirstName + pc.SecondName,
			Age:  pc.Age,
			Job:  pc.Job,
		})
		// さらに何らかの処理。。。
	}
}

func main() {
    ...
	var p2 []Person
	cp := ComplexProcess(&p2)
	if err := gocsv.UnmarshalBytesToCallback([]byte(test), cp); err != nil {
		log.Fatalln(err)
	}
	for _, v := range p2 {
		fmt.Println(v)
	}
    ...
}
```

### 3の実装
```
func ComplexProcess2(person *[]Person, personCSV PersonCSV) {
	// pに値を加工して代入するような何らかの複雑な処理
	*person = append(*person, Person{
		Name: personCSV.FirstName + personCSV.SecondName,
		Age:  personCSV.Age,
		Job:  personCSV.Job,
	})
}

func main() {
    ...
	var p3 []Person
	if err := gocsv.UnmarshalBytesToCallback([]byte(test), func(pc PersonCSV) {
		ComplexProcess2(&p3, pc)
	}); err != nil {
		log.Fatalln(err)
	}
	for _, v := range p3 {
		fmt.Println(v)
	}
    ...
}
```

ざっくり書いたのは以下。
https://github.com/lapis2411/go-evaluation/blob/main/gocsv.go

よりよさげな対応あればコメントなどで教えて頂ければ！
【DBスペシャリスト試験】トランザクションの分離レベル

イメージ掴みたい方用

### トランザクションの分離レベルとは
- トランザクションに指定できる直列化の度合い。
- 直列化とは、並列化の反対で、トランザクションを順番に実行するようにすること。
- 直列化の度合いとは、複数トランザクションを実行したときの結果が、どれだけ「順番に実行した結果」に近くなるか、ということ。 
  - 最高は順番に実行したとき。
    - 分離レベル高：整合性↗、処理効率↘（順次実行に近いと整合性は担保できるが遅い）
  - 最低はまだコミット前のデータでも読んでしまう（別トランザクションの結果を確定前でも先読みしてしまう）ようなとき。
    - 分離レベル低：処理性能↗、整合性↘（並列化すると処理速度は上がるが複数の処理が混じってデータが整合しないことあり） 
- SQLで"SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;" みたいにして使う（MySQLの例）

### 各分離レベル
低い順。
異常形態の名前の解釈は個人のものです。あくまでイメージを掴むため...
（ただし、固有名詞は参考書やドキュメントに記載のあるもの）

#### READ UNCOMITTED
他のトランザクションが更新した、コミット前のデータも読む。
実際にはコミットされずロールバックされた場合には、コミット前のデータはダーティデータとなり、上記読み取りは**ダーティリード**と呼ぶ。

#### READ COMITTED
他のトランザクションでコミット済みのデータを読む（コミット待ちの変更は読まない）。
ただし、コミットさえされれば読むため、
トランザクション中で同じデータを2回以上読んでいる場合は、1回目と2回目とで読み取り結果が異なる、があり得る。
これは、再度読んでも同じ結果が返らない（繰り返しが効かない）、という意味で**ノンリピータブルリード**と呼ぶ。

#### REPEATBLE READ
トランザクション内であれば、同じデータを何度読みだしても、（他のトランザクションがそのデータを更新してコミットしようが）必ず同じ結果を返す。
ただし、対象データの更新や削除を無視するだけで、処理途中に新規追加された行がぽんと現れることはある。
これは、1回目などには存在しなかった行が現れるという意味で、**ファントムリード**と呼ぶ。

#### SERIARIZABLE
順番に実行する。
並列実行しても制御されて直列実行される。

#### 分離レベルと各異常形態の関係
ある分離レベルで起こりうる異常は、それ以下の分離レベルでも起こりうる。
| 分離レベル\異常形態 | ダーティリード | ノンリピータブルリード | ファントムリード |
| ---- | ---- | ---- | ---- |
| READ UNCOMITTED | 許す | 許す | 許す |
| READ COMITTED | 許さない | 許す | 許す |
| REPEATABLE READ | 許さない | 許さない | 許す |
| SERIALIZABLE | 許さない | 許さない | 許さない |

### 参考
- MySQL
[3.3.7 SET TRANSACTION ステートメント](https://dev.mysql.com/doc/refman/8.0/ja/set-transaction.html)

- データベーススペシャリストドットコム
[平成31年春期 午前Ⅱ 問9](https://www.db-siken.com/kakomon/31_haru/am2_9.html)

##### ひとこと
多くのDB製品はデフォルトはREAD COMITTEDらしい。実際は排他制御とかも使っていい感じにやってるらしい。
間違いやこの方が覚えやすいよ等あればコメントやご指摘いただけますと嬉しいです！
「terraform apply」実行時の「invalidamiid.notfound」エラー

# 概要
実践Terraformの第2章 基本操作を参考にEC2を作成しようとしたところエラー発生、、　
エラー解消方法の備忘録

# エラー内容
`terraform apply`を打ち、`Enter a value: yes`までは問題なく進み、その後以下のようなエラーが起きた

```
╷
│ Error: creating EC2 Instance: InvalidAMIID.NotFound: The image id '[ami-06ca3ca175f37dd66]' does not exist
│       status code: 400, request id: d50d2d34-5a79-45ab-beb9-95d0c11b1e40
│
│   with aws_instance.example,
│   on main.tf line 5, in resource "aws_instance" "example":
│    5: resource "aws_instance" "example" {
╵
```
その時のmain.tf。⇩⇩

```terraform:main.tf
provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_instance" "example" {
    ami = "ami-06ca3ca175f37dd66"
    instance_type = "t2.micro"
    tags = {
      Name = "example"
    }
}
```
コンソールを見るとちゃんとAMIは存在していて、IDも間違っていない。


# 原因
main.tfのproviderで東京リージョンを指定しているのに、バージニア北部のAMIを指定していたため、「そんなAMIないよー」と怒られていた、、

なので解決法としては、以下の2つかなと思う
* providerで指定するリージョンをus-east-1にする
* AMIを東京リージョンにあるAMI IDに変更する

改めて、東京リージョンにあるAMI IDを指定し、applyしたら無事EC2を作成できた！
[AWS Q&A 365][ECS]AWSのよくある問題の毎日5選 #93

# 1. AWS FargateのAmazon ECSユーザーガイドでのリソースとは何ですか？
A: リソースとは、Amazon ECSで実行中のタスクに必要なCPUやメモリなどのコンピューティングリソースを指します。

# 2. AWS FargateのAmazon ECSユーザーガイドでリソースをどのように管理しますか？
A: AWS FargateのAmazon ECSユーザーガイドでリソースを管理するには、タスク定義にCPUとメモリの値を指定します。

# 3. AWS FargateのAmazon ECSユーザーガイドでのタグとは何ですか？
A: タグは、クラスターやサービス、タスクなどのAmazon ECSリソースに割り当てることができるキーと値のペアです。リソースの組織化や検索に使用することができます。

# 4. Amazon ECSのリソースにタグを追加する方法は？
A: AWS管理コンソール、AWS CLI、またはSDKを使用してAmazon ECSのリソースにタグを追加することができます。

# 5. AWS FargateのAmazon ECSユーザーガイドでタグを使用する目的は何ですか？
A: AWS FargateのAmazon ECSユーザーガイドでタグを使用する目的は、リソースの組織化、コストの追跡、特定のリソースに対する権限の適用などです。
[AWS Q&A 365][ECS]Daily Five Common Questions #93

# 1. What are resources in Amazon ECS User Guide for AWS Fargate? 
A: Resources refer to the computing resources such as CPU and memory required by tasks running in Amazon ECS. 

# 2. How can you manage resources in Amazon ECS User Guide for AWS Fargate? 
A: You can manage resources in Amazon ECS User Guide for AWS Fargate by specifying the CPU and memory values in the task definition. 

# 3. What are tags in Amazon ECS User Guide for AWS Fargate? 
A: Tags are key-value pairs that you can assign to Amazon ECS resources such as clusters, services, and tasks. They can be used for organizing and searching resources. 

# 4. How can you add tags to Amazon ECS resources? 
A: You can add tags to Amazon ECS resources using the AWS Management Console, AWS CLI, or SDKs. 

# 5. What is the purpose of using tags in Amazon ECS User Guide for AWS Fargate? 
A: The purpose of using tags in Amazon ECS User Guide for AWS Fargate is to organize resources, track costs, and apply permissions to specific resources.
[Snowflake] 指定した日付間の日付一覧を作成するクエリを書いてみた

```sql
arr AS (
  SELECT
    ARRAY_GENERATE_RANGE(
      0, 
      DATEDIFF('DAY', '2023-07-01', '2023-07-10') + 1
    )
)
```

この部分で [0, 1, 2, 3, … 9] という、10個の要素を持つ ARRAY を作成しています。10個なのは 2023-07-01 ~ 2023-07-10 までの日数が10日間だからで
す。DATE_DIFFで計算しています。

```sql
dates AS (
  SELECT
    DATEADD('DAY', value, DATE('2023-07-01')) AS date
  FROM
    TABLE(FLATTEN(INPUT => SELECT * FROM arr))
)
```

ここでは、先程の部分で作成される ARRAY を FLATTEN を使って行に展開し TABLE関数 で読み込んでいます。
最後に ARRAY の各要素 (0 … 9) を 2023-07-01 に DATE_ADD してやると完成です。
※ FLATTENでARRAYを展開すると、6列 × ARRAYの要素数 のデータが出力され、VALUEという列にARRAYの各要素が格納されます [参考]

日付一覧に加え、曜日などの情報を付加してviewにしておくと便利だと思います。

```sql
CREATE OR REPLACE VIEW calendar AS 

WITH
arr AS (
  SELECT
    ARRAY_GENERATE_RANGE(
      0, 
      DATEDIFF('DAY', '2023-07-01', '2023-07-10') + 1
    )
),

dates AS (
  SELECT
    DATEADD('DAY', value, DATE('2023-07-01')) AS date
  FROM
    TABLE(FLATTEN(INPUT => SELECT * FROM arr))
)

SELECT 
  date,
  EXTRACT(YEAR FROM date) AS year,
  EXTRACT(MONTH FROM date) as month,
  EXTRACT(DAY FROM date) AS day,
  EXTRACT(DOW FROM date) AS dow,
  DAYNAME(date) AS day_name
FROM
  dates
```
# 指定した日付からN日間の日付一覧を得るクエリ
指定した2つの日付間ではなく、指定した日からN日間の日付一覧であれば、以下の様にもっとシンプルに書くこともできます。

```sql
-- 2023-07-01から10日間の日付一覧を得るクエリ
SELECT
  DATEADD('DAY', seq1(), DATE('2023-07-01')) AS date
FROM
  TABLE(GENERATOR(rowcount => 10))
```
[Snowflake] UDFを試してみた (スカラーUDF編)

# UDFの種類
snowflakeのudfには以下の2種類があるようです。[参考]
今回はこのうちScalar UDFを試してみます

* Scalar UDF
入力行ごとに1つの出力行を返す
* Tabular UDF
入力行ごとに表形式の値を返す

# UDFの定義
生年月日を受け取って年齢を計算するUDFの定義がこちらです。Pythonで書いています。
Python, Java, Javascript, Scala などが使用できるようです。[参考]

```sql
create or replace function birthday2age(birthday string)
returns int
language python
runtime_version = '3.9'
handler = 'main'
as
$$
import datetime
def main(birthday):
    today = datetime.date.today()
    birthday = datetime.datetime.strptime(birthday, "%Y-%m-%d")
    age = (int(today.strftime("%Y%m%d")) - int(birthday.strftime("%Y%m%d"))) // 10000
    return age
$$;
```

このコードを実行すると、実行時に指定している `DATABASE.SCHEMA` の下にUDFが作成されています。
![](https://storage.googleapis.com/zenn-user-upload/91b8098fb99c-20230710.webp)


# 作成したUDFの利用
作成したUDFはSELECT文の中で利用できます

```sql
SELECT BIRTHDAY2AGE('1999-01-01')
-> 24
```
Leetcode 111. Minimum Depth of Binary Tree

https://leetcode.com/problems/minimum-depth-of-binary-tree/

```java
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */

class Solution {

    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        } else if (root.left == null && root.right == null) {
            return 1;
        } else if (root.left == null) {
            return minDepth(root.right) + 1;
        } else if (root.right == null) {
            return minDepth(root.left) + 1;
        } else {
            return 1 + Math.min(minDepth(root.right), minDepth(root.left));
        }
    }

}
```