OmniAICreator/Qiita-1.07M huggingface dataset:
数式無しでAIのニューラルネットワークをざっくり解釈してみた

#はじめに
私は前職ではソーシャルゲームのwebエンジニアをやっていました。
いわゆる APIサーバーの構築などをやっていました。
数学とか数字とかすっごい苦手な雰囲気エンジニアです。
そんな私が、縁あってAIベンチャーに入ったので、AIの勉強をしてみることにしました。
まず、手始めに [Udemy の 「みんなのAI講座 ゼロからPythonで学ぶ人工知能と機械学習」](https://www.udemy.com/learning-ai/learn/v4/content) からニューラルネットワークについて勉強してみたので、数式とか使わずにざっくりまとめてみたいと思います。

#ニューラルネットワークとは
「人間の脳神経系のニューロン(神経細胞)が結合によりネットワークを形成したもの」だそうです。
AIのニューラルネットワークは人間のニューラルネットワークを模倣したものになります。

#ニューラルネットワークは層構造
下の図のように層に分かれて構成されています。
左の入力層から中間層へ、中間層から出力層へデータが流れていきます。
この丸1子がニューロンとなり、複数のニューロンがつながっているこがイメージできます。

![nn_1.png](https://qiita-image-store.s3.amazonaws.com/0/93763/ea8ececd-cbe1-f479-63c7-b7cf69487dd0.png)

#ニューロンについて
1つ１つのニューロンについてはこんな感じになります。
複数の情報を受取ります。
その「入力値」に「重み(Weighat)を掛けた」ものに、「バイアス」を足して結果を求めます。
重みとは結合の強さを表し、バイアスとは結果に偏りをもたせるためのスパイスのようなもの？
考え方としては、ここのニューロンは学習の中で、それぞれ別の重みとバイアスを持つようになり、それぞれのニューロンに個性(差)ができあがり、それぞれ別の判断を下すニューロンが複数つながることにより、複雑な結果を返すことができるらしいです。

上記で「入力値に重み(Weighat)を掛けて、バイアスを足したものが結果となる」と言いましたが、正確にはその結果を活性化関数を通したものが出力されます。
![nn_2.png](https://qiita-image-store.s3.amazonaws.com/0/93763/6bf71b72-a6ff-cfcf-2f55-ad7b8877d21f.png)

## 活性化関数
活性化関数とは、出力値を決定する関数のことを言います。
いろんな関数が活性化関数として使用されるようです。
例えば Udemy の講座でもでてきた **シグモイド関数** という関数は、「0または1」という2つの解を求める場合によく使用されるそうです。
活性化関数を通ることで、入力値から 「これは〇〇である」 or 「これは〇〇ではない」 といった結果を返すことができるそうです。


#ニューラルネットワーク
さて、ニューロンが重みとバイアスによって、それぞれの解釈で結果を返すということがわかりました。
このニューロンがたくさん結合したものがニューラルネットワークということもわかりました。
では、これがどうやって機械学習をするのでしょうか？

#学習とは？
過去1000日分のビールの売上を学習し、未来の売上を予測したいとします。
このとき、1000日分の売上(答え)とそれに紐づくインプット(例えば1000日分の気温 と 天候)の情報を渡します。
そうすると、インプットから答えを出し => 答え合わせをする といったことを繰り返します。
結果、インプットと答えの中の関係性を勝手に見出し、未来を予測するようになるそうです。

#バックプロパゲーション
上記で説明した、「インプットと答えの中の関係性を勝手に見出し、未来を予測する」ことを実現しているのが、__バックプロパゲーション__です。
先程、ニューロンには重みやバイアスがあり、それにより回答が変わるという話をしましたが、この重みやバイアスを適切に調整することが学習となります。

さきほどのビールの学習でいうと、インプットから予測した結果を正解と比較します。
そして、正解に近づくように重みやバイアスを調整していきます。
この重みやバイアスが調整されたニューラルネットワークは、インプットと答えの中の関係性を見出した結果になるわけですね。
この、関係性にそって未来を予測すると、それなりに実績にそくした結果が得られるようになります。

緑の○が重み(Weighat)
![nn3.png](https://qiita-image-store.s3.amazonaws.com/0/93763/f57ba521-f2ab-2185-43a3-6efb48720c22.png)



#まとめ
これが ニューラルネットワークのざっくり概要です。(はずです)
本当は自前のソースコードなんかも書いてみようと思ってたのですが、間に合わなかったので割愛しました。

ニューラルネットワークについては、ネット上でしらべても数式が出てきた時点でサッとページを閉じていたのですが、ようやく概要が理解できました。
機械が物事を考えるってこういう仕組みで成り立ってるんだなって事がわかりました。
人間の脳の仕組みと同じって...
脳の仕組みを解いた事もすごいし、それをロジックにして機械に落とし込むなんて驚きでしたね。
さて、私もどんどん勉強して目指せ__スカイネット__！！
WicketプロジェクトをGradleでビルドしたらMarkupNotFoundExceptionが発生

別チームの人がWicketで作成したWebアプリをサーバに乗せてくれと頼まれたので、
「デプロイするだけでOKならいいですよー」と安請け合いしたら、以下を知らなくて意外とハマった

## 開発者から受け取ったもの

* ソースコード一式
* build.gradle

曰く、gardleでwar作れるようになってるので、作ったwar置けばOK！
早速言われたとおりに、`gradle war`を実行し、出来上がったwarファイルをWebサーバに配備

## MarkupNotFoundException

配備したアプリにアクセスすると以下のエラーが発生

```
ERROR org.apache.wicket.RequestCycle - unexpected exception when handling another exception: Markup of type 'html' for component 'com.xxx.HomePage' not found. Enable debug messages for org.apache.wicket.util.resource to get a list of all filenames tried.: [Page class = com.xxx.HomePage, id = 1, version = 0]
```
どうやら「HTMLファイルがないよ」的なことをいっている。

サーバに配備されたアプリの、WEB-INF配下を見てみると確かにHTMLファイルが見当たらない

```
$ ll ${APP_HOME}/WEB-INF/classes/com/xxx/
合計 48
-rw-r--r-- 1 root root 1377 12月 13 14:45 2018 BasePage.class
-rw-r--r-- 1 root root  415 12月 13 14:45 2018 ErrorPage.class
-rw-r--r-- 1 root root  420 12月 13 14:45 2018 HomePage.class
-rw-r--r-- 1 root root 2703 12月 13 14:45 2018 WicketApplication.class
drwxr-xr-x 2 root root 4096 12月 13 14:56 2018 commons
drwxr-xr-x 2 root root 4096 12月 13 14:56 2018 dao
drwxr-xr-x 2 root root 4096 12月 13 14:56 2018 info
drwxr-xr-x 3 root root 4096 12月 13 14:56 2018 tools
```

受け取ったソースコード一式の中には、HTMLファイルは存在している模様

```
src
 └─main
    └─java
       └─com
          └─xxx
             │ commons
             │ dao
             │ info
             │ tools
             │ BasePage.html
             │ BasePage.java
             │ ErrorPage.html
             │ ErrorPage.java
             │ HomePage.html
             │ HomePage.java
             └─WicketApplication.java
```

## 原因

* HTMLファイルが`src/main/java`配下に入っているのがダメ
  * Gradleの規約に沿っていないため、war作成時に含まれなかった
  * 以下のようなディレクトリ構成に変更することで解決

```
src
 └─main
    │─java
    │  └─com
    │     └─xxx
    │        │ commons
    │        │ dao
    │        │ info
    │        │ tools
    │        │ BasePage.java
    │        │ ErrorPage.java
    │        │ HomePage.java
    │        └─WicketApplication.java
    └─resources
      └─com
         └─xxx
            │ BasePage.html
            │ ErrorPage.html
            └─HomePage.html
```

## まとめ
成果物は誰かに渡す前に動作確認すること！
gem 'fall_snow'を使ってRailsアプリケーションに雪を降らせる

## はじめに
今回のAdventCalendar言い出しっぺのtatsukichiです。

DMM WEBCAMP AdventCalendarの最終日を担当させていただきます。




クリスマスシーズンでいろいろなアプリケーションで雪を降らす演出が年々増えてきていますね。
みなさんが使っているアプリケーションでもよく見かけませんか？

そんな演出を手軽にアプリに導入できたらクリスマスも盛り上がるのではないかと思い、
「雪を降らせるgem」を作ってしまいました。

みなさんの手がけるアプリケーションでも使っていただけたら幸いです。
それでは、簡単ですので使ってみてください。



## どんなもの？
たった6行(最小)のコードで雪を降らせることができます。
本当にそれだけです。

こんなものができあがります。
![fall_snow.gif](https://qiita-image-store.s3.amazonaws.com/0/184333/85cdea6c-3da7-e443-6563-ee68f2247921.gif)

### 公式
https://rubygems.org/gems/fall_snow

## 早速やってみる
それでは雪を降らせていきましょう。

### 1行目
Gemfile

```ruby

gem 'fall_snow'
```
bunble installしましょう。

### 2~5行目
app/assets/stylesheets/application.css

```css
@import 'fall_snow/style.css';
 body{
     background-color: #142744;
 }
```
cssを読み込みます。
bodyに暗めの色を入れて雪が目立つようにしていますが、お好みで調節してください。

### 6行目
雪を降らせたいviewファイルに。

```erb
<%= fall_snow %>
```
bodyタグ内であればおそらく動くでしょう。

### 以上
このような感じでサクッとできてしまいました。
皆さんのRailsアプリケーションでも冬のうちに降らせてみてはいかがでしょうか？

ちなみにこれだけで雪は降るのですが、これ以上に機能は今の所ありませんw
今後の機能拡充に期待しましょう。

gemを作成した話も盛り込もうと思ったのですが、ボリュームが大きくなりそうだったので
いいねが100超えたら書こうと思います。

ありがとうございました。
Ubuntu18.04 LTSにpgRouting環境を構築してみる

pgRouting環境の構築方法は色々と既存記事があると思いますが、Ubuntu18.04での記事が見つからなかったので覚書として残しておく。


##リポジトリの追加
参考：https://wiki.postgresql.org/wiki/Apt
標準のDEBでもPostgreSQLはインストールできるんですがpgRoutingを入れるならリポジトリを追加しておきましょう。

```
$ sudo apt install curl ca-certificates
$ curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
$ sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
```

パッケージリストを更新

```
$ sudo apt update
```
##インストール
PostgreSQL10とPostGIS、pgRouting、管理用にpgAdmin4をインストールします。
pgRoutingを入れるとPostGISは付いてくるので指定していません。

```
$ sudo apt install postgresql-10 postgresql-10-pgrouting pgadmin4
```

ちなみにpgAdmin4はメモリをやたらと使いますのでサーバ上で動かす場合はメインメモリを2GB程度は割り当てておかないとまともに動かせませんでした。ご注意を。

##初期設定
postgresユーザーができているのでそちらに切り替えて作業をする。
CentOSだとrootからpostgresユーザーにsuしてたのでpostgresユーザーにパスワードを指定せず（通常ログイン不可状態として）使っていたけどUbuntuではどうするのが一般的なんでしょうか。
ここではpostgresユーザーにパスワードを設定してsuします。

```
$ sudo passwd postgres
新しい UNIX パスワードを入力してください: 
新しい UNIX パスワードを再入力してください: 
passwd: パスワードは正しく更新されました
$ su - postgres
```

psqlコマンドで接続してpostgresアカウント（PostgreSQLのログインロール）のパスワード設定とテスト用データベースの作成をします。

```
$ psql
postgres=# ALTER USER postgres PASSWORD 'new_password';
ALTER ROLE
postgres=# create database testdb;
CREATE DATABASE
postgres=# \q
```

今度はテスト用データベースにpostgresアカウントで接続してPostGISとpgRoutingを有効にします。

```
$ psql -d testdb -U postgres
testdb=# CREATE EXTENSION postgis;
CREATE EXTENSION
testdb=# CREATE EXTENSION pgrouting;
CREATE EXTENSION
testdb=# \q
```

できました。

##確認
pgAdmin4を使ってローカルDBに接続して空間関数やpgr関数が設定されているかを確認します。


pgAdmin4を起動したら左のツリーのServersを右クリックして[Create]-[Server]を選ぶ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/240181/a209926d-ecc4-8a52-cb7d-92b53c6c8a3f.png)

GeneralタブのNameに適当に名前を入れたら、ConnectionタブのHostname/addressに[localhost]、UsernameとPasswordに先ほど設定したpostgresアカウントを設定してSaveボタンをクリック。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/240181/8dcb07f0-165e-059d-6b66-d050f31a6f6c.png)

するとツリーにサーバが追加されるのでどんどん開いていきましょう。
Functionsまで開いて横に(1384)みたいな数字が出ればOKです。
ずらずっと下げていくとST_ほにゃららとかpgr_ほにゃららが出てくると思います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/240181/55e98a79-b9e6-1c02-d7ae-0716371b9c76.png)

##感想
手軽にインストール出来ました。
pgRoutingのDockerfileを公開している方もいるのでそういうのを使ってみるのもいいかもしれない。
データの投入や使い方は以下の記事を参考にするといいと思う。
https://qiita.com/sanak/items/f50e8c5bb97bf9619958

##困りごと
pgAdmin4からツールの実行をしようとすると以下のエラーがでるんで解決したい。
pythonではなくpython3にPATHが通るようにするか、pythonでも動くようにするかだと思ってる。
できればvirtualenvは使いたくない。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/240181/a782fbab-1053-05b3-0860-492c2cb6ec6e.png)
【Google Spreadsheet】セルを変更すると、自動的に日付更新するGoogleAppsScript


## はじめに
リブセンスでProduct Manager(PM)をしてる新卒2年目の萩原といいます。
今年の1月より転職会議のメディアグループに異動しました。
メディアグループに異動する前までは、営業ばかりしていたため、SQLやGoogleAppSctipt？？なにそれ美味しいの？状態でした。
今回は、営業しかしていなかった私が、業務で実際に活用できたGoogleAppsScriptについて記載したいと思います。
普段はSQLの方が圧倒的に使いますが、他のうちの社員が書きそうなのでSQL記事はやめましたw
ちなみに趣味は、マンガと落語です。

## 対象
Spreadsheetを利用することがあり、自動化とかに興味がある方。(営業や事務など含む)
初心者向け

## この記事を読むとできるようになること
特定のセルを変更すると自動的に特定のセルの日付を更新し取得するScriptを使うことができます。
もう少しわかりやすく書くと、例えば、企業情報とそのステータスが記載されているシートがあるとします。
そこでステータスを変更すると更新した日付が自動的に入力されるといった具合です。
(イメージ図でいうとG列を更新すると同じ行のA列が自動的に更新される)
[イメージ図]
![image.png](https://qiita-image-store.s3.amazonaws.com/0/224886/3f48488a-e3d5-a1f9-2218-ead48fdcf2a6.png)
※企業名やステータスは適当です。

業務上、ステータスが更新した日時を記載する必要があり、それを毎回手作業で入力する手間を省くことが目的でした。

## 手順とスクリプト
それでは実行までの手順とスクリプトです。
　　1. Scriptを導入したいSpreadsheetを開く
　　2. ツールをクリック
　　3. スクリプトエディタをクリックする
　　4. 下記のコードをコピペして一部修正する。

```
function insertLastUpdated() {
  var ss = SpreadsheetApp.getActiveSpreadsheet(); //現在触っているファイルを取得
  var sheet = ss.getSheetByName('hoge'); //対象のシート名を選択(hogeの部分にシート名記載)
  var currentRow = sheet.getActiveCell().getRow(); //アクティブなセルの行番号を取得
  var currentCol = sheet.getActiveCell().getColumn(); //アクティブなセルの列番号を取得
  var currentCell = sheet.getActiveCell().getValue(); //アクティブなセルの入力値を取得
  var updateRange = sheet.getRange('A' + currentRow); //どの列に更新日時を挿入したいか。この場合はA列
  Logger.log(updateRange); //更新日の記入
  if(currentRow > 2　&& currentCol == 7) { //2行目以降かつG列の変更を参照とする 
    if(currentCell) {
    updateRange.setValue(new Date());
    }
  }
}
```
以上です。簡単ですね。

## 最後に
GSは非エンジニア以外の方が使うことが多いのかなと思います。JSに非常に似ているので、習得もしやすい方ではないでしょうか？(自分はJS含め勉強中です)
プログラミング興味あるけど何から手を付ければいいかわからないという人にはいいかもしれません。

P.S.
初めてのQiita投稿緊張した。
WordPress のサーバーのアクセスログを CloudWatchLogs Insights を使って確認してみた。

# ０．はじめに

以下の記事の手順で、WordPress のサーバーのアクセスログを CloudWatchLogs に送っているんですが、

* [AWS CloudWatch で、Amazon Linux のパフォーマンスとログの監視をしてみる \- Qiita](https://qiita.com/kusokamayarou/items/b59d34b0ee0f8ff544c1)

CloudWatchLogs Insigths を使って確認してみました。

# １．CloudWatchLogs Insights

1. まずは、CloudWatchLogs Insights を開きます。
    * [CloudWatch Management Console](https://ap-northeast-1.console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#logs-insights:queryDetail=~(editorString~'fields*20*40timestamp*2c*20*40message*0a*7c*20sort*20*40timestamp*20desc*0a*7c*20limit*2020~end~0~isLiveTail~false~queryId~'*2faws*2flambda*2fMaintenanceEC2_Image~source~'*2faws*2flambda*2fMaintenanceEC2_Image~start~-3600~timeType~'RELATIVE~unit~'seconds))

1. 以下の設定を行い、「クエリの実行」ボタンを押下。
    * ログストリーム : ※所定のログストリーム
    * クエリ : 
    
```sql
fields @timestamp, @message
| sort @timestamp desc
| filter (@logStream="i-************" and @message like "xmlrpc.php")
```
1. そうすると、こんな感じで表示されます。
    * <img width="1280" alt="スクリーンショット 2018-12-12 9.19.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/161939/418cd786-41d8-bc78-8a18-14e9c84571d7.png">

# ９９．ハマりポイント

* そこまで大きなハマりは無かったですが…。
<br><br>
* CloudWatchLogs Insights の記事がそれほど見当たらなくて、ちょっと時間掛かりましたが、以下のドキュメント見て、色々試しながらやってみました。
    * [CloudWatch Logs Insights Query Syntax \- Amazon CloudWatch Logs](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html)
<br><br>
* うまく使っていければ、運用だけじゃ無く、開発やテストもすごく便利になるんじゃないかと思います。クエリはダッシュボードに保存できるし、Insights の設定は URL にも反映されるので、よく使いそうなクエリや複雑なクエリは、ブクマで保存しとけば便利かと思います。

# ＸＸ．まとめ

本当 AWS はどんどん便利になっていきますよね♪

ありがとう AWS さん!!
grpc-webを使って.protoファイルからWEBブラウザ用JSコードを自動生成する

## こんな人向け

* gRPCの基礎知識は押さえてる
* WEBフロントエンドからgRPCサービスにアクセスしたい
* .protoファイルからWEBフロントエンド用のJSコードを自動生成したい
* Mac使ってる（他OSの方はそれぞれ読み替えてご覧ください）



## 用語

### grpc-web

WEBブラウザからgRPCサービスにアクセスするためのJavaScriptライブラリ。

### protoc-gen-grpc-web

grpc-web公式のprotocプラグイン。
WEBブラウザ用のJavaScriptコードを自動生成してくれる。



## コード生成手順

### Protocol Bufferインストール

`protoc` というコマンドを使うのでprotobufをインストール

```shell
brew install protobuf
protoc --version
```

### protoc-gen-grpc-webインストール

下記ページ内にある `protoc-gen-grpc-web-1.0.3-darwin-x86_64` って感じのファイルをダウンロードする（Macはdarwin）
https://github.com/grpc/grpc-web/releases

ダウンロード後、そのファイルパスを下記コマンドに入れて実行

```shell
sudo mv ~/Downloads/protoc-gen-grpc-web-1.0.3-darwin-x86_64 /usr/local/bin/protoc-gen-grpc-web
chmod +x /usr/local/bin/protoc-gen-grpc-web
```

### protoファイルを作る

```helloworld.proto
syntax = "proto3";
package helloworld;
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
  string name = 1;
}
message HelloReply {
  string message = 1;
}
```

### コード生成コマンド実行

下記を実行すると２つのJSファイルが生成される

```shell
protoc -I=./ helloworld.proto \
--js_out=import_style=commonjs:./ \
--grpc-web_out=import_style=commonjs,mode=grpcwebtext:./
```

* `helloworld_grpc_web_pb.js`
* `helloworld_pb.js`



## 生成されたJSの扱い方

```index.js
import helloworld from './helloworld_grpc_web_pb'

const greeter = new helloworld.GreeterPromiseClient('http://localhost:50051')
const req = new helloworld.HelloRequest()
req.setName('World')
greeter
  .sayHello(req)
  .then((res)=>console.log(res))
  .catch((err)=>console.error(err))
```


## 実際に動かしてみる

otanuさんという方が作られたこちらのサンプルが非常に分かりやすいので、実際に動かして試してみたいという方は是非。（丸投げですいません...！）
https://github.com/otanu/hello-grpc-web



## 参考文献

下記ページを参考にさせていただきました。
先人の皆様へ感謝。ありがとうございます。

https://qiita.com/otanu/items/98d553d4b685a8419952
https://developers.google.com/protocol-buffers/docs/reference/javascript-generated
https://github.com/grpc/grpc-web
https://qiita.com/keitarou/items/487972af127d8b720d4b
http://blog.64p.org/entry/2018/10/31/141431
http://terachanple.hatenablog.jp/entry/2018/11/01/214855
【バグ解消】FileMakerProAdvanced17からESSでMySQL接続するとSleep状態でコネクションはり続けられる問題

# 2019/01/16 14:40 追記
* FileMakerProAdvanced 17.0.4 のリリースにともない、解消されました。
* アップデータのダウンロード先　→　[FileMaker Pro 17.0.4 Advanced アップデータリリースノート](https://support.filemaker.com/s/article/FileMaker-Pro-17-0-4-Advanced-%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%82%BF%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%83%8E%E3%83%BC%E3%83%88?language=ja)
* 以下は記録として残しておきます。

# 前書き
未解決なのですが、掲題のような問題に遭遇しているので、これから FileMaker Pro Advanced 17 ( 以下 FMPA17 ) を導入しようと考えている人への注意喚起の記事です。


## 対象読者
* FMPA17 のアップグレードを検討中で、FileMaker Server ( 以下 FMS ) に MySQL ODBC Driver を入れて MySQL へ接続している
* FMPA17 新規導入 or 既に FMPA17 を利用中で、新たに上記のように MySQL への接続を検討中


## FMPA から MySQL への接続とは
FMPA をクライアントとして、外部データソース ( MySQL, SQL Server, Oracle 等 ) のデータを閲覧／操作することができます。便利！

[公式サイト - 外部 SQL データソースの概要](https://www.filemaker.com/jp/support/technologies/sql.html)


# 問題の症状
FMPA17 経由で MySQL 接続をおこなうと、 Sleep 状態でコネクションが延々とはり続けられてしまいます。
wait_timeout 設定無視です。例えば、値が 3,600 とかになっていたとしても 10,000 超えても続きます。
すると、やがて max_connections の設定上限値に達して、 MySQL への接続ができなくなってしまいます。

その状態で FMPA 17 から新たな接続を MySQL に対して試みようとすると、認証情報を問われるようになり、正しく入力しても、認証が通らなくなります＝接続できないため。

なお、以前の ver. で FileMakerPro 15 ( 以下 FMP15 ) をクライアントとして接続すると、上記症状は発生しません。
FMPA17 特有の問題ではないかと思われます。
あるいは、 FileMakerPro 16 から、プロセスとウィンドウ表示の仕様が変更されたので、それが影響しているのではと考えられます。細かく検証はしていませんが。


## 症状の確認方法
MySQL へログインした状態で、以下のコマンドを実行すると、 Sleep 状態のコネクション一覧が表示されます。

```
select *
  from information_schema.processlist
  where command = 'Sleep'
  order by left(host, 20) desc, time desc;
```

max_connections, wait_timeout の現在設定値がいくつになっているかの確認は、以下コマンドで。

```
show global variables like 'max_connections';
```

```
show global variables like 'wait_timeout';
```


## 環境についての諸情報
症状発生においての環境をまとめておきます。

### FileMaker サーバ
* Windows Server 2016
* FileMaker Server 17.0.2
* MySQL ODBC Driver Unicode 5.2.7 / 5.3.9 / 5.3.11

### MySQL サーバ
* MySQL 5.7.20

### クライアント
* Windows 10 Home / Pro
* FileMakerPro Advanced 17.0.3



# 解決に向けて
現在、日本のファイルメーカー社へ問い合わせ中です。経由で、本国の FileMaker,Inc に問い合わせてもらっています。
何らか有効な情報が追加され次第、記事更新していきたいと思います。

## 2018/12/18 11:30 追記
ファイルメーカー社から公式回答をいただきました。引用許可の承諾済です。

>FileMaker Pro 17 Advancedのバージョン17.0.3.304において症状が発生する事が本国の開発部署より回答がございました。
>現状解決策がなく、FileMaker Proの15や16をご利用いただくか、
>FileMaker Pro 17 Advancedの17.0.2.205を新規にインストールしていただき症状発生を回避していただきたく存じます。

とのことでした。
これを受けての Q&A も以下にまとめておきます。

### Q&A
* 17.0.4 まで待てば修正はされるか？
    * 17.0.4 で修正される確証はありません。修正の ver. として 17.0.5 になるか 18 になるかもわかりません。
* 修正されたかどうかの確認方法について。
    * リリースログに記載があるかどうかで、ご確認ください。

とのことでしたので ESS 利用される場合には、くれぐれもご注意ください。
また、私の方でも情報をキャッチアップできたら、記事の更新をします。

## 2019/01/16 14:40 追記
* 冒頭の通り、解決されました。
python de 競技プログラミング

この記事では、python3で競技プログラミングを始めるにあたって知っておくとお得なことをまとめました。
pythonなどの高級な言語は、競技プログラミング向けでないと思われがちです。実際、ほとんどのレッドコーダーはC++をメインにやっており、時々JavaやC#を使う人がいるって程度です。**しかし、pythonだけで（少なくとも）オレンジコーダーになることは可能です。**（ちなみにこの記事を書いてる人は青コーダーです）

# なぜpythonか

#### メリット
- **書きやすい**
- **読みやすい**
- C++などと比べてコード量を小さくできる（早解きや実装が重いときに有利）
- numpyとscipyが便利かつ速い（Atcoderに限る）
- 使ってる人が多いのでわからないことはググれば大体出てくる
- 標準ライブラリが豊富

#### デメリット
- **どうしても解けない（TLEする）問題がある**

ですが安心してください。**ほとんど**の問題は解けます。

# 知ってるとお得な標準ライブラリのモジュール
pythonには強力な標準ライブラリがあります。物によってはCなどで実装されてる機能もありかなり速いです。

#### [`collections`](https://docs.python.jp/3/library/collections.html)（様々なコンテナデータ型）

- `deque` 両端での出し入れが速いキュー。`list`は末尾の出し入れについてのみ高速。
- `defaultdict` ファクトリ関数を呼び出して存在しない値を供給する辞書。
- `Counter` 数え上げをしてくれる`set`。たまに使うと楽なことがある。

`defaultdict`については、`defaultdict(int)`や`defaultdict(list)`が頻出パターン。DPやグラフ系の問題で何かとお世話になります。
   
#### [`itertools`](https://docs.python.jp/3/library/itertools.html)（イテレータに関わる便利グッズ）
ここではよく使うのだけ紹介しますが、他にも色々あります。

- `accumulate(p, func=sum)` 累積和をとってくれる。関数を投げられるので累積maxなど何でもできる。
- `chain.from_iterable(iterable)` 複数のiterableを連結してくれる。
- `product(p, q, ..., repeat=1)` 直積集合。ネストしたforループと等価。グリッド内の点を全部巡回したいときなど
- `permutations(p[, r])` 長さrの重複なし順列
- `combinations(p, r)` 長さrの重複なし組み合わせ

#### [`bisect`](https://docs.python.jp/3/library/bisect.html)（二分探索）
#### [`heapq`](https://docs.python.jp/3/library/heapq.html)（優先度付きキュー）

# numpy/scipyを活用する
行列演算だけが取り柄だと思われがちですが、numpyを用いることで実行速度を速め、かつコードを簡潔にすることができます。

#### グリッド系
[ARC089D Checker](https://beta.atcoder.jp/contests/arc089/tasks/arc089_b) [`np.cumsum`とスライス記法]

#### 動的計画法（DP）
[ABC113D Number of Amidakuji](https://beta.atcoder.jp/contests/abc113/tasks/abc113_d) [行列積]
[CODE FESTIVAL 2018 C 半分](https://beta.atcoder.jp/contests/code-festival-2018-quala/tasks/code_festival_2018_quala_c) [DPの状態に`np.array`]

#### グラフ
[`scipy.sparse.csgraph`](https://docs.scipy.org/doc/scipy/reference/sparse.csgraph.html)には、グラフ関係のアルゴリズムが多数実装されていますので、是非使いたいところです。ダイクストラ法やクラスカル法はもちろん、二部グラフの最大マッチングなどもやってくれます。

# PyPyを用いる
pythonで提出してTLEした場合は、他言語で書き直す前にPyPyでの提出をやってみてください。間に合う可能性があります。

# おわりに

時間がなかったので大分やっつけな記事になってしまいまして、すいませんでした。質問や意見は[@hahho28](https://twitter.com/hahho28)までお願いします。
【rails5】findメソッドとfind_byのメソッドの違い

##findメソッドとfind_byメソッドの違いで躓いたため、メモしておきます。

###findメソッドはidによって値を取得する。

###findの検索条件はidのみ。複数のidを取得出来る。

railsには、 デフォルトで「id」カラムがプライマリキーとしてデータベースに追加されるため、何も設定することなくfindメソッドを使える。

```
基本形
モデル名.find(引数）
引数には、数値型,文字列の数字,数字のリスト,数字の配列を指定できる。
```

```
使い方
User.find(1)　Userテーブルの中から、idが１のユーザーを返す
```


###find_byは特定の条件にマッチした最初の値を取得する。

###find_byメソッドは１つしか値を取得出来ない。複数の条件で検索出来る。

（複数の値を特定の条件で取得したい場合は、whereメソッド）


###使い方

```
Userテーブルの中から、nameカラムがmasaruとマッチした最初のデータを取得する。
User.find_by(name: 'masaru')
```

```
Userテーブルの中から、nameから、nameカラムがmasaruかつ、管理者（adminがtrue）である最初のデータを取得する。
User.find_by(name: 'masaru', admin:true) 
```

```
Userテーブルの中から、作成日が1週間以内のデータを取得する。
User.find_by("created_at > ?", 1.week.ago) 
```

###上記findメソッドを使って実現したいこと

###【管理者としてログインし、ユーザー一覧から一般ユーザーの各ページに飛べるようにする】

showアクションで、find_byメソッドを使っていたので、一般ユーザーのidが取得出来ていなかった。

```
users_controller
@user = User.find_by(params[:id])
```

では、一人のユーザーidしか取得できない。

つまり、
###【管理者としてログインしてから、一般ユーザーの各ページに飛ぶ、という事が出来ない】（管理者自身もid１を持っているので、値を取得するための枠がない)

これを実現するには、複数の値を取得出来るよう、findメソッドを使う必要があった。

```
users_controller
def show
@user = User.find(params{:id])
```

に修正。

これで管理者ユーザーでログインしてからでも一般ユーザーのidが取得でき、各ユーザーの基本時間やプロフィールの編集が出来るようになりました！ 

###findとfind_byの違いまとめ
検索条件の違い
findの検索条件はidのみ、***複数のidを取得出来る。***
find_byは複数の条件を指定したり、id以外でも検索出来るが、***取得できる値は、最初にマッチした１件のみ。***

エラー時の違い
findメソッドは例外を発生させる
find_byはnilを返す

###その他
railsのfindとrubyのfindは全く違う。

rubyのfindは、検索条件に一致した最初の１つ目の要素だけを返す。

rubyのfind_allは検索条件に一致した全ての要素を返す。selectも全く同じメソッド。

any?メソッドは配列の中に条件に一致しているものが一つでもあれば、trueを返し、１つも含まれていないならfalseを返す。

参考
[findとfind_byの違い](https://www.sejuku.net/blog/13000)
VHDの縮小方法

VHDから"未割当領域"を除外するツールについてのメモです。

VHD Resizerがお手軽で便利そうなので、いろんなサイトを探し回るけれどもどれもリンク切れでダウンロードできませんでした・・。

[こちらのサイト](https://blog2.k05.biz/2011/03/fixevhd.html)の追記欄にアーカイブリンクがありました。
文字列のスペース区切りを削除するJavascript in Max

#はじめに
メッセージボックス内のスペース区切りの文字列を削除するMaxパッチがなさそうだったので、[js]オブジェクトから削除する方法を試してみました。
#JSオブジェクト内のコード
```javascript
var outstr = "";

function bang()
{
	outlet(0,outstr);
	
}
function anything()
{
	var inputstr = String(arrayfromargs(messagename, arguments));
	outstr = inputstr.replace(/,/g, '');
	bang();
}
	
````

下のスクショの通り、"this is taito otani"が"thisistaitootani"と出力されるオブジェクトができました。

<img width="239" alt="スクリーンショット 2018-12-13 15.27.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/152481/2963abd1-eddb-6802-f680-aa5bc1ccfa2d.png">

#まとめ
prependオブジェクトなどで文字列を追加するとスペース区切りになってしまうので、これで解決できるシチュエーションがあるかもです。

逆に便利なスペース削除ができるMaxオブジェクトがあれば教えてください。
link_toで指定したIDのページへ飛ばす

少しハマったので忘備録として残します。

1. 飛ばしたい位置(指定したいリンク先の場所)のタグにidを指定

```Ruby:home/index.html.erb
<h1 class="display-4" id="service">サービス概要</h1>
省略
```

---
2. pathの引数に`anchor: "ID名"`を渡してあげる

```ruby:layouts/_header.html.erb
<%= link_to "サービス概要", root_path(anchor: "service"), class: "nav-item nav-link" %>
```
同時にclassも指定することも可能です。

---
以上です。簡単ですね。

上の例の場合だと、ヘッダーのナビリンク内のにサービス概要というリンクがあり、どのページからでもサービス概要をクリックすれば、home/indexページ内のサービス概要と`<h1>`で書かれている場所まで飛ばしてくれます。
Rのデータセットの中身を確認したい

#はじめに
統計学の勉強をしようとR言語を入れたけど何がどうなっているかわからない。
Rには分析や検証に使える様々なデータセットが用意されている。
それらのデータセットはいったいどのような情報を持っているのか、それらを調べる方法をまとめていく。

chickwtsというデータセットを使用する。
ひよこ(?)の「餌の種類」と「体重」の情報が存在するデータセットである。

#str()で内容を表示

```
$ str(chickwts)
```
```
'data.frame':	71 obs. of  2 variables:
 $ weight: num  179 160 136 227 217 168 108 124 143 140 ...
 $ feed  : Factor w/ 6 levels "casein","horsebean",..: 2 2 2 2 2 2 2 2 2 2 ...
```
このデータセットには71のデータがあり(71匹いる)、それぞれにweightとfeedの2つの変数が存在することが読み取れる。
'data.frame'はchickwtsのクラスであり、numとFactorは変数の型のようだ。
そして末尾の「2 2 2 2 2 ...」が何なのかわからない。

また、$ View(chickwts) でExcelのような表を表示させることができる。

#table()で集計

```
$ table(chickwts)
```
```
      feed
weight casein horsebean linseed meatmeal soybean sunflower
   108      0         1       0        0       0         0
   124      0         1       0        0       0         0
   136      0         1       0        0       0         0
   140      0         1       0        0       0         0
   141      0         0       1        0       0         0
   143      0         1       0        0       0         0
   148      0         0       1        0       0         0
   153      0         0       0        1       0         0
   158      0         0       0        0       1         0
   160      0         1       0        0       0         0
   168      0         1       0        0       0         0
   169      0         0       1        0       0         0
   171      0         0       0        0       1         0
   179      0         1       0        0       0         0
   181      0         0       1        0       0         0
   193      0         0       0        0       1         0
   199      0         0       0        0       1         0
(((以下略)))
```
このように表を出力することが可能。また、属性ごとに集計することもできる。

```
$ table(chickwts$feed)
```
```
casein horsebean   linseed  meatmeal   soybean sunflower 
    12        10        12        11        14        12 
```
feedの内容ごとにカウントすることができた。
Dockerで手軽にlibp2p(js-libp2p)を動かしてみる

[libp2p](https://github.com/libp2p)のJS実装である[js-libp2p](https://github.com/libp2p/js-libp2p)を触ってみる

# やること
リポジトリのexamplesにある[transfer](https://github.com/libp2p/js-libp2p/tree/0b75f99d752f7960ce4377d54b098be914600200/examples/transports)を動かしてみる。

# 手順
手順は上記のexampleの説明通りだが、環境構築など面倒なので[Docker化した](https://hub.docker.com/r/sot528/libp2pjstest/)。

```bash
docker run -it sot528/libp2pjstest
```

コンテナに入るのでサンプルスクリプト実行

```bash
root@73b031df5d57:~/work# node 3.js
```

3つのノードが立ち上がり、接続していることが確認できる。

```bash
node 1 is listening on:
/ip4/127.0.0.1/tcp/32907/ipfs/QmVSd89zgVLqC3cUVzN3R3dpA8xextxEFBuACd8uSMXXLM
/ip4/172.17.0.4/tcp/32907/ipfs/QmVSd89zgVLqC3cUVzN3R3dpA8xextxEFBuACd8uSMXXLM
node 2 is listening on:
/ip4/127.0.0.1/tcp/40709/ipfs/QmWe7Md6CyDDXaApaXPijKuXYhpK3uktmMamuw5MzW3zWu
/ip4/172.17.0.4/tcp/40709/ipfs/QmWe7Md6CyDDXaApaXPijKuXYhpK3uktmMamuw5MzW3zWu
/ip4/127.0.0.1/tcp/10000/ws/ipfs/QmWe7Md6CyDDXaApaXPijKuXYhpK3uktmMamuw5MzW3zWu
node 3 is listening on:
/ip4/127.0.0.1/tcp/20000/ws/ipfs/QmeKhkwXHPQ29BzbRJuqzMdkKDzWVwwFreWKRRJDLRvw1H
node 3 failed to dial to node 1 with: Circuit not enabled and all transports failed to dial peer QmVSd89zgVLqC3cUVzN3R3dpA8xextxEFBuACd8uSMXXLM!
node 1 dialed to node 2 successfully
node 2 dialed to node 3 successfully
```

**3.js** をいじることでいろいろと挙動の確認が可能。
ハウスホルダー法による行列三重対角化の可視化

[ヤコビ法による行列対角化の可視化](https://qiita.com/antiplastics/items/17d3885fe1fc033e0e09)の時と同様に、ハウスホルダー法による三重対角化の様子を可視化する。

処理としては、ヤコビ法と似ていて、行列Aにハウスホルダー行列Pを繰り返し両側からかける。

PをAの両側からかけることで、元行列の特定の行・列ベクトルに鏡像変換をかけたことになる。

行列三重対角化以外に、QR分解のための手法としても用いられる。
cf. https://ja.wikipedia.org/wiki/ハウスホルダー変換

```R
library("fields")
library("stringr")

HouseholderMatrix <- function(A, step){
	x <- A[, step]
	y <- rep(0, length(x))
	y[1:step] <- A[1:step, step]
	s <- sqrt(sum(A[setdiff(1:nrow(A), 1:step), step]^2))
	y[step+1] <- - s
	u <- (x - y) / norm(as.matrix(x - y), "F")
	P <- diag(1, nrow(A))
	P <- P - 2 * u %*% t(u)
	P
}

plotA <- function(A, step){
  image.plot(log10(A[, ncol(A):1]+1),
    main=paste0("k = ", step),
    xaxt="n", yaxt = "n")
  if(step != nrow(A)-1){
	  pos <- seq(0, 1, length = nrow(A))
	  text(pos[step], 1-pos[(step+2):length(pos)], "×")
	  text(pos[(step+2):length(pos)], 1-pos[step], "×")  	
  }
}

Householder <- function(A, viz=FALSE, viz.dir=""){
  if(viz){
    if(viz.dir==""){
      plotA(A, 0)
      Sys.sleep(0.2)
    }else{
      png(file=paste0(viz.dir, "/Step0000.png"))
      plotA(A, 0)
      dev.off()
    }
  }
  U <- diag(1, nrow(A))
  step <- 1
  for(k in seq_len(nrow(A)-1)){
  	P <- HouseholderMatrix(A, step)
    U <- U %*% P
    A <- P %*% A %*% P # Update
    if(viz){
      if(viz.dir==""){
        plotA(A, step)
        Sys.sleep(0.2)
      }else{
        png(file=paste0(viz.dir, "/Step",
          str_sub(paste0("000", step), start = -4),
          ".png"))
        plotA(A, step)
        dev.off()
      }
    }
    step <- step + 1
  }
  list(U=U, Sigma=A)
}

# 30×30行列で実験
dir.create("HouseHolder", showWarnings=FALSE)
A <- matrix(runif(30*30), nrow=30, ncol=30)
A <- t(A) %*% A # 対称行列にする
out <- Householder(A, viz=TRUE, viz.dir="./Householder")
```

xは次のステップで0になる予定箇所。
行列Aが徐々に三重対角要素を残して疎な行列になっていく様子がわかる。
![movie.gif](https://qiita-image-store.s3.amazonaws.com/0/17038/8c392558-4d86-d3ee-c600-f14902d66cb1.gif)

ヤコビ法の対角化と比べると、三重対角化は(行列Aの次数)-1分だけ処理をすればいいので、計算がすぐ終わることがわかる。
この三重対角行列にさらに二分法など別の手法を適用することにより、元の行列Aの固有値・固有ベクトルがもとめる。
密行列と比べて要素数も少ないので計算がかなり楽になる。

# 参考
[計算による線形代数](https://www.amazon.co.jp/計算による線形代数-工系数学講座-2-神谷-紀生/dp/4320016009/ref=sr_1_1?ie=UTF8&qid=1544600095&sr=8-1&keywords=計算による線形代数)
[Matrix Computation](https://www.amazon.co.jp/Computations-Hopkins-Studies-Mathematical-Sciences/dp/1421407949/ref=sr_1_1?ie=UTF8&qid=1544600109&sr=8-1&keywords=matrix+computation)
ヤコビ法による行列対角化の可視化

行列の対角化とは、ある正方行列を以下の形に分解すること
cf. https://ja.wikipedia.org/wiki/対角化

```math
A = P^T\Lambda P
```

このような正則行列$P$が存在する場合、相似変換といい、対角行列は$\Lambda$は元の行列Aの固有値になる。

行列対角化を実現するための教科書的な手法としてヤコビ法があり、処理としては、行列Aに平面回転行列P（ギブンス行列）を繰り返し両側からかける。

（全く同じ名前で連立方程式を解く手法があることに注意 cf. https://ja.wikipedia.org/wiki/ヤコビ法 ）

ここでは、各ステップごとに、行列が徐々に対角化されていく様子を可視化する。

```R
library("fields")
library("stringr")

MaxNonDiag <- function(A){
  # To select only upper triangle elements
  diag(A) <- min(A)
  A[lower.tri(A)] <- min(A)
  MaxPos <- max(A) == A
  # Row Position
  k <- unlist(apply(MaxPos, 2, function(x){
    which(x == TRUE)
  }))
  # Columns Position
  l <- unlist(apply(MaxPos, 1, function(x){
    which(x == TRUE)
  }))
  # Return
  c(k,l)
}

GivensMatrix <- function(A){
  R <- diag(1, nrow(A))
  MP <- MaxNonDiag(A)
  k <- MP[1]
  l <- MP[2]
  if(A[k,k] != A[l,l]){
      theta <- 0.5 * atan(-2*A[k,l] / (A[k,k] - A[l,l]))
    }else{
      theta <- pi / 4
    }
  # Return R
  R[k,k] <- cos(theta)
  R[l,k] <- -sin(theta)
  R[k,l] <- sin(theta)
  R[l,l] <- cos(theta)
  R
} 

plotA <- function(A, k, l, step){
  image.plot(log10(A[, ncol(A):1]+1),
    main=paste0("k = ", step),
    xaxt="n", yaxt = "n")
  pos <- seq(0, 1, length = nrow(A))
  text(pos[k], 1-pos[l], "Max!")
  text(pos[l], 1-pos[k], "Max!")
}

Jacobi <- function(A, thr=1E-2, viz=FALSE, viz.dir=""){
  MP <- MaxNonDiag(A)
  k <- MP[1]
  l <- MP[2]
  U <- diag(1, nrow(A))
  step <- 1
  if(viz){
    if(viz.dir==""){
      plotA(A, k, l, 0)
      Sys.sleep(0.2)
    }else{
      png(file=paste0(viz.dir, "/Step0000.png"))
      plotA(A, k, l, 0)
      dev.off()
    }
  }
  while(A[k,l] > thr){
    R <- GivensMatrix(A)
    U <- U %*% R
    A <- t(R) %*% A %*% R # Update
    MP <- MaxNonDiag(A)
    k <- MP[1]
    l <- MP[2]
    if(viz){
      if(viz.dir==""){
        plotA(A, k, l, step)
        Sys.sleep(0.2)
      }else{
        png(file=paste0(viz.dir, "/Step",
          str_sub(paste0("000", step), start = -4),
          ".png"))
        plotA(A, k, l, step)
        dev.off()
      }
    }
    step <- step + 1
  }
  list(U=U, Sigma=A)
}


# 固有値がdiag(3,1)
# 固有ベクトルがc(1/sqrt(2), 1/sqrt(2))と正解がわかっているデータで確認
A <- rbind(2:1, 1:2)
Jacobi(A, viz=TRUE)
eigen(A) # eigenとも一致

# 30×30行列でも実験
dir.create("Jacobi", showWarnings=FALSE)
A <- matrix(runif(30*30), nrow=30, ncol=30)
A <- t(A) %*% A
eigen(A)
out <- Jacobi(A, viz=TRUE, viz.dir="./Jacobi")
```

"Max!"と書かれている非対角要素は次のステップでギブンス回転によって0になる予定箇所。
行列Aが徐々に対角要素を残して値の小さな行列になっていく様子がわかる。

![movie.gif](https://qiita-image-store.s3.amazonaws.com/0/17038/f265954e-c77a-4c75-3525-a5ed27328c89.gif)

ただし、ある非対角要素を0にすることで、他の要素の値が変化するため、一度0にした要素が再び非ゼロになるため、収束するまで計算を繰り返す必要がある。

# 参考
[計算による線形代数](https://www.amazon.co.jp/計算による線形代数-工系数学講座-2-神谷-紀生/dp/4320016009/ref=sr_1_1?ie=UTF8&qid=1544600095&sr=8-1&keywords=計算による線形代数)
[Matrix Computation](https://www.amazon.co.jp/Computations-Hopkins-Studies-Mathematical-Sciences/dp/1421407949/ref=sr_1_1?ie=UTF8&qid=1544600109&sr=8-1&keywords=matrix+computation)
[[Pythonによる科学・技術計算] ヤコビ法による実対称行列の固有値・固有ベクトルの数値計算，数値線形代数](https://qiita.com/sci_Haru/items/dd638e698fb72659951b)
Kubernetesドキュメント翻訳プロジェクトに参加する

本記事は[@nasa9084](https://twitter.com/nasa9084)による[Kubernetes Advent Calendar 2018](https://qiita.com/advent-calendar/2018/kubernetes)の13日目の記事です。
昨日は[@yuanying](https://twitter.com/yuanying)さんの[CVE-2018-1002105 の issue を読んで kube-apiserver に詳しくなろう！](https://qiita.com/yuanying/items/f2dd6ac8252cb87860f7)でした。

---

さて、みなさんは[Kubernetesのドキュメント](https://k8s.io/docs)を読んだことがありますか？この記事を読みにきているような方であれば、まぁ一度くらいは見たことがあるでしょう。
おそらく、日本人である皆さんは[^japanese]英語でドキュメントを読んでいるものとおもいます。しかし、画面の右上に注目していただくと、ドキュメントの言語を変更できるセレクトボックスがあることに気づきます。
そうです。Kubernetesのドキュメントは多言語対応サイトとなっているのです。

現在のところは英語の他には[中国語](https://k8s.io/zh/docs/home/)、[韓国語](https://k8s.io/ko/docs/home/)に対応しています。それぞれ、docs-zhチーム、docs-krチームが翻訳を行なっています。これらは各国の有志による翻訳チームで、実は日本にもdocs-jaチームが存在します。

docs-jaチームでももちろんドキュメントの翻訳作業を進めており、[いくつかのPull Request](https://github.com/kubernetes/website/pulls?q=is%3Apr+is%3Aopen+label%3Alanguage%2Fja)も提出されています。翻訳作業にはどなたでも参加することができます。
現在はproduction環境にマージしてもらうための最小限のページ[^minimum]を翻訳しきることを[マイルストーンに据えて](https://github.com/kubernetes/website/issues?q=is%3Aopen+is%3Aissue+label%3Alanguage%2Fja)います。

## 翻訳に参加するには

翻訳の流れは次のようになっています。

1. [Linux Foundationのアカウントを取得する](https://identity.linuxfoundation.org/)
1. [CLAに署名する](https://identity.linuxfoundation.org/projects/cncf)
1. [websiteのリポジトリ](https://github.com/kubernetes/website)をforkする
1. 適宜ブランチを作成し、翻訳する
1. [websiteのリポジトリ](https://github.com/kubernetes/website)にPull Requestを出す
1. Reviewers[^reviewer]がレビューし、Owners[^owners]がapproveする
1. botがマージする

簡単ですね！現状は手元のエディタで翻訳作業を行なっていますが、翻訳ツールの助けを借りたい場合、[Crowdin](https://crwd.in/kubernetes-docs-ja)プロジェクトは用意してあります[^crowdin]。翻訳語、ファイルをダウンロードしてPull Requestに加えるという運用となっています。

情報交換や打ち合わせは[Kubernetes Slack](http://slack.k8s.io/)の`#kubernetes-docs-ja`チャンネルで行なっています。お気軽に参加してください。

最小一行からPull Requestを受け付けていますので、ぜひ翻訳に参加をお願いします！

---

明日は[@junpayment](https://twitter.com/junpayment)さんです

[^japanese]: 日本人以外の方も読んでくれてるかもしれませんがおそらく大半は日本人でしょう
[^minimum]: とはいってもそれなりに量があります
[^reviewer]: [OWNERS_ALIASES](https://github.com/kubernetes/website/blob/master/OWNERS_ALIASES)にsig-docs-ja-reviewsとして記載されたレビュワーメンバー
[^owners]: [OWNERS_ALIASES](https://github.com/kubernetes/website/blob/master/OWNERS_ALIASES)にsig-docs-ja-ownersとして記載されたオーナーメンバー
[^crowdin]: 正式な採用ではないため、インテグレーションなどは設定されていません。
prometheusポート変更起動方法メモ

# 問題

* 諸事情によりprometheusのデフォルト9090ポートが使えない
* そのためprometheusが起動できない
* しようがないので8080ポートを使う
* しかしなかなか起動できなかった
* 解決したのでメモ

# 結論

* ポートを変更する場合は起動オプションが必要だった

## prometheusの場合

```text:正
$ ./prometheus --config.file=./prometheus.yml --web.listen-address=:8080 &
```

```text:誤
$ ./prometheus --config.file=./prometheus.yml &
```

## node exporterの場合

```text:正
$ ./node_exporter --web.listen-address=:8080 &
```

```text:誤
$ ./node_exporter
```

## alert managerの場合

```text:正
$ ./alertmanager --config.file="alertmanager.yml" --web.listen-address=":8081" &
```

```text:誤
$ ./alertmanager --config.file="alertmanager.yml" &
```

# エラー参考

```
level=error ts=2018-12-13T03:47:00.050290723Z caller=main.go:582 err="Opening storage failed open DB in data/: Locked by other process"
```

* プロセスがファイルシステムを掴んでいるらしい。OS再起動したら治った
UiPathでロボットを共有

UiPathでは、プロジェクトのフォルダ配下に置いてあるファイルが 
パッケージ対象となる為、 
複数ロボットで外出しにしたロボットを共有することができません。

[イメージ図１] 
![Img01.png](https://qiita-image-store.s3.amazonaws.com/0/326011/995531a9-6522-1e5d-12ab-6e4e8dfb748b.png)
※ロボットA内から共通ロボット配下を参照している場合、 
　パッケージ化した際にエラーになります。

小規模のロボットの場合、差ほど不便にはなりませんが、
規模が大きければそれだけ共通化したくなる場面が出てきます。

そこで、今回は、
２つの対応方法を紹介したいと思います。

---
**【対応方法１】**
　元になる共通ロボットを外部に作り、 
　各フォルダ配下にコピーして使用します。
　※この場合、共通ロボットが更新される度に、 
　　各フォルダ配下のファイルを上書きしなければなりません。 
　　**<font color="Red">更新漏れに注意</font>**

<font size="2">[イメージ図２]</font>
 ![Img02.png](https://qiita-image-store.s3.amazonaws.com/0/326011/47a10388-9399-d318-2649-80e2eaaa3d8e.png)

**【対応方法２】**
　各ロボット配下にシンボリックリンクで共通ロボットを設置します。
　※SVN使用時のみ可能 
　SVN上ではシンボリックリンクですが、チェックアウト時には 
　実態（ロボット）が存在する為、 
　結果パッケージに含まれる事になります。 

　※共通ロボットが更新された場合、 
　　**<font color="Red">SVNでの更新が必要になります。</font>** 
　　【対応方法１】と違い、SVNの画面から更新されていないロボットの 
　　確認、更新が容易です。 

[イメージ図３] 
![Img03.png](https://qiita-image-store.s3.amazonaws.com/0/326011/7bd5de2c-bb34-2729-8b09-0b42b370ee51.png)

◆シンボリックリンクの設定方法 

　１．TortoiseSVNのPropetiesを選択する 
　２．Propeties画面で「new」ボタンをクリックする 
　３．「Externals」メニューを選択する 
　４．「new」ボタンをクリックする 
　５．下記内容を設定 
　　　ローカルパス：（リンクを付けるフォルダ） 
　　　　　　　　　　例）共通ロボット 
　　　URL            :（リンク元のパス） 
　　　　　　　　　　例）^/UiPath/共通ロボット 
　６．「OK」ボタンをクリックする 
　７．「OK」ボタンをクリックする 
　８．TortoiseSVNのSVNUpdataで、ファイルを更新する 

　シンボリックリンクを設定したフォルダ配下のファイルが配置されます。

---

いかがでしたでしょうか。
少しでもお役に立てたら光栄です！

まだまだ他にもやり方はあると思いますので、
また、より良い方法を見つけたら、
ご紹介したいと思います。

最後までお付き合いくださり、
ありがとうございました♪
Dockerfile で npm install すると EXDEV を返され通らなくなる問題の解決方法

# 問題
Dockerfile で npm installを行うと以下のエラー。

```bash
npm ERR! EXDEV: cross-device link not permitted, rename '/usr/local/lib/node_modules/pull-stream' -> '/usr/local/lib/node_modules/.pull-stream.DELETE'
```

# 対応
2行に分けていたものを一行にまとめたら解決。

```dockerfile
RUN npm install libp2p libp2p-tcp peer-info async @nodeutils/defaults-deep
RUN npm install  pull-stream
```

↓

```dockerfile
RUN npm install libp2p libp2p-tcp peer-info async @nodeutils/defaults-deep pull-stream
```

# 環境
- `Ubuntu 18.4`

# 備考
- https://qiita.com/muddydixon/items/7e7fa0c58d0fe495ce07
python3でのrss取得

# python3 feedparserでのrss取得方法
## 環境
macOS mojave
python 3.7.0(anaconda)
feedparser 5.2.1
## feedparserのインストール
condaのupdate
```conda update conda```
feedparserの有無確認
`conda list`
なければ
`conda install feedparser`

*anacondaなのでconda。普通ならpip*
## python code
テストフォルダを作成して `mkdir rss-test`
pythonのファイル作成 `touch rss-test.py`

```
# feedparserのインポート
import feedparser

# URLの取得（今回は朝日新聞デジタルからデジタルジャンルの記事を取得）
RDF_URL = "http://www3.asahi.com/rss/digital.rdf"

degital_news_dic = feedparser.parse(RDF_URL)

print(degital_news_dic.feed.title)

for entry in degital_news_dic.entries:
  title = entry.title
  link = entry.link
  print(link)
  print(title)
```
##実行

`python rss-test.py`

```
デジタル - 朝日新聞デジタル
http://www.asahi.com/articles/ASLDD514HLDDUCVL01T.html?ref=rss
今年のグーグル検索ランキング１位は「ワールドカップ」
http://www.asahi.com/articles/ASLDD2W65LDDULFA001.html?ref=rss
グーグルなどの規制強化、政府が新組織　独禁法適用も
http://www.asahi.com/articles/ASLDD3HBMLDDUTIL00M.html?ref=rss
マウント・ゴックス元ＣＥＯに懲役１０年を求刑
http://www.asahi.com/articles/ASLDC4VLSLDCULFA01L.html?ref=rss
中国機器排除、５Ｇでも自主対応促す　携帯各社に総務相
http://www.asahi.com/articles/ASLDC5G3XLDCUHBI01P.html?ref=rss
グーグル＋、閉鎖時期を前倒し　また欠陥発覚
http://www.asahi.com/articles/ASLDD2VZKLDDUHBI00H.html?ref=rss
グーグルの中国再参入、いきなり慎重に「計画はない」
http://www.asahi.com/articles/ASLDD32QWLDDULFA002.html?ref=rss
ソフトバンク通信障害、３０６０万件に影響　過去最大級
http://www.asahi.com/articles/ASLDC61YLLDCUTIL056.html?ref=rss
ユーチューブに警察無線投稿か　岩手の男性、自ら警察へ
http://www.asahi.com/articles/ASLD76R2WLD7UEHF00N.html?ref=rss
「ＬＩＮＥで支持されたメディア」朝日新聞デジタル大賞
http://www.asahi.com/articles/ASLDB40XNLDBULFA00S.html?ref=rss
菅官房長官「国際ルールに整合」　中国通信２社の排除で
http://www.asahi.com/articles/ASLD73SJ9LD7UTIL008.html?ref=rss
知らないのはあなただけ？動画アプリＴｉｋＴｏｋって
http://www.asahi.com/articles/ASLD826DFLD8UHBI009.html?ref=rss
トランプ氏、前国務長官を侮辱　「とてつもないバカ」
http://www.asahi.com/articles/ASLD753B4LD7UTIL022.html?ref=rss
東京や新宿、ＡＩが案内します　山手線６駅で実証実験
http://www.asahi.com/articles/ASLD755SLLD7UTIL027.html?ref=rss
スマホつながらないだけなのに…大混乱　どう備える？
http://www.asahi.com/articles/ASLD74RPVLD7ULFA01S.html?ref=rss
携帯参入の楽天・三木谷氏、通信障害に「安定性を追求」
http://www.asahi.com/articles/ASLD7413QLD7UHBI018.html?ref=rss
マリオットの５億人顧客情報流出、背景に中国のスパイか
http://www.asahi.com/articles/ASLD75CJ6LD7UCLV00M.html?ref=rss
海賊版静止画のＤＬ規制を　文化審議会が意見まとめる
http://www.asahi.com/articles/ASLD64HS7LD6UCVL00D.html?ref=rss
ダフ屋行為に罰則、不正転売禁止法成立へ　来年６月施行
http://www.asahi.com/articles/ASLD73SJTLD7PLFA003.html?ref=rss
京セラ稲盛氏の経営塾、解散へ「一代限りで終わらせる」
http://www.asahi.com/articles/ASLCQ4SY1LCQPTIL00N.html?ref=rss
＃ニュース４Ｕ、始めます　ＳＮＳで声集め、深掘り取材
```
こんな感じでRSS取得ができました。
フォームのinputボックスの内容に数字しか入力できないように制限する

金額の入力欄を作りまして。
その入力内容をつかって合計値の計算とかしたかったので数字以外が入ると都合が悪い。
なので数字しか入力できないようにしました。

```.html
<!-- inputボックスを表示 -->
<input type="tel" id="input_name">

<script type="text/javascript">
  //費用は数値しか入力できない
  $('#input_name').on('input', function() {
    let value = $(this).val();
    $(this).val(value.replace(/[^0-9]+/g, ''));
  });
</script>
```
`.on('input', function { 〜 }`でinputボックスの入力内容を監視し、なにか入力されたら`〜`を実行する。
実行内容は`.replace`で数字以外の文字を削除し、それをinputボックスの値とする、という内容。

正規表現については最初/[^0-9]/と書いていたのですが、その場合は
コピペで入力できるとのご指摘をいただきましたので、
２文字以上コピペしても入力できないように`+`を付け、
コピペした文字列の途中まで文字が入っていても適用できるように/gを記載しています。
（@KeisukeKudo さん、@takaram さんありがとうございました！）
Amazon CloudWatch Logs Insightsでapacheログを解析

11月26日～11月30日にかけてラスベガスで開催された『AWS re:Invent 2018』で発表された機能のひとつ、CloudWatch Logs Insightsを使ってみました。

## 前提 ##

前提として、apacheのcombinedアクセスログをCloudWatch Logsにロググループ"/var/log/httpd/access_log"として蓄積できているものとします。

## クエリを実行してみよう ##

コンソールからCloudWatchを開くと、左のメニューに`ログ`があります。その下階層に`インサイト`が追加されました。これをクリックして、インサイトの画面を開きます。

* 対象のロググループを選んで
* 必要があればタイムスタンプの範囲を指定して
* クエリを書いて実行します。

![cloudwatch.png](https://qiita-image-store.s3.amazonaws.com/0/51921/555965b6-9261-0c29-c95d-2a8fe6366a2f.png)

試しにこんな簡単なクエリを実行してみました。

```
parse '* - * [*] "* * *" * *' as host, identity, dateTimeString, httpVerb, url, protocol, statusCode, bytes
|filter statusCode=500
```

apacheのログはparseクエリで一時的なフィールドとして取り出す必要があります。「クエリのヘルプ」のparseにマウスオーバーするとapacheのcombinedログにそのまま使えるparseが書いてあります。あとはひっかけたい条件をfilterで書いてやればよいです。

## 使ってみた感想 ##

CluodWatch LogsをS3に置いてAthenaに読み込ませて…よりは、はるかに簡単なステップでログにクエリを実行できます。しかし、
<b>必要最低限</b>
のクエリしかありません。私がやりたかったのは、Splunkの置き換えなんですが、さすがにそこまでできてしまうとSplunkの存在意義がなくなってしまいます。

具体的にはrexで正規表現にひっかけた結果をGROUP BYして、だったのですがいまのところは無理でした。

パイプラインで結合してstatsとかは、かなりSplunkを意識しているようなんですけどね。
今後の機能充実に期待です。
QMKでつっかかった所のメモ

# QMK_Firmwareとは

自作キーボード界隈で騒がれてたりなんだったりするファームウェアの事です。  
こちらは[tmk firmware](https://github.com/tmk/tmk_keyboard)を元に進化したファームウェアになります。  
自作するならtmkじゃなくて[QMK](https://github.com/qmk/qmk_firmware)にするといいよー。ってのもある。  
そんな[QMK](https://github.com/qmk/qmk_firmware)のキーの設定で自分がつまった所を書いておいて他の人の役にでも立てばとか思ったやつです。  
ちなみに僕はC言語殆ど理解出来てないのでそのせいもありそう。何が原因か言語の仕様が理解出来てないせいだったら教えてもらえるとありがたいです。(他力本願)  
色々自分が弄っていく上でつっかかった所が増えていく予定、つまり増えないほうがよろしい。  

基本的に普通に各キーを設定しただけで動かなかった場合、その大元の関数を代わりに設定してあげればよいっぽいのでその関数を調べる方法を後で書きます

## Tap-DanceでRESETキーが効かない。

自分の場合Tap-danceを有効にしていて、そのTap-danceの2回タップした時にRESETキーを設定していたらコンパイルは通り、正常に焼けたのにかかわらず、実際にキーを打つと何も入力されない、何かaキーの入力になってる。とかがありました。

### 対策

RESETキーは実際はreset_keyboard()という関数が呼ばれていた。  
そのため、```ACTION_TAP_DANCE_DOUBLE()```を```ACTION_TAP_DANCE_FN()```に変更し、関数を書いた。  

```
before
- [TD_RESET] = ACTION_TAP_DANCE_DOUBLE(KC_NO,RESET)
after
+ [TD_RESET] = ACTION_TAP_DANCE_FN(dance_td_reset)
+ void dance_td_reset(qk_tap_dance_state_t *state, void *user_data) {
+     if (state->count == 2) {
+         reset_keyboard();
+     }
+ }
```

## Tap-DanceでTG()キーが効かない。

自分の場合Tap-danceを有効にしていて、そのTap-danceの2回タップした時にTG()キーを設定していたらコンパイルは通り(ry。

### 対策

同じく関数書いて解消しました。  
何故こうなるのかの根本は調べがつかなかったので、調べたい。  
Tap-danceだと何かある?後で見よう。(めんどう…)    

```
before
- [TD_DEFAULT] = ACTION_TAP_DANCE_DOUBLE(KC_NO,TG(DEFAULT))
after
+ [TD_DEFAULT] = ACTION_TAP_DANCE_FN(dance_td_default)
+ void dance_td_default(qk_tap_dance_state_t *state, void *user_data) {
+     if (state->count == 2) {
+         layer_clear();
+         layer_on(DEFAULT);
+     }
+ }
```

# 終わりに

初投稿なため、腑甲斐無い所は甘く見て頂きたい。  
C言語頑張るーーー。  
とりあえず詰まったら関数そのものを書けばいい感じかな。  
その関数の調べ方を書きます。いつか。
DDD + Clean Architecture で要件の複雑さに立ち向かった話

こちらは[DMM.com Advent Calendar 2018](https://qiita.com/advent-calendar/2018/dmm) 13日目の記事です。
DMM GAMES のプラットフォーム開発に携わっているエンジニアのwkubotaです。

ゲームプラットフォームならではの要件にたいして、最近巷で話題のDDDとClean Architectureを武器に立ち向かった話をつらつらと書いてみようと思います。

## 経緯
ゲームプラットフォームでは普段みなさんがゲームをするための環境（本稿では本番環境と表現します。）とゲーム開発会社さんが、開発中のゲームを一般ユーザーには公開せずに動作させるための環境（本稿ではサンドボックス環境と表現します。）が存在します。  
それぞれの環境をざっくりまとめると以下のようになります。  

|環境|説明|
|:--|:--|
|本番環境|一般ユーザーに公開している。課金を含む全ての機能が利用可能|
|サンドボックス環境|ゲーム開発会社向けで一般公開はしていない。ユーザー管理など機能は部分的あるいは模擬的なもの|

さて、そのようなそれぞれの環境に向けたAPIを提供する際のお話をしようと思います。

## DDD + Clean Architectureで解決したかった問題
既存のアプローチでは、本番環境向けとサンドボックス向けそれぞれ対応する場合、様々な問題が発生していました。
それは以下のようなものです。

### 1. 本番・サンドボックスを別ソースとして管理
だいたいこの方針です。
ただ、２系統を維持していくのは保守運用コストとしては無視できないものですし、差分の管理は時間を追うに従って困難になります。

### 2. 本番・サンドボックスは同一ソースで内部で必要に応じて条件分岐
経験のある開発者なら、既に嫌な予感を覚えているかもしれませんね・・・。
  
```php
if (env->sandbox) {
	// サンドボックス向け処理
} else {
	// 本番向け処理
}
```

この方針がもたらすものはIf文の嵐です。実装の各所に上記のような条件文が入り見通しが悪くなります。[^1]
[^1]: ぶっちゃけ、流石にほとんどこんなことにはしていません。別ソースにするのが多い  

## DDD + Clean Architectureを用いることでどのように問題に立ち向かったのか？
Clean Architecture とは　Robert C. Martin の提唱したDDDを念頭においたアーキテクチャです。
[The Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)
![](https://blog.cleancoder.com/uncle-bob/images/2012-08-13-the-clean-architecture/CleanArchitecture.jpg)
それ、を我々の要件に当てはめると以下のような進め方が出来るのではないかと考えました。
![product_sandbox_clean_architecture.png](https://qiita-image-store.s3.amazonaws.com/0/18012/7d0b91c2-3cfd-0ccc-76d9-f66fc4068d88.png)

上図の概念としては、ドメインモデルは本番環境とサンドボックス環境の差異はなく環境毎の実装は外周部に押し出し、依存関係逆転の法則を使ってドメインモデル側では意識しないで済むようにする。

## 具体的な工夫あれこれ

### 外部データをそのままドメインモデルに持ち込まない
External Interfacesで受け取ったデータはドメインモデルに到達する前に__必ず__ドメインモデルのオブジェクトに載せ替える
DDDを採用しているところでは常識的なことかもしれませんが、今回の要件として環境毎の差異をドメインモデルに絶対持ち込みたくなかったので必ずオブジェクトを持ち替える形を徹底しました。

### 環境ごとの機能の有無の違いを吸収するためにNull Object pattern
ドメインモデル内で環境毎のデータモデルの存在確認やふるまいの分岐をしないで済むように [Null Object Pattern](https://en.wikipedia.org/wiki/Null_object_pattern)を多用する形ですすめました。

## 結果どうなったか？

実装としては、ドメインモデルとして守るべき所と環境毎の差分とで綺麗に収まるべきところが明確になり全体的にスッキリまとまりました。  
ただ、最終的に完全に同一のドメインモデルを提供する方針を時間の関係でとることができず（ドメインモデルだけライブラリかAPIにするのが本当は綺麗だったはず）、本番環境とサンドボックスそれぞれにほぼ同じ実装をもったドメインモデルが存在する形になっています。

## まとめ
DDD と Clean Architecture をビジネス要件が持つ複雑さへの銀の弾丸にするには、自分の力不足で不十分となってしまいましが、
テストコードの書き易さや処理の責任毎の置きどころがハッキリするなど非常にメリットも多い全体のアーキテクチャとすることが出来ました。  
また、今後、保守運用していくなかでより良くするのに手を付けやすい状態にしておけたのは本件における成果だと考えています。

自分たちが選択したアプローチが皆様が普段抱えている問題の少しでも助けになったら嬉しいです。
SIer出身者からみたジーズアカデミー

##はじめに
ジーズアカデミーのスタッフをしています、kanomiです。

2018年。平成最後の…なんて冠がつくことも多い年。
平成一桁生まれのわたしは焦燥感に駆られて（？）転職し、今年の9月にジーズアカデミーに飛び込みました。

前職は何をしていたかというと。
この夏まで、1次請けもしくは2次請けで受託開発を請け負うSIerで5年ほど働いていました。

![SI構造.png](https://qiita-image-store.s3.amazonaws.com/0/317454/38c0fd4e-548d-3259-2320-23176e133317.png)


といっても、エンジニアではなく営業。開発するわけではなく、開発案件を獲ってくるお仕事です。

特にオートモーティブ系の仕事に携わっていて、自動運転とか、高精度地図とか
「近未来！何それかっこいい！！」ということを現場のエンジニアの方から色々と学ぶことができ、
すごくいい経験でした。


さて、この記事では、SIerで5年働いたわたしから見たジーズアカデミーについて、ちょっとだけお話したいと思います。

**注：主観で書いています！SIerについてもこれが全てではないので悪しからず、です！**



##SIer目線から見た、ジーズアカデミー


####▼5年間エンジニアと接してみてわかったこと

前職で営業として接していたお客様はほとんどがエンジニアですし、獲ってきた開発案件に対して一緒に考えるのもエンジニア。
ですので、仕事柄様々なエンジニアの方とお話をしてきました。

その中でも特によく聞いた言葉がこちらです。

**＜エンジニアからよく言われる言葉ベスト3＞**

**1位「やりたいことはあるけど客先の仕事が忙しすぎて、そんな暇ない」**
　⇒自分の好きなものを作って、技術イベントやコンテストに応募したいけど、
　　どうしてもお客様案件が優先になってしまう、ということですね。
　　営業のわたし「お客様案件オナシャス…！」
　　個人のわたし「コンテスト！？ぜったい楽しい！出ましょう！！」
　　…この葛藤を何度したことか。

**2位「営業はエンジニアを商品としか見ていない」**
　⇒実際はそんなこと思ってないのですが、そう言われても仕方ない…。
　　とくにSES営業の方はめっちゃ言われるのではないでしょうか。メンタル鍛えられますよね！笑
　　売上云々より、いちエンジニアとして技術を活かせる仕事にアサインしろ。そりゃそうだ。
　　なまじ技術力が高い人は、なんでも屋さん的な感じでありとあらゆる仕事に入ってもらっていたので、よりそう思うこともあるでしょう。

**3位「自社サービスの開発に携わりたい」**
　⇒転職したいエンジニアが口を揃えて言うことですね。
　　実際、自社サービスを開発している会社に転職したエンジニアも多いです。
　　　
と、まあごちゃっと書きましたが、
とにかく、エンジニアには**「折角磨いた技術があるのに、活かしきれていない！自分のやってみたいことができない！」**という歯がゆさがあるのだなあ、ということが分かりました。

※これはあくまで一意見です。実際にやりたいことやっているSIerのエンジニアもいっぱいいると思います！



####▼SIer営業、ジーズアカデミーを知る。

エンジニアの歯がゆさは痛いほど分かったけど、結局何も解決できないまま。
紆余曲折ありジーズアカデミーに出会ったのが、今年の夏。

「セカイを変えるGEEKになろう」
![qiita用.png](https://qiita-image-store.s3.amazonaws.com/0/317454/1c0575b6-ee2f-e961-f2fa-8cea2eed1d19.png)

いやいやセカイって！？なんかただのプログラミングスクールじゃなさげ…！？？

そんな気持ちで受けたジーズアカデミーの面接の場で言われた、

**「SIer業態が中心のIT産業構造だと、新しいサービスって生まれてこないよね？好きなもの作ろうぜ！」**

シンプルだけど、確かにその通りだなと思いました。

と同時に、わたしが前職の5年でわかった「折角磨いた技術があるのに、エンジニアがやりたいことできていない」という課題の解決に通じるものがあるのでは？と。

- 顧客要求に応えるあまり、自分の技術力を自分なりに活かせる機会がない
- 技術力があるばかりに、本当に活かせる開発ができていない
- こういうサービスあったらいいのに、を実現できる環境にない

それって、物凄くもったいない。
いまのIT産業構造を変えていければ、文句ばかり言われていたわたしでも「自分の磨いた技術で好きなもの作りたい」っていうエンジニアを救うことができるんじゃないかな。

とっっっても烏滸がましくも、そんな風に思ってしまったんです。

SIerにいたときにはきっと気づけなかった、というか、気づいても気持ちに蓋をしてたと思います。


####▼というわけでSIerエンジニアとして働いている人も、

説明会に来てもらいたい！そう思っています。

入学する、しないは別にして（そりゃあ、入学してもらうに越したことはないですが。笑）、
きっとSIerの仕組みの中で、本当はやりたいことあるのに、という想いに蓋をして
盲目的になっているエンジニアも多いんじゃないかなと思うので、その蓋を開けるお手伝いができたらいいなあ、なんて思います。



##さいごに

偉そうなことを色々書きましたが、今のところわたし自身何か成し遂げられているわけではないです。
が、日本のIT業界のあり方がちょっとずつ変わっていく、そんなお手伝いをジーズアカデミーで出来たらいいなという思いを変わらずに持ち続けて、来年も頑張ります。

（結局エンジニアの皆さんに助けられてばかりなのは前職と変わらなくて、自分の力不足を実感中。。）

ともあれ、今年もあとわずか。皆さまありがとうございました！
2019年もよろしくお願いいたします！！
複数のViewportのスクリーンショットをコマンド一回でまとめてとるためのCLIツールをつくった

レスポンシブデザインのサイトの動作確認をしたいときに、マウス操作で人差し指が痛くなることありますよね。

というわけで、コマンド一発でスクショをまとめてとるCLIツールを作りました。

https://github.com/tilecloud/shootbot

## 使い方

```
$ shootbot https://example.com/
```

上のコマンドを実行すると、あらかじめ定義されている `1200`, `992`, `768`, `576` という4通りのウインドウ幅で、`https://example.com/` のスクリーンショットを保存します。

ウインドウ幅は、コマンドラインオプションで以下のように指定することも可能です。

```
$ shootbot https://example.com/ -v 1200,320
```

高さの指定がない場合、全ページのスクショをとりますが、以下のように高さを指定することもできます。

```
$ shootbot https://example.com/ -v 1200x800,320x480
```

あと複数の URL を指定することも可能です。

```
$ shootbot https://example.com/ https://example.jp/
```

デフォルトではレンダリングエンジンに Chrome を使用していますが、Firefox を指定することもできます。

```
$ shootbot https://example.com/ -b firefox
```

たとえば多言語サイトでは、以下のように言語を指定することも可能です。

```
$ shootbot https://example.com/ -l ja
```

ヘルプは以下の通り。

```
$ shootbot -h
Usage: shootbot [options] <URL ...>

Take screenshots with multiple viewports with headless browser.

Options:
  -V, --version                     output the version number
  -b, --browser <browser>           `chrome` or `firefox`. The default is `chrome`
  -v, --viewports <viewports>       Viewports to take screenshots. e.g, `--viewports 1200x800,320`.
  -l, --accept-language <language>  The language. The default is `en`.
  -w, --waitfor <seconds>           The number of seconds to wait for saving screenshots. The default is `3000`.
  -h, --help                        output usage information
```

## インストール方法

```
$ npm install -g @tilecloud/shootbot
```

## 設定ファイル

コマンドラインオプションの初期値を設定ファイルでカスタマイズすることも可能です。

`~/.shootbot.json`

```
{
  viewports: '1200,320',
  browser: 'chrome',
  acceptLanguage: 'ja',
  waitfor: 3000,
}
```

## 既知の不具合

### Firefox では言語指定ができない

puppeteer-firefoxというモジュールを使っているのですが、リクエストヘッダをごにょごにょするためのメソッドが実装されていません。

同様にレスポンスヘッダーも取得できないので、もしかしたら Firefox での制限が今後増えるかも。