OmniAICreator/Qiita-1.07M huggingface dataset:
大容量CSVを編集するためにPowerShellが使える

# はじめに

備忘録です。自分用メモといってよい。

# 前提とするCSV

160Mbくらいで300000行✕27列くらいのCSV
ちなみに、SuperPhoenixとかいう麻雀AIの牌譜分析に作ってたらこうなった。

[マイクロソフトが麻雀AIを開発　「天鳳十段の実力」 \- ITmedia NEWS](https://www.itmedia.co.jp/news/articles/1908/29/news125.html)

[Super Phoenixの論文 - Suphx: Mastering Mahjong with Deep
Reinforcement Learning](https://arxiv.org/pdf/2003.13590.pdf)

# ところでCSVを編集するソフトウェアって何使う

蛇足。
どれ使ってもいいけど、大体の感想をば。

| 使うもの | メリット | デメリット |
|:-:|:-:|:-:|
| Excel | 見やすい！編集しやすい！ | クソ重 |
| Googleスプレッドシート | どこでも使える！ | 行列合わせて500000セル制限 |
| テキストエディタ | ベーシックなテキスト操作、比較的軽い | 見にくいし計算できない |
| Python | 色々計算できる。真面目に作るならこれ | デフォルトのcsvパッケージがわかりにくい、環境が必要、内容も閲覧しにくい |
| R | 一回読み込めばすごく軽い、グラフ出すのとかすっごい楽、ちょっとした編集もすごい楽 | ちょろっとしたスクリプト組むと意外にも重く使い物にならない |
| Powershell | Windowsがあればどこでも、スクリプトできる、比較的軽い | 見やすくはない。だれもお前を愛さない |

# 本題：PowerShellでCSVを使う

## CSVを読み込む

utf8形式でカンマ区切りのCSVを読み込む。とりあえず以下のコマンドを打っておけば、$csvという変数内にPSObject形式で読み込まれる

```PowerShell
$csv = Import-CSV .\hogehoge.csv -Delimiter "," -Encoding utf8
```

### パラメータ
- -Delimiter 
  - 区切り文字。`tとしたりするとタブ区切りも読める
- -Encoding
  - 文字コード。PowerShellで一番キレる。もともとのCSVファイルをutf8にしておくことをおすすめする。

### かかる時間

たとえば、150MBくらいのファイルをImportしてみたら、6.5秒程度で読み込むことができる。

```PowerShell

PS D:\Work\suphx\rspace> Get-ChildItem .\allout_utf8.csv

    Directory: D:\Work\suphx\rspace

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2020/12/07    21:55      163871122 allout_utf8.csv
PS D:\Work\suphx\rspace> Measure-Command { Import-Csv .\allout_utf8.csv -Delimiter ',' -Encoding utf8 }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 6
Milliseconds      : 555
Ticks             : 65554450
TotalDays         : 7.58732060185185E-05
TotalHours        : 0.00182095694444444
TotalMinutes      : 0.109257416666667
TotalSeconds      : 6.555445
TotalMilliseconds : 6555.445

```

## CSVをファイルに出力する

PSObject形式の配列をパイプでExport-CSVに投げてやるとファイル出力できる。

```PowerShell
$csv | Export-CSV .\output.csv -Delimiter "," -Encoding utf8
```

### パラメータ
- -Delimiter 
  - 区切り文字。`tとしたりするとタブ区切りにもできる
- -Encoding
  - 文字コード。PowerShellで一番キレる。utf8はutf8だがなぜかBOM付きutf8。キレそう。

## CSV（PSObject）の行の値を表示する

なお、ここからは、もうPSObjectの話なので、正直CSVは関係ない。
$csvは配列で入っているので例えば0を指定すると１行目の値が出力できる。

```PowerShell
$csv[0]
```
## CSV（PSObject）の値を変える

直接ぶっこめば良い。PSObjectなのだが、Import-CSVで読み込むとヘッダーがプロパティに当たる。

```PowerShell
$csv[0].列名 = "変更後"
```

## なんか色々計算して列として追加する

たとえば、A列とB列をかけたものを列名Xとして追加する。気をつけたいのは、基本的にStringで読み込まれるので数値計算するときは型変換してあげたほうが良い。
下のコマンドで直接$csvの変数のPSObjectにプロパティを加えることができる。

```PowerShell
$csv | % { 
    $tmp = [int]($_.A列) * [int]($_.B列)
    $_ | Add-Member -Type NoteProperty -Name "X列" -Value $tmp
}
```

# 結論

PowerShellは意外とデータ編集には使えるよ、って話。Windows環境なら環境構築せずとも数分くらいで大容量CSVを編集できるので、楽だよねという感想です。

でも、大容量CSV、というか、大容量テキストファイルを扱うのに、一番取り回しがいいのは、EmEditorなのでぜひ。

[EmEditor \(テキストエディタ\) – Windows用テキストエディター](https://jp.emeditor.com/)
ArchUnit 実践：StringUtil(s) 多すぎ問題に負けない

```
// 実行環境
* AdoptOpenJDK 11.0.9.1+1
* JUnit 5.7.0
* ArchUnit 0.14.1
```

## アーキテクチャテストのモチベーション

フレームワークや複数のライブラリを導入すると、それぞれで独自に実装された StringUtil(s) クラスがコード補完に複数でてきてどれを使えばいいのか困る、ということはよくあります。

開発者によって使用する StringUtil(s) クラスが違ってくると、一貫性のない、想定外の依存を含んだコードになってしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899/49f694b5-e1b1-d74e-513a-81a2ef1de02b.png)

例えば、「StringUtil(s) は `org.apache.commons.lang3.StringUtils` を使う」ということがプロジェクトのガイドラインとして決まっているのであれば、それをアーキテクチャテストによって担保できます。

## アーキテクチャテストの実装

```java
package com.example;
　
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import org.junit.jupiter.api.Test;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;

class ArchitectureTest {

    // 検査対象のクラス
    private static final JavaClasses CLASSES =
            new ClassFileImporter()
                    .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
                    .importPackages("com.example");

    @Test
    void StringUtilsはApacheCommonsLang3のStringUtilsのみ使用可能() {
        classes()
            .should()
            .onlyDependOnClassesThat(new DescribedPredicate<>("org.apache.commons.lang3 の StringUtils クラス") {
                /**
                 * @param clazz 依存先のクラス
                 * @return 依存先のクラスが org.apache.commons.lang3.StringUtils である場合、true
                 */
                @Override
                public boolean apply(final JavaClass clazz) {
                    boolean isStringUtil = clazz.getSimpleName().endsWith("StringUtils")
                        || clazz.getSimpleName().endsWith("StringUtil");

                    if (! isStringUtil) {
                        // StringUtil(s) でないクラスは、このテストでの依存チェック対象外
                        return true;
                    }

                    return clazz.getPackageName().equals("org.apache.commons.lang3");
                }
            })
            .check(CLASSES);
    }
}
```
.dockerignoreでイメージを軽量化した

## 背景
最近Dockerを学んでみて、やっと自分のポートフォリオにも導入ができそうだったので試しにポートフォリオのRailsイメージをビルドしてみるとめちゃくちゃ遅いので原因を調べてみた。

## 結論
.dockerignoreで余計なものをビルドするのを防いだら多少早くなった。

## 解決法
Dockerfileと同じディレクトリに.dockerignoreを配置する。自分の場合はCarrierwaveのローカルでテストしてアップロードした画像ファイルや音楽ファイルが大量に残っていたのでこのディレクトリを追加した。

```:.dockerignore
/public/uploads
```

改めてbuildする。

```:console
docker build -t rails_app .
```

docker image lsなどで容量確認してみるとimageの容量が半分になった。build時間もある程度改善された。
Dockerの仕組みを超ざっくりまとめ

## 概要（簡単にまとめ）
- DockerはDocker Engineのある環境で動く
- 実行環境をコンテナという単位で管理し、それぞれは隔離されている。
- コンテナはイメージというものから作成されて、そのイメージとやらは[DockerHub](https://hub.docker.com/)というリポジトリから取得できる
- コンテナにはOSなどがなくオーバーヘッドが少ない（VirtualBoxなんかは仮想化された環境ごとにOSが存在する）

## 疑問
```
dockerイメージにはLinuxディストリビューションが配布されている
= dockerのコンテナ上にはOSができる場合もあるのではないか。

別の言い方をすれば、ホストOSと違うOSベースのコンテナイメージが
何故Docker上で動くのか
```


## 答え
```
Linuxカーネルには互換性があり、その範囲内であれば
異なるカーネル上でも同じ実装でアプリケーションは動作できるから
```

- コンテナはホストOSのカーネルに対して、ABIというインターフェースを介してシステムコールを行っている
- Linux系と呼ばれるOS群にはRHEL、CentOS、Ubuntuとかたくさんあるけど、これらは基本的に共通のカーネルを使用している。
- Linuxカーネルにもバージョンが存在するが、古いバージョンであってもABIに対しては同じ仕様で呼び出すことができる。

=> つまり、コンテナ内に存在しているのはアプリケーションの実行に必要なライブラリや特定のディストリビューション上でのファイルシステムである、ということが言える。


## あれ、でもそれってLinux OSだった場合の話でWindows/Macの場合は話が違うよね？

```
【答え】 Docker for Macなどのソフトをインストールして代替。 
```
- Macに関してはHyperkitという仮想化ツールでdockerホストとなるVMを作ることで対応しているらしい。つまり、MacOSにABIを被せているわけではなく、LinuxOSを別個に立てて、そこでよしなにやってくれるらしい
- windowsの細かいことは分からないです。ただ、Macと同様の仕組みがあるらしい。

## 参考
https://qiita.com/kirikunix/items/33414240b4cacee362da
https://thinkit.co.jp/article/17301

## 最後に
間違ったこと書いてたらツッコミくれると助かります。
LINEWORKSとヒアラブルデバイスの連携で起こった問題とその対処

## はじめに
LINEWORKSとZeenyを使って音声メッセージのやりとりができる機能を開発しました。
今回はうまくやりとりができない問題が発生してしまったので紹介します。

## Zeenyって何？
Zeeny[ジーニー]は、人々をスクリーンから解放する株式会社ネインによって運営されている、ヒアラブルデバイスを中心とした、ウェアラブルプロダクトブランドです。

ZeenyヒアラブルデバイスとZeenyAppによって、スマートフォンの受け取るあらゆる通知を音声で伝えます。

## LINEWORKSとの連携

連携については前回の投稿で。
[LINEWORKSと連携して音声メッセージのやりとりをする - Qiita](https://qiita.com/miyataNain/items/1b03ae0f17182feb962e)

メールやLINEなど通常メッセージの読み上げにはTTSを使用していますが、こちらは投稿された音声をそのまま通知に利用します。

Zeenyデバイスのボタン操作で音声が録音され、その音声をサーバーに送信。サーバー側は音声をテキスト化し、LINEWORKSにそのテキストを投稿します。受け取る側のZeenyはLINEWORKSからの通知を受け取り、投稿された音声を再生します。
デスクトップAppやWebからも確認できるようにボイス再生ボタンを用意しています。

ボイスメッセージよりも少しだけ良いユーザー体験を提供します。
<img width="400" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/944240/d3f3b8b0-126c-7ae6-af34-54f1cc890571.png">

## 問題発生

音声再生の仕組みとしては、サーバーがメッセージ投稿と同時にFirebase Cloud Messaging(FCM)で音声の保存場所をZeenyに伝えます。受け取ったZeenyはその音声を取得して再生します。

バックグラウンドでこの音声のやりとりを続けると、受け取れないメッセージが多発してしまうという問題が発生しました。

バックグラウンドで受け取れる回数に制限がある！
[Pushing Background Updates to Your App](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app)

>Important
The system treats background notifications as low priority: you can use them to refresh your app’s content, but the system doesn’t guarantee their delivery. In addition, the system may throttle the delivery of background notifications if the total number becomes excessive. The number of background notifications allowed by the system depends on current conditions, but don’t try to send more than two or three per hour.



できるだけリアルタイムに会話のキャッチボールをしたい本サービスで回数制限は大問題です。
泣く泣くLINEWORKSへの投稿に音声URLを埋め込む形に修正。メッセージを受けた際にそのURLにアクセスすることで、制限なく音声を再生することができるようになりました！（通知の受け取りは、Zeeny独自の仕様で実現しています！）

## URLが長すぎ問題

URLをそのまま投稿するとかなり長くなって肝心のメッセージがとても見づらくなってしまいました。

これを解決するために、Firebase Dynamic LinksのURL短縮機能を利用して１行に収まるようにしました。この手法についてはたくさん記事があると思いますので割愛します。

最終的な完成形はこちら。

<img width="400" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/944240/b7691e68-e716-43be-342c-536d2c91d7e3.png">

それでも視認性はあまり良くないので改善したい。。

実はこれ以外に、iOS12.4からバックグラウンドで音声を録音できないという問題も発生したのですが、こちらについてはまたの機会に。

## まとめ
業務用サービスとして展開している本サービス、介護士の方が手にボールペンで書くメモ、営業さんが商談した際に残したいちょっとした自分用のメモ、そんなことを音声で解決する様な用途にも最近お声がけいただくことが増えてきました。

リモートワークが増えた現在、テキストだけのやりとりではなかなかうまく伝わらない問題を、少しでも改善する一助となればと願い、これからも開発を続けていきたいと思います。

## 参考
[https://qiita.com/chocoyama/items/56cd3ac2daaf69dffa0f](https://qiita.com/chocoyama/items/56cd3ac2daaf69dffa0f)
第8回

\![Ubuntu-20.04.1](<https://img.shields.io/badge/Ubuntu-20.04.1-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 

これは講義用のまとめサイトです。見た人は是非LGTMを押しといてください。


# やったこと

-   rake
-   command\_line


# rake

rakeとは、makeコマンドのruby板である<br>makeコマンドとは、MakeFileに記述したコマンドを一挙に実行するコマンド<br>rakeも同様にRakeFileにコマンドを書いておけばいちいちいくつもコマンドを打たなくてもいいというものらしい<br>つまり、gitにアップロードするときに毎回「git pull～」「git add～」「git commit～」「git push～」と打ってたのを一発で実行できるようにしたりできる。こう言われると確かに嬉しい気がする


## とりあえずコピペ

```ruby
task :default do
  system 'rake -T'
  exit
end

desc 'hello NAME'
task :hello do
  name = ARGV[1]
  puts "Hello #{name}!"
  exit
end
```

で、

```ruby
>rake hello World
>Hello Wordl
```

となる。これはつまりRakefileの中の「hello」というtaskを実行したことになる。<br>なお、「desc 'hello NAME'」のdescって何？机？と思って調べたら、descはdescription、つまり単にtaskの説明を書いてるものらしく、なくてもよかった<br>(12/16追記)<br>先生からのコメントによると、descを書いておくことでhelpなどで説明が出るようになるので(暗黙的に)なくてはならない物だそうです。


## gitの操作を一発でできるようにしよう

system callで実用的なtaskを作っておこう

```ruby
desc 'git push'
task :push do
  p comm = "git pull origin main"
  system comm
  p comm = "git add -A"
  system comm
  p comm = "git commit -m \'commit\'"
  system comm
  p comm = "git push origin main"
  system comm
  exit
end
```

これはgitにアップロードする際の一連のコマンドをまとめたtaskである。これをRakefileに書き込んでおけば、さっきと同じ要領で

```ruby
> rake push
```

とするだけでなんとgitにアップロードできちゃうのです。こりゃだいぶ楽になった<br>しかも変数も使えるらしく、例えばコメントのところは毎回違う内容を入れたいならARGV[0]で入力を受け付けてやれば実現できる


# command\_line

上ではsystem関数を呼び出して無事gitのアップロードが楽になりましたと言いたいところだが・・・このやり方はsystemで外部のコマンドを呼び出してるので高速ではないらしい<br>そこで組み込み関数を学んでプログラムを高速化することを考える


## 標準出力を得たい

目標：組み込み関数を使ってほかの人のREADME.orgの情報を得てデータを成形し、標準出力を取り出す<br>その前に

```ruby
> gem install command_line
```

でcommand\_lineというgemをインストールしておく。これは標準出力を取り出すためのもので、ruby2.4以上じゃないと使えないらしいけど、一応確認すると2.7.1を使ってるので無問題<br>とりあえず最初の5人分テストで取り出してみることにする

```ruby
require 'command_line/global'
desc 'make list'
task :mk_list do
  targets = "../**/README.org"
# systemを使った場合
  # system 'ls -1 {#targets}'
  # p targets
# command_lineを使った場合
  Dir.glob(targets)[0..4].each do |file|
　　p file
　　res = command_line "grep qiita_id #{file}"
  　p res.stdout
  end
  exit
end
```

targetsに拾ってきた各人のREADME.orgへのパスが入る。<br>組み込み関数のDir.globはsystem関数でlsで呼び出してた動作を代替している。ここではとりあえず0番目から4番目を呼び出してる<br>取得した各ファイルについて、eachでファイル名、そして各ファイル内にあるqiita\_idを出力させている<br>結果

```ruby
"../0922tooy/README.org"
"#+qiita_id: 0922tooy\n"
"../acoe5781/README.org"
"#+qiita_id: Acoe\n"
"../adchello/README.org"
"#+qiita_id: adchello\n"
"../batamon-427/README.org"
"#+qiita_id: batamon-427\n"
"../createiveIKEP/README.org"
"#+qiita_id: creativeIKEP\n"
```

はい、5人分のqiita\_idが取得できましたね。まあsystemで全員分のREADME.org呼び出す操作を実行したところで、この程度の人数なら見た目では別に差はないんですが


# 参考記事

[チャート式ruby-appendix-IV(rake)](<https://qiita.com/daddygongon/items/1c2d6d2895333ccf5e62>)  [Rakeで自動化&Export](<https://qiita.com/evendemiaire/items/4dbcfb1819fc23ac8ba9>)



------
 - **source** ~/MasahiroOba/grad_members_20f/members/MasahiroOba/chapter8.org
ダミーデータをブラウザ上で作ってCSV, JSON, SQLで吐き出せるサイトを作った

# あらまし

個人開発も何回か続けていると **得意ネタ** ができてくるみたいです。

自分の場合は

- インプット部分で入力されたデータを、アウトプット部分に動的に吐き出す
- インプットとアウトプットは一画面を分割した感じ（Qiitaの投稿欄みたいな）

という感じのサイトが得意な気がします。

今回は画面上部のボタンでテーブルを作り、画面下部のテキストエリアにCSV, JSON, SQLとして吐き出されるというWebアプリを作りました。

# できたもの

[Dummy-Table-Generator](https://mi-ki-ri.github.io/dummy-table-generator/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92027/c2fd5cee-712d-ed38-3fca-cc7388e9c5c8.png)

*Increment* とか *Name* とかあるのはデータのタイプです。

Incrementだったら行ごとに1追加された数値、

Nameだったらランダムな名前を表示するようになります。

*Change Row Count* することでデータ部分を増減できます。

限界は999行です。

~~今現在、列を増やすことはできても減らせません…。~~

# 開発過程

## フロントエンド:  Nuxt.js

慣れてるのでNuxt.jsを使用しました。

**pages** の中身はindex.vue(とReadme)だけ。

indexでは上部に **MyTable** コンポーネント、下部に **Csv**, **Json**, **Sql** コンポーネントを配置しました。

Csv, Json, Sqlは変数によってスイッチします。

変数はセレクトボックスによって変わります。

ダミーデータは後述の方法で作ったjsonファイルをnuxtの **$http** モジュールで読みに行きます。

この処理はindex.vueの中で行うので、Csvその他のコンポーネントにデータを渡す形になります。

この場合 **props** を使います。

```xml
<csv v-if="currentMode == 'CSV'" :obj="inputObj" :keys="keysArr" />
```

こんな感じで変数をバインドしてやって、コンポーネント側で

``` js
props: ["obj", "keys"],
```

こう指定することで `this.obj` のように取り出せます。

また、MyTable コンポーネントからは列追加や行追加など、index.vueに向かって親方向に値を届けたいときがありました。

こういうときは **$emit** を使います。

コンポーネント側で

```js
this.$emit('addRow', this.currentNumber)
```

こんな処理を書き、index側で

```xml
<my-table @addRow="hoge" />
```

のようにイベントを受け取ります。

**hoge** メソッドに引数を指定すれば値も渡せます。

そんなこんなでゴリゴリと処理を書いていき、フロントエンドはできました。

## バックエンド: ダミーデータがつまったjsonファイル

バックエンドはサーバーですらないjsonファイルです。

これをnuxtプロジェクトのpublicフォルダの中に置きました。

jsonを作るのに **python** パッケージの [Faker](https://faker.readthedocs.io/en/stable/) を使わせてもらいました。

Pythonスクリプトがちょっと今手元に無いのですが、

単純に10000回くらいループしつつダミーの電話番号やダミーのメールアドレスを配列に叩き込んでいき、

最後にすべてをまとめたオブジェクトをJSONとして書き出しました。

ただ、JSONがユニコードでエスケープされていて、ちょうどいいタイミングで戻すのに手こずりました。

## デプロイ: Github-pages

デプロイ先はGithubpagesですが、ここでもやや手こずりました。

404が表示されて、デプロイの設定が何か違うのかと勘違いしていたけれど、

実際のところはjsonファイルがうまく読めてなかっただけでした。

面倒だったので **URLをハードコーディング** して済ましました。

## まとめ

慣れているつもりのNuxtでもちょっとしたことでエラーになったり詰まったりするので、

やはり手を動かさないと分からないことというのはあるなと思います。

Let's 個人開発！
Githubが自動マージできるようになるらしいけど、もっと前からやってたが？

![スクリーンショット 2020-12-10 20.31.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411927/2e761ce1-7bfb-d7ad-6684-a42866705ecb.png)
# はじめに

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Pull Requestの自動マージが可能となります。有効化するとレビュー、ビルドなどのチェックが成功していれば、そのPull Requestが自動でマージされます。これで次のタスクに取り掛かりやすくなりますね。数週間以内に展開予定ですので乞うご期待。 <a href="https://twitter.com/hashtag/GitHubUniverse?src=hash&amp;ref_src=twsrc%5Etfw">#GitHubUniverse</a></p>&mdash; GitHub Japan (@GitHubJapan) <a href="https://twitter.com/GitHubJapan/status/1336526627396718593?ref_src=twsrc%5Etfw">December 9, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

GithubがPRの自動マージができるようになると発表しました！
ステータスチェックがオールグリーンなら自動でマージされるようです。

↓ステータスチェック
![スクリーンショット 2020-12-10 20.31.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411927/2f2f42c0-200e-68e2-8386-73d7626c0f91.png)

僕もっと前からやってましたが！？

ということでどういう風に再現しているか解説していきます。

# 環境
### コード管理
Github

### CI環境
Github Actions

# 解説
解説というほど大それたものでもないです。
ApproveされたらGithub ActionsからGithub API叩くだけです。

Approveされたらというトリガーはないので、レビューされたらというトリガーというトリガーを使っていきます。
https://docs.github.com/ja/free-pro-team@latest/actions/reference/events-that-trigger-workflows#pull_request_review

このトリガーで走ったGithub Actionsはpull_request_reviewのWebhookが使えます。

https://docs.github.com/ja/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review

レビューされたというトリガーかつstateがapproveの場合のみ走るCIを作ればいいだけです！

あとはGithubのAPIを叩くだけです。
https://developer.github.com/v3/pulls/#merge-a-pull-request


```yaml
name: Auto Merge

on:
  pull_request_review:
    types: [ submitted ]

jobs:
  merge:
    if: ${{ github.event.review.state == 'approved' }}
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Auto Merge
        run: |
          curl \
          -X PUT \
          -H "Content-Type: application/json" \
          -d '{"sha": "${{ github.event.pull_request.head.sha }}", "merged": "true", "message": "Pull Request successfully merged"}' \
          "${{ github.event.pull_request.url }}/merge"
```

これだけでレビューでApproveされたら勝手にマージされるようになります。

# まとめ
以上！！
Githubより先を行きましょう！！
WSL最高

ども。
Hiro_Matsunoです。
また連チャンで書いてますねｗ。
 [WSL Advent Calendar 2020](https://qiita.com/advent-calendar/2020/wsl "WSL Advent Calendar 2020")の１０日目です。
明日は３連載というシゴキが待ってます。

#WSLっていいの
正直言いましょう。
こぞって企業さんが入れてほしいのがこのWSLです。
WSLによってセキュリティは上がるしLinuxサブシステムも入るのでデバックするのにも便利だし。
あとはディストリビューションもいっぱいありますし。
開発者にとってはウハウハものでよだれ物です。
ちなみにbashもLinux流儀に変わるのでいいと思いますよ。
Linuxはおなじみの物が手に入りますしね。
俺はもちろんUbuntuですが。
#失敗のリスクが少ない
これは言えてるでしょうね。
Windowsの中にSubsystemとしてLinuxが入ってるんですから。
VMなみにいじりたい放題です。
VM派だった自分は速攻で乗り換えましたが。
一つだけ困ったことがMySQL入んねぇ。
これだけかな。
使いたい放題に使えるのでいいと思います。
DeepLearningをやりたい人は是非WSL入れてください。
Windowsではない凄みがあります。
Macもこうなってくれるといいんだけど。
#ディレクトリはWindowsで見れる
これが一番のポイントですね。
Web開発してるときにXamppとか使ってる人堂々と乗り換えましょう。
Linuxはやっぱ動きいいです。
WSL環境はWindowsと接続できるので非常に便利です。
Explorerで見れるというのが一番のポイントでこれであなたはVMいらずです。
#AWSには負けちゃうね
正直言うとAWSには負けてしまいます。
向こうはそれ専用のものが入ってますから。
WSLは所詮Windowsの中でWeb開発やAndroidなどの開発目的なので結局の所強みといえばXamppいらずになるってところです。
Xamppは一々一つ一つ起動を確認しながらの作業になりますのでめんどいです。
WSLならwslコマンド一発起動なので結構楽になると思いませんか。
AWSは処理スピードは高いですが回線という問題がぶら下がってるので早い回線のところは無償枠の範囲外なんですよね。
開発するならWSLです。
#Gitクライアントに使わないで
正直言いますがWSLはWindowsサブシステムに関するディストリビューションでGitクライアント代わりに使えるなんて書いてた人いますが正直その使い方勧めません。
あとで地獄を見ますよ。
WSLはかんたんに壊せるということ忘れないでください。
#壊すことを恐れるな
自分も何回か壊しました。
何回も入れ直せるという所が良いところだと思います。
VMだと労力がいるので疲れました。
カーネルですがInsiderPreviewユーザはwsl --updateでできるみたいです。
前に一回やってみたら見事にカーネルバージョンが上がってくれました。
色々遊び尽くせるのでいいと思います。
といいながら今日はMacOSで書いているというおまけ付きですが。

WSLはLinuxを始めてみたい人にはもってこいだと思いますので一回環境壊す勢いで使ってみることをおすすめしておきたいと思います。

今日はありがとうございました。
wp_head();とwp_footer();がないとWordPressテーマは機能しない

自作したWordPressテーマをサイトにアップデートしても

wp_head();とwp_footer();を決まったところに記載していないと
テーマは動かないです。

##wp_head(); 記載場所

まず、これは
`</head>`の直前に入れる。


```php:index.php
<!DOCTYPE html>
<html lang="ja">
<head>
 <meta charset="utf-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <title>サイトタイトル</title>
 <?php wp_head(); ?>
</head>
```

##wp_footer(); 記載場所

これは
`</body>`の直前に入れる。


```php:index.php
<?php wp_footer(); ?>
</body>
</html>
```

##まとめ

最初のうちは、なんでWordPressが動かないのか謎な時ありますが
こういう、決まりの物が抜けてたりします。

以上！！
salesforceのオブジェクト内のデータをsfdxコマンドですべて削除したい

## コマンド

`sfdx`コマンドを用いて以下コマンドで消去できます。
これでいちいちログインせずとも、カスタムオブジェクトの削除が可能になります。

```bash
sfdx force:data:soql:query -u ALIAS -q "SELECT id from CustomObject__c" -r csv > result.csv
sfdx force:data:bulk:delete -u ALIAS -s CustomObject__c -f ./result.csv
rm ./result.csv
```

`Git Bash`などで叩く場合は、`;`でつなげてあげればワンライナーで実行できます。

## 解説

 - `ALIAS`の部分は組織へのエイリアスを入力してください。
 - `CustomObject__c`の部分は削除したいオブジェクトのAPI名を入力してください。

`sfdx force:data:soql:query -u ALIAS -q "SELECT id from CustomObject__c" -r csv > result.csv`
これでカスタムオブジェクトのIDをcsv形式で取得します。

`sfdx force:data:bulk:delete -u ALIAS -s CustomObject__c -f ./result.csv`
これでcsv内のデータを削除します。

`rm ./result.csv`
これでcsvを削除してお掃除します。
マンガでわかる梯子外しミニアンチパターン

![8DA7018F-70AE-40A8-8861-7F01516BC8A1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/0271f5b9-ef03-6c1e-dbd0-1a9b17105f1d.png)
http://wiki.c2.com/?DeadEnd

英語ではデッドエンド、袋小路に入って行き場をなくすという意味の名前が割り当てられたパターンです。突然現れた行き止まりのために、進むことも戻ることもできなくなる状況を表しています。

梯子外しの原因はベンダー側にあるので、いくら自分で気をつけていても、完全に回避することはできません。今は企業経営に左右されるプロプラエタリ製品に代わって、オープンソースが多用されるようになり、企業の都合に影響されるケースは減りましたが、それでも、OSS パッケージのメンテナンスが継続されないケースはよくあります。数多くの個人の努力に依存するようになったぶん、逆に不安定になったかもしれません。また、現在もなお大手ベンダーが業界標準への影響力や、クラウドプラットフォームのサービスラインナップを変える権限を握っているのも事実です。

梯子外しを完全に避けることはできませんが、できるだけ被弾率を下げる立ち振る舞いや、被弾した場合でも代替技術に切り替えるための工数バッファを確保しておくことは可能です。行き詰まらないために、リスクコントロールを意識したいですね。
【Swift】Firestoreにデータを追加・取得


##データの書き込み
コレクションのフィールドにはMessages、ドキュメントは固有ID、
ドキュメントフィールドにメッセージデータを入れるとします。

```Swift
import FirebaseFirestore
...

Firestore.firestore().collection("Messages").document().setData([
            "date": Date(),
            "senderId": "testId",
            "text": "testText",
            "userName": "testName"
        ])
```
collection("Messages")で以下の画像のようにコレクション名が生成され、
document()のように()内を指定しない場合は固有IDが振られます。
最後にsetDataでメッセージのデータをmap(辞書)で書き込んでいます。

##反映されたデータ


![スクリーンショット 2020-12-10 20.29.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585922/1b10ff7b-acab-d031-38e8-6712605d806b.png)

##データの取得

Firestoreから取得したデータは、扱いやすいように
構造体を型にしてアプリ側で処理をするとします。

```Swift
struct FirestoreData {
    var date: Date?
    var senderId: String?
    var text: String?
    var userName: String?
}

```


```Swift
import FirebaseFirestore
...
...

Firestore.firestore().collection("Messages").getDocuments(completion: {
      
      (document, error) in
            if error != nil {
                print("ChatViewController:Line(\(#line)):error:\(error!)")
            } else {
                if let document = document {
                    for i in 0..<document.count {
                        var storeData = FirestoreData()
                        storeData.date = (document.documents[i].get("date")! as! Timestamp).dateValue()
                        storeData.senderId = document.documents[i].get("senderId")! as? String
                        storeData.text = document.documents[i].get("text")! as? String
                        storeData.userName = document.documents[i].get("userName")! as? String
                        self.firestoreData.append(storeData)
                        print(self.firestoreData)
                    }
                }
            }
        })
```

Firestore.firestore().collection("Messages").getDocumentsで
Messagesコレクション配下のドキュメントとそのデータを全て取得します。

ドキュメントは複数返ってくるため、for in文で処理をします。
document.documents[インデックス番号]でドキュメント内のデータにアクセスし、
ドキュメント配下のデータには document.documents[インデックス番号].get()でアクセスします。

get()内にキー名を指定することで、ドキュメント配下のデータを取得することができます。
型はこちら側で明示する必要があります。

##注意事項

Firestoreの日付情報は、Date()型で渡してもTimestamp型で返ってくるため、
Timestampにキャストして .dateValue()でDate型に変換する必要があります。
Nimでファイルの権限を付与、取得する

## 権限を付与

FilePermissionはenumなので、その中の付与したい権限をsetとして定義します。

```Nim
# setFilePermissionsはosにあります
import os

var perms: set[FilePermission]
perms = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead, fpOthersExec, fpOthersRead}

# ファイルに権限を付与
setFilePermissions(DATA_TASK_DIR, perms)
```

## 権限を取得
```
getFilePermission()
```

実際にsetFilePermissionsを行っているソースが見つからず、少しハマったので参考になれば。
Ruby で解く AtCoder Educational DP Contest E ナップサック問題

# はじめに
*[AtCoder Problems](https://kenkoooo.com/atcoder/#/)* の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。
# 今回のお題
*[AtCoder Educational DP Contest - E - Knapsack 2](https://atcoder.jp/contests/dp/tasks/dp_e)*
Difficulty: ---

今回のテーマ、動的計画法

前回の投稿 [Ruby で解く AtCoder Educational DP Contest D ナップサック問題](https://qiita.com/superrino130/items/b0564afdd103ef0f6a12) と同じ感じなのですが、同じコードですと`RE`(Runtime Error) になりますので、工夫が必要です。
# 前回のコード - RE
```ruby.rb
n, mw = gets.split.map(&:to_i)
p = n.times.map { gets.split.map(&:to_i) }
dp = Array.new(mw + 1, 0)
p.each do |w, v|
  dp_tmp = dp.dup
  w.upto(mw) do |i|
    dp_tmp[i] = dp[i - w] + v if dp[i] < dp[i - w] + v
  end
  dp = dp_tmp
end
puts dp[mw]
```
```runtime.error
array size too big (ArgumentError)
```
# Array コピー
```ruby.rb
n, mw = gets.split.map(&:to_i)
wv = n.times.map { gets.split.map(&:to_i) }
dp = Array.new(wv.map { _2 }.sum + 1, 10**10)
dp[0] = 0
wv.sort.each do |w, v|
  dp_tmp = dp.dup
  v.upto(dp.size) do |i|
    next if dp[i - v] > mw
    dp_tmp[i] = dp[i - v] + w if dp[i] > dp[i - v] + w
  end
  dp = dp_tmp
end
vmax = 0
dp.each_with_index do |w, v|
  vmax = v if vmax < v && w <= mw
end
puts vmax
```
```dp.rb
    dp_tmp[i] = dp[i - w] + v if dp[i] < dp[i - w] + v # 前回
    dp_tmp[i] = dp[i - v] + w if dp[i] > dp[i - v] + w # 今回
```
前回と今回で、`w`と`v`を入れ替えていることが分かります。
この工夫で、ArgumentError を回避しています。

```init.rb
dp = Array.new(mw + 1, 0) # 前回
dp = Array.new(wv.map { _2 }.sum + 1, 10**10) # 今回
dp[0] = 0
```
`w`と`v`を入れ替えるために、前回`0`で初期化していたところを十分大きな数に変更しています。
# Array 後ろから
```ruby.rb
n, mw = gets.split.map(&:to_i)
wv = n.times.map { gets.split.map(&:to_i) }
dp = Array.new(wv.map { _2 }.sum + 1, 10**10)
dp[0] = 0
wv.sort.each do |w, v|
  dp.size.downto(v) do |i|
    next if dp[i - v] > mw
    dp[i] = dp[i - v] + w if dp[i] > dp[i - v] + w
  end
end
vmax = 0
dp.each_with_index do |w, v|
  vmax = v if vmax < v && w <= mw
end
puts vmax
```
```inf.rb
dp = Array.new(wv.map { _2 }.sum + 1, Float::INFINITY)
dp = Array.new(wv.map { _2 }.sum + 1, 10**10)
```
`Ruby`で大きな数といえば`Float::INFINITY`ですが、Float::INFINITY は浮動小数点数であるため、整数と浮動小数点数の比較にコストがかかるため、10**10 のような大きな整数を使用しています。

この高速化は、[Ruby競プロTips(基本・罠・高速化108 2.7x2.7)](https://zenn.dev/universato/articles/20201210-z-ruby) を参照しました。
# Hash（追記）
```rb:Hash
n, w = gets.split.map(&:to_i)
wv = Array.new(n){ [0, 0] }
n.times do |i|
  wv[i][0], wv[i][1] = gets.split.map(&:to_i)
end
dp = Hash.new(1000000001)
dp[0] = 0
wv.sort_by{ |wv| [wv[1], wv[0]] }.each do |wv|
  dp.keys.sort.reverse.each do |k|
    if dp[k + wv[1]] > dp[k] + wv[0] && dp[k] + wv[0] <= w
      dp[k + wv[1]] = dp[k] + wv[0]
    end
  end
end
puts dp.select{ |_, v| v <= w }.sort_by{ |k, v| [-k, v]}[0][0]
```

||Array コピー|Array 後ろから|Array コピー(INFINITY)|Array 後ろから(INFINITY)|Hash|
|:--:|:--:|:--:|:--:|:--:|:--:|
|コード長 (Byte)|406|370|415|379|432|
|実行時間 (ms)|581|528|710|680|584|
|メモリ (KB)|74712|15032|74768|15104|60176|

上記高速化で`150ms`ほど早くなっています。
# まとめ
+ D - Knapsack 2 を解いた
+ @universato さんありがとうございました
+ Ruby に詳しくなった
【AWS】基礎的Webアプリ基盤作ってみた

----------------------------------------
本記事は**[ Advent Calendar 2020 ](https://qiita.com/advent-calendar/2020/htc)**の2020/12/10分です。
※Advent Calendar 2020 へはHTCのチームメンバー5人で
毎日日替わりで投稿させていただいていますので、暇なときに覗いてください。
※HTCの紹介は[本イベント1日目の投稿](https://qiita.com/koooota/items/d5b8b036d3b6541a4f63)をご参照ください。

----------------------------------------
文系学部卒SIer新人の**かいと**です。

今回は、AWS初心者の私が**Webアプリのシステム基盤**を作成しましたので、
ネットワーク制御を中心に個人的な**備忘録**&
初心者でもこんなこと出来るのかという**気付き**を自分と同じような初心者に提供できればと思います！
※本記事は所属する会社の大先輩よりご教示いただいたものになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691623/0b0dbac7-1454-3186-031a-9e5763bf3b36.png)





# はじめに
そもそも、```基盤```とは？と思う方もいらっしゃると思います。
アプリの駆け出しエンジニアである私はそうでした。。。
ただ、この記事を見て、基盤に最低限必要なサービスと、利用用途を理解していただければ、概要は理解できると思います！
(今回は、詳細な各サービスの設定は省き、個人的にベストプラクティスが分からないネットワーク制御周りに関して書きます。)

それでは、作成した基盤のアーキテクチャ(↓)を念頭に置いていただき、説明に移りたいと思います！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691623/64e9a303-cd45-3764-d47d-868c1af036d4.png)
それでは、早速備忘録スタートです～

# 利用サービス/使用用途
- ***IAM***：ユーザーや、サービス間のロール権限
- ***VPC***：ネットワーク
    - **サブネット**：ネットワークの中のネットワーク的なもの。
    - **ルートテーブル**：EC2各インスタンスにひもずける。ルートテーブルには入力し許可したIPが通れる。
    - **インターネットゲートウェイ**：インターネットとの通信/外部アクセスを仲介する。これがアタッチされたルートテーブルに紐づいたサブネットはプライベートサブネットになる。
    - **セキュリティグループ**：インスタンス(EC2とか)単位でネットワークの制御をかける。プロトコル/IPなど選択した通信を許可する。
    - **ネットワークACL**：サブネット単位でネットワーク制御をかける。
- ***EC2***：Webサーバー
    - **Elastic IP**：グローバルIPアドレス。EC2はデフォルトでパブリックなIPしかつけることができないので、これを代用。
    - **ELB(ALB)**：ロードバランサー。下記ターゲットグループにアタッチされたEC2にアクセスを分散・冗長化を図る。
    - **ターゲットグループ**：ALBに使用。ターゲットとなるEC2群をまとめるもの。
    - **キーペア**：EC2の秘密鍵に使用。
- ***RDS***：データベース
    - **サブネットグループ**：DBの[Multi-AZ](https://aws.amazon.com/jp/rds/features/multi-az/)化に必要。要は可用性が上がる。（サブネットも別途作成する）
- ***Route53***：ドメイン取得
- ***ACM***：https通信用の証明書発行

#ネットワーク
ここでは、社内ネットワークからのアクセスのみを許可するという方針で作成したネットワーク制御を記します。
ただ、個人的に変更したい点もありますので、そちらも一緒に。。

####前提
上記で記したように、ネットワーク周りは下記で基本は構成されています。
**サブネット：ACL ｜ インスタンス：SG**

####現状
- ACL：適当に設定。
- SG：※すべてがインバウンドのみ制御
    - Webサーバ(EC2・プライマリ/セカンダリ)用：社内IP(http,ssh)、SG(RDS用、ALB用)
    - RDS用：SG(Webサーバ(EC2・プライマリ/セカンダリ)用)
    - ALB用：社内IP(https)

####こう変更したい
- ACL：SGとうまく住み分けをしたい。。。
- SG：
    - 開発者用：インバウンドに社内IP(http)のみ
    - Webサーバ(EC2・プライマリ/セカンダリ)用
        - インバウンド：SG(RDS用、ALB用、開発者用) ← ALBが障害出たときにユーザー(社員)にEIPで直アクセスで利用してもらえないのが怖い。ほかで担保すべきなのは明らかやけど。
        - アウトバウンド：SG（RDS用、ALB用）← ほかに影響が出そうで怖い。。
    - RDS用：SG(Webサーバ(EC2・プライマリ/セカンダリ)用)
    - ALB用：社内IP(https)

 

#詰まった部分
・[前回の記事](https://qiita.com/k-u2nomiya/items/5f64d4ede9434d3ed255)にてCICDを作成したお話をしましたが、CodeBuildにてテストを行う際に、プライベートサブネットに配置したRDSの参照がデフォルトではできませんでした。CodeBuildを同一VPC内のRDSと同じprivate subnetに置き、別のSGをアタッチ、WebサーバーにアタッチしてあるNatゲートウェイを上記private subnetのルートテーブルにアタッチすることで、テストができました。。。

参考資料：AWS公式CodeBuildのVPCサポートについてのドキュメント
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/vpc-support.html



# まとめ
・基盤を作成するにあたり、ドメイン取得やHTTP→HTTPS通信変更、Webサーバー負荷分散/冗長化、DBの冗長化など、
アプリのエンジニアとしてはあまり触れない部分を触れることができ、単純に楽しかったです。。。

・今後は、オンプレのアーキテクチャをそのままAWSにした感の強いこの構成を、よりクラウドチックでサーバレスな基盤、CI/CDに変更したいなと陰ながら思っております～
Python beautifulsoupを使ってweb scrapingするときにつまずいたこととか

## とりあえずコード

```python:get-html.py
import requests
from bs4 import BeautifulSoup
import urllib.request

response = requests.get('https://www.google.com/search?q=japanese&rlz=1C5CHFA_enJP834JP834&sxsrf=ALeKk02zyBpLsv9QCQOhAyZnOylqFDzv8Q:1606105228848&source=lnms&tbm=isch&sa=X&ved=2ahUKEwjaooyd6JftAhWB62EKHUMRCTEQ_AUoAXoECBEQAw&biw=1084&bih=634')

#response = requests.get('http://google.co.jp')
# print(response.text)
soup = BeautifulSoup(response.text, 'lxml')

titles = soup.find_all("img", limit=10)
ind = 0
for title in titles:
  url = title.get("src")
  if "https://" in url:
    save_name = "/Users/aspara/Desktop/pg/mask_face/japanese/face"+str(ind)+".jpg"
    tgt = urllib.request.urlopen(url).read()
    with open(save_name, mode='wb') as f:
      f.write(tgt)
    ind += 1
```

googleでjapaneseと検索して出てくる画像を上から10枚取ってきて保存する。

## 証明書が古いことにより出たエラー

実行する際に、以下のようなエラーが出た。

```
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
```

どうやら、通信の際に証明書なるものが必要で、サーバー側とクライアント側（自分側）で必要なようだが、自分側の証明書がだめらしい。というわけで調べてみると、このような記事が出てきたので同様に自分のpython3.9のフォルダからinstall Certificates.commandというファイルを見つけ、そこに記載の通り、

```
/Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9 -m pip install --upgrade pip
```

というコマンドを実行すると、

```
Collecting pip
  Downloading pip-20.2.4-py2.py3-none-any.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 2.9 MB/s
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 20.2.3
    Uninstalling pip-20.2.3:
      Successfully uninstalled pip-20.2.3
Successfully installed pip-20.2.4
```

の通り、証明書が最新のものにアップデートされた。
これで再度実行すると解決した。
認定 Platform デベロッパー資格の更新 (Winter '21)　⇒　Platform デベロッパーの Apex の新機能の学習

１．一時停止されたイベントを、一時停止中に公開されたイベントを一切失うことなく、停止した場所から再開するにはどうすればよいですか。
２．[すぐに公開] 動作が設定されているイベントについての正しい文はどれですか?
３．ロック解除済みパッケージを昇格してリリースするためのコードカバー率の最低要件はどれですか?
４．SELECT 句で WITH SECURITY_ENFORCED を使用するときに、句で参照されている項目へのアクセス権がユーザにない場合どうなりますか?
５．開発者が重要なイベントの発生時にカスタム通知を送信したいと考えています。この開発者が使用できるものはどれですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/e7186019-7c0e-16af-1b82-8c1698ea484f.png)
【PHP】 標準入力fgets(STDIN)の扱い方(初学者用)

「標準入力」は、プログラム言語を勉強し始めている段階の人だと出くわすことは少ないですが、競技プログラミングやアルゴリズム・プログラミングスキルテストなどでしばし使われます。
慣れると特に難しい概念ではありませんが、私は勉強をはじめたばかりの頃に少し手こずったので、普段使っている標準入力の扱い方をメモしました。

<h2>標準入力を使った例</h2>
標準入力の仕組みを使うと、外部から与えられた入力値を受け取ることができます。

例えば、echoを使って文字列を出力する際の違いです。

```.php
echo "こんにちは"; //出力:こんにちは
```



```.php
$word = "こんにちは";
echo $word;  //出力:こんにちは
```


```.php
$word = fgets(STDIN);
echo $word;  //出力:fgets(STDIN)の内容

//慣れたらまとめて書くと綺麗です。
echo fgets(STDIN); //出力:fgets(STDIN)の内容
```



プログラミングスキルテストなどは、自動でfgets(STDIN)に値が入れられてプログラムが動く仕組みになっているものもありますが、
LinuxなどのOSでphpファイルを出力する場合は、自分で任意の文字を入れて動かすことができます。

<h3>Linuxで出力する場合</h3>
例えば下記内容を書いたindex.phpファイルを作ります。

```index.php
echo fgets(STDIN);
```

それをLinuxで出力します。
phpファイルを出力したいときは、$(プロンプト)の後にphpを書いてからファイル名を指定します。

```
//Linux画面

$ php index.php

```

Enterキーを押すと出力が開始されますが、
fgets(STDIN)を使っている場合は、
fgets(STDIN)に入れる値を自分で入力するまでプログラムは動きません。

```
//Linux画面

例1
$ php index.php
おはよう //任意の入力値を自分で入れる
        //出力：おはよう

例2
$ php index.php
こんばんは //任意の入力値を自分で入れる
        //出力：こんばんは
```

<h2>標準入力の扱い方</h2>
標準入力の仕組みでは、１つの文字列を例としていましたが、
標準入力で与えられる入力値はさまざまな形式があります。

<h3>前後に空白がある文字列が与えられる場合</h3>
与えられた複数の文字列の前後に空白がある場合は、前後の空白も配列に取り込んでしまいます。
この様な場合は、trim関数を使うと前後の空白をなくしてくれます。

trim関数の詳しい文法は公式PHP文法サイトよりご確認ください。
[Google検索](https://www.php.net/manual/ja/function.trim.php)


```.php
//例 fgets(STDIN)に与えられる文字：A(後ろに空白がある)

$array = trim(fgets(STDIN));

echo $array[0]; //出力:A(後ろに空白なし)
```

<h3>(配列編)半角スペースで区切られた2つ以上の文字列(前後の空白なし)が与えられる場合</h3>
半角スペースで区切られた2つ以上の文字列が与えられる場合は、
与えられた文字列をまず配列に入れておくと扱いやすいです。
使う関数はexplodeで、今回は「" "」(空白)で区切れられているところで分けながら
配列に入れています。

explode関数の詳しい文法は公式PHP文法サイトよりご確認ください。
[Google検索](https://www.php.net/manual/ja/function.explode.php)

```.php
//例 fgets(STDIN)に与えられる文字：A B C

$array = explode(" ", fgets(STDIN));
//$array = [A,B,C]←配列に格納される

echo $array[0]; //出力:A
```

空白以外の区切り方でfgets(STDIN)を受け取ったとしても、explode関数の「" "」部分を変更すれば解決できます。


<h3>(list編)半角スペースで区切られた2つ以上の文字列(前後の空白なし)が与えられる場合</h3>
fgets(STDIN)で与えられた入力値を配列に入れる他に、
与えられる文字列の数が少数だと直接変数に値を移す方法もあります。
list関数を使います。

list関数の詳しい文法は公式PHP文法サイトよりご確認ください。
[Google検索](https://www.php.net/manual/ja/function.list.php)

```.php
//例 fgets(STDIN)に与えられる文字：A B C

list($a, $b, $c) = explode(" ", fgets(STDIN));

echo $a; //出力:A
echo $b; //出力:B
echo $c; //出力:C
```

<h3>半角スペースで区切られた2つ以上の文字列(前後には空白あり)が与えられる場合</h3>
さまざまな要素が複合的になっても、関数を組み合わせれば解決できます。
explode関数とtrim関数やlist関数とtrim関数などは合わせて使うことが多いです。


```.php
//例 fgets(STDIN)に与えられる文字：A B C(空白)

//配列の場合
$array = explode(" ", trim(fgets(STDIN)));
//$array = [A,B,C]←配列に格納される

echo $array[0]; //出力:A

//listの場合
list($a, $b) = explode(" ", trim(fgets(STDIN)));

echo $a; //出力:A
echo $b; //出力:B
echo $c; //出力:C
```


初学者さんの参考になれば嬉しいです。
今まで作ったmattermost botを振り返る（2020年版）


この記事はFujitsu Advent Calendar 2020 12日目の記事です。

現在自分が所属している部署では、作業時間のごにょ％を自己研鑽に充てることが可能です。
そんな前提があり、所属のMattermostに通知するbotを作成していました。

昔はHubotやJenkinsで対話（・対話モドキ）botで遊んだりもしましたが
今年はちょっとしたbotの量産をしたので、それを振り返ってみたいと思います。

# 技術的な要素

Pythonスクリプトとして実装しcronにより定期実行しました。

- Python
- Mattermost incoming webhook
- Mattermost API
- Slack API
- webスクレイピング
 
# 作ったbotたち

## GitHub release checker

リリースを追いたいOSSについて、GitHubリリースページのatomを定期的に参照して
追加があれば通知します。

各OSSのSNSや公式ページをずっと監視するわけにもいかず
~~全部のスクレイピング実装もかったるい~~ GitHubのリリースページに目をつけて実装しました。
数々のリリース検知に活躍したので、今回紹介する中では一番働いた子だと思います。

GitHub APIの方がかっこいい（？）実装ですが、対象OSSの増加などから
あえてトークンの制限がないatomによる実装としています。

## GitHub add repository

GitHubの特定組織のrepoページのatomを定期的に参照して
repository追加があれば通知します。

repo追加を監視すると、論文や新しいOSSの公開を追えたので興味深かったです。
こちらもトークン制限回避のためatomによる実装です。

## GitHub status checker

https://www.githubstatus.com のatomを定期的に参照して
追加があれば通知します。

GitHubを開いていて50xエラーに延々と遭遇したときに作りました。
[githubstatusのatom](https://www.githubstatus.com/history.atom)はEntryの更新時にタイムスタンプupdatedも一緒に更新されていたため
進捗状況も通知しています。

## Mattermostチャンネル追加通知

1日1回公開チャンネルの一覧をチェックし、追加があれば通知します。

過去に似たbot（メンバが追加されたら、ウェルカムメッセージとチャンネル一覧をPOST）を作っていましたが
別所属のMattermostでチャンネル通知のみのbotを見かけ、そちらのほうが便利そうなので新たに作り直しました。
所属のMattermostでは認証基盤を別にしているため、Mattermostの認証APIが使えず、若干苦労しました。

## PREMIUM FRIDAY!!!!!!!

プレミアムフライデーを通知します。

テレワークになり、なかなかプレミアム撤退がやりにくいのが痛しかゆし。

## mat2mat

MattermostのチャンネルAのPOSTをチャンネルBに転記し
元POSTには転記済みのマーキングとして絵文字リアクションをします。

次のslack2mattermostのための習作でした。現在はslack2mattermostが稼働しているため停止しています。

## slack2mattermost

SlackのPOSTをMattermostに転記します。
作った経緯などを[別記事](https://qiita.com/kanitabetai/items/a0b7435d6018fe0b5964)にまとめましたので、よろしければそちらをご覧いただければと思います。


## Slack status checker

https://status.slack.com/ のatomを定期的に参照して
追加があれば通知します。

GitHub版と同じノリで作りましたが、[slack statusのatom](https://status.slack.com/feed/atom)は
updatedがatomページにアクセスしたタイムスタンプが設定されているのかEntryの更新を検出できませんでした。
そのためSlack版では進捗の通知はできていません。

## CUDA, cuDNN release checker

CUDA, cuDNNの最新ドキュメントをスクレイピングし
バージョンが更新されていたら通知します。

CUDA,cuDNNはGitHub管理ではないため、リリース検知として作りました。
スクレイピングはchrome canaryを使いたかったのですが、プロキシの壁に阻まれphantomJSを利用しています。


# 今後作りたいbot

久々に対話・対話モドキがやりたくなっているので、今後もbotを作っていきたいと考えています。
Hubotで遊んだのは5～6年前でしょうか、最近の流行りも追いかけたいですね。

## みんなで更新、用語辞書

ちょっとした単語から社内用語まで、なかなか人に聞きづらかったりしますが
Mattermostに"♯what_is" (～とは)チャンネルを作り、わからない単語とその意味をPOSTしてみたところ
ありがたいことにいろんな方にも参加いただけるようになってきました。

ただ、gitlab wikiにも用語集のページは作ってありますが、それを更新するまでは至っていないため
botでつなげられればいいなと思っています。

対話モドキとして、ハッシュタグによるコマンドbotとして検討中です。

## Mattermostログ + search

Mattermostは非常に便利ですが、検索機能には少し不満があります。
別サーバにログを保存し、ログ＋検索用botが作れないかなーとぼんやり検討しています。


# さいごに

**最終的にはこういうbotになりたいです。**

![brain_nou_suisou_denkyoku.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255407/b6182fd3-7ff5-4bd7-b298-3dff5f94b6b1.png)


以上、ありがとうございました。

# 追記

うっかり記事公開とリンク修正を忘れていたので更新しました。（12/12 22:00）
開発の遅れを減らすコミュニケーション

# 1.この記事について
## 1-1.対象
- 開発チームの実装遅延に悩んでいるQA社員

## 1-2.読了時間
3分

# 2.はじめに
「QA開始日までに実装が終わりそうにないです。すみませんが、実装が終わってる箇所から随時みていっていただけないでしょうか。」
QAに携わったことがある方なら誰しも一度は、開発チームからこのような相談を受けたことがおありかと思います。

私が担当しているタイトルでもそういった相談をいただくことがあり、品質リスクにもつながる可能性があったことから、開発チームと連携して実装遅延対策を進めることにしました。

結果的に遅延件数を60%程（※）削減することに成功したので、どんな打ち手をとったのかを簡単にご紹介できればと思います。

※データや画像がQA段階で実装されていない旨の不具合チケット件数で集計


# 3.【打ち手①】開発遅延の現状を可視化し、改善意欲を上げていただく

開発遅延はQAだけでは直せません。
バグと同じで、実際に直していただくのは開発チームなので、まずは「直していこう」と開発メンバーにもQAと一緒の温度感で思ってもらうことからスタートです。

そのために2つの数字を用意しました。

## 3-1.各施策の不具合チケットのうち「未実装の旨のチケット」の割合を示したグラフ
「QA開始日までに実装が間に合っておらず品質リスクが高い状態です」と口で言っても、実際どれくらい遅れている状態なのか伝わらないので、以下のように可視化しました。

![スクリーンショット 2020-12-16 17.18.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553255/98923b97-f762-18ff-2586-941a896b21d6.png)

また「月の未実装の旨のチケット数を○月までに0まで持っていきましょう」とKPIとして定めることができ、開発チームとQA間で共通のゴールを設定することができました。

## 3-2.弊社の他タイトルと比較した不具合率（不具合チケット数/テストケース項目数）
加えて「弊社の他タイトルと比べて、QA段階での不具合が多く、比較的品質リスクが高い状態になっている」と開発体制に対する課題感を高めていただくために、弊社の他タイトルと比較した不具合率（不具合チケット数/テストケース項目数）も合わせて提示しました。

![スクリーンショット 2020-12-16 17.18.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553255/426f0f97-1fc1-2e23-a094-af49ff6df475.png)

相手の一歩を導き出すためには「相手の現状の問題点を自身で認識してもらう」は欠かせないポイントかなと思います。

しかし、どうしても開発チームへの指摘となってしまい、QAからすると大変言い出しにくい部分だと思います。

ただ、事実（数値）ベースで話せば建設的に議論ができるので、QA社員にはその準備力と開発チームへ提案する勇気が必要だと思います。

# 4.【打ち手②】QA社員が開発進捗に影響するタスクのリマインドと進捗確認を徹底する
3-1のグラフを作成するにあたり、未実装の旨の不具合チケットの集計・分析を行いました。

その結果、QA開始時点で実装が完了していない箇所に傾向があったため、その部分の実装状況の確認をQA社員から行うように努めました。

具体的には、毎朝QAから各開発担当者への進捗状況確認を実施しました。

開発メンバーの朝会にQA社員が参加し、開発ガントを参照しつつ、開発期間に入っている（または、近々入りそうな）施策の担当者へ、アートチームへの発注のリマインドや、データ入稿状況の確認などを行っていきました。

毎朝の状況確認とリマインドを実施することで、該当箇所の遅延の軽減に繋がりました。

# 5.【打ち手③】開発遅延に対して原因と対策を話し合う場を設ける
障害（本番環境で発生した不具合）の振り返りを行い、再発防止行うことは当然だと思います。

一方で、開発遅延が発生しても、QAが無事完了となればその件は流れてしまう状態となっていました。
やはり、開発遅延に対する原因分析と再発防止の導入は、ポジティブな気持ちで動き出せないものだと思います。

しかし、振り返りを行わないと課題の温度感も上がっていきませんし、対策のノウハウも蓄積されません。

そこで、QA開始までに開発が間に合わなかったことをヒヤリハットとして捉え、個別に原因と再発防止を考えるようにしました。
具体的には、週次のMTGを開催し、開発遅延が発生した施策の担当者にその原因と再発防止を報告いただき、QA社員が再発防止の導入状況をモニタリングするようにしました。

しかし実際には、なかなか報告を取りまとめてもらえないことが多かったのも事実です。
ただそこで、対応してくれないことを責めるのではなく、定期的に（朝会の進捗確認のタイミングで）呼びかけを行い、必要な場合は直接QA社員から声をかけて再発防止にむけた情報取集を行いました。

# 6.まとめ
これらの取り組みの共通点は「QAから積極的に開発メンバーへコミュニケーションをとっていく」です。

これらの取り組みの結果、開発遅延が減少しただけではなく、コミュニケーション量に比例して、開発メンバーからQAへの信頼が厚くなっていくのを感じることができました。

改めてまとめると、開発遅延の軽減には以下の3つのアクションが効果的でした。

- 開発遅延の現状を可視化し、改善意欲を上げていただく
- QA社員が開発進捗に影響するタスクのリマインドと進捗状況を徹底する
- 週次で開発遅延に対して原因と対策を話し合う場を設けて、再発防止に工数をかける

特にポイントは以下2点でした。

- 開発⇄QA間のコミュニケーション量
- QAからの積極的な働きかけ

また、今回個人的にPMのような立ち位置で動けたのは楽しかったので、PMBOKなどでより専門的にプロジェクトマネジメントを学ぼうと思った次第です。
Power Automate 手動でフローをトリガーする

# 概要

Power Automateでは、トリガーとなるイベント（`リストにアイテムが追加された`，`ドキュメントにファイルが追加された`，`SharePointのサイトが更新された`などのイベント）によって、さまざまなアクションを実行することが可能です。

便利な機能ではありますが、わざわざSharePointやTeamsなど、Microsoft365のPowerAutomate以外のサービスを操作しないと、PowerAutomateで構築したフローを動作検証できないのはちょっと不便と感じるケースがありました。
そんな時に便利に使えるのが[手動でフローをトリガーする]です。

# 手動でフローをトリガーする

PowerAutomateのサイトにアクセスし、[作成] -> [インスタントフロー]を選択します。
![content.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/c4ba7e5c-eaf4-c9e5-4483-c78ea6efee61.png)

フロー名に任意の名前を設定し、[手動でフローをトリガーする]を選択して[作成]ボタンをクリックします。
![スクリーンショット 2020-12-10 20.00.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/63b560b1-fb67-6fe8-d8f8-7737ea6dd96c.png)

例えばTeamsに任意のメッセージを送信する動作だけを簡単にテストしたい場合を想定して、以下のような単純なアクションを追加します。

手動でトリガーするため、SharePointのリストにアイテムを追加するなどの操作をせず、この画面右上にある[テスト]ボタンをクリックすることで、すぐに動作確認が可能です。

![スクリーンショット 2020-12-10 20.02.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/01250d57-4343-1891-bf86-7bc3460bc402.png)

テストの実行が完了すると、実行した際のアクションがどのような処理を行ったのか、実行情報を確認することが可能です。
![pa3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/4b89a173-e459-64c9-f10b-081414739fa1.gif)

手動でフローをトリガーするサンプルとしては以上です。
これがなんの役に立つのか疑問に思うこともあろうかと思いますが、複雑なフローを構築しようとした際に、それぞれのアクションの挙動を事前に確認したり、何らかのデータ加工処理を行いたい場合の動作検証にかなり利用することになるかと思います。
AIはどの分野に応用できる？人工知能の活用事例5選

 [人工知能](https://jp.scrapestorm.com/)は次第に我々の生活に入ってきました。各分野に応用して人工知能は、多くの業界に巨大な経済効果をもたらしただけでなく、人々の生活にも多くの変化と便利さをもたらしました。これから、幾つかの人工知能の応用領域を紹介します。
##1.顔認識
顔認識は顔識別とも呼ばれ、人の顔の特徴情報に基づいて識別する生物識別技術である。顔認識に関する技術は主にコンピュータ視覚、画像処理などがあります。
顔認識システムの研究は20世紀の60年代から始まりました。その後、コンピュータ技術と光学イメージング技術の発展によって、顔認識技術の水は20世紀80年代に引き続き向上しています。
現在、顔認識技術は金融、司法、国境検査、電力、教育、医療など多くの分野に応用されています。
![顔識別.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/89c33dc2-7c8d-358b-5ca5-60dc42908fc5.jpeg)
##2.自動運転
近年、人工知能ブームの高まりに伴い、無人運転が話題となり、国内外の多くの会社が自動運転と無人運転の研究に取り組んでいます。例えば、GoogleのGoogle X実験室では、無人車Google Driverless Carの開発に積極的に取り組んでいます。
しかし、無人運転の複雑さは予想をはるかに超えています。商業化を実現するにはまだ長い道のりがあります。
![無人運転.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/58f3671e-82d6-3563-f923-36dbbcc6fbac.jpeg)
##3.機械翻訳
機械翻訳とは、ある自然言語を別の自然言語に翻訳する変換を、コンピュータを利用して全て自動的に行おうとするものである。インターネットの急速な発展に伴って、機械翻訳技術は政治、経済、文化交流などの面で価値が現れ、人々の生活にも多くの便利をもたらしました。
![機械翻訳.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/0f3d1719-e620-a5c3-fa17-8d21d3c9ef5a.png)
##4.スマートスピーカー
スマートスピーカーとは、AIスピーカーとも呼ばれ、対話型の音声操作に対応したAIアシスタント機能を持つスピーカーである。内蔵されているマイクで音声を認識し、情報の検索や連携家電の操作を行う。
人工知能技術の応用によって、スマートスピーカーもより自然な音声対話方式でより多くの家庭の応用を創造してきた。
![スマートスピーカー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/3186427c-18b0-a413-2c08-9e6cbcf5c063.jpeg)
##5.スクレイピング
[ScrapeStorm](https://jp.scrapestorm.com/)とは、強い機能を持つ、プログラミングが必要なく、使いやすく人工知能[Webスクレイピングツール](https://jp.scrapestorm.com/)です。違う基盤のユーザーに二つの[スクレイピング](https://jp.scrapestorm.com/)モードを提供し、1-Clickで99％の[Webスクレイピング](https://jp.scrapestorm.com/)を満たします。ScrapeStormにより、大量のWebデータを素早く正確的に取得できます。手動で[データ抽出](https://jp.scrapestorm.com/)が直面するさまざまな問題を完全に解決し、[情報取得](https://jp.scrapestorm.com/)のコストを削減し、作業効率を向上させます。
![ScrapeStorm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/e4549230-6844-8f6f-2124-ba50054c32f0.png)
Supershipでエンジニアのグループリーダーを4年やったら開発部長になった話

これは Supershipグループ Advent Calendar 2020の11日目の記事です。

こんにちは！Supership データソリューションスタジオ(DSS)の部長をやっている @funnythingz です。
月日が経つのは早いもので前回のアドベントカレンダー投稿から2年経ちました。何を隠そうQiitaの記事も2年ぶりです。

前回の記事ではエンジニアグループのグループリーダー(GL)の時の内容を書いています。
https://qiita.com/funnythingz/items/b5f7281342a68c3b10e3

今回は2年前の続編としてGL時代の振り返りと部長になってからの感想でも書いてみようかなと思います。

# GL4年間の振り返り

振り返りも兼ねて感想をざっくり書いてみます。

単独のグループだけではなく、複数のグループのGLを兼務しながら複数案件に首突っ込んでマネジメントしていたため、広い範囲のプロジェクトや一時期は20人近いメンバーとの1on1をしたりかなりマルチに広範囲に見ることができたので、自分の中でのマネジメントの引き出しがかなり増えたと感じています。

エンジニアだけではなく、ディレクター、デザイナーのアサインや採用活動も一緒にやっていたのでマネジメントできる職種の幅も広がりました。
元々受託系のデザインチームに所属していたことや、受託系ディレクターの部署でクライアントワークも一緒にやったりしていたので、キャッチアップの時間もかからずすんなりやれたと思います。

プレイングマネージャーとしてやっていたのもあり、PM/要件定義(ディレクション)/UI設計(ワイヤーフレームつくったり)/開発というところまでをリソース足りなくてアサインできない時はパワープレイで全部やってしまうという時もありました。これは中々大変だったのでアラートあげてリソース足せば良かったな等と今は思います。

メンバーとの1on1は定期的にやっていました。
1on1はとても重要な時間で、案件の進捗や状況を聞くのも大事ですが、何よりメンバーのコンディションを探る上では絶対必要だと思ってます。メンバーとの信頼関係を築き続けていくにも大事なので時間は多めに割いていました。グループの状態が良ければほとんどのことはうまくいくと思っています。逆にうまく行ってない時は自分だけではどうにもできないことも多々あるので、上長や人事にも協力いただいて課題に取り組んだりしていました。

正直一人では何もできないことの方が多いので周りからたくさん力を貸してもらうことでより大きな取り組みができるんだなということを4年間で学びました。

今エンジニアマネージャーをやってる人たちに伝えたいのは一人で抱え込まずに周りの協力を得て力をもらいながらやっていくのが良いですよということです。一見当たり前のことではあるのですが、忙殺されてるとそれすら考えることができなくなったりしますし、意外に周りの助けを乞わずに自分が上司なんだから自分が何とかしないと！という方も少なくないので、あまり気負いすぎずにやるのが良いと思います。

ということで、GLの最後の方はもはやストレスもほぼなくやれていましたが、ここだけの話、むしろちょっと飽きて物足りなくなっていたかもしれません。

# そして開発部長へ

物足りなくなっていた頃、当時の上長がCTOになるとのことで、まさかの自分がその開発組織の部長をやることになりました。予兆を全く感じていなかったのでなんとまさかの！という気持ちでした。それと同時に、50人前後(プロパー&業務委託含む)の開発組織のリーダーとなるのでプレッシャーも凄くありました。僕の見ている開発組織はエンジニア/デザイナー/ディレクターが所属していて本当にみんな優秀なのでそこは問題ないのですが、僕の上長(現CTO)がカリスマ性のある凄い人なので自分がリードできるのか？という心配もありました。

約9ヶ月経った今ではそこそこ慣れてきたのでまだまだ未熟者ではありますが何とかやれていると信じたいです。これも本当にみんなのおかげです！

常にやったことないことに挑戦していくのが好きということもあり、部長職は権限も責任もかなり大きいため(漫画のONE PIECEの海軍でいうところの中将クラスくらい。鬼滅の刃だと柱？)、やれることが本当に限界ないです。今の上長からは特に何か言われることはないですが、もっとやれるよね？という無言のプレッシャーは感じているので、もっとバリューを発揮していかないといけないなと思ってます。(僕が貢献し続けていかないとイケない病にかかってる可能性もありますが)

# さらに新たな挑戦へ

弊社、UIデザイナーや開発系ディレクターが少ないのもあり、プロダクトのUIや開発系マネジメントの強化もしていきたいなと思っています。今は開発組織の部長ですが、こういった部分においても僕がリードしていきたいと思っているので新たに部署を立ち上げてやっていく予定です。

特に開発系ディレクター(PMも可)を欲しているので我こそは！という方いたら連絡ください。
僕の直接の知り合いの方たち、特にあなた達ですよ！！
すみません、取り乱しました。やってやりたいぜ！という方いましたらぜひお願いします。

# 最後に

Supershipではプロダクト開発やサービス開発に関わる人を絶賛募集してますよ！
[Supership株式会社 採用サイト](https://supership.jp/recruit/)
是非ともよろしくお願いします！
Elasticsearch > Filebeat > Apacheログの取り込み


UseCase: 

- Elasticsearchサーバーは構築済み
- ApacheのログをElasticsearch＆Kibanaでサクッとみてみたい
- Dockerでサクッとやりたい



## dockerの設定

### docker-compose.yml
 
docker-compose.yml

```:docker-compose.yml
version: "2.2"
services:
  filebeat:
    build: ./filebeat/
    volumes:
      - ./external_log/:/usr/share/filebeat/external_log/
```


### Dockerfile

```:Dockerfile
FROM docker.elastic.co/beats/filebeat:7.10.0

# filebeatの実行に必要な設定ファイルをDockerイメージの中へコピー
COPY ./config/filebeat.yml /usr/share/filebeat/filebeat.yml

# apacheモジュールを有効化
COPY ./config/apache.yml /usr/share/filebeat/modules.d/apache.yml

# filebeatを実行
USER root
RUN chown root:filebeat /usr/share/filebeat/filebeat.yml
USER filebeat

```

### Docker起動

```
docker-compose up --build
```


### clean up

```
docker-compose down --volumes
```
Power Automateチュートリアル

# 概要

Power Automateには無限の可能性があるんだろうな〜と期待しつつ、できることを調べるよりも「まずやってみる」ことから始められるように、チュートリアル的なことをしてみました。

ここでは、SharePointに作ったリストにアイテムが追加された際、Teamsにそのアイテムが追加されたことを通知するPower Automateのサンプルを構築します。

## 使っているMicrosoft365関連サービス（アプリ）

- SharePoint
    - リスト（実際にはMicrosoft Lists？）
- Power Automate
    - SharePointのリストに新規アイテムが追加されたことを検知する
    - Teamsにチャット通知を行う
- Teams
    - チームのチャットに通知するため

# チュートリアル

このチュートリアルでは、以下3つのステップでPower Automateを触っていきます。

- トリガーを指定する
- アクションを指定する
- 動きを確認する
    - 上記２ステップでPower Automateの作成が完了したら、実際に動作を確認します。

## 事前準備

事前にSharePointのサイトに`リスト`を作っておく必要があります。
Power Automateチュートリアルとしては、リストの内容は重要ではないため、タイトルのみのシンプルなリストを利用します。

![スクリーンショット 2020-12-10 19.32.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/2022b005-c2b5-ea5c-5b08-ab84699d3c69.png)


## トリガーを指定する

トリガーとは、Power Automateで自動化される処理を開始するためのイベントを指します。
このチュートリアルでは、リストにアイテムが追加されたというイベントがトリガーとなります。

1. PowerAutomateのサイトにアクセス<br>https://japan.flow.microsoft.com/ja-jp/
1. [＋作成]をクリック
1. [自動フロー]をクリック
1. [フロー名]に任意の名前を入力し、[項目が作成されたとき]のフローを選択して[作成]ボタンをクリック
1. [項目が作成されたとき]トリガーの[サイトのアドレス]と[リスト名]を指定する

![pa1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/396a019c-8484-e810-9d6e-ba620c6ceb5d.gif)

## アクションを指定する

`アクション`とは、[メールを送信する] [ファイルを削除する] [ツィートする]など、PowerAutomateで実行する処理を指します。
このチュートリアルでは、Teamsに通知する処理がアクションとなります。

1. [＋新しいステップ]をクリック
1. [Microsoft Teams]のアクション[メッセージを投稿する]を選択する
1. 以下を設定
    1. [チーム] Teamsに作ってあるチームを指定する
    1. [チャネル] 通知先のチャネルを指定する<br>※チーム内にチャネルを作成せず利用している場合、デフォルトのチャネル[General]を指定する
    1. [メッセージ] Teamsに通知するメッセージ本文を指定する<br>本文は、トリガーとなるイベントの情報も利用することが可能です。<br>（例えば、リストに追加されたタイトル情報を本文に含めるなど）
1. [保存]ボタンをクリックし、作成したPowerAutomateを保存する

![pa2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/296f8e82-2892-77c3-13d4-b52860e8985b.gif)

## 動きを確認する

このチュートリアルでは、リストにアイテムを追加することで、作成したPowerAutomateの処理が実行されます。
リストに任意のタイトルをつけたアイテムを追加して確認していきます。

![スクリーンショット 2020-12-10 19.45.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/17145221-4c46-9606-2a81-5afc928ce574.png)

![スクリーンショット 2020-12-10 19.45.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/0dbfdec7-6f63-180b-9d7d-b658453485b2.png)

お買い物リストに「大根」を追加しました。
しばら〜く待っていると、Teamsに通知が届きます。

![スクリーンショット 2020-12-10 19.48.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/93506d96-4350-d7ab-9a9f-88d8d45f1756.png)

ここで紹介しているPowerAutomateのチュートリアル自体は大したことをやっているわけでもなく、何かに役立つかどうかもわからないようなレベルのものですが、「まずやってみる」レベルにちょーどいい感じかなぁと思っています。
自分自身もまだまだMicrosoft365について知らないことばかりなので、ちょっとずつ習得していこうかなぁと思っています。