OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】学習時間を記録するDiscord Botを作成する

# 概要
discordでオンライン勉強会を行っている。
勉強時間を自動で記録したいと思いdiscord botを作成したので以下に方法を記載する。
処理としてはボイスチャンネルにいた時間を計測し、メンバーが退室した時点で該当のメンバーのボイスチャンネル滞在時間を出力するものになる。

# 方法
## bot作成
処理内容は置いといてまずはbotを作成してみる。
ローカルで稼働するbotの作成方法については以下の記事が非常にわかりやすいので参考にした。
https://qiita.com/PinappleHunter/items/af4ccdbb04727437477f
ひとまずこれで作成して動いたらbotの作成は完了。

## 常時稼働させる
上記はローカルで稼働するbotであり、自環境でプロセスを稼働させ続ければbotを動き続けるが、
当然自環境(プロセス)を停止すれば非稼働となる。
そこでクラウドでアプリケーション実行環境を用意し、そこで稼働させ続けることで常時稼働させる。
常時稼働botの作成は以下を参考にした。
https://fuurinblog.com/settigs-discordbot/

## 時間記録処理の作成
APIリファレンスは以下。
https://discordpy.readthedocs.io/en/latest/api.html

リファレンスを見ると、`on_voice_state_update()`がボイスチャンネルへの入退室が行われるたびに呼び出されるらしい。
入室時・退室時の処理をそれぞれ分けて書く。
本処理では、特定のボイスチャンネルの滞在時間のみ出力しているが、時間の記録自体は全ボイスチャンネル分行っているので、
`WATCH_CHANNEL_ID`の処理を削除、部屋名を出力するようにすれば部屋ごとの滞在時間も出力可能である。

```Python
import discord
import datetime
from os import getenv

client = discord.Client()
pretime_dict = {}
SEND_CHANNEL_ID = <メッセージを送信するテキストチャンネルのID>
WATCH_CHANNEL_ID = <滞在時間を記録するボイスチャンネルのID>

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

@client.event
async def on_voice_state_update(member,before,after):
    # 入室時
    if before.channel is None:
        pretime_dict[after.channel.name] = datetime.datetime.now()
    # 退室時
    elif after.channel is None:
        if before.channel.id != WATCH_CHANNEL_ID:
            return

        duration_time = pretime_dict[before.channel.name] - datetime.datetime.now()
        duration_time_adjust = int(duration_time.total_seconds()) * -1

        hours = duration_time_adjust // 3600 
        remain = duration_time_adjust - (hours * 3600)
        minutes = remain // 60
        seconds = remain - (minutes * 60)
        time_text = '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))

        send_channel = client.get_channel(SEND_CHANNEL_ID)
        send_text = f'【{member.nick}】勉強時間： {time_text}'
        # print(send_text)

        await send_channel.send(send_text)

token = getenv('DISCORD_BOT_TOKEN')
client.run(token)
```
ilasmでstack machine その13

# 概要
ilasmでstack machineやってみた。
HelloWorldやってみた。

# サンプルコード

```

.assembly extern mscorlib {
}
.assembly hello {
}
.method static void main() {
.entrypoint
	ldstr	"Hello World!!"
	call	void [mscorlib]System.Console::WriteLine(string)
	ret
}


```

# 実行結果

```
>ilasm ihello.il

Microsoft (R) .NET Framework IL Assembler.  Version 2.0.50727.8784
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembling 'ihello.il'  to EXE --> 'ihello.exe'
Source file is ANSI

Assembled global method main
Creating PE file

Emitting classes:

Emitting fields and methods:
Global  Methods: 1;

Emitting events and properties:
Global
Writing PE file
Operation completed successfully

>ihello
Hello World!!

>
```

以上。
ilasmでstack machine その12

# 概要
ilasmでstack machineやってみた。
練習問題やってみた。

# 練習問題
九九表示せよ。

# サンプルコード

```

.assembly extern mscorlib {
}
.assembly kuku {
}
.method static void main() {
.entrypoint
.locals init(int32 i)
.locals init(int32 j)
	ldc.i4	1
	stloc	i
	ldc.i4	1
	stloc	j
loop0:
	ldloc	i
	ldc.i4	9
	bgt		bye
loop1:
	ldloc	j
	ldc.i4	9
	bgt		tugi
	ldloc	i
	ldloc	j
	mul
	call	void [mscorlib] System.Console::Write(int32)
	ldstr	" "
	call	void [mscorlib]System.Console::Write(string)
	ldloc	j
	ldc.i4	1
	add
	stloc	j
	br		loop1
tugi:
	ldc.i4	1
	stloc	j
	ldstr	" "
	call	void [mscorlib]System.Console::WriteLine(string)
	ldloc	i
	ldc.i4	1
	add
	stloc	i
	br		loop0
bye:
	ret
}

```

# 環境

wiindows10

# コンパイル手順

```
>set PATH=C:\Windows\Microsoft.NET\Framework\v2.0.50727;%PATH%

>ilasm ikuku.il

```

# 実行結果

```
>ikuku
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81

>

```
以上。
GitHub Actions入門～Pythonを自動で実行する～

**GitHub Actions**で**Python**スクリプトを自動実行する手順

## 1.リポジトリ作成
今回はサンプルなので、`Public`で作成する

## 2.Pythonファイルの作成
**ルートディレクトリ**に以下の内容で`sample.py`を作成する

```py
import numpy as np

a = np.array([1, 2])
b = np.array([3, 4])
print(a + b)
```

## 3.Pythonライブラリ設定ファイルの作成
**ルートディレクトリ**に`requirements.txt`を作成する
**Python**スクリプトで利用する**ライブラリ**とその**バージョン**をすべて記載する必要がある
今回は`numpy`を利用するので以下の内容を記載

```txt
numpy >= 1.21
```

## 4.GitHub Actions設定ファイルの作成

1. ルートディレクトリに`.github/workflows/`フォルダを作成する
1. yamlファイル`sample.yaml`を作成し、以下の内容に編集する

```yaml
name: Sample

on:
  push:
    branches: 
      - main
  workflow_dispatch:

jobs:
  numpy-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup Python
        uses: actions/setup-python@v2
        with:
          python-version: '3.8'
          architecture: 'x64'
      - name: Install dependencies
        run: pip install -r requirements.txt
      - name: Run Python
        run: python sample.py
```

## 5.GitHubリポジトリにpushする
作成したファイルをすべて`commit`してGitHubリポジトリに`push`する

## 実行結果の確認
**GitHub**の**Actionsタブ**を開くとワークフローが成功していることが確認できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/9ddbb3ee-13cd-b571-b759-8c2ca682a3e8.png)

中身を確認すると、Pythonの実行結果が出力できていることが確認できます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/c0182dab-d44a-2d65-7271-d4210d9b2bab.png)


## 今回作成したリポジトリ

https://github.com/rararapi/actions-python

## 参考
[Python のビルドとテスト - GitHub Docs](https://docs.github.com/ja/actions/automating-builds-and-tests/building-and-testing-python)
[GitHub ActionsでPythonスクリプトを実行する](https://helve-blog.com/posts/git/github-actions-python/)
ilasmでstack machine その11

# 概要
ilasmでstack machineやってみた。

# 命令セット


|ニーモニック	|意味|				stackの状態|
|:--|:--|:--|
|nop|			何もしない。			|	変化無し|
|ldc.i4 	1	|stackに整数 1を積む。			|1個増える
|ldstr	"fizzbuzz"  |stackに「fizzbuzz」を積む。	|1個増える
|ldloc	i		|stackに変数iの値を入れる。	|1個増える
|stloc	i		|変数iにstackを入れる。		|1個減る
|call	void [mscorlib] System.Console::WriteLine(int32) 			|stackをint32印刷。		|1個減る
|beq		bye		|stack-1,stackを比べて等しいならbyeに飛ぶ。	|2個減る
|bgt		bye		|stack-1,stackを比べて小さいならbyeに飛ぶ。	|2個減る
|blt		bye		|stack-1,stackを比べて大きいならbyeに飛ぶ。	|2個減る
|br		tugi		|tugiへ飛ぶ。|変化無し
|brfalse	fizzbuzz	|ゼロで無いならfizzbuzzに飛ぶ。	|1個減る
|brtrue	fizzbuzz	|ゼロならfizzbuzzに飛ぶ。	|1個減る
|dup			|stackにコピーを積む。		|1個増える
|pop		|stackを一個減らす。			|1個減る
|add			|stack-1,stackの加算を求める。	|1個減る
|sub			|stack-1,stackの減算を求める。	|1個減る
|mul			|stack-1,stackの乗算を求める。	|1個減る
|div			|stack-1,stackの除算を求める。	|1個減る
|rem			|stack-1,stackの剰余を求める。	|1個減る

以上。
STM32L010でI2C EEPROで遊ぶ1

目的
I2C EEPROMのテスト

使用ハード

ＩｃｈｉｇｏＪａｍ用外部記憶装置キット　ＩｃｈｉｇｏＲＯＭ
[AE-IchigoROM]
通販コード　K-12061
発売日　2017/08/23

I2C アドレス　0x50 と　0x51(2バンク目)


![o_con576.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6acddd34-9584-15c6-b1b8-bf06369b0997.jpeg)


![o_con586.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/08bb16c1-710c-b3d2-f7fb-8475bc1c0d2b.jpeg)





読み取り


```c++



//SER_I2C_EEPROM_read1_010_1

#include "mbed.h"

I2C i2c(PA_10, PA_9); //010

//#define S5851A 0x48
#define ADDR        ((0x50)<<1)   //  address


//四桁の変換
//#define DIV10(n) (((n*409)+((n*154)>>8))>>12)
int DIV10(int n)
{
    return    (((n*409)+((n*154)>>8))>>12)    ;
}
char data[16];
char *itoa9999(int d)
{

    data[4] = 0;
    data[3] = '0' + (  d - (DIV10(d) * 10)  );  // '0'+(d%10)
    d = DIV10(d);
    data[2] = '0' + (  d - (DIV10(d) * 10)  );  // '0'+(d%10)
    d = DIV10(d);
    data[1] = '0' + (  d - (DIV10(d) * 10)  );  // '0'+(d%10)
    data[0] = '0' +  DIV10(d);                  // '0'+(d/10)

    return (data);

}//itoa99

//仮想シリアルへの一文字出力 9600bps
DigitalOut TX(PA_2);
//DigitalIn  RX(PA_3);
#define UART_DELAY 101 //  1/9600 98-105
int pc_putc(char ch)
{
    TX=1;
    TX=0;//Start
    wait_us(UART_DELAY);

    for(int ii=0; ii<8; ii++) { //Data x 8
        TX=(ch>>ii)&1;
        wait_us(UART_DELAY);
    }; //for

    TX=1;//Stop
    wait_us(UART_DELAY);

    return(0);
} //pc_putc


//文字列の表示 nana_seg
int pc_puts(char *str1)
{
    //文字の中身がゼロか
    while(*str1) {
        pc_putc( *str1 ++);
    } //while

    //戻り値
    return(0);
}//pc_puts

int main()
{

    char data_read[8]; //バッファー

    char ad_hl[2];

    pc_puts("\r\n<START>\r\n");

    //無限ループ
    while(1) {

        pc_puts("for 0 to 15\r\n");

        for(int ii = 0; ii<16; ii++) {

            //アドレス
            //set address
            ad_hl[0] =    ii >> 8   ;
            ad_hl[1] =    ii & 0xff ;
            //pc_puts( itoa9999(ad_hl[0]) );
            //pc_puts( "#" );
            //pc_puts( itoa9999(ad_hl[1]) );
            //pc_puts( " " );
            i2c.write(ADDR, ad_hl, 2); //addres 0

            //データの読み込み
            // Read temperature register
            i2c.read(ADDR, data_read,1,false);
            //data_read[0] = 123;
            pc_puts( itoa9999(data_read[0]) );
            pc_puts("\r\n");

            //1秒待つ
            wait_ms(1000);

        }//for

    }//while

}//main

//容量削減
void error(const char* format, ...) {}



```
欠損値レコードを確認して削除/抽出する(SPSS Modeler データ加工逆引き5-8)

# 欠損値レコードを確認して削除/抽出（欠損値/空白の削除と抽出）

![スクリーンショット 2022-07-13 13.11.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/aa255683-76dc-be39-06cf-4ff00d9dd047.png)

## 1.想定される利用目的

・顧客属性データのクレンジング
・設備IoTデータの欠損値の処理

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/missing_null.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2022-07-13 13.43.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2d0fe0ba-016f-cc46-518d-8942ea7ce1b2.png)

a.入力するデータは以下の通りです。

![スクリーンショット 2022-07-13 13.38.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/7e8bd0bc-f42c-3d2c-dad4-bf4f1a9da39b.png)

#### [テーブル]ノードから削除/抽出のノードを自動生成させる方法

b.[テーブル]ノードを実行します。Nullのセルを選んだままメニューから[条件抽出ノード(AND)]を選択します。
![スクリーンショット 2022-07-13 13.39.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b28c5e8d-38f2-7456-6789-7de3fe6cfca3.png)

c.[条件抽出]ノードが自動生成されます。Nullのレコードを確認します。
![スクリーンショット 2022-07-13 14.01.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/c9605d0e-d29f-fdcd-ef20-6cbf8ec06918.png)

[プレビュー]します。
![スクリーンショット 2022-07-13 14.01.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8e85e98f-b413-7f66-f190-87410d4d031f.png)

d.[条件抽出]ノードを複製して[含める]から[破棄]へ選択を切り替えます。
![スクリーンショット 2022-07-13 14.01.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/84c3bbdd-3060-8383-c620-da33137596d1.png)

[プレビュー]します。
![スクリーンショット 2022-07-13 14.01.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/29599a7c-92f9-e277-1631-823df411890d.png)

####  [データ検査]ノードを利用する方法

e.[データ検査]ノードを実行します。有効なレコード4件が欠損値だとわかります。
[値]の行を選択したまま以下のメニューを選びます。
![スクリーンショット 2022-07-13 14.02.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ad3c22d0-557a-ac0c-2f45-fc60666f1cc2.png)

[テーブル]で選択したフィールドを選択しています。
![スクリーンショット 2022-07-13 11.17.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/5986c3d8-d8d4-a595-aec9-8c5fb673eff6.png)

f.[条件抽出]ノードが自動生成されます。d同様に欠損値を抽出します。
![スクリーンショット 2022-07-13 14.03.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/025037d1-ec03-2ff0-f4af-087005ca865e.png)

g.fの反対のモードです。cと同様に該当レコードを破棄します。
![スクリーンショット 2022-07-13 14.03.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/7810ac40-1d18-a21b-2609-178ae2405c16.png)

#### 注意点

値で昇順ソートすると、存在すれば先頭レコードがNullになるため、その方法でも確認が可能です。

## 4.参考情報

#### [データ検査]ノードの解説記事

https://www.ibm.com/blogs/solutions/jp-ja/spssmodeler-push-node-3/

https://qiita.com/416nishimaki/items/27fc3b6a2e596726877c

https://qiita.com/kawada2017/items/2a99ab2941f3793fc300


#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
eclipseにオフラインでプラグインをインストールする

# オフライン環境のeclipseにPayara Toolsを導入する。

## プラグインのダウンロード

以下のコマンドを実行
（c:\Dev\tools配下にダウンロードする場合）

```
eclipse.exe -nosplash -verbose -application org.eclipse.equinox.p2.artifact.repository.mirrorApplication -source https://raw.githubusercontent.com/payara/ecosystem-eclipse-plugin/release-artifacts/repository/latest -destination C:\dev\tools
eclipse.exe -nosplash -verbose -application org.eclipse.equinox.p2.metadata.repository.mirrorApplication -source https://raw.githubusercontent.com/payara/ecosystem-eclipse-plugin/release-artifacts/repository/latest -destination C:\dev\tools
```
アーティファクトとメタデータをダウンロードします。

## eclipseに追加する。
「ヘルプ」→「新規ソフトウェアのインストール」で、ダウンロードしたディレクトリを指定する。


![tools.zip.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653097/0a4cbdf3-2671-6fa2-4766-2d30319b0abd.jpeg)
100日後くらいに個人開発するぞ！day061


## 今日はDateクラスを学んでみた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/f4865f3e-8561-bc35-d6b1-0c1ac300ca35.png)


## 今日の学び

### Dateクラスの読み込み
* Dateクラスを用いると日付を扱うことができる
* DateクラスはRubyが用意しているクラスなので`require`で読み込みことができる
    * 既に用意されているクラスを読み込む際は`require "クラス名"`
        * 注)`require /.クラス名`ではない


### Dateクラスの使い方
* Dateクラスは他のクラスと同様にDate.newとすることでインスタンスを生成できる
    * `インスタンス変数 ＝ Date.new(年,月,日)`


### 曜日を判定するDateクラスのインスタンスメソッド
* 「日曜日かどうか」を真偽値で返す例
    * `requre "date"`
    * `date1 = Date.new(2022,7,22)`
    * `puts date1.sunday?`→「false」

### 今日の日付を取得するDateインスタンス
* 例
    * `requre "date"`
    * `date1 = Date.today
    * `puts date1`
【VSCode】エディタの配色をカスタマイズする

## 画面配色の設定項目
```json-doc:setting.json
{
  "workbench.colorCustomizations": {
    "editor.background": "",  // エディタの背景色
    "editor.foreground": "",  // エディタの前景色
    "editorGroup.border": "", // 複数のエディタを横に並べた時の境界線の色
    "editorLineNumber.foreground": "", // エディタの行番号の色
    "editor.selectionBackground": "",  // エディタカーソルの背景色
    "errorForeground": "",  // エラーメッセージの全体的な前景色

    "button.background": "",  // ボタンの背景色
    "badge.background": "", // バッジの背景色

    "input.background": "",  // 入力ボックスの背景
    "input.border": "",  // 入力ボックスの枠線
    "input.placeholderForeground": "",  // プレースホルダ

    "scrollbarSlider.background": "",  // スクロールバー背景色
    "scrollbarSlider.hoverBackground": "",  // ホバー時のスクロールバー背景色

    "statusBar.background": "", // ワークスペースを開いていない状態のステータスバー背景色
    "statusBar.foreground": "", // ワークスペースを開いていない状態のステータスバー前景色
    "statusBar.noFolderBackground": "",  // フォルダーを開いていない状態のステータスバー背景色
    "statusBar.debuggingBackground": "",  // プログラムをデバッグしている時の背景色
    "statusBar.border": "",  // ステータスバーの枠線
    "statusBarItem.prominentBackground": "",  // ステータスバー内で強調する項目の背景色

    "list.activeSelectionBackground": "",  // 選択された項目のリスト/ツリー背景色
    "list.hoverBackground": "",  // ホバー時のリスト/ツリーの背景
    "list.invalidItemForeground": "",  // 無効な項目のリスト/ツリーの文字色

    "activityBar.background": "",  // アクティビティバーの背景色
    "activityBar.foreground": "",  // アイコン
    "activityBar.border": "",  // アクティビティバーとサイドバーの境界線
    "activityBarBadge.background": "",  // 通知バッジの背景色
    "activityBarBadge.foreground": "",  // 通知バッジの文字色

    "titleBar.activeBackground": "", // タイトルバーの背景色
    "titleBar.activeForeground": "", // タイトルバーの文字色

    "sideBar.background": "",  // サイドバーの背景色
    "sideBar.foreground": "",  // サイドバーの文字色
    "sideBar.border": "",  // サイドバーとエディターの境界線の色
    "sideBarTitle.foreground": "",  // サイドバータイトルの前景色

    "editorGroupHeader.tabsBackground": "",  // タブの背景色
    "tab.activeBackground": "",  // アクティブなタブの背景色
    "tab.activeForeground": "",  // アクティブなタブの文字色
    "tab.border": "",   // タブを区切るための境界線
    "tab.activeBorder": "",  // アクティブなタブの下の線
    "tab.inactiveBackground": "",  // 非アクティブな色の背景色
    "tab.inactiveForeground": "",  // 非アクティブなタブの文字色
  }, 

```
米国でのSIMの購入・使えるスマホ端末

# 米国のMNO (2021年10月時点での情報)

1. Verizon: 1億2200万ユーザ
2. T-Mobile: 1億900万ユーザ
3. AT&T: 9900万ユーザ
4. Dish Wireless: 870万ユーザ
5. U. S. Cellular: 490万ユーザ

# つながり度合い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316423/ea9751e7-d77e-df1a-cdfe-de1f75d0d80c.png "出典: アメブロ")

# SIMの候補

## Mint

ぐぐって一番最初に出てきたところです。
T-MobileのMVNO。

## Verizon

日本のNTTドコモ的存在。信頼性は高そうですが値段も少しお高め。

## H2O

議論中に出てきた候補。AT&Tの回線を使用。

## US Mobile

Verizonの回線を使っているMVNOを調べていたところ出てきました。

## Google Fi

T-MobileとU. S. CellerのVMNO。

## Boost Mobile

Dish Wireless、AT&T、T-MobileのVMNO。
Dish Wirelessグループらしい。Ting Mobileとは仲間。
なんとなく、Ting Mobileよりかは良さそう。

## TracFone Wireless

Verizon、AT&T、T-Mobile、UScellerのMVNO。
Verizonの子会社？最強のVMNOの予感。

## SIMPLE Mobile

## Ting Mobile

Dish Wireless、T-MobileのVMNO。
AT&Tが無い分、Boost Mobileよりかは悪そう。

## cricket

## H2O

## ultra mobile

## total



# スマホの候補

Xperia Ace IIを使ってます。
特に日本での手続きは必要なくSIMを指すだけでさくっと行けました。

# 日本のSIMカードでのローミング

ドコモはAT&Tを使ってるようです。

# 日本の番号をそのまま海外で使う方法

ローミング以外はない模様。

# 個人の感想

UCSDに2022年7月～2023年6月に行ったときの記録です。
今のところT-Mobileは繋がり辛い印象です。
Verizonを持っている友人は結構いつでもアンテナが2～3本立っているのに対して、T-Mobileは繋がってはいるけど細い印象です。

# 参考リンク

- [アメリカの携帯会社・通信キャリア事情をプロがわかりやすく解説！（2022年版） | アメスマモバイル](https://amesma.net/blog/smartphone/wireless-carrier-in-usa/19859/)
- [アメリカの格安SIM「mint mobile」の購入・開通手順 | せなログ](https://okilakugokulaku.com/life/america-life/mvno-mintmobile/2963/)
javascript 関数 (初学者の学習メモ)

# Javascript 関数の学習メモ

### 関数の特徴
「関数とは、複数の処理をひとまとまりにしたもの」
「関数を利用することで目的ごとに処理を分割したり、似たような処理を何度も書かなくて済むようにできる」
「JavaScriptにおける基本的な構成要素のひとつであり、Function型のオブジェクトとして扱われる。」
「関数をオブジェクトとして扱うことが出来るのはJavaScript特有の特徴」

### 関数の使い方

#####  「関数宣言」で関数を定義する方法
もっとも代表的な関数定義の方法として「関数宣言」がある。
`function 関数名(引数) { 処理 }` という記法で関数を定義する。

```javascript:関数宣言

//広告を呼び出す為の関数
function showAD(message ="AD") { // message=仮引数  "AD"がデフォルト値(←必ず必要なわけではない)
  console.log("--------------------");
  console.log(`-----------${message}------------`);  //messageの部分に実引き数が代入される
  console.log("--------------------");
}

//showADで関数の処理をしている。
showAD("Header"); //Header AD＝実引数
console.log("Tom is great!");

console.log("BoB is great");
showAD(); //AD＝実引数が入力されていないためデフォルト値が代入される
console.log("Steave is great");
console.log("Richard is great");
showAD("Footer"); //Footer AD＝実引数
```

![スクリーンショット 2022-07-21 02.15.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741753/9de339c7-ae69-90d2-dc9d-f646d6f5318e.png)


##### returnで値を返す

〇 return文は主に以下の２つの目的で使われる
1. 呼び出し元に値を返したい
→関数の中で return 文を使用することで呼び出し元へ値を返すことができる
2. 関数の実行を終了したい


```javascript:関数宣言
function 関数名(仮引数1, 仮引数2, ...) {
  処理;
  処理;
  return 返り値;
}
```
```javascript:呼び出し
関数名(実引数1, 実引数2, ...);
```

```javascript:関数宣言：実例

function sum(a, b, c) {  // ()内が仮引数
  return a + b + c;  //returnで値を返す(計算することを「sum」に命じている？)
}

const total = sum(1, 2, 3) + sum(3 ,4, 5); //実引数を仮引数に入れ、「sum」で計算している？
console.log(total); //18
```

#####  「関数式」で関数を定義する方法
`const 定数名 = function(仮引数) { 処理 };` という記法で関数を定義する
＊関数式の場合、最後がブロックで終わっているが、最後に`;` が必要。
```javascript:関数式
const 定数名 function 関数名(仮引数1, 仮引数2, ...) {
  処理;
  処理;
  return 返り値;
};  ///定数で始まる時は、ブロックで終わっているが;が必要
```
```javascript:呼び出し
定数名(実引数1, 実引数2, ...);
```
```javascript:関数式：実例
const sum = function (a, b , c) {
  return a + b + c;
};

const total =sum(1,2,3) + sum(3, 4, 5);
console.log(total);  /// 18
```

##### 関数宣言と関数式の違い
1. 関数式は関数の引数として直接代入できる
2. 関数宣言は巻き上げが起こる (関数式は起こらない)
3. 同じ関数名を定義すると、先の関数が上書きされて呼び出せなる。→ ＊同じ関数名をつけてもエラーにはならない？(関数宣言の場合、関数名が必要なので問題が起きる可能性がある？)

＊どちらを優先的に使用するべきかは現状の知識では判断が難しいが
ひとまずはconstを使用する関数式を優先的に使おうかと考える。

> dotinstall
https://dotinstall.com/questions/gllx7h7

##### アロー関数 (関数式)
省略した書き方


/// 通常の関数宣言

function sum(a,b,c) {
  return a+b+c;
};

```javascript:アロー関数 (関数宣言)
/// 通常の関数宣言

function sum(a,b,c) {
  return a+b+c;
};

/// アロー関数の書き方 

(a,b,c) => { 
  return a + b + c;
};

/// さらに、処理の中身がreturnするだけの場合、下記のような書き方も可能。
/// (本文が1文の場合は｛｝とreturnを省略できる)

(a,b,c) => a + b + c;

/// 引数が一つの場合は、引数の( )も省略できる。

a => a + b + c;

/// 引数が無い場合は( )を省略しない

() => console.log('Hello world!'); 
```

```javascript:アロー関数 (関数式)
/// 通常の関数式

const sum =function(a,b,c) {
  return a+b+c;
};

/// アロー関数の書き方

const sum = (a,b,c) => { 
  return a + b + c;
};

/// さらに、処理の中身がreturnするだけの場合、下記のような書き方も可能。
/// (本文が1文の場合は｛｝とreturnを省略できる)

const sum = (a,b,c) => a + b + c;

/// 引数が一つの場合は、引数の( )も省略できる。

const sum = a => a + b + c;

/// 引数が無い場合は( )を省略しない

const sum = () => console.log('Hello world!'); 
```

# まとめ
まだまだ、関数についてはいろいろ学ぶべきものがありそうですが、ひとまず今日はここまでとします。
libopencm3をUbuntu 20.04 @ WSL2にインストール

[guides:stm32toolchain [UKHAS Wiki]](https://ukhas.org.uk/guides:stm32toolchain)を見つけて進めようとしたのだけど結局本家から直接ダウンロードする必要があった。

場所は
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads
から。

```
$ cd /usr/local
$ sudo http --download https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.10/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
$ sudo tar jxvf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
```

すると`/usr/local/gcc-arm-none-eabi-10.3-2021.10`にいろいろ展開される。

.bashrcに
```
export PATH=/usr/local/gcc-arm-none-eabi-10.3-2021.10/bin:$PATH
```
を追加。

シェル再起動。

```
$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$
```

動いたっぽい。
ncursesのことがなんか書いてあるけどとりあえず無視。
- [apt - How to install arm-none-eabi-gdb on Ubuntu 20.04 LTS (Focal Fossa) - Ask Ubuntu](https://askubuntu.com/questions/1243252/how-to-install-arm-none-eabi-gdb-on-ubuntu-20-04-lts-focal-fossa)

ファームを書き込んだりするのにstlink-toolsというのが必要らしい。これはaptで入った。

```
$ sudo apt install stlink-tools
```

Windowsで書き込むのはこっちも便利らしい。
- [STSW-LINK004 - STM32 ST-LINK utility (replaced by STM32CubeProgrammer) - STMicroelectronics](https://www.st.com/en/development-tools/stsw-link004.html#get-software)
[Laravel]withメソッドを理解する

# はじめに
今回は`withメソッド`の使い方について学んだので、ご紹介します。

# 環境
- Laravel：8.83.4

# 1. withメソッドを使ってリレーション先のデータを取得する
以前書いた記事のUserモデルを使って進めていきます。

https://qiita.com/HuntingRathalos/items/da638c17827d5b12e4ea

## 1-1. リレーションが１つの場合
```php
$users = App\User::with('posts')->get();
```
`withメソッド`の引数にはモデルで定義したリレーションメソッド名を文字列で指定します。
今回の場合、Userモデルに`postsメソッド`を定義したので、`'posts'`と指定します。

## 1-2. リレーションが複数ある場合
```php
$users = App\User::with(['posts', 'target'])->get();
```
`withメソッド`の引数に配列を渡すことで複数のリレーションデータを取ることができます。

## 1-3. ネストしたリレーションの場合
`Postモデル`に下記のようなリレーションを定義した場合、
```php:app/Models/Post.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
//略
    /**
     * リレーション - commentsテーブル
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class);
    }
//略
}
```
```php
$users = App\User::with('posts.comments')->get();
```
`.`でつなぐことでネストしたリレーション先のデータを取得することができます。


## 1-4. 指定したカラムのみ取得したい場合
```php
$users = App\User::with('posts:id,user_id,title')->get();
```
`:`の後に取得したいカラムを指定することで特定のカラムを取得することができます。

## 1-5. 条件を追加したい場合
```php
$users = App\User::with(['posts' => function ($query) {
    $query->where('content', 'like', '%good%');
}])->get();
```
取得するリレーションデータに条件を追加して限定したい場合は、`withメソッド`の中でクロージャを使うことで実現できます。
上記は`content`に`good`を含むリレーションデータだけをEagerロードしたいという場合を想定しています。

# 2. おわりに
`withメソッド`にはさまざまな使い方があることがわかりました。
今回は割愛しましたが、特定の条件下でのみEagerロードしたい場合には`loadメソッド`が利用できるので、うまく使い分けていきたいです。

# 3. 参考文献

https://readouble.com/laravel/8.x/ja/eloquent-relationships.html
[令和最新版]AWS Certified SysOps Administrator - Associate(SOA-C02)受験記

# はじめに
SAA → DVA → CLFの順番で受験していってアソシエイトレベルのラスボスとして受験しに行きました。

# SysOps Administrator(SOA-C02)の試験概要
- 問題数 56問 + ラボ試験2問
- 試験時間: 180 分
- 試験料: 15000円
- 試験範囲
    - 分野1:監視,ロギング,および修復 20%
    - 分野2:信頼性とビジネス継続性 16%
    - 分野3:デプロイ,プロビジョニング,およびオートメーション 18%
    - 分野4:セキュリティとコンプライアンス 16%
    - 分野5:ネットワークとコンテンツ配信 18%
    - 分野6:コストとパフォーマンスの最適化 12%

# 勉強方法
1. AWSのWeb問題集で学習
    - koiwaclub( https://aws.koiwaclub.com/ )を利用
    - 1回7問*97で679問+間違えたところ200問くらい
    - AWS認定試験モードで試験前に85%
2. 書籍
    - AWS認定資格試験テキスト　AWS認定SysOpsアドミニストレーター – アソシエイト(https://www.sbcr.jp/product/4815609085/)
    - わかりやすくまとめられていて試験に出るサービスの全体像を把握するのに役に立った
    - ~~出たばかりの本なのでちょいちょい誤字がある~~
3. 公式模擬試験
    - 選択問題の模擬試験
    - 申込時にメールに記載されているラボ試験の模擬試験
    - 一番本番に近い問題を摂取することができるのでやるべき


# ラボ試験対策
いろいろな合格体験記や記事を読んで以下の対策をしました。

- CloudWatchメトリクス / SNS 連携
- CloudFormation / テンプレート更新
- VPC / パブリック(NATゲートウェイ/ルートテーブル)・プライベートサブネット 作成 /フローログ
- S3 / クロスリージョンレプリケーション / ライフサイクルポリシー 設定 / ロギング
- Event Bridge / SNS連携 / Lambda連携
- EC2 / ALB,AutoScaling / 起動テンプレート


# 受験1回目(不合格)
7月2日に受験

とりあえず受けてみようの精神で受けに行ったところ見事に撃沈・・・。

点数は689点 
ほとんどの分野がコンピテンシーを満たしていない

単純に知識量が足りなかった+ラボ試験対策が甘かった(準備不足)

# 受験2回目(合格)
7月21日に受験

前回の反省を生かしまずはひたすらkoiwaで問題を解き,間違えたサービスのドキュメントを読み込んだ。また,様々な体験記を読みラボ試験対策を行った。

点数は798点 
結構自信があった試験ラボを落としてたっぽいが他は取れていたらしい。

勉強量を増やしたのもあるが,1回目と2回目の間に書籍を利用して学習したのでそれも大きいかもしれない。

# ２回受験しての所感
- ちょいちょい翻訳が怪しい問題があり英語に切り替えた
- ラボ試験の指示があいまいな時がある(上と同じ理由)
- ラボの採点基準が謎い
- AMIについての問題がめちゃめちゃ出た印象
- Organizationに関する問題もそこそこ出てきた
- koiwaの問題集はクオリティが半端ない
- 試験結果はすぐ出ないと聞いていたが２回とも7~8時間程度で送られてきた

# まとめ
4択問題については問題集などを利用して出題されるサービスについて学習すれば問題なさそうだなと思いました。
問題はラボ試験で、業務経験がある方ならある程度こんな感じかなで進められるとは思いますが、業務経験が少ないのであればしっかり対策をして受験することをお勧めします。

# 次の目標
次はセキュリティのスペシャリティあたりをとろうかなと考えています。
Terraformを使ってサーバーレスでサービスを作成したので振り返る

# はじめに

個人開発でサービスを作るのが趣味です。
Terraform, Lambda, DynamoDBを使ってサーバーレスで簡単なービスを作成してみました。
未来の僕が現在の僕の思考を振り返られるように記事にしました。


# 今までの構成

今まではSpring Boot, MySQL, AWS, Conoha VPCなどを使ってサービスを作っていました。
このような構成です。

### ALB + Fargate + RDSを使った構成

![ecs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63855/50459573-187a-e8dc-8052-4ecfda53da3c.png)


### ConoHa VPC + RDSを使った構成

![conoha.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63855/33854c56-138a-8adc-f354-7705bf54bfea.png)

この構成では突発的な負荷に弱かったり、お金がかかりすぎてしまうことがありました。
ALB + Fargate + RDSを使った構成では5000円/月ほど、ConoHa VPC + RDSを使った構成では3000円/月ほどサービスの維持に必要です。さらに開発環境を用意しようとすると倍のお金がかかります。
この問題を解決するためにTatteform, Lambda, DynamoDBなどを使い負荷に強く低コストで運営できるサーバーレスでサービス作成することにチャレンジしました。


# 今回の構成

今回作成したサービスはiOSアプリにレビューが付くとSlackに通知してくれるサービスです。(作成したと言っても全然未完成です、リポジトリは [こちら](https://github.com/takoikatakotako/app-review-notification))
このような構成です。

![lambda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63855/22addff6-cb88-baab-74a2-e86d6791cf3b.png)


アプリケーション（API）は Lambdaの関数URL機能とDynamoDBを使っています。
Lambdaの言語はPythonです。
フロントは生のHTML、JSで作成し、S3とCloudFrontでホスティングしています。
アプリのレビューチェックなどの定期実行にはAmazon EventBridgeとECS Fargateを使っています。
イメージのビルドやデプロイにはGithubAction を使っています。

本番環境と開発環境の管理にはAWS OrganizationとTerraformのはWorkspace機能を使っています。

![account.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63855/22bb564a-825b-3488-fa7c-168aa9784844.png)


# 良かったこと

## 負荷に強くなった

LambdaとDynamoDBによるサーバーレス構成にしたことで負荷に強くなりました。
いつバズっても負荷を気にしなくても済みます。バズったことないですが。


## サーバー代が安くなった

お金のかかるRDS, Fargateなどを使うのをやめたので（ユーザーが少ない間は）サーバー代が安くなりました。500円/月程度です。
またにコード管理をすることで簡単に開発環境のリソースを消したり作り直したりすることができるようになり、開発環境でお金がかからなくなりました。


## 全てをコード管理できるようになった

全てをコード管理することで、インフラ部分のコードを使いまわせるようになりました。
簡単に開発環境のリソースを消したり作り直したりすることができるようになったのは嬉しいです。


# 悪かったこと

## テストが書きにくい、ローカルで実行できない

今までSpring Boot（JUnit）を使っていたのでテストを書くのが簡単でした。
この構成では単体テストがとにかく書きにくいです。というより書くための仕組みがありません。
ローカルで実行できないのでCIでテストを回すことができません。
何かしらローカルでテストを実行する仕組みを用意する必要を感じました。
後述のServerless Frameworkで良い感じに解決できるのかもしれません。


## DBで制約が欲しい

今までMySQLを使っていたのでDB自体に制約をつけることができました。（Not Null, 外部キー, etc）
DynamoDBではDB自体に制約をつけることができないのでDBのデータを信用できません。
DBから取得したデータを常に疑いながらコードを書く必要があります。
作るサービスによってはどうしてもRDBMSを使いたくなるかもしれません。


## Lambdaを静的型付け言語で書きたい

使い捨てではないコードは静的型付け言語で書きたい派の人間です。
Pythonは好きですがどうしても型が欲しくなります。
とはいえ静的型付け言語をLambdaを使う場合はコンパイルする必要があります。
仕組みを整える必要があります。


# 検討したけど採用しなかったこと

## Serverless Frameworkについて

Lambdaを使ったサーバーレスサービスを作る場合に真っ先に選択肢に上がるのはServerless Frameworkだと思います。
Terraform好き & 構成管理ツールを複数使うことに抵抗がある、学習コストが高そうなどの理由から採用しませんでした。
両方を組み合わせて使っている方がいらっしゃいましたらコメント頂きたいです。m(_ _)m


## Firebaseについて

Firebaseを使ってしまうと僕のAWS力が活かせなくなりそうなので採用しませんでした。
AWSは新しいサービスを次々とリリースしているのでそれらを僕の個人開発に活かしたいです。


## PlanetScaleについて

とても興味がありました。
Lambda から PlanetScale（MySQL）を使うには Lambda Proxy を使う必要があり、そこそこ高そうなので採用しませんでした。


# さいごに

最後まで読んでくださりありがとうございました。
早く個人開発で一発当てて Aurora Serverless とかを気にせず使えるようになりたいです。
【Markdown】画像サイズの変更

# 実現方法
| 通常 | 変更 |
|:-:|:-:|
|```![代替テキスト](画像のURL)``` |  ```<img src="画像のURL" width="値(%でも可)">```|



# 記述方法

```markdown:コピペ用
<img src="" width="">
```

```markdown:解説
<img src="画像のURL" width="値(%でも可)">
```

```markdown:例1
<!-- 値の場合は単位不要 -->
<img src="○○.png" width="300">
```

```markdown:例2
<!-- %でも指定可能 -->
<img src="○○.png" width="50%">
```

# やりたいこと
* Qiita投稿時に画像サイズを小さくしたい。

| 100% | 50% |
|:-:|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/d9880408-e240-f7e2-f187-5c0a21647631.jpeg" width="100%">   |  <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/d9880408-e240-f7e2-f187-5c0a21647631.jpeg" width="50%"> |

# 参考文献
https://k-koh.hatenablog.com/entry/2020/02/22/111440
【Google Chromeデベロッパーツール】HTMLとCSSのパネルを縦に配置する

# やりたいこと
Google Chromeデベロッパーツールの要素パネルのレイアウトを**水平方向**にする。

| 変更前| 変更後 |
|:-:|:-:|
| <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/64d2d12b-5404-d6fb-08ee-ad7f3a21cc84.png" width="100%">  | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/d8af8b05-0542-fbb7-6a1c-411c0bb7bfae.png" width="100%">  |

# 手順
### 1. 要素パネルの右上の歯車を押し、設定を開く
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/8dcb8cd2-d7cc-2ce5-2689-bb2b074899b9.png" width="100%">

### 2. パネルレイアウトを水平方向に設定する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/59bc88f5-028b-1837-be46-a434170fe3a9.png" width="70%">

### 3. 設定の右上の ✖ を押し、要素パネルに戻る
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/4fc391b8-8cc3-ad85-32e5-3209081ee722.png" width="70%">

### 4.設定完了
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/d8af8b05-0542-fbb7-6a1c-411c0bb7bfae.png" width="70%">
webエンジニア界隈で使われる各言語のテンプレートリテラル比較してみた

# はじめに

昨日書いた記事でもしれっと使ってるんですが、固定の文字列＋連番みたいなことをやるときに、普通に文字列連結してもいいのですが見づらいし直感的ではないので、テンプレートリテラル（テンプレート構文）というものを使って、文字列に直接変数をぶっこんでしまう、というやり方を日常的にやるんじゃないかと思います。

昨日書いた記事はこちら

https://qiita.com/layzy_glp/items/7f3e43af11858eff622d

というわけで、昨日書いた記事の順番で各言語のテンプレートリテラルを紹介していきたいと思います。

※追記
後から知りましたが、大概の言語で日本語の呼び方はブレるけど英語では `String interpolation` と呼ばれている機能なんだそうですね。

# Ruby

```ruby:例
v = "hoge"
print "hoge#{v}" # hogehoge
```

ダブルクォートで囲われている中の `#{v}` のところですね。変数名を `#{変数名}` ってな感じで囲むやり方です。
割と古く（v1系）からのrubyでは当たり前のように使われているもののようです。
正確には「**式展開(string interpolation)**」と呼ばれるものらしく、変数どころかruby式を入れることができるそうです。

だから、こんな感じのこともできるってわけですね。

```ruby:例
v = "hoge"
w = "fuga"
print "hoge#{v+w}" # hogehogefuga
```

https://docs.ruby-lang.org/ja/latest/doc/spec=2fliteral.html

# Python

バージョンによって書き方が違うようです。文字列リテラルはシングルクォート、ダブルクォートどっちでも動作するみたいです。

```python
v = "hoge"

# 古いpython(%構文)
print("hoge%s" % v) # hogehoge

# python3以降（formatメソッド）
print("hoge".format(v)) #hogehoge

# python3.6以降(f文字列)
print(f"hoge{v}") #hogehoge
```

f文字列いいですね、かっこいいっす。python3.8以降なら式も入れれるようです。

https://docs.python.org/ja/3.8/tutorial/inputoutput.html

読みやすい記事はこちら

https://gammasoft.jp/blog/python-string-format/

# PHP

これも古くからある機能で、比較的に日常的に行われているせいか特別な名前はついていません。例によって文字列リテラルがダブルクォートの場合のみです。

```php
$v = "hoge";

// 以下どれでも動作します
echo "hoge$v"; //hogehoge　（見づらいので推奨しない）
echo "hoge${v}"; //hogehoge　（ちょっと見やすいけど、あまり見ない。@tadsanのコメントによるとPHP8.2からDeprecatedになるそうなのでやめようぜ）
echo "hoge{$v}"; //hogehoge （一番良く見る。実は式展開もできる）
```

書き方複数ありますが、 `{$変数or式}`　の書き方が一般的な気がします。式展開できるのはこの書き方のみです。下記のJSと違って`$`が`{}`の内側に入り込んでるのがポイントですね。

https://www.php.net/manual/ja/language.types.string.php#language.types.string.parsing

@tadsan さんにコメントで教えていただきましたが　`${変数}` の書き方はPHP8.2で非推奨（PHP9で廃止）になりそうなのだそうです。
使うのはやめましょう。

https://wiki.php.net/rfc/deprecate_dollar_brace_string_interpolation

# JavaScript

そもそもテンプレートリテラルはJavaScriptでの呼び方です。ES6以降で使用できます。式展開もできるらしいです（あんまやったことない）。
`` `変数` ``のようにダブルクォートの代わりにバッククォート（バックティック）で囲んだところの中に `${変数or式}` とします。

```javascript
const v = "hoge"

console.log(`hoge${v}`); // hogehoge
```

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Template_literals

# (おまけ)C#

@ktz_alias さんにコメントで教えていただきました。

```cs
var v = "hoge";

System.Console.WriteLine($"hoge{v}");
```

> 文字列リテラルを$"..."とし、その中の{}に計算式を置くスタイル。
また、{}の中のダブルクォーテーションはエスケープ不要。
C#界隈では、テンプレートリテラルとは呼ばず、文字列補完(String interpolation)と呼ぶ模様。

ほえええ、そうなんですね！

# おわりに

いかがでしたでしょうか。
言語によって各々やり方がちょっとずつ違うわけですが、どれもだいたい同じことができる、というのが大事なポイントです。
皆さんも色々試してはいかがでしょうか。
ラズパイのSoC温度を定期的にチェックし閾値を超えたらメール通知する

## vcgencmdで温度をチェックしてsmtlibでメール通知する
### vcgencmdとは？
+ Raspberry Pi上のVideoCore GPUから情報を出力するツール
+ [ラズパイ公式サイト](https://www.raspberrypi.com/documentation/computers/os.html#vcgencmd)

| コマンド | 内容 |
|:-:|:-:|
| get_camera | Raspberry Piカメラの有効状態、検出状態を表示 |
| measure_temp | Raspberry Pi 4 の内部温度センサーで測定した SoC の温度を返す |
| measure_clock arm |  指定されたクロックの現在の周波数を返す：ARM(CPU) |
| measure_clock core | 指定されたクロックの現在の周波数を返す：CORE(GPU)  |

+ 温度取得例

```
$ vcgencmd measure_temp
temp=45.9'C
```

### ユースケース
+ Raspberry Pi4は以前の機種より熱を持つらしいのでcronでvcgencmdをまわし温度チェックを定期実行する
+ Gmailを使ったメール送信は [こちら](https://qiita.com/eito_2/items/ef77e44955e43f31ba78) の記事を参考にさせて頂いた
+ crontabで15分毎に定期実行する

### モジュール１ [temp_check.py]
``` temp_check.py
import subprocess
import send_email

# Alert criteria temparature
criteria = 40.0

def temp_check():
    value0 = subprocess.run(['vcgencmd', 'measure_temp'], 
                            stdout=subprocess.PIPE, text=True)
    value1 = value0.stdout.rstrip('\n')
    value2 = value1.split('=')
    temp_data = value2[1][:-2]

    if float(temp_data) >= criteria:
        print(f'[ALERT] Raspi Temp : {temp_data}°C')
        body_message = '[ALERT] Raspi Temp : ' + temp_data + '°C'
        send_email.smtp_email(body_message)
    else:
        print(f'Raspi Temp : {temp_data}°C')


if __name__ == ('__main__'):
    temp_check()
```

### モージュール２ [send_email.py]

``` send_email.py
from email.utils import formatdate
from email.mime.text import MIMEText
import smtplib

def smtp_email(body_message):
    sendAddress = 'xxx.xxx@gmail.com'
    password = 'passwordpasswprd'

    subject = 'Raspberry Pi Temparature Alert!'
    bodyText = body_message
    fromAddress = 'xxx.xxx@gmail.com'
    toAddress = 'xxx.xxx@gmail.com'

    # Connect to SMTP server
    smtpobj = smtplib.SMTP('smtp.gmail.com', 587)
    smtpobj.starttls()
    smtpobj.login(sendAddress, password)

    # Create an email
    msg = MIMEText(bodyText)
    msg['Subject'] = subject
    msg['From'] = fromAddress
    msg['To'] = toAddress
    msg['Date'] = formatdate()

    # Send an email
    smtpobj.send_message(msg)
    smtpobj.close()


if __name__ == ('__main__'):
    smtp_email('test send!')
```

### crontab
```
$ crontab -e

*/15 * * * * /home/mashcannu/.venv/bin/python /home/mashcannu/temp_check.py
```

### Alert Email

![alert_email.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699739/3ca80239-fe20-e866-8ff7-ff0722e29ff6.png)
StreamServer Interceptorでコンテキストを上書きしたい時

Interceptorで認証情報などの値をコンテキストに入れて使いたいときがあります。
Unary　RPCだと、第一引数で受け取ったコンテキストをそのまま使えばいいですが、Stream RPCの場合は一工夫必要だったのでメモしておきます。

ContextとServerStreamをEmbedded fieldとして持つStructを定義して、それをhandlerに渡します。
実際のStreamの処理でContext()を呼び出せば、値を入れたコンテキストを取り出すことが出来ます。

```go
func myStreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
        ctx := context.WithValue(ss.Context(), "key", "value")
		return handler(srv, &serverStreamWrapper{
			ServerStream: ss,
			ctx:          ctx,
		})
	}
}

type serverStreamWrapper struct {
	grpc.ServerStream
	ctx context.Context
}
func (s *serverStreamWrapper) Context() context.Context { return s.ctx }
```
Linuxについて２（自分用メモ

Linuxには、rootという管理者アカウントがあり。あらゆる管理者権限をもつ。スーパーユーザーとも呼ばれる。
rootユーザー以外は一般ユーザーという。
Linuxではrootでログインして作業することは推奨されていない。少しの操作ミスでシステム全体に致命的な危機を与える可能性がある。

ログイン後
「＄」一般ユーザー、「＃」rootユーザー　と表示

ログアウト
exit、またはCtrl＋D

コマンドに指示する値のことを引数という。
コマンドにはオプションを指定することもできる。オプションはコマンドの動作を調整する役割をもつ。


・コマンド
man　コマンド
オンラインマニュアルの最初の行だけ抜き出して表示する
例）man passwd（ユーザーのパスワードを設定・変更する）

whatis コマンド名
オンラインマニュアルの最初の行だけ参照する
例）whatis passwd

--helpオプションでmanコマンドより簡素な説明を表示できる
例）paｓｓｗｄ　--help

ls　［オプション］　［ファイル名　または　ディレクトリ名］
ファイルの一覧を表示
-lオプションをつけて実行するとファイルの属性情報も併せて表示できる





・システム終了するコマンド
shutdown

・システム終了するコマンドの主なオプション
-r システム終了後に再起動
-h システム終了し停止
-c 実行中のシャットダウンをキャンセル
【GAS】定期的にメール送信させたい

ヤクルト1000を飲み忘れることが多いので、毎晩23:00にメールを飛ばすようにした。


# 目次
[1. 概要](#1-概要)
[2. 構成](#2-構成)
[3. スクリプト](#3-スクリプト)
[4. 感想](#4-感想)

# 1. 構成
・次回メール送信時刻
・更新頻度
・メール宛先、タイトル、メール本文

を定義する列をそれぞれ作成

![001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643466/96a23385-f44e-280e-8f7b-02fb8de4accd.png)

# 2. スクリプト
時刻の扱いは一度UNIXTIMEに変換すると計算が容易になります。
すぐ変換できるように共通関数として用意。

メール送信のところの動きとしては、

・次回実行時刻が過去時刻であれば実行対象
・次回実行時刻の再計算結果とメールの内容を変数に定義
・メール送信
・次回実行時刻更新

といった具合。

メール送信だけではなく、LINE通知とかにも転用可能。

```taskscheduler.js
//━━━━━━━━━━━━━━━
// シート定義
//━━━━━━━━━━━━━━━
var appSs = SpreadsheetApp.openById('スプレッドシートID');

//━━━━━━━━━━━━━━━
// 共通関数
//━━━━━━━━━━━━━━━
function getLastrow(sh, col) {
  return sh.getRange(sh.getMaxRows(), col).
    getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
}

function convUnixtime(jsttime) {
  var unixtime = Date.parse(jsttime)/1000;
  var unixtime_str = unixtime.toFixed();
  var unixtime_int = parseInt(unixtime_str);

  var year = jsttime.getFullYear();
  if (year === 1899) {
    return unixtime_int + 2209194000;
  } else {
    return unixtime_int;
  }
}

function convJsttime(unixtime) {
  return Utilities.formatDate(new Date( unixtime * 1000 ), "JST", "yyyy/MM/dd HH:mm:ss");
}


//━━━━━━━━━━━━━━━
// メール送信 
//━━━━━━━━━━━━━━━
function sendMailByCron() {
  var sh = appSs.getSheetByName('sendMail');
  var lastrow = getLastrow(sh, 1);
  var now = new Date();

  for (var i = 2; i <= lastrow; i++) {
    var exeTime = sh.getRange(i, 1).getValue();
    if　(exeTime <= now) {
      var freqCount = sh.getRange(i, 2).getValue();
      var freqCount = Math.trunc(freqCount)
      var freqDuration = sh.getRange(i, 3).getValue();
      var nextExeTime = getNextExeTime(exeTime, freqCount, freqDuration);

      var to = sh.getRange(i, 4).getValue();
      var title = sh.getRange(i, 5).getValue();
      var description = sh.getRange(i, 6).getValue();
      
      MailApp.sendEmail(to, title, description);
      sh.getRange(i, 1).setValue(nextExeTime);
    }
  }
}

//━━━━━━━━━━━━━━━
// 次回実行時刻算出
//━━━━━━━━━━━━━━━
function getNextExeTime(exeTime, freqCount, freqDuration) {
  var before = new Date(exeTime);
  switch(freqDuration) {
    case 'year':
      var after = before.setFullYear(before.getFullYear() + freqCount);
      break
    case 'month':
      var after = before.setMonth(before.getMonth() + freqCount);
      break
    case 'week':
      var after = before.setDate(before.getDate() + freqCount * 7)         
      break
    case 'day':
      var after = before.setDate(before.getDate() + freqCount);
      break
    case 'hour':
      var after = convUnixtime(before) + freqCount * 3600;
      var after = convJsttime(after)
      break
    case 'minute':
      var after = convUnixtime(before) + freqCount * 60;
      var after = convJsttime(after)
      break
  }
  var after = new Date(after);
  var after = Utilities.formatDate(after, 'JST', 'yyyy-MM-dd HH:mm');
  return after
}

```
R勉強会　第五回　アウトプット用課題　解答例&解説

この記事は[こちら](https://qiita.com/roadricefield/items/2ed01faaecd3fc35c2b9)の記事の解答例&解説です．作成途中です．  

# 第1問  

```R
CV <- function(data){
  return(sd(data)/mean(data))
}
```  

# 第2問  

```R
zero_one_scale <- function(vec){
  res <- (vec - min(vec))/(max(vec) - min(vec))
  return(res)
}
```  

# 第3問  

```R
my_cumsum <- function(vec){
  res <- c()
  now <- 0
  for(x in vec){
    now <- now + x
    res <- append(res, now)
  }
  return(res)
}
```  

# 第4問  

```R
test_of_no_correlation <- function(N, r){
  t <- (abs(r)*((N-2)**(1/2)))/((1-r**2)**(1/2))
  p <- 2*pt(t, N-2, lower.tail = FALSE)
  return(p)
}
```  

# 第5問  

```R
extremum_detector <- function(data){
  n_points <- length(data)
  extremum_index <- c()
  for(i in 1:(n_points-4)){
    window <- data[i:(i+4)]
    zougen <- c()
    for(j in 2:5){
      zougen <- append(zougen, window[j] - window[j-1] >= 0)
    }
    if(sum(xor(zougen, c(TRUE, TRUE, FALSE, FALSE))) == 0 | sum(xor(zougen, c(T, T, F, F))) == 4){
      extremum_index <- append(extremum_index, i+2)
    }
  }
  return(extremum_index)
}
```  

# 第6問
  
```R
my_kmeans <- function(x, y, k){
  centroids <- list()
  for(c in 1:k){
    centroids <- append(centroids, list(c(sample(1:100,1), sample(1:100,1))))
  }
  now_cls <- rep(1, 50)
  while(1){
    next_cls <- c()
    for(i in 1:50){
      dist <- c()
      for(j in 1:k){
        dist <- append(dist, (centroids[[j]][1] - x[i])**2 + (centroids[[j]][2] - y[i])**2)
      }
      next_cls <- append(next_cls, which.min(dist))
    }
    if(sum(next_cls == now_cls) == 50){
      return(as.character(now_cls))
    }else{
      now_cls <- next_cls
      for(c in 1:k){
        centroids[[c]] <- c(mean(x[now_cls == c]), mean(y[now_cls == c]))
      }
    }
  }
}
```
「streamlit hello」を実行すると「command not found」になる

## エラー内容および対処法

**実行環境：** MacOS ターミナル

```言語:エラー内容
% streamlit hello
zsh: command not found: streamlit
```

streamlit までのPATHが通っていないのが原因。
下記のようにPATHを指定すると実行できた。

```言語:対処内容（streamlitまでのPATHを指定して実行）
% /Users/{ユーザー名}/Library/Python/3.8/bin/streamlit hello 
```

正常に実行されると、Streamlitに関するニュースを送るためにメールアドレスの入力を促されるが、何も入力せずにエンターでOK。

その後、ブラウザが起動する。

<img width="500" alt="AZ900試験結果" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2739239/0d5a4e53-9369-9779-d2a5-a7ea377817b7.png">

終了したい場合、ブラウザはそのまま閉じればOK。
ターミナルは 「control + c」 で抜けられる。

## 備忘録 PATHの設定方法

```言語:ターミナル
% echo 'export PATH=$PATH:/Users/{ユーザー名}/Library/Python/3.8/bin' >> .zshrc   
```

.zshrc に streamlit までのPATHを設定しておくと、次回ターミナルを開いてもそのままコマンドが使えるようになる。

## 当該エラーが発生した経緯

Udemyの「爆速で5つのPython Webアプリを開発」の冒頭にて、streamlitをインストールした後の「streamlit hello」にて エラーが発生した。

ただPATHが通ってないだけのエラー対処に1時間近くかかってしまった、、、

まぁこういう道をみんな通ってるんだよね（と自分に言い聞かせる）

頑張ります。
ER図について

# ER図とは
ER図（Entity Relationship Diagram）とは、データベース設計の中で代表的な設計図です。
E = エンティティ（Entity）=モノ
R = リレーションシップ（Relationship）=関係
つまりモノと関係の組み合わせでシステムのデータやデータ間の処理構造を設計します。
システム開発においてER図は不可欠な存在です。
現在、よく使われているER図の記法は「IE記法」「IDEF1X記法」です。
今回は、「IE記法」と「IDEF1X記法」について記載したいと思います。
# IE記法　と　IDEF1X記法　の違い
### IE記法のイメージ図
![F9C63D7C-A81F-403F-A842-CE9F7DD3DAB0_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961595/f096606a-57ab-382e-6ede-d8d7deb1c524.jpeg)
### IDEF1X記法のイメージ図
![7EA61186-F7DD-4750-9AB8-FB5894DA90CF_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961595/a63f6247-fff4-9cb9-c116-fa3d30d9a862.jpeg)
「IE記法」と「IDEF1X記法」の違いは「カーディナリティ」です。
詳しくは別の章で記載します。
# ER図の各部分の名称について
![9B6C1A6A-76B0-495F-9CFA-6EFC79F33CA9_1_105_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961595/a64a1515-6ebc-ab7d-e8c2-4cf03e8fdc57.jpeg)
1.エンティティ
属性（データ）のまとまりです。
2.アトリビュート
エンティティの中にある属性情報です。
アトリビュートの中で対象の項目に「PK：主キー」「FK：外部キー」を記載します。
3.リレーション
エンティティとエンティティの相互関係です。
4.カーディナリティ
それぞれのエンティティが何個の関連を持つか表す。
![7384E110-9625-4C9C-A662-0487A66F40C4_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961595/bbd3b4df-1770-0211-6da0-199c57c8141d.jpeg)
5.エンティティの依存関係と非依存関係
依存関係とは、必ず紐づくデータのことです。その場合、エンティティ間で親子関係となり、子エンティティの枠線は角丸で表現します。
非依存関係は、エンティティ間で親子関係にありません。その場合、どちらのエンティティも直角の枠線で表現します。

# ER図の書き方
1.システムシナリオを確認
システムシナリオが明確になっていることが重要。ユースケース図とユースケース記述を作成する。
※ユースケース図とは、「ユーザーの視点でシステムの利用例を表現する図解術」です。ユースケース記述は、1つのユースケース図につき、1つのユースケース記述を作成します。内容は、ユースケースが実行する具体的な振る舞いを文章で記述したものです。
2.エンティティを洗い出す
ユースケース図やユースケース記述からエンティティを洗い出します。
3.情報を整理
アトリビュートを洗い出す前に、「マスタ系」と「トランザクション系」のデータを整理します。
4.アトリビュートを洗い出す
エンティティの中のアトリビュートを洗い出します。
5.ER図に落とし込む
ここまで準備した情報を元に、リレーション・カーディナリティ・PK（主キー）・FK（外部キー）を加えてER図に落とし込みます。
# まとめ
正直なところ、ER図は一度しか作成していません。
まだまだ不慣れです。
これから回数を重ねて、理解を深めたいと思います。
プログラマーに役立つビジネスフレームワーク集

## はじめに
「ビジネスフレームワークって便利だけど、いつ何を使ったらいいかわからない」

そんなあなたのために、フローチャート形式でまとめてみました！

## 対象者
この記事は下記のような人を対象にしています。

- 駆け出しエンジニア
- プログラミング初学者

## 結論
とにかく、フローチャートを見て！
詳しい解説はリンク先の記事を読んで！

## ビジネスフレームワーク使い分けフローチャート
![フレームワークまとめ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2157342/eac5072e-53ca-bb5d-eb45-a4bee2b43f87.png)

## リンク集
### 課題の整理

https://qiita.com/YutaManaka/items/ed128dccf03057b276e7

https://qiita.com/YutaManaka/items/58539278b79a7ec0ce27

https://qiita.com/YutaManaka/items/af3bf3512c082c3c469c

https://qiita.com/YutaManaka/items/6e6df2fd0397898d930a

https://qiita.com/YutaManaka/items/74d9c853be75f934ffc2

https://qiita.com/YutaManaka/items/0fa94826082c7505d1b9

https://qiita.com/YutaManaka/items/59e549073f7bff792d48

https://qiita.com/YutaManaka/items/e0b43b7c94f03cdc15d2

### アイデア発想

https://qiita.com/YutaManaka/items/5223e956d737822afbf2

https://qiita.com/YutaManaka/items/89ea6ef41a25ef925c35

https://qiita.com/YutaManaka/items/d83dba08dd1461380c46

https://qiita.com/YutaManaka/items/59e549073f7bff792d48

https://qiita.com/YutaManaka/items/ed128dccf03057b276e7

https://qiita.com/YutaManaka/items/c8f3da04552247750991

https://qiita.com/YutaManaka/items/e6759414d7722a136ed1

https://qiita.com/YutaManaka/items/26f8d142d5d2f3eef459


### 進捗管理

https://qiita.com/YutaManaka/items/a1c917951b1ef00d76e2

https://qiita.com/YutaManaka/items/574ccff0a9bbd8dbe7b7

https://qiita.com/YutaManaka/items/bfc10cd17866dd704665

### 目標設定

https://qiita.com/YutaManaka/items/50d812e348116638e0ef

https://qiita.com/YutaManaka/items/e6b31aa13f5fd90bb2f5


## おわりに
ビジネスフレームワークをフローチャートで解説しました。
【unity】非同期処理について

# はじめに
unityにて、非同期処理を行いたく調査をして実装したので、メモ。
（ちなみに非同期処理というのは、かなり簡潔に言うと自分以外の誰かに処理を任せるようなことを言う。）

# 内容
unityでは「コルーチン」という便利な仕組みがあり、非同期処理を簡単に実装できる。

```c#:非同期処理
    IEnumerator Example()
    {
        // フラグを設定する
        exFlg = true;

        // 指定の秒数、処理を停止する
        yield return new WaitForSeconds(waitSecond);

        // フラグを解除する
        exFlg = false;
    }
```

上記のように、`IEnumerator`というキーワードを用いて実装したい非同期処理を実装する。今回は、一定時間の間、フラグを設定する処理を実装してみた。
肝になるのは`yield`というワードで、ここで指定した時間だけ処理が止まる。と言っても、この処理の内部で止まるだけで、ゲーム自体が止まるわけではないので、ご安心を。

```c#:非同期処理（呼び出し側）
    public void waitExample(){
    
        // 非同期処理の呼び出し
        StartCoroutine("Example");

        // ここは非同期処理を呼び出してすぐに実行される。
        Debug.Log("test");
    }
```
先ほど定義した非同期処理（コルーチン）を呼び出してみる。
呼び出すには、`StartCoroutine("コルーチン名")`にて呼び出すことができる。

コルーチンを呼び出した後は、すぐにそのあとの行（`Debug.Log`の部分）が呼び出される。まさに、処理を誰かに依頼しているイメージでいるとわかりやすい。

# まとめ
- `IEnumerate`で実装したいコルーチンを定義。
- 定義する際は`yield`にて停止時間を定義する。
- `StartCoroutine`にてコルーチンを呼び出す。

これらを覚えておけば、おそらく簡単なゲームを作るのには困らないだろう。
ちなみに、誰かに処理を任せるようなイメージでいるとよい、ということは何度でも言っていく。

# 参考文献
- [【Unity】非同期処理を理解する〜コルーチン編〜](https://qiita.com/riekure/items/9f59fec68c3e31f38f11)
ServerlessFrameworkでサービス名を長くしすぎるとデプロイできない

# はじめに
ServerlessFrameworkでAPIGateway, Lambdaへのデプロイした際に発生したエラーについて記録に残したいと思います。

# 原因
デプロイの際、作成されるIamRoleの文字数制限を超えてしまい、エラーが発生する。

### エラー内容
```bash
Error:
CREATE_FAILED: IamRoleLambdaExecution (AWS::IAM::Role)
1 validation error detected: Value 'XXXXXXX-XXXX-XXXXXXXXXXXXXX-XXXX-XXX-dev-ap-northeast-1-lambdaRole' at 'roleName' failed to satisfy constraint: Member must have length less than or equal to 64 (Service: AmazonIdentityManagement; Status Code: 400; Error Code: ValidationError; Request ID: XXXXXXXXXXXXXXXX; Proxy: null)
```
「`XXX..-lambdaRole`というロール名は制約を満たしていません。64文字以下でなければなりません。」と言われました。

### クォータについて
AWSのサービスにはクォータ（quota）と呼ばれる制限のようなものが設定されています。
可用性と信頼性の高いサービスを提供し、またオペレーションミスなどによる意図しない支出からユーザーを保護するために実装されているそうです。
一部のクォータについては引き上げをリクエストすることができますが、それ以外はリクエストできません。

https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html
### IAMのクォータについて
IAMにはオブジェクトのサイズを制限するクォータがあり、それに影響を及ぼす、オブジェクトの数や文字数に制限が設定されています。
IamRoleに関しては64文字以下と設定されていました。

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html#:~:text=128%20characters-,Role%20name,-64%20characters

### ServerlessFrameworkによるIamRoleの命名規則について
ServerlessFrameworkではデプロイ時以下のようにロールの名前がつけられます。
```
<serviceName>-<stage>-<region>-lambdaRole
```
つまり、stageが`dev`、regionが`ap-northeast-1`の場合、serviceNameには34文字しか使用できません。
なので、サービス名34文字を超えるとIamRole名の文字数制限に引っかかり、エラーが発生してしまいます。

# 解決方法
IamRole名を64文字以下に収めるため、ステージ名やリージョンにもよるがサービス名を長くても30文字程度に収める。

# 参考
https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html#:~:text=128%20characters-,Role%20name,-64%20characters

https://aws.amazon.com/jp/blogs/news/aws-service-quotas/