OmniAICreator/Qiita-1.07M huggingface dataset:
ローカル環境のまま外部と連携を確認する方法

#はじめに
LINEなどでBotを開発している場合、今までは公開されているサーバーにわざわざアップロードして動作を確認していました。
しかし、[ngrok](https://ngrok.com/)というサービスを使えばローカルのまま確認ができ、修正もしやすくなりました。
すごく便利だったのでメモを残しておきます。

# セットアップ
[https://ngrok.com/](https://ngrok.com/) に登録するとセットアップの手順が書かれています。

1. 「Download for Windows」というボタンからZIP圧縮されたngrokをダウンロードします。
2. ダウンロードしたファイルを解凍するとngrok.exeが入っていますので、適当なところに設置してください。
3. コマンドプロンプトを立ち上げて、以下のコマンドを実行すると設定ファイル`ngrok.yml`が作成され、セットアップが完了します。
アクセストークンは[こちら](https://dashboard.ngrok.com/auth)で確認できます。

```
> ngrok.exe authtoken <YOUR_AUTH_TOKEN>
```

# 基本的な使い方

以下のコマンドでローカルホストの80にトンネルが設置されます。

``` 
> ngrok.exe http 80
```

```:実行画面
ngrok by @inconshreveable

Session Status                online
Account                       Xxxxxxxx Xxxxxxx (Plan: Free)
Version                       2.2.8
Region                        Asia Pacific (ap)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://53d87b73.ngrok.io -> localhost:80
Forwarding                    https://53d87b73.ngrok.io -> localhost:80

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

```

※53d87b73の部分は実行するたびに変わります。

# 応用的な使い方

## 接続先を変更する
ローカル環境の設定応じて接続するポート番号やIPアドレスを指定することができます。

```:WEBサーバーが8080番ポートで動作している場合
> ngrok.exe http 8080
```

```:vagrantのローカル環境を構築している場合
> ngrok.exe http 192.168.33.10:80
```

## Regionを指定する
デフォルトのRegionは`United States`ですが、他の地域を指定することもできます。

```:RegionにAsia/Pacificを指定
> ngrok.exe http -region=ap 80
```

## Basic認証を設定する
ローカル環境を一部のメンバーにだけ公開したい場合はBasic認証を設定することもできます

```:ユーザー名：username、パスワード：passwowdで認証
> ngrok.exe http -auth="username:password" 80
```

## 設定を保存する
Windowsの場合はユーザーディレクトリに設定ファイル`C:\Users\user\.ngrok2\ngrok.yml`が作成されます。
こちらを書き換えることで毎回オプションを指定する必要がなくなります。

```yaml:ngrok.yml
authtoken: <YOUR_AUTH_TOKEN>
region: ap
tunnels:
  vagrant:
    proto: http
    addr: 192.168.33.10:80
```

```:設定を使って起動する場合
> ngrok.exe start vagrant
```


# 動作環境
- Windows 10 Home
- ngrok 2.2.8
Rails Tutorial にいいね機能をAjax対応で実装できない

http://mochikichi.hatenablog.com/entry/rails_tutorial_like
を参考にRails Tutorialの拡張機能としていいね機能（Ajax対応）を実装できず困っております。
いいね機能は実装できましたが、Ajax対応ができずページ更新しなければアイコンの色やカウントが変化しない状態です。

下記はHerokuのURLです
https://stark-sierra-88856.herokuapp.com/

関連するView、パーシャルは下記の通りです。

```micropost.html.erb
<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="content">
    <%= micropost.content %>
    <%= image_tag micropost.picture.url if micropost.picture? %>
  </span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
    <% if current_user?(micropost.user) %>
      <%= link_to "delete", micropost, method: :delete,
                                       data: { confirm: "You sure?" } %>
    <% end %>
  </span>
  <!--like function-->
    <%= render partial: 'likes/like', locals: { micropost: micropost, likes: @likes } %>
</li>
```

```_like.html.erb
<% if micropost.like_user(current_user.id) %>
  <%= button_to micropost_like_path(likes, micropost_id: micropost.id), method: :delete, id: "like-button", remote: true do %> 
    <%= image_tag("icon_heart.png") %>
    <span>
      <%= micropost.likes_count %>
    </span>
  <% end %>
<% else %>
  <%= button_to micropost_likes_path(micropost),id: "like-button", remote: true do %>  
    <%= image_tag("icon_gray_heart.png") %>
    <span>
      <%= micropost.likes_count %>
    </span>
  <% end %>
<% end %>
```

```create.js.erb
$("#like-buttons").html("<%= j(render partial: 'like', locals: { micropost: micropost, likes: @likes, like: @like}) %>");
```

```destroy.js.erb
$("#like-buttons").html("<%= j(render partial: 'like', locals: { micropost: micropost, likes: @likes }) %>");
```

その他に必要情報があれば早急に対応しますのでよろしくお願いいたします。
laravel5.7 新機能 ユーザ登録時のメールアドレス検証

laravel5.7でメールアドレスの検証が機能追加されました
これまでは独自で実装していたので楽になりますね

# 使い方

User Eloquentに `\Illuminate\Contracts\Auth\MustVerifyEmail` インターフェースを実装し,Auth::routesの引数を足すだけです

users migrationファイルに `email_verified_at`　カラムが追加されています

```php
class User extends Authenticatable implements MustVerifyEmailContract
{
    use Notifiable, MustVerifyEmail;
    //省略
}
```

```php
Auth::routes(['verify' => true]);
```

この状態でユーザ登録を行うと確認メールが届きリンクを踏んで本登録という流れです

# ルート保護
認証は、`auth`の場合メールアドレス認証をしていない場合でも見れます
メールアドレス認証が必要なルートは`verified`を使うことで保護できます

# 参考
実装
https://github.com/sizukutamago/laravel5.7-email-verify/commit/b37c7fe7ee8467a9a5e21fc11f1550f7ee6f3fd3

リリースノート
https://readouble.com/laravel/5.7/ja/releases.html

laravel5.7から404の画面とかフォントとかも変わってますね
実装を追うのはまた今度で
[Node.js] Express を TypeScript で書く - MongoDB 接続編

# はじめに

この記事は続き物となっております。以下も合わせてお読みください。

- [[Node.js] Express を TypeScript で書く - 環境整備まで](https://qiita.com/kuroneko8960/items/74347b6a58020f33b18d)
- [[Node.js] Express を TypeScript で書く - ルーティング編](https://qiita.com/kuroneko8960/items/1e6dcd0d897b42567319)

また環境は以下を前提としてます。

- Windows 10
- Node.js 10.10.0
- Express 4.16.3
- TypeScript 3.0.3
- MongoDB 4.0.2 Community Server
- MongoDB Node.js 3.1.4
- Visual Studio Code 1.26.1

# MongoDB の導入

## サーバーの導入

[MongoDB公式](https://www.mongodb.com/) よりCommunity Server をダウンロードしてきます。インストールはwindows環境であればインストーラーのウィザードに従うだけで出来ます。サーバーはサービスとして登録されるので特に意識して立ち上げるといった必要はありません。

## モジュールの導入

プロジェクトの方に戻り、MongoDB用のモジュールをインストールします。TypeScript用の型定義も一緒にインストールします。現時点ではバージョンは3.1です。

```bash
npm install --save mongodb @types/mongodb
```

# MongoDBを使用する準備

APIの各所でMongoDBを使うことになるので、接続、DB取得までを共通で使える部品を作ります。[公式のドキュメント](http://mongodb.github.io/node-mongodb-native/3.1/quick-start/quick-start/)を見ながら作ります。

接続までは以下のソースコードの通りです。

```ts
import * as MongoDB from 'mongodb';

const url = 'mongodb://localhost:27017';

client.connect(url, { useNewUrlParser: true }, (err, client) => {
    if (err) {
        // 接続エラー時の処理
        return;
    }

    // 接続後の処理
    client.close();
});
```

`{ userNewUrlParser: true }` を入れておかないと `mongodb://` といったURLを使ったときに警告がでるので入れておきます。

接続後、dbを取得するのは簡単で以下のように書くだけです。

```ts
const db = client.db('dbname');
```

これらをまとめて関数化し部品にしたものが以下のソースになります。

```ts:src/common/mongodbClient.ts
import * as MongoDB from 'mongodb';

const url = 'mongodb://localhost:27017';
export const dbName = 'nekoblog';

export default function (callback: (err: MongoDB.MongoError, client: MongoDB.MongoClient, db: MongoDB.Db) => void) {
    const client = MongoDB.MongoClient;
    client.connect(url, { useNewUrlParser: true }, (err, client) => {
        if (err) {
            callback(err, null, null);
            return;
        }
        callback(null, client, client.db(dbName));
    });
}
```

使い方は以下の感じです。

```ts
import mongodbClient from './mongodbClient';

mongodbClient((err, client, db) => {
    if (err) {
        // エラー時の処理
        client.close();
        return;
    }

    // 接続完了時
    client.close();
});
```

## 接続テスト

接続テスト用のAPIを作成し、MongoDBに接続が出来ているか確認します。

```ts:src/routes/dev/index.ts
import * as Express from 'express';
import mongodbClient from '../../common/mongodbClient';

const router = Express.Router();

router.get('/mongodb', (req, res, next) => {
    mongodbClient((err, client) => {
        if (err) {
            res.status(500).json({ message: 'MongoDB not connected.' });
            return next(err);
        }
        client.close();
        res.json({ message: 'MongoDB Connected.' });
    });
});

export default router;
```

`src/server.ts` への記述は省略しますが上を `/dev` に割り当ててます。

サーバー起動後、 `http://localhost:3000/dev/mongodb` に接続し `{ message: 'MongoDB Connected.' }` が取得できればOKです。

次からCRUDの実装をしていきます。

- [[Node.js] Express を TypeScript で書く - MongoDB CRUD編](https://qiita.com/kuroneko8960/items/438936767a0fed68afe4)
Athena(prestoDB)でgroup byしたあとあるカラムの内容を最初のN件だけとってかえすSQL

# 目標

Group byで、ユーザアカウントしたものの、サンプルとして、いくつかUidsを返したい `limit`してArrayにいれられればいいのだが、残念ながら無い


# 解決策

tableは、

group_columnとuser_idの2つだけの簡単なものでサンプルを以下に記す

```sql
SELECT group_column,
         slice(array_agg(distinct user_id), 1, 2) AS uids, 
         count(distinct user_id) AS cnt
FROM db.my_table
GROUP BY  group_column
ORDER BY  cnt DESC limit 10; 
```

これで


| group_column | uids | cnt |
|:--|:--|--:|
| A | [1, 2] | 10 |
| B | [11, 12] | 6 |
| C | [17, 18] | 4 |

という結果が得られる

# ポイント

```sql
slice(array_agg(distinct user_id), 1, <取りたい数>)
```

## array_agg(x) → array<[same as input]>

aggregate functionの`array_agg`を使って、GroupされたものをArrayにする

## slice(x, start, length) → array

array function の `slice` を使って切る

一番最初から撮りたいときは、startは0ではなく1!!!


## aggregation functionとarray functionの詳細

1. https://prestodb.io/docs/current/functions/aggregate.html
2. https://prestodb.io/docs/current/functions/array.html
IE11でArray.findIndexの代替はLodashで回避した

ハッシュ配列から要素を引いてくるときに、[Array.prototype.findIndex](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex#Browser_compatibility) つかってたのですが、IE11で実装されていませんでした... :weary:

```js:favs
favs = [
  {
    "code": "c1",
    "name": "foo"
  },
  {
    "code": "c2",
    "name": "bar"
  }
];
```

```js:Before
ByCode = function (item) {
  return item.code == this;
}
var code = "c2";
found = favs.findIndex(ByCode, code);
// found == 1
```

# Lodashなら雰囲気を維持したままIE11対応できるのが :ok_hand: 

- [Lodash #findIndex](https://lodash.com/docs/4.17.10#findIndex)

```html
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
```

```js:After
var code = "c2";
found = _.findIndex(favs, function(item){
  return item.code == code;
});
// found == 1
```
FuelPHPのRestで、responseを必ずjsonフォーマットにする方法

以下のように protected $formatに代入することで必ずjsonになります。

```
class Controller_Example extends Controller_Rest
{
    protected $format = 'json';

　　//メソッドを記述...
}
```
詳しくはドキュメントを参照
http://fuelphp.jp/docs/1.7/general/controllers/rest.html#/formats
デザインツールの便利なスクリプト、プラグインなどのメモ


```
もの忘れが激しいので自分用にメモ。気が向いた時に編集
```

# Illustrator
##### お気に入り
- [テキストばらし old](http://d-p.2-d.jp/ai-js/pages/01_scripts/text/#10_split_text_line)
 - 改行ごとにテキストをバラバラにしてくれる。古いillustratorならこっち。
- [テキストばらし new](https://www.tactsystem.co.jp/applescript/illustrator07.html)
 - 同上。CS6以降はこっち。

##### 今後試したいもの
- [参考サイト](http://www.dtp-transit.jp/adobe/illustrator/post_2238.html)
 - まずは 「#8 改行を削除する」,「#10 次（前）のアートボード、先頭・末尾のアートボードに移動」 から試したい。
- [behance](https://www.behance.net/)
 - 手作りアイコン整理してここに保管したい。

# Photoshop
- [テキストの抽出](https://blog.fenrir-inc.com/jp/2013/05/psd_text_export.html)
 - レイヤーの重なり順にテキストが並ぶので、抽出前に調整するのが良い。

##### 今後試したいもの
- [参考サイト](https://web-guided.com/post-472)
 - まずは「レイヤーを一括リネーム」を試したい。
PostgreSQLのクエリ

## カラム

### カラムを消す
ALTER TABLE `table name` DROP COLUMN `column name`

### カラムを追加する(数字)
ALTER TABLE `table name` ADD COLUMN `column name` INTEGER

### カラム名を変更する
ALTER TABLE `table name` RENAME `column name` TO `column name`

### 部分一致しているカラムを検索する
SELECT * FROM `table name` WHERE `column name` LIKE `%part_of_value%`

## レコード

### レコードを削除する
DELETE FROM `table name` WHERE `column name` = '`value`'

### レコードを追加する
INSERT INTO `table name`(`column name`, `column name`, `column name`) VALUES ('string', 12345, '')

### カラムにNULLを設定しないようにする
ALTER TABLE `table name` ALTER COLUMN `column name` SET NOT NULL

### NULL文字を空文字に置き換える
UPDATE `table name` SET `column name` = '' WHERE `column name` IS NULL;

## 強制キャンセル

### 最上位のpidを確認
SELECT * FROM pg_stat_activity WHERE state = 'active' ORDER BY xact_start;

### クエリを強制的にキャンセル
SELECT pg_cancel_backend(`pid of the process`)
Internet Explorer 11 のローカル ストレージを消去する

1. `F12` キーを押して開発者ツールを開く
2. `[コンソール]` タブをクリックします。
3. フィールドに `localStorage.clear()を入力して Enter`

> ![image.png](https://qiita-image-store.s3.amazonaws.com/0/2883/4b97bf08-c384-40a6-574b-a12dcf33a06a.png)
論文まとめ：Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network

# はじめに
今更感があるけど、SRGANをまとめてみた。

[1] C. Ledig, et. al. "Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network"

https://arxiv.org/abs/1609.04802

コードも既にいろいろ転がってる。例えばtensorflowの実装。
https://github.com/tensorlayer/srgan

# 概要  
- SRGANという名の超解像度のモデル
- residual blockをベースとしたGANで学習した
- perceptual lossを導入した

以下の図の右から２つ目がSRGANで生成された画像。一番右が元の高解像度画像。元の画像とは違うものの、それっぽい画像が生成されている。

<img width="856" alt="SRGAN_img_002.png" src="https://qiita-image-store.s3.amazonaws.com/0/116706/a4af3121-fe96-58c4-3ef9-7b26d39ebf64.png">
[1] Figure 2より

# 目的関数
## Perceptual loss 

Perceptual loss はgeneratorを学習させる際のloss。まず loss 全体 $l^{SR}$ は

```math
l^{SR} = l_X^{SR} + 10^{-3} l_{Gen}^{SR}
```

右辺１項目が content loss 、２項目が adversarial loss。

## content loss 
この論文の最大の特徴はこの content loss。

これは学習済みのVGGNetに目標値となる高解像度画像 $I^{HR}$ 、及びgeneratorで生成された超解像度画像 $I^{LR}$ を入れ、j 番目のpoolingの前のi番目convolutionの後の特徴量 $\phi_{i,j}$ 同士でMSEを計算する。

```math
l^{SR}_{VGG/i,j} = \frac{1}{W_{i,j}H_{i,j}}\sum^{W_{i,j}}_{x=1}\sum^{H_{i,j}}_{y=1}(\phi_{i,j}(I^{HR})_{x,y} - \phi_{i,j}(G_{\theta_G}( I^{LR}))_{x,y})^2
```
 
単に $I^{HR}$ 、と $I^{LR}$ とからMSEをとると、平均的に両者が近い、ぼやけた画像となるが、特徴量同士で比較することでより鮮明で多様な画像を生み出すことが期待される。

以下の図の中央青枠が直接pixel wiseなMSEをとった場合。考えられうる多様な画像（赤枠）の平均的な画像が生成される。perceptual loss（黄色枠）ではより自然な画像に近いものが生成される。

<img width="420" alt="SRGAN_img_003.png" src="https://qiita-image-store.s3.amazonaws.com/0/116706/f02a170b-384d-838f-aafb-b583bc093f1d.png">



## adversarial loss  
adversarial な loss は通常のもの。

```math
l_X^{SR} = \sum^{N}_{n=1} - \log D_{\theta_D} (G \theta_G (I^{LR}))
```

# ネットワークのアーキテクチャ 
generatorとdiscriminatorのアーキテクチャは以下のresidual blockをベースとしたもの。

<img width="841" alt="SRGAN_img_004.png" src="https://qiita-image-store.s3.amazonaws.com/0/116706/862b6303-9a04-14ed-992b-15ff79924d05.png">

# 実験と結果 
## 使用したデータセット 
- Set5 
- Set14
- BSD100
- BSD300（テスト用）

## metrics 
- PSNR(dB) 
- SSIM （structural similarity）[2]
- MOS（Mean opinion score）

MOSは評価者に超解像された画像の質をスコアリングする手法。

MSEで学習するとPSNRとSSIMは上がるが、MOSは低いと思われる。一方でcontent loss（あるいはperceptual loss）で学習するとPSNRやSSIMは期待できないがMOSがよくなると期待される。

## SRResNetとの比較 
SRResNetとの比較は以下。

<img width="421" alt="SRGAN_img_005.png" src="https://qiita-image-store.s3.amazonaws.com/0/116706/ce18c0f0-3d95-8ced-e846-340204836087.png">

確かにSRRNetと比較した場合、SRGANはPSNRとSSIMは劣るが、MOSが高くなっている。

## 種々の手法とMOSで比較

SRResNet以外にSRCNNなど多くの手法とMOSを比較した結果は以下。

<img width="428" alt="SRGAN_img_006.png" src="https://qiita-image-store.s3.amazonaws.com/0/116706/d8232f64-9001-b044-7787-8a03c8d07940.png">

SRGANが一番いい。

## 種々の手法とPSNR、SSIM、MOSで比較

種々の手法と３つのメトリクスで比較した結果は以下。

<img width="849" alt="SRGAN_img_008.png" src="https://qiita-image-store.s3.amazonaws.com/0/116706/f65ed589-1ddb-2aae-334f-7e10be6da225.png">



# reference 
[2] Image Quality Assessment: From Error Visibility to Structural Similarity
play-redisから`PeerClosed`のログが出る理由

# 問題

`redis.actors.RedisClientActor - ConnectionClosed PeerClosed`のWarningログが各APIのCloudWatchに出続ける（出現間隔は1分に1回）

# 原因

redisにtimeoutが設定されているため、timeout時間内にredisに対してread/writeの操作がなければ、redisへのコネクションを切る
そのため、各APIでredisへのread/writeが頻繁に起こらない状態だと、redis側からコネクションが切られ、play-redis(scala)から`PeerClosed`のログが発生する。

# 対策

redisのtimeout値を長く取るか、定期的にreadの処理を走らせるという対策が考えられる
ただし、PeerClosedのログは本番環境など、頻繁にredisへの処理が走る環境では発生しない
redisにはtimeoutの他にも、出力バッファなど上限を超えるとコネクションを切るようなパラメータも設定されているため、注意が必要

# `PeerClosed`のログの意味

- https://doc.akka.io/docs/akka/2.5/io-tcp.html#closing-connections

> PeerClosed will be sent to the listener if the connection has been closed by the remote endpoint. 
> Per default, the connection will then automatically be closed from this endpoint as well. 
> To support half-closed connections set the keepOpenOnPeerClosed member of the Register message to true in which case the connection stays open until it receives one of the above close commands.

要約： コネクションがリモートのエンドポイントから切断されている

# `redis.actors.RedisClientActor - ConnectionClosed`のログの調査
`ConnectionClosed`は以下のrediscalaから出ているログ

- https://github.com/etaty/rediscala/blob/master/src/main/scala/redis/actors/RedisWorkerIO.scala#L107

play-redisではrediscalaを使っている

- https://github.com/KarelCemus/play-redis/blob/af4e8ed7bd3ff23d5d3a4f0a3ff946895f5af21b/build.sbt#L28

# ElastiCache(AWS)のRedisの設定
redisに`timeout`のパラメータが設定されており、値が`60`(デフォルト値)に設定されていた
そのため、read/writeの処理がtimeout時間中にリクエストされければ、コネクションは切断される

redisの固有パラメータ

- https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/ParameterGroups.Redis.html

redisの`timeout`パラメータ

- https://redis.io/topics/clients

## timeoutの詳細
timeoutは`60`に設定してるため`ノードがアイドル状態のクライアントを切断するまでに待機する秒数。`となる

- https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/ParameterGroups.Redis.html


> ノードがタイムアウトまで待機する秒数。値は次のとおりです。
> 0 – アイドル状態のクライアントを切断しません。
> 1-19 – 無効な値です。
> `>=20 – ノードがアイドル状態のクライアントを切断するまでに待機する秒数。

アイドル状態とは`idle (not requested by read or write operations)`らしい
つまり、readとwriteのリクエストがない状態のことを言うらしい

- https://redis.io/commands/object

> OBJECT IDLETIME <key> returns the number of seconds since the object stored at the specified key is idle (not requested by read or write operations).
初めてのLinux環境構築(proxy環境下)

## はじめに

### 本記事の対象者
- Linux環境でこれからC,C++でのプログラミングを始める人
- 社内、学内プロキシサーバの設定が必要な人

###投稿者の環境
`ubuntu 18.04 LTS`

## aptのプロキシ設定

### aptの設定ファイル作成
```bash
$ cd /etc/apt
$ sudo touch apt.conf
```
- `cd`はディレクトリの移動。
- `touch`はファイルのタイムスタンプ更新。指定したファイルが無い場合は新たに作成。

### プロキシ設定書き込み
```bash
$ echo 'Acquire::http::proxy "http://your.proxy.address:8080/";' | sudo tee -a apt.conf
$ echo 'Acquire::https::proxy "http://your.proxy.address:8080/";' | sudo tee -a apt.conf
```
- `echo`の入力値をパイプで`tee`に渡すことでapt.confにプロキシ設定を書き込む。
- ダブルクォートの中身は実際のプロキシに読み替えること。

`vi`で編集したい人は以下のコマンドでapt.confを開く

```bash
$ sudo vi apt.conf
```
- `sudo`が無いと書き込みできない。

## C,C++環境インストール
```bash
$ sudo apt update
$ sudo apt install build-essential
```
パッケージのインストール前に、aptのリポジトリを更新する必要がある。

## エディタ、ターミナル、シェルはお好みのものでどうぞ
```bash
$ sudo apt install emacs terminator zsh
```

## その他あると便利なツール
```bash
$ sudo apt install tmux
```
## 追記
2018/9/6 プロキシ設定書き込み修正。`sudo echo`ではroot権限でのファイル書き込みはできませんでした。
参考: https://qiita.com/nobu666/items/891705a4d34c91232ec1
log4j2でログファイルの権限設定

log4j2で出力されるログファイル、デフォルトだと所有者にだけ書き込み権限がついていた。別ユーザでファイルを触る必要があり、グループにも権限が欲しい。
やれやれ。僕は検索した。

[**Log4j 2 Appenders**](https://logging.apache.org/log4j/2.x/manual/appenders.html)

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace" name="MyApp" packages="">
  <Properties>
    <Property name="baseDir">logs</Property>
  </Properties>
  <Appenders>
    <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
          		 filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyyMMdd}.log.gz"
                 filePermissions="rw-------">
      <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
      <CronTriggeringPolicy schedule="0 0 0 * * ?"/>
      <DefaultRolloverStrategy stopCustomActionsOnError="true">
        <PosixViewAttribute basePath="${baseDir}/$${date:yyyy-MM}" filePermissions="r--r--r--">
        	<IfFileName glob="*.gz" />
        </PosixViewAttribute>
      </DefaultRolloverStrategy>
    </RollingFile>
  </Appenders>
 
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
 
</Configuration>
```

これによるとRollingFileの属性として`filePermissions`を書いてあげればいいらしい。

[**File permissions log4j2**](https://stackoverflow.com/questions/49810431/file-permissions-log4j2)

↑によると、どうも2.9.0以降の機能とのこと
残念ながら2.7.0を使っていたのでgradleで最新版を落とした

```gradle
ext {
    log4jVersion = '2.11.1'
}
dependencies {
    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: "${log4jVersion}"
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: "${log4jVersion}"
}
```

使っていたlog4j2.xmlの定義に合わせるとこんな感じ

```xml
<RollingFile name="logfile"
             append="true"
             fileName="path/to/log" 
             filePermissions="rw-rw-r--">
  <PatternLayout pattern="${pattern.of.log}"/>
  <Policies>
    <TimeBasedTriggeringPolicy />
  </Policies>
</RollingFile>
```

これでよし。次にxmlが読み込まれるタイミングで対象のファイル権限が変更された。
当然といえば当然だけど、既にローテートされた過去のファイルに関しては権限はそのままだった。
scala, sbtでのkamon-cloudwatchの使い方

kamon-cloudwatch

- https://github.com/timeoutdigital/kamon-cloudwatch

build.sbtに以下を追加

```
libraryDependencies += "com.timeout" %% "kamon-cloudwatch" % "0.0.1"
```

application.confに以下を追加

```
kamon {
  metric {
    # 秒間60でメトリクスを取得
    # これを追加しないとCloudWatchの料金が大変なことになる
    tick-interval = 60 second
  }
  cloudwatch {
    # カスタムメトリクスで表示する名前
    namespace = kamon-`<アプリ名>`
    # Cloudwatchのリージョン
    region = eu-west-1
    # Cloudwatchに一度に送るデータ数？
    batch-size = 20
    # falseだったらCloudwatchにメトリクスを送らない？
    send-metrics = true
    # スレッドプール数
    async-threads = 5

    # 取得するメトリクスを指定
    subscriptions {
      histogram         = []
      min-max-counter   = []
      gauge             = []
      counter           = []
      trace             = []
      trace-segment     = []
      akka-actor        = []
      akka-dispatcher   = []
      akka-router       = []
      # ヒープのメトリクスだけならこれでOK
      system-metric     = [ "jmx-memory" ]
      http-server       = []
      akka-http-server  = []
    }
  }
}
```

## kamonを必要としないアプリの設定

application.confに以下を追加

```
play.modules.disabled += "kamon.play.di.GuiceModule"
```

## AWSでの設定
カスタムメトリクスをPutする権限をIAMポリシーに追加

- https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/iam-identity-based-access-control-cw.html

```
{
  "Version": "2012-10-17",
  "Statement":[{
      "Effect":"Allow",
      "Action":["cloudwatch:PutMetricData"],
      "Resource":"*"
    }]
}
```

Cloudwatch -> カスタムメトリクスで確認

- kamon-`<アプリ名>`があればOK
RDSのパラメータグループをぶっこ抜くコマンド

```
PramaterGroup=hogehoge
aws rds \
 describe-db-parameters \
 --db-parameter-group-name ${PramaterGroup} \
 | jq -r '.Parameters[] | "\(.ParameterName), \(.ParameterValue), \(.AllowedValues), \(.IsModifiable), \(.Source), \(.ApplyType), \(.DataType), \(.Description)"' \
 > rds_parameters.csv
```

# ヘッダ
名前, 値, 許可された値, 変更可能, 送信元, 適用タイプ, データ型, 説明
Dockerコンテナからheapdumpを取得する方法

DockerでJavaアプリケーションを動かしたとき、メモリリークしてアプリが落ちる場合があります。
そのときにjavaが使っていたヒープをダンプして、解析できるようにします。

## DockerfileでJAVA_OPTSにヒープダンプのオプションを設定

```
ENV JAVA_OPTS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/dump.hprof"
```

## Docker cpでヒープダンプを取得

```
docker ps -aq | xargs -I{} docker cp {}:/tmp/dump.hprof /tmp/{}_dump.hprof
```

## ヒープダンプを解析
解析にはMATかjhatを使用する

memory analyzer (MAT)

- http://www.eclipse.org/mat/

jhat

- https://docs.oracle.com/javase/jp/6/technotes/tools/share/jhat.html

## 参考URL
- http://krdlab.hatenablog.com/entry/20110109/1294509590
- https://qiita.com/i_matsui/items/0d1ae2c7e9d17b6c04e0
Incoming webhookを使ってCircleCIのSlackへの通知をJob別に分ける

CircleCI2.0では、Slackへの通知はWorkflow別に設定できるが、Job別には設定できない
※ CircleCIはGithubと連携していることを前提にしています。

## incoming-webhookを使ってJobの正常終了を通知
### Slackでincoming wobhookを設定
すごくわかりやすいのでこちらを参考にしてください
- https://qiita.com/fushikky/items/c7bd05f897eab58ea7e4

### Githubのブランチ直下に`incoming-webhook.sh`を作成
```
例）
#!/bin/bash

COMMIT_MESSAGE=$(git log --format=%B -n 1 ${CIRCLE_SHA1})
HOOK_URL="<incoming webhookのHook URL>"

if [ ${CIRCLE_JOB} = '<CircleCIのジョブ名>' ];then
  curl -X POST --data-urlencode \
    'payload={
      "channel": "<slackのチャンネル名>",
      "username": "<slack通知で使うユーザ名>",
      "attachments": [
        {
          "color": "#36a64f",
          "text": "Success:  '${CIRCLE_USERNAME}' '${CIRCLE_JOB}' (#<'${CIRCLE_BUILD_URL}'|'${CIRCLE_BUILD_NUM}'>) in (<'${CIRCLE_COMPARE_URL}'|'${CIRCLE_BRANCH}'>)\n - '"${COMMIT_MESSAGE}"' "
        }
      ],
      "icon_emoji": "<slackのアイコン名>"
    }' \
  ${HOOK_URL}
fi
```

### 権限を設定
- `chmod a+x ./incoming-webhook.sh`

### 通知したいJobの最後に以下を追加
- `- run: ./incoming-webhook.sh`

### Jobが失敗した場合は、今まで通りすべてを通知する
- `https://circleci.com/gh/<ユーザ名もしくは組織名>/<ブランチ名>/edit#hooks`で設定
    - `Slack` -> `Fixed/Failed Only` をチェック
    - `Webhook URL`にSlackで設定したHook URLを設定
Firebase Analytics BigQuery standardSQLで直近90日のデータを指定する

# 動作環境

- FirebaseとBigQueryを統合し、FirebaseAnalyticsのデータをBigQueryにインポートしている環境です。
- `standardSQL` を使用します

# クエリ

```sql
#standardSQL
SELECT event_date
FROM `testapp.analytics_0123456789.events_*`
WHERE _TABLE_SUFFIX > FORMAT_DATE("%Y%m%d", DATE_SUB(CURRENT_DATE('Asia/Tokyo'), INTERVAL 90 DAY))
```

# 説明

- `testapp` と `0123456789` の部分はアプリごとに適当な値を設定してください
- BigQueryでは `testapp:analytics_0123456789.events_20180906` となっていますが、 `:` は `.` に置換する必要があります

# 参考にしたページ
- [Qiita: BigQueryの日付テーブルにおける、日付指定リファレンス](https://qiita.com/Bacchus/items/e3a5250dfeae2e65520d)
- [Google Cloud: https://cloud.google.com/bigquery/docs/wildcard-tables](https://cloud.google.com/bigquery/docs/wildcard-tables)
[Jest] Promiseの中でthrowされたエラーをテストする方法

# はじめに

[Jest](https://jestjs.io/)でエラー処理をテストするときによくやるやつ。
Promise中にエラーを投げる例外処理があるとして、それをテストするやり方。
いつもうろ覚え状態なので書いておく。

# やり方

ここに載ってる。
https://jestjs.io/docs/en/tutorial-async#rejects

こんなPromiseの処理があるとして、

```PromiseFunc.ts
export default class PromiseFunc {
  constructor() {}
  public async helloAsync(name) {
    if(!name) throw new Error('name is empty');
    return new Promise((resolve) => {
      resolve('Hello ' + name);
    });
  }
}
```

こんな風に使ってるとする。

```Hello.ts
import promiseFunc from './PromiseFunc';

const main = async () => {
  try {
    const func = new promiseFunc();
    const res = await func.helloAsync('bathtimefish');
    console.log(res);
  } catch(e) {
    console.error(e);
  }
};

main();
```

`PromiseFunc.test.ts`のテストはこんな感じ。

```PromiseFunc.test.ts
import promiseFunc from '../PromiseFunc';

describe('PromiseFunc', () {

  it('should get greeting', async () => {
    const func = new promiseFunc();
    const res = await func.helloAsync('bathtimefish');
    expect(res).toBe('Hello bathtimefish');
    // await (expect(func.helloAsync('bathtimefish'))).resolves.toEqual('Hello bathtimefish');
  });

  it('should throw error because of name is empty', async () => {
    const func = new promiseFunc();
    await expect(func.helloAsync(null)).rejects.toEqual(new Error('name is empty'));
  });

});
```

[rejects](https://doc.ebichu.cc/jest/docs/ja/tutorial-async.html#rejects) 便利。正常系のテストも上記でコメントしてるように[resolve](https://doc.ebichu.cc/jest/docs/ja/tutorial-async.html#resolves)を使う手があるんだけど、個人的には`toBe`のほうが平滑な感じがして好き。
Amazon Linux 2 LTSにCloudWatch Logsをインストール・設定する



### IAMポリシー作成
``` json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:DescribeLogStreams"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:logs:*:*:*"
        }
    ]
}
```

### IAMロール作成
作成したIAMポリシーをIAMロールに紐付ける

### IAMロール割り当て
作成したIAMロールをwebサーバに割り当てる


### CloudWatch Logsインストール

``` sh
sudo su -
yum update -y
yum install -y awslogs

# 東京regionを設定
cp -ip /etc/awslogs/awscli.conf /etc/awslogs/awscli.conf.org
diff /etc/awslogs/awscli.conf.org /etc/awslogs/awscli.conf
# 差分の無いことを確認

vi /etc/awslogs/awscli.conf
# =====vi ここから=====
region = ap-northeast-1
# =====vi ここまで====

diff /etc/awslogs/awscli.conf.org /etc/awslogs/awscli.conf
# 編集した差分を確認

# 取得したいログファイルを設定
cp -ip /etc/awslogs/awslogs.conf /etc/awslogs/awslogs.conf.org
diff /etc/awslogs/awslogs.conf.org /etc/awslogs/awslogs.conf
vi /etc/awslogs/awslogs.conf
# =====vi ここから=====
[general]
state_file = /var/awslogs/state/agent-state

[MessagesLog]
file = /var/log/messages
log_group_name = MessagesLog
log_stream_name = {instance_id}
datetime_format = %b %d %H:%M:%S

[SecureLog]
file = /var/log/secure
log_group_name = SecureLog
log_stream_name = {instance_id}
datetime_format = %b %d %H:%M:%S
# =====vi ここまで====

diff /etc/awslogs/awslogs.conf.org /etc/awslogs/awslogs.conf
# 編集した差分を確認

mkdir -p /var/awslogs/state/
ls -ld /var/awslogs/state/
# ディレクトリが存在することを確認

# サービス起動
systemctl status awslogsd.service
systemctl start awslogsd.service
systemctl status awslogsd.service
# 起動していることを確認

# サービスの自動起動有効化
systemctl is-enabled awslogsd.service
systemctl enable awslogsd.service
systemctl is-enabled awslogsd.service
# enableであることを確認
```

### 確認
「AWSコンソソールのサービス＞CloudWatch＞ログ」に
ロググループ「MessagesLog」と「SecureLog」が作成されていれば成功です

### 参考記事
https://www.yamamanx.com/aws-cloudwatch-logs-ec2-nginx/
https://dev.classmethod.jp/cloud/aws/awslogs-amazonlinux2/
Rspec

# rspec

## やってみて大変だった事

・モデルの理解（importだったから）
・期待値の設定
・取り込むデータの設定
・評価の方法
　→結果の生成　count　
　→結果としてよく使われる：sucesscount の数　表示メッセージの一致
　　　　Lsuccesscountは、ソース状にかく（この時はrake task）
CircleCIで重複したWorkflow(Job)を止める

# CircleCIで重複したWorkflow(Job)を止める

- 問題
CircleCIではGitのリポジトリに変更があるたびにWorkflowが実行される
場合によっては、変更が同時にマージされ複数のWorkflowが走ることがある

- やりたいこと
実行中のWorkflowのうち、リポジトリが同じものは止めたい

## CircleCIのAPIを使ってWorkflowを止める
CircleCIのAPIを叩くだけですが、今回はnodejsを使います
(シェルスクリプトでもできますが、ブランチ名がチェインケースやスネークケースの場合は`jq`が使えないので・・)

APIトークンについては以下を参照してください
- https://qiita.com/f-naoto832/items/89730cb5e3bfcbd34bd2

リポジトリの直下に以下を作成

```cancelCircleCI.js
var request = require('request');
const CIRCLE_API_HOST = "https://circleci.com/api/v1.1/project/github"
const CIRCLE_USERNAME = process.env.CIRCLE_PROJECT_USERNAME
const CIRCLE_REPONAME = process.env.CIRCLE_PROJECT_REPONAME
const CIRCLE_TOKEN = '?circle-token=' + '<CircleCIのAPIトークン>'
const CIRCLE_BRANCH = process.env.CIRCLE_BRANCH
const CIRCLE_BUILD_NUM = process.env.CIRCLE_BUILD_NUM
const BASE_URL = CIRCLE_API_HOST + '/' + CIRCLE_USERNAME + '/' + CIRCLE_REPONAME
const GET_JOB_API_URL = BASE_URL + CIRCLE_TOKEN

// 直近30個のJobのうち、実行中のJobだけをとってくる
function get_build_num(base_url, api_url, circleci_branch, circleci_build_num, token){
	var options = {
		url: api_url,
		method: 'GET',
		json: true
	}
	var build_nums = []

	request(options, function (error, response, body) {
		body.forEach(function(body){
			if (body.build_num < circleci_build_num && body.status == "running" && body.branch == circleci_branch) {
				build_nums.push(body.build_num)
			}
		})
        // 実行中のJobをキャンセル
		cacnel_running_job(build_nums, base_url, token)
	})
}

// 実行中のJobをキャンセル
function cacnel_running_job(build_nums, base_url, token){
	build_nums.forEach(function(build_num){
		var options = {
			url: base_url + '/' + build_num + '/cancel' + token,
			method: 'POST',
			json: true
		}

		request(options, build_num, function (error, response, body) {
			console.log('[INFO] Cancel job => ' + body.build_url)
		})
	})
}

get_build_num(BASE_URL, GET_JOB_API_URL, CIRCLE_BRANCH, CIRCLE_BUILD_NUM, CIRCLE_TOKEN)
```

config.ymlで呼び出し

```
- run: npm install request && node cancelCircleCI.js
```

## CircleCIで使える環境変数
1.0と2.0の対応表もあるのですごくわかりやすい
- https://qiita.com/jkkitakita/items/4554a965e86d376e3ecd
CircleCIで、直前に実行したJobによって次のJobで実行する処理を変える

## gitのリポジトリ直下に適当なディレクトリとファイルを追加する
異なるJob間で共有するディレクトリを作成

- `mkdir circleci`

共有するファイルを作成

- `touch circleci/environment`

## 直前に実行するJobの変数を格納
変数を`environment`に格納後に`persist_to_workspace`を使って、異なるJob間で変更したファイルを共有

```.circleci/config

    - run:
        name: Update Environment
        command: |
            cat <<'EOF' | tee -a ./circleci/environment
                export PATH=~/.local/bin:$PATH
                export ENV='staging'
                export REGION='eu-west-1'
            EOF
    - persist_to_workspace:
        root: circleci
        paths:
            - "./*"
```

### 次のJobで変数を読み込み
直前に`persist_to_workspace`で保存したディレクトリを`attach_workspace`でアタッチする

```.circleci/config
    - attach_workspace:
        at: circleci
    - run:
        name: Setting environment
        command: |
          source ./circleci/environment
```
CircleCIでDockerコマンドを使う

dockerやdocker-composeを使用する場合はmachineを使えばOKです。

machine
- https://circleci.com/docs/2.0/executor-types/#using-machine

docker_layer_cachingを使えば、docker buildを早くできるそうです（有料）
- https://circleci.com/docs/2.0/docker-layer-caching/#configyml

machineのコンテナに何が入っているのかは以下を参考にしてください
- https://qiita.com/f-naoto832/items/6e9522a70ba1334f5bc5
XMLHttpRequestでCORSエラーとネットワークエラーを区別する方法は存在しない

XMLHttpRequestでリクエストを発行してエラーになったとき、

1. CORSエラー（`Access-Control-Allow-Origin` ヘッダが存在しないなど）
2. ネットワークエラー（TCPコネクションを確立できないなど）

上記のどちらが原因なのかをプログラム的に判定する方法は存在しない。

- どちらも `xhr.readyState==4` かつ `xhr.status==0` になる
- CORSの仕様的に、どちらも同じふるまいをするように規定されているらしい
- Chrome Devtoolsのコンソールには `No 'Access-Control-Allow-Origin' header is present on the requested resource. ` というエラーが表示されるんだけど、この文言をプログラム的に取得する方法はない

参考：
[ajax - How to Detect Cross Origin (CORS) Error vs. Other Types of Errors for XMLHttpRequest() in Javascript - Stack Overflow](https://stackoverflow.com/questions/19325314/how-to-detect-cross-origin-cors-error-vs-other-types-of-errors-for-xmlhttpreq)
CircleCIで使われているコンテナの中身

CircleCIではDockerHubにあるコンテナは使用可能
ただし、CircleCIでmachineなどのオプションを使っているとその中身を知りたいときがある
machineでは`circleci/classic`を使っているらしいがDockerhubを探しても見つからない

machine
- https://circleci.com/docs/2.0/executor-types/#using-machine

## プロビジョニング用のスクリプト
CircleCIではスクリプトを使ってコンテナ別にパッケージをインストール

- https://github.com/circleci/image-builder/tree/master/circleci-provision-scripts

例えばPythonではpyenvを使っている

- https://github.com/circleci/image-builder/blob/master/circleci-provision-scripts/python.sh

## machineで使われているスクリプト
以下のURLの先の`See the picard-vm-image branch of our image-builder repository for details.`がそれに当たるらしい
- https://circleci.com/docs/2.0/vm-service/#configuration

picard-vm-imageのブランチ
- https://github.com/circleci/image-builder/tree/picard-vm-image/circleci-provision-scripts

ちなみに、`an Ubuntu 14.04 image with Docker version 17.03.0-ce and docker-compose version 1.9.0`らしいので
Ubuntu 14.04のDockerfileも見てみると`RUN sudo -H -i -u ubuntu pyenv global 2.7.11`となっている・・・
もし、3系を使いたい場合はDockerコンテナ内で `pyenv global 3.X.XX` とすればOK

- https://github.com/circleci/image-builder/blob/picard-vm-image/targets/ubuntu-14.04-enterprise/Dockerfile
CircleCIで提供しているAPIのTIPS

## APIの使い方
### 「`GET: /me`」の例
```
例）
TOKEN="12345abcd・・・・"
curl -s -u ${TOKEN}: https://circleci.com/api/v1.1/me
# もしくは
curl https://circleci.com/api/v1.1/me?circle-token=${TOKEN}
```

#### 参考URL
- https://qiita.com/yukimura1227/items/0478230c388cc8735b20

#### 説明
- トークン(TOKEN)の作成方法
    - `https://circleci.com/account/api`で作成
- プロジェクト(ブランチ)別にトークンを分ける方法
    - `https://circleci.com/gh/<CircleCIのユーザ名もしくは組織名>/<ブランチ名>/edit#api`で作成
- CircleCIのAPIのendpointsは、全て`https://circleci.com/api/v1.1/`で始まる
- curlのオプション
    - `-s, --silent`
        - サイレントモード、エラーメッセージなどが出ない
    - `-u, --user <user:password>`
        - 認証のためのユーザ名とパスワード用のオプション、今回はトークンのみ指定
- `/me`のURIを叩くと`{ "message" : "You must log in first." }`のエラーが出る場合は、ブラウザで確認してみる
    - ブラウザでの確認方法：ブラウザでCircleCIにログインした状態で、別タブに`https://circleci.com/api/v1.1/me`を入力
    - なぜAPIが叩けないのかを調査する場合は`curl -v`のオプションを付ける
        - 認証が通っていないときは`401 Unauthorized`が出る、その場合はトークンがうまく作れていない場合が多い

### 「`GET: /project/:vcs-type/:username/:project`」の例
```
例）
TOKEN="12345abcd・・・・"
# guthubと連携している場合
curl -s -u ${TOKEN}: https://circleci.com/api/v1.1/project/github/<CircleCIのユーザ名もしくは組織名>/<ブランチ名>
# もしくは
curl https://circleci.com/api/v1.1/project/github/<CircleCIのユーザ名もしくは組織名>/<ブランチ名>?circle-token=${TOKEN}
```
2018-09-05
## APIの一覧 (2018-09-05現在)
https://circleci.com/docs/api/v1-reference/#summary
たくさんのGameObjectを簡単にナンバリングするツールをつくった

# こんなことがしたい

ゲームオブジェクトを作ってコピーしたけど、ちょっと名前のフォーマットが揃ってなくて気持ち悪い.

<img width="274" alt="plan.png" src="https://qiita-image-store.s3.amazonaws.com/0/15000/6b2d90d3-dfa2-31a4-5f1c-afa03eed867c.png">

また編集していって、途中にGameObjectを追加した時など、ひとつひとつにナンバリングするのは面倒だ.

<img width="285" alt="inserted.png" src="https://qiita-image-store.s3.amazonaws.com/0/15000/d6d7922c-a3eb-43c0-2715-12f4c3289bde.png">

こうゆうGameObjectの名前が乱雑になっている状況で一瞬で名前をナンバリングしたい

## つくった

それを簡単にできるツールをつくった

- [github.com/mattak/NumberingEditor](https://github.com/mattak/NumberingEditor)

動作

![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/15000/b34250b6-f0bc-d34a-b490-3d052a36b9c9.gif)

こんな感じで、選択したobjectを簡単にナンバリングできる。
ナンバリングのフォーマットも変えられるので、3桁の0詰め数字にするとかもサクッとできる.

ついでにソート機能もつけた

![demo-sort.gif](https://qiita-image-store.s3.amazonaws.com/0/15000/d0ea1f23-ece7-49d5-4f5b-5c5e6c8b9bdb.gif)

## Install

[github.com/mattak/NumberingEditor/releases](https://github.com/mattak/NumberingEditor/releases) から .unitypacakgeを落としてインストール.

もしくは、umm経由でもinstallできる

```
$ yarn add "mattak/NumberingEditor#^1.0.0"
```

## Usage

Window > Numbering で開く

![open.gif](https://qiita-image-store.s3.amazonaws.com/0/15000/da5f15c3-94ab-30f7-3e48-cbaf425b081f.gif)

あとは好きに編集するだけ!

![rename.gif](https://qiita-image-store.s3.amazonaws.com/0/15000/4cef43e8-a99a-307c-23c6-a7acb571c53b.gif)


## Setting

Basename Regex
- ナンバリングするときの規定になる文字を正規表現の `Group[1]` で指定する
- Basenameは選択した１つめのオブジェクト名から得る
- 例: `GameObject 001`, `^(\S+)` => `GameObject` がBasenameになる

Replace Format
- ナンバリングするときのフォーマット
- `string.Format` が各Object名に適用される
- `{0}` : Basenameが挿入される
- `{1}` : ナンバリングの数字が挿入される. `{1:D3}` なら3桁数字 (`001` など)

Ordering Offset
- ナンバリングが開始するときのOffset

## github

よかったらスターください! 💫

- [github.com/mattak/NumberingEditor](https://github.com/mattak/NumberingEditor)
ORACLE ODBCドライバをインストールしようとしてodbc_installを実行たらOracle ODBC Driver with same name already exists.となった時の対応方法

# 事象

```sh
$ odbc_install JA
Oracle ODBC Driver with same name already exists.
```

# 原因：権限がないから
本当に既にインストールされている場合もあります。

## 対応：管理者権限でプロンプトを起動する

```sh
$ odbc_install JA
Oracle ODBC Driver is installed successfully.
```
Vim初心者が感じた、Vimの不満点を改善してみた

# AtomからVimへ
今までテキストエディタはAtomを使用していたのですが、[こういった記事](https://qiita.com/nnishimura/items/e3c9af1f47a9e41e0171)を見てからAtomを使うのが億劫になってしまいました。
なので、最近はVimを使うようにしています。
Qiitaの記事を見ながら色々とプラグインを入れたりしていたのですが、操作に不満を覚えることがあったので、今回はVim初心者の私が改善した点を投稿します。

# 行頭・行末の移動とコマンドモードに戻るキー入力、打ちにくくないですか？
Vimはデフォルトでは、

| Key |　結果　|
|:-----:|:--:|
|　0　|　行頭に移動　|
|　^　|　行頭に移動　|
|　$　|　行末に移動　|
|　Esc　|　コマンドモードに戻る　|
|　ctl + [　|　コマンドモードに戻る　|
となっています。
しかし、どれもホームポジションから少々離れているので、これを改善しようと思います。
私のタイピングスキルが低いだけですかね？笑
でも、少なくとも`$`とかは誰でも打ちにくいと思います……！

# .vimrcの編集
こういったVimのコマンドを編集するのは`.vimrc`ファイルを用います。
デフォルトでは無いので、自分で作ります。
そうしたら、このファイルを開いて自分の好きなように編集出来ます。

```
~$ touch .vimrc
~$ vim .vimrc
```
私は以下のようにしました。

```
noremap <C-h> 0
noremap <C-l> $
inoremap <C-j> <Esc>
vnoremap <C-j> <Esc>
```
これらは何を意味しているのかというと、

| Key |　結果　|
|:-----:|:--:|
|　ctl + h　|　行頭に移動　|
|　ctl + l　|　行末に移動　|
|　ctl + j　|　コマンドモードに戻る　|
という風にVimのコマンドを編集したことになります。
詳しい編集方法などは、下記の「参考にしたサイト」から見てみてください。
上記のようにすると、ほぼホームポジションが崩れないので、初心者でも高速にVimを扱えるようになると思います。

こういうのを考えるようになると、他の人がどういう設定をしているのか気になってきます笑
もし上記の設定だとまずい場合があれば教えてください！

# 参考にしたサイト
http://vimblog.hatenablog.com/entry/vimrc_key_mapping
https://cocopon.me/blog/2013/10/vim-map-noremap/
Springのバリデーションの実装時の導入でのエラー

#springでのバリデーション実装エラー
## 環境
```xml:pom.xml
<properties>
	<!-- Generic properties -->
	<java.version>1.7</java.version>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

	<!-- Web -->
	<jsp.version>2.2</jsp.version>
	<jstl.version>1.2</jstl.version>
	<servlet.version>3.1.0</servlet.version>


	<!-- Spring -->
	<spring-framework.version>3.2.3.RELEASE</spring-framework.version>

	<!-- Hibernate / JPA -->
	<hibernate.version>4.2.1.Final</hibernate.version>

	<!-- Logging -->
	<logback.version>1.0.13</logback.version>
	<slf4j.version>1.7.5</slf4j.version>

	<!-- Test -->
	<junit.version>4.11</junit.version>
</properties>
```

##実装時でエラーが出るまでの手順
pom.xmlに2つのjarファイルを追加

```xml:pom.xml
<!-- validation-api(入力値検証で使用) -->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
<!-- Hibernate(入力値検証で使用) -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.0.1.Final</version>
</dependency>
```

##2つのエラーが出現

1, サーブレットがinit()エラー

```
HTTPステータス 500 - サーブレット dispatcherServlet のServlet.init()が例外を投げました
type 例外レポート
------------------------------------------------------------------------------------------

メッセージ サーブレット dispatcherServlet のServlet.init()が例外を投げました

説明 The server encountered an internal error that prevented it from fulfilling this request.

例外-------------------------------------------------------------------------------------------

javax.servlet.ServletException: サーブレット dispatcherServlet のServlet.init()が例外を投げました
	org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
	org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
	org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:436)
	org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
	org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
	org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
	java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	java.lang.Thread.run(Thread.java:745)

<!-- 以下省略 -->
```

2, @NotEmptyが使用できない

##エラーの解消

原因は追加したjarファイルのバージョンの関係
pom.xmlを変更し、再度プロジェクトの更新を行ったら２つとも解消

```xml:pom.xml
<!-- validation-api(入力値検証で使用) -->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>
<!-- Hibernate(入力値検証で使用) -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.3.4.Final</version>
</dependency>
``` 

##!!!エラーは消えたが、使用できない!!!

今回はバージョンの関係ということはわかったが、根本的な解決には至らなかったので、別の機会に再検討
Djangoでウェブアプリ - templateでif-then条件分岐

Djangoを使ってウェブアプリを作ります
templateでif-thenの条件分岐をしてみます

- このページで作成されたDjango環境は[ここ](https://github.com/eggplnt/northernlights32)からダウンロード可能です

#1. ファイルを用意します

- `penguin`フォルダの`urls.py`に以下を追加します

```python:penguin/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('exercise', views.exercise, name='exercise'),
    path('', views.index, name='index'),
]
```

- `penguin`フォルダの`views.py`に以下を記述します

```python:penguin/views.py
from django.shortcuts import render

def index(request):
    return render(request, 'index.html')

def exercise(request):

    p = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71 }

    return render(request, 'exercise.html', { 'prime': p } )
```

- `static`フォルダに下記のようなcssを用意します

```css:test.css
.a1 {
  background-color:  #98d98e;
  height: 120px;
  padding: 20px;
}
.b1 {
  background-color:  #e4de8a;
  padding-left: 20px;
  height: 120px;
  text-align:left;
  padding: 20px;
  font-size: 18pt
}
```

- `penguin`フォルダの`templates`サブフォルダに下記のようなhtmlを用意します

```html:penguin/templates/exercise.html
{% load static %}
<html>
<head>
</head>
<body>
  {% block extrahead %}
  <link href="{% static 'test.css' %}" rel="stylesheet">
  {% endblock %}

  <div class='a1'>
    <h1>テストページ</h1>
  </div>

  <div class='b1'>
    <p>
      <b>30以下の素数：</b><br>
      {% for p in prime %}
        {% if p <= 30 %}
          {{ p }}
        {% endif %}
      {% endfor %}
    </p>
  </div>

</body>
</html>
```

#2. 稼働を確認します
- `python manage.py runserver`を実行し、Djangoを起動します
- ブラウザで`localhost:8000/exercise`へアクセスし、views.pyからのデータが表示されていることを確認します

<img width="609" alt="スクリーンショット 2018-09-06 9.58.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/6b88072a-7063-0aac-d0ff-8bf08ebe9b15.png">
備忘録：Err.Raiseの動作検証

#作成理由
エラー番号毎の出力メッセージが知りたかった。

#コード

```vb
Sub ErrorRaisetest()
    On Error GoTo Err
    
    'エラーを発生させる
    '”アプリケーション定義またはオブジェクト定義のエラーです。”のエラーが発生する
    Err.Raise 1
    
    '"プロシージャの呼び出し、または引数が不正です。"のエラーが発生する
    Err.Raise 0
    
    '"プロシージャの呼び出し、または引数が不正です。"のエラーが発生する
    Err.Raise 5
        
    Exit Sub

'エラー処理
Err:
    Debug.Print Err.Number & vbCrLf & Err.Description
    Resume Next

End Sub
```

#参考文献
[Raise メソッド - MSDN - Microsoft](https://msdn.microsoft.com/ja-jp/vba/language-reference-vba/articles/raise-method)
Vue.js+TypeScriptのテストでRouterLinkがないって怒られたときの対応

## 概要

Vue.jsのRouterはmain.tsで読み込んでると、コンポーネントなどで```router-link``` を意識せずに利用できて便利なのですが、コンポーネントの単体テストを書いているとそんなコンポーネント知らない！と怒られるので対応します。


## 環境

Vue CLIを利用してプロジェクトを用意します。
開発環境やプロジェクト作成方法についてはこちらご参照ください。

DockerでVue.js+TypeScript開発環境を構築する
https://qiita.com/kai_kou/items/d581a9f8f3ee8605aed1

GitHubにも今回利用したソースをUPしていますので、よかったらどうぞ。
https://github.com/kai-kou/vue-js-typescript-import-router-link


## 再現

以下のようにコンポーネントを作成します。

```sh
> touch src/components/Hoge.vue
> vi src/components/Hoge.vue
```

```vue:src/components/Hoge.vue
<template>
  <router-link to="/">
    リンク！
  </router-link>
</template>

<script lang="ts">
  import {
    Component,
    Vue,
  } from 'vue-property-decorator';
  
  @Component
  export default class Hoge extends Vue {}
</script>

```

テストも用意します。

```sh
> touch tests/unit/Hoge.spec.ts
> vi touch tests/unit/Hoge.spec.ts
```

```ts:tests/unit/Hoge.spec.ts
import { expect } from 'chai';
import { shallowMount } from '@vue/test-utils';

import Hoge from '@/components/Hoge.vue';

describe('Hoge.vue', () => {
  it('RouteLinkが利用できるか', () => {
    const wrapper = shallowMount(Hoge, {});

    wrapper.is(Hoge);
    expect(wrapper.findAll('router_link')).to.length(1);
  });
});

```

テストを実行します。

```sh
> yarn test:unit

  Hoge.vue
[Vue warn]: Unknown custom element: <router-link> - did you register the component correctly? 
For recursive components, make sure to provide the "name" option.

found in

---> <Hoge> at src/components/Hoge.vue
       <Root>
    ✓ RouteLinkが利用できるか (69ms)

  1 passing (119ms)

 MOCHA  Tests completed successfully
```

はい。
テストはパスしますが、```[Vue warn]``` がでてしまって気持ち悪いです。
モヤモヤします。
なんとかしたいです。

router-linkが認識されるようにテストを変更します。

```ts:tests/unit/Hoge.spec.ts
import { expect } from 'chai';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Router from 'vue-router';

import Hoge from '@/components/Hoge.vue';
const localVue = createLocalVue();
localVue.use(Router);
const RouterLink = localVue.component('router-link');

describe('Hoge.vue', () => {
  it('RouteLinkが利用できるか', () => {
    const wrapper = shallowMount(Hoge, { localVue });

    wrapper.is(Hoge);
    expect(wrapper.findAll(RouterLink)).to.length(1);
  });
});

```

では、再度テストを実行してみます。

```sh
> yarn test:unit

 MOCHA  Testing...

  Hoge.vue
    ✓ RouteLinkが利用できるか (95ms)

  1 passing (264ms)

 MOCHA  Tests completed successfully
```

やったぜ。


## 参考

Expose RouterLink and RouterView components #1976
https://github.com/vuejs/vue-router/issues/1976

Vue.js+TypeScriptで開発するときの参考記事まとめ
https://qiita.com/kai_kou/items/19b494a41023d84bacc7
Linuxサーバー時刻を（現在時刻と）合わせる

初期設定だとLinuxサーバーの時刻設定がめちゃくちゃになっているので
正しい時間帯で使用する場合、自分で設定しないといけない

**※ 詳しいことはこちらの記事で**
[Linux/UNIXサーバは立てたらまず時刻同期の設定](https://qiita.com/yuba/items/66d2d45a61b28737c098)

# 現在の設定時刻を確認
```zsh:システムクロック
date
```
```zsh:ハードウェアクロック
hwclock -r
```
# 設定作業

## ntpサーバのインストール

```zsh:RHEL(CentOSとか)系
yum install ntp
```
```zsh:Debian系
apt-get install ntp
```

## 自動起動設定
```zsh
# centos6 & etc
chkconfig ntpd on

# centos7
systemctl enable ntpd
```

## ntpdの設定ファイルを編集
時刻の同期設定するサーバ（日本国内）を記述する

```zsh:/etc/ntp.conf
# 以下の各行を編集する

#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst

# ↓

server -4 ntp.nict.jp iburst
server -4 ntp1.jst.mfeed.ad.jp iburst
server -4 ntp2.jst.mfeed.ad.jp iburst
server -4 ntp3.jst.mfeed.ad.jp iburst

#  iburst は環境によっては記述しない
```
## システムクロックの時刻を合わせる

```zsh
ntpdate ntp.nict.jp
```

## ntpdサービスを起動

```zsh
# centos6 & etc
service ntpd start

# centos7
systemctl start ntpd.service
```
## ハードウェアクロックの時刻を設定
システムクロックの時刻に合わせる

```zsh
hwclock -w
```
## 設定された時刻を再確認

```zsh:システムクロック確認
date
```
```zsh:ハードウェアクロック確認
hwclock -r
```

# 同期状況の確認
ntpdの起動後に少し時間を置いてから以下のコマンドで同期状況を確認できる

```zsh
ntpq -p
```
```zsh:コマンド実行が早すぎた場合（まだ同期時刻取得中）
***Request timed out
```
```zsh:時刻同期の実行結果
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*ntp-a2.nict.go. .NICT.           1 u   30   64  377    4.766   15.553   7.141
+ntp1.jst.mfeed. 133.243.236.17   2 u   36   64  377    3.187   16.979   6.375
-ntp2.jst.mfeed. 133.243.236.17   2 u   37   64  377    3.226   11.573   5.880
+ntp3.jst.mfeed. 133.243.236.17   2 u   33   64  377    3.408    3.691  11.861
```
各サーバ名の左側の記号について

| 記号 | 意味 |
|:-:|:-:|
| ＊  | 同期中  |
| ＋  | 同期完了（参照可能なサーバー）  |


# ハードウェアクロックへ定期的に同期する設定
以下は任意で設定。

```zsh:/etc/crontab
#毎朝5時にソフトウェアクロックをハードウェアクロックに反映
0 5 * * 0 root /sbin/hwclock -w > /dev/null 2>&1
```


# 参考
>
[Linux/UNIXサーバは立てたらまず時刻同期の設定](https://qiita.com/yuba/items/66d2d45a61b28737c098)
[ntpq -pの見方 – 猫型iPS細胞研究所](http://ips.nekotype.com/1494/)