OmniAICreator/Qiita-1.07M huggingface dataset:
Nuxtでenvを取得しようとした時に空になってしまう件について

Nuxtのコードにおいてnuxt.config.jsで定義した値を取得しようとして`console.log(process.env)`とすると、空のオブジェクトが返ってくる。

一見するとバグのように見えるが、これはNuxtの正常な挙動のようだ。

> つまり、console.log（process.env） は {} を出力しますが、 console.log（process.env.you_var） は個別に定義しマップされた値を出力します。
> https://ja.nuxtjs.org/api/configuration-env/

というわけで、env内に定義した特定の値を取得したい場合はピンポイントでプロパティを取得しないといけないとのことらしい。

```js
console.log(process.env) // return {}

console.log(process.env.nodeEnv) // return local, etc
```
DynamoDBをOn-demandキャパシティに変えた際の挙動

AWS re:Invent 2018で、DynamoDBのOn-demandキャパシティモードが発表されました。

https://aws.amazon.com/jp/blogs/news/amazon-dynamodb-on-demand-no-capacity-planning-and-pay-per-request-pricing/

従来のスループット指定とは異なり、事前の設定なく数千リクエストを捌けるというモデルです。

定常的にスループットを使うのではなく、通常はアクセスがないけど突発的にアクセスがくるような使い方には非常に向いているものです。

うちにもいくつかこのようなテーブルがあるので早速変更してみましたが、その前にいくつか気になる点があったので、確認してみました。

## モード変更中のアクセス
マネジメントコンソールから、現状のモードとOn-demandの切り替えタブがあり、変更できます。
試しに切り替えながらアクセスしてみましたが、特にエラーは発生しませんでした。

## スループットの取得
APIを使うとread/writeのスループットを取れますが、On-demandモードの場合に取得をすると、0が返ってきました。
エクスポート用途などで、既存のスループットを元にキャパシティを増減させるようなプログラムを書いている場合はおかしなことになるので、注意が必要そうです。

## スループットのセット
On-demandモードの場合にAPIを使ってスループットを指定するとどうなるかというと、以下のようなエラーが発生しました。

## 同時にモード変更できるテーブル数
On-demandモードへの変更は、同時に10テーブルまでのようです。10テーブル以上を同時に変更しようとすると、LimitExceededExceptionが発生します。

````
"One or more parameter values were invalid: Neither ReadCapacityUnits nor WriteCapacityUnits can be specified when BillingMode is PAY_PER_REQUES"
````

上記とも関連しますが、OnDemandの場合は、スループット系のAPIは使わないようにするのが良さそうです。
なおオンデマンドかどうかは、DescribeTable APIの戻り値のBillingModeSummaryをみるか、もしくは単純に取得したスループットが0かどうかをみれば良さそうです。

https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html
Fluentdのプラグインが動作しない

# Fluentdのプラグインが動作しなかったのでメモ

nginxのログをFluentdで収集したいけど、timestampフィールドはログを収集するサーバ側の時刻timeを適用するっぽいので、[fluent-plugin-record-reformer](https://github.com/sonots/fluent-plugin-record-reformer)プラグインを入れてイベントレコードを置換えたいと思った。
サーバ側が何らかの問題により停止していたり、ログを受け取れなかった場合に時刻がずれる（復旧した後のサーバの時刻になる）のを心配していたため。


# 上手くいかなかった手順

[fluent-plugin-record-reformer](https://github.com/sonots/fluent-plugin-record-reformer)プラグインのサイトのREADMEの通りコマンドを実施。

```
gem install fluent-plugin-record-reformer
```

同じくREADMEをまねして /etc/td-agent/td-agent.conf に定義。
（source タグの定義部分は省略しています）

```
<match foo.**>
  type record_reformer
  remove_keys remove_me
  renew_record false
  enable_ruby false
  
  tag reformed.${tag_prefix[-2]}
  <record>
    hostname ${hostname}
    input_tag ${tag}
    last_tag ${tag_parts[-1]}
    message ${record['message']}, yay!
  </record>
</match>
```

テストしてみたけど動作しない。
エラーログも無い。

# 上手くいった手順

いろいろ調べてみると fluentd が使用している Ruby と OS にインストールされている Rubyは違うらしい。
私の環境では以下のコマンドで成功しました。

```
/opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-record-reformer
```

おしまい
Route53レコードの変更手順メモ

Route53のレコードの変更手順メモ

### 確認

対象のzoneが存在するか確認する
CNAMEのエンドポイントを書き換えるつもりで記述

```bash:command
aws route53 list-hosted-zones \
    --query "HostedZones[].{zoneId: Id, hostedZoneName: Name}"
```

変更対象のレコードが存在するか確認する

```bash:変数
ZONE_ID=""  # 上記で確認したIDを使用する
```

```bash:変数
RECORD_NAME="" # 対象のレコード名(FQDN)
```

```bash:コマンド
aws route53 list-resource-record-sets \
    --hosted-zone-id ${ZONE_ID} \
    --query "ResourceRecordSets[?contains(Name,\`${RECORD_NAME}\`)]"

OLD_RECORD=$(aws route53 list-resource-record-sets \
    --hosted-zone-id ${ZONE_ID} \
    --query "ResourceRecordSets[?contains(Name,\`${RECORD_NAME}\`)].ResourceRecords[].Value" \
    --output text)

TYPE=$(aws route53 list-resource-record-sets \
    --hosted-zone-id ${ZONE_ID} \
    --query "ResourceRecordSets[?contains(Name,\`${RECORD_NAME}\`)].Type" \
    --output text)
    
TTL=$(aws route53 list-resource-record-sets \
    --hosted-zone-id ${ZONE_ID} \
    --query "ResourceRecordSets[?contains(Name,\`${RECORD_NAME}\`)].TTL" \
    --output text)
```

### 変更

```bash:変数
NEW_RECORD="" # 変更後のレコードの値
```

```bash:JSONの作成
JSON=$(cat << _FIN_
{
  "Comment": "",
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "${RECORD_NAME}",
        "Type": "${TYPE}",
        "TTL": ${TTL},
        "ResourceRecords": [
          {
            "Value": "${NEW_RECORD}"
          }
        ]
      }
    }
  ]
}
_FIN_)
```

```bash:command
STATUS_ID=$(aws route53 change-resource-record-sets\
    --hosted-zone-id ${ZONE_ID} \
    --change-batch file://<(echo ${JSON}) \
    --query "ChangeInfo.Id" \
    --output text) && echo ${STATUS_ID}
```

### 確認

```bash:command

while true ; do
  STATUS=$(aws route53 get-change --id ${STATUS_ID} \
    --query "ChangeInfo.Status" \
    --output text);
  echo ${STATUS}
  sleep 10
  [ ${STATUS} = "INSYNC" ] && break;
: ;done

```

```bash:command

UPDATED_RECORD=$(aws route53 list-resource-record-sets \
    --hosted-zone-id ${ZONE_ID} \
    --query "ResourceRecordSets[?contains(Name,\`${RECORD_NAME}\`)].ResourceRecords[].Value" \
    --output text)

cat << _FIN_
変更レコード名:${RECORD_NAME}
変更前レコード値: ${OLD_RECORD}
変更後レコード値:${UPDATED_RECORD}
_FIN_
```
[AWS]AWSAmplifyConsoleを使ってVue製アプリをデプロイする

# はじめに

今年のre:Inventも新サービスやアップデートがてんこ盛りで、さらに追いかけるのが難しくなってきましたね…衛星通信をマネージドで提供するって何？www
その中で `AWS Amplify Console` なるサービスが発表されました。今回はそのサービスを利用してVue製のアプリケーションをデプロイしようと思います。

## 注意書き

この記事ではVueのことはほぼ触れません。
なんでVue製のアプリをデプロイしようとしたのかは、筆者がVue好きだからです。

## AWS Amplify Console

このサービスは一体何かと言うと、アプリケーションをデプロイするするためのCI/CDパイプラインを一括で設定することができるサービスなのです！
普段CodeBuildやCodeDeployといったCode兄弟を利用してパイプラインを構築している方が多いと思います。
このAmplifyConsoleを利用するとその手間が一切なくなるのです！！

## 早速試していきましょう

今回でデプロイするのはこれです！！

<img width="1260" alt="スクリーンショット 2018-11-30 13.35.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/25e6d8b6-e805-2c15-a178-4ae43a1669c6.png">

はい、VueCliで `vue create` したそのままの状態ですw
予めこのソースコードをGitHubにpushしきます。

### リポジトリを選択する

GitHub / GitLab / BitBucket / CodeCommit の中から選択できます。今回はGitHubのリポジトリを利用します。

<img width="555" alt="AWS Amplify Console 2018-11-30 13-42-57.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/efd1e259-c760-ff3b-95f1-9152a636ff17.png">

### リポジトリとブランチを選択する

GitHubとの認証をして、リポジトリとブランチを選択します。

<img width="552" alt="AWS Amplify Console 2018-11-30 13-44-05.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/4585fd7a-187d-fdd6-30be-d9829d1e1db4.png">

### ビルド設定

ビルドの設定をします。
ビルドの設定はデフォルトでこのようになっています。

<img width="539" alt="AWS Amplify Console 2018-11-30 13-46-32.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/400d2dc4-0465-54ee-0690-b9410edd935c.png">


```
version: 0.1
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands:
        - yarn run build
  artifacts:
    baseDirectory: dist
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
```

普段からCodeBuildを利用して `build_spec.yml` などを書いている方はイメージ付きやすいと思います。
どのステージで、どのようなコマンドを実行するのかなどを設定することができます。今回はデフォルトのままでいきましょう。

### デプロイする

これで準備が整ったのでデプロイしましょう！

<img width="545" alt="AWS Amplify Console 2018-11-30 13-50-09.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/cb849417-9232-bb9b-dbb9-eb3ca2b1b476.png">

このような画面に遷移して、デプロイのステータスを確認することができます。

<img width="1383" alt="AWS Amplify Console 2018-11-30 13-51-26.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/a0e890cc-d601-4180-d824-da1b60f35bbe.png">

### 画面を確認する

デプロイが完了したら、コンソールのリンクから実際にページを確認しましょう

<img width="1388" alt="AWS Amplify Console 2018-11-30 13-54-53.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/e329fc68-b7d5-9d5e-dd88-47f68e27621b.png">

<img width="856" alt="スクリーンショット 2018-11-30 13.57.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/75f8740f-2a41-0032-4ed8-6e56ea16a285.png">

デプロイできました！！

## さいごに

ここまで10分程度で作業が完了しました。
もちろん、対象ブランチがpushされるたびにデプロイが実行されます。
デフォルトでは `https://blanch.xxxxxxxxx.amplifyapp.com/` というようなURLが用意されます。HTTPS対応されているのが嬉しいですね！
自分でやろうと思ったらCloudFrontなりELBなりを用意して証明書を適用しないといけませんから大変です。
また独自のドメインで公開することも可能です。
AWS Amplify Consoleを利用することで、デプロイするためのパイプラインを構築するのがすごく用意になりました！！嬉しい！！！
ではまた！
Azure DevOpsで組織(organizations)またはプロジェクト(project)を削除する

2018年11月時点では公式ドキュメントがまだ日本語化されていないので、リンクと日本語訳を

## プロジェクトを削除する

公式ページ
[Delete a project in Azure DevOps](https://docs.microsoft.com/en-us/azure/devops/organizations/projects/delete-project)

- 画面のメニューからOrganization settingsを選択
![](https://docs.microsoft.com/en-us/azure/devops/_shared/_img/settings/open-admin-settings-vert.png?view=vsts)

- General -> Projectsを選択
![](https://docs.microsoft.com/en-us/azure/devops/_shared/_img/settings/admin-organization-settings.png)

- 削除したいプロジェクトの名称の横[・・・]をクリックしてDeleteを選択

<font color="Red">プロジェクトを削除すると、そのプロジェクトに関連付けられているデータがデータベースから永久に削除される。回復することはできません。
後でアクセスする可能性のあるプロジェクトデータは保存する必要があります。</div>
</font>


![](https://docs.microsoft.com/en-us/azure/devops/organizations/projects/_img/delete-project/choose-delete-menu-option.png?view=vsts)

- 表示されるダイアログボックスに、プロジェクトの名前を入力し、[Delete Project]をclick。
![](https://docs.microsoft.com/en-us/azure/devops/organizations/projects/_img/delete-project/delete-team-project-dialog.png?view=vsts)




## 組織を削除する

公式ページ
[Delete your organization in Azure DevOps](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/delete-your-organization)

30日以内で復元可能で、その後 組織とデータは完全に削除されるとのこと

- 画面のメニューからOrganization settingsを選択
![](https://docs.microsoft.com/en-us/azure/devops/_shared/_img/settings/open-admin-settings-vert.png?view=vsts)

- General -> OverviewからDeleteを選択
![](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/_img/delete-organization/organization-overview-settings.png?view=vsts)

- OverviewからDeleteを選択
表示されるダイアログボックスのドロップダウンメニューから、組織を削除する理由を選択。
次に、組織の名前を入力し、[Delete]をclick。
![](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/_img/delete-organization/delete-organization-popup.png?view=vsts)
PowerAppsでモーダルを実装する

# 概要

PowerApps でギャラリーを利用して、モーダルを実装します。
方法として、Visibleを制御する方法とコレクションの制御をする方法が考えられますが
今回は前者の方法で実装します。

# 完成イメージ

今回はヘルプアイコンを押した時に説明が書かれたモーダルを表示させます。

![キャプチャ.JPG](https://qiita-image-store.s3.amazonaws.com/0/183354/b45ecd47-a9cd-17e8-de3c-2fff09db777d.jpeg)

# 実装

## Screen

今回はギャラリーを使用してのモーダル実装の為、コレクションを作ります。
ちなみに、ギャラリーはitemsがnullの場合中のラベルやボタンといったアイテムを表示したくなります。

| プロパティ      |       数式 | 
|:-----------------|------------------:|
| OnStart             |              ClearCollect(helpVieCollect,{id:0});Set(help,false) | 


## header

見栄えをよくするためにヘッダーを用意します。

![キャプチャ.JPG](https://qiita-image-store.s3.amazonaws.com/0/183354/5b9db1cb-3190-fe60-7721-16c6cafff3a1.jpeg)

## モーダル

ここからが今回の本題です。
ギャラリーを挿入し、その配下にヘッダーとラベルを用意します。

![キャプチャ.JPG](https://qiita-image-store.s3.amazonaws.com/0/183354/b45ecd47-a9cd-17e8-de3c-2fff09db777d.jpeg)

こんな形です。

### ※ポイント
ここまで作ったら一度名前を付けて保存を行い、ページをリロードしページを読み込みなおしましょう。理由は OnStart でコレクションに対してidを挿入していますが、そのまま実行しても OnStart  は実行されない為、一度リロードを行ってコレクションに値を追加し、モーダルが表示されるようにします。


## helpIcon

表示非表示用の、変数を制御します。
helpがtrueの時に選択された場合は flase に false の時は true に変更する数式を書きます。

| プロパティ      |       数式 | 
|:-----------------|------------------:|
| OnSelect            | If(help,Set(help,false),Set(help,true))| 

## modalCloseIcon
選択された時にモーダルを非表示にします。

| プロパティ      |       数式 | 
|:-----------------|------------------:|
| OnSelect         | Set(help,false)| 


## モーダル
最後にモーダルの Visible に対して help を指定します。

| プロパティ      |       数式 | 
|:-----------------|------------------:|
| Visible            | help|


## 完成

以上で完成です。
実際に動作するか確認してみましょう。


## まとめ

- ギャラリーはitemsがnull又は空だと中に作ったアイテムは表示されない
- OnStartは一度リロードしないとうまく動かない

今回作成したファイルは[こちら](https://github.com/github129/PowerApps_ModalSample)からダウンロードできます。
How to fix certbot error : acme==0.5.0

## Symptom

 **certbot renew**  -> An unexpected error ocurred: `Requirement.parse('acme==0.5.0'))

```
# certbot renew
An unexpected error occurred:
VersionConflict: (acme 0.27.1 (/usr/lib/python2.7/site-packages), Requirement.parse('acme==0.5.0'))

2018-11-30 13:27:23,575:DEBUG:certbot.log:Exiting abnormally:
Traceback (most recent call last):
  File "/usr/bin/certbot", line 9, in <module>
    load_entry_point('certbot==0.27.1', 'console_scripts', 'certbot')()
  File "/usr/lib/python2.7/site-packages/certbot/main.py", line 1338, in main
    plugins = plugins_disco.PluginsRegistry.find_all()
  File "/usr/lib/python2.7/site-packages/certbot/plugins/disco.py", line 206, in find_all
    plugin_ep = PluginEntryPoint(entry_point)
  File "/usr/lib/python2.7/site-packages/certbot/plugins/disco.py", line 52, in __init__
    self.plugin_cls = entry_point.load()
  File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 2345, in load
    self.require(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 2368, in require
    items = working_set.resolve(reqs, env, installer, extras=self.extras)
  File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 789, in resolve
    raise VersionConflict(dist, req).with_context(dependent_req)
VersionConflict: (acme 0.27.1 (/usr/lib/python2.7/site-packages), Requirement.parse('acme==0.5.0'))
2018-11-30 13:27:23,575:ERROR:certbot.log:An unexpected error occurred:
```

## How to fix

 - pip uninstall letsencrypt - remove old letsencrypt package

```
# pip uninstall letsencrypt
Uninstalling letsencrypt-0.5.0:
  Would remove:
    /usr/bin/letsencrypt
    /usr/lib/python2.7/site-packages/letsencrypt-0.5.0.dist-info/*
    /usr/lib/python2.7/site-packages/letsencrypt/*
Proceed (y/n)? y
  Successfully uninstalled letsencrypt-0.5.0
```

 - certbot renew

```
certbot renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/xxx.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/xxx/fullchain.pem expires on 2019-01-23 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
```

OK :smile:
background

#backgroundについて
##backgroundの概念
主に背景のことについて記載するときに使うコードである
ショートハンド可能
種類は以下の通り

|コード|意味|
|:-----------|------------:|:------------:|
|background|文字色（前景色）|
|background-attachment|背景画像の固定・移動|
|background-color|背景色を指定|
|background-image|背景画像を指定|
|background-position|背景画像の表示開始位置を指定|
|background-repeat|背景画像のリピートの仕方を指定|
OctoberCMSプラグイン作成：対話式インタプリタ(tinker)で実行結果を確認する

ちょっとメソッドの挙動を確認したい、けどテスト用のクラスを作成するのも面倒、という時に気軽にコードを実行できるのがtinkerだ。tinkerはLaravelのartisanコマンドなので、正直OctoberCMS独自の機能ではない。

### 起動
artisanがあるディレクトリ（Octoberプロジェクトのルート）で下記を実行すると、シェルが起動する。

```
$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.0.30-0ubuntu0.16.04.1 — cli) by Justin Hileman
>>> 
```

### モデルクラスを試してみる

```
>>> use Cocci\Ec\Models\Product;
>>> MobileSuite::find(2);
=> Pikanji\Gundam\Models\MobileSuite {#3511
     id: 2,
     name: "ギャン",
     code: "YMS-15",
     pilot: "マ・クベ"
   }
```

便利。
PostgreSQL Function の中で Function を呼び出す (Call function in other function)

PostgreSQL のストアドファンクション内 で ファンクションを呼び出す方法です。

## 返り値が `void` のファンクションを呼び出す。

`PERFORM` を使います。

```sql
PERFORM function_name();
```

この `PERFORM` は、 psql で直接使うことはできません。
psql での関数呼び出しには `SELECT` を使います。

`TABLE` を返すようなファンクションは ファンクション内でも `SELECT` を使って呼び出せます。

----

The way to call stored function in function, in PostgreSQL.

## Call function with `void` return value

Use `PERFORM`.

```sql
PERFORM function_name();
```

`PERFORM` cannot be used in psql console.
It's available only in function.
To call function in psql console, use `SELECT`.

To call the function that returns `TABLE` type in other function, you can use `SELECT`.
Perlのコード整形ツールPerltidyを導入する

# Perltidyとは
Perlのコード整形ツール。フレームワークCatalystとかも使っててもいい感じに整形してくれるよ！
様々なルールを `Perltidyrc` に記述することで定義可能。

* 100文字で改行
* カッコ内の空白は空けない 等

# 導入
cpanmは使えるようにしておいてください。

```
$ cpanm Perl::Tidy

# 確認
$ which perltidy
/usr/local/bin/perltidy
```

導入完了

# 設定ファイルの記述
記述場所はホームディレクトリの中です。vimrcとかbashrcとかあるあそこですね。

```
$ vim ~/.perltidyrc
```

この中に色々記述していきます。とりあえず僕のやつ貼っときます。

```perl

# basic option
-enc=utf8      # 文字コードUTF-8(しかしwarning出る)
-ole=unix      # 改行は LF
-i=4           # スペース4つ
-l=150         # 1行の長さが150文字以内に収まるようにする
--check-syntax # 整形後 perl -c -T でチェック

# code indentation control
--closing-token-indentation=1 # 配列指定時などに、終了カッコを開始と同じ位置までインデント
--nooutdent-long-quotes       # インデントされ過ぎた文字列があっても引き戻して来ない
--nooutdent-long-lines        # インデントされ過ぎた行があっても引き戻して来ない

# whitespace control
--nospace-for-semicolon      # forループの指定のセミコロンの前にスペースを置かない
--nospace-terminal-semicolon # セミコロンの前にスペースを置かない
--add-semicolons             # 行末にセミコロンを置き、次の行に終わりの中括弧を置く
--tight-secret-operators     # 0+$val などの特定の表現のときは 0 + $val の様なスペースを空けない
--paren-tightness=2          # 括弧の中のスペースは開けない

# comment control
--minimum-space-to-comment=2 # 行末コメントとコードの間のスペースは2つ

# line break control
--opening-brace-always-on-right # 開き括弧は必ず右端に置く

# controlling list formatting
--maximum-fields-per-table=1     # 配列要素の指定を横に並べる数
--break-at-old-comma-breakpoints # カンマの後の改行を変更しない

# brank line control
--keep-old-blank-lines=2 # 過去の空白行を消さない

# overview
--backup-and-modify-in-place # ファイルを書き換えて、整形前のファイルを.bak で保存する
```

その他の記述方法はcpanmを見てください。 https://metacpan.org/pod/perltidy

## 設定ファイルの記述が面倒！
そんなあなたに、Perlのベストプラクティスな設定を自動でやってくれるオプションがあります。 `-pbp`
これで問題ないのであれば設定ファイルの記述は飛ばしてください。

# 使用方法
perltidyコマンドの後ろにファイル名を指定するだけです！
ファイル全体にコード整形を通します。

```
$ perltidy test.pl
```

これでもうperltidyに記述したコード整形ルールに則ってコードを整形してくれるはずですね。
設定ファイルを記述せずに、ベストプラクティスを使うのであれば

```
$ perltidy -pbp test.pl
```

の指定でOKです。

## 選択範囲のみにPerltidyを実行する
うちのプロジェクトは1ファイル5000行とかザラなので、改修した関数範囲にのみかけるパターンが多いです。
その場合は、エディタの設定に記述します。Vimで記述している人向けの説明になります。他のはわかりません。ごめんなさい。

### .vimrcを編集する
```vim
$ vi ~/.vimrc

noremap <buffer> ,ptv <Esc>:'<,'>! perltidy<CR>
```

上記を `.vimrc` に記述します。
使うときは、 Shift + v -> 範囲選択 -> ,ptv となります。
意味としては、 

* `'<,'>` : ヴィジュアルモードでの選択範囲
* `,ptv` ：選択してからタイプする文字。 今回は `,ptv` とします
  * `,ptv` をタイプすると、選択した範囲が perltidy に渡されコード整形させる

となります。

### ベストプラクティスを使う場合

```
noremap <buffer> ,ptv <Esc>:'<,'>! perltidy -pbp<CR>
```

# 注意！
perltidyrcと、-pbpオプションは共存させると思わぬ挙動になります。
こいつのせいでしばらく悩まされました。

両方記述した場合、順番としてperltidyrcのオプションを読み込んだ後に、-pbpオプションの記述内容に変換します。
完全に上書きというわけでなく、-pbpオプションに記述されている内容のみ上書きするので一部はperltidyrc、一部はpbpと超ややこしいコード整形ルールになります。
共存は絶対辞めましょう。
Swift製Webフレームワーク Vaporの紹介2018


# Vaporとは

Vaporは、Swift製のWebフレームワークです。
公式URLは https://vapor.codes/ で、Vapor 本体のリポジトリ(https://github.com/vapor/vapor) には　

> Vapor is a web framework for Swift. 
> It provides a beautifully expressive and easy to use foundation for your next website, API, or cloud project.　

と説明が書いてあります。
スター数も多く(2018年12月現在1万5千程度)、これからが楽しみなフレームワーク&コミュニティです。
今回はVaporアドベントカレンダー2018の初日として、インストールとHelloWorldをしてみようと思います。

# 環境構築

## for MacOS
公式(https://docs.vapor.codes/3.0/install/macos/)

Xcode(9.3 以上)が必要なのでApp Storeからダウンロードします。(https://itunes.apple.com/us/app/xcode/id497799835?mt=12)
また最新のVapor3には Swift 4.1 以上が必要なので、バージョンを確認します。

``` bash
$ swift --version
```

```
Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)
Target: x86_64-apple-darwin17.7.0
```

次にVaporのプロジェクト作成が簡単にできるVapor ToolBoxをインストールします。

``` bash
$ brew install vapor/tap/vapor
```

Vapor ToolBoxがインストールできたことを確認します。

``` bash
$ vapor --help
```

## for Ubuntu
公式(https://docs.vapor.codes/3.0/install/ubuntu/)
Vaporは以下のバージョンのUbuntuでサポートされています。
最新のUbuntu18ではサポートされていないので気をつけてください。

| Version  | Codename  |
|---|---|
|16.10  |Yakkety Yak  |
|16.04	  |Xenial Xerus  |
|14.04	  |Trusty Tahr  |

以下のスクリプトでVaporのリポジトリをAPTで参照できるようにします。
このスクリプトはサポートされていないバージョン以外で動かすとエラーが出てしまいます。

``` bash
eval "$(curl -sL https://apt.vapor.sh)"
```

リポジトリの参照をマニュアルでやりたい方はこちらのコマンドを実行してください。

``` bash
wget -q https://repo.vapor.codes/apt/keyring.gpg -O- | sudo apt-key add -
echo "deb https://repo.vapor.codes/apt $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/vapor.list
sudo apt-get update
```

APTを使ってswiftとvaporをインストールします。

``` bash
$ sudo apt-get install swift vapor
```

インストールされたことを確認します。

``` bash
$ swift --version
$ vapor --help
```

# HelloWorld

環境構築が完了したので早速プロジェクトを作成します。
プロジェクトの作成には `new` コマンドを使用します。

``` bash
$ vapor new リポジトリ名
```

また、RailsのAPIモードのようにフラグをつけることでテンプレートを選ぶことができます。
今回は　`Web`　テンプレートを使用してプロジェクトを作成します。
フラグを付けずにプロジェクトを作成するとAPIテンプレートで作成されます。

| Name  | Flag  | Description  |
|---|---|---|
|API  |--template=api  | Fluentデータベースを使ったJSON API |
|Web  |--template=web  | Leafテンプレートを使ったを含むHTMLウェブサイト|
|Auth |--template=auth-template  | Fluent DBとAuthを使ったJSON API |

今回は`myApp`プロジェクトをWebテンプレートで作成します。

``` bash
$ vapor new myApp --template=web
```

プロジェクト名のディレクトリが作成されれます。
ディレクトリの中に入り、 `build` コマンドでビルドします。

``` bash
$ cd myApp
$ vapor build
```

ビルドが完了したら `run`　コマンドでアプリを実行します。

``` bash
$ vapor run
```

ブラウザで　http://localhost:8080/ にアクセスすると起動が確認できます。

![vapor.png](https://qiita-image-store.s3.amazonaws.com/0/63855/e6c30063-4f6c-63ae-2596-0ea05c14401e.png)

# おまけ

Vaporのユニークな機能として、Xcodeを使うことができます。
`xcode`コマンドで `.xcodeproj` ファイルが作成されます。

``` bash
$ vapor xcode
```

作成された`.xcodeproj` を開き、iOSのように三角ボタンでビルドすることができます。
ビルドが終わったら`run`　コマンドでアプリを実行します。

``` bash
$ vapor run
```
良いチームを作るために必要な要件

この記事は、僕の会社のアドベントカレンダー企画のために書いた記事です。
Qiitaはプログラミング技術を書くところ・・・らしいですが
プログラミング的なことは10年くらいやってなくて書くことないので、ちょっと毛色の違うことを書こうと思います。

#ことの発端
これを読んでいる皆さんは、自分の所属しているチームは良いチームだと思いますか？
問いかけておいてなんですが、僕はこれまで良いチームとはどんなチームなのか大して考えたことがありませんでした。

でもこの前、たまたまデザインシンキングの研修に抜擢されて、およそひと月の間、僕の工数の半分を使って6人チームでワークに取り組む機会がありました。
そこで学んだのは、デザインシンキングのなんたるか・・ではなく、チームの力でした。

#良いチームとは
そもそも良いチームの定義とはなんでしょうか。
もちろん、定義は人それぞれで良いと思いますが、この記事では**個人では到達できない領域の優れたアウトプットをするチーム**を良いチームと定義します。

別の言い方をすると、チームだからこそ達成できる成果があると言えるチーム、と言えます。
個々のメンバは特別優れているわけではないけれど、チームになることで予想以上の成果が出るチーム。
三人寄れば文殊の知恵というやつです。

この記事ではそうしたチームに必要な要件を書いていきます。

#いきなり結論
良いチームを作るために必要な要件は、そのチームを構成する個人がそれぞれ謙虚であることです。

まぁでもこれではざっくりすぎるので、ひとつずつ紐解いていきましょう。

#謙虚 ＝ 相手を尊重すること
「心理的安全性」
ちまたで人気の言葉です。良いチームを作るために必要であるに違いありません。
Googleで検索してみると
>他者の反応に怯えたり羞恥心を感じることなく、自然体の自分を曝け出すことのできる環境や雰囲気のこと
*引用元:[心理的安全性とは？googleが発見したチーム生産性を高める唯一の方法 | BizHint（ビズヒント）- 事業の課題にヒントを届けるビジネスメディア](https://bizhint.jp/keyword/101187)*

だそうです。

でもただ自分を曝け出すって色々な問題を引き起こすだろうことは想像に難くありません。
みんながみんな言いたいことを言っていたらまとまらないばかりか雰囲気が悪くなることウケアイです。

必要なのは言いたい事を言う気概ではなく、相手の発言に耳を傾けようという配慮です。
みんな言いたいこと言うけど聞く側は怒らず我慢しろよ、という意味ではありません。
**他人は自分と違う視点を与えてくれる、有難い存在だという意識を持つ**ことです。

さらに、聞く側の配慮がある前提で、発言する側は自分の意見を押し通す事に注力してはいけません。
最終的な目標は「個人では到達できない領域の優れたアウトプットをする」ことなので、個人の意見を押し通すことは逆効果なのです。
自分の意見よりチームの意見を信じましょう。

#謙虚 ＝ 人間関係に上下を作らないこと
「個人では到達できない領域」とはすなわち、複数の個人が相互作用してより高い領域に到達するということです。
そのためには個人個人に権力の差があってはいけません。

まぁ平たく言うと、**地位・立場、声の大きさなどで意見が左右される状況は良くない**ということです。

なので、最終的な意思決定を司る絶対的な権力を持ったリーダはチームに存在するべきではありません。
あるいはプロジェクトの中心者がメンバに仕事を分配したり、元請けが下請けに指示したり、といった構図も同様です。
上意下達では個人の枠を超えられません。当たり前ですね。

ただしファシリテータとしての役割を持つリーダは必要です。
地位や立場が同じでも、中々主張できない性格の人は存在します。
（逆に往々にしてそういう人が思慮深かったりする）
そうした個人の意見を拾っていくのは最終的に周りの配慮なので、ファシリテータがそれをうまくアシストする必要があります。

ちなみに、地位や立場、声の大きさなどを吸収して均一にする良いツールが付箋です。
偉い人も下っ端も、積極的な人も奥手な人も、意見を付箋にして貼ってしまえば等価になる上、
意図的に剥がして捨てない限り文字情報として残るので、発言でやり取りするよりずっと平等な機会が与えられます。


#謙虚 ＝ 謙遜しないこと
「あんまりでしゃばるとチームの和を乱すかな、控えめに控えめに・・」
これは謙虚ではありません。謙遜です。字は似てますが意味は全く違います。

今更ですが「謙虚 意味」とGoogleで検索してみると
>自分を偉いものと思わず、すなおに他に学ぶ気持があること。

と出てきます。
つまり、すなおな向上心を持っている状態です。
それに比して「目立ちたくないな」とか「面倒事は嫌だな」と手を抜くのは謙虚と正反対の姿勢と言えます。

チームでは、個人個人に得意不得意や趣味嗜好のズレがあってもカバーし合うことができます。
心理的安全性が確保されているのであれば、得意不得意や趣味嗜好のズレについて遠慮する必要はありません。
逆にそうした**個人の尖った特性は他の人には無い美点なので、遺憾なく発揮するべき**です。

そうしているうちに、みんなお互いがかけがえのないチームメンバだと認識して、好循環に繋がります。

#謙虚 ＝ 客観的な批判を素直に受け止めること
どんなに平等で心理的安全性が高い雰囲気の良いチームだとしても、ずっとそのチームに浸かっていると良くない方向に向かい始めます。
思い込み、希望的観測、甘え、あるいは馴れ合い、楽な方へ楽な方へ流れてしまうのが人情です。

そういった良くない要素を排除できるのが、チーム外からの客観的な批判です。

人は批判されると自分を守りたくなります。
　でも・・・。
　だって・・・。
　そんなこと言ったって・・・。
　etc.
だめです。言い訳禁止です。「そうですね・・・」と言いましょう。

**批判は、自分たちが気づかなかった良くないところを正す有難いチャンス**です。
たとえ理不尽と感じる批判でも、その批判の原因になった何かが存在します。
真摯に受け止め、何に対する批判なのか冷静に考えましょう。
そして何らかの改善に繋げて、さらに批判をもらえたなら儲けものです。


#改めて結論
良いチームを作るために必要な要件は、そのチームを構成する個人がそれぞれ謙虚であることです。

ひとつずつ紐解いたつもりですが、結局全部同じことを言っている気がしますね。

謙虚に、自分の力より自分を含むチームの力を信じることができれば、自分でも予想ができないようなアウトプットができます。
加えて、チームの結束も強まって、チームでいることが幸せになります。

どうか、世の中のチームのメンバがみんな幸せになれますように・・
ARKit2 UnitySDKを入れた状態でIL2CPPビルドするとエラーが出た時のメモ

ARKit2のUnitySDKとARCoreのUnitySDKを入れてマルチプラットフォームな環境を作ってた時につまづいたのでメモです。

IL2CPPのビルドにするとエラーが出る
<img width="320" alt="スクリーンショット 2018-11-30 12.36.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/159111/64ad7b7d-b919-5037-7396-d8e09919d8b8.png">
<img width="688" alt="スクリーンショット 2018-11-30 12.42.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/159111/49ecbef9-b617-48c1-088f-f2146dc423b7.png">


Exception: /Applications/Unity/Hub/Editor/2018.2.16f1/Unity.app/Contents/il2cpp/build/il2cppcore/il2cppcore.dll did not run properly!
みたいなエラーが発生しました

ちなみにIL2CPPからMonoにした場合はちゃんとビルドが通る。


解決策
https://bitbucket.org/Unity-Technologies/unity-arkit-plugin/issues/25/android-il2cpp-build-fail
調べたところissueが上がってました。
ARVideoFormat.csの

```
        #if UNITY_EDITOR
        private static void EnumerateVideoFormats(VideoFormatEnumerator videoFormatEnumerator) {
        }
        #else
        [DllImport("__Internal")]
        private static extern void EnumerateVideoFormats(VideoFormatEnumerator videoFormatEnumerator);
        #endif
```

ここを

```
        #if UNITY_EDITOR ||  !UNITY_IOS //こうする
        private static void EnumerateVideoFormats(VideoFormatEnumerator videoFormatEnumerator) {
        }
        #else
        [DllImport("__Internal")]
        private static extern void EnumerateVideoFormats(VideoFormatEnumerator videoFormatEnumerator);
        #endif
```

このようにプラットフォーム識別を変えてやると解決します。

~~ちなみに先ほど見たところ最新のコミットで修正対応されているようです。
https://bitbucket.org/Unity-Technologies/unity-arkit-plugin/src/472ea0983dcd12a563e7c47a23d9bb405bdeb2a5/Assets/UnityARKitPlugin/Plugins/iOS/UnityARKit/NativeInterface/ARVideoFormat.cs?fileviewer=file-view-default
プロジェクトの都合がつくなら最新版持ってきた方が良さそうです。~~

治ってなかったです（2019年1月現在）
https://bitbucket.org/Unity-Technologies/unity-arkit-plugin/pull-requests/57/fixed-define-in-arvideoformat-to-allow/diff
MRは出てた
特定の曜日だけ書き出す

#:date: javascriptで、任意の月の特定曜日を書き出す

練習用の投稿になります。

<b>:cat: 取得方法の概要</b>
(1) 現在の日付から月を取得
(2) 月の日数を取得
(3) 日数の中で、条件に該当する日だけを書き出す

##(1) 現在の日付から、今月が何月であるかを取得する

:small_orange_diamond: <b>現在の日付を取得</b>

```javascript:
var today = new Date();
```

:small_orange_diamond: <b>現在の日付から、西暦の取得</b>

```javascript:
var y = today.getFullYear();
```

:small_orange_diamond: <b>現在の日付から、月の取得</b>
実行結果は0から数えた番号（1月であれば0、2月であれば1）で返されるので、
月の数字に直すには、+ 1をします。

```javascript:
var m = today.getMonth();
var mm = m + 1;
```

##(2) 一か月の日数を取得
:small_orange_diamond: <b>取得した月を利用して、月間日数を取得</b>
new Date(西暦,月,0) とすることで、その月の最終日を取得する事ができます。
取得した最終日から getDate() 関数で日だけを取り出します。

```javascript:
var d = new Date(y, mm, 0).getDate();
```

##(3) 特定の曜日の日だけをピックアップ
:small_orange_diamond: <b>取得した初日～最大日数までの中で、該当する日をピックアップ</b>
1日から始め、最終日まで処理を繰り返していきます。

```javascript:
var i;
for (i = 1; i <= d; i++) {
  // [i]日が一週間の中で何番目かを取得。実行結果は0から数えた番号で返されます。
  var w = new Date(y, m, [i]).getDay();
  
  // 取得した w はそのままでは曜日の文字にはならないので、配列を利用して日本語を書き出します
  var ww = ['日', '月', '火', '水', '木', '金', '土'];

  // [i]日の曜日が、日曜と土曜の時だけ書き出す
  if (w === 0 || w === 6) {
    window.console.log(y + '年' + mm + '月' + [i] + '日' + (ww[w]) + '曜日');
  }
}
```


##:memo: 実行結果
> 2018年11月3日土曜日
> 2018年11月4日日曜日
> 2018年11月10日土曜日
> 2018年11月11日日曜日
> 2018年11月17日土曜日
> 2018年11月18日日曜日
> 2018年11月24日土曜日
> 2018年11月25日日曜日
AWS LambdaのRuby、カスタムランタイムで動作している説

AWS LambdaのRubyの実行環境が何で動いているのか気になって軽く使ってみたのでメモ

※2018-12-06追記
コメント欄でカスタムランタイムで動いていることを @JONAO33 さんに教えて頂きました。ありがとうございます！

>"The Runtime API is the future of how we’ll support new languages in Lambda. For example, this is how we built support for the Ruby language."
https://aws.amazon.com/jp/blogs/aws/new-for-aws-lambda-use-any-programming-language-and-share-common-components/

Hello worldをして呼び出し時間（課金時間）を簡単にベンチマークしてみた

なお計測前に何回か実行してコールドスタートになるのを回避している

### 環境

- Ruby 2.5

### 検証

以下のコードを使用

```ruby
def lambda_handler(event:, context:)
    puts 'Hello world!'
end
```

10回試行しそれぞれ課金された時間(Billed duration)を測る。単位はms

```ruby
32.69
10.87
39.41
3.27
20.45
14.54
38.23
23.63
7.50
27.59
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/47983/292aebc5-bc36-696b-a248-9b35002834d5.png)


### 結果
平均: 21.82ms
中央値: 22.04ms
最小: 3.27ms
最大: 39.41ms

かなりばらつきが大きくLambdaのランタイムとしてgolangを使用した時と似たような挙動となった。
そもそもネイティブのRubyでもHello worldしただけで何十msもかかるわけがない。

```ruby
$ time ruby -e 'puts "hello"'
hello
ruby -e 'puts "hello"'  0.04s user 0.00s system 98% cpu 0.046 total
```

ならなぜこんなにかかるのかというとLambdaのランタイムに仕組みがある。
以前からも実は自分でRubyやPHPなどをLambdaで動かそうと思えば自前でバイナリを用意してプロセス間通信でパラメータを渡してあげれば出来たが、今回追加された[カスタムランタイム](https://aws.amazon.com/jp/about-aws/whats-new/2018/11/aws-lambda-now-supports-custom-runtimes-and-layers/)と同様にRuby 2.5ランタイムも一回OSのパイプを経由していると思われる。

やたらばらつきが大きいのも一度OSのレイヤーに降りているので他のOSリソースにスケジューリングを奪われて実行が遅れているのかもしれない。

### Pythonの場合

同様にPythonのHello worldも実行してみた

#### 環境

- Python 3.6

#### 検証

```python
def lambda_handler(event, context):
    print("hello world")
    
    return 'ok'
```

```python
0.34
0.43
0.52
0.34
0.34
0.34
0.35
0.33
0.35
0.43
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/47983/2c640375-6a8e-4668-6304-950a638040c5.png)


平均: 0.38ms
中央値: 0.35ms
最小値: 0.33ms
最大値: 0.52ms

となった
PythonランタイムはLambdaのコンテナが一度実行されるとしばらくそのコンテナを使いまわしてキャッシュする仕組みになっているため、ランタイムの初期化をスキップ出来る。
OSを経由しないためネイティブに近い速度が出るようになっている

```python
$ time python -c "print(1)"
1
python -c "print(1)"  0.01s user 0.00s system 98% cpu 0.013 total
```

## まとめ

Hello worldのばらつきからLambdaのRubyはカスタムランタイムで動いてる説を推測してみた

他のカスタムランタイムでも同様のランタイム初期化のオーバーヘッドは存在するため、ターンアラウンドタイムが重要になる場合や、オーバーヘッドを超えるような処理でない場合はLambdaに既に最適化されているPythonでサクっと処理するのがいいかもしれない
PowerShellベーシック認証接続メモ


### Credential作成
Get-Credential でユーザーとパスワードの認証を入力するようにした
Invoke-WebRequestを利用してBasic認証を行う。


# ベーシック認証を利用したダウンローダー
```powershell

# Base64 encode
function Get-BasicAuthCreds {
  param([string]$Username,[string]$Password)
  $AuthString = "{0}:{1}" -f $Username,$Password
  $AuthBytes  = [System.Text.Encoding]::Ascii.GetBytes($AuthString)
  return [Convert]::ToBase64String($AuthBytes)
}

$tmpcred = Get-Credential
$BasicCreds = Get-BasicAuthCreds -Username $tmpcred.UserName -Password $tmpcred.GetNetworkCredential().Password
    #取り出したURLからファイル名を取り出し、変数$fileにセット
    $uri = New-Object System.Uri($url)
    $file = Split-Path $uri.AbsolutePath -Leaf

try {
    Invoke-WebRequest -Uri $url -Headers @{"Authorization"="Basic $BasicCreds"} -OutFile $file
} catch {
    $_.Exception.Response.StatusCode.Value__
    if ($_.Exception.Response.StatusCode.Value__ -eq 404) {Write-host "エラー 404: $urlにアクセスできません" -foregroundcolor red}
    exit
}
Write-host $file "をダウンロード完了しました。"　-foregroundcolor green
```
【Linux】grepの便利なオプション

# 便利なオプション
たまに使うやつは毎回忘れてググるのでメモ。
※grep対象のパターン指定は`"pattern"`でも`'pattern'`でもどっちでもOK

## 指定した単語を除く
`-v`の後ろに除きたい単語を指定する

```
$ grep "https://xxx.co.jp/" /var/log/debug.log | grep -v "200"
```

## 大文字と小文字を区別しない
`-i`のオプションを付けると大文字小文字を区別しない

```
$ grep -i "retry" /var/log/debug.log
```

## マッチした前後の行も表示
- 後ろだけ表示したい場合はAfter：`-A`
- 前だけ表示したい場合はBefore：`-B`
- 前後両方表示したい場合はContext：`-C`

```
# 後ろ5行だけ表示したい場合
$ grep -A 5 "retry" /var/log/debug.log

# 前5行だけ表示したい場合
$ grep -B 5 "retry" /var/log/debug.log

# 前5行、後ろ10行を表示したい場合
$ grep -B 5 -A 10 "retry" /var/log/debug.log

# 前後5行を表示したい場合
$ grep -C 5 "retry" /var/log/debug.log
```

## 完全一致した単語だけ
`-w`を付けないと`RESPONSE-BODY`も引っかかるけど、`-w`を付けると`RESPONSE`と独立してて完全一致する場合だけ引っかかる

```
$ grep -w "RESPONSE" /var/log/debug.log
```

## 複数の単語で検索
### 複数の単語でOR検索
`-e`を複数付けて指定するか、`-E`と`|`を組み合わせて複数の単語を指定するとOR検索になる

```
$ grep -e "success" -e "count" /var/log/debug.log
$ grep -E "success|count" /var/log/debug.log
```

### 複数の単語でAND検索
grepを`|`でつなげればAND検索になる

```
$ grep "success" /var/log/debug.log | grep "count"
```
Git で今いるブランチにコミットしたものを別ブランチに移す

# 一連のコマンド

## 移す先のブランチを今いるブランチから作成

```bash
git checkout -b another
```

## 元のブランチに戻る

```bash
git checkout rootBranch
```

## 元のブランチでリセットする

```bash
git reset origin/rootBranch --hard
```

# 例えば master から移すケースなら

```bash
git checkout -b another
git checkout master
git reset origin/master --hard
```
PlayFab ～マルチプレイの実装(Thunderhead)～

11月中旬にプレビュー版が実装されたPlayFabのマルチプレイサーバ(Thaunderhead)に関してまとめてみました

もともとマルチプレイはPhotonと連携することで利用できた機能だけど
PlayFabのみでも利用できるようになりましたよ、という話
※とはいえ、あくまでプレビュー版なので利用するにはPlayFab側への依頼が必要

有効にした場合、こんな感じで設定できる

![Multi_01.png](https://qiita-image-store.s3.amazonaws.com/0/313446/eb5f5a71-03a9-f916-b884-cc7b0f9d6470.png)

## 〇実装へのみちのり〇
### (1)GameServerの作成
マルチ用のゲームサーバを作る
PlayFabマルチプレイ用コンテナイメージはWindowsCoreをベースにしています
ローカルでテストする場合は、[DockerHub](https://hub.docker.com/r/microsoft/playfab-multiplayer/)経由でダウンロードできます

※私的ハマりポイント※
1)DockerforWindows を利用してローカルにPullしようとしたところタイムアウトしてしまった
ちゃんとMicrosoftOfficialに[手順](https://docs.microsoft.com/ja-jp/virtualization/windowscontainers/quick-start/quick-start-windows-10)が書いてあるという罠
2)latestのPullがうまくいかなかった
タグ指定したらできました。
初心者に優しくない

ちなみにコンテナは現在Linuxには対応していないが、近いうちにサポートされる予定らしい

### (2)GameServer実行ファイル、アセット(必要であればSSL証明書)をアップロードする
ゲームサーバーの実行ファイルとアセットをアップロードします。
Game ManagerまたはPlayFab APIおよびSDKを使用してサーバーをアップロードし、ビルドを管理します
アセットのサイズはZipファイルで10GB以下にする必要があります
展開するサーバのリージョンや各リージョンでの最低・最大サーバ数を決定できます
※契約してないので「容量がありません」と表示されていますが、本来は表示されない(はず)

![Multi_02.png](https://qiita-image-store.s3.amazonaws.com/0/313446/11ccc851-b582-f625-76f0-c937292e0793.png)


### (3)ゲームサーバのBuild
アップロードされたBuildはPlayFab側でサーバを動的に作成しリサイクルすることができます
サーバはAzure内で展開されます
Buildの更新を行った場合、新しいBuildの追加と合わせて古いサーバのスタンバイサーバ数を減らすことで
古いサーバへの割り当てを減らしていく形で切り替えます


### (4)プレイヤーのレイテンシーの確認
プレイやーがマルチプレイを始めると、PlayFab側でUDPメッセージを送信しネットワーク遅延をAzureで測定します
マルチ用サーバは冗長性とユーザの近いリージョンでプレイできるよう、12以上のAzureリージョンに設定することができます
UDPでビーコンを送信するC++のSDKは[公式](https://api.playfab.com/docs/tutorials/landing-tournaments/multiplayer-servers-2.0/using-quality-of-service-qos-beacons-to-measuplayer-latency-to-azure)で提供されています

### (5)プレイヤーからのリクエストの処理
ロビーサーバもしくはマッチングサーバから、もしくはクライアントから直接リクエストが飛んでくる
GameServeはコンテナなのでIPv4のIPが割り振られます
ポート番号も設定することで任意に変更可能です。
(ただし事前に展開されるAzure側で開けておく必要がある模様)

### (6)接続
サーバがアクティブになるとクライアントはサーバに接続してマルチプレイができるようになる
ユーザのアクセスに応じて設定した数字でサーバの拡縮が自動的に行われる感じ
どうもログはサーバから手動でとってこなくてはいけない模様・・・


※現在C#、C++、Javaのサンプルコードは出ているが、Unityのサンプルは2019年1月頃までに準備されるとのこと


Preview版のためサービスを触り切れなかったので、確認できたら追記したい(希望)
Nginx経由のGitbucketに接続できない時の対処法

# 事象
1. Gitbucketに接続出来ない事象が発生
2. Nginxのerrorlogを確認

```/var/log/nginx/error.log
[error]connect() failed (111: Connection refused) while connecting to upstream
```

- なんとなく「upstream」が怪しそう・・・
- 同じnginxからリバースプロキシしているredmineやsvnは上記のエラーは発生していない
- 別サーバから参照していた場合も同様のエラーが発生する

### とりあえず「connect() failed (111: Connection refused) while connecting to upstream」でググってみる
- https://teratail.com/questions/1256010
    - default.confが怪しそうなので確認
        - なんとなく大丈夫そう

```/etc/nginx/conf.d/default.conf
upstream unicorn-redmine {
    server unix:/opt/rails/redmine/tmp/sockets/unicorn.sock;
}

upstream unicorn-redmine-first {
    server unix:/opt/rails/redmine-first/tmp/sockets/unicorn.sock;
}

server {
    listen       80;
    server_name  $http_host;

・・・

   location /redmine {
        #proxy_pass http://127.0.0.1:8282/;
        proxy_pass http://unicorn-redmine;
    }

    location /gitbucket {
        proxy_pass              http://127.0.0.1:8080;
        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_connect_timeout   150;
        proxy_send_timeout      100;
        proxy_read_timeout      100;
        proxy_buffers           4 32k;
        client_max_body_size    500m; # Big number is we can post big commits.
        client_body_buffer_size 128k;
    }

・・・

```

### そもそもListen状態なのか確認

```
lsof -i:8080
```

⇒Listenしてない！
　⇒Tomcatサービスが起動してない？？

### サービス起動確認

```
ps -aux
```

⇒Tomcatサービスが起動してない！

### Tomcatサービス存在確認

```
systemctl list-units --type=service
```

# 原因
Tomcatサービスが起動してないことが原因

# 対応
Tomcatサービスを起動する

```
sudo systemctl start tomcat
```

# 謎
Tomcatサービスは自動起動の設定にしてあるのになぜ？？？
誰かが意図的にサービスを停止させたとしか思えないが、、、
Visual Studio CodeのMac版で、開いているウインドウ一覧に亡霊が残る問題の解決方法

# Visual Studio CodeのMac版で、開いているウインドウ一覧に亡霊が残る問題の解決方法

アプリにはDock上に「開いたことがあるもの(ファイル,フォルダ)」と「開いているウインドウ」のリストがある。これはDock上から消えた時(固定されている場合は固定解除した時)などにアプリ側で保存される。

VSCodeのMac版にはこの辺りにバグがあるらしく、不意に開いてもないウインドウの亡霊が「開いているウインドウ」のところに出っ放しになることがある。これは一旦発症するとアプリを再起動しても改善しない。

解決方法は、下記手順である

- VSCode を終了する
- 「Dockに追加」がチェックついていれば外す
- ~/Library/Application\ Support/Code/storage.json を他のエディタで開く
- openedPathsList項目の、workspaces2 と files2 を空配列にする
- VSCode を普通にまた使い始める(Dockに追加もやってOK)

## 発症を経験したバージョン
- 1.29.1(OS X El Capitan,10.11.6)

※ここに書いたのはあくまで私が発症を確認したリストです。これより前のバージョンでも発生すると思われますし、OSとの相性の可能性もあります
deflate と zlib と gzip の整理

## TL; DR
- 毎回忘れて調べるので、書き留めておきます

時間のない人向けまとめ

- `deflate` = 圧縮アルゴリズム（LZ77 + ハフマン符号）
- `zlib`, `gzip` = 圧縮ライブラリ名 兼 ヘッダ/フッタフォーマットの定義

## deflate
Wikipedia: https://ja.wikipedia.org/wiki/Deflate

> Deflate（デフレート）とはLZ77とハフマン符号化を組み合わせた可逆データ圧縮アルゴリズム。

- `deflate` = 圧縮アルゴリズム（LZ77 + ハフマン符号）
- Golangのパッケージ: https://golang.org/pkg/compress/flate/

## zlib
Wikipedia: https://ja.wikipedia.org/wiki/Zlib

> zlibは、データの圧縮および伸張を行うためのフリーのライブラリである。
> ヘッダーやフッターなどのデータ形式はRFC 1950 (ZLIB Compressed Data Format Specification)として仕様化されている。

- `zlib` = 圧縮ライブラリ名 兼 ヘッダ/フッタフォーマットの定義
- 圧縮アルゴリズムは `deflate` を使用
- Golangのパッケージ: https://golang.org/pkg/compress/zlib/

## gzip
Wikipedia: https://ja.wikipedia.org/wiki/Gzip

> gzip（ジー・ジップ）は、データ圧縮プログラムのひとつ、およびその圧縮データのフォーマットである。
> フォーマットはRFC 1952 「GZIP File Format Specification」として文書化されている。

- `gzip` = 圧縮ライブラリ名 兼 ヘッダ/フッタフォーマットの定義
- 圧縮アルゴリズムは `deflate` を使用
- Golangのパッケージ: https://golang.org/pkg/compress/gzip/

## おまけ: Context Takeover (WebSocket)
RFC: https://tools.ietf.org/html/rfc7692#section-7

>  The term "use context takeover" used in this section means that the
>    same LZ77 sliding window used by the endpoint to build frames of the
>    previous sent message is reused to build frames of the next message
>    to be sent.

- `context takeover` = `deflate` 圧縮の LZ77 ウィンドウを引き継ぐこと
- `gzip の context-takeover` とかは 誤用なので注意

## おまけ: Content-Encoding: deflate について

- `deflate` の 生ストリームではなく、 `zlib` 形式なので注意

[HTTP圧縮でdeflateではなくgzipが採用される理由とは?](https://teratail.com/questions/5026)

> HTTPのヘッダー上では、zlibヘッダー付きのdeflateをdeflateと指定するのですが（RFC2616の3.5節）、名前のせいで生のdeflateストリームとしてしまうプログラムがあるようで、うまくやりとりが出来ないことがあるため、多少バイトが増えてもより安全なgzipが使われる、とのことです

[Golangにて"compress/flate"パッケージがflateで圧縮したデータを復元できなかった件について](https://qiita.com/liubin/items/a98e3fac7590ea02e966)

> 調べたところ、この スレード のように、入力データは Zlib のストリームなので、 compress/zlib を使うべきだった。
> 
> なんでクライアントが Zlib のデータなのに Content-Encoding に deflate 設定したのだろう。
Azure Pipelines で Xamarin.Android の AOT Compile を使う

Xamarin.Forms で簡単なアプリを作って、その Android 版を社内向けに配布しようとしたんですけど、 .apk のサイズが 60Mbyte超 もあって、「仕方ないよね…」と思いながら、 モバイル回線でそれをダウンロードさせるのかー、と思うと良心の呵責を感じてしまい、可能な限りで apk のサイズを縮小することを試みました。

## Xamarin.Android アプリのビルドオプションを調整して apk サイズを減らす

apk サイズの削減については、

* [Xamarin.Android 起動速度改善の記録 (追記あり) - Qiita](https://qiita.com/conduits/items/cd7338329c3b7c22dc9c)

を参考にさせていただきました。当該記事は「起動時間」にフィーチャーしていますが、サイズ縮小についても十分に有用です。

最終的に落ち着いたコンパイルオプションは、

* Android Build - Enable AOT
* Linker - Link SDK assemblies only

で、これも上記記事と同じです(LLVM は使ってません)。
この結果 apk のサイズは 60Mbyte超 → 33Mbyte になりました。

（上記に比べてさらに、「Linker - Link all assemblies」 とすれば 25Mbyte にまで削減できましたが、このアプリは起動せず、「リンクしたらマズそうなアセンブリ」を Ignore assemblies に追加していったら起動するようにはなったものの apk は 29Mbyte になったので、かけるコストに対して効果は薄そうだと判断してやめました。）

ここまではアプリのビルドの話で、次からが本題です。

## Azure Pipelines で Xamarin.Forms(Android) アプリをビルドする

[Azure Pipelines](https://azure.microsoft.com/ja-jp/services/devops/pipelines/) は Azure DevOps というサービスに含まれるサブサービスの一つで、CI/CD の機能を提供します。

Android, iOS, Linux, macOS, Windows 用のアプリをビルド・デプロイできます。
OSS向けならビルド時間は無制限、個人プライベート向けでも1800分/月[^a] まで無料で使うことができます。

[^a]: サイトには「並列ジョブ (1 か月あたり最大 1,800 分)」 とあるので、単一のジョブなら無制限なのかもしれません。

Azure Pipelines で Xamarin.Android 向けのプリセットを選択すると、ほぼそのままアプリのビルドが行える状態になります。このプリセットで使用されるビルドエージェントは "Hosted VS2017" で、つまり 「Visual Studio 2017 がインストールされた Windows マシン」 です。

が、上記の 「Enable AOT」 を有効にしたプロジェクトで CI ビルドさせると、以下のエラーが出ます。

> XA5101: Missing Android NDK toolchains directory '\toolchains'. Please install the Android NDK.

どうやら Android NDK がインストールされていない様子。 Agent の Pool information を見ても Android NDK は記載されていません。

そこで [公式Twitter](https://twitter.com/AzureDevOps) に凸! すると、

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="en" dir="ltr">Thanks for reaching out! We rely on Visual Studio to install the Android NDK. This thread with a similar scenario might come in handy: <a href="https://t.co/rSqfEaoLhS">https://t.co/rSqfEaoLhS</a>.</p>&mdash; Azure DevOps (@AzureDevOps) <a href="https://twitter.com/AzureDevOps/status/1068128192685375488?ref_src=twsrc%5Etfw">2018年11月29日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

「Android NDK は Visual Studio が入れちゃんだわ、NDK は ``C:\Microsoft\AndroidNDK64\android-ndk-r15c`` に入ってるよ(超意訳)。」とのこと。
これを手がかりにさらに調べると、

* [Missing Android NDK toolchains directory '\toolchains' when building Xamarin.Android with hosted tfs build server - Stack Overflow](https://stackoverflow.com/questions/36940896/missing-android-ndk-toolchains-directory-toolchains-when-building-xamarin-and/47338287#47338287)

> in the MSBuild Options, provide the following Additional Argument:
>
> VS2017 Hosted agent: 
> /p:AndroidNdkDirectory="C:\ProgramData\Microsoft\AndroidNDK64\android-ndk-r13b"

これだね。

というわけでビルドタスクのオプションに、

```
/p:AndroidNdkDirectory="C:\Microsoft\AndroidNDK64\android-ndk-r15c"
```

を追加します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/8227/1025aa90-0845-16c6-2578-a4db3949904d.png)

これで AOT を有効にした状態の Xamarin.Android プロジェクトがビルドできるようになりました。

そういえば AOT はまだ Experimental ですね。
あと Enterprise Edition でしか使えないということだったような？ まあ見なかったことにしよう。
「そこは less で表示してほしくない！」という時に使える cat

Git の pager に less を指定している場合など、何もしないと less で表示される場合があります。便利なのですが、行番号が表示されたりと不便なこともあります。

1 コマンドだけそれを解除する方法です。

# やり方
最後に `| cat -` をつけるだけ。

```sh:console
# git diff # => less で表示されてしまう
git diff | cat - # => コンソールに表示される
```

# 使いどころ
自分は `git diff --name-only` でファイル名をターミナルからコピーしたいときに使います。

# どうしてこうなる
パイプに流すと less で表示されず、標準入力をそのまま出力する `cat -` でコンソールに出力しています。

# 終わりに
コピー用途なら `pbcopy` や `clip` を使うほうが楽だと思います。
BeanstalkでRailsアプリをeb deploy（デプロイ）した時にnokogiriが原因でうまく行かないとき

##結論
人によって原因は違うと思うのですが、
僕の場合はインスタンスのサイズが小さすぎて、
（デプロイしたタイミングで）nokogiriをインストール時に
（多分）メモリが足りなくて落ちていました。

なので、インスタンスタイプを大きくすると解決しました。
（私の場合はt2.smallで無事動きました。）

参考：
https://stackoverflow.com/questions/25963315/nokogiri-installation-failes-on-elastic-beanstalk

>Don't try to run ruby on anything smaller than a t2.small.

##挙動

テスト環境として使っていたため、
費用を抑えるため、
インスタンスタイプにt2.nanoを使用しており、
その状態ではbundle installでコケてました。

しかもアプリにリクエストを送ると
クライアントにはcorsエラーが表示されてました。

サーバ内エラーが出てる時に
とりあえずcorsだすのやめて欲しい。

私の場合は、
t2.smallにインスタンスタイプを設定すると動きました。

それ以外にも原因はあるかもですが、

・本番では動いてるのにテスト環境では動かない
・環境によってnokogiriが原因で落ちる時がある

といった場合は一度インスタンスタイプを確認してみてください。

##終わり
何か間違ってることなどがあればご指摘いただけると幸いです。
ENUM から電番の引き方

https://danielpocock.com/a-quick-look-at-enum

ENUM, as defined by the IETF, is a convenient and powerful way to map telephone numbers to the latest communications technologies such as SIP, XMPP (Jabber) and web sites.

ENUM resolution operates much like reverse DNS lookup:

- Take the number you want to call and normalize it into E.164 format - in other words, by removing any leading zero and punctuation and adding the country code. For example, for a British number "020 7123 4567", the country code is 44 and so the normalized form of the number is +442071234567
- Remove the leading plus symbol, reverse the digits and insert a dot between each digit. For our sample number +442071234567, it becomes 7.6.5.4.3.2.1.7.0.2.4.4
- Choose the ENUM suffix. The official ENUM tree defined by the IETF uses the e164.arpa ENUM suffix. There are several third-party suffixes as well, such as e164.org and for the sip5060.net service, use the suffix e164-addr.sip5060.net. For our example, the full string, with suffix, is 7.6.5.4.3.2.1.7.0.2.4.4.e164.arpa
- Perform a DNS lookup, typically looking for NAPTR records

```
dig -t naptr 7.6.5.4.3.2.1.7.0.2.4.4.e164.arpa
```
CuPyインストールガイド

#環境
OS: Ubuntu 16.04 LTS
CUDA: 9.0

```
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.5 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.5 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
```
```
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2017 NVIDIA Corporation
Built on Fri_Sep__1_21:08:03_CDT_2017
Cuda compilation tools, release 9.0, V9.0.176
```
#インストール手順
インストール前に一応pipとsetuptoolsをアップデート

```
$ pip install -U setuptools pip
```

CUDAのversion確認

```
$ nvcc -V
```

CUDAのversion(下記は9.0の場合)のCuPyインストール

```
$ pip install cupy-cuda90
```

CuPyが入ってるか確認

```
$ pip freeze
```
cudaが入っていない or cudaをUpgradeしたい場合の参考
https://qiita.com/1O1/items/c7b0cec503d48b2efde1
#参考
https://docs-cupy.chainer.org/en/stable/install.html#using-pip
Spinnerの読み込みを停止すると、より良いことがある

##はじめに

読み込みスピナーは、コンテンツ読み込みの問題の解決策になるかもしれません。しかし、私はあなたにそれがそうではないことを伝えるためにここにいます。
あなたのユーザーインターフェイスで退屈なローディングスピナーの使用をやめてください。それはあなたが知っている以上にあなたのアプリケーションの経験を殺している。

##なぜ読み込むスピナーが動作しないのか

読み込みスピナーはユーザーインターフェイスのデザインで最もよく使用される進行状況インジケータの1つです。 しかし、それは一般に見落とされる独自の欠陥があります。
![facebook_loading_spinner_overload.png](https://qiita-image-store.s3.amazonaws.com/0/149434/26f72049-4691-c1f6-bb45-aebf9220d965.png)

###進歩の兆候なし

ローディングスピナーはあなたに何を伝えますか？ コンテンツが現在ロード中であることを示します。 しかし、どのくらいの負荷がかかっていると言いますか？ どのくらいの負荷が残っていると言いますか？
__いいえ、そうではありません。__
さらに、それを決定することは困難です。 可能であれば、進行状況バーを正しく使用していますか？
###不確定な時間
- ローディングスピナーを見ると、どれくらいの時間が経過するのか分かりましたか？
- どのくらいのコンテンツが読み込まれていますか？
- どのくらいの負荷が残っていますか？

私たちはただローディングスピナーを見つめています。 これらの3つの質問のいずれにも答えることなく、時間通りに読み込むことを望んでいます。
さらに、ネットワーク接続が不安定になる可能性があります。 だから、コンテンツが常に高速に読み込まれることは決して許されません。
それでは私たちは何をすべきか？答えは__Skeleton Screens。__

##Skeleton Screens
ローディングスピナーとは異なり、UIは一度にすべて表示されます。 スケルトン画面は、少しずつユーザーインターフェイスを読み込むのに役立ちます。
これは、ベアボーンのUIが最初に表示されることを意味します。 その後、ロードされたコンテンツは徐々に画面に表示されます。
![linkedin-skeleton-screen-loading.png](https://qiita-image-store.s3.amazonaws.com/0/149434/e80b644d-c3e5-1294-3fa0-327df46bad3f.png)
_LinkedInは最近、読み込みのためにスケルトンスクリーンを使用し始めました。_

スケルトン画面はユーザーの注目を集めます。 待ち時間ではなく進歩に焦点を当てる。
スケルトン画面は、ユーザーがインターフェースから何を期待するかを視覚的に示します。 それは、来るべきものを頭に浮かべ、徐々に進歩の感覚を作り出します。

何よりも、人々はあなたのサイトが実際よりも速いと感じさせます。 実際の人々が使用するためのインタフェースを設計していることに注意してください。 人々にスピードの錯覚を与える必要があります。
スケルトン画面を使用すると、次の利点があります。

- 人々が画面をより速く読み込むようにする
- 驚きをなくす
- UIの段階的な読み込み - 進捗状況の明確な表示
- ロードされているものとまだロードされていないものを正確に表示します

###次第に進行
まず、裸の骨のUI（スケルトン画面）をレイアウトします。 次に、テキストデータをロードします。 ユーザーはコンテンツを受け取ったことを知っています。 最後に、イメージを怠惰に読み込みます。 ユーザは、コンテンツの大部分がロードされたことを理解する。 残っているのは画像です。
このようにして、ユーザーは次のように指定できます。

- 進歩の明確な感覚
- 次は何を期待する
- 期待していたこと
![facebook-skeleton-loading-website.png](https://qiita-image-store.s3.amazonaws.com/0/149434/57a1b5cd-96bb-d414-0b50-4f2b7847cc4d.png)

###イメージのプログレッシブ読み込み
以下は画像のプログレッシブロードに関する一般的な手順を示します。

- スケルトン画面を表示する
- 非常に低品質の（ピクセル化された）バージョンのイメージ（または顕著な色）を読み込み
- 高品質の画像を背景に読み込む
- 以前の低品質のものを置き換えて、高品質の画像をフェードイン

もちろん、最初に表示するものは異なります。 例えば、Mediumは非常に小さなピクセル画像を使用することを選択し、その上にぼかしフィルタを適用します。 その後、高品質のイメージをロードして置き換えます。 一方、Googleは画像の目立つ色を最初に表示します。

###AndroidとiOSのスケルトン画面

スケルトン画面の例のほとんどはウェブサイトだと主張するかもしれません。 それでは私はどのようにモバイルでこれを行うのですか？ あなたは絶対に正しいです。
私はあなたにこれを行う方法のヒントを与えていない場合、このすべてを読むことは価値がないだろう。

FacebookはAndroidとiOSの両方に`Shimmer`というライブラリを書いています。
これはFacebookがスケルトンUIを使って入ってくるコンテンツを読み込むのと同じように機能します。シマーアニメーションは、コンテンツが現在読み込まれていることを示します。
このライブラリを使用して、アプリケーションの読み込みを示すスケルトン画面を表示することができます。

##まとめ
アプリはスマートになっています。 人々は、Loading SpinnerがUXを傷つけていることに気付き始めています。
スケルトン画面ではインターフェイスの読み込みが徐々に進行します。そのような増分フィードバックは、より良いユーザ体験を提供し、不確実性を低減する。さらに、人々はもう少し長く待つことになります。

それではスケルトンスクリーンについてどう思いますか？以下のコメントで私に教えてください。
redash_matadata  を使ったredash統計情報

参考
https://qiita.com/toyama0919/items/f3482ab9e96c82df5952


クエリ閲覧数ランキング

```SQL
SELECT
    q.id,
  '<a href="/queries/' || q.id || '" target="_blank">' || q.name || '</a>' AS name,
  COUNT(e.id) AS view_cnt,
  COUNT(DISTINCT e.user_id) AS user_cnt
FROM events e 
INNER JOIN queries q  ON CAST(e.object_id AS INTEGER) = q.id
WHERE 
  e.action = 'view' AND e.object_type = 'query'
and is_archived = false
and is_draft = false
GROUP BY 1,2
ORDER BY 3 DESC
```
　ダッシュボード閲覧数ランキング

```SQL
SELECT
  '<a href="/dashboard/' || d.slug || '" target="_blank">' || d.name || '</a>' AS name,
  COUNT(e.id) AS view_cnt,
  COUNT(DISTINCT e.user_id) AS user_cnt
FROM events e 
INNER JOIN dashboards d ON CAST(e.object_id AS INTEGER) = d.id
WHERE 
  e.action = 'view' AND e.object_type = 'dashboard'
GROUP BY 1
ORDER BY 2 DESC
```

クエリのfolk数ランキング

```SQL
SELECT distinct
    q.id,
    '<a href="/queries/' || q.id || '" target="_blank">' || q.name || '</a>' AS name,
    count(*)
FROM queries q
LEFT JOIN events e
ON CAST(e.object_id AS INTEGER) = q.id
WHERE
    action = 'fork'
and is_draft = false
and is_archived = false
GROUP BY 
    1,2
ORDER BY
    3 desc
```