OmniAICreator/Qiita-1.07M huggingface dataset:
【RuboCop】特定の「ディレクトリ」をチェック対象外とする

# 概要
bundle exec rubocopを実行した際、ルール違反のファイルを指摘してくれるが、
その中で**特定のディレクトリ**をルール適用対象外とする方法についてメモ。

## 環境
ruby 3.0.2
rails 6.1.4
mysql 8.0.26
rubocop 1.23.0
rubocop-rails 2.12.4

### ルール違反の検出
前提：多数のカラムを持つSampleモデルをrails generateで作成した直後とする。

```terminal:terminal
# チェックの実行
❯❯❯ bundle exec rubocop

# ルール違反箇所の検出
sample-app/.rubocop.yml: Warning: no department given for MethodLength.
Inspecting 63 files
.............................................................C.

Offenses:

db/migrate/20220119115229_create_sample.rb:2:3: C: Metrics/MethodLength: Method has too many lines. [11/10]
  def change ...
  ^^^^^^^^^^

63 files inspected, 1 offense detected
```

検出した違反：**Metrics/MethodLength**
これはメソッドが11行以上ある場合に違反とするもの。

>参考

https://qiita.com/tbpgr/items/46af4c0f5be30c5c6ccc

https://docs.rubocop.org/rubocop/cops_metrics.html#metricsmethodlength

**今後もmigrationでは11行以上のメソッドが必要になる可能性がありそうなので、ディレクトリ単位で除外しておきたい**

### 対象外設定方法
.rubocop.ymlに例外として記述する。

```yml:.rubocop.yml
# migrationファイルはメソッド行数が11行以上でも許可する
MethodLength:
  Exclude:
    - 'db/migrate/*' # *でmigrate以下のファイルを全て指定する
```

db/migrate以下のファイルを、デフォルトの10行制限の対象外とすることができた。

※特定の**ファイル**を対象外にしたい場合は、そのままファイル名まで指定すればOK

>参考

https://stackoverflow.com/questions/36896279/how-to-tell-rubocop-to-ignore-a-specific-directory-or-file

### 最後に

より良い方法や間違い等ありましたらご指摘いただけますと幸いです！
外部のDLLにあるグローバル変数をVSデバッガで見る

VisualStudioデバッガの小ネタです。
デバッガで外部のDLLにあるグローバル変数を見ようと思って、例えば`GUObjectArray`などとウオッチ窓に入力しても「そんな変数はない！」と突っぱねられてしまいます。
外部DLLはUnrealEngineやVSのデバッガの中ではモジュール(Module)と呼ばれたりします。(※この行は検索クローラー用のテキスト)

そんなときは`[dllの名前]![グローバル変数名]`とすることで変数を直接見ることが出来ちゃいます！便利！
例: `UE4Editor-CoreUObject-Win64.dll!GUObjectArray`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223804/a128d598-7811-8b83-962a-1ee6680b2dbd.png)


ちなみにGUObjectArrayはUnrealEngine中で全てのUObject継承オブジェクトとその付随情報を保持する巨大配列です。例えばGCの動作はUObjectを直接書き換えず、GUObjectArrayの構造体FUObjectItemの中にあるフラグを操作して行われていたりします。
UObjectBase::InternalIndexがこの配列へのインデックスになります。


# リンク
UObjectの動作原理(GUObjectArray.ObjObjects.Objects[][]の直接参照の仕方について記載があります。)
https://hexadrive.jp/lab/43608/
【備忘録】rbenvの導入（anyenv経由）




```
# rbenvのインストール
$ anyenv install rbenv

# 初期化処理をzshrc記述
$ echo 'eval "$(rbenv init -)"' >> ~/.zshrc

# インストールできるRubyの一覧表示
$ rbenv install -l

# 3.1.0をインストール
$ rbenv install 3.1.0

# ~/.rbenv/versions/*/bin/ 以下のファイルを ~/.rbenv/shims/ 以下にコピー
$ rbenv rehash

# グローバル指定
$ rbenv global 3.1.0

# バージョンの確認
$ ruby -v

```

参考記事：https://mogulla3.tech/articles/2020-12-29-01
【備忘録】anyenvの導入

## anyenvの導入


```
# anyenvのインストール
$ brew install anyenv

# 初期化処理をzshrc記述
$ echo 'eval "$(anyenv init -)"' >> ~/.zshrc

# シェルを再起動
$ exec $SHELL -l

# anyenvの初期化
$ anyenv install --init

# 各envのアップデートも簡単に出来るようにプラグインを導入
$ mkdir -p $(anyenv root)/plugins
$ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update

# updateコマンドが利用できるようになる
$ anyenv update
```
chromebookでのandroidアプリ開発時のWebView表示エラーにハマった件

###エラー事象

chromebookでandroidアプリ開発していますが、
twitter_loginでログインをしようとするとエラーとなって動きません。
twitter側の認証画面を表示するWebViewが表示できないようでした。

###エラー内容

![Screenshot 2022-01-19 10.39.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1864453/8a21f918-4176-85a0-c00e-c7d5c7b71cb5.png)

エラー表示されている内容はtwitter_loginが出力しているメッセージです。
実機を接続した場合は問題なく動きますので、chromeが有効化されていないってことだと思いますが、
chromebookなんだしchromeがなぜ有効化されていないのかが理解できず、
引数やDeveloper側の設定がまずいのかといろいろ試行錯誤するも変わらず。
１週間ほど悩みました。
何しろ元アプリでは動いていたものですから。

で、元アプリはWindowsで開発していたので、これはchromebook側の問題かとここでやっと気が付きました。

###対応１

flutterのWEBは使わないんで、Lunux側のchromeはインストールしていませんでした。
![Screenshot 2022-01-19 10.36.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1864453/b43d2087-1e73-0c27-6708-6e12954c6262.png)

これが原因かと思い、インストールしてみましたが変わらず。

###対応２

ふと思いついたのが、あくまでもandroid環境にあるchromeが呼び出されるんじゃないかと。
chromeOS上でもなく、Linux上でもなく、android上ですね。
android側のアプリ一覧を見るとchromeは存在しません。
（設定→アプリ→Google Playストア→Android設定を管理→アプリと通知）
なるほど、これかと。

ってことでPlayストアからchromeをインストールします。
ややこしくなるかと思ってBeta版を入れてみました。
![Screenshot 2022-01-19 11.33.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1864453/73dc0bc1-e8a8-ec47-b6f3-fc5ce08af47a.png)

今キャプチャを撮るとAndroid System WebViewがありますが、
これも入っていなかったような気がしますが、これが動けば問題なかった？

ってことで再度実行です！

はい、動きましたよ。
１週間ぐらい悩んだ末の結果がこれだったとは......
ABC234 D - Prefix K-th Max

k番目に大きい値を記録しておき，それよりも大きな数がきた場合はかつてのk番目に大きな値がk+1番目に大きな値となる．そのためk+1番目(かつてのk番目）に大きな値を二分探索し，その一つ前の値を新たなk番目に大きな値として更新する．
計算量$O(nlogn)$

```c++
#include<bits/stdc++.h>
using namespace std;

int main(){
    int n, k;
    cin >> n >> k;
    vector<int> p(n);
    for(auto &e : p) cin >> e;
    set<int, greater<int>> st;
    for(int i=0; i<k; i++) st.insert(p[i]);
    int t = *prev(st.end());
    cout << t << "\n";

    for(int i=k; i<n; i++){
        st.insert(p[i]);
        if(p[i]>t){
            auto itr = st.lower_bound(t);
            t = *prev(itr);
        }
        cout << t << "\n";
    }

    return 0;
}
```
Django REST framework - jwt 軽く触ってみる

# DRF - JWT 軽く触ってみる

作ってるアプリをDjango×Reactにするため、DjangoRESTframeworkを利用しています
認証機能にはDjango REST framework JWT を使うと良いということなので、公式？チュートリアル(Usage)をみてやってみる

[公式Usage](https://jpadilla.github.io/django-rest-framework-jwt/#usage)

# Securityについて

セキュリティについては、以下の記述がありました。

> 他の典型的なJWTトークンと違って、DRF-JWTモジュールは保護されたDRFに対して、
> 「リクエストを送るユーザが誰なのか」ということを認証するトークンのみ発行する

> そのため、実際のJWTトークンのClaim内には、リクエスト内容は**含まれない**
> つまり、ユーザからのリクエストは`署名されていない、もしくは改ざんされている可能性がある`

> これを回避するためには、APIエンドポイントは必ずSSL/TLSを利用して守ってあげる必要がある

## jwt インストール

pip で install するだけ！

```shell
$ pip install djangorestframework-jwt
```

## settings.py に設定追加

`DEFAULT_PERMISSION_CLASSES` と `DEFAULT_AUTHENTICATION_CLASSES` を追加
おそらく `JSONWebTokenAuthentication` が DEFAULT_AUTHENTICATION_CLASSES に入ってたらOK
それ以外の設定は今のところ詳細不明

```py
# drf settings
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}
```

## url.py に設定追加

```py
urlpatterns = [
    ...
    path('api-token-auth/', obtain_jwt_token),
]
```

## この時点でもうjwt認証ができるようになっている

- token 発行

urlにて設定したアドレスにユーザ名とパスワードを入れてPOSTすると、トークン情報が返ってくる

```shell
$ curl -X POST -d "username=admin&password=password" http://127.0.0.1:8000/api-token-auth/

# 長いので略
{"token":"xxxx.yyyy.zzzz"}
```

- トークンを利用してGET

入手したtoken情報をhttpのリクエストヘッダに入れると、APIでJSONを返せるようになる
`$ curl -H "Authorization:jwt <token情報>" http://127.0.0.1:8000/api名` で試せる

```shell
$ curl -H "Authorization:jwt xxxx.yyyy.zzzz" http://127.0.0.1:8000/snippets/
{"count":5,"next":null,"previous":null,"results":.略.}
```

## Refrash, Verify

同様にして、refresh と verify のURLを追加すると、初期化と認証機能が追加できる

```py
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token

urlpatterns = [
    path('', include('snippets.urls')),
    path('api-token-auth/', obtain_jwt_token),
    path('api-token-refresh/', refresh_jwt_token),
    path('api-token-verify', verify_jwt_token),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]
```

- refresh

refresh機能は[デフォルト設定](https://jpadilla.github.io/django-rest-framework-jwt/#additional-settings)では無効になっているので、
設定追加する

Falseのままアクセスすると `{"non_field_errors":["orig_iat field is required."]}` と返ってくる

```py:settings.py
JWT_AUTH = {
    'JWT_ALLOW_REFRESH': True,
}
```

refresh実行

```shell
$ curl -X POST -H "Content-Type: application/json" -d '{"token":"xxxx.yyyy.zzzz"}' http://127.0.0.1:8000/api-token-refresh/

# 別のTokenが返ってくる
{"token":"xxxx.aaaa.bbbb"}
```

- verify

```shell
$ curl -X POST -H "Content-Type: application/json" -d '{"token":"xxxx.yyyy.zzzz"}' http://127.0.0.1:8000/api-token-verify/

# status code 202 で返ってくる
{"token":"xxxx.yyyy.zzzz"}
```

## おわり

他にもいろいろ設定をいじれるようですが、
この記事では一番簡単に実装できる部分だけ紹介という形になります。

この後は実際のログイン認証機能作成だ
Webpackerでerror Command "webpack-dev-server" not foundになる

# はじめに

最近Railsの開発環境を作成しています。
[こちらの記事](https://zenn.dev/jinwatanabe/articles/4d26ac177069f374eb6a)で構築手順を載せています。

そこで、GitにリポジトリをあげたコードをCloneして起動したところうまく起動できない事態が発生したため手直しのさいに解決した方法をまとめます。また、この記事とは別にWebpackerの問題がもう一つ起きています。
以下の記事から確認ください。

https://qiita.com/Sicut_study/items/d3c8b30570ce49dc6d8c

# 問題

DockerでWebpackerを環境を作成して起動したところ以下のエラーが発生しました。

```
webpacker_1  | error Command "webpack-dev-server" not found.
```

何度か起動するとエラーが消えて、git cloneしてくると初回は発生しました。

# 解決方法

これは`yarn install`された際に自動生成される`/node_modules`がないためにおこるエラーです。
本来であればWebpackerコンテナの中に`yarn install`された時点で`/node_modules/webpack-dev-server`が作成されます。しかし、Git clone時はローカルに`node_modules`が存在しないため(gitignoreされているため)ファイルマウントがおきずにこのようなエラーになります。

そこで、Dockerfile内で`yarn install`をすることでエラーを解決しました。

```Dockerfile
FROM ruby:alpine3.13

ARG UID

RUN adduser -D app -u ${UID:-1000} && \
      apk update \
      && apk add --no-cache gcc make libc-dev g++ mariadb-dev tzdata nodejs~=14 yarn

WORKDIR /myapp
COPY Gemfile .
COPY Gemfile.lock .
RUN bundle install
COPY --chown=app:app . /myapp
RUN yarn install # 追加
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
# EXPOSE 3000
# CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]

USER app
RUN mkdir -p tmp/sockets
RUN mkdir -p tmp/pids
```

そして、このコンテナ内で作成された`node_modules`を使えばよいのですが、docker-compose.ymlでボリュームを設定していないとコンテナ内の`node_modules`は勝手に削除されます。

[【Docker】docker compose upするとnode_modulesがマウントされて消える問題](https://rara-world.com/dockerfile-node-modules/)

こちらの記事通りに`docker-compose.yml`で`volumes`マウントして消えないようにします。
またRailsコンテナでもnode_modulesは必要なので(yarn installしたライブラリを利用するので)、こちらにも`volume`を追加します。

```docker-compose.yml
version: "3.3"
services:
  rails:
    build: .
    container_name: rails
    command: bundle exec puma -C config/puma.rb
    volumes:
      - .:/myapp
      - public-data:/myapp/public
      - tmp-data:/myapp/tmp
      - log-data:/myapp/log
      - /myapp/node_modules # 追加
    env_file:
      - .env
    depends_on:
      - db
    environment:
      WEBPACKER_DEV_SERVER_HOST: webpacker

  webpacker:
    build: .
    volumes:
      - .:/myapp
      - /myapp/node_modules # 追加
    command: ./bin/webpack-dev-server
    environment:
      WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
    ports:
      - "3035:3035"
```
# おわりに

yarnやpackage.jsonについて初めて勉強したのでかなり沼りました。
また、ネットにもほしい情報はなく検証をかなりして解決することができました。
このあとにWebapackのCSSやVueが読み込まれなかったり、Template Errorが発生するトラブルを解決していますので困った方は確認してみてください。

https://qiita.com/Sicut_study/items/d3c8b30570ce49dc6d8c

# 参考

- [【Docker】docker compose upするとnode_modulesがマウントされて消える問題](https://rara-world.com/dockerfile-node-modules/)
【Python3】abcモジュールで抽象クラスを実装する

## はじめに

Pythonの標準モジュールである```abc```(abstract base class)を使うと抽象クラスを利用することができます。

## 環境
- Ubuntu20.04
- Python3.8.10

## 使い方

### 抽象クラスを定義

```python:animal.py

# 1. モジュールをインポート
from abc import ABC, abstractmethod

# 2. ABCクラスを継承
class Animal(ABC):
    
    # 3. デコレータで抽象メソッドであることを宣言
    @abstractmethod
    def cry(self):
        pass
```

まずは冒頭でabcモジュールからABCクラス・abstractmethodデコレータをインポートします。

クラスの定義時にABCクラスを継承することで抽象クラスとして定義できます。

```
class Animal(ABC):
```

以下のような書き方も可能です。


```
class Animal(metaclass=ABCMeta):
```

@abstractデコレータをメソッドにつけると抽象メソッドであることが示されます。
抽象メソッドにも具体的な処理を記述することはできますが、抽象メソッドであることを明示するためには何も書かないのが望ましいでしょう。

### 継承先クラスを実装

先ほど定義したAnimalクラスを継承したクラスを実装します。

```python:cat.py
# 抽象クラスをインポート
from animal import Animal
# 抽象クラスを継承
class Cat(Animal):
    
    def __init__(self, name: str):
        self.name: str = name 
    # 抽象メソッドを実装
    def cry(self):
        print('にゃーん')

# Animal型のオブジェクトとしてcatを宣言
cat: Animal = Cat("ハチワレ")
cat.cry()
```

cat.pyを実行します。

```bash
$ python3 cat.py 
にゃーん
```

正常に実行することができました。

Animalクラスで定義されているcryメソッドを実装しない場合はどうなるでしょうか。

```python:dog.py
# 抽象クラスをインポート
from animal import Animal

# 抽象クラスを継承
class Dog(Animal):
    
    def __init__(self, name: str) ->None:
        self.name: str = name 
   
    # 抽象メソッドを定義しない

dog: Dog = Dog("ポチ")
```

このdog.pyを実行してみます。

```bash
$ python3 dog.py 
Traceback (most recent call last):
  File "dog.py", line 9, in <module>
    dog: Animal = Dog("ポチ")
TypeError: Can't instantiate abstract class Dog with abstract methods cry
```

Animalクラスで定義したcryメソッドを実装していないとエラーになります。

このように、抽象クラスを使えば継承先のクラスにメソッドを実装するように強制することができます。実装漏れや同じようなクラスで振る舞いが異なるという事態を事前に回避するのに役立ちます。

### 参考資料

[abc --- 抽象基底クラス](https://docs.python.org/ja/3/library/abc.html)
【備忘録】キーリピートの設定


## リピート入力認識の速度をあげる

```
# 現在の設定は以下のコマンドで確認
$ defaults read -g InitialKeyRepeat

# リピート入力認識を上げる
$ defaults write -g InitialKeyRepeat -int 12
```

## キーリピートの速度を上げる

```
# 現在の設定は以下のコマンドで確認
$ defaults read -g KeyRepeat

# キーリピートの速度を上げる
$ defaults write -g KeyRepeat -int 1
```

## Macの再起動

上記コマンドを実行後、Macを再起動後キーリピートが速くなる

## (補足)元に戻したい場合

```
# リピート入力認識速度を初期化
$ defaults delete -g InitialKeyRepeat

# キーリピート速度を初期化
$ defaults delete -g KeyRepeat
```

## 補足

カーソルのエフェクトツール

https://apps.apple.com/jp/app/screen-cursor-%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%83%9E%E3%83%BC%E3%82%AB%E3%83%BC%E3%83%84%E3%83%BC%E3%83%AB/id1577211880?mt=12
【備忘録】ターミナル設定

## 前提

- brewコマンドが使えること  

https://qiita.com/kenji7157/items/737db12d883382e32fea

## やること

1. zsh インストール
2. oh my zsh インストール
3. デフォルトのログインシェルを設定
4. iTerm2 インストール/シェル設定
5. zsh, iTerm2 テーマ設定
6. PATHの追加読み込み設定
7. .bash_profile読み込み設定

## 1. zsh インストール

- Homebrewでzshをインストールする

```
$ brew install zsh
```

- インストールされたzshのバージョンを確認する

```
$ which zsh
/usr/local/bin/zsh

$ /usr/local/bin/zsh --version
zsh 5.8 (x86_64-apple-darwin19.6.0)
```

## 2. oh my zsh インストール

- oh my zsh: zshのフレームワーク

```
$ curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh
```


## 3. デフォルトのログインシェルを設定

- ターミナルを再起動して、ログインシェルを確認する

```
$ echo $SHELL
/bin/zsh
```

- ログインシェルをbashに戻す

```
$ chsh -s /bin/bash
```
ターミナルを再起動して、ログインシェルを再確認する

```
$ echo $SHELL
/bin/bash
```

## 4. iTerm2 インストール/シェル設定


- 以下のリンクからiTerm2をインストール

https://iterm2.com/

- zshをデフォルトシェルに設定


```
$ sudo sh -c "echo '/bin/zsh' >> /etc/shells"
$ chsh -s /bin/zsh
```

## 5. zshのテーマ(Candy)設定

- .zshrcにて、candyにテーマを設定する

```
$ vi ~/.zshrc

ZSH_THEME="candy" を追記
```





参考記事：https://qiita.com/NaokiIshimura/items/249bb1a101b626a59387
Kotlinデビューしたくて環境構築してみた


# はじめに
Kotlinを触ってみたくなったので、環境構築をしてみました。
実際に動かすのは、今後になる予定です。

# 環境構築（Windows）
## JDKのインストールをする

1.公式サイトからJDKをダウンロードする
https://www.oracle.com/java/technologies/downloads/#jdk17-windows

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/e268999c-43d7-70a0-086f-3aab9ca40368.png)


2.インストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/64ba3798-24b6-6f5a-48cb-e2a390fd40db.png)

3.環境変数の設定をする

「スタートメニュー」＞「設定」＞「システム」＞「詳細情報」＞「システムの詳細設定」＞「環境変数」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/070e48eb-41bb-38eb-1402-066855141799.png)

「JAVA_HOME」を追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/6cfdf0a6-42ac-e026-9ed2-9b1ed8955854.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/6da484cf-f133-e84d-b927-58574a9804f6.png)

インストールが完了したことを確認する

```cmd
C:\Users\XXX>java -version
java version "17.0.1" 2021-10-19 LTS
Java(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)
```

## Android Studioをインストールする（統合開発環境）

1.　公式サイトからAndroid Studioをダウンロードする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/f3bf3c60-c976-4fcb-f514-2d6e9c273c99.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/78fbe6e8-f711-6764-7e82-41b186ee3acd.png)

特に変更がないのでどんどん進めていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/88d386e5-671a-a5f7-dd2f-b11bbc841d83.png)

初回起動時に上記画面が出てきましたが、特にインポートせずに進めます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/eb6e98d1-ea3e-2a32-87ac-bb821fefac91.png)
セットアップを行いますので、好みの設定を行いました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/7a65ae18-2cbd-d4a0-d276-464b576b7817.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397779/0de78188-39f9-38cc-11ea-5da6f3c7f0f3.png)

セットアップが完了しました。
AWS Step Functions メモ


## 概要

* AWSが提供するサーバーレスオーケストレーションサービス。
* 分散アプリケーション・マイクロサービスを「ステートマシン」と呼ばれる仕組みでオーケストレートする。
  * 定義したステートマシンはAWS コンソールから「ワークフロー」という形式で可視化できる。

## 用語

### ステート

* 状態または一つの作業単位を表す。

### ステートマシン

* ステートからなるフロー(ワークフロー）を指す。

  ![step_functions_wf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/dfb17d9a-2d6e-8131-1d02-2e538fdd7da8.png)


* ASL (Amazon States Language) と呼ばれるJSON 形式の言語で定義する。

* ASL例

  ```json
  {
    "Comment": "A Hello World example of the Amazon States Language using Pass states",
    "StartAt": "Hello",
    "States": {
      "Hello": {
        "Type": "Pass",
        "Result": "Hello",
        "Next": "World"
      },
      "World": {
        "Type": "Pass",
        "Result": "World has been updated!",
        "End": true
      }
    }
  }
  ```

  * `Comment`:コメント（概要等）

  * `StartAt`:最初に実行するState

  * `States`:ステートマシンを構成するStateを定義する。複数のStateの指定が可能。

    * `Task`:処理の単位
    * `Choice`:条件分岐
    * `Fail/Succeed`:失敗または成功として停止
    * `Pass`:入力を単純に出力に渡す、または一部の固定データを出力
    * `Wait`:処理停止時間
    * `Parallel`:並列処理
    * `Map`:配列要素ごとに処理を実行

`Task`例


| フィールド       | 説明                                                         |
| ---------------- | ------------------------------------------------------------ |
| `Name`           | タグ                                                         |
| `Resource`※必須  | URI/サービスARN                                              |
| `Parameters`     | Stateに渡すJSON形式の値                                      |
| `ResultPath`     | Stateの実行結果を受け取るフィールド                          |
| `Retry`          | Stateでランタイムエラーが発生した際の再試行ポリシー          |
| `Catch`          | Stateでランタイムエラーが発生し、再試行ポリシーが使い果たされたか定義されていない場合に実行される処理 |
| `TimeoutSeconds` | 処理をタイムアウトさせる時間                                 |

など

### ワークフロー

* ステートマシンを作成する際に以下いずれかのワークフローを選択する。
  * **標準**
     * 実行レート：毎秒 2,000
     * 状態遷移レート：毎秒4,000 
     * 課金形態：状態遷移ごと
  * **Express**※大量データ処理向き
     * 実行レート：毎秒100,000 
     * 状態遷移レート：ほぼ無制限
     * 課金形態：実行回数と実行期間

## サポートAWS サービス

* 次のようなサービスとの連携をサポート

  * Lambda
  * DynamoDB
  * SNS
  * SQS
  * Batch
  * ECS

  など

* **連携パターン**

  * リクエストレスポンス
        * リソースに対してHTTP応答を要求。ジョブの完了を待たない。
  * ジョブの実行
        * AWS Batchなどとの統合の場合にリクエストが完了するのを待ってから次のStateに遷移
  * コールバックまで待機
        * リソースからタスクトークンが返されるまで処理を中断

## ステートマシン実行方法

- API呼び出し
- マネジメントコンソール
- CloudWatch Events
- API Gateway
- AWS CLI
- SDK
- ステート(ネストして実行)



## 参考情報

* [AWS Step Functions とは](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/welcome.html)
* [20190522 AWS Black Belt Online Seminar AWS Step Functions](https://www.slideshare.net/AmazonWebServicesJapan/20190522-aws-black-belt-online-seminar-aws-step-functions)
RailsでMissing helper file helpers/〜〜というエラーが出た時の解決策

# はじめに
プログラミング初学者の[@kat_log](https://twitter.com/kat__log "Twitter")と申します。

Railsチュートリアル6版の学習中、14章の「14.2.4[Follow]ボタン(基本編)」の
`$ rails generate controller Relationships`
を実行後に
>Missing helper file helpers/relationships_helper.rb (AbstractController::Helpers::MissingHelperError)

というエラーが出て戸惑ったのですが、解決したため共有です。

# 結論
`$ spring stop`
コマンドで解決しました。

## springとは
「開発効率を上げるためにバックグラウンドで動いてくれているやつ」らしいです！

https://nyakanishi.work/lets-stop-spring-when-the-rails-command-does-not-work-properly/#toc1

## spring再起動方法
`rails c`等でspringも(再)起動されます。

https://qiita.com/residenti/items/937d9fa3e98eaa498ff6#%E5%86%8D%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B

# その他解決策
-  bundle update

自分は同様の問題が13章「13.2.3プロフィール画面のマイクロポストをテストする」でも発生したのですが、その時は下記記事をもとに
`$ bundle update`で解決しました。

https://qiita.com/aboru/items/cdb9d631fc2f4c0806f9#comment-3c1d89bdf8fb39011a32

- tmpデータ削除

`$ bin/rails tmp:clear`にてエラー解消された方もいらっしゃるようです。
（下記記事コメント欄より）

https://qiita.com/KuroganeHey/items/962fc74669ef7f4221dd

# おわりに
お読みいただきありがとうございました。
自分と同じ状況で困った方の参考になれば嬉しいです。
XAMPPをDropBoxで複数台のPCで共有したがうまくいかないときの対処法

表題のような問題にかなりの時間を費やしてきました。
2台のPCを並べて、WordPressをインストールし、共有がとてもうまくいったときには感動しました。
PC1で書いた記事が、DropBox共有が終わったらPC2でも反映されてる。。。なんて便利なんだ。

そういういきさつで、満を持してPCを別々の事業所に配置。

しかしあんなに確認したのに、XAMPPのエラーが・・・
色々やって何とかエラー解消したが、WordPressの共有が切れていたり、なぜか初期設定の画面になったり、もう色々。
データベースも編集できないし。

またPC2台横に並べて調整しなきゃいけないのか？？
そんな時間的余裕はない。。。
でも、とても良い方法を見つけました。

##XAMPPをDropBoxで複数台のPCで共有したがうまくいかないときの一番いい対処法
###共有しない。

開発するPCを1台に決める。一番集中できる環境にあるPCでしか開発しない。

もう何時間もグダグダやらない。
どうしてもほかのPCでやるときは、AllInOneWPMigration使う。

以上が私の最適解です。
Windows からのとりあえず post

curl 入れないといけないとかめんどい、とりあえずの場合は powershell だけで何とかしたい、というのが目的。

```
cat -Encoding UTF8 'post.json' | Out-File -Encoding DEFAULT 'test.txt'
$w = Invoke-WebRequest -Method Post -InFile 'test.txt' -ContentType 'application/json' http://***
echo $w.RawContent |Out-File 'response.txt'
```

utf8にBOMがある場合そのまま投げると Invoke-WebRequest で失敗する(↓メッセージ)。一行目はut8をshift-jisに変換してこれを防ぐ。

BOMなしutf8を作るのはちょっとめんどいが一応できるらしい。https://qiita.com/yaju/items/b519ff54a6906338442c
OSSECについて学び始めた その３

#はじめに
ふとセキュリティについて何か学習を始めたいと思いました。オープンソースのプログラムを解読しながら、理解を深めていきたいと思います。
まずはオープンソースのOSSECについて学習します。まずはドキュメントを読むことから始めます。
https://www.ossec.net/docs/

今回は第三弾としまして、OSSECがサポートするシステムについて読んでいきます。
https://www.ossec.net/docs/docs/manual/supported-systems.html

#対応システム
##オペレーティングシステム
OSSECエージェントは、以下のOSに対応しています。
・GNU/Linux (all distributions, including RHEL, Ubuntu, Slackware, Debian, etc)
・Windows XP, 2003, Vista, 2008, 2012
・VMWare ESX 3.0,3.5 (including CIS checks)
・FreeBSD (all current versions)
・OpenBSD (all current versions)
・NetBSD (all current versions)
・Solaris 2.7, 2.8, 2.9, 10 and 11.4
・AIX 5.2 and 5.3
・Mac OS X 10.x
・HP-UX 11
##Syslogでサポートされるデバイス
これらのシステム/デバイスは、リモート syslog でもサポートされています。
・Cisco PIX, ASA and FWSM (all versions)
・Cisco IOS routers (all versions)
・Juniper Netscreen (all versions)
・SonicWall firewall (all versions)
・Checkpoint firewall (all versions)
・Cisco IOS IDS/IPS module (all versions)
・Sourcefire (Snort) IDS/IPS (all versions)
・Dragon NIDS (all versions)
・Checkpoint Smart Defense (all versions)
・McAfee VirusScan Enterprise (v8 and v8.5)
・Bluecoat proxy (all versions)
・Cisco VPN concentrators (all versions)
・VMWare ESXi 4.x
##エージェントレスでデバイスとオペレーティングシステムを
OSSECエージェントレスオプションを使用すると、以下のシステムもサポートされます（ログ解析およびファイル整合性チェックのため）。
・Cisco PIX, ASA and FWSM (all versions)
・Cisco IOS routers (all versions)
・Juniper Netscreen (all versions)
・SonicWall firewall (all versions)
・Checkpoint firewall (all versions)
・All operating systems specified in the “operating systems” section
#おわりに
今回はここまで。では、また。
OSSECについて学び始めた その２

#はじめに
ふとセキュリティについて何か学習を始めたいと思いました。オープンソースのプログラムを解読しながら、理解を深めていきたいと思います。
まずはオープンソースのOSSECについて学習します。まずはドキュメントを読むことから始めます。
https://www.ossec.net/docs/

今回は第二弾としまして、OSSECのアーキテクチャについて読んでいきます。
https://www.ossec.net/docs/docs/manual/ossec-architecture.html

#OSSECアーキテクチャ
##マネージャー（またはサーバー）
マネージャーは、OSSECの展開の中心的な部分です。
・ファイルの整合性チェックのデータベース
・ログ
・イベント
・システム監査のエントリ
を保存します。
すべてのルール、デコーダ、主要な設定オプションは、マネージャに一元的に保存されます。
エージェントは、ポート1514/udpでサーバに接続します。
エージェントがサーバと通信するためには、このポートへの通信が許可されている必要があります。マネージャーはOSSECサーバーと呼ばれることもあり、この文書では単にサーバーと呼ぶこともある。とのことですので、エージェントはクライアントで、マネージャーはサーバのことだと思います。
##エージェント
エージェントは、監視対象のシステムにインストールされる小さなプログラム、またはプログラムの集合体である。エージェントは情報を収集し、それをマネージャ（OSSECサーバ）に転送して解析と相関をとる。ある情報はリアルタイムで収集され、他の情報は定期的に収集されます。デフォルトで非常に小さなメモリとCPUフットプリントを持ち、システムの使用率に影響を与えません。

エージェントのセキュリティ 低権限のユーザ（通常、インストール時に作成されます）で、システムから隔離された chroot jail 内で実行されます。エージェントの設定のほとんどは、マネージャ（OSSECサーバ）からプッシュすることができます。
OSSECは、Microsoft Windowsプラットフォームにのみ、エージェントとしてインストールすることができます。このようなシステムでは、Linuxやその他のUnix系システム上で動作するOSSECサーバーが必要になります。
##エージェントレス
エージェントがインストールできないシステムについては、エージェントレス対応により、完全性チェックを行うことができる場合があります。エージェントレススキャンは、ファイアウォール、ルーター、さらにはUnixシステムの監視に使用することができます。
##仮想化/VMware
OSSECでは、ゲストOSにエージェントをインストールすることができます。また、VMWare ESXの一部のバージョンにインストールすることもできますが、サポート上の問題が発生する可能性があります。VMware ESX内部にインストールされたエージェントを使用すると、VMゲストのインストール、削除、起動などの際にアラートを受け取ることができます。また、ESXサーバー内部でのログイン、ログアウト、エラーも監視します。さらに、OSSECはVMwareのCIS（Center for Internet Security）チェックを行い、安全でない設定オプションが有効になっているか、その他の問題があれば警告を発します。
##ファイアウォール、スイッチ、ルーター
OSSECは、多種多様なファイアウォール、スイッチ、ルーターからsyslogイベントを受信し、分析することができます。すべてのCiscoルーター、Cisco PIX、Cisco FWSM、Cisco ASA、Juniperルーター、Netscreenファイアウォール、Checkpoint、その他多くのルーターに対応しています。

#おわりに
今回はここまで。では、また。
マテリアル設定を一括コピーして VRoid で生成した VRChat 用アバターのマテリアル再設定を自動化する

私は [VRMConverterForVRChat](https://qiita.com/100/items/7315fe3a7eb75732ae43) を利用して VRoid で生成した VRM 形式のアバターを VRChat に持ち込んでいます。

[VRoidAvatarSetupUtils](https://qiita.com/jirko/items/7f1aaee574675273bc39) を併用すれば VRCSDK パラメータの再設定[^1]やオブジェクトのコピーが自動化できて便利です。それでも、シェーダの変更やシェーダプロパティといったマテリアルの設定は手動で行う必要があります。インポートのたびに繰り返すのは面倒ですよね。

[^1]: [Playable Layers と Expressions 、Constraints をコピーする機能を追加し、VRCPhysBoneに対応したフォーク版](https://github.com/yokra9/VRoidAvatarSetupUtilsKai/releases)を公開しています。

というわけで、ソースとして指定したマテリアルの設定を取得して複数のマテリアルに一括で適用するツールを作成してみました。

## MaterialSetupUtils の導入方法

1. [Booth](https://yokra.booth.pm/items/3588840) もしくは [GitHub](https://github.com/yokra9/MaterialSetupUtils/releases) から取得した Zip ファイルを展開 (解凍) します。
2. `.unitypackage` ファイルを、Assets にドラッグ&ドロップします。

## MaterialSetupUtils の使い方

1. メニューバーで `[Tools]` - `[MaterialSetupUtils]` を開きます。
　　![MaterialSetupUtils-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463374/1fce26aa-645b-3733-4ac8-5638b4b3a9ff.jpeg)

2. `Source Material` としてパラメータをコピーしたいマテリアルを指定します。
   ![MaterialSetupUtils-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463374/ec2aa359-9736-90fd-e586-15f19c5eab95.jpeg)

3. コピーしたいシェーダプロパティにチェックを入れます。`Filter (Prefix)` でプロパティをフィルタできます（前方一致、大文字と小文字を区別）。また、画面下部でチェックの一括設定や保存・読込ができます。
   ![MaterialSetupUtils-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463374/4a0889ab-2f4a-ae23-5420-383a30452399.jpeg)

4. Assets でコピー対象のマテリアルを選択します（複数選択可）。このとき、検索機能で対象を絞り込んだり、`★`で検索条件を保存しておくと便利です。
   ![MaterialSetupUtils-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463374/20d31d8e-85d3-7625-9e22-1c0fde2fa2d6.jpeg)

5. 画面下部の `Copy` を押下すると、選択中のマテリアルに対してプロパティのコピー処理が実行されます。

## 不具合報告

[GitHub の Issue](https://github.com/yokra9/MaterialSetupUtils/issues) もしくは [私の Twitter アカウント](https://twitter.com/yokra9)までお気軽にご連絡ください。

## 参考リンク

- [VRM から VRChat へアップロードする流れ](https://qiita.com/100/items/7315fe3a7eb75732ae43)
- [VRoid から生成した VRChat 用アバターのパラメータ再設定（DynamicBone 含む）を自動で行う](https://qiita.com/jirko/items/7f1aaee574675273bc39)
- [Material の Shader プロパティーを表示　その 1（Editor 拡張）](https://karanokan.info/2020/10/22/post-5625/)
- [UnityEngine.Material](https://docs.unity3d.com/ja/2019.4/ScriptReference/Material.html)
- [UnityEngine.Shader](https://docs.unity3d.com/ja/2019.4/ScriptReference/Shader.html)
Rubyで解く射撃王

[問題解決力を鍛える！アルゴリズムとデータ構造](https://www.amazon.co.jp/%E5%95%8F%E9%A1%8C%E8%A7%A3%E6%B1%BA%E5%8A%9B%E3%82%92%E9%8D%9B%E3%81%88%E3%82%8B%EF%BC%81%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0-%EF%BC%AB%EF%BC%B3%E6%83%85%E5%A0%B1%E7%A7%91%E5%AD%A6%E5%B0%82%E9%96%80%E6%9B%B8-%E5%A4%A7%E6%A7%BB%E5%85%BC%E8%B3%87-ebook/dp/B08PV83L3N/ref=sr_1_4?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=16M9DX8AQWUYQ&keywords=%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0&qid=1642588719&s=books&sprefix=%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%2Cstripbooks%2C315&sr=1-4)を読み進めていく中で、二分探索法でAtCoderの[射撃王](https://atcoder.jp/contests/abc023/tasks/abc023_d)という問題が出題されていました。
C＋＋で解答が書かれていたがいまいちピンと来なかったので、Rubyで自分なりに解釈しながら書き換えていきました。
実際にACもらったので、コメントで説明してあるRubyコードを載せます。


```ruby
n = gets.chomp.to_i
hs = Array.new(n) {gets.chomp.split(' ').map(&:to_i)}

#bsearchメソッドで二分探索開始(ブロックの評価結果が true になる最初の要素を返すか、nil を返す)
ans = (1..10**15).bsearch do |v|
  # v は目標高度のデッドラインとなる
  timetable = Array.new(n, 0)
  flug = true
  hs.each do |h, s|
    #(v-h)/s で、風船がデッドラインに達するまでの時間
    #風船がデッドラインに達するまでの時間と 最低限待てる時間を比べ、小さい方を選ぶ
    second = [(v-h)/s, n-1].min
    if second < 0
        #風船のデッドラインまでの時間が負（既にデッドラインに達している）ならfalseにする
	    flug = false 
    else
        ##まだ正（デッドラインに達するまで時間がある)なら割らなきゃいけない時間の配列に+=1
	    timetable[second] += 1
    end
  end
  
  shootable = 0
  #shootable = その時間までで割れる風船の数
  n.times do |j|
    shootable += 1
    #もしその時間までで割れる風船の数よりも多くの風船をその時間内に割らなきゃいけないなら、flug=false
    flug = false if shootable < timetable[j]
    #そうでないなら、割った数だけ引く
    shootable -= timetable[j]
  end
  #flug = true ならvで与えたデッドライン以内で割れるということ
  flug
end

#falseとtrueの境目のansが与えられる
p ans
```
１週間でITパスポート

## 目次
[・はじめに](#はじめに)
[・そもそもITパスポートって何？](#そもそもITパスポートって何？)
[・ITパスポートの難易度は？](#ITパスポートの難易度は？)
[・勉強法](#勉強法)
[・＋αで見ておくべきページ](#＋αで見ておくべきページ)
[・さいごに](#さいごに)


---
## はじめに
勉強時間がない！勉強が嫌い！参考書を買いたくない！
※ITパスポート受験予定で十分な勉強時間がない方（追い込まれた方）、最低限の勉強で合格したい方向けの記事です。
これは自分自身が知識ほぼ０からの勉強で、取得した際の情報です。
2021年下期に後輩もこの勉強法で１週間で合格できたので実績有。

---
ITパスポートとは、ITを利活用する全ての社会人もしくは、これから社会人となる学生が備えておくべき、ITに関する基礎的な知識が証明できる国家試験である。

詳しくは、公式サイトである[こちら](https://www3.jitec.ipa.go.jp/JitesCbt/index.html)を参照してください。


---
## ITパスポートの難易度は？
ITパスポートはIPAが公開している情報処理試験区分によると基礎部分に該当します。
![https___qiita-image-store.s3.amazonaws.com_0_278934_e88983ab-1872-ba3c-c7d5-d7aa1220503b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661604/fc81fc94-4c91-eeeb-78f6-4bf07163b834.png)


---
## 勉強法
①　ITパスポート試験の概要を確認しよう
【パスITパスポート試験】
https://www3.jitec.ipa.go.jp/JitesCbt/index.html



②　ITパスポート試験ドットコム 過去問道場でどんな試験が出るのか見てみる
【ITパスポート試験ドットコム 過去問道場】
https://www.itpassportsiken.com/ipkakomon.php

過去問をスマホやパソコンで閲覧可能！
一問一答形式で解説有。正答率も集計してくれるので、どの分野が苦手か自分の実力を確認できる！

③　②の過去問道場の問題を直近から4.5年分解いてみる！試験日までひたすら！
基本的に過去問ベースの出題のため、過去問を暗記するくらいになっておけば合格できる！
→近年傾向が変わりつつあるので、テキストを１冊購入しておくのが良いと思います。



---
## ＋αで見ておくべきページ
ITパスポート試験における出題範囲・シラバスの一部改訂について（高等学校情報科「情報Ⅰ」への対応など）
https://www.jitec.ipa.go.jp/1_00topic/topic_20211008.html
https://www3.jitec.ipa.go.jp/JitesCbt/html/about/range.html
出題範囲情報が掲載されている。受験時期によってシラバスの情報は試験に直結するので、必ず確認しておきましょう！


・CBT疑似体験ソフトウェア
https://www3.jitec.ipa.go.jp/JitesCbt/html/guidance/trial_examapp.html
実際の試験で使用される疑似体験ソフトが配布されている！
当日慌てないように一度は使っておきましょう！



---
## さいごに
上記方法は特に参考書等も買わず、ネット上のリソースを活用しての勉強方法なので本当におススメです。
※よくIT業界の方だと無勉で合格できると言っている方もいますが、あくまでも国家資格！
油断せずに勉強しましょう。
SlackでIncoming Webhookの設定を行う

#はじめに

GASとSlackを連携して、botでお知らせをする機能を作成するため、
Incoming Webhook について学んだので備忘録として設定方法をまとめます。
Slackで Incoming Webhook を始めたいと思っている方の手助けになればと思います。

#ターゲット

**(前提)**
Slackにてワークスペース、チャンネルを作成済みであること

- Slackを普段使用している方
- Incoming Webhook を触ってみたい方

#Incoming Webhook とは

Incoming Webhook は、外部ソースからの情報を簡単にワークスペースと共有する方法です。

- 選択したチャンネルにデータを送信する
- Webhook メッセージの書式を設定してチャンネルの他のメッセージよりも目立たせる
- メッセージテキストとその他のオプションを含むJSONペイロードのHTTPリクエストを送信できる  
（[公式サイト](https://slack.com/intl/ja-jp/help/articles/115005265063-Slack-%E3%81%A7%E3%81%AE-Incoming-Webhook-%E3%81%AE%E5%88%A9%E7%94%A8)より引用）

#設定手順

主な手順は以下の通りで進めていきます。
　1. Slackアプリを作成する
　2. 「Activate Incoming Webhooks」をオンにする
　3. アプリ投稿先のチャンネルを選択し、「許可する」をクリックする
　4. Slackにメッセージを投稿する

##1. Slackアプリを作成する

[Slack API](https://api.slack.com/apps)の画面から「**Create New App**」ボタンをクリックする。
表示されたモーダルウィンドウにて「**From scrach**」を選択する。
![01.CreateApp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/3c97f0c9-9e32-da90-6cef-02b5a7405dd4.png)
次に表示されたモーダルウィンドウにて、以下を入力して「**Create App**」ボタンをクリックする。

**App Name**：アプリ名を入力（ここでは、Sample Appとしています）
**Development Slack Workspace**：ワークスペースを選択
![02.AppName_Workspace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/e52f23f5-2387-e199-a18d-07fcac0d3cd0.png)

##2. 「Activate Incoming Webhooks」をオンにする

1 にてSlackアプリを作成すると、作成したアプリ詳細画面が開くので、
右上の「**Incoming Webhooks**」を選択する。
![03.IncominigWebhooks.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/1cc4b3d1-2a9b-2b43-47f1-9696070fec19.png)
「**Activate Incoming Webhooks**」のスイッチコントロールを `Off` → `On` に変更する。
変更すると非表示になっていた画面が表示されるので、
スクロールして「**Add New Webhook to Work space**」をボタンをクリックする。
![04.ActivateIncomingWebhooks.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/b0f450c7-52af-7354-1dab-bd6d26fa3cfd.png)

##3. アプリ投稿先のチャンネルを選択し、「許可する」をクリックする

2 にてボタンをクリックすると、
投稿先のチャンネルを選択するモーダルウィンドウが表示されるので、
プルダウンから任意のチャンネルを選択し、「**許可する**」ボタンをクリックする。
![05.SelectChannel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/0484b15a-15fe-4b5b-2535-17dc950b2af3.png)

Slackアプリの設定はこれで終わりです。

##4. Slackにメッセージを投稿する

ターミナルを開き、下記に表示されているコマンドを実行する。
（**ok**と返ってくれば、成功です！）

```:コマンド
curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' YOUR_WEBHOOK_URL_HERE
}
```
※`YOUR_WEBHOOK_URL_HERE` は選択したチャンネルのWebhook URLを入力してください。
![06.WebhookURL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/254a8900-56be-cb78-9fe2-9251c6e69619.png)

コマンドを実行し、選択したチャンネルを開くと、
作成したアプリ「**Sample App**」からメッセージが投稿されていることを確認できます。

コマンドの`"text"`の値を変更すれば、投稿されるメッセージも変わります！
![07.SlackMessage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/a192c57a-4e30-ae5c-a675-4c6b7e0fd28e.png)

#さいごに

Slackで Incoming Webhookの設定方法を紹介しました。
次回、GASからSlackへのメッセージ投稿を行う方法について記事化したいと思います。

#参考サイト

- [Slack での Incoming Webhook の利用](https://slack.com/intl/ja-jp/help/articles/115005265063-Slack-%E3%81%A7%E3%81%AE-Incoming-Webhook-%E3%81%AE%E5%88%A9%E7%94%A8)
- [Sending messages using Incoming Webhooks](https://api.slack.com/messaging/webhooks)
glTF に audio を埋め込みたいメモ

メタバースで NFT で 3D モデルのビックウェーブに乗らねば!

3D model に glTF 使うの増えているっぽ?

音声も glTF に埋め込みたいけどどうすれば...?

## extension

glTF に audio データの直接の対応はありません.
 
https://github.com/KhronosGroup/glTF/issues/1582

現時点(2022/01/19)では, `MSFT_audio_emitter` , `OMI_audio_emitter` が提案されています.

`OMI_audio_emitter` 拡張が active そうですね.

https://github.com/omigroup/gltf-extensions/pull/1

どちらの拡張も音声再生できるのは viewer によります. Godot Engine 自体は `OMI_audio_emitter` 対応するっぽそう?
LaravelでSQL Server（Azure SQL Database）のシーケンスを取得

ググっても見つからなかったのでメモ。
こんな感じで取れました。

```
$sql = "
DECLARE @next_val BIGINT = NEXT VALUE FOR sequence_test;
SELECT @next_val AS next_val;
";
$test = DB::connection('sqlsrv_test')->select($sql);

echo $test[0]->next_val;
```

もっといいやり方があれば更新します。
【ターミナル操作】bash⇄zsh ログインシェルの変更方法

# ターミナルを開くと何か言われた

今まで気付いていなかっただけかもしれないけど、ターミナルを開いたら何か表示されていたので読んでみた。

```
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
```
デフォルトのシェルは`zsh`ですよって教えてくれているようです。
（macOS 10.15 Catalina以降はデフォルトのログインシェルが`zsh`、それまでは`bash`）

# シェルって？
> シェル（英語: shell）はオペレーティングシステム（OS）があるような高機能なコンピュータにおいて、ユーザーのためにインタフェースを提供するコンピュータプログラムであり、オペレーティングシステムが提供する機能へのアクセスを提供する。

Wikipediaを読むとなんだか難しく感じるけれど、簡単に言うとターミナルなどでコマンドを入力することで動くプログラムのこと。

# 現在使用しているログインシェルを確認する

```
$ echo $SHELL
/bin/bash
```
この場合だと、ログインシェルは`bash`の状態。

# 使用可能なシェルを確認する
ホスト上で使用出来るシェルの一覧を確認してみる。

```
$ cat /etc/shells

/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
```

（色々あるようだが、正直シェルを意識して使用したことがないので`zsh`と`bash`くらいしか馴染みがない…。）

# ログインシェルを変更する
ログインシェルを変更するコマンドは`chsh`。
オプションで`-s`の後に変更したいシェルを指定することが可能。

`zsh`に変更してみる。（パスワードの入力を求められます）

```
$ chsh -s /bin/zsh
Changing shell for *****.
Password for *****:
```

再度ログインシェルを確認してみる。

```
$ echo $SHELL
/bin/bash
```
コマンドを叩いただけでは変更されないようです。

# ログインシェルの変更を反映する
**ターミナルを終了し、起動し直す**、という手順が必要。


```
$ echo $SHELL
/bin/zsh
```
変更が反映され、ログインシェルが`bash`から`zsh`になりました。

## VSCodeのターミナルだとうまくいかない？
VSCodeのターミナルだと、ターミナルを起動し直しても、VSCode自体を起動し直しても、変更が反映されず。

設定がどうなっているか確認してみる。

```
chsh
```
オプションを付けずに`chsh`コマンドを叩くと、vimで設定ファイルが開きます。

```
# Changing user information for *****.
# Use "passwd" to change the password.
##
# Open Directory: /Local/Default
##
Shell: /bin/zsh
Full Name: *****
Office Location:
Office Phone:
Home Phone:
```

`Shell`は間違いなく`zsh`に変更されているようなので、うーーーん。
その後、何を試しても変更が反映されないので、ダメ元で**PC自体を再起動**してみた。


そして確認。

```
$ echo $SHELL
/bin/zsh
```
### 変更された！

## 設定変更の反映まとめ

通常のターミナルは　**ターミナルを終了し、起動し直す**
VSCodeのターミナルは　**PCを再起動する**
【Access VBA】kernel32.dllを用いてSleepをモジュールで使用できるようにする。


自分用のメモとして残します。

普段はwebエンジニアなので、久しぶりに使用しようとしたときに面倒だったのでメモします。


#やり方

##1.kernel32を宣言
**モジュールの一番上に下記を追記↓**

```
#If VBA7 Then
    #64bitのoffice用
    Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As Long)
#Else
    #32bitのoffice用
    Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
#End If

```
##2.Sleepを任意の箇所で呼び出す
同モジュール内で呼び出す。

```
Function hoge()
    #ミリ秒
    Sleep 5000 

End Function
```

SleepのリファレンスURL
https://docs.microsoft.com/ja-jp/windows/win32/api/synchapi/nf-synchapi-sleep


以上です。

#余談
kernel32に限ったことではありませんが、コアとなるライブラリで何が使えるのか一通り目を通しておいた方が、貧弱VBAくんの手助けにもなるかもですね。
【Gradle】Dependency Management Pluginでライブラリの利用する依存が意図せず書き変わった状況への対処【Spring Boot】

# TL;DR
- `Dependency Management Plugin`は`Spring Boot Gradle Plugin`などから読み取ったバージョンでライブラリの利用する依存も書き換える
- これによってライブラリの利用する依存が意図せず書き変わることがある
- 書き換えられると困るライブラリは`dependencies`に追加することで対処できる

# 本文
## 起きた問題
`Spring Boot Gradle Plugin` + `Dependency Management Plugin`の環境で、利用しているライブラリに不思議なエラーが発生しました。

## 原因
調査の中で`./gradlew dependencies`の出力を確認した所、当該のライブラリが利用している依存のバージョンが下がっており、これによって当該のエラーが発生していることが分かりました。
下がった先のバージョンは`./gradlew dependencyManagement`の出力に記載されていたものと一致しました。

冒頭に書いた通り、`Dependency Management Plugin`は`Spring Boot Gradle Plugin`などからバージョンでライブラリの利用する依存も書き換えます。
本来であれば、これによってプロジェクト全体のライブラリバージョンが揃えられることで、互換性による問題が回避されます。
一方、今回は書き換えによってエラーが発生していました。

## 対処
一番簡単な対応方法は、バージョンが書き変わると困るライブラリを`dependencies`に追加することです（例では適当なライブラリを追加しています）。

```diff_kotlin:build.gradle.kts
dependencies {
+  implementation("com.squareup.okhttp3:okhttp:4.9.3")
}
```

その他の書き換え方法はドキュメントに記載があります（個人的に`ext`を書き換える方法も試しましたが、ドキュメントで言及されている通り、`Spring`の方で定義されているプロパティが優先されてしまって機能しませんでした）。

https://docs.spring.io/dependency-management-plugin/docs/current/reference/html/#dependency-management-configuration-bom-import-override-dependency-management
MediaPipeのFACE_CONTOURSでトラブった話

# トラブル内容

https://github.com/google/mediapipe/tree/master/mediapipe/python/solutions

こちらのサンプルでフェイスメッシュして遊ぼうとしたら、
エラー吐いて落ちる現象。

```
AttributeError: module 'mediapipe.python.solutions.face_mesh' has no attribute 'FACE_CONTOURS'
```
#環境
* Windows 10 64bit
* Python 3.9.1

#解決方法
海外サイトを漁っていたら見つけた情報。
「Update: FACEMESH_CONTOURS is the correct new name.」

サンプルのfacemesh.pyの３５行目あたり、
FACE_CONTOURSをFACEMESH_CONTOURSに書き換えたらすんなり動いた。

```
connections=mp_face_mesh.FACEMESH_CONTOURS ,
```
必要な .class ファイルから間接的に参照されています

エラー解消に時間がかかったのでメモ。
ビルドパスのエラーの可能性があるのはわかっていたのですが…。

今後はjavaのビルド・パスを見て、
JREシステム・ライブラリがアンバインドとなっていないかを真っ先に確認すること:zap:

「アンバインド済み」という言葉があった場合は、
一旦除去して同じライブラリ（or Jar）を入れなおすと治ります。
【RSpec】変数名を付けながら大量のデータ作成したとき

##instance_variable_set

テストで変数名を付けながら大量のデータを作成したいときに便利。

```ruby
(Date.new(2022, 1, 1)..Date.new(2022, 1, 31)).each_with_index do |date, i|
  instance_variable_set("@date#{i+1}", date)
end

@date1 #=> Sat, 01 Jan 2022
@date2 #=> Sun, 02 Jan 2022
@date3 #=> Mon, 03 Jan 2022
...
```


##参考

https://docs.ruby-lang.org/ja/latest/method/Object/i/instance_variable_set.html

https://qiita.com/yosaprog/items/c008c709e851c9e7c717
全画面表示時のview崩れ対策

#はじめに
今回、自分はStatusBarを透過させた状態でViewをStatusBarに被せて表示をさせる際に、単一Activity複数Fragmentで実装していたため、動的にStatusBarの状態を変更していたところ、被せて表示させていない画面から被せて表示させたい画面に遷移し、その後被せて表示させていない画面に戻ったとき、BottomNavigationのViewが大幅に崩れてしまっていたため、その解決策を備忘録として置いておきます。

###実装状態
まず、自分の場合に行っていたStatusBarの透過処理とViewの被せて表示する方法を記述しておきます。

```kotlin:
// 画面全体表示設定trueの場合被らず表示、falseの場合被せて表示
        WindowCompat.setDecorFitsSystemWindows(window, true)
// StatusBarの文字色を変更trueの場合白、falseの場合グレー
        val wic = WindowInsetsControllerCompat(window, window.decorView)
        wic.isAppearanceLightStatusBars = true
// 透過させたいのはStatusBarだけなのでNavigationBarは透過させていない
// しかしWindowCompat.setDecorFitsSystemWindows(window, true)は問答無用で全画面表示に適応させるため
// bottomにmarginを入れてあげないとViewが崩れてしまうので、下記の設定によりView崩れを阻止
        binding.root.setOnApplyWindowInsetsListener { rootView, windowInsets ->
            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())
            rootView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
                bottomMargin = insets.bottom
            }
            WindowInsets.CONSUMED
        }
```

###解決方法
さて、ここからが本題です。
最初は、BottomNavigationが崩れてしまうのは`setOnApplyWindowInsetsListener`への設定が残ってしまっているからだと思い、`onDestroyView`でマージンを上書きする様にコードを書きましたが、それでもViewは崩れたままでした。
そこで解決策となるのが下記のコードです。

```kotlin:
binding.bottomNavigation.setOnApplyWindowInsetsListener(null)
```
こちらを設定してあげることにより`BottomNavigation`にも設定されてしまっていた下部へのマージンを上書きし、View崩れを直すことができました。

###最後に
Android30から`SystemBar`関連に色々と調整が入り、今まで設定していたものができなくなっていってしまう中、公式から出されている`hide`と`show`は従来の実装とは大幅に変わってしまうものでした。
なので、従来の実装とは変わらずにできる方法を探したところ今回の様な内容になりました。
何かの手助けになれたら幸いです
@google-cloud/bigquery などのライブラリを利用した際に発生した「Type 'void' is not assignable to type 'this'」的な型エラーについて

## 起こった現象

Node.js で `@google-cloud/bigquery` を利用していると、ある日突然このような型エラーが発生するようになった。

```
node_modules/@google-cloud/paginator/build/src/resource-stream.d.ts:37:5 - error TS2416: Property 'end' in type 'ResourceStream<T>' is not assignable to the same property in base type 'Transform'.
  Type '(...args: any[]) => void' is not assignable to type '{ (cb?: (() => void) | undefined): this; (chunk: any, cb?: (() => void) | undefined): this; (chunk: any, encoding?: BufferEncoding | undefined, cb?: (() => void) | undefined): this; }'.
    Type 'void' is not assignable to type 'this'.
      'this' could be instantiated with an arbitrary type which could be unrelated to 'void'.

37     end(...args: any[]): void;
       ~~~
```

原因は `@types/node` の https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57473 の変更で、これは `readable.destroy()` と `readable.end()` の返り値が、Node.js の仕様上は `this` であるのに対し、 `@types/node` 上の型定義だと `void` になってしまっている問題を修正するもの。
2022/01/19 時点では `@google-cloud/paginator` の型定義がこの変更に追従できておらず、型エラーを起こしてしまっている。

## 回避策

`@types/node` はマイナーバージョンまでは Node.js のバージョンと一致してるが、パッチバージョンは修正があるたびにインクリメントする事になっている。
そのため、この問題を回避するには https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57473 の変更が行われる前の `@types/node` のパッチバージョンに固定すると良い(健全ではない)。
具体的には `12.20.39` と `14.18.3` が直前のバージョンに該当する。

## よくわからん

`@types/node` と Node.js の LTS の関係をよく知らないのでわからなかったけど、この変更は現在の Node.js の LTS であるところの v16 系には含まれていない。なんでなんだろ
PR を出そうと思ったが、 `@google-cloud/paginator` の現在の Node.js のバージョンが v16 系になっており、 https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57473 の変更が降ってこないのでどうしたものか……となってしまった

## 本来はどうなるべきなの？

本来はすべてが Node.js の仕様に準ずる形になるのが妥当ですが、影響範囲が広すぎるので、https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57473#issuecomment-1010494671 でも提案されているように

> Base type has relaxed definitions like `end(): this | void`. It might miss some errors of type usage.

あたりの落とし所が実現すると世界が平和になるなあと思います。

## 追記(2022/01/25)

[`@types/node` v16 系にもこの型定義の変更を取り込むように提案する PR が作られました](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/58358)

## 追記
https://github.com/googleapis/nodejs-paginator/issues/308 でこの問題は修正されました！ :tada:
[Firebase + NestJS] jsonwebtokenがいきなりタテついてきた件

## あらすじ
いつものように開発していたが、突如github actionが落ちた・・・
何事かと中身を見ると下記エラーが発生していた。

```bash
src/auth/firebase.guard.ts:57:22 - error TS2339: Property 'email_verified' does not exist on type 'string | JwtPayload'.
  Property 'email_verified' does not exist on type 'string'.

57         if (!decoded.email_verified)
```

*む！？*

ちなみに該当コードの前後はこんな感じ
firebaseの認証を使っていて、jsonwebtokenというパッケージを使って
jwtを公開鍵で検証したあと取り出したデータの中身を検証する場所だった。

```typescript
jwt.verify(jwtToken, cert, { algorithms: ['RS256'] }, (err, decoded) => {
  if (err) throw new BadGatewayException(err);

  if (!decoded.email_verified)
    throw new BadGatewayException(
      'Auth Error: メール認証がされていません',
    );
```

## 解決法
エラーの内容を見るに、

```
stringまたはJwtPayloadらしいけど、
stringだったらemail_verifiedなんてプロパティねぇぞ！
```
って意味です。

ですので、string型である可能性を潰してあげましょう

```typescript
jwt.verify(jwtToken, cert, { algorithms: ['RS256'] }, (err, decoded) => {
  if (err) throw new BadGatewayException(err);
  
  // ここから
  if (typeof decoded === 'string')
    throw new BadGatewayException('認証エラー__jwtデコード失敗');
  // ここまで

  if (!decoded.email_verified)
    throw new BadGatewayException(
      'Auth Error: メール認証がされていません',
    );
```

## あとがき
コードの変更ほとんどしていないのに、急にビルド通らなくなるから焦りました。
同じところでハマってる方のヘルプになれば幸いです。
ちなみにどういう時stringの型としてデータが入るかまでは検証していません。
詳しい方いたら教えてください。

## 補足
JwtPayloadの本来のお姿はこっちでした。

```typescript
export type VerifyCallback<T = JwtPayload> = (
    err: VerifyErrors | null,
    decoded: T | undefined,
) => void;
```
【AWS】LambdaからCognitoユーザーを削除する

LambdaからCognitoユーザーを削除することがあり、少し手間取ったので残しておきます。

## 前提
 - **Cognitoの削除が可能なポリシーをLambdaのロールにアタッチしていること。**
 - ※今回はAWS管理ポリシーの AmazonCongitoPowerUser をLambdaのロールにアタッチしています。
 - LambdaのランタイムはNode.js 14.x です。

## Lambdaのコード

```javascript:index.js
let aws = require("aws-sdk");

exports.handler = async (event) => {

    // eventから削除するCognitoユーザーのユーザー名リストを受け取る
    let userNameList = event.userNameList;

    // Cognitoユーザーの無効化メソッドをコール
    await disalbeCognito(userNameList);

    const response = {
        statusCode: 200,
    };
    return response;
};

/**
 * Cognito情報を無効化し、ログインできないようにする
 */
async function disalbeCognito(userNameList){

    if (userNameList.length > 0) {
        // Cognitoを使う準備
        aws.config.update({
            region: 'ap-northeast-1',
        });
        const cognito = new aws.CognitoIdentityServiceProvider({
            apiVersion: '2016-04-18'
        });
        // 対象のCognitoユーザープールID
        const user_pool_id = "hogehoge";

        for (let userName of userNameList) {
            // ユーザー削除
            try {
                await cognito.adminDeleteUser({
                    UserPoolId: user_pool_id,
                    Username: userName
                }).promise();
                console.log("Success! userName : " + userName);
            } catch (err) {
                console.log("Failed! userName : " + userName);
                if (err.code == 'UserNotFoundException') {
                    // ユーザープールにユーザーが存在していない場合
                    console.log('UserNotFoundException');
                } else {
                    // その他のエラー
                    console.log(err, err.stack);
                }
                throw err;
            }
        }
    }
}
```
意外とハマってしまった比較演算子のタイポ=>｜デバッグの記録

単純なタイポですがjavascriptで遭遇し恥ずかしながら少しハマったので
改めて原因や対策などをまとめてみます。

# >=が正解
aはb以上はa >= b。
aはb以下はa <= b。

大なりイコールと読み方で覚えるのや
アロー関数と逆という覚え方も良いかも。
これでも実際コード見ている時は映像として馴染んでしまってわかりづらいので
やっぱり後述するIDEのLintをしっかり設定するのが最優先だと思います。
特にPHPのアロー演算子=>やjavascriptのアロー関数=>をいじってたりすると
目がなれてしまって見逃しがちなんですよね。。。と言い訳してみる。

# 状況
window.innerWidthで判定している部分でそれをresizeイベントで呼び出していました。

```changeWidth.js

const changeWidth = () => {
    const nowWidth = window.innerWidth;

    if (nowViewPortWidth => 768) {
        alert("判定true")
    }
}
window.addEventListener('resize', changeWidth);

```

これでどのような動きになったかというと
ぬるぬる動きながらランダムにバグ的な動きが発動するという感じでした。

具体的な動きを書くと、changeWidthはresizeイベントで設定している関数ですが
スクロールしたときに発動し「判定true」が表示され、そのタイミングがよくわからない
（早くスクロールすると発動したり、トップに移動したときに発動したり、はたまたしなかったり）
という状況でした。

# resizeはiosでスクロールでも発動する
こちらの独特な挙動もあり、原因を特定するのに手惑いました。
[iOS Safariでスクロールしただけでリサイズイベントが発生する原因と対処法](https://qiita.com/tonkotsuboy_com/items/d32ec6e7a1f6f592d415)

# IDEにESLintが設定されていなかった。
ESLintが設定されていないと警告も出ないんですね。
またデベロッパーツールでも特に警告もエラーも出ていませんでした。
個人的にはこの辺りがハマりポイントだな〜という感じがしています。

[PhpStorm](https://pleiades.io/help/phpstorm/eslint.html#ws_node_docker_lint)
[WebStorm](https://www.jetbrains.com/help/webstorm/eslint.html#ws_js_eslint_verify_code)

上記のページを参考にESLintを設定したら無事警告を出してくれるようになりました。

# 所感｜自戒
IDEの設定は継続的に見直した方が良さそう。
複数のバグが重なると原因がよくわからなくなる傾向があるので問題の切り分けを細かくしたほうがよい。
デベロッパーツールでも捕捉されず動くバグがあるということを忘れない。
【AWS認定試験】ANS-C00取得しました

# はじめに

先日ANS-C00を受験し、取得することができました。
ネットワークの経験はあまりありませんが取得できたので、同じような方の参考になればと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/51bcfd52-8310-bc48-f623-d59f742d9eb5.png)

## これまでのAWS認定受験歴
|年月|試験|点数(合格点)|合否|
|---|---|---|---|
|2020/08|AWS認定クラウドプラクティショナー(CLF)|809/1000(700)|〇|
|2020/11|AWS認定ソリューションアーキテクトアソシエイト(SAA)|753/1000(720)|〇|
|2021/01|AWS認定デベロッパーアソシエイト(DVA)|862/1000(720)|〇|
|2021/02|AWS認定SysOpsアドミニストレータアソシエイト(SOA)(C01)|731/1000(720)|〇|
|2021/04|AWS認定ソリューションアーキテクトプロフェッショナル(SAP)|698/1000(750)|×|
|2021/06|AWS認定ソリューションアーキテクトプロフェッショナル(SAP)|832/1000(750)|〇|
|2021/06|AWS認定DevOpsエンジニアプロフェッショナル(DOP)|821/1000(750)|〇|
|2021/09|AWS認定セキュリティ専門知識(SCS)|798/1000(750)|〇|
|2021/11|AWS認定データベース専門知識(DBS)|756/1000(750)|〇|
|2022/01|AWS認定高度なネットワーキング専門知識(ANS)←★new!|848/1000(750)|〇|

## 試験対策

### 勉強時間
約30H

### やったこと

以下を利用しました。

- AWS WEB問題集で学習しよう

https://aws.koiwaclub.com/

こちらのプロフェッショナルに登録して問題集を繰り返し解きました。
初めて利用させてもらったのですが、7問1区切りの1問1答で効率よく勉強できたような気がします。
こちらの問題集を解きつつ、わからないネットワークの専門用語を調べました。

全体を通して3週は解いたと思います。

- Udemy

https://www.udemy.com/course/practice-exam-aws-certified-advanced-networking-specialty/

上記問題集だけでは不安だったので、試験前々日から前日にかけてUdemyも利用しました。
65問の模擬問題があったので最終調整のような形で利用しました。
一部KoiwaClubではカバーできていなかったものもあったのでやってよかったと思います。

- BlackBelt

大正義BlackBeltも利用しました。
ANSではオンプレとAWS間の通信も問われるようでしたので、DirectConnectのBlackBeltを中心に観ました。

https://www.youtube.com/watch?v=mEtluVrgXlk

https://www.youtube.com/watch?v=IEQ1ZM93DMo

# 感想

今回の勉強・試験を通してネットワークの知識が少しはついたような気がします。特にDirect Connect周りの知識が付きました。
試験としては、他の方もおっしゃっているようにちょっと古いなという印象でした。というのも、C-00で開始されてから一度もアップデートされていないよう？なので今なら違うやり方があるのでは？と思う問題もありました。
難易度は、ほかの専門知識と同等レベルだと感じました。SAPよりも難しいという声も見かけるのですが個人的にはSAPの方が難しかったです。