OmniAICreator/Qiita-1.07M huggingface dataset:
ChromeBookで挫折したこと

本記事は、[めんどい太郎の Advent Calendar 2023](https://qiita.com/advent-calendar/2023/mendoitarou_first_calendar) 24日目の記事です。

# はじめに

この記事は初心者が書いています。

今回はしばらくChromebookをメインPCで使ってきた中で挫折したこと、できなかったことをご紹介します。

# Chromebookのスペック
私が使用しているChromebookのスペックを少し紹介しておきます。

```
CPU: Intel(R) Celeron(R) N4500
MEM: 4GB
ROM: 32GB(eMMC)
```

# 挫折したこと
## Raspberry Pi Zero Wのセットアップ
アドベントカレンダーの21日目の記事[^1]のやつです。

USB OTGを使用したssh接続ができませんでした。

これに関してはWindowsやMac、UbuntuなどのLinuxでしかできなさそうだな〜と感じてはいました。

まぁしょうがないですね。

## Unity
Unityがもしかしたら使えないかな...と思いインストールしてみました。

容量ギリッギリですがインストール自体は無事に終了しました。よかった。

UnityHubでプロジェクトを作成し、起動してみます。

...エラーメッセージが表示され何度やっても起動しません。

スペック不足なのか、ChromeOSの仮想Linuxだからなのか...

まぁ何度やってもできませんでした。

## AndroidStudio
ChromeOS用Android Studioがリリースされたとの噂を聞きつけ、インストールしてみました。

インストールに成功し、起動もできましたが...めちゃ重い。

これに関しては推奨スペックもかなり要求が高いので仕方がないです。

あと容量不足でビルドができません。

残念。

## Raspberry Pi Pico(Tohnny)の使用
これに関しては僕の環境が悪いです。

友達は普通に使えています。

私の環境はLinuxを再インストールしてもなぜかMicroPythonとRaspberry Pi Picoが選択肢に表示されませんでした。

謎。

なぜなんでしょうね...

### 追記

Thonnyをapt経由でインストールするとこうなってしまいます。

Thonnyの公式GitHub Repositoryの[Releases(Latest)](https://github.com/thonny/thonny/releases/latest)から``thonny-~.~.~.bash``をダウンロードし、実行する方法でインストールをするとRaspberry Pi Pico用のMicroPythonが表示されます。

# 逆に意外とできたこと
## wine
wineは意外と動きました。

PC Watchさんの記事[^2]が非常に参考になります。

ただし容量がガッツリ減るので実用は無理だと思います。

## Steamでゲーム
軽いゲームなら全然動きます。

アドベントカレンダーの15日目の記事[^3]なんかで紹介したHacknetはたまーにFPSが急降下しますが普通に動きます。

他には[Open TTD](https://store.steampowered.com/app/1536610/OpenTTD/)なんかも普通に遊べます。

しかしOpen TTDは日本語化が少々面倒です。

そんな感じで軽いゲームなら普通に動きます。

# 終わりに
Chromebookで挫折したこと、おまけに意外とできたことを紹介しました。

Chromebookでガッツリ開発は無理ですね。


[^1]:[ChromebookでRaspberryPiZeroを使いたかった](https://qiita.com/mendoitarou_/items/07655de87350be9e97e5)

[^2]:[Chrome OS Flexと最新版Wine 7.0の組み合わせでWindowsアプリを動かしてみる](https://pc.watch.impress.co.jp/docs/column/nishikawa/1401328.html)

[^3]:[Hacknetのすゝめ](https://qiita.com/mendoitarou_/items/3f8bd64fa60c381507f0)
[CDGC] 2023.12 Microsoft Edge向けInformatica QuickLook

# はじめに

<!-- ★『インフォマティカが提供する、 CDGC(データガバナンスとデータカタログ)を使って』までは定型文 -->
[インフォマティカ](https://www.informatica.com/jp/)が提供する、 [CDGC](https://www.informatica.com/jp/products/data-governance/cloud-data-governance-and-catalog.html)(データガバナンス＆カタログ)において、2023年12月にリリースされたバージョンで、QuickLookブラウザ拡張機能が、新たにMicrosoft Edgeにも対応しました。
※2023/12時点の情報を元にしています。

# QuickLookとは？
2023.11 リリースにて追加された機能で、詳細は下記の記事をご覧ください。

https://qiita.com/masatoshimada-max/items/cc18d4407e487473fcda

# 2023.12 リリース
Google Chromeブラウザに加え、Microsoft EdgeブラウザにもInformatica QuickLookブラウザ拡張機能をインストールして使用できるようになりました。

利用方法などは、基本的に、Chrome版と同じとなっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110338/ed33ed1b-9cca-1e33-0425-ee25029679fc.png)



# 参考文献
<!-- ★URLをそれぞれのカタログ・ソースに応じて変更する -->
- [**Install the browser extension on Microsoft Edge** *ログインが必要](https://docs.informatica.com/data-governance-and-quality-cloud/data-governance-and-catalog/current-version/informatica-quicklook-browser-extension/set-up-informatica-quicklook/install-the-browser-extension/install-the-browser-extension-on-microsoft-edge.html)

- [**2023.12 What's new** *ログインが必要](https://docs.informatica.com/data-governance-and-quality-cloud/data-governance-and-catalog/current-version/what-s-new/december-2023/new-features-and-enhancements.html)
ラベルごとに仕分けしたメールをGoogle Apps Script(GAS)を用いて毎日自動でアーカイブ化する

# 概要
使っているGmail宛に色々なメールが届いていますが，「すべての受信トレイ」をよく見る自分からすると，会社用メールとプライベートメールがごちゃまぜになるのは余り気分がよくありません．なので毎日会社用メール宛に届く似たようなメールはラベル付けを行ってGASで自動的にアーカイブ化するようにします．

## ラベル付けとフィルタリング設定
Gmailの左下にあるラベルの「+」からラベルを作成できます．
![label.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469304/6bf0446f-7edd-4db0-c9a3-472afedde15c.jpeg)
そこから自分がメールのフィルタリングしたいラベルを作成します（例: AWS，GitHubなど)
次にGmailの設定から「フィルタとブロック中のアドレス」をクリックします．
![filter_and_block_addresses.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469304/46aa63d0-eadf-6ff7-9b61-a5b41d2eeddb.jpeg)

次にフィルタリング設定を行います．メールの宛先や件名から既存のメールをフィルタリングすることができます．
下記の画像では，Googleカレンダーをフィルタリングしたので「calendar」を含む設定にします．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469304/0742658b-6ca7-a0d7-f25e-680548064b2e.png)
次に「フィルタを作成」をクリックします．

メールが設定した条件に完全一致する場合に実行するものを選択できます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469304/d5fc880c-996a-e1ef-38d4-af7eac19d3dd.png)
今回の場合は以下を選択します．
- 受信トレイをスキップ（アーカイブする）
- ラベルを付ける: (作成したラベル）
- 一致するスレッドにもフィルタを適用する．

上記で問題がなかったら「フィルタを作成する」をクリックすることでフィルタが作成されます．
作成したラベルをクリックすると，検索条件に基づいたメールがアーカイブ化されています．

## 新たに受信したメールをGASを用いて自動的にアーカイブ化
上記のやり方はすでに受信したメールをアーカイブ化することができますが，新たに受信したメールは手動でアーカイブ化するしかありません．それはやりたくないので，Google Apps Scripts(GAS)を用いて新たに受信したメールは1日後にアーカイブ化するようにします．

以下がコードになります．

```js
function archiveLabelEmails() {
  // 昨日の日付と今日の日付を取得
  var yesterday = new Date();
  yesterday.setDate(yesterday.getDate() - 1);
  var today = new Date();
  
  // 昨日の日付と今日の日付をYYYY/MM/DD形式の文字列に変換
  var yesterdayString = Utilities.formatDate(yesterday, Session.getScriptTimeZone(), 'yyyy/MM/dd');
  var todayString = Utilities.formatDate(today, Session.getScriptTimeZone(), 'yyyy/MM/dd');

  // すべてのラベルを取得
  var labels = GmailApp.getUserLabels();
  // 各ラベルに対して処理を行う
  for (var i=0; i < labels.length; i++) {
    var label = labels[i];

    // ラベルが付与されているメールスレッドも取得
    // ラベルが付与され、日付が一致するメールを検索
    var searchQuery = 'label:' + label.getName() + ' after:' + yesterdayString + ' before:' + todayString;
    var threads = GmailApp.search(searchQuery);
    
    // 各スレッドをアーカイブ
    for (var j = 0; j < threads.length; j++) {
      threads[j].moveToArchive();  
    }
    Logger.log("Completed: " + label.getName());
  }
}
```
上記のコードをデプロイします．
次にトリガーを設定します．
自分の場合は毎日午前0字から1時の間に上記のコードを実行するようにしています．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469304/28ef7407-df84-bd7e-8c06-f8d6cf90252c.png)
上記を設定することで，新たに受信したメールでも，1日後にはメールをラベルごとにアーカイブ化することができます．

# 終わりに
基本的に毎日受信するメールは似たような内容のものが多いので，ラベル付けによるフィルタリングとGASをうまく利用することで本当に重要なメールを確認することができます．
本記事が参考になったら幸いです．

# 参考文献
- https://capotast.co.jp/article/detail/16/
- https://dekiru.net/article/17161/
[CDMP] 2023.11 リリースまとめ

# はじめに

<!-- ★『インフォマティカが提供する、 CDGC(データガバナンスとデータカタログ)を使って』までは定型文 -->
[インフォマティカ](https://www.informatica.com/jp/)が提供する、 [CDMP](https://www.informatica.com/jp/products/data-governance/cloud-data-marketplace.html)(クラウド データ マーケットプレイス)にて、2023年11月にリリースされた内容について記載します。
※2023/12時点の情報を元にしています。

# 2023.11 リリースとは？
2023年11月に新しい機能を含むリリースとなり、関連製品のCDGCと同様に、CDMPも多くの新機能がリリースされました。
- マイデータページの追加
- オーダーの強化
- データコレクションの検索強化
- リンクデータ・アセット作成プロセスの強化
- オーダーページの消費者アクセスリンクを閲覧
- データコレクションを評価したユーザーを表示する
- デフォルトの配信テンプレートを削除する
- デリバリー・ターゲットの削除
- データコレクションに関する記述の変更

以下、主要な部分を解説いたします。

# マイデータページの追加

今までの画面。メニューに「所有しているデータ」、「使用しているデータ」を表示していました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110338/6f05394b-1460-e339-e125-d3795c835585.png)

新しい画面。メニューに「マイデータ」が追加。その詳細画面にて、「所有しているデータ」、「使用しているデータ」を表示し、メニューがすっきりしましたね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110338/4fc61a57-1cbc-fe32-984d-43930e908223.png)

# リンクデータ・アセット作成プロセスの強化
データカタログのCDGC側のアセットを確認するのに、下記の項目も表示されるようになり、アセット選択の精度を上げる事ができるようになりました。
- ビジネス名
- ソースパス 説明
- 技術データアセット
- 階層
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110338/ccdec5fb-9f3a-c02a-4daa-482343cc3bc1.png)


# 参考文献
<!-- ★URLをそれぞれのカタログソースに応じて変更する -->
- [**マニュアル** *ログインが必要](https://docs.informatica.com/data-governance-and-quality-cloud/data-marketplace/current-version/what-s-new/2023-november/new-features-and-enhancements.html)
【Swift】キャストとは

# キャストとは？
キャストとは変数や定数の型を、より具体的な型や抽象的な型として扱うことです。

## 具体的な型や抽象的な型とは？

抽象化の例としては
・ポチ→犬→動物
・にんじん→野菜→植物

このように構造上でより広い意味へシフトしていくのが抽象化です。
swiftではこれを<b>アップシフト</b>といいます。
これの逆が具体化です。

例：・動物→犬→ポチ
　　・植物→野菜→にんじん
これを<b>ダウンシフト</b>といいます。

# アップキャスト
アップキャストは構造上でより広い意味へシフトしていくことでしたね。
これをコードで書く場合は<b>「as」</b>を用います。

```swift
let a = "あいうえお" as Any
```
このコードではString型である「あいうえお」をより広いAny型へアップキャストしています。

間違ったコード例です。
```swift
//間違った例
let int = "あいうえお" as Int
//→エラー
```
これはString型からInt型へアップキャストをしようとしていますが、String型からInt型へはより広い意味にはならないためエラーが発生します。

# ダウンキャスト
ダウンキャストの意味は構造上より具体的な型へシフトさせることでしたね。
ダウンキャストのコードの書き方は2種類あります。
①as?を用いる
②as!を用いる
それぞれ見ていきたいと思います。
## ①as?を用いたダウンキャスト

```swift
let b = 1 as Any //1(Int型)→Any型へアップキャスト
let c = b as? Int //1(Int型)→Any型へアップキャスト
```
こちらがas?のコード例となります。
次は間違った使用例を見てみましょう。
```swift
let b = 1 as Any //1(Int型)→Any型へアップキャスト
let c = b as? Int //Any型からInt型へダウンキャスト
let d = let c as? String //dにはnilが代入される。間違った使用方法
//Int型からString型はより具体的になっていない
```
こちらが間違ったas?の使用例になります。
先ほどのコードの続きとして書きました。
これはInt型からString型へはより具体的な型にはなっていませんね。

## ②as!を用いる

```swift
let e = 1 as Any //1(Int型)→Any型へアップキャスト
let f = e as! Int //1(Int型)→Any型へアップキャスト
```
こちらがas!を用いたコード例です。
同様に間違った使用例を見ましょう。
```swift
let e = 1 as Any //1(Int型)→Any型へアップキャスト
let f = e as! Int //1(Int型)→Any型へアップキャスト
let g = f as! String //エラーが出て処理落ちする
```
こちらが間違ったas!の使用例です。
as?と同様より具体的な型になっていませんね。
違いとしてはas?の違いとしてはnilが代入されるのかエラーになるのかですね。
これについてはオプショナル型のラップ、アンラップを理解する必要があります。
これについては別途記事にしようかと思います。
.NET 8 の Blazor WebAssembly は高速化されたというのでベンチマークで比較してみる

## .NET 8 の Blazor WebAssembly には Jiterpreter が搭載!

.NET 8 より前の Blazor WebAssembly では、AOT コンパイルを有効にしない限り、.NET アセンブリ内の IL コード (中間言語) は、WebAssembly 上で稼働するインタープリターによって逐次実行されます。インタープリター方式なので、演算処理性能的には極めて不利なのです。もちろん、遅すぎてどうにもこうにもならないということはなく、インタープリターにしては結構高速に動作し、多くの Web アプリケーションではさほど演算処理性能を要求しないため充分な性能です。ですが、やっぱりインタープリターである以上、限界はあります。

AOT コンパイルを有効にすれば、MSIL ではなく WebAssembly バイトコードが発行時に生成されるため、演算処理性能に関しては解決可能です。ただそれと引き換えに、発行時間が分単位と長くなり (まぁ、発行時間くらいは我慢できるケースも多いかもです)、コンテンツサイズが 2 倍かそれ以上に膨らみます。

そのような背景下、2023年11月にリリースされた .NET 8 では、Blazor WebAssembly の MSIL インタープリターに **"Jiterpreter"** と呼ばれる、一部コードを**実行時**に **WebAssembly バイトコードネイティブに変換** (JIT、つまり Just In Time、"ちょうどそのときに" コンパイルする機能) して処理速度を稼ぐ、という技術が搭載されるようになりました。フルセットの JIT コンパイラではなく、あくまでも基本動作はインタープリターであるため、"JIT" + "Interpreter" = "Jiterpreter" という造語で呼んでいるようです。これは、.NET 8 における Blazor WebAssembly の MSIL インタープリターとしての機能であるため、プロジェクト側で何か指定や設定をすることなく、タダでついてきます。

つまり、**.NET 8 の Blazor WebAssembly は、それより前の世代の Blazor WebAsembly より、演算処理性能が向上している**、というわけです。

ということで、ではいったいどれくらい早くなるのか、かなり雑なベンチマークになりますが、.NET 6、7、8 それぞれの速度を比較してみました。

## 速度比較の題材

4032 x 2016 ピクセルの画像 (下図) を白黒画像化する、そのような Blazor WebAssembly アプリケーションを作成し、.NET 6、7、8 それぞれでリリース構成で発行して、それぞれ白黒画像化にかかる時間を計測します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58450/7abecb3a-b7ea-e9e0-cba7-be49ebdd8725.png)

画像データは 1 ピクセルあたり 4 バイトで R、G、B、A の各値を1バイトで持ち、これを一次元の `byte` 配列に持ちます。この画像データ (`byte[]`) を白黒画像化して上書き変更する処理を、以下のように実装しました。

```cs
public static void ConvertToGrayScaleByDotNet(int sx, int sy, byte[] pixelData)
{
    for (var x = 0; x < sx; x++)
    {
        for (var y = 0; y < sy; y++)
        {
            var ir = (x + y * sx) * 4;
            var ig = ir + 1;
            var ib = ir + 2;
            var r = pixelData[ir];
            var g = pixelData[ig];
            var b = pixelData[ib];
            var m = (byte)Math.Round(0.3 * r + 0.6 * g + 0.1 * b);
            pixelData[ir] = pixelData[ig] = pixelData[ib] = m;
        }
    }
}
```

ものすごくシンプルな演算処理ですね。

## 結果発表

では以下に測定結果です。

なお計測ですが、テスト用 PC 上でサーマルスロットリングの発生に注意しながら、各バージョン 5 回実行し、最後の 3 回の平均値を取ってみました。

対象プラットフォーム | 処理時間 (秒)
-------------------|--------------
.NET 6             | 0.67
.NET 7             | 0.79
.NET 8             | 0.41

なぜか .NET 7 より .NET 6 のほうが 100 msec 以上速いのが気になりますが、さておき、.NET 8 では、フルの JIT ではないとはいえ、明らかに高速化されていることがわかります。**.NET 7 に対して 1.8 倍以上**、**.NET 6 に対しても 1.6 倍近く**高速化しています。

(ちなみに AOT コンパイルすると、処理時間は 0.10 秒にまで短縮されます。)

## まとめ

多くの Web アプリケーションでは、ここまでの演算処理性能が求められることは少なく、そのような多くの Blazor WebAssembly アプリケーションではこの .NET 8 の Blazor WebAssembly における Jiterpreter 技術の恩恵も少ないのかもしれません。

とはいえ、.NET 8 に移行するだけで、それ以上の追加の手間も何もなしに、且つこれといったトレードオフもなく、演算処理性能の向上が見込まれるのは歓迎されるべきことでしょう。

以上です。

Happy Coding! :)
スマートフォルダって知ってた？意外と知らないMacの便利なファイル検索

## はじめに
今までこんなことで困ったことありませんか？

**昔作ったたファイルがどこにもない！！！！！**

恥ずかしい話ですが、筆者は大学生時代死ぬほどファイルを失くして困っていました。

さて、ファイル名が分からず、履歴で参照できない場合は、拡張子や残された手がかりを元にファイルの検索を行うしかありません。

複数条件を使った高度な検索は`find`コマンドでもできますが、条件を逐次的に付け加えてコマンドを打つのは意外と大変です。

今回はMac限定ではありますが、Finderの「スマートフォルダ」を用いた検索をご紹介します。

## スマートフォルダの使い方
まずFinderを右クリックして「新規スマートフォルダ」を選択します。

![ 2023-12-17 19.52.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/b2d8bcc4-e72d-147d-b93a-051b088890a5.png)

次に下記画面の保存の右隣の`+`ボタンを押して条件を追加してください。

![ 2023-12-17 19.59.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/746074a0-09c1-912d-2065-cc578058ec45.png)

例えば以下の3つの条件を満たしたファイルを簡単に検索できます。

- pdf
- 半年以内に開いた
- 名前にLLMを含む


![ 2023-12-17 20.02.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/05689738-825d-8d5b-281f-bf2a13eab1dc.png)

とても簡単ですね！！！

## スマートフォルダの良さ
:::note
### 条件をGUIで簡単に追加できること
:::
前述しましたが、なんといっても使い方がわかりやすいです。`find`などのコマンドのオプションを一々調べる手間が生じるないのが利点です。

:::note
### ファイル名+ファイルイメージ付きで検索できる
:::
ファイル検索の途中結果をファイルイメージ付きで確認できるのが地味に便利です。

ファイル名を思い出せないくらい断片的な記憶だと、該当のファイルを検索できたところで、お目当てのファイルかどうか判定に時間がかかります。ヒトにとってフレンドリーな検索ができるのがスマートフォルダの強みです。


## おわりに
いかがだったでしょうか。

筆者はCUI信者の側面もあるのですが、Macのファイル検索に関してはスマートフォルダ一択かな、という気がしています。

ぜひ困った時に使ってみてください。
PyCharmの有償版機能まとめ

無償版（Community）でも十分に活躍できるPyCharmですが
コーティングがもっと快適になる有償版（Professional）の機能についてまとめてみました。
※全部は書ききれないので一部を抜粋しています。


## [フルラインコード補完](https://pleiades.io/help/pycharm/auto-completing-code.html#full-line-code-completion)
最近追加された機能です。
巷で流行っているいわゆるAIコーティング支援機能は別枠での有償扱い（JetBrains AI Pro）なのですが
こちらは完全ローカル内で動作するものだそうで、記入中のコードに対して続くものを薄く表示してくれます。
そして、そのままTABキーを押すと反映されます。

## [重複を分析する](https://pleiades.io/help/pycharm/analyzing-duplicates.html)

気が付かない内に同じコードを書いている場合があります。
それを検知し、お知らせしてくれる機能です。

## [リモート PyCharm によるデバッグ](https://pleiades.io/help/pycharm/remote-debugging-with-product.html)

SSH経由でサーバー上でのpythonを実行することができます。
ただ実行するだけではなく、ファイルの転送やデバッグ実行も可能です。
手間が大幅に減るのでおすすめです。

## [JavaScript のデバッグ](https://pleiades.io/help/pycharm/tutorial-debugging-javascript-with-product.html)
フロントエンドに詳しく無くてもjavascriptのコーディング支援機能があります。
書き方が間違っているとか、この変数は未定義だとか指摘してくれます。

## [データベースツールおよび SQL](https://pleiades.io/help/pycharm/relational-databases.html)
SQLファイル(.sql）やコード内のSQL文について誤りを指摘してくれたり、
DBへ直接接続するクライアントが内蔵されています。
また、接続したDBのテーブルとカラムが違うなど不整合もチェックできます。


## 総評

無償版（Community）でも十分強力な機能があるPyCharmですが
有償版（Professional）を使うとさらに痒いところに手が届く優秀なIDEです。
　
最近リリースされたAIコーティング支援機能（JetBrains AI Pro）はさらに別枠の有償機能です。
プレビューで試してみた時点でもチャットで自分の中に無いノウハウの提案、コードを読み解いての説明、
エラーメッセージの解説、コミットメッセージの提案など魅力的な機能が満載です。
利用者のレビューを見つつ、契約してみるのも快適なコーディングライフになりそうです。
なお、JetBrains製品が[2024年1月15日に値上げ](https://samuraism.com/2023/11/11/14865)されるようなので早めがよいかもしれません。
1.69inchの液晶Displayをxiaoで動かしてみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146663/d0e6cbef-17be-210f-84bf-55b43dc9aa92.png)

1.69inchの液晶Displayです。
xiaoとSPIで接続して動かしてみます。

http://www.lcdwiki.com/1.69inch_IPS_Module

今回はAdafruitのGFXライブラリではなく以下のArduino_GFXライブラリをインストールしました。
※Adafruitのライブラリではうまく動作しませんでした...

https://github.com/moononournation/Arduino_GFX


HelloWorldのサンプルプログラムのコメントにある通りにxiaoを配線します。

```
* Seeeduino XIAO dev board    : CS:  3, DC:  2, RST:  1, BL:  0, SCK:  8, MOSI: 10, MISO:  9
```

プログラム中の以下の箇所を液晶Displayの解像度に合わせます。

```
Arduino_GFX *gfx = new Arduino_ST7789(
  bus, 7 /* RST */, 0 /* rotation */, true /* IPS */,
  240 /* width */, 280 /* height */,
  0 /* col offset 1 */, 20 /* row offset 1 */,
  0 /* col offset 2 */, 20 /* row offset 2 */);
```

プログラムを書き込むとちゃんと画面が映りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146663/63333c12-9780-590b-4175-38a89c02ff9e.png)
AndroidでのRemoteConfig実装方法

# はじめに
今回は、AndroidでRemoteConfigを受け取る部分を紹介していこうと思います
### 本文
MainActivityのonCreate内で下記の処理を追加します。
`remoteConfig`からgetStringで`parameter`の`key`を指定することでほしい値をJsonStringで取得することができます
```kotlin:MainActivty
val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig
        remoteConfig.fetchAndActivate()
            .addOnCompleteListener(this) { task ->
                if (task.isSuccessful) {
                    RemoteConfigParameter.values().map {
                        // 行いたい処理を記述
                    }
                }
            }

        remoteConfig.addOnConfigUpdateListener(object : ConfigUpdateListener {
            override fun onUpdate(configUpdate: ConfigUpdate) {
                RemoteConfigParameter.values().map {
                    if (configUpdate.updatedKeys.contains(it.key)) {
                        // 行いたい処理を記述
                    }
                }
            }

            override fun onError(error: FirebaseRemoteConfigException) {}
        })
```
### 最後に
今回はAndroideでのRemoteConfigを使った処理を紹介しました
備忘録程度ですがどなたかのお役に立てれば幸いです
latest（）を使って新しい順にレコードを並び替える

## はじめに
Laravelでプロフィール編集機能を実装しようとしていた時、コントローラでどのように今更新したレコードを取得し、引数としてbladeファイルに渡すか迷っていました。

このようにレコードを新しい順に並び替えたい時は、latest()メソッドを使います。

## 問題
ユーザの作成したプロフィールを最新順に並び変えたいです！
```terminal: デフォルトでは古い順に並ぶ
> $user->profiles()->get();
= Illuminate\Database\Eloquent\Collection {#7287
    all: [
      App\Models\UserDetail {#7285
        id: 1,
        occupation: "庭師",
        age: 55,
        business_area: "庭師",
        nickname: "ガーデン・ファンタジスタ",
        created_at: "2023-12-00 00:00:00",
        updated_at: "2023-12-00 00:00:00",
        user_id: 3,
      },
      App\Models\UserDetail {#7284
        id: 2,
        occupation: "トレーナー",
        age: 10,
        business_area: "ポケモン",
        nickname: "ポケモンマスター",
        created_at: "2023-12-02 00:00:00",
        updated_at: "2023-12-02 00:00:00",
        user_id: 3,
      },
      App\Models\UserDetail {#7283
        id: 3,
        occupation: "遊撃小隊隊長",
        age: 19,
        business_area: "西風騎士団",
        nickname: "この恨み、覚えておくわ！",
        created_at: "2023-12-03 00:00:00",
        updated_at: "2023-12-03 00:00:00",
        user_id: 3,
      },
```


## 解決法
latest()メソッドを指定します。
```terminal: 最新順に並び替える
> $user->profiles()->latest()->get();
= Illuminate\Database\Eloquent\Collection {#7287
    all: [
      App\Models\UserDetail {#7283
        id: 3,
        occupation: "遊撃小隊隊長",
        age: 19,
        business_area: "西風剣術・旧貴族",
        nickname: "この恨み、覚えておくわ！",
        created_at: "2023-12-03 00:00:00",
        updated_at: "2023-12-03 00:00:00",
        user_id: 3,
      },
      App\Models\UserDetail {#7284
        id: 2,
        occupation: "トレーナー",
        age: 10,
        business_area: "ポケモン",
        nickname: "ポケモンマスター",
        created_at: "2023-12-02 00:00:00",
        updated_at: "2023-12-02 00:00:00",
        user_id: 3,
      },
      App\Models\UserDetail {#7285
        id: 1,
        occupation: "庭師",
        age: 55,
        business_area: "庭師",
        nickname: "ガーデン・ファンタジスタ",
        created_at: "2023-12-00 00:00:00",
        updated_at: "2023-12-00 00:00:00",
        user_id: 3,
      },
      
```

最新のレコードのみを取得したいときは、get()に代えてfirst()を指定します。
```terminal: 最新のレコードのみを取得
> $user->profiles()->latest()->get();
= Illuminate\Database\Eloquent\Collection {#7287
    all: [
      App\Models\UserDetail {#7283
        id: 3,
        occupation: "遊撃小隊隊長",
        age: 19,
        business_area: "西風騎士団",
        nickname: "この恨み、覚えておくわ！",
        created_at: "2023-12-03 00:00:00",
        updated_at: "2023-12-03 00:00:00",
        user_id: 3,
      }
```




## まとめ
「あれ？そもそもプロフィールを更新するたびに、古いやつを消すようにしてればいいやん」って今更ながら思いました。
podman machine start で失敗した話

久しぶりに podman machine start を実施したところ、エラーが出て起動できませんでした。

```
$ podman machine start
Waiting for VM ...

Error: qemu exited unexpectedly with exit code -1, stderr: qemu-system-x86_64: Error: HV_DENIED
```

こちらの記事を参照し、brewを更新したら解消しました
https://github.com/containers/podman/issues/19708

```
$ brew update; brew upgrade qemu
```



```% podman machine start          
Starting machine "podman-machine-default"
Waiting for VM ...
Mounting volume... /Users:/Users
Mounting volume... /private:/private
Mounting volume... /var/folders:/var/folders
```

macOS: Sonoma 14.0
Arch: amd64
【測域センサ・Unity】transform.position assign attempt for 'Cube' is not valid. Input position is { NaN, NaN, NaN }

## サンプルのシーンでは検出が上手くいくが...
Github上などでヒットする測域センサとUnityの連携に関するプロジェクトですが、サンプルで用意されているシーン上では上手く稼働していても、他のシーンで稼働させようとするとエラーが発生するといった場合、この記事が役立つかもしれません。

## エラー内容
```c#:DebugRenderer.cs エラー
transform.position assign attempt for 'Cube' is not valid. Input position is { NaN, NaN, NaN }
```
謎エラーです。
検知した位置にオブジェクトを移動させる処理でエラーが発生しています。
本来であればポジションの引数にfloat型をセットするはずですが、NaNとなっています。

## 解決策
Unity上のMainCameraの角度(回転)を下記のようにしてください。

```
X : 90度
Y : 0度
Z : 0度
```

これでエラーが解消されるはずです。
DebugRenderer内でカメラのオブジェクトから何か情報を取得しているので、それが関係しているかもしれません。
角度をこれ上記以外のものにすると基本的にエラーが発生します。
tRPCについて

## tRPCとは？
- スキーマやコード生成なしに型安全なAPIを簡単に構築および利用できるようになるTypeScriptモノレポ向けに設計されたRPCの実装の一つ。
- APIエンドポイントの静的型付けを行い、その型をクライアントとサーバー（サーバーとサーバー）間で共有できるようにする。

https://trpc.io/docs/concepts

### RPC
Remote Procedure Call（リモート プロシージャ コール）の略。
あるコンピュータ（サーバー）上の関数を、別のコンピュータ（クライアント）から呼び出す方法。
HTTP/REST APIでは、URLを呼び出してデータを取得するが、RPCでは関数を呼び出してデータを取得する。

```ts
// HTTP/REST
const res = await fetch('/api/users/1');
const user = await res.json();

// RPC
const user = await api.users.getById({ id: 1 });
```

### Monorepo（モノレポ）
プロダクトに関するコードを全て一つのリポジトリで管理する方法。

https://zenn.dev/burizae/articles/c811cae767965a

## 頻繁に使用される用語
| 用語 | 説明|
|:-|:-|
| Prucedure    　　| APIエンドポイント。Query、Mutation、Subscriptionを使用できるようになる。　　　　　　　　|
| Query       　　 | データを取得するプロシージャ。  |
| Mutation    　　 | データを作成、変更、削除するプロシージャ。 |
| Subscription　　 | データの変更をリアルタイムで、検知し受け取るプロシージャ。 |
| Router      　　 | 共有された名前空間の下にあるプロシージャの集まり。  |
| Context      　　| 全てのプロシージャがアクセスできるもの。セッション状態やDB接続などに使用される。 　　　|
| Middleware   　　| プロシージャの前後でコードを実行できる関数。 コンテキストを変更することができる。 　　　|
| Validation   　　| 正しい入力データか確認するプロセス。 　|
bootstrap5 を使ってチェックボックとスクロールバー付きのテーブルを作成

メモ

```javascript
    function toggleCheckboxes(source)
    {
      // 全てのチェックボックスを取得
      let checkboxes = document.querySelectorAll('.rowCheckbox');

      console.log(checkboxes.length);
      for (let i = 0; i < checkboxes.length; i++)
      {
        // 書くチェックボックスの状態を更新
        checkboxes[i].checked = source.checked;
      }
    }
```

```css
      .scroll-container {
          /* テーブル全体のサイズ */
          height: 500px; 
          overflow-y: scroll;
          border: 1px solid #dee2e6;
      }

      .scroll-container::-webkit-scrollbar {
          width: 10px;
      }

      .scroll-container::-webkit-scrollbar-track {
          background: #f1f1f1;
      }

      .scroll-container::-webkit-scrollbar-thumb {
          background: #888;
      }

      .scroll-container::-webkit-scrollbar-thumb:hover {
          background: #555;
      }
```

```html
  
    <div class="scroll-container">
      <table class="table table-bordered">
        <thead class="sticky-top bg-white">
        <tr>
          <th scope="col">
            <input class="rowCheckbox" type="checkbox" id="selectAll"
                   onclick="toggleCheckboxes(this)">
          </th>
          <th scope="col">#</th>
          <th scope="col" class="col-5">First</th>
          <th scope="col" class="col-5">Last</th>
          <th scope="col">Handle</th>
        </tr>
        </thead>
        <tbody class="table-group-divider">
        <tr>
          <td><input class="rowCheckbox" type="checkbox" name="rowSelect"></td>
          <th scope="row" >1</th>
          <td class="col-5">Mark</td>
          <td class="col-5">Otto</td>
          <td>@mdo</td>
        </tr>
        <tr>
          <td><input class="rowCheckbox" type="checkbox" name="rowSelect"></td>
          <th scope="row" >2</th>
          <td class="col-5">Jacob</td>
          <td class="col-5">Thornton</td>
          <td>@fat</td>
        </tr>
        <tr>
          <td><input class="rowCheckbox" type="checkbox" name="rowSelect"></td>
          <th scope="row" >3</th>
          <td colspan="2" class="col-10">Larry the Bird</td>
          <td>@twitter</td>
        </tr>
        </tbody>
      </table>
    </div>
  </div>
```
Pull Requestのタイミングでlinter・formatterを実行する方法

# やりたいこと
プルリクのタイミングでlinter・formatterを実行させて、成功しないとマージできないようにしたい。

# Pipelineの設定
### 1. 新しいPipelineを作成
![スクリーンショット 2023-12-17 19.20.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/d9b3e15c-0e0a-36b2-f910-03bdb97028a5.png)
Azure Devopsの左サイドバーから「Pipelines」を選択して、右上にある「**New pipeline**」を押下。

<br>

![スクリーンショット 2023-12-17 19.20.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/5199c5eb-8a6e-3720-4323-e1aee7fc633d.png)
「**Azure Repos Git**」を押下。
次のタブで対象のリポジトリを選択。

<br>

![スクリーンショット 2023-12-17 19.20.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/43715b51-0f9b-d4a1-bf63-8451729f4412.png)
「**Starter pipeline**」を押下。

<br>

![スクリーンショット 2023-12-17 19.21.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/2a56ac9a-95af-a2e6-b32d-e9f873876618.png)
pipelineのファイル名を変えます。
今回は「**continuous-integration.yml**」にしました。

<hr>

### 2. yamlファイルの作成
```continuous-integration.yml
trigger:
- none

pool:
  vmImage: ubuntu-latest
strategy:
  matrix:
    Python39:
      python.version: '3.9'

steps:
- script: |
    python -m pip install black
    black --check --diff .
  displayName: 'Run format tests'

- script: |
    python -m pip install isort
    isort --check-only .
  displayName: 'Run import sort tests'

- script: |
    python -m pip install pyproject-flake8
    pflake8 .
  displayName: 'Run lint tests'

- script: |
    python -m pip install mypy
    mypy --ignore-missing-imports .
  displayName: 'Run type check tests'

```
▪️ trigger...「none」でOK。
▪️ strategy...Pythonのバージョンは複数選ぶことも可能です。今回はPython3.9を使ってるので「'3.9'」に設定。
▪️ steps....ここに実行させたいコマンドを入れていきます。

<br>
...以上でpipelineの設定は完了。
<br>


# プルリクのタイミングで実行されるように設定
![スクリーンショット 2023-12-12 23.18.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/b8868ef7-cfa4-fc8e-a1dc-a96a76eb6b8d.png)
Devopsの左サイドバーから「Repos」→「Branches」を選択。
<br>

![スクリーンショット 2023-12-12 23.18.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/4772ca8c-fc70-95f7-8c7e-dd2909aa9322.png)
右の3点リーダーボタンから「**Branch policies**」を選択。
<br>

![スクリーンショット 2023-12-12 23.19.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/f146b64f-fbc1-4d53-c2d2-a0062f502507.png)
「**Build Validation**」に新しく追加をしていく。
右の「+」ボタンを選択。
<br>

![スクリーンショット 2023-12-12 23.19.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/e2ad8f9f-469e-56fb-2410-3910e4cb22df.png)

先ほど作成したPipelineを選択。
そのほかの設定は、
▪️ Trigger...こちらは自動でおこなって欲しいので、「Automatic」を選択。
▪️ Policy requirement...成功しないとマージできないようにしたいので「Required」を選択。
▪️ Build expiration...ビルドの有効期限ですが、こちらは「Never」を選択。

「save」をクリック。
...
<br>

![スクリーンショット 2023-12-12 23.20.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/98dc02e7-cdcc-4bc0-a03d-9b56b9e7859e.png)
するとスクショのように「Build Validation」に新しく追加されたと思います。

# 検証
![スクリーンショット 2023-12-12 23.20.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/42286571-6642-a007-3985-7437f3e51ba7.png)
ブランチにプルリクを作成すると自動でPipelineが実行されました。
succeededになったのでマージできました。
CRLを見てみよう

# CRLをみてみよう
CRLについて見てみます

## CRLとは
#### 証明書の失効情報リスト です。
Certificate Revocation Listの 略です。
認証局(CA)から発行された有効期間内に失効した証明書のシリアルナンバーなどの証明書情報が記載されています。
これを見ればSSLサーバ証明書が失効しているかわかります。
ブラウザはこれを確認して証明書が有効か確かめているんですね。

## CRLはどこにあるのか、どうやってみるのか
CRLは認証機関ごとにあります。でも発行していないところもあるので注意です。
Cybertrustの証明書を例に見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3353450/c769c274-330e-de02-4a8a-44106e61a045.png)

証明書情報を表示し、詳細、CRL配布ポイントを見ます。
そこにアクセスすると拡張子が.crlのファイルがダウンロードされるのでその中にシリアル番号があれば証明書が失効していることがわかります。
オプション設定をシンプルに、"OptionsResolver"

[Symfony Component Advent Calendar 2023](https://qiita.com/advent-calendar/2023/symfony-component)の20日目の記事です。

## オブジェクトのプロパティ設定をシンプルに、"OptionsResolver"

[OptionsResolver](https://symfony.com/doc/current/components/options_resolver.html)は、配列でオプションの値を管理している際に、デフォルト値をシンプルに定義するレゾルバを提供します。

### インストール

```shell
composer require symfony/options-resolver
```

### 使い方

通常、配列でオプションの値を管理して、メソッドで値を設定できるようにするには、ちょっとめんどくさいことをしなければいけません。

```php
class SomeService;
{
    private array $options;
    
    public function setOptions(array $options = [])
    {
        $this->options['name'] = $options['name'] ?? 'Anonymous';
        $this->options['email'] = $options['email'] ?? 'sample@qiita.com';
    }

    // もしくは
    public function setOptions(array $options = [])
    {
        $this->options = array_replace([
            'name' => 'Anonymous',
            'email' => 'sample@qiita.com',
        ], $options);
    }
}
```

OptionsResolverはこのデフォルト値の設定や必須項目などを定義することができます。

```php
use Symfony\Component\OptionsResolver\OptionsResolver;

class SomeService
{
    private array $options;

    public function setOptions(array $options = [])
    {
        // OptionsResolverの設定
        $optionsResolver = new OptionsResolver();
        $optionsResolver->setDefaults([
            'name' => 'Anonymous',
            'email' => 'sample@qiita.com',
        ]); // デフォルト値の設定
        
        $optionsResolver->setRequired('email'); // 必須項目の設定
        $optionsResolver->setAllowedType('email', 'string'); // 型の設定

        $this->options = $optionsResolver->resolve($options);
    }
}
```

`setDefaults()` でデフォルト値、`setRequired()`で必須項目、`setAllowedType()`で型の設定ができます。
`resolve()`で未設定の場合はデフォルト値をセットした配列を取得できます。

### 効果的な使い方

これだけ見ると、逆にちょっとめんどくさくなった感がありますが、親子関係を持ったクラスなどに便利です。

```php

abstract class ArticleReader
{
    protected HttpClient $httpClient;
    protected array $options;

    public function setOptions(array $options)
    {
        $resolver = new OptionsResolver();
        $this->configureOptions($resolver);
        $this->options = $resolver->resolve($options);
    }
    
    public function read(array $options)
    {
        $this->setOptions($options);
        
        $this->httpClient->request(
            $this->options['method'],
            $this->options['url'],
            $json,
            [
                'headers' => $this->options['headers'],
            ]
        );

        ...
    }
    
    public function configureOptions(OptionsResolver $resolver);
}

class QiitaArticleReader
{
    public function configureOptions($resolver) {
        $resolver->setDefaults([
            'url' => 'https://qiita.com/api/v2/items',
            'method' => 'GET',
        ]);
    }
}

class ZennArticleGenerator
{
    public function configureOptions($resolver) {
        $resolver->setDefaults([
            'url' => 'https://zenn.dev/api/articles',
            'method' => 'GET',
        ]);
    }
}
```

## まとめ
今回は`OptionsResolver`について紹介しました。このほかにも配列からオブジェクトを作るためのFactoryクラスなどでも役立ちます！
Linuxに関する知識

# はじめに
Linuxに関する知識をまとめます。「[新しいLinuxの教科書](https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84Linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E4%B8%89%E5%AE%85-%E8%8B%B1%E6%98%8E/dp/4797380942/ref=sr_1_1?adgrpid=113196705062&gclid=Cj0KCQiAsvWrBhC0ARIsAO4E6f_AFGHzoIngbK7dR-chb04pLcGh3A0OLZfYqOCo_vh8w5YENKKrRaEaAo9AEALw_wcB&hvadid=651122190449&hvdev=c&hvlocphy=1009300&hvnetw=g&hvqmt=e&hvrand=6457217146992724220&hvtargid=kwd-1152146940662&hydadcr=21814_13455335&jp-ad-ap=0&keywords=%E6%96%B0%E3%81%97%E3%81%84linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8&qid=1702780070&sr=8-1)」の内容を、ほぼ自分のメモ的な感じで使っています🙇

# Linuxのディレクトリ構造
Linuxのディレクトリ構造は、ルートディレクトリを頂点とした階層構造となっている。
![](https://camo.qiitausercontent.com/d055704e995bd3bb7897ae420789b7d4c18a69eb/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3631393437392f35333638373336652d633737612d613834652d616436622d3031303237303937373237652e706e67)
※参考

https://qiita.com/nys9302/items/a8ddeedd3cd9d0deb332

### (主な)各ディレクトリの役割
- **/bin**
システムの基本的なコマンドやプログラムが格納されている場所
〜/binディレクトリの具体的な例〜
    - ls：ディレクトリ内のファイルやサブディレクトリの一覧を表示するコマンド
    - cp：ファイルやディレクトリのコピーを行うコマンド
    - mv：ファイルやディレクトリの移動、または名前の変更を行うコマンド
    - rm：ファイルやディレクトリを削除するコマンド
    - bash：Bashシェル自体の実行ファイルも/binに含まれています。これはユーザーがコマンドを入力し、システムと対話するためのプログラムです。
- **/dev**
「デバイスファイル」のための特別なディレクトリ。Linuxシステムがデバイスとのやり取りを行うための基本的な仕組みを提供している。
- **/etc**
システム全体の設定ファイルを保持する場所。Linuxシステムの運用やトラブルシューティングにおいて重要。
- **/home**
ユーザごとに割り当てられる、**ホームディレクトリ**が配置されるディレクトリ。ホームディレクトリとは、Linuxのユーザごとにそれぞれ割り当てられる個人用ディレクトリのことで、ユーザ名がそのままディレクトリ名となっている。
ユーザーが自分の文書、画像、設定ファイルなどを保存するためのパーソナルスペースとして機能する。
- **/usr**
システムの標準的なアプリケーションやプログラム、ライブラリなどを格納するための重要なディレクトリ。
サブディレクトリとして、bin, sbin, etcなどを持つ。
- **/opt**
追加のソフトウェアやアプリケーションをインストールするための場所。特に、標準のシステムパッケージ管理システムに含まれていないサードパーティ製のソフトウェアや商用ソフトウェアがここに配置されることが多い。
自分の場合、homebrewはここにインストールされていた。
```
% ls ../../opt
homebrew
```

:::note info
/binと/usr/binの違いは？
>/binがOSの働きの根幹に関わるような役割をもつコマンドがはいっているのにたいして、/usr/binにはそれよりももっと一般的に使われるようなコマンドが主に入っている。
:::
参考記事

https://qiita.com/totzyuta/items/84d610f56129a186f0c5#:~:text=/usr/-,bin,-%E7%B6%9A%E3%81%84%E3%81%A6

# コマンドを探す
Linuxのコマンドはディレクトリツリーのどこかにファイルとして存在している。例えば、```cat```コマンドは/bin/catというファイルがある。
```
% ls -lF /bin/cat
-rwxr-xr-x  1 root  wheel  135408  1 14  2023 /bin/cat*
```
しかし、```cat```コマンドは、毎回```/bin/cat```と打たなくても実行できる。（homeディレクトリにいても実行できるとか）
これは、```$PATH```という環境変数に設定された場所から自動的にコマンドを探してくれるから。（いわゆる、パスが通っているっていうやつか？）

# 個人的に便利だなと思ったコマンド（オプション含む）
- ```mkdir -p```
深いディレクトリを一気に作成できる。
```
mkdir -p report/2014/01
```
- ```rm -r```
ディレクトリの削除。逆に```rm```コマンドだけだと、ディレクトリは削除できない。ちなみに```rmdir```コマンドは、からのディレクトリを削除するコマンドである。
```
rm -r dir1
```
- ```find```
ファイルを探すコマンド
```
% find . -name dir1
./dir1
```
- ```mv```
ファイルを移動させつコマンド
```mv [オプション] <移動元> <移動先>```
ミューテータとappend()

## はじめに
私は株式会社qnoteにて、勉強会の幹事を務めております。
2023年度勉強会の珠玉のネタを2023Qiitaアドベントカレンダーに投稿していこうと思います。

## 対象者
この記事は下記のような人を対象にしています。

- 駆け出しエンジニア
- プログラミング初学者

## 結論
ミューテータは便利なので使いましょう！
ただし、記述箇所は慎重に検討しましょう。

## ミューテータの定義はモデルで

https://www.yoheim.net/blog.php?q=20181105

```php
<?php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Hoge extends Model
{

	public function getHugaHugaAttribute() // get + XX + Attributeで定義
    {
        return 'hugahuga';
    }
}
```

## 取得はappend()で

```php
$hoge = Hoge::find(1)->append('huga_huga'); // append()の引数はスネークケース文字列で

print($hoge->huga_huga);

// 出力
'hugahuga'20

```

```php
Hoge::where('id', 1)->get()->append('huga_huga'); // get()でも使える
Hoge::where('id', 1)->get()->toArray()->append('huga_huga'); // get()->toArrayでも使える
Hoge::first()->append('huga_huga'); // first()でも使える
Hoge::all()->append('huga_huga'); // all()でも使える
Hoge::append('huga_huga'); // Builderには使用できない！！！
```

## append()なしで取得する場合はモデルに$appendsを定義

```php
<?php
 
namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class Hoge extends Model
{
    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = ['huga_huga'];

		public function getHugaHugaAttribute()
	    {
	        return 'hugahuga';
	    }
}
```

```php
$hoge = Hoge::first(1);
print($hoge->hoge_hoge);

// 出力
'hugahuga'
```

※モデルが使用される全ての箇所で使用されるので要注意。

## おわりに
ミューテータとappend()についてまとめました。



## 参考記事
https://www.notion.so/append-47fc8ade89ad46c190b1f103522d70cc?pvs=4
collectionのwhen()

## はじめに
私は株式会社qnoteにて、勉強会の幹事を務めております。
2023年度勉強会の珠玉のネタを2023Qiitaアドベントカレンダーに投稿していこうと思います。

## 対象者
この記事は下記のような人を対象にしています。

- 駆け出しエンジニア
- プログラミング初学者

## 結論
collectionにもwhen()が使える！

## やりたいこと
append()でCollectionに'huga_huga'を追加したいが、フラグON/OFFで追加する/しないを切り替えたい。

## 失敗した方法(間違ったwhen()の使い方)
```php
// これだと動かない(append()はコレクションのヘルパー関数なので、get()より後に記述しないといけない)
$flag = true;
Hoge::when($flag, function ($q) {
	return $q->append('huga_huga');
})->get();
```

## Collectionにもwhen()があった！

https://laravel.com/docs/10.x/collections#method-when

```php
// これでOK
$flag = true;
Hoge::get()
	->when($flag, function ($q) {
		return $q->append('huga_huga');
	});
```

## おわりに
collectionのwhen()についてまとめました。


## 参考記事
https://www.notion.so/collection-when-154f9a15e549410b88fe4d79c49b8956?pvs=4
積読解消に読んだ『プロジェクトマネジメントの基本が全部わかる本』が最高だった件

# 0. はじめに
こんにちは、情報系の大学に通っている大学3年のShuntaです。
こちらはプロジェクトマネジメントに関する本の紹介記事になります。

なぜ、学生なのにプロジェクトマネジメントに関する本を読んでいるのか気になった方もいらっしゃるかもしれません。まずはそのことからお話しましょう。

 # 1. 読んだきっかけ
エンジニアとして活躍している先輩が「[**この本**](https://www.amazon.co.jp/dp/4798177415)良いよ」とオススメしてくれたのをきっかけに購入しましたがしばらく積読状態でした。

私が通っている大学には、「プロジェクトデザイン管理」と呼ばれる講義があり、プロジェクト管理を体験・理解できるものとなっています。平成25年度には経済産業省「社会人基礎力を育成する授業30選」[^1] [^2] に選出される等、各方面で高評価を受けている貴重な講義です。

本講義で、私はそのプロジェクト内で結成されたチームのプロジェクトリーダーを担当することになりました。しかし、これまでのリーダー経験がほとんど無いことと、プロジェクトリーダーとしての役割を果たすにはどうすればいいのか分からず、途方に暮れていました。

そんなとき、積読状態になっていた本のタイトルに惹かれて手に取って読んでみると大変参考になりました。きっと、Qiita記事にもこの本の紹介記事があるだろうと思い、Qiitaで「"プロジェクトマネジメントの基本が全部わかる本"」と検索してみると数件の記事しかヒットしませんでした。私と似たような悩みを抱えている方がこの本の存在を知れたらいいなと思い、筆を執りました。

# 2. 『プロジェクトマネジメントの基本が全部わかる本』
https://www.amazon.co.jp/dp/4798177415

本書は「そもそもプロジェクトとは何か？」という話から始まります。大学の講義でも最初にプロジェクトについて説明がありましたが、すっかり忘れていたので復習になりました。プロジェクトの目標についても明確に書かれており、チームメンバーの方と目標を共有することができました。

プロジェクトリーダーを担当していて苦労したことの一つに役割分担があります。その方法についても第3章に書かれていました。本書では、要件定義、設計、テストなどについても書かれており、それぞれの場面において参考になりました。

実務においては、プロジェクトリーダーやプロジェクトマネージャーを担当することになった際に今、悩んでいる部分と関連のある章を読むと良いでしょう。例えば、役割分担で悩んでいる場合は第3章のタスクマネジメントを参照します。

# 3. 『プロジェクトマネジメントの本物の実力がつく本』
https://www.amazon.co.jp/dp/4798180963

[『プロジェクトマネジメントの基本が全部わかる本』](https://www.amazon.co.jp/dp/4798177415)を読み終えた頃に、同著者によって書かれた[『プロジェクトマネジメントの本物の実力がつく本』](https://www.amazon.co.jp/dp/4798180963)という本が発売されました。今取り組んでいるプロジェクトを成功させたいのであれば前者のみで十分ですが、プロジェクトマネジメントをキャリアの方向性として捉えるのであれば後者の本も読んでおくと良いでしょう。

前者の本ではスキルを中心に紹介していますが、後者の本ではスキル以外に大切なことを紹介しています。その一つに「メタ認知」があります。その導入として、「失われた30年」および「IT業界の構造」を扱っています。失われた30年についてあまり知らなかった私にとっては興味深いものでした。

私は、これまでのリーダー経験がほとんど無いことからリーダーシップについてもっと知りたいと思っていたため、第4章の「リーダーシップを鍛える」を丁寧に読みました。

リーダーは、チームメンバーに対して役割分担を行うことも大切ですが、自分自身が頑張るべき場面もあります。そのような場面におけるストレスマネジメントや具体的にはどのような場面で頑張るべきなのか書かれており、参考になりました。

# 4. 最後に
プロジェクトリーダーをやっていて思うことは、いつになっても慣れないということです。未だに人を動かそうとするのに苦労しますし、試行錯誤しながら頑張るしかないと感じています。ただし、目的を持たずにとりあえずやってみるというのは試行錯誤とは言えません。今回紹介した2冊はその目的を明確にすることを手助けする本とも言えるでしょう。

最後までお読みいただきありがとうございました。

[^1]: [「プロジェクトベース設計演習」経済産業省“社会人基礎力を育成する授業30選”に選出](http://www.is.kyusan-u.ac.jp/journal/j2014/05Inenaga.pdf)
[^2]: [「社会人基礎力を育成する授業30選」実践事例集](https://www.libertas.co.jp/pub/kisoryoku30prize.pdf)
Effekseerを使って案内や看板を作る！

# はじめに
Vキャスでルームを作成する際、スタジオとは異なり、作製主が居ない状態でご覧いただくこととなるため、案内や看板が必要となる場面が多くなるかと思います。
Vキャスには、画像やPDFからアイテム化できる優秀な機能があるため、簡単に案内や看板を作製することができますが、プレートに画像を貼った簡素な状態となります。
ここでは、簡素な案内や看板から、ちょっとリッチな状態にグレードアップするために、Effekseerを使った案内や看板作りをご紹介します。
# コンセプトを考える
今回は、こちらのエフェクトを例に挙げて、説明していきます。
![ダウンロード (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985893/b76a0767-e90c-1619-c8f4-c52479af9f82.gif)
こちらのエフェクトは、ルームのVCIすべてローディングされるまで、その場で待っていただくためのエフェクトになります。
待っていただくための仕組みはこちらをご参照ください。

https://qiita.com/young_shinobu/items/cc7468cc362b32b0a1eb

このエフェクトの役目は、
- VCIがローディング中であることを伝えること
- ルームの雰囲気を阻害せず、エフェクトの下の注意文を読んでいただくこと

です。

そうすると、作りたいエフェクトイメージがおおよそ決まってきます。
- ルームや音楽に合わせて、文字の動きは小さめに、また、ゆっくりと。文字の色もルームの色と同系色に。
- ただし、注目してもらうために、目を引くものを使う（今回は黄色い星）
- エフェクトには、注意文と関係性のある星のエフェクトを使う

こんな感じで、エフェクトのイメージが出来上がったら、実装していきます！

# エフェクトの構成
###  文字幅に注意が必要なプロポーショナルフォント
文字のエフェクトを入れる際には、文字の”それぞれ”の横幅に注意しなければなりません。
例えば、下の画像の「I」は横幅がかなり小さいですが、その左右の「D」や「N」は縦と同じくらいの幅があります。
これを知らずに文字を等間隔に並べると、バランスの悪い文字列になってしまいます。
フォントには、実はプロポーショナルフォントというものがありまして、「MSゴシック」と「MS Pゴシック」というように「P」が付くものがプロポーショナルフォントにあたり、文字ごとに文字幅を個別に設定しているフォントになります。
プロポーショナルフォントを、等間隔に並べてもバランスが悪くならない場合もありますが、基本的にはバランスがよく見えるように文字ごとに文字幅を設定しているので、この文字幅を守ったまま文字の配置を行ったほうが綺麗に見えます。
ペイントソフトなどから出力した文字画像と、エフェクトとして使うように文字を等間隔に並べた画像を、それぞれ準備し、文字画像をベースにエフェクトの文字の位置調整をしていくとよいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985893/c11e0e41-e6d4-bdbe-451e-abc4c9b043de.png)
### 文字のアニメーション
文字をアニメーションさせる際、最後、もしくは、途中で、文字のアニメーションを止める必要があります。（文字を読んでいただく必要がありますので。）
今回は、黄色の光の玉が横切ると、NOW LOADINGの文字がクルクルと回転・減速・停止し、文字列が表示されるというエフェクトにしています。
Fカーブを使う方法もありますが、Fカーブは使いにくいので、**回転・ブレーキをかけて減速させるエフェクト**と**停止させたエフェクト**をそれぞれ準備してエフェクトを表現します。
例えば、「N」の文字のエフェクトですと、「N」と「Nstop」がそれぞれ、それにあたります。
これをすべての文字で準備します。
参考までに、「N」の回転・減速・停止までのエフェクトの設定値を載せておきます。
これで、100フレームかけて回転が停止するエフェクトとなります。
![スクリーンショット (165).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985893/d61087c0-84ab-7bfe-adcf-cf63654ebc37.png)


### エフェクト用の画像の準備
エフェクト用の画像は、それぞれの文字を別個に準備してもいいのですが、ひとつの画像にまとめて管理しやすいようにしましょう。
文字の参照にはUV機能を使うので、1枚の画像に文字を等間隔に並べる必要があります。
優秀なペイントソフトなどでは、そういった機能があるのかもしれませんが、自分はフリーソフトしか持っておらず、綺麗に並べそうになかったので、ブラウザのツールを使いました。
一応、使用したツールのリンクを置いておきます。
こちらのツールを使用して、横幅に違いがある文字に空白を入れて、すべて500ｘ500となるようにしました。

https://photocombine.net/cb/

# 案内や看板用のエフェクトならスクリプトはいらない！（場合が多い）
ここまで読んで頂いた方の中で、もしかしたら、スクリプト何もわからん！という方もいるかもしれません。
そんな方には朗報です！
案内や看板用であれば、エフェクトは常にONの場合が多いので、そういった場合にはスクリプトを書く必要はありません。
というのも、エフェクトはVCIを読み込んだ際に再生されてしまうので、以下の画像のように、「Effekseer Emitter」をオブジェクトにつけ、エフェクトを入れ、「Is Looping」にチェックを入れるだけで、常に繰り返し再生されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985893/35b94d10-5a6a-8761-6259-4a9ad3722efe.png)

# おわりに
これで、あなたのルームにも、エフェクトを使った少しリッチな案内や看板を飾れるようになりました！
エフェクトは見えているだけでも、楽しいものですので、みなさんのルームにもオリジナルのエフェクト案内や看板を是非飾ってみてくださいね！
unset()で複数引数持てる

## はじめに
私は株式会社qnoteにて、勉強会の幹事を務めております。
2023年度勉強会の珠玉のネタを2023Qiitaアドベントカレンダーに投稿していこうと思います。

## 対象者
この記事は下記のような人を対象にしています。

- 駆け出しエンジニア
- プログラミング初学者

## 結論
unset()で配列の要素を削除する場合、引数を複数持たせて記述を短くしましょう！

## 解説
ループ処理内でunset()を利用する際に、短く記述できる方法を紹介します。

### unset()複数回記述する
こんな感じで、削除する要素の数だけ、unset()を実行してました...

```php
$array = ['りんご', 'バナナ', 'いちご', ];

unset($array[0]);
unset($array[2]);

print_r($array);

// 出力
Array
(
    [1] => バナナ
)
```

### unset()に複数引数を記述
unset()に複数引数を持たせることが可能です。

```php
$array = ['りんご', 'バナナ', 'いちご', ];

unset($array[0], $array[2]);

print_r($array);

// 出力
Array
(
    [1] => バナナ
)
```

## おわりに
unset()で複数引数持てる方法についてまとめました。

## 参考記事
https://www.notion.so/unset-c5ee8971709d46bc8488a6b0b71dfbad?pvs=4
二宮和也さん公式サイトのWordPress高速化アドバイス

同じ83年生まれとしてWordPress高速化専門の立場から、WordPressを使用して制作された二宮和也さんの新しい公式サイトの表示速度を今よりもっと速くする対策を難易度別にまとめてみました。

本記事で指摘している内容は高速化案件でよくあるパターンです。WordPressはじめ様々なサイトで応用できますのでご参考にしていただければ幸いです。

:::note warn
注意事項
- WebPageTestでサイトを調査した上で、現在の利用テーマ・プラグインを変更しない前提で対策できる内容としています。（高速化現場ではプラグイン整理・変更が実施されることがあります。）
- 阿部寛さんのサイト構造とWordPress及び今回利用されているAstra及びElementorでは読込量に差があり、またHTMLと動的なPHPでは処理性能に違いがあります。ただ最大限近づけることは可能です。
- 掲載内容は読込調査など表から確認可能な部分のみの情報を基に判断しています。具体的なプラグイン設定画面など表面だけの情報では把握できない箇所については考慮していません。
:::

## 2023/12/18時点の改善状況

本セクションは下記の最新読込に基づいています。

https://www.webpagetest.org/result/231218_AiDcYE_4D5/

同じ条件で測定した場合、リリース当初トップページ表示が120秒かかってましたが3.4秒まで改善しました。比較動画は下記投稿から確認できます。

https://twitter.com/skillsharejp/status/1736640909419413958

## 難易度：低（基本的に誰でも対策可能な箇所）
### 画像の最適化
- 画像ファイル名に日本語名を含めないこと（例：背景-1-1-1.png）
- 必要以上に高解像度の画像を使用しないこと
    - top-1-1-1.png
    - n1253-1-1.png
    - 背景-1-1-1.png
- 同じ画像を重複して読み込まないこと

EWWW Image Optimizerが使用されてますが、解像度が大きい画像を自動圧縮させても限度があります。最も効率的に画像サイズを低くするには、**アップロード前に画像を適切な形式に変換又はリサイズすることが大事**です。

例えば**top-1-1-1.pngは現状3MBですが、PNGからJPGにして画像品質を90%にすると同じ解像度でもファイルサイズは337KBまで減ります**。写真の場合はPNGよりJPGが効率的です。

この画像を更に**画像最適化ツールで最大限圧縮すると77KBに下がります**。これでも過度な画質劣化はないため、ウェブサイト掲載用の品質としては十分です。

なおWordPress側で画像アップロード後に圧縮する場合は、ローカル上の画像（手元の画像）を圧縮しないで使用してください。何度も圧縮ツールを通すと意図しない画質劣化のリスクがあります。

また同プラグインは無料版と有料版で圧縮率が異なります。先ずは元画像を最適な状態にした上でアップロードし、無料版でも使用できるWebP形式に変換するだけでも画像読み込み時間が改善し、表示速度も高速化します。

### 画像の最適化（2023/12/18追記）

上記の指摘内容は早速改善されましたので

## 難易度：中（人によって経験者に頼る方が良い対策）
### ウェブフォントの読み込み改善
- Googleフォントの使用を停止する
- Googleフォント読み込みをCloudflareで改善する（フォント使用が必要な場合）

まずサイトを軽量化するに最も効率良いのはウェブフォントを使用しないことです。トップページでは53のフォントファイル読み込みがGoogleの配信サーバーからあるので、これを無くせばより表示速度が高速化します。

もしデザイン上Googleフォントが必要であれば、Cloudflareが最近提供を開始したCloudflare Fontsを使用すればWordPress上で細かな調整なく、簡単な画面操作で改善できます。

https://www.cloudflare.com/ja-jp/cloudflare-fonts/

条件として現在エックスサーバーに設定されているネームサーバーをCloudflare指定の内容に変更する必要がありますが、基本的な機能は無料版でも利用できるので将来的な負荷対策としても特に二宮さんみたいにアクセスの見込めるサイトでは有効です。

CloudflareにはCDNでのキャッシュなど、いくつか適切な調整が必要な箇所があります。慣れた人にお任せするのが安全です。

## 難易度：高（WordPress高速化経験がないとおすすめできない対策）
### サイト構成ファイルの読み込み制御

WordPressではデザインを構成するファイルでも、表示したいページでは不要なデータも読み込まれます。例えばお問い合わせフォームの構成ファイルも、トップページでは必要ありません。

他にもElementorは特に余計な読み込みが多いので、不要なCSSを削除したり、ページ上で必要のないファイル読み込みを制御することでそれぞれのページで表示速度が改善します。

これには専用プラグインを使用しますが慣れてないとレイアウトが崩れたり、本来意図する機能が使えなくなるなど弊害があります。あくまで、もっと高速化する手法があるという例えです。

## その他高速化に関する推奨項目

- 海外アクセスを見込み予め海外閲覧者に対しても快適な閲覧環境を提供する。
- CloudflareやCDNを活用しエックスサーバーの処理能力を超えないようにする。
- 著名人なので対策しなくても大丈夫と思いますが、SEOに関係するCore Web Vitals対策を実施する。

https://qiita.com/skillsharejp/items/acc51ec062af43aa84c0

もし余裕があればサイトの作り直しが必要ですが、高速化ノウハウを提供しているSWELLテーマを利用することで読み込みの軽量化と表示速度の改善がしやすくなります。

https://swell-theme.com/

## その他高速化以外の推奨項目

- WordPressの定期的なアップデート。
- 不正アクセス、サイト改ざんを防ぐセキュリティ対策の実施。

保守管理作業としての具体例は下記を参考に。

https://qiita.com/skillsharejp/items/b1930efe4530b5ec0fec
Pythonで写経

## はじめに
　先日、こんな記事を見かけました。

https://qiita.com/youwht/items/616ccc062725fa050a34

　これは面白い！と思ったので、自分も作ってみることにしました。

## 般若心経を写経
　NHKのサイトに載っていた「般若心経」を参考に制作することにしました。

https://www.nhk-fdn.or.jp/han/pdf/hannyashingyou.pdf

```python:notepad.py
import pyautogui
import pyperclip
import subprocess
import time

print("cyber-yuito723/HeartSutra\n\nメモ帳が起動した後、３秒後に写経がはじまります。")
time.sleep(3)
subprocess.Popen("notepad.exe")
time.sleep(3)

def display(letter):
    pyperclip.copy(letter)
    time.sleep(0.3)
    pyautogui.hotkey("ctrl", "v")
    time.sleep(0.1)

script_1 = ("観", "自", "在", "菩", "薩", "　", "行", "深", "般", "若", "波", "羅", "蜜", "多", "時")
script_2 = ("照", "見", "五", "蘊", "皆", "空", "　", "度", "一", "切", "苦", "厄")
script_3 = ("舎", "利", "子", "　", "色", "不", "異", "空", "　", "空", "不", "異", "色")
script_4 = ("色", "即", "是", "空", "　", "空", "即", "是", "色")
script_5 = ("受", "想", "行", "識", "　", "亦", "復", "如", "是")
script_6 = ("舎", "利", "子", "　", "是", "諸", "法", "空", "相")
script_7 = ("不", "生", "不", "滅", "　", "不", "垢", "不", "浄", "　", "不", "増", "不", "減")
script_8 = ("是", "故", "空", "中", "　", "無", "色", "無", "受", "想", "行", "識")
script_9 = ("無", "眼", "耳", "鼻", "舌", "身", "意", "　", "無", "色", "声", "香", "味", "触", "法")
script_10 = ("無", "眼", "界", "　", "乃", "至", "無", "意", "識", "界")
script_11 = ("無", "無", "明", "　", "亦", "無", "無", "明", "尽")
script_12 = ("乃", "至", "無", "老", "死", "　", "亦", "無", "老", "死", "尽")
script_13 = ("無", "苦", "集", "滅", "道", "　", "無", "智", "亦", "無", "得", "　", "以", "無", "所", "得", "故")
script_14 = ("菩", "提", "薩", "埵", "　", "依", "般", "若", "波", "羅", "蜜", "多", "故")
script_15 = ("心", "無", "罣", "礙", "　", "無", "罣", "礙", "故", "　", "無", "有", "恐", "怖")
script_16 = ("遠", "離", "一", "切", "顛", "到", "夢", "想", "　", "究", "境", "涅", "槃")
script_17 = ("三", "世", "諸", "仏", "　", "依", "般", "若", "波", "羅", "蜜", "多", "故")
script_18 = ("得", "阿", "耨", "多", "羅", "三", "藐", "三", "菩", "提")
script_19 = ("故", "知", "般", "若", "波", "羅", "蜜", "多")
script_20 = ("是", "大", "神", "呪", "　", "是", "大", "明", "呪")
script_21 = ("是", "無", "上", "呪", "　", "是", "無", "等", "等", "呪")
script_22 = ("能", "除", "一", "切", "苦", "　", "真", "実", "不", "虚")
script_23 = ("故", "説", "般", "若", "波", "羅", "蜜", "多", "呪")
script_24 = ("即", "説", "呪", "曰")
script_25 = ("羯", "諦", "　", "羯", "諦", "　", "波", "羅", "羯", "諦", "　", "波", "羅", "僧", "羯", "諦")
script_26 = ("菩", "提", "薩", "婆", "訶")
script_27 = ("般", "若", "心", "経")

scripts = (script_1, script_2, script_3, script_4, script_5, script_6, script_7, script_8, script_9, script_10, script_11, script_12, script_13, script_14, script_15, script_16, script_17, script_18, script_19, script_20, script_21, script_22, script_23, script_24, script_25, script_26, script_27)

for i in scripts:
    for j in i:
        display(j)
    pyautogui.press("enter", presses = 1)

input("\n御勤めお疲れさまでした。\n終了する場合は、エンターキーを押してください。")
```
　こんな感じのコードを書きました。タプルの中に般若心経を一文字ずつ入れておいてそれをfor文で一文字ずつ取り出すつくりにしました。以下のリポジトリで公開しています。
※`notepad.exe`（メモ帳）を起動してから、写経が始まるようにしています。なので、このコードではWindows上でしか動きません。

https://github.com/cyber-yuito723/HeartSutra

## おわりに
　Pythonの勉強をすることも功徳を積むことも同時にすることができました。これからもニッチなコードと記事を書いていきたいと思います。
unset()の注意点

## はじめに
私は株式会社qnoteにて、勉強会の幹事を務めております。
2023年度勉強会の珠玉のネタを2023Qiitaアドベントカレンダーに投稿していこうと思います。

## 対象者
この記事は下記のような人を対象にしています。

- 駆け出しエンジニア
- プログラミング初学者

## 結論
unset()の引数として、配列/連想配列の存在しないインデックスorキーを指定してもエラー出ないので要注意！

## 解説
ループ分の中でunset()を利用している場合、存在しないキーを指定するものの、エラーが出ず、処理が先に進んでしまうケースがあります。
別途、「配列内にキーが存在するかどうか」を判定する記述を入れる必要上がるかどうか、検討したほうがよさそうです。

### 配列の場合
    
```php
$array = [1,2,3];
unset($array[3]);
print_r($array);

// 出力
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)
```
    
### 連想配列の場合
```php
$array = ["a" => 1, "b" => 2];
unset($array["c"]);
print_r($array);

// 出力
Array
(
    [a] => 1
    [b] => 2
)
```

## おわりに
unset()の注意点についてまとめました。

## 参考記事
https://www.notion.so/unset-aebe5fec2b744f64891099b517b91c48?pvs=4