OmniAICreator/Qiita-1.07M huggingface dataset:
inDesign XML XSLT 要素名を統一する

inDesignでXMLを書き出す際にXSLTを適用してRootの直下にある要素名を統一するスタイルシート（拡張子はxsl）は、これで良いのかな・・・？

~~~xml
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" standalone="yes"/>
    <xsl:template match="/*">
        <xsl:copy>
            <xsl:for-each select="./*">
                <xsl:element name="Story">
                    <xsl:attribute name="OriginalElementName">
                        <xsl:value-of select="name()"/>
                    </xsl:attribute>
                    <xsl:for-each select="./*">
                        <xsl:copy-of select="." />
                    </xsl:for-each>
                </xsl:element>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
~~~

↓ 変更前（見やすくしてあります）

~~~xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
    <Code_01>
        <Paragraph1>01</Paragraph1>
        <Paragraph2>猫</Paragraph2>
    </Code_01>
    <Code_02>
        <Paragraph1>02</Paragraph1>
        <Paragraph2>犬</Paragraph2>
    </Code_02>
    <Code_03>
        <Paragraph1>03</Paragraph1>
        <Paragraph2>熊</Paragraph2>
    </Code_03>
</Root>
~~~

↓ 変更後（見やすくしてあります）

~~~xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
    <Story OriginalElementName="Code_01">
        <Paragraph1>01</Paragraph1>
        <Paragraph2>猫</Paragraph2>
    </Story>
    <Story OriginalElementName="Code_02">
        <Paragraph1>02</Paragraph1>
        <Paragraph2>犬</Paragraph2>
    </Story>
    <Story OriginalElementName="Code_03">
        <Paragraph1>03</Paragraph1>
        <Paragraph2>熊</Paragraph2>
    </Story>
</Root>
~~~
Bulk APIを使ったデータ連携(準備編)

[CURLコマンドをSalesforceで活用するに戻る](https://qiita.com/Keiji_otsubo/items/51b46b9539af7edef85e)

# はじめに
Salesforceに初期値を移行する時、他のシステムとバッチでデータを連携する時にみなさんは、何を使っているでしょうか？
私は　Linux上でシェルからBulk API(V1)を呼び出して行っています。

データのインポート作業は

1. 何かしらの元データを用意する(Excel,csv,固定長テキスト、あるいは直接データベースからのデータ抽出）
2. 目的のオブジェクトに合わせて加工する。
3. 文字コードをUTF-8に変換する(特にWindowsで作ったcsvファイルは要注意です）
4. Bulk APIを使ってインポートする。(実際はupsert）

という流れだと思いますが、シェルで行えば1～4のステップを同じ環境で行えるし自動化もできます。特に文字コードの変換はコマンドが用意されているLinux(Unix)が便利です。またxlsxファイルもPythonに便利なライブラリopenpyxlがあるので簡単にCSVデータに加工できます。

基幹システム等のデータソースに直接アクセスできる権限があれば、PHPなどでデータベースに直接アクセスしてCSVに加工できるので、大変便利です。PHPであればかなり多くのデータベースに簡単に接続できます。ただし、SQL Serverはうまく行かなかったように思います。DB2は苦労しましたがPHPからでも接続可能でした。


# Linux環境の準備
すべてのLinuxディストリビューションで試したわけでないのですが、おそらく以下を満たせたら問題はないと思います。

一番大事なのはTLS1.2で通信できることです。既に[Salesforce による TLS 1.1 の無効化](https://help.salesforce.com/articleView?id=000321556&type=1&mode=1) が実施されているので、これは必須です。LinuxではOpen SSHが使えると大丈夫と言えます。

私の現在の環境はDebian 9です。以前はRed Hat Linux 8でした。Red Hat Linux 8にはOpen SSHをソースコードから展開したのでとても苦労しましたが、Debian 9はaptコマンドで簡単にインストールできました。(私の趣味でソースから作成するのが好きだったせいです。Red Hat Linux 8の問題ではないですよ)

シェルを使って処理をするのですが、bashシェルがいいかと思います。他のシェルでも問題はないかと思いますがこれからの例題はすべてbashシェルになります。必要な方は読み替えて下さい。

また、Salesforceと接続するためにはインターネット接続は必須ですね。

1. Open SSH
2. bashシェル
3. インターネット接続(Salesforceに接続できれば大丈夫）

# Salesforce側の設定

1. ネットワークアクセスにIPアドレスを登録しておくこと
2. 上記をしない場合はログイン時にセキュリティトークンが必要です。

セキュリティトークンは Salesforce から自動生成されるキーです。たとえば、パスワードが mypassword で、セキュリティトークンが XXXXXXXXXX の場合は、ログイン時に「mypasswordXXXXXXXXXX」と入力する必要があり>ます。

# トラブルシューティング

【未解決】
[Upload files to salesforce via sfdx force:data:bulk:upsert ?](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Bt2Gq)

# 資料

+ [Bulk API の制限](https://developer.salesforce.com/docs/atlas.ja-jp.230.0.api_asynch.meta/api_asynch/asynch_api_concepts_limits.htm)

+ [BULK API 2.0 Import Data with newline](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V000076B6wdSAC)


# 考察

https://trailhead.salesforce.com/content/learn/modules/org-scaling/learn-about-factors-affecting-scale?trail_id=explore-scalability

複合 API を使用して、複数の API 呼び出しを 1 つの呼び出しに統合します。Bulk API を使用する場合は、再試行の制限やタイムアウトを避けるためにバッチ サイズを最適化します。バッチ サイズは、バッチ ジョブが失敗する主な理由です。バッチ サイズが大きすぎる場合、システムはバッチが一時停止されるまでの割り当てられた 10 分以内にバッチを処理できません。 

Salesforce は、10 分を超えて実行されるバッチをタイムアウトします。組織で Bulk API 2.0 を使用している場合、バッチサイズの問題は自動的に解決されます。ただし、組織が V1 を使用している場合、通常、顧客はより高いバッチ サイズ (10,000) から開始し、タイムアウトが発生した場合はバッチ サイズを減らそうとします。 

> Bulk V1 が実行中の場合は、バッチ サイズがタイムアウトに達しないように、バッチ サイズを 7,000 に下げ、次に 5,000 に下げるというように変更するのが適切です。バッチ サイズによりスループットが低下すると同時に、ロックが排除され、再試行の回数が最小限に抑えられます。タイムアウトが継続的に問題になる場合は、Bulk API 2.0 に移行してください＞
RustのResult型のエラーハンドリング

## パターンマッチを使う方法

```rust
fn main() {
    let result: Result<i32, String> = Ok(200);
    let int = match result {
        Ok(int) => int,
        Err(code) => panic!("Error! code: {}", code)
    };
    println!("Success! int: {}", int);

    let result: Result<i32, String> = Err(500.to_string());
    let int = match result {
        Ok(int) => int,
        Err(code) => panic!("Error! code: {}", code)
    };
    println!("Success! int: {}", int);
}
// Success! int: 200
// thread 'main' panicked at 'Error! code: 500', src/main.rs:***/***
```

わかりやすいけど、ネストが深くなりがち。
## `unwrap_or_else`を使った方法

```rust
fn main() {
    let result: Result<i32, String> = Ok(200);
    let int = result.unwrap_or_else(|e| panic!("Error! code: {}", e));
    println!("Success! int: {}", int);

    let result: Result<i32, String> = Err(500.to_string());
    let int = result.unwrap_or_else(|e| panic!("Error! code: {}", e));
    println!("Success! int: {}", int);
}

// Success! int: 200
// thread 'main' panicked at 'Error! code: 500', src/main.rs:***:**
```

これでいい感じに書ける。


他にも`unwrap_or` とか`expect` とかあるけど、`unwrap_or_else`が使いやすそう。

## 参考
- 実践 Rust プログラミング入門
- [RustのOptionとResult](https://qiita.com/take4s5i/items/c890fa66db3f71f41ce7#result%E3%81%AE%E4%BE%BF%E5%88%A9%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)

## バージョン情報
```
$ cargo --version
cargo 1.54.0 (5ae8d74b3 2021-06-22)

$ rustc -V                                                                                                                                                                 
rustc 1.54.0 (a178d0322 2021-07-26)

$ rustup -V                                                                                                                                                                
rustup 1.24.3 (ce5817a94 2021-05-31)
```
XPathで指定した要素のうちN番目の要素を指定する方法

# 結論

最初の指定箇所の記述を( )で囲んでから番号を指定する。

```:例（「ログイン」という文字列が含まれるdivタグを子要素にもつbuttonタグのうち2番目の要素）
(//button[div[contains(text(), "ログイン")]])[2]
```

単純ですが検索してもなかなか見つからなかったので記事にしました。
お役に立てたら幸いです。
【RxSwift】Subject について

#概要

`` Subject`` → ``event``を``subscribers``に伝達する

新聞に例えると、、、
 新聞（``Subject``）は世の中の情報等（``event``）を人々（``subscribers``）に伝達するといったイメージです。

``Subject``とはイベントの検知だけではなく、イベントの発生をさせることができます。つまり、``ObservableType``であり、``ObserverType``でもあるということです。
#種類

RxSwiftで使用される代表的なものとして以下が挙げられます。

・Publish Subject
・Behavior Subject
・Relay Subject

##Publish Subject

初期値は持たずバッファーもなし。subscribeした時から出力される

```swift
let publishSubject = PublishSubject<String>()

publishSubject.onNext("issue 1")

publishSubject.subscribe { event in
    print(event)
}

publishSubject.onNext("issue 2")
publishSubject.onNext("issue 3")

// 出力
next(issue 2)
next(issue 3)
```
##Behavior Subject
publish Subjectとは異なり、初期値とバッファーを持つ。
subscribeした時点から一つ過去のeventから流している。

```swift
let behaviorSubject = BehaviorSubject(value: "issue 1")

behaviorSubject.onNext("issue 2")
behaviorSubject.onNext("issue 3")

behaviorSubject.subscribe { event in
    print(event)
}

behaviorSubject.onNext("issue 4")

// 出力
next(issue 3)
next(issue 4)
```

##Relay Subject

Behavior Subjectのバッファーが指定できるようになったバージョン。ただし初期値はなし。

```swift
let replaySubject = ReplaySubject<String>.create(bufferSize: 2)

replaySubject.onNext("issue 1")
replaySubject.onNext("issue 2")
replaySubject.onNext("issue 3")

replaySubject.subscribe { event in
    print("event1",event)
}
replaySubject.onNext("issue 4")
replaySubject.onNext("issue 5")

print("Subscription2")

replaySubject.subscribe { event in
    print("event2",event)
}
replaySubject.onNext("issue 6")
replaySubject.onNext("issue 7")

// 出力
event1 next(issue 2)
event1 next(issue 3)
event1 next(issue 4)
event1 next(issue 5)
Subscription2
event2 next(issue 4)
event2 next(issue 5)
event1 next(issue 6)
event2 next(issue 6)
event1 next(issue 7)
event2 next(issue 7)

```

##終わりに

以上です！
xargsと|(パイプ)の役割をgrepを例にして理解する

#始めに

いきなりですが、こんな感じでgrepをしたこと/見たことがある方は多いかと思います。

```
$ find . -name "*.php" | xargs grep hoge
```
これはカレントディレクトリ配下の「.php」がつくファイルから「hoge」という文字列を検索するコマンドになります。

以前、「なぜxargsが必要なのか」「|だけじゃダメなのか」と問われたことがあります。
頭の中ではなんとなく理解しているのですが、うまく他人に説明することができませんでした。

なので今回は備忘録を兼ねて、xargsと|(パイプ)の役割について記述していきたいと思います。

#両者の役割
##xargs
コマンドの標準出力結果を次のコマンドの引数として受け取る。
##|(パイプ)
コマンドの標準出力結果を受け取り次のコマンドに渡す。

うん。つまり？
文面じやわかりにくいですね。
この後、実際にgrepを使ってどのように動くか見ていきたいと思います。


#grepを例にして違いを見てみる
##準備
テスト用のディレクトリ内でhoge.phpとfoo.phpを用意する。
中身は2つとも同じ。

```
$ find . -name "*.php"
./hoge.php
./foo.php

$ cat *
<?php
 echo 'hoge';
<?php
echo 'hoge';
```

findの標準出力結果は、上記の通りですがこの結果を次のコマンドに渡します。

##grepで結果を比較
* |(パイプ)のみの場合

```
$ find . -name "*.php" | grep hoge
./hoge.php
```

findの標準出力結果そのものの中からgrepしていることがわかる。

* xargsをつけた場合

```
$ find . -name "*.php" | xargs grep hoge
./hoge.php:echo 'hoge';
./foo.php: echo 'hoge';
```

findの標準出力結果をgrepの引数にして実行していることがわかる。

つまり簡単に言うと
grepの対象が

前者は
「./hoge.php ./foo.php
という文字列の中から検索」

後者は
「./hoge.phpと./foo.php
というファイルの中から検索」

と考えると分かりやすいと思います。
GitHubがハロウィン仕様になっている話（茶番）

## イントロダクション

本日、10月31日はハロウィンである。

そして、今日いつものようにGitHubを眺めに行ったらとある異変に気づいた。

![スクリーンショット 2021-10-31 10.12.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1912656/fc5e36ab-a14c-8094-fdbb-4efd4817e962.png)


<strong>contributionsの色がおかし（お菓子）な色になっているではありませんか。</strong>


## これは一体、、、？

これは一体何なのだろうか？

まず、私はエンジニアとしての勘を働かせ、「GitHub version update」や「GitHub 色変更」などの検索ワードで、GitHub側の仕様変更を疑った。

場合によっては、これが今後の開発に影響をきたすかもしれない、、
ならばこちらも早急にその変化に順応すべきなのだ。


しかし、それらのワードで検索しても私が望んだ答えは見つかることがなかった。



## 解決策

答えはここにあった。

https://tiryoh.hateblo.jp/entry/2019/10/31/210410

どうやら、毎年10月31日はGitHub側がcontributionsの色を意図的にハロウィンカラーに変えているらしい。

さらに、よく見ると左下には「Happy Halloween!」の記載があった。

![スクリーンショット 2021-10-31 10.19.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1912656/e0c54d14-4a15-5ffa-5ea7-e386c416a7b2.png)

これに気づけば、これらがバグでないことぐらいすぐに分かったのに。
今回の一件で「早とちりは良くない」と思い知った。



## 最後に

こうした開発者向けのツールでの遊び心にはいつも胸を踊らされる。

いつも使っているツールの変化に気づくことや、その変化が意味するバックグラウンドを知ると結構面白い。
GitHubがハロウィーン仕様になるように、Qiitaもクリスマスで雪が降るような演出があるんじゃないかと心のどこかで願っている。


最後まで読んでくれてありがとう！
branchしてみた

初めてチーム開発したので、備忘録！


#ブランチを作る

```
git checkout -b ブランチ名
```
git branch すると作られたブランチに移動しているのがわかりますね

#結合する

ローカルブランチをmasterに結合します

git checkout masterでマスターに移動してから

```
git merge ブランチ名
```
```
git push origin ブランチ名 
```
これでリモートリポジトリに反映できる

#ついでにブランチの消し方

結合した後のブランチを消す

```
git branch -d ブランチ名
```

結合してない場合はこちら

```
git branch -D ブランチ名
```
設計書を書くときの3つの秘訣

# はじめに
設計書の書き方は人それぞれあり、ベテランの人でもそれぞれ気にしていることがあると思います。
初めて設計書を書く人達のために自分が実際に現場で設計書を書くときに気にしているコツをお伝えできればと思っています。
具体的には「いきなり設計書を書き始めない」「同じ処理の書き方は統一する」「他人が見る視点で書く」の３つとなります。

# いきなり設計書を書き始めない
個人的には一番大事にしていることでもあります。設計書はいきなり書き始めるものではなく作成物への設計が完了してから書くものだと思います。具体的には下記のような順番になるように意識しながら作業しています。

1. **作成物の情報を集める**
1. **作成物をイメージする**
1. **イメージした作成物が実現可能か考える**
1. **設計書を書く**

一見当たり前に思えるかもしれませんが、割と設計書をいきなり書き始める人は多いと思います。もちろん設計書を書いている途中で何かに気づいて作成物の情報をまた集めるみたいなことはありますが、それでもあまり平行してやらないほうが良いと考えています。
特に重要なのは「作成物の情報を集める」の部分でうまく書けない人の特徴として設計書を書くために情報収集しているために本当に作ろうとすると情報が足りていなかったりすることがあります。これはいきなり設計書を書くと起こりがちなのでそれを防ぐ効果があると思います。まずは純粋な心で作ろうとしてるものに関する情報を集めるということをやってみるだけでも効果はあるかもしれません。

# 同じ処理の書き方は統一する
これは設計書を書く時だけでなくてコーディングの時も意識しています。もしも自分がこの方がいいと思う書き方があっても原則は現場の既存の書き方に合わせた方が良いと思います。(もちろん余りにもおかしければ提案はするかもですが…)
ここでいう書き方の統一とは例えば桁数チェックの書き方でも以下のような書き方があります。

- 〇桁以上〇桁未満の場合はエラー
- 〇~〇桁でない場合はエラー
- 〇桁以上の場合はエラー。〇桁未満の場合はエラー。

全部書いていることは同じだと思うのですが、書き方が違います。ほかにも「ボタンを押す」と「ボタンを押下する」など書きっぷりは現場でことなります。この辺りを統一することは重要だと思います。理由としてはその現場にいる人たちにとって読むときに余計な思考が不要になるからです。ロジックを書く時も同じで自分が普段書く書き方と違っていても著しく劣化しているわけでない場合は書き方を揃えることでその現場の中では読みやすいコードになることが多いと思います。

# 他人が見る視点で書く
これは設計書に限らずあらゆるドキュメントを書くときに意識したほうが良いポイントでもあります。
よくあるのは謎の塗りつぶしや文字色の変更があったりよくわからない記号でグループ化されていたりとおそらく本人は意味があってそうしているのだろうと思いますが、読み手に伝わらないことが多いです。
何か塗りつぶし等を行っている場合は凡例をつけるなどして他人に伝わるように意識してみるとよいと思います。
初心者のうちに難しければまわりに意見をもらってもいいと思います。
どこまで考えても相手に伝わってないということはよくあります。「これで書いていること伝わりますか？」って聞いてみるてフィードバックを得ることでよりコツがわかると思います。

# 終わりに
いろいろ書いてみたものの自分もこれが完璧にできているのかといわれると自信が持てない部分もあります。
とはいえこれらを意識して設計書を作成しているので大きな手戻りを起こすこともなく進められているのではないかと思います。
絶対的に正しいやり方というわけでもないと思いますが、初心者の方で設計書の書き方に悩むようなことがあれば意識してみることでうまくいくかもしれません。
windowsでnvim lua

# はじめに
windowsでnvimを利用している場合に、init.vimからinit.luaへの移行

# 前提
通常、vimとnvimを共有させて利用している場合
/users/[user]/AppData/Local/Nvim/init.vim
というのをmklinkで_vimrcを参照させているという場合が多いと思う。
(管理者権限のプロンプトで以下のコマンドを入力
cd /users/[user]/AppData/Local/Nvim
mklink init.vim c:/users/[user]/_vimrc)

そういうわけで、_vimrcを残しつつ、init.luaで設定をするという話

# 参考資料
まともにコンバートするんだったらここを参照。けっこう面倒くさい
https://www.imaginaryrobots.net/2021/04/17/converting-vimrc-to-lua

# 私の移行方法
1)/users/[user]/AppData/Local/Nvim/init.vimをinit2.vimにrename
2)/users/[user]/AppData/Local/Nvim/init.luaを次のように書く

```init.lua
vim.cmd('source ~/AppData/Local/Nvim/init2.vim')
```
っで、お終い。
ただ、私の場合、その下にrequireとかlua独自の設定を作成
しとるので、まあ、lua化は必須。まあ、vimを使うのをやめれば全部luaに変更するのも
いいかもしれないけどねえ
NSGでWindows Updateを許可する方法

Twitterで「NSGでWindows Updateを許可する方法」という記事を見つけたので検証を行った結果をまとめました。
まずはNSGでできることとWindows Updateの通信の説明を簡単に行い、問題点、解決法、実装、をまとめました。
実装は2021年10月31日時点でGUIとCLI(PowerShell)を組み合わせて行うしかありません。

#NSGでできること
5タプル(条件)により通信を制御できます。
##5タプルとは
1.Source IP Address
2.Destination IP Address
3.Protocol
4.Source Port
5.Destination Port
の5つです。

#Windows Upadateの通信
以下の2つの手順を自動で行います。

1.Updateを行う対象マシンが、自身に必要なWindows UpdateのメタデータをTCP443番ポート(https)を使い<font color="red">FQDN</font>宛に通信し取得する
2.実際に必要なUpdateのデータをTCP80番(http)を使い<font color="red">FQDN</font>宛に通信しダウンロードしてインストールを行う

#問題点
NSGは[前述](#NSGでできること)の通り5タプルでの通信制御なのでFQDNでの通信制御ができません。
現状FQDNでの通信をAzure上のサービスで自由に制御しようと思うとAzure Firewallが必要です。
Azure Firewallは通信負荷を自動で検出しスケールアウトしてくれる非常に便利なサービスですが、利用の有無に関わらずデプロイ直後から月10万円近くかかる機能ですのでWindows Updateの制御のみで費用対効果は出にくいサービスと思います。
NSGで制御できれば良いのですが、Windows Updateで利用する宛先のIPアドレスは公表されていないので実質不可能である、というのが問題点です。

#解決策
NSGの通信制御方法、5タプルのSource IP AddressとDestination IP Addressですが、ここはIPアドレス以外にAzure独自の機能の<font color="red">サービスタグ</font>をいう機能があり、このサービスタグにWindows Updateに必要なFQDN郡が追加されました！
この新たなサービスタグを利用してWindows UpdateをNSGで許可すること(＝本記事)がこの[問題点](#問題点)の解決策です。

#実装
それでは実装していきますが、まずは前提の設定から確認します。
##前提
NSGで送信方向がロックダウン(Any Any Deny)されている状況を前提とします。
送信方向がAny Any Allowの場合であればそもそもWindows Updateも許可されているので今回の記事には当てはまりません。
送信方向ロックダウンとは具体的には以下の状況です。
![送信方向ロックダウン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/566b2722-80d1-3e14-0360-b4975bd874a5.png)
赤字で囲まれた部分、[名前:DenyAllOutBound]が送信方向ロックダウンの設定値です。
インターネットへの不要な通信をできないようにしたい、というセキュリティポリシーのある環境でよく見る設定です。

この状況でWindows Updateを行うと当然失敗します。
Azure上のWindows VMはデプロイ直後は英語なので日本語化(ローカライズ)作業が発生することもありますが、この送信方向ロックダウンのサブネット上のVMでは日本語の言語パックのダウンロードも失敗します。

##GUI実装
送信セキュリティ規則の[+ 追加]をクリックし、以下の図のように設定します。
<font color="red">赤枠</font>の部分がポイントです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/72073094-bf1e-2d01-8081-63f8eb91915a.png)
この設定はWindows Updateでも80番の通信を許可する設定になります。
正しく設定できると以下のような画面になります。
![NSG追加01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/8c47d5da-5798-be36-1e97-8b1e96b96c01.png)

##CLI実装
次はPowerShellでしか実装できない部分です。
PowerShellを管理者権限じ起動し、以下のコマンドを実行します。

```AzureUpdateDelivery追加.sh
$nsgName="[設定追加対象NSG名]"
$rgName="[NSGの存在するリソースグループ名]"
$nsg=Get-AzNetworkSecurityGroup -Name $nsgName -ResourceGroupName $rgName
$nsg | Add-AzNetworkSecurityRuleConfig -Name AllowAzureUpdateDeliveryHttpsOutBound -Access Allow -Protocol TCP -Direction Outbound -Priority 202 -SourceAddressPrefix "*" -SourcePortRange "*" -DestinationAddressPrefix AzureUpdateDelivery -DestinationPortRange "443"
$nsg | Set-AzNetworkSecurityGroup
```

正しく実行できると以下のようになります。
![AzureUpdateDelivery追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/b8dbcb21-6260-2aef-d38c-4e2527abf573.png)

これにてWindows Update、ローカライズが送信方向をロックダウンしていても行えるようになりました。
検証としてWindows Server 2022、Windows 10、Windows 11をこのNSG設定で日本語化を行いましたが、すべてうまくいきました。

今回はここまで。
InDesign JavaScript XML ストーリーの段落を要素に

ストーリーの段落を要素にするスクリプトは、これで良いのかな・・・？

~~~JavaScript
/*
このスクリプトを利用して起こった不具合の責任は取れません。
ご了承下さい。

更新 2021/10/31
*/

// アプリ指定
#target "indesign";

// スクリプト名
var scriptName = "ストーリーの段落を要素に";

//スクリプトの動作指定（一つのアンドゥ履歴にする、及び、アンドゥ名）
app.doScript(function(){

    // ダイアログ
    var dialogueFlg = confirm("ストーリーの段落を段落の「終わりの記号」を除いて要素にします。" + "\r\r"
    + "段落の先頭に「索引マーカー」がある場合は追加された要素にその「索引マーカー」は含まれないので注意して下さい（手抜き仕様）。" + "\r\r"
    + "ストーリーの要素を選択してスクリプトを実行して下さい。"
    ,"", scriptName);

    // Noの場合
    if(dialogueFlg == false){
        exit();
    }

    // 検索の初期化
    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;
    
    // 検索文字列
    app.findGrepPreferences.findWhat = ".+";
    
    // 段落の最大数
    var paragraphCountMaxNumber = 0;

    if(app.activeDocument.selection.length > 0){

        // 最大の段落数を調べる
        for(var i = 0; i < app.activeDocument.selection.length; i++){
            if(app.activeDocument.selection[i].constructor.name == "XMLElement"){
                if(app.activeDocument.selection[i].xmlContent.constructor.name == "Story"){
                    if(paragraphCountMaxNumber < app.activeDocument.selection[i].xmlContent.paragraphs.count()){
                        paragraphCountMaxNumber = app.activeDocument.selection[i].xmlContent.paragraphs.count();
                     }
                 }
             }
         }

        // タグを追加する
        for(var i = 1; i <= paragraphCountMaxNumber; i++){
            if(app.activeDocument.xmlTags.itemByName("Paragraph" + i).isValid == false){
                app.activeDocument.xmlTags.add("Paragraph" + i);
            }
        }

        // 段落に要素を関連付け
        for(var i = 0; i < app.activeDocument.selection.length; i++){
            if(app.activeDocument.selection[i].constructor.name == "XMLElement"){
                if(app.activeDocument.selection[i].xmlContent.constructor.name == "Story"){
                    for(var ii = 0; ii < app.activeDocument.selection[i].xmlContent.paragraphs.count(); ii++){
                        
                        // 置換でタグを付ける
                        app.changeGrepPreferences.markupTag = app.activeDocument.xmlTags.itemByName("Paragraph" + (ii + 1));
                        app.activeDocument.selection[i].xmlContent.paragraphs.item(ii).changeGrep();
                    }
                }
            }
        }
    }

    // 検索の初期化
    app.findGrepPreferences = NothingEnum.NOTHING;
    app.changeGrepPreferences = NothingEnum.NOTHING;

//スクリプトの動作指定の続き
}, ScriptLanguage.JAVASCRIPT, [scriptName], UndoModes.ENTIRE_SCRIPT, scriptName);
~~~
FastAPIで作るWebアプリ - Form validation

今回はFastAPIのFormのValidationについてです。

【過去記事】
[Python Asyncio入門](https://qiita.com/sand/items/0e445a13d81d20ea33c3)
[Aiohttpで作るSimple Web Server - Qiita](https://qiita.com/sand/items/971c851598ff59c1c905)
[Starletteで作る Simple Web Server - QIita](https://qiita.com/sand/items/dd622ce4f9249399974c)
[FastAPIで作るWebアプリ - 基本](https://qiita.com/sand/items/bba0913fe4504c612b3a)
[FastAPIで作るWebアプリ - validation](https://qiita.com/sand/items/85068532388826258df4)
[FastAPIで作るWebアプリ - Body validation](https://qiita.com/sand/items/470b33d7539713432090)
[FastAPIで作るWebアプリ - Form validation](https://qiita.com/sand/items/207f306bdacdc0fb9571)

[FastAPI 公式サイト](https://fastapi.tiangolo.com/ja/)


Bodyの時とほぼ同じプログラムです。

```python:form1.py
from fastapi import Form, FastAPI

app = FastAPI()

@app.post("/items/")
async def create_item(name: str=Form(...), price: float=Form(...)):
    return {"name": name, "price": price}
```

Form()関数はBody()関数とほぼ同じですが、以下の違いを吸収します。

* Body Request => Content-Type: application/json
* Form Data => Content-Type: application/x-www-form-urlencoded


正常なデータをRequestします。

```
curl -X 'POST' 'http://localhost:8000/items/' -H 'accept: application/json' -H 'Content-Type: application/x-www-form-urlencoded' -d 'name=Hanako&price=5.3'
```

サーバ側は200 okの出力をし、クライアント側は以下のデータを受け取ります。


```
{"name":"Hanako","price":5.3}
```


もちろんエラーデータのRequestに対しては、Bodyの時と同じようにエラーとなります。

今回は以上です。
【JavaScript】関数とオブジェクト⑯　クラス



#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/f95766c27d099ed686ba

#目的

* 関数とオブジェクトについての理解を深める

#本題
###1.クラス

コンストラクター関数をクラス表記したもの
→　シンタックスシュガー

####例1

````js
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.hello = function() {
  console.log('hello ' + this.name);
}
````

上記のPersonコンストラクターをクラスに書き換えていく


````js
// クラスを用意
class Person {
  // constracterで関数を定義
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  // プロトタイプのメソッドも関数と同じ並びに配置
  // function削除
  hello() {
    console.log('hello ' + this.name);
  }
}

//　インスタンス化
const Lupin = new Person("ルパン", 26);
// 出力するとPerson {name: 'ルパン', age: 26}で返ってくる
console.log(Lupin);
````

JavaScriptではインスタンス化したら、オブジェクトで返ってくる

###2.クラス継承

クラス継承とは他のクラスのメソッドやプロパティを継承すること

####例1.

````js
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.hello = function() {
  console.log('hello ' + this.name);
}

function Japanese(name, age, gender) {
  Person.call(this, name, age);
  this.gender = gender;
}

Japanese.prototype = Object.create(Person.prototype);

Japanese.prototype.hello = function() {
  console.log('Konnichiwa ' + this.name);
}

Japanese.prototype.bye = function() {
  console.log('Sayonara ' + this.name);
}

const taro = new Japanese('Taro', 23, 'Male');
`````

上記のプロトタイプ継承されたコードをクラス継承に変えていく

````js
// Personをクラス表記に変更
class Person{
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  // helloメソッド追加
  hello() {
    console.log('hello ' + this.name);
  }
}

// 同様にjapaneseクラスを作成
// Javaでも使用したモノ！
class Japanese extends Person{
  constructor(name, age, gender) {
    // クラスの継承では下記を使用していたが、クラスではextendsを使用
    // Person.call(this, name, age);
    // superを使用することで継承元のプロパティを使用できる
    super(name, age);
    this.gender = gender;
  }
  // helloメソッドを追加
  hello(){
    console.log('Konnichiwa ' + this.name);
  }
  // byeメソッドを追加
  bye() {
    console.log('Sayonara ' + this.name);
  }
}
// 下記のコードもextendsによって実現されるので不要
// Japanese.prototype = Object.create(Person.prototype);

// インスタンス化
const taro = new Japanese('Taro', 23, 'Male');
// 出力するとオブジェクトが生成される
console.log(taro);
// taroメソッドが使用される
taro.hello();
`````



今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
ElixirのIExをElixirカラーにする


- IExの`iex>`をElixirカラーにする
- その他、適宜IExの設定変更

イメージ
![](https://user-images.githubusercontent.com/7563926/139561007-e9460682-065e-4ed9-b5ec-59e746b0fcd9.png)

## [`.iex.exs`]ファイル

2種類あります

- グローバル
  - `$HOME/.iex.exs`
  - すべてのElixirアプリに適用したい設定をおいておくところ
- ローカル
  - `my-app/.iex.exs`
  - 各Elixirアプリごとに`alias`とかをおいておくところ

IExの`iex>`はすべてのElixirアプリに使用されるので、グローバルの[`.iex.exs`]ファイルに設定を書きます

ここに一例をあげますが、楽しいのでぜひ自由にカスタマイズしてみてください

```elixir:~/.iex.exs
# どの iex.exs ファイルが使用されているかを表示
[:blue_background, :bright, :white, "Using config file: ", __ENV__.file]
|> IO.ANSI.format()
|> IO.puts()

# IExの設定
IEx.configure(
  inspect: [limit: 5_000],
  history_size: 100,
  # `iex>`のカスタマイズ（通常時）
  default_prompt:
    [:light_magenta, "%prefix>"]
    |> IO.ANSI.format()
    |> IO.chardata_to_string(),
  # `iex>`のカスタマイズ（分散ノード使用時）
  alive_prompt:
    [:light_magenta, "%prefix(%node)>"]
    |> IO.ANSI.format()
    |> IO.chardata_to_string()
)

# Phoenixアプリでよく使うmoduleはimportしておくと便利かも？
import_if_available(Plug.Conn)
import_if_available(Phoenix.HTML)
import_if_available(Ecto.Query)
import_if_available(Ecto.Changeset))
```

ローカル[`.iex.exs`]ファイルには忘れずにグローバルの[`.iex.exs`]ファイルをインポートしてください

```elixir:my-app/.iex.exs
import_file_if_available("~/.iex.exs")

...
```

[Nervesターゲット端末のIExをカスタマイズ](https://qiita.com/mnishiguchi/items/9e259b8836054bb5cb34)も可能です

## 資料

- [Configuring the shell]
- [`IEx.configure/1`]
- [`Inspect.Opts`]
- [`IO.ANSI`]

```elixir
iex> h IEx.configure/1
```

おーはらさんのスライドに日本語で包括的に説明されています。Awesome!

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">本日の発表資料です<a href="https://t.co/IjC8wnIYIF">https://t.co/IjC8wnIYIF</a><a href="https://twitter.com/hashtag/tokyoex?src=hash&amp;ref_src=twsrc%5Etfw">#tokyoex</a></p>&mdash; おーはら (@ohrdev) <a href="https://twitter.com/ohrdev/status/1474968395087237121?ref_src=twsrc%5Etfw">December 26, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<!-- Links -->
[`.iex.exs`]: https://hexdocs.pm/iex/IEx.html#module-the-iex-exs-file
[`IO.ANSI`]: https://hexdocs.pm/elixir/IO.ANSI.html
[`IEx.configure/1`]: https://hexdocs.pm/iex/IEx.html#configure/1
[`Inspect.Opts`]: https://hexdocs.pm/elixir/Inspect.Opts.html
[Configuring the shell]: https://hexdocs.pm/iex/IEx.html#module-configuring-the-shell
[Nukkit]Configを使う

# はじめに
備忘録です

# setup
## resourceにconfig.ymlを作る
```config.yml
Test:
  Message: "てすとめっせーじ"
  Wallet: 1000
```

## 起動時にconfig.ymlを保存する
この時点でresourceに書いたconfig.ymlがプラグインのデータファイルにコピーされます
二回目以降の起動では行われません

```kotlin
override fun onEnable() {
    saveDefaultConfig()
}
```

# つかう
## configの取得
Pluginクラスから取得できます

```kotlin
val plugin = Main()
val config = plugin.config
```

## 値の取得
`config.getT("key")`（文字列なら`getString("key")`）を使います
階層はドット（.）で表すことができます

```kotlin
val message = config.getString("Test.Message")
logger.info(message) // てすとめっせーじ
val wallet = config.getInt("Test.Wallet")
logger.info(wallet) // 1000
```
ランダムなダミーの温湿度の値で急激な変動がない値を生成する（Node.js で simplex-noise を利用）

「デバイス＋センサー」が MQTTクライアントになった構成の開発をしている中で、MQTT の値を受信する MQTTブローカーの部分や別クライアント側に手を加える開発をするのに、以下のような物理部分をセットしなくても開発できるようにしたくて、今回の内容を進めました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">GR-ROSE と「Grove - CO2 &amp; Temperature &amp; Humidity Sensor (SCD30) 」の接続はスルーホール用テストワイヤを使い、差し込み式で接続してる。 <a href="https://t.co/hA2wu3KYw3">https://t.co/hA2wu3KYw3</a> <a href="https://t.co/WbV3yNgNB6">pic.twitter.com/WbV3yNgNB6</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1454448956109312001?ref_src=twsrc%5Etfw">October 30, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 概要

ひとまず温湿度の 2つの値を対象に、それらをランダムに生成するプログラムを作っていきます。
その値について、JavaScript だと [Math.random()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/random) を使う方法もありますが、あまり急激な変化はしてほしくなかったため、乱数生成の部分には「Simplex Noise」を使いました（パッケージは以下を利用）。

●simplex-noise - npm
　https://www.npmjs.com/package/simplex-noise

ちなみに、Simplex Noise をざっくり説明すると、以下のパーリンノイズと同じようなものになります。

●パーリンノイズ - Wikipedia
　https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%83%AA%E3%83%B3%E3%83%8E%E3%82%A4%E3%82%BA

## 必要になる環境など
開発には Node.js を使っていきます。

MQTTブローカーを何らか用意し、今回のプログラムを動作させる PC の中で動かしてください。
また、以下のコマンドで 2つのパッケージを利用できるようにしておいてください。

```bash
$ npm i mqtt simplex-noise
```

## プログラム
プログラムの内容は、以下のとおりです。

```javascript
const mqtt = require("mqtt");
const client = mqtt.connect("mqtt://localhost");
const { SimplexNoise } = require("simplex-noise");

const simplex = new SimplexNoise();
let count = 0;

client.on("connect", function () {
  const timerId = setInterval(() => {
    const randomT = convertedValueRandom(simplex.noise2D(count, 10), 20, 25);
    client.publish("outTopic/T", randomT + "");
    const randomH = convertedValueRandom(simplex.noise2D(count, 20), 60, 80);
    client.publish("outTopic/H", randomH + "");
    console.log(`
    温度: ${randomT}, 
    湿度: ${randomH}`);
    count += 0.007;
  }, 2000);
});

function convertedValueRandom(inputSimplexNoise, min, max) {
  const randomZeroToOne = (inputSimplexNoise + 1) / 2;
  return randomZeroToOne * (max - min) + min;
}
```

simplex-noise　は -1　から 1　の間の値を生成するため、Math.random() のような　0 から 1 の値を生成させたい場合は、少し手を加える必要があります。
上記の中では、 `convertedValueRandom()` でその変換を行っています。

また、 `count += 0.007` の値を変更すると、生成される乱数の変化の度合いを変えることができたりもします。
【Ruby】条件分岐　備忘録

#目的
条件分岐 備忘録

#結論
とりあえず3種類あった。
if文
unless文 
case文

```ruby:timesメソッド　#if文
a = 10
b = 20
if a > b
  puts "aはbより大きくない"
elsif a < b
  puts "aはbよりも小さい"
end
=>aはbより大きくない
```


```ruby:timesメソッド　#unless文 
a = 10
b = 20
unless a > b
　　puts "aはbより大きくない"
end
=>aはbより大きくない
```

```ruby:timesメソッド　#case文
array = [ "a", 1, nil ]
array.each do |item|
  case item
  when String
    puts "item is a String"
  when Numeric
    puts "item is a Numeric"
  else
    puts "item is something"
  end
end
=>item is a String
  item is a Numeric
  item is a something
```
#参考
たのしいRuby第５版
【TailwindCSS】クラスを自動整形する方法について

#はじめに
こんにちは。
こちらの記事では、TailwindCSSのクラスを自動整形を行う方法を記しています。
誤っている点がございましたらコメントいただけると幸いです。

##なぜ自動整形する必要があるのか
Tailwindcssでは、classに直接スタイルの記述を行えますが、ルールを決めないとクラスの順番に一貫性がなくなり、見づらくなってチーム開発でも弊害が発生してしまうかと思います。
そのため、こちらの記事では[Prettier Plugin Tailwind](https://github.com/Acidic9/prettier-plugin-tailwind)を使用して、クラスの自動整形を行う方法を紹介いたします。


##実装手順
今回は、下記のdivタグのクラスを整形していきます。


```html:template
<div class="px-4 py-20 md:py-40 items-center mx-auto md:flex container"></div>
```

###1. Prettier Plugin Tailwindのインストール
yarnでインストールする場合は、GitHubのとおり下記のコマンドで実行。

```
yarn add --dev prettier prettier-plugin-tailwind
```

npmの場合は、下記のコマンドで実行する。

```
npm install --save-dev prettier prettier-plugin-tailwind
```

yarnのコマンドをnpmに変換したいときは、[こちらの早見表](https://qiita.com/rubytomato@github/items/1696530bb9fd59aa28d8)が参考になるかと思います。

インストールが完了したら、`package.json`の`devDependencies`に追加されていることを確認します。

※ `dependencies`は、本番環境で使われるパッケージ（ nuxtやaxiosなど ）
※ `devDependencies`は、開発時のみ使われるパッケージ（ PrettierやJestなど ）

###2. Prettier Plugin Tailwindを実行する
クラスを整形したいファイルを保存することで、処理がはしります。先ほどのdivタグを自動整形すると以下のようになります。

```html:template
<div class="container items-center mx-auto px-4 py-20 md:flex md:py-40"></div>
```

Githubにも記載がありますが、デフォルトの並び替えは以下のようになっているようです。

```
{
"container,position,zIndex,inset,display,flex,flexDirection,flexGrow,flexShrink,flexWrap,gap,gridAutoFlow,gridColumn,gridColumnEnd,gridColumnStart,gridRow,gridRowEnd,gridRowStart,gridTemplateColumns,gridTemplateRows,alignContent,alignItems,alignSelf,justifyContent,justifyItems,justifySelf,verticalAlign,placeContent,placeItems,placeSelf,float,clear,order,tableLayout,margin,padding,width,minWidth,maxWidth,height,maxHeight,minHeight,textAlign,textColor,textDecoration,textOpacity,wordBreak,whitespace,fontFamily,fontSize,fontSmoothing,fontStyle,fontVariantNumeric,fontWeight,letterSpacing,lineHeight,backgroundColor,backgroundImage,backgroundSize,backgroundPosition,backgroundRepeat,backgroundAttachment,backgroundClip,backgroundOpacity,borderWidth,borderStyle,borderColor,borderOpacity,borderRadius,borderCollapse,placeholderColor,placeholderOpacity,outline,fill,stroke,strokeWidth,boxShadow,gradientColorStops,opacity,visibility,accessibility,appearance,boxSizing,cursor,pointerEvents,userSelect,divideColor,divideOpacity,divideStyle,divideWidth,listStylePosition,listStyleType,objectFit,objectPosition,overflow,overscrollBehavior,transform,transformOrigin,translate,textTransform,resize,rotate,scale,skew,space,animation,transitionProperty,transitionDuration,transitionDelay,transitionTimingFunction,preflight"
}
```

<br>

#おわりに
ここまでTailwindCSSのクラスを自動整形を行う方法についてまとめました。
今後もアウトプットしながら学習を進めていきたいと思います！
以上、最後まで読んでいただきありがとうございました！
DatabricksのHIPAA準拠デプロイメント

[HIPAA\-compliant deployment \| Databricks on AWS](https://docs.databricks.com/security/privacy/hipaa-compliant-deployment.html) [2021/6/11時点]の翻訳です。

Databricksは、お客様がPHI(保護対象保健情報：protected health information)データを処理する前に、Databricksとオーダーフォーム、および、Business Associate Agreement (BAA)に対して相互にサインした場合に、PHIデータを処理するためのHIPAA(Health Insurance Portability
and Accountability Act of 1996:医療保険の携行性
と責任に関する法律)準拠のデプロイメントをサポートすることができます。

# AWSとBusiness Associate Agreement(BAA)にサイン

お客様のアカウントマネージャーにコンタクトするか、sales@databricks.comにメールを送り、HIPAA規制に準拠する様にDatabricks、AWSの両方とBusiness Associate Agreement(BAA)にサインします。このアグリーメントはHIPAA準拠の下、Databricksでお客様がPHIを処理することを許可するために必要となります。

# HIPAA準拠クラスターの作成および検証

これらのステップでは、PHIデータを処理するHIPAA準拠クラスターの作成方法を説明します。

## ステップ1: クラスターの作成

[クラスター作成](https://qiita.com/taka_yayoi/items/d36a469a1e0c0cebaf1b)の手順に従います。設定のステップにおいて、[Databricksランタイム](https://docs.databricks.com/runtime/index.html#dbr-overview)を選択する必要があります。

> **警告!**
[Databricks機械学習ランタイム](https://qiita.com/taka_yayoi/items/824b507019d3ade7eedc)には、[MPI \(Message Passing Interface\)](https://en.wikipedia.org/wiki/Message_Passing_Interface)や、低レベルコミュニケーションプロトコルを使用する、高パフォーマンス分散処理機械学習パッケージが含まれています。これらのプロトコルは、ネイティブで通信時の暗号化をサポートしていないので、これらのMLパッケージには、センシティブなデータを暗号化されない状態でネットワークに送信する潜在的リスクが存在します。お使いのワークフローにおいて、これらのパッケージに依存しないのであれば、これらのパッケージによって通信時のデータ暗号化が変更されることはありません。

> **どのようなリスクが？**
MLパッケージによってネットワークに送信されるメッセージは、多くの場合、MLモデルのパラメーターかトレーニングデータに関するサマリー統計情報ですので、多くの場合、PHIのようなセンシティブなデータが暗号化されない状態で送信される訳ではありません。しかし、特定の設定や、これらのパッケージの利用(例えば、特定のモデルの設計)によって、これらの特別な情報がネットワーク上のメッセージとして送信される可能性があります。

> **どのパッケージが関係するのか？**

> - [XGBoost](https://docs.databricks.com/applications/machine-learning/train-model/machine-learning.html#xgboost)
- [Horovod](https://github.com/horovod/horovod)、[HorovodEstimator](https://docs.databricks.com/applications/machine-learning/train-model/distributed-training/horovod-estimator.html#horovodestimator)、[HorovodRunner](https://docs.databricks.com/applications/machine-learning/train-model/distributed-training/horovod-runner.html#horovodrunner)
- 分散[TensorFlow](https://github.com/tensorflow/tensorflow/blob/master/SECURITY.md)

## ステップ2: EBSボリュームを用いたクラスター設定

デフォルトのローカルストレージは暗号化されないため、暗号化されたDatabricks EBSボリュームを選択して、EBSボリュームを配備します。
![](https://docs.databricks.com/_images/ebs-volumes.png)

## ステップ3: 暗号化が有効化されていることを確認

1. ワークスペースでノートブックを作成し、上のステップで作成したクラスターにアタッチします。
1. ノートブックで以下のコマンドを実行します。

```scala:Scala
%scala spark.conf.get("spark.ssl.enabled")
```

trueが戻って来れば、暗号化が有効化された状態でクラスターを作成できたことになります。そうでない場合には、help@databricks.comにご連絡ください。

> **重要!**
`spark-submit`は、HIPAA準拠クラスターではサポートされていません。

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
[実践] JMeterを使ってAWS環境のWebアプリケーションを性能検証する① 導入

システムパフォーマンスの本を読んで、自分も検証してみたい！と思ったけど、環境構築が手間で諦めた。。。という人、多いと思います。

本記事では、性能検証のための環境構築と、検証の観点について記載いたします。お役に立てたら幸いです。

# システム概要

<img width=100% alt="システム概要図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269289/45c13a4a-bd5f-29e5-14ab-059d80c0fe14.png">

* 本システムは、構成管理兼踏み台、負荷掛け、Web3層の3つのパートからなります。
* AWSの構成管理には CloudFormation を、各サーバのミドルウェアの管理には Ansible を使用します。
* Webアプリへの負荷掛けは JMeter サーバ/クライアントを通して行います。
* Webサーバには Apache httpd と Tomcat、アプリケーションは [TERASOLUNAサンプルアプリケーション](https://github.com/terasolunaorg/terasoluna-tourreservation)を使用します。
* DBエンジンは PostgreSQL を採用します。

# 今後の流れ

* 性能検証の進め方は、[「Amazon Web Services負荷試験入門」](https://gihyo.jp/book/2017/978-4-7741-9262-8 "Amazon Web Services負荷試験入門")を参考にしました。

* 環境構築、性能検証に用いるファイルは[githubリポジトリ](https://github.com/muroya2355/aws_performance_test)で公開しています。

## ①導入
* 本ページです。

## [②環境構築（1）AWS編](https://qiita.com/muroya2355/items/11029a17acec5f0d0e78)
* CloudFormation を用いて、ELB + EC2 + RDS のオーソドックスな AWS システムを構築します。AWS構成図は以下になります。

<img width=80% alt="システム概要図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269289/94982380-505e-2999-0d93-e7119fbddea4.png">


## [③環境構築（2）Ansible編](https://qiita.com/muroya2355/items/c5fda6ddb635f70cca7a)
* 構成管理サーバの Ansible を用いて、各サーバをプロビジョニングしていきます。ソフトウェア構成図は以下。

<img width=100% alt="システム概要図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269289/9cbd4e26-7503-90fa-5a6f-31090fc418ef.png">

## [④JMeterシナリオ作成、動作確認](https://qiita.com/muroya2355/items/8ed24acc763ed62273aa)
* 今回のサンプルアプリケーションに合わせた JMeter のシナリオ作成と、軽い負荷掛けで動作確認を行います。


## ⑤性能検証（1）性能目標に向けたチューニング
* あらかじめ性能目標を立てておき、それを満たすようにチューニングを行います。（アプリケーションには手を加えず、インフラ面でのチューニングを行います。）

## ⑥性能検証（2）限界スループット確認
* 更にチューニング、スケールアップ等を行い、本システムの限界性能を確かめます。
[競プロ] 利益を最大化するジョブスケジューリング問題

## 利益を最大化するジョブスケジューリング問題を解く

[1235. Maximum Profit in Job Scheduling](https://leetcode.com/problems/maximum-profit-in-job-scheduling/)

## DP

Jobを下記のように定義し、startTimeでソートしておく

```
job = {startTime, endTime, profit}
```

DPを下記のように定義する

```
DP[startTime] = 取得可能な最大利益
```


## 回答

Job配列の後ろからループを回し、現在のjobの利益と終了する時刻以降の最大利益を利益とする。

```
DP[startTime] = profit + DP[endTime]
```

```c++
int currentMax = 0;
map<int,int> mp; // mapを使ってDPを定義する
for (int i=n-1; i>=0; i--) {
    auto it = mp.lower_bound(job[i][1]); // 現在のjobの終了時刻以降で取得できる最大利益を探す
    if (it == mp.end()) currentMax = max(currentMax, job[i][2]); // ない場合は今のjob利益のみ
    else currentMax = max(currentMax, job[i][2] + it->second);
    
    mp[job[i][0]] = currentMax; // 現在の最大利益を現在のjobの開始時刻で記録しておく
}

return currentMax;
```

## 関連問題
[1751. Maximum Number of Events That Can Be Attended II] (https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended-ii/)
[2008. Maximum Earnings From Taxi](https://leetcode.com/problems/maximum-earnings-from-taxi/)
[2054. Two Best Non-Overlapping Events](https://leetcode.com/contest/biweekly-contest-64/problems/two-best-non-overlapping-events/)
【SPARQL】独自の型の値をFilterで絞り込みしたい

## SPARQLについて
SPARQLは現状（2021年10月）、Wikipedia（[DBpedia](http://ja.dbpedia.org/)）や自治体関係のデータのAPI取得などで度々用いられるクエリです。
概要については[SPARQL入門](https://www.slideshare.net/takemikami/sparql-123607069)を参照ください。

## 今回のトピック
法人情報のデータを取得できるAPI、[gBizINFO](https://info.gbiz.go.jp/)においてSPARQLを使用できます。gBizINFOの概要については[gBizINFOから法人情報APIを取得してみる](https://qiita.com/jfk20tktk04/items/36586833dddc39b13a6c)の記事などを参照ください。

このgBizINFOで、例えば財務データの勘定科目を取得する際に、以下のような独自の型で設定された項目がレスポンスで来たりします。

```json
"shihyou": {
  "datatype": "http://imi.go.jp/ns/core/rdf#コード型",
  "type": "literal",
  "value": "http://hojin-info.go.jp/code/財務情報/資本金"
},
```

これを資本金だけに絞り込みたい場合、以下のようなFilterの設定では上手くいきません。
`FILTER(?shihyou = "http://hojin-info.go.jp/code/財務情報/資本金")`


## 対応
[リテラルと任意のデータ型とのマッチング](https://www.asahi-net.or.jp/~ax2s-kmtn/internet/rdf/REC-sparql11-query-20130321.html#matchArbDT)の記事にある通り、独自の型でマッチングさせたい場合は`^^型名`のような感じで明示的に型を指定してあげる必要があります。
なお、`xsd:string`や`xsd:integer`などの一般的（？）な型であれば、あえて型名を指定する必要がなく、SQLと同じような感じでFilterに条件を書くことができます。

## クエリサンプル
gBizINFOのAPIで、資本金の項目でデータを取得したい場合のクエリを例にします。

```sparql
PREFIX hj: <http://hojin-info.go.jp/ns/domain/biz/1#>
PREFIX ic: <http://imi.go.jp/ns/core/rdf#>

SELECT ?cID ?name ?value ?hyouki ?shihyou
FROM <http://hojin-info.go.jp/graph/zaimu>
WHERE {
  ?s hj:法人活動情報 ?o .
  ?o ic:名称/ic:表記 ?name .
  ?o ic:ID/ic:識別値 ?cID .
  ?o hj:数量コレクション/hj:数量 ?c .
  ?c ic:数値 ?value .
  ?c ic:単位表記 ?hyouki .
  ?c hj:指標 ?shihyou
  FILTER(?shihyou = "http://hojin-info.go.jp/code/財務情報/資本金"^^ic:コード型)
}
limit 100

```
USB接続されたRaspberry Pi Zeroに、Virtual BoxのUbuntu経由でWindowsからSSH・VNC接続する方法

自分の環境では、どうしてもWindowsからRaspberry Pi Zero（以下、RPi）にUSB接続（USB Ethernet）できなかったので、Windows上のVirtual Box（以下、VBox）でUbuntuを起動して、これを経由してWindowsからRPiにVNC接続するまでをまとめました。   

+ 参考URL：https://yomon.hatenablog.com/entry/2018/09/raspberrypizeroinit

##20211104続報
↓ VBoxのUbuntuでも見えなくなりました。その後、Imagerの際にホスト名を変更したらアクセスできました。ネームとしての識別性が重要なのか。また続報します。

## 手順
	
1. 上記URLを参考にmicroSD（RPi OS）ドライブ内のconfig.txt、cmdline.txtを編集、sshという空ファイルを作成
    1. RPiをPCにUSB接続 ← PC環境はWindows＋VBox（Ubuntu）
1. VBoxでUbuntuを起動
    1. VBoxのメニュータブから「デバイス → USB → Linux ... Ethernet Gadget」をチェック
    1. Ubuntuターミナルでifconfigを実行 ← USB Ethernetのinterfaceが加わっている。例えば、``enxb662d8c332e8``
1. それを用いて、以下のコマンドを順次実行（上記URLを参照）

```
$ nmcli c add type ethernet con-name raspi-usb ifname enxb662d8c332e8
$ nmcli c modify raspi-usb ipv4.method shared
$ nmcli c up raspi-usb
```

- これでUSB Ethernetが正常に接続するはず ← Ubuntu側（上記interface）に``10.42.0.1``みたいなIPが振られる
    1. まずは ``ssh pi@raspberrypi.local``でログイン（←このように名付けていれば）
    1. ログイン後、RPi側でifconfigでIPを調べる → 例えば、``10.42.0.151``
- 後は、仮にVBox UbuntuのIP（ホストオンリーネットワーク）が``192.168.56.101``となっているとして、Windowsのcmdから以下のトンネルを掘る
    1. ``ssh -L 5900:10.42.0.151:5900 username@192.168.56.101`` ← VNCを5900ポート運用として
    1. これでWindows``localhost:5900``からVNC経由でRPiに接続できる
javascript演習　１１日目/３０日

覚えたこと

videoタグ

paused と　pause()

```javascript
if(video.paused){
        video.play();
    }else{
        video.pause();
}

//こうも書ける

const method = video.paused ? 'play' : 'pause';
video[method]();
```


video.currentTime　と　this.dataset

```javascript
<button data-skip="-10" class="player__button">« 10s</button>
<button data-skip="25" class="player__button">25s »</button>

<script>
function skip(){
video.currentTime += parseFloat(this.dataset.skip);
}
</script>
```


name属性を使って連動させる

```javascript
<input type="range" name="volume" min="0" max="1" step="0.05" value="1">
<input type="range" name="playbackRate" min="0.5" max="2" step="0.1" value="1">

<script>
function handleRangeUpdate(){
    video[this.name] = this.value;
}
</script>
```


video.duration　と　cssのflex-basis

```javascript
function handleProgress(){
    const percent = (video.currentTime / video.duration) * 100;
    progressBar.style.flexBasis = `${percent}%`;
}

video.addEventListener('timeupdate', handleProgress);
```


その他

```javascript
function scrub(e){
    const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration;
    video.currentTime = scrubTime;
}
```

あとaddEventListener　の　mousedown　とか　mouseupとか

 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ーーー
参考

https://developer.mozilla.org/ja/docs/Web/API/HTMLMediaElement
【備忘録】fakerで生成した文字列がLaravelのテストを通らない

##結論

####ヘルパーファンクションをつかって特殊文字のエスケープ

テストをこうする

```php
$response->assertSee(e($Sample->name));
```

e()で特殊文字をエスケープしてテストすることができる

##経緯

####クォーテーションが入ってるダミーデータが生成されると通らない
Laravel 6でファクトリーを使って生成した文字列データをAssertSeeでテストすると通ったり通らなかったり。
確認したところクォーテーションが入ってるダミーのみ通っていないっぽい。

ファクトリー

```php
$factory->define(Sample::class, function (Faker $faker) {
    return [
        'name' => $faker->realText(10),
    ]
```

テスト

```php
$response->assertSee($Sample->name);
```

***


####参考

https://laracasts.com/discuss/channels/testing/assertsee-on-strings-with-a-quote

***
fortigateでVLANスイッチなしにtaggedポートとuntaggedポートを共存する方法

##目的

FortigateでVLANを設定すると必ず「tagつきポートしか定義できない」「tagなしポートを使うにはVLANスイッチ配下に」という検索結果が多くありましたが、そうではないのではないかということで、調査し、fortigate内でtaggedポートとuntaggedポートの共存が可能であることを確認できましたので報告します。なぜそのような誤解があるのかも触れます。

---
##検証機器
Fortigate 60E v5.6.3 build1547
※古いファームウェアです。　最新のFortigate 40Fを入手して追検証予定です。


##目標
・fortigate内でタグなしポートとタグありポートを共存させる。
・各ポートからインターネット接続を確保する

---
##システム構成
fortigate内に検証用vdomを設定
internal 1-2をタグ付きポート　（VLAN番号21）
internal 3-4をタグなしポート(VLAN番号21と通信できるようにする)

インターネットへはvdom-linkを使い既存環境へ接続

internal1とinternal2にはVLAN対応のHUBを接続
internal3とinternal4には通常の端末を接続

---
##・設定手順
1.tagをつけたいポートが複数ある場合はハードウェアスイッチを定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234086/d88f6a01-9b5e-7b81-973d-0b53ef28d075.png)
※ポートによってVLANの内容が違う場合などは、この手順を省略して、個別のポートにVLANを定義します

---
2.VLANを定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234086/8efe4885-61fb-1e22-79ce-d44cc63e009c.png)
VLANを定義します。ただし、ここではIPアドレスなどの設定を行いません。
インターフェース名を「vlan21-hs1」とvlanのIDとインターフェイスの組み合わせがわかるようにネーミングすることをお勧めします。

---
3.ソフトウェアスイッチを定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234086/5b8e5c5a-7fd8-4c28-a0f1-e851c2491697.png)
ソフトウェアスイッチにてtagedポートのhs1のvlan21-hsとuntaggedポートのinternal3 internal4を
インターフェースメンバーに加えたvlan21というソフトウェアスイッチを定義します。
インターフェース名をvlan21としましたが、VLANidではなく具体的な用途の方が管理しやすいと思います。
管理機能やDHCPなどの必要な設定もここで行います。
ソフトウェアスイッチのインターフェース名を利用して、
ポリシー定義を行うとインターネットへの接続などか可能となります。

---
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234086/257c18e3-fa36-27ff-29e7-5fe6e771c34c.png)
手順通り行うと上記画面のような設定になります。これにより　一つのfortigate内でtaggedポートとuntaggedポートが共存でき、相互の通信が可能となります。　

---
##・なぜ共存できないという記事が多いのか
fortigateでVLANを定義する画面にIPアドレスなどのインターフェースの詳細を定義するところがあり、ここに詳細設定してしまうと、Fortigateの他のポートをuntaggedポートとして設定する余地はないので、そのような誤解があるのだろうと思います。
私も参考文献を見るまでは、そのように思っていました。
ただ、VLANインターフェースをソフトウェアスイッチのメンバーに加えられることと、VLAN定義が個別のインターフェース毎に行うことから、VLANインターフェース画面で詳細定義するかはユーザに委ねられたことであって、それをソフトウェアスイッチで取りまとめることで柔軟な設定が可能であることが解りました。
他のスイッチングHUBではVLANを定義してからタグ付きポート、タグなしポートを定義するわけですが、fortigateでのVLANインターフェースでは、タグ付きの通信をするインターフェイスを定義しているにすぎない事がわかります。

---
##・複雑な設定（より良い理解のため)
以下のようなVLAN構成を実施するとします。

|ポート|VLAN21|VLAN22|VLAN23|
|---:|:----:|:----:|:----:|
|1   |tagged|      |tagged|
|2   |tagged|tagged|      |
|3   |tagged|tagged|untagged|
|4   |      |untagged|    |

VLANのtagged unttagedの組み合わせが違う場合はハードウェアスイッチを使わずに個別にVLANインターフェースを定義して、ソフトウェアスイッチで取りまとめます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234086/7baf0999-d757-36fb-1c05-0e7c6bed1788.png)
設定すると上記のようになります。

---
##・応用設定 VLANのtagの付け替え
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234086/e56b5389-418c-a87e-d261-4212de5ffc6a.png)
ソフトウェアスイッチは柔軟にインターフェースを取り込めますので、異なるタグVLANを一つのスイッチに入れ込むことができます。
普通のL2スイッチだと定義できないタグの付け替えのて通信も定義できます。
この場合はポート２がタグ付き21番ポート３がタグ付き22番ポート４がタグ付き50番　ポート１がタグなしとなります。

---
##・参考文献
https://nwengblog.com/fortigate-sfsw-vlan/

タイトル：FortiGate のソフトウェアスイッチとタグ VLAN を検証する  
著者：松田一久様

---
##最後に
FortigateでtagVLANを利用しているが検証用にuntaggedポートを利用したくて確認しました。
Fortigateの上位機種ではポート数が多い機種があるので、センタースイッチングHUB機能を含めた提案などにも使えると思います。参考になれば幸いです。
ソフトウェアスイッチを使うことの是非についても意見がありましたらお寄せください。
【RSpec】Railsチュートリアル第6版　第4章

#はじめに
Railsチュートリアル第6版のテストをRSpecで書き直していく。

###目次
- [第3章](https://qiita.com/supyolo888/items/35081ead2cfafb40a995)
- 第4章（本記事）
- [第5章](https://qiita.com/supyolo888/items/42234ac2ed3919b14586)
- [第6章](https://qiita.com/supyolo888/items/bd10e64c77fe391cf203)
- [第7章](https://qiita.com/supyolo888/items/d2824ced26402b5f58d1)
- [第8章](https://qiita.com/supyolo888/items/508caaa40edf307093ed)
- [第9章](https://qiita.com/supyolo888/items/62e471b07a0c9a81575d)
- [第10章](https://qiita.com/supyolo888/items/a8695b20ec8082f85223)
- [第11章](https://qiita.com/supyolo888/items/5c81331e46f1d9d5ab3c)
- [第12章](https://qiita.com/supyolo888/items/fbb95671d39dfbf9df90)
- [第13章](https://qiita.com/supyolo888/items/c88b6acd4ff55750defc)
- [第14章](https://qiita.com/supyolo888/items/532390902bf3e0f5348e)

#Minitest

####StaticPagesコントローラーのテスト

```rb:test/controllers/static_pages_controller_test.rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  def setup
    @base_title = "Ruby on Rails Tutorial Sample App"
  end

  test "should get home" do
    static_pages_home_url
    assert_response :success
    assert_select "title", "Ruby on Rails Tutorial Sample App"
  end

  test "should get help" do
    static_pages_help_url
    assert_response :success
    assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
  end

  test "should get about" do
    static_pages_about_url
    assert_response :success
    assert_select "title", "About | Ruby on Rails Tutorial Sample App"
  end

end
```

#RSpec

####StaticPagesコントローラーのテスト

```rb:spec/requests/static_pages.rb
require 'rails_helper'

RSpec.describe "StaticPages", type: :request do

  let(:base_title) { "Ruby on Rails Tutorial Sample App" }

  describe "GET /home" do
    it "returns http success" do
      get "/home"
      expect(response).to have_http_status(:success)
      assert_select "title", "#{base_title}"
    end
  end

  describe "GET /help" do
    it "returns http success" do
      get "/help"
      expect(response).to have_http_status(:success)
      assert_select "title", "Help | #{base_title}"
    end
  end

  describe "GET /about" do
    it "returns http success" do
      get "/about"
      expect(response).to have_http_status(:success)
      assert_select "title", "About | #{base_title}"
    end
  end

end
```

`/home`で基本タイトルのみを表示するよう変更。
【Blender】ガラス瓶の質感を設定する方法


環境メモ
⭐️Mac OS Catalina
⭐️Blender2.94.4

ガラス瓶の質感を設定する方法

↓↓完成内容
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🎃Blender🎃<br>🎃ハロウィン🎃ドーム作ってみたよぉ🤩<br>ドーム部分のガラス瓶の質感を表現してみたよぉ✨<br>後ろの✨キラキラ🌲ツリー🌲の反射も写り込んでて、Blenderって凄いなぁ😍<br><br>↓↓ガラス瓶の質感の設定方法メモ📝<a href="https://t.co/5MM08GcFSD">https://t.co/5MM08GcFSD</a><a href="https://twitter.com/hashtag/blender?src=hash&amp;ref_src=twsrc%5Etfw">#blender</a> <a href="https://twitter.com/hashtag/%E3%83%8F%E3%83%AD%E3%82%A6%E3%82%A3%E3%83%BC%E3%83%B3?src=hash&amp;ref_src=twsrc%5Etfw">#ハロウィーン</a> <a href="https://t.co/kiIyWTEBTJ">pic.twitter.com/kiIyWTEBTJ</a></p>&mdash; non (@nonnonkapibara) <a href="https://twitter.com/nonnonkapibara/status/1454492107997999105?ref_src=twsrc%5Etfw">October 30, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 環境テクスチャを設定する

まず、環境テクスチャを設定する
（やり方は以下の記事を参考）
【Blender】Blender2.8で海の波を手軽に作る方法
https://qiita.com/nonkapibara/items/cb1f13c8ddb05bd95d03

# ガラス瓶のレンダリングを設定する
レンダリング をCyclesにする
![スクリーンショット 2021-10-31 1.34.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/98332742-ab49-8b1e-de53-19bcc1f6e38d.png)


# ガラス瓶のマテリアルを設定する
ガラス瓶のマテリアルの設定を以下の通り設定する


サーフェス:プリンシプルBSDF
メタリック：0
粗さ:0
IOR:1.3
伝播:1.0
アルファ:1.0
![スクリーンショット 2021-10-31 1.22.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/04533305-2e10-98fd-6aca-418d2f96cc52.png)


![スクリーンショット 2021-10-31 1.24.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/93ac1652-6df8-94fc-9fe6-5df452616f3f.png)