OmniAICreator/Qiita-1.07M huggingface dataset:
CircleCIからAutify for Mobileへアップロードする

# about

CircleCIからAutify for Mobileへアップロードする方法について書きます。

ここではFlutter環境でiOSの.appファイルをアップロードしていますが、
iOSネイティブでも参考になるかと思います。

# how to

今回はconfig.ymlに書きました。
fastlaneで書いても良いと思います。
(´-`).｡oO （そうするとまたshコマンドで表現するところで躓きそう)

## 準備

CircleCIの環境変数に以下を追加しておきます。

- AUTIFY_ACCESS_TOKEN
Autifyの設定画面→`パーソナルアクセストークン`から生成できます。

- AUTIFY_PROJECT_ID
Autifyの設定画面を開いたときにURLに表示されています。
```profile?current={PROJECT_ID}```

## zipアーカイブ

appファイルをzipでアーカイブしてアップロードする必要があるので、zipコマンドを実行します。
Runner.appが生成されるディレクトリを見つけるのがひと手間でした。

fastlaneでgymやbuild_appを実行した後に記載します。

```sh
- run:
    name: archive app file
    command: zip -r Runner Runner.app
    working_directory: {Runner.appの生成されたパス}
```
これで`~/flutter_app/build/ios/iphoneos/Runner.zip`が生成されます。

## ポイント

普通にビルドすると`armv7 arm64`なので`x86_64`でビルドする必要があります。
その方法は以下の記事が参考になるかと思います。

https://qiita.com/kanari3/items/542a7977ac91d889af91

特に気をつける点としては、`Runner.app`のパスです。

- 通常
`flutter build`では`~/flutter_app/build/ios/iphoneos/`に生成される

- `x86_64`でビルドした`Runner.app`
⇡の記事の理由により`~/Library/Developer/Xcode/DerivedData以下`に生成される



## Autify APIでアップロード

2021.10.07現在はcurlでアップロードするのが良さそうです。

Swaggerを確認すると以下の通り
`POST: ​/api​/v1​/projects​/{project_id}​/builds`
https://mobile-app.autify.com/api/docs/

そこにパラメータを追加すると以下のようになります。

```sh
- run:
    name: autify upload
    command: >-
      curl -X POST "https://mobile-app.autify.com/api/v1/projects/${AUTIFY_PROJECT_ID}/builds" \
        -H "accept: application/json" \
        -H "Authorization: Bearer ${AUTIFY_ACCESS_TOKEN}" \
        -H "Content-Type: multipart/form-data" \
        -F "file=@Runner.zip;type=application/zip"
    working_directory: {Runner.appの生成されたパス}

```

# response

成功するとステータスコード201で以下のようにIDが返ってきます

```sh
{
  "id": "yLA6m0oM"
}
```

# トラブルシューティング

- ymlのインデント
Android StudioやVSCodeでオートインデントしましょう

- Authorization Header
SwaggerのTry it outで生成されるcurlだと`Bearer`が入らないので躓きました
=> 現在は修正されているようです！

- zipファイル
ワーキングディレクトリを指定しないと、階層構造が再現されてしまい、`Runner.app`が見つからないと言われることがありました
一度ローカルでzipを生成しブラウザのアップローダから試してみると良いと思います


# 参考
Autify API 連携
https://autify-for-mobile.zendesk.com/hc/ja/articles/4403483275417

How to run curl request in yml
https://stackoverflow.com/questions/68268869/how-to-run-curl-request-in-yml
Special thanks: @sasasin

# Bitriseの場合
autify-uploadステップを使えばOKです！
https://www.bitrise.io/integrations/steps/autify-upload
［オンプレ］SoftEther VPN ServerをUbuntuにインストール

# 1. はじめに
この記事は、Ubuntuを小型PC「BMAX」にインストールする方法の備忘録です。


# 2. Ubuntu Server 20.04 LTSをインストール
Rufusを使ってUSBメモリにUbuntuのISOイメージを書き込む。
Escキーを連打してBMAXのBIOSに入りブート順序を変更する。
Ubuntuをインストールする際にSSHも同時にインストールする。


# 3. パッケージの更新
```
sudo su
apt update
apt upgrade -y
```


# 4. ファイアウォールの許可設定
```
ufw allow ssh, 443, 500, 4500, 5555
ufw enable
```


# 5. SoftEther VPN Serverをインストール
必要パッケージをインストールする。

```
apt install -y gcc make
```

作業用ディレクトリに移動する。

```
mkdir tmp
cd tmp
```

最新版をダウンロード、解凍する。
https://www.softether-download.com/ja.aspx?product=softether

```
wget https://~.tar.gz
tar -xzvf softether~.tar.gz
```

ビルドする。

```
cd vpnserver
make
```

ディレクトリを移動、パーミッションを設定する。

```
cd ..
mv vpnserver /usr/local
cd /usr/local/vpnserver
chmod 600 *
chmod 700 vpncmd vpnserver
```

サービスに登録する。

```
nano /etc/systemd/system/vpnserver.service
```

次の通り編集する。

```/etc/systemd/system/vpnserver.service
[Unit]
Description=SoftEther VPN Server
After=network.target

[Service]
Type=forking
User=root
ExecStart=/usr/local/vpnserver/vpnserver start
ExecStop=/usr/local/vpnserver/vpnserver stop
Restart=on-failure
RestartSec=3s

[Install]
WantedBy=multi-user.target
```

Ctrl + X　→　Y　→　Enterで保存。

```
systemctl daemon-reload
systemctl enable vpnserver
systemctl start vpnserver
reboot
```
サービスを有効化、起動。

# 6. 管理ツールからサーバーに接続、設定
クライアントPCにSoftEther Server Manager for Windowsをインストールする。
https://www.softether-download.com/ja.aspx?product=softether

- リモートアクセスVPNサーバーを有効
- 仮想ハブを作成
- L2TPサーバー機能を有効
- 事前共有キーを設定
- VPN Azureは無効
- ユーザーを作成
- tapデバイス「sevpn」を作成しローカルブリッジ作成


# 7. IPアドレスを固定、仮想ブリッジを定義
このままではVPN接続時、サーバー自身にアクセスすることができないため次の設定をする。

```
nano /etc/netplan/hogehoge.yaml
```

- enp2s0のIPアドレスは明示的に0.0.0.0を割り当てる
- br0にIPアドレスを設定する

```hogehoge.yaml
network:
  ethernets:
    enp2s0:
      dhcp4: false
      addresses: [0.0.0.0/24]
    tap_sevpn:
      dhcp4: false
  bridges:
    br0:
      interfaces: [enp2s0, tap_sevpn]
      addresses: [192.168.0.112/24]
      gateway4: 192.168.0.1
      nameservers:
        addresses: [192.168.0.1, 8.8.8.8, 8.8.4.4]
  version: 2
```

設定を反映する

```
netplan apply
```

エラーが出る場合は、「interfaces」は記述せずに一旦上書きして上記コマンドを実行し、
再度「interfaces」を記述する。

※物理NIC：enp2s0、仮想ブリッジ：br0

# 8. 物理NICとtapデバイスをブリッジ

```
apt install -y bridge-utils
brctl addif br0 enp2s0
brctl addif br0 tap_sevpn
ip link set up dev br0
```

以上でVPN接続時にもサーバー自身にアクセスすることが可能になる。


# 9. 参考文献
1. あまり費用と労力をかけずにVPSにVPNサーバを立てる (SoftEther VPN) - Qiita
https://qiita.com/Wankosoba/items/3fb56443e77fd6a0b6e7

2. softetherをubuntu18.04にインストールする - Qiita
https://qiita.com/rimksky/items/e169f9af83ce472b4ce3

3. ネットワークブリッジ - ArchWiki
https://wiki.archlinux.jp/index.php/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%96%E3%83%AA%E3%83%83%E3%82%B8#bridge-utils_.E3.82.92.E4.BD.BF.E3.81.86

4. SoftEherVPNでTAPデバイスとのブリッジが失敗する場合 - Qiita
https://qiita.com/nemochu33/items/ca52cd8a5f0d0ccfb0d3
ターミナルにてVScodeを開く方法

# はじめに
本記事では、ターミナルにてVScodeを開く方法を記述します。
かなり簡単なので、すぐにできてしまいます。

# 手順
`VScode`は、ターミナル上で、

```
% code .
```
と入力すればVScodeを開くことができます。

＊`.`はカレントディレクトリのことです。

しかし、設定しないと

```
% code .
zsh: command not found: code
```
と表示されます。

コマンドを設定する必要があります。

[![Image from Gyazo](https://i.gyazo.com/469557b2b7d914ac83d708cf52edb2c2.png)](https://gyazo.com/469557b2b7d914ac83d708cf52edb2c2)

`ctrl+shift+P`を押すと、`コマンドパレット`が開けます。
`shell command install`で検索します。

[![Image from Gyazo](https://i.gyazo.com/87606be2c2114a22766a1905b357a3ac.png)](https://gyazo.com/87606be2c2114a22766a1905b357a3ac)


これで完成です。

```
% code .
```

で以下のようになります。

[![Image from Gyazo](https://i.gyazo.com/ce4ef97069f35f7c3455d8bbd2820e09.gif)](https://gyazo.com/ce4ef97069f35f7c3455d8bbd2820e09)

Dockerは関係ないので、スルーしてください。

以上です。

# 終わりに
VScodeは便利なものですので、
自分なりにさらに使いやすいものにしたいですね。

何かVScodeの設定で、これは良い！というものがあれば、
ぜひ教えていただけますと幸いです。

明日も頑張ります！
ABC63 C - Bugged を解いた

https://atcoder.jp/contests/abc063/tasks/arc075_a

![abc63_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/a5971fa2-20c3-c390-6449-ae100bf15ed7.png)
![abc63_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/1f14bca0-c330-e190-bb4f-89f762d2e087.png)
![abc63_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/b935cc24-af22-d703-bc01-5bf37ce4241c.png)

ビット探索が頭をよぎったけど、2^100 って無理だな。
OK
じゃあ,if で行こう。

```Bugged.py
N = int(input())
S0 = [] #10の倍数
S1 = [] #not 10 の倍数
for _ in range(N):
    s = int(input())
    if s%10 == 0:
        S0.append(s)
    else:
        S1.append(s)

S1.sort()
Total = sum(S0)+sum(S1)

if Total%10 != 0:             #全部足した状態で not 10 の倍数なら答え
    print(Total)
else:
    for i in range(len(S1)):  #not10倍数だけのリスト S1 から小さい順に引いていく
        Total -=S1[i]
        if Total%10 != 0:     #TotalSum%10 != 0 なら最大値
            print(Total)
            break
    else:
        print(0)#26ms
```

気を付けたのは入力 S。
求めたいのは合計の最大値。
よって、引いていきたいのは not 10 の倍数を一個ずつ引いて試したい。
だから入力時に s1,s2... はデータを受け取る時点で分別した。

例えば、 10,15,25 って入力の場合、小さい順で引いていくと最大値は 25 になる。
でもそれって、15 だけ引けば、最大値は 35 になるよね？的なイメージ。

***

ちょっとだけ早くなりました。

```abc63c.py
N = int(input())
S = [int(input()) for _ in range(N)]

if sum(S)%10 != 0:
    print(sum(S))
else:
    S.sort()
    X = sum(S)
    for i in range(N):
        if S[i]%10 != 0:
            X -= S[i]
            if X%10 != 0:
                print(X)
                exit()
    print(0)#24ms
```
特定のグループへの追加、削除を許可する IAM ポリシー


以下の通り。

```shell-session
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "iam:AddUserToGroup",
                "iam:RemoveUserFromGroup"
            ],
            "Resource": "arn:aws:iam::${AWS::AccountId}:group/xxxxxx"
        }
    ]
}
```
【Linux】Ctrl+zで一時停止したプロセスの再開方法

## 前置き

うっかりCtrl+zで停止してしまったプロセスを再開する方法を備忘録として残しておく。

今回はfileAを編集中に誤って`Ctrl+z`でプロセス一時停止してしまった場合を想定。



## プロセスの停止

下記のとおりうっかり`Ctrl+z`でプロセスを一時停止してしまった！

```
$ vim ./fileA

[1]+  停止                  vim ./fileA
```



## ジョブIDを確認

`jobs`コマンドを使用して先ほど一時停止したジョブのIDを確認する。

```
$ jobs
[1]+  停止                  vim ./fileA
```



## フォアグラウンドにする

`fg <ジョブID>`コマンドでジョブをフォアグラウンドにする。

ちなみにバックグラウンドにする場合は`bg <ジョブID>`だ。

```
$ fg 1
```



## jobsのhelp

```
$ jobs --help
jobs: jobs [-lnprs] [jobspec ...] または jobs -x command [args]
    Display status of jobs.

    Lists the active jobs.  JOBSPEC restricts output to that job.
    Without options, the status of all active jobs is displayed.

    Options:
      -l        lists process IDs in addition to the normal information
      -n        lists only processes that have changed status since the last
                notification
      -p        lists process IDs only
      -r        restrict output to running jobs
      -s        restrict output to stopped jobs

    If -x is supplied, COMMAND is run after all job specifications that
    appear in ARGS have been replaced with the process ID of that job's
    process group leader.

    Exit Status:
    Returns success unless an invalid option is given or an error occurs.
    If -x is used, returns the exit status of COMMAND.
```

google翻訳

```
$ jobs --help
jobs：jobs [-lnprs] [jobspec ...]ジョブjobs-xコマンド[args]
     ジョブのステータスを表示します。

     アクティブなジョブを一覧表示します。 JOBSPECは、出力をそのジョブに制限します。
     オプションがない場合、アクティブなすべてのジョブのステータスが表示されます。

     オプション：
       -lは、通常の情報に加えてプロセスIDをリストします
       -nは、最後からステータスが変更されたプロセスのみを一覧表示します
                 通知
       -pはプロセスIDのみをリストします
       -r出力を実行中のジョブに制限します
       -s出力を停止したジョブに制限します

     -xが指定されている場合、COMMANDは、次のすべてのジョブ仕様の後に実行されます。
     ARGSに表示されるものは、そのジョブのプロセスIDに置き換えられました
     プロセスグループリーダー。

     終了ステータス：
     無効なオプションが指定されないか、エラーが発生しない限り、成功を返します。
     -xを使用すると、COMMANDの終了ステータスが返されます。
```



## fgのhelp

```
$ fg --help
fg: fg [job_spec]
    ジョブをフォアグランドにします。

    JOB_SPEC で識別されたジョブをフォアグランドにして、現在のジョブにします。
    もし JOB_SPEC が存在しない場合、シェルが現在のレントジョブとして考えている
    ものが利用されます。


    終了ステータス:
    フォアグラウンドになったコマンドのステータスを返します。または、エラーが
    発生した時に失敗を返します。
```
Power BI: 個人的エラーの対処法備忘録

# Windows Serverにインストールしたら動かない
エラーメッセージ
> power bi サーバーに対する変更の保存に失敗しました。 M エンジンでエラーが発生しました 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645569/c0253e44-f581-45bd-fee4-666b21706760.png)

エラーフォルダー
> %appdata%\..\Local\Microsoft\Power BI Desktop\CertifiedExtensions<br>

### 対処法
1. 管理者権限で起動

## 以前使えていた OData Feed でアクセス禁止表示が出る
実際のエラーは
> Expression.Error リソースへのアクセスが禁止されています。

内部エラー
> microsoft.mashup.engine.interface.resource access forbiddenexception

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645569/2540142a-b428-d3eb-7399-e7709453510a.png)

### 対処法
- アクセス許可の編集　はダメだった
- アクセス許可のクリア　後、再設定で、回復
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645569/c40db6c2-a43a-8576-69cf-2c85b7651620.png)
「英語→カタカナ変換機」を叩いて英単語をカタカナに変換したい

# 何？

[英語→カタカナ変換機](https://www.sljfaq.org/cgi/e2k_ja.cgi)をBashかPythonで叩きたいなあと思った。

## 注意

連続して取得したい場合は十分なウェイトを空けておくこと。

## Bash

```bash
word="test"
curl 'https://www.sljfaq.org/cgi/e2k_ja.cgi?o=json&word='"${word}"'&lang=ja' \
     -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
```

```json
{
  "words": [
    {
      "j_pron_spell": "テスト",
      "type": "dictionary",
      "word": "test",
      "j_pron_only": "テスト"
    }
  ],
  "is_romaji": 0,
  "has_spelling": 0
}
```

## Python

```python
from json import loads
from json import loads
from pprint import pp
from urllib.parse import urlencode
from urllib.request import Request, urlopen

url = "https://www.sljfaq.org/cgi/e2k_ja.cgi"
data = {
    "o": "json",
    "word": "test",
    "lang": "ja",
}
headers = {
    "User-Agent": (
        "Mozilla/5.0 (X11; Linux x86_64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/51.0.2704.103 Safari/537.36"
    ),
}
params = urlencode(data, doseq=True)
req = Request(f"{url}?{params}", headers=headers)
res = loads(urlopen(req).read())
pp(res)
```

```python
{'has_spelling': 0,
 'words': [{'j_pron_spell': 'テスト',
            'type': 'dictionary',
            'word': 'test',
            'j_pron_only': 'テスト'}],
 'is_romaji': 0}
```
今こそPodman使ってみるか (Docker互換のコンテナエンジンPodmanの環境構築)

# 概要
Docker Desktopが有料化したニュースが最近巷を賑わしている。
今回は、そんなDockerを脱却した時の代替手段としてPodmanと呼ばれるDocker互換のコンテナエンジンがあるので、その環境構築から調査した内容をまとめました。

https://www.itmedia.co.jp/news/articles/2109/02/news112.html

# Podman
[Podman](https://github.com/containers/podman)とは、Docker互換のコンテナエンジンです。
REHELや、CentOS,Fedoraなどに標準で付属しているようです。
また、PodmanのCLIは、コマンド名がdockerではなくpodmanに変更するくらいで、ほとんどDockerと同じようです。
**Podmanでは、Podmanを用いてKubernetesのPodを管理することは、基本的にはできないようです。**

## Podmanの特徴

* Podmanの制御下にあるコンテナは、rootまたは非特権ユーザーのいずれかによって実行できるようです。

* デーモンを起動しなくても使える
=> 基本的にPodmanはデーモン無しで動作するようです。
正確には、バックグランドでconmonと呼ばれるプロセスを起動し、ユーザがconmonの存在を意識しなくて済むように設計されているようです。
しかし、ホストOS起動時にコンテナの自動起動をさせたい場合は、Docker/Podmanでも、systemdなどの設定が必要になるようです。

* コンテナ間のネットワークにPodmanはKubernetesと同じCNI(Container Network Interface)を使っているようです。
podman network createコマンドでカスタムネットワークの作成ができますが、複数のネットワーク間での通信が禁止されていないことが特徴の一つです。

# Podmanをinstall

Macクライアントは、Homebrewからinstallできます。

```
brew install podman
```

* ちなみにPodmanには、podman machineVMを自動的に管理するコマンドが含まれているので、Podmanが管理するVMを起動することができます。

```
podman machine init
podman machine start
```

* podmanのインストール情報を確認するのは下記のコマンドです。

```
podman info
```





# 参考文献
https://docs.podman.io/en/latest/index.html

https://github.com/containers/podman

https://podman.io/getting-started/
setodaNoteCTF - tkys_never_die 50 

#問題

https://ctf.setodanote.net/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/ea296bbc-8834-df82-27a3-9371e22cc1c4.png)

#解いてみた

ファイルを見ましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/36d404d3-1618-e7f2-7b0d-9d2d1bd8487d.png)

問題文に「通信が途切れる直前に～」とあるのでこのhttp通信が怪しそうです。
右クリック[追跡]⇒[HTTPストリーム]をやります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/0098922f-7688-67c9-d01a-99fa24807ed8.png)

レスポンスのところを見ると「Hi, This is Flag!」と書かれていて、flag.pngが表示されていたようです。

[ファイル]⇒[オブジェクトをエクスポート]⇒[HTTP]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/80aedfeb-f133-528a-c58a-aeb2019eece7.png)

flag.pngがあったのでそれをダウンロードして表示してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/e5c4819c-d50a-8db8-828e-fc3d844cedca.png)

flagがありました。
Amazon Timestream のテーブルへ、コマンドライン(AWS CLI)からデータ書き込みを行う


Amazon Timestream のテーブルへ、AWS CLI からデータ書き込みする方法です。
知っておくと、素早く Amazon Timestream の検証ができます。

### 動作確認

WSL2 の Ubuntu 20.04 と AWS CloudShell で確認しています。
※ `uuidgen` コマンドはだいたい入ってるっぽいですね。

```:WSL2側
❯ aws --version
aws-cli/2.2.40 Python/3.8.8 Linux/5.10.16.3-microsoft-standard-WSL2 exe/x86_64.ubuntu.20 prompt/off
```

```:AWS_CloudShell側
$ aws --version
aws-cli/2.2.15 Python/3.8.8 Linux/4.14.243-185.433.amzn2.x86_64 exec-env/CloudShell exe/x86_64.amzn.2 prompt/off
```

## 書き込みの条件は以下の通り

### Amazon Timestream 側

- データベース名 = `tsdb1`
- テーブル名 = `data1`

### 書き込みデータ

- ディメンション 1つめ
    - 名前: `iid`
    - 値: uuidgen で生成した値
- ディメンション 2つめ
    - 名前: `d1`
    - 値: `example1`
- メジャー (1つのみとしました)
    - 名前: `val1`
    - 値: `$RANDOM` で動的生成した値
    - 値の型: `BIGINT`
    - タイムスタンプ: `date +%s%3N` で動的生成した値

## 実際のコマンドライン

```console
export DB="tsdb1"
export TBL="data1"
export IID=$(uuidgen)
aws timestream-write write-records --database-name ${DB} --table-name ${TBL} --records "Dimensions=[{Name=iid,Value=${IID}},{Name=d1,Value=example1}],Time=$(date +%s%3N),MeasureName=val1,MeasureValueType=BIGINT,MeasureValue=${RANDOM}"
```

## 確認 (Amazon Timestream のクエリー)

```sql
SELECT * FROM "tsdb1"."data1" ORDER BY time DESC LIMIT 10
```

### 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/bda8337c-77b5-00c9-ca54-541f79fa88f9.png)

## あとがき

`--records` のオプションは[Record - Amazon Timestream](https://docs.aws.amazon.com/timestream/latest/developerguide/API_Record.html)をご覧ください。

EoT
railsチュートリアル第七章 Strong Parameters 

###Strong Parameters 
 
```rb
user = User.new(params[:user]) 
```
paramsハッシュ全体を初期化するという行為はセキュリティ上、極めて危険
この場合誰でも管理者に化けることができるため

paramsを使うのに条件をつけた。
paramsハッシュでは:user属性を必須とし、名前、メールアドレス、パスワード、パスワードの確認の属性をそれぞれ許可し、
それ以外を許可しないようにする。

```rb
params.require(:user).permit(:name, :email, :password, :password_confirmation)
```
:user属性でなければ、情報を確認できないようにした。
それを解決した。

```rb
class UsersController < ApplicationController
.
.
.
  def create
    @user = User.new(user_params)
    # 外部メソッドを使う
    if @user.save
      # 保存の成功をここで扱う。
    else
      render 'new'
      # 保存に成功しなければnewアクションに移動する
    end
  end
  
  private
  #外部から使えないようにする
  #習慣的に二つインデントを下げる
  
    def user_params
    # Usersコントローラの内部でのみ実行される
    # Web経由で外部ユーザーにさらされない
       params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end
end
```
間違ってもエラーメッセージが出てこない
かつ有効なユーザー情報を入力しても登録されない。
これから改良するらしい。

###演習
1./signup?admin=1 にアクセスし、paramsの中にadmin属性が含まれていることをデバッグ情報から確認してみましょう。

```
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  admin: '1'
  controller: users
  action: new
permitted: false
```
adminが入っていた。
railsチュートリアル第七章 ユーザー登録失敗

##ユーザー登録失敗
フォームを理解するには```ユーザー登録の失敗```のときが最も参考になる。
この節では、無効なデータ送信を受け付ける```ユーザー登録フォームを作成```し、ユーザー登録フォームを更新して```エラーの一覧を表示```します。

###正しいフォーム
```rb
Rails.application.routes.draw do
  root 'static_pages#home'
  get  '/help',    to: 'static_pages#help'
  get  '/about',   to: 'static_pages#about'
  get  '/contact', to: 'static_pages#contact'
  get  '/signup',  to: 'users#new'
  resources :users
end
```
urlにusersを入れることができる。
それによりcreateアクションを使い、新規作成者を作ることができたりした。

```rb
<form action="/users" class="new_user" id="new_user" method="post">
```
POSTリクエストを/usersというURLに送信

####ユーザー登録の失敗に対応できるcreateアクション
```rb
class UsersController < ApplicationController
.
.
.
  def new
    @user = User.new
    #新しくユーザーオプジェクトを作成する
    # オブジェクトの属性をつける
  end
  
  def create
    @user = User.new(params[:user])    # 実装は終わっていないことに注意!
    if @user.save
      # 保存の成功をここで扱う。
    else
      render 'new'
      # 保存に成功しなければnewアクションに移動する
    end
  end
end
```
プレビューで確認 失敗
```ActiveModel::ForbiddenAttributesError in UsersController#create```
createアクションで失敗したらしい。

```
Request
Parameters:

{"authenticity_token"=>"dfo0Ltyd8b+HqfZYMQ4dsyiL4b1FM0LqBY3mAQfni3QmVBfVE7B9kwrZIQ3kuT/QLU/He+TpHuJQrkuWwFvUNw==",
 "user"=>{"name"=>"", "email"=>"", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"},
 "commit"=>"Create my account"}
```
Usersコントローラにparamsとして渡されます

```html
<input id="user_email" name="user[email]" type="email" />
```
"user[email]"という値は、userハッシュの:emailキーの値と一致

2つのコードの意味は一緒らしい。

```rb
@user = User.new(params[:user])
```

```rb
@user = User.new(name: "Foo Bar", email: "foo@invalid",
                 password: "foo", password_confirmation: "bar")
```
昔のバージョンのRailsでは、次のコードでも動いた。

```rb
@user = User.new(params[:user])
```
しかし悪意からの対策としてわざとエラーを起こす```Strong Parameters```という技術で今は動かない。
setodaNoteCTF - Host 30 

#問題

https://ctf.setodanote.net/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/0d5d61b5-38f3-f0e3-5f3c-8f6284aaba3d.png)

#解いてみた

ファイルを見ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/4ad5695b-8064-9710-60b0-dd9c2137bd85.png)

pcapファイル内にGETのところがあるので右クリック[追跡]⇒[HTTPストリーム]をやるとHTTPのヘッダーなどが見れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/f73f4dd1-d9f7-6d34-adbc-7be4f957c778.png)

Hostに書かれているのが答えです。
`rails s` 実行時にRubyGemsのエラーが発生する

## 環境情報

- macOS Big Sur 11.6
- Ruby 2.6.1
- Rails 5.2.6

## 起きたこと

OSのアップデートやrbenvの再インストールを行った後、
`rails s` や `rails c` を実行した時に下記エラーが発生するようになってしまった　　
（起きていた現象として、エラーが発生するだけで起動は行われる）

```
/path/to/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.2.28/lib/bundler/rubygems_integration.rb:12: warning: already initialized constant Bundler::RubygemsIntegration::EXT_LOCK
/path/to/.rbenv/versions/2.6.1/lib/ruby/2.6.0/bundler/rubygems_integration.rb:12: warning: previous definition of EXT_LOCK was here
/path/to/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.2.28/lib/bundler/version.rb:4: warning: already initialized constant Bundler::VERSION
/path/to/.rbenv/versions/2.6.1/lib/ruby/2.6.0/bundler/version.rb:10: warning: previous definition of VERSION was here
/path/to/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.2.28/lib/bundler/constants.rb:4: warning: already initialized constant Bundler::WINDOWS
/path/to/.rbenv/versions/2.6.1/lib/ruby/2.6.0/bundler/constants.rb:4: warning: previous definition of WINDOWS was here
/path/to/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.2.28/lib/bundler/constants.rb:5: warning: already initialized constant Bundler::FREEBSD
/path/to/.rbenv/versions/2.6.1/lib/ruby/2.6.0/bundler/constants.rb:5: warning: previous definition of FREEBSD was here
/path/to/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.2.28/lib/bundler/constants.rb:6: warning: already initialized constant Bundler::NULL
/path/to/.rbenv/versions/2.6.1/lib/ruby/2.6.0/bundler/constants.rb:6: warning: previous definition of NULL was here
/path/to/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.2.28/lib/bundler/current_ruby.rb:12: warning: already initialized constant Bundler::CurrentRuby::KNOWN_MINOR_VERSIONS
/path/to/.rbenv/versions/2.6.1/lib/ruby/2.6.0/bundler/current_ruby.rb:12: warning: previous definition of KNOWN_MINOR_VERSIONS was here
/path/to/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.2.28/lib/bundler/current_ruby.rb:26: warning: already initialized constant Bundler::CurrentRuby::KNOWN_MAJOR_VERSIONS
/path/to/.rbenv/versions/2.6.1/lib/ruby/2.6.0/bundler/current_ruby.rb:24: warning: previous definition of KNOWN_MAJOR_VERSIONS was here
/path/to/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/bundler-2.2.28/lib/bundler/current_ruby.rb:28: warning: already initialized constant Bundler::CurrentRuby::KNOWN_PLATFORMS
/path/to/.rbenv/versions/2.6.1/lib/ruby/2.6.0/bundler/current_ruby.rb:26: warning: previous definition of KNOWN_PLATFORMS was here

```

## 解決方法

`gem update --system` を実行する（gemコマンドをアップデートする）

## 参考

https://github.com/rubygems/rubygems/issues/3279
【UE4】ボックスコリジョンの操作性を向上させる

#概要
なにかしらのイベントのトリガーとしてよく使われるBoxComponentですが、
サイズを変更したいとなった時にサイズの変更→サイズに合わせて位置を再結締という手順で作業しなければならず、
繰り返し微調整がしにくいなぁと感じていました。
頂点を引っ張って変形する形にできないかなと思い、実装してみました。
完成品としては以下のような感じです。
![2021年10月07日BoxActor00.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530664/c8712942-bf0d-58c6-269b-c16a1d7958a9.gif)


#今回使用する仕組み
```C++
virtual void OnConstruction(const FTransform& Transform) override;
virtual void PostEditMove(bool bFinished) override;

UPROPERTY(EditAnywhere, Meta = (MakeEditWidget= true))
    FVector startPoint_;

UPROPERTY(EditAnywhere, Meta = (MakeEditWidget= true))
    FVector endPoint_;
```
OnConstructionはプロパティの値が変わるたびに呼び出される関数ですね。

PostEditMoveは移動完了時に呼ばれる関数で、後述の3DWidget機能にも有効です。
端折ってますが#if EDITOR_ONLY ~ #endifで囲う必要があります。

MakeEditWidgetはビューポート上で相対座標として表示してくれる機能です。
ビューポート上で選択し、つかんで移動することで値を変更することもできます。

実装としてはMakeEditWidgetによる移動でボックスの大きさ・位置を制御していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530664/107b29f6-2f8d-992e-1c1c-e88bdd963c0a.png)


#実装
コードとしては以下のような感じです。

```C++
UCLASS()
class ABoxActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ABoxActor();

	virtual void OnConstruction(const FTransform& Transform) override;

#if WITH_EDITOR
	virtual void PostEditMove(bool bFinished) override;
#endif

protected:

	UPROPERTY(VisibleDefaultsOnly)
		USceneComponent* rootScene_;

	UPROPERTY(VisibleDefaultsOnly)
		class UBoxComponent* boxComponent_;

	UPROPERTY(EditAnywhere, meta = (MakeEditWidget  = true))
		FVector startPoint_ = FVector(50.f);

	UPROPERTY(EditAnywhere, meta = (MakeEditWidget  = true))
		FVector endPoint_ = FVector(-50.f);

};
```

```C++
ABoxActor::ABoxActor()
{
	rootScene_ = CreateDefaultSubobject<USceneComponent>(FName(TEXT("RootScene")));
	{
		RootComponent = rootScene_;
	}

	boxComponent_ = CreateDefaultSubobject<UBoxComponent>(FName(TEXT("BoxComponent")));
	{
		boxComponent_->SetupAttachment(RootComponent);
		boxComponent_->SetBoxExtent(FVector(50.f));
	}
		
	PrimaryActorTick.bCanEverTick = false;
}

void ABoxActor::OnConstruction(const FTransform& Transform) 
{
	Super::OnConstruction(Transform);

	// 位置が変わるたびにボックスの大きさを変更
	if (startPoint_ + endPoint_ != FVector::ZeroVector)
	{
		const FBox box = FBox(startPoint_, endPoint_);
		boxComponent_->SetRelativeLocation(box.GetCenter());
		boxComponent_->SetBoxExtent(box.GetExtent().GetAbs());
	}
}

#if WITH_EDITOR
void ABoxActor::PostEditMove(bool bFinished) 
{
	// 移動が完了したら位置を修正する
	if (bFinished)
	{
		startPoint_ -= boxComponent_->GetRelativeLocation();
		endPoint_ -= boxComponent_->GetRelativeLocation();
		SetActorLocation(boxComponent_->GetComponentLocation());
		boxComponent_->SetRelativeLocation(FVector::ZeroVector);
	}
}
#endif
```

#結果
ボックス判定のサイズ・位置調整がしやすくなります。
ぜひお試しください。
またより良い実装方法などありましたらご教授いただければと思います。
調べものは１次情報から？ ２次情報から？

## コラム

調べものをする時、１次情報と２次情報のどっちから調べるかについては、意見が分かれるところだろう。１次情報とは公式サイトの事で、２次情報とはQiita、はてなブログなど、一般的な投稿記事の事を指している。

先輩エンジニアは新人エンジニアに対して、よく次のようにアドバイスすることが多いようだ。「１次情報から調べろ！、２次情報だけを頼りにしていては成長できないぞ！」

そのアドバイスにはある意味真理が含まれていると思われる。きっと先輩エンジニアは、自身が１次情報を頼りにしてきたためここまで成長できたのだという、自身の経験を通した実感があるから、このようなアドバイスをするのだろう。

さて、自分はといえば、駆け出し頃は調べものはもっぱら２次情報だけであった。それはそれで、それなりの成長はあったとは思っている。駆け出し頃は１次情報に対し抵抗感を感じていた。初学者の段階からいきなり１次情報というのはどうだろうかという思いを抱いていたからだ。

たとえば、話は少し違うかも知れないが、法学の初学者がいきなり六法全書から学ぼうとし始めるだろうか。経済学の初学者がいきなりマルクス経済論を原本から学ぼうとし始めるだろうか。まず最初は次のようなタイトルの本から入って、ざっとでもいいので、簡単な理解から学び始めた方がいいのではないかと思う。

- 「はじめてでもわかる法学入門」
- 「サルでもわかる経済学」
- 「マンガで読む法学入門」

初学者がいきなり１次情報から調べるという事は、結構敷居が高いものです。

初学者が２次情報から入っていけば次のようなメリットがあると考える。２次情報を書いた人は、きっと１情報を元ネタにしているので、１次情報の内容を第三者に分かりやすく咀嚼して記事に落としているため、分かりやすい表現になっている。

１次情報の内容は完全に正しいことが書かれている。１次情報は数学でいえば「公理」であるのに対し、２次情報は「定理」に該当すると言えるだろう。

１次情報を発信する人は１次情報を作るというだけあって、才能に秀ではいるが、文章の表現力に関してはいまいちな場合も応々にしてありうる。

スポーツの世界では、一流の選手だった人が指導者になっても一流の指導者になりうるかといえば、どうもそうとは言い切れないと言われているように、一流のエンジニアは皆一流の表現力を持っているわけではないようだ。

２次情報を発信する人はジャーナリスト的な役割を果たしている。第三者に伝えようとする気持ちが強い分、表現が分かりやすくなっていくのだろう。

２次情報にも当然デメリットはある。２次情報は書いた人のスキルによって嘘になってしまうことが発生しうる。２次情報を元に、３次情報４次情報と次元が上がっていくにつれ、伝言ゲームのように情報が書き換えられることも発生するかも知れない。

自分が考える情報検索の順位は、初学者は２次情報から入ってよろし。ある程度初学者から脱出しつつある段階になってから、１次情報に触れるようにする。
Laravelの認証のGuard

Laravelの認証には「Guard」と「Provider」という概念がある。
今回は「Guard」について一度整理してみる。

# Guard

[公式](https://laravel.com/docs/8.x/authentication#introduction)による定義は以下。

>Guards define how users are authenticated for each request. For example, Laravel ships with a session guard which maintains state using session storage and cookies.

デフォルトでは以下のGuardが用意されている。
- [SessionGuard](https://github.com/laravel/framework/blob/8.x/src/Illuminate/Auth/SessionGuard.php)
- [TokenGuard](https://github.com/laravel/framework/blob/8.x/src/Illuminate/Auth/TokenGuard.php)
- [RequestGuard](https://github.com/laravel/framework/blob/8.x/src/Illuminate/Auth/RequestGuard.php)

またinterfaceは以下。
[Guard](https://github.com/laravel/framework/blob/8.x/src/Illuminate/Contracts/Auth/Guard.php)

上記公式による定義の通り、Guardはリクエストごとにユーザーを認証する方法を定義しているが、どうやって定義しているかをinterfaceを使って見てみる。

## `check()`

```php
    /**
     * Determine if the current user is authenticated.
     *
     * @return bool
     */
    public function check();
```

現在のユーザーが認証されているかを確認し、認証されていればtrueを返す。

## `guest()`

```php
    /**
     * Determine if the current user is a guest.
     *
     * @return bool
     */
    public function guest();
```

現在のユーザーがguest、つまり未認証かどうかを確認し、未認証であればtrueを返す。
`check()`の反転。

## `user()`

```php
    /**
     * Get the currently authenticated user.
     *
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function user();
```

認証済みのユーザーを返す。

## `id()`

```php
    /**
     * Get the ID for the currently authenticated user.
     *
     * @return int|string|null
     */
    public function id();
```

認証済みのユーザーのIDを返す。

## `validate()`

```php
    /**
     * Validate a user's credentials.
     *
     * @param  array  $credentials
     * @return bool
     */
    public function validate(array $credentials = []);
```

ユーザーの識別情報を検証する。OKであればtrueを返す。

## `setUser()`

```php
    /**
     * Set the current user.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @return void
     */
    public function setUser(Authenticatable $user);
```

認証済ユーザーをセットする。

# interfaceを見て

interfaceを見たら大体使い方が分かってくる。

- ログイン時の検証を`validate()`で行い、OKであればそのユーザーを`setUser()`でセットしてする。
- 認証済みかどうかをチェックしたい場合は`check()`、`guest()`を使う。
- 認証済みのユーザー情報を取得したい場合は`user()`や`id()`を使う。
AWS　覚えておきたい基本単語

#はじめに
AWSに出てくる基本単語を備忘録を兼ねてまとめます。
ざっくりイメージで記載している箇所も多々あるので、その点はご容赦ください。
当方初学者故、誤りがあればコメントでご教授いただけると幸いです。

## VPC　（Virtual Private Cloud）
AWS上に仮想ネットワークを作成できるサービスのこと。
AWSの敷地にないに自分の領土を広げるイメージ。
VPC内にアプリに必要なサーバーやサブネットなどを配置する。

## サブネット
VPCを細かく区切ったネットワーク、そのグループのこと。
VPC内で役割が異なるパーツを外部接続、内部接続など、接続先ごとにサブネットというグループに分類する。
サブネットは複数のAZに接続する。

## インターネットゲートウェイ
VPCから外部に出るときに通る出入り口のこと。VPCにアタッチして設定する。

## ルートテーブル
サブネットごとに作成できる、通信に関するルールブック。

## セキュリティグループ
サブネットごとに作成できる、セキュリティに関するルールブック。
ホワイトリスト方式でルールを記載する。（記載されたルール以外は全て拒否する）
・インバウンドルール：来る通信のルール
・アウトバウンドルール：送る通信のルール

## RDS(Relational Database Service)
DBを提供するサービス。
AWSでDBを利用するには２種類の方法がある
・EC2インスタンス（サーバー）にDBをインストールする
・RDSを利用する

## EC2インスタンス（Elastic Compute Cloud）
EC2とはクラウド上に存在する仮想サーバーのこと。
EC2インスタンスとは、EC2によって実際に建てられたサーバーのこと。

##AMI(Amazon Machine Image)
インスタンスの起動情報が入ったOSのイメージ.
作成するサーバーのコンピューターのテンプレートのこと。
AMIを選択してクイックスタートすることでパッケージ化されたOSの起動に必要な情報を簡単にインストールできる。

## ElasticIP
動的なクラウドコンピューティングのために設計された静的な IPv4 アドレス。
Elastic IP アドレスはユーザーの AWS アカウントに割り当てられ、解放するまでユーザーのアドレスとして使える。
tcshになれた人がbash,zshを使う際の違和感を緩和する試み

# 動機

物心ついたときから`tcsh`を使い続けて二十余年、キーバインドを頭でなく指が覚えている。そのため、永らく他のシェルに関しては「食わず嫌い」であったが、昨今の軽量化の流れの中でシステムデフォルトでないシェルをインストールするのが憚られる風潮になってきたので、`tcsh`育ちの者がうける違和感を和らげる設定を試みることにした。似たような記事はいくつか存在するようだが、いずれも断片的な情報が多いので、自分用に情報を順次整理していくことにした。

# 参考資料

- [便利な shell いろいろ](http://ukai.jp/Articles/1993/uu-whatis12.txt): かなり古典的な資料だが、3つのシェルの直接比較がとても参考になった。

# 違和感その1: コマンドプロンプト行末の`Ctrl-D`で補完候補表示

`tcsh`では、`Ctrl-D`は、「行末では補完候補を表示、それ以外では一文字削除」となっている。`bash`で真っ先に感じる違和感は、行末の`Ctrl-D`で補完候補が表示されないことであろう。`tcsh`では行の途中で補完候補を表示するのに`Esc,Ctrl-D`を叩くが、`bash`ではこれも動作が違うので違和感が最高潮に達する。

- `bash`の場合には、`~/.inputrc`に下記の記載をして、`readline`の変数でキーバインドを設定する模様。

```bash:~/.inputrc
# tcsh-like key binding
"\C-d": delete-char-or-list
"\M-\C-d": possible-completions	
"\e\C-d":  possible-completions	
```

- `zsh`の場合には、デフォルトで`tcsh`と同じ挙動の模様。なにも足さない。なにも引かない。

# 違和感その2: `Esc-p`,`Esc-n`でのヒストリ補完

`tcsh`では、コマンドを途中まで打ったところで`Esc-p`を叩くと、同じ文字列を含むコマンド履歴を辿って表示してくれる。オプション引数がたくさんついた長〜いコマンドを何回も叩く場合に多用する機能だが、`bash`ではキーバインドが違う。

- `bash`: これに関しては設定例の記事があったのでそのまま使わせていただく。
    - [bashでtcsh風なM-p/M-nでのヒストリ検索を行う](https://hnw.hatenablog.com/entry/20070107)
    - [tcshライクにbashでヒストリリストから補完する方法](https://kaworu.jpn.org/kaworu/2007-12-28-2.php)

```bash:~/.inputrc
# tcsh-like key binding
"\M-p": history-search-backward
"\M-n": history-search-forward
"\ep": history-search-backward
"\en": history-search-forward
```

- `zsh`の場合には、デフォルトで`tcsh`と同じ挙動の模様。なにも足さない。なにも引かない。

# 違和感その3: 補完候補が多い場合に表示するか聞かれる。さらにページ毎に表示。

`tcsh`では補完候補の表示は非常にシンプルであるが、`bash`,`zsh`の場合には、補完候補の数が多い場合に`Display all nnn possibilities? (y or n)`などと言ってお伺いをたててくれるが煩わしい。余計なキー入力、タイムラグなく表示して欲しい。

- `bash`の場合には、`~/.inputrc`に下記の2行を追加する。

```bash:~/.inputrc
# Disable prompt for long completion list
set completion-query-items -1
set page-completions off
```
- `zsh`の場合: 2つある補完機能のうち`compsys`を選んで設定する必要があるようだ。(`compctl`でのやり方は不明). **ただし不完全。効果があったりなかったり...orz**
    - [Pipe zsh auto completion list to file or less](https://unix.stackexchange.com/questions/26789/pipe-zsh-auto-completion-list-to-file-or-less/30092#30092)とマニュアルを参考にした。

```zsh:~/.zshrc
# Disable prompt for long completion list
zstyle -d ':completion:*' list-prompt 
unset LISTPROMPT
LISTMAX=-1
autoload -Uz compinit
compinit
```

# 違和感その4: 文字列のコピー/カット/ペーストのキーバインド

`tcsh`では、`Ctrl-@`とともに`Ctrl-SPACE`でマークをつけられる。`bash`では、``ESC-w`でペーストされない。`zsh`の場合には、`Ctrl-w`に単語の消去(`backward-kill-word`)が割り当てられていて、`tcsh`(リージョンの消去)と挙動が違う。

- `bash`の場合には、`~/.inputrc`に下記の3行を追加する。

```bash:~/.inputrc
# tcsh-like copy & paste
"\M-w": copy-region-as-kill
"\ew": copy-region-as-kill
"\C-w":  kill-region
```

- `zsh`の場合には、`~/.zshrc`に下記の1行を追加する。

```zsh:~/.zshrc
# tcsh-like copy & paste
bindkey '^w' kill-region
```
Carthageで入っている各ライブラリのSwiftバージョンを洗い出すシェル芸

ABI Stability & Module Stability 対応しているライブラリはSwiftのバージョンを上げて `carthage bootstrap --cache-builds` してもキャッシュが効いてビルドが走らないが、その関係で複数のSwiftバージョンでビルドされたライブラリが混在する結果になる。

そこで、各ライブラリがどのバージョンでビルドされているのかが知りたくてシェルを書いた。

```sh
$ find Carthage/Build -name "*.version" -exec /usr/local/bin/jq '.iOS[] | [.name, .swiftToolchainVersion] | join(": ")' {} \; | cat | uniq | sed -r 's/\"//g'
```

```sh:result(例、一部抜粋)
KeychainAccess: 5.4.2 (swiftlang-1205.0.28.2 clang-1205.0.19.57)
SVProgressHUD: 
OHHTTPStubs: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
Device: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
Alamofire: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
RxBlocking: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
RxCocoa: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
RxRelay: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
RxSwift: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
RxTest: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
APIKit: 5.4.2 (swiftlang-1205.0.28.2 clang-1205.0.19.57)
CryptoSwift: 5.4.2 (swiftlang-1205.0.28.2 clang-1205.0.19.57)
FBSnapshotTestCase: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
MultipartFormDataParser: 5.5 (swiftlang-1300.0.31.1 clang-1300.0.29.1)
SDWebImage: 
SDWebImageMapKit: 
```

※空白になっているのはObj-C製なのでswiftToolchainVersionが存在しない
以前のバージョンのjsPsych(Ver.6系)を使いたい時の入手方法について

## はじめに
jsPsychをインストールしないでRawGit経由で使うという横着な事をしていたところ、2021年10月に突然動作しなくなりました。
エラーメッセージを見てみるとどうやらファイルそのものが存在しないようですが、いやいやそんなわけないでしょうということで、数カ月ぶりにgitを見に行くと jspsych.js もないし、 extensions もないし、なんじゃこりゃああ！！

本家サイトの、support/Migrating an experiment to v7.x を、おそるおそるDeeplにコピペするとしれっと書いてありました。　おい。

```
バージョン7.0のリリースでは、jsPsychのいくつかのコアコンポーネントが変更されています。
これらの変更は、パッケージマネージャやバンドラーなどの最新のJavaScriptツールとjsPsychの互換性を向上させ、
jsPsychのコードベースに貢献する人々の開発者体験を改善するために行われました。これらの変更により、
プロジェクトの長期的な存続が可能になり、より多くの開発者がjsPsychに貢献してくれることを願っています。
```

後ほどマイグレーションはやってみるとして、有志の皆様が残してくれたドキュメントを活用するためには今までと互換性のあるバージョンを使わなければなりません。

## やること

今回リリースされたVer.7と、Ver.6以前の後方互換性が無いので、Ver.6の一式を使って環境構築します。
gitのタグでver.6系の最終バージョンを指定してダウンロードするだけなので、使い方がわかる方は以上で終了です。

以下は、gitを使い慣れていない人向けの図解となります。

## 手順

### 1.本家サイトからgitへ
本家サイト(https://www.jspsych.org/7.0/) の、右上辺りの赤枠をクリックしてgitに行きます。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/c3b19b87-33af-761a-2db9-ce2b00f168e2.png)

### 2.git で旧バージョンを指定する
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/26132f62-9446-b9e3-df42-6e6ab8c2fe5c.png)

git(https://github.com/jspsych/jsPsych/) に遷移すると、ここには見慣れた jspsych.js は無く、見知らぬ package なるディレクトリがあります。
この状態でファイルを入手すると最新版(Ver.7系)になってしまうので、git を操作して古いバージョンの一式を入手する必要があります。
左上の赤枠の中にある main をクリックしてメニューを開きます。

main をクリックするとメニューが表示され、初期表示は branches になっているので、ここで、tags をクリックすると旧バージョンの一覧が表示されます。
今までの互換性があるVer.6系最後のバージョンは、v6.3.1のようなので、これを選びます。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/b3061ce7-221b-02fb-99d5-292511623cde.png)

### 3.旧バージョンをダウンロードする
v6.3.1を選択すると、見慣れたファイルとディレクトリ構成が表示されます。
ここで右上の赤枠にある Code をクリックします。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/870603d5-dccf-fe53-3fc0-8e3bd92291b8.png)

表示されたメニューから Download ZIP を選択すると、無事にダウンロードする事ができます。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/d87c611b-7aff-3684-fd06-b216d3c0efab.png)

### 4.自分のPCへのインストール
ダウンロードしたZIPファイルを展開してインストール完了です。　
Windowsであれば、ダウンロードしたファイルを右クリックして出てきたメニューで「すべて展開」です。
これで、今まで見慣れたVer.6の環境ができあがっています。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/ccea4dec-8708-ea8e-c82e-84b0c4ed57a3.png)


以上、おつかれさまでした。


## 余談
みんなが卒論の提出期限を意識しまくりのこの時期に、今さらマイグレーションしてテストをやり直す心の余裕は無いので、今年度はこのままVer.6系で進めて、来年度からVer.7系でやってみようと思います。
海外で秋からの新学期だとこの時期のリリースが一番ダメージを被る人が少ないのでしょうかね..
こんな事なら自前で実験用のフレームワークを作った方がマシかなと思ったのですが、私自身が配属が変ったり何かあったらサポートできないので、やはり開発コミュニティーが無いと困るよねーというところで思いとどまりました。
アクセスを制限する拡張機能

# 初めに
この間、間違えたURLを踏んで、誤操作してしまいました。こんなことがあってはならないので、予防するために、アクセスを制限する拡張機能、アプリを入れました。（戒め）

# 注意
最新の状態を確認して下さい。

# 最終更新日
2021年10月7日


# 環境の情報
OS
ubuntu 20.04
Windows10

# PC側、導入した拡張機能
環境
OSはubuntu、Windowsにて。
ブラウザは、Chrome、firefox、edgeにて、こちらを入れました。

https://chrome.google.com/webstore/detail/siteblock/pfglnpdpgmecffbejlfgpnebopinlclj?hl=ja

https://addons.mozilla.org/ja/firefox/addon/blocksite/


https://chrome.google.com/webstore/detail/blocksite-block-websites/eiimnmioipafcokbfikbljfdeojpcgbh?hl=ja
Athenaの特定のSQLクエリ構文のクエリ結果が変更になるよう(2021/12/1以降)

# 概要
* 2021年12月1日以降、Athenaの特定のSQLクエリ構文のクエリ結果が変更になるようです。
* 今回は、その該当するクエリ構文がどのようなものかをまとめました。
 
# 該当するクエリ構文
**1: CHAR 型カラムと文字列リテラルの比較の評価が容易になります。文字列リテラルにはパディングは必要ありません。**

  
データ型 CHAR (5) の col5 という名前の列があり、列 col5 の値 'abcd ' (末尾のスペースに注意) の行が含まれている。

**現在の仕様:** クエリで結果を一致させるには、まったく同じ文字列リテラルを使用する必要があった。

```
SELECT 1 FROM t WHERE col5 = 'abcd '; (末尾にスペースが必要)
```

**新しい仕様:** 条件と一致するためにクエリの末尾にスペースを入れる必要がなくなった。

```
SELECT 1 FROM t WHERE col5 = 'abcd';
```

**ちなみに、上記のクエリは両方とも一致し、現在の動作は引き続き有効な模様。**


**2: MAP 型の存在しないキーにアクセスすると、結果として NULL が返されるのではなく、エラーが発生する。**

**現在の仕様:**  MAP データから存在しないキー「abc」の値にアクセスする際に、キー 'abc' は MAP に存在しないため、Athena は NULL を返す。


**新しい仕様:** Athenaが「マップに存在しないキー:abc」を示すエラーを返す。


下記のようなクエリを発行し、NULL を返すことを望む場合は、TRY 関数を利用する。

```
SELECT MAP(array['foo', 'bar'], array[1, 2])['abc'];
SELECT TRY(MAP(array['foo', 'bar'], array[1, 2])['abc']);
```


**3: 「.field [n]」形式の匿名行フィールドへのアクセスはサポートされなくなった。**

**現在の仕様:** 匿名行のフィールドにアクセスすると、Athena は次のクエリの最初のフィールド ('a') を返す。

```
SELECT ROW('a', 'b').field0;
```

**新しい仕様:** Athena は「列 'ROW ('a', 'b') .field0' を解決できません」というエラーを報告する。


ただ、匿名でない行にアクセスする方法には影響しない。
次のクエリは変わらず動作し、'a' を返します。

```
SELECT CAST(row('a', 'b') AS ROW(col0 char, col1 char)).col0;
```
Raspberry pi 4 の入手～初期セットアップ

Raspberry piを触ったことすらない初心者なのでスターターキットが欲しかったのですが、売り切れてしまって久しいので、必要と思われるものを自力で揃えました。

# 買ったもの

全部で15,000円くらいでした。

## 本体

https://ssci.to/6370

## ケース＆熱対策

https://ssci.to/5959

https://ssci.to/6827


## ACアダプター

https://ssci.to/5683

## HDMIケーブル

https://ssci.to/5960

HDMIケーブルくらいその辺で安いの買えばいいんじゃね？と思ったが、なんとこのケーブルは公式のもので、ラズベリーパイのロゴが入っている。これは外せない。

## MicroSDカード

余っていたやつ（64GB Class10/UHS-1）を採用。
Amazonとかで安いのを買ったらいいと思います。

# Raspberry pi OS のインストール

Raspberry pi Imager を使います。

https://www.raspberrypi.com/software/

Raspberry pi OS (32-bit) を選んで、ストレージのドライブを選んで、WRITEを押すだけです。

![2021-10-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147207/97c92290-aec3-4585-c394-5a53d78e6532.png)


# 最初にやったこと

## ファンがうるさいので止める

デフォルト設定だとファンが常時回り続けます。
これだとうるさくて仕方ないので、80℃以上になった場合にファンが回るように設定を変更します。
[商品ページ](https://ssci.to/6827)に詳しく載っていますのでそちらを参照してください。

> 1. 更新をすべて完了させた状態で、左上隅のRaspberry Piアイコンをクリックし、"Preference"を選択、"Raspberry Pi Configuration"を選択する。
> 2. "Performance"タブを選択する。
> 3. "Fan"を"Enabled"をクリックする。
> 4. 上記のようにPWM制御ピンを14番に接続した場合、ピン番号を変更する必要はありません。ほかのピンに接続した場合は、接続したピン番号に変更してください。
> 5. "Fan Temperature"で回転を始めたい温度に設定します。デフォルトは80°Cです。

Raspberry pi に温度センサーモジュールを付けている人を見かけますが、本体が結構熱を持つのであまりアテにならないんじゃないかなってのはちょっと思ったりもします。
[PHP] 文字列の連結・文字列のサイズ

#文字の連結

```
PHPでは'+'ではなく,'.'を連結演算子として使います。
```

```
// str型 + str型
echo 'w' . "ord" . PHP_EOL;
echo "飛ぶ" . "NO" . PHP_EOL;
```

```
// 更にPHPでは、int型 . str型 = strになります。
// 連結演算子の場合、PHPはint型とfloat型を勝手にstr型に変更します。
echo "The year is : " . 2000 . PHP_EOL;


// float型 . str型 = str型。
echo "Left : " . 20.343 . "km" . PHP_EOL;
```

#文字列のサイズ
```
//文字列のサイズを得るために, strlen()という関数を使います。 strlen(str型)
echo strlen("California") . PHP_EOL;
```

```

// 最後の文字のインデックスは2(=3 - 1)
echo "cat"[strlen("cat") - 1] . PHP_EOL;

// インデックス演算子を使って、文字列CaliforniaのCをコンソールに出力してください。
echo "California"[strlen("California") - 10] . PHP_EOL;

// インデックス演算子を使って、文字列Desktopのkをコンソールに出力してください。
echo "Desktop" [strlen("Desktop") - 4] . PHP_EOL;

// 文字列Computerの文字数をstrlen()を使って出力してください。
echo strlen("Computer") . PHP_EOL;

// 文字列recursion@info.comの文字数をstrlen()を使って出力してください。
echo strlen("recursion@info.com") . PHP_EOL;

// 文字列Computerの最後の文字をstrlen()を使って出力してください。
echo "Computer"[strlen("computer") - 1] . PHP_EOL;

// 文字列recursion@info.comの最後の文字をstrlen()を使って出力してください。
echo "recursion@info.com"[strlen("recursion@info.com") - 1] . PHP_EOL;
```
#静的型付け言語

静的型付け言語では変数を宣言する際に、データ型も一緒に割り当てる必要があります。データ型の宣言によって、プログラミング言語がビットを正しく読み取り、データ型を処理することができます。
>プログラムを実行する前 （マシンに対して命令が作成される瞬間、つまりコンパイル時） に型検査を行うプログラミング言語を静的型付け言語と呼びます。静的型付け言語の例として、C++、C#、Java などが挙げられます。

#動的型付け言語
動的型付け言語の場合、変数を宣言する際に、データ型を割り当てる必要はありません。しかし、動的型付けでは、型を宣言しなくて良いため簡単に実装できる反面、プログラムを実行しないとバグがわからないという難点を持っています。
>プログラムの実行時に、型検査を行うプログラミング言語を動的型付け言語と呼びます。動的型付け言語の例として、JavaScript、Python、PHP、Ruby などが挙げられます。

>プログラム実行中に型検査が行われる言語を一般に静的型付け言語
プログラム実行前に型検査が行われる言語を一般的に動的型付け言語
RSpec create_listの使い方

# RSpecとは
RSpecはRailsでwebアプリを開発をする際に使う、テストフレームワークです。

# create_listとは
***FactoryBotを使う際にファクトリーで定義している時、複数まとめてインスタンスを作成できるメソッド***です。

⚫︎補足
- ```ファクトリ(Factory)```とは
***テストのサンプルデータを生成してくれるgem***です。


# create_listの使い方
まず下のようなstaffファクトリが定義されているとします。

```staffs.rb

FactoryBot.define do
  factory :staff do
    name {Faker::Name.name}
    account{Faker::Internet.username}
    email{Faker::Internet.email}
  end
end

```

下で3つstaffインスタンスを作成するとします。

```staff_spec.rb
RSpec.describe "Staffs",type: :request do
describe "GET /staffs" do
subject {get(staffs_path)}
 before{3.times {create(:staff)}}  #3人分のstaffデータを作る
 it "::::"　do
end
end

```

staffが３つある見づらいですよね。
そこで***create_list***を使って3つをまとめて書くことができます。

```staff_spec.rb

RSpec.describe "Staffs",type: :request do
describe "GET /staffs" do
subject {get(staffs_path)}
 create_list(:staffs, 3)

 it ":::::"　do
end
end

```
これだとだいぶ見やすくなりますよね。





# 参考資料

https://qiita.com/kodai_0122/items/e755a128f1dade3f53c6

https://post-output.com/400-2/#toc2
vscodeでRemote-Containersの作業フォルダが開かない

2021/10/07投稿

**※最新版は[haroot.net](https://haroot.net/articles/12)に移動しました。**

# 結論
Remote-Containersの`open container configuration file`コマンドで開かれる○○.json(○○はdockerのイメージ名)のworkspaceFolderの値を修正すればよい。

# 環境
Windows10 Pro 21H1
VSCode 1.60.2
Docker 20.10.8
docker-compose 2.0.0
Docker(VSCode) 1.17.0
Remote-Containers(VSCode) 0.194.3

# 動機
docker-composeを使ってリモートにフォルダを作成してみたところ、フォルダの場所が良くなかった(/app)ので変更することにした(/home/app)。
1. docker-compose.ymlの`volumes`と`working_dir`を編集してフォルダが作成されるパスを変更
2. `docker-compose up -d`でリモート環境を再構築
3. vscodeのリモートエクスプローラーから再構築したコンテナへ`attach`

これで作業フォルダを開いたvscodeが起動するはずだったが"開くことができません"とエラーが出てしまった。
![InkedUntitled (1)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156083/00566400-eab4-4467-9df5-ed3b87e2139e.jpeg)

# パス修正
試行錯誤した結果、どうやらRemote-Containersの作業フォルダのパスはvscode側に保存されるらしく、そのパスが古いまま(/app)更新されていないのが原因だった。

コマンドパレット(ctrl+shift+P)や左下のDev Container:○○から、`Open Container Configuration File`を選択。
![InkedUntitled (2)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156083/36db31da-57a5-9c6b-8568-02b87e413fb1.jpeg)

すると○○.json(○○はdockerのイメージ名)が開かれる。
(実際のファイルの場所はwindowsなら、 ~/AppData/Roaming/Code/User/globalStorage/ms-vscode-remote.remote-containers/imageConfigs/○○.json あたりにある)
![InkedUntitled (3)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156083/4ec967ac-ba2a-b64f-4614-97e9ed2303b1.jpeg)

ここのworkspaceFolderが古いまま(/app)なので新しいパスに書き換える(今回なら/home/app)。
これで保存してもう一度`attach`すればちゃんと/home/appが開かれる。
頻繁に「python setup.py test」と打つのが面倒だった

#はじめに
理由はわからないけど「python setup.py test」って打つのが面倒。
度々「pytyhon」なんて打ってしまう…

#対処

元々、``~/.inputrc`` にこんな設定（※一部）は入れていた。

```ini
"\C-f": reverse-search-history
"\C-m": accept-line
```

設定を入れていなくても「Ctrl-r」でイケるけど、ブラウザーの「Ctrl-f」と合わせてると指が楽。

ここから過去コマンドを探すわけだけど、頭が悪いことに前方一致しか使っていなかった。部分一致が使えることに、今更ながらに気づいた。

で、こんな風に入力することで容易に ``python setup.py text`` が特定できるようになった。打ち慣れているのか、指も楽。

```bash
py te
```

#以上
マカーのためのHomebrewで簡単Hacktoberfest攻略

## はじめに
IT系のイベントではしばしばパーカーやTシャツなどが賞品として与えられます。
最強のエンジニアはTシャツとパーカーを一生買わないと言われるほどです。\[要出典\]

しかし、初心者にとってこのような賞品を得るまでの道のりはなかなか大変です。
そんな中、毎年10月にDigitalOceanによって開催される**Hacktoberfest**では、比較的簡単にTシャツをゲットすることができます。

## Hacktoberfestとは
[Hacktoberfest](https://hacktoberfest.digitalocean.com/)は毎年10月にDigitalOceanが開催しているイベントです。
簡単に言えば、GitHubでPull Request(PR)をいっぱいするとご褒美がもらえるイベントです。

賞品を獲得するには、以下の条件を満たすPRを10月中に4回[^回数]行う必要があります。

- PR先レポはパブリックであること
- 以下のいずれかを満たすこと
    - レポに`hacktoberfest`トピックが付いている
    - PRに`hacktoberfest-accepted`ラベルが付与された
- 上の条件を満たしたのち、無効化[^PRの無効化]されずに14日経過すること

完了するとTシャツをもらったり木を植えたりできます。

[^回数]: 回数は開催年によって異なり、これは2021年の回数です
[^PRの無効化]: PRに`invalid`ラベルが付与された場合、PRはカウントされません

## Homebrewとは
[Homebrew](https://brew.sh/)はmacOS向けのパッケージマネージャです。
大きな特徴として、パッケージの更新がコミュニティベースであることがあります。
多くのパッケージマネージャでは各パッケージにメンテナがいて、その人が担当パッケージの更新を管理しています。
一方でHomebrewは全ての更新がGitHubのPRとして行われ、決まった担当者は存在しません。

## なぜHomebrewで簡単にHacktoberfestが攻略できるのか
Homebrewには`brew bump-formula-pr`および`brew bump-cask-pr`という、パッケージのバージョン更新PRを半自動化するコマンドがあります。
これを使えばHomebrewの役に立ちつつ簡単にHacktoberfestを攻略できます。

## あったほうがよい技能
- `git`の知識(「コミットを全部1つにまとめて！」と言われたらできる程度）
- 英語の技能(指摘を受けたときに読んで対応できる程度(DeepL可))

## 具体的なフロー
### バージョンが古いパッケージを探す
自分でパッケージのホームページを見て最新バージョンを確認してもいいですが、`brew livecheck`を使うと自動でホームページからバージョンを取得して表示してくれます。

`brew livecheck`は基本的には引数でパッケージ名を与えてそのパッケージの最新バージョンを確認するものです。
ただ、今回はローラー作戦で古いパッケージを探したいです。
この場合、引数なしで`--installed`オプションを付けて以下のように実行すると、自分の環境に入っているパッケージを全てチェックしてくれます。

```zsh
% brew livecheck --installed
```

![Screenshot 2021-10-07 at 18.32.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71548/a4e41186-4207-6d90-ae4a-51703b3b032c.png)

ちなみに、インストール如何にかかわらず全てのパッケージを調べる`--all`もありますが、パッケージは全部で1万近くあるのでやめた方がよいです。

古いパッケージを見つけたら、右側に表示されている新しいバージョンを控えておきます。
上の画像では`aom`が更新されているようなので、これを例にしてPRを作成してみます。

### パッケージの種類を識別する
Homebrewが扱うパッケージには、*formula*と*cask*の二種類があります。これらの違いはここでは詳しく書きません。
どちらを更新するかによってコマンドが違うので、上で見つけたパッケージがどちらかを識別する必要があります。
識別するには、以下のコマンドでパッケージの記述を確認するとよいです。

```zsh
% brew cat <パッケージ名>
```

formulaでは先頭行に`class <パッケージ名> < Formula`と書かれています。
caskでは先頭行に`cask "<パッケージ名>" do`と書かれています。

`aom`を見てみます。上の判断基準からすると`formula`のようです。
![Screenshot 2021-10-07 at 19.12.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71548/541fd69a-6416-ee0d-7869-da0c98353045.png)

### バージョン更新のPRを作成・送信する
ここまででパッケージ名、パッケージの種類、新しいバージョンの3つの情報を手に入れました。
あとはコマンドを使ってPRを送るだけですが、パッケージの種類によって以下のどちらかになります。

```zsh:formulaの場合
% brew bump-formula-pr <パッケージ名> --version=<新バージョン>
```

```zsh:caskの場合
% brew bump-cask-pr <パッケージ名> --version=<新バージョン>
```

特に問題がなければ、上のコマンド一発でPRが送信されます。

逆に、問題がある場合というのはたとえば以下のような場合です。

- すでに対象のパッケージに対するPRが存在する
- `resources`[^2]が存在する

この場合、コマンドは失敗し、エラーを返します。
これらの問題を頑張って対処してもいいですし、あきらめて他のパッケージを探しに行くのもいいでしょう。

ちなみに、`aom`は執筆時点でPRがすでにあるのでエラーになります。

[^2]: パッケージをビルドするために必要なソースコード以外のリソースを記述するのに用います。これがある場合はバージョン更新にあたってリソースも更新する必要があるため、コマンドによる自動PRは行えません。

### PRがマージされるまでちゃんと世話を見る
バージョン更新PRの大半はなんの問題もなくHomebrew側のテストをパスしマージされます。
一方で、更新によってテストが失敗するようになり、対処を求められる場合もあります。
自分でなんとかできるようなら対処し、難しいようなら割り当てられたレビュワーに助けを求めましょう。

## おしまい
Homebrewを使う人は多いのにPRを送る人はあんまりいないので記事を書いてみました。
改善点あればお気軽にコメントください。
ちょっとした動作確認をするためのスクリプト、を作るためのスクリプト

#はじめに

perlとか、bashとか、pythonとか、プログラムを組んでいると「ちょっとした確認」のためにスクリプトを書く。

毎回作るのが煩わしかったので、こんなスクリプトを作ってPATHを通してあるディレクトリに置いた。

#スクリプト

便利。

```bash
#!/usr/bin/bash

echo "#!/usr/bin/python" > zzz.py
echo >> zzz.py
chmod u+x zzz.py
```

※捨てファイルは「zzz*」と決めています。

#以上
他にいい方法があったら教えてください。