OmniAICreator/Qiita-1.07M huggingface dataset:
AtCoder AGC021 A - Digit Sum 2(300点)

#問題概要
[問題のリンク](https://atcoder.jp/contests/agc021/tasks/agc021_a)

$N$  以下の正の整数の $10$ 進法での各桁の和の最大値を求めてください。

#制約条件

- $1≤N≤10^{16}$
- $N$ は整数である

#考えたこと

やることは一見とてもシンプル！$1$から$N$までの整数を、それぞれ各桁の和をとっていき最大値を求めたい。
だが制約をみたらわかる通り、全探索はとても間に合わない。

求めたいのは最大値なのでできるだけ9が多いほうがいいのは自明である。よって$(N-1)*9+N桁目の値f$が答えとなる。この時、$N$の$1$から$N-1$桁目が全て9である場合、$f$は$N$桁目の値であるが、そうでない場合、$N$桁目の値 - $1$が$f$となる。(そうしないと$N$より大きい値の各桁の和をとることになるので。)

#解答

```a.cs
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args) {
        long n = long.Parse(Console.ReadLine());
        long l = digitLength(n);
        long f = digitFirst(n);
        Console.WriteLine((l-1)*9 + f);
    }
    static long digitLength(long x) {
        long length = 0;
        while(x>0) {
            length++;
            x /= 10;
        }
        return length;
    }
    static long digitFirst(long x) {
        long first = 0;
        List<long> digit = new List<long>();
        while(x>0) {
            first = x%10;
            digit.Add(x%10);
            x/=10;
        }
        for(int i = 0; i < digit.Count()-1; i ++) {
            if(digit[i] != 9) {
                first -= 1L;
                break;
            }
        }
        return first;
    }
}
```
無理に拡張するなら、まるごと変えてしまったほうがいいという話

## 何があったのか

コミットログを眺めていると、以下のような差分を見かけました。

``` C#
const int MAX_A_FILE_SIZE = 15;
const int MAX_B_FILE_SIZE = 10;
const int MAX_C_FILE_SIZE = 20;

int MAX_FILE_SIZE = ( MAX_A_FILE_SIZE > MAX_B_FILE_SIZE ) ?
    ( ( MAX_A_FILE_SIZE > MAX_C_FILE_SIZE ) ?
        MAX_A_FILE_SIZE : MAX_C_FILE_SIZE ) :
    ( ( MAX_B_FILE_SIZE > MAX_C_FILE_SIZE ) ?
        MAX_B_FILE_SIZE : MAX_C_FILE_SIZE );
```
※ 該当の箇所だけピックアップしました。実際は1ファイルあたり1000行以上で、言語も異なります。

修正前のソースは以下のようになっていました。

``` C#
const int MAX_A_FILE_SIZE = 15;
const int MAX_B_FILE_SIZE = 10;

int MAX_FILE_SIZE = ( MAX_A_FILE_SIZE > MAX_B_FILE_SIZE ) ? MAX_A_FILE_SIZE : MAX_C_FILE_SIZE;
```

これは「いずれかの定数のうち、より大きい値を設定する」という処理です。

恐らく、デグレを恐れた、もしくは手間を減らすために三項演算子の条件を増やしたと思います。

## 何が良くないのか

以下の点が良くない点です。

1. 一目で何をしたいのかがわからない。
2. 今後、条件が増えた時に誤修正が発生しそう。

## 改善方法

三項演算子での最大値選択から、関数で最大値を返却するようにする。

``` C#
int max_file_size()
{
    int max = MAX_A_FILE_SIZE;

    if (max < MAX_B_FILE_SIZE)
    {
        max = MAX_B_FILE_SIZE;
    }
    if (max < MAX_C_FILE_SIZE)
    {
        max = MAX_C_FILE_SIZE;
    }

    return max;
}
```
より良い方法はいくつかありますが、当初の三項演算子だらけよりも読みやすくなり、改修しやすくなったと思います。

## まとめ

工数削減するために無理に拡張するより、工数や手間を増やしてでも作り直したほうがいいよ。という話でした。
Raspbianに接続したUSBをSFTPでアクセスできるようにしたメモ


## 環境

```
grep "PRETTY_NAME" /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
```

## 目的

USBで接続したexFATでフォーマットされているストレージにSFTPでアクセスしたい。

## 前提条件

ストレージのファイルシステムは「exFAT」
sftpクライアントは「WinSCP」

## 手順

1. [USBストレージを自動マウントするように設定](https://qiita.com/miyabi_ver39/items/46da8e544f08f9952092)
2. sftp専用ユーザを作成
3. 公開鍵認証でsftpユーザがアクセスできるようにする
4. WinSCPからsftpでアクセスする

### USBストレージを自動マウントするように設定

[USBストレージを自動マウントするように設定](https://qiita.com/miyabi_ver39/items/46da8e544f08f9952092)

### sftp専用ユーザを作成

SFTP以外は操作させたくないため、ログイン禁止ユーザを作成する。
ユーザ名は今回は「sftp-user」とする。

```
$ sudo useradd sftp-user -m -p sftp-user -s /usr/sbin/nologin
```

### 公開鍵認証の設定

アルゴリズムは意識の高いed25519にする。
パスワードは念の為、設定しておく。総当たりを回避できれば良いので、30文字程度で良さそう。

```
# 鍵作成
ssh-keygen -t ed25519 -N "<ココにパスワードを記載>" -C "sftp-user" -f "./id_ed25519"

# 公開鍵を追記する
$ sudo mkdir -p /home/sftp-user/.ssh
$ sudo sh -c "cat ./id_ed25519.pub >> /home/sftp-user/.ssh/authorized_keys"
$ sudo chown sftp-user:sftp-user /home/sftp-user/.ssh
$ sudo chown sftp-user:sftp-user /home/sftp-user/.ssh/authorized_keys
$ sudo chmod 600 /home/sftp-user/.ssh/authorized_keys
```

秘密鍵はSSHクライアントのSCP機能を使って、ローカルに保存するのが良さそう。

### sftpの設定

sftpはsshでやり取りするため、「/etc/ssh/sshd_config」を編集します。

以下のように設定します。

```
Match group sftp-user
  ChrootDirectory /media/sftp
  ForceCommand internal-sftp
```
対象グループは追加した「sftp-user」としました。
ディレクトリは「/media/sftp/」とするようにしました。

sftpを有効にする場合、親ディレクトリは所有者が「root」、パーミッションは「755」でないとアクセスできません。

```
$ sudo chown root:root /media/sftp
$ sudo chmod 755 /media/sftp
$ ls -la /media/
drwxr-xr-x  3 root root 4096  5月 22 00:59 .
drwxr-xr-x 23 root root 4096  1月 28 02:07 ..
drwxr-xr-x  3 root root 4096  5月 22 00:59 sftp
```

設定ができたら、sshを再起動させます。

```
$ sudo systemctl restart ssh
```

### USBストレージの設定

対象ストレージのファイルシステムは「exFAT」です。
exFATは権限や所有者という概念がありません。
そのため、マウント時に設定します。

### sftp専用ユーザのGIDを確認

以下のように確認します。

```
$ id sftp-user
uid=1003(sftp-user) gid=1004(sftp-user) groups=1004(sftp-user)
```

uidは「1003」で、gidは「1004」でした。
この取得したuidとgidをマウントオプションに追加します。
ついでに、マウント先を「/media/sftp/usb1」に変更します。

以下のように設定しました。

```
$ grep "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" /etc/fstab
PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX   /media/sftp/usb1   exfat    nofail,uid=1003,gid=1004          0       0
```

設定完了後、再マウントをして設定が反映されているか確認します。

```
$ sudo umount -a
$ sudo mount -a
$ ls -la /media/sftp
合計 1032
drwxr-xr-x 3 root      root         4096  5月 22 00:59 .
drwxr-xr-x 3 root      root         4096  5月 22 00:59 ..
drwxrwxrwx 1 sftp-user sftp-user 1048576  1月  1  1970 usb1
```

きちんと「sftp-user」でマウントされていますね。

### WinSCPからsftpでアクセスする

通常どおり、秘密鍵でアクセスする時と同じ手順でアクセス可能です。
転送プロトコルは「SFTP」としてください。


以上で設定完了です。

### 参考記事
[2017年版 SSH公開鍵認証で使用する秘密鍵ペアの作り方](https://qiita.com/wnoguchi/items/a72a042bb8159c35d056)
jetson_clocks

# はじめに
Jetson Nanoの各種記事を読むとコンパイル前に`jetson_clocks`コマンドでパフォーマンスを最大化してから行っている。そもそもこのコマンドが何をしているのか気になったので調べた。

# コマンドラインのヘルプ

ヘルプを見る限り、CPUとGPUとEMC(External Memory Controller)のクロックを変更できるようだ。

```bash
yamamo-to@jetson-nano:~$ /usr/bin/jetson_clocks -h
Maximize jetson performance by setting static max frequency to CPU, GPU and EMC clocks.
Usage:
jetson_clocks.sh [options]
  options,
  --show             display current settings
  --store [file]     store current settings to a file (default: ${HOME}/l4t_dfs.conf)
  --restore [file]   restore saved settings from a file (default: ${HOME}/l4t_dfs.conf)
  run jetson_clocks.sh without any option to set static max frequency to CPU, GPU and EMC clocks.

```

現在の設定は`--show`オプションで表示とのことなので、sudoをつけた上で実施した。

```
yamamo-to@jetson-nano:~$ sudo /usr/bin/jetson_clocks --show
[sudo] password for yamamo-to: 
SOC family:tegra210  Machine:jetson-nano
Online CPUs: 0-3
CPU Cluster Switching: Disabled
cpu0: Online=1 Governor=schedutil MinFreq=1428000 MaxFreq=1428000 CurrentFreq=1428000 IdleStates: WFI=0 c7=0 
cpu1: Online=1 Governor=schedutil MinFreq=1428000 MaxFreq=1428000 CurrentFreq=1428000 IdleStates: WFI=0 c7=0 
cpu2: Online=1 Governor=schedutil MinFreq=1428000 MaxFreq=1428000 CurrentFreq=1428000 IdleStates: WFI=0 c7=0 
cpu3: Online=1 Governor=schedutil MinFreq=1428000 MaxFreq=1428000 CurrentFreq=1428000 IdleStates: WFI=0 c7=0 
GPU MinFreq=76800000 MaxFreq=921600000 CurrentFreq=76800000
EMC MinFreq=204000000 MaxFreq=1600000000 CurrentFreq=1600000000 FreqOverride=0
Fan: speed=80
NV Power Mode: MAXN
```

# スクリプトの内容

このファイルは単なるシェルスクリプトなので中身を確認できる。およそ402行目から408行目にヒントが書かれている。

```
do_hotplug
do_clusterswitch
do_cpu
do_gpu
do_emc
do_fan
do_nvpmodel
```

最初にSOCファミリー(Jetson nanoはtegra210)を環境変数にセットした後、上記項目を一つずつ実行する。

- hotplugはCPUホットプラグのことで使えるCPUを全部使うようにする
- clusterswitchはディレクトリ`/sys/kernel/cluster/`の有無を確認した上でアクティブなクラスタが利用可能ならばEnableにする
- cpuは動的に変わる周波数の最小値を最大周波数(1.36GHz)に変更する
- gpuは最初にrail_gate_enableに0を書き込みクロックゲーティングを無効にし[^1]、CPU同様最小駆動周波数を最大値まで引き上げる
- EMCクロックの最小駆動周波数を最大値まで引き上げる
- FANスピードを最大(255)にする
- nvpmodelは何もしない[^2]

# まとめ

`jetson_clocks`コマンドはCPUやクラスタなど使えるものはすべて使える状態にした上で、各種動作周波数を最大まで上げるコマンドのようだ。

[^1]: GPUの動作を勉強していないがスリープ状態にさせないということか?
[^2]: `--show`オプションが指定された場合のみ動作
Lambdaでloggingすると同じログが2つ出てしまう人向け

## 概要

Lambdaには最初からルートロガーに `LambdaLoggerHandler` というのが登録されているので、ログの整形がしたいとかで自前のハンドラを追加で登録していると、ログが二重に出るようになる。

自前で登録しようとしてる人以外は知らない。

propergate=Falseとかすると良いかも。。

## 確認

```python
import logging
logger = logging.getLogger()
print(logger.handlers)
```

↑をLambda上で実行すると、

```
[<LambdaLoggerHandler (NOTSET)>]
```

コマンドラインから実行すると、

```
[]
```

## 関連

* [Pythonでロギングする（ログレベルとかメッセージのフォーマットもする時の標準的？な方法）](https://qiita.com/k_hoso/items/497dff4b2f8023f711b2)
Unity2018でシリアル通信できない問題

#はじめに
ArduinoをUnityとつなげていろいろしていて，LTS版が出たことを機にUnity2018に環境を移行させようとしたところエラーが発生したのでメモっときます．

2019/10/28　発生していたエラーについて追記しました．

#環境

- OS:Windows10
- Unity2018.4.0f1
- Arduino Uno

なお，UnityとArduinoの接続に関してはこちら[「UnityとArduinoをシリアル通信」](https://qiita.com/yjiro0403/items/54e9518b5624c0030531)にお世話になっております．

#エラー内容
いつものようにシリアル通信を行うためにAPI Compatibility Levelを.NET 2.0 Subnetから.NET2.0へ変更
（やり方は，[こちら](https://qiita.com/yjiro0403/items/54e9518b5624c0030531)を参考にお願いします．）
（Unity2018.4.0f1ではAPI Compatibility LevelがOptimizationではなくConfigurationにある点に注意）

そして，[「UnityとArduinoをシリアル通信」](https://qiita.com/yjiro0403/items/54e9518b5624c0030531)からお借りした「SerialHandler.cs」をAdd Componentしたところ...

Consoleに以下のような表示が

`Assets\SerialHandler.cs(3,17): error CS0234: The type or namespace name 'Ports' does not exist in the namespace 'System.IO' (are you missing an assembly reference?)
Assets\SerialHandler.cs(20,13): error CS0246: The type or namespace name 'SerialPort' could not be found (are you missing a using directive or an assembly reference?)`

![erro1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316749/5001975c-8773-725f-b8d9-771c7a56b096.png)

また，「SerialHandler.cs」をVS2017で開くと，![erro2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316749/b35015f1-2949-4982-b791-b43f92bc740c.png)

思いっきりエラーが出てます．

要約すると「System.IOにPertsってやつなんていないよ！」ってことなので，用意してあげたいと思います．

#解決方法

調べたら，Microsoftの公式でUnityに.NETのdllファイルを新たに入れてあげる方法がありました．

[「Unity で.NET 4.x を使用する」](https://docs.microsoft.com/ja-jp/visualstudio/cross-platform/unity-scripting-upgrade?view=vs-2019#taking-advantage-of-net-compatibility)

上記リンクの「.NET との互換性を利用する」ってところを参考に行います．

以下の方法を実行する前に**Build Settingsを開いて，プロジェクトのプラットフォームをUWP(Universal Windows Platform)に変更**してください(2019/10/28追記)


1. [このリンク](https://www.nuget.org/packages/System.IO.Ports/4.6.0-preview5.19224.8)から「system.io.ports.4.6.0-preview5.19224.8」をダウンロード（2019/05/24現在のファイル名です．）して，拡張子を「.nupkg」から「.zip」へ変更し，解凍
2. 解凍したフォルダ内の `lib/netstandard2.0` に移動し、System.IO.Ports.dll をコピー
3. Unity プロジェクトの Assets フォルダに、Plugins という名前の新しいフォルダを作成し，System.IO.Ports.dll ファイルをペースト
4. さっきと同じAssetsフォルダに link.xml という以下のファイルを作成

```xml:link.xml
<linker>
  <assembly fullname="System.Core">
    <type fullname="System.Linq.Expressions.Interpreter.LightLambda" preserve="all" />
  </assembly>
</linker>
```

以上です．

#結果
もう一回「SerialHandler.cs」をVS2017で開くと
![safe1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316749/7a89ded5-d2f6-292a-d879-38623a2debe4.png)
エラー表示が消えました～

UnityのConsoleにも表示が消えていると思います！
いやー，無事解決できてよかった！

なお，ビルドした状況で利用してないので，ビルドした場合どうなるかは不明です．


（追記1）
実は， Edit > Project Setting > Player > Inspector > Other Settings > Configuration にある Scripting Runtime Version を .NET 3.5 Equivalent に変更してもエラーは消えます．
.NET 4 にこだわる必要がない方はそっちでもいいかもしれませんね (-_-;)

（追記2）
~~現在，以下のようなエラーが確認されています．~~
~~解決策などありましたらご教授いただけると助かります．．．(-_-;)~~

`PlatformNotSupportedException: System.IO.Ports is currently only supported on Windows.`

~~2019/7/12
コメント欄で解決策を教えていただきました！
ご一読おねがいします。~~

2019/10/28
コメントを踏まえて内容を修正しました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316749/a58569a3-bcb8-f6f9-7eb7-2687672f230f.png)
Python関係まとめ

## 基本

* [Python初心者向け、あまり教えて貰えない三種の神器](https://qiita.com/k_hoso/items/f9c019e1f1d05565dc33)
* [（外）Pythonのタイムゾーンの指定の仕方（本題名：Python3のdatetimeはタイムゾーンを指定するだけで高速になる）](https://qiita.com/mattsu6/items/5511c5631e7a54550f7f)
* [VSCode+Pythonで未使用importがある場合、"問題"パネルに表示＋エディタ上で視認しやすくする](https://qiita.com/k_hoso/items/e902f53d60ce71b388c4)

## MySQL

* [Python3でMySQLdbを求められたときの問題と解決](https://qiita.com/k_hoso/items/b47d78df5e7b92d35bfa)
* [Lambda上でmysqlclientを動かす](https://qiita.com/k_hoso/items/6bab9eb288cba01cdb18)
* [Linux上でPython3でMySQLへアクセスするためのyumコマンド](https://qiita.com/k_hoso/items/578503e10b2bbbcc9c1c)
* [libmysqlclient.so.18がないといわれる](https://qiita.com/k_hoso/items/f1a2b42e85099d8bc9fb)

### dataset（ORマッパー）

* [Pythonのdataset（SQLAlchemyのラッパー）のclose系処理を調べる](https://qiita.com/k_hoso/items/85cb71216b7056864634)
* [dataset（PythonのORマッパー）で実行したSQLを取得する](https://qiita.com/k_hoso/items/562a579e8b211e8ed956)

## bytes

* [Pythonのbytesの使い方色々](https://qiita.com/k_hoso/items/fc1ed60dbd418fe60fca)

## ロギング

* [Pythonでロギングする（ログレベルとかメッセージのフォーマットもする時の標準的？な方法）](https://qiita.com/k_hoso/items/497dff4b2f8023f711b2)

## Docker

### AmazonLinux2

* [AmazonLinux2のDockerコンテナにPython3を入れる](https://qiita.com/k_hoso/items/bcd773bbfd260656e621)
iOSのARKitを使ったFaceTrakingの標準のマスクのテクスチャの当たりを作成するたった一つの方法

### はじめに
iOSのFacetrackingの標準で作成ができるARSCNFaceGeometryことグレーマスクですが、あのフェースマスクにテクスチャを貼りたいことってあると思います。しかしモデルをどのように取得したらいいかわからなかったので、今回調査してみました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61218/e1713aa9-df57-410e-91f5-4b667262a6da.png" width=50%>
###取得方法
具体的な方法は次の通りです

 1. XcodeでARSCNFaceGeometryを表示します
 2. Xcodeのヒエラルキー表示をします（実行中に、図の青い四角の部分のボタンを押します）
 3. ヒエラルキーにSCNSceneが表示されるので、選択する
 4. Exportボタンを押してDAE形式で出力する
 
<img alt="DAE出力画面" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61218/50630de3-4534-f234-eb77-1a67c21330f6.png">

### DAEとは
DAEとは、ソニーがPS3の時に提唱し、現在クロノス・グループが管理している3Dオブジェクトの形式です（現在は、glTFのほうが一般的ですが）

### マスクオブジェクトのテクスチャの当たりの作成
DAEは、Blenderでもサポートしていますし、Mayaでもサポートしていますので、お好きなツールを使ってUVを表示し、画像として保存してテクスチャ作成用の当たりを作成できます。
<img  alt="UV画像" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61218/6f898c9a-ab7f-a438-ed49-b8a3be282c50.png">

###まとめ
iOSの端末から、マスクの3Dオブジェクトを出力しUV用の当たりを作成することができました,Faceのオブジェクトを利用した面白いコンテンツを作りましょう

### FaceTrakingのデータおよび、当たりのデータ
FaceTrackingしている３Dオブジェクトおよび当たりの画像データをあげておきました、解像度などで納得がいかない場合は3Dデータから再作成してみてはいかがでしょうか。
https://github.com/tarotaro/iOSFaceMaskUVImage
Pythonでロギングする（ログレベルとかメッセージのフォーマットもする時の標準的？な方法）

## 概要

Pythonでロギングする時の手順

## 環境

* Python 3.7

## 実装

```python
import logging
import sys

# ルートロガーの取得
logger = logging.getLogger()

# ログレベルの設定
logger.setLevel(logging.DEBUG)

# ルートロガーにハンドラが登録されていない場合、自前のハンドラを用意追加する
# Lambda上で実行する場合、最初からハンドラが登録されているため、一律でハンドラを追加すると、
# ログが2つに出るようになるので注意
if len(logger.handlers) == 0:
    h = logging.StreamHandler(stream=sys.stdout)
    logger.addHandler(h)

# ハンドラにフォーマットをセットする
for handler in logger.handlers:
    handler.setFormatter(logging.Formatter("format: %(message)s"))

# 設定した内容でログがでる
logger.info("auaua")
# > format: auaua

# ルートロガーに設定を追加しているので、名前付きでロガーを取得しても設定を全部引き継ぐ
# ※厳密にいうと、名前付きロガーに打ったログ情報がルートロガーに伝播している
alogger = logging.getLogger("a")
alogger.info("alogger")
# > format: alogger

ablogger = logging.getLogger("a.b")
ablogger.info("ablogger")
# > format: ablogger

```
「Rails」タグについて(タグシノニム: 「RubyOnRails」「Ruby-Rails」「rails」「ROR」「#RubyOnRails」)

# 対象

https://qiita.com/tags/Rails

# 説明

DRY（Don't Repeat Yourself, 同じことを繰り返さない）とCoC（Convention over Configuration, 設定より規約）を基本理念としたRuby製のWebアプリケーションフレームワーク

# github
https://github.com/rails/rails

# タグシノニム

https://qiita.com/tags/RubyOnRails
https://qiita.com/tags/Ruby-Rails
https://qiita.com/tags/rails
https://qiita.com/tags/ROR
[https://qiita.com/tags/#RubyOnRails](https://qiita.com/tags/%23RubyOnRails)

# バージョン違い
https://qiita.com/tags/Rails4
https://qiita.com/tags/Rails4.2
https://qiita.com/tags/Rails5
https://qiita.com/tags/Rails5.0.0.1
https://qiita.com/tags/Rails5.1.2
https://qiita.com/tags/Rails5.2.2
https://qiita.com/tags/Rails6
https://qiita.com/tags/RubyOnRails5.2
https://qiita.com/tags/RubyonRails4.0
https://qiita.com/tags/RubyonRails5.0.0.1
https://qiita.com/tags/rails3
https://qiita.com/tags/rails3.2
https://qiita.com/tags/rails4.0
https://qiita.com/tags/rails4.1
https://qiita.com/tags/rails5
https://qiita.com/tags/rails5.1
https://qiita.com/tags/rails5.2
[https://qiita.com/tags/#rails](https://qiita.com/tags/%23rails)
[https://qiita.com/tags/#rails5](https://qiita.com/tags/%23rails5)


# 関連タグ
[「Railsチュートリアル」タグについて](https://qiita.com/j5c8k6m8/items/4a9942da598b5e787383)
HTTPを理解する①  HTTPとは？

## HTTPとは
HTTPはデータをクライアントとサーバー間でやりとりするためのプロトコル(ルール)です。私たちがwebサイトを見るときwebブラウザがほしいwebサイトのデータが保存されているサーバーに対して要求します。サーバーは要求に対して返事を返すといった流れを定めているのがHTTPです。このHTTPがデータをやりとりする上での標準となっているため、私たちは世界中から情報を得ることができます。
HTTPはHyper Text Transfer Protocolと名前がハイパーテキストの転送用プロトコルとなっていますが、実際はテキストだけでなく、画像、動画、音声、PDF、ドキュメントファイル、JSプログラムといったコンピュータで扱うデータ全般を転送することができます。

## クライアントとサーバーのやりとり
HTTPではクライアント(webブラウザ)から出したリクエストをサーバー(webサーバー)が処理をしてレスポンスとして返します。これをリクエスト/レスポンス型レスポンスといいます。実際のやりとりとして以下のようになります。
① webブラウザからURLを使用
② URLのリンク情報をもとにデータをwebサーバーに対してデータを要求
③ webサーバーは受け取った要求内容を解析
④ 解析した結果から、必要なデータをwebブラウザへレスポンスとして返答
⑤ webブラウザはwebサーバーから受け取ったレスポンスを解析して、webページとして表示する

## クライアント側がしていること
クライアント側が一つのリクエストを送り、レスポンスが返るまでにやっていることを見ていきます。
① リクエストメッセージの構築
② リクエストメッセージの送信
③ レスポンスが返ってくるまで待機
④ レスポンスメッセージの受信
⑤ レスポンスメッセージの解析
⑥ クライアントの目的を達成するために必要な処理(たりないデータを再リクエスト)

このように必要なデータ(画像やリンクなど)が揃うまで①~⑥の流れを繰り返し、最後にブラウザがHTMLを解析してウィンドウに表示します。

## レスポンス側がしていること
クライアントが送ってきたリクエストを受けたサーバー側を見ていきます。
① リクエストの待機
② リクエストメッセージの受信
③ リクエストメッセージの解析
④ 適切なアプリケーションプログラムへの処理の委譲
⑤ レスポンスメッセージの構築
⑥ レスポンスメッセージの送信
【JavaScript】入力値を監視して別のnodeに値を反映させる

```html:index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="main.js" type="text/javascript"></script>
    <script src="sha512.js" type="text/javascript"></script>
</head>
<body>
    <div>
        <h2>Input data for replace hadh</h2>
        <input id="data" type="text" value=""/>
    </div>
    <div>
        <h2>result</h2>
        <textarea id="result" type="text" value="" style="width: 390px; height: 40px"></textarea>
    </div>
</body>
</html>
```

id="data"に入力された値を常に監視し、hash関数に入れた返り値をid="result"にリアルタイムで入れる。

```javascript:setHash.js
window.onload = () => {
    const result = document.getElementById("result");
    const sethash = (it) => {
        const shaObj = new jsSHA("SHA-512", "TEXT");
        shaObj.update(it);
        result.innerText = shaObj.getHash("HEX");
    };
    document.getElementById("data").addEventListener("input" , (it) => {
        sethash(it.target.value);
    });
}
```
`shaObj`は以下のライブラリの`src/sha512.js`をコピペして、HTML上で呼び出して使用する。

https://github.com/Caligatio/jsSHA
とあるRailsエンジニアのリモートワークトライアル 2019-05-23 on Twitter

# ファミコンとかでもステージ1から最後のボスまでやり直すのってたるいよね。
プログラングのチュートリアル学習でも途中のステージから始めたりするんだろうか。2周目3周目は。
 [*](https://twitter.com/YumaInaura/status/1131324063484219392")
[@runes224](https://twitter.com/runes224/)

>#Railsチュートリアル の第14章を走破しました！ https://t.co/mORJAnI3Qx @RailsTutorialJP
>
>50時間くらい使ってようやく終わった。
>正直、10章以降は理解が曖昧なとこがあるから、また３週目やらないと😂
# 今朝はTwitter採用の返信と、Wantedlyのスカウト返信と、プライベートのTwitterAPI叩くやつのバグ修正と、波動拳画像の検索を次々にこなせたので、一気に4個のタスク消化をして脳に優しくなれた水曜日の朝だった。
今日って水曜日だよね？
 [*](https://twitter.com/YumaInaura/status/1131330730179452928")

# 飲食業に比べたらプログラミング業界のハードさなんて。

 [*](https://twitter.com/YumaInaura/status/1131336582953226241")
[@toshi65811](https://twitter.com/toshi65811/)

>エンジニア界隈の初心者への優しさは異常。数年前、一瞬すし職人を目指して寿司学校行って働いてみたけど、死ぬほど厳しかったぞ。
>なのになんだ、この優しい世界は。
>
>ちなみにこれ卒業時に握ったやつ。あの時すし学校じゃなくプログラミングスクールに行ってたらな…😭 https://t.co/EKSbY9J7gi
![image](https://pbs.twimg.com/media/DxG8ATlUYAAel6r.jpg)

# プログラミングスクールをディスるのはひねくれた恋のようです。

 [*](https://twitter.com/YumaInaura/status/1131337356810772483")
[@KMY774774](https://twitter.com/KMY774774/)

>昨日も今日もだけど、ほぼ毎日ウェブカツ（と顧問）をdisるツイがRTなどで流れてくる。名前を出さないように、身内で巧妙にコソコソしながら毎日話題にしてるってもはや恋では。
>
>エンジニアって名乗る人たちが陰湿でスケープゴート探してる人ばっかりでうんざり。
# とあるRailsエンジニアのリモートワークトライアル 2019-05-22 on Twitter [ポエム] on @Qiita
 [*](https://twitter.com/YumaInaura/status/1131342405972553729")
<https://qiita.com/YumaInaura/items/b07c6b7a03ac4cf9bcce>
# 飲食業に比べたらプログラミング業界のハードさなんて。
  2019-05-23 on Twitter
 [*](https://twitter.com/YumaInaura/status/1131395728042004485")
<https://github.com/YumaInaura/YumaInaura/issues/1978>
# Apppppplllllllleeeeeeeeeeeeeeeeeeeeeee!!!!!!!!

"MacBookのキーボード無償修理プログラム、全モデルに拡大。
出たばかりの2019年モデルも対象"
 [*](https://twitter.com/YumaInaura/status/1131440231847063552")
<https://japanese.engadget.com/2019/05/21/macbook-2019/>



# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1984








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
画像データの水増し

###機械学習などで十分に画像が集まらなかった際にすでにあるデータを使ってデータの量を増やすことができる。


```python:mizumashi.py
#画像の水増し
import os
import glob
import numpy as np
from keras.preprocessing.image import ImageDataGenerator,load_img, img_to_array, array_to_img

# 画像を拡張する関数
def draw_images(generator, x, dir_name, index):
    save_name = 'extened-' + str(index)
    g = generator.flow(x, batch_size=1, save_to_dir=output_dir,
                       save_prefix=save_name, save_format='jpeg')

    # 1つの入力画像から何枚拡張するかを指定（今回は10枚）
    for i in range(10):
        bach = g.next()

# 出力先フォルダの設定
output_dir = "出力先のフォルダの名前"

if not(os.path.exists(output_dir)):
    os.mkdir(output_dir)

# 拡張する画像の読み込み
images = glob.glob(os.path.join("拡張したい画像が入ったフォルダの名前", "*.jpg"))

# ImageDataGeneratorを定義
datagen = ImageDataGenerator(rotation_range=20,
                            width_shift_range=0,
                            shear_range=0,
                            height_shift_range=0,
                            zoom_range=0,
                            horizontal_flip=True,
                            fill_mode="nearest",
                            channel_shift_range=40)

# 読み込んだ画像を順に拡張
for i in range(len(images)):
    img = load_img(images[i])
    img = img.resize((350,300 ))
    x = img_to_array(img)
    x = np.expand_dims(x, axis=0)
    draw_images(datagen, x, output_dir, i)
```
pythonの基本的なデータベースの処理について

未来電子テクノロジーでインターンをしている山田です。
プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

pythonの標準ライブラリに含まれる、sqlite3モジュールを使うことで、pythonでデータベースを扱うことができます。

##モジュールの読み込み
まず、モジュールを読み込みます。
import sqlite3

##データベースファイルの作成
conn = sqlite3.connect('sample.db')

このコードで、新しくデータベースファイルを作成します。
作成場所はサーバーを立ち上げたディレクトリです。
既にファイルが存在する場合、そのファイルにアクセスすることと同義です。


##カーソルの作成
curs = conn.cursor()

カーソルとは、データベースを処理するときの現在位置を示すものです。
カーソル作成以降は、
curs.execute(SQL文)
でデータベースを扱うことができます。

##テーブルの作成
curs.execute("CREATE TABLE　data(id INTEGER PRIMARY KEY AUTOINCREMENT, A, B, C...)")

テーブルは、データベースに値を入れるための欄みたいなものです。
さきに枠組みを作るイメージです。
idの部分は自動割り振りですが、必要なければ削除してください。


既にテーブルがあるときにこの処理をまた行うとエラーが出たので、その時は
curs.execute("CREATE TABLE if not exists data(id INTEGER PRIMARY KEY AUTOINCREMENT, A, B, C...)")
と書くとテーブルが未作成の場合のみの条件分岐ができます。


##値の挿入
curs.execute("INSERT INTO data(A, B, C) values('a', 'b', 'c')")

データベースで管理したい値を入れていきます。

curs.execute("INSERT INTO data(A, B, C) values(?, ?, ?)",[a, b, c])
とすることで、[]内に変数を用いることができます。

##データベースの保存
conn.commit()

このコードでデータベースを保存します。
これがないとページ移動でデータが消えてしまいます。

##カーソル、データベースの終了
curs.close()
conn.close()

それぞれ、通信を終えます。
フォルダの中の複数の画像ファイルから顔の部分を切り取る。

###[前回記事](https://qiita.com/baraobara/items/39fa9e6eac40dfa56460)では単一の画像で顔の切り出しを行なったが、より使いやすくするためにフォルダ内の複数画像で顔の切り出しを行う場合でも使えるようにする

####
[参考サイト1](https://qiita.com/FukuharaYohei/items/457737530264572f5a5b)
[参考サイト2](https://www.robotech-note.com/entry/2016/12/08/204143)
[参考サイト3](http://jd-engineer.hateblo.jp/entry/2017/02/24/202747)

###
multiface_cut.pyとinput(処理したい画像が入ったフォルダ）とoutputs(処理後の画像を入れたいフォルダ）を同じ階層に配置してある。

###　複数の画像が入ったフォルダから画像を取り出して処理し、特定のフォルダに保存するコード
```python:multiface_cut.py
import cv2
import glob


HAAR_FILE = "./models/haarcascade_frontalface_default.xml"
cascade = cv2.CascadeClassifier(HAAR_FILE)


files = glob.glob(os.path.join("./input/*.jpg"))
files = [s.replace('./input/', '') for s in files]
for file_name in files:
    img = cv2.imread('input/'+file_name)
    img_g = cv2.imread('input/'+file_name,0)
    face = cascade.detectMultiScale(img_g)
    for x,y,w,h in face:
        face_cut = img[y:y + h, x:x + w]
        cv2.imwrite("./outputs/"+file_name, face_cut)
```
JavaScript で配列の shallow copy をする better な方法

# 動機

タイトルのとおり、JavaScript で配列のコピーをする必要がありました。
Qiita などで幾つかの方法が紹介されていましたが、
「じゃぁ、どれが一番適切なの？」という疑問が湧き、
その疑問を解決するべく調べた結果を報告します。

# 結論

結論を先に述べると、 執筆時点では Array.slice() を用いる方法が一番高速でした。

５種類の shallow copy のアルゴリズムと、処理速度比較結果を表示するサイト
https://jsperf.com/duplicate-array-slice-vs-concat/31　
での実行結果を以下に示します。

### 実行結果

動作環境
- CPU: Intel Core i7-2770K 3.50GHz
- Mem: 32GB
- OS: Windows 10 (64bit)

評価方法
- Browser は Google Chrome, Firefox, MS Edge の３種類を使用
- ５回の試行で評価（実行タイミングを公平にするため、各ブラウザ１回ずつの試行を１セットとして５セットを実施）

(1) Google Chrome 74.0.3729

|    アルゴリズム       | 実行速度[Ops/sec] | 標準偏差 | 備考  |
|:---------------------|-----------------:|--------:|:-----:|
| while [] preallocate |          1337.8  |    89.5 |       |
| Array.slice          |          1889.4  |   124.2 | 最速! |
| while push           |           197.4  |    20.5 | worst |
| while []             |           418.2  |    19.5 |       |
| Array.concat         |          1348.8  |    64.9 |       |

(2) Firefox 66.0.0

|    アルゴリズム       | 実行速度[Ops/sec] | 標準偏差 | 備考  |
|:---------------------|-----------------:|--------:|:-----:|
| while [] preallocate |           603.6  |    21.7 |       |
| Array.slice          |          1344.4  |   110.0 | 最速! |
| while push           |           650.4  |    39.7 |       |
| while []             |           608.8  |    40.8 |       |
| Array.concat         |           500.6  |    27.5 | worst |

(3) Microsoft Edge 17.17134.0

|    アルゴリズム       | 実行速度[Ops/sec] | 標準偏差 | 備考  |
|:---------------------|-----------------:|--------:|:-----:|
| while [] preallocate |           979.8  |    24.1 |       |
| Array.slice          |          1442.4  |    12.4 | 最速! |
| while push           |           182.8  |    13.6 | worst |
| while []             |           425.0  |    35.4 |       |
| Array.concat         |           651.4  |    59.4 |       |


### 感想

- 各ブラウザで、処理系の特徴があって面白いなぁと感じました。
- Edge の Array.slice の処理速度が安定しているのが、ちょっと不思議に感じました（単なる偶然？）。
これはこれで良い特徴だと思うのですが、今後　Chrome ベースになってしまうのが少し残念？です（競争相手が減るという意味で）。
- 今回の疑問解決において、上記サイトを見つけることができて、とても幸運でした。先人の労力に感謝！！！
PureScriptの新しいパッケージマネージャ・ビルドツール spago がいい感じだったので広めたい

何のきっかけだったか忘れてしまったのだけれど、PureScript のパッケージマネージャ・ビルドツールで [spago](https://github.com/spacchetti/spago) というものがあるのを見つけた。

少し試してみたらいい感じだったので、紹介したい。

# 背景

たいていの入門的記事には PureScript のビルドツールとして [pulp](https://github.com/purescript-contrib/pulp) 、パッケージマネージャとして [bower](https://bower.io/) をインストールするように書かれていると思う。

pulp はまあ、いいのだが、bower は公式サイトに

> ...psst! While Bower is maintained, we recommend using Yarn and Webpack or Parcel for front-end projects read how to migrate! 

と書かれているように新しいプロジェクトではもう使わないようにしたほうがよさそうな雰囲気。

また代替として紹介される [psc-package](https://psc-package.readthedocs.io/en/latest/) も少し触ってみたが、[Pursuit](https://pursuit.purescript.org/) で検索して見つけたパッケージが登録されていなくて使えなかったり、手動で含めようにもやり方がよくわからない・手軽にできない[^1]のがいまいちな感じがした。

[^1]: [package-set](https://github.com/purescript/package-sets) に PR して入れてもらわなければならないっぽい？ 英語がちゃんと読めていないだけかもしれない…。

# spago の紹介

spago は PureScript 向けのパッケージマネージャ・ビルドツール。
パッケージマネージャとしては psc-package と同じく package-set を利用しているが、dhall を使って簡単に上書きや追加ができるのがとてもうれしいところ。
spago そのものも Haskell で開発されているためか、npm でインストールしても余計な依存関係が全然ない。

また psc-package を使ったプロジェクトで `spago init` とすれば、既存の設定を spago 用に移行してくれる。

[この記事](https://bouzuya.hatenablog.com/entry/2018/12/29/233209)には

> 残念なのは `spago repl` がないこと。たぶん近いうちに追加されるだろうな。

とあるが、予想されていた通り現在は使用できるようになっている。

pulp + psc-package でできたことは大体 spago 一つで可能なようだ。

ただ1点私も残念に思うところがあって、それは pulp にはあった簡易サーバー機能がないこと。

フロントエンドアプリを作っていると、確認用にサーバーが欲しくなる時があり、pulp だと組み込み機能でそれができたのだが、spago ではどうやらできないもよう。

その辺は Webpack や Parcel と組み合わせてやってくれということだろうか。
プリンタ情報を出力する

プリンタ情報が知りたい場合、PowerShellから次を実行する。（全プロパティ）
プロパティは適宜削る。
※このままではステートメント長すぎてエラーとなる。

- Get-WmiObject Win32_Printer 対象プロパティ[,対象プロパティ[,対象プロパティ...]]

##全項目表示するにはこちら

- Get-WmiObject -Class Win32_Printer | Format-List -Property *
- Get-WmiObject -Class Win32_Printer | Select-Object -Property *

##プロパティ
Attributes
Availability
AveragePagesPerMinute
Capabilities[]
CapabilityDescriptions[]
Caption
CharSetsSupported[]
Comment
ConfigManagerErrorCode
ConfigManagerUserConfig
CreationClassName
CurrentCapabilities[]
CurrentCharSet
CurrentLanguage
CurrentMimeType
CurrentNaturalLanguage
CurrentPaperType
Default
DefaultCapabilities[]
DefaultCopies
DefaultLanguage
DefaultMimeType
DefaultNumberUp
DefaultPaperType
DefaultPriority
Description
DetectedErrorState
DeviceID
Direct
DoCompleteFirst
DriverName
EnableBIDI
EnableDevQueryPrint
ErrorCleared
ErrorDescription
ErrorInformation[]
ExtendedDetectedErrorState
ExtendedPrinterStatus
Hidden
HorizontalResolution
InstallDate
JobCountSinceLastReset
KeepPrintedJobs
LanguagesSupported[]
LastErrorCode
Local
Location
MarkingTechnology
MaxCopies
MaxNumberUp
MaxSizeSupported
MimeTypesSupported[]
Name
NaturalLanguagesSupported[]
Network
PaperSizesSupported[]
PaperTypesAvailable[]
Parameters
PNPDeviceID
PortName
PowerManagementCapabilities[]
Attributes
Availability
AveragePagesPerMinute
Capabilities[]
CapabilityDescriptions[]
Caption
CharSetsSupported[]
Comment
ConfigManagerErrorCode
ConfigManagerUserConfig
CreationClassName
CurrentCapabilities[]
CurrentCharSet
CurrentLanguage
CurrentMimeType
CurrentNaturalLanguage
CurrentPaperType
Default
DefaultCapabilities[]
DefaultCopies
DefaultLanguage
DefaultMimeType
DefaultNumberUp
DefaultPaperType
DefaultPriority
Description
DetectedErrorState
DeviceID
Direct
DoCompleteFirst
DriverName
EnableBIDI
EnableDevQueryPrint
ErrorCleared
ErrorDescription
ErrorInformation[]
ExtendedDetectedErrorState
ExtendedPrinterStatus
Hidden
HorizontalResolution
InstallDate
JobCountSinceLastReset
KeepPrintedJobs
LanguagesSupported[]
LastErrorCode
Local
Location
MarkingTechnology
MaxCopies
MaxNumberUp
MaxSizeSupported
MimeTypesSupported[]
Name
NaturalLanguagesSupported[]
Network
PaperSizesSupported[]
PaperTypesAvailable[]
Parameters
PNPDeviceID
PortName
PowerManagementCapabilities[]
PowerManagementSupported
PrinterPaperNames[]
PrinterState
PrinterStatus
PrintJobDataType
PrintProcessor
Priority
Published
Queued
RawOnly
SeparatorFile
ServerName
Shared
ShareName
SpoolEnabled
StartTime
Status
StatusInfo
SystemCreationClassName
SystemName
TimeOfLastReset
UntilTime
VerticalResolution
WorkOffline
XcodeでOpenCVのヘッダーファイルが読み込めない時

# はじめに
XcodeでOpenCVを使おうと思い、[こちら](https://qiita.com/bird_tummy/items/0b927e3682726f192fd1)のサイトを参考にさせて進めたのですが、エラーが出てしまったので、その時の解決法について書いておきます。

# 環境
OpenCV：4.1.0
Xcode：10.2.1

# ヘッダーファイル

まずヘッダーファイルについてですが、記事を参考にして以下のようにするとエラーが出ました。

```
// これだとエラーが出る
#include <cv.h>
#include <highgui.h>
#include <ctype.h>
```

`opencv/cv.h' file not found`とエラーが出てしまいました。
実はこれはOpenCVのバージョン2.1までで2.2以降は以下のようにします。

```
#include <opencv2/opencv.hpp>
```

これでとりあえずエラーは消えるはずです。

もしこれでもエラーが出る場合は「Build Setting」の
「Search Paths」 > 「Header Search Paths」を確認してみてください。

`/usr/local/Cellar/opencv/4.1.0_2/include`をrecursiveで追加していることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260272/7855a2e1-34b0-9aed-dc3d-e77dbd7248f4.png)


# リンクエラーを直す

これでコンパイルできると思いきや、次はこのようなエラーが出てしまいました。

```
undefined reference to cv::VideoCapture::VideoCapture(int)
```

この原因はリンクが上手くできていないことです。

「Build Phases」の「Link Binary With Libraries」にライブラリを加えます。

フォルダで`/usr/local/Cellar/opencv/4.1.0_2/lib/`を開き、エイリアスでない.dylibファイルを全てドラッグ&ドロップします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260272/85eebe55-6d7c-fac8-9586-2de67a419c66.png)

# サンプルコード

```
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;

int main(){
    cv::Mat imMat(256,256, CV_8UC3);
    
    for(int y = 0 ; y < imMat.rows; y++){
        for(int x = 0 ; x < imMat.cols; x++){
            cv::Vec3b &p = imMat.at<cv::Vec3b>( y, x);
            p[0] = x;
            p[1] = y;
            p[2] = (int)((x+y)/2);
        }
    }
    imshow("openCVTest",imMat);
    waitKey(0);
    return 0;
}

```

# 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260272/9e4ac0b7-9af6-5640-97ae-84e8579c44cc.png)

無事OpenCVを使うことができました。

# まとめ
もとはと言えば検索して上に出てきたからと言って記事の日付も確認しなかったのがいけませんでした。環境構築はバージョンの違いによるエラーが多いので、参考記事のバージョンを確認するよう意識しようと思います。

# 参考

- [Homebrew と Xcode で OpenCV の環境を作る](https://qiita.com/bird_tummy/items/0b927e3682726f192fd1)
- [XcodeでOpenCVを使えるようにする](http://shirashinomiya.hatenablog.com/entry/2018/07/26/212524)
先頭に$がついたコマンドを素早くコピペして実行する方法

## 先頭に$がついたコマンドを素早くコピペして実行する方法
記事中にコマンドが出てくる場合、先頭に`$`がついていることがあります。
例

```bash
$ ls
```

これを全部コピペして実行すると`command not found`になります。
そこで先頭の`$`を消す必要があるのですが、ここで便利な小技があります。
ctrl + Aからのctrl + Dでカーソルを先頭に移動して、カーソルの右側の一文字を消すことができます。
便利ですのでぜひご活用ください。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
Magic Leap MagicScript Landscape Application. UiTab

Prepare
Magic Leap One
https://www.magicleap.com/magic-leap-one

mlsdk v.0.20.0
https://creator.magicleap.com/downloads/lumin-sdk/overview

magic-script-cli v2.0.1
https://www.npmjs.com/package/magic-script-cli

magic-script-polyfills v2.2.0
https://www.npmjs.com/package/magic-script-polyfills

image file
https://pixabay.com/ja/illustrations/%E3%83%80%E3%82%A4%E3%83%A4%E3%83%A2%E3%83%B3%E3%83%89-%E5%88%86%E9%9B%A2-%E9%80%8F%E6%98%8E-1857736/

3d model file
https://poly.google.com/view/esWz3QtmDCX

**Create Project**

```sh
magic-script init my-tab org.magicscript.tab "Tab"
cd my-tab
mkdir res
```
place imgae file and 3d model file in res folder.

**Code**

Change app.package

```sh
DATAS = "digest.sha512.signed" : "." \
        "bin/" : "bin/" \
        "res/" : "res/"
OPTIONS = package/minApiLevel/2
```
Change app.js

```jsx
import { LandscapeApp, ui } from 'lumin';
const { 
  UiTab,
  UiText,
  UiImage,
  UiLinearLayout, 
  EclipseLabelType, 
  Orientation, 
  Alignment} = ui;

export class App extends LandscapeApp {
  onAppStart () {
    const prism = this.requestNewPrism([0.9, 0.3, 0.5]);
    const topLayout = UiLinearLayout.Create(prism);
    const text = UiText.Create(
      prism, "Standard Tabs:", EclipseLabelType.kT7);
    
    text.setTextSize(0.0303);
    topLayout.addItem(text, 
        [0.04, 0.04, 0, 0], Alignment.CENTER_LEFT);
    topLayout.setOrientation(Orientation.kHorizontal);
    
    const tabLayout = UiLinearLayout.Create(prism);
    tabLayout.setOrientation(Orientation.kVertical);
    
    const tab1 = UiTab.Create(prism, "Tab1");
    tab1.setTextColor([1, 1, 1, 0.4]);
    tabLayout.addItem(tab1,
        [0, 0, 0.02, 0.02], Alignment.CENTER_LEFT);
    
    const tab2 = UiTab.Create(prism, "Tab2");
    tab2.setTextColor([1, 1, 1, 0.4]);
    tabLayout.addItem(tab2, 
        [0, 0, 0.02, 0.02], Alignment.CENTER_LEFT);
    
    topLayout.addItem(tabLayout, 
        [0.04, 0.04, 0, 0], Alignment.CENTER_LEFT);
    
    const resource = prism.createModelResourceId(
        "res/ar-poop-vroom.glb", 0.1);
    const model = prism.createModelNode(resource);
    const image = UiImage.Create(prism, 
        "res/diamond-1857736_640.png", 0.1, 0.1);
    topLayout.addItem(image, 
        [0.04, 0.04, 0, 0], Alignment.CENTER_LEFT);
    tab1.onActivateSub(function(event)
      {
        topLayout.removeItem(2);
        topLayout.addItem(image, 
          [0.04, 0.04, 0, 0], Alignment.CENTER_LEFT);
      }  
    );
    tab2.onActivateSub(function(event)
      {
        topLayout.removeItem(2);
        topLayout.addItem(model, 
          [0.04, 0.04, 0, 0], Alignment.CENTER_LEFT);
      }  
    );
    prism.getRootNode().addChild(topLayout);
  }
}

```

**Build**

```sh
magic-script build -i
```

**Run**

```sh
magic-script run --port=10000
```

**Reference**
UiTab(Magic Script API Doc)
https://docs.magicscript.org/lumin.ui.UiTab.html

Tabs (UiTab)(Guide C++)
https://creator.magicleap.com/learn/guides/luminrt-uitab

magicscript
https://www.magicscript.org/

Thanks!
AWS Cloud9、踏み台経由設定でのハマりポイント

ブラウザ上で使えるクラウドIDE「aws cloud9」の実行環境を、ssh経由のサーバーで稼働させ、かつ踏み台経由で接続する設定の場合に一つハマったので、知見を共有しておきます。

開発環境が一通り入っているサーバーを外のネットワークに直に晒すのは気持ち悪いので、awsのpublic subnetにある踏み台とprivate subnetにある実働サーバーというよくある構成を考えます。
ここでsshの踏み台にするec2インスタンス(以下サーバーA)、Cloud9を実際にホストするec2インスタンス(以下サーバーB)とも、aws EC2の現時点でのデフォルトOSであるamazon linux2で仮想マシンを生成しておきます。
(awsのVPCやサブネットの構築などについてはすでに知っている前提とします)

また、サーバーBにはCloud9が要求する開発ツール類を事前に一通り入れておきます。

```
sudo yum update -y
sudo yum groupinstall -y "Development Tools"
sudo yum install -y glibc-static
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
. .bashrc
nvm install v10
```

ここから、新規にCloud9の接続設定を作ります。
サービス一覧からCloud9を選択、"Create environment"で適当に環境名を指定して"Next step"をクリックして設定画面に移行。
今回はSSH接続にしたいのでEnvironment typeは「Connect and run in remote server (SSH)」を選択。ユーザー名、サーバーBのローカルIP、ポート番号を入力。
また、"Copy key to clipboard"でコピーした公開鍵を、この時点でサーバーA、サーバーBとも、
~/.ssh/authorized_keysに追加しておきます。
続いてAdvanced settingsを開き、"SSH jump host"の項目に
踏み台にするホストAのユーザー名とIPを設定します。
![FireShot Capture 004 - Create a new environment - ap-northeast-1.console.aws.amazon.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224954/38bf6314-67a6-ac2d-2178-e0124201d1f1.png)

これで下の"Next step"ボタンをクリックすると(ちょっとスクリーンショットのキャプチャ範囲が見切れていますが)確認画面に進むはずが、なぜか「AWS Cloud9 couldn't connect to SSH server」と出て進めません。
![FireShot Capture 006 - Create a new environment - ap-northeast-1.console.aws.amazon.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224954/03dd58c4-4d1e-586b-973d-dea828c55454.png)

ここから先に進めずにしばらく無駄に時間を費やしたのですが、AWSのディスカッションフォーラムに答えがありました。
https://forums.aws.amazon.com/thread.jspa?messageID=872411&tstart=0
> The Amazon Linux 2 AMI does not come pre-installed with one of the Cloud9 SSH required packages nc/netcat. I manually installed the nc package (sudo yum install nc -y) on the Jump Host instance which resolved the Cloud9 SSH connection issue. An alternative would be to use the Amazon Linux 1 AMI as my Jump Host instance.

amazon linux 2の初期状態では、nc(netcat)コマンドが入っていないために踏み台経由の初期化処理を実行できない、というのが原因でした。
そこでサーバーAで

```
sudo yum install -y nc
```
を実行し、もう一度"Next step"をクリック。
今度は無事設定確認画面に進んだので、あとはクリックして進めていくだけでOK。
無事Cloud9が起動しました。
![FireShot Capture 012 - c9test - AWS Cloud9 - ap-northeast-1.console.aws.amazon.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224954/7e8e01f6-1569-8f66-cc8c-10a614c57679.png)

同じawsの中なのに、意外なところでハマるもんですね。
require_onceでファイルの読み込み、色々あるけど結局どう書けばいいのか

##結論 
```php:index.php
require_once __DIR__.'/foo/A.php';
```
これが一番てっとり早くて、設定による差異もなさそう。

https://php.net/manual/ja/language.constants.predefined.php
>そのファイルの存在するディレクトリ。include の中で使用すると、 インクルードされるファイルの存在するディレクトリを返します。 つまり、これは dirname(\_\_FILE__) と同じ意味です。 ルートディレクトリである場合を除き、ディレクトリ名の末尾にスラッシュはつきません。

## ディレクトリ構成
/src/をドキュメントルートに指定している想定

```
src/
  foo/
   A.php
   B.php
  index.php
```

### 相対パスでの指定
```php:A.php
require_once 'B.php';
```
```php:index.php
require_once 'foo/A.php';
```

相対パスでもindex.phpからA.phpを読み込むことは可能ですが、
A.phpで同じく相対パスを使ってB.phpを読み込んでいた場合エラーになります。

相対パスで記述した場合はPHPファイルを実行したファイルがある位置からの相対パス、
つまりこの場合であればsrc/foo/B.phpではなく、存在しないsrc/B.phpをよんでいることになります。


### ドキュメントルートからの指定

```php:index.php
require_once $_SERVER['DOCUMENT_ROOT'].'/foo/A.php';
```
https://www.php.net/manual/ja/reserved.variables.server.php

>現在実行されているスクリプトが存在するドキュメントルート ディレクトリです。サーバーのコンフィグレーションファイルで 定義されています。

$\_SERVER['DOCUMENT_ROOT']はApacheの場合httpd.confで設定されています。
ローカルと本番環境など設定によっては差異があることがあります。

### サーバーのルートからの指定

```php:index.php
require_once '/var/www/html/src/foo/A.php';
```
ドキュメントルートとサーバーのルートは別物です。
現在は/src/をドキュメントルートに設定しているという想定ですが、
サーバーのルートからパスを指定する場合はドキュメントルートより上のディレクトリも記述しないといけません。
/var/www/html/はサーバーの設定によって異なります。


### include_pathでの指定
```php:index.php
require_once 'foo/A.php';
```
https://www.php.net/manual/ja/function.include.php
>ファイルのインクルードは、指定されたパスから行います。パスを指定しない場合は、 include_path の設定を利用します。 ファイルが include_path に見つからないときは、include は呼び出し元スクリプトのディレクトリと現在の作業ディレクトリも探します。

相対パスと同じ記述方法ですが、include_pathが設定されている場合、include_pathから先にファイルを探してくれるようです。
include_pathはphp.iniや.htaccess、set_include_path関数などで設定できます。

### dirname(\_\_FILE__)での指定

\_\_DIR__と同じ意味です。

\_\_DIR__が追加されたのが5.3.0以降なのでそれ以前のバージョンではこちらを使用します。

https://php.net/manual/ja/language.constants.predefined.php

>| 5.3.0 | \_\_DIR__ と \_\_NAMESPACE__ が追加されました。 |
|:--|:--|


## 以下余談

### include, requireの違い
処理失敗時にエラーを発するか、警告を発するか。

require : エラー（処理がストップする）
include : 警告（処理は続行）

https://www.php.net/manual/ja/function.require.php

### require_onceとrequireの違い

require_onceは一度しか呼び出さない。

```php:foo.php
$foo = 1;
```
```php:bar.php
$bar = 1;
```
```php:index.php
require_once 'foo.php';
$foo ++;
var_dump($foo);  // 2

/*
  foo.phpは一度しか呼び出されないので$fooが初期化されない
*/
require_once 'foo.php';
var_dump($foo);  // 2


require 'bar.php';
$bar ++;
var_dump($bar);  // 2

/*
 　bar.phpがもう一度呼び出されるのでbar.phpが初期化される
*/
require 'bar.php';
var_dump($bar);  // 1
```

### オートローダを使う
いちいちrequire_onceを記述するのも面倒なのでオートローダを使った方が良さそう。
オートローダーはspl_autoload_registerを使って自作することもできますが、
Composerを使うのが楽でよさそうです。

[Composerでautoload.phpを作成する](https://qiita.com/tkek321/items/80b20f341f29f3ecf381)

## 参考
[【PHP】include, requireの安全なパスの書き方と違い](http://web-codery.com/php/135)
[【PHP】include, requireの違いと使い分け](http://web-codery.com/php/284)
IT系行事の会場下見前確認事項、設営

IT系イベント実施の会場設営チェックリストを作った
https://qiita.com/surumegohan/items/60f435d8ad13d59041fe

自己経験で補足中。

#会場下見前確認項目

#会場までの道のり
##何種類の情報源があるか
建物の設置者、会場の所有者、会場のサービス主体など、同じ場所で複数のWeb情報があり、詳細度が違う場合がある。何種類の情報があるかを下見前に確認しておく。

それぞれの情報のうち、どれが最新か、どれが詳細かを確認する。

#駐車場
会場に無料の駐車場があるかどうか。
行事参加者が無料または割安で借りられる駐車場があるかどうか。
有料の駐車場で、満車にならない可能性がある格安なところはどこか。


#搬入口、搬入用エレベータの存在の有無の確認

主催者が機材を搬入するか、機材の搬入が必要な参加者がいるかで、
会場に駐車場がなくても、搬入口、搬入用エレベータ有無を事前確認し、
現地で再確認するとよい。

備え付けの台車が借りられるかどうかも重要。借りられなければ、台車持参しないと腰痛める。

#会場下見確認項目

#会場までの道のり
##何種類の情報源があるか
建物の設置者、会場の所有者、会場のサービス主体など、同じ場所で複数のWeb情報があり、詳細度が違う場合がある。何種類の情報が

##Webに記載の経路で、道路の刑事、建物の看板などがわかるか。

似た名前の建物が近所にあれば、どれくらいあるかの一覧を作るとよいこともある。

####実例：
名古屋市北区にあった名古屋工業技術研究所と、
名古屋市熱田区にある名古屋市工業研究所、
技術があるか、市があるかの違いで、間違っていった講演者がいる。

区名を言わないとタクシーが間違えることもあるらしい。

検索するから大丈夫というのは、検索する場所の名前を間違えずに全部入れた場合の話。
似た施設があれば、全部入れないと違う方へ誘導することあり。

#投影機動作確認

音声を流す場合には、接続方法、スピーカーのワット数などを記録。

PCがプロジェクタに映るかどうかを確認するだけでは不十分。
最終的には、講演者が事前に接続試験をすることが大事。
事前に機材の型番を調べて置き、マニュアルをダウンロードしておくとよい。

機材によっては、PCとプロジェクタが、相互に動的に設定を変えて、無限ループに入って映らないことがある。

どちらかの設定を固定して、無限ループにならないようにするには、機材の方を自動認識しないようにする設定がわかっていることが大事。

接続方法は、HDMI, VGAでもコネクタの種類はいろいろある。変換ケーブルなどを数種類用意しているとよい。

PCがモニターに映るかどうかを確認する
モニタなのか、スクリーンなのか、HDMIなのか、VGAなのか、数、位置、投影時の操作
登壇者のPC、デバイスから音量が流れるか
HDMIだとしも、OSやケーブル相性に注意
マイクジャックを抜き差しする際に騒音がでるケースがある
最悪、PCなどのデバイスにマイクを近づけて対応できるか

##会場の音量制限
展示会などでは、通路での最大音量が何ホーンかを決めていることがある。
実際に音を出して、規定以内かどうか確認するとよい。

登壇者のマイク、参加者のわいがや、スマートスピーカーの音などの音量が他会場に迷惑にならないか
モニタなのか、スクリーンなのか、HDMIなのか、VGAなのか、数、位置、投影時の操作
登壇者の声が伝わるか
登壇者の声が会場全体に伝わるか
狭い会場ならマイクなしでも良い
スマートスピーカーのような音をだすデバイスの音量が会場全体もしくは展示箇所で十分伝わるか

##マイク数
大きな会場では、司会用、登壇者、質問者２つの合計４つ用意することがある。

質問者にマイクを回すより、マイクスタンドを１つか２つ立て、質問者はそこに並んでもらう方がよいこともある。

マイクを持って回る人を手配するより、人でが省けるし、時間も無駄にならない。

##指示器(pointer)
会場の貸し出し、主催者が用意、講演者・参加者が各自持参など、いろいろな場合がある。
主催者が用意する場合は、くれぐれも名札を貼っておく。
【初心者向け】Goプログラムを手軽に書いて実行してみた

Go初心者向けの投稿です。
まずはGo言語を始めるにあたっての簡単なコマンドとテストコードを書いて実行しています。
## go run
「Hello,world!」をGoで書くと次のようになります。

```main.go
package main

import (
  "fmt"
)

func main () {
  fmt.Println("Hello,World!")
}
```
`$go run hello.go`

Goは基本的にコンパイルを前提としているが`go run`コマンンドでビルドプロセスを隠蔽できます。便利ですね。

## 参照のないパッケージについて
Goでは使用していない不要なパッケージがimportされているとエラーになります。
これはプログラムにゴミを残さないためにも大切ですが、エラーになるのが面倒な場合は下記指定「アンダーバー」でバイパスが可能です。

```
import (
  _ "fmt"  // 参照されないパッケージを取り込む方法
)
```

## go build
hoge.goファイルをコンパイルして実行ファイルを作成することが出来ます。
` $ go build -o hoge hoge.go `
ビルドに成功するとGoプログラムと同じディレクトリに実行ファイルが作成されます。

## go run と go buildの違い
`go run` も `go build` もコンパイルして実行ファイルのの作成をしてくれるが、`go run` の場合`go build`のようにカレントディレクトリ以下のすべてのファイルが読み込まれるわけではないです。

## goの実行ファイルはgoファイルよりも容量が大きくなる
GoはOSによって提供される標準的なライブラリに依存されないようにするため、プログラムが必要とするパッケージを実行ファイルの中に組み込んでいます。
そのため容量は大きくなります。

## パッケージとディレクトリ
Goでは「１つのディレクトリには１つのパッケージ定義のみ」という原則があります。
この原則に従わない状態でビルドを行うとエラーになります。

## 実際に動かしてみよう
<img width="300" alt="スクリーンショット 2019-05-23 23.10.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356294/189bc256-6220-bac6-554d-122b30862436.png">

```main.go
package main

import (
	"fmt"
	"./animals"
)

func  main() {
	fmt.Println(animals.CatCry())
	fmt.Println(animals.DogCry())
	fmt.Println(animals.RabitCry())
}
```
```cat.go
package animals

func CatCry() string{
	return "nya---n"
}
```
```dog.go
package animals

func DogCry() string{
	return "wanwan!!!"
}
```
```rabit.go
package animals

func RabitCry() string {
	return "usagidayo--!!!"
}
```
簡単なファイルが用意できたら`go run`で動かします！

```
$ go run main.go
nya---n
wanwan!!!
usagidayo--!!!
```
想定通りに動いてますね。
## testの記載方法について
goには標準でパッケージの機能をテストするための機能が組み込まれています。

```animals_test.go
package animals

import (
	"testing"
)

func TestCatCry(t *testing.T) {
	expect := "nya---n"
	actual := CatCry()

	if expect != actual {
		t.Errorf("%s != %s", expect, actual)
	}
}

```
## testの実行
```
$ go test ./animals
ok      _/hello-go/animals    0.006s
```
okとなっているので成功しているのが解ります。
せっかくなのでコードを変えて失敗させてみます。

変更前：

```
expect := "nya---n"
```
変更後：

```
expect := "wawanwanda-"
```

変更したらバチーンとtestコマンドを実行します。

```
$ go test ./animals
--- FAIL: TestCatCry (0.00s)
    animals_test.go:12: wawanwanda- != nya---n
FAIL
FAIL    _/hello-go/animals    0.006s
```
FAILとなってテストが失敗しているのがわかります。どこで失敗しているのかも出ているので簡単に追えますね。

## まとめ
はじめてGoに触れましたが、コマンドが豊富で記載も簡潔。開発者に優しい設計になっていますね。これからどんどん触ってどんどん投稿していきます。
写真からOpenCVを用いて顔部分を切り出す。

##参考サイト
[opencv公式](https://opencv.org/releases/)
[参考サイト](https://newtechnologylifestyle.net/opencv_face_trimingu/)

###まずcascadeファイルを得る
[opencv公式](https://opencv.org/releases/)の一番上のRereasesに入って、一番上のOpenCV –〜.〜.〜みたいな奴のSoursesをクリックしてzipファイルをお好きなフォルダにダウンロードし（少し時間がかかります。）展開してください。
沢山ファイルが入っていますが使うのは、dataフォルダのhaarcascadesの中のhaarcascade_frontalface_default.xmlというファイルだけです。
そのファイルの場所は把握しておき、""cascade_file = ""のところで定義しましょう。

私は、
000001.jpg（試したい画像ファイル）とcvcut.py（以下のコード）とmodelsフォルダを同一の階層におき、modelsの中にhaarcascade_frontalface_default.xmlファイルを置く、という構造にしました。

###顔の切り出し+顔部分を枠で囲むコード

```python:cvcut.py

import cv2
cascade_file = "./models/haarcascade_frontalface_default.xml"
cascade = cv2.CascadeClassifier(cascade_file)
#画像ファイルの読み込み
image_picture = "画像ファイルの名前"
img = cv2.imread(image_picture)


#グレースケールに変換する
img_g = cv2.imread(image_picture,0)

#顔部分の検出
face = cascade.detectMultiScale(img_g)

#顔の座標を表示する
print(face)

#切り取る
for x,y,w,h in face:
    face_cut = img[y:y+h, x:x+w]

#白枠で囲む
for x,y,w,h in face:
    cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,255),2)

#画像の出力
cv2.imwrite('face_cut.jpg',face_cut) #切り取った写真(この場合はface_cut.jpgとして出力される）
cv2.imwrite('face_white.jpg', img)#顔部分が白枠で囲まれた写真(この場合はface_rectangle.jpgとして出力される）
```
cvcut.pyがある階層において、
```
python cvcut.py
```
を実行する。
すると新しくface_cut.jpgと、face_white.jpgができているのがわかるだろう。
Python 2次元配列(数値)の数値を半角空白で区切ってprintする

# はじめに

競プロやブラウザでのプログラミング問題を解く場合、
演算結果をprintで出力することが多いと思います。

2次元配列の数値のリストを
空白区切りで出力をする必要が出た時に、
混乱したのでメモしておきます。

戒め。

# やりたいこと
以下のような2次元配列を用意する。
2の出力を行います。

```python
sample_list = []
for i in range(4):
    sub = []
    for j in range(5):
        sub.append((i*10)+j)
    sample_list.append(sub)
```

```
# 1. print(sample_list)の場合
[[0, 1, 2, 3, 4], [10, 11, 12, 13, 14], [20, 21, 22, 23, 24], [30, 31, 32, 33, 34]]

# 2. やりたい出力
0 1 2 3 4
10 11 12 13 14
20 21 22 23 24
30 31 32 33 34
```

# 実現方法
mapメソッドでリスト内の要素を文字に変換します。
それを再度listに入れ、
空白で区切って文字列にするためにjoinメソッドを使用します。

```python
for i in range(H):
    print(' '.join(list(map(str,sample_list[i]))))
"""
出力
0 1 2 3 4
10 11 12 13 14
20 21 22 23 24
30 31 32 33 34
"""
```


# おまけ
２次元配列をそのままmapで変換できないかと思い、試してみたのですが、
一つ下の次元に対してstrメソッドが適応されるようでした。

この仕様を初めて知ったので問題を解いている時に混乱してしまいました。
冷静に考えるとすぐ上記に記載した方法でできますね。

```python
S = list(map(str,sample_list))
print(S)
print(' '.join(S[0]))
"""
['[0, 1, 2, 3, 4]', '[10, 11, 12, 13, 14]', '[20, 21, 22, 23, 24]', '[30, 31, 32, 33, 34]']
[ 0 ,   1 ,   2 ,   3 ,   4 ]
"""
```

# おわりに
最終的に1次元ずつ変換することに落ち着いたのですが、
何次元あったとしても一気に変換する方法ないのでしょうか...?
pythonのインデントはタブ派？スペース派？

#1.背景
私はデータ分析を行う際にpythonを使っています。これまでは、特に深く考えず、pythonを書く時のインデントは「タブキー」を押していました。

Jupyter notebookではタブキーをおしても半角スペース４つとして扱われるので問題がなかったのですが、他のエディタを使ったときに半角スペースとタブが混在して「IndentationError」が頻発しました。

そこで、今後は明確にどちらかに統一していこうと考えたことから、**「半角スペースかタブのどちらが良いのか？」**という疑問が生まれました。

#２.Twitterでのアンケート調査　－タブ派多数！
周りの人がどのようにしているのか知ろうと思い、Twitterでアンケートを取ってみました。結果は「タブ」と「スペース４個」がいい勝負で、**タブ派の勝利**。ただ、この設問だと**「タブキーで半角4個」のパターンの人が「タブ」を選択している可能性**があるため、設問が悪かったなぁと思いました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">python使っている方に質問です。インデントのつけ方を教えてください。</p>&mdash; はぁこ🌸ビール女子麦子開発中 (@paco_itengineer) <a href="https://twitter.com/paco_itengineer/status/1131205069930549249?ref_src=twsrc%5Etfw">May 22, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

#３.PEP8を確認　－スペース４つ！
[PEP8-jaのインデントの章](https://pep8-ja.readthedocs.io/ja/latest/#id5)を見てみると以下のように書かれています。

>1レベルインデントするごとに、スペースを4つ使いましょう。

はい。明確に描かれていますね😝**「スペース４つ」**だそうです。

#４.今後の方針
これより、今後、私はpythonのインデントには**「スペース４つ」**を使うことにしました。ただし、「タブキー」を押す習慣は今さら変えられないので、エディタ側で**「タブキーを押すとスペース４つを入力する」**という設定を徹底しようと思います。

（ちなみに、普段使っているJupyterNotebookは、タブキーを押すとスペース４つ入力されるようになっていました。）

本件は私個人が調べて判断した結果ですので、他の考え方やご意見があれば、コメントいただけると幸いです。