OmniAICreator/Qiita-1.07M huggingface dataset:
ランダムにGroupKFoldする

[GroupKFold](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GroupKFold.html)には、他のKFold系と違って`random_state`を指定する引数がないが、アンサンブルなどでランダムにGroupKFoldしたいことがある。

```python:環境
import numpy as np
from sklearn.model_selection import GroupKFold, KFold
```

# NG例：シャッフルして渡す
さっそくダメな例から。

```python:NG例
gkf = GroupKFold(n_splits=3)
group = np.array([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6])
for i in range(3):
    print(i, "回目", group)
    for t,v in gkf.split(group,group, group):
        print(set(group[t]), set(group[v])) 
    np.random.shuffle(group)
```

>0 回目 [1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6]
{1, 2, 4, 5} {3, 6}
{1, 3, 4, 6} {2, 5}
{2, 3, 5, 6} {1, 4}
1 回目 [5 4 3 4 4 6 1 6 1 3 6 5 4 2 1 6 5 2 3 3 2 2 5 1]
{1, 2, 4, 5} {3, 6}
{1, 3, 4, 6} {2, 5}
{2, 3, 5, 6} {1, 4}
2 回目 [1 2 6 3 1 2 3 1 6 3 1 2 4 3 6 5 5 4 5 4 4 2 5 6]
{1, 2, 4, 5} {3, 6}
{1, 3, 4, 6} {2, 5}
{2, 3, 5, 6} {1, 4}

渡すラベルの順序が異なるのに、全部同じ結果が返ってきた。
ソース読んでないが、Foldサイズをなるべく均等に分けようとするので、各ラベルの個数を数えるときに内部でソートされるのだと思われる。
今回はどのラベルも同じサイズにもかかわらず。

# OK例1：ランダムにマッピングして渡す
GroupKFoldに渡すときだけ、別の値にマッピングして渡すようにする。
ループごとで毎回そのマッピングを変えることで、毎回異なる結果を得る。

```python:OK例
gkf = GroupKFold(n_splits=3)
group = np.array([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6])
mapping = np.arange(group.max()+1)
for i in range(3):
    print(i, "回目", mapping[group])
    for t,v in gkf.split(group,group, mapping[group]):
        print(set(group[t]), set(group[v])) 
    np.random.shuffle(mapping)
```

>0 回目 [1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6]
{1, 2, 4, 5} {3, 6}
{1, 3, 4, 6} {2, 5}
{2, 3, 5, 6} {1, 4}
1 回目 [0 0 0 0 4 4 4 4 3 3 3 3 6 6 6 6 1 1 1 1 5 5 5 5]
{1, 2, 5, 6} {3, 4}
{1, 2, 3, 4} {5, 6}
{3, 4, 5, 6} {1, 2}
2 回目 [1 1 1 1 3 3 3 3 4 4 4 4 2 2 2 2 6 6 6 6 5 5 5 5]
{1, 3, 4, 6} {2, 5}
{1, 2, 3, 5} {4, 6}
{2, 4, 5, 6} {1, 3}

毎回違う結果が返ってきた。
これで十分だが、**レベルのサイズに偏りがある場合は、「なるべく均等にしようとする」せいで、結局同じ分け方が返ってくる恐れはある。**

# OK例2：ラベル集合をKFoldする
ラベルの集合をランダムにKFoldする。

```python:OK例
def my_gkf(group, n_splits, random_state):
    unique_group = np.unique(group)
    kf = KFold(n_splits=n_splits, random_state=random_state, shuffle=True)
    for t,v in kf.split(unique_group, unique_group):
        t_group = unique_group[t]
        v_group = unique_group[v]
        yield np.where(np.isin(group, t_group))[0], np.where(np.isin(group, v_group))[0]

group = np.array([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6])
for i in range(3):
    print(i, "回目")
    for t,v in my_gkf(group, 3, i):
        print(set(group[t]), set(group[v])) 
```
>0 回目
{1, 2, 4, 5} {3, 6}
{1, 3, 5, 6} {2, 4}
{2, 3, 4, 6} {1, 5}
1 回目
{1, 4, 5, 6} {2, 3}
{2, 3, 4, 6} {1, 5}
{1, 2, 3, 5} {4, 6}
2 回目
{1, 3, 4, 6} {2, 5}
{1, 2, 5, 6} {3, 4}
{2, 3, 4, 5} {1, 6}

毎回違う結果が返ってきた。
偏りを特に気にせずやる場合はこれがよさそう。
Rで書かれた異常検知に関する本のコードをpythonに移植する(今のところ第2章のみ)

# 修正・追記(2022/04/05)
- 関連サイト部分に無関係なサイトが記載されていたので修正

# やったこと
- タイトルの通り、以下の本のコードを一部`R`から`python`へ移植した。
  - https://www.coronasha.co.jp/np/isbn/9784339024913/
  - 現在は2章のみ。今月中にある程度カタをつけたいなの気持ち。
  - `python`のみでなく、`Julia`にも移していければいいなの気持ち。
- 移植できた部分は、`RPubs`で公開した。
  - https://rpubs.com/yaminabeworks/ideodpyjl

# なぜやったのか
- 今筆者は`R`のコードを読める必要と`python`などのコードを書ける必要がある。
  - `R`で書かれた実装を移植することで経験値にしていきたいという気持ち。
  - 異常検知分野だといまだに話題に上がる本なので取り組んでみることに。
- まだやってないけど、第3章と第4章は結構いい感じがするのでこの機会に精読したいという気持ち。

# 参考文献

1.は参考としている書籍となります。2.は、この記事よりもよほど詳しく丁寧に同じことをやられている記事となっています。参考にしていきたいと思いました。

1. https://www.coronasha.co.jp/np/isbn/9784339024913/
2. https://qiita.com/tanaka_benkyo/items/a6af56bd881b2988909a

# 関連サイト

1.は筆者により`RPubs`でみられるようにしたものです。

1. https://rpubs.com/yaminabeworks/ideodpyjl

# 感想
- 半ば衝動的にやっつけでコードとブログを書き始めた。
  - うまいこと着地させた後でMLPの方を詳細に読んでいきたいという気持ち。
- 内容はまださほど難しくない部分だがグラフ周りでいつもつらい気持ちになる。
  - 可視化に関してはもう少しまとめて勉強しておきたいという強い気持ち。

# 次にやる、この記事に関連すること
- 次の章、次の次の章を読み進めていきたい。
  - 書籍中の実行例3.1と3.2は、`fitdistr`の仕様がわからないので後回しにする予定。
AmazonS3ゲートウェイエンドポイントを作成するときの注意点

[AWS FargateではVPC Endpointを使う](https://qiita.com/ldr/items/7c8bc08baca1945fdb50)で作成したS3ゲートウェイエンドポイントを使用する際の注意点があります。

S3ゲートウェイエンドポイントは1つしか作成できないので、staging用、production用といった用途で使い分けはできません。そのため、Interface型と違ってGateway型は複数のルートテーブルを定義できるようになっています。
![スクリーンショット 2022-04-04 18.59.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58788/283ee31c-ebc7-949b-115a-5f15d7981d41.png)

ポリシーもstg,prodを定義しておきます。
```aws_vpc_endpoint.tf
(snip)
policy = jsonencode(
{
  "Version" : "2008-10-17",
  "Statement" : [
    {
      "Sid" : "Access-to-specific-bucket-only",
      "Effect" : "Allow",
      "Principal" : "*",
      "Action" : [
        "s3:*"
      ],
      "Resource" : [
        "arn:aws:s3:::prod-ap-northeast-1-starport-layer-bucket",
        "arn:aws:s3:::prod-ap-northeast-1-starport-layer-bucket/*",
        "arn:aws:s3:::prod-bucketname",
        "arn:aws:s3:::prod-bucketname/*",
        "arn:aws:s3:::stg-ap-northeast-1-starport-layer-bucket",
        "arn:aws:s3:::stg-ap-northeast-1-starport-layer-bucket/*",
        "arn:aws:s3:::stg-bucketname",
        "arn:aws:s3:::stg-bucketname/*",
      ]
    }
   ]
 }
)
```
Apacheから直接Fluentdに送りたい！

メモベースです

Apacheからログファイルをtailするとローテートとか色々考えないといけない事が非常にめんどくさかったので色々試行錯誤してみた。

必要な設定は予めしておく

- apache
- fluentd
- selinuxとかセキュリティ周り

Apache LogFormatをこんな感じのJSONにする
```

LogFormat "{\"remotehost\":\"%h\",\"ident\":\"%l\",\"user\":\"%u\",\"datetime\":\"%t\",\"request\":\"%r\",\"status\":\"%>s\",\"byte\":\"%b\",\"referer\":\"%{Referer}i\",\"user_agent\":\"%{User-Agent}i\",\"time_taken\":%D}" combinedjson

CustomLog "|/opt/td-agent/bin/fluent-cat -p 24224 test" combinedjson

```

Fluentd側はこんな感じで適当に

```
<source>
  type forward
  port 24224
  bind 0.0.0.0
  tag test
  <parse>
    type json
  </parse>
</source>

<match test>
  type stdout
</match>

```

そうすると、動いてくれた。

```
2022-04-04 16:36:26.937969132 +0900 test: {"remotehost":"192.168.56.1","ident":"-","user":"-","datetime":"[04/Apr/2022:16:36:26 +0900]","request":"GET /index.html HTTP/1.1","status":"304","byte":"-","referer":"-","user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36","time_taken":179}
```

後は好きなようにいじればOK…と、
これで煩わしいファイル管理をしなくて良くなる。
stdoutに出力する事も考えましたが、errorや他のログと分離させるのが面倒なのでポートやsocketを分けて利用する方が使いやすいかなと思った。
VSCode ターミナルの配色をCampbellに (March 2022で変わったターミナルの色味を戻す）

vscode を March 2022 にアップデートしたところ、ターミナルの色味が変わってしまいました。
原因は[こちら](https://code.visualstudio.com/updates/v1_66#_minimum-contrast-ratio-default-changed)で（リンク踏んでも正しくスクロールしないので、4.5で検索をしてください）、
`terminal.integrated.minimumContrastRatio` のデフォルトが `1` から `4.5` になったことが影響していました。
とりあえず色味を戻したい場合は、上記設定をsettings.jsonに `1` で書き込めばOKです。

ところでこのタイミングで、デフォルトの `Dark+` の背景が明るいのが気になっていたので、より暗い`GitHub Dark Default` に変更しました。
が、ターミナルの配色が Windows Terminalのカラーテーマと思いっきりずれて違和感を覚えたため、Windows Terminalの `Campbell` と同じ色味の設定を行いました。

下記に記載しましたので、ご参考まで！


```json:settings.json
"workbench.colorTheme": "GitHub Dark Default",
"workbench.colorCustomizations": {
    "terminal.background":"#0C0C0C",
    "terminal.foreground":"#CCCCCC",
    "terminal.ansiBlack":"#0C0C0C",
    "terminal.ansiBlue":"#0037DA",
    "terminal.ansiBrightBlack":"#767676",
    "terminal.ansiBrightBlue":"#3B78FF",
    "terminal.ansiBrightCyan":"#61D6D6",
    "terminal.ansiBrightGreen":"#16C60C",
    "terminal.ansiBrightMagenta":"#B4009E",
    "terminal.ansiBrightRed":"#E74856",
    "terminal.ansiBrightWhite":"#F2F2F2",
    "terminal.ansiBrightYellow":"#F9F1A5",
    "terminal.ansiCyan":"#3A96DD",
    "terminal.ansiGreen":"#13A10E",
    "terminal.ansiMagenta":"#881798",
    "terminal.ansiRed":"#C50F1F",
    "terminal.ansiWhite":"#CCCCCC",
    "terminal.ansiYellow":"#C19C00",
}
```
IRI・URI・URL・URN 違い

# はじめに
インターネット上の情報の位置を記述するための表記法です。
IRI以外全て「Uniform Resource」となっています。


**IRI**: Internationalized Resource Identifier(s)
**URI**: Uniform Resource Identifier(s)
**URN**: Uniform Resource Name(s)
**URL**: Uniform Resource Locator(s)

<!-- 各チャプター -->
<a id="URI"></a>
# URI
URIはURLとURNを合わせもちます。
![URI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239825/faa325bc-32d8-642f-9b77-c37888908c3b.png)

また、URI(URL)は以下のように構成されています。
![URI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239825/2515487f-ca78-40aa-2707-45729b71f020.png)


<a id="#Chapter2"></a>
# IRI
IRIはURIをさらに拡張したもので、国際化資源（リソース）識別子とも言われます。

- URIではアスキー文字しか使うことができません。
- IRIではユニコード文字を使うことができます。

<a id="#reference"></a>
# 参考文献
- [Techpit:URLとURI](https://www.techpit.jp/courses/64/curriculums/67/sections/538/parts/1853)
- [CCNA](https://ccna-200-301.online/)
- [IT用語辞典](https://e-words.jp/w/URI%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%A0.html)
【階層線形モデル(HLM)】学生時代挫折した階層線形モデル(HLM)についてまとめてみる -解説編

# はじめに
統計学を専攻していた時、階層線形モデル（Hierarchical Linear Model）の授業を受講したのですが、当時の自分には（今でも少し）理解がむつかしかったので、リベンジするためにブログにまとめようと思いました。

# 階層線形モデル(HLM)とは
階層線形モデル、Hierarchical Linear Model(HLM)とは、階層的な属性をもつデータに回帰分析をかける際、データのもつ階層的要素を活かしつつ、回帰分析の前提(Assumption)も守れる、マルチモデルの1つです。線形混合モデル(Linear Mixed Model)とも呼ばれます。

# 階層的データとは
階層的データとは、ひとつひとつの観測値が独立していなく、なんらかの階層的要素を持っている。という事です。
例えば、学校Aに通う高校3年生のクラスA,B,Cの生徒を対象にした学力調査を行なった場合、学校Aという大きなグループの中にクラスA,B,Cという階層が含まれている(nested)事になります。
また、1人の特定の人物における異なる時点での観測値も、同じ人物に含まれる、nestedするという事になります。
さらに、階層的データは3段階以上になる事もあり、上記の学校の定期身体検診の2回の結果を観測値とすれば、階層が3階に増えます。
![統計力 (AIxデータ).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1044781/e8c28b4f-ecc3-267b-ae04-0b55e327f0be.png)


# 線形回帰における前提(Assumption)とは Review  
線形回帰が活用できる前提条件は以下になります。 
1. Linear relationship: $\beta$が「+」で繋がる式で表現されている　　
2. Independence: 観測値が独立である　　
3. Homoscedasticity: 残余が一定である　　
4. Normality: 残余が正規分布に従う

この前提の内2と3が階層データを扱うことで破られてしまいます。
2. Independence: 観測値が独立である→階層が含まれるので何らかの関係性を持つ
3. Homoscedasticity: 残余が一定である→階層が含まれるので、階層内で残余が偏る可能性がある　　

また、それ以外の懸念点として、説明関数が階層毎に与える影響が変化してしまう可能性があります。
例えば、上記の3階層の例において、学力調査のため、入学時に学力テストを行い(Time1)、各教科の難易度を変化させ再度学期末に行なった所(Time2)、担任が数学担当であったクラスBだけ数学のテストの成績が上がったとした場合。
線形回帰を使用し、階層を無視して分析を進めてしまうと、説明関数の１つであるである数学の難易度の効果が全体的に薄れた事になります。結果、「数学のテスの難易度を上げても、成績にあまり影響しない」といったミスリーディングな分析になってしまう場合があるのです。

# Why HLM ?
この様なデータを扱う際、それぞれの階層をカテゴリー変数として線形回帰モデルに導入すればいいと思うかもしれません。しかしそうすると、先ほどのクラスBの例で説明した通り、ある変数における効果が階層内のグループで乖離している場合、その効果(スロープ)が同一になってしまいます。また、同じ階層内のグループごとにモデルをフィットさせる方法は、サンプルサイズが少なくなり、重要なグループ内同士の情報をモデルに加味し損ねる可能性があります。

# 方程式 

```math
Y_{ij} = \alpha_{0j} + \beta_{1j}X + e_{ij} \\
\alpha_{0j} = \gamma_{00} + r_{1j}\\
\beta_{1j} = \gamma_{10} + r_{2j}\\
```
 
j:階層内のグループ（クラスA,B,C）
$\gamma_{00}$:全ての値の平均の切片
$r_{1j}$:グループ毎の切片
$\gamma_{10}$:全ての値の平均の傾き
$r_{2j}$:グループ毎の傾き

$r_{1j}$と$r_{2j}$を誤差項(Error Term)とし、式を結合

```math
Y_{ij} = \gamma_{00} + \gamma_{10}X + r_{1j} + r_{2j}X +e_{ij} \\
```

### イメージ　
仮に学校AにおけるクラスA,B,Cの国語の成績と数学の成績の相関

![統計力 (AIxデータ)_JapanesevsMath.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1044781/c2ca6777-a69b-10aa-e928-0e55ff07a1b2.png)


# Intra-class Correlation Coefficient (ICC)
Intra-class Correlation Coefficient (ICC)とは、グループ内の相関関係を0~1の値で示したものです。この数値が高い（一般的に0.1以上）ほど、HLMを使用する価値があるといえます。各グループの分散($\tau_{j}^2$)と、全体の分散$(\sigma^2+\tau_{j}^2)$の割合を現したものになります。

$$
ICC = \dfrac{\tau_{j}^2}{\sigma^2+\tau_{j}^2}
$$
 

# 終わりに

次回はRで実装してみようかと思います！

https://qiita.com/Shu25/items/c1b628169faa3de4fedb

### 参考文献　
- http://web.pdx.edu/~newsomj/mlrclass/ho_icc.pdf Newsom (2019)
- http://cogpsy.educ.kyoto-u.ac.jp/personal/Kusumi/datasem17/nishiguchi1.pdf 西口 (2016)
- https://towardsdatascience.com/hierarchical-linear-modeling-a-step-by-step-guide-424b486ac6a3 Chansiri (2021)
- https://www.youtube.com/watch?v=2w7Q4Wjn1uM Methods Consultants of Ann Arbor (2015)
cscの作法 その95

# 概要
cscの作法、調べてみた。
ラプラシアンフィルタやってみた。

# 参考にしたページ

https://qiita.com/santarou6/items/3b606a68ae2bdba32223

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6ab50047-be81-ad30-0d75-87f2d00b196b.png)

# サンプルコード

```

using System;
using System.Windows.Forms;
using System.Drawing;

class Form1: Form {
	PictureBox pb0;
	PictureBox pb1;
	Image img;
	Button button1;
	Form1() {
		Text = "lap";
		ClientSize = new Size(370, 700);
		pb0 = new PictureBox();
		pb0.Location = new Point(30, 10);
		pb0.Width = 300;
		pb0.Height = 300;
		this.Controls.Add(pb0);
		img = Image.FromFile("sprite-animation4.png");
		pb0.Image = img;
		button1 = new Button();
		button1.Location = new Point(30, 330);
		button1.Size = new Size(50, 20);
		button1.Text = "test";
		this.Controls.Add(button1);
		button1.Click += Button1_Click;
		pb1 = new PictureBox();
		pb1.Location = new Point(30, 360);
		pb1.Width = 300;
		pb1.Height = 300;
		this.Controls.Add(pb1);
	}
	private void Button1_Click(object sender, EventArgs e) {
		int i,
			j,
			nx,
			ny;
		int gray;
		Color col;
		nx = (int) img.Width;
		ny = (int) img.Height;
		int[,] f = new int[nx, ny];
		Bitmap bmp = new Bitmap(img);
		for (j = 0; j < ny; j++)
		{
			for (i = 0; i < nx; i++)
			{
				col = bmp.GetPixel(i, j);
				f[i, j] = (int)((col.R + col.G + col.B) / 3);
			}
		}
		for (j = 1;  j < ny - 1; j++)
		{
			for (i = 1; i < nx - 1; i++)
			{
				gray = f[i, j - 1] + f[i - 1, j] - 4 * f[i, j] + f[i + 1, j] + f[i, j + 1];
				gray += 128; 
				if (gray > 158)
				{
					gray = 0;
				}
				else
				{
					gray = 255;
				}
				bmp.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
			}
		}
		pb1.Image = bmp;
		this.Invalidate();
	}
	[STAThread]
	public static void Main() {
		Application.Run(new Form1());
	}
}




```
以上。
GAS(Google App Script)でスプレッドシートの特定のシートの列の最終行数とその値を取得して返す関数を作ったけどどうです？

## 経緯
GAS(Google App Script)で横着をすると、特定の列の最終行を取得できないので関数を作ってみた。
VBAだとこんな何行も書かなくても済むのにGASは大変だねぇ。
せっかく作るので、最終行の行数とその値を連想配列にて返してくれる感じにしておきました。
もっとスマートな書き方があるんだろうけども、whileとifでかけるからまあ、許してよ。

```javascript: GASのfunc
function getLastRowFuncs(clm, sheetName) {
  // 最終リターンする連想配列用変数
  let answerArray = {};

  // アクティブなスプレッドシートのオブジェクトを代入
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  
  // 引数で渡されたシート名のオブジェクトを代入
  const targetSheet = spreadsheet.getSheetByName(sheetName);

  // 指定した列の値を配列で取得  
  const columnsVals = targetSheet.getRange(`${clm}:${clm}`).getValues();
  
  console.log(columnsVals.length);
  let lastCellFlg = false;
  let cnt = columnsVals.length -1;
  let chk_var;
  
  while(lastCellFlg !== true){
    // 配列の中に配列が入っている状態で渡ってくるので末尾に[0]としている
    chk_var = columnsVals[cnt][0];
    // console.log(`chk_var[0]: ${chk_var}`);
    if(chk_var !== ""){
      lastCellFlg = true;
      answerArray["lastRow"] = cnt + 1;
      answerArray["lastValue"] = chk_var;
    }
    cnt --;
  }
  
  // ログに出力
  Logger.log(answerArray);

  return answerArray;
}

```


こちらが呼び出し元となるmainで記述する書き方
```javascript: 呼び出し元のfuncs
    let sheetName = "課題シート";
    var clm = "F";

    lastRowArr = getLastRowFuncs(sheetName, clm);
    console.log(lastRowArr);
    
    //取得内容はシートによって変わるよ 
    //{lastRow= 82.0, lastValue= No}


```

そんな感じで！！
TOTO くじ を題材として Ruby で スクレイピング

# はじめに
`Nokogiro`の練習として、TOTOくじを題材にスクレイピングをやってみました。
# TOTOくじ
https://toto.yahoo.co.jp/vote/toto

例えば、投票状況から皆さんが本命視している組合せを調べます。
# Nokogiri
```rb
require 'nokogiri'
```
`require`します。
```rb
doc = Nokogiri::HTML.parse(html)
```
htmlソースをパースします。
今回は、細かなオプションなしでうまくいきました。
```html
<tr>
<td class="zero_bar" height="26%"><img src="https://s.yimg.jp/images/toto/totoBIG/result/toto_vote_blank.gif" width="16" height="100%" title="26.56％"></td>
</tr>

// 必要な部分を抜き出す ↓

<td class="zero_bar"><img title="26.56％"></td>
```
スクレイピングしたい部分をまとめますと、タグに`css`が対応、属性に`attribute`が対応していることが分かります。
```rb
doc.css('td.zero_bar img').each_with_index do |td, i|
  votes[i][0] = td.attribute('title').value.to_f
end
```
`td.attribute('title').value` は `"26.56％"`の様な文字列ですが、`to_f`で変換しますと、先頭から数値に変換可能な文字のみを変換しますので、`％`が取れます。
# ソース
```rb:ruby
require 'nokogiri'
require 'open-uri'

url = 'https://toto.yahoo.co.jp/vote/toto'
html = URI.open(url){ |f| f.read }
doc = Nokogiri::HTML.parse(html)

votes = Hash.new{ |h, k| h[k] = {} }
    
doc.css('td.td_team').each_with_index do |td, i|
  votes[i + 1]["team_name"] = td.text
end
doc.css('td.zero_bar img').each_with_index do |td, i|
  votes[i][0] = td.attribute('title').value.to_f
end
doc.css('td.one_bar img').each_with_index do |td, i|
  votes[i][1] = td.attribute('title').value.to_f
end
doc.css('td.two_bar img').each_with_index do |td, i|
  votes[i][2] = td.attribute('title').value.to_f
end
doc.css('td.three_bar img').each_with_index do |td, i|
  votes[i][3] = td.attribute('title').value.to_f
end

pp votes

puts votes.values.map{ _1.key([_1[0], _1[1], _1[2], _1[3]].max) }.join(" ")
```
```rb:output
{1=>{"team_name"=>"京都", 0=>23.17, 1=>40.91, 2=>24.89, 3=>11.03},
 2=>{"team_name"=>"Ｇ大阪", 0=>16.93, 1=>35.15, 2=>31.69, 3=>16.23},
 3=>{"team_name"=>"磐田", 0=>43.77, 1=>39.79, 2=>11.93, 3=>4.51},
 4=>{"team_name"=>"川崎", 0=>9.35, 1=>22.94, 2=>35.91, 3=>31.8},
 5=>{"team_name"=>"広島", 0=>35.35, 1=>41.86, 2=>16.45, 3=>6.34},
 6=>{"team_name"=>"横浜Ｍ", 0=>13.53, 1=>29.19, 2=>34.92, 3=>22.36}}
1 1 0 2 1 2
```
第1293回 totoGOAL3の最終の人気の組合せは、`1 1 0 2 1 2`の様です。
# まとめ
+ Nokogiri に詳しくなった
Gitの基本操作


### ローカルにリポジトリを作成する　

⑴「git init」がリポジトリを作成する
⑵「git add」がファイルをインデックスに追加する（Gitに管理する対象のfileをアップする）
⑶「git commit」でインデックスした内容を変更する
　　git commit -m "ここにコメントを記載できます！"

```
$ git init
$ git add .
$ git commit -m "Initial commit"
```

### リモートにプッシュする 
→超簡単に言えばアップデートしましょうねという話
⑴「git remote add origin "URL"」で新しいリモートの設定
⑵「git push origin master」ローカルのコードをoriginというリモートリポジトリに送る

```
$ git remote add origin https://github.com/XXXX/XXXXXX.git
$ git push  origin master
```

### アップデートした内容を取り消す
インデックスされた特定のfileの変更を取り消す
```
$ git reset .
$ git reset HEAD .

$ git reset <File_Name>
$ git reset HEAD <File_Name>

```
Vuetifyでアイコンモジュールエラーを解決した流れ

#言語
HTML/CSS/JavaScript
Ruby 2.6.3

#フレームワーク
Vue 2.6.12
Vuetify
Rails 6.1.3.2

＃Uncaught Error: Cannot find module '@mdi/font/css/materialdesignicons.css'
上記エラーがブラウザコンソールで表示されました。

私はカレンダーアプリを作っていて、Vuetifyのカレンダー関連が表示されなくりました。

エラーを訳してみるとVuetifyで使っているアイコン(Material Design Icons)のモジュールが読み込めていない模様。


＃私が試した解決策(あくまでも一例として)

私の場合yarnを使用していたので、yarnで再度インストールをしました。ターミナルでインストールコマンドを実行。

~~~~~
$ yarn add @mdi/font
~~~~~

インストール完了し、Railsサーバーを起動すると表示が元通りになっていました。

正直、この流れがで解決したのか分かりませんが、アウトプットのため残すことしました。
HTML【個人用ドキュメント】

# form

### onsubmit属性
「onsubmit」は「formタグ」内の属性として記述するようになっており、submitされた時に起動するイベントです。
### preventDefault()メソッド
preventDefault() メソッドは、ユーザーエージェントに、イベントが明示的に処理されない場合にその既定のアクションを通常どおりに行うべきではないことを伝えます。通常submitするとその情報を送信してページを更新することですが、それを防ぐことができます。
#### formの記述例
```
//onsubmit属性,event.preventDefault()
<form id="bank-form" class="form" onsubmit="initializeUserAccount(); event.preventDefault()">
    <div class="form-group">
        <input type="email" name="userEmail" class="form-control" placeholder="Email" required>
    </div>
    <div class="form-group">
        <input type="text" name="userFirstName" class="form-control" placeholder="First name" required>
    </div>
    <div class="form-group">
        <input type="text" name="userLastName" class="form-control" placeholder="Last name" required>
    </div>
    <div class="form-group">
        <input type="number" class="form-control" name="userFirstDeposit" aria-describedby="emailHelp" placeholder="Enter your first deposit" required>
    </div>
    <div class="form-group">
        <div class="form-check">
            <input class="form-check-input" type="radio" name="userAccountType" id="userAccountType1" value="savings" checked required>
            <label class="form-check-label" for="userAccountType1">
                Savings
            </label>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="radio" name="userAccountType" id="userAccountType2" value="checkings" required>
            <label class="form-check-label" for="userAccountType2">
                Checkings
            </label>
         </div>
    </div>
    <button type="submit" class="btn btn-primary col-12">Submit</button>
</form>
```

# input

### required属性
input要素のrequired属性は、その入力項目が必須属性であることをブラウザに知らせることができる。HTML5では、required属性を設定するだけでJavaScriptによる入力チェックがなくてもエラーメッセージを表示させることが可能。

https://recursionist.io/dashboard/course/17/lesson/344

https://web.havincoffee.com/html/tag/select/required.html

### aria-describedby属性

https://developer.mozilla.org/ja/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute

https://www.riarise.com/coding/bootstrap4-accessibility-wai-aria-vol03/


# button

https://qumeru.com/magazine/276
写真の光の加減を自在に変える手法について　その１

# はじめに
https://www.youtube.com/watch?v=KeebkkaZhhI
https://augmentedperception.github.io/total_relighting/
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581710/c6f5e03f-c3e3-4a8b-6a90-c08c2676446b.png" width=30%>
写真に写った人物を別の背景写真に乗せてライティングを調和させる技術。
SIGGRAPH 2021でGOOGLEが発表した「Total Relighting」の試みが面白そうなので、
論文に乗ってる関連資料をすこしずつすこしだけ読んでみます。

# 前提
背景に人を合成する場合。
背景の上からそのまま人の画像だけ貼り付ければ光の当たり方の違いでうまく調和しません。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581710/b9ab8b63-ed05-4910-49c3-94fdeeade704.png" width=30%>


ファンタジーな背景を映す映画では、ブルースクリーンに背景画像を合成したり、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581710/acbf89c9-85a7-2275-0c80-8353ddd4e2ae.png" width=30%>

「マンダロリン」という映画では、円筒上のLEDという大型の装置を用いることで、
背景の合成をおこなっているそうです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581710/76fb9dfc-7371-633b-5de5-e28090fe5bc9.png" width=30%>

https://ascmag.com/articles/the-mandalorian
これらの取り組みは、どうしても設備に依存してしまうため、
一枚の画像から気軽に行うことを目標にしたのが、「Total Relighting」の取り組みらしい。

# Image-Based Relighting
写真からライティングを調和させる技術を一つも知らないので、
関連Paperにかかれているものをいくつか見てみます。

## Acquiring the Reflectance Field of a Human Face
https://www.pauldebevec.com/Research/LS/debevec-siggraph2000-high.pdf
「人間の３Ｄデータ」と「写真に写る人間」
例えばそれぞれ、夕暮れのシーンに加工しようと思ったとき、
どちらが楽でしょうか。結論から言えば、「人間の３Ｄデータ」は比較的容易でしょう。

なぜなら、３Ｄデータであれば、
体の複雑な形状、空間内での位置、カメラの視線方向、照明方向・位置を明確に定義することができ、
さらには、肌の「拡散反射」と「鏡面反射」を数値で定義することができるからです。

３Ｄの仮想空間上であれば、
上記のパラメータでどのようにピクセルの色が決まるかを、明示的に計算できます。

しかし写真の場合、
上記の情報を測定して既知の状態で、再現しなければなりません。
特に、ピクセル単位の肌のそれぞれの反射の特性を把握することは極めて難しいです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581710/ff833c2b-8bb4-98c8-1644-499c6d13d185.png" width=30%>

そこでこの論文では、
球状に光が当たる装置を利用して頭全体に均一な光を当てます。

肌に光があたったときの特性を推定し、
照明による効果を既知のものとしてセッティングすることで
任意の照明効果を再現します。。
LambdaでS3のファイルを読み書きする

Lambda(Python)からS3へファイルをアップロードしたり、読み書きしたりすることがあったので書き記しておきます。

権限周りの話は以前こちらに書いてあるので参考にして下さい　↓↓↓

https://qiita.com/ymktmk/items/174ab4fecb14a0a3c7e0

## Client APIとResource APIの違い

https://aws.amazon.com/jp/sdk-for-python/

・Client APIはレスポンスが辞書型なので必要な情報を取り出しにくい
・Client APIはHTTP API 操作との 1 対 1 のマッピングが提供される
・Resource APIの方がオブジェクト指向っぽく書ける
・Resource APIが用意されていないことがあるサービスもある

＊ Resource APIはresponse.bodyというようにオブジェクトを取得してから属性を参照できると書いてあったが自分はなぜかレスポンスが辞書型であった。よく分からない。

## S3にファイルをアップロードする

＊ 上書きするときもs3.put_objectで行う
＊ バケットポリシーに"Action": "s3:PutObject"を追記する

### boto3.clientの場合

```python
import json
import boto3
from datetime import datetime

s3 = boto3.client('s3')

def lambda_handler(event, context):
    file_contents = '[{"name": "tomoki","age": 21},{"name": "yamaoka","age": 21}]'
    bucket = 's3-backet-redshift'
    key = 'test_' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.json'
    response = s3.put_object(Body=file_contents, Bucket=bucket, Key=key)
    return response
```

### boto3.resourceの場合

```python
import json
import boto3
from datetime import datetime

s3 = boto3.resource('s3')

def lambda_handler(event, context):
    file_contents = '[{"name": "tomoki","age": 22},{"name": "yamaoka","age": 22}]'
    bucket = 's3-backet-redshift'
    key = 'test_' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.json'
    bucket = s3.Object(bucket,key)
    response = bucket.put(Body=file_contents)
    return response
```

## S3のファイルを読み取る

＊ バケットポリシーに"Action": "s3:GetObject"を追記する
＊ 自分は読み取りに少し時間がかかってデフォルトの3秒を超えてTimeoutになったので10秒くらいにしておくと良い

```python
import json
import boto3
from datetime import datetime

s3 = boto3.client('s3')

def lambda_handler(event, context):
    bucket = 's3-backet-redshift'
    key = 'test_2022-04-04-06-11-43.json'
    response = s3.get_object(Bucket=bucket, Key=key)
    body = response['Body'].read()
    return body
```

## S3のファイルを削除する

＊ バケットポリシーに"s3:DeleteObject"を追記する

```python
s3.delete_object(Bucket=bucket, Key=key)
```

## 終わりに

この記事を見るとLambdaにS3バケットに対する読み取り権限を付与するのでもいいっぽい。
**(update 2022/5/24)SSAの試験勉強をしているとLambdaにIAMポリシーを適用する方が良いとのこと。**

https://dev.classmethod.jp/articles/get-s3-object-with-python-in-lambda/

## 参考文献

https://dev.classmethod.jp/articles/boto3-client-api-and-resource-api/
Kintoneについて調べてみました。

近年、DX(デジタルトランスフォーメーション)を取り入れる会社が増えてきましたが業務の効率化を図るために[Kintone(キントーン)](https://kintone.cybozu.co.jp/?_gl=1*11e9nq4*_ga*MjM3NjI2MDQzLjE2NDg4MDI2MjQ.*_ga_T5K95WXL54*MTY0OTA0OTkxMy41LjEuMTY0OTA1MDIxMi42MA..)というサイボウズ社が提供するクラウドサービスについて調べてみました。
今までは、エクセルなどで管理していたデータをキントーンを使えばわかりやすく簡単にまとめられ、検索などもスムーズにできるようになります。
Webデータベースとも言われ、主に見積書や請求書を自社のひな形として直接入力できるフォームアプリが作成できるので、アプリ一つ一つがマイクロサービスとなり、APIなどを使用してカスタマイズする事で沢山の可能性を引き出すことができます。
![スクリーンショット 2022-04-04 15.13.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/6ed964c3-4d65-573a-50c9-005c5b683a2b.png)
まずは、お試しで30日間無料で全ての機能を体験できるので、しっかりここで機能を覚えて、見積書や経費精算書などのアプリを作ってみると良いでしょう。
![スクリーンショット 2022-04-04 15.19.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/cedd29e6-e4ec-6335-c340-1375874d7efe.png)
チュートリアルをもとに**はじめから作成**ボタンからアプリ作成画面に移動して作成します。
![スクリーンショット 2022-04-04 15.14.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/b79cac0c-d0a5-3e55-1cb0-b3c8b5b44a7e.png)
ドラッグアンドドロップでフォームが作成できるので非常に簡単です。
![スクリーンショット 2022-04-04 15.26.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/8dc7df71-7fd1-600e-b06c-f80079fa7beb.png)
作成のポイントとしては、実際に使い手のことを考えて項目はできるだけ最小限に抑えて必須項目なども極力作らなようにシンプルなものにしましょう。
![スクリーンショット 2022-04-04 15.30.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/c00f3c72-e6b4-9953-54ef-783d477d95d9.png)
カスタマイズするのにもチュートリアルがあるので、安心です。
![スクリーンショット 2022-04-04 15.45.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/5259c5b2-1f77-dfa8-a8cf-280b4ca48fec.png)
**JSFiddle**や**Chrome**の`console`を使用して、初心者でもプログラムを学習することができます。
![スクリーンショット 2022-04-04 16.13.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/2cf528d2-a12e-cbd5-c198-7a2d17deabeb.png)
JavaScriptをkintoneに導入すると、アップデートで動かなくなる可能性が出てくるのと、コードを書いた人にしかわからなくなってしまう属人的な面もあるので、サブスクなどで有料ではありますがプラグインがあるのでそちらで対応することをオススメします。
![スクリーンショット 2022-04-04 16.19.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/0aefc1d7-914e-a4b8-eb5c-d27d960a6232.png)
APIを使用し、アプリAの情報が更新されたらアプリBに登録されたデータを更新させたりできます。
![スクリーンショット 2022-04-04 17.00.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/be50d148-8dc6-3611-173d-ce8a8b71168d.png)
Kintoneはリレーショナルデータベースでトランザクションという単位でユーザが実行した一連の処理を管理するような概念がなく、データの重複をなくし整合的にデータを取り扱えるようにする正規化で処理されています。
![スクリーンショット 2022-04-04 17.18.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/cbc23b71-a44d-1c14-497c-fdfd42bdfb26.png)
導入することで多種多様な職種に新しい可能性を見出せそうですね。
Javascript object の配列をあるメンバ変数を利用してソートしたい

# Javascript objectの配列をあるメンバ変数でソートする

# たぶん今後自分が一番よく使う比較関数を利用するパタン
値を２つ受け取ってそれらの大小をjavascriptルールに従って判定して、大きければ1を小さければ-1を返すというのを作成
```javascript
function compare(a,b) {
    let rtn_value = 0;
    if(a > b) {
        rtn_value = 1;
    } else if (b > a) {
        rtn_value = -1;
    }
    return rtn_value;
}
```

これを sort 関数の引数として渡してあげるとその評価関数にしたがってソートしてくれる
```javascript
const array = [2, 4, 3, 8];
array.sort(compare);
// => 2, 3, 4, 8
```

# これを応用する形でオブジェクトのメンバ変数を指定した比較関数を書いておく
objectのメンバ変数にdistanceという 'number'型の変数があったとします。
```javascript
function compareMyObj(a,b) {
    let rtn_value = 0;
    if(a.distance > b.distance) {
        rtn_value = 1;
    } else if (b.distance > a.distance) {
        rtn_value = -1;
    }
    return rtn_value;
}
```
としておけば、distanceの大きさによってオブジェクトの配列がソートされるはずです。
実際にうまくいきました。

逆に大きい順に並べたいときには return する数値を反対にしてあげれば良さそうです。
```javascript
function compareMyObj(a,b) {
    let rtn_value = 0;
    if(a.distance > b.distance) {
        rtn_value = -1;
    } else if (b.distance > a.distance) {
        rtn_value = 1;
    }
    return rtn_value;
}
```
【PAD】入出力変数について

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/0fa81a5f-3fa5-4191-c5ac-d91d3bf71d00.png)

<b>入力変数</b>はフローが実行される前に定義され、<b>出力変数</b>はデスクトップフローの実行後に、フローのプロセスに沿って定義されます。
Power Automateのクラウドフローや他のDesktopフローと連携する際などに有用です。

:::note info
Desktopフローからクラウドフローを呼び出すことは現状できないようです。
:::

【例】Web APIがあるシステムについてはそのデータをクラウドフローで呼出し、Web APIがなくCSV出力などでデータ提供されているWEBシステムをPADで用意してお互いのデータを突き合わせたい場合

# 入出力変数の追加の仕方
- フロー変数の追加の仕方とは違い、**予め入出力変数を変数ペインで設定する必要があります**。
1. 「入出力変数」の一覧の右上にある「＋」ボタンを押下し「変数の種類(入力/出力)」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/210bef01-b716-2c76-ffc5-c8d56e9410c8.png)
1. 「変数名」プロパティはPADフロー内での変数名、「外部名」プロパティは出力先のフローでの変数名。
【例】クラウドフローから上記の出力変数が呼び出された場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/1a2b05f4-2b2d-ac9d-52ab-3d1c6a61f8dd.png)
![Items.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/fc9ece59-8718-f29c-082c-517274bc0696.png)


1. 任意のアクションで使用する値(出力先の値)を1で設定した入力(出力)変数に設定する。

## 出力したいデータがDataTable型やList型の場合
この場合そのまま送信すると<font color="red">全ての値が文字列として結合されてしまい後続のフローで値を取り出しづらくなります。</font>
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/1bc88dc7-aca3-d44d-9859-131de5b40044.png)
従って**Desktopフローの方でJSON形式の変数を生成する**と良いです。
<font color="gray">※取得したいDataTable(/List型)のデータによってはJSON形式に変換しなくてもクラウドフロー側で文字列の分割などで対応できる場合もあるかと思います。そのような場合は1レコードずつ取り出すには[こちらの記事](https://qiita.com/kojisaiki/items/d7fb7932e6f20e1e6628)が参考になるかもしれません。</font>

【例】
（DesktopフローでJSON形式になるようデータを生成）
![Items (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/eac52ef0-2de7-7f4c-286e-e9baa6f05f73.png)

（クラウドフローでの呼出結果）
![Items (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/78ec2495-9e80-3534-fdd5-13475e47a09d.png)
- KintaiDataをアクション「JSONの解析」を通せば後続のフローで使用しやすくなる。
![Items (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/495dc6eb-f4fe-ac00-0bf6-5f9f8e8f0cc5.png)

JSONのデータ作成の仕方の基本については以下の記事が分かりやすいかと思います。

https://qiita.com/shuntaro_tamura/items/5a92c517a7d95d655505#2-1%E5%85%A8%E4%BD%93%E3%81%AE%E8%A8%98%E8%BF%B0%E6%96%B9%E6%B3%95


---
# 参考
https://docs.microsoft.com/ja-jp/learn/modules/input-parameters/

https://docs.microsoft.com/ja-jp/learn/modules/pad-variables/5-input-output-variables
特定バージョンのAndroidでButtonテキストのHTML装飾が効かない

特定バージョンのAndroidで、`Html.fromHtml` でテキストを装飾したボタンのスタイリングが効いていないと問い合わせがあったのでメモ。

どうやら、ボタンテキストを大文字化しているメソッドに不具合があるらしく、Spannable の装飾がキャンセルされてしまうらしい。
この機能をキャンセルすると解決する。

```xml
<Button
    ...
    android:textAllCaps="false" />
```

Button と Spannnable で調べればいくつも情報が見つかるのだが、TextViewでは問題が出ないことと、Spannable ではなく fromHTML から調べてしまいハマってしまった。

Android 5.0 の頃から発生しているらしい。 今回は 7.1.1 で報告があった。

#### 参考
https://stackoverflow.com/questions/29007746/button-settext-with-spannable-doesnt-work-for-android-5-0-lollipop

https://qiita.com/furusin_oriver/items/18561c06ea6fa33d0c26
「Qiita で Mermaid 対応した話」をMermaidを使いながら書いてみた

先日、Qiita で[**Mermaid でのダイアグラム表示がベータ版として公開されました！**](https://qiita.com/release-notes#2022-03-28)

[![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/d1675a28-e952-c037-59d0-bed50ad4788d.png)](https://qiita.com/release-notes#2022-03-28)

僕は Mermaid でダイアグラムを書いたことがなく、せっかくなので「Qiita で Mermaid 対応した話」を**Mermaid を使って**記事にします。

## Mermaid とは

Mermaid とはダイアグラム（図）を書くためのツールで、コードを書くことでグラフを書くことができます。
詳しくは[公式ドキュメント](https://mermaid-js.github.io/mermaid/#/)をご覧ください。

Qiita では以下のようにすることで書くことができます。

:::note warn
ベータ版を有効にする必要があります
:::

    ```mermaid
    graph TD;
        A-->B;
        A-->C;
        B-->D;
        C-->D;
    ```

上記のコードブロックが以下のようなグラフになります。

```mermaid
graph TD;
    A-->B;
    A-->C;
    B-->D;
    C-->D;
```

## どうやって実現しているのか？

結論から話すと、Qiita では Web Component を使って実現しています。

ですが、はじめは [mermaid-cli](https://github.com/mermaidjs/mermaid.cli) をベースに Qiita の Markdown パースの仕組みに組み込もうとしていました。

### 当初の予定

ざっくりとしたイメージは以下です。

```mermaid
sequenceDiagram
    actor ユーザー
    ユーザー ->> Qiita Markdown: 書いたMarkdown
    Qiita Markdown ->> mermaid-cli: Mermaidのコード
    mermaid-cli ->> Qiita Markdown: 変換された画像
    Qiita Markdown ->> ユーザー: HTML
```

理由としては、

- 記事・質問ページの CLS 悪化
- エディタ上でのプレビューのちらつき

によるユーザー体験の悪化をなくしたかったためです。

しかし、`mermaid-cli`での処理時間が長く、最適化を行っても 300ms 程度かかってしまっていました。
（`mermaid-cli`の内部としては、ブラウザを立ち上げて実際にレンダリングさせ、レンダリングされた画像を返している実装になっています）
`mermaid-cli`が遅いと、その分プレビューなどのレスポンスタイムにも影響が出てしまうため、断念しました。

```mermaid
sequenceDiagram
    actor ユーザー
    ユーザー ->> Qiita Markdown: 書いたMarkdown
    note left of mermaid-cli: 変換の処理が遅い！
    Qiita Markdown ->> mermaid-cli: Mermaidのコード
    mermaid-cli ->> Qiita Markdown: 変換された画像
    Qiita Markdown ->> ユーザー: HTML
```

### クライアントでやるしかない

`mermaid-cli`の件で、サーバー側で Mermaid を処理することは難しいため、ユーザーのブラウザ側で Mermaid を処理することにしました。

クライアントでやるといっても方法はいくつか考えられます。結論としては Web Component を使った実装にしました。

```mermaid
sequenceDiagram
    actor ユーザー
    ユーザー ->> Qiita Markdown: 書いたMarkdown
    note right of Qiita Markdown: mermaidのコードブロックを<br>カスタムエレメントに変換
    Qiita Markdown ->> ユーザー: HTML
    note left of ユーザー: カスタムエレメントを<br>レンダリングする
```

理由は、

- サーバー側では Mermaid のコードブロックをカスタムエレメントとして変換するだけで良い
- クライアントの実装がカスタムエレメントで完結する

ためです。

### プレビューのちらつきがつらい...

クライアントで Mermaid をレンダリングするにあたり、Qiita のエディタのように要素の入れ替わりが激しい場合、毎回レンダリングを行うため、どうしてもプレビュー画面の Mermaid ダイアグラムがちらつき、ガクガクしてしまいます。

当初、サーバーで処理をしたかった理由の、

- 記事・質問ページの CLS 悪化
- エディタ上でのプレビューのちらつき

を少しでも軽減するために、Qiita では Mermaid のレンダリングに少し工夫をして、**Mermaid のコードが書き変わったときのみ**Mermaid をレンダリングするようにしています。

イメージは以下のような感じです。

```mermaid
sequenceDiagram
  カスタムエレメント ->> キャッシュストア: キャッシュの問い合わせ
  alt キャッシュがある場合
    note right of キャッシュストア: キャッシュがある！
    キャッシュストア ->> カスタムエレメント: キャッシュされている画像を返す
  else キャッシュがない場合
    note right of キャッシュストア: キャッシュがない...
    キャッシュストア ->> カスタムエレメント: キャッシュがありません
    カスタムエレメント ->> Mermaid: レンダリングを依頼する
    Mermaid ->> カスタムエレメント: レンダリングした画像を返す
  end
  note left of カスタムエレメント: 画像をレンダリング
```

これによって、エディタで Mermaid のコードブロック以外を書いている際にプレビューでの Mermaid ダイアグラムのちらつきをなくしています。

## さいごに

Mermaid を使って「Qiita で Mermaid 対応した話」を書いてみました。
ぜひ、Mermaid を使って記事を書いてみていただけると嬉しいです！

もし不具合などありましたら、

https://github.com/increments/qiita-discussions/discussions

よりご報告していただけると幸いです。
Google Play Consoleでアプリを申請・公開する方法

## 環境
chromeブラウザ


## 1. アプリをアップする

申請したいアプリをアップします。
App Bundle エクスプローラ　＞　新しいバージョンをアップロード　＞　aabファイルをアップする

## 2.リリースを作成する

製品版　＞　新しいリリースを作成　＞ App Bundleをライブラリから追加を選択し、手順1でアップしたaabファイルを選択
　![スクリーンショット 2022-03-31 11.05.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130708/865daaa1-0a46-e509-20bf-ea1999fe8484.png)

リリース名、リリースノートを記載する。
※リリースノートは以前のノートをコピーすることも可能
![スクリーンショット 2022-03-31 11.08.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130708/8082521d-6bab-97e5-ddb4-f381d080feaa.png)

画面右下の[保存]をタップし、[リリースのレビュー]をタップ

## 3.リリースのレビュー

段階的な公開の割合を100%にする。
※アプリの状況次第です。

![スクリーンショット 2022-04-01 17.15.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130708/36a43646-9353-112b-428c-80c3c5401e06.png)

[製品版としての公開を開始]をタップすると申請完了です。

## 4.審査状況の確認
[公開の概要]　に遷移すると審査状態が分かります。
![スクリーンショット 2022-04-01 21.24.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130708/d4957bba-842f-839a-8c47-f41cfa692d9c.png)

## 5.リリース
変更の公開準備完了になったら、公開ができる状態になっています。
※この動作はアプリの公開タイミングが手動設定の場合です。
[変更を公開]をタップし公開。
![スクリーンショット 2022-04-04 9.45.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130708/f402e191-8cc1-87cb-c47d-850eb6255ed7.png)
Scalaの勉強はじめました 5 〜パターンマッチ〜

## はじめに
N予備校で「Scala基礎」を受講しています。
今回はパターンマッチについてです。

## パターンマッチ
```scala
def intToName(num: Int): String = {
    num match {
      case 1 => "one"
      case 2 => "two"
      case _ => "other"
   }
 }
```
これが`match`の基本。
JSと違って`break`を書かなくても次の処理が実行されることはない。

同じ処理結果なら`|`でまとめられる。
```scala
creature match {
      case "cat" | "dog" => "animal"
    }
```

### コレクションのパターンマッチ
```scala
val seq = Seq("A", "B", "C", "D", "E")
    seq match {
      case Seq("A", b, c, d, e) =>
        println(s"b = ${b}")
        println(s"c = ${c}")
        println(s"d = ${d}")
        println(s"e = ${e}")
      case _ =>
        println("nothing")
    }
```
一つでもマッチすれば右辺が評価される。

:::note
引数や定数などの名前に対して特定の値を固定することを束縛という。
:::

ここでは、`Seq`の先頭が"A"で 5つの要素のパターンにマッチすると、残りの b, c, d, e の変数にそれぞれ `Seq`の 2番目以降の要素が「束縛」される。

ガード句も使える
```scala
val seq = Seq("A", "B", "C", "D", "E")
    seq match {
      case Seq("A", b, c, d, e) if b != "B" =>
        println("b = " + b)
        println("c = " + c)
        println("d = " + d)
        println("e = " + e)
      case _ =>
        println("nothing")
    }
```
束縛された結果、`b = "B"`になるが、`if`の条件によってワイルドカードパターンにマッチする。

### as パターン
```scala
val seq = Seq(Seq("A"), Seq("B", "C", "D", "E"))
    seq match {
      case Seq(a@Seq("A"), x) =>
        println(a)
        println(x)
      case _ =>
        println("nothing")
    }
```
パターンの前に`@`がついたものを `asパターン`という。
`Seq("A")`が 変数`a`に入る。

### ジェネリクス
```scala
def patternMatchGenerics(): Unit = {
    val obj: AnyRef = Seq("a", "b", "c")
    obj match {
      case v: Seq[Int] => println("Seq[Int]")
      case v: Seq[String] => println("Seq[String]")
    }
  }
```
`AnyRef`は Javaの`Object`型に対応したデータ型。
ジェネリクスは、コレクション型の`[]`の中に入る要素の型指定のこと。

:::note warn
Scala が動いている JVM の仕様で、型として利用されるときには `Int` のジェネリクスの型の 情報が消えてしまうため、`Seq[Int]`ではなく`Seq`としてマッチしてしまう。
:::

```scala
case v: Seq[_] => println("Seq[_]")
case _ => println("nothing")
```

ワイルドカードを利用する。

## まとめ
次の更新から関数型プログラミングに入るんですが、`match`を使う場面がとにかく多いので整理がてらまとめました。抽象化しようとすると、`if`よりも`match`の方が都合がいいのかと、なんとなく思ってます。
gcloud で Google Cloud Functions を使う

次の Cloud Function を gcloud から使う方法です。

```js:test-function-uchida-apr04
/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
exports.helloWorld = (req, res) => {
  let message = req.query.message || req.body.message || 'Hello World! Apr/04/2022 PM 16:12';
  res.status(200).send(message);
};
```

Region は asia-northeast1
Project は　project-apr0401
とします。

```text
$ gcloud functions list
NAME                        STATE   TRIGGER       REGION           ENVIRONMENT
test-function-uchida-apr04  ACTIVE  HTTP Trigger  asia-northeast1  2nd gen
```

## 環境設定

```text:$HOME/.config/gcloud/configurations/config_default
[core]
account = example@gmail.com
project = project-apr0401
```

## Login

```bash
gcloud auth login
```

## 実行コマンド

```bash
gcloud functions call  --region=asia-northeast1 test-function-uchida-apr04
```

## 実行結果

```text
$ gcloud functions call  --region=asia-northeast1 test-function-uchida-apr04

  Hello World! Apr/04/2022 PM 16:12
```

Curl を使った例

```bash
curl -X GET "https://asia-northeast1-project-apr0401.cloudfunctions.net/test-function-uchida-apr04" \
	-H "Authorization: bearer $(gcloud auth print-identity-token)"
echo ""
```

Httpie を使った例

```bash
http "https://asia-northeast1-project-apr0401.cloudfunctions.net/test-function-uchida-apr04" \
	"Authorization: bearer $(gcloud auth print-identity-token)"
```
NVM for Windows利用時にNode.jsバージョン変更後「npm ERR! Unexpected token '.'」が出るとき

# 経緯

NVM for Windows 1.1.7を利用中、Node.jsのバージョンを14系から16系に上げた際、
>npm ERR! Unexpected token '.'

が出てビルドできなくなってしまう事象が発生。


# 対応

> NOTICE: If you downloaded this version before Dec 15, 2021 and are affected by issue #706, please re-download. This fix was not present in the initial binary and has since been corrected.
https://github.com/coreybutler/nvm-windows/releases/tag/1.1.9

や

https://github.com/npm/cli/issues/4234#issuecomment-1080927985
のコメントを参考に、
1. まず[NVM for Windows](https://github.com/coreybutler/nvm-windows)を、「[1.1.9](https://github.com/coreybutler/nvm-windows/releases/tag/1.1.9)」までバージョンアップ
1. `nvm uninstall v16.14.2` （管理者権限プロンプトで／エラーが出てしまったバージョンを一回消す）
1. `nvm install v16.14.2` （指定バージョンを入れなおす）
1. `nvm use v16.14.2`

といった形で入れ直してから、npmのビルドをかけると解消された模様。

NVMのバージョンアップ後に、使いたいバージョンのNode.jsを入れるのが良さげです。
7回目　ルーター

ルータについて解説します。
![ルータ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2606732/b8b3a89a-d766-236c-d7c4-9dd0290239a4.png)

第一分岐点（ルータそのもの、情報、機能）
第二分岐点（具体例）

### 初めに
ルーターはWAN通しを接続して、複数の端末をインターネットに接続するために必要になります。例えるならば宅配便の営業所で、その店舗の規模、担当エリア、配送でよく使う道路などルータによって異なります。そうして多くのルータ通しがやり取りすることで、データの送受信が可能になっています。ただ単に標識や分岐点というわけでなくWANのIP管理して振り分けるという情報や機能といった役割もあります。


#### ルータによく似た機器
（とは）で検索するとルータを購入する人向けの記事が上位に上がるため解説
モデム：モデムはデジタル信号とアナログ信号を変換する機器、無線LANとかでお世話になる
スイッチ：転送先をMACアドレスを元に選択する（L２スイッチ）
ハブ：LAN配線を分岐して増やすための機器、コンセントのタコ足のいイメージ
![ルータ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2606732/cdd9c249-bac6-2c06-a467-550ed81a408b.png)

#### ルータが持っている情報
ルータはルーティングテーブルと呼ばれる目的地までの最適ルートを書いた地図を表形式のデータとしてもっている。どんな情報が必要かというと「宛先ルート（route）」、「パケット転送先（next hop）」、「出力インターフェース（interface）」などがある。
・宛先ルート（パケットの宛先となるルート）「route」
右か、左か、車道か、歩道か、　かぶらない
「10.0.0.0/8」といった文字であらわされる
・ゲートウェイ（パケットを次に転送する先、最初に送る相手のアドレス）「next hop」
右の交差点か、左の交差点か
「172.16.1.1」といった文字であらわされる　同じ場合がある
・インターフェース（パケットを転送するルーター自身のインタフェース）「interface」
出入りする場所によって速度などが異なる、追い抜き路線か
「eth0」といった文字であらわされる　2～3択
理解ができておらず、例えがこじ付けになっているので申し訳ない。

#### ルータの機能
新しいルートができた際にルータのデータを更新する必要がある。ルートの更新方法は静的ルーティングと動的ルーティングの二つに分けられる。静的ルーティングは管理者が主導で最適なルートを登録する方法、動的ルーティングはルータ同士が情報を交換しあい自動で更新する方法である。

### まとめ
ルーターはWAN通しのデータを送受信するために必要で、宛先へのルートや次の宛先といった情報を持っている。これらの情報はリレー形式で送信先から送信元までの経路がつながっている必要があり、それらを更新するプロトコルなども必要となる。

次回は「ルーティング」について解説する。
CmakeでEmbreeを使う

# CmakeでEmbreeを使うには
備忘録的な記事です

### Embreeとは
Intelが提供しているCPUレイトレーシング向けのソースコード。いわゆる衝突判定の部分を高速でやってくれる。
自作でBVHを作る必要がなくてなおかつかなり高速なので便利

https://www.embree.org/

テストコードなど用意されており結構ドキュメントが豊富
### Cmakeでコンパイルするには
Cmakeを使ってEmbreeを自分のプロジェクトに入れるにはfind_packageを使うだけ

```
find_package(embree 3.0 REQUIRED)
```

この際、find_packageで見つからない場合はたんにcmakeにファイルパスが通ってないのでembree-config.cmakeがあるフォルダーのパスをcmake側に知らせればいいらしい
方法としては、コマンドを打つ際に
```
cmake -Dembree_DIR=embree-config.cmakeのパス ..
```
と付け加えてあげればOK

この辺の詳しい話はExampleの部分で話されているので参照

https://www.embree.org/api.html
[EC2]windowsではsshを使えないと思い込んでいたけどそんなことなかった。

# はじめに

???「その点macってすげぇよな、sshまでターミナルでできるんだもん」

>参考記事

https://www.onebizlife.com/windows10-ssh-client-1980

！？

随分前からデフォルトでsshできるようになってたっぽいです。反省。

# 試しにEC2へSSH接続してみる。

powershellを使ってログインしようと思います。
windows10側の事前準備は特に必要ありません。
適当なec2へログインします。

```
# ssh接続のコマンド
$ ssh -i .\キーペア名.pem ec2-user@ec2のパブリックip
```

成功
![amazon linux2 ami.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2338398/f5a2f98f-d72e-dc17-d4f7-6807158fbf33.png)

青い。

ログアウトするときは`exit`を入力します。

# おわりに
思い込みって恐ろしい。
LinuxサーバにSSHしたくてもできない人へ

## クラウド上のLinuxサーバへSSHしたいけどできない。けどやりたい。

会社のネットワークだとガチガチに縛られてることがある。
だけど「クラウド上のLinuxサーバへSSHしたい！」という人へ。

::: note alert
普通にSSHさせてくれないのには理由があるはずです。
やるなら自己責任で。
:::

このコマンドを叩いたら幸せになれます。

```
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 22
```

### 「このコマンドを叩くためにログインしないとダメだろ」
はい。AWSならSystemsManager使ってください。
それで事足りるなら、無理にiptablesを叩かなくていいと思います。
それでも「Teratermを使って接続したいんだ」という熱い思いがある方はiptableを叩いてください。

OCIなら、、、自宅で細工してからですかね。
コンソール接続で忍び込めそうなら、それで細工してからでもいいかも。
Azureは知らん。GCPも知らん。
個人で三菱UFJの口座情報をAPIで取得しようとしたけど…

# 結論から言うと
[API開発者ポータル](https://developer.portal.bk.mufg.jp/)でアカウント登録、シークレットKeyを発行してもあくまでその時点で登録できるのは体験コースプラン、できることはテストデータへAPI経由でアクセスだけで、本番環境へのアクセスは[三菱UFJダイレクト APIサービス・BizSTATION APIサービス](https://developer.portal.bk.mufg.jp/api_service_directbiz)に留意点に記載されている通りでハードル高い感じでした。
![Screen Shot 2022-04-04 at 14.31.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/c4a53ee3-1bc6-d87f-598a-04a4d1240555.png)
まぁそりゃそうか…

以上、採用系のプロダクトを提供している会社でもろもろ担当する予定のAkibinでした。

# やってみたかったこと
いちいち三菱UFJダイレクトにログインするのが面倒なので、Node.jsかGASで口座残高ぐらいでもとってこれないか思ってました。

# 一応作業内容
1. [API開発者ポータル-アカウント作成](https://developer.register.bk.mufg.jp/#/registration)でアカウント作成
1. [APIキー発行](https://developer.portal.bk.mufg.jp/application)から`クライアントID`と`クライアント・シークレット`を取得（この時点で三菱UFJダイレクトと紐付け的なのないのかな？と思ってました）
1. 作成されたシークレットIDなどの下の方に`配信登録`とあるので、プランを選択する（体験版しかないんですが）<br>![Screen Shot 2022-04-04 at 14.45.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/389ebd4c-af20-c76a-353f-b25da6fb547b.png)<br>![Screen Shot 2022-04-04 at 14.48.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/efa2cb0a-9c79-05db-0716-5f639a8d5307.png)<br>![Screen Shot 2022-04-04 at 14.48.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/f165993a-9152-16f7-e38d-63e5c01df645.png)<br>![Screen Shot 2022-04-04 at 14.50.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/057c9796-96ff-0c15-49ef-57d5312bec6d.png)<br>これでアプリケーションにプランが登録されました
1. これでAPIを試せます。[API](https://developer.portal.bk.mufg.jp/api/retail/accounts_trial_v2)に言語ごとにサンプルコードが用意されており、X-BTMU-Seq-No(YYYYMMDD-16桁英数字)を入れて`操作の呼び出し`を実行するとサンプルデータがjsonで返されます<br>![Screen Shot 2022-04-04 at 14.55.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/142c8380-dd3d-f3ac-4c33-bcbd295dfd3c.png)<br>![Screen Shot 2022-04-04 at 15.32.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/eaa81317-c4e9-1535-0869-4789fc2ca130.png)

ポータルもしっかりできててサンプルもあり、とても使いやすそうな印象です。個人でもどうしてもAPIが使いたいときに申請してみようかな、通るかはしらんが。

# こちらもチェックお願いします！
[Twitterアカウント](https://twitter.com/akibinmusic)
[Youtubeチャンネル](https://www.youtube.com/channel/UC-JOpwEnJn3gCrUA4NdCYgg)
【Windows】Windows標準のアカウントロックの設定とは？

# はじめに
情報システム部門に常駐をしていた際にWindowsのアカウントロックについて調査をしておりました。
その調査の中で分かったWindows標準のアカウントロックの設定について記事を書きたいと思います。

# 前提
Windows10へ設定することが前提になります。

# アカウントロックとは？
Windowsへのログオンを実施する際に、パスワードを複数回間違えた際に一定時間ログインできないようロックする機能になります。

# 設定
Windowsのアカウントロック設定について解説します。

## 設定場所
**1.ファイル名を指定して実行(`Windows+R`)を開き、`gpedit.msc`と入力する。**
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/35364114-e083-8537-6ca8-73185f5eb884.png)

**2.ローカルグループポリシーエディタが表示される。**

以下のフォルダーまで移動する。

`コンピューターの構成 > Windows の設定 > セキュリティの設定 > アカウント ポリシー > アカウントロックアウトのポリシ`

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/7e50a9a4-2b4f-3962-d9be-44729922c21c.png)

## 設定項目
それぞれの設定についての説明は以下になります。

|  設定項目  |  説明  | 備考 |
| ---- | ---- | ---- |
|  アカウントのロックアウトのしきい値  |  失敗できるログオンの回数の設定  | 例)10回ログオンに失敗 |
|  ロックアウトカウンターのリセット  | 失敗したログオンのカウンターを0にリセットされるまでの時間を分単位で設定 | 例)30分後 |
|  ロックアウト期間  | ロックアウトされたユーザーアカウントが自動的にロック解除されるまでのロックアウト期間を分単位で設定  | 例)30分 |

### 例)10回ログオンに失敗した場合に、30分後にロックアウトが解除される設定

![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/96a12e44-b615-1578-9e1b-db3383d7ef87.png)



# 参考記事
[Windows 10 サインイン時にパスワード入力の失敗回数を制限するユーザーアカウントのロックアウト](https://www.billionwallet.com/gpedit/password-fail-lockout-gpedit.html)
【Docker】Docker Desktopで%CPUが100%なってしまうバグ

# はじめに

Docker Desktop の version を上げたら docker の CPU の使用率が 100%近くまで使ってしまうバグが発生しています。

## 環境

- macOS 12.3.1
- Docker Desktop 4.6.1

# 解決法

設定の`Open Docker Dashboard at startup`のチェックを外すことで問題が解決します。
![docker_desktop](https://raw.githubusercontent.com/tomoron/qiita/main/markdown/images/mac_docker_desktop.png)

# 参考

[Github](https://github.com/docker/fozr-mac/issues/6166)