OmniAICreator/Qiita-1.07M huggingface dataset:
GitHubとSourceTreeの基本操作について 

#はじめに

こんにちは。
Quiitaは見習いプログラマーである木下が、学習進行状況のアーカイブとしてまとめる日記兼メモ帳のように使って行こうと思います。
更新頻度は不明ですが、記事を作ったらTeamのチャンネルにバンバン投稿（たぶん）していくので、よろしくお願いします。

今回は、今後の業務に必須であるGitHubとSourceTreeの使い方についてまとめていきます（＾ω＾）

#GitHubってそもそも何だ
まだうろ覚えですが、Gitは複数人で開発コードを管理する時に非常に便利なツールのようです。つまり、自分の書いているコードを問題がないか責任者に見てもらったり、他の人が書いたコードを引き継いだり、コードとコードを統合したりすることなど出来るようです。

昔は集中型情報データベースというのが当たり前のようだったらしいですが、現在では分散型情報データベースと呼ばれるGitが主流になったようです。
集中と分散とかって何が違うの？って話ですが、大きな決定はローカルリポジトリとリモートリポジトリという二つの大きな領域を行き来することらしいです。

※便利な説明画像がありました。
![Qiita](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F63338%2F10f08e65-d53a-7615-a892-3cfc459394af.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=3613c63a8ee31575ab812d4a0a406b7a)

で、さっそくコマンドラインの使い方から覚えようと思っていたら、樋口さんからSourceTreeというGitを使用する上で、便利なインターフェースを通して操作できるツールを教えてもらいました。

なので、今回はSourceTreeでGitを操作するという前提で解説していこうかなと思います。

#Gitで使われる専門用語を覚えよう

まずGitのチュートリアルをYoutubeでザっと眺めていると、全く聞いたことないようなカタカナの専門用語が
ドッと出てきて、かなり混乱しました。なので、今後分からなくなった時にすぐに言葉の意味を確認できるように辞書的にまとめておきたいと思います。

**インデックス**
これから登録するファイルが，以前とどう変わったかを登録する一時的な場所です。

**リポジトリ**
貯蔵庫．データなどを保存しておくという意味らしい。


**ローカルリポジトリ**
自身のPC上の場所を指します。コードを改変した後に、このローカルリポジトリに一度移動してからリモートリポジトリに移動させる工程を行う必要があります。なんか工程が多くて無駄じゃない？と思いましたが、データのバックアップや他の人が誤操作してしまった時のデータの消失を防ぐためにこうした流れになったようです。

**ステージ**
コードを編集すると自動で作業ツリーのファイルに編集を加えたファイル名が表示されます。（しかも編集を加えた行を緑と赤で丁寧に教えてくれる！）
しかし、ただ自動追加されるだけでは何ら意味を成さないので、上のステージという枠にあるところにドラッグ＆ドロップしてコミットの準備をします。

**コミット**
ステージ上で準備が完了したら行う工程です。コミットするとは、簡潔に言えばローカルリポジトリにデータを送信すデータを登録するということです。コミットする際は、コメントを付けたりして、それがどういう変更を加えたのか説明文として残しておくと良さそう！

**プッシュ**
ローカルリポジトリーでコミットして登録されたデータをGitHubのホームページ上に送信＆同期することを言います。つまり、自分の編集したコードを他のチームに公開することができます！

**ブランチ**
ブランチとは、言葉の通り枝のようにコード内容が分岐することを意味します。
なぜ、分岐させるのかというと、開発版、リリース版、バージョンアップデート版、バグフィックス版などと目的によって分けることができるからです。また分岐したブランチを他のブランチと合流させることもできます。
しかし、あまりにも分岐させすぎると逆にごちゃごちゃしすぎるので要注意とのこと。
![Qiita](https://backlog.com/ja/git-tutorial/assets/img/stepup/stepup1_1.png)

**マージ**
マージとは先ほど説明した、ブランチ同士を合流させる作業です。例えば、デバッグしたブランチを本筋のブランチに合流させる時などに使います。ただし、同じ行を改変した場合は、コンフリクトというエラーが出て、改変前か改変後、あるいは二つの案を採用するかなどの選択を決めなければいけません。

![Qiita](https://engineering.linecorp.com/wp-content/uploads/2018/12/simple_auto-closed.png)

**リモートリポジトリ**
GitHubのデータをWEBページを通して管理している場所を指します。これを使うことで複数人がコードの共有や改変、チェックなどを行うことができます、

**フェッチ**
リモートリポジトリで更新されたデータを一度、ローカルリポジトリに降ろしてくる作業です。つまり、チームが変更した内容をそのまま自分の環境に反映させるという役割があります。しかし、フェッチの段階では、データを習得するだけなのでマージ（統合）は行っていません！いわば、上書きの一歩手前みたいな作業ですね。

**プル**
こちらはリモートリポジトリの変更を、一気にローカルリポジトリ環境に統合する内容です。フェッチと似ていますが、こちらは直でマージを行ってくれるので、使う際は要注意となります。

![Qiita](http://elsur.xyz/wp-content/uploads/2017/02/git-flow-768x324.png)
※プルとフェッチの違いについて

**プルリクエスト**
これはいわば、書いたコードを責任者にレビュー（バグ等がないか検閲する）ためにある機能のようです。
「実装終わったので、確認お願いします！」という感じで、リポジトリの管理者に見てもらい、修正があればコメント付きで返信が返ってきたり、OKであればそのままマスターブランチにマージされるというのが主な使われ方のようです。

#操作間違えた時の対処法
とりあえず、「削除」や「破棄」を安易に使うのはやめておいた方がいい。ローカルリポジトリ内の出来事でも、進行中のコードそのものを消してしまう可能性あり。なので、「現在のブランチまでリセット」という操作で一旦作業を巻き戻すと考えた方が良いらしいです。

#とりあえず総じて
GitHub、SourceTreeの目的や用語は何となく理解しましたが、やはり実際の場面で使ってみないと実感がわきません。次回は、練習か、あるいは実戦でGitを使うところから始まるかもしれませんが、必要に応じてブログを残していきたいと思います。
YouTubeのチャット取得に再チャレンジして結果駄目(クォータが足りない)だった話

## 概要
前回諦めたとなったが、諦めきれずに再挑戦して、やっぱり駄目だった話。

## ざっくり結果
- 20秒毎の取得としたが、取得漏れが発生した。
- 欲しいチャンネルの全チャットを取得しようと思うとクォータが足りない。
- 中途半端となるなら取らないとなった。

## 詳細
- [前回](https://qiita.com/DevIwatan/items/0c3b61db9b40d8e5d6d7)の結果として、レスポンスのpollingIntervalMillis(大体5秒くらいが返却される)分waitして次のnextPageへリクエストすれば良さそうとなったので、試そうかと思ったが、さすがに5秒に一回だとクォータが底を尽きそうなので、20秒固定でリクエストを送った。
- リクエスト(ざっくり詳細は[前々回](https://qiita.com/DevIwatan/items/165abd6e834caf78ee18#%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88)を参照)のmaxResultを1000としているが、最大200までしか取得できない(ここでデータの欠落が生じているっぽい)
- 昨晩のあるVTuberさんのスパチャを集めてみたが、あるサイトでは1200弱のスパチャで250万円だったが、自分で集めたのは550で130万円程度で欠落が生じている。
- pollingIntervalMillisをそのまま使えばいいのかとは思うが、それでは確実にクォータが足りない。
- 色々他にもAPIを使っているので使用クォータ数の計算がざっくりだがliveChat/messages で 4クォータは消費している様に見える。
- 欲しいチャンネルが約50チャンネルで日の合算配信時間が平均130時間程度と見積もる。
- 5sec 1req = 1hour=720req → 130hour = 93,600req ... 1req = 4quota → 93,600req = 374,400 quota。
- 残念ながら他に使用しているクォータも考慮すると自分の持っているクォータでは足りない。

## 次のアクション
- 欠落が生じてもある程度は楽しめるコンテンツを作れるならチャットを取得しても良さそうだが、今のところ思いつかない
- どうしても欲しい！となったら、クォータの追加申請（できるのか？次は有料？）をしてみようと思う。

## 備考
- [過去気にしていたこと](https://qiita.com/DevIwatan/items/165abd6e834caf78ee18#%E3%81%9D%E3%81%AE%E4%BB%96%E6%B0%97%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F%E4%BA%8B)はStackOverlowで質問して大丈夫そうな回答を得たので安心して使える。
SSH接続先で開いたtmuxペイン上で動いているemacsとクリップボードを共有する

私は普段リモートサーバーにSSHして、emacs + tmux環境で作業をしています。

その時に、emacsのコードをローカルのクリップボードにコピーしたかったり、逆にローカルでコピーしたコードをリモートのemacsにペーストしたいということがよくあります。

最近になってようやく解を見つけたので、紹介したいと思います。

# 環境について

- クライアント
    - Windows 10
    - ターミナルとしてWSL1 (Penguin)を使用
    - X clientはX410
- サーバ
    - CentOS 6.9 
    - emacsclient 26.3
    - tmux 2.3
    - xsel 1.2.0

# 方法

emacs(client), tmux, xselはそれぞれサーバに入っている前提です。また、SSH接続する際には`X11 Forwarding`を有効にしてあります(`alias ssh='ssh -X'`でも、`~/.ssh/config`で書くもよしです)。

[以前に書いた記事](https://qiita.com/sho0405/items/9bb37f6c0a7f34f49f05#session%E3%81%8C%E6%8C%81%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8Bdisplay%E5%A4%89%E6%95%B0%E3%81%AF%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%9Fdisplay%E5%A4%89%E6%95%B0%E3%81%8C%E4%BF%9D%E6%8C%81%E3%81%95%E3%82%8C%E3%82%8B)で詳しく紹介しておりますが、tmuxは今開かれている環境変数を返す`tmux showenv`コマンドというものがあります。これで返して来た環境変数を使って`xsel`コマンドを動かしてあげることによって、実現可能です。

具体的には

```shell
hoge | env $(tmux showenv DISPLAY) xsel -bi
```

のようにすれば、例えどんな環境変数を持ったアプリケーションが起動していても、正しいX(クリップボード)にアクセス出来るという仕組みです[^1]。

[^1]: これまでは、これを応用して`xclip`を`env $(tmux showenv DISPLAY) xclip`にaliasし、MELPAにある`xclip-mode`を使っていて、概ねうまくいっていました。しかし`xclip`コマンドを評価するのはemacs(client)の起動時で、tmuxをDetachして別のDISPLAY変数の端末でAttachすると、前のDISPLAY変数で`xclip`を実行してしまい、うまくいきませんでした。そこで、コマンドが実行される度に式を評価してもらうようにelispを書きました。

[stack overflowの記事](https://stackoverflow.com/questions/21830813/how-to-kill-yank-code-between-emacs-buffers-using-screen/21833639#21833639)を参考に、以下のようなelispを`~/.emacs`などに書きます。

```lisp:.emacs
;; sync with x clipboard
(unless window-system
    (defun xsel-cut-function (text &optional push)
      (with-temp-buffer
	(insert text)
	(call-shell-region (point-min) (point-max) "env $(tmux showenv DISPLAY) xsel -bi")))
    (defun xsel-paste-function()
      (let ((xsel-output (shell-command-to-string "env $(tmux showenv DISPLAY) xsel --clipboard --output")))
	(unless (string= (car kill-ring) xsel-output)
	  xsel-output )))
    (setq interprogram-cut-function 'xsel-cut-function)
    (setq interprogram-paste-function 'xsel-paste-function))
```

基本的に上のものを使わせてもらいましたが、`call-process-region`ではどうやら`$`マークを正しく評価出来ずうまくいかなかったので、ここをprocessではなくshellで行うように書き換えました。


# 結果

挙動のテスト結果のgifを置いておきます。

テストとして

1. 異なるDISPLAY変数を持つ2つのログイン済端末を用意(Windows Terminalのタブで2つ用意し、一つは19.0, もう一つは20.0であることを確認済)
2. 19.0の端末でtmuxを開き、emacsclientを立ち上げる
3. "from emacs (19.0)" という文字列をemacsのkill ringに格納
4. Windows上のクリップボードからメモ帳に貼り付け
5. 逆に、Windowsのクリップボードに"from windows (client)"という文字列を格納し、19.0で開いているemacsにyank
5. 20.0の端末で19.0で開いているtmuxをattachする
6. 19.0の端末でログアウトする(ここでDISPLAY=19.0の接続が切れる)
7. 20.0の端末で開かれているemacs上で"from emacs (20.0)"という文字列をkill ringに格納
8. Windows上のクリップボードからメモ帳に貼り付け
9. Windowsのクリップボードに"from windows (client)"という文字列を格納し、20.0で開いているemacsにyank

の操作を行っています。

![shared_clipboard_tmux.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255755/ff4491aa-a8eb-eef7-fcaa-e4ba6d89dc1c.gif)

この一連の動作でDISPLAY変数が変わってもクリップボードが共有されていることが確認出来ました。
Android Studioの設定

初めに
===
開発をしていく上で役に立ちそうなAndroid Studioの設定をまとめます。


環境
===
Android Studio 4.1.1
PC Windows 10


設定内容
===
##フォントサイズ・字体
File > Settings > Editor > Font
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/19334c03-e0c4-842a-a3f9-c9178631eaaa.png)

##未使用のimportの削除
File > Settings > Editor > General > Auto Import
1. Optimize imports on the fly(for current project)にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/ffcc8461-30eb-2f26-4ff2-89a99e8b083e.png)

##ショートカットの設定・確認
File > Settings > Keymap
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/b7a46fba-ab22-d3b8-9106-b4d229e3bdf7.png)
[キーボード ショートカット](https://developer.android.com/studio/intro/keyboard-shortcuts?hl=ja)

##Logcatの色の変更
File > Settings > Editor > Android Logcat
1. Inherit values from: Console→Standard outputのチェックを外す
2. Foregroundの色を変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487320/78d84486-5296-323d-8b70-714cf3578cbc.png)

おまけ
===
設定内容をエクスポートしてほかの環境でインポートするには以下の方法で可能なので、
ファイル共有できる環境であれば一度設定してしまえば使いまわすことが可能です。
[AndroidStudioの設定をエクスポートしてインポートする方法](https://qiita.com/kakky0418/items/99f527f3a0f198a851a1)

最後に
===
他にやっておいた方がいい設定あれば、追加していきたいので、
コメントいただければと思います。
Windowsの標準機能でファイル作成日時を変更

# PowerShell

ファイルパス内にスペースがあっても問題ありません。

```powershell:
Set-ItemProperty "ファイルパス" -name CreationTime -value "2020/01/01 00:00"
```


# コマンドプロンプト

こちらもファイルパス内にスペースがあっても問題ありません。

```bat:
powershell Set-ItemProperty 'ファイルパス' -name CreationTime -value '2020/01/01 00:00'
```

コマンドプロンプトでいける = batファイルが作れます。

『作成日が古いファイルを自動削除する機能』系のテストで、頻繁に作成日が古いファイルを作りたい時は便利です。


# 蛇足

ドラッグドロップした複数ファイルの作成日を一括変更するbatファイル作ろうとしました。（下記）

```bat:
for %%f in (%*) do (
	powershell Set-ItemProperty %%f -name CreationTime -value '2020/01/01 00:00'
)
```
動くことは動く……しかしファイルパスにスペースが入るとエラーになる。
（PowerShellにファイルパスを渡す時にダブルクオテーション付きで渡しているらしく……上手い回避策が見つからなかった）

batにこだわらずにC#でexe作っちゃった方が簡単な気がした…(´・ω・`)



# バージョン

Windows10 Pro バージョン1909 OSビルド19042.630
PSVersion 5.1.19041.610
rtl-sdr その2

#概要

購入するので、調査。

#SDRの３つのタイプ

##ダイレクトコンバージョン方式（ゼロＩＦ方式）

受信したい信号と同じ周波数、あるいは非常に近い周波数の信号を内部の局部発振器で作り、受信信号と混合することで信号処理する。

##ヘテロダイン方式

スーパーヘテロダイン方式のＩＦ信号または検波信号を信号処理する方法。

##ダイレクトサンプリング方式

ＨＦ帯のように周波数が低い場合、受信信号を直接Ａ／Ｄ変換してＦＰＧＡとＤＳＰでデジタル信号処理を行う。

#rtl-sdrは、

28.8MHz クリスタルを使用したゼロ IF 出力のチューナーをサポートし、usbにIQ信号を出力する。

#gnuradioでFMラジオを組むには。

RTL-SDR sourceとlow pass filterとRational ResamplerとWBFM Receiverを配置。

サンプリングレートは、sourceは 2M, WBFM 48k出力にする。

以上。
【SpringBootActuator】prometheusのエンドポイントがテストで404になってしまう

## やりたいこと
`GET /prometheus`を叩いてHttpStatus200を確認するテストを実装したい。
Spring Bootのバージョンアップ等でうっかり消えてしまっていたというミスを無くすため。

## 問題
実際にアプリケーションを起動すると叩けるのに、テストだと404になってしまう。。。
GET /info, GET /healthは200なのに:astonished:

### 問題のコード

テストフレームワークはSpockを使用しています。

```application.yml
management:
  endpoints:
    web:
      base-path: /
      exposure:
        include: info, health, prometheus
```

```PrometheusSpec.groovy
@SpringBootTest
@AutoConfigureMockMvc
class PrometheusSpec extends Specification {
    @Autowired
    MockMvc mockMvc

    def "GET /prometheus"() {
        when:
        ResultActions actual = mockMvc.perform(MockMvcRequestBuilders
                .get("/prometheus"))
        then:
        actual.andReturn().getResponse().getStatus() == HttpStatus.OK.value()
    }
}
```

### 実行結果
```java
actual.andReturn().getResponse().getStatus() == HttpStatus.OK.value()
|      |           |             |           |  |          |  |
|      |           |             404         |  |          |  200
```

## 解決方法
`@AutoConfigureMetrics` をclassに付与することで解決。

> クラスパスに関係なく、@SpringBootTest を使用する場合、メモリ内でバックアップされているものを除いて、メーターレジストリは自動構成されません。
>
>統合テストの一環としてメトリックを別のバックエンドにエクスポートする必要がある場合は、@AutoConfigureMetrics でアノテーションを付けます。

https://spring.pleiades.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-detecting-config



## あとがき
ドキュメント読むの大事。
未経験エンジニアがAZ-900を取得するまで

# きっかけ。

弊社では業務に Microsoft Azure を使っているようです。
そこで、まずは Microsoft Azure について知るためにAZ-900(Azureの入門編)の資格を取得してみました。

とりあえずなんとか行けるだろうと思ったけど、意外と覚えることがありそのときの記録を残すために書いておきます。

[AZ-900](https://docs.microsoft.com/ja-jp/learn/certifications/exams/az-900 "AZ-900")　公式サイト

# 勉強方法。
まずはひたすら、Microsoft が提供しているLearningを行いました。
ラーニングパスが提供されているみたいで、細かな部分まで教えてくれます。

スキルの評価方法はも同じくMicrosoftが提供しているので、Microsoft Learnと一緒に確認しておくとよいかも。
[スキル評価] (https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE3VwUY)　日本語あればいいな・・・。

ラーニングバスも提供されており、コンテナの形式でクエリの実行を行い触ることもできましたが、
すべてを操作することができず、Azure の無料サブスクリプションを使用しました。
https://azure.microsoft.com/ja-jp/free/?cdn=disable
無料である上に、Azure Active Directory Premium P2 も無料でお試しすることができるので、
条件付きアクセスや、Intune を実際に触ってみたい！という人だったら、120%おすすめします。

個人的には、どのような問題が出てくるのか気になって会社で共有されている問題集を1回だけやりました。

##困ったこと。
ラーニングパス終了時に練習問題が出てくるのですが、3問ぐらいしか出てこず、
本当に理解できているのかなと不安になりました。特に参考資料もなくラーニングパスばかりやっていたので、
会社の経費で参考書をねだればよかったなと書きながら思いました。:woman_tone1:

試験概要は他の人がいくつか記載しているので割愛。


##受験後の所感。

通常は試験会場で受験ですが、このご時世もあるのかオンライン受験ができるようで、
初オンライン受験を受けてみました。身分証を見せたり、部屋の中にモニターがないのかなどいくつか試験官による確認が終わった後に
試験を受けました。家にいながら試験ができるので本番のような緊張感を感じることはあまりありませんでした。
ただ、移動の手間などは省けるのでこれはこれでありなのかなと感じます。


試験は　Windows ではなく、macos で実施したのですが監視しているせいか動作が重たく正しく回答ができているか1番不安な部分でした。
（勉強しているときよりも不安かもしれなかったです）

試験官とチャットができるのですが、タイムラグがすごく変な部分で改行が行われたりと不安でしたが無事に試験を終わり合格することができました。(ここ重要です!)試験レポートも正しく表示され、ひとまず安心でした。





次は[MS-500](https://docs.microsoft.com/ja-jp/learn/certifications/exams/ms-500)を取得するために勉強中。
監視システムも動きが軽くなっているといいな・・・・。



2021/04/27　追記

[MS-500](https://qiita.com/Tomtams/items/807974bb1b381be2748f
)合格できました。（一回落ちた体験記）
なぜ const(定数) で宣言したオブジェクトの中身を書き換えられるのか

今javascriptを勉強しているのだが、その過程で得た知識を共有しようと思う。
(間違っていたら指摘していただけると非常に助かります。)

javascriptを体系的に学ぶ前には　そういうもの　として逃げていたことなのだが、先程 オブジェクトのコピーの挙動を理解したときにピンと来て理解したものが以下である。

まず、以下のことははご存知のことだと思うが

```js
let myList=[0,1,2,3,4];
let mymyList=myList;
mymyList[0]=100

console.log(myList[0],myList[0])//100 100  ⇐両方100になる
```

javascriptでは以下のようにすると myList も mymyList も両方中身が書き換わってしまう。

今回のテーマを解説する前に、先にこちらの挙動を解説しておくと、

実はmyList という変数は、少し難しく言うと、'そのオブジェクト自体へのアドレスへの参照'を保持しているのである。

もっと簡単に大雑把に説明すると myList は 0,1,2,3,4　といった小さい箱を包み込んだ大きい箱 のメモリ上での場所を指しているのだ。

そして mymyList に　'同じ箱のアドレス'を渡してあげたので myList からでも　mymyList からでも同じ要素にアクセスできる　のである。

ここで本題に戻るが、 const　では　"その変数が指す大きな箱のアドレスを変えられなくするもの"　である。

つまり、

```javascript
let box=[0,1,2,3]
box=[9,9,9,9]
```

のように let　を使うと box に別ので確保したメモリのアドレスを新しく格納することはできるが、

const を使うとエラーが起きる。

あくまでもconstで固定されたのは、'大きい箱の場所'であって、大きい箱からアクセスされるところは変えることができるのである。


以上が自分のconstについての理解である。
PHPでの基本的なこと (2)

備忘録代わりにまとめる
毎回文末の;を忘れそうになる

#if文
###if
if文は if(条件式){真だった場合}と表記する

```php
$code = "Qiita";

if ($code == "Qiita"){
    echo "$code は　\"Qiita\"";
}
// Qiita は　"Qiita"
```

###else
elseを含んだif文は if(条件式){真だった場合}else{偽だった場合}と表記する

```php
$code = "Ooita";

if ($code == "Qiita"){
    echo "$code は　\"Qiita\"";
}else{
    echo "$code は \"Qiita\"　ではない";
}
// Ooita は "Qiita" ではない
```

###else if
else ifを含んだif文はif(条件式1){条件1が真だった場合}else if(条件式2){条件式2が真だった場合}else{すべて偽だった場合}と表記する

```php
$code = "Ooita";

if ($code == "Qiita"){
    echo "$code は　\"Qiita\"";
}else if {
    echo "$code は　\"Ooita\"";
}else{
    echo "$code は \"Qiita\" でも \"Ooita\" ではない";
}
// Ooita は "Ooita"
```

#ループ
###while
whileはwhile(条件式){実行}と表記する

```php
$code = 1
while ($code < 10){
    echo $code++."回目のループ";
}
// 1回目のループ2回目のループ3回目のループ……9回目のループ
```

改行はしないことに注意
改行を含めて行いたい場合は\nをつけること

###for
for文はfor(変数とその初期値の宣言；繰り返しの条件；一回行う事の処理){処理}と表記する

```php
for( $i = 0; $i < 10; $i+=2 ) {
echo "$i\n";
}
/*
0
2
4
6
8
*/
```
非エンジニア広報のMicrosoft Azure Fundamentals（AZ-900）受験記

本記事はQiitaの「エーピーコミュニケーションズ Advent Calendar」に参加しています。
https://qiita.com/advent-calendar/2020/ap-com

# 私のスペック

現在は広報担当。
8年くらい前までは、ネットワークエンジニア的なことをしていて、CCNAを持っていた。CCNPもあと1つでコンプリート！というところまでは取得。（あと１つというところで挫折）
なので、今は非エンジニアだが、ネットワークに関しては薄っっっすらと知識がある（ような、ないような）。
しかし、記憶は薄れゆく一方でアップデートは全くしておらず、クラウドに関しては「あー、クラウド？クラウドね、はいハイﾊｲ……（フェードアウト）」くらいなレベル。

# 準備1：非エンジニアの受験記を探す

「非エンジニアでも、ホントに取れるのかしら？」という最初の引っ掛かりを解消すべく、非エンジニアさんの受験期を探し、こちらの記事を参考にした。本当に感謝。

【AZ-900】広報採用担当ですが Microsoft Azure Fundamentals 合格しました -ビヨンドブログ-
　https://beyondjapan.com/blog/2020/08/az-900/

【非エンジニア合格体験記】Azure Fundamentals (2019年5月) -カテイデザイン-
　https://hide336.hatenablog.com/entry/cert_001

# 準備2：「MicrosoftLearn　Azureの基礎」を読む

Microsoftが提供している無料の学習コンテンツで、実際のAzureを触って実施する演習もありナカナカ面白い。
ただ、読み進めていってもすんなりと頭に入ってこず、「やっぱり向いてない…」と半分くらいのところで力尽きる。挫折寸前。

【MicrosoftLearn　Azureの基礎】
　https://docs.microsoft.com/ja-jp/learn/paths/azure-fundamentals/

# 準備3：受験バウチャー付きの無料トレーニングを受ける

Microsoftが主催している「AZ-900 Microsoft Azure Virtual Training Day: Fundamentals」というトレーニングを受講。
Totalで5時間のオンライントレーニングで、これを受講すると12,500円かかる試験をタダで受けられる。なんと太っ腹な。ありがたし。
もともとはオフラインで実施していたそうだが、コロナ禍ということで今はオンライン開催となっている。

「２」で折れかけていた心にムチを打って受講したのだが、思いのほか理解が進んだ。
めっちゃ駆け足だが、講師の方の図解がわかりやすかったのと、受講中にMSエンジニアの方がリアルタイムにチャットで質問に答えてくれるのが良かった。他の受講生からの質問やその回答もチャットに流れてくるので、気づきも多い。

# 準備4：参考書を読む

「合格対策 Microsoft認定 AZ-900:Microsoft Azure Fundamentalsテキスト&問題集」を購入。
https://www.amazon.co.jp/dp/4865942319?tag=note0e2a-22&linkCode=ogi&th=1&psc=1

「３」の復習を兼ねてざざっと一読。手で書かないと頭に入らない派なので、自分なりにまとめながらもう一周。
巻末の模試をやって苦手分野をあぶりだし、その部分をもう一読した。

# 準備5：「MicrosoftLearn」の確認テストをやる

「MicrosoftLearn」の各モジュールには、そのモジュールの理解度を測るテストが数問ある。
とにかくテスト慣れしたくて、こちらのサイトで紹介されていたモジュールの理解度テストを一通やり、本番に臨んだ。

【Azure】AZ-900 試験範囲を整理した -shimapapa.io-
　https://rikupapa-shima.hatenablog.com/entry/2019/07/06/150330

# 受験してみて

受験時間は60分だが20分ほどで解き終わり、もう一回すべての問題を見直せるくらいの余裕があった。
考えてわかる問題はほとんどなく、「知ってるか」「知らないか」で勝負は決まる。
ただ、「そんなのどこにも出てこなかったじゃん！」という問題もほとんどなかったので、上記の教材をしっかり覚えればクリアできるはず。
特に「こういうことをするために必要なAzureサービスはどれか」というのが多かったので、めんどくさがらずに覚えておくことをおススメする。（←めんどくさがって冷や汗をかいた人）

# 最後に：非エンジニアの同志（チャレンジャー）へ

実務で使うわけではなく、Azureのアウトラインを理解したいということであれば「４→３」で十分かと。「資格取得」までをgoalにするなら「５」もやっておくことをおススメする。

「非エンジニア」と題しているが、薄っっっすらと残っていたネットワークの知識に大いに助けられた。なので、ITインフラに関する知識が全くないという方は、「ちょっとー話が違うじゃない！」と思われるかもしれない。ゴメンナサイ。
でも非エンジニアでも取れない資格ではないので、ぜひ頑張って頂きたい。
EJSのif文でtrueの時だけ出力する。

## やりたいこと
```js
<% const person = { name: 'taro' };%>
<% if (person.name) { %><%= person.name %><% } %>
```
- 上記のような値があったときだけ出力する記述をスマートに書きたい。
- `<%`が多いので減らしたい。

## 結論
以下のように書くと完結に書くことができます。

```js
<%= person.name ? person.name : '' %>
```
三項演算子を使用します。偽値の場合は空文字です。

## 試したこと
```js
<%= if(person.name) { person.name } %> // エラー
<%= if(person.name) person.name %> // エラー
<% if(person.name) person.name %>  // 出力されない
```


偽値を省略できていないのが心残りですが、
結論の`<%= person.name ? person.name : '' %>`がシンプル。

他にいい方法があったら教えてください :bow_tone1:
【Unity】Transform座標をRectTransform座標に変換する方法

キャラクターの手前にHPゲージを表示したかったのだが、キャラクターがTransform、HPゲージは円ゲージを採用していたのでRectTransform。つまりワールド座標をスクリーン座標に変換してImageを表示する必要があった。![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/da518ec8-1013-febd-8814-7e9133a285fb.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/bbe1b6d8-a8d3-44a4-a402-5d72343cb146.png)

#方法

[テラシュールブログ](http://tsubakit1.hateblo.jp/entry/2016/03/01/020510)さんでやりかたが載っていたのでありがたく参考にさせていただいた。
ソールファイルはキャンバスオブジェクトにつける。

```cpp:test.cpp

    [SerializeField] private Image bossHp = default;        // ボスHP画像
    [SerializeField] private Vector2 bossHpPos = default;   // ボスHP座標調整

    private RectTransform bossHpRectTrans;
    private RectTransform canvasRectTrans;

    private void Awake()
    {
        bossHpRectTrans = bossHp.GetComponent<RectTransform>();
        canvasRectTrans = GetComponent<RectTransform>();
    }

    /// <summary>
    /// ボスのHP座標を設定する
    /// </summary>
    /// <param name="target">ボス座標</param>
    public void SetBossHpPotision(Vector3 target)
    {
        var newPos = Vector2.zero;
        var camera = Camera.main;

        var screenPos = RectTransformUtility.WorldToScreenPoint(camera, target);
        RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTrans, screenPos, camera, out newPos);
        bossHpRectTrans.localPosition = newPos + bossHpPos;
    }

```

解説としては
1つ目のRectTransformUtility.WorldToScreenPointでTransform（ワールド）座標をスクリーン座標に変換する。
2つ目のRectTransformUtility.ScreenPointToLocalPointInRectangleでスクリーン座標をRectTransform座標に変換する。

おそらく2つ目のほうはカメラ、キャンバスが複数あった場合、どのカメラに映っているキャンバス用RectTransformに変換するか？ということだと思う。キャンバスごとにカメラで映る解像度が変更できるし、Overlay設定とかもあるからそれのためなのかな？よくわからん…

今回もそうなんだけどSpineキャラクターは足元とかが中心座標になってたりするのでHP画像を表示する際には位置調整用に変数も追加。実行中に座標調整ができるという点に関してUnityは本当に便利。

まぁ、とりあえずこれでやりたいことはできたので一安心。
![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/51f2b48c-61f5-2760-4465-5b85bf4fb0e7.png)
ワールド座標とスクリーン座標の違いすらよく分かってなかったし、いつもマウスの座標取得すら手当たり次第に関数ぶつけて確認してるくらいの未熟者だったから今回のはマジでよくわからなかった。調査＆実装で3時間。＋備忘録作成に1時間もかかってしまった…これがなかなか難しいねんな。
Blenderのマテリアルを削除する方法【Blender2.8x】

##はじめに
VirtualMarket5に入稿する際にマテリアル数に限りがあったため、
Blenderでマテリアルを削除する方法を調べたのでまとめます。

##削除手順
削除手順は以下です。
#####①不要なマテリアルを選択する
#####②削除する
#####③再起動する

##①不要なマテリアルを選択する
削除したいマテリアルを選択し、設定する。
![Image01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/8a498924-dd08-afa4-cd8b-b026134f14cb.png)

##②削除する
Shiftを押しながら×ボタンを押す
![Image02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/a6bb47f5-59a3-af2b-9bdd-bb3bcc560f1c.png)

マテリアル名の左に「０」と表示されていれば、削除の判定になってます。
![Image03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/b6e64174-08b1-723a-9c4b-778253893012.png)

##③再起動する
再起動すると、「０」が表示されているものが削除されます。
![Image04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/9d38f399-1120-f9f5-c620-898f721b047a.png)

##おわりに
FBXでUnityにインポートした際に
モデルのReMappedMaterialが大変な数になり兼ねないので、不要なマテリアルは都度削除することをお勧めします！！
![Image05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436651/2b40d1a3-1384-5dc3-b6f3-21d4a1631533.png)
Intl.DateTimeFormatを使った日付や時間の0詰め

# 本題

最近仕事でNode.jsとV8のチェンジログを追っていたところ、`Intl.DateTimeFormat`という新機能を見つけました。使うと、日付や時間の0詰めを外部ライブラリに頼らずにシュッと書けそうなので試してみました。

サンプルコードは以下のような感じです。

```
const date = new Date('2020-01-01');
const dateStr =new Intl.DateTimeFormat('jp', {
  year: 'numeric', month: '2-digit', day: '2-digit',
}).format(date);
console.log(dateStr); // 2020/01/01
```
```
const date2 = new Date('2020-01-01');
const dateStr2 = new Intl.DateTimeFormat('jp', options = {
  year: 'numeric', month: '2-digit', day: '2-digit', 
  hour: '2-digit', minute: '2-digit', second: '2-digit', 
}).format(date2);
console.log(dateStr2); // 2020/01/01 09:00:00
```

コンストラクタ`Intl.DateTimeFormat`の第2引数にはオブジェクトで表示のオプションが渡せます。プロパティ値が`2-digit`なら`0詰めした値`、`numeric`なら`そのままの値`でフォーマットします。第1引数にはロケールを渡すのですが、各国の主要な表示方法でフォーマットするようです。

これで以下のようなコードとはおさばらじゃ！！

```
const date3 = new Date('2020-01-01');
const month = ('0' + (date3.getMonth()+1)).slice(-2);
```

# 参考
- [Intl.DateTimeFormat
](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)
Leafのテンプレートファイルが読み込まれない

VaporのLeafを使っている時に起きるエラーです。
ファイル構成は正しいはずなのに `.leaf` が読み込まれず `LeafKit.LeafError.Reason.noTemplateExists` と表示される場合は

Edit Scheme -> Run -> Options タブの中の `Check the "Use custom working directory` にチェックを入れ、プロジェクトのルートディレクトリを選択すると `.leaf` ファイルが読み込まれるようになりました。


![checkmark.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63855/52bac5c1-a72e-deb0-1265-0a51f359b89c.png)


参考: [Ask questionsRunning Feather from Xcode causes error](https://www.gitmemory.com/issue/BinaryBirds/feather/4/668321258)
[競プロ]Goの標準入力をまとめる

##はじめに
ある日Paizaにハマったので、Goの標準入力についてまとめておく。
##1つのデータの入力
```
package main

import "fmt"

func main() {
	var s string
	fmt.Scan(&s)
	fmt.Println(s)
}
```
##1行のデータの入力
```
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main()  {
	reader := bufio.NewReader(os.Stdin)
	s, _ := reader.ReadString('\n')
	fmt.Println(s)
}
```
##n行のデータの入力(1行目にデータ数)
```
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main()  {
	reader := bufio.NewReader(os.Stdin)
	s, _ := reader.ReadString('\n')
	s = strings.TrimSpace(s)
	n, _ := strconv.Atoi(s)
	for i:=0; i<n; i++ {
		s, _ = reader.ReadString('\n')
		s = strings.TrimSpace(s)
		fmt.Println(s)
	}
}
```
##複数のデータ(今回は3つ)の入力(スペース区切り)
```
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	s, _ := reader.ReadString('\n')
	s = strings.TrimSpace(s)
	t := strings.Split(s, " ")
	fmt.Println(t[0])
	fmt.Println(t[1])
	fmt.Println(t[2])
}
```
##n個のデータの入力(1行目にデータ数, 2行目にn個のデータ(スペース区切り))
```

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main()  {
	reader := bufio.NewReader(os.Stdin)
	s, _ := reader.ReadString('\n')
	s = strings.TrimSpace(s)
	n, _ := strconv.Atoi(s)

	s, _ = reader.ReadString('\n')
	s = strings.TrimSpace(s)
	t := strings.Split(s, " ")

	for i:=0; i<n; i++ {
		fmt.Println(t[i])
	}
}
```
##行列の作成
```
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	var matrix[][] string
	reader := bufio.NewReader(os.Stdin)
	s, _ := reader.ReadString('\n')
	s = strings.TrimSpace(s)
	t := strings.Split(s, " ")
	n, _ := strconv.Atoi(t[0])

	for i:=0; i<n; i++ {
		s, _ = reader.ReadString('\n')
		s = strings.TrimSpace(s)
		x := strings.Split(s, "")
		matrix = append(matrix, x)
	}
	fmt.Println(matrix)
}
```
IE11対応(JavaScript)

#IE対応の意義
下記URLを見ると2020年11月現在でも未だIE対応しなければならない現実があります.
https://gs.statcounter.com/browser-market-share/desktop/japan/#monthly-201810-202010

下記の通り2020年11月現在, IEが7.88%のシェアを占めています.
![IE_adjustment01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677894/fd544b61-8cb1-8bd1-b125-c3b3dd2bd616.jpeg)

(ちなみに全世界だとIEのシェアは2.15%まで落ちます(2020年11月現在))

世の中ではまだまだIEが使われていることがわかる.

IE11においては, JavaScript?のES6が一部のみの対応に留まっている.
モダンな実装ができないと困るのでBabelというものを使う.

#Babel
JavaScript?のコンパイラ. ES6以降の構文をES5以前の形式に変換するのに利用されたり, TypeScript?のコンパイルにも使われたりする.
https://babeljs.io


例えば下記のコードは普通だとIE11では動きません
アロー関数とテンプレートリテラルがIE11で非対応だからです.

```javascript:ES6
//Doesnot work on IE11  
let foobar = ( hoge, fuga ) => {  
        return console.log("ほげの出力:${hoge}");  
//~~~~~~~~~~処理~~~~~~~~~~~~~~  
        return console.log("ふがの出力:${fuga}");  
//~~~~~~~~~~処理~~~~~~~~~~~~~~  
  }  
```
これを下記のようなES5形式に自動コンパイルしてくれる.

```javascript:ES5
// Works on IE11  
let hogefuga = function( hoge, fuga ){  
        return console.log("ほげの出力:" + hoge);  
//~~~~~~~~~~処理~~~~~~~~~~~~~~  
        return console.log("ふがの出力:" + fuga);  
//~~~~~~~~~~処理~~~~~~~~~~~~~~  
  }  
```

ES6形式の方が効率がよく, できることも多く, 実装によっては(promiseなどは特に)必須になってくることがあるので,
コンパイルしてもらったほうがいい.


#BabelPolyfill
スタンドアロンのBabelPolyfill?を使うとIE11でもES6記法が動く.
CDNだけで対応できてお手軽.

#BabelスタンドアロンCDNの場合

```html:html
<script src="https://cdn.jsdelivr.net/npm/@babel/polyfill@latest/dist/polyfill.min.js"></script>  
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@latest/babel.min.js"></script>  
<script type="text/babel" data-presets="env,stage-3" src="./js/main.js"></script>  
```
main.jsは適宜書き換えてください.

#npmの場合
```shell
npm install --save @babel/polyfill  
```

```javascript
import "@babel/polyfill";
```
PowerShellのバージョン確認方法

#確認コマンドはこちら
PowerShell開いて下記。

```
$PSVersionTable
```
結果の例。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c6b0f744-1c36-3549-c12b-de7a98fec549.png)


#蛇足
いろんなバージョン番号が出てくるけど **PSVersion** がPowerShellのバージョン。
一番上に来てるし、名前からいってもそうだね。


#バージョン
Windows10 Pro バージョン1909 OSビルド19042.630
ActiveRecordでは present? の代わりに exists? を使おう

小ネタです。

# 条件に該当するレコードが存在するかを確認したい
ActiveRecordで条件に存在するレコードが存在するかを確認するのに、つい、

```ruby
Model.where(conditions).present?
```

と書いてしまいがちですが、これはパフォーマンス上の問題が生じる可能性があります。

`.present?` は ActiveSupport によってモンキーパッチされたメソッドです。
`Mode.where(conditions)` のような `ActiveRecord_Relation` クラスのオブジェクトに `.present?` を適用するとどうなるか？

すると条件に該当するレコードを**全てDBから取得して**、（Rails上のモデルの）配列として評価することになります。
配列に要素が存在すれば `true`、 しなければ `false` ですね。

## なぜこれはダメなのか
一見すると問題なさそうですし、実際結果自体は正しいのですが、条件に該当するレコードが1つでも存在することを確認できれば良いわけで、全件を取得する必要はありません。
100万レコードが条件に該当した場合、その100万レコードがDBからピックアップされ、その100万レコード分のデータがRails側に転送され、100万のモデルが作成された上で捨てられる。という壮大な無駄が発生します。結果、いつまでたっても結果が返ってこない。というパフォーマンス上の障害を引き起こしてしまうのです。

こういうのはレコード数の少ない開発環境では顕在化しずらく、レコード数の多い本番環境でいきなり顕在化してパニックになることがあります。

## では、どうする？
`.exists?` メソッドを使いましょう。

```ruby
Model.where(conditions).exists?
```

こちらを使うと、SQLが `exists` 式を使うものに代わります。
`exists` 式は条件に該当するレコードが1件でも存在すればDBがそこで探索を打ち切ってくれるので、無駄に全件を取ってくることはありません。
DBレベルで `true` または `false` で返してくれるのでオーバヘッドが最小で済みます。

## present? の逆は？
`.present?` の逆である `.blank?` に対応するメソッドは `.empty?` になります。
`.empty?` を使えばSQL上は `exists` 式を使います。

ただ、条件に該当するレコードが存在しないことを確認するには、結局全件のチェックが必要になるので両者（ `.blank?` と `.empty?` ）に速度的な差は少ないかもしれません。
TableExportで好きな位置にExcelやCSV出力ボタンを配置する



# はじめに
JQueryプラグイン「TableExport」ではテーブルを簡単にExcel、CSV、テキストファイルなどで出力できます。ただ、出力ボタンの位置は上下で固定っぽくて不便だったので、改善策を備忘録として残しておきます。

TableExport自体の使い方は[こちらのサイト](https://www.wp-benricho.com/tableexport/)が分かりやすいので参考にされてください。

開発環境は以下の通り

* Ruby 2.6.3
* Rails 5.2.4.4
* jQuery 1.12.4

(Ruby on Rails使用してますが、今回の記事ではjQueryのみ取り上げているのであまり関係ないかと思います)

なお、bootstrapを使えばデフォルトでオシャレなボタンにできますが今回は使いません。

# 問題点
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688567/b9f0a27b-7c8c-e506-4901-dfd71c6d54f5.png" width="70%">

<br>
Export to xlsxボタンがとんでもないところにありますね。
普通のテーブルだともう少しマシかもしれませんが、このテーブルは見出し固定のスクロール式で、テーブルを横にスライドするとボタンも一緒に流されてしまうので余計見にくい代物になってしまいます。。

<br>
一応オプションでボタンの位置を指定できますが、前述した通り上下の指定しかできないので改善には至りませんでした。

~~~ruby
$(".table").tableExport({
    ...
    position: "bottom",
    ...
});
~~~

# 解決策
至ってシンプルです。

①tableExport()で生成されるボタンを隠して代理ボタンを配置する
②代理ボタンが押されたらtrigger()でもともとのボタンが押されたことにする

~~~html:htmlファイル

...

<table id="export-table">
    ...
</table>

<button type="button" id="export-btn">Excel出力</button>

...

~~~

~~~ruby:jqueryファイル
...

$('#export-table').tableExport({
    formats: ["xlsx"],
    bootstrap: false
});

$('#export-table caption').hide();

$('#export-btn').on('click', function(){
    $('.table caption button').trigger('click');  
});

...

~~~

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688567/ab7d497b-4324-8b1a-7b5a-7e28b61dad83.png" width="70%">

うまくいきました！
もちろんCSVやテキストファイルの出力にも使用できます。

# おわりに
TableExportはとても簡単に外部ファイルを出力できるプラグインですが、扱っている記事自体がとても少ないので、こういうちょっとした解決策っていうのはもっと増えていくと嬉しいですね。
ruby 演習メモ V (Recursive Fibonacci)



# 目的

ruby のコードを実際に書いてみよう.
今回は第 V 弾.


# お題:Fibonacci数列

    fib(n) = fib(n-1)+fib(n-2)
    0 1 1 2 3 5 8 13 21 ...

を recursion (再帰) で求める.
([ここ](https://qiita.com/daddygongon/items/1bb27b8920c201d5c520)にある課題)


# 解説

以下のような関数 fib をつくる

-   **関数名** : fib
-   **入力** : n (項の番号)
-   **出力** : 第 n 項の値

~~今回は TDD (Test Driven Development : テスト駆動開発) を意識して解説を書く.~~
解説を書こうと思ったけど, 先程リンク先にある内容と同じになるので割愛. (細かな解説はリンク先を見よう.)

一応, TDD の作業概要を以下に書いておく.

-   テストを作る
-   **red** : エラーを出す
-   **green** : エラーをなくす (green)
-   **refactoring** : code を綺麗にする (refactoring)


## まとめ

TDD で良い感じに Fibonacci 数列の code を書けた. 素晴らしい.


# 今回書いた code の全体

最終的にこうなった. ファイル名は "fibonacci.rb".

```ruby

require './assert_equal_final'

def fib(n)
  return 0 if n==0
  return 1 if n==1
  return fib(n-1) + fib(n-2)
end

if $PROGRAM_NAME == __FILE__
  [[0,0],[1,1],[2,1],[3,2],[4,3],
   [5,5],[6,8],[7,13],[8,21],[9,34]].each do |index, expected|
    assert_equal(expected, fib(index))
  end
end

```


# 参考資料

[チャート式ruby-V(Recursive Fibonacci)](https://qiita.com/daddygongon/items/1bb27b8920c201d5c520)



------
 - **source** ~/Lecture/multiscale_simulation/grad_members_20f/members/gagagagazelle/docs/c5_fibonacci.org
10分でHMS Audio Engineを利用してアプリにカラオケ機能を実装

##カラオケ機能（エコー機能）のアプリを作りました。
早速HMS Audio Engineを使って、シンプルにカラオケ機能（エコー機能）をアプリで作りました。

◆ Object作成、Object初期化、Callbackの登録

```php
mHwAudioKit = new HwAudioKit(this, callBack);
mHwAudioKit.initialize();
// Create KaraokeFeature:
mHwAudioKaraokeFeatureKit = mHwAudioKit.createFeature(HwAudioKit.FeatureType. HWAUDIO_FEATURE_KARAOKE);
// Create a callback task.
IAudioKitCallback callBack = new IAudioKitCallback() {
@Override    
public void onResult(int i) {
        if (i == 0) {
             // HwAudioKit initialization is successful. Its APIs can be used, such as
             mHwAudioKit .getSupportedFeatures(); //Return the list set.
             mHwAudioKit .isFeatureSupported(FeatureType type); // Return true or false: true indicates supported, while false indicates the product does not support the query function.
        }
        if (i == 2) {
            // The Engine service is not installed and the kit is not supported
        }
        if (i == 1000) {
            // HwAudioKit initialization is successful. Its APIs can be used, such as:
            // Query whether Karaoke is supported: true indicates supported, while false indicates not.
            int isSupport = mHwAudioKaraokeFeatureKit.isKaraokeFeatureSupport();
            // Turn on or off the headset monitoring function. The value 0 indicates success, 1806 indicates that the product does not support the karaoke function, and 1805 indicates that no headset is inserted.
            boolean enableSuccess = mHwAudioKaraokeFeatureKit.enableKaraokeFeature(enable);
            // Set the sound effect and volume. The value 0 indicates success, 1806 indicates that the product does not support the karaoke function, 1805 indicates that no headset is inserted, and 1807 indicates parameter error. 
           int success = mHwAudioKaraokeFeatureKit.setParameter(HwAudioKaraokeFeatureKit.ParameName.CMD_SET_AUDIO_EFFECT_MODE_BASE, value);
           // Obtain the latency information.The value -1 indicates obtaining failure
           int latency = mHwAudioKaraokeFeatureKit.getKaraokeLatency();
        }
    }
}

```



◆ Object廃棄

```php
mHwAudioKaraokeFeatureKit.destroy();
mHwAudioKit.destroy();
```


##完成

![audio.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677524/c68cdc04-7178-30b6-b324-051d7c24fa00.png)

START RECORDING、STOP RECORDING、PLAY RECORDINGで自分の音声を録音して再生。
TURN ON KARAOKEで自分の音声をリアルタイムで聞くことができます（エコー機能）。
さらに、KTVモードやTHEATERモードなども変更可能です。


##参考
HMS Audio Engineについて
https://developer.huawei.com/consumer/en/doc/development/Media-Guides/audio-introduction

開発ガイド
https://developer.huawei.com/consumer/en/doc/development/Media-Guides/audio-guide
WindowsでNimからPostgreSQLにアクセスする

## libpq.dllはどこに？

開発PCにDockerがインストールされている環境では、PostgreSQL等のDBサーバーを立ち上げるのは比較的簡単です。

DBサーバーを立ち上げることは簡単になったものの、WindowsからPostgreSQLにアクセスする場合、Nimであれば`db_postgres`モジュールを使えばアクセスできるわけではなく、`db_postgres`が、`libpq.dll`というDLLファイルに依存しており、このファイルが無いことには、PostgreSQLにはアクセスできません。

```nim
import db_postgres
let db = open("localhost:5432","user","password","database_name")

# Error
# could not load: libpq.dll
```

## libpq.dllだけを落としてきてもダメ

今どきでは、libpq.dllを検索するとダウンロードサイトがいくつかヒットします。
ですが、Windows32ビット版だったりなど、なかなかうまく行きません。

## 結局のところ、PostgreSQLをダウンロードせよ

PostgreSQLの本体はインストールしたくないけど、クライアントツールのインストールさえできれば、DLLが手に入りそうなので、諦めて本家(https://www.enterprisedb.com/downloads/postgres-postgresql-downloads) から、PostgreSQLのインストーラをダンロードします(およそ200MBくらい)。

![2020-11-25 17.14.18 www.enterprisedb.com ca0e93a85381.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58872/3e3cd5e1-435a-3245-ae98-c877cbd80130.png)

## Let's インストール

ダウンロードしたファイルはExe形式になっているのでこれを実行し、インストーラを起動します。
![2020-11-25_17h41_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58872/28c4d81f-8744-05f1-36c7-cb82de6091a0.png)

### コマンドラインツールだけを選択しインストール

PostgreSQL自体はDockerで導入するので、CommandLine Toolsをチェックし、インストールを継続します。

![2020-11-25_17h42_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58872/fa61a9ba-825f-ef87-9107-78a24c4e6072.png)

## libpq.dllはどこに？(その２)

インストールされたフォルダを確認すると、`C:\Program Files\PostgreSQL\11\bin`フォルダに、念願のlibpq.dllが入っています。

![2020-11-25_17h46_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58872/446dc216-e89f-8baa-947e-878fc9fd2c64.png)

## libpq.dllだけをコピって使おうとしてもやっぱりダメ

nimソースのあるフォルダにlibpq.dllファイルをコピーし、先のコードを実行しても、まだlibpq.dllが無いと怒られます。
この理由はlibpq.dllが更に他のDLL(binフォルダに配置されていたDLL)に依存しているからです。

これは、[dependency walker](https://www.dependencywalker.com)というツールを使うと確認できます。

![2020-11-25_18h19_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58872/0767d598-d07c-fd10-c08e-c87dcc6ec74e.png)

そのために取れる手段としては、以下の２つのうちのどれかとなります。
* インストール先のbinフォルダへPathを通す
* binフォルダ内のすべてのdllファイルを(nimインストール先のbin)コピーする

## まとめ的な何か

PostgreSQLのインストール先\binにパスを通し、以下のソースを実行してみます。

```nim:pgsample.nim
import db_postgres

const host_port = "localhost:5432"
const user_name = "username"
const password  = "password"
const db_name   = "postgres"

block:
  let db = open(host_port,user_name,password,db_name)
  echo "opened"
  defer:
    db.close 
    echo "closed"
  for x in db.fastRows(sql"select current_schema()") :
    echo x
```

結果はこちら。

```shell
opened
@["public"]
closed
```

この手の方法はその他DB(Oracle/MySQL)でも同様で、クライアントツール等のインストールを行い必要なDLLへのパスを通すなどの作業は必要です。
当初はlibpq.dllだけが必要ならそれだけ落としてこれば良いかと思って始まった勘違いの旅路でした。
Google Cloud PlatformからAPIキー発行

#YouTube API
YouTubeに上がっている動画情報をAPIで取得し, 自分のwebページに展開したい.

#目次
 1. Googleアカウントがある
 2. Google Cloud Platform(GCP)にアクセス
 3. API key発行
 4. axiosでAPI取得


#GCPでAPI keyの発行
##ダッシュボードに行きAPIとサービスに入る.
![screen_GCP_dashboard.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677894/0d8b545c-d668-d44b-56c4-192c5c3c6167.jpeg)



##上部の認証情報作成を押す.
![screen_GCP_authinfo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677894/fd4d3224-68b3-494d-2380-f6b86de5c6be.jpeg)


##APIキーが作成されるのでどこかにメモっておく.
当たり前だが, こういったAPIキーは不正に利用されることがあるので取り扱い注意.
![screen_GCP_api_key.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677894/c319bd36-877f-e6dd-3b41-c2dabd8a9608.jpeg)


##API制限
APIはフロントエンドで使われるため, キーに制限を設けて不正利用を防ぐ.
ここでは, HTTPリファラーとして`*.hogehoge.com/`を指定している.
ローカル環境でも許可したい場合は任意で適当に追記する.
![screen_GCP_api_key_restriction.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677894/20a953ab-0051-583d-f444-e3721a305394.jpeg)



以上
IE11対応【JavaScript編】

#IE11対応の意義
下記URLを見るとレガシーと言われながらも2020年11月現在でも未だIE対応しなければならない現実があります.
https://gs.statcounter.com/browser-market-share/desktop/japan/#monthly-201810-202010
下記の通り2020年11月現在, **デスクトップでは**IEが7.88%のシェアを占めています.

![browser_share_jp_01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677894/c97f4731-499d-23da-146c-dc7380df5a07.jpeg)
(ちなみに全世界だと全デスクトップブラウザのうちのIEのシェアは2.15%まで落ちます(2020年11月現在))

世の中ではまだまだIEが使われていることがわかる.

IE11においては, JavaScriptのES6が一部のみの対応に留まっている.
モダンな実装ができないと困るのでBabelというものを使う.

#Babel
JavaScriptのコンパイラ. ES6以降の構文をES5以前の形式に変換するのに利用されたり, TypeScriptのコンパイルにも使われたりする.

[https://babeljs.io/]("Babeljs.io")

例えば下記のコードは普通だとIE11では動きません
アロー関数がIE11で非対応だからです.

```javascript
let hogefuga = ( hoge, fuga ) => {
        return console.log("ほげの出力:${hoge}");
//~~~~~~~~~~処理~~~~~~~~~~~~~~
        return console.log("ふがの出力:${fuga}");
//~~~~~~~~~~処理~~~~~~~~~~~~~~
  }
```
これを下記のようにES5形式に自動的にコンパイルしてくれるのがBabel.

```javascript
let hogefuga = function( hoge, fuga ){
        return console.log("ほげの出力:" + hoge);
//~~~~~~~~~~処理~~~~~~~~~~~~~~
        return console.log("ふがの出力:" + fuga);
//~~~~~~~~~~処理~~~~~~~~~~~~~~
  }
```
ES6形式の方が効率がよく, できることも多く, 実装によっては(promiseなどは特に)必須になってくることがあるので,
コンパイルしてもらったほうがいい.

#Babel Polyfill
Polyfillを使うといろんなブラウザ(IE11)でもES6記法が動くようになる

```javascript
import "@babel/polyfill";
```

##npmの場合
```shell
npm install --save @babel/polyfill
```

##yarnの場合

```shell
yarn add @babel/polyfill
```


##スタンドアロンCDNの場合
ES6記法を使う直前に以下を記述.

```html
<script src="https://cdn.jsdelivr.net/npm/@babel/polyfill@latest/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@latest/babel.min.js"></script>
<script type="text/babel" data-presets="env,stage-3" src="./js/main.js"></script>
```
EC2を複製（コピー）したい場合に「同様のものを起動」ボタンという罠

小ネタです。
EC2インスタンスを複製、コピーしたい場合に、

- AMI（イメージ）の作成
- ↑で作成したAMIからEC2を作成

という手順をするのが[正解](https://qiita.com/ponsuke0531/items/ceca4ac18c097f8b24b8)ですが、**「同様のものを起動」** という、一発でコピーしてくれそうなボタンがあります。

![インスタンス___EC2_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32169/5c8b4aad-40ad-4e55-4c58-a0f590fe167e.png)


が、これは罠で、インスタンスのコピーではなく、一部設定のみを引き継ぐ、というものです。EC2内部のファイル諸々はコピーされません。

[AWSのdoc](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/launch-more-like-this.html)

> [Launch More Like This (同様のインスタンスをさらに起動)] ウィザードオプションでは、選択されたインスタンスは複製されません。一部の設定が複製されるのみです。インスタンスのコピーを作成するには、最初にインスタンスから AMI を作成して、AMI からさらに多くのインスタンスを起動します。

残念。

私達が本当に欲しい、

- AMI（イメージ）の作成
- ↑で作成したAMIからEC2を作成

をまとめてやってくれる機能はまだ（2020/11現在）ありません。残念。
マルチスケールシミュレーション特論10

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# Recursive Fibonacci


## 講義ページリンク

[チャート式ruby-V(Recursive Fibonacci)](https://qiita.com/daddygongon/items/1bb27b8920c201d5c520)


## 内容

rubyで再帰処理


## 課題

フィボナッチ数列を計算するプログラムの作成


## 解答例

```ruby:"assert_equal.rb"
#!/usr/bin/env ruby
# frozen_string_literal: true

def fib(n)
  if n.zero?
    0
  elsif n == 1
    1
  else
    fib(n - 1) + fib(n - 2)
  end
end

require './assert_equal'
[[0, 0], [1, 1], [2, 1], [3, 2], [4, 3],
 [5, 5], [6, 8], [7, 13], [8, 21]].each do |index, expected|
  puts assert_equal(expected, fib(index))
end
```

出力

    > ruby fibonacci.rb
    expected: 0
    result: 0
    succeeded in assert_equal.
    
    expected: 1
    result: 1
    succeeded in assert_equal.
    
    expected: 1
    result: 1
    succeeded in assert_equal.
    
    expected: 2
    result: 2
    succeeded in assert_equal.
    
    expected: 3
    result: 3
    succeeded in assert_equal.
    
    expected: 5
    result: 5
    succeeded in assert_equal.
    
    expected: 8
    result: 8
    succeeded in assert_equal.
    
    expected: 13
    result: 13
    succeeded in assert_equal.
    
    expected: 21
    result: 21
    succeeded in assert_equal.


# NOTE

-   再帰処理は他のプログラミング言語と同じように書ける
-   rubocopいわくfibというmethod名は短いらしいけど特に問題ないので無視する



------
 - **source** ~/multiscalesim_toku/grad_members_20f/members/lynd2299/mss10.org
Swift製Webフレームワーク Vaporの紹介2020

# Vaporとは

Vaporは、Swift製のWebフレームワークです。
公式URLは [https://vapor.codes/](https://vapor.codes/) で、Vapor 本体のリポジトリ([https://github.com/vapor/vapor](https://github.com/vapor/vapor)) には　

> Vapor is a web framework for Swift. 
> It provides a beautifully expressive and easy to use foundation for your next website, API, or cloud project.　

と説明が書かれています。
Vapor はスター数も多く(2020年12月現在1万9千程度)、[gitignore.io](https://www.toptal.com/developers/gitignore) などVaporで開発されたアプリケーションも少しずつ増えてきました。
今回はVaporアドベントカレンダー2020の初日として、インストールとHelloWorldをしてみようと思います。


# 環境構築

## for MacOS
公式(https://docs.vapor.codes/4.0/install/macos/)

Xcode(11.4 以上)が必要なのでApp Storeからダウンロードします。(https://apps.apple.com/us/app/xcode/id497799835?mt=12)
また Vapor4 には Swift 5.2 以上が必要なので、バージョンを確認します。

``` bash
$ swift --version
```

```
Apple Swift version 5.3.1 (swiftlang-1200.0.41 clang-1200.0.32.8)
Target: x86_64-apple-darwin20.1.0
```

次に Vapor のプロジェクト作成が簡単にできる VaporToolBoxを インストールします。

``` bash
$ brew install vapor
$ brew upgrade vapor  # すでにインストールされている場合
```

Vapor ToolBoxがインストールできたことを確認します。

``` bash
$ vapor --help
```

## for Linux
公式(https://docs.vapor.codes/4.0/install/linux/)
Vapor4は以下のLinuxディストリビューション & バージョンでサポートされています。

| Version      | Version      | Swift Version |
|---           | ---          |---            |
| Ubuntu       | 16.04, 18.04 |>= 5.2         |
| Ubuntu       | 20.04	      |>= 5.2.4       |
| Fedora       | >= 30        |>= 5.2         |
| CentOS       | 8	      |>= 5.2.4       |
| Amazon Linux | 2	      |>= 5.2.4       |

Swift がインストールされた状態でVaporToolBoxを インストールします。

``` bash
$ git clone https://github.com/vapor/toolbox.git
$ cd toolbox
$ git checkout <desired version>
$ make install
```

Vapor ToolBoxがインストールできたことを確認します。

``` bash
$ vapor --help
```


# HelloWorld

環境構築が完了したので早速プロジェクトを作成します。
プロジェクトの作成には `new` コマンドを使用します。

``` bash
$ vapor new プロジェクト名
```

`vapor new`コマンドを実行すると対話式でプロジェクトを作成することができます。(必要なパッケージが組み込まれた状態でプロジェクトが作成されます。)
`-n` フラグをつけてプロジェクトを作成するとパッケージが組み込まれない素の状態のプロジェクトを作成することができます。
今回は`-n` フラグをつけてプロジェクトを作ります。


``` bash
$ vapor new hello -n
```

プロジェクト名のディレクトリが作成されれます。
ディレクトリの中に入り、 `Package.swift` ファイルをXcodeで開きます。

``` bash
$ cd hello
$ open Package.swift
```

パッケージのインストールが終わったらビルドボタンを押すことでアプリを実行します。
ブラウザで　http://localhost:8080/ にアクセスすると `It works!` と表示され、アプリケーションが起動していることが確認できます。

Xcodeを使わない場合は以下のコマンドでビルドとアプリケーションの実行をすることができます。

``` bash
$ cd hello
$ vapor build
$ vapor run
```
JupyterNotebookあれこれ

JupyterNotebookをPythonの学習で使うにあたって使いこなしたいテクニックについてまとめていく。

# セルについて
JupyterNotebookは一般的なテキストエディタ、コードエディタとは違い、セルによって区切ることができ、セル単位でコードの実行ができることが特徴。
出力もセル直下にそれぞれ表示されるため、コードと実行結果の対応がわかりやすい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499408/c1f83d95-649c-3a82-b081-a3e86d71e40f.png)
JupyterNotebookと同じくAnacondaに標準で入っているVisualStudioCode(VScode)との比較
上記のように、区切ったセルごとにMarkDown形式で説明やコメントをつけることができる点で、学習に使うツールとしてVSCodeよりJupyterNotebookが優れているといえる。
また、LaTeX(TeX)という形式で数式を入力することができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499408/b36cb3b8-c5b4-a33c-f3cb-a693fc3ccfa2.png)
開発などで大量のコードを書く場合には
JupyterNotebookでコード単位の単体テスト
↓
VSCodeでコードをまとめて全体のテスト
という風に使い分けている。

# CommandModeとEditMode
JupyterNotebookのセルにはCommandModeとEditModeという2つのモードがある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499408/fbbba2ad-5c8b-f585-91b3-a85accd763c5.png)
上記画像のように左の線が水色になっているのがCommandMode
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499408/2d4c13aa-ef1f-19cb-5085-c01df49c204d.png)
上記画像のように左の線が緑色になっているのがEditMode

CommandMode → EditMode は `Enter`
EditMode → CommandMode は`Escape`
で移行できる。

# CommandModeで使えるテクニックまとめ


1. **`H`を押すとショートカット一覧が出る**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499408/fe67ccc8-7e1c-0b49-f41a-2dd022456e6c.png)

1. **新規セルを挿入**
`A`で現在のセルの上(Above)、`B`で現在のセルの下(Below)に新しいセルを挿入することができる

1. **CodeモードとMarkdownモードを切り替える**
Pythonのプログラムを書いて実行するために使うセルはCodeモードで使い、説明やコメントをつけるときにはMarkdownモードで使う。
`Y`でCodeモードへ、`M`でMarkdownモードへと移行できる。
新規セルを挿入したときにはデフォルトでCodeモードになっているので、MarkDownモードで入力したいときには
`Esc`→`M`→`Enter`→入力
をクセづけるとスムーズに

1. **`X`でセルの切り取り、`C`でコピー、`V`で貼り付け**
よく使う`Ctrl+C`と同じ。
切り取った後貼り付けなければ実質削除なのでよく`X`を削除として使う。
(ちなみに本当の削除コマンドは`D`2連打)



# EditModeで使えるテクニックまとめ

1. コード実行
`Ctrl+Enter`でコード実行
`Shift+Enter`だと、下にセルがある場合は下のセルに移動、下にセルがない場合はセルが追加された上で次のセルに移動
末尾セルで入力していき、実行しながらどんどん書いていきたい場合には`Shift+Enter`を自分の中でデフォルトにしておくといいかも

1. `Shift`で入力補完
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499408/29d12d37-91ec-4ddd-674d-2f5f56dba469.png)
入力途中で`Shift`を押すと候補を提示してくれる。
ライブラリ名やメソッド名が長いときや思い出せないときに便利
TensorFlow.kerasのModel.fit()実行時におけるsteps_per_epoch

# 概要
TensorFlow.keras(以下tf.keras)ではModel.fit()を実行してモデルの訓練を行います。
そのModel.fit()の引数に**steps_per_epoch**という項目があり、これにどんな値を与えれば良いのかを確認します。データ拡張などで**ImageDataGenerator**を使用することを前提としています。

# ImageDataGenerator
tf.keras内のデータ拡張を簡単に行うことができるクラスです。ImageDataGeneratorは指定したバッチサイズ・画像の加工内容で無限にバッチを生成することができます。このバッチ生成は訓練時に行われるため、大規模データセットや比較的大きなバッチサイズでも使用するメモリを少なくし訓練を可能にします。

```train.py
# インスタンスの作成 (画像の加工内容の指定)
train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range=30,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.1,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode='nearest'
)

train_generator = train_datagen.flow_from_directory(
    TRAIN_DATA_DIR, # データセットがあるディレクトリ
    target_size=(IMG_WIDTH, IMG_HEIGHT),
    color_mode='rgb',
    classes=CLASSES, # クラスの配列 ['dog', 'cat']など
    class_mode='categorical',
    batch_size=BATCH_SIZE # 1回のバッチ生成で作る画像数
)
```

ImageDataGeneratorはこのように使われます。classesは与えなくても自動的にディレクトリの構成で判断してくれる機能も備わっています。また、訓練データに対するgeneratorと検証データに対するgeneratorをそれぞれ用意することが一般的です。

# ImageDataGeneratorを使用したfit()
ここからが本題です。以下はModel.fit()の実行例です。

```train.py
# modelは作成したModelクラスのインスタンス (省略)
history = model.fit_generator(
        train_generator,
        steps_per_epoch=STEPS_PER_EPOCH, # ?
        epochs=EPOCHS,
        validation_data=validation_generator,
        validation_steps=VALIDATION_STEPS # ?
)
```


第一引数には訓練データのgeneratorを指定します。その他で意味がわかりくいのはsteps_per_epochとvalidation_stepなどだと思います。

### steps_per_epoch
各エポックの**イテレーション回数**を指定します。イテレーションは簡単に言うと各エポックで重みを更新する回数です。通常バッチごとに重みが更新されるので、各エポックでバッチを生成する回数に等しいです。steps_per_epochの値は1以上のint型であればどんな値でもエラーは出ないと思われます。デフォルトの値(None)は、**画像数 ÷ バッチサイズ**で与えられます。

例を示すと以下になります。
1000(訓練用画像数) ÷ 10(バッチサイズ) = 100(steps_per_epoch)

簡単な計算ですが**注意**があります。

もし、**「データ拡張を使用して画像数を3倍にした」**と解説を添えた場合に、上の計算の総画像数はどうなるでしょうか？**これを1000と3000のどちらに定義するのかが曖昧なのです。**　
色々な解説記事を見てみると、**記事によってまちまち**だと感じます。
なので、自分が実験で何を比較したいかなどを考えてから設定すべきなのかなーとも思います。それとも、デフォルトの値が生の訓練用画像数を用いて計算していることから「画像数を○倍にした」という解説自体がナンセンスなんでしょうか？自分には答えは出せません...。

**どちらにしろ理解していることが重要**だと思うので今回記事にさせていただきました。


ぼやき：研究で作成した小さなデータセットでデフォルトの値だと学習曲線がガタガタで何が起きているかわからない...:sob:

### validation_steps
Model.fit()実行時に各epochの終了時点で検証データに対するlossとaccuracyが計算されます。その際に何回バッチを生成して値を求めるかをvalidation_stepsに与えます。デフォルト(None)ではsteps_per_epochと同様にデータセットの検証データの画像を全て使いきるような値に設定されます。( 検証用画像数 ÷ バッチサイズ )。検証用データには画像加工などを施さないことが一般的なので、こちらはNoneを指定して問題ないと思います。

# 補足
以前はImageDataGeneratorのデータ拡張を使用した際の訓練はModel.fit_generator()が使用されていましたが、現在はModel.fit()もgeneratorを使用した訓練のサポートがされているため、そちらを使おうという方針になっています。(2020/11/25)

![スクリーンショット 2020-11-25 16.36.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381461/8d3efb39-0ad9-645b-79a5-fe727fd43119.png)


※記事に誤りがあった場合は修正または削除で対応します※


# 参考
* [公式ドキュメント: TensorFlow Core v2.3.0 tf.keras.Model](https://www.tensorflow.org/api_docs/python/tf/keras/Model#fit_generator)
【#PowerApps】Power Apps から指定した日時に Twitter に投稿する仕組みを考える

# 概要

https://zuvuyalink.net/nrjlog/archives/4728
この記事をみて、１度限りの投稿であればデータソース必要ないかな？と考えたので、データソースを使わない方法を探してみました。


# やり方

方針として、データソースを用いないかつ Power Apps からなのでトリガーは Power Apps トリガーとなります。
その後、指定した時刻まで待機する処理をしてあげれば実現できそうな気がします。

指定した時刻まで待機するにはスケジュールコネクタが使えそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183354/f7fda878-6fba-3281-a00d-85d50e7719ac.png)

延期期限アクションまたは、遅延アクションを用いれば後続のアクションを待機することができるので、指定した日時にそれ以降の処理を実行することができます。


# その他

今回は Twitter への投稿ですが、ツイートの投稿の部分を違う処理に変更すれば、SharePoint への指定時刻に一括データ登録のようなことも実現可能です。