OmniAICreator/Qiita-1.07M huggingface dataset:
シンプルなImageEffect　その４。「Vignette（ビネット）」

TwitterでアップしたVignette（ビネット）のコードを貼っておきます
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Viewport座標の内積で軽量なVignette(ビネット)作った。<br>これもまた週末にでも記事書きます。 <a href="https://t.co/JoC9bNYznD">pic.twitter.com/JoC9bNYznD</a></p>&mdash; MIYAKE (@ScreenPocket) <a href="https://twitter.com/ScreenPocket/status/1250442449295519752?ref_src=twsrc%5Etfw">April 15, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

```glsl:Vignette.shader
Shader "ScreenPocket/ImageEffect/Vignette"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Power ( "Power", Float ) = 0
    }
    
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv.xy = v.uv;
                o.uv.zw = o.vertex.xy;
                return o;
            }

            sampler2D _MainTex;
            float _Power;

            fixed4 frag (v2f i) : SV_Target
            {
                half4 col = tex2D( _MainTex, i.uv.xy );
                float2 vp = (i.uv.zw);
                col.rgb -= dot(vp,vp) * _Power;
                return col;
            }
            ENDCG
        }
    }
}
```
頂点シェーダで[ImageEffectで使いやすい2つの座標情報](https://qiita.com/ScreenPocket/items/dab8d785859faa05ed18)で紹介したViewport座標を、o.uv.zwを介してFragmentShaderに渡し、Viewport座標xyの内積を取る（dot(vp,vp)）ことで円形に暗くしています。
また、強さを_Powerで指定できるようにしておいたので、値を大きくすることでより暗く、負の値にすることでより明るくすることも可能です
※値を増やして暗くなるのが違和感ある人は -= を += に変更して下さい。

暗い方はよくあるビネットとして使えそうですし、明るい方も回想シーンなどで使えるかもですね。
SELinuxって意味あるのか

Peingへの質問と回答を備忘のため転載します

> SElinuxって、root奪取されるような事態になってはじめて設定がいきてくる仕組みだから、設定作業に四苦八苦するより、さっさと無効にして権限設定したり定期的にパッチ当てたりとセキュリティ対策するほうが良いでしょうか。
[peingの質問](https://peing.net/ja/q/3c96608e-13c3-4307-baa9-aedf0832acec) より転載

そんなこともないと思います。
モデルケースとして、CentOS7かCentOS8上でApache+PHPによりWordPressを稼働する例で説明します。

標準的なWordPressのインストールでは、wp-contentディレクトリにApache(PHP)から書き込みできる権限を与えます。これに備えて、CentOS7以降では、あらかじめ /var/www/html(/.*)?/wp-content(/.*)? に対して、SELinuxのタイプ httpd_sys_rw_content_t が設定されており、PHPから wp-content ディレクトリに書き込みできる権限が SELinux を有効にしても与えられます。

この条件だと、外部からの攻撃により、wp-contentディレクトリにウェブシェルが設置できてしまいそうですよね。
しかし、WordPressに対する典型的な攻撃では、WordPressプラグイン等のリモートコード実行可能な脆弱性を悪用して wget コマンドを起動し、外部からウェブシェルをダウンロードして設置します。上述のケースですと、PHPからは wp-content ディレクトリに書き込みできますが、wgetからは（PHPと同じユーザーで実行されていても）wp-contentディレクトリには書き込みできません。これがSELinuxの効果です。

この効果に対して、wgetを実行する代わりに、PHPのfile_put_contents関数などでウェブシェルを書き込めると反論があるかもしれません。理論的にはそうですが、wgetが実行できる局面で必ずPHPの任意関数が実行できるとは限りませんし、wget（あるいはcurlなど他のコマンド）を使う典型的な攻撃が制限できるだけでも、SELinuxは魅力的だと思います。
【初級編】JavaScript連想配列(オブジェクト)

今回は連想配列について簡単に説明できたらとおもいます。
今回は key(キー）:value（値）この関係のことを連想配列と呼ぶことにしたいと思います。

## 📗 連想配列とは
***・連想配列とはキーと値がセットで作られている配列となります。***

コレまで使ってきた配列は数値0,1,2といったように数値が値に振られて、その数値を指定することで取り出していましたが
連想配列は、値に対して名前みたいなものをつけて、名前を読んだら値が来るみたいなイメージです。

今までは何番収容所の囚人番号何番！って感じだったのが
連想配列を使うと、イケメン小学校のイケメン太郎君！って感じに呼び出しやすくなったのです！

この連想配列を他の言語だとハッシュや辞書なんて言ったりします。
またES６以前は、連想配列という仕組みがなかったようで、オブジェクトで対応していたようです。
ES6以降になって連想配列Mapが使えるようになりました。


初学者の方は、ちょっと何言ってるかわからないと思うので、実際にコードを書いてみましょう。

## 📗 実践！！
今回はランチの情報を書いてみたいと思います。

```javascript
　連想配列の基本形
const 変数 ={
  ' キー ' : ' 値 '
};

const の部分は適宜letとかvarとかにしてください。
大切なのは キー :　値　という形になることです。
//取り出し方
console.log(変数[キー]);

```

```javascript
 const lunch = {         //lunchという変数に
  'menu':'スープセット',     //キーをmenu,値をスープセット
  'price':'1200円',      //キーにprice,値を1200円　と定義します。
};

console.log(lunch['menu']); //こう書くことで、lunchの中のmenuの値を出力することが出来ます。

console.log(lunch.menu); //このように、.でつなげることで記入を少なくすることも可能です。（省略形）
```

ランチの種類を増やして見ましょう♪


```javascript

const lunch = {
 'lunch_1':{
   'menu':'スープセット',
   'price':'1200円',
 },
 'lunch_2':{
   'menu':'生姜焼き定食',
   'price':'1300円',
 },
};

では、生姜焼き定食という情報を出力してみましょう。

 console.log(lunch['lunch_2']['menu']);  //ランチの中のランチ２のメニューを出力してくださいということですね。

 console.log(lunch.lunch_2.menu);        //あるいは、このようにもかけます。

```

このように、どんどん階層を深くしていくとすごくたくさんの情報を一つの変数に含んで自由に扱うことが可能です！

## 📗 まとめ
- 連想配列は値に名前（文字）をつけて管理できる。
- 連想配列はたくさんの情報を一つの変数に含める
- 出力するときは[]でもOKだけど、.で省略して書くことが可能！

以上今回はこの辺にしておきます！ご指摘有りましたら編集リクエストまでよろしくお願いいたします！

## 📗 次回予告

次回は if文について触れていきたいと思います。
お楽しみに！！
CentOS7 + Firefoxの環境で パスワード入力画面でキー入力ができない

#はじめに

CentOS7は殆どGUIで使ってなかったのですが、先日GUIでFirefoxを立ち上げてとあるサイトにログインしようと、「ユーザID」と「パスワード」を入力しようとしたら、、

画面がチカチカして、入力をまったく受け付けてくれません。

困ったな。。

CentOS7の問題のようでCentOS6では正常のようです。

#Firefoxのバグっぽい
(正確にはFirefoxのバグではないようです。後述)

FirefoxのバグじゃなかろうかとFirefoxをdowngradeしてみました。

注意: 2020年4月27日より前の話。

どうやら、「firefox-60.9.0-1.el7.centos.x86_64」にダウングレードすると正常にユーザIDとパスワード入力ができるようです。次のコマンドでダウングレードできます。



```
$ yum downgrade firefox-60.9.0-1.el7.centos.x86_64
```

少なくとも4月より前だったらこの方法でよかったのですが、2020年4月27日にCentOSがCentOS7.7から7.8にアップグレードされました。現在は失敗します(>_<) 

このFirefox-60.9.0はCentOS7.7に含まれるパッケージだったのですね。

CentOS7.8でファイルが無くなってしまって、現在はこうなります。

```
$ yum downgrade firefox-60.9.0-1.el7.centos.x86_64
読み込んだプラグイン:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * epel: xx.xx.xx.xx
パッケージ firefox-60.9.0-1.el7.centos.x86_64 は利用できません。
エラー: 何もしません
```

さてさてどうしたものでしょうか。CentOS7は実質的にFirefoxが使いものにならなくなってしまったようです。

Google Chromeを入れて逃げました。

参考文献: https://www.karelie.net/how-to-install-google-chrome-on-centos7/

#そもそも原因はなんなんだ？

前出のfirefox-60.9.0-1.el7.centos.x86_64の次にリリースされたのは firefox-68.1.0-2.el7.centos.x86_64でして、メジャーリリースが60系から68系に更新されたようです。ここで何らかのバグが発生したようです。

次に、英語なので斜め読みですが、firefoxではなくてgnome-shell の問題のようです。

https://bugs.centos.org/view.php?id=16545
> 0016545: ibus and gnome-shell breaks password fields in Firefox


https://bugzilla.redhat.com/show_bug.cgi?id=1771841
> Bug 1771841 - High CPU usage and text cursor flickering when password field is focused in firefox 68

以上。
Web Strage勉強用

# Web Strageとは？
ユーザのローカル環境(ブラウザ)にデータを保存するための仕組み。
データの取得や削除などの操作はJavaScriptを介して行われる。
データをkey-valueペアのリスト構造で保存するなど、HTTP cookieと似た仕組みになってる。

HTML5からの新実装で、モダンなブラウザは対応済み。

以下の異なる２種類の仕組みがある。

- sessionStorage
- localStorage

# 比較表

|保存方法|異なるWindow間の<br>データ共有|データの<br>有効期限|データ量の上限|サーバへの<br>データ送信|
|:-:|:-:|:-:|:-:|:-:|
|HTTP cookie|O|指定の期限まで|4KB|アクセスのたびに<br>毎回自動で送信|
|sessionStorage|x|セッション中のみ|オリジンごとに5MB|必要のたびに<br>フォーム等で送信|
|localStorage|O|永続的に有効|オリジンごとに5MB|必要のたびに<br>フォーム等で送信|

＊ セッション
ページの再読み込みや復元を含むブラウザを起動している間のこと

＊ オリジン
ページにアクセスする際のURLにおける、プロトコル(スキーマ)からドメイン(ホスト)およびポートまでのこと


# HTTP cookieと比較した場合のメリット
- 使えるデータ量が多い
アプリケーションのデータをブラウザにキャッシュして再利用したい場合に便利

- サーバへのデータ送信を制御できる


# Web Strage利用の注意点
- Stringデータしか保存ができない
(HTTP cookieも同じだけど)Stringで表現できないデータは保存できない

- 同期処理
(HTTP cookieも同じだけど)同期処理なので複雑な処理中と合わせて使うとパフォーマンスが下がる

- WebWorkerから利用できない
なのでバックグラウンド処理ができない

- あらゆるJavaScriptコードから自由にアクセスできる
データ保護的なものもないので、全くもって**セキュアじゃない**

# Web Strageを使うシチュエーション
- 秘密情報を一切含まない
- 公開されても大丈夫な情報のみを含む
- 5MBを超えないデータである
- Stringデータのみを取り扱う
- 保存するアプリケーションでパフォーマンスを要求されないこと

# じゃあWeb Strageに保存するべきでないデータはどうするの？
## 秘密情報を管理する場合
サーバーサイドセッションを使う。
そして、セキュリティ対策を十分に実施する。

セキュリティについては以下を参照。
- [HTML5のLocal Storageを使ってはいけない（翻訳）](https://techracho.bpsinc.jp/hachi8833/2019_10_09/80851)

- [セキュリティー - Cookieは暗号化されていれば盗まれてもいいの？｜teratail](https://teratail.com/questions/49297)

- [セッションを暗号化することになんの意味がありますか？暗号化したとしても、その暗号化したものを使ってリクエストしてしまえばサーバー側で復号してくれるので通ってしまうと思います。 - Quora](https://jp.quora.com/sesshon-wo-angou-ka-suru-kotoni-nan-no-imi-ga-arima-suka-angou-ka-shita-toshite-mo-sono-angou-ka-shita-mono-wo-shi-tte-rikuesuto-shi-te-shima-e-ba-sa-ba-gawa-de-fukugou-shi-te-kureru-node-toori-tte-shimau-to-omoi)


## (秘密情報ではない)Stringデータで扱えないデータの場合
IndexedDBを利用する。

## オフラインキャッシュでもデータを参照したい場合
Service Workerを利用する。
ObsPyで読み込んだ地震波形データをMatplotlibで描画してみよう

# 本稿の目標
以前の記事で、読み込んだ波形を描画するのは、単に

```python
st[0].plot()
```
とするだけでOKだとご紹介しました。これはこれで便利なのですが、matplotlibを使って、工夫を凝らした図を作りたいということもあるでしょう。そこで、matplotlibを使って簡単な図を作ります。単一の波形を描画した上で、目盛りの数値の書式の指定、軸ラベルやタイトル、その他任意の印字をします。なお、複数の波形を使った描画については、回を改めて紹介しようと思います。

# 波形の描画
波形データは、`st[0].data`に1次元の`numpy.ndarray`の形で入っています。例えば、以下のようにすれば、図が描けます：

```python
import matplotlib.pyplot as plt
plt.plot(st[0].data)
plt.show()
```
![matplotlib_plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242916/4d8f10bc-1174-3d28-9767-42dedc0c7bb2.png)

# 横軸を時間にする
ただ、これだと横軸がサンプル番号になってしまいます。横軸をデータ開始時からの時間にするには、例えば、以下のようにすれば良いです。

```python
import numpy as np
plt.plot(np.arange(st[0].stats.npts) * st[0].stats.delta, st[0].data)
plt.show()
```
![matplotlib_plot2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242916/72ba0188-d9dc-3186-eaca-5381287b5ccb.png)

# 指数表記にする
y軸に位取りのための0がたくさんあって見づらいので、表記を変えたいと思います。

```python
fig = plt.figure()
plt.ticklabel_format(style="sci", axis="y", scilimits=(0,0))
plt.plot(np.arange(st[0].stats.npts) * st[0].stats.delta, st[0].data)
plt.show()
```

![matplotlib_plot3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242916/58c3b9b0-c22d-d983-28f0-6869b4f18436.png)

# 軸にラベルをつける
両軸にラベルをつけたくなった場合は、以下のようにしてください：

```python
fig = plt.figure()
plt.plot(np.arange(st[0].stats.npts) * st[0].stats.delta, st[0].data)
plt.xlabel("time [s]")
plt.ylabel("velocity [m/s]")
plt.ticklabel_format(style="sci", axis="y", scilimits=(0,0))
plt.show()
```
![matplotlib_plot4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242916/a2a9f790-a197-fda9-a2b3-f1ae522e6275.png)

# いろいろ盛り込んでみました
[なんやかんや](https://www.nhk.or.jp/design-ah/nanyakanya/)ありまして、いろいろな要素を盛り込んだ図ができました。何をやったかは説明しませんが、おそらく推測可能だろうと思います。詳しくは[マニュアル](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.html#module-matplotlib.pyplot)をご参照下さい。

```python
fig = plt.figure()
plt.plot(np.arange(st[0].stats.npts) * st[0].stats.delta, st[0].data, color='r')
plt.xlabel("time [s]")
plt.ylabel("velocity [m/s]")
plt.title(st[0].stats.station + " " + st[0].stats.channel)
plt.ticklabel_format(style="sci", axis="y", scilimits=(0,0))
plt.text(40,1e-5,"P",fontdict={'fontsize':'14'})
plt.text(46,1e-5,"S",fontdict={'fontsize':'14', 'weight':'bold'})
plt.xlim(30,60)
plt.ylim(-6e-4,6e-4)
plt.show()
```
![matplotlib_plot5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242916/ef753373-f086-6bd3-2729-34e2b3992803.png)

また機会を改めて、複数の波形を一度にプロットしてみたりしたいと思います。では。
GenericなUITableViewCellを使う

# P.S この記事の内容は古くなりました。
iOS14にて、よく利用するセルのパターンとそのカスタマイズのために[UIContentConfiguration](https://developer.apple.com/documentation/uikit/uicontentconfiguration)というオブジェクトが提供されました。

まずそちらを参考にしてください。

# まえがき
TwitterのTLで少し前に**「UITableViewCellのサブクラスを毎回作るのではなく、GenericsなTableViewCellにUIViewを載せて対応する」**という方針を採用されておられる方がいて、良いなぁと思ったので作ってみました。

# やったこと
GenericなUITableViewCellをつくる/つかう

https://github.com/yosshi4486/GenericCell/blob/master/Sources/GenericCell/GenericTableViewCell.swift

```swift:GenericCell.swift
@dynamicMemberLookup public class GenericTableViewCell<View : UIView>: UITableViewCell {
    
    public let customView: View = .init(frame: .zero)
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        commonInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        
        commonInit()
    }

    public subscript<U>(dynamicMember keyPath: ReferenceWritableKeyPath<View, U>) -> U {
        get {
            customView[keyPath:keyPath]
        }
        
        set {
            customView[keyPath:keyPath] = newValue
        }
    }
    
    private func commonInit() {
        contentView.addSubview(customView)
        
        customView.translatesAutoresizingMaskIntoConstraints = false
        customView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        customView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
        customView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
        customView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
    }

}

```

# この構造のメリット
`UITableViewCell`をサブクラスしてViewを構築していく時の問題として、例えば表示内容は全く同じなのに`UICollectionView`を利用した別の画面を作る必要が出た時に移行がすごく面倒です。

なので、普段から`UIView`ベースでViewを作成してGenericなTableViewCellに載せる構成にしておくことで、プロジェクトの変更・拡張に対してロバストです。

# この構造のデメリット
Viewスタックが一層余分に増え、そのままではアクセスも`customView`プロパティ経由になるので少し冗長になります。

なので、後者の問題を消すために`dynamicMemberLookup`を採用し、直接内部Viewへのアクセス可能にしています。

# 使い方
## TableViewへのセルの登録

```swift:Register.swift
tableView.register(GenericTableViewCell<YourCustomView>.self, forCellReuseIdentifier: "Cell")
```

## セルの表示

```swift:Use.swift
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! GenericTableViewCell<YourCustomView>

```

# CollectionViewCellでは？
`CollectionViewCell`でも同じような仕組みを作る事ができます。実装はほぼ変わりません。


## 追記
コメントで頂いたのですが、この記事では

```swift
public let customView: View = .init(frame: .zero)
```

としていますが、これではNib経由でのUIViewのインスタンス化が出来ません。

Nib経由でのインスタンス化に対する柔軟性が欲しい場合は、`<View: UIView>`とせずに生成は別の具体型に任せるFactoryMethodのようなデザインにすると良いでしょう。

詳しくはコメント欄をチェックしてみてください！
Rails.cache.fetch を正しく運用する！Active Record オブジェクトをキャッシュしたい時


# 問題

Rails エンジニアなら一度はハマる現象。

 `Rails.cache` で Active Record オブジェクトをキャッシュする際、キャッシュしたは良いものの、毎回クエリが発行されてしまう場合があります。

例えば以下のコード。

```ruby
Rails.cache.fetch(key) do
  User.where('status = 1').limit(1000)
end
```

# 原因と解決策

[Rails.cacheの落とし穴](https://waterlow2013.hatenablog.com/entry/2018/01/17/005335) の記事に分かりやすく原因と解決策が書かれているので引用します。

> ActiveRecord は評価を遅延させます。@users = User.allとしてもすぐにSQLが発行されることはなく@users.eachなど発行するクエリが決まった段階でクエリ発行されるわけです。

>結論に書いたケースだとUser::ActiveRecord_Relationのインスタンスがキャッシュに入り、インスタンスが評価された段階でSQLが発行されるため、結果としてキャッシュを使っても毎回SQLが発行されてしまうわけです

> 以下の用にto_aを使ってクエリを即時発行すればOK。

```ruby
Rails.cache.fetch(key) do
  User.where('status = 1').limit(1000).to_a
end
```

# デメリット


しかし `.to_a` や `.all` を使ってキャッシュさせる場合、以下のようなデメリットがあります。

- DB のレコードやカラムに変更があった場合、キャッシュされたオブジェクトには適用されないため、不整合が起きる可能性がある
- 巨大なオブジェクトをキャッシュするのはコストがかかるので、メモリを埋め尽くす可能性がある
- 利用元で `ActiveRecord::Relation` 特有のメソッド（`where`など）が利用できなくなる

# 好ましい形

```ruby
user_ids = Rails.cache.fetch(key) do
  User.where('status = 1').limit(1000).pluck(:id)
end
@user = User.where(id: user_ids)
```

上記のデメリットを回避したい場合、id などの変更されない値をキャッシュすることを考えます。

この場合、 `User.where(id: user_ids)` は常に実行されますが、主キーを使用したクエリなので処理は高速です。これにより、先に説明したデメリットを回避しつつキャッシュを有効活用できます。

# 参考リンク

[Confusion caching Active Record queries with Rails.cache.fetch
](https://stackoverflow.com/questions/11218917/confusion-caching-active-record-queries-with-rails-cache-fetch)
RSpecを使ったRailsのテストについて

#自動テストのメリット
はじめに自動テストを行うメリットを列挙すると以下のものがあげられる。

・テスト全体にかかるコストの削減
・変更をフットワーク軽く行えるようになる
・環境のバージョンアップやリファクタリングのため
・適切な粒度のコードになりやすい
・確実性を高めることで開発効率をあげる

#自動テストを行うのに必要なツール

##RSpec
Rubyのテスティングフレームワークの一つ。
他にはMinitestなどもあるが、開発現場で広く使われているのはRSpecらしい（現役エンジニアの方から聞いた話。）

仕様書を書くようにテストコードを書くので、どのように書けばいいのかイメージしやすい。

参照：https://qiita.com/ShuntaShirai/items/465ddfc2c0f29ed93523

##Capybara
WebアプリケーションのE2E（End-to-End）テスト用フレームワークの一つ。
RSpecなどのテスティングライブラリと組み合わせて使う。
Webアプリケーションのブラウザ操作をシュミレーションできる。

参照：https://qiita.com/morrr/items/0e24251c049180218db4

##FactoryBot
テスト用データの作成をサポートするgem。
テスト用データを簡単に用意できて、テストから呼び出して利用することができる。

参照：https://qiita.com/morrr/items/f1d3ac46b029ccddd017

#テストの種類
「テスト」には様々な種類がある。

###全体的なテスト
・システムテスト（RSpecではSystem Spec, Feature Specと呼ばれている）
・結合テスト
・機能テスト

###個々の部品のテスト
・モデル
・ルーティング
・ビュー
・ヘルパー
・メーラー
・ジョブ

いずれも重要なテストだが、特に重要なのはテストの粒度として一番大きく外側に位置しているシステムテスト。

#System Specの書き方
代表的なSystem Specの例を示すためにタスク一覧表示機能のテストを書いていく。

タスク一覧表示機能のテストには
・ユーザーのデータ
・タスクのデータ
が必要なのでFactoryBotを使ってテストデータを作る。

```spec/factories/users.rb
FactroryBot.driven do
  factory :user do
    name { 'テストユーザー' }
    email { 'test1@example.com' }
    password { 'password' }
  end
end
```

```spec/factories/tasks.rb
FactoryBot.driven do
  factory :task do
    name { 'テストを書く' }
    description { 'テストの準備' }
    user #users.rbで定義したuserという名前のFactoryと関連を生成する。という意味。
  end
end
```
これでデータの準備完了。

そしてSpecのコードを書いていく

```spec/system/tasks_spec.rb
require 'rails_helper'

describe 'タスク管理機能', type: :system do
  describe '一覧表示機能' do
    #before doでFactoryBotで作ったデータを読み込み、適宜オーバーライドしていく
    before do
      user_a = FactoryBot.create(:user, name: 'ユーザーA', email: 'a@example.com')
      FactoryBot.create(:task, name: '最初のタスク', user: user_a)
    end

    context 'ユーザーAがログインしているとき' do
      before do
        #visit [URL]でURLを指定
        visit login_path
        fill_in 'メールアドレス', with: 'a@example.com'
        fill_in 'パスワード', with: 'password'
        click_button 'ログインする'
      end

      it 'ユーザーAが作成したタスクが表示される' do
        #expect(表示場所).to have_content'内容'　で「どこ」に「どんな内容」が期待されるのか書く
        expect(page).to have_content '最初のタスク'
      end
    end
  end
end
```
#補足
この例では簡単なテストなので簡潔に書けるが、さらに複雑なテストを書いていく場合には``before``、``let``、``shared_example``を使って共通化すると、簡潔でまとまったテストを記述することができる。

参照：https://qiita.com/hirotakasasaki/items/fa3b131e27f5d0694c2c
参照：https://qiita.com/yu-croco/items/d0088a75b033d46f8c39
AWS・Elastic Beanstalk・Djangoを使って無料ストレージサービスをリリースしました

タイトルの内容そのままです。基本的にはドメインもサーバーもAWSに頼りました。今回はDjangoとElastic Beanstalk、RDS、S3、Route53、ACMで作っています。

GW中に何か一つサービスをリリースしたかったのですが、Gigafile便とかおくりん坊みたいな無料ファイル転送・オンラインストレージサービスで、Google Adsenseで収益化できないかなと思って作りました。全部で１週間位だと思います。

あと、Djangoの強いところに国際化があります。.poファイルをコンパイルするだけで簡単に多言語化できます。

取り急ぎ、スタックのご紹介でした。firestorageみたいにログインして容量緩和とかもやってみたいなと思っています。

<h2>無料・大容量のファイル転送サービスLettace(レタス)</h2>

https://lettace.net/ja/

![main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300500/72a66fe7-ecbb-a63a-ce08-890f7373048d.png)
[Python] cx_FreezeでTkinterのプログラムの配布ファイルを作成する

# 1. はじめに

Tkinterで作ったGUIプログラムを、配布するときに、**exe実行ファイル**より**Installer**として渡したほうがいいと思います。cx_Freezeにその機能があったので、それを試してみました。

今回、Installer化するプログラムはこちらです。（OS:Windows 10, 64bit)

[[Python] Tkinterで複数のWindowを表示](https://qiita.com/kotai2003/items/0d6bafb753bb0374033c#comment-d311e5235323de155626)

*file name：multi_winews_tkinter.py*

# 2. cx_Freezeの設置

Anacondaを使っているため、pipではなくcondaで設置します。

```
conda install -c conda-forge cx_freeze
```

# 3. setup.pyファイルの作成
Pythonのプログラム（*file name：multi_winews_tkinter.py*）が置いてあるフォルダーにsetup.pyを作成します。

setup.pyの書き方は、こちらのページを参考にしました。
様々な用途の、サンプルsetup.pyが容易されているので、参考にしてください。（例：PyQTでGUI作成）
[https://github.com/anthony-tuininga/cx_Freeze/tree/master/cx_Freeze/samples](https://github.com/anthony-tuininga/cx_Freeze/tree/master/cx_Freeze/samples)

```Python:setup.py
import sys
from cx_Freeze import setup, Executable

base = None
if sys.platform == 'win32':
    base = 'Win32GUI'

executables = [
    Executable('multi_windows_tkinter.py', base=base)
]

setup(name='simple_Tkinter',
      version='0.2',
      description='Sample cx_Freeze Tkinter script',
      executables=executables
      )
```

# 4. InstallerファイルのBuild

ターミナルで、下記の命令を実行します。

```
python setup.py bdist_msi
```

そうなると、Installerファイル(msiファイル）が形成されます。今回のInstallerの容量は、11MBでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/e0b841e6-c12a-2efd-f468-c540b7038656.png)

# 5. 別のPCでInstallerを実施

Python環境が設置されていないPCで、上記のInstallerファイルを実行します。
下記の画面が表示され、設置が始まります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/26f9f34b-fada-ca7f-10e0-48627e07c784.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/216ae6f8-cf22-5632-1bd9-0adb65d6ba25.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/852c9a0b-70d0-5b16-e983-bcc6ad8f90dc.png)

設置結果、問題なく動作しました。
最後に、アンインストールしたい時には、Windows Control Panelで他のWindows Program同様、簡単にアンインストールが可能です。便利ですね。

# 6. まとめ

1. cx_FreezeでTkinterプログラムの配布ファイルを作成。
2. Exe形式ではなく、Installer形式を作成。
3. Python環境がないパソコンにInstallし、無事に動作していることを確認。

　cx_Freezeいいですね。動作も早いし、生成ファイルのサイズも小さく、満足しています。


#参考資料

1.[[Python] Tkinterで複数のWindowを表示](https://qiita.com/kotai2003/items/0d6bafb753bb0374033c#comment-d311e5235323de155626
)
2.[cx Freeze distutils setup script](https://cx-freeze.readthedocs.io/en/latest/distutils.html
)
3.[cx Freeze setup examples ](https://github.com/anthony-tuininga/cx_Freeze/tree/master/cx_Freeze/samples)
エンジニアの業種を整理してみた

#はじめに
以前転職活動をした際（当時は社内SEから社内SEを目指していた）に、
「IT系の業種ってわかりにくいな🤔」と感じていました。

エージェントや現役エンジニアの方に聞いた情報や、自分で調べた情報をもとに、エンジニア・ITの業種を少しまとめてみました。

網羅的でなく私見も入っていますが、よかったら見てください🙇‍♂️
（ご指摘いただけるとありがたいです！）

※ちなみに私は、都内の40名ほどの企業で社内SE(1人情シス)しています。

# 追記（2020/07/29）
自社開発企業のメガベンチャーから内定をいただけました。
立てた転職戦略をnoteにまとめたので、もし興味があれば覗いてみてください🙇‍♂️

[未経験からWeb系エンジニアへ転職するために立てた逆算戦略〜【仕事しながら6ヶ月でメガベンチャーから内定獲得】〜](https://note.com/sew_sou/n/n6d7b5f7cbefd)

#どの業種でも最終ゴールは共通する

どの業種・職種を選択した場合も最終的には
**「上流工程・マネジメント」がゴール**になってくる。

そうしないとキャリアアップできず、ずっと低い単価で下流工程やることになるためです。
(ずっとコーディングだけやるプログラマーになりたいなら別ですが、、、)

※上流工程・下流工程についての説明は、この辺りの記事がわかりやすいです。
[システム開発での上流工程と下流工程の違いと求められるスキルとは](https://crowd.itpropartners.com/pieceblog/752)

#業種別の特徴
##自社開発(いわゆるweb系)
「こういうシステムあったら便利では！！」と自社でサービスにして収益化

```
・1→10の経験（既存サービスのグロース・運用）がメイン。0→1もある
・納期等が緩くブラックになりにくい
・自分の意見がシステムに反映されやすい（裁量が大きい）
・特定の言語スキルしか身につかない可能性がある
・自社サービスありきなので、業種によっては不況の煽りを受けやすい
（逆にサービスがバズれば一気に規模拡大する）
・求人が少ない、競争率が高いので未経験にはハードルが高い
```

##受託開発(いわゆるSIer)
顧客(企業)から「こういうシステム開発してくれ！」と案件を受注して開発

```
・0→1の経験（企画、要件定義など0からシステム作る）ができる
・多くのプロジェクトに携わるので、業務の幅もスキルの幅も広がりやすい
・企業として安定しやすい（営業力にもよるが）
・顧客ありきなので、裁量は小さい傾向。顧客に振り回される可能性
・2次請けなど、下層になればなるほど納期がシビア＝ブラック度が上がる
・第二新卒なら未経験、ポートフォリオなしでも潜り込める可能性ある
```
※いわゆる`IT土方(どかた)`と言われるのはここです。
建築業界と同じように、大手ゼネコン（＝プライムベンダー）が大口受注し、それを2次請け・3次請けに外注しているのと同じ構図が発生しているためです。

※Sierはさらに独立系・メーカー系・ユーザー系・外資系など種類が分かれますが、今回は省きます。

##SES (System Engineering Service)
・顧客(企業)から「うちでシステム開発してるけど人手足りないから来て！」とクライアント企業に常駐して開発

```
・人材派遣とは違う（指揮命令権が雇用されている企業にある。派遣は指揮命令権がクライアント企業）
・未経験者にはハードルが低い（と言われている）
→単に求人の数が多いから？
・客先常駐が嫌な人には向かない→人間関係を案件毎に1から築く必要ある
（逆に色んな企業を見たい人には向いている）
・常駐先で成果を出せばその企業からスカウトされることもある（らしい）
・上流工程には携わりにくい
・案件ガチャの可能性がある（現場によっては、Excelのコピペをひたすら繰り返すだけ、、みたいな）
・割り切って「実務経験あり」になるためならアリなのかと
```

##ITコンサル
「おたくの会社はここが課題だけど、こういうシステム入れれば解決するよ！」と助言・開発する

```
・上流工程がメイン
・開発など実際手を動かすことはほぼない
（アクセンチュアなど一気通貫型のところはチームによってある）
・最近は一気通貫型になる流れが強まりつつある
・めちゃくちゃハードだが年収高い
・転職よりは新卒から入る方がハードルが低い（印象）
・論理的思考力が求められる（CAB・GABみたいな）
・国内企業はそれぞれ国内での成長の限界、危機感（国内マーケットの売上減少を危惧してる)
→グローバル進出における課題が多い
・英語力が求められる企業が多い
```
※コンサルも分けると種類がかなりあるので、説明は省きます。

##事業会社の社内SE　⇦ 今の僕がここ
「社内でこういう業務をもっと効率化できたら便利だよね！」と社内で使うシステムを開発

```
※会社によって形態が大きく異なるので、一般的なものを
・上流工程がメイン
・最終ゴールはCIO(最高情報責任者)寄り
・社内のシステム開発なので納期など緩い（自社開発企業に近い）
・システムの規模＝会社の規模なので、事業の成長と仕事の幅が比例する
・実際に手を動かすことはほぼない（ベンダーコントロールがメイン）
・規模の小さい会社だと外注orSaasのカスタマイズしかやらない
・ワークライフバランスは高いが、中小だと物足りなくなく感じるかも（スキルも身につきにくい）
・社内SE→社内SEの転職は、前職の規模感をかなり重視される
```

###自社開発企業との違い
- 「会社外で使うシステムの開発（＝自社開発）」→本来の事業の開発に携わる
- 「会社内で使うシステムの開発（＝社内SE）」→本来の事業は別 

※社内システムを外販することはある

##その他（調査中）
- インフラエンジニア
- SE（Web系以外）


#どの業種・職種に就きたいか？を考えるには
一番大事なのは`自己分析`です。

「なんでウチ（自社開発企業）で働きたいの？」という質問に
「かっこよさそうだから！」「インフルエンサーがおすすめしてたから！」という回答はNGです。

自分が仕事を通じて何をしたいか、どういう働き方をしたいか、に照らした根拠のある回答が必要です。
そのためにも、各業種の特徴をとらえ、自分の軸だったらどこが最適化？を深く考えましょう！

#おまけ
※完全に私見の就職難易度です
・自社 ⇒ 4
・受託(プライム) ⇒ 3
・受託(二次請け以降) ⇒ 2
・SES ⇒ 1
・ITコン ⇒ 5
・社内SE(大手) ⇒ 4.5
・社内SE(中小) ⇒ 3.5
vscodeの説明の補足

「萌え系テキスト」[^1]の画面キャプチャがすこし古くて迷われるかもしれませんので，補足を加えておきます．英語の表記がデフォルトなんで，そちらで表示しています．

## プログラムを実行してみよう
テキストのp.28あたりです．viewのところにもterminalがあるんですが，terminalというメニュー項目からえらんでください．
![2020-05-10 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151211/1cdde339-9032-df41-6229-9cad5ffac914.png)
![2020-05-10 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151211/34b92a64-282c-acd7-c019-250b8c3baa29.png)
![2020-05-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151211/e6b98f52-30c2-79ee-2398-22cb03f21261.png)

それとうまくpythonが起動できないかもしれません．そのときは，起動するpythonを正しく選択するようにしてください．下のステータスバーの左に表示されたpythonのバージョンを選択して，真ん中上に現れる選択肢のなかから選んでください．授業中におこなったpython.orgからdownloadしたのは，今表示されているどちらもが動くはずです．
![2020-05-10 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151211/f6e9b4f2-a5c3-7954-27c2-f1443ee39e6e.png)

## 2章の出力
2章でつくった時間問い合わせゲームのひな型です．
![tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151211/83b884c2-b6de-ee82-1737-25c6b9c01f87.png)

# my_birthday_calendar
5/15の課題のmy_birthday_calendar.pyのソースコードと実行結果です．
わたしは幾つでしょう？
![c1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151211/ca94261c-346b-24f0-dbf4-9a7303973265.png)

[^1]: 「12歳からはじめる ゼロからの Pythonゲームプログラミング教室」, 大槻有一郎 (著), リブロワークスPython部 (著), 雪印 (イラスト), ラトルズ(2017/5/11)．
Eclipseでコンストラクタを自動生成する方法

# はじめに
久方ぶりにJavaとEclipseを触りました。昔Eclipseを使っていた時なんか使いづらいと感じ食わず嫌いのような感じになっていましたが、ショートカットや機能を憶えるとなかなか使いやすいんじゃないかと思いました。とりあえず今回はコンストラクタの自動生成のやり方について書きます。
# フィールドからコンストラクタを自動生成
例えばこんなクラスがあるとします。

```Java
public class Dog {
	String name;

	void bark() {
		System.out.println(name + ":「Bowwow.」");
	}
}
```

ここでコンストラクタをいちいち手入力するのはめんどくさいのでメニューバーのSource →Generate Constructor using Fields...を選択して、設定したいフィールドを選びgenerateをクリックすると、コンストラクタを自動生成してくれます。
![con1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267562/044154de-3892-9b0c-e492-cfdad4da5604.png)
![con2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267562/0fcb71b6-46de-7ad4-f148-48e7d56505b0.png)


```java

public class Dog {
	String name;

	void bark() {
		System.out.println(name + ":「Bowwow.」");
	}

	public Dog(String name) {
		super();
		this.name = name;
	}
}
```

これで時短になります。
５G時代に向けた新サービス? Azure Edge Zone って何？

5Gを生かした新たなAzureのサービスとして出てきた「Azure Edge Zone」がプライベートプレビューが2020年夏頃開始という情報がでたのでどういったものなのか調べてみました
公式ドキュメントは[こちら](https://docs.microsoft.com/en-us/azure/networking/edge-zones-overview)

### そもそもAzure Edge Zone とは
低遅延を必要とする５Gアプリケーションを、少ないホップ数で、クラウドのコンピューティング能力、ネットワーク、ストレージに接続できるようにするマネージドサービス。

Azure Edge Zone は Azureネットワークの一部で、ユーザに近いエッジ(キャリアやデータセンター)でアプリケーションが実行され、Azureと低遅延でつながるようになっている
Azure Edge Zoneはマイクロソフトで管理運用され、デプロイはポータルから可能

実装方法としては下記3つのやり方

・Azure Edge zone
・Azure Edge Zone with Carrier
・Azure private Edge Zones

### Azure Edge Zone with Carrier
モバイル向けにキャリアと提携し、キャリアデータセンタに Edge Zone を配置することで10ミリSec未満のレイテンシーを実現することが可能
Azure と Edge Zone 間は

### Azure private Edge Zones
お客様のローカル内にでAzure が利用できるAzure Stack の一部 (Azure Stack Edge) として利用者のローカルデータセンタ内に置くことが可能
またプライベートモバイルネットワークのEdgeとしても利用可能

どちらにしてもまだまだ構想段階なので実際にもっと詳しい情報が出てきたところでUpdateしたいと思います
Ruby on Railsでweb-consoleを使う方法

プログラム勉強中です。自分の備忘録として投稿します。

# web-consoleを使う方法
```config/environments/development.rb
Rails.application.configure do
  config.web_console.whitelisted_ips = %w[127.0.0.1 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16]
end
```
【Rails】ページごとに表示を変える

# 目的
ページごとに共通部分を変えたり、ユーザーの状況によってページ表示される内容を変えたい
# 前提
deviseを導入している（ユーザー がログインしているか？で使う）

# 色々なパターン（具体例を提示）
①ユーザーがサインインしているか？で条件分岐
②訪れているページがどこか？で条件分岐
③コントローラーごとに共通部分を分ける
④アクションごとに、共通部分を分ける

他にも色々あるとは思いますが、自分が試した物を書きます。

# 実装例①ユーザーがサインインしているか？で条件分岐

```html.haml

- if user_signed_in?

```
これはよく使うのが、サインインしていれば新規投稿ボタンが表示されるなど
上記で囲み

    user_signed_in?
でログインされていたら表示するという使い方をする

# 実装例②訪れているページがどこか？で条件分岐

### root_path かどうか
    current_page?(root_path)

### /users/:id が current_user かどうか
    current_page?(current_user)

### 任意のコントローラ/アクションかどうか
    current_page?(controller: 'foo', action: 'bar')

###　URLが"sign_in"という文字を含む時、link_toを非表示

```html.haml
- unless request.path.include?("sign_in")
# URLが"sing_in"をいう文字を[含まない時]、次の処理を実行

  = link_to "サインイン", new_user_session_path

# つまり、"sing_in"をいう文字を含む時、下の処理は実行しない（表示しない）
```

# 実装例③コントローラーごとに共通部分を分ける
「app/views/layouts/任意の名前.html.haml」というファイルを用意する

```
class コントローラ名 < ApplicationController
  layout 'レイアウトファイル名'

  def アクション名
  end
end
```

# 実装例④アクションごとに、共通部分を分ける
「app/views/layouts/任意の名前.html.haml」というファイルを用意する

例えばapp/views/layouts/compact.html.hamlを用意

compactの記述を反映させたいアクションに以下の記述をする。

```
class コントローラ名 < ApplicationController
  def アクション名
    render layout: 'compact'
  end
end
```

# 参考文献
https://www.javadrive.jp/rails/template/index3.html
https://qiita.com/Yohei_Shiina/items/ed39dfd74895d54f3cf2
Elixir製の小説家になろうAPIラッパーをリリースしました

Elixirでの小説家になろうAPIラッパーがなかったので作成しました。

Elixirらしく書けるようにするために、パイプオペレータでクエリを実行できるようにしました:ok_hand:

[リポジトリ](https://github.com/harukikubota/narou)

## インストール

```elixir:mix.exs

# Elixirのバージョンは1.10以上必要

def deps do
  [
    {:narou, git: "https://github.com/harukikubota/narou.git"}
  ]
end
```

## 使い方

### [小説検索](https://dev.syosetu.com/man/api/)

```elixir
iex> use Narou
iex> Narou.init(%{type: :novel})
    |> select([:t, :w])
    |> where(ncode: "n2267be")
    |> Narou.run!

    {
      :ok,
      1,
      [
        %{
          title: => "Ｒｅ：ゼロから始める異世界生活",
          writer: => "鼠色猫/長月達平"
        }
      ]
    }
```

### [ランキング検索](https://dev.syosetu.com/man/rankapi/)
こちらは日付とランキングタイプを指定して、作品毎のポイントを取得します。

```elixir
iex> use Narou
iex> Narou.init(%{type: :rank})
    |> where(y: 2020, m: 03, d: 31, t: :d)
    |> Narou.run!

    {
      :ok,
      [
        %{"ncode" => "N7378GC", "pt" => 4450, "rank" => 1},
        %{"ncode" => "N7529GB", "pt" => 4280, "rank" => 2},
        %{"ncode" => "N2361GC", "pt" => 3698, "rank" => 3},
        %{...},
        ...
    }

```

### [殿堂入り検索](https://dev.syosetu.com/man/rankinapi/)
こちらは作品を指定して、いつ、どのランキングに入ったか検索します。

```elixir
iex> use Narou
iex> Narou.init(%{type: :rankin})
    |> where(ncode: "n2267be")
    |> Narou.run!

    {:ok,
      [
        %{pt: 90, rank: 103, rtype: "20130501-d"},
        %{pt: 4739, rank: 72, rtype: "20130501-m"},
        %{pt: 9947, rank: 86, rtype: "20130501-q"},
        %{...},
        ...
    }

```

### [ユーザ検索](https://dev.syosetu.com/man/userapi/)

```elixir
iex> use Narou
iex> Narou.init(%{type: :user})
    |> select([:userid, :name, :yomikata])
    |> where(userid: 235132)
    |> Narou.run!

    {
      :ok,
      1,
      [
        %{
          name: "鼠色猫/長月達平",
          userid: 235132,
          yomikata: "ネズミイロネコ/ナガツキタッペイ"
        }
      ]
    }

```

### その他細かい機能

細かい使い方などは `iex`からモジュールヘルプで参照できるようにしています。`iex> h Narou`

#### `Narou`
APIの種類と、初期パラメータを設定します。

`lib/narou/api_struct/`に`init/1`の戻り値構造体が定義されてます。

#### `Narou.Query`
`select`, `where`, `order`を定義しています。

#### `Narou.ApiKeyNameConverter`
`select`句で指定するキー名のテーブルを確認できます。

### あとがき
筆者はElixirの勉強を始めてからまだ一週間ですが、ここまでのものを無事リリースできました。

Rubyでのライブラリ開発の経験も大きいんですが、Elixirの言語機能が強力なおかげで楽に書けてますw

最後に一言。

---
> シャンフロはいいぞおじさん「[シャンフロ](https://ncode.syosetu.com/n6169dz/)はいいぞ。」

---
帯域とはなにか？言葉の使われ方と変遷


通信速度について調べた時に出てくる謎キーワード「帯域」
2.4Ghzだと5Ghzだの出てきてそれが何なのか解説するのが難しい「帯域」

一体全体この帯域とは何を示しているのでしょうか？
この記事ではその帯域について解説致します。


#帯域とは複数の意味がある単語、元々は「電波の周波数の範囲」を指す

帯域には現在では複数の意味が存在しています。
元々帯域とは、占有する周波数の幅の事を指していました。

例：900Mhz~950Mhzの帯域を使う場合、帯域は差の「50Mhz」という感じになり、また、900~920Mhzなら「20Mhz」という感じになります。

この幅は、広ければその分だけ同時に伝達できる情報の数が増える為、一定時間あたりの通信量が大きく、その分素早い通信が可能になります。

つまり帯域とは、元々は**情報を送る水道管の太さ**を指しています。

#帯域が太い≒通信速度が良い、なので転じて「通信速度」の意味で使われるようになった。

帯域は元々通信域の太さというニュアンスで使われていましたが、使用者の観点からすると太さはどうでもよく、それより速いかどうかが求められてしまいます。
なので、一般には帯域が広いという言い方は、「通信速度が速い」というニュアンスで話されることが多いのです。

元の意味からかけ離れたニュアンスの言葉になったわけではないですが、**実用的な面を全面に出す表現へと変わった言葉**と言えそうです。


#まとめ

帯域とは、

**元々は、電波の周波数の範囲を指す言葉**
**一般的には、通信速度そのものを指す言葉**
Slack APIのchannels.historyが使えなくなる対策

#Slack API / channels.history から conversations.history への移行メモ
Slack APIのドキュメントを見ていたら、channels.historyは、2020/6以降のアプリでは使用できない、2020/11以降は全面廃止とのことなので、記載されている通りに conversations.history に移行してみた。

完全に同じというわけではなくて、違いがあるので、気づいたところのメモ

https://api.slack.com/methods/channels.history
https://api.slack.com/methods/conversations.history

##パラメータ
unreads が無くなった。これは未読メッセージの数を返すことがなくなったということ。unread_count, unread_count_display は全般的に廃止されたっぽい。Slackは既読をあえて明示しないポリシーなので、APIからも削除したのかも。

##Response
大きな違いは、conversations.history は、スレッドメッセージを返さなくなったこと。

## channels.history からの移行戦略
channels.history はスレッドメッセージを含んだ形で全メッセージを返していた。一方、conversations.history はスレッドメッセージを含まず、それを取得するための別API conversations.replies を使う必要がある。

https://api.slack.com/methods/conversations.replies

conversations.replies は、token, channel に加えて ts が必須パラメータとなる。ts は親メッセージの ts である。

（余談：ts は、ドキュメントでは"Unique Identifier"と説明されているが、おそらく Time Stampだったんだろう。でもTime Stampだと同じ時間に投稿した場合は？みたいな疑問が出てくるので、"Unique Identifier"に読み替えたと思う。数値からして Time Stampだが、Unique にするために同じchannel内で同じTime Stampは発生しないように調整していると思われる。
検証したわけではないが、channel+token+tsの３つでの組み合わせがuniqueになるように設計されているのだろう。）

conversations.history の messagesのうち、スレッドを持つものは、

* "thread_ts" : スレッドとしてのts。 (tsと同じ値であった)
* "latest_reply" : 一番新しいリプライのts
* "reply_users" : リプライを書き込んでいるユーザの一覧(配列)
* "reply_users_count" : リプライを書き込んでいるユーザの数

が返る。

よって、(message.thread_ts!==undefined) の時に、{"ts":thread_ts}で conversations.replies を呼び出せば良い

##channels.historyと同様の結果を得る
もし、channels.history と同様に、スレッドメッセージまで一緒くたになっているリストが欲しいのなら、

* conversations.history でメッセージ配列を取得
* 取得したメッセージから thread_ts を持つものをすべて抜き出し、それぞれ、conversations.replies を呼び出し、結果をマージしてゆく
* マージが終了したメッセージ配列を ts をキーにソートする

で、ほぼ同じ結果が得られる。
ただし、conversations.history にわたす limit より、スレッドの分が追加され、メッセージ数は大きくなるなど、完全に同じにはならない。
PyTorchで層化分割(Stratified Split)を行う

## 層化分割(Stratified Split)とは
機械学習をしていると、データセットを学習用データとバリデーション用データに分割することがよくあります。特に分類問題の場合、クラスラベルを考慮せずランダムに分割してもいいのですが、分割後のデータのクラスラベルの分布が元データと同じになるように分割するのが望ましいです。このように各クラスの比率を保ったまま分割することを、層化抽出とか層化分割(Stratified Split)と言います。

## PyTorchでの実装例
scikit-learnでは`sklearn.model_selection.train_test_split()`という関数に`stratify`オプションを渡すことでStratified Splitを行うことができます。

一方、PyTorchにはそのような仕組みがありません。`torch.utils.data.random_split()`のような関数を使えばデータセットをランダムに分割することはできますが、ストレートにStratified Splitを行うことはできません。そこで、scikit-learnの`train_test_split()`と組み合わせることで、Stratified Splitを実現します。

例えば、次のようなコードでStratified Splitを行うことができます。

```python
import torch
import torchvision.transforms as transforms
from sklearn.model_selection import train_test_split

transformer = transforms.Compose([
    transforms.ToTensor(),
])

# 画像を読み込む
dataset = torchvision.datasets.ImageFolder(root='directory_name', transform=transformer)

# データセットをtrainとvalidationに分割
train_indices, val_indices = train_test_split(list(range(len(dataset.targets))), test_size=0.2, stratify=dataset.targets)
train_dataset = torch.utils.data.Subset(dataset, train_indices)
val_dataset = torch.utils.data.Subset(dataset, val_indices)

# DataLoaderを作成
train_data_loader = torch.utils.data.DataLoader(train_dataset, batch_size=4, shuffle=True, num_workers=4)
val_data_loader = torch.utils.data.DataLoader(val_dataset, batch_size=4, shuffle=True, num_workers=4)
```

順に説明します。

初めに、ImageFolderで画像を読み込んでDatasetを作成しています。

```python
transformer = transforms.Compose([
    transforms.ToTensor(),
])

dataset = torchvision.datasets.ImageFolder(root='directory_name', transform=transformer)
```

次に`train_test_split()`でデータを分割しますが、Datasetを直接渡すことはできないので、`list(range(len(dataset.targets)))`でDatasetのインデックス配列(`[0,1,2,3,...データ数]`)を生成し、それを代わりに渡します。そして、このインデックス配列に対するクラスラベル`dataset.targets`を`stratify`オプションとして渡すことで、元データのクラスラベルの比率を保ったまま、インデックス配列を学習用とバリデーション用に分割することができます。

```python
train_indices, val_indices = train_test_split(list(range(len(dataset.targets))), test_size=0.2, stratify=dataset.targets)
```

分割したのはあくまでインデックス配列なので、そのインデックスを元にデータセットを分割します。Subsetはその名の通りデータのサブセットを作るためのクラスで、元となるDatasetとインデックス配列を渡すことで、インデックスに対応するDatasetを生成できます。

```python
train_dataset = torch.utils.data.Subset(dataset, train_indices)
val_dataset = torch.utils.data.Subset(dataset, val_indices)
```

あとはいつも通りDataLoaderにDatasetを渡してあげるだけです。

```python
# DataLoaderを作成
train_data_loader = torch.utils.data.DataLoader(train_dataset, batch_size=4, shuffle=True, num_workers=4)
val_data_loader = torch.utils.data.DataLoader(val_dataset, batch_size=4, shuffle=True, num_workers=4)
```

## 参考サイト
https://discuss.pytorch.org/t/how-to-do-a-stratified-split/62290
[Python] Tkinterで複数のWindowを表示

#はじめに

Tkinterで複数のWindow画面を表示する方法を説明します。

#結果
[Tkinterのクラス化のテンプレート](https://qiita.com/kotai2003/items/fe9b5e59c7164a95ded8
)を利用しました。
下記の手順で、コードを組み立てます。

1. Window 1のためのWin1クラスを用意する。
2. Window 2のためのWin2クラスを用意する。
3. Win1クラスのCall back function（Buttonを押すときの動作）に、Windows 2を開ける動作を定義する。

![bandicam-2020-05-11-11-46-00-975.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/501863da-16ce-0fa3-b7aa-87d810250e44.gif)


#プログラミングコード

```Python
import tkinter as tk
from tkinter import ttk

class Win1(tk.Frame):
    def __init__(self,master):
        super().__init__(master)
        self.pack()

        self.master.geometry("400x400")
        self.master.title("window 1")
        self.create_widgets()

    def create_widgets(self):
        # Button
        self.button_new_win = ttk.Button(self)
        self.button_new_win.configure(text="Open Window 2")
        self.button_new_win.configure(command = self.new_window)
        self.button_new_win.pack()

    #Call back function
    def new_window(self):
        self.newWindow = tk.Toplevel(self.master)
        self.app = Win2(self.newWindow)



class Win2(tk.Frame):
    def __init__(self,master):

        super().__init__(master)
        self.pack()
        self.master.geometry("300x300")
        self.master.title("window 2")
        self.create_widgets()

    def create_widgets(self):
        # Button
        self.button_quit = ttk.Button(self)
        self.button_quit.configure(text="Close Window 2")
        self.button_quit.configure(command=self.quit_window)
        self.button_quit.pack()

    def quit_window(self):
        self.master.destroy()


def main():
    root = tk.Tk()
    app = Win1(master=root)#Inherit
    app.mainloop()

if __name__ == "__main__":
    main()

```

#参考資料

1. [【Python】Tkinterのテンプレート](https://qiita.com/kotai2003/items/fe9b5e59c7164a95ded8)


2.　[Tkinter example code for multiple windows](https://stackoverflow.com/questions/16115378/tkinter-example-code-for-multiple-windows-why-wont-buttons-load-correctly)
SQL Server 統計情報更新の動作とSQLまとめ

# 概要

- SQL Serverではデフォルトで自動統計情報更新が有効で、色々条件はあるがざっくり20%以上のデータ変動があったら自動で更新される。
http://tech.kou.asia/?p=1672

- この場合、件数が増えると20%に達するまでに時間がかかる。
それを回避するためにトレースフラグ2371をオンにすることで動的閾値を利用した統計更新を実現できる。
http://azwoo.hatenablog.com/entry/2013/02/14/125848

- 商用環境では想定外の動きになるのを防止するため自動更新機能は利用せず自前で統計情報更新の処理を実装する事を検討。
https://docs.microsoft.com/en-us/archive/blogs/jpsql/on-12


- デフォルトでは統計情報の自動更新はInsert/Update文の一部として実行されるが、"AUTO_UPDATE_STATISTICS_ASYNC"をONにする事により非同期に実行する事ができる。
https://docs.microsoft.com/en-us/archive/blogs/jpsql/on-12
https://fyts.hatenadiary.org/entry/20081112/async


# SQL

## 統計情報の自動作成

#### 設定状況確認

```
select
  name 
  ,is_auto_create_stats_on
  ,is_auto_create_stats_incremental_on
  ,is_auto_update_stats_on
  ,is_auto_update_stats_async_on
from sys.databases order by name
```
| 列名 | データ型 | 説明 |
|:--|:-:|:--|
| is_auto_create_stats_on  | bit  | 1 = AUTO_CREATE_STATISTICS は ON です。 |
| is_auto_create_stats_incremental_on  | bit  | 自動統計の増分オプションの既定の設定を示します。<br>0 = 自動作成の統計は非増分です。<br>1 = 可能な場合は、自動作成の統計情報は増分されます。<br>適用対象: SQL Server 2014 (12.x) 以降。 |
| is_auto_update_stats_on  | bit  | 1 = AUTO_UPDATE_STATISTICS は ON です。 |
| is_auto_update_stats_async_on  | bit  | 1 = AUTO_UPDATE_STATISTICS_ASYNC は ON です。 |

#### 設定変更
```ALTER DATABASE データベース名 SET AUTO_CREATE_STATISTICS ON|OFF```
```ALTER DATABASE データベース名 SET AUTO_UPDATE_STATISTICS_ASYNC ON|OFF```


## トレースフラグ2371

- 確認
```DBCC TRACESTATUS(2371)```

- 有効化
```DBCC TRACEON(2371)```

- 無効化
```DBCC TRACEOFF(2371)```

http://azwoo.hatenablog.com/entry/2013/02/14/125848


## 統計情報の操作


#### 更新の実行
```EXEC sp_updatestats```

#### オブジェクトの統計情報更新状況確認

https://blog.engineer-memo.com/2012/04/19/%E7%B5%B1%E8%A8%88%E6%83%85%E5%A0%B1%E3%81%AE%E6%9B%B4%E6%96%B0%E7%8A%B6%E6%B3%81%E3%81%AE%E7%A2%BA%E8%AA%8D/

```
SELECT
    so.name
    , ss.name
    , ss.auto_created
    , ss.user_created
    , ss.no_recompute
    , STATS_DATE(ss.object_id, ss.stats_id)
FROM
    sys.objects AS so
    LEFT JOIN
        sys.stats AS ss
    ON
        ss.object_id = so.object_id
WHERE
    type = ‘U’
ORDER BY
    so.name
```

#### 最終更新日時・更新回数の確認

http://wiki.examind.net/index.php?SQL%20Server/%E7%B5%B1%E8%A8%88%E6%83%85%E5%A0%B1

```
SELECT
    OBJECT_NAME(dsp.object_id) 
    , dsp.object_id 
    , ss.name
    , dsp.last_updated 
    , dsp.rows
    , dsp.rows_sampled 
    , dsp.steps 
    , dsp.unfiltered_rows 
    , dsp.modification_counter 
FROM
    sys.stats AS ss 
    CROSS APPLY 
    sys.dm_db_stats_properties(ss.object_id, ss.stats_id) AS dsp 
WHERE
    OBJECT_SCHEMA_NAME(dsp.object_id, DB_ID()) <> ‘sys’
```
本当にあったやらかしDB設計⑤【第三正規化病】

どうも、近々引っ越しを考えていたのに在宅勤務が始まって引っ越す意味がなくなった人です

今日は[「本当にあったやらかしDB設計④【テストチューニング】」](https://qiita.com/bouitengineer12/items/bca2317b2282e8ccd1e3)に続いてびっくりしたことを紹介します

#第三正規化病
「正規化は第三正規化までやればいい！」と誰かが言ってたらしいです
僕の周りには[R無しRDB](https://qiita.com/bouitengineer12/items/ca7beb7ba83c3233d316)を見ても何も思わないような人ばっかりなので直接聞いたことはないですが…ｗ

しかし、<font color = "red">**第三正規化まですればいい、というのは嘘です**</font>
必要に応じて更に正規化を行う必要があります
ほとんどの場合、更に正規化をしたほうが良いです

※詳細について知りたい方は、是非[SQLアンチパターン](https://www.amazon.co.jp/SQL%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-Bill-Karwin/dp/4873115892)の付録としてついてきている「正規化のルール」を見てください


###何が悪いの？？
正規化という考え方に縛られてはいけません
一番重要なのは<font color="red">**データの不整合を防ぎつつ、データの冗長性も減らすこと**</font>です



###問題
第三正規化までやればいい！、という考えに縛られていると、冗長なデータが生まれ、それが元になってデータの不整合が発生する可能性があります
データの不整合が起こると、**ありもしないデータが存在していることになったり、存在しているはずのデータが紛失したりします**
恐ろしいですね



###原因
なぜ、第三正規化までやればいい！なんて言葉がまかり通っているのか、ちょっと考えてみました

- **正規化を勉強するのがめんどくさい**

正規化を勉強するのは意外と面倒です
正規化は複数の種類があり、正規化のレベルが上がっていくごとに段々複雑になっていきます
第三正規化までやればいい！みたいなことを言っておけば、確かに学習コストがその分下がるかもしれません(それだと正規化を勉強している意味がない気がしますが)
ただし、実は言うほど複雑ではありません


>正規化のルールは、難解なものでも複雑なものでもありません。
>正規化のルールは冗長性を減らし、データの整合性を保つために用いられる、ごく常識的な技法なのです。

>SQLアンチパターンより

- **テーブル設計をするときの目安が欲しかった**

テーブル設計に不慣れな人は意外にも多いです
不慣れな人は基準を欲しがります
そこに、第三正規化までやればいい！と言われて信じ込んでしまうと第三正規化病に罹ります
重要なのはデータの不整合を起こさないことです

###解決方法
第三正規化病に罹らないようにするためにはいくつか予防策があります

######初心者向けの教材を信じない
初心者向けの教材は理解させることに重点を置くため、適度に嘘をつきます
初心者向けの教材を理解した後にはもっとレベルの高い教材にチャレンジしてみてください

######参照整合性を考える
同じ意味を持ったカラムが複数のテーブルに存在している場合は、必ず外部キー制約を使って参照整合性を確保してください

かんたんなやり方は、参照整合性をカラムごとにチェックすることです
同じ意味を持ったカラムがひとつのテーブルにしかない場合は、ユニークキー制約やチェックキー制約など、他の制約を利用することも考えるべきです

僕の経験上、<font color = "red">**制約の必要が無いカラムはほとんどありません**</font>

制約が付いていないカラムがあったら、本当にそれで良いのか議論するべきです
大抵の場合は制約を付けるべきです

#####冗長なデータが生まれないようにする
冗長なデータがあるとボリュームを食う上、データの不整合が発生する可能性があります
履歴テーブル(ログテーブル)と呼ばれるようなものは僕もよく使いたくなってしまいますが、冗長なデータがめちゃくちゃ生まれますｗ
とある時点でのデータを参照するのには役立ちますが、このような使い方をするのは分析用DBであり、処理用DBでは使うべきではないと考えています
T字形ER手法というやり方もあるのですが、今はあまり理解していないのでまた後程…w(とりあえず本は注文した)

2020/08/19追記
T字形ER手法についてまとめました
下記記事を参照してください
[T字形ER手法って何？？？](https://qiita.com/bouitengineer12/items/530d04075e68b3f1a6f6)



#まとめ
- 第三正規化までやればいい！は嘘
- データの不整合を許すな
- 冗長なデータがあると金かかるよ

データの不整合を許容する理由は分析系DB以外には**絶対にありません**
根拠の無い嘘に騙されないでください
第三正規化病は、データの不整合を許容するために使う方便です

しかし、正規化は基本となる手法をまとめたとても役に立つものです
正しく正規化を理解することで良いテーブル設計ができるような手助けをしてくれます

是非、最高の正規化をしてください

- [本当にあったやらかしDB設計シリーズ一覧](https://qiita.com/bouitengineer12/items/e63e5f7d6f628da11362)
ABCIでjupyter notebookを使う方法

## 準備

ターミナルを3つ使用する．

1. ABCIに接続するためのシェル．
2. ポートフォワーディング用
3. SSHトンネル用

なお，以下の「手順」でそれぞれ使用されるシェルのマシンの割り当ては以下の通り．

- `[username@es1 ~]$`: ABCIのインタラクティブシェル (ログインして最初に入るところ)
- `[username@g0001 ~]$`: ABCIの計算ノード (qrshで入るところ)
- `[username@local ~]$ `: ローカルのシェル

## 手順

1. qrshで計算ノードを実行

    ```bash
    [username@es1 ~]$ GROUP=YOUR_GROUP_NAME
    [username@es1 ~]$ qrsh -g $GROUP -l rt_F=1 -l h_rt=01:00:00
   ```

2. ホストネームを取得

    後々必要になるため，取得した値をメモする．

    ```bash
    [username@g0001 ~]$ hostname
    g0001.abci.local
    ```

3. jupyter-notebookを実行

    ```bash
    [username@g0001 ~]$ jupyter notebook --ip=`hostname` --port=8888 --no-browser
    ```

4. ローカルのPCでポートフォワーディング

    ```bash
    [username@local ~]$ username=your_user_name_in_abci
    [username@local ~]$ identity_file=~/.ssh/your_identity_file
    [username@local ~]$ ssh -i $identity_file -L 10022:es:22 -l $username as.abci.ai
    Welcome to ABCI access server.
    Please press any key if you disconnect this session.
    ```

5. 別ターミナルでSSHトンネルを作成

    2で取得したホストネームを使用する点に注意

    ```bash
    [username@local ~]$ qrsh_host_name=g0001
    [username@local ~]$ username=your_user_name_in_abci
    [username@local ~]$ identity_file=~/.ssh/your_identity_file
    [username@local ~]$ ssh -N -L 8888:$qrsh_host_name:8888 -l $username -i $identity_file -p 10022 localhost

    ```

6. 3で表示されている `http://127.0.0.1:8888/?token=~` にアクセス

    jupyter-notebookを実行している計算ノードのシェルにローカルのURLが表示されているため，アクセスするとブラウザでJupyter-notebookが開く．

## 参考

- [ABCI User Guide: Jupyter Notebookの起動](https://docs.abci.ai/ja/tips/jupyter-notebook/#start-jupyter-notebook)
[rails]Githubのマスター情報が反映されない、、、

結論)新たにブランチを切った上で、下記を実施することで解決しました。
ブランチを切っていなかったことが原因でした。

[マスター情報の反映手順]

①ローカルのmasterブランチへ移動

```
git checkout master
```

②リモートのmasterを反映

```
git pull origin master
```

③開発中のブランチへ移動

```
git checkout 開発ブランチ
```

④maserの内容を取り込む

```
git merge origin master
```
MetricBeatsのインストール手順


### 目的

MetricBeatsのインストール手順と設定手順について纏める。

###インストール手順

Download and install the public signing key:

```bash:Download-and-install-the-public-signing-key
sudo rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
```

Create a file with a .repo extension (for example, elastic.repo) in your /etc/yum.repos.d/ directory and add the following lines:

```bash:/etc/yum.repos.d/elastic.repo
[elastic-7.x]
name=Elastic repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
```

Your repository is ready to use. For example, you can install Metricbeat by running:

```
sudo yum install metricbeat
```

To configure Metricbeat to start automatically during boot, run:

```
sudo systemctl enable metricbeat
```


###設定手順

Modify metricbeat.yml to set the connection information:
Where <password> is the password of the elastic user, <es_url> is the URL of Elasticsearch, and <kibana_url> is the URL of Kibana.

```bash:/etc/metricbeat/metricbeat.yml
output.elasticsearch:
  hosts: ["<es_url>"]
  username: "elastic"
  password: "<password>"
setup.kibana:
  host: "<kibana_url>"
```

Index setup and Loading dashboards (Kibana must be running and reachable)

```
/bin/metricbeat setup
```

###実行手順

```
systemctl start metricbeat.service 
```

以上
alpine linuxでherokuをインストールする

# alpine linuxでherokuをインストールする
alpineの環境でherokのコマンドを使用できるようにするのに少し手間取ったので、解決した方法を載せます。
環境はdockerのphp:7.3-fpm-alpineというイメージを使用しています。

## 必要なライブラリのインストール
```
apk add bash nodejs
```
alpineではashというシェルを使っていますが、herokuをインストールする際にはbashというシェルが必要です。nodejsも必要になるのでインストールしてください。
## herokuのインストール
```
curl https://cli-assets.heroku.com/install.sh | sh
```
このコマンドを実行することで、herokuがインストールできるはずです。
```heroku -v
```
でインストールされているかを確認して、バージョンが確認できればインストール完了です。

## dockerfile
上記でうまくいかない場合、私の環境のdockerfile内でモジュールをインストールしているのが関係あるかもしれないので、ご確認ください。
```RUN docker-phpext-install bcmath pdo_mysql sockets
```
dockerfileで追加でモジュールをインストールしています。
Microsoft Teams ユーザの一括登録

#はじめに
本記事は，Microsoft Teamsにおいて自分が所有者であるチームへのユーザの一括登録の方法を述べたものである．

#準備
- Windows 10 Professional
- PowerShellがインストールされていること(Version **5.1**が推奨されている）
- .Net FrameWork **3.5**を有効にしておく．
- .Net Fracework **4.8 Advanced Services**の中の**ASP.NET 4.8**にチェックを入れる
<img width="622" alt="スクリーンショット 2020-05-11 11.05.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98153/7ba64cca-a8f0-a2c4-8288-01db6503a854.png">
<img width="422" alt="スクリーンショット 2020-09-14 11.07.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98153/6096b733-3da8-54a4-8dd0-52f2098363d0.png">


#PowerShellを管理者として実行する
<img width="413" alt="スクリーンショット 2020-05-11 11.08.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98153/ea576e09-e505-7e09-841b-4ca86a76465b.png">


##以下のコマンドを一行ずつ実行していく．

```powershell
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
```

#### （プロキシを経由する必要がある環境での注意）
プロキシを経由する必要がある場合には，

```powershell
$ProxyUrl = "http://proxy.example.com:8080"
```

を始めに実行し，以下のすべてのコマンド（「GroupIdの取得」，「ユーザの追加コマンド」を含む）の末尾に，``-Proxy $ProxyUrl``を追加する．（たぶん）

```powershell
Install-PackageProvider -Name NuGet -Force
```

```powershell
Install-Module -Name AzureAD
```

```powershell
Install-Module -Name MicrosoftTeams
```

#Microsoft Online Services サインイン アシスタントのインストール
- [Microsoft Online Services サインイン アシスタント](https://www.microsoft.com/ja-jp/download/details.aspx?id=41950)
    - 64bit版で良いと思われる(32bit OSの場合は32bit版)

#GroupIdの取得
PowerShellに戻って，

```powershell
Connect-MicrosoftTeams
```
を実行し，資格情報を入力してサインインする．次に，

```powershell
Get-Team -User 自分のユーザID（メールアドレス)
例：Get-Team -User hoge@fuga.com
```
を実行し，自分の所属するチーム情報を表示．ユーザを追加したチームのGroupIdをコピーするかメモするかしておく．

#ユーザの追加コマンド

```powershell
Add-TeamUser -GroupId ユーザを追加したいチームのGroupId -User 追加したユーザ名（メールアドレス）
例：Add-TeamUser -GroupId 31f1ff6c-d48c-4f8a-b2e1-abca7fd399df -User dmx@example.com
```

上記のコマンドはPowerShellにペーストできる．したがって，ユーザ一名一覧が手元にある場合，Excel等を利用してコマンド一覧を作り，それをコピー&ペーストすることで一括登録が可能．

#注意
当然のことであるが，自分が所有者でないチームには上記の操作は行えない．