OmniAICreator/Qiita-1.07M huggingface dataset:
QGISのGDALラスタ計算機で周囲の値を使って計算する


# 概要
+ GRASS GIS r.mapcalc.simpleでは周りのセルの値を相対のindexで取得できる　
   +  [QGISで滑らかな等高線を作成する](https://qiita.com/ishiijunpei/items/ef8dc3f00b5df116a6a1)
+ ただ、GRASSはWindowsのQGISのインストーラーがMSIになってから使えていない。
   + [Missing CP949 (Korean) encoding at GRASS processing](https://github.com/qgis/QGIS/issues/29712)
   + [v.clean UnicodeDecodeError when special character (German Umlaute) in path](https://github.com/qgis/QGIS/issues/29845)
+ 2024/8/7追記：QGIS 3.32あたりからGRASSが使えるようになっています。 [Fix GRASS7/SAGA UnicodeDecodeError in QGIS of Windows-Japanese or others #49226](https://github.com/qgis/QGIS/pull/49226)
+ GDALラスタ計算機は機能豊富なnumpy関数が使えるからなんとかならんか という

# GDALラスタ計算機
+ A,B,C ... の文字に入力ラスタを割り当て、「A*2」のように式を入れる。
+ A[0,0]でラスタの起点セルの値を取得できるが、絶対のindexなので、当該セルの周りの値は取得できない。
+ 加減乗除+-*/は普通に書ける。
+ 等号、不等号=<>は使えず「equal(A, 0)」のような関数で書く。
+ ラスタ単位での処理なので、個別のセルに対するforループのような処理はできない。
+ 論理関数　https://numpy.org/doc/stable/reference/routines.logic.html
+ 数学関数　https://numpy.org/doc/stable/reference/routines.math.html


# いろいろ試す
+ indexとなる連続値のラスタを新たに作ればいいのでは、、と思って作ってみた。
+ が、「A[B,C]」のような式はB,Cが当該の値ではなくラスタなので、使えなかった。
## ラスタサイズの取得　shape
+ 形状のタプルを返す
+ https://numpy.org/doc/stable/reference/generated/numpy.shape.html#numpy.shape
+ shape(A)[0]  ->Y軸（高さ）
+ shape(A)[1]  ->X軸（幅）
## 同形状で値が0のラスタ　zeros
+ ゼロで埋めた配列を返す
+ zeros(shape(A))　　-> Aと同形状で0で埋めたラスタを返す
+ 返す配列の形状が同じであれば、新たに作ってもよいらしい
## 起点から1セルごとに値が１増加するラスタ
+ repeat([arange(shape(A)[1])],shape(A)[0] ,axis=0)  ->X軸方向に連続値
+ repeat([arange(shape(A)[0])],shape(A)[1] ,axis=0).T  ->Y軸方向に連続値

# 発想の転換、周りの値を移動させる
## roll 関数
+ 値をシフトする関数で、左に1セルシフトすれば、1つ右側の値を取得できる。
+ ただし、左1セルシフトすると、右端の値は左端の値になる。
+ roll(A, (0, -1))　　→左に1セルシフト（右側の値を取得）
+ (roll(A, (0, -1)) + roll(A, (0, 1)))/2　　→ 左右のセル値の平均
+ https://numpy.org/doc/stable/reference/generated/numpy.roll.html?highlight=roll#numpy.roll

## ラスタの外周セルの削除をラスタ計算機でできないか
+ 周囲１セルを計算に使用した場合、ラスタの外周の１セル分は意味のない値。
+ 先ほどの軸のインデックスラスタを使って、外周の値の削除できるが、4辺あるので、煩雑
+ たとえば、X軸の左端が0のラスタBを使って、Aの左端を0に
   + not_equal(B,0) * A

## 外周を削除するのは、他のプロセッシングで切り抜いた方速い
1. レイヤ範囲の抽出
1. バッファ(マイナス１セル分)
1. マスクレイヤで切り抜く（マスクレイヤの領域に切り抜き範囲を一致させる　のチェックを外す）

# おわりに
+ QGISのGDALラスタ計算機で周囲の値を使って計算することはできないことはないが、ややトリッキーな気がする。
+ もっと簡単な方法があったらコメントください。
【UE5】外部プラグインをプロジェクトに導入する方法

## 目的
外部プラグインをプロジェクトに導入したい
## 手順
- プロジェクトフォルダ直下にフォルダ「Plugins」を作成する
- Git等で公開されたプラグインファイルを作成したフォルダにコピーする
- 対象プロジェクトを起動しプラグインからプラグイン名を検索する
- 検索できたら有効にしてプロジェクトを再起動する
- すると使用できるようになる
wordcloudインストール時のエラー

よくネットで見るこんな感じの画像を作りたいと思い、[wordcloud](https://github.com/amueller/word_cloud)をインストールすることに
![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1074988/7717ef07-deda-be7e-838b-30cb00f417a9.png)
```cmd
pip install wordcloud
```
でエラーが発生しました。

```cmd
error: command 'C:\\ Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.14.26428\\bin
\\HostX86\\x64\\cl.exe' failed with exit status 2
```

## 解決方法
最新版の[Visual Studio BuildTools](https://visualstudio.microsoft.com/ja/downloads/)をインストールする事で解決

## 補足
そもそも[Visual Studio BuildTools](https://visualstudio.microsoft.com/ja/downloads/)がインストールされていない時は下記のエラーが出るみたいです。
```cmd
error: Microsoft Visual C++ 14.0 is required. Get it with "Build Tools for Visual Studio": 
https://visualstudio.microsoft.com/downloads/
```
【Python】icrawlerを用いた画像収集（たった３行！）

# はじめに
Pythonで簡単に画像収集ができるので、趣味での収集だけでなく、機械学習でのデータセットでも活用できると思ったので記載します。

## icrawlerパッケージのインストール
```
pip install icrawler
```

## コード
例として、Googleから犬の画像を１０枚取得します。
keywordに検索したい用語を記載（日本語でも英語でも可）
max_numにダウンロード枚数を記載
```
from icrawler.builtin import GoogleImageCrawler
crawler = GoogleImageCrawler(storage = {"root_dir":"dogs"})　# ダウンロード先のディレクトリ名
crawler.crawl(keyword="犬",max_num = 10)　
```

実行すると下記の通り、動き出しますので少し待ちます。
```
2022-05-28 20:32:53,646 - INFO - icrawler.crawler - start crawling...
2022-05-28 20:32:53,654 - INFO - icrawler.crawler - starting 1 feeder threads...
2022-05-28 20:32:53,659 - INFO - feeder - thread feeder-001 exit
2022-05-28 20:32:53,665 - INFO - icrawler.crawler - starting 1 parser threads...
2022-05-28 20:32:53,670 - INFO - icrawler.crawler - starting 1 downloader threads...
2022-05-28 20:32:54,428 - INFO - parser - parsing result page https://www.google.com/search?q=%E7%8A%AC&ijn=0&start=0&tbs=&tbm=isch
2022-05-28 20:32:54,767 - INFO - downloader - image #1	https://guide.line.me/ja/dogday_01.jpg
・
・
・
```

そして、フォルダを確認するとちゃんと１０枚ダウンロードされてます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2544095/a99523b8-5d01-9ee4-cece-4dd611531954.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2544095/b62afde7-3cb1-4da3-16db-547d7f05bc1d.png)


### 他の画像も収集
最近欲しくてたまらないジムニーの画像を収集してみようと思います。
```
from icrawler.builtin import GoogleImageCrawler
crawler = GoogleImageCrawler(storage = {"root_dir":"jb64"})
crawler.crawl(keyword="jb64カスタム",max_num = 10)　
```
無事、１０枚ダウンロードすることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2544095/32174b9e-a0b8-4941-360d-2ce92a9f019a.png)

いろんな方のカスタムを見るのは楽しいので、趣味として利用するのもありですね！
JSでErrorを継承して作った独自エラークラスを判定する方法

Errorを継承して独自のエラークラスを作る方法は以下の感じです。

```js
class MyError extends Error {
  constructor (msg) {
    super(msg)
  }
}

try {
  // ...
  // ここでエラーがあったとき
  throw new MyError('エラー')
  // ...
} catch (err) {
  // instanceof でエラーの型を判定
  if (err instanceof MyError) {
    console.log('MyError')
  } else if (err instanceof Error) {
    console.log('その他のエラー')
  }
}
```

複数の場合も同じ感じです。

```js
class MyError extends Error {
  constructor (msg) {
    super(msg)
  }
}

class MyErrorEx extends MyError {
  constructor (msg) {
    super(msg)
  }
}

try {
  // ...
  // ここでエラーがあったとき
  throw new MyError('エラー')
  // ...
} catch (err) {
  // instanceof でエラーの型を判定
  if (err instanceof MyErrorEx) {
    console.log('MyErrorExのエラー')
  } else if (err instanceof MyError) {
    console.log('MyErrorのエラー')
  } else if (err instanceof Error) {
    console.log('その他のエラー')
  }
}
```

# エラー判定の注意点

ただし、instanceofの順番を間違えるとおかしなことになります。
`MyErrorEx → MyError →　Error`
の順番で確認する必要があります。

なぜなら、以下を実行してみると分かりますが、継承したオブジェクトはinstanceofでtrueを返すからです。

```js
const e = new MyErrorEx('hoge')
console.log(e instanceof MyErrorEx) // true
console.log(e instanceof MyError) // true
console.log(e instanceof Error) // true
```

この原則に気付かず、かなりハマってしまいましたので、皆さんもご注意を。
AWS Certified Security - Specialty（SCS-C01）に合格するまで

今回はSCSを取得しました。
以下取得するまでの流れです。

## 事前の知識
・インフラエンジニア歴７年くらい
・AWS経験は１年くらい
・CLP、SAA、SOA、DVA取得済

## 勉強内容
**・総勉強時間：30hくらい（1ヶ月弱）**
過去試験と同じく平日は2hくらい、土曜は５hくらい。直前はさらにがっつりやりました。
GWもがっつりやれましたが、GW後はちょっとダレて少しペースが落ちました。
長期休暇後のメンタルってけっこう難しいですね。

試験は勉強開始時点で合格者の情報拾って1ヶ月後で予約しました。
合格者の情報は問題集と同じくkoiwaclubで拾ってます。

**・勉強内容①：問題集**
<img width="200" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/50aa08f9-e50b-6011-05a2-b986b0a255fe.jpeg">

今回からは新たに要点整理シリーズです。
ボリュームは多くも少なくともなく、
掴みとしては過去一番バランスの良い参考書でした。

**・勉強内容②：koiwaclub**
いつものkoiwalub神。
そろそろお祈りをささげないといけないかもしれません。
今回も数問、同一のサービス問題が出てます。

今回も３週実施。
１週目の平均点：54
２週目の平均点：65
３週目の平均点：77

全体的にDVAの時より少し落ちました。
Specialtyはアソシエイトより長文が増えるので、
若干難易度があがるイメージです。

## 試験
今回も渋谷道玄坂で受験。今後はここで受けていきます。

若干躓いた問題が５問くらい。あとはすらすら解けて1時間くらいあまりました。
残りの時間で残した問題を解きました。１問だけSGとNACLの細かい問題がでたので
はじめて借りたメモとペンを使って構成図をかきました。

これがよくでたってのはあまりありませんでしたが、
意外とAmazon Macieが２問くらいでました。
個人情報はMacie！って覚えておけば良いかと思います。

今回も800点ごえの合格でした。

## 最後に
いつも合格判定は自信がなかったですが、
今回はいけたかなぁという感じがあり、少し自信がついてきたようです。
次はANSいきます！！
【PowerShell】SharePoint Onlineの特定のリストでメジャーバージョン保持数を100未満に設定する

# はじめに
SharePoint Onlineのリストではバージョン管理においてメジャーバージョンを有効にした場合、バージョンの保持数は<font color="Red">100～50000に制限されます。</font>（2022/05/28現在）
⇓⇓⇓こんな感じ⇓⇓⇓
![SharePointOnlineバージョン設定エラー画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2669464/edafb73b-8d2f-9a05-308f-0d3234060ea9.png "バージョン設定エラー")
バージョンが増えると何が起こるかというと、保持しているバージョン分の容量を食ってしまうというSharePoint Onlineの仕様があるようです。
そのため例えば100バージョン保持していると原本と同様の容量×100の容量を食っていることになります。（50000の制限は一体誰が使うのでしょうか…）
**引用元：「SharePoint Online ：ライブラリのドキュメントのバージョンの容量についてサポートに問い合わせました」**

https://art-break.net/tech/?p=6780

しかし、実はこのバージョン保持数を強引にPowerShellでいじっている海外の猛者がいました。後ほど参考URLも記載いたします。

# やり方
用意するファイルは以下です。
- ps1ファイル

## ps1ファイル
```powershell:keepVersion.ps1
<#SharePoint Online PowerShell Moduleをインポート#>
Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking

<#パラメータ設定#>
$siteURL="サイトのURL"
$listName="変更したいリストライブラリのタイトル"
$versioningLimit = 指定したい100未満のバージョン保持数

<#接続認証#>
$Cred= Get-Credential "アカウント名"

<#コンテキストを設定#>
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL)
$Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)

<#リストのバージョン設定取得#>
$List = $Ctx.Web.Lists.GetByTitle($listName)
$List.Retrieve("EnableVersioning")
$Ctx.ExecuteQuery()

<#バージョン履歴保持設定#>
If($List.EnableVersioning){

    $List.MajorVersionLimit = $versioningLimit
    $List.Update()
    $Ctx.ExecuteQuery()
    Write-host -f Green "Version History Settings has been Updated on '$($listName)'"

}Else{

    Write-host -f Yellow "Version History is turned-off on '$($listName)'"

}

```
**引用元：「SharePoint Online: Set Versioning Limit using PowerShell」**

https://www.sharepointdiary.com/2019/07/sharepoint-online-set-versioning-limit-using-powershell.html

こちらはもちろんSharePoint Onlineの仕様に背くことになるので、このツールを流した後に[設定]>[バージョン設定]の中をいじりたい場合は、一度[次の数のメジャー バージョンを保存する]の設定を100～50000の数値に戻してから諸々の設定を進めてください。（このままだとエラーではじかれます）

# さいごに
影響範囲を調べていないのでこちらのツールを流すことで発生した不具合等については責任を負いかねます。自己責任でお願いします。
それにしてもSharePoint Onlineの仕様ってちょこちょこありますが、「そんなの教えてもらわないとわからないよ…」なんてこともよくあるな～と個人的に思っています。
never型を使ってswitch文のエラーを検出する

switch文でnever typeを使ってエラー検出する処理を書いていきます。



## よく見る一般的なswitch関数

```ts
enum SampleEnum {
    hoge,
    popo,
}

function doSwitch(value: SampleEnum): boolean {
    switch (value) {
        case SampleEnum.hoge: return true;
        case SampleEnum.popo: return true;
        default: 
            throw new Error("default");
    }
}
```


doSwitch関数で引数のSampleEnumの値に応じてtrue or falseを返します。
defaultはオプションのようですが、今回はnever typeを使うのもあり追加しています。




今回はSampleEnumの値に新メンバーhugaを追加してみます。
```ts 
enum SampleEnum {
    hoge,
    popo,
    huga //hugaを追加
}
```
上のdoSwitch関数はSampleEnum.hogeとSampleEnum.popoの時のみ判別しているので
定義されていないhugaがいきなり入ってきたら ` default:throw new Error("default");`が呼ばれるようになります。

```ts
function doSwitch(value: SampleEnum): boolean {
    switch (value) {
        case SampleEnum.hoge: return true;
        case SampleEnum.popo: return true;
        default: 
            throw new Error("default"); //hugaは定義されていないので、ここが呼ばれる
    }
}
```


これでもエラー検出できるのでいいですが、新しい値をSampleEnumに追加する度に忘れずにdoSwitch関数内の処理も更新しなくてはなりません。
なので関数の更新を忘れることも考えられます。


## never typeを使ってエラーを検知する

実行時にエラーが発見できることもありますが、never typeを使うことでもっと早い段階でエラー検出ができそうです。

```ts

enum SampleEnum {
    hoge,
    popo,
    huga //hugaを追加
}

function doSwitch(value: SampleEnum): boolean {
    switch (value) {
        case SampleEnum.hoge: return true;
        case SampleEnum.popo: return true;
        default: 
          //never typeを追加
          const notExpectedValue: never = value;
          throw new Error(notEexpectedValue);
    }
}
```
never型のnotExpectedValueという変数を用意します。
先ほどと同様にdoSwitch関数内にはSampleEnum.hogeとSampleEnum.popoの処理が書いてあるので、その二つの値は正常に処理できそうです。

ただ新メンバーのSampleEnum.hugaが入ってきたときは、処理書かれてないからdefaultに流そう!ってことでdefaultに到達します。



そしてdefault内の処理としては、知らないメンバーがきたらエラー返してねって処理です。
`const notExpectedValue: never = value;`ここのコードでは
notExpectedValueはnever型なんだからvalueなんて値代入できないよ。っと怒ってくれます。

ここで代入したかったvalueが今回でいうSampleEnum.hugaに当たります。



実際にコード上ではこんなエラーが出るかと思います。
```ts
「型 'SampleEnum' を型 'never' に割り当てることはできません。ts(2322)」
```


## 感想

doSwitch関数ないの処理追加するの忘れそうなので、never typeを使っていこうと思います!




## 参考記事
https://stackoverflow.com/questions/39419170/how-do-i-check-that-a-switch-block-is-exhaustive-in-typescript/39419171#39419171
kuromojiを使ったJavaScriptだけの形態素解析

# はじめに
形態素解析というと、Pythonを使って[mecab](http://taku910.github.io/mecab/)というのが鉄板でしょうかね。辞書は[neologd](https://github.com/neologd/mecab-ipadic-neologd)で。
でもほかの環境でも形態素解析したい場面があり、今回はJavaScriptでやってみるお話です。使うライブラリはkuromojiのJavaScript版。

https://github.com/takuyaa/kuromoji.js

ちなみに、mecabもneologdもkuromojiも、更新が止まっています。mecabは、2013/02/18 MeCab 0.996 が最新、neologdは2020/08/20 v0.0.7が最新、kuromojiは2018/11/24が最終更新日です。（2022/5/28時点）
最新の単語に対応していない等の問題が出る可能性がありますので、ご使用の際にはちょっとご注意ください。

## 作ったもの
動くものを置いておきます。公式のデモとほぼ同じですが、自分で文章を作れるのがほしかった。

https://nlp-kuromoji-js.herokuapp.com/

ソースはgithubに置いておきます。

https://github.com/yo16/nlp_kuromoji_js

# 1. 環境
README.mdを見るとNode.jsの手順が書いてありますが、私は素のHTMLとJavaScriptで、ブラウザで見たかったので、ちょっと特殊かも。

githubのページから、`/build/kuromoji.js`と`/dict/*`を入手し、HTMLから相対パスで見れるところへ配置します。

# 2. HTML

HTML側は、kuromoji.jsを読むだけです。パスは適当に。

```html:HTML側
<script type="text/javascript" src="./js/lib/kuromoji.js"></script>
```

# 3. JavaScript

上記のjsを読み込んだ後であれば、`kuromoji.builder()`が使えるので、こんな感じで使います。

```javascript:JavaScript
$(function(){
    $("#btn_execute").click(function(){
        kuromoji.builder({ dicPath: "./js/lib/kuromoji-dict/" }).build(function (err, tokenizer) {
            // tokenizer is ready
            
            // 入力のテキストを取得
            let target_text = $("#input_text").val();
            console.log({target_text});

            // 形態素解析実行
            let path = tokenizer.tokenize(target_text);

            // 結果を描画
            let tbody = $("#tbl_result > tbody");
            tbody.empty();
            for(let i=0; i<path.length; i++){
                let word = path[i];
                let tr = $("<tr></tr>")
                    .append($("<td></td>").text(word["surface_form"]))
                    .append($("<td></td>").text(word["pos"]))
                    .append($("<td></td>").text(word["pos_detail_1"]))
                    .append($("<td></td>").text(word["pos_detail_2"]))
                    .append($("<td></td>").text(word["pos_detail_3"]))
                    .append($("<td></td>").text(word["conjugated_type"]))
                    .append($("<td></td>").text(word["conjugated_form"]))
                    .append($("<td></td>").text(word["basic_form"]))
                    .append($("<td></td>").text(word["reading"]))
                    .append($("<td></td>").text(word["pronunciation"]))
                ;
                tbody.append(tr);
            }
        });
    });
});
```

`kuromoji.builder()`で辞書フォルダのパスを指定して作り上げ、`build()`で実行する処理を書いてます。これだとボタンを押すたびにbuildしてるけど、一度buildしたものを流用するようにできそうだけど、ひとまず。


# おわりに
特に引っかかることはなくさらっと実現できました。何かで使える場面がありそうなので、道具の１つとして覚えておこうと思います。
ちなみに、ローカルに置いたHTMLだと動きません。これはブラウザのセキュリティ対策のため。私はchromeの機能拡張でWeb Server for Chromeで確認し、herokuで動かしました。
DockerのイメージをGithub ActionsでHerokuにデプロイする

個人で開発しているWebサービスのバックエンドをHerokuで構築しているのですが、ある時、「いちいちデプロイするのめんどくね？」と感じた。。。

Dokcerのイメージを自動でHerokuにデプロイしてくれる方法はないかと模索していると、どうやらGithub Actionsで出来るらしい。

そんなところで、今日はタイトルにも書いてあるとおり、DokcerのイメージをGithub Actionsを使ってHerokuに自動でプロイしていきます。

# Actionsの設定ファイル

``.github``ディレクトリを作成し、その中に``workflows``というディレクトリを作成する。

```terminal
$ mkdir .github && mkdir .github/workflows
```

その``.github/workflows``内で任意の名前の``yml``形式のファイル名を作成。

この記事では``deploy-heroku.yml``とします。

```terminal
$ touch .github/workflows/deploy-heroku.yml
```

中身は以下をコピペ

```deploy-heroku.yml
# Your workflow name.
name: Deploy to heroku.

on:
  push:
    branches: [main] # デプロイするブランチ名を選択

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Build, Push and Release a Docker container to Heroku.
        uses: gonuit/heroku-docker-deploy@v1.3.3
        with:
          email: ${{ secrets.HEROKU_EMAIL }}
          heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
          heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
          dockerfile_directory: ./
          dockerfile_name: Dockerfile
          docker_options: "--no-cache"
          process_type: web
```

# 環境変数の設定

デプロイするリポジトリの``Settings``ページを開き、左のメニューの``Secret``ページを開く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/338110ed-a6ff-b166-2ab5-8153214c0eb5.png)

そして、「New repository secret」ボタンを押し以下の環境変数をとそれに対する値を追加。

|HEROKU_EMAIL|ログインメールアドレス|
|-|-|
|HEROKU_API_KEY|APIキー（https://dashboard.heroku.com/account）|
|HEROKU_APP_NAME|デプロイするアプリ名|

これらの設定が完了したら設定ファイル等をプッシュする。

リポジトリの「Actions」タブからビルドおよびデプロイされているかを確認してください。

# 最後に

最近個人の開発でチームで開発しているのですが、Githubの利便性に日々感謝しております。

今回のGithub Actionsも「これも無料で使えるのか！」と驚きを隠せませんでした。

Herokuに自動デプロイすることで、日々開発効率がグッと上がりますね。

同じ境遇の方の助けになれれば幸いです。

何かご不明点等あればコメントにお知らせください。

以上、「DockerのイメージをGithub ActionsでHerokuにデプロイする」でした。

Thank you for reading.

# 参考文献

- https://github.com/marketplace/actions/build-push-and-release-a-docker-container-to-heroku
- https://simple-minds-think-alike.moritamorie.com/entry/github-actions-heroku-deploy
オンプレのサーバーからS3にバックアップする方法

# はじめに

以前に[オンプレのSubversionサーバーをクラウドへ移行](https://qiita.com/nkojima/items/f52e3b9e6b3ce86403a3)という記事に、S3へバックアップを保管する方法について書いたことがあります。

上記の記事は「AWS上のサーバー（EC2）からS3へのバックアップ方法」となるため、今回は改めて「オンプレのサーバーからS3へのバックアップ方法」についてまとめてみました。

# AWS上のサーバーとの違い

[オンプレのSubversionサーバーをクラウドへ移行](https://qiita.com/nkojima/items/f52e3b9e6b3ce86403a3)に書いてある内容との相違点は以下の通りです。

1. オンプレのサーバーのOSｈAmazon Linuxではないため、AWS CLIをインストールする必要があります。
1. S3にアクセスするためのユーザーを作り、そのユーザーのアクセスキーを使う必要があります。
   * AWS上のサーバーは「ロールを付与」することでS3にアクセスできますが、オンプレ環境ではこの方法は使えません。

# 設定手順

以下の手順は、Alma Linux 8で構築したサーバー上での手順となります。

## AWS上の設定

### IAMユーザーの作成

* AWSでは「最小権限の原則」というものがあるため、バックアップに必要な権限のみを付与したIAMユーザーを作成します。
  * ここでは`s3-backup`というグループを指定していますが、これはユーザー作成と同時に新規作成したグループとなります。
  * `s3-backup`というグループに割り当てる権限は、`AmazonS3FullAccess`のみとします。
* ユーザー作成時にアクセスキーを1回だけDLできるので、安全な場所に保管しておきます。

|項目|設定値|
|---|---|
|IAMユーザー名|backup|
|AWS認証情報タイプ|アクセスキー|
|グループ名|s3-backup|
|グループのポリシー|AmazonS3FullAccess|

### S3バケットの作成

* バックアップ先となるバケットを作成します。
  * ここではバケット名を`nkojima-backup`としています。
  * AWSの管理コンソールからもバケットを作れますが、もしAWS CLIをインストール&設定済みであれば以下のコマンドでバケットを作成できます。

```shell-session:
[nkojima@akagi ~]# aws s3 mb s3://nkojima-backup/
make_bucket: nkojima-backup
```

## AWS CLIの導入

### インストール

* [こちらのページ](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)に書かれているLinuxのインストール手順に沿ってインストールします。

```shell-session:
// インストール
[nkojima@akagi ~]# curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
[nkojima@akagi ~]# unzip awscliv2.zip
[nkojima@akagi ~]# sudo ./aws/install

// インストール後にバージョンを確認
[nkojima@akagi ~]# aws --version
aws-cli/2.5.5 Python/3.9.11 Linux/4.18.0-240.22.1.el8.x86_64 exe/x86_64.rocky.8 prompt/off
```

### セットアップ

* `aws configure`と入力した後、バックアップ用のユーザーを作成した際にDLしたアクセスキーの情報を指定します。

```shell-session:
[nkojima@akagi ~]# aws configure
AWS Access Key ID [None]: {アクセスキー}
AWS Secret Access Key [None]: {シークレットアクセスキー}
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

### 動作テスト

* 適当なファイル（※ここでは`test.txt`）を作成して、`aws s3`コマンドで所定のS3バケットにアップロードできることを確認します。

```
[nkojima@akagi ~]# touch test.txt
[nkojima@akagi ~]# aws s3 cp /root/test.txt s3://nkojima-backup/
upload: ./test.txt to s3://nkojima-backup/test.txt
```


## バックアップ用スクリプトの作成

* 上記の動作テストと同じく、以下のように`aws s3`コマンドを呼び出すスクリプトを作成します。
* このスクリプトをcrontabなどに登録して、定期実行するように設定すればバックアップを自動化できるはずです。

```shell-session:backup.sh
#!/bin/sh

echo "バックアップ開始..."
/usr/local/bin/aws s3 cp {バックアップファイルのパス} s3://nkojima-backup/
echo "バックアップ終了"
```


# 参考URL

* [オンプレのSubversionサーバーをクラウドへ移行](https://qiita.com/nkojima/items/f52e3b9e6b3ce86403a3)
* [AWS CLI の最新バージョンをインストールまたは更新します](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)
scipy.stats: 独立 k 標本の等分散性の検定

# scipy.stats: 独立 k 標本の等分散性の検定

複数の群の母分散が等しいかどうか検定する。

帰無仮説 $H_0$: それぞれの母分散は等しい。$\sigma^2_1 = \sigma^2_2 = \dots = \sigma^2_k$

対立仮説 $H_1$: それぞれの母分散は等しいとはいえない。$\sigma^2_1 = \sigma^2_2 = \dots = \sigma^2_k$ ではない（どこか少なくとも 1 つの等号は不等号である）。

## 1.　Levene 検定，Brown-Forsythe 検定

`levene(*args, center='median', proportiontocut=0.05)`

関数名が levene であるが，それはデフォルトの `center='median'` から見れば不適切である。

Levene は `center='mean'` に相当する検定を提唱した（1960）。

Brown と Forsythe は後に `center='median'` とする検定を提唱した（1974）。そのため，Brown-Forsythe 検定と呼ばれることもある。

分布が対称な場合には Levene 検定，そうでない場合には Brown-Forsythe 検定が推奨されるが，現在では特にこのような区別をしないで Brown-Forsythe 検定が使われることが多い。そのため，デフォルトで `center='median'` となっているのであろう。

これらのことは Help に書いてあるが，読まずに検定関数を使っている人も多いかもしれない。


```python
from scipy.stats import levene
```


```python
a = [301, 311, 325, 291, 388, 412, 325, 361, 287];
b = [197, 180, 247, 260, 247, 199, 179, 134, 163, 200];
c = [209, 302, 187, 166, 234, 290, 175, 116];
d = [342, 216, 316, 386, 324, 145, 254, 228]
```

### 1.1.　Brown-Forsythe 検定


```python
levene(a, b, c, d)
```




    LeveneResult(statistic=2.242478379513558, pvalue=0.10300664426579469)



### 1.2.　Levene 検定


```python
levene(a, b, c, d, center='mean')
```




    LeveneResult(statistic=2.4024185774979356, pvalue=0.08650303516190276)



## 2.　Fligner-Killeen 検定

ノンパラメトリック検定である。`leven（）` と同じく `center` 引数がある。デフォルトは 'median' であるが，'mean' を選択することもできる。

`fligner(*args, center='median', proportiontocut=0.05)`


```python
from scipy.stats import fligner

fligner(a, b, c, d)
```




    FlignerResult(statistic=5.380295369379748, pvalue=0.1459761847478772)




```python
fligner(a, b, c, d, center='mean')
```




    FlignerResult(statistic=6.549000694989363, pvalue=0.0877499400483345)






## 3.　Bartlett 検定

有意に正規分布とはいえない母集団からのデータに対しては，前項の Levene 検定, Brown-Forsythe 検定がより頑健である。

`bartlett(*args)`


```python
from scipy.stats import bartlett

bartlett(a, b, c, d)
```




    BartlettResult(statistic=4.465020251776652, pvalue=0.2154317034832133)
scopeとクラスメソッドの戻り値の違い

「とある条件に見合う最初のデータを取ってきたい」としたときにクラスメソッドとscopeでは戻り値に違いがある。ということがわかったので今後の使い分けの参考に。

## そのときやりたかったこと

ページに単純な定型文を表示させる機能を作った時のこと。条件としては、

- 本文がある（これを表示させる）
- 公開状況をON・OFFしてONのものを表示させる
- 公開状況がONであるデータが複数あったときにも一つだけが表示されるよう更新日時が一番新しいものを表示させるようにする

というもの。

それをページに表示させるため複数のデータの中から条件に合うデータを一つだけ持ってくるコードをそのモデルの中に書くことに。view側は単純で

```ruby
- if @announcement.present?
  = @anouncement.body
```

とし、そのデータがあるようであれば表示するという条件のみ。

## scopeを使う

まず最初に使ったのがscope。書き方としては、

```ruby
scope :published_latest, -> { where(published: true).order(updated_at: desc).first }
```

とした。意味としては、「公開済みのデータを取得し、そのデータ（複数）を更新日時が新しい順に並べ替え、その最初の一つ目を取得する」となる。しかし、この方法を使うと「該当するデータがない場合」にview側で不具合が出てしまう。

それは何故かというとscopeの戻り値は

```markdown
ActiveRecord::Relationオブジェクト
```

となるため、もしデータがなかったとしても「からの配列が存在する」ということになり

```ruby
- if @announcement.present?
```

が「true」になってしまうから。

## クラスメソッドを使う

scopeでは該当データが存在しない場合エラーが出てしまうので、クラスメソッドを使うことに。コードはこんな感じ。

```ruby
def self.published_latest
  where(published: true).order(update_at: desc).first # 中身は一緒です
end
```

クラスメソッドを使うと、もし該当データが存在しない場合「nil」が返ることになり上記のview側のコードが期待通り「false」を返してくれる。同じ内容のコードでも戻り値の違いがあることに初めて気がついた。

## 結局は

ただ、結局は他のコードがscopeで統一されているのに一つだけクラスメソッドなのはおかしいのと、「publishedがtrueであること」と「更新日時を新しい順に並べる」というのは分けて書いた方がいいんではないか？ということになり

```ruby
scope :published, -> { where(published: true) }
scope :order_by_recently, -> {order(updated_at: desc)}
```

とscopeを二つに切り分けて設定し、

```ruby
@announcement = Announcement.published.order_by_recently.first
```

 と、「first」もscopeの外に追い出すことによってview側の問題も解決することができた（最初からクラスメソッドを使う必要なんてなかった。）

しかし、二つの機能に違いがあることがわかったのでそれはいい勉強になったと思う。
An account already exists with the same email address but different sign-in credentials.

# 背景
Google firebaseのSNS認証で、同じemailアドレスを登録しているプロバイダで認証したところ
(例えば、FacebookアカウントとGoogleアカウントのメールアドレスが同じ場合など)

An account already exists with the same email address but different sign-in credentials...
のエラーメッセージと共にログインできなくなってしまいました...💦


# 改善策

Google Firebase様の公式ドキュメントの通りにjavascriptを書けばよさそうです!!


https://firebase.google.com/docs/auth/web/account-linking
Firebaseでemailが取得できない

# 原因

・Sign-in-method/詳細で、**「1つのメールアドレスにつき複数のアカウントの作成を許可」**　しているため


# 解決策

**「1つのメールアドレスにつき 1 つのアカウント」**　にしたところ、取得できるようになりました🙌
google colabのバグ？で1日で5万のGCP請求

# 概要
　私は、google colab（pro）, GCS(GCPのS3), google driveの構成で深層学習モデルを学習させていた。毎月おおよそ合計2000円いかないぐらいの超コスパ構成だった。しかし、1日で5万円を利用しているとしてGCPから請求された。この原因を究明するためにGCPに問い合わせを行ったり、再現実験（課金）を行った。その結果、2021/12/22頃にgoogle colabのインスタンス実体がUSリージョンに限定されなくなったという結論を得た。

# 1. 緒言
　普段、私は深層学習モデルを組み込んだデスクトップアプリを開発している。約1000円のgoogle colab proのGPUインスタンスをお得に利用可能なサービスを用いて深層学習を学習していた。また、pythonの学習等のソースコード(train.pyとか)はgoogle driveに保存し、それらをcolabにmountさせ、ソースコードを実行（python train.pyとか）していた。また、教師データや学習済みのモデルは、mountさせたGCSに入出力していた。これらの構成では毎月合計2000円もかからず、コストパフォーマンスに優れた機械学習モデルの開発および研究が可能だった。しかし、2021/12/22に5万を超える請求が発生し、平穏な暮らしが破られる。
## 1.1 Why Google Drive
手元でごにょごにょしつつ更新が多く発生するものは、GUIのサポートがしっかりしたツールを使いたい。pythonのスクリプトは頻繁に変更するためDriveに保存した

## 1.2 Why GCS
Google Driveのデータをcolabから読み取ると遅かった。教師データ読み込みが学習のボトルネックを解消するためにGCSに保存した。このGCSリージョンは北アメリカだったかな？google colabの実体と同じリージョンにしなければ、大陸間で多くのデータ転送が行われてコストが大変なことになる。（これがすごく大事）

# 2. 目的
2021/12/22に発生した5万を超える請求の原因を明らかにする。また、5万の内訳である「US（アメリカ）からAP（アジアパシフィック）へのデータ転送」が請求されたメカニズムを解明する。

# 3. 方法
以下に実施した調査を箇条書きにする。
- GCPのサポートに問い合わせ
- 課金をする（後述）

# 4. 結果
各方法に対しての結果をそれぞれ示す
## 4.1 GCPのサポートに問い合わせ
丁寧に対応してもらったが、あまり納得のできる内容をいただけなかった。（私の英語力不足かもしれない）
無料サポートなのであまり文句は言えないが、正直ドキュメントぐらい読んでほしかった。
そこで自腹を切ってお金がかかった原因を調査することにした。

## 4.2 課金をする
おそらくGCSとcolab間データ転送があやしい。しかし、12/21まで大陸間データ転送にコストはかかっていない。モデルをGCSからダウンロードすると数GB分の大陸間転送コストを請求されるだけである。今回の5万は数TB分のコストなのでおかしい。そもそも数TBのデータを扱っていない。数TBデータ転送？中国人のわるいやつにいたずらされた（偏見）？GCPのバグ？色々考えた結果、実はcolabがUSリージョンにあるという前提を疑うことにした。つまり学習時に大陸間データ転送がポコポコ走って、数TBになったという説である。データ転送量を見積もるとそれっぽい数字であった。
### 4.2.1 colabのリージョン検証方法
 再び学習スクリプトを複数回実行し、以前のように大陸間データ転送の有無を調査した。ただし、１回の学習にかかる時間を減らしデータ転送コストが発生した際に数百円以下となるようにした。また、念の為学習スクリプト２日に１回にすることで、前日に行われた実験に要したコストと統合されないように注意を払った。

### 4.2.2 検証結果
１日目：あー。やっぱり学習時になんか転送しとるな。自分のリージョンになるんかな？
２日目：は？ヨーロッパにデータ転送？
![Screenshot from 2022-05-28 17-45-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2239698/7a9a79a4-b7a1-1de2-e1e2-ecb8024775c3.png)

# 5. 考察
検証結果の画像から分かるとおり、GCPからヨーロッパにデータ転送されている。私は日本に住んでいるため、このプロジェクトで意図的にヨーロッパにデータを転送させることはない。したがってgoogle colabのインスタンスがヨーロッパであると考えられる。

# 6. 結論
本件では、google colabとGCP（GCS）を連携させた際に請求金額が跳ね上がった原因を調査した。その結果、google colabの実体がUSリージョンに縛られなくなったという結論を得た。今後はこのリージョン選択ができるようになることを祈りながら、3090 or 4090のマシーンを組み始めた。（いきなりそんな請求が来るぐらいなら、自分で管理したい。あと異種マルチGPUとかして遊びたい）

# おまけ
## GCPのサポート
とても親切だったが「数TB分のデータを作ってすぐに消したのでは？」みたいなこと言われたけど、ログにも残ってないわけですし。あと、日本からUSにアップロードしたらお金かかるよって話だったけど、そうだっけ？という感じ

## 割引
最終的に色々割引が入って7000ぐらいになった。
![Screenshot from 2022-01-31 22-01-24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2239698/2270c67a-a626-ce05-adae-ded179896176.png)

## プロジェクト名
えっちな命名にしたら、サポートの方に見られてはずかしかった。
「STEP UP GO」第1回イベントレポート


# 導入

2022年5月28日開催の __「STEP UP GO」__ というメルカリさん主催の学生・第二新卒向けのイベントに参加させていただきました。

5月から7月にかけて行われる全3回の勉強会の第1回では、
前半でGolangの基本情報をメルカリのtenntennさんに紹介していただきつつ、
後半ではメルカリUSに所属されているNSEGAさんとのパネルディスカッションを拝聴しました。

Qiitaの記事にするほど綺麗にまとめられているわけではないですが、
自分が知って勉強になったことなどをメモ書き程度に書き留めておこうと思います！


# 学び
インプットは良質なアウトプットするために行う。
勉強をやみくもにするのではなく、アウトプットが前提にあるべきということを再確認した

# Goについて

* 使っていないimport宣言を許していないのは、ビルドが遅くなる要因を排除する目的があるから
    * なんで許さないのか → 開発のスケールしやすくなることをGo自体が目指しているから。
* 言語ごとの開発の背景を学ぶべきである
    * 「Goに入ってはGoに従え」

* ソースコードだけで解析が可能
    * C言語だとどのソースコードを使ってプログラムをビルドするかはMakefileに書いている。
    * ただし、Makefileの形式が自由すぎたり、そもそもC言語のソースコードだけで分からないから見るところが増えて困る
    * 一方でGoでは、例えば、カスタム型がコードに出てくる時に「どこからimportされた型なんだ...？」とならなくて済む

* 機能がたくさんあれば「良い言語」というわけではない、安定した開発が行われたのかというのがより大切
    * プロダクトのユーザーからすればちゃんと使えるかが一番大事なことだから

* go toolとしてtestの標準コードが用意されているなど、会社によるブレがないのが素晴らしい

* gofmtの素晴らしいところは、高機能なフォーマッターが使えるというところよりも、例えば、半角スペースを空ける空けないなど、クリエイティブじゃないところで宗教戦争が起きない仕組みが作られているのが素晴らしい。
* tenntennさんはif文の中かっこを必須にしたのが1番の功績だとお考え

* GOPATHやGOROOTの設定は不要。なんならネットの記事で「GOPATHの設定しましょう」とかは2022年現在では閉じてしまっていい。
    * Go Modulesを今は使えるため。

# ハンズオン

* `println()`は標準エラーに出力。`fmt.Println()`は標準出力に出力。fmtと違ってimportを必要としないため、初学者にGoを説明する時に使う場合は有用。

* `go build -o myprogram .` -o の後の名前で実行ファイルを作成できる

# NSEGA（セガさん）とのパネルディスカッション

* 新しい言語に移行することのメリット
    * 既存のシステムの見直しができるから、無駄な機能の削減や深い理解に繋げられる

* Goを採用することで、他の言語であれば並行処理を使わない場面でも並行処理で書くことは増えるのか？（Goを採用することで並行処理は増えるのか）
    * Goであってもなるべくシリアルで書くべきだと思う。
    * 並行処理は複雑になって処理を追いづらくなるから、手段の1つとして適切である場合は使う。
    * ただしミドルウェアに関しては並行処理にしている箇所は比較的多い

* メルカリにインターン生として採用される時に必要な技術力
    * atcoderの緑ならGood, 茶色でも可

* fatalやpanicは使うなというが使うケースはあるか 
    * fatal (exit code 1 で固定になってしまう), panicはプログラム自体が終了するからまず使わない
    * 「この機能が動かないならプログラム全部落ちてしかるべき」くらいのことがありえるなら使うこともあり得るかもだけど... （DBに繋げない時とか）

* エンジニア1年目にやってよかったこと　→　
    * 技術的なコミュニティに参加した
    * 炎上案件につっこんだ

* オススメの勉強リソース
    * 本は情報が遅いから読む頻度は少ない（代わりにオフィシャルドキュメントを英語で読むことが多い）
    * 枯れた情報を体系的に学ぶのであれば本はOK
    * [エンジニアのロードマップ](https://roadmap.sh/backend)に沿って勉強
    * [e34のポッドキャスト](https://e34.fm/)を聞いてキャッチアップ
　
* エンジニアとして成長が早い人の特徴
    * レジリエンスがある（立ち直りが早い、失敗してもへこたれない、PDCA回す）
    * コツコツやる人（毎日勉強している）
【node】恐怖、いれたはずのnodeがない…

## 起きたこと
node,nvm,npmをインストールし、使用できていたのに、ある日急にどのコマンドもないと言われた
「command not found」:sob:

## 確認したこと
ホームディレクトリ直下にてファイルの一覧を表示（実行結果は省略して一部のみ表示）

```sh:ターミナル
xxx@DESKTOP-5QEHRDB:~$ ls -lah
drwxr-xr-x  5 xxx xxx 4.0K  5月  5 20:37 .nvm
```

フォルダは存在していた！

## 原因

PATH通ってなかった！

## 解決策

`.bashrc`か`.bash_profile`にPATHを記述

```sh:.bashrc
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
```

## `.bashrc`と`.bash_profile`どっちがいいの？

読み込みの流れとしては、`.bash_profile`→`.bashrc`の順で読み込まれるので、どちらでもOK

:raising_hand:役割分担の考え方➀
`.bash_profile`：（ログイン時に一度だけ行えば良い）環境変数の定義担当
`.bashrc`：その他の対話的操作で必要な設定担当
→こうしたいなら、今回の設定は **`.bash_profile`に書く**

:raising_hand_tone1:役割分担の考え方➁
`.bash_profile` ：`~/.profile` と `.bashrc` の読み込み担当
`~/.profile`：環境変数の定義担当
`.bashrc`：bash の対話的操作で必要なもの担当
→こうしたいなら、今回の設定は **`.bashrc`に書く**

このへんついて参考にした記事↓
図で整理できる方すごい…めちゃくちゃ助かります…:nose:
[bash の初期化ファイル .profile, .bashrc, .bash_profile の使い分けと管理方針](https://blog1.mammb.com/entry/2019/12/01/090000#%E5%8D%98%E4%B8%80%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E7%AE%A1%E7%90%86bashrc)

## それでもうまくいかないときは
bashの起動時に上記の設定が読まれていない可能性がある

一時的になんとかするなら、sourceコマンド（ファイルに書かれた内容をコマンドとして実行する）を実行
```sh:ターミナル
$ source ~/.bashrc
```

毎回↑これをやらないためには、`.bash_profile`に以下の設定を追加して、ターミナル起動のために`.bashrc`を読み込むように設定
```sh:.bash_profile
if [ -f ~/.bashrc ] ; then
. ~/.bashrc
fi
```

## 参考
[入れたはずのnode.js や npmが見つからないとき](https://yoshikiito.net/blog/archives/2261/)
[bashの編集](https://qiita.com/savaniased/items/d9d37d3b958c1f54237e)
1 : データベースなしでブラウザチャット作ったけど質問ある?


### 2: >>1 なんでデータベースなしでやったの?
#### 金かかるからw
#### 有料系のやつじゃないとクッソ重いしだるいからやて

### 俺、佐藤裕也（｀ェ´）ﾋﾟｬｰ
#### お金がないので今日も、無料のブラウザサーバーを謳歌する
#### というわけでw replitっていうブラウザエディタ使ってんだけど、無料でサーバー使えるんだよねw
#### で、せっかくここまで有料を華麗に回避してきたのに、今更有用のデータベース使うのアホらしいんだよねw
#### じゃあもう自分で擬似データベース作ろうとwっていうわけなんだお

## 仕組みのお話。
#### `POSTでデータを送信　→ phpで、ファイルに保存。(txtでもなんでもいいお) → 非同期通信でリアルタイムで表示するためにajaxで表示`
#### みたいな感じだおw　仕組みはEZ

## ソースコードとかとか
#### まあ基本コードって感じかな？これベースにしていくよ。
##### POSTのPHP register的な？　送信先の処理だけどw
```php:post.php
//日本語が文字化けしないようにするやつ

//postを起動したら
if($_POST){
  //postから送られてきたデータをcontentに入れる
  $content = $_POST['comment'];
  
  //ファイルパス　任意でよろ
  $file_name = './database/bbs.txt';

  //先程作った関数に、データを渡す
  fwrite('$file_name, $content');
  //リロード
  header('Location: ./');
}
```
##### 送信フォーム。 ここはphpじゃなくてもHTMLでもいい
##### 送信フォームにチャットを表示させることがあると思うので、その処理も買いときます。コメント見て
```html:form.html
<html>
  <head>
    <title>SiChats</title>
  </head>
  <body>
    <form action="" method="POST">
      <input type="textare" name="comment" value="">
    </form>

    //チャット表示↓↓↓↓↓↓↓↓
    <div id="load_this"></div>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  </body>
</html>
```

##### ajaxのファイル。jQueryのやつ使う。送信フォームのとこにjQueryインポートしたのもそのため。
```js:script.js
$('#load_this').load('database/bbs.txt #loadbox');
count = 0;
var countUp = function() {
  $('#load_this').load('database/bbs.txt #loadbox');
}
time = setInterval(countUp, 5000);
```

##### txtを読み込めるようにちょっと改造w
```txt:database/bbs.txt
<div id="loadbox">
```
##### こうすることによって、ajaxが読み込めるようになるんだお
##### jQuesyのやつは、ajaxのload関数を使ってるんだお

##### これがノーマルって感じかなw
##### よかったら、ワイのchatのやつ来てね
##### リンク→https://qiita-sichats.moysi.repl.co
##### 気に入ったらフォローよろしく!!

##### Zennもやってるお!
Power AutomateでExcelのTableを動的に取得する。

# 背景(ストーリー)
下図のような、計測器の使用予定を管理しているエクセルがあるとする。（今時エクセルで管理するなよと言われそうですが。現場ではあると思う。）
月毎にSheetとTableができ、各人が予定を記入するが、当日忘れることが多い。
そこで、PowerAutomateで今日の予約をTeamsで通知すれば防げるのではと考えた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2401966/c8bb5448-151b-2128-683b-e26d51d104ee.png)

# 前提条件
- PowerAutomateを使用するにはライセンスが必要
私は無料の[Microsoft365 開発者プログラム](https://developer.microsoft.com/ja-jp/microsoft-365/dev-program/?WT.mc_id=m365-qiita-timura)に参加しています。

- また、PowerAutomateはクラウドです。デスクトップ版ではありません。

- PowerAutomateでのExcelデータの抽出はTableの必要がある。

# 作成
今回作成するのは、テーブルを動的に取得するところまで。


## (1) Tableの取得
取得したいエクセルの情報を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2401966/353291a1-e83f-f4e5-da33-5e3fc78133ea.png)

## (2) デバッグ用の"作成"アクションを追加

今月のTableを取得するには、[関数](https://docs.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference)を使えばよいが、すこし癖があるのでこの作成アクションを入れと、関数の結果が出力される。
"作成"アクションは"組み込み"→"データ操作"の中にある。
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2401966/00413873-fe7d-b28f-cddb-35b23a68764c.png)
**↓**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2401966/5175b244-bdf5-aad7-da68-9d1d251496d5.png)

Tableの名前は"Plan"+"yy"+"MM"となっているので下図の式を入力するところへ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2401966/46f00dbe-1d78-fe48-d4f7-9c9f692f4312.png)
↓を入力する。

```
concat('Plan',addDays(utcNow(),0,'yyMM'))
```
> 前月でテストできるようにaddDays関数を使っているが下記でも問題ない。
```
concat('Plan',utcNow('yyMM'))
```

## (3) Apply to eachでTableをループして分岐処理
Apply to eachを追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2401966/f6973e50-8a76-232c-3399-3616de111626.png)

この下に"条件"を追加。
Tableの名前と(2)の"作成"の"出力"で比較する。
"出力"でなくても、同じ関数を入力すればできるが、同じものはできるだけ使わないほうが変更に強い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2401966/6b629ad9-1ddc-30b6-4924-308fa01d598c.png)

後は、"はい"の場合にアクションを追加しごにょごにょすればいいが、今回はテーブルを動的に取得するところまでなので、
"作成"で出力して完成とする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2401966/ac0ba0b7-e840-96c9-89cb-a0bfc2d6d27f.png)


---

Tableからデータを取得してTeamsで通知するのはまた今度。
マシン君 自分探しの旅

# マシン君 自分探しの旅

社内のマシンや、何らかの管理ソフトから管理対象とするマシンを、一意のそれに定められる識別子を調べていました。  
マシン君「僕はxxを以って僕です！」  
と言ってくれる何か

## マシン名
マシン君「これが僕の名前です。これが僕です。」  
否。マシン名は出生後いつも何度でも変更可能で、同一ネットワーク内で被っていても公的な問題はありません(問題はある)。

## IPアドレス
マシン君「これが僕のアドレスです。住所です。僕はここにいます。」  
否。アドレスは複数持つことが可能です。また、任意に変更することもできます。  
分離されたネットワークなら同じアドレスが許されます。

## macアドレス
NICに割り振られている一意のIDです。  
具体的には以下のフォーマットで表されます。  
```
FF:FF:FF:FF:FF:FF
```
表現できるバリエーションは2の46乗。70兆個以上。  
これなら被ることもあるまい。
マシン君「このmacアドレスが僕です！」  
だめです。使用するNICによって変わるし、レジストリエディタやデバイスマネージャーから変更することができるので。
  
## MachineGuid
2022/06/02追記  
以下のレジストリにMachineGuidが格納されています。
```
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
```
マシン君「Windowsとして振られたこの識別子が僕です」
なるほど。でも脳移植(OS再インストール)すると違うものになるしなぁ

## UUID
**U**niversally **U**nique **UD**entifier  
名前からして、今回の答えのような要素です。

マシン君「マザーボードに刻まれた、この世界に一つのユニークなIDが僕である証拠です！」
具体的には以下のフォーマットで表されます。  
```
FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF
```
表現できるバリエーションは2の122乗。5澗個以上(もうよくわからんな。   

以下のコマンドで確認可能です。
```
wmic csproduct get uuid
```

# 一旦の結論
マザーボードのUUIDは変更できず被ることは確率的にないため、windows/linuxに限らず、これをそのマシンである識別子にする。で良いのではないでしょうか

# 考察
とはいえ。そのベンダーが提供している方法などを用いれば、UUIDを変更することはできる。   
またVMやHyer-V、ESXiなどの仮想マシンでは、より簡単に変更できます。  
UUIDはマザーボードを交換すると変わります。またベンダーによっては割り当てがされておらず、デフォルト値が返ってくるようです。
なんか脳移植の倫理観的な問題になってきたな。

どこまで行っても変更が可能なので、現実的な範囲で採用する識別子を決めたいですね。
5.10 (標準) 大数法則，中心極限定理，標本分散の一致性

## 方針

確率収束，分布収束に使える最もメジャーな道具である大数法則 (LLN) と中心極限定理 (CLT) を解説する．iidの確率変数が列になっていた場合，標本平均の形を見つけてLLN，CLTに繋げるパターン．

![知ったこと-53.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/5f4b892d-e93d-75fa-6e37-bc612b56e3e2.jpeg)
![知ったこと-54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/41ca3a09-03d9-7d00-6844-d9a683bfebd4.jpeg)

## 答案

![5.-17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/f3657b01-c62f-4dbd-9f4f-edfe9a7e21ce.jpeg)
![5.-18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/249b141e-e3f5-3ba7-aec4-5eaf6b3450d8.jpeg)

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
VScodeで便利だと感じている拡張機能

## 前提
ローカルで作業をする上でVScodeで便利だった拡張機能

入れている拡張機能を出先でPC変わったとかで入れなおすときにいろいろ忘れないようにメモ

<b>随時更新</b>

## VScode
* Japanese Language Pack for Visual Studio Code -> 日本語化


## Git系
* Git History -> commit logみたりするのに使う。
* Git Graph -> Git Historyはlogのみだっただけど、こちらのほうが梱包してあって見やすい。コミットグラフとか。

## Html系
* Live Preview　-> HtmlをVSCodeで閲覧するときに便利。

## Shell
* PowerShell -> VScodeにコマンドプロントを入れるようなイメージ

## MySQL
* MySQL -> MySQLWorkBenchみたいな使い方をVSCodeでできる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1211754/234e4cb9-2bac-857f-dd41-b584c930355c.png)

## liot.js
* Riot-Tag -> そのフレームワークごとにシンタックス直してくれるのは入れるべき

---
## 最後に
何かおすすめとかあったら教えてほしいです。
topic::GitBash  bash5.x へ移行中

- topic::GitBash ,本格的に bash5.x へ本格的な移行を開始した模様
    - こちらより `` https://github.com/git-for-windows/git/releases/tag/v2.36.1.windows.1 `` 
    ```
     from : Git for Windows 2.36.1/ Upcoming breaking changes
     We plan to update the included bash to version 5.1 (currently 4.4) soon after Git for Windows 2.36.0 is released. Please check your shell scripts for potential compatibility issues.

     Git for Windows will also stop supporting Windows Vista soon after Git for Windows 2.36.0 is released. Around the beginning of 2023, Git for Windows will drop support for Windows 7 and for Windows 8, following Cygwin's and MSYS2's lead(link) (Git for Windows relies on MSYS2 for components such as Bash and Perl).
      - link/ Cygwin's and MSYS2's lead - https://www.msys2.org/docs/windows_support/
    ```
     - [驚き] ...Git for Windows will drop support for Windows 7 and for Windows 8,...
     - 現 GitBash 2.37
         ``` 
$ git --version; bash --version
git version 2.37.0.windows.1
GNU bash, version 4.4.23(1)-release (x86_64-pc-msys)
           Copyright (C) 2016 Free Software Foundation, Inc.
           License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
           
           This is free software; you are free to change and redistribute it.
           There is NO WARRANTY, to the extent permitted by law.
         ``` 
     - GitBash 2.36.1
         ``` 
           $ git --version; bash --version
           git version 2.36.1.windows.1
           GNU bash, version 4.4.23(1)-release (x86_64-pc-msys)
           Copyright (C) 2016 Free Software Foundation, Inc.
           License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

           This is free software; you are free to change and redistribute it.
           There is NO WARRANTY, to the extent permitted by law.
         ``` 
    - 2022/06/28? 頃　
        - https://github.com/git-for-windows/git/releases/tag/v2.37.0.windows.1
    - 2022/06/19.upd.06/23 ... GitBash Ver2.37.0-rcX. が進行中
        - GitBash Ver2.37.0-rc2
             - https://github.com/git-for-windows/git/releases/tag/v2.37.0-rc2.windows.1
        - GitBash Ver2.37.0-rc1
             - https://github.com/git-for-windows/git/releases/tag/v2.37.0-rc1.windows.1
        - GitBash Ver2.37.0-rc0
             - https://github.com/git-for-windows/git/releases/tag/v2.37.0-rc0.windows.1
【Node.js】用語の整理

# 用語の整理

npmとかnvmとかnodeとか…なんとなくごちゃごちゃってなってきたので整理する

## node.js
- JavaScript実行環境
- node,npm,npxをセットにしたもの
→nodeとnpmは基本的には同じバージョンにしておけばよい

## node
- JavaScript実行エンジン

## バージョンマネージャ

### nvm
- Node Version Managerの略
- Node.jsのバージョンを管理するためのツール
- Node.jsのインストール、アップデート、バージョンの切り替えができる

## パッケージマネージャ

### npm
- Node Package Managerの略
- Node.jsで外部パッケージをインストールして使うためのマネージャ
- インストールしたパッケージの、バージョンと依存関係を管理する
- パッケージのインストール・アンインストール・更新ができる
- `npm install`コマンド実行時の挙動
    - package.json に記述されている情報を元に、そこに記述されている パッケージを node_modules にインストールする

cf) npx
- npmパッケージを簡単に実行できるコマンド
- Node.js のコマンド実行を補助する
- npm@5.2.0から同梱されるようになった
- npm runはnpmで管理してるライブラリの何かしらのコマンドをpackage.jsonに登録して実行できる機能。npxはそれをわざわざ登録しなくても実行できる機能

### yarn
- JavaScriptのパッケージマネージャ
- npmと互換性がある = 同じpackage.jsonが使える
- npmよりインストールが速い
- npmより厳密にモジュールのバージョンを固定できる
    - yarn.lockファイルで、各パッケージのインストールバージョンを固定できる
- npmと一緒に使える
    - npmと同じのpackage.jsonが使えるため、同一プロジェクトでnpm or yarnで固定しなくて良い

## まとめ
よくわからず使ってしまっていたけれど、今度から何のためのコマンドを何のために使用しているか意識したい！
AWSコンソールへの多要素認証方法について

# 多要素認証とは
一般的なユーザID、パスワード以外の第三の情報と合わせて認証する仕組み。
詳しくは[こちら](https://ja.wikipedia.org/wiki/%E5%A4%9A%E8%A6%81%E7%B4%A0%E8%AA%8D%E8%A8%BC)を参照

# AWSコンソールのユーザについて
AWSコンソールの管理ユーザの位置づけには以下の二つがある
　・ルートユーザ：
　　　文字通り、root権限を持った最上位のユーザアカウント

　・IAMユーザ
　　　ルートユーザが作成した運用上の管理者アカウント

IAMユーザ権限で基本的な作業を行い、何か問題があったり、IAMユーザの権限を操作したい場合にルートユーザを利用する環境が望ましい。

ルートユーザはAWS契約をするときのメールアドレス、パスワードでログイン可能なため、まずはIAMユーザの作成について記載。

# IAMユーザの作成
　詳細な手順は[こちら](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_users_create.html#id_users_create_console)を参照
  作成イメージは以下の通り
　　①ユーザを作成
　　②作成したユーザに対してロールを割り当てる
　　　※ロールは既存のロールでも自分で作成しても問題ない
　　　　ここでは自分で作成してイメージをつかむ。
　　③ロールを作成し、何を許可したいかポリシーを決める
　　　ロールとポリシーの関係は以下のイメージ
　　　![ロールとポリシー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667683/34763b14-af73-f05b-a76b-5affcf6a19da.png)

※[AmazonSSMManagedInstanceCoreについて](https://dev.classmethod.jp/articles/not-recommended-amazonec2roleforssm/)

上記のポリシーを許可することで、ざっくりEC2とS3にはフル機能を操作できる

# 作成したIAMユーザを多要素認証(MFA)できるようにする
IAMダッシュボードを開くと以下のような画面が表示されているはずだ。
筆者は既にrootユーザに対してMFA化しているため、rootユーザにはエラーは表示されていない![IAMダッシュボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667683/795a63ab-f42e-75fa-8b54-bee187be41df.png)

ここではスマートフォンのアプリ(Google)を第三の認証情報として記載する
①Google Authenticatorをスマホにインストール
②"MFAを追加"→"MFAデバイスの割り当て"→"QRコードの表示"をクリック
③Google Authenticatorを起動し、QRコードを読み取る
④スマホの画面上に、ランダムな6つの数字が表示される
⑤その数字をMFAコード1と、MFAコード2に入力する
　※MFAコード2には30秒後の別のランダムな数字6桁を入力する
⑥MFA割り当てで完了

これで、AWSコンソールログイン時にユーザID、パスワード、自分のスマホの6桁の数字という3つの要素で認証できるようになる。
![IAMダッシュボード2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667683/efabf4a5-5cf2-ddc9-d156-207304097969.png)
【Python】wave形式のファイルから波形データを取り出す

久しぶりに音声処理をしたくなりました。目標はMFCCと呼ばれるメルケプストラム係数で特徴量抽出をすることです(2022/06/12: 達成しました)。

このあたりの記事をググってもPython2系だったりと10年前ぐらいの記事が多いため、新しく記事を書くことにしました。

ここでの実行環境は次の通りです。
```
Python 3.8.1
Ubuntu 20.04.4 LTS
```

# 検証するwaveファイル
ここでは、440Hzのsin波を1秒間だけ再生するwave形式の音声ファイル(440Hz.wav)で検証を行うことにします。ファイルパラメータは次の通りです。
```
・チャネル数：モノラル
・1サンプルあたりのバイト数：2 byte
・サンプリング周波数：44100 Hz
・再生時間：1秒
```

# 【簡単】waveファイルの波形データをnumpy配列に変換
音声処理をするPythonのライブラリの選択肢は多いです。今回はsoundfileを使用します。
```python
import soundfile

fname = "440Hz.wav"
data, fs = soundfile.read(fname) #data:波形データ, fs:サンプリング周波数
```
理解していれば3行で波形データを抽出できるので使い勝手がよいです。しかし、これで満足してしまうと少々危険です。なぜかというとwaveの音声データから-1~+1に正規化された波形データになるところがブラックボックスになっているためです。

もう少し詳しく調べるには、組込みwaveモジュールを取り扱う必要があります。ただし、多少のバイナリも触れる必要がある。

以下からは、解説記事になります。

# 【waveモジュール】組込みwaveモジュールでwaveの波形データを詳細に調べる
wave形式に詳しくなければ、一度自分で調べたいところ。その場合は、組込みwaveモジュールが有効です。

まずは、ファイルパラメータを確認してみます。
```python
import wave

fname = "440Hz.wav"
wave_file = wave.open(fname, 'r')

nchannels = wave_file.getnchannels() #チャネル数
print("nchannels: {0}".format(nchannels))
sample_width = wave_file.getsampwidth() #1サンプルサイズのバイト数
print("sample_width: {0} byte".format(sample_width))
fs = wave_file.getframerate() #サンプリングレート
print("fs: {0} Hz".format(fs))
nframes = wave_file.getnframes() #音声データのデータ点数
print("nframe: {0}".format(nframes))
```

実行結果は次のようになる。
```
nchannels: 1
sample_width: 2 byte
fs: 44100 Hz
nframe: 44100
```

もしくは、次のコードでまとめてパラメータを表示させることができる。
```python
params = wave_file.getparams()
print(params)
```

実行結果は次のようになります。
```
_wave_params(nchannels=1, sampwidth=2, framerate=44100, nframes=44100, comptype='NONE', compname='not compressed')
```

さて、本題に移ります。
どのように正規化された波形データを取得するかを調べます。

手順としては、
```
1. 一度waveファイルのバイナリの波形データを取得する。
2. 16bit符号付き整数型に変換する。
3. -2^15 ~ 2^15 - 1 の範囲でサンプルデータが量子化されているため、戻してあげると-1~+1の範囲で正規化される。
```
※なぜ16bit符号付き整数にするかは、標準の形式があるらしく、少々奥が深いので割愛します。

```python
import wave
import numpy as np

fname = "440Hz.wav"

wave_file = wave.open(fname, 'r') 
x = wave_file.readframes(wave_file.getnframes()) #waveをバイナリ化 
x = np.frombuffer(x, dtype="int16") / (2**15-1) #16bit符号付き整数型に変換し,-1~1で正規化
print(max(x), min(x))
```

実行結果は次のようになります。確かに44100サンプルあるデータが-1~+1の範囲に収まっています。
```
0.999969481490524 -0.999969481490524
```

このx配列と、soundfileライブラリで取得したdata配列を比較すると、同じ配列になっていることがわかります。ファイルパラメータさえ確認してしまえば、納得しながらsoundfileライブラリで波形データが取得できると思います。

# 公式ドキュメント
[wave --- WAVファイルの読み書き](https://docs.python.org/ja/3/library/wave.html)
rust-analyzer の型ヒントの色がうるさいのでいい感じにする

# 前提

VSCode v1.67.2
rust-analyzer v0.3.1066

# 結論

`settings.json` にこれを書く

```json
"workbench.colorCustomizations": {
    "[Atom One Dark]": {
        "editorInlayHint.background": "#00000000",
        "editorInlayHint.foreground": "#5C6370",
    },
}
```

**設定適用前**
![color_default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42200/6a8f97fb-35d9-be5b-f936-ccba051575e6.png)
**設定適用後**
![color_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42200/ca7ecc7f-2bf1-42c0-c150-c41939d1f117.png)

`[Atom One Dark]` 部分は自分が使っているカラーテーマの名前に変える。
各foreground色はお好みに合わせて変えると良い。Atom One Dark ではだいたいこのくらいの色だとコメントとほぼ同じ色。

# 参考

https://github.com/rust-lang/rust-analyzer/blob/master/docs/user/manual.adoc#color-configurations
特微量と次元



特徴量の個数 ＝ 次元の数
　
一言で言うと「特徴量」と「次元」とは・・・
求めたいものを特徴づけるもののことを特徴量と言い、特徴量の数が次元の数に相当します。3つの特徴量なら３次元となります。
特徴量の個数 ＝ 次元の数
特徴量とは、求めたいものを特徴づけるもののことですが、これだけでは中々理解が難しいですよね。もっとわかりやすく言うと例えば、自分が飲食店で働いているとして過去の売上から未来の売上を予測したい場合、天気や気温、湿度等々売上に寄与する情報は、未来の売上げを予測するために必要な特徴量と言います。

また特徴量に似た言葉に「次元」がありますが特徴量の個数が「次元の数」に相当し、特徴量を減らすとは次元の数を減らすということです。

さらに一般的に上記の例のように、求めたい（予測したい）もの（売上）を目的変数、目的変数に寄与するもの、影響を与えるものを説明変数と言います。

ややこしくなってきたので、整理すると、

特徴量の個数 ＝ 次元の数 = 説明変数の数

となります。特徴量に似た言葉に「属性」がありますが、属性はデータタイプ（上記の例では「気温」）を表すのに対して、特徴量は一般に属性と値（上記の例では「気温 + 30℃」）という二つの意味を含んで表す単語として使われます（ただし、特徴量は文脈次第で様々な意味に変化することもあるようです）。けれども、実際は属性と特徴量を同じ意味で使う人が多いことも確かなので注意しましょう。

ここまで特徴量を中心にお話ししてきましたが、機械学習モデルの訓練がうまく行われるためには、訓練データに求めたいものに作用する（関係のある）特徴量が十分に含まれ、無関係な特徴量が多すぎないことが必要です。

機械学習モデルの精度を高めるためには、モデルに学習させるための適切な特徴量を揃えることが重要です。こうした過程は特徴量エンジニアリングと呼ばれています。

参考文献
https://aizine.ai/glossary-features/
Javaで競技プログラミングをする際に見つけた面白いメソッド、演算子

#### **Java**で競技プログラミングを始めなければ、一生使わなかっただろうメソッド、演算子があったのでQiitaの練習を兼ねて記事にします。

[AtCoderに登録したら解くべき精選過去問10をJavaで解いてみた](https://qiita.com/0x841/items/0ce887c86cf081312a08)にて紹介されていた回答から興味を持ったメソッド、演算子をまとめます。

# [ABC 081 B - Shift Only](https://atcoder.jp/contests/abc081/tasks/abc081_b)

まずは以下の回答で使われていた、演算子の`|= `
メソッドの`Integer.numberOfTrailingZeros()`です。

~~~java
import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int bit = 0;
        for (int i=0; i<N; i++) {
            bit |= sc.nextInt();
        }
        System.out.println(Integer.numberOfTrailingZeros(bit));
    }
}
~~~

問題の内容は、与えられたN個の整数が全て偶数の場合、すべての整数を2で割った数に置き換える、この操作を何回繰り返す事ができるかが答えとなる問題でした。

ある数が偶数か判別する方法として、２進数にした際１の位が0であれば偶数と判断できます。
つまり、1の位から続く0の数が、その数の2で割る事ができる回数になります。

今回の回答では演算子の`|= `を使って与えられた数すべてと論理和演算をする事で、与えられた整数の中で一番1の桁から続く0の数が少ない整数と同じ数だけ0の数を持った整数を作り出します。
1の位から続く0の数は`Integer.numberOfTrailingZeros()`に代入する事で調べる事ができます。

演算子の`|= `、メソッド`Integer.numberOfTrailingZeros()`がとても面白く、印象に残る使い方だったため紹介させて頂きました。
ジェネリクスを伴うインターフェイスを具象クラスでimplemetsする際に型制約に幅を持たせる方法

# 何をしたかった？

ジェネリクスを伴うインターフェイスを具象クラスでimplemetsする際に、「型の制約に幅をもたせたい！」というケースに遭遇しました。
しかし、「ジェネリクス　インターフェイス　Typescript」のように検索しても、implememtsする際に型を唯一に制約するような例しか出てきませんでした。

例えば以下のようなものです。
ジェネリクスの入門記事でよく見かけるような内容かと思います。
```typescript
interface IHoge<T extends number | string | boolean> {
  hoge(item: T): T;
}

class Hoge implements IHoge<number> {
  hoge(item: number): number {
    return item;
  }
}
```

自分が実現したいのは「`number` と `string` を取り扱える具象クラスを実装したい！」というものでしたが、上例のように実装してしまうと、クラス`Hoge` は `number`型しか取り扱えなくなります。


# どうやって解決した？

以下のように、インターフェイス`IHoge` に `T` を渡し、具象クラス`Hoge` において `T extends ○ | △`  で制約をかけることで実現できました。

```typescript
interface IHoge<T extends number | string | boolean> {
  hoge(item: T): T;
}

class Hoge<T extends number | string> implements IHoge<T> {
  hoge(item: T): T {
    return item;
  }
}
```
【git】git管理から除外したいファイルの設定方法

## 背景
- 機械学習では、学習に使用する巨大なデータはgit管理から除外したいというニーズがある。
※学習に使用するデータ：trainやtestデータなど

## git管理から除外したいファイルの設定方法
### 結論
「.gitignore」ファイルを使用する。

### 「.gitignore」ファイルとは
- git君に「このファイルに記載されているファイルはgit君管理しなくていいよ。」っていうことを記載したファイル

### 使い方
- git管理をしているフォルダに「.gitignore」というファイルを作る。
- 「.gitignore」ファイルにgit管理に入れなくて良いファイル名を記載しておく（下記例）

```bsah:とあるフォルダ
.
├─ .git
├─ .gitignore
├─ train.csv                #学習データなのでgit管理から除外したい    
├─ test.csv                 #テストデータなのでgit管理から除外したい    
└─ machine-learning.ipynb
```
```bash:.gitignore
train.csv
test.csv
```
- 上記の場合、「train.csv」と「test.csv」はgit管理から除外される。

## 参考資料
https://techacademy.jp/magazine/10179

## 個人ブログ

https://takuma-tech.com/2022/09/27/212/