OmniAICreator/Qiita-1.07M huggingface dataset:
supabaseで簡単なTodoアプリを構築した話 - ポリシー設定

# はじめに

Baas(Backend As A Service)で何かサービスを構築してみたいと思い、
firebaseを触ってみようと思ったところ、Firebase の代替と謳われているsupabaseを発見。

こちらの方が面白そうだと感じたため、構築してみることに

# 使ったもの

* Vite + Svelte + Typescript
    * @supabase/supabase-js
    * tailwind css

* supabase
    * auth
    * db
    * realtime

# これまで

1. フロント側でsupabaseを呼び出せるところように

    https://qiita.com/doyaseizin/items/8820a095a433d09f300d

1. データ取得・操作

    https://qiita.com/doyaseizin/items/d6e0237b700448cc1826


#### tasksテーブル
|項目|型|
|----|----|
|id|uuid|
|user_id|uuid|
|content|text|
|is_done|boolean|
|created_at|date|

前回まででこのテーブルからTodoの取得や新規登録ができるようになった。

### 今回

前回まででデータの取得・操作が行えるようになったが、
このままだと自分が作ったTodo以外まで取得・操作できてしまうため、
自分が作ったものだけを操作できるようなポリシーの設定をしていく。

### 1. RLS(Row Level Security)の有効化

1. サイドメニューより、`Authentication`タブを開く
1. `Policies`を選択し、`tasks`テーブル`Enable RLS`からRLSを有効化する
1. テーブル名の隣に`RLS enabled`となっていたら有効化になっている。

### 2. Policy作成

このままだと誰も閲覧・操作できないので、
例として、`自分のTodoのみ閲覧可能`にするようなポリシーを設定してみる。

1. `New Policy`からポリシーを設定する
1. テンプレートはいろいろ用意されているが、今回は`For full customization`を選択。
1. `Policy name`には分かりやすい名前を設定。（日本語OK）
1. `Allowed operation`は`SELECT`を選択
1. `Target roles`はログイン済みのユーザーのみにしたいため、`authenticated`を選択
1. `USING expression`にはどういった条件を満たした時に、というものを記述する。
    今回の場合は、ログインしてアクセスしてきているユーザー**auth.uid()**と、
    tasksテーブルの**user_id**が一致しているという条件にしたいため、
    `auth.uid() = user_id`と記述すればOK。

これを設定ことで自分のタスクのみ閲覧することができるようになるため、
↓のようにフロント側でわざわざ条件を付ける必要がない。

```javascript
const listTodo = async () => {
  const user_id = session.user.id
  const query = supabase
    .from('tasks')
    .select()
    .match({'user_id': user_id})  // ユーザーIDで絞り込み

  const { data, error } = await query
}
```

同様にINSERT UPDATE DELETEに関してもポリシーを設定し、
自分のTodoしか閲覧・操作できないようにすることができた。

ここまででもTodoアプリとしては機能するが、共同作業などを行っているときは、
他の人が作成したTodoが即座に自分の画面に表示された方が都合がいい場合が多い。

次回はリアルタイム機能を使って、DBの操作が行われたときに、
即座に画面に反映されるようにしていく。

supabase、とってもいい感じですね
海外格安VPS ContaboがBlack Fridayをしていたので申し込んでみた

海外格安VPSのContaboがBlack Fridayをしていたので申し込んでみた。

# Black Friday
通常のセールではVPSは対象にならないようですが
今回はSetup FeeとLocation Feeが無料になるようです。

<img width="400" alt="Black Friday Deals" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/62a5997c-0640-3a4f-d489-3f50b5444ee7.png">

・Setup Feeは12か月未満の契約で加算される
・Location Feeはドイツ以外の場所を選択した際に加算される

# 料金表
一番安い＄8.49でも8GBメモリと200GB SSDと
個人の趣味でやるにはいいお手頃価格。

<img width="400" alt="priceList" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/678826c8-d2ab-8d5f-717f-9f052ff09eca.png">


# 設定

シンガポールにしたかったが半額なので、アメリカ西海岸にした。

<img width="300" alt="conf1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/55c710c5-53d8-99c5-fcf2-ce1ddfcf1db2.png">
<br>
<img width="300" alt="conf2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/c1ad9d84-1fd2-e048-abb2-21e9b1a2c97e.png">
<br>
<img width="300" alt="conf3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/4392f09a-b4a9-7f61-5614-dfa4a2aeb817.png">
<br>
<img width="300" alt="conf4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/8dbaa747-ba72-bd40-80ee-be0b814f94b9.png">

# Welcome Mail
料金の支払いが完了するとすぐにWelcome Mailがきた

<img width="300" alt="welcomeMail" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/9f1b3e0c-f9ac-15dd-c319-6daaa1fa6364.png">


# control panelにログイン

control panelにログインしてログイン情報を確認する

<img width="300" alt="controlPanel" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/2891ca4f-40a9-5f58-e073-a8355a543a81.png">

Your servicesをクリック

<img width="300" alt="yourService" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/78e34366-c258-0875-8d8c-47f1ec7547ba.png">

# サーバーにログイン

Contabo用にカスタマイズされているみたいですね。

<img width="300" alt="login" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99234/7be10d9a-4c3f-cfa5-7771-705a8dbc27a1.png">
[SQLAlchemy] 神速の爆裂理解！！！コンソールログ上のパラメータをマスキングする方法！！！

## 実装の目的
- AWSのCloudWatchなどのコンソールログ上でお客様の個人情報を開発者の目に触れるのを防ぐため
    -  SQLAlchemyではデフォルトでマスキングの設定はされていないため
## 説明しないこと
- DBへの接続方法
## DBセッティングファイルに以下の記述を追記
↓最初のログはこんな感じ
```
2022-11-02 16:37:03,292 INFO sqlalchemy.engine.Engine [generated in 0.00014s] (2151, 1, 99, '20220101', 1, 20)
INFO:sqlalchemy.engine.Engine:[generated in 0.00014s] (2151, 1, 99, '20220101', 1, 20)
2022-11-02 16:37:03,297 INFO sqlalchemy.engine.Engine INSERT INTO workplace (customer_id, company_name, kana_company_name, business_type, company_size, company_phone_number) VALUES (%s, %s, %s, %s, %s, %s)
INFO:sqlalchemy.engine.Engine:INSERT INTO workplace (customer_id, company_name, kana_company_name, business_type, company_size, company_phone_number) VALUES (%s, %s, %s, %s, %s, %s)
2022-11-02 16:37:03,297 INFO sqlalchemy.engine.Engine [generated in 0.00014s] (2151, 'ミミドン株式会社', 'ミミドンカブシキガイシャ', 30, 1, '08012345678')
INFO:sqlalchemy.engine.Engine:[generated in 0.00014s] (2151, 'ミミドン株式会社', 'ミミドンカブシキガイシャ', 30, 1, '08012345678')
2022-11-02 16:37:03,298 INFO sqlalchemy.engine.Engine COMMIT
INFO:sqlalchemy.engine.Engine:COMMIT
INFO:     127.0.0.1:55543 - "POST /application HTTP/1.1" 200 OK
```
DBとの接続設定ファイルに記載している
create_engine()の引数にhide_parameters=Trueを渡す
```db_setting.py
# DBとの接続
ENGINE = create_engine(
    connection_url,
    # 文字コードを指定
    encoding="utf8mb4",
    # 自動生成されたSQLを吐き出すようにする
    echo=True,
    # これだね↓
    hide_parameters=True,
)
```
↓するとこんな感じでDBに格納するデータをマスキングすることが可能
```
INFO:sqlalchemy.engine.Engine:[generated in 0.00028s] [SQL parameters hidden due to hide_parameters=True]
2022-11-02 16:35:56,971 INFO sqlalchemy.engine.Engine INSERT INTO workplace (customer_id, company_name, kana_company_name, business_type, company_size, company_phone_number) VALUES (%s, %s, %s, %s, %s, %s)
INFO:sqlalchemy.engine.Engine:INSERT INTO workplace (customer_id, company_name, kana_company_name, business_type, company_size, company_phone_number) VALUES (%s, %s, %s, %s, %s, %s)
2022-11-02 16:35:56,971 INFO sqlalchemy.engine.Engine [generated in 0.00015s] [SQL parameters hidden due to hide_parameters=True]
INFO:sqlalchemy.engine.Engine:[generated in 0.00015s] [SQL parameters hidden due to hide_parameters=True]
2022-11-02 16:35:56,975 INFO sqlalchemy.engine.Engine COMMIT
INFO:sqlalchemy.engine.Engine:COMMIT
INFO:     127.0.0.1:55269 - "POST /application HTTP/1.1" 200 OK
```

## 参考
[SQLAlchemy Engine Configuration](https://docs.sqlalchemy.org/en/14/core/engines.html)

### この記事が誰かの力になっていれば幸いです。
#### P.S. SQLAlchemyのドキュメント見辛すぎる・・・
Wordファイルからgrepのように抽出する

# 概要
Word(docx)ファイルから、指定の単語を含む行（パラグラフ）を抜き出して列挙します。
単にWordの機能で検索するよりは、ある単語がどういうところで使われているか、をまとめて取り出すのに便利かと思います。

cf. python wordgrep.py -f "path/filename.docx" -w "ほげほげ"
単語の指定には、正規表現が使えます。
PyInstaller で、windows 用実行ファイルを作成してあります（Windows10 検証済み）

# 仕組み
基本的な仕組みは簡単で、python-docx でWordファイルを読み込むと、1パラグラフごとに取得できるので、それを配列に入れて、その配列を正規表現でフィルタ（match）させるだけです。

# コード
## コマンドラインからの引数の設定など
```python
from docx import Document
import sys
import argparse
import os
import re

# outline --help
parser = argparse.ArgumentParser(
    description="Text extraction from Word(docx) files")

parser.add_argument(
    '-f',
    '--file',
    type=str,
    help='path\\filename.docx',
    required=True)

parser.add_argument(
    '-w',
    '--word',
    type=str,
    help='search word(Regular expression enabled)',
    required=True)

cmd_args = parser.parse_args()
file_path = cmd_args.file
```

## メインの処理
```python
def wordgrep(path, search_word):
    lis = []
    document = Document(path)
    # 1パラグラフごとに配列に入れる
    for i, p in enumerate(document.paragraphs):
        i_text = str(i) + ' : ' + p.text
        lis.append(i_text)
    # 検索条件
    pattern = ".*" + search_word + ".*"

    # Match the above pattern using list comprehension
    filtered_lis = [x for x in lis if re.fullmatch(pattern, x, re.IGNORECASE)]

    # 結果の配列の表示
    print('\n'.join(filtered_lis))
```

## コマンドライン引数を処理する
```python
if __name__ == '__main__':

    if not file_path:
        sys.exit('Arguments are too short')
    else:
        # 絶対パスへ変換
        path = os.path.abspath(file_path)
        # ファイルの存在有無
        if not os.path.isfile(path):
            sys.exit("I don't have that file.")
        # .docxを想定している場合
        if path.split(".")[-1] != "docx":
            sys.exit("That's not the right extension!!!")
        search_word = cmd_args.word
        wordgrep(path, search_word)
```

# 実行ファイル化
このままでももちろん使えますが、一応、実行ファイル化しました。

```
pyinstaller wordgrep.py --onefile
```

# 実行例
```
C:\Users\xxx>wordgrep.exe -f "C:\Users\xxx\舞姫.docx" -w ベルリン
6 : 　余は幼きころより厳《きび》しき庭の訓《おし》えを受けし甲斐《かい》に、父をば早く喪《うしな》いつれど、学問の荒《すさ》み衰うることなく、旧藩《きゅうはん》の学館にありし日も、東京に出でて予備黌《よびこう》に通いしときも、大学法学部に入《い》りし後も、太田豊太郎《おおたとよたろう》という名はいつも一級の首《はじめ》にしるされたりしに、一人子《ひとりご》の我を力になして世を渡る母の心は慰みけらし。十九の歳《とし》には学士の称を受けて、大学の立ちてよりそのころまでにまたなき名誉なりと人にも言われ、某《なにがし》省に出仕して、故郷なる母を都《みやこ》に呼び迎え、楽しき年を送ること三とせばかり、官長の覚え殊《こと》なりしかば、洋行して一課の事務を取り調べよとの命を受け、わが名を成さんも、わが家を興《おこ》さんも、今ぞとおもう心の勇み立ちて、五十を踰《こ》えし母に別るるをもさまで悲しとは思わず、はるばると家を離れてベルリンの都に来ぬ。
12 : 　官長はもと心のままに用いるべき器械をこそ作らんとしたりけめ。独立の思想をいだきて、人なみならぬ面《おも》もちした る男をいかでか喜ぶべき。危うきは余が当時の地位なりけり。されどこれのみにては、なおわが地位を覆《くつがえ》すに足らざりけんを、日ごろ伯林《ベルリン》の留学生のうちにて、ある勢力ある一群《ひとむ》れと余との間に、おもしろからぬ関係ありて、かの人々は余を猜疑《さいぎ》し、またついに余を讒誣《ざんぶ》するに至りぬ。されどこれとてもその故なくてやは。
33 : 　このとき余を助けしは今わが同
(以下省略)
```

# ヘルプ
一応ヘルプをつけました。
```
C:\Users\xxx>wordgrep.exe -h
usage: wordgrep.exe [-h] -f FILE -w WORD

Text extraction from Word(docx) files

options:
  -h, --help            show this help message and exit
  -f FILE, --file FILE  path\filename.docx
  -w WORD, --word WORD  search word(Regular expression enabled)
```

# おわりに
ソース、実行ファイルとも以下に置きました。
https://github.com/wonox/wordgrep
プライベートIPアドレスとパブリックIPアドレスについて

●プライベートIPアドレス
無償

・動的プライベートIPアドレス
動的にアドレス値が割り当てられる。既定。

・静的プライベートIPアドレス
アドレス値を決めうちできる

●プライベートIPアドレスの設定
※実行中の仮想マシンに対して、現在と異なるアドレス値を指定した場合は、設定の保存時に仮想マシンが自動的に再起動するので注意。


●パブリックIPアドレス
有償

・パブリックIPアドレスの動的割り当て
関連づけられたリソースの起動時にアドレスを割り当て、停止時にアドレス値をリリースする。


・パブリックIPアドレスの静的割り当て
一度割り当てられたパブリックIPアドレスを保持し続けられる

●パブリックIPアドレスの作成とSKU
パブリックIPあどれすのSKU(Stock Keeping Unit)にはBasicとStandardの２つがある。SKUとはコストや機能及び性能などを表す管理単位のこと。
パブリックIPアドレスの２つのSKUにも違いがあり、StandardではBasicに加えて可用性ゾーンがサポートされている。パブリックIPアドレスのSKUは、リソースの作成時に選択可能。

※パブリックIPアドレスのSKUがStandardの場合は、静的割り当てのみ使用できる

※動的割り当てが使用されている仮想マシンでは、Azureぽーたるでの仮想マシンの停止操作のタイミングで静的割り当てに変んこうできる。
【Unity】MVRPパターンを使用してHPゲージを作ってみた

# はじめに
UniRxを書くようになって、UniRxと相性の良いMVRP(Model-View-Reactive-Presenter)パターンがあるというのは耳にしていたのですが、今回初めて自分で書いてみたので記録として残しておきます。

# 環境
OS : Windows10
Unity バージョン : 2021.3.2f1

# HPゲージの作成
1. プレイヤーの頭上に追従するHPゲージを実装したかったため、プレイヤーの子にCanvasを用意します。
2. SliderをCanvasの子に作成し、Handle Slide Areaは今回使用しないため削除します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368729/b8ba68bc-a54a-0266-243f-2afae44e0b69.png)
 
# コンポーネントの作成
今回作成したコンポーネントは以下3つになります。
 - HPModel
 - HPView
 - HPPresenter
 
### HPModel
HPModelでは、ReactivePropertyを使用し、HPを公開しているのみです。

```C#:HPModel.cs
using UnityEngine;
using UniRx;

public class HPModel: MonoBehaviour
{
    /// <summary>
    /// 最大HP
    /// </summary>
    public readonly int maxHP = 100;

    /// <summary>
    /// 残っているHP
    /// </summary>
    public IReadOnlyReactiveProperty<int> HP => _hp;

    private readonly IntReactiveProperty _hp = new IntReactiveProperty();

    private void Start()
    {
        _hp.Value = maxHP;
    }
    /// <summary>
    /// ダメージを受けたときの処理
    /// </summary>
    public void GetDamage()
	{
        _hp.Value -= 10;
	}

	private void OnDestroy()
	{
        _hp.Dispose();
	}
}
```

### HPView
HPViewでは、Sliderを変化させるのみです。

```C#:HPView.cs
using UnityEngine;
using UnityEngine.UI;

public class HPView : MonoBehaviour
{
    /// <summary>
    /// HPゲージ
    /// </summary>
    private Slider _hpGuage;

    private void Start()
    {
        _hpGuage = this.GetComponent<Slider>();
    }

    /// <summary>
    /// HPゲージの設定
    /// </summary>
    /// <param name="maxHP">最大HP</param>
    /// <param name="hp">残っているHP</param>
    public void SetGuage(int maxHP, float hp)
    {
        _hpGuage.value = hp / maxHP;
    }
}
```

### HPPresenter
HPPresenterでは、HPModelとHPViewの橋渡しを行います。
```C#:HPPresenter.cs
using UnityEngine;
using UniRx;

public class HPPresenter : MonoBehaviour
{
    [SerializeField] private GameObject _player;
    private HPModel _hPModel;
    private HPView _hpView;
    private IGetHitEventProvider _getHitEventProvider;

    void Start()
    {
        _getHitEventProvider = _player.GetComponent<IGetHitEventProvider>();
        _hPModel = this.GetComponent<HPModel>();
        _hpView = this.GetComponent<HPView>();
        // 敵に当たった時の処理
        _getHitEventProvider.GetHit
            .Where(getHit => getHit == true)
            .Subscribe(_ => _hPModel.GetDamage());
        // HPModel内のHPが減ったことをViewへ知らせる
        _hPModel.HP
            .Subscribe(hp => _hpView.SetGuage(_hPModel.maxHP, hp)).AddTo(this);
    }
}
```

# 作成したコンポーネントをアタッチ
最初に作成したSliderにすべてのコンポーネントをアタッチします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368729/815cef28-c1ba-493a-e433-ee433ba6fad0.png)
実際に動かすとこのようになりました。
![ezgif-3-32c6f86455.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368729/fe93fdf1-aa22-a635-c603-c7421379d0c1.gif)


# 参考
- [【Unity】Model-View-(Reactive)Presenterパターンとは何なのか](https://qiita.com/toRisouP/items/5365936fc14c7e7eabf9)
AWSにおけるインシデント発生時のフローと概要

# はじめに
前回からの続きです。
AWSにおける、インシデント発生時のフローと概要をまとめます。

https://qiita.com/Regryp/items/0e402d18d1a8ad0d3057

# フロー
基本は以下のような基本的なフローとなります。
次節で詳細を解説します。
![スクリーンショット 2022-11-26 15.59.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584167/0c2c24f4-2a88-da70-0b33-bdc3910f298b.png)


# 各種サービスと確認タイミング
| No | フェーズ | 概要　 | 
| :---: | :---: | :--- |
| 1 | インシデント検知 | CloudWatchやEventBridgeを利用し、各種セキュリティイベントの通知を行います。メール、SNS、Slack等々確認が容易なものに送付することが望ましいです。また、インシデント管理として、SSM IncidentManagerやServiceNowとの連携もおすすめです。 このフェーズでは、アラートのレベルにより通知有無、通知先を変更することをおすすめします。緊急度の高い（例；GuardDutyのシビリティ7.0以上など）ものは優先的に対応できるような運用体制をとっておくと良いでしょう。|　
| 2 | 内容の確認 | 通知内容から、詳細を確認します。AWS上でのイベントではSecurityHubに概ね通知内容をまとめることができるので、SecurityHubで情報を集約することがおすすめです。必要に応じて各種AWSのセキュリティサービスのコンソールまたは、検知元のサービスを確認し、対応の要否を見定めます。 |
| 3 | 調査、対応 | GuardDutyなどAWS上でのイベントであれば、Detectiveを利用することがおすすめです。該当のイベントから、どの国からの攻撃か、対象のIAMユーザは誰か、どのような操作をしたのか、どのEC2からリクエストされているのかなどドリルダウンにより関連サービスを調査可能です。この時点で、必要に応じて、該当IAMユーザ、ロールの無効化や、VPCでの通信遮断、対象EC2でのダンプ取得等、被害の拡大防止、調査のための環境保全を行いましょう。 |

# まとめ
インシデント発生のフローは、比較的シンプルですが、実際に発生した場合に適切かつ迅速に対応ができるかがポイントとなります。定期的な構成の見直しや、セキュリティ診断、対応の自動化、メンバのトレーニングそしてなによりインシデント発生に備えた訓練を行いましょう。訓練により今不足していることが見えてくるはずです。
（例えばログ調査に必要なツールやノウハウなど）
Well-ArchitectedFrameworkのインシデントレスポンスを一度読むことをおすすめします。

https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/incident-response.html
PHP <input type=”date”>のバリデーションの方法

<h2>概要</h2>

会社情報を登録して、表示するメモアプリを作成していたのですが、`<input type="date">`のバリデーションがめんどくさかったので、残しておこうと思います。

<h2><input type="date">バリデーションで確認したい事 2つ</h2>

<b>1.日付が正しい形式で入力されているか？を確認する</b>

yyyy-mm-dd の形式で入力がされているかどうかを確認する。
日付以外の文章などが入力されている場合はエラーを表示するようにする。

<b>2.存在する日付かどうか？を確認する。</b>

2022年の17月65日みたいな、ありえない日付が入力されている場合はエラーを表示する。
<br>
<br>

ユーザーが入力をするフォーム
```html
<form action="index.php" method="POST">
    <div>
        <label for="date">設立日</label>
        <input type="date" id="date" name="date">
    </div>
</from>
```

<h2>使用した処理</h2>

```PHP

$dates = explode('-', $date);

    if (count($dates) !== 3) {
        $errors['date'] = '日付を正しい形式で入力してください';
    } elseif (!checkdate($dates[1], $dates[2], $dates[0])) {
        $errors['date'] = '日付を正しい日付で入力してください';
    }
```

`$date`ユーザーが入力した日付
`$dates`ユーザーが入力した値を、年、月、日にの3つに分けたもの

<h2>手順</h2>

<b>`$date`を3つに分割して、$dates変数に格納する。</b>

explode関数を使用して、日付を3つに分割する。
yyyy-mm-dd → yyyyとmmとdd

$datesに格納

```php
$date = [
	'yyyy',
	'mm',
	'dd'
]
```

<b>count関数で形式を確認する</b>

yyyy-mm-dd以外であれば、$errorsにエラーメッセージを入れる。

文章などが入っていた場合は、"-"で分割ができないためエラーになる。
※参考に関数についてのドキュメント記載

<b>checkdateでありえない日付を確認する</b>

存在しない日付であれば、$errorsにエラーメッセージを入れる。

:::note warn
<b>checkdateのパラメータは(月,日,年)の順番で入れてください。</b>
:::


<h2>おわり</h2>

ある程度のバリデーションに関しては、HTMLのfromに備わっていますが、万が一を考えての処理になります。

<h2>参考</h2>

[独学エンジニア](https://dokugaku-engineer.com/)
[StackOverflow](https://stackoverflow.com/questions/12030810/php-date-validation)
[PHP公式ドキュメント explode](https://www.php.net/manual/ja/function.explode.php)
[PHP公式ドキュメント checkdate](https://www.php.net/manual/ja/function.checkdate)
サニタイジング とは

## 勉強前イメージ

わからん！

## 調査

### サニタイジング とは

sanitizingは無害化することを意味し、webアプリケーションのセキュリティ対策で用いられる方法です。

webアプリケーションではユーザが入力した文字データを受け取り際にサニタイジングということが行われます。
どういうことかというと、 `&` や `<` などの特殊文字が入力された際にコードとして意味を持ってしまうことがあり
入力された文字から攻撃される可能性があります。
それを防ぐためにサニタイジングが行われます。

### どういう攻撃が防げるか

- XSS

クロスサイトスクリプティングと読み、webアプリケーションにある脆弱な箇所をついて悪意のあるコードを送ったりします。
それがされていますとwebサイトにアクセスしたユーザに別のサイトを表示させたり、悪意のあるスクリプトを実行したりしてしまいます。

詳細は [こちら](https://qiita.com/miyuki_samitani/items/9b8a535a50706d74b343) をごらんください

- SQLインジェクション

データベースを攻撃するもので、webサーバから想定外のSQL文を送ることで攻撃する手法になります。
データ取得されてしまえば情報漏洩にも繋がりますし、データベースそのものの削除などされてしまう可能性もあります。

## 勉強後イメージ

文字列をそのまま持ってこないってことね。

## 参考

- [サニタイズとは何か？クロスサイトスクリプティングを防ぐ方法](https://ssaits.jp/promapedia/technology/sanitize.html)
- [サニタイジング【sanitizing】](https://e-words.jp/w/%E3%82%B5%E3%83%8B%E3%82%BF%E3%82%A4%E3%82%B8%E3%83%B3%E3%82%B0.html)
Docker composeでAPI,MySQLサーバーを立てる

# はじめに
Docker composeを用いて、GoAPIコンテナ、mysqlコンテナを立ち上げたときに調べたことをまとめます。

# Docker composeとは
> Docker Composeとは
Docker Composeは、複数のコンテナで構成されるアプリケーションについて、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールです。
[Docker入門（第六回）〜Docker Compose〜](https://knowledge.sakura.ad.jp/16862/)


``` 
version: '3'
services:
  db:
    image: mysql-db
    container_name: mysql-db
    build: 
        context: .
        dockerfile: ./dockerfile/mysql
    volumes:
      - ./mysql/db:/docker-entrypoint-initdb.d  #初期データ
    environment:
      MYSQL_ROOT_PASSWORD: cafe-password
      TZ: "UTC"
    ports:
      - "127.0.0.1:3307:3306"
  api-server:
    image: go-api-server
    container_name: go-api-server
    build:
      context: .
      dockerfile: ./dockerfile/goapi
    ports:
      - "127.0.0.1:8080:8080"
    depends_on:
      - db     
  app:
    build:
      context: .
      dockerfile: ./dockerfile/app
    ports:
      - "127.0.0.1:3000:3000"
    tty: true
    volumes:
      - ./src:/app #ホスト:コンテナ
    environment:
     - WATCHPACK_POLLING=true
    #command: sh -c "npm run dev"


```

## 各項目の解説
* image
 ｢docker-compose build｣を実行したときのimage名を設定
* container_name
｢ docker-compose up -d｣したときのコンテナ名
* build
  context…｢docker build｣ コマンドを実行したときのカレントディレクトリを設定。ビルドコンテキスト
　dockerfile…ビルドコンテキストからのdockerfileの位置を指定
[docker-compose.ymlのbuild設定はとりあえずcontextもdockerfileも埋めとけって話](https://qiita.com/sam8helloworld/items/e7fffa9afc82aea68a7a)
* ports
 公開するポート番号を設定。(ホスト:コンテナ)
*  depends_on
コンテナの依存関係を設定する。
*  command
[docker-composeで指定するcommandはDockerfileよりも優先される](https://qiita.com/ganyariya/items/3594ec682a3ccf917477)

## Linuxのコマンド
* sh
 シェルを起動する。-cはオプションで単一コマンドのためにシェルを呼び出すプログラム (例えば、エディター) のときに使用する。


## 参考
[Docker Compose - docker-compose.yml リファレンス](https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa)
LeetCode 問題番号8

### 8. String to Integer (atoi)
https://leetcode.com/problems/string-to-integer-atoi/

これめちゃくちゃ難しいというか場合分けが多すぎて辛かった。
多分もっとキレイなやり方あるんだと思います。
やり方としては順番に読み込んでいって
文字が来た場合はそこで終了するが
まだ数字が来てない状態でのスペースはスキップして正負記号は正負の判定に使う。
数字が出た場合はメモ用の文字列の最後に追加。

また場合分けとしては
まだ0以外の数字が出てきていない時に出てきた0はスキップする。
最終的に数字だけのstring型の文字列になった場合に
2**31-1より大きいまたは-2**31より小さい場合にはそれぞれint型に収まる範囲にする。
今回は文字のサイズで判定したこれは一応通ったけど2**31とかピンポイントな数字はアウトなはず(LeetCodeのテストケースが悪いかも？)
一応通ったコードになります。

```C++
long long mycast(string s)
{
    long long num = 0;
    long long ten = 1;
    for (int i = s.size() - 1; i >= 0; --i)
    {
        num += ten * (s[i] - 48);
        ten *= 10;
    }
    return num;
}
int myAtoi(string s)
{
    string t;
    bool check = false;
    bool check1 = false;
    bool positive = true;
    bool notzero = false;
    long long minimam = -1, max = 1;
    for (int i = 0; i < 31; ++i)
    {
        minimam *= 2;
        max *= 2;
    }
    max -= 1;
    if (s == "")
    {
        return 0;
    }
    std::regex re{R"(\d+)"};
    for (auto i : s)
    {
        bool isnum = false;
        string str = ""s + i;
        if (std::regex_match(str, re))
        {
            isnum = true;
            check = true;
            if(i != '0')
            {
                notzero = true;
            }
            if(notzero)
            {
                t += i;
            }
        }
        if (!isnum)
        {
            if (check)
            {
                break;
            }
            else
            {
                if (check1)
                    break;
                if (i == '-')
                {
                    positive = false;
                    check1 = true;
                }
                else if (i == '+')
                {
                    check1 = true;
                }
                else if (i != ' ')
                {
                    break;
                }
            }
        }
    }
    if (t == "")
    {
        return 0;
    }
    if (t.length() > to_string(max).length() || t.length() > to_string(minimam).length())
    {
        if (positive)
        {
            return max;
        }
        else
        {
            return minimam;
        }
    }
    long long ans = mycast(t);
    if (!positive)
    {
        ans -= ans * 2;
    }
    ans = ans < minimam ? minimam : ans;
    ans = ans > max ? max : ans;
    return ans;
}
```
以外と知られてない Emacs Lisp のコメント自動インデント

## 問題点

```elisp
(progn
  ; this is comment
  (setq a 123 b "abc xyz")
  ; this is comment 2
  (xprint a b)
  (xdump a b)
  )
```

上のコードを M-x indent-sexp したり、コメント(セミコロンのある)行でタブを入力すると以下のようになります。

```elisp
(progn
                                        ; this is comment
  (setq a 123 b "abc xyz")
                                        ; this is comment 2
  (xprint a b)
  (xdump a b)
  )
```

最初のコメントは (setq ...) に合わせたいし、次のコメントは (xprint ...) に合わせたいので心外です。
やり方がわからないので、こんなもんかとあきらめていました。

----

## 解法を発見！

> [実践Common Lisp](http://www.amazon.co.jp/exec/obidos/ASIN/4274067211/)
> 作者: Peter Seibel,佐野匡俊,水丸淳,園城雅之,金子祐介
> 出版社/メーカー: オーム社
> 発売日: 2008/07/26
> メディア: 単行本（ソフトカバー）

↑ をたまたま読んでいたら p.50 に以下のような説明が書かれていました：

```cl
;;;; セミコロン 4 つはファイルヘッダのコメントに使う

;;; セミコロン 3 つのコメントは、後に続く大きな
;;; コードセクションに対する段落コメントになる

(defun foo (x)
  (dotimes (i x)
    ;; セミコロン 2 つは以降のコードに対する
    ;; コメントであることを示す。以降に続く
    ;; コードと同じインデントにする
    (some-function-call)
    (another i)             ; この行だけに対するコメント
    (and-another)           ; これも、この行だけに対するもの
    (baz)))
```

そこで、最初のコードを書き換えました(セミコロンを 2 つにしました)。わざとインデントをずらしてます：

```elisp
(progn
     ;; this is comment
  (setq a 123 b "abc xyz")
     ;; this is comment 2
  (xprint a b)
  (xdump a b)
  )
```

上のコードを M-x indent-sexp またはタブキーで再インデントすると期待通りに以下のようになりました：

```elisp
(progn
  ;; this is comment
  (setq a 123 b "abc xyz")
  ;; this is comment 2
  (xprint a b)
  (xdump a b)
  )
```

## 教訓

4つ、3つ、2つ、1つのセミコロンを使い分けましょう！
Unable to load contents of file list: ‘/Target Support Files/Pods-XXXX/Pods-XXXX-frameworks-Debug-input-files.xcfilelist’　の対応

Stub環境を構築しようとして出たエラー内容

```
Unable to load contents of file list: ‘/Target Support Files/Pods-XXXX/Pods-XXXX-frameworks-Debug-input-files.xcfilelist’
```

pod update すると解決した
ディレクトリリスティング とは

## 勉強前イメージ

ディレクトリを見るやつ？

## 調査

### ディレクトリリスティング とは

webサーバにおいて本来見えないはずのディレクトリ配下のファイルの一覧を表示させる攻撃方法です。
ディレクトリを指定したアクセスがあるとそのディレクトリに含まれるファイルやディレクトリの一覧が見えてしまいます。

例えば、以下のようなディレクトリ構成のwebサーバがあったとします。

```
[root@localhost html]# tree
.
├── index.html
└── test_dir
    ├── a.html
    ├── b.html
    └── c.html
```

`http://[IPアドレス]/test_dir/` を指定してwebページでアクセスを行うと以下のようにディレクトリの中のファイルが見えてしまいます。
これを悪用して隠しファイルや情報を読み取られてしまう可能性があります。
また、 [ディレクトリトラバーサル](https://qiita.com/miyuki_samitani/items/30468a42eaf1570041df) になってしまうこともあります。

![1Index of _test_dir — Mozilla Firefox 2022-11-26 14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/da257f2c-a4f4-86f0-97cd-68426373b8b3.png)


このディレクトリ内ののファイルを表示する機能はwebサーバの機能で `/` で終わるURLを指定すると表示されます。
apacheだとDirectoryIndexで設定されています。
DirectoryIndexは以下の機能があります。

- indexのファイルがあればそれを表示
- indexのファイルがなければ一覧を表示

### 見えないようにするには？

`/etc/httpd/httpd.conf` にある `Indexes` を削除することで見えなくすることは可能です。

```
....
    Options Indexes FollowSymLinks
    Options FollowSymLinks
....
```

```
service httpd restart
```

設定後は以下のように見えなくなりました。

![2403 Forbidden — Mozilla Firefox 2022-11-26 14.53.0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/84c7e604-faf1-d553-4fc3-b9203756fe16.png)

## 勉強後イメージ

確かにファイル見えちゃうと攻撃できたりしちゃうよね....

## 参考

- [ディレクトリリスティング【directory listing】](https://e-words.jp/w/%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%83%AA%E3%82%B9%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0.html)
- [ディレクトリリスティングを無効にしよう。ApacheWEBサーバー脆弱性](https://lpeg.info/security/directory_listing.html)
Create a sharing rule for the Project object

+ [Create a sharing rule for the Project object. cant have the priority onto field](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000LHJ1n)

フィールドを優先することはできません

[Salesforce Trailhead 開発者初級 > データセキュリティ > 共有ルールの定義(7) 課題やりかた](https://qiita.com/yongjugithub/items/78b387aca5dc8ad629be)

これが正確にできてなかったようですね。

Priorityのカスタムオブジェクトを課題の要件を確認しながら、以下のように作成する。記入したら、右下NEXT.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d3ad96bf-036c-bf2c-0368-3cb90946efef.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0931e680-78f6-2c62-c3d9-f9616d88ad75.png)

# 優先度カスタム ピックリスト(Priority custom picklist)がオプションとして見つかりません

+ [Can't find the Priority custom picklist as an option when doing the Data Security challenge](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KduN6)


:::note
私自身、「プロジェクト オブジェクトの共有ルールを作成する」チャレンジを完了しているときにこの問題に遭遇しました。各ステップで行ったことを戻って確認した後、プロジェクト オブジェクトの「優先度」フィールドを作成するときに、データ型として「選択リスト」ではなく「選択リスト (複数選択)」を誤って選択したことに気付きました。優先度選択リストのデータ型を「選択リスト」に変更し、共有ルールの作成に戻ると、共有ルールの条件を設定するときにドロップダウン オプションに「優先度」が表示されるようになりました。

I encountered this problem myself when completing the 'Create a sharing rule for the Project object' challenge. After going back and checking what I had done for each step, I realised that when creating the 'Priority' field for the Project object I accidentally selected 'Picklist (multi-select)' for the data type, instead of 'Picklist'. I changed the data type for the Priority picklist to 'Picklist', went back to creating the sharing rule, and 'Priority' was then showing in the dropdown options when setting the criteria for the sharing rule.

https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Jgwgj
:::
民生機器と産業機器

# 問題１
### 工場の機器メンテナンス業務においてIoTを活用した場合の基本要素とデバイス・サービスの例を整理した。基本要素に該当するものはどれか？

#### IoTとは？
```Internet of Things```の略。
パソコンやスマートフォンだけでなく、```さまざまな物（機器）にインターネット接続の機能を持たせ```、機器同士で情報をやり取りしたり、```データの収集・分析```などを行う仕組みをのこと。これにより、システムを使った高度な判断や自動制御を実現できる。身近なところでは```家電製品やカーナビ、センサを使ったホームセキュリティ```などがある。

# 問題２
### HEMSの説明はどれか？
#### HEMSとは？
Home Energy Management System: ヘムス
電気やガスのメータ、太陽光発電装置、家電製品などを家庭内ネットワークに繋ぎ、HEMSコントローラに接続することで制御し、```エネルギー使用量を可視化して節約```に結びつけたり、```快適な生活環境を作る```ためのシステム。日本政府は、```エネルギー消費量の削減と温暖化防止```を目的として、全家庭にHEMSを設置することを目指している。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
KoyebでNode-REDを動かしてみた

# はじめに

無料で使えるNode-RED実行環境をいろいろ探しています。

https://qiita.com/kitazaki/items/970a10cbd1059c89aca5

新たにKoyebというサービスを見つけ、Node-REDを動かしてみました。

https://www.koyeb.com/

# 無料枠(Hobbyプラン)の仕様

|サービス|無料プラン|CPU|メモリ|Disk|時間|非アクティブまでの時間|その他|
|---|---|---|---|---|---|---|---|
|Koyeb|Hobby|1vCPU|512MB|5GB|5$|不明|1個のMICRO(1vCPU,512MB,5GB)、または、2個のNANO(1vCPU,256MB,2.4GB)|

# 手順

## 1.アカウントを作成

アカウントを作成してログインするとダッシュボード画面が表示されます。

![koyeb_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/67f4cd8a-d83f-c720-3901-3f4968f8c9b9.jpeg)

![koyeb_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/fd1d00d7-16ea-df26-5c06-aeaf83ea5411.jpeg)

## 2.アプリケーションのデプロイ

「Deploy an existing project」項目の「Deploy」ボタンを押します。

![koyeb_2_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/832e0eb7-8498-aad4-bd7f-4be789bca0df.jpeg)

「1.Select deployment method」で「GitHub」を選択します。

![koyeb_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/b1a66929-8815-a010-5bad-0e033df8d62e.jpeg)

「2.Import project」で自分の「Github repository」または「Public GitHub repository」を選択します。

![koyeb_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/7d617948-21af-ae42-19cf-6afa582871f0.jpeg)

今回は以下のレポジトリを使用します。

https://github.com/kitazaki/node-red-test-02

![koyeb_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1bd1d256-c25a-d11e-8a87-742aca54b515.jpeg)

「3.Configure service and deploy」で以下を選択します。

- 「Regions」→「FRA」しか選択できません
- 「Instance」→「Micro」(1vCPU,512MB,5GB)、または、「Nano」(1vCPU,256MB,2.4GB)を選択できます

![koyeb_6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/3452e58d-aa22-03e3-d18e-c95d124139ac.jpeg)

次に「Advanced」を選択します。

- 「Environment variables」→ Name「PORT」のValueを「8000」→「1880」へ変更します
- 「Exposing your service」→ Portを「8000」→「1880」へ変更します
- 「App name」→ 好きな名前(URL)を入力します

![koyeb_7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/3f05b4c8-8f51-af1a-64c2-d281be55ec8e.jpeg)

最後に「Deploy」ボタンを押してしばらく待ちます。
「Service」タブの「Build logs」でビルドの進捗状況を確認できます。

![koyeb_9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/16eea040-117e-70f2-2660-6387637cd9ce.jpeg)

![koyeb_8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/456e7fd4-14a7-0291-8bab-3821a5452740.jpeg)

「Runtime Logs」タブでNode-REDの起動ログ、動作状況を確認できます。

![koyeb_10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/21163585-2262-ad8d-cb72-4cb496b0bc65.jpeg)

# 動作確認

正常にビルド、Node-REDの起動が完了すると、「Overview」タブで動作状況を確認できます。
「Status」が「Healthy」と表示されていれば正常です。

![koyeb_11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/0bb45216-6d98-1acc-a3a5-132dc5a5c06c.jpeg)

URLへアクセスしてNode-REDが動作していることを確認します。

![koyeb_12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f4affed6-b540-adec-48a4-23136258c530.jpeg)
PowerShellのprompt関数について

`Oh-My-Posh`でいい感じにプロンプトをカスタマイズした環境で気になることはありませんが。
`Windows Server`上などのカスタマイズされていない`PowerShell`のプロンプトでは、下記画像の用にデフォルト表示として`PS カレントディレクトリ>` と表示されており、長いパス等を表示した際に見づらいと感じる事があるかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/b3dd2e52-ab2a-86d0-165c-00a95d871303.png)

上記画像くらいのパス長だったらいいのですが、パス名が長くて見づらいときなどは。
下記のコマンドを実行するとプロンプトの表記を書き換え、パスを表示しないようにできます。

```powershell
function prompt{}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/6730c476-d0fc-08b0-6505-0b3d911b5e9c.png)

実行すると上記画像のようにプロンプトにパス表示がなくなります。
なおプロセス中で実行した事設定は一時的な物となり、再起動すると元に戻ります。

これは組み込み関数であるprompt関数を編集した結果となりますが、本記事ではこのprompt関数についてみていきます。

## ドキュメント

[プロンプトについて](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_prompts?view=powershell-7.3)

## prompt関数って？

[プロンプトについて](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_prompts?view=powershell-7.3)

ドキュメントに記載がある通り、プロンプト表示をカスタマイズするための関数になります。

何もカスタマイズしていないデフォルトの状態では下記のように設定されています。

```PowerShell
# Get-CommandコマンドレットでPrompt関数を取得して、ScriptBlockを表示
(Get-Command Prompt).ScriptBlock
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/7fd3cba4-cfd3-2c8b-4a48-b24f72377ff9.png)

`"PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1))"`のように定義されており。

分解してみると下記の要素が表示されている事がわかります。

- PS
- $executionContext.SessionState.Path.CurrentLocation
- $('>' * ($nestedPromptLevel + 1)) 

PSはPSという文字列を表示

$executionContext.SessionState.Path.CurrentLocation は現在のカレントディレクトリを表示

$('>' * ($nestedPromptLevel + 1)) は自動変数$nestedPromptLevel + 1 の数だけ>を表示

となっています。
冒頭でパス表示等を無効化したのは、この設定をブランクで上書して表示を無効化しています。

## 総評

ワンタイムでちょっとした作業をする際に、`PowerShell`のプロンプトが見づらいと言った際に、さっと利用して表記を変更できると便利かと思います。

なおWindows専用の`Windows Powershell`とクロスプラットフォーム対応の`PowerShell 7`ともに同様となります。
Discord.jsで短縮URLを作りたい

# Discord.jsで短縮URLを作りたい
突然ですがDiscordでURLを短縮したい！って思ったことはありませんか？
っていうことで今回はDiscord.jsを使ったURL短縮プログラムを紹介します
***
## 必要なもの
* Node.js 16.x　
* discord.js ^13.12.0　
* My bot　（持ってなきゃ作れない）

## 作り方

ではまずnpmを入れていきます
isgdをいれます
```json:package.json
{
  ...
  "engines": {
    "node": "16.x"
  },
  "dependencies": {
    "discord.js": "^13.12.0",
    "isgd": "^1.1.3",
  }
}
```

そしてこのようなやつを書きます

```java:index.js
const { ... } = require("discord.js");
const client = new Client({
  intents: [...],
});

var isgd = require("isgd");

client.on("messageCreate", (message) => {
   if (message.content.startsWith("!url")) { //もし!urlが送られたら
    const aarsd = message.content.split(" ").slice(1).join(" ");
    if (!aarsd)
      return message.channel.send("空白がないまたは入力されていません。"); //もしurlが未記入だったら
    isgd.shorten(aarsd, function (res) {
      message.delete();
      message.channel.send("短縮成功！\n> " + res);
    });
});

client.login(DISCORD_BOT_TOKEN); //BOTにログイン
```

試しに!url ここにURL を送ってみましょう

このように前にあったメッセージは消され
URL短縮されたメッセージが送られてきました。![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986727/a8f52454-f31b-d1e3-69df-d881f8cb1ec3.png)

## おわりに
はじめて記事を投稿しました。
壊滅的な国語力のなさですが許してください（〒▽〒）
Lambdaのメモリサイズの設定値について考える

## 概要

 - Lambdaでのパラメータ値であるメモリサイズについての選択についての記事です
 - Lambdaをあまり使ったことのない人、チュートリアルで使ったことのある人向けに記事です

## tl;dr

 - Lambdaは実行時間課金なのでメモリサイズを大きくする=ランニングコストが高くなるわけではない
 - コスパの良いメモリサイズを選択するために、「AWS Lambda Power Tuning」で測定してみましょう
 - 並列処理(CPU依存)をしている場合にはメモリサイズとコア数の関係を意識してメモリサイズを選択しましょう

## Lambdaの課金体系

Lambdaの利用料金は、「リクエスト数」×「実行時間」によって決まります。
ここでいう実行時間は、「何MBのメモリサイズで何秒実行されたか」というような計算で決まります。
つまり、EC2などのサービスとは異なり、リソースサイズが大きいほど利用料金が高くなるというわけではありません。

例: メモリサイズを2倍にすることで実行時間が1/2になる場合は、利用料金としては変わらなくなります(変わらないということはレイテンシーが低い分メリットの方が大きいという捉え方もできます)

参考: https://aws.amazon.com/jp/lambda/pricing/


## AWS Lambda Power Tuningでの最適なメモリサイズの選択

### 実行準備

こちらのページを開くと、aws-lambda-power-tuningのデプロイページに飛ぶことができ、`デプロイ`ボタンを押すだけでデプロイができます。
https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:451282441545:applications~aws-lambda-power-tuning

### 実行

ツールの実体はStepFunctionsなので、StepFunctionsのコンソールを開き、powerTuningStateMachine-XXXのステートマシンを開きます。

ステートマシンの実行時に、

```
{
    "lambdaARN": "your-lambda-function-arn",
    "powerValues": [128, 256, 512, 1024, 2048, 3008],
    "num": 10,
    "payload": "{}",
    "parallelInvocation": true,
    "strategy": "cost"
}
```

をインプットします。
※ strategyには、"cost" or "speed" or "balanced" の3つがあるそうです。

### 実行結果

Analyzerのステートの出力に、visualization用のURLがあるのでそちらを開きます。

![Screenshot 2022-11-26 12.49.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385190/3e492b1a-566c-82e6-8852-365410899985.png)

このような可視化されたデータが得られ、今回だと256MBのコストを選ぶと最もコスト的に優れているという結果が得られました。
メモリの間隔やプロット数(実行数)などはパラメータで調整可能です。

## 並列処理を実装していて、コア数によって性能が変わる場合

プログラム内で並列処理を実装している場合、ライブラリや実装方法にも依りますが並列数の上限値がコア数に依存するケースがあります。その場合、少しメモリサイズをアップさせることでコア数が上がるのであればメモリサイズをアップさせた方が良い場合もあるかと思います。

メモリサイズとコア数については公表はしていないようですが、下の記事等で検証している実例があったりするので、ある程度参考になりそうです。先ほどのLambda Power Tuningでざっくりとメモリサイズを選んだ上で更に細かくコア数が変わる前後のメモリサイズでレイテンシーなどを比べてみるのも選択肢の1つとしては持っておいても良いかと思います。

https://qiita.com/komikoni/items/101ccd3cb98fdc4f4389

## まとめ

Lambdaを利用する際に、実行時間上限値やメモリサイズなど色々な設定値がありますが、今回は、メモリサイズについての考え方、選び方について触れさせていただきました。
APIGateway+LambdaでAPIを構築する際などは、リソースごとにLambdaを分けるか1つのLambdaで全てのリソースを実装するか等の構成に悩むこともありますが、このような観点を持っておくと、1つだけメモリサイズを極端に大きくしたい場合にはLambdaを分けるといったような構成にするという選択肢を検討する材料になるかと思います。とはいえ、Lambdaを分けるとCloudWatchLogsのロググループが分かれたりとメリット・デメリットあるかと思いますので、あくまでも構成を考える上での1つの材料になれば幸いです。

LambdaはAPIであったり、バッチ処理、Webhookなど利用シーンも多岐に渡るので、ユースケースに合わせて最適な使い方ができると良いなと改めて考えるきっかけとなりました。
【PowerShell】自作関数を作る

# はじめに

これまでにPowerShellを使って以下のような小さなプログラムを幾つか作ってきましたが、もう少し大きなプログラムを作るには自作関数を作れると便利です。
そこでPowerShellで自作関数を作る方法を記事としてまとめてみました。

* [tnsnames.oraを探すスクリプト](https://qiita.com/nkojima/items/02970521224f982389a2)
* [ノートPCのバッテリーの劣化度合いを調べるスクリプト](https://qiita.com/nkojima/items/0bd18549668ee2d3024f)
* [簡易ポートスキャナを作ってみた](https://qiita.com/nkojima/items/852a2d5a3d8fddf548d5)
* [未割り当てのドライブレターを探す方法](https://qiita.com/nkojima/items/3053cb206d4e6d96ba8b)

# 関数の命名規則

* Microsoftの公式リファレンスを見ると、「動詞と単数形の名詞を含むパスカルケース名を使用すること」とされています。
  * パスカルケースはアッパーキャメルケースと同じ意味だそうです。

```text:関数名の一例
CheckISOHash     // ISOファイルのHash値をチェックする
ConvertToSVG     // SVGファイルに変換する
ReadUserConf     // ユーザーの設定ファイルを読み込む
SendSlack        // Slackにメッセージを送信する
WriteDebugLog    // デバッグ用のログを書き込む
```

# 関数の構文

## 基本的な関数

* 基本的な関数の構文は以下のようになっており、他の言語とほとんど変わらない印象です。

```powershell:基本的な関数の例
function SayHello {
    Write-Host "Hello"
}
```

```powershell:実行結果
> SayHello
Hello
```

## パラメーター付きの関数

* パラメーター付きの関数の場合、以下のように定義するそうです。
  * C#などと比べて、ちょっと変わった書き方に感じますね...

```powershell:パラメーター付きの関数の例
function PrintMessage {
    param($message)
    Write-Host $message
}
```

```powershell:実行結果
> PrintMessage "Hello,world!"
Hello,world!
```

```powershell:実行結果（パラメーター名を指定する場合）
> PrintMessage -message "Hello,world!"
Hello,world!
```

* 上記の`PrintMessage`関数のパラメーターでデータ型を指定する場合、以下のようになります。

```powershell:パラメーター付きの関数（＋データ型の指定）の例
function PrintMessage {
    param([string]$message)
    Write-Host $message
}
```

## 戻り値のある関数

* 戻り値は他の言語と同様に`return`を使いますが...

```powershell:戻り値のある関数の例
function AddNumber {
    param([int]$a, [int]$b)
    return $a + $b
}
```

```powershell:実行結果
$result = AddNumber 2 3
Write-Host $result
```

* 以下のような書き方でも、上記と同様に`$a + $bの結果`を返してくれるそうです。
  * returnなしのパターンは、ちょっとRubyっぽさを感じますね。

```powershell:戻り値のある関数の例（returnなし）
function AddNumber {
    param([int]$a, [int]$b)
    $a + $b
}
```

```powershell:戻り値のある関数の例（returnだけの場合）
function AddNumber {
    param([int]$a, [int]$b)
    $a + $b
    return
}
```


# 参考URL

* [第9章 - 関数 (PowerShell 5.1)](https://learn.microsoft.com/ja-jp/powershell/scripting/learn/ps101/09-functions?view=powershell-5.1)
* [about_Return (PowerShell 5.1)]()
プログラミングは覚えるでなく使えるようにしよう

前プログラミングの質問に答えた時にボクが感じたことについて。

質問してきた人の様子を見ていると、がんばってプログラミングの仕方を「覚えよう」としていた。
ボクの意見だが、「覚える」よりむしろ「使える」ようにすることが大事だと思う。
「使える」といっても、あまりイメージできないかもしれない。
そこでここでは、実際の現場を例に出しながらどうやって「使える」力を身に着けるか、説明していこうと思う。

#### <font color=blue>１．「覚える」でなく、「調べる」力を身につける。</font>
あくまでボクの感覚だが、実際に現場でプログラミングする時は勉強している言語とは全く別の言語で頼まれる、ということがよくある。
そんなときに例えば、自分が覚えた言語で画像を表示できたり、数字の計算ができたりしても別の言語なので太刀打ちできない。。という状況になってしまう。
なので、プログラミングする方法より、「画像を表示」する方法/計算する方法を調べる力がむしろ大事なのだ。

#### <font color=blue>２. 「覚える」でなく、わからない時に人に質問できる力をつけよう</font>
実際の現場では、ひとつの開発現場に自分以外にメンバーがいる。
この状況でプログラミングの方法がわからないときに自分で調べるより、別のメンバーの人に聞く方が早いケースがよくある。
こういった場合に、自分がプログラミングで何をしたいのか、どこで行き詰っているのか説明する必要がある。
そういったときに「覚える」ことよりも人に聞く力が重要になってくる。

#### <font color=blue>３．「覚える」でなく、忘れたときに思い出せる仕組みをつくろう</font>
いくつかの言語をつかってプログラミングしていると、どうやってプログラミングしているかよく忘れる。
なので、「覚える」というより見てすぐ「思い出せる」仕組みをつくっておこう。
例えば、自分のローカルにいままでつくったプログラムを所定の場所に置いて、特定のワードで検索すると、すぐどうやってプログラミングしていたかを思い出せるようにする等。


参考になれば。
[golang] GormでDISTINCTを使う

# はじめに
GormでMySQLを操作していたところ、DISTINCTを使いたくなった。
[GORMのサイト](https://gorm.io/ja_JP/docs/query.html)をみてやってみたけど上手くいかなかったので、
色々自分で試す。上手くいく方法が見つかったので、そのメモ。

# 結論
Select()の取得対象指定の際に、頭に"DISTINCT "を付与する

# ソースコード
確認時のソースコード

``` go
package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

const (
    TBL_TEST string = "Test"
)

// 元のテーブル
type Test struct {
    Id		uint32  `gorm:"column:ID" json:ID`
    Name	string	`gorm:"column:name" json:name`
    Age	    uint32	`gorm:"column:age" json:age`
}

// 取り出したい対象
type result struct {
    Age	    uint32	`gorm:"column:age" json:age`
}

func main() {
	var rslt []result = []result{}
    var dbCnct *gorm.DB

    // DBへの接続処理（省略）
  
    err := dbCnct.Debug().Table(TBL_TEST).Select("DISTINCT " + TBL_TEST + ".age").Scan(&rslt).Error
    fmt.Println(rslt)
}
```
（備忘録）Raspberry Pi の Serial （シリアル番号）を確認する方法

# 1. コマンド

```shell:コマンドライン

// Raspberry Pi シリアル番号
$ grep Serial /proc/cpuinfo | awk '{print $3}'

// イーサネット MACアドレス
$ ifconfig eth0 | grep ether | awk '{print $2}'

```

# 2. 余談
Raspberry Pi シリアル番号を用いることで、端末固有の設定反映や挙動をさせることに使えるかもです
GitHub DesktopでUnityをバージョン管理する方法

# 初めに
GitHub DesktopとUnityを紐付けようとした時にうまくできなくて時間がかなり掛かってしまったのでまとめておきます。

# 操作手順

__GitHub Desktopの設定__

１、
![スクリーンショット 2022-11-25 13.02.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/2ce270c2-e71d-7736-7e87-e5ac71d83379.png)
①作成済みリポジトリにアクセス
②新規リポジトリ作成
今回は２の新規作成から行う。


２、
![スクリーンショット 2022-11-25 13.48.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/2e30fb0d-999d-e4ac-ecf8-741cc4906b44.png)
①作成したいリポジトリ名
②リポジトリの説明（空白可）
③pc上のパス（Unity側と同じ場所にする必要あり）
④必ずUnityにすること
⑤デフォルトのまま
⑥設定したらCreate repositoryを選択

３、
![スクリーンショット 2022-11-25 13.40.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/b5f59e33-7d37-fc80-248e-02571f601a09.png)
①Publish repository を選択

４、
![スクリーンショット 2022-11-25 13.49.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/84b5c863-d5b7-a0d1-c039-6172966c448c.png)
②Keep this code private にチェックあり→非公開　/ なし→公開
①Publish repository を選択することでGitHubへ反映される


__Unityの設定__
５、
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323935383137302f61633435643265302d316636352d623234662d646665392d3865333135366435666638342e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/106ff6f6-f28d-bd24-0608-c797255a0581.png)
①作成したいUnityの名前
②２の③で作成した中パスの中へ入れる（重要）
③Publish repositoryを押してプロジェクト作成

__不要なファイルを除外__
６、
![スクリーンショット 2022-11-26 13.09.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/992e79a4-2a01-5878-f178-e85c7969e53d.png)
![スクリーンショット 2022-11-26 13.13.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/895c36e3-9319-6ccc-588f-958e12738578.png)
![スクリーンショット 2022-11-26 13.13.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/f736d291-8270-7314-62cb-6a22b102efe8.png)



①ターミナルを開き、Unityプロジェクトの中(Assetsと同じ位置)まで移動する。
 コマンド→ cd ~/
②空のファイル作成（名前は必ず.gitignore）
　　コマンド→ touch .gitignore
③.gitignoreファイルが出来ているか確認する。「.」は隠しファイルの為通常は隠れている。
確認ショートキー→ 「⌘ + shift + .（ドット）」
　画像３枚目のように「.」ファイルが表示される

７、

https://github.com/github/gitignore/blob/main/Unity.gitignore

①Rawクリックして全文コピー
②.gitignoreファイルにペースト保存
（上記URLからでも、自分の作成したGitHubの.gitignoreからのコピーでも可能です）




８、６７の手順をやらないと不要なファイルが全て反映されてしまいトラブルの元になります

９、![スクリーンショット 2022-11-26 13.49.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/c277dc71-066f-5665-80b0-c169d046ed18.png)
６７の手順をすることで必要なファイルだけ反映させることが出来る(チェックがついているのが反映される)

![スクリーンショット 2022-11-26 14.00.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/f436f820-486a-5267-45ff-8920eae278d1.png)
①詳細、題目を記載（必ず）
② ①の内容を詳しく記載(空白可)
③上記を記載したら押す

__GitHubに反映させる__
９、
![スクリーンショット 2022-11-26 14.03.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/9688d20d-8eaa-a3d3-88ad-9c96d11faac9.png)
①押すとGitHubに反映される


# 終わりに

この流れでバージョン管理の初期設定は完了です！
中々しっくりくる記事が見つからず探りながら行った為、もっと手軽に出来るやり方があるかもしれないです。
調べてまた追記していきます。
BCCWJの短単位TSVデータとUniDic基本10属性+語種の対応

対応確認しようとしてよく忘れるのでメモ。

参考（短単位TSVデータのフィールド）
https://clrd.ninjal.ac.jp/bccwj/tsv.html

上記サイトに記載の短単位TSVフィールドに対応するUniDicのフィールド名を併記したのがこちら。
UniDicのフィールド名はこのページを参照。
https://clrd.ninjal.ac.jp/unidic/faq.html

||BCCWJ TSV|UniDic||
|:-|:-|:-|:-|
|0| サブコーパス名|||
|1|サンプルID|||
|2|文字開始位置|||
|3|文字終了位置|||
|4|連番|||
|5|出現形開始位置|||
|6|出現形終了位置|||
|7|固定長フラグ|||
|8|可変長フラグ|||
|9|文頭ラベル|||
|10|語彙表ID|||
|11|語彙素ID|||
|12|語彙素|lemma||
|13|語彙素読み|lForm||
|14|語彙素細分類|mean|ここが空でない場合、lemma-mean がlemma|
|15|語種|goshu||
|16|品詞|pos1(-pos2(-pos3(-pos4)))||
|17|活用型|cType||
|18|活用形|cForm||
|19|語形|||
|20|用法|||
|21|書字形|||
|22|書字形出現形|orth, orthToken||
|23|原文文字列|||
|24|発音形出現形|pron, pronToken||
slack あれこれ

slackの応用器が、使っているOSが対象外になり使えなくなった。　
基本で使っている閲覧器も対象外になった。　

たまたま、Chromeは最近導入したもので接続できた。　

久しぶりに接続したら、discordに移行していた。　

たまたま、あるLTがdiscordで参加したことがあり、なんとか接続できた。

# 対象ソフトウェア　

macOS 10.15 まもなく買い換えようと思い、10.13を利用。ハードウェアがそれ以上対応していない。

# 移行先　

discord一箇所。

他のSlack班はまだ確認していない。

順次調べていく所存。　

基本はgithubを根城にしたい。コードがかけていない。コンパイル統合環境が作れていない。
【1分】レンタルサーバーにNode.js, Expressを導入してAPIサーバーを構築する。(CoreServerへ、node環境を構築。)

Coreserver V2 に、Node.js (express)　を導入しよう。

そう思ったものの、レンタルサーバーにExpress サーバーを立てることは容易ではなく、一日詰まってしまいました。

ですが、以下の方法により瞬殺でExpress環境を整えることができたので共有します。

https://kaedeee.com/coreserver-node-express-cgi/

# 詰まっていた理由
* VPSでないレンタルサーバーの場合、CGI スクリプトから各言語を動かすことになるが、js は対応していないっぽかった。
* 調べても、Flask サーバーを立てるHow to しか載っていない。


# これだけ！解決法
npm にて、cgi-express をインストールすることで、解決

https://www.npmjs.com/package/cgi-express?activeTab=versions
```
npm i cgi-express
```

# もっと！解決法
以下、詳しく説明します。

## nvm 経由で安定版 node をインストール
以下のページが参考になりました。

https://best-lifeup.net/conohawing-cgi/

## node のシンボリックリンクを作成
nvm 経由でインストールしたnode は、隠しファイル内に存在するため、このままではcgiでは読み込めません。そこで、シンボリックリンクを作成して、見えるパスからアクセスできるようにします。
これまた、以下のページが参考になりました。

https://best-lifeup.net/conohawing-cgi/

## express, cgi-express をインストール

```
npm i express
```
👇あまり認知されてない？っぽい神パッケージ。自己責任でオナシャス！

https://www.npmjs.com/package/cgi-express?activeTab=versions
```
npm i cgi-express
```

## index.cgi, .htaccess を作成
cgi スクリプトのpermission は、755 で。


``` index.cgi
#! /home/（ユーザー名）/.local/bin/node/v18.12.1/bin/node

const express = require('express')
const cgiExpress = require('cgi-express');

const app = express();

app.get('/', (req, res) => res.send('Hello World!'));

cgiExpress.execute(app);
```

.htaccess スクリプトのパーミッションは644

``` .htaccess （常時SSL化, 強制https化）
SetEnvIf Request_URI "." Ngx_Cache_NoCacheMode=off SetEnvIf Request_URI "." Ngx_Cache_StaticMode

RewriteEngine On

RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.cgi/$1 [QSA,L]
```

``` .htaccess （常時SSL化ではない）
SetEnvIf Request_URI "." Ngx_Cache_NoCacheMode=off SetEnvIf Request_URI "." Ngx_Cache_StaticMode

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.cgi/$1 [QSA,L]
```

# 終わり
おしまい！閉廷！
npm 神パッケージ制作ニキ、ありがと🍆

https://kaedeee.com/coreserver-node-express-cgi/
データローダのバッチ運用

いつもはBulk APIをCURLコマンドで実行しているので簡単にバッチ化できますが、Dataloderのバッチの参考資料をまとめておきます。

+ [Windows コマンドラインインターフェースでのバッチファイルの実行](https://help.salesforce.com/s/articleView?id=sf.using_the_command_line_interface.htm&type=5)
+ [バッチモードでの実行](https://help.salesforce.com/s/articleView?id=sf.loader_batchmode.htm&type=5)
+ [ステップ 5: データをインポートする](https://help.salesforce.com/s/articleView?id=sf.command_line_import_data.htm&type=5)


# Error : dataloader.exception.OAuthBrowserLoginRunnerException: Connect to login.Salesforce.com:443

+ [データローダ バッチ自動化「Connection timed out: connect」エラー](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000LHYxPSAX)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ba7afbbf-4920-7a65-66ce-83656aff2691.png)

# 運用管理の考察

+ [Salesforceのバッチ処理の管理](https://qiita.com/Keiji_otsubo/items/21f1d3771437bccaa81a)


# データローダ用暗号化パスワード

+ [データローダ用暗号化パスワードを生成ができない](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmX9dSAE)


パスワードは、process-conf.xml ファイルに追加する前に暗号化しておく必要があるため、このプロセスでは、鍵の作成が最初のステップとなります。

https://developer.salesforce.com/docs/atlas.ja-jp.dataLoader.meta/dataLoader/command_line_create_encryption_key.htm