OmniAICreator/Qiita-1.07M huggingface dataset:
Box Signを実務で使ってみた

2021年11月、BoxにBox Signという電子署名機能が付きました！
Businessプラン、Enterpriseプランをご利用の方は追加費用無しで使うことができます。
[Box Sign](https://www.box.com/ja-jp/esignature)

ということで、さっそく実務で使ってみました！

# 事例記事作成業務でBox Signを使ってみる
私は、普段の業務でお客様の事例記事を作成しています。
事例作成前に、お客様に事例化について承諾をいただく際に書類に記入して送っていただくことがあります。もちろん、電子データでやりとりをおこなうのですが、それでも、ファイルをダウンロード→Officeで記入→アップロードと3つのステップをおこなわなくてはいけないのって、ちょっと面倒ですよね...
それだけが勿論理由ではないのですが、書類の記入依頼がきても後回しにしがちかなと思います。
そこで、この書類の記入の代わりに、Box上でサインしてもらうというフローに変更しました！

# 手順
## 事前作業
Signを管理対象ユーザーが使えるように、有効化します。
[管理コンソール]-[Enterprise設定]-[コンテンツと共有]-[Sign]から設定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/5feddb34-7b70-0770-36df-d342a1a126df.png)

##　サイン依頼のフォームを作る
1. Boxで同意書のフォーマットをプレビューします。
今回はこんなフォーマットを使おうと思います。（大人の事情により実際の業務で使った同意書とは異なります！）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/11cfb4e2-2d02-f9ba-f051-9472d834e510.png)

2. Signを起動する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/f6a0cc27-cf96-01f5-f902-92b4db7ed65c.png)

3. サインをおこなう人を選択
今回、サインをしていただく方は社外の方のみで社内は回覧しないので「他の人のみ」を選択し、続行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/59beab70-6043-bfb3-d8fa-0546f24e4f8b.png)

4. フォームを配置する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/0ebff43f-4d81-d8c7-aaa0-a4be548e2660.png)

5. オプションを設定する。
メール通知や、リマインダーの設定ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/cae2ee34-b89a-980b-78c3-5308e427b915.png)

以上で完成です！

## サイン依頼をおこなう
フォームの設定が終わったら右上の[リクエストの送信]をクリックし送信します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/578fc174-b1b8-6e33-93a7-ed0aa02e2499.png)

## サインする
相手には、このようなメールが届きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/4749ffbd-fe0b-c8e8-a38a-a4506a297114.png)

早速サインしてみましょう！

こんな感じで、緑色のガイドが出てくるので、次に何をすればいいのか一目瞭然です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/307d4986-c7d9-5d76-fd3b-1f2c9264dd8d.png)

ポチポチしていくだけでサインが完了できます。あっという間。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/8ca95c84-9bf8-79a3-9ce7-cd6dd5032cd0.png)


## 結果を受け取る
サインが完了すると、このようなメールが届きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/d181a5df-f923-8004-3124-ec68dbdec5d4.png)

フォルダには、サイン済ファイルとログが残ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/0686830f-7488-6eb6-e003-384ccb56e934.png)

サイン済ファイル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135983/94024420-1fab-2dd5-5b88-bbc61883dd3f.png)


# 結果
Box Signを使うと、サイン作業がWebブラウザ上で完結します！ファイルダウンロードする必要もありません！
ステップ数が減って効率化されたからか、お客様も秒でサインしてくださり、あっという間に複数社から返事をいただくことができました。

社内の「覚書」的な書類からBox Signを使って電子署名をはじめてみるのは良さそうです。
オープンワールド系のゲーム開発を経験したので色々話す#0

#まずは挨拶

お久しぶりです。てんぺんです。
いつの間にか就活も終わり気づいたら12月になろうとしています。

この期間、何もしていなかったかというと、そういうわけでもなく...


タイトルの通りオープンワールドのゲームの開発をし始めたので、そのお話を何回かに分けて話そうと思います。(毎週投稿予定)


下記リンクからそれぞれの記事に飛べるので、是非読んで行ってください。


＃1 TerrainとDitail編
https://qiita.com/hemmiyuya/items/b9bc17d65cc629f07500

＃2 街づくり編
https://qiita.com/hemmiyuya/items/c3593c049d60d3afd5e1

＃3 NPC編
12/19投稿予定

＃4 クエスト編
12/26投稿予定
#まとめ

読んでもらったらわかると思うのですが、バチバチにコードを書いていく時間よりも、Unityの機能を使って何かする。という時間が結構長いので、プログラムを書くのが好きな人だと結構やっていて苦痛な時間が多いのかなと思います。

それでも、自分が作りたいものがどんどんできていくというのはとても嬉しいしワクワクするものなのでこの記事を読んだ方も是非挑戦してみてください。(オープンワールドゲームに限った話じゃないけどね！)

あと、自分も初心者だったりするので、もっとこーゆーことしたら良くなるよとか、他にはどんなことしたんですか？とか、アドバイス質問等あったらどんどんください！

それではノシ
ネットでVisual Basic関連を検索する時に除外する略名群

# はじめに
これは、[Visual Basic Advent Calendar 2021](https://qiita.com/advent-calendar/2021/vb)の4日目の記事となります。

ネタ探しに Yahooのリアルタイム検索で「[VB OR VBA OR VBS OR "Visual Basic" OR VisualBasic](https://search.yahoo.co.jp/realtime/search?p=VB+OR+VBA+OR+VBS+OR+%22Visual+Basic%22+OR+VisualBasic&ei=UTF-8&ifr=tl_sc)」を検索してみました。

VBと書いてあってVisual Basicの略名かと思ったら、ウィルスバスターだったとかってありますよね。
VBなんて簡易な略名なんで当然ですが、Visual Basicに関連しない項目が出てくるわけですね。

果たして何の略名なのか調べてみました。これを知れば除外対象として素早く判断できるようになります。
1日分ぐらいしか調べてないですが、今後も見つけしだい追加していきます。

# VBの略名
|VB|内容|
|:--|:--|
|VB|[バーチャルおばあちゃん](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%BC%E3%83%81%E3%83%A3%E3%83%AB%E3%81%8A%E3%81%B0%E3%81%82%E3%81%A1%E3%82%83%E3%82%93) 関連 コウくん|
|VB|声優・アニメ誌『VOICE BRODY』が『VB』へとリニューアル|
|VB|VB（バーチャルブラッド）（またはヴァンパイアブラッド）の略名 飲み物 関連 レッドブル|
|VB|MasterofEpic Moeのヴァルキリー ブレイドの略名|
|VB|[VenusBlood(ヴィーナスブラッド)](https://ja.wikipedia.org/wiki/VenusBlood)の略名|
|VB|バイタルブレスの略名 VBラボ、VBコイン 関連 デジモン|
|VB|ウィルスバスターの略名|
|VB|バレーボールの略名|
|VB|架空の商品販促の略名|
|VB|ビタミンB群の略名 医療系|
|VB|ベンチャー企業の略名|
|VB|Virtual Boyの略名|
|VB|仮想オーディオデバイスの略名 VB-Audio、VB-CABLE、「VB-Audio Virtual Cable」|
|VB|イーサリアム共同創設者であるヴィタリック・ブテリン氏の主要ETHウォレット|
|VB|ビブラート・エフェクターの略名 関連 BOSS|
|VB|Aria(荒井貿易が手がけるブランド)のバイオリンベースのギター|
|VB|ヴェルダン ブラックの略名 関連 下村工業|
|VB|ニトリのマットレスの型番の一部|
|VB|コム デ ギャルソン財布 関連 コイン|
|VB|NECのノートPC Versapoの型番の一部|

# VBAの略名
|VBA|内容|
|:--|:--|
|VBA|GBAのエミュレータと言えばVisualBoyAdbanceの略名|
|VBA|ヴォーグ・ビューティー・アワードの略名|
|VBA|VOCAL BATTLE AUDITIONの略名|

# VBSの略名
|VBS|内容|
|:--|:--|
|VBS|プロセカのVividBADSQUADの略名　「プロジェクトセカイ」に登場するユニットのひとつ 関連 リン、KAITO|
|VBS|シューティング Vampire Bloody Star-Xの略名 VBS-X|

# 最後に
リアルタイム検索ってことで、直近の話題としての、[バーチャルおばあちゃん](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%BC%E3%83%81%E3%83%A3%E3%83%AB%E3%81%8A%E3%81%B0%E3%81%82%E3%81%A1%E3%82%83%E3%82%93)の勢いがすごいですね。
【Tableau】VIZの垢抜けスキル③〜二重軸でどんなのできる？〜

この記事は[Advent Calendar 2021 Tableau](https://qiita.com/advent-calendar/2021/tableau2021)の3日目の記事となります。

本日は二重軸を活用してどんな事ができるのか、いくつかバリエーションを紹介します。
※私の解説＆キャプチャはTableauDesktopのバージョン2020.4、PCはMacを使ってます。
バージョンが異なったりPCがWindowsの場合、操作が一部異なる場合もあるかもしれません。

二重軸では、二つのメジャーを利用します。
異なった二つのメジャー利用し、メジャー同士を比較する為に活用する事もありますが、
**ここでは同じメジャーを二つ使い**どんな見せ方があるかの紹介になります。

##棒✖️丸（ロリポップチャート）
![birthday.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/0805c1e5-7477-808d-e8bf-18a49cb12abc.png)
VIZリンク：https://public.tableau.com/app/profile/misaki.takatsu/viz/MoM_2021W26_HowCommonisYourBirthday/birthday

このマッチ棒のようなチャートは、ロリポップチャートと言います。
線グラフに丸を重ねることで、頂点が強調されて見やすくなる利点もあります。

マーク部分の設定は棒と丸。
色を統一して使うとこのようになります。
![スクリーンショット 2021-12-04 23.11.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/6cfbeb59-fc98-bef3-a917-c80affae14d0.png)

色を変えるとこのようになります。
![スクリーンショット 2021-12-04 23.12.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/98677667-190c-9200-0402-46fff69ced77.png)

この時は誕生日に関するVIZだったので、キャンドルに見立てて活用しました。

##エリア✖️丸
![スクリーンショット 2021-12-04 23.16.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/d96f13f8-91be-2fff-b645-a775a11b7f8f.png)

マーク部分の設定はエリアと丸。二つのメジャーの色を、バランスを見てそれぞれ選択してます。
![スクリーンショット 2021-12-04 23.18.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/f6459e64-feb8-2c4a-11b9-b7a96863a801.png)

##棒✖️棒
![スクリーンショット 2021-12-04 23.16.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/25a1bde2-185b-940d-284d-7e3be68f057a.png)

これは二つのメジャーどちらもマークで棒を選択。
![スクリーンショット 2021-12-04 23.18.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/4a37a0fe-318a-5b32-755e-76dbd2bdbdbd.png)

以下のように二つそれぞれのサイズを、異なるサイズに設定することで可能です。

一つ目のメジャーサイズ
![スクリーンショット 2021-12-04 23.19.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/4f6f195d-5fd3-6801-d2e5-524bbca645f4.png)

二つ目のメジャーサイズ
![スクリーンショット 2021-12-04 23.20.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/69983c31-5b42-0795-36e6-7ae711c88012.png)

VIZリンク：https://public.tableau.com/app/profile/misaki.takatsu/viz/MoM_2021W16_MonthlyAirPassengersinAmerica/Monthly

##棒✖️形状
これを利用すると魔法ステッキのようなチャートもできます。
![スクリーンショット 2021-12-04 23.34.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/5b43c832-33ff-13ca-5cbc-0d1fe3e36fc3.png)

これは棒のサイズを細くして、もう一つのメジャーはマークで形状を選択。
その後、更に形状の詳細を選択します。
![スクリーンショット 2021-12-04 23.35.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/8aa5fc53-9d8d-9902-7826-6489cf08f78e.png)

ロリポップチャートの形を変えたバージョンなので頂点が強調されるメリットはありますが、悪目立ちもしそうなのでバランス次第で使えそうだなと思いました。
形状と色を変えて色んなパターンが試せそうです。
![スクリーンショット 2021-12-04 23.44.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/2408116b-d7c5-73f3-53c7-39a45815747d.png)
Lightship ARDK のベースプロジェクトの作り方

Nianticから公開されたARアプリの開発キットであるLightship ARDKについて、基本的なことをまとめていきます。
今回はLightship ARDKのアプリを作成するときに、必ず行うベースプロジェクトの作成方法をまとめます。

## ベースプロジェクトの作成

1. Unityで3Dのプロジェクトを作成します。
1. ARDKのパッケージをインポートします。
1. [Resources] - [ARDK]フォルダを作成します。  

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/478cb8e3-6e8c-cb44-0ef6-f50e4d5d50cb.png)

1. ARDKフォルダを選択して、[Create] - [ARDK] - [ArdkAuthConfig]からコンフィグファイルを作成します。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/bffd8c69-2514-ad85-5b7a-e912daf2bcad.png)

1. 作成されたArdkAuthConfigを選択しInspector表示されるApiKeyにLicense keysを入力します。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/8c5956e0-91c0-d71e-2202-c932c3cf43d7.png)

1. SceneにあるMain Cameraを削除します。
1. [Assets] - [ARDK] - [Extensions] - [Prefabs]にあるARSceneManagerプレハブをHierarchyにおきます。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/171530b9-be80-7d99-d563-37c982be800e.png)

1. (Androidの場合) ARSceneManagerにAndroid Permission Requesterを追加し、Cameraパーミッションを追加すると、起動時にパーミッション確認をすることができます。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/7ea9b6a7-d79d-989e-2f0b-4d7cd8d53800.png)


## 各プラットフォーム向けのビルド方法

### iOS

下記公式ドキュメントにまとめられていますので、こちらを参照してください。    
https://lightship.dev/docs/building_ios.html

### Android

下記公式ドキュメントにまとめられていますので、こちらを参照してください。    
https://lightship.dev/docs/building_android.html

## 実機で表示
実機で動かすと下図のようにカメラが起動します。
<img width="300" alt="Screenshot_20211204-233604.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/b2ae4536-6f17-b8cf-d9c5-235ac55486ba.jpeg">


## 参考サイト
- 公式ドキュメント    
    https://lightship.dev/docs/
[初学者必見]デフォルトシェルはbashにしようという話


## 初めに
自分は環境構築やLinux関係に苦手意識を感じています。
エラーを吐かれようものなら、とりあえず参考記事からコピペ実行！
それで通ったならばよし。めでたしめでたし、と済ませていました（本当にめでたい）
しかし、このままではいけないと思い、[Linux標準教科書](https://linuc.org/textbooks/linux/)を参考に学習しました。
今回はそこから感じ考えたことを記事に残しておこうと思います。

## シェルとは
シェルとは、Linuxの核となるカーネルに対して命令をしたときに、
カーネルが理解できる機械語に翻訳して伝達する役割を担っているインターフェイスのこと。
Linuxを理解する上で、切っても切り離せないものです。

## 主なシェルの種類
[B系]
・sh
・bash
・ksh
・dash

[C系]
・csh
・tcsh

[B系ベース + Cシェル系にも対応]
・zsh

## 初学者はbash推奨
Mac(catalina以降)のデフォルトシェルはzshですが、
サーバーに入ったりLinuxを触るときはほとんどがbashになります。
それに慣れておく意味合いでも、ターミナルでもbashを使うことを推奨します。

:::note warn
2021/12/9追記
Macのデフォルトシェルがbashからzshになったのは、セキュリティ面からの整理とのこと。
https://www.infoq.com/jp/news/2019/07/macos-ditches-bash-for-zsh/
:::

## シェルの変更方法
```$ echo $SHELL```
/bin/zsh

```$ chsh -s /bin/bash```
ターミナルを再起動。再度シェルを確認すると、、
/bin/bash
  
:::note warn
~/.zsh_profile(~/.zshrc)などに書かれたターミナル起動時のシェルの設定は引き継がれません。
必要な設定は自身で改めて~/.bash_profile(~/.bashrc)などに転記してください。
:::
パスの設定については[こちら](https://qiita.com/k3ntar0/items/eb8cdbd8eba9da388def)が参考になります。
【Laravel UIのインストール】Your requirements could not be resolved to an installable set of packages.と出たとき

LaravelのアプリでReactを使いたくて`Laravel UI`をインストールする際にエラーとなってしまいました。
その際の覚書きです。

## 実行環境
- macOS Catalina 10.15.7
- Composer 2.1.12
- Laravel 6.20.40


## 実行コマンドとエラー内容

実行コマンド

```
$ composer require laravel/ui
```
結果

```
Using version ^3.4 for laravel/ui
./composer.json has been updated
Running composer update laravel/ui
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - laravel/ui[v3.4.0, ..., 3.x-dev] require illuminate/console ^8.42|^9.0 -> found illuminate/console[dev-master, v8.42.0, ..., 8.x-dev, 9.x-dev (alias of dev-master)] but these were not loaded, likely because it conflicts with another require.
    - Root composer.json requires laravel/ui ^3.4 -> satisfiable by laravel/ui[v3.4.0, 3.x-dev].

You can also try re-running composer require with an explicit version constraint, e.g. "composer require laravel/ui:*" to figure out if any version is installable, or "composer require laravel/ui:^2.1" if you know which you need.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.
``` 

## 結論 
調べたところ，Laravel UIとLaravelは対応するバージョンが決まっているようです。

|  Laravel UI  |  Laravel  |
| ---- | ---- |
|  1.x  |  5.8、6.x  |
|  2.x  |  7.x  |
|  3.x  |  8.x  |


https://github.com/laravel/ui


                             
自分の使ってるLaravel`6.20.40`に対応したバージョン`1.0`を指定してインストール

```
$ composer require laravel/ui:^1.0 --dev
```

無事インストールできました！

```
./composer.json has been updated
Running composer update laravel/ui
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking laravel/ui (v1.3.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Downloading laravel/ui (v1.3.0)
  - Installing laravel/ui (v1.3.0): Extracting archive
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: laravel/ui
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
68 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
```

## 余談
この後，Laravelのバージョンを`7.30.5`に変更したので，Laravel UIのバージョンも`2.0`に変更しました。
PhpStormでHTTPプロキシを介したSFTP Deploymentをしたい@Windows

Webサーバーの運用ではセキュリティ的な観点から、しばしばSFTP（もしくはSSH）接続をおこなう際はIP制限をかけておいて、プロキシ認証（今回の場合はHTTPプロキシ）を介さないとアクセスできないようにしておくことがあります。

そういった環境のファイルをいじりたいとき、そこそこの規模なサイト・サービス構築をするときはGit経由でファイルをデプロイするのでコンソールにさえ繋げれば問題ありません。が、ちょっとしたLPを置いておきたいだけだとか、あとはログの軽いチェックなどをしたいとき、直接SFTPでサーバーへ繋ぎたいときもありますよね。

ちょうど先日、上記のようなタイミングにぶち当たりました。日々のコーディングをだいたいPhpStormでやっている私なのでSFTP設定を試みますが、残念なことにPhpStormではプロキシ経由のSFTP設定をおこなうことができません。ということで、以下どうにかしてHTTPプロキシ（認証あり）経由のSFTPをつないだ備忘録です。

# 環境
Windows 10 Pro
PhpStorm 2020.3.1

# やったこと

1. まだGitがインストールされていない場合はGit for Windowsをインストールしておく。Git for Windowsに同梱されているconnect.exeが必要です（場所はC:\Program Files\Git\mingw64\binあたり）。もしかするとMingw-w64を単体でインストールしてもいいのかもしれませんが、未確認です。

1. C:\Users\hogehoge\\.sshにconfigという名前のファイルを作る（拡張子なし）。そして、以下のように記述。ファイルパスとかは適宜変更してください。あとは普通の手順でPhpStormのSFTP設定をすれば接続時にプロキシのパスワードが聞かれるようになります。

```config:config
Host [接続したいサーバーのIPアドレス]
	ProxyCommand C:\Program Files\Git\mingw64\bin\connect.exe -H [プロキシのユーザー名]@[プロキシのIPアドレス]:[プロキシのポート] %h %p
	ServerAliveInterval 10
```

# むすび
ということで普通にSSH Configを利用する方法です。まあGit使えばだいたい解決する話ですね。
まあこうしておくとオートデプロイとかできて便利ですし、テスト環境組むとかにも便利なのでいいんじゃないでしょうか。知らんけど。

# 参考
https://qiita.com/ko-he-8/items/06ae39f77dd5189df59b
https://kaworu.jpn.org/security/HTTP%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7%E3%82%B5%E3%83%BC%E3%83%90%E7%B5%8C%E7%94%B1%E3%81%AEssh%E6%8E%A5%E7%B6%9A
Qt Creatorでcmakeからビルドする方法

Qt Creatorでは最初qmakeというビルドシステムが選択されますが,cmakeに慣れている場合こちらに変更することができます。

手順を動画で撮影したのでよろしければご覧ください。

https://www.youtube.com/watch?v=qt7Wq3B6VFM
【Node.js 2021】 WAVファイルを Node.js で再生する（Mac で node-wav-player を利用する）

この記事は、[2021年の Node.js のアドベントカレンダー](https://qiita.com/advent-calendar/2021/nodejs) の 8日目の記事です。

内容はタイトルの通りで、以下のものに関する記事です。

●node-wav-player - npm
　https://www.npmjs.com/package/node-wav-player

## 音の再生に必要なもの（Mac の場合）
node-wav-player のページ上部に、以下のような記載があります。

![環境.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/b5ff75db-decd-8955-a498-a007a7c26f97.jpeg)

自分の場合 Mac を使っているので「afplayコマンド」が必要になるようです。
例えば、以下の記事に afplayコマンドに関する記載があります。

●afplayコマンドをつかってMacにてターミナルからコマンドで音楽ファイルを再生する 💻 - みかづきブログ・カスタム
　https://blog.kimizuka.org/entry/2020/07/10/174935

このコマンドが使えることを確認しておきましょう。

## 簡単なサンプルで試してみる
それでは、公式ページに書いてあるサンプルを試してみます。

試す前に `npm i node-wav-player` を実行しておきましょう。

```javascript
const player = require('node-wav-player');
player.play({
  path: './【WAVファイルの名前】.wav',
}).then(() => {
  console.log('The wav file started to be played successfully.');
}).catch((error) => {
  console.error(error);
});
```

WAVファイルは、以下の記事にも書いていた方法で準備しました。
（効果音ラボさんの素材として公開されている MP3ファイルを、ffmpeg で WAVファイルに変換）

●【M5Stack 2021】 #M5Stack Core2 ＋ #UIFlow で音を鳴らすのに手間が少なそうな方法（＋ ffmpeg での音声ファイルの処理の話） - Qiita
　https://qiita.com/youtoy/items/57fce216e2f74dff2452

適当な WAVファイルを用意して、上記を実行すると、音を鳴らすことができました。

## サンプルに手を加える
### ２つの音を鳴らす1（同時に鳴る）
次に、2つの WAVファイルを用意して、それを鳴らすような処理を書いてみます。

```javascript
const player = require("node-wav-player");
const wavList = [
  "【1つ目のWAVファイルの名前】.wav",
  "【2つ目のWAVファイルの名前】.wav",
];

function playWav(inputWav) {
  player
    .play({
      path: inputWav,
    })
    .then(() => {
      console.log("The wav file started to be played successfully.");
    })
    .catch((error) => {
      console.error(error);
    });
}

playWav(wavList[0]);
playWav(wavList[1]);
```

これを実行すると、2つの WAVファイルが同時になりました。

### ２つの音を鳴らす2（順番に鳴る）
上記のプログラムで、音が同時になったのは、以下の記載に関係していそうです。
![オプションの設定.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/ed725ae7-d750-ad05-cb55-39102a074d2f.jpeg)
ここに書かれているオプションが false になっていると、1つ目の WAVファイルが再生され始めてすぐに、次の再生へと進むようです。

このオプションを true にして、かつ、処理を少し書きかえたプログラムを実行してみます。

```javascript
const player = require("node-wav-player");
const wavList = [
  "【1つ目のWAVファイルの名前】.wav",
  "【2つ目のWAVファイルの名前】.wav",
];

player
  .play({
    path: wavList[0],
    sync: true,
  })
  .then(() => {
    console.log("The wav file started to be played successfully.");
    player
      .play({
        path: wavList[1],
        sync: true,
      })
      .then(() => {
        console.log("The wav file started to be played successfully.");
      });
  })
  .catch((error) => {
    console.error(error);
  });
```

これで、2つの音声ファイルが順番に鳴りました。
この書き方が良いのか、ちょっと不安がありつつ...

## おわりに
Node.js のプログラムで、 WAVファイルを再生することができました。

「何か処理が終わったタイミングでとか、操作をしたタイミングで」といったところで音を鳴らすとか、使えそうな場面はいろいろありそうなので、さらに活用法を考えたりお試しをしたり、というのをやっていければと思います。
ectoでテーブルを変更するやり方まとめ

テーブル名の変更-> [rename/2](https://hexdocs.pm/ecto_sql/Ecto.Migration.html#rename/2)

```
rename table("posts"), to: table("new_posts")
```

あるテーブルのカラム名を変更-> [rename/3](https://hexdocs.pm/ecto_sql/Ecto.Migration.html#rename/3)

```
rename table("posts"), :title, to: :summary
```

既存のテーブルをまとめて変更-> [alter/2](https://hexdocs.pm/ecto_sql/Ecto.Migration.html#alter/2)

```
alter table("posts") do
  add :summary, :text
  modify :title, :text
  remove :views
end
```

カラムのタイプを変更-> [modify/3](https://hexdocs.pm/ecto_sql/Ecto.Migration.html#modify/3)

```
alter table("posts") do
  modify :title, :text
end
```
DNSリフレクション攻撃 とは

## 勉強前イメージ

リフレクション？反射？
反射の攻撃？？

## 調査

### DNSリフレクション攻撃 とは

DNSアンプ攻撃とも言いますが、DNSを利用したDoS攻撃の一種。
送信元IPを偽装してDNS問い合わせをDNSサーバに行うことで
DNSサーバが応答パケットを攻撃対象に送り、使用できない状態にします。
送信元IPを偽装することで、本来の問い合わせ元ではなく攻撃対象のホストへ
応答を返すので、DNSを経由して攻撃対象のホストやネットワークに負荷をかけます。

![12021-12-04 # DNSリフレクション攻撃 とは - diagrams.net - Goog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/f42d51ce-da16-ca56-7c8e-9379b7094163.png)


### DNSリフレクション攻撃の対応

- 不要なポートを塞ぐ

ポートの数だけ攻撃範囲が広がるので不要なポートは防ぎましょう

- レートリミットの設定

DoS攻撃に有効な手順で、
過剰なリクエストを送ってくるIPアドレスのリクエストをブロックでき
被害を抑えることができます。

- IPレピュテーション

IPレピュテーションとはIPアドレスを評価し、通信を制限する仕組みですが
判断基準としてIPアドレスがブラックリストに載っていないかなどをチェックし
載っているとブロックするような方法です。

## 勉強後イメージ

DNSを介して攻撃をすることか・・・
誰がやったかは特定しづらい感じですね

## 参考

- [DNSリフレクター攻撃（DNSアンプ攻撃）](https://jprs.jp/glossary/index.php?ID=0156)
- [DNSリフレクション攻撃/DNS増幅攻撃/DNS水責め攻撃とは](https://www.nic.ad.jp/ja/basics/terms/dns-dos.html)
【誤送信対策】Outlook遅延送信設定方法

- 間違った宛先にメール送信
- 本文の途中で誤送信
- 添付忘れで誤送信
- 様、御中付け忘れで誤送信

上記の問題をOutlookの簡単な設定で回避することができます。

## Outlookの遅延送信設定の方法

まず最初にOutlookを開き、上部の**[ファイル]**タブを選択する。
![outlook_open.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1028011/bd838a7b-6714-cf6e-4b47-f3857530f9fa.jpeg)

すると、以下の画面に切り替わるので、**[仕分けルールと通知の管理]**を選択する。
![outlook_rule.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1028011/b3f36f00-0a75-c0b7-566d-b166fe3d109d.jpeg)

ポアアップ画面が開くので、**[新しい仕分けルール(N)]**を選択する。

![outlook_setting_slow.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1028011/eaf7053d-23f3-ed70-714d-e7ccf123e4b4.jpeg)

**送信メッセージにルールを適用する**を選択し、[次へ]ボタンをクリックする。

ステップ1：条件を指定してください(C)と出るが**ここはスルー**し、[次へ]ボタンをクリック。

この時、「！ この仕分けルールはすべての（送信メッセージ）に適用されます。よろしいですか？」と聞かれるので**[はい]**を選択する。

次に、チェックをできる画面に飛ぶので、**指定した時間 分後に配信する**にチェックを入れる。すると、下部にステップ2で**指定した時間**の青字をクリックし、[1]か[2]を選択する。
※個人的には[1分]を推奨する

そして完了ボタンをクリックし、適用をクリックすれば遅延送信設定が完了です。
【Flutter】VScodeでデフォルトのパッケージ名を変更する方法

# 概要
VSCodeでFlutterアプリを作成する際の、デフォルトのパッケージ名を変更する手順のまとめ
# 手順
1. 「VSCode」を開く
2. 「ファイル」>「ユーザー設定」>「設定」を開く
3.  検索ボックスで「flutter create organization」と検索
4. 「settings.json」で編集をクリック
5. 「"dart.flutterCreateOrganization": "com.任意のドメイン名"」を追加する
6. 「VSCode」でFlutterプロジェクトを作成し、パッケージ名が変更されていることを確認する
NoMethodError:        undefined method `<<' for #<Mandalart::ActiveRecord_Relation:0x000055f2bd5bb070>

# 前提

![mandal-art-06.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653881/41007dc7-7cb4-2559-8997-87969c1adbbf.jpeg)

マンダラートのアプリを作っています。
マンダラートとはアイデア出しの手法の一つで
こんな感じで、連想してアイデアを出してくような感じ。

# エラーが起きた

```ruby

class MandalartsController < ApplicationController
  def index


    # 最初から配列の要素を9つ入れとく
    # 配列の要素の中身があれば、何もしない
    # 配列の要素の中身があれば、""の要素を入れとく


    @mandalarts = Mandalart.all
    binding.pry

    if @mandalarts.count < $mandalart_blocks_num

      ($mandalart_blocks_num - @mandalarts.count).times do |mandalart|
        mandalart = Mandalart.create(text: '')
        @mandalarts << mandalart
      end
    end
  end

```


     NoMethodError:        undefined method `<<' for #<Mandalart::ActiveRecord_Relation:0x000055f2bd5bb070>


といったエラーが起きた。
`@mandalarts << mandalart`
の部分でエラーが起きてる。

`active_record`オブジェクト?に配列っぽく`<<`で値を追加できないみたい。


```rb:app/controllers/mandalarts_controller

class MandalartsController < ApplicationController
  def index


    # 最初から配列の要素を9つ入れとく
    # 配列の要素の中身があれば、何もしない
    # 配列の要素の中身があれば、""の要素を入れとく


    @mandalarts = Mandalart.all

    if @mandalarts.count < $mandalart_blocks_num
      ($mandalart_blocks_num - @mandalarts.count).times do |mandalart|
        Mandalart.create(text: '')
      end
      @mandalarts = Mandalart.all
    end

  end


```


とすることで、
配列の中身が`$mandalart_blocks_num`分(9つ)足りなかったら、
足りない分、レコードを作成する。
そうして、 `@mandalarts = Mandalart.all`と`if`の中で定義することで
最初の`@mandalarts = Mandalart.all`とバッティングしない。


```rb:spec/requests/mandalarts_spec.rb

    it "works! (now write some real specs)" do
      get root_path
      expect(response).to have_http_status(200)
    end


```

といったテストもパスできた。

レコードが`$mandalart_blocks_num`分なかったら、`$mandalart_blocks_num`分
レコードが作られるか確認できるテストも書きたいと思う。
LocalStackがあれば大体何でもローカルでAWS開発ができる

この記事は　[ZOZO #3 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/zozo) ８日目の記事になります。

AWSのサービスの中でもフルマネージドサービスを多用するアプリケーションを実装するうえで一番困るのは、ローカルでどうテストするか？かと思います。
例えば、LambdaとかSQSとかKinesisとかフル活用するサービスなどがその対象になりますね。

そこで[LocalStack](https://localstack.cloud/)。実は５年前にLambda中心のServerlessアーキテクチャのサービスを作ったときにも一度検討しましたが、当時はまだ使い勝手が良くなく、結局毎度AWS環境にあげて試していました。

そこが現在、とても使いやすいサービスとなっていて、この度のプロジェクトではフル活用しました。ローカルで試せるのはとても助かります。

CommunityEditionとProEditionがありまして、その差は[こちら](https://localstack.cloud/pricing/)になりますが、大方のユースケースではCommunityEditionで十分かと思います。

使い方も簡単。
１．　docker-compose.yaml作って起動

```yaml
services:
  localstack:
    image: 'localstack/localstack:0.12.12'
    ports:
      - 4566:4566
```

```bash
docker compose up -d
```

2. LocalStack用のCLIを用意（基本AWS CLIと同じコマンドが使える)

```bash
pip install awscli-local
```


3. CloudFormationのファイルを用意（本番と共通でよい）。

4. CloudFormationをLocalStack用のCLIで実行

```bash
awslocal cloudformation create-stack --stack-name test-stack --template-body file://resources.yaml --parameters file://parameters/local.json
```

これで多くのAWSサービスがlocalhost:4566で使用可能になります。
ちなみに今のプロジェクトで使用しているのは
・S3
・Kinesis
・SES
・DynamoDB
になります。

ぜひ参考にしてみてください。

次の日も自分ですね。セキュリティから始まるDDDというタイトルでお届けします。
それって サステナブルですか？ ～AWS Well-Architected Framework 6つめの柱～

# AWS Well-Architected Frameworkの新しい柱
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117386/86a43f91-0c97-9912-4d58-abf135deeb3d.png)

* re:Invent 2021でW-Aの新しい柱(サステナビリティ)が追加されました。
* サステナビリティとは、直訳すると『持続可能性』。
* https://docs.aws.amazon.com/wellarchitected/latest/sustainability-pillar/sustainability-pillar.html


# そもそも Well-Architectedとは？
* AWSとAWSユーザの10年以上の経験からまとめられた設計原則とベストプラクティクス集
* 多くの失敗反省を元に作られ、AWSを活用する際に同じ失敗をしないためのガイドライン
* W-Aフレームワークに基づいた設計レビュー(W-Aレビュー)は、一貫した基準でAWSアーキテクチャーを評価して改善領域を見つけることが目的トラブル(工数不足、設計ミスなど)を未然に防止し、リスクを軽減、スキルアップにも効果

### アーキテクチャー設計の評価観点原則
1. 運用の優秀性
1. セキュリティ
1. 信頼性
1. パフォーマンス効率
1. コスト最適化
1. **サステナビリティ ← 2015年から6年ぶりに追加**

# サステナビリティとは？
## サステナビリティ
目先の利益を追い求めるのではなく、**自然環境や社会システムの維持**にも目を向けようという考え方や活動を指す言葉。

## 環境問題に対するAWSのアプローチ
* "実行中のクラウドワークロードによる**環境への影響を最小限に抑えること**に重点を置いています。環境への影響とは、特にエネルギー消費と効率にフォーカスしています。"
* Wernerの [Tech Predictions for 2022 and Beyond](https://www.allthingsdistributed.com/2021/12/tech-prediction-for-2022-and-beyond.html) 予測4にも、「サステナビリティは独自のアーキテクチャーを」というキーワードがあります。このあたりも要チェックですね。

## 責任共有モデル
* 利用者とAWSの間で共通の責任
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117386/efd8cf25-9a75-7d28-3b23-0cb629bfcf45.png)
* AWSテクノロジーを使用して、広範囲なサステナビリティの課題を解決しようぜ、というのがAWSからのメッセージ。
* 課題とは？二酸化炭素排出量の削減、エネルギー消費の削減、水のリサイクル、廃棄物の削減

# サステナビリティの柱とは？
* プロビジョニングされたリソースのメリットを最大化し、必要な総リソースを最小限に抑えることで、エネルギー消費量を削減し、ワークロードのすべてのコンポーネントの効率を高めることで、サステナビリティへの影響を継続的に改善する。
* こうした取り組みのためのベストプラクティス。

# 設計原則
1. 影響を理解する<br>ワークロードの影響を測定して、将来の影響をモデル化(KPI)する。
1. サステナビリティの目標設定<br>長期的なサステナビリティの目標を設定する。
1. 使用率の最大化<br>効率的な設計により高い使用率を確保し、電力効率を最大化する。
1. より効率的なハードウェアやソフトウェアの提供を予測して採用する効率的なHW/SW製品を迅速に採用できるようにチェック、柔軟な設計を行う。
1. マネージドサービスを使用する<br>顧客でのサービス共有、電力やNWなどの効率化。
1. クラウドワークロードのダウンストリームの影響を軽減する<br>サービスの利用に必要なエネルギーやリソース量の削減。

# 質問とベストプラクティス
1. SUS1：地域の選択(1)<br>再生可能エネルギー、炭素強度が低いリージョンを選択。
1. SUS2：ユーザの行動パターン(5)<br>ビジネス要件を満たすために必要なリソースの数を最小限にする。
1. SUS3：ソフトウェアとアーキテクチャーのパターン(5)<br>アーキテクチャーを見直して使用率の低いコンポーネントを統合する。
1. SUS4：データパターン(8)<br>より効率的なパフォーマンスのよいストレージを活用し、不要なデータを削除。
1. SUS5：ハードウェアパターン(4)<br>プロビジョニングとハードウェアの量を最小限にする。
1. SUS6：開発と展開のプロセス(4)<br>ワークロードを最新の状態に保つ。

括弧内は質問数。トータル27個。
※詳しく読み込めたらまだアップデートします。


# まとめ
* 環境に目をむける時代がやってきた
* 既存の柱とはちょっと違うので最初は戸惑うかも<br>改善プロセスや非機能要件についても目を通しておきましょう。
* 他の柱とのトレードオフに注意を<br>コストとセキュリティ・可用性と同様、信頼性とサステナビリティ・コストの関係性にも留意を
* 柱の優先度
* W-Aレビューの時間がかかっちゃう
【Flutter】祝日判定

# 内閣府のデータを使って祝日判定
条件分岐で祝日を個別に判定しようと試みましたが、振替休日などの判定が難しく誤った祝日が発生しかねないので、内閣府の祝日データを元に祝日判定を行うことにしました。

## 祝日データをダウンロード

内閣府の祝日データをダウンロード
[https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html](https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html)

## Assetsの読み込み準備

Assetsの読み込みはこちらを参照
[https://docs.flutter.dev/development/ui/assets-and-images](https://docs.flutter.dev/development/ui/assets-and-images)

プロジェクトのディレクトリ直下に`assets`フォルダを作成
`assets`フォルダにダウンロードしたデータをコピー

```:directory
.
├── android
├── assets // 追加
│   └── syukujitsu.csv // 追加
├── build
├── ios
├── lib
│   └── main.dart
├── test
└── pubspec.yaml
```

`pubspec.yaml`に`assets`を記述

```yaml:pubspec.yaml
flutter:
  assets:
    - assets/syukujitsu.csv
```

文字列の日付をDateTimeに置き換える関数

```dart
DateTime stringToDate(String str) {
  List<String> splitDate = str.split('/');
  int year = int.parse(splitDate[0]);
  int month = int.parse(splitDate[1]);
  int day = int.parse(splitDate[2]);
  return DateTime(year, month, day);
}
```

## CSVをDateTime型の配列に変換

デコードにはこのプラグインを使いました。
[https://pub.dev/packages/charset_converter](https://pub.dev/packages/charset_converter)

```dart
import 'package:charset_converter/charset_converter.dart';

Future<List<DateTime>> loadCsv() async {
  // assetsからCSVを読み込んで、ByteDataを取得
  final ByteData byteData = await rootBundle.load('assets/syukujitsu.csv');
  // ByteDataをUint8Listに変換
  final Uint8List uint8List = byteData.buffer.asUint8List();
  // charset_converterでデコード
  final String? decode = await CharsetConverter.decode('cp932', uint8list);
  // 余分な余白を削除
  final String trim = decode!.trim();

  List<HolidayModel> list = [];
  // 改行で分割
  for (String line in trim.split('\r\n')) {
    // コンマで分割
    List<String> rows = line.split(',');
    // ヘッダーを読み飛ばす
    if (rows[0] == '国民の祝日・休日月日' && rows[1] == '国民の祝日・休日名称') continue;
    // 文字列をDateTimeに変換
    DateTime date = stringToDate(rows[0]);
    // 配列に格納
    list.add(date);
  }
  return list;
}
```

`rootBundle.loadString()`で読み込みが出来ればもう少し簡単に文字列での取得ができましたが、文字コードがUTF-8にのみ対応しているみたいなので今回は使えませんでした。
`rootBundle.load()`で`ByteData`で取得して、`Uint8List`へ変換し`CharsetConverter`を使ってデコード。
最後の行に空白があるので、`trim()`で削除して`\r\n`と`,`で分割する。
ヘッダーは必要ないので`continue`で読み飛ばし、文字列の日付を`DateTime`に変換して配列へ格納。

## 祝日を判定

```dart
Future<bool> isHoliday(DateTime date) async {
  // 読み込みの結果を待つ
  var result = await loadCsv();
  for (var i = 0; i < result.length; i++) {
    // 祝日データと引数の日付を比較
    if (DateUtils.isSameDay(result[i], date)) {
      return true;
    } else {
      continue;
    }
  }
  return false;
}
```

```dart
final DateTime date = DateTime(2021, 1, 1);
isHoliday(date).then((result) {
  print('$result'); // true
});
```
【クリぼっちだと宣言するだけのものを作りました】 #クリぼっちーず #クソアプリアドベントカレンダー #クリぼっち #アドベントカレンダー


ただフォームに入力して

クリスマスは１人で過ごします（クリぼっちです）

と投稿するだけのサイトをとにかく作りました。

　　
クリぼっちだということを

ただただ宣言するだけでも

投稿・シェアしてもらえたりすると嬉しいです。



##2021年12月20日追記

#####①. 気に入った投稿を、SNSシェアできるように**アップデート**しました

>**気に入った投稿をシェアした例**
![クリぼっちーずアップデート](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1391827/1c049c6f-5179-e30a-71fa-2ce394bf6519.png)


####②. SQLインジェクションへの対策を行いました

:::note info
SQLインジェクションという攻撃への脆弱性があるとウラルさんに教えていただいて、
セキュリティアップデートを行いました。
:::
---


###ユーザーさんから頂いた投稿の例
>**こんな感じのテキトーな投稿なども歓迎です**
![クリぼっちーずへの投稿の例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1391827/c294f324-e9aa-40d9-4bcb-c772c9106c68.png "クリぼっちーずへの投稿の例")

　　

**その他、投稿例は
[こちらから](https://kuriboccheese.imelabo.site)
👆**


##クソアプリアドベントカレンダー参加のきっかけ

[運営者ギルド](https://qiita.com/organizations/admin-guild) でお世話になっている @2zn01 さんにクソアプリAdventCalendarというイベントがあると教えていただいて
興味を持って参加しました。



##なぜクリぼっちーずを作ったのか

デフォルトが基本クリぼっちなので、パッと思いつきで

ただフォームに入力して
クリぼっちです
と投稿するだけのサイトをとにかく作りました。


入力内容は
1.**ニックネーム**
2.**当日は●●をする予定です**
3.**ひとことコメント**

の３つです。

<font color="#898989">（可能であればネタ的な投稿シェアも歓迎しています）</font>



##どんなふうに作ったか

もともと借りているVPSのLAMP環境、
PHPとJavaScriptで作りました。

フォームに入力した項目が、
ただ表示されるだけのサイトなので、
特筆する点はないかとおもいます。



##つまづいた点
+ 非同期処理
+ Facebookのsharer.phpでシェアボタンを設置して、デフォルトで本文を含めようとしてムダに時間を使ってしまった
+ etc...



##気づいた点

知人にクロスサイトスクリプティングというものがあると教えていただいて
サニタイズという対策をしたり、知らなかったこと・大事なことを知れました。

セキュリティのことをちゃんと勉強しないとです。

ユーザーアカウントやログインを省きたかったので、
セッションでユーザー識別をする範囲でとどまっていますが、作りがテキトー過ぎるのではないか少し気になっています。



##ひとこと

過去の転用でjQueyを惰性的に使っていますが、今後は脱jQueryしていきます。

ちゃんと学んでセキュリティのこともしっかりしていきます。
なにか問題点があればご教示いただけると助かります。

クソアプリAdventCalendar参加をきっかけに、
キリが付けにくくても作業にキリをつけたり、
いつリリースするか決めて取り組むようにやっていきます。



##まとめ

[こんなつまらないもの](https://kuriboccheese.imelabo.site)ですが

**どんなテキトーなことでも**

**投稿してもらえたりすると嬉しいです。**


https://kuriboccheese.imelabo.site


[https://kuriboccheese.imelabo.site](https://kuriboccheese.imelabo.site)
👆
**[クリぼっちーず](https://kuriboccheese.imelabo.site)**
PyQt5 QToolBarを使ってみる

# 内容

サイドメニューの作り方が気になり調べたところ,`QToolBar`を使うと作ることができそうでした。

以下のサイトにサンプルがあったので動かしてみました。

https://www.tutorialspoint.com/pyqt5/pyqt5_qtoolbar_widget.htm

```qtoolbar.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class tooldemo(QMainWindow):
   def __init__(self, parent = None):
      super(tooldemo, self).__init__(parent)
      layout = QVBoxLayout()
      tb = self.addToolBar("File")
		
      new = QAction(QIcon("test.png"),"new",self)
      tb.addAction(new)
		
      open = QAction(QIcon("test.png"),"open",self)
      tb.addAction(open)
      save = QAction(QIcon("test.png"),"save",self)
      tb.addAction(save)
      tb.actionTriggered[QAction].connect(self.toolbtnpressed)
      self.setLayout(layout)
      self.setWindowTitle("toolbar demo")
		
   def toolbtnpressed(self,a):
      print("pressed tool button is",a.text())
		
def main():
   app = QApplication(sys.argv)
   
   ex = tooldemo()
   ex.show()
   sys.exit(app.exec_())
	
if __name__ == '__main__':
   main()
```

# 結果

![Screenshot from 2021-12-04 22-29-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/9cbff017-d72a-40c6-17f3-5752fa57752a.png)

# 解説

`QToolBar`widgetは動かすことが可能で,テキストボタン,アイコンボタン,または他のウィジェットを格納できます。

メソッドの一覧は以下のようになります。

1:`addAction()`:テキストorアイコンを持つツールボタンの追加
2:`addSeperator()`:グループ内のツールボタンを表示?
3:`addWidget()`:ボタン以外のツールバーを加える?
4:`addTooBar()`:QMainWindowクラスがもつツールバーを追加するメソッド?
5:`setMovable()`:ツールバーが移動可能になる
6:`setOrientation()`:ツールバーの方向を設定(Qt.Horizontal または Qt.vertical)

ツールバーのボタンが押されるときには`ActionTriggered()`シグナルが発火されます。そしてQActionオブジェクトもなにかするみたい?

`addToolBar()`メソッドでファイルツールバーを追加

```
tb = self.addToolBar("File")
```

以下でボタンを作成している

```
new = QAction(QIcon("test.png"),"new",self)
tb.addAction(new)
```

# 最後に

QToolBarはQMainWindowクラスが内部で持っていて生成したりするもののようです
Cで書いた自作Lispインタープリタ Lesxeの紹介と感想

この記事は[Lispアドベントカレンダー2021](https://qiita.com/advent-calendar/2021/lisp)の５日目の記事です。

https://github.com/jinhanada/lesxe

後でいろいろ実験するベースになりそうな、できるだけ変に目立った特徴が無いLisp処理系が欲しい、という動機で作りました。

実装について下記の選択をしています。

- できるだけ上から下まで把握しておきたいのでGCは自作。フラグメンテーションに悩まされない、かつ何回も作ったことがあるので[CheneyのコピーGC](https://en.wikipedia.org/wiki/Cheney%27s_algorithm)
- VMベースのLispはいくつか書いたことがあるので、Cなどで書いたことがなかった普通のインタプリタ。インタプリタの方がどれぐらい簡単なのか知りたい
- 末尾呼び出し最適化
- 64bitリトルエンディアン環境固定。データ型は62bit整数・nil・ペア（リスト）・シンボル・配列・バイト配列・文字列
- evalの前にコード変換用のフックを作って、マクロ展開器はLisp自身で書く

[簡単なプロトタイプベースのオブジェクトシステム](https://github.com/jinhanada/lesxe/blob/e5de085e260d04dda2c2b4756d5c3a798e87f300/src/core.le#L983)や[シングルスレッドなのでchromeからアクセスすると応答しなくなるHTTPサーバー](https://github.com/jinhanada/lesxe/blob/e5de085e260d04dda2c2b4756d5c3a798e87f300/example/server.le)などある程度遊べるぐらいには作っています。

## 感想とメモ

同じようなものを作ってみたい人、特に初めて(Lisp)処理系を書いてみたい人の参考になればと思います。

### GCでよく起きたバグ

Copying GCやMark Compactionなどオブジェクトのアドレスが移動するGCの場合、ほとんどのやっかいなバグは、保護し忘れたオブジェクトが誤って回収されることで起きました。Lesxeの場合保護用スタックを使っていますが、大抵の場合はpushし忘れです。

そういったバグは、回収されてしまったオブジェクトへGCのちょっと後にアクセスすることで起きます。そのため、原因となる場所の特定が面倒です。

デバッグの際は下記を参考にしてみて下さい。

- できるだけ小さい関数に小分けして一度に扱う保護すべきオブジェクト数を減らす。長いところは怪しい
- アドレスを他の変数に代入して、片方だけ保護し忘れてないか？そういうところは怪しい
- Lisp（ターゲット言語）ではなくC（ホスト言語）のevalなどから場所を絞り込んだ方が早いかも


### VM(+コンパイラ)とインタプリタどっちが楽か

予想通りインタプリタの方が楽でした。ただ、コアの部分(VM/インタプリタ）はあまり変わりません。ASTの操作vsバイトコードの操作など、どちらかというとVMの方が楽な場面も多いです。

しかし、VM(+コンパイラ)の場合、どれもセルフホスティングにしましたが、コンパイラ自体を改良するときに現在のコンパイラが壊れないように気をつけないといけないのが面倒になってしまいました。結局全て放置しています。

VMを採用する場合、ある程度はVMのホスト言語でコンパイラを書いてしまったほうが楽かもしれません。

VMは[SECDマシン](https://ja.wikipedia.org/wiki/SECD%E3%83%9E%E3%82%B7%E3%83%B3)をアセンブリとCで、[3impのスタックVM](https://www.cs.unm.edu/~williams/cs491/three-imp.pdf)をCで書いたことがありますが、初めてのVMならSECDを先に作ってみるのがオススメです。後者を理解しやすくなりました。


## 今後

下記をやれたらやるか〜と考えています。

- [tgc](https://github.com/orangeduck/tgc)を参考にConservative GCを書いてみる
- インタプリタから「徐々に」VMへ切り替えていけるか試してみる
- アセンブリで書き直してみる
- [Scheme(Gauche)で書いたシンセ・音楽生成スクリプト](https://github.com/jinhanada/sanmai-scm)をLesxeで書き直して処理系高速化・ライブラリ充実の動機を作る
Atcoder 解答例 AGC 013 A - Sorted Arrays

#AGC 013 A - Sorted Arrays 解答例
問題は[こちら](https://atcoder.jp/contests/agc013/tasks/agc013_a)

解答例が見当たらなかったため、備忘録がてら投稿します。
何かアドバイスがあれば気軽にコメントください。


```C++
#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>

using namespace std;


int main() {
	int N;
	cin >> N;

	int A[100001];
	int split_count = 0;

	for (int i = 0; i < N; i++) {
		cin >> A[i];
	}

	bool is_up = false;
	bool is_down = false;

	for (int i = 0; i < N-1; i++) {
		if (A[i] - A[i + 1] < 0) {
			is_up = true;
		}
		else if (A[i] - A[i + 1] > 0) {
			is_down = true;
		}

		if (is_up == true && is_down == true) {
			split_count++;
			is_up = false;
			is_down = false;
		}
	}

	cout << split_count + 1 << endl;

	return 0;
}
```
fluent bitのタグってなんだ？

この記事は　[ZOZO #3 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/zozo) 7日目の記事になります。

これまでFfluent bitなど使ったこともなかったのですが、このたび、AWS ECSからのログ送信のためにfluent bitを使うことになり最も苦戦したところを紹介します。

ユースケースとては以下の通り。
1. コンテナベースのサービスであるECSを使う限り、ログは外部に送信する必要がある。
2. ログはDatadog及び、社内で管理できる箇所の２箇所に送信する。fluent bitから2箇所にOutputする処理をしている。
3. 問題は個人情報。社内で管理できる場所はともかく、Datadogなどの外部サービスには出したくないのでこちらのみ個人情報をマスクして送信したい。


マスク自体はfluent bitではlua言語を使ってログを加工することができるので、問題ありません。ただ、普通にマスクして流すとDatadogはもちろん、もう一箇所の方にもマスクした情報が流れてしまいます。なんとかしたい。


そこで便利なのが、タグ機能。普通タグといえば、ブログのタグみたいなものを思い浮かべますが、fluent bitでタグを打つと、タグ別にログを複製するらしく、この機能を使ってDatadogに流す用のタグだけにマスク処理をかけるということができます。

これflent bitのドキュメントから全然見つけられずかなり苦労しました。。。
confファイルはこんな感じになります。

```conf
[FILTER]
    Match *
    Rule * masked true # ここでmaskedというタグを打つ。タグがないログとmaskedというタグが付いたログの２つログができる。

[FILTER]
    Name         lua
    Match        masked # maskedが付いたタグのログだけにマスク処理をかける
    script       /mask.lua
    call         mask

[OUTPUT]
    Name         datadog
    Match        masked # maskedが付いたタグのログだけdatadogに流す

[OUTPUT]
    Name         xxxxx
    Match_Regex  ^(?!.*masked).+$　#　 maskedが付いていないログをもう一方に流す
```

ご参考まで。
次の日も自分ですね。localstackがあれば大体何でもローカルでAWS開発ができるというタイトルでお届けします。
【Linux小ネタ】teeコマンドとリダイレクト〜標準入出力、パイプ〜

#前提条件

**OS**
 MacOS Monterey 12.0.1
**CPU**
 Apple M1(arm64) 
**Docker**
Docker Desktop 4.2.0 (70708) 
**CentOS**
CentOS Linux release 7.9.2009 (AltArch)

#この記事の内容
ほんの備忘録です。
実行結果を画面とファイルに出力する「tee」コマンドと、標準入出力を変える「リダイレクト」を、同じ状況で検証・比較するものです。

DockerでCentOS環境を構築し、Linuxコマンドの基礎勉強をやっています。
下記参考文献にある教科書で練習をしていて、簡単にまとめたかったので記事にしました。

#やりたいこと

単語の羅列であるファイルの中から「app」を含む部分（大文字・小文字の別は不問）を検索し、その結果を新しいファイルに出力する

#手順

まず、実験用のファイルを作ります。内容はこんな感じ。

```
[Qiita@0a412e1af0a1 ~]$ cat bunsyo1.txt
sam
101
Apple
samp21
APPLE
apple
Linux
test
PINEAPPLE
```

**１　リダイレクトを使う場合**

```
[Qiita@0a412e1af0a1 ~]$ grep -i app bunsyo1.txt > apple.txt
```

大文字・小文字を区別せず検索するため、grepにはiオプションをつけます。

`> apple.txt`
標準出力を、ディスプレイからファイルに切り替えます。
（ここでは出力するファイルとして「apple.txt」を新規作成します。）

出力されたファイルの中身を確かめます。

```
[Qiita@0a412e1af0a1 ~]$ cat apple.txt
Apple
APPLE
apple
PINEAPPLE
```
（ちなみに・・・）

```
[Qiita@0a412e1af0a1 ~]$ grep -i app bunsyo1.txt > apple.txt | cat apple.txt
[Qiita@0a412e1af0a1 ~]$ 
```
`| cat apple.txt`
パイプの後にcatを記述しても画面出力はされません。
リダイレクトで出力先をディスプレイでなくファイルとしているので、当然といえば当然ですね笑
すいませんでした（）


**２　teeコマンドとパイプを使う場合**


一旦、rmコマンドで出力されたapple.txtを削除してから試してみます。

```
[Qiita@0a412e1af0a1 ~]$ grep -i app bunsyo1.txt | tee apple.txt 
Apple
APPLE
apple
PINEAPPLE
```
**出力されたファイルの中身自体は同じ結果となります。**


teeコマンドは、実行結果を「画面」と「ファイル」に出力してくれます。

（公式マニュアル記載　抜粋）
`The  tee  utility  shall  copy  standard input to standard output, making a copy in zero or more files. `

・標準入力（キーボードから入力されたコマンドの実行結果）の内容を標準出力（ディスプレイ）にコピーする
・コピーは別ファイルに作成することもできる（今回でいうapple.txt）

といった趣旨のことが書いてありますね。

#参考文献

https://www.amazon.co.jp/%E3%81%95%E3%82%8F%E3%81%A3%E3%81%A6%E5%AD%A6%E3%81%B6-Linux%E5%85%A5%E9%96%80%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-%E8%B5%A4%E6%98%9F%E3%83%AA%E3%83%8A/dp/4839969019
Tableau Publicで統計データの傾向を見る時に使う機能：「消費支出」と「ネットショッピングの支出額」


##生活費とネットにかけるお金
**[家計調査報告](https://www.stat.go.jp/data/kakei/sokuhou/tsuki/index.html) と[家計消費状況調査](https://www.stat.go.jp/data/joukyou/index.html)**は、ともに総務省統計局が毎月調査結果を更新しています。
両社の違いはよくわかりませんが、それぞれが報告している月の生活費**「消費支出」**と、**「ネットショッピングの支出額」**をのデータをマージして並べると、ネットの利用の広がりが顕著になります。
**「Tableau Public」**や**「Power BI Desktop」**を使い、たまに推移を確認しています。

下記画面は、Tableau Publicを使った推移です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/5c65e173-9c31-f765-9a30-2c61dfc86736.png)

データラベルは、最小値と最大値を示しています。

##傾向線

月によって変動が大きいので、傾向を確認したい場合、例えば**「傾向線」**を使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/5e499f26-f160-78b1-3625-2688810ed6bc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/44b05b70-8d11-c256-6015-42e1614eaefa.png)

##移動平均

**「移動平均」**も使います。
**「簡易計算表」**から**「移動平均」**を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/097ecc8b-20c1-9dd0-2e21-4796160c8ed4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/e9dfb94c-d754-8212-3fb3-01d4c4b88e6e.png)

デフォルトでは「2カ月間の移動平均」のようです。
配置したフィールドをダブルクリックすると計算式を編集できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/59e3ed65-be45-b66e-abcf-848603ad080b.png)

```
WINDOW_AVG(AVG([インターネット支出]), -2, 0)
```

6カ月単位の移動平均に変更します。

```
WINDOW_AVG(AVG([インターネット支出]), -6, 0)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/5a408278-61e3-3de9-2ca5-36f0a3ae6892.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0ad730a0-9756-c7f9-2c99-d814b26d000c.png)

##前年同月比

**「前年同月比」**で見ることもあります。
この場合、x軸を（YYYYを外し）「月」表示にし、「年」ごとの推移を描きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/a847f733-b9f8-5659-0af7-109fe81339c9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/f4f262af-6971-7fb1-d3f1-9144cfd2fc6f.png)

**「簡易計算表」**から**「前年比成長率」**を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/25ce224d-a2ed-85c5-e72b-ef24f540cb86.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/3b097758-8e1f-5072-aa67-4dbefa4ef2b0.png)

見やすくするように、グラフを上下に分けました。
2019年、2020年、2021年の3種類の前年同月比グラフを表示するように指定し、かつ色も年ごとに変えました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0d002b04-1ba7-ed17-7e96-f0a8963cce15.png)

**了**
【React】useRefの基本的な使い方・活用術・注意点

おはこんばんちは、[@ちーず](https://qiita.com/cheez921)です。
アドベントカレンダー4日目、本日のテーマは`useRef`です！！

## `useRef`とは

`useRef`とは、参照を保持するためのhookです。

```jsx
// 変数名 = useRef(初期値)
const ref = useRef(initialValue)
```

`useRef`はとてもシンプルな設計で、
Refオブジェクト(`{current: initialValue}`) を生成して、その値をメモ化しているだけです。

値の取り出し、変更は下記のように書きます。

```jsx
// 設定した値を取り出す
const value = ref.current;

// 値を変更する
const ref.current = 2;
```

つまり、`ref.current`の値を変更させているだけなので
**再レンダリングが走らない**です。

これが、`useRef`の最大の特徴です。

▼ 参考

https://qiita.com/seira/items/0e6a2d835f1afb50544

## `useRef`の活用術

### DOMに対する参照
圧倒的にこの使われ方が多い`useRef`ですが、
HTML要素に`ref`という属性で`useRef`の値を渡してあげることで参照できます。

```jsx
// useRefの型
// interface MutableRefObject<T> {
//  current: T;
// }
// function useRef<T>(initialValue: T): MutableRefObject<T>;

export const InputComponent = () => {
  const inputElement = useRef<HTMLInputElement>(null)

  return <input ref={inputElement}/>
}
```

これだけで、
`inputElement.current.focus()`でフォーカスさせたり、
`inputElement.current.offsetHeight`で高さを取得したりすることができます。


### 値に対する参照
9割くらいDOMの参照として使われているイメージですが、値に対して使うケースもあります。

#### 一回のみ実行したい

再レンダリングが発生しない点を利用して、
一回のみ実行したい処理があった時の制御で`useRef`を使うことができます。

```jsx
const once = useRef(true);

useEffect(() => {
 if (!once.current) return;
 // 実行したい処理
 once.current = false;
}, [])
```


#### `useState`の前の値を保持する
公式ドキュメントにも記載がありますが、前の値を保持する時に`useRef`を使います。

https://ja.reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state


```jsx
const [count, setCount] = useState(0);
 
const prevCountRef = useRef();
useEffect(() => {
  prevCountRef.current = count;
});

const prevCount = prevCountRef.current;
```

どのような仕組みで前の値が保持されているかは、下記の記事にてとてもわかりやすく説明されていたため、参考にしてください。
 
▼ 参考

https://blog.logrocket.com/how-to-get-previous-props-state-with-react-hooks/


## `useRef`の注意点

### `useEffect`の第二引数にいれても、変更を検知しない
今までの話を通して、「そりゃそうだろ！！」 と思うかもしれませんが

たとえ第二引数に`ref.current`を書いたとしても、
再レンダリングが起きないため、値が変更しても検知できません。

```jsx

export const InputComponent = () => {
  const inputElement = useRef<HTMLInputElement>(null)

  useEffect(() => {
    if(inputElement.current) {
      // 実行したい処理   
    }
  }, [inputElement.current]);
  

  return <input ref={inputElement}/>
}

```

しかし、初期状態でマウントされておらず、nullになり続けてしまうケースもあるでしょう。
そのような時は、コールバックRefが使えるかもしれません。
(自分は使ったことがいまのところないです。)

https://ja.reactjs.org/docs/refs-and-the-dom.html#callback-refs

---

以上、「useRefの基本的な使い方と活用術」でした！
vueがリアクティブにならない場合


これは結構ハマりやすそう

<h3>エラー例</h3>

配列の中身を表示するシンプルなプログラム
ボタンをクリックすると配列の２番目が「青 → 緑」に変更する

```javascript
<template>
  <div>
    <button @click="fun">ボタン</button>
    <div v-for="(data, index) in datas" :key="index">
      {{data}}
    </div>
  </div>
</template>

<script>
export default {
  data(){
    return{
      datas:["赤","青","黄",]
    }
  },

  methods:{
    fun(){
      this.datas[1]="緑"
      console.log(this.datas)
    }
  }
};
</script>

```

が動かない。

コンソールを見ると配列は

```
['赤', '緑', '黄']
```

ちゃんと変わっている。

<h3>正しい例</h3>

<a href=https://jp.vuejs.org/v2/guide/reactivity.html">公式ドキュメント</a>を見ると（配列に関してのところ）この書き方では、変更を検知できないらしい。

色々やり方はあると思うが一例として[set]を使ってみる。

```javascript
<template>
  <div>
    <button @click="fun">ボタン</button>
    <div v-for="(data, index) in datas" :key="index">
      {{data}}
    </div>
  </div>
</template>

<script>
export default {
  data(){
    return{
      datas:["赤","青","黄",]
    }
  },

  methods:{
    fun(){
      this.$set(this.datas, 1, "緑");
      console.log(this.datas)
    }
  }
};
</script>


```

なんでリアクティブに変更されないかと思った時は、これを疑った方がいいかも
SixtyFPS用のneovim設定を整える

## はじめに

[SixtyFPS](https://sixtyfps.io/)を少しだけ触り始めたのでnvim設定を整えておきます。

## 環境等
Rust 1.56.1 stable
MacOSX 11.6 (Intel Mac)
SixtyFPS 0.1.5
neovim 0.6.0

## sixtyfpsのvim拡張

[sixtyfps-vim](https://github.com/RustemB/sixtyfps-vim)をインストールする。

```vim:init.vim
call plug#begin('~/.config/nvim/plugged')
Plug 'RustemB/sixtyfps-vim'
call plug#end()
```

## LSP

`sixtyfps-lsp`をインストールして `coc-settings.json` に設定を追加するだけ。

```shell-session
$ cargo install sixtyfps-lsp
```

```json:coc-settings.json
{
  "thisiscomment": "以下を追加",
  "languageserver": {
    "sixtyfps": {
      "command": "sixtyfps-lsp",
      "filetypes": ["sixtyfps"]
    }
  }
}
```

## 結果
before:
![sixtyfps-neovim-settings-before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1775/21bee2ba-7c83-cf45-10cf-e693f17469ac.png)


after:
![sixtyfps-neovim-settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1775/eda5579d-6504-fa82-f188-1421733cc911.png)

いい感じにシンタックスハイライトと補完効くようになりました。
SegamakerのDirectマルチコンテナエンドポイントを構築してみる


# 背景
* 独自コンテナより推論エンドポイント
* 複数モデル
* コストを考えている


# 自動インフラ構築

*  InferenceExecutionConfig: { Mode: 'Direct' }の設定はAWS Consoleに設定できない、デフォルトは{ Mode: 'Serial' }で、推論パイプラインになる

```
  Model:
    Type: "AWS::SageMaker::Model"
    Properties:
      InferenceExecutionConfig: 
        Mode: 'Direct'
      Containers:
        - ContainerHostname: 'aaa'
          Image: !FindInMap [ConfigMap, !Ref EnvType, Image]
          Mode: 'SingleModel'
          ModelDataUrl: 's3://xxx'
        - ContainerHostname: 'bbb'
          Image: !FindInMap [ConfigMap, !Ref EnvType, Image]
          Mode: 'SingleModel'
          ModelDataUrl: 's3://yyy'
      ExecutionRoleArn: 'arn:aws:iam::xxx:role/xxxx'
```

# 独自コンテナ変更
* 以下のラベルをDockerfileに追加
    * LABEL com.amazonaws.sagemaker.capabilities.accept-bind-to-port=true
* 8080 番ポートではなく、SAGEMAKER_BIND_TO_PORT の環境変数のポートを使用している

```
print(os.environ.get("SAGEMAKER_BIND_TO_PORT"))
filename = '/opt/program/nginx_copy.conf'
with open(filename, 'r') as f:
    fileText = f.read()
    after = fileText.replace('SAGEMAKER_BIND_TO_PORT', os.environ.get("SAGEMAKER_BIND_TO_PORT"))
    print(after)
filename = '/opt/program/nginx.conf'
with open(filename, 'w') as f:
    f.write(after)
```

# 気になること
* ml.g4dn系とml.inf1系のインスタンスは、Directマルチコンテナエンドポイントへサポートしていない

# 感想
* マルチモデルの場合は、独自コンテナのソースコードを修正しないといけない
* マルチコンテナの場合は、Dockerfileとnginxのみ修正してOK
* 単一コンテナより低い負荷の場合は一つのインスタンスの価格で複数モデルへ対応できる
AOJトライに関する知識知見の記録共有：Volume0-0054

# タスク概要

Sum of Nth decimal places

https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0054
 
# コード実装例
TIPS

1. 例外処理含む評価パターンを追加
1. 素数5に着目し高速化

```Python
import pprint, sys, time
import sympy

def core(arg, acc=True):
    if acc:
        prime_factors = {n: sympy.factorint(n) for n in range(2, arg) if n % 5 == 0}
        ret = [sum([prime_factors[v][5] for v in prime_factors if 5 in prime_factors[v]])]
    else:
        prime_factors = {n: sympy.factorint(n) for n in range(2, arg)}
        ret = [sum([prime_factors[v][n] for v in prime_factors if n in prime_factors[v]]) for n in [2, 5]]
    return ret

def app(*args):
    ret = []
    for arg in args:
        st = time.time()
        try:
            r = core(arg)
        except Exception as e:
            r = e
        ret.append([arg, round(time.time() - st, 6), r])
    return ret

print(sys.version)
pprint.pprint(app(
    # basic examples
    2, 12, 10000, 
    # additional examples
    4,
    # exceptional examples
    "例外入力"
))
```

# 実行結果
各種補足情報出力（入力値FB、デバッグログ等）含む

```Python
3.8.10 (default, Jun  2 2021, 10:49:15) 
[GCC 9.4.0]
[[2, 5e-06, [0]],
 [12, 2.6e-05, [2]],
 [10000, 0.009006, [2495]],
 [4, 5e-06, [0]],
 ['例外入力', 4e-06, TypeError("'str' object cannot be interpreted as an integer")]]
```

# 補遺
残課題

1. 実行速度の改善（枝刈り、データ構造の見直し等）