OmniAICreator/Qiita-1.07M huggingface dataset:
SQLAlchemy 2.0でよく使う文法まとめ

### はじめに

PythonのRDBのORMapperの代表的なものとしては、SQLAlchemyがメジャーかと思います。
今SQLAlchemyはメジャーバージョン2へのアップデートへの移行に伴い、バージョン1.4では新しい文法を使えるようになっています。

新しい文法での、一般的なクエリの書き方を備忘的に残します。

### コネクションの作成

```python
from sqlalchemy import create_engine
from sqlalchemy.engine.url import URL
engine = create_engine(URL(...接続設定))

print(next(engine.execute('select 1')))

with engine.connect() as conn:
    print(next(conn.execute('select 1')))
```

エンジンオブジェクト自体もクエリを実行できるし、コネクションオブジェクトもクエリを実行できる

### セッションの作成

```python
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
engine = create_engine("sqlite+pysqlite:///:memory:")

with Session(engine) as session:
    print(next(session.execute('select 1')))
```

セッションも従来と同じように作成できる

### モデルの作成とShowTables

```python
from sqlalchemy import create_engine, Column
from sqlalchemy.dialects.mysql import VARCHAR
from sqlalchemy.engine.reflection import Inspector
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class User(Base):
    __tablename__ = "user"

    user_id = Column(VARCHAR(10), primary_key=True)
    user_name = Column(VARCHAR(10))

engine = create_engine("sqlite+pysqlite:///:memory:")

print(Inspector(engine).get_table_names())
Base.metadata.create_all(engine)
print(Inspector(engine).get_table_names())
```

### Insert

エンジンとモデルは上記を再利用しています

```python
from sqlalchemy.orm import Session
from sqlalchemy import select

with Session(engine) as session:
    session.add(User(user_id="test_id1", user_name="test_name1"))
    session.commit()

print(engine.execute(select(User)).all())
```

モデルを使う書き方は、上記のような以前と変わらない書き方や、下記のような書き方もできるようになっています


```python
from sqlalchemy import insert

engine.execute(
    insert(User)
    .values(user_id='test_id1', user_name='test_name1')
)

print(engine.execute(select(User)).all())
```

### Select

#### where

```python
from sqlalchemy.orm import Session
from sqlalchemy import select

with Session(engine) as session:
    session.add(User(user_id="test_id1", user_name="test_name1"))
    session.add(User(user_id="test_id2", user_name="test_name2"))
    session.commit()

stmt = select(User).where(User.user_name == 'test_name2')
print(engine.execute(stmt).all())
```

#### group_by

```python
from sqlalchemy.orm import Session
from sqlalchemy import select, func

with Session(engine) as session:
    session.add(User(user_id="test_id1", user_name="test_name1"))
    session.add(User(user_id="test_id2", user_name="test_name2"))
    session.add(User(user_id="test_id3", user_name="test_name2"))
    session.commit()

stmt = (
    select(User.user_name, func.count())
    .group_by(User.user_name)
)
print(engine.execute(stmt).all())
```
Lambdaの中からS3のPythonファイルをインポートする

# 背景・目的

AWSのLambdaをPythonで利用するとき、外部ライブラリをパッケージにまとめてデプロイするのが一般的かと思います。
その場合、パッケージのバージョンは固定されることになるのですが、あるとき、実行時にS3に配置したPythonファイルを実行時に読み込むというケースがあったので、その実現方法について備忘します。


# システム構成


```plantuml
package AWS {
   database S3
   () Lambda
}

Lambda <-up- S3 : Pythonファイルを読み込み
```

# 例

### S3にアップロードするファイル

下記の内容を`s3://some-bucket-name/uploaded_script.py`というパスにアップロードすると仮定します。インポートの挙動を確認するために、少し冗長ですが、標準ライブラリであるjsonをインポートしています。

```python
import json

def hello():
    print(json.dumps({"hello": "world"}))
```

### Lambdaのスクリプト

import_from_s3という関数でS3をインポートする例は下記のようなスクリプトになります。

```python
import json  # Lambdaのスクリプトで使っていなくても、S3側のファイルで必要なのでインポートが必要
import boto3

def split_s3_path(s3_path):
    """
    s3://bucket_name/some/path
    を
    bucket_name, some/path
    に分割する
    """
    parts = s3_path.split("/")
    assert len(parts) >= 4, "S3のパスのパーツがあっていません"
    bucket = parts[2]
    key = "/".join(parts[3:])
    return bucket, key

def get_python_script(s3_client, s3_path):
    bucket, key = split_s3_path(s3_path)
    return s3_client.get_object(Bucket=bucket, Key=key)["Body"].read().decode("utf-8")

def import_from_s3(s3_client, s3_path, module_name):
    """
    S3上にあるpythonファイルからインポートする
    """
    exec(get_python_script(s3_client, s3_path))
    return locals()[module_name]

def handler(event, context):
    s3_client = boto3.client('s3')
    hello_func = import_from_s3(s3_client, "s3://some-bucket-name/uploaded_script.py", "hello")
    hello_func()
```

これを実行すると、S3側のファイルの関数を実行することができます。

# まとめ

今回は、結構レアなケースかと思うのですが、S3上のPythonファイルをインポートできる方法について書きました。
実際に利用される際には、Lambdaのセキュリティ面で穴を一つ増やしてしまうことになるので、ご注意ください。
自動コードレビューツールSonarCloudを導入してみて

### はじめに

ここ半年間ぐらい、[SonarCloud](https://sonarcloud.io/?gads_campaign=Row-2-SonarClouds&gads_ad_group=SonarCloud&gads_keyword=sonarcloud&gclid=Cj0KCQjw37iTBhCWARIsACBt1Iy7M7VyaLJJOSvd8-4xIPv0n6UmzGwBAtdpjQXdMzxmmJC3QPD2BeoaAhLvEALw_wcB)とGitHubを連携してPullRequestのレビューを一部自動化しているのですが、
その使用感について振り返ってみたいと思います

### SonarCloudって何

一部無料で使える、自動コードレビューのためのSaaSです。
GitHubと連携すると、PullRequestをバグ・脆弱性・コードスメル・コード重複などの視点で自動レビューし、問題があればステータスに反映してくれます。チェックの結果は下の図のようなイメージでPullRequestに表示されます。
色々なプログラミング言語に対応しているのですが、うちではPythonとTypeScriptのプロジェクトに対して適用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144584/9ba2a65b-eccc-f91e-9778-87f50f6aabac.png)

（画像引用: [SonarCloud公式の機能説明ページ](https://sonarcloud.io/github?gads_campaign=Row-2-SonarCloud&gads_ad_group=SC-GitHub&gads_keyword=github%20sonarcloud&gclid=Cj0KCQjw37iTBhCWARIsACBt1IxaRCkeFzYqjAJQ6myYhQ27oU8kHWVbuwdDTY3uvNHmRvrhPkoVxHAaAuHAEALw_wcB))

### 使ってみて

実際に使ってみると、たまに人でのレビューが行き届かないバグを見つけてくれることもあり、コードの品質を維持する目的ではとても役に立っていると思います。
VSCodeのプラグインなども提供してくれているため、PullRequestに出す手前の段階でも事前に一部の問題に気づくこともできるような工夫があってありがたいです。

悩ましいところとしては、PullRequestに表示されるのはあくまでもバグの個数などで、指摘内容の詳細についてはSonarCloudのWebページに遷移して確認する必要があり、そのときにログインが必要になるのですが、そこで1ステップ挟まってしまうのでどうしても確認のための心理的ハードルが高くなってしまうということがあります。
また、自動チェックだと避けられない部分もあるとは思うのですが、うちの場合テストコードなどを書くときにどうしてもコード重複が発生することがあり、それが原因でチェックが通らないことも多々あります。そういうときは、SonarCloudを無視してマージせざるを得なくなるのですが、その辺り、適切に運用するためには、開発スタイルにあったチェックのルールをメンテナンスする必要は出てくるかと思います。（その辺り、ルールをカスタマイズできるようにはなっています）

### まとめ

短くなってしまいましたが、備忘的にSonarCloudの使用感について振り返ってみました。
まだまだ、これから成長しているSaaSだと思うので、これからさらに進化することを期待しつつ使っていきたいと思います。
GitHub copilotとかもそうですが、どんどんコードの解析が賢くなっていて、いつかコードを書かなくても良い日が来るのではないかと期待してしまいますね。
ラズパイにAdgurd homeとPiVPNで俺俺VPNに繋げばDNSブロックできるようにした

いつもの箇条書き

# Q：なぜNextCloudタグがついているんですか？<br>A:オンプレでNextCloudがすでに動いてるマシンにAdgurdHomeのっけたから。(ポート80の奪い合いが発生)

# 結論から
- オンプレのNextCloudは退けれなかったのでAdgurdHomeはDockerで起動した
- ポート53はDNSで指定する都合なんとかフリーに開けてね！(うちではたまたま使ってなかった)
- その後OpenVPNをPiVPNでDNSを自分指定で立てた
- セキュリティ設定その他は各自の環境に合わせて頑張ってね！（ここでは取り扱わない）

# 最初にやること
+ **現環境をDDコマンド等できちんとバックアップ取ること**(下記手順試行錯誤の過程で何度か環境壊れたのでバックアップしてないと詰んでた)
+ Dockerを動かせる環境の準備

どちらも詳細は特に書く予定はないので必要に応じて調べてください。

# 詳細と参考にしたページ
- DockerのAdGurdHomeの設定は下記のページの内容をベースにカスタマイズしたものを使用
https://zenn.dev/zilch/articles/b915c82c23c326
ポート80や443の奪い合いを調整したdocker-compose.yml
重要なのはXXXXと伏せ字にしたところを適当な使ってないポートに変えてNextCloudなどの既存の80番と取り合わないようにするところ(53はなんとか開けよう)
```
version: "3"

services:
  adguard:
    image: adguard/adguardhome:latest
    ports:
      - '53:53/tcp'
      - '53:53/udp'
      - 'XXXXX:80/tcp'
      - 'XXXXX:443/tcp'
      - '3000:3000/tcp'
    volumes:
      - './work:/opt/adguardhome/work'
      - './conf:/opt/adguardhome/conf'
    restart: unless-stopped
```
- ひとまずこの時点でAdGurdHomeのDNSがちゃんと動いてるかをPCなどからDNSを直接変更して確認する
- 次にPiVPNを下記の記事を参考にインストール
https://qiita.com/morinokami/items/8b58f210c2bdec2b13cd
  - 重要な点1つ目として**OpenVPNを選ぶこと**。(WireGuardでは下記のDNS設定をするとうまく繋がらなくなった)
  - ここで重要なのは途中のDNS設定の場面で**固定済み(のはず)の自身へのローカルIPを指定すること**。(IPV4環境でのみ確認、127.0.0.1でもOKなのかは確認していない)
  - DDNSサービスは予め取得しておくこと、こちらなどを参照(下記ではWireguardをセットアップしている)
  https://raspida.com/pivpn 
- 最後に普通に？VPNファイルを作り接続する

上記手順で作ったVPNに繋いだ状態で広告ブロックされていれば成功。

# 余談
- PiVPN自体にPi-holeがついている？ようなのでちゃんと設定できるならAdGurdHomeをわざわざ別に入れなくても多分良さそうな気はする(設定の仕方がわからなかった)
- 上記の仕様のためかPi-holeを何も考えず入れると環境ぶっ壊れる(壊した)
- また、Pi-holeをDockerで動かしてみたが思うように動作せずAdGurdHomeに切り替えることに(多分おま環と知識不足が原因)
- Docker関係は下記のURLを参考にした
https://qiita.com/morinokami/items/8b58f210c2bdec2b13cd
https://qiita.com/taiga_tech/items/d9361f10d521a55659ee
https://junchang1031.hatenablog.com/entry/2016/05/18/000605
https://qiita.com/eijenson/items/25b35916afa38cdf9cea
https://www.takunoko.com/blog/docker-compose%E3%81%A7docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%92os%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AB%E7%AB%8B%E3%81%A1%E4%B8%8A%E3%81%92%E3%82%8B/
https://qiita.com/okyk/items/a374ddb3f853d1688820
Laravelのメールアドレス確認用メールのテンプレートを変更し、テキストメールで送信する

Laravelのメールアドレス確認メールのテンプレート変更について、なかなか情報に行き当たらなかったので備忘録的に書いておきます。

## 対象バージョン

Laravel: 8.0

## やりたかったこと

- ユーザー登録後、メールアドレス確認用のメールを送信する
- 送信したメールアドレスに確認用のURLを記載して、そのURLをクリックしたらサイトに飛ばす
- 飛んだ先のサイトで認証し、メールアドレスを確認済みとする
- **このメールアドレス確認用メールをオリジナルのテキストメールにしたい**

## やったこと

- [この記事](https://codeanddeploy.com/blog/laravel/how-to-implement-laravel-8-email-verification)を参考に、メールアドレス確認メールの実装をした （認証自体もこの記事内になるURLを参考にしました）
- [この記事](https://helog.jp/laravel/notification-text-mail/)を参考に、テキストメール用のオーバーライドクラスを作成した
- [公式](https://readouble.com/laravel/8.x/ja/verification.html) にある記事を参考に、AuthServiceProviderのbootに記述を追加した

## 参考になりそうなソースコード

```php:app/Providers/AuthServiceProvider.php

<?php

namespace App\Providers;

use App\Services\MailService;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Notifications\Messages\MailMessage;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array<class-string, class-string>
     */
    protected $policies = [
        // 'App\Models\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        // メールアドレス確認メールを変更
        VerifyEmail::toMailUsing(function ($notifiable, $url) {
            return (new TextMail)
                ->subject('メールタイトル')
                ->from(getenv('FROM_EMAIL_ENTRY'))
                ->to($notifiable->email)
                // テキストを選択、ビューと変数を指定できる
                ->text(
                    'email.email_verify_mail', [
                        'email' => $notifiable->email,
                        'url' => $url
                    ]
                );
        });
    }
}

// Mailableをオーバーライドしたクラス
class TextMail extends Mailable {
    use Queueable, SerializesModels;
    public function build() {}
}


```
【Terraform AWS】既存IAMユーザーにIAMポリシーを付与する

# はじめに
Terraformで既存のIAMユーザーにIAMポリシーを付与する方法です。

# 説明
IAMポリシーはAWS管理ポリシーのAmazonEC2FullAccessをデータリソースとして取得しました。
IAMユーザーもタイトルにあるように既存のIAMユーザーを取得しました。
aws_iam_user内のxxxxxxはポリシーを付与したいIAMユーザー名を指定します。

# コード
```tf
# IAMポリシー取得
data "aws_iam_policy" "policy_01" {
  arn = "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
}

# IAMユーザー取得
data "aws_iam_user" "user_01" {
  user_name = "xxxxxxxx"
}

# IAMユーザーにIAMポリシーを付与
resource "aws_iam_user_policy_attachment" "attach" {
  user = data.aws_iam_user.user_01.user_name
  policy_arn = data.aws_iam_policy.policy_01.arn
}
```

# 参考サイト
Terraformの公式ドキュメントは読みやすく分かりやすい
* [Data Source: aws_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy)
* [Data Source: aws_iam_user](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_user)
* [Resource: aws_iam_user_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy_attachment)
Vagrant コマンド一覧（随時更新予定）

業務で使ったり、自分で調べて理解できたVagrantコマンドを備忘録として一覧にしてみる
# Vagrantって？
[![Image from Gyazo](https://i.gyazo.com/3cbdf5c44460f8e8e4707ed7eab17def.png)](https://gyazo.com/3cbdf5c44460f8e8e4707ed7eab17def)

パソコン上に作る偽物のパソコンを仮想マシンとか、仮想環境とか言います。
自分のローカルパソコン上に、いくつかのパソコンをエミュレートさせることができる便利なツール`Virtualbox`。(virtualbox以外にも仮想環境を作るツールはあるみたい)
[Virtualboxについて](https://qiita.com/Shi-raCanth/items/aed05bea93c56e1bba8b)


 **Vagrantは管理ツールとして、その作られた仮想マシンを操作するのに利用される**

そしてその操作に使うのがVagrantコマンドというわけでして、コマンドプロンプトやターミナルで打ち込みます

# コマンド一覧

|コマンド|効果|備考|
|-----|---|----|
|vagrant --version|Vagrantのバージョン確認|「vagrant -v」も同じ|
|vagrant up|仮想マシンの起動|vagrantfileのあるディレクトリで実行|
|vagrant halt|仮想マシンの終了|virtualboxでは"電源オフ"の状態|
|vagrant reload|仮想マシンの再起動|upとhalt|
|vagrant ssh|仮想マシンへの接続、ログイン||

今のところ業務で使ったコマンドです。
調べてみると、まだまだたくさんある…
これからどんどん追加していきたいなぁ

<br>
※補足等ありましたらコメントしていただけると幸いです。
Easy OCR memo

# はじめに

Easy OCRに関するメモです。

# Easy OCRの設置


```python
pip install easyocr
```

* CUDA利用時は、easyocrの設置前にtorchをインストールする必要があります。

** opencvとクラッシュを起こすときがあります。
2022年5月の基準に、opencv-python==4.5.4.60がOKです。

```python
 pip uninstall opencv-python-headless
 pip install opencv-python==4.5.4.60
```

# Easy OCRの利用

```python

import easyocr

#インスタンスを立てます
reader = easyocr.Reader(['en'])

#numpy arrayを入力
img_path = './image/001.png'
img_array = cv2.imread(img_path)

#OCR実施、結果を返してもらう。
result = reader.readtext(img_path)

```


# 画像のOCR

```python

import cv2
import easyocr

import numpy as np

reader = easyocr.Reader(['en'])
font = cv2.FONT_HERSHEY_SIMPLEX


def draw_boxes(img, result):
    for detection in result:
        p0 = tuple((detection[0][0]))
        p1 = tuple((detection[0][1]))
        p2 = tuple((detection[0][2]))
        p3 = tuple((detection[0][3]))
        points = np.array([p0, p1, p2, p3],dtype=np.int32)

        text = detection[1]
        confidence = round(detection[2],2)
        img = cv2.polylines(img, [points], True, (255, 0, 0), thickness = 2)
        print('p0',p0)
        img = cv2.putText(img, text , (int(p0[0]), int(p0[1])) , font, 1, (255, 0, 0), 2, cv2.LINE_AA)

    return img


#numpy arrayを入力
img_path = './image/001.png'
img_array = cv2.imread(img_path)

img2 = draw_boxes(img_array, result)
cv2.imshow('box', img2)

cv2.waitKey(0)

```

# output format

```python
result = 
[([[189, 75], [469, 75], [469, 165], [189, 165]], '愚园路', 0.3754989504814148),
 ([[86, 80], [134, 80], [134, 128], [86, 128]], '西', 0.40452659130096436),
 ([[517, 81], [565, 81], [565, 123], [517, 123]], '东', 0.9989598989486694),
 ([[78, 126], [136, 126], [136, 156], [78, 156]], '315', 0.8125889301300049),
 ([[514, 126], [574, 126], [574, 156], [514, 156]], '309', 0.4971577227115631),
 ([[226, 170], [414, 170], [414, 220], [226, 220]], 'Yuyuan Rd.', 0.8261902332305908),
 ([[79, 173], [125, 173], [125, 213], [79, 213]], 'W', 0.9848111271858215),
 ([[529, 173], [569, 173], [569, 213], [529, 213]], 'E', 0.8405593633651733)]

```

ここで、リストの各エレメントを見ると、'(a bounding box,  the text detected, confidet level)' である。
```python
(a bounding box,  the text detected, confidet level) 

([[189, 75], [469, 75], [469, 165], [189, 165]], '愚园路', 0.3754989504814148)


p0 = tuple((detection[0][0])) -> (189, 75)
p1 = tuple((detection[0][1])) -> (469,75)
p2 = tuple((detection[0][2])) -> (469,165)
p3 = tuple((detection[0][3])) -> (189,165)
points = np.array([p0, p1, p2, p3],dtype=np.int32)

text = detection[1] -> '愚园路'
confidence = round(detection[2],2) -> 0.37

```
https://github.com/JaidedAI/EasyOCR
2022年春、WindowsでPythonはじめるためにDockerいれる

「そうだ、Pythonで機械学習やろう」と思い立ったので、自PCのwindowsへPython環境を構築することにする。

# 方針検討
いろんなアプリケーションを入れると諸々干渉し合うことがある。
Dockerを導入すると、そういった環境構築で躓くことはなさそう＆定番のやり方っぽいので、これでいく。

Anacondaが機械学習にいいらしい。

https://qiita.com/ku_a_i/items/8c7d91f6e13a5091f51c


この中でWindowsでDockerを始める手順があったので、この通りやっていく。

https://qiita.com/techpit-jp/items/f4a1319a909dd508f372

# 実践

ほとんどこの記事どおりで進んでいける。素晴らしい。

Ubuntu 20.04.4 LTSも同様。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23504/46a0f225-f210-06fc-00ec-5c470fb0b62b.png)

記事と少し違う点も。1年前ですし。Windowsのリンクをクリックするとダウンロード開始した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23504/a9ccf468-3060-1fc5-3808-fdf4034275e1.png)

ででどん。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23504/c8476eaa-abd3-923c-348c-b3a97da6d404.png)
機能設計にかかせない考え方「プロコン」とは？

## はじめに
「いつも上司に指示を仰がずに、自分で考えてみてよ」と言われること、ありませんか？
そんな時に「プロコン」というフレームワークを使ってみましょう。
一見、悩ましくて判断できなそうな問題でも、クリアに意思決定できるようになるはずです。

## 対象者
この記事は下記のような人を対象にしています。

- 駆け出しエンジニア
- プログラミング初学者
- なかなか自分で決められないマン

## 結論
プロコンを使うと、「これ、どっちにしようかな〜」と悩んでいることがクリアに判断できるようになります！

## プロコンとは？
プロコンとは、意思決定をしやすくするためのフレームワークの一つです。
Pros(賛成意見)とCons(反対意見)を箇条書きにしてリスト化することで、複雑そうに見える課題を決断しやすくするものです。

早速、具体例を見てみましょう！

## プロコン活用例1
プロコンは機能実装する際に大活躍します。
例えば、「フォームのラジオボタン部分をコンポーネント化したいんだけど、めんどくさいなぁ。どうしようかなぁ」と悩んでいる時に使えます。

まずは単純なプロコンのフレームワークで整理してみましょう。

黒字：Pros(賛成) / <font color="Red">赤字：cons(反対)</font>
| プロコン |    コンポーネント化する     |    コンポーネント化しない(都度ベタ書き)    |
|:-:|-------------|------------|
| Pros(賛成)  |コード表記が揃い、可読性UP。|フォームの実装が容易。|
| Cons(反対)  |<font color="Red">コンポーネント作成に手間がかかる。</font>|<font color="Red">表記揺れによりコードの可読性DOWN。</font>|

上記のままだと、まだ悩ましいですね。
プロコンにさらにQCD(品質、コスト、納期)の考え方を加えると、わかりやすくなります。

| QCD |    コンポーネント化する     |    コンポーネント化しない(都度ベタ書き)    |
|:-:|-------------|------------|
| Quality(品質)  |可読性UP。|<font color="Red">可読性DOWN。</font>|
| Cost(コスト)  |<font color="Red">コンポーネント作成が手間。<font>|フォームの実装が容易。|
| Delivery(納期)  |レビュー時間短縮。|<font color="Red">レビューに時間がかかる。<font>|

これなら、コンポーネント化する方が良さそうに見えますが、まだ定性的なので決めづらそうです。
最後に、定量情報を補足してみましょう。

| QCD |    コンポーネント化する     |    コンポーネント化しない(都度ベタ書き)    |
|:-:|-------------|------------|
| Quality(品質)  |可読性UP。|<font color="Red">可読性DOWN。</font>|
| Cost(コスト)  |<font color="Red">コンポーネント作成が手間(5時間)。<font>|フォームの実装が容易。|
| Delivery(納期)  |レビュー時間短縮(10分/回)。|<font color="Red">レビューに時間がかかる(1時間/回)。<font>|

こうなると、このコンポーネントが何回使われるか、で意思決定できますね。
6回以下だった場合、あえてコンポーネント化しない選択になります。
6回以上であれば、コンポーネント作成の手間以上にレビュー時間を短縮できるメリットの方が大きくなるので、コンポーネント化する選択になるでしょう。

## プロコン活用例2
「自分はまだ設計とかしない駆け出しプログラマーなので、プロコンは不要かな...」と思っているそこのあなた！
あなたの日常業務でもプロコンの考え方は活かせます。
例えば、社内システムにデータを入力する提携業務があるとします。
これを、現状維持で続けるか、自動化を検討するか、意思決定するのにプロコンで考えてみましょう。

黒字：Pros(賛成) / <font color="Red">赤字：cons(反対)</font>
| QCD |    現状維持(都度入力)     |    自動化を検討する    |
|:-:|-------------|------------|
| Quality(品質)  |<font color="Red">入力ミスをする可能性。</font>|入力ミスが無くなる。<br>他人に任せられるようになる。|
| Cost(コスト)  |慣れた手順で出来る。|<font color="Red">自動化スクリプト作成に手間がかかる。</font>|
| Delivery(納期)  |<font color="Red">入力に時間がかかる。</font>|作業時間が短縮できる。|

上記のままだと、定性的なので、判断が付きづらいですね。
定量データを入れてみましょう。

| QCD |    現状維持(都度入力)     |    自動化を検討する    |
|:-:|-------------|------------|
| Quality(品質)  |<font color="Red">入力ミスをする可能性(1回/月)。</font>|入力ミスが無くなる。<br>他人に任せられるようになる。|
| Cost(コスト)  |慣れた手順で出来る。|<font color="Red">自動化スクリプト作成に手間がかかる(10時間)。</font>|
| Delivery(納期)  |<font color="Red">入力に時間がかかる(1時間/週)。</font>|作業時間が短縮できる(5分/週)。|

こうなってくると、11週以上この業務をやる場合は自動化した方がメリットが大きいですね。
逆に1ヶ月しかやらない業務の場合は、あえて現状維持する方がメリットが大きそうです。

このように、個人のタスクでもプロコンの考え方を使えば、簡単に意思決定ができるようになるので、おすすめです！

## おわりに
プロコンについてまとめました。
日常業務で悩んだら、プロコンで状況を整理して、より効率の良い意思決定をしましょう！
MMDをThree.jsに読み込んでも、なんかWebGLのシェーダーエラーが出るよ！

# せっかちな人へ

r133でリファクタリングが行われているのでMMDToonShader.jsが最新の場合はThree.jsのバージョンをr133以上にしましょう。

# 何がしたいの？

MMD動画を見ていたら、唐突に自作ゲーム（Electron＋Three.js）のキャラモデルにMMDを使用可能にしたくなりました。[^1]

# 唐突なシェーダーエラー

![twitter_FThy6MuVIAEHqgM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2309889/f701aacf-3da0-169b-b6c2-44fb1302f65f.jpeg)

他のどんなサイトでもこの方法でうまく行っているのに、なぜかシェーダーエラーが出ます。

`no matching overloaded function not found`と言っているので言いたいことはわかります。

**が、シェーダーの知識は全くないので修正することができません。オワタ。**

# Google先生お願いします

BRDF_BlinnPhongでぐぐると、Three.jsの変更点についてまとめているサイトがありました。

https://scrapbox.io/0b5vr/Three.js%E3%82%92%E8%BF%BD%E3%81%A3%E3%81%8B%E3%81%91%E3%82%8B

![スクリーンショット 2022-05-24 23.06.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2309889/ed8b0b39-8430-d41c-8638-da68a5226725.png)

**BRDF_BlinnPhongの引数が変わっている…？**

```js:MMDToonShader.js（一部抜粋）
reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;
```

**使っている心当たりしかありません。**

なにやらr133でBRDF_BlinnPhongの引数のリファクタリングが行われたようです。

それと、このコミットにはMMDToonShader.jsのアップデートも含まれているようです。
MMDToonShader.jsをダウンロードしたのは数時間前のことなので、こちらのアップデートは不要だ、と判断したのですがThree.jsのアップデートはしたような記憶がありません。

# アップデートって重要

差し替えたところ動きました。

アップデートは様子を見て…と言いつつ結局アップデートするのがかなり遅くなる派の私ですが、ライブラリのアップデートは積極的にしていこうと思いました。まる。

![スクリーンショット 2022-05-24 23.05.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2309889/2a0c5dea-3b6c-4780-cb07-09e3a8aadd33.png)[^2]

ご覧いただきありがとうございました。良きThree.js＋MMDライフを。

[^1]: 私は無駄機能を作ることが大好きです。
[^2]: 足しか写っていませんが、にがもん式霊夢V01_s05aです。
[AWS Puppeteer on Lambda ] ロングスクロールページをスクショする

## 背景
Lambda上でPuppeteerを動かして,
指定したWebページをスクショする機能がある.

Webページの中にはものすごく長いページ(ロングスクロール)が存在する.
このようなページをスクショしようとすると下記のエラーが発生して処理が終わる.

https://github.com/puppeteer/puppeteer/issues/5341

今回, Lambda上で動くPuppeteerにおいて,
これを乗り越えてものすごく長いページでもスクショができる方法がわかったので,
同じように長いページをスクショしたい勢に向けて贈る.

## 対応方法

### Lambdaのエフェメラルストレージを増やす

最近更新されたコメントによってエラーの詳細が明らかになった.

つまるところ, /tmpディレクトリの容量が足りてないらしい.
https://github.com/puppeteer/puppeteer/issues/5341#issuecomment-1118387787


Lambdaは最近, /tmpディレクトリの容量増やせるようになったので下記を参考にしながら増やしましょう.
https://aws.amazon.com/jp/blogs/news/aws-lambda-now-supports-up-to-10-gb-ephemeral-storage/

### launchのargsにオプションを設定

実はエフェメラルストレージを増やしただけだと取れなかった.
下記のエラーが出る.
`[0524/103738.281035:ERROR:tile_manager.cc(821)] WARNING: tile memory limits exceeded, some content may not draw`

https://github.com/puppeteer/puppeteer/issues/5530

タイルメモリの制限を超えているらしい.

これはコメントにある通り, 
launchのargsに `--force-gpu-mem-available-mb` を設定すると良い.
我々は下記のように設定.

```ts
module.exports = async (args) => {
    const browser = await chromium.puppeteer.launch({
        args: chromium.args.concat(['--force-gpu-mem-available-mb=4096']),
        defaultViewport: chromium.defaultViewport,
        executablePath: await chromium.executablePath,
        headless: chromium.headless,
    });

...以下略
```

これで取れるようになった.

※ オプションは下記に一覧がまとまってます
https://peter.sh/experiments/chromium-command-line-switches/

## 最後に
あまり需要がないケースかもしれませんが,
もし困っている人がいたら参考にしていただければと.
new Map()について

# 初める前に
転スラ書籍の小説読み進めないとちょっとネタバレになるかもです💦


# 初めに
今回業務でnew Map()に大いに助けられたので、備忘録として記載していこうと思います。
かなり便利な関数なので、皆さんも積極的に使用していただけたらと思います！

# new Map()関数とは
そもそもnew Map()とは何かについてですが、ざっくり説明すると[{key, data}]で格納されているiterateble型になっています。

例えば、リムルの配下をmapで格納したい場合は以下のようになります。

```js
const mapData = new Map()
mapData.set('リムル・テンペスト', {
 '魔神王': 'ディアブロ',
 '幽幻王': 'ゼギオン',
 '赫怒王': '紅丸'
})

console.log(mapData)

// Map(1) {size: 1, リムル・テンペスト => {魔神王: 'ディアブロ', …}}

// 中身
// key:'リムル・テンペスト'
// value:{魔神王: 'ディアブロ', 幽幻王: 'ゼギオン', 赫怒王: '紅丸'}
```

# mapDataに格納した対象keyのデータを取得したい(`map.get(key)`)
上記でリムル・テンペストというkeyでmapDataにデータを格納したのでそのデータを取得したい場合は以下の通り

```js
console.log(mapData.get('リムル・テンペスト'))
// {魔神王: 'ディアブロ', 幽幻王: 'ゼギオン', 赫怒王: '紅丸'}
```

# new Map()で格納したデータをfor文などで回したい
1件ずつmapDataの中身を確認したい場合などでfor文等でループ処理を行いたい場合は以下の通り
```js
// forの場合
for(const [key, value] of mapData.entries()){
  // keyがリムル・テンペスト、valueが{魔神王: 'ディアブロ', 幽幻王: 'ゼギオン', 赫怒王: '紅丸'}
  // 処理
}

// forEachの場合
mapData.forEach(value, key, index){
  // keyがリムル・テンペスト、valueが{魔神王: 'ディアブロ', 幽幻王: 'ゼギオン', 赫怒王: '紅丸'}
  // 処理
}
```

# 対象のkeyにデータを追加したい(`map.set()`と`map.get(key).カラム名`の組み合わせ)
リムルの聖魔十二守護王で残っている人物を追加したい場合は（今回はシオンを追加）以下の通り
```js
mapData.set('リムル・テンペスト', {
  '魔神王': mapData.get('リムル・テンペスト')['魔神王'],
  '幽幻王': mapData.get('リムル・テンペスト')['幽幻王'],
  '赫怒王': mapData.get('リムル・テンペスト')['赫怒王'],
  '闘神王': 'シオン'
})

console.log(mapData)

// key:'リムル・テンペスト'
// value:{魔神王: 'ディアブロ', 幽幻王: 'ゼギオン', 赫怒王: '紅丸', 闘神王: 'シオン'}
```

注意点として以下のように記載してしまった場合は、上書きされてしまうので要注意です
```js
mapData.set('リムル・テンペスト', {
  '闘神王': 'シオン'
})

console.log(mapData)

// key:'リムル・テンペスト'
// value:{闘神王: 'シオン'} <- ディアブロ、ゼギオン、紅丸がいなくなっている
```

意図して上書きする場合は問題ないのですが、既に入れたデータを引き継ぎたい場合は`map.get(key).カラム名`を記載しましょう

# 対象のkeyがあるかないかの確認(`map.has(key)`)
new Map()でどのkeyを書いたか忘れてしまった場合は、`map.has(key)`で既に格納していたらtrue、していないならfalseを返します
今回の場合で言うと以下の通りとなります
```js
const rimuru = mapData.has('リムル・テンペスト')
const milim = mapData.has('ミリム・ナーヴァ')

console.log(rimuru) // true
console.log(milim) // false
```

自分的にはこの対象keyのデータが格納されていた場合の処理、されていなかった場合の処理と`if分岐`などの条件分岐で使用することが多いですね

# 対象keyのデータを消去したい場合(`map.delete(key)`)

これは単純にリムル・テンペストというkeyのデータを消去したければ以下の通りになります
```js
mapData.delete('リムル・テンペスト')

console.log(mapData) // Map(0) {size: 0} 
```

# 格納したmapのデータ全てを消去したい場合(`map.clear()`)
全てを消去する場合は`map.clear()`をするだけです
```js
mapData.clear()

console.log(mapData) // Map(0) {size: 0}
```

# 最後に
以上で`new Map()`の備忘録は終了です。
今回がっつり使用してみて、かなり使いやすいと感じました。
同じものでは`new Set()`というのもあるのですが、使用したい場面を見極めてそれぞれ使用できれば、選択の幅が広がると思います。

あまり記事を書くのが得意ではないので、逃げ道的に備忘録と言ってます笑
以前から大分空いてしまったのですが、時間がある時にこういった備忘録を書いていきますので、誰かの助けになれたら幸いです。

# 参考記事
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map
https://ja.javascript.info/map-set

以上
競技プログラミング用ユーザースニペット(Python)

# 初めに
先日AtCoderで茶色になったのでアウトプットとして書いてみます。
技術的なことは他の方がたくさん書いているので、使用しているユーザースニペットについて書いてみようと思います。

# スニペットとは
あらかじめ書いて登録したコードを短いキーワードで呼び出せる機能です。
詳しくは[こちらの記事](https://qiita.com/12345/items/97ba616d530b4f692c97)を参考にしてください。
[こちらのサイト](https://migi.me/vsc_snippet/)を使えば簡単にスニペット用コードが作れます。

`ファイル` -> `ユーザー設定` -> `ユーザースニペット`から編集できます。
![スクリーンショット (451).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2186646/c5d84b52-312f-6713-123a-a822e600d2df.png)

# 私が使っているスニペット
少し長いので分割しながら解説します。

まずはいわゆるテンプレです。
各種import、modなどの定数の定義など。
prefixをmainにすると他と競合するのでmaiにしてます。

```json:python.json
"main": {
    "prefix": "mai",
    "body": [
        "import sys",
        "inputSys = sys.stdin.readline",
        "# sys.setrecursionlimit(10**7)",
        "from copy import deepcopy",
        "import itertools",
        "import bisect",
        "import math",
        "from functools import lru_cache",
        "import string",
        "mod = 998244353",
        "mod2 = 1000000007",
        "inf = float(\"inf\")",
        "minf = -float(\"inf\")",
        "def YesNo(flag: bool, yes=\"Yes\", no=\"No\"): print(yes) if flag else print(no)",
        "\n\n\n"
    ]
},
```

次は入出力関連です。
`input()`の代わりに`sys.stdin.readline()`を使用しています。改行コードが残るので注意。`split()`を使うと消えます。

```json:python.json
"print": {
    "prefix": "p",
    "body": "print($0)"
},
"input": {
    "prefix": "inp",
    "body": "inputSys().rstrip()\n"
},
"intInput": {
    "prefix": "intin",
    "body": "int(inputSys())\n"
},
"s=input": {
    "prefix": "si",
    "body": "s = inputSys().rstrip()\n"
},
"n=intIn": {
    "prefix": "ni",
    "body": "n = int(inputSys())\n"
},
"hw=mapIn": {
    "prefix": "hw",
    "body": "h, w = map(int, inputSys().split())\n"
},
"mapInt": {
    "prefix": "mi",
    "body": "map(int, inputSys().split())\n"
},
"listMapInt": {
    "prefix": "lsmi",
    "body": "list(map(int, inputSys().split()))\n"
},
"listInput": {
    "prefix": "lsin",
    "body": "list(inputSys().rstrip())\n"
},
"splitInput": {
    "prefix": "splitin",
    "body": "inputSys().split()\n"
},
```

最後はstring関連です。
aからzまで手打ちしたらタイポしてWA出して以来使っています。地味に便利です。

```json:python.json
"az": {
    "prefix": "az",
    "body": "a_z = string.ascii_lowercase"
},
"AZ": {
    "prefix": "AZ",
    "body": "A_Z = string.ascii_uppercase"
},
"aZ": {
    "prefix": "aZ",
    "body": "a_Z = string.ascii_letters"
},
"0-9": {
    "prefix": "zn",
    "body": "zero_nine = string.digits"
},
```

# 終わりに
つたない記事ですが読んでいただきありがとうございました。
スニペットを使用してからコーディングがかなり快適になったので皆さんもぜひ自分好みのスニペットを作ってみてください。
AWS Control Towerとは

## 記事の背景
仕事上、Control Towerの設計・構築を担当することとなりました。
環境区分・サブシステム区別ごとにアカウントやOrganization　Uniｔ（OU）を分割する必要があり、その過程で採用が決まりました。


## Control Tower概要
エンタープライズレベルでは、複数アカウントの管理が当たり前になってきています。
アカウント横断でガバナンスを効かせる方法はOraganizationでSCPを設定する手順がありましたが、
SCPを定義してメンテして・・・といった手間がかかっていました。
Control　Towerを利用すると、

- マルチアカウントに対し適用するルールをある程度マネージドで提供してくれる
- 監査証跡を残すための仕組みを提供してくれる

といったことをやってくれます。一つづつ説明していきます。

## 適用するルールについて
「ガードレール」という仕組みが提供されます。これはControl　Tower配下のアカウントに対し共通でルールを適用してくれます。
見たほうが早いと思います。👇のような感じです。

![スクリーンショット 2022-05-21 15.03.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171131/05546f4d-7f91-8b6c-ef93-c8d3bdec4c7b.png)

このように必須・強く推奨・選択式のルールが提供されます。
必須は選択の余地なく適用され、他のルールはデフォルトでは適用されていません。
個人の考えですが、強く推奨のルールは一旦ONにしておいて、問題が発生したらOFFにするのかなと思います。

## 監査証跡の仕組みを提供してくれる
Control Towerを建てると、Cloud Trailやログ格納のS3バケットなどが自動で作られます。
また、デフォルトでガードレールによってS3のバケットポリシーを変更不可にしたりなど、監査に役に立つ仕組みも提供されます。
![スクリーンショット 2022-05-24 22.55.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171131/8ecc0ace-fd34-bd16-cda6-1d686209c1dc.png)

https://controltower.aws-management.tools/ja/automation/cfct/

## 何がメリットなのか
この仕組みですが、何がメリットなのかというと、一般的なアカウント統制ルールをマネージドで提供してくれることなのかと思います。
この仕組みをControl　Towerなしで実装すると、一つ一つのルールを手作りしたり、ログの仕組みを作り込んだりする必要があります。

まだまだわからないことも多いですが、また新しいことが判明したら記事にします。
もっともツイートされているMOBAを調べてみる

直近7日間でもっともツイートされているMOBAのゲームアプリはどれなのか調査を行いました。

調査を行ったMOBAのゲームアプリは以下の3つです。

![pokemon unite-アイキャッチ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849608/8fc0042d-7895-aee3-ed23-2fbdd789ae31.jpeg)
![wildrift-アイキャッチ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849608/9d3e1399-a662-d6ff-5eb5-9ff241e1b0fd.png)
![モバイル・レジェンドカテゴリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849608/6c6dcc7e-9e2d-8743-cca6-c747c4ba5849.png)

それぞれ、『ポケモンユナイト』『ワイルドリフト』『モバイル・レジェンド』です。
今回はこちらの3つがどのくらいツイートされているのかを調べてみたいと思います。

## 準備
準備は簡単です。
### 登録
調査にはTwitterAPIを使用します。
このTwitterAPIを使用するためには、『Developer Portal』に登録する必要があります。
詳しい登録方法はネットで検索すれば出てくると思いますので割愛させていただきます。
※2021年11月から、TwitterのデフォルトAPIはv1.1からv2に変わっています。なので、探すときはv2で探しましょう。
私としては下記がわかりやすいのかなと思います。
https://di-acc2.com/system/rpa/9688

### インストール
登録が済んだら調査に使用するPythonライブラリのtweepyをインストールしましょう。
```
pip install tweepy
```

## 実装
実装したソースがこちら。
```python
import tweepy

# API情報を記入
BEARER_TOKEN        = "BEARER TOKEN"
API_KEY             = "API キー"
API_SECRET          = "API シークレット"
ACCESS_TOKEN        = "アクセストークン"
ACCESS_TOKEN_SECRET = "アクセストークンシークレット"

client = tweepy.Client(bearer_token    = BEARER_TOKEN,
                           consumer_key    = API_KEY,
                           consumer_secret = API_SECRET,
                           access_token    = ACCESS_TOKEN,
                           access_token_secret = ACCESS_TOKEN_SECRET,
                          )

# 検索
## 実装
searchWord = "検索したいワード"  # 検索対象
tweets = client.get_recent_tweets_count(query = searchWord)
tweetCount = tweets.meta['total_tweet_count']
print(tweetCount)
```
ソースを見ていただければわかりますが、難しいことはほとんどしていません。
tweepyのClientクラスの中の、get_recent_tweets_countをパラメータを指定して動作させるだけです。
このドキュメントは下記に載せておきます。
https://docs.tweepy.org/en/stable/client.html
たったこれだけで、検索ワードの直近7日間のツイート数を調べることができます。
また、TwitterAPIには取得できるツイート数に月ごとで制限があるのですが、ツイートの総数を調べるだけなら、その制限に引っかかることもないので、気軽に気になった事柄のツイート数を調べることができます。

## 調査結果
私が運営しているMOBA研究所というサイトに結果の記事がありますので、よければ見てみてください。
[MOBA研究所の調査結果](https://shanbenzzz.com/research/moba-recnent-tweet)

# 最後に
tweepyのメソッドを使えば簡単にツイート数を調べることができました。
ただ、直近7日間のツイート数しか取得できない（Essentialでは）ので、7日分の情報を定期的に集めてもう少し長期的に調べていければいいなと思います。
kotlin filter 

# Kotlin filter
## 役割:条件に合致した値のみリストに返却
### 使い方
```kotlin:filter
A.filter{ it XXXX }
→A(List)の1つ1つに対して順番に処理を実行し、XXXXの条件に合致するもののみリストに返却する
```
#### Stringのリストの各要素に対して処理実行
```kotlin:filter
  fun filter(){
    val okashiList = listOf("cookie","chocolate","pinapple","manjuu","chuppachapps")
    println(okashiList.filter { it.contains("c") })
  }
```
```tex:result
[cookie, chocolate, chuppachapps]
```
#### Integerのリストの各要素に対して処理実行
```kotlin:count
fun main(){
    val pieList = listOf("3","1","4","1","5","9","2","6","5","3","5","8","9","7","9","3","2","3","8")
    println(pieList.filter { it.toInt() % 2 == 0 })
    println(pieList.filter { it.toInt() % 2 != 0 })
}
```
```tex:result
[4, 2, 6, 8, 2, 8]
[3, 1, 1, 5, 9, 5, 3, 5, 9, 7, 9, 3, 3]
```
RKE2で構築したk8sクラスタの更新後にコンテナが上がってこなくなった時の対処方法

## なにがあったのか
- serverおよびagentで構成されたクラスタのRKE2のバージョンを上げた
- 更新そのものは成功し、基本的なアプリケーションのPodとContainerは問題なく起動した
- PVに依存する一部のContainerだけ何故かタイムアウトで上がってこなくなってしまった
- PVのストレージにはlonghornを使用

## 更新後、クラスタの上に建てたMySQLのPodの様子がおかしくなる

https://qiita.com/YasuhiroABE/items/b12f2439834a897e017f

発生していた事象としては↑の記事とほぼ同じで、ContainerCreatingから進まなくなってしまうという事象でした。

内部のコンテナが上がってこないのでMySQLのPodは死んでいる状態になっています。

```bash
$ kubectl describe mysql8-db-0 -n database
....
Events:
  Type     Reason       Age                      From               Message
  ----     ------       ----                     ----               -------
  Warning  FailedMount  7m18s (x151 over 7h40m)  kubelet  Unable to attach or mount volumes: unmounted volumes=[data], unattached volumes=[xxxxxxxxxxxx]: timed out waiting for the condition
  Warning  FailedMount  2m47s (x51 over 7h38m)   kubelet  Unable to attach or mount volumes: unmounted volumes=[data], unattached volumes=[xxxxxxxxxxxx]: timed out waiting for the condition
```

どうやらタイムアウトしているらしい....? PVのストレージに使っているlonghornが死んでいる....?

といろいろ疑います。

しかし同じlonghornのストレージに載っているRedisは問題なく起き上がってきます。なにかがおかしいですね。

```bash
$ kubectl get pvc -A
NAMESPACE   NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
database    data-mysql8-db-0                   Bound    pvc-xxxxxxxx   8Gi        RWO            longhorn       105d
database    redis-data-redis-server-master-0   Bound    pvc-xxxxxxxx   8Gi        RWO            longhorn       105d
```

Statusも異常なし、ログを見ても異常なし... どう考えても何かがおかしい....

## 試行錯誤の末、PVを残した状態でMySQLのPodを作り直すことに

MySQLの運用に必要なデータは全て永続化ボリュームの中に格納されているので、これを削除しなければ問題なくサービスを再開出来るのでは？ということで作業を進めます。

(通常であれば、更新前やこういった破壊的な作業の前にはデータのバックアップはきちんと取った方が良いですが、今回趣味で作ってる奴だしということで横着してやりませんでした。ちゃんとバックアップは取りましょう！)

というわけで、MySQLのPodはhelmとhelmfileで管理していたのでhelmから消してあげます。

:::note warn
**必ず**SCのreclaimPolicyとPVCのpersistentVolumeReclaimPolicyがRetainになっていることを確認した上で実行してください。
(ポリシーがdeleteになっていたりrecycleになっていると、helm deleteを実行した際にPVごと消えてしまうので注意しましょう)
:::

```bash
$ helm delete mysql8-db --namespace=database
```

削除して... helmfileを管理しているレポジトリに入り、helmfileから作り直しをやります。

```bash
$ helmfile apply
```

しばらく待つとPodが上がってきます。

```bash
$ kubectl get pods -n database
NAME                    READY   STATUS    RESTARTS   AGE
mysql8-db-0             1/1     Running   0          53m
redis-server-master-0   1/1     Running   0          53m
```

生き返りましたね。

しっかり元通りになっていることを確認して一安心して今回のトラブルシューティングは終了！
韓国IT業界について

面白いからメモを取っておく
----------------------------------------------------------
韓国では有名なIT企業、五つの会社を表す表現があります。
それは네카라쿠배(ネ・カ・ラ・ク・バ）と読みます。
[原文url](https://qiita.com/Kani_Kim/items/3aa84e49590d6b27c0ae)

* NAVER(네이버・ネイバー): 韓国のYahooジャパンのようなPortalの位置
* KAKAO(카카오・カカオ): 韓国人の９９％が利用するメッセンジャー
* LINE(라인・ライン): 国民メッセンジャ
* COUPANG(쿠팡・クーパン): 韓国バージョンアマゾン
* BAEMIN(배민・배달의민족・配達の民族): UBER EATSの韓国バージョン

以上。
SOFA framework備忘録 (1) インストールと基礎編

Sofa frameworkについての日本語リファレンスがないので忘備録も兼ねて手順とか詰まったとこを記録していきます。

# Sofa frameworkってなに
ざっくりいうと有限要素法ベースの物理シミュレーションソフトウェア
臓器とかソフトロボットのシミュレーションに使えるぐらいには高精度らしい(まだそこまで使ってないからわからない)
unity向けのプラグインとかも出てるから使ってみると面白いかもね

詳しくは以下を参照
https://www.sofa-framework.org/

# インストール
Windowsで入れられるので右上のdownloadからzipを落とす
GitHubのほうもあるけどとりあえずはこっちでいいと思うよ

以上

# 起動
実行ファイルは`\SOFA_vXX.XX.XX_XX\bin\runsofa.exe`

開いてヘビが絡みついた棒が出てくればインストール完了
やったね

# 基本操作
左側の操作パネルについて
|操作|結果|
|:----:|:----:|
|Animate|シミュレーションを再生|
|Step|シミュレーションをコマ送り再生|
|Reset Scene|シミュレーションをリセット|
|Reset View|視点をリセット|
|Save View|視点を保存|
|Save ScreenShot|スクショ|


画面操作
詳細はViewerタブを参照
|操作|結果|
|:----:|:----:|
|マウス|視点操作|
|Shift+左クリック|オブジェクトを動かす|
|A|XYZ軸表示|
|B|背景色変更|
|C|視点中心に移動|
|H|操作のヘルプ|

以上
【VSCode】拡張子別で使用する言語モードの設定をする

# settings.jsonの編集

```json:setting.json
  "files.associations": {
    "*.blade.php": "blade"
  }
```

キーに適応する拡張子を、値に適応する言語モードを入力する。
上記の場合、.blade.phpの拡張子ファイルの場合は言語モードをbladeで編集する。
【Javascript】時間の取り扱い（Timestamp ⇄ Dateオブジェクト）

# Dateオブジェクト作成

まずはDateオブジェクトの作成から。

## 現在時刻で作成

```jsx
new Date();
```

## 年月日時分秒の値を渡して作成

```jsx
console.log(new Date(2015));
// Thu Jan 01 1970 09:00:02 GMT+0900

console.log(new Date(2015, 0));
// Thu Jan 01 2015 00:00:00 GMT+0900

console.log(new Date(2015, 15));
// Fri Apr 01 2016 00:00:00 GMT+0900

console.log(new Date(2015, 0, 20));
// Tue Jan 20 2015 00:00:00 GMT+0900

console.log(new Date(2015, 0, 40));
// Mon Feb 09 2015 00:00:00 GMT+0900

console.log(new Date(2015, 0, 20, 14));
// Tue Jan 20 2015 14:00:00 GMT+0900

console.log(new Date(2015, 0, 20, 25));
// Wed Jan 21 2015 01:00:00 GMT+0900

console.log(new Date(2015, 0, 20, 9, 30));
// Tue Jan 20 2015 09:30:00 GMT+0900

console.log(new Date(2015, 0, 20, 9, 75));
// Tue Jan 20 2015 10:15:00 GMT+0900

console.log(new Date(2015, 0, 20, 9, 30, 45));
// Tue Jan 20 2015 09:30:45 GMT+0900

console.log(new Date(2015, 0, 20, 9, 30, 85));
// Tue Jan 20 2015 09:31:25 GMT+0900

console.log(new Date(2015, 0, 20, 9, 30, -30));
// Tue Jan 20 2015 09:31:25 GMT+0900
```

## 文字列を渡して作成

`<input type="date">` や `<input type="time">` で選択した値を元にDateオブジェクトを作成するときに使用。

```jsx
console.log(new Date('2000-04-01T18:39:00'));
// Sat Apr 01 2000 18:39:00 GMT+0900 (日本標準時)

console.log(new Date('2000-04-01'));
// Sat Apr 01 2000 09:00:00 GMT+0900 (日本標準時)

console.log(new Date('2000-04-01 10:00'));
// Sat Apr 01 2000 10:00:00 GMT+0900 (日本標準時)

console.log(new Date('2000-04-01 05:43:21'));
// Sat Apr 01 2000 05:43:21 GMT+0900 (日本標準時)

console.log(new Date('2000/05/01 06:20:00'));
// Mon May 01 2000 06:20:00 GMT+0900 (日本標準時)

console.log(new Date('July 1, 2000 07:15:30'));
// Sat Jul 01 2000 07:15:30 GMT+0900 (日本標準時)

console.log(new Date('8 3, 1995 08:05:20'));
// Thu Aug 03 1995 08:05:20 GMT+0900 (日本標準時)

console.log(new Date('09 08, 1994 09:00:00'));
// Thu Sep 08 1994 09:00:00 GMT+0900 (日本標準時)
```

# 変換（Timestamp ⇄ Dateオブジェクト）

## Timestampとは

- 「1970年1月1日午前0時0分0秒（UTC）」からの経過秒数で表現したもの
- 「1970年1月1日午前0時0分1秒」だったら「1」のように、UTCで「1970年1月1日午前0時0分0秒」を基準にして、そこからの経過秒数で日時を表現するやり方

## UTCとは

- Coordinated Universal Time
- 日本時間から9時間引いた時間（協定世界時）
- UTCに**9時間足したのが日本時間**

## UnixTime → Dateオブジェクト

「1567566215」のような数字から、「2022/01/01」の形に変換。
UnixTimeは秒単位であり、Dateオブジェクトに変換するにはミリ秒になおす必要があるため、 `timestamp * 1000` が必要。

```jsx
//UnixTimestamp = 1648758600 で検証
let date = new Date(timestamp * 1000);

console.log(date.getFullYear());                     //2022
console.log(date.toLocaleDateString().slice(5));     //4/1
console.log(date.toLocaleTimeString().slice(0, -3)); //5:30
```

## Dateオブジェクト → UnixTime

2022/01/01のような形から、「1567566215」の形に変換。
Dateオブジェクトはミリ秒単位であり、UnixTimeに変換するには秒単位になおす必要があるため、 `timestamp / 1000` が必要。

```jsx
let date = new Date();
let timestamp = Math.floor( date.getTime() / 1000 );

console.log(timestamp); //1651585200
```

# 参考

- [指定した日時のDateインスタンスを作る](https://gray-code.com/javascript/make-a-date-instance-with-specified-time/)
- [UNIX時間との相互変換](https://so-zou.jp/web-app/tech/programming/javascript/grammar/object/date.htm#no9)
kotlin count カウント

# Kotlin count
## 役割:要素の数を数える
### 使い方
```kotlin:count
A.count()
A.count{ it XXXX }
→{}の中に条件式を記載
```
#### リストに対してカウント
```kotlin:count
  fun count(){
    val mojiList = listOf("a","b","c","a","a","e","p")
    println(mojiList.count())
    println(mojiList.count { it == "a" })
  }
```
```tex:result
7
3
```
#### 数字に対してカウント
数字にはcountは使えないので、文字列に戻してから実行する必要がある
```kotlin:count
  fun count(){
    val suuji = 3173374856338339483
    println(suuji.toString().count())
    println(suuji.toString().count{ it == '3' })
  }
```
```tex:result
19
8
```
PowerPointにPower BIを埋め込もう！🎉

# はじめに

シンプルですが、強力な機能が使えるようになっていました。

# PowerPoint のアドイン登録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/8d2b7dd8-3755-4716-4e3a-a0308ad37519.png)

# リリース日で並び替え

今だったらこれが楽です。
名前で「Microsoft Power BI」で検索してもOK🎉
Power BI Tiles という似たアドインもあるので注意。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/0bbe20ea-51a0-0997-dfb5-f85c8daf066d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/a68f646d-89ad-ed4d-e18b-1df3b47178db.png)

# あとは共有リンクを貼りつけるだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/9acdf438-fcd5-abd5-3ee9-405a3ee13706.png)

## こんな感じ

わかりにくいけど、これ、PowerPointなんです！😆
動きもスムーズでストレスなし。素晴らしい！

![2022-05-24_21-57-08.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/62e0f170-ca3e-fa23-8227-e195a7d609cd.gif)

# まとめ

明日ちょうどデモをする予定があったので、さっそく使ってみよう。

PowerPointとの連携は下記の記事も参考になります。

https://qiita.com/ishiayaya/items/77dc292a6f05e305a184
npm proxy を .npmrc に書いて楽をする

# 前提確認
社内ネットワークなどでプロキシを使用している場合に，`npm` や `git` など様々なコマンドがそのままでは利用できない．この問題を解決する手段として，コマンドにプロキシを設定するやり方がある．

今回は `npm` での設定方法について記述する．

# コマンドラインでの設定
全てのプロジェクトに設定したい場合，以下のように設定すれば基本は問題ない（はず）．

```bash
npm -g config set proxy http://<proxy_host_name>:<proxy_port>
npm -g config set https-proxy http://<proxy_host_name>:<proxy_port>
npm -g config set registry http://<proxy_host_name>:<proxy_port>
```

なお，これらの設定を解除するには，次の通り実行する．

```bash
npm -g config delete proxy
npm -g config delete https-proxy
npm -g config delete registry
```

一度設定するだけで良ければ上記でも良いが，「ネットワークによってプロキシを変更したい」「プロジェクト毎に設定を分けたい」という人もいるでしょう．（本当に？）

# `.npmrc` の書き方
そこで登場するのが `.npmrc`．
`.bashrc` などと同じように，予め設定した情報をコマンド実行時に読み込んでくれる．
`npm` プロジェクトフォルダ直下に置けば，プロジェクト毎に違う設定を適用できる．
ネットワーク毎に切り替える機能ないようだが，特定のネットワーク下でのみ適用するように工夫すれば，前述の6つのコマンドを実行するよりは簡単にプロキシの有効化／無効化を切り替えられる．

書き方は次の通り．

```bash:.npmrc
proxy=http://<proxy_host_name>:<proxy_port>
https-proxy=http://<proxy_host_name>:<proxy_port>
registry=http://<proxy_host_name>:<proxy_port>
```
SlimとSassの静的サイトジェネレーター、RTramを作ったよ

RTram（あーるとらむ）はLPなどの静的なWebページ作成で、Ruby on Railsのエンジニアに馴染み深いSlimとSassを使いやすくするためのツールです。

https://github.com/rinkei/rtram

Rubyの構文とシンプルな記法でHTMLを表現できるSlimと、CSSをメンテナンスしやすく書けるSassを使って、高速にWebページを作成することができます。インストールは次の通りです。

```
$ gem install rtram
```

RTramはSlimとSassをHTMLとCSSに変換しながらlocalhostでホスティングするサーバーを提供します。
RTramのバージョン1.0.0ではプロジェクトディレクトリを作るコマンドとサーバーを起動するコマンドだけがあります。
プロジェクトディレクトリは次のような構成です。

- `slim`: 変換の対象となる.slimファイルを置くディレクトリ
- `sass`: 変換の対象となる.scss、.sassファイルを置くディレクトリ
- `output`: Slimから変換されたHTMLが出力されるディレクトリ
- `output/css`: Sassから変換されたCSSが出力されるディレクトリ

この構成のプロジェクトディレクトリは次のコマンドで作成することができます。

```
$ rtram new PROJECT_NAME
```

サーバーを起動する時は、プロジェクトディレクトリ内、またはプロジェクトディレクトリのpathを引数に渡して次のコマンドを実行します。

```
$ rtram s [project directory's path] 
```

サーバーの起動直後に最初の変換を行い、後はファイルの保存時に変換されます。`output`ディレクトリがサーバーのドキュメントルートになっており、 http://localhost:5000 で確認することができます。
使い方の説明としては以上です。

今後の展望としてはTypeScriptの変換とかもやるかもです。
Specification of FlexRay interface, No.27, AUTOSAR R21-11(167) CP

Specification of FlexRay interface, No.27, 2021-11

https://www.autosar.org/fileadmin/standards/classic/21-11/AUTOSAR_SWS_FlexRayInterface.pdf


AUTOSAR R21-11記事一覧はこちら。

AUTOSAR 21-11, 140文書読んだ。2022年5月末に半分到達予定。

https://qiita.com/kaizen_nagoya/items/4043e8414f850ce266a4

AUTOSAR R21-11(0) 仕様ダウンロード一覧。単語帳。参考文献資料作成

https://qiita.com/kaizen_nagoya/items/9b3a1b9b8d1e8d7e288e

# 用語(terms)

|Term|Description|
|:--|:--|
|BSW |(AUTOSAR) Basic Software
|CAS| Collision Avoidance Symbol
|CC |(FlexRay) Communication Controller
|CDD |Complex Driver
|CHI |Controller Host Interface of a FlexRay CC
|COM |Communication (AUTOSAR BSW module)
|ComM |Communication Manager (AUTOSAR BSW module)
|DEM| Diagnostic Event Manager (AUTOSAR BSW module)
|DET| Default Error Tracer (AUTOSAR BSW module)
|FrIf| FlexRay Interface (AUTOSAR BSW module)
|FrNm |FlexRay Network Management (AUTOSAR BSW module)
|FrTp| FlexRay Transport Layer (AUTOSAR BSW module)
|ISR |Interrupt Service Routine
|MCG| Module Configuration Generator
|PduR |PDU Router (AUTOSAR BSW module)
|POC| Protocol Operation Control
|WUDOP| Wake-Up During Operation
|WUP |Wake-Up Pattern
|WUS |Wake-Up Symbol
|System Designer| The person responsible for the configuration of all system parameters that do not influence the executable code itself (i.e. the sequence of instructions executed during runtime), but the data used to configure which operations this executable code performs on which data and at which points in time.
|i.e.| [lat.] id est = [eng.] that is
|e.g. |[lat.] exempli gratia = [eng.] for example
|N/A |not applicable

## 英日単語帳
日本語は仮訳

T.B.D.

# 参考(reference)

[1] List of Basic Software Modules
AUTOSAR_TR_BSWModuleList.pdf
[2] Layered Software Architecture
AUTOSAR_EXP_LayeredSoftwareArchitecture.pdf
[3] General Requirements on Basic Software Modules
AUTOSAR_SRS_BSWGeneral.pdf
[4] Input for API Specification of AUTOSAR COM Stack
[5] Specification of Communication Stack Types
AUTOSAR_SWS_CommunicationStackTypes.pdf
[6] Requirements on FlexRay
AUTOSAR_SRS_FlexRay.pdf
[7] Specification of FlexRay Driver
AUTOSAR_SWS_FlexRay.pdf
[8] Specification of FlexRay State Manager
AUTOSAR_SWS_FlexRayStateManager.pdf
[9] Specification of FlexRay Transceiver Driver
AUTOSAR_SWS_FlexRayTransceiverDriver.pdf
[10] Specification of FlexRay Transport Layer
AUTOSAR_SWS_FlexRayTransportLayer.pdf
[11] Specification of FlexRay Network Management
AUTOSAR_SWS_FlexRayNetworkManagement.pdf
[12] Specification of PDU Router
AUTOSAR_SWS_PDURouter
[13] Specification of BSW Scheduler
AUTOSAR_SWS_BSW_Scheduler
[14] Specification of ECU Configuration
AUTOSAR_TPS_ECUConfiguration
[15] Specification of Memory Mapping
AUTOSAR_SWS_MemoryMapping
[16] General Specification of Basic Software Modules
AUTOSAR_SWS_BSWGeneral.pdf
[17] FlexRay Communications System Protocol Specification Version 2.1
Revision A
[18] FlexRay Communications System Electrical Physical Layer Specification
Version 2.1 Revision A
[19] FlexRay Communications System Protocol Specification Version 3.0
[20] Flexray Communications System Electrical Physical Layer Specification 3.0
Specification of Ethernet Transceiver Drive, No.431, AUTOSAR R21-11(166) CP

Specification of Ethernet Transceiver Drive, No.431, 2021-11

https://www.autosar.org/fileadmin/standards/classic/21-11/AUTOSAR_SWS_EthernetTransceiverDriver.pdf


AUTOSAR R21-11記事一覧はこちら。

AUTOSAR 21-11, 140文書読んだ。2022年5月末に半分到達予定。

https://qiita.com/kaizen_nagoya/items/4043e8414f850ce266a4

AUTOSAR R21-11(0) 仕様ダウンロード一覧。単語帳。参考文献資料作成

https://qiita.com/kaizen_nagoya/items/9b3a1b9b8d1e8d7e288e

# 用語(terms)
|Term| Description|
|:--|:--|
|EC| Ethernet controller
|ET |Ethernet transceiver
|Eth |Ethernet Controller Driver (AUTOSAR BSW module)
|EthIf| Ethernet Interface (AUTOSAR BSW module)
|EthTrcv| Ethernet Transceiver Driver (AUTOSAR BSW module)
|MCG| Module Configuration Generator
|MII |Media Independent Interface (standardized Interface provided by Ethernet controllers to access Ethernet transceivers, see IEEE 802.3 -2006)
|PLCA |Physical Layer Collision Avoidance
|P2P| Point-to-Point
|TO| Transmit Opportunity
|OA| TC10 Open Alliance TC10 (see [3])


## 英日単語帳
日本語は仮訳

T.B.D.

# 参考(reference)

[1] Specification of Ethernet Interface
AUTOSAR_SWS_EthernetInterface
[2] Glossary, AUTOSAR_TR_Glossary
https://www.autosar.org/fileadmin/standards/foundation/21-11/AUTOSAR_TR_Glossary.pdf
[3] OPEN Sleep/Wake-up Specification for Automotive Ethernet
http://www.opensig.org/Automotive-Ethernet-Specifications/
[4] General Specification of Basic Software Modules
AUTOSAR_SWS_BSWGeneral
[5] Requirements on Ethernet Support in AUTOSAR
AUTOSAR_SRS_Ethernet
[6] Specification of Default Error Tracer
AUTOSAR_SWS_DefaultErrorTracer
3.2 Related standards and norms
[7] IEC 7498-1 The Basic Model, IEC Norm, 1994
[8] IEEE 802.3-2006
[9] IEEE 802.3cg-2019