OmniAICreator/Qiita-1.07M huggingface dataset:
ペーパーレスファックスの構築 (1)

# 概要
ファックス使ってますか？
何かと生産性を阻害する元凶のように扱われがちなファックスですが、そうは言っても相手のあることなので、まだまだファックスの出番は多いです。
ファックスのペーパーレス化もだいぶ進んできて、専用のサービスもありますが、今回はPower Automateによってペーパーレス化した事例を取り上げます。

## 紙によるファックスの何が問題か
ざっと思いつくところでこんなところでしょうか。
- 紙をなくしてしまう
- いらないファックスまでプリントアウトして、紙代やカウンター代がかかる
- ファックスの宛先の人に届ける手間がかかる

特に３番目の、紙を届けるというのが邪魔くさいです。同じフロアの見渡せる範囲だけであればまだいいのですが、隣の建物まで持っていくとか、以前はよくありました。
雨や雪の日なんかは最悪です。

## 方針
- ファックスの受信文書を誰でも見れるようにする。
（セキュリティ上好ましくないようであれば、アクセス権を考慮する必要があります。うちは少人数なので、まあ...）
- 総務が確認して、受信者に割り当てる。
- 保管期限が切れたら、自動的に削除する
補完する必要がある文書は、ファイルサーバー等に保存しておく

上記を実現するため、ファックスを受信したらSharePointの決まったフォルダに保存し、SharePointにファイルが保存されたら、Plannerにタスクを生成しファイルを添付します。
Plannerのタスクに添付されたファイルを総務が確認して、受信者に割り当て、受信者は内容を確認して必要な処理を行ったらタスクを完了します。
完了したタスクは定期的に添付ファイルを含めてクリーンアップします。

なお、ファックスをSharePointに保存する部分は、リコーのカンタンファックス仕分けを利用しています。
[RICOH カンタンファックス仕分け for Cloud](https://www.ricoh.co.jp/service/kantan-fax-shiwake-for-cloud)

![paperless.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244231/d19e079d-e20f-eea7-122e-71a5b2fd821c.png)

# 完成図
受信したファックスは Planner のタスクとして管理し、Microsoft Teams のタブに表示させています。
![2022-07-02_17h15_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244231/09d572f7-b858-6d43-de63-d67c8733a236.png)

# 次回の予定
ファックスの受信文書をSharePointに保存する部分は、以前は複合機の標準機能で専用のアドレスへメール送信して、専用アドレスでメールを受信したらSharePointに保存させていましたが、たまに飛ばないときがあったりしたため、別途料金は発生しますが「カンタンファックス仕分け」を利用することにしました。（仕分ける機能は使っていません。全部同じフォルダに入れてます）
この辺は複合機のメーカーや機種によってもやり方が変わってくると思いますので、ここでは触れません。

次回以降は、SharePointに保存したあとのPower Automateで構築しているフローについて紹介する予定です。
[OutSystems]Unicodeの文字を正規化する話

最近仕事で文字コード関連のことを検討していて、改めて[プログラマのための文字コード技術入門](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E6%96%87%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89%E6%8A%80%E8%A1%93%E5%85%A5%E9%96%80-WEB-PRESS-plus-plus%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA/dp/477414164X)を読み返していました。そこで「正規化というやつが必要では？」と気付いたので少し調べてみました。

# ここで言う正規化とは？
例えばUnicodeで"ぱ"はU+3071で表すことができる一方、"は"（U+306F）と丸（U+309A）の合成でも表現できます。もしも後者の文字をブラウザ等に表示すると、「一見"ぱ"のように見えるが検索ではヒットしない」などの問題が出るため、符号化表現を一通りに揃えることが有効です。これを正規化と言うそうです。

# 実験環境
* Personal Environment 11.15.0
    * DBMSはSQL Server
* Service Studio 11.53.5
    * 久しぶりに仕事以外でService Studioを使ったら自動アップデートされていてUIがかなり変わっていました

# 実験内容
## 前提
* 取り扱う文字列は"あ～あ①髙島屋パバぱ"とします。10文字のように見えますが、この中の最後の3文字"パバぱ"は合成した文字なため実際は13文字です
* 正規化はExtesionで行いました。Extensionの中で[String.Normalize メソッド](https://docs.microsoft.com/ja-jp/dotnet/api/system.string.normalize?view=net-6.0)を呼び出しています。`NormalizationForm.FormC` を利用し、合成済の文字に寄せる方向としました。

## 正規化する/しないにより文字数は変わるのか？（OutSystems）
OutSystems組み込みのLength()を使って確認してみました。結果、正規化する/しないに関わらず10文字と判定されました（不思議）
→[StringInfo.LengthInTextElements](https://csharp.programmer-reference.com/stringinfo-lengthintextelements/)が使われているのかもしれません。

## 正規化する/しないにより文字数は変わるのか？（C#）
正規化を行うExtensionの中でString.Lengthを確認してみました。結果、正規化する場合は10文字、しない場合は13文字と判定されました（納得の結果）。

## 正規化せずに長さ10のEntity Attributeに登録できるのか？
"String or binary data would be truncated." のエラーが発生しました。そのためやはり事前の正規化が必要そうです。

## Entityに登録された正規化した文字列、正規化していない文字列に差はあるのか？
`Attribute like "%ぱ%"` で検索すると、正規化した"ぱ"も正規化していない"ぱ"もヒットしました（不思議）

## Entityから取り出したデータに変化はあるのか？
「正規化せずに登録したデータをEntityから取り出すと勝手に正規化されていたりしないか？」確認しましたが、特に変化はなく杞憂に終わりました。

## 番外編：Unicodeエスケープは入力可能か？
残念ながらText型の変数に"\u2660"などと入力しても認識してくれませんでした。

## 番外編：本当にブラウザはうまく検索してくれないのか？
正規化した文字列、正規化していない文字列を取得するREST API Methodを作成しブラウザで表示しました。ブラウザ（Chrome)の検索機能を使い"ぱ"を検索すると、正規化したものもしていないものもどちらもヒットしました（本に書かれていたことと違う）。少し古い本なので技術が発展して課題解決されたのかもしれません。

# 結論
OutSystems上では正規化してもしなくても文字列の長さが同じだったり、Entityの検索でもどちらもヒットしたりで、正規化しなくていいかもとも思いましたが、正規化していない場合Entity登録の際にエラーが発生する可能性があるため、以下のように初めに正規化を行おうと思います（これを行っていないとサーバーサイドバリデーションをすり抜けてEntityに登録しようとし、そこでエラーが発生してしまう）。

1. 正規化
2. サーバーサイドバリデーションの一環で最大文字数を超えていないか確認
3. Entityに登録

ただ、正規化すると一部文字（"Å"（U+212B）など）は別の文字に変わる、またその文字をShift_JISに変換しようとするとJIS X 0208には該当文字が存在しないため文字化けが発生するなどの背反もあるので「いつも正規化が正しい」わけではなさそうです。
partedでGPTパーティションを作ってbtrfsで初期化

# やりたいこと
partedを使ってUSBメモリにGPTパーティションを切ってbtrfsで初期化します。

# 手順

### 1.まずはbtrfs-progsをインストール

```shell
sudo apt install btrfs-progs
```

### 2.partedを使ってパーティションを作成する

partedを起動
```shell
parted /dev/sda
```

partedのプロンプトからGPTパーティションテーブル初期化
```shell:paterd
mklabel
    - label type: gpt
````

適当にパーティションを作る
```shell:paterd
mkpart
    - partition name: swappt01
    - File system type: linux-swap
    - start: 0%
    - end: 6%
mkpart
    - partition name: varpt01
    - File system type: btrfs
    - start: 6%
    - end: 18%
mkpart
    - partition name: sharept01
    - File system type: btrfs
    - start: 18%
    - end: 30%
mkpart
    - partition name: timemachinept01
    - File system type: btrfs
    - start: 30%
    - end: 42%
mkpart
    - partition name: apppt01
    - File system type: btrfs
    - start: 42%
    - end: 100%
````

### 3.各パーティションをファイルシステムで初期化

```shell
mkswap -L swapfs01 /dev/disk/by-partlabel/swappt01
mkfs.btrfs -L varfs01 /dev/disk/by-partlabel/varpt01
mkfs.btrfs -L sharefs01 /dev/disk/by-partlabel/sharept01
mkfs.btrfs -L timemachinefs01 /dev/disk/by-partlabel/timemachinept01
mkfs.btrfs -L appfs01 /dev/disk/by-partlabel/apppt01
```

### 4.各パーティションがラベル付されて認識されているか確認

```shell
ls -l /dev/disk/by-partlabel/
ls -l /dev/disk/by-label/
```
Pythonで.envファイルから環境変数を設定する

# はじめに
.envファイルから環境変数を設定し、その後環境変数を取得し、
GitHubにコミットする際に、APIキーやユーザID・パスワードなどを含めてコミットしないように
.envファイルに外出しして、.gitignoreファイルで.envファイルをコミットしない点をまとめた

# 前提
pip3がインストールされていること
Python3がインストールされていること

# 環境変数の設定〜取得方法
1.「.env」ファイルを作成し、隠したい情報を設定する
（例）
```.env
username="taro"
password="sampletaro"
```

2.ターミナルを開いてモジュールをインストールする
```
pip3 install python-dotenv
```

3.Pythonを開いて下記を記載する
```python
from dotenv import load_dotenv
load_dotenv()
```
これで.envファイルに記載したものが環境変数に設定できました

4.環境変数を取得します
```python
import os

userName = os.getenv('username')
password = os.getenv('password')
```
これで、.envファイルに設定した「username="taro"」と「password="sampletaro"」という情報を取得できます

# Gitへコミット手順
1.「.gitignore」ファイルを作成し、下記を記載
```.gitignore
.env
```

2. コミット・プッシュします


以上
自分へのメモ書きでまとめました。
RaspberryPi4の初期セットアップ

# やりたいこと

RaspberryPi4にRaspberryPi OS Liteの入ったSDカードを入れて起動したらまずやりこと。

# 手順

### OSの最新化

```shell
sudo apt update
sudo apt full-upgrade
sudo shutdown -r now
sudo apt autoremove
audo apt clean
```

### raspi-config
- Keybordsレイアウトの設定でHappyHakkingにする
- TimeZoneをAsia/Tokyoにする

### /etc/defaults/locale

localeをC.UTF-8にする

```shell:/etc/defaults/locale
LANG=C.UTF-8
```
RaspberryPi4で固定IPを振る

# やりたいこと

RaspberryPi4で固定IPを振ります。

# 手順

### 1.dhcpcd.confを編集する

```shell:/etc/dhcpcd.confに以下の行を追加
static ip_address=192.168.10.220/24
static routers=192.168.10.1
static domain_name_servers=192.168.10.1
```
RaspberryPi4でWifiに繋がるようにする

# やりたいこと

raspberrypi4でwifiが繋がるようにします。

# 手順

### 1.wpa_supplicant.confを設定してWifiに繋がるようにします

```shell:/etc/wpa_supplicant/wpa_supplicant.conf
cntr_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP
network {
    ssid="xxxx"
    psk="xxxx"
}
```

これで再起動して繋がるかと思いきや、何故か繋がりませんでした。
ifconfigで確認してもwlan0が見えません。

### 2.wlan0を手動で起動してみる

```shell
sudo ip link set wlan0 up
```

すると、"Operation not possible due to RF-kill"と言われます。
たぶん、無線関連の仕組みがブロックされているのかと思われます。
そこで、rfkillコマンドで状態を確認します。

```shell
sudo rfkill list all
```

想定通り、Wireless LANがSoft blockedになっていました。
ブロックを外して再度起動します。

```shell
sudo rfkill unblock wifi
sudo ip link set wlan0 up
```

これでifconfigするとwlanが見えるようになります。
Linux(RaspberryPiOS)でUSBメモリをマウントする

# やりたいこと

RaspberryPi4（RaspberryPiOS）でUSBメモリをマウントします。

# 手順

### 1.まずはマウントポイントとなるディレクトリを作ります

```shell
sudo mkdir /data
sudo mkdir /data/homepi
```

### 2.デバイスファイルのパスを確認します

```shell
ls -l /dev/disk/by-label/
```

USBメモリに名前を設定してればそれっぽいのが出てくるはず。

### 3.マウントします

```shell
sudo mount -t vfat -o defaults,noatime,uid=root,gid=pi,umask=0002/dev/disk/by-label/HOMEPI/ /data/homepi/
```

vfatの場合、Linuxのアクセス制御に対応してないので、uid/gid/umaskなどをマウントオプションで指定してあげる必要があります。
【Xcode】コードスニペットについて

# はじめに
コードスニペットとは？
正確かはわかりませんが私の認識では、「何度も使うコードを定型文として登録する」みたいな感じで思っています。

今回はSwiftUIでダークモードを検知する事ができるコードを登録します
`@Environment(\.colorScheme) var colorScheme`

これ毎回忘れて必ずググっちゃうんです笑

# やり方

登録したいコードを選択します。
![スクリーンショット 2022-07-02 16.45.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/a0947b81-5fae-9cfa-c2da-75e86f310cd7.png)

選択したコードの上で右クリックします。
「Create Code Snippet」を選択します。
![スクリーンショット 2022-07-02 16.47.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/828a0f5d-64f5-b497-181b-a9745edc4615.png)

編集画面が表示されます
編集する所は3箇所あります
①タイトル
②説明
③検索文字列
![スクリーンショット 2022-07-02 16.59.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/7920c28c-80a8-48ae-c9c8-11ecd0a27652.png)

上記の画像のように設定した場合、以下のように表示されます
![スクリーンショット 2022-07-02 17.06.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/71f14343-8390-1ae1-c741-037305edd9be.png)

# おわり
繰り返し使うようなコードであればコードスニペットに登録して時短しましょう！！
野獣先輩の配色をまとめる。４色カラーコードでウェブデザイン兄貴もニッコリ。

野獣先輩の配色(野獣先輩の色)を

* 16進数カラーコード
* RGB

でまとめました（絶望）
毎回調べるの面倒だからさ俺もさ。


茶色:  `#A1736B` / `rgb(161, 115, 107)`

紫色:  `#3E343F` / `rgb(62, 52, 63)`

緑色:  `#979F9B` / `rgb(151, 159, 155)`

白色:  `#C9BFB6` / `rgb(201, 191, 182)`


メモ用。追加していきます。
トランスポゾン解析その1

**EDTAの出力データで色々やりたい**
EDTAでトランスポゾンを検出したあとに色々やりたいが、それには細々した工夫が必要だったので忘備録としてまとめます。間違いなどあればご指摘いただけると幸いです。

※事前に解析に使うツールはcondaでインストールしてあるものとします。
※パソコンのスペックや目的によって最適なパラメータが違うのでオプションは各自いじっていただければと思います。

  
# 系統樹を描く
今回は系統樹を描いてみます。複数種のTElibをまとめて系統樹を書いたときに、A種とB種では共通のファミリーがゲノム中に存在するけどC種では全然違うファミリーがある、とか分かれば楽しいなと思っている。

あってるかわからないけど今回は{hoge}TElib.faを使って系統樹を描いてみます。


#### ~~0. TElib.faを丸ごと使って下流の解析を行なってもいいと思うが、今回はseqkitを用いてGypsyだけ抽出してみる~~
```{bash}
seqkit faidx hoge.TElib.fa -r 'Gypsy' >hoge_Gypsy.TElib.fa
```
TElib.faはEDTAで使用したリファレンス配列が含まれるので、系統樹を描いたりする解析には使えなかった。てっきり新しく構築されたコンセンサスが出力されているのだと思っていたが違ったようだ。

#### 1. TEsorterでdomain探索
```{sh}
TEsorter hoge_Gypsy.TElib.fa \
-db rexdb-plant \
-p 24
```
#### 2. RH RT INTのdomainでアライメント+concatenate
```{sh}
python ~/miniconda3/envs/repeatmasker/pkgs/tesorter-1.3.0-py_0/site-packages/TEsorter/modules/concatenate_domains.py \
hoge_Gypsy.TElib.fa.rexdb-plant.cls.pep RH RT INT \
> hoge_Gypsy.TElib.fa.rexdb-plant.cls.pep.RH-RT-INT.aln
```
**注意！**
condaでTEsorterを入れた場合、`TEsorter`コマンドは正常に動くものの、`concatenate_domains.py`は大元のスクリプトがあるところまでフルパスを記載する必要があるようです。
参考:
https://github.com/zhangrengang/TEsorter/issues/34
どのドメインでアライメントを行うかはお作法に従うのだと思われます。今回はLTR型なので以下の論文を参考にRH, RT, INTの3つのドメインを解析に使用しました。
参考:
https://mobilednajournal.biomedcentral.com/articles/10.1186/s13100-018-0144-1

#### 3. iqtreeで系統樹推定
```{sh}
iqtree -s hoge_Gypsy.TElib.fa.rexdb-plant.cls.pep.RH-RT-INT.aln \
-bb 1000 -nt AUTO -T 20
```
出力されるtreefileで系統樹描く
【2022年版】 Ubuntu 22.04 で apt install すると、Which services should be restarted?  ときかれる

# 【2022年版】 Ubuntu 22.04 で apt install すると、```Which services should be restarted?``` ときかれる。

## はじめに

  - Ubuntu 22.04 環境で、apt install を行うたびに、```Daemons using outdated libraries``` ```Which services should be restarted? ``` と表示されてしまう。
  - 確認なしに必要なデーモンは再起動してくれたら良い。

                                           ┌────┤ Daemons using outdated libraries ├─────┐                                            
                                           │                                             │                                            
                                           │                                             │                                            
                                           │ Which services should be restarted?         │                                            
                                           │                                             │                                            
                                           │    [ ] networkd-dispatcher.service          │                                            
                                           │    [ ] unattended-upgrades.service          │                                            
                                           │                                             │                                            
                                           │                                             │                                            
                                           │          <Ok>              <Cancel>         │                                            
                                           │                                             │                                            
                                           └─────────────────────────────────────────────┘                                            
      
## 環境

```terminal
~$ uname -a
Linux linux 5.15.0-40-generic #43-Ubuntu SMP Wed Jun 15 12:54:21 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
```

```terminal
~$ cat /etc/os-release 
PRETTY_NAME="Ubuntu 22.04 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
```

```terminal
~$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04 LTS"
```

## 作業

  - ```/etc/needrestart/conf.d/``` 配下に、設定ファイルを作成する。

```terminal
~$ echo "\$nrconf{restart} = 'a';" | sudo tee /etc/needrestart/conf.d/50local.conf
$nrconf{restart} = 'a';
```

## 動作確認

  - apt install を行なってみる

## 参考

  - [Ubuntu Weekly Recipe - 第718回　needrestartで学ぶパッケージのフック処理](https://gihyo.jp/admin/serial/01/ubuntu-recipe/0718)

## おわりに

  - かんたんでしたね
pyenvで.python_versionを設定していてもPythonのバージョンが切り替わらないとき

「pyenvで`.python_version`を設定していてもPythonのバージョンが切り替わらないとき」とはこんな時です。
```sh
$ ls
.python_version

$ cat .python_version
3.9.8

$ pyenv global 3.9.8

$ python -V
Python 3.10.3
```

`pyenv versions`を実行します。

```shell
$ pyenv versions
  system
  2.7.13
  3.10.1
* 3.10.3 (set by PYENV_VERSION environment variable)
  3.6.4
  3.9.8
$ $PYENV_VERSION                                                      
zsh: command not found: 3.10.3
```

環境変数`PYENV_VERSION`に`3.10.3`が設定されていました。これをpyenvが優先して読み込んでいるようです。この環境変数を`unset`します。

```shell
$ unset PYENV_VERSION
$ pyenv versions
  system
  2.7.13
  3.10.1
  3.10.3
  3.6.4
* 3.9.8 (set by /foo/bar/.python_version)
```
Rails validates

## バリデーション
Railsではvalid?メソッドを実行するとバリデーションが実行されます！
バリデーションが通ればtrueを返し、引っかかればfalseを返します。
invalid?メソッドは逆の振る舞いをします。

### 空でないこと
```ruby 
validates :title , persence: true
```
### booleanの場合
```ruby
validates :island, inclusion: { in: [true , false ] }
```
### unique
```ruby
validates :user_name , uniqueness: true
```

### 含むかどうかを検証する場合
```ruby
validates :fruit, inclusion : {in: %w(banana apple orange)} 
```
### 含まないことを検証する場合
```ruby
validates :country, exclusion: {in: %w(china japan)}
```

### 長さ
```ruby
validates :password, length: {minimum: 1} #　１文字以上
validates :password , length: {maximum: 8} # 8文字以下
validates :password , length: {in: 1..12} #1文字以下
validates :password , length: {is: 8} #8文字のみ
```

### numericality
```ruby
validates :age, numericality: true # 数字のみ
validates :age, numericality: {only_integer: true} #integer
validates :age, numericality: {greater_than: 20} #指定された値（あたい）よりも大きいか
validates :age, numericality: {less_than: 10} #指定された値よりも小さいか
validates :age, numericality: {equal_to: 10} # 指定された値と等しい（ひとしい）か
validates :age, numericality: {greater_than_or_equal_to: 10} #定された値と等しい、あるいは大きいか
validates :age, numericality: {less_than_or_equeal_to: 10 } #指定された値と等しい、あるいは小さいか
validates :age, numericality: {odd: true} #trueに設定した場合　奇数か
validates :age , numericality: {even: true} #even trueに設定した場合　偶数か
```

### reg
```ruby
VALID = /\A[a-zA-Z]+\z/
validates :name, format: {with: VALID}
```
グラフィックス勉強のノード＿1.1＿レンダリングパイプライン（RenderingPipeline）

[toc]

# レンダリングパイプライン（RenderingPipeline）

## 1. 全体の流れ

![image-20220628110002848](https://s2.loli.net/2022/06/28/XeHnJANbuiwQT9r.png)

1. Application ステージ
2. ジオメトリー ステージ(Geometry　Processing)
3. ラスタライズ ステージ (Rasterisation)
4. Pixel Processing ステージ
5. Post Processing //現在のゲーム制作として重要な一環です。

## 2. Application ステージ 

​	一般的はCPUで実行する

1. シーンデータの準備

   オブジェクトの頂点座標、uv座標、positon、rotation、Scaleなど

   ライティングデータ

2. 加速アルゴリズム/Culling

   見えないオブジェクトをカリング(Culling)する。よく使われているアルゴリズムはBVH(Bounding Volume Hierarchy)、八分木(Octree)

3. レンダリングステータスの設定

   Batching、レンダリング順番、レンダリングターゲット(Framebuffer/RenderTarget)、レンダリングモード（Forward/Deferred）

4. DrawCallを使って、データをGPUに輸出

   頂点データ，MVPマトリクスなど

## 3. ジオメトリー ステージ(Geometry　Processing)　

​	GPUで実行する

![image-20220628110218831](https://s2.loli.net/2022/06/28/oVufQPdtkUFqW34.png)

1. Vertex Shadering 

   1. 頂点の色を三角形に渡って補間されます

   2. MVP変換　

      ObjectSpace -> WorldSpace -> ViewSpace -> ClipSpace->SceenSpace

      ![image-20220628122310687](https://s2.loli.net/2022/06/28/OGPQLFJiENMZ1mk.png)

2. Optional Vertex Processing

   1. テッセレーション (Tessellation) (optional)

      ポリゴンをさらに分割して表現することです、画像をより詳細かつ滑らかで現実感のあるものにする技術である

   2. Geometry Shader(Optional)　

3. Projection　

   直交（orthogonal）、透視投影（perspective projection）![image-20220628120808187](https://s2.loli.net/2022/06/28/dIrhAK3qiEYon7X.png)

4. Clipping 

   1. Cull Front/Back/Off　//
   2. Frustum Culling //カメラ以外Primitivesを除外する。レンダリングしない![image-20220628115244201](https://s2.loli.net/2022/06/28/N4ZnVsQv2fjkCFL.png)

   **注意：opengl NDC座標xyz範囲（-1,1）　d3d NDC座標xy範囲(-1,1) z範囲(0,1)**

   流れ: ClipSpace -> NDC Space -> ScreenMapping -> ScreenSpace

5. Screen Mapping  (NDCSpace範囲は（-1,1）=>ScreenSpace(スクリーンの大きさ（1920x1080など）))![image-20220628115435020](https://s2.loli.net/2022/06/28/H1AIQ2KYTufGdiv.png)

## 4. ラスタライズ ステージ (Rasterisation)

![image-20220628123021346](https://s2.loli.net/2022/06/28/GFD9rVcstulUhXe.png)

1. 三角形設置 頂点座標とインデックスを使って三角形を設置

<img src="https://s2.loli.net/2022/06/28/SVQE4GCmnUhTfl2.png" alt="image-20220628123452568" style="zoom:50%;" />

2. 三角形内のピクセルをトラバーサル（Traversal）して、ピクセルの線形補間を行う。![image-20220628123506208](https://s2.loli.net/2022/06/28/RVGL2kDlu3O7QeI.png)

3. アンチエイリアシング anti-aliasing

   1. MSAA(Multisample AA)　ラスタライズ段階、複数もサンプルポイントを設置する。![https://mynameismjp.files.wordpress.com/2012/10/msaa_partial_coverage2.png](https://vip2.loli.io/2022/06/28/6dQXlphFP1zSJbq.png)

   2. SSAA (SuperSample AA) 

      //この段階ではない、ゲーム解像度よりｎ倍大きいバッファをレンダリングする、そのバッファをサンプリングします。

   3. FXAA/TXAA　//この段階ではない、Postproceing技術


## 5. Pixel Processing ステージ

1. Fragment Shader

   ピクセルの色計算![Snipaste_2022-06-28_13-42-58](https://vip2.loli.io/2022/06/28/Y58CrOLjQedURXI.png)

2. Color Blending

   1. alphaTest 
   2. depth buffer test
   3. Stencil Test
   4. Blending

3. RenderTarget

   ​	FrameBuffer, RenderTexture

## 6. Post processing

​	前のレンダリング完成後、その結果を再処理する

## 参考資料

​	Real-Time Rendering 4th Edition

​	https://learnopengl.com/

​	https://www.hardwaretimes.com/pc-graphics-settings-explained-msaa-vs-fxaa-vs-smaa-vs-taa/
【Dart入門】【自動テスト】Dart で雑にWebdriver を利用する


## これは何か
Dart でWebの自動テストをしたくなりました。
Googleの提供するDart 用の[Webdriver](https://pub.dev/packages/webdriver)があるのですが、利用方法をサクッと紹介する日本語記事がなかったため執筆しました。

## 以下を対象読者としています
- Pythonなど他言語で、Selenium を利用したことがある
- Dartを利用して自動テストしたい
- 初期セットアップだけやれれば、あとは自走できる

## 動作環境
- MacOS Monterey
- chromedriver (103)
- webdriver: ^3.0.0

## 1. chromedriver のインストール
```
% brew install selenium-server-standalone
% brew install chromedriver
```

※ 細かいですが、chromedriverを以前からinstallしてある人は、バージョンが最新かチェックしましょう。
```
% chromedriver --version
ChromeDriver 103.0.5060.53 (...略)
```
上記コマンドで出てくるバージョン（私の場合103番台）と、ご利用中のGoogle Chrome のバージョンがあっているかどうか確認しましょう。これがあっていないとエラー出ます。([よくあるエラー](https://yuki.world/python-chrome-driver-version-error/)ですね)


## 2. Dart側の設定
pubspec.yamlにwebdriverを追加

```
dependencies:
  webdriver: any
```

## 3. chromedriver をターミナルから起動
```
% chromedriver
```

うまくいけば、以下のようなレスポンスがあります
```
Starting ChromeDriver 103.0.5060.53 (...略...) on port 9515
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
```

これでいう1行目に書いてあるポート番号（こちらだと「9515」）をメモしましょう。（あとで使う）

また、このターミナルは起動したまま放置しておきます。
（※PythonのSelenium だと、この過程がなかったと記憶しています。気をつけましょう）

## 4. Dartファイルを作る
どこでもいいので、Dart プロジェクトの適当な場所にテストファイルを設置します。

```one_test.dart
import 'package:webdriver/io.dart';

void main() {
  //このuriの'9515'となっているところに、3.でメモしたポート番号を入れる
  var driverUri = Uri.parse('http://127.0.0.1:9515/');
  String targetUri = 'https://google.com/';

  Future<WebDriver> driver =
      createDriver(uri: driverUri, spec: WebDriverSpec.W3c);

  driver.then((WebDriver d) {
    d.get(targetUri);

    //例えばここでDOM操作 できます
    //var ans = d.findElement(By.id('hogehoge'));
    //print(ans);

  });
}
```

## 5. 自動で Windowを開くところまでやる

3で利用したのとは別のターミナルから、4で作成したdartのファイルを起動します
```
% dart run one_test.dart
```

## 6. できました
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348026/2810d7ec-e81d-143d-44df-144b00e69cb2.png' width=512>


それでは。

### 参考
https://pub.dev/packages/webdriver

https://qiita.com/isyumi_net/items/49a7e60fed6b39377e6a
【野良】Google driveをPWA化する【PWA】

# 前回のあらすじ
https://qiita.com/m-m-n/items/504f10c147e800f436cd

Google driveをコマンド一発で呼び出せると良いのでPWAアプリのコマンド化を行いました

# Google driveがPWAじゃなくない？
どうやらそのようですね？

ではPWAにしてしまいましょう！

# 野良PWA化
## どうやって？
普通に考えると人様のサービスを勝手に変更はできません
なので自分のドメインでPWAのサイトを作ります

あとはそこからGoogle driveにリダイレクトします

ね、簡単でしょ？

## コード
以下に野良PWA用のコードを用意しました
https://github.com/m-m-n/nora-pwa

### 使い方
以下を用意します
- サーバー
- ドメイン
- 証明書

Webサーバーの設定等は省略します

`/path/to/nora-pwa` に配置したとします

```bash
cd /path/to/nora-pwa/scripts
vim sites/drive.google.com.json
```

以下のようなJSONファイルを用意します
```json
{
  "domain": "drive.google.com",
  "redirect_to": "https://drive.google.com/",
  "site_name": "Google ドライブ",
  "short_name": "ドライブ",
  "icons": [{
    "file_name": "icon.png",
    "sizes": "192x192",
    "type": "image/png"
  }],
  "theme_color": "#1a73e8",
  "background_color": "#ffffff"
}
```

```bash
./generater.php sites/drive.google.com.json
```

これで `/path/to/nora-pwa/public` にGoogle driveをPWA化するためのディレクトリーが生成されます

```bash
cd /path/to/nora-pwa/public/drive.google.com
ls
index.html  manifest.json  redirect.html  sw.js
```

アプリのアイコンが無いので適当に生成してサーバーにアップロードします
```bash
ls
icon.png  index.html  manifest.json  redirect.html  sw.js
```

### アクセスする
準備が整ったのでアクセスしてみましょう

`https://YOUR-DOMAIN/drive.google.com/index.html` を開くとPWAのインストールが促されるかと思います
促されない場合はGoogle Chromeの右上にある三点のメニューアイコンをクリックし、インストールします
インストールの項目がない場合はmanifest.json、service workerあたりが存在しているか確認します

manifest.jsonを確認するとPWAとして起動した初期URLではindex.htmlではなくredirect.htmlとなっています
redirect.htmlで本来のGoogle driveのサイトへジャンプするようになっているので、勝手に作ったPWAアプリがあたかもGoogle driveのように見えます

厳密には別ドメインに遷移してるので、遷移先のURL(この場合 `https://drive.google.com` )が表示されますが、それを承知でやっているので問題ないでしょう

これでPWAとしてインストールが出来たので、前回の手順でコマンド化することが出来るようになりました

# 嬉しい副産物
スマホでアプリがリリースされていないサービスも勝手にPWA化してインストールできる！！！！

---

それでは良いPWAライフを。
Navigator.maxTouchPointsプロパティのサンプルコードで見かけるmsMaxTouchPoints

Navigatorインターフェイスの[maxTouchPointsプロパティ](https://developer.mozilla.org/ja/docs/Web/API/Navigator/maxTouchPoints)の使い方をググると、サンプルコードで`maxTouchPoints`と共に`msMaxTouchPoints`というプロパティの値も併せてチェックしているスニペットを載せた記事を見かけます。
例）
https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
https://stackoverflow.com/questions/24121433/detect-if-touch-device-with-ie11-using-javascript/24121527

IE絡みっぽいですが、今も必要なのかわからなかったので、旧バージョンに遡って確認してみました。
テストに使ったコードはこちら： https://codepen.io/kaz_hashimoto/pen/wvmBOMv
これは、問題のプロパティがundefinedになるかどうか、読み取った値は何かを画面に表示します。

BrowserStackを使ってIE11, IE10, IE9で実行した結果はこれです。
![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/08c578b0-31b8-624b-667d-59289eaab121.png)

`msMaxTouchPoints`はIE10で導入され、IE11では`maxTouchPoints`もサポートしたことがわかりました。
`msMaxTouchPoints`は最新のEdgeでもundefinedですし、もう考慮する必要はないですね。

**参考記事**
[タッチスクリーンであるかを JavaScript で判定する](https://www.bugbugnow.net/2020/12/is-touch-device.html)
関数ポインタの使い方

# 目的
関数ポインタの使い方を説明する。

# 内容
関数ポインタとは、関数をメモリに保存して呼び出すものである。
- メリットは、switchやifなど条件分岐を使用せずに、関数を間接的に呼べることである。
- デメリットは、プログラムの実行速度が遅い可能性があることである。

関数ポインタの宣言にtypedefが使用される。
```C
// typedef （新しく設定した関数の型）　の宣言
typedef 返り値 (*関数)(引数);
```
関数ポインタの例を以下に示す。
```C
#include <stdio.h>

int add(int num1, int num2){
    return num1 + num2;
}

int sub(int num1, int num2){
    return num1 - num2;
}

typedef int (*fptrOperation)(int, int);
typedef int (*operation)(int, int);
operation operations[128] = {NULL};

void initializeOperationsArray(){
    operations['+'] = add;
    operations['-'] = sub;
}

int evaluateArray(char opecode, int num1, int num2){
    fptrOperation operation;
    operation = operations[opecode];
    return operation(num1, num2);
}

int main(void){
    initializeOperationsArray();
    printf("%d\n", evaluateArray('+', 5, 6));
    printf("%d\n", evaluateArray('-', 5, 6));
    return 0;
}

```

プログラムの流れを説明する。
- プロトタイプ宣言
    - fptrOperation関数ポインタ型の宣言(返り値：int, 引数：int, int)
    - operation関数ポインタ型の宣言(返り値：int, 引数：int, int)
    - operation関数ポインタ型の配列operationsの初期化
- メイン関数
    -  initializeOperationsArray関数の処理
    -  evaluateArray('+', 5, 6)の結果の出力→add関数の処理
    -  evaluateArray('ー', 5, 6)の結果の出力→sub関数の処理
- initializeOperationsArray関数
    - operations配列のインデックスが’＋’の場合は、配列にaddを代入
    - operations配列のインデックスが’ー’の場合は、配列にsubを代入
- add関数(引数：num1, num2）
    - 渡された2つの引数の足し算の結果を返す
- sub関数(引数：num1, num2）
    - 渡された2つの引数の引き算の結果を返す
- evaluateArray関数(引数：opecode, num1, num2）
    - fptrOperation関数ポインタ型のoperationを宣言
    - oprationに、opecodeのインデックスをもつoperations配列を代入→operationにadd、subが代入される
    - num1,num2を引数にもつoperation関数を返す→add(num1, num2)、sub(num1, num2)の処理

# 所感
関数ポインタ型のoperations配列に実行したい関数を入れておき、メイン関数で配列を指した関数ポインタを実行することで、
自由に関数を呼び出せる利点があると感じた。

## 参照
詳説Cポインタ　P82, 83
WindowsにMinGWをインストールする（Scoopで）

WindowsにC言語の開発環境を整えようと思い、
MinGWを[MinGW-w64](https://www.mingw-w64.org/)からダウンロード＆インストールしようとしました。

しかし問題が発生。

## インストール中に"The file has been downloaded incorrectly!"と表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/6defe649-b37d-75d6-49ed-1d345e329ef0.png)

これです。

ググったところ他にも同じところで詰まっている方が結構居ました。

開発者権限で実行するとか、再度ダウンロードするとか、一般的な対応方法ではうまくいかないようです。（私もダメでした。）

公式からのダウンロード＆インストールを諦めて、Scoopを使ったところうまくいきました。

## ScoopでMinGWを入れる

[Scoop](https://scoop.sh/#/)とは

> A command-line installer for Windows

です。`apt`とか`home-brew`だ、と思えばいいです。

インストールがまだの方は以下記事参照してインストールしてください。

参考：[Windows用コマンドラインインストーラのScoopを使う - Qiita](https://qiita.com/YoshikiIto/items/66b4b9ca853c9dda7547)

インストールが済んだら、Scoopを使って入れたいもの、を先の公式ページから検索してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/29e5f5b8-0188-d9d6-e2b9-14ebaa52a211.png)

MinGWもちゃんとScoopにありましたので、書いてあるコマンド

``` powershell
scoop install mingw
```

を実行。

``` powershell
PS C:\Users\yoshiki.ito> scoop install mingw
Installing 'mingw' (8.1.0) [64bit]
x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z (47.1 MB) [==========================================================] 100%
Checking hash of x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z ... ok.
Extracting x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z ... done.
Linking ~\scoop\apps\mingw\current => ~\scoop\apps\mingw\8.1.0
Running post_install script...
'mingw' (8.1.0) was installed successfully!
Notes
-----
- You are installing the Mingw-w64 implementation of GCC.
This implementation has a better compatibility, but may not support newer C/C++ standards.
For more recent GCC versions, try 'mingw-winlibs' or 'mingw-nuwen'.
```

インストールが無事完了しました。

Scoopから入れておけば管理も楽ですし、違うやり方がどうしてもうまくいかない、という場合はScoop使うのはアリです。

念のため`gcc --help`でインストールできていることを確認

``` powershell
PS C:\Users\yoshiki.ito> gcc --help
Usage: gcc.exe [options] file...
Options:
  -pass-exit-codes         Exit with highest error code from a phase.
  --help                   Display this information.
  --target-help            Display target specific command line options.
  --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...].
                           Display specific types of command line options.
  (Use '-v --help' to display command line options of sub-processes).
※以下略
```

問題なさそうです。
RustでCSVを作成してZIPファイルにするライブラリを書きました。

# 目的
CSVファイルを作成して、ZIPファイルに圧縮するコードを書いていました。社内の別のプロジェクトでもそのようなコードが書かれていたので、ライブラリ化して利用できるようにしました。

[csv-zip-maker](https://crates.io/crates/csv-zip-maker)

# 特徴
* CSVファイルもZIPファイルもテンポラリなディレクトリに作成して、処理が終わったら自動でファイルを消します。後処理のことを考えなくてよいです
* ファイルに書き込むので、大量のデータでもメモリを食いつぶすことはありません
* エクセル向けに特化してカスタマイズを用意しています。

# 利用例
```rust:main.rs
use csv_zip_maker::{CsvZipError, CsvZipMaker};

fn main() -> Result<(), CsvZipError> {
    let mut maker = CsvZipMaker::new("test", "summary")?;
    let mut csv_maker = maker.make_csv_maker_for_excel("summary1")?;
    csv_maker.write(&vec!["aaa", "bbb"])?;
    csv_maker.write(&vec!["ccc", "ddd"])?;
    maker.add_csv(&mut csv_maker)?;
    let mut csv_maker = maker.make_csv_maker("summary2")?;
    csv_maker.write(&vec!["111", "222"])?;
    csv_maker.write(&vec!["333", "444"])?;
    maker.add_csv(&mut csv_maker)?;

    let path_buf = maker.make_zip_file()?;
    std::fs::copy(path_buf, "test.zip")?;
    Ok(())
}
```

# まとめ
CSVやZIPの作り方を、いちいちぐぐってると大変ですが、一度ライブラリ化すれば安心して使えるようになります。
ファイルからZIPファイルに書き込むサンプルがぐぐっても中々見つからなくて、同じ苦労をしなくてよくなるので、うれしいです。
外注に投げるための引き継ぎ資料の実例

 # 外注に投げるための引き継ぎ資料作成記録

## 概要
外注に投げるための引き継ぎ資料の作り方について
私もだいぶ忘れたが記憶を頼りにある例を書いてみようと思います。
何らかの参考になれば幸いです。
### 外注に投げろ　あるベンチャー企業で
あるベンチャー的な会社で派遣していたことがあります。
そこにあるやり手の複数案件を抱えているリーダーさんがいました。
SNS的な案件で大企業とか公的機関がお客さんでした。
リーダーさんが全部抱えているような状況でした。
リーダーが急にやめるって言い出しました。それでこれからはプロジェクトを外注に
全部投げます、そのために資料をまとめる担当になりました。

## 基本方針
◾️ 誰になにを聞けばいいのかを押さえる。知識そのものではない。
← そのために案件ごとに大きな　データセンター　　お客さん　などの図を
書く。
◾️ ソリューション集を作る
## メンバー構成
・社員さん
・メール整理担当
・技術サポート
## 仕事の仕方
◾️ 対象プロジェクトリーダーからの聞き取り
◾️ 問題管理シートとそれに関連するメールの整理を行い
対象プロジェクトリーダーに対する聞き取り



### 記録
◆A案件　公的機関　
◾️行動範囲
データセンター　打ち合わせ場所
注　データセンターの〇〇さんはどういう人なのか？
礼儀を大事にする人とか・・・いろんな情報
◾️ 運用用　ソリューション集　元ネタ　問題管理表　またはリーダーのメール
例）こういう問題があって再起動したらよくなりました。

◆B案件　ショッピングサイト
◾️行動範囲
データセンター　打ち合わせ場所
注　データセンターの〇〇さんはどういう人なのか？
◾️ 運用用　ソリューション集　元ネタ　問題管理表　またはリーダーのメール
例）こういう問題があって再起動したらよくなりました。

### 懸念点
リーダーさんは頭が回る人なんで何かしらの回答が来るから、それに対して騙されないようにしないとねとは思っていました。そのためリーダーはヒアリングは社員さんも含めた３人で臨みました。
### テクニック
細かいところから攻めて行くというやり方で・・・・
完了しているのかとか・・・愚直にコツコツとメールを私は確認し・・・
社員さんも含めたグループで会議室でリーダーを読んでヒアリングしました。

### 教訓
のりで話しているようなプロジェクトは気をつけたほうがいいかも。
笑い声が聞こえる。それも誰かをばかにしているような感じの笑い声が聞こえたり
議論が勢いで進んで行くプロジェクト
Javaの定数はコンストラクタで初期化できた

Javaの定数は変数名の前にfinalが付き、一度初期化したらあとは変更できないというものです。

1度は必ず初期化しないとコンパイルエラーになります。

```
final int a = 1;
```
のような初期化以外にもコンストラクタでも初期化できることを知りました。
そこでやってみたソースが以下です。
```php:FinalFormat.java
package sample;

public class FinalFormat {
	
	final int f;
	
	//コンストラクタ
	FinalFormat(int g){
		f = g;
	};
	
}
```
```php:Main.java
package sample;

public class Main {

	public static void main(String[] args) {
		FinalFormat finalformat = new FinalFormat(123);
		
		System.out.println(finalformat.f);

	}

}
```
実行結果は画像の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725725/a784a0c5-dd58-0a2d-6c23-2a79e1fd0261.png)

コンストラクタで定数を初期化したので、コンパイルエラーにならずに実行し正しい結果が得られました。
condaでopencvをinstallすると「ImportError: DLL load failed: 指定されたモジュールが見つかりません」

何度か躓いている気がするので、解決策をメモ。

# やりたいこと
pythonでopencvを使いたい

# 詰まったこと
検索して出てくる記事を参考に下記コマンドでopencvをinstallして`import cv2`をすると、「ImportError: DLL load failed: 指定されたモジュールが見つかりません」とエラーになる。
`conda install -c conda-forge opencv`

# 解決策
pipで入れたらどうにかなる。(condaでpip使うなというのはあるが、どうしてもcondaだけでは解決できなかった)
`pip install opencv-python`

# 補足
詳細は不明だが、他の仮想環境にconda installで入れたopencvが残ったままだとエラーが継続していた。
キャッシュを利用している？
pipでうまくいかなかったら、他仮想環境のopencvをuninstallするか、仮想環境ごと一回消すとよいかもしれない。
※仮想環境を消すと当然他のライブラリも消えるので、問題ないかを良く確認してから消すこと！
KtorでHello Worldを表示する

# はじめに
自社の新規プロダクトにて、Kotlinでのサーバーサイドの開発を進めています。
他の記事でHello Worldを表示するまでの手順が最新だと異なっているものが多かったので、簡単にまとめておこうと思います。

# 手順
環境はIntelliJ IDEAを使用することを前提としています。

IntelliJ IDEAにてWelcom画面を表示し、new Projectを選択します。

![スクリーンショット 2022-07-02 15.06.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354522/f30b3c6d-2860-8103-6389-8365c1ae0f83.png)

new Projectを押すと以下画面が表示されますので、以下のktorを選択します。

![スクリーンショット 2022-07-02 15.07.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354522/aa769930-1239-185b-ee70-9ccc10fe448f.png)

Nameやパッケージ名などは任意のものを入力してください。

Nextで次に進むと以下画面が表示されます。

![スクリーンショット 2022-07-02 15.20.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354522/afd03a6c-4a0e-6c39-97ed-5f8a0ce00fbc.png)

上記画面で使用したいものがあればAddで追加をして設定が終わればCreateで先に進みます。

プロジェクトを作成すると自動ビルドが走り、最終的に以下のようなツリー構造のプロジェクトになるかと思います。

![スクリーンショット 2022-07-02 15.22.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354522/f3a0e585-b614-3846-238d-903224b6dec0.png)

Applicationクラスを選択し、以下の実行アイコンを選択してください。

![スクリーンショット 2022-07-02 15.25.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354522/4590f1da-e0e3-c978-e04a-421646df79b8.png)

すると実行が始まり、Window下部のRun部分にhttpから始まるURLが表示されているはずですので、こちらのリンクを選択するとHello World!と表示されているはずです！

# さいごに
アプリとサーバー一貫してKotlinで書けるのはAndroidエンジニアの多い弊社では大変魅力です。
今後はサーバーサイド側の実装時に得た知見などもこちらで残していこうと思います。
PythonとSQLiteを使ってみた

仕事ではJavaやJavaScriptが多いですが、個人的にはpythonが好きです。
pythonの現場に行く機会があった時にできるようになっていたいなあとなるべく毎日勉強しています。

今回はpythonに標準であるSQLiteを使って基本的なことをやってみました。
まず、DB作成からテーブル、データのinsertまで。

```Python
import sqlite3

#データベースファイルを作る
dbfile = sqlite3.connect('fruit.db')
c = dbfile.cursor()

createSql = 'create table FruitName(id,name);'
c.execute(createSql)

insertSql = "insert into FruitName(1,'Apple');"
c.execute(insertSql)

dbfile.commit()
dbfile.close()
```
作成したテーブル内のデータを表示するためのソースがこちら
```Python
import sqlite3

connectDb = sqlite3.connect("fruit.db")
c = connectDb.cursor()

for row in c.execute('select * from FruitName'):
    print(row)
connectDb.close()
```
データが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725725/7311e7d8-b63c-f348-4d49-41c86d746cc8.png)

同じデータが2個入っているのはinsert後のソースでエラーが出て、直してからもう一度実行することによりinsertが2回動いたためです。
vue.js twitter の screen_name で routing

見栄えよく
https://twikon.club/helpee_club/
って感じでアクセスしたらマイページを表示するようにしたい。

ルーティングの設定とスクリーンネームの取得方法を紹介しよう

```app.js
    const routes = [
        {
            path: "/sample",
            component: Sample
        },
        //これが大事
        { path: '/:screen_name(.*)', component: NotFound }
    ];
```

URLの末尾にスラッシュが付く場合があるので削除してから取得

```NotFound.vue

<template>
    <div>
        私のスクリーンネームは {{this.getScreenName}} です
    </div>
</template>

<script>
    export default {
        computed: {
            getScreenName() {
                return this.$route.params['screen_name'].replace('/','');
            },
        },
        created(){
            alert(this.getScreenName);
        },
    }
</script>

```

`OK`
確率の問題（白いボールの箱）

## 問題

> 箱の中に、ボールが1つ入っている。
ボールの色は、黒か白のどちらかである。
この箱の中へ白いボールをひとつ追加して、箱をよく振ってボールを1つ取り出してみたところ、白だった。
さて、箱の中に残ったボールが白である確率は？

## 解答

わからない

## 解説

最初のボールが黒である確率をpとします。
2つにしてから白いボールを取り出す割合は、`1 - 0.5 p`です。
また、残りが白いボールの割合は、`1 - p`です。
このことから、「箱の中に残ったボールが白である確率」は、`(2 - 2 p)/(2 - p)`です。
さて、最初のボールは、白と黒から無作為に選ばれているでしょうか？そのような記述はないので、無作為ではありません。したがって、pは不明なので、解答は「わからない」です。

### 補足

下記の方が解答として良いと考える人もいるかもしれませんが、問うているのは確率であり、問題にない前提を使って解答を書いても意味がありません。

> 最初のボールが黒である確率をpとしたとき、解答は、`(2 - 2 p)/(2 - p)`である

もし、問題が「箱の中に、ボールが1つ入っている。このボールが白である確率は？」のとき、「ボールが白である確率をpとしたときp」という解答に意味はあるでしょうか（哲学の問題ではなく数学の問題とします）。

## 余談

googleで[「確率 白いボールの箱」を検索](https://www.google.co.jp/search?q=確率+白いボールの箱)して、何件か確認しても、p=0.5を仮定した`2/3`という解答しか見つかりませんでした。もっと正しい考え方が広まって欲しいものです。

以上
Storybookの導入方法

# Storybookの導入
storybookはCDDを実践するにあたって便利なツール

以下のコマンドでStorybookをインストール
`$npx degit chromaui/intro-storybook-react-template taskbo`
`$cd taskbox`
`$yarn`

その後、アプリケーションが動くことを確認
`$yarn test --watchAll`
`$yarn storybook`

以下のようなページが表示されれば完了![スクリーンショット 2022-07-02 15.11.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727856/06fdc330-b854-826e-73bc-ec1d55042234.png)
マイティマウスのトラックボール

USBとBluetoothのマイティマウスをハードオフで入手しました。トラックボールの反応が悪く、ネットの情報を試してみたのですが、うまくいかず結局分解してみました。

![写真（2022-07-02 15.02） #2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/e90f61a5-5afa-4b6f-ab6f-000caf985d49.jpeg)

片方のトラックボールは一つ黒い磁石のホイールが完全になくなっていました。写真の軸だけになってるものです。

またあまり強い力でグリグリするとゴムパッドが痛んで穴が空いてしまいます。

それと白いプラ部品に付いてる、ボールのスイッチの金属も取れています。

写真に写ってない方のフラットケーブルは断線させてしまい、どうにか継ぎました。

ニコイチはあまり好きではないのですが、結局ニコイチにしてBluetoothのマウスを使っています。

ボールはどきどきアルコールを染み込ませたテイッシュで拭いてきれいにして、なでる程度の力で操作するのが良いようです。

ボールでスクロールが出来なくなってもあまり力をかけずに、地道にクリーニングしてます。

上下と右のスクロールはできるのですが、左がうまく動かないため、マウスの設定で「垂直のみ」にしてあります。

![スクリーンショット 2022-07-02 15.13.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/b3686c96-4f5e-ebcc-5f7f-0b0734753141.png)

プラ部品は傷みやすいので、分解はどうしようもなくなったときにするのが良いです。

元の通り組み立てるときに、黒枠, 金属, フィラットケーブル, ゴムシート, 白いプラの順で重ねてホイールとボールを置いて、写真に写ってない白い上蓋のプラでとめます。

出来上がったらボールを操作して、ホイールが回ってることを確認してから、取り付けます。

ホイールの軸の支えの部分にグリースの様なものを付けて回りやすくするという方法も考えられますが、ゴミがたまりやすくなり、かえって状況は悪くなる気もします。

電圧の低いエネループで使っているためか、すぐに電池消耗のアラートがでますが、そのまま普通に使えます。

マジックマウスは120gくらいですが、マイティマウスは145gあります。

Appleはマジックマウス以降のマウスの新製品がなく、つまらない会社に成り下がっています。
collectionViewのFallbackでクラッシュ

# きっかけ
tableViewで
```tableViewController.swift
if hoge {
  return UITableViewCell()
}
```
このようにFallbackしていて、同様にcollectionViewにも
```collectionViewController.swift
if hoge {
  return UICollectionViewCell()
}
```
としていたらクラッシュしてしまった。

【クラッシュログ】
```
 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the cell returned from 
- collectionView:cellForItemAtIndexPath: does not have a reuseIdentifier 
- cells must be retrieved by calling 
- dequeueReusableCellWithReuseIdentifier:forIndexPath:'
```
# 原因
collectionViewの場合はregisterしたcell以外を返すとクラッシュするみたいです。。。
tableViewと同じ仕様を実現する場合は注意が必要ですね。
wsl2



https: //aka.ms/wsl2

WSL1 か WSL2 の確認
wsl -l -v　または wsl --list --verbose

デフォルト変更
wsl --set-default-version 2

バージョン変更
wsl --set-version Ubuntu-20.04 2
>変換中です。この処理には数分かかることがあります...
>WSL 2 との主な違いについては、https://aka.ms/wsl2 を参照してください>変換が完了しました。
Log4j Append機能を使ったKafkaへログ転送


## Inspiration
Javaアプリのログからデータ分析を行うことはできるかが気になり、まずログを収集する方法について調べました。
他のライブラリも同様にできますが、初めに目についたものがLog4jだったのでできるかを検証してます。
結果はできたものの、これによってアプリにさらなる外部ライブラリ依存が発生します。

## 環境
- JDK 8 以上
- kafka-client-3.2.0
- log4j-api-2.17.2
- log4j-core-2.17.2
- log4j-iostream-2.17.2
- log4j-slf4j-impl-2.17.2
- log4j-web-2.17.2
- lz4-java-1.8.0
- slf4j-api-1.7.36
- snappy-java-1.1.8.4
- tjconsole-1.7-all
- zstd-jni-1.5.2-1



## 実装
下記のソースコードを使います。
コードについて出力するだけのロジックになります。

```Java
package com.tutorial;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Main {
	
	private static final Logger logger = LogManager.getLogger(Main.class);
	   
	public static void main(String[] args) {

		System.out.println("Initial RUnnn");
		logger.info("test runun!");
	}

}

```

log4jの設定XMLは下記になります。

```xml log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN">
  <appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>

    <Kafka name="Kafka" topic="quickstart-events">
      <PatternLayout pattern="%date %message"/>
        <Property name="bootstrap.servers">localhost:9092</Property>
    </Kafka>

  </appenders>

  <loggers>
    <logger name="com.tutorial.Main" level="trace">
      <appender-ref ref="Console"/>
      <appender-ref ref="Kafka"/>
    </logger>
    <root level="error">
      <appender-ref ref="Console"/>
    </root>
  </loggers>
</configuration>

```

## 動作確認
1. まず、Kafkaのサーバーとブローカーサーバを実行します。
  ![スクリーンショット 2022-07-02 14.48.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/6e30cf97-c409-b05c-d118-db86f12ac404.png)
  ![スクリーンショット 2022-07-02 14.49.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/3c24b077-436e-ee25-9dcb-b2a2446076da.png)

1. ターゲットイベントを確認するためのConsumerを起動します。
1. Javaのアプリを実行します。
1. コンソールからのログです。
![スクリーンショット 2022-07-02 17.11.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/53339978-f254-f825-5d33-425cbca0720f.png)

1. Kafka-Consumerからのログです。
![スクリーンショット 2022-07-02 14.51.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089747/158c160d-d22a-2330-c718-2fae19478d17.png)

## 終わり
Log4jのAppend機能を使うことで追加で必要になったライブラリですが、kafka-client, slf4jなど必要になります。log4jのライブライだと、JDK６から使えるものですが、kafka-clientの最低要求JDKバージョンが8になるのでJDK６だと制約を受けることになります。
アプリにデータ集計のために追加でソースコードを記載しなくても済む方法になるので既存の資産を修正したくない場合には有効な方法になるかと思います。ただ、Kafkaを使っていますので追加で管理する箇所が発生する点とアプリログをKafkaに送ることで想定外のエラーが発生する可能性があります。
他のログライブラリだと、Logbackからもできそうですので、好みで選んでいただければと思います。
Google Photoの思い出をTweetするBotを作った

当記事で2018年から実装していた仕組みをリニューアルし、GCP上で構築しました。

- [AWS LambdaでGooglePhotosAPIから思い出の写真をTwitterに投稿 - Qiita](https://qiita.com/paper2/items/30cf7b2daa5a5f588cc5)
- [Twitter API を使って思い出を振り返る - Qiita](https://qiita.com/paper2/items/65e07ad14520510cc472)

最初はラズパイ上で動かし、次にAWS Lambdaで動かし、そして今回はCloud Functions上で動かしています。普段はインフラ系の業務が多くコーディングをしないので、「プログラミング楽しい〜」と言いながら作っています笑

続きははてなブログに記載しています。

[Google Photoの思い出をTweetするBotを作った - Paper2 Blog](https://paper2.hatenablog.com/entry/2022/07/02/144415?_ga=2.216099158.138539503.1656738751-624303411.1644039579)
[AWS] MySQL エンジンバージョン 5.7.36は非推奨

DBインスタンスのバージョンアップを推奨するメールがAWS来たので、
エンジンバージョンをアップデートしていたときのメモ。

対象のデータベースは、5.7.33　で停まっていたので、メジャーバージョン5の最新まで1バージョン毎アップデートしていきました。

ちなみに、1バージョン上げるのに、20分くらいかかりました。
バージョン更新中は、データベースに接続できなくなるので、注意です。

## 非推奨のバージョンにすると、設定が変更ができなくなる

5.7.36 にした際に、必須項目であるインスタンスを選択できなくなりました。
必須項目が選択できないと、他の設定項目を変更して、保存することもできなくなります。

操作できるようにするには、
エンジンバージョンを次のバージョンを選択します。
インスタンスクラスも値が入り、操作が保存できるようになります。

![スクリーンショット_2022-06-30_11_46_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8222/a37f96d7-d9d2-aaac-8b22-0a29e6289986.png)

バージョンは必ずしも1個ずつ上げなければならないことはないので、
非推奨のバージョンを飛ばして、次にバージョンを指定することができます。
Azure File Sync の Agent バージョンを確認する

How to check Azure File Sync Agent Version

ipmo 'C:\Program Files\Azure\StorageSyncAgent\StorageSync.Management.ServerCmdlets.dll'
Get-StorageSyncServer

	ServerId                           : xxxxxx
	SubscriptionId                     : xxxxxx
	ResourceGroupName                  : test-xxxxxx
	StorageSyncServiceName             : test-filesync-xxxxxx
	AgentVersion                       : 15.0.0.0
	AgentExpirationStatus              :
	AgentExpirationDate                :
	ManagementServiceUri               : https://xxxxxx-privatemanagement.eastus.afs.azure.net:443/
	MonitoringServiceUri               : https://xxxxxx-privatemonitoring.eastus.afs.azure.net:443/
	IsServerClustered                  : False
	ClusterId                          :
	IsAppLevelProxyEnabled             : false
	IsAppLevelProxyAuthEnabled         : false
	IsEnrolledToMicrosoftUpdate        : True
	IsDiagnosticsDataCollectionEnabled : True
	InstalledInUnattendedMode          : False
	IsEnrolledToAutoUpdate             :
	LastSuccessfulTime                 :
	LastAttemptedTime                  :
	UpdateSuccess                      :
	UpdateError                        : 0
	UpdatesInstalled                   :
	RebootNeeded                       :
様々な言語の 16進数リテラル

# これは何？

特に言語を限定するような話もせずに「16進数は頭に `0x` を付けます」のようなことが書いてある記事（もう見失っている）を見て、いや色々あるよ、と思ったので調べてみた。

# 調べてみた

## 0x... チーム

頭に `0x` をつける言語たとてもたくさんある。

C, C++, Objective-C, Haskell, OCaml, Perl, Python, PHP, Ruby, Java, JavaScript, C#, Swift, Go, Rust, ...

上記のリストを見る限り、C言語に由来しているように見える。

Cの祖先といえば BCPL ということで [BCPL のマニュアルらしきもの](https://www.cl.cam.ac.uk/~mr10/bcplman.pdf) を見てみると

```bcpl:たぶんBCPL
deadcode=#xDEADC0DE.
```

などとあるので、どうも BCPL 由来ではないらしい。

じゃあ B言語かなと思って [B 言語のマニュアルらしきもの](https://www.thinkage.ca/gcos/expl/b/manu/manu.html) を見ると、こちらには 16進数リテラルがそもそも存在しない。

C言語 をデザインするときに発明したものなのかなぁ。

`0` に続く `x` は、 he**x**adecimal の x なんだろうなぁと思う。

あと。
Haskell・OCaml などの、あまり C 言語の影響下に無さそうな人たちも `0x..` 方式を採用しているのに驚いた。
そう思うと C 言語由来じゃないのかもとも思うけど、どうなんだろう。

## Pascal と Delphi

Pascal とその末裔は

```pascal:pascal_or_dephi
val := $deadbeef;
```

のように、頭に `$` をつける。

じゃあ 8進数どうすんだって思うわけだけど、

`&377` のように別の記号を使う。贅沢だね。

## Basic とその末裔

Basic では、頭に `&h` をつける。この `h` は **h**exadecimal の h なんだと思う。

## Fortran

書き方が

* `Z'DEADBEEF'`
* `X'DEADBEEF'`
* `'DEADBEEF'X`

のように色々あるらしい。末尾に `Z` をつける例は見当たらなかった。

最初に書いた `Z'DEADBEEF'` が主流で、残りは非推奨っぽい。

なんで `Z` なのかというと。
https://fortran-lang.discourse.group/t/boz-constants-but-why-z/981/4
によると、X が使えなかったから、らしい。

## Common Lisp

`#16rDEADBEEF`

のように、`#` +基数+`r` を頭につけるらしい。

`r` ってなんだろ。

2022.7.4 追記: [コメントを頂き](https://qiita.com/Nabetani/items/a1969bc55f44912626e6#comment-bbce394f18fa6af812d9) ああ radix か、そりゃそうか、と思った。ありがとうございます。

よく使う 16進数 には `#x` というシンタックスシュガーもあって、

`#xDEADBEEF`

でもよいらしい。

## Smalltalk

`16rDEADBEEF`

のように書くらしい。Common Lisp と似ているね。

## Ada

`16#DEADBEEF#`

のように、 `16#`〜`#` で書くらしい。

## PL/I

[Enterprise PL/I for z/OS Language Reference - IBM](https://www.ibm.com/docs/en/SSY2V3_5.1.0/com.ibm.ent.pl1.zos.doc/lrm.pdf)

に

```PL/I
’100’XN /* same as ’00000100’XN with value 256 */
’8000’XN /* same as ’00008000’XN with value 32,768 */
’FFFF’XN /* same as ’0000FFFF’XN with value 65,535 */
```
とあるので、 `'DEADBEEF'XN` という形式らしい。

## CASLⅡ

`#DEAD` のように、先頭に `#` をつける。

じゃあ 8進数どうすんだって思うわけだけど、 8進数は書けないらしい。

# 調べて思ったこと

0x... 方式は

* 16進数であることを示すために必要な文字が 2文字だけ。
* `$` や `&` などの文字を特定の用途に専有することもない。
* 16進数以外も同じような記法で作れる。

と、わりと優れている感じがする。

これで「`0` で始まったら 8進数」というルールさえなければ手放しで絶賛なのだけど。


# まとめ

やっぱり色々あるね。

色々あるんだけど、新し目の言語の殆どは `0xdeadbeef` 方式を採用しているっぽい。

C 言語発祥なのかなぁ。

それと。[Wikipedia に素晴らしい記事]( https://en.wikipedia.org/wiki/Hexadecimal#Distinguishing_from_decimal )があることを [教えていただいた](https://qiita.com/Nabetani/items/a1969bc55f44912626e6#comment-6ca9805dd59b1f0cc912 )。
完全にこの記事より優れている。

この記事を見ると、 AT&T アセンブラ が発祥なのかもしれない（が、明確には書いていない）。

# お願い

この言語はこうだよ、みたいな情報をコメントに書いていただけると、私が喜びます。
Javaの開発環境を整理する（Mac+VScode）

しばらく個人PCを触ってなかったので更新します。

## やりたいこと
・Javaのインストール
・VScodeのインストール
・SpringBootのサンプルPJを動かす


使ってる機器はMacBook Air (M1, 2020)です


### Javaのインストール
最近のJDKはいくつか選択肢があり以下の記事が大変参考になります
https://qiita.com/gishi_yama/items/ee3526e7e7a922148333

JDK17を使いたかったので以下の17をインストールする
https://aws.amazon.com/jp/corretto/

```sh
kaikusakari@kais-MacBook-Air ~ % java -version
openjdk version "17.0.3" 2022-04-19 LTS
OpenJDK Runtime Environment Corretto-17.0.3.6.1 (build 17.0.3+6-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.3.6.1 (build 17.0.3+6-LTS, mixed mode, sharing)
kaikusakari@kais-MacBook-Air ~ % 
```

### VScodeのインストール
https://code.visualstudio.com/
最新の安定板1.68をインストールした

```json:VScodeのjavahomeの設定（json）
{
    "json.schemas": [
    {
        "fileMatch": [
            "/myfile"
        ],
        "url": "schemaURL"
    }
    ],
    "code-runner.clearPreviousOutput": true,
    "code-runner.runInTerminal": true,
    "files.exclude": {
        "**/.classpath": true,
        "**/.project": true,
        "**/.settings": true,
        "**/.factorypath": true
    },
    "editor.suggestSelection": "first",
    "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
    "java.jdt.ls.java.home":"/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home/",
    "java.debug.settings.exceptionBreakpoint.skipClasses": [
    
    ],
    "spring-boot.ls.java.home": "",
}
```

Gradle Language Support
Gradle for Java

### サンプルを動かす
以下をデプロイする
https://spring.pleiades.io/guides/gs/spring-boot/
https://github.com/spring-guides/gs-spring-boot

いけました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110457/e3ad1ee0-03ef-f27f-3ff8-8ec85860e890.png)

JDKやVSCodeを最新のバージョンに更新しました。実際に開発を進める上での準備はできましたので今後は検証環境の構築を進めていきます。PC上にLinuxのVMを起動してDockerで動かしながら検証を進めていきたい。

並列してTypeScriptフロントエンドの知識の棚卸も進めていってますが、まずはサーバーサイド側の知識を整理します。
【Python】変数に無限大を設定する方法

# 無限大を設定する方法
* [float()の引数に"inf"を渡す](#floatの引数にinfを渡す)
* [math.infを使う](#mathinfを使う)
* [numpy.infを使う](#numpyinfを使う)

## float()の引数に"inf"を渡す
```python
inf = float("inf")
infinity = float("infinity")

print(inf)
print(infinity)
```
```
inf
inf
```

## math.infを使う
```python
import math 

inf = math.inf

print(inf)
```
```
inf
```

## numpy.infを使う
```python
import numpy as np

inf = np.inf

print(inf)
```
```
inf
```
Linux（ハードリンクとシンボリックリンク）

# ■はじめに
Linuxの基礎を学んでいる、インフラエンジニアです。
LinCの試験取得に向けて、学んだ内容を記事にしていきます。

今回はハードリンクとシンビリックリンクについて、書いていこうと思います。


# ■前段
ハードリンクとシンボリックリンクの前段理解として、
iノードについて理解していきました。

`iノード`
ファイルの作成者・グループ・作成日時・サイズ等の属性情報が格納されており、
iノードはファイルシステム毎に管理されている。

詳しくは、以下の記事がわかりやすいです。
https://kazmax.zpp.jp/linux_beginner/inode.html


# ■内容
`ハードリンク`
ファイルには、それぞれ対応するiノードが存在する。
ハードリンクでは、ファイルの実態(iノード)に別名をつけること。
inode番号は全て同一であり、複数のハードリンクがある場合その全てを削除しない限りファイルの実態は削除されない。

lnコマンドを使うと、別名でハードリンクを作成することができる。
~~~
lnコマンド
$ ln 参照元 新規のハードリンク名
~~~

`シンボリックリンク`
windowsのショートカットみたいな、リンク元の場所を指すリンク。
シンボリックリンク作成時の参照元となっているファイルにつながったダミーファイル。
ファイルの実態を参照しているわけではないので、リンク元のファイルが消えればリンク切れとなり参照することができない。
※inode番号は異なる番号が付与される。
~~~
シンボリックリンクはln コマンドに-s オプションで作成。
$ ln -s 参照元　シンボリックリンクのファイル名
~~~