OmniAICreator/Qiita-1.07M huggingface dataset:
AEのモーショングラフィックスをJsonで出力してReactで表示する

#はじめに
この記事は、AEのモーショングラフィックスをjsonとして出力して、Reactで表示する記事です。

なぜReactを使用するかというと、最近のWEBブラウザはセキュリティの対策によって基本的にサーバーを立てなければ非同期通信が行えないようになっており、HTML/CSSのみのような静的な環境だとエラーが表示されてしまうからです。

```
Access to XMLHttpRequest at 'test.json' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
//こんな感じのエラー
```

詳しくは>[ここ](https://yukimonkey.com/fix-error/cros1/)

つまり、サーバーを立てなければ、Jsonを使ったアニメーションを見ることすらできないということです。

また、ReactのLottieは導入が非常に簡単で、簡潔に実装することができます。

使うものは、

- AfterEffect
- bodymovin
- React v16.12.0
- @crello/react-lottie v0.0.7

##注意事項
BodymovinがJsonとして出力できる範囲は限られています。
一度チュートリアル動画を視聴した後に作ったほうが良いと思います。
[Wow.. You can Export Adobe After Effects Animations as SVG! Here's how.](https://www.youtube.com/watch?v=h8tInajwIHo)

|  | 対応状況 |
|:-:|:-:|
|  詳細 | [Supported After Effects](https://airbnb.io/lottie/#/supported-features)  |

[参考](https://qiita.com/17genai/items/37e988d0f68ffe6b44ef)


#AEでのモーショングラフィックス

AEでのモーショングラフィックスは友達に任せたので、やり方は知りません。
モーショングラフィックスをどのようにJsonとして出力するかというと、Bodymovinというプラグインを使用します。


1. [Adobeアドオン](https://exchange.adobe.com/creativecloud.details.12557.html#.WTydMMbANP0)からBodymovinをインストール

2. このままJSONを書き出すとエラーが出力されてしまうので、
**[ファイル]** > **[環境設定]** > **[スクリプトとエクスプレッション]**　> 
**[スクリプトによるファイルへの書き込みとネットワークへのアクセスを許可]**に**チェック**を入れる

3. **[ウィンドウ]** > **[拡張機能]** > **[Bodymovin]**をクリックして、コンポジションを保存する場所を選んで、**Render**をクリック。
4. するとJSONファイルが生成される

#ReactでJsonを表示する。
ここは最新の情報が少なかったり、``react-lottie``が混在(派生?)しているのかわかりませんが、地味にはまりました。

##0. テスト
[LottiePreview](https://lottiefiles.com/preview)に出力したjsonファイルをアップロードすることで、出力されたjsonファイルのアニメーションを簡単に見ることができます。

##1. [@crello/react-lottie](https://www.npmjs.com/package/@crello/react-lottie)
現状だと、[@crello/react-lottie](https://www.npmjs.com/package/@crello/react-lottie)が個人的に良いと思います。というか、普通の``react-lottie``だと**バージョンによってはエラーが出力されます**
 
**ここ>[github-issue](https://github.com/chenqingspring/react-lottie/issues/100)**

```
yarn add @crello/react-lottie 

npm install @crello/react-lottie
```

##2. importの仕方
基本的には、[@crello/react-lottie](https://www.npmjs.com/package/@crello/react-lottieLottie)のUsageに従えばいいはずです。

```React
import { Lottie } from '@crello/react-lottie'
//Lottieコンポーネント
import jsonData from './myAwesomeAnimation.json'
//jsonファイルのインポート
```
##3.Jsonを表示させる!!!!

`react-lottie`ではpropsに'options'を使っていますが、
**@crello/react-lottieではconfigです!!!!(重要)**

```React
export default class App extends Component{
  render(){
    const defaultOptions={
      loop: true,
      autoplay: true, 
      animationData: jsonData,
    }
    return(
        <>
          <h1>Lottie</h1>
          <Lottie config={defaultOptions}/>
        </>
      );
  }
}
```
| プロパティ|引数|
|:-:|:-:|
| loop  |  booleanでループさせるか/数値でループする回数 |
|  autoplay  |  読み込み後の自動再生 |
|  animationData |  アニメーションさせるデータ(JSON) |
|  詳細 |  [@crello/react-lottie](https://www.npmjs.com/package/@crello/react-lottie) |

#おわりに
リッチなWEBを作成できそうですか？
ReactNativeでも使えるそうなので、興味があればやってみてください！
タスクランナー mask のススメ


## これは何?

この記事は、[FOLIO Advent calendar 2019](https://qiita.com/advent-calendar/2019/folio-sec) の21日目の記事です。
20日目は、[sachiohappy08](https://qiita.com/sachiohappy08)さんの[現役編集者がWEBエンジニアにお伝えしたい、出版業界と印税のお話](https://note.com/editor_sachio/n/n71c2313eac22)でした。
22日目は、[k_masa777](https://qiita.com/k_masa777)さんの[苦しんだScopedStorageについて](https://note.com/m_kikuchi777/n/nae3a98d43d8d)です。

:performing_arts: [jakedeichert/mask](https://github.com/jakedeichert/mask) を使ってみて、開発が捗ったので他の人に勧めたいと思ったので、書いてみました。

## おすすめする理由

弊社はマイクロサービスを採用しているため、複数のレポジトリを同時に見る必要があったりします。
その際に、各ディレクトリを移動することなくマイクロサービスのレポジトリのタスクランナーを扱ったり、ミドルウェアをdockerで集約したりしたい時に、自分だけのタスクランナーとしてmarkdownで書かれたタスクの定義を実行できるので、各サービスを汚さずに上手く扱えるので、開発が捗ります。

## 使い方

### install

maskはRustで書かれているので、Rustのビルドツール兼パッケージマネージャーである `cargo` からインストールします。

```shell
cargo install mask
```
もちろん、githubのリリースからダウンロードしてPATHを通して利用することも出来ます。

updateする際は、自分は神経質ではないので、サクッと下記のコマンドで最新版をインストールしてしまいます。

```shell
cargo install mask --force
```

### global maskfile.md

https://github.com/jakedeichert/mask#running-mask-with-a-different-maskfile


この例のように

```shell
~/dev/maskfile.md
```

みたいなのを置いておいて

```shell
mask --maskfile ~/dev/maskfile.md 
```

をaliasにしておけば、各プロジェクトのディレクトリに移動することなく自分だけのタスクを実行できるようになります。

コマンド引数やフラグも用意されているので、各ツールのコマンドラインオプションに併せると、自分だけのコマンドを作ることが出来ます

### 使ってみた

https://github.com/grimrose/cloud-build-slack-notifications/blob/master/maskfile.md


仮にプロジェクト配下に `maskfile.md` を置きたいが、gitで管理されたくない場合は、globalのgitignoreで `maskfile.md` を除外するようにしておけばよいかと思います。

実態は単なるmarkdownファイルなので、よっぽどのことが無い限り、他に影響することは無いとは思います。

例に挙げたプロジェクトでは、Scalaのsbt、Nodeのyarn、GCPのgcloudといった複数のタスクランナーやCLIをうまく扱う必要があったので、maskを導入しました。

一つのタスクから他のタスクを呼ぶのも可能なので、タスクの依存関係も分かりやすくなります。

## おわりに

いかがだったでしょうか。
タスクの定義をmarkdownで記載することで、ドキュメントとしても分かりやすくなりますし、markdownを使い慣れている人であれば、導入も簡単なのではと思います。

ちょっとしたshell scriptやMakefileを書こうかなと思った時に思い出してもらえると幸いです。
Amazon Corretto11 インストール

久しぶりのQiita投稿です。（リハビリ投稿ですｗ）

新しいPCを買ったので、**早速セットアップしよう！**と思ったんですが、
せっかくなので、セットアップ手順を書いてみようかと思います。（何回かに分けて）
今回は**「JDK」**（Java Development Kit）を入れていきます。

## JDK、何にする？問題
JDKを入れる前に、**どのJDKを使おう？**という問題。

以前、Javaのイベントで発表していた「@yamadamn」さんのスライドを参照させて頂きます。
> @yamadamn さん
>https://www.slideshare.net/TakahiroYamada3/tasting-openjdk-distribution-201907-157792196?>ref=https://cards-frame.twitter.com/i/cards/tfw/v1/uc/1154337033382313984
>**▶ 「これからのJDK/JVM 何を選ぶ？どう選ぶ？」**

色々ありますね…。
自分の環境で何を使おうか、と考えたんですが、今回は**「Amazon Corretto」**（アマゾン コレット）を入れることにしました。

**【Amazon Corretto】**
https://docs.aws.amazon.com/corretto/index.html

マルチプラットフォーム対応だし、作ったJavaアプリケーションは今後AWS環境にデプロイして運用しようと考えておりまして。作成したアプリをAWS環境に載せることを考えたら、Amazonさんが出しているJDKで開発すれば間違いないと思った次第です。
（現場で使った経験もあるので、それが決め手でもありますｗ）

**2019年12月**現在で、***Amazon Corretto 8*** と***Amazon Corretto 11***があるんですが、ここはもちろん新しい方。***「Amazon Corretto 11」***を使用します。

**▶ Amazon Corretto 11 とは**
https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-11-ug/what-is-corretto-11.html


**＜セットアップ手順＞**
１） 早速、ダウンロードリンクに飛びます
https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-11-ug/downloads-list.html


２） Windows版をダウンロード（Linux版、Mac OS版もありますので、適宜）
https://d3pxv6yz143wms.cloudfront.net/11.0.3.7.1/amazon-corretto-11.0.3.7.1-1-windows-x64.msi
ダウンロードしたら、インストール。すぐ終わります。
インストール後、Cドライブ直下にインストールしたJDKが配置されています。
![jdkインストール後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173505/1588b1e1-5ed6-e671-38d4-29f0df9e5bdc.png)

３） システム環境変数の設定は不要！
インストール後は特に何も設定いりませんでした。システム環境変数を確認すると、すでにPathも通ってました。
![システム環境変数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173505/1f076d2c-d85b-9480-7db4-42d469cf6122.png)

４） コマンドプロンプトからJavaのバージョン確認
java -version
![コマンドプロンプトで確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173505/76b0de25-041b-bdb4-1e80-299db4fbdf32.png)

Javaのバージョンが表示されているので、インストール完了です。

## まとめ
今回はAmazon Correttoをインストールしましたが、他のOpenJDKやOracleJDKもインストール方法はほぼ変わらないです。作業時間は、ズバリ**「5分！」**ですｗ

####ダウンロードサイトでダウンロード→インストール→システム環境変数の設定→完了

自分はSESで色々な現場に行くのですが、まず最初にやることは***「開発環境のセットアップ」***
Javaエンジニアなので、現場で使う言語は***Java***。ということは、必ず毎回JDKのインストールをします。もう何回もやってますね・・・。手順は不要ですｗ

以上、あっという間に終わりました。
次回以降は、もう少し踏み込んで技術の深掘り等もしていきたいと思います。

以上、リハビリ投稿でした。
ionic ブラウザでもアプリでもQRスキャンを使用可能にする

#結論
![61757715-28a44800-ad98-11e9-9f58-555d2f187c50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368226/3dc29a18-620e-c006-fd51-682b25de1a79.png)

　**@zxing/ngx-scanner** を使用するのが良い。
URL: https://github.com/zxing-js/ngx-scanner

#なぜ@zxing/ngx-scannerを選んだか。
- ionic（Angular）で使用できるため。
- ブラウザでもアプリでも使えるようにしたかったため。
- 実はcordovaのQR ScannerというプラグインのBrowserバージョンをビルドし使用した。しかし、実機のブラウザでは動かないという現象が起きたため。
    - 理由：このプラグインのBrowserバージョンは元々開発用に開発されたもので、実際プロダクトとして使用される想定ではなかったため動作の保障はされていない。
- 時間の都合から、実装が簡単なものが良かったため。

#使い方

### インストール

```
npm i @zxing/ngx-scanner@latest --save
```

### 使用方法
- html

```html:html

<zxing-scanner class="scanner" [torch]="torchEnabled" [(device)]="currentDevice"
                   (scanSuccess)="onCodeResult($event)"
                   [tryHarder]="tryHarder" (permissionResponse)="onHasPermission($event)"
                   (camerasFound)="onCamerasFound($event)"></zxing-scanner>
```

- typescript

```typescript:typescript

    availableDevices: MediaDeviceInfo[];
    currentDevice: MediaDeviceInfo = null;
    hasDevices: boolean;
    hasPermission: boolean;
    torchEnabled = false;
    tryHarder = false;

onCamerasFound(devices: MediaDeviceInfo[]): void {
        this.availableDevices = devices;
        this.hasDevices = Boolean(devices && devices.length);
    }

// このコンポーネントを立ち上げたコンポーネントで結果を受け取るようにしている。
    onCodeResult(resultString: string) {
        this.modalController.dismiss(resultString);
    }

//カメラへのアクセス許可をチェック
    onHasPermission(has: boolean) {
        if (!has) {
//アクセスを許可してほしい旨のメッセージ等を入れる。
            this.close();
        } else {
            close();
            this.hasPermission = has;
        }
    }
```

# 参考
- https://github.com/zxing-js/ngx-scanner
Microsoft Learn 19日目

12月は、毎日 [Microsoft Learn](https://docs.microsoft.com/ja-jp/learn/) を受講していこうという記録。
※受講後に書き込むので公開に間に合わないこと多々あります(アドベントカレンダーの意味ｗ)

12/19 は
**Core Cloud Services - Azure コンピューティングオプション**
 - Azure でサーバーレス コンピューティングを試す

を受講。以下、簡易メモ。

# Core Cloud Services - Azure コンピューティングオプション
## Azure でサーバーレス コンピューティングを試す
2 つのサーバーレス コンピューティングの実装がある。
### Azure Functions
サービスを実行しているコードのみに関心があり、基になるプラットフォームやインフラストラクチャには関心がない場合は最適。
必要に応じて自動的に拡大縮小するので、需要が変化する場合、堅実な選択肢となる。
Functions は、サーバーレスコンピューティングの主要なコンポーネントだが、任意の種類のコードを実行するための一般的なコンピューティングプラットフォームでもある。
開発者のアプリのニーズに変化が生じた場合は、そのプロジェクトを非サーバーレス環境にデプロイすることができる。

### Azure Logic Apps
Azure Functions に似ている。
Functions の場合コードが実行されるが、Logic Apps の場合ビジネスシナリオを自動化するために設計され、事前定義されたロジックブロックから構築されたワークフローが実行される。
ロジックアプリを使ったワークフローはいずれも、トリガーによって起動される。
【2019年12月】GCP Associate Cloud Engineer 取得メモ

先日、Google Cloudの認定資格「Associate Cloud Engineer」を受験、無事合格しました。
入門の資格となりますが、どのように取得したかまとめました。

#はじめに
今は営業部として働いていますが、元々運用部門にいましたので、
CCNP、LPICレベル3、AWS 認定ソリューションアーキテクト等の資格を保持しています。
ネットワーク、レガシーなOS周り、クラウドについては最低限知識を持っています。

#試験の概要について
2019年12月現在、
アソシエイト認定資格・1種類
プロフェッショナル認定資格・6種類
があります。

公式サイト
https://cloud.google.com/certification/?hl=ja

プロフェッショナル認定の中で、
Professional Cloud Network Engineer
Professional Cloud Security Engineer
Professional Collaboration Engineer
は英語でのみ提供されています。
また、G Suiteも認定資格があります。


アソシエイト認定資格である「Associate Cloud Engineer」試験は
GCPの概要、コンソール画面とコマンドを使ってのスキルを基に、
GCPのマネージドサービスやソリューションを理解する、という印象を受けました。


##試験時間、費用
・時間　2時間
・費用　$125（クレジットカードのみ）

前提条件はないため基本的にどなたでも申し込みすることができます。
尚、すべて4つの中からの選択問題でした。

##申し込み方法
https://www.webassessor.com/googlecloudjp/
でアカウントを作成し、申し込みを行います。
他のベンダー資格など受験経験のある方でしたらピアソンなどと同じイメージです。
当方は大阪での受験でしたが、ピアソンより受験会場・時間の制約は多いです。

##注意点
申し込みを行うと、「Google Cloud認定試験登録確認」というメールが届きます。
**この中に「受験者承認コード」というものがあり、このメールを印刷して持参するよう、注意書きがあります。**
私は当初これを見逃していたのですが、直前にメールを確認し記載に気づき、急ぎ印刷して持参しました。
そのため受験当日の受付はスムーズにできました。
また、身分証も2種類必要なこともほかのベンダー資格と同様です。

##試験について
テストセンターのため、各自PCが用意されており、試験官の方が開始まで案内していただきました。
当方受験時はテスト後提出ボタンをクリック→合否表示→その後もクリック
しないといけないことの注意を受けました。
（試験官の方の確認作業があるということ）
結果は合否のみの表示、セクション毎の点率や取得点数は表示されません。

#勉強方法について
勉強期間は2週間ほどです。


##概要を知る
[GCPの教科書](http://www.ric.co.jp/book/contents/book_1195.html)は参考になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541506/7dd4ce3b-e545-f27e-ebc7-75b9c144ff00.png)

まずどのようなものなのかを探る、理解するために利用しました。
似てるサービスで、どのような用途の違いがあるか、表にまとめられていることも参考になりました。
gcloudの文法などもわかりやすかったです。


##公式ドキュメント
GCPはドキュメント構成が非常に上手で見やすく作られています。
Compute Engine、Google Kubernetes Engine、Cloud SQL、BigQuery 
など、試験範囲のドキュメントはしっかり読み込みました。
https://cloud.google.com/certification/guides/cloud-engineer/

##コンソールでの操作、インスタンス作成等
新しくアカウントを作成するとクレジット提供もあるので、インスタンスの作成、CloudSQLの作成や
VPCの作成、Peering接続、ファイアウォールの設定、SSH接続、権限の作成等
基本的にシステムを構築するインフラ面をしっかり理解しました。

##模擬試験
無料で受験できます。
試験となっていますが、中身はGoogleFormです。正解不正解は提出後に表示されます。
不正解の場合、どれが正解だったかも表示されます。
模擬試験の中で、どのような事を試験に求めているのかを体感できるかと思います。
https://cloud.google.com/certification/practice-exam/cloud-engineer

##合格後
最終確定結果のメールが数日後に来ます。
メールにはcredential.netでのデジタル証明書のリンクが張られています。


###デジタル証明書、バッチについて
credential.netでのアカウントを持っていなかったためこのままだと証明書、バッチのダウンロードができません。（当方の会社は資格取得の申請に証明書提出が必要なため）
サインアップのリンクがありますので、webassessorと同じメールアドレスでアカウントを作成（メール認証）し、無事に証明書のダウンロードができました。

#今後について
トップゲート社より、AppEngineとBigQueryの本がちょうど出版されていたのでこちらを購入。

[Google Cloud Platform 実践Webアプリ開発 ストーリーで学ぶGoogle App Engine](https://www.shuwasystem.co.jp/book/9784798059556.html)
[Google Cloud Platform 実践ビッグデータ分析基盤開発 ストーリーで学ぶGoogle BigQuery](https://www.shuwasystem.co.jp/book/9784798059563.html)

次回は「Professional Cloud Architect」を目指します！
GitHub Actionsを使ってGitHub PagesにReactアプリを公開する

# 背景・動機

先日、以下の記事で簡単なReactアプリを開発した話を投稿しましたが、masterへpushで簡単にデプロイしたいなと思いはじめました。
https://qiita.com/nouka/items/a4c25ce685294dc17ce3

- スマホにインストールしたGitHubクライアントアプリで、通勤中に開発したいと思った。
- GitHub Actionsの勉強のため。
- Advent Calendarのネタのため。

# 事前準備

## 1. 秘密鍵、公開鍵を生成

以下のコマンドを実行し秘密鍵と公開鍵を生成します。

```
ssh-keygen -t rsa -b 4096 -C "$(git config user.email)" -f gh-pages -N ""
```

> 参考：https://qiita.com/peaceiris/items/d401f2e5724fdcb0759d

## 2. gh-pages.pub(公開鍵)をDeploy keysに登録

生成したgh-pages.pub(公開鍵)をリポジトリの[Settings]->[Deploy keys]->[Add deploy key]から登録します。

<img width="995" alt="スクリーンショット 2019-12-19 23.48.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127338/36d38dbb-a76d-2de7-0cb7-2fc56944439b.png">


## 3. gh-pages(秘密鍵)をSecretsに登録

gh-pages(秘密鍵)はリポジトリの[Settings]->[Secrets]->[Add a new secret]から`ACTIONS_DEPLOY_KEY`という名前で登録します。

<img width="995" alt="スクリーンショット 2019-12-19 23.49.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127338/f2dbe2e0-c6ed-5418-bc60-f50dc55385ba.png">


# ワークフローを設定

リポジトリの.github/workflowsディレクトリに任意の名前のymlファイルを生成します。
今回はbuild.ymlというファイルを作成します。内容は以下の通りです。

**.github/workflows/build.ymlの内容**

```yml
# ワークフローの名前
name: Release GitHub Page

# 起動のタイミング
# 今回はmasterブランチへのpush
on:
  push:
    branches:
      - master

# ジョブの定義
jobs:
  build:
    # 実行するインスタンス
    runs-on: ubuntu-latest

    # nodeのバージョン一覧
    strategy:
      matrix:
        node-version: ['12.x']

    # 各ステップの実行
    steps:

    # チェックアウト
    - uses: actions/checkout@v1

    # 使用するnodeのバージョンを指定
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}

    # パッケージのインストールとアプリのビルド
    - name: install and build
      run: |
        npm ci
        npm run build
      env:
        CI: true

    # gh-pagesを使って公開
    - name: deploy
      uses: peaceiris/actions-gh-pages@v2
      env:
        ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }}
        PUBLISH_BRANCH: gh-pages
        PUBLISH_DIR: ./build
```

これでmasterブランチにpushすれば、ワークフローで定義した通りコンテナが起動し、アプリを公開してくれます。
GitHub Actionsを使えば、lintやユニットテストもGitHubだけで実行できそうなので、今度やってみたいと思います。
【ブレイザー？】Blazor、日本語でなんて読む？【ブレザー？】

BlazorのGitHubの[FAQ](https://github.com/aspnet/Blazor/wiki/FAQ#q-where-does-the-name-blazor-come-from)に「Q: Where does the name "Blazor" come from?」という項目があります。

内容的にはこんな感じ。

> Blazor makes heavy use of Razor, a markup syntax for HTML and C#. Browser + Razor = Blazor! When pronounced, it is also the name of a swanky jacket worn by hipsters that have excellent taste in fashion, style, and programming languages.

注目して欲しいのは、ここ。

> When pronounced, it is also the name of a swanky jacket worn by hipsters

つまり英単語の「blazer」と同じ読み方をするらしい。

発音記号的には「ˈblāzər」

---

ところ皆さんは「あのジャケット」のこと、日本語でなんて書いて、日本語でなんて読みます？

「制服って、詰襟なの？ブレザーなの？」
「ほら、ブレザーしわになるから早く着替えて！」

そう、「あのジャケット」のことを我々は「ブレザー」と書いて、日本語でもそう読みますね。

---

英語だと、発音記号的には「ˈblāzər」で、「blazer」と同じ発音をする「Blazor」

日本語だと、なんて読みましょうかね？

周りを見渡すと「ブレイザー」が多い気がします。自分も「ブレイザー」って読んでた気がします。

でも「あのジャケット」の事考えると、「ブレザー」の方が自然な気もしてきました・・・

---

こう言う場合、どう言うふうに読み方って決まるんでしょうね？


Azureってどう言う流れで「アジュール」って読まれるようになったんでしょう？ちなみに同じ綴りで[「アジュア」って読ませる曲がある](https://trysail.jp/contents/205416)みたいです。

コメント欄か、Twitterで相談しましょ！
Xamarinでアプリ開発して良かったこと悪かったこと Part2

これは Xamarin Advent Calendar 2019 の20日目の記事です。

ちなみにPart 1は[こちら](https://tech-note.hypermild.com/2017/07/12-03.html)。2017年7月ですね。
ほぼ２年半経って、自分が当該プロジェクトから離れることもあり「どうだったか」「今後も使いたいか」の総まとめをします。
（Part 1で書いたことへの追記部分だけを書きます）

# どういうプロジェクトだったか

iOS/Android向けに同じアプリを作ってきました。（受託ものです）
もともとiOS(Objective-C)なアプリとAndroid(Java)なアプリがあって、それらの「同じようなロジック部分」をBinding Library化してPCLで共通ライブラリとし、そこにXamarin.FormsをかぶせてForms製アプリ化した、という感じです。

最初に作ったプロジェクトをベースに似て非なるアプリを数種類作り、同時進行で開発＆リリースを行っていました。

中盤以降の自分の役割はプロジェクト管理や顧客窓口をしながら、Jenkinsのお守りと時々iOSやAndroidのネイティブ周りをいじる、という感じでした。今回はそういう目線が強めの記事です。

# Xamarinだから良かった点

- iOSとAndroid向けのアプリをほぼ同時にリリースし続けられました。

iOSとAndroidの両方向けのアプリ開発をネイティブ実装で進めるとどうしても担当が分かれがちです。そうなると進み具合にもバラツキが出やすくなります。基本的に画面周りはXamarin.Formsを使っているので、その部分だけでもiOSとAndroidで足並みが揃いやすいことは非常にやりやすかったです。

- ソースコードの共有率がそこそこあった

最終的には全体で5割くらいはXamarin.FormsなどC#によるiOS/Androidのソース共有ができました。元々が別アプリだったのでもっと少ないかと思ったけど案外いけました。画面系だけなら8割くらいはPCL(C#)でした。
おかげで、ある程度慣れた人であれば「誰でも触れる部分が多い」という会社組織的にはありがたい状況もできました。

# Xamarinだから良くなかった点

- アプリのファイルサイズが大きい
    - 外部ライブラリを組み込みすぎたというところもありますが、実行ファイルのサイズがなかなかヤバいことになりました。
    - リンクオプションとかProGuard(R8)とか色々と対策し、それらの効果はありましたがそれでも大きいです。
- 実行時メモリ消費量が大きい
    - アプリ内で表示する画像の量が多かったということもありますが、Formsの場合Pageで画面遷移しても結局1個のViewController、1個のActivity内ですべてやることになるので、メモリ消費量が大きいための問題も結構引きずりました。
- 起動や実行速度が遅い
    - そういうわけで少し、モッサリです。悲しい。

ある意味で向いていなかったのかもしれない、と最近は思っています。
あるいはもう少しやりようがあったのかもしれません。

# Xamarinだからツラかった点

主にネイティブ関連で苦しめられました。
この数年でストア要件の強制が厳しくなりましたよね・・・。

- iPhone Xのセーフエリア。マジでApple嫌いになるところでした。
- AndroidのtargetSdkVersion上げが強制されるのもしんどかったです。
    - 連動してSupport Library上げないといけないですし。
- 中国の地図SDKを入れたらPlayストアから怒られたり。
- クラッシュ時のスタックトレースがなぜか見づらいときがあったり

その割に、プロジェクト全体としては安定していくため「できるネイティブも分かるマン」が抜かれて「PCL(C#)書けるマン」だけになっていくのもしんどかったです。
ある意味ネイティブだけだったら起きづらい問題です。

# 次に同じような開発案件が来たらXamarinを推すか

iOSとAndroid向けにアプリを作りたい。なるほど。
たいして凝ったことしないから簡単に作れるやつで。なるほど。

ストア公開しない業務アプリとかならXamarinもいいかもなぁと思います。
クロスプラットフォームなツールでストア要件に振り回されるのは少しツラいです。

ストア公開しないなら、次は初期費用の話をしましょう。

新しめのお高いMac、そしてMSDN付きVisual Studioが開発者の人数分すでにある、もしくは即座に購入可能でしょうか。

iOS向けにアプリを作るのならどうしたってMacは必要になります。
Visual Studioの費用が問題にならないならXamarinも検討できます。

逆に言うと、社内の別プロジェクトが解散して「C#できるマン」が大量に余っている、といった特殊事情がないかぎり、MSDN付きVisual Studioをわざわざ追加購入するということは滅多にない気がします。

- MSDN付きVisual Studioが用意できない場合

Flutterでいいんじゃないですかね。
それでも開発者の半分くらいにはMacを与えてください。
あとはWindowsでAndroid向けを頑張りましょう。

もしFlutter(Dart)が技術的あるいは要員レベル的に難しいなら、変に欲張るのは諦めて普通にネイティブでいきましょう。

- MSDN付きVisual Studioが用意できる場合（or Communityがいける場合）

まだまだXamarinもいいぞ。


# まとめ

何ごとも理想とはほど遠いですね・・・。
.NEXT JAPAN 2019 2048Championshipの件について

- この記事は [\[3枚目\]Nutanix Advent Calendar 2019](https://adventar.org/calendars/4037) の 20日目です。

- ~~ネタ枠~~参加記録としてお楽しみ頂ければ幸いです


# .NEXT JAPAN

昨年までは .NEXT Tourの東京会場だったものが格上げ(?)になりました
Togetterはこっち -> [Nutanix .NEXT Japan 2019 関連ツイート](https://togetter.com/li/1405244)
(@smzkstsさん毎回ありがとう…)

# 2048 Championship

[2048 wikipedia](https://ja.wikipedia.org/wiki/2048_(%E3%82%B2%E3%83%BC%E3%83%A0)) 

パズルゲームである2048とNutanixに一体何の関係が…？と思った方は、
以下の手順を踏むと体験できます。

1. 「Nutanix Test Drive」を検索する
2. 入力フォームにあれこれ入れて"START TEST DRIVE"する
3. ログインする
4. 画面右上の「admin」-> 「Nothing To Do?」を選択する

すると遊べます。

![home2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84344/cac7114b-f345-b712-a560-31d71d0318f2.png)

![2048.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84344/5d07a250-961c-b8ec-1066-668a2f4d9917.png)

あまりに運用が簡単(シンプル)なので、やることがなくなっても
頭の体操をさせてくれるNutanixさんの心意気好き
(仕事にも遊び心って大事ですよねっ)

# 本題

.NEXT JAPANのアフターパーティでもある「after.NEXT by Nutanix Meetup」で企画されていた
2048 Championshipにその場の雰囲気と空きっ腹にキメた少しのお酒と先輩に背中を押され
私は参加したのだった。。。
![twitter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84344/5d5f6371-01b8-fcd7-c531-befd255176c2.png)

# 雰囲気と流れ

かなり広めな会場にスタンディングテーブルをが配置されたところから仕切られた一角に
丸テーブルとノートPCの山…そうそこがまさかの予選会場だったのでした。

※この辺見てもらえればわかります。
https://twitter.com/NutanixJapan/status/1172437845681659906
https://twitter.com/NutanixJapan/status/1172440091563683843
https://twitter.com/NutanixJapan/status/1172446636745715719

あ…限定キットカットもらいそこねた…

# 参戦記

参加者で2048を競うのですが実は1つのルールがありました。
そう制限時間です。

予選、準決勝:1min
決勝:3min

予選：丸テーブルで参加した人の中から大体1000点出せた人挙手 -> 準決勝へ
～ここから登壇して衆人環境～
準決勝:4人1組x4組(うち1組はNTCの方々の魔窟) -> 1位のみ決勝へ
決勝:勝ち上がった4人での戦い

決勝までの大体のボーダーラインですが、
予選:1000点～
準決勝:2000点～2500点(3000点出てたかも)
だったと思います。

で、緊張と(お酒による)手の震えもありぶっちゃけ予選、準決勝とも
一番点数低かったような気がします。
※みんななんであんなに1min勝負うまいんだろうか…

結局決勝でなんだかんだ優勝できたんですが、
3minあったことで最初こそリスク背負って飛ばしたものの、
ある程度盤面が出たら少し考えながら進めたのが良かったのかなと思います。
※512作ったあたりで歓声が湧いたのにうっすら気がついたようなわからなかったような

最終的に5600点くらいだったと思います。
なお優勝商品(選択式)として[Google Nest Hub](https://store.google.com/jp/product/google_nest_hub)をもらえました。
他にはAlexaとかあったような気がします。
賞品はIoT系に寄せてたみたいです。(Xi IoTにちなんでたんですよね？)

※この記事書いてるときにTest Driveで試しにもっかい同じ条件(1min、3min)でやってみました。

- [1min]
![2048_1min.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84344/fbbee32c-d7f5-4515-0890-877febc9f8b3.png)

- [3min]
![2048_3min.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84344/aa1ba6f6-2e12-778e-b46c-5f99373dd423.png)

※ちゃんとNest Hubさんに測ってもらいました。不正はなかった

# Test Driveについて

制限時間付きではあるものの、無償で利用させてもらえる環境としてはかなり優秀ではないかと。
CVMは流石に触れないですが、Prism(Element)の操作感を掴むには問題ないので
導入を検討されてる方は一度触ってみると良いと思います。
※某WebClientもHTML5化されて良くなってきましたが、個人的にはUIの使い勝手などでPrismに軍配が上がるかなと。(あくまで個人の意見です)

ちなみにTest Driveでデプロイされているのは、
- CVM
- loadrunner1(負荷試験ツールのあれでいいのかな？)
- VMx2
でした。

ぶっちゃけ2048だけだとアレだなって思い、
CVMログインしてdiagnosticsたたけないかなーって思いましたが流石に無理のようで…
あの夏の抽出件数を僕はまだ忘れていない

これから読む君へ、さきにひとつ謝っておこう。
華々しい本番やらかしの告発が連なるこのカレンダーにおいて
今夜語る事件はあまりにも些細で地味なものだ。

そうさ、些細だが
1円を笑うものが1円に泣くように
1行を笑うものは1行に泣く。

データってやつに裏切られたくなかったら
しっかり両目を開いて見つめるんだ。
むろん、ブルーカット眼鏡も忘れずにな！

※年数がたっていて記憶がおぼろげなのをいいことに
　だいぶフィクション感てんこ盛りでお送りしたいと思います。そして小説風に便乗する輩。

#あの夏
当時ぼくは零細SESの中でも、体育会系の空気を馬鹿にしきっていたので
逆に年かさのオジサンたちからは、素行の悪い輩だと目をつけられていた。

僻地での開発案件でけだるく過ごした後、あたらしく配属された常駐現場は
やる気のないやつはこれでもやってろと言わんばかりに
初めて運用の現場での契約となった。


斜にフーンと構えるぼくの胸算用とは別に
出迎えたチームメンバーとリーダーは少なからず期待をしてくれたようで
いかにもサーフィンが好きそうな日焼けしたパリピ主任と
いかにもいい人で眼鏡七三のサラリーマンパイセンと
スクエアな雰囲気でキレを感じさせるギークなリーダと
これまたいかにもいい人で気の弱そうないぢられメンバーくんetc.に
「開発経験者なんだってね！？」と温かな眼差しで迎えられた。



###リーダ「ここはちょっと特殊な現場でね。ふつうはこんなにアクロバティックなことはしないんだけど」
　　　

業務内容は顧客データの保守運用なのだが
運用は初なので、ぼくには本来のオペレーションがどうあるべきかわからない。
ただただ本番データに触るのは、嫌な汗をかくなぁ…と
その時のぼくは呑気に遠い目をしていた。


普段の作業はこうだ。
既存の検証済みクエリを使ってデータの抽出または更新を行う。
実行したクエリごとに必ず抽出結果は残し、
連続したクエリは都度結果を確認しながら作業を完了させていた。
担当部署から作業依頼が来れば対応するし、
定常で月次週次で行う作業もする。
IR用の集計データなんかも、その一つだ。

データの更新に関していえば、絶対にダブルチェック・2者でのオペレーションが必須だった。
問題は抽出だったが、こちらも基本的にはダブルチェック…だったんじゃないかな。


時々、既存のクエリでは補いきれないからと
新規のクエリの建付けをしなければならない時があった。
そういう時は数日かけて、設計⇒製造⇒検証を行って初めて本番で使用…と言いたいんだが
組んでいたのは結局本番DB上だったような気がする。
テストデータは既存に触れないから、上流のチームに調整してテストデータを挿入してもらう。

この時点でけっこう怖いな？


建付けたクエリは当然レビューを受ける。
ぼくの場合はパリピ主任がお目つけ役だ。
よく深夜作業をしながらモテ自慢を挟んでくる以外は気のいい主任だし、
若いから、締め付けもゆるくて仕事がしやすい。
主任は主任で抱えている作業も多く、
ぼくが早々に自走できるようになったのでずいぶん信頼したのか
うるさく言われないのは大変に快適な環境だった。
まぁそんな期待に応えられなかったのは大変申し訳ないんだが。


ある日、お客様データの中から月次の通知かなにかの送信先を抽出したが
3件間違って送られていたという障害報告が入った。


本番DBで流したクエリの誤りを見つけて
本来抽出されるべきだった3名を改めて抽出しなくてはならない。

当然ながら緊急対応で、クエリを建付け、クエリのレビューも受け…たよな？
あれ？記憶ないぞ？

まぁカチャカチャとSQLを組み立て、ぼくは当該顧客の特定に急いだ。
終電まで小一時間というところで、
想定件数通りの3名を抽出したぼくは
パリピ主任に元気よく報告したんだ。

ぼく「クエリOKです！抽出できましたよ！」
主任「よっしゃ、3件？」
ぼく「3件！」


たしかそのとき、主任は主任で作業を抱えていたんだ。
緊急対応が無事済み、重い仕事をそれぞれ仕上げてスッキリしたぼくたちは
現場近くのBarでわずかな時間ながら祝杯をあげた。
忘れもしない。
主任は、よく対応してくれたと言って、ぼくのビールも気前よく払ってくれたんだ。



翌日、抽出作業には続きがあった。
昨晩抽出した3件の顧客はその時点で担当部署に送信され、
速やかに、つつがなく、フォローの対応がされていたはずだ。


報告作業用だったろうか、
改めて抽出結果の3件のレコードを、まじまじと見ていたんだ。


・・・

・・・？

？！



1行…値の違うレコードが混ざってる！！！！！！！！！?





##惨劇はなぜおこってしまったのか


あれ？
昨日、ぼくってば確認したよね
主任と一緒に

「３件？」
「３件！」

そう、件数だけな。

まともに情報系の勉強してきた人なら当たり前の話さ。
クエリの検証に件数のみの一致では足りないなんてさ。

でも、でもだよ。

何十万何百万レコードを登録されてるわけじゃないか。
そんなさ、ぴったりさ、たった3件だけ
それも3件のうち1件だけが別物にすり替わって抽出されるもんだろうか？

###抽出されるもんなんだよな！現実に
全身から血の気が引くという言葉の意味を、校長先生の話以外で感じたのはこの時ばかりだったよ。


障害発生からのお詫び対応での抽出失敗……！
最悪のタイミングでSQLの奥深さを思い知ったぼくなのだった。

##二度と惨劇を起こさないためにどうしたのか


お気づきの方も多いと思うが、
日常的にオペレーションが効率重視で危うい運用ではあったんだとは思う。
まぁ、日本の金融・保険業界あたりでは打ち首獄門レベルで許されない間違いも
他業種では案外ゆるかったりもするし、
リスクも挽回のコストが払えるんならむしろ許容っていう外資のスタンスと思えば
起ったことは、自分が思うほど組織のダメージには、なってなかったのかもしれない。

それでも開発だけやってきて、本番コワイと思ってドナドナされてきた青少年には
ちょっと刺激の強いトラウマだったんだ。とらうま。


現場はどうあれ、
技術者的には検証は念入りに。
というかデータを保証できるだけの勘所を無駄なく効率的に検証するに越したことはない。


まぁパリピ主任のような口頭確認のみでダブルチェックとは呼べないあれも、
自分がその立場の時には気を付けような。
という雑な反省ですまない。


データというのは実に奥深いし、舐めてると痛い目を見るのだ。
そんな気持ちが文章量には反比例するだろうけども、
少しでも伝わったら僕はうれしい。
OpenShiftのBuildConfig

#はじめに
OpenLibertyのOpenShiftでの実行ガイドでは Buildの部分は oc のコマンドでしていたのでその部分を BuildConfigでできるようにします。

# yamlファイル作成

実行したい内容

```shell:oc
sudo docker pull openliberty/open-liberty:latest
oc login
oc new-project liberty
oc registry login --skip-check
sudo docker login -u `oc whoami` -p `oc whoami -t` `oc registry info`
sudo docker tag openliberty/open-liberty:latest docker-registry.default.svc:5000/liberty/openliberty:latest
sudo docker push docker-registry.default.svc:5000/liberty/openliberty:latest
oc get is

```


Docker Login用のsecret作成 (dockerログインしている前提でないと buildでエラーになるようです)

```shell:create-docker-login-secret
sudo docker login -u `oc whoami` -p `oc whoami -t` `oc registry info`
oc create secret generic dockerhub --from-file=.dockerconfigjson=$HOME/.docker/config.json --type=kubernetes.io/dockerconfigjson
```

dockerの処理を BuildConfigにする

```yaml:build.yaml
kind: "BuildConfig"
apiVersion: "v1"
metadata:
  name: "openliberty-build" 
spec:
  runPolicy: "Serial" 
  strategy:
    type: "Docker"
    dockerStrategy:
      from:
        kind: "DockerImage"
        name: "openliberty/open-liberty:latest"
  source:
    dockerfile: "FROM openliberty/open-liberty:latest" 
  output: 
    to:
      kind: "DockerImage"
      name: "docker-registry.default.svc:5000/liberty/openliberty:latest"
    pushSecret:
      name: "dockerhub"
```

oc login済みの projectに Buildを作成

```shell:oc
oc create -f build.yaml
```


Webコンソールから Buildができるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262366/70d48986-dcdb-61bb-0bdc-f87dc497a55c.png)


#参考
[Build Inputs](https://docs.openshift.com/container-platform/3.11/dev_guide/builds/build_inputs.html)
[Deploying microservices to OpenShift](https://openliberty.io/guides/cloud-openshift.html)
【Rails5.2.4】rails newしたらsass-railsとsprocketsのバージョンが合わなくてエラー発生

## はじめに
Rails+Vue.jsの環境構築をしていたときに発生した単純なエラーについて解決法を残します。

## 環境
```yaml
OS: macOS Catalina 10.15.1
zsh: 5.7.1
Ruby: 2.6.5
Rails: 5.2.4.1
```
## エラー内容

```shell
$ rails new
...略
Resolving dependencies....
Bundler could not find compatible versions for gem "sprockets":
  In snapshot (Gemfile.lock):
    sprockets (= 4.0.0)

  In Gemfile:
    sass-rails (~> 5.0) was resolved to 5.1.0, which depends on
      sprockets (>= 2.8, < 4.0)

    rails (~> 5.2.4, >= 5.2.4.1) was resolved to 5.2.4.1, which depends on
      sprockets-rails (>= 2.0.0) was resolved to 3.2.1, which depends on
        sprockets (>= 3.0.0)

Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
       rails  webpacker:install
Could not find gem 'mysql2 (>= 0.4.4, < 0.6.0)' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.
...略
```

`sprockets`のバージョンが`4.0.0`だけど、
`sass-rails(~> 5.0)`は`sprockets(>= 2.8, < 4.0)`に対応してるからうまくいかないよ！という内容。

## 解決法

```Gemfile:Gemfile
gem 'sass-rails', '~> 5.0'
```

↓

```Gemfile:Gemfile
gem 'sass-rails'
```
↓

```shell
$ bundle install
```
**バージョン指定**を外してあげれば無事通るようになりました。

## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかのエラー解決時間の短縮につながればと思います。:relaxed:

## 参考にさせて頂いたサイト（いつもありがとうございます）
[【Rails】Vue.js入門してみた。（rails new ~ hello?） - おぴよの気まぐれ日記](https://opiyotan.hatenablog.com/entry/rails-vue-sample)
ド素人が超簡単なwebアプリ作ってみた2。

# 第2段はRailsで
今年10月の半ばに完成。第一弾がから数ヶ月。細く長く学んできました。
見てくれしょぼくてもこれ引っさげて現在転職活動中。
ポートフォリオは有効と聞いたが未経験での転職だとそもそも見られない事が多いね。意欲は認めてくれる。やっぱ職歴が全てってかんじ。

#何するアプリ？
普段業務でLPのコラム書いたりするのでテキストと画像を投稿するだけのシンプルなアプリ。

#実装機能
・記事投稿、記事更新、記事削除機能
・ユーザー作成、更新機能
・検索、ソート機能

#技術スタック
・Webフレームワーク：Ruby on Rails、Bootstrap4
・PaaS：heloku

#見どころ
ログイン機能はGem使わずに実装しました。

#URL　
・デプロイ先
https://crudsample20190928.herokuapp.com/

・Githubのリポジトリ　
https://github.com/rrrhtm/curdsample

#おわりに
言語やフレームワークにこだわらないで色々面接受けていこうと思う。
未経験者の戦闘力がインフレしているらしいので不安だけども。
長すぎる文字列をCSSで...表示にする方法

#長すぎる文字列をCSSで...表示にする方法

##使用言語
cssのみ！

##こんな時に使えます！

アプリ作成を際にとても長い文章を表示しなければならず、ビューが崩れてしまったことはありませんか？
ビューが崩れてしまうくらいなら一部だけ文章を表示するだけにしたい...そんな時に使います

試しに使ってみましょう！
以下のような文章があったとします
<img width="712" alt="スクリーンショット 2019-12-19 23.12.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536777/47da4bef-3d8e-84e3-0fec-4f6ebb474762.png">


例では真っ白な画面に文字を表示させているだけですが、凝ったビューを作る際はこのような長い文章が邪魔になってしまうことがあります
しかし、この文章を以下のように表示させることができます！
<img width="399" alt="スクリーンショット 2019-12-19 23.12.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536777/44397f86-9625-662c-3b0b-b027db927b89.png">

##やりかた
とても簡単です！
...の表示に変えたいクラスに対して以下のcssを設定するだけ！（.targetです）
<img width="399" alt="スクリーンショット 2019-12-19 23.08.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536777/9adad0a5-3c04-cc6d-7bdd-1bc01ef39bd6.png">
この４つの記述を組み合わせることで...表示を実現できます
widthの値を変えることでどこから...表示にするかも変えられます

試しにwidthを70pxにしてみると...
<img width="176" alt="スクリーンショット 2019-12-19 23.19.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536777/f47ee580-0914-4b1b-c0cc-f85c440e4712.png">


##仕組み
なぜこの記述で非表示にできるのでしょうか？
１つずつ順番に見ていきましょう


①
overflow: hidden;
これで、はみ出した文字を非表示にできます
しかし、はみ出したorはみ出してないはどこで判断するのでしょうか？


②
width:;
横幅を指定します　widthで指定した値よりもはみ出てしまうとoverflow: hidden;が適用します


③
text-overflow: ellipsis;
はみ出てしまった要素の表示方法を指定します　ellipsisにするとはみ出た要素を...で表示するようになります！


④
white-space: nowrap;
改行を半角スペースに置き換えます
一見...表示には関係ないように思えますね
①〜③だけで...表示は実現できるように思うかもしれません　なぜwhite-space: nowrap;が必要なのでしょうか？
試しにwhite-space: nowrap;を削除した表示を見てみましょう

<img width="176" alt="スクリーンショット 2019-12-19 23.33.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536777/4eb05585-b950-aef1-d5a6-caba93797fbc.png">

そうなんです！
widthの幅で勝手に改行されてしまいます
はみ出るよりも改行が優先されてしまうので...表示に出来なくなってしまいます　これを防ぐためのwhite-space: nowrap;です！



##フィードバックをください！
私はプログラミングの勉強を始めたばかりでアウトプットのために記事を書いています
この記事で分かりにくかったところや今回紹介した方法よりももっと良い方法があれば教えてください！
Ruby 学習アウトプット2

###はじめに
初学者のrubyシルバー取得に向けての学習アウトプットです。
文章もただただ、タコ殴りしてるだけなので、温かい目で見守っていただけると幸いです。

##今回の教材
###REx

REX??恐竜？？？
T-REXっていうバンドもいますよね。

否！！


[https://www.ruby.or.jp/ja/certification/examination/rex](https://www.ruby.or.jp/ja/certification/examination/rex)

受ける度に問題の内容が変わります。8割共通で残りの2割が入れ替わる。
もちろん以前の問題を再び受け直すことも可能。解説も割と書いてある。
スマホからも受けられて便利。そして無料。
githubアカウントとの連携が必要。


####やってみて
100点中、52点。。。。。まだ先は長い。
ということで復習しましょう

####復習(復讐)

* 次のコードのXXXXに記述するとエラーが発生するコードはどれですか？

```ruby

puts XXXX

"0x90".hex  #=>144
'90'        #=>"90"
0b2         #=>numeric literal without digits(エラー)
'80'.oct    #=>0

```
0xは16進数を表すプレフィックスです。
String#hexは文字列を16進数で解釈して、整数で返します。16進数で解釈できない場合は0を返します。
0bは2進数を表すプレフィックスです。
今回の選択肢0b2は2進数ではありません。0b10が正しい定義です。
String#octは文字列を8進数で解釈して、整数で返します。8進数で解釈できない場合は0を返します。
今回の選択肢”80”は8進数ではありません。"100"が正しい定義です。

上記解説なのですが、○進数に関して全然分からないというか、義務教育の過程で習ったのかどうかも、、、ってことなのでここは分かるようにしときたいです。



この解説で理解できなかったので○進数について学びなおします。とほほ。

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

* 次のプログラムを実行するとどうなりますか？

```ruby

$val = 0

class Count
  def self.up
    $val = $val + 1
    $val == 3 ? true : false
  end
end

[*1..10].any? do
  Count.up
end

p $val


#以下のどれが表示されるか

10
1
0
3

```

答えは３です。
`[*1..10].any?`こちらは`[1..10]`だとRangeクラスで範囲になりますが、`[*1..10]`で`[1,2,3,4,5,6,7,8,9,10]`のArrayクラスの配列になります。そして`any?`でブロックが真が返したときは繰り返しを中断してtrueを返します。ブロックの戻り値がすべて偽であるとき、あるいはレシーバが空であるときにはfalseを返します。
繰り返しが止まるのは3回目の繰り返し、つまり$valが3になった時点です。

この問題のプログラムを実行すると、3が表示されます。

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

* 次のコードを実行するとどうなりますか

```ruby

hoge = "a".to_h
puts hoge.class


Stringと表示される
Arrayと表示される
Hashと表示される
エラーになる

```

答えはエラーになるです。
` undefined method `to_h' for "a":String (NoMethodError)`


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

* 次のコードを実行するとどうなりますか？

```ruby

10.times{|d| print d == 3..d == 5 ? "T" : "F" }



シンタックスエラーとなる
FFFFFFFFFF と表示される
FFFTFTFFFF と表示される
FFFTTTFFFF と表示される

```

答えは`FFFTTTFFFF と表示される`なのですが、最初解説見ても全然分からなくてですね。
特に`d == 3..d == 5`この部分が`d == 3..d`????そんで`3..d == 5`??????
となっていたのですが、実はこれ`(d == 3)..(d == 5)`として考えれば、なんの問題もなく理解できました。`範囲式`でググればOKです。

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

####やってみて
1回目50点、2回目は80点超えではありました。
今の所、自分ができていないのでは○進数系の問題、ヒアドキュメント、Dateクラス、IOクラス

とりあえず、そのへんを固めていきたいです。

以上になります。
java エラー対策編

今回はjavaで出るエラーについて書いて見ます。

# コンパイルエラー
ます初心者にありがちなコンパイルエラーと対処方法を紹介します。

* セミコロン「;」が不足
* ダブルクオーテーション「”」が不足
* 全角空白文字
* ファイル名とクラス名が異なる
* 閉じ括弧「}」

などあります。

## セミコロン「;」が不足
Javaの記述ルールは、1つの命令ごとにセミコロン「;」をつける決まりです。

```java:セミコロン「;」が不足

public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("Hello World!")  // ← セミコロン（「;」）が足りない
	}
}
```

## ダブルクオーテーション「”」が不足
文字列の終わりのダブルクオーテーション「”」が不足していると、こんなエラーが起きます。

```java:ダブルクオーテーション「”」が不足
public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("Hello World!);  ← World!の後に「"」がない
	}
}
```

## 全角空白文字
本来「半角空白」文字を入れるべきところに、「全角空白」文字を入れてしまったことから発生してます。

```java:半角空白文字

public □ class HelloWorld {		   // ← publicの後に全角空白（□）
	public static void main(String[] args) {
		System.out.println("Hello World!")  
	}
}
```

## ファイル名とクラス名が異なる
例をあげると
ソースファイルに記述されているクラス名が「HelloWorld」であるのに対し
ファイル名を「Hello.java」としたために発生します。

Javaでは、一つのファイルに一つのクラスを記述し
ファイル名は「クラス名.java」とする決まりです。

## 閉じ括弧「}」
数十行のプログラムで、if(){}やfor(){}のような段落のとじ括弧が不足していると
非常にわかりづらいです。

```java:閉じ括弧「}」
	public static void main(String[] args) {
		System.out.println("Hello World!")  
	// ← 「}」がない
}
```

# 構文エラー
少し難しくなって、配列やif構文で出てくるエラー内容を紹介します。

主な内容はこちら

* java.lang.NullPointerException
* java.lang.ArrayIndexOutOfBoundsException
* java.lang.NumberFormatException
* java.lang.ClassCastException
* java.lang.ArithmeticException
* java.lang.NoClassDefFoundError
* java.lang.OutOfMemoryError

## java.lang.NullPointerException
このエラーはnullのオブジェクトに対してアクセスしようとしたときに発生する。
プログラミング時に比較的発生しやすいエラーで、エンジニアの間では「ヌルポ」と呼ばれています。

### 対策
* インスタンスの生成や値の設定が正しく行われているかをチェックする。
* オブジェクトがnullになってしまうタイミングをデバッグで確認する。
* プログラムでオブジェクトがnullかどうかのチェックを行い、エラーの発生をできる限り回避する。

##  java.lang.ArrayIndexOutOfBoundsException
配列のインデックスとして存在しない要素を指定した場合に発生するエラーで
先ほどのエラーの例でも紹介した。配列のインデックスとして1～9のインデックスしかないところ
10のインデックスに値を設定しようとする場合などに発生する。

対策
* 正しい配列のインデックスを指定できているかチェックする。
* 配列の設定を繰り返し処理で行っている場合、繰り返し回数などに問題がないかチェックする。

##  java.lang.NumberFormatException
このエラーは文字列の値を数値に変換(キャスト）しようとしたが
文字列に数値として正しくない値が設定されている場合に発生する。

### 対策
* 文字列にアルファベットや記号など、数値以外の文字が設定されていないかチェックする。
* 文字列に空白やnullが設定されていないかチェックする。
* 文字列には数値が設定されているが、変換しようとしている数値型で扱える値の範囲をオーバーしていないかチェックする。

##  java.lang.ClassCastException
このエラーはあるクラスを変換できないクラスにキャストしようとした時に発生する。

### 対策

* 配列などに設定した値のクラスと、値を取り出す時にキャストしようとしている型が一致しているかをチェックする。
* 継承関係のある2つのクラスで、サブクラスにスーパークラスをキャストしようとしていないかをチェックする。

##  java.lang.ArithmeticException
このエラーは数値の計算において、不正な算術処理が行われた場合に発生する。例えば数学的にあり得ない「ゼロ除算（10÷0 など）」が発生するとこのエラーが発生する。

### 対策

* ゼロ除算が行われてないかをチェックする。
* 数値型変数で計算している場合、割る数の変数にゼロが設定されていないかチェックする

##  java.lang.NoClassDefFoundError
メソッドを呼び出す時や、インスタンスを生成しようとしている時に
Javaがクラス定義を読み込むことができないエラーです。

### 対策

* 環境変数CLASSPATHが誤っている可能性があるのでチェックする。
* ファイル名やパッケージ名に誤りがないかチェックする。
* プログラムに必要な外部ファイル(jar)が読み込まれているかチェックする。

##  java.lang.OutOfMemoryError
Javaは実行時にスタック領域とヒープ領域という2つのメモリー領域を使用するが
このエラーはプログラムの実行に必要なヒープ領域のメモリーサイズが不足した時に発生する。

ヒープ領域とはクラスやメソッドの定義など、オブジェクトのインスタンスが割り当てられるメモリー領域のことだ。

### 対策

* プログラム内で無限ループになっていしまっている箇所がないかチェックする。
* 一度に大量のデータを処理しようとしている箇所がないかチェックする。
* 不必要にスコープ（公開範囲）が広いメソッドや変数を多用していないかチェックする。
svmモジュールのSVCについて（数学は抜く。）

皆さんこんばんわ。
12/19の文を書いていきます。
今日は用事があって遅くなりましたね。。。

今日は昨日勉強した直線SVCモデルの分類をまとめていこうと思います。

#分類の目的
![2019_12_19_blog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255565/087e7f8f-1192-d5ba-2dd1-59b5410065a3.png)

上の写真を見てください。
分類とはこの青の点とオレンジのバツを分ける線を自動的に見つけることです。
２次元だと人間にとってとても簡単ですよね？
SVCモデルは高次元の場合でも分ける為の式を求めれられるらしいので凄いですよね。
さぁ、これが何に役に立つの？と思った方も多いでしょう。
下の画像はいかがでしょうか？

![2019_12_19_picpng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255565/01665bdd-ebeb-09d0-1164-083369ed6096.png)

違いがわかりましたか？
そう、Gメールでは当たり前のように迷惑メールを弾いてくれますが、これはAIの力なのです。（アルゴリズムはもっと複雑です。）
けど、やっていることは同じで、ある直線（面）を引いてスパムか有効なメールかを分析しているのです。
美しいし、凄いですよね。

さて、今日の最終の目的の画像を見せますね。
以下になります。

![Figfdsaure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255565/c0cc11c8-bc2c-93f4-38f1-02f2ed550945.png)

⚠︎注意したいことがあります。
それはこの例の場合だと、無限の線が引けると言うことです。
よって、この点線の幅（マージ）が一番広くなった上で、その真ん中に実線（決定境界）を引きます。

さてこの決定境界を求める為のコードを見ていきます。

#サンプルコード
```python
import numpy as np
from sklearn.svm import SVC
import matplotlib.pyplot as plt
xmin = 0
xmax = 2
ymin = 0
ymax = 2

# 0 ~ 1 までの正規分布に従った値が入った（100行２列（X＆Y)）の行列を作成
X0 = np.random.uniform(size=(100, 2))
y0 = np.repeat(0, 100)

X1 = np.random.uniform(low=1.0, high=2.0, size=(100, 2))
y1 = np.repeat(1, 100)

svc = SVC(kernel='linear', C=1e8)

# 学習
# svc.fit(train_features, train_labels)
svc.fit(np.vstack((X0, X1)), np.hstack((y0, y1)))

fig, ax = plt.subplots()

# ax.scatter(x, y) 散布図
ax.scatter(X0[:, 0], X0[:, 1], marker='o', label='class 0')
ax.scatter(X1[:, 0], X1[:, 1], marker='x', label='class 1')

# 格子点を準備
xx, yy = np.meshgrid(np.linspace(xmin, xmax, 100), np.linspace(ymin, ymax, 100))
# decision_functionの為に一つの行列に。
xy = np.vstack([xx.ravel(), yy.ravel()]).T

# 100 * 100 の行列。
# z = x*2 + y*2 とする部分のzの高さの部分。
# svcの決定関数を使ってxyという格子点からzを求めている。
z = svc.decision_function(xy).reshape((100, 100))
# 決定境界とマージンをプロット
ax.contour(xx, yy, z, colors='k', levels=[-1, 0, 1], alpha=0.3, linestyles=['--', '-', '--'])
plt.show()
```
流れとしては、
1. データを準備
2. SVCのインスタンスを作成
3. 入力データをそれを紐付かせたラベルをfit関数に入れることで学習させる。
4. 格子点を作成（[参考記事](https://qiita.com/mitsumizo/items/6e21eb07c94f430c8be5))
5. Zをfitで学んだdecision_functionを使って作成
6. contourを使って等高線を引くと、決定境界を書くことができる。

大切な関数はfitとdecition_funkctionである。
fitの使い方は理解したが、decision_functionの方は分類器を利用してZを求めることくらいしか理解できてない。
それはもう少し勉強が進んで記事にしようと思う。

今日は夜が遅いのでこれくらいで。
おやすみなさい。
C++　入門のおすすめの本


C++のおすすめの本です。
小さいサンプル、動作説明、これがメインで大変わかりやすいですし、忘れたときにサンプルコードを見るだけで思い出しやすくとても便利です。

https://amzn.to/3WKFwyn





「C++入門の本と言えば、ロベールの・・・」
「あ、知ってます。持ってます。」

「あ！そういえば知ってます！他の人にも紹介されました！」

というような会話を何度もしました。

古い本ですが、プログラミングに支障ないです。全く問題ありません。

小さいサンプル、実行結果、説明、と読んですぐに分かるし、入門と言ってもSTLなどにも触れられてます。

また辞書替わりでもいいでしょう。目次を見て飛んで確認とか。


入門と言えば、有名どころでは　C++の絵本　があります。こちらはイラスト付きで優しい雰囲気です。

C++の絵本
https://amzn.to/4jxEorI

STLまでは書かれていませんが、こっちもありかもしれません。
比較的軽い本なので、入りやすく、イラストを眺めるくらいでも楽しいかもしれません。

慣れてきたらロベールの本とかが良いでしょう。

ロベールの本は初学～入門本じゃあまりやらないところまで、サンプルコード込みで丁寧に説明しています。

**<font color="Red">C++の絵本</font> ＞＞ 慣れてきたら(全部読まなくていい) ＞＞ <font color="Red">ロベールのC++入門講座 </font>**
**<font color="Blue">2冊買っちゃうといいですね。</font>**
C++の絵本はかわいいイラストが良く描かれているので癒されてまったり読めます。
ロベールの本は、大変分かりやすいですが、内容が濃いいので慣れていないと疲れるかもしれません。C++の絵本で慣れてからなら安心できます。

ロベールさんに最近バージョンのC++もやってほしいですが、サイトが長年更新されていないので、生きているかどうかも怪しいところです。それは残念なところです。

**ロベールのC++入門講座**    著者サイト：
なんと書籍内容を閲覧、ダウンロードできてしまう太っ腹さ。
http://www7b.biglobe.ne.jp/~robe/cpphtml/

バージョンは古いですが、まあ問題ないでしょう。

慣れてきたら、Copliot に質問して、もっと便利な命令を聞くなどして新しいバージョンの
命令も、場合によっては使用すると良いです。

C++は、使い所が難しい、用途を間違えるとかえって煩雑になり使わないほうが良い、などの命令があります。
（※他言語開発者は、C++の良いところは取り入れ、煩雑な命令は取り入れないとか、そういう印象があります。なので、他言語にはない特殊な命令は使わないほうがいいかも？と考えても良いかもしれません）

無理して新しい命令は使わず、堅実に行うか、
新しい命令に関しては、しっかりメリット、デメリットを理解したうえで使う必要があります。

取り急ぎ、これに掲載されていないもので、利便性で考えた場合、C++の enum class はオススメで、簡単に言うと、C言語のenum から C#の enum の性能ぐらいにアップされたものです。要素の被りはOKになり、型として int で扱われなくなりますし、
(int)でキャストすれば、int の値を取り出すことが出来ます。
C#のenumは他にも機能はありますが、細かいことを述べていると長くなるので割愛します。

詳細はCopilotに 小さいサンプルを提示してもらったりすると理解しやすいかと思います。

自分はある程度したら、ロベールのC++サイトから C++を覚え、後は必要に応じて、ネットで調べて＋α を覚えました。
Copilotがあるからもう本いらないんじゃない？とか考えています。

小さいプログラムサンプルと少しの説明が分かりやすいですよね。これをCopilotに出してもらうんです。
個人開発アプリのシステム構成の話と今後の計画

Ubiregi Advent Calendar 2019 19日目の記事になります。

今回は個人で開発中のアプリのシステム構成の紹介と、そのシステム構成をどう変更していくかという計画の話をします。

## アプリ概要

現在iOS向けに「ゴミアプリ」というそのままの名前でゴミ収集日のカレンダーアプリを出しています。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">こんなアプリです。 <a href="https://t.co/JgE2yEYVto">pic.twitter.com/JgE2yEYVto</a></p>&mdash; 「ゴミアプリ」開発者 (@gomi_tech) <a href="https://twitter.com/gomi_tech/status/1086532960499593216?ref_src=twsrc%5Etfw">January 19, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 現在のシステム構成

### 概要

主にはFirebaseのFirestoreに各自治体のカレンダーデータを格納しておき、アプリ側でそのデータを取ってきてカレンダーとして表示しています。
自治体のカレンダー以外に自分で収集パターン（例：毎週火曜日は燃えるゴミ、など）を登録して、そのパターンを組み合わせて独自の収集日カレンダーを作る機能も提供しています。こちらはローカルのrealmにデータを保存し、取り出して加工しています。
ただこの構成でいくつか「問題点」があって、将来的に`iOSローカル`でやっているところをすべてFirebaseに移行したいなと考えています。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5497/fd53b612-eb06-8ba9-0bbb-c2a0fcff59c5.png)

### 現在アプリが抱える問題点

構成図を見ると左下の通知部分が未実装です。
未実装の理由としてはLocalNotificationで通知機能（「今日は資源ごみです」みたいな通知）を実装しようとしたのですが、LocalNotificationでは機能要件を満たさないことがあとから分かって一旦開発を止めたのです。


機能要件を満たすため、RemoteNotificationにしたいのですが、そうなるとローカルにある「収集パターン」のデータと、ユーザーの設定値（どの自治体のデータを取ってくるのかという設定値）もリモートに置く必要がでてきます。

## 将来的に目指したいシステム構成

### 計画

というわけでいろいろとリモートに上げていかなければならないので以下のような構成を計画しています。

![未来予想図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5497/bdc5c4e5-603b-19a1-6bdf-4f9c3f2ee278.png)

### 変わったところ

大きなところとしては、Cloud Functionsです。
Cloud Functionsに通知送信のためのバッチ処理をやってもらおうかなと考えています。更に収集パターンからカレンダーデータを作成する処理もまかせています。将来的なAndroind対応を考えるとそれぞれにロジックをもたなくて済みますからね。

あとはユーザー設定も通知のときに必要になるので、Firestoreに移行します。

## 最後に

計画についていろいろ考えてきました。そこから具体的にやらないといけないことをリストにするとこんな感じでしょうか。

- セキュリティルール変更・テスト
- ゴミ収集パターンからカレンダーデータ作成する処理の設計・実装・テスト
- ゴミ収集パターンのテーブル追加
- 通知の設計、通知登録処理の設計と実装
- 通知設定のテーブル追加
- バッチ処理設計・実装
- ユーザー設定のカラム追加

超大変。一個も手をつけていません。

なかなか大変なので一旦これは横においといて、iOS13周りで対応しないといけないところがあるので、そちらの修正からやって行こうと思います。
Fizz Buzz を解いてみた

## この記事について
[CODEBASE okinawa Advent Calendar 2019](https://qiita.com/advent-calendar/2019/codebase-okinawa) の19日目の記事にあたります。

## 内容
いい感じに**Fizz Buzz問題**をPython3を用いて解いていきます。
とりあえずやってみよう。

## Fizz Buzz問題とは
最初のプレイヤーは「1」と数字を発言する。次のプレイヤーは直前のプレイヤーの次の数字を発言していく。ただし、**3で割り切れる場合は「Fizz」、5で割り切れる場合は「Buzz」、両者で割り切れる場合（すなわち15で割り切れる場合）は「Fizz Buzz」**を数の代わりに発言しなければならない。発言を間違えた者や、ためらった者は脱落となる。
『Fizz Buzz』 [Wikipediaより](https://ja.wikipedia.org/wiki/Fizz_Buzz)

### 整理して考えてみる
- 3 で割り切れる数字(3, 6, ...)のときはFizz  
- 5 で割り切れる数字(5, 10, ...)のときはBuzz
- 3 と 5 の両方で割り切れる数字(15, 30, ...)のときはFizzBuzz
- 上記の条件に満たないならそのまま数字

## 条件ごとに分解したコードに直す
言語としては Python3 で条件ごとにコードにしていきます。
また数字は**変数x**に置いて進めていきます。

### 3 で割り切れる場合
**3 で割り切れる**とは 3 で除算を行った場合に余りが 0 になると考えることが出来る。
条件分岐は if 表現で書くことができ、条件を満たすなら中の処理を行います。
Python はインデント(半角スペース4つ)で区切られてます。

```python

if x % 3 == 0:
    print("Fizz")
```

### 5で割り切れる場合
**5 で割り切れる**とは 5 で除算を行った場合に余りが 0 になると考えることが出来る。

```python

if x % 5 == 0:
    print("Buzz")
```

### 3 と 5 の両方で割り切れる場合
今までの if 表現だけで書くと下のように書けます。

```python

if x % 3 == 0:
    if x % 5 == 0:
        print("FizzBuzz")
```
上記のコード以外にも 3 と 5 の両方を満たすを 15 で割り切れると考えられます。

```python

if x % 15 == 0:
    print("FizzBuzz")
```

### 条件に満たない場合
if の条件分岐を満たさないを書きたい場合は else 表現を用いる事ができます。

```python

if 条件式1:
    `条件式1を満たすときに行う処理`
else if (elifに省略可) 条件式2:
    `条件式1を満たさず条件式2を満たすときに行う処理`
else:
    `全ての条件式を満たさないときに行う処理`
```

## 実際のコードとして書いてみる
### 条件分岐部分を書いてみる
条件ごとに分解して書いたコードを合体させてコードを完成させていきます。
ここでの注意点としてコードは上から下に見ていく事です。
つまり最初の if 条件を満たしたならそれ以降の条件に当てはまっても基本的には処理を行わないと言う事です。この注意点を踏まえたうえでコードを書くと下記になります。

```python

if x % 15 == 0:
    print("FizzBuzz")
elif x % 5 == 0:
    print("Buzz")
elif x % 3 == 0:
    print("Fizz")
else:
    print(x)
```
これで基本的な FizzBuzz の条件をコードにする事ができました。

### 条件分岐に使う変数 x の準備
変数 x は 1, 2, 3, ..., 30  になるように準備します。
繰り返し処理を行うためのコードは下記になります。

```python

for x in range(1,31): 
    `繰り返したい処理`
```
上記のコードで 1 ~ 30 まで処理を行い、変数 x に試行回数分の値をセットできます。

### これで本当にコードが完成！！
```python

for x in range(1,31):
    if x % 15 == 0:
        print("FizzBuzz")
    elif x % 5 == 0:
        print("Buzz")
    elif x % 3 == 0:
        print("Fizz")
    else:
        print(x) 
```

## 色々コードを加工してみよう ~~(本編です)~~
### 文字の加算を利用した FizzBuzz
文字同士の加算が可能な言語なら if 条件だけでも書く事が可能です。

```python

for i in range(1,31):
    ans = ""
    if i % 3 == 0:
        ans += "Fizz"
    if i % 5 == 0:
        ans +=  "Buzz"
    if ans == "":
        ans = i
    print(ans)
```
### 1 行の FizzBuzz リスト内包表記版
リスト内包表記を用いると 1 行で Fizz Buzz を書く事ができます。

```python

print("\n".join("FizzBuzz" if n % 15 == 0 else "Fizz" if n % 3 == 0 else "Buzz" if n % 5 == 0 else str(n) for n in range(1,31)))
```
### 1 行の FizzBuzz bool 型利用版
Python では bool 型の True, False は int 型の 0, 1 と等価として四則演算が可能である。
この条件と文字の加算を利用して下記のように書く事も出来ます。

```python

print("\n".join( "Fizz" * (n % 3 == 0) + "Buzz" * (n % 5 == 0) or str(n) for n in range(1,31)))
```
socket.ioとvue.jsを利用したチャット作りましょう

こんにちは！
node.jsのモジュールであるsocket.ioを利用してチャットを作ってみました。

#socket.ioとは？
socket.ioはサーバとブラウザを双方向通信を可能にするnode.jsのモジュールです。HTML5のwebsocketプロトコルを基に様々なブラウザで動作する双方向通信が可能なアプリケーションを作ることができます。
socket.ioを利用すればチャットルームのようにリアルタイムにデータが伝送されるようなチャットを簡単に作るのができます。
#websocketとは
ウェブサーバの一つのポートでこの中で接続したクライアントが自由にデータをやり取りする方式です。
元来はクライアントからの要請があればサーバはそれに応答していたが、websocketはクライアントからの要請があったときにつながっている全てのクライアントに変更事項を伝達する仕組みです。
**つまり、クライアントからの要請なしでもサーバの変更事項をクライアントにリアルタイムに配信できるようになりました。**

#実装
サーバはexpress、フロントアンドはvue.jsを使用しました
↓はサーバコードです。とても簡単なコードでエクスプレスでサーバーを構成し socket.ioを連結しました。


```app.js
const express = require('express');

const app = express();

const server = app.listen(3001, function() {
    console.log('server running on port 3001');
});

const io = require('socket.io')(server);

io.on('connection', function(socket) {
    socket.on('SEND_MESSAGE', function(data) {
        io.emit('MESSAGE', data)
    });
});
```
socketサーバーはクライアントの受信を'SEND_MESSAGE' という名前で待機し、この要請があったときにemitメソッドを通じて接続されたクライアントにデータを送信します。
<br>
↑のサーバコードを見れば、```「MESSAGE」```でサーバのデータを受信待機し、```「SEND_MESSAGE」```にデータを転送する仕組みです

```
<template>
  <div>
    <h1>チャット</h1>
    <ul>
      <li v-for="(msg, index) in messages" :key="index">{{msg.message}}</li>
    </ul>
    <div>
      <input type="text" @keyup.enter="sendMessage()" v-model="message">
    </div>
  </div>
</template>

<script>
import io from 'socket.io-client';

export default {
  name: 'room',
  data() {
    return {
      messages: [],
      // 1) サーバ連結
      socket : io('localhost:3001')
    }
  },
  methods: {
    sendMessage(message) {
      // 2) メッセージをサーバで送信
      this.socket.emit('SEND_MESSAGE', {message});
    }
  },
  mounted() {
    // 3) サーバの変更内容を受信
    this.socket.on('MESSAGE', (data) => {
        this.messages = [...this.messages, data];
    });
  }
}
</script>
```
これまでチャットためのクライアントとサーバの基本仕組みを作成してみました。
上のコードを通じてどのようにデータが行き来するかを理解することができました。

#参考
https://socket.io/
ngrokを使ってRaspberryPiで構築された録画サーバーの番組表に外出先からアクセスする

我が家では、Raspberry Pi + Mirakurun + EPGStation でTVの録画サーバーを構築しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/8b545f2d-97c5-bdde-3674-dad4d0a2d0ea.png" width="360">

録画された動画データはサーバーに転送すればよいのですが、
肝心の番組表UIはローカルにあるので、外出先からアクセスするにはちょっとめんどう・・・

ですが、ngrokを使うとlocalhostを外部ネットワークからアクセスできるようにしてくれて便利。



## ngrokをインストール

### ダウンロード

[https://ngrok.com/download](https://ngrok.com/download) から Linux (ARM)をダウンロード

```
$ wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip
```

### zipを解凍

```
$ unzip ngrok-stable-linux-arm.zip
``` 

### 使いやすいように /usr/local/bin/ に配置

```
$ sudo mv ngrok /usr/local/bin/
```


### 準備完了
```
$ ngrok -v
ngrok version 2.3.35
```


## Authtokenの取得

[https://dashboard.ngrok.com/auth](https://dashboard.ngrok.com/auth) こちらから token を取得し、以下を実行し登録します。

```
$ ngrok authtoken xxxxxxxxxxxxxxxxxxxxxxxxxxx
```


## ngrokしインターネットに公開

```
$ ngrok http 8888
ngrok by @inconshreveable                                                                                                       (Ctrl+C to quit)
                                                                                                                                                
Session Status                online                                                                                                            
Account                       xxxxxxx@xxxxxxx.com (Plan: Free)                                                                                
Version                       2.3.35                                                                                                            
Region                        United States (us)                                                                                                
Web Interface                 http://127.0.0.1:4040                                                                                             
Forwarding                    http://xxxxxxx.ngrok.io -> http://localhost:8888                                                                 
Forwarding                    https://xxxxxxx.ngrok.io -> http://localhost:8888                                                                
```

Forwardingで表示されるURLで外部から表示させることができます。
無料プランでは毎度URLが変わってしまうので注意。


## 外から確認してみる

![Artboard.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/1b947ae6-dea8-2c56-da02-f0e610d216d7.png)

ちゃんと録画操作もできます。


## serviceに登録し自動で起動させる

```:/etc/systemd/system/ngrok.service
[Unit]
Description=ngrok

[Service]
Type=simple
ExecStart=/usr/local/bin/ngrok http 8888
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
IgnoreSIGPIPE=true
User=pi

[Install]
WantedBy=multi-user.target
Alias=ngrok.service
```

```
$ sudo systemctl enable ngrok.service
$ sudo systemctl start ngrok.service
```


[https://dashboard.ngrok.com/status](https://dashboard.ngrok.com/status) にURLが表示されていれば成功です。


## おわり