OmniAICreator/Qiita-1.07M huggingface dataset:
トランプカードを並び替え後、任意のカードを探す

**＜アルゴリズム問題シリーズ（Python）＞**

#１．はじめに
同一ファイル内で入力から出力を実施する方法としてはhttps://qiita.com/ajim/items/4d350710ba70056f5f6f を参考にしました。

```py
import sys
import io


_INPUT = """\
5 4
1
3
4
5
"""
sys.stdin = io.StringIO(_INPUT)
```
・`sys`モジュールはインタプリタで使用・管理している変数や、インタプリタの動作に深く関連する関数を定義しています。`sys.stdin`はインタプリタが使用する、それぞれ標準入力、標準出力、および標準エラー出力の ファイルオブジェクト であり、stdin は (input() の呼び出しも含む) すべての対話型入力に使われます。https://docs.python.org/ja/3/library/sys.html
・io モジュールは様々な種類の I/O を扱う Python の主要な機能を提供しています。StringIO オブジェクトはインメモリーのテキストストリームです。
`io.StringIO(initial_value='', newline='\n')`のように使用し、バッファの初期値を initial_value で与えることが出来ます。改行変換を有効にすると、改行コードは write() によってエンコードされます。ストリームはバッファの開始位置に配置されます。https://docs.python.org/ja/3/library/io.html?highlight=io#io.StringIO

#２．問題
・N枚のカードが重ねられていて、上からｔ番目のカードにはｔと書かれている。
・ｔ回目の操作として「一番上のカードを取り除き、それを上からｔ番目にいれる」を行い、これをＮ回実施する。
・上の操作後、ｔ個目の質問として「M_tが書かれたカードは上から何番目？」が聞かれ、その答えをA_tとする。これがK回実施される。
・N,K,Mは全て整数であり、1 <= M_t <= Nである。
この時、K個の質問の答え(A_1．．．A_K)をすべて出力として表示するプログラムを書け。
入力方式はsys.stdinとする。
##入力
```py
 N K
 M_1
 .
 .
 M_K
```
##出力
```py
 A_1
 .
 .
 A_K
 ```
##例
```py
入力
5 4
1
3
4
5
出力
3
5
2
4
```


#３．解答
```py
N,K = map(int,sys.stdin.readline().split())
lines = []    
for i in sys.stdin:
    lines.append(i.rstrip('\r\n'))
lines_int = list((map(int,lines)))   

cards = []
for i in range(1,N+1):
    cards.append(i)
for i in range(N):
    del_card = cards.pop(0)
    cards.insert(i, del_card)
for i in range(K):
    print(cards.index(lines_int[i]) + 1) 
```

#４．実行例
```py
import sys
import io

_INPUT = """\ #入力例
10000 10
1
2
3
4
45
543
756
4657
7333
9999
"""
sys.stdin = io.StringIO(_INPUT)
出力
6384 #１万回の操作後、1と書かれたカードが上から6384番目に存在する
2288
240
4336
1392
7360
2088
8626
4665
9997
```

#５．メモ
**リストから要素を削除する方法**
１．del リスト[インデックス] / del リスト[開始インデックス:終了インデックス]
２．リスト[開始インデックス:終了インデックス] = [] 
３．リスト.pop() / リスト.pop(インデックス) 
４．リスト.remove(値)　
５．リスト.clear()　
https://www.javadrive.jp/python/list/index8.html

**リストに要素を追加する方法**
１．リスト.append([6, 7])  # 要素[6, 7]を末尾に追加
２．リスト.extend([4, 5])  # リストの要素を末尾に追加
　　リスト.extend(6)  # TypeError
３．extendメソッドではリスト以外の反復可能オブジェクトもリスト末尾に追加できる。リスト.extend((3, 4))  # タプルの要素がリスト末尾に追加される
４．リスト.insert(5, [3.25, 3.5])  # 第2引数に指定した値は単一の要素として挿入される。　
print(リスト)  # [0, 1, 2, 2.5, 3, [3.25, 3.5], 4]
https://www.atmarkit.co.jp/ait/articles/2012/11/news015.html

#６．参考文献
https://docs.python.org/ja/3/library/sys.html

https://docs.python.org/ja/3/library/io.html?highlight=io#io.StringIO

https://qiita.com/Ma_AtoP/items/63ec026b3b373b7f84c1

https://qiita.com/ajim/items/4d350710ba70056f5f6f

https://www.javadrive.jp/python/list/index8.html

https://www.atmarkit.co.jp/ait/articles/2012/11/news015.html
#７．ご意見・ご感想をお待ちしております
当方、未熟なプログラマーのため、よりよいコード等ありましたら教えていただけると幸いです。
皆様のメッセージをお待ちしております。
全角チルダ？波ダッシュ？に殺された記録

# 事件はAndroidの文字入力で起きました．

## PCとスマホで入力文字の挙動が違う

依頼を受けてブラウザ上で縦書き画像を簡単に作れるサービスを開発していました．

textareaから文字の入力を受けて，それをcanvas上にjavascriptで縦書き文字として描画するっていうシンプルなロジックのものでした．

Reactをベースにして，特にこれと言ったライブラリは一切使っていませんでした．
![TankeGen_202164143934.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209490/0b67f428-5ebd-b967-1108-2f3dd9cce381.png)

### 事件はそのとき起きました

依頼者の方から，
「～が横のままになってるのでそこだけ修正お願いします～！」
と連絡がきました．

これはまずいと思い，急いでPCから修正を行おうと思いましたが・・・

![TankeGen_202164144122.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209490/ffd445b8-415f-a6e0-45a9-b31985c334fd.png)

### まったく縦のままでした・・・．

いやいや依頼者の方,なんの文字を入力したんだと思いその環境を聞くと

「スマホのChromeです～！」

とのこと．ふむふむなるほどと思い私もスマホのchromeで確認すると

![216570.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209490/67e32856-00bd-d171-d8a2-4d3d8b2312da.jpeg)

### あああああああああああああああああああああああああああああああああああああああああ（断末魔）

はい，PCとスマホで挙動が違うじゃありませんか．

## 検証

原因はなんとなく推測がつきます．

### 文字コード

これしかないやろと．

ということでtextareaで受け取った文字を比較しました．

```javascript
encodeURIComponent(input)
```

### 結果

PC
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209490/b638e7d1-7e19-e375-3a48-cce5ed395814.png)

スマホ
![216571.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209490/44e2c427-27c8-ad6f-24c3-91433c48b076.jpeg)

### やった！原因合ってた！！！！！！！！

### あああああああああああああああああああああああああああああああああああああああ（断末魔）

## 修正

文字をそのまま比較していたところを文字情報で比較することにしました


```javascript
// 修正前
if(ch === "～"){
//
}

//修正後
if(["%EF%BD%9E","%E3%80%9C"].includes(encodeURIComponent(ch)){
//
}
```

## 結果

スマホ

![216573.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209490/d4c159c7-cd2d-eafc-b666-5963bdc02925.jpeg)

### GG
Railsで架空のCafeのHPを作ってみよう!【13日目】『f.text_areaの値を改行、空白含めそのまま反映』編

#概要
基本Railsの記法に則り書いていきます！
１から全ての説明ではなく
その中であれ？どうやるの？と
疑問に思った点や実装に困った箇所を
ピックアップして紹介していきます♩

#設定と準備
・Rails
・HTML
・CSS
・Javascript(jQuery)

↑上記の言語とフレームワークを使い
架空(自分で考えたテキトーなもの)のCafeの
HPを作っていこうと思います！

#13日目の作業内容:round_pushpin:
・ビューの作成(一覧ページ)

#13日目の気になった箇所:zap:
f.text_areaで入力された値をそのまま反映したいが
どのようにすれば良いだろうか。

#仮説:pushpin:
調べたらrailsのヘルパーメソッドである
simple_formatや
safe_joinなどを使うと
表示できるらしい。

testsテーブルのsampleというカラムに保存させて反映させていくとします。

```tests/new.html.erb
<%= f.text_area :sample %>
```
まずは入力フォームを作成。

```
入力例)
sample
 sample

   sample
```

上記のように文字の前に空白や改行を適当に入力したとします。

```tests_controller.erb
def show
  @test = Test.find(params[:id])
end
```

コントローラでインスタンス変数に格納し使えるようにします。

```tests/show.html.erb
<%= @test.sample %>
```

これで反映はされれるが

```
sample sample sample
```

このように表示されてしまいうまく表示できない。

ではここにヘルパーメソッドを使い検証していきます。

```tests/show.html.erb
<%= simple_fomat(@test.sample) %>
```

```tests/show.html.erb
<%= safe_join(@test.sample) %>
```

どちらもエラーが出てしまいうまくいかなかった。


#結論:star:
上記で検証したsimple_fomatやsafe_joinでも
うまく反映させることが可能だと思いますが
今回は私がうまくいった方法を紹介します。

上記と同じものを使うと仮定するので入力フォームなどは割愛させていただきます。

では、同じようにように表示させていきます。

```tests/show.html.erb
<p><%= @test.sample %></p>
```
表示させたい値をpタグで囲っていきます。

今回はpタグで囲いましたがクラス名を付与でも可能です。↓

```tests/show.html.erb
例)
<%= @test.sample, class:"text" %>
```

次にこのpタグ(もしくは付与したクラス名)に
CSSを当てていきたいと思います。

```show.css
p {
  white-space: pre-wrap;
}

/* クラス名の場合 */

.text {
  white-space: pre-wrap;
}
```

たったこれだけで空白、改行全て反映してくれます！
このwhite_spaceというプロパティは要素内の空白をどのように
扱うかを指定するものです。
今回はpre-wrapを指定しましたが、他にも

要素を詰めて空白を作らない
改行はするが最初の空白は作らない　など

用途に合わせて使えると思いますので、気になったら調べてみてください！
【自分用】Git branchのコマンド

・branchの作成
$ git branch feature/(機能やクラス名)

・現在のbranchの確認
$ git branch

・branchの切り替え
$ git switch (branch名)

・branchの作成と切り替えを同時に行う場合
$ git switch -c feature/(機能やクラス名)


＊メモ
・$ git branchで今どこのブランチを操作しているか常に確認する
MS Learn の勉強5･･･「カスタム列を作成する」

[<前の備忘録](https://qiita.com/max_kamitoda/items/25700e7d863674fba55c)

どのように勉強したかの備忘録です。

https://docs.microsoft.com/ja-jp/learn/modules/create-measures-dax-power-bi/1-introduction

**Power BI でカスタム列を作成するには、次の 3 つの方法があります。**

この段落がカスタム列を作成する方法を説明しようとしていることは理解できた。
しかしちょっと待って欲しい。
そのカスタム列を作成する目的が提示されていないにもかかわらず、その作成手法を解説するのは早計に過ぎないか。

どこかで聞いたようなフレーズが頭に浮かびました。
これは初心者殺しだ(笑)。

>
1. **データを取得するときに、ソース クエリで列を作成する。**(たとえば、リレーショナル データベースのビューに計算を追加する。)
- **Power Query でカスタム列を作成する。**
- **Power BI で DAX を使用して計算列を作成する。**

この界隈の強者には自明のことなのかもしれませんが、私には前章の「計算列を使用する」から内容が飛躍しすぎているように感じて、当初理解が出来ませんでした。

俺、舘、カスタム･･･違いますね。

カスタムとは特別仕様、あつらえといった意味を持ちますが、特別仕様の列ということですかね？

”通常⇔特別” という関係を考えると、どうやら実存列と計算列の関係がありそうな気がしてきました。

**＞3.Power BI で DAX を使用して計算列を作成する。**

↑ は前回勉強したので何を言っているのかわかります。

**＞2.Power Query でカスタム列を作成する。**

ですが、これは･･･？
Power BI だけではなく、Excel にもある機能ですね。
Power Query でカスタム列を作成できることは知っていましたが、DAX の勉強をしているときに唐突に出てきたので混乱しました。
あれのことだったのですね。

**＞1.データを取得するときに、ソース クエリで列を作成する。(たとえば、リレーショナル データベースのビューに計算を追加する。)**

最後はこれです。
ははぁん、ここまでで何を言いたかったのか朧気ですが、わかってきたような気がします。
今自分が ユーザ というマスにいて、向こうの方に データ（ベース） のマスがあるとします。
そしてその間に Power BI のマスがあって、そのマスの中に PQ と DAX の小さいマスがあります。
それらのマスのどこで生データを加工して「計算した列」を作成するかという**段取り**の話題のようですね。
自分なりのイメージを図にしてみました。
![イメージ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195544/9a4553b3-f158-1393-a2a4-34daedba127e.png)

"Imaginary Column" とでも言うべきものを作成する段階によって、手段と呼称が異なる。
　1.データベース･･･SQL、列
　2.PowerQuery･･･M言語、カスタム列
　3.PowerBI･･･DAX、計算列

**＞一般に、列の作成が早ければ早いほど良い結果を得られます。 別のメカニズムを使用できる場合は、計算に DAX を使用することは最適な方法とは見なされません。**

つまるところ、"Imaginary Column" とでも言うべきものを、どの段階で作るか（作っておくか）で、結果を得るまでに必要となるリソース(時間、メモリ等)に差が出るので、建付けをよく考えてねということのようです。

建付けで思い出しましたが、別業界の似た例を挙げるとすれば、このような感じでしょうか。
[東洋経済ONLINE：家造りから｢大工｣が消える？効率化の光と影](https://toyokeizai.net/articles/-/217531)

**また、計算列の使用を回避する方法の 1 つは、SUMX、COUNTX、MINX などの X 関数のいずれかを使うことです。 X 関数はこのモジュールの範囲を超えていますが、これを使用すると、個々の行のデータを認識するメジャーを作成し、行の合計に基づいて合計を計算することができます。 これらの関数はメジャー内で使用されますが、個々の行を反復処理して計算を行うため、反復関数と呼ばれます。 X 関数は、計算列よりもパフォーマンスに優れ、使用するディスク領域が少なくなります。 X 関数の詳細については、[Microsoft のドキュメント](https://docs.microsoft.com/ja-jp/dax/sumx-function-dax)をご覧ください。**

もっといい方法もあるから、そっちも勉強してねとマイクロソフトが言ってますので、後ほどジョジョに勉強することにします。

今回はここまで。
【Drupal】CKEditorの設定モジュールの作成

コンテンツ登録の際に、CKEditorのフィールドタイプを使用した場合に例えばspanの空タグを入力すると消去されます。
空タグを許可するために、CKEditorの設定モジュールを作成したので備忘録として残しておきます。（コントリビュートモジュールでCKEditorの設定モジュールは転がっていると思いますが）

モジュールのディレクトリ名は**「ckeditor_custom_setting」**としておきます。

### MY_MODULE.info.yml
```modules/custom/ckeditor_custom_setting/ckeditor_custom_setting.info.yml
name: CKEditor Custom Setting
description: CKEditorのカスタム設定を有効化します。
type: module
core: 8.x
core_version_requirement: ^8 || ^9
package: Custom
```
### MY_MODULE.info.module
**[hook_editor_js_settings_alter](https://api.drupal.org/api/drupal/core%21modules%21editor%21editor.api.php/function/hook_editor_js_settings_alter/9.1.x)**を利用します。

```php:modules/custom/ckeditor_custom_setting/ckeditor_custom_setting.module
<?php

function ckeditor_custom_setting_editor_js_settings_alter(array &$settings) {
  foreach (array_keys($settings['editor']['formats']) as $text_format_id) {
    if ($settings['editor']['formats'][$text_format_id]['editor'] === 'ckeditor') {
      $settings['editor']['formats'][$text_format_id]['editorSettings']['customConfig'] = base_path(). drupal_get_path('module', 'ckeditor_custom_setting'). '/config.js';
    }
  }
}
```
### config.js
設定用のjsファイルを作成する。

```Javascript:modules/custom/ckeditor_custom_setting/config.js
CKEDITOR.editorConfig = function( config ) {
  config.fillEmptyBlocks = false;
  config.allowedContent = true;
  config.autoParagraph = false;
 
  // 空のspanタグを許可
  CKEDITOR.dtd.$removeEmpty.span = 0;

  // 他に例えばh2タグをaタグで囲いたい時は以下のように記す
  CKEDITOR.dtd['a']['h2'] = 1;
};
```
論理演算とは何か

# はじめに
基本情報技術者の書籍を読み進めていて、ずっとインプットばかりではよくないと思い記事にしてまとめてみようと思いました。基本的なことを書くので物足りないところもあるかと思いますが読んでいただけると嬉しいです。


# 論理演算とは
ます、論理演算というのは簡単にいうと真の値(条件が成立する場合)と偽の値(条件が成立しない場合)の二つの値を使って行う演算のことです。2進数の1(真)か0(偽)の入力値に対して一つの値を出力します。学生のときに「ベン図」というのを習ったことがある方も多いと思います。
こういう図ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1403010/71f72d05-31c3-df0d-a89b-33c2bd1ef20e.png)

Aに一致するグループ(Aが真)とBに一致するグループ(Bが真)、AとBのどちらのグループにもなっていない値など、様々なことを視覚的に表すことができる非常に便利な図ですね。まさにこれが論理演算です。


# 論理積(AND)
論理積(AND)では、二つの条件の両方が合致する場合に真となります。
ANDを「かつ」と考えていただければ大丈夫です。
Aの値が１(真)でBの値も１(真)の場合に真(1)になります。Aが０(偽)でBが1(真)の演算結果は0(偽)になります。


# 論理和(OR)
論理和では、二つの条件のいずれかが合致する場合に真となります。
ORは「または」と訳して考えます。演算する値のどちらか一方が1(真)なら真になります。
つまり、「AまたはBが真なら結果は真」ということになります。

# 否定(NOT)
否定(NOT)では、ある条件の「合致しない」ものを真とします。これは一つの値に対して行う演算です。
一つの値が反転します。例えば２進数の場合は1と0しかないので1なら0に、0なら1にするということです。

# 排他的論理和(XOR)
これは、OR演算と似ていますが少し異なります。
演算する値の両方が1(真)なら結果が0になります。両方が0でも結果が0になります。
Aが1(真)でBが０(偽)のときに1(真)になります。演算する値が同じなのを嫌うというイメージですね。

# 参考文献
[キタミ式イラストIT塾　基本情報技術者　令和03年](https://gihyo.jp/book/2020/978-4-297-11781-8)
【個人用メモ】Nuxt.jsでFirebaseAuth認証と連携したAPIサーバとの通信にaxiosを使う

# 概要

Nuxt.js で API サーバーへアクセスするとき、自分は plugins ディレクトリにラッパーを作ってアクセスしている。その時、Bearer トークン等もまとめて渡せるように実装して使いまわしているので、ここでメモをしておく。(かなり雑なので個人用メモとして投稿)

# 条件

- Content-Type は application/json と multipart/form-data に限定
- APIサーバURLは https://example.org/v1/example の形になる (v1部分は変更可能)
- HTTPヘッダで Firebase の idToken を Bearer トークンの形で送信
- エンドポイントは環境変数に保存している (cross-envを利用)

# axios側の実装

plugins ディレクトリに実装する。

```rest_gateway.js
import axios from 'axios'

// URIやHeadersは固定なのでここでaxiosをラップする
export default class {
  constructor(path, params, idToken, allowStatus = null, version='v1') {
    this.uri = process.env.apiEndpoint + version + '/' + path;
    this.params = params;
    this.headers = {
      'Content-Type': 'application/json',
      Authorization: 'Bearer ' + idToken
    }

    this.validateStatus = (status) => {
      const normal = status >= 200 && status < 300;
      if (allowStatus === null) return normal;
      return normal || status === allowStatus;
    }
  }

  get() {
    return axios.request({
      method: 'get',
      url: this.uri,
      params: this.params,
      headers: this.headers,
      validateStatus: this.validateStatus
    })
  }

  post() {
    return axios.request({
      method: 'post',
      url: this.uri,
      data: this.params,
      headers: this.headers,
      validateStatus: this.validateStatus
    })
  }

  put() {
    return axios.request({
      method: 'put',
      url: this.uri,
      data: this.params,
      headers: this.headers,
      validateStatus: this.validateStatus
    })
  }

  delete() {
    return axios.request({
      method: 'delete',
      url: this.uri,
      data: this.params,
      headers: this.headers,
      validateStatus: this.validateStatus
    })
  }

  postForm() {
    this.headers['Content-Type'] = 'multipart/form-data'
    return this.post()
  }

  putForm() {
    this.headers['Content-Type'] = 'multipart/form-data'
    return this.put()
  }
}
```

# ラッパー利用側の実装

```js
import RestGateway from '@/plugins/rest_gateway'
// ...
 try {
    const idToken = await firebase.auth().currentUser.getIdToken(true);
    const response = await new RestGateway('<path>', {param1: value1, params2: value2}, idToken).get();
    console.log(response.data.key);
  } catch (error) {
    if (error.response) {
      // 200以外の処理はここで行う (例として403を用いている)
      if (error.response.status === 403) { }
    }
    // それ以外の場合のエラー
    window.alert("エラーが発生しました: " + error);
    console.error(error);
  }
```
絵文字などで使うゼロ幅接合子を Vim と echo で置換する方法

絵文字なんかで使われる「ゼロ幅接合子」U+200D を含む文字列を置換したりしたときに使ったことの覚書。

# Vim で置換する
Vim で検索する場合は `\%u200d` で表現する。
Ex モードで置換する場合の例は以下のような感じ。

```sed
# 「[任意の絵文字👮]<200d>♂」な文字列を 「[任意の絵文字👮]<200d>♂️」に置換
:%s/\([^\x01-\x7e]*\)\%u200d♂/\1\%u200d♂️/gc
```

## 簡単な説明

```sed
\%u200d # Vim における U+200D の表現
[^\x01-\x7e] # 任意の 2 バイト文字
```

## Vim だけじゃ駄目だった。
Vim を使って上記のように `\%u200d` に置換すると単に `u200d` という文字列になって「ゼロ幅結合子」にならなかったので、`echo` コマンドを使って `sed` で置換します。

```sh
sed -i "s/u200d/$(echo -ne '\u200d')/g" file.txt
```

# 参考資料
* [Removing special characters(<200c> <200d> from a text file - stack overflow](https://stackoverflow.com/questions/9257103/removing-special-characters200c-200d-from-a-text-file)
* [正規表現がわからないから見たいリンク集 - Qiita](https://qiita.com/ponsuke0531/items/64f6a180a4b699336096)
メモ：データサイエンス100本ノック（構造化データ加工編）

# はじめに
勉強のためデータサイエンス100本ノックを遂行中。

https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess

環境設定は下記を参考にしました。

[Macでデータサイエンス100本ノックを動かす方法](https://qiita.com/karaage0703/items/1b18b1f4ab65d35afb5f)

# 動作環境
macOS Catalina 10.15.7

# 途中経過

![スクリーンショット 2021-07-29 13.33.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1123801/df1b61ab-9833-0233-3066-24287e2d4e8a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1123801/b33fe107-f5ec-6128-489f-e4d93d72d923.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1123801/1cfb3767-a8e6-6858-ea8a-48b5a667508f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1123801/3b8c8984-f430-1276-e7a4-0a30e1dd2638.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1123801/42e844d6-6cfb-4476-84db-f15317304e0c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1123801/c06dd9f7-59b2-e353-6045-9635dbceef73.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1123801/e7f02b80-98ec-6338-08c4-3bd36f2a2937.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1123801/a7ddbdd7-5dd9-1579-1b8f-a96f4c091fd5.png)
PHPでメモリを使いすぎてたらアラート飛ばす

php.iniのmemory_limitの設定値以上のメモリを使用した場合、
『Fatal error : Allowed memory size of ...』のエラーになってしまいますが、
エラー発生の兆候をキャッチしておくことで、事前に対応を入れることができます。

今回はregister_shutdown_functionを利用して、
メモリ使用量がmemory_limit値に近い場合はアラートを飛ばす簡単な例を紹介します。


```php
function checkMemory() {
	// memory_limit値を取得
	$limit = ini_get('memory_limit');

	// 設定値は『128M』のような文字列なので、数値と単位に分ける
	// 『128.8A』など、小数だったり不正な単位が付いてたりする場合も、とにかくint型にキャストされる
	$byte = (int) $limit;
	$unit = strtoupper(substr($limit, -1));

	// 数値と単位からバイト数を算出
	switch ($unit) {
	case 'G':
		$byte *= 1024;
	case 'M':
		$byte *= 1024;
	case 'K':
		$byte *= 1024;
	}

	// memory_limitの下限値が存在しているため、下限値未満は下限値が自動的に割り当てられる
	// マイナス値はmemory_limit無制限になるため下限値を割り当てない
	// PHP8=2M PHP7=2M PHP5=256K
	$min = 2 * 1024 * 1024;
	if (0 <= $byte && $byte < $min) {
		$byte = $min;
	}

	// memory_get_peak_usageはPHPによって割り当てられたメモリの最大値
	// その最大値がmemory_limit値の90％を超えていたらアラート飛ばす
	if (memory_get_peak_usage() / $byte > 0.9) {
		// ログ残す、メール飛ばす、などお好みの処理を
	}
}
register_shutdown_function(function () {
	checkMemory();
});
```

スクリプト内でmemory_limitを一時的に変更しているような場合は少し工夫が必要になります。

何かのお役にたれれば幸いです。
Adobe Acrobat Reader DCで上書き保存できるようにする

アクロバットリーダーでPDFを開き、注釈等を入れた後に保存する際に上書き保存しようとすると、「名前を付けて保存」が開き大変不便ですが、下記の設定で「上書き保存」ができるようになります。

Ctrl+Kで環境設定を開く

「起動時に保護モードを有効にする」のチェックを外して「OK」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532979/66bcc993-8c80-8011-d126-301b519ccfdc.png)

再起動すると、注釈等を入れても「Ctrl+S」で上書き保存できるようになります。
ansibleでsymantec endpoint protectionのfirewallの設定をする

ansibleのwin_firewall_ruleモジュールでは、symantec endpoint protection(以降SEP)でファイアウォールを管理している環境への設定はできなかったので、調べてやってみた。

以下のような感じでやったらできた

```
---
- name: Export current firewall rule
  win_command: '"C:\Program Files (x86)\Symantec\Symantec Endpoint Protection\smc.exe" -exportadvrule {{ temp_dir }}\firewall_rule.xml'

- name: edit firewall rule
  win_xml:
    path: '{{ temp_dir }}\firewall_rule.xml'
    xpath: '/AdvancedRules'
    type: element
    fragment: '<AdvancedRule EnableTimeGroup="0" Description="My Service" RuleEnabled="1"><Services><RawTcp LocalPort="30000,30001"/></Services>
<ActionGroup><Action Enable="1" LogEvent="1" LogRawTraffic="0" PacketProcess="PASS"/></ActionGroup></AdvancedRule>'

- name: Import firewall rule
  win_command: '"C:\Program Files (x86)\Symantec\Symantec Endpoint Protection\smc.exe" -importadvrule {{ temp_dir }}\firewall_rule.xml'
```

### ポイント１: SEPのコマンドライン操作

コマンドライン操作があるか探して、以下を見つけた。
https://techdocs.broadcom.com/jp/ja/symantec-security-software/endpoint-security-and-management/endpoint-protection/all/appendices/windows-commands-for-the-endpoint-protection-clien-v9567615-d19e6200.html

```smc -exportadvrule``` コマンドでfirewallの設定をxml形式のファイルでexportでき、
```smc -importadvrule``` コマンドでfirewallの設定をimportできるとのこと。

importのコマンドでは、import対象のファイルに書いていないルールは削除される挙動をした。
なので、追加したいルールだけではなく、既存のルールも書いておかないといけない。

### ポイント２：xml操作
exportしたfirewall ruleのファイルに、追加したいルールを記述する。
ansibleには、win_xmlモジュールというものがあって、それでxmlファイルを編集できる。
https://docs.ansible.com/ansible/latest/collections/community/windows/win_xml_module.html

今回は単純に要素を追加しただけ。
冪等性が確保できてなくて、複数回実行すると同じルールが複数できてしまう。。。
冪等性を確保するためには、もう少し書き方の工夫が必要
CBL-MarinerのインストールISOのビルド手順

#0.初めに
2021/07/29時点でやってみた内容です。

CBL-Marinerのインストール手順ではなく
インストールISOをビルドする手順です。

#1.ビルド環境

Ubuntu 20.04でビルドします。

※Dockerなどのコンテナ環境は不可
※WSL環境の場合はWSL2で動作していること(WSL1環境は不可)

#2.ビルドに必要なパッケージをインストール
~~~
$ sudo apt update -y
$ sudo apt upgrade -y
$ sudo apt install -y make tar wget curl rpm qemu-utils golang-go genisoimage python2-minimal bison gawk
~~~
#3.ビルドに必要なファイルのダウンロードと展開
~~~
$ mkdir ~/src
$ cd ~/src
$ wget https://github.com/microsoft/CBL-Mariner/archive/refs/tags/1.0.20210628-1.0.tar.gz
$ tar zxf 1.0.20210628-1.0.tar.gz
~~~

#4.ビルド
~~~
$ cd ~/src/CBL-Mariner-1.0.20210628-1.0/toolkit
$ sudo make iso REBUILD_TOOLS=y REBUILD_PACKAGES=n CONFIG_FILE=./imageconfigs/full.json
~~~

#5.ビルドされたインストールISOの場所
~~~
~/src/CBL-Mariner-1.0.20210628-1.0/out/images/full/full-1.0.20210729.0613.iso
~~~
PowerShell で Exchange Online の全ユーザーの予定表の既定の共有権限を「参照者」にする

ユーザーのスケジュール内容をデフォルトで公開にする。

```powershell
Get-Mailbox|
foreach {Get-MailboxFolderPermission -User "既定" -Identity ($_.Identity + ":\予定表") }|
Where-Object{$_.AccessRights -notlike '*Reviewer*'}|
foreach {Set-MailboxFolderPermission -User "既定" -Identity $_.Identity -AccessRights Reviewer}
```

※ ユーザーの言語が日本語でないと変更されないので事前に言語を日本語にしておく必要があります。
[Powershell で Exchange Online の全ユーザーのメールボックスの言語設定を日本語に変える](https://qiita.com/panda7461@github/items/51c86a14256acbcc4802)
CloudFormationのスタックで, SecretsManagerからインポートする値をImportValueなどで解決する

# はじめに

SecretsManagerのシークレット名はstackでリソース作成時に自動生成していたのですが, いざその値を使いたいときにどうかけば良いか少しかかったので

## 解決

ImportValueの場合, JoinしながらImportValueを組み込めば終わります.

```yaml
Parameters:
  TestParameter:
    Default: test-secret
    Type: String

HogehogeSecretKey:
  Fn::Join:
    - ""
    - - "{{resolve:secretsmanager:"
      - !ImportValue ExampleSecret
      - ":SecretString:SecretKey}}"

SubSample: !Sub "{{resolve:secretsmanager:${TestParameter}:SecretString:hoge}}"
```

## 注意点

逆のこと (resolveした値からRefなど)はできません

```yaml
Parameters:
  MyParameter:
    Default: my-parameter-value
    Type: String

Resources:
  SampleLambda:
    Type: AWS::Lambda::Function
    Properties:
      # ...
      Environment:
        Variables:
          # MyParameterの値をRefしたいがエラー
          RefSample: !Ref "{{resolve:secretsmanager:test-secret:SecretString:paramname}}"
```

必ず, 組み込み関数の処理後にresolveが行われます.

## まとめ

パラメータストアなどでもですが, 利用の幅が広がりますね
REST APIとは

# REST API　とは
　
1 ***情報の操作は全てHTTPメソッド（CRUD処理）で行われる。***

|CRUD 処理の種類|controller_methods|
|-----|-------|
|Create|Create|
|Read|indexとshow|
|Update|update|
|Delete| destroy|



2 ***URI(URL)を読むだけで『何のリソース』に『　どのような処理』をするのかわかる。***
***ここではURLはarticles***にする
***『何のリソース』は/articlesかarticles/:id***
***どのような処理はHTTP method***

|CRUD 処理の種類|HTTP　method |URL  Pattern | controller_methods |
|---|----|--|--|
|Create|POST|POST /articles|create|
|Read|GET|GET /articles|index|
|Read|GET|GET /articles/:id|show|　　　        ​              
|Update|PUT PATCH|PUT or PATCH/articles/:id| update|
|Delete|DELETE|DELETE/articles/:id| destroy |
                                    
                                        

# 有益な動画

https://www.youtube.com/watch?v=rEGmSRZ-dWY

https://www.youtube.com/watch?v=6_zIN-bByB4
MS Learn の勉強4･･･「計算列を使用する」その2

[<前の備忘録](https://qiita.com/max_kamitoda/items/5763c081485f7a969d51)

どのように勉強したかの備忘録です。

https://docs.microsoft.com/ja-jp/learn/modules/create-measures-dax-power-bi/1-introduction

**たとえば、販売取引を含むデータベースからデータをインポートするとします。 個々の販売取引には、次の列が含まれます:Order ID、Product ID、Quantity、Unit Price。各注文の売上合計を表す列は存在していないことがわかります。**

**＞データベースからデータをインポート**
インポートされたデータはデータベースにあるそうなので、全て「実存列」と扱えそうです。
>
- 注文番号 ( Order ID )
- 製品番号 ( Products ID )
- 商品数 ( Quantity )
- 単価 ( Unit Price )

**＞各注文の売上合計を表す列は存在していないことがわかります。**
「押すなよ、絶対押すなよ。」ですね、わかります。
次の「列」がうっすらと見えるような気がしてきました。
>
- 売上合計 ( Total Price )

**単価と数量を乗算する計算列を作成することで、DAX の使用を開始できます。 この計算列によって、行ごとに "Total Price" という値が作成されます。 新しい列を作成するには、[フィールド] の一覧からテーブルの省略記号 ([...]) ボタンを選択し、[新しい列] を選択します。**

新しい列を作成する指示をポチっと･･･。

**上部のリボンの下の数式バーに、新しい DAX 式が表示されます。**
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195544/246defa2-e614-2f45-61e8-ca9f96732470.png)

これって Excel ･･･だよね。

**既定のテキスト "Column =" を、次のテキストの例に置き換えることができます。**

*Total Price = 'Sales OrderDetails'[Quantity] * 'Sales OrderDetails'[Unit Price]*

**等号の左側にある値は、列名です。 等号の右側にあるテキストは、DAX 式です。 このシンプルな DAX 式では、個々の行について数量の値を取得し、単価の値と乗算します。**

なんと、上式の左辺は列の名前、右辺はその計算根拠だそうです。
読み解くと、こんな感じでしょうか。

売上合計(の列) = 販売受注詳細テーブルの商品数列 × 販売受注詳細テーブルの単価列

Excel では**セル単位**で計算式を埋め込む操作をしていました。
しかし、DAX では**列単位**でそれを行うようです。
これは処理したいことが膨大にある人にとってはありがたい機能だと思います。

**テーブル内のレコードごとに 1 つの値が生成されます。 [フィールド] の一覧から視覚エフェクトに新しい列をドラッグすると、新しい値が表示されます。**

**＞テーブル内のレコードごとに 1 つの値が生成**
なんだか怖いことをサラッと述べておられますが･･･。

**計算列は、Power BI ファイル拡張子 .pbix で具体化されます。つまり、計算列を追加するたびに、ファイル全体のサイズが大きくなります。 計算列が多すぎると、パフォーマンスが低下し、Power BI の最大ファイル サイズにより早く到達してしまいます。**

**＞計算列が多すぎると、パフォーマンスが低下**
なるほど、用法・容量を守ってお使いくださいとはこのことだったのですね。
Excel でいうと、関数が埋め込まれたセルが多いと再計算に時間がかかって困るような状態ですな。
ということは、Excel は実存セルと計算セルの組み合わせ、Power BI は実存列と計算列
の組み合わせとでも言えるのかもしれません。

一つ言えることは、『メモリを、我により多くのメモリを！』です。

今回はここまで。
3.10(標準) 対数正規分布

## 答案

Xの期待値は，

```math
\begin{align}
\mathbb{E}_{X\sim f_X}[X]&= \int_0^\infty\frac{1}{\sqrt{2\pi}}\exp\{-\frac{(\log x)^2}{2}\}dx\tag{1}
\end{align}
```

t=log xと置換すると，

```math
\begin{align}
(1)&= \int_{-\infty}^\infty \frac{1}{\sqrt{2\pi}}\exp(-\frac{t^2}{2}+t)dt\\
&= \int_{-\infty}^\infty\frac{1}{\sqrt{2\pi}}\exp\{-\frac{(t-1)^2}{2}+\frac{1}{2}\}dt\\
&= e^{1/2}
\end{align}
```


分散は，

```math
\begin{align}
\mathbb{E}_{X\sim f_X}[X^2]&= \int_0^\infty\frac{x}{\sqrt{2\pi}}\exp\{-\frac{(\log x)^2}{2}\}dx\tag{2}
\end{align}
```

t=log xと置換すると，

```math
\begin{align}
(2)&= \int_{-\infty}^\infty\frac{1}{\sqrt{2\pi}}\exp(-\frac{t^2}{2}+2t)dt\\
&= \int_{-\infty}^\infty\frac{1}{\sqrt{2\pi}}\exp\{-\frac{(t-2)^2}{2}+2\}dt\\
&= e^2\\
Var(X)&= e^2-e=e
\end{align}
```

次に，Y=logXなる変換を考える．

```math
\begin{align}
P[Y\leq y]&= P[\log X\leq y]\\
&= P[X\leq e^y]\\
&= \int_0^{e^y}f_X(x)dx
\end{align}
```

なので，

```math
\begin{align}
f_Y(y)&= f_X(e^y)\frac{de^y}{dy}\\
&= \frac{1}{\sqrt{2\pi}}\exp\{\frac{-(\log e^y)^2}{2}+y\}\\
&= \frac{1}{\sqrt{2\pi}}\exp(-\frac{y^2}{2})
\end{align}
```

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
コンテナの中で操作できちゃうECS Execの使い方

#はじめに
Fargateを使って、コンテナの中から色々操作したい（特に開発環境）時に使えるのがECS Execです。
入れたらめっちゃ便利になったので備忘録的に残しておきます。

#結論
これ読んでください。すごくわかりやすく書いてあります。
[[アップデート] 実行中のコンテナに乗り込んでコマンドを実行できる「ECS Exec」が公開されました](https://dev.classmethod.jp/articles/ecs-exec/)

ただ、ちょっとだけつまったところをメモしておきます。

- AWS CLIを最新バージョンにしておく（ECS Execのコマンドが入ってるバージョンであれば良いです）
- ECS TaskExecRoleじゃなくてTaskRoleにポリシー付与（なんかごっちゃになったので）
- aws ecs update-serviceを使うときは、自分のconfigのリージョンが東京の可能性あるので、--region ap-northeast-3っていうオプションつける（これはこれに限った話じゃないですが、デフォルトのコンフィグと違うリージョンで使う場合にはリージョンの指定が必要です）
- コマンドはbin/shじゃなくてshだけ（これは多分dockerイメージ的にそうしないといけないだけだと思うからイメージによりそう）
- session-manager-pluginっていうのをローカルにインストール必要

最終的なコマンドは

```
aws ecs execute-command \
    --cluster cluster-name \
    --task task-name \
    --container container-name \
    --interactive \
    --command "sh" \
    --region region-name
```

これでコンテナの中で操作できると思います！

# まとめ
めっちゃ便利
【IQ Bot】カスタムロジック：選択肢の中からもっとも近いものを答えとする（IQ Bot Helper - fuzzy match）

# このページで解説すること

IQ Botで、正解の選択肢が決まっている読取項目に対して、「OCRの読み取り結果を選択肢の中で最も近いものに寄せたい！」という場合に使えるロジックです

なお、このページに書いてある方法が使えるのは、Automation360.21以降に付随するIQ Botのみです。

# こんなときに便利

例えば「決済方法」という項目で、正解が「代引」「銀行振込」「クレジット」のいずれかに決まっているとします。

OCRの読み取り結果は、正解を正しく読めるかもしれないし、「クレジツト」（ツが大文字）などのように微妙に誤読をするかもしれない。

でも、「クレジツト」は３つの正解の中では明らかに「クレジット」に近いので、結果をそれに寄せたい！　というときに使えます。

# ズバリこうやります

フィールド項目の場合は、ズバリこうやります。

```python:選択肢の中から最も近いものを答えとする

import IQBotHelper as iq

matchList = ("代引","銀行振込","クレジット")  #カスタム部分①

maxRatio = 0
currentRatio = 0
result = ""

for i in matchList:
  currentRatio = iq.fuzzy_match (field_value, i, ratio = True)
  if currentRatio >= 0.5:  #カスタム部分②
    if currentRatio > maxRatio:
      result = i

field_value = result

```

コメントで記載した「カスタム部分」を読みたい条件に合わせて変えればできあがりです。変え方は後述します。

テーブルの場合は、上記を関数化して項目に適用するだけなのですが、そちらのチートシートも機会があれば作ります。

本当はもう少し解説を深掘りするべき部分があるとわかっているのですが（IQBotHelperってなんやねんとか）、

# カスタム部分の解説

## カスタム部分①：選択肢

カスタム部分その１は、以下の部分です。

```python:カスタム部分①　選択肢
matchList = ("代引","銀行振込","クレジット")  #カスタム部分①
```

matchListの中身を、正解の選択肢に変えてあげます。数は自由です。
「りんご」「バナナ」「みかん」「ぶどう」が選択肢なら、こんな感じにします。

```python:カスタム部分①　変更例
matchList = ("りんご","バナナ","みかん","ぶどう")  #カスタム部分①
```

## カスタム部分②：閾値

続いてのカスタム部分は、ここの３行目です。

```python:カスタム部分②　閾値
for i in matchList:
  currentRatio = iq.fuzzy_match (field_value, i, ratio = True)
  if currentRatio >= 0.5:  #カスタム部分②
    if currentRatio > maxRatio:
      result = i
```

「currentRatio >= 0.5」の「0.5」の部分には、ファジーマッチの結果の閾値を指定します。

いくら「もっとも近いものを答えとする」といっても、「クリケット」を「クレジット」に補正するくらいならいいけど、「オーストラリアット」を「クレジット」に補正されるのはどうもなぁ（最後の「ット」が共通しているとはいえ）……みたいなときに使います。

上記のように、「たとえ選択肢の中では一番近くても、一定の確信度を満たしていなければ空欄にした方がマシ」みたいな場合は、そのマッチ度を設定します。

「0.5」は50%なので、マッチ度が50%を超えていて、なおかつ選択肢の中でいちばん近いものがIQ Botの結果として出て来ます。
この場合、選択肢のどれとも50%以上のマッチ度でマッチしなければ、IQ Botの結果としては空欄が返ります。

「いやいや、マッチ度はどんなに低くてもいいので、とりあえず何か正解らしきものを入れておきたい！」という場合は、ここをゼロにします。

#以上！

現時点では以上ですが、そのうちもう少し解説を書くつもりです。

IQBotHelperについてとか、ファジーマッチってなんやねんとか。。。とかとか。。。

(IQBotHelperライブラリは、Automation360.21から追加された、IQ Botの補正に便利なカスタムロジックのライブラリでオンプレ・クラウド問わず使えるやつなんですが、個人的にはライブラリを使って処理する価値があるのはこのfuzzy_matchくらいだと思ってます。他は特にライブラリ使わなくても、下記のページにまとめた内容で対応できるので)

https://qiita.com/IQ_Bocchi/items/1d8e7c77ad47e838476c
モナドを完全に理解したんだが質問ある？？

# モナドとは
関数型言語でIOとかの副作用を扱う方法として教わった。
でも、本質的には違う！！
プログラミングについてとらえなおす。
プログラムの関数とはある型A(のインスタンスa)からある型B(のインスタンスb)への写像である。
各型Aは内部的にAのインスタンスを区別する比較基準を持っている。関数型言語の純粋関数とは引数がAの型の意味で等しければその返り値も等しいという性質を満たす関数である。ここで特別な型としてUnit型がある。Unit型は区別できないので、Unit型を返す関数は完全に純粋関数である。(返り値の意味で迷う要素はない)
ここで、IOを考えてみよう。
doInput関数がもしキーボードから入力待ちをして、入力を返す関数だとすると、それは呼び出すごとに返り値が変わるので純粋関数ではない！これがうざいので、Monad型でラップしてみる。つまり、doInput関数を呼ぶとdoInput()はMonal型を返し受け取った値はMonad型の中にあるように扱うのである。こうすると、doInput(Unit):Monadと書けて、doInput()の返り値が変わることはない。
しかし、このままではMonalの中でラップされている入力された値に触れられない！なので、Monad.bind\[T,U\](Monad[T],T => U): Monad[U]を考える。これによって内部の値に関数を適用できるようになる。しかし、その返り値もMonaldにラップされているのでそのまま使うとはできなくて、bindを介して関数適用することしかできない。
もう一つの関数としてMonald[T].toMonald(T):Monadが必要である。これがないとMonad型を作れない。
このように返り値をラップして関数適用のみを許したような、変数の制限版がモナドである。モナドにいろんな文脈を持たせることで関数適用だけでプログラムを作れるような純粋間推移型言語が存在するのである。
# モナドの例
例えば、Optional[T]はMonadである。Optional[T].map(T=>U):Optional[U]がbindにあたる。しかし、Optional[T]にはgetとかunwrapが実装されているので、上のモナドが純粋性を作り出すよな性質はない。Listを作る文脈に副作用は不要なので問題ない。
List[T]もモナドである。List[T].map(T=>List[U]):List[U]がbindに当たる。これも同様に純粋性を作り出す性質はないが、Listを作る文脈に副作用は不要なので問題ない。
以上のようにいろんなMonad的なものは存在する。人間もモナドである。外界からの影響が脳に蓄積されているが、それは状況のもとでの行動からしかわからない。
# 考えたこと
純粋関数型言語的な目線で行くとMonaldから値を取り出すという行為をしたくないように思う。Monadを使う関数はUnit型を返してほしい。つまり内部でMonaldを使用する関数の連鎖を終わりまで記述してほしいと思うのではないかと感じた。
【Windows】Windows10で言語／キーボード切替のショートカットを無効にする【設定】

# やりたいこと
Windows10で不意に言語切替やキーボードレイアウト切替のショートカットが働いてイラッとするのを解消する
# 経緯
作業中に不意に言語が切り替わって日本語変換できなくなる、キーボードレイアウトが普段使っているGoogleIMEからMSIMEに切り替わっていた、なんてことがちょいちょいあって、そのたびにイラッとしていた。
なにかのショートカットを踏んでしまったんだろうと思っていたけど我慢できなくなったので調べてみた。
# 設定方法
スタートボタン横の検索窓で「キーボードの詳細設定」で検索して設定画面を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198489/9639f515-17e7-c90b-155a-afc54bd45fd5.png)
入力言語のホットキーを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198489/cfce5d41-1431-1f43-5db2-72894f8c0429.png)
キーシーケンスの変更を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198489/7de030fc-4a50-0b6e-30aa-e242f8cdb2ea.png)
入力言語の切り替え と キーボードレイアウトの切り替え をそれぞれ割り当てなしに変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198489/f7b4d75d-6317-27cc-ed66-1ce79c3e4cff.png)

以上
jQueryでのObject→Array変換

以前業務で、以下のようなObjectをArrayに変換して使用したくてちょっと詰まった。

```javascript


// Object
var obj = { 1: {code: 1, name: "北海道"}, 2:{ code: 2, name: "青森"}, 3:{ code: 3, name: "岩手"}}

// ↓変換

// Array
var obj = [ { code: 1, name: "北海道"}, { code: 2, name: "青森"}, { code: 3, name: "岩手"}]


```

## 解決方法: Object.values()を使う。

```javascript
const prefectures = Object.values(obj);
});
```

## ~~解決方法: map()を使う。~~

```javascript
var prefectures = $.map(obj, function (value)) {-
      return value;
});
```

## まとめ
keyは要らないけど、valueだけを扱いたいときに使えそうです。
元々は"map()"を使って修正していたのですが、@il9437 さんにご教授いただいた"Object.values()"を使用した修正方法に変更しました。

>https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Docker + Nginx + Node.js で開発環境構築

業務でNext.jsに触れる機会があったのでDockerで開発環境構築をやってみたいと思ったので書いていきます。
実際にはMySQLも含みますがサーバーサイド側のため割愛します。

*ローカル開発環境構築の想定のため、セキュリティは本番環境を想定していません。

## やりたいこと
`docker-compose`で`Nginx`コンテナをリバースプロキシとして`Node.js`コンテナへリクエストを投げる環境の構築

##環境構築
Docker for Macをインストール済みかつNext.jsでプロジェクト作成済みを想定


#### docker version

```terminal
$docker --version
Docker version 20.10.6, build 370c289
```

#### ディレクトリ構造
```terminal
├── docker-compose.yml
├── node
|   ├── Dockerfile 
├── nginx
   ├── default.conf 
  
```

#### docker-compose.yml
```yml
services:
  nginx:
    image: nginx:1.21-alpine
    container_name: next-nginx
    ports:
      - "80:80"
    depends_on:
      - node
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
  node:
    build: ./node
    container_name: node
    volumes:
      - {プロジェクトルーティング}/:/usr/src/app/
```

#### Dockerfile
curl使ってAPIとの連携確認できたら便利かなと思い入れています。

```Dockerfile
FROM node:16-alpine

RUN apk --no-cache add curl

WORKDIR /usr/src/app/
```

#### default.conf

```conf
server {
    listen 80;
    server_name node.docker.internal;

    root /var/www/public;

    access_log /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass 127.0.0.1:4000;
    }
}
```

#### /etc/hosts
```terminal
127.0.0.1 node.docker.internal
```

## docker-compose up
```terminal
$docker-compose up -d --build // imageダウンロードとかbuildのログがいっぱいでてきます。
$docker-compose ps
    Name                   Command               State                           Ports
--------------------------------------------------------------------------------------------------------------
nginx      /docker-entrypoint.sh ngin ...          Up      0.0.0.0:80->80/tcp,:::80->80/tcp
node       docker-entrypoint.sh npm r ...          Up      3000/tcp, 5000/tcp,
```
うまく起動できたようなので次はnodeコンテナに入り`npm run dev`を実行します。

```terminal
$docker-compose exec node sh
#npm run dev する際のポートを変更する
$vi package.json
  "scripts": {
    "dev": "next dev --port 4000", //← ここに--port 4000を追加
    "build": "next build",
    "start": "next start"
  },
$npm run dev
```

これで`node.docker.internal:80`をたたくとプロジェクトが表示されていると思います。


##現状の課題
nodeコンテナを`compose up -d -build`するとデフォルトで`3000`ポートが公開されていて`npm run dev`されていない状態でも閲覧可能でした。しかし、ファイルを編集しても`npm run dev`していないので変更が反映されないので、`default.conf`の`proxy_pass`で`4000`ポートを指定し、`npm run dev`するポートも`4000`に変更しました。
`docker-compose up -d --build`した時点の`npm run dev`のポートが占領されてしまうため、`docker-compose up -d --build`後に`package.json`を編集する必要がありました。

この部分は最適解ではないと思うので、どうすれば対策できるか調べていこうと思います。
コメントでも是非教えて頂ければ幸いです。
ゾロ目を判定したい

# はじめに
入力された値がゾロ目かどうかを判定したい。

2021.7.30
コメントを頂き、空白文字が入力された際の対策を追加しました。

# 条件
```
ruby 2.6.5
```

# 実際の記述
最終的な記述は以下となる。

```ruby
n = gets.gsub(/　| /){""}

if n.length > 1
  puts  n.chomp.split("").uniq.size == 1
else
  puts "少なくとも2文字以上入力してください"
end
```

## 1. 空白を除外
入力された値に空白が含まれている場合を考慮。

```ruby
n = gets.gsub(/　| /){""}
```
以下のように`gsub`で、「全角空白」と「半角空白」が含まれていれば「空白なし」に置換している。

```ruby
gsub(/　| /){""}

# ① (/　| /) :　　全角・半角を含むものを判定
# ② {""}　   : 全角・半角を "" に置換する
```

```ruby
# 【例１】 : n に 1 1 1 1 が入力された場合(間に半角空白を入力)
n = gets.gsub(/　| /){""}

# => 1111

# 【例2】 : n に 1　1　1　1 が入力された場合(間に全角空白を入力)
n = gets.gsub(/　| /){""}

# => 1111

# 【例3】 : n に    1111 が入力された場合(先頭にに半角空白3つ入力)
n = gets.gsub(/　| /){""}

# => 1111
```
https://docs.ruby-lang.org/ja/latest/method/String/i/gsub.html

## 2. uniq
`uniq`で入力された値に被りがあるか確認。
被り（重複）がある場合は、その要素を取り除き、新しい配列を結果として出力してくれる。

```ruby
n = gets.gsub(/　| /){""}
n.chomp.split("").uniq
```
```ruby
# 【例１】 : 渡ってきた値に被りがある時①
n = gets.gsub(/　| /){""}
# n に 1111 が入力された場合

n.chomp.split("").uniq
# => 1


# 【例2】 : 渡ってきた値に被りがある時②
n = gets.gsub(/　| /){""}
# n に 1122 が入力された場合

n.chomp.split("").uniq
# => 1
#    2


# 【例3】 : 渡ってきた値に被りがない時
n = gets.gsub(/　| /){""}
# n に 1234 が入力された場合

n.chomp.split("").uniq
# => 1
#    2
#    3
#    4
```

https://docs.ruby-lang.org/ja/latest/method/Array/i/uniq.html

## 3. size
`uniq`で被りが含まれていない配列を作成した次に、`size`を使いその配列の要素数を数える

```ruby
n = gets.gsub(/　| /){""}
n.chomp.split("").uniq.size
```
```ruby
# 【例１】
n = gets.gsub(/　| /){""}
# n に 1111 が入力された場合

n.chomp.split("").uniq.size
# => 1


# 【例2】
n = gets.gsub(/　| /){""}
# n に 1122 が入力された場合

n.chomp.split("").uniq.size
# => 2


# 【例3】
n = gets.gsub(/　| /){""}
# n に 1234 が入力された場合

n.chomp.split("").uniq.size
# => 4
```
先程の`uniq`で生成された配列の要素数を出力してくれている。

https://docs.ruby-lang.org/ja/latest/method/Range/i/size.html

## 4. ゾロ目の判定
「ゾロ目」ということは、<b>入力された全ての値が同じ</b>であると言える。
なので、最終的に`size`で出力された値が`1`であれば入力された値は同じ数であると言える。

そのため、以下のように `==`の条件演算子を用いる事で結果を`true`または`false`で出力してくれる。

```ruby
n = gets.gsub(/　| /){""}
n.chomp.split("").uniq.size == 1 # sizeの値が1と等しいかどうか判定
```

```ruby
# 【例１】
n = gets.gsub(/　| /){""}
# n に 1111 が入力された場合

n.chomp.split("").uniq.size == 1
# => true


# 【例2】
n = gets.gsub(/　| /){""}
# n に 1122 が入力された場合

n.chomp.split("").uniq.size == 1
# => false


# 【例3】
n = gets.gsub(/　| /){""}
# n に 1234 が入力された場合

n.chomp.split("").uniq.size == 1
# => false
```
もし、結果を`true` `false`でなく`Yes` `No`で出力したければ、以下のように記述することで出力できる。

```ruby
n.chomp.split("").uniq.size == 1 ? "Yes" : "No"
```
https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html

# おわり
`true` `false`の判定を１行でできるのはいいですね！
`if`とうまく使い分けていこうと思います。
PostgreSQL: どのカラムにどんな権限があるか確認するSQL

PostgreSQLで、どのロールに、どのテーブルのどのカラムに、どんな権限(`INSERT`, `UPDATE`, `SELECT`)が付与されているかを確認するSQLです。

```sql
select grantee,
       table_name                                         as "table",
       privilege_type                                     as type,
       string_agg(column_name, ', ' order by column_name) as columns
from information_schema.column_privileges
where table_schema = 'public'
group by grantee, table_name, privilege_type
order by grantee, table_name, privilege_type;
```

実行結果の例

![CleanShot 2021-07-29 at 11.22.05@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/ea45e338-761e-01c0-102d-2e79948041c2.png)

ここで紹介したSQLは「カラム単位」の権限確認です。テーブル単位の大まかな権限の確認方法は次の記事をご覧ください。

https://qiita.com/suin/items/63b127e2cc5dc4ea87e5
基本情報技術者試験に合格したのでその対策など

ずいぶん前のことになりますが、基本情報技術者試験に合格したので
合格するために大事なことなどを書いていきます。

業界5年目のときに受けて突破できたので参考になればと思います

:::note alert
ネタ成分強めです
ちゃんとした基本情報技術者試験の対策は他を参考にすると良いと思います。
:::

---

# 第0次試験を突破する。
よくネタで会場に定刻につくことを第0次試験といったりしますが。

ここが最初で最後の壁です
これが本当にしんどい。
ここが突破できなくて、毎年基本情報技術者試験を突破できませんでした。

そして突破するために行きついた答えが


### 会場の近くに車中泊でした。

これをしたことで第0次試験を突破できました。

### 車中泊で役立ったグッズ

 * 枕とマットと毛布

:::note info
車のシートは地味に硬いので安眠するために重宝します。
:::
 * 飲み物
 
:::note info
普通に熱いので必須だと思います。熱中症に気を付けてください
:::
 * メンズボディーシート
 
:::note info
車中泊で入浴できないので体臭などに気をつけましょう。
:::

---
# 午前問題を突破する
業界5年目ということで気を付けるのは

* 受験番号を間違えない
* 時間配分を間違えない


この2点になります。
全部熟考すれば解ける問題かなと思いますが・・・

時間がけっこうシビアなので
### 5秒考えて即答できない問題、読み切らない問題は後回しにします。

合格するためには6割取れればいいので、即答できる問題を取りこぼさないようにしてればおのずと突破できます。

---
# 午後問題を突破する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/4adb4f2d-41b6-ddfd-6e49-228d1230b61e.png)
https://www.fe-siken.com/fekeisiki.html
より抜粋

何を解くか決めておくと時間が短縮できて良いです。

----
# まとめ
業界で数年やってるとノー勉で受かるとか聞きますが

* 会場に行くのが難しかった。
* 問題を解くことはできるのだが、問題を限られた時間で沢山解くということには慣れていないため時間が足りない

業界を何年やってても上記対策をしないと普通に落ちる
Before starting UiPath:DataTableで覚えておくアクティビティ

## 皆もすなるQiitaといふものを、儂もしてみむとてするなり。

と言う訳で、こん＊＊は！はなっち！です。

★★★この記事はUiPathブログ発信チャレンジ2021サマー、7/29の記事です。★★★

今回は、ちょっとしたシリーズです。UiPathを使うに当たって、UiPathの機能ではなく、コンピュータ言語を使う上での基礎知識を展開していこうと思います。

#DataTableで覚えておくアクティビティ

DataTable型の変数では、Excelの機能を実現するようなアクティビティが用意されています。
Excekでは実現できますが、UiPathでは実現しにくい事もあります。

Excelの機能を実現するようなアクティビティ
　　１）VLOOKUPワークシート関数のような機能。。。「データテーブルの結合」アクティビティ
　　　　VLOOKUPワークシート関数は、検索値を範囲の左端で探し、見つかった行の指定列を返す機能を持っています。

　　　　UiPathでは、「データテーブルの結合」アクティビティを使用します。
　　　　「データテーブルの結合」アクティビティでは、左辺のDataTableと右辺のDataTableとを指定キーで結び、
　　　　それぞれのDataTableの列を出力のDataTableとして出力するものです。

　　２）オートフィルタのような機能。。。「データテーブルをフィルタリング」アクティビティ
　　　　オートフィルタはシートに設定し、欲しい値をその場で変えながら、必要な行以外を表示させない機能です。

　　　　UiPathでは、「データテーブルをフィルタリング」アクティビティを使用します。
　　　　「データテーブルをフィルタリング」アクティビティでは、入力のDataTableに存在する列を指定し、
　　　　その列に含まれるであろう値に対する条件を指定し、その条件を満たす行を保持あるいは削除する事が出来ます。

　　３）シートの並び替えのような機能。。。「データテーブルを並べ替え」アクティビティ
　　　　シートの並び替えは、シート上の複数の列の値を、昇順、あるいは降順に並び替える機能です。
　　　　Excelでは値の他に、セルの色、フォントの色、条件付き書式のアイコンを並び替える事ができます。

　　　　UiPathでは、「データテーブルを並べ替え」アクティビティを使用します。
　　　　「データテーブルを並べ替え」アクティビティでは、入力のDataTableに存在する列を指定し、
　　　　並び替えをする列を一つだけ指定します。Excelは複数指定できますが、UiPathでは一つだけです。
　　　　また、値だけでの並び替えになります。Excelのような、セルの色などでの並び替えは出来ません。

　　４）Excelでは手作業で行うしかない機能。。。「データテーブルをマージ」アクティビティ
　　　　あるシート上の値を、別のシートにマージするには、手で行うか、シート間参照を用いる方法があります。

UiPathでは、「データテーブルをマージ」アクティビティが利用できます。
ソースに指定されたDataTableを保存先のDataTableに追加します。その際、保存先のDataTableの列の並びに変換します。
ですので、列の並びを変える際に応用できます。

##おわりに
いかがでした？

唐突にUiPathアクティビティの紹介が始まって、ビックリされた方もらっしゃる事でしょう。DataTable型の話をした流れで、EXCELでの違いを説明するにはいいタイミングと思ったからです。
DataTable型は、アクティビティでの操作以外に、LINQ機能で操作する方法もあり、まるでスルメのように、触れれば触れるほど味が出るものです。色々と研究してまいりましょう。

是非UiPathでのロボ開発の一助になればと思っています。

ありがとうございました！
aws_eip_associationって何だ

## これは何ですか

aws_eip_associationって何に使うんや、と思ったときに書いたメモです。
EC2のドキュメントを眺めていた時、どういうときに使うのかよくわからん、と思ったので、とりあえず構築して理解することにしました。

## つまり
新規構築で、EIPをEC2に割り当てる祭、aws_eipを使うと思います。
ただ、既存のEIPを割り当てたいケースもありますよね、きっと。
そこで、aws_eip_associationを使うことで、解決できます。

## やってみた

まずはEIPをCLIで払い出します。(一時的に払い出しているだけなので、構成情報は書いても問題ないと思うのですが、念のためぼかしてます。)

```
$ aws ec2 allocate-address
{
    "PublicIp": "Your_EIP",
    "AllocationId": "eipalloc-○△□",
    "PublicIpv4Pool": "amazon",
    "NetworkBorderGroup": "ap-northeast-1",
    "Domain": "vpc"
}
```

aws_eip_associationを定義します。

```
resource "aws_eip_association" "eip" {
  instance_id   = "${aws_instance.Your_EC2.id}"
  allocation_id = "eipalloc-○△□"
}
```

applyして構築します。

```
$ terraform apply
```

コンソール上から確認してみます。
おお〜、本当に紐づいてますね。面白い。

![スクリーンショット 2021-07-29 11.06.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/15b7cdd8-e790-484a-d3f1-5323af36a944.png)

何だかぼかしまくってて具体的にイメージできなそうですが…
一応、デプロイできたことを確認できました。

## 最後に

やはり文章、記事かなんかでアウトプットするのが一番身になるなと思いました。終
3.9(標準) ポアソン分布

## 方針

ポアソン分布について書く．ポアソン分布は単位時間内に平均lambda回起きる事象が起こる回数を示す確率分布である．確率密度関数は，

```math
f_X(x)=\frac{\lambda^x}{x!}\exp(-\lambda),\ \ \ x=0,...
```

積率母関数は，

```math
\begin{align}
M_X(t)&= \mathbb{E}_{X\sim Po(\lambda)}[e^{tX}]\\
&= \sum_{x=0}^\infty\frac{\lambda^x}{x!}\exp(tx-\lambda)\\
&= \exp(-\lambda)\sum_{x=0}^\infty \frac{(e^t\lambda)^x}{x!}\\
&= \exp(-\lambda)\exp(e^t\lambda)\\
&= \exp\{\lambda(e^t-1)\}
\end{align}
```

二項分布の積率母関数(3.8で解説)において，

```math
\lambda=np
```

と置くと，n→∞において

```math
\begin{align}
\lim_{n\rightarrow\infty}(\frac{\lambda}{n}e^t+1-\frac{\lambda}{n})^n&= \lim_{n\rightarrow\infty}\{1+\frac{\lambda(e^t-1)}{n}\}^n\\
&= \exp\{\lambda(e^t-1)\}
\end{align}
```

であるから，ポアソン分布は二項分布でn→∞とした形であることがわかる．

期待値は，

```math
\begin{align}
\mathbb{E}_{X\sim Po(\lambda)}[X]&= \sum_{x=0}^\infty x\frac{\lambda^x}{x!}\exp(-\lambda)\\
&= \lambda\sum_{x=1}^\infty\frac{\lambda^{x-1}}{(x-1)!}\exp(-\lambda)\\
&= \lambda\sum_{x'=0}^\infty\frac{\lambda^{x'}}{x'!}\exp(-\lambda)\ \ \ \ x'=x-1\\
&= \lambda
\end{align}
```

分散は，

```math
\begin{align}
\mathbb{E}_{X\sim Po(\lambda)}[X^2]&= \sum_{x=0}^\infty x^2\frac{\lambda^x}{x!}\exp(-\lambda)\\
&= \lambda\sum_{x=1}^\infty x\frac{\lambda^{x-1}}{(x-1)!}\exp(–\lambda)\\
&= \lambda\sum_{x'=0}^\infty(x'+1)\frac{\lambda^{x'}}{x'!}\exp(-\lambda)\\
&= \lambda(\lambda+1)\\
Var(X)&= \lambda(\lambda+1)-\lambda^2=\lambda
\end{align}
```

## 答案

確率変数Yの積率母関数は，

```math
\begin{align}
M_Y(t)&= \mathbb{E}_{X\sim Po(\lambda)}[e^{tY}]\\
&= \mathbb{E}_{X\sim Po(\lambda)}[e^{\frac{t(X-\lambda)}{\sqrt{\lambda}}}]\\
&= \exp(-t\sqrt{\lambda})\mathbb{E}_{X\sim Po(\lambda)}[e^{\frac{t}{\sqrt{\lambda}}X}]\\
&= \exp(-t\sqrt{\lambda})\sum_{x=0}^\infty\frac{\lambda^x}{x!}\exp(\frac{t}{\sqrt{\lambda}}x-\lambda)\\
&= \exp(-t\sqrt{\lambda}-\lambda)\sum_{x=0}^\infty\frac{(e^{\frac{t}{\sqrt{\lambda}}})^x}{x!}\\
&= \exp(-t\sqrt{\lambda}-\lambda+\lambda e^{\frac{t}{\sqrt{\lambda}}})
\end{align}
```

今，

```math
\psi(t)=\log M_Y(t)
```

とおけば，n→∞で，

```math
\psi(t)\rightarrow\frac{t^2}{2}
```

であることを示せば良い．

```math
\psi(t))=-t\sqrt{\lambda}-\lambda+\lambda e^{\frac{t}{\sqrt{\lambda}}}
```

指数部分について，漸近展開して，

```math
e^{\frac{t}{\sqrt{\lambda}}}=1+\frac{t}{\sqrt{\lambda}}+\frac{t^2}{2\lambda}+\mathcal{o}(\frac{1}{\lambda})\ \ \ as\ \ \lambda\rightarrow\infty
```

なので，

```math
\begin{align}
\psi(t)&= -t\sqrt{\lambda}-\lambda+\lambda(1+\frac{t}{\sqrt{\lambda}}+\frac{t^2}{2\lambda}+\mathcal{o}(\frac{1}{\lambda}))\\
&= -t\sqrt{\lambda}-\lambda+\lambda+t\sqrt{\lambda}+\frac{t^2}{2}+\mathcal{o}(1)\\
&\approx \frac{t^2}{2}\ \ \ as\ \lambda\rightarrow\infty
\end{align}
```

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
AlmaLinux に mininet をインストールする

mininetをAlma Linuxにてビルドする時に少し手間取ったのでメモします．

# 前提
今回は個別に Open vSwitch をインストールしておく ([https://docs.openvswitch.org/en/latest/intro/install/index.html](https://docs.openvswitch.org/en/latest/intro/install/index.html))
その他，足りないパッケージがあれば適宜インストール

# mininetのインストール
まずは，[公式ドキュメント](http://mininet.org/download/)通りにgithubからソースをcloneします．

```bash:bash
$ git clone git://github.com/mininet/mininet.git
$ git checkout -b mininet-2.3.0 2.3.0
```

この後，公式ドキュメントに従えば `./mininet/util/install.sh` を実行するだけでmininetをインストールできるのですが，
Alma Linux にインストールする場合は install.sh の中身をいくつか書き換える必要があります．

## install.shの書き換え
①  install.sh の51行目に以下のように追記する

```shell:install.sh
49 test -e /etc/fedora-release && DIST="Fedora"
50 test -e /etc/redhat-release &&  DIST="RedHatEnterpriseServer"
51 test -e /etc/almalinux-release && DIST="AlmaLinux"  # この行を追記
```

② 変数DISTの値が Fedora と RHEL だった時に分岐するif文があるので，そこに AlmaLinux を書き加える

```shell:install.sh
if [ "$DIST" = "Fedora" -o "$DIST" = "RedHatEnterpriseServer" ] || [ "$DIST" = "AlmaLinux" ]; then
```

このif文は複数あるので，適宜書き加えます．

③ 86行目にAlma Linuxを書き加える

```shell:変更前
86 DISTS='Ubuntu|Debian|Fedora|RedHatEnterpriseServer|SUSE LINUX'
```

```shell:変更後
86 DISTS='Ubuntu|Debian|Fedora|RedHatEnterpriseServer|AlmaLinux|SUSE LINUX'
```

④ pythonのバージョンを3に指定する
依存パッケージに関する install.sh の仕様として，インストール先の環境に python2 がインストールされている場合は， python3 より python2 の関連パッケージを優先する場合があるようです．
python2 ではそもそもパッケージが提供されてなかったりと不都合があるので，python3 の関連パッケージがインストールされるように修正します．

```shell:変更前
109 for python in $PYTHON python2 python3; do
110     if $python -c "$PRINTVERSION" |& grep 'major=2'; then
111         PYTHON=$python; PYTHON_VERSION=2; PYPKG=python
112         break
113     elif $python -c "$PRINTVERSION" |& grep 'major=3'; then
114         PYTHON=$python; PYTHON_VERSION=3; PYPKG=python3
115         break
116     fi
117 done
```

```shell:変更後
109 for python in $PYTHON python3; do
110     if $python -c "$PRINTVERSION" |& grep 'major=2'; then
111         PYTHON=$python; PYTHON_VERSION=2; PYPKG=python
112         break
113     elif $python -c "$PRINTVERSION" |& grep 'major=3'; then
114         PYTHON=$python; PYTHON_VERSION=3; PYPKG=python3
115         break
116     fi
117 done
```

また関連して，166行目の `python-setuptools` のパッケージを `python3-setuptools` に書き換えておきます．

```shell:install.sh
166 iproute telnet python-setuptools libcgroup-tools
```

## iperfのインストール
install.sh に記述されている依存パッケージの1つに iperf があるのですが，AlmaLinuxの標準リポジトリには iperf3 しかなく， iperf は見つかりませんでした．
なので今回は， iperf の RPM を取得して直接インストールしました．
(ダウンロード元：https://iperf.fr/iperf-download.php)

## install.sh の実行
以上の手順を踏まえた上で，以下のように install.sh を実行するとインストールが完了します．

```shell:bash
$ ./mininet/util/install.sh -nf
```

# 参考URL
[http://ns2.ainoniwa.net/pelican/2015/0810a.html]
(http://ns2.ainoniwa.net/pelican/2015/0810a.html)
[https://techandtrains.com/2014/09/13/mininet-and-open-vswitch-on-centos-7/](https://techandtrains.com/2014/09/13/mininet-and-open-vswitch-on-centos-7/)

# 環境
AlmaLinux 8.4
IAMでIPアドレス制限をかける

先輩からある日こんなことを言われました。

『IPアドレス制限(※)というセキュリティ対策があるということを知ったので、MFAではなくIAMにその設定を入れ込んでほしいです。
(※)AWSアカウントにアクセスする際のグローバルIPを制限し、その指定IP以外はアクセス出来なくする手法

調べれば出てくると思いますのでやってみてください。』

先月からAWSをいじり始めたひよっこにはよくわからん話すぎたがとりあえず調べてやってみることに。:relaxed:


いろいろ調べていくうちにやらなきゃいけないことは大体つかめた。

要は、自分のパソコンのIPアドレス以外からのアクセスを拒否するIAMポリシーを作る→ユーザーグループに付与しなきゃいけないんだと思う。多分。

ということで、その方向で調べてみると神みたいな記事を見つけた。もうこの記事書いた人に頭が上がらない。ありがとう:sob:
その神記事がこちら↓

https://hacknote.jp/archives/43145/

とりあえず『AllowAssumeRoleWithSourceIPRestriction ポリシーの編集』までやって、そこからはポリシーをユーザーグループに紐付け！

IAMのユーザーグループにいって・・・
![ユーザーグループ_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1780205/14bdf62f-611f-a211-bedf-ecef1784e686.jpeg)

紐付けたいユーザーグループを選択

![アクセス許可_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1780205/3664fe3a-8550-5d14-4304-390786f1418b.jpeg)

アクセス許可のタブを開いて『ポリシーをアタッチ』
で、さっき作ったポリシーを選択して完了！パチパチ:clap:

自分、記事見てやっただけですがとってもお勉強になりました:grin: