OmniAICreator/Qiita-1.07M huggingface dataset:
nodenvをupdateして新しいバージョンのNode.jsをインストールする

# nodenvで欲しいバージョンのnodeが見つからない……

プロジェクトで指定されたバージョンのNode.jsをインストールしようとして

```zsh
nodenv install --list
```

とうっても、欲しいバージョンがリストに出てこないときってありませんか？


どうやらnodenvはインストール時に登録されているバージョンしか表示してくれないようです。

調べてみても、nodenvを消してから再インストールするみたいな、ええっ🙄という情報が多いです。

# nodenvをアップデートする一番簡単な方法

[anyenv](https://github.com/anyenv/anyenv)のプラグインである[anyenv-update](https://github.com/znz/anyenv-update)を使いましょう。

※ そもそもanyenv使っていない人は、[こちら](https://qiita.com/kyosuke5_20/items/eece817eb283fc9d214f)などが参考になります。anyenv、オススメです。


## anyenv-updateのインストール

anyenvのルートディレクトリ（デフォルトでは`~/.anyenv`）の下に、pluginsディレクトリを作り、リポジトリをクローンします。

```zsh
mkdir -p $(anyenv root)/plugins
git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
```

## nodenvのアップデート

コマンドをうつだけです。かんたんですね😌

```zsh
anyenv update
```

※ anyenvで管理しているnodenv以外のツールもアップデートしてくれます

# anyenv使いたくないよって人は……

## 手動でリストをアップデートする

[公式のREADME](https://github.com/nodenv/nodenv#updating-the-list-of-available-node-versions)に方法が載っていました。

node-buildというデフォルトのプラグインのリポジトリを最新にすればよいらしいです。

```zsh
cd ~/.nodenv/plugins/node-build
git pull
```

## nodenv-updateを使う

[nodenv-update](https://github.com/nodenv/nodenv-upde)というプラグインがあるようです。

```zsh
# インストール
mkdir -p "$(nodenv root)"/plugins
git clone https://github.com/nodenv/nodenv-update.git "$(nodenv root)"/plugins/nodenv-update

# アップデート
nodenv update
```

# おわりに

参考になれば幸いですっ。
mysqlで新規ユーザーを作成する方法

1 まずはデフォルトユーザーであるrootでmysqlにログインする

>mysql  -u  root 



2  ログインできたら、mysqlのユーザ一覧でどんなユーザーがいるのか確認する

>SELECT Host, User FROM mysql.user;



3  新しくユーザー作成する
>grant all on データベース名.* to ユーザー名@接続元 identified by ‘パスワード’;

4  現在rootでログインしてるためexitでログアウトする


5  新規で作成したユーザーでログインする
>mysql -u ユーザー名   -p
Mochaで実行時に特定のテストをスキップする

こんな感じで ```this.skip()``` を使えばOK。

```javascript
const assert = require('assert');
const os = require('os');

suite('テスト', function(){
    test('Winの場合はスキップ', function(){
        if (os.platform() == 'win32') this.skip();
        assert.ok(1);
    });
});
```
```this``` が必要なので、アロー関数内のテストだとダメ。関数で囲うべし。
Project Oakdale有効にしたチーム消したらどうなるんだろう

以下のような状態 (remove teamというチームでOakdaleが有効になっている）で、チームをアーカイブした場合、消した場合に環境に影響があるかどうかを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/2f2d7b5d-9a45-131a-4f3a-fb226d9de751.png)

なお、この環境にはアプリとカスタムエンティティが作成されていることとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/0fce5545-fda4-1122-3034-e2b256bc0c0d.png)

#1. アーカイブ時の挙動

チームをTeamsの管理センターからアーカイブします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/c90d15fe-1250-97b2-e80d-503c15df1b73.png)

この状態で、タブに追加したアプリからレコードの作成を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/f53a2404-4c1c-106a-f38b-3ecaafbf4bba.png)

特に問題なくデータ登録できました。
念のためPower Platformの管理センターで確認してみましたが、環境に変化はありませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/94d51753-8324-5de6-5191-74a886dd67d2.png)


#2. 削除時の挙動

続いて、チームを消してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/37118f34-f939-e3dd-c171-8559be49aac1.png)

Power Platform管理センターで環境を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/2bc6473a-5829-2869-5373-1d166b40b3a6.png)

特に変化はないようにみえます。試しに環境の設定と、実際にアプリが使えるかを確認してみると・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/27918520-e9e3-aef1-b161-eaad5d2cce22.png)

環境へのアクセス権はチーム削除前と変わらず。アプリもURLが分かっていれば利用可能でした。

唯一異なるのは、Oakdaleな環境に特有の「セキュリティグループとの関連付け」がなくなっていることです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/12083117-a925-2209-2e68-004c6471d537.png)
※セキュリティグループ云々については [こちら](https://mofumofupower.hatenablog.com/entry/2020/09/25/200421)

# まとめ
Project Oakdale (Teams上のPower Apps) が有効になっているチームで、対象のチームをアーカイブ・削除したときの挙動を確認しました。

個人で確認した範囲では・・・

1. アーカイブしても無影響 （SharePointとは違う）
2. 削除しても環境とリソースは残る (ただしチームとの関連付けは消える)

という結果になりました。数日して環境が消えたりということがあるかもしれないので、更新があれば追記します。

チームをうっかり消してしまっても、アプリやデータが即時消えるわけではないので安心な反面、ゴミが残るのはちょっと考えなければなりませんね。（上限があるので）

このあたりは [**ここ**](https://mofumofupower.hatenablog.com/entry/2020/09/25/200421 ) で紹介しているようなPower Automateを使った方法で、セキュリティグループの関連付けがなくなったOakdaleな環境は削除する というフローを作成してもいいかもしれませんね。

※あくまで個人の調査結果、プレビュー機能ですので、結果については責任は負えません
JavaScriptの関数

#コールバック関数
何らかの動作後に実行したい関数を実装する手段。
引数として関数を渡すことで、任意のタイミングで関数の処理実行を実現している。

```test.js
function func(callback) {
 console.log('word1');
 callback();
}

func (function(){
 console.log('word2');
});

//実行結果は　word1 word2と順に表示される。
```

#巻き上げ
verを使用して関数内で変数を宣言したばあい、全てその関数の先頭で宣言されたものとみなされる。
これは、関数内のどこでも変数を宣言できる代わりに受ける制約。

```test.js
ver a = 'word1';

function func() {
 console.log(a); //undefined
 ver a = 'word2';
 console.log(a); //word2
}

f();
```

実際の動作

```test.js
ver a = 'word1';

function func() {
 ver a;
 console.log(a); //undefined
 a = 'word2';
 console.log(a); //word2
}

f();
```


#即時関数
関数の定義と同時に実行する手段。
再利用しない場合などに使用できる。

```test.js

(function(a, b) {console.log(a + b);}(1, 2)); //3
```
redis-fainaを用いてRedisの実行コマンドを解析する



redis-cliの[monitor](https://redis.io/commands/monitor)コマンドでコマンドの実行ログを見ることでが出来ますが、自力で解析するのは大変です。
redis-fainaを用いることでmonitorコマンドの結果を解析して、統計情報を表示してくれるので、頻繁に実行されているコマンドやキーを特定したい時に役立ちます。

#redis-faina

redis-fainaはInstagramの開発者によって作られ、facebookが公開しているpython製のツールで、簡単に使うことが出来ます。

https://github.com/facebookarchive/redis-faina

#インストール

```bash
$ git clone https://github.com/facebookarchive/redis-faina.git
$ cd redis-faina
```

#実行


#### ファイルから読み込む場合

```bash
$ redis-cli -p 6379 monitor | head -n 10000 > outfile.txt
$ .redis-faina.py outfile.txt
```

#### 標準出力からから読み込む場合

```bash
$ redis-cli -p 6379 monitor | head -n 10000 | .redis-faina.py outfile.txt
```

#### 実行結果

```bash
Overall Stats
========================================
Lines Processed         10000
Commands/Sec            12967.49

Top Prefixes
========================================
key             2000    (20.00%)
counter         1000    (10.00%)

Top Keys
========================================
mylist                  2999    (29.99%)
myset                   2000    (20.00%)
key:__rand_int__        2000    (20.00%)
counter:__rand_int__    1000    (10.00%)

Top Commands
========================================
PING    2000    (20.00%)
LPUSH   1999    (19.99%)
INCR    1000    (10.00%)
SET     1000    (10.00%)
SADD    1000    (10.00%)
GET     1000    (10.00%)
SPOP    1000    (10.00%)
LPOP    1000    (10.00%)

Command Time (microsecs)
========================================
Median          68.0
75%             84.75
90%             116.0
99%             241.75

Heaviest Commands (microsecs)
========================================
PING    160997.25
LPUSH   152823.0
GET     83242.75
SET     80229.75
SADD    76377.0
INCR    75668.25
LPOP    71876.0
SPOP    69945.0
```

#参考

[redis-faina: a query analysis tool for Redis](https://instagram-engineering.com/redis-faina-a-query-analysis-tool-for-redis-3ad96ffb2e87)
Microsoft 365 サービス正常性を取得する

# 記事概要
SaaSの障害にユーザーは無力。仕事できない。何もできない。何が起こったかわからない。Microsoft 365(旧称:Office 365)の障害情報(サービス正常性)を取得する方法を知り、他のユーザーにも共有しよう。

# この記事の対象
・Microsoft 365に障害が発生するたびにユーザーから問い合わせがあり、サービス正常性を効率的に取得・共有したい情報システム部門
・Microsoft 365を利用している開発者

# サービス正常性を取得する方法
公式情報としてサービス正常性を取得する方法は4つある。
## 1. Microsoft 365 管理センターにアクセスする

**特徴**
・専門知識は不要。[Microsoft 365 管理センター](https://admin.microsoft.com/Adminportal/Home?source=applauncher#/servicehealth)にアクセスすればよい
・Microsoft 365 の管理者権限が必要


## 2. Microsoft 365 Management API
**概要**
Azure Active DirectoryにManagement APIを登録して、各種ツールでサービス正常性を取得する。

**特徴**
・情報取得にAPI、情報の整理にJSONを利用する為、それらに関連した技術やナレッジが必須となる

## 3. Twitterアカウントをフォローする
**概要**
[Twitterアカウント](https://twitter.com/MSFT365Status)をフォローする。

**特徴**
・管理者権限が不要
・ブラウザのブックマーク機能等を利用すれば閲覧用のTwitterアカウントも不要になる
・140字の制約上、他の方法と比較すると情報が断片的である
・すべてのサービス正常性を取得できるわけではない。逆にテナントによっては管理センターで閲覧できないインシデントを取得することでもできる

##  4. メールで受信
**概要**
2019年から提供された機能。正常性サービス配信先のメールアドレスを2つまで指定可能
管理センター→サービス正常性→ユーザー設定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338126/1575099c-24d5-9b45-b02a-98bfe0402140.png" width=50%>


**特徴**
・メールアドレスを指定する操作には管理者権限が必要だが、指定するアドレスは管理者のアドレスである必要はない(配布グループのアドレスでも配信されることを確認済み)
・受信対象のサービスを選択可能(テナントで利用頻度の高いサービスのインシデントのみ取得する、といった設定も可能)
・メールで受信する関係上、Exchange Onlineに障害が発生すると機能しない可能性がある
・アドバイザリやインシデントのステータスが更新される都度配信される仕様の為、障害が多い日は多数のメールを受信する可能性がある。後述のPower Automateなどのツールでワンステップ挟んで制御する必要がある

# 自動配信先を設定する
2.と3.と4.についてはMicrosoft 365のPower Automateで他のサービスと連携することによって効率よく配信できる。

**配信先サービス**
例)Teams、メール、Yammer

**配信先ユーザー**
例)全社、グループ、ユーザー

## 2.の設定例
r-wakatsuki 様の記事がとてもわかりやすいので、こちらを参考に。

【Microsoft Flow】フローを利用して Office 365 サービス正常性を監視する
https://qiita.com/r-wakatsuki/items/e72f2ed4e3fd213483cf

## 3.の設定例
**取得用のTwitterアカウントを使用しない場合**
1. SharePoint OnlineのWebパーツを利用する
2. SharePointのページを編集し、+をクリックして「Twitter」で検索して選択

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338126/6340ba37-41cb-d673-b46d-a1963df4a0a0.png" width=50%>

3. Webパーツの編集画面で「@MSFT365status」と入力する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338126/faccc5ce-6fe3-0dfb-e849-8c81c855e52f.png" width=50%>

## 4.の設定例
**Outlook**
1. サービス正常性受信の為のフォルダーを作成する
2. 1で作ったフォルダーに「仕分けルール」を設定する
サービス正常性は特定のメールアドレスから受信する為、それを元に仕分けルールを作成する。仕分けルールが正常に動作することを確認してからPower Automateの設定に入ること。

**Power Automate**
1. Office 365のOutlookトリガー「新しいメールが届いたとき(V3)」を設定する
このステップでOutlookで仕分けルールを設定したフォルダーを指定する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338126/ce1344db-6850-e25d-dcba-333f4b451148.png" width=50%>


2.各サービスに投稿するアクションを設定する
メールメッセージはHTMLなので、サービスによってHTMLをプレーンテキストに変換するアクションを挟んで可読性を高くすると◎

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338126/d44a7882-772d-22e4-b9ea-912649c9fda3.png" width=50%>


# 参考文献
[Office 365 サービスの正常性をチェックする方法](https://docs.microsoft.com/ja-jp/office365/enterprise/view-service-health)
[Office 365 Management API の使用を開始する](https://docs.microsoft.com/ja-jp/office/office-365-management-api/get-started-with-office-365-management-api)
Homebrew, rbenvの組み合わせでRuby 3.0.0 Preview 1 をインストールする

## 背景
Ruby 3.0.0 Preview 1 がリリースされました。
https://www.ruby-lang.org/en/news/2020/09/25/ruby-3-0-0-preview1-released/

## インストールしてみる

### 最初にやったこと
以下を参考
https://github.com/rbenv/ruby-build#upgrading

```sh
brew update && brew upgrade ruby-build
```

### インストール可能なRubyを確認
```sh
$ rbenv install --list
2.5.8
2.6.6
2.7.1
jruby-9.2.13.0
maglev-1.0.0
mruby-2.1.2
rbx-5.0
truffleruby-20.2.0
truffleruby+graalvm-20.2.0

Only latest stable releases for each Ruby implementation are shown.
Use 'rbenv install --list-all' to show all local versions.
```

stableでlatestなものしか出ていないので`--list-all`で確認

```sh
$ rbenv install --list-all | grep 3.0.0-preview1
3.0.0-preview1
```

あった。

#### Ruby 3.0.0 Preview 1 インストール
```sh
$ rbenv install 3.0.0-preview1
```

#### インストール確認
```sh
$ rbenv versions
  system
  2.6.1
  2.7.0
* 2.7.1 (set by /Users/soul/.rbenv/version)
  3.0.0-preview1
```

## rbenvで使用するRubyバージョン指定
```sh
# システム全体で 3.0.0-preview1 を使用する
rbenv global 3.0.0-preview1

# バージョン確認
ruby -v
ruby 3.0.0preview1 (2020-09-25 master 0096d2b895) [x86_64-darwin19]
```

# 確認
```irb
irb(main):001:0> RUBY_VERSION
#=> "3.0.0"
require 'prime'
#=> true
# Ruby3で導入される右代入
Prime.find {|p| p > 10000} => x
#=> 10007
x
#=> 10007
```
Ruby3で追加される右代入記法が使えるようになっている。
【Linux】文字コード関連

サーバ上でファイルを読んだ時に文字化けしてしまう場合、nkfに渡してやると日本語化してくれたりする。

（例）メールファイルのsubjectが文字化けして読めない場合、以下のようにする。

```
# cat メールファイル名 | grep -i subject | nkf
```

文字コードの確認

```
# file -i memo
memo: text/plain; charset=iso-8859-1
```
```
# nkf --guess memo
EUC-JP
```

memoファイルの文字コードをEUC-JPからUTF-8に変換してmemo_newとして保存

```
# iconv -f EUC-JP -t UTF-8 memo -o memo_new

# nkf --guess memo_new
UTF-8
```
メモ: terminal でグラフ描画 termplotlib

## インストール

```sh
apt install -y \
    python3-scipy \
    python3-seaborn \
    python3-gnuplot \
    python3-pip

pip install termplotlib
```

## グラフ描画

```py:graph.py
import termplotlib as tpl
import numpy as np

x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x) + x
fig = tpl.figure()
fig.plot(x, y, width=60, height=20)
fig.show()
```

![スクリーンショット_2020-09-29_11-43-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/37765fbc-586b-2b3a-f334-336bbac721c7.png)


## csvを利用

```csv:a.csv
1, 3
2, 1
3, 2.5
4, 8
```

```py:graph.py
import pandas as pd
headers = ['x', 'y']
df = pd.read_csv('a.csv',names=headers)
#print(df)

import termplotlib as tpl
x = df['x']
y = df['y']
fig = tpl.figure()
fig.plot(x, y, width=60, height=20)
fig.show()
```

![スクリーンショット_2020-09-29_12-16-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/c3f43812-1077-8702-aef6-236f803543bc.png)
Google Drive APIの設定まとめ

Google Drive APIをPHPから使用するために以下を入れたものの、
設定がよくわからなかったのでまとめ。
https://github.com/googleapis/google-api-php-client

# やりたかったこと
共有ドライブに設置されたファイルをPHPで取得する

# Google Drive APIの設定
APIキー、OAuth、サービスアカウントの３タイプの接続方法があり、
今回はサービスアカウントを使用しての接続をした。

## DriveAPI使用許可設定
1.ログインし、以下よりGoogle APIsのページに移動してGoogle Drive APIを検索
https://console.developers.google.com/apis/library
2.Google Drive APIを押下し、有効化する
3.有効化完了

## 認証ファイル作成
1. 以下のページに移動する
 * https://console.developers.google.com/apis/dashboard
2. 新しいプロジェクトを作成
 * プロジェクト名「任意のプロジェクト名」
3. 作成後、「認証情報」ページに移動し、サービスアカウントの「サービスアカウントの管理」リンクをクリック
4. ヘッダより「サービスアカウントを作成」
 * 名前：任意の名前
 * 説明：省略可能
 * メール：任意のサービスアカウント名@〜（これをコピーしておく※1）
5. 次にキーを作成する「鍵を追加」→「新しい鍵を追加」
6. 「JSON」を選択し、保存ボタンを押す
7. 生成された鍵を保存する

# グループ作成
これはファイルアップロード担当者と、DriveAPIの接続に使用します

1. 以下に接続
  * https://admin.google.com
2. 「グループ」を選択
3. 「グループを作成」リンクをクリック
4.  以下情報を入力して保存
 * 名称：任意の名称
 * メール：任意のメールアドレス@ドメイン
 * 説明：省略可能
5.  「メンバーを追加」で上記※1でコピーしたユーザーを追加する

# PHPサンプル

サービスの設定をして、指定したディレクトリのファイルを取得する。

```
/**
 * Google DriveのAPI認証
 * @return Google_Client the authorized client object
 */
private function getService()
{
    $client = new Google_Client();
    $client->setApplicationName("File Upload ※任意");
    $client->setScopes(Google_Service_Drive::DRIVE_READONLY);
    $client->setAuthConfig('作成した認証ファイルのパス');
    if ($client->isAccessTokenExpired()) {
        $client->refreshTokenWithAssertion();
    }
    return new Google_Service_Drive($client);
}

/**
 * Google Driveからファイルを取得する
 *
 * @return mixed
 */
private function getFiles()
{
    $service = $this->getService();
    // 接続情報を取得
    $optParams = array(
        // ターゲットディレクトリIDを指定する
        'q'                         => "'取得元のディレクトリID' in parents",
        'includeItemsFromAllDrives' => true,
        'supportsAllDrives'         => true,
        /*
         * id：ファイルID
         * name：ファイル名
         * createdTime:ファイル作成日
         * modifiedTime:ファイル編集日
         * lastModifyingUser:最終編集者
         * size:ファイルサイズ
         */
        'fields'                    => 'nextPageToken, files(id,name,createdTime,modifiedTime,lastModifyingUser,size)',
        //'pageSize' => 10,
    );
    return $service->files->listFiles($optParams);
}
```
Django REST framework 3.12とdjoser2.0.5の組み合わせは動かない

多分今日(2020/09/29)、Django REST framework(以下DRF)の最新バージョン3.12系がリリースされました。
このバージョンのDRFにおいて認証にdjoserを使っていると、以下のエラーが出て動きません。

```
TypeError: Abstract base class containing model fields not permitted for proxy model 'TokenProxy'.
```

対応するまではDRFのバージョンを指定して使いましょう。

```
pip install djangorestframework==3.11.1
```
Railsコマンドが正常に操作しない時疑うべきはspring


#動機
Railsを用いてテストコードを作成中に以下のコマンドを打つと正常に動作しなくなったので備忘録としてどのように解決したかを記述

```
$ rails g rspec:request article


Running via Spring preloader in process 15349
Deprecation warning: Expected boolean default value for '--orm'; got :active_record (string).
This will be rejected in the future unless you explicitly pass the options `check_default_type: false` or call `allow_incompatible_default_type!` in your code
You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.
Could not find generator 'rspec:request'. Maybe you meant "rspec:decorator"?
Run `rails generate --help` for more options.
```

#springとは？
ザックリですが
「開発をよりスピードアップさせるため開発しているアプリケーションをバックグラウンドで保持し、「テスト・rakeタスク・マイグレーション」を毎回起動しなくてもいいようにしてくれるRailsアプリケーションのプリローダー」


といいやつに見えて、ここのプロセスが残っていたりするのが問題の可能性があります。

#解決手順

まずはspringのstatusを確認

```
$ spring status


Spring is running:

 3729 spring server | blogapp | started 17 hours ago
```

やはり止まっていました。


次にspringの停止を行います。

```
$ spring stop
Spring stopped.
```

再度状態確認

```
$ spring status
Spring is not running.
```

###再度Railsコマンド実行

```
$ rails g rspec:request article
Running via Spring preloader in process 15565
      create  spec/requests/articles_spec.rb
```

成功しました！

再度コマンド操作を行うとspringも実行されますのでご心配なく

身に覚えの無いエラーが起きた際はspringを疑ってみましょう
Rubyで、TSVファイルからCSVファイル(BOM付き)への変換


# はじめに
Rubyにおけるタブ区切りのファイル（TSVファイル）から、BOM付きのCSVファイルへの変換方法です。

# 目次
０．完成コード
１．BOMを付けたCSVファイルの作成
２．TSVファイル内データの読み込み
３．CSVに1行づつ読んでは書いていく
４．プログラムを実行

# ０．完成コード
```ruby:tsv_to_csv.rb

require 'csv'

# CSVファイルを作成し、bomを付ける。
File.write("meibo.csv", "\uFEFF")

# 'meibo2.txt'の情報を1行毎に読み込み、splitで配列にして、CSVファイルに1行ずつ入れていく。
CSV.open("meibo.csv", "a", force_quotes: true ) do |meibocsv|
  File.foreach('meibo.txt') do |student|
    meibocsv << student.chomp.split("\t", -1)
  end
end
```

# １．BOMを付けたCSVファイルの作成
BOM(Byte order mark)は、Unicodeの符号化形式で符号化したテキストの先頭に着ける数バイトのデータのことを言います。
ExcelはCSVファイルを開くときデフォルトでShift-JISで開こうとするため、UTF-8では文字化けを起こしてしまいます。その対処法として、UTF-8で出力する際にBOMを付けてあげることでExcelにUTF-8で書かれていると認識させて、文字化けを防ぐことができます。
以下のようにしてBOMを付けてます。

```ruby
File.write("meibo.csv", "\uFEFF")
```

# ２．TSVファイル内データの読み込み

読み込むTSVファイルは以下。

```meibo.txt
john	m	18
paul	m	20
alice	f	15
dabid	m	17
jasmin	f	17
```
タブ区切り形式のデータが書かれたmeibo.txtを読み込みますが、１行読み込んでは１行書き込むという手法をとりたいです。タブ区切りデータ１行をsplitで配列に変換した後、そのままCSVファイルに書き込んでいくようにします。

```ruby
File.foreach('meibo.txt') do |student|
  （CSVファイル） << student.chomp.split("\t", -1)
end
```
# ３．CSVに1行づつ読んでは書いていく
上のコードをCSV.openで囲えば、１行読み書きができます。
基本的に、タブ区切りファイルから、CSVファイルへ移すという場合は、１行ずつ処理していきます。なぜならば、仮に１０００万行のような膨大なデータであっても、メモリがオーバーすることを防ぐためです。

```ruby
CSV.open("meibo.csv", "a", force_quotes: true ) do |meibo_csv|
  File.foreach('meibo.txt') do |student|
    meibo_csv << student.chomp.split("\t", -1)
  end
end
```
因みにsplitの第２引数（limit)に、-1を渡しています。
この第２引数の値はデフォルトでは0になっており、配列末尾の空文字列を取り除いてしまいます。
これではTSVに空のフィールドがあったときにうまく行きません。-1を渡してあげることで、解決することができます。

# ４．プログラムを実行
```bash
% ruby tsv_to_csv.rb 
```
データが書き込まれたCSVファイルが生成される。

```meibo.csv
"john","m","18"
"paul","m","20"
"alice","f","15"
"dabid","m","17"
"jasmin","f","17"
```
カンマ区切りのCSVファイルに正しく変換されました。
JavaScriptのスコープ基本事項

#見本

```test.js
class Test {
  constructor() {
   this.test = 'グローバルスコープ';
  }
}

const word1 = 'グローバルスコープ';

function test(){
  let word2 = '関数スコープ';
  if(.....){
    let word3 = 'ブロックスコープ'
  }
}
```


##グローバールスコープ
どこからでもアクセス可能なもの。
また、```let、constを省略した場合```は関数の中であってもグローバルスコープ。

##ローカルスコープ
###関数スコープ
関数の中だけ有効となるもの。
ただし、```letまたはconstを用いて宣言したものだけ```が、ブロックスコープ。
```let、constを省略した場合```は関数の中であってもグローバルスコープ。

###ブロックスコープ
```{}の中```だけで有効なもの。
[Rails]カスタムフォントの設定

# はじめに
アプリ開発でフリーフォントを使用してデザインを変えたのでその使用方法をまとめました。

# 目次
1 フリーフォントの準備
2 フォントの読み込み

# 1 フリーフォントの準備
まず、フリーフォントサイトから自分が使用したいものをダウンロードします。
その後、ダウンロードしたファイル(拡張子ttfまたはotf)をapp/assets/fonts下に配置します。

### 注意事項
フォントはそれぞれ利用条件が異なります。商用可能であっても利用できる範囲に制限があったり、使用時に報告が必要なものもありますので、ご利用の際には必ず配布ページをご確認ください。

# 2 フォントの読み込み
CSSファイルに以下を記述します。

```css

@font-face {
  font-family: “abcdefg”;
  src: url('/assets/abcdefg.ttf') format("truetype");
  font-weight: normal;
  font-style: normal;
}
```

フォントを適用したい箇所にfont-familyを指定します。

#### 例

```css

p {
  font-family; “abcdefg”;
}
```

これでフォントを適用することができました。

# 3 本番環境への適応
このままでは本番環境でフォントが適用されなかったため、以下を変更しました。

```/config/production.rb
# 変更前
config.assets.compile = false
# 変更後
config.assets.compile = true
```

これにより本番環境で読み込まれていなかった画像ファイルも表示することができました。

# 参考リンク
https://qiita.com/dir_sh0606/items/ce605b70f1cb333f9d59
https://qiita.com/kinpin/items/bd7c9a7d7a739e297742
whoコマンドメモ

ログインしているユーザー、ログイン時間、接続元などが表示される。

```
$ who
miisuke     pts/0        2019-07-19 13:32 (gateway.test.jp)
```

-H をつけた方が項目名がついてわかりやすいかも。

```
$ who -H
名前     端末         時間             コメント
miisuke     pts/0        2019-07-19 13:32 (gateway.test.jp)
```

サーバーが起動した時間を表示

```
$ who -b
         system boot  2014-07-07 14:26
```

uオプションもつけてみる。

```
# who -uH
USER     LINE     LOGIN-TIME   IDLE  FROM
number   tty1     Nov 21 01:54  old
number   pts/1    Nov 22 01:16 06:37
hoge     pts/0    Nov 21 16:24   .   (xxx.xxx.xxx.xxx)
number   pts/2    Nov 22 01:29 02:08
hoge     pts/3    Nov 23 03:03 00:06 (xxx.xxx.xxx.xxx)
```
＜IDLE列の表示について＞
. が表示されている場合は、ユーザーが1分以内に端末操作を行っているということ。
old が表示された場合、ユーザーが24時間以上端末操作を行っていないということ。
Splunk 時刻(_time)をファイル名から取得するには

データの中にタイムスタンプを持っていなかったり、出力時刻がファイル名に記載されている場合の対処法。
以前のSplunkVersionではdatetime.xmlを駆使する形だったけど、7.2以降は INGEST_EVAL が transforms.conf の中で使えるようになり、Eval関数で柔軟に定義できるようになってます。
まずベーシックな INGEST_EVAL の使い方は

```ruby:transforms.conf
[eval_sample]
INGEST_EVAL = create_field = length（_raw）* 2
```
```ruby:props.conf
[sample]
TRANSFORMS = eval_sample
```

上のように transforms.conf にフィールド(create_field)を作成して、取り込むデータの長さを2倍した値を代入 するような形をEvalでかけるので、それをprops.confから呼び出す。

これを使ってファイル名に埋め込まれた日付から_timeを取得
ファイル名  : PoC_test_2020-09-07T11-15-02
フォーマット : PoC_test_%Y-%m-%dT%H-%M-%S

```ruby:transforms.conf
[eval_time]
INGEST_EVAL = _time=strptime(replace(source,".*(?=/)/",""),"PoC_test_%Y-%m-%dT%H-%M-%S")
```

```ruby:props.conf
[date_from_filename]
TRANSFORMS = eval_time
```
以上です。


以下リファレンス
https://docs.splunk.com/Documentation/Splunk/8.0.6/Admin/Transformsconf
https://docs.splunk.com/Documentation/Splunk/latest/Data/IngestEval
https://community.splunk.com/t5/Getting-Data-In/How-do-you-extract-a-timestamp-from-a-filename/m-p/427089
Web上でHLSを再生する

# 準備
##HLSファイルはffmpegで作成する
1. ffmpegのインストールは別記事参照
[ffmpegインストール](https://qiita.com/Stchan/items/d0e1ac8f4d585d8bd998)

1. ffmegでmp4からm3u8,tsファイルを作成するのは下記参照
[ffmpeg を使って mp4 を HLS に変換する](https://blog.foresta.me/posts/convert_mp4_to_hls_with_ffmpeg/)

# コードを記述する
1. 下記を参考にhls.jsを利用して再生用のhtmlを作成
~~[おすすめhls web player hls.jsを使ってみる](https://www.techlive.tokyo/archives/4295)~~
[動画をストリーミング配信する方法](https://itskillmap.com/menu2_30/)
※こちらの方がわかりやす。『３．ストリーミング配信の方法』を参照

```html
<h1>hls-video</h1>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="video_smaple" controls>
<script>
  if(Hls.isSupported()) {
    var video = document.getElementById('video_smaple');
    var hls = new Hls();
    hls.loadSource('./video/video.m3u8'); //ここで.m3u8ファイルを指定
    hls.attachMedia(video);
 }
</script>

```

~~上記を実施すると"Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first."が発生し再生できない~~
※変更により自動再生しないのでエラー発生しない

# 対策
~~[Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first #1991](https://github.com/video-dev/hls.js/issues/1991)を参考にミュートで実行。~~
~~※参考　[Autoplay Policy Changes](https://developers.google.com/web/updates/2017/09/autoplay-policy-changes)~~

~~※ミュートの解除は今後の課題とする~~

# 参考
[hls.jsでお手軽 動画・生配信視聴プレイヤー作ってみた 【お盆休みの自由研究2019その1】](https://ch.nicovideo.jp/skas-web/blomaga/ar1798847)
[HLS（HTTP Live Streaming）で動画を配信・再生してみよう](https://www.yaz.co.jp/tec-blog/web%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9/212)
[【PDF】FFmpegの本](https://booth.pm/ja/items/830235)

#hlsをmp4に変換する
[HLS(m3u8+ts)形式の動画をFFmpegを使ってmp4に一発変換する方法](https://shotaste.com/blog/convert-hls/)

#[ライブ動画配信プロトコル（HTTP Live Streaming, HLS）の概要図解メモ（AbemaTV／FRESH!）](https://did2memo.net/2017/02/20/http-live-streaming/)

#[暗号化されたHLSストリームをブラウザのHAR経由で保存する](https://qiita.com/okuoku/items/eb21fac7c27a56e0a659)
【Java開発】ロジック練習問題 - 逆三角数字

#初めに

皆さん。こんにちは！

DreamHanksの254cmです。

今回はロジック練習問題とその解説について作成していきます。

この記事あるようなロジック脳トレ問題のまとめは[こちら](https://blog.dreamhanks.com/category/java%e3%83%ad%e3%82%b8%e3%83%83%e3%82%af%e5%95%8f%e9%a1%8c/)です。

Java記事のまとめは[こちら](https://qiita.com/DreamHanks/items/6b1996e1f8ed66bbd456)です。


#逆三角数字

javaプログラムを作成して下記のような出力結果を出してください。

![20200929 問題サンプル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708649/c615434a-61c1-12b4-e0c8-76609ce12565.png)


##解説

上記の画像を見ると一つ目の行で

```
012345678910
```
0から10まで出力されています。

二つ目からは両方の数字が一つずつ減って

```
 123456789 
  2345678  
   34567   
    456    
     5     
```
になります。

0~10までの数字を一行ずつ出力しますが、両方の数字を切り詰めながら出力するのがポイントです。

つまり、0~10まで出力するfor、両端の数字の場合に処理を分けるif

上記の処理を6回繰り返すforが必要になります。

※上記の画像は6行を出力しているので、6回繰り返します。


しかし、両端の数字を消すだけではいけません。

両方の数字を消しさえすれば

```
012345678910
123456789
2345678
34567
456
5
```
になって問題の画像のようになりません。

消された数字の位置にスペースを入れて逆三角形の姿が維持されるようにします。


#ソースコード

```java
public class LogicSample01 {

	public static void main(String[] args) {

		int[] a = new int[11];
		for (int i = 0 ; i<a.length;i++) {
			a[i] = Integer.parseInt(args[i]);
		}
		for (int i= 0 ;i<6;i++) {
			for (int j = 0;j<a.length;j++) {
				if(j<i||j>a.length-i-1) {
					System.out.print(" ");

				}
				else {
					System.out.print(a[j]);
				}
			}
			System.out.println();
		}
	}
}
```

#終わりに

今回の記事は以上になります。

ご覧いただきありがとうございます。

この記事あるようなロジック脳トレ問題のまとめは[こちら](https://blog.dreamhanks.com/category/java%e3%83%ad%e3%82%b8%e3%83%83%e3%82%af%e5%95%8f%e9%a1%8c/)です。
Rubyのメソッド内で引数に再代入してから `super` と呼び出した場合 → 再代入したものが使われる

* 「たしか `super` を引数なしで呼び出したら、現在のメソッドの引数と同じものが渡されるんだっけ」
* 「あれ？　引数に**代入**して上書きした場合[^assign]、元のと新しいののどっちが使われるんだろう？」

[^assign]: 代入でなく破壊的メソッドを作用させただけの場合は、元のも新しいのもオブジェクトとしては同一なので今回の疑問の対象外

と分からなくなったので、実験してみた。

```ruby
class Foo
	def mtd(str)
		puts "[Foo:1] str => %p (%#08x)" % [str, str.__id__]
	end
end

class Bar < Foo
	def mtd(str)
		puts "[Bar:1] str => %p (%#08x)" % [str, str.__id__]
		str *= 2
		puts "[Bar:2] str => %p (%#08x)" % [str, str.__id__]
		super
	end
end

Bar.new.mtd("abc")
```

```text:結果
[Bar:1] str => "abc" (0x00003c)       <-- 仮引数に渡された元のオブジェクト
[Bar:2] str => "abcabc" (0x000050)    <-- 再代入して上書きしたオブジェクト（IDが異なる）
[Foo:1] str => "abcabc" (0x000050)    <-- 結果：上書きしたほうが使われる
```

`super` とだけ書いた場合は `super(str)` という感じに補完してくれて、結果として再代入したほうが使われる。

念のためリファレンスマニュアルを見たら、**[サンプルコード](https://docs.ruby-lang.org/ja/latest/doc/spec=2fcall.html#super)にしっかり書いてあった**。（やはり文章での説明だとどちらにも解釈できるので難しい）
firebase login で "Assertion failed: new_time >= loop->time, file src\win\timer.c, line 37"と出てコケる

# firebase login で "Assertion failed: new_time >= loop->time, file src\win\timer.c, line 37"と出てコケる

Intelのice lake chipを搭載したwindows 10のパソコンで発生する、nodejs内のバグが原因のようです。

node v14.6.0で修正のパッチがあたっているので、それ以上のバージョンにアップデートすれば解決します。

Github 
Assertion failed: new_time >= loop->time #1633
https://github.com/libuv/libuv/issues/1633
> Newest Node release, Node v14.6.0 contains the fix for this. Give it a spin.

nodeのバージョンを変えたくない人は、好きなバージョンに下記のパッチを自分で当ててビルドすれば動くようです。
https://github.com/libuv/libuv/commit/796744869669842bd5405a71de8ba60b1556fc24
CloudFront + S3 で SPA 環境を構築

個人メモ
時間があれば、もう少し詳しく書く。



CloudFront, S3 のデフォルトで index.html を設定する方法があるが、
HTTPステータスコードが変な感じになるので、lambdaEdgeで対応

CloudFrontのDefaultにlambdaEdgeを指定。
それ以外は、lambdaEdgeを呼ばない様に。


参考
https://hackernoon.com/how-to-host-a-single-page-application-with-aws-cloudfront-and-lambda-edge-39ce7b036da2
自分用k8sメモ（整理中）

## ClientIP Serviceの落とし穴とHeadless Serviceの活用

ClientIP Serviceはvipを持っており、それに対してのRequestをiptablesのロードバランシング機能を利用してロードバランシングするが、http2のロードバランシングには対応していない.
Headless ServiceはDNS Round Robinでのロードバランシングになるので、http2等のClientIP Serviceが対応していないhttpプロトコルを利用する場合は、Headless Serviceを利用する.

## namespaceとそれに関するディスカバリ

podから他のnamespaceのサービスはこんな感じで見える.

```
[service].[namespace]
```

理由は`resolve.conf`に設定が書いてあるから、名前解決ができる

```
# コンテナ内のresolv.confを確認
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod --command -- cat /etc/resolv.conf
nameserver 10.11.240.10
search default.svc.cluster.local svc.cluster.local cluster.local google.internal
options ndots:5
```

しかし、Serviceで書けるselectorには他のnamespaceを指定する手段が提供されていないので、Serviceは同一namespaceのPodにしかロードバランシングできない.
この課題を解決する為にEnvoy等を利用する.

## ConfigMapとSecret

ConfigMapは更新しても既に立ち上がっているPodには反映されない(古いのを見たまま).
反映させるためにはPodを再起動しなければならない.

Secretを更新とか、リソースを削除した場合はPodを立ち上げ直さなくても反映されるのかはわからないので要調査. (環境に反映されてもRailsとかGoのアプリケーションは大体起動時に環境変数を読み込んでその後値を保持しているので、アプリケーションの振る舞いを変えるにはやはり再起動しないと行けないけどね

## ExternalName Serviceの注意点

いつ使うのかわからないけど、ClusterIP Service使ってたけど、ExternalName Serviceに切り替える場合、spec.clusterIPを明示的に空にする必要がある.
空じゃなくてもkubectlのバリデーションは通過してDeployされてしまうらしい(その際の挙動がどうなっているのかは知らない).

この様なスキーマをこう定義しないと行けないよね。等のポリシーはOPA(Open Policy Agent)で制御可能らしい.
この辺の奴をCIに組み込んでバリデーションするのが良いらしい.

**参考リンク**
* https://thinkit.co.jp/article/17511
* https://engineering.mercari.com/blog/entry/introduce_conftest/
* https://argoproj.github.io/argo-cd/

## その他雑なメモ
* https://kubernetes.io/ja/docs/concepts/containers/container-lifecycle-hooks/#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%83%95%E3%83%83%E3%82%AF
* https://kubernetes.io/ja/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
SQLのSUMを使うと結果がNULLになる！？その対処法

# はじめに

SQLでの集計時にSUMを利用するシーンは多くあると思いますが
結果に*`NULL`*が返って来ることがありました。
`0`として返して欲しかったのでその対処法を紹介します。


# 検証

そもそも、なぜ*`NULL`*が返ってきてしまうのか？
SUMしてるんだからどんな事があろうと`0`で返ってくるでしょ！という思い込みを技術的に検証します！


### サンプルデータ

|購入者|購入価格|
|---|---|
|A|100|
|B|120|
|C|NULL|
|A|80|
|A|200|
|C|NULL|
|D|0|


### 全員の合計額を取得

*`NULL`*は無視され、ちゃんと合計額が取得できました。

```sql
SELECT SUM(`購入価格`) FROM table_name

-- 結果：500
```


### Cさんの合計額を取得

SUMする対象のカラムが全て*`NULL`*の場合は、*`NULL`*になりました！

```sql
SELECT SUM(`購入価格`) FROM table_name WHERE `購入者` = 'C'

-- 結果：NULL
```


## NULLを0で返すには「COALESCE関数」を使う

COALESCE関数は*`NULL`*だった場合に、引数に指定した値を表示してくれます。
これで思うようなデータになりました！

```sql
SELECT COALESCE(SUM(`購入価格`), 0) FROM table_name WHERE `購入者` = 'C'

-- 結果：0
```



# さいごに

テーブル定義は大事！！！
でも、たまにちゃんとしていないテーブル定義もあるのでこういう小技も必要…
アプリの効果的なログ出力にするための考察

## はじめに

アプリ開発でログ出力をする際に気を付けておいた方がよいと思ったことのメモ書きです。
とりあえず、体裁を整えたレベルでの投稿なので、時間があればブラッシュアップしていきます。


## 1. 設計

### ファイル名

機能名と出力年月日時分秒の組み合わせが一般的です。

- {機能名}_yyyyMMddHHmmss.log
- yyyyMMddHHmmss_{機能名}.log

更に「OK / NG」「N(Normal) / E(Error)」「結果ステータス」といった内容を合わせて出力しておくと、ファイルを開かなくても結果が分かるのでよいと思います。


### 出力内容

ログの目的を考えると以下は必須になります。

- 開始時刻
- 終了時刻
- 機能名
- パラメータ値

### フォーマット

大量のログを調査用に集計する際に grep 結果をExcelに貼って体裁を整えれば完了といった形が望ましいです。ですので、サマリ行があるとベターです。


```log:「結果概要\,」でgrepすれば集計が楽
2020-09-21 13:50:30 [I] 処理開始
：
2020-09-21 13:53:40 [I] 処理結果：0
2020-09-21 13:53:40 [I] 処理終了
2020-09-21 13:53:40 [I] 
2020-09-21 13:53:40 [I] 結果概要（機能名,開始時刻,終了時刻,処理時間,結果ステータス）
2020-09-21 13:53:40 [I] 結果概要,ＸＸ処理,2020-09-21 13:50:30,2020-09-21,0 13:53:40,00:03:10,0 
```


## ２．開発

### ログライブラリを使用する

log4net や log4j など、既存のものを使いましょう。
開発効率だけでなく、仕様が汎用化されるため保守性も上がります。

### 独自のログライブラリを作成する

独自で作成する場合は、既存のログライブラリを参考にすることになります。
以下は、意外と考慮漏れになる致命的な実装です。

- 処理中にファイルを開かれた場合にシステムエラーにならない。止まらない。
- ログ出力によって処理が遅くならない。（別スレッドでの実行がベター）

### ライフサイクルを考慮する

稼働当初からのログが残りっぱなしのシステムをたまに見ます。削除のタイミングも設計して実装するようにしましょう。


## おわりに

エラーをいかに効率よく見つけるか、ボトルネック個所はどこかといった調査の視点も入れた方がよいですね。
LogStashの設定ファイルに関する所感

初LogStashです。

設定ファイルを書いていたときに、様々なサンプルを試したり、他の人の環境にも配慮して書いたり、これをそのまま本番に持っていける形にしたい、と色々調べていて、いい感じに出来そうだったので所感をメモします。

### 複数の設定を扱いたい場合はmultiple pipelinesを使う

複数の設定ファイルを扱いたくなる場合があります。単純に2つの異なるファイルを扱いたいときですね。
しかし`path.data`が競合している状態では2つ以上を同時に動かせません。

``` bash
logstash -f foo.cfg &
logstash -f bar.cfg # エラー
```

この対処法としては3つぐらいあるようです。

- 1つの設定ファイルに条件分岐を書く
  - inputでtagsを与え、if文でtagsを見てfilterやoutputの処理を分ける
  - 影響なく設定を足していくのは大変
- 起動時に`--path.data`を与えて競合が起きないようにする
  - Javaプロセスが2つ動くのでちょっと重い
- multiple pipelinesを使う
  - pipelines.ymlの管理が必要（でも他と比べればマシ）

おすすめはmultiple pipelinesです。未来永劫1つの設定ファイルしか扱わないと決まっている場合以外は、たとえ1つからでもmultiple pipelinesで始めておいたほうが良いと思います。扱う設定ファイルが増えて嫌かもしれませんが、後からmultiple pipelinesに切り替えるよりは良いです。





### `--path.settings DIR`で設定ファイルの置き場所を変更する

logstashはデフォルトはインストール方法やインストール先に依存したファイル構成をしています。
https://www.elastic.co/guide/en/logstash/current/dir-layout.html

これは最初に動かしてみる分には楽ですが、複数人で開発したりインスタンスを複数立てたくなった場合にこの構成は障壁になると思っています。

ところで、コマンドで `--path.settings DIR` を与えると、logstash.ymlの配置場所をデフォルトから変えることができます。logstash.ymlは他のデータ（上記のpath.dataやログなど）の配置先を明示できます。これを利用します。

以下は`/path/to/directory`を起点に考えた場合の設定例です。

``` /path/to/directory/config/logstash.yml
path.data: ./data
path.logs: ./logs
```

``` /path/to/directory/config/pipelines.yml
- pipeline.id: foo
  queue.type: persisted
  path.config: ./config/foo.cfg
```

``` /path/to/directory/config/foo.cfg
input {
  exec {
    command => "echo hello"
    interval => 5
  }
}

output {
  stdout { codec => rubydebug }
}
```

起動コマンドは以下のようにします。

```
cd /path/to/directory
logstash --path.settings "./config"
```

ポイントはファイルの配置と実行の時以外で`/path/to/directory`が出てこないところです。


設定ファイル内で相対パスを指定すると、現在の作業ディレクトリを基準に解決してくれるようです。（設定ファイルからの相対パスでないところが若干わかりにくいですね）
ただ、配置場所を気にしなくてよくなるので、各開発者の環境でgit cloneしたらそのまま実行ということができるようになりますし、既にデフォルトで入っている設定を汚すこともありません。
また、こうするとLinux/Windows問わない設定にできるので、Windowsで開発してLinuxで運用するというケースがある場合はこの形にしておくと楽だと思います。



### 設定ファイル内での変数の利用

環境によって微妙に値が違うときがあります。つまり変数を使いたくなる場合があると思いますが、環境変数が扱えます。
また、デフォルト値が設定できるので、いつもは環境変数無しで開発したりして、本番環境では環境変数を設定しておくという形が取れます。

https://www.elastic.co/guide/en/logstash/current/environment-variables.html

### 処理の共通化について

input/filter/outputの設定を共通化したいという場合は次が参考になるかもしれません。

https://www.elastic.co/jp/blog/how-to-create-maintainable-and-reusable-logstash-pipelines

ただ私はフィルター処理がglobの順序性に依存するのはあまり良くない気がしています。あと、行き過ぎた共通化にも思えます。
こういったETLなツールで変に共通化にこだわると、処理の順序性が追いにくくなりかえって読みにくくなる、他に影響がないか怖くなる、という経験をしています。（私の書き方がよくないだけかもしれません）

なので今のところ、多少冗長でも1パイプライン1ファイルで書いたほうがいい気がしています。
Shopifyパートナーになりたい人が読むべきオススメ記事３選

# はじめに
今回は、Shopifyパートナーになりたい人が読むべきオススメ記事を３つに厳選して紹介していきます。

# そもそもShopifyとは
Shopifyとは一言でいえば'Amazonキラー'と呼ばれるECプラットフォームです。

簡単にオンラインストアを開設することができ、各々の会社や個人が独自のECサイトを持つことができます。

オシャレなサイトを作成しやすく、ブランディングや集客がしやすいという点から、徐々に日本でも広がりを見せています。

# Shopifyパートナーとは
以下は別のブログからの引用です。

>Shopifyパートナーは、Shopifyストアの構築や移行、アプリやテーマの開発、新規顧客を紹介するアフィリエイト活動により報酬を得ることができます。Shopifyパートナーの収益は、Shopify自体の収益より多いと言われています。Shopifyは、エコシステムを活発にすることでユーザー数と売り上げを伸ばしています。

引用：[Shopifyパートナープログラムとは?できることや報酬を調べてみた](https://unreact.jp/blog/about-shopify-partner)

まとめると、ShopifyパートナーとはShopifyを用いて行う業務を代行することにより収益を稼ぐプログラムだと言えます。

それでは、次からShopifyパートナーになりたい人が読むべきオススメ記事を紹介します。

#Shopifyパートナープログラムとは?できることや報酬を調べてみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/752045/4620d73b-bbcf-10f2-0982-9590ac4aad50.png)
[Shopifyパートナープログラムとは?できることや報酬を調べてみた](https://unreact.jp/blog/about-shopify-partner)

こちらは株式会社UnReactが運営を行っている[日本一分かりやすいShopifyブログ](https://unreact.jp/)の記事です。

ShopifyパートナーについてやShopifyパートナーになったらできること、Shopifyパートナーになる方法などが網羅的にまとまっています。

Shopifyパートナーが受け取ることができる報酬なども知ることができるのも良いですね。

また、Shopifyパートナーになる方法は画像付きで説明されいるため、迷うことは無いでしょう。

オススメの記事です。

#Shopifyパートナープログラムについて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/752045/13beebb2-4318-db03-99de-2aef5b893095.png)

[Shopifyパートナーについて](https://help.shopify.com/ja/partners/about)

こちらはShopifyJapan公式が運営を行っているShopifyパートナープログラムの解説記事です。

公式が出している情報のため、間違いがない情報を知りたい方におすすめです。

# Shopify Partner（パートナー）とは？世界で注目されているエコシステム
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/752045/91a54d0e-958e-47d5-82d5-b3e282e2b35f.png)

[Shopify Partner（パートナー）とは？世界で注目されているエコシステム](https://commerce-media.info/blogs/ec/shopify-partner)

こちらの記事もShopifyパートナープログラムについて知る上でオススメの記事です。

情報が網羅的にまとまっており、細かいところまできちんと書いてあります。

Shopifyパートナープログラムに申し込む前に一度目を通してみると良いでしょう。

#終わりに
今回はShopifyパートナーになりたい人が読むべきオススメ記事を３つ紹介しました。

少しでも皆様の役に立てれば幸いです。
Nginxでサブドメインとバーチャルホスト設定

Nginxでサブドメインとバーチャルホストを作成する方法になります。
今回の以下の構成で。

| ドメイン | ディレクトリ |
|:---|:---|
| https://domain-name.com  | /usr/share/nginx/html  |
| https://sub.domain-name.com  | /usr/share/nginx/html/sub  |

```/etc/nginx/conf.d/virtualhost.conf``` を作成します。

```/etc/nginx/conf.d/virtualhost.conf
server {
    listen 80;
    server_name sub.domain-name.com;
    root /usr/share/nginx/html/sub;

    location / {
      index index.html;
    }
}
server {
    listen 80;
    server_name domain-name.com;
    root /usr/share/nginx/html;
}
```
サブドメインが付かないもの最低限の設定にしています。
まず```/etc/nginx/nginx.conf```から読み込まれるので、そこを最低限邪魔しないようにしてます。

※AWSのEC２＋ELB＋Route53でも同様の構成で動作検証を行いました。
ゼロから作るDeepLearning　備忘録

#概要
「ゼロから作るDeepLearning」を読んだので、自分なりに参考になった点などを備忘録としてまとめました。
なにかご指摘などあれりましたら、メッセージをいただけると幸いです。

##2章　パーセプトロン
・パーセプトロンとは
　　・複数の信号を入力として受け取り、ひとつの信号を出力する
　　・パーセプトロンの信号は　流すか流さないかの二値の値
・パーセプトロンでは，「重み」と「バイアス」をパラメータとして設定する
・パーセプトロンを用いて，ANDやORゲートなどの論理回路を表現できる
・多層のパーセプトロンは、理論上コンピュータを表現できる

##3章　ニューラルネットワーク
・ニューラルネットワークとは
　　パーセプトロンの考え方を応用したもので、入力層からのデータが中間層を通り、最後に出力層で求める出力を表現する
・活性化関数とは
　　入力信号の総和を出力信号に変換する関数のこと
・ニューラルネットワークで使用される活性化関数
　　ステップ関数
　　シグモイド関数


##4章　ニューラルネットワークの学習
・ニューラルネットワークは，データから学習できる
・損失関数
　　・最適なパラメータに近づくための指標となる
　　・よく使用される関数「２乗和誤差」、「交差エントロピー誤差」
・２乗和誤差
　　出力と正解データの差の２乗の総和を求める。この総和が小さければ小さいほど、出力と正解データの誤差が少ないことになる
・交差エントロピー誤差
　　出力の自然対数と正解データとの積を計算する。
・重みパラメータを更新する際には，重みパラメータの勾配を利用して，勾配方向に重みの値を更新する作業を繰り返す
・微小な値を与えたときの差分によって微分を求めることを数値微分という
・数値微分によって，重みパラメータの勾配を求めることができる
・数値微分による計算には時間がかかるが、その実装は簡単である。一方、自称で実装するやや複雑な誤差逆伝播法は、高速に勾配を求めることができる。

##5章　誤差逆伝播法
・誤差逆伝播法とは
　　数値微分による勾配の計算は、実装が平易だが、計算に時間がかかるという難点があるため、微分計算を効率的に行う誤差逆伝播法を使用する
・計算グラフを用いることで、計算過程を視覚的に把握することができる
・計算グラフのノードは局所的な計算によって構成される。局所的な計算が全体の計算を構成する
・計算グラフの順伝播は、通常の計算を行う。一方、計算グラフの逆伝播によって、各ノードの微分を求めることができる
・ニューラルネットワークの構成要素をレイヤとして実装することで、勾配の計算を効率的に求めることができる
・数値微分と誤差逆伝播法の結果を比較することで、誤差逆伝播法の実装に誤りがないことを確認できる

##6章　学習に関するテクニック

##7章　畳み込みニューラルネットワーク
・畳み込み層とは
　　画像は3次元の形状であり、空間的情報を含む。その形状を維持しつつ、次の層にデータを出力する
・プーリング層とは
　　タテ／ヨコ方向の空間を小さくする
・ディープラーニングの発展に、ビッグデータとGPUが大きく貢献している

##8章　ディープラーニング
・層を深くすることで、ネットワークのパラメータを少なくできる
・ディープラーニングの実用例
　　・物体検出
　　・セグメンテーション
　　・画像キャプション生成
・多くの問題では、ネットワークを深くすることで、性能の向上が期待できる
・ディープラーニングを用いたアプリケーションとして、画像のキャプション生成、画像の生成、強化学習などもある
超解像アルゴリズム「PULSE」の論文をかみ砕いて、5分で理解してみる

[こちら](https://qiita.com/mine820/items/25833213b8028c3f5155)の記事でPULSEを動かしてみましたが、やはり中で何をしているのかが気になりますので、[ソースコード](https://github.com/krantirk/Self-Supervised-photo)を参考に、[論文](https://arxiv.org/abs/2003.03808)を理解してみます。

論文全部を理解するのは大変なので、ポイントだけ抑えて、5分で理解できるようにしてみます。

# タイトル、作者
```text
PULSE：生成モデルの潜在空間探査による自己教師あり写真アップサンプリング
Sachit Menon、Alexandru Damian、Shijia Hu、Nikhil Ravi、Cynthia Rudin
デューク大学
ノースカロライナ州ダーラム
{sachit.menon、alexandru.damian、shijia.hu、nikhil.ravi、cynthia.rudin} @ duke.edu
```

メノンさんとダミアンさんの共著です。

# 今までの超解像の問題
今までの超解像の手法では、細かい部分（周波数成分が高い）でぼやけるという問題がありました。
これは、ロスの計算で、正解画像と超解像画像の差をMSE（平均二乗誤差）で求めているためでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/9fa5fa14-966e-7bef-bab6-cb92efb9dc9c.png)

MSEを改良した方法も出てきてますが、ぼやけは改善されていないようです。

# PULSEの手法
以下の3つの特徴があります。

- StyleGANを使用して超解像画像を生成し、そこからダウンスケールした画像を作成します
- 「正解画像－超解像画像」での比較ではなく、「入力画像－ダウンスケールした画像」で比較します
- StyleGANに渡す潜在変数を、高次元ガウス分布（球の表面）に従うようにします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/4be9da5f-3a52-90f6-bfc8-2e8866fd9ab5.png)

StyleGANで画像を生成する際に使用する潜在変数を調整していきます。
超解像画像の生成のところはStyleGANをそのまま使うので、そこで画像がぼやけることはありません。

# ロスの計算
2つのロスを使用します。
（難しい式は省略）

- MSE（平均二乗誤差）で、低解像度画像間の差を計算
- GEOCROSSで、潜在変数が高次元ガウス分布（球の表面）に乗るように調整

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/fef7360f-1146-8c3a-eb6b-ffeb80c4921f.png)

この2つのロスにそれぞれ重みを掛けて、全体のロス値としています。
（実装コードでは、L1ロスも指定できるようになっています）

なお、GEOCROSSは以下のように計算しています。

```python
X = latent.view(-1, 1, 18, 512)
Y = latent.view(-1, 18, 1, 512)
A = ((X-Y).pow(2).sum(-1)+1e-9).sqrt()
B = ((X+Y).pow(2).sum(-1)+1e-9).sqrt()
D = 2*torch.atan2(A, B)
D = ((D.pow(2)*512).mean((1, 2))/8.).sum()
```

ここでは「latent」が潜在変数（18x512のランダムな値にガウス関数を掛けたもの）になります。

# 補足
- 学習時間はかかりませんが、空間探索するため、多少処理時間がかかります
- 使用しているStyleGANは「CelebA-HQ」で学習済みのモデルを使用しています
- ガウシアンの値もすでに計算済みのものを使用しています
- 実装コードのフレームワークはPyTorchを使用しています

# 最後に
ざっくりと書きすぎているため、間違った記述があるかもしれませんが、もし気づいた方がいらっしゃいましたらご指摘いただけるとありがたいです。
liquidのasset_urlフィルタについて

前作[Shopify Liquid言語 CSS上でLiquidを使う方法](https://qiita.com/aliceroot0678/items/e10fac2c3d1b18e55431)の続き？
というか、画像を読み込むときのフィルタ、asset_urlフィルタについて

# imgタグ→asset_url
画像をassets/から読み込む。
:warning::warning::warning:読み込む画像ファイルは**assets直下**にないといけない。フォルダとかもつくっちゃだめ！！:warning::warning::warning:
assetsフォルダの中が大変なことになってるけど仕方ないらしい！:frowning2:

```liquid
<img src= "url" alt="">

<img src="{{ "url" | asset_url }}" alt="">

```
`|asset_url` はliquidのurlフィルターの一つ。フィルターによって出力結果を変えることができる。

>asset_url
Returns the URL of a file in the "assets" folder of a theme.
>>(Google翻訳)テーマの「assets」フォルダー内のファイルのURLを返します。
>>[Shopify公式- filters/url-filters](https://shopify.dev/docs/themes/liquid/reference/filters/url-filters)

## ちなみに
urlフィルターの機能は他にも似たようなのがたくさんある。`global_asset_url`、`file_url`、`img_url`とか。下の`link_to`もurlフィルターの一種。
特に、上記のコードは画像のurlがほしかったので、「`asset_url`と`asset_img_url`とどっち使うんだ？:thinking:」と悩んだ。ので、
それについて少しだけメモ。:point_down_tone2::point_down_tone2::point_down_tone2::point_down_tone2:
### `asset_img_url`

>Returns the asset URL of an image in the "assets" folder of a theme.
>accepts an image size parameter .

こっちはassetsフォルダ内の画像ファイルのurlを返す。
あと、画像のサイズのパラメータを受け取ることができる。
（今回は、画像のサイズは別で指定していたので、問題なさそうなので`asset_url`にした。ホントはだめかも:cold_sweat:）
#### 逆に画像ではない場所で、asset_img_urlを使ったらどうなるか？
assetsフォルダ内の、元々は`asset_url`フィルタで呼んでいたcssに対して試してみた。:writing_hand_tone2:
すると、見事にcssが崩れ、ソースを表示すると`<link href...>`の形をとっていなかったので、
**画像じゃないとこに`asset_img_url`を使うのはだめ！学んだ**:clap_tone2::clap_tone2:


# link_to
aタグ的な役割だけど、、、
クラスつけたりとかHTMLを構えないらしい。:pensive:外側にタグつけてそこにスタイルを適用して対応した。

```liquid
<a href="リンク先url">text</a>
              ↓
{{ 'text' | link_to:"リンク先url"}}

```
PILで背景透過。（putalphaがNoneType Objectを返す時の対処法）【Pillow】

![fashion-wear-of-a-man-in-black-long-sleeve-3678375.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/9f852f50-e7b1-0206-46f4-2b70bfc45b50.jpeg)![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/4b74ebc9-f0f8-274c-633f-ecd8352277ad.jpeg)![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/a618b4d0-c0a7-0201-d33a-cc1d270d2210.png)
たとえば、上記のような画像にマスク画像を適用して背景を透過したいとします。
以下でOK。

```python

from PIL import Image

img.putalpha(mask)
img.save(writepath)
```

このときに、作った背景透過画像を変数に当て込むとエラーになります。
putalphaメソッドがNoneタイプのオブジェクトを返すからだそうです。

```python
from PIL import Image

img = img.putalpha(mask)
img.save(writepath)
""" PIL: AttributeError: 'NoneType' object has no attribute 'save'
```
最初のコードとのちがいわかりましたか？
最初のコードでやると保存できます。

ちなみに、人型のマスクで切り抜く方法は[こちらの記事](https://qiita.com/john-rocky/items/d8adeb91c747011f76f9)。

🐣

****
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[MLBoysチャンネル]
(https://www.youtube.com/channel/UCbHff-wfjTnB3rtXIP6y0xg)
[Medium](https://medium.com/@rockyshikoku)

[相棒](https://twitter.com/oka_yuuji)
[note](https://note.com/oka_yuuji)
UnityChanSSUをAndroid実機ビルドした際シェーダのコンパイルエラーで失敗した時の対処法

個人的に偶然キレイなビジュアルが作れたので、PCではなくスマホで動かしたくなりました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">購入したUnityアセットを組み合わせたら、UnityChanのダンス影練に遭遇みたいな絵になった。<a href="https://twitter.com/hashtag/Unity?src=hash&amp;ref_src=twsrc%5Etfw">#Unity</a> <a href="https://twitter.com/hashtag/madewithunity?src=hash&amp;ref_src=twsrc%5Etfw">#madewithunity</a> <a href="https://t.co/u7wKPoiN8H">pic.twitter.com/u7wKPoiN8H</a></p>&mdash; 大庭俊介@UXエンジニア (@ohbashunsuke) <a href="https://twitter.com/ohbashunsuke/status/1309085175578583045?ref_src=twsrc%5Etfw">September 24, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


Androidビルドした所、UniversalToonシェーダのコンパイルエラーで失敗。

>Shader error in 'Universal Render Pipeline/Toon': invalid subscript 'vertexSH' at /Unityプロジェクトまでのパス/Packages/UnityChanToonShaderVer2_Project-release-urp-2.2/Runtime/Shaders/UniversalToonBodyDoubleShadeWithFeather.hlsl(41) (on gles3)

上記のようなエラーが出力されていました。



## シェーダの確認

エラー内容に従ってシェーダを調査します。

<img src=https://user-images.githubusercontent.com/144386/94372175-9aafb400-0136-11eb-8db9-04523b5008ed.png width=450 />
UniversalToonを選択してインスペクタを確認。

<img src=https://user-images.githubusercontent.com/144386/94372124-2e34b500-0136-11eb-9e6e-be0537acad28.png width=450 />

おおお、、エラー沢山。。。
とりあえず`invalid subscript 'vertexSH' `が原因ぽい。

## シェーダのReimportで解決

UniversalToonを右クリックからReimport実行。

<img src=https://user-images.githubusercontent.com/144386/94372223-e19da980-0136-11eb-8942-afc2330dafa7.png width=450 />

なぜかと言われると答えられませんが、UniversalToonシェーダをReimportすると直ります。

<img src=https://user-images.githubusercontent.com/144386/94372250-0560ef80-0137-11eb-8e8d-109865d6bde3.png width=450 />

するとこのようにきれいなインスペクタに戻ります。


### ビルドは成功しませんでした

インスペクタ上ではコンパイルは成功しているのですが、実機ビルドでは失敗します。また、再度シェーダのインスペクタを見てみるとエラーは元に戻っていました。


## OpenGLES3.1をターゲットにする

<img src=https://user-images.githubusercontent.com/144386/94372827-ffb9d880-013b-11eb-81c6-2d1f24ebd7c3.png width=450 />

`Require ES3.1`にチェックを入れることでビルドが成功しました。
詳しく調べられてはいませんが、ES3.0以下では対応していないシェーダがあったということだと思われます。

## 無事に動いた！！

無事にUnityChanSSUがAndroid実機で動くようになりました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">何もチューニングせずにPixel3aで動かしてみたが6FPSくらいしか出なかった。。。(重いだろうな〜っていうことは分かってた。)<br>何が一番のボトルネックなのか調査してみよう。(おそらくGPU負荷だと思うけど)。<a href="https://twitter.com/hashtag/Unity?src=hash&amp;ref_src=twsrc%5Etfw">#Unity</a> <a href="https://twitter.com/hashtag/unitychan?src=hash&amp;ref_src=twsrc%5Etfw">#unitychan</a> <a href="https://t.co/4j0RR0E9xQ">pic.twitter.com/4j0RR0E9xQ</a></p>&mdash; 大庭俊介@UXエンジニア (@ohbashunsuke) <a href="https://twitter.com/ohbashunsuke/status/1310376175127068673?ref_src=twsrc%5Etfw">September 28, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
LIKE句を使って検索機能を実装する

データベースに保存されたデータを検索し、HTML上に表示する場合、基本的に「LIKE句」というものを使って実装していく。

#LIKE句の使い方
```
モデルクラス名.where('検索するカラム名 LIKE(?)', "検索するキーワード")
```

ただ、これでは完璧に一致するものしか検索結果に表示することができない。
（例えばgoogleで「野球」検索した時、完全に一致しないものも（野球場、プロ野球など）検索結果に出てくる。

そのような設定にしたい場合は、
検索するキーワードの前後に％を入れてLIKE句を指定すると、文字列の中に含まれたキーワードがヒットする。

```
Product.where('title LIKE(?)', "%#{params[:keyword]}%")
```

↑の場合、タイトルの中にキーワードが含まれるデータを検索できる。

また、このほかにもデータ検索する方法がある

```
where('title LIKE(?)', "a%")
#↑aから始まるタイトルを検索
```

```
where('title LIKE(?)', "%b")
#↑bから始まるタイトルを検索
```

```
where('title LIKE(?)', "%c%")	
#↑cから始まるタイトルを検索
```
【初心者向け】MacOSでのJenkinsのインストールセットアップまとめ

# 概要

新しくMacBookProを買ったのですが、昔セットアップしていた内容を繰り返しているのでまとめておいた方が後々役に立ちそうなのでメモ。

# インストール手順

## Homebrew ※インストール済みの場合はJenkinsへ

command+spaceでSpotlight検索を呼び出して、ターミナルと入力し、ターミナルに以下のコマンドを入力します。

```terminal
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

Passwordなどを要求されるので本体のパスワードを入力。（初めて入力する場合は何も入力されていないように見えますがきちんと入力できているので大丈夫です。）


## Jenkins

```terminal
brew install jenkins-lts
```

最新版をHomebrewを使ってダウンロードし、

```terminal
brew services start jenkins-lts
```

上記のコマンドでサービススタートする。

するとデフォルトの設定では

http://localhost:8080/

でサービスが立ち上がるため、アクセスすると、パスワードが

```
file:///Users/[Your_user_name]/.jenkins/secrets/initialAdminPassword
```

このディレクトリにあるからそれをコピペしてね！というような文とフォームがあるのでcatコマンドかブラウザのアドレスバーに直接入力してアクセス、コピペして入力すると、以下のような画面になるので、初期セットアップのためのユーザー名やパスワードを入力し、次の画面に進むとセットアップが始まります。

![スクリーンショット 2020-09-29 7.24.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412789/96785560-b56d-0240-3ba9-7e29ec99aca2.png)

そしてそのセットアップが終わると無事使えるようになります。

![スクリーンショット 2020-09-29 7.27.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412789/8f27e92e-61e7-b843-bb36-67351a181aa3.png)



![スクリーンショット 2020-09-29 7.40.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412789/114b0313-8f26-85d5-d321-414363ca021c.png)



以上で設定は終了です、楽しいJenkinsライフを送りましょう！
ElixirでABC178のC Ubiquityを解いてみる

この記事を見てElixirという言語でコードを書いてみたくなりました。

- [ElixirでABC178のA,B,C問題を制する！(べき乗の計算に課題あり😥) - Qiita](https://qiita.com/torifukukaiou/items/2f739c12c031325016a2)

Elixirがまったく初めてなので、コンパイル・実行の仕方から調べながらです。コードは上記記事を手本にして書きました。

Elixirソースのコンパイルと実行の方法

```console
$ elixirc sample.ex
$ elixir -e Main.main
```

AtCoderに提出したコードはこちら。AC取れました。

```elixir
defmodule Main do
  @divisor 1_000_000_007

  def main do
    IO.read(:line)
    |> String.trim()
    |> String.to_integer()
    |> solve()
    |> IO.puts()
  end

  def solve(n) do
    rem(2 * @divisor + pow(10, n) - 2 * pow(9, n) + pow(8, n), @divisor)
  end

  def pow(m, n), do: pow(m, n, 1)

  def pow(_, 0, acc), do: acc

  def pow(m, n, acc) do
    if rem(n, 2) == 1 do
      pow(rem(m * m, @divisor), div(n, 2), rem(m * acc, @divisor))
    else
      pow(rem(m * m, @divisor), div(n, 2), acc)
    end
  end
end
```

書いたコードこれだけの段階での感想ですが、Elixirは関数型でScalaに似た雰囲気があって、ひょっとしたら自分にも合うかも。

AtCoderコンテスト当日はScalaで書きましたが、あまりイケてないコードだったので、今回の記事を機に書き直しました。

```scala
object Main extends App {
  val m = 1_000_000_007;

  def pow(a: Int, b: Int): Int = {
    @scala.annotation.tailrec
    def sub(a: Long, b: Int, result: Long): Int = {
      if (b == 0) {
        result.toInt;
      } else {
        val result2 = if (b % 2 == 1) result * a % m else result;
        sub(a * a % m, b / 2, result2);
      }
    }
    sub(a, b, 1);
  }

  val sc = new java.util.Scanner(System.in);
  val n = sc.nextInt();

  val answer = (2L * m + pow(10, n) - 2L * pow(9, n) + pow(8, n)) % m;
  println(answer);
}
```