OmniAICreator/Qiita-1.07M huggingface dataset:
Matplotlib入門

## Matplotlib入門

Matplotlibはデータの可視化とカスタマイズに最も柔軟性のあるインターフェースpyplotを提供します。
pyplotの簡単な使用方法は以下：

```python
import pandas as pd

df01 = pd.DataFrame(
    {'time': ['1s', '2s', '3s', '4s', '5s'],
     'value': [1, 2, 3, 4, 5]})
df02 = pd.DataFrame(
    {'time': ['1s', '2s', '3s', '4s', '5s'],
     'value': [5, 4, 3, 2, 1]}
)
```

```python
# matplotlib.pyplotをインポート
import matplotlib.pyplot as plt

# FigureとAxesオブジェクトを作成
fig, ax = plt.subplots()

# df01のvalueをtimeに対してプロット
ax.plot(df01['time'], df01['value'])

# df02のvalueをtimeに対してプロット
ax.plot(df02['time'], df02['value'])

# プロット表示
plt.show()
```

![01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/22f01a83-264f-32f1-fe48-ef6ab3943b0c.jpeg)

## プロットのカスタマイズ

マーカー、線のスタイル、線の色を設定できます。  
また、タイトル、X軸の名称、Y軸の名称も設定できます。

設定可能なフォーマットは [matplotlib.pyplot.plot](https://matplotlib.org/3.3.3/api/_as_gen/matplotlib.pyplot.plot.html) にあります。

```python
# マーカー、線のスタイル、線の色を設定
ax.plot(df01["time"], df01["value"], color='b', marker='o', linestyle='--')
ax.plot(df02["time"], df02["value"], color='r', marker='v', linestyle='--')

# X軸の名称を設定
ax.set_xlabel('Time (s)')

# Y軸の名称を設定
ax.set_ylabel('Value')

# タイトルを設定
ax.set_title('Value patterns in df01 and df02')

plt.show()
```

![02.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/0609e37c-0273-a1a0-e2dd-de4233b059d6.jpeg)


## サブプロット

プロットにデータを追加しすぎると、場合によってはプロットが煩雑になりすぎて、パターンが見えなくなってしまうことがあります。
その場合はサブプロットを使用します。 [matplotlib.pyplot.subplot](https://matplotlib.org/3.3.3/api/_as_gen/matplotlib.pyplot.subplot.html)

```python
# 2行1列のサブプロットを作成
fig, ax = plt.subplots(2, 1)

ax[0].plot(df01['time'], df01['value'])

ax[1].plot(df02['time'], df02['value'])

plt.show()
```

![03.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/8f476d48-88a5-5177-3204-98946b359b6d.jpeg)
tinyAVR 0シリーズ（ATtiny402）と tinyAVR 1シリーズ（ATtiny412）の比較

###概要
新しいAVRマイコンシリーズで、tinyAVR0シリーズ(tinyAVR® 0-Series)とtinyAVR1シリーズ(tinyAVR® 1-Series)があります。
簡単に0シリーズと1シリーズを比較してみました。
###0シリーズと1シリーズの違い
1シリーズは通常のタイプで0シリーズは機能を落とした安価タイプになります。
ATtiny85との比較ですが、0シリーズ、1シリーズにFLASHが8kByte品が無いのが悔やまれます。
0シリーズのATtiny402がお安くなっています（mouser調べ）
![スクリーンショット 2021-01-24 15.58.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111210/29e687c1-f17e-8f29-118a-7e5df7f25c52.png)
###ATtiny402とATtiny412の違い
ATtiny402
1.<font color="Red">3</font>-channel Event System
2.<font color="Red">TCD無し(12bitタイマーカウンター)</font>
3.One 16-bit Real-Time Counter (RTC) running from Internal RC Oscillator
4.Analog Comparator (AC)
5.<font color="Red">DAC無し</font>

ATtiny412
1.<font color="Red">6</font>-channel Event System
2.One 12-bit Timer/Counter type D Optimized for Control Applications (TCD)(12bitタイマーカウンター)
3.One 16-bit Real Time Counter (RTC) Running from <font color="Red">External Crystal or </font>Internal RC Oscillator
4.Analog Comparator (AC) <font color="Red">with Low Propagation Delay</font>
5.8-bit Digital to Analog Converter (DAC)

mouser調べてATtiny402とATtiny412を比較すると5円くらいの差しか無いので、ホビーユースならATtiny412でも良いかな！
###参考リンク
みなぎのサイト
新しいAVRマイコンシリーズの紹介
https://mngu.net/blog/diy/introduction-of-the-new-avr-series.html


ねむいさんのぶろぐ
AVR再びはぢめました(ATTINY104とATTINY202を使ってみる)
http://nemuisan.blog.bai.ne.jp/?eid=231677
[Ansible]複数のサーバに一括で環境変数を設定する方法


##環境
EC2  (Amazon Linux 2 AMI)
Ansible 2.7.10


##やりたいこと
Ansibleを使って複数のEC2に一括で同じ環境変数を設定したい。(Ansibleはインストール済みとする)

![ansible.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151361/6ca9ab23-dffa-f14e-d0c9-c4629144482f.png)



##ディレクトリ構成

　.
　├ group_vars/
　├ host_vars/
　├ roles/
　│　└ set_environment/
　│　　　├ files/
　│　　　│　└ environment.j2
　│　　　└ tasks/
　│　　　　　└ main.yml
　├ inventory.ini
　├ playbook.yml
　└ ansible.cfg ← SSH接続で使用する秘密鍵のファイルのパスを指定


##実装

Ansible には、`template`というモジュール があり、`src`というパラメータに指定したファイルをテンプレートとして、`dst`に指定したリモート先にファイルを生成することができます。このモジュールを利用して対象のサーバの/etc/environmentを上書きします。

まずタスクファイルにtemplateモジュールを設定します。

```yml:main.yml
- name: set /etc/environment
  template:
    src: ../files/environment.j2
    dest: /etc/environment
  become: yes
- name: results
  debug: var=RESULT.results
```

`src`に指定した`environment.j2`に設定したい環境変数を定義します。
(※templateモジュールはJinja2というテンプレートエンジンによるテンプレートファイルを利用するため、必ず`.j2`ファイルに定義する)

```j2:environment.j2
DB_NAME="xxxxxxxxxxxxxxxx"
DB_USER_NAME="xxxxxxxxxxx"
DB_PASSWORD="xxxxxxxxx"
DB_HOST="xxxxxxx.c4s7xxxxxxiwp.ap-northeast-1.rds.amazonaws.com"
```

`playbook.yml`のrolesにrole(set_environment)を設定します。

```yml:playbook.yml
---
- name: set environment(環境変数の設定)
  hosts: all
  user: ec2-user
  become: True
  roles:
    - set_environment
```

```ini:inventory.ini
[host_group1]
xx.xxx.xxx.xxx
xx.xxx.xx.xxx
xx.xxx.xx.xxx
xx.xxx.xxx.xxx

[host_group2]
xx.xxx.xxx.xxx
xx.xxx.xx.xxx
xx.xxx.xx.xxx
xx.xxx.xxx.xxx

[host_group3]
xx.xxx.xxx.xxx
xx.xxx.xx.xxx
xx.xxx.xx.xxx
xx.xxx.xxx.xxx
```

上記の設定をした上で下記のようにplaybookを実行すると、対象のサーバの環境変数を設定することができます。

```
$ ansible-playbook -i inventory.ini -l <host_group> playbook.yml
```
ラビットチャレンジ　応用数学レポート

##0. はじめに
本ページは[ラビット・チャレンジ](https://ai999.careers/rabbit/)（E資格認定講座）の課題レポートです。

##1. 線形代数
###1.1 行列
行列とは連立方程式の研究の中から生まれたもの。
行列を使って連立方程式を解くには、逆行列を求める必要がある。

###1.2 逆行列の求め方(掃き出し法)
![縦長画像 01-24-2021 17.31~2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569342/d814ccf8-e13c-d0b6-8d1a-954e60665331.jpeg)

###1.3 逆行列が存在しない条件
解がない、解が一組に定まらないタイプの連立方程式。
これらの係数を抜き出したような行列は、逆行列を持たない。
![縦長画像 01-24-2021 17.33~2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569342/05faf5fc-0109-45df-51d2-1880b5c5648d.jpeg)
行列式の計算結果が0になる場合、逆行列を持たないことになる。

###1.4 行列式の計算
![縦長画像 01-24-2021 19.09~2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569342/c274acde-b6a0-e063-5a13-4421e8532251.jpeg)

###1.5 固有値と固有ベクトル
![縦長画像 01-24-2021 19.11~2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569342/0617af9b-f5c0-1906-9963-6e4b2f68ff35.jpeg)
![縦長画像 01-24-2021 19.12~2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569342/001d1a47-ae50-63e6-4333-245105844ce5.jpeg)
固有ベクトルはいくつも存在する。重要なのはベクトルの比。

(参考)解の公式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569342/87035653-f525-4968-24a4-35f167fcb3c3.png)


###1.6 固有値分解
![縦長画像 01-24-2021 19.14~2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569342/a6e3d65f-ab46-8bab-7267-69b411677dbb.jpeg)

###1.7 特異値分解
![縦長画像 01-24-2021 19.15~2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569342/33f7af88-e965-3709-e99f-a6e3946f8c5e.jpeg)
特異値分解の例題は、[こちら](https://note.com/fugusaka/n/nebab826b270e)に記載されている解き方が個人的にしっくりきました。

(つづく)
ブラウザのブックマークをNotionに移行したら素敵だった件

# はじめに
## 概要
* 最近Notionという素敵アプリを知りました。
    * https://www.notion.so/

* Notionは直感的には、下記のようなツールのいいとこ取りのような印象です
    * Evernoteのように気軽に取れるノートを取れる
    * Dokuwikiのように階層を持ったページ単位のwikiを作れる
    * trelloのようなカンバン方式で状態管理がでぉり
    * Redmineのようなガントチャートで情報を可視化できる


---

# 本編
## 全体像/結論
* GoogleChromeのブックマークをNotionで管理するようにしたらすごく管理しやすくなりました。
    * 本来はノート＋タスク管理などがメインの使い方だと思いますので、少し変わった使い方だと思いますが。。。
* NotionにはWeb Clipper機能があるので、Webサイトの管理が簡単にできます。
* 今回はこの機能を使って、GoogleChromeのブックマークをNotionのDBで管理します。

## Chromeのブックマークからの移行で解決すること
### 0. ブックマークを整理できる
* NotionでDB化するにあたって、重複の整理/リンク切れの発見/タグを整頓する機会になります
    * 久しぶりにアクセスすると、意外とサービスが終わっていたりするんですよね。。。

### 1. プロパティなどの表示/非表示と順番を変えられる
* 表示できる項目や順番はかなり柔軟に変えられます。
* 下の例は、タイトルとURLとタグを表示しています。
    * リンクはそのままページを開くことができます。

![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/81b3b5a1-ae67-4fb3-0cd5-00068502c8d0.png)


### 2. タグ管理できる
* ブックマークは階層で管理されるので、重複したり、どこにおいたかがわからなくなったりします。
* タグ管理で、後述するダッシュボードや一覧を利用することで必要な機能に素早くアクセスできます。

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/8e08ef80-1c62-741c-502e-31fca7dca9ac.png)

* それぞれのビュー毎に保存ができるので、タグのフィルタ＝ブックマークのフォルダのようなイメージで管理できます

### 3.リスト、ダッシュボード、テーブルなど表示形式を変えられる
* DBデータとして管理されているので、データを変えずに、Table,List,DashBoardなどを切り替えて、いろいろ観点でブックマークを見れます

![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/7160a8e7-dc61-96bf-9b5c-2c5919fa3b3c.png)

### 4.ブックマーク以外の情報と合わせて管理できる
* この機能は、NotionのDatabase機能の1つに過ぎないので、左側のサイドメニューにあるように、別のデータなどと親子関係を作れたり、このページの上や下に情報を入れることもできます。

### 5. ショートカットキーが使える/Undoできる
* 上下移動後にDelで削除したり、項目をTabで次に進められたりするのはいいですね。
* Undoで間違ったときに戻せるのもGood

## Chromeのブックマークからの移行で逆に困ること
### 1.シークレットウィンドウがひと手間増える
* Notionからはリンクが直接開けますが、シークレットウィンドウを直接開けないようなので、一度シークレットウィンドウ開いてから、URLを入れる必要があるようです

### 2. 保存先がローカルからクラウドになる
* このサービスに障害があると使えない。。。
* ブックマークは、プライバシーの塊みたいなものなので、抵抗ある人もいるかも。。。
きっとgit使えないとbad

#はじめに
私は、プログラミングを始めた当初から、GitHub Desktopを使っていました。ですが、現場ではターミナルで操作することの方が多いと思うので、封印します。ターミナルで操作できるように少しずつコマンドを覚えていこうと思います。

今回は、いちばんよく使う、GitHub Desktopでいうところの、コミットからプッシュまでを紹介します。

##コミットまで

```bash
% git add ファイル名
```
- ファイル名はパスで指定する。  
※app/views…みたいな感じ。
- 複数のファイルを登録する場合は、ファイル名を半角スペースで開ける。  
※同じフォルダ内なら、`,`で区切る。
- 全ファイルを登録する場合は、

```bash
% git add -A
```


```bash
% git commit -"コミットメッセージ"
```
ここまでをGitHub Desktopでは、コミットメッセージを書いて、ワンクリックだったなぁ…
`add`の概念が無かった…


```bash
% git status
```
で状態を確認することができる。

##リモートリポジトリにプッシュ

```bash
% git push
```
これも、GitHub Desktopでは、ワンクリックだったなぁ。

##最後に
調べていると知らない概念がたくさんあって、もっと勉強しないといけないと思わされました。
フレームワークexpressのインストールと起動

#初めに
以下コマンドでコンソール起動

```
vagrant up
vagrant ssh
```

#次に
以下コマンドで<a> Express application generator</a>をインストール

```
yarn global add express-generator@4.16.0
```

#最後に

以下コマンドでファイルでファイル作成
hoge部分はファイル名

```
express --view=pug hoge
```

以下コマンドでPORT=8000で起動
http://localhost:8000/ にアクセスすると開ける

```
yarn install
DEBUG=hoge:* PORT=8000 yarn start
```
RHEL8にjupyter notebookをインストール

#pythonの設定

[このサイト](https://xn--o9j8h1c9hb5756dt0ua226amc1a.com/?p=4038)に準じて行う。
RHEL8には標準でPython3.6が提供されいるので、これを呼出やすいようにする。pipも同様。
これをしないと単にpython,pipと入力しただけではコマンドが見つからないと表示されてしまう。

なお、Anacondaは別途インストールする。

#jupyter notebookのインストール

jupyter notebookは手動でインストールする必要がある。
下記のとおり行う。

```
sudo pip install notebook
```

ターミナルでjupyter notebookと入力して、立ち上がればOK。
【Workato】CSVファイルの文字化けをなんとかする方法

#TL;DR
- WorkatoでShift_JISでエンコードしたい場合
- `Error calculating input for field 'message': U+2757 from UTF-8 to Shift_JIS`みたいなエラーメッセージが出る

`.encode("Shift_JIS", { :invalid => :replace, :undef => :replace, :replace => "?" })`
というformulaを使いましょう。

#Shift_JISでエンコードする
Workatoのレシピで作成したCSVファイルを開いたとき、それが文字化けしている場合がある。(Excelで開いたときの文字化け)
これはWorkatoではUTF-8という文字コードでテキストを扱っているからである。ExcelではCSVなどのテキストファイルを開くとき、Shift_JISでデコードするため、UTF-8でエンコードされているファイルは文字化けしてしまうのである。

そのため、

- できたCSVをUTF-8の文字としてデコードする
- WorkatoでCSVを生成するときにShift_JISでエンコードするように設定する

の2通りがある。今回はformulaを使ってCSVを生成するときにShift_JISでエンコードする方法を記述する。

#encode() formula
`.encode()`というformulaを使うことでテキストを好きな文字コードでエンコードすることができます。
ただし、UTF-8で表現できる文字でもエンコード後の文字コードに存在しない文字に遭遇した場合はエラーになってしまいます...
そこで、`.encode()`にオプションを記述します。
最終的には、Shift_JISにエンコードしたい場合はこのようなformulaを使用します。

`.encode("Shift_JIS", { :invalid => :replace, :undef => :replace, :replace => "?" })`

Shift_JISにエンコードできなかった文字は`?`に自動的に置き換えられます。
これでエラーで止まってしまうことはなくなります。
LinuxからAndroid(その逆も）へバックアップ

Alpineでも日本語入力Mozcが利用可能であることは確認できました。
現在は、Arch Linuxベースの[Manjaro Linux](https://manjaro.org/)(xfce)に落ち着いています。
グラフィカルなインストーラー)(Calamares？)でインストール先のパーティションも手動で選べます。
日本語環境も整えやすいです。

個人的にはブラウザのfirefoxがあれば、Webは一通り見れるし、動画も再生できる。Webメールのgmailも見れる。
Yahooのニュースのライブ動画もUser Agent Switcherのアドオン入れて、Windowsと同じですよ宣言しておけば、再生できます。

バックアップに使うアプリ（ソフトウェア）は、
syncthing
を選択しました。P2Pらしい。

無料のクラウドストレージには限度がある。クラウドまでは必要ない。アクセスするのは重たいし。
バックアップも無意識にLinuxとAndroidで同期(Sync)してくれたら、助かる。そういったニーズのアプリです。
私の場合には、スマホに取り付けたSDカードにバックアップできればなぁというケース。
Windowsもあるようです。

バックアップで同期元（送信のみ）、同期先（受信のみ）も設定できて、ファイルのバージョンもとれるらしい。
そこまではチェックしてないけれど。
スマホでとった写真を、Wifiにつながったときに、自宅のPCと同期して、バックアップとる、という、私のケースの逆パターンでも、有効活用できると思います。
大きなストレージが不要なら、BOX,Dropbox,Google Driveで十分ではありますね。

ポイント！
外部SDカードで、受信も可能にする場合。
アプリに付与されるパーミッションの関係か、共有フォルダを
Android/data/com.nutomic.syncthingandroid/files
フォルダ以下に指定する必要がある。

パスが深くなるので、
ファイラーでホームディレクトリに設定できるものや、ホーム画面にショートカットを作れるタイプがあると便利でしょう。

ファイラーで、無料で広告無しで、良かったのは
DVファイルエクスプローラー（Dovi Tools）
ホーム画面にショートカットを作成でき、タップすると、DVファイルエクスプローラーがそのパスで立ち上がる。
ただ、レビューによるとAndroid10でSDへのアクセス権限付与でうまく動作しない場合があるらしい。

他には、最新バージョンはProが99円だが、
シンプルファイル管理（Simple Mobile Tools)は、ファイラーを立ち上げたときの初期パスを設定できるので、これでも良いかもしれない。
環境によって、エラーがあるようなので、Proを使うのが安心かもしれない。動作確認できるまでは、バックアップをとっときましょう。

Androidのファイルシステムではsymlinkはないので、同期元にシムリンクが含まれている場合、Androido側のsyncthingは未同期になります。
同期元でtarballを展開して、シムリンクが生成されたりすると、その部分で同期ができないので、未同期と表示されます。
イレギュラーなケースなので、まずないでしょうが、バックアップができてない、と焦らないようにしましょう。
最初に一通り動作チェックを行っていれば、多分、問題なく動いてくれるでしょう。
設定すれば、ファイルのバージョンまでとってくれるらしい。（履歴？)
初期設定でAndroidではオフになってましたので、設定して、テストしてみてください。
最初のチェックは特に大切（笑）
docker-composeでのMySQL環境構築（タイムゾーン、UTF-8対応）

# はてなブログに移行しました

https://p5750-tech.hateblo.jp/entry/docker-compose-mysql


# はじめに
ローカル開発環境を立てるためにMySQLのコンテナを用意することがよくあるが、（主にタイムゾーンとUTF-8の対応で）毎回同じようなところで詰まって調べていたので、備忘録も兼ねて自分的な「いつものやつ」を残しておく。

# 結論
https://github.com/p5750/docker-mysql-sample

# ディレクトリ構成

`./docker/myqsl/data` をvolumeとすることでDBのデータを永続化する。
なお、初回起動時にこのディレクトリに余計なファイルが入っているとコケることがあるので注意。
`.gitkeep` は置いておいて大丈夫だった。

```:構成
.
├── docker
│   └── mysql
│       ├── data
│       │   └── .gitkeep
│       └── Dockerfile
├── .env
├── .gitignore
└── docker-compose.yml
```

# 各ファイルの内容

## Dockerfile

MySQLのバージョンはお好みで。
タイムゾーンを `Asia/Tokyo` に、ロケールは `en_US.UTF-8` にしている。 日本語にしたければ `ja_JP.UTF-8` にする。

```Dockerfile:Dockerfile
FROM mysql:8.0.23
RUN apt-get update && \
    apt-get install -y tzdata locales && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
    locale-gen
ENV LANG en_US.UTF-8

CMD ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
```

## .env
適宜書き換える。

```sh:.env
MYSQL_ROOT_PASSWORD=root_password
MYSQL_DATABASE=sample
MYSQL_USER=sample_user
MYSQL_PASSWORD=sample_password

MYSQL_PORT=3306
ADMINER_PORT=8080
```

## docker-compose.yml

`version` は特に理由がなければ最新でよさそう。使えるものは[公式のドキュメント](https://docs.docker.com/compose/compose-file/)でわかる。
[Adminer](https://www.adminer.org/)はお好みで入れる。個人的にはローカル用なら入れといて損はしないかなと思っている。

```yml:docker-compose.yml
version: '3.8'
services:
  db:
    build: ./docker/mysql
    env_file:
      - .env
    ports:
      - "${MYSQL_PORT}:3306"
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
  adminer:
    image: adminer:4.7.8-standalone
    ports:
      - "${ADMINER_PORT}:8080"
```

## .gitignore

データ永続化用の `docker/mysql/data` と、認証情報が含まれる `.env` は必ずignoreする。
`.idea` はJetBrainsのIDE用。VSCodeなら `.vscode` になる。

```:.gitignore
docker/mysql/data
.env
.idea
```

# コマンド
Dockerの基本操作は本稿の趣旨ではないので割愛する。

## DBを抹消して作り直すとき

ゴミが残るので、必ず先に `down` する。

```sh
docker-compose down                    # コンテナを止めて削除する

rm -rf ./docker/mysql/data             # volumeでマウントしているデータをディレクトリごと消す
mkdir ./docker/mysql/data              # ディレクトリを作り直す
touch ./docker/mysql/data/.gitkeep     # gitに.gitkeepをコミットしているなら作り直す。
                                       #   ※差分出てるはずなのでgit resetとかで復旧してもよい。

docker-compose up -d                   # 再度立ち上げる。Dockerfileに変更が入っていたら --build も必要
```

# リンク集
- 公式MySQLコンテナ https://hub.docker.com/_/mysql
    - 環境変数とかたまに調べる
- 公式Adminerコンテナ https://hub.docker.com/_/adminer
【個人開発】初めてWebサービスを作った

#（１）作成のきっかけ
今まで、Udemyや参考書でpythonやflaskを勉強してきたが、実際のwebサービスを作ってみたことがなかったため、どうせなら一度作ってみたいと思っていました。

ところが、いざwebサービスといっても、何をどのように作って良いのか分からず、"webサービスを作ろう！"と思ってから、ダラダラと１年以上が経過していました。

そんな中、[れとるときゃりー](https://qiita.com/retoruto_carry)さんの記事を見かけ、あ、こういう発想でいいんだ！と妙に納得？してからは、試行錯誤しながらサービス開発に勤しみました。

ほんと、[れとるときゃりー](https://qiita.com/retoruto_carry)さんには感謝です。

#（２）作成したwebサービス

[Twitterで、Mリーグ（プロ麻雀リーグ）の応援を支援するサービスです。](http://m-league-ouen.herokuapp.com)


もともとMリーグ（プロ麻雀リーグ）が大好きで、Abemaでリーグ戦開催中は欠かさずチェックしてます。※Mリーグの詳細は[こちら](https://m-league.jp)

Twitterでただ単純に応援するよりは、もっと面白く応援できたらいいな、と思いサービスを作りました。
![sample9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29856/d2c6f5a5-b7a5-63c8-46fd-c5640d41c6ea.png)

#（３）使った技術
・Python3.8.2
・Tweepy
・Flask
・Bootstrap
・Heroku

Twitter Developersに登録し、Tweepyをインストール。
OAuth認証を設定。
FlaskとBootstrapでバックエンドとフロントエンドを作成。

#（４）参考にさせていただいたサイト
###①Flaskまわり
[Flaskページ間で変数を渡す方法は？](https://www.it-swarm-ja.tech/ja/python/flaskページ間で変数を渡す方法は？/1050284636/)
###②OAuthまわり
[認証に関するチュートリアル](https://kurozumi.github.io/tweepy/auth_tutorial.html)
[Twitterで自動ふぁぼ、認証機能を実装してWEBアプリ化！](https://yukituna.com/1569/)
[【Python】Flask+TweepyでTwitter連携アプリを作る](https://shirokai.hatenablog.com/entry/flask-tweepy)
[Flaskを使用してURLから名前付きパラメータを取得する方法](https://www.it-swarm-ja.tech/ja/python/flaskを使用してurlから名前付きパラメータを取得する方法/1048547243/)
[【Python3】tweepyで認証情報(AccessToken)の取得方法](https://sleepless-se.net/2018/11/17/hwo-to-get-tweepy-accesstoken-on-python3/)
###③Herokuまわり
[Tweepyで自動フォロー＆ファボを実装し、Cronで定期実行](https://qiita.com/deadhead13/items/ef909ef69277ef11b345)
[Pythonのプログラムの定期実行が無料でできるHerokuのscheduler【10分で完了】](https://hashikake.com/heroku-scheculer)
[Herokuのアドオン「Heroku Postgres」を使ってみる](https://kin29.info/herokuのアドオン「heroku-postgres」を使ってみる/)
[Herokuのタイムゾーン変更](https://qiita.com/Horie1024/items/85688099707610f70fa6)
###④その他
[SQLiteの基本操作（データベース、テーブル、レコード追加などのコマンド一覧）](http://blog.e-riverstyle.com/2010/05/sqlite.html)
[【Python】【Flask】外部CSSファイルやJavaScriptを読み込む](https://max999blog.com/python-flask-import-css-javascript/)
[汎用的な利用規約の雛形（ひな型）](https://kiyaku.jp/hinagata/gp.html)

#（５）終わりに
今回、本当にいろいろ苦労しました。特にOAuthまわりはハマりました。
これまで、Udemyや参考書で勉強してきましたが、、こうやって自分のサービスを作成すると、参考書通りには行かないことがたくさんありました。ただ、試行錯誤しながらも、ググれば大半のことはわかります。
とにかく”何か”を作成することが重要だとしみじみ思いました。
LabVIEWを使って単純パーセプトロンによる分類をやってみた

# 本記事の内容
LabVIEW Community Editionを使い、Irisデータセットに対して、単純パーセプトロンによる分類をおこないました。
下記サイトをゴッソリ参考にさせていただき、標準関数のみを使用して分類処理を作成しています。

"機械学習の元祖「パーセプトロン」とは？"
https://rightcode.co.jp/blog/information-technology/simple-perceptron

# 処理の流れ
次の流れで処理をおこなっています。
1.データセットの読込、2.教師データの作成、3.散布図用データの作成、4.確率的勾配降下法による重みの更新、5.境界直線データの生成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/1b89fbda-e54e-9046-36ab-6549ec927a07.png)
順番に処理を説明します。

## 1.データセットの読込
あらかじめ下記処理で保存しておいたCSVファイルを読み込みます。
Irisデータセットは4次元のデータですが、結果のプロットを簡単にするため、sepal lenght(cm)とsepal width(cm)の2つのデータをのみを使用します。

```Python
from sklearn.datasets import load_iris
import pandas as pd

iris = load_iris()
iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
iris_df["species"] = [iris.target_names[i] for i in iris.target]
iris_df.to_csv("./Iris.csv")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/dc13e95a-eced-bb01-09a3-27bfaef5cb0e.png)

## 2.教師データの作成
2クラス分類とするため、virginica行を削除して教師データを作成しています。setonaは0、versicolorは1とラベリングします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/a75e72dc-cdb1-6b92-2c33-f2ec7b3c4d1e.png)

## 3.散布図用データの作成
Sepal lenghおよびSepal widthを要素とするクラスタを、SetosaとVersicolorそれぞれで作成し、Build array関数で結合した後でXYグラフへ入力することによって、プロットを分けてグラフ表示することが可能となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/ae42fe33-c462-1867-67b5-7415ecfd2c29.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/b5ce330c-52f7-3faf-77b1-53eb4c6edd4e.png)

## 4. 確率的勾配降下法による重みの更新
-w0 + w1 × Sepal length + w2 × Sepal width をstep関数(0より大きければ1を、それ以外は0を出力)に入力した値がラベリングした値と一致するように、重みw0,w1,w2を更新する。 誤差が0になるか、エポック数が上限に達するまで処理を繰り返します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/5f9f4514-5a1b-5e9e-58fd-ca112aa769f4.png)

## 5.境界直線データの生成
重み値を使って境界直線データを生成します。
ループ回数10回は適当に決めた値です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/45e63034-31b6-fd97-44ef-e43380aa768f.png)

#結果
エポック数の上限を200とすることで、繰り返し試行した場合においても正解率はほぼ100%となりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/64b59b8b-22dd-74e9-9ace-1efb8c167330.png)

まれに100%未満となる。重みの初期値によって結果が変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/339bc64e-830c-e877-606f-7aad42671940.png)

#おわりに
本記事ではLabVIEWを使ってパーセプトロンによる分類をおこないました。
LabVIEWの標準関数を使用することでまったく問題なく処理を実装することができました。
TypeScriptでチェックが入ったチェックボックスの値のみを取得する方法

## 実現したいこと
「チェックボックスにチェックをして、削除ボタンを押すと、チェックされた項目が一括削除される」という、よくある処理をTypeScriptで行いたい。
そのためには、**チェックボックスにチェックの入った要素だけ**を取得する必要がある。

![スクリーンショット 2021-01-24 19.31.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518222/34e85fb7-b457-67a0-ad1c-a3169b907ad2.png)

## 結論
**チェックボックスのHTML**

```index.html
<td><input type="checkbox" name="checkBox" value="1"></td>
<td><input type="checkbox" name="checkBox" value="2"></td>
<td><input type="checkbox" name="checkBox" value="3"></td>
<td><input type="checkbox" name="checkBox" value="4"></td>
```

**チェックボックスにチェックの入った要素を配列で返す関数**

```App.ts
const checkBoxes = document.getElementsByName('checkBox');

const checkedArray = (checkboxes: NodeList): HTMLElement[] => {
    let resultArray: HTMLElement[] = Array.prototype.slice.call(checkboxes).filter(checkbox => checkbox.checked)

    return resultArray
}

checkedArray(checkBoxes)
```

## 解説

まずは、チェックボックス全部を取得します。

```App.ts
const checkBoxes = document.getElementsByName('checkBox');
```

次に、取得した要素(checkBoxes)の中から、チェックの入った要素のみを配列で返す関数を作ります。
[ドキュメント](https://developer.mozilla.org/ja/docs/Web/API/Document/getElementsByName)にある通り、`getElementsByName`は`NodeList`を返すので、

```App.ts
const checkedArray = (checkboxes: NodeList): HTMLElement[] => {
}
```
引数を`NodeList`型に指定して、返り値を`HTMLElement`の配列に指定します。

引数として渡ってきたcheckboxesの中からチェックの入った要素のみを判別して配列に入れたいのですが、

```App.ts
let resultAry: HTMLElement[] = checkboxes.filter(checkbox => checkbox.checked)
// => Property 'filter' does not exist on type 'NodeList'.
```
`NodeList`に`fileter`は使えないとエラーが出ます。

なので、

```App.ts
let resultAry: HTMLElement[] = Array.prototype.slice.call(checkboxes).filter(checkbox => checkbox.checked)
```
`Array.prototype.slice.call()`を使って`filter`で`checked`の要素のみを配列に入れます。

あとは結果の配列を`return`すればOK👍🏻

```App.ts
const checkedArray = (checkboxes: NodeList): HTMLElement[] => {
    let resultArray: HTMLElement[] = Array.prototype.slice.call(checkboxes).filter(checkbox => checkbox.checked)

    return resultArray
}
```

## いざ実行

![スクリーンショット 2021-01-24 20.55.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518222/1bdf5e29-9e5a-5ace-bf7f-899208635b88.png)

```App.ts
let checkedElements = checkedArray(checkBoxes);
console.log(checkedElements);
```
以下の要素がコンソールに出力される

```console
<td><input type="checkbox" name="checkBox" value="1"></td>
<td><input type="checkbox" name="checkBox" value="3"></td>
```

## 1/25 追記
@vf8974 様より、コメントでウルトラ超シンプルな記述を教えていただきました！

```App.ts
const checkBoxes = document.querySelectorAll('input[type=checkbox]:checked');
```
1行で書けた…

ここから値を取り出して配列にしたい時は、

forEachを使ったり、

```App.ts
const checkBoxes = document.querySelectorAll('input[type=checkbox]:checked');

let values = [];
checkBoxes.forEach(node => values.push(node.nodeValue));

console.log(values);
// ["1", "3"]
```

mapを使えばいい感じ。

```App.ts
const checkBoxes = document.querySelectorAll('input[type=checkbox]:checked');

let values = Array.prototype.slice.call(checkBoxes).map(element => element.value);

console.log(values);
// ["1", "3"]
```


## バージョン情報
TypeScript 4.1.3
Puppeteerで3rd-party cookieを保存・利用する

Puppeteerで3rd-party cookieを保存・利用したい場合の処理についてまとめました。ログイン処理がクロスサイトになっているWebページをPuppeteerで利用する場合など、以下で紹介するコードが必要になることがあります。

## cookieのセーブ

cookieを保存するファイルをtmpdirに作る方針のコードです。別のパスに保存する場合はよしなに変更してください。

```javascript
const os = require('os');
const path = require('path');
const fs = require('fs').promises;

/*（中略）*/

    try {
      const client = await page.target().createCDPSession();
      const allBrowserCookies = (await client.send('Network.getAllCookies')).cookies;
      const cookiePath = path.join(os.tmpdir(), 'cookies.json');
      await fs.writeFile(cookiePath, JSON.stringify(allBrowserCookies, null, 2));
    } catch(err) {
      // do nothing
      console.log(err)
    }
```

このコードのポイントはCDP (Chrome DevTools Protocol)のメソッドを呼び出してcookieを取り出している部分です。`page.cookies()`だと現在のURLに紐付いているcookieしか返してくれないので、3rd-party cookieが必要な場合は使えません。CDPのプロトコルメソッド`Network.getAllCookies`なら全cookieを取り出せます。

## cookieの読み込み・利用

cookieの読み込みは特に注意点はありません。

下記コードではファイルが見つからなかったときのエラーを無視していますが、仕事のコードならもう少し真面目にエラー処理を書いた方がいいと思います。

```javascript
const os = require('os');
const path = require('path');
const fs = require('fs').promises;

/*（中略）*/

    try {
      const cookiePath = path.join(os.tmpdir(), 'cookies.json');
      const cookiesString = await fs.readFile(cookiePath);
      const cookies = JSON.parse(cookiesString);
      await page.setCookie(...cookies);
    } catch(err) {
      // do nothing
      console.log(err)
    }
```

## 元ネタ
 - [javascript \- Puppeteer get 3rd\-party cookies \- Stack Overflow](https://stackoverflow.com/questions/50252943/puppeteer-get-3rd-party-cookies/50290081)
デベロッパーツールでWebサイトの見た目を変更したまま更新しても維持する方法はあるのか

先に述べますが、表題そのままの解決ができたわけではありません。
発生した課題の解決自体はできています。

## やりたかったこと

-ChromeのデベロッパーツールでWebサイトのスタイルシートを好みの状態にイジった後、更新したり再度訪問してもその状態を維持したい
-（具体的には）Twitter Webの右側にあるトレンドを消し去りたかった。タイムラインで情報は追いかけたいが、トレンドは嫌でも目について気が散ってしまう

## 通常の検索でわかったこと

-「デベロッパーツール」を軸にしたキーワードで検索
-デベロッパーツールでsave overrideをすることで、更新・再訪問しても、デベロッパーツールを開けば変更した状態を維持できるが、デベロッパーツールを開いていない状態では変更は反映されない

## 検索方法を変えてわかったこと

-拡張機能も検討したが、「デベロッパーツールの固定」といったキーワードではやはり見当たらない
-そもそも直で「twitter トレンドエリアを消す　デベロッパーツール」と検索したところ、[こちら](https://www.gcmstyle.com/howto-twitter-trend-display-none/)のサイトがヒット

## 使った拡張機能

[Stylus](https://chrome.google.com/webstore/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne?hl=ja)

## 学んだこと

-実は当初は拡張機能も探していたが、思いつく限りの検索ワードでは「過去に使えていたXXXという拡張機能が今は使えない」というような記事しかHitしなくて諦めていた
-今回のように「ツイッターのトレンドエリアを消す」といったような、全く別の検索アプローチ－－ユーザーの多いコンテンツを軸に何らかの状況を限定した想定－－で目当てのものが見つかることもある。今回はもともとの目的のキーワードでHitしたからよかったものの、情報自体はネットに転がっているが、そのキーワードおよび存在自体を知らない場合もあるので、やはり幅広い知識を持つことは重要である

## さいごに
-参考先ページにもあるが、ChromeだけでなくFireFoxでも利用可能　[Stylus（FF版）](https://addons.mozilla.org/ja/firefox/addon/styl-us/)
-ググり方の上手さが大事だというが、ここまで斜めだとは思わなかった
Firebase Cloud Functionsで"Error: Could not start Functions Emulator, port taken."の対処法

Firebaseで`firebase emulators:start`コマンドが失敗するときの対処法について。

```tarminal:tarminal
>firebase emulators:start
i  emulators: Starting emulators: functions, hosting
⚠  hub: emulator hub unable to start on port 4400, starting on 4401 instead.
⚠  emulators: It seems that you are running multiple instances of the emulator suite for project mynarration-20210110. This may result in unexpected behavior.
i  emulators: Shutting down emulators.
i  hub: Stopping emulator hub
⚠  functions: Port 5001 is not open on localhost, could not start Functions Emulator.
⚠  functions: To select a different host/port, specify that host/port in a firebase.json config file:
      {
        // ...
        "emulators": {
          "functions": {
            "host": "HOST",
            "port": "PORT"
          }
        }
      }
i  emulators: Shutting down emulators.

Error: Could not start Functions Emulator, port taken.
```

ポートがすでに使われていることが原因。
一度killしてプロセスを開放する必要がある。

4400で起動したいがすでに占有されているので下記コマンドでkill

```tarminal:tarminal
lsof -t -i tcp:4400 | xargs kill -9
```

下記コマンドで起動できるようになった

```tarminal:tarminal
firebase emulators:start
```
[iOS]FlutterでHTTPレスポンスのバイトデータをUTF-8にdecodeできない問題の解決方法

趣味でFlutterを使ってアプリを作っている際にHTTPレスポンスのバイトデータをUTF-8にデコードする際に詰まったので解決方法を共有します。

# 問題
WebViewで指定したURL(以下targetURL)を表示する前にページの内容を確認する場合、以下のようにHTTPレスポンスのバイトデータをUTF-8でdecodeし文字列に変換したい場面がありました。
response.bodyをそのまま扱おうと思いましたが、後述同様に詰まりました。
下記は[この記事](https://qiita.com/takyam/items/98d6336f1b2fe912fd56)を参考にしています

```dart:issue
var response = await http.Client().get(Uri.parse(targetURL), headers: {'User-Agent': userAgent});
String decoded_body_byte = await CharsetConverter.decode("UTF-8", response.bodyBytes); // charset_converter: ^1.0.3
print("decoded_body_byte: ${decoded_body_byte }"); // decoded_body_byte: nullとなる
```
上記をiOS Deployment Target=9.0でPhone12 Pro Maxのエミュレータで実行した結果、3行目のコメントにあるようにUTF-8でdecodeされたHTML文字列が格納されている想定のdecoded_body_byteはnullとなってしまいました。
AndroidのPixel 2のエミュレータでは問題なくdecodeできていたのでiOS特有の問題かと思います。
2行目を以下1.2.に置き換えてもしてもこの行以降にプログラムが進まなくなってしまいました。


```dart:試行1
var decoded_body_byte = utf8.decode(response.bodyBytes); // この行以降進まない
```
```dart:試行2
var decoded_body_byte = Utf8Decoder().convert(response.bodyBytes); // この行以降進まない
```
# 解決方法
原因はdecode対象のHTTPレスポンスボディにUTF-8にとって不正な文字列が含まれていたことのようです。
bodyBytesに`sublist(start, end)`メソッドを用いて一部分のdecodeを試みたところ成功した及び以下のコードで成功したことが上記推測の根拠です。

```dart:solution
var decoded_body_byte = Utf8Decoder(allowMalformed: true).convert(response.bodyBytes);
```
[Utf8Decoder](https://api.flutter.dev/flutter/dart-convert/Utf8Decoder-class.html)の`allowMalformed: true`とする事により、UTF8の不正文字置換オプションを有効化できたことが効いたようです。

皆様の参考になれば幸いです。

もしよろしければ以下アプリを使ってみていただければ幸いです。
評価いただければ更に嬉しく思います。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ひたすらこのアプリを作っています<a href="https://t.co/FrseksoEgS">https://t.co/FrseksoEgS</a></p>&mdash; ponyo877 (@ponyo877) <a href="https://twitter.com/ponyo877/status/1353270345600389121?ref_src=twsrc%5Etfw">January 24, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Adobe Auditionのマルチトラックセッションから複数の設定でミックスダウンしエクスポートするExtendScriptスクリプト

# Adobe Auditionのマルチトラックセッションから複数の設定でミックスダウンしエクスポートするExtendScriptスクリプト
## やりたいこと
- 例えばボイスドラマの編集と書き出しをやっており、次のような設定で最終出力したいとします。
  - SEなし、MP3
  - SEなし、PCM
  - SEあり、MP3
  - SEあり、PCM
- 12トラックあると48回の出力作業。設定間違えやすいので楽にしたい。

## 環境

- iMac (Retina 4K, 21.5-inch, 2019) macOS Big Sur 11.1
- Adobe Audition 2020
- Visual Studio Code


## Auditionでスクリプティング
- Auditionでは、「ファイル」-「スクリプトを参照して実行」でjsxファイルを実行できます。ExtendScriptというAdobeに独自拡張されたJavaScriptです。
- デバッガとしてVisual Studio Code拡張機能でExtendScript Debuggerが供給されています。

## 実例
- Auditionにはセッションテンプレートという機能があり、そこでトラック2〜5はSEに設定してあるという想定です。実際には名前で判断したほうがいいかもですね。

```js

var document;
var minSeTrack = 2;
var maxSeTrack = 5;

function main() {
  if (app.name.indexOf("Audition") < 0) {
    alert("Audition用のスクリプトです", "エラー", true);
    return;
  }
  document = app.activeDocument;
  if (!document) {
    alert("アクティブなドキュメントがありません", "エラー", true);
    return;
  }
  if (document.reflect.name != "MultitrackDocument") {
    alert("マルチトラックセッションを選択してください", "エラー", true);
    return;
  }
  var fileNameWithoutExt = document.path.substr(0, document.path.lastIndexOf("."));
  setSeTrackActive(false);
  mixdownAndSave(fileNameWithoutExt + "_noSe");
  setSeTrackActive(true);
  mixdownAndSave(fileNameWithoutExt + "_Se");
  setSeTrackActive(true);
  app.invokeCommand("File.CloseUnusedMedia");
  alert("変換完了しました", "完了", false);
}
function setSeTrackActive(isActive) {
  for (var i = 0; i < document.audioTracks.length; i++) {
    var isMute = false;
    if (minSeTrack <= i && i <= maxSeTrack) isMute = !isActive;
    document.audioTracks[i].mute = isMute;
  }
}
function mixdownAndSave(name) {
  var num = app.documents.length;
  app.invokeCommand("Multitrack.MixdownAllToNewFile");
  while (num == app.documents.length) {
    $.sleep(500);
  }
  var mixdown = app.documents[app.documents.length - 1];
  saveAs(
    mixdown,
    new AudioFileFormat(AudioFileFormat.FORMAT_WAVE_PCM),
    name + ".wav"
  );
  saveAs(
    mixdown,
    new AudioFileFormat(AudioFileFormat.FORMAT_MP3_),
    name + ".mp3"
  );
  document.activate();
}

function saveAs(target, audioFileFormat, filename) {
  var params = new WaveDocumentSaveAsParameters();
  params.fileFormat = audioFileFormat;
  params.includeMetadata = true;
  params.sampleTypeConversion = null;
  target.saveAsDocument(filename, params);
  while (target.isBusy) {
    $.sleep(500);
  }
}

main();
```

## 参考にしたもの
- まともな情報がありません。ディベロッパーコンソール https://console.adobe.io/apisandservices からAdobe Audition SDKが落とせて、その中に入ってるJSXでCommands.jsx,ScriptDictionary.jsx,ScriptDictionary2html.jsx,ScriptDictionaryElements.jsx,utils.jsxを使うと、app.invokeCommandに投げるAudition固有のコマンド文字列とクラスライブラリのドキュメントが一応得られますので、それを読んで頑張れば結構色々出来ます。
  - リフレクションで情報を取得して出力しているらしい。リフレクションを自分で使って解析もある程度は出来そうです。昔Sketchプラグインの仕事で似たようなことしてた経験が生きた。
- ExtendScript共通のクラスや関数、使い方についてはこちら。 https://extendscript.docsforadobe.dev/extendscript-toolkit/index.html 特にExtendScript Tools and Featuresのところから飛べる奴は最初に読んでおくべきかも。

## 次にやること
- 台本処理のrubyスクリプトから何かしら吐いてそれを元に自動でリソースを取り込んでいい感じに連結して準備してくれるツールを作ろうと思っています。
Gatsbyのページ間でのリンク

aタグを使ってリンクを作るのではなく、リンクコンポーネントを使う。
#使い方
##Linkコンポーネントをインポートする
```react
import React from "react"
import {Link} from "gatsby"
```
##Linkタグを記述
```react

const Home = () => {
    return (
        <div>
            <Link to="/about">About Me</Link>
            <Link to="/">Topへ</Link>
        </div>
    )
}

export default Home
```

#次回
**ページごとにテキストを変更？**
RHEL8にCUDAを入れる

#RHEL8にCUDAを入れる
RHEL8をインストールしたがCUDAが上手くインストールできなかったので、メモ的に残しておく。

#下準備
下記により必要な物をインストールする。

```
sudo dnf install kernel-devel
sudo dnf install make pciutils acpid libglvnd-devel
```

その後めんどうを防ぐため、下記を行う。

```
mkdir nv-driver
cd nv-driver
```

[こちらの公式HP](https://developer.nvidia.com/cuda-downloads)より最新のCUDAツールキットを確認し、wgetする。
rpm(local)を選択する。

#NVIDIA公式HPの記載
NVIDIA公式HPにはwgetの後、下記の様に記載されている。

```
sudo rpm -i cuda-repo-rhel8-11-2-local-11.2.0_460.27.04-1.x86_64.rpm
sudo dnf clean all
sudo dnf -y module install nvidia-driver:latest-dkms
sudo dnf -y install cuda
```

しかし、このまま行うと、sudo dnf -y module install nvidia-driver:latest-dkmsの時点でエラーが出る。
dkmsがRHELのデフォルトのリストにないからだと思われる。

#dkmsのインストール準備
dkmsをインストールするためには、epelを有効にしなければならない。
epelを有効にするには、まず下記のとおりインストールする。

```
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y
```
その後、下記のとおり有効にする。

```
sudo yum config-manager --enable epel*
```
```
sudo yum repolist all | grep -i epel
```
で有効になっていればOK。

その後、下記を行う。

```
sudo yum install epel-release
```
これで準備は整った。

#CUI環境にする
nouveauをブラックリストにし、再起動してCUI環境からログインする。
方法はネットにいくらでも転がっているので、それを参考にする。

#CUDAのインストール

```
sudo rpm -i cuda-repo-rhel8-11-2-local-11.2.0_460.27.04-1.x86_64.rpm
sudo dnf clean all
sudo dnf -y module install nvidia-driver:latest-dkms
sudo dnf -y install cuda
```
をCUI環境でうちこみインストールする。
エラーがでなければOK。

#GUIへ戻る

```
sudo systemctl set-default graphical.target
reboot
```
でGUIに戻れば無事CUDAが使用できる。
Localtunnel 設定

# 概要
 - k8sテスト環境構築<br>
<b>Localtunnel インストール</b><br><br>

`Localtunnel`を利用し、ローカル環境を外部公開する
[`ngrok`](https://ngrok.com/)を使っても良い

# 構築目次
 - [全体目次] (https://qiita.com/prodigy413/items/89fcb8cfb71e80f541d8)

# 環境
 - Rancher: v2.6.3
 - kubernetes(Client): v1.22.4
 - kubernetes(Server): v1.22.4
 - Localtunnel: v2.0.2

# 前提条件
 - MetalLB インストール済み<br>
[MetalLB インストール] (https://qiita.com/prodigy413/items/3a24ff85819dc5eafe25)

# インストール
 - 作業場所: ClientPC
 - Localtunnel Install Page<br>
https://github.com/localtunnel/localtunnel<br>

### Localtunnel インストール
npmを利用するが、コマンドがない場合は`sudo apt install npm`でインストール

~~~
## インストール
$ sudo npm install -g localtunnel

## バージョン確認
$ lt --version
2.0.2
~~~

### 動作確認
 - PodとService作成<br>
- `Service`の`type`は`LoadBalancer`
- 本環境では`LoadBalancer`として`MetalLB`を利用<br>
※インストールは<b>[ここ](https://qiita.com/prodigy413/items/3a24ff85819dc5eafe25)</b>参照

~~~yaml:test-nginx.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  type: LoadBalancer
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.21.4
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
~~~

 - manifest適用

~~~
$ kubectl apply -f test-nginx.yaml
~~~

 - Localtunnel 実行

~~~
## LB IP(EXTERNAL-IP)を確認
$ kubectl get svc
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)        AGE
..........
nginx-svc    LoadBalancer   10.43.98.164   192.168.245.113   80:31486/TCP   8s
..........

## Manifestで設定したポートとIPを指定してLocaltunnel実行
## urlを確認
$ lt --port 80 --local-host 192.168.245.113
your url is: https://fat-dragonfly-30.loca.lt
~~~

 - Access 確認  

~~~
## 上記のurlでアクセス確認
$ curl -I https://fat-dragonfly-30.loca.lt
HTTP/2 200
..........
~~~
pydicomで圧縮されたDICOM画像を見る

#目的
**圧縮されたDICOM画像をpydicomで読み込み表示させる．**
普通にpydicomで圧縮されたDICOM画像を読み込もうとすると，以下のようなエラーを吐いたので参考までに．

エラーに対する解決方法を書きましたが読むのが面倒くさい方は，`面倒な人向け`と`環境`に載っているものと同じバージョンのライブラリをインポートして`完成版`でコンパイルしてみてください．

#環境
**・Windows 10**
**・Visual Studio Code**

・pip                    21.0
・numpy                  1.19.5
・matplotlib             3.3.1
・Pillow                 7.2.0
・opencv-python          4.4.0.42
・pydicom                2.1.2
・pylibjpeg              1.1.1
・pylibjpeg-libjpeg      1.1.0
・pylibjpeg-openjpeg     1.0.1

**注意事項**
Macでも同じことをしようとしましたが，gdcmがインポートできませんでした．
調べたら他に方法があるかもしれないので，見つけた方はぜひ教えて下さい．

#エラー内容
<details><summary>**1つ目のエラー**</summary><div>

</div></details>

```python:
`RuntimeError: The following handlers are available to decode the pixel data however they are missing required dependencies: GDCM (req. GDCM)`
```
コマンドプロンプトで`pip install gdcm`をインポートで解決


<details><summary>**2つ目のエラー**</summary><div>

</div></details>

```python:
`RuntimeError(msg + ', '.join(pkg_msg))`
```
コマンドプロンプトで`pip install pylibjpeg`をインポートで解決


<details><summary>**3つ目のエラー**</summary><div>

</div></details>

```python:
`ImportError: DLL load failed: 指定されたモジュールが見つかりません。`
```


コマンドプロンプトで`pip install pylibjpeg`をインポートしてコンパイルしたところ3つ目のエラーが．．．
いろいろ調べて試した結果，pydicomのバージョンをアップデートしたところ直りました．

コマンドプロンプトで`pip install -U pydicom`を入力
私の場合，`pydicom-2.0.0 → pydicom-2.1.2`にバージョンアップしました．

もう一度，コンパイル．
ここで，`pylibjpeg-libjpeg`のモジュールが無いと言われたら，コマンドプロンプトで`pip install pylibjpeg-libjpeg`を入力し，もう一度コンパイル．

**これで無事，画像が表示されました！**

#面倒な人向け
コマンドプロンプトでとりあえず以下を入力しておく．
1.`pip install pydicom`
2.`pip install numpy`
3.`pip install matplotlib`
4.`pip install gdcm`
5.`pip install pylibjpeg`
6.`pip install pylibjpeg-libjpeg`
7.`pip install Pillow`
8.`pip install opencv-python`


#完成版
```python
import pydicom
import numpy as np
from matplotlib import pyplot as plt
import pylibjpeg

path = "パスを入力"
compressed_Data = pydicom.read_file(path)

#表示
plt.imshow(compressed_Data.pixel_array, cmap = "gray")
plt.show()
```
PlantUMLでER図を描いてみる


# 必要なもの

- エディタ
  - VSCode
- VSCodeプラグイン
  - [PlantUML](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml)

# 環境構築

DockerでPlantUMLが動く環境を構築する。

## PlantUML Serverを起動

- [plantuml-server](https://hub.docker.com/r/plantuml/plantuml-server)

```bash
docker run -d --name plantuml_server -p 8080:8080 plantuml/plantuml-server:jetty
```

## VSCodeの設定

プラグインのPlantUMLにカーソルを合わせて右クリック→Extension Settings。

| 設定項目         | 値                    |
| ---------------- | --------------------- |
| Plantuml: Render | PlantUMLServer        |
| Plantuml: Server | http://localhost:8080 |

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/de6ee838-431a-6ca8-7f50-7d1f658ed2b9.png" width="400px" /><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/38b34323-5dad-bab8-6050-d4b2dcfa3445.png" width="400px" />

# 単一テーブルを作成する

```java
@startuml ""

Class "order:注文" as order <<T,FFAA00)>> {
  + order_id: 注文ID [PK]
  ---
  order_date: 注文日
  product_code: 商品コード [FK]
  customer_code: 顧客コード [FK]
  quantity: 数量
  created_at: 作成日
  updated_at: 更新日
}

@enduml
```

![スクリーンショット 2021-01-24 20.17.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/2d40242a-12df-2f50-8b63-2bd2fea4c724.png)

プレビューはMacだと「オプション + D」で開きます。

# 複数テーブルを作成してリレーションを引いてみる

```java

@startuml ""

!include ./order.pu
!include ./customer.pu
!include ./product.pu

product "1..*"--ri--"1" order
order "1..*"--ri--"1" customer

@enduml
```

![スクリーンショット 2021-01-24 20.18.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/76253056-1bcc-0411-1555-289251c6e291.png)

# レイアウトの方向

| 方向 | キーワード |
| ---- | ---------- |
| 上   | up         |
| 下   | do         |
| 左   | le         |
| 右   | ri         |

# 参考

- [PlantUML で ER 図（ERD）を描く（似非ではないです）](https://qiita.com/Tachy_Pochy/items/752ef6e3d38e970378f0)
listen tcp 0.0.0.0:xxx: bind: address already in us の対処法

##目的
Ruby on Railsでポートフォリオを作成していた途中にdocker-compose upをした際に、<strong>listen tcp 0.0.0.0:xxx: bind: address already in us</strong>とエラーが出たのでその時の対処方法を忘れないように書きます。

##エラー内容
```
$ docker-compose up -d
-------------------------
-------------------------
Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use
ERROR: Encountered errors while bringing up the project.
```

##対処方法
最初にこのコマンドを打ちます。

```
$ sudo lsof -i -P | grep "LISTEN"

name1   633      ~~~~~~   10u  IPv4 0xc46fc72c3028ba51      0t0  TCP localhost:49362 (LISTEN)
name2   634      ~~~~~~   53u  IPv6 0xc46fc72c50688ca1      0t0  TCP *:3000 (LISTEN)
name3   96145    ~~~~~~   54u  IPv6 0xc46fc72c506892c1      0t0  TCP *:3306 (LISTEN)
name4   72412    ~~~~~~   82u  IPv4 0xc46fc72c4cf4e591      0t0  TCP localhost:62741 (LISTEN)

```
エラー内容は3306ポートはすでにあるよと言われています。
なので3306ポートをkillします。

```
$ sudo kill -9 96145
```
これでdocker-compose upができます！！
【Python】行列の積 〜pypy〜用【AtCoder】

ABC189
[E - Rotate and Flip](https://atcoder.jp/contests/abc189/tasks/abc189_e)
ででてきた行列の積

今後のためにも行列の積の定義をfor文で作った
※np.dotよりも処理速度速い気がする　〜pypy用〜

#行列の積
```python:test.py
def dot_nm(a,b):
    n,l,m = 3,5,2
    return [[sum([a[i][k]*b[k][j] for k in range(l)]) for j in range(m)] for i in range(n)]
def dot_n1(a,b):
    n,l = 3,2
    return [sum([a[i][j]*b[j] for j in range(l)]) for i in range(n)]
def dot_1m(a,b):
    l,m = 4,2
    return [sum([a[j]*b[j][i] for j in range(l)]) for i in range(m)]

print('---pypy---')
print(dot_nm([[2,1,9,5,1],[3,5,-2,-1,-9],[7,9,0,6,5]], [[4,6],[1,1],[-3,4],[3,1],[9,3]]))
print(dot_n1([[2,1],[3,5],[7,9]], [4,6]))
print(dot_1m([3,4,-7,1], [[2,1],[3,5],[9,8],[8,6]]))
print('---numpy---')
import numpy as np
print(np.dot([[2,1,9,5,1],[3,5,-2,-1,-9],[7,9,0,6,5]], [[4,6],[1,1],[-3,4],[3,1],[9,3]]))
print(np.dot([[2,1],[3,5],[7,9]], [4,6]))
print(np.dot([3,4,-7,1], [[2,1],[3,5],[9,8],[8,6]]))
```
![スクリーンショット 2021-01-24 20.32.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/785975/691d75d7-e845-6a5b-ca6c-5398f1cae1fb.png)




おわり！！！
pg_hba.confファイル内のクライアント認証の優先順位

「現場で使える Ruby on Rails 5 速習実践ガイド」のChapter 6-9-3 「production環境用のデータベースを作成する」で詰まったのでメモ書きします。

###### 実行環境
PostgreSQL 10.15
Ruby 2.7.1
Vagrant 2.2.9
CentOS 7.8.2003

###### 問題点
production環境用のデータベースを作成する以下のところでエラー発生

```
RAILS_ENV=production bin/rails db:create db:migrate
```

原因はPostgreSQLのユーザー認証がパスワード認証になっていないことのようだった。

###### 修正点
修正にはpg_hba.confというファイルを書き換えてパスワードを使った認証ができるように、設定する必要があるようだった。

ユーザーtaskleafはパスワード認証、元々使っていたユーザーvagrant, rootはそのままにしておきたかったので、できないか調べたところ、pg_hba.confは上方にある記述が優先されるとの記載があった。

>接続形式、クライアントアドレス、要求されたデータベース、およびユーザ名に一致する最初のレコードが認証処理に使用されます。

[リンク：日本PostgreSQLユーザ会](https://www.postgresql.jp/document/8.2/html/auth-pg-hba-conf.html)

以下のようにmd5(パスワード認証にするための設定)の行を追加、
vagrant, rootユーザーは元のとおりpeerに設定して意図どおり修正できた。
修正前

```:pb_hba.conf
# listen on a non-local interface via the listen_addresses
# configuration parameter, or via the -i or -h command line switches.
local   all             all                                     peer
```

修正後

```:pb_hba.conf
# listen on a non-local interface via the listen_addresses
# configuration parameter, or via the -i or -h command line switches.
local   all             vagrant                                 peer
local   all             root                                    peer
local   all             all                                     md5
```
EC2インスタンスのJupyter Notebookにローカルのブラウザから接続する

# 初めに
atmaCup オンサイトデータコンペ #9 に参加するにあたって、AWSのg4dnを動かしたいと思った。
(Azure使いたい!枠で参加表明しているので、計算資源には困らない)
手順を残しておこうと思い、自分用のメモとしてこの記事を書くことにした。
メモなので、雑に書いてる。

本来、ある程度自動化するべき内容なのだろうけど...。


# 手順など

GPUインスタンスを初めて作るときは、予めGタイプのインスタンスを作れるようにしておくこと

## インスタンスを作成する

コンソールから上げた。Deep Learning AMI を選ぶ。Deep Learning AMI (Ubuntu 18.04) Version 39.0を選択した。

![Screenshot_2021-01-24 インスタンスウィザードを起動 EC2 Management Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/948481/0a647182-36ec-b40e-5ece-4f9b2d92bf53.png)

## 接続

二つの方法で実施(Windowsから接続する。)

* git bashから接続する
* [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) をインストールして、EC2へ接続する

# 設定など

[AWSの公式ドキュメント](https://docs.aws.amazon.com/ja_jp/dlami/latest/devguide/gs.html)を読みながら実施。

Anacondaが入っていて、すでに仮想環境がいくつか作られているので、それを使うのが楽だと思う。

Jupyter のほうも、AWSのドキュメント(https://docs.aws.amazon.com/ja_jp/dlami/latest/devguide/setup-jupyter.html) にきっちり書いてあるので、これを見れば設定できるはず。

EC2インスタンスとローカルの間にトンネルを作るためにgit bashから操作した。

それも書かれていた。(https://docs.aws.amazon.com/ja_jp/dlami/latest/devguide/setup-jupyter-configure-client-linux.html)

```bash

$ ssh -i /c/Users/ユーザ名/.ssh/証明書.pem -N -f -L 8888:localhost:8888 ubuntu@xxxxx
```

# 接続確認

```
https://localhost:8888
```
に接続して、接続できるか確認する。オレオレ証明書を使っていたら、警告が出るが無視。
ZabbixによるWindows監視- CPU監視

##1.WindowsタスクマネージャのCPU使用率
WindowsServerのタスクマネージャを開くと、CPUの使用率を見ることが出来るが、Zabbixサーバで取得した値と異なる値が取得できます。
実は、この値はCPUコアの一番使用率が高い値を表示しているだけであって、Zabbixサーバでは、全体の使用率平均値を取得しているため、タスクマネージャとは異なる値を取得してしまいます。

##2.リソースマネージャ
Windows上で平均値を確認したい場合は、リソースモニターを開くと確認することが出来ます。リソースモニターはWindowsのタスクマネージャから、[パフォーマンス]タブを開くと[リソースモニターを開く]があり、クリックすると、リソースモニターを起動することが出来ます。
![task.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/9c9bcc3c-12af-2812-2f56-35235a3ecca3.png)


リソースモニターでは、CPU以外に、ディスク、メモリ、ネットワークを詳細にモニターすることが出来ます。
![リソースモニタ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/92521556-0864-6180-5a7d-bfa81c1a3e71.png)




##3.CPU使用率の設定
ZabbixAgentとZabbixServerのインストールと監視対象のホスト登録後のアイテムとトリガーの設定ですが、以下のようにおこないます。

#####1. アイテムの作成

アイテムは、[Configuration]-［Hosts］(またはTemplate)から設定対象をクリックします。
![select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/186edaf2-d3ec-e37a-400f-ddbfa95b2f06.png)


[item]タブに移動し、右上の[Create Item]をクリックして、新しいアイテムを作成します。
![item select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/d591a5db-9888-059e-117a-8de6791e2522.png)

値を入力してアイテムを作成します。
Name:なんでもいいです。
Tyep: Zabbix Agent
Key: system_cpu_util[All,system,avg1(１分間の平均値、10avgなどで10分間の平均値にすることも可能)]
Type of Information:Numeric(unsigined)
Units:%
Update interval:30s (CPU使用率の取得タイミングなので、任意の値でいいです。)
![item create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/9842a9bc-a04c-8dbb-3a3d-33c547e92b4d.png)


[Monitoring]-[Latest data]を開き、対象のホストの最新データ一覧を開きます。
CPUの使用率を確認することができます。
(設定直後だと、値を取得できていないため、1-2分後に確認する。)
![lastdata.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/72a685c9-c403-9a15-f0f6-394ce49dcf81.png)



#####2. トリガーの作成
トリガーはアイテム作成より自由値が高いため、一例となります。

[Configuration]-［Hosts］(またはTemplate)から設定対象をクリックします。
![select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/fb9bad52-546b-f145-873b-47d646825691.png)

[triggers]タブに移動し、右上の[Create Trigger]をクリックして、新しいトリガーを作成します。
![select triger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/ed2c0987-43b4-73ef-364e-444872d61921.png)

値を入力してトリガーを作成します。
Name:なんでもいいです。
Severity:障害レベルを選択する。
Expression:5回連続で90%以上の値を取得した場合、アラートを上げる
{WindowsServer2016:system.cpu.util[,system,avg1].count(#5,90,ge)}=1
Allow manual close:有効　(これを有効にしないと主導でクローズが出来なくなる。)
![create triger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/af19185e-550a-079a-09c1-dfca5cf2cb77.png)


実際に、90%以上の値を出し続けていると、[Monitoring]-[Problem]でアラートを確認することが出来ます。
![アラート２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226209/286093a5-89c2-5d43-8e03-99943d2aa885.png)


##4.参考URL
- Zabbix 4.0 マニュアル
https://www.zabbix.com/documentation/4.0/manual