OmniAICreator/Qiita-1.07M huggingface dataset:
A5M2でサーバーのMySQLに接続した際の備忘録

##データの追加と削除
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637823/0236c84d-b55a-0928-09ed-8e5f8ac295a3.png)

##基本設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637823/06ef65f9-e1ff-a66b-5c90-d189a9c66d61.png)

|ポイント|説明|備考|
|----|----|----|
|ホスト名|localhost|ホスト名の確認コマンドは下記記載|
|ポート番号|基本的には3306||
|ユーザーID|ubuntuの場合、<b>rootは不可</b>（sudo権限が必要なため）<br>事前にユーザーを作成するなどの処置をしておく。|https://www.webdevqa.jp.net/ja/mysql/sudo%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%9B%E3%81%9A%E3%81%ABmysql%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B/824503754/|
|パスワード|指定したユーザーIDでログインするためのパスワードを入力||
|データベース|デフォルトではrootユーザーのmysqlになっているが、<b>存在しないDBを指定すると接続エラーになる</b>ので注意|show databases;で確認可能|

##SSH2トンネル設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637823/901ea452-4d9f-6764-e0b7-b16caba55437.png)

|ポイント|説明|備考|
|----|----|----|
|SSH2トンネル経由で接続する|☑をいれる||
|SSH2ホスト名|接続するサーバーのグローバルIPアドレスを指定|サーバーのコントローラー等で確認可能|
|ポート番号|SSHのポートを22から変更している場合はその番号を指定||
|ユーザーID|サーバーに接続する際のユーザーを指定||
|鍵ファイル認証|鍵認証形式でログインする場合は選択||
|パスフレーズ|SSH接続時のパスフレーズを指定||
|秘密鍵ファイル|SSH接続時の秘密鍵のパスを指定||
|SSHローカル待ち受けポートを自動で決定|☑をいれる||

##テスト接続
テスト接続を押下して、接続ができれば、OKを押下して完了

##MySQLユーザー一覧
```
 select user,host from mysql.user;
```
|ポイント|説明||
|----|----|----|
|ホスト名「%」|Host に % を設定すると、全てのホストにマッチする。 Host を空にすると「%」と同じになる。これらの値は、どんなホストもサーバーに接続できるということになる。||

上手くいかない時

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637823/b5cf517e-082a-c2ed-a219-4ae3efe4e0a8.png)

|エラー時の状況|説明||
|----|----|----|
|teratermで作りなおした「id_rsa」を秘密鍵に指定したして接続テストを実行|SSH接続時の鍵を使用すること||

##MySQL ユーザーの作成方法
```
CREATE USER 'sample_user'@'localhost' IDENTIFIED BY 'sample_password';
GRANT ALL PRIVILEGES ON sample_db.* TO 'sample_user'@'localhost';
```
https://qiita.com/YuichiTanaka007/items/f31f94ace4bac0aaf990#mysql%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%A8%E8%A8%AD%E5%AE%9A

|ポイント|説明|
|----|----|----|
|CREATE USER '<b>sample_user</b>'@'<b>localhost</b>'|ユーザー名：「sample_user」<br>ホスト名：「localhost」||
|IDENTIFIED BY '<b>sample_password</b>'|ログイン時のパスワード：「sample_password」||
|GRANT ALL PRIVILEGES ON <b>sample_db</b>.* TO '<b>sample_user</b>'@'localhost';|権限の付与<br>例ではデータベースレベル(sample_dbに関する)権限を「sample_user@localhost」に対して付与している||
|<span>@</span>localhost|ホスト名||
DynamoDBをこうやって理解しよう

DynamnDBって、RDB長くやっている人ほど、なんか理解できない、話はわかるけど腑に落ちない存在だったりしませんか？

自分はこうやってDynamoを理解しました。正確にあっているかは自分でもわからないです。なかなか、説明を読んでも腑に落ちない人向けの記事なので、正確に理解している方は読む必要なしでしす。

さて、DynamoDBでググると、以下のようなイメージで書かれていることが多いと思います。

```
・DBにはカラムを定義する
・その中の特殊なカラムとしてパーティションキーとソートキーなるものが存在する。
・この二つを組み合わせてプライマリキーとする。パーティションキーだけでもプライマリーキーとして使用可能
・通常のSQLは使えない
・プライマリーキーでレコードを特定する
```

通常のRDBを長くやっていると、まずこの言葉遣いで混乱するし、全然イメージが沸かない。個人的にはプライマリキーという言葉は使わない方がいいとさえ思う。

自分が人にDynamoの説明をするときには、あえて以下のような説明を行います。

```
・DBと言いつつ、限りなくハードディスクのようなもの、Cドライブとか
・パーティションキーというのは、ディスク直下のフォルダだと思って
・ソートキーというのはその中に入っているファイル名
```
つまりDB内の１つのファイルを探すには、フォルダ名とファイル名の２つが決まればいい。逆に、この条件でしか調べられないからSQLは使用できない

まあ、誤解を覚悟の上で言えば、SQLは使えないけど、フォルダサーチはできて、かつ、その中のファイル一覧は持ってこれるという仕様なのです。（ソートも可能）

ソートキーがない場合は、パーティションキーだけでプライマリキーになるというのもこのあたりの仕様が理由です。


それと理解しておきたいのはDynamoに物理的なテーブル定義が存在しない点です。もちろんテーブル定義は作成できるけど、それはあくまで論理的なもので、こうやって使うぞ！と自主的に決めるテーブル定義となリます。

実際にAWSのDyanmoのコンソールを見れば、テーブル定義は作れないことがわかると思います。逆に好きなカラム名のデータを自由に入れることができる。

その中で唯一テーブル定義的な存在がパーティションキーとソートキー 




もう少し、パーティションキーの説明をします。

パーティションキーの値によって、格納される物理DBは異なります。

？？DBは１つじゃないの？？？

ここがDynamoDB理解の肝なのですが、使用されるレコードは１つの物理的なユニットに全部収められているのではなく、パーティションの値次第で物理的に別のDBに納められている模様

いや、実際にAMAZONの社内で調べたわけではないけど、そうゆう話が流布されてます。

つまり、パーティションによって、物理的には別DBに入っているということです。

パーティションキーA は　物理DB Xに入る
パーティションキーB は　物理DB Zに入る

みたいです（実際には物理DBというより物理ディスクといったほうがいいのかもしれないです。実際に見たことはないけど複数のマシンであるとは思う）

このようなDB分割方法を水平Shardと言うらしいです。データの中の特定のカラム（パーティションキー ）の値によって格納するDBを分散させようという考え方。

これによって大量のデータを分散処理することは可能になりますが、RDBの利点が失われます。SQLが使えないとかね。

なのでShard万能ではなくて、むしろ使える局面が限られます。

おそらくDynamoDB使って会計システム作る人はいないです。


ざっくり理解するための記事ですので、この辺りで終わりにしますが、詳細はこのあたりとか読んでみると良いかもしれません。
https://www.alexdebrie.com/posts/dynamodb-partitions/
簡潔にMVCモデルまとめてみた

###MVCモデルとは？
①Model
②View
③Controller
これらの頭文字を取ってMVCモデルと呼んでいます。

###図解
ここにルーティングと呼ばれる機能も含め解説を行っていきます。
※イメージです。
![My First Board.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188773/6ec13860-1a41-3413-a5ec-7c2209f20bb4.jpeg)


サイトを閲覧するにはルートを経由し、そのサイトにアクセスする必要があります。
ルートからアクセスが来たら、
コントローラーがモデルにデータを取ってくるよう指示を出します。
取得してきたデータをコントローラーがビューに渡す事で、
私たちが普段見ているサイトの表示がされるという流れです。

###ルーティング
あるアドレスにアクセスした際、何の処理を呼び出し実行するのかを決める役割があります。
routesフォルダの中のweb.phpにコードを記載していきます。

###モデル
データ操作機能の役割があります。
データベースから取得したデータをSQLを書かなくても表示させる事ができます。
・Artisanコマンドの『php artisan make:モデル名』で作成可能です。モデル名はテーブル名の単数形する必要があります。
例）
 articles 　　　=>　 Article
(テーブル名)　　　(モデル名)


###ビュー
画面表示を担当する役割があります。bladeと呼ばれるテンプレートエンジンが用いられています。
HTMLの記述、PHPのソースコードをそのままテンプレートとして使う事ができます。



###コントローラー
どのような処理を行うのかを制御する役割があります。必要があればモデルからデータを取得し、それをビューに渡して表示をさせる事ができます。
・Artisanコマンドの『php artisan make:controller コントローラー名』で指定したコントローラーの作成が出来ます。
HomebrewでPyenvを入れているとbrew doctorでWarningが出る

# HomebrewでPyenvを入れていると．．．

ターミナルで`brew doctor`と打つと

```
$ brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: "config" scripts exist outside your system or Homebrew directories.
`./configure` scripts often look for *-config scripts to determine if
software packages are installed, and which additional flags to use when
compiling and linking.

Having additional scripts in your path can confuse software installed via
Homebrew if the config script overrides a system or Homebrew-provided
script of the same name. We found the following "config" scripts:
  /Users/username/.pyenv/shims/python2-config
  /Users/username/.pyenv/shims/python3.7-config
  /Users/username/.pyenv/shims/python2.7-config
  /Users/username/.pyenv/shims/python3.10-config
  /Users/username/.pyenv/shims/python3.7m-config
  /Users/username/.pyenv/shims/python-config
  /Users/username/.pyenv/shims/python3-config
```

というようなエラーが出る．これが邪魔なので自分の使っているシェルに応じて，`.bashrc`か`.zshrc`に以下を記載する．

```zsh
alias brew='env PATH="${PATH//$(pyenv root)\/shims:/}" brew'
```

するとスッキリ．

```
$ brew doctor
Your system is ready to brew.
```

# 参考
https://github.com/pyenv/pyenv#prerequisites
iPhoneでおもちゃのDeveloperツール作成

# iPhoneでDeveloperツールが使いたかった
ChromeやEdgeにあるF12で出るやつです。
あれがiPhoneで使いたかった。

調べたのですが、Macと繋げばできるよみたいな情報はあるものの、
Mac持っていないのだよなあ。

# ショートカットアプリ
最近はまっているiPhoneのショートカットアプリで何やらできそうな気がしてくる

# おもちゃのDeveloperツール作成
![IMG_9852.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246479/75952c32-3f5e-20eb-ad3e-ebe6c5ac3d06.jpeg)
![IMG_9853.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246479/071234c1-ee45-9551-9860-47b7c69cbe84.jpeg)
![IMG_9854.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246479/d1160c51-2168-3f4c-8c00-fb5a244e8293.jpeg)

# 結果
htmlの中身を取得することができました。
![IMG_9856.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246479/7ef35082-c195-1b23-b383-3ea2ae1e131f.jpeg)
![IMG_9858.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246479/2951571d-3271-021a-ee79-56c625d781fd.jpeg)


# 参考にさせていただいた記事

https://qiita.com/sentencebird/items/e537ad94bdd0f697f432
LocomotiveScroll と ScrollTriggerを連携させる

LocomotiveScroll と GSAPのScrollTriggerを連携させたときのメモです。

GSAPの公式がCodepenに[サンプル](https://codepen.io/GreenSock/pen/ExPdqKy)をあげてくれていますので、完成形やより詳細を知りたい方はこちらを参考にしてください。
ポイントとなる部分のコードをみていきます。

```jsx
gsap.registerPlugin(ScrollTrigger);

const locoScroll = new LocomotiveScroll({
	el: document.querySelector(".smooth-scroll"),
	smooth: true
});
locoScroll.on("scroll", ScrollTrigger.update);

ScrollTrigger.scrollerProxy(".smooth-scroll", {
	scrollTop(value) {
		return arguments.length ? locoScroll.scrollTo(value, 0, 0) : locoScroll.scroll.instance.scroll.y;
	},
	getBoundingClientRect() {
		return {top: 0, left: 0, width: window.innerWidth, height: window.innerHeight};
	},
	pinType: document.querySelector(".smooth-scroll").style.transform ? "transform" : "fixed"
});

ScrollTrigger.addEventListener("refresh", () => locoScroll.update());
ScrollTrigger.refresh();
```

まずは、GSAPでScrollTriggerを扱えるようにpluginを登録します。

```jsx
gsap.registerPlugin(ScrollTrigger);
```

次にLocomotiveScrollの初期化をおこないます。
今回はSmoothScrollの機能を使用したいので `smooth: true`を設定します。
`el`にはSmoothScrollをonにしたい部分を指定します。

```jsx
const locoScroll = new LocomotiveScroll({
	el: document.querySelector(".smooth-scroll"),
	smooth: true
});
```

LocomotiveScroll内でscrollイベントが走る度に、ScrollTriggerも更新します。

```jsx
locoScroll.on("scroll", ScrollTrigger.update);
```

SmoothScrollがonになるとLocomotiveScrollがスクロールを制御するようになるため、elで指定した部分で色々な高さの調整が行われますので、ScrollTriggerでもそのproxyを使用するようにします。
（この部分はGreenSock公式が公開してくれているcodepenの[サンプル](https://codepen.io/GreenSock/pen/ExPdqKy?editors=0010)により詳しい解説が書いてくれています...）
LocomotiveScrollを初期化した際のDOM要素と同じものを指定します。

```jsx
ScrollTrigger.scrollerProxy(".smooth-scroll", {
	scrollTop(value) {
		return arguments.length ? locoScroll.scrollTo(value, 0, 0) : locoScroll.scroll.instance.scroll.y;
	},
	getBoundingClientRect() {
		return {top: 0, left: 0, width: window.innerWidth, height: window.innerHeight};
	},
	pinType: document.querySelector(".smooth-scroll").style.transform ? "transform" : "fixed"
});
```

そしてwindowが更新される度にScrollTrigger、LocomotiveScrollの両方を更新するようにします。
全ての更新が終わりLocomotiveScrollで高さの調整が終わった後、最後にScrollTriggerをrefreshします。

```jsx
ScrollTrigger.addEventListener("refresh", () => locoScroll.update());
ScrollTrigger.refresh();
```
urlparseのnetlocはホスト名じゃない

# URLからホスト名を取得したい
調べたらurllib.parse.urlparseが使えるとのこと

```python
from urllib.parse import urlparse

r = urlparse("https://www.example.com/hogehoge.html")

print(r.netloc) # >>> www.example.com
```

urlparseにURLを入れてそれのnetloc属性がホスト名を持つらしい
普通に使う分にはこれで事足りました

# しかし、とある要素が入ると動かなくなる

何故かこの場合の動作がおかしくなります

```python
from urllib.parse import urlparse

r = urlparse("https://localhost:8000")

print(r.netloc) # >>> localhost:8000
```

### いや、お前(ポート番号)何でついて来るんだ

何でなんでしょう

とりあえずこう書いてみた

```python
from urllib.parse import urlparse

r = urlparse("https://localhost:8000")

print(r.netloc.split(":", 1)[0]) # >>> localhost
```

はい、わざわざ:で分割してるあたり気持ち悪いですね

# 解決策
urlparseのドキュメントに凸ったら「hostname」といういかにもそれらしき属性を発見しました

```python
from urllib.parse import urlparse

r1 = urlparse("https://www.example.com/hogehoge.html")

print(r1.hostname) # >>> www.example.com

r2 = urlparse("https://localhost:8000")

print(r2.hostname) # >>> localhost
```

勝ちましたね

それにしてもnetlocって何の意味があるんでしょうね
調べるとurlparseのnetloc属性=ホスト名だといった記事がたくさんヒットするんですが……

謎だ……
【備忘】GKEからコンテナに対して環境変数を渡す

# GKEからコンテナに対して環境変数を渡す
## やりたいこと
Javaで下記のような設定ファイルを用意したとする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727502/062d7cf8-971a-7a1f-0297-3b3116f6f2d3.png)

application.ymlでlocal用の設定とstg用の設定を使い分けるようにしたい場合がある。

application.yml

```yaml
spring:
  profiles:
    active: ${APPLICATION_ENV:local}
```
${APPLICATION_ENV:local}で環境変数「APPLICATION_ENV」に値がない場合、デフォルトではlocalの設定を使用する(application-local.ymlを読み込む)。
GKE上でアプリを動作させる場合、「APPLICATION_ENV」にstgを設定してapplication-stg.ymlを読み込みたい。


## ConfigMapを作成する
### ConfigMapとは
ConfigMapとはデータをキーバリュー形式で保存できる機能。コンテナから設定(環境変数とか)としてConfigMapを参照できる。

### ConfigMapを作成する
作り方として色々あるが、私は次のやり方で作成した。

Cloud Shellを起動して下記ファイルを作成する。

```
hoge@cloudshell:~$ vi config.yml
```

config.yml(ConfigMapの元)

```yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  APPLICATION_ENV: stg
```

ConfigMap作成

```
hoge@cloudshell:~$ kubectl apply -f config.yml
```

GCP上のKubernetes Engine >> ConfigMapとSecretに対象のConfigMapが作成されていることを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727502/348d0151-bb45-f91c-0425-3d6713a0ca10.png)

## ワークロードでConfigMapを読み込むようにする
### デプロイメントを編集してワークロードを更新する。
Kubernetes Engine >> ワークロード >> 対象のワークロードを選択 >> YAMLタブをクリック
編集モードでデプロイメントのyamlに - env以下を設定して保存する

```yaml
    spec:
      containers:
      - env:
        - name: APPLICATION_ENV
          valueFrom:
            configMapKeyRef:
              key: APPLICATION_ENV
              name: env-config

```

以上で環境変数をコンテナが読み込める。
pixi.jsのSpriteを星型にトリミング(マスク)する

# はじめに

pixi.jsで作成したGraphicsやSpriteをトリミングするためには、[マスク処理](https://pixijs.download/dev/docs/PIXI.Container.html#mask)が必要になります。今回は画面全体に表示した芝生を星型にトリミングしてみようと思います。

![FireShot_Capture_005_-_Vite_App_-_localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349238/d911fe76-00f9-b043-b74c-873e0249575b.png)


# ApplicationにSpriteを追加

まずは、画面全体に芝生を表示します。Spriteを上下左右、指定した幅まで繰り返し表示したいので、今回は[PIXI.Sprite](https://pixijs.download/dev/docs/PIXI.Sprite.html)ではなく、[PIXI.TilingSprite](https://pixijs.download/dev/docs/PIXI.TilingSprite.html)を使用しています。第二、三引数に横幅と縦幅を指定してあげることで、その幅まで画像が繰り返し表示されます。

```jsx
import * as PIXI from 'pixi.js';

const app = new PIXI.Application({
  width: window.innerWidth,
  height: window.innerHeight,
  backgroundColor: 0x1099bb,
});

const texture = PIXI.Texture.from(
  'https://pixijs.io/examples/examples/assets/bg_grass.jpg'
);
const tilingSprite = new PIXI.TilingSprite(
  texture,
  window.innerWidth,
  window.innerHeight
);
app.stage.addChild(tilingSprite);

document.body.appendChild(app.view);
```

![FireShot_Capture_004_-_Vite_App_-_localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349238/66f0b4b6-f65c-45f3-3374-1d97ed7f8a4f.png)


# 星型にトリミングする

次に、トリミングするために星型をGraphicsで作成します。

```jsx
const starMask = new PIXI.Graphics();
starMask
  .beginFill()
  .moveTo(108, 10)
  .lineTo(141, 80)
  .lineTo(218, 88.3)
  .lineTo(162, 141)
  .lineTo(175, 215)
  .lineTo(108, 180)
  .lineTo(41.2, 215)
  .lineTo(55, 141)
  .lineTo(1, 88)
  .lineTo(75, 78)
  .lineTo(108, 10)
  .endFill();
```

このGraphicsをtilingSpriteのmaskプロパティに代入してあげれば、トリミング完了です。

```jsx
tilingSprite.mask = starMask;
```

![FireShot_Capture_005_-_Vite_App_-_localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349238/4c4c38e1-3e3b-f3be-4f9c-5416aa769ef7.png)
Docker+GPU環境でESPnet2を使用する

ESPnetを動かすための環境設定にはいくつか方法がありますが、ここではDocker環境でGPUを利用しつつ、ESPnetを動作させるための方法について説明します。以下、ESPnetと書いていますがESPnet2を使っています。
https://github.com/espnet/espnet

#Docker環境を作る
まずNvidia GPUが使用できるDocker環境を作ります。ここで重要なのは使用するdockerイメージのバージョンです。ESPnetが対応しているcudaのバージョンのdockerイメージを使う必要があります。またcudaのバージョンはできるだけ新しいほうがよいです。たとえばRTX3000系のGPUを使うためにはcuda11以降を使う必要があります。

```
FROM nvidia/cuda:11.3.1-devel-ubuntu20.04
```

使用できるNvidiaのdockerイメージのリストはこちらのサイトで確認できます。baseと書いてあるイメージではなくdevelと入っているものを使用しましょう。baseのほうでは/usr/local/cuda-XX/binが存在しないのでESPnetのインストール時にエラーになります。
https://hub.docker.com/r/nvidia/cuda

Pytorchのバージョンも同様に合わせる必要があります。こちらはESPnetのgithubのページの表を参照してください。私の環境では1.10.1を使っています。

# Dockerを起動してESPnetをインストールする
次にdockerを起動して、その環境の中でESPnetのインストールを行います。ESPnetが対応しているcudaの正確なバージョンはこのタイミングで確認できます。対応していないバージョンの場合はエラーメッセージが出て、インストールが停止します。

```
cd espnet/tools
make
```

cudaのバージョンでエラーになった場合は、自分の意図したcudaのバージョンが入っているか確認しましょう。cuda11.3の場合は、docker環境の中に/usr/local/cuda-11.3/binが存在するか確認しましょう。nvcc --versionでも確認できます。いずれも「docker環境の中」で確認してください。

espnet/toolsでのmakeの実行結果がおかしくなったらmake cleanしてからmakeしましょう。

#動作確認
docker環境に入って、ESPnet2の適当なフォルダでrun.shを動かして動作確認を行います。cudaまわりの設定が正しくできていれば正常終了します。設定がおかしい場合は学習のところで止まるはずです。

```
cd espnet/egs2/an4/asr1
./run.sh
```
DeepL APIで複数のテキストを一度に翻訳

DeepL API：https://www.deepl.com/ja/docs-api/translating-text/
Python Requestsライブラリ：https://note.nkmk.me/python-requests-usage/

DeepL APIは、パラメータ`text`を1回のリクエストで複数個設定することが可能である。
GETメソッドで言えば、以下のような形式のURLが可能である。

```
https://api-free.deepl.com/v2/translate?auth_key={...}&text={１つ目のテキスト}&text={２つ目のテキスト}&text={３つ目のテキスト}&target_lang={...}
```

HTTPリクエストにPythonのRequestsライブラリを使用している場合、複数のテキストを一度に翻訳するには、パラメータ`text`をリストにすればよい（リストの最大要素数は50）。

```sample.py
import requests

API_KEY = '__YOUR_API_KEY__'
TEXT = 'Dragon Quest #3 is my favorite game.'
TEXT2 = 'Dragon Quest #5 is also my favorite game.'
URL = "https://api-free.deepl.com/v2/translate"  # Free版の場合
# URL = "https://api.deepl.com/v2/translate"  # 有料版の場合
params = {
            "auth_key": API_KEY,
            "text": [TEXT,TEXT2],
            "target_lang": 'JA'
        }

request = requests.post(URL, data=params)
result = request.json()
print(result["translations"][0]["text"])
print(result["translations"][1]["text"])
```

実行結果は以下の通り。

```
ドラゴンクエスト＃3は私のお気に入りのゲームです。
ドラゴンクエスト＃5も大好きなゲームです。
```

もちろん、複数の文を空白や改行記号で結合すれば、一度に複数の文の翻訳を得ることができる。ただし、パラグラフごとのデータがあって、結合せずに翻訳結果を得たい場合などには、`text`をリストにするやり方が都合がよい。
Homebrewでインストールされたnvmのデフォルトプレフィクスがホームディレクトリ以下に変更になりました

## TL;DR

Homebrewでnvmをインストールしている人限定の話です。
`NVM_DIR`をrcファイルに記載していない人の環境は一旦ぶっ壊れます。（nvmのアップデートで毎回ぶっ壊れていたので問題ないでしょう）
これからは、`NVM_DIR`を.bashrcなり.zshrcに指定しなくても、nvm関連のファイルは自動的に`~/.nvm`以下にインストールされるようになります。
つまり、以下をrcファイルに指定するだけで正しい動作をするようになったんです！

```sh:Intel
[ -s "/usr/local/opt/nvm/nvm.sh" ] && \. "/usr/local/opt/nvm/nvm.sh"  # This loads nvm
```

```sh:M1
[ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh"  # This loads nvm
```

## プルリク

去年の8月から作業してました。

https://github.com/Homebrew/homebrew-core/pull/86782

## 説明

Arch LinuxのAURと同じことをするようにしただけです。

```sh:nvm.sh
# $NVM_DIR should be "$HOME/.nvm" by default to avoid user-installed nodes destroyed every update
[ -z "$NVM_DIR" ] && export NVM_DIR="$HOME/.nvm"
\. /usr/local/Cellar/nvm/0.39.1_1/libexec/nvm.sh
# "nvm exec" and certain 3rd party scripts expect "nvm.sh" and "nvm-exec" to exist under $NVM_DIR
[ -e "$NVM_DIR" ] || mkdir -p "$NVM_DIR"
[ -e "$NVM_DIR/nvm.sh" ] || ln -s /usr/local/opt/nvm/libexec/nvm.sh "$NVM_DIR/nvm.sh"
[ -e "$NVM_DIR/nvm-exec" ] || ln -s /usr/local/opt/nvm/libexec/nvm-exec "$NVM_DIR/nvm-exec"
```

まず、`NVM_DIR`が設定されていなければ`~/.nvm`に設定します。これがHomebrewでのデフォルト値になります。
次に本物のnvm.shを読み込みます。
最後に`NVM_DIR`が存在しなければディレクトリを作成し、それ以下にnvm.shとnvm-execが存在しない場合はそれぞれの本物にシンボリックリンクを貼ります。いくつかのnvmのプラグインが`NVM_DIR`以下にこの2つのスクリプトが存在していることを前提とした動作をするらしいのでこのようなコードが追加されています。

## なぜこのような実装が必要になったか

nvmは`NVM_DIR`が設定されていない場合、nvm.shの実体がある場所をデフォルトの`NVM_DIR`として設定します。
Homebrewの場合、`/usr/local/opt/nvm/libexec`のようなパスに設定されるのですが、このoptディレクトリというのがクセ者で、nvmが更新される度に全消しされます。
実体は`/usr/local/Cellar/nvm/0.39.1_1`のような位置にあり、更新のたびに全消しされるのはHomebrewの仕様上仕方ないことです。
どうもnvmの作者であるljharbはこの問題が発生するたびにnvmにIssueが立つのにキレたらしく、Homebrew経由でnvmをインストールすると以下の警告文が表示されます。

> Please note that upstream has asked us to make explicit managing
> nvm via Homebrew is unsupported by them and you should check any
> problems against the standard nvm install method prior to reporting.

ljharbの主張は、「ユーザーがインストールしたnodeは神聖な物であり、何人たりともそれを破壊することは許されない」だそうです。（どこで主張していたかは忘れました）

## 結論

今回の変更で、Homebrewはnvmがインストールしたユーザーのnodeにデフォルトで触らなくなったので、早くHomebrew経由のインストールがnvm公式が推奨するインストール方法の一つとして認められるといいなと願っております。
mktexlsr を sudo で実行すると別の ls-R を更新してしまう

### sudo mktexlsr すると別の ls-R を更新してしまう
texlive 2021 でスタイルファイルを追加したので更新しようと `mktexlsr` を実行したところ, `directory not writable. `と言われてしまいました. 
そこで, `sudo` をつけてやると, 私の環境では別の `mktexlsr` が実行されてしまいます. 

``` terminal
[user@localhost ~]$ mktexlsr 
mktexlsr: /usr/local/texlive/2021/texmf-config: directory not writable. Skipping... 
mktexlsr: /usr/local/texlive/2021/texmf-dist: directory not writable. Skipping... 
mktexlsr: /usr/local/texlive/2021/texmf-var: directory not writable. Skipping... 
mktexlsr: /usr/local/texlive/texmf-local: directory not writable. Skipping... 
mktexlsr: Done.  

[user@localhost ~]$ sudo mktexlsr
[sudo] password for user: 
mktexlsr: Updating /usr/share/texlive/texmf-config/ls-R... 
mktexlsr: Updating /usr/share/texlive/texmf-dist/ls-R... 
mktexlsr: Updating /usr/share/texlive/texmf-local///ls-R... 
mktexlsr: Updating /usr/share/texlive/texmf-var/ls-R... 
mktexlsr: Done.
```

よく見ると, `sudo mktexlsr` は /usr/local/texlive/2021/~ じゃなくて, /usr/share/texlive/~ の方の mktexlsr を実行しているやん、、、。

### /usr/local/texlive/2021/~ 下の mktexlsr を実行する
`/usr/local/texlive/2021/~` 下の `mktexlsr` を実行するには, 多分次のどちらかをします。

- 書き込み権限が無いと怒られたディレクトリ全部に書き込み権限を付与する
- `which mktexlsr` で実行ファイルの Path を取得して, sudo で実行. 

今回は後者にしました. 

```terminal
[user@localhost ~]$ which mktexlsr
/usr/local/texlive/2021/bin/x86_64-linux/mktexlsr
[user@localhost ~]$ sudo /usr/local/texlive/2021/bin/x86_64-linux/mktexlsr
[sudo] password for user: 
mktexlsr: Updating /usr/local/texlive/2021/texmf-config/ls-R... 
mktexlsr: Updating /usr/local/texlive/2021/texmf-dist/ls-R... 
mktexlsr: Updating /usr/local/texlive/2021/texmf-var/ls-R... 
mktexlsr: Updating /usr/local/texlive/texmf-local/ls-R... 
mktexlsr: Done.
```

無事, `ls-R` の更新ができました. 

### そもそもなぜ texlive が2つあるの？
うーん、dnf でインストールしたからなのかな、、、。package 管理システムは使うなと有識者に怒られそう。。。

```terminal
/usr/local/texlive/2021/~   # 一般ユーザで実行したときのやつ
/usr/share/texlive/~        # sudo で実行したときのやつ
```

:::note info 
教えて偉い人！
:::

（追記）本当に偉い人に御教示いただきました。
`/usr/share/texlive/~` は パッケージ管理システム (dnf) でインストールした方だったとのこと. 詳しくは：
https://okumuralab.org/tex/mod/forum/discuss.php?d=3300
「エクセルを起動する」に失敗する時の対処法

ブランクを挟みましたが、プロデルは福祉現場で変わらず重宝しています。そして、PC環境が充実した職場に移りましたが、ネ申Excelとの付き合いは相変わらず切れません。

このところ、作ったアプリで「エクセルを起動する」がエラーを吐いてしまい、その対応に苦慮しておりました。このようなメッセージです。

```
[エクセル]を起動
エラーが発生しました。
文法に間違えがないか、指定した値が正しいか、ご確認ください。

発生した例外:
型 'Microsoft.Office.Interop.Excel.ApplicationClass' の COM オブジェクトをインターフェイス型 'Microsoft.Office.Interop.Excel._Application' にキャストできません。IID '{000208D5-0000-0000-C000-000000000046}' が指定されたインターフェイスの COM コンポーネント上での QueryInterface 呼び出しのときに次のエラーが発生したため、この操作に失敗しました: インターフェイスが登録されていません (HRESULT からの例外:0x80040155)。

文法や使い方に誤りがない場合、不具合によって発生したエラーと思われます。申し訳ございません。

[エラー番号901] [はじめ:1行目]
プロデル 1.8.1094 (32)
```

バージョン違いのOfficeが入っている環境で発生するらしいというのは分かっていたのですが、意外に簡単に解決できることを知りました。
https://elleneast.com/?p=866
Windows10 + Office2021 + PowerPoint2016 + Access2010という環境で試してみたところ、Office2021からOfficeの修復をするだけであっけなく解決しました。
職場のPCはほとんどがこういうツギハギ環境なので、「例外監視」文でエラーを吐いたらOfficeの修復を促す旨表示するように修正しました。

今更ですがよかったよかった。
Notificationメモ

# トラブルシューティング
## `new Notification`は、WebWorkerで機能する
PC/Chromeでなぜか動いてしまうため、誤認しやすい。

| 環境| 稼働|
|:----|:-----|
|PC/Chrome| 実行できる。|
|Android/Chrome| 実行できない。|
|WebWorker|実行できる。|

### doc
https://developer.mozilla.org/ja/docs/Web/API/Notification/Notification

# Frontでの呼び出し方
```javascript
navigator.serviceWorker.ready.then(function (registration) {
  return registration.showNotification("Title", {
    body: "body"
  })
}).catch(e => {
  // error処理
})

```

# Service Workerからの呼び出し方
```javascript
self.registration.showNotification(notificationTitle, notificationOptions)
```
【論文読み】Federated learning for predicting clinical outcomes in patients with COVID-19

## はじめに

こんにちは。論文を1人で読んだ結果の紹介記事です。  
今回紹介するのは、「Federated learning for predicting clinical outcomes in patients with COVID-19」という論文です。  

- タイトル：Federated learning for predicting clinical outcomes in patients with COVID-19
- 出典：Ittai Dayan, et al.; Nature Medicine, 2021  
- URL：https://www.nature.com/articles/s41591-021-01506-3.pdf  


## 概要
複数の医療機関でデータを共有せず連合学習を適用してCOVID-19患者の酸素必要量を予測した。
AUCは0.92を達成し、単一の医療機関で学習させるよりも16%も平均AUCを向上した。


## 技術的特徴
- 連合学習（Federated Learning, FL）の1つであるクライアント・サーバー方式では、未学習モデルを他のサーバー（ノード）に送り、ノードで学習が行われる。その結果を中央のサーバーで統合（連合）し、訓練を終了させるまで(モデルが収束するまで)反復する。クライアントとサーバーの間ではモデルの重みや勾配のみが伝達される。   
- 説明変数は20個の特徴量(胸部エックス線画像や血液検査の結果、酸素飽和度など)で、目的変数は救急診療部への入院から24時間後、72時間後の患者の酸素投与量（リスク）
- 目的変数は5種類の0から1の値をとる。分類ではなく回帰を行うので出力値は0~1。
- 画像データに対してはResNet34を使用して特徴抽出する。
- 重みの更新を25%しか共有しなくても連合学習モデルは同等の性能を発揮
- 2019年12月から2020年9月まで20機関から合計16,148件のデータが用意


## 想定される適用例
- データを共有できないシステム間でのモデルの統合  
- エッジとクラウドで構成されるIoTシステム全般


## 参考
- [連合学習でCOVID-19感染者の酸素投与量予測](https://ai-scholar.tech/articles/federate-learning/Federated_Learning_for_outcomes_in_COVID19)  
- [Federated learning for predicting clinical outcomes in patients with COVID-19](https://www.nature.com/articles/s41591-021-01506-3.pdf)
v-bindディレクティブ [属性へのバインド]　Vue備忘録#2

#バインド時の注意点

v-bindディレクティブを使って属性へのバインドをした時、
下記のように属性バインドしたタグ内のpタグは表示されない。

当然のことなのでしょうか？
何かわかったらまた追記予定。。。


```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Vue.js app</title>
    <link rel="stylesheet" href="main.css">
</head>
<body>
    <div id="app">
        <div v-bind:text-content.prop="message">
            <p>yeah</p> <!--今のところjsファイルのmessageプロパティが表示されていて、pタグ部分は表示されない-->
        </div>
        <div v-bind:scroll-top.prop="scroll"></div>
    </div>
    <pre>{{ $data }}</pre>  
    <script src="vue.js"></script>
    <script src="main.js"></script>
</body>
</html>
```

```JavaScript:main.js
var vm = new Vue({
    el: '#app',
    data: {
        message: 'hello vue.js!',
        scroll: 0
    },
    mounted: function() {
        this.scroll=100
    }
})
console.log('ok')
```
Laravelでポリモーフィックを使ってるにも関わらずnamespaceを変えてしまった時は

# 背景
ORMでポリモーフィックをいい感じにやってくれるなら使わない手はないということで安易に使った後で、リファクタリングの際に利用しているEloquentモデルのnamespaceを変えてしまった。

```
App\Models\Document => App\Models\Hoge\Document
```
こうしてしまうと、これまでフィールドに使っていた`App\Models\Document`が利用できなくなってしまう。

# 解決策
`Relation::morphMap`を利用する。
詳しくはこちらに書いてあるので公式を参照
https://readouble.com/laravel/6.x/ja/eloquent-relationships.html

簡単にいうと完全なクラス名で参照していたところを任意の名前に変更しかつ、その任意の名前からクラスを参照するようにバイバスできる。

```php
Relation::morphMap([
    'document' => 'App\Models\Hoge\Document'
]);
```

ただこれを使う場合には、該当のフィールドを全部カスタム名に変更する必要が出てしまうため注意。
＊6系はデフォのクラス名のケースとカスタム名のケースの両立ができない模様

それでも使う場合には、serviceproviderを新規に作成するかAppServiceProviderの中で定義してあげれば良い。


# そもそも論
リファクタリングをきっかけに気づいたけれど、使うならアプリケーションサイドの変更がDBサイドに影響しないように最初からカスタム名を使うべきだった。

またDBでイイ感じに紐付けて引っ張ってこれる点に魅力を感じたものの、そもそもその責務はサービスレイヤーとかに任せる方が保守・拡張性の高いシステムになる気がした。
シフト JIS コードは 0x2000 / 0xA000 と XOR して扱う

[SHIFT JIS の領域](https://qiita.com/ikiuo/items/9e2f8f955d92f5a8d4a2) (CP932) の上位4ビットを見ると

| 上位4ビット | 8 | 9 | A | B | C | D | E | F |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| S-JIS | ● | ● | | | | | ● | ● |

8,9,E,F が対象で領域が分離されています。

しかし、XOR（2 または A）すると、(8,9)と(A,B) および (C,D)と(E,F) が交換されて

| S-JIS | | | ● | ● | ● | ● | | |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| XOR 2 | A → 8 | B → 9 | **8 → A** | **9 → B** | **E → C** | **F → D** | C → E | D → F |
| XOR A | A → 0 | B → 1 | **8 → 2** | **9 → 3** | **E → 4** | **F → 5** | C → 6 | D → 7 |

シフトJIS の範囲を連続的（A-D または 2-5）に扱えます。

```C:最初の1バイトがS-JISか？

int is_sjis(int first_byte)
{
  return ((unsigned)((first_byte ^ 0xa0) - 0x21) < 0x3c); /* CP932の範囲 */
}

```
railsのwrap_paramerterがやっている事と設定の方法について

# wrap_paramerterとは

コントローラーの名前からリソースの名前を推測してリクエストパラメータをリソースの名前でラップする仕組みの設定を行います。

https://railsguides.jp/action_controller_overview.html#json%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF

rails6.1までのrailsアプリケーションでは`rails new`した際に`config/initializers/wrap_parameters.rb`というファイルが作成されます。

```ruby:config/initializers/wrap_parameters.rb
# Be sure to restart your server when you modify this file.

# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.

# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: [:json]
end

# To enable root element in JSON for ActiveRecord objects.
# ActiveSupport.on_load(:active_record) do
#   self.include_root_in_json = true
# end
```

# やっている事

コントローラー名からモデル名を推測し、元のパラメーターをストロングパラメーターに対応させるようにモデル名でラップして新しいパラメーターを作ります。

```ruby
'モデル名': {attributes}
```

例えば、コントローラーがUsersControllerの場合railsはコントローラーの名前からUserモデルがあると推測し、Userモデルのattributeを取得しattributesと同じ名前(=`attribute_names`)のパラメータキーが渡ってきた場合にラップの対象にします。

```ruby
user: { name:, email: }
```

# 設定方法

ラップパラメーターを使うかどうかは前述の`config/initialisers/wrap_paramerter.rb`で可能です。デフォルトではリクエストのcontent_typeがjson場合はリクエストパラメーターをラップさせる様に設定されます。

```ruby
ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: [:json]
end
```

または、コントローラー単位で個別で指定することも可能です。

```ruby
class UsersController < ApplicationController
  wrap_parameters format: [:json, :xml, :url_encoded_form, :multipart_form]
end
```
Yew（Rust＋WASM）でぷよぷよを作ってみてわかったゆるふわRust初学者が理解しておくべき３つのこと

[Monacaさんで提供されている写経用のぷよぷよjsコード](https://puyo.sega.jp/program_2020/)を参考にしつつ、Yewというフレームワークを使ってRust+WASMでぷよぷよライクなアプリを作ってみたのですが、その結果得たRust初学者としての感想をまとめてみました。

![rusrus_sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210824/210cf3d8-1fb6-40ab-6205-e36a54979670.gif)


ソースコードは以下で公開しています。

https://github.com/robitan/rusrus

主に勉強を目的として作成したためアプリとしての完成度は低いですが、似たような環境を学習したい方はご参考にどうぞ。


# その１、所有権は怖くない（でも絶対に理解しておくこと）

Rustについて調べると「他の言語にはない"所有権"という概念がある」ということが必ず書かれています。

大半の言語はライブラリの参照方法と変数定義・関数定義・制御文の書き方さえ理解していれば（というか調べられれば）とりあえず動くものは作れます。今回もエラーが出たら調べよう、という軽い気持ちで作り始めたのですが、結局作り上げるまでの時間の半分以上は所有権について理解していなかったことに起因して浪費しました。いっぽう所有権について理解してからはあっという間に開発が進みました。

所有権およびそれに伴う借用・参照という概念は、本当にRust特有のもので、それを理解していないとどんなにわかりやすいエラーメッセージが出ていてもその意味を理解できません。他言語にどんなに慣れていても、どんなに面倒くさがりの人でも、そこについてだけは[Rustの公式サイトのページ内容](https://doc.rust-jp.rs/book-ja/ch04-00-understanding-ownership.html)をきちんと理解してから進めることをお勧めします。

なお、所有権について理解して以降は、他の言語に所有権という概念がないことをむしろ面倒に感じるようになり、Rustが開発者の間で人気がある理由について非常に納得いくようになりました。所有権という単純なルールで管理されてさえいれば、メモリ管理で問題が発生した際にも言語ごとのガベージコレクションの仕様を調べなおす必要がなく、自分のコードを見直すだけでことがすみます。むしろ見直す必要がないくらい、はじめに書くときに意識させてもらえます。素晴らしすぎませんか？


# その２、検索で見つかる情報が自分の環境にはあてはまるとは限らない

今回はそもそもRustをやりたかったわけではなくWebAssemblyでなにか作ってみるにあたりRust+WebAssemblyという環境を選択したのですが、Rust自体はOSカーネルの開発などでも使われている言語です。そのため、Rustというキーワードでひっかけた場合、必ずしも自分の環境に当てはまる情報とは限りません。

また、開発者に人気のHotな言語ということもあり、関連のライブラリにも日々更新がかかっています。今回使用したYewというフレームワークも、着手当時リリースされたばかりのバージョン0.18を採用したにもかかわらず、そこから一ヶ月も経たずバージョン0.19がリリースされ、さらに後継バージョンも開発が進んでいます。そして、その時に最良と思われた内容を大胆に採用しているというか、つまり後方互換はあまり意識されていませんし、リリースが早いだけにバージョンごとの情報もあまり出回っていません。

他のライブラリなどについても類似のケースがままあり、少し前のバージョンと現行バージョンではかなり仕様が違う、という場合も少なくありませんでした。個人の善意であげられている記事などでは内容の対応バージョンについて明記されていないことも多く、ある問題を解決するにあたり参考にした記事のライブラリのインストールまではできたものの結局自分の環境ではうまく動かなかった、という場合も多かったです。

結局は、個人の記事は参考程度にしつつ、基本は公式が提供している自分の環境にあった情報を読み解きながら自分で少しずつ試しながら進めるほうが早かったです。

もちろんそうではない場合もありましたし、同じような状況は他言語においても発生します。ただ、いつも慣れ親しんでいる言語に比べて現状はそういう状況に行き当たりやすい、ということは意識しておいたほうが、時間を無駄にしないかもしれません。


# その３、それらを押さえていれば意外と簡単

ここまででRustが難しそうに思われる話を書きましたが、逆に言えば、それさえわかっていれば学習前の印象よりもむしろとっつきやすく感じました。

サンプルコードを見ていただければわかるようにRustの機能のすべてを活用しきれているとは言えませんが、他言語と同様にゆるふわく、最適な書き方ではないにせよとりあえず動く、というものはいくらでも作れます。

また、少なくとも今回使ったYewの環境ではコンパイラがエラー発生時についでに直し方を提案してくれる場合もあり、Rustという言語それ自体は言われているほどとっつきづらいものではないように感じました。

とはいえ、変数ってなんですか？　というところから始めるのであればさすがにあまりお勧めしません。

変数の値渡しと参照渡しについては理解しているという程度であれば問題なく、それについて自分が選択したやりかたが正しかったのかいつも悩んでいる、という人にはむしろ福音をもたらす言語ではないかと思います。




以上３点、なにかの参考になりましたら幸いです。
Githubリポジトリ分割したときのメモ

# 概要

旧リポジトリにはアプリ以外の情報が色々と入っていたので、それらと分離して管理するためにアプリ単体でリポジトリ分割を実施した。
既存のリポジトリから新しくリポジトリを初めて作成したのでメモとして手順を残しておく

# 注意
調べて一般的な方法でうまく行かなかった部分があり、我流の部分あり。

# 環境、前提等
ローカルはWindows環境。

# 手順
１．GitHubでリポジトリ新規作成
２．移行元リポジトリのリモートとローカルの状態を合わせておく
３．ローカルのファイルシステムを移行元リポジトリの対象としたいブランチに切り替え(cd <移行元リポジトリ>→git checkout <ブランチ名>)
４．エクスプローラーを開く。対象ブランチの内容になっていることを確認
５．移し替えたいフォルダをエクスプローラーからローカルの任意の場所にコピーペースト
６．フォルダを移し替えただけなのでgitコマンドは使えない。試しにターミナルから移行先フォルダに移動してgit branchと打ってみるとfatal: not a git repository (or any of the parent directories): .gitといわれる
７．移行先フォルダでgit init、git config設定、.gitignore作成を行う
８．git remoteでリモート追跡ブランチ追加を行う(git remote add origin git@github.com:hoge/fuga.git→git remote -vで確認)
※git@github.com:hoge/fuga.gitは、リモートの移行先リポジトリパス
９．移行先フォルダの全ファイルを対象にgit add .→git commit
１０．git pushと打つとアップストリームの設定をしろと言われるので、エラーメッセージに従って実施(git push --set-upstream origin master)
１１．GitHub側でもリポジトリの変更が反映されていることを確認
DjangoでOCI Autonomous Databaseに接続するには (自分用備忘録)

# Windows 10 
[参考](http://everything-you-do-is-practice.blogspot.com/2017/11/oracle-instant-client-windows.html)

[ここ](http://www.oracle.com/technetwork/topics/winx64soft-089540.html)からWindows 64 ビット版のOracle Instant Clientをダウンロードする。

ダウンロードするのはinstantclient-basic-windows.x64-WW.X.Y.Z.T.zipである。
展開すると、instantclient_WW_Xというフォルダになる。

instantclient_WW_X内で、

```sh
$ odbc_install JA
```
で実行するとODBC ドライバがインストールされる。
次に、環境変数にこのフォルダを追加する。

```sh
$ set PATH=%PATH%;C:\instantclient_WW_X
$ set ORACLE_HOME=C:\instantclient_WW_X
```
`%ORACLE_HOME%`はDjangoなどが参照するフォルダである。

その後は、`instantclient_WW_X\network\admin\`以下にウォレットを追加する。[参照](https://qiita.com/kira_puka/items/aea2435d32624566417d)

最後にDjangoのsetting.pyに

```py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': 'TNS名',
        'USER': 'ADMIN',
        'PASSWORD': 'password',
    }
}
```
とすればよい。


# Linux版
[参考](https://symfoware.blog.fc2.com/blog-entry-2378.html)

まず、cx_Oracleをインストール。

```sh
$ pip install cx_Oracle
```
次にOCIライブラリをインストールする。
[ここ](https://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html)からLinux x86-64版のOracle Instant Clientをダウンロードする。

```shell
$ sudo mkdir -p /opt/oracle
$ sudo mv instantclient-basic-linux.x64-WW.X.Y.Z.Tdbru.zip /opt/oracle
$ cd /opt/oracle
$ sudo unzip instantclient-basic-linux.x64-WW.X.Y.Z.Tdbru.zip
```
libaioもインストール。

```sh
$ sudo apt install libaio1
```

展開したライブラリのパスを/etc/ld.so.conf.d/に追加

```sh
$ sudo sh -c "echo /opt/oracle/instantclient_WW_X > /etc/ld.so.conf.d/oracle-instantclient.conf"
$ sudo ldconfig
```
あとはWindows版と同様
TypeScript とは

## 勉強前イメージ

シェルスクリプトの一つ？

## 調査

### TypeScript とは

JavaScriptを拡張して作られたプログラミング言語で、
オープンソースになります。
TypeScriptのコードをコンパイルするとJavaScriptのコードに変換されるので
JavaScriptが実行される環境ならすぐに使えます。
2017年にGoogleが社内の開発言語として採用されており
今後も需要がある言語になります。

### TypeScriptの特徴

- 型の宣言ができる

型を宣言できるので、実行時にしかわからないエラーを防げます。
また、型アノテーションを使って変数に型を付けられるので詳細に指定できます。

- クラスが作れる

クラスベースオブジェクト指向言語として作られているのでクラスを定義することができます。

### JavaScriptとの違い

- 型について

```
JavaScript → 動的型付け言語
TypeScript → 静的型付け言語
```

`動的型付け言語` は変数や関数のデータ型の宣言が必要なくプログラムが勝手に型を決めます。
他にもPythonやRubyも動的型付け言語になります。

`静的型付け言語` はデータ型を宣言してから開発を行います。
エラーやメモリの最適化などができます。
他にもC#やC++なども静的型付け言語になります。
このことから型が宣言できる特徴があります。
また、実行時にJavaScriptより動作が早いことが多いです。

- クラスについて

TypeScriptはクラスを作成できます。
複雑な開発の際はJavaScriptではコードが長くなってしまいますが、
TypeScriptではクラスが作れるためコードが短く読みやすくなります。

## 勉強後イメージ

最初のイメージとは全然違ったw
JavaScriptとの互換性があるのね、進化版的な感じ？

## 参考

- [需要急上昇で学習コスパ最強!TypeScript(タイプスクリプト)の特徴と将来性](https://descartes-search.com/media/why-you-should-learn-typescript/)
- [TypeScriptとは？ Webアプリ開発で注目の言語を初心者向けに徹底解説](https://www.sejuku.net/blog/93230)
- [【入門】TypeScriptとは？言語の特徴やJavaScriptとの違いを解説](https://www.pasonatech.co.jp/workstyle/column/detail.html?p=2761)
残して良かったドキュメント、いまいちだったドキュメント

## この記事の概要

エンジニア的な文化・行動として「ドキュメントを残そう」をよく聞きますよね。

私の在籍するQiita株式会社では、社内の情報共有もかなり強く意識しています。
普段からドキュメントを残している中で、どんなものが効果的だったかを記事にしてみました。

なお、ここでいうドキュメントとはコード内のコメントやREADMEではなく社内Wikiのようなものを指しています。

## 残して良かったドキュメント

### 定期的に人に説明する内容

- 入社時にやること
- 今導入している技術やサービスのまとめ
- 制度上のフローやガイドラインなど

新しく入社した人に説明する内容や、チーム間で異動があったら共有すべき内容などのイメージ。

自分は「この内容、何度か人に説明してるなあ」と気付いたらドキュメント化するよう心がけています。

また、これらがしっかり残っていると、次の「新しく何かを始める際の記録」が取りやすくなります。

### 新しく何かを始める際の記録

- 技術を導入する際の選定の比較や議論
- 制度が変わる際、過去とこれからの差分
- 大きめなプロジェクトのまとめ

議論したことや決めたことを都度記録し、将来の自分たちが振り返れるドキュメントを作るイメージ。
現時点での情報はある程度まとまっている前提です。

これらのドキュメントを書く際に参考資料として「定期的に人に説明する内容」のリンクが貼ってあると非常に役立ちます。
あるドキュメントを入り口にして変更差分をどんどん辿っていけるため、色々な判断がしやすくなるでしょう。

### フィードバックのまとめ

- Request for Comments
- 社内検証中に見つけた問題点
- ユーザーやクライアントの皆さまからのフィードバック

日々のフィードバックをトピックごとにまとめておくイメージ。
社内で今あるものに対して「これってどう？もっとこうなって欲しいとかある？」とコメントを求めるものから、利用者の皆さまからいただいた意見まで、色々な種類のものがあります。

「新しく何かを始める」にあたって、何から始めるかを決めるときにこれらの内容を見ながら決めることも多々あります。

### 調査記録

- 技術の調査
- 市場の調査

何を調べたのかと、いつの調査なのかがタイトルやタグで分かりやすいと重宝。
調べたときに使えなかったとしても、後から別なプロジェクトの参考資料として役立つ場合も多いです。

## 残してもいまいちだったドキュメント

### いつからいつまでの話か分からない

- タイトルに「新」とか「最新」とかついているけど明らかに現在は実施していない
- 最終的に完了したのかしてないのか、読んでも分からない
- 過去に書かれてメンテナンスされていない「将来やりたいことリスト」

現在の状況にフィットしているのか、既に解決しているのか、どこまで進んでいるのか……。
一目で分からないドキュメントは残っていても解読に時間がかかります。

### 振り返りやまとめがない

上の「いつからいつまでの話か分からない記録」と似ているかもしれません。
今まさに進行中に見える内容では、後から読み返しても困惑してしまいます。

また、世に出した後の反応や修正点がないと、後から担当する人が大変です。
「リリース完了！おしまい！」では、ドキュメントが存在している意味とは？となってしまうでしょう。
キャリアリサーチと準備

Unity Learnでキャリアについてのチュートリアル[^1]があったので，個人的にメモしておく．

# 概要

このチュートリアルでは，キャリアエリア，職種，必要な資格・検定について調べ，
キャリアゴールを明確にする．

このチュートリアルですること：

- 身につけたスキルを専門的な仕事で生かすために，キャリアの選択肢を探る．
- これらの職務に就くために必要な主なスキルや資格を明らかにする．

## キャリアの選択肢を研究する

リアルタイムキャリアの多くは，以下の2つのカテゴリに大別される：

- **Art and Design**  
モデリング，アニメーション，ライティング，オーディオ，その他のエフェクトを駆使して，
プロジェクトのルック，サウンド，フィーリングを作り上げること．
- **Programming**
ゲーム性，ネットワーク，人工知能など，プロジェクトの機能性を作り上げること．

### 自分に合った役割を考える

職務に応募するためのスキル：

- **Quality assurance technician**  
バグの発見と報告
 - テストケースとテスト計画の作成
- **Junior programmer or analyst**  
文書化された設計に基づきコードを記述し，機能を維持するためにアプリケーションを修正する．
- **Junitor software developer**  
プロトタイプの作成，コードの記述，モジュールやコンポーネントのテストと開発．

自分に合った仕事を考え，転職サイトなどで現在の求人情報を調べてみよう．

自分の目標や希望に合った仕事を見つけるための注意点：

- 職務内容
- 職務要件と重要なスキル

**Tip**:
ジュニアプログラマ，ジュニアデベロッパ，C#やUnityに特化したジュニアソフトウェア食など，
特定の職種を検索してみる．

## 認証取得

Unityは，さまざまな役割に必要なコアスキルがあることを検証し，次のキャリアへの準備をアピールするために，
さまざまな認定資格を提供している．

![Certification](https://connect-prd-cdn.unity.com/20201112/learn/images/c49d06ce-2b21-4fd2-b74b-c917607c168a_Screen_Shot_2020_11_11_at_8.41.21_AM.png.2000x0x1.png "Certification")

**User**:

- Certified User: Programmer  
UnityとC#の基礎的なプログラミングスキルの検証する．
- Certified User: VR Development  
Unityを使ったバーチャルリアリティ体験の制作に特化していることをアピールする．

**Associate**:

- Certified Associate: Game Developer  
リアルタイム3Dゲームのエコシステムにおいて，即戦力となるUnityのスキルやキャリアをアピールする．

**Professional**:
 
- Certified Professional: Programmer  
プロジェクトの構想から立ち上げ，そしてその先の技術的な遂行に貢献するために必要な，  
コアなプログラミングスキルを検証する．
- Certified Professional: Artist  
リアルタイム・インタラクティブ・ソフトウェア・プロジェクトの技術的なスキルと  
芸術的な実行の取得を検証する．

**Expert**:

- Certified Expert: Programmer  
あらゆる業界でUnityプログラミングの高度な能力を検証し，  
技術力と応用知識がトップクラスであることを世界にアピールする．
- Certified Expert: Technical Artist in Shading & Effects  
自分の専門性を確認し，ゲーム業界の上級職に必要な  
テクニカルスキルと応用知識を有していることを雇用主に証明する．
- Certified Expert: Technical Artist in Rigging & Animation  
テクニカルアーティスト，リガー，テクニカルアニメーター，テクニカルキャラクターデザイナなどの上級職で，  
自分の専門性を検証し，技術力があることを雇用主にアピールする．

## 雇用主は何を求めているの？

好奇心旺盛であること，コミュニケーション能力や協調性があることなど，技術的なこと以外も重要なスキルとして挙げられる．
また，ほとんどの場合，リアルタイム開発では，自分の作品を紹介するためのポートフォリオを作成する必要がある．

## キャリアリサーチドキュメントを作成してみよう！

キャリアリサーチドキュメントは，可能性のあるキャリアを探求し続ける中で，
自分のアイデアや重要な洞察を記録するのに最適な方法である．

自分自身のキャリアリサーチドキュメントを立ち上げてみよう：

- 興味のある職種
- キャリア領域内の資格を伴う具体的な仕事内容
- 各キャリア領域で期待されるスキルセット
- 各キャリア領域で期待される技術的知識
- 必要なトレーニングや資格
- 特定の仕事に対する予想される給与の範囲

> 後日あげるかも

## 最後に

興味のある職種が決まり，その職種に必要な知識やスキルについて調べ始めていることでしょう．
また，自分のスキルを証明するために利用できる認定資格のオプションについても検討されたことでしょう．

目標決まるといい感じに刺激になっていいですよね．
認定資格についてはお高いので，金銭的に余裕があり，非常に興味を持たれた方はやってみてはいかがでしょうか．

[^1]: [Unity Learn Tutorial Career research and presentation](https://learn.unity.com/tutorial/career-research-and-preparation?uv=2020.3&pathwayId=5f7e17e1edbc2a5ec21a20af&missionId=5f7648a4edbc2a5578eb67df#)
SQL基礎

#SELECT#

##基本##

```SQL:
SELECT [取得するカラム名]
FROM [テーブル名]
```

- カラム名を複数取得する場合は「**,**」で区切る。
- 全てのカラムを選択する場合は「**＊**」を使う。

##検索条件を指定する##

```SQL:
SELECT [取得するカラム名]
FROM [テーブル名]
WHERE [検索条件]
```

- 比較演算子を使う。

|比較演算子|説明|
|---|---|
|=|等しい|
|!=|等しくない|
|>|より大きい|
|<|より小さい|
|>=|大きいか等しい|
|<=|小さいか等しい|

- 条件を複数指定する場合は、「**AND**」または「**OR**」で区切る。

##ソート条件を指定する##

```SQL:
SELECT [取得するカラム名]
FROM [テーブル名]
ORDER BY [ソートしたいカラム名]
```

|昇順/降順|説明|
|---|---|
|ORDER BY [ソートしたいカラム名]|昇順|
|ORDER BY [ソートしたいカラム名] DESC|降順|

##取得範囲を指定する##

```SQL:
SELECT [取得するカラム名]
FROM [テーブル名]
LIMIT [行数] OFFSET [番目]
```

#INSERT文#

##基本##

```SQL:
INSERT INTO [テーブル名]([登録するカラム名])
VALUES ([登録するデータ])
```

- [登録するカラム名]を省略することも可能。省略した場合は全てのカラムが対象となる。
- [登録するカラム]が複数ある場合は、「**,**」で区切る。
- 指定しなかったカラムには、「**NULL**」というデータが返却される。もしくは初期値が返される。
- 文字データの場合は、「**'**」で囲む必要がある。
- [登録するデータ]が複数ある場合は、次のように、VALUESを1回のみ使えば良い。

```SQL:
INSERT INTO [テーブル名]([登録するカラム名])
VALUES 
 ([登録するデータ]),
 ([登録するデータ]),
 ([登録するデータ])
```

#UPDATE文#

```SQL:
UPDATE [テーブル名]
SET [カラム名] = [カラムの登録する値]
WHERE [検索条件]
```
- 変更したいカラムが複数ある場合は、「,」で区切る。

#DELETE文#

```SQL:
DELETE FROM [テーブル名]
WHERE [検索条件]
```

- DELETE FROM [テーブル名] だけで実行してしまうと全テーブルのデータが消えてしまうので注意。
Ubuntu20.04 ノートPCにインストールした直後にやること(IPアドレス固定など)


# まずはapt

```
sudo apt update
```

```
sudo apt dist-upgrade
```

apt dist-upgradeはapt upgrade機能に加えて、不要パッケージの自動削除も実施します。


# Vimを入れる（なくてもよい）

```
sudo apt install vim
```

# IPアドレス固定化

古いやり方のサイトが散見されますが、以下が正式なやり方です。
ファイル名はこのままが正式です。

```
sudo vim /etc/netplan/99_config.yaml
```

ファイルの中身は以下です。

```
network:
  version: 2
  renderer: networkd
  ethernets:
    ens160:
      dhcp4: false
      addresses:
        - 192.168.11.6/24
      gateway4: 192.168.11.1
      nameservers:
        addresses: [192.168.11.1]
```

適宜変更する項目は以下です。

|  上記での記載  |  変更内容  |
| ---- | ---- |
|  ens160  |  変更したいネットワークの名前。コマンドip aで確認した名前  |
|  - 192.168.11.6/24  |  固定化したいIPアドレス  |
|  gateway4: 192.168.11.1  |  デフォルトゲートウェイのアドレス。  |
|  addresses: [192.168.11.1]  |  DNSのアドレス。普通はデフォルトゲートウェイと同じ。  |

以下のコマンドで設定を反映します。

```
sudo netplan apply
```


# ノートPCを閉じてもスリープやサスペンドしないようにする

変更するファイルは以下です。


```
sudo vim /etc/systemd/logind.conf
```

変更内容は以下です。
すでに#でコメントアウトされているので、#を外し、ignoreに変更します。

```
HandleLidSwitch=ignore
```

以下のコマンドで設定を反映します。

```
systemctl restart systemd-logind.service
```


参考文献
https://server-network-note.net/2021/05/ubuntu-20-04-lts-server-set-ipv4address/
https://nisshingeppo.com/ai/ubuntu-nonsleep/
架空のニュースを作る

こちらの記事を参考にしました

https://qiita.com/muraokaz/items/210f82014aff73aa7a9a

# NLTKエラーが出る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175961/e3587206-6048-4fff-ad9b-d4b96cf97969.png)

以下を参考にこれ打った

```
python -c "import nltk; nltk.download()"
```

https://qiita.com/ldap2017/items/158a9aa5ec330e907197

# 形態素解析の準備を省く

学習データに形態素解析したテキストがいるのですが
webアプリでmecab使えるサイトを作ってくれている方がいたので
ここで形態素解析してもらってダウンロードしたテキストを加工した

http://www4414uj.sakura.ne.jp/Yasanichi1/unicheck/

# 学習させる

2014年のmacbook pro使ってやってます。GPUなんてもちろんないのですごい遅い。
ゴオーーーーーーーーーーーってずっといってる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175961/55d15e4d-bd1d-da7a-520e-bc03a31251df.png)

データは適当にニュースサイトから2021年のニュースを引き抜いて分かち書きにし学習データに、
2020年のニュースを分かち書きにしてテストデータにした。

そして実行して1時間、60エポックで出てきた文章
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175961/122ba8b8-049a-945a-0f70-e21554ebc1b0.png)

崩壊している。

# そもそもこれの目的は何か

これの入力になる文章を自動生成できないかなって思って。

https://qiita.com/o________o/items/58f483f3474f286ba01d


なので最終的にはgoogleのtext-to-speechに読ませこうなる予定。

https://soundcloud.com/bjack_mijilme/voice

そしてこうなる感じ。

https://soundcloud.com/bjack_mijilme/python-poem-1

原文は60エポックで生まれたこちら

>ワクチン 日本 日 と 民主 4 年 歳 に 支給 から 半数 獲得 は 違反 は 1 から よる 閲覧 問題 れ 、 サントリー 現金 が 少年 氏 の 来年 も 変異 チケット 調査 漫画 c 集まる 区 4 3 なる 経ち する 反対 で 新 も よる 豪州 。

文章としては崩壊しているけど今回の目的に沿って使うだけならなんかこれでもいいかなって気もする。

# 今後の展開

裁判の判決文とかでやってもいいかも

https://www.courts.go.jp/app/hanrei_jp/search1

https://kanz.jp/hanrei/

# なんにしても遅すぎるので

google colaboratoryでGPU使えたと思うんだけど出来るかな、やる気出たら試してみる。
seleniumでXpathを使用せず属性値が一致するものを見つけ出す方法

# はじめに

pyhtonで動的なページのスクレイピングをする必要が生じ、なかなか解決しなかったことがあったので、皆さんの参考になればと思い、記事を書きました。

seleniumで基本的な要素を取得する方法は下記が参考になると思います。
https://qiita.com/humuhimi/items/2d1225b1e33576e4f0c8

driver.find_element_by_css_selector("xxx")
という指定方法は古い指定方法なので注意が必要です。
新しい指定方法は下記になります。
driver.find_element(by=By.CSS_SELECTOR,value="xxx")

# 本題
下記のようなページがあり、「テキスト2」の部分を見つけ出したい場合に有効です。
Xpathで指定する方法もあるかと思いますが、特定の属性値を指定する方法が今回ご紹介する内容です。

```html:test1.html
<div class="test" data-item-index="1">テキスト1</div>
<div class="test" data-item-index="2">テキスト2</div>
<div class="test" data-item-index="3">テキスト3</div>
```

### seleniumでの指定方法

```python:test.py
element = driver.find_element(by=By.CSS_SELECTOR,value="div.test[data-item-index="2"])
```

以上、参考になれば幸いです。
PHP 連想配列で同じキーの要素をまとめる　要素が配列の連想配列

### やりたいこと
以下のような連想配列を持つ多次元配列がある。
データベースからデータを取ってきたときによく見る形ではないだろうか。

```input.php
$array = [
    ['key1'=>'aa','key2'=>'b','code'=>'c'],
    ['key1'=>'a','key2'=>'b','code'=>'d'],
    ['key1'=>'aa','key2'=>'bb','code'=>'e'],
    ['key1'=>'a','key2'=>'bb','code'=>'f'],
    ['key1'=>'aa','key2'=>'bb','code'=>'g'],
    ];
  ```

この配列をkeyが同じものでまとめて、配列にしたい。

```result.php
Array
(
    [aa] => Array
        (
            [b] => Array
                (
                    [0] => c
                )
            [bb] => Array
                (
                    [0] => e
                    [1] => g
                )
        )
    [a] => Array
        (
            [b] => Array
                (
                    [0] => d
                )
            [bb] => Array
                (
                    [0] => f
                )
        )
)
```

以前に以下の記事を書いた。

・[js 連想配列（オブジェクト）で同じキーの要素をまとめる　配列を持つプロパティ](https://qiita.com/Jinta/items/deed7bc09128bf032c6c#comment-674cd2b16a63006746ea)

これを書いたのはPHPでこの処理を書いたときに、jsの場合はどう書くのか気になったからである。

### やったこと

```index.php
foreach($array as $data){
        if(!$newArr[$data['key1']][$data['key2']]){
            $newArr[$data['key1']][$data['key2']]=[$data['code']];
        }else{
            array_push($newArr[$data['key1']][$data['key2']],$data['code']);
        }
    };

    echo('<pre>');
    print_r($newArr);
    echo('</pre>');
```

jsより簡単だと思うのは、undefindでも（定義しなくても？）要素を追加できるところでしょうか。

よければ、別解などご意見いただけると幸いです。
再起動後のコンソールで「node -v」実行後「zsh: command not found:node」とエラーが出る

##はじめに
VSCodeでNode.jsを使用できない。
インストールはできており、コンソールの再起動前は「node -v」を実行できていた。
エラーを見るにパスが通っていないことが原因と考えた。

##試したこと
###✖️1.VSCodeの環境変数設定をしている「settings.json」に追記。

```
"terminal.integrated.env.osx": {
      "PATH": "${workspaceRoot}/node_modules/.bin:${env:PATH}"
    }
```

以下のエラーが出て断念。

```
Expected commajsonc(514)
```

「settings.json」の理解不足が原因だと考える。
VSCode悪くないんじゃないかと感じ「2.」を実行。


###2.環境変数を設定
Node.jsインストール手順「環境パスを通す」は以下をコンソールで実行していた。


```
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile
```


きちんと

```
source　~/.bash_profile
```
も行った。

ここで
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
bash以外で使いたいときは各シェルの適したファイルに追記します。
なんとmacOS X 10.15 Catalinaからはzshがデフォルトになったので、zshでは以下になります。
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

という文章を後に発見。

記載通り以下をコンソールで実行。



```
echo ‘export PATH=$HOME/.nodebrew/current/bin:$PATH’ >> ~/.zprofile
```


けどもだめ。

そもそもbashとzshどっち見ているのか確認。以下をコンソールで実行。

```
echo $SHELL
```

結果

```
/bin/zsh
```

zshを見ているらしい。
zprofileとは何かを検索。
3種類あるらしい。以下の文章を発見。
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
~/.zshenv と ~/.zshrc だけ使えば、ほとんどの場合 OK
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

zshrc見たことある…。と思い中身を確認するために以下を実行。

```
vim ~/.zshrc
```

結果

```
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Java/JavaVirtualMachines/adoptopenjdk-17.0.1.jdk/Contents/Home/bin

export PATH=/opt/homebrew/bin:$PATH
export PATH="/opt/homebrew/opt/mysql@5.7/bin:$PATH"
```

PATH設定の場所を無事に発見。
以下を実行。

```
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zshrc
source　~/.zshrc
```

PATHが通り、「node -v」にエラーが出なくなった。

##まとめ
###環境変数設定はMacOSの場合以下の2種類ある。
・bash
・zsh
macOS X 10.15 Catalinaからは【zsh】がデフォルトになった。



###【zsh】には3種類ある。
「.zprofile」
→ログインシェルに必要な設定だけを記述する

「.zshrc」
→ログインシェル、インタラクティブシェルの場合に読み込まれる

「.zshenv」（影響範囲が広く注意する必要があるらしい）
→zsh が起動して、必ず最初に読み込まれる設定ファイル

まだ全然わからないが忘れないように記載。
自分のIPアドレスを（外から）調べる一番速い方法

# 自分のIPアドレスを（外から）調べる一番速い方法

自分のIPアドレスがWAN (ワイド・エリア・ネットワーク、つまり自宅などの外側のネットワーク) からどう見えるかは以外と調べにくい。
自端末からifconfigなどで見えるアドレスはNATなどで変換されていることがあるので、
正確に知ろうと思うとLAN外のサーバにアクセスしてみるほかない。

ターミナルから

```
curl http://ipinfo.io/ip
```
とやるのが今のところおすすめ。IPアドレスを教えてくれるサーバはいろいろあるが、ここはIPアドレス以外のタグなどの装飾文字列が何もついてこないところが良い。
typescriptのcallback関数がぱっと見が謎だった

udemyの講座を見ていてぱっと見謎だった。
console.logで42が表示されるソースが以下。

```index.ts
function doubleAndHandle(num: number, cb: (num: number) => number) : void {
  const doubleNum = cb(num * 2);
  console.log(doubleNum);
}
doubleAndHandle(21, doubleNum => {
  return doubleNum;
});
```

googleでアロー関数を調べて理解した。要は無名関数の以下と同義。

```index.ts
doubleAndHandle(21, function (doubleNum) {
  return doubleNum;
});
```

()を付けたほうがわかりやすいと思った。

```index.ts
doubleAndHandle(21, (doubleNum) => {
  return doubleNum;
});
```
カフェに入ったらsshのグローバルIPでAWSのSGを開けれるシェル

#前提

awsの権限はすでに設定されている前提
aws configure叩いたらこんなのが出てくるし、権限も充分に付与されている状態

```
 aws configure
AWS Access Key ID [*******************T]: 
```

#sh

``` sh
ip=$(curl -s httpbin.org/ip | sed -n -e "s/.*: .\(.*\).$/\1/p")
port 22 --cidr $rtn/32)
#なんかもっとかんたんな気もする👆
aws ec2 authorize-security-group-ingress --group-id あなたのSG --protocol tcp --port 22 --cidr $ip/32
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1364181/72b71e29-079e-5108-4335-2de0bb20c8ee.png)


#後記

これを叩きまくるとSGがmaxに到達するのでそのときの削除はバッチ処理してください...orz
->この上限があがったかもしれません
Slack-APIでUserOAuthTokenを発行するメモ

#UserOAuthTokenが見当たらない
IncomingWebhook経由で通知を飛ばしていたのですが、通知の数が多すぎてワークスペースを圧迫していました。なのでGAS(GoogleAppsScript)を利用して一定期間が過ぎたIncomingWebhookの通知を削除していくシステムを作ろうとしたのですが、どうやらIncomingWebhookの投稿BotとGASで使用するBotが別ユーザー扱いらしく、削除するためには別ユーザーの投稿を消すことができる権限を持ったUserOAuthTokenが必要とのこと。しかし、私のSlackAPIのページにはBotUserOAuthTokenしか見当たらず、UserOAuthTokenがどこにもありませんでした。

#AppManifestに直接書き込めばいけた
デフォルトではbotの欄しかありませんが、userを追加して権限を与えればUserOAuthTokenを発行できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2305694/7a4de973-5cfe-b39a-26fd-acae50b31e6c.png)

#その後botの再インストール
AppManifestに追記した後にワークスペースにbotの再インストールを行うとミッションコンプリートです。更新したらUserOAuthTokenが出てくるはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2305694/30780c79-e5ff-8ecf-72f1-57192351a263.png)


#AppManifestが最近できたからか情報が少なかった
めっちゃ調べたんですけどUserOAuthTokenについての情報が全然ありませんでした。当たり前のこと過ぎてみんな書いていないんだろうか...。少なくとも私はめちゃめちゃ時間取られたので黙示録も兼ねて記事にしました。自分自身めちゃめちゃ素人なので、めちゃめちゃ素人の方の助けになれたらいいな。

#参考資料
別件ですが、SlackのIncomingWebhookを期限によって随時削除するプログラムの参考にさせていただいた記事をまとめておきます。
[簡単にSlackの一定期間経過した投稿を自動で削除する方法 | notwork | モバイルアプリ開発情報](https://tech.naturalmindo.com/notwork_slackapi/)
[Google Apps Script (GAS)を使ってSlackの一定期間経過した投稿を自動削除のメモ - Qiita](https://qiita.com/a2d4f3s1/items/42440c13ad05fa16746c)
[SlackAPIを使うまでのメモ - Qiita](https://qiita.com/kotaronov27/items/21338b193e6cb3947fe9)