OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】2021年秋期応用情報受験記

# はじめに
2021年10月10日に開催された情報処理技術者試験を受験された皆さん、お疲れ様でした。
私は応用情報技術者試験を受験してきました。
試験から数日経ち、午後の解答速報も出そろったところで備忘録として記事を残します。

簡単ですが自分の経歴を少し記しておきます。

* SE歴15年以上
* 基本情報／初級シスアドを所持

今回応用情報を受験しようと思ったのは、昨年からインフラエンジニアへキャリアチェンジしており、現時点の自分の実力がどの程度なのかを応用情報試験で試したいと思ったからです。

ちなみに以前はJavaとCOBOLで業務システムを作成していましたが、あまり情報処理試験の知識を必要としない現場だったので、社会人になってからは国家試験取得をサボっていました。
そのため、情報技術者試験を受けるのは十数年ぶりになります。（前回受験した年を覚えていない）

#試験対策

試験対策として、７月ごろから[応用情報技術者試験ドットコム](https://www.ap-siken.com)様にて、直近２回分を除く過去問を10回分をひたすら解きまくりました。
勉強していくうちに、特に午後が苦手だということに気づき、９月以降はほとんど午後の対策をしていました。

最終的に試験前の正解率の平均は午前・午後ともに80％を超えていたので、本番でも楽勝だろうと思っていました。
（むしろ、問題を解きすぎて解答を覚えてしまっていた）

#午前

午後の事を考えて午前は早めに11時10分頃退室。
所感としては見たことある過去問が体半分程度、残りは見たことない問題で結構難しかった印象でした。

#午後

午後はセキュリティの他に以下の４つを選択。

* ネットワーク
* データベース
* 情報システム開発
* システム監査

＜セキュリティ＞
過去問をみっちりやってきたので対策はバッチリと思いきや、物理的なセキュリティの問題でかなりテンパってしまいました。
特に考え込んだのが、設問３の(1)と(4)で、ここでかなり時間を使ってしまい、時間使っても結局答えが分からなかった。

＜ネットワーク＞
設問１のaの解答がIPアドレスになるはずなのに、表２の項番１、３、４は「（省略）」との記載になっており、セキュリティでテンパってたこともあって「もしかしてこれはひっかけ問題か？」と疑心暗鬼になってしまい、「（省略）」と記載してしまう痛恨のミス。
また、設問４の(3)で総務部のみが１階に移動する問題を全ての部署が移動すると勘違いしてしまう。
ここは冷静に読んでれば２問確実に取れてたはず。

＜データベース＞
以前の現場でデータベースを触っていたこともあり、SQLを記述する設問は問題なくクリア。
受験当時は特に大きなミスはなかったと考えていたが、試験後に見返すと設問２の(2)や設問４の(2)を思い切り間違えていた。

＜情報システム開発＞
データベースまで終えた時点で残り50分ということもあり、駆け足で解答する羽目に。
駆け足で解答した割にはまぁまぁな記載できた印象だったが、実際はボロボロだった。
試験中はこの辺でだいぶ心が折れかけていた。

＜システム監査＞
残り時間20分でひたすら問題読んで解答書いての繰り返し。
何とか終了時間までに回答を埋めて試験終了。


#まとめ
自己採点の結果、午前は51/80で合格ラインで、午後は厳しめ採点で50点で不合格ラインでした。
易しめの採点でも60点まではいかないだろうといったところです。

試験直後は午後６割取れてるといいな。。。ぐらいの感触だったので、やはりといった感じでした。

試験後で冷静になって問題を見直すと、なんでこんな解答したんだ・・・という回答がチラホラ。

まだ正式な結果は出ていませんが、どんな結果でも今回受験して良かったと思っています。
今回久しぶりに情報処理試験を受けて、勉強している間も楽しかったし、試験本番も良い経験になりました。
また次春に受けるときは午後を落ち着いて受験できるように対策を練っておきたいと思います。

情報処理技術者試験を受験された皆さんも良い結果が出ることを祈っております。

#2022/01/07　追記
試験結果はやはり不合格でした。
午後は自己採点より若干取れてたので、部分点というか大筋で回答内容があっていれば点数もらえることが分かっただけでも収穫かと思います。
確実に取れる問題を取れなかったのが今回の不合格の原因だと思うので、2022春期の応用情報でリベンジしたいと思います！

![スクリーンショット 2022-01-07 204729.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1262522/1d5f17ef-b886-f716-d5fd-d5ce9fae1b32.png)
【フォーム】追加ボタンを押して関連した入力欄2つを同時に増やしていく方法

#はじめに
今回以下のようなフォームは作ったので、備忘録として残しておきます。
![スクリーンショット 2021-10-14 23.34.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1697283/80e628f3-5947-3bef-1c1a-b9c3636b2643.png)

#HTML部分

```php:create.brade.php
<label>{{ __('材料') }}
      <a onclick=add() class="btn btn-sm btn-light">+追加</a>
      <div id="input_plural">
          <div class="d-flex">
              <input type="text" class="form-control mb-1" name="ing-name-1">
              <input type="text" class="form-control mb-1" name="ing-size-1">
              <input type="button" value="削除" onclick="del(this)">
          </div>
      </div>
</label>
```

#javaScript部分

```javaScript:main.js
let inputPlural = document.getElementById('input_plural');
var count = 2;

function add() {
    let div = document.createElement('DIV');
    div.classList.add('d-flex');

    var input = document.createElement('INPUT');
    input.classList.add('form-control');
    input.setAttribute('name', 'ing-name-'+count);
    div.appendChild(input);

    var input = document.createElement('INPUT');
    input.classList.add('form-control');
    input.setAttribute('name', 'ing-size-'+count);
    div.appendChild(input);

    var input = document.createElement('INPUT');
    input.setAttribute('type', 'button');
    input.setAttribute('value', '削除');
    input.setAttribute('onclick', 'del(this)');
    div.appendChild(input);

    inputPlural.appendChild(div);
    count++;
}

function del(o) {
    o.parentNode.remove();
}
```

#おわりに
bootstrapを使ってちょっぴり整えているので、その点はご了承ください。
「git revert」の「git revert」がしたい！


```git revert```はコミットの取り消しを行うコマンドです。

表題の通り、取り消しの取り消しを行う必要があったのでまた発生したときに焦らない用メモです。

#なぜする必要があったか

1. プルリク発行⇒topicブランチにマージされた後、やっぱりおかしいのでは？とrevertされる

1. レビュアと話し合った結果、revertされた実装で合ってたという結論に至る

1. 「ごめんね、元の実装でプルリク出し直しておいて」と言われ、元のブランチから再度プルリクを出そうとしたが...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/874156/b93467fa-ea13-ec93-9d44-38582d0370d1.png)

変更あるって！と思いましたが、よく考えたら以下の図のようなことで取り込み済と判断されるのは当たり前でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/874156/644fb26c-f5f1-fe6c-ed55-bb899da81f3c.png)

commitID:abc123の作業はtopicブランチにマージ済なので「もう取り込んでるけど？」と言われていたのでした。

こうなったら取り消しの取り消しを行うしかない...。

#実際の手順

topicブランチをpullして新しいブランチを作成し、revertコミットをrevertしました。

```php
> git pull // 1.revertされた状態のtopicブランチに合わせる

> git checkout -b revert-revert // 2.新しいブランチを作成する

> git log // 3.revertのコミットIDを特定する

commit 456def.......... (origin/revert) // revertのコミットID
Author: レビュア
Date:   Thu Oct 14 05:16:11 2021 +0000

    Revert "イケてる実装 (pull request #001)"

commit 123abc..........
Author: shun.kondo
Date:   Thu Oct 14 05:14:41 2021 +0000

    イケてる実装

> git revert 456def // 4.revertのコミットIDを指定してrevert（取り消しの取り消し）

[<作業ブランチ名> <新しいコミットID>] Revert "Revert "イケてる実装 (pull request #001)""
 1 file changed, 1 deletion(-)

> git push --set-upstream origin revert-revert // 5.再度push!
```

無事に取り消しの取り消しを行い、元の実装の通りマージすることができました:v:

#他の方法もあるのか一応調べた

```git reset```でコミットのログごと消して```-f```オプションを付けて強制的にpushしてコミットログを綺麗にする...なんて方法もあるようです。

確かに「revert」「revertのrevert」とコミットログが並んでいるのはかっこよくはないですが、```git reset```はコミット自体がなかったことになるのでコンフリクトが起きやすいなどの弱点もあるようです。

なんにせよ作業の手順がそのまま残るのは悪いことではないと思うので、チーム開発では`git revert`を使用しておいた方が良い気がします。
onchangeイベントで確認ダイアログの結果に応じてキャンセル with jQuery

# 結論

Deferredとクロージャ使った。
もっとベターなやり方は山ほどありそう。

# なりゆき

やっほー☆フロント側をjQueryだけで開発しているみんな、こんにちは！
なんでこんなことになっているんだろうね！？うらむならプロジェクトをうらもう⭐️

突然だけど、プルダウンの変更時、変更前の情報を知りたいと思ったことはないかい！？

んー、そう？

ぼくはあります！今まで何度もありました！ていうか今日もありました！

んでまあ、過去の実装を参照してもいいんですけど、今の自分ならどうするか、って考えてあんまりみないことにしました。jQueryのみでなんとかしていることから分かる通り、プロジェクト自体が緩いので許される・・・・・・と思いたい。

# 考えたこと

## DOM側に情報を持たせる

多分、今までも大体これでやっていたはず。
確定したタイミングで`<input type="hidden" id="hidLastValue" />`みたいなやつに値を設定するとか。
全然悪くはないし、手っ取り早いし、いいとは思う・・・・・・。

でも責務がぶれてるかなあ・・・・・・？

HTMLは単なる構造化文書であって、サーバー側との送受信項目はまだしも、クライアント側のみで使う値をhiddenやdata-*属性で持たせる・・・・・・。

いや、悪くはない！ぼくも結構その手は使っている！

でも、他に方法はないかなあ・・・・・・？

## 微妙なプロパティの値を使う

実際全く微妙じゃないかもしれないけど！
調べたら結構あったんですよね、jQueryのこのプロパティは前の値で、DOM要素のこれは今の値、みたいなやつ。

いや、いいと思うんですよ。

でもそれ、コード自体が説明的じゃないよな・・・・・・・。

わたしがみたやつのイメージだと、ほんとわずかな書き方の違いだけでbefore-after切り分けていて、え、これ調べなきゃ前後比較してるってわかんねーだろ、みたいな。

あとそこまでいくと環境依存入らない？みたいな。


## わたしなりに頑張る

javascriptで値保持、と言えばグローバル変数。ほんとそれ、ではあるんだけど、書き換え可能。さっきのhiddenとかdata-*もそうだけど、ユーザーが容易に書き換えできるのは、もちろん要件次第ではあるんだけど、どうなの？っていう気持ちが強い。

バニラなjsでカプセル化っぽいことしたかったら、わたしが知る限りはクロージャ。

クロージャ、要するに参照されているかぎり変数生きてる、みたいな技。

以下、思い出しながら書いているので間違っていたらごめんなさい。

letとか使ってみたい


```javascript
$(document).on('change', '#selectElem', (function() {})(
  var lastValue = document.getElementById('selectElem').value;
  return function(e) {
    var def = new $.Deferred(); // ここのスペル自信ない:)
    confirm(function(result)) {
      result ? def.resolve() : def.reject();
    }); // ここの確認処理でYes/No判定
    def.promise().done(function(){ lastValue = e.taget.value; /* Yesのときは流れのまま */})
    .fail(function() { $('#selectElem').val(lastValue); /* 元に戻す */ });
  }
));
```
エンジニアスタイル東京とは

フリーランスのエンジニア・デザイナー向け求人・案件情報なら【エンジニアスタイル東京】で。言語、職種、フレームワークなどからフリーランス求人・案件をまとめて単価比較できます。
https://engineer-style.jp/
sed・gsedコマンドを使い、Automatorでアプリ化

#はじめに
sedとgsedコマンドを使用したスクリプトをAutomatorでアプリ化したのでまとめます。
アプリ化することで、1クリックで実行できるため、チーム開発時、コマンドが疎いメンバーにも実行することができるメリットがあります。

#2つのスクリプト
2つのスクリプトを作成しました。
`hostsファイルに一行挿入するコード`と`挿入した行を削除するコード`をアプリ化します。
このアプリを共有することで、hostsファイルの編集は、通常vimコマンドを用いて編集しますが、このアプリで各メンバーが簡単に実行することができます。

##hostsファイルに一行挿入するコード
`hostsファイルに一行挿入するコード`は、`sed`コマンドを使用しますが、macのデフォルトだと難しいので、`gnu-sed`をインストールします。

```
$ brew install gnu-sed
```
<br>
hostsファイルの8行目に`111.111.111.111 www.hoge.com`を加えるコード

```
$ sudo gsed -i -e "8i11.111.111.111 www.hoge.com" /private/etc/hosts

#もしくはこれでもできました
$ sudo sed -i '8i11.111.111.111 www.hoge.com' /private/etc/hosts
```
`-i`オプションは、ファイルの上書きをします。
`-e` オプションの方は、`「行追加したい行」` + `i` + `追加したい文字列`という書式で書きます。
`111.111.111.111`と`www.hoge.com`の間にはスペースをいれますので、空白の前に`\`を入れています。

hostsファイルの末尾の行に挿入したい場合`8i`ではなく`$ a`に変えます。
`8i11.111.111.111 www.hoge.com`→`$ a11.111.111.111 www.hoge.com`

<br>
##挿入した行を削除するコード
hostsファイルの`www.hoge.com`がある行を全て削除するコードです。

```
sudo sed -i -e  '/www.hoge.com/d' /private/etc/hosts
```
`'/www.hoge.com/d'`は、`/一致する文字列/` + `d`(削除)という書式になります。

#Automatorでアプリ化
`Automator`→`アプリケーション`→`ユーティリティ`→`シェルスクリプト`で以下の通りにコードを記載します。
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/365eda3e-26e1-e3fe-2353-8c222eccf49e.png">

hostsファイルの`www.hoge.com`がある行を全て削除するコードをアプリ化します。

```hosts:delete-hosts-file
domain="/www.hoge.com/d"
osascript -e 'do shell script "sudo sed -i,e '$domain' /private/etc/hosts" with administrator privileges'
```
`sudo`を使用するときは、パスワードを求められるため、
`osascript -e 'do shell script "sudo <コマンド>" with administrator privileges'`
というコードにする必要があります。

`実行し`、`ワークフローが完了しました`の表示が出ると、問題なくコードが実行されています。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/0e4f09b9-eb13-811e-697c-b858544e70b1.png">
<br>

次に、hostsファイルの8行目に`111.111.111.111 www.hoge.com`を加えるコードを実行します

```hosts:add-hosts-file
export PATH=$PATH:/usr/local/bin
osascript -e 'do shell script "sudo gsed -i,e \"8i11.111.111.111 www.hoge.com\" /private/etc/hosts" with administrator privileges'
```



###`export PATH=$PATH:/usr/local/bin`が必要な理由
Automatorでシェルスクリプトを実行するの環境は、ターミナルの環境依存を継承しないためgsedコマンドをそのまま使うことがでず、gsed command not foundエラーが発生します。つまりパスが通っていない状態です。
また、sudoを使用すると、PATHが設定し直されることがあるようです。

```terminal:error
アクション“シェルスクリプトを実行”でエラーが起きました: “0:112: execution error: sudo: gsed: command not found (1)”
```
<br>
`実行`し、`ワークフローが完了しました`の表示を確認しました。


finderの`Service`ディレクトリにあるアプリをクリックすると、コードが実行されるようになりました。
・hosts:delete-hosts-file
・hosts:add-hosts-file

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/cf135e7c-ea3d-9018-1de0-7a747a6a6842.png">

#参考
[MacとLinuxでは、sedの動作が異なるので注意](https://it-ojisan.tokyo/mac-linux-sed/)
[macOS標準sedをGNU sedに置き換える](https://qiita.com/yohhoy/items/f026173bfb70cad52f8a)
[sedコマンドの使い方](https://qiita.com/hana_shin/items/eb61f970456ff96ef14c)
[MacのAutomatorでnpmコマンドを使う](https://qiita.com/07JP27/items/db402c1a2028d56ce42a)
Udemy「ネットワークエンジニアを目指す初心者はここから始めよう！「ゼロから学ぶネットワーク基礎」1013

本日からUdemyで「ネットワークエンジニアを目指す初心者はここから始めよう！「ゼロから学ぶネットワーク基礎」を学習します。


データ
・コンピュータが扱う情報のこと。

・データの内容はそのつど変化する。

・データを送り合うことを通信（送信、受信）と呼ぶ。


有線ネットワーク

・ケーブルで接続されているネットワーク全般を指す。

・デスクトップ型のパソコンなどで多い。



無線ネットワーク

・スマホや携帯電話、wifiや無線LANもその一つ。
『Linuxで動かしながら学ぶTCP/IP入門』でネットワークの基礎実践（Docker環境つき）

基本情報・応用情報技術者試験を勉強する中で、ネットワーク系の箇所に苦手意識があったので、ネットワークの基礎がわかる・自分で手を動かしながら学べる書籍を探していたところ、[『Linuxで動かしながら学ぶTCP/IP入門』](https://www.amazon.co.jp/exec/obidos/ASIN/B085BG8CH5/momijiame-22/)を見つけました。  

「ネットワークの初歩」的な内容ですが、今まであった所謂解説本とは異なり、実際にpingやtcpdumpコマンドを使いながら疎通を覗くことで、パケットやEthenetヘッダーの動きを知ることができます。   

以下、各章で学ぶことができる内容を簡単にまとめました。このあたりの理解に不安がある方は、手を動かしながら学んでみることをおすすめします。  

なお、書籍内では、検証に使用するLinux環境（Ubuntu）は実機またはVagrantを紹介していますが、実務でDockerを使用する機会が多かったので、***Docker***でUbuntu環境を構築しました。  

## 環境構築   
-DockerFile  
-docker-compose.yml

```[DockerFile]
FROM ubuntu:20.04

# 検証に使用するモジュールのインストールをしておく
RUN apt-get update
RUN apt-get -y install \
    bash \
    coreutils \
    grep \
    iproute2 \
    iputils-ping \
    traceroute \
    tcpdump \
    bind9-dnsutils \
    dnsmasq-base \
    netcat-openbsd \
    python3 \
    curl \
    wget \
    iptables \
    procps \
    isc-dhcp-client
```

```[docker-compose.yml]
version: '3'

services:
  ubuntu:
    build: .
    working_dir: /var/tmp
    volumes:
        - ./work:/var/tmp
    # コンテナ起動後、StatusがExitにならないようttyの設定
    tty: true
    privileged: true
```


## TCP/IPとは
- TCP/IP・プロトコル・パケット・IPアドレス・ヘッダなどの基礎項目のおさらい
- pingの結果が読める
- tcpdumpでping(icmp)の通信をキャプチャできる・その内容がわかる
- 端末からルーターを通してインターネットに繋がるイメージをつかむ


## Network Namespace
- ```netns```コマンドを利用して、同一セグメント内（ネットワークアドレスが同一）の仮想ネットワークを作成できる
- ```netns```コマンドを利用して、ルーターを経由し、セグメントが2つのネットワークを作成できる
- ルーティングテーブルの内容を理解できる
- ```netns```コマンドを利用して、セグメントが3つ（ルーターが2つ）のネットワークを作成できる


## イーサネット
- IPのパケット
  - トランスポート層
  - IPアドレスを使用して送信元・送信先を判定
- イーサネットのフレーム
  - データリンク層
  - MACアドレスを使用して送信元・送信先を判定
- ```netns```コマンドを利用して、MACアドレスを基準としてパケットがイーサネットのフレームで運ばれる様子をtcpdumpでキャプチャできる
- 同一セグメント内のイーサネットのフレームの動きを観察できる
- セグメントが2つに増えた場合、イーサネットのフレームが変わる様子を観察できる
- ブリッジの仕組みを理解し、同一のブロードキャストドメインに複数のネットワーク機器をつなげる方法を理解する
  - ブリッジ：それぞれのポートに繋がっているMACアドレスを学習して、必要なポートにだけフレームを転送する


## トランスポート層のプロトコル
- アプリケーションとポート番号の関係性
- ```nc```コマンドを使い、UDPで文字列を送受信する
- 信頼性のあるトランスポート層のプロトコルでTCPを使用する。スリーウェイハンドシェイクによってコネクションを確立した上でデータの送受信を行う流れを観察する


## アプリケーション層のプロトコル
- HTTPサーバを立てて、疎通・データの流れをキャプチャできる
- DNSでの名前解決の仕組みについて説明できる。OS内部のリゾルバによる挙動によってコンピュータ内部（hostsファイル）と外部（DNSサーバ）で異なる点について理解できる
- DHCPプロトコルでコンピュータのネットワークを自動的に設定する仕組みについて理解できる


## NAT
- グローバルIP・ローカルIPアドレスの違いが理解できる
- NAT・NAPTの仕組みを理解できる
- ```netns```で仮想LAN・WANを作成し、仮想LANの送信元IPアドレスがグローバルIPアドレス（＝ルーターのアドレス）に書き換えられる挙動を仮想WAN側で観察できる（SourceNAT）
- ```netns```で仮想LAN・WANを作成し、仮想WANの送信先IPアドレスがローカルIPアドレス（＝LAN内の特定のパソコン）に書き換えられる挙動を仮想LAN側で観察できる（DestinationNAT）


## ソケットプログラミング
- ソケットプログラミングとは
- ソケットの仕組みをPythonスクリプトで再現し、ソフトウェアからTCP/IPをどのように扱っているのかを理解する


## 最後に
今まで、用語だけ覚えて何となくの理解しかできていなかった部分について、  
実際にデータの流れを追うことで、落とし込むことができたかなと思います。
Rust: proc macro server crashedではまった

## 環境
- rustc 1.55.0 (c8dfcfe04 2021-09-06)
- rust-analyzer v0.2.776
- Windows10

## 背景
WindowsでVScodeでrust開発していたのだが、あるコード行(struct宣言部分)でrust-analyzerのエラーが発生するようになった。

メッセージは、以下のものだった。

```
proc macro server crashed
```

## 解決法
以前は動いた気がしたので、rustのバージョンを下げた。  
具体的には1.52.1に下げた。

```shell
$ rustc -V
rustc 1.55.0 (c8dfcfe04 2021-09-06)
$ rustup install 1.52.1
...
...
1.52.1-x86_64-pc-windows-msvc installed - rustc 1.52.1 (9bc8c42bb 2021-05-09)
$ rustup default 1.52.1
info: using existing install for '1.52.1-x86_64-pc-windows-msvc'
info: default toolchain set to '1.52.1-x86_64-pc-windows-msvc'

  1.52.1-x86_64-pc-windows-msvc unchanged - rustc 1.52.1 (9bc8c42bb 2021-05-09)
```

## 備考
1.52.1じゃなくても大丈夫かもしれませんが、とりあえずそこまで下げたら動きました。
にしても、rust-analyzerが重い。
WSL2でやったほうがまだましなのかな。。

## 参考
https://github.com/rust-analyzer/rust-analyzer/issues/6755
NanoPiのMicroSDをコピーする方法

## はじめに
NanopiのMicroSDの破損に備えて、MicroSDのコピーを取っておきたいとか、設定済みのMicroSDを大量にコピーしたい。
そんな時は次の方法でコピーを作成することができます。

##
PCにWin32DiskImagerをインストール

## 手順
MicroSD→PCへのイメージの吸い上げ
1. NanoPiからMicroSDを抜き、PCに接続したSDカードリーダに挿入。 
2. PCで空のファイルを作成し、拡張子を「img」にする。
3. Win32DiskImagerを起動
4. Image Fileに3.で作成したファイルを指定する
　 DviceにSDカードリーダーに割り当てられたドライブ名を指定する。
5.「Read」ボタン

PC→MicroSDへのコピー
1. PCに接続したSDカードリーダに空のMicroSDを挿入。 
2. Win32DiskImagerを起動
3. Image Fileに3.で作成したファイルを指定する
　 DviceにSDカードリーダーに割り当てられたドライブ名を指定する。
4.「Write」ボタン

以上


6.「Read」ボタン
Gitの初期設定でブランチ名をmasterからmainに変更できないときの原因と解決方法

# エラー内容

```git init```の実行後、```git branch -M main```を実行すると、以下のようなエラーが出る。

```
% git branch -M main
error: refname refs/heads/master not found
fatal: Branch rename failed
```

# 解決方法

```README.md```ファイルを新規作成し、```git add```実行後に```git commit```を実行するとエラーは解消され、mainブランチを作成することができる。

```
% touch README.md
% git add README.md
% git commit -m "initial commit"
% git branch -M main
```

上記コマンドを実行後に```git branch```コマンドでブランチ一覧を確認し、mainブランチが作成されていれば成功です！

```
% git branch
* main
```

# エラーの原因
ブランチはコミットへのポインタであるため、コミットが未作成の場合ブランチは存在しません。そのため、存在しないブランチの名前を変更することはできません。

なので、最初のコミットを行うことでブランチが作成され（デフォルトではmaster）、それから（ブランチが存在するので）名前を変更できるようになります。
マザーボードの電池とPCの故障

タイトルは良い案が思いつかなかったのでキーワードを詰めた．
体験しないと意外と気づかない見落としだと思ったのでメモとして残す．

# TL;DR
電源を入れても(UEFI) BIOSが起動しない時はマザーボード上の電池が原因の可能性がある．

# 事件
PCの電源を入れてもOSが立ち上がらない・・・
どころか，まず**BIOSまで行き着けていない**，という事態が発生した．
（実はこの事件が起きる少し前から近い症状が出ており，物理的に何回かリブートすると直るのでHWの寿命が近そうとは感じていた．）

# 症状
### 電源は入る
- 電源が入ると言うことは，電源ユニットからの電力は問題なく供給されている（必要な量の電力内）．
- そもそも，前回までは起動していた上に，特にパーツの追加・交換等は行っていない．

### BIOSに入れない（そこまでいかない）
- 電源投入後，画面出力がない．
- GPU経由で画面出力を行なっていたため，最初はGPUの故障，あるいはケーブルの断線を疑った．

### USBに電力が供給されない
- 途中で気づいたが，キーボード，マウス等に電源が供給されていないのが分かった．
- （正確にはゲーミングデバイスなので，光らなかったというのが正しい）

# 解決の試み
PCが起動しない場合，大抵はメモリエラー（接触不良）のようなケースが多い（私個人の経験上）のだが，今回はそもそも，電源投入後は画面出力がないまま，電源が入ったままであった．
そのため，可能性が低そうであるが，

- メモリを全て外し一枚だけ挿して起動した．
- GPUを外し，マザーボードからの出力にした．（この時使えるケーブルなのかも確認を行った）

が，症状は改善しなかった．
よって，（手軽にできる最後の手段として）大抵の人がよくわからんがやる伝家の宝刀CMOSクリアを実行した．

***なんとBIOSまで起動できたのである***．

これにて一件落着・・・ならこの記事は書いていない．
CMOSクリアを行ったため，Windowsの時刻がリセットされてしまっているのでNTPにより時刻合わせを行い，再起動したのである（Valorantをプレイするには致し方なかった）．

***なんと同じ症状に戻ったのである***．
こいつ（PC），私を弄んでやがる・・・などと言ってる場合ではない．
再びCMOSクリアを敢行．

***BIOSまで起動できたのである***．そして案の定，***同じ症状に戻ったのである***．

何度かCMOSクリアのくだりを行い，一つ分かったことは，BIOSそのものに問題がある可能性である（デフォルト設定をリストアすると起動するので）．
（正直なところ，ここでもうマザーボードの寿命だと思い諦めるつもりだった．）

一応ネットのありがちな，「PCの故障と解決方法！」みたいなページを読んでいると，「時間がリセットされるならマザーボードの電池が原因かも！？」のような内容が目に入った．ここでふと思ったのだ，マザーボードの電池ってBIOS等の時間・設定を記録しているだけだよな？

調べるとHP社の[あるページ](https://www.hp.com/us-en/shop/tech-takes/what-is-cmos-battery-how-to-remove-and-replace)の"How do I know my CMOS battery failed?"の下に”The laptop has difficult booting up”の記述がある．
つまり，***電池が原因でブートできない可能性がある***ということを大手メーカーが教えてくれたのだ．
（実を言うと，その前でそういう可能性があるというのは，他のサイトで記述はあったのだが，引き起こされる理由から眉唾物だと思っていた．これぞ権威主義．）

# 解決
CR2032（おそらくどのマザボもこれ）のボタン電池を買い，入れ替えることで無事解決された．
（実際には入れ替えただけでは起動せずCMOSクリアを行っている．）

# あとがき・考察
それなりに解決に時間がかかったのだが，その原因は，マザボの電池というのは時間と設定を保存しているだけで，電池が無くなったらそれがリセットされ，クソ不便ではあるが起動には問題ないという認識があったためであった．
なので，そもそもマザボの電池って実際にはなにをやってるんだ？を調べようとしたが，なかなかそういう記事が見つからず，つまりは基板を直接見ろ！ということのようだが，私にはわからないので諦めた．

一つ思うのは，電池とは急に電圧０になるわけではないので，電圧が低くなった結果CMOSに書き込む/読み込む内容が，おかしくなったのではないかと考えている．デフォルトの設定はROMに入っているであろうから，他に今回のようなことが起きる要因が私には思いつかない．
【Swift】UIAlertControllerやUIAlertActionを手軽に実装できるライブラリ「Alertift」の操作

SwiftでUIAlertControllerやUIAlertActionを実装するとコード量が多く見辛いというデメリットが有る。

そんな悩みを解決してくれるのが「Alertift」というライブラリ。
## 基本情報
Alertiftの基本情報。

CocoaPodsまたはCarthageで導入可能。

https://github.com/sgr-ksmt/Alertift

## 実装コード

実際に実装すると以下のようになる。

```swift
Alertift.alert(title: "タイトル", message: "メッセージ")
.action(.default("OK")) { [unowned self] in
    print("OK")
}
.action(.destructive("削除")) { [unowned self] in
    print("delete")
}
.action(.cancel("キャンセル"))
.show(on: self)

```
最後の`.show(on: self)`がないと表示されないので注意が必要。

`UIAlertController.Style.actionSheet`を実装したい場合は以下の通り。

```swift
Alertift.actionSheet(title: "タイトル", message: "メッセージ")
.action(.default("OK")) { [unowned self] in
    print("OK")
}
.action(.destructive("削除")) { [unowned self] in
    print("delete")
}
.action(.cancel("キャンセル"))
.show(on: self)
```
UITextFieldを組み込みたい時は以下の通り。

```swift
Alertift.alert(title: "タイトル", message: "メッセージ")
.textField { textField in
    textField.placeholder = ""
}
.handleTextFieldTextDidChange { textField, index in
    print(textField.text ?? "")
}
.action(.cancel("キャンセル"))
.show(on: self)
```

## 参考文献

https://github.com/sgr-ksmt/Alertift

https://qiita.com/sgr-ksmt/items/b5e29805f4f834470023

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
【JavaScriptのメモ】OKやキャンセルのダイアログを表示する関数

今回は、JavaScriptで使用される基礎的なダイアログを表示する関数を紹介します。

confirm()
```JavaScript
confirm('文字列')
```
confirm()においては、戻り値が意味を持ちます。
戻り値はTrue、Falseの二種類で
OKを押せばTrueでキャンセルを押せばFalseを返す仕組みになっています。

confirm()とalert()の違いは、ボタンの数
alert()はOKだけですが、confirm()はボタンがOKとキャンセルの二つです。
prompt()はボタンがOKとキャンセルそして、テキスト入力エリアが表示されます。
【python】モンティホール問題

# モンティホール問題とは
プレーヤーの前に閉じた3つのドアがあって、1つのドアの後ろには景品の新車が、2つのドアの後ろには、はずれを意味するヤギがいる。プレーヤーは新車のドアを当てると新車がもらえる。プレーヤーが1つのドアを選択した後、司会のモンティが残りのドアのうちヤギがいるドアを開けてヤギを見せる。

ここでプレーヤーは、最初に選んだドアを、残っている開けられていないドアに変更してもよいと言われる。
ここでプレーヤーはドアを変更すべきだろうか？

wikipediaより引用
https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3%E3%83%BB%E3%83%9B%E3%83%BC%E3%83%AB%E5%95%8F%E9%A1%8C

## pythonによるシミュレーション

```monty_hall.py
import random

def monty_hall(n_trial=1000, change_door=True):
  n_wins = 0
  for i in range(n_trial):
    doors = [0, 0, 0]
    win_place = random.randint(0, 2)
    doors[win_place] = 1
    choice = random.randint(0, 2)

    # ハズレドアの１つを公開
    if doors[choice] == 0:
      revealed = 3 - choice - win_place
    else:
      revealed = (choice + random.randint(1, 2)) % len(doors)

    # ドアを変えたければ変える
    if change_door:
      choice = 3 - revealed - choice
    
    if doors[choice] == 1:
      n_wins += 1
    
  return n_wins

n = 1000
print("ドアを変えた場合 : {} 回中勝ち {} 回。".format(n, monty_hall(n_trial=n, change_door=True)))
print("ドアを変えない場合 : {} 回中勝ち {} 回。".format(n, monty_hall(n_trial=n, change_door=False)))
```
ドアが３つしかないのでドアインデックスの和を利用することで少し簡潔に書くことができる。

結果

```
ドアを変えた場合 : 1000 回中勝ち 668 回。
ドアを変えない場合 : 1000 回中勝ち 354 回。
```
【Laravel】ルートパラメータの渡し方

#はじめに#
　URLにパラメータを渡して、それをコントローラーで受け取る方法をメモしておきます。
Webページを作るのにとても便利です。

#view#
まずはリンクを設定します。
bladeテンプレートにこのように書いていきます。

```php:view.blade.php
<a href="{{ route('index',['id' => 1]) }}">テスト</a>
```

route関数の第二引数にこのように指定していきます。
ここでは直接数字を入れていますが、データベースから取得してきたデータのIDなどを入れるパターンが多いと思います。


#ルーティング#
web.phpにはルーティングを書いていきます。

```web.php
Route::get('/index/{id}', [HomeController::class, 'index'])->name('index');
```

URLには先ほど　bladeテンプレートのaタグで指定したidが入ります。
ルーティングのURlが指定されてリクエストが送られると、コントローラーのメソッドが呼び出されます。


#controller#
コントローラーのメソッドはこのように記述します。

```controller.php
public function index($id)
{
    $post = Post::where('id',$id)->first();
    return view('index',compact('post'));
}
```

あくまで一例ですが、こんな感じで取得してきたidをEloquentのwhere句に使ったりすることで、特定のデータを取得することができます。

あとはview側でテンプレートを使って煮るなり焼くなりするだけです！
テンプレートの書き方は省略します。

#終わりに#
書き方いつも迷うので備忘録として書きました。
Webページの詳細をアイテムごとに表示したりするのに便利なので、使い方を覚えておいて損はないと思います！
UITableViewCellをスワイプアクションでアラート表示

#今回の内容

* UITableViewCellでスワイプアクションをした時に、削除機能を行う前にアラートで削除するか確認する様にする。
 
#コード

```Swift:
extension SearchViewController:UITableViewDelegate{
    
    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
            
            let deleteAction = UIContextualAction(style: .destructive, title: "") { action,_,_  in
                
                let alert = UIAlertController(title: "確認", message: "選択中のデータを削除しますか?", preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "削除", style: .destructive, handler: { _ in
                    
                    //配列内の値を削除など
                    tableView.deleteRows(at: [indexPath as IndexPath], with: .automatic)
                    tableView.reloadData()
                }))
                alert.addAction(UIAlertAction(title: "キャンセル", style: .cancel, handler: nil))
                self.present(alert, animated: true, completion: nil)
            }           
            
            deleteAction.image = UIImage(systemName: "trash")
            
            return UISwipeActionsConfiguration(actions: [deleteAction])
    }
    
}
```

# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
mayaScannerをbat処理したい


最近めっきり増えてきた mayaのデータに取り付くタイプのマルウェア。
mayaScannerによってファイルopen/import時に何とか対応してくれるのですが、
数が多いとどうにもダイアログが鬱陶しい。

何とか一気にスキャンできないものかと調べたところ

なるほど mayaBatch.exe でファイルを開けばmayaScannerが走ってくれるのか。

    "C:\Program Files\Autodesk\Maya2019\bin\mayabatch.exe" -file "hogehoge.ma" -command "evalDeferred (""loadPlugin MayaScanner; MayaScan;"")"

実行して、マルウェアがhitすると問答無用で除去して、問答無用でファイルを上書きする。

ただ毎回書いて処理するのも面倒なので、**複数ファイルを一気に処理したい** & **ドラッグアンドドロップで処理したい**

    for %%f in (%*) do (
    "C:\Program Files\Autodesk\Maya2019\bin\mayabatch.exe" -file %%f -command "evalDeferred (""loadPlugin MayaScanner; MayaScan;"")"
    )

※実際はさらに案件ごとのuserSetup.pyを読み込ませてます。
これを .batで保存してそこにファイルをドラッグアンドドロップすれば一気に処理ができる。

ただし先述の通り、
**マルウェアがhitすると問答無用で除去して、問答無用でファイルを上書きする**ので、
オリジナルのファイルはどこかに逃がしておいた方が良さそう。


参考：

https://support.borndigital.co.jp/hc/ja/articles/900001546106-Maya-Security-Tools%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88

http://myara.blog.fc2.com/blog-entry-233.html

https://tm8r.hateblo.jp/entry/2020/08/31/223846

https://qiita.com/YHiga/items/83908a71015e1f120742
【Swift】ユーザーレビューを促す訴求ダイアログを表示する方法

Swiftで開発したiOSアプリでユーザーレビューを促すダイアログを表示させる方法。

## 公式リファレンスの解説
#### SKStoreReviewController
> An object that controls the process of requesting App Store ratings and reviews from users.
ユーザーにAppStoreの評価とレビューを要求するプロセスを制御するオブジェクト。

#### Overview
> Use the requestReview() method to indicate when it makes sense within the logic of your app to ask the user for ratings and reviews within your app.
このメソッドを使用して、アプリのロジック内でユーザーにアプリ内の評価とレビューを求めることが理にかなっている場合を示します。

## 実装コード

必要なのは２行だけ。

```swift
import StoreKit

SKStoreReviewController.requestReview()
```
ただしダイアログを表示できるのは365日で最大３回まで。

どのタイミングで表示させるか工夫しないと、効果を得られないので注意が必要。

またユーザーは設定画面からレビュー訴求ダイアログの非表示設定が可能であるため、必ず表示されるとは限らない。

https://developer.apple.com/design/human-interface-guidelines/ios/overview/themes/

## おすすめ情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
ABC159 C - Maximum Volume を解いた

https://atcoder.jp/contests/abc159/tasks/abc159_c

![abc159c_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/c42048f0-d66c-d513-6b8d-a6162d9498dd.png)
![abc159c_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/dbd18f31-79b6-81f7-31d2-1325a954fc4f.png)

確証はないが、サンプルが三等分してるので、
マネしてみた。

```abc159c.py
L = int(input())
print("{:.6f}".format( (L/3)**3 ))
```
[Ruby]10進数⇄2,3,4...16進数に表示してみる(追記・訂正あり)

# はじめに
本記事では、10進数⇄2,3,4...16進数に~~変換~~表示してみる記事です。

```
「追記」
コメントにてご指摘いただきしたが、
正式には、
`to_iメソッド`によって10進数に変換されているのではなく、
10進数として表示されたということになります。
```

詳しくは、以下の記事を参考にしていただけますと幸いです。
[Ruby の "1101".to_i(2) は 2 進数を 10 進数に変換している，わけじゃない](https://qiita.com/scivola/items/a8976caed1d8ba8f36e8)

# コード
こちらを参考にしています。
→[Ruby リファレンスマニュアル](https://docs.ruby-lang.org/ja/latest/method/String/i/to_i.html)

```ruby
p 表示したい10進数の数字.to_s(表示したい○進数の○の部分を記述)
# "表示したい進数の数が表示"

p "表示したい○進数の数字".to_i(表示したい○進数の○の部分を記述)
# 10進数に表示した数が表示
```

`10進数`でないと`数値`と見なされません。→間違いです。
`2進数など他`では`文字列`で表現することになります。

```
[訂正]

10進数のほかに、2進，8進，16進の数値リテラルがあります。
本記事のコメント欄にて情報をいただいておりますのでご確認ください。
申し訳ございません。
```


以下、実際に2~16進数へ表示してみました。

```ruby
p 255.to_s(2)
# "11111111"

p 255.to_s(3)
# "100110"

p 255.to_s(4)
# "3333"

p 255.to_s(5)
# "2010"

p 255.to_s(6)
# "1103"

p 255.to_s(7)
# "513"

p 255.to_s(8)
# "377"

p 255.to_s(9)
# "313"

p 255.to_s(10)
# "255"

p 255.to_s(11)
# "212"

p 255.to_s(12)
# "193"

p 255.to_s(13)
# "168"

p 255.to_s(14)
# "143"

p 255.to_s(15)
# "120"

p 255.to_s(16)
# "ff"
```

せっかくなんで、それらを10進数で表示します。

```ruby
p "11111111".to_i(2)
# 255

p "100110".to_i(3)
# 255

p "3333".to_i(4)
# 255

p "2010".to_i(5)
# 255

p "1103".to_i(6)
# 255

p "513".to_i(7)
# 255

p "377".to_i(8)
# 255

p "313".to_i(9)
# 255

p "255".to_i(10)
# 255

p "212".to_i(11)
# 255

p "193".to_i(12)
# 255

p "168".to_i(13)
# 255

p "143".to_i(14)
# 255

p "120".to_i(15)
# 255

p "ff".to_i(16)
# 255
```

以上です。

# 終わりに
ITパスポートの勉強で、
2進数から10進数に変換する問題があったので、
rubyでできるのかなと思い、調べました。
余裕でできましたね。

明日も頑張ります！
AWS Well-Architected Tool とは

## 勉強前イメージ

アーキテクチャを診断してくれる的な？

## 調査

## AWS Well-Architected Tool とは

サーバーレスアプリケーションの評価ができる機能で、
AWSが定めた5つの柱でクラウド環境のシステム設計や運用を最適化するフレームワークです。
元々は今までのノウハウをホワイトペーパーで公開していたもので、
現在はAWS Well-Architected Toolとして統合され、誰でも改善を行うことができます。

## 5つの柱

AWSが定めた以下のような5つの柱で構成されており、
AWS Well-Architected Toolではそれぞれの設計思想の元、質問項目が準備されています。

- 運用上の優秀性

変更の自動化など日常業務を管理や、モニタリングなどの継続的な改善に焦点を当てています。

- セキュリティ

情報とシステムの保護に焦点を当てて作っており、
権限管理やシステムの保護、セキュリティイベントの検知などを確立することが目的になります。

- 信頼性

意図した機能を期待通りに一貫して実行できることに焦点を当てており、
障害からの復旧や分散システムにの設定など考えることが目的になります。

- パフォーマンス効率

リソースを効率的に使用することを目的としており、
要件に応じたリソースタイプやサイズ、ビジネスサイズの増大の対応など
情報に基づいて決定できます。

- コスト最適化

ビジネスのサイズに応じたスケーリングをし、
不要なコストを回避することに重点を置いています。

### 使用するメリット

- レビューと評価ができる

全体をモニタリングしてリスクの把握に役立ちます。
またツールから次のステップを割り出します。

- アーキテクチャガイダンスを利用できる

一連の質問に回答することでステップバイステップのアーキテクチャガイダンスを閲覧できます。

## 勉強後イメージ

今までのノウハウを使ってレビュー、また次どうしたらいいのか確認できるってことですかね
今ほぼ環境がないのでこちら使えませんが・・・悲しい

## 参考

- [AWS Well-Architected Toolをさわってみた](https://blog.serverworks.co.jp/2021/02/13/141357)
- [AWS Well-Architectedの概念5つ｜行う時のポイントも紹介](https://www.fenet.jp/aws/column/technique/372/)
【Git】過去のコミット位置に戻ってブランチを切る

今の状態も消したくはないけど、過去のコミット位置に戻りたいなと思った時の小技を知ったのでメモメモ。

過去のコードに戻すにはresetしないといけないのかなと思ったけど、今編集しているブランチはそのままに、過去の特定のコミット位置から新しくブランチを切る方法があるらしい。

##手順

####1. 戻りたいコミットのハッシュ値を調べる

`$ git log`コマンドで、このコミット位置に戻りたい！というコミットのハッシュ値を調べておく。

####2. 新しいブランチを作成する

以下のコマンドで、指定したコミット位置から新しいブランチを切ることができる。

```
$ git checkout -b [新しいブランチ名] [コミットのハッシュ値]
```


頻繁に使うものではないと思うけれど、覚えておけばresetせずに済んで助かることもあるかなと思いました(^○^)


###参考記事

https://chaika.hatenablog.com/entry/2017/07/20/093000
ABC158 C - Tax Increase から学んだ

https://atcoder.jp/contests/abc158/tasks/abc158_c

![abc158c_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/df30699a-9b7a-33ee-c50a-5b30f348f0cd.png)
![abc158c_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/4cd0b507-8b8d-bb62-4845-5a5251474a07.png)
![abc158c_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/5397807d-fb22-33df-cf42-caf6f9b9f74d.png)

油断したつもりはなかったが WA

```abc158c_ng.py
A,B = map(int,input().split())
from math import floor
for x in range(1,101): #<= ここ
    if floor(x*0.08) == A and floor(x*0.1) == B:
        print(x)
        exit()
print(-1)
```

敗因はコメントにある**ここ**。
A,B は max 100 .つまり 答えの数値を 1/100 して 100 なわけだから 100 の 100 倍は最低でも覚悟しないとダメ。
一応、多めに for は回してみた。

```abc158c_ok.py
A,B = map(int,input().split())
from math import floor
for x in range(1,10**5+1):
    if floor(x*0.08) == A and floor(x*0.1) == B:
        print(x)
        exit()
print(-1)
```
FirebaseのFirestore v9でサブコレクションを取得する

FirebaseとReactでアプリを作成していたときに、Firestore ウェブバージョン9のサブコレクションを取得する方法を記載した記事が中々なかったのでまとめます。

# サブコレクションとは？
Firestoreはリレーショナルデータベースとは構造が違い、ドキュメントとコレクションの組み合わせで構成されています。

### リレーショナルデータベースとFirestoreの違い
とあるユーザがいてそのユーザに紐づくブログ記事（複数）があった場合、
リレーショナルデータベースでは「ユーザ」テーブルと「ブログ記事」テーブルがそれぞれあり、ブログテーブルにユーザIDを持つなどして「ユーザ」とそれに紐づく「ブログ記事」を定義すると思います。

Firestoreでは、複数の「ユーザ」というコレクションがあり、個々のユーザの中にそれぞれサブコレクションとして「ブログ記事」があるというイメージです。


# FireStoreからサブコレクションを取得する方法

上記で書いた通り「ユーザ」と紐づく「ブログ記事」があるという想定で、ユーザに紐づくブログ記事を取得してみます。
以降のソースは全て、以下の通りinitializeやgetFirestoreでdbを取得した前提のソースです。
ここのdbの取得の方法もあまり記載した記事がなかったので念の為記載します。

```ts
import { initializeApp } from 'firebase/app'
import { getFirestore } from 'firebase/firestore'

const firebaseConfig = {
 // Firestore上で取得できる固有のconfig値
}

initializeApp(firebaseConfig)
const db = getFirestore()
```

## サブコレクションを全て取得する

```ts
import { collection, getDocs } from 'firebase/firestore'

const uid = 'user1' // user1　というIDを持ったユーザであると仮定します。

// 'users'というコレクションの中のユーザ一人を'user1'というIDで一意に特定します。　＝　ドキュメント
// 'user1'というドキュメントの中の'blogs'というコレクションを全て取得。
const snapShots = await getDocs(collection(db, 'users', uid, 'blogs'))
snapShots.forEach((s) => {
  // なんらかの処理
})
```

## サブコレクションの中をさらに一意に特定する

```ts
import { doc, getDoc } from 'firebase/firestore'

const uid = 'user1'
const blogId = 'blog1' // 'blog1'というIDを持ったブログが1つあると仮定します。

// 取得したサブコレクションから、更に'blogId'で一意に特定する
const blog = await getDoc(doc(db, 'users', uid, 'blogs', blogId))
const blogData = blog.data()
```

## サブコレクションをソートして取得する
```ts
import { collection, getDocs, orderBy, query } from 'firebase/firestore'

const uid = 'user1'

// queryとorderByを使って、ブログの日付の新しい順で並び替えます。
const q = query(
  collection(db, 'users', uid, 'blogs'),
  orderBy('date', 'desc')
  // これ以降にさらにorderByで並び替え条件を追加することも可能。
)
const snapShots = await getDocs(q)
snapShots.forEach((s) => {
  // なんらかの処理
})
```

# まとめ
1.　コレクションを取得するときはgetDoc **s** (docの複数形です！)とcollectionを使う
2.　ドキュメントを取得する時はgetDocとdocを使う
3.　コレクション名の指定　→ IDを指定 → サブコレクション名の指定 → IDを指定... の順番で、どんな深いサブコレクションでもコレクション自体やドキュメントを指定できます。

以上です！
mysql起動時のERROR! The server quit without updating PID fileを解決

#起こったこと

mysqlを学ぼうとインストール→起動の時点で躓きました。

```
 % mysql.server start                   
Starting MySQL
.. ERROR! The server quit without updating PID file (/usr/local/var/mysql/MacBook-Pro.local.pid).

```

#試したこと(ERROR!パターン)

<b>アンインストール→インストール→起動→ERROR!</b>

```
% brew uninstall mysql
% brew install mysql
% mysql.server start
Starting MySQL
.. ERROR! The server quit without updating PID file (/usr/local/var/mysql/MacBook-Pro.local.pid).
```

#試したこと（SUCCESS!パターン）

<b>アンインストール→mysqlに関するファイルを全て削除→再度インストール→起動→SUCCESS!</b>

```
% brew uninstall mysql
% sudo rm -rf /usr/local/mysql
% sudo rm -rf /Library/StartupItems/MYSQL
% sudo rm -rf /Library/PreferencePanes/MySQL.prefPane
% sudo rm -rf /Library/Receipts/mysql-.pkg
% sudo rm -rf /usr/local/Cellar/mysql*
% sudo rm -rf /usr/local/bin/mysql*
% sudo rm -rf /usr/local/var/mysql*
% sudo rm -rf /usr/local/etc/my.cnf
% sudo rm -rf /usr/local/share/mysql*
% sudo rm -rf /usr/local/opt/mysql*
% sudo rm -rf /usr/local/var/mysql/MacBook-Pro.local.pid
% brew install mysql
% mysql.server start
Starting MySQL
. SUCCESS! 
```


やっとこれで駆け出せそうです・・・。

#参考

https://teratail.com/questions/295270
PDFで作成された申込用紙等にパソコンで文字を書く方法

## はじめに
市役所や銀行の申込書がPDFファイルでできていて、そのフォームに住所や氏名を書きたいと思うことがよくあります。もちろん専用ソフトをインストールすればできますがちょっと面倒です。
次の方法を使えば、比較的に簡単にできて元のPDFも変更せず、印刷もできるようになります。

## 手順
1. パソコンにLibreOffice Drawをインストール。
2. Drawを起動する
3. レイヤーを一つ作る。（仮にレイヤーの名前を「レイヤー１」とします）
4. 「レイヤー１」を選択し、エクスプローラからPDFファイルを選択し、Drawの画面にドロップし用紙の位置にPDFの位置を合わせる。
5. レイヤーをもう一つ作る。（仮にレイヤーの名前を「レイヤー２」とします）
6. 「レイヤー１」を選択し、「レイヤーの変更」→「ロックする」にチェックしてPDFの位置を固定。
7. 「レイヤー２」を選択して、文字を記入。

以上
ABC156 C - Rally を解いた

https://atcoder.jp/contests/abc156/tasks/abc156_c

![abc156c_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/1407c871-6b2a-25a1-dd99-38f981a9bea3.png)
![abc156c_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/67b2457e-892c-94fa-1bed-a0ea4c0f5068.png)
![abc156c_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/e50c3ad0-6fd1-a39a-a0c3-b68007ed9b1c.png)

文章通り入れてみた。別に sort しなくても
良いと思うけど。。。

```abc156c.py
N = int(input())
X = list(map(int,input().split()))
X.sort()

ans = float("inf")
for i in range(1,101):
    score = 0
    for j in range(N):
        score += (X[j]-i)**2
    ans = min(score,ans)

print(ans)#28ms
```

別解として面白いものを見つけた。
座標として有効なのは X の平均値とあたりを付ける場合。

```abc156c.py
def solv():
    N = int(input())
    X = list(map(int,input().split()))
    
    canditates = [sum(X)//N,sum(X)//N+1]
    a,b = 0,0
    for x in X:
        a += (x-canditates[0])**2
        b += (x-canditates[1])**2
    if a > b:
        print(b)
    else:
        print(a)
solv()#28ms
```

しかし、平均値も 2.01 なのか 2.91 なのかで、
妥当な平均値は 2 の場合、3の場合と別れる。

それぞれの場合で体力の消耗を合算していき、
小さい方を出力する。

**なぜ平均値?**
例えば、問題では 2 点が与えられたとする。
その場合の、それぞれの体力消耗は以下で求まる

(x0-p)^2 = x0^2 -2x0p+p^2
(x1-p)^2 = x1^2 -2x1p+p^2

上記を合算し、p について整理をすると

2{**p^2** - {(x0+x1)/2}**p** + (x0^2+x1^2)/2}

となる。お気づきだと思うが
上記を p に関する二次関数と判断すると

p = (x0+x1)/2 の時、p の関数は最小値になることが分かる

(x0+x1)/2 って与えられた 2 点の平均ですよね?(笑)

何も考えず、雰囲気で for 文を回すのと
数式で考えて for 文を回すのでは問題に対するスタンスが
全く違うようです。

処理時間は殆ど変らないけど(笑)
Draggable使用時に"Could not find the correct Provider"エラーが出た場合の対処法


Draggableでドラッグ可能なWidgetを実装したところ、
ドラッグ時にProviderのエラーが発生しました。

```
Could not find the correct Provider
======== Exception caught by widgets library =======================================================
The following ProviderNotFoundException was thrown building Consumer<HomeViewModel>(dirty):
Error: Could not find the correct Provider<HomeViewModel> above this Consumer<HomeViewModel> Widget

This happens because you used a `BuildContext` that does not include the provider
```

この時のコードは以下です。

```
Widget build(BuildContext context) {
  return Draggable(
    child: method(),
    feedback: method(),
  );
}
Widget method() {
  return Consumer<HomeViewModel>(builder: (context, model, child) {
    return Text(model.text);
  });
}
```


原因は `feedback` の中で `Consumer` を使用しているためです。
`Draggable` よりも前に `Consumer` を使えば解決します。


```
Widget build(BuildContext context) {
  return Consumer<HomeViewModel>(builder: (context, model, child) {
    return Draggable(
      child: method(model),
      feedback: method(model),
    );
  });
}
Widget method(HomeViewModel model) {
  return Text(model.text);
}
```
ABC154 C - Distinct or Not を解いた

https://atcoder.jp/contests/abc154/tasks/abc154_c

![abc154c_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/17b295e8-8463-8d84-958b-1718aff232d4.png)
![abc154c_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/8d58df06-cc79-37e8-45d6-23a84e6967a3.png)

うん。できた。

```abc154c.py
N = int(input())
A = list(map(int,input().split()))

print("YES" if len(list(set(A))) == len(A) else "NO" )
```
ABC153 C - Fennec vs Monster を解いた

https://atcoder.jp/contests/abc153/tasks/abc153_c

![abc153c_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/10bf7a0c-ec16-a00c-7a68-d5afdfc20086.png)
![abc153c_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/2a85fb5c-f09e-6b33-1f3f-e2cc515bbbf0.png)
![abc153c_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/f627b8ea-2395-277d-bf9a-e370d4e5ef99.png)

たぶん、やり方は色々あると思う。

```abc153c_r1.py
N,K = map(int,input().split())
H = list(map(int,input().split()))
H.sort(reverse=True)
#print(H)

if K > N:
    H =[0]
else:
    for i in range(K):
        H[i] = 0

print(sum(H))#117ms
```

極力シンプルに書くとスピードが上がるようだ。

```abc153c_r2.py
N,K = map(int,input().split())
H = list(map(int,input().split()))

H.sort()

if K > N:
    print(0)
else:
    print(sum(H[:N-K]))#105ms
```
Azure Time Series Insightsの階層構造

既存データやAzure IoT CentralデータをAzure Time Series Insightsで分析できるようになりました。

* [既存の時系列データをAzure Time Series Insightsでデータ分析](https://qiita.com/matsujirushi/items/bd6affcc44c6b2719288)
* [Azure IoT Centralの時系列データをAzure Time Series Insightsでデータ分析](https://qiita.com/matsujirushi/items/120e64ad566874539d60)

これからは、Azure Time Series Insightsの中の機能を試していこうと思います。

第一弾の今回は**階層構造**に取り組みます。

# Azure Time Series Insightsの階層構造

[デモ環境](https://insights.timeseries.azure.com/preview/demo)の下図赤枠の部分は**階層ツリー**というもので、デバイス（正確にはTime Series Instance）が沢山あって探しにくくなったときに、木構造で整理、表示できる機能です。英語は**Hierarchy**と言います。下図では、Time Series IDが18672e3d-2beb-4007-9846-042b09ef3c73のTime Series Instanceが、Contso Plant 1 - W6 - Generator System - ActivePowerに含まれることを示しています。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/a7b6b29d-afbc-afb9-f1f2-ede43891f438.png">

HierarchyとTime Series InstanceはN対Nの関係で定義されます。ようするに、1つのTime Series InstanceをHierarchyの複数箇所にぶら下げることができるようになっています。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/6b784ec8-e3ce-12fc-d7b5-07fbe45f644a.png">

なんだか、少しややこしいですね。
でも心配無用です。用語はややこしいですが、実際は単純な作りなので。

# 作ってみよう

では、Hierarchyを作ってみましょう。

題材はこちら。VDK05とVDK09のTime Series Instanceを、Hierarchyで**デバイスの場所**と**屋内or屋外**がパッとわかるようにしてみましょう。

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/fbcb5eb2-018d-072d-affe-3806f3a1492f.png">

## Hierarchyを作る

デバイスの場所を示すHierarchy、**Location**を作ります。Locationは、Country, State, Cityの階層構造にしてみます。
TSI ExplorerでModel画面のHierarchiesタブを選択して、Add hierarchyをクリックし、表示された画面に諸々入力してください。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/d1c70693-3009-1fab-6a02-0224a29a6385.png">

同様に、屋内屋外を示すHierarchy、**Indoor/Outdoor**も作ってください。

このように出来上がれば正常です。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/2a384da1-8d00-4b28-f0e8-6ec2e99383c6.png">

## Time Series InstanceにHierarchy情報を設定する

次は、Time Series InstanceにHierarchyの情報を設定します。
Model画面のInstancesタブを選択して、対象のTime Series InsitanceのEdit（鉛筆マーク）をクリックしてください。そして、Instance fieldsタブを選択して、Hierarchiesをチェック、表示されたInstance fieldsに値を入力してください。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/c0e55c2a-afe5-668e-08e5-0e7438dc5806.png">

## 出来上がり

TSI Explorerの左側に階層ツリーが表示されました！

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/deba4261-deb7-5254-959f-42e5b4f8f493.png">

# 注意事項

Time Series InstanceのInstance fieldsのところでHierarchyをチェックすると、Instance fieldsにHierarchyのLevelsに入力したNameが構造化されずフラットに追加されます。そのため、LevelsのNameが複数のHierarchyで重複していて同時に追加しようとすると、追加できない(つд⊂)ｴｰﾝ という事態になります。LevelsのNameは慎重に決めましょう。
Linux は POSIX の認証を 1 ドルで得られる申し出を断っていた（POSIX に完全準拠することに興味がないため）

Linux は 1 ドルで POSIX の認証を得られる機会を Andrew Josey （POSIX の議長）から与えられており、Linux を POSIX に準拠すべく Josey は Linux が POSIX 規定と動作が異なる箇所のリストを作成していたりしましたが、Linux （正確には LSB） 側の興味を得られずに 2005 年にそのプロジェクトは終了したとのことです。（ソース [[1]](https://unix.stackexchange.com/questions/467010/is-linux-considered-xsi-compliant-or-largely-so) [[2]](https://en.wikipedia.org/wiki/Unix-like)）

Linux の人々が OpenGroup に完全に準拠するつもりはないと答えた後に書かれた Josey の POSIX と Linux の C 言語インターフェースやシェルとユーティリティ等の非互換レポートはこちらです。（2005 年当時の話なので今はなにか変わってるかもしれませんが）

[Conflicts between ISO/IEC 9945 (POSIX) and the Linux Standard Base](https://personal.opengroup.org/~ajosey/tr20-08-2005.txt)

てっきり認証に費用がかかるからかと思ってたんですが費用の問題はなかったんですね。別件で色々調べていたらたまたま見つけて面白かったのでついでに記事にしてみました。有名な話なんでしょうか？Linux は POSIX に準拠してないと言われますが、この話は検索しても日本語で書いてるページが見つからなかったです。

なお POSIX の認証 「[POSIX™ Certification Register](http://get.posixcertified.ieee.org/register.html)」です。これは UNIX 認証である「[UNIX® Certified Products](https://www.opengroup.org/openbrand/register/index.html)」とは別物です。POSIX の認証があっても UNIX は名乗れません。UNIX 03 または UNIX V7 の認証であれば POSIX と内容が含まれるはずなので POSIX 準拠（POSIX 認証とは言っていない）になるとは思います。（参考 [Greg's Wiki: POSIX](https://mywiki.wooledge.org/POSIX)）

ちなみに GNU の POSIX（正確には GNU 以外の標準規格）に対する考えは「[こちら](https://www.gnu.org/prep/standards/html_node/Non_002dGNU-Standards.html)」にかかれており「他の組織による標準は命令ではなく提案とみなす。考慮はするが従うことはない。」と明確に述べられています。**GNU はユーザーの利便性の方を重視**しており、POSIX で決まっていたとしても厳密に従うことはないとのことです。もちろん厳密に従うことはないってだけで、基本的には Linux はだいたい POSIX に準拠してるはずです。念の為。

####★ あわせて読みたい

[What is POSIX? Richard Stallman explains](https://opensource.com/article/19/7/what-posix-richard-stallman-explains)
「POSIX とは何？ リチャード・ストールマンの説明」

リチャード・ストールマンへのインタビューです。POSIX の仕様のナンセンスな部分とか、GNU から POSIX に採用された仕様の話とか、いろいろおもしろい話が書いてあります （誰か翻訳してくれないかなぁ）。「[Richard Stallman: The Coder](https://www.karmak.org/archive/2003/01/12-14-99.epl.html) 」にも同じような話が書かれていますが、現時点では証明書の有効期限切れで警告がでるので一応アクセスは自己責任ということで。


リチャード・ストールマンは説明するまでもないとは思いますが GNU プロジェクトの創始者です。1980 年代には最終的に POSIX と呼ばれることになる標準規格を作成していた IEEE 委員会に参加（[Think GNU 第 11 回](https://think-gnu-distribution.appspot.com/html/tga11.html)には「オブザーバーとしてコメントしていた」と書いてあるので重要な立場ではなさそう）していたそうで、POSIX という名前の命名者でもあります。

IEEE は標準規格の名前を IEEEIX にしようとしていたらしいのですが、[POSIX と名前をつけた理由](https://stallman.org/articles/posix.html)には、IEEEIX の発音は恐怖の叫び声のようだ → 誰もそんな名前で呼ばないだろう → みんな Unix と呼ぶんじゃないか？ → GNU のライバル、Unix という名前で呼ばれるのは嫌だ（※ GNU は GNU is Not UNIX の略）と書いてあって笑いました。POSIX を Unix と呼ばせたくなかったんですね。POSIX 標準化委員会は Unix を作った AT&T とは別組織なので不思議なことではありませんが、Unix の標準規格と言えるようなものでありながら Unix と呼ばれないための名前がつけられていたというのも面白い話です。

あと細かいことに気づいたんですが、POSIX は「Portable Operating System Interface」の略として知られていますが、リチャード・ストールマンによると（誰かが書いた）「Portable Operating System」に `IEEEIX` と同じ接尾辞の `IX` をつけたとありますね。`X` の意味は何？とよく言われますが、元々は（UNIX とか Xenix とかの）`IX` だったのか。
ABC152 C - Low Elements を解いた

https://atcoder.jp/contests/abc152/tasks/abc152_c

![abc152c_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/baa01f6d-f858-e527-adee-0d108d73323e.png)
![abc152c_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/224a7a12-12f8-f0fa-7cc3-7ec3c124f6aa.png)
![abc152c_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/973940ee-fba4-3ce9-4075-61ff4c7473c3.png)

文章のまま入力

```abc152c.py
N = int(input())
P = list(map(int,input().split()))

x = P[0]
lis = [x]
for i in range(1,N):
    if x >= P[i]:
        lis.append(P[i])
        x = P[i]
print(len(lis))
```
SQLの集計とグループ化をおさらいしてみた

#データを集計する
SQLには集計関数が存在します。代表的な集計関数を表にまとめました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265227/bd7da907-1e84-6ce4-c2f1-f359102b4b8b.png" width=50%>

前回学習した関数と集計関数では挙動が異なる点に注意が必要です。
集計関数は集計の対象となったすべての行に対し計算を行い、１つの答えを出します。違いをわかりやすくイラストにしてみました。

![スクリーンショット 2021-10-14 19.37.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265227/d1f4bf91-a25d-0f45-c115-a487036ca7e0.png)

![スクリーンショット 2021-10-14 19.40.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265227/02ffc28f-4e41-d96d-40b4-9019be124313.png)

集計関数は１つの答えを出すので必然的に結果は１行になります。
では、以下のような費目別の出金額集計表を作りたいときはどうすればよいでしょうか。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265227/dc6cbd6b-2e07-2b20-cae4-dab402c42535.png" width=50%>

このようなケースは費目でグループ化してそれぞれの合計を求める事で解決できます。
基本構文は以下のようになります。

```sql:sql
SELECT グループ化の基準列名、 集計関数
FROM　テーブル名
（WHERE　絞り込み条件）
GROUP BY　グループ化の基準列名
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265227/2df31bfd-523b-720d-57fd-10d95f09c427.png" width=80%>


グループ集計は３つのステップで実行されます。
１．　もとの表に対してWHERE句による通常の検索処理が行われ、行が絞り込まれます。
２．　検索結果はGROUP BY句で指定された列に同じ値を持つ行ごとに分類されます。
３．　最後に各グループに対して集計関数の処理が行われた後、SELECT句の選択列リストによって列が絞り込まれ、結果表となります。

##HAVING句について
グループ化する際に先程の例のを見ると給料が0になっています。そこで出金額 > 0のものだけを取り出すとしましょう。

誤った例としてWHERE句でとりだそうとします。

```sql:sql
SELECT 費目、 SUM（出金額） AS 費目別の出金額
FROM　家計簿
WHERE　SUM（出金額） > 0
GROUP BY　費目
```

このクエリはエラーをはきます。なぜならWHERE句最初の検索時点で評価されるものであって最終的な集計関数の結果をまだ知らないからです。
そこで、専門の構文であるHAVING句を利用します。

```sql:sql
SELECT 費目、 SUM（出金額） AS 費目別の出金額
FROM　家計簿
（WHEREもとの絞り込み条件）
GROUP BY　費目
HAVING　SUM(出金額) > 0
```

このようにHAVING句を利用することで当初の目的にあった集計結果を得ることができます。

##参考
書籍： スッキリわかるSQL入門 第2版 ドリル222問付き！　
　　　 中山 清喬　著/飯田 理恵子　著
MapLibre GL JSをTypeScriptで用いる際のTips

# 問題

MapLibreをTypeScriptとともに用いる際、型定義がほしい。

# 背景

- TypeScriptを用いたReactアプリの中でMapLibre GL JSを使いたいと思った。
- useEffectのなかでMapLibreを読み込み地図を描画する。
    - しかし、`new maplibregl.Map()`によって作成されたインスタンスにはスコープ外からもアクセスしたい。
- そのため、インスタンスを作成する前に変数宣言し、明示的に型宣言しておきたい。


# 解決法

型定義は`maplibre-gl/types/ui`以下に用意されています。
必要なものをここから読み込んで使えば良さそうです。

```javascript
import maplibregl from 'maplibre-gl';
import Map from 'maplibre-gl/types/ui/map';

let map: Map;
function create() {
    map = new maplibregl.Map(options);
}
```

このほかにも、`maplibregl.Marker`や`maplibregl.Popup`になどについては次のようにすれば良さそうです。

```javascript
import Marker from 'maplibre-gl/types/ui/marker';
import Popup from 'maplibre-gl/types/ui/popup';
```
RapidMinerの紹介

####RapidMinerとは
SPSS Modelerと同じようなBIツール製品で、ドラッグ&ドロップの簡単な操作でデータ加工（前処理）からデータ可視化、モデル作成、評価、運用までできる機械学習プラットフォームです。
※オフィシャルサイト：https://rapidminer.com/get-started/

####インストール手順
#####アカウント申請
下記のサイトでアカウントを申請できます。（無料試し期間は30日、Freeバージョンあり）
https://my.rapidminer.com/nexus/account/index.html#signup

#####ダウンロード
申請したアカウントでダウンロードします。
https://my.rapidminer.com/nexus/account/index.html#downloads
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/58a648cf-4ac2-7514-0d1d-f3deb1391493.png">


#####インストール
基本的には続行で簡単にインストールできます。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/2a89ea74-c990-6371-134a-08b674f6b4a0.png">  <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/90d23ea8-c6c1-26a9-7e4f-601eeb2ce2c1.png">
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/6396c05e-7f76-3e6c-708b-a71b2e0a5ff9.png">  <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/4a89acf6-e081-20c2-53ad-b634bdbd63bb.png">
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/8fa3fc39-bdbd-4f85-42e0-9c0d50d0cd92.png">

#####起動
exeを開き、サインインすればソフトウェアも画面が起動されます。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/b9a34858-3afa-2a26-8ceb-9efd79bc925f.png">  <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/c2eac797-1f7f-609b-9445-5ffa6bd546ff.png">
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/a3d73258-b1de-c536-e04d-f0b49f68ec45.png">  <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/67d6bdde-f3ca-e688-3e51-04db04c8253e.png">

実際画面が下記のようになります。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/217c357b-2dc3-86d9-ddd4-d7abe9ec67c5.png">

####チュートリアル
（実際画面の図で分かりますが、）ソフトウェア製品内にチュートリアルの詳しい手順が（英語で）記載され、Process画面でヒントも提示されていて、初心者にとってとてもやさしいです！また、チュートリアルは初級から上級まで用意されていて、StepByStepで実施してとても達成感も感じます。
**チュートリアル一覧は以下のようになります。**
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531194/0877effc-679c-807c-09e7-8ae513bb7646.png">

####まとめ
個人的に、画面のレイアウトはSPSS Modelerと比べると分かりづらいですが、ソフトウェア製品内にチュートリアルがあり、初心者にとってとてもやさしいです。
以上、RapidMinerの紹介とチュートリアルの紹介でした。Freeバージョンもあるので、個人研究としてはとてもおすすめです。