OmniAICreator/Qiita-1.07M huggingface dataset:
なぜサーバAPIプログラムはJavaではなくGoなのか？

# 背景

最近、プロジェクトのアプリケーション開発で選択する言語で迷う事が多い。
今一度なぜGoでアプリケーションを書くべきなのかをアーキテクトな視点でまとめてみる。
特に、既存あるいは新規プロジェクトで、サーバアプリケーションをjavaで開発すべきかGoで開発すべきか、という議論から始まる事が多い。
特にサーバサイドをコンテナ化していく、という際にAPI用プログラムにGoを選択する。
JavaではなくGoを選択する理由とは何なのか。

# なぜ、「ナウいGo使おうぜ」では満足しないのか

もちろん、新しい技術を採用し知見を溜めたい。
今後の潮流にのっかるために、目の前のプロジェクトをお試しとしてGoを選択する、という案もある。
一方で、既に技術者や知見が残っている、安全性の高い言語で目の前のプロジェクトを安全に終わらせたい、という人間も少なからずいる。
そういった人間を説得しなければならず、そういった人たちには「新しいこと」は害悪である。
彼らは分からないことが怖い。新しい技術だからこそ、採用を見送りたく思うのである。
だから、新しい言語を選択したときに考慮しなければならない点、デメリットについて考えなければならない。

今回はマネジメント視点は除外し、サーバアプリケーションを開発する、という視点でのメリットとデメリットを考えてみた。

### Goのメリット

* コンテナの起動速度が非常に速い。耐障害性を考えた際に～分で新しいコンテナが起動するJavaと、秒で新しいコンテナが起動するGoではやはり後者にメリットを感じる。
* ~~javaであるgcがないこと。~~ Javaと比べてGCによるオーバーヘッドが小さいこと。オンラインシステムでGcにこれまでやられて来たよね。

### Goのデメリット

* オブジェクト指向ではないこと。


ここで、「オブジェクト指向でないこと＝デメリット」と考える具体的な理由は何なのか？

# なぜオブジェクト指向だったのか

C言語だった我々があるときjavaを手に入れた。その時にそもそもCで感じていた課題感とJavaのメリットは何だったのか。ドンピシャの本があったので読了
『オブジェクト指向でなぜつくるのか』 (平澤 章/日経BP)

以下、上記の本の要旨。

## C言語からJavaに世界が流れた理由

### Step1. 機械語からアセンブリ言語

* 機械言語は人間には理解しにくい。人間で理解できる言葉で書けるようアセンブリ言語が生まれた。アセンブリ言語からコンパイルにより機械語に変換するようになった。

### Step2. アセンブリ言語から高級言語

* メモリ上などのコピー処理の手順を記載する必要があるなど、アセンブリではまだ記載が複雑だった。そのため、更に高級な言語が作られた。
* Cobolは申請書のようなフォーマットで書くことを目指して。

### Step3. 構造化プログラミング

ポイントは以下2点

* 更に分かりやすく作成するために考案された。
* GOTO死すべし

プロジェクトを分かりにくくしている元凶であるGOTO分を廃止。ロジックを逐次進行、条件分岐、繰り返しの3つのみで表現することを提唱した。そもそも、それまではプログラムが小さくメモリを利用しないことが必要とされていた。そのため、分かりやすさよりトリッキーなコードだった。 分かりやすさを考えた場合、GOTOは廃止したほうが良い。

#### 保守性の高いサブルーチンの考え方

サブルーチンの独立性を高めて保守性を高める必要がある。
 
重要なのは、サブルーチンの独立性を高める方法は呼び出し側とサブルーチンで共有する情報を少なくしたい。ただし、共有する情報をグローバル変数とし、全体から参照されてしまうことでグローバル変数の書き換えについて書き換え元を特定できず、デバッグに時間がかかる。そのため、外部から参照されないローカル変数が発明されし、値渡しを前提とした。これで、サブルーチンが勝手に他のサブルーチンが参照している値の書き換えをしないようになった。
 
#### ここで残った問題点 

* グローバル変数問題：長期的に必要な値はプログラムを書くために必要。ただし、ローカル変数は関数消えたら消えてしまう。結局グローバル変数は残る。そのため、グローバル変数をどこから参照しているか、影響範囲を調べるためにロジックをすべて調べなければならない。

* 貧弱な再利用：サブルーチン程度しか再利用されない。より大規模な再利用が必要。

### Step4. オブジェクト指向

外部から参照される変数、手続きをクラス化してまとめた。
クラスの効用-まとめる、隠す、たくさん作る。これにより、大規模な再利用ができるようになった。

## そして、Goを選択する理由とは？

このオブジェクト指向の流れを踏まえたうえで、言語選択について考えなければならない。
結果、Goのオブジェクト指向でないことがデメリットとなるのは、条件がある。

* 外部から参照される変数、手続きをクラス化してまとめる必要があること
* フレームワーク化してより大規模な再利用が必要となること。

この2つが必要となるとき、Javaが力を持つ。

**しかし、「サーバサイドをコンテナ化していく、中で、サーバサイドのAPI用プログラムにGoを選択する」という場合はどうだろうか？**

上記を考えた時、APIを設計する、という行為の中に上記オブジェクト指向で対応した問題点が内包されている。

#### APIのRestの考え方

APIではRESTFulという考え方がある。

詳細は割愛するが、RESTFulAPIでは機能を(ドメイン指向などありますが)最小単位とし、CRUDをHTTPのプロトコルで表現する
APIを設計する。これががそもそもオブジェクト指向におけるクラスの作成に似ている。
APIのバックエンドにデータベースを持つことにより、長期的なデータの保存が可能となる。
APIのインターフェースを設計することにより、外部からなんの情報が参照され、更新されるかが明確になる。
tokenのscopeにより制御範囲を明確にすることにより、誰に何を提供しているかが明確に判断できる。
グローバル変数変更する際、影響範囲を調べるためにロジックを全て調べなければならない、問題はAPIのインターフェースを変える際にv1/v2とバージョンアップすることにより、
古いインターフェースを守りながら、新しいインターフェースを提供することができる。

# 結論

つまり、APIの設計をする、ということがオブジェクト指向における隠ぺい化を担っている。
APIの設計をするということが、オブジェクト指向のクラスを分類する、という行為と似ているのだ。

その前提をもって、設計されたAPIの実現であれば、Goによる開発のメリットを受けられるのではないか。

マイクロサービスアーキテクチャ、を実現するためにAPIを実現するときに、軽量かつ高速なGoという言語がその真価を発揮する。メリットを享受し、デメリットをより上位の設計で吸収することができる。

と、考えてサーバAPIの実装はGoに限ると思っています。
プロキシ環境下でGrowiから社内のMattermostにwebhookで通知

## はじめに
どうも！生産技術部のエンジニアです。GrowiとMattermostをひとつのサーバに同居させ、社内のプロキシ環境下で、Mattermost宛てのwebhookをしようとしたところ、うまく通知が飛ばない問題がありました。解決する方法を紹介します。

## 環境
* CentOS : 7.6.1810
* Docker-CE : 19.03.1
* Docker Compose : 1.25.0
* Growi :以下
![systeminfo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451049/52d07779-1788-77bf-c2cd-d96ed5b1bac7.png)

**※現在、Growiのバージョンは3.7.2が最新ですが、webhookの設定ができなかったため、バージョンを落としています。この問題についてはSlackにて連絡し、即座に修正いただきました。お忙しい中ありがとうございました。
[fix notification setting can't update without slack token #1849](https://github.com/weseek/growi/pull/1849)**

## 前提条件
Growiの導入が実施済みであること。プロキシ環境下で立ち上げる場合は以下を参考にしてください。

[「プロキシ環境下でDocker Composeを用いてGrowiを立ち上げる」](https://qiita.com/TomoyukiSugiyama/items/94e7f43f93215146f4d2)
ただし、以下の様にgrowiのバージョンを指定して導入しました。

```dockerfile
# FROM weseek/growi:3
FROM weseek/growi:3.7.0
```

## まず試したこと
[mattermostの公式ドキュメント](https://docs.mattermost.com/developer/webhooks-incoming.html#simple-incoming-webhook)を参考にcurlコマンドを使って、webhookが正常に動作しているか確認しました。
### 1.growi,mattermost同居のサーバ⇒mattermostにcurlを実行

```bash
curl -i -X POST -H 'Content-Type: application/json' -d '{"text": "Hello, this
 is some text\nThis is more text. :tada:"}' http://<サーバIP:ポート>/hooks/xxx-generatedkey-xxx
```
通知できず失敗
### 2.社内にある別PC⇒mattermostにcurlを実行
コマンドは１と同様。通知できず失敗。どうやらプロキシを使っているからうまく届いていない様だ。

### 3.プロキシを使用しないように設定し、curlを実行

```bash
curl --noproxy <サーバIP> -i -X POST -H 'Content-Type: application/json' -d '{"text": "Hello, this
 is some text\nThis is more text. :tada:"}' http://<サーバIP:ポート>/hooks/xxx-generatedkey-xxx
```
**--noproxy**オプションを追加することで、growi,mattermost同居のサーバからでも、社内にある別PCからでも通知成功。あとは、growiにnoproxyを設定するだけ！

## noproxyを設定し、growiからwebhookする
Dockerfileに環境変数を設定することで、解決します。

```dockerfile:growi/Dockerfile
ENV http_proxy 'proxy.example.com:8888'
ENV https_proxy 'proxy.example.com:8888'
# 以下の行を追加
ENV no_proxy '<サーバIP>'
```

docker-composeでbuildし直し、動作確認すると、うまく通知が出来るようになりました。

## 最後に
これでwebhookも利用でき、必要な設定がある程度完了しました。これで運用が開始できます。

ただし、
社内では、growiでサポートされていないIEしか使わない人がほとんどなので、ここが一番の問題ですｗ みんなChromeに乗り換えてくれえええ

## ご参考
* [mattermost #Simple Incoming Webhook](https://docs.mattermost.com/developer/webhooks-incoming.html#simple-incoming-webhook)
* [growi #アーキテクチャ](https://docs.growi.org/ja/dev/plugin/architecture.html#%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3)
【Git】ベアリポジトリとノンベアリポジトリ

# ベアとノンベアの違い
今回はリポジトリの概念であるベアとノンベアについて説明して行きます。

### ベアリポジトリ
ワーキングディレクトリを持たない、Gitの更新情報だけを持っているリポジトリ。

### ノンベアリポジトリ
ワーキングディレクトリを持つリポジトリ。

つまりベアリポジトリはGitの更新管理をするための物で、ノンベアリポジトリは作業用のフォルダやファイルなどの情報を持つ物ということになります。

# ベアリポジトリとノンベアリポジトリの仕組み
**ベアリポジトリ集中管理型**
![16144747077_787354afda_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357475/081fd68e-3897-164f-0692-735d349777aa.jpeg)
ベアとノンベアの仕組みは上記の画像の通り、ローカルからのプッシュは全てリモートのベアリポジトリに対して行い、その後ノンベアリポジトリがベアリポジトリからプルして情報を更新するという仕組みみたいです。

**ノンベアリポジトリ管理型**
![16328853931_990fb4c068_z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357475/9794568c-d261-fe15-f6ec-fd21682f09ad.jpeg)
作業PCが一つだけで複数人で開発しないなら、上記のようにリモートにノンベアリポジトリを作り作業することができます。
ただ実際にやると警告が出るみたいで、またGitにはファイルロック機能がないので、複数人で使用する場合はデータに不整合が生まれるので、基本的にはベアとノンベアを使い分けてGitを管理した方が良いみたいです。

# ベアリポジトリとノンベアリポジトリの切り替え
各当のノンベア・ベアリポジトリのあるディレクトリまで移動したとした場合

```
//non-bare repositoryからbare repositoryに変換
git config core.bare true

//bare repositoryからnon-bare repositoryに変換
git config core.bare false

```
# 参考
https://www.nekotricolor.com/entry/theory-of-bare-and-non-bare-repository-manage-wordpress-themes-with-git
https://qnighy.hatenablog.com/entry/2017/02/25/154752
【Rで自習統計学】公務員の給与調整や消費者物価指数の計算【ラスパイレス指数】



統計検定くらいでしか使う事ないと思いますがメモとして。

# ラスパイレス指数とは

ドイツのラスパイレスさんが作った指数
物価に対してラスパイレス指数を使う時は、ここでは「ラスパイレス物価指数」と呼ぶことにする。
数量に対してラスパイレス指数を使う時は、ここでは「ラスパイレス数量指数」と呼ぶことにする。

ラスパイレス価格指数は統計検定では基準年の物価と比較年の物価の問題として出てきます。


# ラスパイレス価格指数
>
例：2015年および2016年の1世帯当たりの牛肉と豚肉の購入量と購入時の金額を調べた。
2015年 : 牛肉 6200 g 340円/100 g : 豚肉 19865 g 149/100g
2016年 : 牛肉 6400 g 340円/100 g : 豚肉 20418 g 144/100g


これをラスパイレス指数に変換することで総合的な価格動向をとらえることが出来ます。
2015年を基準として、2016年の指数を計算すると、


```r
df <- data.frame(price_2015=c(340,149),
                 price_2016=c(340,144),
              quantity_2015=c(6200,19865),
              quantity_2016=c(6400,20418))

numerator<- df$price_2016 * df$quantity_2015
denominator<- df$price_2015 * df$quantity_2015
sum(numerator)/sum(denominator)
```

```
0.98
```

基準年の数値を100とするため、100を掛け算するので

```
0.98 * 100 = 98
```

2015年の物価に比べると、2016年は物価が少し下がっていることが分かります。
上記の例では2016年に豚肉の値段が下がっているので物価が下がっているというざっくりとした指標はあっているように思います。



別の視点で肉の流通量はどうなっているのか？を考えましょう。

# ラスパイレス数量指数

価格と数量を入れ変えるだけです。

```r
numerator<- df$quantity_2016 * df$price_2015
denominator<- df$quantity_2015 * df$price_2015
sum(numerator)/sum(denominator)
```

```
1.029 * 100 = 103
```

肉の流通量は上がっているということが分かりました。


# 公務員の給与計算のラスパイレス指数

公務員の給与の診断のためにラスパイレス指数が使われているそうです。
国家公務員の年齢や勤務年数などから層分けして人数を集計する。
地方公務員も同じような層の人が同じような人数で働いていると仮定して、
国家公務員と地方公務員の給与差がどのくらいかを計算することで、特定の地域の公務員が安すぎる（高すぎる）給与でないかを調べることができる。

人数を国家公務員基準で決めているのでザックリとした比較になるが、給与設定が適切であったかどうかの指標にはなる。

## 地方公務員の給与が安いとき---を仮定したデータ

```r
df <- data.frame(salary_government=c(300,400,500,700,800,1200,1500),
                 salary_local=c(300,350,400,500,550,600,700),
                 number_of_government=c(50,40,30,20,20,20,10))

numerator<- df$salary_local * df$number_of_government
denominator<- df$salary_government * df$number_of_government
(sum(numerator)/sum(denominator) ) * 100
```

```
70.43
```

## 地方公務員の給与が高いとき---を仮定したデータ

```r
df <- data.frame(salary_government=c(300,400,500,700,800,1200,1500),
                 salary_local=c(400,500,800,1200,1500,1600,1700),
                 number_of_government=c(50,40,30,20,20,20,10))

numerator<- df$salary_local * df$number_of_government
denominator<- df$salary_government * df$number_of_government
(sum(numerator)/sum(denominator) ) * 100
```

```
145.2
```

# 実際の公務員は

国家公務員の給与から離れすぎないように調節をするため、このように100から大きく離れた値はとらないようです。
平成31年の集計結果は総務省のページから参照できます。

```
https://www.soumu.go.jp/menu_news/s-news/01gyosei12_02000001.html
```

# ついでに

ラスパイレス指数が出てきたらパーシェ指数とフィッシャー指数についても簡単にメモ

## パーシェ指数

公務員の給与の話で国家公務員の人数と地方公務員の人数の年齢・学歴・勤続年数などが同じと仮定してラスパイレス指数を計算していましたが、地方公務員の人数分布の方を優先して給与を比較したいときに使える。

計算例としては先ほどのお肉の話を使う。

```r
df <- data.frame(price_2015=c(340,149),
                 price_2016=c(340,144),
              quantity_2015=c(6200,19865),
              quantity_2016=c(6400,20418))

numerator<- df$price_2016 * df$quantity_2016
denominator<- df$price_2015 * df$quantity_2016
(sum(numerator)/sum(denominator) ) * 100
```

```
0.98
```

この例ではほとんど変わりませんが、2016年の数量をもとに2016年と2015年の価格を比較している。


## フィッシャー指数

```math
\begin{align}

フィッシャー指数 =\sqrt{ラスパイレス指数　×　パーシェ指数}

\end{align}
```

ラスパイレス指数とパーシェ指数の幾何平均
基準側と比較側の数量や人数分布のどちらかを優先していたが、幾何平均をとることで平均的な値を求めたもの。

# おわり
IIJmioで低速モードを回避する

## 前段

諸事情でネット環境のない場所におり、ネット開通までの10日間をテザリングでしのぐ必要が出てきたので、
調べた内容をまとめておく。

## 1日のデータ通信量
 
テザリング環境で1日仕事して、通信量は1.6GB〜2GB程度
・meetにテレカン 6本
・10時〜21時までテザリングでネット利用

## 低速モードになる制限
> 下記の条件に当てはまる状態で3日あたりの通信量が「366MB」を超えてしまうと、通信速度を制限する場合があります。
> ・クーポン残量がない
> ・クーポンをOFFにしている状態（最大200kbpsでの通信時）
> ・また、IIJmioモバイルサービス タイプAをご利用の場合、クーポンのON/OFFに関わらず、直近3日間あたりの通信量6GBを超えた場合も通信速度の制限を行う場合があります。
https://help.iijmio.jp/s/article/000001770

## 考察
公式によれば、クーポン（データ通信量）残量が残っていれば良いらしい。
ファミリーシェアタイプ契約なので、は12GB/月まで利用できる。
かつ、タイプD（docomo回線）での契約のため、タイプA（au回線）の制約にもかからない。
https://www.iijmio.jp/hdd/spec/typed.jsp
ネット開通が4/17（金）なので後10日しのげれば良いと考えると、大容量オプションに申し込めば回避できると思われる。

## 対策
今月だけ「データオプション 20GB ＋3,100円/月(税抜)」を申し込めば、
ネット開通までの 4/17（金）あと10日間はまかなえるはず（低速モードにもならないはず）

## 注意点
https://help.iijmio.jp/s/article/000001965
最低利用期間はご利用開始月の翌月末日までとなります。
例：2017/6/5 利用開始の場合、2017/7/31 が最短解約日となります。
この場合6月はデータ量 / 月額料金 共に日割りとなり、7月の料金は満額発生します。

ので、本日申し込みしたので、5/31に忘れずに解約する必要がある。
slackの remind で 5/31にアラート飛ばすようにしておいたので未来の自分に期待しておく。


2020/04/09 追記

タイプD契約だったので、直近3日間のデータ使用量が6GBを超えても低速モードにならないことを確認済

| 対象日 | 高速通信利用量 | 低速通信利用量 |
|:--|:--|:--|
| 2020年04月09日 | 482MB | 0MB |
| 2020年04月08日 | 2722MB | 0MB |
| 2020年04月07日 | 2657MB | 0MB |
| 2020年04月06日 | 1805MB | 0MB |
Ansible学習用Dockerコンテナの作成

# 概要

Ansibleの実行環境にVagrant+Virtualboxを使っている例が多いと感じたものの，
せっかくなのでDockerで環境を作ってみました．

# 環境

- Mac OS X 10.15
- Docker version 19.03.5

# 作成手順

まずは普通にインストールする場合のコマンドを並べ，最後にDockerfileに落とし込んだ上でビルドします．

## 元イメージの決定
今回はCentOS7で作ってみます．
他OSでも問題ないですが，以下の手順は適宜読み替えて下さい．

## ansibleのインストール
CentOS7でansibleをインストールするにはepelリポジトリを追加する必要があるため，以下コマンドで追加した上でインストール．

```bash
yum install -y epel-release
yum install -y ansible
```

## sshのインストール

CentOS7のイメージにはsshサーバ/クライアントが含まれていないため，これらをインストール．
ちなみにサーバは`openssh-server`ですが，クライアントは`openssh-clients`(末尾にsが必要)なので注意(自分はここでハマり，コンテナ起動後にsshコマンドが打てず泣きました)．
`sshpass`はパスワード認証の際に必要．

```bash
yum install -y openssh-server
yum install -y openssh-clients
yum install -y sshpass
```
## その他のコマンドのインストール

無くても良いものの，あると便利なコマンドをインストール．
自分はIPアドレスの確認に`ip`コマンドを使いたいので，追加でインストールしました．
他に欲しいコマンドがあれば追記していきます．

```bash
yum install -y iproute
```

## 軽量化

yum関係の不要なキャッシュを削除することで，イメージを軽量化します．

```bash
rm -rf /var/cache/yum/*
yum clean all
```
## sshの設定

rootログインの許可，rootパスワードの設定等を行います．
あくまで検証用なので，セキュリティ的な観点は無視しています．

```bash
sed -ri 's/^#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config && \
    echo 'root:password' | chpasswd && \
    ssh-keygen -t rsa -N "" -f /etc/ssh/ssh_host_rsa_key
```

## sshdの起動

sshの設定が終わったので，sshdを起動します．

```bash
systemctl start sshd.service
```
## Dockerfileに落とし込む

上記までの内容をDockerfileに書くと，以下のようになります．

```dockerfile
FROM centos:7

RUN yum update -y && \
    yum install -y epel-release && \
    yum install -y \
      ansible \
      openssh-server \
      openssh-clients \
      sshpass \
      iproute && \
    rm -rf /var/cache/yum/* && \
    yum clean all && \
    sed -ri 's/^#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config && \
    echo 'root:password' | chpasswd && \
    ssh-keygen -t rsa -N "" -f /etc/ssh/ssh_host_rsa_key

CMD ["usr/sbin/sshd", "-D"]
```

## イメージのビルド

以下のコマンドで上記のDockerfileからイメージをビルドします．

```bash
docker build -t <イメージ名> .
```


# 完成

ビルド完了後，`docker run`でコンテナを作成し，ansibleがインストールされていることを確認．

```bash
$ docker run -itd --name test --rm --privileged <イメージ名> /sbin/init
$ docker exec -it test /bin/bash
$ ansible --version
ansible 2.9.6
///省略
```

sshサーバ，クライアント両方を入れているので，コンテナを2つ起動することで一方からもう一方をansibleで操作することができます．
[Ruby]fizzbuzz問題

#fizzbuzz問題とは
数値が3の倍数であれば、戻り値は”Fizz”
数値が5の倍数であれば、戻り値は”Buzz”
数値が3の倍数であり5の倍数でもある場合は、戻り値は”FizzBuzz”
上記のどれも満たさない場合は、その数値自体を戻り値にする
というもの。転職活動時に簡単な問題として出題されるとなんどか見たので、復習がてら解いて見ました。

##rubyで解く
まず、メソッドを作ります。

```
def fizzbuzz(num)
end
```

次にif文で条件分岐させます。

```
def fizzbuzz(num)
 if num % 3 == 0 && num % 5 == 0 
   puts ”FizzBuzz”
 elsif num % 3 == 0
   puts ”Fizz”
 elsif num % 5 == 0
   puts ”Buzz”
 else 
   puts num
 end
end
```
上から順に、

- numを３で割った余剰が0と等しい　かつ　numを5で割った余剰が0と等しい(num % 3 == 0 && num % 5 == 0)
- numを３で割った余剰が0と等しい（num % 3 == 0）
- numを5で割った余剰が0と等しい（num % 5 == 0）
- どれにも当てはまらない場合、numを出力

という風に条件分岐させました。
次は1から100まで繰り返してnumに代入させます。繰り返しなので、each文を使うことにします。

```
(1..100).each do |num|
 def fizzbuzz(num)
  if num % 3 == 0 && num % 5 == 0 
    puts ”FizzBuzz”
  elsif num % 3 == 0
    puts ”Fizz”
  elsif num % 5 == 0
    puts ”Buzz”
  else 
    puts num
  end
end
```

(1..100)とすることで、「1~100の範囲で」といった意味がつきます。そしてeachでそれをひとつずつ取り出して num に代入していきます。
最後に `puts fizzbuzz(num)`　を追加してあげれば完成です。

```
num_max = 100
(1..num_max).each do |num|
  def fizzBuzz(num)
    if num % 3 == 0 && num % 5 == 0
      puts "FizzBuzz"      
    elsif num % 3 == 0
      puts "Fizz"
    elsif num % 5 == 0
      puts "Buzz"
    else
      puts num
    end
  end  
  puts fizzBuzz(num) 
end
```
[リアルタイム]KinesisからのLambdaが遅延した！！　その時の対処は？

# 何が起きたのか
リアルタイムを実現するアーキテクチャを以下のように組みました

逐一流れてくるデータソース(企業秘密)→Kinesis→Lambda→DynamoDB

データソースにもDynamoDBのデータの双方に書き込みのタイミングのタイムスタンプが入っていました。そのタイムスタンプがずれてたんです！

それも**1時間**。果てどうしたものか・・・

# AWSがヒントを提供していた
この遅延、実はメトリクスで分かったんです。そのメトリクスは

**IteratorAge**

です。Kinesisでも*IteratorAgeMilliseconds*としてメトリクスに書かれていました。
このIteratorAgeは

＊＊ 読み込んだ時刻と処理時刻の差分

の事のよう。つまり、「入った時間と出る時間の差分」つまり、Kinesis+Lambdaのリアルタイム処理の「遅延」を表していることになると至りました。

「Amazon CloudWatch による Amazon Kinesis Data Streams サービスのモニタリング」
https://docs.aws.amazon.com/ja_jp/streams/latest/dev/monitoring-with-cloudwatch.html

# そして答えも提供していた
「Lambda 関数の IteratorAge メトリクスが上がるのはなぜですか ?」
https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-iterator-age/

この中に書いてある大事なのは「バッチサイズ」「シャード」「Duration」

## バッチサイズ
バッチサイズが小さすぎると、その分多くのlambda起動が必要で、上限数による処理の限界があるのはもちろん、起動時間などのその他の時間も多く発生していまします。秒を争うリアルタイム処理ではこのその他の時間も馬鹿になりません。

## シャード
一回に処理できる出口の数。蛇口が多い層がそりゃいいですよねって話。Lambdaの同時実行数が気になるところですが、上限緩和は可能なのでRealTimeの称号に勝るものはありません。

## Duration
リアルタイム処理では「1秒間に何データ処理できるか」が大事になります。処理時間が長引けば当然「意秒間に処理できるデータ数」は減っていきます。これは短いに越したことがない

## おまけで「Lambdaのバッチウインドウ」
これは時と場合によると思います。「何秒ごとに処理をするのか」といった設定になります。これが

*1秒間に入ってくるデータ数＞1秒間の処理できるデータ数*

となると当然未処理データが溜まっていきますので**遅延が発生する**結末を迎えます


# 結局何をしたのか
ここまできて私たちがしたこと

* シャードを1→4に
* バッチサイズを10→100へ
* lambdaのメモリを254MBへ

と変更しました。
最初の設定、**リアルタイムを舐めてる**としか言えないレベルの設定でしたねｗ

これにて通常時はめでたく1秒以内を実現。めでたしめでたし。。。


# しかし、これだけでは終わらなかった
このリアルタイム処理、夜の約4時間は停止していたのですが起動直後に**大遅延が発生する**トラブル発生。
## 原因は停止直後からのデータ
Kinesisは24時間データを保管しておく設定でした。なので、停止直後から起動直前までのデータがはKinesisに存在していました。。これらから順に処理されていたために、その後の処理が後回しになり遅延が発生。

## lambdaの設定を変更
「Maximum age of record (レコードの最大期間)」というTriggerの設定項目があります。
ここがデフォルトでは7日間。このままでした。
これだと、処理対象は「7日前」からになりますので、停止から起動までの4時間は当然処理対象となってしまいます。これが遅延の原因でした。

止まってる期間のリアルタイム処理は処理しないで良い仕様なので、最小値の60秒に設定。1分前のデータしか対象にならないようにしました。

# これで晴れて安定稼働

# 最後に
リアルタイムの処理では当たり前の観点ですが、この点がすべてインフラで設定できてしまうのはさすがクラウドと感心してしましました。
またこれも常識ですが、リアルタイムの処理とはいえ、集計はある程度まとめて行う必要がある（バッチサイズとか）のでアプリの設計も意識しなければならないなぁと感じました


ご静聴ありがとうございました
テレワークを楽しく！バ美肉おじさんがテレワークする方法

お疲れ様です！

新型コロナの影響により、外出自粛が求められるようになってきました。
弊社でもその状況を鑑みて、史上初のテレワークを実施しています。

しかし、家で一人で過ごすというのはとても退屈なものです。
日を追うにつれ、テレワークに感じていた最初のワクワクが段々と薄れてきてしまいます。

そこで、テレワークを楽しく！と思い、**誰でも美少女キャラでテレワークできる方法**をご紹介します！

<img width="460" alt="スクリーンショット 2020-04-06 22.23.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/2ff225e4-11e0-1b08-7a5b-9e853c2c8067.png">


# 用意するもの
* Mac PC（MacBook pro 10.14.6、iMac 10.15.3で確認）
* Macで動かすビデオチャットツール（Meet、Zoomなど）
* [CamTwist](http://camtwiststudio.com/)（v3.4.3で確認）
* QuickTime Player
* iPhone（iPhoneでキャプチャする場合）
* REALITY（iPhoneでキャプチャする場合）（ホロライブ、FaceRigなどでも可）

※Windowsの場合はOBSのVirtualCamプラグインを使うか、Unityを使う方法があるようですが、この記事では取り扱いません。

# iPhoneにモーションキャプチャアプリ(REALITY)をインストール
REALITYとはアプリの名前で、プリセットからアバターを作成して配信することができるiPhoneアプリです。
※今回は配信ではなく、顔のモーションキャプチャ機能のみを利用させてもらいますので、そのほかのモーションキャプチャアプリでも代用可能です。

インストールしたら適当なアバターを作成して、Macに接続します。

# QuickTime PlayerでiPhoneの画面をMacに表示

### 新規ムービー収録を開始
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/7ff742d0-bf76-1c35-6133-3ebefac96e75.png)

### 録画ボタン右側の▽からiPhoneを選択して画面を表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/3322e9ec-f736-2e16-04d6-e99aa110e62b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/34d1a0e9-585c-0bfb-60c9-6cab5b333239.png)
<img height="720" alt="スクリーンショット 2020-04-06 22.23.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/4a38c395-beaa-3367-2423-e1387565304b.png">

※iOSのアップデートをする必要がある場合はQuickTime Playerが落ちる場合があります。

# [CamTwist](http://camtwiststudio.com/)で仮想Webカメラにアウトプット
[CamTwist](http://camtwiststudio.com/)を使うと、DesktopのWindowをキャプチャして仮想Webカメラにアウトプットすることができます。

インストールして起動すると、以下のような画面が表示されます。
<img width="870" alt="スクリーンショット 2020-04-06 22.23.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/99d0a1d2-235c-4951-1708-d7b0df312ee3.png">

### 設定のポイント
* チャットツールを立ち上げて画面を確認しながらやると良いです
* Desktop+を選択して[Select]ボタンをクリック
* 右端のSettings欄の[Full Screen]は外して[Continue to Application windows]を選択
* [Select from existing window]から、QuickTime Playerのウィンドウを選択
* 必要に応じて、[Do not scale]や[Select capture area]でサイズを調整

ここでビデオチャットツールを立ち上げると、以下のようにCamTwistという仮想Webカメラが選択できるようになります。
※環境によっては再起動が必要だったり、読み込んでくれなかったりします。
※CamTwistの許可設定がされていない場合、表示されないようです。
 「システム環境設定」から「セキュリティとプライバシー」で「プライバシー」タブの「カメラ」の項目「下のアプリケーションにカメラのアクセスを許可」に「CamTwist.app」を追加すると解決できるかも知れません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103853/adb59818-6bdb-dfe8-1394-f5e083987ce3.png)

# 以上！
これであなたも明日から美少女です。

https://twitter.com/GroGroPHP/status/1247145828805824515?s=20
Rubyで数値を3桁区切りにする方法 (正規表現)

# 背景
通貨を表示する際、数字を3桁区切りでカンマを挿入するかと思います。
Rails環境では
- `number_to_currency`メソッド
- `delimited`メソッド
どちらかを利用して簡単に表示できますが、Ruby環境では両者が利用できませんでした。そのため、正規表現を用いてメソッド化をしました。

`number_to_currency`メソッドについては、[Rubyで数値を3桁区切りにする方法！](https://qiita.com/wacker8818/items/cc213ba3ce72891dfb23)を参照してください。

# 実装したコード
```Ruby
def converting_to_jpy(price)
    puts "#{price.to_s.reverse.gsub(/\d{3}/, '\0,').reverse}円"
end

converting_to_jpy(1234567890)
# => 1,234,567,890円
```

## 仕組み
`考え方`
**数字の末尾から数えて３文字毎にカンマを入れる**
つまり
1. 数字を文字列に変換
2. その文字列を反転（順番を入れ替える）
3. ３文字毎にカンマを入れる
4. 最後にもう一度反転させ、元の順番に戻す

という流れで実装しました。
ポイントとしては、`3. ３文字毎にカンマを入れる`の部分でしょうか。

```Ruby
.gsub(pattern, replace)
```
は文字列中で`pattern`にマッチする部分全てを文字列`replace`で置き換えた文字列を生成して返すメソッドです。
また、`\0`は一致した文字列全体に置換する正規表現です。このケースの場合`\d{3}`に該当します。つまり、以下のように言えます。

```Ruby
"1114447770".gsub(/\d{3}/, '\0,')
# => "111,444,777,0"
# 3文字毎の文字列の後ろにカンマを入れる
```



# 開発環境
ruby 2.5.1
[Swift] Macアプリで常に最前面に表示する方法

# はじめに

タイトルに示す通りのことを実現したくて「常に最前面 MacApp」でググったら、**クリアメモリ**さんの[『【Swift】常に最前面に表示されるOSXアプリの作り方』](https://clrmemory.com/programming/swift/cocoa-stayinfront-app/)のページがヒットしました。この記事に書いてある手順で無事に実現できたのですが、OS他のバージョンが上がっており多少の変更が必要でしたので、元記事からの変更点をまとめておきます。
_ほとんどはコンパイルエラーが出て教えてくれますが、元記事への恩返しの意味です。_

## 前提とする環境

当方の環境（執筆時点）；

- maxOS Catalina version 10.15.3
- Xcode version 11.1 (11E148) 
- Apple Swift version 5.2 (swiftlang-1103.0.32.1 clang-1103.0.32.29)


# 変更点

## AppDelegate.swift

「Stay in Front」メニューをクリックした時の、チェックオン/オフのトグル処理のコードにおいて、`NSMenuItem.state`の値が変更になっています。

```Swift:元記事のコード
func toggleMenuChecked(){
    if stayInFrontMenu.state == NSOnState {
        stayInFrontMenu.state = NSOffState
    }else if stayInFrontMenu.state == NSOffState{
        stayInFrontMenu.state = NSOnState
    }
}
```

```Swift:新しいコード
func toggleMenuChecked() {
    if stayInFrontMenu.state == .on {   
        stayInFrontMenu.state = .off
    } else if stayInFrontMenu.state == .off {
        stayInFrontMenu.state = .on
    }
}
```

## WindowController.swift

実際にウィンドウを最前面に設定する処理のコードにおいて`NSWindow.Level`の値が変更になっています。

```Swift:元記事のコード
func stayInFront(){
    let normalWindow = Int(CGWindowLevelForKey(.normalWindow))
    let floatingWindow = Int(CGWindowLevelForKey(.floatingWindow))

    if window?.level == normalWindow{
        window?.level = floatingWindow
    }else if window?.level == floatingWindow{
        window?.level = normalWindow
    }
}   
```

```Swift:新しいコード
func stayInFront() {
    if window?.level == .normal {
        window?.level = .floating
    } else if window?.level == .floating {
        window?.level = .normal
    }
}
```

## WindowController.swift　（２箇所目）

NotificationCenterのオブザーバから呼び出されるメソッドに`@objc`attributeが必要です。[^1] [^2]

```Swift:元記事のコード
func nCenter(notification: NSNotification) {
    stayInFront()
}
```

```Swift:新しいコード
@objc
func nCenter(notification: NSNotification) {
    stayInFront()
}
```


## その他

変更点ではありませんが、コンパイルエラーが出ないので気付きにくい点として；

> 新しく「WindowController」というクラスを作成し、ストーリーボードで設定してあります。
> この工程は省くので、各自設定しておいてください。

下図の様にカスタムクラスを設定する必要があります。これを忘れると _WindowController_ が機能しません期待通りに動きません。
![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/23575488-2406-da39-48b0-4968bcb558b8.png)



# 終わりに

元記事では、他にも _Outlet_ や _Action_ の接続手順も省略しています。もしこの記事をご覧の方で、これらの手順も知りたい方は、コメントいただければ追加いたします。

2023.7.18追記
SwiftUIで書いた`Mac Catalyst`アプリでの実装方法を、↓こちらに公開しました。

https://qiita.com/nak435/items/fc26f7d98466a782803e


[^1]: なぜ`@objc`が必要なのか、[**こちら**](https://qiita.com/masakihori/items/4a715f28fc7f18d1a625#objc%E3%81%AE%E8%A9%B1)に説明があります。

[^2]: `@objc`他のSwiftのattributeについては[**こちら**](https://qiita.com/shtnkgm/items/a793f26445f2b8390bee)に説明があります。
Linuxとは

##そもそもLinuxとは？

- LinuxとはOSの一種である。OSとは、画面操作や情報を渡すなど、コンピュータの土台のようなもの。
- LinuxはオープンソースのOSであり、オープンソースとは無料で可変可能なプログラムのようなもの。Linuxの機は　MacOSやWindowsOSなどとあまり変わらないが、無料で新たにサーバーを立ち上げたり、OSを作ったりすることができる。
- Linuxの操作はCUIでコマンドを打って操作する。

##Linuxコマンド
- ディレクトリ移動

```:shell
$ pwd  //作業しているディレクトリを表示

$ cd ディレクト名  //ディレクトリを変更

```
- ファイル表示

```:shell
$ ls  //今いるディレクトリにあるファイルを表示
```
- ファイル操作

```:shell
$ mkdir　ディレクトリ名 　//ディレクトリを作成
$ cp コピーしたいファイル　コピー後の名前  //コピー
$ mv 移動させたいファイル　移動先  //移動
$ rm ファイル名  //削除
```
蟻本　Lake Counting (POJ No.2386)

@drkenさんの[AtCoder 版！蟻本 (初級編)](https://qiita.com/drken/items/e77685614f3c6bf86f44#2-1-%E3%81%99%E3%81%B9%E3%81%A6%E3%81%AE%E5%9F%BA%E6%9C%AC-%E5%85%A8%E6%8E%A2%E7%B4%A2)のLake Counting (POJ No.2386)の類題を触って見ました


##ATC001_A

```c++

#include <bits/stdc++.h>
#define rep(i,n) for(int i = 0;i < (n);i++)
using namespace std;

const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

int H,W;
vector<string> c;

bool seen[510][510];
void dfs(int h,int w){
    seen[h][w] = true;
    for(int dir = 0; dir < 4 ;dir++){
        int nh = h + dx[dir];
        int nw = w + dy[dir]; 
        if (nh < 0 || nh >= H || nw < 0 || nw >= W) continue;
        if (c[nh][nw] == '#') continue;
        if (seen[nh][nw]) continue;
        dfs(nh,nw);
    }
}

int main(){
    cin >> H >> W;
    c.resize(H);
    for(int h = 0;h<H;h++) cin >> c[h];
    int sh, sw, gh, gw;
    for(int h = 0; h < H;h++){
        for(int w = 0;w < W;w++){
            if (c[h][w] == 's') sh = h, sw = w;
            if (c[h][w] == 'g') gh = h, gw = w;
        }
    }
    memset(seen, 0, sizeof(seen));
    dfs(sh, sw);
    if (seen[gh][gw]) cout << "Yes" << endl;
    else cout << "No" << endl;
}

```

##ARC031_B

```c++

#include<bits/stdc++.h>
using namespace std;

#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rep1(i, n) for (ll i = 1; i <= (ll)(n); i++)
using ll = long long;
using Graph = vector<vector<int>>;

vector<int> dx = {1,0,-1,0};
vector<int> dy = {0,1,0,-1};
int seen[10][10];

void dfs(vector<string> &Field, int x, int y,int &num){
    seen[y][x] = 1;
    num++;
    for(int dir = 0; dir < 4; dir++){
        int nx = x + dx[dir];
        int ny = y + dy[dir];
    if(nx<0||ny<0||nx>=10||ny>=10)continue;
    if(Field[ny][nx]=='x')continue;
    if(seen[ny][nx])continue;
    dfs(Field,nx,ny,num);
    }
}

int main(){
    vector<string> Field(10);
    rep(i,10)cin>>Field.at(i);
    int num = 1;
    rep(y,10)rep(x,10)if(Field[y][x]=='o')num++;
    rep(y,10){
        rep(x,10){
            if(Field[y][x]=='o')continue;
            int tmp = 0;
            rep(i,10)rep(j,10)seen[i][j]=0;
            dfs(Field,x,y,tmp);
            if(tmp==num){
                cout<<"YES"<<endl;
                return 0;
            }
        }
    }
    cout<<"NO"<<endl;
    return 0;
}


```

##ARC037_B

```c++

#include <bits/stdc++.h>
#define rep(i,n) for(int i = 0;i < (n);i++)
using namespace std;
typedef long long ll;
 
 
int main(void) {
	int n, m, i, j, u1, u2, p, ans = 0, rt;
	vector<int> g[103];
	bool u[103] = { false }, ok;
 
	cin >> n >> m;
	for (i = 0; i < m; i++) {
		cin >> u1 >> u2;
		g[u1 - 1].push_back(u2 - 1);
		g[u2 - 1].push_back(u1 - 1);
	}
 
	for (i = 0; i < n; i++) {
		if (!u[i]) {
			queue<int> q;
			q.push(i);
			ok = true;
			while (!q.empty()) {
				p = q.front();
				q.pop();
				u[p] = true;
				rt = 0;
				for (j = 0; j < g[p].size(); j++) {
					if (u[g[p][j]]) rt++;
					else q.push(g[p][j]);
				}
				if (rt > 1) ok = false;
			}
			if (ok) ans++;
		}
	}
	cout << ans << endl; 
	return 0;
}
```

###感想
今回はじめて深さ優先探索というものを勉強しました。昨日勉強したビット全探索よりもかなり理解しやすかったです。応用できるように今後も勉強していこうと思います。
リストの結合、extendするより足し算した方が早くね？

# 簡単に速度測定

`sub_list = list(range(10000))`を空のリストに追加したときの速度を測定してみる。

## 1. `extend`の速度
```python
In:
%%timeit

li = []
li.extend(sub_list)
```
```
Out:
26.7 µs ± 2.44 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
```

## 2. 足し算の速度
```python
In:
%%timeit

li = []
li += sub_list
```
```
Out:
25.3 µs ± 281 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
```

**足し算の方が早く、速度も安定している。`extend`って組み込み関数なのに遅くね？**

# 詳しく速度測定

この問題には、

- 元のリストの長さ
- 追加するリストの長さ

の2つの変数があるので、それをいじったときの速度を測定する。そして、速度同士の引き算をして、`extend`と足し算のどちらが勝ったのかを見てみる。

## リストが短い場合

- 縦軸：元のリストの長さ
- 横軸：追加するリストの長さ
- 白:`extend`の方が早い
- 黒:足し算の方が早い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488916/5f15bcc3-55ce-0790-4eca-6c3d5c2a885d.png)

**足し算優勢**


## リストが長い場合

- 縦軸：元のリストの長さ
- 横軸：追加するリストの長さ
- 白:`extend`の方が早い
- 黒:足し算の方が早い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488916/495bb3df-1643-81e2-371d-d4dc85244bca.png)

**`extend`優勢**


なんだろ、Pythonそもそもの実装に関わってくるのかな？

# コード

```python
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from time import time


def extend_time(old_i, new_i):
    old = list(range(10 ** old_i))
    new = list(range(10 ** new_i))
    s = time()
    old.extend(new)
    e = time()
    return e - s


def add_time(old_i, new_i):
    old = list(range(10 ** old_i))
    new = list(range(10 ** new_i))
    s = time()
    old += new
    e = time()
    return e - s


extend_time = np.vectorize(extend_time)
add_time = np.vectorize(add_time)


shape = (8, 8)
extend_graph = np.fromfunction(extend_time, shape, dtype=np.int)
add_graph = np.fromfunction(add_time, shape, dtype=np.int)

result = np.where(extend_graph - add_graph > 0, True, False)
sns.heatmap(result, cbar=False, xticklabels=[10 ** i for i in range(shape[0])], yticklabels=[10 ** i for i in range(shape[0])])
plt.ylabel("old list length")
plt.xlabel("new list length")
plt.show()
```
Djangoで画像をURL化するなんちゃってAPIを作ってみた

 今回は、画像ファイルを載せてPOSTリク送れば、https化されたURLを生成してくれるよってやつ作ってみました。
まだまだ試行錯誤中ですが、完成したものがこちらです(PC用サイトになります):basketball_player_tone3:
→[なんちゃってAPI](https://www.takopanman.work/)
ちなみに、使い方やコードサンプルも乗っています:v:
#やりたいこと
DjangoでファイルをPOSTで受け取りたい。
受け取ったファイルに対してのURLを発行したい。

意外と簡単だったので、ローカルで実装して紹介したいと思います。

#プロジェクトの作成

```bash:bash
$ django-admin startproject app
```
これで、フレームが完成します。次にPOSTリクエストを受け取って処理するアプリの雛形を作成します。postという名前でいきましょう。

```bash:bash
$ cd app
$ django-admin startapp post
```
#POSTリクエストで画像を受け取る

```python:#post/views.py
from django.shortcuts import render
import json
from django.http.response import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.core.files.storage import default_storage

# Create your views here.
@csrf_exempt
def get_img(request):
    
    if request.method == "POST":
        # ← 受け取ったPOST画像データを保存
            res, file_name = save(request.FILES["image_file"])
            res = request.build_absolute_uri(res) #絶対pathに基づくURLの作成
    
    else:  # ← methodが'POST'ではない = 最初のページ表示時の処理
        return HttpResponse("this is post page!")

    ret = {"url": res}

    # JSONに変換して戻す
    return JsonResponse(ret)


def save(data):
        file_name = default_storage.save(data.name, data)
        return default_storage.url(file_name), data.name
#受け取ったファイルをストレージに保存
```
　ストレージってどこぞやって思ったかもしれません。settings.pyで宣言してあげなければなりません。

```python:#app/settings.pyに追記
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
```
これで/media以下にファイルが保存されていきます。

#ルーティングの設定
最後にurls.pyでルーティングを決めていきます。

```python:#app/urls.py
from django.urls import path, include
from django.contrib import admin
from . import settings
from django.contrib.staticfiles.urls import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns

urlpatterns = [
    path('post/', include('post.urls',namespace='post')),
]

urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
#/media以下のファイルをhttp経由で表示するために追加
```
今回adminとか無駄なものは省きます。画像をディレクトリから取り出してみるには、最後の二行がとっても重要になります:relaxed:

```python:#post/urls.py
from django.urls import path, include
from . import views

app_name = "post"

urlpatterns = [
    path('', views.get_img, name = "img_get"),
]

```
先ほど書いたViewにつなげてあげます。これで完成:wine_glass:
　
#テストしてみた
```python:test.py
import requests
import json
#POSTするURL設定
post_url = "http://127.0.0.1:8000/post/"

#POSTするファイルの読込
files = { "image_file": open('./sample.jpeg', 'rb') }

#POST送信
response = requests.post(
    post_url,
    files = files,)

print(json.loads(response.text))

```
こんな感じでPOSTできます。image_fileの名前は変更するときは、views.pyの該当箇所も変えてください。
成功すると、

```bash:bash
{'url': 'http://127.0.0.1:8000/media/sample.jpeg'}
```
こんな感じのレスポンスが。アクセスしてみよう!
<img width="1212" alt="スクリーンショット 2020-04-06 22.24.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541141/ec5a5437-901c-574a-14dd-1de8a36bf8c9.png">

うまくいきました。なんちゃってAPIの完成です:bicyclist:


#最後に
実際、Djangoで画像ファイルとかを保存して使いたいって時があると思うので参考にしていただけると幸いです。ありがとうございました:joy:
意外と難しい、Vuetifyのv-slot=activator="{ on }"についての簡単な解説

[
一部のVuetifyのコンポーネントでは、Vueのスロットの機能を利用します。
これが意外と複雑ですので、解説します。

内容としては、Vueの**名前付きスロット**と**スコープ付きスロット**になります。

例えば、v-menuコンポーネントの使い方は下のようになります。

```html
<v-menu>
  <template v-slot:activator="{ on }">
    <v-btn v-on="on">
      メニューを開く
    </v-btn>
  </template>
  <v-list>
    <v-list-item>
      メニューの項目1
    </v-list-item>
  </v-list>
</v-menu>
```
`v-on="on"`を指定したHTML要素をクリックすると、`v-list`の部分が表示されます。

ここではVueの**名前付きスロット**機能と、**スコープ付きスロット**の両方を使用しています。

このコードの中で、普段あまり使わない文法は

```html
<template v-slot:activator="{ on }">
```
の部分だと思います。

これは、この`<template>`が`activator`という`name`に対するスロットであることを指定しています。
また、スロットプロパティとして、デフォルトスロットを表示するためのイベントハンドラを受け取っています。
そのイベントハンドラは、スロットプロパティのうち`on`というキーで`<v-menu>`コンポーネントから渡されるため

```html
<template v-slot:activator="{ on }">
```
となるのです。

詳しく知りたい方は、スロットについてのVue公式ドキュメントを全部読むことをおすすめします。
https://jp.vuejs.org/v2/guide/components-slots.html
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
わかんねぇ単語たち

#コンテナ


仮想化 とは、1台の物理的なコンピュータの上で、複数の仮想的なコンピュータを実行させる技術・仕組みのことです。仮想化技術を利用すると、それぞれのコンピュータが、個別にOSやアプリケーションなどを実行することが可能となります。

仮想化を実現する技術は、 ホスト型 、 ハイパーバイザー型 、 コンテナ型 があります。

 
#イラスティックサーチ
Elasticsearch(エラスティックサーチ)とは、Elastic社が提供する「Lucene」ベースのオープンソース全文検索エンジン。
なお全文検索エンジンとは、大量にあるドキュメントデータの中から、目的のワードを含むドキュメントデータを検索するための仕組み。

#コネクション
こねくしょんってなんだぁーーー
#クロモジ
くろもじってなんなんだよぉーーー
#アイシーユー
ICU
主な意味　集中治療室、集中強化治療棟
どゆこと？？

#ナノ

```

//ファイル名を指定せずに開く場合
nano

//ファイル名を指定して開く場合
nano [ファイル名]

//オプションを指定してファイルを開く場合
nano [オプション] [ファイル名]


```
これは割と納得

#ビーコンテナ
コンテナの一種とみた。
#ナナサン
きっと７３のことだとおもうけど　何の話だったか忘れた　
#ビップ
VIP
主な意味　偉い人、要人
これだけは絶対違うと思う

```
天野：
多分pipのことだと思う
pythonのライブラリ管理ツール
```

#ドッカーピーエス
docker psコマンドで現在のコンテナの稼働状況を確認します。
なるほどね！

```
amano
コンテナの稼働状況を確認するでOK
オプションをつけると停止したコンテナも見れる
```

#バイナリーバッシュ
bash は、標準入力やファイルから読み込んだコマンドを実行する。

バイナリーバッシュってどういうことだろうねぇ
#ディシュ
ディッシュってなんだーーーーー
でてこねーーー
めげそう

#ゼッシュ

多分バッシュの聞き間違いと思われ
#コアアイファイブ
パソコンのバージョンみたいなやつか
#128のオトコ
これは竹末さんが何か言ってたやつだから無視
#ホストネーム
http://www.example.co.jp
ホスト名　www
ドメイン　example.co.jp

なるほどね

#ギットクローン

cloneコマンドは、その名の通りクローンを作るためのコマンドだ。指定されたディレクトリに元のリポジトリと同じものを複製するコマンドになる。

まぁそんな気はしてたけどね
OSSに参加にする敷居を下げるコマンドgossを作ったよ 


#ご挨拶
こんにちは。
職業は盛り上げマスター(MM)です。
盛り上げマスターとは、最近新しくアジャイルな開発で導入され話題になっている役割で（嘘）
チーム内の居心地の良さを最大化することが仕事です。要はワイガヤ担当。

Goを最近勉強しています。Go歴は1ヶ月です。
間違っている箇所など優しくご指摘いただけると嬉しいです。

そしてGo初心者が作った物なので、このコマンドを実行して何か問題が発生しても自己責任でお願いします。

#作った物

https://github.com/kankanSunaga/goss

#何を作るか考えた
最近これ話題になってますよね。
https://github.com/tokyo-metropolitan-gov/covid19
東京都のコロナ対策アプリです。

私もプルリクを出しましたが、案の定マージはされませんでしたw
でもこういった取り組みに参加できて良かったなと思っています。

参加して思ったのが、もっとOSSの文化が根付ばいいな〜と思いました。
そこでできるだけOSSの参加の敷居を下げたいと思い、
コマンド一発で、fork,clone,remote の追加をできるコマンドを作成しました
(hubコマンドでよくねって思っても口にしちゃダメ)

#できること

現在いるパスにossに参加したいプロジェクトのfork,clone,remoteの設定ができます。

#使い方
まずgithubのtokenを取得してください。
https://github.com/settings/tokens
取得したらこんな感じで下記のコマンドを実行してください。

```
$ echo 'export GITHUBTOKEN="取得したgithubのトークン"' >> ~/.bash_profile
$ source ~/.bash_profile
$ echo $GITHUBTOKEN
先ほど取得したgithubのトークンが表示されたらOK！
```
これでセットアップ完了です。
実行

1. プロジェクトを追加したいフォルダまで移動してください。
2. 参加したいOSSのgithubのページまで飛んでください。そしたら、画像の①と②をコピってください 
![スクリーンショット_2020-04-06_22_41_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138676/138c1c09-0fb2-c9e5-7c93-e80f6f3c9d97.png)


3. 以下を実行してください

```
$ goss ２でコピった①　2でコピった②
```

そしたらあら不思議
remoteにupstreamとリポジトリののforkができています（はず）

#意識した点
- Goっぽい書き方でできるだけ書く
- 日本人のプログラミング初心者にわかりやすくするため、エラー文言をできるだけ日本語を使った
- 無駄な機能は乗っけずに、必要最低限の物にした
DNSについて

#DNS(Domain Name System)
私たちは日ごろからメールアドレスやWebアドレスなどを使っています。
これらのアドレスは本来、数字の羅列で表されます。

例）
いま : hoge.jp
本来 : 172.20.2.1

しかし、このような数字の羅列では多くのアドレスを覚えることができません。
そこで、現在使われているような人間が覚えやすい表記（ドメイン名）を使ったアドレスが使われるようになったのです。

DNSを使うことでこのドメイン名からIPアドレスを知ることができます。

##ドメイン名
ドメイン名はIPアドレスを人間が覚えやすいように変換したものです。





ドメイン名は"ホスト名 + 組織名"というようにつけることができる

例) 
hoge.ac.jp


## 少し前のIPアドレスの管理
少し前にはhostsファイルにホスト名とIPアドレスの対応を記録し、一括管理していました。
しかし、ネットのユーザーが増え、ネットワークの規模が大きくなってきたため、一か所で管理することが困難になりました。


例）

| IPアドレス      | ホスト名 |
|:---------------:|:----------:|
| 172.20.2.1 | hoge.jp |
| 172.20.2.2 | fuga.jp | 
| 172.20.2.3 | piyo.jp |
| ...|...|

そのためDNSが普及していったのです。

## 感想
DNSのことは少し知っていたのですが、詳しく調べたことはなかったので、
良い機会になりました。

DNSによる問い合わせについても調べて書きたいと思います。
【Java】カレントディレクトリの取得方法

#きっかけ#

Javaで同階層のファイルを開こうと相対パスを与えたのだが開いてくれなかった
そこで絶対パスを与えてやろうと検索してみたら記事が少なかったので覚書

#簡単#

あまりにも簡単だから誰も書かないのか
常識の範囲だから書かないのか
わからないけどとっても簡単でした

##それがこちら##

```Dir.java
import java.io.File;

class Dir {
    public static void main(String[] args) {
        String path = new File(".").getAbsoluteFile().getParent();
        System.out.println(path);
        // 例:C:\Users\xxxxx\Documents\java
    }
}
```

もうひとつ

```Dir.java
class Dir {
    public static void main(String[] args) {
        String path = System.getProperty("user.dir");
        System.out.println(path);
        // 例:C:\Users\xxxxx\Documents\java
    }
}
```

#おまけ#

```Dir.java
import java.io.File;

public class Dir {
    public static void main(String[] args) {
        String path = new File(".").getAbsolutePath();
        System.out.println(path);
        // 例:C:\Users\xxxxx\Documents\java\.
    }
}
```

`.`のごみが付きますが置換でやっつ…

けられませんでした
ユーザー名などにピリオド入ってたらいっかんの終わりです。

#感謝#

散々探してやっとたどり着いたページがこちらです
[【Java】カレントディレクトリを取得する](http://www.openreference.org/articles/view/603)
【Flutter】Android license status unknown.の解決方法

# 概要

```
$ flutter doctor
```

を実行すると

`Android toolchain` のところが失敗しており掲題のエラーが出た。

```
flutter doctor --anroid-licenses
```

を実行すると

```
Android sdkmanager tool not found
```

と言うエラーが出た。

# 解決方法

Anroid Studioにて、 [Preferences] -> [System Settings] -> [Android SDK]で、

SDK Toolsタブを選択し、 `Android SDK Command-line Tools` をインストールしたら解決しました。

<img width="1014" alt="スクリーンショット 2020-04-06 21.44.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11800/970d5d30-ad13-5da5-9e95-388079998edd.png">


誰かのお役に立てば。
Python＆機械学習 勉強メモ⑤：アヤメの分類

#はじめに
① https://qiita.com/yohiro/items/04984927d0b455700cd1
② https://qiita.com/yohiro/items/5aab5d28aef57ccbb19c
③ https://qiita.com/yohiro/items/cc9bc2631c0306f813b5
④ https://qiita.com/yohiro/items/d376f44fe66831599d0b
の続き

- 参考教材：[Udemy みんなのAI講座 ゼロからPythonで学ぶ人工知能と機械学習](https://www.udemy.com/course/learning-ai/)

#scikit-learn
今回用いる機械学習ライブラリ

#課題設定
花弁と萼それぞれの長さと幅を与えると、アヤメの品種特定をする。
0は"Setosa"を表す。
1は"Versicolor"を表す。
2は"Virsinica"を表す。

#ソースコード
##インポート

```python
from sklearn import datasets
from sklearn import svm
```

##サンプルデータの読み込み
```python
# Irisの測定データの読み込み
iris = datasets.load_iris()
```
`iris`には以下のようなデータが入っている

```:iris.data
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
...
```
```:iris.target
[0 0 ... 1 1 ... 2 2]
...
```
どちらも要素数は150。おそらく、"0:Setosa", "1:Versicolor", "2:Virsinica"それぞれの正解データが50個づつ入っているものと思われる。

##サポートベクターマシンによる分類

```python
# 線形ベクターマシン
clf = svm.LinearSVC()
# サポートベクターマシンによる訓練
clf.fit(iris.data, iris.target)
```
`svm`のメソッドを使ってサポートベクターマシンに学習させる。
今回使っている線形ベクターマシンは、平面(多分、何次元でもいいのだと思う)に打ち込んだ複数の点の集まりに対して線（3次元だったら面）を引いてグルーピングさせるモデル。
今回のケースだと、扱うデータは「花弁の長さ」・「花弁の幅」・「萼の長さ」・「萼の幅」の4つなので、4次元空間に正解データをプロットして、識別できる線を引いている？と思われる。

##分類

上記で作成したclfに3つのデータを読ませ、"0:Setosa", "1:Versicolor", "2:Virsinica"のどれになるか、それぞれ分類させる。

```python
# 品種を判定する
print(clf.predict([[5.1, 3.5, 1.4, 0.1], [6.5, 2.5, 4.4, 1.4], [5.9, 3.0, 5.2, 1.5]]))
```

##結果
なんかワーニングが出るが、分類ができている？

```
C:\Anaconda3\python.exe C:/scikit_learn/practice.py
C:\Anaconda3\lib\site-packages\sklearn\svm\_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
[0 1 2]
```

#おまけ
iris.dataの中身がどのようなデータなのかを見える化してみた

```python
from sklearn import datasets
import matplotlib.pyplot as plt

# Irisの測定データの読み込み
iris = datasets.load_iris()

# Setosa, Versicolour, Virginica
sepal_length = [[], [], []]
petal_length = [[], [], []]
sepal_width = [[], [], []]
petal_width = [[], [], []]

for num, data in enumerate(iris.data):
    cls = iris.target[num]
    sepal_length[cls].append(data[0])
    petal_length[cls].append(data[1])
    sepal_width[cls].append(data[2])
    petal_width[cls].append(data[3])

plt.subplot(1,2,1)
plt.scatter(sepal_length[0], petal_length[0], c="red", label="Setosa", marker="+")
plt.scatter(sepal_length[1], petal_length[1], c="blue", label="Versicolour", marker="+")
plt.scatter(sepal_length[2], petal_length[2], c="green", label="Virginica", marker="+")
plt.xlabel('sepal_length')
plt.ylabel('petal_length')
plt.legend()

plt.subplot(1,2,2)
plt.scatter(sepal_width[0], petal_width[0], c="red", label="Setosa", marker="+")
plt.scatter(sepal_width[1], petal_width[1], c="blue", label="Versicolour", marker="+")
plt.scatter(sepal_width[2], petal_width[2], c="green", label="Virginica", marker="+")
plt.xlabel('sepal_width')
plt.ylabel('petal_width')
plt.legend()

plt.show()
```

![iris.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571638/95498c2c-e1cc-b59d-45af-505c91fd2174.png)

Setosa, Versicolour, Virginicaのグループの間に線を引くことで、(Versicolour, Virginicaのライン近傍のデータは難しいかもしれないが)おおむね分類できそうなことが理解できる。
apache module 覚書

# apache moduleとは？
Apacheの機能はモジュールを追加することで拡張できる。Apacheの核となる「Core」がまずあり、そこへモジュールを追加して機能を拡張する。モジュール名は慣習的に「mod_XXX」と付けられる。XXXは機能の概要名である。例えば「mod_dir」「mod_alias」「mod_setenvif」などとなる。※1
C言語で記述する。

# Apache Portable Runtimeとは？
サーバと OS の 間の基本的なインターフェースの多くを提供する(訳注: OS の差を吸収する)ライブラリのセット。 APR は 独立した プロジェクトとして Apache HTTP Server と平行して開発が行われています。

C言語における移植性の確保を行ってくれる抽象レイヤーで、関数名が apr_ から始まる。
メモリプールの管理や文字列操作などなどApache Module APIで利用できていた機能を利用できる。

# 主要機能
## apr_pools
メモリプール機能。確保した領域について明示的なfreeは不要。
http://apr.apache.org/docs/apr/1.5/group__apr__pools.html

## apr_strings
C言語では複雑になりがちな文字列操作を簡単に行うことができる。
返り値の領域はメモリプールから確保される。
http://apr.apache.org/docs/apr/1.5/group__apr__strings.html

## apr_tables
動的に拡張される配列などを提供
http://apr.apache.org/docs/apr/1.5/group__apr__tables.html

## apxs
apacheの拡張モジュールをビルドして、インストールしてくれる。
https://kazmax.zpp.jp/apache/apache3.html

## request_rec 構造体
HTTPリクエストを表現した構造体。
include/httpd.hで定義。モジュールを書く上で最もよく使う構造体。

|メンバ|概要|
|---|---|
|r->handler        | 処理するハンドラの名称|
|r->content_type   | Content-Typeヘッダ取得|
|r->header_only    | HEADリクエストかどうか|
|r->pool           | リクエスト毎のメモリプール|
|r->args           | QUERY_STRING値|
|r->method_number  |　リクエストメソッドの数値表現？|
|r->headers_in     | リクエストヘッダ apr_table_t型|
|r->headers_out    | レスポンスヘッダ apr_table_t型|
|r->r->uri         | URI|
|r->filename       | DISK上のファイル名|
http://nukin.jugem.jp/?eid=23
https://ci.apache.org/projects/httpd/trunk/doxygen/structrequest__rec.html


業務で利用された機能を追記予定


# これ買えばたぶんもろもろの情報網羅
[WebエンジニアのためのApacheモジュールプログラミングガイド](https://play.google.com/store/books/details/Web%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEApache%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%82%AC%E3%82%A4%E3%83%89?id=jR7LMext5oEC)


# 参考
http://apr.apache.org/
https://www.slideshare.net/shebang/apache-module-presentation
http://module.jp/cookbook/apache_api/aprize_your_project.html

※1 https://ja.wikipedia.org/wiki/Apache_HTTP_Server
Arduinoと8ビットシフトレジスタで７セグを制御する

###はじめに
表示系の部品としてあらゆるところで使われています。しかし、LEDとは違い単純に電圧をかけても数字は表示されません。さらにどうしても配線が多くなってしまうため、シフトレジスタも活用して使い方をマスターしましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/01c1eac9-e6d4-7d8a-391f-ed72fb754c92.png)
### 7セグメントLEDの回路
下記の図のように、a~g + DP（ドット）までの8ピンがあります。それらのピンに入力があるとその場所が光ます。
また、共通ピン（com）が「＋」か「ー」の2種類の回路がありますので使用する場合はよく確認しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/ae744718-2284-580c-475c-9c5208c1dd2d.png)


### 配線図
このように配線を行います。特にプログラムは必要ありません。実行すると全て点灯すると思います。今は3.3VとGNDしか使用していませんので制御らしい動きはできません。
実際にはこれをGPIOピンに挿入＆入力を与えることで制御できますが、そうなると8pinも消費してしまい、ちょっと勿体無い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/de510889-6982-8a2c-f34e-aefc07ebd24b.png)


###　シフトレジスタを使って配線を整える
シフトレジスタを加えることによって3線で入力を与えることができます。数字はシリアルで入力できるので簡単なコードで数字を順次に表示するコードも簡単にかけます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/b2f560e2-63ce-dfd7-a618-a3fcb43cdb0c.png)

```c


#define SRCLK   (5)//シフトレジスタのクロック信号
#define RCLK    (6)//ストレージレジスタのクロック信号
#define SER     (7)//シリアル入力

void setup() {
  pinMode(SRCLK, OUTPUT);
  pinMode(RCLK,  OUTPUT);
  pinMode(SER,   OUTPUT);
}

// 点灯パターン
const uint8_t PATTERNS[] = {
	B01110111,
	B00010001,
	B01101011,
	B00111011,
	B00011101,
	B00111110,
	B01111110,
	B00010111,
	B01111111,
	B00111111
};

void loop() {
  
  // 点灯パターンの数
  int pattern_num = sizeof(PATTERNS)/sizeof(PATTERNS[0]);

  for (uint8_t i=0; i<pattern_num; i++) {
    // 8ビット分のデータをシフトレジスタへ送る
    shiftOut(SER, SRCLK, LSBFIRST, PATTERNS[i]); 

    // シフトレジスタの状態をストレージレジスタへ反映させる
    digitalWrite(RCLK,  LOW);
    digitalWrite(RCLK,  HIGH);

    delay(500);
  }
}

```


###おわりに&参考文献
7セグやシフトレジスタなどが登場するとちょっと身構えてしまう方も多いと思います。ですが、原理は難しくなくシフトレジスタは関数がハード化されたと思えば気が楽ではないでしょうか？　まずは手を動かしてトライしてみましょう！

[7セグメントLEDとは？](https://www.rohm.co.jp/electronics-basics/led/led_what7)
[Arduinoでシフトレジスタ(SN74HC595)を使用して8個のLEDをチカチカさせる](https://stupiddog.jp/note/archives/1152)
岡山県版新型コロナウイルス対策サイトを開発・運用している話

![ogp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285513/5969e785-c2de-434e-a422-5d30a673182d.png)
# はじめに
[岡山県版新型コロナウイルス対策サイト（非公式）](https://okayama.stopcovid19.jp/)の運用のルサカです。
今回は岡山県版新型コロナウイルス対策サイトを開発・運用の過程についてQiitaに投稿しました。
# 開発開始
岡山県版作るのに東京都のコロナウイルス対策サイト[GitHubのリポジトリ](https://github.com/tokyo-metropolitan-gov/covid19)を活用し作成しました。以下のようにふじしゃんこと藤原出帆さん（[Twitter](https://twitter.com/fujiwaraizuho)）と役割を分担し開発をしました。
ふじしゃん →　東京都版の部分を岡山仕様にするなどなど
ルサカ　→　ロゴやOGP画像などを独自の岡山仕様にするなど
その結果、約１８時間で開発を終え、公開することができました。
# さくらインターネットさんとの出会い
もともとは、Netlifyで公開していましたが、転送量の上限が100GBと万が一アクセスが増えた場合対応ができなくなるため、さくらインターネットさんが新型コロナウイルス関連で提供してくれているサーバーを利用することにしました。本当にさくらインターネットさんありがとうございます！！！
詳細↓
https://www.sakura.ad.jp/information/pressreleases/2020/03/23/1968203129/
# オープンソースで開発へ
開発開始からしばらくの間はふじしゃんの僕のみでGitHubのプライベートリポジトリにて開発をしていましたが、岡山県版新型コロナウイルス対策サイトをよりよい物にし、多くの方に活用していただくためにオープンソースで開発することにしました。
# 最後に
岡山県版新型コロナウイルス対策サイトの運営の誰がいつ新型コロナウイルスに感染するかもわからないため特定の人に依存することのない運用を目指しています。
さらに、岡山県版新型コロナウイルスをより良いものにするためには沢山の人の力が必要です。
### 岡山県版新型コロナウイルス対策サイトに力を貸してください！！！
岡山県版新型コロナウイルス対策サイト↓
https://okayama.stopcovid19.jp/
GitHubリポジトリ↓
https://github.com/stopcovid19-okayama/covid19
Twitter↓
https://twitter.com/covid19_okayama
Slack↓
https://join.slack.com/t/okayama-stopcovid19/shared_invite/zt-d86r1ajq-ba1w0w71DGcX_fed6lufog
### よろしくお願いします！！！
# リンク
[東京都新型コロナウイルス対策サイト]
https://stopcovid19.metro.tokyo.lg.jp/
[さくらクラウド]
https://cloud.sakura.ad.jp/
Rails ActiveAdminのインストール時にエラー(superclass mismatch for class Application (TypeError))

# はじめに
railsでactiveadmin gemを使用したアプリを作成する際、ActiveAdminインストールで、エラーが発生した。
そのエラー発生原因が思いもよらなかった(railsプロジェクト名によるもの)ため、発生情報と解決方法を記す

# 環境
- debian : 10.3
- ruby: 2.6.6 (rbenv使用)
- rails: 5.2.4.2

# 発生情報
"active_admin"という名前でプロジェクトを作成(rails new)し、gemにactiveadminを追加＆bundle install (ココまでは問題なし）
その後、Userモデルの作成、DBのテーブル実施後、以下のactive_admin似必要なファイルインストールを実行したタイミングでエラー発生。

```
$ rails generate active_admin:install
/home/great084/jinsei/active_admin/config/application.rb:21:in `<module:ActiveAdmin>': superclass mismatch for class Application (TypeError)
・・・以下略
```

# 原因
railsプロジェクト名が"active_admin"であったため。それ以上は私の知識ではわからず。
※active_adminという名前は禁止されている(模様)

# 対処
active_adminというrailsプロジェクトは一旦削除し、他の名前(active_admin_apl)で再度プロジェクト作成。
→　`rails generate active_admin:install`でエラー発生せず。

# 参考

[Ruby-on-Rails: ActiveAdmin SuperClass Mismatch TypeError(stacoverflow.com)](https://stackoverflow.com/questions/17264878/ruby-on-rails-activeadmin-superclass-mismatch-typeerror)
よく使うDocker コマンド覚書

# Dockerコマンド覚書
コンテナ操作に不慣れな私の備忘録

## 実行中のコンテナをリスト

```
$ docker ps -a
CONTAINER ID        IMAGE                                                         COMMAND                  CREATED             STATUS              PORTS               NAMES
dffbdaebcd67        ibm-workload-automation-agent-dynamic:9.5.0.00.201903080412   "/opt/wautils/wa_s..."   12 days ago         Up 12 days                              modest_swartz
5be02e1472cc        ibm-workload-automation-server:9.5.0.00.201903080358          "/opt/wautils/wa_s..."   2 weeks ago         Up 2 weeks                              xenodochial_sinoussi
53e263c5aec7        ibm-workload-automation-console:9.5.0.00.201903080738         "/opt/wautils/wa_s..."   2 weeks ago         Up 2 weeks                              hardcore_haibt
7f55c57b70a0        7afd43c3fd50                                                  "/opt/wautils/wa_s..."   3 weeks ago         Up 3 weeks                              distracted_jones
```

## コンテナ内でコマンド実行(/bin/bash)

```
$ docker exec -it container_id /bin/bash
Setting CLI environment variables....
IBM Workload Scheduler Environment Successfully Set !!!
IBM Workload Automation Environment Successfully Set !!!
wauser@5be02e1472cc:/$ 
```

## コンテナのログを見る

```
$ docker logs container_id
```

## コンテナのログを見る（tail)

```
$ docker logs -f container_id
```

## exitしてしまったコンテナ内のファイルなどを確認する
```
$ docker run --rm -it container_id sh
```