OmniAICreator/Qiita-1.07M huggingface dataset:
Excelなどでチェックマーク（✓、✗、⛝）を入力する

# Excel関数で入力する
UNICHAR関数を使用すると引数の数値（10進数）により参照されるUnicode文字を返します。  

例）「&#x2713;」を入力したい場合  
=UNICHAR(HEX2DEC("2713"))  
![uni.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193449/1b92c279-3a87-b638-fcd0-a54927deb9f5.png)  
* 文字に対応する数値（16進数）を調べるときは[Unicode一覧表 - Wikipedia](https://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7%E8%A1%A8)。
* 記号関連は[2000-2FFF](https://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7_2000-2FFF)。下記は入力の一例。  

|入力する数式|表示される文字|入力する数式|表示される文字|
|:---|:---|:---|:---|
|=UNICHAR(HEX2DEC("2713"))|&#x2713;|=UNICHAR(HEX2DEC("2705"))|&#x2705;|
|=UNICHAR(HEX2DEC("2714"))|&#x2714;|=UNICHAR(HEX2DEC("274E"))|&#x274E;|
|=UNICHAR(HEX2DEC("2715"))|&#x2715;|=UNICHAR(HEX2DEC("26DD"))|&#x26DD;|
|=UNICHAR(HEX2DEC("2716"))|&#x2716;|=UNICHAR(HEX2DEC("2610"))|&#x2610;|
|=UNICHAR(HEX2DEC("2717"))|&#x2717;|=UNICHAR(HEX2DEC("2611"))|&#x2611;|
|=UNICHAR(HEX2DEC("2718"))|&#x2718;|=UNICHAR(HEX2DEC("2612"))|&#x2612;|
|=UNICHAR(HEX2DEC("274C"))|&#x274C;|=UNICHAR(HEX2DEC("25A3"))|&#x25A3;|


# コピペする

そもそも[2000-2FFF](https://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7_2000-2FFF)のページから直接コピペするだけでOKです。ExcelだけでなくWordやメモ帳でもそのままコピペ可能です。
Atcoder典型90問 002 - Encyclopedia of Parentheses

0427進捗
# Atcoder典型90問 002 - Encyclopedia of Parentheses
▶︎https://atcoder.jp/contests/typical90/tasks/typical90_b

## 問題
長さ 
N の正しいカッコ列をすべて、辞書順に出力してください。

ただし、正しいカッコ列は次のように定義されています :

() は正しいカッコ列である
    <==>
* S が正しいカッコ列であるとき、文字列 '(' + S + ')' は正しいカッコ列である
* S,T が正しいカッコ列であるとき、文字列 S+T は正しいカッコ列である
* それ以外の文字列はすべて、正しいカッコ列でない

例えば、

()()
(()())(())
()()()()()()()()
は正しいカッコ列ですが、

)(
)))()(((
((((a))))
は正しいカッコ列ではありません。

また、 ( の方が ) よりも辞書順で早いものとします。

## 制約
```math
1 \leq N \leq 20 \\
N \in \mathbb{N}
```

## 試したこと
* 2の20乗は100万くらいなので全探索は計算量ギリギリ。for文の中でも処理を行うことを考えると最低限探索範囲は絞りたい。
* とりあえずNの中の'('と')'の個数は絞り込めるので、実際の探索対象は N Comb (N/2)。
* 正しいカッコ文かどうかはwhile & replaceで行える。O(N)なので耐えると判断。
* 「正しいカッコ文」に対して探索をかけるか、「"("の個数だけは最低限絞り込んだカッコ文」に対して探索をかけるかが難しい。ただ前述したように正しいかどうかの判定がロジックと計算量の面でともに余裕があるのと、正しいカッコ文を綺麗に数え上げるアルゴリズムが思いつかなかったので後者を選択。
* itertoolsの存在を知らなかった。これ知らなくて15分くらい沼った。

## 適切な方針
* 模範解答はよくわからなかったので我流の解説を書きます。
* Nの中の'('と')'の個数はともにN /2個と絞り込めるので、実際の探索対象は N Conb (N /2)。これに対して探索をかける。
* このとき、探索対象を「N文字の'('の中から、N /2個 を')'に置き換えたstring」の集合と読み替えたのがうまくいった。置き換え対象の選び方は、0からN-1までのintを順番に格納したlに対してitertools.combinationsで組み合わせ列挙を行うことでtupple型で得られるので、あとは各選び方について該当部分のindexを')'に書き換えればよい。
    * (例) N = 4のときは 4つの'('から2つを')'に書き換えればよいので、itertools.combinationsに[0, 1, 2, 3]から2つを選んだ選び方のiteratorを返してもらい、それをindexとして
        * (0, 1) => ))((
        * (0, 2) => )()(
        * ...と書き換えを行い、順番に探索対象の文字列(cur_S)を生成していけばよい。
* 辞書順に出力するのに、このアルゴリズムだと逆順になってしまうのに気づかず出力して1ペナ
* 自力で解いたけど1時間くらいかかってしまった。permutationとcombinationがitertoolsを使えば即出せるということは知っておくべきだと思った。


## 解説付きコード
```py
import itertools
anslist = []
N = int(input())

#偶数の時のみ処理を行う
if N % 2 == 0:
  #lは後で使う
  l = range(N)
  #書き換え前の文字列に対応する配列Sを作成
  S = ["(" for i in range(N)]
  # N/2 個は '('、 N/2 個は ')'
  # N個のうち N/2個を")"に書き換えた文字列を生成する
  p_itr = itertools.combinations(l, N // 2)
  for p in p_itr:
    #配列はアドレスで持っているので単純な代入は許されないことに注意
    cur_S = S.copy()
    #tupple pの各要素をindexとして、該当部分を'('から')'に書き換える
    for k in p:
      cur_S[int(k)] = ")"
    #コピーと検索が面倒なので文字列にする
    cur_S = "".join(cur_S)
    check_S = cur_S
    #正しいカッコ文かどうかの判定
    while ("()" in check_S ):
      check_S = check_S.replace("()", "")
    #除去できない余り文字がある→正しいカッコ文ではない
    if len(check_S) > 0:
      continue
    else:
      anslist.append(cur_S)
#辞書順にするのを忘れない
anslist.reverse()
for s in anslist:
  print(s)
```
SQLSTATE[HY000] [2019] Unknown character set のエラーについて

# 発生経緯
PHPにおいて PDO接続をしようとしたら、ブラウザに
>SQLSTATE[HY000] [2019] Unknown character set

が出てきた。

# 原因
charset=utf8mb4となっていなかったことが原因。
というか、自分のタイプミス。
```
$dsn = 'mysql:dbname=??????;host=localhost;charset=utfmb4'; <-utf'8'mb4 8が抜けていた
$user='????';
$password='????';
```

# 結果
こんなことでうんうん、悩んでいました。
ただ、出力されたエラー文でそのまま検索かければ、解決策がすぐヒットしたので
この方法は今後続けていきたいと思います!!
同じことで悩んだ初学者の方がいれば、力になれたら幸いです。
【議事録作成もさくさく！】Googleドキュメントでマークダウンプレビューをする方法

Qiitaの記事を書く前に、Googleドキュメントで下書き→社内で校閲してもらってからQiitaに下書き→記事投稿の流れで私は記事を書いているのですが、Googleドキュメントだとマークダウン記法がちゃんと出来ているのかどうか確認と変換が面倒くさい…。
書きながらマークダウンで表示されたらいいのに。出来ないの？と思って調べてみました。
**出来ました！！！！！**

出来ました。あっさり悩みが解決したので嬉しい＆便利だったのでまとめてみました。
Qiitaの記事だけじゃなくて簡単なドキュメントを作る際に役立ちそうなので是非お試しあれ。

# 設定方法
1.Googleドキュメントを開く
2.上部に表示される「ツール」→「設定」をクリック
![キャプチャ１.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2028933/ab35f118-17df-ae43-91db-cc4c65bdab07.png)



3.設定の中から「Markdownを自動検出する」にチェックを入れる
![キャプチャ２.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2028933/5ef0bf97-a360-0feb-3672-38d25acf672e.png)

**これで設定は完了！**

## 実際に書いてみる。
まずは見出し。
見出しの書き方は文頭に「#」をつける。
![キャプチャ３.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2028933/54aa6cdc-91a7-7dd0-b5ef-ad4dd3629f56.png)

半角で「#」の後に半角スペースを打ち込みエンターを押すと……
![キャプチャ４.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2028933/9463cb42-12c0-8417-f5d0-3a72cf2b006f.png)


見出しサイズに変換されました！　やったね(｀・ω・´)
ネットの情報によれば反応するものとしないものがあると聞いたので、主だったものを試してみました。結果はこちら。
![uploading...0]()



文中でコードを引用する「 ` ` 」とコードの挿入をする「 ``` 」と引用は反応しませんでしたが、その他はちゃんと検出してくれて反応しました。

**ら、楽だ……！**

これで記事書くのも捗りそうです！
OpenAIのアカウントを削除＆復活申請してみた

OpenAI、絶好調ですね！

そんな絶好調のOpenAIですが、試しにアカウントを削除したら大変だったので、注意喚起を兼ねてメモです。

# アカウントをなぜ削除したのか
Google認証をパスワード認証に変更してみたかったのですが、変更方法がよく分からなかったので、一旦削除してみました。
削除したらどうなるんだろう、という興味も、もちろんあります。
（復活できるだろう、という期待もあります）

# 削除したらどうなったのか
再度サインアップしようとしたら、以下のメッセージが表示されました。アカウントが存在しているとのこと。おそらく論理削除の状態。
![スクリーンショット 2023-04-27 20.41.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/89066b3c-ba10-8e4d-b884-37544113bf28.png)


仕方がないので、最初に登録した通り、Google認証でログイン。
![スクリーンショット 2023-04-27 20.21.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/1b4b5be7-55ef-a38b-ccaf-8900de0ee777.png)

あなたのアカウントは削除されたから、存在しないですよ。
これがエラーだと思うなら、連絡してね。とのこと。

## とりあえず、問い合わせてみる
さすがOpenAI、ヘルプもAIです。
適切な選択肢が無いので、「Other」を選択。
とりあえず、アカウントを復活させたい、と要望を送ってみます。
![スクリーンショット 2023-04-27 20.15.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/4286feb0-9938-4cd2-bd7c-69f3631fe159.png)
どうやら、一度削除が完了すると、同じメールアドレスで新規アカウントを作成する手段が無いようです。
無効化されたアカウントの申し立てを行うか聞かれたので、送ってみます。
![スクリーンショット 2023-04-27 20.16.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/604f40d6-ee46-363c-a11c-d4870e1d29ca.png)

## アカウントの復活をお願いしてみる
メールアドレスを入力し、チケットを送信。
![スクリーンショット 2023-04-27 20.16.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/70b740e5-cd7b-0195-680f-8bbbf65eb7b3.png)
通知用のメールアドレスとアカウント削除日時、申し立ての理由、メールのスクリーンショットを添付して送信します。
![スクリーンショット 2023-04-27 20.16.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/a7f7cb31-738e-8162-fe53-c5b0312b79be.png)
今回は削除完了のメールが届いていないので、Oops!のスクショを添付してみました。

## 受付完了のメールが届く
丁寧に、受け付けましたよ、というメールが届きます。
![スクリーンショット 2023-04-27 20.49.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/d3971344-14da-b478-8ca6-8834312b7cf1.png)

おそらくすぐには対応されないと思うので、続報を待ちます！

# まとめ
・削除すると、復旧は大変
・サポートは丁寧に感じる
・AIチャットボットは、対応が丁寧

AIチャットボットを使ってみて、導入してみたくなりました。

改めて、続報をご報告します！
[AWS Q&A 365][SES]AWSのよくある問題の毎日5選 #41

# 1. Amazon SESとは何ですか？
回答：Amazon SESとは、Amazon Simple Email Serviceの略称であり、ビジネスが顧客に大量の電子メールを送信できるクラウドベースの電子メール送信サービスです。

# 2. Amazon SESを使用する利点は何ですか？
回答：Amazon SESを使用する利点には、高い配信率、コスト効率、ビジネスのニーズに応じたスケーリング能力などがあります。Amazon SESはフィードバック通知を提供し、DKIMのセットアップも容易です。

# 3. Amazon SESはどのように機能しますか？
回答：送信者がSESに電子メールリクエストを送信すると、SESは電子メールを処理し、受信者の電子メールサーバーに送信します。SESは送信者にフィードバック通知を提供し、DKIMのセットアップも容易です。

# 4. Amazon SESで送信クォータを増やすにはどうすればよいですか？
回答：Amazon SESで送信クォータを自動的に増やすか、増加を要求することができます。増加を要求するには、送信プラクティスと送信する電子メールのタイプに関する情報を提供する必要があります。

# 5. Amazon SESで送信クォータを監視するにはどうすればよいですか？
回答：Amazon SESコンソールまたはAmazon SES APIを使用して、Amazon SESで送信クォータを監視できます。送信限度に達すると、エラーメッセージが表示され、限度がリセットされるまで待つか、増加を要求する必要があります。
[AWS Q&A 365][SES]Daily Five Common Questions #41

# 1. What is Amazon SES? 
Answer: Amazon SES stands for Amazon Simple Email Service. It is a cloud-based email sending service that allows businesses to send bulk email messages to their customers. 

# 2. What are the benefits of using Amazon SES? 
Answer: Some of the benefits of using Amazon SES include high deliverability rates, cost-effectiveness, and the ability to scale up or down based on business needs. Amazon SES also provides feedback notifications and allows for easy DKIM setup. 

# 3. How does Amazon SES work? 
Answer: When a sender sends an email request to SES, SES processes the email and then sends it to the recipient's email server. SES also provides feedback notifications to the sender and allows for easy DKIM setup. 

# 4. How can I increase my sending quotas with Amazon SES? 
Answer: You can increase your sending quotas with Amazon SES either automatically or by requesting an increase. To request an increase, you will need to provide information about your sending practices and the type of emails you will be sending. 

# 5. How can I monitor my sending quotas with Amazon SES? 
Answer: You can monitor your sending quotas with Amazon SES using either the Amazon SES console or the Amazon SES API. If you reach your sending limit, you will receive an error message and will need to wait until your limit resets or request an increase.
javascriptでアプリ開発できるってよ😎

# webエンジニアでもアプリが作れる！！
普段、iosやandroidアプリのようなネイティブアプリを作ってみたいけど、専門言語に触れてこなかった私ですが、この度アプリを作りました。

# 使った技術
## #  [Ionic](https://ionicframework.com/) <font color="#f2cd02">★</font>49k

公式サイト抜粋
> Ionic FrameworkはオープンソースのUIツールキットで、HTML、CSS、JavaScriptなどのウェブ技術を使って、 [Angular](https://ionicframework.jp/docs/angular/overview/), [React](https://ionicframework.jp/docs/react/), and [Vue](https://ionicframework.jp/docs/vue/overview/) といった人気フレームワークと併用することで高性能で高品質なモバイルアプリやデスクトップアプリを作ることができます。

### 個人的な魅力✨
1. 普段使っているAngular, React, Vueのフレームワークを直接使える開発が可能
```vue
<template>
  <ion-app>
    <ion-router-outlet />
  </ion-app>
</template>

<script setup lang="ts">
  import { IonApp, IonRouterOutlet } from '@ionic/vue';
</script>
```
私はvueで開発しました。😤
公式や参考資料はangularが多めなのでangularに慣れている方はそれで開発した方がいいかもです。😳

感覚的にangular > react > vueの順で参考資料が多かったです。

- web開発をしている感覚で開発を進めていくが、ビルドするとiosとandroidの開発が完成している。
![スクリーンショット 2023-04-27 21.57.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712534/016854a3-5ba0-1791-e8f4-53d17a92efaa.png)
ブラウザで、ホットリロードしながら開発することができますので、web開発に慣れている方からすれば、とても開発しやすいと思います。💪

- 学習コストが圧倒的に低い

JSで記述できるネイティブアプリ用の代表的な技術に[react native](https://reactnative.dev/)があるが、学習コストがかかる。
それに比べIonicは、いきなり開発することができる。

[github](https://github.com/ionic-team/ionic-framework)


# 参考文献
- [JavaScriptでスマホアプリを作る7つ方法](https://qiita.com/schrosis/items/ec00ff318c3852293d3c)

# 今後
- Ionicを中心に記事を書いていきます。
- Ionic ✖︎ Vueの組み合わせの記事が少ないため私が書いていきます😎😏


# 移行した話
結論、メイン開発は、ionicからflutterへ移行したのですが、理由は、　input系の挙動が遅いことです。

ionicはどうしてもネイティブアプリの動作が遅くなってしまいます。仕方ないです。

しかし、web開発者が、アプリを開発する際の学習コストがほとんどない点はとても素晴らしいので魅力的。

react nativeの選択もあるので、reactできる人はそっちがいいかもしれないです。私は、flutterで開発しています。

自身のスキルやコストに応じて選択するのがいいでしょう。
Pythonのimportのパスの扱いがうまく行かない

# はじめに

久しぶりにPythonを書いていたのですが、毎回Importの仕方で躓くなと感じたのでまとめていきたいと思います

# 問題

以下のディレクトリ構成があるとします

```
┣ app
    ┣ main.py
    ┣ driver
        ┣ get_driver.py
    ┣ gateway
        ┣ get_gateway.py
┣ test
    ┣ test_gateway.py
```

main.pyでは`gateway.py`を読み込んでいます

```py:main.py
from gateway.get_gateway import GetGateway
```

main.pyでは`get_gateway.py`を呼び出します
gateway.pyでは`get_driver.py`を読み込みます

```py:gateway.py
from driver.get_driver import GetDriver
```

ここで`main.py`からこのコードを実行すると`main.py`からみて`from`のパスは相対パスになっているので問題なく動きます

```
┣ app
    ┣ main.py ←ここからみてる
    ┣ driver
        ┣ get_driver.py
    ┣ gateway
        ┣ get_gateway.py
┣ test
    ┣ test_gateway.py
```

しかし`test_gateway.py`は`get_gateway.py`を直接読み込んで関数を実行しているため相対パス的に`driver`がないと言われます



```
┣ app
    ┣ main.py
    ┣ driver
        ┣ get_driver.py
    ┣ gateway ←ここからみてるので下の階層にdriverはないのでエラー
        ┣ get_gateway.py
┣ test
    ┣ test_gateway.py
```

このようにテストとmainでインポートがちぐはぐになってしまいました
これをなんとかしたいと思いました

# 解決方法

インポートのパスをみるときは全部`app`から見るように設定することで解決しました

```
$ export PYTHONPATH=/root/src/app
```

これを実行することでうまく辻褄があうようになりました

私の環境はDockerなので以下のようにしました

```yml:docker-compose.yml
version: "3"
services:
  app:
    build: .
    container_name: "app"
    tty: true 
    working_dir: /root/src
    volumes:
      - ./src:/root/src
    environment:
      - PYTHONPATH=/root/src/app
```

# おわりに

地味に躓いてしまいましたがChatGPTのおかげで解決できました
そのうちQiitaも不要になるのではないかと思いました
AndroidアプリのプロジェクトでGradle 8.0更新時にJava Toolchainを使うのはまだ早いかもしれない

Android アプリのプロジェクトで Gradle 8.0 移行に更新すると(ここでは not Android Gradle Plugin) kapt や ksp を使っているプロジェクトによっては以下のようなエラーが出ることがあります。

>Execution failed for task ':app:kaptGenerateStubsDebugKotlin'.
>  \> 'compileDebugJavaWithJavac' task (current target is 11) and 'kaptGenerateStubsDebugKotlin' task (current target is 17) jvm target compatibility should be set to the same Java version.
  Consider using JVM toolchain: https://kotl.in/gradle/jvm/toolchain

この場合はエラーに書かれている Java Toolchain に置き換えるよりも以下のコードで Kotlin のコンパイルタスクが実行される JVM のバージョンを固定する方が現時点では対処しやすいかもしれない。  

```kotlin
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>()
    .configureEach {
        kotlinOptions {
            // targetCompatibilityと揃える
            jvmTarget = JavaVersion.VERSION_XXX.toString()
        }
    }
```

## 起きている問題の解説

これは Java と Kotlin のコンパイル時に target JVM のバージョンが一致していない場合に出るエラーで、Gradle 8.0 の更新で以下のような状況から JVM のずれが生じます。
- Gradle 8.0 から Gradle の Kotlin DSL が 1.8 になった
- Kotlin DSL 1.8 ではビルドを実行する JDK のバージョンを使用する
- Android Studio Flamingo についている JDK は 17
- Android のプロジェクトの target JVM は 17 でない(大抵 8 or 11)


https://docs.gradle.org/8.0/release-notes.html#kotlin-dsl-updated-to-kotlin-api-level-1.8


以下の記事でもこの辺りの変更点が解説されていてとても参考になる。

https://nashcft.hatenablog.com/entry/2023/02/27/132910

## 問題の回避策と罠

エラーに書かれているように Java Toolchain で実行される JVM のバージョンを揃えるのが本当は望ましい。
将来的にも Java Toolchain で統一されそうで移行されていくことになるはず。　　
しかし、Java Toolchain で揃えようとするといくつか罠がある。

#### 1. Android Studio Flamingo 以降の JDK は 17 がバンドルされている

このため、Java Toolchain で JVM のバージョンを 11 に設定しようとした場合は、プロジェクトで使用される JDK も 11 にダウングレードするもしくは Java Toolchain での自動ダウンロードの設定をすることになる。
Package Manager が入っていればそこからなければ別途設定が必要であったり、CI/CD でも必要とする JDK のバージョンがない場合に何かしらの手段で JDK を使える状態にする必要がある。

https://docs.gradle.org/current/userguide/toolchains.html#sec:auto_detection

#### 2. Desugar は JVM 17 に対応していない

1 の回避として Toolchain で JVM とプロジェクトを 17 に設定しようという案も出るとは思うが、Desugar は JVM 17 に対応していないのでプロジェクト全体を 17 にすることは避けた方がいいらしい([ドキュメント](https://developer.android.com/studio/write/java11-minimal-support-table)には Java 11+ とあるけど…)。

https://github.com/android/nowinandroid/pull/689

#### 3. Android Gradle Plugin における Java Toolchain のサポートは AGP 8.1.0-alpha09 以降
compileOptions の targetCompatibility も将来的には Java Toolchain に統一されるがそれは AGP 8.1.0-alpha09 以降となる。
ここで 2 の問題があるのでどのみち Java Toolchain で統一する場合は Desugar が対応されるまで 11 にするしかなく、1 の調整が必要となる。

https://kotlinlang.org/docs/gradle-configure-project.html#gradle-java-toolchains-support




Java Toolchain に移行するにはプロジェクトの環境によってすんなり移行できないことがあるため、しばらくは `kotlinOptions.jvmTarget`　で様子を見る方がいいかもしれないというお話。
Google Pixel Watchの新品交換する方法

Google Pixel Watchをアマゾンで購入して２日でスピーカが壊れました
Googleに連絡して交換はしてもらえましたが…

![P_20230427_185334.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/cd4a3006-3a84-b4cf-bdac-1795191f6f07.jpeg)

こんな感じで帰ってきます…

え？　再生品って言うことは新品でなくて中古？
買って２日で壊れて、中古を掴まされるってどんなプレイ？

さぁここからバトル開始です

前提条件　アマゾンで購入し３０日以内

# 正常系
・問題なく機能すること

# 準正常系
・壊れる
・アマゾンに連絡
・30日以内であれば交換可能

# 異常系
・壊れる
・グーグルに連絡
・中古が届く
・アマゾンに連絡
・中古（購入したもののシリアル番号）なので交換出来ません

# 異常系対処方法
・壊れる
・グーグルに連絡
・中古が届く
・アマゾンに連絡
・中古なので交換出来ません
・生活消費センターに連絡する
　・教えてもらった裏技でクレジット会社に諸事上を連絡
　・経費で落としている場合はなんか別の手段である（忘れた）
・上記２つは面倒くさいので「生活消費センター」に相談したことをアマゾンに伝える
・アマゾンが「グーグルが交換許可くれれば」対応するとなる
・グーグルの担当者を別の人にして交渉て許可をもらう
・アマゾンに伝える
・発送待ち


# 結論
・アマゾンの人曰く、メーカ交換する前に連絡くださいと、そうしたらなんとかなるシステムらしい
　但し30日ルール
・これ、直接メーカからハードを買うものはリスクあるなと感じた
・直接でなくて良かった
・ハード（物）買って初期不良でごねたら「消費生活センター」に連絡して手段を教えてもらおう


アップルウオッチを先に買いました。
もう呆れて心をは何処かに行きました。

ことの発端は、グーグルが適切に答えていればここまで大事にしませんでした。
多分グーグルの担当者は再生品交換できたからといって、以後のメールの返信を一切しなかったことに火種をつけました。
多分、担当者は今頃怒られているでしょう。

# 参考情報
グーグル　10日かかって中古品届く
アマゾン　条件揃えばすぐに交換品発送

この差何よ？
IT企業の文化として興味深い

ここのことから、僕はアマゾンの信頼度は上がり、グーグルはダダ下がりです
補足：代わりにグーグルの対応してくれた方はまともでした

備品として買うんだったらあんましトラブりたくないので、何処の製品がトラブって
何処の製品がトラブりにくいかアンテナを広げる必要があると認識した
MySQLでデータベースを作ってテーブルにデータを入れて取得してみた

# 概要
今日もデータベースの勉強ということで、MySQLで遊んでみました。
インストールして、データベースを作って、テーブルを作って、データを入れて、取得するところまでやってみました。
以下のページを参考にしました。
https://www.javadrive.jp/mysql/

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

# rootでログイン
以下のコマンドを実行しました。
```
$ sudo mysql
```
ユーザーを作りました。create userを実行しました。
```
mysql> CREATE USER 'user1'@'localhost' IDENTIFIED BY '********';
Query OK, 0 rows affected (0.10 sec)
```
データベースを作りました。create databaseを実行しました。
```
mysql> CREATE DATABASE mydb;
Query OK, 1 row affected (0.09 sec)
```
user1に権限を与えました。grantを実行しました。
```
mysql> GRANT ALL ON mydb.* TO 'user1'@'localhost';
Query OK, 0 rows affected (0.11 sec)
```

# user1でログイン
以下のコマンドを実行しました。
```
$ mysql -u user1 -p
```
データベースを切り替えました。useを実行しました。
```
mysql> use mydb;
Database changed
```
テーブルを作りました。create tableを実行しました。
```
mysql> create table animal (id int, name varchar(10));
Query OK, 0 rows affected (0.52 sec)
```
データを入れました。insertを実行しました。
```
mysql> insert into animal (id, name) values (11, 'monkey');
Query OK, 1 row affected (0.09 sec)
```
データを取得してみました。selectを実行しました。
```
mysql> select * from animal;
+------+--------+
| id   | name   |
+------+--------+
|   11 | monkey |
+------+--------+
1 row in set (0.00 sec)
```
何かの役に立てばと。
chatgpt プロンプトの分類

はじめに
結構雑にあげてるのでこんな用語あるんだ程度で聞いてもらえると幸いです

<h1>プロンプトの分類






プロンプトの種類は全部で5あるとされているようです
分別して捉えた方が思考が整理されるので紹介していきます

プロンプトといっても色々あるので、自分の作ったプロンプトが複数にまたがる意味を持つ場合もあると思います

<h2>質問型プロンプト

　the 定番って感じのプロンプトですね。問題を聞いたら返してくれたり、
エラー投げたらよこしてくれるものを質問型プロンプトと言います

<h2>指示型プロンプト

「面白いこと言ってください」
みたいなもんだと思っています


<h2>創作型プロンプト

主にgptで小説を描いているのがこれに当てはまるんじゃないでしょうか

<h2>話題提供型プロンプト

「スポーツの重要性について述べてください。」
などのディベートでのお題で使用されそうなプロンプトですね
Oracle Linux 9でLet's EncryptのSSL/TLSサーバ証明書を取得する

# はじめに
Oracle Linux 9ではdnfによるcertbotのインストールが行えなかったため、podmanからcertbotを利用して証明書の取得を行ってみました。


# 手順
## 【１】podmanをインストールする
```sh
# dnf install podman
```

## 【２】ディレクトリを作成する
```sh
# mkdir -p /etc/letsencrypt
```

## 【３】SELinuxを無効化する
```sh
# setenforce 0
```

## 【４】certbotで証明書を取得する
### Webrootで認証する場合
#### １）Nginxをインストールする
```sh
# dnf install certbot
```

#### ２）ディレクトリを作成する
```sh
# mkdir -p /var/www/html
```

#### ３）nginx.confの設定変更を行う
```sh
root         /usr/share/nginx/html;
↓
root         /var/www/html;
```

#### ４）nginxサービスを開始する
```sh
# systemctl start nginx
```

#### ５）podmanでcertbotを実行する
※各コマンド実行後、画面の指示に従い作業を進めます。

```sh
# podman run -it --rm -v /etc/letsencrypt:/etc/letsencrypt -v /var/www/html:/var/www/html certbot/certbot certonly --webroot -w /var/www/html -d example.org --agree-tos
```

### DNSで認証する場合
```sh
# podman run -it --rm -v /etc/letsencrypt:/etc/letsencrypt -v /var/www/html:/var/www/html certbot/certbot certonly --manual -d example.org --agree-tos
```

#### ワイルドカード証明書を取得する場合
```sh
# podman run -it --rm -v /etc/letsencrypt:/etc/letsencrypt -v /var/www/html:/var/www/html certbot/certbot certonly --manual -d example.org -d *.example.org --agree-tos --server https://acme-v02.api.letsencrypt.org/directory
```
Cockpitを使い、virt-managerと同様の処理をする。

# Cockpitって？
`Cockpit`は、WebUIで Linux サーバの管理ができるツール。
以下のサイトから見てみると、CentOS,Ubuntuなどに対応しており、最新のWebブラウザに対応している。

https://cockpit-project.org/running.html

- PCのリソースの管理
- 仮想ゲストの管理

ができるので、是非とも試してみよう

# 設定方法
とても簡単。yuminstallして、firewallのポート(9090)を開けるだけ

cockpitのインストール。
```:コマンド
sudo yum install cockpit
```

cockpitサービスの有効化
```:コマンド
sudo systemctl enable --now cockpit.socket
```

使用するポートをfirewallで許可する。
```:コマンド
sudo firewall-cmd --add-service=cockpit
sudo firewall-cmd --add-service=cockpit --permanent
```
その後、`https://サーバのIPアドレス:9090`をWebブラウザに入力し、
アクセスする。

以下のような画面になるので、ログインする。
ログインに必要なパスワードは、普段サーバにアクセスするときに使うユーザ名とパスワードで大丈夫
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/3b626d01-6bb5-2e84-71e7-06973a3a9c2b.png)

ログイン直後、管理者アクセスをオンにすると、仮想マシンへのアクセス等ができたりする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/40b2d3f9-9925-b517-43db-c9ab40cfe260.png)

なお、CPUやメモリの使用量なども確認できる。*写真は公式サイトから見たイメージ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/965c242e-f621-1a85-e117-eb44ab824f32.png)


# 参考サイト

https://cockpit-project.org/
Notionで論文管理 Crossref APIの利活用

私ごとですが、この春、大学院に進学しました。:sunny:
学部は文系でしたので、晴れて理系の身になったわけですが、重要なのはそこではなく、読む論文が増えてきたことが眼前の問題でした。
世の中にはMendeleyやZoteroなどの論文管理ソフトがいくつかありますが、私はいずれに対しても不満がありました。モバイル版の廃止や同期速度の問題など、「論文管理のためだけにあるソフト」でありながら使い勝手が気になるのです。

# Notionで管理したい
できることならその上でbib出力もしたい。doiやpdfからメタデータを抜き出せないのかな？と常々考えていましたが、アイディアを考えることに疲れ、GWも差し掛かった今日この頃まで論文管理ソフトの導入を先延ばしにしてきました。
ZoteroとNotionをリンクさせるサービスや、同じくMendeleyとの併用こそ、Qiitaにも投稿されていましたが、どうにか別途サービスを使わず完結させたい。そう考えていると、こんな記事がありました。

[こうやってNotionで論文管理しています](https://qiita.com/issakuss/items/f204f56fe2b28988eff8#fn-2)

本稿はこの記事を参考にあくまで自分用に実現したものです。改善案お待ちしております。
どうやらpdf2doiを使ってpdfからメタデータを抽出しているようで、論文データベースへのアクセスはCrossrefのAPIを使っているようでした。この記事を見るまで私はCrossrefというサービスを知らず、ましてAPIを無料で取得できることを知らなかったので、渡りに船でした。
私の環境ではひとまずpdfから取得することは急務ではなかったので、これを省略し、doiからメタデータを取得することを考えました。
# 準備
コードは[Github](https://github.com/130noel/doi2notion)にあげていますが、NotionDBやAPIなど、事前に必要な用意がありますので、その点はご自身でお調べください。
私が使っているNotionテンプレートは[notion-scholar](https://github.com/thomashirtz/notion-scholar)[^1]にて、公開されている[Bibliography](https://thomashirtz.notion.site/Bibliography-68cfc13ff00f423787470214fd1d688f)というテンプレートを利用しています。

# 構造
Crossrefではdoiがあれば論文情報をJSON形式で取得できるようです。（Crossref APIを使ったサービスの検索をかけていたら`CR-Clickthrough-Client-Token`を使ってAPIキーを設定している方もいたのですが、それが何なのかよくわかりませんでした:joy:）
Webで論文探しや論文読みをしているとき、必ずdoiの記載がありますよね。そこから最短距離でNotionDBに保存するには、ブラウザの拡張機能として実装していくのが良さそうですが、それはおいおい。
というわけで、現状ではdoiやurlをコピーした状態でPythonを動かすと、メタデータを取得しPythonで扱えるよう変換した上でNotionに格納されるようになっています。
とは言っても現状では、エラー対策が何一つと言ってもいいほど済んでいません。何が原因でエラーを吐いているのかチェックする機構を追加していない現状ですので、これから改善していかなければなりません。
404が出た場合はCrossrefに当該論文データが存在しないことを暗示していると思って使っているような現状です（うまくコピーができていない可能性もあります）。



# 終わりに
前口上と言えるほど大層なものではありませんが、海外発サービスでの英文記事を読んでいると、自分の身の上話から始まることが多いように感じており、本稿ではそれを踏襲してみました笑
下書きこそあれど実際の公開記事は初めてだったので、至らぬところが多いことかと思います。後ほど時間がある時に変更する予定です。図やスクショを入れたりしたいです。


[^1]:BibTexファイルからNotionDBに保存するサービス。
Azure Reposに対してgit cloneでエラーTF401019: The Git repository with name or identifier [リポジトリ名].git does not exist or you do not have permissions for the operation you are attempting.

# 概要
git cloneした際にエラーででてくる下記のエラーは通常は対象のリポジトリが存在しないか、もしくはリポジトリ名を間違えているときにでるエラーのようです。

```
TF401019: The Git repository with name or identifier [リポジトリ名].git does not exist or you do not have permissions for the operation you are attempting.
```


# 躓いた状況

今回私の環境ではGitHubではなく、Azure Repos上のリポジトリに対してgit cloneしようとした際に当該のエラーが発生しました。

# 原因
リポジトリurlの末尾に「.git」を追加していたことが原因

# 解説
通常GitHubからリポジトリurlをコピーすると末尾が「.git」になりますが、Azure Repoでは.gitがつかない。


GitHubの画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/00ef1a4b-a675-24b9-0365-735c339a696c.png)


Azure Reposの画面
![{9EDE8F3D-3ED9-4C24-ABC2-6A9A5928B0F6}.png.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/62df044d-e14d-6c29-8aaf-9b38e1658d61.jpeg)

GitHubからのクローンが習慣化していたせいかリポジトリurlの末尾は「.git」だろ！
という思い込みで良かれとつけていた.gitが原因でした。
Git 間違えて編集してしまったadd前のファイルを元に戻す方法

```
$ git checkout ファイル名
```
`ファイル名`を`.`にすると、ステージング前の全ての変更内容がなくなる

### 参考
* [[git] 戻したい時よく使っているコマンドまとめ - Qiita](https://qiita.com/rch1223/items/9377446c3d010d91399b)
fish shellのfunctionで環境変数を設定する

## やること

fishのfunctionで環境変数を設定する

## 背景

プロキシを介したり、介さなかったり、そのときの状況で変わるので、https_proxyの設定を簡単に行うために、functionで解決しようとした。

## 環境

Git for windowsにMSYS2を適用してpacmanでfishをインストールしている。

## やること

### functionを作る

```
function proxy
    export HTTPS_PROXY=〇〇〇
end
```

### プロキシを使うとき

```shell
proxy
```

## ポイント

setではできなかった。exportだとできる。
WSLでlaravel sailのデータベースをmigrateするのに苦労したので覚書

# 今回対処したエラーコード

>SQLSTATE[HY000] [2002] Connection refused (Connection: mysql, SQL: select * from information_schema.tables where table_schema = todo and table_name = migrations and table_type = 'BASE TABLE')


## 素朴な疑問、Windows環境でどうやったらsailのコンテナにアクセスできるというのだろう。。。

WindowsでLaravel Sailを使うのは何かと面倒なことが多いです。

SailがLinux上で使うことを前提にしているので、LinuxベースではないWindowsで使おうとすると、何かと困難が多いわけです。

WindowsでSailの環境を作るのにも骨が折れましたが、こちらの記事の通りにやると、割と簡単に導入できますので、ぜひお試しください。

参考サイト：[Laravel SailをWindowsにインストールする手順を分かりやすく解説
](https://biz.addisteria.com/01laravel_sail/#toc2)

## cloneした環境のデータベースをmigrateしたかった

今回は環境はすでにある状態なのですが、こちらでcloneした環境のデータベースをセットアップしなきゃいけないという状況。

にしても、sailを立ち上げたターミナルにはコマンド入力できないし。。。ということで、別窓でターミナル立ち上げ→WSL起動で
`$ ./vendor/bin/sail artisan migrate --seed`
を実行してみました。

そこで帰ってきた答え。
Sail is not running.

Sailが走ってないってよ😱
そりゃそうです。Sailが立ち上がってるのは別窓だから。

というわけでググりまくってると、バックグラウンドでSailを走らせる方法があったんですね。
それがこちら。
`$ ./vendor/bin/sail up -d`

おおお！
打てる。。。打てるぞよ。。。コマンドが😭

というわけで改めてmigrate実行

・・・

```
 Illuminate\Database\QueryException 

 

  SQLSTATE[HY000] [2002] Connection refused (Connection: mysql, SQL: select * from information_schema.tables where table_schema = todo and table_name = migrations and table_type = 'BASE TABLE')

 

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:793
    789▕         // If an exception occurs when attempting to run a query, we'll format the error
    790▕         // message to include the bindings with SQL, which will make this exception a
    791▕         // lot more helpful to the developer instead of just the database's errors.
    792▕         catch (Exception $e) {
  ➜ 793▕             throw new QueryException(
    794▕                 $this->getName(), $query, $this->prepareBindings($bindings), $e
    795▕             );
    796▕         }
    797▕     }

 

      +38 vendor frames 

 

  39  artisan:35
      Illuminate\Foundation\Console\Kernel::handle()

``` 

なにそれ？😢

あきらめないのであります。

**要はConnection refusedということだよねと。**

そしてググってググってググった挙句みつけた答え。

## .envファイルのDB_HOSTが原因だった

IPアドレスではなく、DBのコンテナ名で指定してやると良いとのこと。

Before
```.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=todo
DB_USERNAME=root
DB_PASSWORD=
```
After
```.env
DB_CONNECTION=mysql
DB_HOST=mysql  #127.0.0.1
DB_PORT=3306
DB_DATABASE=todo
DB_USERNAME=root
DB_PASSWORD=
```

参考サイト：[【Laravel】migrateができないのは環境変数が間違っているからかも！あるあるエラーを.envと共に振り返る。](https://qiita.com/wallkickers/items/47efb41dd200722a98fe)

ほんとにそれだけ？

と、半信半疑で再びコンテナ再起動で
`$ ./vendor/bin/sail artisan migrate --seed`
トライ！！

おおお！サクサクmigrateが始まってくれました！😊

というわけで、データベースの準備ができたところでガッツリ開発に集中できます！！

お疲れ様でした😘
Python3: PostgreSQL のテーブルのコラム名とタイプを取得

## プログラム

```py:show_columns.py
#! /usr/bin/python
#
#	show columns
#
#				Apr/27/2023
#
# --------------------------------------------------------
import os
import sys
import json
import psycopg2
from dotenv import load_dotenv
#
# --------------------------------------------------------
sys.stderr.write ("*** 開始 ***\n")
data_base = sys.argv[1]
table_in = sys.argv[2]
sys.stderr.write ("%s\n" % data_base)
sys.stderr.write ("%s\n" % table_in)
#
dotenv_path = '.env'
load_dotenv(dotenv_path)
USER=os.environ.get("user")
PASSWORD=os.environ.get("password")
#
dsn="dbname=" + data_base + " user=" + USER + " password=" + PASSWORD
conn = psycopg2.connect(dsn)
cursor_aa = conn.cursor()
#
sql_str = "select column_name,data_type from information_schema.columns where table_name = '" + table_in + "'"
cursor_aa.execute(sql_str)
rows = cursor_aa.fetchall()
dict_aa = {}
for row in rows:
	dict_aa[row[0]] = row[1]
#	print(row[0],row[1])
conn.commit ()
#
cursor_aa.close ()
conn.close ()
#
str_out = json.dumps(dict_aa)
print(str_out)
#
sys.stderr.write ("*** 終了 ***\n")
#
# --------------------------------------------------------
```

```text:.env
user='scott'
password='secret'
```

## 実行結果

```text
$ ./show_columns.py city cities | jq
*** 開始 ***
city
cities
*** 終了 ***
{
  "population": "integer",
  "date_mod": "date",
  "id": "character varying",
  "name": "text"
}
```

## 確認したバージョン

```text
$ python
Python 3.12.3 (main, Apr 10 2024, 05:33:47) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import psycopg2
>>> psycopg2.__version__
'2.9.9 (dt dec pq3 ext lo64)'
```
Docker composeを使用してRails + MySQLを起動しよう！！

# はじめに
今回初めてDockerを触ってみて色々と苦戦したので、備忘録として残しておきます。
解釈違う部分もあるかと思いますので、ご指摘よろしくお願いいたします。
また、同じ初学者に少しでもお力になれればと思います。
前提条件として今回使用するものは以下になります！
またDockerはインストールしているものとし、記述方法も最新版に準拠しますのでよろしくお願いします。
- M１mac
- Ruby 3.1.2
- Rails 7
- MySQL 8.0

# ファイルの作成
まずは必要なファイルの準備を行います。
今回のファイル構成はこのようにします。
```　ruby:ディレクトリ
myapp
 |-- Dockerfile
 |-- compose.yml
 |-- Gemfile
 |-- Gemfile.lock
```
これらファイルを使いイメージ作成、コンテナの作成と進んでいきます。


# 各ファイルの中身
## Dockerfile
```Dockerfile:Dockerfile
FROM ruby:3.1.2
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs vim
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
```
まずDockerfileから見ていきます。
このファイルでは下記を使いそれぞれイメージを作成していきます。
イメージとはコンテナを作る上でのテンプレートのようなものでイメージを元にコンテナを作成します。
- FROM: 使用するイメージとバージョン
- RUN: コマンドの実行
- WORKDIR: 操作ディレクトリの設定
- ADD: 記述されたファイルを追加する
 
細かい説明としては下記です。
1\.apt-get updateとapt-get installはそのままの意味で今回コンテナ内で使用する必要のあるgem等をアップデートしたのちにインストールするという意味です。
2\.-qqオプションと-yオプションは-qqでエラー以外の何も表示しない設定で、-yはインストールする際にyesかnoを問われるものに対して全て自動でyesを返すというオプションです。

## compose.yml
```compose.yml
services:
  db:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - ./db/mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    tty: true
    stdin_open: true
    depends_on:
      - db
```
compose.ymlでは複数コンテナを同時に作成できるもので今回はMySQLのデータサーバーとRails7のサーバーが必要になるのでこちらで作成します！
dbと記述してインデント下がっている部分がデータサーバーに対する記述でweb移行がRails７の為のサーバーです。
主な説明としては下記になります。
- services：コンテナのこと。
- image：今回使用するイメージの記述
- command：実行する処理
- volumes：コンテナに接続する。
- environment：環境変数
- tty：擬似端末の配置
- depends_on:コンテナ間の依存関係

:::note warn
注意
上記２つのファイルではインデントで処理がどこに属しているか判断しているのでインデントは揃えましょう！！！
:::


## Gemfile
```:Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 7.0.0'
```
ここでは今回使用するRailsのバージョンを記載しておきます！後ほど上書きされます。

# コマンドの実行
それではコマンドの実行を行います！私はiTermを使用しているのでこちらに記述していきます！

### 1
```
docker compose run web rails new . --force --database=mysql
```
このコマンドでRailsの元が作成され、Gemfileも上書きされます。
この後、エラーでbundle　installしてくださいとエラー出ます、、、もっといい記述方法あるかと思うのですが今回はインストールして進めていきます。

### 2
```
docker compose run web bash
```
このコマンドでDocker内でコマンド使えるのでこの後にbundle installの実施。その後、exitで抜けてください。

### 3
```
docker compose build
```
そしてイメージをbuildします。

### 4
```
database.ymlのpasswordのところをpasswordに変え、hostのところをdbに変更。
```
ここで１度ファイルに戻っていただきconfig配下のdatabase.ymlにて上記部分を変更いたします。

### 5
```
docker compose run web rails db:create
```
そして再度コマンドで上記打っていただき、db作成します。

### 6
```
docker compose up
```
最後にこのコードで完成です！localhost:3000にアクセスするとRailsの初期画面が出るかと思います！


# 最後に
長くなってしまいましたが私の環境構築以上になります。
bundle installしなくてはいけない部分があるので改善できしだい再編集してあげたいと思います、、、
まだまだ初学者なため至らない点多いかと思いますが、同じ境遇の方のお力になれればと思います！
最後まで読んでいただきありがとうございました！
[Arduino Uno]ボタン連打ゲームを作ってみた！

# 動機
secHack365の思索駆動コースの応募課題を提出するためプログラム以外の制作物を用意する必要があったから。

# 購入したもの
Amazonで[これ](https://www.amazon.co.jp/gp/product/B06XF2HZGT/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1)をポチりました。キャンペーンのおかげか20%offで買えたので嬉しかったです。(4130円:v:)

https://www.amazon.co.jp/gp/product/B06XF2HZGT/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1

# 制作物の説明
<iframe width="560" height="315" src="https://www.youtube.com/embed/pV8_ZJwgzSU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
ボタンを連打して押し込めたら勝ちです！とてもシンプル。

# 実装方法
Arduino IDEのインストール、portとボードの設定を付属資料に従い終了させたあとに以下のように回路を作りました。(もう少し短いワイヤが欲しい...)


その後IDEでCプログラムを作成し、コンパイルとアップロードを行います。
使用したプログラム全体を示します。
```c
// LED右端のピン番号
int ledPinMR = 6;
// LED左端のピン番号
int ledPinML = 12;
// 右のボタンのピン番号
int buttonPinR = 5;
// 左のボタンのピン番号
int buttonPinL = 13;
// 点灯させるLEDのピン番号(初期設定は真ん中)
int now = (ledPinMR+ledPinML)/2;
// 実行を制御するフラッグ
// flag: 0->ゲーム終了, 1->ゲーム未終了
// rFlag: 0->右のボタンが押下げられている, 1->押下げられていない
// lFlag: 0->左のボタンが押下げられている, 1->押下げられていない)
int flag = 1, rFlag = 1, lFlag = 1;

void setup() {
// ボタンのピンから入力を得るための初期設定
  pinMode(buttonPinR, INPUT_PULLUP);
  pinMode(buttonPinL, INPUT_PULLUP);
// ledのピンに出力するための初期設定
  for(int i=ledPinMR;i<=ledPinML;i++) pinMode(i, OUTPUT);
}

void loop() {
// もしゲームが終了している場合
  if(flag == 0) {
    for(int i=ledPinMR;i<=ledPinML;i++) digitalWrite(i, HIGH);
    delay(1000);
    for(int i=ledPinMR;i<=ledPinML;i++) digitalWrite(i, LOW);
    if(ledPinML < now)digitalWrite(ledPinML, HIGH);
    if(now < ledPinMR)digitalWrite(ledPinMR, HIGH);
    delay(1000);
    return;
  }
// もしボタンが押下げられていない場合
  if(digitalRead(buttonPinL) == HIGH) lFlag = 1;
  if(digitalRead(buttonPinR) == HIGH) rFlag = 1;
// もしボタンが押下げられていないときにボタンが押下げられたときnowを操作しボタンのフラグを0にする
  
  if((digitalRead(buttonPinL) == LOW) && (lFlag == 1)) {
    now--;
    lFlag = 0;
  }
if((digitalRead(buttonPinR) == LOW) && (rFlag == 1)) {
    now++;
    rFlag = 0;
  }
// nowが片方に押しやられたときゲームを終了する
  if(now > ledPinML || ledPinMR > now) flag = 0;
// nowに従いledを点灯する
  for(int i=ledPinMR;i<=ledPinML;i++) {
    if(i == now) digitalWrite(i, HIGH);
    else digitalWrite(i, LOW);
  }
}

```

# 迷ったこと
最初nowを以下のようにしていたのですが、ボタンを押下げた瞬間にゲームが終了しました。
```c
  if(digitalRead(buttonPinR) == LOW) {
    now++;
  }
  if(digitalRead(buttonPinL) == LOW) {
    now--;
  }
```
## 原因
一度の押下げでも大量のloop()が呼ばれていました。
```c
Serial.begin(9660);
```
をsetup()に追加し、
```c
Serial.print(rFlag);
Serial.print(lFlag);
Serial.print("\n");
```
をloop()に追加して確認を行いました。押下げされた後のnowが一瞬で片方に振り切れていることがわかりました。
## 対策
変数nowへの操作を行うのは押下げを検知した最初のloopだけに制限し、ボタンが元の状態に戻るまでnowへのアクセスを禁止するとうまく実行されました。
そのためにrFlag, lFlagを用意しました。

# 完成！
![S__37445669.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531876/f4efa1c9-6cee-ec43-9d0e-fdfa4f545bab.jpeg)

![S__37445668.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531876/467eb684-9fd8-6292-6ac4-097075d0fc0d.jpeg)

人生で初めてこういう形になるものを作りました！思いがけないエラーに悩まされましたが解決できて嬉しかったです！これからも何か作っていきたいです。皆さんの作ったゲームや面白いものがあったら紹介してください！

また注文した翌日に配達してくださった配達員さんに感謝します！

以上、ありがとうございました。:kissing_smiling_eyes::wave:
ワケあってffmpegを使うことになったので使ったコマンドをまとめる

パスは全部相対パスで書いてます。
細かいオプションは省略。

# 動画を変換する

```shell
ffmpeg -i src/input.mp4 -b:v 436k -c:v h264 -b:a 48k -c:a aac dest/output.mp4
```

# 動画を結合する

結合したい動画ファイルを一覧に起こす

```text:files.txt
file src/input1.mp4
file src/input2.mp4
file src/input3.mp4
```

## 結合だけする

```shell
ffmpeg -f concat -safe 0 -i files.txt -c copy dest/output.mp4
```

## 結合しつつ変換もする

```shell
ffmpeg -f concat -safe 0 -i files.txt -b:v 436k -c:v h264 -b:a 48k -c:a aac dest/output.mp4
```

# 動画を分割する

60秒ごとに分割する例

## 分割だけする

```shell
ffmpeg -i src/input.mp4 -ss 0 -to 60 -c copy dest/output1.mp4
ffmpeg -i src/input.mp4 -ss 60 -to 120 -c copy dest/output2.mp4
ffmpeg -i src/input.mp4 -ss 120 -to 180 -c copy dest/output3.mp4
```

## 分割しつつ変換もする

```shell
ffmpeg -i src/input.mp4 -ss 0 -to 60 -b:v 436k -c:v h264 -b:a 48k -c:a aac dest/output1.mp4
ffmpeg -i src/input.mp4 -ss 60 -to 120 -b:v 436k -c:v h264 -b:a 48k -c:a aac dest/output2.mp4
ffmpeg -i src/input.mp4 -ss 120 -to 180 -b:v 436k -c:v h264 -b:a 48k -c:a aac dest/output3.mp4
```
AWS WAF　通したいリクエストが通らなかったときの対応方法

# はじめに

自分用のメモです。

## 該当リクエストを探す

AWS WAF > Web ACLs > 対象のWeb ACLsをクリック

Overviewの下部、Sampled requestsの中でBLOCKされている通したいリクエストを特定する。

「Rule inside rule group」のカラムを見て、該当のルールをメモする。

## セーフリストへ追加

Rulesタブをクリック
Rulesの中で該当のルールをクリック
ページ上部の「Edit」をクリック
「Core rule set rules」の中で対象のルールを「Coute」にセット。
設定を保存。

これでセーフリストに追加されます。

## 参考資料

https://repost.aws/ja/knowledge-center/waf-detect-false-positives-from-amrs
◯バージョンによって変化するlist()◯

備忘録として投稿。

・PHPのlist()は、配列から値を抽出して変数に代入するための便利な機能である。
ただし、古いバージョンのPHPでは、list()による代入ができるのは配列のインデックスのみであり、連想配列に対しては使用できなかった。

例えば、以下のコードをPHP 5.6以下で実行すると、list()は構文エラーを引き起こす。
~~~php
$person = array('name' => 'John', 'age' => 30);
list('name' => $name, 'age' => $age) = $person;
~~~

・一方、PHP 7以降では、list()が連想配列に対しても使用できるようになった。
したがって、上記のコードはPHP 7以降で正常に動作する。

・また、PHP 7.1からは、list()による代入がnull合体演算子(??)と組み合わせて使用できるようになった。
これにより、以下のように変数にデフォルト値を設定できるようになった。
~~~php
$person = array('name' => 'John');
list('name' => $name, 'age' => $age) = $person ?? ['age' => 18];
~~~
この場合、\\$personにageキーが含まれていない場合、$ageにはデフォルト値として18が代入される。

◎余談◎
・PHP 7.0より前のバージョンでは、list()で配列から値を取り出す場合、配列の先頭から順に値を割り当てていく。
例えば、以下のコードを実行すると、変数\\$aに2→1の順で格納される。
~~~php
list($a[], $a[]) = [1, 2];
~~~
しかし、PHP 7.0からは、list()で配列から値を取り出す場合、配列の最初から順に値を割り当てるように変更された。
つまり、上記のコードを実行すると、変数\\$aに1→2の順で格納されるようになる。

・この変更は、複数の値を返す関数から返された配列をlist()で変数に割り当てる場合に、より自然な動作をするようになるために行われたもの。
ただし、これまでのコードとの互換性が失われるため、注意が必要。

※訂正※
・list()は、関数ではなく言語構造。勘違いしてました。
https://www.php.net/manual/ja/function.list.php
・list()は、PHPバージョン7.0を境に格納する順番が変わります。
https://3v4l.org/CpIoV#v7.0.0
【Azure】DataFactoryのForEachを用いたループ処理

## はじめに

こんにちは。株式会社ZEALの@ey___00129です。

**DataFactoryのForEachを用いたループ処理**について
**Lookupアクティビティで取得した値をもとにループする処理**を実装していきたいと思います。

利用するAzureリソースは以下
・DataFactory
・AzureSQLDatabase(プロシージャを作成し、ループ処理の確認用として)


所要時間：30分程で実装可能


## AzureSQLDatabaseにてプロシージャ作成

まずは、**ループ処理の確認用のプロシージャを作成**します。
今回は確認目的なので連携されたパラメーターをInsertするプロシージャを作成。


```
CREATE PROCEDURE [dbo].[Insert_parameter]
@parameter AS  [varchar](20)
AS 
DECLARE @parameter1 AS [varchar](20)  
SET @parameter1 = @parameter;  
EXECUTE ('INSERT INTO [dbo].[parameter_insert_table] VALUES ('''+ @parameter1 +''');'); 

GO
```

一旦、AzureSQLDatabase上で挙動確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/68842e5d-91d7-3bbb-ac71-e6984b5e77e1.png)

正しくパラメーターが取り込まれていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/8c519f73-1004-d590-ae5e-80955193b7b1.png)


## DataFactoryのパイプライン作成

ここからは、**Lookupアクティビティで取得した値**を
**ループ処理に引き渡し取得したデータを元に、プロシージャを繰り返し実行**していきたいと思います。

利用するアクティビティは以下。
・Lookup
・ForEach
・Stored procedure

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/f011bcec-4b7d-07bb-cc56-3539be4c5a51.png)


Lookupアクティビティでは、parameterテーブルに存在する値を取得するクエリを記載。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/1fea6034-f4ff-de80-cbf3-77a803516c2c.png)

**ForEachのItemsでは、Lookupから渡された結果をvalueとして受け取ります**。

Sequentialでは、チェックを入れると順次ループ処理が実行されます。
チェックを入れないと、並列で処理が実行されます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/afbd7895-c3dd-76e1-8582-822f745ec9f7.png)

Itemsは、以下
```
@activity('Lookup').output.value
```

最後に、ForEachの中にStored procedureを作成し
Stored procedure parametersに渡したいパラメーター（@item().parameter）を記載します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/8d4191e5-c0b6-b44d-dc84-f9fd7dd9591b.png)


これで設定は以上です。



## DataFactory実行確認

＜実行前＞
Lookupアクティビティが取得する先のテーブル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/ec57dbee-bb08-1b69-5a2a-50a2ecbef01e.png)

パラメーター取り込み先テーブル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/113aab59-1c7d-3233-e60a-c3b4ea1b9259.png)


DataFactoryを実行
**Stored procedureがパラメーター分３回繰り返し実行**されていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/41f358bb-cad1-5342-3d44-eec1cbcd2d8e.png)



＜実行後＞
パラメーター取り込み先テーブルにも正しく３レコード取り込まれていました！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741843/034b5413-e586-425c-5227-c51b2db339d6.png)


以上で、完了です。


今回は基礎的なループ処理を実装してみましたが、
処理を共通化するときなど、他にも応用して使えるので是非お試しください。
【EC2】ディスクを拡張する時にすることメモ📝


開発で使っていたEC2がディスクフルになりそうだったので拡張作業をしないといけなかった。。。
今後もおんなじようなことが起こりそうなので備忘のためメモ

## 基本情報
OS:Ubuntu
プラットフォーム：x86

## 事前作業

サーバーを起動したままでスナップショットの取得やディスク拡張を行うと、故障する可能性があるのでEC2は停止します。
（あとは他の人がサーバーにアクセスして操作することの防止）

## スナップショットの取得をする

切り戻しができるように拡張作業をする前は、事前にEBSボリュームのスナップショットを取得します。[^1]

![ボリュームの拡張.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/0506df85-c5b7-67cb-047d-8f1a4609b068.jpeg)


スナップショットの説明は、サーバー情報や日付などプロジェクトに決まりがあればそれを入力します。

![スナップショットの作成.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/e81a83a8-cd64-fb6b-3be3-00b368d3a5d7.jpeg)


## EBSボリュームを拡張する

対象のEBSボリュームの画面に遷移したら、右上の変更ボタンを押します。

![ボリュームの変更１.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/27c29c3a-ad65-4c14-ada0-94cab0fcfb50.jpeg)

今回はボリュームをgp2からgp3に変更し、変更ボタンを押します。[^2]

![ボリュームの変更.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/9d8c88e3-14ec-3ee7-a93e-b6bd7e0c08a8.jpeg)

しばらくボリュームの状態がOptimized...になった後、使用中のステータスになったらEC2を起動します。

![ボリューム変更後の画面.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89244/0994d37b-0b70-248d-e262-6a416fd3de36.jpeg)

## 拡張されたかを確認する

EC2にログインしdfコマンドで対象のSizeが変更後の値になっているかを確認します。[^3]

```console
~$ df -hT
Filesystem      Type      Size  Used Avail Use% Mounted on
/dev/root       ext4       49G  7.2G   42G  15% /
devtmpfs        devtmpfs  3.8G     0  3.8G   0% /dev
tmpfs           tmpfs     3.8G   52K  3.8G   1% /dev/shm
tmpfs           tmpfs     766M   13M  753M   2% /run
tmpfs           tmpfs     5.0M     0  5.0M   0% /run/lock
tmpfs           tmpfs     3.8G     0  3.8G   0% /sys/fs/cgroup
/dev/loop0      squashfs   25M   25M     0 100% /snap/amazon-ssm-agent/6312
/dev/loop1      squashfs   56M   56M     0 100% /snap/core18/2721
/dev/loop2      squashfs   50M   50M     0 100% /snap/snapd/18596
/dev/loop3      squashfs   54M   54M     0 100% /snap/snapd/18933
/dev/nvme0n1p15 vfat      105M  6.1M   99M   6% /boot/efi
/dev/loop4      squashfs   56M   56M     0 100% /snap/core18/2714
/dev/loop5      squashfs   64M   64M     0 100% /snap/core20/1852
/dev/loop6      squashfs   92M   92M     0 100% /snap/lxd/24061
tmpfs           tmpfs     766M     0  766M   0% /run/user/1000
```

所感
今までは拡張後にe2fsckして整合性を確かめ、resize2fsをするみたいな作業をしないといけなかったけど
最近はストレージ拡張のパーティションの拡張もAWS側でしてくれて便利だなーって思いました。
ついでに、ボリューム拡張の際に表示される料金のリンク404になっていたのでサポートに教えてあげた。


参考資料

[ボリュームサイズ変更後の Linux ファイルシステムの拡張](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html)

脚注

[^1]: [Amazon EBS スナップショットの作成](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-creating-snapshot.html)
[^2]:[EBS ボリュームへの変更のリクエスト](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/requesting-ebs-volume-modifications.html)
[^3]:[dfコマンド](https://linuxjm.osdn.jp/html/GNU_coreutils/man1/df.1.html)
実行後にアプリを起動するインストーラの設定(.NET)

# 環境
.NET6
Visual Studio 2022
Microsoft Visual Studio Installer Projects 2022

# はじめに
どうも、水無月せきなです。

長らく開発している[VRCToolBox](https://github.com/MinadukiSekina/VRCToolBox)の配布を、インストーラ（.msi）で行っています。
インストーラ実行後はEXEが起動する（あるいはオプションで起動できるようになっている）アプリケーションが多いと思いますが、Installer Projectsで作成する場合はちょっとひと手間が要ります。

インストーラプロジェクトの設定などを実際にしたのはだいぶ前なので、忘れている部分もありますが、適宜思い出しつつ、備忘録的に記したいと思います。

# 手順
### 1. インストーラ作成準備
インストーラを作成できるように準備します。
今回の本題ではないので、以下の記事などを参考に準備してください。

[Visual Studio 2022でアプリケーションのインストーラーを作成する](https://zenn.dev/overdrive1708/articles/howto-vs2022-create-application-installer)
[Visual Studio Installer Projects 拡張機能 と .NET 6.0](https://learn.microsoft.com/ja-jp/visualstudio/deployment/installer-projects-net-core?view=vs-2022)

※注意点として、.NET（Core系列）の場合は、インストーラに含めるプロジェクト出力は「項目の公開（英語版だと Publish Items）」です。.NET Framework の場合とは異なります。

### 2. Orca の準備
作成したインストーラ（.msi）を編集するため、Orca というソフトが必要になります。
以下の記事などを参考にOrcaをインストールしてください。

[Orcaの入手法 - dobon.net](https://dobon.net/vb/dotnet/deployment/orca.html#wsdk)

Windows SDK が入っていれば、Orca のインストーラもある可能性が高いです。私の場合は下記にありました（{Windowsのバージョン}は適宜置き換えてください）。
>C:\\Program Files (x86)\\Windows Kits\\10\bin\\{Windowsのバージョン}\\x86

以降は、Oraca をインストール済みとして話を進めます。

### 3. インストーラを Orca で開く
インストーラプロジェクトをビルド後、.msi ファイルを右クリック → `Edit With Orca` を選択して、Orca で .msi を開きます。

### 4. exe の File ID を探し出す
![インストーラ１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1843472/70f1dac1-7b6c-bd2b-c817-f09127103c65.png)
`Tables` の `File` を選択し、exe の行を探します。その行の `File` 列のセルを右クリック → `Copy　Cell` でコピーします。

### 5. カスタムアクションを定義する
![インストーラ２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1843472/7bb037a9-c627-6006-7001-4200d3c1de2f.png)
`Tables` の `Custom Action` を選択し、空いているスペースをダブルクリックします。
すると、アクションを追加する画面が開くので、下記のように入力します。

Action：LaunchApp
Type：210
Source：さっきコピーした File ID
Target：空白

![インストーラ５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1843472/b0cc65a0-b610-9917-a19d-c6af6e777769.png)

### 6. インストーラ終了時にカスタムアクションを実行するように設定する
![インストーラ３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1843472/885c9969-fbcf-1138-c587-c25487428ef1.png)

1. `Tables` の `Control Event` を選択し、`FinishedForm` の行を探します。その行を右クリック → `Copy Row(s)` でコピーします。その後、右クリック → `Paste Row(s)` で貼り付けます。

2. 今貼り付けた行の `Dialog` 列が `FinishedForm0` のようになっているはずなので、その行を探し出します（たぶん最下行にあるはず）。

3. セルをダブルクリックすると編集できるようになるので、下記のように値を変更します。
   Event：DoAction
   Argument：LaunchApp
   最後に、`Dialog` を `FinishedForm` に変更します。

4. 元の `FinishedForm` の行の `Order` を `1` に変更します。

### 7. 変更を保存する
左上の保存マーク、もしくは `File` → `Save` などで保存します。

### 8. インストーラを実行する
インストール後、アプリが起動するようになったはずです。

### 参考
[インストール終了後にアプリケーションを起動するか選択できるようにする - dobon.net](https://dobon.net/vb/dotnet/deployment/uieditor.html#reboot)

VBS を使う方法で紹介されています（し、初期は私もVBSでやってましたが……）。ただ、VBS はセキュリティで止まるかもとか言うのをネットで見た気がするので、直起動が良いかも？ と思って今回の方法に至りました。
【初学者向け】RubyのStructクラスをわかった気になろう！

# はじめに
  この記事では、初学者の方を対象に、Rubyにおける **Structクラス** について「なんとなくだけど理解できた！」となることを目標としています。

:::note warn
  警告
  筆者独自の見解を基に説明していますので、正確性が犠牲になっていたり、場合によっては間違っている可能性もあります。
  最終的には公式のリファレンス等を確認してください。
  Ruby公式リファレンス：[class Struct](https://docs.ruby-lang.org/ja/latest/class/Struct.html)
:::

# Structクラスとは
  Structクラスとは、簡単なデータ構造を定義するためのクラスです。

  ... 正直なところ、説明を聞くより簡単なコードを読む方が理解が早いと思います。
なので具体例として記載しているコードと説明文を行き来しながら読み進めてください(￣▽￣)

# 使い方
  **Struct.new** をすることで、Structクラスの **サブクラス** を生成することができます。
  このサブクラスでは、インスタンス変数やアクセサメソッドなどが自動的に用意されます。
  そして、そのサブクラスから具体的なデータであるインスタンスを生成して使用します。

具体的には、以下のように記述することで、StructクラスのサブクラスであるPersonクラスを定義することができます。
```ruby
  Person = Struct.new(:name, :age)
```
上記のコードではPersonクラスを定義しています(インスタンスを生成して定数に代入しているのではありません)。
上記のコードは、下記のコードとほぼ同じような振る舞いをします(似ているだけで同じではありませんが)。
```ruby
  # Personクラスは、Structクラスのサブクラス
  class Person < Struct
    # アクセサメソッドが自動的に用意されている
    attr_accessor :name, :age

    # インスタンス変数のようにデータが保持されている
    def initialize(name, age)
      @name = name
      @age = age
    end
  end
```

# 具体例
具体例を通して理解を深めましょう。
```ruby
  # Structを使ってPersonクラスを定義
  Person = Struct.new(:name, :age)

  # Personクラスのインスタンスを作成
  person1 = Person.new("Alice", 19)
  person2 = Person.new("Bob", 25)

  # アクセス
  puts person1.name  # => "Alice"
  puts person1.age   # => 19
  puts person2.name  # => "Bob"
  puts person2.age   # => 25

  # 更新
  person2.age = 31
  puts person2.age   # => 31
```
# で、何がいいの？
Structクラスを用いることの利点はいくつかありますが、一番は「コードが読みやすい」ことだと思います。
仮に配列person に名前と年齢が入っていた場合、インデックス番号を用いて指定しなければなりません。まして、２次元配列だったらさらに読みにくいです。
それよりはこっちの方が自然言語っぽくて読みやすいよね！ってことだと思います。

# 最後に
  ここまで読んでいただきありがとうございました！！
  もし本記事が少しでも理解の助けになったなら、ぜひイイね！をよろしくお願いします (*ᴗˬᴗ)⁾⁾
PlatformIO環境でのESP32のシリアルコンソール文字化けメモ


文字化けは通信速度問題がよくあるとのことで、

https://kanagawa16.sakura.ne.jp/wp/?p=257

設定を変えたいのですがPlatformIOだとiniファイルに書き込んで設定するようです。

http://kunsen.net/2018/07/28/post-618/#i-9

以下のように通信速度を115200で指定したらなおりました。

```
monitor_speed = 115200
```

こちらの記事を書いたときのiniファイルに追記してみます。

https://qiita.com/n0bisuke/items/88b3d274263b9d4f6dc7

全部だとこんな感じです。

```platformio.ini
; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:m5stack-atom]
platform = espressif32
board = m5stack-atom
framework = arduino
lib_deps = 
	m5stack/M5Atom@^0.1.0
	fastled/FastLED@^3.5.0
	earlephilhower/ESP8266Audio@^1.9.7

monitor_speed = 115200
```

これを書くだけで特にビルドしなおしなどせずに文字化けが解消されました。

> ![スクリーンショット 2023-04-27 19.02.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/34b3074d-2b20-7de4-5e35-016aa8d0dd80.png "スクリーンショット 2023-04-27 19.02.18.png")