OmniAICreator/Qiita-1.07M huggingface dataset:
LINE新機能「OpenChat（オープンチャット）」がリリースされた話

LINEの新機能OpenChatがリリースされたのでまとめてみます。

## OpenChat（オープンチャット）とは？
使い方の詳細はブログに書いてますのでそちらをご覧ください。

https://www.wow-creators.com/2019/08/19/line新機能「openchat（オープンチャット）」の使い方/

> 1. トークルームごとにプロフィールを変更できる。
> 2. トークルームごとに公開／非公開を設定できる。
> 3. 途中から会話に参加した場合も、直前のやりとりをさかのぼってチェックできる。
> 4. ひとつのトークルームに最大5000人まで参加できる。
> 5. URLやQRコードで、トークルームに招待できる。
> (※年齢認証をしていないユーザー、18歳未満のユーザーについては、一部機能が制限されます）

出典:新機能「OpenChat（オープンチャット）」が登場しました | LINE公式ブログ

http://official-blog.line.me/ja/archives/79902633.html

簡単にいうと、
自分のプロフィールを通常とは別の変更した状態でグループトークに参加できるというものです。

## 利用用途は？普及する？

利用用途は使い方次第ですが色々想定されます

- 一時的なセミナーやイベントでのトークルームの生成
- オンラインサロンなどのイベントで無料枠として一時利用
- 学生同士の交流の場として活用
- 飲み友達の募集
- 同じ趣味を持つもの同士のつながり
- スポーツ観戦時などの一時利用

通常のLINEのグループは友達同士の利用なので差別化できるとして、
Facebook、Instagramはそもそも別のベクトルなので、
あとはTwitterとの差別化が重要かと思います。
今後東京オリンピックも開催されますし、
同じ場を共有するもの同士の情報交換や繋がり、交流の手段として良い活用をしていければいいですね。

違うプロフィールを設定できるということはより匿名性の高いものにはなるので
いたずらや悪意をもった使用などは注意が必要ですね。
どちらにしても便利なツールはうまく使うか悪意をもって使うかで全然変わってくるものなので
便利に使って普及していくといいですね。
WEBスクレイピング用のサーバーレス環境を比較した【 Firebase vs AWS Lambda】

## スクレイピング 遅すぎる問題

- Node.jsのライブラリ「Puppeteer」でWEBスクレイピング
- Google Cloud Functionsに置いてJSONを返すHTTPトリガー化
- Google App Scriptで上記トリガーからJSON取得
- Spread Sheetに整形して貼り付け

という構成でスクレイピングデータを加工して利用しています。
が、スクレイピングスクリプトが重くてめちゃくちゃ時間がかかるので、どうにかならないかと思い、Google Cloud Functionsと同様のサーバーレス環境FirebaseとAWS Lambdaを比較しました。


## Firebase（Cloud Functions for Firebase）

### 概要
https://firebase.google.com/products/functions/?hl=ja

Firebaseの中にあるCloud Functionsは、そもそもGoogle Cloud Functionsとほぼ同様のものでした。

>Google Cloud Functions は、イベント駆動型アプリケーションを作成するための Google のサーバーレス コンピュート ソリューションです。Google Cloud Platform チームと Firebase チーム共同のプロダクトです。
https://cloud.google.com/functions/docs/concepts/functions-and-firebase?hl=ja

何が違うかというと、Firebaseという統合環境の中での連携が楽、という差のようなので、Google Cloud Functionsの上位互換、といったことではなさそうです。

### ランタイム

- Node.js 6,8,10
- Python 3.7
- Go 1.11

### 料金

※2019/8/20現在

|Cloud Functions     | Spark プラン [ 無料 ] | Flame プラン [ $25/月]  | Blaze プラン [ 従量制 ]|
|:-----------------|-----------------:|------------------:|------------------:|
| 呼び出し           |              12.5 万/月 |        200 万/月        |        $0.40/百万   |
| GB 秒                 |            4 万/月 |       40 万/月      |   $0.0025/千   |
| CPU 秒                 |              4 万/月 |        20 万/月      |     $0.01/千    |
| アウトバウンド ネットワーキング |   Google サービス専用 | 5 GB/月 |   $0.12/GB |


>呼び出し料金は 1 回あたり $0.0000004 の単価制で、関数の結果や使用期間に関係なく請求されます。ただし、毎月最初の 200 万回までは無料です。

料金詳細
https://cloud.google.com/functions/pricing?hl=ja

料金も、Cloud Functions for FirebaseとGoogle Cloud Functionsでは差がなさそうです。

### 使ってみての感想

Cloud Functions for FirebaseはGoogle Cloud Functionsと同じなので、Google Cloud Functionsを触ってみての個人的感想ですが、非常にとっつきやすいです。特に元非エンジニアで駆け出しエンジニアの私のような存在には大変ありがたい！設定時の操作に迷うことはありませんでした。
さくさくと設定できて、HTTPトリガーがすぐに使えるので非エンジニアの方でも手を出しやすい印象です。

## AWS Lambda

https://docs.aws.amazon.com/ja_jp/lambda/

### ランタイム

- Node.js 8.10, 10
- Python 2.7, 3.7, 3.6
- Ruby 2.5
- Java 8
- Go 1.x
- .Net Core 2.1
- .Net Core 1.0

Cloud Functionsよりも豊富ですね。

### 料金

※2019/8/20現在

|AWS Lambda|  無料利用枠 |以降 |
|:---------|----------:|----:|
| 呼び出し   |100万件/月  |リクエストあたり 0.0000002USD |
| GB 秒     | 400 GB-秒 |GB-秒あたり 0.0000166667USD|

料金詳細
https://aws.amazon.com/jp/lambda/pricing/

Cloud Functionsは毎月最初の200万回が無料なので、Firebaseの方が無料で使える範囲が大きい様です。

### 使ってみての感想

スクリプトをデプロイしただけではHTTPトリガーにはならず、API Gatewayを利用してトリガー化する手間がありました。
設定も少々複雑で初学者にとってはとっつきにくい印象ですが、カスタマイズも豊富で、他のAWSサービスとの連携も取れるので、堅牢かつ柔軟性の高い環境を構築できそうです。

## まとめ

Cloud Functions for Firebaseは非エンジニア、初学者向きで、本当に簡単なスクリプトを利用する際にはおすすめです。
AWS Lambdaはエンジニア向きで、詳細な要件に合わせて柔軟なシステムを構築したい場合はこちらがおすすめ。

と、現段階の理解レベルでは結論づけました。
語彙力のなさや理解度の浅さは当然あるかと思うので、ご意見大歓迎です。
理解が深まった時には、加筆修正、もしくは別記事をあげる等してきたいと思います。

### 今後のこと

元々の課題のスクレイピング遅すぎる問題は、AWS Lambdaでの構築時にはAPI Gatewayのタイムアウトでうまいこと移行ができず、そもそも組んでいるスクリプトがクソなのでは？という疑問が湧いてきたので、当面はCloud FunctionsとNode.jsの学習に取り組む所存です。
textのAttributedStringをClearする


AttributedStringは、文字に背景色を付けたりする際に用います。

AttributedStringはlabelに付けれるだけでなく、
TextViewやTextFieldなどの入力でも利用できます。

![](https://i.imgur.com/69ub97z.png)

この **「AttributedStringをClearしたい」** とき、
例えば **「TextView Edit中は背景色を透明に戻したい」** とき、
処理を実現するのに少し苦労したので、備忘録として記載します。

## TextViewの文字背景色を黄色に

まず、TextViewの文字背景色を黄色にするコード。

```swift
@IBOutlet weak var textView: TextView!

func fillIn(value: String) {
    let attributes: [NSAttributedString.Key: Any] = [
        .backgroundColor: UIColor.yellow,
        .font: UIFont.systemFont(ofSize: 20.0)
    ]
    textView.attributedText = NSAttributedString(string: value,
                                                 attributes: attributes)
}
```

これでtextViewに値をFillInした際に、文字背景色が黄色になります。

## TextViewの文字背景色を透明に戻す

AttributedStringをClearする、みたいな方法は見つけられませんでした。
そこで `.backgroundColor: UIColor.clear` を設定した別のAttributedString
を用いることで、Clearを実現します。

「textViewの編集を開始したタイミング」でClearをします。
textViewのDelegateを設定しつつ、

```swift
textView.delegate = self
```

テキスト入力を始めた時 `textViewDidBeginEditing` に処理を書きます。

```swift
extension ViewController: UITextViewDelegate {
    func textViewDidBeginEditing(_ textView: UITextView) {
        let attributes: [NSAttributedString.Key: Any] = [
            .foregroundColor: UIColor.black,
            .backgroundColor: UIColor.clear,
            .font : UIFont.systemFont(ofSize: 20.0)
        ]
        textView.attributedText = NSAttributedString(string: textView.text ?? "",
                                                     attributes: attributes)
    }
}
```

背景色を透明に設定したAttributedStringを利用することで、
文字背景色を透明に戻します。

![](https://i.imgur.com/FhfeEVP.png)

これで目的達成！！

## と思いきや！文字を追加してみたら

![](https://i.imgur.com/t5sEfdO.png)

...目的達成ならず :cry: 

他の設定が必要。 `typingattributes` なるものが。
https://developer.apple.com/documentation/uikit/uitextview/1618629-typingattributes

既に入力されたテキストだけでなく、
これから入力するテキストについても設定を追加する必要でした。

```swift
extension ViewController: UITextViewDelegate {
    func textViewDidBeginEditing(_ textView: UITextView) {
        let attributes: [NSAttributedString.Key: Any] = [
            .foregroundColor: UIColor.black,
            .backgroundColor: UIColor.clear,
            .font : UIFont.systemFont(ofSize: 20.0)
        ]
        textView.attributedText = NSAttributedString(string: textView.text ?? "",
                                                     attributes: attributes)
        textView.typingAttributes = attributes // New!!
    }
}
```

これで無事、目的達成。

## まとめ

他に方法を知っている方がいればご教示頂けると幸いですm(__)m

## 参考

- https://qiita.com/KikurageChan/items/bab37e1fb19002256119
- https://qiita.com/touyu/items/2e08bea72cba85107616
iOSで遅延処理


iOS(Swift4)以上で遅延処理を行う場合についてのまとめ。

## 単純に処理を遅延させたい

DispatchQueueのasyncAfterを利用。

```swift
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
    // 2.0秒後に実行したい処理
}
```

## アニメーションが絡む処理を遅延させたい

UIView.animateを利用。

```swift

UIView.animate(withDuration: 1.0, delay: 2.0, options: .autoreverse, animations: {
    // 2.0秒後に実行したいアニメーション処理
}, completion: { _ in
    // アニメーション終了後に実行したい処理
})
```

- withDuration: アニメーションの実行時間
- delay: 遅延時間
- option: アニメーション動作の種類 `UIView.AnimationOptions`
- animations: アニメーション処理
- completion: アニメーション完了後処理 (nilでもOK)

※UIView.AnimationOptionsの種類:
https://developer.apple.com/documentation/uikit/uiview/animationoptions

## 参考

公式ドキュメント

- https://developer.apple.com/documentation/dispatch/dispatchqueue/2300020-asyncafter
- https://developer.apple.com/documentation/uikit/uiview/1622451-animate

参考サイト

- https://kitoko552.hatenablog.com/entry/20180308/1520514926
IBM Cloud Activity Tracker with LogDNAのFAQ

#1. はじめに
IBM Cloud Activity Tracker with LogDNA（以下、Activity Trackerと略）は、IBM Cloudでの作業の監査を行うためのサービスです。例えば、ユーザーを作成したとか、新しく設定を追加した、などの作業に対してAPIでの操作やポータルからの操作を問わず、履歴を残すことが可能です。これにより、不正な行為が行われていないかどかを確認することができます。
https://cloud.ibm.com/docs/services/Activity-Tracker-with-LogDNA?topic=logdnaat-getting-started

なお、（名称が似ているために混乱しがちですが）、従来あったActivity Trackerは現在は既に非推奨であり新規にはプロビジョニングできません。ドキュメントによって、Activity Trackerと書かれているものが実は古いものを指している可能性があります。これから利用するサービスは、必ずActivity Tracker **with LogDNA**になっていることを確認してください。


>https://cloud.ibm.com/docs/services/cloud-activity-tracker?topic=cloud-activity-tracker-getting-started
IBM® Cloud Activity Tracker is deprecated. As of 9 May 2019, you cannot provision new Activity Tracker instances. Existing premium plan instances are supported until 30 September 2019. To continue monitoring the activity of your IBM Cloud account, provision an instance of the IBM® Cloud Activity Tracker with LogDNA.

#2. FAQ

`Q: global events、location-based eventsとは何ですか？`
Activity Tracker with LogDNAで管理するイベントにはglobal eventsと呼ばれるアカウント全体にまたがったイベント（例：ユーザー作成など）と、location-based events（例: Tokyoリージョンで提供されているサービスの構成変更など）と呼ばれるリージョンごとに管理されるイベントがあります。global eventsを参照するためにはFrankFurtリージョンにインスタンスを作成する必要があることに注意してください。
https://cloud.ibm.com/docs/services/Activity-Tracker-with-LogDNA?topic=logdnaat-monitor_events#mon_def_event_type
https://cloud.ibm.com/docs/services/Activity-Tracker-with-LogDNA?topic=logdnaat-manage_events#manage_events_provision

`Q: どのリージョンで利用可能ですか？`
A: Tokyo, Frankfurt, London, Dallasです。最新情報は以下を参照してください。
https://cloud.ibm.com/docs/services/Activity-Tracker-with-LogDNA?topic=logdnaat-regions

`Q: どのサービスに対応しており、どんなイベントが収集できますか？`
A: 以下を参照してください。
https://cloud.ibm.com/docs/services/Activity-Tracker-with-LogDNA?topic=logdnaat-cloud_services

以下は、CISのDNSにAレコード（参照先は8.8.8.8)を追加した時の例です。
<img width="1279" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/ee9d05e6-48ff-ef97-d5e4-8fe1bd6d79ff.png">


`Q: 幾つまでActivity Trackerを作成可能ですか？`
A: インスタンスはリージョンごとに１つしか作成できません。
https://cloud.ibm.com/docs/services/Activity-Tracker-with-LogDNA?topic=logdnaat-provision

`Q: どんなサービスプランがありますか？`
A: Lite（無償）, 7 Day Event Search(`$1.50 USD/Gigabyte-Month`), 14 Day Event Search(`$2.00 USD/Gigabyte-Month`), 30 Day Event Search(`$3.00 USD/Gigabyte-Month`)の4種類存在します。このうち、Lite PlanはLive streamingのデータ（リアルタイムデータ）しか確認できません。残りの有償プランであれば、各々定められた保管期間に対してイベントログを検索することが可能です。詳細は以下を参照してください。
https://cloud.ibm.com/observe/activitytracker/create
https://cloud.ibm.com/docs/services/Activity-Tracker-with-LogDNA?topic=logdnaat-service_plan

`Q: 後からプランを変更することはできますか？`
A: 下記から変更可能です。
<img width="1278" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/c67c140e-962e-cd5c-027f-5a4acd1a8027.png">


`Q: 過去のイベント情報を外部保管できますか？`
A: ICOS(IBM Cloud Object Storage)に保管することが可能です。詳細は以下を参照してください。
https://cloud.ibm.com/docs/services/Activity-Tracker-with-LogDNA?topic=logdnaat-manage_events#manage_events_archive
https://cloud.ibm.com/docs/services/Activity-Tracker-with-LogDNA?topic=logdnaat-archiving
Vue基礎：IE11対応

Vue.jsではIE11はサポートされないですね。画面は真っ白になってしまう場合があります。

babel-polyfillというツールで対応できます。
ただし、古いブラウザ対応のため変換したコードは、長いし、速度も遅いようです。

いつかIE11のサポートは対象外になると幸せですね。

#インストール
`npm install babel-polyfill --save`

#babel.config.js
```javascript
module.exports = {
  presets: [
    ['@vue/app', {
      polyfills: [
        'es6.promise',
        'es6.symbol'
      ]
    }]
  ]
}
```

#import "babel/polyfill"
main.jsにてVueと同じ位置でimport

```javascript
import Vue from 'vue'
import "@babel/polyfill";
```

#fetchメソッド
IE11ではfetchメソッドがないからエラーになる場合があります。
その際には、whatwg-fetchを利用して回避できます。

###1. インストール
`npm install whatwg-fetch --save`

###2. App.vueに設定追加
```javascript
import 'whatwg-fetch'

if (window.fetch === undefined) {
  window.fetch = fetch;
}
```

うまくいかない場合はIE11のコンソールのエラーを見てGoogle先生に聞きながら調整しましょう。

参考記事：https://cli.vuejs.org/guide/browser-compatibility.html#browserslist

以上
日付 YYYYMMDD が妥当な内容か? Oracle PL/SQL

```SQL:IS_YYYYMMDD
CREATE OR REPLACE FUNCTION IS_YYYYMMDD
    (
    IN_YYYYMMDD IN VARCHAR2 -- YYYYMMDD
    )
    RETURN VARCHAR2 -- 'OK' or 'NG'
--
--  日付 YYYYMMDD が妥当な内容か判断する。
--
IS
    L_DATE DATE ;
BEGIN
    L_DATE := TO_DATE(IN_YYYYMMDD, 'YYYYMMDD') ;
    RETURN('OK') ;
EXCEPTION
    WHEN OTHERS THEN
        RETURN('NG') ; -- エラー
END IS_YYYYMMDD ;
/
-- ↓実行権をPUBLICにし、インスタンスの全スキーマから実行可能に
-- https://docs.oracle.com/cd/E57425_01/121/SQLRF/statements_9014.htm#i2155015  SQL language reference
GRANT EXECUTE ON IS_YYYYMMDD TO PUBLIC ;
-- ↓PUBLIC SYNONYM に
-- http://docs.oracle.com/cd/E57425_01/121/SQLRF/statements_7001.htm#CJAJCDDF  SQL language reference
CREATE OR REPLACE PUBLIC SYNONYM IS_YYYYMMDD FOR IS_YYYYMMDD ;
```

```SQL:
-- 使用例
SQL> COLUMN YYYYMMDD    FORMAT A10
SQL> COLUMN IS_YYYYMMDD FORMAT A10
SQL> WITH DATE_LIST AS  -- since Oracle11.1.0
  2      (
  3      SELECT '20160229' AS YYYYMMDD FROM DUAL UNION ALL
  4      SELECT '20170229'             FROM DUAL UNION ALL
  5      SELECT '20180229'             FROM DUAL UNION ALL
  6      SELECT '20190229'             FROM DUAL UNION ALL
  7      SELECT '20200229'             FROM DUAL UNION ALL
  8      SELECT '20210229'             FROM DUAL
  9     )
 10  SELECT DL.YYYYMMDD
 11       , IS_YYYYMMDD(DL.YYYYMMDD) AS IS_YYYYMMDD
 12  FROM DATE_LIST DL ;

YYYYMMDD   IS_YYYYMMD
---------- ----------
20160229   OK
20170229   NG
20180229   NG
20190229   NG
20200229   OK
20210229   NG

6行が選択されました。
```
c++始めてみた：c++をJupyter Notebookで使う方法？？？個人ノート1.7

# c++をJupyter Notebookで使う方法？？？

~~（今思えば、C＋＋のビルド？コンパイル？してからPYTHONの様に動かすというC＋＋の流れはJupyter Notebookにそもそも合わないんじゃないか？と感じました）~~

以前から探していたC＋＋コードをJupyter Notebookで使う方法

複数件探し出しましたが、（VScodeを使っている現在）今更感があります。

ですが、一応メモとして、ここに残しておきます。

2017
[Interactive C++: Jupyter上で対話的にC++を使う方法の紹介 [Jupyter Advent Calendar 2017]](https://r9y9.github.io/blog/2017/12/21/jupyter-cxx/)

紹介している方法
- root/cling 付属のカーネル
- root/root 付属のカーネル
- xeus-cling
- Keno/Cxx.jl をIJuliaで使う

記事の筆者のお勧めとしては、Jupyter上でC＋＋だけを使うなら
condaに既に組み込まれているxeus-clingを使うといいらしいですが、外部ライブラリを使おうとするとエラーがあったらしいです（2017年）現在の状況は、試していないので不明です。

2019
[xeus-clingを実装している記事（英語）](https://www.learnopencv.com/xeus-cling-run-c-code-in-jupyter-notebook/)

Qiita先輩も挑戦してますね！
2018
[Qiita: Cling on Jupyter [C++] 環境づくり](https://qiita.com/pollenjp/items/93e9852d9530e36f986a)

2017年・2019年の記事で紹介していた
REPL – Read-Evaluate-Print-Loopなるものが、どういったものなのか興味があります。
正規表現によるスクレイピング

#正規表現によるスクレイピング
「Python クローリング＆スクレイピング」という本を読んでいて詰まってしまい解決した時の方法を載せます。

p49 リスト2.11
このまま打ち込むと
①UnicodeDecodeError: 'cp932' codec can't decode byte 0xef in position 130: illegal multibyte sequence
①を解決しても
②AttributeError: 'NoneType' object has no attribute 'group'
というエラーが帰ってきてしまう。

- ①の解決方法
　openメソッドにencoding=utf-8を追加
- ②の解決方法
  4つある「title =」　をtry: except: で囲みexcept:の中身はtitle = None　とする。

これでURLと書籍のタイトルが取得できるはず。

参考サイト
https://codeday.me/jp/qa/20190511/794837.html
Ubuntu18.04/Re:VIEW/docker-compose/zathuraを使った薄い本を書く手順

# モチベーション
- なるたけ楽して$LaTeX$使って薄い本を書く．
- ホスト環境を変更せずに素早く薄い本を書く．

# 使用するもの
- Docker（仮想環境を簡単/便利に扱えるツール）
- docker-compose（複数の仮想環境を簡単に扱えるツール）
- Re:VIEW（軽量マークアップ言語からpdf(latex), epubなどの書籍が簡単に作れるツール）
- zathura（vimのキーバインドが使える軽量PDFビューアー）

# 手順
## 1. Re:VIEWのDockerイメージをダウンロードする
```bash:bash
$ sudo docker pull vvakame/review
```

## 2. 薄い本の雛形を作成する
```bash:bash
$ cd
$ sudo docker run --rm -v `pwd`:/work vvakame/review /bin/sh -c "cd /work && review-init hello"
```
## 3. docker-composeを使ってpdfファイルを作成する
```bash:bash
$ cd

# 所有権を変更する
$ sudo chown -R solareenlo:solareenlo hello

$ cd hello

# Dockerfileを作成する
$ echo FROM vvakame/review > Dockerfile

# docker-compose.ymlを作成する
$ cat <<EOF > docker-compose.yml 
version: '3'
services:
  review:
    volumes:
      - .:/work
    build: .
    working_dir: /work
EOF

# pdfファイルを作成する
$ sudo docker-compose run review rake pdf
```

## 4. zathuraで作成したPDFを確認する
```bash:bash
$ sudo apt install zathura
$ zathura --fork book.pdf
```

## 5. いろいろ削除する
```bash:bash
# pdf作成過程で出来た不要なコンテナを削除する
$ sudo docker container prune

# Re:VIEWのDockerイメージを削除する
$ sudo docker image rm vvakame/review:latest

# zathuraを削除する
$ sudo apt uninstall zathura
```

# あとは好きなエディタとドキュメントを見ながら作成する

# 参考文献
- [kmuto/review](https://github.com/kmuto/review)
- [vvakame/docker-review](https://github.com/vvakame/docker-review)
データ収集からAI開発、Webアプリ公開まで全てPythonで済ませた話

# はじめに

こんにちは、はなたです。
今回は（一般的な？）機械学習プロジェクトの一連の流れである

**データ収集→データ整形→機械学習（AI）モデル開発→モデル活用・公開**

を全てPythonでやってみたよ、という記事です。プロジェクトと書きましたが、あくまで個人の趣味開発レベルです。



## 動機

大学院に入学してから機械学習について勉強し始めたのですが、実践する機会があまりありませんでした。kaggleは精度を競うゲームみたいな感じで個人的にはそこまで惹かれておらず、また自分で何か機械学習のモデルを作ろうと思っても「別に予測したいものなんてねえよ（笑）」という感じでした。

つい先日、[Webスクレイピングの記事](https://qiita.com/hanata/items/b5a973422b04634b822f)を書いたのですが、これを書き終えた後に今回のテーマを閃きました。今回のテーマは**「コード進行から曲のキーを判別するAIを作る」**です。自分の趣味である音楽の内容かつ、他に誰もやっていなさそうなアイデアだったので、寝食を忘れて開発に没頭しました。





# 完成したWebアプリがこちら
Djangoを使用して開発、herokuで公開しています。

[https://kja-app.herokuapp.com/](https://kja-app.herokuapp.com/)

![gui_do.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405491/95352bc0-21ae-78ad-322e-2067cb9feaa0.gif)
動作の様子

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405491/9e11a2e6-d075-758a-4fb2-42127441b45b.png)

現在は各キーの予測確率も表示させています。

コード譜掲載サイトで有名な[U-fret](https://www.ufret.jp/)に掲載されている曲のURLを入力すると、その曲のキーをAIが判断して表示してくれます。
※今のところU-fret以外のサイトは非対応です。今後、他のサイトやcsvインポートに対応するかも？



# 開発手順

以下の順序で開発しました。それぞれ詳細は記事にしましたので、興味のある部分を読んで頂ければ幸いです。



[0.設計編(キーを判別するAIとは？)](https://qiita.com/hanata/items/38163b6dddbc2ec8812e)
今回の目的である「キーを判別するAI」をプログラムに落とし込む過程が書いてあります。「そもそもコード進行とかキーってなんぞや？」という方のために、その辺の音楽理論についても軽く触れています。



[1.データ収集(クローリング)](https://qiita.com/hanata/items/cbc6cc377321a2880f5b)
今回作るAIは機械学習のモデルなので、訓練データが必要です。訓練データ収集について書いてあります。



[2.データ整形(スクレイピング)](https://qiita.com/hanata/items/692f98ee83295614599f)
集めたデータを機械学習モデルに突っ込めるよう、データ整形を行います。コード進行の情報を上手く扱うために、クラス設計を行いました。

[3.機械学習を用いたAIの開発](https://qiita.com/hanata/items/d1fb6241cccf405bbc58)←執筆中です
機械学習モデルとハイパーパラメータ選定について書いています。

[4.Djangoを用いたWebアプリ開発](https://qiita.com/hanata/items/968040a366c9bb1dbc93)
Django+Herokuでのデプロイについて書いてあります。


# おわりに
データ収集からWebアプリ開発まで、最初から最後までやり遂げられて非常に満足しています。しかし、モデルの予測精度やWebアプリの見た目など改善すべきところはたくさんあるので、時間を見つけて修正していきたいと思います。ここ直した方が良いよ、というコメントをお待ちしております！！！

あと予測が全然合ってねえよ！って曲がありましたら、教えていただけると幸いでございます。
Nextcloud 17 ベータ1 がリリースされました

Nextcloud の次期メジャーバージョンである Nextcloud 17 の実装機能が凍結され、最初のベータ版である **Nextcloud 17 beta1** がリリースされました。

※情報発信元: [Nextcloud 17 Beta 1 is out, time for some testing!](https://nextcloud.com/blog/nextcloud-17-beta-1-is-out-time-for-some-testing/)

※ダウンロードはここから: [Nextcloud 17 beta 1](https://download.nextcloud.com/server/prereleases/nextcloud-17.0.0beta1.zip)

今後はバグ修正や洗練を重ねて、予定では、2019年9月26日に正式リリース予定となっております。

### Nextcloud 17 今後のリリーススケジュール

* Beta 1: 2019-08-15　**← NOW !!**
* Beta 2: 2019-08-22
* Beta 3: 2019-08-29
* Beta 4: 2019-09-05
* RC 1: 2019-09-12
* RC 2: 2019-09-19
* Release: 2019-09-26

Nextcloud 社では、自動テストや動作確認のためのスモークテストは行っているものの、無数の使い方をテストすることを置き換えることはできないとして、テストの支援を求めています。バグ修正はもちろん、小さな UI 改善、細かい修正などのため多くのみなさまのテスト支援を求めています。

早速ダウンロードしてインストールしてみました。
以下は画面イメージの一例です。

①ファイル操作
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316764/105c3af9-ec99-5183-5a31-406d5e28135b.png)

②管理者 - 基本設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316764/36349854-58c9-700e-c901-f8122a8e70bf.png)

③管理者 - システム (現在の "モニタリング")
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316764/211c70fb-9439-8dbb-7e12-cf29d8c52ace.png)

大きな変化は確認できませんが、管理者のシステム画面 (現在のモニタリング画面) では、より細かい情報が出力されるようになっております。

またアプリについては、まだ未対応のものが多く、これから少しずつ対応するものが増えてくると思われます。

**★この記事は、[スタイルズ社のNextcloudサイト](https://nextcloud.stylez.co.jp/) の [Nextcloudブログ](https://nextcloud.stylez.co.jp/nextcloudblog)にも公開しております！**
ちょっとした編集でよく使う正規表現

# 目的
よく使う正規表現をメモ

# 含まない行
Valueを含まない行

```
^(?!.*Value).*$
```

# 何も無い空行
空文字で置換すれば、空行が削除できる。

```
^[\r\n]+
```

# 何も無い空行、またはスペース・タブのみの行
空文字の置換で削除。

```
^[ \t]*[\r\n]+
```

# 特定の文字より後の文字
「あ」より後の文字

```
(?<=あ)(.*)
```

# 特定の文字より前の文字
「あ」より前の文字

```
(.*)(?=あ)
```

# 最後に
こういうの必要なときにスラスラ書けたらいいですけど、諦めました。。
違うことを覚えることにしました。
tasksetとは

# tasksetとは
プロセスはロードバランサ機能によってシステムの負荷に応じて複数の論理CPUをまたいで実行することがあるらしい.
そこで, プログラムを１つの論理CPU上で実行させるためのコマンドとして, `taskset` と呼ばれるものが用意されている.

# つかいかた
tasksetコマンドは `-c` オプションで指定した論理CPU上で, 引数に与えたプログラムを実行する.
以下の場合, 論理CPU 0上で `a.out` というプログラムが走ることになる.

```
$ taskset -c 0 ./a.out
```

# CPUの情報を確認する
tasksetコマンドを使う前に, そもそもマシン上のCPUの情報を確認しておきたいというケースがある.
そういったときに使えるコマンドをまとめた.

### 物理CPUの確認
以下の実行結果の場合, 物理CPUは１つだと分かる(physical idが全て同一のため).

```
$ cat /proc/cpuinfo | grep 'physical id'
physical id	: 0
physical id	: 0
```

### 論理CPUの確認
以下の実行結果の場合, 論理CPUは２つだと分かる.

```
$ cat /proc/cpuinfo | grep processor
processor	: 0
processor	: 1
```

### コアの確認
以下の実行結果の場合, それぞれの論理CPUはコアを２つ持っていると分かる.

```
$ cat /proc/cpuinfo | grep 'cpu cores'
cpu cores	: 2
cpu cores	: 2
```

# 余談
ちなみにVirtualBoxでは, `設定 > システム > プロセッサー > プロセッサー数` から論理CPUの数をいじることができる.
LINE オープンチャットでBotは使えるか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/4632de3d-43b6-7f6a-8522-1c1bd0f9e9bb.png)
LINEの新機能「[OpenChat（オープンチャット）](http://official-blog.line.me/ja/archives/79902633.html)」が突如現れました。LINEのグループトーク機能を拡張した機能という説明があるので、Messaging APIを使ったBotが使えるか試してみました。
結果は・・・、Botは使えませんでした。（成功された方、いらっしゃいますか？）

#試したこと
[以前](https://qiita.com/yuppejp/items/ff64f488a78f8c2bc595)作ったテスト用のローカル環境で試してみました。

```javascript:index.js
'use strict';

const line = require('@line/bot-sdk');
const express = require('express');

// create LINE SDK config from env variables
const config = {
  channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
  channelSecret: process.env.CHANNEL_SECRET,
};

// create LINE SDK client
const client = new line.Client(config);

// create Express app
// about Express itself: https://expressjs.com/
const app = express();

// register a webhook handler with middleware
// about the middleware, please refer to doc
app.post('/callback', line.middleware(config), (req, res) => {
  Promise
    .all(req.body.events.map(handleEvent))
    .then((result) => res.json(result))
    .catch((err) => {
      console.error(err);
      res.status(500).end();
    });
});

// event handler
function handleEvent(event) {
  console.log(event);
  return Promise.resolve(null);
}

// listen on port
const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`listening on ${port}`);
});
```

サンプルのecho-botを招待してみました。従来のグループの場合はjoinイベントが飛んでくるのですが、オープンチャットの場合は何も飛んできませんでした。オープンチャットはグループトークの概念とは異なるようです。

#公式ガイドでは
LINEの使い方ガイドをみると、現在は通訳Botのみ使えるようです。
http://openchat-blog.line.me/archives/cat_36815.html

##翻訳Botのみ使える
スマホのLINEアプリで画面を確認すると、確かに固定の翻訳Botのみしか選択できません。
<img width="375" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/4857e37c-0a69-5ee8-8017-cf823ae53b5f.png">

##LIFFは使える
LINE Front-end Framework（LIFF）は正式サポートされていないようですが、一部機能は使えるようです。
https://developers.line.biz/ja/docs/liff/overview/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/7f4b4699-13f8-18c7-b32a-3f0b7cc5ab48.png)

Botが使えないのは仕様上なのか、これから使えるようになるのか不明ですが、オープンチャットでBotが使えると便利そうなので、今後に期待ですね。
build-essentialとは

# build-essentialとは
名前の通り, 開発に必須のビルドツールを提供しているパッケージ.
gcc(GNU C Compiler)とかg++(GNU C++ Compiler), makeとかその他色々入るらしい.

aptが使える環境の場合,

```
$ apt install build-essential
```

でインストールできる.

ちなみに `yum` での `build-essential` に相当するパッケージには `Developer Tools` があり,

```
$ yum install "Developer Tools"
```

でインストールできる.
初めてRails のサイトを Heroku でホスティングするときに躓いたPrecompiling assets failed. とrails credentials:edit

## 何があったか

RailsでHelloWorldを表示するサイトを作って，Herokuでホスティングしたい

``` 
git push heroku master
```

をすると，

``` 
$ Precompiling assets failed.
```

が出てくる．

## 結論

### エラーの本体

```
ArgumentError: Missing `secret_key_base` for 'production'environment, set this string with `rails credentials:edit`
```

Precompiling assets failed. はエラーの本体ではない？  
参考：[Herokuにpushしたらprecompile assets faild.が。pushできたと思ったらApplication Errorが。解決するまで。- Qiita](https://qiita.com/hellojtokyo/items/ef1d4a390f8cbb06f6b7)

### 対処法

以下のコマンドを打つ

```
$ heroku config:set RAILS_MASTER_KEY=<your-master-key>
```

your-master-keyはconfig\master.keyに書かれている文字列

例

```
$ heroku config:set RAILS_MASTER_KEY=123456789
```

参考：[Rails 5.2 with master.key - Heroku deployment - stackoverflow](https://stackoverflow.com/questions/49661757/rails-5-2-with-master-key-heroku-deployment)

## 何故このエラーが生じるのか

復号鍵を渡さないといけない？

詳細は以下に詳しく書かれてます．  
参考：[Rails 5.2 で ActiveSupport::MessageEncryptor::InvalidMessage - Qiita](https://qiita.com/scivola/items/cc06ddbfd94d3118f693)

## 最後に

最初，Precompiling assets failed.で調べてたので，かなり時間をとってしまった．  
ログはちゃんと見るべき

### その他参考にしたところ

https://railstutorial.jp/chapters/beginning?version=5.1#sec-exercises_hello_world

https://qiita.com/fuku_tech/items/b21e49ff49cb19f04838

https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39
lessコマンド

# 目次

* [はじめに](#はじめに)
* [コマンド](#コマンド)

# はじめに

忘れがちなlessのコマンド(オプション)を残します。(2017.09)
普段lessを使用しないので内容が凄く薄い。。。

# コマンド

`-N`　行番号表示　※1
`-S`　(長い行を)1行で表示　※1
`-M`　ファイル名&行数&位置の表示　※1
`g`　ファイルの先頭に移動
`G`　ファイルの末尾に移動
`h` or `H`　ヘルプを表示
`q` or `Q`　終了

※1　コマンドを2回実行すると元に戻ります。  

`&pattern` grep の様にpatternが含まれる行だけ表示
`Shift+F` tail -f の様に自動更新
`Ctrl+C` tail -f を停止

その他コマンドは `less --help` 参照

# オプション
`+F`　tail -f の様に自動更新
`-S`　(長い行を)1行で表示
RaspberryPiでLチカをやってみた

# -
独学初心者がRaspberryPiを使って色々動かしてみる記事です。
あくまで備忘録として書いていますが間違っているところ、アドバイスなどがあればコメントお願いします:bow_tone1:

今回はラズパイでLチカをやってみます
~~正直LED光らせたところで何も役に立たなそうだしやる意味あんのか？~~と思っていましたがその考えは全くの間違えでした

触って動かすことが大事でそこから色々学べたし次に何を学ぼうかを考えるのもできてものすごいいいきっかけになりました

# 前提条件
- RaspberryPi Model B+
- Python 3.7.4



# 用意するもの
**ブレッドボード**
![EC6F76FE-A010-49E0-81C8-8B0F6CEB1DDC.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149008/e08b2265-95aa-e6db-24b3-5b5199e71caa.jpeg)

裏側に金属版がはめ込まれてて列で電気が通るようになっている
何も知らなかった、、、



**ジャンパワイヤ（オス-メス） 2本**
![8B4E2C8F-E99C-49DC-9817-0E21D028E8CD.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149008/0c3a88ab-491f-5780-9933-b73205eae870.jpeg)


**抵抗　220Ω**
![A2C32F23-F8B6-4AF5-9C06-1FD5D0057ADC.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149008/52c75951-fe36-22d0-bb6d-7e995dd364f6.jpeg)

**LED 2V 10mA**
![12E89936-2356-40A2-B17C-B1ABEA681811.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149008/213e83fd-3506-16ab-c10d-a0fb8a402354.jpeg)



# 抵抗の計算
ラズパイの電圧が3.3vでLEDが2vなのでこのまま電源を繋ぎプログラムを実行すると壊れてしまう

そこで中学のとき寝ながら聞いてたオームの法則を調べてみる

**電圧**を求めるとき
`電圧 = 抵抗 × 電流*
(E = R × I)
(V = Ω × A)
`

**電流**を求めるとき
`電流 = 電圧 ÷ 抵抗
(I = E ÷ R)
(A = V ÷ Ω)`

**抵抗**を求めるとき

`抵抗 = 電圧 ÷ 電流
(R = E ÷ I)
(Ω = V ÷ A)`

それぞれ公式を書いたけど意味は全部同じ
サイトごとに使われてるアルファベットが違うから全て記述した

これを踏まえて

ラズパイ 3.3V
LED 2V 10mA

ラズパイ - LED = 1.3V
1.3 ÷ 0.01 = 130Ω

*130Ω*の抵抗が必要

持っている大きさが近い抵抗を使う
大きすぎるとつかなかったり小さかったりする

# LEDを光らせてみる

こんな感じ

![9BB37AD3-4300-4E3F-8831-944BD612C18F.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149008/18da81c0-9be4-30cc-f35a-8203096f2bac.jpeg)


GPIO
1番　3.3V +
6番　GND -

GPIOの1番は3.3Vの電流を発している
6番で電気を逃している

ただ、このままではLEDが光っぱなしで面白みがないのでここからLチカさせる

# Lチカさせてみる
GPIO
6番 GND -
8番 14ポート +

```led.py
import RPi.GPIO as GPIO
import time

LED = 14 # ピン番号8番、14ポート
GPIO.setmode(GPIO.BCM) # GPIOをポート番号で指定する
GPIO.setup(LED, GPIO.OUT) # ポート状態の設定 出力

print('-----start-----')

for i in range(1,11):
    print('{}回目'.format(i))
    if GPIO.input(LED) == 0:
        # LEDが点灯していなければ点灯させる
        GPIO.output(LED, GPIO.HIGH)
        time.sleep(1)
    else:
        GPIO.output(LED, GPIO.LOW)
        time.sleep(1)
        
print('-----end-----')

GPIO.cleanup() # クリーンアップ(初期化)

```

プログラムの説明は後日追加で書く

### 実行する

![E6F4AEDD-F3BF-4C7F-88D0-6B57F6FE1578.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149008/bca2b45c-26b3-b602-2288-7d1c101a2a7a.gif)

うまく動いた！

# まとめ
- Lチカはあまり興味なかったけど色々学べた
- プログラム自体はそこまで難しくなかったけどこれからもう少し理解して追記する
- 電気の知識をつける(まずは小中高くらい)
- 文章力、構成力をつけたほうがいい

# 参考書籍
[やさしくはじめるラズベリー・パイ ~電子工作で簡易ロボット&ガジェットを作ってみよう~ ](https://www.amazon.co.jp/dp/4839961638/ref=cm_sw_r_cp_api_i_vAYwDb5BKF4Z9)

＊2019/08/23　編集済み
Docker 上で Pytorch を実行している際に DataLoader worker (pid xxx) is killed by signal: Bus error.  というエラーが出る

Docker コンテナ上で pytorch を動かしているときに、  

```bash
DataLoader worker (pid xxx) is killed by signal: Bus error. 
```

というエラーが出ました。
原因を調べたのでメモしておきます。

エラーメッセージをググると、 Pytorch のフォーラムでのディスカッションが出てきます。  

https://discuss.pytorch.org/t/shm-error-in-docker/22755

どうやら、shared memory が足りていないらしい。  
ためしに以下のコマンドを打つと、

```bash
$ df -h
```
以下のような感じになっていました。

|Filesystem   |   Size | Used | Avail | Use% | Mounted on|
|:-:|:-:|:-:|:-:|:-:|:-:|
|shm          |    64M  |   0 |  64M  | 0% |/dev/shm|


64M しか確保されていない。

この問題は、docker run もしくは docker-compose up をするときに解決することができます。


https://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources
https://stackoverflow.com/questions/30210362/how-to-increase-the-size-of-the-dev-shm-in-docker-container

docker run の場合、

```
docker run --rm -it --shm-size=256m Image /bin/sh
```
というふうに `--shm-size` というオプションを渡してあげればよいです。  
渡せる値の形式は `<number><unit>` となっており、 
numberは0より大きい整数、unitは、b, k, m, g のうちから一つ選択となっています。  

docker-compose も同じで、

```yml:docker-compose.yml
build: .
shm_size: '2gb'
```
といった感じで書けるようです。

実際、 `docker-compose.yml` に `shm_size: '2gb'` を追加して実行すると、  

|Filesystem   |   Size | Used | Avail | Use% | Mounted on|
|:-:|:-:|:-:|:-:|:-:|:-:|
|shm          |    2.0G  |   0 |  2.0G  | 0% |/dev/shm|

というふうに出力されて、無事めでたく shared memory の容量が増やせています。


---
2023/5/7 追記

以前この記事では、 
```yml:docker-compose.yml
build: 
  - context: .
  - shm_size: '2gb'
```
のような書き方ができると書いていましたが、うまく動かなかったので、ChatGPT に聞いてみたところ、buildの中に書く書き方は間違っているようでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115634/7d439503-2d41-38f5-9ef7-113c1c6f3b4b.png)

真偽の程は不明ですが、とりあえず解決できたので、参考になれば。

---
viコマンド

# 目次

* [はじめに](#はじめに)
* [画面分割](#画面分割)
* [モード切替](#モード切替)
* [カーソル移動](#カーソル移動)
* [検索](#検索)
* [置換](#置換)
* [コピー](#コピー)
* [貼り付け](#貼り付け)
* [削除](#削除)
* [元に戻す](#元に戻す)
* [行を連結する](#行を連結する)
* [ファイル操作](#ファイル操作)
* [その他](#その他)

# はじめに

vi(Vim)エディタを使うことが多いので、よく使うけど忘れがちなものだけメモを残します。
※ 気付き時点で追記します。
※ `:set`は`:se`で記載しています。

確認バージョン：
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Jan 20 2017 04:38:11)

# 画面分割

`Ctrl+w s`, `:split`　画面分割(上下)
`Ctrl+w v`, `:vsplit`　画面分割(左右)
`Ctrl+w w`　画面移動(順番に移動)
`Ctrl+w k`　画面移動(↑)
`Ctrl+w j`　画面移動(↓)
`Ctrl+w h`　画面移動(←)
`Ctrl+w l`　画面移動(→)
※画面分割解除は `:q` でウィンドウを閉じる

# モード切替

`i`　コマンドモード->入力モード(カーソル位置に文字を入力)
`a`　コマンドモード->入力モード(カーソルの後ろに文字を入力)
`o`　コマンドモード->入力モード(カーソルの下に文字を入力)
`O`　コマンドモード->入力モード(カーソルの上に文字を入力)
`<ESC>`　入力モード->コマンドモード

# カーソル移動

`:行番号`　指定した行番号へ移動
`G`　ファイルの末尾
`h`　左へ1文字
`j`　下へ1文字
`k`　上へ1文字
`l`　右へ1文字
`w`　次の単語へ
`0`　行の先頭
`$`　行の末尾

# 検索

`/検索文字列`　次を検索
`?検索文字列`　前を検索
`*`　カーソル位置の単語を検索
`#`　カーソル位置の単語を逆方向に検索
`%`　対応する括弧を検索
`n`　次へ
`N`　前へ
`:noh`　ハイライトを消す

# 置換

`:s/置換対象文字列/置換後文字列/`　行内で1つ置換
`:s/置換対象文字列/置換後文字列/g`　行内で全部置換
`:%s/置換対象文字列/置換後文字列/g`　ファイル内で全部置換
　→　`c` を付ける　確認しながら置換
　例) `:%s/置換対象文字列/置換後文字列/gc`

# コピー

`yy`　1行
`yw`　1単語
`y0`　カーソル位置から行頭まで
`y$`　カーソル位置から行末まで

# 貼り付け

`p`　カーソルの右(下)
`P`　カーソルの左(上)

# 削除

`x`　1文字削除
`dw`　1単語削除
`dd`　1行削除
`dG`　カーソル位置からファイル末尾まで削除

# 行を連結する

`J`　行を連結する
`gJ`　行を連結する(スペースを挿入しない)

# 元に戻す

`u`　1つ戻す(Undo)
`Ctrl+r`　Undoを1つ戻す(Redo)

# ファイル操作

ファイルを開く／保存する／閉じる

`:e ファイル名`　ファイルを読み込む
`:e`　ファイルを再読み込み

`:w`　保存(上書き)
`:w ファイル名`　ファイル名で保存

`:q`　終了

# その他

`:se nu`　行番号表示(:set number)
`:se nonu`　行番号非表示(:set nonumber)
`:se ff=ファイルのフォーマット`　ファイルの改行コードを変更する
　→　`ff=dos`　DOS(Windows)の形式
　→　`ff=mac`　Macの形式
　→　`ff=unix`　UNIXの形式
　→　`ff`　現在設定されている形式を表示

`:help`　ヘルプを表示
webarenaでubuntu その19

#概要

webarenaでubuntu18.04やってみた。
postfix3.3やってみた。
dovecotやってみた。
windowsメーラーでやってみた。

#インストール

```
sudo apt-get install dovecot-pop3d
```

#master.cfの修正

```
submission  inet   n	 -	 n	 -	 -	 smtpd
```

#dovecot.confの修正

```
listen = *
```

#10-auth.confの修正

```
disable_plaintext_auth = no
```

#ポートの開放

```
tcp:110,110,ip4:0.0.0.0/0
tcp:587,587,ip4:0.0.0.0/0
```

以上。
Altairでデータをフィルタリングして表示するインタラクティブなグラフ

## 背景
* 筆者は ~~ル＊ン三世~~  Jake先生[^1]の大ファンである。
* 筆者は初心者なので色々勉強のためにQiitaに投稿している。
* 下記YouTube動画でAltairに魅せられたので、Altairの記事を書きたくなった。

[Jake VanderPlas - Exploratory Data Visualization with Vega, Vega-Lite, and Altair - PyCon 2018](https://www.youtube.com/watch?v=ms29ZPUKxbU)

[^1]: O'reilly社の「Pythonデータサイエンスハンドブック」の著者、天文学者、データサイエンティスト [Jake VanderPlas](http://vanderplas.com/)

* アルタイル（伊）/ アルテアー（英）/ 彦星（日）　、オサレである。

## 目的
* Altairの基本的な使い方を学ぶ
* ソフトウェアエンジニアがいないところでドヤ顔できる成果物を仕上げる

## 結果
目論見通りのインタラクティブなグラフを作成することができた。
ドヤ顔できそうだが、「Excelでも出来るモンスター」に何か言われたときに差別化できる特徴をみつけておきたくなった。

## ポイント（以下をどうしたか今後解説を加える）
* グラフ作成のテンプレ
* 軸範囲指定
* Log軸
* データ選択用の仕組み
* 2つ以上のチャートの配置
* グラフタイトルの表示

## コード

```python
import altair as alt
from vega_datasets import data

cars = data.cars()
```


```python
click = alt.selection(type='multi', encodings=['x', 'y'])

scatter1 = alt.Chart(cars).mark_point().encode(
    alt.X('Horsepower:Q',
          scale=alt.Scale(type='log', domain=(30, 300)),
          axis=alt.Axis(title='Horsepawer[MPa]')),
    alt.Y('Miles_per_Gallon:Q',
          scale=alt.Scale(domain=(0, 50))),
    color=alt.condition(click, 'Origin:N', alt.value('lightgray'), legend=None),
    tooltip=['Name:N']
).properties(
    selection=click,
    title='Once a famous cars data')

base = alt.Chart(cars).mark_point().encode(
    alt.X('Cylinders:N'),
    alt.Y('Origin:N'),
    color=alt.condition(click, 'Origin:N', alt.value('lightgray'), legend=None)
).properties(
    selection=click,
    title='Data selector with [Click + Shift-key]')


plot = base | scatter1
plot.save('plot.html')
plot
```

## 成果物
jupyter lab (or notebook)上に以下の表示が得られます。
htmlとして出力することも可能です。
本来はグリグリ動きますが、ここでは画像としてアップロードしました。
（htmlの良い公開方法を知らない・・・） 

### 出来立てほやほや
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312064/e0122316-cf87-f02b-3e31-f40599208bcc.png)

### データ選択してみたところ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312064/fed1cfe6-cabb-fe6f-bcc2-822c0759e497.png)
git switchとrestoreの役割と機能について

先日8/16にGitバージョン2.23.0がリリースされました。
今回の目玉機能と言えば、新しいコマンド `git switch` と `git restore` ですね！
本稿ではこちらの2つに絞ってどういう役割・位置づけの機能なのか英語ソースの引用も含めてご説明します。

## TL;DR
 + ブランチの変更は `git switch`
 + ファイルの変更は `git restore`
 + 今まで通り `git checkout` は使える
 + 新機能は「実験的機能」なので今後変更の可能性あり

## 新機能が追加された背景

[Highlights from Git 2.23](https://github.blog/2019-08-16-highlights-from-git-2-23/)によると、 `git checkout` に出来ることがあまりに多いため（ブランチ操作のほか、indexされたファイルの復旧、履歴上のファイルの取得など）、役割を明確に分けるためのコマンドが追加されたとのことです。

>It turns out git checkout can do quite a lot.
(中略)
>The new commands, by contrast, aim to clearly separate the responsibilities of git checkout into two narrower categories: operations which change branches and operations which change files. To that end, git switch takes care of the former, and git restore the latter.

ブランチの変更は `git switch` に、ファイルの変更は `git restore` に役割を分けています。
git 2.23.0のドキュメントを見ても、各コマンドの役割が分けられたことで分かりやすくなっています。

**公式ドキュメント(英語)**
[git-checkout](https://git-scm.com/docs/git-checkout/2.23.0) | [git-switch](https://git-scm.com/docs/git-switch/2.23.0) | [git-restore](https://git-scm.com/docs/git-restore/2.23.0)


**git checkoutのオプション**

```
git checkout [-q] [-f] [-m] [<branch>]
git checkout [-q] [-f] [-m] --detach [<branch>]
git checkout [-q] [-f] [-m] [--detach] <commit>
git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>]
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>…​
git checkout [<tree-ish>] [--] <pathspec>…​
git checkout (-p|--patch) [<tree-ish>] [--] [<paths>…​]
```

**git switch**

```
git switch [<options>] [--no-guess] <branch>
git switch [<options>] --detach [<start-point>]
git switch [<options>] (-c|-C) <new-branch> [<start-point>]
git switch [<options>] --orphan <new-branch>
```

**restore**

```
git restore [<options>] [--source=<tree>] [--staged] [--worktree] <pathspec>…​
git restore (-p|--patch) [<options>] [--source=<tree>] [--staged] [--worktree] [<pathspec>…​]
```

特に `git restore` についてはオプションも含めて意味が明確で分かりやすくなったと感じます。

## 各コマンドと `git checkout` との比較

基本的には「機能を分けること」が目的であり、使い勝手は大きく変わらないです。

### git switch
`git switch` はその名の通り、 `checkout` で行っていたブランチの変更を担当します。

```bash
# ブランチの切り替え
git checkout <branch>
git switch <branch>

# ブランチを新規作成して切り替え
git checkout -b <branch>
git switch -c <branch>
```

### git restore
`git restore` はファイルの変更に使用します。ファイルを復旧させる時に使うことが多そうなので、良いネーミングですね。

```bash
# ファイルの変更を取り消す
git checkout -- <filename>
git restore <filename>

# 特定ファイルを特定のコミットの状態にする
git checkout <commit> -- <filename>
git restore --source <commit> <filename>
```

**--worktree と --staged オプション**

`git restore` コマンドは `git reset` のようにステージングエリアも変更出来るようになっています。

```bash
# ステージングエリアにあるファイルを復旧する（実ファイルへの変更はそのまま）
git reset <filename>
git restore --staged <filename>

# ワークツリー上のファイルを復旧する（実ファイルの変更がリセットされる。checkoutの例と同様）
git reset --hard <filename>
git restore --worktree <filename> # オプションがない場合、デフォルトで --worktree オプションが付きます
```

## まとめ

個人的には `git checkout` の「機能全部乗せ感」がちょっと使いづらく感じていたので、今回の新機能は率先して使っていくつもりです。
ただ、これらの機能はあくまで "*Experimental alternatives*(実験的な代替手段)" ということなので（マニュアルにも書いてある）、今後仕様変更される可能性もありますので、使用される方は気に留めるようにしてください。
Python の print を C++ でも (n 番煎じ)

# はじめに
[Pythonみたいなprint関数をC++で書きたい！](https://qiita.com/Lily0727K/items/06cb1d6da8a436369eed)
上の記事に触発されて自分でも書いてみた話。

# 方針
- `operator<<` が使える場合は優先して使う
- Range, Set, Map, Tuple っぽいものが現れたらいい感じに表示する
- Python の `print` らしくするために、キーワード引数 (sep, end, file, flush) を実装する

# 実装
`operator<<` が使えるかを知るために、今回はクラステンプレートと `std::void_t` による detection idiom を用いる。

```cpp
template <class Stream, class T, class Void = void>
struct is_insertable : std::false_type {};

template <class Stream, class T>
struct is_insertable<Stream, T,
  std::void_t<decltype(std::declval<Stream>() << std::declval<T>())>
> : std::true_type {};

template <class Stream, class T>
constexpr bool is_insertable_v = is_insertable<Stream, T>::value;

static_assert(is_insertable_v<std::ostream &, int>);
```

Range などの検出も同様に行う。コンセプトがあれば楽なのかもしれない。

キーワード引数は、まあ愚直に実装する。予期せぬ代入を避けるため、名前の頭にアンダースコアをつけるのがよいと思われる ([参考](https://www.boost.org/doc/libs/1_71_0/libs/parameter/doc/html/index.html#keyword-naming))。

# できたもの
[pyprint.hpp](https://github.com/iorate/pyprint/blob/master/pyprint.hpp)
C++17 必須。GCC 9.1.0、Clang 8.0.1、Visual C++ 14.2 でたぶん動いている。

# 例

```cpp
// ... 標準ライブラリのインクルード ...

#include "./pyprint.hpp"

int main() {
  using namespace std;
  using namespace pyprint;

  // 基本
  print(42, 3.5, "Hello, world!");
  // 42 3.5 Hello, world!

  // Range
  print(vector<vector<string>>{{"foo"s, "bar"s,}, {}, {"baz"s, "qux"s}});
  // [[foo, bar], [], [baz, qux]]

  // Set と Map
  print(set{42, 23, 50}, unordered_map<string, int>{{"hoge"s, 15}, {"fuga"s, 21}});
  // {23, 42, 50} {fuga: 21, hoge: 15}

  // Tuple
  print(pair{'A', "bcd"sv}, tuple{list{1, 2}, set{'A', 'B'}});
  // (A, bcd) ([1, 2], {A, B})

  // キーワード引数
  print(42, L"Hello, error!", _file = wcerr, _sep = L'\n', _end = L"\n-- END --\n");
  // 42
  // Hello, error!
  // -- END --
}
```

# Q&A
Q. [{fmt}](https://github.com/fmtlib/fmt) とかでよいのでは?
A. せやな
VPNの次の選択肢Software-Defined Perimeter(SDP)って何？

![appgatesdp.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/27a3ca0c-2738-01dd-ef49-2c754176d08c.jpeg)

佐藤です。いつまでVPNの運用をすれば良いかお悩みではないですか？

# 閉域網へアクセスするためのVPN
閉域網へのアクセスをしたいとなれば、VPNルータを用意すると思います。
理由はいくつかありますが、閉域網への通信経路を暗号化して安全に通信するため、
また、特定のユーザー、クライアントを認証してから、外部からのアクセスする手段を提供するためが主な理由と思います。

# VPNの運用はつらい
しかし、VPNの運用は大変です。
接続するユーザーの最大数に合わせて、物理的な機器とライセンスを用意する必要があります。
また、通常のVPNルータでは基本的にL3レベルまでのネットワーク制御を行うため、クライアントからの通信がすべて閉域網に流れ、ネットワークの増強も合わせて必要になります。
信頼されているユーザーであるかは、証明書を配布することによって担保され、証明書期限に合わせて更新する作業も必要になります。
つまり、運用は大変です。

# VPNだから安全？
VPNを導入したからと言って、外部からのアクセスが安全にできると断言することは難しいです。
閉域網内に機密情報があるのではなく、SaaS上、例えばBoxに機密情報があるのであれば、VPNを必要とせず仕事ができるようになります。
その場合、閉域網内で担保しているセキュリティ、例えばプロキシを経由せず仕事もすることができます。
セキュリティポリシーを一貫して担保したい情シスはSaaS側にIP制限をしようと考えますが、それではVPNの運用負荷は楽にはなりません。
今後SaaSのみを利用して業務がすべて行われればVPNは不要になりますが、そう簡単ではありません。

# すぐにはSaaSへの移行はできない
閉域網内にシステムを一度でも構築した環境では、閉域網が提供する最大の機能「ネットワーク内が安全」でという前提から逃れることが困難です。
SaaSを推進しようにも、オンプレミスのシステムと同時に展開していくと閉域網の物理的な制約と常に戦い続けます。
この過渡期をVPNという選択肢で戦うのではなく、Software-Defined Perimeter(SDP)のフレームワークに基づいた製品を導入することを選択肢に入れることで、柔軟なネットワーク設計ができるようになります。

# SDPって？
SDPは「境界線（Perimeter）をソフトウェア上、IaaSで構築することができ、コントラストで集中的に制御し、アクセス制御に関わる設定を柔軟に動的に変更して安全にデータを転送する」技術のことです。
IaaS上で構築できるため、キャパシティの増減が行い易くなります。
また、システムがAWSにあっても、オンプレミスであっても、アクセス先となるゲートウェイを複数配置できるためハイブリッドクラウド環境にも適しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/974362c8-871d-b5a6-68b5-dbd126ce72e4.png)
引用：https://procureadvisor.com/the-definitive-guide-to-software-defined-perimeter/

# AppGateSDPとは？
SDPを取り入れている製品として、Cyxtera(シクステラ)社が提供している「AppGateSDP」という製品があります。
このSDPの考えで、最大のメリットは、コントローラーで複数のゲートウェイを構築することができ、コントローラーでユーザーのアクセスを認証する場合には、IdPと連携することができます。
これによってSaaSへのアクセスの認証基盤と閉域網へのアクセスを1つのID、セキュリティポリシーで統一することができます。AppGateSDPはそれを実現できる製品です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/66e33df3-1b33-64b1-dee0-47bd9166958f.png)
引用：https://www.techmatrix.co.jp/product/appgate/

# さらに柔軟なアクセス
認証認可のメリットだけではないです。
VPNではL3レベルでのネットワーク制御となりますが、AppGateSDPでは、ドメイン単位、例えばbox.comの通信のみはゲートウェイを通過するようにできます。
その他のSaaSへの通信は端末からそのままインターネットへ抜けることができます。
つまりは、L7レベルの通信制御をコントローラーで中央集約して管理するすることができます。
この機能を利用すれば、閉域網への通信トラフィックを最小限に抑えることもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/d1c582db-f172-92d8-62b4-dcce5c620d85.png)
引用：https://www.techmatrix.co.jp/product/appgate/

# まとめ
VPNの保守切れ対応に合わせて、SDPの考えを取り入れた製品を検討するなどが現実的ではないかと考えます。
SDPを取り入れている製品を徐々に組み合わせていくことによって、さらにネットワークは柔軟にすることができると思います。
Gridsome+AWS CloudFront+S3でリロードでAccessDeniedされたときに確認すること

備忘録です

# やりたいこと

* GridsomeでbuildしたページをCloudFront + S3の構成で配信する。
    * 多分Gridsome関係ない。SPA全般に当てはまる
* SPAなので、実際のS3には存在しないパスがある。
* トップページからアクセスすればなんとかなるけど、リロードすると Access Denied されちゃうので、なんとかしたい

# やりかた

* エラーページをindex.htmlに設定する
* S3の Static website hosting を CloudFrontのOriginに設定する

以下を参考にさせていただきました
[AWSのCloudFront&#43;S3でSPAするときにErrorPagesを使いたくない | AreaB Blog](https://area-b.com/blog/2017/12/02/2205/)

## 詳細

### S3のバケットポリシーを設定する

```json:S3BucketPolicy
{
    "Version": "2008-10-17",
    "Statement": [
        {
            ...
        }, 
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        },
        {
            ...
        },
    ...
}
```

### S3のStatic website hosting を設定する

* "このバケットを使用してウェブサイトをホストする"
* インデックスドキュメント: index.html
* エラードキュメント: index.html
    * 参照元はこの設定ではないが、これでも動作する
    * この時点で、Static website hosting エンドポイントではリロードを含めた操作ができるようになるはず

### CloudFrontを設定する
* Originを設定する
   * **このときサジェストされるS3ではなく、Static website hosting エンドポイントを設定すること**
        * ここでハマった
        * Origin Type が Custom Origin(S3 Originではない)
   * サジェストされるS3(S3 Origin)を設定すると、先に記載したとおりトップからはアクセスできるが、リロードするとAccess Denied

# そもそも
* 静的サイト開設時にCloudFrontにS3 Origin設定しろってどこにも書いてない
    * どこかで勘違いしていたらしい
.NET Coreで オブジェクト を JSON に変換する

# 概要
.NET Core でオブジェクト (POCO) を JSON に変換する方法です。

# 環境
- Windows10
- Visual Studio 2019
- .NET Core 2.2

# コードサンプル
サンプルコードを Github にアップしています。
https://github.com/tYoshiyuki/dotnet-core-convert-json

# 解説
変換対象のクラスを準備します。
ポイントとして変換対象となるクラスに DataContract を付与します。
また、変換対象となるメンバーに DataMember を付与します。
JSONのキー名は通常小文字になるかと思いますので、Name でキー名を設定します。

```C#

[DataContract]
public class SampleModel
{
    [DataMember(Name = "intValue")]
    public int IntValue { get; set; }

    [DataMember(Name = "stringValue")]
    public string StringValue { get; set; }

    [DataMember(Name = "dateTimeValue")]
    public DateTime DateTimeValue { get; set; }

    [DataMember(Name = "listValue")]
    public List<string> ListtValue { get; set; }

    [DataMember(Name = "mapValue")]
    public Dictionary<string, string> MapValue { get; set; }

    [DataMember(Name = "subSampleModel")]
    public SubSampleModel SubSampleModel { get; set; }
}

public class SubSampleModel
{
    [DataMember(Name = "intValue")]
    public int IntValue { get; set; }

    [DataMember(Name = "stringValue")]
    public string StringValue { get; set; }
}

```

データの変換には System.Runtime.Serialization.Json の DataContractJsonSerializer を利用します。
![2019-08-20_001733.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/353069/98171cad-ce8b-8635-8e99-610efc4c61c0.png)

```C#

var settings = new DataContractJsonSerializerSettings
{
    UseSimpleDictionaryFormat = true,
    DateTimeFormat = new DateTimeFormat("yyyy-MM-dd'T'HH:mm:ss.fff'Z'"),
};

var model = new SampleModel
{
    IntValue = 10,
    StringValue = "ABC",
    DateTimeValue = DateTime.Now,
    ListtValue = new List<string> { "First", "Second", "Third" },
    MapValue = new Dictionary<string, string>() { { "Key01", "Val01" }, { "Key02", "Val02" } },
    SubSampleModel = new SubSampleModel { IntValue = 20, StringValue = "DEF" }
};

using (MemoryStream ms = new MemoryStream())
{
    var serializer = new DataContractJsonSerializer(typeof(SampleModel), settings);
    serializer.WriteObject(ms, model);
    Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}

```

DataContractJsonSerializerSettings の UseSimpleDictionaryFormat = true とすることで、
Dictionary を キー : 値 の形式で出力する事が出来ます。
また、DateTimeFormat を設定することで日時フォーマットの出力形式を変更する事ができます。

```json

{
	"dateTimeValue": "2019-08-20T00:32:57.420Z",
	"intValue": 10,
	"listValue": [
		"First",
		"Second",
		"Third"
	],
	"mapValue": {
		"Key01": "Val01",
		"Key02": "Val02"
	},
	"stringValue": "ABC",
	"subSampleModel": {
		"intValue": 20,
		"stringValue": "DEF"
	}
}

```
Project Euler 57をPythonでやってみる

# 問題57
英語
https://projecteuler.net/problem=57
日本語
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2057

# 解答57
この問題の第$n$項目の連分数を$a_n$とすると1〜4項目は以下のようになる。

```math
\begin{align}
a_1 &= 1+\cfrac{1}{2} = \cfrac{3}{2} \\
a_2 &= 1+\cfrac{1}{2+\cfrac{1}{2}}=\cfrac{7}{5} \\
a_3 &= 1+\cfrac{1}{2+\cfrac{1}{2+\cfrac{1}{2}}}=\cfrac{17}{12} \\
a_4 &= 1+\cfrac{1}{2+\cfrac{1}{2+\cfrac{1}{2+\cfrac{1}{2}}}}=\cfrac{41}{29}
\end{align}
```
上の4つにおいて次の$*$の部分に注目する。

```math
1+\cfrac{1}{*}
```

すると、$*$は前の項に1を足したものになっていることが分かる。
この関係を漸化式にすると次のようになる。

```math
a_{n+1}=1+\cfrac{1}{a_n+1}
```

さらに$a_m$の分子を$N_m$ , 分母を$D_m$とおくと次のような関係が分かる。($N_m,D_m$は互いに素)

```math
\begin{align}
a_{m+1} = \cfrac{N_{m+1}}{D_{m+1}} &= 1+\cfrac{1}{1+\cfrac{N_m}{D_m}} \\
&= 1+\cfrac{D_m}{N_m+D_m} \\
&= \cfrac{N_m+2 \cdot D_m}{N_m+D_m}
\end{align} \\
\therefore N_{m+1} = N_m+2 \cdot D_m \\
N_{m+1} = N_m+D_m
```

ここまで分かったのであとは分母と分子をそれぞれ更新して桁数をチェックしていけばいいです。
コードは次のようになります。

```python:ProjectEuler51.py
def next(num_tpl):
    return (num_tpl[0]+2*num_tpl[1],num_tpl[0]+num_tpl[1])

count = 0
fraction = (3,2)
for i in range(1,1000):
    fraction = next(fraction)
    if len(str(fraction[0])) > len(str(fraction[1])):
        count += 1

print(count)
```

0.091 seconds
圧縮しながらSSHでファイル転送する

## 概要
別サーバにファイル転送をする際にローカルで一度吐き出す処理をせず、そのまま転送したい場合がある。
いろいろな用途で使えるためメモとして残しておく

## コマンド例
```
$ tar zcvf - images | ssh hostname "cat > ~/images.tar.gz"
```
UE4.22にインポートしたスケルタルメッシュがモバイルで表示されないときの対策

#はじめに
Blenderで作成したキャラクターをUE4にスケルタルメッシュとしてインポートしてOculusQuestで見ようとしたら表示されない！調べてみたら英語情報は見つかったけど日本語情報が見つからなかったのでメモ書きとして残します。

#発生した問題
表示したいスケルタルメッシュはこれ。UE4のビューポートでは問題なく表示されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/42c47a5b-9c31-3d14-c9e3-b979a49a53bf.png)
けど、OculusQuestでは表示されない・・・。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/19c361fc-1043-26d9-65ab-b8d613ab0793.png)

#Mobile Previewerを使ってみる
[Unreal Engine 4 ドキュメント Mobile Previewer](https://docs.unrealengine.com/ja/Platforms/Mobile/Previewer/index.html)
> 選択されたモバイル プラットフォームに応じて UE4 Editor 内でゲームのプレビューをする機能です。

描画レベルをプレビュー > Android ES2　にするとエディタ上でも表示されなくなった。まずはこのプレビュー状態で表示されることを目指す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/8a560362-0d57-976a-fe2c-989dd795be2e.png)


# アウトプットログに表示されていた警告
LogSkinnedMeshComp: Warning: SkeletalMesh ****, is not supported for current feature level (ES2) and will not be rendered. NumBones 18 (supported 75), HasExtraBoneInfluences: true

（警告：SkeletalMesh ****は、現在の機能レベル（ES2）ではサポートされていないため、レンダリングされません。）

# 警告の内容を検索したらUE4 ANSEWRHUBで見つかった情報
[Skeletal mesh is not visible in mobile preview after updating to UE4.21](https://answers.unrealengine.com/questions/848288/skeletal-mesh-is-not-visible-in-mobile-preview-aft.html)

##この情報を参考にやってみた。
Android ES2プレビューのままスケルタルメッシュを開くとここでもメッシュが表示されない
![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/f22b832d-8f7b-978f-32e3-1c21ba4a6a1e.png)

アセット詳細 > LOD 0 > LOD Info > Reduction Settings
Percent of Trianglesを0.99に変更しRegenerate LODを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/0c6e3027-ad91-dd0b-347e-5a585b2f14a1.png)

「はい」を押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/15426ee0-945a-8008-bed9-2af3df065f77.png)

表示された！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/59d7c8a5-3883-14fe-cad2-f74880b4f0be.png)

OculusQuestでも表示された！！
![com.YourCompany.BP_VRStudy0814-20190820-000249.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/b4ea942d-3724-01dc-6471-58d3874cbe19.jpeg)
Ubuntu 18.04でL2TP/IPsecに接続できない

Ubuntu 18.04をクライアントとしてL2TP/IPsecのVPNに接続しようとしたところ，正しい設定にもかかわらず何故か継続的に接続に失敗していたのですが，

```sh
$ sudo apt install libreswan
```
で解決しました．

参考リンク：
https://unix.stackexchange.com/a/400073/284535