OmniAICreator/Qiita-1.07M huggingface dataset:
AWS上に構築した IBM Security Verify Access のリソース監視を行う① 

# はじめに

以前 Amazon Marketplaceに公開されているAMIイメージを利用して、AWS上に IBM Security Verify Accessの検証環境を構築しました。

[Amazon EC2 に IBM Security Verify Access の検証環境を構築する](https://qiita.com/fitz/items/718d88b4e863f6721251)

今回は構築したIBM Security Verify Accessのリソース監視について調査しました。


# AWS Cloudwatchのメトリクスについて
AWS Cloudwatchのメトリクスとして、標準メトリクスとカスタムメトリクスがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/efe57be7-58f8-0dd8-66ee-1845c634667e.png)
(参考・引用元)
標準/カスタムの差異がわからない状態で拝見して大変参考になりました。
[CloudWatchの標準メトリクスでEC2インスタンスのメモリ使用率はなぜ取得できないのか](https://qiita.com/mittsukan/items/5185a119f9a22a0c88ff)　
[20190326 AWS Black Belt Online Seminar Amazon CloudWatch](https://www.slideshare.net/AmazonWebServicesJapan/20190326-aws-black-belt-online-seminar-amazon-cloudwatch?startSlide=24)

ISVAでCPU使用率、メモリ使用率、ディスク使用率を監視するためには、標準メトリクス、カスタムメトリクスの両方が必要です。


|分類  |監視対象  |Cloudwatch Agent要否 |参考  |
|---|---|---|---|
|標準メトリクス  |CPU使用率  |不要|[インスタンスメトリクス](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html#ec2-cloudwatch-metrics)  |
|カスタムメトリクス |メモリの使用率　ディスクの空き容量  |必要|[CloudWatch エージェントにより収集されるメトリクス](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/metrics-collected-by-CloudWatch-agent.html)  |


# IBM Security Verify Access Extension for Amazon CloudWatch Agentについて

ISVAはアプライアンス製品のためCloudWatch Agentをインストールすることができません。
代わりに、Extensionという形式でAmazonCloudWatch Agentをサポートしていました。
[Amazon CloudWatch サポートの構成](https://www.ibm.com/docs/ja/sva/10.0.5?topic=activities-configuring-amazon-cloudwatch-support)

IBM Security Verify Access Extension for Amazon CloudWatch Agentは、 IBM Security App Exchange からダウンロードできます。
[IBM Security Verify Access Extension for Amazon CloudWatch Agent ](
https://exchange.xforce.ibmcloud.com/hub/extension/7e7da8c3ba8a8d05ab7ffe8baf84ce79)

# 次回について
次回は、Extensionのインストールについて紹介したいと思います。

# 参考
- [CloudWatchの標準メトリクスでEC2インスタンスのメモリ使用率はなぜ取得できないのか](https://qiita.com/mittsukan/items/5185a119f9a22a0c88ff)
- [20190326 AWS Black Belt Online Seminar Amazon CloudWatch](https://www.slideshare.net/AmazonWebServicesJapan/20190326-aws-black-belt-online-seminar-amazon-cloudwatch?startSlide=24)
- [インスタンスメトリクス](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/metrics-collected-by-CloudWatch-agent.html)
- [Amazon CloudWatch サポートの構成](https://www.ibm.com/docs/ja/sva/10.0.5?topic=activities-configuring-amazon-cloudwatch-support)
- [IBM Security Verify Access Extension for Amazon CloudWatch Agent ](
https://exchange.xforce.ibmcloud.com/hub/extension/7e7da8c3ba8a8d05ab7ffe8baf84ce79)
【AtCoder入茶記事】地方国立大数学科のAtCoder挑戦記 -入茶編-

# 1.挨拶
どうもこんにちは、TsubakiMintです。
AtCoderを初めて一つ目の目標としていた入茶を達成しましたので、入茶記事というものを書きます。

# 2.自己紹介
- ハンドルネーム:TsubakiMint
- 所属:地方国立大の理学部数学科学部生
- 使用言語:Python3
- 競プロを始めた時期:2022年12月

# 3.競プロを始めた理由
僕は実は競プロを始めるまでプログラミングが全くできませんでした。具体的には「大学のJavaの授業で途中から分からなすぎてバックれ、単位は貰えたが最低評価」、「大学のCの授業で同様の理由でバックれ、落単」くらい酷かったです。
このままではよくないと思い、プログラミングの勉強を真面目にやろうと思いました。しかし、ただ勉強するだけでは飽きてしまうと思いました。勉強の成果がコンテストの結果として返ってくる競プロはうってつけだったのです。
また、言語は直感的に書ける（と調べたら書いてあった）Pythonを選びました。

# 4.入茶するまで
## 4.1.コンテスト初参加まで
- 言語はPythonを使用すると決まったので、PC上に統合開発環境（IDE）であるPyCharmを導入しました。
- 次に、プログラミングの基礎（文字列、数値、リストなど）とPythonの基本的な文法を勉強しました。
- その後、ABC042以降のA問題を20問くらい解きました。最初はB問題など到底解けませんでした。
- A問題を20問くらい解き、B問題もやってみると、いくらか解けるB問題もありました。

## 4.2.ABC初参加
ABCの初参加はABC281（2022/12/10）です。
![48BB024D-63A1-4397-AA78-148D29E05048.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/fc12c51d-3a25-93dd-f2d9-04ccece9b4e3.jpeg)
![B8CE6420-CF37-42A7-8920-C380B1D26807.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/3e0c6956-fa33-2d62-74f1-329cb37b10c8.jpeg)
なんと、C問題が解けてしまいました。この当時はやはり感動しました。

この辺りで、ひとまず入茶を目指そうと心に決めました。

## 4.3.入茶までにしたこと
- 競プロの参考書を購入する
競プロを本格的にやるにあたって買っておいた方が良いだろうと思い、米田優峻さんの『競技プログラミングの鉄則』（所謂「鉄則本」）を購入しました。丁度クリスマスの時期だったので、親にクリスマスプレゼントとして欲しいと言ったら買ってくれました。（21歳にしてクリスマスプレゼントを貰いました。）
鉄則本を前から読み、難しい所は飛ばして読みました。
- AtCoder Problemsを使って丁度いい難易度の問題を沢山解く
書いてある通りです。最初はABCのAB問題をやりました。レートが200を超えてからは灰diff上位〜茶diffをひたすら解きました。
- 他の人の色変記事を読む
色々読みました。問題演習の方法など、参考になる部分も多々ありました。

## 4.4.入茶
僕が入茶したのはABC286（2023/01/21）です。ちなみに、ABC286は1位に100万円の賞金がかけられていました。
![76BA1B04-5E9A-41B5-AADC-4781C59DE9C0.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/2f8f7835-be1b-41f2-50c0-8b4ec93e318f.jpeg)
![72670E9D-ED1B-42C4-B0B9-8B2A1BF5DAC7.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/ef3ecdf3-fda2-8f8f-8cd9-bcb3e53bd999.jpeg)
このコンテストで4完をし、コンテスト6回目の参加にして無事入茶することが出来ました。
ABC284からはD問題も（茶diff程度なら）解けるようになっていたので、いけそうだなとは思っていました。

## 4.5.入茶の次の日のARC
ABC286で入茶した次の日のARC154（2023/01/22）に参加しました。
![8CE6950B-8E3D-4536-BA09-D539E6437AE7.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/81ce1c51-4344-3628-07c0-7c96eb5e9014.jpeg)
![8D84A1C6-BC4E-4AB6-830A-68BB4C7B80A0.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3094206/7fe31595-8488-d081-9a6b-cc5f3499112b.jpeg)
結果はABの2完でパフォーマンスは1351と水パフォを出すことが出来ました！とても嬉しかったです。
レートが637に上がり、早くも緑が見えてきました。

# 5.今後
今後は緑レート（800）に向けてひたすら精進します。
「鉄則本」の飛ばした所やできていない所をもう一度やろうと思います。

# 6.さいごに
ここまで読んでいただき、ありがとうございました。入緑したらまた記事を書くかもしれないので、その時はよろしくお願いします。
Node.jsの基礎をまとめる2

前回の続きです。ぜひこちらを読んでから御覧ください。

https://qiita.com/ysk-s/items/be9db685d51aac20e179

クライアントから受け取ったリクエストとレスポンスを引数として受け取り、ブラウザへ処理を返す。

最初に"res.writeHead()を追加する。これはリクエストに対してこういうHead情報を返しますよという関数。

第1引数には200を入れる。これは通信がうまくいってますよというステータスコード。
第2引数にはHeadの中身を入れる。今回はそのレスポンスで返すコンテンツの中身はhtmlファイルですよっていう中身を送る。

それが以下のようなコードになる。

```
    //ブラウザからアクセスが来たときの処理
    res.writeHead(200, {"Content-Type": "text/html"});
```

そして、htmlファイルを読み込ませる。

htmlファイルを読み込ませるにはfsというモジュールが必要になる。
fsモジュールを読み込んでreadFileSync()という関数で非同期処理でindex.htmlのファイルの中身を読み取るという機能をインスタンス化する。

```
const html = require("fs").readFileSync("./index.html")
```

そして、HTMLをレスポンスとして返す処理をcreateServerの中に記述する。

```
//webサーバーを作ろう
const server = http.createServer((req, res) => {
    //ブラウザからアクセスが来たときの処理
    res.writeHead(200, {"Content-Type": "text/html"});
    res.write(html);
    res.end();
});
```

res.end();は終了の記述として必ずいる。

そして、サーバーがリクエストを待っている状態であることを指示するのがlisten()関数である。この場合、PORT番号を8000としている。

```
const http = require("http");
const html = require("fs").readFileSync("./index.html")

const PORT = 8000;

//webサーバーを作ろう
const server = http.createServer((req, res) => {
    //ブラウザからアクセスが来たときの処理
    res.writeHead(200, {"Content-Type": "text/html"});
    res.write(html);
    res.end();
});

server.listen(PORT, () => {
    console.log("server running!")
});

```

そして、nodemonをインストールして、package.jsonのscriptsの部分のnodeをnodemonと変更する。
すると、サーバーを再起動しなくても変更を反映させることが出来る。というか、変更を加えると勝手に再起動してくれるのがnodemon。

```
const server = http.createServer((req, res) => {
    //ブラウザからアクセスが来たときの処理
    res.writeHead(200, {"Content-Type": "text/html"});
    res.write(html);
    res.end();

    if (req.method == "GET"){

    }

    if (req.method == "POST"){
        
    }
});

```

静的なWebサイトをホスティングするサービスはたくさんあるが、クライアントからのリクエストがGETやPOSTなどであったらそれによって処理を変更できるのがサーバーから開発することのメリット。
Contentful CMSを使った感想

### 概要
Headless CMSの数が増えていく中でそれぞれの違いが分からなくなっているため、複数のCMSごとに同一のwebページを作成することでCMSごとのメリデメを明確にしていくプロジェクトを始めました。

その際CMSの1つとして採用した「Contentful CMS」が初心者には理解の難しいコンセプトだったため、理解を深めるためにアウトプットします。

### Contentfulとは
ドイツのスタートアップが開発したHeadless CMSです。CMSに保存できる言語の数がかなり多いことが特徴です。

ドキュメントや管理画面は日本語対応していないため、英語を読めないと使えません。

### Contentfulは何がいいの？
カスタムコンテンツをたくさん作れる & コンテンツ同士を参照できるため、管理できる情報がブログの記事やニュースに留まらず、例えばページ内のコンテンツ全て（見出しテキストや画像..etc）管理することができます。

また、**参照の機能を使い、定義したデータをコンポーネントのように使い回すことで複数のページにわたって使われるコンポーネントのpropsをCMS上で簡単に管理することができる**点がContentful CMSの最大の特徴かなと思います。
実際、他のCMSでもコンポーネントのpropsを管理することはできますが、参照の機能がないため、例えば同じ画像を再アップロードしなければならなかったり、同じテキストを再度入稿しなければならなかったりします。

また、gitのようにコンテンツをブランチごと（CMS上の言葉では「環境ごと」）に設定できるため、本番で表示しているデータと、ローカルで表示されるデータを分けて閲覧することができます。

※ただし、多機能なのでこれが正解！といった言い方はできませんので、他の使い方もあると思います。

### CMSの設計工数

機能が多いため、設計難易度は他のCMSと比べて高い。

１つのコンテンツを管理するのに、大きく以下の3つを設定する必要がある

- スペース（アプリケーションごとに分けて使う）
- 環境（バージョン管理に使う）
- 言語

特に初心者には使いこなすのに時間がかかる

### 他のCMSと比べた時のメリットデメリット

▼メリット

- 無料枠がかなり大きい
- データの参照機能により、登録ずみのデータを使い回しやすい
- バージョン管理機能により、開発用のデータと本番用のデータを分けて管理できる
- データが多言語対応している

▼デメリット

- 管理画面が日本語対応していない（ドキュメントも英語のみ）
- ドキュメント上に設定例の記載が少ない
- 高機能のため、エンジニアもクライアントもCMSを理解するのに時間がかかる
microCMSについてメモ

### サマリ

日本製のHeadlessCMS。シンプルなUIで使いやすさはかなり高い。非技術者でも簡単にコンテンツを管理できる。

### 機能

- コンテンツ管理とAPI管理を同時に実現
- 複数アプリのデータを簡単に管理

↓

- コンテンツ管理とAPI管理を同時に実現

コンテンツを修正するだけでAPIのレスポンスも変化する
![](https://storage.googleapis.com/zenn-user-upload/cf3b23e2a3ad-20230121.png)



### 他のCMSと比べた時のメリットデメリット

▼メリット

- 管理画面、ドキュメント共に日本語対応
- 様々な開発言語のチュートリアルが記載されており、クライアントの言語の要望に応えやすい（kurocoCMSのドキュメントにはNuxtのみ記載…）
![](https://storage.googleapis.com/zenn-user-upload/9c1ab7e8753b-20230121.png)

    
- 非技術者にも使いやすいUI（APIを別で管理する必要がない）

▼デメリット

- 無料枠が小さい（2人以上で開発する際は必ず費用がかかる。）
Nuxt - スクロール処理の設定について

### はじめに
スクロールの振る舞いを制御したい時に以下のファイルを修正します。
　app/router.scrollBehavior.js

このファイルは、プロジェクトルートにある`app`フォルダー配下に置く必要があります。

Nuxtにデフォルトで入っているこのファイルの設定は以下のページから閲覧できます。
https://github.com/nuxt/nuxt/blob/2.x-dev/packages/vue-app/template/router.scrollBehavior.js

あるプロジェクトでこのファイルを触ったときに理解に苦しんだのでzennに記事を書きました。

### router.scrollBehavior.jsとは
冒頭でも書きましたが、ルーティングに関する処理でスクロールの振る舞いを変えたいときにこのファイルを触ります。

ファイルの中で関数を`default export`することで、その設定が適応されます。
実はこのファイルは`vue-router`が元となっています↓
https://router.vuejs.org/guide/advanced/scroll-behavior.html

### 何に苦しんだの？
そもそもプロジェクトで実現したかったこととしては
- 同じページ内の遷移は、`smooth`スクロール
- 違うページに遷移後は、該当箇所へ通常のスクロール
でした。

そこで最初に書いたコードはこちら
```
export default function (to, from, savedPosition) {
  let position = false
  if (savedPosition) {
    position = savedPosition
  } else if (to !== from) {
    position = { x: 0, y: 0 }
  }

  // ページ内ではsmoothスクロール
  if (to.hash && to.path === from.path) {
    const element = document.querySelector(to.hash)
    if (element) {
      return window.scrollTo({
        top: element.offsetTop,
        behavior: 'smooth',
      })
    }
  }

  // ページ遷移した際は通常のスクロール
  let offset = {}
  if (to.hash && to.path === from.path) {
    position = {
      selector: to.hash,
      behavior: 'auto',
      offset,
    }
    return position
  }
}
```

しかしこれではうまくいきませんでした。想定していた箇所へ遷移してくれないのです。

原因は、**ページ遷移した際、ページが生成される前にスクロール処理を実行したらスクロールが失敗する**というものでした。

### どういうことか
ページ内遷移では、既にページのDOMが生成されスクロールの処理がいつでも正常に動きます。

しかし、ページ遷移する際は「ページのDOMが生成　→ jsがバインドされる　→ スクロール処理が正常に動く」と、ページ内と比べてスクロール処理が正常に動くまでラグがあります。

そのため、スクロール処理が正常に動かない間にスクロールしようとした際に失敗していたのです。

### どう解決したか
以下のコードへ修正しました

```
export default function (to, from, savedPosition) {
  let position = false
  if (savedPosition) {
    position = savedPosition
  } else if (to !== from) {
    position = { x: 0, y: 0 }
  }

  // ページ内ではsmoothスクロール
  if (to.hash && to.path === from.path) {
    const element = document.querySelector(to.hash)
    if (element) {
      return window.scrollTo({
        top: element.offsetTop,
        behavior: 'smooth',
      })
    }
  }

  // ページ遷移した際は通常のスクロール
  // `triggerScroll`イベントがemitされた際に実行される※`triggerScroll`イベントとは、スクロール処理が動作可能になったことを知らせるイベントです
  if (to.hash && to.path !== from.path) {
    return new Promise((resolve) => {
      this.app.$root.$once('triggerScroll', () => {
        position = {
          selector: to.hash,
          behavior: 'auto',
        }
        resolve(position)
      })
    })
  }
}
```

ちなみに、`triggerScroll`イベント内では`nextTick`が使われているそうです

### 参考記事
こちらは、本内容を理解するのにかなり役に立ちました！
https://qiita.com/yuta-katayama-23/items/6c3dd3f79dc675db2abb
【ABC285_D】 BFS(幅優先探索)で解いてみた 【C++】

[abc285のD問題](https://atcoder.jp/contests/abc285/tasks/abc285_d)をBFS(幅優先探索)を使って解いてみました。
言語はC++です。

UnionFindやDFSを使った別解はこちら。

- [UnionFindを使って解いてみた](https://qiita.com/Sakasu/items/28d153111042c9562bc7 " UnionFindで解いてみた")
- [DFSを使って解いてみた](https://qiita.com/Sakasu/items/6765f09172cad421d171 " DFS(深さ優先探索)で解いてみた")

# Point

1. **a → b → c → aと一巡したらダメ**そう
    * グラフ理論でいうところの**サイクル(閉路)があるかどうかを検出**
2. **探索した頂点をmemo**することでTLE対策
3. **BFS**(幅優先探索)で全頂点を探索してサイクルがあるかを検出
    * **既にvisitedな頂点に再度訪問 -> サイクル有り**
    ```    
       a------>b------>c　　 既に訪問済みの頂点aに対し、aに再訪問するとサイクルができる
       ^---２回目のa---|
    ```      
4. 解けました！

# コード例

```c++:d_bfs.cpp

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
#define rep(i, a, b) for (int i = a; i < b; i++)

int n;
using Graph = unordered_map<string, vector<string>>; //グラフ作成
Graph G;
unordered_map<string, bool> visited; //訪問済みかどうか
unordered_map<string, bool> memo; //TLE対策で訪問済みの頂点をメモ
queue<string> que; //BFSの要

//サイクルが存在すればtrue, 無ければfalseを返す
bool bfs(string start) {
    que.push(start);        //探索の起点となる頂点を筒に入れる
    while(!que.empty()){    //筒が空になるまで≒前頂点の探索が終了するまで
        string s = que.front(); //筒の先頭を保持
        que.pop();              //筒から先頭を取り出す
        visited[s] = true;  //先頭を探索済みに
        for(auto v : G[s]){ //先頭の頂点に隣接する頂点について、探索済みか否かを判定
            memo[v] = true; //探索済みの頂点として記録
            if(visited[v]) {
                return true; //探索済みの頂点であれば、サイクルが存在
                //ex. a---->b---->c---->aは  最初のaでvisited[a]=trueなので、
                //    a---->b---->c 二回目のaではサイクルができる
                //    ^-----------|
            }
            que.push(v);  //先頭に隣接する頂点を筒に格納(次の先頭の候補とする)
        }
    }
    return false;
}

int main(){
    cin>>n;
    vector<string> s(n), t(n);
    rep(i,0,n){
        cin >> s[i] >> t[i];
        //s->tのグラフを作成
        G[s[i]].emplace_back(t[i]);
    }
    rep(i,0,n){
        string start = s[i];
        if(memo[start]) continue; //探索済みの頂点であればTLE対策で無視
        bool closed = bfs(start); //BFSでサイクル判定
        if(closed) {
            cout << "No" << endl;
            return 0;
        }
        visited.clear(); //複数のグラフが存在する可能性があるので毎回初期化
    }
    cout << "Yes" << endl;
    return 0;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2404591/a8526c02-7361-a47e-3700-dad87356ffe1.png)

解けました！
エンジニアインターン6日目

今日も前回と同じようなsql文を修正する作業をした。今日は調子が上がらず、苦労した。完全にメンタルで負けた。そこで、先輩エンジニアは自分に1つの課題に手こずっていると徐々に視野が狭くなり、解決とは遠くなってしまう。そういう時はいっかい頭をリセットさせると効果的。とのことだった。自分は昼休憩をして頭の思考をフレッシュにした。その効果はすぐに得ることができ、いろんなアイディアまで浮かんだ。エンジニアは常にエラーと戦う職業である。だからこそメンタルがとても大事になってくる。長い時間うまくいかなかったら1回その課題から距離を置き、頭をスッキリさせて解決できるように試みよ。そして、何回もチャレンジしよ。そしたら少しずつエラーに対して良いメンタルで迎えられると思う。だからこそ何もできない今が大事だ。エラーを解決することに慣れよう。いろんな思考回路を持とう。良いエンジニアはみんなこの道を通っている。継続して自分も良いエンジニアになれるように努力しよ。
エンジニアと孤独とリモートワーク


近年、リモートワークが普及し、多くの人が自宅や自分のペースで働くことができるようになりました。
しかし、リモートワークには孤独感という欠点もあります。

みなさん、孤独感と聞いてハッとしたあなた。
孤独感は、人間が社会的に存在することが必要であることから生じる現象!!らしいです。
リモートワークをすると、自宅にいるために、社内やオフィスでの人間関係を持つことができなくなり、孤独感を感じはじめます。

そのため、リモートワークをする上では、孤独感やストレスを感じないようにするために、意識的に対策を取ることが重要です。

1. コミュニケーションを取る
リモートワークをする上では、チャットやビデオ通話などを使って、仕事以外のトピックでもコミュニケーションを取ることが重要です。
仕事以外のトピックって何を話していいかわからない。。
そんなあなたには、すごい雑談力という本がおすすめです。（チェックしてね）

2. 社会的なイベントに参加する
リモートワークをする上では、オンラインイベントやミーティングなどに参加することで、社交的な環境を持つことができます。
自分は、オンラインで顔を出したくない人なので、割と抵抗があります。

3. バランスを取る
リモートワークをする上では、仕事とプライベートのバランスを取ることが重要です。十分な休憩をとり、ストレスを感じないようにすることが大切です。
夜までずっとコーディングをしてるなんてこともあるんじゃないでしょうか？
ちゃんと休憩もってストレスを抱えないように！

4. コワーキングスペースを利用する
リモートワークをする上では、コワーキングスペースを利用することで、社交的な環境を持ち、孤独感を軽減することができます。
誰かが周りにいるだけで孤独を感じなくなります。
そして、#新しい人との出会いの場にもなります。
一人寂しくリモートワークをし続け約3年、出会いが欲しい、、そんなあなたにはコワーキングスペースを強くお勧めします。
定期的にイベントやミーティングなどが開催されることで、仕事以外でも交流を持つことができ、新しいアイデアや視点を得ることができます。 また、様々な業種の人々が集まるため、恋愛の出会いの場にもなる可能性もありますよ！

TSUTAYAのコワーキング
https://tsutaya.tsite.jp/store/lounge/
WeWork
https://weworkjpn.com
コワーキングスペース検索サイト
https://coworking-hub.com
[AWS]Lambdaに送られるIot topicのpayloadにtopic名を含める方法

# はじめに
LambdaをトリガーするIot topic ruleのtopic名を取得する必要があったので、そのやり方について調べてみました。

# やりたいこと
Iot topicへのメッセージ発行をトリガーにLambda関数を実行し、そのLambda関数のhandlerのeventに渡されるpayloadに、該当topicのtopic名を含めたい。

図で表すとこのようなイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/20449b6f-9d7d-a0c5-b74d-38f49e09e4e9.png)


# やり方
結論から言うと、topic ruleのクエリでtopic()関数を使うことで実現可能です。

試しにIot topic ruleを作成し、Lambdaトリガーを設定してみます。
Iot Core管理コンソールを開き、「メッセージのルーティング > ルール」をクリックします。
「ルールを作成」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/50b31bd5-3110-9510-3333-55f379cef418.png)

ルール名を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/8a0f6031-affe-f6eb-7649-31d2d45dd37f.png)

「2016-03-23」のSQLバージョンを選択し、以下のSQLステートメントを入力します。
※topic()関数はSQLバージョン`2015-10-08以降`でサポートされているようです

```sql
SELECT topic() as topic, * FROM 'test/topic'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/3d2618e5-b1f9-ae37-aa40-5420c8d04e90.png)

ルールアクションの設定で事前に用意したLambdaを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/432f2bca-8b79-4712-38a7-30b9c8e3dead.png)


# 動作確認
まず対象Lambdaのトリガーに該当Iot ruleが追加されていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/1d505484-7380-5570-bd41-93f656498702.png)

runtimeをpython3.9に設定しているので、以下のコードを作成して、deployします。渡されるpayloadをそのまま出力する処理です。
```python
def lambda_handler(event, context):
    print(event)
```

IoT Core管理コンソールに戻り、「MQTTテストクライアント」をクリックして、「トピックに公開する」タブをクリックします。
トピック名に「test/topic」を入力し、メッセージペイロードに以下のメッセージを入力します。
```json
{
  "message": "hello world"
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/2a6f7a5e-9c24-0714-3714-875ebb0f3c67.png)

「発行」をクリックすると、対象Lambdaが実行されます。

CloudWatchロググループで対象Lambdaの実行ログを見てみると、以下のようにtopic名がpayloadに入っていることがわかります。（eventをそのままprintしているので、pythonのdictとして出力されています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/c8d18232-62aa-4be7-634a-f845a845f1d6.png)

さらに、topic()関数の引数を指定することで、取得したいtopic名のセグメントを指定することができます。（引数が指定されていない場合はtopic名全体が返されます）
例えば、「test/topic」の1番目のセグメントである「test」のみ取得したい場合は、以下のようなクエリになります。
```sql
SELECT topic(1) as topic, * FROM 'test/topic'
```

# 参考
- [AWS IoT Core - AWS IoT SQL リファレンス - 関数 - topic(10 進数)](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sql-functions.html)
Tips: Treasure workflowでの`create_table`の処理は指定するクエリエンジンによって挙動がちょっと違う

## この記事は何
QiitaではTreasure workflowを使って一部データの加工などを行っています。
Treasure workflowを使う中で、ちょっとハマるポイントがあったので記事にしました。

## Treasure workflowとは
Treasure workflowとはTreasure Data上で処理をワークフローとして定義、実行したいときに使うことができる機能です。
digdagをベースに作られています。

https://docs.treasuredata.com/display/public/PD/Getting+Started+with+Treasure+Workflow

この機能を使うことで、データの加工、保存などをワークフローとして定義することができ、必要な処理をスケジュール毎やボタンひとつで実行することができます。
使用するクエリエンジンなどもスクリプト上で定義することが可能です。

```digdag:例
_export:
  engine: hive
  engine_version: stable
  td:
    database: test

+users:
  td>: users.sql
  create_table: users

```

Treasure workflowには`create_table`というコマンドがあります。このコマンドを利用すると、実行した処理の結果を、指定したテーブルに保存することができます。

```digdag:例
+users:
  td>: users.sql
  create_table: users
```

## `create_table`のはまりポイント
`create_table`は前項で説明した通りシンプルな処理なのですが、`create_table`は、すでにテーブルが存在した時は上書きの処理が走ります。

この処理が指定するクエリエンジンによって異なるのです。

### クエリエンジンがPrestoの場合
クエリエンジンにPrestoを指定した場合は、`create_table`コマンドを指定していると`DROP TABLE IF EXISTS`が実行されます。
つまりテーブルごと削除した後に、再度`CREATE TABLE`の処理が走ることで、データの上書きを行なっています。

### クエリエンジンがHiveの場合
クエリエンジンにHiveを指定した場合は、`create_table`コマンドを指定していると`INSERT OVERWRITE`が実行されます。
つまりテーブルは残したまま、文字通りデータの上書きを行なっています。

## 何が困るのか
`create_table`の処理がクエリエンジンごとでどのような処理になるかは前項で説明しました。
この違いで主に困るのはPrestoの方です。
Prestoは上書きではなくテーブルの作り直しをしています。
それにより、Treasure Data上でテーブルに対して何か変更（カラムの説明）を加えても、実行するたびに全て消えてしまいます。
この特性を知らないでいると、準備したものが全てパーにもなり得るので注意してください。
消えてほしくない場合はクエリエンジンにHiveを指定するようにしましょう。

## 参考文献

https://docs.digdag.io/operators/td.html
【IBM Application Gateway】コンテナにHTTPS（8443）ではなくHTTP（8080）でアクセスする

# IBM Application Gatewayのポートについて

IBM Application Gatewayのデフォルトポートは以下となります。


|プロトコル  |ポート  |
|---|---|
|http  |8080  |
|https  |8443 |


IBM Application Gatewayの前段に負荷分散装置を配置/SSLオフロードする構成にしたく、コンテナにHTTP（8080）アクセスさせるつもりがうまく構成できなかったため調べてみました。


```
#8080ポートでコンテナをマッピング、デプロイ
>sudo docker run --hostname iag-test --name iag-test --detach  --publish 8080:8080 --volume /
mnt/c/IAG/config.yaml:/var/iag/config/config.yaml --env LANG=ja  icr.io/ibmappgateway/ibm-application-gateway:2
2.07

#ポート確認
>docker container port iag-test
8080/tcp -> 0.0.0.0:8080
8080/tcp -> :::8080

#接続エラー
>curl localhost:8080
curl: (56) Recv failure: Connection reset by peer
```

# HTTP(8080)を設定する
[server] - [protocols] を利用することで、解消しました。

```
server:
 protocols:
  - https
  - http
```

# 参考
- https://docs.verify.ibm.com/gateway/docs/yaml-server-protocols
GithubでどのブランチからのコミットでもSlackに通知させる方法

## はじめに
当記事ではGithubとSlackを連携させ、`main`ブランチのコミットに紐づけて通知を受け取る設定が完了していることを前提としています。

### デフォルトのsubscribeではmainブランチからのコミットでしか通知されない
まずデフォルトのsubscribeでできることは下記の通り
| オプション | 通知されるイベント |
|:-:|:-:|
| issue  |  作成されたまたはクローズした |
|  pulls | 新しく作成されたまたはマージされたプルリク、および「Ready for Review」とマークされた  |
|  commits | `main`ブランチでコミットされた  |
|  release | リリースが公開された  |
|  comment | `issue`とプルリクに関する新しいコメント  |

デフォルトのままでは`main`ブランチからのコミットでしか通知されないのである


### 全てのブランチからのコミットを通知したい時
結論から申し上げるとこれでOK
```sh
/github subscribe owner/repository reviews comments branches commits:*
```
全てのレビュー、コメント、ブランチの作成、コミットが通知されるようになる！！

コマンド実行後にコミットした結果


![スクリーンショット 2023-01-23 19.14.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/79a07fa5-817b-3c73-aa68-31bd93ca9410.png)

これで`main`以外のブランチがコミットしたら通知が来るようになった:laughing:

#### 参考
https://mseeeen.msen.jp/subscribe-github-commits-for-all-branches-in-slack/

https://github.com/integrations/slack
DjangoでBootstrap5

# DjangoでBootstrapを使う時にすること

## 概要

　Djangoのアプリを作り始めるときに行うことの一つ、Bootstrapの設定について記します。
　対象OSはWindowsです。
　VisualStudioCode（以下 VSCode）を使用します。
　以下の手順で作成します。

1. django-bootstrapのインストール
1. settings.pyへ登録
1. ベーステンプレートを作る
1. テンプレートの作成
1. views.pyの作成

　環境の作成は以下を参照して下さい。

https://qiita.com/cmssai/items/38dea4c5eb5efb52d45a

https://qiita.com/cmssai/items/cde9080e32b7dfd75030

https://qiita.com/cmssai/items/82f8ff73dca573354e9d

　事前に以下の設定を行っているものとします。

https://qiita.com/cmssai/items/101d239022742e00fcb7

## django-bootstrapのインストール

　django-bootstrap5 を仮想環境内にインストールします。

```console
(venv) PS C:\ws\sample> pip install django-bootstrap5
Collecting django-bootstrap5
  Downloading django_bootstrap5-22.2-py3-none-any.whl (24 kB)
Requirement already satisfied: Django>=3.2 in c:\ws\sample\venv\lib\site-packages (from django-bootstrap5) (4.1.5)
Requirement already satisfied: asgiref<4,>=3.5.2 in c:\ws\sample\venv\lib\site-packages (from Django>=3.2->django-bootstrap5) (3.6.0)
Requirement already satisfied: tzdata in c:\ws\sample\venv\lib\site-packages (from Django>=3.2->django-bootstrap5) (2022.7)
Requirement already satisfied: sqlparse>=0.2.2 in c:\ws\sample\venv\lib\site-packages (from Django>=3.2->django-bootstrap5) (0.4.3)
Installing collected packages: django-bootstrap5
Successfully installed django-bootstrap5-22.2
```

## settings.pyへ登録

　django-bootstrap5をsettings.pyへ登録します。

```diff_python:project\setings.py
# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
+    'django_bootstrap5',
    'app01',
]
```

## ベーステンプレートを作る

　これから作成するhtmlの共通部分をベーステンプレートとして作成します。
　これ以降作成するテンプレートはこのベーステンプレートを継承して作成します。

```html:app01\templates\app01\base.html
{% load django_bootstrap5 %}

<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>{{title}}</title>
    <meta charset="utf-8">
    {% bootstrap_css %}
    {% bootstrap_javascript %}
  </head>
  <body>
    {% block content %}
    {% endblock content %}
  </body>
</html>
```

## テンプレートの作成

　ベーステンプレートを継承するようにテンプレートファイルへ記載します。

```python:app01\templates\app01\index.html
{% extends 'app01/base.html' %}
{% block content %}
  <div class="bg-primary text-white">
    {{text}}
  </div>
{% endblock content %}
```

## views.pyの作成

　ベーステンプレートにタイトルをつけたのでその分の記載を追加します。

```python:app01\views.py
from django.shortcuts import render

# Create your views here.

def index(request):
    message = {
        'title':'app01',
        'text':'Hello',
    }
    return render(request, 'app01/index.html', message)
```

これでBootstrapが使えるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/a10e0956-7d93-6e63-4361-d8b8f9829826.png)
【Laravel】クエリビルダを使ってデータがちゃんと入ってるか確認する

## はじめに
テーブルを作ってデータを入れた後、コントローラやモデルに処理を書いてビューに渡すことがかなりあるが、クエリビルダを使ってあげることで簡単にデータの確認をすることができる。

一般的にはSQLを書いてデータ挿入だったり、テーブルの中身確認をすると思うが、
クエリビルダがその役割を担ってくれる。

## クエリビルダ書き方
### tinker を起動する
クエリビルダを使うには、`コンテナにアクセスした上で`、
```
root@c347a0a2c39c:/var/www# php artisan tinker
```
を打ち込んで起動する。

その上で、クエリビルダを使いたいクラスを`use文`で指定してあげる。

```
use App\Models\Post;
```

## tinkerの使い所
様々な場面で使うことができるtinkerだが、
実際の業務の中で使うシーンを少しあげてみます。

### データの挿入(insert文)
```
Post::insert(['massage' => 'Hello']);
```
動作確認などでデータを入れて試してみたいときなどに使います。

### 条件をつけて取り出す(Where句)
```
Post::where('message', 'Hello')->get();
```
`message`カラムが`Hello`のレコードを取り出します。

## さいごに
個人的にはデータの挿入よりも実際の挙動の確認などで使うことが多いです。
非常に使い勝手がよく、動きが見れるのですごく好きです。

たまにコンテナに入らないでコマンドを打ってしまいエラーになるので焦ることもあります。(よくある)
AWS Api Gateway APIを登録する

# 概要

- APIの情報をApi Gatewayに登録する方法をまとめる。

# 情報

- 登録するAPIの情報を下記にまとめる。

    | 項目 | 情報 | 備考 |
    | --- | --- | --- |
    | URL | /foo/var |  |
    | メソッド | GET |  |

# 方法

1. AWSにログインしApi Gatewayのページに移動する。
1. 左サイドバーの「API」をクリックし、初回作成の場合は「REST API」の「構築」をクリックする。
    - 各APIタイプに関しては下記を参照
        - [AWS ApiGateway APIタイプを選択で何を選択すればよいのか迷った](https://qiita.com/miriwo/items/ddf149dba0d6a76b07b7)
1. 詳細情報を設定する（なお、下記の情報はAPIの作成後にも左サイドバーのAPI直下の設定から変更する事ができる。）
    
    | 項目 | 情報 | 備考 |
    | --- | --- | --- |
    | プロトコルを選択する | REST |  |
    | 新しいAPIの作成 | 新しいAPI |  |
    | API名 | 任意の名前を記載 | 今回は「test-api」とする |
    | エンドポイントタイプ | リージョン |  |

1. 上記を設定して「APIの作成」をクリックする。
1. 「アクション」をクリックする。

    ![API_ゲートウェイ_-_APIの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/df320903-a10d-8025-2fd0-837304e91a92.png)

1. 「リソースの作成」をクリックする。

    ![API_ゲートウェイ_-_APIの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/f7189371-a4b9-c6af-cba2-6e31175984f0.png)

1. リソースの詳細情報を設定する。

    | 項目 | 情報 | 備考 |
    | --- | --- | --- |
    | 新しいウインドウにプロキシリソースが開きます | チェックしない | この辺は各々の設定に合わせて有無を設定 |
    | リソース名 | foo |  |
    | リソースパス | foo |  | 
    | API Gateway CORSを有効にする | チェックしない | この辺は各々の設定に合わせて有無を設定 |

1. 上記を設定して「リソースの作成」をクリックする。
1. 今作成されたリソースをクリックし選択状態にする。
    
    ![API_ゲートウェイ_-_APIの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/2876d9f8-1892-38c2-c027-9b028c758e08.png)

1. 「アクション」をクリックし、「リソースの作成」をクリックする。

    ![API_ゲートウェイ_-_APIの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/18e75736-10de-c03b-400c-3ece14aa21af.png)

1. リソースの詳細情報を設定する。

    | 項目 | 情報 | 備考 |
    | --- | --- | --- |
    | 新しいウインドウにプロキシリソースが開きます | チェックしない | この辺は各々の設定に合わせて有無を設定 |
    | リソース名 | var |  |
    | リソースパス | var |  | 
    | API Gateway CORSを有効にする | チェックしない | この辺は各々の設定に合わせて有無を設定 |

1. 上記を設定して「リソースの作成」をクリックする。
1. 今作成されたリソースをクリックし選択状態にする。

    ![API_ゲートウェイ_-_APIの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/5211c343-1a8f-13ef-d082-353a6fe0cb51.png)

1. 「アクション」をクリックし、「メソッドの作成」をクリックする。

    ![API_ゲートウェイ_-_APIの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/8d238f40-ec58-ce0a-755f-44fed07f0fd8.png)

1. プルダウンでメソッドを選択する。

    ![API_ゲートウェイ_-_APIの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/3d3efdeb-7852-73f0-5682-b915c1311a52.png)

1. チェックマークをクリックする。

    ![API_ゲートウェイ_-_APIの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/30f8c7ec-13cf-8447-8704-0186ff380aa4.png)

1. 「統合タイプ」を任意のものに設定して細かい情報を記載して完成となる。

    ![API_ゲートウェイ_-_APIの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/97e3b719-02f9-c3e2-94ac-21081c1d3642.png)
ちょっとだけCSSアニメーションを追加したい時

# やりたいこと

- サイトにアニメーションを追加したい
- がっつりじゃなく、ちょっとだけ
- スクロールしたらフワッと出てくる
- サクッと追加したい（ファイル追加とかしないで、既存のコードに追加くらいで済ませたい）

# CSSアニメーションでサクッとやる

かんたんなアニメーションなら、Animistaで使いたいコードをコピペしてくる。
https://animista.net/

下からフワッと上がってくる＆フェードインならこんな感じ
``` style.css
/*

animation List
from : https://animista.net/

*/

.site-content .setAnime{
	opacity: 0;
}
.site-content .is-animate.slide-in-down {
	-webkit-animation: slide-in-down 1s ease-in-out both;
	        animation: slide-in-down 1s ease-in-out both;
}
.site-content .is-animate.fade-in {
	-webkit-animation: fade-in 1s ease-in-out both;
	        animation: fade-in 1s ease-in-out both;
}

/*
 * ----------------------------------------
 * animation fade-in
 * ----------------------------------------
 */
@-webkit-keyframes fade-in {
  0% {
	  opacity: 0;
  }
  100% {
	  opacity: 1;
  }
}
@keyframes fade-in {
  0% {
	  opacity: 0;
  }
  100% {
	  opacity: 1;
  }
}

/*
 * ----------------------------------------
 * animation slide-in-down
 * ----------------------------------------
 */
@-webkit-keyframes slide-in-down {
  0% {
	  opacity: 0;
    -webkit-transform: translateY(50px);
            transform: translateY(50px);
  }
  100% {
	  opacity: 1;
    -webkit-transform: translateY(0);
            transform: translateY(0);
  }
}
@keyframes slide-in-down {
  0% {
	  opacity: 0;
    -webkit-transform: translateY(50px);
            transform: translateY(50px);
  }
  100% {
	  opacity: 1;
    -webkit-transform: translateY(0);
            transform: translateY(0);
  }
}
```

```class="is-animate slide-in-down"```を追加すれば、表示と同時にアニメーションする。

## スクロールしたら動くようにしたい

スクロールをトリガーにしたい場合は、以下のコードをページ内に追加。
``` index.html
<script type="text/javascript">
const myFunc = function(){
	//Classを追加する要素を取得
	const target = document.getElementsByClassName('setAnime');
	//Classを追加する位置を指定（ビューポート内）
	const position = Math.floor(window.innerHeight * .75); //ビューポート内の上から75%の位置を指定
	//要素の数だけループする
	for (let i = 0; i < target.length; i++) {
		//要素の上部座標を取得する（小数点切り捨て）
		let offsetTop = Math.floor(target[i].getBoundingClientRect().top);
		//要素の上部座標がpositionの位置を通過したら
		if (offsetTop < position) {
			//要素にClassを追加する
			target[i].classList.add('is-animate');
		}
	}
}
//スクロールイベントリスナーに登録
window.addEventListener('scroll', myFunc, false);
</script>
```
WordPressならカスタムHTMLブロックとかで追加してもいい。

スクロールトリガーの場合、```class="setAnime slide-in-down"```を追加。
表示領域に入ったら「setAnime」が付いた要素に「is-animate」が付くので、そこでアニメーションする。

setAnimeに```opacity: 0;```入れてるのは、フェードイン系は最初に透明にしておかないと、アニメーション発動直前に表示されちゃうから。

たまに使うけど、忘れちゃうのでメモ。
C#.NETで『外部端末のタスクスケジューラ情報接続』に失敗する時の対応

# 概要

『C#でタスクスケジューラ情報を取得』については下記。

https://qiita.com/waokitsune/items/f34b57d123094ebf893f

上記はローカルのタスクスケジューラ情報を取得している。

でも、 ```ITaskService.Connect()``` は下記のように、外部端末のタスクスケジューラ情報を取得することもできる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c3730255-75e4-547b-d3af-8ab4817ab58a.png)

だが、接続情報が正しいはずなのに下記のように失敗する。

>この要求はサポートされていません。 (HRESULT からの例外:0x80070032)

また、接続できたとしても下記のような失敗になる。

>アクセスが拒否されました。 (HRESULT からの例外:0x80070005 (E_ACCESSDENIED))

そういった時に『この設定を変えれば直るかも』という内容です。

:::note warn
細かい動作検証はしていないので、参考情報となります。
あたいの環境ではこうやったら解決しました、という記録（メモ）レベル。
:::

# ファイアウォール

まず『この要求はサポートされていません。』で失敗する時は、ホスト（接続される側）のファイアウォールで弾かれてる可能性が高い。

『受信の規則』の『スケジュールされたリモートタスク管理（RPC）』を許可してあげると接続できた。

例えばドメイン参加端末であればホスト側が下記のようになっている必要あり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a4a569da-d105-499b-b454-6bed74338f81.png)

# 接続ユーザー

接続できたのに『アクセスが拒否されました。』で失敗する時は、接続ユーザーが原因である可能性が高い。

例えば『hoge』って名前のユーザーでホスト側にタスクスケジューラ設定したとする。
（フォルダーとかタスク作ったりとか）

そうしたらクライアント側も『hoge』というユーザーで接続しないと『アクセスが拒否されました。』で失敗する可能性が高い。

これは ```ITaskService.Connect()``` に引数で渡すユーザー情報の話。
exeをキックするユーザーは関係ない。（違っていても問題無い）

これについては…

接続できるのに、なんで『アクセスが拒否されました。』で失敗するんだろう…。
もしかして『設定したユーザー』と『接続するユーザー』が違うからかな？
試しに同じに揃えてみるか…。
あ、解決した！

っていうくらいの動作確認のみ。

# 参考サイトさん

https://stackoverflow.com/questions/46440340/connect-remote-task-scheduler-using-c-sharp-throws-error

# バージョン

Windows 10 Pro 22H2 OSビルド 19045.2486
Microsoft .NET Framework Version 4.8.04084
STPの仕組み

STPの動きが自分の中で怪しかったので実際に構築しておさらい。
下記の様な構成をイメージして書きました。

![stp-Page-1.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088255/9b9b61a4-1640-f8e1-5855-0310327c1a8c.png)



## ①
STPではまず RootBridge をBrigde ID(priority値:macアドレス)が最小の値のスイッチが選ばれる。
※priority値が先頭に来るので値を小さくすればmacアドレス関係なくroot brigdeに指定できる

## ②
RootBridge を最上流として BPDU が下流スイッチに流れていく。

## ③
NW全体で各SW間でBPDUを送信しあって
優先度の低いBPDUを送出するSWのIFのBPDU送信を止める。

1.Path Cost　　　　　←上から優先
2.送信元 Bridge ID
3.送信元 Port ID 

1.
帯域幅	コスト値（ IEEE改定後 ）	コスト値（IEEE改定前）
10Gbps	2	1
1Gbps	4	1
100Mbps	19	10
10Mbps	100	-

## ④
BPDU を受信するポートが UpLink (上流へ向かうポート)、
BPDU を送信するポートが DownLink (下流へ向かうポート) 
となり
-Uplinkが複数あると優先度の高いBPDUを受信しているIFをRootポートとして通信可になる。
-DownLinkは指定ポートとして通信出来るようになる。
上記の2点以外はブロックポートとなる。

■参考
https://milestone-of-se.nesuke.com/nw-basic/stp/stp-summary/


# CONFIG


~~~md:root brigde
# config

Switch#show spanning-tree

VLAN0001
  Spanning tree enabled protocol ieee
  Root ID    Priority    4097
             Address     34a8.4efb.XXXX
             This bridge is the root
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec

  Bridge ID  Priority    4097   (priority 4096 sys-id-ext 1)
             Address     34a8.4efb.XXXX
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec
             Aging Time  300 sec

Interface           Role Sts Cost      Prio.Nbr Type
------------------- ---- --- --------- -------- --------------------------------
Gi1/0/1             Desg FWD 4         128.1    P2p
Gi1/0/3             Desg FWD 4         128.3    P2p

~~~


~~~md:右下のSW
Switch#show spanning-tree

VLAN0001
  Spanning tree enabled protocol ieee
  Root ID    Priority    4097
             Address     34a8.4efb.XXXX
             Cost        4
             Port        1 (GigabitEthernet0/1)
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec

  Bridge ID  Priority    8193   (priority 8192 sys-id-ext 1)
             Address     1833.9dda.XXXX
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec
             Aging Time  300 sec

Interface           Role Sts Cost      Prio.Nbr Type
------------------- ---- --- --------- -------- --------------------------------
Gi0/1               Root FWD 4         128.1    P2p
Gi0/23              Desg FWD 4         128.23   P2p

~~~

~~~md:左下のSW
Switch#show spanning-tree

VLAN0001
  Spanning tree enabled protocol ieee
  Root ID    Priority    4097
             Address     34a8.4efb.XXXX
             Cost        4
             Port        1 (GigabitEthernet1/0/1)
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec

  Bridge ID  Priority    12289  (priority 12288 sys-id-ext 1)
             Address     d4a0.2a7f.XXXX
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec
             Aging Time  15  sec

Interface           Role Sts Cost      Prio.Nbr Type
------------------- ---- --- --------- -------- --------------------------------
Gi1/0/1             Root FWD 4         128.1    P2p
Gi1/0/24            Altn BLK 4         128.24   P2p
~~~


ちなみに右下のSWのpriprityを12289に左下SWを8192にするとちゃんとBLKポートが右下のSWになりました。
M1 Mac に Python MIP をインストール

# name 'cbclib' is not defined に悩まされている人へ

- bash か zsh か確認するべし
- 私は zsh なのにずっと ~/.bashrc に書き込んでいて時間を溶かした

# 手順
1. ターミナルを開き、bash か zsh か確認
2. coinbrew による Cbc のビルド (ターミナル上)
    1. `cd`
    2. `git clone https://github.com/coin-or/coinbrew.git`
    3. `cd coinbrew`
    4. `./coinbrew fetch build Cbc@master --no-prompt --prefix=/usr/local --tests=none --enable-cbc-parallel`
3. zsh の人
    1. `cd`
    2. `touch .zshrc`
    3. 以下を書き込む
4. bash の人
    1. `cd`
    2. `touch .zshrc`
    3. 以下を書き込む   
```
export PMIP_CBC_LIBRARY="/usr/local/lib/libCbc.dylib"
export LD_LIBRARY_PATH="/home/haroldo/prog/lib/":$LD_LIBRARY_PATH
```

- あとは、`pip install mip`で、Python-MIP のインストールをすれば完了



# 参考
https://zenn.dev/ohtaman/articles/install_python_mip_m1
GitのログからGitHubのプルリクエストでマージされたコミットログを抜き出す

developと現在のブランチ間のコミットログからプルリクエストでマージされたコミットのログを抜き出す。

``` bash
git log origin/develop..`git branch --contains | cut -d " " -f 2` --merges --pretty=format:"%s" | awk -F'[#|/| ]' '/^Merge pull request/{print $0}'
```

コミットログにブランチ名が入ってるので色々やる際の前処理に使う予定
【Markdown Preview Enhanced】VSCodeのMarkdown Preview Enhanced拡張が使用する、PlantUMLのバージョンを上げる【Windows用】

# 目的
VSCodeのMarkdown Preview Enhanced拡張機能は、様々なUML記法をプレビューしてくれる。
(Ctrl + Shift + [V])
しかしこの拡張機能のPlantUMLは2021年のバージョンであり、
様々な記法に対応していない。

ので、Markdown Preview EnhancedのPlantUMLを更新する。

# 手順
## 1. 最新のplantuml.jarを取得
chocolateyを使用している場合。
(使用していない場合は、[公式](https://plantuml.com/ja/download)からダウンロード可能)

```
choco install plantuml
```

上記コマンドで下記ファイルが取得可能
C:\ProgramData\chocolatey\lib\plantuml\tools\plantuml.jar

## 2. VSCodeにMarkdown Preview Enhancedをインストール
```
Name: Markdown Preview Enhanced
Id: shd101wyy.markdown-preview-enhanced
Description: Markdown Preview Enhanced ported to vscode
Version: 0.6.7
Publisher: Yiyi Wang
VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced
```

## 3. plantuml.jarを更新
* 変更対象ファイル
    * ~\\.vscode\extensions\shd101wyy.markdown-preview-enhanced-0.6.7\node_modules\@shd101wyy\mume\dependencies\plantuml\plantuml.jar
* 持ってくるファイル
    * C:\ProgramData\chocolatey\lib\plantuml\tools\plantuml.jar

# 参考
https://otepipi.hatenablog.com/entry/20210520/1621458229
SwiftUIのButtonは書き方によってタップ時に反応が異なるよ、という話

よく`Button("hogehoge", action: hoge)`みたいな書き方を見るけれど`Button(action:label:)` とどう違うの？とか`ButtonStyle`とどう違うの？とか ~~どうでも良いことについて~~ の解説。

## 検証環境
Xcode: Version 14.2 (14C18)
iOS target: 16.2

## 検証コード

```Swift
import SwiftUI

struct ContentView: View {
    @State var isShowAlert = false
    var body: some View {
        ZStack {
            Color.brown
            VStack(spacing: 10) {
                Button("title", action: showAlert)
                    .foregroundColor(.white)
                    .padding(.horizontal, 50.0)
                    .padding(.vertical, 10.0)
                    .background(
                        RoundedRectangle(cornerRadius: 20)
                            .fill(.red)
                    )
                
                Button(action: showAlert){
                    Text("title")
                        .foregroundColor(.white)
                        .padding(.horizontal, 50.0)
                        .padding(.vertical, 10.0)
                        .background(
                            RoundedRectangle(cornerRadius: 20)
                                .fill(.red)
                        )
                }
                
                Button("title", action: showAlert)
                    .buttonStyle(.customStyle(color: .red))
            }
            .alert("メッセージ", isPresented: $isShowAlert) {
                Button("Continue", role: .cancel) { }
            }
        }
    }
    private func showAlert() {
        isShowAlert = true
    }
}

struct CustomButtonStyle: ButtonStyle {
    
    var color: Color = .blue
    
    public func makeBody(configuration: CustomButtonStyle.Configuration) -> some View {
        CustomButton(configuration: configuration, color: color)
    }
    
    struct CustomButton: View {
        let configuration: CustomButtonStyle.Configuration
        let color: Color
        
        var body: some View {
            
            return configuration.label
                .foregroundColor(.white)
                .padding(.horizontal, 50.0)
                .padding(.vertical, 10.0)
                .background(
                    RoundedRectangle(cornerRadius: 20)
                        .fill(color)
                )
                .opacity(configuration.isPressed ? 0.3 : 1.0)
        }
    }
    
}

extension ButtonStyle where Self == CustomButtonStyle {
    static func customStyle(color: Color = .red) -> some ButtonStyle {
        CustomButtonStyle(color: color)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

```

## 検証結果
![button.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421964/655c4770-5b4e-7a32-cd1c-5a857523f6eb.gif)


### Buttonにモディファイアを付ける場合
paddingに反応しない。文字の領域をタップした時だけボタンが反応し、背景色が変わることはない。

### init(action: label:)のlabelに装飾を付けた場合
今回はTextにモディファイアをつけた。
paddingに反応する。タップ時に背景色が薄くなるボタンらしい変化をする。

### ButtonStyleで装飾を付けた場合
paddingに反応する。**自分でタップした時の処理を指定しない場合は、色が薄くならない**。
今回opacityを0.3に設定したが、本来のボタンはもう少し薄い…。

## まとめ
Buttonにモディファイアを付けることは反応の面からも止めたほうが良いと思う。
手軽に作るならば`init(action:label:)`がベストだけれども、きちんと作るならばButtonStyleを使ったほうが良さそう。
Prismaで新規レコード作成時に@default(now())なカラムと@updatedAtなカラムに差異が生じる問題

# 環境
- Prisma：3.13.0
発生条件は <= 4.3.1(後述)
- Provider：MySQL

# 概要
こんな感じで定義されたテーブルに対して、
```schema.prisma
model User {
  id        Int      @id @default(autoincrement()) @db.UnsignedInt
  createdAt DateTime @default(now()) @map("created_at")
  updatedAt DateTime @updatedAt @map("updated_at")

  @@map("users")
}
```
`prisma.user.create({})`を実行すると以下のように`created_at`と`updated_at`がミリ秒単位で差異が生じる結果となる。
```sql
MySQL > select id,created_at,updated_at from users;
+----+-------------------------+-------------------------+
| id | created_at              | updated_at              |
+----+-------------------------+-------------------------+
|  1 | 2023-01-23 02:17:42.875 | 2023-01-23 02:17:42.894 |
+----+-------------------------+-------------------------+
```
`created_at`と`updated_at`を比較するような実装はよくあるケースなので、
そういうケースでこの問題に直面すると結構頭を抱える問題。

メジャーなF/WのORM(railsのActiveRecordやLaravelのEloquent)と同じ仕様だと勝手に思い込んでいたのでかなり驚いたが、
これは3.13.0時点(厳密には <= 4.3.1)での仕様であり、GitHubリポジトリ上に[Issue](https://github.com/prisma/prisma/issues/12572)も既に上がっていた。

コントリビューターの方が丁寧に[コメント](https://github.com/prisma/prisma/issues/12572#issuecomment-1082757147)してくれている通り、`@default(now())`はDBで書き込んでいるが、
`@updatedAt`はPrismaクライアントから書き込んでいることでミリ秒単位の差異が生じている模様。

最終的にprisma-enginesの[こちらのPR](https://github.com/prisma/prisma-engines/pull/3200)で対応され、無事バージョン4.4.0でリリースされた模様。

# 対応
ということで、Prismaのバージョンを上げるだけで期待する動作になるはずなので、
Prismaのバージョンを上げて再度検証してみる。
```package.json
{
  "dependencies": {
    "@prisma/client": "^4.8.0",
    "prisma": "^4.8.0"
  }
}
```
`prisma.user.create({})`を実行し、レコードを確認すると。
```sql
MySQL > select id,created_at,updated_at from users;
+----+-------------------------+-------------------------+
| id | created_at              | updated_at              |
+----+-------------------------+-------------------------+
|  1 | 2023-01-23 02:50:32.466 | 2023-01-23 02:50:32.466 |
+----+-------------------------+-------------------------+
```
`created_at`と`updated_at`がミリ秒まで含め同じ値となっていることが確認できた。

# まとめ
`@default(now())`なカラムと`@updatedAt`なカラムを定義し、
かつその差分を比較する必要があるケースでは必ずバージョン4.4.0以上のPrismaを使用しましょう。

ただ、Prisma4から`$queryRaw`等に[仕様変更](https://www.prisma.io/docs/guides/upgrade-guides/upgrading-versions/upgrading-to-prisma-4)が入っているので、
既存アプリケーションのPrismaバージョンアップは慎重に。
※こちらはまた[別記事](https://qiita.com/irohafox/items/a18c9ac1d9b1f719c70b)で書きます。

# 参考
https://github.com/prisma/prisma

https://github.com/prisma/prisma/issues/12572

https://github.com/prisma/prisma-engines/pull/3200

https://www.prisma.io/docs/guides/upgrade-guides/upgrading-versions/upgrading-to-prisma-4

# 関連
[Prisma4にアップグレードした際に$queryRawを使用している箇所でTypeError: Cannot mix BigInt and other types, use explicit conversionsが発生する問題](https://qiita.com/irohafox/items/a18c9ac1d9b1f719c70b)
【Unity】Unityちゃんテラスタル！！【Shader芸】


# はじめに
本記事は 『【年末だよ】Unity お・と・なのLT大会 2022』で登壇した内容の文字起こしとなります。
(諸事情でUnity Learning Materials には掲載されておりません）

動画でチェックしたい方は是非とも以下のリンクよりご確認ください。

https://youtu.be/Qea4ziAg5jk?t=82

# 概要
ポケモンSVで登場している「テラスタル」の見た目を頑張って再現してみた話です。

見た目については下記ツイートのgifにて

https://x.com/8bitdots/status/1595623764527415296

# How to再現

結論としては `クリスタルシェーダー` と `FlatShading` の組み合わせになります。

## クリスタルシェーダー

クリスタルシェーダーとは名前の通り「クリスタルっぽい見た目」になるシェーダーのことです。
※名前は今回名付けたもので一般的な用語ではありません

よくダイヤモンドのキラキラした感じとかで利用されます。

今回は海外ニキがYoutubeで公開していたのでそちらを参考にしました。

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

原理としては「ノイズ画像」と視差オクルージョンマッピングを組み合わせて、Emmision に渡してあげることで
面によってキラキラさせるといった形です。

## Flat Shading 
フラットシェーディングとは簡単に解説すると、各面の法線をスムージングをかけないでポリゴンを描画する方法です。

詳しくは [オモチャラボさんの記事](https://nn-hokuson.hatenablog.com/entry/2017/02/13/195748) で解説されてますので、こちらを是非ご覧ください。

# 課題点
## UnityちゃんSDモデルがURP非対応
URPプロジェクトでSDモデルを追加すると全身ピンクの状態になります。
Toon ShaderがBRP（Built-in RenderPipeline）対応でURP非対応なのが原因です。

そのため、UnityちゃんSDに設定されているmaterialを全てURP対応版に変更する必要があります。

検証段階では雑に URPのLit シェーダーを無理矢理適応されることで表示させました。

※商用プロダクト等ではヴィジュアルの調整が必須になるのでこの手法は非推奨です。ヴィジュアルアーティストさんの調整やテクニカルアーティストに専用のToonShader を使うなどして回避した方がおすすめです。


## 画角によっては、ずれる
今回は3Dモデルのアウトライン表示のやり方の一つである背面法の亜種のような形で実装してます。
つまりクリスタルの方は元のモデルより1.01倍大きくスケールさせてます。

そのため、このスケールの影響で、画角によってはちょっとクリスタルのモデルが浮いているように見えてしまっています（髪の毛の部分などが顕著）。


## 結晶の厚み

今回は同じモデルをクリスタル化して重ねて表示していますが、わずか 1%大きくなっただけなので結晶感を出すための `結晶の厚み` はかなり薄くなっています。
本家ですと、しっかり厚みのある結晶になっているため、ここに関しては改善の必要があります。


# 最後に
## ライセンス

![imageLicenseLogo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/8809319c-8af1-76a4-e77d-fcbfb9dee3f9.png)

本件は[ユニティちゃんライセンス条項](https://unity-chan.com/contents/license_jp/)の元に提供されています。


## 資料
本記事の登壇動画は以下から。

https://youtu.be/Qea4ziAg5jk?t=82

また、説明スライドのリンクは以下からアクセスすることが可能です。

https://speakerdeck.com/cova8bitdots/unity-chan-dot-terrastal
React Native初心者がアプリを作成してみる

# 進め方

1. 本でも動画でもいいので１連の流れを把握
1. 必要そうな機能を抜き出して自作する
1. 自作アプリの作成に

## １連の流れを得るために参考にしたもの

-　[React Native(Expo)によるiOSアプリ開発](https://www.udemy.com/course/react-native-expo-firebase/)
簡単な初心者アプリとFirebaseや画面遷移が入ってくるアプリの２段構成になっているので入りやすい．

-　[React NativeとExpoで作るiOS・Androidアプリ開発入門 - これ一冊でストアリリースまで進める本格的入門書](https://amzn.to/3J7H7bt)
ちょっと古いがコンポーネント一つ一つの使い方がわかるので良い

## 必要そうなモジュールや機能

### Expo
[別記事](https://qiita.com/mikanbaco/items/3d81f4a7cb3f9f76be9a)
- 環境構築
- プロジェクトの作成方法

### React Navigation
[React Navigationを使ってみる - Qiita](https://qiita.com/mikanbaco/items/bde7a7038bd6859621bc)

stack, tab, drowerを使用した画面遷移

### Redux toolKit

### TailWind
【大前提の話】詐欺の溢れる海外FXで稼いだ人が、これから稼ぐと息巻いている人に言いたいことPart1

よくわからんけどお金稼ぎたいとか漠然としたことを思い浮かべたことありますか？
僕は月30万円の手取りで一人暮らししていた時に、友人との飲み会以外で何にもお金を使うことなく過ごしているときに思いました笑
ただ超稼いでいるわけでもなく、FIREできるほど貯蓄があるわけではないけど一応もっとお金欲しいなくらいの感覚の時にたどり着いたのが海外FXでした。

怪しいと言われてるけど、言われ続けていてもなくならないってことは意外と安全じゃないか？と考えて調べていていました。

流石に新興業者で怪しいところは詐欺のことが多いけど、みんな知ってるくらいの大手なら別に問題ない気がしたので。

例えば、こういうので紹介されているやつとかね。

https://forextester.biz/fx/

海外FXといえば何を思い浮かべるでしょうか？
詐欺？
借金？
出金拒否？
資金の持ち逃げ？

正直全部思い浮かべますよね笑

でもそれって日本でもやるやつはやるし、やらないやつはやらないんですよ。
しかも海外FX業者ってトレーダーの損失＝利益じゃないし、トレーダーの取引手数料＝利益だから、大手が詐欺とかやる必要なくね？って思ったんです。

しかもレバレッジ1,000倍とかザラだし、なんなら普通にボーナスとかみ入金でもらえるし、ゼロカットあって借金しないしむしろお得やろと思ったのですよ。

ゼロカットってこれね

https://forextester.biz/fx/fx-zero-cut/

まぁつまり、ああいうサイトで自分で勉強して、自分で信じれるものを探して、自己責任で投資しろよってことです。

今回はここまで、大前提の話
anacondaとOpenCVで”libstdc++.so.6: version `GLIBCXX_3.4.30' not found”が出たときの対処

# 背景

Archlinuxでanacondaの仮想環境上でOpenCVの勉強をしていたときに、作成した画像を出力しようとしたときにエラーが出た

```bash
libGL error: MESA-LOADER: failed to open radeonsi: /home/username/anaconda3/envs/OpenCV/lib/python3.10/site-packages/PIL/../../../././libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by /usr/lib/dri/radeonsi_dri.so) (search paths /usr/lib/dri, suffix _dri)
libGL error: failed to load driver: radeonsi
```

# 解決方法

stackoverflowで下記のコマンドを実行して最新版のgccをインストールしたらいいと書いてあったので実行したら直った

```bash
conda install -c conda-forge gcc=12.1.0
```

https://stackoverflow.com/questions/72540359/glibcxx-3-4-30-not-found-for-librosa-in-conda-virtual-environment-after-tryin
Apexカスタイマイズ可能な自動採番

同時更新されない頭文字と長さを自由に設定する自動採番する数字を一箇所に表示する方法をこの記事で教えます。

## 1.専用のオブジェクト
表示するオブジェクトOrder_Headerのレコードをテキスト型に設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2705822/beca246e-a82b-68df-5167-09d4069f6fd3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2705822/970ed246-6cd8-b0bb-c6bd-7ca4072f5400.png)
採番を管理するオブジェクトSequenceNoを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2705822/3093932a-6716-34b8-798e-8aa3d1b4966e.png)


## 2.メソッド作成する
頭文字を決めるprefix + 数字を決めるSequeceId + 尾語決めるsuffix　で”Case00000ｘ”の形式にする。
```
 public static String getNewOrderHeaderCaseNo(){
        //更新が被らないようにFOR UPDATEを使い排他性をつける
        SequenceNo__c lists0 = [SELECT id,Type__c,prefix__c,sequenceId__c,suffix__c From SequenceNo__c WHERE Type__c='CaseNo' Limit 1 FOR UPDATE];
        
        lists0.sequenceId__c+=1;
        Decimal maxCaseNo=lists0.sequenceId__c;
        String newmaxCaseNo='000000'+maxCaseNo;
        String suffix=lists0.suffix__c;
        //尾語がNullなら空にする
        if(suffix==null){
            suffix='';
        }
        //左に自動シフトするように.right(6)をつける
        String CaseNo=lists0.prefix__c+newmaxCaseNo.right(6)+suffix;
        update lists0;
        system.debug(CaseNo);
        return CaseNo;

    }
```