OmniAICreator/Qiita-1.07M huggingface dataset:
VBA エクセル　アイコンを表示　条件書式を追加

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/b8b12dda-c1f1-63f4-072a-a6fc399174b6.jpeg)
セルの範囲内で上位３３％が青、下位３３％以下が赤、３３％以上６７％以下が黄
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/e23081ed-1104-8d1f-c68a-6265ee37e334.jpeg)
全値の平均以下だったら文字色と塗りつぶし
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/ab33deb3-be7b-8841-4432-7350bb7de782.jpeg)


```vb
Sub アイコンセットの表示()
'矢印のアイコンセットを表示
 Range("B4:F15").FormatConditions.AddIconSetCondition
    With Range("B4:F15").FormatConditions(1)
        .IconSet = ActiveWorkbook.IconSets(xl3Arrows)
    End With
End Sub

Sub 強調表示()
'平均以下だったら文字色と塗りつぶし
 Range("B4:F15").FormatConditions.AddAboveAverage
 With Range("B4:F15").FormatConditions(2)
    .AboveBelow = xlBelowAverage
    .Interior.Color = RGB(255, 230, 180)
    .Font.Color = RGB(255, 0, 0)
 End With
End Sub

```
【Google Cloud Day'21】「Anthos GKE On-Prem と Google Cloud による運用システム基盤の提供」を視聴して

<table>
	<tr>
		<th>質問</th>
		<th>回答</th>
	</tr>
	<tr>
		<th>Anthos GKE On-Prem で一番良かった機能はなんですか？</th>
		<td>Bunddled LB です。MetalLB にさらに期待しております。</td>
	</tr>
	<tr>
		<th>なぜ、LBを 2つ使われているのですか。アプライアンスLBは何を利用されましたか。回答可能なら教えて下さい。</th>
		<td>使い分けているわけではなく、アプライアンスと Bunnddled LB (ソフトウェア)の二種類が選択可能です。アプライアンスLBについては当時選択可能でった F5 BIG-IP で PoC は実施しました</td>
	</tr>
	<tr>
		<th>インフラチームとアプリチームとのコミュニケーションで苦労した点はなんですか？</th>
		<td>コロナ禍もありそもそもコミュニケーション自体が難しかったですが、Meet を利用したコミュニケーションにもなれました。アプリとインフラでは要件を合わせるところが、リモートというところもありより難しかったところです。</td>
	</tr>
	<tr>
		<th>Private Service Connect は使用しないのでしょうか？</th>
		<td>]本構成図は少し前のものとなりまして、 先月GAされた PrivateServiceConnect については現在採用に向けて検証・移行を進めております。</td>
	</tr>
</table>


<table>
	<tr>
		<th>切り口</th>
		<th>内容</th>
	</tr>
	<tr>
		<th>運用システム</th>
		<td></td>
	</tr>
	<tr>
		<th>GKE導入の狙い</th>
		<td></td>
	</tr>
	<tr>
		<th>チーム体制</th>
		<td></td>
	</tr>
	<tr>
		<th>Anthos GKE On-Premとは</th>
		<td></td>
	</tr>
	<tr>
		<th>POCの評価</th>
		<td></td>
	</tr>
	<tr>
		<th>Anthos GKE On-Preが優れている点</th>
		<td>他社とのマルチクラウド化も円滑にできそう</td>
	</tr>
	<tr>
		<th>オンプレミスとの接続状況</th>
		<td></td>
	</tr>
	<tr>
		<th>Anthosに期待すること</th>
		<td></td>
	</tr>
</table>

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/7921f02c-e9d5-9860-2f43-09a5455b3c50.png)

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/011b2ede-4425-4563-fddc-d9a8149d0d53.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/1e8fff86-77f9-0d5d-4d96-104dfb45bd22.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/a22a83c4-b128-62c6-2cc0-54dc6280bd00.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/b64496a4-2d42-cc70-4173-a4e5d16a506f.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/c3e0881f-9896-d9a0-8651-cca1af93425a.png)
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/036e71dd-9aa6-9c21-7276-b937a686c61c.png)
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/a9577f7b-9be2-a9f4-2a3e-2bf69574b81c.png)
[UE4] 文字列からアセットを指定してロードする

# 背景
　DLC(ダウンロードコンテンツ)を考慮してコンテンツを作成するようなケースにおいての注意点として、DLCのコンテンツが独立している必要があります。ここで言う[独立している]というのは、アセットのリファレンスがDLCの中で完結している必要があるということです。

# 具体的な例（初期アプリケーションとDLCの関連性）
　例えば以下は良くあるケースですが、アプリケーションの初期状態とDLCのようにコンテンツが分かれている状態を図示したものです。デバイスはコンソール機でもモバイルデバイスでもよいですが、上の図は最初にアプリケーションをダウンロードした状態で、実行ファイルと初期状態で遊ぶのに必要なコンテンツがchunk0として存在しています。

　DLCのコンテンツは例えば、DLC1にキャラクターA、DLC2にキャラクターBの追加キャラクターがあるとします。テクスチャやマテリアルなどのキャラクターのアセット一式がそれぞれchunk1, chunk2として分けられていて、それぞれ.pakのようにアセットを1まとめにしてDLCとして構成しています。

　DLCを購入してデバイスにインストールした図が下の図です。DLCは購入後にインストールされ、.pakをマウント(アプリケーションの中からアセットを取り出すことができる状態)することで利用可能となります。例えば格闘ゲームの追加キャラクターであれば、DLCをダウンロードしてマウントして初めて利用できるようになるということです。
![2021-06-17_02h24_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/774e534a-cecd-2c44-3b1c-cef84bce6e6c.png)

　このようにまずDLCを利用する際には、それらが必ずしも存在しているとは限らないため、DLC1の中のアセットと本体コンテンツのアセットがリファレンスされる（参照することによって結びついてる）ことを避ける必要があります。同様にDLC1とDLC2のようなDLC同士でもリファレンスを持つことは避けなければなりません。もし、DLC1の中のアセットと本体コンテンツのアセットリファレンスを持っているような場合は、本体コンテンツの.pakに含まれる(DLC1のアセットが想定外の.pakに含まれる)ことになるので注意が必要です。

# アセットの呼び出しにおいて
　唐突ですが、この図は「アセットを文字列から参照してロードして対象のActorをスポーンする例」です。このように文字列からアセットを引っ張ってくることでリファレンスすることなく特定のアセットを持ってくることができます。これは例えば、本体コンテンツの中からDLCのアセットをロードしたいようなケースで利用できます。アセットを直接リファレンスすることは避けるべきなので、リファレンスを使用しない方法をこのようなケースでは利用してアクセスするようにしましょう。

![Path.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/5bf19522-f76e-ec92-89e7-f2d6e62d3d87.png)
dotnet replでDynamoDBのデータを検索する

.NETで利用できるREPL処理系はいくつかありますが、Hanselmanのブログで紹介されていたdotnet replがちょっと気になったので触ってみました。
dotnet replは [dotnet interactive](https://github.com/dotnet/interactive)をバックエンドにしたREPL環境で現時点ではバージョンが0.1.11とだいぶ初期のプロジェクトなためできないことも多いですが、コンソールだけで完結できるものとしては手軽に試せて結果表示などわかりやすくて良さげだなーという印象でした。

- GitHubのプロジェクトページ https://github.com/jonsequitur/dotnet-repl
- Nuget https://www.nuget.org/packages/dotnet-repl/

# dotnet replのインストールと実行
ターミナルで次のコマンドを実行するとグローバルにインストールされます。

```
dotnet tool install -g dotnet-repl
```

上記のコマンドを実行後`dotnet repl`とターミナルに入力すれば、C#のREPL環境が立ち上がります。C#以外にF#のREPL環境も実行できるようですが試していません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/ea8623b2-2fd0-d1af-5e8c-b4871adcadd4.png)
Nugetでパッケージを追加したい場合は、.NET Intaractiveの#rコマンドが使えます。
DynamoDB用の接続ライブラリをインストールする場合は、`#r "nuget:AWSSDK.DynamoDBv2`のように実行すればそのセッションが有効な間利用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/1348d9f5-795e-7e66-2dd7-88313930a6e5.png)

# DynamoDBにつないでみよう

今回はこんな感じのテーブルを検索してみます。

```
aws  dynamodb create-table `
  --table-name test `
  --attribute-definitions `
    AttributeName=Id,AttributeType=S `
  --key-schema `
    AttributeName=Id,KeyType=HASH `
  --provisioned-throughput `
    ReadCapacityUnits=1,WriteCapacityUnits=1
```

とりあえずドキュメントモデルでデータを出し入れするので、入れ物用のクラスを定義しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/643cabb9-fb7e-fdb8-4e20-b5a898e89f14.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/b993ca55-89bb-3105-d34c-bee268778f39.png)
複数行にまたがる入力をする場合はShift+Enterで行を継続できます。ただ、コピー＆ペーストで張り付ける場合にうまいこと行継続してくれないので現在点では複数行入力がちょっと大変ですね。あと、行末にセミコロンの省略はできないので付け忘れるとエラーになります。

コネクションを作った後にコンテキストを作成して、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/c945d817-a41d-cf64-74df-0938045dd824.png)

データを追加した後に、検索してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/d4f286a7-6ce8-abbd-797c-776b998ebd4e.png)
検索結果が表示されていますね。

# ノートブックを読み込む
.NET Intaractiveをベースに作られているので、あらかじめ作成してあるノートブックを読み込んで実行することもできます。
たとえば、こんなノートブックを作っておき

``` cs:hoge.dib
#!csharp

#r "nuget:AWSSDK.DynamoDBv2"

#!csharp

using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

#!csharp

var clientConfig = new AmazonDynamoDBConfig();
clientConfig.RegionEndpoint = RegionEndpoint.APNortheast1;
var client = new AmazonDynamoDBClient(clientConfig); 
var context = new DynamoDBContext(client);

#!csharp

[DynamoDBTable("test")] 
public class Test 
{ 
    [DynamoDBHashKey] 
    public string Id { get; set; }
    public string Name { get; set; }
}

#!csharp

var data = new Test 
{
  Id = "3",
  Name = "てすと"
};
await context.SaveAsync(data);
var data2 = await context.LoadAsync<Test>("1");
display(data2);
```

dotnet repl実行時に --notebook でファイルのパスを渡すと実行してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/d7e3e458-05eb-5a3e-35fa-ad206c884b7c.png)

# まとめ
.NETのREPL環境もいろいろ出てきたけれど、.NET Intaractiveをバックエンドに使える.net replは触ってみると面白い。
まぁ、VSCodeで.NET Intractiveを触る方が簡単ではあるけれど。
mallocについて調べてみた。

#背景
昔、エンジニアをしていた時に動的メモリの確保はページサイズ×ｎで行うものだと徹底して指導された。
ただ、それが何故なのかはよく分かっていなかったので、効率的な動的メモリの確保方法について調べてみた。<font color=red>答えは見つかっていないです。</font>
※本記事はあくまで自分の備忘録です。

#そもそもmallocって・・・
mallocの機能は、取得希望を出した領域が取れたか取れてないかを教えてくれるものですが（当然、アドレスくれます）、実際いくつ領域が確保できたかは教えてくれないんです。
一応、linuxではmalloc_usable_sizeという関数で動的確保済み領域のサイズを教えてくれるのですが、標準サポートでないとのことで信用できるかは不明というどうしようも無さがあります。

#判明点
mallocはライブラリであり、別にシステムコールじゃないよということ。
mallocは取得希望のサイズが少ない場合はbrkというシステムコールを発行し、多い場合にはmmapというシステムコールを発行している。
この閾値はMMAP_THRESHOLD(デフォルトは128 kB、変更も可能)

brkは任意のサイズ（データバス幅に従う）を指定可能
mmapは<font color=red>ページサイズの倍数を指定可能</font>

#調べてみて感じたところ
brkだとフラグメンテーションだらけになるから、ぼこぼこ呼んだり離したりしまくるもんじゃない。小さい領域なら初めから静的に確保すれば良い。（場当たり的にmallocで小さい領域とるなよ・・・）
mmapだと大きくとるので、その領域を利用者がきれいに管理しながら使う必要がある。
インメモリキャッシュ、インメモリデータベースとは？

#きっかけ
AWSクラウドプラクティショナー試験の対策をしていたら、AWS DAXというサービスが出てきた。
調べてみるとどうやらDynamoDBを速くするヤツらしく、公式ページいわく
>フルマネージド型高可用性インメモリキャッシュ

らしい。

フルマネージドなんとかは置いといて「インメモリキャッシュ」がわからない。
ElastiCacheの説明でも出てきた気がするけど全然覚えてない。
クラウドプラクティショナーのレベルだと絶対いらない気がするけど、調べてみることにする。

#キャッシュとは
一度使ったデータを保持しておき、再度必要になった時に素早く取り出せるようにしておくこと。
>インターネットブラウザで一度読み込んだ画像データなどをキャッシュファイルとして、ブラウザが利用するメモリに一時保存することで、表示を早くする方法として利用されている。画像データがメモリにあることで、インターネット上のWebサーバからデータが送信されるまで待つ必要がなくなる。

https://it-trend.jp/words/cache

#インメモリキャッシュ
キャッシュをメモリに保持するのがインメモリキャッシュ。
DAXはDynamoDBの手前で、メモリにキャッシュするサーバーを配置してEC2からのリクエストに素早く答えれる、ということらしい。

https://aws.amazon.com/jp/dynamodb/dax/


#インメモリデータベース
>インメモリデータベースとは、専用データベースの一種です。データをディスクや SSD に保存するデータベースではなく、データストレージ用のメモリに主に依存します。

https://aws.amazon.com/jp/nosql/in-memory/

前提として、主記憶装置（メモリ）は補助記憶装置（SSD,HDD）よりもデータの読み書きが早い。
しかし１GBあたりの価格がメモリの方が相当高い上に、通電していないと内部の情報が揮発する。
そのため、全てのデータをメモリに保存して作業は通常しない（と思う）。
それをやってしまったのが「インメモリ」の「データベース」、と理解した。
全データをメモリ上に保存するから、確かにSSDに保存するより相当早そう。
TagからEC2-IDを取得してSSMログインするときの覚書

（ssmでなんやかんやする時にecsのIDを知りたい）

tagを指定してfiltersで取得する覚書
`{}` 内は適宜置き換えてください。

```bash
export ENV={env}
export AWS_DEFAULT_REGION=ap-northeast-1

export BASION_ID=`aws ec2 describe-instances --filters "Name=tag:{tag-key},Values=$ENV" | jq -r .Reservations[0].Instances[0].InstanceId`
```

これ↓でssmでログインできるはず

```bash
aws ssm start-session --target $BASION_ID
```

sshしたい場合は↓を `~/.ssh/config` に追記

```ssh
host i-* mi-*
    ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
```

これ↓でsshでログインできるはず

```bash
ssh -i id_rsa ec2-user@$BASION_ID
```

※ 鍵の設定は必要
※ 22番ポートは開けなくてよい

---

RDSトンネルしたい場合

```bash
ssh -i id_rsa ec2-user@$BASION_ID -L {your-tunnel-port}:{your-rds-host}:{your-rds-port}
```
Autodesk Inventor API Hacking (Out processからの操作)

# 0. はじめに
[Freeradical](https://www.freeradical.jp)の中の人、[yamarah](https://qiita.com/yamarah)です。
APIをハックする際に、「AddInを使うのは手間なので、VBAでやるか・・・」という状況を打破する方法を見つけました。
なぜもっと早く気付かなかったんだ・・・

# 1. 実行中のInventorに外部から接続する
予めInventorを起動しておいて、後から接続して操作すれば、色々な邪魔くさいことは関係なくなるのです。
## 1.1 Console Applicationを使う
新規のConsole Applicationを作成して、コードを書いてみましょう。

```c#
using Inventor;
using System;

namespace InventorAccessor
{
    class Program
    {
        static void Main(string[] args)
        {
            var invApp = (Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Inventor.Application");
            Console.WriteLine($"Version {invApp.SoftwareVersion.DisplayName}");

            var document = invApp.ActiveEditDocument;
            if (document is null)
            {
                Console.WriteLine($"document is null.");
            }
            else
            {
                Console.WriteLine($"SelectSet.Count : {document.SelectSet.Count}");
            }

            Console.WriteLine("Hit any key.");
            _ = Console.ReadKey();
        }
    }
}
```

```:実行結果
Version 2020.4 (Build 244396000, 396)
SelectSet.Count : 1
Hit any key.
```
再コンパイルもし放題ですし、ブレークポインタを使ったデバッグも出来ます。デバッグを停止しても、Inventorごと終了することもありません。まさにVBAのルーズさが、今ここに!!
注意する点は、GetActiveObjectはなぜか.NetCoreにはないので、.NetFrameworkを使うということです。
それと、当然ですがInteropのdllを参照しておく必要があります。

## 1.2 C# Interactiveを使う
もっと簡便には、C# Interactiveを使う手もあります。
Visual Studioのメニューから、`表示`→`その他のウィンドウ`→`C# Interactive`を選択して、以下のように操作します。

```C#:C#&#x20;Interactive
Microsoft (R) Visual C# インタラクティブ コンパイラ バージョン 3.10.0-4.21269.26 ()
'CSharpInteractive.rsp' からコンテキストを読み込んでいます。
詳細については、「#help」と入力します。
> #r "Autodesk.Inventor.Interop"
> using Inventor;
> var app = (Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Inventor.Application");
> app.SoftwareVersion.DisplayVersion
"2020.4"
> 
```

このように、VBAのイミディエイトウィンドウのように操作することが出来ます。

# 99. 親の記事に戻る
[Autodesk Inventor API Hacking (概略)](https://qiita.com/yamarah/items/cee08eb8f2b7aecbda83)
VSCode Remote-Containers で　プロジェクトが開けなくなった

# 概要
windows10 上の VSCode で Remote-Containers を使って Dockerファイルを起動しようとして以下エラーが出て 嵌った時の備忘記録です。

```
 Dcoker retumed an erro.Make sure the Docker Daemon is running.
```



# 現象
Microsoftの[チュートリアル](https://docs.microsoft.com/ja-jp/learn/modules/use-docker-container-dev-env-vs-code/)に従って Githubからgit cloneし、途中何度もコンテナとWSLのローカルを行き来しつつ、一通りチュートリアルを終了した。<br>
その後、別のプロジェクトを試してみようと思って、WSL ディストリビューション(Ubuntu) をアプリから起動して　新規プロジェクトを作成した後、このプロジェクトを　Remote-Containers の `Open Folder in Container... ` で開こうとしすると上記エラーが出た。また、既存のチュートリアルで作成したものも同様に開けない状態になった。

# 解決編

WSLをアプリからではなく、VSCode上で Reomte-WSL を使って開く<br>
### Docker Desktop のドキュメントを試す ###

Docker Desktop のドキュメント[Develop with Docker and WSL 2](https://docs.docker.com/docker-for-windows/wsl/#develop-with-docker-and-wsl-2)には 
1. VSCodeにRemote-WSL エクステンションをインストールし
2. ターミナルに下のようにタイプするように書いてある。<br>

```
 wsl 
 code . 
```
私の場合、これがエラーになった。<br>
アプリのターミナルで `wsl`と入力するとエラーがでる。

```
Command 'wsl' not found, but can be installed with:
```
VSCodeのWindows PowerShell で入力しても、windowsのファイルシステムが表示されるだけで繋がらない。
### 解決 ###
VSCodeの　左下のRemote-Development アイコンをクリックして　コマンドパレットの ```New WSL Window using Distro ``` からUbuntu に入ることができた。<br>
※Ubuntu に wsl をインストールしていない。

その後、最初に起動していたVSCode　(WSLに接続していない）から Remote-Containers の `Open Folder in Container... ` でスムーズにプロジェクトを指定することができるようになった。

#補足
###環境設定

1. Windows にWSLをインストール　[Microsoft公式](https://docs.microsoft.com/en-us/windows/wsl/install-win10#manual-installation-steps)

2. WSLでデストリビューションをインストール
3. Docker Desktop をインストール　[Docker Desktop Document](https://docs.docker.com/docker-for-windows/install/)

4. Windows の Git と SSH の　設定
    ✅ Gitbash上で実行
5. WSL ディストリビューション上でGitの導入  [マイクロソフト公式](https://docs.microsoft.com/en-us/windows/wsl/tutorials/wsl-git)
   ✅ Git Credential Manage setup まで行なう　

5. VSCodeでRemote-Devlopmentを導入

### その他
Rimote- WSL で接続する時は　Docker Desktopを起動しておくこと

そもそも　面倒くさくしているのは Microsoft のチュートリアルでリポジトリをpullする時に Remote-WSL 上で行なう事にしていないことでは？
【Laravel】ログインやユーザー登録を行なった後のリダイレクト先を変更したい

ログインやユーザー登録をした後のリダイレクトを変更する方法を記載します。

#使用環境
Laravel 6.2

#前提
LaravelのAuth機能を使っていることを前提としています。

#1,デフォルトの動き
標準のAuth機能で、ログイン、ユーザー登録をすると以下のmethodにより、
`home.blade.php`が呼び出されると思います。

```php:Auth\LoginController.php
use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = RouteServiceProvider::HOME;
```

#2,遷移先を変える
以下のmethodを追記してあげます。

```php
public function redirectPath()
    {
        return '/URL'; #遷移させたいURL
    }
```

**注意**

`redirect（）`の記載などにすると怒られます。

以上です。
【Go】go getでうまくモジュールのバイナリファイルが落ちてこないときの解決手順

# go getでうまくモジュールのバイナリファイルが落ちてこないとき

解決した際の手順メモ

1. 適当な作業ディレクトリ切る

```
sola$ mkdir hogehoge
```

２. `go mod init example.com/hoge` コマンド実行


```
sola$ mkdir hogehoge
sola$ cd hogehoge/
hogehoge sola$ go mod init example.com/hoge
go: creating new go.mod: module example.com/hoge
```

３. ほしいパッケージを指定して`go get`実行

```
hogehoge sola$ go get github.com/golang/mock/mockgen@v1.4.3
```

4.落ちてきたか確認する
AWSにてインスタンスにssh で接続する方法

#背景

現在AWS について学習中です。
ssh 接続は頻繁に行うのでメモとして書きました。

#インスタンスへのssh接続

```
ssh -i キーペアファイル名 ec2-user@パブリックIPアドレス
```

ec2-user とはAmazon Linux 2 または Amazon Linux AMI の場合におけるデフォルトユーザー名です。
[目次] Prometheusで監視システムを作る with Docker

## Prometheus
### インストール手順
- **[Prometheus + AlertManager + Grafana with Docker](https://qiita.com/Esfahan/items/0feaedfd771f49ac7ee4)**
    - Prometheus, AlertManager, Grafanaのインストール手順
    - NodeExporterのインストールもここで行う

### 認証
Prometheus本体には認証機能はないので、別途用意する必要がある

- **[Apache2.4でLDAP認証用のリバースプロキシを作る with Docker](https://qiita.com/Esfahan/items/e3ce00411a23cbe3682f)**
    - LDAP認証の場合
- **[ApacheでOpenIDのリバースプロキシを作る with Docker](https://qiita.com/Esfahan/items/e44c9b866cb037034541)**
    - OpenID認証の場合

### 基礎知識
- **[PromQLを扱う前に知っておいたほうがよい超最低限の知識](https://qiita.com/Esfahan/items/2b8f8763b648d8bb3eb9)**
    - AlertManagerで監視ルールを作るために必要なPromQLの最低限の知識

## Exporters
### 各種Exporterのインストールと設定手順
- **[Node Exporter](https://qiita.com/Esfahan/items/01833c1592910fb11858)**
    - CPUとメモリとディスクを監視する。
- **[MySQL Exporter](https://qiita.com/Esfahan/items/ccd0b09a681da0b7cb85)**
- **[Postgres Exporter](https://qiita.com/Esfahan/items/08d0c1ff94710603bac9)**
- **[mtail](https://qiita.com/Esfahan/items/7fdef62746e0c7bf16c4)**
    - ログ監視のためのGoogle製のツール。自作ルールの作り方も説明する。
- **[blackbox_exporter](https://qiita.com/Esfahan/items/82dd496f1e150f089950)**
    - ポート監視をする。

### Exporterのポートを一本化する
- **[exporter_proxyを使って各exporterのポートを1つにまとめる](https://qiita.com/Esfahan/items/7f749344cd6f848242fb)**
    - 各exporterはそれぞれ利用するポートが違うので、複数ポートを開放するのが面倒な場合などの対策方法。

## Grafanaで可視化する
- **[GrafanaでPrometheusを可視化する](https://qiita.com/Esfahan/items/5bc0b804735602decda2)**

## その他
- **[DockerコンテナからホストOSのPostgresにアクセス全開設定にせずにログインする方法](https://qiita.com/Esfahan/items/47ade6398aa2f8a466b1)**
    - postgres-exporterコンテナからホストOSのpostgresに接続する例。
wslgでGUIを出そうとしたときに"Error: Can't open display: :0"と言われたときの対処法

備忘録的な
# 問題
```
Error: Can't open display: :0
```
ってエラーが出た。

#直し方
```
sudo rm -r /tmp/.X11-unix
ln -s /mnt/wslg/.X11-unix /tmp/.X11-unix
```
~~これ実行する。~~

~~ただ、再起動するとリセットされる。~~

もっといい方法があった。
下のやつを`/etc/tmpfiles.d/wslg.conf`に追加すればいい。
そうすれば再起動しても問題ない。
https://github.com/microsoft/wslg/issues/43#issuecomment-826039096

```
#  This file is part of the debianisation of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.

# See tmpfiles.d(5) for details

# Type Path           Mode UID  GID  Age Argument
L+     /tmp/.X11-unix -    -    -    -   /mnt/wslg/.X11-unix

```
出力系 meta,css,script

## require_css
headタグ内に出力される
= standard_header_includesに出力される

```
{% require_css %}
    <style>
        body {
            color: red;
        }
    </style>
{% end_require_css %}
```

## require_js

body閉じタグ上に出力される
= standard_footer_includesに出力される

position="footer"
body閉じタグ上に出力される
= standard_footer_includesに出力される

違いが不明。順番を指定するための属性だろうか。

```
{% require_js position="footer" %}
    <script>
        console.log("running");
    </script>
{% end_require_js %}
```

## require_head
headタグ内に出力される
= standard_header_includesに出力される

```
{% require_head %}
  <meta name="third-party-app-verification-id" content="123456">
  <link rel="prefetch" href="http://example.com/large-script.js">
{% end_require_head %}
```
Seaborn定量比較-折れ線グラフ

## 折れ線グラフとは

折れ線グラフは散布図の一種で、プロットされた点を直線でつないだものです。
通常は時間の経過を軸とします。

## 簡単な折れ線グラフ

折れ線グラフはrelplot(relational plot)で描きます。

```python
import matplotlib.pyplot as plt
import seaborn as sns

sns.relplot(x='year', y='value', data=test_data, kind='line')

plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/772a98a3-0190-c69e-845a-101c81894e7c.png)

## X値に対して複数Y値が存在ある場合

X値に対して複数Y値が存在ある場合、散布図は以下になります。

```python
sns.relplot(x='year', y='value', data=test_data, kind='scatter')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/44aba9a0-9041-98fb-ec71-ce34c65d4baf.png)

これを折れ線グラフに表現すると以下になります。

```python
sns.relplot(x='year', y='value', data=test_data, kind='line')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/35a5d408-34b6-3f36-8cac-02299d42a762.png)

実線は平均値を示し、範囲はデフォルトで信頼区間(confidence interval)を示します。（95%の確率でこの範囲に真値が存在すること）
範囲で標準偏差(standard deviation)を示したい場合はciで'sd'を指定します。

```python
sns.relplot(x='year', y='value', data=test_data, kind='line', ci='sd')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/53b88992-c442-ebe0-b929-68751054d5f6.png)

範囲を無くしたい場合は、ciでNoneを指定します。

## 常用オプション

* hue: 色で新しい次元を表示
* style: 点と線のスタイルで新しい次元を表示
* markers: 点の表示/非表示
* dashes: 破線で表示True、直線で表示False

```python
sns.relplot(x="year", y="value", 
            data=test_data, kind="line", 
            hue="origin", style="origin",
            markers=True, dashes=False)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/3fe6fb94-47ce-b5a5-5b8b-cdd18dc6204b.png)
クリックするだけ！ 10分で無料のBlogサイトを作る Nextjs+Sanity.io

# 事前準備
githubアカウント作成


# Sanityのプロジェクトを作る
ここへ行く
https://www.sanity.io/create?template=sanity-io%2Fsanity-template-nextjs-blog-comments

このURLに飛んでクリックするだけなので、この記事はこれで終わりですが、記事っぽくするためだけにスクリーンショットなどを貼り付けています。さようなら。

## Sanityアカウントを作成する
![スクリーンショット 2021-06-17 10.44.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/4e496617-bd9c-ea3a-9b2d-d8238f676132.png)

## Sanityのプロジェクトを作成する
![スクリーンショット 2021-06-17 10.46.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/d203bc42-cf27-a0f5-3831-364582b8fdd3.png)

## Deploy to Vercel
![スクリーンショット 2021-06-17 10.51.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/4c46a9ec-688a-8c82-d471-06838fe3f298.png)
Vercelのサイトが開いたと思います。

## Vercelとgithubの連携
![スクリーンショット 2021-06-17 10.52.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/a3a1a019-24d4-dcf4-7475-522a4e8ee05f.png)

## vercelプロジェクトの作成
そのままcontinue
エラーが出たら一旦vercelのアカウントにログインして、プロジェクト名が重複していたら消してください。
![スクリーンショット 2021-06-17 11.22.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/62f6e9f2-6d02-243e-0c12-714329e93fd4.png)


よくわからんがinstallしてcontinue
（Deploy時にSanityで必要な環境変数などを設定している模様。
![スクリーンショット 2021-06-17 11.10.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/84c8a509-430c-42b4-45c2-b810674e4f68.png)

## git リポジトリの連携
手動でcloneしていなくてもここでできます。
![スクリーンショット 2021-06-17 11.30.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/7165dc56-821c-0329-7b7b-28e3c755b788.png)

特に何も指定せずDeployを押す。
EnvironmentVariablesを開いてみると、先ほどインストールした時に環境変数を自動でセットしてくれたようです。

![スクリーンショット 2021-06-17 11.32.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/9b2ec4f3-7677-537e-8ced-a8d5e514990f.png)

デプロイ中...
![スクリーンショット 2021-06-17 11.35.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/d570f86c-e9d1-fa78-093c-6919f871f4bb.png)

デプロイが完了したら、祝ってくれます:tada:

# デプロイしたやつを見てみる
vercelのダッシュボードに何かできていると思うので、visitを押す
できたやつ↓
https://next-js-blog-with-comments-virid-beta.vercel.app/

# Sanityで内容を変更する
Sanityにログインして、STUDIOをクリック
![スクリーンショット 2021-06-17 11.42.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273334/68be4803-8ab8-d874-877e-f522828efa08.png)

マネジメント画面が出ると思うので、適当にいじってください。

ご指摘等あればコメントいただけると幸いです。

以上です。
Spring Bootの実行可能jarを解凍する方法

#背景
生成されるjarファイルを以下のように実行可能jarにしたら7zipで解凍できなくなってしまった。

```xml:pom.xml
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <executable>true</executable>
            </configuration>
        </plugin>
    </plugins>
</build>
```

jarコマンドならと思い、jar -xvf ○○.jarを行ってもなにも起こらず一瞬でコマンドが終了する始末。


#解決方法
上記で生成したjarをテキストエディタで開くと、以下のように先頭にbashスクリプトが記載されている。

```bash
#!/bin/bash
#
#    .   ____          _            __ _ _
#   /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
#  ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
#   \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
#    '  |____| .__|_| |_|_| |_\__, | / / / /
#   =========|_|==============|___/=/_/_/_/
#   :: Spring Boot Startup Script ::
#
               中略
exit 0
```
1行目からexit 0までの行を削除し、再度解凍したところ上手く解凍できた。

#参考
https://stackoverflow.com/questions/37783069/why-cant-i-extract-a-spring-boot-executable-jar
備忘録もしくは日記のようなもの


#現在の状況
IT系の企業に就職が決まった大学院生。
まずは「基本情報技術者試験」から資格取るといいよー、と言われているのでどんなものか調べているところ。
資格取ることがモチベーションになるわけではないので好きなジャンルを模索中。

#興味のあるもの
LINE bot　：自分にとって便利なツールを作ってみたい

競技プログラミング：問題解くの面白い

VR：どんな環境が必要なのか調べていきたい

#参考になるサイト
独立行政法人　情報処理推進機構　　　https://www.ipa.go.jp/index.html
セガ　情報技術　　https://techblog.sega.jp/entry/2021/06/15/100000
LinuxとUNIXの違い

本ページはLinuxとUNIXの違いと共通点についてです。
OSの系統図についても簡単にまとめてみました。

#違い
###Linux
・GUIでもCUIでも操作
　→コマンドを覚えていなくても操作できる
・無料、オープンソース
・必要なプログラムやソフトウェアをまとめた環境パッケージ、ディストリビューションの再配布が可能
・サーバーとして利用


###UNIX
・CUI(キャラクターユーザーインターフェース)：コマンドで操作
　→コマンドを覚える必要がある
・昔は無料だった、ライセンス契約になった
　→自由に開発
・パソコンよりも大きい規模、インターネットサーバーで利用
・今のインターネットを支えてきた



#共通点
・UNIX(系)OS
・コマンドで操作(も可能)
・サーバーとしての利用


#まとめ OS系統図
POSIX互換OS　ー　UNIX系OS　ー　UNIX　 ex.macOS
　　　　　　　　　　　　　　　Ｌ　Linux:penguin:　 ex.RedHat,CentOSなど
　　　　　　　　　　　　　　　　　 ＬVine Linux:grapes:
　　　　　　　　　　　　　　　　　 ＬDebian:lollipop:  　ex.Ubuntu
　　　　　　　　　　　　　　 　Ｌ　BSD:smiling_imp:　ex.FreeBSD 
　　　　　　　　　　　　　　 　Ｌ　Solaris:sunny: 


#感想
LinuxはUNIXのジェネリック的な印象を受けました。
無料にすると人が集まりますが、お金が絡むとややこしいことになるのはいつの時代でもそうですね…
/etc/network/interfacesに自動で無線につながるように設定する(on Debian 8,9,10)

今回は備忘録的な扱いの記事です．
Debian系PCで固定IPアドレスにする場合は，/etc/network/interfacesに必要事項を記載します．
有線なら，簡単なのですが，無線となるとconfファイルが必要になってきます．
その辺りも含めて記載していきます．

# まずは肝心の/etc/network/interfaces
記載事項は以下のとおりとなります．
説明としては
auto wlp24s0 だと，電源が入ったら，自動的にwlp424s0も立ち上がります．
allow-hotplugの場合は，抜き差しを検知してくれます．
すなわち有線の場合で説明すると，有線LANのケーブルを挿したら自動的にインターフェースが立ち上がります．

```
allow-hotplug wlp24s0
もしくは
auto wlp24s0
iface wlp24s0 inet dhcp #DHCPで自動的にIPアドレスを割り振ります．
    wpa-conf /opt/wpa_hogehoge.conf
    up ifconfig wlp24s0 mtu 1454
    dns-nameservers aaa.bbb.ccc.ddd
    dns-search xxx.yyy.zzz.jp
```

# ここで，肝心の/opt/wpa_hogehoge.confの中身

```
network = {
  ssid="ESSID"
  # ESSIDを記載
  psk="PASSWD"
  # 暗号化キー．要するにパスワード
  key_mgmt=WPA-PSK   
  # 暗号化キーの管理方式
  proto=WPA WPA2
  # 暗号化プロトコル
  pairwise=CCMP  TKIP  
  # ユニキャスト用暗号化方式
  group=CCMP TKIP
  # ブロードキャスト／マルチキャスト用の暗号化方式
}
```

このconfファイルは，パスワード付き接続をする場合の中身です．
皆さんの家のルータに接続する場合や，学校の無線LANなど，各個人の状況によって書き換える必要があります．
暗号化方式などは接続元に合わせる必要がありますので，その辺りは各個人で調べていただければなと思います．


参考サイト

https://www.atmarkit.co.jp/ait/articles/1601/22/news026.html
namespaceとusingの使い方。参照の範囲

php の namespace + useってC系の namespace+using と違うよねって話があって…
意識したことなかったけど確かにそうだなーと思っていろいろわかりやすそうな資料を探ったんだけども…
見つからないので自分なりにまとめてみた。

php use ≒  java import
パッケージ（名前空間で分離された） クラス等の処理をまとめる
故
利用(use/import)するときには、区切られた空間の中のパッケージ（クラス）を利用する意思を指定する必要がある

```php
namespace HOGEHOGE {
  class A {
    //... 処理
    public function hoge() { ... }
  }
  class B {
    // ... 処理
    public function hoge() { ... }
  }
}

use HOGEHOGE\A; // HOGEHOGEスペース（パッケージ）の中のAクラスを使うよ！
A::hoge(); // use宣言されてるので利用可
B::hoge(); // use宣言されていないので利用不可. この場合グローバルに定義されているBが呼ばれることになるのでNotFound.
```

C系
名前空間は`空間`として認知される
故
using 宣言された空間に定義されているクラスは利用可(空間内を走査して参照解決される)

```csharp
namespace HOGEHOGE {
  class A {
    //... 処理
    public function hoge() { ... }
  }
  class B {
    //... 処理
    public function hoge() { ... }
  }
}

using HOGEHOGE; // HOGEHOGEnamespaceを使うよ
A::hoge(); // HOGEHOGE namespace内にあるAクラス。読み込み可
B::hoge(); // HOGEHOGE namespace内にあるBクラス。読み込み可
```

もっとわかりやすくするためにいろんなリファレンスを参照してみようと思う
ド忘れしていたRubyの基礎5選①

どうも、三町哲平です。

最近LeetCodeでRubyをEasyランクから勉強し直しているのですが、easyでも思った以上に難しい内容でその都度Googleで調べていますのでその共有になります。

どんどんシリーズ化していこうと考えていますのでよろしくお願いします。

今回は、コチラの問題を解く際を想定
[(4) Two Sum - LeetCode](https://leetcode.com/problems/two-sum/)

解き方は、コチラを参照
[RubyでLeetCodeやってみる-TwoSum - Qiita](https://qiita.com/Wa_takumi/items/5c8283ca9d455b955742)

# 1. (.. と ...)
```ruby
(1 .. 10).each {|i| puts i}
=> 1 2 3 4 5 6 7 8 9 10
(1 ... 10).each {|i| puts i}
=> 1 2 3 4 5 6 7 8 9
```
引用及び参考記事:[RubyのRangeオブジェクトについて(ドット2つ、ドット3つの用法)](https://viblo.asia/p/ruby%E3%81%AErange%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%83%89%E3%83%83%E3%83%882%E3%81%A4%E3%83%89%E3%83%83%E3%83%883%E3%81%A4%E3%81%AE%E7%94%A8%E6%B3%95-jvEla6Lm5kw)

..の場合、10以下となり、...の場合、10未満となる。

# 2. require関数

自分で書いたコードを読み込む場合には、./から始めてパスを書きます。

```ruby
irb(main):004:0> require './aaa.rb'　# .rbは省略可
```
引用及び参考記事:[Rubyの外部ファイル読み込みとrequireの使い方を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン](https://techacademy.jp/magazine/21359)

irbコマンド実行時などに重宝します。

# 3. lengthメソッド

「文字列の長さ」や「 配列の長さ」を調べることが出来ます。

```ruby
data = [1,2,3,4,5,6,7,8,9]
data.length
# => 9
```
引用及び参考記事:[Rubyでlengthを使う方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン](https://techacademy.jp/magazine/28245)

# 4. return

* return は省略可
* returnがある場合はそこでの戻り値でメソッドは抜け
* returnがない場合は一番最後の戻り値が返される

```ruby
def aisatsu
  return 'こんにちは' # returnは省略可
end

puts aisatsu　#=> こんにちは
```
引用及び参考記事:[Rubyのreturnでメソッドの戻り値を返す方法【初心者向け】 | TechAcademyマガジン](https://techacademy.jp/magazine/19784)

# 5. storeメソッド

```ruby
#hashの初期化
h = {}
#keyがMike,valueが20を渡す
h.store("Mike",20)
```
引用及び参考記事:[Rubyのdeleteメソッドの使い方を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン](https://techacademy.jp/magazine/21220)

https://qiita.com/TeppeiMimachi/items/f3a9047dffdbc119df27
【Laravel】Time型のレコードをフォーマットして出力する時のエラーの回避対策

Time型のレコードを出力したい時に、少し手間取ったのでメモを残します。

#使用環境
Laravel 6.2
MySQL 8.0

#現象
Time型のレコードをbladeにformat（時：分）して出力をしたいが、エラーがでます。

```php:xxx.blade.php
{{ $model->start_time->format('hh:ii') }}
```

`Call to a member function format() on string`

エラーを調べると、modelにカラムを追加すると解消できるとありました。
公式では、「日付ミューテタ」とあります。

```php:model.php
protected $dates = [
        'start_time', 
    ];
```
ですが、また別のエラーが出力されました。

`Unexpected data found. Unexpected data found. Data missing`


所謂、取り出すデータと出力するフォーマットが異なっているエラーだと思います。

#結論
そもそも、Time型の値を日付ミューテタにするのは間違いです。
日付ミューテタと言っているくらいなので、Date型などの日付に絡んだレコード出ないといけません。

また、`Call to a member function format() on string`も
文字列をformatできないエラーです。
DBから直接、値を出力しているため文字列になります。

では、一番簡単に(時：分）で出力するためには？？

#対策
`substr`を使うと手っ取り早いです！
以下、PHP公式マニュアルです。
>substr(string $string, int $offset, int|null $length = null): string
文字列 string の、offset で指定された位置から length バイト分の文字列を返します。

なので、（時:分)で表すには、

```php:xxx.blade.php
{{ substr($model->start_time,0,5) }}
```
これで出力できます。

#参考
https://teratail.com/questions/192540
https://qiita.com/shimotaroo/items/acd22877a09fb13827fb
https://readouble.com/laravel/6.x/ja/eloquent-mutators.html
https://www.php.net/manual/ja/function.substr.php
【Ruby】ちゃんとインスタンス変数を使おう

基本的すぎる内容ですが、インスタンス変数を使わないことでコードが冗長化していることがあったので、戒めとして書きます。自分用の学習メモです。

# インスタンス変数が活用できていない...

```rb:
require "time"
require 'csv'

class User
  attr_reader :name, :birthday

  def initialize(name:, birthday:)
    @name = name
    @birthday = birthday
  end
  
  def self.calc_age(now, birthday)
    ((now - birthday) / 365).to_i
  end
end

class Product
  attr_reader :name, :quantity, :price

  def initialize(name:, quantity:, price:)
    @name = name
    @quantity = quantity
    @price = price
  end
end

CSV.foreach("sales.csv", headers: true) do |row|
  user = User.new(name: row[0], birthday: row[1])
  now = Time.now
  birthday = Time.parse(user.birthday)
  age = User.calc_age(now, birthday) 
  product = Product.new(name: row[2], quantity: row[3].to_i, price: row[4].to_i)

  puts "#{user.name}(#{age})は#{product.name}を#{ product.quantity * product.price}円お買い上げ。"
end
```

```csv:sales.csv
名前,誕生日,買上品目,数量,単価
つんく♂,1968/10/29,チロルチョコ,13,10
はたけ,1968/8/17,雪見だいふく,3,100
まこと,1968/12/31,チョコモナカ,3,140
たいせい,1969/11/29,フルーツコッペ,4,300
```

改善点

- 変数nowを定義する必要はない
- birthdayはプロパティとして持っているのでそのままインスタンス変数で使えば良い
- quantityとpriceはプロパティとして持っているのでそのままインスタンス変数で使えば良い
    - 今回はさらに簡潔にするためにメソッドに切り出す

- その他
    - 年齢算出処理ではインスタンスに含まれるデータを参照しているのでクラスメソッドではなくインスタンスメソッドで定義する

# インスタンス変数を活用する

```rb:
require "time"
require 'date'
require 'csv'

class User
  attr_reader :name, :birthday
  
  def initialize(name:, birthday:)
    @name = name
    @birthday = birthday
  end

  def age
    ((Date.today - @birthday) / 365).to_i
  end
end

class Product
  attr_reader :name, :quantity, :price

  def initialize(name:, quantity:, price:)
    @name = name
    @quantity = quantity
    @price = price
  end

  def sum
    @quantity * @price
  end
end

CSV.foreach("sales.csv", headers: true) do |row|
  user = User.new(name: row[0], birthday: Date.parse(row[1]))
  product = Product.new(name: row[2], quantity: row[3].to_i, price: row[4].to_i)

  puts "#{user.name}(#{user.age})は#{product.name}を#{product.sum}円お買い上げ。"
end
```

プロパティとして持っているものはインスタンス変数でコードが簡略化できないか疑うこと。
当たり前のことでも実際にコードを書くとできていなかったりするので、適宜メモを残していこうと思います。
If文（引数が０なら偽。引数が１なら真）

```java
package If;

public class If {

	public static void main(String[] args) {
		
		int num1 = 0;
	    int num2 = 1;
	    if (num1 < 5 ||  num2 < 20 ) {
        System.out.println("引数が０なら偽。");
    } {
        System.out.println("引数が１なら真");
     }
	}

}
```

①int numで数値を表示
②if文で条件を追加
③表示

引数…（）内の数値や文字
EC2の自動開始と自動停止 備忘録

毎日同じインスタンス使うのに、毎回立ち上げと停止するのめんどい&停止するの忘れるのでcloudwatch使って自動化した備忘録。
(CLI設定するのもちょっと今はめんどくさい)

# 使用するサービス
- IAM
- CloudWatch
- AWS Systems Manager

# やり方
## サービスロールの作成
まずはIAMからサービスロールを作成します。
IAMのコンソール > ロール > ロール作成
以下のような画面が出たら、サービス選択から `Systems Manager`を選択。
ユースケースはSystems ManagerとSystems Manager -Inventory and Maintenance Windowsがありますが、今回はSystems Manager を選択します。
![スクリーンショット 2021-06-17 10.25.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505734/2b8753b0-4e22-f973-b559-72a4830dc0b4.png)

アクセス権限ポリシーは`AmazonSSMAutomationRole`を選択します。
![スクリーンショット 2021-06-17 10.31.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505734/350cc02c-58f0-83a7-cbec-975d00e2cef1.png)

確認画面まできたらロール名等を設定します。ロール名はなんでも良いですが、　今回は`ssm-automation-role`にしました。

追加できたら、作成したロールの信頼関係を編集します。
大体は既に設定されていますが、PrincipalのService部分だけ変更しておきます。
![スクリーンショット 2021-06-17 10.39.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505734/10e7c3e0-7939-c6c7-835b-b0dd5151e6a9.png)

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com" //ssm → evnet
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

## CloudWatch Eventの設定(自動起動)
次にCloudWatch Eventを作成します。
CloudWatch > イベント > ルール > ルールの作成

今回、イベントソースはCron式で設定します。
画像は日本時間で平日の午前10時に自動起動させたい場合のcron式です。**イギリス標準時間で表示されるので、日本時間から９時間引く必要があります。**
Cron式：`0 1 ? * 2-6 *`

ターゲットはSSM Automationを選択し、AWS-StartEC2Instanceを選択。
インスタンスIdとロールをそれぞれ入力し、次の画面で名前を決めたら自動起動の設定は完了です。

![スクリーンショット 2021-06-17 10.48.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505734/75e189b0-8dde-ce14-6f0d-017839413162.png)

## CloudWatch Eventの設定(自動停止)
自動停止も基本的には一緒です。違う部分はcron式とドキュメントくらい。

日本時間の平日19時に停止させたいので、Cron式は `0 10 ? * 2-6 *`にします。
またターゲットのドキュメントは`AWS-StopEC2Instance`にします。

![スクリーンショット 2021-06-17 10.54.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505734/37fbfb67-c58c-0ee0-1729-0ec958311e9c.png)

これで自動停止も完了です。
Gravioでお茶出しくん（改）

めっきりオフィスには行かなくなったのですが、そんな中、妄想で始まった「[Gravioでお茶出しくん][Gravio-Tea]」。よくよく考えると、どの部屋かってのと同時に、お茶いくつ持ってくの？ってのもわからないと、頼まれた方も困りますよね。もちろん、スケジューラーとか見ればわかるかもしれませんが、予定と違う人数が来てることなんて日常茶飯事。一度持っていったのに足りないとか、逆に面倒になるなら電話で～ってなりますよね。
そこで、ボタンを押す回数で、お茶をいくつ持ってきて～ってわかるようにしてみました。

# TL;DR
* ボタンをクリックした回数だけお茶の数として扱う
* ボタンをダブルクリックするまでのクリックの数を数える
* クリックした回数はSensor Data DBでボタンレイヤーのデータを検索し、それをStatisticsでカウントする
* 回数はStatisticsのあと `cv.Statistics.Count` で参照できるので、これをAWS Polly Speechに渡して喋らせる

# 使用環境
* Gravio HubKit v4.3.0-6722
* Gravio Studio v4.3.4162.0
* Gravio ワイヤレススイッチ
* Gravio Hub
* Bluetoothスピーカー
* Amazon Polly

# 事前準備
* 「[Gravioでお茶出しくん][Gravio-Tea]」 を参考に、ボタンを押すと「XXにコーヒー持ってきてねー」的なことは言えるようにしておく

# 手順
## アクションにコンポーネントを追加する
「[Gravioでお茶出しくん][Gravio-Tea]」 で使っていたアクションに、クリック数を取得するためのSensor Data DBとStatisticsの２つのコンポーネントをAWS Polly Speechの前に追加します。
アクションは最後に追加されるので、ドラッグしてぐいっと前に持ってきてね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/3c8745f0-43df-1b86-9713-af3125c0374d.png)

## Sensor Data DBコンポーネントの設定
Sensor Data DBコンポーネントでクリックデータを取得できるように指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/7dd9075e-5cd5-2e55-4af0-217a6accdf19.png)
エリア、レイヤーは対象ボタンのものを選びます。
あまり前のものを拾っても仕方ないので、ダブルクリックまでの20秒くらいのものを拾ってきましょう。「From Previous」には `20`を入力、「タイムスケール」では `秒`を選びます。
これだけだとだブルクリックのものも拾っちゃいますので、「フィルター式」を指定します。シングルクリックは `1` になりますので、`Value.Data == 1`と指定しましょう。

## Statisticsコンポーネントの設定
Sensor Data DBのレコードを使って統計情報を計算するだけですので特別なことは何もありません。Sensor Data DBからのデータを使うので「値式」は `cv.Payload.Data`としておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/854739cf-9444-a90a-0d5a-6ae0acd11615.png)

## AWS Polly Speechの設定
メッセージに個数を入れましょう。Pre Mappingsの式をつぎのようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/62fec112-75da-57cf-7563-4473cb0ea0af.png)

```cp.Text
cp.Text = tv.AreaName + "にコーヒーを" + cv.Statistics.Count + "つお願いします"
```
はい。10個以上になると「つ」はおかしいですが、1桁なら問題なく自然ですね。気になるなら「杯」や「個」を使ってみてください。ここは好みですね。
ちなみに、レコードがない場合はSensor Data DBで終わりますのでAWS Polly Speechは実行されません。

## トリガーの変更
最後にトリガーの変更です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/504786ef-1ba6-33f4-165b-20ac7802fbfd.png)
「[Gravioでお茶出しくん][Gravio-Tea]」ではシングルクリックでメッセージが流れましたが、今度はシングルクリックではなくダブルクリックになりますので、条件を変更します。

# 試してみる
ボタンを数回クリックしたあとにダブルクリックしてみてください。「会議室にコーヒーを３つお願いします」みたいな感じで個数も一緒にお願いされましたか？
ただ、これ、慌ててボタンを押すとシングルクリックがダブルクリックになったり、結構運用は大変そうです。ダブルスイッチの左右のボタンを使い分けるとか、最後はモーションセンサーを付けた札を倒すとか、アイデア次第でいろいろできそうですね。

# 参考
* [Gravioでお茶出しくん][Gravio-Tea]
* [Gravio][]
* [AWS Polly Speechコンポーネント][Gravio-AWSPollySpeech]
* [Sensor Data DBコンポーネント][Gravio-SensorDataDB]
* [Statisticsコンポーネント][Gravio-Statistics]
* [Amazon Polly][AmazonPolly]

[AmazonPolly]:https://aws.amazon.com/jp/polly/
[Gravio-Tea]:https://qiita.com/zrock/items/2cc5e38289500acde574
[Gravio]:https://www.gravio.com/jp
[Gravio-AWSPollySpeech]:https://doc.gravio.com/manuals/gravio4/1/ja/topic/amazonpollyspeech-action-component
[Gravio-SensorDataDB]:ttps://doc.gravio.com/manuals/gravio4/1/ja/topic/sensordb-recent
[Gravio-Statistics]:https://doc.gravio.com/manuals/gravio4/1/ja/topic/statistics
springboot repositoryにupdate文を作成するサンプル

package test.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import test.TestEntity;

@Repository
public interface TestEntityRepository extends JpaRepository<TestEntity, int>{

	@Transactional
	@Modifying
	@Query("update TestEntityset UPDATE_DT=:UPDATE_DT UPDATE_ID=:UPDATE_ID where ID=:ID")
	int updateBase(@Param("UPDATE_DT")LocalDateTime UPDATE_D,@Param("UPDATE_ID")String UPDATE_ID,@Param("ID")int ID);

}
ids for this class must be manually assigned before calling save() spring boot

1、sqlserver identityを自動インクリメント設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/67e08170-6955-7a17-361b-1c575ec3d96f.png)

2、entityファイルのIDに「@GeneratedValue(strategy=GenerationType.IDENTITY)」宣言

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)//追加
	@Column(name="ID", nullable=false, columnDefinition="DECIMAL(28,0)")
	private BigDecimal id;
【Google Cloud Day'21】「Fastly セキュリティ ソリューションのご紹介」を視聴して

概要：昨年の Signal Sciences の買収により、Signal Sciences の強力な Web アプリケーションと API のセキュリティソ リューションが加わりました。開発者の働き方に合わせて設計された強固なセキュリティ ポートフォリオにより、エッジでのイノベーションを加速させ、開発者、運用担当者、セキュリティ担当者間のサイロ化を解消して開発サイクルを短縮し、Web サイトと Web アプリケーションを同時に保護します。

<table>
	<tr>
		<th>切り口</th>
		<th>内容</th>
	</tr>
	<tr>
		<th>CDNとVCL</th>
		<td></td>
	</tr>
	<tr>
		<th>Fastlyエッジクラウドプラットフォーム</th>
		<td>CDNのイメージが強いが、いろんな製品を展開している。GoolgeCloudともテクノロジーパートナーなので、どのように実装するかを対応できる。</td>
	</tr>
	<tr>
		<th>SignalScienceについて</th>
		<td>WAFがメイン。Web Application Firewallとは、ウェブアプリケーションの脆弱性を悪用した攻撃からウェブアプリケーションを保護するセキュリティ対策の一つ。WAFを導入するウェブサイト運営者は、検出パターンを設定することで、ウェブサイトとウェブサイト利用者との間の通信の内容を機械的に検査する。</td>
	</tr>
	<tr>
		<th>何をできるか。</th>
		<td>Webサーバーにインストールして動かす。攻撃を検知する。連携すると攻撃を受けた状況の可視化ができる。GCPに構築したアプリにこのツールをインストールすることで守ることができる。</td>
	</tr>
	<tr>
		<th>SignalSciencesのアプローチ</th>
		<td>WAFの課題は誤検知を低くすることだったが、SignalSciencesではそのチューニングに力を入れている。SignalSciences自身のロジックで危険性を検知している。</td>
	</tr>
</table>


![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/f0423b13-f103-ea23-076a-94b6bfbe75e9.png)

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/a84cc732-9724-2306-0822-30974f4e83ba.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/8052d4aa-bb98-9b3e-1f11-73ce63fe7b56.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/2cba71d3-f047-4b51-9487-ee68061c3608.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/5a5a1867-b75f-79c0-3abf-8c5aa31d5ebc.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/12ab2f07-50f9-4bc6-fb5a-c9655f27d549.png)
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/1583d423-5690-2af6-f0ee-698502dace48.png)
FibaseとTableauを連携させる＆大きなテーブルでVIZを作る際のViewを使った小技

FirebaseをTableauで可視化するには
- Fiebaseを有料プランでやる必要がある
- 出力はBigQueryになるので、Firebase→BigQueryでローデータを吐き出す
- BigQueryに対してTableauで可視化する！

となります。
FirebaseをBigQueryに出力する方法は、[他の記事](https://support.google.com/firebase/answer/6318765?hl=ja#zippy=%2C%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AE%E5%86%85%E5%AE%B9) におまかせします。


#TableauとFirebase（BigQuery）の連携
Tableauを立ち上げ、スタートページから　サーバーへ→Google BigQueryを選択して接続します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/b47a27fc-d862-2599-4df3-2bea430b1a2e.png)

BigQueryのブラウザ認証が走るので、対象となるアカウントで認証して、アクセス許可をしてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/7617a61f-bcb3-530a-6956-cd6a85fe4388.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/5e2f2cba-2789-3206-9643-1b384d605604.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/39724f97-f04b-e9dc-bf8f-856c11b38eb9.png)

こちらのメッセージが出ればOK。ブラウザを閉じて、Tableauへ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/73913d03-aedd-e19f-6445-74d65940d604.png)

対象となるFirebaseのテーブルをドラッグ＆ドロップします
※ここではまだエラーにはならない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/69a5ff44-e93a-0b70-8466-3dde78a96bbd.png)

「今すぐ更新」とかをするとエラーが出ます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/2932046d-ffc4-90f3-ac66-9ac45a385a6b.png)

```error.txt
Unexpected Error
Google BigQuery サービスがクエリをコンパイルできませんでした。
エラー コード: 015CFBE6
Cannot access field key on a value with type ARRAY<STRUCT<key STRING, value STRUCT<string_value STRING, int_value INT64, float_value FLOAT64, ...>>> at [38:27]
```

このようなエラーが出て、閲覧ができません。
これは、Firebaseのカラムの中に、構造体が入っているので、そちらをUNNESTしてフラット化して上げる必要があります。

``` firebase_unnest.sql
SELECT
  event_date,
  event_timestamp,
  event_name,
  event_param.key AS event_param_key,
  event_param.value.string_value AS event_param_string_value,
  event_param.value.int_value AS event_param_int_value,
  user_id,
  user_pseudo_id
FROM
  `(Dataset).firebase.events`,
  UNNEST(event_params) AS event_param
LIMIT
  1000
```
もしくは

``` firebase_unnest2.sql
SELECT
　　　event_date,
　　　event_name,
　　　(SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location") AS page_location
  　FROM 
　　`(Dataset).firebase.events`
```

このどちらかでFlat化するのが良さそう
下のSQLで Where区をいれないと、複数の値があると怒られます
``` sql
SELECT value.string_value FROM UNNEST(event_params) AS property
``

上記の結果を、Viewに保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/ca0a73c1-0255-b918-bd95-717391352e4a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/00e75a65-8d2d-a39d-8ef5-7d0791386051.png)


これでVIZをつくります。

VIEWの中にLIMIT句をいれていますが、データソースが非常に大きいときは、VIEWの中にLIMIT句を入れ、VIZを作り
本番運用の際には、VIEWの中からLIMIT句をはずすとVIZを作るのにストレスがなくていいです！
（自動更新を止めたりする必要がない）
springboot ajax通信サンプル

.js
 //設定登録
    function saveSetting(){

	    // 設定フォーム要素を取得
	    var $form = $("#setting_form");
	    
	    var data = JSON.stringify( $form.serializeArray() );
	    
	    $.ajax({
	        type: "POST",
	        headers: { 
		        'Accept': 'application/json',
		        'Content-Type': 'application/json' 
		    },
	        url: "./saveSetting",
	        data: data,
	        dataType: "json"
	      }).done(function(data){
  
		   console.log("data:",data);
		     	
	      }).fail(function(XMLHttpRequest, status, e){
	    	  console.log(XMLHttpRequest);
	    	  console.log(status);
	    	  console.log(e);
	      }).always(function(){
	      
	    });
    }

.controller

	/*
	 * 設定タブ登録(AJAX)
	 * 
	 * @param reqMap HashMap jsonデータ
	 * @return 　
	 */
	@ResponseBody
	@RequestMapping(value="/saveSetting", method=RequestMethod.POST,consumes="application/json")
	public Object saveSetting(@RequestBody List<HashMap<String,String>> reqMap ) {
		
		Object result = null;
                 result = service.getResult(reqMap.get("testName1"),reqMap.get("testName2"));


		return result;
	}
ホームページのリンク先を全部取り出したい

時々HTMLのリンク先を取り出したくなるので、その方法を忘れないようにメモとして残します。なおOSはUbuntu20.04で、使用しているブラウザはGoogle-Chromeです。

#BeautifulSoupを使う

リンク先を取り出す手段で、真っ先に思いつくのがBeautifulSoupを使う方法です。

```bash:BeautifulSoupのインストール
pip3 install bs4
```

```python:Python3+BeautifulSoupのサンプル
import requests
from bs4 import BeautifulSoup
html = requests.get('https://qiita.com')
soup = BeautifulSoup(html.content,'html.parser')
for link in soup.find_all('a'):
    print(link.get('href'))
```

しかし、この方法では静的コンテンツの場合はちゃんとリンク先は出るのですが、動的コンテンツの場合は取り出すことができません。

#Seleniumを使う

調べたいページが動的コンテンツの場合にはSeleniumを使い対応します。Seleniumでページを読み込んだ5秒後にリンク先を取り出しています。なおSeleniumの裏でChromeが動いています（画面の表示をしないHeadlessモードで動いている）のでChromeが入っていることが前提です。

```bash:Seleniumのインストール
apt install python3-selenium
```

```python:Python3+Seleniumのサンプル
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument('--headless')
driver = webdriver.Chrome('/usr/bin/chromedriver',options=options)
driver.get('https://qiita.com')
time.sleep(5)
tags = driver.find_elements_by_tag_name('a')
for link in tags:
    print(link.get_attribute('href'))
```

#Javascriptを使う

でもやっぱり動的コンテンツの場合は、ブラウザ操作中の好きなタイミングでリンク先を調べたくなります。その場合はブラウザの開発モードのconsoleで下のJavascriptを実行します。

```javascript:javascriptのサンプル
for(let link of document.getElementsByTagName("a")){ console.log(link.href) }
```

このやり方はページ毎に自分で操作をしなければいけません。

#おわりに

多数のページのリンク先を集めるならSeleniumで、１ページだけでいいならJavascriptで、と使い分けが必要ですね。後日もっと良い方法を調べてみます。
Flutter×FirebaseのCRUD処理まとめ

M1 MacBook、Android Studio、Flutter 2.0
2021年1月末からプログラミング学習始めた初心者です。自分用メモ。

1、FlutterとFirebaseをリンク
https://firebase.google.com/docs/flutter/setup

2、最初のおまじない

```
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}
```
3、以下、CRUD処理
・登録（Create）

```
var collection = FirebaseFirestore.instance.collection("sauna");
    collection.add({
   'title': title,
      'isDone': false,
      'createdTime': Timestamp.now()
    });
```
読取（Read）

```
StreamBuilder<QuerySnapshot>(
      stream: saunas.snapshots(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return ListView.builder(
            itemBuilder: (BuildContext context, int index){
              if(snapshot.data!.docs[index]['isDone']) return Container();
              return CheckboxListTile(
                controlAffinity: ListTileControlAffinity.leading,
                title: Text(snapshot.data!.docs[index]['title']),
                value: snapshot.data!.docs[index]['isDone'],
```
更新（Update）

```
onPressed: ()async{
       await snapshot.data!.docs[index].reference.update({
           'title': editTitleController.text,
           'updatedTime': Timestamp.now(),
            });
            Navigator.pop(context);
            },
            child: const Text('編集'),
```
削除（Delete）

```
onPressed: ()async{
       await snapshot.data!.docs[index].reference.delete();
            Navigator.pop(context);
            },
            child: Text('削除実行'),
            ),
```
[windows]よく使う単語をクリップボードに入れるコマンド作成

# よく使う単語をコマンドでクリップボードに入れたい！
webサービスのログインとかで自分のメアドとかよく使いますよね。
辞書登録しても良いのですが、半角/全角の切り替えも面倒くさいし、変換候補から選ぶのもちょっとだけ面倒。そんな時に使える手段です！

## コマンド

以下のbatを使います。

``` bat
set /P ="よく使う単語"< nul | clip
```

## 環境変数


batファイルの場所を環境変数「path」に登録しておきましょう。
「環境変数って？」という方は[こちら](https://qiita.com/jeyei/items/2c385e4e0488a5fa2591)。

## ファイルを指定して実行

windowsキー + rを押すとこのウィンドウが出てきます。
ここに、bat名を入れて実行しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504218/951ffb41-0412-a18f-66ef-6bfaba3c6405.png)


## コピー出来た！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504218/efd8eb1d-35ce-0065-00c3-163a444e0f79.png)


コピーできました。

なんか便利でかっこよいのでぜひ使ってみてください。
ajaxでフォームごとをpostする方法

	    // フォーム要素を取得
	    var $form = $("#setting_form");//フォームID
	    
	    var data = JSON.stringify( $form.serializeArray() );//フォーム内容を配列にし、json型に変換



controllerで取得した内容：
[{name="testname",value="testvalue"}]
C# 7.0からの引数nullチェック

# C# 7.0からの引数nullチェック

`破棄` と `null合体演算子` を使ってワンライナーnullチェックが行えます

```Csharp
void testMethod(object arg)
{
    _ = arg ?? throw new ArgumentNullException();
    // 以下処理
    :
}
```


https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/null-coalescing-operator
https://docs.microsoft.com/ja-jp/dotnet/csharp/fundamentals/functional/discards