OmniAICreator/Qiita-1.07M huggingface dataset:
ラズパイでPLC側のリレーを駆動する回路

#はじめに
　クライアントの工場にIoT機器を設置することにしたとする。
自分が持っているIoT機器は、ラズベリーパイだとする。そのラズベリーパイのGPIOボードを介し、工場の機器との通信を行う予定である。

　例えば、ラズベリーパイにPythonでプログラムを動かし、工場の装置にOK/NG信号に送ったり、装置の状態を示すフラグ信号を受け取ったりすることである。

　ここで問題が一つある。工場の装置には、PLCと呼ばれる産業用コンピューターが使われている。このPLCはなぜか24Vが標準である。直流電源も24V。IOレベル電圧も24Vである。それに対し、ラズベリーパイのGPIO電圧レベルは3V~3.3Vでできている。困ったことだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/1c123115-7c29-ca8d-cbc0-a744277db73d.png)
写真：三菱電機のPLC（三菱電機のPLCの製品名はシーケンサー。Copy機をXeroxと呼ぶことと同じ。）

　そして、ここでもう一つ盲点がある。PLC側にはリレーが使われていることが多い。
　リレーを駆動するためには、ある程度の電流（50mA程度）が必要である。単に3.3Vを24Vに変換する回路あったとしても、電流が出せなかったらリレーを駆動することができない。

　従って、ざっくり下記のようなスペックのものが必要となる。

| 項目  |  内容　|   コメント    |
|:-:|:-:|:-:|
|入力電圧|3.3V|ラズベリーパイのGPIOレベル |
|出力電圧|24V|PLCのGPIOレベル |
|出力電流|36mA以上|リレー駆動最低限の電流|


#3.3Vを24Vに変換する回路

　電圧を変換する際には、フォトカプラがよく使われる。
  駆動原理は下記の図に書いてある。図の中で、「入力側と出力側のGNDが繋がっていない」と書いてありますが、これがみそである。
　入力側と出力側が電気的に絶縁されているため、例えば、出力側にサージなどが発生しても入力側に影響を及ぼすことはない。本当に賢い設計思想だと思う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/5d9ade6c-dfee-384a-d156-a93f4a6e2b85.png)

　そして、フォトカプラにはシャープ製のPC817がよく使われる。今回のシミュレーションと試作にもPC817を利用した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/42248a51-fc14-8174-72b7-4cc6c09f28bc.png)

　下記に3.3Vの信号を24Vに変換する回路を示す。
　3.3V側の抵抗330Ωと24V側の抵抗2200Ωは、電流値を10mA程度に絞る役割である。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/51e76fe4-e339-20a8-599a-11742b003a08.png)

　下記のシミュレーション結果を示す。
　3.3V側のパルスが、24V側に変換され現れることが確認できた。
　ここで、Voutにリレーを繋いだら動くかと言うと、それは動かない。
　それは、PC817の内部のトランジスターの定格電流値が、リレーを駆動するのに足りないからである。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/ff44e134-23e5-38cf-a1e0-105c3e0d14bf.png)

#NPNトランジスタを使った電流増幅回路

　そこで、下記のような回路を使う。
　フォトカプラの出力の先に、NPNトランジスタのエミッタ接地増幅回路を用意する。
　フォトカプラの出力をNPNトランジスタのベースに繋ぎ、トランジスタをON・OFFすることである。
　トランジスタのエミッタは接地し、コレクターにリレーを繋いでおく。増幅されたコレクター電流で、リレーに24V,最大150mA程度の電流を流しリレーをON/OFFするのである。（トランジスタの 飽和領域を利用するため、コレクター電流の最大値は、定格の150mAg程度）

 最初に見る人には複雑に見えるかもしれない。 しかし、この構成の回路が定番として使われている。　ラズベリーパイやマイコンのGPIO変換の時は、この回路が最もシンプルで、確実である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/4e9121d1-cad5-4b7d-6d49-80566ea22dc1.png)

　下記の図に、この回路のシミュレーション結果示す。
　3V側の入力で、リレーを駆動することが可能となった。途中に、トランジスタベース電流及びリレーコイルに流れる電流を示す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/c9ee1bc5-f1f8-bc80-c21b-bed61b3901a4.png)

　ブレッドボードに実際の回路を組み動作を確認した。
　Youtubeの動画のリンクも掲載しておく。
https://www.youtube.com/watch?v=kdzRCSrn6X4
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/2bb8ea0f-81bd-b5cd-f8cb-64fb77c731fa.png)

#まとめ
1. フォトカプラ、NPNトランジスタを用いて、3.3V→24V電圧変換及びリレー駆動回路を設計・動作確認した。

#参考資料
1.[リレー駆動をシミュレーションする](https://qiita.com/kotai2003/items/a8fbdec8a6d0251a5041)
データモデリング

###テーブルの正規化とは？
データをより効率的に無駄なく管理できるようにテーブルの構造を改良していくこと。
1 Fact in 1 Place(1つの事実は1箇所のみでしか表現されていない状態）の実現


3段階の正規化がある。
####第一正規化: テーブルの中に同じ内容を表すカラムの繰り返しが存在しないようにすること。

同じ内容を表しているカラムを抜き出す。

####第二正規化:　テーブルの主キー以外のカラムが、全て主キーに関数従属している状態にすること

主キーの一部に関数従属しているカラムを抜き出す


####第三正規化:　テーブル内のカラムに推移的関数従属性がない状態にすること

※推移的関数従属性
A,B,Cの3つのカラムにおいて、Aの値が決まるとBの値が一意に決まり、さらにBの値が決まるとCの値が一意に決まるような状態のこと。
Android Build時の unityeditor.buildplayerwindow+buildmethodexception

<img width="1486" alt="Screen Shot 2020-06-19 at 3.31.04 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632178/44664f28-648d-d1c5-1c03-8734cab8457c.png">
このエラーの原因が分かりませんした。

## 結果
ダイアログを出そうとして
`EditorUtility.DisplayDialog()` を書いていたのが原因でした。


## References
- [【Unity】UnityEditor.BuildPlayerWindow+BuildMethodExceptionが発生してAndroidビルドできないときの対処方法](https://qiita.com/riekure/items/132abbc8ea73ffaec5c4)
- [UnityEditor.BuildPlayerWindow+BuildMethodException?](https://stackoverflow.com/questions/54194428/unityeditor-buildplayerwindowbuildmethodexception)
- [Build failed with errors. at UnityEditor.BuildPlayer+Default buildMethods how to resolve it ?](https://answers.unity.com/questions/1380921/build-failed-with-errors-at-unityeditorbuildplayer.html)
【PHP 】sqlをPHPにてブラウザ上にて表示させる

本日は、sqlをphpを使ってブラウザ上に表示していく。

始めに、sql.phpにて

```php
$pdo=new PDO('mysql:host=localhost;dbname=mydb;charset=utf8','root','root');
```
のようにPDOの中に記載していく。

```php
$pdo=new PDO('使用するsql:host=ホスト名;dbname=データベース名;charset=utf8','ユーザー名','パスワード');
```
PHP とデータベースサーバーの間の接続を表します。
データベースを代入すると

```php
$sql='SELECT * FROM dbPractice';
```

のようにデータベースのテーブル名を選択する。
そして、

```php
$statement=$pdo->prepare($sql);
```
とsqlを使用する準備をする役割を持つparepare()関数を使用する。

最後に

```php
$statement->execute();
```
executeメソッドによってデータを取得する。

これでーデータの取得が完了する。
そして、これらのデータを取り出す作業に移行する。

```php
$results=[];
while($row=$statement->fetch(PDO::FETCH_ASSOC)){
    $results[]=$row;
}
```
このように記述する。
while構文の条件式は、
fetch関数により、配列を一行ずつ取り出す。
そして、
引数のPDO::FETCH_ASSOCは、列名を記述し配列で取り出す設定をしている。配列の最後まで下記を実行し続ける。
そして、予め作成しておいた$results変数の空配列に$rowを代入する。

```php
$statement=null;
$pdo=null;
require_once 'view/sql.tpl.php';
//テンプレートの呼び出し
```
最後にsql.tpl.phpに

```php
  <?php foreach($results as $value){?>
       <p><?php print_r($value);?></p>
    <?php }?>
```
これで以下のようにデータベースの取得結果が出力される。
<img width="1440" alt="スクリーンショット 2020-06-19 16.44.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612642/99dc5b62-6e02-3210-2619-597c82c9010b.png">

引き続きアウトプットとインプットを続けていく。
間違っている部分、フィードバックなどございましたら教えていただけると嬉しいです。
よろしくお願い致します。
windowsでmusic 21のインストール方法

#Install
基本的にはpipコマンドでインストールすれば良い。

```
pip install music21
```

#Musescoreで楽譜を表示してみる

[Mususcore](https://musescore.org/ja)をインストールする

Musescoreがインストールされたパスの設定をする

```
us = environment.UserSettings()
us['musicxmlPath'] = 'C:/Program Files/MuseScore 3/bin/MuseScore3.exe'
us['musescoreDirectPNGPath'] = 'C:/Program Files/MuseScore 3/bin/MuseScore3.exe'
```
###楽譜の表示
```
from music21 import note,stream,corpus,chord,environment,converter,midi

note = note.Note("C4", quarterLength = 1)
note.show()
```

考えられるエラー

> SubConverterFileIOException: png file of xml not found. Or file >999 pages?

対応策
`subconverters.py`の891行目にある
`os.system(musescoreRun)`を`subprocess.run(musescoreRun)`. に変更し、`import subprocess`を`subconverters.py`に追記

参考
https://stackoverflow.com/questions/53646669/unable-to-show-scores-in-music21
JAWS-UG CLI専門支部に捧ぐ - 手順実行の際にコピペを楽にするブックマークレット

[JAWS-UG CLI専門支部](https://jawsug-cli.connpass.com/) 楽しいですよね。ご存じない方は [総合案内](https://qiita.com/tcsh/items/14c3278f69ab073afe0f) あたり参照してみてください。

手順を実行する際に Web から CLI コマンドをコピペするのですが、ここで選択範囲をミスってコマンドエラーになると少し悲しいです。私は手先が器用ではないので、たまにありますw

というわけで、自分用のクイックハックとして「CLI コマンドをワンクリックで全選択する JavaScript コード」を書いてみました。ブックマークレット書くなんて何年振りだろう…

# JavaScript コード

[対象のページ](http://prototype-handson-cli.s3-website-ap-northeast-1.amazonaws.com/handson_light-aws_service/handson_light-aws_service-ec2_ami/index.html) をみると、CLI コードが記載されている HTML Element は以下の4種の CSS セレクターで選択できそうです。

* pre.command
* pre.setenv
* pre.checkenv
* .highlight-sh .highlight

であればコードは簡単で、HTML 要素を選択して、onClick イベントを仕込めばok。たとえば以下のようになります。

```JavaScript
document.querySelectorAll("pre.command, pre.setenv, pre.checkenv, .highlight-sh .highlight").forEach(e => {
  e.addEventListener('click', function(){
    var r = document.createRange();
    r.selectNodeContents(this);
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(r);
  });
});
```

JAWS-UG CLI の手順ページでコンソールを開き、上記のコードをコピペして実行すれば、CLI コードをワンクリックで選択できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193519/ecd9af01-dcc1-8980-8e5b-ae4fd39a6661.png)
あとは Ctrl-C Ctrl-V などで、コンソールにコピペすればok。

一応、Chrome と Firefox ブラウザで動作を確認してあります。

# ブックマークレット化してみる

毎回 Web ブラウザのコンソールで実行するのも面倒なので、ブックマークレットにしておきましょう。ワンクリックで機能が使えるようになります。

Chrome の場合、まずは適当にブックマークしてタイトル(名前)を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193519/1f17131f-2ddf-cc6c-44f8-5a42ce64a7b0.png)
「その他」をクリックして詳細設定の画面に移動して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193519/a9ee0f78-0fed-9919-9568-3559de2a80b6.png)
以下のコードを URL 欄に設定すればokです。

```
javascript:document.querySelectorAll("pre.command, pre.setenv, pre.checkenv, .highlight-sh .highlight").forEach(e => {e.addEventListener('click', function(){var r = document.createRange();r.selectNodeContents(this);var sel = window.getSelection();sel.removeAllRanges();sel.addRange(r);});});
```

後は手順ページで、この作成したブックマークレットをクリックすれば、ワンクリックでの CLI コード選択が使えるようになります。

これで手順をスピードアップし、もっと雑談チャットに参加しましょうw
Power BIのストリーミングデータセットの日時型についてのあれこれ

# はじめに
GravioでセンサーデータをPower BIで可視化しようとしていまいち思ったように出なかったのでちょっと調べてみたので書いておく。
かなり雑に調べたので間違ってたら教えて下さい。
# 前提
* クラウド版のPower BI。DesktopでもProでもありません
* ストリーミングデータセットは下図のように設定
*  ![streamingdatasetdefinition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/32cd91d6-b676-f48b-e68a-e2e64bf1a8bb.png)
*  Postmanでゴニョゴニョ形式をイジってみた

# 調査結果
色々調査した結果、下記のような仕様になってるようだ。

* 内部ではUTCで扱っている
* APIで渡した値にタイムゾーン情報がついていた場合はちゃんと計算してUTCとして格納される
* タイムゾーン指定子は `Z` (UTC)、もしくは `±hhmm` `±hh:mm` `±hh` など。基本的にはISO8601に沿っていれば良い
* `JST` などの略称はエラーになる
* タイムゾーンを指定しないときはUTCとして扱われる
* レポートやグラフの表示はUTC表示以外に変更できない **→ これを変えたくて色々調べたが。。もしやり方を知ってる人がいたら教えてほしいです。。**

# 結論
とにかくUTCで扱われる。ただ、タイムゾーンを指定しなければなんとなくローカルタイムで扱ったようには見えるので、あまり深く考えずタイムゾーンを指定しないのが吉。。。。

# 試したパターン

## UTC 2020/6/19 03:00:00 で格納される
### JSTを ±hh[[:]mm] 形式で指定
```
"timestamp" :"2020-06-19T12:00:00+09:00"
```
```
"timestamp" :"2020-06-19T12:00:00+0900"
```
```
"timestamp" :"2020-06-19T12:00:00+09"
```
## UTC 2020/6/19 12:00:00 で格納される
### UTCを明示的に指定
```
"timestamp" :"2020-06-19T12:00:00Z"
```
```
"timestamp" :"2020-06-19T12:00:00+0000"
```
### タイムゾーン指定なし
```
"timestamp" :"2020-06-19T12:00:00"
```
## エラーになる
### 日本標準時を略語で指定
```
"timestamp" :"2020-06-19T12:00:00 JST"
```
# Gravioの場合

## SendHttpRequestを使う場合
* Bodyを `"[{\"data\": 10, \"timestamp\":\"" + av.Timestamp + "\"}]"` とするとUTC時刻がタイムゾーン指定なしで送られるのでUTC時刻で格納される
* Bodyを `"[{\"data\": 10, \"timestamp\":\"" + ToLocalTime(av.Timestamp) + "\"}]"` とするとローカルタイムがタイムゾーン指定なしで送られるので**ローカルタイムで格納される！**
![sendhttprequest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/0fc85b55-2319-c8b0-6e71-f35c57e94c83.png)

## SendRecordを使う場合
* av.Timestampをそのまま渡すとUTC時刻がUTC指定(Z)されて送られるのでUTC時刻で格納される
* ToLocalTime(av.Timestamp)を渡してもローカルタイムがタイムゾーン指定（+09:00）されて送られるのでUTC時刻で格納される
* ステップ出力の変数をDateTime型ではなくString型にするとタイムゾーン指定が外れ、**ローカルタイム時刻で格納される！**

![sendrecord.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/db1aca0d-7e88-c5a1-e6d7-bb1811f150c6.png)

## ただし・・・
ローカルタイム時刻が格納されるが、UTC表現でのローカルタイム時刻なので、実際の時刻はローカル時刻ではないので注意 （ややこしい・・・）

## (追記 2020/8/11)
当たり前ですが忘れてました。日本時間の場合、UTC時間で無理やり9時間足すことになるので、相対日付のフィルターを使って最近N日とかやっててもリアルタイムでデータが表示されません。未来の日付なので。。。
大量のexcelをマージして１つのexcelにするpython

３０ファイルに及ぶ設定ファイルがexcelで、全て別ファイルとして丁寧に送られてきたので
一つ一つ開くのは基本的人権の侵害に当たると思い、pythonさんにやってもらった記録です。

# 作戦
エクセルを１つのフォルダにすべてぶっこみ、同フォルダにpythonを一つ作って、
all.xlsx というファイルの１シート目に内容をすべて記載する。

# 実践
## ファイル配置
```sh
.
├── all.xlsx         # 最終的に出来上がるエクセル
├── excel_merge.py   # 今回作るpythonちゃん
├── site-packages    # 利用するパッケージが入っている。今回使うのはnumpyだけ。
│   ├── bin
│   ├── numpy
│   └── numpy-1.18.5.dist-info
├── hogehoge1.xlsx   # 丁寧に送られてきた大量のexcel様
├── hogehoge2.xlsx
・・・
└── hogehoge30.xlsx
```

## numpyをインストール

```
pip install numpy -t site-packages/
```

-t でフォルダ名を指定すると、その場にファイルを展開してインストールしてくれます。


## excel_merge.pyを作る
こんな感じのソースを書いて保存しましょう

```python
import os, sys, glob
sys.path.append(os.path.join(os.path.dirname(__file__), 'site-packages'))
import openpyxl as px

NEW_FILE = "all.xlsx"

# エクセルのファイルを全て取得する
files = glob.glob("./*.xls*")

all_data = []
for f in files:
    # 開いているexcelがあったら無視。all.xlsxがあっても無視。
    if f.startswith('./~')  or f == NEW_FILE:
        continue
    # excelを開いて頂く
    wb=px.load_workbook(f, data_only=True)
    # シートを開いて頂く
    ws = wb.worksheets[0]
    # シートを読み込んで全行取得して頂く
    for row in ws.iter_rows(min_row=2):
        # 不要な行があったら飛ばす。
        if row[0].value is None or \
            not str(row[0].value).strip() or \
            row[1].value is None or \
            row[0].value == 'nanika zyogai sitai mozi':
            continue
        values = []
        # 全セルを舐め回してデータを取得する
        for col in row:
            values.append(col.value)
        # 全セルデータを一つの配列に保存する
        all_data.append(values)

# ここからall.xlsxを作る作業
# print(all_data)
wb = px.Workbook()
ws = wb.worksheets[0]
start_row = 2
start_col = 3
# 全セルデータを順番に書き込み
for y, row in enumerate(all_data):
    for x, cell in enumerate(row):
        ws.cell(row=start_row + y,
                    column=start_col + x,
                    value=all_data[y][x])

#名前を付けて保存
wb.save(NEW_FILE)
```
[Rails]logフォーマットを自分好みに変更する

## 前提

* ruby: 2.7.1
* Rails: 6.0.3

## 自分好みの Formatter を定義する

```ruby:config/logger_my_formatter.rb
class Logger
  class MyFormatter < Formatter
    def call(severity, time, progname, msg)
      "[%s#%d] %5s -- %s: %s\n" % [format_datetime(time), $$, severity, progname, msg]
    end
  end
end

```


## 自分好みの Formatter を指定する

```ruby:config/application.rb
require_relative 'boot'
require_relative 'logger_my_formatter' # 追記

# ...
```

動作確認は `production` モードで行います(`development`モードは`ActiveSupport::Logger::SimpleFormatter`)。

```ruby:config/environments/production.rb
Rails.application.configure do
  # ...
  config.log_formatter = ::Logger::MyFormatter.new # 追記
end
```

## 動作確認

デフォルト

```
I, [2020-06-19T16:16:21.592424 #4688]  INFO -- : [e8b5388b-e8d9-4a31-a350-1f3cafdd0dda] Completed 200 OK in 224ms (Views: 102.2ms | ActiveRecord: 40.3ms | Allocations: 65613)
```

:arrow_down:

変更後

```
[2020-06-19T16:21:53.497691 #5177]  INFO -- : [d8ef0edd-4d3b-4618-bba7-050a185fa30b] Completed 200 OK in 12ms (Views: 6.3ms | ActiveRecord: 2.5ms | Allocations: 5132)
```
「プログラマのためのgoogle cloud platform入門」の第２章でエラーが出た全ての方へ

#サービスがアクティブにならない！！
問題となっているのは86ページ。バージョン2の起動時です。

```
sudo systemctl start dengonban.service
```
を実行しても

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485045/d5d0ec20-cc45-04ea-933c-02e3a304e483.png)


どうやらその前段階の

```
sudo systemctl start cloudsqlproxy.service
```
ですでにダメだったみたい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485045/d98b94be-0355-bf78-9354-9019163fe6f1.png)

エラーを見ると

```
 googleapi: Error 403: Cloud SQL Admin API has not been used in ~
```
とか抜かしてやがる。

##いや、教科書通りやってましたけど、僕
まあ間違いとかもあるかもしれんし、とりあえず確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485045/ed94adc4-e51b-f79c-199b-92a51c215d5e.png)

##ほ〜ら有効じゃん！
じゃあ何がアカンかったんでしょうねー、なんて考えながら戻るボタンを押すと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485045/14d12306-a08a-be74-c98b-aad76bc7246c.png)

##Cloud SQL 「 Admin API 」だと！？
いや、ちょっと待て、なんでそもそもこんな似た感じのAPIがあるん？
とか
Adminてなんや？こっちの方がそれっぽいやんか！
とか思いながら恐る恐る有効化

#で、でけた・・・

<img width="678" alt="スクリーンショット 2020-06-19 15.54.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485045/c0a35e71-ff42-1c42-b838-13e36bb436ce.png">

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485045/d3cf2945-1c38-633d-821d-17cbdcb5b5c3.png)

#結論
APIの有効化は
「Cloud SQL」では無く**「Cloud SQL Admin API」**です。

ちなみに
「Cloud SQL」は有効化していてもしてなくても関係ありませんでした。

概要の説明を見ても
「Cloud SQL」
Google Cloud SQL is a hosted and fully managed relational database service on Google's infrastructure.

「Cloud SQL Admin API」
API for Cloud SQL database instance management

と、「Cloud SQL」でそれっぽいことが書いてあるので要注意。

#じゃあ「Cloud SQL」ってなんだろう?
もしかしたらAPIってついてないから「Cloud SQL」のサービスそのものか、と思ったのですが、
無効にしても特にSQLに問題なし(バージョン２の掲示板はきちんと動作する)。
サービス画面上も正常に見える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485045/54a617be-a9e5-8bb1-a0eb-77b8fceb47ca.png)
※教科書は「websql」でしたが「testsql」としてます。

違いを調べてもなかなか出てこないのですがどなたか知っていたら教えてください。

#20200709追記
公式には正誤表に載ってました。
まずは正誤表、常識でしたね。。。
https://www.shoeisha.co.jp/book/detail/9784798137148
Raspberry Pi 4B が爆熱⇒ケースとファン買ってみて満足した


前回の続き「[Raspberry Pi 初期設定まとめ](https://qiita.com/murachi1208/items/79706fce06a201231216)」 まだ画面はOFFってない(苦笑

# 熱い…
いや Raspberry Pi 4B がね。そもそも爆熱の Pi 4B なので、大きいヒートシンクつけているので平気だと思ったら意外と熱いのでびっくりした。ともかく85'Cでサーマルスロットリングが発生するらしので 24/7 では熱対策が必須！

ヒートシンクのみで動かしていたとき触ってみるとかなり熱い。たぶん気持ちよく風呂に入れる温度でないことは確か。

簡単に負荷かけて温度を計測してみる。`yes > /dev/null` を 2job動かしたときの温度でいいでしょう。あと面倒だからグラフ化してない。

室温 23度で計測。`vcgencmd measure_temp`  の値。

|| 負荷なし | 負荷あり |
| :--- | :---: | :---: |
| ヒートシンクのみ | 60'C～65'C | 65'C～72'C |
| ヒートシンク+3.3V冷却ファン | 42'C～46'C | 50'C～54'C |
| ヒートシンク+5V冷却ファン | 39'C～42'C | 42'C～47'C |

結果：ヒートシンクのみではキツイ。ファン必須。静穏化を狙い 3.3V で運用ならなんとかいけるか？

# ファンはこれを買ってみた

https://www.amazon.co.jp/gp/product/B07FMXJ3TZ/ref=ppx_yo_dt_b_asin_title_o03_s00?ie=UTF8&psc=1

![IMG_5558.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/575cda9b-2ec7-9bb9-9da5-3bee802c40d0.png)

amazonで「DCブラシレス冷却ファンヒートシンク冷却ラジエータコネクタRaspberry」と検索すれば結構ヒットので好きな物を購入するです。私が購入したのは 2個/799円でしたYO。3.3V は超静穏ですがね 5V は…察してくださいませ。

# ケースが悪い気がする
「[Pi4 B 8GB スターターキット V1 32GB 透明](https://raspberry-pi.ksyic.com/main/index/pdp.id/551/pdp.open/551)」の”透明ケース"（＋3.3V冷却ファン）ですが、蓋をすると平常時 46～50'C なのでケースを購入してみました。※単に欲しかった言い訳

・[ラズベリーパイ4冷却ファン](https://qiita.com/NT1123/items/52a0987126733f7f213e)

## これ購入した
https://www.amazon.co.jp/gp/product/B07TXSYGKS/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

![IMG_5560.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/188c77d5-f278-ff52-fcd0-6f2869fa1395.png)

プラモデルを組み立てる感じでサクサク作れます。説明書は最低限のことしか書いていないのでネジとナットどっちむき？とかそういうのは多少の試行錯誤が必要ぐらいです。プラスドライバーが曲者でファンのネジ穴に合わせているので別途必要なぐらい（100均のドライバーセットあれば平気）。

で、

![IMG_5563.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/84538c9d-81e3-2abb-a2c1-817273b64984.png)

上部下部にフィルム貼ってるの判らず「なにこの切り出しだ感じ！！」って思ってた。フィルム剥がしたら綺麗綺麗。

## あ、そうだ 3.3/5V ってどのピン？
すぐ忘れる。しかも割と探すの苦労するので貼っときます。

![GPIO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/e2bd286e-d56b-c5d3-ee5f-7ea755012054.png)

https://www.raspberrypi.org/documentation/usage/gpio/README.md



## 再度検証してみた

室温 23度で計測。`vcgencmd measure_temp`  の値。

|| 負荷なし | 負荷あり |
| :--- | :---: | :---: |
| ヒートシンク+3.3V冷却ファン | 38'C～42'C | 45'C～50'C |

やっぱり 5Vは、うっさいので。3.3V で運用します。まあいっても 60'C 位ならいいんじゃないって感じ。

# 次回予告
画面はOFFろうと思ってたんだった。次回こそ…
sshもセキュアな設定してないしちょいと気合いれてみる
Rubyでトリボナッチ数列の問題を解いてみた(制限時間10分)

# はじめに
低学歴の筆者がトリボナッチ数列の問題を10分以内で解決しなければならない状況に陥り、トリボナッチという言葉を忘れてしまった状態（記憶喪失状態）から10分以内でrubyで解決した体験記でございます。
数学に自信がある人・ない人も力試しに10分以内で実施してみてはどうでしょうか？

# 問題
>問１
1,3,7,11,21,39...
50番個目にある数字は何ですか？

という問題を解決しなければいけない状況になりました...

...(;ﾟдﾟ)ｺﾞｸﾘ

10秒くらい意識を失いましたが、とりあえず現状を理解せねば！！と気合を入れ直しました。

## トリボナッチ数列について
トリボナッチ数列とは、項の数字がその前の3つの項の数字の合計となっている数列である...らしいです
中学入試で勉強するらしいが、昨日何食べたっけ？レベルのメモリーしかない私の記憶喪失は治りませんでした（...現在30歳）

検索した結果...

>トリボナッチ数とは、
...中略
a[0]=a[1]=0
a[2]=1
a[n]=a[n-1]+a[n-2]+a[n-3]
と定義された数列
この数列の一般項を求める。
f(z)=Σ[n=0→∞]a[n]zⁿ
=a[0]+a[1]z+Σ[n=2→∞]a[n]zⁿ
=Σ[n=2→∞]a[n]zⁿ
=a[2]z²+Σ[n=3→∞]a[n]zⁿ
=z²+Σ[n=3→∞]{a[n-1]+a[n-2]+a[n-3]}zⁿ
=z²+Σ[n=3→∞]{a[n-1]}zⁿ+Σ[n=3→∞]{a[n-2]}zⁿ+Σ[n=3→∞]{a[n-3]}zⁿ
=z²+zΣ[n=3→∞]{a[n-1]}z^(n-1)+z²Σ[n=3→∞]{a[n-2]}z^(n-2)+z³Σ[n=3→∞]{a[n-3]}z^(n-3)
=z²+zΣ[n=2→∞]a[n]zⁿ+z²Σ[n=1→∞]a[n]zⁿ+z³Σ[n=0→∞]a[n]zⁿ...以下略

~~いや10分じゃ理解できねーよ！！~~
~~理解することは諦めて~~、筆者的解釈のもとrubyで表現しました。

### 筆者的解釈
1個目 + 2個目 + 3個目 = 4個目
2個目 + 3個目 + 4個目 = 5個目の繰り返し
ところてん方式的なやつか　←　全然違う

1個目をaとし、2個目をb、3個目をcと表現し合計である4個目をdと表現
足した後、bがaになりcがb、dがcになると考えそれぞれを代入し、それを47回繰り返す！！
※ 47としているのは最初に3個の値を代入しているため50から3を引いた47としています。

```ruby:tribonacci.rb
a = 1
b = 3
c = 7
n = 0
while n < 47
  d = a + b + c
  a = b
  b = c
  c = d
  n += 1
end

puts c
```
最後のcが47個目の数字になる！！

これだ！！<br>
この考えをもう少し丁寧に表現して...

```ruby:tribonacci.rb
puts "求めたい数字を入力して下さい"
puts "１つ目の数字"
a = gets.to_i
puts "２つ目の数字"
b = gets.to_i
puts "３つ目の数字"
c = gets.to_i
puts "何番目の数字を求めますか？"
t = gets.to_i

n = 0
while n < (t - 3)
  d = a + b + c
  a = b
  b = c
  c = d
  n += 1
end

puts "#{t}番目の数は#{c}です"
```

これで50個目の数字17079382868243を求めることができました！！
正確な時間は測ってませんが、なんとか10分以内で実装しました。

## おわりに
もっと良い計算方法があると思いますが、低学歴の私には10分以内で表現するのはこれぐらいが限界でした。
皆様はどうでしたか？10分以内って結構焦りますよね？
Wikipediaで5行くらいで書いてるコードもあったのでもっと簡単にかけるはずですが、時間制限にテンパってしまってこんなコードになってしまいました...
エンジニアになるためには、コードを書くだけでなく数学の勉強もしなければならないと今回の件で痛感しました。
vagrant コマンドがなんだか動かない時

vagrant コマンドがよくわからないエラーに悩まされるときがある。

そんな時は、xcodeのバージョンアップが影響している事がしばしば。

一旦以下のコマンドを実行して試してみる事をオススメする。

```
$ xcode-select --install
```
[PyTorch]ToTensor()はどのように動いているんだろう

## はじめに
PyTorchで画像を扱っている際，tochvisionのTransformsにあるToTensor関数(1)って何をしているのかが気になったので調べてまとめておこうと思います．

## 要約
ToTensor関数の動きを理解しnumpyと相互変換できるようになる

## sample code
[ここ](https://discuss.pytorch.org/t/understanding-transform-normalize/21730/9?u=kazuki_hamaguchi)(2)のコードを参考にしながら，numpyで画像を読み込んだと仮定して```numpy -> tensor -> numpy```に戻してみます．ダミー画像の大きさは$(W,H,C)=(4,5,1)$とします．また，動作確認のみなのため，```ToTensor()```と同じ機能を持つ```import torchvision.transforms.functional.to_tensor()```を使用しています．

```python
import torchvision.transforms.functional as TF
import numpy as np
import torch

gray_image = np.asarray(torch.randint(0,255,(4, 5, 1), dtype=torch.uint8))
# 内部で gray_image = gray_image/255 してる．255は輝度の最大値
# numpy to tensor [0,1]の閉区間で正規化
nomalized_tensor_gray_image = TF.to_tensor(gray_image)
print(tensor_gray_image)

# tensor to numpy
nomalized_numpy_gray_image = np.asarray(nomalized_tensor_gray_image)
# (C,W,H)を(W,H,C)に変換するのと，[0,1]から[0,255]に直す．
numpy_gray_image = nomalized_numpy_gray_image.transpose(1,2,0) * 255
# データの形をもとに戻す np.float32 -> np.uint8
numpy_gray_image = numpy_gray_image.astype(np.uint8)
# もとに戻ったか確認
print(gray_image == numpy_gray_image)
```

## ToTensorの役割
関数名だけを見るとnumpyやPIL Image(W,H,C)をTensor(C,W,H)に変換するだけだと思っていました．
しかし，[実際の説明](https://pytorch.org/docs/stable/torchvision/transforms.html#conversion-transforms)を見ても
>Converts a PIL Image or numpy.ndarray (H x W x C) in the range [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0] if the PIL Image belongs to one of the modes (L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1) or if the numpy.ndarray has dtype = np.uint8

>In the other cases, tensors are returned without scaling.

と[0,255]を[0,1.0]に変換しているよと言ってます(データの型も```uint8```から```float32```に代わっています)．modeでは，画像の種類(RGBやGrayScale)なども選択できます．

## なぜ正規化する？
正規化をする理由としては，[0,255]だとデータのばらつきが大きく画像の特徴が俯瞰しにくいことが挙げられます．また，読み込まれたときの値が，なぜ[0,255]かは，画像の輝度に由来しています．GrayScale画像で考えると，一番暗い場所を```0```,一番明るい場所が```255```になります．RGBの画像でも輝度の概念は変わらないので知っておくと何かと便利です． 
計算機としては学習の際，浮動小数点を扱うため，丸め込み誤差などを考えると，なるべく小数桁を多くとりたい意図があると考えられます．

## おわりに
もともとは，```transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])```ってなんでこんな値設定しているんだろうから始まった調べものですが，ToTensorも意外とこじゃれたことをしていることがわかり，書き残しました．感想や，議論があればコメントに書いていただけると幸いです．

## 参考文献
(1) [Torchvision doc: Conversion Transforms](https://pytorch.org/docs/stable/torchvision/transforms.html#conversion-transforms)
(2) [Understanding transform.Normalize()](https://discuss.pytorch.org/t/understanding-transform-normalize/21730/9?u=kazuki_hamaguchi)
laravel-dump-serverインストールでエラー

# 経緯
新しく用意したLaravel開発用のサーバーにおいて、そろそろdump-serverで色々dumpさせて確認しようかと思い、下記をコマンドを叩いたら

```Bash
composer require --dev beyondcode/laravel-dump-server
```
こんなエラーが返ってきて何ぞ？ってなった話です。

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

  Problem 1
    - Installation request for beyondcode/laravel-dump-server ^1.4 -> satisfiable by beyondcode/laravel-dump-server[1.4.0].
    - Conclusion: remove symfony/var-dumper v4.4.10
    - Conclusion: don't install symfony/var-dumper v4.4.10
    - beyondcode/laravel-dump-server 1.4.0 requires symfony/var-dumper ^5.0 -> satisfiable by symfony/var-dumper[5.0.x-dev, 5.1.x-dev, 5.2.x-dev, v5.0.0, v5.0.0-BETA1, v5.0.0-BETA2, v5.0.0-RC1, v5.0.1, v5.0.10, v5.0.2, v5.0.3, v5.0.4, v5.0.5, v5.0.6, v5.0.7, v5.0.8, v5.0.9, v5.1.0, v5.1.0-BETA1, v5.1.0-RC1, v5.1.0-RC2, v5.1.1, v5.1.2].
    - Can only install one of: symfony/var-dumper[5.0.x-dev, v4.4.10].
    - Can only install one of: symfony/var-dumper[5.1.x-dev, v4.4.10].
　　〜省略〜
    - Can only install one of: symfony/var-dumper[v5.1.1, v4.4.10].
    - Can only install one of: symfony/var-dumper[v5.1.2, v4.4.10].
    - Installation request for symfony/var-dumper (locked at v4.4.10) -> satisfiable by symfony/var-dumper[v4.4.10].
```
# 環境の確認
エラーを見る感じsymfony/var-dumperが要因なのはなんとなく分かるのですが、
何をどうすりゃいいのか？な状態。
改めてphpやLaravelのバージョンを確認すると

```Bash
php -v
PHP 7.4.5 (cli) (built: Apr 23 2020 00:10:21) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.5, Copyright (c), by Zend Technologies
```
```Bash
php artisan --version
Laravel Framework 6.18.20
```
割と新しい目な構成。
もっと枯れたバージョンを使うしか無いんかなと諦め気味でググってると下記を実行しろとな。
本家でissueがあったのですが、laravel-dump-serverのバージョンを指定しないとダメやでって事でした。
https://github.com/beyondcode/laravel-dump-server/issues/62

```Bash
composer require --dev beyondcode/laravel-dump-server:1.3.0
```
俺にdump-serverが帰ってきた。
大好きなSCANDALのLINEbotを作りたいの巻1

#作りたいbot
毎日決まった時間にランダムでSCANDALのMVを送るbot
※SCANDALは女性バンドです。

####そのための僕の頭の中の構想（railsで作成）
1. まずはWEB上で動く物を作る
2. それをLINEbotにする
3. そこから機能を追加していく（例えば、ACIDMANとLINEで送るとACIDMANの曲をランダムに返すなど）
※ACIDMANもバンドです。

####ひとまずできたこと

1. まずはWEB上で動く物を作る

####参考にした記事

Qiitaの記事を元にYouTube Data APIのリファレンスを参考にしました。
> Qiita
https://qiita.com/sakakinn/items/46c0d4945e4646f346f6

>YouTube Data API
https://developers.google.com/youtube/v3/docs?hl=ja

####コード
```index.html.erb
<% number = 0 %>
<% ran = rand(1..11) %>
<% @youtube_data.items.each do |item| %>
  <% number = number + 1 %>
  <% if number == ran %>
   <% snippet = item.snippet %>
   <p><%= snippet.title %></p>
   <p><%= snippet.published_at %><%= snippet.channel_title %></p>
   <div><iframe width="560" height="315" src="https://www.youtube.com/embed/<%= item.id.video_id %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
  <% end %>
<% end %>
```

```youtube_controller.rb
class YoutubeController < ApplicationController
  def find_videos(keyword)
    service = Google::Apis::YoutubeV3::YouTubeService.new
    service.key = ENV["YOUTUBEKEY"]

    next_page_token = nil
    opt = {
      q: keyword,
      type: 'video',
      channel_id: 'UCSNX8VGaawLFG_bAZuMyQ3Q',
      max_results: 11,
      order: :date,
      page_token: next_page_token
    }
    service.list_searches(:snippet, opt)
  end

  def index
    @youtube_data = find_videos('SCANDAL')
  end
end
```
出力結果↓
https://twitter.com/pompom06yutoz/status/1273869183491559425?s=21

####今わかっている課題
1.　Viewで11個のデータにアクセスしているので、それを無くしてランダムにチャンネルからデータを一つだけ取り出したい。（助けてくれ〜ww）
2.　今のままだとチャンネルが固定（いったんスルーで）

####次にすること
とりあえずこれをLINEbotにしてみて、課題が浮上したらその時に考える。

####最後に
プログラミング学習始めて約4ヶ月が経過し、今程よく楽しんでいる人間です。
もし、何か良い代替の案があったら気軽にコメントお願いします〜。
後、SCANDALが好きな人もぜひ。
つづく
Homebrew で brew install した curl を使う

Homebrew で install を試した時に SSL のエラーが発生した、みたいな時にもしかしたら回避できるかもしれない話です。

```:例えばこんなエラーが出たとして
curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.haxx.se/docs/sslcerts.html
```

システムの curl (`/usr/bin/curl`) だと証明書のエラーが確認できましたが、brew install した curl (`/usr/local/opt/curl/bin/curl`) ではエラーが出なかったので、ひとまずそっちを使って進めてみます。

環境変数 `HOMEBREW_FORCE_BREWED_CURL` をセットしてあげるだけです。

```fish:fishの場合
env HOMEBREW_FORCE_BREWED_CURL=1 brew install ...
```
Microsoft MPI(MS-MPI)のメモ

## 背景

* Windows, macOS, Linux などでクロスプラットフォームで動く MPI アプリを作りたい
  * 機械学習とか, レンダリングとか 
* 一応 openmpi とか Windows 対応版あったが, ディスコンになった
  * https://www.open-mpi.org/software/ompi/v1.6/ms-windows.php

Microsoft MPI(MS-MPI. 相変わらずネーミングが雑ですね)を試します.

## MS-MPI

MS-MPI 自体は前からあって, Windows Server 用だけに提供されていたようですが, 最近(?) OSS になったようです.

https://github.com/Microsoft/Microsoft-MPI

SDK は Nuget でも入ります.

ランタイムなどが欲しいだけであれば, インストーラーで入れるのが手っ取り早いでしょうか

`.exe` と, `.msi` の両方をインストール必要です
(`.exe` インストーラーは `mpiexec.exe` など, `.msi` は SDK が入る)

デフォルトでは,

`C:¥Program¥ Files¥Microsoft MPI`
(bin)

`C:¥Program¥ Files¥ (x86)¥Microsoft SDKs¥MPI`
(include/lib)

にインストールされます.

Server 版である必要はなく, 普通の Windows 10 でも動きます.

### ビルド?

CMake は無いし, Gfortran とか, Perl とか必要とされるので, 断念しました.
余裕のある方はビルド頑張ってみてください.


## TODO

* [ ] Linux と Windows 混在で動くか試す(linux 側を MPICH にすればいけるか?)
Chromebookの標準ターミナルで日本語入力できるようにする

USキーボードでお金をかけずVimを使って簡単なコーディングがしたい！
という欲求を叶えてくれそうなPCを探した結果、3万円のChromebookを購入しました。 
[Google Chromebook Lenovo ノートパソコン 14.1型HD液晶 英語キーボード S330](https://www.amazon.co.jp/Lenovo-Chromebook-14-0%E5%9E%8B%E3%83%95%E3%83%ABHD%E6%B6%B2%E6%99%B6-%E3%80%90%E6%97%A5%E6%9C%AC%E6%AD%A3%E8%A6%8F%E4%BB%A3%E7%90%86%E5%BA%97%E5%93%81%E3%80%91-81JW0011JE/dp/B07RT8ZKV1/ref=sr_1_1_sspa?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=lenovo%2BS330&qid=1592542884&s=computers&sr=1-1-spons&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUFURUw1Vk8wSVE5NlQmZW5jcnlwdGVkSWQ9QTA3MTUwOTdQT1ZQN0NROUVIQzcmZW5jcnlwdGVkQWRJZD1BSU8wUUNaSkJSSFZFJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ&th=1)

最近のChromeOSは設定一つでLinuxが使えます。
[Chromebook で Linux（ベータ版）をセットアップする](https://support.goole.com/chromebook/answer/9145439?hl=ja)  
ただし、日本語入力対応はChromeosとは別に設定する必要があります。
検索すると出てくるのがfcitxを使った方法なのですが、この方法だとLinuxアプリには対応できるのですがChromeOSでLinuxを有効にするとインストールされる標準のターミナルには対応できません。
[Linux on Chromebook のソフトウェア開発者向けカスタマイズ例](https://qiita.com/weakboson/items/9086e2171fcbe986c8de)  
試行錯誤の末標準ターミナルでも日本語入力できる方法を見つけたので紹介します。
## 1. uim-fep, uim-mozcをインストール
コンソールで使える入力メソッドモジュールをインストールします。  

```console
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install uim-fep uim-mozc
```

## 2. 設定ファイルを追加する
$HOME直下に.uimというファイルを作成し、次のように記述します。

```sh:$HOME/.uim
(define default-im-name 'mozc)
(define-key generic-on-key? '("<Control> "))
(define-key generic-off-key? '("<Control> "))
```

IMEの選択と英語↔日本語の切り替えを行うためのキーを設定しています。
ここではUSキーボードのデフォルトであるCtrl+Spaceで切り替えられるようにしています。  

## 3. 実行
```console
$ uim-fep
```
を実行するとターミナルの下部にmozc[Mz- RM]というステータスが表示されるようになります。
これでCtrl+Spaceで入力切替ができるようになりました。
ターミナルの起動の度に実行が必要ですが、.bashrcに書いておけばターミナル起動時に自動実行してくれるので便利です。  

## 参考にした記事
[【FreeBSD】仮想コンソールで日本語入力したい(uim-fep+mozc)](https://hacolab.hatenablog.com/entry/2019/06/14/224827)
Go言語でHelloWorldを実行しようとしたらエラーになった

# Hello world が出来なかった
業務でGolangを使用する機会がありました。
本格的には触らなかったので、とりあえず自習しようとしました。

- とりあえず`hello.go`を作ってhello worldを表示しようとします。

```sh
$ go run hello.go
exec: "C:\\Users\\xxxxx\\AppData\\Local\\Temp\\go-build929698758\\b001\\exe\\hello": file does not exist
```

ああ？？なんだこれ？hello World で死ぬか？普通？ってなったわけです。

# 失敗した原因
とりあえず build だけやってみる

```shell
xxxxx@xxx MSYS /c/Users/xxxxx/Documents/test/go
$ go build hello.go

xxxxx@xxx MSYS /c/Users/xxxxx/Documents/test/go
$ ls
hello  hello.go
```
- バイナリ?が windows のじゃない！！

windowsで実行するなら

```sh
$ ls
hello.exe  hello.go
```
ができるのが正解ですよね～

**こうなる原因が環境変数のGOOSでした。**

```sh
$ env | grep GOOS
GOOS=linux
```
こうなっていたわけですよ。この`GOOS=linux`がいけなかった。
業務中にテキトーに設定したのがいけなかった。
`GOOS=linux`って環境変数を設定していると`build`して作られるバイナリファイルがLinux向けに作られるっぽい？
`MSYS2`または`git-for-windows`上でなら実行できるのでは？とか思ったのですがエラーでしたね。
てことで、

# どうすれば良いのか
GOOSを変えます


```sh
$ export GOOS=windows
# cmdだったら以下
set GOOS=windows
```
をした後に build すると
`hello.exe` が生成されますよっと。
これで解決。
`GOOS=windows`に設定するのが正しいのかは知らない。
もうこの環境変数消した方がいいのかな。
NervesにPhoenixを入れてHTTPのGETでLEDをウェブチカ〜準備編1/3〜

# 概要

NervesにPhoenixを入れてウェブチカできたので備忘録です。

- NervesにPhoenixを入れるとNerves起動時にPhoenixも起動します
- ウェブチカとは、とあるURLにアクセスするとNervesにつけているLEDをチカらせることを言ってます
- 前提としてNervesとPhoenixはインストール済みとします

```shell:fish
❯ mix nerves.new -v
Nerves Bootstrap v1.8.0

❯ mix phx.new -v
Phoenix v1.5.3
```

長編になりそうだったので3部作としました(^^ゞ

- [1/3　準備編](https://qiita.com/nishiuchikazuma/items/bfd04b36fb4524d49a59)　←いまここ
- [2/3　Nerves設定編（exineris）](https://qiita.com/nishiuchikazuma/items/175fdc4a646cbbfcc04d)
- [3/3　Phoenix設定・確認編（neosapi）](https://qiita.com/nishiuchikazuma/items/609c3faa4cfa36b77e90)


# 構成
NervesでPhoenixを動かすのは以下のNervesの公式ドキュメントを参考に実施します。Ponchoプロジェクトストラクチャーと呼ぶそうです。

- [Nerves / Interfaces / Phoenix web interfaces](https://github.com/nerves-project/nerves/blob/master/docs/User%20Interfaces.md#phoenix-web-interfaces)

## Ponchoプロジェクトストラクチャー

Nervesのプロジェクトと同じ階層にPhoenixのプロジェクトを作成して、NervesからPhoenixを起動する設定をおこないます。

管理しやすくするため、2つのプロジェクトをまとめるディレクトリを作って、このディレクトリの中にNervesとPhoenixのプロジェクトを作成した方がいいです。今回はexineosディレクトリの中にNervesプロジェクトのexineris、Phoenixプロジェクトのneosapiという構成としました。

```shell:shell
❯ tree -L 1 -F exineos
exineos
├── exineris/    ←Nervesのプロジェクトディレクトリ
└── neosapi/     ←Phoenixのプロジェクトディレクトリ
```

NervesとPhoenixのおおよその棲み分けはこのような感じだと思っています。

- Nerves：パッケージの管理、IPアドレスなどネットワークの設定
- Phoenix：ウェブ画面、ビジネスロジックの実装


# 準備

各プロジェクトを作成して、Nerves起動後Phonenixの画面が見えるまで準備します。

ネットワークはこのようないつもの構成にしました。
![ネットワーク構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51020/95e29daf-01e9-ac3b-3e5e-3d4448db4f19.png)

## 各プロジェクト作成

はじめにNervesとPhoenixを作成するディレクトリを作成します。

```shell:fish
❯ mkdir exineos
❯ cd exineos
```

次にNervesとPhoenixのプロジェクトを作成します。
まずはNervesのプロジェクトを作成し、以下の記事を参考にネットワークの設定をしてSSHログインまで確認します。

- [nerves_pack（vintage_net含む）を使ってNervesのネットワーク設定をした〜SSHログインまで〜](https://qiita.com/nishiuchikazuma/items/01f5df5472ec0feceb5f)

```shell:fish
❯ pwd
/path/to/exineos

❯ mix nerves.new exineris --nerves-pack
❯ cd exineris

❯ set -x MIX_TARGET rpi3
❯ mix deps.get

＜ここでネットワークの設定をする（上のリンク参照）＞

❯ mix firmware
❯ ssh 192.168.5.55
```

次にPhoenixのプロジェクトを作成します。
データベースを利用しないので`--no-ecto`、ウェブパックも使わないので`--no-webpack`オプションをつけています。
詳細は`mix help phx.new`を実行してください :wink: 

次に`mix phx.gen.secret`コマンドで秘密鍵（という名の文字列）を生成して、シェルの環境変数に設定し、関連するパッケージを取得します。

最後に`mix phx.server`を実行して`http://localhost:4000/`にアクセスしPhoenixの画面が表示されていれば準備は完了です。

```shell:fish
❯ pwd
/path/to/exineos

❯ mix phx.new neosapi --no-ecto --no-webpack

❯ mix phx.gen.secret
Y55U5mBi4/fViTfhegeVyWHJiCMkMMDhuNK+eqSsY0u2l1XheAZ97oruXIGqf2kC
❯ set -x SECRET_KEY_BASE Y55U5mBi4/fViTfhegeVyWHJiCMkMMDhuNK+eqSsY0u2l1XheAZ97oruXIGqf2kC

❯ mix deps.get
❯ mix phx.server

```


# つづく…
- [1/3　準備編](https://qiita.com/nishiuchikazuma/items/bfd04b36fb4524d49a59)　←いまここ
- [2/3　Nerves設定編（exineris）](https://qiita.com/nishiuchikazuma/items/175fdc4a646cbbfcc04d)
- [3/3　Phoenix設定・確認編（neosapi）](https://qiita.com/nishiuchikazuma/items/609c3faa4cfa36b77e90)
Windows Native C++でWinRTのOCR APIを使う方法

# はじめに

こんにちは。Daddy's Officeの市川です。

私が10年以上開発を続けているWindowsPCを監視カメラシステムにする「LiveCapture3」。
先日、このソフトにOCR機能を追加して、カメラ映像内の数値を検出できるようにしました。
（この機能により、サーマルカメラを使用した自動温度計測＆通知システムの構築が可能です）

「LiveCapture3」のコア機能はC++で実装しているので、C++でOCR機能を実装する必要がありました。
C++でのOCRといえば、「[Tesseract][1]」が有名ですが、今回は画像内の数値のみ検出すればよく、そこまで大掛かりにしたくありませんでした。

そこでWindowsのAPIを調べたところ、ありました！
[Windows.Media.Ocr][2]

しかし、よくよく見てみると、これは[WinRT][3]っぽい感じ。
つまり、UWPアプリやストアアプリであれば使えるのですが、デスクトップアプリから使うにはちょっと細工が必要そうです。

ということで

- WinRTのWindows.Media.Ocrを.NetFrameworkのC#で使えるようにする
- 上記のC# .NetFrameworkモジュールをC++から使えるようにする

という２段階で実装しました。

# WinRTのWindows.Media.Ocrを.NetFrameworkで使う

言語としてはどちらもC#なので、参照を追加できれば基本はOKです。

まず、.NetFrameworkのクラスライブラリとしてプロジェクトを生成します。

OCRを使用する為には、下記のUWPライブラリが必要です。

 - Windows.Media.Ocr
 - Windows.Storage.Streams
 - Windows.Graphics.Imaging

これらを使えるようにするために、プロジェクトの参照で、直接ライブラリを追加します。
![参照.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382663/868376bf-78b2-3d4e-3208-8e3fa10e0cf9.jpeg)

追加するのは下記の２つです。

| 名前 |パス|
|:-:|:-:|
|Windows.Foundation.UniversalApiContract|C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.winmd|
|Windows.Foundation.FoundationContract|C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd|

これで、準備はできました。

OCRエンジンの使い方は非常に簡単で、画像を渡すと認識結果の文字列が返却されるというものです。

```C#
using Windows.Graphics.Imaging;
using Windows.Media.Ocr;
using Windows.Storage.Streams;

async Task<OcrResult> detect(SoftwareBitmap bitmap)
{
     var ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages();
     var ocrResult = await ocrEngine.RecognizeAsync(bitmap);
     return ocrResult;
}
```

ただ、面倒くさいのが

- 引数の画像はSoftwareBitmap(WinRT)を使う必要がある
- WinRTのAsyncは、デスクトップのasync/awaitとは違う形式になっている

というところを解決しないといけません。

色々調べた結果、以下に素晴らしい説明がありました！

[Microsoft OCR をデスクトップのWFPアプリで動かす方法][4]

参照追加の方法がちょっと違いますが、実装コードはこのまま行けました！

# .NetFrameworkライブラリをC++からコールする

これは、以前私が投稿した下記のやり方で行います。

[既存のC++ネイティブプロジェクトでC#マネージドコードを使う][5]

これで、Native C++からWinRT用のOCR APIをコールしてOCR機能を実現することができました！

# ソースコード

ソースコード一式(VisualStudio2019)はこちらに置いておきます。

[ソースコード一式][6]

#参考
[Microsoft OCR をデスクトップのWFPアプリで動かす方法][4]
[既存のC++ネイティブプロジェクトでC#マネージドコードを使う][5]

[1]:https://ja.wikipedia.org/wiki/Tesseract_(ソフトウェア)
[2]:https://docs.microsoft.com/en-us/uwp/api/Windows.Media.Ocr?view=winrt-19041
[3]:https://ja.wikipedia.org/wiki/Windowsランタイム
[4]:https://www.moonmile.net/blog/archives/8584
[5]:https://qiita.com/Yukio-Ichikawa/items/f1a15dfda18bf8748268
[6]:https://github.com/daddyYukio/WindowsOCR/tree/master
Microsoft STL(MSVC C++ STL 実装)のメモ

## 背景

* MSVC 非依存で, 再配布可能な C++ STL ライブラリが欲しい
  * C++ JIT アプリ用とか 
* 最近 Microsft STL(名前がよくない) が OSS 公開されたので, これがつかえるか?
  * https://github.com/microsoft/STL
  
結論として, 実装が MSVC べったり + MSVC ランタイム依存です. clang-cl 対応なども考えられていないようなので, MSVC オンリーと考えたほうがいいでしょう.
(2022/08 追記: clang-cl 対応もちょこちょこ進んでいるようです. ただまだ完全ではなく, clang-15 or clang-16 くらいから動き始めそうな雰囲気?)

他の MSVC 関連の STL を利用しているライブラリを使っているのでなければ, MinGW gcc or llvm-mingw(clang) で libstdc++(MinGW gcc) or libcxx(llvm-mingw) を使ったほうがよいです.
 
## Microsoft STL とは?

今まで MSVC で使っていたのをそのまま OSS 公開したらしいっぽい. ソースコードは Microsoft らしく, きたないです :cry:

スタックガードなど使っているのか, MSVC ランタイムに依存しているため, 現状 MSVC 開発環境がないとビルドできない.
clang-cl でビルドできるかもしれない(ただし一部対応してないコンパイラフラッグを書き直しなど必要)
付属の CMakeLists では, clang-cl など他のコンパイラは考慮されていない.

Boost を math の特殊関数(e.g. bessel)の実装に使っていますので, Boost がいります
(ただ, math だけなので, vcpkg で Boost インストール+ビルドしなくても, Boost ヘッダーだけでもいけるかも?) 

AzurePipeline で CI ビルドされていますが, Artifact は配布されていないので, 自前ビルドする必要あります.

## まとめ

Microsoft STL を再配布し, アプリで使う場合

- STL ヘッダは Microsoft STL のを使う
- ビルドは MSVC で行い,  lib(dll)を作っておきこれを配布
- (Optional) MSCVRT が必要であれば, 再配布パッケージをユーザーに入れてもらう

でしょうか. 

## TODO

* [ ] vcpkg, choco, conan とかで prebuild 済みのがないか調べる
* [ ] GitHub Actions あたりで CI ビルドする(オフィシャル側では AzurePipeline で Artifact 生成はやる気なさそうなので)
* [ ] ビルドした STL が, clang-cl, mingw gcc/clang でビルドできるか調べる
51歳（現52）からのプログラミング　備忘　formから配列を送ってクッキーに登録してリダイレクト

<font color="#00f">実用的なコードは、コメント欄にご投稿頂きました rfc828様 の素敵なコードをご参照ください（←おすすめ）</font>

構成
sam1.php
sam2.php

```php:sam1.php
<form action="sam2.php" method="post">
<input type="text" name="sam[]" value="<?= $_COOKIE['sam'][0] ?? 'no';?>">
<input type="text" name="sam[]" value="<?= $_COOKIE['sam'][1] ?? 'no';?>">
<button>send</button>
</form>
```
<font color="#f00"><?= $_COOKIE['sam'][int] ?? 'no';?></font>
条件演算子のNULL合体演算子を使ってます。
条件A　?? 条件B　// 条件Aがnullでなければ条件Aを実行、nullなら条件Bを実行

これで、クッキーにsam配列が登録されていれば、input欄に該当する値をセットだね。

```php:sam2.php
<?php
$i=0;
foreach($_POST['sam'] as $v){
  setcookie("sam[$i]",$v);
  $i++;
}
header('Location:sam1.php');
```
POSTされた配列を、foreachで取り出して、クッキーにsam[]として登録ですね。
SwiftUIでOptional型のBindingの変数をunwrapする方法

SwiftUIでToDoアプリを作っていて、CoreDataに保存した日付データを持ってきて、表示しようと思いました。
この時の場合、日付をセットしない場合のことも考えて日付はOptional型で保存していました。
そして、日付がnilだった時（日付を設定してない時）に「日付をセットする」ボタンのようなものをつけたいと思いました。
そこで、最初に書いたコードが次のコードです。(`body`変数の中で、taskはCoreDataから取ってきたデータの入った変数です。`task.date`は`Binding<Date?>`となっていました。）

 ```swift
if task.date == nil {
    Button(action: {
        self.task.date = Date()
    }) {
        Text("Set Date")
    }
} else {
    DatePicker("Date", selection: $task.date!)
}
```
すると次のようなエラーが出てしまいました。

```
Cannot convert value of type 'Binding<Date?>' to expected argument type 'Binding<Date>'
```
そこで色々と検索して、[とあるStackOverflowの質問](https://stackoverflow.com/questions/58297176/how-can-i-unwrap-an-optional-value-inside-a-binding-in-swift)を見ると、`Binding($task.date)!`で同じようなことができるとわかりました。

```swift
if task.date == nil {
    Button(action: {
        self.task.date = Date()
    }) {
        Text("Set Date")
    }
} else {
    DatePicker("Date", selection: Binding($task.date)!)
}
```
これを実行してみると、目的通りに動きました。

# 最後に
何度か検索キーワードを変えてやっと出てきたので、また検索して時に出てこないかもしれないと思い、自分用のメモのような意味で書きました。
もっと良い方法や、間違い、改善点などがありましたら、コメントや編集リクエストなどをご気軽にお願いします。
PHP でリダイレクト (Apache2,Nginx)

次のページを参考にしました。
[PHPの「正しい」リダイレクト方法と、HTTPステータスコード](http://www-creators.com/archives/1012)

RaspberryPi で走る Apache2.4 と Nginxで確認しました。

```php:index.php
<?php
	$url = 'https://ekzemplaro.org/';
	header('Location: ' . $url, true, 301);
	exit;
?>
```

RaspberryPi の　OS

```text
$ uname -a
Linux violet 5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021 armv7l GNU/Linux
```

Apache2 のバージョン

```text
$ apachectl -v
Server version: Apache/2.4.38 (Raspbian)
Server built:   2020-08-25T20:08:29
```

Nginx のバージョン

```text
$ nginx -v
nginx version: nginx/1.14.2
```

>Nginx は php7.3-fpm とセットで使います。
無料版のAdobe Acrobat Reader DCを使って、PDFファイルに90度回転したテキストを入力する方法

テキストを無理やり回転させて書きたいなんてそこまで需要はないかもしれません。
そのせいか、調べた限り、このような内容を書いているサイトは見つからなかったので、投稿しようと思いました。
## 前提条件
使用するソフトウェア: Adobe Acrobat Reader DC(無料版)
OS: Adobe Acrobat Reader DCがインストールできればなんでも。
（windows10以外は試してないので、もしかしたら紹介する方法はできないかもしれません）
但し、Linuxの場合はLibreOfficeシリーズの中でPDF編集できるソフトウェアが存在するので、この方法よりはそちらを使うことをお勧めします。

## Adobe Acrobat Reader DCのインストール
Adobe Acrobat Reader DCに関しては無料でインストールできるAdobe公式のPDF表示用のソフトウェアです。下記からインストールできるはずです。
[Adobe Acrobat Reader DC インストール (すべてのバージョン)](https://get.adobe.com/jp/reader/otherversions/)

## PDFファイルにテキストを挿入し、それを回転させる方法
以下のようなpdfファイルがあったとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516498/e9c90c2d-b78f-323e-0f22-a5021c7d3375.png)

このpdfファイルの番号やら性別やら生年月日に文字を入れたいとします。
上のほうは何とかなりそうですが、下のほうは文字を回転させないといけません。
その方法を以下に示します。

### テキストの挿入
これに関しては他のサイトでも紹介されていますが、念のため紹介します。

1. 最初に紹介したpdfファイルの右にあるバーから吹き出しマークの注釈ボタンを押します。(これは無料版のAdobeでも使えるはずです。)
2. 上のほうに表示されるようになったバーの中からTを押して入力したいところでダブルクリックすればカーソルが出て、入力できます。
3. 文字の大きさは・・・マークからプロパティを使って変更できます。

この手順を実際に行うと以下のようになります。
![buzz2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516498/b936a781-a684-b4fb-58b8-7bcc16e6d08c.gif)

### 90度回転したテキストの挿入(本題)
さて、本題に入ります。次のようにして90度回転したテキストを挿入できます
1. 表示タブから右に90度回転を選ぶ。(これによりpdfファイル自体を90度回転させます。)
2. その後、入力したいところにテキストを挿入
3. 再度表示タブから左に90度回転を選んで、表示を元に戻す。

この手順を実際に行うと以下のようになります。
![buzz.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516498/e79ad41b-3246-5204-c6d9-67efe60f45c7.gif)

## 追記
操作をわかりやすくしようと思い、gif画像を載せましたが、むしろ画面がうるさくなってしまったかも。。
見づらかったらすいません。
競技プログラミング練習記 No.15【ABC142練習】

初回 -> [はじめに](https://qiita.com/easychoco/items/a9ae28aca97cfe47091f)

[ABC142](https://atcoder.jp/contests/abc142)を解きました。
4完です。
E問題は解説を見て解きました。

今回はジャッジ速度が速かったです。嬉しいw
1サンプルあたりの実行時間はいつも通りなのですが、全サンプルをジャッジする待ち時間が短かったです。
内部で並列処理になっているのでしょうか。


|問題|時間|アルゴリズム|実行時間
|:-:|:-:|:-:|:-:|
| A |  3min |-|6ms|
| B |  2min |-|12ms|
| C |  2min |-|23ms|
| D | 60min |公約数|24ms|
| E | - |動的計画法|13ms|



## A
```c++
	int n;
	cin >> n;
	printf("%.7f\n", (n + 1) / 2 / (double)n);
```
A問題にしては難しかった。。。
1WAしました。反省。
`(n + 1) / 2`で奇数の数が分かります。
全体の数は`n`なので`(n + 1) / 2 / (double)n`が答えです。
型に注意。

いつもA問題の実行時間は1msなのですが、今回は6msでした。
キャストが重いのでしょうか。


## B
``` c++
	int n, k, h;
	cin >> n >> k;
	int ans = 0;
	for(int i = 0; i < n; ++i)
	{
		cin >> h;
		if (h >= k)
		{
			ans++;
		}
	}
	cout << ans;
```
入力を受け取りながら`k`以上の数値があったら`ans++`します。

## C
``` c++
	int n, a;
	cin >> n;
	vector<int> stu(n);
	for(int i = 0; i < n; ++i)
	{
		cin >> a;
		stu[a - 1] = i + 1;
	}

	for(const auto& s : stu)
	{
		cout << s << " ";
	}
```
問題文の
> 生徒たちには 1 から N までの出席番号が重複なく割り当てられています。

より、サイズNと重複しないことがわかるので、
`stu[a - 1] = i + 1;`とすればそれが答えになります。
`stu[i] = a;`として、ソートしても答えが出せます。

## D


``` c++
	ll a, b;
	cin >> a >> b;

	map<ll, bool> cd;
	cd[1] = true;
	ll prime = 2;
	while(a >= prime * prime)
	{
		if (a % prime == 0)
		{
			while(a % prime == 0) a /= prime;
			cd[prime] = true;
		}
		prime++;
	}
	cd[a] = true;

	prime = 2;
	ll ans = 1;
	while(b >= prime * prime)
	{
		if (b % prime == 0)
		{
			while(b % prime == 0) b /= prime;
			if (cd.find(prime) != cd.end())
			{
				ans++;
			}
		}
		prime++;
	}
	if (b != 1 && cd.find(b) != cd.end())
	{
		ans++;
	}
	cout << ans;
```
`a`と`b`を素因数分解して、共通の素因数の数が答えになります。
例えば、

```math
a\ =\ 1 \times 2^3 \times 3^2 \times 5^1 \times 11^1 \times 13^5 \\
b\ =\ 1 \times 3^2 \times 5^1 \times 7^3 \times 11^2 \times 13^2
```

とすると、`a`と`b`の共通の素因数は`1,3,5,11,13`の5個なので、答えは5だとわかります。
プログラムでは`1`の扱いに注意です。


## E

```c++
	int n, m;
	cin >> n >> m;
	vector<int> a(m);
	vector<int> b(m);
	vector<int> c(m);
	for (int i = 0; i < m; ++i) 
	{
		cin >> a[i] >> b[i];
		for (int j = 0; j < b[i]; ++j)
		{
			int input;
			cin >> input;
			input--;
			c[i] += (1 << input);
		}
	}

	const int INF = 1000000000;
	vector<int> dp(5000, INF);
	dp[0] = 0;
	for(int i = 0; i < m; i++)
	{
		int now = c[i];
		for(int mask = 0; mask < (1 << n); mask++)
		{
			dp[mask | now] = min(dp[mask | now], dp[mask] + a[i]);
		}
	}
	cout << (dp[(1 << n) - 1] == INF ? -1 : dp[(1 << n) - 1]);
```

bitDPです。
bitmaskで宝箱が開いているかを表現します。
`dp[mask]`は「`mask`の宝箱が開いているときの最小コスト」です。
`O(2^N * M)`になります。

自力で解けませんでした。動的計画法と聞くと身構えちゃいます。
まだまだDPに慣れていませんね。精進します。

以上です。ありがとうございました。
PHP 改行コード brタグ

# 改行コード\\n

- **テキスト**内で改行するときに使う
- ダブルクォート(")内で記載し、出力する必要がある
- 改行コードはOSによって異なる
- 定義済み定数**PHP_EOL**を使うとOSを自動判定し改行文字を自動的に設定してくれる
- HTMLでは**連続する空白文字は全てスペース１つに置き換えられる**

# brタグ

- **HTML**内で改行するときに使う
- ソースでは改行されない。**ブラウザがHTMLをレンダリング**する際に改行される。

# 参考
https://pisuke-code.com/php-diff-of-nl-code-and-br-tag/
https://www.flatflag.nir87.com/nl2br-540#ltbrgt-2
【超爆速メモ】サンプルデータを少しずつ自分のアバターに変えていこう【VRoid】※随時更新していきます!!

ゼロからアバターをVRoidでデザインするには、自分にとってはハードルが高いので、普段収録でお世話になっているVita(サンプル)を少しずつ改造しようと思う。

## 「髪型編集」→「テクスチャ」→「ヘアー」

- 基本色
- かげ色
- かげ色
- ハイライト
- アウトライン

【超爆速メモ】VRoidで頭部にアクセサリーをつけたいんじゃが【VRoid】※随時更新していきます!!
https://qiita.com/sanpeita/items/239fa7b89a9c5af56b13

## 「名前をつけて保存」

- Macの場合、ユーザーアカウント名直下に、「vroid」フォルダがあるので、その中の「avatars」に.vroidファイルが保存されている。
【PHP】受動的攻撃

こちらの記事は以下の書籍を参考に執筆しました

- [入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



##受動的攻撃と能動的攻撃

###能動的攻撃
攻撃者が直接Webサーバに対して攻撃することです。
###受動的攻撃
攻撃者がWebサイトの利用者をとうして攻撃することです。
Webサイトに罠を仕掛け、罠を閲覧してたユーザを通して攻撃をします。
以下主な受動的攻撃の例を上げていきます。
####単純な受動的攻撃
攻撃者がいわゆる「怪しいサイト」を用意し、ユーザが閲覧してマルウェアに感染する場合です。
####正規サイトを悪用する受動的攻撃
これはサイトに罠が仕掛けられている場合です。
以下の順番で行われます。

1. 攻撃者が正規サイトを攻撃して仕掛けを仕込む
2. 罠が仕掛けられたサイトを利用者が閲覧する
3. マルウェア感染、情報漏洩、不正操作などが起こる。

1だけを見ると能動的攻撃ですが、2、3は受動的攻撃であり、1はこれの準備であると言えます。

単純な受動的攻撃よりも手間がかかりますが、攻撃者にとって以下のようなメリットがあります。

- 罠サイトに誘導する手間がかからない
- 正規サイトは利用者が多いので被害が拡大する可能性が高い
- 正規サイトの機能を不正利用することにより攻撃者にメリットが得られる。
- 利用者側の個人情報を盗むことにより攻撃者にメリットが得られる。

正規サイトに罠を仕込む手法は以下の4つが用いられます。

- FTPなどのパスワードを不正入手してコンテンツを書き換える。
- Webサーバの脆弱師をついた攻撃によりコンテンツを書き換える。
- SQLインジェクション攻撃によりコンテンツを書き換える。
- SNSなどの利用者が投稿できるサイト機能のクロスサイト・スクリプティング脆弱性を悪用する。

####サイトをまたがった受動的攻撃
罠サイトを正規サイトをまたがった攻撃です。

1. 利用者側が罠サイトを閲覧する
2. 罠サイトから仕掛けを含むHTMLをダウンロードする
3. HTMLのし掛けが作動して正規サイトに攻撃のリクエストを送信する。
4. 正規サイトからJavaScriptなどの仕掛けを含むレスポンスが返る。

##ブラウザはどのようにして受動的攻撃を防ぐか
###サンドボックス
ブラウザ上ではjavasctipやJavaアプレット等、サイトを閲覧した状態でプログラムを実行する機能が提供されています。javascriptなどは安全性を高めるために以下の考え方に基づいています。

- 利用者に配布元を確認させた上で利用者が許可した場合ものみ実行する
- プログラムの「できること」を制限するサンドボックスと言う環境を用意する

前者は一般的なアプリ-ケーションに用いるには利用者の負担が大きく、セキュリティ上の問題が出やすいため、提供元からのサポートが終了しつつあります。

サンドボックスはプログラムができることに制約があり、悪意のプログラムを作ろうとしても利用者に被害が及ばないよう配慮されます。
javascriptのサンボドックスでは以下のように機能が制限されます。

- ローカルファイルへのアクセスの禁止
- プリンタなどの資源の使用禁止
- ネットワークアクセ酢の制限(同一オリジンポリシー)

ネットワークについては厳しい成約があり、この制約を**同一オリジンポリシー**と呼びます。

###同一オリジンポリシー
javascript等のクライアントスクリプトからサイトをまたがったアクセスを禁止するセキュリティ上の制限であり、ブラウザのサンドボックスに用意された制限の1つです。
mac XAMPP インストール

# Mac Catalina に XAMPPをインストールする方法

Windowsでもポイントは同じ

**ポイントは、インストール時のパッケージの選択とあとはバーチャルホスト vhostの設定**

## XAMPPのダウンロード

トップページからダウンロードすると意図しないXAMPPがダウンロードされるのでダウンロードページから

https://www.apachefriends.org/jp/download.html

目的は、PHP7.3 をインストールしたいんだが、よく見ると２つある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84965/2becad93-33ca-90db-966f-c3c6ee3a9f1b.png)

どこで確認するかというと、青い「ダウンロード」ボタンのリンクがどうなっているか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84965/27843e99-d041-645c-3473-9ecd6310bfe8.png)

と
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84965/fbaf53ec-da0b-0e6c-5a6a-f6da062137d0.png)

２つある
違いは、vmかどうか。vmの意味は、Virtual Machineという意味。
vmを選ぶと、macの中に仮想環境を作ってそこでApacheやMySQLを起動させるということ。

VMということになると、PCの中にさらに別のネットワークが存在するということを忘れないように。

とはいえ、仮想環境を立ち上げてさらにWebサーバー立ち上げて、PCからVMにログインして作業とかなるとちょっと面倒。なので、vmではないのをインストールします。


ダウンロードインストールまでは、かんたんなので大丈夫。

では、もうひとつ。

## Virtual Hostの設定（apache)

もう、最近のapacheは、バージョン2.4系しか無いと思うので、ぐぐってみるとまだ2.2系の書き方もでてくるのでそこだけ注意です。

XAMPPをインストールすると
/Application/XAMPP/etc/httpd.conf 
ここにapacheの設定ファイルがあります。
ここでまずは、vhostの設定ファイルを読み込むようにします。
Include の前に#でコメントになっているので、取り除きます。

``` httpd.conf
# Virtual hosts
Include etc/extra/httpd-vhosts.conf
```

そして、そこに指定されている
etc/extra/httpd-vhosts.confを設定します。
いったんファイル内すべて消していいです。全部コメントになっているので。

Listenは、待受ポート番号　６５５３５まで指定可能。だけど、基本的にいくつかは予約されていてすでに別のサービスで使われているので、8000以降とか10000以降とか指定すればまあ、空いてるので大丈夫。

sampleユーザさんとしてpublicが公開ディレクトリの場合はこう。
ちなみに、以前は10080ポートがいい感じだと思ってたけど、このポートは、Chromeだとブロックされることに！まあよくあるポート番号だからかな。

``` httpd-vhosts.conf
# sample
Listen 10001
<VirtualHost *:10001>
     DocumentRoot "/Users/sapmle/sampleproject/public"

     ServerName localhost
     <Directory "/Users/sapmle/sampleproject/public">
        AllowOverride All
        Options All
        Require all granted
    </Directory>
</VirtualHost>
```

### httpd.conf を変更したら XAMPP再起動を忘れずに！！ apacheの再起動が必要です

## macでphp7.4の場合、403エラーがおきるようです

``` httpd.conf
User foo ←ローカルユーザ名にする
Group daemon
```