OmniAICreator/Qiita-1.07M huggingface dataset:
rbenvインストール時のおまじないの秘密を解明してみた


rbenvのインストールの際には、初心者にはおまじないのように見える下記コマンドの実行が必要です。


```
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
```

```
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
```
実際自分も、当初は意味が分からず実行していました。ですが、意味を分からずに使っているとインストールの手順を間違えたりしてエラーが出た時に、何が間違っているのかがわからなかったりします。そこで、上記コマンドの意味をちゃんと調べてみることにしました。

# 実はパスを通している
まず、```export PATH="$HOME/.rbenv/bin:$PATH```の意味を解明していきます。これは、「環境変数（$PATH）の記述を変えて、コマンド検索パスを追加する」ことをやっています。いわゆる「パスを通す」というやつです。

Linuxはファイルでできており、コマンドの実行 = ファイルの実行です。例えば、catというLinuxコマンドを実行するということは、/usr/bin/catのcatファイルを実行するということを意味します。

ただし、パスを通していなければcatと省略して実行することはできません。catと入力するだけで/usr/bin/catが実行できるのは、/usr/binが環境変数$PATHに含まれているからなのです。以下のように、パスの通ったディレクトリは：で区切られて同環境変数内に保存されています。

```
/usr/bin:/usr/local/sbin:/usr/sbin:/home/ec2user/.local/bin:/home/ec2-user/bin
```
$PATHに/usr/bin/cat含ませるとすると、次のようにする必要があります。

```
export PATH="/usr/bin/cat:$PATH"
```
exportは、指定したシェル変数を環境変数として設定してくれます。この際、```/usr/bin/catの後に:$PATH（もしくは前に$PATH:）```とすることで、/usr/bin/catを環境変数に追加できます。```export PATH="$HOME/.rbenv/bin:$PATH```で:〜を後ろに付けているのは、$HOME/.rbenv/binを環境変数内で先頭に配置するためです。先に入っているものほど優先的に実行されます。

$HOME/.rbenv/binにパスを通すと、その配下にあるrbenvファイルが実行できるようになりますので、rbenv initやrbenv installなどのコマンドが使えるようになります。

```echo '' >> ~/.bash_profile```としているのは、exportで設定した環境変数はbashを終了すると消えてしまうからです。~/.bash_profileにexport以下を記載すると、bashが起動した時に記載内容が自動的に実行されるようになります。echoは画面に文字列などを出力するLinuxコマンドですが、>>で出力先を~/.bash_profileに変えています。既存の記述を消さないよう、>ではなく>>で追記しています。

次に```echo 'eval "$(rbenv init -)"' >> ~/.bash_profile```を見てみましょう。

rbenv initは、公式ドキュメントによると4つの意味のあるコマンドなのですが、最も重要な作用は```~/.rbenv/shims```にパスを通すことです。この配下にrubyやrubocopのファイルが置かれるため、これらのコマンドを実行するにはrbenv initを実行する必要があります。

evalは文字列をコマンドとして実行するLinuxコマンドです。~/.bash_profileに追記することで、rbenv initがbash起動時に常に実行されるようになります。

なお、rbenv initを実行すると、~/.rbenv/shimsが$PATH内で先頭に記述されます。その結果、先に書かれた記述が優先的に実行されるため、gemが提供する実行可能ファイルよりも先に呼び出されます。そのため、~/.rbenv/shims配下のファイル実行を経由して、実行可能ファイルを実行することができるようになります。

何の意味があるかと言うと、例えばRuboCopを導入する場合、実行可能ファイルは~/.rbenv/versions/X.X.X/bin/rubocopのような形でインストールされているのですが、複数のバージョンのRubyで同じgemをインストールしている場合でも、適切なバージョンのRubyを選んだファイル実行が可能になります。


#参考文献
パスやLinuxコマンドの説明については、下記記事や書籍を参考にしました。

- [Linux入門 ~「パスを通す」とは~](https://qiita.com/Naggi-Goishi/items/2c49ea50602ea80bf015)
- [新しいLINUXの教科書](https://www.sbcr.jp/product/4797380941/)

rbenvについては以下の公式ドキュメントを参考にしました。特に~/.rbenv/shimsの働きについては、下記ブログ記事を参考にしました。

- [Groom your app’s Ruby environment with rbenv.](https://github.com/rbenv/rbenv)
- [ちゃんと理解するrbenv : (4) shimsを理解する](https://mogulla3.tech/articles/2021-07-12-understanding-rbenv-4/)
Fastly入門(仕組み理解)

## 本記事について

Fastly導入にあたり、Fastlyの仕組みについてまとめます。
こちらでは構築や設定方法については記載しません。
あくまでも概要理解のためにまとめます。

## 入門した理由

元々キャッシュは自前で用意したVarnishサーバーで運用していたのですが、
利用範囲の拡大により冗長化と拡張が必要になったため、導入を検討しました。

Varnishだと無料で複数サーバーのキャッシュ共有ができないことが一番の理由。

## Fastly(ファストリー)とは？

CDN、画像の最適化、ビデオとストリーミング、クラウドセキュリティ、負荷分散などを提供してくれるサービス。
今回はCDN(キャッシュ)に焦点を当てて記載します。

## Fastly CDNについて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199056/ca0d7701-3127-1750-032d-e6f83491dae1.png)

上記の図の通り、ユーザー→Fastly→オリジンサーバーの順でFastlyを経由してオリジンサーバーにアクセスします。
Fastlyを経由することにより、2回目のアクセス(自分、他人含め)はFastly上のキャッシュがユーザーに返却されます。

Fastlyはユーザーに近いキャッシュサーバーを自動で選択してくれるため、例えばオリジンサーバーが日本にあったとしてもアメリカのユーザーはアメリカのキャッシュサーバーから配信されるため、より早くコンテンツを取得することができます。

### オリジンシールドについて

Fastlyには `オリジンシールド` という概念が存在します。
上記の例では `ユーザー→Fastly(キャッシュサーバー)→オリジンサーバー` の経路でしたが、
オリジンシールドを配置すると以下のように構成が変わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199056/b054fab0-42ea-debd-d7c0-a96bcf94d48e.png)
[手書きが汚いので公式はこちら参照](https://docs.fastly.com/ja/guides/shielding)

図の通り、オリジンシールドはFastlyキャッシュサーバーとオリジンサーバーの間に配置します。

通常、キャッシュサーバーにキャッシュが存在しない場合はオリジンサーバーを参照に行きますが
オリジンシールドを配置した場合はキャッシュサーバーはオリジンシールドを参照します。
オリジンシールドにキャッシュが存在する場合はキャッシュが返り、存在しない場合は代理でオリジンサーバーに問い合わせします。

そうすることにより、どのキャッシュサーバー経由でアクセスしてもキャッシュがオリジンシールドに蓄えられるので
最寄りのキャッシュサーバーにキャッシュが存在しない場合でもオリジンシールドのキャッシュを利用することができます。

## 設定の管理方法について

執筆時点で以下の方法があります。

1. VCL
1. Compute@Edge

`VCL`はVarnish同様、C言語っぽいVCL言語を使用して設定を記載します。
`Compute@Edge` は執筆時点でRust、AssemblyScript、JavaScriptを使用して設定を記載します。

構成管理ツールにTerraformを使用することができます。
Terraformで構成を管理し、キャッシュの設定をVCLやCompute@Edgeで行うイメージです。

日本語のブログがあるので構築するときは[こちら](https://www.fastly.com/jp/blog/how-to-configure-your-fastly-services-with-terraform)参照。

## キャッシュについて

### デフォルトでキャッシュされるHTTPステータス

以下以外(例えば500系)はデフォルトではキャッシュされません。

- 200
- 203
- 300
- 301
- 302
- 404
- 410

上記以外をキャッシュしたい場合は別途VCLで設定が必要。
逆に上記をキャッシュしたく無い場合も同様。

### TTL(有効期限)

キャッシュのTTL(有効期限)を設定することでキャッシュを利用する期間を設定できます。
デフォルトは `3600秒`

TTLの設定は複数パターンあり、以下の優先順位で適用されます。

1. `Surrogate-Control: max-age` 、 `Cache-Control: max-age` 、 `Expires` ヘッダー
1. FastlyのコントロールパネルまたはVCLのTTL設定値
1. デフォルト値 (3600秒)

つまり、VCLでTTLを設定してもヘッダーの設定で上書きすることが可能。

### Grace modeについて

`Grace mode` を使用すると、TTLが切れてからもユーザーには一定期間キャッシュを返却します。

[メリット]

- オリジンサーバーに障害が発生した場合、TTLが切れても一定期間キャッシュを返却できる
- TTLが切れた後、本来はユーザー→Fastly→オリジンサーバーの経路になるためレスポンスが遅れるが先にキャッシュが返るのでレスポンスが早い

[デメリット]

- コンテンツ更新時に明示的にPurge処理を行わないとしばらく古いコンテンツが表示される

## 最後に

まだまだ仕様理解できていないので多分書き足します。
アルゴリズム備忘録

アルゴリズム・データ構造

|タスク|手法|手法|必要な計算量|必要な計算量|
|-----|-----|-----|-----|-----|
| 最大公約数 | 両者の余りが0になる最大公約数を地道に探す方法 |  |$\mathcal{O(n)}$|
|  | ユークリッドの互除法 |  | $\mathcal{ O(logn)}$ |-----|
| ソート | 選択ソート |  | $\mathcal{O(n^2)}$ |-----|
|  | マージソート |  | $\mathcal{O(nlogn)}$ |-----|
|  | クイックソート |  | $\mathcal{O(nlogn)}$ |入力配列がソートされていると $\mathcal{O(n^2)}$ |
| データ探索 | 線形探索 |  | $\mathcal{O(n)}$ |-----|
|  | 二分探索 |  | $\mathcal{O(nlogn)}$ |-----|
|  | 二分探索木 | 平衡木 | $\mathcal{O(logn)}$ |ソート $\mathcal{O(n)}$|
|  | ヒープ | 最小値を取り出す| $\mathcal{O(1)}$ ||
|  |  |更新|   $\mathcal{O(logn)}$ ||
|  |  | 作成 | $\mathcal{O(n)}$ ||
|  | ヒープソート |  | $\mathcal{O(nlogn)}$ ||
|  | ハッシュテーブルの探索 |  | $\mathcal{O(1)}$ ||
| 要素の除去 | pythonのリスト | dequeの方が効率的 | $\mathcal{O(n)}$ ||



グラフ構造

|タスク|手法|手法|必要な計算量|必要な計算量|
|-----|-----|-----|-----|-----|
| 探索 | 幅優先探索 |  ||
| 探索 | 幅優先探索 |  ||
| 最短距離計算 | ダイクストラ法 |  ||
`gcloud run deploy` で `Failed to start and then listen on the port defined by the PORT environment variable.` エラー

AWS をちょこっと触っていた人間による CloudRun への初めての deploy 作業。

image ( 呼び方あってるかわからない ) をビルドして、`gcloud run deploy` を実行。
以下のエラーが発生。

> Cloud Run error: Container failed to start. Failed to start and then listen on the port defined by the PORT environment variable.

以下の質問・回答がドンピシャでした。

https://stackoverflow.com/questions/55662222/container-failed-to-start-failed-to-start-and-then-listen-on-the-port-defined-b

環境変数で定義されたポートを用いないといけないようです。

```Dockerfile:Dockerfile
# (略)

ENV PORT 4000
EXPOSE 4000

# (略)
```

node.js のエントリポイントではリッスンポートの指定を環境変数から受け取れるようにします。

```typescript:index.ts
// (略)

const port = process.env.PORT || 4000;

// (略)
```

その後、再度ビルドしてデプロイ。

```bash
Deploying container to Cloud Run service [hoge] in project [hoge] region [asia-northeast1]
✓ Deploying... Done.
  ✓ Creating Revision...
  ✓ Routing traffic...
Done.
Service [hoge] revision [hoge-XXXX-XXX] has been deployed and is serving 100 percent of traffic.
Service URL: https://hoge-XXXXXXXXXX-an.a.run.app
```

無事にデプロイできました。

おしまい。
#timeline チャンネルを生成できるSlackアプリを作った話：リモートワーク時代に良い可能性

この投稿を見たのはもう7年も前ですか。
https://qiita.com/kozyty@github/items/2a87bf7e652765b9967d
当時はHubotのことがよく分からず、自作するにも技術力が足らずという感じだったのですが、最近Slackアプリ開発をいくつかやっていく中で、やれそうな感じになったので書いてみます。

ちなみに、公開アプリにしたので、皆さんの環境でもお試し頂けます。
詳細はこちらから御覧ください。インストールもこちらの資料より可能になっています。
https://lne.st/wr21

## どんな技術で実現しているか
こちらの応用です
https://qiita.com/geeorgey/items/e52cf443c6d991264f3c
Bolt for PythonというSlack純正の開発キットを使って構築しています。
アプリケーション自体はHerokuでホスティングしています。

## タイムラインチャンネルを作ってみて思ったこと
数日運用してみての感想ですが、どのチャンネルでどんな会話がなされているかを断片的に把握することができます。
これはさながらオフィスで小耳にはさむあの感じに似ています。
もしあなたのチームがリモートワークベースになっているのであれば、タイムラインチャンネルを作るのは意外と悪くない選択肢かもしれません。
見ているそばから流れていってしまうのですが、それがオフィスに居るときのその瞬間その場所にいたから耳に入った情報みたいな感覚と似ているように思います。

## オプション
組織の１日のpost総数とか、チャンネルのpost数推移なんかも表示できるようになっています。

ということでよろしければどうぞ！
https://lne.st/wr21
BlenderでISBNから書影の自動作成

# 目的

3DCGソフトウェアの[Blender](https://www.blender.org/)では、Pythonを使っていろいろな処理を自動化できます。
ここでは、ISBNから書籍の書影画像を作成する方法を紹介します。

※ macOSのBlender2.93で確認しています。適宜直せばWindowsでも動くはずです。
※ 書影の元画像は、[openBD](https://openbd.jp/)から取得します。openBDに登録してある書籍が対象になります。

# 書影の元になるBlenderファイルの作成手順

- 「[Blenderのコマンドサンプル](https://qiita.com/SaitoTsutomu/items/6b70367455f843a979b1)」を参考に、下記のようにBlenderのPythonに`requests`と`openbd`をインストールしてください。

```
blender_pip install -U requests openbd
```

- 適当なJPEG画像を`/tmp/book.jpg`としてコピーします（この画像は後で上書きされます）。
- Blenderを起動します。
- 起動後に立方体がなければ、`Shift + A`の`メッシュ - 立方体`で作成します。
- 立方体の名前を`book`に変えます。
- `N`でサイドバーを出します。`book`を選択しアイテムタブの寸法のX、Y、Zを`0.21, 0.025, 0.297`にします（A4判のサイズ）。
- `book`のマテリアルを2つ作成し、2つ目のベースカラーを画像テクスチャにし、`/tmp/book.jpg`を指定します。
- 編集モードで正面の面を選択し、2つ目のマテリアルに割り当て、オブジェクトモードに戻ります。
- UV Editingウィンドウにし、右側で`A`を押し、左側で`AS4 + Enter`と`R-90 + Enter`を押した後、`G`で下図のように左の四角が重なるようにします。

![uv.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/072378a6-c70c-0c80-b3d3-9ad87d9027f1.jpeg)

- Scriptウィンドウにし、新規作成し、名前を`book_image.py`にし、下記をコピペします。

```py:book_image.py
import sys

import bpy
import fire
import requests
from openbd import book_info


def book_image(isbn):
    bi = book_info(str(isbn))
    res = requests.get(bi.image)
    with open("/tmp/book.jpg", "wb") as fp:
        fp.write(res.content)
    bpy.data.images["book.jpg"].reload()
    bpy.context.scene.render.filepath = "book"
    bpy.ops.render.render(write_still=True)
    bpy.ops.wm.save_as_mainfile()


if __name__ == "__main__":
    sys.argv = sys.argv[:1] + sys.argv[(sys.argv + ["--"]).index("--") + 1 :]
    fire.Fire(book_image)
```

参考：[BlenderでPythonを実行する方法](https://qiita.com/SaitoTsutomu/items/cec67381a8789b40e377)

- テキストメニューの`登録`をチェックします。登録すると起動時に実行できるようになります。
- Layoutウィンドウにし、カメラとライトなどを調整し、レンダリングしたときに好みの書影になるようにします。
- `book_image.blend`という名前で、Blenderを保存し終了します。

# 実行

書影にしたい13桁または10桁のISBNを調べてください（下記では例として 9784764905801 を使っています）。

調べたISBNを使って、下記のように実行します。

```
blender -b -y book_image.blend -- 9784764905801
```

- `-b`は、バックグラウンド実行の指定です。
- `-y`は、自動実行時に確認を省略させる指定です。
- `--`以降が、book_image.pyの関数`book_image`の引数になります。

（適宜モデリングすると）以下のような`book.png`が作成されます。

![book.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/1fdd26e2-31b2-41d0-8d22-61386f07704e.png)


以上
【Laravel】ルーティングで定義していないURLにアクセスしたときに自動的にリダイレクトさせる。

自分用のメモとして残します。

ルーティングで定義されていないページにアクセスした場合、404エラーを表示するのではなく自動的にリダイレクトさせる方法をメモ。

#やり方
Route::fallbackをルーティングに追記する。

```routes\web.php
<?php

Route::fallback(function(){ //存在しないURLは自動的にTOPにリダイレクトさせる。
    return redirect(route('home')); 
});
```


以上です。
Unityで日本語文章が現示できないエラー解決方法

Unity WebGL で標準書体としてArial をサポートしますが、これでは日本語で書かれた文章を現示することはできません。
Unity Editor では問題になりませんが、webGL でbuildしてBrowser でアクセスする場合、日本語を表示できないという問題が発生します。
これを解決する方法は、MS-Gothic書体を積載してAsset登録簿にコピーした後、該当文字列の書体属性をGothic書体に変更することによって解決できます。
Unity WebGL日本語入力方法

UnityプロジェクトをwebGLにBuildした時、入力部分に日本語の入力が英語で入力される場合があります。

解決方法は 
1.https://github.com/kou-yeung/WebGLInputでパッケージをDMされます。
2.日本語入力部分に「WebGLInput」Componentを追加します。
3.Buildします。
参考URL:https://github.com/PROCW/WebGLInput
テストhttps://URL:unityroom.com/games

以上です。
歪度(わいど Skewness)・尖度(せんど Kurtosis)というクセ。

統計検定2級を取得すべく統計の学習を再開しましたが、歪度・尖度というクセを見つけたので忘れないためにメモ書き。
一応、pythonでもどのように見るのかも調べたので、書こうと思います。

適度に統計ならではの用語が出てきたりしたときは説明しようと思いますが、pythonの基礎らへんは飛ばします

# 歪度
まずは概要からいきましょう。

漢字のとおりにどの程度「歪んでいるか？」を表す指標の一つです。
この歪みとは、正規表現（normal distribution）からの歪みを意味します。（やはり全ての物事は正規表現から始まる）

数値的に計算することもありますので、式を載せておくと以下。
$$ \frac{n}{(n-1)(n-2)}\sum_{i=1}^{n}(\frac{x_i - \bar{x}}{s})^3 $$

マイナスもプラスも0もとります。

実際に検定を受けるときはこの式を覚えておかないと爆死することはないです（多分です。保証はできないですw）
（実際に後ほどpythonで書くので、ここで手計算の例は省略。）

通常の統計においても頻繁に出る代物でもないので、用語や必要に迫られた時に検索するスタンスで個人的には良いと思っています。

## 独特な表現方法
この歪度ですが、表現が少し特殊です。

### 歪度 > 0 
歪度が非負な数をとるときの形状は左に山がある状態で、右にいくほど平坦になります。
これを<B>「右裾が長い」と表現したり、「左に偏っている」</B>と表現したりします。
![スクリーンショット 2021-10-20 16.32.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865635/4e69c784-6c48-5f3a-337a-b6a9397a08e0.png)

感覚として正の値を取ると右に大きくなるようなイメージをしがちですが、あくまで歪度が0であるとは上記のような図をイメージしておきましょう。

### 歪度 < 0
逆に負の数を取ればこの反対です。
<B>左裾が長い、右に偏っている</B>、と表現します。
![スクリーンショット 2021-10-20 16.36.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865635/578bd3ef-93f6-ec09-cf43-422e63ec010d.png)

### 歪度 = 0
歪度0とは、簡単にいえば正規表現に代表される、左右対称な状態を意味します。

# 尖度
裾の広がり具合を知りたいときに使われ、
漢字の通り、正規表現から「どのくらい尖っているのか？」を表します

式は歪度よりも複雑であり、以下。
$$ \frac{n(n+1)}{(n-1)(n-2)(n-3)}\sum_{i=1}^{n}(\frac{x_i - \bar{x}}{s})^4 - \frac{3(n-1)^2}{(n-2)(n-3)}$$
もしくは
$$ \frac{n\sum_{i=1}^{n} (x_i - \bar{x})^4}{(\sum_{i=1}^{n} (x_i - \bar{x})^2)^2}$$

マイナスもプラスも0もとります。

グラフに関してはわりとイメージしやすく、大きくなればなるほど尖った形状を表現します。
例えば、t分布などは自由度が大きくなるにつれて尖度が大きくなります。
![スクリーンショット 2021-10-20 16.56.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865635/3010eaf2-2e03-29de-c163-edbe6d981c1a.png)

# pythonでの歪度・尖度の実装
以前にkaggleでもちらっと見かけた記憶があるのですが、忘れたので自分で実装します。

ちなみに英語では歪度・尖度それぞれ「skewness」・「kurtosis」と言われ、投資でも「skew指数」とかで使われたりします
（オプションとかの話なので、内容の理解はしてないです）

簡単にirisのデータで見ていきます。
実はskew, kurt関数がpandas.DataFrameにはあるので、それ使うだけなんですよね。

```

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

from sklearn.datasets import load_iris


iris = load_iris()
data = pd.DataFrame(iris.data, columns=iris.feature_names)

# 描画準備
col = len(data.columns)
_, axes =  plt.subplots(1, col, figsize=(18, 5))

for i, var in enumerate(data.columns):
  sns.histplot(x=var, data=data, ax=axes[i], kde=True)
  axes[i].set_title('Skewness: {} \n Kurtosis: {}'.format(data[var].skew(), data[var].kurt()), fontsize=15)

plt.tight_layout()
plt.show()
```

![スクリーンショット 2021-10-20 17.30.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865635/f2dc2e75-49c7-da90-d1fa-92651280dc52.png)

わかりやすくタイトルにそれぞれの指数を入れました。
確かに右に山があるとskewnessは負の値を取っていたり、尖っているものの尖度は他に比べ大きかったりと外観の理解はできたのではないでしょうか？

いろんなデータセットでも試してみるとおもしろいです！

# 終わり
ちょっと普段の機械学習では見かけないようなものと遭遇しましたので、書いておきました
またなんかあれば書きます！


# 参考にさせていただいた記事
[https://bellcurve.jp/statistics/course/17950.html](https://bellcurve.jp/statistics/course/17950.html) <- このサイトは神と思っている
[pandasで歪度(Skewness)と尖度(Kurtosis)を計算](https://qiita.com/ymmy02/items/36e708d3d9e5e4e6a457)
BioRubyでgenbankファイルを取得する

今まで `BioRuby` で genbank 形式のファイルを取得するときは [`BioRuby Shell`](https://github.com/bioruby/bioruby-shell) を起動して `getent()` をしていたが、いちいち起動するのは面倒なので Ruby のコード内で取得する方法を調べたのでまとめる。

## 要約

```ruby
require "bio"

acc = "NC_012920"
ret = Bio::NCBI::REST::EFetch.nucleotide(acc)

entry = Bio::GenBank.new(ret)

File.open("#{entry.entry_id}.gbk", "w") do |f|
  f.puts(ret)
end
```


### データの取得

データは `Bio::NCBI::REST::EFetch.nucleotide` で取得する。

他のものの取得は[ここ](https://github.com/bioruby/bioruby-shell/blob/master/lib/bio/shell/plugin/entry.rb#L95-L122)を参照。


### データのパース

取得したデータは `String` なのでパースする。

今回は `GenBank` 形式決め打ちでパースしたが、他の形式もパースできるようにするには以下のように書く。

```ruby
cls = Bio::FlatFile.autodetect(ret)
entry = cls.new(ret)
```

[参照](https://github.com/bioruby/bioruby-shell/blob/cbd143af4b87c6b7097250b29f0f0594793a60a0/lib/bio/shell/plugin/flatfile.rb#L49-L51)
Nuxt.js reset.css の設定

## 環境

- **OS** Mac11.4
- **node** v16.11.1
- **npm** 8.0.0
- **Nuxt.js** v2.15.8 

## reset.css をインストール

今回は、`normalize.css`をインストールします。
その他の`reset.css`の場合は移行の手順で適宣書き換えが必要です。

```
npm install --save normalize.css
```

## nuxt.config.js の書き換え

`nuxt.config.js`の中身を書き換える。
`css:`の項目に下記を追加。

```
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
  'normalize.css/normalize.css'
],
```

## nuxt.config.js （変更後）

```
export default {
  // Target: https://go.nuxtjs.dev/config-target
  target: 'static',

  // Global page headers: https://go.nuxtjs.dev/config-head
  head: {
    title: '',
    titleTemplate: '',
    htmlAttrs: {
      lang: 'ja'
    },
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' },
      { name: 'format-detection', content: 'telephone=no' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

  // Global CSS: https://go.nuxtjs.dev/config-css
  css: [
    'normalize.css/normalize.css'
  ],

  // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
  plugins: [
    '@/plugins/element-ui'
  ],

  // Auto import components: https://go.nuxtjs.dev/config-components
  components: true,

  // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
  buildModules: [
    // https://go.nuxtjs.dev/eslint
    '@nuxtjs/eslint-module',
    // https://go.nuxtjs.dev/stylelint
    '@nuxtjs/stylelint-module',
  ],

  // Modules: https://go.nuxtjs.dev/config-modules
  modules: [
  ],

  // Build Configuration: https://go.nuxtjs.dev/config-build
  build: {
    transpile: [/^element-ui/],
  }
}
```

## 参考文献

- [normalize.css - npm](https://www.npmjs.com/package/normalize.css/v/8.0.1)
- [Nuxt 設定](https://nuxtjs.org/ja/docs/features/configuration#css-%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3)
linuxのファイルのパーミッション4桁目

linuxのファイルのパーミッション
0644とかの4桁目のことをよく忘れるのでメモ。

# 3桁目まで
| 100 の位 | 10 の位 | 1 の位 |
|:--------:|:--------:|:------:|
| オーナー| グループ | 全員  |


| 読込権限 | 書込権限 | 実行権限 |
|:--------:|:--------:|:------:|
| 4| 2 |1  |


# 4桁目
4桁目は特殊な権限設定

| setuid | setgid | sticky bit |
|:--------:|:--------:|:------:|
| 4| 2 |1  |

0 : とくになにもなし
1 : スティッキービット: 所有者以外消せないけど誰でも書き込めるって奴。　/tmpとかのディレクトリに初期設定されてる。ファイルに付与したら何も起きない。
2 : SGID:　付けた場合、そのファイルの所属グループの権限で動くようになる。
4 : SUID: 付けた場合、そのファイルの所有者の権限で動くようになる。

### 2が一番使う？

例えば
person-aとperson-bで更新したいので
同じwebグループに所属させて・・・

```
# groupadd web
# usermod -a -G web person-a
# usermod -a -G web person-b
# chmod 2775 /var/www/html/contents/
```

contents/ 以下に作成されるファイル/ディレクトリのグループは、すべてcontents/ と同じ「web」になる
【Android Studio】画像スピナー(プルダウン)作成

スピナーに画像をセットする処理。
作成するのに少々時間がかかったのでメモ。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/1659d636-8787-7fa1-9144-dfbed2269f84.gif" width=50%>

# スピナーアイテムのレイアウト作成
各々の画像表示用のアイテム

``` item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	android:layout_width="60dp"
	android:background="#FFFFFF"
	android:layout_height="40dp">

	<ImageView
		android:id="@+id/image_view"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:contentDescription="@null"
		app:layout_constraintBottom_toBottomOf="parent"
		app:layout_constraintEnd_toEndOf="parent"
		app:layout_constraintStart_toStartOf="parent"
		app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
```

# Adapterの作成

`getDropDownView`のコメントアウトを外すと、ドロップダウンのビューと表示ビューを切り分けることができるようになる。

```SpinnerAdapter.kt
class SpinnerAdapter(private val imageResIdList: List<Int>) : BaseAdapter() {

	override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
		val view = convertView ?: LayoutInflater.from(parent?.context)
			.inflate(R.layout.item, parent, false)
		view.findViewById<ImageView>(R.id.image_view).setImageResource(imageResIdList[position])
		return view
	}

	override fun getItem(position: Int): Any {
		return imageResIdList[position]
	}

	override fun getCount(): Int {
		return imageResIdList.size
	}

	override fun getItemId(position: Int): Long {
		return position.toLong()
	}

	/*
	override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup?): View {
		val view = convertView ?: LayoutInflater.from(parent?.context)
			.inflate(R.layout.dropdown_item, parent, false)
		view.findViewById<ImageView>(R.id.image_view).setImageResource(imageResIdList[position])
		return view
	}
	 */
}
```

# Activityレイアウト作成

メインビュー内にスピナーを配置。

```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	xmlns:tools="http://schemas.android.com/tools"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	tools:context=".MainActivity">

	<Spinner
		android:id="@+id/spinner"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		app:layout_constraintBottom_toBottomOf="parent"
		app:layout_constraintEnd_toEndOf="parent"
		app:layout_constraintStart_toStartOf="parent"
		app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
```

# Acitiviyの処理作成

スピナーにアダプターをセット。

```MainActivity.kt
binding.spinner.adapter = SpinnerAdapter(listOf(R.drawable.check_icon, R.drawable.clear_icon, R.drawable.square_icon))
```
古いDebianをインストールするには（個人的作業覚書）

備忘録として・・・。

http://cdimage.debian.org/mirror/cdimage/archive/
まずは古いdebian のdebian-508-i386-netinst.isoをダウンロードしてくる。

1.アーカイブミラーのサポートが終了しているので設定せず最小構成でインストールする
（※英語版じゃないとCUIすら文字化けで使い物になりませんので注意）
2.その後CUIで立ち上げ


```
su
rm /etc/apt/sources.list　
```

からの　

```
nano /etc/apt/sources.list
```
これに

```
deb http://archive.debian.org/debian/ lenny main
deb-src http://archive.debian.org/debian/ lenny main
```

を書き加えて、　apt-getが使えるようにします。

```
apt-get update
reboot
```

これだけではGUIが使えないので、GNOMEをインストールします。
これはかなり困難でしたがxwindowの存在で助かりました。

```
apt-get install x-window-system
```

インストールが終わったら

GNOMEのインストール。

```
apt-get install gnome gdm gdm-themes
```

このあとGUI画面でワークグループ→OKでEnterを押し、
DHCP →　YESでまた各種インストールが走ります。
割と時間がかかるので気長に待ちましょう。

```
reboot
```

これで無事GUI環境からスタートできるはずです。

ちなみに過去のVer名はこちら。
Debian 9 (stretch) 
Debian 8 (jessie) 
Debian 7 (wheezy) 
Debian 6.0 (squeeze) 
Debian GNU/Linux 5.0 (lenny)
コンピューターグラフィックスツールを開発しました

コンピューターグラフィックスのツールを開発しました。皆様に使っていただきたくて、こうして宣伝記事を書いています。よろしくどうぞ！！！

# プロジェクト詳細

プロジェクト名は ShadowEye といいます。

![2021-10-20 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4734/e77fc581-7a00-ae6b-1a80-74b7af0e0982.png)


# 開発の背景

普段OpenCVを使ってコードを書いているけれども、あのOpenCVのAPIすぐに使いたいなーと思った時に、従来であれば面倒くさいmain.cppファイルを書き、ビルドして、実行して初めて結果が得られますよね。私はその手間が嫌でした。なので、OpenCVのAPIに対応する機能をGUIから選んで入力した画像に適用してやるようなアプリの開発を目指しました。

当プロジェクトはスクラッチ開発です。2014年あたりから開発をしていましたが、以来2021年10月になるまでホコリかぶっていました。今日ソースコードをサルベージして公開するに至りました。

# 動作環境

Windows 10/Windows 11等
.NET Framework 4.8 が必要です。

# どんなことができるの？

バージョンv1.1.3現在、3つの入力ソースと8つの画像処理があります。

## 入力ソース

* カメラ（USBWebカメラでも組み込み済みカメラでも可）
* 画像ファイル
* スクリーンショット（仮想スクリーン全体/各スクリーン/デスクトップ/ウィンドウ）

## 利用可能な画像処理

* 減算
* 乗算
* チャンネルの統合
* チャンネルの抽出
* 2値化
* 拡大縮小
* 色空間変換

まだ書いている途中ですが、HowToUse.mdを用意しましたので、そちらも参照ください。

[HowToUse.md](https://github.com/dhq-boiler/ShadowEye/blob/develop/HowToUse.md)

# お金がかかりますか？

オカネカカリマセン！カンゼン☆ムリョウデス！！！

# プロジェクトURL

https://github.com/dhq-boiler/ShadowEye

# どこからダウンロードできるの？

[GitHub Release](https://github.com/dhq-boiler/ShadowEye/releases)からzipファイルのダウンロードができます。それを展開して好きなところに配置すればインストール完了です！

# バグ報告はどうやればいい？

[Issues](https://github.com/dhq-boiler/ShadowEye/issues)から好きなように投稿していただければと思います。日本語OK、English OKです。

バグ報告どんどん来て欲しい...。

皆様の研究活動がさらにはかどることを願って。
2021/10/20

# 宣伝

こちらもよろしくです。

ベクターグラフィックスドローイングを開発しました
https://qiita.com/dhq_boiler/items/dd2afcc36a5a205872eb
GASでfunction () { [native code] } が出た

#結論
() 忘れが原因だった

#詳しい話
```js
function myFunction() {
  const spreadSheetByActive = SpreadsheetApp.getActive();
  const sheet = spreadSheetByActive.getSheetByName('sheet1');
  const cell = sheet.getRange('A1');
  Logger.log(cell.getValue);
}
```

こんなの書いてました
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1053860/d12ec552-a1f9-840a-5b01-17bdc327bdb2.png)
なにこれ。
`function () { [native code] }`てログがあります。なにそれ。

あっ！気が付きました！

```js
function myFunction() {
  const spreadSheetByActive = SpreadsheetApp.getActive();
  const sheet = spreadSheetByActive.getSheetByName('sheet1');
  const cell = sheet.getRange('A1');
---  Logger.log(cell.getValue);
+++  Logger.log(cell.getValue());
}
```
ただのミスでした。
laravel collective　間違いやすい箇所

# なんでもtokenを書くべきじゃない

```php
Form::open(['url' => 'home'])

//↓HTMLではこう書かれていることになる
<form method="POST" action="http://localhost:3000/home" accept-charset="UTF-8">
<input name="_token" type="hidden" value="eAFowzR2efsBNQYrVzQ4VymRbYQB2afVyEDijzqd">
```

自動的にCSRFトークンが追加されて出力される。

そのためこの直後に

```php
{{Form::token()}}
```

は必要ない


重複していた
{{Form::token()}}を書くとf12で調べると↓ができてた（無駄に）

```php
<input name="_token" type="hidden" value="yaSSZowIRXjlDCEpHuO2wasNlcf4U3moVPG4lOE0">
```


# 意外に間違われているlabel

```php
//HTML
<label for="name">氏名</label>

# Formファサード
{{Form::label('name','氏名')}}
```

第1引数 は"関連付けフォームの指定 for（input要素のid）"
→nameではない

input要素にid属性を設定し、label要素のfor属性でinput要素のidを指定する

↓参考記事
https://style.potepan.com/articles/20037.html
s3 ウェブサイトに route53 でカスタムドメインを設定する

# はじめに

s3 で構築したウェブサイトに route53 でカスタムドメインを設定しようとしたときに少しハマったので、問題点と解決方法を簡単にまとめました。

# 結論

ドメイン名とバケット名を完全に一致させる。

## ハマったこと

route53 で s3 のウェブサイトエンとポイントに対して A レコードを設定しようとした際に、リソースが見つからないと表示されました。s3 の東京リージョンには、バケットは複数存在しているので原因がわからず困っていました。
![スクリーンショット 2021-10-20 15.40.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582722/0cc4efc1-7ffb-f765-af84-f3dca00f9968.png)



# 解決方法

困っていたところ下記の記事を見つけました。

[Configuring a static website using a custom domain registered with Route 53](https://docs.aws.amazon.com/AmazonS3/latest/userguide/website-hosting-custom-domain-walkthrough.html#root-domain-walkthrough-create-buckets)

> To support requests from both the root domain and subdomain, you create two buckets.
> 
> - **Domain bucket** – `example.com`
> - **Subdomain bucket** – `www.example.com`
> 
> These bucket names must match your domain name exactly. In this example, the domain name is `example.com`.
> 

こちらにある通り、ドメイン名とバケット名を完全に一致させてやる必要があります。

そこでドメイン名と全く同じ名前のバケットを作成しました。

![スクリーンショット 2021-10-20 15.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582722/3da71337-476d-e752-b186-e2083d90e7b7.png)


s3 で静的ウェブサイトの設定を行い、再度 route53 にアクセスすると、みごとターゲットが表示されました！

![スクリーンショット 2021-10-20 15.51.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582722/25485094-1bbe-7668-d02f-85fa7aa51478.png)


レコードを作成して、指定したドメインにアクセスすると s3 の静的ウェブサイトの項目で設定したコンテンツが表示されるはずです。

# cloudformation

上記の内容を cloudformation で構築すると以下のようになります。

```yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Create S3 Website

Parameters:
  HostZoneId:
    Type: String
  Domain:
    Type: String
Mappings:
  S3Config:
    ap-northeast-1:
      WebsiteEndpointHostZoneId: Z2M4EHUR26P7ZW

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref Domain
      AccessControl: PublicRead
      PublicAccessBlockConfiguration:
        BlockPublicAcls: false
        BlockPublicPolicy: false
        IgnorePublicAcls: false
        RestrictPublicBuckets: false
      WebsiteConfiguration:
        IndexDocument: index.html

  DNSRecordSet:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref HostZoneId
      Name: !Ref Domain
      Type: A
      AliasTarget:
        HostedZoneId: !FindInMap
          - S3Config
          - !Ref AWS::Region
          - WebsiteEndpointHostZoneId
        DNSName: !Sub s3-website-${AWS::Region}.amazonaws.com
```

下記コマンドでリソースを構築できます。

```sh
aws cloudformation create-stack \
  --stack-name s3-sample \
  --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \
  --template-body ${template file の path} \
  --parameters \
    ParameterKey=HostZoneId,ParameterValue=${route53 のホストゾーンID} \
    ParameterKey=Domain,ParameterValue=${設定したドメイン名}
```

# 余談

s3 の静的ウェブサイトは https に対応していないので、https に対応させるためには cloudfront を導入する必要があります。

[Route 53 に登録されたカスタムドメインを使用した静的ウェブサイトの設定](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/website-hosting-custom-domain-walkthrough.html)
Excel VBAメールを送信

# はじめに
Excelからマクロ(VBAマクロ)を使って、Outlookアプリケーションを呼び出し、メールを送信する仕組みを実装したい。

# やりかた

## 1.参照設定

1. [ツール]-[参照設定]にある[Microsoft Outlook 16.0 Object Library]をチェックし、[OK]ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/26b65943-4d78-50c7-2aca-77814c409a3d.png)

## 2.テストメールを送信するSub関数を作ります

```vb:
Sub testmail()
    Dim appOutlook As Outlook.Application
    Dim objMail As Outlook.MailItem
    
    Set appOutlook = New Outlook.Application
    Set objMail = appOutlook.CreateItem(olMailItem)
    
    With objMail
        .To = "test@test.domain"
        .Subject = "テストメール"
        .Body = "テストメールを送ります。これはExcelマクロから送られました"
        .BodyFormat = olFormatPlain
    End With
    
    objMail.Send
End Sub
```

これで単純にメールを送信できるようになりました。

# 参考

https://officevba.info/excelvbaoutlookoperation/

https://tonari-it.com/excel-vba-outlook-mail-send/
ファイル名やディレクトリ名に指定できない文字のチェック

ファイル名やディレクトリ名に使用できない文字が含まれていないかチェックするために、正規表現を使ったのでまとめておく。

# 正規表現
**正規表現**とは、特殊な文字や記号を使っていくつかの文字列を1つの文字列で表現する方法のこと。今回正規表現の記号と意味についての紹介は省略します。JavaScriptで正規表現を使う方法は2種類ある。
■ **正規表現リテラル**
・スラッシュ(/)の中に正規表現パターンを直接指定する。
・正規表現のパターンが変化しない時に使用。
■ **RegExpのコンストラクタ**
・```RegExp()```の引数に正規表現パターンを直接指定する。
・外部からの入力など正規表現パターンが変化する場合に使用。

```javascript
const pattern = new RegExp(<正規表現パターン>);
```

# 実装
###1.正規表現パターンの指定
今回は、ファイル名やディレクトリ名に使用できない文字は固定なので、**正規表現リテラル**を使用した。名前に指定できない文字は「**\/:*?"<>|**」の9種類なので、正規表現リテラルを使用して以下と書いた。

```javascript:正規表現リテラル
const pattern = /[\\\/:\*\?\"<>\|]/;
```
ここで、```[]```は[]内のいずれか任意の1文字と一致することを意味している。
さらに、「*」や「?」などは特殊文字として認識されないように「\」を付加して記述する必要がある。これを<font color="Red">エスケープ処理</font>という。

###2.正規表現パターンとの比較
正規表現には、```match```や```replace```などのメソッドが用意されている。
今回は、```test```メソッドを使って正規表現パターンとの比較を行った。
```test```は、引数で指定された文字に正規表現パターに一致する文字があれば、true。なければfalseを返す。書き方としては、以下となる。

```javascript
正規表現パターン.test(比較対象の文字列);
```

これを用いて比較を行った。以上を使ってチェックする関数を書いてみた。

```javascript:
function checkNameFormat(name) {
  const pattern = /[\\\/:\*\?\"<>\|]/;
  return pattern.test(name);
}
```

#まとめ
正規表現を使ったファイル名やディレクトリ名に使用できない文字が含まれていないかチェックする方法をまとめてみた。まだ理解しきれていない所があり、誤りがあるかもしれないが今後修正を行っていきたい。

####参考
[https://www.sejuku.net/blog/20973](https://www.sejuku.net/blog/20973)
CronusMaxPlusでホリツインスティック設定のメモ

■ツールのインストール

・https://cronusmax.com/ で
　MENU -> DOWNLOADS -> CLICK HERE ->DOWNLOAD
　Cronus PRO のDownloadボタンを押す

・Cronus_0121_Setup.zipを解凍、Cronus_0121_Setup.exeを実行。
　指示に従いインストール。


■ファームウェアアップデート

・プログラミングポートにminiUSBケーブルをつなぎ、PCのUSBポートとつなぐ。

・Cronus PRO起動。

・Tools -> Firmware Updateを選択、指示に従い必要に応じてアップデート。

■基本設定

・Tools -> Options を選択。
・Deviceタブで1ms Responseのチェックを入れる。
・CMax Plusタブで
　Enable PS4 Partial crossover support (auto reconnect every 10 min)に
　チェックを入れる。
・Close押して閉じる。（先の「焼き込み」して初めて実機に反映されると推測さる）

■マッピング設定（基本のキーマップ変更スクリプト生成）

・Plugins -> MAX Mapper を選択。

・INPUT:欄をXBOX360パッド（右から2番目）を、
　OUTPUT:欄をPS4（左から1番目）を選択。

・設定にあたり考えた割り当て

　ホリツインスティックのボタンは、
　　左端　　　 XBOXボタン
　　上段左から Y X B A
　　下段中央　 BACK
　　右端　　　 START
　タニタツインスティックは
　　上段左から ○ △ ×
　　下段中央　 □
　　右端上段左から　SHARE PS
　　右端下段　　　　OPTIONS
　なので、
　　XBOX ->   PS ※
　　A    ->   SHARE
　　X    ->   △
　　Y    ->   ○
　　B    ->   ×
　　BACK ->   □
　　START->   OPTIONS ※
　に割り付ける。
　タッチパッド・ACCX,Y,Zには割り当てなし。

・設定おわったらGenerate GPC Scriptを押す。
　そうするとこんなスクリプトが自動生成される。

～～～～～
//
// 2020-01-05 20:08:24
// Script generated by MAX Mapper Plugin
//----------------------------------------
remap XB360_A -> PS4_SHARE;
remap XB360_Y -> PS4_CIRCLE;
remap XB360_B -> PS4_CROSS;
remap XB360_BACK -> PS4_SQUARE;
unmap PS4_ACCX;
unmap PS4_ACCY;
unmap PS4_ACCZ;
unmap PS4_TOUCH;

main {
}
～～～～～
　※印の項目については、スクリプト記述無しでも割り当てられる標準割り当てなので
　　該当スクリプト行がない。

・スクリプトを次のように書き換え、File -> Save Asから名前をつけて保存する。

～～～～～
remap XB360_A -> PS4_SHARE;
remap XB360_X -> PS4_TRIANGLE;
remap XB360_Y -> PS4_CIRCLE;
remap XB360_B -> PS4_CROSS;
remap XB360_BACK -> PS4_SQUARE;
unmap PS4_ACCX;
unmap PS4_ACCY;
unmap PS4_ACCZ;
unmap PS4_TOUCH;

main {
	remap_leftstick();
}

function remap_leftstick(){
	if(get_val(XB360_UP))
	{
		set_val(PS4_LY,-100);
	}
	else if(get_val(XB360_DOWN))
	{
		set_val(PS4_LY,100);
	}
	if(get_val(XB360_RIGHT))
	{
		set_val(PS4_LX,100);
	}
	else if(get_val(XB360_LEFT))
	{
		set_val(PS4_LX,-100);
	}
	return 0;
}
～～～～～
　これにより、ホリの左スティック操作（＝デジタル十字パッド扱い）に応じて
　アナログ左スティック操作もされるよう処理される。

■コンパイル

・Compiler -> Compileを押す。

■ビルドと動作テスト

・Compiler -> Build and Runを押す。

・このとき、実際に使用するコントローラを変換器本体のUSBメスポートに
　刺しておくと、コントローラ操作に応じて何が出力されるか画面で確認できる。

■設定の焼き込み

・Compiler -> Program Device を押す。

・終わったら、PCから外してPS4につなぐ。


■使用時の注意

・本体のボタンを押し、7セグLEDが「1」を表示するようにする。
・なおTwin-Aで操縦するのを前提としている設定だが、
　△＝レスキュー　□＝味方指示　と別途VOMP上で設定が必要。
セキュリティ資格ロードマップ

本記事の更新版が以下にあります。

https://qiita.com/log0417/items/fda1ad7248435c13dc0b

# セキュリティ資格ロードマップとは？
以下に掲載されているものです。Security Certification Roadmapというもので、随時更新されたものが公開されています。
https://pauljerimy.com/security-certification-roadmap/

セキュリティ資格ロードマップは、横に長いほど複数の分野にまたがっていることになります。
例えばセキュリティ業界では最も有名な資格の1つであるCISSPは、ここに記載されているすべての分野にまたがっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549537/f3998a91-adb7-9da9-1b69-079a7f56b228.png)

また、明記はされていませんが、上に記載されているほど難しい資格になると思われます。
一番上に記載されているGSEは、受験するための条件から厳しく、間違いなく最難関だと思います。
ただ、そのすぐ下にGREMは、確かに難しい資格ではあると思いますが、CISSP以上の難易度だとは思いません。
おそらく見方としては、他分野の資格と比較するのではなく、同じ分野の資格と比較すべきなのでしょう。

# 保有資格との整合性チェック
このマップの中で私が保有する資格を黄色枠で囲いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549537/9ff30012-9731-d650-d864-c5028abe8d42.png)


前述のとおり、同一分野の資格同士で比較するようにしますが、明らかに位置がおかしい場合は記載することにします。

* 左下のNet+はCompTIA Network+です。難易度は妥当と思います。
* LPIC-1～LPIC-3までが縦に並んでいます。１と２は妥当と思いますが、３は上すぎる気もします。CASP+よりは明らかに下だと思います。
* Security+、SSCP、CASP+、CISSPの順番は妥当と思います。感覚的にはCASP+はもう少し上かもしれません。
* CySA+はCompTIA CySA+です。思ったより下かなという印象です。LPIC-2より下とは思いません。もう少し上が妥当かもしれません。ただ、分野があまりに異なるので、単純な比較は難しいです。
* GREM、GCFAはどちらも難関資格の部類ですが、CISSPほどではないかなと思います。これは持ち込み可能ゆえに難易度が落ちているだけで、試験そのものはCISSPと同等以上だと思います。（こういった試験の特性を含めて比較するのは難しいですね）
* PenTest+はCompTIA PenTest+です。これも思った以上に下だなと思います。とはいえ、OSCPが真ん中付近にあることを踏まえると、妥当なのだと思います。

# Next Challenge
ぜひ保有している資格を探して、次に目指す資格を見つけてみてください。
私はGNFA、CISA、CISMの順に挑戦していく予定です。
海しるAPIを使ってみる その2

[海しるAPIを使ってみる](https://qiita.com/hightidesgoodvibes/items/4edeb73ea808311bcf07)の続き。

海洋速報のデータを取得するAPI

https://portal.msil.go.jp/api-details#api=602b24c865379cd6fe879151

まずはJSON出力。

必須項目はないものの、日付を指定しないとすごい量のデータが出てくるので、それだけは指定したい。日付はUNIX時間で記述するので、変換ツールを使いながら入力。

https://tools.m-bsys.com/development_tooles/unix_time.php

[海しるAPIポータル](https://portal.msil.go.jp/api-details#api=602b24c865379cd6fe879151&operation=612c2271507c96ff35c252d9)で作成したHTTPのコード。

```
GET https://api.msil.go.jp/oceanography/current-observation/quick-bulletin/v1/query?units=meter&time=1634569200000&returnGeometry=true&type=kuroshio HTTP/1.1

Cache-Control: no-cache
Ocp-Apim-Subscription-Key: 0e83ad5d93214e04abf37c970c32b641
```

python3で。

```
import requests
r_uri = "https://api.msil.go.jp/oceanography/current-observation/quick-bulletin/v1/query?units=meter&time=1634569200000&returnGeometry=true&type=kuroshio HTTP/1.1"
headers = {
# Request headers
'Cache-Control': 'no-cache',
'Ocp-Apim-Subscription-Key': '0e83ad5d93214e04abf37c970c32b641',
}
r_get = requests.get(r_uri,headers=headers)
print(r_get.status_code)
print(r_get.json())
```

画像出力。こちらはバウンディングボックスと時刻が必須。

python3で。

```
import requests
r_uri = "https://api.msil.go.jp/oceanography/current-observation/quick-bulletin/v1/export?bbox=135.0%2C30.0%2C140.0%2C40.0&time=1634569200000&transparent=false&dpi=96"
headers = {
# Request headers
'Cache-Control': 'no-cache',
'Ocp-Apim-Subscription-Key': '0e83ad5d93214e04abf37c970c32b641',
}
r_get = requests.get(r_uri,headers=headers)
print(r_get.status_code)
file_name = "png.png"
with open(file_name,"wb") as aaa:
    aaa.write(r_get.content)
```

参考にした記事

https://note.nkmk.me/python-requests-web-api/

https://qiita.com/ozaki_physics/items/c17ca626b480d352e90f
WordPressのブロックエディタでサイト構築した感想

# 背景
WordPressブロックエディタ（Gutenberg）を使って
サイト構築する機会がありましたのでその感想を残しておきます。

## 環境
WordPress v5.7.2
ブロックエディタの採用は一画面の本文エリアのみ
残りはオリジナルテーマのテンプレート使用

# ブロックエディタ（Gutenberg）について

- 管理画面の見た目をフロントに合わせることができる
- いままでのWPエディタ（クラシックエディタ）でもできたけど複雑なパーツはウィジェットの組み込みが必要だった
- より直感的に記事の編集ができるようになった

# ブロックについて

選べるブロックは65種類（v5.7.2）
[ブロック一覧の画像（別タブで開きます）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164197/359e80e7-5d80-94da-4256-90cd1f35cadc.png)


## 必要ブロック選定前後の比較

![必要ブロックの選定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164197/f5f0c12f-ae2e-c5aa-c17d-147ca11eebc4.png)

画像左側: ブロック一覧
画像右側: ブロック一覧から無効化するブロックをグレーアウト

実際に運用で使う可能性があるブロックは極一部だとわかりました。
この案件で必要なブロックは18個でした。

# エディタのカスタマイズで気にする点

役割間で連携がクラシックエディタよりも必要

## ディレクター視点

- 運用で使う可能性があるブロックの選定（無効化するブロックや機能を決める）

## デザイナー視点

- デザインが必要なブロックの洗い出し（youtube等外部サービスの埋め込みのデザインは作る必要がない）

## 実装者視点

- エディタの自由度をどこまで許容するか
- ブロック（新規ブロックを作成するか既存ブロックを拡張するか）として実装するか、パターンとして実装するか

→運用時の操作に関わってくるのでディレクターと連携が必要（操作方法の共有が必要になる）

# 実装上の注意

- WordPressのバージョンは5.8以降か（[theme.json](https://make.wordpress.org/core/2021/06/25/introducing-theme-json-in-wordpress-5-8/)で設定ができるようになって楽）
- CSSの設計（scssファイルの分け方：どのファイルをincludeするか、個別でビルドするか、WPデフォルトのcss変数を踏襲するか等）

# 感想のまとめ
- 使用ブロックの選定は事前に行う
- できればWordPressバージョンは5.8系以降を採用すること（実装難度や工数に関わるため）
- CSSの設計はstaticだけでなく、あらかじめWP環境でも試しておく（読み込みが必要なファイルの洗い出しを行いたい）
if __name__ == '__main__': って何？

pythonの勉強をしていると

    if __name__ == '__main__' :
という記述を見かけますよね、これがあると何が起こるのかという話です。

これがあると
<strong>importしたときに関数が実行されなくなります。</strong>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531208/a1be105b-4b83-5f95-906d-ea303753cb83.png)
こんな関数helloをimportすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531208/cbc0e812-d58c-9847-863d-7d11af68bdff.png)

とimportしただけで関数mainが実行されてしまいます、では

    if __name__ == '__main__' :
を入れたバージョンをimportしてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531208/ab9d0b72-c5d4-a8f1-abd7-5bc6f02c2744.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531208/49466bf5-13da-1897-7a05-9f63800085a4.png)
これをつけることでimportしたときに関数が実行されなくなりましたね。

#そもそも\_\_name\_\_って何？#
\_\_name\_\_は<strong>pythonの特殊な変数</strong>です。
これには<strong>Pythonのモジュール名</strong>が文字列で格納されています、
つまり
import hello
とすれば\_\_name\_\_ は'hello'　という文字列になります。
python hello.py
とすれば \_\_name\_\_は'\_\_main\_\_'という文字列になります。
これらはPythonが自動で設定してくれます。

##つまり##
    if __name__ == '__main__': 
というIF文はこのコードが

    python hello.py
で実行されたものなのか否かを判定しているわけです。
4-3.2 CSS演習2

# 完成イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/bb84d099-a0d8-30a1-f34b-50af1f61cb86.png)

※ブラウザの幅を変えてみてください。各幅の割合は一定を保っています。

# ソース

後ほど公開します。

```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>タイトル</title>
    <style>
      .tblsec {
        width: 100%;
      }
      .tblsec th {
        color: blue;
        background-color: burlywood;
      }
    </style>
  </head>
  <body>
    <h1>演習</h1>
    <table border="1" class="tblsec">
      <tr>
        <th colspan="2">平均</th>
        <th rowspan="2">い</th>
      </tr>
      <tr>
        <th style="width: 20%">高さ</th>
        <th style="width: 20%">幅</th>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>
          <input type="radio" name="rdo1" value="0" />55
          <input type="radio" name="rdo1" value="1" />32
        </td>
      </tr>
      <tr>
        <td>4</td>
        <td>5</td>
        <td>6</td>
      </tr>
    </table>
  </body>
</html>
```
nullをreturnしないメモ

# 概要
チームメンバーがnullをreturnしていたのですが、想定している挙動が分からないので他に置き換えた方がいいのではと思い、説明のために整理したメモ。

nullのreturnは、例えばこのようなコードです。

```java
public ZonedDateTime calculationDate(ZonedDateTime acceptAt) {
        if (acceptAt == null) {
            return null;
        }
```

## null返り値が保守作業に与える悪影響の調査
ソフトウェアシンポジウム2013で発表があった模様。
https://sdl.ist.osaka-u.ac.jp/pman/pman3.cgi?DOWNLOAD=229

null返り値はバグを含みやすくなる。

> 分析の結果，null 返り値および null チェックが，規模や作業工程の種別に関係なく頻繁に修正されることを確認した.修正頻度が高いという ことは，バグを含みやすくなると考えられるため，null 返り値および null チェックが保守作業に悪影響を 及ぼしていることを示している.

null返り値は簡易に記述できるのが利点の一方で、バグを発生させる原因として知られている。

> メソッド内で満たすべき条件を満たさなかった際に null を返す記述が多数存在する (null 返り値).エラー定数 や例外処理を用いる場合に比べ，null 返り値を用いる利点は以下のとおりである.
• null は特殊な値であるため，プログラムが満たすべき条件を満たさなかったことが一目でわかること.
• 満たさなかった条件に合わせたエラーメッセージを考える必要がないこと.
• 例外処理などに比べ，簡易な記述が行えること.
null 返り値はこのように開発者の助けとなる一方で，バグを発生させる原因として知られている.null 返り値 に関連する主なバグとして，null 値参照が挙げられる.

null返り値を安易に記述してしまう前に他の記述を考えるべきとある。

> これらの分析により，様々なプロジェクトにおいて，null 返り値および null チェックが保守作業に悪影響を与えて いることがわかった.そのため，開発者は null 返り値を 安易に記述してしまう前に，他の記述で置き換える事がで きないかを考えるべき，といえる.具体的には，例外処理 を用いる方法，null の代わりに適切なオブジェクト(空の 配列，特殊なクラスなど)を返す，などが挙げられる

## Javaでメソッドから戻る・戻り値を戻す returnの使い方と活用方法
nullかもしれないならOptionalでreturnするのも良さそう。
https://www.bold.ne.jp/engineer-club/java-return#-nullOptionalreturn

```java
static Optional<String> getNullable() {
```

#　まとめ
null返り値を使ってはいけないわけではないですが、まずは他の記述に置き換えられないか考えてみないとですね！
Docker DesktopをインストールしたらHyper-VをDisableにしてもVMware Playerが起動しなくなった

VMware PlayerとHyper-Vが共存できるようになったというので、VMware Workstation 16 Proが動いているWindows10にDocker Desktopをインストールしてみたら、ハードウェア的に要件を満たしていなかったらしくVMwareが立ち上がらなくなった。

エラーは以前も見たことがある以下の通り

「Hyper-V または Device/Credential Guard が有効な状態で VMware Workstation を実行するのに必要な最小要件をホストが満たしていません。詳細については、https://kb.vmware.com/kb/76918 で VMware ナレッジベースの記事 KB76918 を参照してください。」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120864/e39e2a4e-da91-27a9-b0c6-951dc3f61f48.png)




「トランスポート（VMDB）エラー -14： Pipe connection has been broken。」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120864/78b54eba-2456-5726-b4b0-fd957e0215c4.png)


（いつものように）Hyper-VをDisableにしてから立ち上げてみるも状況変わらず・・・

[VMware Workstation and Device/Credential Guard are not compatible" error in VMware Workstation on Windows 10 host (2146361)](https://kb.vmware.com/s/article/2146361?lang=en_US)にある以下コマンドを、管理者として起動したコマンドプロンプトから実行することで解決。

```
>bcdedit /set hypervisorlaunchtype off
```
"brew install wget"でエラー（Mac M1）

Homebrewをインストールして`brew install wget`を実行したところ、以下のエラーが発生しました。その際に試して上手くいった解決法をメモします📝

```エラー文（Terminal）
% brew install wget
==> Tapping homebrew/cask
Cloning into '/opt/homebrew/Library/Taps/homebrew/homebrew-cask'...
remote: Enumerating objects: 598443, done.
remote: Counting objects: 100% (64/64), done.
remote: Compressing objects: 100% (53/53), done.
remote: Total 598443 (delta 30), reused 37 (delta 11), pack-reused 598379
Receiving objects: 100% (598443/598443), 268.33 MiB | 5.37 MiB/s, done.
Resolving deltas: 100% (422958/422958), done.
Tapped 3928 casks (4,008 files, 287.5MB).
Warning: No available formula or cask with the name "wget".
==> Searching for similarly named formulae...
Error: No similarly named formulae found.
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
==> Searching taps on GitHub...
Error: No formulae found in taps.
```
`Warning: No available formula or cask with the name "wget"`と書かれており、wgetが見つからないと書かれています。

そんなはずないということでネットで検索していたところ、以下のコマンドを実行することによって解決できました。

```
brew update-reset
```
処理が完了した後に再度`brew install wget`を実行したところ無事にインストールすることができました。

### 実行環境
macOS BigSur ver. 11.5.2
MacBook Air (M1, 2020)



### 参考サイト
https://github.com/Homebrew/homebrew-core/issues/37724
SQLインジェクションについてまとめてみた

### 本日のお題
本日のお題は*SQLインジェクション*です。
最初に学んだ時には今ひとつ理解しきれなかった感が強かったものですが、改めて学んでみてある程度理解が深まったので記念に残しておきます。
### 目次
- SQLインジェクションとは
- SQLインジェクションの具体例
- SQLインジェクションの回避策

### SQLインジェクションとは
最初に、SQLインジェクションという単語の大まかな説明をしておきます。
SQLインジェクションとは、フォームの入力欄やURLにSQL文を埋め込むことでページを書き換えたり情報を不正に入手したりする方法です。
### SQLインジェクションの具体例
では、SQLインジェクションの具体例として、本来であればユーザー名とパスワードを入力しなければならないページにパスワードなしでログインし、ユーザー情報を盗みるということをやってみようと思います。

前提として、フォームにユーザー名とパスワードが入力されると以下のクエリが実行され、ユーザー認証およびユーザー情報の返却を行うものとします。

```sql
select * from users where name='$name' and password='$password'
```
では、ここに以下のように入力するとどうなるでしょうか

```
$name = taro
$password = ' or 'a'='a
```
シングルクォーとの数があっていなかったりして少し気持ち悪いですが、上記のsqlに代入すると以下のようになります。

```sql
select * from users where name='taro' and password='' or 'a'='a'
```
少し変な文章ですが、以下のどちらかが成り立てばtaroの情報が返却されます。

- passwordが空文字の場合
- a = a が成り立つ時

後者は必ず成り立つので、パスワードが不明でもユーザー名さえ分かっていればユーザー情報が取得できるというわけですね。

では、このようなSQLインジェクションはどうすれば防げるのでしょうか。
### SQLインジェクションの回避方法
回避方法の一つ目は、フォームのデータを受け取る時点で''を他の文字に変換することです。
SQLにおいては''は文字列の切れ目を表しており、これを入力内容に混ぜることでクエリの操作が可能になります。

逆に、フォームに入力された''を他の文字に変換してしまえばそのようなことはできなくなるのでSQLインジェクションは成り立たなくなります。

```sql
// ''を*に置き換えた例
select * from users where name='taro' and password='* or *a*=*a'
```
上記の例であれば、ユーザー名が"taro"でパスワードが"* or *a*=*a"のユーザーを検索するクエリが実行されるだけなので、不正アクセスはできなくなります。

SQLインジェクションの回避方法の二つ目は、先にSQLの構文を決めてしまうことです。
SQLはselect, where, and, orなどからなりますが、これらの有無をフォームの値を受け取る前に先に決めてしまおうということですね。

```shell
Preparing: select * from m_user left join m_department on m_user.department_id = m_department.department_id where user_id = ?
```
例えば、上記は私がjavaの学習を行なっていた際にターミナルに出力されたログです。
?を関数でいうところの仮引数的に使用することで、SQLの文型を固定しています。

同じように、上記の例でも?を用いて構文を固定してしまえば、フォームに何を入力してもOR句ありの文章に変更することはできなくなります。

```sql
select * from users where name=? and password=?
```
ちなみに、先ほどから?のことを引数と読んできましたが、SQLの世界ではプレースホルダーと呼びます。
JAS_2021_10 作業環境


# obd python 3.7.10

```bash
$ conda create -n py37_JASMINE_2021_10 python=3.7 anaconda

Collecting package metadata (current_repodata.json): done
Solving environment: failed with repodata from current_repodata.json, will retry with next repodata source.
Collecting package metadata (repodata.json): done
Solving environment: done


==> WARNING: A newer version of conda exists. <==
  current version: 4.9.2
  latest version: 4.10.3

Please update conda by running

    $ conda update -n base -c defaults conda



## Package Plan ##

  environment location: /home/_user_name_/.pyenv/versions/anaconda3-5.2.0/envs/py37_JASMINE_2021_10

  added / updated specs:
    - anaconda
    - python=3.7


The following NEW packages will be INSTALLED:

  _libgcc_mutex      pkgs/main/linux-64::_libgcc_mutex-0.1-main
...


Proceed ([y]/n)? y

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
#     $ conda activate py37_JASMINE_2021_10
#
# To deactivate an active environment, use
#
#     $ conda deactivate

```

## photutils
```bash
$ pip install photutils
WARNING: Keyring is skipped due to an exception: Failed to unlock the collection!
Collecting photutils
  Downloading photutils-1.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (842 kB)
     |████████████████████████████████| 842 kB 5.9 MB/s 
Requirement already satisfied: astropy>=4.0 in ./.pyenv/versions/anaconda3-5.2.0/envs/py37_JASMINE_2021_10/lib/python3.7/site-packages (from photutils) (4.2.1)
Requirement already satisfied: numpy>=1.17 in ./.pyenv/versions/anaconda3-5.2.0/envs/py37_JASMINE_2021_10/lib/python3.7/site-packages (from photutils) (1.20.1)
Requirement already satisfied: pyerfa in ./.pyenv/versions/anaconda3-5.2.0/envs/py37_JASMINE_2021_10/lib/python3.7/site-packages (from astropy>=4.0->photutils) (1.7.3)
Installing collected packages: photutils
Successfully installed photutils-1.2.0

```
Simplifying Cloud Migration with SaaS Back-up and Recovery for the Financial Service Industry

The cloud data storage system has been proven as essential and critical now more than ever. The benefits and security of data protection on the cloud are unquestionably helpful for businesses across the globe. This pandemic has ensured the usage of cloud applications by organizations on a daily basis. As ‘Data’ has become equally important as ‘Money’ or an asset, so a lot of investment and planning goes into protecting and backing up that data. While organizations understand the importance of ‘Data’ and how an error manual or haphazardly can turn into a blunder. 

It can be a human error either a computer system crashes or a server issue, such situations can be disastrous. That is why having a backup for SaaS or Data is an absolute necessity when in need of recovery. The swiftness, flexibility, and cost-effectiveness that data storage provides have not yet been entirely embraced by the financial services industry (FSI) due to certain challenges in terms of the security of sensitive data/information.
The Law

Recently, the government of India has proposed new law – Personal Data Protection (PDP), pertaining to the GDPR regulations and data protection framework. The PDP Bill puts limitations and restrictions on the usage of personal data collected of individuals with notice and consent. Data localization and consulting in-house data protection officers for companies. In South Africa, the POPAI – Protection of Personal Information Act is set in place for data protection and security regulations.

Companies that do not abide by the rules of the act shall face charges and jail in some cases (Source ITWEB). As the world evolves with Digital Transformation, so with it the risk around data security grows as well. To avoid the loss of data or fraudulent attacks, it becomes an equal responsibility of everyone, cloud service providers, data centers, clients, and individuals of keeping the data safe and secure.

Source: https://www.esds.co.in/blog/simplifying-cloud-migration-with-saas-back-up-and-recovery-for-the-financial-service-industry/