OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Certified Security - Specialty に合格しました

2021/10/09 に AWS Certified Security - Specialty 試験を受験して、無事に合格しました。試験対策とメモを残しておきます。
![aws-scs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/780549/6ec30655-b03a-00e5-39a2-66bf1ca6f1c3.png)

## 対策
[要点整理から攻略する『AWS認定 セキュリティ-専門知識』](https://www.amazon.co.jp/%E8%A6%81%E7%82%B9%E6%95%B4%E7%90%86%E3%81%8B%E3%82%89%E6%94%BB%E7%95%A5%E3%81%99%E3%82%8B%E3%80%8EAWS%E8%AA%8D%E5%AE%9A-%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3-%E5%B0%82%E9%96%80%E7%9F%A5%E8%AD%98%E3%80%8F-Compass-Books%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE-ebook/dp/B08DCLRHC7/)を使って試験対策しました。この参考書に練習問題（40問）が用意されているので、まずは練習問題を解いて自分の苦手なサービスを明らかにするようにしました。その後苦手なサービスを参考書を使って理解するようにしました。私の場合は、KMS の理解があやふやだったので 4 章 の KMS の節を読み込みノートにまとめるようにしました。

## 所感
セキュリティ試験では、AWSサービスの深い知識を問われるというよりかは、サービスのセキュリティの基本的な知識を問われた印象です。「[要点整理から攻略する『AWS認定 セキュリティ-専門知識』]」を読み込んで各AWSサービスのセキュリティの基本的な知識を詰め込んだら、あとは、それらを組み合わせて問題文に答えるだけでした。
Type of the default value for '〇〇' prop must be a function

## 問題
```
Type of the default value for '〇〇' prop must be a function
```

というエラーが出た。

中身は以下のような感じ

```:sample.vue
<script>
export default {
  props: {
    〇〇: {
      type: Array,
      default: [],
    },
  },
}
</script>
```

## 解決法
defaultの部分を修正する！

```:sample.vue
<script>
export default {
  props: {
    〇〇: {
      type: Array,
      default: () => [],
    },
  },
}
</script>
```
【備忘録】WebAPIサーバを作るとはどういうことか

RailsとReactでSPA化を実装したいのですが、そもそもWebAPIサーバの意味が理解できていなかったため、記事に残しました。

SPAでは、最初のページにあたるHTMLのみをサーバから取得し、その後の画面の書き換え等をすべてクライアント側（ブラウザ内）のJavaScriptで実施する。
そのため、SPAのアプリケーションでは、サーバ側(Rails側)のアプリケーションの役割はいわゆるWebAPIとしてブラウザ側のJavaScriptとAjax通信を行うのみ、というケースも多い。

# API専用Railsアプリケーションの生成コマンド

```
$ rails new my_api --api
```

▼詳細はRailsガイドを参照

https://railsguides.jp/api_app.html



▼参考記事

https://www.transnet.ne.jp/2018/02/20/rails_webapi_colnk/

大変わかりやすかったです！
Rubyのオブジェクト指向について

# Rubyはオブジェクトでできている
Rubyはものを作る時に、
```『コンピューターに、こうやって作れ』と指示を出しながらサービスを作っていく言語```です。

そのような```Rubyはオブジェクトでできています。```
オブジェクトとは何かを一言で表現すうるのは難しいのですが、
```何かのクラスのインスタンス```です。
Rubyにはそれぞれ```インスタンス、メソッド、クラス```を持っています。
この3つをもとに説明して行きます。

# クラスとインスタンス
オブジェクト指向を理解するにはクラスとインスタンスの理解は必須です。

***クラスとは設計図***のことです。
***インスタンスは設計図をもとに作られた実体です。***

●家を例にします。

家の設計図がクラス。その設計図をもとに作られた家がインスタンスです。
設計図があればいろいろな家を作れますよね。
赤い色の家も作れますし、黄色い家も作れます。

設計図があれば同じような家をたくさん作れます。
もっといい性能の家を作りたければ、設計図を修正すれば
１つ１つの家を建て替えたりする必要はなくなり、毎回毎回性能のいい家に住めます。

このような考えをコードでも実践できます。

# オブジェクト指向の３大要素

***1クラス(カプセル化)***
```メソッドを定義```することにより```何をやっているのかをわかる```ようにします。
つまり***内部に何が入っているのかは意識せず、指示や命令を与える***ことができます。

***2ポリモーフィズム***
```同じ種類のものでもそれぞれ異なるものとして動く仕組みのことです。```
例えば人間で例えると
人間という生き物は共通しているけど、名前や性別、などみんなそれぞれ違いますよね。
こんな感じのイメージです。


***3継承***
***設計図をもとに同じような性能を持ったものを作ることです。***

例えば、
設計図が車だとすると、その車をもとに、
フェラーリやランボルギーニを作れます。
車に少し性能を加えたものを作ることができます。


# 最後に
説明が足りない部分もありましたが
一通りのことはまとめました。
大事な概念なのでいろいろ調べてみてください。

# オブジェクト指向の使い方
オブジェクト指向の使い方は３段階に別れます。

1 ***設計　***
2 ***作成***
3 ***使用***

それぞれ見ていきます。家を作るときに例えます。

1.***設計***
まず家を作るときに設計します。
そのイメージです。

```rb

class home  #クラス(設計図)
   def living  #仕様(メソッド)
          
  end #仕様(メソッド)

end  #クラス(設計図)
```

2.***作成***
設計図をもとに大工さん(newメソッド)が家(インスタンス）を作ります。

```rb
@home = Home.new
```
これがインスタンスの実態です。

3.***使用***
大工さんが作った家を使います。使う時は

1 ***.メソッド名***

2 ***インスタンスが入った変数.メソッド名***
 ***@home.door***

みたいなイメージです。


# 最後に
説明が足りない部分もありましたが、一通りのことはまとめました。
大事な概念なのでいろいろ調べてみてください。

# 参考資料

https://www.sejuku.net/blog/124336

https://pikawaka.com/ruby/class

https://qiita.com/Hashimoto-Noriaki/items/e94a27c3d5d40ba4d41c

https://qiita.com/shogo-1988/items/e749208c0733bbe025c0
Windows10 から Windows11にアップグレードする時、ATOKユーザは要注意

Windows(R)10 から Windows(R)11 にアップグレードした時に、ハマったので、要注意。

ATOKユーザで、普段ATOKを使っていたのだが、Windows(R)11 にアップグレードしたら、OS動作が異様に遅くなった。

何かのアプリケーションを起動した際に、数十秒待たされ、カーソルがウエイトカーソルでくるくるくるくる、Vistaかよ、という状況であった。

仕方がないので、とあるアプリケーションの動作確認をしていると、普通にテキストファイルを開くところで、メモ帳が開くのだが、フリーズするという事象に遭遇。

タスクマネージャで確認すると、ATOKファイルアクセスツールが遅くて、応答なしとなることが判明した。

ATOKサポートに確認すると、ATOKをバックアップツールでバックアップした後、アンインストールして、再起動、インストールして試してくださいということだった。

その通りにすると、Windows(R)11 は軽快に動作するようになった。

ATOK ユーザの方で、Windows(R)11アップグレードする方への参考となれば幸いです。
【perl】MiSeqの出力ファイル名からサンプル名を抽出するワンライナー

# 実行環境
Microsoft Windows [Version 10.0.19042.1237]
Windows Subsystem for Linux 2
Ubuntu 20.04.3 LTS
perl5 (revision 5 version 26 subversion 2)

# 例
```bash:処理
ls -1v | perl -lne 'if(/_R1/){print "$`"}'
```
```bash:対象データ
(base) usr@LIN:~/test$ ls -1v 
SampleName1_S1_L001_R1_001.fastq.gz
SampleName1_S1_L001_R2_001.fastq.gz
SampleName2_S2_L001_R1_001.fastq.gz
SampleName2_S2_L001_R2_001.fastq.gz
```
```bash:実行結果
(base) usr@LIN:~/test$ ls -1v | perl -lne 'if(/_R1/){print "$`"}'
SampleName1_S1_L001
SampleName2_S2_L001
```

# 解説

### perl の特殊変数[^1]
1. マッチした行全体：`$_`（省略可）
2. マッチした文字列：`$&`
3. マッチした部分より前の文字列：`` $` ``
4. マッチした部分より後の文字列：`$'`

`grep`だと行単位で前後の出力はできるが、行内だと難しい。
今回は 3 を使用。

### perl の条件分岐とパターンマッチ

`` 'if(/_R1/){print "$`"}' ``

「入力行にもし`_R1`が含まれていれば、`_R1`より前の文字列を出力する」という意味。

### その他
+ bash
`ls -1`：ディレクトリ一覧を縦に並べる
`ls -v`：ディレクトリ一覧を数字の昇順で並べる（100が2より後にくる）

+ perl
`-n`：一行ずつ読み込んで最終行まで処理する
`-l`：入力行から行末の改行を除去して、出力時に改行を付ける
`-e`：ワンライナーであることを宣言（オプションの中で最後に付ける）

# 正規表現を使った実用例
```bash:処理
ls -1v | perl -lne 'if(/_.*_.*_R1/){print "$`"}'
```
```bash:実行結果
(base) usr@LIN:~/test$ ls -1v | perl -lne 'if(/_.*_.*_R1/){print "$`"}'
SampleName1
SampleName2
```
### perlの正規表現[^2]
`.`：改行を除く任意の一文字
`*`：直前の文字が0個以上

# 備考
##### MiSeqの出力ファイル名（フォーマット）（＊イルミナHPから引用, 2021/10/09）
[Naming Convention](https://support.illumina.com/help/BaseSpace_OLH_009008/Content/Source/Informatics/BS/NamingConvention_FASTQ-files-swBS.htm)

>FASTQ files are named with the sample name and the sample number, which is a numeric assignment based on the order that the sample is listed in the sample sheet. For example: Data\Intensities\BaseCalls\SampleName_S1_L001_R1_001.fastq.gz<br>
>▶ **SampleName** —The sample name provided in the sample sheet. If a sample name is not provided, the file name includes the sample ID, which is a required field in the sample sheet and must be unique.
▶ **S1** —The sample number based on the order that samples are listed in the sample sheet starting with 1. In this example, S1 indicates that this sample is the first sample listed in the sample sheet.
　　NOTE
　　>Reads that cannot be assigned to any sample are written to a FASTQ file for sample number 0, and excluded from downstream analysis.
>▶ **L001** —The lane number.
▶ **R1** —The read. In this example, R1 means Read 1. For a paired-end run, there is at least one file with R2 in the file name for Read 2. When generated, index reads are I1 or I2.
▶ **001** —The last segment is always 001.
FASTQ files that do not follow this naming convention cannot be imported into BaseSpace.

### 参考サイト
[^1]: [Perlの特殊変数](https://perlzemi.com/blog/20161102147817.html)
[^2]: [Perlの正規表現をマスターしよう](https://perlzemi.com/blog/20100827127859.html)
AWSクラウドプラクティショナー-合格体験記

##はじめに
2021年10月にAWSクラウドプラクティショナーを受験し、無事に合格しました。
私自身クラウドに関する勉強を始めたばかりですので、同じようにこれから勉強を始めようとされている方の参考になれば幸いです。

##クラウドプラクティショナーとは
そもそもこの資格が一体何なのか、AWSの公式サイトでは以下のように説明されています。

>この認定は、AWS クラウドに関する基本的な知識とスキルをお持ちの方を対象としており、AWS クラウドについての総合的な理解ができていることを証明する基礎レベルの認定資格です。出題範囲には、AWS の主なサービスや料金、サポートに関する内容を含みます。技術者だけでなく、マネージメントやマーケティング等、AWS に関わるすべての方に理解いただきたい内容です。

AWSの11個ある試験の中で入門編の資格です。各種サービスの概要など基礎的な内容の試験のため、業務未経験者や非エンジニアの方などにも広く受験されています。今からクラウドの勉強を始める方にちょうど良いレベルだと思います。

##勉強教材
書籍
[AWS認定資格試験テキスト AWS認定 クラウドプラクティショナー(緑本)](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC-%E5%B1%B1%E4%B8%8B-%E5%85%89%E6%B4%8B/dp/4797397403)

模擬試験
[この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（7回分455問）](https://www.udemy.com/course/aws-4260/)

##学習内容
１週間で合格することを目標とし、短期に集中して学習しました。平日は約2時間、休日は約4時間勉強しました。

まずは参考書を読み基礎知識を習得しました(約4日間)。ここは時間をかけず、大体の理解で良いと思います。どんなサービスがあってそれぞれどんな役割を持つのか、要点のみを押さえて読み進めました。

参考書を軽く一周した後はUdemyの模擬試験をひたすら解きました(約3日間)。ここでどれだけ問題を解くがが合格に向けてのポイントだと思います。模擬試験で間違った問題は参考書で正解をしっかり確認し、理解を深めました。私は基本レベル①,②と応用レベル①,②をそれぞれで8割以上とれるまで繰り返し解きました。

##試験結果
合格ライン700点で、試験結果は720点とギリギリで合格することができました。
１週間の勉強期間でギリギリだったので、１ヶ月程度しっかり集中して勉強すれば、もっと余裕をもって合格できると思います。

体感的には実際の試験は模擬試験の基礎レベルよりも難しく、応用レベルより簡単という印象でした。模擬試験とほぼ同じような問題も多数出題されていました。

##まとめ
- クラウドプラクティショナーはAWS認定資格の入門編です。これから勉強を始める方にちょうど良いレベルだと思います。
- 基本的に模擬試験中心で勉強することが合格への近道です。正答率が8割以上になるよう繰り返し解くことをおすすめします。
YOLOv5をJetson Nano2G(4G)で動かして、物体を検知するから応用まで　その2

[YOLOv5をJetson Nano2G(4G)で動かして、物体を検知するから応用まで　その1]
(https://qiita.com/ShimoyamaAi/items/9b97f0888632fbc342ec)
の続きです

今回はOpenCV 4.5.1の導入です

###更新履歴
2021年10月　初版

##2.OpenCV導入

詳細は
[GitHub]
(https://qiita.com/ShimoyamaAi/items/9b97f0888632fbc342ec)
4時間程度はかかります

```
wget https://github.com/Qengineering/Install-OpenCV-Jetson-Nano/raw/main/OpenCV-4-5-1.sh
sudo chmod 755 ./OpenCV-4-5-1.sh
./OpenCV-4-5-1.sh
```
辛抱強く待ちましょう
その後不要なファイルを消します

```
rm OpenCV-4-5-1.sh
```
###JTOP起動し成功しているか確認します

```
jtop
```



このようにOpenCVの後ろにcompiled CUDA:YESを確認してください
![Screenshot from 2021-10-08 11-53-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2142883/6ac86867-dba1-52a5-4cdf-465d99fe72bf.png)

次回はPyTorch TorchVision の導入を行います

[YOLOv5をJetson Nano2G(4G)で動かして、物体を検知するから応用まで　その3]
(https://qiita.com/ShimoyamaAi/items/7e44d07bc4b98d7ee055)
Candy Rock Star ダンスアニメーションを変更する

##前編
過去記事でCandy　Rock　Starのモデル変更方法について書いた。
今回は、ダンスのアニメーションの変更方法を書いていく。

https://qiita.com/skuromaku/items/7106d07611331ba3c308

##やりたいこと
ダンスのアニメーションを変更したい。

##環境
unity version 2020.3.18f1

##ダンスアニメーションの変更
どうやら本編では利用されていないけどバックダンサー用に２つのアニメーションが用意されている。

#####UnityChan¥Animators¥McapC86を開く

![スクリーンショット 2021-10-09 22.59.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85010/d7505a27-7867-9f3e-6033-c2d965189b35.png)

#####003_NOT01_Finalのモーションをクリックする

![スクリーンショット 2021-10-09 22.59.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85010/591d1236-9ef5-5b41-9f72-a44f9e2f50f5.png)

#####赤枠のどちらかを選択する

![スクリーンショット 2021-10-09 23.00.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85010/f141ddbc-e0fe-cbf8-4b95-60e776ba4578.png)

##これで無事に踊れました！

https://www.youtube.com/watch?v=I-YYZQV3QAM

https://www.youtube.com/watch?v=RL8wgeEq3wk
Windows PowerShell コマンド

##前書き
どうもこんにちは、そこらへんのオフィスか作業部屋を徘徊しているサーバインフラエンジニアです。(´・ω・｀)

仕事柄PowerShellコマンドを使うので、備忘録として残そうかなと考えた次第です。
はい、さっそく列挙していきますね。

***



##よく使うコマンド集
絶賛更新中！！(´・ω・`)

###コマンド出力結果をテキストファイルとしてフォルダ配下に保存する。

```PowerShell:PowerShell
#コマンド[hostname]の出力結果を[C:\work\logs]フォルダ配下に[test.txt]として保存する。(追記保存)
hostname >> C:\work\logs\test.txt
```


###保存したテキストファイルを開く。


```PowerShell:PowerShell
#[C:\work\logs]フォルダ配下にある[test.txt]を開く
C:\work\logs\test.txt
```

###コンピューターの管理を開く。

```PowerShell:PowerShell
compmgmt.msc
```

###ローカルユーザーとグループのみを開く。


```PowerShell:PowerShell
lusrmgr.msc
```

###ADSI エディタを起動する。

```PowerShell:PowerShell
adsiedit.msc
```

###PowerShell のログの取り方！

https://qiita.com/Kacy-Infra-Minzoku/items/7f31a72c1d687bfa91a0


###ホスト名を確認する。

```PowerShell:PowerShell
hostname
```


###Windows Server の役割と機能の一覧を出力する。

```PowerShell:PowerShell
Get-Windows Feature | Format-Table -Autosize -Wrap
```

###コンピュータ名を取得する。

```PowerShell:PowerShell
$Env:COMPUTERNAME
```

###サービス一覧を取得する

```PowerShell:PowerShell
get-service | select-object displayname,name,status,starttype | Format-Table -AutoSize -Wrap
```

###IPアドレス情報を取得する。

```PowerShell:PowerShell
Get-NetIPAddress
```

###関連記事

https://qiita.com/Kacy-Infra-Minzoku/items/fc09de1c3ad8eeefce41

https://qiita.com/Kacy-Infra-Minzoku/items/2cad6544d0d61634e258

https://qiita.com/Kacy-Infra-Minzoku/items/72b8e72d03f8bf49a745


##あとがき
随時更新していくよ！
こんな書き方でいいのかな？(゜-゜)

コマンドの表示を「折り畳み式」にしようか「全開の状態」にしようかで迷ってます。
どちらがいいとかいったコメントいただけると恐縮です。m(_ _)m
Silverblue で grub2-install やるためには、EFI と BIOS と両パーティション要るのね

<code>
# grub2-install --target i386-pc /dev/sda
</code>
としたら、
<quote>
grub2-install: warning: ../grub-core/partmap/gpt.c:194:this GPT partition label contains no BIOS Boot Partition; embedding won't be possible.
</quote>
と出た。

EFI boot しかしないから要らないと思って作らなかったんだけど、
BIOS Boot パーティションも作っておかないとダメなのね。

<quote>
 1            2048          409600   199.0 MiB   EF00  EFI system partition
...
20          409601          411647   1023.5 KiB  EF02  BIOS boot partition
</quote>
Blackmagic DesignのMicro Converter BiDirectional SDI/HDMI 3Gが良かった話

久しぶりに記事を書きます。
今回は、前から気になっていたMicro Converter BiDirectional SDI/HDMI 3Gを購入したので、それについての話を書きたいと思います。
僕は、映像本職の人ではない一介の大学生なので、一部誤りがあるかもしれません。コメントで修正をいただけるとありがたいです。
この記事もどちらかというと、アマチュアなどで映像作品を展示したり、カメラでリアルタイムに何かをしたい人たち向けの記事になります。

本製品は以前から存在していたMicro Converter　SDI to HDMI 3G及びMicro Converter　HDMI to SDI 3Gのシリーズとして、2021年に発売された製品になります。
値段は65＄、日本で買うと大体1万弱ぐらいのようです。

## 本職じゃない人向けざっくり解説
HDMI: いつも使うやつ
SDI: 長く引き回したい時に使うやつ

ガチガチの映像やさんでもなければ基本的にHDMIしか使わないと思うんですが、ちょっと舞台後ろからカメラで撮りたいとか、プロジェクターを客席から打ちたいってなった時に、SDIが必要になってきます。SDIであれば、3Gでも100mほど伸ばせるので相当大きなホールとかでもない限り大丈夫でしょう。
こういう時に、僕らのような知識がない人々はAmazonとかで売っているLANケーブルでHDMIを延長できるエクステンダー（5000〜10000程度）に手を出しがちですが、あまりこれらの製品はおすすめできないです。大抵トラブルのもとになるイメージしかありません。（接続順にとても気を使う必要があったり、相性問題が非常に起きやすい）
僕らのようなアマチュアだと、基本的にはHDMIをSDIにして長くケーブルを引いて、HDMIに戻すというような使い方になると思います。
![Screen Shot 2021-10-09 at 22.43.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/73f7002e-47e5-d6ef-42c7-a2baae2b57ce.png)
客席のプロジェクターだったら、HDMIソースがPCでHDMIアウトプットがプロジェクターです。引きのカメラだったら、HDMIソースがカメラでHDMIアウトプットがキャプチャボードとかスイッチャーです。

## 使い方
これから出てくる図で、線が出てくるところの入出力は以下の図の通りです。
![Screen Shot 2021-10-09 at 22.14.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/097606f9-7772-11a0-81d4-68d2fd1d4151.png)

### SDI/HDMIのコンバーターとして（ループアウトあり）
もちろん、今までのSDI→HDMI、HDMI→SDIとしての機能をこの1台で賄うことができます。さらに、HDMIのループアウトもつきます（HDMI→SDIではSDIが2本出ていた）。SDIももちろんループアウトが出ます。

![Screen Shot 2021-10-09 at 22.15.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/654b648f-25f7-1ecd-905d-62a67ba2ebdd.png)
![Screen Shot 2021-10-09 at 22.15.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/46761768-b677-a9b7-7261-159189657529.png)

### SDI/HDMIのリピーター（延長）として
それぞれ引き伸ばせる最大の長さとしてHDMIは10m、SDIは現実的にHDで200、3Gで100m程度が目安かと思います。
それ以上伸ばしたい時にはリピーターが必要になりますが、本製品もSDIのリクロッカーやHDMIのフォーマッターが入っているのでリピーターとしての役割を果たすことができるということです。
![Screen Shot 2021-10-09 at 22.14.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/2d00a88e-cee6-3e5f-81c3-bb312d004c58.png)　![Screen Shot 2021-10-09 at 22.14.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/c59b9cd0-00bf-cc6f-7b4b-0f2d5199939a.png)

### SDI→HDMI、HDMI→SDIの同時使用
個人的にはこれができることにびっくりしたのですが、SDI→HDMIとHDMI→SDIを同時に1台で変換することができます。（世間的には当たり前なのかもしれない...)
これができると、遠くのカメラマンの映像を送るとともにマルチビューをカメラマンの手元に返してあげることなどが可能になりますね。
![Screen Shot 2021-10-09 at 22.49.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/e16bd194-5455-a98d-db7e-ca3dd2fe95b1.png)

## まとめ
貧民の我々アマチュアには、この機材は1台あるだけでかなり心強いと感じました。値段的にもものすごい高いわけでもないし、汎用性・耐用年数を考えても買って損はなさそうな製品かなと思います。
ただ、これらの製品は比較的レンタルが安いので、たくさん必要な時とかはレンタルするといいよと昔の自分だったら知りたかったので、ここに書いておきます。

にしてもこんだけの使い方があって1万弱ってのは安すぎる気がしますね。。。
Blackmagicさん流石すぎる...

これで手持ちのBMDちっこいのシリーズは4台になりました。これだけでもかなりのことができるようになったかなと思います。
![IMG_0333.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/19f92a7d-33ec-6d15-8fef-cf26a2f73215.jpeg)
flutter testでurl_launcherのメソッドが呼ばれたことを確認

# はじめに

flutter testでurl_launcherのメソッドが呼ばれたことを確認する方法です。
url_launcherで使用するメソッド(canLaunch, launch)がスタティックメソッドのため、単純にmockitoでmockにすることが出来なかったため、試行錯誤した最終のもとを記載します。


# 環境
- flutter: 2.5.2
- url_launcher: 6.0.11
- mockito: 5.0.16

# コード

```dart
// Package imports:
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';

// Project imports:
import 'sample_test.mocks.dart';

class SampleViewModel {
  Future<void> openUrl(String url) async {
    if (await canLaunch(url)) {
      await launch(url);
    }
  }
}

class FakeUrlLauncherPlatform extends Fake
    with MockPlatformInterfaceMixin
    implements UrlLauncherPlatform {}

@GenerateMocks([FakeUrlLauncherPlatform])
void main() {
  late MockFakeUrlLauncherPlatform mockUrlLauncherPlatform;

  setUp(() {
    mockUrlLauncherPlatform = MockFakeUrlLauncherPlatform();
    UrlLauncherPlatform.instance = mockUrlLauncherPlatform;
  });

  test('openUrl', () async {
    final viewModel = SampleViewModel();

    const url = 'https://example.com';

    when(mockUrlLauncherPlatform.canLaunch(url)).thenAnswer((_) async => true);
    when(mockUrlLauncherPlatform.launch(url,
        useSafariVC: true,
        useWebView: false,
        enableJavaScript: false,
        enableDomStorage: false,
        universalLinksOnly: false,
        headers: {})).thenAnswer((_) async => true);

    await viewModel.openUrl(url);

    verify(mockUrlLauncherPlatform.canLaunch(url));
    verify(mockUrlLauncherPlatform.launch(url,
        useSafariVC: true,
        useWebView: false,
        enableJavaScript: false,
        enableDomStorage: false,
        universalLinksOnly: false,
        headers: {}));
  });
}
```

## mockito

mockitoのmockやwhen, verifyについては、こちらを参照ください。
https://pub.dev/packages/mockito

## UrlLauncherPlatform.instance

url_launcherのメソッド(canLaunch, launch)は、UrlLauncherPlatform.instanceで取得したインスタンスのメソッドを実行しています。
そのため、それをmockに差し替えることでメソッドが呼ばれたことを確認できるようにしています。
https://github.com/flutter/plugins/blob/url_launcher-v6.0.12/packages/url_launcher/url_launcher/lib/url_launcher.dart

## FakeUrlLauncherPlatform

UrlLauncherPlatform.instanceに設定するインスタンスですが、UrlLauncherPlatformのままではPlatformInterface.verifyTokenでエラーとなるため使用できませんでした。
そのため、MockPlatformInterfaceMixinを使用したFakeクラスを作成し、そのmockを作成するようにしています。


https://github.com/flutter/plugins/blob/url_launcher_platform_interface-v2.0.4/packages/url_launcher/url_launcher_platform_interface/lib/url_launcher_platform_interface.dart#L37
https://github.com/flutter/plugins/blob/plugin_platform_interface-v2.0.2/packages/plugin_platform_interface/lib/plugin_platform_interface.dart


# まとめ

url_launcherのメソッドが呼ばれたことを確認することができました。
当初は、MethodChannelのinvokeMethodで確認する実装をしたのですが、もっと手前で確認する方法はないか調査して、このような方法となりました。
もっと簡単は方法などあれば、教えて下さい。
xmllint を使って、xmlをパースした

個人用メモっす。


## xmlintとは

shell scriptでxmlをパースしてくれる君。

## 使い方

自分が必要になった分だけメモる。

```sh
# linuxの場合
sudo apt update
sudo apt install libxml2-utils

# xmlを整形して表示
echo file.xml | xmllint --format -  

# 特定のpathのnodeを取得
xmllint --xpath "/testsuite/testcase/failure" tmp/test-results/rspec.xml                                                                                   
# 以下出力
# <failure message="RSpec::Core::MultipleExceptionError" type="RSpec::Core::MultipleExceptionError">
# </failure><failure message="RSpec::Core::MultipleExceptionError" type="RSpec::Core::MultipleExceptionError">
# </failure>                                                                                                                                                                                                                                                                                         

# そのnodeの特定の属性の値を取得する
xmllint --xpath "/testsuite/testcase/failure/@message"  tmp/test-results/rspec.xml
# 以下出力    
# message="RSpec::Core::MultipleExceptionError"

# このnodeの親nodeを取得する
xmllint --xpath "/testsuite/testcase/failure/parent::node()"  tmp/test-results/rspec.xml
# 以下出力
# <testcase classname="spec.features.post_articles_spec" name="Post Article Company post" file="./spec/features/post_articles_spec.rb" time="7.636209"><failure message="RSpec::Core::MultipleExceptionError" type="RSpec::Core::MultipleExceptionError">
# </failure></testcase><testcase classname="spec.features.post_articles_spec" name="Post Article User post" file="./spec/features/post_articles_spec.rb" time="1.935865"><failure message="RSpec::Core::MultipleExceptionError" type="RSpec::Core::MultipleExceptionError">
# </failure></testcase>

```

## Ref.

- 親nodeの取り方: https://chrome.hatenablog.jp/entry/2017/04/02/195139
F#のコードの中にSQLを書く時の便利プラグイン VSCode

下記のプラグインがとても便利

Highlight HTML/SQL templates in F#

https://marketplace.visualstudio.com/items?itemName=alfonsogarciacaro.vscode-template-fsharp-highlight&ssr=false#overview


こんな感じです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149269/3e7ccce0-812f-2d4e-58b9-841c904e7801.png)


コード例

```fsharp
open Microsoft.Data.Sqlite
open Dapper

let sql s =
  let sql (s:string) = s
  sql $"""

      /* ---------------------------------------------------

          SQL Highlight!!!  (^_^)/

          Highlight HTML/SQL templates in F#
          by @Alfonso Garcia-Caro(Great Man!)
      --------------------------------------------------- */

          select 'Hello!'
          union
          select 'World!'
          union
          select '{s}'

      ;
    """

[<EntryPoint>]
let main argv =
  let sqCon = new SqliteConnection("Data Source=memory")
  sqCon.Open()
  sqCon.Query(sql=sql("every one!")) |> Seq.iter(fun x -> printfn "%A" x)
  sqCon.Close()
  0 // return an integer exit code
```

現場からは以上です
Tweepyで 'API' object has no attribute 'search'

#エラー内容


https://tk-medical-news.com/twitter-autofavorite

今回はこちらの記事を参考にいいね自動化を行ったところ
``` 'API' object has no attribute 'search'```

というエラーが出ました。

#解決策
```
search_results=api.search(q=q,count=count) #countの数だけ検索結果を表示
```
のapi.searchをapi.search_tweetsに変更します。

```
search_results=api.search_tweets(q=q,count=count) #countの数だけ検索結果を表示
```

これで作動しました。
search_tweetsはタブ補完機能で見つけました。

#まとめ
公式のAPIメソッドについてはこちらの記事を参照してください。

https://docs.tweepy.org/en/stable/api.html

searchで見ると
```API.search_30_day()
API.search_full_archive()
```
などが目につきますが、こちらは有料版なので気をつけてください。
OpenSSHを8.8にしたら繋がらなくなった

OpenSSHのバージョンを8.8に上げたところ、特定のサーバーへの接続時に次のようなエラーが表示されるようになりました。

```
no matching host key type found.
```

調べてみると、古いプロトコルが廃止されるときによく表示されるメッセージのようです。

OpenSSHのリリースノートによると、8.8ではSHA-1ハッシュアルゴリズムを使うRSA署名が無効化されており、次のいずれかが対応策になりそうです。

# 対策1

サーバー側のOpenSSHのバージョンも 7.2 以降に上げる。

サーバー側のOpenSSHのバージョンが比較的新しい場合は、自動的にSHA-1以外のアルゴリズムが選択されるので、そもそもこの問題は発生しません。

# 対策2 (非推奨)

~/.ssh/config の設定で、無効化されたアルゴリズムを強制的に有効にする。

```
Host 接続に失敗するホスト
    HostkeyAlgorithms +ssh-rsa
    PubkeyAcceptedAlgorithms +ssh-rsa
```

サーバー側のOpenSSHのバージョンをすぐに変えられない場合は、一時的にこの対応をする必要がありそうです。

# 参考リンク

https://www.openssh.com/txt/release-8.8
USB Logic Analyzer 買ってみた

Thanks to:

https://qiita.com/infinite1oop/items/b18197f74864b908a556
https://lang-ship.com/blog/work/cypress-ez-usb-fx2lp/

# 購入
いわゆる互換品ですね。

HiLetgo 24MHz 8チャンネル USBロジックアナライザ 8CHロジックアナライザ UART IIC SPI デバッグ MCU FPGA ARMに対応 [並行輸入品]

というものです。

# セットアップ・確認

結構試行錯誤しましたが

https://sigrok.org/download/binary/pulseview/PulseView-0.4.2.dmg

で動きました。MojaveなMacです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/24b41ead-c552-6e36-df96-d1e44621562c.png)


# サンプリング

ここがキモですね。右 3MHz がサンプリング周波数。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/d735727a-afd9-2572-c570-32cca543defb.png)


# GPIOを見る

10msごとにToggleするピンを見てみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/4be75f39-9f5a-dced-8375-d054d6dce5b4.png)

拡大します。およそ10msecが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/7bc521a9-e730-6921-9384-37439f3eb80c.png)

さらに拡大します。TogglePinを実は3回実行しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/94f71242-4393-d6f4-acc0-0e858b3f0671.png)

# UARTを見る

うまく読めているようです。"a" "b" と送信しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/a48380d7-513c-cf40-dc56-5141ccb8024e.png)

# I2Cを見る

よくあるSSD1306の描画の時がサンプリングできました。ACKも認識しています。

I2C address は 0x78 ですが，0x3cと表示されています。Arduinoスタイルですね。(0x78>>1 == 0x3c)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/699f7c16-fa1f-7262-29a1-ef6820bcb455.png)

# 最後に

うーん，早く買えばよかった。

ポートの論理が簡単に見えるのは，小型CPU遊びにはすごくいいです。このぐらい自作しようと夢見てたこともありましたが，先人たちの努力はすごいです！ すごく楽しいです。
UITextField内に画像などを表示させる (.leftView、.rightView)

#今回の内容
<img width="150" alt="205FB713-620C-4939-B425-B8B65B86563C_1_105_c.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/9edd9f1c-d159-23a9-8a4f-8d0109388923.jpeg">

#コードと簡単解説

* `.leftViewMode`を`.always`で設定しているので常に`.leftView`が表示されます。（`.rightView`でも同様です）

* `.leftView`と`.rightView`は`UIView`を設定しなければなりませんが、`UIImageView`や`UISwitch`などの様に`UIView`が階層に含まれていれば設定できる様です。(全て調べられた訳では無いので設定出来ない場合もあるかも知れません)

```Swift:
import UIKit

class FirstActionViewController: UIViewController {
    
    @IBOutlet weak var textfield: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        textfield.leftViewMode = .always
        textfield.leftView = {() -> UIImageView in
            
            let imageView = UIImageView(frame: CGRect(x: textfield.frame.minX + 10, y: textfield.frame.minY, width: textfield.frame.height - 10, height: textfield.frame.height))
            imageView.image = UIImage(systemName: "lock.fill")
            imageView.tintColor = .systemRed
            
            return imageView
        }()
        

        //コードで作成したUITextField
        let textfield01 = UITextField()
        textfield01.frame = CGRect(x: view.frame.maxX / 10, y: view.frame.maxY / 6, width: view.frame.width - (view.frame.maxX / 5), height: 50)
        textfield01.placeholder = "UITextField01"
        textfield01.layer.cornerRadius = 10.0
        textfield01.layer.borderWidth = 1.0
        textfield01.leftView = {() -> UIImageView in
            
            let imageView = UIImageView(frame: CGRect(x: textfield01.frame.minX, y: textfield01.frame.minY, width: textfield01.frame.height, height: textfield01.frame.height))
            imageView.image = UIImage(systemName: "lock.fill")
            imageView.tintColor = .systemRed
            
            return imageView
         }()
        
        textfield01.rightViewMode = .always
        textfield01.rightView = UISwitch()
        textfield01.leftViewMode = .always
        textfield01.layer.borderColor = UIColor.black.cgColor
        textfield01.backgroundColor = .white
        view.addSubview(textfield01)   
    }
       
}
```

# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
Power Automate: Yammer 用のカスタムコネクターの作成 #1

# なぜ？

Yammer の メンバー一覧を取得したいという要望があったけど、Actions が無かったので。
ただ、カスタムコネクターは自社ではまだ使えない・・ので、PoC どまりですが・・😅

# カスタムコネクターの作成
とりあえず、簡単な Users 一覧から作成してます。

メンバー一覧取得 Action を知りたい場合は以下

https://qiita.com/baku2san/items/889b586963adf8868da3

## ブランクから作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/40f1519f-1556-1162-8216-b3352d095dfb.png)
## 名前を付ける
```text:Connector_Name
YammerRestAPIs
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/fc2684f4-4565-5f0c-4005-e0519afd0ea5.png)
## General タブ
```url:Host
www.yammer.com
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/9cfb89c0-46ae-1370-1932-ed66810fefa8.png)

## Security タブ
OAuth 2.0 を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e7987045-231a-6951-ac3b-8dc041f3f88f.png)
### Client ID/ Client Name を取得

1. [ClientApplication](https://www.yammer.com/client_applications) へアクセス
1. アプリ登録<br>
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/741fa8ef-f3c5-b8ad-7de8-f6f42c2bc5d4.png)
1. Client ID/Secret をコピー<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/2fcc870c-94c8-9659-06f8-0a3d9cb0e295.png)

### Security タブへの記入
取得した ID/Secret を貼り付けて、Create Connector をしておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/9e6f1e95-edcc-555e-0cc9-807940ddcb8f.png)

```url:RedirectURL
https://global.consent.azure-apim.net/redirect
```

## Definition タブで使う API とか定義
1. New Action で Action 追加
1. 以下記入し、[Import from sample] から生成
    1. Summary: Automateで表示される名称
    1. Description: ↑の説明
    1. Operation ID: Unique ID<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/727c517c-2b4d-036f-e525-90c3019b5179.png)
1. Update Connectorで更新しておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/34607433-8d43-470a-2c67-b117a30ba7e1.png)

```url:GetUsers
https://www.yammer.com/api/v1/users.json
```

## Test タブ
1. New Connection で利用可能にして
1. Test Operation で動作確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/ea84445b-103f-262b-33b1-db68b43e4f92.png)

# 後は使うだけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/35ea41f9-b2d1-85d5-ac81-6e60b1b79d1d.png)

# Yammer Rest API

https://docs.microsoft.com/en-us/rest/api/yammer/rest-api-rate-limits

以下から↑に移動してそうです
~~https://developer.yammer.com/docs/~~

# あとがき

次回は、もともとの目的であった Group Members を作ろう

# keyword

how to create custom connector with Yammer Rest API

https://docs.microsoft.com/ja-jp/connectors/custom-connectors/define-blank
Pythonで空白(半角/全角)、スペース、タブを削除する方法

## はじめに

ユーザーに名前の入力を促すと、どうしても半角スペースや全角スペースが名前の間に入ってくることがあります。
`例）理想：田中太郎　現実：田中　太郎`

こちら側で設定できる場合には強制すればいいのですが、手元にあるデータだとそうもいきません。

そこで、今回はPythonを用いて空白文字を削除する方法を紹介したいと思います。

## 環境
macOS Big Sur バージョン11.5.2
python 3.7.10

## サンプルデータ
タブ、全角半角スペース、入力前の謎のスペース色々なパターンの入力を想定してみました。

```Python
sample_list = ["山本 大地", "坂本  卓郎", "鈴木　美奈子", "　高田栄作", "国枝  正樹"]

# 結果
['山本 大地', '坂本  卓郎', '鈴木\u3000美奈子', '\u3000高田栄作', '国枝  正樹']
```
（サンプルデータの人名は実在の人物とは関係ありません。）

## split()で空白(半角/全角)、スペース、タブを削除する

まず思いつくのが組み込み関数`str.split()`を使うことです。

```Python
[''.join(name.split()) for name in sample_list]

#　結果
['山本大地', '坂本卓郎', '鈴木美奈子', '高田栄作', '国枝正樹']
```

split()で区切り文字無しで分割した後にjoinでくっつけるということを行なっています。


## 正規表現の利用して空白(半角/全角)、スペース、タブを削除する

正規表現であれば他の言語でも似たような動作をすると思うのでこちらも紹介しておきます。
`re`モジュールを利用します。

```Python
import re

[re.sub("[\u3000 \t]", "", name) for name in sample_list]

# 結果
['山本大地', '坂本卓郎', '鈴木美奈子', '高田栄作', '国枝正樹']
```

## replace()を利用して空白(半角/全角)、スペース、タブを削除する
最初検索した時に見つけたページを参考に書いたものです。
こちらは`str.replace()`を利用しております。求めていた処理はできるのですが、上記と比べるとかなりみっともない出来ですので、上のものをご利用ください。

```Python
import pandas as pd
result_list = pd.Series(sample_list).str.replace("[\u3000 \t]", "", regex=True)
list(result_list)

# 結果
['山本大地', '坂本卓郎', '鈴木美奈子', '高田栄作', '国枝正樹']
```

## 最後に
Pythonで空白(半角/全角)、スペース、タブを削除する方法を紹介しました。

自動化する際には、スペースなどが人によって違いがあるとかなり手こずることも多いと思うので、こういった地味な処理も大事にしていきたいです。


この記事は以下の情報を参考にして執筆しました。

https://pandas-docs.github.io/pandas-docs-travis/reference/api/pandas.DataFrame.replace.html

https://note.nkmk.me/python-str-replace-translate-re-sub/

https://docs.python.org/ja/3/library/stdtypes.html?highlight=split#text-sequence-type-str
【MySQL】カラム作成時によく使う項目（初心者向け）

#はじめに
MySQLでテーブルを作成しカラムを追加していく際に、よく使う項目について見ていきます。

#項目
##Name
カラム名を入力します。

##Type
カラムのデータ型を指定します。
・`INT`：整数
・`BIGINT`：整数（数字がかなり膨大になりそうなとき）
・`BOOLEAN`：真偽値（1か0か）
・`VARCHAR`：文字列（こっちを使うことが多い）
・`TEXT`：文字列（検索ができる）
・`DATETIME`：timezoneが加味されない
・`TIMESTAMP`：timezoneが加味される
・`ENUM`：選択肢をあらかじめ作成

##Length/Values
長さ・桁を指定します。
`ENUM`のリストはここに入力します。

##Default
カラムの初期値を指定します。
`created_at`の場合、`CURRENT_TIMESTAMP`を選択します。

##Collation
言語のフォーマットを指定します。
指定する場合は、`utf8_unicode_520_ci`を指定することが多いです。

##Attributes
属性を指定します。
・`UNSIGNED`：マイナスの値を含まない
・`on update CURRENT_TIMESTAMP`：更新したときにタイムスタンプが入る（`updated_at`にはこれをつける）

##Null（=Nullable）
チェックしなかったら必須項目になります。

##index
・`PRIMARY`
このテーブルの中でレコードを特定するための1番重要なカラムにこれを設定します。1カラムにしかつけることができません。よく設定するのは`ID`で、このカラム内での重複は許されません。
・`UNIQUE`
動き自体はPRIMARYと似ていて、カラム内での重複が許されないものに設定します。PRIMARYと違うのは、グループでも指定できるという点で、複数のカラムをグループとしてUNIQUEを指定すると、その中のカラムが1つでも一致していなかったらデータを入れることができるが、全部一致していたらはじかれることになります。
・`INDEX`
これを指定したカラム用にメモリを割り当てることができ、検索のスピードが速くなるため、よく条件で使われるようなカラムに指定します。しかし、指定しすぎるとメモリに負荷がかかるため、注意が必要です。
・`FULLTEXT`
データ型で`TEXT`をしていた場合に、これを指定することで検索ができるようになります。

##AI（=Auto Increment）
数字を1個ずつ自動的に増やしてくれるので、IDによくつけます。
Insert時にエラーが発生するとそれも1とカウントされてしまうので、エラーを修正して再度Insertしても、IDが1つ飛ばされた状態で増えていくことになります。

##Comments
このカラムに対するコメントを記述するところで、日本語でも書くことができます。

#おわりに
`save`をクリックすると、無事カラム作成完了です。
hello! world! on WPF console

# Summary

Hello! World! on WPF console

## like this

A. hello world text file

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149269/8e338289-fb46-0792-6d34-d10c6682e4b9.png)


B. fs proj

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149269/0604a221-d25d-5cac-b33e-2377999abe71.png)


C. fsharp code

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149269/17492714-c6d4-c194-0c9d-75a2dbc7f9a4.png)


Have fun!
【Flutter】子Widgetの再描画が動かない

bottomNavigationBarを使っている画面で、画面再描画がうまく機能しなかった件の対応方法です。

##元の状態

親ページはbottomNavigationBarでの画面切り替えを行っており、bodyを_pageListで切り替えています。

```
  List<Widget> _pageList = [];
  @override
  void initState() {
    super.initState();
   _pageList = [
      PageA(),
      PageB(),
      PageC()
    ];
  }
```

この状態でPageB()で表示しているDBを親ページ側で更新します。
そこでsetState()しても親ページの再描画は行われますが、子WidgetのPageBは再描画されません。

##対応方法

StatefulWidgetのKeyを使います。こういう使い方ができるんですね。
まだ良くわかっていませんが、今回はGlobalKeyを使いました。

まず子Widgetの方。Keyを受け取ります。

```
class PageB extends StatefulWidget {
  PageB({Key? key}) : super(key: key);

  @override
  _PageBState createState() => _PageBState();
}

```

親ページ。GlobalKeyを作成します。

```
 GlobalKey _key = GlobalKey<State<PageB>>();
```

_keyを引数で渡します。

```
   _pageList = [
      CampListPage(),
      MyGearListPage(key: _key),
      SettingPage()
    ];
```

子WidgetのsetState()を実行

```
_key.currentState?.setState(() {});
```

これで子Widgetが再描画されました。
指定月数後の日付をkintoneの標準機能で計算する

#指定月数後の日付を計算
kintoneでは、指定月数後の日付を求める関数がありません(2021年10月現在)。
下記の手順で、指定月数後の日付をkintoneの標準機能で求めることができます。

ただし、ここでは計算フィールドで変換しているため、リマインダー通知の基準日など、日付・日時フィールドであることが必要な機能に利用することはできません。日付・日時フィールドに計算結果を入力するには、JavaScriptカスタマイズやプラグインなどが必要です。

##例1
日付 : 2021年10月9日
月数 : 24
↓
月数後の日付 : 2023年10月9日

##例2
ただし、求められた日付が月末日を超えている場合は、翌月の1日とします。
日付 : 2021年1月31日
月数 : 1
↓
月数後の日付 : 2021年3月1日

##参考
[年と月と日をkintoneの標準機能で日付に変換する](https://qiita.com/t0ru/items/68fe31d1f73a88eacfc3 "年と月と日をkintoneの標準機能で日付に変換する")

#考え方
##1.日付を年と月と日に分ける
計算しやすくするために、DATE_FORMAT関数で年、月、日を求めます。
・日付の年 : DATE_FORMAT(日付,"yyyy","Etc/GMT")
・日付の月 : DATE_FORMAT(日付,"M","Etc/GMT")
・日 : DATE_FORMAT(日付,"d","Etc/GMT")

##2.年と月を加算
入力された月数を年数と分けて、入力された年と月に加えます。
・年数 : ROUNDDOWN((日付の月-1+月数)/12)
・年 : 日付の年+年数
・月 : 日付の月+月数-年数*12

##3.年をUNIX日付に変換
kintoneでは1970年1月1日からの秒数で日付を扱う(UNIX日付)ため、1970との年数の差を秒単位で足します。4年に1度のうるう年も考慮します。1900年以降なら下記の計算で対応できます。
その年 : ((年-1970)*365+ROUNDDOWN((年-1968)/4))*24*60*60

##4.月をUNIX日付に変換
上記で求めた年に、月を秒単位で足します。1月の場合は、足す必要がないため、月から1を引きます。
その月 : その年+(月-1)*31*24*60*60

##5.日をUNIX日付に変換
その月に日を加えて結果日付を求めます。
その月の日 : DATE_FORMAT(その月,"d","Etc/GMT")
その月の1日 : その月-(その月の日-1)*24*60*60
結果日付 : その月の1日+(日-1)*24*60*60

##6.月末の扱い
結果日付が月末を超えている場合に翌月の1日とします。
結果日 : DATE_FORMAT(結果日付,"d","Etc/GMT")
月数後の日付 : IF(日>結果日,結果日付-(結果日-1)*24*60*60,結果日付)

#kintoneのアプリ
※フィールドコードはフィールド名と同じにします。

##完成イメージ
![指定月数後の日付を計算.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152073/636d3bca-06f5-7fc2-4c8d-f16a81b6fb3a.gif)

##入力
・日付［日付フィールド］
・月数［数値フィールド］

##計算用
・日付の年 [計算フィールド]
　計算式 : `DATE_FORMAT(日付,"yyyy","Etc/GMT")`
　表示形式 : 数値

・日付の月 [計算フィールド]
　計算式 : `DATE_FORMAT(日付,"M","Etc/GMT")`
　表示形式 : 数値

・日 [計算フィールド]
　計算式 : `DATE_FORMAT(日付,"d","Etc/GMT")`
　表示形式 : 数値

・年数 [計算フィールド]
　計算式 : `ROUNDDOWN((日付の月-1+月数)/12)`
　表示形式 : 数値

・年 [計算フィールド]
　計算式 : `日付の年+年数`
　表示形式 : 数値

・月 [計算フィールド]
　計算式 : `日付の月+月数-年数*12`
　表示形式 : 数値
　
・その年［計算フィールド］
　計算式 : `((年-1970)*365+ROUNDDOWN((年-1968)/4))*24*60*60`
　表示形式 : 日付

・その月［計算フィールド］
　計算式 : `その年+(月-1)*31*24*60*60`
　表示形式 : 日付

・その月の日 [計算フィールド]
　計算式 : `DATE_FORMAT(その月,"d","Etc/GMT")`
　表示形式 : 数値

・その月の1日 [計算フィールド]
　計算式 : `その月-(その月の日-1)*24*60*60`
　表示形式 : 日付

・結果日付 [計算フィールド]
　計算式 : `その月の1日+(日-1)*24*60*60`
　表示形式 : 日付

・結果日 [計算フィールド]
　計算式 : `DATE_FORMAT(結果日付,"d","Etc/GMT")`
　表示形式 : 数値

##指定月数後の日付
・月数後の日付 [計算フィールド]
　計算式 : `IF(日>結果日,結果日付-(結果日-1)*24*60*60,結果日付)`
　表示形式 : 日付
f.select選択時に、jQueryを利用して、動的にフォーム要素を表示・非表示させる

#はじめに
プルダウンの選択した種類によってフォームの表示を変更して行きます。

##記述変更箇所
application.scss
view
application.js

##scss
```
.time{ display: none; }
```

##view
```html
<%= f.text_area :sentence %>
    <select name="task[category]" id="task_category">
      <option value="">選択してください</option>
      <option value="時間が決まったタスク">時間が決まったタスク</option>
      <option value="よく使うタスク">よく使うタスク</option>
      <option value="たまたま行ったタスク">たまたま行ったタスク</option>
      <option value="ToDo">ToDo</option>
    </select>
//f.selectをやめデベロッパーからhtmlをコピペ
    <%= f.time_field :time, class: "time" %>
    <%= f.submit %>
```


##application.js

```Javascript
document.addEventListener('DOMContentLoaded', (event) => {
//処理が適用されなかったため追加
  $( "#task_category" ).change(function() {
//select_idを取得しハンドラーで適用
    if (this.value == "時間が決まったタスク"){
//this.valueで#task_categoryのvalueを取得
      $("#task_time").removeClass( "time" );
//idをデベロッパーで確認しremoveClassでcssを削除
    }else{
      $("#task_time").addClass( "time" );
//addClassでcssを追加
    }
  });
});
```
さくらのレンタルサーバーに接続する方法（超初心者向け）

#前準備
・さくらのレンタルサーバーをレンタルする。
・契約後に届くメールから接続情報を確認する。
　※私の場合は"[さくらのレンタルサーバ] 仮登録完了のお知らせ"というメールに書かれてありました。
・Vimの初歩的な操作の理解（編集、保存、閉じる操作ができる程度）

````:メール
    《 契約サービスの接続情報 》
     FTPサーバ名   ： hoge.sakura.ne.jp
     FTPアカウント   ： hoge
     FTP初期フォルダ ： www
     サーバパスワード　　： fuga
````

#本題
ログイン方法はいくつかあるがここでは下記の３つの方法を紹介する。
　・「FTPアカウント名」＋「FTPサーバー名」＋「サーバーパスワード」　を使ってログイン
　・「FTPアカウント名」＋「FTPサーバー名」を使ってログイン
　・「FTPアカウント名」を使ってログイン


###１．「FTPアカウント名」＋「FTPサーバー名」＋「サーバーパスワード」　を使ってログインする
(1)ターミナルで下記コマンドを実行

````:ローカルマシン
#ssh [FTPアカウント名]@[FTPサーバー名]を実行する
ssh hoge@hoge.sakura.ne.jp
````

(2)実行するとパスワードの入力を求められるため、サーバパスワードを入力する

````:ローカルマシン
#passwordを入力を求められる
hoge@hoge.sakura.ne.jp's password:
fuga
````

**Welcome to FreeBSD!と表示されたらログイン成功です。**

###2.「FTPアカウント名」＋「FTPサーバー名」を使ってログインする方法
毎回、サーバーパスワードを入力するのは面倒なので入力を不要にします。

(1)SSHキーの公開鍵をコピーする

````:ローカルマシン
#公開鍵を確認する
cat ~/.ssh/id_rsa.pub
 ssh-rsa AAAB3Nz.............  #表示されたものをコピーする

````

(2)home/hoge/.sshの中に[authorized_keys]を作る

````:さくらのレンタルサーバー
#さくらのレンタルサーバーにログインする

#home/hoge/.sshへ移動する
cd .ssh

#.sshの中にauthorized_keysを作成する
vim authorized_keys
````

(3)authorized_keysの中にSSH鍵の公開鍵を貼り付ける。


(4)authorized_keysのアクセス権限の変更
authorized_keysに不要な権限を付与しているとSSHに失敗するため、権限(パーミッション)の変更を行います。

````:home/hoge/.ssh
#authorized_keysのアクセス権限を確認する
% ll
total 4
-rw-r--r--  1 hoge  users  580 Oct  9 17:20 authorized_keys
````

**パーミッションの見方についてちょっと説明**
>[-rw-r--r--]の部分がパーミッションになります。
わかりやすいように4つに分けて説明します。
-/rw-/-r-/-r-
1つ目の区切り：ファイルタイプ（ - : ファイル , d : ディレクトリ）
２つ目の区切り：root(hoge）に与えられた権限
３つ目の区切り：usersに与えられた権限
４つ目の区切り：その他のユーザーに与えられた権限

今回は、authorized_keysの権限を
rootのみ読み書き可能とし、それ以外のユーザーには権限を与えないように設定を変更します。

もっと詳しい説明については「[こちらの記事][chmod]」に書いてあります。
[chmod]:https://qiita.com/shisama/items/5f4c4fa768642aad9e06」

````
#変更前の権限を確認する
% ll
total 4
-rw-r--r--  1 hoge  users  580 Oct  9 17:20 authorized_keys

#chmod <モード> <対象ファイル名> でパーミッションを変更する
% chmod 600 authorized_keys

#変更後の権限を確認する
% ll
total 4
-rw-------  1 hoge  users  580 Oct  9 17:20 authorized_keys

% exit
````

(5)ログインできるか確認

````:ローカルマシン
#ssh [FTPアカウント名]@[FTPサーバー名]を実行する
ssh hoge@hoge.sakura.ne.jp
````

**パスワードの入力を求められることなく、Welcome to FreeBSD!と表示されたらログイン成功です。**



###3.[FTPアカウント名]、[FTPサーバー名]を入力せずにログインする方法
毎回[FTPアカウント名]、[FTPサーバー名]を入力するのは面倒なのでさらに簡単にログインできるようにします。

(1)ローカルに[.ssh/config]を作る。

(2)configの中にログイン情報を書き込む

````:ローカルマシン/.ssh/config
Host piyo   #なんでもいい
HostName hoge.sakura.ne.jp
User hoge
Port 22   #SSH接続のPort番号
````

(3)ログインできるか確認

````:ローカルマシン
#ssd piyo(さっきconfigに記載したもの)を実行する
ssh piyo
````

**Welcome to FreeBSD!と表示されたらログイン成功です。**
年と月と日をkintoneの標準機能で日付に変換する

#年と月と日を日付に変換
kintoneでは、分かれて入力された「年」と「月」と「日」を1つのフィールドにまとめて、日付形式で表示するための関数がありません(2021年10月現在)。
下記の手順で、年と月と日をkintoneの標準機能で日付形式に変換することができます。

ただし、ここでは計算フィールドで変換しているため、リマインダー通知の基準日など、日付・日時フィールドであることが必要な機能に利用することはできません。日付・日時フィールドに計算結果を入力するには、JavaScriptカスタマイズやプラグインなどが必要です。

##例1
年 : 2021
月 : 10
日 : 9
↓
日付 : 2021-10-9

##例2
ただし、月に2、日に31などが入力されて、月末日を超えている場合は、翌月の1日とします。
年 : 2021
月 : 2
日 : 31
↓
日付 : 2021-3-1

##参考
[1か月後の日付をkintoneの標準機能で計算](https://qiita.com/t0ru/items/1c4273b122c070edbfc6 "1か月後の日付をkintoneの標準機能で計算")
[指定月数後の日付をkintoneの標準機能で計算する](https://qiita.com/t0ru/items/4874ad6dff60020b346c "指定月数後の日付をkintoneの標準機能で計算する")

#考え方
##1.年の扱い
kintoneでは1970年1月1日からの秒数で日付を扱う(UNIX日付)ため、1970との年数の差を秒単位で足します。4年に1度のうるう年も考慮します。1900年以降なら下記の計算で対応できます。
その年 : ((年-1970)*365+ROUNDDOWN((年-1968)/4))*24*60*60

##2.月の扱い
上記で求めた年に、月を秒単位で足します。1月の場合は、足す必要がないため、月から1を引きます。
その月 : その年+(月-1)*31*24*60*60

##3.日の扱い
その月に日を加えて結果日付を求めます。
その月の日 : DATE_FORMAT(その月,"d","Etc/GMT")
その月の1日 : その月-(その月の日-1)*24*60*60
結果日付 : その月の1日+(日-1)*24*60*60

##4.月末の扱い
結果日付が月末を超えている場合に翌月の1日とします。
結果日 : DATE_FORMAT(結果日付,"d","Etc/GMT")
日付 : IF(日>結果日,結果日付-(結果日-1)*24*60*60,結果日付)

#kintoneのアプリ
※フィールドコードはフィールド名と同じにします。

##完成イメージ
![年と月と日を日付に変換.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152073/50e456ba-520b-83d6-1e41-a695da931a25.gif)

##入力
・年［数値フィールド］（1900～）
・月［数値フィールド］（1～12）
・日［数値フィールド］（1～31）

##計算用
・その年［計算フィールド］
　計算式 : `((年-1970)*365+ROUNDDOWN((年-1968)/4))*24*60*60`
　表示形式 : 日付

・その月［計算フィールド］
　計算式 : `その年+(月-1)*31*24*60*60`
　表示形式 : 日付

・その月の日 [計算フィールド]
　計算式 : `DATE_FORMAT(その月,"d","Etc/GMT")`
　表示形式 : 数値

・その月の1日 [計算フィールド]
　計算式 : `その月-(その月の日-1)*24*60*60`
　表示形式 : 日付

・結果日付 [計算フィールド]
　計算式 : `その月の1日+(日-1)*24*60*60`
　表示形式 : 日付

・結果日 [計算フィールド]
　計算式 : `DATE_FORMAT(結果日付,"d","Etc/GMT")`
　表示形式 : 数値

##変換された日付
・日付 [計算フィールド]
　計算式 : `IF(日>結果日,結果日付-(結果日-1)*24*60*60,結果日付)`
　表示形式 : 日付
【一発合格】AWS認定ソリューションアーキテクトアソシエイト合格までにしたこと

## はじめに

AWS認定ソリューションアーキテクトアソシエイト試験に一発で合格することができました。

学習に使った教材や記事などをまとめてみました。
ほとんどUdemyの講座ですが。

試験概要は[こちら](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/)の公式サイトからどうぞ。
受験を考えている方は[試験ガイド](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Exam-Guide.pdf)を読んでおくと良いと思います。
こちらの前にクラウドプラクティショナー試験を取得してから受験しています。その学習方法は[こちら](https://qiita.com/tukky/items/b06da92c4ae63fed493b)。

## 合格までにしたこと &  学習時間

- 学習期間  
  - 2021年8月1日 ~ 2021年10月8日
- 学習時間  
  - 1日 1~3時間
- 学習内容
  - [Udemy試験突破講座](#udemy試験突破講座) 2周（2倍速）
  - [Udemy模擬試験問題集](#udemy模擬試験問題集) 4周
  - [Udemy短期突破講座](#udemy短期突破講座) 3周（2倍速）
  - [その他](#その他)


## 学習のポイント
- 分からない内容や問題はとりあえず言葉や答えだけ覚えてとにかく先へ進む
- 毎日学習する
- 間違えた問題はその日すぐに復習する

Udemyのいいところは、**スマホアプリで講座をダウンロードできる**ところにあります。
ダウンロードしておけば、スマホで通勤中などにも学習できてよいです。
いろんな教材に手をつけずに、とにかくUdemyの教材をひたすらやり続けることが結果的に良かったかなと思っています。

クラウドプラクティナーに比べたらAWSサービスの範囲は狭いですが、深く学習する必要がありました。
覚える問題に加え、考える問題も増えた印象です。


## Udemy試験突破講座
こちらの講座を購入しました。
実際に手を動かしながら、楽しく学ぶことができます。
講座を購入すると、**講座で使用しているスライドをすべてPDFでダウンロードすることができる**ため、空き時間の学習にも困りません。
[これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）](https://www.udemy.com/course/aws-associate/)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630487/65dfb357-41f6-4c3e-761a-4255b06df201.png" width="800">


## Udemy模擬試験問題集
こちらの模試を購入しました。
直前の1ヶ月は毎日模試の問題を解き続けました。
最初は点数50%くらいしか取れませんでしたが、最終的には6回とも正答率80-90%くらいになっていました。（答えを覚えてしまっている感は否めませんでしたが…）
[【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）]
(https://www.udemy.com/course/aws-knan/)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630487/51a307d4-ffe5-bb8a-ded0-234bbd072b3e.png" width="800">


## Udemy短期突破講座
試験2週間前に購入しました。
ハンズオンなしで、完全に試験対策に特化した講座です。
模擬試験問題集よりも全体的に難易度が高かったため、これを実施することで自信がつきました。本番で出題された問題を考えると点数も上乗せされたと感じます。
総復習という意味でも知識を定着させるために役立ちました。
[AWS認定ソリューションアーキテクト アソシエイト試験：短期突破講座（300問の演習問題）](https://www.udemy.com/course/aws-uoyc/)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630487/61092e99-bde1-b539-3daf-d638ecba9a1b.png" width="800">


## その他
その他学習に使用した教材です。

- [AWS認定試験【ソリューションアーキテクトアソシエイト試験対策】](https://www.youtube.com/playlist?list=PL2nCE2iR-lplkSsCoKuixZB4dNlFoHjEW)
YouTube無料で100問以上の問題と、その解説が視聴できるためスキマ時間にちょうどよいです。

- [CloudTech](https://aws-cloud-tech.com/)
有料AWS学習オンラインスクールですが、無料会員登録するだけで200問の問題を無料で解くことができます。


## おわりに
自分は学習にNotionというツールを使用してまとめていました。
お気に入りのツールを使用して学習すると、モチベーション維持にいいんですよね。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630487/69e3edaf-49a2-3d45-0d5f-03d45b2722cc.png" width="800">

資格を取ったから仕事ができるようになるというわけではないとは思いますが、「知識の証明」だけでなく「意欲の証明」にもなるし、職場の士気も上がることを考えると学習が苦でないなら取っておいて損はないと自分は思いました。

受験を考えている方の参考になれば幸いです。
カーネルについて


## カーネルについて

LinuxはOSの名前であるが、厳密に言えばカーネルの名前となる。カーネルとは文字通りOSの核となるファイルの事で、各種コマンドは、カーネルを通して実行される。

コマンドが動く仕組みだが、コマンドがカーネルに対し実行して欲しい処理を依頼して、カーネルに実行してもらうことになる。カーネルは実行結果をコマンドに返して、コマンドはあたかも自分が実行したかように結果を表示する。このようにバックでカーネルが処理を実行しているのだ。コマンドがカーネルに処理を依頼することを、**システムコール**と呼ぶ。

Linuxカーネルのファイルはどこに保存されているのかといえば、**/boot**の中の**vmlinuz**というファイル名で保存されている。**ls -l**をしてvmlinuzファイルを見てみると、**vmlinuz5.4.0.80-genericのシンボリックリンク**となっている。大元のvmlinuz5.4.0.80-genericファイルも、vmlinuzがある同じディレクトリ配下に存在している。

また、同一ディレクトリ配下に、**vmlinuz.old**という名のファイルも存在している。このファイルもまた、vmlinuz5.4.0.80-genericのリンボリックリンクとなっている。oldという拡張子がついてるということは、恐らく、vmlinuzのバックアップリンクの役割だと思われる。カーネルファイルが壊れた場合、このoldファイルをリネームして、拡張子を取れば復旧できるようになっているものと思われる。

vmlinuzだが、拡張子はついていないが、**fileコマンド**で詳細を表示してみると、**bziImage**という形式のイメージファイルであることが確認できる。OSを起動したときに、**ブートローダー**がこのvmlinuzファイルを、メモリ上にロードすることでOSは起動される。そしてブートローダーを起動するのは、マザーボード上に組み込まれている、**BIOS**もしくは**UEFI**というファームウェア。カーネルがロードされるメモリ空間のことを**カーネル空間**と呼ぶ。また、vmlinuzの後についている5.4.0.80-genericは、カーネルのバージョンを指している。

**ls -lh**で、vmlinuzの容量を確認してみると、**12M**であることが分かる。重要なファイルである割には、随分と軽いファイルになっている。実は軽い方がOSの起動が短時間で済むため、あえて軽くしているのだ。カーネルファイルを軽くできる理由は、本来、カーネルに含まれていた機能を**モジュール**として別ファイルにして外部に出しているためだ。そして、モジュールはカーネルが起動されたとき、カーネルの中に一緒に組み込まれることで動作するようになっている。各種モジュールファイルは、**/lib/modeules**の配下に格納されている。**/lib/modeules**の配下をみると、**5.4.0.80-generic**という、カーネルのバージョン番号であらわされたディレクトリが１つだけ存在している。そのディレクトリの中にたくさんのモジュールが格納されていることが確認できる。カーネルのバージョンを表示するコマンドは**uname -r**。実行すると、**5.4.0.80-generic**と表示される。OSのバージョンはUbuntu20.4なので、OSのバージョンとカーネルのバージョンは全く関連性がないことになる。

ls -lでモジュールが保管されているファイルの一覧を表示するには、**ls -l /lib/modeules/5.4.0.80-generic**となるが、**ls -l /lib/modeules/`uname -r`**というコマンドを使って応用することができる。これはちょっとしたテクニック。

OS起動時にカーネルに組み込まれたモジュールの一覧を表示するコマンドがある。それが**lsmod**コマンド。

vmlinuzは起動した後は、ディレクトリの大元である、**ルート（/）のファイルシステムをマウント**して、各種サービスを起動する大元のプログラム、**/sbin/init**を起動して、準備OKとなる。
十字方向に動くセレクトUIの実装


ドラクエなどでよくあるこういうやつです。
![画面収録 2021-10-09 20.01.20.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/dc778ab8-4185-b24a-9d9f-9de6ad3138db.gif)




今回GameMaker Studio2で実装したので、　JS風のGMLという言語で実装していますが、
特殊な機能はほとんど用いていないのでどんな言語/ゲームエンジンでも応用が効くと思います。

このロジックでは、次に指し示すべきindex位置を取得し、
それを元に描画すべきページ数を計算するという流れになっています。

```js

// ここら辺はキーを押した判定のための変数です。
keyLeft = keyboard_check_pressed(ord("A")) || keyboard_check_pressed(vk_left);
keyRight = keyboard_check_pressed(ord("D")) || keyboard_check_pressed(vk_right);
keyUp = keyboard_check_pressed(ord("W")) || keyboard_check_pressed(vk_up);
keyDown = keyboard_check_pressed(ord("S")) || keyboard_check_pressed(vk_down);
keySpace = keyboard_check_pressed(vk_space);


pressX = keyRight - keyLeft;
pressY = keyDown - keyUp;
itemCount = array_length(selectList);

selectCount = selectIndex - startIndex;
posXY = [selectCount  % 2, floor(selectCount / 2)]; // xy座標

// x軸
if(pressX != 0) {
    selectIndex += pressX;

    // 次のページが存在しない場合
    if(selectIndex > itemCount - 1) selectIndex = 0;
    // 前のページが存在しない場合
    if(selectIndex < 0) selectIndex = itemCount - 1;
}


// y軸
if(pressY != 0 && itemCount > 2) {
    var _prev = selectIndex;
    var _nowPage = floor(_prev / 4);
    selectIndex += pressY * 2;

    // 次のページが存在しない場合
    if(selectIndex > itemCount - 1) {
        // アイテム数が奇数の場合かつ1つ前が存在すればそれを返す
        if(itemCount % 2 == 1 && itemCount - 1 >= selectIndex - 1) {
            selectIndex -= 1;
        } else {
            selectIndex = posXY[0];
        }
    }
    // 前のページが存在しない場合
    if(selectIndex < 0) {
        // アイテム数が奇数の場合は最後尾を返す
        if(itemCount % 2 == 1) {
            selectIndex = itemCount - 1;
        } else {
            selectIndex = (itemCount - 1)  - 1 + posXY[0];
            
        }
    }
}

// ページ位置計算
startIndex = floor((selectIndex) / 4) * 4;
```

あとは他コンポーネントで`startIndex(ページ位置の始まりのindex位置)`、`selectIndex（現在洗濯中の項目のindex）`を用いて画面描画すればOKです。
選択した項目は`item[selectIndex]`などで取得すればいいですね。

## ポイント
### 奇数アイテムに注意
奇数アイテムだと、y軸方向（上か下）には偶数の場合と同様には移動することができないので注意です。

```js
// アイテム数が奇数の場合かつ1つ前が存在すればそれを返す
if(itemCount % 2 == 1 && itemCount - 1 >= selectIndex - 1) {
    selectIndex -= 1;
} else {
    selectIndex = posXY[0];
}
```
上記は先頭から戻る場合(上に進む場合)に、x座標が0,1どちらであっても一番最後のindexを示すように調整しています。
ユーザ的にその方が自然に感じるかと思いそう実装してみました。
![Untitled (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/41d1ada9-5cfb-8b6c-8bfa-c6c07c5adbd1.png)

下に進んだ場合はその場合も**2つ戻った先の1つ前が存在すればそれを返す**ようにしています。
こうすることで、下が空白だった場合にも違和感のない挙動が実現できます。


```js
// アイテム数が奇数の場合かつ1つ前が存在すればそれを返す
if(itemCount % 2 == 1 && itemCount - 1 >= selectIndex - 1) {
    selectIndex -= 1;
} else {
    selectIndex = posXY[0];
}
```

![Untitled (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/203f1cdf-aa68-844d-e1ab-5a69e141339b.png)


## まとめ
実は最初の頃は、「ページ遷移が起こるか否か」を一番最初の分岐に持ってきてしまい、
ロジックが非常に複雑になってしまいましたが、選択するのindex基準でリファクタリングしたところ非常にシンプルに実装することができました。
怪しい雲行きになってきた時は見方やロジックの根本部分を見直すのがとても大切だと改めて学びました🐕

また、上記コードだと必要ない工程まで毎度走ってしまうので、
パフォーマンス調整するなら一部を関数化してreturnするなどの調整が必要だと思います...!（今回手を抜いてしまいました）