OmniAICreator/Qiita-1.07M huggingface dataset:
Carbonを使ってみる

環境
初書：2020/09/04
PC：macOS 10.15.6
php 7.4.9
Composer： v1.10.10
carbon： v2.39

# Carbonとは
時間関係の処理をまとめてくれるライブラリ

https://carbon.nesbot.com/

# インストール
※[composerは設定済み](https://qiita.com/yuu_1st/items/23aa44584c2f1f80fbd4)として話を進めていく

ターミナルで以下を実行する

```zsh
% composer require nesbot/carbon
```

# 使い方
newするだけ。

```php:index.php
use Carbon\Carbon;

$time = new Carbon();
echo $time; //2020-09-04 16:00:21
echo Carbon::now(); // 2020-09-04 16:00:21。この場合はnewすらする必要はない
```
なお、タイムゾーンは```date_default_timezone_set('Asia/Tokyo');```で設定できる。
（…が、これで設定してもいいのだろうか？）

主な使い方については下記ページの方がまとめてくれているので、こちらを参考に。。。

[PHPで日付時刻処理を書くならCarbonを使うべき](https://qiita.com/yudsuzuk/items/ff894bd0b76d4657741d)

追記：ミリ秒の取得方法だけ見当たらなかったので記述

```php
$time = new Carbon();
echo $time . "." . substr("00000".$time->micro, -6 , 3); // 2020-09-04 21:44:19.592
```


# テストする場合
開発環境で、一時間ずらしたり、一日ずらしたりする必要がある時

```php
$knownDate = Carbon::create(2020, 9, 1, 11, 26, 13);
Carbon::setTestNow($knownDate);

echo Carbon::now(); //2020-09-01 11:26:13
```
こんな感じで、```Carbon::setTestNow```に指定したい日時を入れるとその時間帯に変更してくれる。

ただし、時間が完全に固定されるため、時間がかかることを想定している場合での使用には使えない。

```php
echo Carbon::now(); // 2020-09-04 16:30:49
sleep(10);
echo Carbon::now(); // 2020-09-04 16:30:59

$knownDate = Carbon::create(2020, 9, 1, 11, 26, 13);
Carbon::setTestNow($knownDate);

echo Carbon::now(); // 2020-09-01 11:26:13
sleep(10);
echo Carbon::now(); // 2020-09-01 11:26:13

```

# 終わりに
公式サイトをみると、かなり色んな日付計算ができるみたいなので、一度見てみてもいいかもしれない（全部英語だけど）
https://carbon.nesbot.com/docs/#api-week
batファイルでpythonスクリプトを動かす備忘録




#windows環境で

・batファイルにしたら極力黒画面をいじらなくて済む
・事前にpythonのpathを環境変数で指定しておく必要あり




#任意のフォルダ内にbatファイル(.bat)作って置く


```
cd /d %~dp0

python test.py
pause
```

#任意の処理をpythonファイル(test.py)にする


```python
from sklearn.datasets import load_iris
import pandas as pd
import seaborn as sns

iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['target'] = iris.target
img1 = sns.lmplot('sepal length (cm)','sepal width (cm)',data=df,hue='target')
img1.savefig("out_img1/img1.png")
img2 = sns.pairplot(df, hue="target")
img2.savefig("out_img2/img2.png")

```


今回は任意のフォルダ内にout_img1と2の名前を付けたサブフォルダを用意した。
出力は指定したサブフォルダへ出力される。

batファイルとpyファイルを同じフォルダ内に置いてbatを実行

#以上
Amazon S3 互換の Wasabi hot cloud strage を使う

NTTPCコミュニケーションズのwebarenavpsを利用しているが、[AmazonS3互換かつ低価格な、Wasabiオブジェクトストレージ]の無料キャンペーンがあったので、Wasabiを使ってみた。

- WebARENA Wasabi オブジェクトストレージ最大1TB分相等額（税込834円/月）が年内無料
- データの保管先は、NTTPCではなくWasabiのサーバで国内にはない
- S3互換なので、awscliからアクセス可能（一手間必要）
- ブラウザから直接ファイル参照ができる。動画も配信できる。!!!
- AmazonS3は、データ保存量に加え転送量でも課金されるが、Wasabiは転送量課金がなく、データ保存量課金のみ。そして834円/月・1TB。年額10,008円


# Wasabiのアカウント作成
キャンペーン案内メールに従い応募したら、アカウント作成用の情報がメールできたので、これで自分専用のサブユーザを作成した、

* WasabiURL: https://console.wasabisys.com/#/subuserLogin
* ルートアカウントメール又はエイリアス： 57211976d4c94665a404846fc60acd2a@ecl.ntt.com
* サブユーザー名：xxxxx
* パスワード：xxxxx(初期パスワード)

# ストレージを利用するためのユーザを作成
[ここを参考に] (https://magnets.jp/web_design/webservice/11009/)

- Bucket : オブジェクト（ファイル）を格納する場所。名前はWasabiユーザをまたがって一意のようで、`test`などのアリアリの名前は already exist を言われ作成できない。また、Bucketをpublic公開すると、httpsでアクセスできるようになるが、その際のurl中のパス名になる。
- Policy : User に Policy を割当て(attached)することで、Bucket と User のアクセスコントロールをする
- User : s3fs,awscliなどでアクセスする際に使用するユーザを作成する。実際にはユーザ名ではなく、ユーザに紐づく鍵情報を設置する。

UserにPolicyが割当てされ、このPolicyでUserがどのBucketにアクセスできる、決まる。

# 実際に使ってみる
## Wasabiコンソール
https://console.wasabisys.com/ にアクセスすると、ブラウザからファイルのUPLOAD/DOWNLOADができる

## DISKマウントして使う :: s3fs 
### s3fsのインストール
 [ここを参考に](https://qiita.com/srockstyle/items/05f125ef92e12dff38f4) s3fsをインストール。

### アクセスキーの設定
```echo "bucketName:accessKeyId:secretAccessKey" > ~/.passwd-s3fs``` の形式でアクセスキー情報を設定。
```chmod 600 ~/.passwd-s3fs``` もやる。

### raspbianでエラー
 macosでは発生しなかったが、raspbian(raspi2)ではこんなエラーが出た。
[ここを参考に対処](https://github.com/s3fs-fuse/s3fs-fuse/issues/347)

```bash
s3fs: There is no enough disk space for used as cache(or temporary) directory by s3fs.

# mkdir /var/s3fs_cache
# s3fs -o noatime,use_cache=/tmp/s3fs_cache BUCKET-NAME /mnt/s3fs/
```

## マウント（アンマウント）する
```bash:マウント
$ mkdir /MOUNT/DIR
$ s3fs BUCKETNAME /MOUNT/DIR -o passwd_file=/PASSWD/DIR/.passwd-s3fs -o url=https://s3.us-west-1.wasabisys.com
```

url の us-west-1 はBucketを作成するリージョンにより異なります。

```bash:アンマウント
fusermount -u /MOUNT/DIR
```

# アクセスする

| アクセス方法 | コマンド |
| :-- | :-- |
| s3fs でマウント | s3fs BUCKETNAME /MOUNT/DIR -o passwd_file=/PASSWD/DIR/.passwd-s3fs -o url=https://s3.us-west-1.wasabisys.com |
| ブラウザ | https://s3.us-west-1.wasabisys.com/BICKETNAME/DIR/FINENAME ※１ |
| ブラウザコンソール | https://console.wasabisys.com/ | 

※１：ファイルをpublic公開にする必要があります。
numpy 機能を自前ライブラリで対応したい用の numpy ソースコードのメモ

# 背景

* numpy の機能を自前ライブラリ(e.g. C/C++)でも対応したい.
  * 乱数や SVD とか
  * スマホ(Android/iOS)に移植して動かしたいとか.
* numpy の一部機能を GPU(e.g. CUDA, OpenCL)で処理したい
  * プロトタイプなどは numpy(CPU)で行い, 実戦では GPU で高速, 大規模処理したいとか
  
## 情報

https://github.com/numpy/numpy

## 概要

ndarray については調べれば他に記事ありますし, C/C++ で numpy っぽい ndarray ライブラリもいくつかありますので省きます.

linalg とか fft とかの話をします.

全部自前で実装しています(依存ライブラリなし).
ただ, 高速化用に third party library(e.g. Intel MKL)も利用できるようになっています.
また, 一部は python テンプレートとかから .c 生成などしています.

インターフェイスは python ですが, 処理が重たいような実装は C で処理しています.
native code 部分は全部 C です. C++ は利用されていません.

binding は, 基本は素の Python C API を呼んでいますが, random 関連は Cython を利用しています. したがって numpy のビルドには cython が必要になります.

基本, 依存ライブラリが無いため, ビルド自体は Linux では比較的簡単です. Ryzen9 3950X でだいたい 3~4 分でビルドできました.

Windows だとビルド面倒かもしれません.

### linalg
 
線形代数ライブラリ. 実装は lapack lite(blas 付き)が標準であります(fortran から f2c で C に変換?).

コンパイルオプションで, 最適化 Blas/Lapack を使うことができるようになっています.

https://github.com/numpy/numpy/blob/master/doc/source/user/building.rst#accelerated-blaslapack-libraries

### random

乱数. poisson 分布など自前で実装しています.

疑似乱数生成アルゴリズムは MT(Mersenne Twister)がデフォルトっぽそうですが, 最近はやりの PCG(pcg64) もあります.

### fft

1.17 から pocketfft(fftpack をベースに numpy 用に自前最適化)が利用されています.

https://numpy.org/devdocs/release/1.17.0-notes.html

pocketfft 自体はポータブルなので, pocketfft だけ抜き出して利用もできます.

音声, 信号処理系ライブラリ nanosnap でも FFT には pocketfft を利用しています.

https://github.com/lighttransport/nanosnap

### Masked array

`numpy/lib/ma` にあります.

通常の ndarary とは実装が別のようです.

### polynomial

多項式.
実装は pure Python のようです.

### シリアライズ, デシリアライズ

`numpy/lib/npyio` にあります. python レイヤーで処理しています.
pickle も利用できるようですが, 非推奨になっています.

### einsum

T.B.W.

## matrixlib

`numpy/matrixlib`

行列クラスですが, 最新 numpy ではもうあまり必要がないっぽい機能のようです.

## umath(Universal math?)

最近では _multiarray_umath に変わっています.

ソースコードには特に記述がないのですが, umath = ufunc 形式の math(ufunc = universal function) = universal math っぽいようです.

https://numpy.org/doc/stable/reference/ufuncs.html

基本的には配列などに一括して適用して処理を早くする感じです.
python のテンプレートから .c を吐いています.

昔は別パッケージだったようで, import error の原因にもなっています.

https://github.com/numpy/numpy/issues/11871

### 自前 ufunc

Writing your own ufunc
https://numpy.org/doc/stable/user/c-info.ufunc-tutorial.html


## まとめ

fft や random あたりは移植や機能切り出し用意でしょうが, ufunc(umath) や Pure python な部分はめんどそうです(e.g. polynomial, einsum)
Cloud Toolkitを使用したECSインスタンスへのNode.jsアプリケーションのデプロイ

この記事では、Cloud Toolkitを使って**Alibaba Cloud ECSインスタンス**に**Node.js**アプリケーションをデプロイする方法を紹介します。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/deploying-a-node-js-application-to-an-ecs-instance_594819)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

前回の記事では、Alibaba Cloud [Elastic Compute Service (ECS) ](https://www.alibabacloud.com/ja/product/ecs)インスタンスに直接ローカル Java アプリケーションをデプロイする方法について説明し、読者から多くのフィードバックをいただきました。そこで、読者からの質問に答えるために、今回の記事ではさらに、Alibaba Cloud ECSインスタンスにNode.jsアプリケーションをデプロイする方法をご紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/6cdb4998-36cf-41d4-eb2b-e042bcb7a3f1.png)

#ローカルでアプリケーションを開発する
この記事では、Webページに「Hello World」を印刷するNode.jsアプリケーションを例に、デプロイ方法を解説します。

```
const http = require('http');
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Alibaba Cloud Toolkit: Hello World');
});
server.listen(port, '0.0.0.0', () => {});
```

前述のコードは、Webページに「Hello World」という文字列を表示するための標準的なNode.jsプロジェクトです。

#プラグインのインストール
Alibaba Cloudは、開発者がローカルIDEで書かれたアプリケーションをECSインスタンスに効率的にデプロイできるようにするEclipseベースのプラグインを提供しています。

プラグインのURL: [https://www.aliyun.com/product/cloudtoolkit_en](https://www.aliyun.com/product/cloudtoolkit_en?spm=a2c65.11461447.0.0.3f6b2416dr44th)

このEclipseベースのプラグインのインストール手順は、一般的なプラグインと似ているため、ここでは詳細を説明しません。

#プラグインの環境設定
プラグインをインストールしたら、選択して環境設定を行います。

トップメニュー > ウィンドウ > 環境設定 > Alibaba Cloud Toolkit > アカウント

以下のページが表示されたら、Alibaba CloudアカウントのAKとSKを設定して、環境設定の設定は完了です(RAMユーザーアカウントを使用している場合は、RAMユーザーのAKとSKを入力してください)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/7780e5bf-2a25-5ad1-2d6c-b0f33b7d009e.png)


#アプリケーションのデプロイ
Eclipseでプロジェクト名を右クリックし、ショートカットメニューからAlibaba Cloud > Deploy to ECSを選択します。以下のようなデプロイ画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/b359f0b5-f4be-1aa4-da0d-af7f6a69e870.png)

デプロイメント設定ダイアログボックスで、デプロイメントパラメータを設定し、デプロイをクリックして初期デプロイを完了します。

/root/nodejs-demo/restart.shファイルには、以下の内容が含まれています。


```
source ~/.bash_profile
killall node
nohup node /root/nodejs-demo/helloworld.js > nohup.log 2>&1 &
```

#配置パラメータの説明
- Deploy File: 2つのオプションがあります。オプションのUpload FileはNode.jsプロジェクトで使用します。
- Maven ビルド：現在のプロジェクトのビルドに Maven を使用している場合、Alibaba Cloud Toolkit を使用してアプリケーションを直接ビルドしてデプロイすることができます。
- ファイルのアップロード: 現在のプロジェクトのビルドにMavenを使用していない場合、またはローカルにパッケージ化されたデプロイファイルが既に存在する場合、ローカルのデプロイファイルを選択して直接アップロードすることができます。
- デプロイする ECSの選択：ドロップダウン リストからリージョンを選択し、そのリージョンにデプロイするECSインスタンスを選択します。
- デプロイ先の場所：ECS インスタンス上のデプロイパスを入力します。
- コマンド：アプリケーションの起動コマンドを入力します。このパラメータは、デプロイが完了した後に実行するコマンドを指定します。Node.js プログラムの場合、通常は起動コマンド node XXX.js です。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*
CronJobの更新

#はじめに
KubernetesのCronJobの更新を実施した際の動きについてのメモです。

#結論
Jobが起動している状態で、新しいイメージを指定してCronJobを更新した場合、既存のJobが削除されることはない。
CronJob自体を削除すると、Jobも削除される。

#確認
CronJobを作成します。

```
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster; sleep 600
          restartPolicy: OnFailure
```

```
$ k apply -f cronjob.yaml                                                                                
cronjob.batch/hello created
```

Jobの起動確認

```
$ k get job
NAME               COMPLETIONS   DURATION   AGE
hello-1599204120   0/1           5s         5s
```

コンテナイメージの変更
image: busybox ->image: busybox:uclibc

```
$ k apply -f cronjob.yaml
cronjob.batch/hello configured
```

古いバージョンのJobが起動していることを確認

```
$ k get job
NAME               COMPLETIONS   DURATION   AGE
hello-1599204120   0/1           81s        81s
hello-1599204180   0/1           21s        21s
```

```
$ k get job hello-1599204120 -o yaml | grep image
       image: busybox
$ k get job hello-1599204180 -o yaml | grep image
       image: busybox:uclibc
```

CronJobを削除してみる

```
$ k get job
NAME               COMPLETIONS   DURATION   AGE
hello-1599204120   0/1           9m56s      9m56s
hello-1599204180   0/1           8m56s      8m56s
hello-1599204240   0/1           7m56s      7m56s
hello-1599204300   0/1           6m56s      6m56s
hello-1599204360   0/1           5m56s      5m56s
hello-1599204420   0/1           4m56s      4m56s
hello-1599204480   0/1           3m56s      3m56s
hello-1599204540   0/1           2m55s      2m55s
hello-1599204600   0/1           115s       115s
hello-1599204660   0/1           55s        55s
$ k delete -f cronjob.yaml
cronjob.batch "hello" deleted
atsum@cs-660110948249-default-default-689gh:~/knative$ k get job
No resources found in default namespace.
```
MicroPythonをはじめよう(macOSで)

# はじめに
[こちら](https://qiita.com/exshonda/items/a1b01fee2d9982ef269a)のような方法でWindows上でMicroPythonを使ってました。
けれど、ちょっとだけ試したいときには普段使っているmacOSで動かすことにしました。

#動作確認環境
- OS: macOS Catalina
- ボード：NUCLEO-F401RE

#インストール
1. ボードをPCに接続　→　ファイルシステムを認識
2. [NUCLEO-F401REのファームウェア](https://github.com/exshonda/enPiTEmbShild_upython/raw/master/bin/NUCLEO_F401RE_ulab.bin)をコピー

#REPL(コンソール/コマンドライン)による実行
screenを使いました。
```screen /dev/tty.usbmodem* 115200```

長く実行しているとフリーズすることがありました。`C-a q` で終了できるように `~/.screenrc`に
```bind q quit```
と書いておきました。

#おわりに
あまりにも簡単で拍子抜けでした。
Spotifyの再生回数ランキングを集計してエクセルに保存する

# はじめに
Spotify、音楽を聴く際に愛用している方も多いことと思います。機能としては非常に便利なのですが、残念なことに再生回数を見ることができません。

その代わりに、Spotifyには再生履歴などの個人データをダウンロードできるサービスがあります。今回はこの個人データを利用して再生回数を集計し、Excelに保存してみたいと思います。`OpenPyXL`というライブラリを使うので、インストールしていない方はあらかじめインストールしておいてください。

なお、今回使用するコードは以下の記事を参考に作成しています。以下の記事を参考に、あらかじめ個人データをダウンロードしておいてください。

参考記事：[Spotifyで再生した曲を、再生回数順に並べる](https://qiita.com/kaiyu0401/items/ea55ab4e49370122ea01)

# コード

```python:count.py
import json
import collections
import openpyxl

# jsonデータの読み込み
with open('StreamingHistory0.json', 'r', encoding='utf-8') as f:
    d = json.load(f)

list = []

search_all = str(input('Search for all? (y/n) >> '))

# 曲名を取り出してリストに追加
# 全体検索
if search_all == "y":
    for i in d:
        list.append(i['trackName'])
# 指定検索
else:
    artist = str(input('Enter the artist name. >> '))
    for i in d:
        if(i['artistName'] == artist):
            list.append(i['trackName'])

# 出現回数順に要素を取得
c = collections.Counter(list)
c_list = c.most_common()

# ワークブックを作成
book = openpyxl.Workbook()

# シートを取得し名前を変更
sheet = book.active
sheet.title = 'Play Count'

#列の長さを曲名に合わせる
max_length = 0

for index, row in enumerate(c_list):
    if index <= 10: #集計する順位
        sheet.append(row)
        if len(row[0]) > max_length:
            max_length = len(row[0])

sheet.column_dimensions['A'].width = max_length

# ワークブックを保存
book.save('SpotifyCount.xlsx')
```
エクセルへの出力以外にも、エンコードの指定や整形をいくつか施してみました。上記のコードでは集計する順位を10位までとしていますが、ここは必要に応じて変更してください。

# 実行結果
全体検索の場合は全体の順位が、指定検索の場合は指定したアーティストの順位がエクセルのシートに記録されていれば成功です。
Ruby 3.0 で変わる Module#include の挙動

[ブログ記事](https://secret-garden.hatenablog.com/entry/2020/09/04/163454)からの転載です。


今日の [RubyKaigi Takeout 2020](https://rubykaigi.org/2020-takeout) の [Ruby Committers vs the World](https://rubykaigi.org/2020-takeout/speakers#rubylangorg) でチラッと話が出たのでちょっとまとめてみます。

* 該当チケット：[Bug #9573: descendants of a module don&#39;t gain its future ancestors, but descendants of a class, do - Ruby master - Ruby Issue Tracking System](https://bugs.ruby-lang.org/issues/9573)


## 注意！！

これはまだ開発版の機能になり Ruby 3.0 がリリースされるタイミングで挙動が変わっている可能性があるので注意してください。


## `Module#include` の変更点

今までは `M.include M2` を行ってもすでに `include M` しているクラス/モジュールの継承リストには反映されませんでした。

```ruby
module M; end

class X
  include M
end
# ここでは M のみ反映されている
p X.ancestors
# => [X, M, Object, Kernel, BasicObject]

module M2; end

# M に対して include してもすでに M を include しているクラス/モジュールの継承リストには反映されない
M.include M2

# M2 は反映されない
p X.ancestors
# => [X, M, Object, Kernel, BasicObject]
```

これが Ruby 3.0 からではすでに `include` されているクラス/モジュールにも反映されるようになります。

```ruby
module M; end

class X
  include M
end
# ここでは M のみ反映されている
p X.ancestors
# => [X, M, Object, Kernel, BasicObject]

module M2; end

# M に対して include すると M を include しているクラス/モジュールにも反映される
M.include M2

# M2 も反映されるようになる
p X.ancestors
# => [X, M, M2, Object, Kernel, BasicObject]
```

これは `prepend` でも同じ挙動になります。
また、これにより（当然ですが）メソッド呼び出しにも影響はあります。

```ruby
module M1
  def hoge; end
end

class X
  include M1
end

# OK
X.new.hoge

module M2
  def foo; end
end
M1.include M2

# 2.7 : error
# 2.8 : OK
X.new.foo
```

この変更自体は結構うれしくて、例えば汎用的なモジュールをあとから `Kernel` に対して `include` できるようになります。

```ruby
module M
  def twice
    self + self
  end
end

Kernel.include M

p "hoge".twice
# 2.7 => error: undefined method `twice' for "hoge":String (NoMethodError)
# 3.0 => "hogehoge"
```

これは便利。


## `Module#include` の変更に対する弊害

弊害というか期待する挙動ではあるんですが以下のようなケースの場合、継承リストに同じモジュールが複数含まれるようになります。

```ruby
class Super
  def hoge
    ["Super#hoge"]
  end
end

module Included
  def hoge
    ["Included#hoge"] + super
  end
end

module Prepended
  def hoge
    ["Prepended#hoge"] + super
  end
end

class X < Super
  include Included
  prepend Prepended

  def hoge
    ["X#hoge"] + super
  end
end

# このあたりは今までどおり期待する挙動
p X.ancestors
# => [Prepended, X, Included, Super, Object, Kernel, BasicObject]

p X.new.hoge
# => ["Prepended#hoge", "X#hoge", "Included#hoge", "Super#hoge"]


module Included2
  def hoge
    ["Included2#hoge"] + super
  end
end

# Ruby 3.0 の変更であとから include した場合でも反映されるようになる
Prepended.include Included2
Included.include Prepended

# Ruby 3.0 だと同じモジュールが複数含まれるようになる…
p X.ancestors
# => [Prepended, X, Included, Super, Object, Kernel, BasicObject]

# 当然 super 経由で同じめそっどが　複数回呼ばれるようになる
p X.new.hoge
# => ["Prepended#hoge", "Included2#hoge", "X#hoge", "Included#hoge", "Prepended#hoge", "Included2#hoge", "Super#hoge"]
```

これは期待する挙動ではあるんですが今までの挙動を知っていると結構ギョッとする挙動になりますねえ。
実際、これに関するバグ報告も来ていました（期待する挙動なのですでに閉じられています。

* [Bug #17038: On master, ancestry edits can lead to duplicates in Module#ancestors - Ruby master - Ruby Issue Tracking System](https://bugs.ruby-lang.org/issues/17038)

と、言う感じで Ruby 3.0 では `Module#include` の挙動が変わる（かもしれない）ので注意してください。
Next.js + Netlifyで作ったサイトにsitemap.xmlを設置する

# 概要
Next.js + Netlifyで作ったサイトにsitemap.xmlを設置しようとしたら多少ハマったのでメモ。

# 環境
next.js 9.5.2

# コード

最終的に動いたコードが以下。
今回加筆したのは2ファイルのみで、とてもシンプルだった。
`./postexport.js`は新しく作成した。

```json:package.json
{
  "name": "サイト名",
  "version": "1.0.0",
  "scripts": {
    "dev": "next -p 8080",
    "build": "next build",
    "export": "next export",
    "deploy": "npm run build && npm run export",
    "postexport": "node ./postexport.js",   //追記
    "start": "next start -p 8080",
    "type-check": "tsc"
  },
...
}
```

```js:./postexport.js
const fs = require('fs');

// ROBOTS.txt
const robotsTxt = `User-agent: *
Sitemap: https://〇〇.com/sitemap.xml
Disallow:`;

fs.writeFile('out/robots.txt', robotsTxt, () => {
  console.log('robots.txt saved!');
});

// SITEMAP.XML
const location = "https://〇〇.com/"
let xmlPaths = `<url>
    <loc>${location}</loc>
    <priority>1.0</priority>
  </url>`;

//ページ名の配列
const page_data = [
  "about",
  "member",
  "gallery",
  "privacy",
  "contact",
];

page_data.map((page_path) => {
  const URL = location + page_path;
  xmlPaths += `
    <url>
      <loc>${URL}</loc>
      <priority>0.5</priority>
    </url>
  `;
});

const sitemapXml = `<?xml version="1.0" encoding="UTF-8"?>
  <urlset
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
    xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
    xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"
    xmlns:geo="http://www.google.com/geo/schemas/sitemap/1.0"
    xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
    xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0"
    xmlns:pagemap="http://www.google.com/schemas/sitemap-pagemap/1.0"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
    xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
  >
    ${xmlPaths}
  </urlset>`;

fs.writeFile('out/sitemap.xml', sitemapXml, () => {
  console.log('sitemap.xml saved!');
});
```

# 参考
https://maferland.com/blog/sitemap-nextjs-netlify-cms
C++で好きなようにソートしたい

C++で自分の思う用にソートしたかったのでメモ。
なにもしないと、

```cpp
vector<int> v;
sort(v.begin(),v.end()); //昇順

vector<string> s;
sort(s.begin(),s.end());//辞書順

vector<pair<int,int>> p; 
sort(p.begin(),p.end());//firstの昇順
```

となる。

これを例えば、<strong>文字数の昇順</strong>にしたいとか、<strong>pairの(first-second)の差の昇順</strong>にしたいとか、いろんな基準でソートしたくなるときがあると思う。

やり方は、sort()の第３引数で、比較関数を設定するというものだ。

例えばvector\<int>を<strong>降順</strong>で書きたい時はデフォルトで<strong>std::greater<int>()</strong>という比較関数が用意されているので、これを指定してあげる。

```cpp
vector<int> v;
sort(v.begin(),v.end(),std::greater<int>()); //昇順
```

といった具合だ。

要するに、自分の好きな用に比較関数を書いてあげれば良い。

今からの例ではvector\<string>を文字数の昇順でソートするための比較関数を書いて説明する。

書き方は至ってシンプルで、

```cpp
bool compare(string& s1,string& s2){return s1.size()<s2.size();}
```
とかくと昇順の比較関数になる。

<strong>第一引数 < 第二引数</strong> がtrueになるように書くと昇順、その逆に書くと降順になる。

```cpp
#include<bits/stdc++.h>
using namespace std;

bool compare(string & s1, string& s2) {return s1.size() < s2.size();}

int main()
{
	vector<string> s{"takahasi","aoki","tanaka","SnukeinAtcoder","Snuke"};

	sort(s.begin(),s.end(),compare );

	for(auto ss:s)cout<<ss<<endl;

	return 0;
}

/*出力
aoki
Snuke
tanaka
takahasi
SnukeinAtcoder
*/

```

また、ラムダ式で書くこともできその場合は以下のようになる

```cpp
#include<bits/stdc++.h>
using namespace std;
int main()
{
	vector<string> s{"takahasi","aoki","tanaka","SnukeinAtcoder","Snuke"};


	auto compare=[](string & s1, string& s2) {return s1.size() < s2.size();};

	sort(s.begin(),s.end(),compare );

	for(auto ss:s)cout<<ss<<endl;

	return 0;
}
/*出力
aoki
Snuke
tanaka
takahasi
SnukeinAtcoder
*/
```

ラムダ式を埋め込んでも良い

```cpp
#include<bits/stdc++.h>
using namespace std;
int main()
{
	vector<string> s{"takahasi","aoki","tanaka","SnukeinAtcoder","Snuke"};

	sort(s.begin(),s.end(),[](string & s1, string& s2) {return s1.size() < s2.size();} );

	for(auto ss:s)cout<<ss<<endl;

	return 0;
}
/*出力
aoki
Snuke
tanaka
takahasi
SnukeinAtcoder
*/
```

以上のようにして比較関数を書いて、自分の好きなようにソートすることができる。
【Laravel】Collection内のオブジェクトを操作する

# はじめに
Laravelでの開発中に、配列内の各オブジェクトにデータを追加する処理を実装する際に、以下のようなコードで実装を行った。

```php
        $collection = new Collection([
            { id: 1, name: '田中' },
            { id: 2, name: '佐藤'}
        ]);
        foreach ($collection as $object) {
            $object->new_data = 'hoge';
        }
        /* 
         $collection = [
            { id: 1, name: '田中', new_data: 'hoge' },
            { id: 2, name: '佐藤', new_data: 'hoge' }
         ]
        */
```

これでプルリクを投げたらレビュアーからこんな指摘が↓
>**これ、Collectionのmap使えばforeachで回さなくてもできるよ**

え、Collectionってそんなこともできるのか！！！（小並感）

ということで実際にやってみた。

# 参考
https://qiita.com/nunulk/items/ef82a35aa2b75200afa3#50-map

# やり方
※Laravelのバージョンは6.0です。

```php
        $collection = new Collection([
            { id: 1, name: '田中' },
            { id: 2, name: '佐藤'}
        ]);

        $collection->map(function ($object) {
            $object->newdata = 'hoge';
        });
        /* 
         $collection = [
            { id: 1, name: '田中', new_data: 'hoge' },
            { id: 2, name: '佐藤', new_data: 'hoge' }
         ]
        */
```

オブジェクトでもarray_mapみたいに処理をかけるのは嬉しい・・・😭

Collectionでは、配列だと実現がめんどくさい処理も簡単にできるようになっていて、使いこなせるようになるとだいぶ開発が楽になるなと感じました。

ホント、Laravelしゅごい

みなさんも是非Collectionをマスターして、快適なLaravel開発ライフを！（僕自身全然マスターできていませんが・・・）
SQLアンチパターン　サーティワンフレーバー

# サーティワンフレーバー

限定する値を列定義で指定するアンチパターン。

私はMySQLを普段使用するためMySQLを例にとって説明する。
MySQLでは列に対して格納、更新などをする際に有効な値を限定する際に「enum型」を用いることで値を限定することができる。

値を限定することができるが格納する値によっては後述するアンチパターンに該当する。

# 使用する目的

上の項目でも記載したが、列に格納する値を限定することが目的である。

列に格納できる値をすると、無効な値が含まれていない事を保証でき、列をシンプルに使える。
例としてBugsテーブル内のstatus列で、バグの状態を

* NEW
* IN PROGRESS
* FIXED

などで指定しているとすると、status列には必ず、このどれかの値が格納されているという事。
データベースが無効なデータ入力を受け付けないのが理想である。

# 格納された値は何か

Bugsテーブル内のenumで定義されたstatus値を使用しようとした場合以下のようなクエリを発行するだろう。
しかし、取得したデータはそのままだとenum定義等を含む値が帰ってくるためそのままだと使用できない。

```mysql
SELECT 
    column_type
FROM 
    information_schema.columns
WHERE 
    table_name = 'Bugs' 
AND 
    column_name = 'status';

+-----------------------------------+
| column_type                       |
+-----------------------------------+
| enum('NEW','IN PROGRESS','FIXED') |
+-----------------------------------+

```

多くのプロジェクトでは上記のようにSQLから取得したデータを使用可能な形式に変換するよりアプリケーション側で値のリストを用意して使用することが多いのではないだろうか。

# 新しい制限の追加

Bugsテーブル内のstatus列に新しい状態を追加する場合はどうしたら良いか。

* NEW
* IN PROGRESS
* FIXED

enumの値やcheck制約を追加、削除する構文はないため新たな値の組合せで列を再定義するしかない。

データベース製品によってはテーブルが空でない場合でなければ列定義を変更できないものもある。
もし、稼働中のプロジェクト等で使用されているテーブルの場合はテーブルの内容をダンプし、テーブルを再定義したのちにダンプしたデータを再度リストアする必要になることもある。

列定義の変更は頻繁に行うべきではない。

# 値の変更

* NEW
* IN PROGRESS
* FIXED

上記の列の値のうちFIXEDを廃止し、CODE COMPLETEとVERIFIEDに分ける場合どうしたら良いか。
新規で登録する場合は新しく定義された値を格納したら良いが、既存のFIXEDが格納されている行をどうするべきか。

NULL？　初期値を設定する？？　新しく作成した２つの値？？　そのまま残す？？

使用しているプロジェクトや用途によって取捨選択する必要がある。

# 移植が困難

check制約やenumなどデータベース製品によって列定義を限定する方法が統一されていない。
先ほどまで何度か紹介したenumはMySQL固有の機能である。

複数のデータベースをサポートする場合やデータベースを別の製品にする場合は製品ごとに差異があるため困難となる場合がある。

# アンチパターンを用いても良い場合

値セットが変わらない限り問題にはならない。
以下のような例が当てはまる

* ON / OFF
* IN / OUT
* 右 / 左
* 有効 / 無効

上記のような相互排他的な値に対して指定する場合は問題ない。

# 解決策

## 参照テーブルの作成

参照テーブルを作成して許可する値を１行に１つずつ格納する。
そして外部キー制約を宣言し参照テーブルを参照するようにする。

## 参照テーブルの値の更新

UPDATE文を用いて名称を変更するだけで良い。
また、新しい限定する値を追加する際はINSERTで追加するだけで良い。

## 廃止された値のサポート

外部キーを設定しているため行の削除はできない。
参照テーブルに廃止を区別する列を追加することで解決できる。

|status|active|
|:---:|:---:|
|NEW|active|
|IN PROGRESS|active|
|FIXED|inactive|
|CODE COMPLETE|active|
|VERIFIED|active|

有効な値を検索する際はactive列がactive、無効な場合はinactiveを条件に検索することで解決できる

# 移植が容易

enum型やcheck制約と違い、参照テーブルを用いた方法は標準的なSQLの機能を用いているため移植が容易である。
値は行に格納するため他の制約とやデータ型違い実質的に無制限に値を格納できる。

# まとめ

列に入力する値を限定するときは、値セットが固定されている場合はメタデータを、流動的な場合はデータを用いましょう

# 参考文献

[SQLアンチパターン](
https://www.amazon.co.jp/SQL%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-Bill-Karwin/dp/4873115892/ref=sr_1_1?adgrpid=104444684056&dchild=1&gclid=CjwKCAjw4_H6BRALEiwAvgfzqy-f83NTsyQkauo7gn6ysgAPmJvKyvuI5FaXFnxFmhVfCzCRRACsaBoCY-oQAvD_BwE&hvadid=447984765572&hvdev=c&hvlocphy=1009332&hvnetw=g&hvqmt=e&hvrand=13417269104929133208&hvtargid=kwd-335484809678&hydadcr=27264_11561110&jp-ad-ap=0&keywords=sql%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3&qid=1599934568&sr=8-1&tag=googhydr-22)

![参考文献.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257405/b46d45ab-75ec-a620-eeb2-a422f6b1e659.jpeg)
Sunaba講座 #0 導入編

- 各講座へのリンクはこちら
    - [Sunaba講座 #1　Hello Sunaba! ＆ メモリについて](https://qiita.com/gmasa/items/30ce81bfc1a5b07cc754)
    - [Sunaba講座 #2　複数行の実行 ＆ メモリメップド I / O について](https://qiita.com/gmasa/items/0d7cb7f1afb0709f1446)
    - [Sunaba講座 #3　線の描画、while、式の種類 について](https://qiita.com/gmasa/items/1d3b96703622da551a3d)
    - [Sunaba講座 #4　四角の描画、２重ループの活用](https://qiita.com/gmasa/items/122ef3636ed7cf326a53)
    - [Sunaba講座 #5　点を動かす ＆ 画面更新 について](https://qiita.com/gmasa/items/6daaecf34bf114b1044c)

# 本講座の対象
主な読者として『プログラミング経験はほぼ無いのに **C言語の習得を迫られている人**』を想定しています。しかし、以下の人達にも役に立つよう頑張ります。

- ゲームを作れるようになりたい人
- 実行結果が文字の表示だけではやる気がおきない人
- #include <□□□□□□□.h> などの『おまじない』が気になって先に進めない人

# どんな講座なの？
教育用言語Sunabaを使って、プログラミング技術の基礎を身につけてもらう講座です。
[書籍『 プログラムはこうして作られる - プログラマの頭の中をのぞいてみよう 』](https://www.amazon.co.jp/dp/479803925X) （以下、Sunaba本）でいいじゃないかと言われそうですが、

- C言語学習前提なので、プログラミング用語を使う
- C言語学習前提なので、英語で記述する
- テトリスよりも簡単な題材を扱う

といった違いがあります。

社内研修での利用も想定しているため、たまに『研修では．．．』という情報が入ることはご了承ください。


# プログラミングを学習する理由、Sunabaを使う理由
**一から何かを作れるようになりたい！**といった漠然としたものでもいいので、みなさん自身で動機を言葉にしておいてほしいです。それが学習の支えになるはずです。
私はゲームを作りたいと願っていましたが挫折続きでした。2013年 Sunaba本に出会い、プログラムに対する考え方を丁寧に教えてもらうことで挫折を克服しました。また、Sunabaの言語仕様は非常に小さく、**おまじない**等のブラックボックスを気にせずに済んだことが、学習のしやすさにつながったとも考えています。

今は初心者向けの教材とツールが充実しており、Sunaba以外の選択肢がたくさんあります。しかし、短期間にC言語を習得しようとする場合にSunabaが効果的だと考えていて、私が担当する社員研修においてはC言語の事前学習として使わせてもらっています。


# Sunabaを手に入れる
- [Sunaba公式ページ](https://hirasho.github.io/Sunaba/) のダウンロードをクリック (Windows or Mac) 
- 圧縮ファイルを展開して、フォルダの中身を確認
- Sunaba.exe をダブルクリックして、Sunabaウィンドウが起動するかどうかを確認
    - Sunabaが起動せず「.NET Framework******* うんぬんかんぬん」と表示される場合があります。その場合はメッセージに従って必要なものをダウンロード＆インストールしましょう
- 関連資料を入手してほしいので、[保管場所１](https://onedrive.live.com/?id=FEB9AEFDFB7E311%21136&cid=0FEB9AEFDFB7E311) にアクセス
    - Sunaba160413.zip と Sunaba追加パッケージ160413.zip をダウンロードしてください
    - Sunaba160413.zip 内 の Sunaba.exeは旧Ver.なので使わないでください

# 作品紹介
作りやすさの面で向き不向きがありますが、頑張ればいろいろできます。この講座ではブロック崩しを作る予定です。

- シューティング
![SunabaST.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703513/2c50bf2c-0efb-4948-a8f6-7e5a5622a805.gif)

- LifeGame
![SunabaLG.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703513/2474758a-852d-8eee-a4a0-c75ccc3f22f3.gif)

- パ〇ドラ風パズル（画面の上半分はお飾り）
![SunabaPD.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703513/975351db-844e-4472-1016-0b2244b5f79d.gif)



# まずはお手本で遊んでみよう
- 『Sunaba160413\サンプル』フォルダ内の『お手本.txt』をSunabaウィンドウにドラッグ＆ドロップしてください
- 矢印キー（←, ↑, →）で、レッツ テトリス！

# Sunabaの特徴
約束事が少なく、言語仕様がA4用紙2枚に収まります。ここで「楽勝じゃん」と早とちりしてはいけなくて、大抵の機能は自分で作らないといけないのです。例えば、**線を引く機能すら用意されていません**。さらに、ここで作ったプログラムは他のプログラミング言語の作品に流用できません。
ここまで聞くと踏んだり蹴ったりだと思うでしょうが、頑張った成果は体の中に残るので安心してください。

# 英語で頑張ろう
Sunabaは日本語でプログラミングできますが、ここはC言語学習前の講座なので始めから英語でいきます。日本語で考えて Google翻訳でそれっぽい英単語を選びましょう。他のプログラミング言語で書かれたプログラムからヒントを得る、というのもいい考えだと思います。

[次回](https://qiita.com/gmasa/items/30ce81bfc1a5b07cc754)から講座スタートです。がんばっていきましょう！
3年目の後輩とのやり取り

## 1. あるイベントログにメッセージを出力できないんですけど
と、3年目の後輩から相談がありました。
「そんなの簡単じゃん、powershellで Write-Eventlogってのがあるからそれでやれば？」
と返したら、
「それでやってるんですけど、エラーになっちゃうんですよ…」
とお返事。んじゃ、見てみますかとなりました。

## 2. 後輩がやりたいこと
ヒアリングしたところ、イベントログのMicrosoft-Windows-DHCP Client Events/Adminに任意のメッセージを出したいとのこと。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693852/d033f125-50b0-4c9f-544b-df5051b895ce.png)
まあ、Write-Eventlogでできると判断。

後輩もできると認識していて、以下のpowershellで実施していたけどエラーになっていたとのこと。

```powershell
PS C:\Windows\system32> Write-EventLog -LogName "Microsoft-Windows-Dhcp-Client/Admin" -Source test -EventID 100 -Message "test"
```

## 3. 後輩がやったこと
まずは後輩とget-help Write-Eventlogでお作法を確認

```powershell
PS C:\Windows\system32> get-help Write-EventLog -examples

名前
    Write-EventLog

概要
    Writes an event to an event log.

    ---- Example 1: Write an event to the Application event log ----
    PS C:\> Write-EventLog -LogName "Application" -Source "MyApp" -EventID 3001 -EntryType Information -Message "MyApp
    added a user-requested feature to the display." -Category 1 -RawData 10,20
    This command writes an event from the MyApp source to the Application event log.
   
    Example 2: Write an event to the Application event log of a remote computer
    PS C:\> Write-EventLog -ComputerName "Server01" -LogName Application -Source "MyApp" -EventID 3001 -Message "MyApp
    added a user-requested feature to the display."
    This command writes an event from the MyApp source to the Application event log on the Server01 remote computer.
```

記述方法は問題なさそう。ただし、-sourceでしている "test"っていうソースがないからエラってると判断。
私：「たぶん、ソースでしているtestが引けないからじゃないの？New-Eventlogでソース指定すればいいよ」
後輩：「それもやったんですが…」
私：「マジ！？じゃあ、エラーの画面見せて？」
それがこれ
↓

```
PS C:\Windows\system32> Write-EventLog -LogName "Microsoft-Windows-Dhcp-Client/Admin" -Source test99 -EventID 100 -Mess
ge "test"
Write-EventLog : ソース 'test99' はログ 'Microsoft-Windows-Dhcp-Client/Admin' に登録されていません (ログ 'Internet Expl
orer' に登録されています)。Source と Log プロパティを一致させるか、または、Log を空の文字列に設定すると、自動的に Sourc
e プロパティに一致します。
発生場所 行:1 文字:1
+ Write-EventLog -LogName "Microsoft-Windows-Dhcp-Client/Admin" -Source ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Write-EventLog]、Exception
    + FullyQualifiedErrorId : ソース 'test99' はログ 'Microsoft-Windows-Dhcp-Client/Admin' に登録されていません (ログ '
Internet Explorer    ' に登録されています)。Source と Log プロパティを一致させるか、または、Log を空の文字列に設定する
と、自動的に Source プロパティに一致します。,Microsoft.PowerShell.Commands    .WriteEventLogCommand
```
## 4. 先輩(私)が対応したこと
私：「エラーメッセージに書いてあるじゃん。IEでイベントログ一度テストした？SourceとLogは一致しないとって書いてあるよ？」
これが正解でした
↓

```powershell
PS C:\Windows\system32> New-EventLog -LogName "Microsoft-Windows-Dhcp-Client/Admin" -source test1
PS C:\Windows\system32> Write-EventLog -LogName "Microsoft-Windows-Dhcp-Client/Admin" -Source test1 -EventID 100 -Message "test"
```

ほら出たぜ！
![20200902.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693852/355829fc-6289-43d5-b5d1-36ea900fb96c.png)
[GAS] google claspをTypeScriptで実装する

## claspって何？

GAS を管理するための CLI ツール
TypeScriptでGASを実装できる

## 今までのGASのデメリット

GASはJavaScript ベースの言語でコーディングを行うが、ES2015などの新しい構文に対応していないため、とても開発効率が悪くモジュールを分けることもできない。
テストコードも書けないし、Lintもできない、使い慣れたエディタも使えないという・・

## 何が嬉しいの？

今までのGASのデメリットを打ち消してくれること

Git でバージョン管理しながらローカルの使い慣れたエディタでコードを書いて、GASにpush して実行するという開発ができる。
もちろん、コーディングの自動補完もできる。

しっかり型を定義できるところが大きい。

プログラムを組むスピードがTSがない場合と比べて爆速です。
型定義はGASを書くスピードを上げるアクセルといっても過言ではないので。

GASに型注釈がつくことで、バグを生みにくくなる。
型定義にジャンプして、引数や返り値の型をチェックできる。

TypeScriptが型で縛ってくれるおかげで「実行 → ログ確認」のフィードバックループを回す回数は格段に減る。

**具体的には**

*  TypeScriptによる実装
*  Gitによる構成管理
*  Prettierによる自動フォーマット
*  TSLintによる静的解析

みたいな感じ。

## どうやってGASと紐付ける？

GoogleがAPIとして、提供してくれている。

TSから古いJSへトランスパイル
（ソースコードのコンパイル的なものという認識でOK！）

googleアカウントごとに紐付けできる。

## どこにPushする？

紐付けされたGoogleアカウント、対象のスクリプトIDなどを指定して、clasp pushする。
clasp pushすると自動的にGASのスクリプトエディタに反映される。

## 参考リンク

https://github.com/google/clasp

https://note.com/hideharu092/n/n935591fe1784

https://tech.actindi.net/2018/09/10/083314
ISUCON10直前！処理高速化の一例

## はじめに

高速化の手法の一例を共有する

## 高速化前のコード

```php:old.php
<?php
class Data {
    public function get_data_old(){
        $pdo = new PDO('mysql:host=localhost;dbname=array_speed_up;','root');
        $query = 'SELECT * FROM `data`';
        $result = $pdo->query($query)->fetchAll(PDO::FETCH_ASSOC);
        return $result;
    }
}

function old_code(){
    $data = new Data();
    $records = $data->get_data_old();
    $tmp_array = array();
    foreach($records as $record){
        array_push($tmp_array, $record['id'].','.'"'.$record['value'].'"');
    }
    //print_r($tmp_array);
    return($tmp_array);
}

echo("--- old ---\n");
$time_start = microtime(true);
$memory_first = memory_get_usage() / (1024 * 1024);
old_code();
$usage_memory = memory_get_usage() / (1024 * 1024);
$memory = $usage_memory - $memory_first;
$memory = round($memory, 4);
$time = microtime(true) - $time_start;
$time = round($time, 4);
echo($memory." MB\n");
echo($time." 秒\n");
```

DBは以下の構成

```sql
  CREATE TABLE `data` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    `value` varchar(255) NOT NULL DEFAULT '',
    PRIMARY KEY (`id`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```

DBからレコードを全て取得し
`id,"value"`
の形に整形して画面に出力する、というような処理

### 問題点

まぁ別にレコードが少なければ問題なく動くが全件取得して表示するためレコードが増えれば増えるほど重い
またレコード数分のループを回しているのも重い
`$tmp_array`に都度整形した結果を格納していくスタイルなので`$records`と`$tmp_array`で2倍の配列を確保するのも重い

## 高速化後のコード

```php:refactor.php
<?php
class Data {
    public function get_data_refactor(){
        $pdo = new PDO('mysql:host=localhost;dbname=array_speed_up;','root');
        $query = 'SELECT CONCAT(CONCAT(CONCAT(CONCAT(`id`, ","), """"), `value`), """") FROM `data`';
        $result = $pdo->query($query)->fetchAll(PDO::FETCH_COLUMN);
        return $result;
    }
}

function refactor_code(){
    $data = new Data();
    $result = $data->get_data_refactor();
    //print_r($result);
    return($result);
}

echo("--- refactor ---\n");
$time_start = microtime(true);
$memory_first = memory_get_usage() / (1024 * 1024);
refactor_code();
$usage_memory = memory_get_usage() / (1024 * 1024);
$memory = $usage_memory - $memory_first;
$memory = round($memory, 4);
$time = microtime(true) - $time_start;
$time = round($time, 4);
echo($memory." MB\n");
echo($time." 秒\n");
```

整形処理をDBから取得するタイミングで既に終わらせているため、データ整形のループが不要
`$tmp_array`のような整形後のデータを格納する配列も不要

## 性能比較

| レコード数 | before | after |
|:--|:--|:--|
| 1  | 0.0177 秒  | 0.0014 秒  |
| 1000  |  0.0295 秒 |  0.0074 秒 |
| 10000  | 0.1153 秒  | 0.0685 秒  |
| 100000  |  1.1397 秒 |  0.5736 秒 |

実行時間は大体倍くらいに速くなった。
メモリに関しては`0.0002MB`が`0.0001MB`に減った。

## まとめ

そのループ本当に必要か？
その配列本当に必要か？
そのテーブルはMAXどの程度レコードが入る想定なのか？
考えうる最善を尽くしていけると良いですね。
【②】WindowsServer2016　FW編

##今回やること
前回引き続きFW設定を行っていきます。
前回の記事はこちら
⇒[【①】WindowsServer2016　FW編](https://qiita.com/nishi-infr/items/eb3dfc76bb5528def141)

##使用ツール
VMware Workstation 15 Player

##FW設定
では前回の方法で**セキュリティが強化されたファイアウォール**を開いていきます。
そして**受信の規則**をクリックします。
![FW.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/acfed890-d0c9-6597-5886-7397f2d12498.jpeg)
ずらずらでてきますね。
右のほうにある**新しい規則**をクリックするとウィザードが立ち上がります。
![FW1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/94b344ca-1341-0333-4fcf-feee40d6432b.jpeg)
ここから規則を作成して追加することが可能となります。

今回はポートを追加してあげて、規則を作っていこうと思います。
![FW2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/f29cc412-2a7d-c7a5-3f36-3368122d4c2e.jpeg)
今回は適当なポート番号を入力します。

そして接続させるかブロックするかの設定をしてあげます。
![FW3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/56233080-a99d-5514-25fa-1f453a7f3de7.jpeg)
どの環境でブロックするかの設定はデフォルトで全てチェックが入っているので
設定したい項目だけチェックするようにします。
今回はデフォルトのままいきます。
![FW4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/38b8fcb8-305c-eec7-9f07-81aada8e4b06.jpeg)
そして適当に名前をつけて完了をクリックします。
すると項目が追加されています。
![FW5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/cf168007-1615-361e-61bb-7c3c709b5ced.jpeg)
あと色々な項目があるFWですが、有効化・無効化については、右クリックして規則の無効化を選べば
無効化できます。
無効になっているものを右クリックすると有効化できます。

##まとめ
今回はお試しでFWの規則を作ってみました。
あと有効化・無効化も色々試したり、どんな項目があるか等、見てみました。
FWの機能も色々いじることができたので、ひとまずFWは終わろうかと思います。

次は何やろうか迷ってます。
引き続きWindowsSVでwebサーバーいじってみるか、ネットワークでIPsec構築してみるか。
やりたいことがいっぱいあるので、時間が足りません・・・

とある方からネットワークで無線構築勉強してみるといいよ！とアドバイスをいただきました。
このようなアドバイスは本当にありがたいです。
早速調べてみると私のルーターで動くかわからないので、新しいのを購入しようか迷ってます。

以上となります。
IBM Cloud Tok02データセンターにて新規VSI仮想サーバをオーダする際に知っておきたいTips

## TOK02でのサーバオーダには注意


* IBMCloudでは、各データセンターごとにPodという単位でサーバなどの機器を収容しており、各データセンターのPod拡張を計画するためPod数はデータセンターによって異なるようです。

* 今回、私がTok02 Pod1で既存で利用しているVRAに対して、新規VSI仮想サーバをオーダしたものの、Podが異なるためオーダしたVSIがVRAにAssociateできなかった問題があったため、この課題を解消した方法について共有させていただきます。

#### Tok02にてPod1を指定してVLANをオーダする方法

* [IBMCloudポータル] -> [リソースの作成] を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703075/acf69bc4-43ff-65cd-0b41-097d649a2d0d.png)

* [カタログを検索] -> [Vlan] と入力し、"VLAN"サービスを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703075/c0d2a577-ed47-da08-c226-0314a8e597f1.png)

* [作成] を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703075/6b5a8634-7682-65b9-18b0-4a47189f3717.png)

* [Private] -> [Pod] -> [tok02.pod01] を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703075/c339a8c6-ab56-d4e4-ed25-215b99d4cd5b.png)

* [Create] を押下

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703075/48fb68e1-f6b1-e8bb-718e-18e598d89f93.png)


#### VSIサーバのオーダ時に先ほど作成したVLAN(Pod1)を指定

* [IBMCloudポータル] -> [リソースの作成] -> [Virtual Server for Classic]
 にて仮想サーバインスタンス作成画面へ遷移

* [ネットワーク・インターフェース] -> [プライベートVLAN]に移動し、自動割り当てを選択
(ロケーションはアジア太平洋-Tok02を選択している必要があります)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703075/044d0539-3abb-e0d1-a661-c3907c90c47a.png)

* 先ほど作成したVLANが表示されているので、選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703075/7bd2e2f2-19d9-895a-86dc-f03cf662aa95.png)

* 上記方法を実行することで、Tok02のPod1に新規サーバをオーダすることが可能となり、
本事例ではVLAN1711が既存のVRAにAssociateできるようになりました。

#### 最後に

* 2020/9/4時点では、東京のDCではTok02のみが複数Pod(pod1,pod2)が存在するためこの問題が発生すると考えられます。（本日時点ではTok04,Tok05についてはまだPodが一つしか選べないため、VLANの事前オーダーは不要）
ncurses 6.2とscreen 4.8.0インストール

■ncursesインストール

Announcing ncurses 6.2
https://invisible-island.net/ncurses/announce.html
Index of /pub/gnu/ncurses
https://ftp.gnu.org/pub/gnu/ncurses/?C=M;O=D

■ソースからncursesをインストールする - noknow
https://noknow.info/it/os/install_ncurses_from_source?lang=ja

```
＞# ./configure --prefix=/usr/local/ncurses/6_1 --with-shared --with-pkg-config-libdir=/usr/local/ncurses/6_1/lib/pkgconfig --enable-pc-files
configureオプション
--with-shared
共有ライブラリを生成する
--with-pkg-config-libdir
.pcファイルの生成先パス
--enable-pc-files
.pcファイルを生成する

# ncurses
NCURSES_INC=/usr/local/include/ncurses

export CPATH=$NCURSES_INC:$CPATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
```


重要
インストール: ncurses | 端末操作の基本ライブラリー – senooken.jp
https://senooken.jp/post/2018/06/20/
＞ --with-shared --with-termlib

■実行した./configure
./configure --prefix=/usr/local/stow/ncurses --with-shared --enable-pc-files --with-termlib

■screenとは

GNU screenのattach時に環境変数を自動的に引き継ぐ - 貳佰伍拾陸夜日記
https://tarao.hatenablog.com/entry/20101025/1287971794

■GNU screenインストール

tmux同様 ncurses が必要。オプションは --enable-colors256 ぐらい？
もしかして、libcryptも？

公式
Screen - GNU Project - Free Software Foundation
https://www.gnu.org/software/screen/
Index of /gnu/screen
https://ftp.gnu.org/gnu/screen/?C=M;O=D


```
$ wget https://ftp.gnu.org/gnu/screen/screen-4.8.0.tar.gz
$ tar xzvf screen-4.8.0.tar.gz
$ cd screen-4.8.0
$ cd screen/src
$ sh autogen.sh
$ ./configure --enable-colors256 --prefix=/usr/local
（Macでビルドする場合は --prefix=/usr/local が必要。/usr/local/stowはNG）
$ make
$ make install
```

Gnu screen-4.1.0のインストール – senooken.jp
https://senooken.jp/post/2013/04/15/

git.savannah.gnu.org/
http://git.savannah.gnu.org/

必読

開発版GNU Screenでコピペを極める - Keep It Simple, Stupid
http://yskwkzhr.blogspot.com/2011/12/master-copy-and-paste-of-gnu-screen.html

■エラーやその他

Cygwin で GNU Screen を使って画面の縦分割をしてみる
https://server-setting.info/blog/cygwin-gnu-screen-install.html

MSYS2 に gnu screen をインストールする - Qiita
https://qiita.com/jp_yen/items/443f29945a154555745c

■実行した./configure
./configure --enable-colors256 --prefix=/usr/local
ScrollViewの中にRecyclerView！

こちらの[記事](https://qiita.com/tg_kondo/items/c82aab2f333edbfd0c4b)でScrollViewの中にListViewをぶっこむときはカスタムListViewを作ればスクロールできてよし！ってなったんだけど、あるお方の助言でRecycleViewでも簡単に実現できましたよ！！:relaxed:

![movie3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678917/91e8a550-9a18-d15a-85e5-9e50c61da042.gif)

RecyclerViewに`android:nestedScrollingEnabled="false"`を追加するだけ！
なんと簡単なんだ。。。

```
<ScrollView
  android:id="@+id/scroll_view"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    ・・・略・・・

    <androidx.recyclerview.widget.RecyclerView
      android:id="@+id/list_view"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:nestedScrollingEnabled="false"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent" />

  </LinearLayout>

</ScrollView>
        
```
【React Hooks】useContextについてシンプルにまとめる

 
#はじめに
useStateを使っていると、データをpropsで子の更に子のコンポーネント、とバケツリレーする形になることが多い。
useContextを使うことで、一気に下層のコンポーネントに渡すことができるということで学習した。


#上層コンポーネント


```tsx:app.jsx

import React, {createContext, useState} from 'react'

//Contextの作成
export const UserContext = createContext()

export default App = () => {

  const [user, setUser] = useState({
    name: 'username',
    email: 'example@example.com'
  })

  return (
　　　　//下位コンポーネントを囲うProviderにstateを渡す
      <UserContext.Provider value={user}>
          <nextComponent/>
      </UserContext.Provider>
  )
}
```


#下層コンポーネント

上層コンポーネントの、`<nextComponent/>`の更に下層に`<nextNextComponent/>`があるとする。

```tsx:nextNextComponent.jsx

import React, {useContext} from 'react'
//上層コンポーネントで定義したContextのインポート
import {UserContext} from '../../App'

const nextNextComponent = () => {
　//インポートしたUserContextをuseContextして変数に代入することで、jsx内で表示できる。
  const user = useContext(UserContext)

  return (
    <p>username：{user.name}</p>
    <p>email:{user.email}</p>
  )
}

```

#感想
規模の小さいプロジェクトで、部分的に使う文には書きやすくて簡単で便利。
下層コンポーネントに渡したいデータが多くなってくると、
`<UserContext.Provider value={user}>`
と定義する部分が増えて見通しが悪くなるかと思いました。

これに対して、Reduxでのstate管理だと、記述量が増えるデメリットがあるが、
・コンポーネントのファイル内がスッキリする
・stateの処理のパターンごとにファイルを分けて管理できる
・データの流れが常に一定で慣れれば理解しやすい
といったメリットがあるのかなと思いました。


###終わりに。
最後まで読んで頂きありがとうございます:bow_tone1:
転職の為、未経験の状態からReact,Railsを学習しております。継続して投稿していく中で、その為のインプットも必然的に増え、成長に繋がるかと考えています。
投稿の内容に間違っているところや、付け加えるべきところが多々あるかと思いますので、ご指摘頂けると幸いです。この記事を読んで下さりありがとうございました。
GoアプリケーションをECSインスタンスにデプロイする方法

今回は、**Alibaba Cloud ECSインスタンス**に**Goアプリケーション**をデプロイする方法を紹介します。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/deploying-a-go-application-to-an-ecs-instance_594790)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

前回の記事では、ローカルJavaアプリケーションをAlibaba Cloud ECSインスタンスに直接デプロイする方法を紹介しました。今回は、Alibaba Cloud [Elastic Compute Service (ECS)](https://www.alibabacloud.com/ja/product/ecs) インスタンスに Go アプリケーションをデプロイする方法を紹介します。

#アプリケーションをローカルに開発する
クラウド上で動作するGoアプリケーションをコンパイルしても、ローカルで動作するGoアプリケーションをコンパイルしても、コーディング方法は同じです。そこで本記事では、Webページに「Hello World」を印刷するGoアプリケーションを例に、展開方法を説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/a416cbbe-7703-4bb9-027e-a6b01d046bfb.png)

```
//Alibaba Cloud Toolkit. http://www.aliyun.com/product/cloudtoolkit
func setupRouter() *gin.Engine {
    // Disable Console Color
    // gin.DisableConsoleColor()
    r := gin.Default()
    // Ping test
    r.GET("/ping", func(c *gin.Context) {
        c.String(http.StatusOK, "Alibaba Cloud Toolkit: Hello World.")
    })
    return r
}
func main() {
    r := setupRouter()
    // Listen and Server in 0.0.0.0:8080
    r.Run(":80")
}
```

[このリンク](https://www.alibabacloud.com/blog/deploying-a-go-application-to-an-ecs-instance_594790)からソースコードをダウンロードできます。

前述のコードは、Web ページに "Hello World" という文字列を表示するために使用される標準的な Go プロジェクトです。

#プラグインのインストール
Alibaba Cloudは、開発者がローカルIDEで書かれたアプリケーションをECSインスタンスに効率的にデプロイできるようにするEclipseベースのプラグインを提供しています。

プラグインのURL: [https://www.aliyun.com/product/cloudtoolkit_en](https://www.aliyun.com/product/cloudtoolkit_en?spm=a2c65.11461447.0.0.436d2553lGbhd1)

このEclipseベースのプラグインのインストール手順は、一般的なプラグインと似ているため、ここでは詳細を説明しません。

#プラグインの環境設定
プラグインをインストールしたら、選択して環境設定を行います。

トップメニュー＞ウィンドウ＞環境設定＞Alibaba Cloud Toolkit＞アカウントの順に選択します。

次のページが表示されたら、Alibaba CloudアカウントのAKとSKを設定して、環境設定の設定は完了です(RAMユーザーアカウントを使用している場合は、RAMユーザーのAKとSKを入力してください)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/555fd5ef-fd83-4e04-bb63-19fc66664cc6.png)


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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/de865507-169a-e1ac-8d19-2de340b97615.png)


Eclipseでプロジェクト名を右クリックし、ショートカットメニューからAlibaba Cloud > Deploy to ECSを選択します。以下のようなデプロイ画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/b9a0c2b3-c09b-8d8a-ecae-937a5eb0c8e1.png)

配置設定]ダイアログボックスで、配置パラメータを設定し、[配置]をクリックして初期配置を完了します。

#配置パラメータの説明
- デプロイファイル: 2つのオプションがあります。
- Maven ビルド：現在のプロジェクトのビルドにMavenを使用している場合、Alibaba Cloud Toolkitを使用してアプリケーションを直接ビルドしてデプロイすることができます。
- ファイルのアップロード: 現在のプロジェクトのビルドにMavenを使用していない場合、またはローカルにパッケージ化されたデプロイファイルが既に存在する場合、ローカルのデプロイファイルを選択して直接アップロードすることができます。
- デプロイする ECSの選択：ドロップダウン リストからリージョンを選択し、そのリージョンにデプロイするECSインスタンスを選択します。
- デプロイ先を指定：ECS インスタンス上のデプロイパスを入力します。
- コマンド：アプリケーション起動コマンドを入力します。このパラメータは、アプリケーションパッケージがデプロイされた後に実行されるコマンドを指定します。Goプログラムの場合、通常は一連のプログラム起動コマンドを入力します。

```
source ~/.bash_profile
pkill -f 'go-demo'
mv /tmp/go-demo /root/go-demo
chmod 755 /root/go-demo
sh -c /root/go-demo
```

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*
【AndroidStudio】【Java】学習メモ&リンク集

※AS＝AndroidStudio

| No | 種別 | 用語 | 自分の言葉で簡潔に | 参考記事 |
|:--:|:----:|:----:|:-----|:--------|
| 1  | AS   | View<br>(Object) | VBで言うとControlに当たる。ボタンやテキストボックスなどのUI部品を指す。<br>例：`view.getId()` | [**Android Viewとは（ViewとViewGroupの関係性）**<br>-ANDROIDろいど- プログラム開発入門](https://androidroid.info/android/view/482/) |
| 2  | AS   | R<br>(Class) | 画面に配置したViewのIDを管理しているクラス。AndroidStudioにより自動生成される。<br><font color="silver">※ver4.0.1では「R.java」というファイルはプロジェクトフォルダ内に見つけられず。</font><br>例：`findViewById(R.id.myButton)` | [**[Android Studio] R.id のRとは？**<br>ロジカルシンキンぐんっ！](https://high-programmer.com/2017/07/21/android-studio-r-id/) |
| 3  | Java | インスタンス | たいやきの焼き型が「クラス」ならそれを使って焼いたたいやきは「インスタンス」である。 | [**インスタンス化**<br>IT用語辞典BINARY](https://www.sophia-it.com/content/%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%8C%96) |
| 4  | Java | 匿名クラス | その名の通り名前のない、使い捨てのクラス。 | [**Javaの匿名クラス（無名クラス）の使い方【初心者向け】**<br>TECHACADEMY](https://techacademy.jp/magazine/19027) |
| 5  | Java | インターフェース<br>(interface) | このクラスはこういうメソッドを必ず保持するというルールを課すためのもの。 | [**インターフェースとは？～継承とは役割が違う～**<br>GiXo](https://gixo.jp/blog/5159/) |
| 6  |  |  |  |  |
| 7  |  |  |  |  |
| 8  |  |  |  |  |
| 9  |  |  |  |  |
| 10 |  |  |  |  |
| 11 |  |  |  |  |