OmniAICreator/Qiita-1.07M huggingface dataset:
Optionalの正しい使い方

# Optional
java8で追加されたnullを処理するためのAPI。
適切に使えばnull制御のコードを綺麗に書ける。


# Optionalの推奨しないメソッド(書き方)

- isPresent()
- get()
- Optionalがクラス、インスタンスフィールドに使われている
- Optionalが引数に使われている


```java:IntelliJからの警告
/**
 * 'Optional<String>' used as type for field 'optional'
 Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter.
 Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result".
 Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not.
 */
private Optional<String> optional;
  
private static void test1(String str) {
    Optional optional = Optional.ofNullable(str);
    /**
     * Optional.get()' without 'isPresent()' check
     */
    optional.get();
}
  
private static void test1(Optional<String> optional ) {
    /**
     * Optional<String>' used as type for parameter 'optional'
     Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter.
     Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result".
     Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not.
     */
    optional.get();
}
```

# optionalの推奨するのメソッド
```java
public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
public T orElse(T other)
public T orElseGet(Supplier<? extends T> other)
public void ifPresent(Consumer<? super T> consumer)
public Optional<T> filter(Predicate<? super T> predicate)
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
```


# 例
```java
private static void test(String param) {
    Optional<String> optional = Optional.ofNullable(param);
    String value;
    
    // NG
    value = optional.isPresent() ? optional.get() : "null";
    // OK
    value = optional.orElse("null");
    
    // NG
    value = optional.isPresent() ? optional.get() : "null";
    // OK
    value = optional.orElseGet(() -> "null");

    // NG
    if (optional.isPresent()) {
        value = optional.get().toUpperCase();
    } else {
        value = "NULL";
    }
    // OK
    value = optional
        .map(String::toUpperCase)
        .orElse("NULL");
}
```
営業職からエンジニアになって営業ツールを作ってなかなか重宝されて嬉しかった話

# **はじめに**
こんにちは！
[リブセンスアドベントカレンダー](https://qiita.com/advent-calendar/2017/livesense-ji)21日目を担当しています、nori_saiです。
以前は同社で法人営業をし、エンジニアに転身して1年ちょっと経ったばかりの新参者でございます。

今日は"**自**"分メインで開発、そして今も保守運用をさせていただいている
愛娘の**シャロ子**ちゃん（通称）:baby_tone1:のお話をしたいと思います。

拙い文章ですが最後までお読みいただけますと、好きがこぼれ落ちます:information_desk_person_tone1::heartbeat:

# **シャロ子とはなんぞや**
さてさて。そもそもシャロ子ってなんなんだというお話なのですが、この子はいわゆる**SFA（営業支援システム）**となっています。
具体的には`新規の企業さんを獲得するために使う管理ツール`です。

まずは、そんなシャロ子に使われている言語について、ご紹介します。

# **使用言語**
シャロ子の周辺プロダクト（Batchなど）も含めて、以下の言語を用いて実装されています。

```rb
LANGUAGE_1     = 'Ruby'
FRAMEWORK_1    = 'Ruby on Rails'
LANGUAGE_2     = 'PHP'
FRAMEWORK_2    = 'FuelPHP'
```
技術選定などは上司が行ってくれたのですが、
今思うと初心者のうちから、多言語に触らせてくれるように選定してくれたのだととても感謝しています。
おかげで初心者ながら**複数の言語を扱うことへの心理的ハードル**が自然と下がっていた気がします。

# **開発にかんすること**
使用言語の次は、シャロ子の開発について触れていきたいと思います。

## **そもそもなぜシャロ子が開発されることになったのか**
実は、社内にはシャロ子の前身となるプロダクト（自社開発）がありました。（3年くらい使われていたサービスです）
ただし、そのプロダクトはMicrosoft Accessで作られていたり、たくさんの課題がありました。

```rb
'個人のPCごとにインストールが必要'
'大量のデータがありめちゃくちゃ重い'
'複雑で見づらい・使いづらいUI'
'運用方法の共有にコストがかかる'
```
要約するとこのような感じです。。。実際に営業する際に使っていた身としては本当に辛い部分でした。
新人研修とかは教える側もヒーヒー言いながら必死に教えていましたね:no_good_tone1:
そんな状況から脱し、生産性をあげて営業をする為に、**WEB化（シャロ子開発）** という判断になったわけです。

## **シャロ子の完成**
なんだかんだあって、シャロ子は完成しました！（**はしょりすぎ**
2016年8月から作り始めて、2017年1月に正式リリースという感じです。
長いのか短いのかは置いておいて、とりあえずはよく頑張ったと思います笑。

さて、実際に課題は解決されたのでしょうか！

## **実際に課題は解決されたのか**
結論から言うと、めちゃくちゃ改善されました:dancer_tone1:

* **WEB化で、インストールの必要なし！**
* **処理などを改善したので、重くない！**
* **INSPINIAという管理画面用テンプレートで見た目作ったので、見やすい使いやすい！**
* **リプレイス時に運用についても再設計し、共有のコスト大幅軽減！**

よし。今までの課題は程度改善できた。ということで
次はWEBだからこそできる機能とか追加して、もっと便利にしたい！というフェーズになりました。

## **楽しく営業してもらいたいという想い**
シャロ子は既存のSFAをリプレイスする名目で開発されたプロダクトです。
無事リプレイス自体は完了したのですが、

* WEBだからこそできる機能を織り込ませたい。
* どうせ使ってもらうなら、楽しく営業できるようにしたい

という思いで、こんなものを実装しました。
それは… **:love_letter: 新規獲得通知 :love_letter:** というものです。

どんな機能かというと、**外部のchatサービスのAPIを利用し、新規の企業を獲得した通知を出す！**というものになります。
一見ただの通知機能に見えるのですが、これがあるのとないのとでは営業さんのモチベーションがだいぶ変わるようでして…:information_desk_person_tone1::sparkles:

実際の通知のスクショをご覧ください！

<img width="421" alt="スクリーンショット 2017-12-01 13.22.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/146581/aad99a6a-97ad-f0e5-08e4-46495d51fd92.png">

なんということでしょう！w 誰かが獲得する度にこんな感じで盛り上がりますw
思ったよりも反響があって**「これ見たいので頑張って獲得してるんです:dancer_tone1:」**みたいな声も現場からもらえたり泣
モチベーションの向上と、楽しく営業する。ということの手助けになっているのではと感じています。とても実装してよかったと思える機能です。

**ユーザに使ってもらえるサービスになるための開発**。大事ですよね。

他にもWEBならではの機能だったりはあるのですが、長くなるので今日はこの機能に絞りたいと思います:information_desk_person_tone1:

# **まとめたい:information_desk_person_tone1:**
シャロ子のお話。いかがでしたでしょうか。

拙い文章 & 特に技術的なお話ではないかもしれませんが
エンジニア初心者の私が**必死に**開発したプロダクトのお話でした！
今は別のプロダクトも開発してますが、引き続き初心を忘れず開発していく所存です。

よし。年明けてからも頑張るぞ〜〜〜〜:angel_tone1:

# **明日は12/22日（金）**
我が社では、年内最後の金曜日です！
@taku_shibuyaさん。よろしくお願いします:baby_tone1:
UIPanGestureRecognizerの練習でなぜかドラッグできなかった

http://hajihaji-lemon.com/smartphone/swift/uipangesturerecognizer/
上のサイトを参考にしながら、自分の気に入ったimageを指でドラッグできるように練習していた。

指示されたとおりやったつもりで、コードも写した。

エラーも出ず動かしてみたら、ドラッグしても動かない。


もっかい初めからどこが間違っていたか確認するとimageviewのアトリビュートインスペクターのところのInteractionのUser Interaction Enableの部分をチェックし忘れていた。
自作Gitクライアントv0.2.0をリリース

自作Gitクライアント「Guitar」v0.2.0のコンパイル済みバイナリをリリースしました。

https://soramimi.github.io/Guitar/

対応プラットフォームは下記の通りです。

- Windows
- macOS
- Debian
- Ubuntu
- Raspbian


[先日も書きました](https://qiita.com/soramimi_jp/items/8425196ddc28bf283333)が、クライアントというか、支援アプリくらいに思って頂いた方が良いかもしれません。v0.2.0なので過度な期待は禁物です（笑）

ダークテーマ（暗いUI）で使いたいという要望を頂いていますが、現在開発中です。そちらはそのうち実現できると思います。

というわけで、お試し頂ければ幸いです。
Django を起動しないで画面テンプレートを開発する方法

# 目的

[前回：Chrome拡張を使って Django を起動せずにテンプレートのデザインを確認する方法]
(https://qiita.com/okoppe8/items/a16ae7369a2797a54488)

テンプレートを静的ファイルとして使っている場合（埋め込みタグ無しの場合）限定で、Djangoを起動せずローカルWebサーバだけでhtmlの確認をする方法です。前回と違いウェブサーバが必要になりますが、JavaScriptも読み込むのでデザインの確認だけでなく通常の開発にも使えます。

#作業手順

・templatesディレクトリとstaticディレクトリを同一の親ディレクトリの配下に配置する

```
project_dir
└app_root
  ├templates
  └static
```

・テンプレートファイル内のstaticリソースへのリンクを、{statc}タグを使わずにルート相対パスで直接「/static/js/main.css」のように書く。

・ローカルWebサーバで、親ディレクトリをサブドメインのルートとして公開し、テンプレートファイルにアクセスする

Djnago起動時のstaticリソースへのパスと、ローカルWebサーバへ直接アクセスしたときのパスが同一になるため、直接テンプレートにアクセスした場合でもstaticリソースが参照されるようになります。

Djangoが無くても開発を進められるので、templatesとstaticディレクトリはフロントエンドエンジニアの管轄として仕事を分業することができます。

#参考

Creating a SPA in Django
http://www.adamwester.me/blog/creating-a-spa-in-django/
Phalcon3.2からServiceProviderが提供されるようになりました

ここ最近Phalconを業務で使うようになったファガイです。

今までLaravelばかり触ってきたのでPhalconの実装になれずにいます、、、
さて、Phalcon3.2からはひっそりとServiceProviderの機能が実装されました。

いままではEventMangerに噛ませるような実装をやるのがおそらく近いやり方だったのですが、公式的に用意されたのでうれしい。

## 対象のPR

https://github.com/phalcon/cphalcon/pull/12543

もともとこれは3.1に入る予定だったようですが、3.2にずれたようで。

## 使い方

簡単です。

```SomeServiceProvider.php
use Phalcon\Di\ServiceProviderInterface;
use Phalcon\DiInterface;

class SomeServiceProvider implements ServiceProviderInterface
{
    public function register(DiInterface $di)
    {
        $di['foo'] = function () {
            return 'bar';
        };

        $di['fooAction'] = function () {
            return new SomeComponent();
        };
    }
}
```

あとはこれをDIに突っ込むだけ。

```php
$di = new \Phalcon\Di\FactoryDefault();
$di->register(new SomeServiceProvider());
```

簡単になってうれしいですね。
Azure新ポータルで共同管理者を作成する方法

# はじめに
https://azure.microsoft.com/ja-jp/updates/azure-portal-updates-for-classic-portal-users/
ついにクラシックポータルが終了するようですね。
結構頻繁に旧ポータルでの作成ができなくなるリソースが増えてきたので、そろそろかなという感じもしてましたね。
そんな中7～8月くらいに旧ポータルを触っていて、不思議な場面に遭遇しました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181154/94ab874a-06b0-05c0-a61e-c2158e9f38b0.png)
**共同管理者が作成できないだと・・・っ！**

上の様に新ポータルで共同管理者にする設定をするようになってました。
少し検索してると、**2017年10月以降共同管理者は作成できない**との書き込みを発見し、社内でもその情報が独り歩きしていたので、今更ですが新ポータルでの共同管理者の設定方法を書いていきたいと思います。

# 事前準備
新ポータルで共同管理者にする際の条件が「**RBACでサブスクリプションに対し所有者の権限が与えられていること**」になります。
つまり、Azureリソースへの全権限を与えられているユーザーのみを共同管理者にすることが出来るのですね。
相変わらず強いですね、共同管理者。
共同管理者の権限が強すぎるためにRBACでの細かい権限操作ができるようになった背景を考えると納得の権限割り振りです。
以下はサブスクリプションの所有者にユーザーをする方法です。

Azureポータルの「その他のサービス」から「サブスクリプションを選択」
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181154/66f35634-136d-8277-1e3b-8451fc8b4713.png)

該当するサブスクリプションを選択し、「アクセス制御(IAM)」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181154/edea1c20-0e0c-a585-703b-c33c2bd883ff.png)

ページ上部の「＋追加」を選択し、役割のプルダウンから「所有者」を選択する。
選択の下の部分にAzureADに登録されているユーザーの一覧が出てくるので、所有者権限を割り振りたいユーザーを選択し、保存する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181154/d31084dc-9e53-401c-c300-08b522b8fcc1.png)


すると下の図の様に所有者の欄にユーザーが追加されます。(下の方のユーザーです。)
この図で分かる通り、ROLEの表示の左側がリソースに対する権限を、右側がサブスクリプションの権限を表しています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181154/f93c1375-531d-4c6d-908c-c14d05f64436.png)



# 共同管理者設定方法
共同管理者の設定は非常に簡単です。
上の図の右側の「・・・」を選択すると以下のようなポップアップが出てきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181154/aff98743-dcf6-93e8-26be-26b4b723ad0c.png)

「共同管理者として管理する」を選択するとユーザーを共同管理者にすることが出来ます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181154/dd1b8d63-e433-e7a8-de77-bb603999edba.png)

非常に簡単ですね。これでスーパーユーザーの出来上がりです。

# 終わりに
Azureの権限周りは中々一筋縄ではいかないですね。
サブスクリプションに対する権限だったり、ディレクトリに対する権限だったり、リソースに対する権限だったり。。。
自分もざっくりとは把握しているつもりですが、人に説明するとなるとどう表現していいのかわからなくなる時があります。
しかし、Azureを本格的に使用していくと必ず理解しなくてはならないところなのが歯がゆいですね。

そういえば旧ポータル閉鎖で一つ懸念があるのですが、サブスクリプションとディレクトリの紐づけ変更は新ポータルでできるようになるのですかね。。（誰か知っている方がいれば情報くださると助かります。）

締まらない終わり方になりましたが、皆様もAzureで素敵な権限管理を行ってください。
ではではー

#追記
この記事書いてすぐに新ポータルでもサブスクリプションとディレクトリを変更する方法が[アナウンス](https://azure.microsoft.com/ja-jp/updates/edit-directory-now-in-new-portal/)されました。
サブスクリプションのメニューから行うんですね。一安心です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181154/d07c4438-fe98-6a92-7b69-17815cbb95d1.png)
サブスクリプション名の変更もアカウントポータルではなく、こちらからできるようになっていたのですね。。。
旧ポータルが廃止されるまでは本当にポータルから目が離せませんね。


# 参考リンク
https://docs.microsoft.com/en-us/azure/billing/billing-add-change-azure-subscription-administrator
https://azure.microsoft.com/ja-jp/updates/edit-directory-now-in-new-portal/
【WebSphere Liberty Hints & Tips】デフォルトのホスト設定は変える


## はじめに
製品版のWebSphere LibertyもOSS版のOpen Libertyも同じです。
製品インストール時のserver.xmlのデフォルトでは、アプリケーションが動くエンドポイントがlocalhostのみになっています。これをうっかり忘れてるとアプリを動かしてるマシンのIP/Host名でアクセスしようとしても接続拒否に遭うので、その時の備忘録です。

## 設定方法
1. アプリケーションはdropinsディレクトリに入っていて動いてるものとします。
2. デフォルトのserver.xmlを確認します。httpEndpointを見てみると、idとhttpPortとhttpsPortがそれぞれデフォルトで設定されています。hostは設定されていませんが、裏ではデフォルトでlocalhostが設定されています。To access...というコメントに注意書きがありますね、これを読み飛ばすと以下に遭遇します（つまり私は読み飛ばした上にデフォルト値も失念してたというわけです）。。

```server.xml
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

    <!-- Enable features -->
    <featureManager>
        <feature>jsp-2.3</feature>
    </featureManager>

    <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint id="defaultHttpEndpoint"
                  httpPort="9080"
                  httpsPort="9443" />

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>

```

3.このままIPを指定してアプリケーションにアクセスしてみても接続できません。
![Kobito.FJS5pn.png](https://qiita-image-store.s3.amazonaws.com/0/129662/fbfe7d8d-38a9-4a99-74fc-98cc185782a0.png "Kobito.FJS5pn.png")

4.curlの結果は以下のとおり接続拒否です。
![Kobito.EiQSwK.png](https://qiita-image-store.s3.amazonaws.com/0/129662/75513f41-05c9-ff3f-6e18-d5aa7ebb1eac.png "Kobito.EiQSwK.png")

5.localhostではアクセスできます。
![Kobito.9YMi5c.png](https://qiita-image-store.s3.amazonaws.com/0/129662/6fbe8e73-936c-5625-c567-679d997e6823.png "Kobito.9YMi5c.png")

6.それではserver.xmlの設定変更します。host="\*"を追記します。\*にすると自マシンで使える全ネットワーク・インターフェースで受け付けるようになりますので、\*でなく特定のIP/Hostを指定してもよいです。ちなみにここでJVMの再起動は不要で変更は自動反映されます。便利ですがうっかりミスしないように気をつけましょう。

```server.xml
<server description="new server">

    <!-- Enable features -->
    <featureManager>
        <feature>jsp-2.3</feature>
        <feature>localConnector-1.0</feature>
    </featureManager>

    <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint" host="*"/>

   <!-- Automatically expand WAR files and EAR files -->
   <applicationManager autoExpand="true"/>
</server>
```

7.再度アプリケーションにアクセスしてみると、今度はアクセスできます。
![Kobito.5Hssp0.png](https://qiita-image-store.s3.amazonaws.com/0/129662/c0c8fb09-9587-fb2a-a7a0-db315f5d87ab.png "Kobito.5Hssp0.png")


## まとめ
localhostだけで動かすことは少ないと思いますので、host=""の設定を忘れずないようにしましょう。。

## 参考情報
HTTP Endpoint (httpEndpoint)
https://www.ibm.com/support/knowledgecenter/en/SSEQTP_8.5.5/com.ibm.websphere.wlp.doc/ae/rwlp_config_httpEndpoint.html
bs-fetch使ってみた


MLたいして触ったことない(※[これ書くときに初めて触った](https://tech.recruit-mp.co.jp/server-side/post-14623/)) & 本職サーバーサイド&インフラで、
WEBは2年前Angular書いて以降は追えてない程度マンですが、AdventCalender誘ってもらったので書いてみます。


ReasonでAPIリクエストする処理を書こうとして、XHRかFetchないか探してみたら
[bs-fetch](https://github.com/reasonml-community/bs-fetch)を見つけたので使ってみたのを雑に書きました。


## 導入

[1日目の記事](https://qiita.com/mizchi/items/2ce23f7964779b237282)の[テンプレート](https://github.com/mizchi-sandbox/simple-reason-boilerplate)落としてきて、Installationの`npm install`とbsconfig追記だけなので割愛。

## 使い方

サンプルコードには↓が載っていた。ヘッダ指定とかこまいところどうするのかわからん・・・

```
let _ =
  Js.Promise.(
    Fetch.fetch("/api/hellos/1")
    |> then_(Fetch.Response.text)
    |> then_((text) => print_endline(text) |> resolve)
  );
```

Fetch.fetch系のシグニチャをみると、4通り実行方法が用意されている模様

```
external fetch : string -> response Js.Promise.t = "" [@@bs.val]
external fetchWithInit : string -> requestInit -> response Js.Promise.t = "fetch" [@@bs.val]
external fetchWithRequest : request -> response Js.Promise.t = "fetch" [@@bs.val]
external fetchWithRequestInit : request -> requestInit -> response Js.Promise.t = "fetch" [@@bs.val]
```

- fetchは第一引数にurlのstringだけ渡してシンプルにGET
- fetchWithInitは第一引数にurlのstring,第二引数にrequestInit型を渡して実行
- fetchWithRequestは第一引数にrequest型を渡して実行
- fetchWithRequestInitは第一引数にurlのrequest,第二引数にrequestInit型を渡して実行

Initは適用前、無印は適用後を表現しているのかな・・・？
ヘッダやbody指定してfetchするならfetchWithInitを使えば良さそう。

ドキュメントなさ気なので[ソース](https://github.com/reasonml-community/bs-fetch/blob/master/src/Fetch.ml)と[サンプル](https://github.com/reasonml-community/bs-fetch/blob/master/examples/reason_examples.re)から読み解く


### HeaderInit

シグニチャ

```
  external make : < .. > Js.t -> t = "%identity"
  external makeWithArray : (string * string) array -> t = "%identity"
```

タプルのArray突っ込めば生成できる模様

```
Fetch.HeadersInit.makeWithArray([|("Accept-Encoding","gzip"), ("bar","foo")|])
```


### RequestInit

シグニチャ↓

```
  let make
    ?method_:(method_: requestMethod option) 
    ?headers:(headers: headersInit option)
    ?body:(body: bodyInit option)
    ?referrer:(referrer: string option) 
    ?referrerPolicy:(referrerPolicy: referrerPolicy = None) 
    ?mode:(mode: requestMode option) 
    ?credentials:(credentials: requestCredentials option) 
    ?cache:(cache: requestCache option) 
    ?redirect:(redirect: requestRedirect option) 
    ?integrity:(integrity: string = "") 
    ?keepalive:(keepalive: bool option)
```    

```
let requestInit = Fetch.RequestInit.make(
  ~method_=Post, 
  ~headers=Fetch.HeadersInit.makeWithArray([|("Accept-Encoding","gzip"), ("bar","foo")|]),
  ~mode=NoCORS, 
  () /* 指定していないoption型引数を埋める */
)
```


こまい設定できた。同じ要領でBodyInit使えばBody指定もできました。


### 実行

```
let _ =
  Js.Promise.(
    Fetch.fetchWithInit(
      "http://localhost:4000",
      Fetch.RequestInit.make(
        ~method_=Get,
        ~headers=Fetch.HeadersInit.makeWithArray([|("Accept-Encoding","gzip"), ("bar","foo")|]),
        ~mode=NoCORS,
      ())
    )
    |> then_((resp) => Fetch.Response.text(resp))
    |> then_((text) => print_endline(text) |> resolve)
    |> catch((e) => Js.log(e) |> resolve)
  );

```

直感的にかけて良い
Monaparty の federated node を立ち上げるための情報

長らくお待たせしました。Monaparty の federated node 用意ができました。

# Federated node ってなに?

Counterparty は複数のサーバアプリケーションから成り立っていて、手作業でデプロイ作業をするとかなりしんどいです。
こういうときには docker-compose や Helm といったコンテナオーケストレーションツールを使うのが常道と思います。

Counterparty Federated Node (しばしば fednode と略されるようです)は、その docker-compose に薄皮を被せたデプロイ環境、およびデプロイ結果の動作環境を指します。

使いやすいかどうかは、正直なところ微妙ですが… docker-compose や docker コマンドを併用できますので、運用時にどうしようもなく詰んでしまうということは無いと思います。たぶん。

# どれくらいのリソースが必要？

2core, 8GB RAM (+ swap), HDD 40GB 程度でとりあえずフルノードが動きます。
Azure VM なら D2_V2 程度です。SSD にしなくても読み書きは間に合います。
Burn イベントも、この構成(と Cloudflare CDN)で乗り切れました[^5xx]。

[^5xx]: ピーク時には「5xx エラー発生」との tweet も見かけましたが。Burn イベントを超える同時アクセスは、よほど大規模なトークン活用ゲームでも企画しない限り無いでしょう。

複数のコンテナが動作しますので、コア数は多いに越したことはないですが、ご予算とご相談ですね。

# インストール

[公式のドキュメント](https://counterparty.io/docs/federated_node/)に概ね沿えば OK です。

Monaparty 独自に注意しなければいけないことは…

1. fednode のリポジトリは https://github.com/monaparty/federatednode.git です。
2. master ブランチと develop ブランチは、それぞれ monaparty ブランチと monaparty-develop ブランチになります。

1 は当然として、2 は疲れていると間違えそうです。monaparty にあるリポジトリでも master と develop は、それぞれ本家 Counterparty のものを追随しています。

# どれくらい信じてもよい？ (品質面)

Burn イベントに全力を注いでいたので、fednode 周りは正直自信がないです。バグは[issue](https://github.com/monaparty/federatednode/issues)へ、修正できてしまった場合には[プルリク](https://github.com/monaparty/federatednode/pulls)頂ければ対応します。
Slack上で動作するチャットシステムの構築

https://qiita.com/advent-calendar/2017/dwango

# はじめに
![slack-logo-5CFD82DDBE-seeklogo.com.png](https://qiita-image-store.s3.amazonaws.com/0/40020/ac94eda0-0131-b27d-a804-ec8feca5a153.png)
皆様、Slack、活用されているでしょうか。
表題の通り、**Slackを用いて、Slack上でメッセージをやりとりできるシステム**を作ります。
もともと、Slack上で動作するゲームを作ろうと思っていて、その習作を兼ねたものになります。
SlackのAPIを用いて状態を受け取り各種メソッドにPostすることで状態を更新していきます。

# リポジトリ
https://github.com/orzngo/slack-chat

# 作る機能
## チャットに入室する
ニックネームを指定してチャットに入室する機能です。これが無いと始まりませんね。
BotのいるSlackチャンネルにて、joinコマンドを発行してチャットに入室します。

## ユーザーに対して画面を表示する
Slackは優れたプラットフォームですが、Canvas描画をサポートしていないため、基本的にテキストと絵文字でユーザーに対して情報を伝える必要があります。定期的な再描画もサポートする必要があるでしょう。
一度に大量の画面を更新しようとすると、その数だけAPIにPostする必要があり、APIのRate Limitに触れてしまうため、更新間隔は参加者同士でばらばらになるように配慮します。

# 動作デモ

## 接続
![スクリーンショット 2017-12-18 16.08.46.png](https://qiita-image-store.s3.amazonaws.com/0/40020/897c2e7f-bb09-7cbe-b006-d0c685b06951.png)


Botが居るチャンネルでBotに大して接続コマンドと使用するニックネームを伝えると入室できます。
この状態でBotに対してメンションするとそれが発言となるのですが、このままでは画面が表示されていないためあまり意味がありません

## チャットの表示
![スクリーンショット 2017-12-18 16.09.01.png](https://qiita-image-store.s3.amazonaws.com/0/40020/42010c04-eb38-5f96-0748-2b036bfb2c46.png)

Botに対して screen コマンドを発行することで、Botからメッセージが返ります。
裏ではメッセージのTimestampと、発言を返したチャンネルを覚えており、この二つの情報で、メッセージに対して定期的な編集をかけます。
人間が行う場合と違い、なぜかAPI経由で編集する場合、時間制限が無いようです。

## 発言
![スクリーンショット 2017-12-18 16.09.15.png](https://qiita-image-store.s3.amazonaws.com/0/40020/75a5242c-2e7f-82fc-7716-38fee4da9afd.png)


Botにsayコマンドで発言すると、それがチャットログとして保存され、全ユーザーに送信されます。  
接続済みの全ユーザーの画面は定期的に更新され、その時の最新のチャットログ１０件が表示されます。

### emoji対応

![スクリーンショット 2017-12-18 16.09.43.png](https://qiita-image-store.s3.amazonaws.com/0/40020/84cef46c-f96e-de9c-2e9d-9ef74b40f02d.png)

Slackというプラットフォームそのものが絵文字に対応しているため特に意識せずとも対応できます。
名前にも使うことができます。自分で作ると大変にだるいのですごいラクです。


## チャンネルの移動
Botがいる別のチャンネルでscreenコマンドを実行すると、今までの画面は放棄され、新しい画面が表示されます。


# 便利な使い方
## 匿名で発言する
チャットの画面はそのチャンネルにいる全員に見える一方、Botに対して発言するチャンネルはどこでもよいため、匿名で発言が可能になります。悪いことが出来そうな気がしますが、結局ログは残っている為出来ないです。

## 議論を公開する
チャットの画面はSlackのチャンネルにいる全ユーザーに見えているため、まずそのチャンネルでScreenを表示した後、別のチャンネルで発言することにより、横槍の入れられない公開討論が可能になります

# まとめと今後の課題
## まとめ
Slackのユーザー同士でスレッドを共有し、それを操作し、それを表示する、という、基本的な仕組みが作れました。
Slack上で複数人で遊べるゲームとかを作りたかったので、だいたいの目的は達したかなと思います。
**Slack上でメッセージのやりとりができるようになったのは非常に便利だと感じました。**

Slackというプラットフォームは非常に優秀で各種APIも充実しており、ゲームやコミュニケーションを行う上での基本的な機能はすべて実装されていると思います。
認証周りもSlackが受け持っているので、その辺を考えることなく、必要な機能の実装だけに注力できたため、数日でこのチャットを作ることができました。
マジで簡単なので、皆さんもSlackのAPIとにらめっこしながら年末年始をゆっくり過ごしてみてはいかがでしょうか。

## 今後の課題
+ チャットルームが一つしか作れないので引数でルーム番号を受け取るようにする
+ 一度作ったscreenを破棄出来ないのでexitコマンドを実装する
+ 発言ログをDBに積んだりしてないのでその辺作ったり
+ なんか面白いゲームを考える
+ ~~Slackにはそもそもチャット機能がある~~
メールを飲み込んで消すメールサーバの構築

## 概要
正常に受信するが、 受け取ったデータは /dev/null に流し込むPostfixの構築。

## そんなことしてなにが嬉しいの
DNSにMX/Aレコードが存在しないドメインからのメールを拒否するPostfixの[設定](http://www.postfix-jp.info/trans-2.2/jhtml/postconf.5.html#smtpd_sender_restrictions)があります。
スパマーでもない限り存在しないドメインからメールを送ることは無いだろうと考えていましたが、 一方的にno-replyメールを送りたい場合があります。
この場合、 メールを拒否されないためには、 メールアドレスのドメイン部分のDNSに何かしら「最終的にIPアドレスとなるもの(MXレコードやAレコード)」を設定しておく必要があります。
しかし、 自前でMTAを持たず、 社内共有のリレーサーバを経由するような場合、 最終宛先にメールアドレス間違い等で拒否された場合に、 リレーサーバが「お届けできませんでした」を送る先に送信できず、 リレーサーバでエラーが出てしまいます。 (DNSを設定しない場合もエラーは出ますが、 ネットワーク接続ができなかったテンポラリエラー扱いで、 リトライ処理が走ってしまう事が多いです)
それくらい許容するという手も全然ありですが、 最小限の労力で「メールを受け付けるけどすぐさま捨てる」というメールサーバを作ることで解決しようと思います。

![postfix_devnull_001.png](https://qiita-image-store.s3.amazonaws.com/0/90487/9535150b-6bee-229c-1c83-1a0680b7f1ae.png)

1. MAIL FROM: <no-reply@hoge.fuga.example.com> / RCPT TO: <user@atesaki-domain.example.jp>
2. MAIL FROM: <no-reply@hoge.fuga.example.com> / RCPT TO: <user@atesaki-domain.example.jp> (そのままリレー)
3. ユーザがいない等のエラー応答
4. no-reply@hoge.fuga.example.com に　「メールをお届けできませんでした」のメール(Bounce)を返したいが、 失敗する



## 設定

### 環境
* CentOS Linux release 7.4.1708 (Core)
* Postfix 2.10.1-6

### 外部からのメールを受け付け許可
```diff:/etc/postfix/main.cf
-inet_interfaces = localhost
+inet_interfaces = all
```
正確には外部のIPからの接続を許可です。 firewalld/iptables/各種クラウドサービスのファイアウォール(tcp:25)も許可してあげましょう。

### 扱うドメインを追加
```diff:/etc/postfix/main.cf
-mydestination = $myhostname, localhost.$mydomain, localhost
+mydestination = $myhostname, localhost.$mydomain, localhost, hoge.example.jp, hoge.fuga.example.com
```
ここに記載したドメイン宛のメールのみ受け付けます。その他の場合は「Relay access denied」と拒否します。
no-reply@xxxxxx のxxxxxの部分で使用予定のものを書いてください。

### no-reply宛を/dev/nullへとルーティング
```diff:/etc/aliases
+no-reply:   /dev/null
```

編集後、 `newaliases` コマンドを実行してください。

### 設定反映
`postfix check`
`postfix reload`
(まだpostfixをを動かしていない場合は、 `systemctl start postfix` して下さい)

## 検証
no-reply@使いたいドメイン に対してメールを送ってみましょう。

```
Dec 18 06:16:17 yourhostname postfix/local[20106]: D959510D2F82: to=<no-reply@your.domain>, relay=local, delay=11, delays=11/0.02/0/0, dsn=2.0.0, status=sent (delivered to file: /dev/null)
```


という風に /dev/null に送られた事がわかります。

## その他
* この設定だけでは問題ないはずですが、 [念のためオープンリレーサーバになっていないかチェックしておきましょう。](http://check.jippg.org/)
* この設定だけでは、 実存するアカウントへのメール (ex. root@xxx.xxx) にはメールが届きます。 ここに迷惑メールが溜まってしまう事もあるので、 それを避けたい場合は `/etc/aliases` を全て /dev/nullに向ける等してみましょう。 (cronが失敗した時のメールも消えてしまいますが、 その辺の設定は書きません)
* 完全に省きましたが、 使用するドメインのDNSの設定(MX/A/SPFのTXTレコード)ももちろん必要です。 この辺はたくさんインターネットに資料があります。
systemd-nspawnのmachinectl shellはホスト側にも使える

[systemd-nspawn Advent Calendar 2017](https://qiita.com/advent-calendar/2017/systemd-nspawn) 20日目の記事です。

```bash
machinectl list-images -a
```

で出てくる.hostは自分自身なので

```bash
# ログイン画面
machinectl login .host
# シェル実行
machinectl shell .host
# ホストをコピーしてコンテナへ
machinectl clone .host hostcontainer
```

などなど
Visual Studio Code の git submodule 対応を試してみる

この記事は、株式会社ACCESS Advent Calendar 2017 の 18日目の記事です！

# あらまし

私はエディターとして **Visual Studio Code (vim keybinding)** を愛用しています。

Visual Studio Code は OSS として github で公開されていて、
欲しいと思った機能が、思ったように動く、開発者が開発者(自分)のために、作り上げているエディターという感触がとても好きです。

利用者も増えてきたことで、めぼしい Extension やハックなどの情報も揃っているのも素敵なところですね。

正直、かなり名前で損をしている気がします。


そんな至れり尽くせりの Visual Studio Code ですが、
**え？この機能ないの？なんで？**というものがありました。

# Visual Studio Code が git submodule に対応した

そう、タイトルにしていますが、なぜか **git submodule に対応していなかった**のです。

確かに git submodule という機能自体に賛否が別れるところで、
個人的にも、できれば避けたい機能ではありますが、Chromium などの大規模な OSS では利用されているものも多く**(要出典)**
vscode を多重起動するか、あるいは必要に応じて integrated terminal でコマンドを叩くなどの併用が必要でした。

実は issue 自体は1年半も前からトラッキングされていたものの、割りと放置気味で、
平日であれば **30～50コミット/day** は平気で master に入る成長の速さにしては異例のように感じました。

* Git submodule support #7829
    * https://github.com/Microsoft/vscode/issues/7829

そして、**2017/12/14 ついに submodule 対応が master に merge** されました。
近日中にリリースタグも切られることと思いますが、
一足先に自前でビルドして動かしてみたので簡単に所感を記します。

# ソースコードからビルドする

本家の README.md よりリンクがありますが、下記を見れば嵌まることなく素直にビルドできました。
https://github.com/Microsoft/vscode/wiki/How-to-Contribute#build-and-run-from-source

Ubuntu 14.04 LTS で試したので yarn のインストールが若干めんどくさかったくらいですね。

* yarn install for Ubuntu 14.04 LTS
    * http://l-chika.hatenablog.com/entry/2017/04/30/095412

# サンプルリポジトリの準備

submodule を利用している軽いリポジトリが見つからなかったので、自分でサンプルリポジトリを用意しました。

* submodule-training-parent
    * https://github.com/diescake/submodule-training-parent

* submodule-training-child (こっちの clone は不要)
    * https://github.com/diescake/submodule-training-child

submodule-training-parent を `git --recursive clone` してビルド済みの vscode からオープンします。

# 試してみる

parent, child のファイルを適当に変更して modified の状態にしておきます。

![submodle_01.png](https://qiita-image-store.s3.amazonaws.com/0/38837/d9a66f19-2e9f-8b06-8e7e-c0917ef80b0d.png)

まず、ファイルツリーには submodule を含む全てのファイルが表示されるようです。
この辺りは、submodule 対応前と変わらないです。

ただ submodule 配下のファイル名横にも **M** が表示されていて git 管理になっているのがわかりますが、
ここは新たに表示するようなった点かも。(未確認)

![submodle_02.png](https://qiita-image-store.s3.amazonaws.com/0/38837/43019736-8e31-a94d-3db8-ddaff7ac1329.png)

git ビューでは上部の **SOURCE CONTROL** エリアが追加され、ここでリポジトリを選択できるようになっています。
リポジトリを切り替えると下部の CHANGES のファイルも切り替わります。
直感的でわかりやすいと思います。

![submodle_03.png](https://qiita-image-store.s3.amazonaws.com/0/38837/f71199c5-3927-b0f8-36c9-ed12e9f7619a.png)

child に切り替えてみました。
submodule 対応前は vscode 上では差分を確認することはできませんでしたが無事 diff が確認できます。（╹◡╹）

![vscode-submodule.gif](https://qiita-image-store.s3.amazonaws.com/0/38837/7ca16aa1-a2f7-0f7d-2510-febc3a4b8be3.gif)

最後に、本家 issue に下記 gif が添付されていたので引用します。
恐らく正式リリースの際に、Release note に利用されるものと思います。

Visual Studio Code の新機能リリースの際は、
大抵の場合は gif によるチュートリアルが添付されるのでわかりやすいですね。

# おわりに

というわけで、ざっくりですが Visual Studio Code の submodule 対応を紹介してみました。ლ(╹◡╹ლ)
ちょっと触った感触では素直な実装で、使い方や挙動で戸惑うことはないように感じました。

それでは、明日は @ymtszw さんです！次回もお楽しみに！ (BGM: Get Wild)

※追記

2018/1 リリースに投入されましたね！
https://code.visualstudio.com/updates/v1_20#_git-submodules
パスワードの強化機能を試す (Oracle Database 12c)



# パスワードの大文字と小文字
Oracle Database 10g以前、データベース・ユーザーのパスワードは大文字／小文字が区別されませんでした。Oracle Database 11g Release 1以降、Oracle Databaseユーザーのパスワードは大文字と小文字が区別される設定がデフォルトです。
この動作は初期化パラメーターsec_case_sensitive_logonで制御します。パラメーター値をデフォルト値のtrueからfalseに変更すると、パスワードの大文字と小文字を区別しなくなります。

# Oracle Database 12cの動作
## インスタンス起動時のログ
初期化パラメーターsec_case_sensitive_logonをfalseに設定することは、Oracle Database 12cでは非推奨になりました。このパラメーターをfalseに設定した状態でOracle Database 12c Release 2インスタンスを起動すると、Alert.logに以下のメッセージが出力されます。

```
Deprecated system parameters with specified values:
  sec_case_sensitive_logon
End of deprecated system parameter listing
```

## Oracle Database 12c Release 2からの動作変更
Oracle Database 12c Release2環境で、初期化パラメーターsec_case_sensitive_logonをfalseに設定する場合にはもう一つの設定が必要です。
必要な設定はデータべス・サーバーのsqlnet.ora ($ORACLE_HOME/network/admin/sqlnet.ora) に、以下の記述を行います。

```
SQLNET.ALLOWED_LOGON_VERSION_SERVER=11
```

Oracle Database 12c Release 2では、このパラメーターのデフォルト値は12です。
このパラメーターの設定値を12または12aに指定した状態を「排他モード」と呼び、旧バージョンのパスワード認証を受け付けない状態になります。

初期化パラメーターsec_case_sensitive_logonをfalseに設定し、上記設定を入れない場合、正しいユーザー名／パスワードを指定してもエラー「ORA-01017: invalid username/password; logon denied」が出力されて接続できません。

SQLNET.ALLOWED_LOGON_VERSION_SERVERの設定により、DBA_USERSビューの内容がどのように変化するかを検証しました。

|ALLOWED_LOGON_VERSION_SERVER|DBA_USERS.PASSWORD_VERSIONS|備考|
|:---|:---|:---|
|11|10G 11G 12C| |
|12|11G 12C|デフォルト値|

上記のように、sqlnet.oraファイルの設定により、CREATE USER文実行時のシステム・ディクショナリが変化します。

下記のマニュアルにはSQLNET.ALLOWED_LOGON_VERSION_SERVERの使用方法が詳しく掲載されています。
https://docs.oracle.com/cd/E82638_01/NETRF/parameters-for-the-sqlnet-ora-file.htm#GUID-1FA9D26C-4D97-4D1C-AB47-1EC234D924AA

JDBC Driverの接続動作にも影響を与えるため、バージョンアップ時には慎重な検討が必要です。
Project Euler Q48 【自身のべき乗(self powers)】

Project Eulerをワンライナーで解いてみる。
間違っていたらコメントください。


## 問題
次の式は, $1^1 + 2^2 + 3^3 + ... + 10^{10} = 10405071317$ である.

では, $1^1 + 2^2 + 3^3 + ... + 1000^{1000}$ の最後の$10$桁を求めよ.

## 解答

```bash
seq 1000 |
awk -M '{s+=$1^$1}END{print substr(s,length(s)-10+1,10)}'
9110846700
```

`-M`オプションが使えない環境用

```bash
seq 1000 |
awk '{a=1;for(i=1;i<=$1;i++){a=substr(a*$1,length(a*$1)-10+1,10)};s+=a}END{print substr(s,length(s)-10+1,10)}'
9110846700
```

## 答え合わせ
こちらのサイト様と一致していればOKとした。
http://kingyojima.net/pje/048.html
[#TouchDesigner] CookのWikiページを翻訳してみた

![thumbnail](https://qiita-image-store.s3.amazonaws.com/0/127402/4c5c911e-b95d-4379-4299-3a02c14b3d04.png)

# はじめに
Cookは、TouchDesignerを扱ううえでとても大切な概念だと感じたため、和訳しておきました。
少々訳しづらい部分もあったため、意訳した部分もありますがご容赦ください。
尚、日本語訳が間違っている場合はバシバシ修正入れてもらって構いません。

参考ページ : [Cook - Derivative TouchDesigner099 Wiki](https://www.derivative.ca/wiki099/index.php?title=Cook)

# Cook
**Cook**とは、ネットワークにあるオペレータが計算を走らせている状態のことを指す用語です。
オペレータをミドルマウスクリックすることで、最後にいつCookされたか、TouchDesignerを起動してから何回Cookされたかを閲覧することができます。

TouchDesignerのオペレータは、オペレータの機能が必要とされたときのみCookされるようになっています。
つまり、毎フレームすべてのノードがCookされているわけではないということです。([Cookの順序](#cookの順序)参照)

一方で毎フレームCookされるものもあり、以下がその例となります([Cookの強制](#cookの強制)参照)

- ビュアーフラグがOnに設定されているオペレータ
- 最後にCookされてから値が変更されたオペレータに接続されているオペレータ
- レンダリングに関連しているパネルオペレータ
- TouchDesignerの外部にネットワークでデータを送信しているオペレータ

ノード間のワイヤーがアニメーション表示されている場合は、上流(左側)のノードがCookされていることを意味し、下流ノード群はCookしている場合としていない場合(単にCookを要求しているだけ)があります。

PerformanceMonitorダイアログでは、1フレーム中に何がCookされたかを表示することができます。
30FPSか60FPSでアプリケーションを実行したい場合は、極力Cookされるノード数を減らす必要があるでしょう。


# Cookの詳細
## 何がCookを発生させるのか？
オペレータがCookされるには、以下2つの条件が真である必要があります。

- **Cook Request** を持つ (オペレータをCookするように求める動作)
- **Cook Reason** を持つ (なぜCookされる必要があるのか)

#### Cook Request
- オペレータの**出力に**接続されたオペレータがCookを要求しているとき
- パラメータでオペレータを参照しているものがCookを要求しているとき
- ビューアがノードのデータを表示しているとき
- CHOPまたはDATが値をエクスポートしようとしているとき
- オペレータのcook()メソッドを呼んだとき

#### Cook Reason
- 入力されいているノードの一つがCookされた
- パラメータを通して参照しているノードがCookされた
- ノードのパラメータが変更された
- 特定のスクリプティングコマンドがノード上で実行された
- エクスプレッションの結果が変化した
- オペレータが参照する変数の値が変更された
- エクスプレッション内で参照されたオペレータがCookされた
- オペレータが時間依存のもので、入力やパラメータの変化にかかわらず毎フレーム異なる値を出力できる(TimeSlice CHOP, VideoDeviceIn TOPなど)場合
- パネルコンポーネントで、ユーザーが操作できる場合

オペレータがCookリクエストを受け取ったとき、そのオペレータに接続されているすべての入力に対しても、実際にCookされるかに関わらず、Cookリクエストを送信します。
入力のうちのどれかがCookされる場合、下流オペレータはCook Reasonが与えられた上でCookされます。
入力のすべてがCookされないのであれば、下流オペレータは利用可能なCook Reasonを探索します。
Cook Reasonが発見されなければ、オペレータはCookされません。(PerformanceMonitor上でも出現しません)

例えば、デフォルト状態のConstant TOP(1つのチャンネルで、エクスプレッションなし)のビュアーを見ていたとします。
このノードは定期的ににCookリクエストを受けています(例えば毎フレームUIが再描画されている状態です)。
しかし、このノードはCook Reasonを持っていないため、Cookされません。


## Cookの順序
TouchDesignerは**"プルシステム"**を採用しています。
よくある間違いに、*TouchDesignerのCookは上流から下流に流れる*というものがあります。

例えば、Math CHOPに接続されたConstant CHOPがあるとします。
ほとんどの人はConstant CHOPの値を変更すると、Math CHOPが強制的にCookされると勘違いしています。
しかし、すべてのオペレータはデータが要求される場合にのみCookされます。

そのため、Constant CHOPのパラメータが変更されている間は自身を**Dirty(汚い)**な状態であるとみなしますが、
何かがこのデータにアクセスしようとしするまでCookを行いません。
つまり、Math CHOPが値を要求するまでConstant CHOPはCookされないのです。

Constant CHOPは、ビュアーがOnになっている、言い換えれば、ユーザーがそのオペレータのデータを見ようとしたなどほかの理由でCookされることもあります。

## Cookの強制
いくつかのオペレータ、特にMovie Out TOP、Touch Out OP, その他Out OPのように、パラメータの変更や入力の変化にかかわらず毎フレームCookされるオペレータも存在します。
この動作は、ムービー、ネットワークパイプなどの出力の受信側が連続したデータストリームを取得できることを保証しています

また、Render TOPや~In OPのような特別なオペレータの場合は、入力やパラメータが変更されていなくてもCookします。
(単なるIn CHOPやIn SOPは除く、Device Inなどです)

レンダリングなどに際しては、Cookをするかどうかの判定にたくさんの入力の変更を監視する必要がありますが、
(Render TOPであれば、マテリアル、ジオメトリの位置、ジオメトリのレンダーフラグなど)
シーンでは常に変化が発生している為、強制的に毎フレームCookさせ余計なCook Reasonの探索が走らないようにすることで、計算時間を99％節約しています。

# 訳してみての感想
結局、知りたいことはわかりませんでした。(笑)
systemd-nspawnのexportとimportアレコレ

[systemd-nspawn Advent Calendar 2017](https://qiita.com/advent-calendar/2017/systemd-nspawn) 19日目の記事です。

# 圧縮形式を指定できる

```bash
# gzでexport
machinectl export-tar ubuntu0 ubuntu.tar.gz
# xzでexport
machinectl export-tar ubuntu0 ubuntu.tar.xz
# bzip2でexport
machinectl export-tar ubuntu0 ubuntu.tar.bz2
```

importはこの逆で`machinectl import-tar ubuntu.tar.bz2`

# 進捗確認

```bash
machinectl list-transfers
# キャンセル
machinectl  cancel-transfers id
```

# ダウンロードしてインポート

```bash
# sha256検証とGPG検証もやる
machinectl pull-tar https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-root.tar.xz
# sha256の検証だけ
machinectl pull-tar --verify=signature https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-root.tar.xz
# 検証しない
machinectl pull-tar --verify=no https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-root.tar.xz
```

検証ファイルは[こんな感じ](https://cloud-images.ubuntu.com/xenial/current/)に同じ階層にSHA256SUMSとSHA256SUMS.gpgが置いてあればOK

ちなみに公開鍵は`/lib/systemd/import-pubring.gpg`あたりにあります。
Debian9の環境ではこれが入っていました

```
pub   rsa4096 2014-07-09 [SCE]
      B467FA46E2CE5FAC349910C2D8D1FA8CA29CB19C
uid           Fedora Secondary (22) <fedora@fedoraproject.org>
sub   elg4096 2014-07-09 [E]
pub   rsa4096 2014-07-09 [SCE]
      C527EA07A9349B589C35E1BF11ADC0948E1431D5
uid           Fedora (22) <fedora@fedoraproject.org>
pub   rsa4096 2013-11-14 [SCE]
      9996E55FA5D418C86CEFF750636DEA19A0A7BADB
uid           Fedora Secondary (21) <fedora@fedoraproject.org>
sub   elg4096 2013-11-14 [E]
pub   rsa4096 2013-11-14 [SCE]
      6596B8FBABDA5227A9C5B59E89AD4E8795A43F54
uid           Fedora (21) <fedora@fedoraproject.org>
pub   rsa4096 2009-09-15 [SC]
      D2EB44626FDDC30B513D5BB71A5D6C4C7DB87C81
uid           UEC Image Automatic Signing Key <cdimage@ubuntu.com>
```
【Python】例外を拾ったりassertRaises等で拾うときのTips

pythonのunittestを書いていてとても初歩的なところでつまづいてて情けなかったのでメモ。

ある条件下でちゃんと期待した例外をあげるかを確認するテストケースを書いてて、
はじめこう書いていたのです。

```
def test_raise_error_method(self):
    with self.assertRaises(Exception):
        raise FileNotFoundError('file not found')  ## 例外を上げる処理（メソッド）をここに書く
```


`assertRaises` で`Exception`と書いてて、
`raise` で、`FileNotFoundError`と書いているのでこのテストケースは失敗するものと思ってた。

なのですが成功（OK）と出る・・・。

悩んだ挙句に人に聞いたところ、
「FileNotFoundErrorはExceptionのサブクラスだから、Exceptionで拾うと全部それにひっかかる」

あ、そうなんだ。と。

調べているときに確かにFileNotFoundErrorがサブクラスというのはドキュメントを見て理解はしていたけど、
まさかそれだったとは。

とはいえ確かに言われてみれば何が返ってくるかわからないときはとりあえず`Exception`で拾うときあるし、それと同じかー。
と思うことで納得。

IT業界はまだまだ知らないことだらけです。
VCCW(Version3)にAWS-CLIをインストールする



AWS-SDKを使うプラグインなどで、AWS-CLIのクレデンシャルを使いたいケースがたまにあるので覚書。

```
$ sudo apt update
$ sudo apt install python-pip
$ pip install --upgrade pip
$ pip install awscli --upgrade --user
$ export PATH=~/.local/bin:$PATH
$ aws
usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

  aws help
  aws <command> help
  aws <command> <subcommand> help
aws: error: too few arguments
```

Playbookにした方がいいんだろうなという気はするので、この記事を読み返す回数が多そうだったら考える。
Gitで追加したファイルを削除して反映する方法

Gitでコミットしたら、そのファイルは余分だから削除して〜って言われた。
これだけの作業でもGit初心者には一苦労。

##方法
```
git checkout　"branchname" ←削除したいファイルのあるブランチに移動
git rm "filename"  ←もしローカルに物理ファイルが無くてもエラーにならない
git commit -m 'ファイルの削除をgitに反映'
git push　"branchname" '削除をプッシュ、Gitから消える'
```

無事消えてました。よかった。
PDFの文字列をテキストエディタにコピペすると文字化けする

#テキストエディタにシステム上の文字列をコピペすると文字化けする

##■実際起きた文字化け例
「12月12日」→「12・12・」
「給与支給」→「給与・給」
以上のような文字化けが起きた。

##■原因
PDFからコピった文字列をそのままシステムのメールテンプレート文に使用していたこと。
→PDFの文字列は印刷用なのでフォントの埋め込みがされていない場合が一部あるそうです。

##■行った対処法
テンプレートで出力する側のファイルを、単純に消して書き直したら解決。
例）
元：「12月12日」→「1212」（一回問題になっている文字を消す）→「12月12日」（自分で月と日を再度入力）

##■大規模に文字化けが起きるときは、Googleドライブで解消できるみたいです。
参考URl:http://uxmilk.jp/45339
pythonでCUIの2Dゲーム基盤

pythonを勉強し始めて半年ほど経ったので書きました。
大学の課題でC言語とかで宝探しゲームとか作らされるやつです。
WASD移動でX座標とY座標それぞれ動きます。

python3です！

<img width="189" alt="スクリーンショット 2017-12-18 15.52.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/160607/819ca6fb-29bd-88ca-5521-7c1dbff8dd63.png">


```python3:maze.py
field = [
    ["-","-","-","-","-"],
    ["-","-","-","-","-"],
    ["-","-","-","-","-"],
    ["-","-","-","-","-"],
    ["-","-","-","-","-"]
]
p_x = 1
p_y = 1

def ref():
    field[p_y][p_x] = '-'

def draw():
    field[p_y][p_x] = '*'

def move(command):
    global p_x
    global p_y
    if command == 'w':
        if p_y > 0:
            ref()
            p_y -= 1
            draw()
        else:
            pass
    elif command == 's':
        if p_y < 4:
            ref()
            p_y += 1
            draw()
        else:
            pass
    elif command == 'a':
        if p_x > 0:
            ref()
            p_x -= 1
            draw()
        else:
            pass
    elif command == 'd':
        if p_x < 4:
            ref()
            p_x += 1
            draw()
        else:
            pass

if __name__ == '__main__':
    draw()
    while True:
        for i in field:
            for j in i:
                print(j, end="")
            print("")
        print("======")
        print('up:w left:a down:s right:d')
        key = input('>> ')
        move(key)
```
PHPでbase64から画像ファイル化

# 概要
大学の授業でグループワークがあって, base64で送られてきた画像を保存することがあったので, その方法.

## やり方
1. `base64_decode()`でデコード
2. 拡張子は, MIMEタイプから判断させるか, `/`区切りの文字列から得る
3. あとは適当に保存

## サンプル
```php
<?php
$data = file_get_contents('profile.jpg');
$data = base64_encode($data); // これが送られてきたと仮定

$data = base64_decode($data);

// PHP 5.3.0 ~
$mime_type = finfo_buffer(finfo_open(), $data, FILEINFO_MIME_TYPE);
var_dump($mime_type); // string(10) "image/jpeg"

// PHP 7.2.0 ~
$type = finfo_buffer(finfo_open(), $data, FILEINFO_EXTENSION);
var_dump($type); // string(17) "jpeg/jpg/jpe/jfif"
```

## まとめ
- `base64_decode()`して`finfo_buffer()`を使う
- オプションは`FILEINFO_MIME_TYPE`でMIMEタイプからゴニョゴニョして拡張子を判定
- PHP 7.2.0以上なら`FILEINFO_EXTENSION`で拡張子が得られる
SwiftLint でカスタムルールを作成する

小ネタですが、SwiftLint でカスタムルールを作成したときのことを書きます。

#背景
SwiftLint は Swift の静的解析ツールでチーム開発をする際にコードフォーマットを揃える手助けをしてくれます。うまく設定すれば、コードレビューの時に、チームのコーディング規約に沿っているかをレビューしなくて済むようになると思うので、私がとても注目しているツールの一つです。

https://github.com/realm/SwiftLint

![SwiftLint.png](https://qiita-image-store.s3.amazonaws.com/0/214356/90854c35-f294-49ac-4f4d-49a26c52195c.png)


先日、あるバグを一時回避するために「`UITableViewDelegate` の `estimatedHeightForHeaderInSection` をこのクラスで実装するのは一時禁止しよう」という話になりました。そこで、SwiftLint のカスタムルールを試してみました。

#やり方
基本的には SwiftLint の設定ファイルを編集するだけです。バグの詳細を説明すると、本題から逸れてしまうので「`SampleClass` の `estimatedHeightForHeaderInSection` の実装禁止」というルールを作成するとします。

##.swiftlint.yml
プロジェクトルートにある .swiftlint.yml を編集します。

```
#　Custom rules
custom_rules:
    sampleclass_estimatedheightforheaderinsection_bug:
        included: "SampleClass.swift"
        name: "SampleClass estimatedHeightForHeaderInSection"
        regex: "(estimatedHeightForHeaderInSection)"
        match_kinds:
            - identifier
        message: "SampleClass で estimatedHeightForHeaderInSection を実装しないで下さい"
        severity: error
```

では、各行の説明をしていきます。

```
#　Custom rules
custom_rules:
```

カスタムルールのセクションがここからスタートします。この後に複数ルールを設定することが可能です。
ちなみに'#'はコメント行です。

```
    sampleclass_estimatedheightforheaderinsection_bug:
```

ルールの ID です。できるだけ分かりやすい名前をつけておきます。

```
        included: "SampleClass.swift"
```

ルールを適用するファイルを指定したい場合はこのように指定します。

```
        name: "SampleClass estimatedHeightForHeaderInSection"
```

ルールに違反した時に出るメッセージのタイトルになります。Xcode 上では "XXX Violation" と表示されるので、ユーザー（ディベロッパー）が分かりやすいタイトルをつけます。

```
        regex: "(estimatedHeightForHeaderInSection)"
```

ルール本体の正規表現です。正規表現の得意な人なら、様々なルールが作成できると思います。

```
        match_kinds:
            - identifier
```

ルールを適用する対象を設定できます。何も指定しないと、コード全体でコメントも含まれてしまうので、このように identifier で絞っています。その他、どのようなものが指定できるかは[公式ドキュメント](https://github.com/realm/SwiftLint#defining-custom-rules)を参照するのが良いと思います。

```
        message: "SampleClass で estimatedHeightForHeaderInSection を実装しないで下さい"
```

ルールに違反した時に出るメッセージの詳細部分です。Xcode 上に表示されるので、他の人にもよく分かるように詳細を書きます。修正の方法まで含めることができれば、完璧でしょう。

```
        severity: error
```

`error` にすると、ルールに違反した時にビルドエラーになります。`warning` にすると、やはり表現が弱いので、他の warning などもあれば、無視されて埋もれてしまう可能性もあります。これは、というルールはビシッと `error` にしてしまった方が良いと思います。

##エラー表示
.swiftlint.yml を保存してビルドをすると、こんな感じでエラーが表示されます。

![SwiftLintCustomRuleResult.png](https://qiita-image-store.s3.amazonaws.com/0/214356/47ae0719-1f91-f5fa-19f8-baa827219bcc.png)


#まとめ
正規表現さえ書ければ、かなり簡単にルールが作成できます。また、ビルド時にルールが適用され、インラインでエラーが表示されるので、ディベロッパーフレンドリーです。

#参考文献
Defining Custom Rules
https://github.com/realm/SwiftLint#defining-custom-rules

SwiftLint の導入方法
https://qiita.com/OSR108/items/4b23b13bd23feada1921

カスタムルールの作成方法
https://qiita.com/shobyshoby/items/586de847169093bfe47d
Project Euler Q47 【異なる素因数】

Project Eulerをワンライナーで解いてみる。
間違っていたらコメントください。


## 問題
それぞれ$2$つの異なる素因数を持つ連続する$2$つの数が最初に現れるのは:

$14 = 2 × 7$
$15 = 3 × 5$

それぞれ$3$つの異なる素因数を持つ連続する$3$つの数が最初に現れるのは:

$644 = 2^2 × 7 × 23$
$645 = 3 × 5 × 43$
$646 = 2 × 17 × 19$

最初に現れるそれぞれ$4$つの異なる素因数を持つ連続する$4$つの数を求めよ. その最初の数はいくつか?

## 解答

```bash
seq 999999 |
factor |
awk '{delete a;for(i=2;i<=NF;i++){a[$i]=1};if(length(a)==4){print $0}}' |
awk '{print $1*1,$1+1,$1+2,$1+3}' |
factor |
awk '{delete a;for(i=2;i<=NF;i++){a[$i]=1};if(length(a)==4){print $0}}' |
awk '{print $1*1}' |
sort -k1,1n |
uniq -c |
awk '$1==4{print $2-3}' |
head -1
134043
```

最初は$134046$と誤答した。$n,n+1,n+2,n+3$を考えたときに、$134046$は$134043$から$134046$に一度ずつ登場するのだから$134046$が$4$回登場する。
つまり先頭は$134043$である。
ということに気付かなかった。悔しい。

## 答え合わせ
こちらのサイト様と一致していればOKとした。
http://kingyojima.net/pje/047.html
Android Studioのプロキシ設定

#Android Studioのプロキシ設定
だいぶ引っかかってしまったので備忘録。

プロキシ設定
**ファイル -> 設定 -> 外観＆振る舞い -> システム設定 -> HTTPプロキシー**

上記で設定することでHTTP通信はクリアされる。

しかし、kotlinのアップデートなどHTTPSでダウンロードしてくる必要がある場合には上記だけではだめだった。

HTTP通信およびHTTP通信ともにクリアするには、**gradle.properties**に両方のプロキシ設定を追加する。

```
# HTTP通信プロキシ設定
systemProp.http.proxyHost=ホスト名
systemProp.http.proxyPort=ポート

# HTTPS通信プロキシ設定
systemProp.https.proxyHost=ホスト名
systemProp.https.proxyPort=ポート
```

# 参考サイト様
[Android Studio KotlinでGradleのプロキシエラーの対処法](http://www.takemisousaku.com/?p=1200)
HTTPSでなくHTTPでダウンロードしてくることもできるらしい
[社内プロキシ環境でAndroid StudioのGradleエラー](http://infinite-trouble.seesaa.net/article/443029044.html)
systemd-nspawnのset-limitでquota設定

[systemd-nspawn Advent Calendar 2017](https://qiita.com/advent-calendar/2017/systemd-nspawn) 18日目の記事です。

systemd-nspawnでbtrs上にコンテナを置いている場合はクォータを使うことができます。

```bash
machinectl set-limit ubuntu1 2G
```

こんな感じで制限します。

```bash
# サブボリューム確認
btrfs subvolume list -p /var/lib/machines 

# 使用状況確認
btrfs qgroup show --si /var/lib/machines
```
vue.jsのコンポーネント集「Element」を使ってマルチプルセレクトを実装する

# マルチプルセレクト何を使う？
マルチプルセレクトとは簡単に言うと複数選択可能なセレクトボックスです。
意外とお客様の求めるUI上必要なことが多く、今までも何度か要望に応えて参りました。
大体jQueryのマルチプルセレクトを使っていたのですが、なんとなく味気ない。

●jQueryマルチプルセレクトのデモ
　https://webkaru.net/jquery-plugin/sources/multiple-select/demo.html

フロントをvue.jsで開発している時に、お客様から
「このセレクトボックス複数選択したい」との要望。あ〜、またか。って感じで、
ちょこっと調べたところ、Vue.js 2.0ベースのコンポーネントライブラリの「Element」が
便利そうなので、使ってみました。

# 導入方法
●インストール
`npm i element-ui -S`

●main.jsにロケールをセットして読み込み

```javascript:main.jsに追記
import ElementUI from 'element-ui'
import locale from 'element-ui/lib/locale/lang/ja'
import 'element-ui/lib/theme-default/index.css'

Vue.use(ElementUI, {locale})
```
※詳しくはhttp://element.eleme.io/#/en-US
のComponentからInstallation、Quick startあたりを参照。
ロケールについてはInternationalizationに書いてある。
#もう使えちゃうマルチプルセレクト
●今回は以下の「Basic multiple select」を使用
http://element.eleme.io/#/en-US/component/select
あ、pug使っているので、適宜読み替えてください。
公式のテンプレートがhtmlなのでそっちを見るか。。

```pug:簡素化した実際のコード.pug
el-select(v-model="shopIds" multiple)
  el-option(v-for="shop in shops" v-bind:key="shop.id" v-bind:value="shop.id")
```

```javascript:簡素化した実際のコード.js
data () {
    return {
        shopIds: []
    }
}
※shopsの中は店の情報の配列
```
こんな感じの画面ができて、選択したshop.idがshopIdsに格納される。
![スクリーンショット 2017-12-18 14.54.27.png](https://qiita-image-store.s3.amazonaws.com/0/221920/245058ba-cdd1-a075-44c2-01acc26531ec.png)


#他にも
とにかくUIのデザイン部分で悩む時間がなくなるだけでかなりありがたい。
一般的に使う他のフロントのフレームワークでカバーできる部分も多いのですが、
私がとりあえず気になったり、使ったりしたもの。
・InputNumber(数字を入力させる場合)
http://element.eleme.io/#/en-US/component/input-number
・DatePicker(日付を入力させる場合)
http://element.eleme.io/#/en-US/component/date-picker
・Rate（星マークで評価させたい場合）
http://element.eleme.io/#/en-US/component/rate
・スイッチ
http://element.eleme.io/#/en-US/component/switch

#disabled,placeholderが効かない
あんまり突っ込んで調べてないのですが、公式通りに実装したつもりでも
disabled,placeholderが効かないことがありました。
マルチプルセレクトはinput使っているので以下のjsにdisabledとplaceholderを追記
node_modules/element-ui/lib/input.js

```javascript:node_modules/element-ui/lib/input.jsのdomprops.js
domProps: {
  "value": _vm.currentValue,
  "placeholder":_vm.placeholder,
  "disabled":_vm.disabled
},
```
[javascript]任意のバイト数で3点リーダー

# 今回の課題
<img width="208" alt="スクリーンショット 2017-12-18 15.13.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/163415/905fc311-7320-6170-a451-54bdb988a734.png">
この画像のように幅が決まってる要素の中で大量のテキストが書かれている場合にこれを3行とか4行とかで末尾に「...」と三点リーダーがつくようにしたい。

## 方法
3行とか4行にするのであればテキストのfont-sizeやらline-heightやらを計算して高さを取得し、
どーのこーのしようと思ったが、文字のバイト数で判断すればいいのではということになった。

## コード
HTML

```.html
<div>
  <p data="">
    ここにテキストが入る。ここにテキストが入る。ここにテキストが入る。ここにテキストが入る。ここにテキストが入る。
    ここにテキストが入る。ここにテキストが入る。ここにテキストが入る。ここにテキストが入る。ここにテキストが入る。
    ここにテキストが入る。ここにテキストが入る。
  </p>
</div>
```

CSS

```.css
div {
  width: 200px;
  border: 1px solid #333;
  word-break: break-all
}
```

js

```.js
const data = document.querySelector('[data]'); //要素を取得

function getByteLength(str){ // バイトに変換してくれる関数？(ちょっと曖昧)
  str = (str==null)?"":str;
  return encodeURI(str).replace(/%../g, "*").length;
}

const a = getByteLength(data.innerText);

if (a >= 144) { //もし、バイト数が144バイト以上だったら
  data.innerText = data.innerText.substring(0, 47);  // 文字列の取得開始位置と取得終了位置を設定
  data.innerText += "..."; //最後に3点リーダー
}
```

定数dataで要素を取得し、
data.innerTextでdataの文字列を取得する。
その文字列のバイト数が144以上だったらdata.innerTextで取得してきた文字列の取得開始位置と、終了位置を設定し、最後の1文字を3点リーダーに置き換える。


## テキストの要素が複数個ある場合
テキストの要素が複数個ある場合は、上のコードでは一番最初の要素しかならない(はず。。。)
その場合はquerySelectorAllで取得し、forで回せば全部対応できる。

```.js
const data = document.querySelectorAll('[data]');

function getByteLength(str){
  str = (str==null)?"":str;
  return encodeURI(str).replace(/%../g, "*").length;
}

for (let i = 0; i < data.length; i += 1) {
  a = getByteLength(data[i].innerText);

  console.log(a);

  if (a >= 144) {
    data[i].innerText = data[i].innerText.substring(0, 47);
    data[i].innerText += "...";
  }
}

```

## まとめ
本当はcssで完結したかったが色々探してみてjsの方が早そうという結果になった。
ちなみに
text-overflow: ellipsis;とline-clamp: 3;の複数行対応のcssのみで完結できるものもあるが、
IEとfirefoxでは使えないらしく断念しました。
3. drbd8.9でサーバーリプレース対応

構築の情報はよく見かけるが、サーバーリプレース対応が見かけなかった。

## 通常Primaryをリプレースすることになった場合

* proxmox55 : 通常Primary（リプレースしたい）
* proxmox56 : 通常Secondary
* 通常Primaryをリプレースすることになった場合。通常Primaryを電源OFFすると以下のようにproxmox56がPrimaryになる。

![障害.png](https://qiita-image-store.s3.amazonaws.com/0/25728/6b796c9a-299b-1b3f-41f8-ac301775a431.png)

* 今の環境は[1. proxmox5(DRBD8.9+Corosync2.4+Pacemaker1.1)でHA MySQL構築をやってみた - Qiita](https://qiita.com/tukiyo3/items/93c0b06ef1c7de870d6a)の手順で構築したものとする。

## 新proxmox55にて以下実施

```sh:fdisk
fdisk /dev/vdb
n p enter enter enter
t 8e
w
```

```sh:drbd用にボリューム用意
pvcreate /dev/vdb1
vgcreate vg1 /dev/vdb1
lvcreate --name mysql-drbd --size 3.99g vg1
```

```sh:/etc/hosts
192.168.100.55 proxmox55
192.168.100.56 proxmox56
```

```sh:新proxmox55にて実施
apt update; 
apt-get install -y \
 drbd-utils pacemaker crmsh
```

```sh:新proxmox55にて実施
modprobe drbd

drbdadm create-md mysqldrbd

service drbd start
```

![overview.png](https://qiita-image-store.s3.amazonaws.com/0/25728/8de9b516-f085-8523-dcd1-a0d38853052a.png)


## 設定を転送

```sh:proxmox56から新proxmox55に設定コピー(drbd)
scp /etc/drbd.d/mysqldrbd.res root@proxmox55:/etc/drbd.d/
```

```sh:proxmox56から新proxmox55に設定コピー(corosync)
scp /etc/corosync/authkey root@proxmox55:/etc/corosync/
scp /etc/corosync/corosync.conf root@proxmox55:/etc/corosync/

scp /etc/default/corosync root@proxmox55:/etc/default/
scp -r /etc/corosync/service.d/ root@proxmox55:/etc/corosync/
```

```sh:proxmox56から新proxmox55に設定コピー(mysql)
scp -r /etc/my.cnf root@proxmox55:/etc/
```

```sh:新proxmox55にてmysqldインストール
wget https://github.com/tukiyo/mysql4.0php5.2/releases/download/debian9/opt-mysql4_4.0.30-1_amd64.deb

dpkg -i opt-mysql4_4.0.30-1_amd64.deb
```

```sh:新proxmox55にてmysqlアカウント作成(uid,gidがproxmox56と一致すること)
addgroup --system mysql

adduser --system \
 --group \
 --no-create-home \
 --home /opt/mysql \
 --shell /sbin/nologin \
 --disabled-password \
 --disabled-login \
 mysql 
```

```sh:新proxmox55にてmysqlのディレクトリ作成
mkdir -p /var/lib/mysql/
chown -R mysql:mysql /var/lib/mysql/

mkdir -p /var/run/mysqld/
chown -R mysql:mysql /var/run/mysqld/
```

```sh:新proxmox55にてcorosyncの現状確認
crm_verify -L -V
crm configure show
crm status
```

![55.png](https://qiita-image-store.s3.amazonaws.com/0/25728/d6cd25f2-f777-d602-8ea9-f673cd866efe.png)
Firebase いろいろ

### child_added問題

* child_added初期イベントで全部データを取ってしまう問題 
  * 参考: [Firebaseの"child_added"で初期呼出しをスキップする方法](https://qiita.com/flexfirm/items/12a6758d07e78b0f81c8)

``` javascript
const now = new Date().getTime()
ref.orderByChild("created_at").startAt(now).on("child_added", snap => {
  console.log(snap.val())
})
```