OmniAICreator/Qiita-1.07M huggingface dataset:
RailsのCSRF対策について

# **CSRFとは**
- Cross Site Request Forgeriesの頭文字をとってCSRF（シーサーフと読むらしい）
- Webアプリケーションにおける脆弱性の１種
- ざっくりいうと「サイトのログイン状態が保持されている状態で悪意のあるリンクを踏むと、意図しないリクエストを送ってしまう」というもの
- 以下具体例
    - 利用者Aがサイトにログインする
        - ログインに成功した時点でRailsアプリはAが使ってるブラウザにセッションクッキーを保存する
        - このセッションクッキーはそれ以降すべてのHTTPリクエストと一緒に送信される
        - Railsはこのセッションクッキーの値を調べることで、ログイン済みかどうかを判断する
  - 攻撃者Xが他のサイトに悪意のあるリンクを仕込む
      - ユーザー認証はブラウザに保存されているセッションクッキーで突破することを前提
  - 利用者Aが攻撃者Xが仕込んだリンクを踏む
      - セッションが切れていなければ、アプリ側はログイン済みだと判断する（他のサイトからのリクエストでもセッションクッキーは送信される）
      - もしアプリ側でCSRF対策がされていなければそのリクエストは有効なリクエストとして扱われるため、利用者Aが意図しない挙動をしてしまう
          - するつもりのない投稿, データの削除, 課金処理 etc,,,


# **RailsにおけるCSRF対策(`protect_from_forgery`メソッド)**
### どうやって対策してるか
- RailsではCSRF対策として「セキュリティトークンを仕込む」という方法を採用している
    - Railsアプリ内からの(GET以外の)リクエストにはセキュリティトークンを仕込み、それを確認することでアプリ内からの有効なリクエストかどうかを判断する
- それをよしなにやってくれているのが`protect_from_forgery`メソッドと、Railsが提供するformのヘルパー
- Railsが提供する`form_with`や`form_for`などのヘルパーを使うと、自動でセキュリティトークン(`authenticity_token`)を仕込んでくれる
- `protect_from_forgery`メソッドを記述すると、Rails側で正しい`authenticity_token`がセットされるかどうかをチェックしてくれるので、CSRFを防ぐことができる

### 具体的な設定方法
- `protect_from_forgery`をcontrollerに指定し、formにはヘルパーを使うだけ
    - Rails5.2以降では`ActionController::Base`内で有効になっているため、デフォルトの設定でよければ自分で記述する必要はない
    - それ以前のバージョンだとrails newした時点でApplicationControllerに記述されている

### `protect_from_forgery`のオプション
- prependオプション
    - デフォルトではfalseになっている
    - `prepend: true`を指定すると記述した場所に関わらずに常に処理の最初に実行される

- withオプション
    - セキュリティトークンが一致しなかった場合の挙動を指定するオプション
    - デフォルトは`:null_session`（セッションを空にする）
    - `:execption`（例外を起こす）を指定している状態でトークンが一致しないと`ActionController::InvalidAuthenticityToken`エラーが起こる

- オプションについて詳しくは[このサイト](https://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html)を参照

# **テスト環境で`protect_from_forgery`を有効にするには**
- Railsのテスト環境のデフォルトでは`protect_from_forgery`が機能しない
(ref: https://github.com/rails/rails/blob/5-2-stable/actionpack/lib/action_controller/metal/request_forgery_protection.rb#L75 )

- `protect_from_forgery`に関するテストを書く場合は、以下のように明示的に`allow_forgery_protection`を有効にする必要がある


```rb:RSpecでの例
before do
  # 明示的にallow_forgery_protectionを有効にする
  ActionController::Base.allow_forgery_protection = true
end

after do
  # 他のテストケースに影響を与えないために無効にしておく
  ActionController::Base.allow_forgery_protection = false
end
```

# 参考サイト
- [「Ruby on RailsのCSRF対策」](https://www.transnet.ne.jp/2016/10/26/%E3%80%8Cruby-on-rails%E3%81%AEcsrf%E5%AF%BE%E7%AD%96colnd/)
- https://railsguides.jp/security.html
- https://api.rubyonrails.org/
メモ：SSHポート番号の変更

##経緯
-ラズパイのセキュリティ対策でSSHのポート番号を変更しようと考えた。
-ちょー基本でどハマりしたので、メモ。。。

##最初

- SSHの設定ファイルをいじるために
   sudo nano /etc/ssh/sshd_config
- 先頭のPortを２２から任意の番号に変更
- Teratermからログインしようとしても、サーバーに拒絶されましたとなる。

##調査
-ファイアウォール見直したり
−ルーターの設定なども見たけれど、変化なし
−諦めて、SSH自体を無効に、VNCで接続することに

##オチ
-macからなら行けるかもと、再度SSHを有効にして、ログイン
 ssh user@ipアドレス
　→ログインできる

 ssh -p ポート番号　user@ipアドレス
　→ログインできない

 ssh -p 22 user@ipアドレス
　→ログインできた

ーー＞ポート番号の＃コメントアウトを外すのを忘れていただけでした。。。
【PHP基本】XSS(クロスサイトスクリプティング)対策

#XSS(クロスサイトスクリプティング)対策

`htmlspecialchars()`を使えば解決できます。

```php:index.php
<?php
$message = "";
$error = false;
$errorMessage = "未入力です！";

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $message = $_POST['message'];

  //バリデーション
  if ($message == '') {
    $error = true;
  }
}

?>

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <title>フォームの練習</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <h1>XSS対策</h1>
  <form action="" method="POST">
    <p>
      <label for="">メッセージ</label><br>
      <?php if ($error) {
        echo "<span id='not_entered'>";
        echo $errorMessage . "<br>";
        echo "</span>";
      } ?>
      <input type="text" name="message">

    </p>
    <p>
      <input type="submit" value="送信">
    </p>
  </form>
  <p><?php echo htmlspecialchars($message, ENT_QUOTES, 'UTF-8'); ?></p>

</body>

</html>
```
AWS EC2 Railsアプリデプロイへの道

何度やっても抜けが出て何かしらのエラーが出てしまうので、
備忘録のために何をするべきなのかとにかく項目を列挙。わからなかったら項目で調べようの精神です。
足りないものは追記していきます。ご指摘あれば是非下さい！
対象：個人的ポートフォリオレベルのアプリケーション

# 大まかな流れ
1. インスタンス作成
2. 環境構築（インスタンスの中身を設定）
3. アプリケーションサーバ設定・アプリケーションサーバのみで起動確認
4. webサーバ設定
5. 自動デプロイ(必要であれば)

# インスタンス作成
- [ ] ログイン
- [ ] リージョン選択（２敗）
- [ ] インスタンス作成
- [ ] Elastic IP取得、関連付け
- [ ] ポート解放（１敗 http用）

# 環境構築
- [ ] ssh接続
- [ ] user作成
    - [ ] user権限設定
    - [ ] Node.js導入 
    - [ ] バージョン確認 
- [x] gitの導入（入っていなければ）
- [ ] rbenv導入
    - [ ] パス設定
    - [ ] ruby-build導入
    - [ ] rehash(１敗)
    - [ ] ruby導入
    - [ ] バージョン確認
- [x]  またはRVM導入
    - [x] バージョン確認 
    - [x] ruby導入
    - [x] バージョン確認
- [ ] database導入
    - [ ] パスワード設定と
    - [ ] 接続確認

# アプリケーションサーバの設定
- [ ] Githubにssh接続
    - [ ] sshキー作成
    - [ ] githubで公開キーを登録
    - [ ] 接続確認
- [ ] unicorn 又は pumaの設定
- [ ] database.ymlの設定（１敗）
- [ ] アプリケーション導入先ディレクトリの作成（１敗）
- [ ] git clone
- [x] （今後の変更はgit pull）
- [ ] スワップ領域の作成（設定がなければ、２敗）
- [ ] bundler を gem install(要：バージョン確認)
- [ ] 環境変数設定（credential導入していればマスターキー作成）
- [ ] ポート解放(rails用 1敗)
- [ ] db作成、migration実施
- [ ] assets precompile 実施
- [ ] 起動確認（テスト用）
    - [ ] 初期起動のみ頭にRAILS_SERVE_STATIC_FILES=1を付ける

# webサーバの設定
- [ ] Nginx/apacheなど導入
- [ ] サーバ設定
- [ ] 外部アクセス用に権限変更
- [ ] 再起動（１敗）
- [ ] unicorn/pumaのNginx設定
- [ ] unicorn/pumaの再起動（読み込みのため）

# 自動デプロイ化
- [ ] capstranoなどツール導入
- 又はシェルスクリプトなどで自己流自動化


---
これらは全てキーワードの箇条書きです。１つ１つにやることが複数あったりします。
手間ですよね。。。この前段階の開発の際の環境構築だって手間です。
IT業界なので当然、作業は自動化してしまうものです。
私と同じ初学者の方はCI/CDやDockerについて調べましょう。
メールの件名に[SPAM]がついてしまう原因は！？CBLブラックリスト解除の話

# 起こった出来事
IPアドレスがCBLのブラックリストに追加されてしまい、
**送信したメールのタイトルに[SPAM]がついてしまう**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232449/c5d4518b-2ea4-ffca-031b-47dda95ebf75.png)
↑メールボックスがこんな感じ

# なぜこの記事を書こうと思ったのか？
**本当に参考記事が少ない**。
私はすごく困りました。
絶対に誰かが喜ぶと思って書きます。

# 迷惑メール判定される原因は？
そのままですが、メールが**スパムメール判定**されているため。
迷惑メールの原因はメールによって異なりますが、

- なりすまし送信している
- 文章が業者っぽい（※１）
- 本文にURL張っている（※１）
- 一斉送信しすぎ（※２）

など様々…
[※１]基準はよくわからない
[※２]ただ「送れない」という現象だったら利用中のサーバーの上限に達している場合もある。要確認。

# CBLとは？
イギリスにある、スパム送信しているメールサーバーを洗い出している団体？機関？
ちょっとその辺定かでないですが、割と公式めな感じ見たいです。

SMTPサーバが安全かどうかを確認しているようです。
WEBサイトを回るわけではないですが、クローリングのイメージです（※私の解釈）。
なので、下記サイトから「該当のIPが〇時間以内に〇回検知された」という情報が公開されています。

ブラックリスト入りしていた際は24時間以内に十数回検知されていました。
おそらく1時間に1回くらいのペースです。
レコードの設定変更ではうまくいきませんでした。

[CBL公式サイト](https://www.abuseat.org/)
※一応言語を日本語にも変換できます(笑)
ここで、IPを入力すると、該当のIPがブラックリスト判定されているか確認できます。

# ブラックリストの解除依頼をする
数回検知されたくらいだと、
検索画面上で解除ボタンが表示されます。
[CBLの検索画面](https://www.abuseat.org/lookup.cgi)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232449/44ef4243-3733-3206-9c3a-4edd2d312932.png)

ただ、繰り返し検知されている場合は自分で解除することができません…。
でもどうしても解除したい。
そんな場合は下記に記載のメールアドレス(cbl@abuseat.org)宛てにメールを送ると対応してくれます。
時差もあるので2日くらいで返信が来ます！
参考：[CBL FAQ](https://www.abuseat.org/faq.html)

ただ、送る先はイギリスなので、**英語**で送りましょう。
つたない英語でも返してくれます。Andy優しい。

# ブラックリストから解除された（1回目）
メールをCBLの本部に送ってついにIPで検索をしてもブラックリストに入らなくなりました。
そんな喜びもつかの間。

ブラックリスト解除をしましたというメールの2時間後には再度リスト入りしてしました。
やはり、根本の解決をせずにブラックリスト解除をするのは早すぎる。
これではイタチゴッコ…。

返信メールにはリスト入りした原因や今後の対策等を丁寧に（英語で）書いてくれていた。
要約すると

- **同一サーバーで複数ドメインのメールを送信している**
- **マルチドメインサービスの利用を推奨**

# 原因の解明
原因は**postfix**の設定でした。

postfixを利用して送信サーバーの構築をしていたのですが、その設定にミスがありました。
**myhostname**を送信するメールの独自ドメインにする必要がありました。

おそらく、これが原因でなりすまし送信としてみなされていた。
さらに、エラー通知として利用していたので、1日何通ものメールが送られていたのも原因かもしれません。

myhostnameに独自ドメインを設定して1日経過。
CBL検索で直近24時間のリスト入りが0回になりました。

晴れて安全なメール送信ができるように！！

# ブラックリストから解除された（2回目）
安全な送信サーバーからメールが送信されるようになったので、
念願の「解除ボタン」がCBL検索画面に現れました。

これで、2度目のブラックリスト解除です！
1度目の即リスト入りの恐怖から数日間確認しましたが、1度もリスト入りはせず！
解決です！！！！！

# おまけ
同じメールを送信しても迷惑メール判定は受信もしくは送信側の設定によります。
多くの記事では**受信側**の問題だと書いてあることがほとんど。

ですが、送信する際のヘッダーに迷惑メール判定の基準を決める項目があったりすることも…。

- X-Spam-Flag:
- X-Spam-Level:
- X-Spam-Status:

など。
これも利用中の送信サーバーの設定だと思いますが、こういう項目って大体コンパネから変更できないことが多いので、
何かおかしいな？と思ったらサーバーのFAQを見てみるとヒントがあるかもしれないです！

# まとめ
迷惑メールの解決手段は

- まずレコードの設定状況の確認
- 受信側の問題ではないか？

などを確認しがち（私のググり方が悪いのかもしれない）
postfixを使っている場合は送信系のトラブルの原因になっている可能性がある
メールは深すぎる。

何か思いつくことがあったら（自分の備忘録として）追記していきます！
Kubernetesのコマンド(kubectl,kubeadm,kubelet)の違いがよくわからないので調べてみた

# はじめに
業務で`kubernetes`を少し前から触るようになりましたが、普段は pod や container の様子をみたり log みたりで、ほぼ`kubectl`しか触っていないことに気づきました。他にも`kubelet`、`kubeadm`とかあるようですが、よくわかってないので調べて意味をまとめてみました。ざっくり理解したい方向けです。

# 構成
- kubectlとは？
- kubeletとは？
- kubeadmとは？  
の３本でお送りいたします。

# kubectlとは？
公式リファレンスの一部を引用しますと、以下とのことです。
`Kubectl is a command line interface for running commands against Kubernetes clusters.`
Kubernetes Cluster(master、wokerなどサーバ複数台で Kubernetes が組まれている状態)に対してコマンドを実行するためのインターフェイス。
構築してある kuberenetes に対し、コマンドで操作するための模様です。node や pod などの確認やyamlファイルから設定の適用、ログの確認などができます。

# kubeletとは？
公式リファレンスの一部を引用しますと、以下とのことです。
`The kubelet is the primary “node agent” that runs on each node. It can register the node with the apiserver using one of: the hostname; a flag to override the hostname; or specific logic for a cloud provider.
`
google先生に翻訳していただくと、「kubeletは、各ノードで実行されるプライマリ「ノードエージェント」です。次のいずれかを使用して、apiserverにノードを登録できます。ホスト名を上書きするフラグ。またはクラウドプロバイダーの特定のロジック。」といった内容だそうです。
・・・ごめんなさい、よくわかりません。

他にもCoreOSブログの記事にkubeletの説明があったので、引用してみた。
`The kubelet is responsible for maintaining a set of pods, which are composed of one or more containers, on a local system. Within a Kubernetes cluster, the kubelet functions as a local agent that watches for pod specs via the Kubernetes API server. The kubelet is also responsible for registering a node with a Kubernetes cluster, sending events and pod status, and reporting resource utilization.`

google先生に翻訳していただくと、以下の内容です。
「kubeletは、ローカルシステム上で、1つ以上の容器で構成されているポッドのセットを維持する責任があります。Kubernetesクラスター内では、kubeletはKubernetes APIサーバーを介してポッド仕様を監視するローカルエージェントとして機能します。kubeletは、ノードをKubernetesクラスターに登録し、イベントとポッドステータスを送信し、リソース使用率をレポートする役割も担います。」

Kubernetes のノードや、Kubernetes APIサーバーを介して pod の監視を行う。podのステータスやリソース使用率をレポートもする、といったところでしょうか。

# kubeadmとは？
公式リファレンスの一部を訳すと、「最小限の実行可能なクラスターを稼働させるために必要なアクションを実行」とあった。
また kubeadm コマンドの help をみてみると、頭の方にざっくりした概要が書いてあった。
「`Easily bootstrap a secure Kubernetes cluster`」
bootstrapの意味が調べてもピンとこなかったので、自分なりの言葉で表現してみると、
「Kubernetes Clusterをセキュアで簡単にするために使うもの」
kubernetes Clusterの構築に使いそうな感じですね。

# まとめ
- kubectl
    - 構築してある kubernetes の操作を行うためのCLI。
- kubelet
    - Kubernetes APIサーバーを介して pod の監視を行う。podのステータスやリソース使用率をレポートもする。
- kubeadm
    - kubernetesクラスタを作るときに主に使用する。

# 最後に
構築済みのkubernetesを使用していたから、kubectlばかりを使っていたことがわかりました。
私の理解度の問題かもですが、ドキュメントやヘルプで説明された内容ではピンとこないことがよくあります。そんな方向けにまずはざっくりとした概要を掴んでいただけたら幸いです。
内容がまちがってたら教えてください。とても助かります。
それではここまで読んでくださり、ありがとうございました！

# 参考にさせていただきました。
- [Kubernetes Reference](https://kubernetes.io/docs/reference)
    - 「公式リファレンス」と本文中で表記していたのはこちらです。
- [Kubernetes: 構成コンポーネント一覧](https://qiita.com/tkusumi/items/c2a92cd52bfdb9edd613)
- [CoreOS Blog](https://coreos.com/blog/introducing-the-kubelet-in-coreos.html)
- [kubeletのログの確認](https://software.fujitsu.com/jp/manual/manualfiles/m190004/j2ul2420/01z200/operation-guide/dita/k8s-kubelet-log.html)
- [Kubernetesと使用するOracle® Container Servicesユーザーズ・ガイド](https://docs.oracle.com/cd/E77565_01/E88884/html/kubectl-basics.html)
Google Apps Scriptの個人的な使い所

# GASでGmailの振り分け・通知サポート

## 初めて投稿します
Qiitaのアカウントを開設してみました。
正直、人様の役に立つようなナレッジは持ち合わせてないのだけど、どっかにアウトプットしないときっとすぐに忘れるので、恥を忍んで書いてみることにしました。
初回は前から運用しているGAS(Google Apps Script)について公開してみようと思います。
GASって略すの未だに慣れないんですよね。

GASはGoogle Apps版のVBAみたいなものと最初は理解していたのですが、簡易的なウェブサービスというかAPIなんかも作れそうだと思い、興味が湧きました。最初はTwitter APIを使って、ツイートとメンションを記録するボット(これはIFTTTでできるね)とか、対話ボット(docomoの対話APIを使用)や訂正ボットなんかを実験的に動かしてました。今は専ら、Gmailや連絡先やGoogleカレンダーの痒いところに手を届かすスクリプトを運用しています。

## 迷惑メールフォルダーに移動する
本当はGmailのフィルターで実現したいところなのですが、何故か迷惑メールフォルダーに移動ができないんですよね…
たぶん、迷惑メールフォルダーに入れることで迷惑メールと学習してるんでしょうから、機械的にごみ箱代わりに流し込まないで！という意図なんでしょうけど。
ただ、迷惑だと感じてるメールはごみ箱ではなくて、迷惑メールフォルダーに流し込みたい。機械的に。なので、今回は

1. Gmailのフィルターで[スパム]というタグを付けておき、
2. GASで[スパム]タグの付いたメールを刈り取って、迷惑メールフォルダーに流し込む

の2段階で処理することにしました。もちろん「フィルターでタグ付け」という一手間を踏まず、フィルターの条件をクエリに書けば1発でも行けますが、フィルタはメール受信時に動きますから、いらん通知を受けたり、タイミングによっては受信トレイで迷惑メールが目に入るといったことを避けることができるんですよね。

コードはこれだけ。実行頻度は困り具合に応じてお好みで。

```.js
function moveToSpam() {
  GmailApp.search("label:スパム").forEach(function (thread) {
    thread.moveToSpam();
  });
}
```

## 自動アーカイブする
受信トレイはキレイに保ちたいし概ね保てていると思っているのですが、ちょっとでも自動化できたらいいなと思って作りました。
ロジックは見ての通りで、下記の条件に合うメールを検索(Gmailの検索式)して、それをアーカイブしてるだけです。

- 受信トレイにあって
- 受信して30日を超過
- 既読
- ラベルが付いてる
- ☆がついてない
- 重要でない

受信トレイに置いておきたいメールはいつも☆を付けとくので、これくらいの条件がぴったりでした。

```.js
function moveToArchive() {
  GmailApp.search("in:inbox is:read has:userlabels -is:starred -is:important older_than:30d").forEach(function (thread) {
    thread.moveToArchive();
  });
}
```

余談ですが、以前は`function(thread)`とスペースを入れずに書いていたのですが、最近は`function (thread)`とスペースを入れて書くようにしています。`function`という関数ではなくて、無名関数なんですね。js-beautifyを使ってて、恥ずかしながら最近気づきました。

## 既読後、放置しているメールを再プッシュ
相変わらず、○○の一つ覚えみたいなロジックで恐縮なのですが。もしかしたら、アイディアというか皆様の使い所のヒントになるかもしれませんから、一応公開してみます。

メールを着信したときにメールは開くのですが、中身をろくに読まずに放置することが多いので、

- 受信トレイにあって
- 受信して3～4日
- 既読

のメールを再プッシュしています。
メーラーを[Spark](https://sparkmailapp.com/ja)にしてからは放置が減ったので、最近は発動してないです。

```.js
function notifyUnreadMail() {
  GmailApp.search("in:inbox is:unread newer_than:4d older_than:3d").forEach(function (thread) {
    thread.getMessages().forEach(function (message) {
      notifySlack(…);
    });
  });
}
```

# 中身を読まないメールはプッシュだけして削除する
ログインアラートとかの通知は受けたいけど、中身は読まないメールは自分宛にSlackして、メールは削除してます。
条件はお好みで。通知は自前の関数を呼んでいますが、LINEでもTwitterでもIFTTTでもお好みでどうぞ。

```.js
function notifyMail() {
  GmailApp.search("is:unread subject:(ログインのお知らせ|…)").forEach(function (thread) {
    const subject = thread.getFirstMessageSubject();
    thread.getMessages().forEach(function (message) {
      notifySlack(…);
    });
    thread.moveToTrash();
  });
}
```
## 最後に

今回はGmail周りの簡単なスクリプトを載せて見ましたが、実は他にもカレンダー登録のサポートとか、連絡先のメンテナンスとかのスクリプトがあって、こちらのほうが重宝しているかも。こちらはまた改めて。
(Qiita始めたばかりなので、次があるかわかりませんが)
MR開発での「HelloWorld」的な何か

# 書くに至った経緯
1. 折角会社資産にHoloLensがあるんだし皆に使ってほしい。
2. でも公式チュートリアルも初心者には結構しんどいぞ...
3. よし、HelloWorld的なのを作ろう。（唐突）

という事で、
<strong>タップするとでボールが落ちる</strong>だけのお手軽チュートリアルを記載します。
# 用意するもの
- Windows 10が動くPC
- [Unity](https://unity3d.com/get-unity/download/archive)  
バージョン管理がしやすいのでUnityHubからインストールしてください。
- [Visual Studio 2019](https://visualstudio.microsoft.com/ja/downloads/)
- [Windows 10 SDK](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk)
- [MRTK v2.1](https://github.com/Microsoft/MixedRealityToolkit-Unity/releases)(執筆段階で最新)<br>
Microsoft.MixedReality.Toolkit.Unity.Foundation.2.1.0.unitypackageというファイルをDLしてください。<br>

# Unityプロジェクト作成
1. UnityHubのプロジェクト項目から新規作成をクリック。
2. テンプレートから【3D】を選び、適当なプロジェクト名を付けて作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551913/f326f13b-8c30-c833-4bf9-df8af7ec36df.png)  
3. プロジェクトが作成されると編集画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551913/ea8f5e21-7b5e-e7c2-5eec-5d01a8b30518.png)
  
# 環境準備
1. File→Build Settingis...を選択。
2. PlatformからUniversal Windows Platformを選択し、Switch Platformをクリック。
3. Assets→Import Package→Cusutom Packageを選択。
4. ダウンロードしたMicrosoft.MixedReality.Toolkit.Unity.Foundation.2.1.0.unitypackageを開く。
5. Import Unity Package画面のチェックボックスをすべて選択し、Importを押す。  
↓の状態になったらOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551913/17ab51d9-3911-ffb1-eb4f-0f15bc5d0e90.png)
6. File→Save as...をクリックし、現状を適当な名前を付けて保存する。


# アプリ作成
<ol><li>Hierarchyという窓を右クリックし、3D Object→Sphereを選択。
<li>Inspector窓のTransformでボールの位置を変更（Zを1に変更）
<li>（ちょっと大きいので）Inspector窓のTransformでボールの大きさを変更（X,Y,Zを全て0.3に）
<li>Add ComponentからRigidbodyを追加。
<li>Add ComponentからRigidbodyを追加。
<li>Add ComponentからNew Script→Ochiruyatuを入力し新規スクリプトを作成。
<li>追加されたAssetsフォルダ内のスクリプトをダブルクリックし、下記のコードを記入する。


 ```C#:Ochiruyatu.xs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ochiruyatu : MonoBehaviour
    
{
    private Rigidbody rb;
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    public void TapAction()
    {
        if(rb != null)
    {
        rb.useGravity = true;
    }
    }
}
```

<li>RigidbodyのUse Gravityのチェックを外す。
<li>Input Action Handler(Script)のOn Input...の+をクリックし下記の様に設定する。
![コメント 2019-12-17 223711.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551913/7834ea0a-a6ab-a004-4f8a-5e3de830e298.png)
<li>HierarchyのMixedRealityToolkitを選択。
<li>Inspector窓のMixedRealityToolkit（Script）項目からCopy&Customizeをクリック。
<li>Clone ProfileウィンドウのCloneをクリック。
<li>赤印の部分も同様にCloneする。
![コメント 2019-12-17 214332.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551913/705b8fe5-fc58-5a1b-6307-8bc3c6e109e1.png)
<li>Add Spatial Observerを選択し、追加されたSpatial Object Mesh Observerを下記の様に変更する。
![コメント 2019-12-17 214523.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551913/d03bb0cf-29dd-ed69-fcc5-fb8f774d7853.png)

# 完成！！！！！！！！
Unityのスタート（再生ボタン）を押して、Games窓で操作してみましょう。
### 操作方法
- WASDキーでカメラの移動
- Space+左クリックで選択
![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551913/d8de52dc-650c-b8bb-046d-c7ba5d9381c2.gif)
DataFrameのカラム整理に便利なメソッドの覚書

# kaggleのkernelを読んで、便利だと思ったメソッド達
最近kaggleに取り組み始め、今まで頑張って手作業で作っていたcolumnsの処理を簡単にするメソッドがあったので、忘備録としてまとめます。
今行っているコンペで使用した使いかたのみ簡単にまとめているので、詳しい使い方は参考にした記事に飛んで調べてみてください。

## 欲しい値を表示したい時に
今回私が行っているコンペでは、与えられたデータがtrain_dataとtrain_labelと存在しており、２つのcsvの中で重複する項目が存在していました。
最終的にはこの２つのデータを合体させて、モデルに与えなければならないため、重複した内容を間引いてから合体させないといけません。

 - unique()  
    対象にしたcolumnsに含まれる、固有の値を抜き出します。
 - isin(```入っているか確認したい値```)  
確認したい値がDataFrameの中に含まれているかを確認します。返り値はbool型で、デフォルトではFalseが返ってきます。`~`を先頭につけるとTrueが返ってくるようになります。
 - where(`対象の条件`, `Trueの場合`, `Falseの場合`, `オプション`)  
対象の条件に適合したindexに対してそれぞれの処理をおこなう。`inplace=True`のオプションをつけると、元のDataFrameに反映される
第２引数と第３引数を省略すると、該当するindexが返ってくる

## カラム毎にグループ化するなどの、複数の対象をとって同じ処理をさせたい

 - groupby([`'グループ化したい１つ目のカラム名'`, `'グループ化したい2つ目のカラム名'`])`
  .適用したい処理`.mean()とかその辺  Aグループに属しているBグループの値段の平均を出す。みたいな使い方をする。指定したカラム名の重複がなくなる。

 - agg({`'処理の対象となるカラム名'`: [`'処理をしたいコト１（minやmaxなど）'`, `処理したいコト2`]}) 
 groupbyを行った後に使用すると便利

## 参考にした記事

[note.nkmk.me](https://note.nkmk.me/python-pandas-value-counts/)
[CUBE SUGAR CONTAINER ](https://blog.amedama.jp/entry/2018/04/16/230703)
Windows + Anaconda + Python3.6 + talib インストールしたときのメモ

*この記事は、*
*fintalk Advent Calendar 2019 - Adventar*
*https://adventar.org/calendars/4331*
*17日目の記事です*

---
2019年8月の作業メモです。
conda install ～　では簡単にインストールできなかったので……

## Python3.6の環境を立ち上げ

株価の勉強会のための環境だったので、名前は「kabka」
Python3.7ではバージョンが合わないとのことで、
Python3.6の環境を作成しました。

```
conda create -n kabka python=3.6
```

その環境をアクティブに

```
(base) PS C:\> conda activate kabka
(kabka) PS C:\>
```

ちなみに今どんな仮想環境が存在してるか知るコマンド

```
conda info -e
```

## ta-libを探して導入

目的のta-libはどこにあるのか探す

```
anaconda search -t conda ta-lib
```
![Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492622/82c01039-8aff-8e9a-abd6-635ab05c378c.png)

バージョンとプラットフォームを確認
このNameの部分をコピー。
anaconda show の後ろにペースト

```
anaconda show masdeseiscaracteres/TA-Lib
```
![Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492622/656f9133-6c2f-bdf6-b0a0-04162ca92f3e.png)

親切にもコマンドラインに記述するべきコマンドが、丸々出てくるので、
最後に出てきた行をコピーしてペーストします。

インストーーーーール！
ちゃんと入ったか　conda list で確認します。
Notionでデータベースを関連付ける

[アルプ株式会社](https://thealp.co.jp/)でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2019](https://qiita.com/advent-calendar/2019/notion) 17日目のエントリです。
16日目は[NotionでRDBのスキーマを設計する](https://qiita.com/pictiny/items/bd890aa23fad729ed800)でした。

# リレーションプロパティ
Notionのデータベースには**リレーション**というプロパティタイプがあります。
リレーションプロパティを追加すると連携するデータベースを選択できます。

<img width="566" alt="リレーションプロパティ1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/7cb8099f-fd10-ca1b-b3a3-cb7d3cdab1c6.png">

データの詳細ページを開きリレーションプロパティをクリックすると、連携先のデータベースからデータが列挙され、関連付けるデータを選択できます。複数選択することもできます。

<img width="1034" alt="リレーションプロパティ2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/ede0e3e8-5d40-f2ab-5e51-0afe7a3c60d2.png">

関連付けると、連携先のデータベースに作成されたリレーションプロパティからも参照されます。

<img width="327" alt="リレーションプロパティ3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/149095cf-fe40-6f18-6404-7ce1b81c3c45.png">

# まとめ
リレーションプロパティは開発タスクから仕様書を参照するときなどに便利です。

公式ドキュメントは[Relations & rollups](https://www.notion.so/Relations-rollups-fd56bfc6a3f0471a9f0cc3110ff19a79)にありますので、そちらもご覧ください。
Salesforce資格取得者数のPDFファイルをダウンロードするマクロ

#初めに
Salesforceに関係はしますが，VBAだけの内容になります．

[Salesforce 認定資格保持者数 企業別一覧](http://tandc.salesforce.com/certificate-holder)が公開されています。資格ごとで毎月のファイルを一つ一つ見ているだけではあまり意味のある情報が得られないかもしれませんが，まとめてみると何か見えてくるかもしれません．
今回は，指定した複数のファイルを指定したフォルダにダウンロードするExcel VBAです。

# 動作環境
Windows 10上のOffice365(64bit)のExcelで確認してます．古いOfficeでは動作しないかもしれません．

## おことわり
環境に依存することや、VBAの使い方など基本的な内容はご自身で解決してください。

# 機能 - PDFファイルのダウンロード
数式ー名前の管理でダウンロードフォルダと資格の一覧の場所が定義されていますので確認してください．
資格一覧シートのB1セルにダウンロード先のフォルダ名を書いておき、"ファイルのダウンロード"ボタンをクリックするとファイルがダウンロードされます。終了すると終了したとメッセージボックスで表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223941/de163782-4041-6d90-297a-612c83210019.png)


#マクロ
```標準モジュールのDownload
Option Explicit

Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _
   (ByVal pCaller As Long, _
    ByVal szURL As String, _
    ByVal szFileName As String, _
    ByVal dwReserved As Long, _
    ByVal lpfnCB As Long _
    ) As Long

Function DownloadPDFFile(url As String, path As String) As Boolean
    DownloadPDFFile = False
    Dim lRes As Long
    lRes = URLDownloadToFile(0, url, path, 0, 0)
    If lRes = 0 Then ' エラーなし
        DownloadPDFFile = True
    End If
End Function

Sub DownloadPDFFiles()
    Dim r As Range
    Dim strDLFolder As String

    strDLFolder = ThisWorkbook.Names("ダウンロードフォルダ").RefersToRange.Cells(1, 1).Value
    If strDLFolder = "" Then
        MsgBox "ダウンロード先フォルダ名が空なので終了します"
        Exit Sub
    End If
    If Dir(strDLFolder, vbDirectory) = "" Then
        MkDir strDLFolder
    End If
    
    Dim rangeExam As Range
    Set rangeExam = ThisWorkbook.Names("Salesforce認定資格").RefersToRange
    For Each r In rangeExam.Rows
        r.Cells(1, 6) = ""
    Next
    
    MsgBox strDLFolder & vbCrLf & "にファイルをダウンロードします", vbOKOnly
    
    For Each r In rangeExam.Rows
        Dim strFileName As String
        Dim strUrl As String
        '列番号は 1:略称 2:URL 3:ファイル名 4:分類 5:資格名 7:DL状況 8:取り込み
        strUrl = r.Cells(1, 2)
        strFileName = strDLFolder + "\" + Mid(strUrl, InStrRev(strUrl, "/") + 1)
        r.Cells(1, 6) = "*"
        If DownloadPDFFile(strUrl, strFileName) = False Then
            r.Cells(1, 6) = "失敗"
        Else
            r.Cells(1, 6) = "完"
        End If
        DoEvents
    Next
    MsgBox "取り込み完了しました", vbOKOnly
End Sub
```

#ファイル
Bitbucketにおいてあります
[SF資格取得者数.xlsm](https://bitbucket.org/okazakiyuji/salesforce-excel/src/master/SF%E8%B3%87%E6%A0%BC%E5%8F%96%E5%BE%97%E8%80%85%E6%95%B0.xlsm)をダウンロードしてください
機械学習と統計学の違い

こんにちは。
僕は今機械学習を勉強しているのですが、ふと疑問が起こりました。
それは**「機械学習」と「統計学」**の違いです。
調べるとたくさんの記事があったので、それを参考にしながら（下記にリンクは貼ります。）自分なりにまとめました。

最初に僕なりの結論を言うとそれは「根本的な目的の差」かなと思います。

例え話に言い換えると、二つとも違うボール遊びをしているようなもの。
「ボール」と言う使っているものは似ていて、点を取るという「大きな目的」は同じ。
しかし、詳しく見ると、違うルールがあり違う目的がある。
根底とゴールが同じだから混乱してしまうのです。

話を戻すと、どちらも根底の知識は「最適化」と「確率論」etc...が複雑に絡み合っているんです。
しかし最終的な目的はどちらも**「データから課題を解決する」**為の**「手段」**なのです。
手段ということは、それぞれ最適化された場所があるのです。
よって、二つが最適化される条件と環境を知っておくことは学ぶ上で大切になるでしょう。

#機械学習と統計学の目的の違い
##機外学習の根本的目的
機械学習の目的は**「正確性」**
つまり、計算方法やアルゴリズムはあまり関係なく数値を入れて、「精度の高い結果」を返すことに着目している手法。

これが最適なのは例えばメールの自動フィルタリングやレコメンド機能など今多く使われているものですよね。
迷惑メールが弾かれる理由よりも弾かれることが大切。
適切なレコメンドが来る理由よりも来ることが大切。
なんと素晴らしい手法なんでしょうか。美しい。（美しいは最近の口癖）


#統計学の根本的目的
統計学の目的は**「解釈」**
つまり、現状のデータの構造を可視化して、解釈を与えることが大切。

「解釈」というのはデータの構造を紐解いて、次に応用すること。これが統計学の強みです。
最適な環境としましては、例えばコンサルや提案です。
なぜなら機械学習と違い相関関係が明確になるため説明・説得がしやすいのです。

#まとめ
どちらも大きな目的は**「データを通して課題を解決する」**です。
しかし、機械学習は**「結果」**、統計学は**「解釈（プロセス）」**を根本的な目的としている為、混在されやすいのです。
※これはあくまで僕の考えです


ありがとうございました！

#参照文献
[結局、機械学習と統計学は何が違うのか？](https://qiita.com/KanNishida/items/8ab8553b17cb57e772d6)
[統計学と機械学習の違いとは？](https://www.bananarian.net/entry/2018/09/01/164125)
【UE4】C++でカメラの回転を設定する


# 最初に

この記事はC++側からサードパーソンにおけるカメラの回転方法を記事にしたものとなります。間違いや更に良い方法があった場合にはそっとTwitter( [@ろっさむ](https://twitter.com/4_mio_11) )やコメント、修正リクエストなどでお知らせ頂けるととても有難いです。 

# 作業環境

記事内で使用する作業環境は以下の通りとなります。

- Unreal Engine：4.23.1
- Visual Studio：Community 2017 or Community 2017 for Mac or Enterprise 2019



# 実装方法

[【UE4】コントローラー入力に対するセットアップをC++で行う](https://qiita.com/4_mio_11/items/e9029c768fa70ec8dab8)　にて記載した、C++側からInputのキーをMappingして登録する手法とよく似ています。

まずはプレイヤーキャラクターのクラスのヘッダーファイルにて`Yaw`と`Pitch`それぞれのマウス感度を表す定数と`Yaw(float amount)`と`Pitch(float amount)`を定義します。



```c++
// CPP_PlayerCharacter.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Characters/Base/CPP_CharacterBase.h"
#include "CPP_PlayerCharacter.generated.h"

/**
 * 
 */
UCLASS()
class ACPP_PlayerCharacter : public ACPP_CharacterBase
{
	GENERATED_BODY()

private:

	static constexpr float YawAmount = 1.0f;
	static constexpr float PitchAmount = -1.0f;
	static constexpr float MouseSensitivity = 100.0f;
    
	// Inputに処理を割り当てるためのセットアップメソッド
	virtual void  SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;

	void Yaw(const float amount);
	void Pitch(const float amount);    
};

```



次にcppファイル側を変更します。



```c++
// CPP_PlayerCharacter.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "CPP_PlayerCharacter.h"

#include "Components/InputComponent.h"
#include "GameFramework/PlayerInput.h"
#include "GameFramework/PlayerController.h"
#include "Engine/World.h"
#include "GameFramework/CharacterMovementComponent.h"

void ACPP_PlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	check(PlayerInputComponent);

    // MouseのX座標更新でのイベント登録するための情報群
	FInputAxisKeyMapping Yaw("Yaw", EKeys::MouseX, YawAmount);

    // MouseのY座標更新でのイベント登録するための情報群
    FInputAxisKeyMapping Pitch("Pitch", EKeys::MouseY, PitchAmount);

    // 実際に登録を行う
	GetWorld()->GetFirstPlayerController()->PlayerInput->AddAxisMapping(Yaw);
	GetWorld()->GetFirstPlayerController()->PlayerInput->AddAxisMapping(Pitch);

    // Yaw()とPitch()をバインドして実際に反応するようにする
	PlayerInputComponent->BindAxis("Yaw",  this, &ACPP_PlayerCharacter::Yaw);
	PlayerInputComponent->BindAxis("Pitch", this, &ACPP_PlayerCharacter::Pitch);

}

void ACPP_PlayerCharacter::Yaw(const float amount)
{
	auto YawValue = MouseSensitivity * amount * GetWorld()->GetDeltaSeconds();
	AddControllerYawInput(YawValue);
}

void ACPP_PlayerCharacter::Pitch(const float amount)
{
	auto PitchValue = MouseSensitivity * amount * GetWorld()->GetDeltaSeconds();
	AddControllerPitchInput(PitchValue);
}

```
ASP.NET 各リクエストでメンテナンス状態かチェックする

「【ASP.NET】メンテナンスページを表示する方法5選」
http://devdevdev.hatenablog.com/entry/2016/04/30/044325

こちらを参考に、１と２を合わせたIHttpModule + ファイルの有無で実現しようと思います。

メンテナンスチェック用モジュールを作成

```C#
using System;
using System.Web;
using System.IO;


namespace MyApp.HttpModules
{
    public class MaintenanceCheckModule : IHttpModule
    {
        public void Init(HttpApplication application)
        {
            application.BeginRequest += new EventHandler(this.CheckMaintenance);
        }

        public void Dispose()
        {
        }

        public void CheckMaintenance(object sender, EventArgs e)
        {
            var app = (HttpApplication)sender;
            string path = app.Context.Server.MapPath("/maintenance.txt");

            if (File.Exists(path))
            {
                string body = File.ReadAllText(path);
                if (body.Length <= 0)
                {
                    return;
                }
                app.Context.Response.Write(body);
                app.Context.Response.Headers.Add("ServerStatus", "Maintenance");
                app.Context.Response.End();
            }
        }
    }
}
```

web.configに起動時にモジュールを読み込むよう追記

```C#

<modules runAllManagedModulesForAllRequests="true">
  <add name="MaintenanceCheckModule" type="MyApp.HttpModules.MaintenanceCheckModule, MyApp" />
</modules>

```

これでサーバー側はリクエストが来るたびにチェック処理が入ります。

クライアント側はHttpResponseMessageのHeadersから取れます

```C#
HttpResponseMessage response = task.Result;

try
{
    string serverStatus = response.Headers.GetValues("ServerStatus").FirstOrDefault();
    if (statusCode == "Maintenance")
    {
        string body = response.Content.ReadAsStringAsync().Result;
        Console.WriteLine(body);
    }
}
catch { }
```
さくらのレンタルサーバの .htaccess に RewriteRule を書いてリバースプロキシする

## 概要
- さくらのレンタルサーバの .htaccess に RewriteRule ディレクティブを記述してリバースプロキシする
- 今回の環境: さくらのレンタルサーバ スタンダードプラン
- 2019年12月18日時点の動作確認結果
- https のサーバにリバースプロキシすると Internal Server Error になってしまう問題がある

## http://example.sakura.ne.jp/ から http://www.example.com/ にリバースプロキシする例

~/www/.htaccess に書く例。

```.htaccess
# http://example.sakura.ne.jp/ にアクセスする際に
# http://www.example.com/index.html にリクエストを投げてしまうため
# disabled で無効にする
DirectoryIndex disabled

# URL書き換え機能を有効にする
RewriteEngine On

# リバースプロキシ先のURLに書き換える正規表現
RewriteRule (.*) http://www.example.com/$1 [P,L,QSA]

# バックエンドのサーバが Host ヘッダを必要とする場合は設定する
RequestHeader set Host www.example.com
```

## http://example.sakura.ne.jp/foo/bar/ から http://www.example.com/foo/bar/ にリバースプロキシする例

### ~/www/.htaccess に書く場合

```.htaccess
# URL書き換え機能を有効にする
RewriteEngine On

# リバースプロキシ先のURLに書き換える正規表現
RewriteRule ^foo/bar/(.*) http://www.example.com/foo/bar/$1 [P,L,QSA]

# バックエンドのサーバが Host ヘッダを必要とする場合は設定する
RequestHeader set Host www.example.com
```

### ~/www/foo/.htaccess に書く場合

```.htaccess
# URL書き換え機能を有効にする
RewriteEngine On

# リバースプロキシ先のURLに書き換える正規表現
RewriteRule ^bar/(.*) http://www.example.com/foo/bar/$1 [P,L,QSA]

# バックエンドのサーバが Host ヘッダを必要とする場合は設定する
RequestHeader set Host www.example.com
```

## https のサーバにリバースプロキシすると Internal Server Error になってしまう問題

いくつかのパターンで試してエラーログを見たところ、どうやら https にはリバースプロキシできないようだ。

```
AH01961: SSL Proxy requested for example.sakura.ne.jp:80 but not enabled [Hint: SSLProxyEngine]
```

```
AH00961: HTTPS: failed to enable ssl support for xxx.xxx.xxx.xxx:443 (www.example.com)
```

```
SSLProxyEngine not allowed here
```

```
ProxyRequests not allowed here
```

SSLProxyEngine ディレクティブは .htaccess では使えないものなので SSLProxyEngine を On にすることもできない。

[mod\_ssl \- Apache HTTP Server Version 2\.4](https://httpd.apache.org/docs/current/mod/mod_ssl.html)

> Context: server config, virtual host, proxy section

## 参考資料
- [mod\_rewrite \- Apache HTTP Server Version 2\.4](http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html)
- [mod\_headers \- Apache HTTP サーバ バージョン 2\.4](https://httpd.apache.org/docs/2.4/ja/mod/mod_headers.html)
- [\.htaccessによるアクセス制御 – さくらのサポート情報](https://help.sakura.ad.jp/206054622/)
- [WordPress、EC\-CUBE、concrete5等CMSが使えるスタンダードプラン \- レンタルサーバーはさくらインターネット](https://www.sakura.ne.jp/standard.html)
【Tips】python+kivyの開発で困ったことと解決策

# 本記事の内容
###`kivy`を利用した`python`アプリの開発で困ったことと解決策を備忘として記載する。

# 環境(2020/04/04時点)
OS:macOS Catalina 10.15.3
kivyが使用するpythonのバージョン:3.6.5(Kivy3.appに入っているもの)
`toolchain.py recipes`が表示するpython3のバージョン:3.7.1(おそらく異なっていても問題ない)
kivyのバージョン:1.10.1


# 事象：`toolchain.py recipes`で表示される`kivy`のバージョンがおかしい
#### 事象詳細
[kivy-ios](https://github.com/kivy/kivy-ios)を`git clone`した直後に`toolchain.py recipes`を実行すると、`kivy`のバージョンが`18f37ed6e29620ee53c2a7699e0e0894e06a7f91`と表示される。

#### 起きていること
`kivy ver1.11.1`のリビジョン番号(正確にはリビジョン番号ではないが)が表示されている。

#### 解決方法
`kivy-ios/recipes/kivy/__init__.py`にバージョンがベタ書きされているので、(例えば1.10.1などに)修正する。
※特にやらなくてもよいかもしれない(私は気持ち悪く感じたので修正した)。


# 事象：`kivy`が実行できない(`import XXX`ができない)
#### 事象詳細
`ModuleNotFoundError: No module named 'kivy._clock'`と表示される

#### 起きていること
(エラーメッセージによると)`cython`のコンパイルができていないらしい。

#### 解決方法
原因がよく分からなかったが、`Kivy3.app`を一旦全削除して再度入れ直したら発生しなくなった。


# 事象：`kivy`のモジュールが`import`できない
#### 事象詳細
ある特定のモジュール(例えば`kivy.uix.listview`など)が`import`できない

#### 起きていること
何らかの理由により、`Kivy3.app`内にモジュールが格納されていない。
※モジュール使用非推奨の為モジュールを格納しなくなった、という理由が本線か。

#### 解決方法
`master`から持ってくる。
`https://github.com/nuigroup/kivy`を`git clone`して、必要なファイルをコピーすればよい。
`Kivy3.app`を`Applications`にコピーしたのであれば、コピー先は`/Applications/Kivy3.app/Contents/Resources/kivy`配下にある。
※モジュール使用非推奨の可能性もある為、ソースコード改修の方がよいかもしれない。


# 事象：`_trigger_reset_populate`が使えない
#### 事象詳細
エラーメッセージは消してしまっったが、`_trigger_reset_populate`項目がないみたいなことを言われる

#### 起きていること
(おそらく)`ListView`が使えなくなった。
※筆者は開発の途中で`kivy`のバージョンを上げた為。

#### 解決方法
`ListView`の代わりに`RecycleView`を使用する。
[ここ](https://github.com/kivy/kivy/tree/master/examples/widgets/recycleview)にサンプルがある。
`self.rv.data`は辞書型を要素に持つリストなので、表示したい値が複数種類存在する場合は`value`と同様に辞書型項目に格納して渡せばよい。

# 事象：`RecycleView`のデフォルト位置が一番上ではない。
#### 事象詳細
`RecycleView`を一度表示、少しスクロール、戻る、また`RecycleView`を表示、とすると、
いちばん上を表示して欲しいが、一度スクロールした場所をデフォルトで表示してしまう。

#### 起きていること
省略。

#### 解決方法
`RecycleView`の`scroll_y`に1を設定する。
これで`RecycleView`を表示すると常に一番上が表示されるようになる。

# 事象：フォントの設定が反映されない
#### 事象詳細
[こちら](https://qiita.com/Kernel_OGSun/items/44eb5b5f6e7bbfb9fc6a)の手順通りにデフォルトフォントを設定しても、反映されない。
※デフォルトフォントの初期値は`Roboto`

#### 起きていること
よく分からない。

#### 解決方法
[2020/06/14]
解決した。
`ダウンロードパス/IPAexfont00301`の箇所は`ipaexg.ttf`のファイルが存在するパス"のみ"を記載する。
`Config`ファイルで設定する方法も試したが、これだと`iPhone`に実機転送した際に上手くいかない様子。
EtherCAT 動画集（デモストレーション編）


この記事は [EtherCATについて語る Advent Calendar 2019](https://adventar.org/calendars/4097) の18日目です。
昨日は@nonnoiseさんの [EtherCAT 動画集（説明編）](https://qiita.com/nonNoise/items/0b471701a9453ae15afa) でした。


#今日の記事

今回も動画紹介記事です。
特に今回は『デモストレーション編』ということで、
EtherCATを展示会で見せる為だけに作られた動画を紹介したいと思います！

oO(なんと言うか、EtherCATを盛り上げる方は、どうも面白いことに使うのが上手いようで、かなり面白い使い方を皆さん考えていらっしゃいます！あぁ真似したい！）

#メーカーデモ動画

32 axis Ezi Servo EtherCAT Bechkoff
[![画像がここに入る](http://img.youtube.com/vi/Z4OJqI4gels/0.jpg)](http://www.youtube.com/watch?v=Z4OJqI4gels)


Cross Synchronous Motion at High Speed Short Pitch driven by Beckoff EtherCAT Controller
[![画像がここに入る](http://img.youtube.com/vi/vJMlKsR6xJc/0.jpg)](http://www.youtube.com/watch?v=vJMlKsR6xJc)


27 Captive LinearStep with Encoder 14 Axes Synchronous Motion driven by Soft Servo EtherCAT Contr
[![画像がここに入る](http://img.youtube.com/vi/UP5vaRSjTeg/0.jpg)](http://www.youtube.com/watch?v=UP5vaRSjTeg)

41 FESTO Gantry EXCH H bot driven by Elmo EtherCAT Controller
[![画像がここに入る](http://img.youtube.com/vi/ne74qQZxjOI/0.jpg)](http://www.youtube.com/watch?v=ne74qQZxjOI)



RosettaCNC & EtherCAT
[![画像がここに入る](http://img.youtube.com/vi/iDy6APcGGbw/0.jpg)](http://www.youtube.com/watch?v=iDy6APcGGbw)

maxon EPOS3 EtherCAT
[![画像がここに入る](http://img.youtube.com/vi/XNwnG00DwG8/0.jpg)](http://www.youtube.com/watch?v=XNwnG00DwG8)

【2019台北自動化展】精巧型EtherCAT多功能控制器
[![画像がここに入る](http://img.youtube.com/vi/0mdl4NePhqs/0.jpg)](http://www.youtube.com/watch?v=0mdl4NePhqs)

EtherCATロボットシステム / EtherCAT Robot System
[![画像がここに入る](http://img.youtube.com/vi/ZP5bRkDWIb8/0.jpg)](http://www.youtube.com/watch?v=ZP5bRkDWIb8)

(株)テクノ PCベースモーション(MECHATROLINK/EtherCAT)
[![画像がここに入る](http://img.youtube.com/vi/p-3S5702bb8/0.jpg)](http://www.youtube.com/watch?v=p-3S5702bb8)

Robot Braccio and EtherCAT using the EasyCAT Shield
[![画像がここに入る](http://img.youtube.com/vi/hnZfr_SReBE/0.jpg)](http://www.youtube.com/watch?v=hnZfr_SReBE)

IntervalZero RTXによるリアルタイムEtherCATデモ　-　ESEC2010
[![画像がここに入る](http://img.youtube.com/vi/1M2qTWDz2JM/0.jpg)](http://www.youtube.com/watch?v=1M2qTWDz2JM)

EtherCAT® with ARM®­ 32-bit Cortex®-M4 Core XMC4800
[![画像がここに入る](http://img.youtube.com/vi/EZyXWGzWeg0/0.jpg)](http://www.youtube.com/watch?v=EZyXWGzWeg0)

ESTUN servo applied for wrapping knitting machines with EtherCATjGTZ8ueQfGg
[![画像がここに入る](http://img.youtube.com/vi/vNl17N3b8Qk/0.jpg)](http://www.youtube.com/watch?v=vNl17N3b8Qk)


# ユーザー開発動画

EtherCAT Master Distributed Clock (DC) tests on Raspberry Pi
[![画像がここに入る](http://img.youtube.com/vi/jGTZ8ueQfGg/0.jpg)](http://www.youtube.com/watch?v=jGTZ8ueQfGg)

EtherCAT Device
[![画像がここに入る](http://img.youtube.com/vi/ImaFCOe_GMg/0.jpg)](http://www.youtube.com/watch?v=ImaFCOe_GMg)


Arduino Due + Ethernetシールド2でEtherCATマスター
[![画像がここに入る](http://img.youtube.com/vi/ZB0Fy-w4dPM/0.jpg)](http://www.youtube.com/watch?v=ZB0Fy-w4dPM)

EtherCAT やっと！やっと出来た！
[![画像がここに入る](http://img.youtube.com/vi/IJ3wDZTYThs/0.jpg)](http://www.youtube.com/watch?v=IJ3wDZTYThs)

#終わりに

まだ日本の動画が少ないですが、面白いデモ作っていますね！
やっぱり高速に制御が出来るって言うのは・・・**遊び道具**に最適じゃないでしょうか！！

それでは！
北神(@nonnosie)
Outlookのデフォルトテーマを変更する  (Windows & Mac)

`Outlook default theme change` とかでググってもまったく必要な情報が出てこなくて、かなり無駄に時間を消費したのでメモ

# 結論
`%appdata%\Microsoft\Templates\NormalEmail.dotm` を編集しろ
*Feb 18, 2020追記:* Macなら `~/Library/Group Containers/UBF8T346G9.Office/User Content.localized/Templates.localized/NormalEmail.dotm`

# 経緯
## 背景
会社のパソコンが物故割れたのでHDDをFormatしてイメージを焼いた。
アホほどデータがあって一昔前ならかなりの苦行だが、O365を導入しているので日頃からデータはOneDriveに入れていて、ちょっと動作が重いとか変なことしすぎてサービスが動かなくなったとかで気軽にイメージから戻せるので良い時代になったと感じる。
とはいえ `~\.ssh` とかの、OneDrive用のディレクトリに入っていないものは手動で退避が必要なのでちょこちょこ移動させていた。が、そもそも「だいたいOneDriveに入ってるしあとは消えても困らん」という思考でやっているので漏れが発生するのである。

イメージリストア後、とりあえずOfficeを入れてOneDriveにサインインして、さーて仕事に戻るかと思ったのだが、メールを新規作成しようとすると游ゴシックになってしまう。フォントの良し悪しの話は宗教戦争を巻き起こしかねないので注意が必要だが、そのへんは主題とは関係ないので見逃していただきたい。結局の所、私は游ゴシックはあまり好きではないので、別のフォントでメールを書きたいのである。

## WordとPowerPointは楽なのに
ところでデフォルトのテーマを変えたいといえば、WordとPowerPointも対象ではないだろうか。かくいう弊社も会社標準のPowerPoint Themeがあるので、そちらに適用した。 (WordのThemeもあるにはあるが、あまり実用的ではないというか、「会社の公式ドキュメント」用なので普段遣いはしていない)
WordとPowerPointは、ググればすぐに情報が出てくるのだが、一応書いておくと、せっせとフォントなり背景なり文字色なりの設定をしたあと、次の場所にテンプレートとしてファイルを保存することで、デフォルトのテーマとして動作する

- Word: `%appdata%\Microsoft\Templates\Normal.dotm`
- PowerPoint: `%appdata%\Microsoft\Templates\blank.potx`

## Outlookはググってもロクな情報がない
フォントを変えたいなと思って、ググって出てくるのは次のようなサイトだ。

-  [電子メール メッセージの既定のフォントまたはテキストの色を変更する - Outlook](https://support.office.com/ja-jp/article/1aabb236-01d4-4faf-b998-a4087da3ceab?omkt=ja-JP&ui=ja-JP&rs=ja-JP&ad=JP)

この通りにやってもまあできるっちゃできるのだが、これは **テーマのフォントは変えず** に、ただ文字を打ったときに指定したフォントになるというだけなのだ。フォントを変更するプルダウンメニューを開くと、「テーマのフォント」の下に「最近使用したフォント」として出てきて、かなりうざい。
私が変えたいのは「テーマのフォント」なのだ。

## 試行錯誤と発見
ところで、新規メッセージを作成して、「名前をつけて保存」で電子メールテンプレートとして保存する機能がある。Wordなどは「テンプレート」で動いていたので、これでなんとかなるのでは？と思ったのだが、どうやらこれは、定形のメール（週次でレポートを出すから本文の定形文と宛先を埋めておくとか）を出すときに使う以上の何者でもないようである。

結局このファイルの中身を確認したり、それっぽいディレクトリ (`.\Document Themes`, `..\Stationary`, `~\Documents\Custom Office Templates` など) に置いてみたり、拡張子をzipに変えて解凍してみたり (xlsxやdocxなどは実態はzipなので拡張子を変えたら解凍できる) して1時間くらい無駄にした。
そうやってファイルをいじくるのにテキストエディタ (Atom) を使っていたのだが、ふとファイルツリーを見たら……
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552879/7f0421a3-8f13-9e07-3ef7-3927d5463612.png)

**なんかある!!!!!!!!!!!!!!!!**

Outlookを起動しているとき、 `NormalEmail.dotm` が開かれた状態になっていた。そもそもOutlookって前提で考えてたから `dotm` のファイルなんて気にしてなかったよ。

## 結局
Wordで新規文書を作成して、中身は真っ白でよいので Theme Font とか Theme Color とか必要に応じて変更して、名前をつけて保存で `NormalEmail.dotm` にして保存したら、普通に効いた。
Firebase ML Kitでオンデバイス翻訳を使ってみる

# Firebase ML Kit
https://firebase.google.com/docs/ml-kit/?hl=ja
Googleの機械学習機能をAndroid、iOSアプリとして提供するモバイルSDK。
数ある機能の内の1つである`翻訳機能`を試してみます。

## デバイス / クラウドの両方に対応
オンデバイスAPIは実行速度が速く、オフライン環境で機能します。
クラウドAPIは、Google Cloud Platformの機械学習を利用して精度の高い処理が可能です。ただし有料。

## 翻訳機能
ML Kitのオンデバイス翻訳APIを使用すると、59の言語間でテキストを動的翻訳することができるらしいです。
Google 翻訳アプリのオフライン モードで使用されているモデルが搭載されています。

早速日本語→英語へ翻訳した動作結果です。
長文を翻訳した感を出したかったので、雑に青空文庫から著作権フリーの作品を引っ張ってきました。

`原文`
![Screenshot_20191018-022119_MLKitTranslation.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235269/d74f86f7-b64d-7e4f-f909-a6eaf12a6b37.jpeg)

`翻訳後`
![Screenshot_20191018-022138_MLKitTranslation.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235269/99f754a4-066a-1bd0-966c-ff7df7444122.jpeg)

文章が長いと翻訳に多少時間がかかりますが、それっぽく翻訳されました。
…`Angu`ってなんだろう？

### 手順
####  Firebaseのアプリ登録
google-services.jsonをプロジェクトに追加します。

#### ライブラリ追加
build.gradleにライブラリを追加します。

```gradle:build.gradle
dependencies {
  // ...

  implementation 'com.google.firebase:firebase-ml-natural-language:21.0.1'
  implementation 'com.google.firebase:firebase-ml-natural-language-translate-model:20.0.4'
}
```
#### 翻訳処理
FirebaseTranslatorオブジェクトを作成します。

```kotlin:Xxx.kt
// 日本語→英語への翻訳
val options = FirebaseTranslatorOptions.Builder()
        .setSourceLanguage(FirebaseTranslateLanguage.JA) // 翻訳元言語
        .setTargetLanguage(FirebaseTranslateLanguage.EN) // 翻訳先言語
        .build()
val japaneseEnglishTranslator = FirebaseNaturalLanguage.getInstance().getTranslator(options)
```

必要な翻訳モデルがデバイスにダウンロードされているか確認する必要があります。
モデルが利用可能になるまでtranslate()を呼び出してはいけません。
モデルは約30MBです。

```kotlin:Xxx.kt
japaneseEnglishTranslator.downloadModelIfNeeded()
        .addOnSuccessListener {
            // 翻訳モデルのダウンロード成功。翻訳準備OK
        }
        .addOnFailureListener { exception ->
            // 翻訳モデルのダウンロード失敗
        }
```

モデルがダウンロードされたことを確認したら、翻訳したい文字列をtranslate()に渡します。

```kotlin:Xxx.kt
japaneseEnglishTranslator.translate(text)
        .addOnSuccessListener { translatedText ->
            // 翻訳成功。翻訳されたテキストがリスナで渡される。
        }
        .addOnFailureListener { exception ->
             // 翻訳失敗
        }
```

## 制限事項
> デバイスでの翻訳は、カジュアルな翻訳や単純な翻訳を対象としています。翻訳の品質は、翻訳元の言語と翻訳先の言語によって異なります。このことを前提として、ご自身が使用する際の翻訳の品質を評価してください。より厳密な翻訳が必要な場合は、Cloud Translation API をお試しください。
>
> ML Kit の翻訳モデルは、英語と他の言語間の翻訳をトレーニングしています。英語以外の言語間で翻訳する場合は、英語が中間言語として使用されるため、品質に影響を与える可能性があります。

このような制限事項の記載がありました。
見ての通り長文翻訳はかなり怪しいので、単純な文章や単語の翻訳くらいに留める必要がありそうです。
WordPressの有料プラグイン「Search & Filter Pro」に除外検索(NOT IN)を追加する方法

###はじめに
複数条件検索を実装できるWordpressの有料プラグインが
1サイト$20と格安だったので購入してみた。

>**Search & Filter pro**
https://searchandfilter.com/

カテゴリ、タグ、カスタムフィールドを自由に組み合わせて
絞り込み検索が手軽に実装になるというプラグインで、
$20にしてはかなり便利なプラグインだと思う。
(デモビデオ：[Search & Filter Pro - Demo Video](https://youtu.be/cOavBxgslj4))

早速作成中のWordPressサイトに追加してみたが、
今回実装したかった除外検索(NOT IN)が選択肢にない...

この部分だけ直接PHPを編集して実装してみた。

---

###1.「プラグインエディター」を開く
「ダッシュボード」の左カラムメニュー「プラグイン」内にある
「プラグインエディター」をクリックして、
画面左上の『編集するプラグインを選択』で
「Search & Filter Pro」を選択する。

###2.phpに除外検索用のコードを追記する
例えばタグ検索の「Search Operator」に
「AND」「OR」に加えて除外検索用の選択肢を追加する場合、
`search-filter-pro/admin/views/fields/tag.php`
このファイルの64〜67行目に以下の記述がある。

```php:tag.php
<select name="{0}[{1}][operator]" id="{0}[{1}][operator]">
<option value="and"<?php $this->set_selected($values['operator'], "and"); ?>><?php _e("AND", $this->plugin_slug); ?></option>
<option value="or"<?php $this->set_selected($values['operator'], "or"); ?>><?php _e("OR", $this->plugin_slug); ?></option>
</select>
```

この部分で「Search Operator」の選択肢に応じて
ユーザーが検索した際の検索方法を指定しているので、

`<option value="NOT IN"<?php $this->set_selected($values['operator'], "NOT IN"); ?>><?php _e("NOT IN", $this->plugin_slug); ?></option>`

`</select>`の直前に上記のコードを加えて保存するだけで、
「Search & Filter Pro」の編集画面の「Tag」に
「NOT IN」という選択肢が加わる。
<img width="600" alt="スクリーンショット 2019-12-17 22.18.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552861/3328c8d1-e349-eaea-cf4b-7f2a9e5f3f58.png">


```php:tag.php
<select name="{0}[{1}][operator]" id="{0}[{1}][operator]">
<option value="and"<?php $this->set_selected($values['operator'], "and"); ?>><?php _e("AND", $this->plugin_slug); ?></option>
<option value="or"<?php $this->set_selected($values['operator'], "or"); ?>><?php _e("OR", $this->plugin_slug); ?></option>
<option value="NOT IN"<?php $this->set_selected($values['operator'], "NOT IN"); ?>><?php _e("NOT IN", $this->plugin_slug); ?></option>
</select>
```

あとはプラグインの画面上でいい感じに絞り込み検索を作成して
除外したい項目の「Search Operator」には「NOT IN」を設定しておけば、
想定どおりの絞り込み検索を実装することができる。

---

###タグ以外の項目で同様の選択肢を実装したい場合は...
`search-filter-pro/admin/views/fields`
上記の場所に「category.php」などそれぞれのPHPファイルがあるので、
「operator」でコード内を検索してみて
「NOT IN」の`<option>`タグを同様に追記すれば実装できる。

---
###注意点
※ PHPを直接いじるのでバックアップ等は必ず取っておくこと
シェルスクリプト set コマンド 3つの使用法

set コマンドはその実行の仕方によって、全く異なる用途に使われます。

#### 1. オプションフラグをセットする
set コマンドでセットできるオプションフラグはいくつかあります。

```bash:help-set
    Options:
      -a  Mark variables which are modified or created for export.
      -b  Notify of job termination immediately.
      -e  Exit immediately if a command exits with a non-zero status.
      -f  Disable file name generation (globbing).
      -h  Remember the location of commands as they are looked up.
      -k  All assignment arguments are placed in the environment for a
          command, not just those that precede the command name.
      -m  Job control is enabled.
      -n  Read commands but do not execute them.
      　　(一部抜粋）
```
たとえば、-f を使用してみます。
通常、echo * を実行すると、カレントディレクトリにあるファイル名に展開されますが、set -f を実行することで展開させないことができます。

```bash:set-optionf
$ echo *
Documents Downloads metastore_db Music Pictures Public Templates Videos
$ set -f  # パス名の展開を無効にする
$ echo *
*
$ set +f  # パス名の展開を有効にする
$ echo *
Documents Downloads metastore_db Music Pictures Public Templates Videos
```

#### 2. 位置パラメータをセットする
```bash:pos-parameter
# オプションなしで set コマンドに引数を与えると、それらは位置パラメータになる
$ set a b c
echo $2
b

# シェル変数を位置パラメータにセットしたい場合 set -- を使う
$ greet=hello
$ set -- $greet
$ echo $1
hello

# オプション(-a など)を位置パラメータにセットした場合も、set -- を使う
$ set -- -a
$ echo $1
-a
```

#### 3. シェル変数の一覧を表示する
引数なしで、set コマンド単体で実行すると、シェル変数の一覧が表示されます。

```bash:list-shell-variable
$ set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
(一部抜粋）
```
ボトムアップのエンジニアリングマネジメントを行って感じたこと

[Engineering Manager vol.2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/em2) 19日目の記事を担当させていただきます[@bayashi_ok](https://twitter.com/bayashi_ok)です。


今回は駆け出しマネージャーがエンジニアリングマネジメントを行う上で考え、心がけていることを書いていきたいと思います。

ちなみに先日のEOF2019 (Engineering Organization Festival 2019)ではボランティアスタッフとして参加し、登壇者やスタッフ、参会者の皆さんと関わり、EMの姿勢を学ばせていただいておりました。

自分自身は現在SREチームのリーダーとしてサイト信頼性向上を名目に、日々のToilの削減・監視見直し・SLOの制定などを行いながら、現在所属しているチームや組織への新技術の導入・プロビジョニングツールのソースコードレビューと管理、プロジェクト内のスポット的な相談役として運用も踏まえたうえでの設計～実装、など様々な事を行っております。

また、現在私は会社の立場的には約1年前にマネージャーなり、周りを引っ張っていく立場になりましたが、評価や1on1、採用（はたまにやっている）までは関わらずあくまでエンジニアの立場からチームや組織を見ながら色んな問題解決を図るようメンバーや上長に提案・実践をしており、いわゆる[Change Management](https://www.hito-link.jp/media/column/change-manegement)のようなものを行っております。

ただこれが果たしてできているのかというと非常におこがましい話となり、技術も劣る中、日々どうすればエンジニアも含め、それ以外の人たちを巻き込み幸せな組織になっていけるかということを、マネージャーの底辺の立場から考えていたりします。

さて、本題になりますが今回はそう言ったことを考え実践していくうえで心がけていること、またその中で迷走し失敗したことや反省点をかいていきたいと思います。

# １.相手に寄り添いながら小さな変化を促していく
近年技術に対するアウトプットがインターネット上で増えて行く中で、もちろんそれは素晴らしいことなのですがそれをそのまま組織やチームに取り入れることは必ずしも正解ではありません。

もちろん変化に柔軟な組織であるならばこれは歓迎されることになります。

ただそうでない組織にとっては、これまで培った文化的背景や技術的資産、個々のスキルやそこに費やせる時間などそういったものを鑑み、またそれらを使用している人たちの気持ちを汲み取り変化を行なっていかないと、いくら新しいものを取り入れたところでそれを受け入れてもらえない状態となります。

そのためにはやはり目の前の「人」を見ながら、寄り添い相手を尊重していくことや、時には厳しく自分の気持ちを発信していくなど、相手に寄り添いお互いの歩み寄りを大事にしていく必要があると考えています。

私自身マネージャーとなり、チームとしての技術の底上げや意識の統一をしていくために、いろんな努力をしてきましたが、その中できちんと「人」を見ながらできていたかというとそうではなく、反省すべき点がいくつもありました。

# ２.絶対に周りのせいにしない

何かがうまくいかないとき人は誰かのせいにしてしまいがちです。

ただそこにはやはりうまくいかなかった原因が何かしら自分にあるんだと思っています。

そのため、何かがうまくいかず周りのせいにしがちになりそうなときは

 - なぜそれができなかったのか
 - どうすればできるようになっていたのか

を考え、それが手段を変え実践していくための一つのアラートだと捉えています。

実際に私自身、なんどもうまく行かないときがありそのたび他責になりがちでした。


ただやはり、他責で終わってしまうとそれはただの「逃げ」になってしまいます。
自分のどこがいけなかったのか、何が相手の脅威になりえたのかをしっかり考えその脅威を取り払う努力をしなければ前に進めないことに気づかされました。

# ３.仲間意識を作る

同じ組織にいる人同士、また企業に所属し働いているものとして物事をよくしていきたいという思いが少なからずあると思っています。
またそこに対してその気持ちがない状態にあることは、その人に対し何らかの理由があるのではないのでしょうか。

その中での問題点や課題を洗い出し、解決していこうという共通の課題を作ることで仲間意識を作っていくことが重要だと考えています。

また時には争いもあるかもしれません。
しかしそこから問題とされている共通の目的意識を作り、ともに倒して行くことも重要になってくると思います。

まさに「昨日の敵は今日の友」となりえるのです。

# さいごに
簡単になりますが、私自身まだまだ新米のマネージャーで、EMの定義の中でも「弱めのEM定義」の部分にしか触れておらず、まだまだ学んでいかないといけない事がたくさんあります。

そういった同じような立場に立つ人たちや、これからエンジニアリングマネージャーを目指していく人たちに少しでも自分の経験を伝えていければと思い、今回のAdvent Calendarに参加させていただきました。

今のところ私は技術の促進も行いつつ、マネジメントも行う二足の草鞋の状態で今後どうしていけばいいかを日々考え、迷いながら日々過ごしております。今後どのような道を目指すにしろこれまでの経験は必ず生きてくるものだと思っておりますので、こういった経験をもとにより良いサービスを作っていけるよう頑張っていきたいと思います。

最後まで読んでいただいた方、誠にありがとうございました。