OmniAICreator/Qiita-1.07M huggingface dataset:
【JavaScript関数ドリル】初級編のjoin関数の実装アウトプット

## join関数の課題内容

_.join関数を自分で実装する課題。
https://lodash.com/docs/4.17.15#join

「課題内容」/「解説動画」/「解答例」を確認したい場合は、以下リンク先のページを参照。
https://js-drills.com/blog/join/


## 課題に取り組む前の状態

- 解答例を見なくてもできそうだと思った。


## 課題に取り組んだ後の状態

- 解答例は引数の配列を一旦新しい配列にコピーし、配列の最初の値を変数宣言時に入れているのが、自分の解答と主に異なる点で、そういう方法は思いつかなかったので、参考になった。

## join関数の実装コード（答えを見る前）
```javascript
function join(array, separator = ',') {
    let str = "";
    for (let i = 0; i < array.length; i++) {
        str += array[i];
        if (i < array.length - 1) {
            str += separator;
        }
    }
    return str;
}
```

## join関数の実装コード（答えを見た後）
```javascript
function join(array, separator = ',') {
    let str = array[0];
    for (let i = 1; i < array.length; i++) {
        str += separator + array[i];
    }
    return str;
}
```
access2000の作法 その37

# 概要
access2000の作法、調べてみた。
sin波、表示してみた。

# 写真
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/978e39a2-9e03-568b-9587-652a90c793c1.png)


# sin波レポートを作る手順。
- 作成>レポートデザインを開く
- プロパティシートを開く
- 詳細をクリック
- イベントを開く
- フォーマット時、コードビルダーを開く
```
Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    Me.DrawWidth = 30
    Dim i
    Dim x
    Dim y
    Dim angle
    Dim pi
    pi = 3.14
    For i = 1 To 720
        angle = i / 360 * 2 * pi
        x = 500 * Sin(angle) + 500
        y = i * 10
        Me.Line (y, x)-(y + 2, x), RGB(255, 0, 0)
    Next
End Sub
```
- フォームを閉じる
- 保存する


以上。
【退職エントリ】 愛媛の受託開発 セーバーを辞めます

今日が最終出社日です。
４年間勤めた[セーバー株式会社](https://www.saver.jp)を辞めます。
夜中に目が覚めたので、退職エントリというやつを書いてみることにしました。

# どんな会社か

セーバーは愛媛にある受託開発を中心に行なっているソフトウェア開発会社です。
WebRTCの受託案件が多いです。

## 業態

業態的にはいわゆるSIerというやつでしょうか。
現時点で社員数は20人足らずで、組織としてはまだまだ完成していない小さな会社です。

巷では「SIerは悪だ、受託開発は悪だ」、「WEB系企業バンザイ、自社開発バンザイ」という風潮がありますが、セーバーは決して悪い会社ではありませんでした。
「SIer=ブラック」だと決めつけるのは早計だと思います。

自社開発では基本的に自社のプロダクトに専念して、深く追求することが出来ます。
一方でSIerでは幅広いプロダクトの開発に携わることが出来ます。

SIerは中間搾取だけで、技術は身に付かないという話も聞きます。
しかし、セーバーでは実際に開発を行なっていますし、僕自身多くのことを学びました。
また、人数が少ない分、手を挙げれば自由にやらしてもらえました。
社長もたいていノリノリで応援してくれます。

## カルチャー

一応、上司と部下という組織図は存在しますが、実態はフラットな組織だと思います。
あまり上下関係を気にする必要はなく、「上司が帰るまで部下は帰らない」などといった文化もありません。

飲み会は年に１、２回程度で、強制ではなく、飯だけ食って抜ける人もいます。
コロナもあって一度も飲み会に参加したことがない人も結構います。

自由に有給が取れて、都合の悪い日はフレックスで調整できます。
遅刻ばかりしていましたが、勤務態度で注意を受けたことはありませんでした。
このゆるさに惹かれましたw

昼休みの過ごし方も自由で、好きな時に１時間取れます。
ゲームをしている人もいます。
僕は会社にダンベルを持ち込んで筋トレをしていました。
写真のヨガマットは、なんか社長が買ってくれましたw

![休憩室](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72814/2dda17f1-c700-6401-4e58-1bc9a27d5cdc.jpeg)

## 給与

給与は高くも低くもないと思いますが、実力次第で変わると思います。
当然ではありますが、残業代もきっちり出るので、忙しい時期は小金持ちになれます。
ぶっちゃけ、瞬間風速的には転職後よりも今の方が給与がいいです。

# 何をしてきたのか

セーバーに入社する前からPHPは基本的なMVC、JavaScriptはjQueryとReactが書けました。
ただし、インフラは全く経験がありませんでした。

入社後はLaravelやSlimやExpressでバックエンドを作ったり、
ReactやAngularでフロントエンドを作ったりしました。

ここ１年はAWSやKubernetesを使った開発も行い、インフラも経験できました。
WebRTCとKubernetesを掛け合わせたような技術基盤を作ってきました。
その集大成とも言えるHelmチャートが完成し、YouTubeで動画を公開しているので是非ご覧ください。

https://youtu.be/d4f17H9Nf6o

※ 動画のセンスがなく、なんか政見放送みたいです・・・OTL

他にもGPSマップのテストをするために端末を持って自転車をこいでみたり、
「Speech To Text × AutoML Translation」のテストをするために部下にドラゴンボールの台詞を喋らせてみたり、そして誤認識の酷さに爆笑したり。

思い返せば、辛いこともありましたが、それ以上に楽しいことが多かったです。

# なぜ辞めるのか

僕が辞めるのはセーバーが嫌になったからではありません。
20代も終わりに近づいて、転職するならそろそろ動かないと動けなくなりそうだと感じたからです。
もとから１社でキャリアを終えるつもりがなく、いつか辞めると周りにも豪語していました。

また、自分が知識をつけていく中で、自分が正しいと信じていることと、周りの意見が食い違うことが増えてきました。
雇用条件などといった表面的な部分ではなく、思想信条のような根幹的な部分で今の自分と会社の方向性が合わなくなってきたのだと感じました。

今の自分が最大のパフォーマンスを発揮できる環境で新しい挑戦がしたい、
持てる全てを爆発させて社会的な意義の感じられる大きな仕事を成し遂げたい。
そんな思いで転職活動に踏み切りました。

# 転職活動

コロナ禍で面接のリモート化が進み、転職活動もとても楽になりました。
[転職ドラフト](https://job-draft.jp) に経歴を書いておけば、あとはオファーがきてそのまま面接という感じでした。
それでも転職活動期間中は受かるのか落ちるのか宙ぶらりんな状態で、絶えず不安な気持ちを抱えていました。
コロナ以前に転職活動をしている人は仕事をしながら飛行機で行ったり来たりしていたのかと思うと、信じられません。

思えば、僕はまともに就職活動というものをしたことがなく、成り行きでここまできました。
大学を中退してからフリーランスを経て、セーバーには派遣で勤め始めてそのまま入社しました。
初めてこういった経験をして、拒絶される辛さや、面接の難しさみたいなものを知りました。
それでも自ら主体的に選択して転職できたので満足のいく結果となりました。

# 今後

１ヶ月の引き継ぎ期間を経て、十分に引き継ぎが完了したと思うので、待望の有休消化期間に入ります。
こんなに長い休みを取れる機会は、もう定年までやってこないかもしれません。
仕事を引き継いでくれる皆さんのおかげです、ありがとう。

家の掃除をしたり、旅行行って充電したり、次の会社の関連技術の勉強をしたりして過ごすつもりです。
OSS活動もしようかな、そんな感じです。

次の会社は[MICIN](https://micin.jp)という医療系のベンチャー企業です。
日本の医療の形を変える、そんな仕事が出来たらいいなと思います。
別れを惜しみつつ、新たな出会いを楽しみにしています。
access2000の作法 その36

# 概要
access2000の作法、調べてみた。
youtubeやってみた。

# youtubeボタンを作る手順。
- menuフォームを右クリック。
- デザインビューを開く
- ボタンを設置
- ウィザードが開く	キャンセル
- プロパティシートを開く
- イベントを開く
- クリック時、コードビルダーを開く
```
Private Sub コマンド67_Click()
    Application.FollowHyperlink "https://www.youtube.com/embed/7MWJ83iIx4g"
    MsgBox "ok"
End Sub
```
- フォームを閉じる
- 保存する


以上。
access2000の作法 その35

# 概要
access2000の作法、調べてみた。
練習問題やってみた。

# 練習問題
zundokoを表示せよ。

# zundokoボタンを作る手順。
- menuフォームを右クリック。
- デザインビューを開く
- ボタンを設置
- ウィザードが開く	キャンセル
- プロパティシートを開く
- イベントを開く
- クリック時、コードビルダーを開く
```
Private Sub コマンド65_Click()
    MsgBox zundoko
End Sub

Function zundoko()
    Dim res
    res = ""
    Dim i
    i = 0
    Do Until (i = 4)
        If Rnd < 0.5 Then
            res = res & "ズン "
            i = i + 1
        Else
            res = res & "ドコ "
            i = 0
        End If
    Loop
    res = res & "ドコ　キヨシ！！"
    zundoko = res
End Function
```
- フォームを閉じる
- 保存する


以上。
access2000の作法 その34

# 概要
access2000の作法、調べてみた。
練習問題やってみた。

# 練習問題
九九を表示せよ。

# 九九ボタンを作る手順。
- menuフォームを右クリック。
- デザインビューを開く
- ボタンを設置
- ウィザードが開く	キャンセル
- プロパティシートを開く
- イベントを開く
- クリック時、コードビルダーを開く
```
Private Sub コマンド64_Click()
    MsgBox kuku
End Sub

Function kuku()
    Dim res
    Dim i
    Dim j
    res = ""
    For i = 1 To 9
       For j = 1 To 9
           res = res & CStr(i * j) & " "
       Next
       res = res & vbCrLf
    Next
    kuku = res
End Function
```
- フォームを閉じる
- 保存する


以上。
access2000の作法 その33

# 概要
access2000の作法、調べてみた。
fizzbuzzやってみた。

# fizzbuzzボタンを作る手順。
- menuフォームを右クリック。
- デザインビューを開く
- ボタンを設置
- ウィザードが開く	キャンセル
- プロパティシートを開く
- イベントを開く
- クリック時、コードビルダーを開く
```
Private Sub コマンド63_Click()
    MsgBox fizzbuzz
End Sub

Function fizzbuzz()
    Dim res
    Dim i
    res = ""
    For i = 1 To 100
        Select Case 0
        Case i Mod 15
            res = res & "FizzBuzz "
        Case i Mod 3
            res = res & "Fizz "
        Case i Mod 5
            res = res & "Buzz "
        Case Else
            res = res & CStr(i) & " "
        End Select
    Next
    fizzbuzz = res
End Function
```
- フォームを閉じる
- 保存する


以上。
Fetch APIとaxiosの違い

## HTTPメソッド
### Fetch API
Fetch APIは`method:"POST"`等と記述する必要があります。
```:Fetch API
export default function Sample () {
  const onButtonClick = () => {
    const params = {
      method: "POST",
      body: JSON.stringify({name: "サンプル"})
    }
    fetch("/api/user", params)
  }

  return (
    <div>
      <button onClick={onButtonClick}>ボタン</button>
    </div>
  )

```

### axios
axiosの場合には以下のようになります。
```:axios
import axios from "axios";

export default function Sample () {
  const onButtonClick = () => {
    axios.post("/api/user", {name: "サンプル"})
  }

  return (
    <div>
      <button onClick={onButtonClick}>ボタン</button>
    </div>
  )
}
```

## JSONデータ
### Fetch API
Fetch APIは`response`で受け取りJSONを抽出する必要があります。
```:Fetch API
export default function Sample () {
  const onButtonClick = () => {
    fetch("/api/user")
      .then((res) => res.json()) 
      .then((user) => alert(`ユーザー名：${user.name}`))  
  }

  return (
    <div>
      <button onClick={onButtonClick}>ボタン</button>
    </div>
  )
}
```

### axios
axiosの場合には以下のようになります。
```:axios
import axios from "axios";

export default function Sample () {
  const onButtonClick = () => {
    axios.get("/api/user")
      .then((res) => alert(`ユーザー名：${res.data.name}`))  
  }

  return (
    <div>
      <button onClick={onButtonClick}>ボタン</button>
    </div>
  )
}
```

## エラーハンドリング
### Fetch API
Fetch APIは正常なレスポンスが返却されたかの判定をする必要があります。
```:Fetch API
export default function Sample () {
  const onButtonClick = () => {
    fetch(api/auth/jwt/create/
      {
        method: 'POST',
        body: JSON.stringify({ username: username, password: password }),
        headers: {
          'Content-Type': 'application/json',
        },
      }
   )
   .then((res) => {
      if (res.status === 400) {
        throw 'authentication failed'
      } else if (res.ok) {
        return res.json()
      }
    })
  }

  return (
    <div>
      <button onClick={onButtonClick}>ボタン</button>
    </div>
  )
}

```

### axios
axiosの場合には以下のようになります。
```:axios
import axios from "axios";

export default function Sample() {
  const onButtonClick = () => {
    axios.post('api/auth/jwt/create/')
      .then((res) => res.data)
      .catch(() => alert("authentication failed"))
  }

  return (
    <div>
      <button onClick={onButtonClick}>ボタン</button>
    </div>
  )
}
```
メモ: Psycopg2 で配列に集約した結果をリストとして受け取るには、クエリに型をつければいい

時間がないので、ざっとメモ。

# 背景: PostgreSQL の array_agg は配列として集約する集約関数

こんな感じでユーザ `user_id` の通った学校の一覧 (`school` 列を配列にしたもの) を返すことができる。

```sql
select user_id, array_agg(school) as schools
from ...
where ...
group by user_id
```

これを psycopg2 で単純に受け取ろうとすると、`{'foo','bar'}` のような配列の文字列表現が得られる。

# 問題: これを psycopg2 でリストとして受け取るには?

Python で扱うならリストとして受け取りたい。

# 解決策: クエリに型をつければいい

クエリには型がつけられる。配列であれば `<要素の型>[]` とすればいい。
たとえば前述の `school` 列の型が `varchar(...)` なのであれば、クエリをこうすればいい:

```sql
select user_id, array_agg(school)::varchar[] as schools
from ...
where ...
group by user_id
```

これで `schools` 列の値は Python のリストとして受け取れる。嬉しい。

(以上)
日本のRGB標高タイル（ZL４～11）をAW3D30から作った

# はじめに
ALOS World 3D - 30m (AW3D30)　をつかい、日本のあたりのRGB標高タイルを作りました。GitHubページと自分のテストサイトにアップロードしました。ここにメモしておきます。

## アクセス情報
* GitHubレポジトリ
    * URL https://github.com/ubukawa/AW3D30-RGB-JPN
    * タイルのURL: https://ubukawa.github.io/AW3D30-RGB-JPN/zxy/{z}/{x}/{y}.png
* 自分のテストサイト（予告なく閉じる可能性があります）
    * タイルのURL: https://www.unvt-test.com/elevation/jpn/zxy/{z}/{x}/{y}.png

# （ソース）ALOS World 3D - 30m (AW3D30)　について
JAXAさんがALOS/PRISMデータから作成したグローバルDEMで、30メートル解像度のものです。無料で公開されています。最新のものは第3.2版ですが、2016年4月の第1版公開以降、着実に公開範囲を広げ、またデータの改善を行ってきているようです。

> 本データセットは、陸域観測技術衛星「ALOS」搭載の光学センサ・パンクロマチック立体視センサ（PRISM）による解像度30m相当（緯度経度1秒間隔を基本）の全球数値地表モデル（DSM）です。 最新版は第3.2版と第3.1版です。 本データセットは、下記「5. 利用規約」の条件において、商用・非商用目的を問わずどなたでも無償でご利用いただけます。 科学研究や教育分野、地理空間情報を活用した新しいサービス等に、本データセットを広くご活用いただければ幸いです。
（JAXAさんのホームページより　https://www.eorc.jaxa.jp/ALOS/jp/dataset/aw3d30/aw3d30_j.htm　）

# 作成方法
これまでに、ALOSの30メートルDEMからRGB標高タイルを作る方法について検討しており、以下のページにまとめてあります。

https://qiita.com/T-ubu/items/dc5022e15f2b770429b3

https://qiita.com/T-ubu/items/e32e51ee85577d733546

ズームレベル４のタイルの区画を意識して、３地域に分けて作業しました。私のPCの処理能力ではズームレベル11までが妥当だと思いました。（また、ズームレベル11であれば１GB 以下なのでGitHubページでもホストできる。）

# 作ったもののスペック
* Mapbox/MapLibre に準拠したRGB elevation tile.
    * base: -10000
    * interval: 0.1
    * Terefore, height = -10000 + ((R * 256 * 256 + G * 256 + B) * 0.1)
* ズームレベル: ４～１１
* ディスクレーマー
    * このデータの範囲は、特定の国の境界について何ら示唆するものではありません。
    * このデータについての保証はありません。As is ベースで公開しています。もともとのデータの利用条件をまもってください。We hold no liability for any consequence caused by the use of the Data or by the quality thereof.
* 範囲
下の薄紫色のところが今回の作業範囲です。（もともとのデータがない部分も含まれています。）
![2022-06-07-coverage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/fc78f085-5120-983b-5ea0-f7105f4d6399.png)
結果として、以下の2つの条件をともに満たすところのタイルができています。
    * z-x-y が4-13-6, 4-14-5, あるいは4-14-6のところ
    * 東経120度～東経160度、北緯20度～北緯50度の範囲



# 謝辞
ALOS World 3D - 30m (AW3D30)データを公開してくださっているJAXAさんに感謝します。

# 参考
- [AW3D30 (ALOS World 3D - 30m) (JAXA)](https://www.eorc.jaxa.jp/ALOS/jp/dataset/aw3d30/aw3d30_j.htm)
- [（簡単）Dockerを使ってAW3D30 (ALOS World 3D - 30m) からRGB標高タイルをつくる](https://qiita.com/T-ubu/items/dc5022e15f2b770429b3)
- [AW3D30 (ALOS World 3D - 30m) からRGB標高タイルを作る](https://qiita.com/T-ubu/items/e32e51ee85577d733546)
スクラムにおいてプロダクトオーナーはどこまで「権限＋オーナーシップ」を持てるのか？

## はじめに
今回はスクラムにおいての役割の1つであるプロダクトオーナーの「権限とオーナーシップ」について、自身の経験を踏まえて書いてみたいと思います。おそらく各組織チームによって状況も違うと思うので1つの答えは出ないと思いますが皆様の参考になれば。

## プロダクトオーナーとは？
まずはスクラムにおいてのプロダクトオーナーとは
![スクリーンショット 2022-06-10 0.38.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502865/ea61cc67-0b1c-f14f-1209-0ed7f4b2bd33.png)
[スクラムガイド2020年11月](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf) より

ここで定義されているように、一番の役割は「プロダクトの価値を最大化することの結果に責任を持つ」になります。主にはプロダクトバックログを管理し、優先順位を決めていきます。開発チームに対して指示は出しませんが、全体の状況把握は必要になります。

**「プロダクトの価値を最大化することの結果に責任を持つ」**

とっても重要そうな役割ですよね。
価値とはなんでしょうか？売上？ユーザー数？品質？ブランド力？いろいろありそうですよね。

そして企業や組織の中で、1プロダクトオーナーがここに結果責任を持つというのは果たして出来るのか？という疑問が出てきます。

とは言っても、基本的にはスクラム開発の中で、プロダクトオーナーが言葉通り「権限＋オーナーシップ」を持っていない場合はなかなかうまくいきません。

このような状況は胸が痛くなりますね…
![スクリーンショット 2022-06-10 1.13.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502865/d41fda99-b71e-8665-5e1c-543196f39035.png)


ただ現実的には予算に対する権限を持っている、持っていないだったり、プロダクトに関する最終決定権の範囲であったりは組織や状況により様々でしょう。スクラムガイド通りにすべてがスムーズにいくことは無いかと思います。



## 誰がプロダクトオーナーをやるのか？パターン

ここで「どのような立場の人がプロダクトオーナーをやるのか？」を考えてみます。

* **事業責任者クラスがやるパターン**
    * 小さい規模だと=社長や創業者になりますが、権限の観点でいくと一番スムーズです。
    * 一方で、そのクラスの場合他の業務も兼務していることがほとんどなので時間をどこまで避けるかが問題です。

* **リーダークラスやマネージャークラスがやるパターン**
    * 現実的には世の中で一番多いパターンでは無いでしょうか？
    * 現場の理解もあり、プロダクトにコミットできる立場でもありそうです。
    * ただし、実際には上に事業部長がいたり、経営陣がいたり…口出しされたりすること多いのでは無いでしょうか。

* **顧客自身がやるパターン**
    * to Bビジネスだったり、社内プロダクトの場合にあるパターンです。
    * この場合オーナーシップ的にはスムーズですがスクラムチームとの意思の乖離が生まれやすいという難しさがあります。
    * プロダクトオーナーと開発チームとで主従関係が出来てしまうこともありそうです。


## どのように「権限＋オーナーシップ」を発揮するのか？

実際私が5年ほどプロダクトオーナーをやっていたときは上記の**リーダークラスやマネージャークラスがやるパターン**でした。

組織上私には上司として事業本部長がおり、全てにおいて権限が自分にあったわけではありません。（板挟み状態も日常的！！）

そんな中でも、プロダクトオーナーとしてスクラムチームを健全に機能させるため、「権限＋オーナーシップ」を持つために工夫していたことをいくつか紹介します。

* **自分の権限は明確にしておいてチームに伝えておく**
    * 実際のところ全ての権限を持っているプロダクトオーナーは稀だと思います。組織によって、プロダクトオーナーが決められる範囲=権限は様々です。
    * そのような時に「プロダクトオーナーはどこまで権限を持っているのか？」についてスクラムチームメンバーが理解していないと大きな混乱を招きます。
    * なので、プロダクトオーナーとして自分が持っている権限についてある程度は明確にして共有をおきましょう。（自分の権限が曖昧なら上司とすり合わせしましょう）
    * 私の場合は毎週上司との定例会議があったので、そこへ持っていく案件（=自分自身の権限を超えるもの）を明確にして毎週整理しながら進めていました。（変なやり方ですがプロダクトバックログとしてメンバーに見えるように案件自体を管理していました）

* **オーナーシップを発揮するための各所コミュニケーション**
    * 例えばプロダクトにおける新規機能の話がチーム内で出たとき。プロダクトオーナーの自分が「上司に確認しますね」と毎回毎回言っていたらどうでしょう。おそらくメンバーからすると「この人はプロダクトオーナーなのか？」と疑問が湧くはずです。
    * これを避けるためには、プロダクトの方向性や様々な可能性について日常的に上司やステークホルダーと常に共有をしておくことが大切です。
    * そこである程度合意が取れている状態をプロダクトオーナーとして醸成しておけば、オーナーシップを持って自身で判断が出来る機会が増えてくるはずです。ここのさじ加減はプロダクトオーナーとしての腕の見せどころのような気がします。

* **権限を超えた意思決定**
    * これはマインド的な話になってしまいますが、プロダクトオーナーである自身もスクラムチームメンバーも、「絶対にこれは必要な機能だ！」と思えている状態　（かつ顧客のニーズも見えている）であれば、例え上司に反対されていようとも作ってしまえば良いと思います。
    * その結果失敗したらプロダクトオーナーは責任をとるべきですが、それくらいの気概を持って臨んで欲しいなと思います。プロダクトについて一番考えているのはプロダクトオーナーなはずなので。
    * ちなみに私はこれで成功したことも失敗したこともあります。


## さいごに
スクラムのフレームワークは約30年の間進化しており、多くの開発チームで採用されている有益な手法だと思います。スクラムガイドに書いてあるとおり、要素を省略したり、独自のルールを採用したりはマイナスになってしまいます。
一方で組織によって個別の事象も発生してしまうことも現実かと思います。そんな中でいかにスクラムの本質に近づくことが出来るのか？を考えてトライをしていくことが大事だと思います。
XcodeのPlaygroundはどこへ消えた？

## TL;DR

***それっ、ココっ！File > New > Playground！！***

![スクリーンショット 2022-06-10 2.08.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526492/c5d7c19a-890d-dc1c-73a6-5db1f1b2d132.png)

## 環境

- macOS Monterey 12.4
- Xcode 13.4.1

## どうしてそうなった？

市営図書館で「たった1日で基本が身に付く！Swiftアプリ開発超入門」を借りてきた。
Xcodeに触れてみる最初のステップで「Get started with a playground」を押すと書いてあるが、以下のようにそんなものはない。

![スクリーンショット 2022-06-10 2.08.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526492/3ca546f2-7c5d-e06e-c595-d6b95d895fa4.png)

色々探してみたら上記パスにあった。
【Swift】配列の重複を取り除く 

Swiftで配列の重複を取り除く方法です。
structの特定の値をkeyとして取り除く方法を今回はご紹介します。

```swift
extension Array {
    func unique<T>(by keyPath: KeyPath<Element, T>) -> Array where T: Hashable {
        var dictionary: [T: Element] = [:]
        forEach { value in
            dictionary[value[keyPath: keyPath]] = value
        }
        return dictionary.map(\.value)
    }
}
```

**使い方**

```swift
struct Item {
  var title: String
  var value: Int
}

let items = [
    Item(title: "a", value: 1),
    Item(title: "b", value: 2),
    Item(title: "b", value: 3),
    Item(title: "c", value: 4),
]

/*
 Result
 [
     Item(title: "a", value: 1),
     Item(title: "b", value: 3),
     Item(title: "c", value: 4),
 ]
 */
let filteredItems = items.unique(by: \.title)
```
シェルスクリプトでJIS第一水準漢字を出力

## 結論

指定された区の94点を表示するスクリプトを作る。

```bash
#!/bin/bash
row=$1
byte0=$((0x81 + row / 2))
if [ $((row % 2)) = 0 ]; then
  byte1s=$(seq 0x40 0x7e; seq 0x80 0x9e)
else
  byte1s=$(seq 0x9f 0xfc)
fi 
echo $byte1s | \
  xargs printf "$byte0 %d 0x0a\n" | \
  xargs printf '\\\\0%o\n' | xargs printf '%b' | \
  iconv -s -f sjis
```

これを `printRow.sh` として、

```
$ seq 15 46 | while read r; do echo $r; ./printRow.sh $r; done
```

とすればよい。

最終の47区では、警告が出るが、これは、47区の末尾に未割当て領域があるため。

## 説明

第一水準がどの区に相当するのかは、

https://ja.wikipedia.org/wiki/JIS_X_0208

から、16～47区を表示すればよいことが分かる。

区と点から、対応するShift JISをどう出力すればよいかは、

https://ja.wikipedia.org/wiki/Shift_JIS

からわかる。

区は1つあたり94点からなり、2バイト目に、2つの区が入る。
なので、偶数、奇数で場合分けする必要が出てくる。
また、`0x7f` に隙間がある点に注意が必要だ。

シェルスクリプトでバイナリを出力する方法は、

https://qiita.com/htsnul/items/bbf230b8628598851e52

を参考にする。

## その他

「JIS X 0208 コード表」で検索すると答えは知ることができる。

しかし、JIS第一水準漢字を利用してそこから何か別のことをするためにはシェルスクリプトから生成できることが便利なことがある。
[Windows+WSL2]VSCode のphp...executablePath にDocker コンテナ内のPHPを指定する

## 経緯
新しく購入したWindows PC でVSCode を使い始めたら、PHP 関連の拡張機能に「php のパスが正しく通ってませんよ」と指摘される。

>Cannot validate since a PHP installation could not be found. Use the setting 'php.validate.executablePath' to configure the PHP executable.

![Screenshot_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/082e796f-542b-bd78-694d-d5b6c269463c.png)

Windows 自体にPHPを入れていれば問題ないのだけど、PHPは開発用Docker コンテナの中に入っているのみ。
PHPファイル自体、開発外で使うこともないので、VSCode にもローカルのWindows 環境ではなく
開発環境を参照しておいてほしい。

ので、コンテナ内のPHPへパスを通します。

## 環境
- Windows 11
- WSL2 (コマンドプロンプト/Powershell でubuntu コマンドが使える状態)
- Docker (WSL2内でdocker コマンドが使える状態) 

## やったこと
1. WSL2 内にコンテナのPHPを実行させるスクリプトを作成
1. Windows のVSCode で開いているプロジェクトのルートディレクトリにバッチファイルを作成
1. パスとしてバッチファイルの場所を指定

### 1. WSL2 にスクリプトを配置

ubuntu コマンドでWSL2 環境へ入ります。

/usr/local/bin へphp という名前のファイルを作成: 

```
sudo touch /usr/local/bin/php
```

権限を変更: 
```
sudo chmod +x /usr/local/bin/php
```

php の中身を変更: 

```
sudo vim /usr/local/bin/php
```

以下のように記載します。

``` php.
path=$(printf '%s\n' "${PWD##*/}")
cd /mnt/c/User/(プロジェクトのルートディレクトリ)
command="docker exec (コンテナ名) php "$@""
echo "Running php on docker (コンテナ名)"
$command
```

コンテナ名は起動中であれば、プロジェクトのルートディレクトリとかで`docker container ps` とすれば確認できます。

スクリプト内でdocker コマンドを使っているので、WSL2 にはDocker が入っていることが必要になります。
WSL2 上の準備はこれでオーケー。

一旦、WSL2 を抜けます。

```
exit
```

ubuntu run でphp を参照できることを確認します。

```
ubuntu run php -v
```

PHP のバージョンが返ってくればオーケー。

```
Running php on docker (コンテナ名)
PHP 8.0.16 (cli) (built: Mar  1 2022 00:31:45) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.16, Copyright (c) Zend Technologies
    with Xdebug v3.1.4, Copyright (c) 2002-2022, by Derick Rethans
    with Zend OPcache v8.0.16, Copyright (c), by Zend Technologies
```

### 2. Windows ローカルにバッチファイルを配置

バッチファイルはVSCode で開いているプロジェクトのルートディレクトリに配置します。

以下の内容でphp.bat を作成します。

``` php.bat
ubuntu run php %1
```

`%1` には引数が入ります。
試しに、バッチファイルを作成したディレクトリで次を実行します。

```
./php.bat -v
```

引数として`-v` を与えています。
先程と同様のPHP バージョン情報が返ってくればオーケーです。

### 3. バッチファイルの場所をパスとして指定

最後に、VSCode の`settings.json` 内の必要な箇所にバッチファイルのパス`./php.bat`を指定して完了です。

``` settings.json
...
    "php.debug.executablePath": "./php.bat",
...
    "php.validate.executablePath": "./php.bat"
}
```

### 動作確認

一度VSCode を閉じて再起動します。
最初に出たような通知が出ないことを確認します。


## 参考

以下のページが元になっています。

https://stackoverflow.com/questions/53501925/visualstudio-code-php-executablepath-in-docker

ここではWindows ではなくLinux 環境で動いているコンテナが対象となっていたため、Linux 上のシェルを直接パスに指定しています。
今回は更にそのシェルへ向かうバッチファイルをWindows 上に作成し、無理やりWindows 環境に応用しました。

シェルと同様の動作をするバッチファイルを作ればもっと事態は簡単かもしれません。
あと、スクリプトの中身はほぼ引っ張ってきただけなので、`path=$(printf '%s\n' "${PWD##*/}")` とか`echo "Running php on docker (コンテナ名)"` とかの記述はひょっとしたら要らないんじゃないかな、やっぱ。
画像で送られてきたソースコードを簡単にテキストに変換する方法


# この記事について
Teames や Slack などで「サンプルコードを送ります！」というメッセージに、ソースコードをスクショした画像が添付されてくることってありますよね。コードブロック使ってよ！コピペできないじゃん！などと思いつつ「ありがとうございます！」って返事したことありませんか？
そんな時、少しだけ心が穏やかになる ( 画像のソースコードをテキストに変換する ) 方法をご紹介しましょう。

:::note warn
注意
ここで紹介する方法では、使用する画像が Google Lens に送信されます。
秘密保持契約の対象となっているソースコードなど、お仕事で書かれたソースコードの画像を使用した場合、契約違反とみなされる場合があることに注意してください。
:::


# 環境
この記事で紹介している手順は、以下の環境にて動作を確認しています。
- Windows 10 Pro 21H2 ( OS Build : 19044.1741 )
- Chrome Version: 102.0.5005.63 ( Official Build ) ( 64bit )
- Brave Version: 1.39.120 Chromium: 102.0.5005.99 ( Official Build ) ( 64bit )

# ブラウザの設定 ( Google Lens 有効化 )
画像からテキストを抽出するために Google Lens を使用しますので、ブラウザの設定で Google Lens を有効にしておきます。
- Chrome
最新版ではデフォルトで有効になっていますので、特に設定の変更は必要ありません。
- Brave
  1. <code>URL</code> 欄に <code>brave://flags/#enable-lens-standalone</code> をコピー＆ペーストして開く
  1. <code>Enable Lens features in Chrome.</code> を <code>Enabled</code> に変更

# 変換手順
手順はたったの 4 ステップです。
1. テキストに変換したい画像をブラウザ ( Chrome or Brave ) で開く
1. 画像を右クリック > [ レンズで画像を検索 ] を選択
1. テキストに変換したい部分を選択して [ コピー ] をクリック
1. エディタに貼り付け

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/8e7f164f-01a7-b69e-ece4-da0ce8bc38b6.png)
![sample2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/41de8807-e8f5-2d2c-23f0-8551a83297dc.png)
![sample4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65765/1a5f5df7-68fb-2282-caa8-31be6d473b12.png)

# 最後に
需要は少ないかも・・・と思いつつ、ソースコード以外にも応用できるので記事にしてみました。誰かの問題解決の糸口になってくれると信じて。
VBA_11_Type_2_File_Folder_Date_Round_サンプル

Keyword
---
Type()
File
Folder
Date
CDate
Round

Sample Code
---
```vb:Typee２つ活用
Public Type BeforeFileInfo   
    BeforeFileName As String
    BeforeFileUpdatedDate As Date
    BeforeFileType As String
    BeforeFileSize As Long
End Type

Public Type AfterFileInfo
    AfterFileName As String
    AfterFileUpdatedDate As Date
    AfterFileType As String
    AfterFileSize As Long
End Type

Public Sub MySample20220609()
    Dim myFso As FileSystemObject
    Dim myFile As File
    Dim myFolder As Folder
    Dim myFolderStr As String
    Dim mySheet As Worksheet
    Dim i As Long, j As Long
    Dim myBfFileInfo(3) As BeforeFileInfo
    Dim myAfFileInfo(3) As AfterFileInfo
    
    Set mySheet = ThisWorkbook.Sheets("20220609")
    
    myFolderStr = "H:\2022\Input"
    
    Set myFso = New FileSystemObject
    
    With mySheet
        For i = 1 To 3
                myBfFileInfo(i).BeforeFileName = .Cells(i + 1, "B").Value
                myBfFileInfo(i).BeforeFileUpdatedDate = .Cells(i + 1, "C").Value
                myBfFileInfo(i).BeforeFileType = .Cells(i + 1, "D").Value
                myBfFileInfo(i).BeforeFileSize = .Cells(i + 1, "E").Value
        Next i
        
        j = 1
        For Each myFile In myFso.GetFolder(myFolderStr).Files
                myAfFileInfo(j).AfterFileName = myFile.Name
                myAfFileInfo(j).AfterFileUpdatedDate = CDate(myFile.DateLastModified)
                myAfFileInfo(j).AfterFileType = myFile.Type
                myAfFileInfo(j).AfterFileSize = Round(myFile.Size / 1024)
                j = j + 1
        Next
    End With
    
    For i = 1 To 3
        If myBfFileInfo(i).BeforeFileName <> myAfFileInfo(i).AfterFileName Then
            Debug.Print "Not Same FileName"
        End If
        If myBfFileInfo(i).BeforeFileUpdatedDate <> myAfFileInfo(i).AfterFileUpdatedDate Then
            Debug.Print "Not Same FileUpdatedDate"
        End If
        If myBfFileInfo(i).BeforeFileType <> myAfFileInfo(i).AfterFileType Then
            Debug.Print "Not Same FileType"
        End If
        If myBfFileInfo(i).BeforeFileSize <> myAfFileInfo(i).AfterFileSize Then
            Debug.Print "Not Same FileSize"
        End If        
    Next i
End Sub

```
Unityで音声スペクトルを使ったゲームを作ってみたい①

# はじめに
初めまして。初投稿するUnity初心者です。試行錯誤しながらゲームを作っていきたいと思ってます。
今回は自分の興味ある分野である音声信号処理とゲームを掛け合わせられないかなと考えて、音声周波数スペクトルでなんか作るかーとなりました。気長にやっていきます。

# 環境(一応)
* Unity 2020.3.32f1
* Visual Studio Code
* **マイク(USB2.0でつなげるやつ)**

# 最初にやったこと
まずProjectを2Dで作成しました。(スペクトルの図は2Dの印象が強いので...)
その後、以下のコードを作成して空のGameObjectにアタッチ。

~~~c#:MicTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MicrophoneController : MonoBehaviour
{

    void Start ()
    {
        var audio = GetComponent<AudioSource>();
        foreach (string device in Microphone.devices)
        {
            Debug.Log("Name: " + device);
        }
        audio.clip = Microphone.Start(Microphone.devices[0], true, 10, 44100);
        while (Microphone.GetPosition(null) <= 0) { }
        audio.Play();
    }

}
~~~

「とりあえずマイクがちゃんとUnityと連携してるかな～」ということを確かめたかったので、
①Unityに認識されているマイクのデバイス名を表示
②起動してから10秒間の間、音声を録音
③音声はそのまま再生
という順序で動くコードを以下の記事から~~パクり~~参考しました。勉強になります。
[DIYer Unityにマイク音声を取り込む](http://twinklesmile.blog42.fc2.com/blog-entry-182.html "DIYer Unityにマイク音声を取り込む")
この記事にある
~~~
audio.mute=true;
~~~
という部分で音声をミュートにしちゃって確認できなかったりするので、コードはちゃんとすべてに目を通したほうがいいですね...(筆者もそこでちょっともたつきました。反省。)

で、実行してみると...自分の声が跳ね返ってきました！わーい！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700020/d3110fb3-cde3-e6e0-6988-d23cb3f9c659.png)

また、こんな感じで認識しているマイクがConsoleウィンドウに表示されてます！
自分のだとUSBマイク、Oculusのマイク、ゲームのキャプチャボードのマイクが認識されていますね。これの先頭から
~~~
foreach (string device in Microphone.devices)
~~~
のMiicrophone.devicesの0,1,2,...番目に入っていく行くようです。使用するマイクのインデックスは要確認ですね。

# 次やりたいこと
次は実際にスペクトルを取得してみようと思っています。とりあえず今回はここまで。気長にやっていきます。それでは！
光量子で関数近似

# はじめに

量子計算には、　離散量　と　連続量　という二種類があります。

離散量を扱う目的では超伝導、イオントラップなどの実装が知られています。
離散量の場合、1量子は$0$か$1$か（あるいはその重ね合わせ）を取ります。状態は2つの複素数$\alpha,\beta$で指定できます。
量子の単位は　量子ビット　と呼ばれ、イオン2個なら2量子ビットです。

連続量を扱う目的では光量子などの実装が知られています。
連続量の場合、1量子の状態は無数の複素数で指定されます。
例えば光量子の”位置$x$”を基底と考えると $\int_{x=-\inf}^{x=+\inf} x_{coeff.}|x> dx$　のような形で書けます。イメージとして。
同じように運動量$p$は $\int_{p=-\inf}^{p=+\inf} p_{coeff.}|p> dp$となります。
また、$x,p$の他に光子の個数$n$に着目した表現方法もあり、
$\sum_{n=0}^{n=+\inf} n_{coeff.}|n>$
このようになります。
基本としては ${x,p}$表現　or ${n}表現$ を使います。
両者は（多くの場合は）基底のとり方が違うだけなので、互いに行き来が可能です。
量子の単位は　量子モード　と呼ばれます。光量子の場合、例えば飛行経路が明らかに違う光子2つは別物とみなせるので、2量子モードといいます。
それぞれの量子モードに対して「光子数」という概念がありますから、その合成系は
$\sum_{n=0}^{n=+\inf}\sum_{m=0}^{m=+\inf} n_{coeff.}|n> \otimes m_{coeff.}|m>$
このようになることに注意します。

連続量のほうが連続濃度だから何でもできそうじゃん！　と思うわけですが、
どんな値でも取りうるということは、所望の結果なのか所望でない結果だけども雑音で誤ってしまってそうなったのかが区別できないことを意味します。
つまり誤り訂正が出来ません。
誤り訂正をするには何らか「離散化」をせざるを得ません。

そうはいっても連続濃度でなにか遊ぼうということで機械学習とのコラボなど考えられています。
今回は連続量量子で機械学習してみます。

# 関数近似してみる

https://pennylane.ai/qml/demos/quantum_neural_net.html

このdemoを使います。
データは自分で生成します。

```python
X = np.linspace(-1,1,50,requires_grad=False)
Y = np.sin(np.pi*X,requires_grad=False)
```

demo通りやってみますが、計算が遅いので途中で学習を打ち切ります。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/56e54c5f-c6fa-dbf4-1a27-366aa05b2684.png)

目標(青色)になろうとしている量子回路出力(緑色)が見えますね。

層数を半分にしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/2c028285-7a96-3b85-f641-188b23b7994e.png)

あまり変わりません。

1層にまでしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/da125ca3-689e-cfce-2236-a0af4a406221.png)

さすがに精度が悪くなりました。

これだけみると、「ニューラルネットワークと同じ感じで使えそうじゃん」と思うわけですが・・・

# 落とし穴：入力データのスケールへの依存性

x -> 2x と置き換えたデータ（xを2倍)を近似させてみます。
すると・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/83c3b6f3-a35e-ef74-a780-cccec7f5710e.png)

全くできなくなります。
ちなみに離散量でもこれと似た現象が起きます。

言い過ぎになるかもしれませんが、そもそもsin(x)という目標自体が「この量子回路でうまく近似できるように恣意的に選ばれた例」だと思っています。
スケールすらも、もとからうまくいくように合わせこまれているのです。
sin(x)ができるから他の関数も当然できる　と誤解しかねませんので、イマイチ不親切かと思います。
「層数増やしたりすれば任意関数でうまくいくんじゃないの？」と思われるかもしれませんが、実際やってみるとそれも難しいです。モデルを大きくすると、パラメータ最適化がうまくできなくなることが知られているためです。

確かにパラメータ調整（機械学習）により量子回路出力を**ある程度**加工することは出来ますが、量子回路固有の性質（例えばデータを位相角に埋め込んだ場合は必ず$2\pi$周期性が出る）を消し去ることは出来ません。
ニューラルネットワークの場合は、活性化関数がsigmoidだからといって出力がsigmoidっぽくなってしまうことはあまりなかったかと思いますが、量子の場合はかなり引っ張られます。
なので、むしろ量子の性質が活きるような問題を考える/与えてやるという重要度が高いと思います。
量子を自分の色に染めようとすると、なかなか染まらなくて苦労します。

# 結論
・連続量で遊ぶのは楽しい
・量子機械学習も、量子の性質が活きるような問題を考える/与えてやることが重要かもしれない。
flutter clean コマンドを実行すると大量のエラーが出てしまう

# エラー概要
```
$ flutter clean
```
・上記のコマンドを実行したところ、ビルドエラーが大量に発生してしまった。
・importの行で「Target of URI doesn't exist」と表示されることから、キャッシュ等と一緒にパッケージも削除されてしまうことが原因であると推測できる。
![スクリーンショット 2022-06-10 0.07.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/852882/6739aea2-029d-f95a-b111-33bf626beb36.png)

# 解決方法
```
$ flutter pub get
```
・上記のコマンドで、パッケージを入れ直すことで解決する。
図解 io.TeeReader(Golang)

# はじめに

Goのioパッケージにはio.Readerやio.Writerのインターフェイスを有効活用するための便利なメソッドがいくつか用意されています。
自分はその中の一つである`io.TeeReader`の挙動を理解するのに手こずったので、備忘録として挙動や使い方を残しておこうと思います。

# [io.TeeReader](https://pkg.go.dev/io#TeeReader)とは

io.TeeReaderメソッドは、引数で渡したio.Readerを、読み込まれた内容を2番目の引数で渡したio.Writerに書き込むio.Readerに変換するメソッドです。
自分はio.Readerを進化させるメソッドだと理解しました。イメージはこんな感じです。
![スクリーンショット 2022-06-09 23.55.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455240/cccc8396-20ef-935f-1b7f-06d1ed09e2d5.png)

## サンプルコード

```go
package main

import (
	"fmt"
	"io"
	"os"
	"strings"
)

func main() {
	var r io.Reader = strings.NewReader("some io.Reader stream to be read\n")
	var w io.Writer = os.Stdout

	teeReader := io.TeeReader(r, w)

	buf := make([]byte, 1024)
	_, _ = teeReader.Read(buf)
	fmt.Println(string(buf))
}
```
https://go.dev/play/p/owSytpJ9d3k

実行結果
```sh
$ go run main.go
some io.Reader stream to be read
some io.Reader stream to be read // こちらがfmt.Printlnによる出力
```

上記の挙動を図にすると以下のようになります。

![スクリーンショット 2022-06-09 23.45.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455240/1fe77acb-5a19-a783-49a2-47e12d2c191e.png)

## ユースケース

ユースケースとしては、クライアントからの入力を読み込むと同時にログに出力する、といったものがあるらしいです(2)。
自分は1つの画像バイナリを複数の形式にデコードしたいときに使用しました。

# おわりに

ちなみにio.TeeReaderの語源は[Unixコマンドのtee](https://ja.wikipedia.org/wiki/Tee_(UNIX))らしいです(2)。たしかに、↑の図を見るとデータの流れがT字になっています。

記事を書いていて気がついたのですが、自分がTeeReaderの挙動をいまいち理解できなかったのは、そもそもio.Readerのイメージが正確では無かったからだと気が付きました。io.Readerは『Readメソッドを実装する構造体』という意味なので、「読まれる」側、つまり受動者です。

しかし、自分はio.Readerを「読む」側だと無意識のうちにイメージしてしまっていたので、理解に躓いたのだと思いました。


# 参考

1. [Goのioパッケージのメソッドを図示](https://christina04.hatenablog.com/entry/golang-io-package-diagrams)
2. [Goならわかるシステムプログラミング 4刷](https://www.lambdanote.com/products/go)
2. https://pkg.go.dev/io#example-TeeReader
[Java]APIサーバーからpush通知を送信できなくなってしまった。


## この記事について
筆者がJavaで構成されるアプリのAPIサーバーを修正していたところ、自前のApiサーバーからAppleのApnsサーバーへpush通知の送信リクエストができなくなってしまいました。その際に対処したことを備忘録として残しておきます。

## 経緯
Apnsサーバーへpush通知の送信リクエストができなくなってしまったのですが、その際サーバーには以下のようなエラーログが吐かれていました。

```
[ERROR] NotificationSender:70 certificateName: □ □ □.p12 / Exception: java.util.concurrent.ExecutionException: java.io.IOException: Stream closed before a reply was received
```

このAPIサーバーで使用しているライブラリはpushyというものです。

https://github.com/jchambers/pushy

筆者は上記のエラー文や、ライブラリ関係の文言でググってもなかなか原因がわかりませんでした。


## セットする変数を誤っていただけだった
結局プッシュ通知が送信できなかった原因は、このライブラリのApnsClientのインスタンスを生成する際にセットする変数の値が、開発環境の場合は
```
api.sandbox.push.apple.com
```
なのですが、誤って本番用の値
```
api.push.apple.com
```
をセットしていたことでした。この変数の値はApnsサーバーのドメインに当たるものです。
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns/

今回、Apnsへのリクエスト送信処理やpush通知の証明書に問題がなく、エラー内容からも原因が特定しにくかったため、原因特定に時間がかかってしまいました。。。
このライブラリを使用していない場合でも、Javaで構成したサーバーからApnsサーバーへ送信するエンドポイントが誤っていた際には似たようなエラーが発生するかもしれません(エラー内容は異なるかも)。

## まとめ
自前サーバーからApnsへpush通知が送信できない際には、一度送信先のエンドポイントを確認してみてください！
Visual Studio で React 開発の初期環境を整えたメモ

Visual Studio のプロジェクトテンプレート `React.js での ASP.NET Core` から開発を始めた際の初期環境構築メモ。

この記事ではフロント側の対応のみ記載する。

# 環境

* Visual Studio 2019
* Node.js 16.15.0
* npm 8.5.5
  * パッケージとして `sass` のみ追加
  * TypeScript は最初から入っている 3.9.10 を使う

# 整えた内容

## TypeScript のコンフィグ設定

Visual Studio では tsconfig.json ではなく、プロジェクトの ProjectName.csproj で TypeScript のコンフィグを設定する。

tsconfig.json を設置／編集しても設定内容が反映されず、 tsconfig.json 目線で検索してもなかなか情報が出てこないので、かなり、わかりにくい罠だと思う。

### 設定メニューから

まずは GUI ベースで設定する。

初期状態では ProjectName.csproj に TypeScript 系の項目が一切なくなんだか触りづらいため、まずは GUI にて設定。

1. Visual Studio のメニューから、 `プロジェクト` → `プロジェクト名 のプロパティ` を開く
1. `TypeScript ビルド` を開く
1. `TypeScript コンパイラ出力をディレクトリにリダイレクトする` に `ClientApp/dist` を設定する
1. 保存

これで出力先ほか、諸々の設定が ProjectName.csproj に書き出される。

### 直接

GUI で設定できない項目は ProjectName.csproj をソリューションエクスプローラ等から開いて、直接設定を記述する。

項目の参考は以下。

* [Compiler Options in MSBuild](https://www.typescriptlang.org/docs/handbook/compiler-options-in-msbuild.html)

#### 設定内容

```xml:ProjectName.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
    <TypeScriptSkipLibCheck>True</TypeScriptSkipLibCheck><!-- *.d.ts ファイルのエラー出力避け。 -->
  </PropertyGroup>
</Project>
```


## .gitignore

GitHub の [gitignore リポジトリ](https://github.com/github/gitignore) を使う。

以下を拝借し、ソリューションのルートに配置。

* [VisualStudio.gitignore](https://github.com/github/gitignore/blob/main/VisualStudio.gitignore)

### 追記

TypeScript のコンパイル先フォルダとして指定した `ProjectName/ClientApp/dist` を追加する。

消さないと Git のコミット候補に出てくるのでうっとうしい。

### .gitignore 設置前に無視ファイルをコミットしている場合

`git rm --cached` で消す。


## プロジェクト除外

外部ファイルや、コンパイル後のファイルはプロジェクトから除外する。

除外しないと移動用の検索で、開発者が直接触ることのないコードが引っかかってしまう。

### ProjectName.csproj の編集

ソリューションエクスプローラからファイルやフォルダを右クリックして「プロジェクトから除外」しても消えないときがあるので、 ProjectName.csproj を直接編集する。

```diff_xml:ProjectName.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
-   <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
+   <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**;$(SpaRoot)dist\**</DefaultItemExcludes>
  </PropertyGroup>

  <ItemGroup>
    <!-- Don't publish the SPA source files, but do show them in the project files list -->
-   <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
+   <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**;$(SpaRoot)dist\**" />
  </ItemGroup>
</Project>
```

## 入れ子設定の編集

Visual Studio にはファイルの入れ子設定がある。

プロジェクトテンプレートから始めたての状態だと、例えば以下の入れ子関係が用意されている。

* App.js → App.test.js
* packcage.json → packcage-lock.json

ソリューションエクスプローラ利用時、親の側にファイルが隠れるので便利だ。

### 設定の流れ

1. ソリューションエクスプローラ上部から、 `入れ子っぽいアイコン右側の ▼` → `カスタム設定の追加` を開く
1. ファイル名を入力し、テンプレートに `Web` を選択し、 `OK` 押下
1. 内容を好きに編集する
1. 保存

Windows ユーザーの場合、ユーザープロファイル内に保存される。

### 足した設定

```js:*.filenesting.json
{
  "dependentFileProviders": {
    "add": {
      "pathSegment": {
        "add": {
          ".*": [
            ".ts",
          ]
  // 略
      "extensionToExtension": {
        "add": {
          ".module.scss": [
            ".jsx",
            ".tsx"
          ],
  // 略
}
```

コンポーネント単位で CSS を管理したいため。

グローバルな設定は `src/globals/css` 的な場所に置く。
【yocto】デバッグログを仕込む方法

# はじめに
- yoctoのデバッグをしたい人向け

# 方法
- .bb/.bbappendには、以下のような文を挿入する
    - 1はログレベル。任意の数字を指定可能。
~~~
bbdebug 1 "message"
~~~
- .bbclassには、以下のような文を挿入する
    - 1はログレベル。任意の数字を指定可能。
~~~
bb.debug(1, "message")
~~~
- bitbakeに-Dオプションを指定することでデバッグログが出力される
    - Dの数で出力するログレベルが指定できる
        - -D=ログレベル1。ログレベル1以下のデバッグログを表示する。
        - -DD=ログレベル2。ログレベル2以下のデバッグログを表示する。
    - recipe-nameは任意のrecipe名
~~~
bitbake -D recipe-name
~~~
~~~
bitbake -DD recipe-name
~~~

# 例
####
- 適当なbbファイルにデバッグ文を追記する
    - ca-certificates_20190110.bbにログレベル1のデバッグ文を追記する
    - do_install_append()は、do_installの後に処理するための関数
~~~
takeshi@X250:~/yocto/poky/build$ cat ../meta/recipes-support/ca-certificates/ca-certificates_20190110.bb | tail -n 3
do_install_append() {
    bbdebug 1 "bb: hello"
}
~~~

- 適当なbbclassにデバッグ文を追記する
    - kernelsrc.bbclassにログレベル2のデバッグ文を追記する
~~~
takeshi@X250:~/yocto/poky/build$ cat ../meta/classes/kernelsrc.bbclass | tail -n 3
python () {
    bb.debug(2, "bbclass: hello")
}
~~~

- bitbake
    - -Dと-DDでデバッグ出力が違う
        - -Dでは、ログレベル1のデバッグ文が出力された
        - -DDでは、ログレベル1とログレベル2のデバッグ文が出力された
~~~
takeshi@X250:~/yocto/poky/build$ bitbake -D core-image-minimal | grep "hello"
DEBUG: ca-certificates-20190110-r0 do_install: bb: hello
~~~
~~~
takeshi@X250:~/yocto/poky/build$ bitbake -DD core-image-minimal | grep "hello"
DEBUG: /home/takeshi/yocto/poky/meta/recipes-kernel/perf/perf.bb: bbclass: hello
DEBUG: ca-certificates-20190110-r0 do_install: bb: hello
~~~

# 注意
- .bb/.bbappendにはbbdebugを使用すると説明したが、正確にはシェルスクリプトで処理を記載する場合にbbdebugを使用する。
- .bbclassにはbb.debugを使用すると説明したが、正確にはpythonスクリプトで処理を記載する場合にbb.debugを使用する。
- yoctoでは、pythonスクリプト/シェルスクリプトを選択して利用できるが、多くの場合、.bb/.bbappendはシェルスクリプト、.bbclassはpythonスクリプトで記述されている。
- sstate-cacheを使用している場合、前回ビルドの一部使用するため、デバッグログが出力されない場合がある。
PowerShellで外部ファイルを非同期実行する

## 背景
既存のexeファイルをマルチプロセスで実行したいと思い、PowerShellで実装できたので備忘のために記載します。
PowerShell 7 Preview.3というバージョンなら、ForEach-Objectの新機能である「ForEach-Object -Parallel」を使えるのですが、会社PCのPowerShellバージョンが5.1だったので、泣く泣く断念しました。

ForEach-Object -Parallelの詳細については以下サイトがとても参考になります。
[[PowerShell] ForEach-Objectの新機能、ForEach-Object -Parallel について](https://dev.classmethod.jp/articles/about-powershell-foreach-object-parallel/)

## 実装
サンプルとして、指定した時間待機をした後に、メッセージダイアログを表示するexeファイルを用意しました。

```batch:batファイル
@echo off
setlocal enabledelayexpansion

powershell -ExecutionPolicy Bypass -command MultiProcess.ps1

endlocal
pause
```

```powershell:ps1ファイル

# 非同期処理の関数
function ParallelForEach-Object
{
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$true, Position=1)][int]$para_num,         # 同時実行数
    [Parameter(Mandatory=$true, Position=2)][string]$process_name,  # プロセス名
    [Parameter(Mandatory=$true, Position=3)][scriptblock]$process,  # プロセススクリプトブロック
    [scriptblock]$begin={}, # ループの一番最初に実施したい処理のスクリプトブロック（今回は未指定です）
    [scriptblock]$end={},   # ループの一番最後に実施したい処理のスクリプトブロック（今回は未指定です）
    [Parameter(ValueFromPipeline=$true)][psobject]$inputObject  # パイプライン処理用のオブジェクト
  )
  begin
  {
    &$begin
    $jobs=@()
  }

  process
  {
    $jobs | Receive-Job

    while(@(Get-Process | ?{$_.ProcessName -eq $process_name})).Length -ge $para_num)
    {
      $jobs | Receive-Job
      start-sleep -Milliseconds 100
    }

    $jobs += Start-Job $process -argumentList $inputObject
    start-sleep -Milliseconds 2000
  }
  end
  {
    while(@(Get-Process | ?{$_.ProcessName -eq $process_name})).Length -ge 0)
    {
      $jobs | Receive-Job
      start-sleep -Milliseconds 100
    }
    $jobs | Receive-Job
    $jobs | remove-Job
    &$end
  }
}

$exePath = "c:\ConsoleApp3.exe"
$processName = [System.IO.Path]::GetFileNameWithoutExtension($exePath)

$objList = @()

# 実行するexeのパスや引数を指定する
# exeの引数として"人名"と"待機時間"を指定しています。
$list = @("Aさん","Bさん","Cさん","Dさん")
$cnt = 40
foreach($name in $list)
{
  $cnt -= 5;
  $objList += [PSCustomObject] @{
    exe = $exePath;
    args = "$name $cnt";
  }
}

# 同時実行数4でexeを起動する
$objList | ParallelForEach-Object 4 $processName {
  Start-Process -FilePath $args[0].exe -ArgumentList $args[0].args
}
```
```text:実行結果⓵
開始時間:2022/06/09 23:14:38
35秒待機しました。ようこそAさん
終了時間:2022/06/09 23:15:13
```
```text:実行結果⓶
開始時間:2022/06/09 23:14:40
30秒待機しました。ようこそBさん
終了時間:2022/06/09 23:15:10
```
```text:実行結果③
開始時間:2022/06/09 23:14:43
25秒待機しました。ようこそCさん
終了時間:2022/06/09 23:15:08
```
```text:実行結果④
開始時間:2022/06/09 23:14:45
20秒待機しました。ようこそDさん
終了時間:2022/06/09 23:15:05
```

## 説明
AさんからDさんの名前を表示するexeを同時実行で呼び出しています。
「Get-Process」メソッドで実行中のプロセス一覧から実行中のexeのプロセス名を確認しており、
そのプロセス名の数が「$para_num」変数で指定した数よりも少なければexeを実行するという仕組みで
同時実行数を制御しています。
位数が 3 mod 4 の場合の平方剰余の根の求め方

## 動機
何回読んでも忘れるのでメモ

## 目的
$y^2=k \pmod q$ の $y$ は存在して、その数を知りたい。
$q \equiv 3 \pmod 4$ で $q$ が奇数の素数の場合、根は簡単に求められる。

## 導出方法
$q$ は奇数の素数で、$q-1$は偶数。$\frac{q-1}{2}$ も整数になる。

ここで、
$y^2 \equiv k \pmod q$ の両辺に、整数の $\frac{q-1}{2}$ をかけると、

$(y^2)^{\frac{q-1}{2}} \equiv k^{\frac{q-1}{2}}$
$y^{p-1} \equiv k^{\frac{q-1}{2}}$

フェルマーの定理によれば、$x$ と $p$ が互いに素ならば、
$y^{p-1} \equiv 1 \pmod p$
なので、
$1 \equiv k^{\frac{q-1}{2}}$

両辺に$k$ をかけると、

$k \equiv k^{\frac{q-1}{2} + 1} = k^{\frac{q+1}{2}}$

位数が $q$ は $3 \bmod 4$ なので $q = 4n + 3\ ...\ (A)$ 
$(A)$ を代入して、

$k \equiv k^{\frac{q+1}{2}} = k^{\frac{4n + 3 + 1}{2}} = k^{\frac{4n + 4}{2}} = k^{2n + 2}$
$k \equiv k^{2n + 2} \ ... (B)$

ここで、
$y^2 \equiv k$

$(B)$を使って、

$y^2 \equiv k^{2n + 2}$

両辺の平方根を取って

$y \equiv \pm k^{n + 1}$

$q = 4n + 3\ ...\ (A)$ を $n$ について整理して

$4n = q - 3$
$n = \frac{q-3}{4}$ 

代入して、

$y \equiv \pm k^{\frac{q-3}{4} + 1} = k^{\frac{q+1}{4}}$

## 手順
平方剰余に $\frac{q+1}{4}$ を乗じると、その数の $\pm$ が根になる。
友達と個人開発したChrome拡張が便利すぎた

# はじめに

GitHubのIssueって使ってますか？

自分は普段、友達との開発ではGitHubのIssueを使ってタスク管理をしています。

個人開発したGitHub用のChrome拡張を自分たちで使ってみたら
とても便利だったので紹介したいと思います！
LGTMだと思ったらLGTMよろしくおねがいします！


# 開発したChrome拡張



:point_down_tone2:こちらです。　今なら無料でインストールできます。

https://chrome.google.com/webstore/detail/mokuren-for-github/nikennffbfoadbajdgnhlngjahofhdef?hl=ja



# なにが便利？
### Issueをサイドバーから開ける！

これが一番便利なところです！
Mokurenがない時には、Issueの一覧ページと詳細ページを
何度も行き来しなければいけませんでした。。。

**MokurenはIssue詳細をサイドバーで開いてくれる**ので、
Issueチェックの効率が爆上がりしました:clap:
![画面収録_2022-06-09_23_12_04_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486544/62a3114c-0f80-b2bf-db02-2276cca37a33.gif)




### Issueタイトルをコピーできる

Issue一覧から個々のIssueのURLをコピーできます。
SlackやプルリクのコメントにIssueのURLを載せたいときにとても便利でした:relaxed:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486544/fb0ab03a-e323-03af-72d6-b2966c5dac2a.png)

`Copy title with URL`でコピーしてSlackに貼り付けると、こんな感じ！
タイトルがついたURLリンクになるので、見る人に優しくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486544/fe766be3-6916-a9cb-f70d-df8a6bb1dc82.png)


### インストールするだけですぐ使える

ログインや初期設定などは要りません！
ストアからダウンロードしてすぐに使えます！便利！

https://chrome.google.com/webstore/detail/mokuren-for-github/nikennffbfoadbajdgnhlngjahofhdef?hl=ja

# 一緒に開発した友達
彼らも今回の開発についてのQiita記事を書いているので、見てみてください！
@imajoriri
@uesho
Visual Studio CodeでIntel oneAPIを使った開発をするための設定方法

# はじめに

Visual Studio CodeでIntel oneAPIを使った開発をするための設定方法を紹介します。

参考：[Using Visual Studio Code with Intel® oneAPI Toolkits User Guide](https://www.intel.com/content/www/us/en/develop/documentation/using-vs-code-with-intel-oneapi/top/ssh-development-top/ssh-wsl.html)

# 拡張機能のインストール

MarketplaceからIntel oneAPIのための拡張機能「Extension Pack for Intel(R) oneAPI Toolkits」をインストールします。

# WSLを使う場合

常にIntel oneAPIを使って開発を行う場合は、`~/.profile`または`~/.bash_profile`に以下の行を加えて、常に環境設定が行われるようにします。

```bash
. /opt/intel/oneapi/setvars.sh &> /dev/null
```

そうでない場合は、前述の拡張機能をインストールすると、「Environment Configurator for Intel(R) oneAPI Toolkits」という拡張機能がインストールされるので、VSCodeを開いた後に以下の手順でIntel oneAPIの環境設定を有効にします。

1. `Ctrl+Shift+P`でコマンドパレットを開く。
2. 「Intel oneAPI」と入力する。
3. 「Intel oneAPI: Initialize default environment variables.」を選択する。

新しいターミナルやプロセスから環境設定が反映されます。

# CMakeとの連携

まずVisual Studio Codeの拡張機能「CMake Tools」をインストールします。そのあと、以下の2つの方法でIntelコンパイラを使ってコンパイルするように設定できます。

## settings.jsonで設定する方法

プロジェクトディレクトリの`.vscode/settings.json`にて、プロジェクトで常にIntel Compiler ClassicまたはIntel Compilerを使うように環境変数として設定します。Intel Compiler Classicの場合は

```json:settings.json
{
    "cmake.configureEnvironment": {
        "C": "/opt/intel/oneapi/compiler/latest/linux/bin/intel64/icc",
        "CXX": "/opt/intel/oneapi/compiler/latest/linux/bin/intel64/icpc",
        "FC": "/opt/intel/oneapi/compiler/latest/linux/bin/intel64/ifort"
    }
}
```

Intel Compilerの場合は

```json:settings.json
{
    "cmake.configureEnvironment": {
        "C": "/opt/intel/oneapi/compiler/latest/linux/bin/icx",
        "CXX": "/opt/intel/oneapi/compiler/latest/linux/bin/icpx",
        "FC": "/opt/intel/oneapi/compiler/latest/linux/bin/ifx"
    }
}
```

この方法ではコンパイラを切り替えることができないので、次に紹介するCMake Kitsを使った方法をおすすめします。

## CMake Kitsを設定する方法

プロジェクトディレクトリの`.vscode/cmake-kits.json`にて、下記の様にIntel Compilerの設定を行います(パスはWSLの例)。

```json:cmake-kits.json
[
    {
        "name": "Intel Compiler Classic",
        "compilers": {
            "C": "/opt/intel/oneapi/compiler/latest/linux/bin/intel64/icc",
            "CXX": "/opt/intel/oneapi/compiler/latest/linux/bin/intel64/icpc",
            "Fortran": "/opt/intel/oneapi/compiler/latest/linux/bin/intel64/ifort"
        }
    },
    {
        "name": "Intel Compiler",
        "compilers": {
            "C": "/opt/intel/oneapi/compiler/latest/linux/bin/icx",
            "CXX": "/opt/intel/oneapi/compiler/latest/linux/bin/icpx",
            "Fortran": "/opt/intel/oneapi/compiler/latest/linux/bin/ifx"
        }
    }
]
```

参考：[CMake Tools | CMake Kits](https://vector-of-bool.github.io/docs/vscode-cmake-tools/kits.html)

設定した後は、コマンドパレットを開き、「CMake: Select a kit」を選択し、上記のいずれかのKitを選択してください。その後ConfigureとBuildを行うと、選択したコンパイラーでコンパイルされます。
【自分用】Rubyの基礎を振り返る。②

# はじめに
前回の続き。
【自分用】Rubyの基礎を振り返る。①

https://qiita.com/hondano_gentuki/items/25d71553b200808cfc2a

# Rubyのあれこれ②
### クラス
クラスは、値の元となるものです。値の共通のルールを定義。
ここで決めるルールは、共通の属性と処理（メソッド）。

例えるのであればクラスが設計図（雛形）でインスタンスが車（普通車・パトカー・スポーツカーなど。）
```
class Car
  # 変数やメソッドの定義
end
```

### インスタンス
クラスを元にして作られるデータ。クラスとは違い実態を持つ。

### newメソッド
クラスは、定義しなくてもnewという特別なメソッドをはじめから持っている。
使用したクラスのインスタンスを生成して返す。
```
# インスタンスを生成し変数で扱う
変数名 = クラス名.new
```

例：
```
class Car

end

fire_truck = Car.new  # Carクラスのインスタンスを生成
puts fire_truck  # インスタンスを出力
```

### インスタンスメソッド
インスタンスが使用できるメソッドクラスに定義しておく。
インスタンスメソッドは、インスタンスごとの個別の情報（属性値）を使った処理に使用する。
```
class クラス名
  def メソッド名
    # 処理
  end
end
```

インスタンスメソッドの呼び出し
```
インスタンス名.メソッド名(引数)
```

例：
```
class Car

  def ride_car()
  end

end

fire_truck = Car.new()
fire_truck.ride_car()
```

### インスタンス変数
データが持つ属性を定義する変数。
インスタンス変数は、クラス内のメソッドの中で、変数名の始めにアットマーク`@`を1つつけて定義。
```
class クラス名
  def メソッド名
    @変数名 = 値  # インスタンス変数
  end
end
```
例：
```
class Car
  def ride_car(ride_number)
    @ride_number = ride_number
  end
end

fire_truck = Car.new()
fire_truck.ride_car(3)
```

### クラスメソッド
クラスが使用できるメソッド。クラスで共通の情報を使った処理に使用。
```
class クラス名
  def self.メソッド名
    # 処理
  end
end
```
クラスメソッドの呼び出し
```
クラス名.メソッド名(引数)
```
newメソッド
```
# インスタンスを生成するためにクラスメソッドとして定義されている
user = User.new
```
例：
```
class Car

  def self.run
    puts '走行します'
  end

  def ride_car(ride_number)
    @ride_number = ride_number
  end

end

fire_truck = Car.new()
fire_truck.ride_car(3)

Car.run
```

## メソッドと変数の違いを整理
|  | クラスメソッド | インスタンスメソッド |
|:-:|:-:|:-:|
| 概念の違い  | クラス全体で共通したふるまい  | クラスから生成されたインスタンスのふるまい  |
| 使い方の違い  | 定義するときは、self.を頭につける。クラスのみに用いることができる。  | インスタンスのみに用いることができる  |
| コード  | def self.メソッド名end  | def メソッド名 end  |

|  | ローカル変数 | インスタンス変数 |
|:-:|:-:|:-:|
| ふるまい | 記述してあるインスタンスメソッド内でしか使用できない  | 別のインスタンスメソッド内でも使用できる  |
| 書き方 | 何も頭につかない  | 頭に@がつく  |

### initializeメソッド
インスタンスが生成された瞬間に、生成されたそのインスタンスが実行する処理を定義するインスタンスメソッド。
```
class クラス名
  def initialize
    # インスタンス生成したときに実行される処理（以下は例）
    puts "クラス名のインスタンスが生成されました"
  end
end

インスタンス = クラス名.new  # initializeメソッドが呼ばれ文字が表示される
```
例：
```
class Car

  def initialize(car_name, car_model, capacity)
    @name = car_name
    @model = car_model
    @capacity = capacity
  end

  def self.run
    puts '走行します'
  end

  def ride_car(ride_number)
    @ride_number = ride_number
  end

end

fire_truck = Car.new('消防車', '大型車', 5)
fire_truck.ride_car(3)

Car.run
```

### 終わりに
以上の2記事がRubyの基礎部分。
というか基礎のきの半分くらい。もしかしたらきの半分の半分かもしれない。
でも基礎概念大事！
ラズパイの【libcamera】を使ってみた。

ラズパイのlicameraのセットアップではまったので、セットアップ方法についてまとめます。

# 環境
環境は、下記の通りになります。

Python version: 3.7.3
OS: Raspbian 10.0
RaspberryPi4 

# 設定
ラズパイのメニューボタン上で、「インターフェイス」タブをクリックし、「カメラ」が「有効」になっていることを確認します。
ラズパイにカメラを接続し、ラズパイのターミナル上で下記コマンドを打ち込みます。
```
vcgencmd get_camera
```
このコマンドは、カメラモジュールが正常に接続されているかの確認しています。下記のように出力されていれば、OKです。
```
supported=1 detected=0, libcamera interfaces=1
```

```boot/config.txt```の末尾にカメラモジュールに合わせて、dtoverlayを追加します。私は、V2カメラを使用しているので、```dtoverlay=imx219```を追加しています。

|    Camera Module    |   Markdown      |
|:-------------------:|:---------------:|
| V1 camera (OV5647)  | dtoverlay=ov5647| 
| V2 camera (IMX219)  |	dtoverlay=imx219|
| HQ camera (IMX477)  | dtoverlay=imx477|
| IMX290 and IMX327   |dtoverlay=imx290,clock-frequency=74250000 <br> dtoverlay=imx290,clock-frequency=3712500|
| IMX378              | dtoverlay=imx378|
| OV9281              | dtoverlay=ov9281|

ここで注意が必要です。[Introducing the Raspberry Pi Cameras](https://www.raspberrypi.com/documentation/accessories/camera.html#getting-started)をみると、下記のように記載がありました。

> Raspberry Pi 3 and older devices may not by default be using the correct display driver. Refer to the /boot/config.txt file and ensure that either dtoverlay=vc4-fkms-v3d or dtoverlay=vc4-kms-v3d is currently active. Please reboot if you needed to change this.

今回、```RaspberryPi4```を使用していたのですが、```boot/config.txt```の```dtoverlay=vc4-fkms-v3d```は、必要でした。

```boot/config.txt
dtoverlay=vc4-fkms-v3d
dtoverlay=imx219
```

リブート後、下記コマンドを実行すると、確認ができます。
```
libcamera-hello
```

### 余談
デバックでカメラを買いなおしたり、ラズパイの再設定をしたりして、状況改善せず、結局新しいモジュールに合わせて```boot/config.txt```を書き換えないといけないというオチでした。動いてよかった。。。