OmniAICreator/Qiita-1.07M huggingface dataset:
Flutter: Sliderのシンプルな実装

必要最低限のSliderの実装方法です。
物覚えが悪いので備忘録として残しておきます。


####Flutterバージョン
```
Flutter 2.3.0-17.0.pre.366 
```

##実装するだけなら
実装するだけなら必須プロパティである`value`に値、`onChanged`にスライドをいじったときの処理を書きます。`onChanged`には変更された値が保持されてるのでその値を使って変数の値を上書きしたりできます。

以下の例はColumnを設置し、その中にSliderの値を表示するTextとSliderを入れています。

```
class _MyHomePageState extends State<MyHomePage> {
  double _number = 1.0;  // 表示する値

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            '${_number.toStringAsFixed(2)}',  // Sliderの値を表示
            style: TextStyle(fontSize: 30.0),
          ),
          Slider(
            value: _number,   // 値を指定
            onChanged: (value) {  // 変更した値を代入
              setState(() {
                _number = value;
              });
            },
          ),
        ],
      ),
    );
  }
}
```
![画面収録-2021-08-02-16.25.13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/55cc6e87-011a-8e2e-3dc6-c48efb672610.gif)

Textの値に`toStringAsFixed(2)`というメソッドを追加して下2桁まで表示させてます。
表示するときは整数化したり表示させたい小数点の指定をしましょう。
そのまま表示すると小数点以下の数字がすごく長くなってしまいます。

値の最小値と最大値を指定するときは、プロパティ`min`と`max`を指定します。

```
class _MyHomePageState extends State<MyHomePage> {
  double _season = 1;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            '${_season.toInt()}',
            style: TextStyle(fontSize: 30.0),
          ),
          Slider(
            value: _season,
            min: 1,
            max: 20,
            onChanged: (value) {
              setState(() {
                _season = value;
              });
            },
          ),
        ],
      ),
    );
  }
}
```

![画面収録-2021-08-02-16.42.56.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/4d22df8b-c35a-ccca-3b7f-e75688a76ba6.gif)

##SliderThemeで装飾する
SliderThemeを使用することで簡単に装飾ができます。プロパティ`data`に`SliderTheme.of(context).copyWith`を定義しいじりたい箇所を指定します。

```
SliderTheme(
            data: SliderTheme.of(context).copyWith(
              activeTrackColor: Colors.green, // 適用されてる領域
              inactiveTrackColor: Colors.grey, // 適用されていない領域
              trackHeight: 10.0, // スライダーの幅
              thumbColor: Colors.red, // つまみの色
              overlayColor: Colors.blue, // つまみを掴んだ時に広がる領域の色
              thumbShape: const RoundSliderThumbShape(
                  enabledThumbRadius: 15.0), // つまみの大きさ
              overlayShape: const RoundSliderOverlayShape(
                  overlayRadius: 30.0), // つまみを掴んだ時に広がる領域の大きさ
            ),
            child: Slider(...
```
![画面収録-2021-08-02-17.04.26.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/c58783eb-b6a5-34f8-5d06-78f01d09b461.gif)

直観的に把握するためするため色を派手にしております。
n回ループする処理をJS/TSで書く

```javascript
const count = 5
Array.from({ length: count }).map((_, index) => console.log(index))

0
1
2
3
4
```


---

以下の書き方は、推奨ではなく、「こんな書き方も出来るよ」という内容です。
不必要にメモリを消費するので、使うとしてもテストコード内にとどめるのが良いと思います。
書き方のメリットは以下です。

- 簡潔に書ける。
- 高階関数が使える。

---


```javascript
[...Array(n)]
// or
Array(3).fill()
```

n に要素数を入れます。

---

これ（↓）で、要素数が 3 で中身が空（undefined）の配列が出来ます。

```javascript
> [...Array(3)]
[ undefined, undefined, undefined ]

> [...Array(3)].length
3
```

```javascript
> Array(3).fill()
[ undefined, undefined, undefined ]

> Array(3).fill().length
3
```

map　で使う。

```javascript
> [...Array(3)].map((val, index) => index)
[ 0, 1, 2 ]
```

forEach で使う。

```javascript
> [...Array(3)].forEach((val, index) => console.log(index))
0
1
2
```
【PHP】IDが一致した配列同士を結合する。配列にカラムを追加する

```PHP
<?php

$cooking = [
  ["menu_id" => 40,"menu_name" => "お好み焼き","submenu_name" => "鰹節","drink" => "ハイボール"],
  ["menu_id" => 20,"menu_name" => "カレー","submenu_name" => "ライス","drink" => "烏龍茶"],
  ["menu_id" => 99,"menu_name" => "パスタ","submenu_name" => "タバスコ","drink" => "ビール"],
  ["menu_id" => 10,"menu_name" => "焼き肉","submenu_name" => "ソース","drink" => "ジンジャエール"],
  ["menu_id" => 30,"menu_name" => "寿司","submenu_name" => "醤油","drink" => "緑茶"],
  ["menu_id" => 50,"menu_name" => "サンドイッチ","submenu_name" => "ラー油","drink" => "紅茶"]
];

$add = [
    0 => [ 'id' => 10, 'age' => '1995年06月08日'],
    1 => [ 'id' => 20, 'age' => '2009年05月23日'],
    2 => [ 'id' => 30, 'age' => '2006年08月26日'],
    3 => [ 'id' => 40, 'age' => '1993年02月24日']
];


$add =  array_column($add, 'age', 'id');


foreach($cooking as $list ){
    if(!empty($add[$list['menu_id']])){
        $result[] = $list + ['age' => $add[$list['menu_id']]];
    }
};


var_dump($result);

```

# 結果


```
array(4) {
  [0]=>
  array(5) {
    ["menu_id"]=>
    int(40)
    ["menu_name"]=>
    string(15) "お好み焼き"
    ["submenu_name"]=>
    string(6) "鰹節"
    ["drink"]=>
    string(15) "ハイボール"
    ["age"]=>
    string(17) "1993年02月24日"
  }
  [1]=>
  array(5) {
    ["menu_id"]=>
    int(20)
    ["menu_name"]=>
    string(9) "カレー"
    ["submenu_name"]=>
    string(9) "ライス"
    ["drink"]=>
    string(9) "烏龍茶"
    ["age"]=>
    string(17) "2009年05月23日"
  }
  [2]=>
  array(5) {
    ["menu_id"]=>
    int(10)
    ["menu_name"]=>
    string(9) "焼き肉"
    ["submenu_name"]=>
    string(9) "ソース"
    ["drink"]=>
    string(21) "ジンジャエール"
    ["age"]=>
    string(17) "1995年06月08日"
  }
  [3]=>
  array(5) {
    ["menu_id"]=>
    int(30)
    ["menu_name"]=>
    string(6) "寿司"
    ["submenu_name"]=>
    string(6) "醤油"
    ["drink"]=>
    string(6) "緑茶"
    ["age"]=>
    string(17) "2006年08月26日"
  }
}
```
DjangoでWebサービスの枠を作るまで

## Djangoプロジェクトの構造

Djangoプロジェクトは、プロジェクトという大枠があり、その中にアプリケーションがあるという構造です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/020cf611-f9b7-a941-4f49-af2feaeddf26.png)

プロジェクトは自分が作成したWebサイトを例えると、Appはブログ、Wiki、フォームなどがあります。
以下はmysiteというDjangoプロジェクトを作成し、そのなかにblogというAppを作成してみます。

## プロジェクトの作成

以下のコマンドを実行します。

```shell
django-admin startproject mysite
```

生成されたプロジェクト構造を見てみましょう。

```text
mysite/
    manage.py
    mysite/
      __init__.py
      asgi.py
      wsgi.py
      settings.py
      urls.py
```

* manage.py
    * プロジェクトを操作するためのコマンドラインユーティリティです。編集する必要がありません。
* mysite/
    * プロジェクトディレクトリ
* \_\_init\_\_.py
    * mysiteディレクトリをPythonモジュールとして扱うように指定する空ファイル
* asgi.py
    * ASGI(Asynchronous Server Gateway Interface) 非同期のWebサーバーとアプリケーションとして実行するための設定です。
* wsgi.py
    * WSGI(Web Server Gateway Interface)アプリケーションとして実行するための設定です。
* settings.py
    * プロジェクトの設定です。デフォルトでは、SQLite3データベースを使用するという基本的な設定と、一般的なDjangoアプリケーションが使用するINSTALLED_APPSのリストが含まれています。
* urls.py
    * URLパターンの定義

続いてデータベースマイグレーションを行います。これで初期アプリケーション用のテーブルをデータベースに作成します。

```shell
cd mysite
python manage.py migrate
```

Djangoには軽量なWebサーバが付属していて、コードを素早く実行することができます。

```shell
python manage.py runserver
```

http://127.0.0.1:8000/ をブラウザで開き、プロジェクトが正常に実行されているページを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/d59443b4-5be6-784a-8aa4-e238399fe650.png)

実行コマンドで、カスタムなホストやポートの指定や、特定の設定ファイルを読み込ませることが可能です。

```shell
python manage.py runserver 127.0.0.1:8001 \--settings=mysite.settings
```

Djangoの開発サーバを実行すると、コードの変更をチェックし続けます。リロードは自動的に行われます。

## アプリケーションの作成

以下のコマンドを実行します。

```shell
python manage.py startapp blog
```

アプリケーションの構造が生成されます。

```text
blog/
    migrations/
        __init__.py
    __init__.py
    admin.py
    apps.py
    models.py
    tests.py
    views.py
```

* migrations/
    * アプリケーションのデータベースマイグレーション
* admin.py
    * Django管理サイトにモデルを登録できます。管理サイトの利用はオプションです。
* apps.py
    * アプリケーションの設定
* models.py
    * アプリケーションのデータモデル
* tests.py
    * アプリケーションのテスト
* views.py
    * アプリケーションのロジックで、各ビューはHTTPリクエストを受け取り、それを処理してレスポンスを返します。

以上でWebサービスの枠を作ってみました。
AWS実務ほぼなしでAWS資格のプロフェッショナル(SAP)を受けて※落ちた話※

#きっかけ
__※注意　落ちた話です__
一昨年AWS Solutions Architect Professional (SAP-C01)を受けてあまり勉強できず落ちました。 
2カ月前くらいにAWSのネットワーク専門知識に合格して
この勢いとネットワークの問題は答えられるからアドバンテージあるなと思って受けたら2回目も落ちました。。
ショックでお酒を飲みまくって、後日二日酔いで嗚咽を吐く悲しきモンスター(私)を生まれないためにも
内容をまとめたいと思います。。

#言いたいこと
__問題と答えを覚えて内容を理解したつもりで受かる気になっていないか？__
これに尽きます。
問題の正答率がよくてもこれに当てはまる場合は受けないことをお勧めします。
私は評価期間もあり、ダメ元で受けましたが余裕を持って受けたほうがよいです。
※とはいえモチベ上がらないとかありますが外的要因を作って無理やり上げましょう。

#絶望したこと
当日試験を受けた際に開始10分で知ってる問題が出てこなく、絶望し、心が折れました。。
6-7割初見でほぼ「これかな？」で答えを選ぶ感じになりました。
落ちたと思って気持ち的にも見直しできませんでした。。

#結果
思ったより点数が取れていました。。
ちゃんと見直ししてれば10%くらいの確立で合格していたかもしれません。。
みなさんも心折られても見直しをすることをお勧めします！！

|![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596030/9fe1f76c-79b7-ec6a-12aa-7bfd9a2d22cd.png)
|:--|

#AWSの知識
AWS実務はAMIの作成・EC2リストアを6日くらい実施。
SAAは3年前に取得していて個人的にEC2作成～PCからSSH接続までを何十回か実施した程度。
SAPはどこかのサイトの問題集を300問くらい2周して受けた結果、玉砕。
上記に前回勉強したAWSネットワーク専門知識の勉強を実施。
https://qiita.com/siberiannhasuki_iijima/items/92e370eb3c76f1d09091

#勉強した期間
1カ月前に試験日を決め、結果として1カ月半の勉強期間となりました。
ただ前回の勉強しきった余韻があり、今回はなかなか勉強が進まなかったです。。
文章が長く難しいのもあるのですが問題集をいったりきたりしていました。

#実施した勉強
・最初の週から半月くらいQiitaやGoogle先生でANSに関連する情報を調べてなんとなく出題範囲などを理解。
・公式のサンプル問題を3周。
　https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-pro/AWS-Certified-Solutions-Architect-Professional_Sample-Questions.pdf
・1カ月前からKoiwaClubに登録して問題を実施し始める。
　https://aws.koiwaclub.com/exam/ans/
　試験の進め方は#1～5まで実施したら、また#1からやり直し、それを繰り返す形で#1～25は実質2～3周した。
　#25以降は時間が無く、2周目を間違えた問題だけ繰り返して確認した程度。
　この時点で正答率7-8割だったので受験した。
・BlackBeltをKoiwaClubの途中で計1回確認。
　KoiwaClubで出てくる問題で見てなかったものを一通り確認。（30個以上タブ開きました。。）
　https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/

#本番
試験当日のギリギリまでKoiwaClubを実施していて余裕がありませんでした。。
見直しフラグもほとんどの問題につき、結果不合格となりました。。
運が悪かったのですが感覚としてKoiwaClubでやっていた問題は2-3割程度だったのかなと思います。
KoiwaClubで不正解だったものを最初はURLまで見ていたりしていましたが途中時間がなく、おざなりになってしまいました。。
思ったより点数が取れていたものの確信的に答えられた問題が1-2割でした。

#終わりに
今回は本番でショックを受けてしまいましたが、やはり見直しは大事なのかなと思いました。。
あと余裕を持って試験を受けることをお勧めします！
次回はしっかり勉強して合格記を書ければと思います！
LINE WORKS を利用できる Android スマートフォンを Google Workspace で制限する

Google Workspace で、LINE WORKS の外部 MDM 連携機能の設定を行いました。
## Google 管理コンソールの設定
Google 管理コンソールで、[アプリ]-[ウェブアプリとモバイルアプリ] にアクセスします。
![l_1517737_1142_1627890415848.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/9568750c-3d93-9aa9-9c50-2887a8771c16.png)
[アプリを追加] で [アプリを検索] をクリックします。
![l_1517737_1143_1627890759048.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/305fda6e-42e9-c866-2b07-a2778e60498f.png)
"LINE WORKS" を検索し、Android 版の LINE WORKS を選択します。
![l_1517737_1144_1627890840849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/2918fd7f-8b3b-52e6-2751-a362cd171d7c.png)
[ユーザー アクセス] と [アクセス方法] は任意の設定を行ってください。
[管理対象の設定] で、"設定名" に任意の名前、"LINE WORKS" に LINE WORKS の管理画面で設定した key value を入力します。
![l_1517737_1145_1627895835987.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396107/39f73ab8-5faf-98af-c83a-2b91c9147110.png)
以上の設定で、Google Workspace のアカウントで、自動インストールされる LINE WORKS アプリ、または仕事用プロファイルの Play ストアからインストールした LINE WORKS アプリからに限って自社の LINE WORKS へのアクセスを制限することができます。
LaravelでArtisanコマンド（コマンドライン（Command））処理のテストを書く

### 経緯
・ Laravelにて、バッチ処理を書くにあたって、Commandで実装してgithub actionsで定期実行する形にしようと考えてバッチ処理実装
・ テスト書いてないとかお前それ t_wadaの前でも。。。があるので、テストももちろん書く！
・ マニュアルにあるように
https://readouble.com/laravel/8.x/ja/console-tests.html

```php
$this->artisan('testBatch')
     ->expectsOutput('batch complete')
     ->assertExitCode(0);
```
と書く。

・ おーいけてるいけてる。じゃあDBの値の変更結果も確認しよう。

```php
$this->artisan('testBatch')
     ->expectsOutput('batch complete')
     ->assertExitCode(0);

$this->assertEquals(Hoge::count(), 1);
```

```
FAILURES!
```
testBatchの中で1行レコードが追加されるはずなのに何で！？！？！？

## 結論
`run()`で処理を明示的に実行させないとダメだった。

修正後

```php
$this->artisan('testBatch')
     ->expectsOutput('batch complete')
     ->assertExitCode(0)
     ->run();

$this->assertEquals(Hoge::count(), 1);
```

`run()`の記述が無い場合、プログラムの最後で`run()`が実行されるようで、command処理実行後の値を取得、アサーションする場合は明示的に`run()`を呼び出す必要があるみたい。

#### 参考
https://laravel.com/api/8.x/Illuminate/Testing/PendingCommand.html

・PendingCommandの`__destruct()`で`run()`が実行される。
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Testing/PendingCommand.php#L361

・`execute()`は`run()`のエイリアス
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Testing/PendingCommand.php#L200
# 【チュートリアル】PrimeHubでMLflowに実験をトラッキング

## はじめに

本文はPrimeHub CEで簡単にMLflowをインストールし、NotebookでMLflowに実行された実験をトラッキングするチュートリアルです。

### MLflow は

>MLflow is an open source platform to manage the ML lifecycle, including experimentation, reproducibility, deployment, and a central model registry.

#### コンポーネント

+ MLflow Tracking 実験のトラッキング
  
+ MLflow Projects 共有と再利用可能なプロジェクトパッケージング
  
+ MLflow Models 多様なデプロイツールをサポートするモデルパッケージングフォーマット
  
+ Model Registry モデル登録、モデルバージョン管理、モデルステージ推移、モデルライフサイクル管理


>本文記載時点はPrimeHub CE v3.6とMLflower v1.9.1を参考にしています。

## 実行環境

+ PrimeHub CE v3.6 (参考：[AWS EC2のインスタンスにPrimeHub CEをインストール](https://qiita.com/GabxInfuseAI/items/6fed00e440a89c34d1c0))

+ [PrimeHub Github リポジトリ](https://github.com/InfuseAI/primehub)

### 事前準備

+ [app_tutorial_mlflow_demo_notebook.ipynb](https://docs.primehub.io/docs/assets/app_tutorial_mlflow_demo_notebook.ipynb)サンプルファイルをダウンロードする


## 1. インスタンスタイプを追加

>注意点：計算リソース充分の場合は、このステップは必要はないです。計算リソース不足の場合はインスタンスを起動失敗する可能性があります。

ステップ：`Admin Portal`▶️`Instance Types`▶️`+ Add`

`0.5CPU/1GB MEMORY`設定し、`phuser`グループにオーナーを指定し、下参照にインスタンスタイプを追加する

![Kapture-create-tiny-instance.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/50dba506-6fe1-8a9b-ae01-b2beb4056e9c.gif)


## 2.MLflowアプリを作成

ステップ：`Apps`▶️`+ Applications`▶️`MLflow`▶️`+ Install to PrimeHub`

前ステップで追加した`cpu-0.5`インスタンスタイプを配置し、下参照にMLflowアプリを作成する

>注意点：Service Unavailableが出た場合は、数秒後ブラウザをリロードしてください。

![Kapture-mlflow-install.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/3b7ad58f-172c-6d10-10f1-8e6e716d3dfe.gif)



## 3.Notebookを起動

ステップ：
+ `Home`▶️`Open Jupyter Notebook`▶️`Start` 又は
+ `Notebooks`️▶️`Start`

`CPU 1`インスタンスタイプを配置し、`TensorFlow 2.4.1 (Python 3.7)`イメージを指定し、下参照にNotebookを起動する

![Kapture-launch-notebook.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/4d659437-74e0-3723-9c68-7308f7d4cb8a.gif)


## 4.サンプルファイルをドラッグ＆ドロップ

ローカルからNotebookへ`app_tutorial_mlflow_demo_notebook.ipynb`をドラッグ＆ドロップしてアップロードする。

![Kapture-notebook-upload.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/951c61f6-79c4-c5c0-2413-7d2bfabe6d62.gif)


## 5.MLflow Tracking URLを設定

四つ目セルにダミーのMLflow Tracking URIテキストが表示されるが、`http://app-mlflow-32adp`を実際に作成したMLflowアプリの`Service Endpoints`に書き変える

```py
mlflow.set_tracking_uri("<Service Endpoints>:5000/")
```

![Kapture-replace-endpoint.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/5b8da296-796b-6287-677e-668d13be136d.gif)


## 6.サンプルコードを実行

`Run All Cells`を実行し、全て終わったら`internal-experiment`実験をMLflowに登録してトラッキングする。

![Kapture-run-cells-check-mlflow.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/ddea40e5-3932-04f0-e09a-c747649da94d.gif)



## 参考

+ [MLflow 公式サイト](https://mlflow.org/)

+ [PrimeHub CE 紹介〜チーム向け機械学習プロジェクトとリソース管理が楽になる](https://qiita.com/GabxInfuseAI/items/b0a24c058f3d31f66a6f)
【Laravel】Routingがあっているはずなのに404となった場合の対処法

# 概要
ブランチ等を切り替えているうちに、Routing登録済みのページで404となる現象が発生したためその時の対処法を記録

## 開発環境
Docker
PHP 8.0.8
Laravel 8.32.1

## 対処法

正しいroutingが登録されていない可能性があるため、下記の手順で確認&修正します。

- 1. 　　登録されているroutingを確認

```
php artisan route:list
```

- 2. 404が出るページのrouting登録が１のリストで表示されない（または正しいものでない)場合、cacheを削除

```
php artisan route:clear
```

- 3. 再度1のコマンドを打ち、正しいroutingとなったことを確認して該当ページの表示確認を実施
C言語のコンパイル処理過程について

#はじめに

　FORTRAN、C、Java、Pascalなどのコンパイル言語で必要となるコンパイルによる機械語への変換処理。普段何気なく使っているコンパイルが何をしているのか、今回はC言語のコンパイルの処理過程について紹介する。

#コンパイルとは
コンパイルとは、人間が読み書きできる状態のSource codeを、コンピューターの実行可能なBinary(Object) codeに変換すること。Binary codeを10進数の世界で生きている人間が理解し記述するのは難しいので、一度人間でも扱える文字で書き、それを変換プログラムで機械後に変換し、CPUで直接処理可能な状態にする。


#具体的な処理
一般的なC言語のコンパイルは以下の処理が順に行われている。

1. プリプロセッサ
1. コンパイル
1. リンク

####1. プリプロセッサ cpp
 プロプロセッサはコンパイルの最初の処理で、ソースコードに記述したヘッダーファイル(.h)やマクロを挿入して、ソースファイルに展開する。またコメントなどを削除してソースファイルを簡潔にする。
例として下記のように記述されたヘッダーファイルを集めてソースコードに展開する。

```cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <cmath>
#include <ctime>
#include <math.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <cstdio>
```

####2. コンパイル
コンパイルは実際にソースコードを機械語に変換する処理。

 - 字句解析(Lexical Analyzer)
識別子、定数、演算子、カンマや括弧などの区切り記号等をトークンと呼ばれるものに分ける。<br>
```for(i==0,i<10,I++){``` => ```for```、```(```、```i```、```==```、```0```、```,```、```i```、```<```、```10```、```,```、```I```、```++```、```)```、```{```

 - 構文解析(Syntax Analyzer)
字句解析で識別したトークンを、まとまりのある構文に分ける。
for
┣== ```i```,```0```
┣<```i```,```10```
┣++```i```

 - 中間コード生成(Intermediate Code Generation)
複数の構文で一連の単純な命令を作る。

 - 最適化(Optimization)
処理速度をあげるため、プログラムのコードサイズを小さくして効率化する。
<font size='0.5'>※最適化によりコードが飛ばされ予期せぬ動きをすることがあるため、最適化オプションを無効化したりする。</font>

 - コード生成(Code Generation)
構造ごとに使用する命令や実行順序、またレジスタの割り当てなどを確定して機械語に変換する。

それぞれのフェーズでは並行してテーブルマネージメントとエラーハンドリングが行われている。

 - テーブルマネージメント
トークンや構文の情報を保持する。

 - エラーハンドリング
各フェーズで字句誤りや構文の間違いをチェックする。

####3. リンク
既にコンパイルされたオブジェクトファイル(.o)を結合して実行形式ファイルを生成する処理。
C言語でいうところの静的リンクライブラリ(.a)や動的リンクライブラリ(.dll/.so)。

#まとめ
コンパイルの処理過程を簡単にまとめた。もし間違いなどあれば、編集リクエストを出して頂くと嬉しいです。
Path Intellisenseでnext.jsのファイルパス保管が効くようにする

next.jsで下記のように絶対パスでimportできるようになったのですが、VSCodeの初期設定だとファイルパスを保管してくれません…

```javascript
import React from 'react';
import CustomAppBar from '/components/uiParts/CustomAppBar';

```

## 設定方法
Path Intellisenseをインストール後、
jsconfig.jsonをおいて、paths設定してあげるとPath Intellisenseでも保管ができるようになります。


```json:jsconfig.json
{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "/*": [
                "./*"
            ]
        }
    }
}
```

### VSCode拡張
Path Intellisense - Visual Studio Marketplace
https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense

## こんなかんじ
![スクリーンショット 2021-08-02 16.08.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3442/8b348bb2-9b72-740a-2403-d1ca9601fc39.png)
【SQL】カンマ区切りでwhere検索

```SQL
        SELECT
            id,
            name   
        FROM Table_date
        WHERE id IN (22,45,75)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/454cdb8f-a17b-aab7-eeb6-023f53c0ebf2.png)

##参考

https://www.relief.jp/docs/003380.html
[Rails] オリジナルの管理者機能を作る 管理者画面編 

# はじめに
Railsで管理者機能をつけるならrails_admin、active_admin、Administrateといった便利なgemを使うのが一般的だと思いますが、
今回はgemを使わず自分の欲しい機能だけの1から自作したオリジナルの管理者機能を作っていこうと思います！


#目標
今回は管理者だけがアクセスできる管理者画面を作っていきます。


#実装
まず前提としてdeviseによるログイン機能が既に実装されていることとします。
流れとしては、
1. Userテーブルにbooleanで一般ユーザーと管理者ユーザーの区別をつけるためのカラムを追加する。
2. seedファイルを使って管理者ユーザーを作成
3. routesに管理者ユーザー用のルートを追加
4. 管理者ユーザー用のController、viewを作成
5. 一般ユーザーが管理者ページにアクセスできないようにする。

こんな感じです。
それでは行こう！

## 1.カラムの追加
まずは、一般ユーザーか管理者ユーザーかを判断するためのカラムをdeviseによって追加されたUserテーブルに追加していきます。


```ruby:ターミナル
rails g migration add_administrator_to_users admin:boolean
```

booleanを追加したいので作成されたmigrationファイルにdefault値を設定します。

```ruby:db/migrate/20210625043921_add_administrator_to_users.rb
add_column :users, :administrator, :boolean, default: false
```

```ruby:ターミナル 
rails db:migrate
```

## 2.seeds.rbで管理者ユーザーの作成
seedファイルで管理者ユーザーを作成します。

```ruby:db/seed.rb
User.create!(email: "email",
            password: "password",
            password_confirmation: "password",
            administrator: true)
```
Userテーブルにnameカラムを追加している場合はnameカラムも記入してください。
ここで大事なのはboolean値の値をtrueにしていることです。

```ruby:ターミナル 
rails db:seed
```

## 3. routesにadmin用のルートを追加

うっかり管理者ページを公開してたなんてことにならないように`namespase`を使ってしっかり区別しておきましょう。

```ruby:config/routes.rb
 namespace :administrator do
    resources :users, only: [:index]
  end
```
今回actionはindexだけにしていますがその辺は自分の用途に合わせてください。

## 4. admin用のController、viewを作成
namespace部分を忘れずに！

```ruby:administrator/users_controller.rb

class Administrator::UsersDataController < ApplicationController
  def index
  end
end

```

viewを追加して表示させます。

```ruby:administrator/users/index.html.haml
%h1 管理者専用画面
```

5. 一般ユーザーが管理者ページにアクセスできないようにする。
最後に管理者のみアクセスできるようControllerに制限をかけていきます。


```ruby:administrator/users_controller.rb
class Administrator::UsersDataController < ApplicationController
  before_action :admin_user
  def index
  end
  
  private
    def admin_user
      redirect_to(root_url) unless current_user.administrator?
    end
end
```

Userテーブルに設定した`administrator`がfalse
つまり一般ユーザーが管理者ページにアクセスしようとすると`root_path`にリダイレクトされるようになってます。

これで完成！

#　おまけ
管理者ユーザーがログイン後管理者ページにそのままリダイレクトされるようにしたいなら以下を`application_controller`に追加してください

```ruby:application_controller.rb
class ApplicationController < ActionController::Base
  def after_sign_in_path_for(resource)
      if current_user.administrator?
        flash[:notice] = "管理者ユーザーとしてログインしました。"
        administrator_users_path
      else 
        root_path
      end
    end
end
```

これでログイン後一般ユーザーはトップページ、管理者ユーザーは今回作った管理者ページにリダイレクトされます。

# まとめ
Userカラムにbooleanを持たせるだけでgemなしでも簡単に追加できますね。
Linux（Mint）でのOpenCVセットアップ

私はは頻繁に環境をリセットしています。
そのため、やや備忘録的な側面が強いです。
今回はLinux　Mint でのOpenCVとPythonの環境構築に関しての記事です。

今回の構築した環境も示しておきます。
lenovo thinkpad x240
cpu : intel core i5 4200u
mem : 4gb
ssd : 128gb


早速ここからが本題ですね
まずターミナルを起動します。

まずはPythonの環境構築を行います。
<H1>Python環境の設定</H1>
Pythoneのパッケージ管理システムをインストールします。

```
sudo apt install python3-pip
```
これを行うことでPython3用のパッケージ管理システムpipのインストールが完了します。
<H1>OpenCVのインストール</H1>
ここでは先程インストールしたpipを用いてOpenCVをインストールを行います。

```
 sudo pip3 install opencv-python 
 sudo pip3 install opencv-contrib-python 
```
ここで問題ながければOpenCV自体のインストールは完了です。
<H1>NumPy</H1>
ここまでインストールを行ったついでにどうせ使うので機械学習などでよく使われているNumPyをインストールしておきましょう。

```
 pip3 install numpy 
```

<H1>確認</H1>
ここまで問題がなければいいのですが念の為確認も行いましょう。

ターミナル上で

```
python3
```
を入力してください

そうするとPytonのインタプリタが起動し入力ができるようになるはずです。
そこで

```
>> import cv2
>> cv2.__version__
```

問題がなければここでインポートエラーがなくバージョン情報が表示されるはずです。
もしここまででエラーが発生した場合はPipのアップデートなどを行い再度コマンドを入力してみてください

<H1>最後に</H1>
ではでは拙い文章ですが見ていただいてありがとうございます。
またどこかでお会いしましょう。
バイバイ！！
【toio.js】toio.jsの公式のサンプルをWindowsで動かす方法

#必要なもの
　Windowsで動かす場合にはBluetooth4.0に対応したアダプタが必要になる。私はAmazonで[Bluetooth USBアダプタ](https://www.amazon.co.jp/dp/B00J84V7OM)を購入した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/c94f1929-be61-4f11-d5a1-32cc337ab23f.png)


##事前にインストールするもの

##1. python
　https://www.python.org/ からpythonをインストールする。このときに<b>Add Python 3.x to PATH</b>を必ずインストールする。

##2. Zading
　Zadingを使って汎用USBドライバーをインストールする。https://zadig.akeo.ie/ からインストールする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/b9566f60-9aa8-d17a-47fc-b6301aa41674.png)

#手順

##1. Zading Toolで汎用USBドライバーの適用をする
　インストールした`zading-2.5.exe`を起動する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/4847d253-a6f7-4f79-b765-65548304cbd6.png)


　`options`から`List All Devices`を選択する。`Reinstall Driver`をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/7b038c88-9edc-c07e-1283-448366fb8964.png)

　`successfully`と出たら完了。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/7639d40b-1b07-5f0d-58a0-3a9936857f90.png)


##2. toio.jsを動かす
##2-1. toio.jsの公式サンプルをクローンする
　(gitが入っていない場合はzipでダウンロードする)

```:ターミナル
git clone https://github.com/toio/toio.js.git
```

##2-2. node-bluetooth-hci-socketをダウンロードする
　toio.jsの中でnode-bluetooth-hci-socketをダウンロードする。

```:ターミナル
cd toio.js
git clone https://github.com/noble/node-bluetooth-hci-socket.git
npm install bluetooth-hci-socket
```

##2-3. 実行する
　toioCubeの電源を入れて、パソコンのBluetoothをオンにしてサンプルを実行する。

```:ターミナル
yarn install
yarn build
yarn example:id-reader // マットのidを取得する
yarn example:keyboard-control // キーボードでcubeを操作する
yarn example:chase // 1つのcubeをもう1つのcubeが追いかける
```
serverless-framework + serverless-http + express で、画像バイナリをダウンロードする


画像をバイナリとして返す
serverless-http生成時、binaryのmimeを設定する

``` handler.ts
app.get("/hoge", (req, res, next) => {
  res.setHeader("Content-Type", "image/png");
  res.send(img);
});

import serverless from "serverless-http";
const binaryMimeTypes = ["application/pdf", "image/*"];
export const main = serverless(app, { binary: binaryMimeTypes });
```

api-gatewayのbinaryMediaTypesへ、image/*を設定する
chromeからはimage/*で来るので、image/pngとかだとうまく動かなかった

```serverless.yml
provider:
  apiGateway:
    binaryMediaTypes:
      - "image/*"
      - "application/pdf"
```

参考

https://qiita.com/rithmety/items/c10386c0fb059a1044a5
Gtk3アプリ iniファイルの操作

###Gtk3アプリ iniファイルの操作


####NugetからINIFileParserDotNetCoreをインストール

```
Install-Package INIFileParserDotNetCore 
```

####使用例

```cs
 IniFile IniFile1 = new IniFile("test.ini");
 IniFile1["aaa","aaaa"] = "aaaa";
 Console.WriteLine(IniFile1["aaa","aaaa"]);
```
####ソース

```cs
using System;
using IniParser;
using IniParser.Model;

/*
 * iniFileParse
 * 
*/

public class IniFile
{
    private string iniFileName = null;
    private FileIniDataParser parser = null;
    private IniData data = null;
    
    public IniFile(string filePath) {
        
        parser = new FileIniDataParser();
        iniFileName = filePath;
        
        try{
            data = parser.ReadFile(iniFileName);
        }
        catch (Exception e)
        {
            if (data == null)
            {
                data = new IniData();
                parser.WriteFile(iniFileName, data);
            }
        }

    }

    public string this[string section,string key] {
        set
        {
            try
            {
                data[section][key] = value;
                parser.WriteFile(iniFileName, data);
            }
            catch (Exception e)
            {
              Console.WriteLine(e.Message);
            }            
        }
        get {
            try
            {
                return data[section][key];
            }
            catch (Exception e)
            {
              Console.WriteLine(e.Message);
            }
        }
    }
}
```

[Gtk３アプリ Dapperのアンダーバーの修正](https://qiita.com/iota_11/items/e701aab0d8188fc1c357)に続く
CodeDeployを使ってみた

## 初めに

Lambdaのデプロイが上手くいかないのでQiitaに書きながら頑張ることにした

## 用語

### Blue/Green Deploy

> Blue/Greenデプロイとは？
> 現在稼働している環境と別にもう1つ稼働環境を作成し、ロードバランサー等のルーティングを新環境に向けるデプロイ方法です。
> 常にリクエストを受けている稼働中のサーバを置き換えるよりも安全にデプロイ可能なのがメリットになります。

https://qiita.com/keitakn/items/6abe6c971e4dec3b69ef

### アプリケーション

### デプロイグループ

デプロイのメイン設定となるもの。

### サービスロール

CodeDeployで利用するロールのこと。

### デプロイ設定

色々あるけど、単に利用するだけなら何でも良い気がする。

### リビジョン

デプロイするファイルがある場所だと思う。
S3においていたら、S3のARNを記載する。

### appspec.yml

CodeBuildのBuildspec.ymlのように、CodeDeployにはAppspec.ymlがあるようだ。
同様にソースコードのトップに置いておく必要がある。

## Error

S3へフルアクセスしているのに以下のエラーが出て詰まっている。

```
The IAM role arn:aws:iam::xxx:role/xxx does not give you permission 
to perform operations in the following AWS service: Amazon S3. 
Contact your AWS administrator if you need help. 
If you are an AWS administrator, you can grant permissions 
to your users or groups by creating IAM policies.
```

権限周りは以下の通り。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56144/2a87288a-9612-b1bc-82d1-ecc99286e085.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56144/de87a722-fcbe-763e-5751-c9abf47047a5.png)
ECS ＋ Fargate構成でECS Execを使おうとしたらハマったポイント

# ECS Execとは
今までFargateで動いているコンテナの中に入りたい場合、AWS System managerを使ってアクティベートコードを取得して、Dockerfileに書いてなどをする必要があった。ちょっとめんどくさい。
https://qiita.com/pocari/items/3f3d77c80893f9f1e132

それを簡単に出来るようになったのがECS Execということみたい。
docker execコマンドみたいな感じ。つまりコンテナの中に入れる。
https://aws.amazon.com/jp/blogs/news/new-using-amazon-ecs-exec-access-your-containers-fargate-ec2/

# ECS Execを使うには
[こちら](https://tech.smartcamp.co.jp/entry/try-amazon-ecs-exec)が参考になりました！ありがとうございます。
ざっくりまとめると、
- ECSタスクロールの作成
- enableExecuteCommandを有効化(タスク起動時)
- AWS CLIを実行するアカウントにexecute-commandを実行できるIAMポリシーを付ける
- AWS CLI 用の Session Manager プラグインをインストールする
- AWS CLIの2.1.31以降のバージョンを使う
- ssmmessagesのVPCエンドポイント(プライベートリンク)を作る <font color="Red">←ここでハマった</font>

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/ecs-exec.html

# ハマったポイント
ECSタスクロールを作ったり、AWS CLIにSession Manager プラグインを入れるのは問題なかったのですが、

```
aws ecs execute-command --cluster [クラスター名] \
    --task [タスクID] \
    --container [コンテナ名] \
    --interactive \
    --command "/bin/sh"
```
としても一向に入れない。。

```
An error occurred (TargetNotConnectedException) when calling the ExecuteCommand operation: The execute command failed due to an internal error. Try again later.
```
```TargetNotConnectedException ``` と怒られる。。色々設定変えたり試行錯誤するも変わらず。。

```
aws ecs describe-tasks \
    --cluster [クラスター名] \
    --tasks [タスクID]
```
と打って状態を確認すると、

```
...
"managedAgents": [
    {
        "lastStartedAt": "2021-08-02T10:24:54.476000+09:00",
        "name": "ExecuteCommandAgent",
        "lastStatus": "RUNNING"
    }
],
...
"enableExecuteCommand": true,
...
```

どうやらエージェントはしっかり動いている様子。じゃあなぜ入れないのだ。。

## 詰まったらこれ使おう Amazon ECS Exec Checker
[公式の英語ドキュメント](https://docs.amazonaws.cn/en_us/AmazonECS/latest/developerguide/ecs-exec.html#ecs-exec-troubleshooting) で見つけたのですが、Amazon ECS Exec Checkerというものがあるらしい。

```bash
# git cloneする
git clone https://github.com/aws-containers/amazon-ecs-exec-checker.git
# jqコマンド入れる(入ってる人は不要)
brew install jq
./check-ecs-exec.sh [クラスター名] [タスクID]
```
これで設定が間違っているところないかチェックしてくれます。便利。
そうするとヒントが見えてきました。

```
SSM PrivateLink "com.amazonaws.ap-northeast-1.ssmmessages" not found. You must ensure your task has proper outbound internet connectivity.
```
ssmmessagesのVPCエンドポイント(プライベートリンク)が見つからないと言っている。
おや？これか？
ssmのVPCエンドポイント(プライベートリンク)は作ってあったので、完全に盲点でした。
試しにssmmessagesのVPCエンドポイント(プライベートリンク)を作る。

再度実行すると、コンテナに入れました！
ssmmessagesのVPCエンドポイント(プライベートリンク)も必須なんですね。
Fargateは難しいと思いつつ、また一つ勉強になりました。
[小ネタ]AmazonLinux2 PHP8にphpredisを入れる

#PHP8 on AmazonLinux2 一発でphp-redisが入らない(2021/08/1現在)ので調べてみた。

##前提として
amazon-linux-extrasでPHP8をインストール済み
Nginx + PHP-FPM + Laravel

*peclでインストールするらしいので、Pearをインストール*
`sudo yum install php-pear`

peclでインストール
`sudo pecl install redis`

*ビルドエラーが起きるので、php-develとgccをインストール*
`sudo yum install gcc`
`sudo yum install php-devel`

*php.iniに追加*
`echo "extension=redis.so" > /etc/php.d/redis.ini`

*php-fpmを再起動*
`systemctl restart php-fpm`

*Laravelの場合*
.envに追加

`SESSION_DRIVER=redis`
`SESSION_LIFETIME=120`
`MEMCACHED_HOST=ygd-dev.u2ark4.ng.0001.apne1.cache.amazonaws.com`
`REDIS_HOST=ygd-dev.u2ark4.ng.0001.apne1.cache.amazonaws.com`
`REDIS_PASSWORD=null`
`REDIS_PORT=6379`

とりあえず、setとgetするだけサンプル
```
use Illuminate\Support\Facades\Redis;
Redis::set('name', 'Taylor:'.date('Y-m-d H:i:s'));
echo "Name = ".Redis::get('name')."\n";
```
CodeBuildを使ってみた

## 初めに

業務で利用しているので簡単にまとめてみた

## 前提

CodeCommitでソースコードをアップロード済み

## 概要

プロジェクト名はコンソールから変更できないので注意。


基本的には以下の流れ。

1. ソースコードのトップにbuildspec.ymlファイルを作成
1. その中に設定を書き込んでソースコードをzip化
1. S3にzip化したファイルをアップロード

注意することは、S3にアップロードする際の権限くらい
CodeBuildにロールを付与するときに、S3FullAccessを付けておくと良い

## buildspec.yml

YAMLファイルの名称はオプションで変更することが可能。（オプショナル）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56144/eb97b46e-5fa0-d8f9-cea0-ed483e787b9d.png)

### サンプルファイル

以下は、Python前提としたテンプレ。

1. その中に設定を書き込んでソースコードをzip化
1. S3にzip化したファイルをアップロード

```yaml
version: 0.2
phases:
  install:
    runtime-versions:
      python: 3.8
  build:
    commands:
      - zip -r xxx.zip ./
      - aws s3 cp xxx.zip s3://xxx/
```

version: 0.2は最新バージョンでおまじないと思えば良い。

### Reference

公式リファレンス
[Build specification reference for CodeBuild](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html)
xserverのgitを最新化したけど、ssh経由の操作しかできない。

# 問題

Xserver上でGitを使いたいが、ちょっと、古いので、最新のバージョンを利用したい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133291/0e095195-ea8b-8a3f-a198-40d838f47587.png)


2024/01/31 追記

Xserverが対応してくださったようで、HTTPSでのCloneができるようになりました！
自前で、Gitをビルドしなくてよくなった！
嬉しい！

![2024-01-31_10h31_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133291/cc5446d1-7e2c-ca79-c5ba-f026650f5b7a.png)




# TL;DR

OpenSSLまでリビルドする必要があるので、バージョンアップは諦めるかな。。。

同じく、HomeBrew(LinuxBrew)を入れてみたけど、GitとCurlのバージョンが古いのでこちらもインストールにコケたりする。

この辺、Xserverの運営者のギリギリのラインになるのかな？って思いました。

# 作業内容

こちらの記事を参考にさせていただいて作業を行う。

[Xserverへgitの最新版をインストールする](https://qiita.com/y-ngi/items/7a170a19d809d2f49a15)

こんな感じでgitのバージョンアップをしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133291/782d06c1-bf86-25d2-4aaf-628f03785980.png)

git cloneをしようと思うと、``https``が使えなくてエラーとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133291/617f5415-dd3d-583b-c7ee-4f2ddb9a5c5e.png)

```bash
[hirotae@ git-2.32.0]$ ./git --version
git version 2.32.0
[hirotae@ git-2.32.0]$ ./git clone https://github.com/surmon-china/vue-quill-editor.git
Cloning into 'vue-quill-editor'...
fatal: unable to access 'https://github.com/surmon-china/vue-quill-editor.git/': Protocol https not supported or disabled in libcurl
```

libcurlでSSLが使えないのが問題。

curlをリビルドすることになるけど、今度は、OpenSSLがないと言い出す。。。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133291/5b06c3ad-497b-7762-d90b-0f723cf7b6f3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133291/57b8260a-4e74-29ad-9546-4cc122800da2.png)


```bash
./configure --with-openssl --prefix=$HOME/local

・・・

checking for HMAC_Update in -lcrypto... no
checking for HMAC_Init_ex in -lcrypto... no
checking OpenSSL linking with -ldl... no
checking OpenSSL linking with -ldl and -lpthread... no
configure: OPT_OPENSSL: yes
configure: OPENSSL_ENABLED:
configure: error: --with-openssl was given but OpenSSL could not be detected
```

OpenSSLを入れるところになるので、Gitのアップデートは諦めた方がいいかな？

https://teratail.com/questions/191732
メモ C++ LPTSTRをcharへ、charをwchar_tへ、文字コード変換


## 引用元

Convert lptstr to char*
https://stackoverflow.com/questions/342772/convert-lptstr-to-char

## 引用元のコード

CP_ACPはSJIS

```WinNIs.h
#define CP_ACP                    0           // default to ANSI code page
#define CP_UTF8                   65001       // UTF-8 translation
```

```Sample.cpp
#include <windows.h>

/* string consisting of several Asian characters */
LPTSTR wcsString = L"\u9580\u961c\u9640\u963f\u963b\u9644";
//LPTSTR wcsString = L"OnlyAsciiCharacters";

char* encode(const wchar_t* wstr, unsigned int codePage)
{
    int sizeNeeded = WideCharToMultiByte(codePage, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* encodedStr = new char[sizeNeeded];
    WideCharToMultiByte(codePage, 0, wstr, -1, encodedStr, sizeNeeded, NULL, NULL);
    return encodedStr;
}

wchar_t* decode(const char* encodedStr, unsigned int codePage)
{
   int sizeNeeded = MultiByteToWideChar(codePage, 0, encodedStr, -1, NULL, 0);
   wchar_t* decodedStr = new wchar_t[sizeNeeded ];
   MultiByteToWideChar(codePage, 0, encodedStr, -1, decodedStr, sizeNeeded );
   return decodedStr;
}

int main(int argc, char* argv[])
{
   char* str = encode(wcsString, CP_UTF8); //UTF-8 encoding
   wchar_t* wstr = decode(str, CP_UTF8);
   //If the wcsString is UTF-8 encodable, then this comparison will result to true.
   //(As i remember some of the Chinese dialects cannot be UTF-8 encoded 
   bool ok = memcmp(wstr, wcsString, sizeof(wchar_t) * wcslen(wcsString)) == 0; 
   delete str;
   delete wstr;

   str = encode(wcsString, 20127); //US-ASCII (7-bit) encoding
   wstr = decode(str, 20127);
   //If there were non-ascii characters existing on wcsString, 
   //we cannot return back, since some of the data is lost
   ok = memcmp(wstr, wcsString, sizeof(wchar_t) * wcslen(wcsString)) == 0; 
   delete str;
   delete wstr;
}
```
俺のLambdaがこんなに遅いわけがない

API Gateway + Lambda(Node.js) + MySQL(sequelize)の構成で、Lambdaの処理時間が2.5秒とだいぶ遅かったです。
その後色々手を加えて当初の32%の0.8秒にまで抑えることができたので対応内容をシェアします。

## メモリ量調整

定番です。
当初256MBでした。増やせば増やすほど早くなりそうな感じでしたが、コストとの折り合いを見て1024MBに変更しました。

これで平均2.1秒と0.4秒減。

## SSM Parameter Storeへの問い合わせを並列実行

コード内で４回Parameter Storeへ値を取得していたのですが、Promise.allを使って並列で取得するようにしました。
1回の値取得に50ミリ秒程度掛かっていたので、これで平均1.95秒と150ミリ秒減りました。

コードのイメージとしてはこんな感じです。

```js
    const [dbHost, dbName, dbUser, dbPass] = await Promise.all(
        [
            retrieveDbSetting('DB_HOST'),
            retrieveDbSetting('DB_DATABASE'),
            retrieveDbSetting('DB_USERNAME'),
            retrieveDbSetting('DB_PASSWORD')
        ]
    );
```

## DBコネクションプールのアイドル時間を待たずすぐにレスポンスを返す (ほぼこれのおかげ)

Sequelizeの設定でpoolというものがあります。
コネクションプーリングの設定なのですが、自分はこれを設定していました。

この時Lambda関数はreturnで処理を終了させていても、コネクションプーリングの待機時間中はLambda関数が終わらないという事になっていました。

解決策としてはコネクションプーリングを削除するか（試してはいませんが）、イベントループ終了を待たないという下記設定をLambdaに書けば大丈夫です。

```js
context.callbackWaitsForEmptyEventLoop = false;
```

## npmのdevDependencyをインストールしないようにする

時間の計測はしていなくて微々たるものだとは思いますが一応…。

普通に`npm install`するとdevDependencyもインストールされてしまいます。
これを防ぐには`npm install --production`とするか、環境変数として`NODE_ENV=production`を定義します。

今回は開発・ステージング・本番環境と同じやり方でパッケージを入れたかったので、後者の環境変数で切り替えました。
Dockerの「because server did not provide an image ID」エラー

# エラー

```
cannot write /var/folders/wn/20c5t0fj2qg6rv9pzdszv481km81hq/T/tmpszp7eu3d because server did not provide an image ID
```
というエラーが出てビルドに失敗する。

# 対策
- Dockerのメモリを増やす
    - Docker for MacならGUIから増やせる
- build時のcacheを削除する
    - `docker builder prune`コマンドで実行

# 参考URL
https://github.com/docker/cli/issues/2971
Lambdaで添付ファイル付きメールを送る

LambdaでNodemailerを使う機会があったのでメモを残します:pencil:

## Nodemailerとは

Node.jsで簡単にメールを送ることができるモジュールです。
公式 https://nodemailer.com/about/
npmのページ https://www.npmjs.com/package/nodemailer

## やりたいこと
S3に置いているPDFファイルを添付したメールを送信する

## 手順
1. メールアドレスの認証
1. 必要な権限を付与
1. ローカルでモジュールを準備
1. Lambdaのコンソール画面でzipをアップロード

#### 1. メールアドレスの認証

サンドボックス解除前のSESは、差出人や宛先に指定するメールアドレスの認証が必要です。

1. SES Homeを開く
1. Email Addresses > Verify a New Email Address
1. メールアドレスを入力
1. 「Amazon Web Services – Email Address Verification Request in region Asia Pacific (Tokyo)」というメールが届くのでメール内のリンクを踏む

#### 2. 必要な権限を付与

1. Lambdaの実行ロールの概要画面を開く
1. インラインポリシーの追加
1. SESのSendRawEmail、S3のGetObjectのアクセス許可を追加する

#### 3. ローカルでモジュールを準備

1. 適当なディレクトリを作成 `mkdir test`
1. 初期化 `npm init`
1. nodemailerインストール `npm install nodemailer`
1. test/node_modulesが作られていることを確認
1. test/index.jsを作成(中身はlambdaで動かしたいコード)
1. node_modulesとindex.jsをまとめてzip化

#### 4. Lambdaのコンソール画面でzipをアップロード

1. 関数の画面を開く
1. 「アップロード元」のリストから「.zipファイル」を選択
1. ローカルで作成したzipファイルを指定してアップロード

#### 今回使ったLambdaのコード
```js:index.js
const AWS = require('aws-sdk')
const nodemailer = require('nodemailer')
const transporter = nodemailer.createTransport({
  SES: new AWS.SES({ apiVersion: '2010-12-01' }),
})
const s3 = new AWS.S3({ apiVersion: '2006-03-01' })
const fs = require('fs').promises

exports.handler = async (event) => {
  //S3に置いているPDFを/tmp配下にコピー
  const paramsForS3 = {
    Bucket: 'バケット名',
    Key: 'ファイル名',
  }
  const contents = await s3.getObject(paramsForS3).promise()
  const path = '/tmp/ファイル名'
  await fs.writeFile(path, contents.Body)

  // メール送信
  await transporter.sendMail({
    from: '差出人のメールアドレス',
    to: '宛先のメールアドレス',
    subject: 'メールの件名',
    text: 'メール本文',
    attachments: [
      {
        filename: '添付ファイル名', //元のファイル名とは別の名前で添付したい場合はここで設定(非必須項目)
        path: path,
      },
    ],
  })
}

```
Laravelでログイン機能を入れる

# 1 アプリのバックアップをしておく
# 2 認証機能をインストールする
### 1 Laravel/ulパッケージをインストールする
```php:ターミナル
アプリ$composer require laravel/ui
```
### 2 パッケージを用いて認証機能を追加する
```php:ターミナル
アプリ$php artisan ui vue --auth
```
```php:ターミナル（結果）
アプリ$do you want~
```
*ここはyesにする！

#3.CSSを適用させる

```php:ターミナル
アプリ$npm run dev
```

→完成！
Django 外部からのアクセス許可方法

### 設定

```python:settings.py
# ALLOWED_HOSTS = [] # もとはこうなっている
ALLOWED_HOSTS = ['*']
```

※プロジェクト名と同じフォルダ内にsettings.pyがある。

### 起動

```console
python manage.py runserver 192.168.1.10:8000
```

※IPアドレスはサーバ起動しているPCまたはサーバのIPアドレス
[VRChat SDK3] Unityで着せ替えをする時、服のArmatureをどこに移動すればよいか解決したのでメモ

着せ替えArmature部分について記事を探したのですが全く見当たらず、一連の流れをライブコーディング（ライブクロージング？）してる動画でようやくわかったので文字に起こしてメモ
（VRC始めて3日とかなので単語とか適当です。正式な呼び名とかあったらぜひ教えてください）

アバターはミーシェちゃんで、服はBOOTHにあった無料のミーシェちゃん用のものを使わせていただいております。

# 1.

まず、服のArmatureフォルダを**Armatureフォルダ**ごとbodyのArmatureフォルダに入れる。

# 2.

移動した服のArmatureの中にあるオブジェクトについて、すでにbodyのArmature内にあるオブジェクトのフォルダ？と部分文字列が一致して**そう**（こことても重要）なのに入れる。
（1.とやってることは本質的には同じ）

これを再帰する。

# 3.

終わり。

# 最後に

最初、服のArmatureフォルダに中にあるものを階層を維持してそのままbodyのArmature直下に持ってくるのかと勘違いしていて思い通りにいきませんでした。（これによって服のArmatureフォルダやBodyフォルダを「中身が空だしいらんやろ！」と言って削除していたのですがヤバかったですね）
~~しかしオブジェクト名を目grepしてオブジェクトを移動してくってエンジニアリング的にどうなんですかね…~~

そのうち手が空いたら画像とかも入れてみます。VRCもUnityも超初心者なので何か間違ってたりしたらぜひツッコミください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835566/1dd87af1-751d-527b-23b5-39e5ec357445.png)

服がズレない感動がここにはあった。。。

# P.S.

> ~~しかしオブジェクト名を目grepしてオブジェクトを移動してくってエンジニアリング的にどうなんですかね…~~

山兔さんが作られたAvatar Skin Replaceというモジュールがそれを解決してくることもあるらしい。（すごい）

https://shatoo.booth.pm/items/1725279
TerraformでAWS backupの設定を入れる

## これは何
TerraformでAWS backupの設定を入れた際の記録です。

## 早速やってみた

```
$ vi aws_backup.tf
```


```terraform
resource "aws_backup_plan" "bastion" {
  name = "tf_backup_plan_bastion"

  rule {
    rule_name         = "tf_backup_plan_rule_bastion"
    target_vault_name = aws_backup_vault.bastion.name
    
　　　　　　　　＃UTC 17時　＝　JTC 2時
　　　　　　　　schedule          = "cron(0 17 * * ? *)"
    
　　　　　　　　＃二日後に削除
    lifecycle {
      delete_after = 2
    }
  }
}

resource "aws_backup_vault" "bastion" {
  name = "tf_backup_plan_vault_bastion"
}

resource "aws_backup_selection" "bastion" {
  iam_role_arn = "arn:aws:iam::<Account ID>:role/service-role/AWSBackupDefaultServiceRole"
  name         = "aws_backup_selection_bastion"
  plan_id      = aws_backup_plan.bastion.id

#<VolumeのID>は、コンソール上のEC2>Volume から確認できます。

resources = [
    "arn:aws:ec2:ap-northeast-1:<Account ID>:volume/<VolumeのID>"
  ]
}
```

## 総じて
構築している最中は、aws_backup_selectionのresourceでvolumeの指定の仕方がよくわからず、苦戦していたのですが、どうやらRegion,Account ID,Volume IDを指定すればいけるっぽいですね。
＊実環境で運用される際には、バックアップが実際に取れるか、まで確認してからをオススメいたしますm(__)m

## 参考

```
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_selection
https://www.jisakeisan.com/?y=2021&m=08&d=02&hh=02&mm=00&t1=jst&t2=utc
```
FARGATEのコンテナにdocker execする【既にECSを使用している方向け】

#1.AWSCLIの更新

```shell:macOS
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
```
macOS以外の更新方法は

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html

#2.SSM(SessionManagerPlugin)をインストール

```shell:macOS
curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/session-manager-plugin.pkg" -o "session-manager-plugin.pkg" &&
sudo installer -pkg session-manager-plugin.pkg -target /
ln -s /usr/local/sessionmanagerplugin/bin/session-manager-plugin /usr/local/bin/session-manager-plugin
```

macOS以外のインストール方法は

https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html#install-plugin-macos-signed

#3.既存のECSサービスのenable-excute-commandを有効にする
2021/8/2現在、AWSコンソール上からは有効にできないため、AWSCLIを使用します。

```shell:
aws ecs update-service \
    --cluster example-cluster \
    --service example-service \
    --enable-execute-command
```

ちなみに、terraformを使用している方は、リソース「aws_ecs_service」のenable_execute_commandをtrueにするだけです。

#4.AWSCLIからFARGATEのコンテナにアクセスする
以下のコマンドでコンテナにアクセスします。

```shell
aws ecs execute-command  \
    --region $AWS_REGION \
    --cluster ecs-exec-example-cluster \
    --task ef6260ed8aab49cf926667ab0c52c313 \
    --container example-container \
    --command "/bin/bash" \
    --interactive
```
region名、cluster名などは、適宜修正が必要です。

## 【補足】　An error occurred (TargetNotConnectedException) when calling the ExecuteCommand operation: The execute command failed due to an internal error. Try again later.

時間を置いて試してもエラーが解決するわけもなく、ECSのタスクロールにSSM関連の権限を与えて、タスクを再起動することで解決しました。同じエラーが出た方の助けになると幸いです。
Docker Desktop for Macの自動起動が出来ない現状の代替手段

:warning: 2022/2/27追記： 最新バージョンの`20.10.12`で自動起動時に毎回ログイン画面に遷移するところから開始し、起動後も各種メニューオプションが表示されないなど、不具合が発生しています。よって、以下の方法は有効です。

:warning: 2021/12/5追記: 以下の問題はDocker Desktop for Macの最新版である`20.10.11`(@ macOS 12.0.1 Monterey)では一応解決しています。しかし、今後再発する可能性が有りますので、再発した場合は、以下の方法が有効です。

Docker Desktop for MacがMacの起動時に自動起動[^startup]出来ず、「Fatal Error Failed to ping backend API」とエラーコンソールが表示されます。しかも、操作ボタンを選ばせる様になっていますが、クリックしても反応しません。故に終了させたくても終了させることが出来ず、ターミナルを起動してKillするか、アクティビティモニタを起動して強制終了するより他に終了出来ません。そこで以下の様に現状の代替手段を考えました。

# 自動起動の無効化
Docker DesktopのPreferences.../Generalの`Start Docker Desktop when you log in`のチェックボックスをオフにします。また、Docker Desktop起動時にダッシュボードが表示されて欲しくない場合は、`Open Docker Desktop dashboard at startup`のチェックボックスもオフにします。

# 起動スクリプトの作成
Docker Desktopの起動スクリプトを作成します。記述内容は以下の通りです。`sleep 300`の部分は遅延起動のために開始を300秒(5分)待つようにしています。これはDockerの起動エラーが起動直後の様々なプロセスの起動が立て込んでいるタイミングでDockerを起動させようとすると発生している傾向が有るからです。

```bash:start_docker_desktop.sh
#!/bin/bash

sleep 300
open /Applications/Docker.app
```

# 実行権限の付与
実行権限を付与します。

```bash
chmod +x start_docker_desktop.sh
```

# Crontabに登録し、起動時に自動実行を有効化
Crontabに登録して、Mac起動時に自動実行出来る様にします。

```bash
crontab -e
```

以下の内容を追記します。

```bash
@reboot start_docker_desktop.shの絶対パス
```

# Reference
https://webkaru.net/linux/sleep-command/

https://genzouw.com/entry/2020/06/05/084536/2040/

[^startup]: 現状Docker DesktopのPreferences.../Generalを覗いてみると、`Start Docker Desktop when you log in`のチェックボックスがオフになっています。ネットで調べて見るとGitHubのIssueにも挙がっており、どうやらバグの様です。
plunker で FZ/KM web

#概要

plunkerでFZ/KM webやってみた。
fuzixがwebで動く。

#参考にしたページ。

http://www.recfor.net/jeans/index.php?itemid=955

#動作ログの見本

'''
Copyright (c) 1988-2002 by H.F.Bower, D.Braun, S.Nitschke, H.Peraza
Copyright (c) 1997-2001 by Arcady Schekochikhin, Adriano C. R. da Cunha
Copyright (c) 2013-2015 Will Sowerbutts <will@sowerbutts.com>
Copyright (c) 2014-2020 Alan Cox <alan@etchedpixels.co.uk>
Devboot
80kB total RAM, 64kB available to processes (15 processes max)
Enabling interrupts ... ok.
Scanning flash: 2591kB: hda: 
SD drive 0: hdb: hdb1 hdb2 
Mounting root fs (root_dev=18, ro): warning: mounting dirty file system, forcing r/o.
OK
Starting /init
init version 0.9.0ac#1
fsck-fuzix: 

 ^ ^
 n n   Fuzix 0.3.1
 >@<
       Welcome to Fuzix
 m m

login: root

Welcome to FUZIX.
# stty erase '^?'
# cd /tmp
# ls
1
# cd /
# ls
bin
dev
etc
init
mnt
root
tmp
usr
var
# prtroot
/dev/hdb2 / fuzix rw 0 0
# df
Filesystem       Blocks   Used   Free  %Used Mounted on
/dev/hdb2          4064   3279    785    81% /
# mount /dev/hda1 /mnt
/dev/hda1: 
# mount /dev/hda /mnt
warning: mounting dirty file system, forcing r/o.
# df  
Filesystem       Blocks   Used   Free  %Used Mounted on
/dev/hdb2          4064   3279    785    81% /
/dev/hda           2016     20   1996     1% /mnt
# cd /usr/games
# ls
fortune
fortune-gen
fortune.dat
startrek
# ./fortune
Breakpoint 1, main (argc=1, argv=0xbffffc40) at main.c:29
29   printf ("Welcome to GNU Hell!\n");
                -- "GNU Libtool documentation"
# ./fortune
On the Internet, nobody knows you're a dog.
                -- Cartoon caption
# ./fortune
The steady state of disks is full.
                -- Ken Thompson
# ./wump
./wump: not found
# ./startrek

 *************************************
 *                                   *
 *                                   *
 *      * * Super Star Trek * *      *
 *                                   *
 *                                   *
 *************************************



Do you need instructions (y/N):

'''

#成果物

https://embed.plnkr.co/plunk/YocF4BHRAMXld60f

以上。