OmniAICreator/Qiita-1.07M huggingface dataset:
【Django】バリデーションエラーのテンプレートへの表示パターン

## サンプルモデル

例えばこんなモデルがあったとする。

```python:models.py
class Urls(models.Model):
    instagram = models.URLField(verbose_name='instagram', blank=True, null=True)
```

## バリデーション

forms.pyで`clean_FIELDNAM`を使いバリデーションする。

```python:forms.py

class UrlForm(forms.ModelForm):
    class Meta:
        model  = Urls
        fields = ('instagram',)

    def clean_instagram(self, *args, **kwargs):
        if self.is_valid():
            insta_url = self.cleaned_data['instagram']
            # 空ならそのまま返す
            if insta_url == None:
                return insta_url
            # インスタのURLと異なればエラー
            elif not "https://www.instagram.com/" in str(insta_url):
                raise forms.ValidationError('「https://www.instagram.com/」で始まる必要があります。')
            # 正常の場合
            return insta_url
```

そもそも`URLField`ではなく、`CharField`でinstagramの`id`を設定するようにすれば良いが、それは置いておく笑

## テンプレートに表示

### その1

`form.errors`には全てのエラーを含むことができます。

```html:html
{{ form.errors }}
    ↓
<ul class="errorlist">
    <li> instagram
        <ul class="errorlist">
            <li>「https://www.instagram.com/」で始まる必要があります。</li>
        </ul>
    </li>
</ul>
```
とても扱いづらそうなので却下！

### その2

次はフィールド名を入れてみます。

```html:html
{{ form.instagram.errors }}
    ↓
<ul class="errorlist">
    <li>「https://www.instagram.com/」で始まる必要があります。</li>
</ul>
```

このパターンは、`input`タグの近くに使えそうです。

### その3

`input`タグとは別の場所に表示したい場合は、全てのエラーを出力したいので`form.errors`を使う必要があります。

for文で処理してみます。

```html:html
{% for error in form.errors %}
    {{ error }}
{% endfor %}
    ↓
instagram
```
表示したいのはそっちじゃない(´・ω・｀)

### その4

エラーの文字列を表示したいので`items`を使う。

```html:html
{{ form.errors.items }}
    ↓
dict_items([
    ('url4', ['「https://www.instagram.com/」で始まる必要があります。'])
])

{% for key, errors in form.errors.items %}
    {% for error in errors %}
        {{ error }}
    {% endfor %}
{% endfor %}
    ↓
「https://www.instagram.com/」で始まる必要があります。
```
多分この方法が正解？

フィールド名を使いたい場合は`{{ key }}`を入れてあげると良いです。

`errors`はfor文で回すと、`<li>`ではなく文字列で返ってくるので、使い分けると良い。


ちなみに、`form.errors`の中には、同メソッド内で出力する`forms.ValidationError`の数しかエラーが入っていないっぽいので、一つしか定義していなければ複数出力されることはないと思います。

`clean_FIELDNAME`は定義された順に実行され、一つずつ処理されるので、他のフィールドのエラーを同時に出力することも無いっぽい。

https://docs.djangoproject.com/en/4.1/ref/forms/validation/#form-and-field-validation

## まとめ

`input`タグの近くでエラー表示させたい場合

```html:html
<!-- リストで返す -->
{{ form.instagram.errors }}

<!-- 文字列で返す -->
{% for error in form.instagram.errors %}
    {{ error }}
{% endfor %}
```

`input`タグとは別の場所で、全てのエラーに対応したい場合。

```html:html
{% for key, errors in form.errors.items %}
    {% for error in errors %}
        {{ error }}
    {% endfor %}
{% endfor %}
```

間違いがあったら教えて下さい(´・ω・｀)
Google Apps Script でスプレッドシートにカスタムメニューを追加する話

## はじめに

Google Apps Script（GAS）のトリガーを使って、スプレッドシートにカスタムメニューを追加することができます。

> Apps Script リファレンス

[onOpen(e)](https://developers.google.com/apps-script/guides/triggers#onopene)

## トリガーを使用

GAS のトリガー `onOpen(e)` はユーザーが Google ドキュメント、スプレッドシート、スライド、フォームのファイルを開いたときに自動的に実行されます。
この関数を使用して独自のメニューを追加します。

```
function onRefresh() {
  // do something
}

/* ファイルを開いたときのイベントハンドラ */
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  var menu = ui.createMenu("ワークフロー");
  menu.addItem("データを更新", "onRefresh");
  menu.addToUi();
}
```
譜面からDance Dance Revolutionの難易度を推し量るモデルをDNNで作った

# Dance Dance Revolutionについて
運動したほうがいいと周囲に言われたため, Dance Dance Revolution(以下DDR)に取り組んでいる.
DDRというのはリズムゲームの一種で, ディスプレイ上の矢印に併せて筐体のパネルを踏むゲームである.
DDRにはstepmaniaというエミュレーターがあり, このstepmaniaの譜面データから, 適切な難易度を類推するモデルを畳み込みニューラルネットワークで作成した.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/94b1c0a7-f606-8a27-ce9e-050978fc9d4e.png)


# 学習データについて

stepmaniaの譜面を公開しているサイトから, テキトーに｢.sm｣をダウンロードし学習データとした.
今回は, 約5000譜面を学習データとし, 加えて左右の上下の入れ替えることでデータの水増しを行った(左右や上下を入れ替えても難易度がそこまで変わらないと仮定).

譜面を(時間)×(状態)の二次元配列に変換し, それをモデルの特徴量とした.
目的変数は,その譜面の難易度(19段階)である.

## 時間軸について
一部譜面には12分や32分などの矢印があるものの, 多く(85%ぐらい)の譜面は4分8分16分のみで構成されている.
そのため, 1小節を16等分する形で, 時間軸を表現した.
12分や32分などの特殊な矢印は, それと位置が近い16分の箇所に書き換えを行った.

## 状態軸(矢印の種類/BPM)について

DDRの矢印を(上下左右)×(矢印の種類:計4種)の計16通りに分類した.
* 普通の矢印
* フリーズアロー(長押し)の開始地点
* フリーズアロー(長押し)の終了地点
* ショックアロー(踏まない)

この16次元は, 該当する矢印があれば1なければ0のベクトルである.

<img src="https://p.eagate.573.jp/game/ddr/ddra3/p/images/howto/how_freeze.jpg" alt="FA" width="300px">
<img src="https://p.eagate.573.jp/game/ddr/ddra3/p/images/howto/how_shock.jpg" alt="SA" width="300px">

加えてDDRではなぜかBPMが変化する曲が多い.
そのため, BPMの状態も入れ込む必要がある.
よって, 状態16種類+BPM一種類の計17次元のベクトルを入力データとした.


## 学習データのまとめ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/290b75fb-c4ab-e6ed-c54b-778248bbc3ab.png)
上記の二次元配列を最終的な特徴量とした.

# 学習モデルについて

今回は時系列解析等で使われる, 一次元の畳み込みニューラルネットで難易度類推器を作成した.
通常のそれとは違い, GlobalMaxPoolingとGlobalAveragePoolingを並列して行っている.
これは, ｢最大の難所｣と｢全体の平均難度｣の２つを抽出することを目的としており, 実際に精度が向上した.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/a56f33ea-8a14-8adc-d467-d3ffe9caf11d.png)

コードの概要は以下になる.
```python
input_x = keras.layers.Input(shape=(2704,17),name='in_X')
input_l = keras.layers.Input(shape=(1,),name='in_l')

u1= keras.layers.Conv1D(128,32, activation='relu')(input_x)
u1 = keras.layers.MaxPooling1D(5)(u1)

u_gmp = keras.layers.Conv1D(128,16, activation='relu')(u1)
u_gmp = keras.layers.GlobalMaxPooling1D()(u_gmp)
u_gap = keras.layers.Conv1D(128,16, activation='relu')(u1)
u_gap = keras.layers.GlobalAveragePooling1D()(u_gap)
u_gap = keras.layers.Multiply()([u_gap,input_l])

u2 = keras.layers.Concatenate()([u_gmp,u_gap])
u2 = keras.layers.Dense(64, activation='relu')(u2)
u2 = keras.layers.Dense(16, activation='relu')(u2)

out = keras.layers.Dense(1, activation='sigmoid')(u2)
model = keras.Model(inputs=[input_x,input_l], outputs=out)
```
入力データは可変長配列のため0埋めしてサイズを揃えている.
よって, そのままだと適切に平均が計算できない.
input_lはその補正項である.
$$input_l=\frac{最大の譜面の長さ}{その譜面の長さ}$$

# 結果

validationのRMSEが0.6程度となった.
そのため, 適切な難易度の目安になること程度なら期待できる


![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950973/1c289349-ac5a-1f6e-164e-0ab38e68182c.png)
【Flutter × Firebase】FlutterFire CLI インストール時の$flutterfire configureで発生したエラー解決方法

# エラー内容

FlutterでFirebaseを利用するための設定で遭遇したエラー。
Flutter プロジェクト ディレクトリから次のコマンドを実行して、アプリ構成ワークフロー作成する際に発生した。

https://firebase.google.com/docs/flutter/setup?platform=ios

## 実行コマンド

```shell
$ flutterfire configure
```

## エラー文

```shell
Unhandled exception:
Exception: /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- xcodeproj (LoadError)
        from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from -e:1:in `<main>'
```

# 解決
エラーの通り`xcodeproj`がない。
なのでインストールする。

```shell
$ gem install xcodeproj --user-install
```

## 参考

`xcodeproj`はXcodeプロジェクトの依存関係を管理するCocoaPodsで利用されていて、
RubyスクリプトからXcodeプロジェクトを作成および変更ができるライブラリ。

https://github.com/CocoaPods/CocoaPods

https://github.com/CocoaPods/Xcodeproj
DatabricksにおけるApache Spark

[Apache Spark on Databricks \| Databricks on AWS](https://docs.databricks.com/spark/index.html) [2022/10/25時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

本書では、Apache SparkとDatabricks、Databricksレイクハウスプラットフォームがどのような関係にあるのかを説明します。

Apache Sparkは、Databricksレイクハウスプラットフォームの心臓であり、プラットフォームの計算クラスターとSQLウェアハウスを強化するテクノロジーです。DatabricksはApache Sparkに最適化されたプラットフォームであり、Apache Sparkのワークロードを実行するための効率的かつシンプルなプラットフォームを提供します。

# Apache SparkとDatabricksはどのような関係ですか？

Databricksという会社はApache Sparkのオリジナルクリエイターによって創業されました。Apache SparkはオープンソースソフトウェアプロジェクトとしてDatabricksを含む[数多くのトップカンパニーからのコミッター](https://spark.apache.org/committers.html)を有しています。

Databricksでは、Apache Sparkの開発と機能のリリースを継続しています。Databricksランタイムには、更なる最適化とApache Sparkをベースとした専用の機能や、C++で再構築された最適化バージョンのApache Sparkである[Photon](https://docs.databricks.com/runtime/photon.html)を含む拡張版Apache Sparkが含まれています。

# Apache SparkはDatabricks上でどのように動作するのですか？

Databricks上でコンピュートクラスターやSQLウェアハウスをデプロイする際には常に、仮想マシンにApache Sparkが設定されデプロイされます。Databricksによって管理されているので、SparkコンテキストやSparkセッションの設定や初期化を機にする必要はありません。

# Apache Sparkを使うことなしにDatabricksを使うことはできますか？

Databricksでは数多くのワークロードをサポートしており、Databricksランタイム内には多数のオープンソースライブラリが含まれています。Databrikcs SQLは内部ではApache Sparkを使用していますが、エンドユーザーはデータベースオブジェクトにクエリーするために標準的なSQL構文を使用します。

Databricks機械学習ランタイムはMLのワークロードに最適化されており、多くのデータサイエンティストがDatabricksで作業する際に、TensorFlow やSciKit Learnのような主要なオープンソースライブラリを使用しています。Databricksによってデプロイ、管理されている計算リソースに対して任意のワークロードをスケジュールするために[ワークフロー](https://qiita.com/taka_yayoi/items/f91b6ff0a2c7f892f401)を活用することができます。

# なぜDatabricksではApache Sparkを使っているのですか？

Databricksレイクハウスプラットフォームは、皆さまのビジネスをスケールさせるエンタープライズソリューションを開発、デプロイするためのセキュアかつコラボレーティブな環境を提供します。Databricksの従業員の多くは、Apache Sparkについて最も知識を持っているメンテナーであり、世界中のユーザーでもあります。我々はユーザーの皆様がApache Sparkが稼働する最速の環境を利用できる様に、継続的に新たな最適化を開発し、リリースし続けています。


### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
LPC812MAXと温度,S-5851Aで液晶温度計 (Mbed)(AQM0802A)



x mbed2リビジョン144
x リビジョンの変更ができる人むけ

x センサーはS-5851A。

目的
AQM0802Aで遊ぶ
適当にあつたI2C温度センサーを使用


![o_cop199.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5a2c9738-cbd3-7f62-162c-5e174bbdb076.jpeg)




I2C_LCD_5851_812_1


```c++



#include "mbed.h"

//5851
#define ADDR        (0x90) //  address
#define ADDR_LCD    (0x7C) //  address

//       SDA    SCL
I2C i2c(A4, A5); //812

//10の割り算 0から1028までは、正しい。主に0から999
#define DIV10(n) ((n*205)>>11)

char    tempval;        //温度
char    data_read[6];   //i2cバッファー

//液晶初期化配列
char INIT_com[]= {0x0,0x38,
                  0x0,0x39,
                  0x0,0x4,
                  0x0,0x14,
                  0x0,0x70,
                  0x0,0x56,
                  0x0,0x6C,
                  0x0,0x38,
                  0x0,0xC,
                  0x0,0x1,
                  0x40,0x41
                 };

//液晶のクリア
char INIT_cls[]= {0x0,0x1};

//メイン関数
int main()
{

    //液晶の初期化
    for(int ii=0; ii<11; ii++) {
        i2c.write(ADDR_LCD, &INIT_com[ii*2], 2);
        wait_ms(2);
    }//for

    //無限ループ
    while (1) {

        //液晶のクリア
        i2c.write(ADDR_LCD,INIT_cls,2);
        wait_ms(2);

        //初期化
        //set address 0
        i2c.write(ADDR, "\000", 1); //addres 0

        //温度の読み込み
        // Read temperature register
        i2c.read(ADDR, &tempval,1);

        //tempval = 21; //debug

        //液晶に出力
        // Display result
        data_read[3] = 0;
        data_read[2] = '0' + tempval - ( DIV10(tempval) * 10 ); //1の桁
        data_read[1] = '0' + DIV10(tempval);                    //10の桁
        data_read[0] = '@';
        i2c.write(ADDR_LCD, data_read,3);

        //1秒待つ
        wait_ms(1000);

    }//while

}//main





```
LINE社が作ったフォントを紹介

今週、Line社からフォントが公開されたようです。
ざっと特徴をご紹介。


###### 公式＆サンプル

以下の公式からどうぞ（丸投げ）

https://seed.line.me/index_jp.html

ざっと閲覧した限り、なかなか良さげな、ポップだけどフォーマルな雰囲気も持ったシンプルな丸ゴシック体（プロポーショナルフォントのみ）ですね。
英字がおそらく印刷媒体系（？）で、見分けづらい文字があったりコーディングには向きませんが、丸ゴシック系が好きな人には閲覧用フォントにおすすめです。


##### ダウンロード

右の「うにょっ」とした「○」の中に「↓」のマーク（ダウンロードマーク）から「LINE Seed JP ↓」をクリックでDL。
なお、言語は4種類から選べます。

***

で、以降はWindowsから見るとちょっと面食らうツッコミポイント含め各フォルダ解説です。


##### 「__MACOSX」

Mac OS XフォルダはMacでzip圧縮した時に付与されるもので、Mac以外の環境だと見えます。見えた人は捨てましょう。


##### 「.DS_Store」

各フォルダに入っているのもMacによるもので、見えた人は捨てましょう。


##### ライセンス

公式の最下部「LINE Seed LICENSE ↑」から飛べるライセンスページにはかなり緩く適当にかかれていますが、DLしたものの中に入っている「OFL.txt」によると、「SIL OPEN FONT LICENSE Version 1.1」のようです。
大きく違わないけど、公式サイトにもちゃんと表記しようよLineさん・・・


##### 用途フォルダ

「App」よくわからないけどアプリ用？
「Desktop」よくわからないけど一般用？ これだけデジタル署名されているようです。
「Web」拡張子 eot, woff, woff2 版
普通に閲覧するにはDesktopで良さそう。


##### フォントの種類フォルダ

「App」「Desktop」には、PCで使えるフォントが入っています。
それぞれ「OTF」「TTF」フォルダがあります。
OTF: OpenType Font、TTF: TrueType Font
OTFは、DTPとか文字組みする人向け。
TTFは、対応しているソフトが多い。
というわけで、普通に閲覧する分には、TTFで良さそうです。

OTFとTTFの違いは、以下あたりが詳しいようです。
https://fontnavi.jp/zakkuri/202-truetype_opentype.aspx


##### フォントの太さ（ウェイト）

ファイル名末尾が・・・
Bd: Bold 太字
Eb: ExtraBold 超太字
Rg: レギュラー 標準
Th: Thin 細字
というわけで、普通に閲覧するにはRgで良さそうです。


##### まとめ

Windowsで使うには・・・
ダウンロードしてきて展開。
Desktop → TTF → LINESeedJP_TTF_Rg.ttf
を右クリックしてインストール。

「LINE Seed JP_TTF」をそれぞれのソフトに選んで設定するか、手打ち指定すればOKです（なんか表記が変則的・・・）。

Chromeなら「設定」→「デザイン」→「フォントをカスタマイズ」から「標準 フォント」「Sans Serif フォント」に指定すると良いでしょう。

（自分でフォント名を確認したい方は、Win10,11なら、フォント管理画面に行くと分かります。「使用可能なフォント」の検索窓に「LINE」って打つといいでしょう。）
２年後にエンジニアになるために

# 憧れから合格まで
3〜４年前、 **退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング** *(https://www.amazon.co.jp/dp/487311778X)* を読んだことをきっかけにプログラミングを用いて現職の業務の効率化を行ってきました。それを続けるうちに次第にエンジニアに憧れるようになり、今年ついに中途採用に応募し、合格までいただきました（１週間以内に内定をいただく予定）。

# 現職への未練
合格をいただいた企業は本当に**本当に**魅力的な条件でしたが、現職で引き止められたこと、自分にも少し未練を感じることから、現職の１つの区切りがつく見込みの２年後までは現職で働くことを決めました。苦渋の決断です。本当に正しい決断だったのか・・・。

# ２年後にエンジニアになるための計画
### ポートフォリオの作成
今年エンジニアへの転職活動をしてみて感じたことは、当たり前ですがどの企業も経験値を重要視しているということです。未経験ではあるとはいえプログラミングを用いて**どんなものを作ったことがあるか**, **それを作っている間にどこで苦労したか**を必ず聞かれます。そこで２年後のために以下のことは実践していこうと思います。
- [x] Qiitaへの投稿
- [ ] Gitを用いてコードの公開
### 需要のある技術の把握
エンジニア転職サイトを見ていると、**必須要件**, **歓迎要件**の提示を見ることができます。やる気や姿勢のような捉えようのないものもありますが、**プログラミング言語**はもちろん、**フレームワーク**や**開発手法**などを見ることができ、現在エンジニアの業界ではどんな技術に需要があるか複数企業見ればある程度把握できます。転職をする年だけ転職サイトに登録するのではなく、継続的にサイトを訪れ、業界の動向の把握はしておいた方が良いだろうと感じました。
- [ ] エンジニア転職サイトには継続的に登録しておく


### 資格の取得
とはいえ「こんな技術を身につけました」と履歴書に書くことができても**未経験**という３文字がそれ以上に大きな足枷になります(経験年数１年以上ですら応募不可能は辛いですよね)。
しかし、どんなに勉強していても**実務経験**がなければ独りよがりではないかと思われるのも仕方ないと私も思います。そこで**資格の取得**をしておくことで多少なりとも企業に安心してもらおうと思います。ちなみに今気になっているのは**aws**です。

- [ ] 需要のある技術の資格を取得

### paiza.jp *(https://paiza.jp/)* のランクを上げる
そもそも合格をいただいた企業に応募したきっかけが paiza.jp *(https://paiza.jp/)* でスカウトをいただいたことでした。paizaにある**スキルチェック**をするだけで、企業の方から声がかかるようになるのでとてもおすすめです。

ランクが上がると、その分**スカウト**や「**気になる**」がたくさんもらえるようになります。私が今回希望し、合格をいただいた企業からスカウトをいただいたのが今のAランクを取った頃でした。

私の場合だけなので確かではありませんが、**取得ランクの１つ下を提示している企業**からスカウトが来るようになる気がします。また１つ下のランクであれば**経験年数が足りなくても**「気になる」はもらえるようなのでチャンスはあるのかもしれません。

Sランクは私にとって別格に難しく、２回ほど挑戦した上で勉強し直そうと一旦諦めているところです。でも２年もあればいけるよね・・？
- [ ] Sランクを取得

## まとめ
上記の 
- [ ] Qiitaへの投稿

にチェックをつけるためだけの今回の投稿でしたが、三日坊主にならないよう、**小さな投稿**を続けていきたいと思います。

今回いただいたチャンスに乗っておけば良かった・・・とは**絶対に**思うはずですが、せめてこの２年、現職もプログラミングも頑張って良かったと思える２年にしたいです。

２年後こそリモートだったりフレックスで働きながら楽しくコードを書く日々を送れるますように！
Vim Shift-Enterのmap

一般人には意味不明なタイトルですが

vim におけるキーマッピング

```vim
:map <S-ENTER> xxxx
```
なり
```vim
:map <C-CR> xxxx
```
が動けば気持ちいいかなと

まだ実装されていない、、と
EnterはCtrl-mで実装されているので`CTRL`や`SHIFT`の同時押しを処理するのは難しそう？と

https://stackoverflow.com/questions/16359878/how-to-map-shift-enter

https://groups.google.com/g/vim_dev/c/Ym6D-kWIsyo?pli=1
SQL Error 文字列データまたはバイナリ データが切り捨てられます

データベースへのインサートにて

「文字列データまたはバイナリ データが切り捨てられます。」

というエラーがログが表示

## 原因
データベースに対し、設定カラムのサイズよりも大きいサイズの値を登録しようとすると発生するエラー

- 入力フォームからの登録において、正しくバリデーションができていないことが原因
- データベースのデータ定義をもとに入力値に対するガードが十分でない

```
e.g.
データ型 nVarchar(20)に、定義した値を超えた文字列を入れる
```

##  解消方法
カラムのサイズと値を確認して、どちらかを修正
特に全角と半角のバイト数に注意して、データ定義とバリデーションの設定をする必要がある
[脳死したい人向け]Nuxt3をDockerでサクッと環境構築、解説してみた

# 自己紹介

初めまして。私は都内でwebエンジニアをしています。

今の会社にインターンとして経て、入社しました。

業務では、Nuxtjs, Golang, Kubernetesを用いて日々苦戦している若輩者です。

今回初めてQiitaに投稿をさせて頂くことになりました。

様々なご意見いただけると励みになりますので、よろしくお願い致します。

## 背景

社内でVue2系のサービスを展開していることが多いものの、Vue2のサポートが来年で終わるとのことなので

Vue3系にリプレイスする話が耳にすることが多くなったので、先駆けて勉強した次第です。

## 前提

Dockerについて軽く知っているが書き方がよくわからない方や、取り敢えずDockerでNuxt3で環境構築をしたい方を想定しております。

## 開発環境

MacBook Pro (16-inch, 2019)

MacOS Monterey

node v18.9.0

```
hogehoge@ nuxt-app % tree
.
├── Dockerfile
├── README.md
├── app.vue
├── docker-compose.yaml
├── nuxt.config.ts
├── package.json
└── tsconfig.json
```

## 環境構築

### ローカル編
まず、[公式](https://v3.nuxtjs.org/getting-started/installation)の手順に乗っ取り、必要なファイルをローカルにダウンロードします。
```zsh
npx nuxi init nuxt-app & nuxt-app
```
次に、依存モジュールをインストールします。
```zsh
yarn install
```
以下のコマンドで開発用サーバーをスタートします。
```zsh
yarn dev -o
```
[localhost:3000](localhost:3000)で立ち上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2083780/7c84cb8f-5a4e-e13a-70f2-43f588e09786.png)
### Docker編
取り敢えず、ローカルでサーバーを立ち上げることができたので、次にDockerで立ち上げていきます。
```Dockerfile
FROM node:18.9.0-alpine
WORKDIR /app
COPY package.json .
RUN apk update
RUN yarn install
COPY . .
EXPOSE 3000
CMD yarn run build
```
#### FROM node:18.9.0-alpine
今回は、nodeのversion18.9.0を使うので、公式で提供されているイメージをベースとして使用します。
#### WORKDIR /app
Dockerのコンテナ内処理を行う作業ディレクトリを指定します。
#### COPY package.json .
ローカルのpackage.jsonを`/app`にコピーします。
#### RUN apk update
利用可能パッケージのインデックスを更新します。
#### RUN yarn install
ローカルからコピーしてきた`package.json`をもとに、依存パッケージをインストールします。
#### COPY . .
ローカルのファイルをDockerイメージにコピーします。
#### EXPOSE 3000
Docker内のコンテナのポートを公開します。
＊外部に公開する訳ではないので、別途設定が必要です。
#### CMD yarn run build
コンテナ実行時に実行するデフォルトのコマンドを指定します。
本番環境時にできるだけイメージのサイズの小さくするため、デフォルトではビルドコマンドを指定します。
### Docker-Compose編
Docker Imageを作成したら、次にDocker-Composeを作成していきます。
```yaml
version: '3.9'
services:
  frontend:
    build: .
    ports:
      - 3000:3000
    volumes:
      - .:/app
    environment:
      - HOST=0.0.0.0
      - port=3000
    tty: true
    working_dir: /app
    entrypoint: yarn dev -o
```
#### verison
docker-composeで使用するバージョンを定義します。
今回は、最新バージョンを指定します。
#### services
Docker-Composeで動かすアプリケーションを定義します。
今回は、サクッと環境構築するするだけなので、frontendのみでございます。
#### build
Docker Imageをビルドを定義します。
直接公式のイメージを指定することもできますが、今回は自作のイメージを使用します。
＊`.`のようにpathを指定している場合は、そのpathに存在している`Dockerfile`をビルドします。
#### ports
Docker内で公開されていない3000portをマッピングすることで外部公開します。
`${外部公開先のポート}:${Docker内のポート}`のように定義します。
#### volumes
ローカルのファイルをコンテナ上にマウントする定義をします。
DockerImageを再ビルドする必要がなく、変更がコンテナ上に反映されます。
#### environment
環境変数を指定します。
こちらの設定で、`localhost:3000`で公開されます。
#### tty
ポート待受とかしていないコンテナ起動するとすぐ終了してしまうので起動し続けるために定義します。
#### working_dir
作業ディレクトリを定義します。
#### entrypoint
コンテナ実行時に必ず実行したいコマンド定義します。こちらでサーバーを立ち上げます。
## 実行
DockerImageをビルドし、docker-composeを立ち上げます。
```
docker-compose up --build
# Stop & Delete Containers
docker-compose down
```
[localhost:3000](localhost:3000)で立ち上がります。
Nuxt3での開発ライフをお楽しみください！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2083780/7c84cb8f-5a4e-e13a-70f2-43f588e09786.png)
## 参考文献
https://v3.nuxtjs.org/
https://docs.docker.jp/
https://docs.docker.jp/compose/toc.html
ダウンロードしたプログラムのハッシュをサクッと照合する方法

テキストファイルを用意してチェックするのが標準的なやり方だと思うのですが・・・
それが面倒で、クリップボードにハッシュ値をコピーしてる状態で、ワンコマンドで確認したい。


### 前提

MD5ハッシュ値：`aaaaabbbbbcccccdedddeeeeefffffggggghhhhh`
DLしたソフトのファイル名：`hoge.exe`


### 方法１：ハッシュチェックコマンドの標準入力にハッシュ値とファイルリストのペアを流しこむ

```
echo aaaaabbbbbcccccdedddeeeeefffffggggghhhhh hoge.exe | md5sum -c -
```

→ `hoge.exe: OK`や`hoge.exe: FAILED`が表示される

●省力キーボード入力例：(ハッシュ値をコピーしている状態で)
`"echo " → ペースト(Ctrl+Shift+V) → "ho" → Tab(補完入力) → "| md5sum -c -" → Enter`等でOK


### 方法２：ハッシュチェックコマンドの標準出力をgrepで比較する

```
md5sum hoge.exe | grep aaaaabbbbbcccccdedddeeeeefffffggggghhhhh
```

→ 「前方一致すれば」`aaaaabbbbbcccccdedddeeeeefffffggggghhhhh hoge.exe`が表示される。
→ そうでなければ何も表示されない
デメリット：前方一致が条件なので、完全一致ではない（ポカミスの原因）


### 方法３：方法２の一部改良

```
md5sum hoge.exe | grep "aaaaabbbbbcccccdedddeeeeefffffggggghhhhh "
```

ハッシュ値の末尾に半角スペースを付与しつつ "" で囲む
→ ハッシュ一致すれば`aaaaabbbbbcccccdedddeeeeefffffggggghhhhh hoge.exe`が表示される。
→ そうでなければ何も表示されない


### おまけ

1\. 正攻法であるハッシュリストからチェックする方法

```
md5sum --check hoge.txt
```

→ プログラム名はリストから自動サーチしてくれるので、目的の行にOKが表示されていたら大丈夫。
→ ファイルリストに記載多すぎて見づらい等は、標準エラー出力を捨てたり、結果を grep したら良いです。
　例：

```
md5sum --check hoge.txt 2>/dev/null | grep linux | grep -e x86 -e x64
```


2\. Macはsha256sumがプリインストールされていないらしい

これでインストール出来るらしい。

```
brew install coreutils
```

### まとめ

OK,NGがしっかり分かる「方法１」がおすすめ。
SHA1の場合は`md5sum`を`sha1sum`にするだけ。
SHA256も同様に`md5sum`を`sha256sum`にするだけ。

余談でWSLだと、`Win+R`→`cmd`→`wsl`→`cd Desktop`とすると、デスクトップをカレントディレクトリにした状態でWSLを起動できます。
(コマンドプロンプトのデフォルトのカレントディレクトリはユーザーのフォルダで、wslコマンドを打つと、さっきまで居たディレクトリがカレントディレクトリになる。)

何でこういうのがサクッと検索で見つからないんでしょうね？


### 参考

Windows 10でWSLが無い状態だと、以下が詳しいです。

【Windows】SHA256などのファイルハッシュ値を確認する方法
https://qiita.com/setonao/items/4e9edd3e2064c56507e4
ドキュメントホスティングサービス「ReadMe」のハマりごと

# 概要
自社プロダクトのマニュアルは、[ReadMe](https://readme.com/)というサービスで公開しています。
ハマりごとやハックなどを記載します。


# ハマりごと

## 非ASCII文字のslugやアンカーリンクには、内部リンクで画面遷移できない
2022/10/29に確認。

ページのslugは、明示的に指定しなければページのタイトルになります。したがってslugが日本語名になることが多いです。
ReadMeでは、以下のようにリンクのプレフィックスを`doc:`にすることで、内部リンクが生成できます。

```
[はじめに](doc:はじめに)
```

https://docs.readme.com/docs/linking-to-pages


しかし、ページの閲覧モードでリンクを押しても、画面遷移しません。
アンカーリンクも同様です。アンカーリンクが非ASCII文字だと、slugがASCII文字でも画面遷移しません。

```
# 画面遷移できる
[種類 - はじめに](doc:introduction#type)

# 画面遷移できない
[種類 - はじめに](doc:introduction#種類)
```


slugは明示的に指定できるので問題ありませんが、アンカーリンクは明示的に指定することはできません。
リンク先にアンカーリンクを指定したい場合は、URLを直接指定するのがよさそうです。
インジケータの使い方

# 設定
Storyboardを用いた場合、コードで変えれる部分が色ぐらいだと思います。(他にもおすすめの設定があればコメント頂けると幸いです。)

```ViewController.swift
@IBOutlet private weak var indicator: UIActivityIndicatorView! {
    didSet {
        // 色指定(青)
        indicator.color = UIColor(red: 44 / 255, green: 169 / 255, blue: 225 / 255, alpha: 1)
    }
}
```

# アクション
それぞれ行いたいタイミングで呼び出します。
インジケータは非同期処理と共によく用いられますが、その説明は別記事で紹介します。

```ViewController.swift
// インジケータを表示
indicator.isHidden = false

// アニメーションを開始
indicator.startAnimating()

// インジケータを非表示
indicator.isHidden = true

// アニメーションを終了
indicator.startAnimating()
```
メソッドとかクラスの名前をつけるのに悩む話(C#)

まあよくある話です。前提としては個人開発(Unity)なのでどんなコード書いても許されます。


---
# 事例その1：見えるかどうか
やりたい事としてはまずオブジェクト(`Object`とする)があって、
![Object_0_R.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40557/87dc67fd-6665-d61e-e109-c3c0d4a9be52.png)
それを他のオブジェクト(`Player`とする)から見えるかどうかを、`Object`自身に判定させるメソッド。
![Object_1_R.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40557/d01194a0-e247-af2f-ca5f-492f96d5a528.png)

最初に思いついたのは`IsVisible`ですが、この命名では「こいつ(`Object`)自身を見ることができるか」(=`enabled`に近い)になってしまいます。
というかIs系は「状態的な可否」(今そのオブジェクトがどうなのか)を表すことが多いのでプロパティにつけることが経験上多く、メソッドにIsをつけるのは心理的に抵抗があります。
次に思いついたのは`CanBeSeenFrom(Player)`です。これはUnreal Engine( https://docs.unrealengine.com/5.0/en-US/API/Runtime/AIModule/Perception/IAISightTargetInterface/CanBeSeenFrom/ )でも使用されているようなので、これでとりあえずは良いとしました。
Can系は「動作的な可否」を表す(動詞が直後につく)ので、See(見る)という動作の可否を表すのにはジャストだなと思いました。
ですが、分解するとCan Be Seen Fromと4単語になるため、`IsVisible`のようなわかりやすさがありません。
ということで、これは結局何にすればいいのかわからないまま放置されています。

# 事例その2：静的なデータベース
ゲームを作っているとしましょう。
そこで、ゲームに登場するステージ(`Stage`)の全データをとどめておくクラスを作成したいとします。
(必要になったときに読み込めばいいとかいう話は置いておいてください)

まずStageManagerは論外です。
~~Unityに喧嘩を売ることになってしまいますが、~~`Management`というのは「管理」を表すので、ゲーム自体(`Game`)に対して使用するのであれば適切となり得ます。
ただ、やりたいこととしてはステージの進行を「管理」するのではなくて、データを「置いておく」ということです。
そこで次に思い浮かぶのが「`Database`」でしょう。
しかしこれも適切ではありません。
Databaseとは「書き換え可能な動的データベース」を示すような単語なので、ステージIDなどそうそう変化しない情報を置いておくにはよくありません。
つまり置いておくということであれば「Store」(動詞のほう)が適切だろう……ということで、最終的には「`StageStorage`」になりました。

もう一つの案としては、静的な情報をとどめておくというのはキャッシュの動作なので「`StageCache`」にする手もあります。
ただ、この名前だと「ステージのプレイ内容や画像をキャッシュするクラス」に見えてしまう可能性もあるので、「Cache」を使うのであれば「`StageInfoCache`」「`StagePropertyCache`」などになるのかなと思いました。
難しい。

# ユーティリティ
そもそもUnityに距離を計算する仕組みがあるよというのは置いておいて、距離を計算したいとします。

「Distance」が妥当でしょうね。

それはそれとして、外郭となるクラス名を付けなければなりません。
~~Minecraftに喧嘩を売ることになってしまいます[^1]が、~~「～～Helper」という命名はしたくありません。個人的に。
となると外郭となるクラス名として適切なのは「MathProvider」……ですかね？
しかし、Providerという名前はデカすぎます。まるでそのクラスが提供するものがすべてかのような意味になる(と思っている)ので、結局「MathHelper」になりました。

[^1]:C#はマルチパラダイム言語でOOPではないとされていますが、骨格がOOPなので比較対象としては妥当だと思います

# どうすべきか

先人たちの情報を参考にすること。
@KeithYokoma [うまくクラス名を付けるための参考情報](https://qiita.com/KeithYokoma/items/ee21fec6a3ebb5d1e9a8)
envファイルをGitHubに上げちゃった！(一度GitHubに上げたものを取り消す方法)

一度envファイルをGitHubに上げた状態で.gitignoreに追加しても反映してくれません。

<h1>以下コマンドで解決</h1>

```
git rm -r --cached .env
```
Flutterでログ出力

print()メソッドでログを出していますが、もう少し情報を追加して、汎用的なメソッドが欲しくて作ってみた。

作った後に知ったけど、[【まとめ】Flutterでログ出力してデバッグする方法 | Dart【2022】](https://off.tokyo/blog/how-to-output-logs-and-debug-in-flutter/)で紹介されているようにいろいろな出力あるらしい。
ログを出力する[logger](https://pub.dev/packages/logger)というパッケージもあるようだけど。

お勉強も兼ねて作ってる部分もあります。
kDebugModeをちゃんと試せてないので、いずれちゃんと確認したいところ。

# 実装と概要

そんなに難しことはやってないので、コードを見ればわかります。

```dart
import 'package:flutter/foundation.dart';
import 'package:intl/intl.dart';


/// ログ出力クラス
class Log{

  /// ログに利用する日時フォーマット
  static final DateFormat _datetimeFormat =  DateFormat("yyyy-MM-dd HH:mm:ss.ms");

  /// デバッグログ
  static void debug(String log){
    if (kDebugMode) {
      _log("DEBUG", log);
    }
  }

  /// 情報ログ
  static void info(String log){
    _log("INFO", log);
  }

  /// 警告ログ
  static void warn(String log){
    _log("WARN", log);
  }

  /// エラーログ
  static void error(String log, [Exception? exception]){
    var exceptionMessage = exception?.toString();
    _log("ERROR", "$log $exceptionMessage");
  }

  static void _log(String prefix, String log){
    String date = _datetimeFormat.format(DateTime.now());
    String stackTrace = StackTrace.current.toString();
    String target = stackTrace.split("#2")[1].split("#3")[0].split("(")[1];
    debugPrint("${target.substring(0, target.indexOf(")")).trim()} : [$date][$prefix] $log");
  }
}
```
やってることは、privateメソッドの_log()を使って、その中で、
1. 日時を取得
1. 呼び出し元のスタックトレースからファイルと行列の情報を取得。
1. debugPrintでログを出力

そして、debug()、info()、warn()、error()を実装し、それぞれ種類わかるように出力しているだけです。


# 参考

- [[Flutter][Dart] Stacktrace取得して関数の呼び先をログ出力する](https://deecode.net/?p=1085)
- [【まとめ】Flutterでログ出力してデバッグする方法 | Dart【2022】](https://off.tokyo/blog/how-to-output-logs-and-debug-in-flutter/)
Pega備忘 Validate

Edit ValidateルールとValidateルール

Edit Validateルール
基本的にプロパティに適用する。
正規表現を用いたパターンチェックで用いることが多い。
javaで実装する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130008/08db5668-0a92-300b-1425-b1e5ef9aa055.png)


Validateルール
入力値に対するチェック全般を行える。
相関チェックや、日付のチェック等を行うことができる。
また、Edit Validateルールを使いことも可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130008/e3370657-a6a2-2464-ccca-b86b30d64698.png)
azure テナントの操作について

●現在のテナントの確認
Azureポータルで、サービスの一覧からIDのカテゴリ内にあるAzure Active Directoryをクリックすると、最初に表示される概要メニューで現在のテナントの名前などの情報を確認できる・


●テナントに関連づけられたAzureサブスクリプションの確認
Azureポータルで対象のテナントに切り替えた上で、サービスの一覧から全般カテゴリ内にあるサブスクリプションをクリック。
１つのAzureアブスクリプションと関連づけられるAzure ADテナントは１つだけ。

●新しいテナントの作成
Azureポータルで作成するには、Azure Active Directoryの概要メニューないでテナント管理、作成を押す。その後の画面でテナントの種類として、Azure Active Directoryを選択し、組織名や初期ドメイン名、国/地域を設定して作成する。

※初期ドメイン名には一意の名前を指定する必要がある。
初期ドメイン名はxxx.onmicrosoft.comという形式。

●テナントの切り替え
Azure Active Directoryの概要メニュー内でテナント管理をクリックし、テナントの切り替え画面でテナントを選択してスイッチをクリック。

※テナントの切り替えは、あAzureポータル上部にある　ディレクトリとサブスクリプションからも行うこともできる。

●新しいテナントでのAZure利用
１つのAzureサブスクリプションと関連づけられるAzure ADテナントは１つだけ。
新しいテナントを作成した場合は、そのテナントに紐づいたAzureサブスクリプションは存在しない。新しいテナントでAzureのサービスを利用するには、既存のテナントで使用しているAzureサブスクリプションとは別に、そのテナントで新しいAzureサブスクリピうションを取得（サインアっぷ）する必要がある。
Pythonでネットワークアドレスに含まれるIPアドレス一覧を得る


# はじめに
　前に「任意のIPアドレスレンジからサブネットを算出する」という記事を書きましたが、むしろ逆にネットワークアドレスに含まれるIPアドレス一覧が欲しいという場合の方が多いかも。
　例えば、<code>192.168.1.0/24</code>に含まれるIPアドレスの一覧が欲しいといったニーズ。

　そんな時も[ipaddress](https://docs.python.org/ja/3/library/ipaddress.html)ライブラリや[netaddr](https://netaddr.readthedocs.io/en/latest/index.html)ライブラリを使えば超簡単に解決できます。

　なお、少し使用目的が違うけど、この[サイト](http://ossan.jp/ipaddr/split/)でOriginal Subnet(s)にネットワークアドレスを入れて、Into:に32を入れると同じ様なことができます(結果に<code>/32</code>がつきますが...)。

# やってみる

まずはipaddressを使った方法。

```python:ipaddrs.py
#ライブラリ読み込み
from ipaddress import IPv4Network

#IPv4Networkクラスにネットワークアドレスを渡して、list()でIPv4Addressオブジェクトのリストを得る。
ipaddrs = list(IPv4Network('192.168.1.0/24'))

print(ipaddrs)
```
・結果
```:結果
[IPv4Address('192.168.1.0'), IPv4Address('192.168.1.1'), IPv4Address('192.168.1.2'), IPv4Address('192.168.1.3'), IPv4Address('192.168.1.4'), IPv4Address('192.168.1.5'), IPv4Address('192.168.1.6'), IPv4Address('192.168.1.7'), IPv4Address('192.168.1.8'), IPv4Address('192.168.1.9'), IPv4Address('192.168.1.10'), ...(中略)... IPv4Address('192.168.1.255')]
```

なんて簡単なんだこれは!

netaddrではこんな感じ。

```:netaddrインストール
pip install netaddr
```


```python:ipaddrs1.py
from netaddr import IPNetwork

#IPNetowrkクラスにネットワークアドレスを渡して、list()でIPv4Addressオブジェクトのリストを得る。
ipaddrs = list(IPNetwork('192.168.1.0/24'))

print(ipaddrs)

```

```:結果
[IPAddress('192.168.1.0'), IPAddress('192.168.1.1'), IPAddress('192.168.1.2'), IPAddress('192.168.1.3'), IPAddress('192.168.1.4'), IPAddress('192.168.1.5'), IPAddress('192.168.1.6'), IPAddress('192.168.1.7'), IPAddress('192.168.1.8'), IPAddress('192.168.1.9'), IPAddress('192.168.1.10'), , ...(中略)...  IPAddress('192.168.1.255')]
```

ほぼ同じだな、こりゃ。

なお、文字列型のリストで結果が欲しい場合は
```python
ipaddrs_str = [*(map(str, ipaddrs))]
```
などとしてあげれば良い。

# さいごに
　この[netaddr](https://netaddr.readthedocs.io/en/latest/index.html)や[ipaddress](https://docs.python.org/ja/3/library/ipaddress.html)というライブラリはIPアドレスやネットワークアドレスに対する操作をするのにすごく便利なライブラリで、サブネット分割だけでなく、さまざまな操作ができます。

　これまでにいくつか記事を書きましたので、そちらもご参照ください。
　また、そのような操作をWeb上でできる[サイト](http://ossan.jp/ipaddr/)を提供しているので是非ご利用ください。

https://qiita.com/aikamanami11/items/d88183c7ced2df071ea0

https://qiita.com/aikamanami11/items/4e8348d7369d9dadb1c4

https://qiita.com/aikamanami11/items/b63f9d663db0fdb34530

https://qiita.com/aikamanami11/items/6ecb4fe19ea94cd1b5e3

https://qiita.com/aikamanami11/items/5376345a7ebb9c220c1f

https://qiita.com/aikamanami11/items/61f8bfe44a777f51d4b0

IP Addr Tools: IPアドレスやサブネットを操作するいくつかのツールを提供しています。

http://ossan.jp/ipaddr/

以上

参考サイト:

https://netaddr.readthedocs.io/en/latest/index.html

https://docs.python.org/ja/3/library/ipaddress.html
【IPFS】Proxmox で "Could not connect to the IPFS API"

> Proxmox VE で Ubuntu の LXC コンテナ上に IPFS のノードを起動し、IPFS の WebUI を開くも、 "<font color=red>⚠️ Could not connect to the IPFS API</font>" と表示される。

## TL; DR <sub><sup>（今北産業）</sup></sub>

1. IPFS の API はデフォルトで [CORS](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)（Cross-Origin Resource Sharing）が無効になっている。
1. API の CORS 設定で `Allow-Origin` を有効にする必要がある。
1. 以下を実行後、IPFS を再起動するとアクセスできるようになります。
    ```bash
    ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://192.168.***.***:5001", "http://localhost:3000", "http://127.0.0.1:5001", "https://webui.ipfs.io"]'
    ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "POST"]'
    ```

## TS; DR

落ち着いて見ると、下の方に回避策が記載されていました。。。とほほ

![スクリーンショット 2022-10-28 23.27.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78776/c796b3cb-32ba-fa1a-e2f3-dd643e2661ef.png)
Pythonで任意のIPアドレスレンジからそれらを包含するサブネットを算出する


# はじめに
　任意のIPアドレスレンジからサブネットを算出する機会がありますかね?
　例えば、<code>192.0.2.0</code>から<code>192.0.2.130</code>までのIPレンジを包含するネットワークアドレスを知りたいといったニーズ。

　そんな時は[ipaddress](https://docs.python.org/ja/3/library/ipaddress.html)ライブラリや[netaddr](https://netaddr.readthedocs.io/en/latest/index.html)ライブラリを使えば割と簡単に解決できます。

# やってみる

まずはipaddressを使った方法。

```python:nwaddrs.py
#ライブラリ読み込み
from ipaddress import IPv4Address, summarize_address_range

#IPアドレスレンジの最初と最後をそれぞれの変数に格納
first_ipaddr = IPv4Address('192.0.2.0')
last_ipaddr  = IPv4Address('192.0.2.130')

#summarize_address_range(最初のIPアドレス, 最後のIPアドレス)でネットワークアドレスが返る
subnets = list(summarize_address_range(first_ipaddr, last_ipaddr))

print(subnets)
```
・結果
```:結果
[IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/31'), IPv4Network('192.0.2.130/32')]
```

　良さげ。
　<code>192.0.2.0</code>から<code>192.0.2.130</code>までのIPレンジを包含するネットワークアドレスは次の3つということがわかる。

|ネットワークアドレス|レンジ|
|:----:|:----:|
|192.0.2.0/25|192.0.2.0 ~ 192.0.2.127|
|192.0.2.128/31|192.0.2.128 ~ 192.0.2.129|
|192.0.2.130/32|192.0.2.130 ~ 192.0.2.130|



netaddrではこんな感じ。

```:netaddrインストール
pip install netaddr
```


```python:nwaddrs1.py
from netaddr import IPRange, IPNetwork

first_ipaddr = '192.0.2.0'
last_ipaddr  = '192.0.2.130'

subnets = IPRange(first_ipaddr, last_ipaddr).cidrs()

print(subnets)
```

```:結果
[IPNetwork('192.0.2.0/25'), IPNetwork('192.0.2.128/31'), IPNetwork('192.0.2.130/32')]
```

# さいごに
　この[netaddr](https://netaddr.readthedocs.io/en/latest/index.html)や[ipaddress](https://docs.python.org/ja/3/library/ipaddress.html)というライブラリはIPアドレスやネットワークアドレスに対する操作をするのにすごく便利なライブラリで、サブネット分割だけでなく、さまざまな操作ができます。

　これまでにいくつか記事を書きましたので、そちらもご参照ください。

https://qiita.com/aikamanami11/items/d88183c7ced2df071ea0

https://qiita.com/aikamanami11/items/4e8348d7369d9dadb1c4

https://qiita.com/aikamanami11/items/b63f9d663db0fdb34530

https://qiita.com/aikamanami11/items/6ecb4fe19ea94cd1b5e3

https://qiita.com/aikamanami11/items/5376345a7ebb9c220c1f

以上

参考サイト:

https://netaddr.readthedocs.io/en/latest/index.html

https://docs.python.org/ja/3/library/ipaddress.html
VBAでボリュームデータのランダム作成

### 要件
性能テストのため、ボリュームデータが必要ですが、本番データがとれない場合、何十万、百万のデータ作成
になります。Excel自身で１００万レコードを表示できるが、手で埋めることは無理です。もう一つは区分、日付はバランス的にうめることは容易ではない。

### 案

・順番できるデータは１から増やせる
　　→SEQ型で、先頭文字を指定する
・区分データはランダム関数を使う。
  　→List型で、区分は配列に入れ、配列「区分数＊Rand」で取ると、バランス的に使われる
　　区分が一つしかない場合、固定値になる

### 実装
　・シートに特別文字ないと、対象シートではないと判断する
　　例：Cells(1, 2)に”TestData”がマークとする
　・作成行数を指定する
　　例：Cells(4, 4)に25件とする
　・テーブル定義が横に置く
　・データ指定、開始行列は下記ようにする
　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/5e790925-3166-e2ca-814d-58a9000d86aa.png)

### ソース
```
Sub MakeData()
 Set wks = ActiveSheet
 If wks.Cells(1, 2) <> "TestData" Then
  MsgBox "You Should use TestData Sheet"
  Exit Sub
 End If
 
 cnt = wks.Cells(4, 4)
 
 jj = 4
 ii = 10
 tbn = wks.Cells(3, 3)
 While wks.Cells(6, jj) <> ""
   cnm = wks.Cells(6, jj)
   tp = wks.Cells(8, jj)
   iniv = wks.Cells(9, jj)
   If tp = "SEQ" Then
    
     For kk = 1 To cnt
       wks.Cells(9 + kk, jj) = iniv & Right("000000" & kk, 6)
     Next kk
   End If
    If tp = "List" Then
      lstv = Split(iniv, ";")
      lstn = UBound(lstv) + 1
    
     For kk = 1 To cnt
       Randomize
       wks.Cells(9 + kk, jj) = lstv(Int(lstn * Rnd))
     Next kk
   End If
 

 
   jj = jj + 1
 Wend
MsgBox "set data ok"
End Sub
```

### おまけ
　JsonデータとJavaまたJavaScript用の形式を生成
```
'make array of json data\
Sub MakeJson()
Set wks = ActiveSheet
 If wks.Cells(1, 2) <> "TestData" Then
  MsgBox "You Should use TestData Sheet"
  Exit Sub
 End If
 
 jstr = "["
 apexStr = "'['"
 
 jj = 4
 ii = 10
 lstr = ""
 vall = "" 'all values for the line
 lcnt = 0
 tbn = wks.Cells(3, 3)
NEXTII:
 While wks.Cells(6, jj) <> ""
   cnm = wks.Cells(6, jj)
   tp = wks.Cells(8, jj)
   vv = Trim(wks.Cells(ii, jj))
   vall = vall & vv
   If tp <> "" Then
     cellstr = Chr(34) & cnm & Chr(34) & ":" & Chr(34) & vv & Chr(34)
     If lstr = "" Then
      lstr = "{" & cellstr
     Else
      lstr = lstr & "," & cellstr
     End If
   End If
 jj = jj + 1
 Wend
 If Len(vall) > 2 Then
  If lcnt = 0 Then
   jstr = jstr & " " & lstr & "}" & vbLf
   apexStr = apexStr & vbLf & " +'" & lstr & "}'" & vbLf
  Else
   jstr = jstr & "," & lstr & "}" & vbLf
   apexStr = apexStr & "+ '," & lstr & "}'" & vbLf

  End If
  lcnt = lcnt + 1
  ii = ii + 1
  jj = 4
  vall = ""
  lstr = ""
  GoTo NEXTII
 Else
  jstr = jstr & "]"
  apexStr = apexStr & "+ ']'"

 End If
  
 wks.Cells(1, 3) = jstr
 wks.Cells(1, 4) = apexStr
 
 MsgBox "make json ok" & apexStr


End Sub
```
Amazon Aurora Serverless v2 料金計算

# はじめに
Amazon Aurora Serverless v2 とは、AWSのサーバーレスのデータベースサービス。
前回の記事ではハンズオンを実施してみました。
[Amazon Aurora Serverless v2 ハンズオンやってみた \- Qiita](https://qiita.com/ebarou/items/237823ac848facabdaa6)


今回の記事では料金の計算方法をまとめたいと思います。

# ACUとは
AWS公式サイトで東京リージョンの料金を確認してみると
**Aurora キャパシティーユニット　　　0.20USD/ACU 時間**
[料金 \- Amazon Aurora \| AWS](https://aws.amazon.com/jp/rds/aurora/pricing/)

キャパシティユニット..? ACU..?


>Aurora Serverless では、データベース容量は 1 秒あたりに請求される Aurora Capacity Unit (ACU) で測定されます。1 ACU には、対応する CPU とネットワークを備えた約 2 GB のメモリがあり、Aurora でプロビジョンしたインスタンスで使用されているのと類似のものです。([料金 \- Amazon Aurora \| AWS](https://aws.amazon.com/jp/rds/aurora/pricing/))

■ ACU とは
Aurora 容量単位。Aurora Capacity Unit。
1ACU あたり約2GBのメモリ、対応するCPU、ネットワークが組み合わせられる。

つまり、db.t3.medium(2コア、4GB)相当の性能にするには、2ACU必要。
1時間動かしたとして、0.20USD × 2ACU × 1時間 = **0.40USD**
db.t3.mediumは1時間あたり **0.125USD**

Oh..Serverless 高すぎ...!?

# Serverlessは高い？

自動でスケールするらしい。

>データベースの容量は、アプリケーションのワークロードのニーズを満たすように自動的にスケールアップまたはスケールダウンされ、非アクティブ時にはシャットダウンされるため、コストを削減し管理する時間を節約できます。([料金 \- Amazon Aurora \| AWS](https://aws.amazon.com/jp/rds/aurora/pricing/))

Aurora Serverlessを起動するときに最小と最大のACUを設定する項目がある。
最小、最大で設定したACU間を負荷に合わせて自動でスケールする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2857191/a578f0ec-fb21-9e13-a48c-c90ba45f69ba.png)

つまり、先ほどのdb.t3.mediumの例でいくと、
1時間常に休みなく4GBを使う処理をしていたら、**0.40USD** 
1時間の間に処理しない時間や4GB未満の処理もあるなら、安くなる。

# Serverlessは本当に安いのか
ServerlessでないAuroraと料金比較してみる。

■ 料金計算の例
・1ヶ月間の料金
・メモリ最大16G ほしい
・ただし、常に16Gのメモリを使うわけではない。
・1日のうち4時間は16G(8ACU)、8時間は1G(0.5ACU)の処理を行い、それ以外は処理しないと想定する。

**【Provisioned型(Serverlessでない)の場合】**
　db.r5.largeを選ぶこととする。
　0.70USD × 24時間 × 30日 = **504USD**

**【Serverless型の場合】**
　最小ACUを0.5、最大ACUを8とする。
　0.20USD × 8ACU × 4時間 = 6.40USD
　0.20USD × 0.5ACU × 8時間 = 0.80USD
　( 6.40USD + 0.80USD ) × 30日 = **216USD**

# おわり
Aurora Serverlessの料金について調べてみました。
Azure AD JoinedなWindowsのユーザーフォルダ名がDisplayNameから取られる問題への対処例

あくまで一例です。

# 前提

* Azure ADの表示名に日本語が含まれている
* Azure AD Joinedである
* Windows 10以降のPCを使用している

# 現象

* Azure AD参加でWindowsのユーザーアカウントを作成すると、DisplayName（表示名）がWindowsのユーザーフォルダ名に使われる

# 問題点

* ユーザーフォルダ名が日本語だと動かないアプリが出てくる
    * VSCodeの拡張機能とか
* 一度ユーザーフォルダを作ってしまうと変更できない
    * 正確にはレジストリ書き換えで可能だが、いろいろな不具合が出る可能性があり、MSとしても非推奨

# 対処法

1. Azure ADの表示名を半角英数字だけにする
    * 運用上許されるのならばこれがベスト！
    * メール誤送信のリスクとかで不可の会社もあるよね…
2. Windowsのセットアップ前だけAzure ADの表示名を半角英数字にし、セットアップ完了後に日本語に変える
:::note info
今回やるのは **2.**
:::

# 実際にやったこと

## 環境

ユーザー山田太郎を一例に。

* 表示名:Yamada Taro (山田 太郎)
* 姓:山田
* 名:太郎
* UPN:taro.yamada@contoso.com
* これから新たにWindowsのユーザーアカウントを作る
    * すでに日本語含んだままユーザーフォルダが作られてしまった人は初期化して再セットアップ

## 流れ
1. Azure ADアカウントの表示名（DisplayName）フィールドを半角英数字のみにする
    * 表示名:taro.yamada
2. ユーザーがWindows PCに初めてサインインする
    * ユーザーフォルダが半角英数字で作られる
        * taroyamada
         :::note info
         .は自動的に削除されます
     
3. 定刻になるとバッチが動いて、Azure ADアカウントの表示名をもとに戻す
    * 表示名:Yamada Taro (山田 太郎)


## バッチ処理（本題）

3.の処理を実現するために

### Power AutomateでGraph APIを毎日午前2時に叩くフローを作った
* 処理内容
    1. MDMデバイス一覧をGraph APIで取得
    1. 1.の取得結果1レコードずつに以下を繰り返し処理
        * MDMデバイスに紐づくユーザー情報を取得
        * ユーザーのdisplayNameが'(surname givenname)'を含んでいるかチェック
        * 含んでいない場合のみ以下の処理
            * リネーム


* ポイントになるGraph APIのクエリ
    1. MDM管理のデバイス一覧を取得（IntuneやO365 Mobile）
        * https://graph.microsoft.com/v1.0/deviceManagement/managedDevices
        * GETで実行
    2. MDM管理デバイスに紐付くユーザーの情報を取得
        * https://graph.microsoft.com/v1.0/users/{user-id}
        * GETで実行
    3. ユーザーの表示名を書き換え
        * https://graph.microsoft.com/v1.0/users/{user-id}
        * PATCHで実行
        * リクエストBodyに修正後の表示名を含めたJsonを含める
     * APIを叩くためにはAzure ADへのアプリ登録が必要
        * 以下を参考に
        * https://www.softbanktech.co.jp/special/blog/cloud_blog/2021/0058/
        * 必要なAPIアクセス許可はGraph Explorerで1.〜3.のクエリを叩いて確認

### Power Automateフロー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380031/de697893-8375-b2ef-dea9-3b217b3bc024.png)


# その他

あまり考えずにオンプレAD環境からAAD+Intuneへ移行したら、表示名がユーザーフォルダになってしまって、開発チームからクレームの嵐！（ってほどでもないけど、だいぶ困った）
それなりのPC台数あると人力でやるのもつらい。
ユーザー自身に表示名変えてもらう案も考えたけど、ユーザー管理者ロールが必要。それを与えると自分以外のユーザーの名前も変更できてしまう。
一時アクセスパスでうまくやる方法もあるのかな？（要調査）
Memory usageを楽しむ（Elixir）

# はじめに

[Nerves](https://www.nerves-project.org/)にsshするとこんな表示がでます。

![スクリーンショット 2022-10-28 22.10.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/0e4a43d1-11c8-d8f5-6c29-8aee170bddd8.png)


この記事は`Memory usage`を深掘してみます。

# こたえ

早速答えです。

https://github.com/nerves-project/nerves_motd/blob/cd97c1773082d41a91856e17299390a37c87bae9/lib/nerves_motd/runtime.ex#L66-L82

```elixir
  def memory_stats() do
    # Use free to determine memory statistics. free's output looks like:
    #
    #                   total        used        free      shared  buff/cache   available
    #     Mem:         316664       65184      196736          16       54744      253472
    #     Swap:             0           0           0

    {free_output, 0} = System.cmd("free", [])
    [_title_row, memory_row | _] = String.split(free_output, "\n")
    [_title_column | memory_columns] = String.split(memory_row)
    [size_kb, used_kb, _, _, _, _] = Enum.map(memory_columns, &String.to_integer/1)
    size_mb = round(size_kb / 1000)
    used_mb = round(used_kb / 1000)
    used_percent = round(used_mb / size_mb * 100)

    {:ok, %{size_mb: size_mb, used_mb: used_mb, used_percent: used_percent}}
  rescue
    # In case the `free` command is not available or any of the out parses incorrectly
    _error -> :error
  end
```

要するに、`free`コマンドの結果で、`Mem`の`total`と`used`の値で計算しています。
文字列を改行（`\n`）でsplitしてあとは巧みにパターンマッチをして値を取り出しています。
coolです。何かの折にきっとこの技を使いたいと切におもいました。

# 試してみる

[Nerves](https://www.nerves-project.org/)をお使いの方は、sshしてお楽しみください。

macOSで試してみようとしました。しかし、macOSには、`free`コマンドはありません。
そこでDockerで動かしてみます。

```bash:CMD
docker pull hexpm/elixir:1.14.1-erlang-25.1.2-ubuntu-xenial-20210804
docker run --rm -it hexpm/elixir:1.14.1-erlang-25.1.2-ubuntu-focal-20211006 iex
```

IExが立ち上がります。
あとは、「こたえ」のところで示したコードを実行してください。
再掲しておきます。

```elixir
{free_output, 0} = System.cmd("free", [])
[_title_row, memory_row | _] = String.split(free_output, "\n")
[_title_column | memory_columns] = String.split(memory_row)
[size_kb, used_kb, _, _, _, _] = Enum.map(memory_columns, &String.to_integer/1)
size_mb = round(size_kb / 1000)
used_mb = round(used_kb / 1000)
used_percent = round(used_mb / size_mb * 100)
```

コピペして貼り付けて、迷わず実行してみてください。

# おわりに

この記事は、[Nerves](https://www.nerves-project.org/)にsshしたときに表示される`Memory usage`を深掘してみました。
Dockerで試してみる方法もご紹介しました。

Enjoy [Elixir](https://elixir-lang.org/)!!!
【備忘録1】Ruby：複数データの奇数・偶数の判定の考え方

備忘録として自分の思考の軌跡を残しておきます。
今回の問題はこちらです。

https://paiza.jp/works/mondai/loop_problems2/loop_problems2__even_output


# 考え方

## 1．奇数を数式で表す

まず考えることは「奇数をどのように表すか」ということです。奇数は数値nを2で割った時の余りが1になればよいので、これを数式で表します。

```ruby
num % 2 == 1
```

Rubyでは「**％**」を使って余りを算出します。

## 2．奇数・偶数の判定方法を考える

今回求められている出力結果は「奇数のみを出力すること」だったので、この式を元に、**if**を用いた場合分けを考えていきます。
上記の式の結果がtrueになったときに出力するようにしたいので、以下のような式を作成します。

```ruby
if num % 2 == 1
	puts num
end
```

## 3．標準入力でのデータ受け取り

それでは入力されたデータを受け取り、実際に組み立てていきます。
今回は以下のような数値を例とします。1行目に整数の個数Nが、2行目に数値が入力されています。

> 5
24 38 55 65 79
> 

まず、**gets**を用いてデータを受け取ります。

```ruby
a = gets.to_i
```

これで受け取ったデータが**a**に代入されました。与えられたデータを数値で受け取る時はgetsの後に「**.to_i**」を付けます。

次に2行目に与えられた整数を配列で受け取ります。

```ruby
ary = gets.split.map(&:to_i)
```

これで2行目のデータが配列として**ary**に代入されました。

このコードでは、まず**gets.split**で入力文字列を配列に分割し、その配列をさらに**.map(&:to_i)**で整数型に変換しています（[じゃいごテック様の記事](https://jaigotec.com/paiza-stdin_primer_read_line_step4-6/)を参考にしています）。

## 4．ループ処理の組み立て

ここからは、数値データが代入されている**ary**を用いて、奇数偶数の判定をしていきます。

全ての数値の判定をするためには繰り返しの処理が必要ですので、**for…in**を用いてループ処理のコードを組み立てていきます。

```ruby
for num in ary

end
```

このような形でループ処理を記述します。**ary**のデータを取り出して**num**に代入し、記述された処理を**ary**のデータを全て取り出すまで行うというイメージです。

## 5．完成

この中に冒頭で作成した**if**を用いたコードを追記します。

```ruby
for num in ary
	if num % 2 == 1
		puts num
	end
end
```

これでaryに入力された数値の奇数・偶数を判別し、奇数だったら出力されるようになりました。

参考までに、すべて記述したものを以下に記しておきます。

```ruby
a = gets.to_i #整数の個数Nの出力
ary = gets.split.map(&:to_i) #配列で受け取り、数値に変換

for num in ary　#配列の数値の奇数・偶数判定
	if num % 2 == 1
		puts num
	end
end
```

もっと良い書き方があると思います。もしありましたらコメントなどでご教授ください。間違いもありましたらあわせてご指摘ください。整数の個数を受け取るやり方などあると思います。

<h2>不明点や理解できていなかった点</h2>
<ul>
    <li>for構文</li>
    <li>.mapを使ったデータ受け取り</li>
</ul>


<H2>参考資料</h2>

https://jaigotec.com/paiza-stdin_primer_read_line_step4-6/

https://www.javadrive.jp/ruby/for/index3.html
【Python】OpenCVで画像処理（グレースケール）（初心者向け）

# １．はじめに
PythonにてOpenCVを用いた画像処理を実施したのでまとめました。
今回はWebアプリを想定しているため、djangoの機能を使用して画像を取り込み、取り込んだ画像をグレースケールに変換してみました。
djangoの使用については、株式会社キカガク殿にて学習した内容を元に作成しました。

# ２．開発環境
・Windows10
・Python 3.9.12
・opencv-python--headless==4.5.1.48

# ３．画像の取り込み
djangoの機能を使用して、画像を選択した後取り込むことができるファームを実装しました（今回の説明では割愛します）。
ファームから取り込んだ画像をプログラム上で処理するためcv2.imread()を使用します。下記pathの中身は、ファイル名を指定しています。

```
import cv2
(省略)

img = cv2.imread(path)
```
# ４．グレースケールに変換
画像をグレースケールに変換するためcv2.cvtColor()を使用します。cv2.cvtColor()の引数には、img(上記ファイル名を示します)とcv2.COLOR_BGR2GRAYを指定します。

```
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
```

# ５．結果
下の画像はグレースケールに変換する前と後の画像になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2940692/76fefc5f-694a-82e9-7d90-7fde8afa3e35.png)
変換前の画像

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2940692/de3649fd-d20e-0bd6-3cb2-4da0d70e6497.png)
変換後の画像

無事にグレースケールに変換することができました。
グレースケールに変換することで、ノイズが減り画像処理の誤認識が減らせるそうです。

# ６．参考文献
・https://camp.trainocate.co.jp/magazine/python-opencv/
$_SERVER['DOCUMENT_ROOT']に関する考察　そもそもドキュメントルートって？

Movable Type引っ越しシミュレーションをする際に、$_SERVER['DOCUMENT_ROOT']で引っかかったので考察を記す。

今回は、エックスサーバーで検証してみよう。

まず、ドキュメントルートを表示するためのindex.phpを準備する。

```
<?php
echo $_SERVER['DOCUMENT_ROOT'];

```

これを下記の①～③の、階層が異なるディレクトリに置いて挙動を検証する。

ちなみに、エックスサーバーのホームディレクトリは、/home/ユーザー名 である。

## ①/home/ユーザー名/hoge.com/public_html/index.php
結果
```
/home/ユーザー名/hoge.com/public_html
```
## ②/home/ユーザー名/hoge.com/public_html/dir/index.php
結果
```
/home/ユーザー名/hoge.com/public_html
```
## ③/home/ユーザー名/hoge.com/public_html/dir/dir2/index.php
結果
```
/home/ユーザー名/hoge.com/public_html
```

つまり、異なる階層でドキュメントルートを呼び出しても、結果は全部同じになる。

そう、ドキュメントルートとは、「公開されるディレクトリの最上部」なのである。。。
※厳密に言うと、「現在実行されているスクリプトが存在するドキュメントルート ディレクトリ」



# 私はいったい何を言いたかったのか
冒頭で書いたMovable Typeのindex.phpの中身はこうだ。
```
<?php
$title = 'home';
$page_meta_keywords = 0;
$page_meta_description = 0;
require_once $_SERVER['DOCUMENT_ROOT'] . '/module/config/config.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/module/config/require.php';

ob_start();
if (DEVICE_TYPE === 'mobile' && MT_MOBILE_USE === '1') {
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/mobile/config.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/mobile/parts/header.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/mobile/layout/main_index.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/mobile/parts/footer.php';
} elseif (DEVICE_TYPE === 'sphone' && MT_SPHONE_USE === '1') {
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/sphone/config.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/sphone/parts/header.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/sphone/layout/main_index.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/sphone/parts/footer.php';
} else {
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/default/parts/html_header.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/default/parts/header.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/default/layout/main_index.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/default/parts/sidebar.php';
	require_once $_SERVER['DOCUMENT_ROOT'] . '/module/template/default/parts/footer.php';
}
$output = ob_get_contents();
ob_end_clean();

//携帯サイトは文字コード変換
if (DEVICE_TYPE === 'mobile' && MT_MOBILE_USE === '1') {
	$output = mb_convert_encoding($output, 'Shift_JIS', 'UTF-8');
}

// 出力
echo $output;
```

そう。$_SERVER['DOCUMENT_ROOT']　だらけだ。

私はシミュレーションの都合上、ドキュメントルートの直下にディレクトリを作り（/home/ユーザー名/hoge.com/public_html/aaa/）、そこにMovableTypeをアップロードしていた。

しかし、5行目でエラーで引っかかる。

そう。MovableTypeは、ドキュメントルート、つまりpublic_htmlの直下にアップロードしないといけないのだ。

それを言いたかったのである。。。
以上。
Sourcetreeでターミナルをwindows Terminalに設定する

Sourcetreeでターミナルを開くと通常git bashが呼ばれるが、これをwindow Terminalを呼ぶように設定してみた。

1. まずwindow Terminalをインストールする。
https://www.curict.com/item/26/2629f94.html

2. window Terminalでgit bashを開けるように設定する。
https://qiita.com/yokra9/items/bdd0882268b308cf22ca

3. sourceTreeでカスタム操作を設定する。
https://qiita.com/tenten0213/items/2b8ceb58f773d0590f06

4. カスタム操作編集画面で、以下のように実行するスクリプトをbatファイルに設定する。
参考：https://www.5cho-me.com/archives/173671
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495919/a4da6560-5d4a-1845-909a-ae8b3c4b11d9.png)

batファイルは、以下のように書く。
参考：https://news.mynavi.jp/techplus/article/techp4959/
`-p "git bash"`は2.で設定したプロファイルのnameを表す。
`-d`は開始するディレクトリを表し、`%1`は4.設定したパラメータ`$REPO`(リポジトリのパス)を表す。

```soureTree.bat
@echo off
C:\Users\user\AppData\Local\Microsoft\WindowsApps\wt.exe -p "git bash" -d %1
```

設定したカスタム操作を呼び出しやると...
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495919/75b47d0c-8f39-7aca-06e5-9394a38386db.png)

windows Terminalが呼び出せた!!
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495919/3c9cccb0-8a8b-520b-5583-ace35b23d861.png)