OmniAICreator/Qiita-1.07M huggingface dataset:
【TouchDesigner】1対多点の当たり判定(衝突)を取得する 


# はじめに

TouchDesignerアドカレ19日目に投稿させていただきます。
[@theruleisobeyed](https://twitter.com/theruleisobeyed)です。XR系ベンチャーの中の研究系チームにいます。
昨年の記事はこちら↓
[[TouchDesigner]Parent Shortcutを活用して強固なシステムを作る](https://qiita.com/theruleisobeyed/items/8fd7343218d06761d432)


# 当たり判定を取りたい
![ezgif-4-a8e43f821171.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151752/4790aab0-e74d-f429-a9c7-1e58440d28b1.gif)

インタラクティブコンテンツを作る際に、トリガーに便利な衝突の判定に関して、TouchDesignerでの実装例が見当たらなかったため本稿ではその一例をご紹介できればと思います。

今回は空間上に配置された点群に対して空間上のオブジェクト（コライダー）の当たり判定を取得し、当たり判定が出ている点に対して情報を割り当てることを考えます。(今回は衝突中の点に中心からの距離に応じた色を付けます)

##サンプル

こちら↓
https://github.com/ktkt40208/TD_CollisionDetector
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151752/0cac77e9-14a0-837d-41a3-3f60fdeea694.png)


## 考え方
今回の例ではDelete SOPを1対多の当たり判定取得に用います。
DeleteSOPではBounding TypeでBounding BoxとBounding Sphereの二種類の形状を選択でき、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151752/53c115d2-7dd9-f2bc-3c58-b6814697c298.png)
入力された点群に対してコライダーの形状の中に内包された点または内包されていない点の情報を取得できます。これを用いて空間上の点とコライダーとの当たり判定を取っていきます。ここでは7x7x7のグリッド状に配置された点群(総数343点)に対して直方体または球体(楕円体)を動かして衝突させます。
![bQtjT3fJpj.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151752/f98f0322-496e-8d09-31a3-fa299dfa6e27.gif)

## 内包された点と内包されなかった点の情報の整理
ただしこのままではコライダーに内包されたorされなかった点のそれぞれの中でのindexと各点の座標情報しか残らないため、全体から見た各点のindexを情報として持たせます。Point SOPのCustomタブでCustom Attrib Type: int とし、custom1val1にme.inputPoint.indexを
指定することでにより343点に対して0-342のインデックスを割り当てることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151752/3f26d480-5dc2-61c3-e90c-cc4bf2e35699.png)

このindex情報をコライダーに内包された点と内包されなかった点それぞれの情報を0,1の値と対応したDATに変換し、合成することで343chの0-1情報へ変換します。
![ru0jzog8aR.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151752/ecc08269-6c52-d0d3-fffd-a951b72c2842.gif)

## 各点毎にユニークな情報の付加と可視化
それでは何かこの343点に対して各点毎にユニークな情報を付加して可視化してみましょう。
コライダーの中心座標からの距離に応じた0-1の値を計算(343ch)し、先程の衝突情報を記録した343chのCHOPと掛け合わせて、
![8FRa9JCjTO.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151752/99b78563-d866-3151-01b4-cd36defd8e50.gif)
衝突している点のみに対してそのコライダー中心座標からの距離に応じたRGBの値を計算し、
![rXo8ntE21s.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151752/d506bb4e-a9a5-a995-dc6a-6270509d6f5e.gif)
Geometry Instancingで表示します。
![fTrit8CBXb.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151752/f711fd91-3d1a-fcbe-e35b-3d0530f98fce.gif)
以上になります。

##制約
今回の実装ではDelete SOPを用いて行いました。その制約として、DeleSOPのBounding TypeのBounding BoxとBounding Sphereに形状が制限されています。
自身のプロジェクトでは点群との衝突を判定する形状はプリミティブで十分でしたので気にせず運用ができましたが、そうでない場合はSDF周りの計算を挟んで解決する形になるのではと考えています。

また、Delete SOPを使う上でBoundのSizeとCenterは操作可能なものの、Rotationのパラメタが存在しないため、Delete SOPの計算前にBoundオブジェクトの回転を打ち消す座標変換を行ってから計算を行う段取りになっています。

もし似たような課題に取り組まれた方がいらっしゃればコメントいただけると幸いです。
デプロイ時のエラー

備忘録として書き残しておきます。
必要に応じて随時編集します。

#Capistranoが動く場合
以下の設定を行うと、本番環境でもローカル開発環境と同じように、ブラウザにエラーメッセージが表示されるようになります。

config/environments/production.rb

```
（前略）
  config.consider_all_requests_local = true
（後略）
```
「config/environments/production.rb」のファイルの中から、上記の記述を見つけましょう。もともと「false」になっているので、「true」に変更します。

この変更を本番環境に反映させる必要があるので以下の2つの操作を行いましょう。
①GitHubへのプッシュ
②「bundle exec cap production deploy」の実行

なお、エラー対応が終わったら、忘れずにfalseに戻してデプロイをし直しましょう。
#####※外部からもエラーメッセージの確認が出来る様になるためセキュリティ上知られてはいけない情報が漏れる可能性があります。

#Capistranoがエラーになる場合
Capistranoがエラーになってしまう場合は、上記の方法が取れません。
エラーログを直接確認しましょう。

エラーの内容によって、主に以下の2つのファイルにログが書き込まれます。
どちらに該当するかわかりにくい場合は、両方とも確認しましょう。

###Unicornのエラーログの確認方法
ターミナル

```
cat /var/www/（アプリ名）/current/log/unicorn.stderr.log 
```
ターミナル

```
cat /var/www/（アプリ名）/current/log/production.log
```
最初は、エラーログを読むのは少し難しいので、以下にいくつかポイントをご紹介します。参考にしてください。

Railsアプリのエラーログの確認方法
エラーログを確認するときは、以下の点に気をつけましょう

エラーログの見方
・ファイルの下に行くほど新しいログが載っています
・いつのログなのかを必ず確認しましょう

いつ起きたエラーに対するログなのかを確認することが重要です。

まず、ログの中にタイムスタンプがあったら、そこに９時間を足しましょう（標準時での出力になるため、日本は９時間の時差があります）。その時刻と、今の時刻を見比べて今起きたエラーなのかをチェックします。

# ログを確認してもエラー表示がなかった場合
稀なケースかもしれませんがログを確認してもエラーが出なかった場合

```
rm current/log/unicorn.stderr.log
```
↑でログの履歴を削除してから

```
less current/log/unicorn.stderr.log
```
↑で確認をすると表示させれる場合があります。
Velodyne Lidar(VLP-16)を設定してMacで点群を確認する

自動運転車でよく使われるVelodyne Lidar（VLP-16）をセットアップして、MacのViewrで点群が表示されることを確認してみる。

# 接続
VelodyneのボックスからLANケーブルを自宅のWifiルーターに接続した。
![IMG_5020.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80263/fbf58567-24c3-554e-b8a5-7e606c54d6f1.jpeg)

# IP確認
arp-scanなどでVelodyneのIPを確認する。分かりやすくVelodyneと出てきた。

```
% sudo arp-scan -l
192.168.0.11		Velodyne
```

# 設定画面
ブラウザでVelodyneのIPにアクセスすると設定画面が確認できる。
自分のMacのIPをHost(Destination)のIPアドレスに設定する。
![Screen Shot 2020-12-20 at 18.18.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80263/6d99a381-424e-1d60-3e78-f862001cc84f.png)

# Viewerで点群を確認
Rvizなどでもよいが、今回はVeloviewを使用。
「Version 3.5.0 – Mac OSX 10.9」これを入れてみた。
https://www.paraview.org/veloview/
ちなみにVelodyne設定のデータポートは、2368でないと点群が表示されなかった。
![Screen Shot 2020-12-20 at 18.17.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80263/3f8663d2-3b15-0d3c-e26d-68a3d715eb6d.png)

# Wiresharkでパケットを確認
Viewerで見れない場合などはパケットを見てみるとよい。
ライダーのIPからMacのIPに大量にデータが流れていることが分かる。
![Screen Shot 2020-12-20 at 18.37.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80263/27810ce6-474d-4e0e-5698-bb1df109fe8e.png)

# 参考
http://wiki.ros.org/velodyne/Tutorials/Getting%20Started%20with%20the%20Velodyne%20VLP16
モンテカルロ法で円周率を求める？（Ruby）

メンターに「新しい言語を覚えるにはモンテカルロ法で円周率を求めてみたりするといいっすよ！」とアドバイスを頂いたので、盲目的にやってみることにしました。

#何を言っているの？(笑)
しかしながら、「モンテカルロ法で円周率を求め」るという日本語が全く意味がわからず、それを理解することからスタートとなりました(笑)

### 単語の整理

- **モンテカルロ法**：乱数を用いて観察、分析すること。モンテカルロとはMonte Carloでモナコ公国のある地区の名前らしいです。
- **乱数**：決められた数字の範囲の中で、ランダムに等確率に出力された数値。
- **円周率を求める**：私が理解したのは、結論から言うと、単位円の面積を求めるということ。
- **単位円**：半径が1の円のこと

まとめると、**モンテカルロ法で円周率を求める**とは、**数字をランダムで生成してそれを分析し、半径１の円の面積を求めること**と理解しました。

まだ、意味がわかりません(笑)

###円周率の求め方
というわけで、ネットに転がっていた頭のいい人たちの考え方をここに整理します。

(1) まず、半径１の円の面積を求めるには、円を四分割します。
(2) そしてそれを一辺が1の正方形の中に収めます。
(3) その正方形を座標と捉え、下図のようにイメージします。
![tansu（仮） (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645077/e71d1f74-8f7c-45a2-6f24-08c9aae2f768.png)
(4) 下が1/4円が入った状態です。（点は一瞬無視してください）
![tansu（仮） (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645077/e3e97469-d665-026a-d89b-043b3c41417b.png)
(5) 上の正方形の中にランダムで点を打っていきます（点を見てください）。つまり、(x, y)の配列をランダムに打っていきます。
(6) これをn回（たくさん）やります。
(7) 円の中に入った点（ピンクに色付け）をカウントし、pとします。
(8) どうやって点が円の中にあると判断するか？始点`(0, 0)`からランダムな点`(x, y)`の長さを計算して、これが1以下であれば円の中と判断すれば良いです。
![tansu（仮）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645077/efbb6445-5dbe-73bb-b984-e68c09b2c36f.png)
(9) `(0, 0)`から`(x, y)`の長さは、これを直角三角形の斜辺として計算すれば良いです。三平方の定理は覚えていますか？（僕は忘れてました）
(10) n回終わったら、pをnで割ると（p/n）、これが1/4円の面積の近似値となります。
(11) p/nを4倍すると、円の値が求まります。

#プログラムにすると
コードですが、僕はこのように書きました。
（コメント欄にて、@scivola さん、 @kojix2 さんのアドバイスもぜひご参照ください）

```ruby:main.ruby
n = 1000000
count = 0

for i in 0 .. n
    z = Math.sqrt((rand ** 2) + (rand ** 2))
    if z < 1
        count += 1
    end
end

#円周circumference
cir = count / n . to_f * 4 #to_f でfloatにしないと小数点以下が表示されない

p cir
```

* `Math`とは、ビルトインモジュールで、数学系のメソッドをグループ化しているもの。
* `.`レシーバのメッセージを指定（この場合、メッセージとは`sqrt()`）
* `sqrt()`とはsquare root（平方根）の略。PHPと似てる。

#あとがき
36歳未経験でIoTエンジニアとして転職しました。そのポジションがRubyメインのため、慣れ親しんだPHPを置いて、Rubyの勉強を始めています。

もしご指摘などあればぜひよろしくお願い申し上げます。


noteに転職経験をまとめています↓
[36歳未経験者がIoTエンジニアに内定しました（1/3）プログラミング学習遍歴編](https://note.com/kakudaisuke/n/nb35aef8a06df)
[36歳未経験者がIoTエンジニアに内定しました（2/3） ジョブチェンジの迷い編](https://note.com/kakudaisuke/n/n0ca8f2631b8d)
GoogleMap がブラウザをリロードしないと表示されない件

ポートフォリオでGoogleMapを取り入れた時に、ページ遷移では動作しない現象が起きました。
その解決法を調べたのでまとめました。

# 原因
**ずばり、Turbolinksが原因です。**
Turbolinksを有効にしたままページ遷移した場合、遷移先にJSの動作があるのに発火しないという状況になってしまいます。

そもそもJSやjQueryには動作を効かせるためのイベントがあります。**Turbolinksは最初のページ読み込み時にこれらのイベントを発火しますが、ページ遷移したときは発火しません。**

# 解決法
`app/assets/javascripts/application.js`に記述してある`//= require turbolinks`の行を消すことで解決します。
他の方法での解決策もあるそうです。

#
---
この問題を解決するに当たってTurbolinksについて調べました。

# Turbolinks とは
Turbolinksとは、Rails4から正式導入された画面遷移を高速化させるライブラリです。Turbolinks自体はJavaScriptのライブラリとして提供されていますが、Railsでは利用しやすいようにGemとしてデフォルトで組み込まれています。

# Ruby on Rails での導入方法
①`gem ‘turbolinks’`を `Gemfile` に記述
②`bundle install`
③`app/assets/javascripts/application.js` に `//= require turbolinks` と記述

※ Rails4以降では`rails new`で自動的にTurbolinksについて記述済

# Turbolinksの仕組み

![スクリーンショット 2020-12-20 18.10.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/870700/baf58f12-60ea-b89f-bcf9-f04a335033cd.png)
「[【Rails】初心者向け！画面遷移の高速化を行うTurbolinksについて図を用いて詳しく解説](https://techtechmedia.com/turbolinks-rails/)」より引用


①リンクのクリックイベントが発火
②画面遷移を阻害し、非同期でリクエストを送る
③HTMLをレスポンスとして返す
④現在のページと一致しているかチェック
⑤画面遷移が起きたように見せかける

### ①リンクのクリックイベントが発火
Turbolinksは同じドメイン内のaタグを監視しており、クリックされることでTurbolinksの仕組みが動き出します。

※ ドメイン = インターネット上の住所

### ②画面遷移を阻害し、非同期でリクエストを送る
Turbolinksはリンクがクリックされたことによる画面遷移を阻害し、History APIを用いた非同期のリクエストを送ります。

※ History API = ブラウザのページ遷移履歴を管理・操作するためのAPI
※ API = アプリケーションをプログラミングするためのインターフェース
※ インターフェイス = コンピュータ用語で「何か」と「何か」をつなぐものという意味

### ③HTMLをレスポンスとして返す
リクエストを受けたサーバーは、HTMLをレスポンスとして返します。

### ④現在のページと一致しているかチェック
レスポンスとして返ってきたHTMLにあるheadタグ内のJSとCSSが現在のページと一致しているかチェックしています。これは次の動作である置き換えを行うための準備に当たります。

### ⑤画面遷移が起きたように見せかける
Turbolinksは現在のbodyタグを置き換え、headタグの中身はマージします。そして、あたかも画面遷移が起きたように見せています。

---
参考記事
[[rails/javascript]googlemapがブラウザをリロードしないと表示されない](https://teratail.com/questions/201038)
[5分でわかるTurbolinks入門【Ruby on Rails】](https://coffeecups.blue/turbolinks/)
[【Rails】初心者向け！画面遷移の高速化を行うTurbolinksについて図を用いて詳しく解説](https://techtechmedia.com/turbolinks-rails/)
RPA勉強会での勉強方法 ～Power Automateを使って～

　この記事は「[RPACommunity：RPAに関するよもやま話 Advent Calendar 2020](https://adventar.org/calendars/4992)」の22日目の記事です。

　　RPACommunityを始め、様々なオンライン・イベントに参加するようになりましたが、参加数が増えてくると悩ましいのが、どのイベントで聞いた話だったか、誰が話した内容だったか思い出せないことがでてきます。オフライン・イベントだと、何かの出来事と結びついていたり、いただいたノベルティをきっかけに思い出すこともあるのですが、オンラインだとそういうものもありません。

　　そこで、当たり前のことですが、ノートをとることにしました。でも、めんどくさがり屋なので、何か自動化できないかと考えました。

#◆Power Automateのテンプレートを使う

　参加するconnpassのイベントは、全てGoogleカレンダーに登録しています。カレンダーへの登録と同時に、OneNoteにページが出来上がっていれば、何かノートに記入せざるを得ない状況になるのではないかと考えました。Power Automateには、既にテンプレートがありますので、これを使っていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/09cd041b-96d8-34e7-f2de-0a6856d3bdcf.png)

テンプレートは以下のようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/dd0fd852-ce20-1b49-39af-bcb71196ef08.png)

#◆条件の追加

　これだけだと、何でもかんでもOneNoteのページが作られてしまうので、条件を追加します。

　connpassからGoogleカレンダーへ登録をすると、説明欄にconnpassのURLが入るので、説明欄に「connpass」の文字が入ってるか、またはタイトルが「☆」で始まる場合という2つの条件を入れています。「☆」は、connpass以外のイベントでもノートを登録できるようにというのと、イベント終了後は、「☆」をタイトルから消して、参加済みとするようにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/c680811e-24b4-08b7-8752-c5a16250c852.png)

　GoogleカレンダーとPower Platform間のデータは標準時になっていますので、開始時間を日本時間に変更してやります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/fbf4fd8b-bc69-10d1-b4e5-9f9488abf954.png)

#◆セクションページを作成

　Onenoteへページの追加を行います。ページコンテンツの書き方は、htmlになっています。タイトルとか、ページの中身に情報を入れ込むようにしています。htmlタグをいくつか試しましたが、あんまり手の混んだことはできないようだったので、<title>と<li>で済ますことに落ち着きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/05dcc3bb-8254-f7ff-c5b4-0aebcf6460f1.png)

　全体は、以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/be9be658-d488-be84-3c07-10f5ae8b2c5a.png)

#◆いざ、実食！

　では、実際に動かしてみます。connmassへイベント参加申し込みを行った後、Googleカレンダーへ登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/a44fe046-9bf5-6da7-4097-4b86050132f5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/a7ff82a3-613a-4d5c-30bc-61c1ad665b4c.png)

　保存する前に、タイトル部分の頭に「☆12/28」と、星マークと日付をつけます。Googleカレンダーには、以下のように登録されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/f3ea877e-7796-fffa-15c7-40c475c2391f.png)

  しばらくすると、OneNoteには、以下のページが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/59da70eb-ff20-df8d-9fd9-a91ea3eb52ed.png)

#◆ノートの取り方

　イベント開始前にはconnpassのタイムテーブルを貼り付け、イベント中は、このノートにスクショを貼ったり、メモを取ったりします。オンライン・イベントになって、一番いいのは、その場でスクショが取れることですね。終了後は、タイトルの「☆」を消して、RPA関連のセクションに移動させてます。このフローがあるおかげで、イベントでノートをとる癖がつきましたし、後から資料とか入手したら張り付けたりして、とても重宝しています。

　やり方も、最初は慣れないところですが、いっぺんに覚えるのは難しいのですが、少しずつなら楽しみながら覚えることができると思います。

　また面白いものができたら紹介できればと思います。

#◆あとがき

　今年も、もう残すところ今日を含めて10日となりました。来年も使えるように、タイトルの日付に西暦入れた方がいいかしら、などと、これまでのノートを振り返りながら考えます。ついでに、OneNoteのページをタイトルでソートできる機能があるといいな。ないなら、自分で作れということかな？
Alexa APL：一見取れなさそうな場所にあるバインド変数を取得・設定する

# はじめに

本記事は[スマートスピーカー Advent Calendar 2020](https://qiita.com/advent-calendar/2020/smart-speaker)の10日目の記事ですが、[20日目](https://qiita.com/kyukkyu81/items/3ae606063ef4c82b84f5)の記事を書く際に発見した事をもう少し共有してみようと思い、20日目の後に書きました。

# お題

SetValueコマンドで値を設定するとき、

**`実行する場所`と`取得元`と`設定先`がみんな違う時、どうするか？**

です。

[今回の例](https://apl.ninja/document/Synoyan/VenR4NUT)は１つのキャラを実装するところまでのコードですが、実際のゲームではキャラクタ同士の衝突判定など、「ゲーム進行役の処理」が必要になってきます。ここでもhandleTickを使うことを考えた際、それぞれのバインド変数がそれぞれのコンポーネントにあるため、「キャラクタのバインド変数が取れない」という壁にぶつかります。

以下のように記述することで、任意の場所のバインド変数を任意のコンポーネントのバインド変数に突っ込むことが出来ます。
例えば・・・

**`"from"というIDを持つコンポーネントの"departure"というバインド変数`**に入っている値を
**`"to"というIDを持つコンポーネントの"arrival"というバインド変数`**に代入する
という処理を、
**`LambdaからのExecuteCommandディレクティブ`**で行ってみたいと思います。

# 実践

## １：下準備
mainTemplate内、一番大元のContainerコンポーネントに名前を付け（ここでは"root"）、バインド変数に以下のように定義します。

```json:ExtremeSetValue-1
{
    "type": "Container",
    "id": "root",
    "bind": [
        {
            "name": "G_var1",
            "value": 0
        }
    ]
}
```

※ 正確には、後述の`取得元`と`設定先`が含まれるコンポーネントであればOKです。

## ２：取得した値を仮置き場に代入

一旦１で作ったバインド変数に値を入れます。

```json:ExtremeSetValue-2
{
    "type": "SetValue",
    "componentId": "from",
    "property": "G_var1",
    "value": "${event.target.bind.departure}"
}
```
G_var1は一番大元のコンポーネントのバインド変数なので、いわばグローバル変数のようなスコープとなり、どのコンポーネントからでも参照可能となっています。
（「ExecuteCommandディレクティブという場所」からG_var1を参照しているのではなく、「fromというIDのコンポーネント」からG_var1を参照している点に注意）

componetIdで指定したコンポーネントのバインド変数を取得するには、"event.target.bind.～"で取得可能です。


## ３：仮置き場の値を設定先に代入
(２に続けて)１で作ったバインド変数から値を取り出し、目的の場所に設定します。

```json:ExtremeSetValue-3
{
    "type": "SetValue",
    "componentId": "to",
    "property": "arrival",
    "value": "${G_var1}"
}
```

できました！:thumbsup:

要は、

+ **グローバル変数（のようなもの）を作って、A⇒tmp⇒Bと２段階代入する**

ということです（おっと１行で説明できてしまったぞ・・・）。

# あとがき

ここまでくるとネタというか大道芸のレベルに突入してそうな気もします…:sweat:

複数の場所で使う場合はそのぶん変数を用意するなど、値の混在に特に気を付けましょう。特にその場でバインド変数があてがえないrenderdocument直下のonMountやLambdaからのexecutecommandディレクティブで重宝するかも？

「なんでそんな事しないといけないの？」と思う方が多いと思いますが、実際に行き詰った方は共感して頂ける…はず…:confounded:例えば"value": "${component.from.bind.departure}"などといったようにバインド変数を取得したいコンポーネントIDを直接指定できればなぁ。（念のためですがそのような記法は存在しないので後で検索で見つけて喜ばないでね）

以上です！
勉強メモ10_VBAの文字列結合を一瞬で終わらせるメモ（＆結合からjoinに変える）

★0　はじめに
　　最近VBAの仕事で普通の文字列結合を
　　「＆」で結合したらばりばり遅いということを知り、
　「1234」という文字を100万回結合して時間を測定する実験を行った。

★1　&でつなげるとまじ遅い、以下の100万ループは30分かかった

```vb
Sub Macro1()
  
  Dim kaishi As Single
  kaishi = Timer

  Dim a As Long
  Dim sq As String
  
  For a = 1 To 1000000
    sq = sq & "1234"
  
  Next a
  
  MsgBox "処理にかかった時間は" & Round(Timer - kaishi, 1) & "秒です。"
  
End Sub

```

★2　JOINでやった場合、1秒で終わった。(midの方がもっと速いらしいけど)

```vb
Sub Macro1()
  
  Dim kaishi As Single
  kaishi = Timer
  
  Dim a As Long
  Dim ss() As String
  Dim sq As String
  
  For a = 1 To 1000000
  
   ReDim Preserve ss(a - 1)
   ss(a - 1) = "1234"
  
  Next a
  
  sq = Join(ss, "")
  
  MsgBox "処理にかかった時間は" & Round(Timer - kaishi, 1) & "秒です。"
  
End Sub

```

★3　参考資料

http://yiaowang.web.fc2.com/programing/vba_xls_speedup/string_append.html
新卒2年目の自分が初めてPMをやってみて得られた教訓

ランサーズ [Advent Calendar 2020 19日目](https://qiita.com/advent-calendar/2020/lancers) の記事です。18日目は [nagayu_suki](https://qiita.com/nagayu_suki) さんの [断捨離されるIssueたちをUXライティングで救う](https://note.com/who_cares/n/nd45e70c9042b) でした。

## はじめに

ランサーズ株式会社でプラットフォーム事業の開発・運用をしている垣井と申します。

今年のアドベントカレンダーは何を書こうかと迷っていましたが、今年初めて(小さなプロジェクトでしたが)PMっぽい業務をやらせていただいたので、そこで得られた教訓を失敗例とともに振り返っておこうと思います。

## 教訓1: 「だろう運転」をしない

「これはこうだろうな」と自分の都合のいい思い込みでちゃんとした確認ができていなかったり、早めに行動した方がよかったことをだいぶ遅くなって行動してしまっていたことがありました。

例えば仕様を確認して機能の設計をしようとした時、設計をどう詰めていくかについて開発責任者の上司に相談をしていたのですが、そもそも達成したい要件が不明確で「なぜこの仕様になったのか、何をしたいのか」に関して正確に答えられない状態でした。

その状態でなぜ上司に設計の相談をしに行ったかというと、渡された仕様書を読んで「これがやりたいんだろうなー」と曖昧に要件を予測していたからでした。

他にも、問題ないだろうと思っていた設計でパフォーマンスに影響のある部分が見つかったりと、「だろう運転」によってリスケを繰り返し行っていたので、失敗に失敗を重ねていました。

教訓としては、「だろう運転」をするとプロジェクトがどんどん後ろ倒しになっていくので、確認することがあれば有識者にすぐ確認する、自分の立ち位置を経験している人に他に確認しておくべきことないかなどを早めに相談してみる、などが必要になってくるのかなと感じました。

## 教訓2: ボールを早く渡すよう意識する・工夫する

「業務を進行していく上での過程のようなもの」を僕は「ボール」として捉えていますが、プロジェクトを進める上で僕が抱えてる時間が比較的長かったように感じています。

例えば設計に関して相談をしたい時、少し複雑な状況も説明する必要があったため長文にしてチャットしていた時が多々ありました。そのチャットの文章を考えるだけで結構な時間を使っていたりと、不必要に時間を使いすぎてしまっていました。

ここで気をつけたのは、時間をかける「バランス」を意識したことです。
最低限の内容にした上でスピードを優先する、自分が億劫になってしまうほど文章を作らないことを念頭に置いてコミュニケーションをするようになりました。

最初はなかなか最初で意味を伝えられず聞き返されることがしばしばでしたが、コミュニケーションの速度はかなりあげられたと思います。

## まとめ

今回PMをやったことで、どうすればプロジェクトがうまく進むかを模索しながら仕事をしていたのでいい勉強をすることができました。特に今回は失敗続きなプロジェクトだったので、今後またPMを任せてもらった際には今回のことを生かして頑張りたいと思います。
【Markdown】個人的に使用するMarkdown記法 チートシート

#個人的に使用するMarkdown記法 チートシート
個人的に使用しそうなMarkdown記法をまとめる。

##見出し
```
#：H1タグ
##：H2タグ
###：H3タグ
####：H4タグ
#####：H5タグ
######：H6タグ
```
結果
# H1タグ
## H2タグ
### H3タグ
#### H4タグ
##### H5タグ
###### H6タグ

##引用
```
> element1
>  1. element1
>  1. element2
※2,3重引用も可
>> element2
>>> element3
```
結果
> element1
>  1. element1
>  1. element2
>> element2
>>> element3

##インラインコード
```
インラインコードは`test`です。
```
結果
インラインコードは`test`です。

##文字修飾
######イタリック
```
_test_
*test*
```
_test_
*test*
######ボールド
```
__test__
**test**
```
######取り消し線
```
~~test~~
```
~~test~~
ドローンバード訓練１

来年の活動目標的な感じで書きたいと思います。

２０１８年？から活動に参加し片手で数えられる程度の参加になりますが
私なりに見えてきた２０２１年の訓練を考えます。

個人的な訓練感想ですが、訓練と言うよりデモ要素が強いと感じています
また、平日に開催されるため、サラーリーマンは休暇を取らねばなりません
この辺りも課題と思ってます。

デモ要素が強いと感じる要因としては、私も含めて飛ばせる人が少ないと思います
故に、飛ばせる人の見学することがメインになっている気がします。
あと、機体をお持ちの方でも飛ばす事に不安があり、不安故に躊躇されてると感じます

私が、計画している２０２１年「訓練プログラム」（体験〜初心者向け）に下記５項目を考えてます

１、休日開催訓練（３ヶ月に１回開催　年４回）
２、固定翼、回転翼のマニュアル飛行訓練
３、家でも手軽に練習できるマイクロドローン紹介
４、シミュレータ訓練
５、マッピング訓練


現状２（固定翼は除く）、３、４番は、ご紹介できるレベルにあると思ってます
このアドベントカレンダーを通じて簡単に紹介して行きたいと思います
もう、日が少ないですけど。。。。
SQLでグルーピングした中で1つを選択したい場合の書き方

# 概要
いまさらながら、SQLでグルーピングした中で1つを選択したい場合の書き方についてのメモです。

例えば下記データのようにコードがあって枝番がある場合。
コードの単位でグルーピングして、その中で枝番が最大のものを抽出したいようなケース。

▼テーブル：fruits

| code | eda | name | |
|:-:|:-:|:-:|:-:|
| A001  | 01  | りんご１  |  |
| A001  | 02  | りんご２  |  |
| A001  | 03  | りんご３  | これを抽出したい |
| B001  | 01  | みかん１  |  |
| B001  | 02  | みかん２  |  |
| B001  | 03  | みかん３  | これを抽出したい |
| C001  | 01  | バナナ１  |  |
| C001  | 02  | バナナ２  |  |
| C001  | 03  | バナナ３  | これを抽出したい |

# SQLの書き方１

コード毎に枝番の最大値を求め、その枝番で絞る。

```sample1.sql
select * from fruits f
where
    f.eda = (
        select max(eda) from fruits
        where code = f.code
    )
```

# SQLの書き方２

コード毎の枝番の最大値を求め、それを条件にして抽出する。
抽出方法はイメージしやすい気がする。

```sample2.sql
select * from fruits f
where
    (f.code, f.eda) in (
        select code, max(eda) from fruits
        group by code
    )
```

# SQLの書き方３

ウィンドウ関数を使う例。
コード毎に区切り、枝番で降順に並べて番号を振る。
最後に枝番最大のものが番号1になるので、それを抽出する。
見た目はシンプルな感じがする。

```sample3.sql
select * from (
    select *, 
        row_number() over (partition by f.code order by f.eda desc) rnum
    from fruits f) a
where
   rnum = 1
```
micro:bitの電波はどれくらい飛ぶのか試してみた話

#micro:bitの電波はどれくらい飛ぶのか試してみた話
###micro:bitのDXチャレンジ
大昔になりますが、中学～大学の頃アマチュア無線に熱中した時期がありました。元をたどると玩具のトランシーバーで遊んだのが原点だったと思いますが、何もない空間を電磁波というよく分からないものでダイレクトに情報が伝わる、という感動はずっと持ち続けていて、いまだにラジオを作ったりエアバンドを聞いて喜んだりしています。
アマチュア無線の醍醐味は自分の家から思わぬ長距離に電波が飛ぶところにあるのですが、長距離通信のことをDX（Distance）という略語で呼びます。自宅のアンテナから出た電波が他県や国外という長距離に到達する経路を想像するのが楽しいのですね。

無線はmicro:bitにとっても重要な機能です。micro:bit同士を通信させるときも、ちょっとした感動があります。無線機能を使うと小学生でも手軽に通信が体験できるのが、他のマイコンボードとの大きな差別要因とさえ言えます。

この無線機能は、室内では障害物がなければ問題なく使用できますが、教育目的の場合、体育館や校庭などの広いエリアでスポーツと絡めた活用法も考えられます。その場合の通信距離はどの程度を想定しておけばよいのか、とりあえず実験してみることにしました。

というのは建前で、micro:bitでDXがどこまで行けるかという、単なる遊びですｗ

###実施方法
実施にあたり必要なのは、広い空間と距離測定の方法です。近所には広大な公園もあるのですが、長尺の巻き尺も測距儀もないので、近所の川沿いの遊歩道を利用してみました。
ここはかなりの直線区間がある上に、転落防止の柵がきっちり２ｍ間隔で作られているため巻き尺代わりに距離が測れるというメリットがあります。

![IMG_2036.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927104/1b5db58d-fcbb-52f0-b494-621dfa132901.jpeg)

計測には、送信機と受信機の２台のmicro:bitを用意しました。送信側はひたすら１を送信し続け、受信側は着信したらLEDを点灯させます。
送信機を柵に固定しておき、自分は受信機を持って遊歩道を歩き、送信機から離れていきます。受信が不能になった（LEDが点灯しなくなった）距離を、通過した柵の本数で測ろうというものです。
####送信側
![送信側.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927104/d93f417d-5ba9-f3f9-acae-4e9c51de7d85.png)
####受信側
![受信側.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927104/127d76bd-1349-ddb6-6480-1cdf41ce0252.png)
![IMG_2038.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927104/3d8e0e65-2393-0111-ceeb-ce2136f061fb.jpeg)

#結果はどうだった
micro:bit V1とV2でそれぞれやってみたところ、LEDが点灯しなくなるまでに通過した柵の本数はV1が45本、V2が43本でした。柵の間隔が２ｍなので、大体90mということになります。個体差もあり、測定も適当すぎるので、差は無視して同じと考えて良さそうです。
V2はアンテナが改良されたらしいのですが、特に違いは感じませんでした。

予想外に飛んでいる感じなのですが、他の方のデータでは半分以下という報告もあり、この場所特有の結果の可能性もあります。川の両側に建物や護岸があり、反射波の影響も考えられますので、広大な公園の方で再度挑戦してみたいと思います。
WordPressブログ 構築備忘録（Amazon Lightsail使用）

# なぜWordPressでブログを書くのか
[ソフトウェア開発者の人生マニュアル](https://www.amazon.co.jp/dp/B01GDS0994/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)という本に影響されてWordPressブログを開設しました。

>開設したブログのURL
>[中堅独立系SIerで成長したい人のブログ](https://tekpro.work)
>https://tekpro.work

WordPressブログで投稿を続けることで、大まかに以下のメリットがあると考えています。

* 意見を発信することで自分をアピールできる
* 学習や実体験のアウトプットの場になる
* アフィリエイトで稼げるようになれば、いざ会社勤めができなくなった時の副収入になりえる

WordPressブログは完全無料ではなく、サーバや独自ドメインの維持費が別途かかります。

しかし、無料サービスのブログはサービス提供者からサーバやドメインを借りている状態のため、いざサービス終了でもすれば共倒れになるといった難点があるのに対し、`WordPressはブログ記事が自分の資産となる`点で勝ります。言うなれば一国一城の主として独立できるといった感覚です。

また、検索上位に来るサイトの多くがWordPressを利用している事に気づき、SEO対策によって`どうすれば検索上位に食い込めるか考えて実践する体験をしたい`と思ったことも、WordPressを選んだ理由です。

この記事もWordPressに書いても良かったのですが、今のところそちらでは私の実体験を元にしたライフハックを中心に発信したいと考えているため、技術的なことはQiitaに書こうと考えました。

# WordPressブログ構築の手順
## Amazon Lightsail環境でWordPressブログを構築

以下の記事を元にAmazon LightsailにWordPressを導入しました。
書籍や解説サイトでは他のサーバが薦められていましたが、それより安くて過去に使ったこともあるためAmazon Lightsailを選びました。
Lightsailの場合CPU使用率が上がると遅延が発生するため、もしアクセス数が増えた場合はサーバを変えるかもしれません。

[【初心者】AWSのlightsailでWordPressを導入するまで](https://qiita.com/tomokei5634/items/9719731e355ad5299fc2)

## 独自ドメイン化・SSL化

独自ドメインは過去の経験を元に[お名前.com](https://navi.onamae.com/)で取得し、Lightsailで取得したIPアドレスとDNSレコードで紐付けました。
SSL化は以下の記事を参考にLet's Encryptで無料で実現しました。

[無料でBITNAMIのwordpressをSSL化](https://qiita.com/_y_s_k_w/items/29f8cd34ac49bd65dfe9)

## テーマ・ウィジェット・プラグイン導入

以下の記事や書籍を元に、ブログの見た目を変える`テーマ`・サイドバーの内容を組み変える`ウィジェット`・SEO対策やセキュリティを向上させたり記事を装飾させたりする`プラグイン`を導入しました。

[WordPressとは│集客できるブログの作り方まとめ](https://bazubu.com/category/wordpress)
[Webエンジニアがやさしく教える WordPressの入門書【ブログ編】](https://www.amazon.co.jp/dp/B08LRMGR9D/ref=cm_sw_r_tw_dp_x_YyW3FbNZ9D687 )

テーマは普通のブログっぽいという理由で[Amphibious](https://ja.wordpress.org/themes/amphibious/)を使用しています。こちらはデフォルトでは英字が全て大文字になってしまうため、自力でCSSを編集して解消しています。
よりSEO対策に向いている有料テーマもあるようなので、今後変更するかもしれません。

## Google Search Console・Google Analytics連携
以下の書籍によると、Google検索で引っかかるようになるインデックス登録のためにGoogle Search Consoleが必要なようであるため連携しました。また、どのようなワードで検索されたかも分かるようになります。

[ブログで絶対に失敗しない10ステップ](https://www.amazon.co.jp/dp/B08LBDSMG5/ref=cm_sw_r_tw_dp_x_iMW3Fb12QBNTZ)

また、Google Analyticsを併用すればユーザがサイトに訪問した後の行動分析も可能になるため、そちらも連携しました。
連携方法についてググると昔の記事も出てきますが、今はUIなどが変わっているため結構苦戦しました。

連携方法 参考サイト：
[WordPressブログとサーチコンソールを連携！設定・活用方法をわかりやすく解説](https://www.xserver.ne.jp/blog/setting-search-console/)
[【初心者向け】ブログへのGoogleアナリティクス初期設定・設置方法を詳しく紹介](https://www.xserver.ne.jp/blog/google-analytics-setting/)
[【2020年10月更新】グーグルアナリティクスの設置・初期設定方法！【最新】](https://hitodeblog.com/analytics-first)

## 記事を書く
適当にプラグインを入れた段階で自分なりに記事投稿していますが、今のところTwitter共有したリンクからしかアクセスが無いようです。

とりあえず前述した書籍やサイト、周囲からのアドバイス、他のブログのやり方を元に、どうすれば検索にかかるかを考えながら投稿していこうと思います。
大事なこととしては、`1つのキーワードで1記事を作ること`、`タイトルや見出し(hタグの文字列)にキーワードを入れる`ことなどが挙げられるようです。

# 最後に
過去にはてなブログで記事投稿していたこともありますが、そちらでは意図せず検索にかかることがあったのに対し、WordPressはきっちりSEO対策をして読まれる記事を書く必要があるというギャップを感じています。
アクセス数が稼げないまま投稿を続けるのは根気が要りますが、SEO対策の成果が出るのは数ヶ月後という話もあるため、諦めずにやって行こうと思います。
「hello, world」と表示されるだけのなんちゃってOS（ブートセクタ）を作ってみた。4/5時限目

おりょうの寺子屋、教師兼生徒を務めますわたくし、
おりょうが、本日は出張授業ですよ～　なんちゃって。

#はじめに

[HTC Advent Calendar 2020](https://qiita.com/advent-calendar/2020/htc)の22日目を担当します。
ONEJAPAN HACKATHONに参加したチームHTCのメンバー、おりょうです。

今回は私が絶賛挑戦中のOS作成の一部分を切り取ってご紹介しようかなと思います。
OSってみんな知ってるけどいざ作るとなるとなんだかハードルが高く感じますよね？
でも実際ちょっと興味ありません？
少なくともここまでの前説を読んでくれているあなたは、
少なからずOSに興味があるから見に来てくれているのでしょう。

そんなあなただけに今回は！
めちゃくちゃ簡単な「なんちゃってOS（ブートセクタ編）」をご紹介いたします。
合計3回に分けて紹介する予定です。

早速見ていきましょう！

##概要
成果物：OS(フロッピーディスクで、フォーマットはFAT12）
アセンブラ：[NASK](http://hrb.osask.jp/wiki/?tools/nask)
想定対象読者：OS自作をこれから始めようとしている人。

##シラバス
[1時限目：アセンブリ言語でソースコードを書こう①（ORG命令～entryラベルまで）](https://qiita.com/meijisinger531/items/1c4cc1c3d8ce4443a106)
[2時限目：アセンブリ言語でソースコードを書こう②（putloopラベル）](https://qiita.com/meijisinger531/items/b6b1cafd8d7b95855242)
[3時限目：アセンブリ言語でソースコードを書こう③（finラベル～msgラベルまで）](https://qiita.com/meijisinger531/items/7205a07d410a33991eee)
4時限目：出来たソースコードを機械語にアセンブルしてみよう。←今日はここ！
5時限目：PC/ATエミュレータを使ってOSを起動させてみよう。

#4時限目：出来たソースコードを機械語にアセンブルしてみよう。

今回は、前回までの計3回の講義?で作成したソースコードをアセンブルしてみようという記事です。

なので、まだ過去3回分の記事を読んでいない方は先にそちらをご覧ください！
最悪ソースコードだけコピペしてくるだけでもいいですよ笑
では、ソースコードを準備できた方は次に進みますよ～～

###アセンブラについてちょっとお勉強してみよう。

さて、ソースコードをアセンブルする前に、
今回使用するアセンブラ含め、アセンブラの概要について少し見ておきましょう。
色々ありますので、ご自身のお好きなアセンブラを使ってみてください。
※アセンブラによって文法が異なりますので、どのアセンブラを使うか決めてからソースコードを書くようにしましょう。
ソースコードよりもまず先にこの記事を書くべきでしたねー。完全に順番ミスです笑

まずはじめに、アセンブラの概要から、今回使用するアセンブラの紹介まで一気に行きます。

####アセンブラの概要
アセンブラとは何なのかは、以下のサイトを少し読んでみてもらえれば理解できると思います。
[【5分で覚えるIT基礎の基礎】だれでも一度はアセンブラを学んでおこう！　第1回 | 日経クロステック（xTECH）](https://xtech.nikkei.com/it/members/ITPro/ITBASIC/20021218/1/)

####アセンブラの種類
アセンブラにはいくつか種類があります。上記記事では「CASL II」が紹介されていましたね。
今回私が使用したアセンブラは「~~[NASK](http://hrb.osask.jp/wiki/?tools/nask)~~」というものです。

これは、フリーソフトで有名なNASMによく似た文法で、でもNASMよりも自動最適化能力に長けたアセンブラです。
過去3回の記事で解説してきたソースコードもこのアセンブラを使用する前提で書かれたソースコードですので、
特にこだわりが無ければNASKをご使用いただくことをお勧めします。

####追記
NASKの配布形体の見直しが行われ、基本、一般公開は打ち切りとなりました。
同様のアセンブラを見つけましたので、そちらをお使いください。
[OSASK計画 - ダウンロード](http://wiki.osask.jp/d/download/index.html)

###アセンブルしてみよう
まあ、大々的にタイトルを用意してみたものの、
C言語とかでコンパイルしたことがある人はわかると思うのですが、
アセンブラを自身の環境に用意した後は、ただソースコードをアセンブラに読ませて機械語に翻訳させるだけなんですよね。

なので、アセンブラが用意できた方はもう後は用意したアセンブラの仕様に合わせてアセンブルしてみてください。
そしたら「.img」のディスクイメージファイルが作成されると思います。
このファイルが作成出来たら今回は無事目標達成です。

次回はこのファイルを使って、実際にOSとして起動させてみることにします。
実際にフロッピーディスクを用意してもいいんですが、コストの関係上、
今回はPC/ATエミュレーターを使用することにします。

では今回はここまで！
CSS 色

#はじめに
CSSの色関連の備忘録。

##色の指定方法
CSSの色の指定は下記の指定の方法がある。

・16進数
・キーワード
・rgb()、rgba()
・hsl()、hsla()

###16進数での色指定。

RGBの各値を16進数で指定する方法。

####RGBとは?
光の三原色である赤、緑、青の組み合わせ。

例)

```
/* 赤色 */
#ff0000

/* 黄緑 */
#00FF00

/* 青 */
#0000FF

```

RGBの各値を示す2桁ずつが同じ数字の繰り返しの場合、重複する1桁を省略して、3桁で表現できる。

例)

```
/* 赤色 */
#f00

/* 黄緑 */
#0F0

/* 青 */
#00F

```

###キーワード
英語の色の名前で指定することも可能。

基本色＋拡張カラーキーワードがあり、150色以上の色が指定可能。
16進数の対応表が調べればでるので使う場合は、参照すること。


例)

/* 白 */
white

/* 黒 */
black

###rgb(), rgba()
rgb()という関数形式の指定方法を使用するとRGBの値を10進数で指定可能。
引数には左から赤のR、緑のG、青のBの値が指定可能。

rgb(R,G,B)

255を100%とする％値で指定も可能。

#####指定できる値の範囲
10進数で0～255、
％値で0%～100%


例)

```
/* 赤 */
rgb(255,0,0)
rgb(100%,0,0)

/* 黄緑 */
rgb(0,255,0)
rgb(0,100%,0)

/* 青 */
rgb(0,0,255)
rgb(0,0,100%)

```

rgba()はRGBの値に加えてAlpha(不透明度のこと)の値を指定できる。
不透明度は0.0～1.0の範囲の数値で指定できる。(整数でも少数でも可能)

0.0で完全透明
1.0で完全不透明


例)

```
/* 赤の半透明 */
rgba(255,0,0,0.5)
```

###hsl(),hsla()

hslは以下の略。
hue(色相)
saturation(彩度)
lightness(明度)

色相、彩度、明度の順で指定する。

彩度と明度は0%から100%のパーセント値で指定する。

色相は色相環(カラーサークル)の角度を示す数値(単位なし)で指定する。

[参考](https://amidagamine.com/notes/wp-content/uploads/2015/07/20150718a.png)

例)

```
/* 赤 */
hsl(0,100%,50%)
```

hsla()は、rgba()と同じくAlpha(不透明度)の値を指定できる。
0.0～1.0の範囲で不透明度の指定が可能。

例)

```
/* 半透明の赤 */
hsla(0,100%,50%,0.5)
```
Go言語でモジュールを作成し、GoDocを使ってドキュメントを作成する

# はじめに
[Go言語についてと開発環境の準備](https://qiita.com/nekoharuyuki/items/d416eb974b6a175bb1cb) でGo言語についてと開発環境の方法を学びました。

Go言語でモジュールを作成し、GoDocを使ってドキュメントを作成する方法について備忘録としてまとめました。

## GoDocとは
GoDocはルールに沿ってソースコードにコメントを記述することで、パブリックな関数、type、変数についての説明や実装例をドキュメントとしてホストしているウェブサイトにまとめてくれます。また、コマンドライン上でもドキュメントを閲覧することが出来ます。

https://godoc.org/

### 参考にしたGo言語学習本

* [基礎からわかる Go言語](https://amzn.to/39O3rFI)
* [スターティングGo言語](https://amzn.to/39L5Sc3)
* [Go言語によるWebアプリケーション開発](https://amzn.to/2VHwm5M)
* [Goプログラミング実践入門　標準ライブラリでゼロからWebアプリを作る](https://amzn.to/37AfX8W)

### 参考サイト
https://godoc.org/golang.org/x/tools/cmd/godoc
https://blog.golang.org/examples

# 事前準備
[Go言語についてと開発環境の準備](https://qiita.com/nekoharuyuki/items/d416eb974b6a175bb1cb) を読んでGo言語の開発環境を準備します。

go getでGoDocのパッケージをインストールします。

```
$ go get golang.org/x/tools/cmd/godoc
```

# テスト実装
Package stringutil をサンプルに実際にドキュメントを作成してみました。

**サンプルコード**
https://github.com/golang/example
https://pkg.go.dev/github.com/golang/example/stringutil/

```
package stringutil_test

import (
    "fmt"

    "github.com/golang/example/stringutil"
)

func ExampleReverse() {
    fmt.Println(stringutil.Reverse("hello"))
    // Output: olleh
}
```

関数コメントや ExampleReverse で使用例を example_test.go に記述し、テストを実行します。

```
$ go test -v
=== RUN TestReverse
--- PASS: TestReverse (0.00s)
=== RUN: ExampleReverse
--- PASS: ExampleReverse (0.00s)
PASS
ok  	github.com/golang/example/stringutil	0.009s
```

ドキュメントをWebページとして表示します。

```
$ godoc -http =：6060
```

![reverse.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229633/50076bf2-ab14-25ca-262b-84ddf8f25af3.png)
youtube-dlをソースから .exe にビルドする方法

長い間放置されているPRを取り込みたかったので自分で .exe にビルドすることにした。

## 必要なもの

 - Windows
 - Python（[インストール方法](https://www.python.jp/install/windows/index.html)）
 - Git（[インストール方法](https://qiita.com/nakazawaken1/items/bbcb4640cf9aceee5745)）

## 手順

GitHubからソースコードをクローン

```shell
git clone https://github.com/ytdl-org/youtube-dl.git
cd youtube-dl/
```

ソースをいじる（内容は割愛）

PyInstallerを使って .exe ファイル化

```shell
# インストール
pip install pyinstaller

# ビルド
pyinstaller youtube_dl/__main__.py --onefile --name youtube-dl
```

ビルドされた .exe は`dist`フォルダ配下にあるので、あとはいつも通り使う。

## 一言

WindowsにPythonインストールしたくなかったので、WSLでビルドしたら動かなかった...

```
However, it is not a cross-compiler: to make a Windows app you run PyInstaller in Windows
```

## 参考

 - [GitHub - pyinstaller/pyinstaller: Freeze (package) Python programs into stand-alone executables](https://github.com/pyinstaller/pyinstaller)
 - [GitHub - ytdl-org/youtube-dl: Command-line program to download videos from YouTube.com and other video sites](https://github.com/ytdl-org/youtube-dl/)
 - [build youtube-dl · GitHub<](https://gist.github.com/pypy-vrc/a2ec2c870e8974e5d8d95850a304cf6d)
CORSエラーの原因がPHPの設定変更だった

自作アプリを作成している際に発生した fetch による CORS エラーの原因が、
単なる PHP 設定変更だったというお話です。

# 内容
React から fetch による PHP へのデータ送信処理を実行したところ、
CORSエラーが発生しました。

```
Access to fetch at 'http://localhost/hoge.php' from origin 
'http://localhost:3000' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
If an opaque response serves your needs, set the request's mode to 
'no-cors' to fetch the resource with CORS disabled.
```

React の fetch 処理は下記の通り。

```
const response = await fetch(
    "http://localhost/hoge.php",
    {
       method: "POST",
       body: JSON.stringify(values),
    }
);
```

最初は
「header("Access-Control-Allow-Origin: *")　つけ忘れかな？」
と思ったけど、PHP 側のファイルを見たら記述されていました。

PHP 側の header 部分：

```
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: Content-Disposition, Content-Type, Content-Length, Accept-Encoding");
header("Content-type:application/json");
```

「ちゃんと記述しているのになんでCORSエラーが出るんだ😡」
と思って、試しにデータ送信先を「存在しないファイル」である hoge2.php に変更したところ同じエラーが発生。

```
Access to fetch at 'http://localhost/hoge2.php' from origin 
'http://localhost:3000' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
If an opaque response serves your needs, set the request's mode to 
'no-cors' to fetch the resource with CORS disabled.
```

ここで
「もしかしてファイルが読み込めてないとか？PHPの設定が問題？」
と思い調査。

・localhost で It works! が表示されるかチェック
　問題なし。

・phpmyadmin が繋がるかどうか
　403 error で繋がらない

「あれ、昨日まで phpmyadmin に繋がっていたのに・・・🤔 phpmyadmin.confの設定がおかしい？」

ここで /etc/apache2/other/phpmyadmin.conf を閲覧したところ、
phpmyadmin.conf に記述していた下記内容が消えていました。

```
<Location /phpmyadmin>                                                                              
    Order deny,allow                                                                                
    Deny from all                                                                                   
    Allow from localhost                                                                            
</Location>  
```

さらに /etc/apache2/httpd.conf でも、有効にしていたはずの
LoadModule php7_module 
がコメントアウトされていました。

これらを元に戻したところ、無事 CORS エラーが発生しなくなりました。

# 原因

原因はおそらく MacOS のアップデート（v10 から v11）ではないかと思ってます。
設定が勝手に変更されるような事で思い当たるのがそれくらいなので・・・。
CakePHP3超初心者のためのモデル周り

## はじめに
CakePHP3を学び始めたとき、
「MVCとはアプリの基本的な機能を3つに分けて設計する考え方」
と学んでも、実際実装するとなるとにどう書けばいいのかわかりませんでした。
なんでもかんでもコントローラーに書いちゃうのを卒業したい一心で色々と試してみて、
最近ようやくCakePHPのModel（例： UsersTable.phpとかUser.php）の使い方がざっくりと分かり始めてきたので、自分の頭の整理も兼ねて記事にしました。
未熟なところや誤りがありましたら、教えて頂けるととっても助かります！

## 対象
 - ファットコントローラが良くないのはわかっているけど、どうしたらいいのかわからない方
 - Modelがテーブルとエンティティに分かれている意味がわからない方
 - そもそもMVCもよくわかんないって方

## MVCとは？
掌田津耶乃さんの『CakePHP超入門』によると、MVCとは
> アプリケーションの基本的な機能を3つに整理して設計する考え方です。
> Model(モデル)：データの管理を担当します。データベースにアクセスをしたりします。
> View（ビュー）：画面表示を担当します。
> Controller（コントローラー）：プログラム全体の制御を担当します。

とのことです。
3つの機能に分けることで、複数人でも開発がしやすかったり、エラー等の影響を小さくすることができるなどのメリットがあります。

## Modelで何ができるのか？
Modelをざっくりといえばデータベース関係担当です。
じゃあデータ関係はModelに任せていいんだな〜とModelディレクトリを見てみると、

    App\Model
       |ー Table
       |ー Entity

と分かれています。
このTableとEntity分かれているところが、まず1つ目の「( ˘ω˘ )？」となる箇所だと思います。

### TableとEntityの違いとは？
リファレンスでは、
#### テーブルクラス
> テーブルオブジェクトは特定のテーブルに保存されたエンティティーのコレクションへのアクセスを提供します。

#### エンティティークラス
> エンティティーは個々の行やドメインオブジェクトを表します。エンティティーは保持するデータにアクセスして 操作するための永続的なプロパティーとメソッドを保有しています。

と説明されています。はて？( ˘ω˘ )という感じですが、

- テーブルクラスはDBのあるテーブルに保存されたレコードをオブジェクトとして扱いたい時に使うクラス
- エンティティークラスは１行の単体のデータをオブジェクトとしていじったりしたい時に使うクラス

とざっくりとした認識でひとまずは問題ないかと思います。

### src/Model/Tableでできること
条件を指定して、テーブルに保存されたレコードを検索したい時などに使います。
例えば、usersテーブルに保存されているデータで、論理削除されていないレコード(`is_deleted = false`)を全部引っ張ってくるメソッドを作成してみます。

~~~php
// src/Model/Table/UsersTable.php 内で
class UsersTable extends Table {
    // 中略
    public function findIsNotDeleted() {
        $isNotDeleted = $this->find()->where(['is_deleted' => false])->toList();
        return $isNotDeleted;
    }
}
~~~
これを、コントローラー側で

~~~php
$isNotDeleted = $this->Users->findIsNotDeleted();
~~~
と呼び出すことで、論理削除されていないUsersテーブルのレコードを全て取得することができます。
モデルに書かずに、コントローラーで`$this->Users->find()->where(略);`とすることもできますが、

 - ファットコントローラーを避けたい
 - 同じコードが何度も出てくる

場合、モデルのテーブルクラスに書くとすっきりしておすすめです。

### src/Model/Entityでできること
DBに保存された、ある特定のレコードの値を更新したいときなどに使います。
例えば、ログインユーザーがそのアカウントを削除したいとき、そのユーザーの削除フラグを立てるメソッドを作成してみます。

~~~php
// src/Model/Entity/User.php 内で
class User extends Entity {
    // 中略
    public function setIsDeleted() {
        return $this->is_deleted = true;
    }
}
~~~
これを、例えばコントローラーで

~~~php
// ログインユーザーのUserオブジェクトを取得し、プロパティの値を書き換える
$user = $this->Users->get($user_id);
$user->is_deleted = $user->setIsDeleted();
$this->Users->save($user);
~~~
とsaveすることで、すでにDBのusersテーブルに保存されているレコードの一部を書き換えて保存することができます。


これらの応用で、テーブルクラスとエンティティクラスを組み合わせて
取得したテーブルオブジェクトの値を全て書き換えることができたりと便利なので、試してみてください。



## 参照

[データベースアクセス & ORM](https://book.cakephp.org/3/ja/orm.html)
チーム開発でフロントとサーバーの開発効率が上がるかもしれないやつ作ってみた

この記事は[Fringe81 Advent Calendar](https://qiita.com/advent-calendar/2020/fringe81)20日目の記事です。
19日目を担当した[tenajimaさんの記事](https://zenn.dev/tenajima/articles/f81_advent_calendar) からのバトンをつなぎます!

# はじめに
皆さんはチームで一つの機能をサーバーフロントで並行して開発する時、サーバーフロントのI/Fをどのように決めていますか？
僕が所属しているチームではまずapiドキュメントを作成して、それを元に開発を進めています。
そうすると、サーバーサイドが完成しないとフロントはmockとか作って動作確認をすることになります。また、サーバーができてもレスポンスがミスってたりすると修正が必要になったりと結構効率が悪い部分がありました。これはどうにか改善したい。

# 解決するぞ
基本的にapiドキュメントのレスポンスの例を使用して開発を進めているので、そいつを元にレスポンスを返してくれるmockサーバー的なやつ、またサーバーが返してきたレスポンスのjsonのkeyがそのドキュメントの例のkeyとあっているかをチェックしてくれるやつを作れば手戻りとかなく結合がスムーズにできそう。

# 作ってみた
そういうわけなので、作ってみました。その名もresp-man(post-manをパクったわけでは絶対にない)。[こちら](https://github.com/gal1996/resp-man)。一応汎用的に作っているので、もし使いたい人がいたら使ってみてください。

# 何ができるか
できることは二つです。

1. response.jsonに記述したjsonをそのままレスポンスとして返す。 `/return_response` をフロントのリクエスト先として登録すればmockサーバー的にデータを返してくれる。
2. サーバー側が作ったjsonを `/check_response` に投げると、response.jsonにあるjsonのkeyと完全に一致しているか見れくれる。

詳しい使い方はREADMEに書いてあるのでそちらをみていただけたらと思います。mm

# 一応、プログラムも
内部の技術的なこともちょっと書いておきます。
golangで実装しているのですが、golangでjsonを扱う時は、基本的に構造体を用意して `json.Umarshal` とかをやると思います。ただ、今回は不特定な形のjsonに対応する必要があり、構造体を予め用意して展開するのは難しそう。最初はjsonのstringから構造体を生成する方法とかないのかなーと思って調べたのですが、見つけられず…ということで、そのまま `[]byte` のまま扱うことにしました。
そうすると、response.jsonをバイト列で読み込んでそのまままるっとレスポンスにしてしまえば良いので、1の機能はさくっと完成。
2の機能に関しては、jsonのkeyをリクエストのbodyとresponse.jsonから抜き出せればいいので以下の関数を実装しました

```go
func extractJsonKeys(rowJson io.Reader) []string {
	jsonKeys := make([]string, 0, 30)
	scanner := bufio.NewScanner(rowJson)
	for scanner.Scan() {
		text := scanner.Text()
		if strings.Contains(text, ":") {
			// 基本的にjsonは 'key: value' の形なので、':'の前がキーになる
			jsonKey := strings.TrimSpace(strings.Replace((strings.Split(text, ":"))[0], "\"", "", -1))
			jsonKeys = append(jsonKeys, jsonKey)
		}
	}

	return jsonKeys
}
```
jsonを1行ずつ読み込んで、`:` のある行を`:`で前後に分割し、前の方をkeyとしています。
response.jsonを読み込んだファイルポインタの `*os.file` とリクエストのbodyの `io.ReadCloser` はどちらも、`io.Reader` を実装しているので、それを引数に取っていい感じに一つの関数にまとめられました。

# 課題
上のプログラムを読むとわかりますが、curlとかで叩く時に、jsonが改行されてないとうまくjsonを読み込めません。ここは改善の余地がありそうです。
また、そもそもresponse.jsonに書いてあるレスポンスのjsonの形式が間違っているとエラーになってしまうのですが、それを検知する仕組みがないのでそこも改善できたらいいかなと思っています。（byteで扱っているのでちょっと大変そう）
別の視点で、使うのに関して今は1種類のレスポンスしか扱えないので複数扱えるようになるといいなーと思っております。（ポート番号変えて複数サーバー立ち上げればいけますが、使い勝手がいいとは言えない…）
と、諸々まだ改善点がありますが、使ってもらってフィードバックもらいながら改善していきたいなーと思っております。


ということで、今回はチーム開発の効率をちょっとだけよくできるかもしれないツールを作ったので、それについて書いてみました！
明日は、[gion](https://qiita.com/gion) さんの記事になります！
機械学習の実装の勉強の記録③（minicondaによる環境構築手順）

#目次
- はじめに
- Minicondaを使用して環境を準備する

#1. はじめに
##1.1 Anacondaが大規模な商用プロジェクトの場合には有償化
一部の商用利用者によるパッケージリポジトリへのダウンロードリクエストによるサーバーへの負荷が大きいため、
大規模な商用プロジェクト利用の場合は有償化したとのこと。
https://qiita.com/tfukumori/items/f8fc2c53077b234384fc

##1.2 Anacondaにtensorflowがインストールできない問題にはまる
何度かAnacondaでtensorflowの環境を準備していたので、何も問題なくいくだろうと作業していたらハマった。

Packageの解決に時間がかかりすぎることで、インストールできない状態にはまった。
解決してはいないが、調べる中でどうやらpipとcondaを併用したことが理由の様。
併用すると環境が破壊される。
http://onoz000.hatenablog.com/entry/2018/02/11/142347

#2. Minicondaを使用して環境を準備する
##Minicondaとは
MinicondaはAnacondaの縮小版のようなPythonディストリビューション
https://dev.classmethod.jp/articles/difference-between-anaconda-and-miniconda/

##2.1 インストール
Windows 10 64bit環境へ、以下のリンク先の以下のモジュールをダウンロードして、
インストールした。
https://docs.conda.io/en/latest/miniconda.html

| Python version | Name | Size | SHA256 hash|
|:-----------------:|:------------------:|:------------------:|:------------------:|
|Python 3.8|Miniconda3 Windows 64-bit|57.0 MiB|4fa22bba0497babb5b6608cb8843545372a99f5331c8120099ae1d803f627c61|

##2.2 Anaconda Prompt(Miniconda3)
コンソールはAnaconda Prompt(Miniconda3)を使用。
ここからはcondaコマンドを使用してCUIで環境を構築する。

##2.3 condaコマンドの使い方
https://qiita.com/naz_/items/84634fbd134fbcd25296
https://qiita.com/yakisobamilk/items/867dce8e53824146ce05

##2.4 手順
```
1. 環境の更新（ログを見てjupyter notebookが入っているか確認しておくとよい）
conda update conda

2. 仮想環境py3k(名前は何でもよい)を作成する
conda create -n py3k python=3.6

3. 作られた環境を確認する。-eは今ある環境を確認。
conda info -e

4. py3kに入る
conda activate py3k

5. tensorflowのインストール
conda install tensorflow

6. 環境にjupyter notebookが入っているか確認。-aは全ての情報を確認
conda info -a

7. jupyter notebookで使用するkernelに今作った環境を指定する。
ipython kernel install -user --name py3k

8.jupyter notebookを起動
今までadminで操作していた人は、このコマンドは通常ユーザーで実行したほうがよさそう。
何故ならjupyter notebookの起動rootがadmin領域になってしまうので。
jupyter notebook
なお、バインドするポートを変えたければ以下のように打てば簡単に変えられる。
jupyter notebook --port 9999

9. ブラウザで表示されたjupyter notebookのkernerlを変更
多分デフォルトだとlocalhostの8888でjupyter notebookのページが開く。
メニューバーの[カーネル]-[カーネルの変更]-py3kを選択する。

10. 適当にこのあたりのコードをjupyter notebookで動かしてみる。
（注意）TensorFlowは2.0以降APIが変わっている。適当にコードをコピってくると、API差分にはまってデバッグに時間がかかるので、公式チュートリアルなどから取ってきたほうがスムーズかも。
https://www.tensorflow.org/tutorials/keras/classification?hl=ja

```
機械学習の実装の勉強の記録②（環境準備）

#はじめに
自分を含め、機械学習をはじめる人のために、環境についてまとめる。
今後勉強が進むにつれて少しずつ情報を加えていきたいと思う。


#環境
##Jupyter Notebook環境
実行ができるブラウザから使用するエディタ。
おそらく機械学習のデファクトスタンダードだと思われる。


##Google Colaboratory
Googleが用意しているラボ環境。
ブラウザ経由でJupyter Notebook環境がすぐに利用できるため、
ちょっと触ってみたい人や、マシンリソースを用意できない人向けの環境。

https://gammasoft.jp/blog/google-colaboratory-for-learning/

## Anaconda
自分自身で環境を構築するならAnacondaのインストールが一番早い。
Anacondaをインストールするだけで、
Jupyter Notebook環境やPythonのライブラリなど一式がまるまる準備できる。
https://www.anaconda.com/products/individual#

## Miniconda
Anacondaの最小パッケージのようなものとして、
Minicondaというものもある。
これについては、少し触ってみたので、別途記事にする。
WEBアプリケーションエンジニアがぶつかる「プログラミングお作法」という壁

　なんか、最近やたら「妥当」という言葉を連呼連発しているうちに、この言葉なしには生きられない体になってしまった。それと同時に「エンジニアの熟練度」について、プロジェクトマネージャーやプロダクトマネージャー的な観点で、知ってる人は知ってるような観点を最近よく思うのでそちらについてちょっとまとめてみる。

# 目次

* 拡大期の会社には割とよくある話
* ユーザーが目に見える「機能」開発
* そして調子に乗る
* そして転ぶ（人もいればそうでない人もいる）
* つまんないプログラミングのお作法
* 「信頼感を持って仕事を任される」＝「ちゃんとお金を稼げる」
* みんな、礼儀正しく、ね。

## おはなし。

## 拡大期の会社には割とよくある話
　ユーザー側を延々やり続けて、ちょっと調子に乗ったWEBアプリケーションエンジニアがある時、開発案件の属性が突然変わってしまい混乱するなんて話は、フェーズが移り変わる拡大期の会社には割とよくある話なんじゃないだろうかと思った。

というか、近々で間近で起きた話である。
（「私の知り合いの話なんだけどね」という流れで始まる話は、大抵が自分の暴露話であると、そういえば高校時代の現国の先生が言っていたな）

## ユーザーが目に見える「機能」開発
　至極当たり前の話であるが、アプリ開発はユーザーが目に見える「機能」を作るところから始まる。チャットメッセージを送るだの、ファイルをアップするだの、情報を編集するだの、まあ色々。

　プログラムを変更すればそのまま画面上に反映される機能は、「正しい動作」かどうか、目の前で起きる事象として目で見てわかるので、品質を保証しやすいという特性をもつ。（前提の構造の複雑性は今は一旦おいておく）

　この畑は、若い新人のエンジニアとしては手応えを感じやすく、人気のある領域なのだと認識している。属に「フロントエンドエンジニア」のほうが若くてキラキラしてるっぽい雰囲気を醸すのは、参加する人の属性によるものな気がする。

## そして調子に乗る
　さて、そんな領域で3～4年もやっていると、一通り言語の習得や上手なコードの記述方法にも慣れて「俺ってこのあたりの言語の開発はだいたいできるようになったな」みたいに調子に乗り始める。そこで多くのエンジニアは「じゃあいっちょ次はコッチの言語かな」とか「AWSやインフラ周りでも触ってみるか」と新しい領域にチャレンジしてみたくなったりするわけ。

## そして転ぶ（人もいればそうでない人もいる）
そんなエンジニアがふとした拍子に「サービスのスケール」に出くわす。途端にどうだろうか。

「あれ、100万レコード入ったら動かなくなったぞ…」

「あれれ、なんだろう、たまに自動処理がしくじってるな…」

「あれれれ、WEBAPIの全件更新で件数が合わない…」

「サービス規模がでかい」という状態になった途端に、処理の中身がブラックボックス化し、「正体不明の不具合」にさらされ、為す術なく沈んでいくことになる。そしてそういうときに大事なのが、実はつまんないお作法なのだ。

つまんないプログラミングのお作法
「自動処理はいちいちログ吐いとこう」

「変数の定義はマメに、データ型も指定しとかんとね」

「DBのコネクションはいちいち接続して、いちいち閉じる」

など、など。小うるさくレビューで言われたりするやつである。実際のところ、ちっちゃい規模の機能開発レベルでは違いなんてほとんど（むしろ全く）現れない。

　しかし、サービスが大きかろうが、小さかろうが、「ちゃんと常に動くものを上げてくる」ビジネス上で信頼感を持って仕事を任される熟練エンジニアはこの辺がきっちりできているのだ。売れる営業が、スーツの着こなしをビシッとしているのと同じだろうか（自分は営業じゃないのでそのへんは知らないけど）。

「信頼感を持って仕事を任される」＝「ちゃんとお金を稼げる」
　そしてビジネス上で「信頼感を持って仕事を任される」というのは言い換えると「ちゃんとお金を稼げる」というふうに言い換えることができると思っていて、「若手でガリガリ書けますよ！」というエンジニアじゃなくて、「コツコツやってきました」というエンジニアに自分が魅力を感じる理由になっている気がする。

　プロジェクトマネージャーとしては、納期的に手戻りになるのがホント恐ろしい。ましてや「できました！」なんて言っておきながら「結局修正に倍の時間かかりました」なんてのは、経験が浅いエンジニアの開発にはざらにある。手戻りどころか倍の工数である。

## ちなみにどの辺で転びやすいか

わざわざnoteからQiitaに転載したのであれば、さすがに味付けは必要だろうということでここ追記。

### 件数が多い時に転ぶ
まあわかりやすく負荷で死ぬと思っていただければ。単発の負荷が上がりすぎて死ぬこともあるし、思ってたよりも全然ユーザー数が多いとかで死ぬこともあります。もしくは更にその掛け算。まあ確かに、機能開発する時わざわざ毎回「100万回回してみた」とかするわけでも無いですが、習慣化されているとなんとなく回避行動されているものです。

### 継続性で転ぶ
恐ろしい話ではありますが、「24時間365日、全く同じ時間と日にちは存在しない」というのもシステムでは実は考慮しておくべき事項だったりします。過去に私が引き起こしたバグでは、「年に一度、3月30日にだけ起こるバグ」なんてものも有りました。
「date関数とかの作り込みが甘かったせいで◯◯」
みたいなことの回避は、やはり継続的なサービス開発にあたっては必要なことです。

### 異常系で転ぶ
「データ型のバリデーションをかけてなかったせいで、intのカラムにstr入れようとした結果、特大の数値が格納されてしまった」
みたいなやつです。開発側からすると「そんなの入れないでくれよ」って思うんですが、長く運用するサービスであればあるほどそこらへんを考慮できてこそ持続可能なサービスというもの。

### 環境で転ぶ
「普段はDB設定だけど、この機能はここに格納されたファイルを参照して機能する」
なぜか昔の人のやり方への単なる右へ倣えでだけでこんなの実装してしまったりすると、「サーバーごとに同期されんやないかい」という本番環境のみで起こる謎の仕様が出来上がったりします。全体像、想像して作りましょう。


## みんな、礼儀正しく、ね。
　営業マンが身だしなみを整えて、定期接触でラポールを築いて毎月コンスタントに契約をとってくるかのように、細かなプログラミングのお作法を覚えてくれるエンジニアが、自分の観測範囲に増えてくれることを祈るばかりな今日このごろです。

（書き出しと締めが一致しているだろうか、不安だけど眠いので終わり）

おわり。
Vimチートシート

# 移動系
`w`次の単語に移動
`b`前の単語に移動
`f`マッチする文字に移動　`;`次のマッチに移動`,`で戻る
`gg`先頭の行に移動
`G`最終行に移動
`0`行の先頭へ(インデント無視して先頭へ)
`^`行の先頭へ
`$`行の末尾へ
`+`下の行の先頭へ
`-`上の行の先頭へ
`zz`カーソルの位置をウィンドウの中心に移
`z<CR>`カーソルの位置をウインドウの最上部に移動

# 削除系

`daw`単語を削除
`ciw`, `caw`単語を削除後インサートモード
`dd`行を削除
`d0`, `d$`行頭、行末までを削除
`df<文字>`カーソル位置から<文字>の位置まで削除
`C`行を削除後インサートモード
`:nd`n行目に移動して削除
`:{start},{end}d`アドレス範囲で行を削除

# 挿入系

`I`行の先頭に挿入
`i`文字の前に挿入
`A`行の最後に挿入
`a`文字の後ろに挿入
`ea`単語の末尾に挿入
`gea`前の単語の末尾に挿入
`di"`delete inside ""(di', di( など応用可能)
`ci"`""の中身を消して挿入
`ca"`""ごと消して挿入

# ビジュアルモード
`<C-v>`短径選択 `2l3j`2×3で選択
`vaw`,`viw`単語をビジュアル選択
`va"`""ごとビジュアル選択

# 検索系
`f`マッチする文字に移動　`;`次のマッチに移動　`,`で戻れる
`*`, `#`下、上方向に検索
`g*`, `g#`部分一致検索

# 補完系
`<C-p>,<C-n>`補完
`<C-d>`補完（コマンドラインモードにて）

# 置換系
`:%s/置換したい文字/置換後の文字/g`全置換

# コピー&ペースト
`:6t.`6行目を現在行の下にコピー
`:t6`現在行を6行目の下にコピー
`t.`現在行をコピー（ノーマルモードの`yyp`）
`yw`単語をヤンク

# ファイル移動系
`gf`カーソル位置に記述されているファイル名にジャンプ
`<C-w>f`画面を水平分割してジャンプ
`<C-o>`/`<C-i>`戻る/進む
`:vimgrep /hoge/ **`hogeを含むファイルを検索
`<C-]>`宣言元にジャンプ


# ディレクトリ操作
`:cd %:h`カレントディレクトリをファイルのディレクトリに変更する

# ファイルの検索
`:vim hoge **/* | cw`vimを開いた階層以下のファイルをhogeという文字列で検索

# タブ機能
`:tabnew`新規タブを作成
`gt`, `gT`次のタブ、前のタブ

# Case
## 確認しながら置換したいとき
`*`で検索
`cw`で削除してインサートモードに入り、入力
`n`で次のマッチへ(`N`で戻る)
`.`で繰り返し


# その他
## 画面分割
`:vsp {file}`, `<C-w>v`縦に分割
`<C-w>w>`フォーカスを変更
`<C-w><`現在のウィンドウの横幅を１文字分狭くする
`:clo`閉じる
`<C-w>x`分割した画面の入れ替え
`<C-w>H`, `<C-w>K`横→縦、縦→横

## バッファ関連
`:ls`バッファを表示
`:b バッファの番号`開く

## json綺麗
`:%!jq '.'`

## vim-surround
`ysiw'`''You surround inside word
`cs'"`'を"に変更Change surround' "
`ds"`Delete surround"
`S<div class="important">`Vで選択した行を<div class="important"></div>で囲む
WEBサービス開発歴約6ヶ月の私が受けたコードレビューをまとめてみた

# はじめに

WEBサービス開発に関わって約6ヶ月のにこと申します！



さて、ここで質問です。

あなたは初めてコードレビューを受けたときのことを覚えていますか？






覚えていますよね？

・・・え、覚えていない？

そしたらこの記事はもしかしたらあなたが駆け出しエンジニアのあの時の頃を思い出させてくれるかもしれません・・・。

私はコードレビューを受けた時に衝撃を受けました。

こんな書き方が出来るとは・・・。私はなんとおブスなコードをかいていたんだろうと・・・。


レビューを受けてから良いコードを書けるようにより意識をするようになりました。（実際にきちんと出来ているかどうかはまた別のお話）

そしてこのコードレビューを自分の中だけで留めておくのはもったいない！！という気持ちと振り返りのためにまとめました。

これからエンジニアになろうとしている方、私と同じくまだ実務経験が浅い方、そして初心の気持ちを思い出したい方（？）に参考になる！！はずです！！

※言語はJavaScript(Vue.js)を使用


# Boolean型を返す変数やメソッドの命名


👎Bad

```jsx
// キャンペーンが有効かどうか
function campaignToggle () {
	// 略
}
```

- どのような値が返ってくるのかわかりにくい
- 確認するのに余計な手間がかかる

👍Good

```jsx

function isCampaignActive () {
	// 略
}
```

 

👉Point
- Boolean型の変数名はその変数名を見たただけで**Boolean型であるかどうかが**わかること
- is +  形容詞　や　has + 過去分詞　が使われることが多い

>参考
[booleanメソッドの命名規則](https://qiita.com/GinGinDako/items/6e8b696c4734b8e92d2b)


# 三項演算子に書き換えよう

👎Bad

```jsx
if (imageSize) {
  return '画像の容量が大きすぎるため、保存できませんでした。'
 }
 return ''
```

👍Good

```jsx
return imageSize
  ? '画像の容量が大きすぎるため、保存できませんでした。'
  : ''
```

👉Point

- 三項演算子を適切に使用すると理解しやすくなる
- if文を簡潔に記述できる(上記例だとreturn を2回書く必要がなくなる！)

> 参考
[条件 (三項) 演算子](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_Operator)

# v-forのkeyには一意の値を使用する

👎Bad

```jsx
<list
	v-for="(campaign, index) in campaignItems"
	:key="index"
/>
```

👍Good

```jsx
<list
	v-for="(campaign, index) in campaignItems"
	:key="campaign.id"
/>
```

👉Point

- 追加や削除など並び替えが発生する場合は、indexをkeyに使うと予期せぬ不具合に繋がる
- indexではなく一意の値を使用する

> 参考
[Vue.js公式 #キー付き-v-for-必須](https://jp.vuejs.org/v2/style-guide/#%E3%82%AD%E3%83%BC%E4%BB%98%E3%81%8D-v-for-%E5%BF%85%E9%A0%88)
[Vue.js: v-forで項目インデックスをkey属性にしていいのか](https://qiita.com/FumioNonaka/items/d1d9c9335116426a8316)

# 0かどうかの判定をする時は省略して書かない


👎Bad

```jsx
<component v-if="!numOfItems" />
```

👍Good

```jsx
<component v-if="numOfItems === 0" />
```

👉Point

- 数値の判定かどうかを式を見ただけで明確にわかるようにする
- 変数名からNumber型か分からない場合、確認する手間が増えてしまうため省略せずに   `変数名 === 0` と書く


>参考
[[JavaScript] null とか undefined とか 0 とか 空文字('') とか false とかの判定について](https://qiita.com/phi/items/723aa59851b0716a87e3)

# undefinedとnullだけを弾く時の判定方法

👎Bad

```jsx
if (item !== undefined && item !== null) {
	// 略
}
```

👍Good

```jsx
if (item != null) {
	// 略
}
```

👉Point

- undefined と null だけの場合は上記のように完結に書ける
- 0 や false は弾かれない

>参考
[[JavaScript] null とか undefined とか 0 とか 空文字('') とか false とかの判定について](https://qiita.com/phi/items/723aa59851b0716a87e3)

# マジックナンバーを避けよう

👎Bad

```jsx
if ([1, 2].includes(statusId)) {
	// 略
}
```

👍Good

```jsx
// status.js
export const STATUS = Object.freeze({
  HAPPY: 1,
  SMAILE: 2,
  SAD: 3
})

// index.js
import { STATUS } from '~/status.js'

if ([STATUS.HAPPY, STATUS.SMAILE].includes(statusId)) {
	// 略
}
```

👉Point

- 番号だけでは何の判定をしているのかすぐに分からない
- 別ファイルに定数を定義することで明示的にわかりやすくする


# まとめ
こちらは今までコードレビューを受けたものの一部ですが、また今後も増やして行きたいと思います。
この中でも私の解釈が間違えていたりもっと良い方法があったり、さらにレビューがある場合は優しく！！教えてコメントいただけますと幸いです。


そしてコードレビューで指摘されまくって落ち込んでいるそこのあなた！とてもわかります！

でもそれはまだまだ伸び代があるってことなので、心の中のフワちゃんに
「いや待って！アタシ伸び代しかないじゃーん！💘まじ最高！！✨✨」
と言わせましょう！！！