OmniAICreator/Qiita-1.07M huggingface dataset:
【開発ゼロ】Amazon ConnectとZendeskを公式アプリで連携してみてよかったこと

クラウド型コンタクトセンター「Amazon Connect」と、クラウド型カスタマーサービスプラットフォーム「Zendesk」を、AWSナレッジセンターで提示されている方法で連携しました。
4ヶ月経って、カスタマーサポート担当者の所感ベースで、連携してよかったことと、公式アプリの限界についても挙げようと思います。


# Zendeskにインストールしたアプリ
[Amazon Connect App Integration with Zendesk Support](https://www.zendesk.co.jp/marketplace/apps/support/243469/amazon-connect/)

以下、AWSのナレッジセンター記事で指定されているアプリケーションになります。
インストール方法などは、こちらをご覧ください。

https://repost.aws/ja/knowledge-center/connect-integrate-zendesk

アプリケーションの設定は、基本、デフォルト値の設定を利用しています。
- Amazon Connect URL（必須）
- AWS Region（必須）
- Default entry point phone number（必須）
    - 連携するアカウントのURLやリージョン、電話番号を入力しました
- Single sign-on URL (任意)
    - シングルサインオンを利用しているため、ログインURLを入力しました
        - こちらを指定すると、ログインしていない際に自動ポップアップするURLを指定できます。SAMLログインの場合は、SAMLログインをするためのURL指定しておくと便利です。

また、Zendeskの契約はSuite Professionalプランです。

# 連携してよかったこと

### 問い合わせ管理ツールと電話ツールが一つになる
サポートデスクでは、Zendesk Talkを利用しておらず、
問い合わせ管理ツール（Zendesk）と、電話ツールが別になっていました。

ログを残す機能であるZendesk内に、受電・架電ができるAmazon Connectのアプリがあることで、
1つの画面で受電しながらログを残せるため、受電業務の後作業時間の短縮に繋がりました。

### 受電時に、自動でチケット作成+録音の自動添付
受電時に、自動でチケットが立ち上がります。
作成主体がCTIツール（着信）となるので、トリガを作ることも容易です。

また、終話後に録音データも自動で追加されます！（個人的には一番うれしかったポイントです）
探す手間が省け、管理者の業務改善に繋がりました。

しかも、この録音データ、Zendesk内に録音データを残す設計ではなく、Amazon Connectで「聴く権限」が与えられていないユーザーには聴けない仕様になっています。
また、Amazon Connectの録音データが保存されるS3のから削除されると、誰からも聴けない仕様であることも確認しました。

### 同じ電話番号にユーザーが紐づく
問い合わせ管理として、これまではZendeskでユーザー作成をしておらず、
電話を受けてお客様を特定して初めて、過去の問い合わせ履歴が確認できる状態でした。
Amazon Connectアプリでは、電話番号からユーザーが自動生成され、
既存ユーザーの場合は紐づけされる仕組みになっているため、
電話がかかってきた時点で、過去にお問い合わせされているお客様の場合は
瞬時に特定ができるようになりました。
※紐づけに時間がかかる場合もあるため、あくまで参考程度として利用しています

### ユーザー紐づけができていたら、架電が簡単
既にZendesk上に電話番号ごと登録されているユーザーであれば、
電話番号をクリックし「電話をかける」を選択すると、電話がかけられます。
いちいち電話番号を打つ必要がなく、打ち間違いの予防にもなります。

# 公式アプリの限界
### 日本語は非対応
自動で入るコメントなどは全て英語になります。
具体的なイメージとしては、[マーケットプレイス](https://www.zendesk.co.jp/marketplace/apps/support/243469/amazon-connect/)の画像がそのまま当てはまります。
Amazon Connectの用語がカタカナ英語でもイメージできていれば、混乱はないと思いますが、見慣れない感覚はあるかと思います。
また、アプリケーションのヘルプセンターも存在するのですが、こちらももちろん英語です。

~~https://help.voicefoundry.cloud/zendesk/~~
※2024/10更新：ベンダーが変更になり、ヘルプセンターが以下に変わったようです
https://zendeskconnector.ttecdigital.solutions/zendesk/v3.0/

### 連携される情報に限界はある
チケットを自動で立ち上げた後は、録音情報と、基礎情報（キュー名など）しか入りません。
アプリはオープンソースのため、カスタマイズしたい場合にはアプリを自社開発するか、ベンダーに依頼することになるかと思います。

### 架電は、ユーザー作成後でないと、自動でチケットが立ち上がらない
これが意外な落とし穴だったのですが、架電時にユーザーが登録されていないと、チケットが自動で立ち上がりません。
先にユーザー登録をしてから、架電するようにしましょう。

# 最後に
入れてみてすでに4ヶ月経過しましたが、ZendeskとAmazon Connectを公式アプリで連携したことで、通話ログの記録が非常に便利になりました。

※実際に利用する現場ユーザーの体験が大きく変わるため、導入前にテスト環境/サンドボックスでの練習はできるだけ実施することをおすすめします。


今回は以上になります！
今後とも、サポートデスクの体験向上・業務効率化を通して、サポートの品質向上に努めます。
React Material UIのTextFieldを使用するとplaceholderと入力値が被る現象

最近現場でReactを使うようになって躓いた部分があったので残しておこうと思います。

## 発生した現象
Material UIのTextFieldコンポーネントを使用して郵便番号欄を作成していました。
スマホ表示時に郵便番号欄をタップした際に、数値のキーボードを初期で表示させたかったのでtype属性をnumberに指定しました。
仕様としてはハイフンなしの半角数値のみが入力される仕様でした。ただtypeをnumberに指定していても半角のハイフンが入力できてしまうようで`100-0001`のように入力すると以下の画像のようにplaceholderの文字と入力値が被って表示されてしまいました。

```js
<TextField
  type="number"
  label="郵便番号"
/>
```

**入力前**
![スクリーンショット 2023-06-10 18.08.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/934895/4a4617e5-c405-32b0-30fc-d4b93896cbc2.png)

**入力後**
![スクリーンショット 2023-06-10 18.08.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/934895/441dc7af-15fc-8ae4-5b24-8fdf7398dcb7.png)


## 原因
以下の記事にあるように、途中でハイフンを入れると空文字扱いになってしまうようです。
従ってこの入力欄には何も入力されていないと判定されます。これが原因で入力前の画像と同じようにplaceholderの文字が表示されてしまうことによって、実際には入力されている`100-0001`と被って見えてしまうということでした。

https://blog.kentokanai.net/input_number/#:~:text=JS%E3%80%8D%E8%A8%98%E4%BA%8B%E4%B8%80%E8%A6%A7-,%E3%81%A7%E5%85%88%E9%A0%AD%E4%BB%A5%E5%A4%96%E3%81%AB,%E3%81%A8%E7%A9%BA%E6%96%87%E5%AD%97%E5%88%A4%E5%AE%9A%E3%81%AB%E3%81%AA%E3%82%8B

## 解決策
他の方法もあると思いますが、今回は以下のうようにして解決しました。

type属性をnumberで指定するのをやめて、新たに`inputmode`を追加することで解決しました。
今回躓いて調べるまでinputmodeという属性があることを知りませんでした。
inputmode属性とは、簡単にいうと`ソフトウェアキーボードの挙動を制御する`ための属性です。

https://reference.hyper-text.org/html5/attribute/inputmode/

キーボードを制御したかったのでtypeをnumberに指定していましたが、今回適しているのはinputmodeでしたのでこちらを追加することにしました。

Material UIのTextFieldコンポーネントを使用していたので、そのままinputmode属性を使用することができませんでした。
TextFieldコンポーネントに`inputmode`属性を追加するには以下のようにすることで指定する事ができました。

```js
<TextField
  inputProps={{ inputMode: 'numeric' }}
  label="郵便番号"
/>
```

このようにして解決する事が出来ました！
Gitブランチを空にしたい

## やりたいこと  

Git管理しているディレクトリの特定ブランチ内のファイル/ディレクトリをすべて削除したい。

前提として以下の条件があるとする。
- ブランチは残す
- 空ディレクトリも残さず削除する

## 方法1 `rm -rf *`

```
rm -rf *
```

カレントディレクトリ以下のファイル/ディレクトリ共に削除できるが、 `.git/` も削除されてしまうので、gitによる管理ができなくなってしまう。

## 方法2 `git rm -r .`

```
git rm -r .
```

gitのサブコマンドを使用する方法。`.git/`  は残しつつ、カレントディレクトリ配下のファイルをすべて削除できるが、空のディレクトリが残ってしまう。

## 方法3 `ls -A | grep -e -V '.git' | xargs rm -rf`

```
ls -A | grep -e -V '.git' | xargs rm -rf
```

`.git/` は残しつつ、ファイルも空ディレクトリも綺麗さっぱり削除できる。

`-e` オプションは、引数で指定した文字列を検索する。今回の場合は ".git" に一致するファイル/ディレクトリが該当する。

`-v` オプションは、結果を反転させる。つまり `".git"` を除いた結果が得られる。

結果として、`ls -A` の結果から ".git" を除いたものが `rm` コマンドに渡され、.git以外のすべてのファイル/ディレクトリを削除できる。

# 参考

参考にさせていただきました。
ありがとうございます🙇‍♂️

[特定のファイル以外を指定して削除する方法](https://it.notepad-blog.com/tool/linux/279/)
高校生が基本情報技術者試験に27時間で受かった

# 正確には応用情報25h+基本情報2h
元々応用情報技術者試験を受けていたのですが完全に**なめてかかった結果**、午前が自己採点55%だったので急遽基本情報技術者試験を受けました。
応用情報の勉強時間が25時間ほど、基本情報が2時間ほどですので合計27時間です。
## 正味午後(B試験)はアルゴリズムやった事あるなら行ける
自分は高3で別にプログラマとかではないですが、unreal engineというゲームエンジンのBP(ブループリント)と呼ばれる、c++をノードベース化したもので約二年ゲームを作っています。ですのでそこそこアルゴリズムに触れていました。
で、**ノー勉でもいけるやろ**と調子に乗りましたが、**635/1000**点とギリギリどうにかなりました。
## 午前(A試験)は大して応用情報と範囲が被ってない
たまたまの可能性もありますが、あまり被っていませんでした。応用情報は最後の方なんも知識なくてもテキトーに計算すれば(思考力があれば)どうにかなる問題がまああったのですが、基本情報は知識げーの要素が強かったと感じました。
逆に言うとしっかり時間を取って勉強すれば普通に受かると思います。
あと応用情報は割と文系寄りの内容が多いのですが、基本情報は普通に情報寄りの内容が多かったのも原因かもです。
点数は**605/1000**点   ふうううあっぶねええ

## 前日にやった勉強法
基本情報の勉強は試験前日にしかやってないのですが、Youtubeで再生リスト化されている動画を倍速で漫画読みながら見てました。これでA試験は何とかなりました。

## 結論 ギリギリにならないように勉強しよう()
自分、cbtだと受験後点数が出るの知らなくて終了ボタン押したら突然点数が表示されて心臓がドキッとしました。
余裕をもって準備、勉強をしましょう。
ちなみに休憩は普通に飛ばせました。
Elixirの対話モードで文字列の動作を確認してみた

# 概要
Elixirの対話モードで文字列の動作を確認してみました。以下のページを参考にしました。

https://elixirschool.com/ja/lessons/basics/strings

# 対話モードで実行
以下のコマンドを実行しました。
```
$ iex
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> string = <<104,101,108,108,111>>
"hello"
iex(2)> string <> <<0>>
<<104, 101, 108, 108, 111, 0>>
iex(3)> 'hełło'
[104, 101, 322, 322, 111]
iex(4)> "hełło" <> <<0>>
<<104, 101, 197, 130, 197, 130, 111, 0>>
iex(5)> ?Z
90
iex(6)> string = "\u0061\u0301"
"á"
iex(7)> String.codepoints string
["a", "́"]
iex(8)> String.graphemes string
["á"]
iex(9)> String.length "Hello"
5
iex(10)> String.replace("Hello", "e", "a")
"Hallo"
iex(11)> String.duplicate("Oh my ", 3)
"Oh my Oh my Oh my "
iex(12)> String.split("Hello World", " ")
["Hello", "World"]
iex(13)> defmodule Anagram do
...(13)> def anagrams?(a, b) when is_binary(a) and is_binary(b) do
...(13)> sort_string(a) == sort_string(b)
...(13)> end
...(13)> def sort_string(string) do
...(13)> string
...(13)> |> String.downcase()
...(13)> |> String.graphemes()
...(13)> |> Enum.sort()
...(13)> end
...(13)> end
{:module, Anagram,
 <<70, 79, 82, 49, 0, 0, 6, 172, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 208,
   0, 0, 0, 21, 14, 69, 108, 105, 120, 105, 114, 46, 65, 110, 97, 103, 114, 97,
   109, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:sort_string, 1}}
iex(14)> Anagram.anagrams?("Hello", "ohell")
true
iex(15)> Anagram.anagrams?("María", "íMara")
true
iex(16)> Anagram.anagrams?(3, 5)
** (FunctionClauseError) no function clause matching in Anagram.anagrams?/2    
    
    The following arguments were given to Anagram.anagrams?/2:
    
        # 1
        3
    
        # 2
        5
    
    iex:14: Anagram.anagrams?/2
iex(16)> 
```

# まとめ
何かの役に立てばと。
Transite Gateway のベストプラクティス TGWアタッチメント専用サブネットについて整理する


Transit Gateway(以下TGW)をVPCに接続する際には、TGWアタッチメントENIの専用サブネットを作成することがベストプラクティスとして推奨されている。来月あたりには詳細を忘れてそうなので、備忘として情報を整理。

## TGWアタッチメントについて

[Transit Gateway Deep Dive アーキテクチャガイド](https://pages.awscloud.com/rs/112-TZM-766/images/B1-05.pdf)によると、TGWにネットワークをくっつけることを「アタッチメント」という。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/9276b345-4126-d35a-3266-be07c191b633.png)

さらに、[Black Belt](https://www.slideshare.net/AmazonWebServicesJapan/20191113-aws-black-belt-online-seminar-aws-transit-gateway) によると、アタッチメントでは、各AZの1つのサブネットにだけENIを作成している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/5cc2415c-e8c0-ce2a-95ee-bae2e3444b9f.png)

他にサブネットがあっても、TGWへのルートテーブルが設定されていれば、アタッチメントで指定したサブネットに配置されたENIを経由してTGWにアクセスできる。

## TGWアタッチメント専用サブネットとは何か？

**アタッチメントがENIを配置するためだけに作成されたサブネット**のことを指す。
「TGWアタッチメント専用サブネット」という正式な用語があるわけではない。
公式ドキュメントの[Transit Gateway 設計のベストプラクティス](https://docs.aws.amazon.com/ja_jp/vpc/latest/tgw/tgw-best-design-practices.html)によると、この専用サブネットを作成することがベストプラクティスとして推奨されている。
>各 Transit Gateway VPC アタッチメントに個別のサブネットを使用します。各サブネットに対して、小さな CIDR (/28 など) を使用して、EC2 リソースのアドレスが増えるようにします。別のサブネットを使用する場合は、次の項目を設定できます:

引用の通り、小さな CIDR (/28 など)を設定することが推奨されている。ENI以外配置しないのなら、多数のIPアドレスは必要ないのでVPC内のIPを節約する。

## なぜTGWアタッチメント専用サブネットを作成するのか？

専用サブネットの必要性については、[Black BeltのQA](https://aws.amazon.com/jp/blogs/news/webinar-bb-aws-transit-gateway-2019/)で解説されている。
>Q. VPC をアタッチするときに指定するサブネットをアタッチ専用のサブネットとする必要性について、もう少し具体例を挙げて説明していただきたいです。そのサブネットの内部のEC2 インスタンスのルーティングに影響あるとのことでしたが、どのような影響があるのか？などを教えていただきたいです。
A. Transit Gateway (TGW) のアタッチメントがついているサブネットと同一のサブネットに EC2 インスタンスが存在する場合に、その EC2 インスタンスはTGWと同じルーティングテーブルを参照します。
例えば　インライン監査用の VPC の TGW の ENI がある Subnet 上に EC2 インスタンスを設置してしまうと、その EC2 インスタンスは必ずインライン監査のミドルボックス ENI に吸い込まれてしまい、EC2 インスタンスの意図するルーティングテーブルを作れなくなってしまいます。こういったことを防ぐために、TGW 専用のサブネットを作ることをお薦めしています。
こちらおよびこちらの資料を併せてご参照ください。

アタッチメントENIとEC2を同じサブネットに配置すると、同じルーティングテーブルを参照してしまうため、EC2のルーティングの柔軟性が下がってしまう、と解釈している。


下記の記事はさらにネットワーク図を用いながら丁寧に説明されていたのでわかりやすい。

https://zenn.dev/tsumita7/articles/best-plactice-for-dedicated-subnet-in-aws-tgw





## 参考資料

https://pages.awscloud.com/rs/112-TZM-766/images/B1-05.pdf

https://docs.aws.amazon.com/ja_jp/vpc/latest/tgw/tgw-best-design-practices.html

https://www.slideshare.net/AmazonWebServicesJapan/20191113-aws-black-belt-online-seminar-aws-transit-gateway

https://aws.amazon.com/jp/blogs/news/webinar-bb-aws-transit-gateway-2019/

https://zenn.dev/tsumita7/articles/best-plactice-for-dedicated-subnet-in-aws-tgw

https://dev.classmethod.jp/articles/routing-of-the-dedicated-transit-gateway-subnet/
💬配列メソッドまとめ

***:cherries:学んだことを随時まとめてく:cherries:***
<font color="MistyRose">~間違っている点があれば是非教えてください~<font>

# 配列メソッドを使う前に
**「ブロック」と「ブロックパラメータ」について理解する**
- ブロック、ブロックパラメータとは？
    - ブロックとは、<font color="MediumOrchid">doからendまでのプログラムのひとかたまり</font>の部分のこと、メソッドを呼び出すときに渡せる。
    - |  |で囲んだブロックパラメータ（ブロック変数）と呼ばれるものを指定できる。
```ruby:
num = [1,2,3,4,5]

num.each do |n|         #|　|中のnがブロックパラメータ
    puts n if n.odd     #do ~ endまでがブロック/ood 整数が奇数かどうかを判定するメソッド
end
# >>1,3,5

```

# any?
<font color="MediumOrchid">
配列</font>の値を一つずつ<font color="CornflowerBlue">ブロック変数</font>に格納して<font color="MediumOrchid">最低１つ条件</font>に当てはまるか判定
<img src="https://drive.google.com/uc?export=view&id=1TddzJk7hhWcRC3PsIlNhqQs2Hlya9jHD" >

```ruby:
array = [1, 2, 3, 4, 5]

#配列.any? {|ブロック変数|　　条件}
array.any? { |num| num > 3 } #true(4,5が当てはまる)
array.any? { |num| num > 6 } #false（１つも当てはまらない）
```
***
**include?**
<font color="CornflowerBlue">指定した要素</font>が配列に含まれているかどうかを確認
返り値は真偽値で返す
```ruby:
array = [1, 2, 3, 4, 5]
puts numbers.include?(3)  # true
puts numbers.include?(6)  # false
```

# each
配列の各要素に対して指定した<font color="CornflowerBlue">ブロック</font>を順番に実行する
<font color="MediumOrchid">配列の要素数</font>だけブロックが<font color="MediumOrchid">繰り返し実行</font>
```ruby:
numbers = [1, 2, 3, 4, 5]
numbers.each { |num| puts num * 2 }  #{ブロック}
```

# map
配列の各要素に対して指定したブロック内の処理を実行し、
その結果を<font color="MediumOrchid">新しい配列</font>に格納する
```ruby:
numbers = [1, 2, 3, 4, 5]
doubled_numbers = numbers.map { |num| num * 2 }
# >>doubled_numbers = [2, 4, 6, 8, 10]
```

# select
配列の各要素に対して指定した条件<font color="CornflowerBlue">（ブロック内の処理）を満たす要素を抽出</font>し、
<font color="MediumOrchid">新しい配列</font>に格納する
```ruby:
numbers = [1, 2, 3, 4, 5]
even_numbers = numbers.select { |num| num.even? } #even? 整数が偶数かどうかを判定するメソッド
# >>even_numbers = [2, 4]
```
【Swift】配列に使える便利な関数✨

# 1. map

💡 配列の全要素に対して処理を行いたい時に使う！

```sample1.swift
// 配列の全要素を５倍するコード
let array = [1, 2, 3, 4, 5]
let mapArray = array.map { $0 * 5 }
print(mapArray) // → [5, 10, 15, 20, 25]
```
※`$0` はクロージャの引数の値を省略した形である
※`$0`は第一要素, `$1`は第二要素を参照している
※mapは辞書型にも利用できる

# 2. compactMap
💡配列を整理したい時に使う！
配列内にnilがあった場合、nilの要素を除去してくれる
```sample2.swift
let array = [3, nil, 10, 1, nil, nil, 7]
let compactMapArray = array.compactMap { $0 }
print(compactMapArray) // -> [3, 10, 1, 7]
```

また、配列の要素を型変換する時に変換できる値のみを取得することも可能である
```sample2-1.swift
// 配列の要素をInt型に変換
let array = ["3", "qiita", "10", "sample", "nil", "/1/", "7"]
let compactMapArray = array.compactMapArray { Int($0) }
print(compactMapArray) // -> [3, 10, 7]
```


# 3. filter

💡 条件にマッチする要素のみを取り出したい時に使う！

```sample3.swift
// 3未満の数値を取り出している
let array = [1,2,3,4,5]
let filterArray = array.filter { $0 < 3 }
print(filterArray) // → [1, 2]
```

# 4. reduce

💡 要素使って結果をまとめたい時に使う！

※第一引数は初期値となる
```sample4.swift
// 配列内の要素を全て足し合わせる処理
let array = [1,2,3,4,5]
let reduceValue = array.reduce(0) { (num1, num2) -> Int in 
	num1 + num2
}

print(reduceValue) // 15

// 別の記述方法
array.reduce(0, +) // 15
array.reduce(1, *) // 120
```
RubyでAtCoder ABC243(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC243のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - Shampoo
https://atcoder.jp/contests/abc243/tasks/abc243_a
```ruby:a-243.rb
v, a, b, c = gets.split.map(&:to_i)
sum = a + b + c
puts v % sum < a ? "F" : v % sum - a < b ? "M" : "T"
```

# B - Hit and Blow
https://atcoder.jp/contests/abc243/tasks/abc243_b
```ruby:b-243.rb
gets.to_i
a = gets.split.map(&:to_i)
b = gets.split.map(&:to_i)
index_equal = a.zip(b).count{ _1 == _2 }

puts index_equal
puts (a & b).size - index_equal
```
## 解説
`A[i] == B[i]`の場合については、`zip`メソッドと`count`メソッドを使うことで求めることができます。次に、A, B両方に含まれるが位置が異なる要素の数については、`&`を使ってA, B両方に含まれる要素を抽出し、そこから先ほど求めた位置も等しい要素の数を引いたものが答えとなります。

# C - Collision 2
https://atcoder.jp/contests/abc243/tasks/abc243_c
```ruby:c-243.rb
n = gets.to_i
array = Array.new(n){ gets.split.map(&:to_i) }

points = Hash.new{ |h, k| h[k] = [] }
s = gets.chomp.chars
array.zip(s){ |(x, y), c| points[y] << [x, c] }

points.values.each do
  next if _1.size < 2
  _1.sort.each_cons(2) do |(_, l), (_, r)|
    if l == "R" && r == "L"
      puts "Yes"
      exit
    end
  end
end
puts "No"
```
## 解説
連想配列を使って、ｙ座標が同じものでグループ分けします。そして、それぞれについて`value`が２つ以上であれば、衝突するものがあるかどうかを調べることにより答えを求めることができます。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
GMAILで受信エラーした際のSPF設定対策

# Gmail用SPF設定

### 1.事象
GMAILのアドレス宛にメールを送信したらエラー。
■エラーメールの内容
```
　　xxxx@gmail.com host gmail-smtp-in.l.google.com[64.233.187.26] said:
    550-5.7.26 This mail is unauthenticated, which poses a security risk to the
    550-5.7.26 sender and Gmail users, and has been blocked. The sender must
    550-5.7.26 authenticate with at least one of SPF or DKIM. For this message,
    550-5.7.26 DKIM checks did not pass and SPF check for [ynet-inc.com] did
    not 550-5.7.26 pass with ip: [999.999.999.999]. The sender should visit
    550-5.7.26  https://support.google.com/mail/answer/81126#authentication for
    550 5.7.26 instructions on setting up authentication.
    t63-20020a637842000000b0052c54de0299si6381730pgc.637 - gsmtp (in reply to
    end of DATA command)
```
内容を解説すると
☆このメールは認証されておらずセキュリティリスクがある為、Google的には受信NG
☆「SPF認証」又は「DKIM認証」のどちらが必要
☆このメールは「DKIM認証」はチェックNG
☆このメールは「SPF認証」はチェックOK
★しかしメールは999.999.999.999から送られてきているがこれはSPF範囲外である
☆よってGoogleのサポートサイトを見ながら設定してください

との事でした。

### 2.SPFとDKIM
googleさんは外部から送られてくるメールのチェックを2022年11月以降強化しており
SPF認証又はDKIM認証のどちらかの認証がないと受信NG又は迷惑メール扱にしていたとの事。

SPF認証　 ：　DNSにメール配信元のサーバを設定しておくことでなりすましでない事を証明
DKIM認証　：　鍵認証にてなりすましや改ざんがない事を証明

SPFはDNSの設定をするだけで済むのに対し、DKIMはメールサーバに鍵認証を仕込む必要がある。
レンタルサーバの場合はDKIMは設定できないケースも多く、今回利用のメールサーバもDKIMは利用できない。

よってSPFを正しく設定して対処する。

### 3.SPFの設定
SPFの設定はDNSサーバにて実施。
今回はAWSのRoute53での設定を行う。

Route53のホストゾーンに下記SPFレコードを追加
```
  レコード名　　　　レコードタイプ　　値　
　ynet-inc.com　　　TXT　　　　　　　 "v=spf1 ip4:999.999.0.0/16 ~all"
```
ポイントはGMAILのエラーメールにあった ```pass with ip: [999.999.999.999]. The sender should visit```この部分。

この[999.999.999.999]が送信元サーバのIPなのでこのIPからの送信であればOKとしてあげる必要がある。なのでspfのレコードにて```ip4:999.999.0.0/16```を設定してあげる事で、送信元サーバの認証がＯＫとなる。

IPそのものではなくサブネット指定にしているのはプロバイダー内でメールサーバを経由して最終的にIPは変わる可能性があるのでプロバイダーのサブネットで指定を行った方が良い。
Pythonでマルコフ連鎖みたいなものを作ってみた

# 概要
ある日私はこう思いました。

無限に文章を作るプログラムを作ってみたい！

と。

ですが私はAIを作る技術もありません。
そこで目に入ったのが**マルコフ連鎖**です。

# janome入れる
janomeってのは日本語を分かち書きしたりするライブラリです。
janomeを入れるコマンドは以下のようになります。
```winbatch
pip install janome
```
もしくは
```winbatch
py -m pip install janome
```

ちなみに同じようなライブラリとしてMeCabというのもあるみたいです。
# とりあえず書く

とりあえず書いてみましょう。テキストデータを先に作っておきます。これはBingAIに作らせました。
```textdata.txt
C++の難しさについて笑ってみましょう
C++はプログラミング言語の中でも特に難しいと言われています。なぜでしょうか？
それは、C++が多くの機能を持ちすぎているからです。
C++はオブジェクト指向、ジェネリック、関数型、メタプログラミングなど、さまざまなパラダイムに対応しています。
しかし、それらの機能を使いこなすには高度な知識と経験が必要です。
C++は自由度が高い分、落とし穴も多いのです。

例えば、C++ではポインタという概念があります。
ポインタとは、メモリ上のある場所を指し示すものです。
ポインタを使えば、効率的にデータを扱うことができます。
しかし、ポインタを使い間違えると、
メモリリークやセグメンテーション違反などの深刻なエラーを引き起こす可能性があります。
ポインタを扱うには、メモリ管理の仕組みやアドレス空間の
構造などを理解しておく必要があります。
```

テキストデータは完成しました。
プログラム本体も書いてみましょう。

```python
import random
from janome import tokenizer

word_dicts = {}

textdata_file = open("textdata.txt", "r", encoding="utf-8") #テキストデータを読み込みます。

textdata = textdata_file.read()
textdata = textdata.replace("\n", "")

Tokenizer = tokenizer.Tokenizer(wakati=True) #分かち書きモードのTokenizerを設定します。
textdata_wakati = Tokenizer.tokenize(textdata) #ここで分かち書きをします。

word_list = list(textdata_wakati)

word_list.append("EOS") #生成を終わらせる単語

for i in range(0, len(word_list) - 1):
    word = word_list[i]
    word_dicts[word] = []

for j in range(0, len(word_list) - 1):
    word = word_list[j]
    next_word = word_list[j + 1]
    word_dicts[word].append(next_word)    

#生成する

g_word = word_list[0]
print(g_word,end = "")
for i in range(100):
    g_word_list = word_dicts[g_word]
    indexs = word_list.index(g_word)
    if len(g_word_list) > 0:
        g_word = random.choice(g_word_list)
    else:
        g_word = word_list[ indexs + 1 ]

    if g_word == "EOS":
        break
    else:
        print(g_word, end = "")
```

汚いコードでごめんなさい
実行結果です。
一つ目
```
C++でも特に難しいと言われているからです。しかし、落とし穴も多いの機能を持ちすぎてみましょうC++が必要です。ポインタを使い間違えるとは、C++でも特に
難しいと、さまざまな知識と経験があります
```
二つ目
```
C++ではポインタを使い間違えるとは、ポインタを使えば、メタプログラミングなどの難しさについて笑っておく必要です。ポインタと経験が必要です。ポインタ 
を指し示すものです。ポインタという概念があります。C++では自由度があります。C++は自由度があります。C++は自由度が多くの中では、さまざまなエラーを扱 
うには、C++は高度なパラダイムにはオブジェクト指向、メモリ管理
```

# 終わりに

マルコフ連鎖であるのかはわかりませんでしたが、文章生成できたのでよしとしましょう。
若干不自然なところはありますけど悪いってわけでもないと思います。

ここまで読んでくれてありがとうございました。
新しめのintelコンパイラを使う場合のopenMXのコンパイルの注意点

[公式にインストールの方法が書かれている](https://www.openmx-square.org/openmx_man3.9jp/openmx3.9_jp.html)ので殊更に細かく書く必要はないと思うし書かないが、詰まって半日使う羽目になったのでその部分だけメモ。
結論から言うとintelのコンパイラが新しくなった影響で、諸々のwarningがerrorになったせいで通らなかったようです。

インストールのコマンド自体は`make`して`make install`するだけですが、`makefile`のオプションが曲者です。
今回は産総研のABCI上でコンパイルするのでmklとかfftw3の場所が特殊ですが、適宜読み替えてください。
```makefile:makefile
MKLROOT = /apps/intel/2023.0/mkl/2023.0.0
CC = mpicc -O3 -xHOST -qopenmp -I/apps/intel/2023.0/mkl/2023.0.0/include/fftw/ -I${MKLROOT}/include -Wno-implicit-function-declaration -fcommon
FC = mpiifort -O3 -xHOST -no-prec-div -qopenmp
LIB= -L${MKLROOT}/lib/intel64 -lmkl_scalapack_lp64 -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -lmkl_blacs_intelmpi_lp64 -liomp5 -lpthread -lm -ldl -lifcore
```

問題なのはCCの部分で`-Wno-implicit-function-declaration`と`-fcommon`を追加しています。
まず`-Wno-implicit-function-declaration`ですが、これは暗黙の関数宣言を認めるというオプションになっています。昔からwarningは出ていたと思うのですが、それが[errorになった](https://community.intel.com/t5/Intel-C-Compiler/Build-failure-with-with-newer-2022-2-compiler-in-pipeline/m-p/1419482)のでこのオプションをつけないと
```
ISO C99 and later do not support implicit function declarations
```
的な出力が出ます。
次に`-fcommon`ですが、詳しくは知らないので[他の記事](https://qiita.com/yasuhirokimura/items/d5337d73a016502b9d54)を見ていただくとして、やはりC言語周りの変更の影響のようです。これも入れないと
```
multiple definition of ~~~
```
という感じの出力が大量に (数万行) 出ます。

南無三。
ElastiCache(Redis)のインスタンス1つを、複数のLaravelアプリで共有して利用できるか

コストを抑えるために、2つの全く関連のないLaravelアプリで、ElastiCacheを利用しようとした際に、
それぞれのアプリで、キーバリューが干渉してしまうのではないかと考え、調べてみたのですが、
思ったよりも時間がかかってしまったので、簡単ですが投稿します！

## 結論: 問題なさそう！

### 調査内容
- stackoverflowに完璧な回答がありました。
要約すると、Redisに追加する際に、prefixをキーに追加して区別することができそうです。
Laravel10ではconfig/cache.phpで、デフォルトでAPP_NAMEを埋め込んでくれていました。

https://stackoverflow.com/questions/31272649/using-redis-for-queues-for-multiple-laravel-applications-on-a-single-server

> //関連部分翻訳
https://laravel.com/docs/5.6/queues#driver-prerequisites が言っています：
redisキュードライバーを使用するには、config/database.php設定ファイルでRedisデータベース接続を構成する必要があります。
そして、https://laravel.com/docs/5.6/redis#predis が言っています：
デフォルトのホスト、ポート、データベース、およびパスワードサーバーの構成オプションに加えて、Predisは、あなたのRedisサーバーごとに定義することができる追加の接続パラメータをサポートしています。これらの追加設定オプションを利用するには、config/database.php設定ファイル内のRedisサーバー設定に追加してください。
connection parameters」ページを読むと、最終的にhttps://github.com/nrk/predis/wiki/Client-Options、「prefix」がサポートされているオプションであると書かれています。

- また、Laravel10だと、Laravelのconfig/cache.php内にも以下の記述がありました。
```
    /*
    |--------------------------------------------------------------------------
    | Cache Key Prefix
    |--------------------------------------------------------------------------
    |
    | When utilizing the APC, database, memcached, Redis, or DynamoDB cache
    | stores there might be other applications using the same cache. For
    | that reason, you may prefix every cache key to avoid collisions.
    |
    */

    'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'),
```
>#和訳
APC、データベース、memcached、Redis、DynamoDBのキャッシュストアを利用する場合、同じキャッシュを利用する他のアプリケーションが存在する可能性があります。そのため、衝突を避けるために、すべてのキャッシュ・キーにプレフィックスを付けることがあります。
週一でPython勉強会やってみる⑨

前回の続き

https://qiita.com/Waddy675/items/5829890652ea98b1106a

諸事情により勉強会の日をずらす・・・人は来ないようだ・・・泣

## セル名と行番号・列番号を相互変換
- セル名で指定したい場合や、行と列が分かってる場合などに変換ができるとよりエクセルが使いやすくなる。
- cellオブジェクトにrowやcolumnプロパティがあるので行と列番号は取得できる。
``` py
cell = sheet["C5"]
print(cell.row, cell.column) # 行と列番号が表示される
# 4 3
```
- 逆にcellのcoordinateプロパティを使えばセル名が取得できる。
``` py
cell = sheet.cell(2,3)
print(cell.coordinate) # セル名が表示される
# C2
```

## データが何行まであるか分からない時
- GASではgetLastRow()で取得できた。
- 同様に`max_row`と`max_column`で取得できる。
- ただし、罫線などが入っている場合は有効範囲が罫線の最後までになってしまうので注意
（解決策としては取り出した後に切ないが空かどうかを判定する）
``` py
rows = sheet["A1":"G55"]
for row in rows:
    values = [cell.value for cell in row]
    if values[0] is None: break #セル未入力の場合はNoneになる
    print(values)
```
- `iter_rows`でも取り出しが可能。さらに`min_row`や`max_row`で取り出す範囲の指定が可能。
``` py
for row in sheet.iter_rows(min_row = 3, max_row = 7):
    values = [cell.value for cell in row]
    if values[0] is None: break #3行目以降7行目までが取り出される
    print(values)
```

## シートの操作
- `create_sheet`で新規のシートを作成できる
``` py
sheet = book.create_sheet(title="シート名")
```

- `copy_worksheet`でシートをコピーできる
``` py
sheet = book.copy_worksheet(book["シート名"])
```

- シート名を変更する
``` py
sheet.title = "変更シート名"
```

- シートを削除する
``` py
book.remove(book["シート名"])
```

## おまけ
エクセルを暗号化したり復号化したりすることも可能。
ライブラリのおかげでエクセルはかなり使えるようになっている。

次回はセルの装飾周りかなー
TypeScriptのEnumとアンビエントEnumの違いについて超わかりやすく説明！

みなさんこんにちは！
今回はEnumとアンビエントEnumの違いについて、雑魚エンジニアでもわかるように説明していきます。
一緒に頑張りましょう！
※説明の大部分はchatGPTを使いました。

## Enumとは
まず、Enumとは何かを理解するために、私たちがよく知っているもの、例えば「季節」を考えてみましょう。季節は4つありますね。春、夏、秋、冬です。これらは一年を通して変わらず、特定の順序で繰り返されます。これがEnum（列挙型）の基本的な考え方です。TypeScriptのEnumは、特定の数の固定された選択肢を表現するのに便利なツールです。

    enum Season {
        Spring = 1,
        Summer = 2,
        Autumn,
        Winter
    }

このとき、AutumnとWinterには自動的に3,4が割り当てられます。

## アンビエントEnumとは
次に、アンビエントEnumについて考えてみましょう。これは、Enumがすでに何らかの方法で定義されているが、TypeScriptがその型情報を必要とする場合に使用されます。これは、あなたが友達の家に遊びに行って、その家のルールを学ぶ必要がある状況に似ています。ルールはすでに存在しますが、あなたはそれを理解し、それに従う必要があります。

    declare enum Season {
        Spring,
        Summer,
        Autumn,
        Winter
    }

## 違い
ここで重要なのは、アンビエントEnumは実際の値を持たないということです。これは、友達の家のルールがあなたの家のルールとは異なる可能性があるため、あなたがそのルールを適用することはできないということに似ています。

また、通常のEnumでは、初期化処理を持たないメンバーは、定数メンバーとみなされます。これは、新しいクラスに入った生徒が、すぐにクラスの一員として受け入れられるということに似ています。

一方、アンビエントEnumでは、初期化処理を持たないメンバーは、計算されたメンバーであるとみなされます。これは、転校生が新しい学校での役割や規則を理解し、それに適応する過程を経るということに似ています。つまり、アンビエントEnumは通常のEunmのように自動的に値が割り振られません。

アンビエントEnumは、別で宣言されている変数を、まとめてEnumとして設定しているための存在なのです。
なぜこんなことが起きているかというと、JavaScriptにはEnumという概念がないため、JavaScriptのコードでは通常オブジェクトや数値、文字列を使ってEnumのような機能を実現します。そのようなJavaScriptのコードをTypeScriptで扱うためには、そのEnumの型情報をTypeScriptに伝える必要があるからです。




以上です。
ここまで読んでくださりありがとうございます！
Amazon S3 VPCエンドポイント　インターフェイス型/ゲートウェイ型

# はじめに
S3用のVPCエンドポイントでインターフェイス型を選択できるようになって、どちらを使用するか迷ったことがあるので、ゲートウェイ型との違いを、まとめたいと思います。

# VPCエンドポイント2種の違い

|  |インターフェイス型 | ゲートウェイ型 |
|:-:|:-:|:-:|
|経路|awsネットワーク経由|awsネットワーク経由|
|オンプレ環境からの使用※1|<font color="Red">可能</font>|不可|
|ピアリング先からの使用※1|<font color="Red">可能</font>|不可|
|料金|<font color="Red">有料</font>|無料|
|使用されるIPアドレス※2|<font color="Red">プライベートIP</font>|パブリックIP|
|アクセス制限|SG+エンドポイントポリシー|エンドポイントポリシー|
|アクセス方法※3|エンドポイントのDNS名を追加で使用|S3のUriのみで可|
|作成時の紐付け対象|サブネット|ルートテーブル|

※1.オンプレ環境及びVPCピアリング先からの使用
ゲートウェイ型ではIGWなどと同様に、ピアリング先のVPCにあるゲートウェイを使用することはできません。
![スクリーンショット 2023-06-13 22.32.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472762/35712cbe-8c18-51da-b774-87bf9cad6b54.png)






※2.使用されるIPアドレスの違い
- インターフェイス型はサブネット毎にENI(Elastic Network Interface)が作成され、ENIにプライベートIPが割り振られる為、対象サービスにはプライベートIPでアクセスします。
- ゲートウェイ型はVPCエンドポイントにパブリックIPが割り振られる為、対象サービスにはパブリックIPでアクセスします。(ただしインターネットには出ません。AWSネットワーク内で完結します。)
![スクリーンショット 2023-06-12 22.05.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472762/b75e910f-42a2-595f-856c-d3d98732f7ab.png)

※3.アクセス方法の違い
```bash
#インターフェイス型
#エンドポイントのDNS名：　*.vpce-xxxxxx.s3.us-east-1.vpce.amazonaws.com
aws s3 ls s3://my-bucket/ --region us-east-1 --endpoint-url https://bucket.vpce-xxxxxx.s3.us-east-1.vpce.amazonaws.com 

#ゲートウェイ型
aws s3 ls s3://my-bucket/ --region us-east-1 
```

#### 使い分け
本題の使い分けに関しては、下記3点を基準に考えていくのがいいと感じました。
| 用途 | 型 |
|:-:|:-:|
|オンプレや他のVPCから使用したい場合|インターフェイス型|
|無料で使用したい場合|ゲートウェイ型|
|プライベートIPでアクセスしたい場合|インターフェイス型|

# 最後に
今回インターフェイス型とゲートウェイ型のVPCエンドポイントの違いを確認しましたが、
プライベートIPを使用してバケットポリシーにてアクセス制御したい等の特別な要件がない限り、勉強用としては基本的に無料で使用することができるゲートウェイ型を使うのがいいと感じました。

なお、プライベートIPはVPCエンドポイントに紐づているサブネット毎のENIから確認することができます。
電子コントローラーの探求により精度と効率を解き放つ

はじめに: 電子コントローラーは、自動車や産業機械、家庭用電化製品、航空宇宙システムに至るまで、さまざまなデバイスにわたってイノベーションを形成し、機能を向上させる上で重要な役割を果たしています。電子コントローラーは、シームレスな操作、正確な制御、効率の向上、シームレスな操作の有効性の向上を保証します。正確な制御、効率の向上。私たちは彼らの世界を深く掘り下げ、彼らの内部の仕組み、応用、そして日常生活に与える深い影響を探ります。

電子コントローラーを理解する:
電子コントローラは、制御ユニットまたはシステムとも呼ばれ、さまざまな形式の機械やシステムを調整および監視するように設計された電子デバイスです。これらのコントローラーは、制御または管理するシステム内のセンサーからのセンサー読み取り値などの入力信号を受信し、アルゴリズムと論理回路を使用してそれらを処理し、出力信号を生成します。出力信号は、アプリケーションによって課せられる、事前に設定された望ましいルールまたはガイドラインに従ってシステムの動作を制御します。対象となるアプリケーションの複雑さの要件に応じて、必要に応じて 1 つのデバイスまたは複数のネットワークにわたって使用できます。

電子コントローラーの種類:
電子制御装置には、さまざまな用途に応じてさまざまな種類があります。一般的な品種は次のとおりです。
マイクロコントローラー: これらのコンパクトなコントローラーには、オンボードのマイクロプロセッサー、メモリー、入出力周辺機器が含まれています。そのため、家庭用電化製品、自動車システム、ホームオートメーションのアプリケーションで広く利用されています。

プログラマブル ロジック コントローラー (PLC): PLC は産業オートメーション向けに特別に設計された耐久性の高いコントローラーであり、過酷な環境でも信頼性が高く、製造、プロセス制御、インフラストラクチャ管理、インフラストラクチャ監視で PLC を簡単かつ効果的に利用できます。

デジタル シグナル プロセッサ (DSP): DSP はリアルタイム信号の処理に特化しており、オーディオ/ビデオ処理、通信システム、医療画像システムに適しています。

電子制御ユニット (ECU): ECU は、エンジン管理、トランスミッション制御、車両の安定性などの機能を調整するために自動車アプリケーションで使用される電子コントローラーです。

電子コントローラーの用途:
電子コントローラーは、幅広い業界に多大な影響を与えてきました。
電子コントローラーは自動車分野に革命をもたらし、アンチロック ブレーキ システム (ABS)、トラクション コントロール、エレクトロニック スタビリティ コントロール、インフォテインメント システムなどの高度な機能を提供するとともに、エンジン性能を最適化することで燃費にも貢献しています。

航空宇宙および防衛: 電子コントローラーは、航空機のアビオニクス、飛行制御システム、航行支援装置、兵器システムにおいて重要な役割を果たし、ミッションクリティカルな運用中の安全性、精度、信頼性を向上させます。

ホーム オートメーション: コントローラーは、照明、温度、セキュリティ システム、家電製品を管理することでスマート ホームを管理し、シームレスな統合とパーソナライズされたエクスペリエンスを提供します。

d) ヘルスケア: ペースメーカー、MRI 装置、輸液ポンプなどの医療機器は、電子コントローラーを使用してバイタルサインを監視し、データを処理し、カスタマイズされた治療を提供します。

e) 産業オートメーション: 電子コントローラーは製造プロセスを自動化し、ロボット工学、組立ライン、マテリアルハンドリングアプリケーション全体で効率と一貫性を向上させます。

電子コントローラーの利点:
電子コントローラーの使用にはさまざまな利点があります。

精度: 電子コントローラーは正確な測定を提供し、誤差を減らしながらパフォーマンスを最適化するきめ細かい制御を提供します。
b) 効率: 電子コントローラーはシステムをリアルタイムで継続的に監視および制御することでエネルギー効率を向上させ、コストを削減しながらリソースを節約します。

c) 適応性: コントローラーは、変化する要件に合わせて簡単に更新したり、適切な状態を維持するためにプログラムを更新したりすることができるため、進化するテクノロジーやニーズに高度に適応できます。

d) 診断機能: 電子コントローラーは、迅速なトラブルシューティングとプロアクティブなメンテナンスのための貴重な診断機能を提供し、トラブルシューティング作業を迅速に行うのに役立ちます。

将来の傾向と発明: 技術の発展に伴い、電子コントローラーも進歩し続けています。将来のトレンドについての興味深い調査には次のようなものがあります。

<a href="https://www.multispanindia.com" target="_blank" rel="noopener">モノのインターネット</a> (IoT) デバイスの統合: 電子コントローラーは IoT デバイスをシームレスに組み込み、相互接続されたシステムとリアルタイム データに基づくインテリジェントな意思決定を作成します。

人工知能の統合: AI を活用したコントローラーは、高度な予測分析、自律的な意思決定機能、適応制御システムを提供します。

エッジ コンピューティング: エッジ コンピューティングは、コントローラー自体にコンピューティング機能を組み込むことで、応答時間の短縮、待ち時間の短縮、プライバシー保護の強化を促進します。

d) サイバーセキュリティ: より多くのデバイスが接続されると、電子制御装置は包括的なサイバーセキュリティ対策を実装して、潜在的なサイバー脅威から身を守ることになります。

結論：
電子コントローラーは、正確な制御、効率の向上、高度な機能を提供することで、さまざまな産業に革命をもたらしてきました。自動車システムから産業オートメーションのオートメーションに至るまで、その影響は日常生活を通して感じられます。時間が経つにつれて、電子コントローラーはさらに進化し、相互接続、人工知能、効率の向上を実現し、模範的な方法で精度と知性が融合する時代を生み出します。
CloudFormationのFn::FindInMapとFn::Subの合わせ技で環境別テンプレートを一元管理

## CloudFormationのテンプレート管理の課題
環境ごとに作成するAWSのリソースは同じだが、設定値など環境ごとに値を変えたい場合があると思います。
そのようなとき、一般的にはparameterを設定し、全環境で同じテンプレートを使用できるようにすると思います。

しかし、その場合個人的には以下の課題があるなと感じました。
- CloudFormation実行時にparameterを渡すのが手間
    - parameterが数10またはそれ以上あると余計に大変
    - stack作成・更新時にparameterに渡す値をミスる可能性がある
    - CLIやAWS SDKを使用してstack作成・更新を行う場合、parameterの追加・削除ごとに処理を修正する必要がある


環境ごとにテンプレートを用意する、という解決策もありますが、管理が冗長になり、環境によってテンプレートの更新漏れなどが生じる可能性もあります

ではどうすればよいのか。


## 解決策
Fn::FindInMapとFn::Subをうまく活用することで、上記課題を解決できることができます！


以下、AWS SecretsManagerのテンプレートを例に挙げます。

```
Parameters:
  EnvName:
    Default: dev
    Type: String

Mappings:
  Map:
    Test1:
      dev: 'test1-dev'
      stg: 'test1-stg'
      prod: 'test1-prod'
    Test2:
      dev: 'test2-dev'
      stg: 'test2-stg'
      prod: 'test2-prod'

Resources:
  AutomationTest:
    Type: 'AWS::SecretsManager::Secret'
    Properties:
      Name: !Sub test/${EnvName}
      SecretString: !Sub
      - |
        {
           "TEST1":"${Test1}",
           "TEST2":"${Test2}"
        }
      - {
          Test1: !FindInMap [Map, Test1, !Ref EnvName],
          Test2: !FindInMap [Map, Test2, !Ref EnvName]
        }


```

上記のようにすることで、CloudFormation実行時に渡すparameterは1つになり、課題を解決することができます。
環境ごとに差分がある値が増えたとしても、その値を上記のMapに追加し、SubとFindInMapを使用しその値を参照できるようにすればparameterの追加は不要で環境差分にも対応できます。

特に、以下の課題が解決できるので、自動更新の仕組みを構築しやすくなると思います。
>CLIやAWS SDKを使用したstack作成・更新を行う場合、parameter変更ごとに処理を修正する必要がある

自動更新の仕組みは、例えば
GitHubでテンプレートを管理し、テンプレートが更新されるとGitHub ActionsのワークフローからAWS CLI呼び出してstackを自動更新する、など。



テンプレート管理に関して、ほかにももっと良い方法あるよって方はぜひ教えてください。


## 参考ページ

テンプレートのサンプル
https://github.com/awslabs/aws-cloudformation-templates/blob/master/aws/services/CloudFormation/FindInMap_Inside_Sub.yaml

FindInMap
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html

Sub
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html
argocdで完了済みのJobを自動削除する

# Jobの自動削除
[終了したJobの自動クリーンアップ](https://kubernetes.io/ja/docs/concepts/workloads/controllers/job/#clean-up-finished-jobs-automatically)で記載のある通り、kubernetes v1.23でGAされている
`.spec.ttlSecondsAfterFinished`フィールドを使用してJobの完了または失敗から任意の時間後にJobをカスケード的に削除できる。

以下説明に使用するマニフェストです。待機時間は不要だと思って`ttlSecondsAfterFinished: 0`としました。
```yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: pi-with-ttl
spec:
  ttlSecondsAfterFinished: 0
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
```

# Out of Syncの発生
`ttlSecondsAfterFinished`で完了済みのJobが自動で削除されるようになったはいいものの、[Deleted jobs by TTL controller show application as "Out of Sync"](https://github.com/argoproj/argo-cd/discussions/8247)で話されていることと同じ現象がおきました。

公式ドキュメントを漁っていると、[Sync Status with Jobs/Workflows with Time to Live (ttl)](https://argo-cd.readthedocs.io/en/stable/user-guide/resource_hooks/#sync-status-with-jobsworkflows-with-time-to-live-ttl)のようなものを見つけ、`.metadata.annotations`に以下の二つを指定することで解決できそうです。
```yaml
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
```
argoのUIでJobに⚓マークが出て、無事にSyncedとなった。

# Jobの完了を待ち続ける (Last Sync: Syncing)
上記のannotationsでOutofSyncが正常に`Synced`になったのですが、`LastSync`がずっと`Syncing`のままなので何かまちがっている。

argoのメッセージには`waiting completion job`(のような雰囲気)が出ていたので、もしかするとJobの完了後に即削除していたので、argo側が認識する前にリソースが削除されていると予想。

そこで以下のように、Jobの削除に待機時間を設けてみる。
```yaml
# .spec
ttlSecondsAfterFinished: 10
```
ここまで長く待つ必要はないが、`Last Sync`も`Synced`となった。

# 参考
- [終了したJobの自動クリーンアップ](https://kubernetes.io/ja/docs/concepts/workloads/controllers/job/#clean-up-finished-jobs-automatically)
- [Deleted jobs by TTL controller show application as "Out of Sync"](https://github.com/argoproj/argo-cd/discussions/8247)
- [Sync Status with Jobs/Workflows with Time to Live (ttl)](https://argo-cd.readthedocs.io/en/stable/user-guide/resource_hooks/#sync-status-with-jobsworkflows-with-time-to-live-ttl)
Webを支える技術　第2部　URI

備忘録です。

## 第4章 URIの仕様

- URI（Uniform Resource Identifier）
    - リソースを統一的に識別するID
    - URLとURNの総称
- URIの例
    - http://yohei:pass@blog.example.jp:8000/search?q=test&debug=true#n10
        - URIスキーム: http
        - ユーザー情報: yohei:pass
        - ホスト名: blog.example.jp
        - ポート番号: 8000
        - パス: /search
        - クエリパラメータ: q=test&debug=true
        - URIフラグメント: #n10
- 相対URI
    - 相対URIはURIスキームやホスト名を省いて、パスだけ表現する
- ベースURI
    - 相対URIの起点となるのがベースURI
    - ベースURIの与え方
        - リソースのURIをベースURIにする
            - クライアント側でリソースURIを保存しておかなければならないのがネック
        - HTMLやXMLで明示的にベースURIを指定する
            - <head>, xml:base属性を使う
- %エンコーディング
    - URIでは、ASCII文字（アルファベット、数字、記号）のみ使えるので、日本語などは%エンコーディングする
    - （%エンコーディングでは）大文字小文字は区別しない（大文字推奨）
    - URIに%を使いたい時は、%25などとする
    - サーバー提供のURIなら問題ないが、クライアント側で生成する場合はどの文字エンコーディングを使うか問題になる
        - 一般的には元のWebページのエンコーディングに準じるとよい
        - UTF-8が無難
- URIの長さ
    - 2038バイトまで

## 第5章 URIの設計

- 変わらない（変わりにくい）URIの設計を目指す
    - 言語依存の拡張子やパスを含めない
        - http://example.jp/cgi-bin/login.pl
            - cgi-binは実装依存
            - 拡張子を入れない
        - http://example.jp/servlet/LoginServlet
            - 特定のサーブレットコンテナを想定している
            - LoginServletの大文字は実装言語依存
    - メソッド名やセッションIDを含めない
        - http://example.jp/Login.do?action=showPage
            - メソッド名を入れない
        - http://example.jp/home.jsp?jsessionid=12345678
            - セッションIDの埋め込み
    - URIはリソースを表現する名詞にする
        - http://example.jp/sample/people/show/123
            - リソースに対するアクションは、URIでなくHTTPメソッドで決定すべき
- loginページの設計例
    - http://example.jp/login
        - ログインフォームリソースのURIを表すのに相応しい名詞は何か
        - loginformやloginpageは冗長なのでloginとする
        - サイトの共通ログインページなのでパスも必要なさそう
- URIのユーザビリティ
    - 端的な名前にする
    - 一般の人でも使いやすい名前にする
- URIを変更したい時
    - 前提として、安易に変更してはならないことに注意
    - 変更する際はできる限りリダイレクトするようにする
- コンテントネゴシエーション
    - クライアントの言語設定に応じて、返すリソースの言語（英語・日本語）を切り替えることができる
    - このように1つのリソースが複数の表現を持つ時、リソースの表現に.ja, .enのような拡張子を使うのは有効
    - 他にも.html, .txt, .jsonなども考えられる
- マトリックスURI
    - ；や,で複数パラメータの組み合わせで表現するリソースに使える
        - http://example.jp/map/lat=35.705471;lng=139.751898
    - ,はパラメータの順序が意味を持つ場合に使う
- URIの不透明性
    - URIをクライアント側で組み立てたり、拡張子からリソースの内容を推測したりできないこと
    - クライアントを作る際は上記の原則を意識しなくてはならない
技術記事を毎日投稿し始めて1年2ヶ月が経った

# はじめに
IT業界は日々進化していきます。
その進化についていくには継続的な努力が不可欠です。

私は継続的な努力のため、技術記事を毎日投稿し続けるという取り組みを始めました。

この記事では、私が技術記事を1年2ヶ月毎日投稿し続けた経験から得たものを共有します。
アウトプットを継続するメリットについてまとめました。

# メリット1 - 学んだことの復習
技術記事を書くことは、学んだことを自身の言葉でまとめ直すプロセスです。
このアウトプットの過程で、自分の理解度や知識の抜け漏れを発見することができます。
自分が他人に教えるつもりで記事を書くことで、学んだことをより深く理解することができます。

ラーニングピラミッドで学習定着率の最も高い「他の人に教える」を自分だけで完結することができます。

![learning_pyramid-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d95e028f-ddf9-c67b-c95a-ab51d5393960.jpeg)
出典：[キャリア教育ラボ](https://career-ed-lab.mynavi.jp/career-column/707/#:~:text=%E5%B9%B3%E5%9D%87%E5%AD%A6%E7%BF%92%E5%AE%9A%E7%9D%80%E7%8E%87%E3%81%8C%E5%90%91%E4%B8%8A%E3%81%99%E3%82%8B%E3%80%8C%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%83%94%E3%83%A9%E3%83%9F%E3%83%83%E3%83%89%E3%80%8D%E3%81%A8%E3%81%AF%EF%BC%9F%201%20%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%83%94%E3%83%A9%E3%83%9F%E3%83%83%E3%83%89%E3%81%A8%E3%81%AF%202%20%E5%AE%9A%E7%9D%80%E7%8E%87%E5%90%91%E4%B8%8A%E3%81%AE%E3%82%AB%E3%82%AE%E3%81%AF%E3%80%81%E8%83%BD%E5%8B%95%E7%9A%84%E3%81%AA%E5%AD%A6%E7%BF%92,3%20%E3%82%AB%E3%82%AF%E3%83%86%E3%83%AB%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%83%BC%E5%8A%B9%E6%9E%9C%E3%81%A8%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%83%94%E3%83%A9%E3%83%9F%E3%83%83%E3%83%89%204%20%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%83%94%E3%83%A9%E3%83%9F%E3%83%83%E3%83%89%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E5%AD%A6%E7%BF%92%E6%B3%95%E4%BA%8B%E4%BE%8B%205%20%E3%81%BE%E3%81%A8%E3%82%81)

# メリット2 - 猛者エンジニアからのフィードバック
技術記事はエンジニアとのコミュニケーションの手段でもあります。
記事を公開することで、読者からフィードバックやコメントを受けることができます。
このフィードバックを通じて、自身の誤りや改善点に気付くことができます。

私は経済学部で周りにエンジニアがいないので、フィードバックはとてもありがたいです。

また、会話が生まれることで人間関係も構築できる可能性があります。

# メリット3 - 自己ブランディング
技術記事の継続的な投稿は、自己ブランディングにも繋がると考えています。
エンジニアは技術記事をチェックしていると思うので、名前やアイコンを覚えてもらえる可能性が高まります。

実際に面接などで「なんかアイコン見たことある」って言われたり、TwitterのDMで仕事の依頼が来るようになりました。

また、エンジニアではない方にも努力がわかりやすいので関心を示してもらえると思います。

# メリット4 - 備忘録
1年前にやったことは大抵忘れます。
そして、1年前に躓いた内容で、再び躓くことは頻繁にあります。

躓いた時に記事を書いておけば、再び躓いた時に自身の記事を見て悩まずに解決することができます。

私は何度も過去の自分に助けられてます。

# メリット5 - 学習の促進
技術記事の継続的な投稿は、学習の促進にも役立ちます。

毎日アウトプットしないといけないということは、毎日インプットしなければいけません。
このサイクルは学習を促進させます。

学習を習慣化することができればライバルに圧倒的な差をつけることができるでしょう。
習慣化の壁は最初の3ヶ月くらいです。
そこを乗り越えたら義務感が出てきて辛さがなくなります。

# おわり
いいね嬉しいです！

他にもこんな記事を投稿してるのでもしよければ見てください！

https://qiita.com/SNQ-2001/items/8002961602ce9bfbb9b6

https://qiita.com/SNQ-2001/items/0d4fe12f4bc13d422c43
ffmpegのパス設定（Bash/windows）

### 本記事の背景
本記事はffmpegを使う時にPathを通さないと上手くプログラムが動かないため、
パスを通す手順メモを残す

### install
インストール手順については省略する
インストール後に以下のパスにファイルが置かれているとする
```terminal
$ ls
ffmpeg.exe*  ffplay.exe*  ffprobe.exe*
$ pwd
/d/python_pgm/bin
```

### パスを通す（Bash）
```terminal
export export PATH=$PATH:/d/python_pgm/bin
```
### パスを通す（Windows)
環境変数を設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576081/81259490-ff04-a0f0-b84f-3335e9890f36.png)

### Pythonの仮想環境でpipインストール
```terminal
pip install ffmpeg-python
``` 
### 余談
上記の設定で何をするかについてわかる人はわかるので、あえて説明しません。

### 参考文献
https://qiita.com/iam1at/items/91cb8478160c9fbee134
https://qiita.com/studio_haneya/items/a2a6664c155cfa90ddcf
【AWS SAM Go】.envファイルの制約と環境変数設定のシンプルな解決策

# 結論
SAM+golangでは、.envで環境変数は設定できませんでした。

<font color="gray">参考
https://github.com/aws/aws-sam-cli/issues/1355</font>

以下方法で設定します。
- ローカル
    - local.jsonで設定
- 環境ごとのデプロイ
    - template.yamlにEnvironmentMapで設定

## 詳細
調べると他にもいろいろな設定方法がありましたが、どれにするのか迷ってしまったので、ここではシンプルに記載します。

他を知りたい方はまとめ記事などあったのでそちらを見てください。

### ローカル
- local.jsonを追加
```local.json
{
  "Function": {
    "ENV": "local",
    "HOST": "local-host"
  }
}
```

- template.yamlにEnvironmentを追加
```template.yaml
Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      Environment:
        Variables:
          ENV:
          HOST:
```

- local実行コマンド
```
sam local start-api --env-vars XXX/local.json
```

os.Getenv("HOST")などで出せます。

### デプロイ
- template.yamlを修正
```template.yaml
Parameters:
  Env:
    Type: String
    AllowedValues:
      - dev
      - stg
      - prd
Mappings:
  EnvironmentMap:
    dev:
      host: "dev-host"
    stg:
      host: "stg-host"
    prd:
      host: "prd-host"
Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      Environment:
        Variables:
          ENV: !Ref Env
          HOST: !FindInMap [EnvironmentMap, !Ref Env, host]
```

- デプロイ実行コマンド
```
sam build --parameter-overrides Env=dev
sam deploy
```
以上。
（よかったら、いいねお願いします！
Pythonで可視化するデータのばらつきの指標

## データのばらつきを表す指標について
データを分析する中で、データがどのくらいばらついているのかを調査する機会がありました。その際に、ばらつきの指標がたくさんありどれが適切な指標なのか分からず調べたので備忘録として以下に記録します。

### 標準偏差(Standard Deviation): 
データが平均値からどれだけ散らばっているかを表す統計指標で、データのばらつきの尺度としてよく使われます。各データ点と平均値との差（偏差）を二乗して平均したもの（分散）の平方根です。数式は以下の通りです。

$$
Standard Deviation = sqrt(Σ(x_i - μ)^2 / N)
$$

ここで、
x_iは各データ点、μは平均値、Nはデータ点の総数を表します。

### ジニ係数(Gini Coefficient): 
経済学で一般的に使用される不平等の指標で、0（完全な平等）から1（完全な不平等）までの範囲の値を持つ。数式は以下の通りです。

$$
Gini Coefficient = Σ(Σ|x_i - x_j|) / (2 * n^2 * μ)
$$

ここで、xi はソートされたデータ、iはデータの順位（ソート順）、μ は平均値、Nはデータ点の総数を表します。

### エントロピー(Entropy): 
データの不確実性や情報の量を表す指標で、確率分布の不確実性を表します。数式は以下の通りです。

$$
Entropy = -Σp(x_i) * log_2(p(x_i))
$$

ここで、p(xi) は各データ点の確率を表します。

### MAD (Median Absolute Deviation): 
データ点が中央値からどれだけ離れているかを表す指標で、外れ値に強い平均の代替として使われます。数式は以下の通りです。

$$
MAD = median(|x_i - median(x)|)
$$

ここで、xi は各データ点、xは全データセットを表します。

### Mean Absolute Deviation (MAD): 
データ点が平均値からどれだけ離れているかを表す指標で、平均と同様にデータの中心傾向を表すが、外れ値の影響を受けにくい。数式は以下の通りです。

$$
Mean Absolute Deviation = Σ|x_i - μ| / N
$$

ここで、xiは各データ点、μは平均値、Nはデータ点の総数を表します。

## pythonコードと可視化
これらの指標をPythonで計算して可視化するためのサンプルコードとサンプルデータを以下に示します。

|index|疑似データ|
|---|---|
|0|1\.764052345967664|
|1|0\.4001572083672233|
|2|0\.9787379841057392|
|3|2\.240893199201458|
|4|1\.8675579901499675|
|5|以下省略|

```python
import numpy as np
import pandas as pd
import scipy.stats as stats
import plotly.graph_objects as go
import math

# ランダムデータの生成
np.random.seed(0)
data = np.random.normal(0, 1, 100)

# 標準偏差
std_dev = np.std(data)

# ジニ係数
data_sorted = np.sort(data)
n = len(data)
gini_coeff = (np.sum((2 * np.arange(1, n + 1) - n  - 1) * data_sorted)) / (n * np.mean(data))

# エントロピー
freqs = pd.Series(data).value_counts(normalize=True)
entropy = -np.sum(freqs * np.log2(freqs))

# MAD
mad = np.median(np.abs(data - np.median(data)))

# Mean Absolute Deviation
mean_abs_dev = np.mean(np.abs(data - np.mean(data)))

# 計算結果(ジニ係数はスケールが違いすぎたので割愛)
results = [std_dev,entropy, mad, mean_abs_dev]

# Plotlyで可視化
fig = go.Figure(data=[go.Bar(
            x=['Std Dev','Entropy', 'MAD', 'Mean Abs Dev'],
            y=results,
            text=results,
            textposition='auto',
        )])

fig.update_layout(title_text='Comparison of Statistical Measures')

fig.show()
```



![](https://storage.googleapis.com/zenn-user-upload/766025d35382-20230613.png)

## まとめ
以下に各統計指標が一般的にどの程度の値を持つか、そしてそれらがどのようにデータ分布の異なる性質を反映するかについて説明します。

### 1. 標準偏差：
標準偏差はデータがその平均値からどれだけ散らばっているかを示します。標準偏差が小さい場合、データ値は平均値に近く集中しています。標準偏差が大きい場合、データは平均値から広く散らばっています。標準偏差の値はデータのスケールに依存します。したがって、比較するためには同じ単位やスケールのデータを使用する必要があります。

### 2. ジニ係数：
ジニ係数は0から1の間の値を持ち、データの不平等度を示します。ジニ係数が0に近いほど、データは均等に分布しています。ジニ係数が1に近いほど、データは不均等に分布しています。例えば、所得の不平等を測る際によく使われます。

### 3. エントロピー：
エントロピーは情報理論における不確実性の尺度で、確率分布全体を考慮して計算されます。エントロピーが高いほどデータの不確実性が高く、低いほど不確実性が低いです。離散的な分布（たとえば、コイン投げやサイコロ投げ）のエントロピーは一般的に0以上の値を取ります。

### 4. MAD (Median Absolute Deviation)：
MADはデータがその中央値からどれだけ散らばっているかを示します。MADが大きいほど、データは中央値から広く散らばっています。MADは外れ値に対して頑健（影響を受けにくい）であるため、データに外れ値が含まれている場合の分散の尺度としてよく使われます。

### 5. Mean Absolute Deviation：
この指標はデータが平均値からどれだけ散らばっているかを示します。Mean Absolute Deviationが大きいほど、データは平均値から広く散らばっています。Mean Absolute Deviationも外れ値に対して頑健です。
saleforceのApexで必須項目の取得方法


早く指定したオブジェクトの中のすべての必須項目を取得する方法

下記のソースで行こう。API名を入れ替えるだけで使える


```
String selectedObj = 'オブジェクトAPI名';
Map <String,Schema.SObjectType> gd = Schema.getGlobalDescribe();
Schema.SObjectType sobjType = gd.get(selectedObj);
Schema.DescribeSObjectResult r = sobjType.getDescribe();
Map<String, Schema.SObjectField> MapofField = r.fields.getMap();
for(String fieldAPIName : MapofField.keySet()) {
   Schema.SObjectField field = MapofField .get(fieldAPIName);
   Schema.DescribeFieldResult F = field.getDescribe();
   if( 
       F.isCreateable() && 
       !F.isNillable() 
      && !F.isDefaultedOnCreate() 
     ){
       system.debug(fieldAPIName );
       system.debug(MapofField.get(fieldAPIName).getDescribe().getLabel() );
   }
}
cscの作法 その361

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
sqliteでsqlを直接、実行して結果をdatagridviewするツールを作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/5da8a370-ecbc-2b6b-612a-1b7dbba3edba.png)

# サンプルコード

```

using System;
using System.Text;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
using System.Data.Common;
using System.Transactions;
using System.Data.SQLite;

class form1: Form {
	private SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter();
	private DataGridView gd0 = new DataGridView();
	private Button sButton = new Button();
	private TextBox bo1 = new TextBox();
	form1() {
		Text = "DataGridView";
		ClientSize = new Size(600, 400);
		bo1.Location = new Point(50, 20);
		bo1.Size = new Size(300, 20);
		bo1.Text = "SELECT * FROM cdata";
		sButton.Location = new Point(400, 20);
		sButton.Text = "submit";
		gd0.Location = new Point(50, 60);
		gd0.Size = new Size(500, 300);
		sButton.Click += new EventHandler(SButton_Click);
		Controls.AddRange(new Control[] {
			bo1,
			sButton,
			gd0
		});
	}
	private void SButton_Click(object sender, EventArgs e) {
		SQLiteConnection conn = new SQLiteConnection("Data Source=db0.sqlite;");
		conn.Open();
		SQLiteCommand command = conn.CreateCommand();
		command.CommandText = bo1.Text;
		dataAdapter = new SQLiteDataAdapter(command);
		DataTable dt = new DataTable();
		dataAdapter.Fill(dt);
		gd0.DataSource = dt;
		conn.Close();
	}
	[STAThread]
	public static void Main() {
		Application.Run(new form1());
	}
}





```


以上。
|=演算子

flag |= false
flag = flag | false


# trueがあったらtrue
true * true = true
true * false = true
false * true = true 
false * false = false

# flagを使い分けて、状態を分ける
```
defalt_flag = false
flag = default_flag
default_flag |= 　hoge.include?("hoge")
```
Azure CLIでアクセストークンを取得してAPI実行する

毎回忘れちゃうので自分用メモとして残します。

# Cloud Shell(Bash)

* Azure PortalにログインしてCloud Shell(Bash)を開きます。

* アクセストークンを取得します。

```bash
token=`az account get-access-token | jq -r .accessToken`
```

* 対象のREST APIを実行します（ここでは例としてリソースグループ一覧を取得しています）

```bash
curl -X GET -L -H "Content-Type: application/json" -H "Authorization: Bearer $token" https://management.azure.com/subscriptions/[Subsciption Id]/resourcegroups?api-version=2021-04-01 | jq .
```

# Azure CLI(ローカル実行)

* ここではWindowsPCでの実行を想定しています。まずはPowerShellを開きます。

* Azureにログインします。

```powershell
az login
```

* アクセストークンを取得します。

```powershell
$token = az account get-access-token | ConvertFrom-Json
$token = $token.accessToken
```

* 対象のREST APIを実行します（ここでは例としてリソースグループ一覧を取得しています）

```powershell
$res = Invoke-WebRequest -Method GET -Headers @{"Content-Type"="application/json"; "Authorization"="Bearer $token"} https://management.azure.com/subscriptions/[Subsciption Id]/resourcegroups?api-version=2021-04-01
ConvertFrom-Json $res.Content | ConvertTo-Json
```

以上です
Tips: copilot.vimでmarkdownの補完もできるようにする

## この記事は何
僕はVimを使っているため、Copilotを[copilot.vim](https://github.com/github/copilot.vim)を用いて利用しています。
copilot.vimを用いてMarkdownの補完もしてもらおうと思っていたところ、

`copilot: disabled for filetype=markdown by internal default`というエラーが出てしまい補完をしてもらうことができませんでした。
この記事では、copilot.vimでmarkdownの補完もできるようにする方法をTipsとしてまとめます。

## 結論

### vimの場合
この設定をvimrcなどに追加すればOKです

```vimscript
let g:copilot_filetypes = {'markdown': v:true}
```

### neovimの場合
`init.vim`に

```vimscript
let g:copilot_filetypes = {'markdown': v:true}
```

を追加するか、`init.lua`に

```lua
vim.g.copilot_filetypes = {markdown = true}
```

を追加すればOKです。

## Ref
https://github.com/orgs/community/discussions/38074#discussioncomment-4049799