OmniAICreator/Qiita-1.07M huggingface dataset:
固定翼機の保険について

Droneの飛行を行うときに保険をかけておくことが重要なことです。
ただし、アレばです。

保険会社もリスクが高いものや、マイナーな機材に関しては、個別に動産保険にかけざるを得ないということになります。
回転翼機に関しては、日本において一般の方でも購入していたり、購入したドローンに１年間の保険が付いていたりします。

固定翼機に関しては、
- 販売会社からの紹介で、動産保険にはいるという方法
- 測量業者であれば、日本測量協会の測量業共済会に加入する方法
があります。

また、開始時期に関しても、回転翼と同様な形ではないことから、確認が必要です。
飛ばしたいタイミングでWebから登録！というようなお気軽に入れるわけではないからです。

固定翼機は、大変広範囲を飛行できて写真を撮影できるメリットがあるため、防災や測量で使用されているのが現状で、なかなかハードルは高いですが、回転翼機より、インパクトは大きいので、楽しいです。

コストコでもParrot DISCOが売っていたりしていた時期はありますが、現在量販店でも購入は難しいと思います。
今後飛行に関しても規制が厳しくなりますが、レベル４飛行については固定翼機に持ってこいだと思いますので、法整備が進むことを期待しています。
Codeigniterのview in viewには引数はなくてもいい

通常、MVCモデルのフレームワークでは、viewを呼び出す際に変数を引数として渡すのが一般的で、CodeIgniterももちろんその例に漏れず、以下のように呼び出すのはCodeIgniterの初歩の初歩で通る道である。

``` app/Contorllers/Hoge.php
namespace App\Controllers;
use CodeIgniter\Controller;
class Hoge extends Controller
{
    public function index()
    {
        $data['hoge'] = 'fuga';
        return view('fuga', $data);
    }
}
```

``` app/Views/fuga.php
echo $hoge; 
// fuga
```

ここで、viewの中に更にviewを呼び出そうとすると

``` app/Views/fuga.php
echo $hoge; 
// fuga

echo view('piyo', ['hoge' => 'fuga']);
```

``` app/Views/piyo.php
echo $hoge; 
// fuga
```

とするのが一般的な方法で、引数がリスト用の配列だったりした場合はここをループで回しながら使うケースも多い。
これだけなら特筆することではないが、CodeIgniterではなんと、**引数を省略すると親viewの引数をそのまま再利用してくれる**機能がある。

## view in view に引数を省略すると親viewの引数を引き継げる

``` app/Views/fuga.php
echo $hoge; 
// fuga

// 引数を指定しない
echo view('piyo');
```

``` app/Views/piyo.php
echo $hoge; 
// fuga（親viewの変数を引き継ぐ）
```

これが地味に便利で、同一viewの中で条件によって表示が大きく変わるようなときに意外と重宝する。
コントローラではDBやモデルの結果だけを持って、変数にHTMLを持ったりしなくて良くなるのが個人的に嬉しい。

私はこれ（view in view）でレイアウトも作成してしまっている。
CodeIgniter3のviewの説明（[Loading multiple views](https://codeigniter.com/userguide3/general/views.html "Loading multiple views")）にある

```php
$this->load->view('header');
$this->load->view('menu');
$this->load->view('content', $data);
$this->load->view('footer');
```

これがすごく気持ち悪く感じたのが発端である。
これをページ毎に記述して、それぞれ引数持たせてログイン時は・・・などの処理をするのが億劫に感じたため、私の場合はすべてのコントローラからは layout.php を呼び出すようにして、その中で処理するようにしている。

``` app/Contorllers/Hoge.php
namespace App\Controllers;
use CodeIgniter\Controller;
class Hoge extends Controller
{
    public function index()
    {
        $data['view'] = 'content';  // メインとなるviewを変数にセットしておく
        $data['hoge'] = 'fuga';
        return view('layout', $data);
    }
}
```

```layout.php
// すべてのviewで $view, $hoge が利用可能
// CodeIgniter4
echo view('header');
echo view('menu');
echo view($view);
echo view('footer');

// CodeIgniter3
$this->load->view('header');
$this->load->view('menu');
$this->load->view($view);
$this->load->view('footer');
```

## 注意

基本的にはやらないと思うが、親viewや子viewで対象の変数を書き換えてしまうと上書きが発生してしまうのでそこだけ注意が必要。
[JavaScript] すごく初歩のJavaScript (コメントアウト,省略形,テンプレートリテラル)

#JavaScript (コメントアウト,省略形,テンプレートリテラル)

JavaScript 自分用の覚え書きです。

```JavaScript:script.js
// ←はコメントアウトのマーク

// 計算式の省略形
number = number + 3;
number += 3;

number = number / 2;
number /= 2;

// テンプレートリテラル
const name = "佐藤";
console.log(`名前は${name}です`);
```
Apple M1チップ搭載MacでNervesを動かす方法(2020.12.8暫定版)

この記事は[Nerves JP Advent Calendar 2020](https://qiita.com/advent-calendar/2020/nervesjp)の10日目の記事です。



# 結論

2020年12月8日現在，NervesはRosetta 2モードでは動作しますが，ARMネイティブモードでは動作しません。

また，ARMネイティブモードで`asdf install elixir (バージョン番号)`としてインストールした後，ターミナルをRosetta 2モードにして起動しなおしたときにElixirは正常に動作するのですが，Nervesを使おうとするとARMネイティブモードとみなされて動作しません。

# Elixirのインストール方法について

現時点でApple Silicon M1チップ搭載Macで推奨されるElixirのインストール方法は，`brew install elixir`でインストールする方法です。

`asdf install elixir (バージョン番号)`によるインストール方法では，ARMネイティブモードとx86_64/Rosetta 2モードのバイナリを共存できない問題があります。Nervesは現時点で後者のモードでしか動作しないので，前者でElixirをインストールしてしまうと Nerves が動作しないという不具合に見舞われます。

Elixirのインストール方法については，こちらを参照ください。Rosetta 2モードのHomebrewでのインストール方法に従ってください。

https://qiita.com/zacky1972/items/f8f7734e9ab46aa74739

# Nervesのインストール

公式ライブラリに沿ってインストールします。

https://hexdocs.pm/nerves/installation.html

ただし，HomebrewでインストールしたElixirはアンインストールせずそのままにして，`asdf`は使わずにしておきます。

手順を上げておきます。

1. アプリケーション/ユーティリティ フォルダを開いてターミナルの「情報を見る」を開きます。
2. 「Rosettaを使用して開く」にチェックを入れます。
3. ターミナルを起動します。
4. Homebrew をインストールします。
5. `brew install elixir`としてElixirをインストールします。
6. `brew update`
7. `brew install fwup squashfs coreutils xz pkg-config`として前提ライブラリをインストールします。
8. `mix local.hex` とします。
9. `mix local.rebar` とします。
10. `mix archive.install hex nerves_bootstrap` としてNervesがインストールできました。

# Hello Nervesをやってみる

https://hexdocs.pm/nerves/getting-started.html

に沿ってファームウェアを作ってみましょう。

1. 試しに`mix nerves.new hello_nerves`としてNervesプロジェクトを作りましょう。
2. 次に，`cd hello_nerves`とします。
3. もし Raspberry Pi 3用にファームウェアを作るのであれば，`export MIX_TARGET=rpi3`とします。
4. `mix deps.get`とします。(もし，ARMネイティブモードになっている場合には，ここでコケます)
5. `iex -S mix`を実行してホストで実行してみます。
    1. `HelloNerves.hello`を実行すると `:world`と出ることを確かめます。
    2. Ctrl-Cとaを押して終了します。 
6. 次のいずれかでターゲット(例えばRaspberry Pi 3)と接続します。
    1. ホストとターゲットをUSBで接続する (今回，未検証です)
    2. ホストとターゲットを有線LANで直に接続する
7. 2の場合は，`config/target.exs`を編集します(後述)。
8. Micro SDをアダプタを介してMacに挿します。
9. `mix firmware.burn`とします。
    1. `/dev/rdisk4? [Yn]` で `y` と答えます
    2. パスワード入力のウィンドウが立ち上がりますので，ログインパスワードを入れてください
10. Micro SDを外して，ターゲットに挿入します。
11. ターゲットを起動します。
12. 接続方法で2を選んだ場合には，`ping nerves.local`として接続を確認します。  
13. 接続されていたら`ssh nerves.local`とします。
    1. `HelloNerves.hello`を実行すると `:world`と出ることを確かめます。
    2. `exit`として終了します。

これで動作が確認できました！

# ARMネイティブモードでNervesを動かすために

NervesをM1 Macで動作させようとして，Rosetta 2モードでは成功したことと，ARMネイティブモードでは動作しなかったことを，世界で初めて私が報告しました。 https://github.com/nerves-project/toolchains/issues/66

Nervesの作者の1人のJustin Schneck氏もM1 Mac入手に動いているのですが，到着するのに4-5週間かかるということなので，私が協力してARMネイティブモードで動かすべく作業を続けています。

方向性としては，M1 Macで`build_release.sh`というスクリプトを使用して，イメージを作成しGitHubに登録すれば良いのですが，なかなか正常に動作せずに苦戦しています。

# おわりに

明日の[Nerves JP Advent Calendar 2020](https://qiita.com/advent-calendar/2020/nervesjp)の11日目は @mnishiguchi さんの[「Elixir/Nervesでパルス幅変調 (PWM) Lチカ」](https://qiita.com/mnishiguchi/items/4bdf88acf0ab0e8e2c7e#_reference-0c91492f373c01c5d98c)です。

本研究成果は、科学技術振興機構研究成果展開事業研究成果最適展開支援プログラム A-STEP トライアウト JPMJTM20H1 の支援を受けた。
pushした一部ファイルの取り消し方

# 経緯
タスクスクリプトを作成しリモートにpushしてレビューに出そうとしたところ、
`Gemfile.lock`と`schema.rb`の差分もpushしてしまっていることに気付きました。

bundle installしたときに更新された分です。
自分が入れたgemじゃないし、今回はタスク追加の変更のみpushしたかったので、`Gemfile.lock`と`schema.rb`の差分pushをなかったことにします。

ログの確認　→　コミット巻き戻し　→　手直し →　force push　という手順で行います。

# まずはログの確認
```
$ git log
commit commitID # 今回pushしたもの
Author: author name
Date:   Fri Dec 4 18:48:13 2020 +0900

    タスクの追加

commit commitID # ここの状態に戻す
Author: author name
Date:   Fri Dec 4 15:06:53 2020 +0900

    ロジック削除

commit commitID
Author: author name
Date:   Fri Dec 4 14:57:10 2020 +0900
    
    中央揃えにする
```

# コミット巻き戻し
「# 今回pushしたもの」の一つ前、「# ここの状態に戻す」ところに`git reset`で状態を戻します。
`git reset commitID`

`git reset`にはオプションがあって、

- `git reset --soft commitID` →  ワーキングツリー* の変更とステージング* の状態はそのまま残る。
- `--hard` →　どちらの内容も消える。
- `--mixed` →　デフォルトはこれ。ワーキングツリーの変更は残るがステージングの状態は戻る。

*ワーキングツリー：ユーザーが作業しているディレクトリ領域。
*ステージング：コミット対象のファイルを登録する領域。`git add`で登録する。

今回は作ったタスクは残しておきたかったので、デフォルトで`git reset`。
ワーキングツリーの状態は残し、pushしないファイル（`Gemfile.lock`と`schema.rb`）はcommit対象から外すため、ステージングを元の状態にしておきます。

コミットを巻き戻したら一応`git log`で状態をみてみます。

```
$ git log
commit commitID
Author: author name
Date:   Fri Dec 4 15:06:53 2020 +0900

    ロジック削除

commit commitID
Author: author name
Date:   Fri Dec 4 14:57:10 2020 +0900
    
    中央揃えにする
```
コミットが一つ消えました。

# 手直し
`Gemfile.lock`と`schema.rb`の変更を取り消します。
vsコードで取り消しました。
vsコードの左上、
![スクリーンショット 2020-12-08 12.43.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570918/b139cae3-5406-02db-f51b-3fd62e75ac5a.png)
のタブにとび、変更を取り消したいファイルにカーソルを当てて、
![スクリーンショット 2020-12-08 12.40.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570918/40ab6999-865f-ceb8-99ff-5d5b4df559b7.png)
をクリックします。



# force pushする
```
$ git add .
$ git commit -m"タスクの追加"
$ git -f push origin <作業ブランチ名>
```
`-f`がforce pushするときのオプションです。
なぜforce pushするかというと、リモートには先ほどローカルでresetしたcommitが残っているからです。リモートとローカルに差異があるので、そこをforce pushで強制的に上書きしてしまいます。
こうすることで、不要なファイルを含んだコミットが消えて、不要なファイルを除いたコミットが記録されます。

# PR出したローカルブランチがすでにないとき
pushした後、早々にローカルブランチ消してしまったといった場合は、
PRをローカルに落として、作業ブランチに移動してからログの確認・・・という手順を踏めばOkです。
`git fetch origin pull/{PR番号}/head:{branch名}`
`git checkout {branch名}`

# 参考
https://qiita.com/yukibe/items/3d25a8de645432519143

を参考にさせていただきました。
Xcode12.1で動かしていたが、iOS14.2のシミュレータが見つからなかった。

### 解決策

XCode12.1にはiOS14.2のシミュレータは含まれていない。XCode12.2以降を使う。どのXCodeにどのSimulatorが含まれているか、およびXCodeの詳細情報はApple公式でチェックできる。

https://developer.apple.com/jp/support/xcode/

### 補足

なお、アプリはXcode12.1でビルドしたいが、シミュレータは(XCode12.2以降にしか存在しない)iOS14.2のものでやりたい、という場合は、以下のような少しトリッキーな技が使える。

[Xcode 11でビルドしたアプリをiOS 14 betaシミュレータ上で動かす方法](https://qiita.com/ShingoFukuyama/items/dc615f823b66b2a7ddd6)
【Swift】繰り返し文について〜while文〜

#while文 とは
while文は、条件式が成り立つ限り繰り返される制御構文になります。

while文は条件式と繰り返し実行される文から成り立ちます。

```swift

while 条件式 {
   条件式が成立する間、繰り返される処理
}
```

while文の条件式は、Bool型を返す必要があります。
**条件式は実行文の実行前に毎回評価され、条件式の結果がtrueの場合は継続処理を行います。**
結果がfalseの場合は繰り返しを終了し、while文全体の処理を停止します。

次のように条件式の`a < 4`が満たされる間は{ }内の処理を実行し続けます。
aの値が4になった時に条件式の結果はfalseを返すのでwhile文を終了します。

```swift

var a = 0

while a < 4 {
    print(a)
    a += 1
}

実行結果
0
1
2
3
```

###repeat-while文

while文は、実行文の実行前に条件式の確認を行うため、
場合によっては一度も実行されないことがあります。

つまり、**while文の繰り返し回数は０回以上ということになります。**

条件式の成否によらず必ず１回以上の繰り返し処理を行いたい場合には、
repeat-while文を使用します。

repeat-while文はwhile文と違い、
実行文の実行後に条件式が評価されます。

```swift

repeat {
   1回は必ず実行され、それ以降は条件式が成立する限り実行される
} while 条件式
```

while文とrepeat-while文の違いを比較するために先ほどの例を少し変更し、
条件式の部分を`a < 0`に変更しました。

while文の場合は、条件式の結果がfalseなので一度も実行されることはなくwhile文が終了します。


```swift
var a = 0

while a < 0{
    print(a)
    a += 1
}
```

repeat-while文の場合は、初回実行が約束されているので０が出力されます。

```swift

repeat {
    print(a)
    a += 1
} while a < 0

実行結果
０
```

while文とrepeat-while文の使い分けについては理解できましたか？
結構単純な処理だと思いますので是非覚えてみてください！

以上、最後までご覧いただきありがとうございました。
【Dr.Sum Datalizer】 CSV出力時にタイトルやヘッダー行を出したくない

DatalizerでCSV出力したとき、定義ファイルのタイトルやヘッダー行出ますよね。
↓こんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/a7ade80c-de23-c496-518f-51d030cc9a11.png)

これ要らないな～、いちいちCSV開いて削除するのも面倒だし。
最初からでなければいいのに。
それ、できますよ。
そう、最初から↓こんな感じに出せるよ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/90ba6f6d-68ee-16e9-a95d-cfb4bb81320e.png)

★手順
タイトル行
レイアウト設定→レイアウト設計→CSVファイル設定→タイトル出力を「出力しない」に

ヘッダー行
レイアウト設定→レイアウト設計→CSVファイル設定→ヘッダー行出力を「出力しない」に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/ba92561e-c266-3a9f-f86d-38e260bba937.png)

#ウイングアークのユーザコミュニティ「nest」
私も参加しています。多くの有益な情報があり、交流があります。
世の中が変わり、社外活動の重要性がより増していると考えております。
社外で自分の価値を計れるものさしを持とう。

https://www.wingarc.com/wug-nest/

以上
高齢出産とバレットグループと私

[Bullet Group Advent Calendar 2020](https://adventar.org/calendars/5143) 10日目の記事です。

# 概要
バレットグループで産んでほんとよかったなという話。

# 経緯

20代の頃から、こどもがほしいなと思っていました。
結婚しなくてもいいからこどもがほしかったのですが、さすがに1人ではどうすることもできず、ようやく結婚したのが40歳の誕生日。
夫もほぼ同年代、あきらかに年齢的に時間が限られているため、すぐに不妊治療に取りかかりました。

バレットグループには、2018年7月に、お声がけいただいて入社。入社後も不妊治療を続けていました。

2019年春、関連会社の日本法人の立ち上げが決まり、プロダクト担当として取締役のオファーをいただきました。
本当にありがたいお話で、ぜひ挑戦したいと思い引き受けたのですが、それからほどなくして妊娠が判明。

ものすごくうれしかった反面、取締役オファーについてはとても悩みました・・・妊娠が順調に経過すれば1年弱で産休に入ってしまいます。最短で復帰したとしても4ヶ月程度は不在になってしまいます。
この状況で責任ある立場になることはさすがに難しいのではないか、でもせっかくのチャンスだし、、、

安定期はまだ先だったのですが、とにかく、代わりを見つけることになったら少しでも早いほうがと思い、オファーをくださった役員に相談しました。

> 私「取締役の件に関してなんですが、実は妊娠がわかりまして、このまま順調にいくと産休も取ることになります。その状況で私が着任するとご迷惑になるのではないかと・・・」
> 役「おめでとうございます！　**ぜんぜん問題ないんじゃないですか**」

あっさり。問題ない。

え、マジで？　産休ですよ？　あっさりOKすぎて聞いた自分のほうが面食らいました。ありがたすぎます。ありがたすぎるけど。え。え。

お言葉に甘えて6月に取締役就任、幸い妊娠も順調に経過し、12月中旬に産休。1月に無事出産しました。

# 何がよかったって
本当にあっさり問題なかったんです。女性の社会参加、育児の男女平等、世の中はもちろんその流れですが、実際に仕事に穴があくっていわれたらふつう躊躇しそうじゃないですか、雇う側としては。
実際、私の知人で同じような経験があり、昇進オファーと妊娠発覚が同時にあったとき、その昇進オファーはなかったことになっていました。女性の多い、女性が活躍するイメージの会社だったけれど、やっぱりそれが現実なんだな、しんどいなと思っていただけに。

妊娠出産だけじゃなくて、いろんな事情でコンスタントに働き続けるのが難しくなることってあると思うんですよね。そんなときに、せっかく仕事できる人たちが一線から完全に引いたり、会社を離れていったりしなければならないのはもったいないと自分でも常々思っていました。
そのハードルがあまりにナチュラルに撤去されていたことには驚いたし、心からうれしかったです。この会社に入れてほんとによかったなと。出産したのがバレットグループにいるときで、ほんとによかったなと思っています。

# その後
保育園にも4月入園が無事決まり、晴れて4月末から職場復帰・・・の予定が、1週間ほど登園したころに新型コロナ影響で緊急事態宣言、登園自粛。
復帰を少し先延ばしして様子を見ていましたが、先が見えず。バレットグループが常時リモートワークにシフトチェンジしたため、思い切って5月に復職を強行しました。
6月から登園自粛は解除し、いまでは元気に保育園通い、母は自宅でのびのびとお仕事させてもらっています。

リモートワークへの転換も決断早かったです。自分としては対面でお仕事するメリットもとても感じているため、いまでは出社もときどき織り混ぜてはいますが、送り迎え後すぐ始業できる、洗濯機まわしながら仕事できる、このありがたさは代えがたいものがあるなと思っております。ほんと助かる。。。

もう少しでこどもも1歳。あっという間の成長に驚かされる日々。まごうことなきシニア母ですが、少しでも自分も一緒に成長していきたいと思います。
子育てを通じて経験できたこと、成長できたことを、仕事にも還元していければと思っています。そして、これから妊娠出産に直面するパパママ、それ以外でも様々な状況の人がいきいきと働けるよう、できる限りの応援をしていきたい。
GCEインスタンスにおいてCloud Shell操作のみでスナップショットからリストアさせるには

## 概要
運用しているサーバが急にクラッシュなどを引き起こし、復旧させたい。
前提条件として、定期スナップショットを取得していること。

## 目標
- インスタンス自体は変更せず、スナップショットから永続ディスクを作成し、インスタンスへディスクを差し替え、復旧させる
- Cloud Shellからの操作で行う

## 環境
- google compute engine(GCE)
- CentOS 7
- Cloud Shell

## 手順

##1. Cloud Shellの実行
GCPのCloud ConsoleからCloud Shellを起動するには、Console画面右上の [Cloud Shell をアクティブにする] ボタンを使用します。＊画像の赤丸の箇所
![スクリーンショット 2020-12-08 15.30.55（2）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110334/ae79dbb1-d35b-33f8-04e7-b93073952ea9.jpeg)

##2. インスタンスの停止
ディスクの差し替えを行うので、インスタンスは停止する必要があります。

```
$ gcloud compute instances stop [INSTANCE_NAMES]
```

##3. スナップショットから新しいディスクに復元
復元したいスナップショットを確認します。

```
$ gcloud compute snapshots list

#発行例
NAME        DISK_SIZE_GB  SRC_DISK                      STATUS
snapshot-1  30            us-west1-a/disks/server01     READY
```
復元したいスナップショットが確認できたら、スナップショットから永続ディスクを作成します。

```
$ gcloud compute disks create [DISK_NAME] \
    --size [DISK_SIZE] \
    --source-snapshot [SNAPSHOT_NAME] \
    --type [DISK_TYPE]

#発行例
$ gcloud compute disks create server02 \
    --size 30 \
    --source-snapshot snapshot-1 \
    --type pd-standard
```

##4. インスタンスから既存のディスクをデタッチする
以下のコマンドよりインスタンスから既存ディスクをデタッチします。

＊公式リファレンスでは、ディスクをアンマウントせずにディスクを取り外すと、I / O操作が不完全になりデータが破損する可能性がありますと記述されていますので、注意が必要。
今回はクラッシュを引き起こしサーバにSSH接続すらできない状態を想定しているため、無視します(笑)

```
$ gcloud compute instances detach-disk [INSTANCE_NAME] \
    --disk [DISK_NAME]
```

##5. 新しいディスクを既存のインスタンスへアタッチする
以下のコマンドより作成したディスクをインスタンスにアタッチします。

```
$ gcloud compute instances attach-disk [INSTANCE_NAME] \
    --disk [DISK_NAME]
```

##6. インスタンスの起動
以下のコマンドよりインスタンスを起動し、完了です。

```
$ gcloud compute instances start [INSTANCE_NAMES]
```
書籍で学習を行う時のコツ

私が書籍で学習する際に行っている方法のご紹介です。

それはズバリ、書籍を読み進めながら、**Qiitaの限定共有記事に要約を書く**、です。

いわゆる「ラーニングピラミッド」理論によると、読書では学習定着率が１０％しかないそうです。[^1]

読書と並行で**要約記事を書いていくと、手を動かしながら頭を使う分だけ少し定着率が上がる**気がしますし、
要約を後から読み直して、パッと内容を思い出せない箇所は記憶が定着していないので、そこを重点的に読み返すと良いです。

学習しようとしている知識の全体像を踏まえて、**構造的な要約を書くことがポイント**です。
それを意識することで、知識を体系立てて定着させることができると思います。

手書きのメモと違って何度も書き直せることと、自宅でも職場でも閲覧・編集できることがQiitaの限定共有記事のメリットです。

ちなみに、**要約の公開は著作権者の事前承諾が必要なケースもある**らしいので、私は公開しないようにしています。[^2]

[^1]: 参考リンク：https://career-ed-lab.mynavi.jp/career-column/707/
[^2]: 参考リンク：https://pf.bunka.go.jp/chosaku/chosakuken/naruhodo/answer.asp?Q_ID=0000338
composer require laravel/uiが失敗【Laravel7系 ログイン機能の実装】

Laravel7 ログイン機能の実装するために詰まったので、メモしました。

##公式ページから一つずつ実行

まず以下の公式ページからLaravel 7系でログイン機能を実装するために、いくつかのコマンドを打ってみました。

https://readouble.com/laravel/7.x/ja/authentication.html

```
composer require laravel/ui
php artisan ui vue --auth
```

上記の二つをコマンドで打つ必要があるとのことでした。

でも

composer require laravel/ui

が失敗...。エラーは以下のものです。

##composer require laravel/uiを打った後のエラー

```
Using version ^3.1 for laravel/ui
./composer.json has been updated
Running composer update laravel/ui
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - laravel/ui[v3.1.0, ..., 3.x-dev] require illuminate/console ^8.0 -> found illuminate/console[v8.0.0, ..., 8.x-dev] but it conflicts with another require.
    - Root composer.json requires laravel/ui ^3.1 -> satisfiable by laravel/ui[v3.1.0, 3.x-dev].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.
```

##いくつかの大切なことを翻訳してみた

```
Your requirements could not be resolved to an installable set of packages.
```

あなたの要件は、インストール可能なパッケージのセットに解決できませんでした。

```
Installation failed, reverting ./composer.json and ./composer.lock to their original content.
```

インストールに失敗し、./composer.json と ./composer.lock を元の内容に戻しました。

##対処してみた！

うーん、なんでだろう…

参考になったサイトは以下のもの

https://atuweb.net/202003f_laravel-ui-composer-error/
と
https://packagist.org/packages/laravel/ui
と
https://laravel.com/docs/7.x/frontend#introduction

Packagist を調べてみると、laravel/ui に対応した Laravel 7は以下のものですね。

__2.x	7 系__

結論は

```
composer require laravel/ui:2
```

<blockquote>僕の場合は
composer require laravel/ui:2.5.0
としました。

composer require laravel/ui:^2.4
でも良さそう☺️
App Store ConnectでApp Privacy Detailsを登録する

## はじめに
- 2020/12/8からアプリのプライバシー情報を申請時に登録が必要になりました。
今後はApp Storeにアプリのプライバシー情報がアプリページに表示されるようになります。
今回は登録時にやったことについてまとめました。
- 詳細はこちら [App privacy details on the App Store](https://developer.apple.com/jp/app-store/app-privacy-details/)

## 項目
- App Store Connect -> `App` -> `App Store` -> `Appのプライバシー`で登録できます
![スクリーンショット 2020-12-08 15.53.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63985/cfce1012-796a-f4de-656a-309ca57b605d.png)


## やったこと
- でてくる質問に対して、該当するところにチェックを入れていきます。

![スクリーンショット 2020-12-08 15.55.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63985/b887a34e-b24d-d62f-b5a3-be678c58e44b.png)

![スクリーンショット 2020-12-08 15.56.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63985/ba886ade-f5c1-bec5-0031-b8b05c87b038.png)

- 該当するデータタイプを選択していきます
- ここまで終わると該当する項目が一覧で表示されます。

![スクリーンショット 2020-12-08 16.04.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63985/75241995-c0fc-a24c-1d02-6b73c4677741.png)

- ここからは各項目の情報の利用目的について、チェックしていきます。

![スクリーンショット 2020-12-08 16.04.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63985/392219e7-7cf8-53f8-a059-11191d0c21a4.png)

![スクリーンショット 2020-12-08 16.05.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63985/f6f9587c-ff0d-f3c1-33cf-64fd07068c4e.png)

- 各項目はいつでも変更可能になっています。

![スクリーンショット 2020-12-09 14.28.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63985/28786de3-109e-6c8b-a434-5f6346a02c7e.png)

![スクリーンショット 2020-12-09 14.41.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63985/75062de6-bcd3-1d8a-ff22-6387e6182018.png)

- 公開ボタンを押すとダイアログが表示され、公開を押すと反映されます

## 追記 2020/12/11
- 実際のApp Storeのページで表示されるのはiOS14.3からです

```
Privacy
•New privacy information section on App Store pages that includes a developer-reported summary of the app’s privacy practices
```

## 運用方法案
### エクセルなどで管理する
- 1番よく使われる方法だと思います。手動で項目を反映さえていくのが結構手間です。

### fastlane
- [Uploading App Privacy Details](https://docs.fastlane.tools/uploading-app-privacy-details/)
    - 設定項目をアップロードするActionが追加されている
    - JSONで管理できるので一度つくってしまえば楽だと思いました

```ruby
upload_app_privacy_details_to_app_store(
  username: "your@email.com",
  team_name: "Your Team",
  app_identifier: "com.your.bundle",
  json_path: "fastlane/app_privacy_details.json"
)
```

```json

[
  {
    "category": "PAYMENT_INFORMATION",
    "purposes": [
      "APP_FUNCTIONALITY"
    ],
    "data_protections": [
      "DATA_NOT_LINKED_TO_YOU"
    ]
  },
  {
    "category": "NAME",
    "purposes": [
      "PRODUCT_PERSONALIZATION",
      "APP_FUNCTIONALITY"
    ],
    "data_protections": [
      "DATA_LINKED_TO_YOU",
      "DATA_USED_TO_TRACK_YOU"
    ]
  }
]
```

## まとめ
- アプリのプライバシー情報を申請時に必要になりました。
- fastlaneなどを使って、運用を楽にしていきたいと思いました。

## 参考リンク
- https://developer.apple.com/jp/app-store/app-privacy-details/
- https://docs.fastlane.tools/uploading-app-privacy-details/
【Dr.Sum Datalizer】CSV出力時の文字コード変更したい

DatalizerでのCSV出力は、普通の設定だとUTF-8で出る場合が多いです。
SJISにしたいなってとき、ありませんか。
出力CSVを別のツールにかませたいけどSJISしかダメ、とか。
そんなときに。超・簡単だよ！

★手順
レイアウト設定→レイアウト設計→CSVファイル設定→出力エンコードを「MS932」に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/fa54439b-1ad4-3e03-ec6f-e097b20e4e59.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/3a71338c-aaf2-98f9-3627-b5ab51b08468.png)


#ウイングアークのユーザコミュニティ「nest」
私も参加しています。多くの有益な情報があり、交流があります。
世の中が変わり、社外活動の重要性がより増していると考えております。
社外で自分の価値を計れるものさしを持とう。

https://www.wingarc.com/wug-nest/
N予備校の拡張機能作成のすゝめ

この記事は、[N高等学校 (1) Advent Calendar 2020 9日目](https://qiita.com/advent-calendar/2020/n-highschool)の記事です。

# はじめに
はじめまして"N予備校を自分好みにカスタマイズするだけして勉強やらない人"です。
N高等学校の5期生でピチピチの一年生です。
※ この記事はレポートの日程を考えないでadvent calenderに申請した人が書いています。
内容が雑かもしれませんがよろしくおねがいします:pray::pray::pray:

### 今回書くこと
今回はN予備校の大雑把にですがいちからN予備校の作る方法や
知っておくと便利な事を書いておこうと思います。
[具体的にこんなのが作れます（露骨な宣伝）](https://qiita.com/tsutoringo/private/6367ebc6684b2eaefae0#%E3%81%9D%E3%82%8C%E3%81%A8%E3%81%9D%E3%82%8C%E3%81%A8)
※Chromeの拡張機能の基本的な作り方は省きます。

## 作り方其の一
`https://www.nnn.ed.nico/courses/*/chapters/*`
のページにcontent_scriptを適用したい場合
これは簡単ですね。

```jsonc:manifest.json
{
	/* 省略 */
	"content_scripts": [{
		"matches": ["https://www.nnn.ed.nico/courses/*/chapters/*"],
		"js": [
			"content_script.js"
		]
	}]
}
```
manifest.json の content_scripts の matches にURLを入力するだけです。
工夫が必要になってくるのは次からです。

## 作り方其の二
レポートやテストのページに適用したい場合
レポートやテストのページはiframeになっているのでmanifest.jsonに一項目追加しなければなりません。
URLはhttps://www.nnn.ed.nico/contents/courses/*/chapters/*/*/* で

```jsonc:manifest.json
{
	/* 省略 */
	"content_scripts": [{
		"matches": ["https://www.nnn.ed.nico/contents/courses/*/chapters/*/*/*"],
		"js": [
			"content_script.js"
		]
		// 追加
		"all_frames": true
	}]
}
```
`all_iframes: true`を追加することでiframeで読み込んだときも適用されるようになります。

## 作り方其の三
動画ページに適用した場合 ※ズルはしちゃダメヨ！単位剥奪がまってる！！
動画ページも上同様iframeなのですが
何故か動画ページだけ複数URLあるので虱潰しで記述しないといけないです。
私が知ってるURLは以下です

```jsonc:manifest.json
{
	/* 省略 */
	"content_scripts": [{
		"matches": [
				"https://*.tokyo-shoseki.co.jp/*",
				"https://www.nnn.ed.nico/contents/links/*",
				"https://www.nnn.ed.nico/contents/courses/*/chapters/*/movies/*",
				"https://cdn.fccc.info/*"
		],
		"js": [
			"content_script.js"
		]
		// 追加
		"all_frames": true
	}]
}
```
誰かURL一覧まとめてください☆（他力本願寺）

# その他tip
私は勉強しないで拡張機能を作ってるときに気づいた便利そうなものおいておきます。

### いろんなデータを取得する
https://www.nnn.ed.nico/courses/*/chapters/*
には理由はわかりませんが其のページの教材のデータがjsonで記述されています。
それを使って色々拡張機能作れると思います。

```JS
const data = JSON.parse(
	document
		.querySelector('div[data-react-class="App.Chapter"][data-react-props]').dataset.reactProps
)
```
データの中身は貼っていいものなのかわからないので貼りませんが
上のコードで取得できます。
reactがわからないので何であるかはほんとにわかりません。
教えて強い人！！

# 終わりに
以上レポートがまだあるのに考えなしにadvent calenderに
申し込みして初めて書いたQiita記事です。

見にくい点、誤字脱字があったらぜひご指摘お願いします:pray::pray:

### それとそれと
ここで~~宣伝~~(ｺﾞﾎﾝｺﾞﾎﾝ)皆様のレポート活動を潤滑に進めれるように
作成した拡張機能を紹介させていただこうと思います。

[文字数カウンタ](https://chrome.google.com/webstore/detail/n-yobi-char-counter/cjgiegfjhnlfbgpcjeainnakegcopdhd?hl=ja)
[github](https://github.com/tsutoringo/N-yobiko-char-counter)
これは単純に文字数をカウントしてくれるものになります。

[ボリュームセッター](https://chrome.google.com/webstore/detail/n-yobiko-volume-setter/fbminpffmmcgebhihlhnkfmljdkahoic?hl=ja)
こちらは動画の音量を保存して毎回適用してくれるようにする拡張機能です。

読みにくいを記事最後まで読んでくださりありがとうございました:pray::pray:
【Java】ApachePOIでExcelを出力する

##初めに
　yuji323です。今回の記事では、Javaのライブラリである__ApachePOI__を使ってExcelファイルを出力する方法について記事にします。
####背景
　業務で必要にかられたので。あと調べても古い記事が多くてちょっと不安だったので。
####環境

```pom.xml
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.0</version>
</dependency>
```

##作成パターン①　-.xlsxファイルを新規作成する
Java上で新規に.xlsxファイルを作成します。コードは以下

```java
class CreateNewFile{
	public static void main(String[] args){

        // 出力先ファイルパス
        String output = "C\\users\\user\Desktop\newFileFromOrigin.xlsx"
  
		// 各オブジェクト作成
        Workbook book = new XSSFWorkbook();
		Sheet sheet = book.getSheet(this.sheetName);
		Row row;
		Cell cell;

		// Excelに書き込み
        row = sheet.getRow(0);
        cell = row.getCell(0);
        cell.setCelValue("Hello POI")

		// 出力
		FileOutputStream fos = new FileOutputStream(fullDataExcelPath);
		book.write(fos);
		book.close();
		fos.close();
	}
}
```

##作成パターン② -既存の.xlsxファイルをもとに作成する。
```java
class CreateNewFile{
    public static void main(String[] args){

        // 入力ファイルパス
        String input = "C\\users\\user\Desktop\template.xlsx"

		// 元ファイル読み込み 
		Workbook book = WorkbookFactory.create(new FileInputStream(input));
		Sheet sheet = book.getSheetAt(0);
		Row row;
		Cell cell;
		
        // Excelに書き込み
        row = sheet.getRow(0);
        cell = row.getCell(0);
        cell.setCelValue("Hello POI")

		// 出力
		book.write(new FileOutputStream(fullDataExcelPath));
		book.close();
		fos.close();
    }
}
```

##まとめ
・新規作成するとき：__Workbook book = new XSSFWorkbook();__
・元ファイルから作成するとき：__Workbook book = WorkbookFactory.create(new FileInputStream("ファイルパス"));__
でファイル作成できる。
【Stereo Depth】Dispnet : concatenationでStereo Matching

<h1>A Large Dataset to Train Convolutional Networks for Disparity, Optical Flow, and Scene Flow Estimation</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/700c188c-752d-15f8-3419-78b0fa1edb80.png)

DispNetは[MC-CNN](https://qiita.com/minh33/items/6b0ed63e7c23afb16ed9)やSGM(Semi Global Matching)と違う方法でDepthを計算していたので、面白いと思い記事にします。
*optical Flowについても記述があるのですが今回は無視します

<h1>新規性</h1>

<h2>左右の画像を結合して入力</h2>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/a387c92d-e353-c0f0-f36e-853639815eea.png)
入力の時点で特徴量6、すなわち右と左のRGBが入力とい事がわかります。
MC-CNNではPatch(9x9のエリアをくり抜いた物)を入力して、CNNで畳込むのですが、すべてのDisparityに対して同じ処理を何回も繰り返さなきゃいけなく、かなり計算コストが重めだった。

しかもこっちの方が画像全体を参照出来るから良いんじゃないかと思った。

<h2>Correlation Layer</h2>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/0fcad8ab-32b4-9df3-cdc4-2de3925ba40e.png)

DispNetとDispNetCorr1Dというのが下の結果のTableにあるのですが、Correlationとは取り得るDisparityに対して右と左のFeature MapをシフトしてCost Volumeを作る事を言います。
*Stereo Matchingの取りうるすべてのDisparityに対して特徴を計算するのに似ています

<h1>結果</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/9d28ef6b-ffdd-3700-cb16-7f92d18591f0.png)
右と左の画像を結合する方法は古典的なSGMやCNNを使ったMC-CNNより高速でした。

<h1>結論</h1>
・2020年現在あまり使われていない右と左の画像を結合して入力とするこの手法は以外と注目されていないだけで、効率的だと思っている。



<h1>参考文献</h1>
A Large Dataset to Train Convolutional Networks for Disparity, Optical Flow, and Scene Flow Estimation
https://arxiv.org/pdf/1512.02134.pdf
【個人開発】SOFT SKILLSで紹介されているタスク管理法に特化したWebアプリを作ってみた

作ったWebアプリのリンク：https://pomo-task.herokuapp.com/

# はじめに
SOFT SKILLSで紹介されていた時間管理法をご存知ですか？

このタスク管理法はポモドーロテクニック、カンバンなどを融合していて、自宅での作業が効率的に行えるようになっています。

とても良い方法ですが、不満な点が1つだけありました。それがツールの使いやすさです。SOFT SKILLSではKanban Flowが紹介されていましたが、このサービスでは個人の時間管理に特化しているわけではないので、少し不満が出てきます。

* 集団での利用を想定して作られているため、個人では使いづらい
* ポモドーロタイマーが使いづらい
* タスクの締め切りを把握しにくい
* 全体のデザインは硬め

この点を解決すべく他のサービスを探していましたが、自分の好みに合うものがなかなか見つかりませんでした。なので自分で作ることに決めました。

また、前からRailsを扱えるようになりたいと思っていたということもあります。毎月新しいプロジェクトを作ると良いと聞いたので、その1つ目です。RubyもRailsも始めて1ヶ月なので至らない点が多いと思いますが、どうかご覧いただければ幸いです。

# 作ったもの
先日、PomoTaskというWebアプリをリリースしました。

https://pomo-task.herokuapp.com/

![localhost_3000_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409132/9519a357-f8d4-978a-46db-cbce8739da6d.png)

## 推しポイント
* ポモドーロタイマーの使い心地
  * START, SKIP, STOPのみの簡単な操作性
  * 何回目かが分かる
  * 音とブラウザ通知で開始、終了１分前、終了をお知らせ
* 目標
  * その日、週のポモドーロ数が分かる
  * 年、四半期、月、週の目標を確認できる
  * 週目標は常に見られる
* 締め切りの見やすさ
* 曜日ルーチン
  * 毎週行うタスクは自動で追加できる
* 集中力を高めるための仕掛け
  * ポモドーロタイマーの色が変わる
  * 集中力を高めるためのコツをヘルプに掲載
* 色、視認性
  * タスクの背景色

# おわりに
最低限使えるレベルのものが作れたような気がします。とりあえず今後は、新しいWebアプリを作ったり、PomoTaskに機能を追加しようと考えています。

付けるべき機能や改善した方がいい点があれば、コメントしていただけると嬉しいです。

# 参考資料
* SOFT SKILLS　ソフトウェア開発者の人生マニュアル - ジョン・ソンメズ
* 自分を操る超集中力 - メンタリストDaiGo
* どんな仕事も「25分+5分」で結果が出る　ポモドーロ・テクニック入門 - フランチェスコ・シリロ
(勉強に使った参考書：現場で使える Ruby on Rails 5速習実践ガイド)
[Python]forとifの処理を１行で書く方法[リスト内包表記]

# 概要
- リスト内包表記を使うことでfor・ifの処理を１行で書くことができます！
- （ifのみの場合は、リスト内包表記を使えません）



# コード（リスト内包表記を使う前）

- リストの宣言やfor・ifを使うと４行書くことになります。
- リスト内包表記を使うと…？？？

```Python
before_list = [1,2,3,4,5,6,7,8,9,10] # １から１０のリスト
# ----------リスト内包表記を使う前----------------------------------------
after_list = [] # 偶数だけを入れるリスト
for i in before_list:
    if i % 2 == 0: # ２で割り切れる（偶数）ときにリストへ追加する
        after_list.append(i)
# -----------------------------------------------------------------------
print(after_list)
```

- 実行結果

```
[2, 4, 6, 8, 10]
```

# コード（リスト内包表記を使った後）

- リスト内包表記を使うと１行で簡潔に書くことができます！

```Python
before_list = [1,2,3,4,5,6,7,8,9,10] # １から１０のリスト
# ----------リスト内包表記を使った後---------------------------------------
after_list = [i for i in before_list if i % 2 == 0]
# -----------------------------------------------------------------------        
print(after_list)
```

- 実行結果

```
[2, 4, 6, 8, 10]
```


# まとめ
- リスト内包表記を使うことでコードを１行で書くことができる。
- リスト内包表記はいいぞ
ループを使わずに配列上の連続する2つの値を要素とするリストを作る

# はじめに

[SENSYN Robotics](https://www.sensyn-robotics.com/)(センシンロボティクス)の中山です。
Webアプリやそのインフラ周りと、Web側とドローンの接続を行うデバイスドライバ的な部分を担当しています。

ここ1〜2年探していた、ループを使わずにリスト上の連続する2つの値を要素とするリストを作る方法をやっと思いついたので、それを記録するためのエントリです。

# なにをしたいか

直近でやりたかったのは、ドローンの飛行記録から実際に飛行した距離を算出することでした。ドローンは飛行している場所(緯度・経度)を定期的に通知しています。CSVにすると、以下のようなイメージのデータです。

```csv
時刻,緯度,経度
2020-12-08T02:26:33Z.231,35.166264279608,138.67945381096
2020-12-08T02:26:33.834Z,35.166264279610,138.67945381097
2020-12-08T02:26:34.102Z,35.166264279611,138.67945381098
...
```
二点の緯度・経度が分かれば、その二点間の距離は計算可能です。そして、2点間の距離が計算できれば、あとは各2点間の距離を足し合わせて飛行した距離が計算できます。

# ループを使って実装してみる

2点間の距離の計算には`npm install geolib`して[geolib](https://www.npmjs.com/package/geolib)を使います。

ループを使うとこんな感じでしょうか。

```js
const geolib = require('geolib');

const route = [
  {latitude: 35.166264279608, longitude: 138.67945381096},
  {latitude: 35.167274290660, longitude: 138.67945381157},
  {latitude: 35.168284321721, longitude: 138.67945381218},
];

let from = null;
let dist = 0.0;
for (const to of route) {
  if (from != null) {
    dist += geolib.getDistance(from, to);
  }
  from = to;
}
console.log(`distance: ${dist}m`);
```
連続する2つの値を扱うために、前回のループの値をfromに入れて、今回の値をtoとして扱っています。

これはこれで悪くないのですが、fromやdistを書き換えているのが気持ち悪いです。if文があるのも美しさに欠けます。

# reduce()を使って実装してみる

変数の書き換えを排除するために`reduce()`を使ってみると、こんな風になりました。

```js
const geolib = require('geolib');

const route = [
  {latitude: 35.166264279608, longitude: 138.67945381096},
  {latitude: 35.167274290660, longitude: 138.67945381157},
  {latitude: 35.168284321721, longitude: 138.67945381218},
];

const dist = route
  .reduce((acc, v) => [...acc, {from: acc[acc.length - 1].to, to: v}], [{from: route[0], to: route[0]}])
  .filter(v => v.from != v.to)
  .map(v => geolib.getDistance(v.from, v.to))
  .reduce((sum, d) => sum + d, 0);
console.log(`distance: ${dist}m`);
```

## 最初のreduce()

```js
  .reduce((acc, v) => [...acc, {from: acc[acc.length - 1].to, to: v}], [{from: route[0], to: route[0]}])
```
ここで連続する2つの値を要素とするリストを作っています。`route`の各要素に対して、適用結果の配列の最後の要素とのペアを作っていきます。

1. `acc`の初期値 `[{from: 要素0, to: 要素0}]`
2. 1回目の適用  `[{from: 要素0, to: 要素0}, {from: 要素0, to: 要素0}]`
3. 2回目の適用  `[{from: 要素0, to: 要素0}, {from: 要素0, to: 要素0}], {from: 要素0, to: 要素1}]`
4. 3回目の適用  `[{from: 要素0, to: 要素0}, {from: 要素0, to: 要素0}], {from: 要素0, to: 要素1}, {from: 要素1, to: 要素2}]`

スプレッド演算子`...`を使わずに、`(acc, v) => {acc.push({from: acc[acc.length - 1].to, to: v}); return acc}`とかでもいいです。

## filter()

ここで目的の「連続する2つの値を要素とするリスト」を含むリストができたのですが、最初の2つの要素は`from`と`to`がどちらも要素0を指しています。距離を計算するのであればこのままでもいいのですが、汎用性を考えるとちょっと問題があります。そこで`from`と`to`が同じものを排除して、「連続する2つの値を要素とするリスト」だけを取り出すのがここの`filter()`です

```js
  .filter(v => v.from != v.to)
```

# map()

2点から2点間の距離を計算しています。

```js
  .map(v => geolib.getDistance(v.from, v.to))
```

## 2個目のreduce()

距離を合計して、ルート全体の飛行距離を計算しています。

```js
  .reduce((sum, d) => sum + d, 0);
```

# まとめ

ループを使わずに配列上の連続する2つの値を要素とするリストを作るには、以下のようなコードを書けば良い。

```js
list
  .reduce((acc, v) => [...acc, {from: acc[acc.length - 1].to, to: v}], [{from: list[0], to: list[0]}])
  .filter(v => v.from != v.to)
```

JavaScript以外でも、`reduce()`と`filter()`が使えれば同じ手法が使えると思います。
Azure AD を使ったお手軽多要素認証の実装

# はじめに
こんにちは！[mediba advent calendar 2020](https://qiita.com/advent-calendar/2020/mediba) 11 日目担当の @mediba_t-sato です。
[mediba](httos://www.mediba.jp) では、社内インフラ、情報セキュリティ、レガシー業務の効率化などを担当しています。

mediba では、2020/3/3 から[テレワーク指示](https://www.mediba.jp/news/20200303/)となり、不要不急の出勤以外はテレワークとなり、現在も日々 90% 近い実施が継続されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148739/41139876-0600-1d46-8b14-c368f00fac1a.png)
こんなコロナ禍の中、企業を狙ったセキュリティ攻撃も増えてきています。（かんべんして・・）

慣れない環境、設備の中、業務を継続していただいている社員の皆さんに感謝しつつ、冬に向けて再び準備に頭を悩ませている社内インフラ担当の参考になれば幸いです。

# 信用しない努力（さっきの感謝はどこいった・・・）
mediba では、2016 年から [Azure AD](https://azure.microsoft.com/ja-jp/services/active-directory/#security) を利用した [SSO 化](https://docs.microsoft.com/ja-jp/azure/active-directory/manage-apps/what-is-single-sign-on)を導入し、重要な社内システムの認証に活用しています。
また、事業用のシステムにも徐々に浸透をしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148739/328042ef-8c81-698a-2865-686ebbc80657.png)

最大のメリットは、利用者が社外環境下でも、社内と同じ ID でシステムへのログインできつつ管理者がコントロールできること。（何時、誰が、何処から、どのシステムにログインしたのか見えるんです。）
また、異常なログインを検知した場合には、自動的に ID をロックするなどの機能を備えています。（これで夜もぐっすり・・・）
各システムのログインに共通の基盤を利用することで、SSO を実現しパスワードの入力機会を削減することでパスワード管理の煩雑さを軽減しています。

この仕組みを全社の主要なシステムに導入するには、かなりの努力と忍耐がいりましたが、それはまた別の機会にでも・・・

# ID・パスワードが漏洩したら意味ないよね
とわいえ、弱点が無いわけではない。
社内アカウントとパスワードが漏洩した場合、IP アドレス制限などを設けられないシステムは恰好の標的となってしまう。
このため、多要素認証（MFA）を同時に利用することが推奨されているが、これらが整備されたアプリを自前で作成するのは結構骨の折れるし、対応している SaaS もまだまだも少ないため Azure AD 側でやってみようというのが今回のお話しです。

# やってみた（前置き長すぎですね・・・）

Azure AD では、3 タイプの MFA の実装が可能です。

* ユーザー単位で MFA の有効化
* SSO アプリケーション全体で MFA の有効化
* SSO アプリケーション単体での MFA の有効化

今回は、SSO アプリケーション単体での MFA の有効化をやっていきます。

## 必要なもの
* Azure AD Premium P1 ライセンス（Microsoft 365 Business Premium ライセンス などにもついてきますね。）
* Azure AD を利用した SSO アプリケーション([過去の記事参考ください](https://qiita.com/t-sato_mediba/items/b2628775c8337245027a))

## 設定
[Azure Active Directory 管理センター](https://aad.portal.azure.com) からコーディング不要で設定可能です。

1. Azure AD から、『エンタープライズアプリケーション』にて MFA を有効化したいアプリケーションを開き、『セキュリティ』から『条件付きアクセス』を選択して "新しいポリシー" を追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148739/1621e2f0-b8c5-705d-fffa-abd34bdd245f.png)

1. 『割り当て』にて MFA を有効化させたいユーザーやグループを選択

1. 『アクセス制御』にて "多要素認証を要求する" にチェックをして "ポリシーの有効化" を オン にして "保存"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148739/1e707ff5-bb1a-cd0f-1638-a1a250272055.png)

たったこれだけ。
あとは、初回ログイン時に、MFA の設定を促されるので、SMS、電話、アプリなどのお好きな方法でユーザー単位で設定を促せばよい。（SMS などの通知を追加負担なしで実現してくれることは流石です。）

# 注意点
Azure AD の SSO のセッションは結構長めに設定されている。
規定値で **180 日**に設定されている場合があるため、前述のポリシーの設定にて『セッションの設定』をしておく方がいい。
これが無いと、MFA がなかなか要求されてこない。という事態が発生する。アプリケーションの利用頻度と合わせて調整をしてみてください。

# おわりに
突然のコロナ禍でテレワーク導入となり、スマホや自宅で利用可能な SaaS 製品に切り替えが進んでいる企業も多いことと思います。
mediba でも大手の SaaS 以外では、まだまだ MFA を導入している企業は少なく、セキュリティ対策に頭を悩ませておりました。
Azure AD を利用したこの方法は、アプリケーション単位での実装の可否や MFA 非対応のアプリケーションへの適用など使い道の多い方法かと思います。
皆さんの参考になれば幸いです。
Cisco Packet Tracerにて学んだことの備忘録

#はじめに
社会人一年目に業務上ルータを触ることになったのでその際、CiscoのPacketTracerであれこれコマンドを試したものを忘れないうちにメモ。
※後に全体的に修正する予定

#コマンド一覧

####en (enable)
特権モードの事で、基本的にこのモードで作業をする
※パスワードを設定した場合、パスワード入力が必要になる


####disable
特権モードからユーザモードへ戻る


####logout
ルータからのログアウト


####reload
ルータの再起動


####conf t (configure terminal)
グローバルコンフィグレーションモードの事で、ルータに対してルータ全体にかかわる設定を行うモードのこと


####Ctrl + Z
^Zと表示され、コンフィグモードやインターフェイスコンフィグから特権モードへもどる


####interface XXXX (XXXXは設定したいものの名前を入れる_interface FastEthernet 0/0など)
インターフェイスコンフィグモード
ルータの各インターフェイスの設定を行うモードのこと
FastEthernet 0/0 のインターフェイスを設定するには、interface FastEthernet 0/0 コマンドを、
FastEthernet 0/1 のインターフェイスを設定するには、interface FastEthernet 0/1 コマンドを実行という形になる
※conf tに入った状態でしか入れないため注意
※description XXXXでXXXXの部分に説明文を入れられる。削除はインターフェイスコンフィグモードからno description


####sh run (show running-config)
現在実行中のコンフィグレーションを表示する
※ルータ起動中に設定変更をしたものが表示されるが、保存をしない状態で電源を落とすとここで表示されている設定が消えてしまうため注意


####sh star (show startup-config)
ルータの起動時に読み込むコンフィグを表示する
ルータ内のNVRAMに保存されていて、ルータ起動時にメモリ (RAM) 上に読み込む設定ファイル
読み込まれたコンフィグレーションは running-config になり、ルータの実行コンフィグレーションとして使用される
※ルータが初期状態の場合は何も保存されていないため、running-configの設定をstartup-configに保存する必要がある


####copy running-config startup-config (write memoryまたはwriteでも同じ結果になる)
現在実行中のコンフィグを起動時に読み込ませるために保存する
このコマンドを実行すると、ルータの電源を落としてもstartup-configに保存されているため設定が消えることはない


####erase nvram:またはerase startup-config
startup-configに保存した設定を削除する


####? (XXXX ?)
今打っているコマンドが実行可能なのか確認できる(ヘルプモード)
実行出来るならcrと表示される


####show terminal
現在のヒストリバッファサイズを確認できる
※ヒストリバッファとは、コマンドモードで以前打ったコマンドを保存しておく機能のこと(↑で以前のコマンドを呼び出せる)
デフォルトでは10コマンドまで保存されるようになっている


####terminal history size XXX
0から256の間でヒストリバッファサイズを変更
※terminal no history sizeでデフォルト値に戻すことが出来る
(terminal no historyでコマンド履歴自体を無効化することも可能)


####hostname XXXX (conf tから設定)
ホスト名を変更出来る


####banner motd # (#はバナー文字入力の終了文字)conf tから
ルータにバナーを付ける
※ルータにコンソール接続やTelnet、ログインした際に表示されるメッセージのこと
no banner motdで設定したバナーを消すことが出来る


####no ip domain-lookup (conf tから設定)
間違ったコマンド入力時に、DNSサーバへ問い合わせをしないようにする
間違ったコマンドを入力時、コマンド認識が出来ないと入力した文字をホスト名だと診断して名前解決を行おうとしてしまうため、DNSサーバへ問い合わせをし返事待ちで時間がかかってしまう
毎回コマンドを間違えた際に問い合わせしてしまうと、作業効率の低下になるため出来れば設定した方が良い
※DNSサーバによる名前解決が必要な場合は別


####exec-timeout XX XXまたはno exec-timeout(exec-timeout　分　秒、conf t→line console 0)
コンソールからのタイムアウトでログアウトするまでの時間
デフォルトでは10分
sh runのline con 0から設定を確認可能


####logging synchronous (conf t→line console 0)
コマンド入力中などにルータからのメッセージによりコマンドが分割されるのを防ぐ
logging synchronousはline vtyにも設定出来る
※no logging synchronousでこの設定を削除可能


####enable password XXXX
暗号化されない特権モードのパスワード


####enable secret XXXX
暗号化される特権モードのパスワード
暗号化されないものと暗号化されるものどちらも設定すると、secretの方が優先されてenable passwordの方は使われないため
通常はenable secretのみ設定する
※sh runで確認


```
conf t→line console 0
password XXXX
login
```
※上から一行ずつ打つ、XXXXには設定したいパスワードを入れる

上記を打った後、logout→Enterでパスワード入力画面になる
※他にもline aux 0でauxパスワードの設定、line vty 0 4でvty(telnet)パスワードの設定ができる


####service password-encryption (conf t)
デフォルトでは暗号化されないパスワードを暗号化する(console、aux、vtyや特権モードの暗号化されていないパスワードも)
現在設定されているパスワードも今後設定するパスワードも暗号化することが出来る
※設定を戻す際はno service password-encryption
→今後設定するパスワードのみ暗号化されなくなる(暗号化せずに設定済みの特権モードパスワードは暗号化されない)


####sh ve (show version)
IOSのバージョンやインターフェイスの種類と数がわかる


####sh fla (show flash:)
フラッシュメモリ内のIOSを確認できる
デザイナーが始めるPostCSS


<h2>はじめに</h2>
Webアプリのデザインにあたり、より効率よくCSSを作成するためにPostCssを導入しました。
導入手順と追加したプラグインを簡単にご紹介します。

<h2>PostCSSとは</h2>
PostCssとはNode.js製のモジュールでCSSをコンパイルできるツールです。
Cssをコンパイルするという点では、SassやLessと基本的には同じようなものだと思います。

PostCSSの特徴
・とにかくコンパイルが早い
・はmixinや変数などの機能1つ1つがプラグインになっており、それらをいれることで使用できる
・プラグイン によっては将来取り入れられる標準公文も使用可能

Sassは複数の機能がパッケージになっているため、使わない機能までついてしまいますが、
PostCssなら必要な機能のみ選んで導入できます。

<h2>PostCssのインストール</h2>
タスクランナーはgulpを使用しています。

コマンドラインでインストールします。

```
$ npm init                 //任意の値を入れてpackage.jsonを生成
$ npm install gulp --save-dev          //Gulpをインストール
$ npm install gulp-postcss --save-dev  //PostCSSをインストール
```

gulpfile.jsを作り、package.jsonと同じ階層に置きます。
gulpfile.jsの中身はこちら

```ruby:gulpfile.js
var gulp = require('gulp');
var postcss = require('gulp-postcss');

gulp.task('css', function () {
  var plugins = [
  ];
  return gulp.src('./css/src/style.css')
    .pipe(postcss(plugins))
    .pipe(gulp.dest('./css/dest'));
});
```

<h2>プラグインのインストール</h2>
プラグインは現在300以上あるようです。
一覧は<a href="http://creator.dwango.co.jp/5146.html">こちら</a>

<h3>今回導入したプラグイン</h3>

<b>cssnext</b>
 ベンダープレフィックスを付与するAutoprefixer、メディアクエリーのパラメーターに名前を付けられるようにするCustom Media、変数定義ができるsimple-varsやcustom-propertiesなどの複数の機能を含んだプラグイン

<b>nested</b>
入れ子表記ができる

<b>import</b>
別ファイルの読み込みができる

<b>preces</b>
Sass同様に$を使った変数を使用できる

コマンドラインでそれぞれのプラグインをインストールします。

```
$ npm install postcss-cssnext --save-dev
$ npm install postcss-nested --save-dev
$ npm install postcss-import --save-dev
$ npm install precess --save-dev
```
gulpfile.jsにインポートしたパッケージを追加します。


```ruby:gulpfile.js
var gulp = require('gulp');
var postcss = require('gulp-postcss');
var cssnext = require('postcss-cssnext'); 
var precss = require('precss'); 
var nested = require('postcss-nested'); 
var cssimport = require('postcss-import'); 

gulp.task('css', function () {
  var plugins = [
    cssimport,
    cssnext,
    nested,
    precss,
  ];
  return gulp.src('./css/src/style.css')
    .pipe(postcss(plugins))
    .pipe(gulp.dest('./css/dest'));
});
```
今回はstyle.cssに複数のcssをインポートするので、コンパイル元は、style.cssのみを
指定しています。
※taskに追加する際、cssimportを一番上に配置しないとコンパイル時にエラーになるのでご注意ください。

<h2>CSSをコンパイルする</h2>
CSSを作成します。
ブレイクポイントの設定とカラー設定は別のCSSで作成し、style.cssにインポートします。

```ruby:/css/src/color.css
$text:#000;
$bg:#F5F5F5;
$shadow:rgba(0,0,0,.16);
```

```ruby:/css/src/breakpoint.css
@custom-media --sp (max-width: 480px);
```

```ruby:/css/src/style.css
@import 'color.css';
@import 'breakpoint.css';

.container{
  color:$text;
  display: flex;
  background-color: $bg;
  .card{
    box-shadow: 0px 3px 6px $shadow;
    &_ttl{
      font-size: 18px;
    }
  }
  @media(--sp){
    display:block;
  }
}
```

コマンドラインで、CSSをコンパイルします。

```
$ gulp css
```

コンパイルされたCSSは以下になります。

```ruby:/css/dest/style.css
.container{
  color:#000;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  background-color: #F5F5F5;
}
.container .card{
    box-shadow: 0px 3px 6px rgba(0, 0, 0, .16);
  }
.container .card_ttl{
      font-size: 18px;
    }
@media (max-width: 480px){
  .container{
    display:block;
  }
}
```
無事にコンパイルできました。

デザイナーでも簡単に使えますので、
ぜひ、大規模なWebサービスのコーディングの時には使ってみてはいかがでしょうか。
svgタグを使って描いた物にリンクをつける方法

#やり方
aタグでsvgタグ全体を囲んでもリンク化することはできない。svgタグ内の図形をaタグで囲みxlink:href属性でリンク先を指定する。

~~~HTML
<svg>
  <a xlink:href="#">
    <path></path>
  </a>
</svg>
~~~

#参考
[SVGを使うときに知っておくといいことをまとめました - Qiita](https://qiita.com/manabuyasuda/items/01a76204f97cd73ffc4e)
[SVGアイコンを実⽤するために知っておきたい、リンク周りの記述⽅法 | Webクリエイターボックス](https://www.webcreatorbox.com/tech/svg-icon-link)
CatalinaでHomebrewのbrew updateがイカれたので対処した 

# 環境

- MacBook Pro (16-inch, 2019)

- macOS Catalina 10.15.7

# エラーの内容

突然以下のエラーが出て，Homebrewのアップデートができなくなった．

```
$ brew update
  Error: homebrew-cask is a shallow clone. To `brew update` first run:
    git -C "/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask" fetch --unshallow
```

# 対処法

以下をターミナルで入力しただけ．

```
$ brew untap homebrew/cask
$ brew tap homebrew/cask
```

# 結果

```
$ brew update
$ brew upgrade
```

どちらも無事にできるようになった．

# ちなみに

```
$ git -C "/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask" fetch --unshallow
```

を入力しても直らなかったので今回の方法を試した．

# 参考

https://stackoverflow.com/questions/65168050/original-brew-update-error-needs-to-run-git-fetch-unshallow-but-got-another-g/65169643
テスト自動化の文化を根付かせるために大切なこと

ここ数年ですっかり定着した「テスト自動化」「自動テスト」
「テスト自動化」「自動テスト」調べるとテスト自動化、自動テストが大きな成果を上げていると書かれている記事が多くあります。
ただ華々しい成功の裏には泥臭い失敗も数多く存在します。

今回はそんなテスト自動化を開発プロセスに根付かせる上で、
私個人が**大切だと思うポイント全４項目**について記事にしたいと思います。


**注意**
・特に記述がない場合は、E2Eテストのテスト自動化について指しています。


# ポイント１：自動化の目的が明確になっているのか

テスト自動化をするとなった目的は何でしょうか？
・流行っているから
・上司に言われたから
・テストがいけてないから
・他社の成功例を聞いてやってみたくなったから
・品質を上げたい
・ヒト、カネを節約したいから
・コスト削減したいから

テスト自動化をやることが目的になっていないでしょうか？
なぜテスト自動化をやるのかの目的を明確にしておかないと、**ダメなテスト自動化**となることがザラです。

テスト自動化で成し遂げたい目的を明確にしないと、それは失敗に終わるでしょう。

# ポイント２：テスト自動化でテストすることが明確になっているか

今まで手動でやっていて効果が低かったテストを自動化しても、それはあまり意味がありません。
・そのテストケースで、何を確認したいのかが分からない
・テスト実施者によって結果が異なる
・テスト設計やテストケース作成がちゃんと出来ていない

上記のような場合、むしろコストが高くなる場合もあります。

テスト自動化研究会が発表している「テスト自動化の８原則」というものがあります。
これについては、別記事にまとめていますので興味のある方がいましたらご一読いただけると幸いです。
[テスト自動化の８原則について](https://qiita.com/Y_MAGARI000/items/cd080ebffa8abda1c8be)

■ テスト自動化の8原則（抜粋）
**1. 手動テストはなくならない**
**2. 手動でおこなって効果のないテストを自動化しても無駄である**
**3. 自動テストは書いたことしかテストしない**


# ポイント３：自動化要員を設けている
テスト自動化　を行うにあたり、世の中には多くのツール・ライブラリが存在します。
有名なところだとMFE社のUFT、Seleniumなどがあります。
これらの特徴として、**コーディング、プログラミング**することが必要となります。

手動テストしかやったことのないテスターさんには、ここがテスト自動化の大きなハードルとなるかと思います。
逆にコードを書いている開発メンバーですと、コードは書けますがテスト知識が不足していて良いテストコードが書けない場合があります。

**テストの知識を持っていて、かつプログラミングスキルを持つ人がテスト自動化を継続するのには大切になります。**

このようなバランスの取れたスキルセットを持つ人は多くありません。

だからこそ専門の要員を立てる必要があります。

開発者が隙間時間に自動テストを導入しても、それは多忙になると放置されることが多々あり、メンテナンスがされず
「自動化？やったんだけど～、使っていないんだ。」ってことになります。

# ポイント４：プロセスに組み込む

テスト自動化を導入する場合、既存のテストフェーズへ自動テストを組み込もうとする組織が多く存在するかと思います。
ですが、自動テストは手動テストとは違い開発に近いプロセスで動いていきます。
そのため、既存のテストフェーズに組み込むと多くの場合自動テストに割ける時間が少なくなり、
自動化を担当するメンバーの負担が大きくなってきます。
そうなると結果的に「自動化する暇があったら手動でやった方が早い」という心理になりがちです。

こういったことを回避するために、自動テストは自動テストで新たにプロセスに組み込むことが必要となってきます。
プロセスに埋め込むことで、自動テストが独立したプロセスと認識ができ、
プロジェクト終了時の評価などで「自動テストのプロセスが完了していないけど」など多くのことが見えるようになってきます。

組織の上の人たちは目に見える形の進捗が大好きです。その上の人たちに「自動テストは独立したプロセス」と認知してもらうことで、
より自動テストに集中して取り組むことが可能となってくるのだと私は思っています。


# おわりに

テスト自動化を根付かせるために大切だと思うポイントを４つ記載してきました。
ここであげたこと以外にも自動化文化を根付かせることが数多くあります。

このポイント１でもそうですが、大前提としてなぜ自動テストをやるのか。これが一番重要になってくるのかと思います。

・自動テストが流行っているから自動テストをやれ
・テストの回数を増やして品質を上げたい。だから自動化をやりたい

前者と後者のような組織があった場合、どちらの組織が自動化に失敗するかを考えた場合、結果は明白です。

**自動化が目的となっている組織、自動化はあくまでも目的を達成するための手段の1つ**

このことを念頭に入れて自動化活動をするかしないか。
それだけで自動化が上手くいくかが見えてきます。
Server Tomcat vx.x Server at localhost was unable to start within 45 seconds.

# 事象 : Tomcat起動時にエラーになった
- 環境
    - CentOS Linux release 7.9.2009 (Core)
    - Apache Tomcat/8.0.21
    - Eclipse IDE for Enterprise Java Developers. Eclipse IDE for Enterprise Java Developers.

```bash
# 英語の場合:
Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
# 日本語の場合:
サーバー ローカル・ホスト の Tomcat8 (Java8) は 45 秒内に始動できませんでした。サーバーがより多くの時間を必要とする場合、サーバー・エディターでタイムアウトを大きくしてください。
```

## 原因 : Javaの処理が重くてTomcatのタイムアウトにひっかかった
参考 : [Apache Tomcatサーバの起動時のデフォルト 45秒のタイムアウト時間の変更方法 (Eclipseで Tomcat Serverを起動する時に 45秒のタイムアウトが発生して起動できない場合の対処方法)](http://www.neko.ne.jp/~freewing/software/apache_tomcat_eclipse/)

Tomcatのデフォルトではタイムアウトは45秒です。

### 対応 : タイムアウトを伸ばす
1. [Servers]タブ > 使っているTomcatをダブルクリックして設定を開く
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/7ac0218d-1add-9606-4f47-991c9d524e7c.png)
1. [Timeouts] > [Start(in seconds)] > 手ごろな値に修正 > 保存(Ctrl + S)
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/aad9fc7d-481f-a09b-ab05-518a86e63da5.png)
1. もう一度Tomcat起動
Polygonからの距離を算出する関数を活用する【OpenSiv3D】

OpenSiv3D には Polygon からの距離を取得する関数 Geometry2D::Distance があります。この関数を使うと様々なエフェクトを作成したり、数値最適化に活用できます。今回は、マウスで描いたポリゴンから距離を算出して、等高線を描くサンプルを紹介します。

![20201208-154801-025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34295/deb2ad70-f6e4-44c5-47e7-02d960ec7606.png)

```cpp:Main.cpp
# include <Siv3D.hpp>

void Main()
{
	// キャンバスのサイズ
	constexpr Size canvasSize(800, 600);

	// ペンの太さ
	constexpr int32 thickness = 4;

	// 書き込み用の画像データを用意
	Image image(canvasSize, Color(0, 0));

	// 表示用のテクスチャ（内容を更新するので DynamicTexture）
	DynamicTexture texture(image);

	// 作成した Polygon の配列
	Array<Polygon> polygons;


	//等高線
	Array<MultiPolygon> contours;

	//等高線の数
	constexpr size_t contourNum = 20;

	//等高線の感覚
	constexpr double offset = 20.0;

	while (System::Update())
	{
		// ペンの色
		const Color penColor = HSV(polygons.size() * 20);

		if (MouseL.pressed())
		{
			// 書き込む線の始点は直前のフレームのマウスカーソル座標
			// （初回はタッチ操作時の座標のジャンプを防ぐため、現在のマウスカーソル座標にする）
			const Point from = MouseL.down() ? Cursor::Pos() : Cursor::PreviousPos();

			// 書き込む線の終点は現在のマウスカーソル座標
			const Point to = Cursor::Pos();

			// image に線を書き込む
			Line(from, to).overwrite(image, thickness, penColor);

			// 書き込み終わった image でテクスチャを更新
			texture.fill(image);
		}
		else if (MouseL.up())
		{
			// 画像の非透過部分から Polygon を作成（穴無し）
			if (const Polygon polygon = image.alphaToPolygon(1, false))
			{
				// 少し単純化してから追加
				polygons << polygon.simplified(2.0);
			}							
			

			{				
				Array<double> distances;
				Grid<double> distanceGrid(image.size());
				contours.clear();

				for (auto p : step(distanceGrid.size()))
				{
					for (const auto& polygon : polygons)
					{
						distances << Geometry2D::Distance(p, polygon);
					}

					const double distance = *std::min_element(distances.begin(), distances.end());

					distanceGrid[p.y][p.x] = distance;

					distances.clear();
				}

				for (size_t i = 0; i < contourNum; ++i)
				{
					// 画像データをリセット
					image.fill(Color(0, 0));

					for (auto p : step(distanceGrid.size()))
					{
						if (distanceGrid[p] < offset * i)
						{
							image[p] = penColor;
						}
					}

					// 画像の非透過部分から Polygon を作成（穴無し）
					if (const MultiPolygon polygon = image.alphaToPolygons(1, false))
					{
						// 少し単純化してから追加
						contours << polygon.simplified(2.0);
					}
				}
			}


			image.fill(Color(0, 0));
			// テクスチャを更新
			texture.fill(image);
		}


		//それぞれの 等高線を描画
		for (size_t i = 0; i < contours.size(); ++i)
		{
			contours[contours.size() - 1 - i].draw(HSV(i * 20, 0.4, 1.0)).drawFrame(4, HSV(i * 20));
		}


		// それぞれの Polygon を描画
		for (auto [i, polygon] : Indexed(polygons))
		{
			polygon.draw(HSV(i * 20, 0.4, 1.0))
				.drawFrame(4, HSV(i * 20));
		}

		// テクスチャを表示
		texture.draw();
	}
}
```