OmniAICreator/Qiita-1.07M huggingface dataset:
GCP でブロガー開始の巻

#目的
学びを資産に変える！

#目標
GCP 環境上へWordpress 環境をデプロイ
１つ目の記事を書く

#なぜなぜ
将来、エバンジェリストとして、市場へ"価値を広める人" を育てることを目指す。
　　その一歩として、ブログで技術や知識へ情報を残し、足場を作るブログをしよう！と。

スモールスタートの究極系 "無料" だから、GCP 上にデプロイ！
　　Always Freeの枠で、環境を作りましょう。

#手順
###GCP アカウントを作成
GCP のサイトへ移動
https://console.cloud.google.com/?hl=ja

アカウントを持っていない方は、以下の手順で。持ってる方は、次項"GCP へVM をデプロイ" へ
![WS000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/3a885ca7-62e8-a0e9-abec-8fe91092edf1.jpeg)

初めての方は、無料トライアルがあるので、下のように同意を進めましょう
![WS000002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/a09376a4-5adf-fc17-36ab-566495337f19.jpeg)

住所やクレジットカード情報を投入しましょう
![WS000003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/e4e59382-3859-2184-951f-875690a55def.jpeg)

すぐに完了します。下のようなページが出たら、本項目は完了。お疲れさまです！次の項へ
![WS000004.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/4335c6c5-585b-6e90-6d4f-5d90bb083240.jpeg)


###GCP へVM をデプロイ
左上の "三" から、マーケットプレイスを選択しましょう
![WS000008.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/9e69dd9e-3dfa-240c-dffa-6ed3df2557b6.jpeg)

今回は、お手軽設定の出来る"Bitnami WordPress" の標準パッケージを利用しましょう
![WS000009.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/b4f5c273-9289-f28f-652e-9dd3ab6bc17b.jpeg)

検索結果から、以下のものを選択しましょう
　　NGINX とは、公開サーバを作る軽量なミドルウェア
　　SSL Certified とは、SSL 証明書を bitnamiでできるもの
　　　　なぜ、SSL 証明するかというと、最近のサイトは http"s" が一般的で、本サイトも"s" 化するため
![WS000010.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/7012147e-dc45-3b64-ab81-ad54ba3c8f0b.jpeg)

さぁ、VM を起動しましょう
![WS000011.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/be3c2192-63f5-dc37-dd9a-fb6bc45a9549.jpeg)

起動ボタンを押すと下のように起動中画面に移ります。５分ほど休憩にしましょう
![WS000012.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/55a01d76-ffaa-f7c3-39cf-9ca4c7cbe85a.jpeg)

デプロイするVM の設定を行います。今回は、無償枠"Always Free" の条件とします
  Zone : us-west1-b
  Type : micro (メモリ 0.6G)
  disk : 30GB (初期値は10G ですが、無償枠の最大値30GB へ変更)

![WS000013.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/8c6b3a75-d52b-5b62-63ef-015e2e4f9218.jpeg)

利用規約へチェックして、デプロイボタンを押しましょう
![WS000015.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/e68294c0-c73c-32e5-58e4-45e8870b2a7d.jpeg)

以下のようにVM 情報が出れば本項は完了です。お疲れさまです！次の項へ進みましょう
![WS000017.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184724/92dc0d1b-72bf-8453-09ce-9cec4c61e8aa.jpeg)


###Wordpress の設定
###Wordpress の評価
###Wordpress を改善
###記事を一つ
NTP Pool Project 日本語訳：規約

# はじめに
これは、NTP Pool Project の翻訳ガイドラインの翻訳対象には含まれていない[Terms of Service](https://www.ntppool.org/tos.html) を Google 翻訳にかけ、用語の前後にスペースを追加したり、注釈を加えるなどの手直しをおこなったものです。法的な利用の根拠としての使用は保証いたしかねます。英文と日本語訳との間で意味する内容、解釈が異なる場合、英文が正となります。
2019年12月3日 (3rd Dec 2019) 現在公開されているドキュメントに基づきます。
翻訳ガイドラインの翻訳対象に含まれているドキュメント及び PO ファイルは、別途[プルリクエスト](https://github.com/abh/ntppool/pull/182)しました。

# 規約 (Terms of Service)
このエンドユーザー向け利用規約（以下「TOS」）は、お客様（以下「エンドユーザー」）とDeveloper LLC（役員、取締役、関連会社、従業員、代理人、代表者、後継者および譲受人と併せて、以下「プロバイダー」）との関係を規定します。

## 1.
プロバイダーが提供する時間管理サービス（以下「サービス」）を使用することにより、エンドユーザーは、この TOS に関連して使用されるコンピューター機器を所有するエンティティを個別に、またはエンティティに代わって、本 TOS を読み、理解し、それに拘束されることに同意します。

## 2.
この契約は、エンドユーザーが最初にサービスにアクセスした日から有効になります。

## 3.
サービスにアクセスすることにより、エンドユーザーは以下を明示的に承認します。
### (a)
エンドユーザーと NTP プールの間で別途契約が結ばれない限り、プロバイダーが提供するサービスはボランティアによって提供され、プロバイダーはサービスに関する表明または保証を行いません。
### (b)
本サービスはベストエフォート型でのみ提供され、いかなる種類の保証も一切保証されません。
### (c)
サービスが提供する時間は、ネットワークの問題、サーバーの問題、人為的エラー、設定ミス、悪意のある侵入者、およびプロバイダーが制御できない他の原因を含み、これらに限定されないさまざまな要因により完全に間違っている可能性があります。

## 4.
エンドユーザーは、以下を行わないことに同意します。
### (a)
ntp デーモン（以下「NTPプロトコル」）を使用している場合、デフォルト設定を変更して、サービスのリクエストをより頻繁に行う。
### (b)
SNTPを使用する場合、30分ごとに1回以上サービスからの時間を要求。（理想的にはさらに長い間隔）
### (c)
デバイスの目的に必要な時間よりも頻繁に時間を設定。

デバイスが数日間合理的に正確な時間を維持できる場合、エンドユーザーは 1 時間ごとに時間を設定しません。
さらに、デバイスが秒単位のみを使用する場合、エンドユーザーはデバイスをミリ秒の精度で最適化しません。
### (d)
「時刻のトップ」、「分のトップ」、「X 分または X 秒」などの定期的な時間同期間隔を設定。[^1]

[^1]: 13時00分、12分00秒、毎時05分、毎分15秒などのような設定を指していると推測されます。

#### 時間設定の例
    悪い例: 毎日午前0時に時刻を設定。
    良い例: （特定の時間ではなく）起動時と起動後36時間ごとの時刻を設定。

    悪い例: 「分のトップ」（0秒）で90分ごとに時間を設定。
    良い例: 89分ごとに時間を設定し、さらに 0〜120 のランダムな秒数を設定。

    悪い例: 2分ごとに時間を設定。
    良い例: 必要に応じて時間を設定。たとえば、4時間ごとまたは毎日（またはそれほど頻繁ではありません） 

## 5.
プロバイダーは、独自の裁量で、虐待行為をブロックするための措置を講じる権利を留保します。 ただし、エンドユーザーは、アクセス制御が制限されているため、不正行為が他のエンドユーザーに付随的な損害を与える可能性があることを認め、同意します。

## 6.
プロバイダは、独自の裁量で、いつでもこの TOS を変更または交換できます。 この TOS の変更後のエンドユーザーによるサービスの継続使用は、そのような変更の承認を構成するものとします。

## 7.
エンドユーザーは、エンドユーザーのコンピューター、または不正確な時間を持っている他のシステムによって潜在的に被害を受ける可能性がある場合、そのユーザーまたはその人生、ビジネス、またはコミュニティを使用しないでください。
提供者が提供するサービスは、「現状有姿」で提供されるものであり、タイトル、非侵害、商品性および所有権の黙示的な保証を含むがこれらに限定されない、明示的または黙示的ないかなる保証もありません。
および任意のコースのパフォーマンスまたはトレードの使用によって暗示される保証は、明示的に否認されます。
プロバイダーは、サービスを通じて取得したデータまたは情報が正確、信頼できる、または完全であり、サービスの使用がエンドユーザーのリスクに限定されることを保証しません。
いかなる場合でも、プロバイダーは、サービスに関する契約、不法行為、厳格な責任、過失またはその他の法的理論の下で責任を負わないものとします
###（I）
あらゆる利益、代替品、またはサービス（ただし、いかなる場合でも）の特別、間接、偶発的、懲罰的、または結果的損害について
###（II）
バグ、ウイルス、トロイの木馬、またはそのようなもの（発信元に関わらず）
###（III）
エラー、脱落、不正確さ、またはエンドユーザーによるサービスの使用の結果として生じたあらゆる種類の損失または損害。

## 8.
この TOS は、法の抵触に関する規則を除き、カリフォルニア州の法律に準拠し、これに従って解釈されるものとします。

## 9.
この TOS は、プロバイダーとエンドユーザー間の完全な合意を表しており、以前のまたは同時期のすべてのコミュニケーションおよび提案（口頭、書面、または電子）に優先します。 この TOS のいずれかの規定が施行不能または無効であると判明した場合、 この条項は、この TOS がそれ以外の場合に完全な効力と効力を持ち、強制力を維持できるように、必要最小限に制限または削除されます。
pyenv シンプルに要点だけ

#開発環境
Linuxカーネル 4.15.0-54-generic

# 参考

[こちらが参考になりました！](https://amzn.to/3eD9M63)


# pyenvを入手する
今回は`pyenv`を`homeディレクトリ`へ配置しますが、パスを正しく通しさえすれば、どこへ配置しても大丈夫です。

```terminal:pyenvをgitから入手
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
```



 ```terminal:その他入れておくと幸せになるもの
sudo apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils libffi-dev
   ```


# つかえるようにパスを通す
私は`echo>>`使わない派なので最初のやり方を推奨します。

#### やり方その① ~/.bashrc(~/.bash_profile)に以下を追記する
```
# pyenvの設定
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi
```

#### やり方その② ターミナルでecho>>を実行
```
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
```
```
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
```
```
 echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bashrc
```
```
exec "$SHELL"
pyenv -v
```


#使い方


## pythonをインストール

```terminal:インストールできるpython一覧を取得
pyenv install -l
```

```:インストール
pyenv install 3.6.9
```

## バージョン管理

#### バージョン確認
```
pyenv versions
system
*3.6.9 ←これがいまのバージョンという見方
3.7.5
```

#### バージョン切り替え
```:システム全体で使いたいとき
pyenv global バージョン番号
```

```:ディレクトリ内だけで使いたいとき
pyenv local バージョン番号
```

#### pythonのフルパスを知る

通常のwhichコマンドで上手いことpyenvが選択中のpythonの場所を押してくれます。

```terminal:systemを選択中のとき
pyenv versions
*system
3.6.9
```

```:location
which python
> /home/osorezugoing/.pyenv/shims/python
```
新人エンジニアが新規事業を担当して失敗した話

はじめまして！
スタートアップでサーバーサイドエンジニアをやっています。なかのです！

[TechTrain Advent Calendar 2019(User ver)](https://qiita.com/advent-calendar/2019/techtrain)の6日目を担当します！
今回はタイトルの通り、新規事業の開発を経験して失敗した事や意識して開発に取り組めたら良かったことなどお話出来たらと思います！


## はじめに


簡単に私の経歴と新規事業についてお伝えしますと、

・今年2月に異業種からWebエンジニアに転職(エンジニア歴10ヶ月程)。
・メディア事業のサーバーサイドを担当していたが、9月中旬より新規事業の担当。
・前任者の方がα版(新規事業のコアな機能)まで開発をしていたが退職されてしまったため、自分はβ版に向けた開発から関わることに。
・基本的に社内でプロダクトに関わっているのはPM1人と自分だけで、あとは業務委託の方にお手伝い頂きながら開発。

このような感じで日々過ごしており、その中で経験したことをつらつらと書いていきます。


## １、 機能に対する認識合わせは明確にする


これは自分が今回の経験でもっとも失敗した部分です。

β版では要らない・実現が難しそうな機能が仕様に含まれていたり、PMがイメージしていた機能と実際に作成した機能が違っていたり、仕様書通りに実装してみたら仕様がおかしいことに気が付く、そもそも何の為に必要な機能なのか分からないなど、、。

開発のやり直しや仕様の練り直し、誰のボールか分からないタスクが発生するなど、うまく開発が進まずに時間だけが過ぎていく経験をしてしまいました。

今回の大きな問題点としては、**サービスの価値をチーム内で認識合わせが出来ていなく、コミュニケーション不足による認識の齟齬**だと思います。

このような失敗をなるべく起こさないように、今回は以下の取り組みを実施しました。

・slackなどのオンライン上のコミュニケーションでは、毎回何かしらの反応をすることで気軽に会話が出来る環境を作り、ログとして情報が残るようにする。
・細かな修正点やUIの表現方法などは事前にPMとデザイナーで形にした上でエンジニア側に落としていく。
・仕様に対する疑問点などは必ず担当者を決めて、タスク管理表に記載しておくことで誰のボールか分からないタスクが無いようにする。
・機能追加に関するタスクは必ずユースケースを洗い出して、エンジニアと設計を考える。
・毎日10分程度、開発の進捗や困っていることを共有する時間を作る。

まだまだ改善するべき部分はありますが、以前よりもやるべきことの解像度が上がり、タスクの完了スピードの向上や修正による時間ロスは確実に減っている実感があります。


## ２、 リリースやその後を意識した機能を設計する


初学者あるあるなのかもしれませんが、自分はローカル上だけで要件を満たした機能開発をおこなってしまっており、実際にどのような環境でユーザーに届けるのか？スケールする際には負荷分散を考えて機能が作られているか？冗長化した際にデータの整合性きちんと取れるのか？など、**本番環境を想定して開発出来ていなく**、いざインフラチームに環境構築を依頼した際、どのように環境を作ればいいのか分からないといった状況に陥ってしまいました。

基本的にサービスは開発してリリースし、その後も必ず運用・改善していくものだと思います。

・何人のユーザーからアクセスがあるのか
・アプリケーション上ではどのような処理を、どのくらいのユーザーが行うのか
・外部サービスにはどのような接続を行い、どのようなアプトプットを期待するのか
・冗長化した際の対応はどうするのか
・セキュリティ面は問題がないか

少し抽象的な記述ですが、最低限上記のことは常に頭に置いて開発するように心掛けています。

また、特にサービスのコアな機能やユーザーがよく使用する機能などはシーケンス図などを書いて説明することで、開発に着手していないエンジニアでも処理の流れが分かり、設計の相談や機能修正点の洗い出しがスムーズになりました。
<img width="438" alt="スクリーンショット 2019-12-07 11.21.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227345/8d6ee97d-8d94-4b8d-9888-85d399de2ddf.png">
(実際にはもっと細かくメソッド単位で書いたりしていますが、今回は雑に書いてます。すみません。。。)


## ３、 開発した機能に対して自分の考えを持つ


既存のサービスではある程度、開発時のルールや方針が決まっているため、それに沿って開発をしていればあまり悩むことなく日々の開発を進める事が出来ました。
しかし、今回0から開発のルールを考えたり、必要なライブラリーの導入などを行ってみると自分の考えが出せず、今までベテランのエンジニアの方々の意見がベストであると思ってしまい、**自分なりのベストな考え**を持っていなかったことを非常に痛感しました。
ネット上には無数に情報が散らばっているので、それを真似てそれっぽい機能が作れたとしても、全体のサービスとしては将来的には崩壊していくと思います。常に自分の意思を持ち、考えて、責任を持ってサービス開発の意思決定をしていくことで、個人の成長だけでなくサービスの向上にも繋がっていくと思います。

今回の経験を通して、まだまだ未熟ですが、少しずつ自分の中でルールを作りながら開発進めており、大きめの機能に関しては事前にスキーマ設計やクラス図などを書いて、ベテランのエンジニアにレビューして頂きながら自分の考えを言語化するようにしています。また未来の自分に向けて、開発ドキュメントに残すことも忘れずにやっています。

技術的な知見や設計などを悩んだ際はTechTrainで気軽にメンターの方に相談することも出来るので、積極的に利用してより良いサービス開発の為に活かしていこうと思います。


## おわりに


本記事では、新規事業の開発を経験して、もっと意識出来た方が良かった事を紹介しました。
この記事を書く事で、今回の経験を振り返る良いきっかけになったと共に、新規事業に関係なくエンジニアとして普段から意識して取り組むべきことだと感じました。また、完璧に改善出来ているという訳ではないので、日々挑戦しながら自分たちのチームが一番開発効率が上がる方法を探していきたいと思います！

新人エンジニアの人にとって少しでも参考になると嬉しいです。

[TechTrain Advent Calendar 2019](https://qiita.com/advent-calendar/2019/techtrain) まだまだ続きますので、気になった方はぜひ見てみてください！！！
GCP でDocker イメージを作る(tutorial のフォロー)

GCPの Cloud Build で [Docker のクイックスタート](https://cloud.google.com/cloud-build/docs/quickstart-docker?hl=ja) をフォローしてみました。

はまりポイントのメモと、最後に結局動かせなかった、という悲しいメモです。

## GCPの設定関係

以前に作成したプロジェクトは作成してあるものを確認。

```
$ gcloud projects list
```

なんだかＡＰＩというのが分からないので作り直した。console.cloud.google.com を開きましょう。

### Cloud build APIを有効に

Project を新たに作り、"Cloud Build API"を有効にします。ここで[GCP プロジェクトでの API の有効化](https://cloud.google.com/endpoints/docs/openapi/enable-api?hl=ja)を参考にしようとしましたが、サービスとAPIが同じものを指しているのか、よく分かりませんでしたが、特に問題にはならず。

まず、Projectを選択し、「＋ＡＰＩとサービスを有効化」のボタンを押します。
![GCP-Docker-API.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/438c5caa-9d4e-89e5-4981-10c97c6af17a.png)

どのサービスを有効にするかですが、検索窓でCloud Build と入力すると、Cloud Build APIを選択できます。

![コメント 2019-12-07 201618.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/b360e8c0-b306-54ff-0c85-2b7f46ec06c7.png)


それで有効にすると、できたっぽいです。料金はとりあえずはかかっていなそう様子。

![コメント 2019-12-07 201618aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/ce6ac27b-4093-0ede-c0e7-175e5bd653f2.png)

### gcloud のupdate

```
$ gcloud components update
```

を実行しますが、権限が無いと言われる。管理者権限でpower shell を立ち上げたところ、update できたみたい。あとは

```
$ gcloud auth login
$ gcloud config set project \[Project ID\]
```

### Windows でのchmod

その後、quickstart.sh と　DockerFile を作成します。quickstart.sh を chmod +x しろと指示があるのですが、power shell からできません。git bash で chmod +x してもダメ。Windows だと icacls を使うようです。

```
> icacls quickstart.sh  /grant Everyone:RX
処理ファイル: quickstart.sh
1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした
> icacls quickstart.sh
quickstart.sh Everyone:(RX)
              LAPTOP-MF1SNQEP\xapyt:(RX)
              NT AUTHORITY\SYSTEM:(I)(F)
              BUILTIN\Administrators:(I)(F)
              LAPTOP-MF1SNQEP\xapyt:(I)(F)
```

と出ているが、後で結局権限がないと言われました。

(追加)　別の方法として、

```
git add --chmod=+x -- quickstart.sh
```

で権限を与えたのですが、それでもだめでした。

### イメージの作成

DockerFile を用いてイメージ quichstart-imnage を作ります。

```
$ gcloud builds submit --tag gcr.io/[PROJECT_ID]/quickstart-image .
```

更に、cloudbuild.yaml を作成して、こちらからもbuild してみます。

```
gcloud builds submit --config cloudbuild.yaml .
```

cloudbuild.yaml は以下のファイルです。Tutorial に書かれています。

```
steps:
- name: 'gcr.io/cloud-builders/docker'
  args: [ 'build', '-t', 'gcr.io/$PROJECT_ID/quickstart-image', '.' ]
images:
- 'gcr.io/$PROJECT_ID/quickstart-image'
```

GCPのツールにある Cloud Build で、build したものを確認できます。
GCPのツールにある Container Rgistry にはプロジェクトで作成したイメージがあります。

Docker でrun しようとしますが、先ほどのquichstart.sh で実行権限を与えていなかったので、動かず。

```
> docker run gcr.io/projectID/quickstart-image
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"/quickstart.sh\": permission denied": unknown.
```

権限についてはいろいろ試したがダメ。膨大な時間をつぎ込んだ挙句敗退。ここまででした。

### イメージの削除

最後にGCPのブラウザの Container Registry でイメージを消しました。イメージ名がフォルダになっていて、中に入ると、「リポジトリ」があるので、それを「削除」します。そのフォルダの中身がなくなると、イメージ名も勝手に消えるようでした。」

### 参考

- [icalcsコマンドを使ってファイルアクセス権限を設定する方法](https://webbibouroku.com/Blog/Article/file-access-controll)
　：結局、私は chmod +x できなかったみたいですが。
Maplat Coreでマーカーを動的に表示する

Maplat Advent Calendar 7日目は、Maplat Coreでマーカーを動的に表示する方法です。
今日の動くものはここで確認できます。 => [CodeSandBox Maplat Advent Calendar day 7](https://codesandbox.io/s/maplat-advent-calendar-day7-dvmmj)

昨日のコードをベースに改造しますが、動的にPOIを追加するので、静的POI設定ファイル入らないので`pois/poi.json`は削除します。

次に、`index.html`、`app.css`に動的に追加するためのボタンの追加などを行います。
アプリ設定ファイルから、`pois`設定も削除します。

```index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Maplat Advent Calendar Day7</title>
    <link rel="stylesheet" href="app.css" />
  </head>
  <body>
    <div class="mainview">
      <div id="map_div"></div>
    </div>
    <div class="button">
      <button id="poi">POI追加</button>
    </div>
  </body>
  <script src="app.js"></script>
</html>
```

```app.css
.mainview {
  position: absolute;
  top: 5%;
  bottom: 5%;
  left: 5%;
  right: 5%;
}
.button {
  position: absolute;
  top: 95%;
  bottom: 0%;
  left: 5%;
  right: 5%;
}
```

```maplat_ac_day7.json
  "home_position": [139.5321, 36.249302],
  "default_zoom": 17,
  "start_from": "tatebayashi_ojozu",
  "sources": [
    {
      "mapID": "tatebayashi_ojozu",
      "setting_file": "https://s.maplat.jp/r/tatebayashimap/maps/tatebayashi_ojozu.json"
    },
    "osm"
  ]
}
```

続いて、JavaScriptに、POIピンを追加する処理`app.addMarker`を追加します。

```app.js
import "@maplat/core/dist/maplat_core.css";
import { MaplatApp } from "@maplat/core";

var option = {
  appid: "maplat_ac_day7"
};

var app = new MaplatApp(option);
app.waitReady.then(function() {
  document.getElementById("poi").addEventListener("click", function(e) {
    app.addMarker(
      {
        id: "castle",
        lat: 36.243881,
        lng: 139.543517,
        name: "館林城"
      },
      "main"
    );
  });
  app.addEventListener("clickMarker", function(evt) {
    app.selectMarker(evt.detail.namespace_id);
    console.log(evt.detail);
  });
  app.addEventListener("clickMap", function(evt) {
    app.unselectMarker();
    console.log(evt.detail);
  });
});
```

第一引数は、追加するPOIの設定で、昨日の記事では静的設定ファイルの中に書かれていた設定そのままです。
第二引数は、追加先のレイヤーIDを指定し、省略した場合はデフォルトレイヤーIDの`main`になります。

これを実行するとこんな感じです。
![タイトルなし3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10108/d704f43f-96e8-95f7-5cbb-576bd53e44b4.gif)

明日は、POIピンの画像を差し替えるサンプルを作ってみます。
Expressでsession管理をらくらくに

# はじめに

[いなたつアドカレ](https://qiita.com/advent-calendar/2019/allinatatsu)の七日目の記事です。

今回はexpressでsessionのチェックと管理をするためのやつです

## じっそー

まずはimportしましょーねー

```js
const express = require('express');
const app = express();

const session = require('express-session')({
    secret: 'userlogin',
    resave: false,
    saveUninitialized: false,
    cookie: null
});

```

sessionの各項目について説明します。
上から順に
- クッキーを暗号化するキー
- sessionを毎回生成するか
- 初期化していない時のsessionの扱い
- クッキーの有効期限

次に、appに反映させます。

```js
app.use(session);
```

そしてセッションを確認するための関数です

```js
const sessionCheck = (req, res, next) => {
    if (req.session.username)
        next()
    else {
        res.redirect('/signin');
    }
};
```

sessionの確認で条件分岐して、うまくいくと、ページを進めます。ダメだとサインインに飛ばします。

最後にsessionCheckの有効範囲を決めます
```js
app.use('/', signinRouter);
app.use('/', sessionCheck); // 以下のルートをチェック
app.use('/', indexRouter);
```

jsが上から読み込まれるため、signinRouterではsessionCheckがおこなわれず、indexRouterでのみsessionCheckがされ、無限に再帰されるといったことはありません。

今回の注意点は、sessionCheckを置く場所が一番上だと、永遠に再帰してしまい、アプリケーションが動作しません、反対に一番下にあると、全てで確認が行われないということになってしまいます。
なので、サインインが必要なページ、必要ないページをしっかりと、sessionCheckを仕切りにして分けましょう
Universal Robots向けのCLIツール作ってみた

# 目的

URを動かすためのツールを作ったので自慢したい

# 対象とする読者

この記事は仕事でUniversalRobotsのロボットを使う必要が出てきたプログラマ向けに書いています。

# 環境

- コントロールボックス CB3.1 SW3.4
- ロボット UR5
- 言語 python3.6
- 使用ライブラリ click

# 何を作ったか

スクリプトをコマンドラインから送ることのできるCLIツールを作りました。[この記事](https://qiita.com/MrBearing/items/a09ab5751be9333cddc5)で解説しましたが、Universal Robotsのロボットは外部からスクリプトでコントロールが可能です。

ロボットに送るスクリプトをコマンドラインから簡単にテストできるツールが欲しくて作りました。コマンドラインパーサーのclickを使って作ったので、ソース自体は数行でできました。

ソケット繋いで送るだけなので正直公開するか悩みましたが、とりあえずおいておきます。

もう少し機能を追加したら年内にはgithubで公開する予定です。。

アドベントカレンダー記事公開に間に合わなかった。。。

```python:urscript_sender.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import socket
import time
import sys
import click


def to_bytes(script_str):
    return bytes(script_str.encode())


@click.command(help='UR script sending program')
@click.option('-p', '--port', 'port', type=int, default=30002, help='UR robot TCP port. 3002 is default. value between 30001 to 30004')
@click.argument('host',type=str)
@click.argument('file_path', type=str)
def send_script(file_path, host, port):
    with open(file_path, 'r') as file:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.connect((host, port))
            script = ''.join(file) ## 文字列連結
            print(script)
            s.send(to_bytes(script))


def main():
    send_script()


if __name__ == '__main__':
    main()

```

# 今後やること
- Dashbord Serverにジョブコールに対応させる(Play Load等)
- サブコマンドをもう少し充実させる
- pipからインストールできるようにGithubで公開する
Azureの基礎　その４

#Azureアカウントを作成する

出展：https://docs.microsoft.com/ja-jp/learn/modules/create-an-azure-account/

##AzureアカウントとAzureサブスクリプション

###Azureアカウントとは
・Azureアカウントは、Azure Active Directory (Azure AD)、またはAzure ADから信頼されているディレクトリ (職場、学校組織など) におけるID
・Azureサブスクリプションとサービスを使用できるようにするためのグローバルに一意なエンティティ
・Azureアカウントを使用してAzureのWebサイトにサインインし、サービスを管理またはデプロイすることができる
・すべてのAzureアカウントは1つ以上のサブスクリプションに関連付けられる

###Azureサブスクリプションとは
・Microsoft Azureにリソースをプロビジョニングするために使用される論理コンテナー
・仮想マシンやデータベースなどのすべてのリソースの詳細が保持される
・すべてのAzureサブスクリプションはAzure ADと関連付けられる
・サブスクリプションのリソースにアクセスするユーザーとサービスは、最初にAzure ADで認証する必要がある

###サブスクリプションの種類
・Azure無料サブスクリプション
　　最初の30日間に任意のサービスで使用できる200ドルのクレジット、最も人気のあるAzure製品への12か月間の無料アクセス、いつでも無料の25以上の製品へのアクセスが含まれる

・Azure従量課金制サブスクリプション
　　従量課金制 (PAYG) サブスクリプションでは、利用者が1か月間の課金期間に使用したサービスに対して請求がなされる
　　個人から中小企業、および多くの大企業までの、広範なユーザーに適している

・Azureエンタープライズ契約
　　エンタープライズ契約では1つの契約でクラウドサービスやソフトウェアライセンスを柔軟に購入でき、新しいライセンスとソフトウェアアシュアランスについては割引がる
　　エンタープライズ規模の組織が対象

・Microsoft Azure for Studentsサブスクリプション
　　最初の12か月間に使用できる100ドルのAzureクレジットと、サインアップ時にクレジットカードが不要な厳選された無料サービスが含まれる
　　組織の自分のメールアドレスを使用して、自身の在学状況を証明する必要がある

##アカウントで複数のAzureサブスクリプションを使用する

・1つのAzureアカウントに複数のサブスクリプションを作成することができる
・アクセス制御と課金はサブスクリプションレベルで発生する（アカウントレベルではない）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545315/cf169cd8-6d06-f3bb-f18c-1fdf9d199481.png)

###アクセス管理
・自身のAzureアカウントに別の組織構造を示す複数のサブスクリプションを作成できる
・ユーザーが各サブスクリプションにプロビジョニングするリソースへのアクセスを管理および制御することを可能にする

###請求
・Azureサブスクリプションごとに毎月1件の請求書が生成される
・課金はサブスクリプション別に行われ、支払いはアカウント所有者が行う

##Azure Active Directoryを使用したアクセスの認証
・Azure ADに登録されているユーザー、アプリケーション、その他のエンティティは、1つのグローバルサービスにひとまとめにはされない
・Azure ADは個々のテナントに分割される
・テナントとは、他から分離されたAzure Active Directoryサービス専用のインスタンスであり、組織で所有および管理する
・組織のAzure ADの専用のインスタンスは、Microsoft Azure、Microsoft Intune、Office 365 などのMicrosoftクラウド サービスのサブスクリプションに新規登録したときに自動的に作成される
・Azure ADテナントとサブスクリプションには、一対多の信頼関係がありる
・テナントは複数のAzureサブスクリプションに関連付けることができるが、各サブスクリプションは1つのテナントとのみ関連付けられる
・Azure ADテナントごとにアカウントオーナーがおり、課金に対して責任を負う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545315/213e032e-ef74-dc69-7eca-d4b473d0f1cb.png)

##Azureのサポートオプション

###無料のサポートオプション
・課金とサブスクリプションのサポート
・Azure製品およびサービスのドキュメント
・オンラインセルフヘルプドキュメント
・ホワイトペーパー
・コミュニティサポートフォーラム

###有料のサポートオプション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545315/495ce0d6-b481-484d-07db-7143e752cb03.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545315/fea9b59d-dab7-3c87-59b5-70edcdd3f641.png)

###利用できるサポートプランと課金
・利用できるサポートプランと課金方法は、Azureの利用者のカテゴリおよびAzureサブスクリプションの種類による

###その他のサポートオプション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545315/8e9e45dc-95cd-c177-5ef4-f6187fe3346f.png)
twigでjsonを出力する

twig内で関数から受け取った値がjsonデータだったのでそのまま出力できないので対応策を調べた。

出力するためにはdecodeしてあげないといけない。
そのために独自関数を実装した。

```jsonDecodeTwigExtension.php

namespace Customize\Twig\Extension;

use Twig\Extension\AbstractExtension;

class jsonDecodeTwigExtension extends AbstractExtension
{
    public function getFilters()
    {
        return [
            new \Twig_Filter('json_decode', [$this, 'jsonDecodeFilter']),
        ];
    }

    /**
     * @param  null  $json
     *
     * @return mixed|null
     */
    public function jsonDecodeFilter($json = null)
    {
        if (! $json) {
            return null;
        }

        return json_decode($json, true);
    }
}

```

以下のようなjsonがあるとする。

```price.json

{
	"min": 5500,
	"max": 121000,
}
```
こうやって出力する。

```price.twig
{% set price = price | json_decode %}
{{ prices.min }}
```
【1-3日目】Rails Tutorial 第1章(1) Gitによるバージョン管理まで

#目的
※PdM(歴4年, 業務ではMySQLやGASを書く)、簡易的なApplication作ったり、Errorを見て問題箇所の把握くらいはできるレベル感である

- Rails Tutorial 1周目ではTestや応用箇所をSkipしてしまったため、振り返りながら習熟度を上げたい(一時期Pythonの勉強の期間のためブランクがある)
- よりEngineersとのコミュニケーションロスを減らしたい
- 2020のテーマが「継続力」「発信力」であり毎日継続的に発信をする習慣をつけたい

# 1日目

## 開発環境
- 1周目ではCloud9を使ったが今回はローカル環境を構築することにした
- まずはhomebrewでrbenvとruby-ruildをインストール

```
$ brew install rbenv ruby-build
```

パスを通す

```
$ echo 'export PATH="~/.rbenv/shims:/usr/local/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile

```

railsの最新verをinstallしglobalに設定

```
$ rbenv install 2.6.4
$ rbenv global 2.6.4
```

反映されているか確認

```
$ which ruby
/Users/user_name/.rbenv/shims/ruby
```

ruby versionも確認

```
$ ruby -v
rbenv: version `2.5.0' is not installed (set by /Users/user_name/Develop/.ruby-version)
```

ビギナーが何回か遭遇するやつ。ちなみに.bash_profileと.bashrcについて理解がなかったためこちらのQiitaを参考。 https://qiita.com/takutoki/items/021b804b9957fe65e093

```
$ rbenv local 2.6.4
$ ruby -v
ruby 2.6.4p104 (2019-08-28 revision 67798) [x86_64-darwin19]
```

railsのversion確認(すでにinstall済みのため)

```
$ rails -v
Rails is not currently installed on this system. To get the latest version, simply type:

    $ sudo gem install rails

You can then rerun your "rails" command.
```

以下を.bash_profileに記述。

```
$ export PATH="$HOME/.rbenv/shims:$PATH"
```

再度 `rails -v` 実行。

```
$ rails -v
Rails 6.0.1
```

無事バージョンの確認ができたのでrails newを実行

```
$ rails new hello_app
```

bundle install実行。

```
$ cd hello_app
$ sudo bundle install
```

```
$ rails server
```

`rails s`実行したら `Webpacker configuration file not found /Users/user_name/Develop/rails_tutorial/hello_app/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /Users/user_name/Develop/rails_tutorial/hello_app/config/webpacker.yml (RuntimeError)`

と言われたので webpacker install実行

```
$ rails webpacker:install
Webpacker requires Node.js >= 8.16.0 and you are using 8.9.4
Please upgrade Node.js https://nodejs.org/en/download/
```

node.jsのversionが低かかったため最新versionをインストール。再度`rails s`実行。

<img width="786" alt="スクリーンショット 2019-12-07 20.31.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334133/769f23da-8934-a67d-fefc-57c2d64a57f6.png">

今日はここまで。2hほど。
https://railstutorial.jp/chapters/beginning?version=5.1#cha-beginning

# 3日目
- 2日目はドキュメントを少し見返しただけ。気持ちを切り替えて就業後にすすめる。

システムセットアップ

```
$ git config --global user.name "Your Name"
$ git config --global user.email your.email@example.com

```

セットアップからコミット追加

```
$ git init
$ git add -A
$ git commit -m "Initialize repository"
```
Firestoreの性能チューニング

# はじめに

DataflowでFirestoreに大量データを投入する機会があって、性能チューニング周りで苦労したのでまとめておく。

大人の事情でサンプルコードは出せないので、概念だけ。

# TL;DR

- とにかくエラーレスポンスを発生させないことが大事
- https://firebase.google.com/docs/firestore/best-practices?hl=ja を真面目に全部やる

# やりたかったこと

- 約1億件のデータを、なるべく短時間でfirestoreにインポートしたい
- インポートは、dataflowを使って並列処理で行う

# 基本戦略
## エラーが起きたらリトライ
並列処理だと、クオータに引っかかったり、サーバ側がたまたま過負荷だったりして、リクエストが正しくてもエラー応答を食らうことがまれによくある。そのため、リトライの機構が必須。（負荷起因のエラーなら、同じリクエストを投げ続ければ、いつかは成功する）

リトライ戦略は、 Exponential backoff を採用。
（GCSのページだけど、 https://cloud.google.com/storage/docs/exponential-backoff?hl=ja あたりが参考になる）

要は　1回目 1000ms待つ, 2回目 2000ms待つ, 3回目 4000ms待つ, , , と waitを倍々していくリトライ戦略。
pythonなら、 https://pypi.org/project/retry/ あたりで実装されている。


## とはいえ、エラーは極力起こさないように努める

### エラーが! 消えるまで！ 投げるのを！　やめない！
という戦略を取るので、一見、エラーが起きても気にせず実行すれば良い気がしてくる。

しかし、 前述の exponential backoffは、リトライ回数が増えるごとにwaitが指数関数的に増えるので、エラーが連続すればするほど、waitが伸び、トータルの実行時間に響いてくる。
よって、エラーをなるべく起こさない投げ方をするほうが、結果的に早く終わる。

# エラーを起こさないために出来ること

ここからは、エラーの発生を抑えつつ、秒あたりのリクエスト量を最大化するために実施したことを並べていく。
世の中にはあまり動作するサンプルがなかったので苦労した。（公開出来ないのが悲しい）

## ID設計
連番IDで書き込むと、書き込み先が分散しないので性能が出ない。

Quotaとは直接関係しないが、 インスタンスのスケール速度を上回るリクエストを投げると、 5xx系のエラーが返ってくるため、書き込み先を分散させるために、連番のIDはhash化するなど、程よく分散させる必要がある。

## リクエストレート
firestoreは、リクエスト量に応じて段階的にスケールするらしく、いきなり Quotaギリギリで投げると耐えられないことがある。そこで、スケールする時間を稼ぐために、 500/50/5ルール に従って段階的にリクエストを増やす必要がある。
具体的には
```新しいコレクションに対するオペレーションは、毎秒 500 回を上限とし、その後、5 分ごとにトラフィックを 50% 増やしていく```

この制御はSDKでは出来ないので、dataflowジョブ側で実装する必要があった。
Dataflowは並列実行でfirestoreにリクエストを投げるため、1workerあたりの秒間リクエストが 500/worker数 からスタートするように制御する。そしてそれぞれのジョブが、5分ごとに50%ずつリクエスト量を増やす。
リクエスト量の調整は、リクエスト送信後に一定時間のwaitをかませることで実現した。

なお、ジョブ数の計算が複雑になるので、Dataflowのオートスケールは無効にして、最初から最後まで同数のworkerで実行した。

注意点

- リクエスト量を増やしすぎると今度はQuotaにぶつかるので注意
- waitの計算時に、firestoreのTATを考慮(減算)すると少しだけ効率が良くなる


## Indexの無効化
Googleに聞いた話の中に、documentのInsert/Updateとは別に、Indexを作成しているジョブがあり、こちらも負荷に応じてスケールしているという話があった。
この、Index作成の負荷も馬鹿にならず、5xxエラーの原因になりうるとのことだった。

ということで、不要なIndexを作成しないように設定を行う。
具体的には、　インポートを始める前に、以下のリンク先の手順に従い、Indexの除外設定を行えばよい。
https://firebase.google.com/docs/firestore/best-practices?hl=ja#index_exemptions

注意点

- 除外設定はコレクション、フィールド単位で行う必要がある。
- すでにドキュメントが存在するコレクションに対してIndex除外設定を追加すると、Index削除のジョブが走ってしまうので、それもまた新たな負荷になってしまう。
   - Index除外設定は、空っぽのCollectionに対して行うようにする
   - どうしても、ドキュメントが存在するコレクションに行いたい場合は、設定してからIndexが削除されるまで待つ（Doc量によるが、私は確実を期すため、帰りがけに実施して翌朝から作業再開した）

# その他、知っておくと役に立ちそうなこと

## エラーの種類

正直、調べても満足な情報が出てこない。大まかに以下のように理解して、試行錯誤を続けた。

### 489エラー（Deadline Exceed）

自分が API Limit にぶつかったときのレスポンス。
よって、リクエスト量（秒間write数、データ量）を再計算し、 API Limit を下回るように調整する必要がある。

### 500, 503エラー

自分は API Limit に抵触していないが、スケール速度を超えて負荷をかけてしまった場合や、（運悪く）他のユーザの負荷が同時にかかっていて、Firestoreサイドが耐えられなかった場合のエラー。
前述のホットスポットや 500/50/5ルールなどを見直して、原因を予想しながらエラーの発生を抑えるチューニングをする必要がある。
（ただし、実行時間をずらすだけで解消する場合や、　ただDataflowジョブを実行し直すだけで解消する場合もあるので、運も絡む）

# 結論

Firestoreはちゃんと調教すればできる子。
Code for Fukuoka の2019年の振り返りと来年に残すもの

# Code for Fukuoka の2019年振り返り
## 1月
2018年に依頼した公園データが福岡市から2018年１２月にオープンデータとして公開され、１月には北九州市からもオープンデータとして公開されました。
福岡県のオープンデータ関連会議でご一緒したことで公園データの必要性が伝わりました。

## 2月
Code for Brigade Meetup Kyushu が佐賀で開催され、九州中のシビックテックプレイヤーが参加しました！ 
Code for Fukuokaも参加し、福岡市さんと一緒に行ったデータアカデミー研修についてもお話ししました。

ふくおかAI・IoT祭りにて、シビックテックシンポジウムを開催しました。
九州内のシビックテックプレイヤーがまた集まり、お話ししました。

## ３月
アーバンデータチャレンジ2018最終シンポジウムに参加しました。
再スタート（2018.3)から初めての参加となったアーバンデータチャレンジの1年が終わりました。
全国のシビックテックプレイヤーとの交流のできる場として良い体験をさせていただきました。

Code for Fukuoka定例会にて、2018年度の振り返りをしました。
グラレコで1年の再スタート後の活動を振り返り、来年度について話し合いました。

## 5月
2019年度キックオフの定例会をしました。
3月に話した内容をもとに1年間の活動を話し合いました。
今年はいよいよ公園アプリを開発することとなりました。

また、今年はシビックテック関係のイベントになるべく全て参加することを決めました。

## 6月
福岡市中央区の公園係様に来ていただき、公園管理の実情など管理側のことを詳しく聞きました。
利用する側、管理する側共に役立つアプリへと考えが進んでいきます。

CIVIC TECH FORUM 2019にて、Code for Fukuokaの話（公園の話）をしました。
全国のシビックテックプレイヤーの話が聞けると共に、Code for Fukuokaの話を聞いてくださった方からお声掛けもいただきました。

## 7月
アーバンデータチャレンジ2019のキックオフシンポジウムに参加しました。
2年目となる今回は顔なじみが増えており、また、Code for Kurumeとも一緒に参加でき、楽しい会でした。

アーバンデータチャレンジ福岡ブロックのキックオフイベントを久留米で行いました。
今年もCode for Kurumeと一緒に福岡ブロック進めていきますが、まずはこのキックオフイベントに久留米市、福岡市の方もいらっしゃってたいへん盛り上がりました！
こども率も高くなりました。

## 8月
福岡市にエンジニアカフェができました！
そのオープニングイベントでCode for Fukuokaも参加しました。
CIVIC TECH FORUMの理事である伴野智樹さんと、九州大学の荒川豊さん（去年までCode for Ikomaでもご活躍）とパネルディスカッションしました。

## 9月
Code for Japan　Summitに参加しました！
登壇はないですが、グラレコスタッフとして参加しました。
Summit初参加でしたのでその規模の大きさにびっくりしました。

## 10月
11月のイベントにむけて企画会議とデータ作成勉強会をしました。
Code for Kurumeのアーバンデータチャレンジ福岡ブロックイベント、アイデアソンにグラレコスタッフとして参加しました。

福岡市に公園のシェイプデータのオープンデータ化の依頼に行きました。

## 11月
Code for Fukuokaものづくり部を発足しました！
Code for Gifuの石井哲治さんが福岡に来てくださったこともあり
一緒に編み物とレーザーカッターによるアクリルパーツ・木製パーツ作りの部活動始めました。

U-16プログラミングコンテスト福岡大会の共催になり、第１回大会に参加しました。
子どもの発想すばらしいです。

Code for Saga、Code for Kumamotoのアーバンデータチャレンジ2019イベント、アイデアソンにグラレコスタッフとして参加しました。

アーバンデータチャレンジ2019イベント、公園HACK DAYという開発イベント開催しました。
機能別の開発チームに分かれて、また非エンジニア向けにデータ作成チーム、子ども向けに好きな公園考える子どもチームも作って１日イベントしました。
アプリ開発に続く成果が出るイベントとなりました。

## 12月
ものづくり部第２回を開催しました。
Code for Gifu手芸部のイベントとオンラインでつないで
子どもも参加して賑やかな会となりました。

Code for Fukuoka再スタートからの2年目、振り返りました。
当初予定していたアプリ開発も進んでいますが、今年はグラレコやものづくり部など非ITなことを通して各地域との連携が強まった気がします。

今年したかったことで衛星データと公園を絡めたイベントができなかったので
来年は衛星データを使ったイベントをしたいと思います。
公園に関するオープンデータ化の促進やアプリ開発は引き続き進めていこうと思います。

1年の振り返りって良いですね。
サーチ画面におけるキーボードショートカット

⌘＋⇧＋F　使ってますか？
Ctrl-¥ の方でしょうか？

リンク先 [ここ](https://docs.splunk.com/Documentation/Splunk/8.0.0/Search/Parsingsearches) をみれば全て載っていいるので改めて書くのもなんなんですが、少し紹介してみます。
なお、基本的に🍎　読み替えてもらうと幸いです。

#検索と置換
| Action | Linux or Windows | Mac OSX |
|:--|:--|:--|
| Find a term. | Ctrl + F | Command + F |
| Find and replace a term. | Ctrl + H | Command + Option + F |
と書いてますが、⌘＋Fを２回押すと検索から置換に変化してくれます。
正規表現ＯＫ
#編集
| Action | Linux or Windows | Mac OSX |
|:--|:--|:--|
| 改行| Shift + Enter | Shift + Enter |
| 行削除 | Ctrl + D | Command + D |
| 指定した行を下にコピー | Alt + Shift + Down arrow | Command + Option + Down arrow |
| 指定した行を上にコピー| Alt + Shift + Up arrow | Command + Option + Up arrow |
| 上と入れ替え | Alt + Down arrow | Option + Down arrow |
| 下と入れ替え | Alt + Up arrow | Option + Up arrow |
| カーソルから行末まで削除 | Alt + Delete | Control + K |
| カーソルから行頭まで削除 | Alt + Backspace | Command + Delete |
| カーソルの右の単語を削除| Ctrl + Delete | Alt + Delete |
| カーソルの左の単語を削除 | Ctrl + Backspace | Option + Delete |
テキストエディタいらないですね。
#サーチアシスタント画面
| Action | Linux or Windows | Mac OSX |
|:--|:--|:--|
| サーチアシスタント画面に移動 | Down arrow key | Down arrow key |
| サーチアシスタント画面を終了 | ESC | ESC |
| サーチアシスタント画面を再開 | Ctrl + Space | Control + Space |
| サーチアシスタント画面での指定| Use the Up arrow and Down arrow keys to highlight the item and press Enter. | Use the Up arrow and Down arrow keys to highlight the item and press Enter. |
| サーチアシスタント画面詳細への切り替え | Tab | Tab |
困った時のサーチアシスタント。
自分のところだと　⌃+Spaceが_Spotlight_になっているので　⌃+\で切り替えている。
#元に戻す、やり直す
| Action | Linux or Windows | Mac OSX |
|:--|:--|:--|
| 元に戻す| Ctrl + Z | Command + Z |
| やり直す | Ctrl + Y or<br> Ctrl + Shift + Z | Command + Y or<br> Command + Shift + Z |
#整形
| Action | Linux or Windows | Mac OSX |
|:--|:--|:--|
| 整形| Ctrl + ¥ | Command + \ or<br> Command + Shift + F |
インテンド等揃えてくれます。感謝
#まとめ
>This documentation applies to the following versions of Splunk® Enterprise: 7.2.0, 7.2.1, 7.2.2, 7.2.3, 7.2.4, 7.2.5, 7.2.6, 7.2.7, 7.2.8, 7.2.9, 7.3.0, 7.3.1, 7.3.2, 7.3.3, 8.0.0

６系のサポート切れが間近になって、これらのショートカットキーがこれからも活躍できます。
しっかり覚えて、SPLをマスターしましょう。

Happy Splunking!
Pythonと正規表現で汚いデータをとっちめる

# 前置き
普段データの前処理などをやってます。
たいていのデータはpandasで読めればなんとかなるけど、読めないデータに遭遇することもあるので奴らとの格闘の記録を残しておきます。

# どんなデータか
- 区切り文字はカンマ「,」で各データはダブルクォート「"」で囲まれている。
- データ中（"と"の間）に改行コードが含まれている。
- データ中にカンマが含まれている。
- データ中にダブルクォートが含まれている。

↓例えるならこんな感じ

```
"a","b"
"1","ほ\nけ""
"2","ふ,か'"
```

※オマケにシングルクォートも足しました。

# 目指すもの
- Pythonのライブラリであるpandasのread.csv()で読み込めるcsvファイルを作成する。
  - あくまで前処理の前段部分なのでこの後の処理のためにもDataFrameにしたい。
- カンマやクォートは意味がある可能性を考慮してそのままデータの一部として扱う。
- データ中の改行コードは悪さしかしないので取り除く。

↓つまりこういうDataFrameにしたい。

|a|b|
|:---:|:---:|
|1|ほけ"|
|2|ふ,'か'|

# 失敗例
### pandasでそのまま読もうとする

```python
import pandas as pd

df = pd.read_csv('hoge.csv')
print(df)
```

### 結果
||a|b|
|---|:---:|:---:|
|1|ほ\nけ"\n2"|ふ,か'|

# 成功したやり方
### スクリプト
- Pythonのバージョンは3.7

```python
import re
import pandas as pd

# テキストとして読み込む
with open('hoge.csv', 'r') as f:
    text = f.read()

tmp_text = re.sub('([^"])\n([^"])', r'\1\2', text) # データ途中の改行コード(\n)を取り除く
tmp_text = re.sub('","', '\t', tmp_text)           # 区切り文字をタブに変換
tmp_text = re.sub('(^"|"$)', '', tmp_text)         # ファイルの最初と最後のクォートを外す
tmp_text = re.sub('"\n"', '\n', tmp_text)          # 途中のクォートを外す

# いったんファイルに吐き出す
with open('data.csv', 'w') as f:
    f.write(tmp_text)

# 確認する
df = pd.read_csv('data.csv', sep='\t')
print(df)
```

```:出力
   a     b
0  1   ほけ"
1  2  ふ,か'
```

読めた。

### ファイル
ファイルの中身はこんな感じ

```:data.csv
a	b
1	ほけ"
2	ふ,か'
```

# 懸念事項
データに\tが含まれていた場合、今回のコードでは当然うまくいかない。
改行コードが違った場合も同様。
どの文字が含まれていて、どう置き換えればうまくいくかチェックする必要がある。
→チェック用のメソッド作成と、区切り文字のパラメータ化？

気が向いたらやる。
jupyter上で処理すればデータの確認もソースの変更も楽なので必要ないかも…？

# 結論
pandasで読めてしまえばもうこっちのもの。
pandasだけでなく、BIツールに食わせる前にも使えるはず。

**正規表現って便利！！**
VICONを用いてUnityでVtuberになる！

##はじめに
この記事はVTuber Tech #1 Advent Calendar 2019 11日目の記事です。

Unityエンジニアの[ゆず](https://twitter.com/Yuzu_Unity)です。

今回は趣味でVICONを使い…
リアルタイムにUnity上でVtuberになれるようにしていたのでそれを記事にします…
ぜひ皆さんも参考にやってみよう！

※モーションキャプチャー提供
aex inc. SHIROMIStudio

##Vicon(バイコン)とは？
![vicon.jpg](https://www.crescentinc.co.jp/images/vicon/vantage/vantagebanner.jpg)
簡単に言うとつよつよな光学式モーションキャプチャー

光学式という点においてはViveと一緒
価格も一…

※正直Vtubderが使うしろものではない…

とれないもの
表情＆指の動き
別途機材等を用いる

##環境構築
とりあえずVIVE Pro Eyeフルセットを数百台ほど買える金額を用意し下記をそろえる
もちろんそこそこに広い場所も必要

 * Viconフルセット（Blade/Shogun）（有料）
 * Motionbuilder（有料）
 * Unity（無料～）
 * MeshSync（無料）
 * PC3台(Blade/Shogun用、Motionbuilder用、Untiy用　有線ローカルネットワークに接続,ポート開放必須)

まぁスーツ1着も1 VIVE Pro Eyeフルセットなんですがね…

##VICONが使われるまでの流れ
Blade/Shogun使う際の流れ
(BladeとShogunには宗教戦争、もはや自作みたいなこともあったり…
Bladeは、マニュアル、Shogunはオートみたいな感じですかね。)

1. VICONカメラ起動！

2. 放置…。（すぐ使うと精度が悪く放置しないといけない…）

3. カメラキャリブレーション‼
マスク（最初からなにかしらの理由で反射している部分を誤認識しないように）を切り
次に棒をひたすら振り回す‼
![CALIB.png](https://www.vicon.com/cms/wp-content/uploads/2019/06/calibration.jpg)
最後に水平面を認識したら終わり‼

4. アクターさんにマーカーをつけキャラクターキャリブレーション
マーカーはきちんとつけましょう(ずれないように…)
![markar.JPG](https://1.bp.blogspot.com/-tSUvghs88R8/VK_dY5WSJII/AAAAAAAAAig/yYyIlodB9vg/s1600/Capture.JPG)
次にするVicon体操はよくテストにでるので覚えておきましょう！
https://www.youtube.com/watch?v=lGnSYjrh1zc
この体操をもとにマーカーの点群データを
人間の体のボーンをにソフト上で作成します！


で、ここでやっとVICONが使えるようになります…（な、長い）
![shogun.png](https://www.crescentinc.co.jp/images/vicon/software/shogun/soft_shogun_overray.png)
さらっと書いていますが
正直使う気失せるくらいには面倒でバグったりします…

#Blade/ShogunからMotionbuilderへモーションをデータ転送する
直接Unityへデータ転送できますがMotionbuilderのリターゲット機能は強いので
Motionbuilderでリターゲットを行います
公式から無料（値段あっても誤差）でプラグインが配布されているのでそれを用いるだけです。

キャラクタライズを行い自分のキャラクタライズ済みキャラクターへリターゲットできるように設定します。

#MeshSyncを用いMotionBuilderとUnityを連動させます。

プラグインが売ってるみたいですが、今回はMeshSync経由です。(それくらい作れそれはそう)

MeshSyncとは各DCCツールの3Dデータをuntiyにリアルタイムに同期するツールです
https://github.com/unity3d-jp/MeshSync

キャラクターを用意します（Unity＆fbx）

* Motionbuilder側
キャラクターのfbxを用意しMotionbuilderで読み込ませ
そのボーンデータのみunityに転送します

* Unity側
ボーンデータが送られてくるので
そのHumanoidボーンの位置/回転情報をキャラクターに適用することで
DynamicBone等の物理演算を併用しつつキャラクターを動かすことができます。

Demo
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">blog用 <a href="https://t.co/3z6JG1k56s">pic.twitter.com/3z6JG1k56s</a></p>&mdash; ゆず@バーチャルクリエイター (@Yuzu_Unity) <a href="https://twitter.com/Yuzu_Unity/status/1203298411178364928?ref_src=twsrc%5Etfw">December 7, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

これでやっとリアルタイムにViconを用いVtuberになれました…

![ViconVtubder (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/e044d3a6-f6e3-bca9-3a39-3a3556369e0e.png)


##まとめ
理論上は自分でアクタースーツを着ることにより
無線マウス等を駆使すれば一人でViconを扱いVtuberになれることが分かった。

今後1人でViconを用いた配信をする個人Vtuberが出てくることを期待しようと思う。

Viconを使った動画はまた今度…


![unitychan.png](https://unity-chan.com/images/imageLicenseLogo.png)
Windowsにおいて、"echo %path%"とシステムのプロパティ>環境変数>Pathの値が違う問題

#背景
Rをインストールするときに「RtoolsをPATHに追加」をオンにしていたところ、RtoolsのmakeがMSYSのmakeを奪ってしまったため、PATHから削除しようと思ったら`システムのプロパティ>環境変数>Path`にはRtoolsが存在しませんでした。

おかしいと思い、`echo %path%`を行ないましたが、そこにはRtoolsが含まれています。

これらを踏まえ、原因を調査しました。

#結果
どうやら、内部で普通の環境変数の`PATH`以外にも`PATH`の値を保持しているようです。

レジストリ(スタートでレジストリエディタと検索すると見れます)内を検索したところ、`コンピューター\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment`の`Path`のところに`echo %path%`と同様な値が入っていました。

ここを変更し、再起動すると、`echo %PATH%`の値も変化することを確認しました。

#最後に
アンインストールしても消えず、かなり困りましたので、同じような悩みの人のため、記しておきます。他にも、DockerやGithubDesktopのパス名が書いてありましたので、場合によってはそれで困っている人がいると思われます。~~せめてRのアンインストーラが消してくれ~~
pythonでtreemap(面積グラフ）を作ったら微妙だったからflourishを使ったらまあまあいい感じになった

# つまり？
matplotlibだったら

![treemap3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/b003523e-4e94-f663-1b4a-9c4a6202a46a.png)

flourishだったら
<img width="1285" alt="スクリーンショット 2019-12-07 19.49.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/f2186f50-61f2-1060-6d3a-7d0f3fa524ce.png">

# データの出典元
https://www.stat.go.jp/data/nihon/02.html




# pythonで作る場合[^1]
もしも、treemap用のライブラリ、```squarify```が無ければ

```
pip3 install squarify
```


```python
# lib
import pandas as pd
import squarify #Treemap Ploting
import matplotlib
from matplotlib import style
import matplotlib.pyplot as plt
import seaborn as sns

# Activate Seaborn
sns.set()
%matplotlib inline

# サイズとフォント設定
matplotlib.rcParams['figure.figsize'] = (16.0, 9.0)
plt.rcParams['font.family'] = 'Hiragino Sans'  
plt.rcParams['font.weight'] = 'bold'

# ggplot style使用
style.use('ggplot')

# dataframe 作成
population = [7369,3788,14360,21356,19476,22431,43248]
label = ["中国(5.58%)","四国(2.87%)","九州・沖縄\n(10.88%)","中部(16.18%)","北海道・東北(14.75%)","関西(16.99%)","関東(32.76%)"]
percentage = [5.58,2.87,10.88,16.18,14.75,16.99,32.76]
df = pd.DataFrame({"Population":population,"Label":label,"Percentage":percentage})

fig, ax = plt.subplots()
# Colormap
cmap = matplotlib.cm.Blues
# Min and Max Values
mini = min(df["Population"])
maxi = max(df["Population"])
# colors setting
norm = matplotlib.colors.Normalize(vmin=mini, vmax=maxi)
colors = [cmap(norm(value)) for value in df["Population"]]
# Plotting
squarify.plot(sizes=df["Population"], label=df["Label"], alpha=0.8, color=colors, text_kwargs={'fontsize':24,'color':'grey'})
# 軸削除
plt.axis('off')
# y軸逆に
plt.gca().invert_yaxis()
# タイトル、位置設定
plt.title("日本の地域別人口比率", fontsize=32,fontweight="bold")
ttl = ax.title
ttl.set_position([.5, 1.05])
# 背景色
fig.set_facecolor('#eeffee')
```
ってやると
![treemap3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/b003523e-4e94-f663-1b4a-9c4a6202a46a.png)

こうなります。
なんかダサいですよね…

そこで、いい感じの可視化が出来るサービスflourish:https://app.flourish.studio/ を使ってやってみます。
# flourishを使う場合
登録は適当にgoogleアカウントとかつかってやってください。

1. new projectを選択
<img width="1176" alt="スクリーンショット 2019-12-07 20.07.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/5873f309-7b87-88bd-cda8-746e82099635.png">

2. treemapを選択
<img width="1637" alt="スクリーンショット 2019-12-07 20.08.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/becd424d-7582-b80e-6f51-e1d0e5efd1a9.png">


とすると作成できます。
今回使ったデータでは以下のようにしています。
<img width="1660" alt="スクリーンショット 2019-12-07 20.13.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/37278295-01a3-6437-c599-d82014b3bdd1.png">

Nestingは地域→都道府県で設定しています。
Size byはもちろん平成29年の推計人口を指定しています。
ご覧の通り日本語も使えますし、Excelなどの表計算ツールと同じような感じで操作できます。

flourishを使ったtreemapを再掲しておきます。
（普通にダウンロードするとラベルが消えてしまうのでスクリーンショットしています）
<img width="1285" alt="スクリーンショット 2019-12-07 19.49.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196857/ece91219-c495-73cc-5b76-0abd57b9d983.png">




[^1]: https://mubaris.com/posts/dataviz-treemaps/
Mac に Laravel6.X のローカル開発環境構築

ブラウザで VM に設置した Laravel6 プロジェクトのトップページを表示するまでの作業ログ
本家が提供してくれてる Homestead なるもので簡単に出来るらしい。

## 各種インストール

### VirtualBox をインストール

https://www.virtualbox.org/wiki/Downloads

### Vagrant をインストール

https://www.vagrantup.com/downloads.html

### Homestead Vagrant Box のインストール

今回は Homestead も 共有フォルダ(後述) もユーザーの Home に設置する。

```
$ cd ~
$ vagrant box add laravel/homestead
```
※ダウンロードに数十分ぐらいかかった

### Homestead のインストール

```
$ git clone https://github.com/laravel/homestead.git ~/Homestead

$ cd ~/Homestead

$ bash init.sh
```

## Homestead の設定ファイルを修正する

$ vi Homestead.yaml

`authorize` と `keys` の項目は公開鍵＆秘密鍵を記述するだけなので省略

下記の内容で一部書き換え

|項目|名称|
|---|---|
|Mac - VM 間の共有フォルダ名|tukanpo-proj|
|Laravel プロジェクト名|tukanpo|
|DB名|tukanpo|

```
folders:
    - map: ~/tukanpo-proj
      to: /home/vagrant/tukanpo-proj

sites:
    - map: tukanpo.test
      to: /home/vagrant/tukanpo-proj/tukanpo/public

databases:
    - tukanpo
```

## mac に共有フォルダ作成

```
$ mkdir ~/tukanpo-proj
$ chmod 755 ~/tukanpo-proj
```

## Vagrant のインスタンスを起動する

```
$ vagrant up
```

## Vagrant へ接続

```
$ vagrant ssh
```

```
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-72-generic x86_64)

Thanks for using
 _                               _                 _
| |                             | |               | |
| |__   ___  _ __ ___   ___  ___| |_ ___  __ _  __| |
| '_ \ / _ \| '_ ` _ \ / _ \/ __| __/ _ \/ _` |/ _` |
| | | | (_) | | | | | |  __/\__ \ ||  __/ (_| | (_| |
|_| |_|\___/|_| |_| |_|\___||___/\__\___|\__,_|\__,_|

* Homestead v10.0.0 released
* Settler v9.1.0 released

0 packages can be updated.
0 updates are security updates.


vagrant@homestead:~$
```

## Laravel プロジェクト生成

```
vagrant@homestead:~$ cd tukanpo-proj
vagrant@homestead:~/tukanpo-proj$ composer create-project --prefer-dist laravel/laravel tukanpo
```

※ Laravel のバージョン指定するには別途コマンドに追記が必要

## 仮想サーバーのホスト名解決

mac の hosts に下記を追加

```
$ sudo vi /etc/hosts
```

```
192.168.10.10   tukanpo.test
```

## 確認

http://tukanpo.test

### 接続できないとき

自分は `Homestead.yaml` の `folders` と `sites` の設定ミスでハマった。

`Homestead.yaml` の `sites` プロパティを修正する場合は下記のコマンドを実行しないと更新されないので注意。

```
$ vagrant reload --provision
```

## バージョン確認方法

### Laravel

````
vagrant@homestead:~/tukanpo-proj/tukanpo$ php artisan -V
Laravel Framework 6.6.2
```

### Homestead

```
$ vi ~/Homestead/bin/homestead
```

この行

```php
$app = new Symfony\Component\Console\Application('Laravel Homestead', '10.0.1');
```

## ここで一旦保存

リモートリポジトリは事前に作っておく

```
$ cd ~/tukanpo-proj
$ git init
$ git add .
$ git commit
$ git remote add origin git@github.com:tukanpo/tukanpo-proj.git
$ git fetch
$ git merge --allow-unrelated-histories origin/master
```

## 参考

https://qiita.com/oreo3@github/items/1705b133e00019800ff6
Mac に zsh と prezto インストール作業ログ

以前 Mac に zsh + prezto 導入した時のメモ  

## Homebrewをインストール

リンク先の通りにインストール

https://brew.sh/index_ja.html

## git をインストール

```
$ brew install git
```

## zsh をインストール

```
$ brew install zsh
```

### /etc/shells にインストールした zsh のパスを追記

```
$ sudo vim /etc/shells
```

```
...
/bin/bash
/bin/csh
...
/bin/zsh
/usr/local/bin/zsh # ← ここ
```

### 起動時のシェルを変更

```
$ chsh -s /usr/local/bin/zsh
```

ターミナルを再起動

```
Last login: Sat Jan 20 17:39:50 on ttys000
This is the Z Shell configuration function for new users,
zsh-newuser-install.
You are seeing this message because you have no zsh startup files
(the files .zshenv, .zprofile, .zshrc, .zlogin in the directory
~).  This function can help you with a few settings that should
make your use of the shell easier.

You can:

(q)  Quit and do nothing.  The function will be run again next time.

(0)  Exit, creating the file ~/.zshrc containing just a comment.
     That will prevent this function being run again.

(1)  Continue to the main menu.

--- Type one of the keys in parentheses --- 0
```

## prezto をインストール

https://github.com/sorin-ionescu/prezto

```
$ git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"
```

## その他

ターミナルを iTerm2 にして Preferences > Profiles > Colors > Color Presets を `Pastel` にするといい感じになる。
![vagrant@homestead: ~ 2019-12-07 19-46-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/de8d5a90-7135-7cbe-6480-758f3c1f2966.png)
様々な言語でFizzBuzzプログラムを書いてみた

# いろいろな言語でFizzBuzzを書いてみた

本日は<a href="https://adventar.org/calendars/4759">Advent Calender</a>の7日目になります。
## はじめに
私自身、Advent Calendarに初投稿ということで、な・な・なんと今回は、ジャブ程度に`Python`・`Ruby`・`JS`でFizzBuzzを書いて見ました。

## FizzBuzzって何？
>「３」で割り切れる数値を引数に渡すと、’Fizz'を返す。
>「５」で割り切れる数値を引数に渡すと、’Buzz'と返す。
>「３」、「５」の両方で割り切れる数値を引数に渡すと、'FizzBuzz'を返す。

## Python version
```
x = int(input("好きな数字を入力してください："))

print(x)
if x % 15 == 0:
    print("FizzBuzz")
elif x % 3 == 0:
    print("Fizz")
elif x % 5 == 0:
    print("Buzz")
else:
    print('？？？？')
```

## Ruby version
```
def fizz_buzz(number)
  if number % 15 == 0
    'FizzBuzz'
  elsif number % 3 == 0
    'Fizz'
  elsif number % 5 == 0
    'Buzz'
  else
    number.to_s
  end
end
 
puts "1 以上の数字を入力してください"
 
input = gets.to_i
 
puts '結果は、、、'
 
puts fizz_buzz(input)

```

## JavaScript 
```
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>hello</title>
    </head>
    <body>
       <script>
        let aiueo = 2;
        if (aiueo % 15 === 0){
            document.write('FizzBuzz');
        }else if (aiueo % 5 === 0){
            document.write('Fizz');
        }else if (aiueo % 3 === 0){
            document.write('Buzz');
        }else {
            document.write('???');
        }
        </script>
    </body>
</html>

```
※Javascriptは只今絶賛勉強中なので許してください。

## 終わりに
今日はトラブルシューティングの大会がありました。
すごく難しかったです。
とりあえず今日は、まぶたの裏を見ながら、反省しようと思います。
~~寝るということでは決してございません。~~
Gitで別ブランチにpushすべき内容を一つのブランチにまとめてcommitしてしまったらどうする？

#はじめに
機能毎の仕様書を読みつつ、「変更点」を忠実にコーディングしてcommitした後、push前に再度仕様書を確認したときのことです。
「...ん？Aパラメータの追加とB検索条件の追加って、別リリースじゃね？汗」
ということで、別ブランチにpushすべき内容を一つのブランチにまとめてcommitしてしまったときの対処を記録しておこうと思います。
対処としてやったこと一つ一つは大したことありませんが、実際やったときは結構焦りましたね...。

#前提となる状況
- とあるプロジェクトの中のとある機能の仕様変更
- A変更とB変更は同一機能かつ同一ファイルに対する変更
- A変更は実際に作業したブランチ(以下、branch_a)にcommitするべき(ここであってた)
- B変更は別のブランチ(以下、branch_b)にcommitするべき(ここじゃダメ)

この状況で、A変更・B変更共にbranch_aにて作業し、いっぺんにcommitしてしまいました(pushはまだしていない)

#対処の流れ
[とりあえず当該commitを作業ツリーに戻す](#とりあえず当該commitを作業ツリーに戻す)
↓
[add -p でこのブランチに対応する変更のみステージングしてcommit](#add--p-でこのブランチに対応する変更のみステージングしてcommit)
↓
[残りをstashで退避して別ブランチに移動](#残りをstashで退避して別ブランチに移動)
↓
[退避していた分を作業ツリーに戻しcommit](#退避していた分を作業ツリーに戻しcommit)

###とりあえず当該commitを作業ツリーに戻す
```
$ git reset HEAD~1
```
[HEAD](https://qiita.com/ymzk-jp/items/00ff664da60c37458aaa)から1つめのcommit、つまり直近のcommitについて、commitとaddを[reset](https://qiita.com/shuntaro_tamura/items/db1aef9cf9d78db50ffe)するコマンドです。
これによってadd前、すなわち全変更が作業ツリー上にあり、ステージングされていない状態に戻ります。

###add -p でこのブランチに対応する変更のみステージングしてcommit
```
$ git add -p
```
[git add -p](https://qiita.com/cotton_desu/items/bf08ac57d59b37dd5188)は、ステージングするときにファイルの一部分だけ選んだりできる便利なコマンドです。
このコマンドを叩くと下記のように、各変更をステージングするか聞かれるので、[こちらの記事](https://qiita.com/cotton_desu/items/bf08ac57d59b37dd5188)などを参考に編集してステージングしていきます。

```
diff --git a/sample.txt b/sample.txt
index 51827b4..68e24a3 100644
--- a/sample.txt
+++ b/sample.txt
@@ -1,6 +1,8 @@
 サンプル
 サンプル
+A変更
 サンプル
+B変更
 サンプル
 サンプル
 サンプル
Stage this hunk [y,n,q,a,d,s,e,?]? 
```
バラバラにステージングしたいので「s」(split)と入力します。
すると以下のように表示されます。(eだと手動でeditできるみたいですね)

```
Split into 2 hunks.
@@ -1,3 +1,4 @@
 サンプル
 サンプル
+A変更
 サンプル
Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?
```
A変更はbranch_a(当該ブランチ)にコミットするので「y」を入力してステージングします。
同様にB変更についても聞かれますが、branch_aではステージングしないため、「n」を入力して作業ツリーに残したままにします。
statusはこんな感じ。

```
$ git status
On branch branch_a
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   sample.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   sample.txt
```
希望通りにステージングされたので、commitします。

```
$ git commit -m "A変更を実装" 
```

###残りをstashで退避して別ブランチに移動

```
$ git stash save
$ git checkout branch_b
```
[stash](https://qiita.com/chihiro/items/f373873d5c2dfbd03250)で一時的に作業(ここではB変更)を退避したあと、本来B変更をcommitするはずだったbranch_bに移動します。

###退避していた分を作業ツリーに戻しcommit
```
$ git stash pop
$ git add .
$ git commit -m "B変更を実装"
```
めでたしめでたし！

#おわりに
今回はpush前だったのでセーフ(?)ですが、pushしてしまった場合も~~バレないうちに~~周りの人に許可を取ってrebaseすればいいかと思います。

commitが大きい点に関しては、チケット毎にcommitするというプロジェクト規約に則っていたので一チケットだと勘違いしてcommitするに至りました。push時に規約に合わせるのはともかくとして、localでは細かくcommitして、push前にまとめればよかったのかもしれません。

あと、一番の解決策は最初からちゃんと仕様書を確認して作業を始めることです。反省します。