OmniAICreator/Qiita-1.07M huggingface dataset:
PixiJS 入門 環境作りと テキストアニメーション

アニメーション 関連は苦手でコレまでやってこなかったのですが、 いま作成中サービスのデザインまわり担当している方から `pixi.js` を提案されたので勉強ついでに少し試してた記事です。

# PixiJS とは
[PixiJS](https://www.pixijs.com/) で提供されている JavaScript用2D描画ライブラリで、WebGLを使って高速な描画が簡単に実装することができるようになります。

[公式のデモ](https://pixijs.io/examples/#/demos-basic/container.js)
たくさんのデモコードが公開されているので参考にして サンプルを動かしてみようと思います。
![Container - PixiJS Examples - Edited.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100147/d6221800-97d5-bbe2-5d44-2fb324a21ff9.gif)

# 環境構築
npm で提供されているようなので vue cli の初期設定と組み合わせると
簡単に環境を作ることができます。
※ `pixi.js@5.0.0` を指定するとエラーなく実行できるようです。

```sh
mkdir pixijs-sample
cd pixijs-sample
vue create vue-app
cd vue-app/
npm i --save @types/pixi.js pixi.js@5.0.0
```

# HelloWorld.vue に描画コードを追加する
`pixi.js` を利用するコードを追加していく。

```js
<div id='pixi_container'>
 <!-- ここに 描画される -->
</div>
...
import * as PIXI from 'pixi.js';
...
private size = {width: 340, height: 240};
private pixiApp: PIXI.Application = new PIXI.Application(this.size);
private textobj!: PIXI.Text;

private mounted() {
  console.log('mounted');
  const container = document.getElementById('pixi_container')!;
  container.appendChild(this.pixiApp.view);

  // テキストオブジェクトを作る
  this.textobj = new PIXI.Text("Hello World!", {font:'bold 60pt Arial', fill:'white'});
  this.textobj.position.x = this.size.width / 2;
  this.textobj.position.y = this.size.height / 2;

  // テキストオブジェクトをステージに乗せる
  this.pixiApp.stage.addChild(this.textobj);

  // アニメーション開始
  this.pixiApp.ticker.add((delta) => {
    this.textobj.rotation += 0.01;
  })
}
```

# 実行してみる
動作確認用のサーバを起動して動作確認をする。

```
npm run serve
```

![vue-app - Edited.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100147/2d2004f4-68b1-8f06-4de5-36a638b539d5.gif)

簡単にテキストを表示して 回転させる事ができました。

# ソースコード等
githubへアップしてあります。
[pixijs-sample](https://github.com/tfuru/pixijs-sample)

# 参考
[簡単アニメーション！Pixi.jsを触ってみる！（1）テキストを動かしてみる](https://qiita.com/tadfmac/items/3684489e133320cd9d75)
- 3年前の記事の為 バージョンの合わず 概要とタイトルだけ参考にしました。

[pixi.jsとLive2Dで雪降るシーンを作る](https://qiita.com/naotaro0123/items/28c23ae4eaf72ebe04c6)
- Live2D との組み合わせもできるようなので後日ためしてみようと思います。

# 作成中サービス
[オオエン](https://ooen.me/)
経験や行動した事をリストにして公開しとくと、誰かが試したよとか行動したよ！が届くのでちょっと嬉しくなるサービス。試したり行動した人を気軽に楽しく応援できます。
興味ある方、 どんなリスト作りたいかなど事前登録で教えて貰えると嬉しいです！
SQL Serverのテーブルのコピー

#SQL Serverのテーブルのコピー
SQL Serverを勉強しているときに、便利だなと思ったので備忘としてメモします。
今回はSQL Serverのテーブルのコピーについてです。手軽にできるのでちょっとびっくりしました。
SQL Server Management Studioを使って、以下試していきます。

##サンプルテーブル作成
以下のDDLで今回使うサンプルテーブルを作成しました（データベースは事前に`sampleDB`という名前で作成しています）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/37ad6821-f20f-7249-d02c-2d525b1c6dc6.png)

##サンプルデータの投入
上記で作成したサンプルテーブルにデータを投入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/5a7b864b-0877-136d-6d05-795c7a59d8f3.png)

##データの確認
用意したサンプルテーブルとデータを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/4392cf9f-2f51-8a8b-7fa8-f040d9fbaa59.png)

##テーブルのコピー
さて、ここからが今回の本題です。今まで作成したテーブルやデータをコピーします。コピーといっても、以下のようなSQLを実行するだけです。通常のSELECT句に、`INTO コピー後テーブル名`でコピーできます。とても簡単ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/7589f795-7a80-8637-5a03-ba2cb49f144e.png)

##テーブルコピーの確認
コピーしたテーブルをオブジェクトエクスプローラで確認しましょう。たしかに上記SELECTで指定した名前でテーブルが新たに作成されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/fdb5ef2d-20fa-c1b4-cbc9-e780d16f2ac4.png)

データも確認してみましょう。こちらも問題なくコピーできているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/5e4eddb8-5285-84cf-e6c6-2ef51640e843.png)

##注意点
上記のように簡単にコピーできるのですが、注意点はあります。今回の方法でコピーしたテーブルには、制約はコピーされませんのでご注意を。列名、データ型、NOT NULLなどはコピーされます。
Markdown記法（おら的メモ） 

# Markdown記法

# 見出し
太文字、サイズが5段階に変えられる。

```
# 見出し
## 見出し
### 見出し
#### 見出し
##### 見出し 
```

# 網掛け
バッククォートで囲む
`helloworld`
`hello`world

```

`helloworld`
`hello`world
```

# 引用
>https:XXXXXXXXXXXXXXXXXXXXXXX
>>https:YYYYYYYYYYYYYYYYYYYYYYY


```
>https:XXXXXXXXXXXXXXXXXXXXXXX
>>https:YYYYYYYYYYYYYYYYYYYYYYY
```
# 水平線
`***` `---` `___` いずれか３つ以上で水平線になるよ
***
---
___

```
***
---
___

```
# pre記法(```)
~~~md
　```
  helloworld
　```
~~~


## あとがき、感想
仕事で使うので勉強という意味で初投稿でmarkdownを選びました。
これから、いろいろQiitaに投稿していこうと思います。

とりあえず、この投稿をもっと詳しく、わかりやすく修正更新していくお
railsのクラスメソッドとscopeの違い

# クラスメソッドとscopeの違い

Rails5.2までのガイドには以下の記述がありましたが実際は全く違います。
Rails6.0から記述が削除されています。

```
This is exactly the same as defining a class method, and which you use is a matter of personal preference:

訳: スコープでのメソッドの設定は、クラスメソッドの定義と完全に同じ (というよりクラスメソッドの定義そのもの) です。どちらの形式を使用するかは好みの問題です。
```

## scope

### 基本的にActiveRecord::Relationを返す。
```ruby
class User < ApplicationRecord
  scope :royal, -> { find_by(royal: true) }
end
```

scopeの結果がnilの場合`.all`の結果が返る

```ruby
$ User.find_by(royal: true)
=> nil

$ User.count
=> 100

$ User.royal == User.all
=> true
```

#### nilを返さないのでscopeをメソッドチェインして使える

### 正し、以下の場合はnilを返す。

```ruby
scope :empty, -> { [] }
```

## クラスメソッド

#### nilを返すのでメソッドチェインして使うと`NoMethodError`が発生する可能性がある

# 参考
## nilを返すケース
https://github.com/rails/rails/issues/34532

## warningを入れるか、raiseするかの検討PR
https://github.com/rails/rails/pull/32846
railsのアソシエーションhas_manyのオプション dependent: :restrict_with_error

# has_manyのオプション dependent: :restrict_with_error

# 前提

以下の様にUserが複数のItemを持っていた場合、
親モデルのUserを削除した場合、子モデルItemのuser_idの参照先が無くなってしまいデータが壊れてしまいます。

```
Class User < ApplicationRecord
  has_meny :items
end

Class Item < ApplicationRecord
  belongs_to :user

```

railsではassociationのオプションに`dependency`を指定する事で、
削除前にコールバックを実行しデータを担保する仕組みが用意されています。

# 使い方

`dependent: :restrict_with_error`を指定し、
関連付けられたオブジェクトが1つでもある場合エラーを発生させ、
親モデルを削除しない様にします。

```
Class User < ApplicationRecord
  has_meny :items, dependent: :restrict_with_error
end

Class Item < ApplicationRecord
  belongs_to :user

```

# restrict_with_errorのエラーメッセージのi18n対応

エラーメッセージをi18n対応

```config/local/custom.ja
ja:
  activerecord:
    errors:
      messages:
        restrict_dependent_destroy:
          many: "%{record}が存在しているため削除できません。"
```

`%{record}`の部分をi18n化する為に`attributes`を定義
定義の仕方は、

* `attributes`の直下に、子モデルの単数形
* `子モデルの単数形`の直下に、子モデルの複数形

```
attributes:
  子モデルの単数形:
    子モデルの複数形: 商品
```

```config/local/custom.ja
ja:
  activerecord:
    errors:
      messages:
        restrict_dependent_destroy:
          many: "%{record}が存在しているため削除できません。"
    attributes:
      item:
        items: 商品
```


# 参考
https://railsguides.jp/association_basics.html
国内アパレル製造業向けCADフォーマットTIIPの仕様について調査してみた

この記事は [ZOZOテクノロジーズ #1 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech) 15日目の記事です。
昨日は @edm17 さんによる [【iOS】簡単にKeyboardを表示したときにTextFieldが隠れないようにする](https://qiita.com/edm17/items/27e3f37fc5f0d9fbc33f)でした。

#はじめに
TIIPの仕様は公開されていないため独自に調査した結果をまとめました。検証に用いたCADに特化した仕様が混ざっているかもしれませんので参考程度に見ていただければ幸いです。お気付きの点があればコメントやご指摘等いただけるとめちゃめちゃ嬉しいです。

#TIIP（てぃーぷ）とは
国内アパレル製造業で使用されるCADファイル形式の一つです。CADの中間フォーマットであるDXFファイルを拡張し、アパレル設計・製造に特有のデータを保存することができます。全日本婦人子供服工業組合連合会により平成９年に開発され、日本で展開されているほとんどのCADベンダーがこの方式でのデータ互換に対応しているようです。

参照元：[アパレルCADデータ互換 TIIP規約](http://www.jwca.or.jp/act/tiipcad.htm)

※そもそもDXFファイルって何？という方は[こちらの記事](https://qiita.com/r-tezuka/items/3bf01caa3b418906b06c)をご覧ください。

#TIIPの仕様
TIIPはDXFをベースに開発されたフォーマットなので、基本的なデータ構造はDXFを踏襲しています。アパレルCAD特有の情報は主にコメント（グループコード=999）を使って記述します。

##コメント
例えばPOLYLINE（ポリライン）のコメントは線の種類が含まれ、

```:POLYLINEのコメント例
999
1     　　// 線の種類
```
LINE（線分）やVERTEX（頂点）はカンマ区切りで4要素が含まれます。

```:LINEまたはVERTEXのコメント例
999
2,1,1,15  // 線の種類, 頂点の種類, ノッチ, 頂点番号
```
これらの要素について解説します。

###線の種類
線の種類が定義されています。確認済みの値は以下の通りです。他にも取りうる値がありそうですがメジャーどころはこの辺りです。

- "1"=外周（裁断）線
- "2"=仕上り線
- "3"=地の目線
- "5"=内部線
- "6"=切り込み線（プロカット線）
- "8"=柄点
- "9"=ドリルホール or 部品位置
- "10"=ボタン類

###頂点の種類
アパレルCADデータをTIIP形式にエクスポートする際、曲線は分割された直線の集合として出力されます。つまり、CADデータに元々存在しなかった頂点が曲線描画の都合で新たに生成されます。TIIPに変換する前に頂点として存在していたのか（頂点の種類＝1）、変換に伴って便宜上追加された点なのか（頂点の種類＝2）を設定します。値を設定しなければ**デフォルトでダミー点扱い**になります。これを理解せずにTIIPファイルを編集してしまうと、アパレルCADで開いた時に激しく形状が歪むので要注意です。

- “1”=元々の頂点
- “2”=曲線描画のために生成されたダミー点(デフォルト)

###ノッチ
頂点にノッチを定義するかどうかの設定です。

- “”=OFF (デフォルト)
- “1”=ON

###頂点番号
BLOCKに含まれる頂点（ダミー点でない）の数に対応した連番です。初期値は1で、BLOCK内の頂点の数だけインクリメントされています。利用用途は不明ですが、スムージングの曲線算出に影響しているのかもしれません。

##コメント以外の仕様
DXFに存在するグループコードや図形の中でTIIP独自の解釈が入っているものを分かっている範囲でご紹介します。

|影響する図形|グループコード| TIIPの解釈|DXFの解釈|
|:--|:--|:--|:--|
|POLYLINE/LINE|6|線の描画タイプ（指定なし=実線/ "1"=破線/ "2"=点線/ "3"=一点鎖線/ "4"=二点鎖線/ etc.）|線種名(BYLAYER 以外の場合に現れます)。特殊な名前 BYBLOCK は、浮動型の線種を示します(省略可能)。|
|VERTEX|38|ノッチの長さ|図形の高度(ゼロでない場合)|
|VERTEX|50|ノッチの角度|角度(DXF ファイルでは度で、AutoLISP と ObjectARX アプリケーションではラジアンで出力されます)|
|POINT|-|ドリルホール or 部品位置|点図形|

#終わりに
TIIPの仕様を理解していくと、アパレルCADデータをハックするための道筋が明らかになり、工場にCADデータを提供する際に発生するちょっとしたデータ変換を自作のツールで自動化できるようになりました。全ての仕様を把握している訳ではないので引き続き発見があれば追記していきます！

明日は @pakio さんが記事を書いてくれます！乞うご期待！
railsのCSRF対策について

# railsのCSRF対策について

## トークンの生成

`Rails new` した後の`app/views/layouts/application.html.erb`に`<%= csrf_meta_tags %>`のタグが記述されています。
この`csrf_meta_tags`メソッドは以下の定義がされています。

```ruby
def csrf_meta_tags
  if defined?(protect_against_forgery?) && protect_against_forgery?
    [
      tag("meta", name: "csrf-param", content: request_forgery_protection_token),
      tag("meta", name: "csrf-token", content: form_authenticity_token)
    ].join("\n").html_safe
  end
end
```

レンダリングされるとする時に以下を行います。

* Sessionにトークンを格納

`SessionStore`を設定している場合はそのストアを見に行きます。

* HTMLに暗号化したトークンを出力

以下のようなHTMLが生成されます。

```html
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="vtaJFQ38doX0b7wQpp0G3H7aUk9HZQni3jHET4yS8nSJRt85Tr6oH7nroQc01dM+C/dlDwt5xPff5LwyZcggeg==" />
```

# 検証

ユーザーがPOSTリクエストを送信するときに、HTMLに埋められていたCSRFトークンも一緒に送信されます。
RailsのCSRF対策では、以下の2つのトークンが同一か検証します。

* `<meta name="csrf-token" content="vtaJFQ38doX0b7wQpp0G3H7aUk9HZQni3jHET4yS8nSJRt85Tr6oH7nroQc01dM+C/dlDwt5xPff5LwyZcggeg==" />`に埋め込まれたトークン`vtaJFQ38doX0b7wQpp0G3H7aUk9HZQni3jHET4yS8nSJRt85Tr6oH7nroQc01dM+C/dlDwt5xPff5LwyZcggeg==`

* Sessionで保持しているトークン

# 参考
## 記事
https://techracho.bpsinc.jp/hachi8833/2017_10_23/46891

## RailsGuide
https://railsguides.jp/security.html#%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3%83%88%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%AA-csrf

## Rails/Rails
### 検証
https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/request_forgery_protection.rb#L135

### CSRFトークン生成
https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/csrf_helper.rb#L22
遺伝研スパコンで Jupyter Notebook を利用する方法

# 概要
遺伝研スパコンのゲートウェイノードを踏み台にしたポートフォワーディングを使うことで、スパコン側で起動している Jupyter Notebook にローカル側から接続することができます。

産総研 ABCI システムの[利用ガイド](https://docs.abci.ai/ja/)を参考にしました。遺伝研スパコンでも応用可能な情報が豊富です。

**ここで紹介する方法に関しては遺伝研スパコンの利用法として問題がないことを管理者に確認をしておりますが、過剰なリソースの占有や他のユーザーに迷惑がかかるような計算処理を行わないように気をつけてください。**

# スパコン側の操作

1. スパコンゲートウェイノードにログインしたのち、`qlogin`をおこなってインタラクティブノードにログインします。複数 CPU を使った並列計算や大量のメモリを必要とする処理を行う場合には`-l`オプションや`-pe`オプションでリソースの指定をして qlogin を行ってください。

2. ログイン先のホスト名を確認します。qlogin 時に負荷の低いノードが自動的に選ばれるためログインごとにホスト名は変わります。

    ```
$ hostname
at029  # 例
    ```

3. `netstat`コマンドで空いているポート番号を調べます。使用したいポート番号を grep して何も表示されなければ空いています。50000番台以降なら問題ないでしょう。

    ```
    $ netstat -an |grep 58888  # 何も表示されないことを確認
    ```

4. Jupyter Notebook を起動したいディレクトリに移動したら、次のようなオプションを指定して起動します。

    ```
    $ jupyter notebook --ip=`hostname` --port=58888 --no-browser
    ```
このとき画面上に接続に必要なトークンが表示されますので確認しておきます。

    ```
$  jupyter notebook --ip=`hostname` --port=58888 --no-browser
[I 21:09:48.392 NotebookApp] Writing notebook server cookie secret to /home/ユーザー名/.local/share/jupyter/runtime/notebook_cookie_secret
[I 21:10:03.057 NotebookApp] Serving notebooks from local directory: /home/ユーザー名/ディレクトリ名
[I 21:10:03.057 NotebookApp] The Jupyter Notebook is running at:
[I 21:10:03.057 NotebookApp] http://at029:58888/?token=e5dfb494845ca2f63284d8878be1899d86312d51d94c5968
[I 21:10:03.057 NotebookApp]  or http://127.0.0.1:58888/?token=e5dfb494845ca2f63284d8878be1899d86312d51d94c5968
[I 21:10:03.057 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 21:10:03.086 NotebookApp] 
    
    To access the notebook, open this file in a browser:
        file:///home/ユーザー名/.local/share/jupyter/runtime/nbserver-37289-open.html
    Or copy and paste one of these URLs:
        http://at029:58888/?token=e5dfb494845ca2f63284d8878be1899d86312d51d94c5968 <== トークン
     or http://127.0.0.1:58888/?token=e5dfb494845ca2f63284d8878be1899d86312d51d94c5968
    ```

### 追記）トークンの指定

`--NotebookApp.token`オプションを指定して接続トークンを指定することができます。

```
jupyter notebook --ip=`hostname` --port=58888 --no-browser --NotebookApp.token='MyToken'
```

### 追記）singularityの利用

Singularity 内の Jupyter Notebook も次のように利用可能です。

```
$ singularity exec datascience-notebook_latest.sif jupyter notebook --ip=`hostname` --port=58888 --no-browser 
```

（使用したイメージファイルは`singularity pull docker://jupyter/datascience-notebook`でビルドしたものです）

なお、Jupyter Notebook 内で "!" をつけてシェルコマンドが実行できるので追加パッケージをインストールすることもできます。

```
!pip install pysam
```

この場合、パッケージのインストールはコンテナ内ではなく、ホームディレクトリの .local 以下になるようです（`~/.local/lib/python3.7/site-packages`）。コンテナ外からも .local を利用していた場合、なんらかのバッティングが生じる場合があるかもしれません。

# ローカル側の操作
以下は Mac や Linux を使用した場合です。Windows でもポートフォワーディングを行えば接続できるはずです。


1. 新たなターミナルを開き ssh コマンドを使って Jupyter Notebook が動いているノードに対しスパコンゲートウェイを経由したポートフォワーディングを行います。下記コマンドはローカルホストの 8888 番ポートへの通信をスパコン at029 ノードの 58888 番ポートへ転送するという意味です。

    ```
$ ssh -L 8888:at029:58888 ユーザー名@gw.ddbj.nig.ac.jp
    ```
    ターミナルは開いたままにしておいてください。
2. ブラウザで http://localhost:8888 を開く
3. トークンを入力してログイン

以上です。
SpreadSheet + GoogleCloudFunctions + Goで管理画面作った

# つくったもの
サークルのホームページとその管理画面
(所属サークルがばれるのでURLは割愛)

# 要件
- 無料で運用したい（サークルの経費節約💸）
- 非エンジニアがHPを更新するので、データを入力する管理画面が必要
- バックエンドはGoで書きたい


# システム概要
<img width="868" alt="スクリーンショット 2019-12-11 22.12.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287191/a9ff16e9-2d99-c212-449c-a13290a6a248.png">


# 管理画面
管理画面を作るのがめんどうだったので、非エンジニアでも使いやすいGoogleSpreadSheetを採用。

<img width="807" alt="スクリーンショット 2019-12-06 0.03.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287191/4bc6d4e6-81a7-e433-5a70-69fa9f243f8e.png">

シート保護しまくってHP管理者がうっかり破壊してしまわないようにしておく。
また、データ入力範囲に名前をつけておく。

<img width="625" alt="スクリーンショット 2019-12-06 0.05.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287191/36e0d914-5e0e-6366-4445-624011b217da.png">

GASに紐づいたボタンを設置。
GASではシンプルにGoogleCloudFunctionsの呼び出しのみを行う。

```javascript

function updateHoge() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var id = ss.getId();
  
    UrlFetchApp.fetch("https://~.cloudfunctions.net/hoge?sheetID=" + id, {"method": "put"});
}
```

HP管理者はデータ入力して更新ボタンをポチッとすれば、HPにデータが反映される👏

# FaaS
GASに書いてしまうこともできるが、スクリプトエディタのコード補完が微妙で書きにくい、、、😖
GASではトリガーを引くだけにして、処理はGoogleCloudFunctionsに置くことにした。
GoogleCloudFunctions採用理由は以下の通り。

- SpreadSheetへのアクセスが簡単（サービスアカウント）
- FaaSなので難しいこと考えなくて良い！
- Goランタイムがリリースされた🎉Goが書ける！！  
<br/>

`func Hoge(w http.ResponseWriter, r *http.Request)`型の関数をデプロイすることができる。
Goの`net/http`で`http.HandleFunc`等に渡す関数と同じ型なので、ローカル実行も簡単。
トリガーはHTTPリクエストにする。
以下のコマンドで、関数Hogeを登録名hogeとしてデプロイできる。

```
gcloud functions deploy hoge --entry-point Hoge --runtime go111 --trigger-http
```
以下のようにMethodで条件分岐しておくと、Methodごとの動作を変えられる。
こうしておくと通常のサーバと同じような振る舞いができる。
例) `curl -X GET ~~~/hoge` -> データ読み出し
`curl -X PUT ~~~/hoge` -> データ書き込み


```go
func Hoge(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		// データを取得する関数
	case "PUT":
		// データを保存する関数
	}
}
```

GETでは、Firestoreからデータを取得して返す。
PUTでは、SpreadSheetの名前をつけた範囲からデータを抽出し、Firestoreに保存する。

# DB

SpreadSheetをDBとして扱うこともできるが、入力途中のデータがHPに公開されるとまずいので、別途DBを用意。

Firestoreを採用。使ってみたかった。
良い感じのデータ構造を考える。

# クライアント

お好みの技術で最強にかっちょいいHPを作って、Firebase Hostingで配信。

GoogleCloudFunctionsのURLにGETリクエストを送って、データを受け取る。

# 感想
- GoogleCloudFunctionsで関数ごとにデプロイするのが少し面倒。
    - コード変更箇所がどの関数に影響するか考えてデプロイするのが面倒だったので、一括デプロイコマンドを作った。
- 全部Googleのサービスで作ったので、各サービスの接続が簡単だった（サービスアカウント）。
- SpreadSheetを管理画面にしたことで、データのコピペや並べ替え機能を容易に提供できた。

# あとがき
もともとFirebase,React,Goでのweb開発の勉強がしたくて、サークルのHPを題材に選んだが、管理画面が必要な経緯でGoogleCloudFunctionsも学べて花まる大満足💮

<br/>
<br/>
MacへRubyをインストールする際の備忘録

# インストールメモ
## `rbenv` と `ruby-build` のインストール
```bash
$ brew install rbenv ruby-build
```

## Ruby をインストール

執筆時点で最新の `Ruby 2.5.6` をインストールする。
補足ですが、Rubyのバージョンは `rbenv install -l` で検索することができます。

```
$ rbenv install 2.6.5
```

## `.zshrc` の編集
`rbenv` のコマンドを利用できるように、パスを設定します。
私は、zshを利用しているため、 `.zshrc` に下記設定を追加しました。

```zsh
export PATH="$HOME/.rbenv/bin:$PATH" 
eval "$(rbenv init - zsh)"
```

追記後、下記コマンドを実行する。

```zsh
$ source .zshrc
```

## Rubyのバージョンを切り替える
MacにはデフォルトでRubyがインストールされているので、今回インストールしたRubyのバージョンに切り替えてみます。

```zsh
$ rbenv versions
* system (set by /Users/username/.rbenv/version)
  2.6.5
$ rbenv global 2.6.5
$ rbenv versions
  system
* 2.6.5 (set by /Users/username/.rbenv/version)
$ ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin18] 
```

## Hello, World!を書いてみる
```ruby:hello.rb
puts "Hello, World"
```
```zsh
$ ruby hello.rb
Hello, World!
```

以上！

# 参考文献
https://qiita.com/shinkuFencer/items/3679cfd966f6a61ccd1b
MacでPythonインストールなら知っておきたい・いろは

#まじで優良記事を見つけたの紹介するだけ
【2019年版】Pythonインストール・Mac編【長く安全に使える環境構築】
https://basicincome30.com/python-install-mac

この記事さえあれば他はいらない。というかこんな記事書いてみたいわ（大嘘）

っというかPythonっていつの間にか生活に浸透してきたけど、基礎の"き"がわかってないから「ヴァージョンが違うやばい」とか悩むことが多かったけどこれであんしんしてPythonできそうな気がしてきた

よくあるのがエラーを直そうとして適当に調べて環境差も分からず記事を斜め読みしてコマンドうちまくったらpipが死亡するとか気を付けていきたい。。。

エラー直そうとして、新たなエラーを呼んでしまうとか。進んでるのか戻ってるのか分からなくなるのが一番やばい。

#「ご安全に！」これを合言葉にしたい
ES2020で入るあついやつ

<img width="1280" alt="Advent Calnder.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16065/e46920ea-72f9-6ca8-c3bf-21c01add8d84.png">

はいよ。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">勝ったわね… <a href="https://t.co/HGQAjQ1V2b">pic.twitter.com/HGQAjQ1V2b</a></p>&mdash; 駆け出し亭めろたん、 (@renyamizuno_) <a href="https://twitter.com/renyamizuno_/status/1204731107305914370?ref_src=twsrc%5Etfw">December 11, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

つい先日、電動昇降デスクを買って気分上々↑↑の一般男性です。
よろしくおねがいします。

これは [bosyu Advent Calendar 2019](https://qiita.com/advent-calendar/2019/bosyu) の 12日目の記事でごわす。

よろしくね。

今回は個人的にずっとこれ欲しかったんすよ。っていうアレがES2020ではいりそうなので紹介するぞ！

## Optional Chaining for JavaScript

https://github.com/tc39/proposal-optional-chaining

みんなJSで

```javascript
const fuga = object.hoge && object.hoge.fuga;
```

こういうの書くじゃん？
めっちゃ出てきたりするじゃん？

これをこうして

```js
const fuga = object.hoge?.fuga;
```

こうじゃ。

**優勝でしょこれ。**

勝ち申したわ。

こんなかんじで `function` もうまく扱える。

```js
const fuga = hoge?.();
```

こんな調子でできちゃう。
いいでしょ。

これを数年待ってた。

## Nullish Coalescing for JavaScript

上のとにたやつですね。(雑)

```js
const fuga = object.hoge || 'default fuga';
```

こういうの。
ここで `object.hoge` が空文字や0の場合、どうなるかというと`'default fuga'`になってしまいますよね。
多分意図していないですよね。

地味に困るというか面倒なやつですが、これを回避できるようになります！

```js
const fuga = object.hoge ?? 'default fuga';
```

~~_なんだよ`??`って_~~

これで上の問題が回避されます！
`null`と`undefined`の場合だけデフォルトの値が入るような感じになるわけですね〜。
優秀では？？？？

## あわせ技

この２つを合わせて使うとめちゃいい

```js
const fuga = object.hoge?.fuga ?? 'default value';
```

`object.hoge.fuga` が 無いときは `'default value'` を返すやつですね。
とても見やすい。

これを今のJSで書こうとすると

```js
const fuga = object.hoge && object.hoge.fuga || 'default value';
```

こういう感じ？あってんの？
正確には0の場合とかがあるので違うけども。

まあパット見分かりづらいものが、だいぶ読みやすいものになるかなぁと思います！

最高！

## 今すぐ体験せよ

実はbabelのstage-3で使える。

最高の Optional Chaining と Nullish Coalescing を今すぐ体験せよ！！！

https://babeljs.io/repl#?browsers=&build=&builtIns=false&spec=false&loose=false&code_lz=MYewdgzgLgBAZgVwOYEMYF4YgEYCsCmwUAdABYhL4D8xiqMVVMA5ACb5woIA2sAbim4J8zANwAoIA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=stage-3%2Cenv&prettier=false&targets=&version=7.7.5&externalPlugins=
ABC147のC問題を自分なりに説明してみる

# はじめに
最近競技プログラミングを始めたクソザコナメクジです。
よろしくお願いします。

先日のAtCoder Beginner Contest(通称ABC) 147回のC問題が個人的に難しかったので、勉強がてら説明を書いてみました。
合ってるかな？とか伝わるかしら？とか色々不安はありますがとりあえず書いてみようと思います。

問題を説明してみた！ってエントリなので当然ですが答えが出てきます。
まだ解いてないよって人は読まないほうがいいと思います。

# どんな問題なの？
問題はAtCoderのサイトで見れるのでそちらを見てください。
https://atcoder.jp/contests/abc147/tasks/abc147_c

## 解いているときに躓いた点
$N$人の証言にムジュンがあるかどうか、数学的に色々ゴニョゴニョしないとわからないんじゃないかと思ってロジックを考え出して結局わかりませんでした！
あとは、不親切な人を嘘つき（必ず虚偽を言う人）だと勘違いしてたのがだめでした。問題文はちゃんと読もう。

# 解き方
[AtCoderに掲載されている解説](https://img.atcoder.jp/abc147/editorial.pdf)をベースに、解き方を自分なりに説明してみます。

## ムジュンを調べてみよう
まずは、証言がどういう場合にムジュンしてしまうのか考えてみます。

3人の人が、以下のような証言をしている場合を考えてみましょう。（問題の入力例1と同じ状況です）

> 1さんは、2さんのことを正直者だと言っています。
> 2さんは、1さんのことを正直者だと言っています。
> 3さんは、2さんのことを不親切だと言っています。

この状況で全員が正直者だと仮定すると、証言と仮定の間にムジュンが生じてしまいます。
なぜなら、3さんが正直者だとすると、2さんは不親切な人です。
ですが、全員が正直者だと仮定していますから、2さんは正直者のはずです。

つまり、ある人$i$さんの状態（正直か不親切か）を仮定したときに、他の人の$i$さんに関する証言と齟齬が発生すればムジュンしてしまうと考えることができます。

ちなみに、重要なファクターなんですけど、不親切だと仮定した人の証言は無視してよいです。（不親切な人の証言は合っていても間違っていても関係ないのです）

### ここまでの実装
なんとなくコードにしてみると、以下のような実装で調べられそうです。
変数は問題文と同じ文字ですが、

- $A_i$は$i$さんが証言した数
- $x_{ij}$は$i$さんの証言が誰についてのものか
- $y_{ij}$は$x_{ij}$さんが正直者かどうか

を示す変数です。
あと、`getState(x[i][j])`は`x[i][j]`さんの状態を取得する関数ですが、説明を簡略化するために登場させただけです。（本物の解説には出てきません）

```cpp
/* N人についてのループ */
for(int i = 1; i <= N; ++i){
  /* iさんの証言について調べるループ */
  for(int j = 1; j <= A[i]; ++j){
    if(getState(x[i][j]) == y[i][j]){
      // ムジュンしない
    }else{
      // ムジュンする
    }
  }
}
```

## 最大値の調べ方
$N$人の状態がわかっていれば、証言とムジュンするかどうかは調べることができました。では、次にそれをすべての場合で調べるにはどうすればいいか考えてみます。

先程も書いたとおり、$N$人の人それぞれについて、正直者であるか不親切な人であるかを仮定すれば、その状態が証言と矛盾しないかは調べることができますね。

これをすべての場合について考えれば、正直者が一番多いパターンがわかるわけですが、$N$人が正直者か不親切な人であるかは、高々$2^N$通りしかありません。

これをどう実装していくか考えていきましょう。

### ここまでの実装
まず、問題では$x_{ij}$さんの状態を$y_{ij}$が0か1かで表現していました。
これをそのまま利用することができそうです。

先程と同じく、入力例1の場合を考えてみます。
正直者が最大のとき、1さん、2さんは正直者、3さんだけが不親切でした。
これを数字で表現すると、`011`のように表現できそうです。（右から数えるのがポイントです）
各桁は0か1しか取りませんから、この数字の列を2進数として捉えることもできます。

そうすると、$N$人の取りうるすべての場合について調べることは、`000`から`111`までのすべての数について（証言とのムジュンがないか）調べることと同じことになります。

以下の実装では、変数`bits`が、$N$人それぞれの状態（親切かどうか）を表現しています。

```cpp
// すべての場合についてのループ
for(int bits = 0; bits < (1 << N); bits++) {
  // ここでムジュンを調べる
}
```
解説ではbit全探索という言葉が出てきますが、このようにbitを使って部分集合のすべてを調べ上げる手法のことみたいです。
[ビット演算 (bit 演算) の使い方を総特集！ 〜 マスクビットから bit DP まで 〜](https://qiita.com/drken/items/7c6ff2aa4d8fce1c9361#bit-%E5%85%A8%E6%8E%A2%E7%B4%A2)

ちなみに、bit全探索だと$N$が増加すると指数関数的に計算量が増大してしまうのですが、今回の問題では$N\leq15$という制限があるので、心配なさそうです。

## まとめると
これまでの実装を組み合わせれば問題が解けそうです。

というか、実は今までの説明はkyort0n様の以下の実装を分解して考えたものになります。
https://atcoder.jp/contests/abc147/submissions/8830089

bit演算に馴染みがないと読むのに苦労するかもしれませんが、一行一行コメントをつけながら読んでいけばなんとかなりました！

やる気があれば、また今度自分で実装してここに載せようと思います。

# おわりに
今回のC問題は一見とても難しそうだったのですが、解説を読んで分解してみると「なるほどなー！」って感じでした。実装例も最初はわからんちんでしたが、調べながら読み進めるとおもしろかったです。
RHELでのNW設定(最初の一歩）

RHEL7ではNWの設定はされていないかもしれない時がある

1)デバイスを確認
nmcli device

結果、eth0だの、ens3だのがわかる

2)インターフェイスを有効化
nmcli c m eth0 connection.autoconnect yes

3-1)IPをDHCP設定にする
nmcli c modify eth0 ipv4.method auto

3-2-1)IPを固定割り当てに設定にする場合
nmcli c modify eth0 ipv4.method manual

3-2-2)IPアドレス、サブネットマスクを設定
nmcli c modify eth0 ipv4.addresses 172.16.0.100/24

3-2-3)デフォルトゲートウェイを設定
nmcli c modify eth0 ipv4.gateway 172.16.0.1

3-2-4)DNS設定
nmcli c modify eth0 ipv4.dns 172.16.0.1 

4)インターフェースを再起動
nmcli c down eth0; nmcli c up eth0 

5)設定を確認
nmcli d show eth0 

or

ip a
StyleGAN2 推論を動かすメモ

https://github.com/NVlabs/stylegan2

## 動作環境

* tensorflow 1.15 GPU
* Python 3.7
* CUDA 10.0
* cuDNN 7.6 以上

CUDA 10.1 などでも動くかもですが, 確認したのは README にあるように CUDA 10.0 になります.

test_nvcc.cu は CUDA 10 SDK でもコンパイル失敗しますが, とりあえず無視します.

## 修正
 
カスタムカーネルが c++14(?)を使っているので, `dnlib/tflib/custom_ops.py` の _prepare_nvcc_cli で

```
    cmd += ' -std=c++14'
```

を追加しておきます. nvcc の裏で動いているコンパイラによっては不要かもしれません　。

cuDNN は 7.6 以上を要求されます. 7.6 以上をインストールしましょう.

## 推論する

あとは README の通りにやれば動くはずです.

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">ありがとう StyleGAN2 <a href="https://t.co/Fxh4AgFqTR">pic.twitter.com/Fxh4AgFqTR</a></p>&mdash; Syoyo Fujita 🌸  RayWa(Ray and Peace) (@syoyo) <a href="https://twitter.com/syoyo/status/1205097336860364800?ref_src=twsrc%5Etfw">December 12, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## TODO

* [ ] 学習を動かす(StyleGAN で学習したときのように, バッチサイズなど減らせば 1080 Ti などメモリ少ない GPU でも学習できると思われる)
* [ ] StyleGAN2 を pytorch, libtorch あたりで書き直して再学習する(元コードは商用利用不可ライセンスのため)
* [ ] 優秀な若人さまが, **StyleGAN2 を人類史上最速でお極めになられることで, 優秀な若人さまが Kaggle Deepfake Detection Challenge https://www.kaggle.com/c/deepfake-detection-challenge/overview/prizes で優勝し 5,400 万円を手になされるスキーム**を確立する旅に出たい
bigquery の DropdownList の条件指定について

## はじめに
* bigquery とは
    * https://thinkit.co.jp/story/2015/08/27/6346

## やりたいこと
### bigquery で DropdownListを設定し、選択した値を別の値に置き換えたものに変換してからデータを抽出したい
* bigquery で Dropdownlistを設定
<img width="598" alt="1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87218/9a4e2f81-7b1d-ec55-dbcd-626f60e8a342.png">

* 設定後の状態

<img width="127" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87218/8992f78d-b4af-490a-7a15-e34c8dba5f94.png">


## 対応方法
* WHERE条件の中にIF文を記載する

~~~SQL
 WHERE ('{{device}}' = '全て' OR device = IF('{{device}}' = 'pc', '1', IF('{{device}}' = 'sp', '2', '')))
~~~

## 参考
* https://cloud.google.com/bigquery/docs/reference/standard-sql/conditional_expressions?hl=ja

## 終わりに
* Tipsでした
お家でRPA！（できなかった話）

#RPAとは
>RPAとは「Robotic Process Automation /ロボティック・プロセス・オートメーション」の略語で、ホワイトカラーのデスクワーク（主に定型作業）を、ルールエンジンやAI（人工知能）などの技術を備えたソフトウェアのロボットが代行・自動化する概念、と定義されています。業務を代行・自動化するソフトウェア型ロボット自体のことを、「デジタルレイバー・デジタルワーカー（仮想知的労働者）」などと擬人化して呼ぶこともあります。

こんなかっこいいこと書いているから、なんでもできると勘違いしている人がいますが、そんなことはない。
できることはわりと限られている（できなくはないにしても、とっても作るの大変だったり）

特定の**定型作業**が楽になるくらいで考えてほしい。。

# Automation Anywhere community edition

Automation AnywhereはRPAの代表的なツール。
これが特定の条件内に限り、無料で使えるようになった（機能はだいぶ限られている）ため、お家でもRPAできる！と思って導入したいと思います。（できなかったけど。）

# インストール（未完）

こちらの「無料の Community Edition をインストールしてみよう」の章の、3番まではいけた。
[Automation Anywhereで始めるRPA - セットアップからHello World!まで](https://qiita.com/RPAbot/items/8d9b14a8b779d1d305e4)

そのあとは画面が変わってたので手探りで。右上のPCマークを押してみる。
<img width="957" alt="AA_login.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185546/9b0292c4-5821-ff8e-d600-df0ddf98230f.png">


Local bot not installed
Click here for next step...

と記載されていたので、click here　をクリック（画面撮り忘れ。。）

そのままダウンロードされる。
<img width="957" alt="aa_download.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185546/83a8401c-cc05-15ac-e4e4-6c7b8fb836b5.png">

その後はポップアップの手順にのっとる。
そしたらLocal Bot agentの準備は完成。

<img width="211" alt="owata.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185546/b84de216-150f-976b-4db4-43d3b4a3efd5.png">



↑ユーザ名とパスワードが、どうにもこうにもうまくいかずに、断念。。。
これを設定していないと、ファイルトリガーのファイルが指定できなくて困っている。
初心者によるプログラミング学習ログ 182日目

# 100日チャレンジの182日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

182日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>182日目<br>webサイトコーディング課題<br>更新履歴ページ作成<br><br>ボタンの設置とか、疑似要素いれたりとか<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1204861227295313920?ref_src=twsrc%5Etfw">December 11, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
LaTeXでの執筆を助けるスクリプト (随時更新)

## 修正ログ

- 2019/12/16 1. に`while`文を書くことを追記。(現時点で4.まで書いた。)

# これは何？

LaTeXで文章(多分論文)を書くときにあるといいな、というshellスクリプトを書いていきます。みなさん執筆頑張りましょう。


## 1. 文献情報の人名をまとめて修正する

おなじみの文献ソフト[Mendeley](https://www.mendeley.com/)を使って、Mendeleyに入っている文献情報を.bibに同期していくことが出来ます。Mendeley中のcitation keyをLaTeXの文中に `\cite{CITATION_KEY}` として埋め込むと良いです。

しかし、落とし穴がありまして、Mendeley側で文献を更新すると、

`García`さんとか`Muñoz`さんのアクセント/アクサンテギュやティルデがおかしなことになります。そこで以下のスクリプトで、毎回直してあげましょう。下記の例では`./res/library.bib`にMendeleyと同期されている`.bib`ファイルを置き、スクリプトは`./bin/`フォルダにまとめることにしています。

```bash:bin/correct_bibtex.sh
#!/usr/bin/sh
sed -i "s/é/\\\'{e}/g" ./res/library.bib
sed -i "s/á/\\\'{a}/g" ./res/library.bib
sed -i "s/ó/\\\'{o}/g" ./res/library.bib
sed -i "s/ñ/\\\~{n}/g" ./res/library.bib
```

このbibtex修正スクリプトを毎回手動で実行するのもめんどくさい！という場合には以下のように`while`文で3分おき実行を仕掛けておきましょう。

```bash
# bash dayo
$ three_mins=180; # sleep関数には秒数を投げます。3分=180秒を指定。
$ while true; do ./bin/correct_bibtex.sh; sleep $three_mins; done
# やめるときは `ctrl+c`
```

## 2. タイポ絶対○すマン

```bash
$ grep $TYPE_STRING *.tex --color # タイポを色付けして表示
$ grep $TYPE_STRING *.tex | head | grep $TYPE_STRING --color # タイポを頭出しして色付け表示
```

`grep`に`-n`オプション付けると文字列がヒットした行の行数も示すので、おすすめです。

## 3. 大文字2文字以上の単語を取ってきてabbreviation listを作る

Nomenclatureとも呼ばれますね、索引です。大文字の略語に正式名称をふる作業で、目視すると抜け漏れが出そうなので機械的にやりましょう。以下のpythonスクリプトを書いて、`$ ./bin/list_capitals.py *.tex` などとすれば、全ファイル中に含まれる2文字以上大文字が連なる単語を引っ張ってこれます。

```python:bin/list_capitals.py
#!/usr/bin/python
import sys;
import re;
fn=sys.argv[1];
f=open(fn,"r",encoding="UTF-8");
lines=f.readlines();f.close();
sent="".join(lines);
g=re.finditer("[A-Z]{2,}",sent);
print(*[c.group() for c in g])
```

**注意点**
- ファイルの文字コードには気をつけてください。上記の例ではUTF-8を指定しています。
- 文字数の制約も自分でしましょう。下から2行目の`{2,}`という箇所で指定しています。

## 4. 目次を作る

`FILENAME.tex`をコンパイルするとき、`FILENAME.toc`というファイルが作られます。このことを利用して、`FILENAME.toc`のリストから文字列だけ取り出すスクリプトを書けば、目次が秒で作成できます。スクリプトは以下のようになります。`awk`コマンドという、各行に同じ処理を適用するコマンドが便利です。

```bash
$ cat ./bin/list_toc.sh
#!/usr/bin/sh
awk -F\} '{print $2,$3}' main.toc | awk -F\{ '{print $3}'
```

## (随時更新中)
SoftetherVPN の Client を Raspberry Pi  で使った時の不具合対策

以下のように、192.168.30.13 というアドレスが取得できているとします。

```text
$ ip addr show vpn_tun0
4: vpn_tun0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether 5e:e2:7a:c5:d9:d6 brd ff:ff:ff:ff:ff:ff
    inet 192.168.30.13/24 brd 192.168.30.255 scope global vpn_tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::5ce2:7aff:fec5:d9d6/64 scope link 
       valid_lft forever preferred_lft forever
```

ルーティングテーブルが次のようになると、VPN の他の端末に ping が通りません。

```text
$ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irt
t Iface
0.0.0.0         192.168.30.1    0.0.0.0         UG        0 0          0 vpn_tun0
0.0.0.0         192.168.8.1     0.0.0.0         UG        0 0          0 wlan0
192.168.8.0     0.0.0.0         255.255.255.0   U         0 0          0 wlan0
192.168.30.0    0.0.0.0         255.255.255.0   U         0 0          0 vpn_tun0
```

次のコマンドで解決します。

```text
# route del -net 0.0.0.0 gw 192.168.30.1 netmask 0.0.0.0
```

修正後のルーティングテーブル

```text
$ netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.8.1     0.0.0.0         UG        0 0          0 wlan0
192.168.8.0     0.0.0.0         255.255.255.0   U         0 0          0 wlan0
192.168.30.0    0.0.0.0         255.255.255.0   U         0 0          0 vpn_tun0
```

こうなれば、VPN の他の端末に ping が通ります。

```text
$ ping -c 3 192.168.30.10
PING 192.168.30.10 (192.168.30.10) 56(84) bytes of data.
64 bytes from 192.168.30.10: icmp_seq=1 ttl=64 time=126 ms
64 bytes from 133.130.124.85: icmp_seq=1 ttl=128 time=126 ms (DUP!)
64 bytes from 192.168.30.10: icmp_seq=2 ttl=64 time=84.4 ms
64 bytes from 133.130.124.85: icmp_seq=2 ttl=128 time=84.5 ms (DUP!)
64 bytes from 192.168.30.10: icmp_seq=3 ttl=64 time=91.9 ms
```

起動時に、このコマンドを実行するようにするには、
[Raspberry Pi に SoftEther_VPN Client をインストール](https://qiita.com/ekzemplaro/items/57b13994fbd1b5e3c286)
で作成した、/opt/vpnclient/dhclient_start.sh　を次のように修正します。

```bash:/opt/vpnclient/dhclient_start.sh
#
#       dhclient_start.sh
#
#                                       Dec/17/2019
sleep 10
#
/opt/vpnclient/vpncmd /client localhost /cmd AccountConnect tun0
#
sleep 1
#
dhclient vpn_tun0
#
for it in {1,2,3}
do
        sleep 20
        route del -net 0.0.0.0 gw 192.168.30.1
done
#
```
HTML5で(ほぼ)リアルタイム音声文字起こし

この記事は[tomowarkar ひとりAdvent Calendar 2019](https://qiita.com/advent-calendar/2019/tomowarkar)の12日目の記事です。

# はじめに
HTML5の標準機能を使えば(ほぼ)リアルタイム文字起こしもJavaScriptだけで書けてしまうんだぜ。

#コード全文
音声文字起こしの[デモサイト](https://tomowarkar.github.io/blog_content/speech/voice_transcribe.html)

```index.html
<h1>音声文字起こし</h1>
<p>Click to Speakを押して話しを始め、話しが終わればClick to Stopを押してください</p>
<button id="button" onclick="toggleStartStop()"></button>
<div id="textarea"></div>

<script>
  if ('webkitSpeechRecognition' in window) {
  } else {
    alert("このブラウザは音声文字起こしに対応していません。")
  }
  let recognizing;
  let recognition = new webkitSpeechRecognition();
  recognition.continuous = true;
  button.innerHTML = "Click to Speak";

  const reset = () => {
    recognizing = false;
  }

  recognition.onend = reset;
  recognition.onresult = function (event) {
    for (let i = event.resultIndex; i < event.results.length; ++i) {
      if (event.results[i].isFinal) {
        textarea.insertAdjacentHTML('beforeend', event.results[i][0].transcript + "<br>");
      }
    }
  }

  const toggleStartStop = () => {
    if (recognizing) {
      recognition.stop();
      reset();
    } else {
      recognition.start();
      recognizing = true;
      button.innerHTML = "Click to Stop";
    }
  }
</script>
```
# おわりに

半年以上前に書いたコードを引きずり出す程度にはストックがなく、
毎日レポートばっかりで時間がない😂

以上明日も頑張ります！！
[tomowarkar ひとりAdvent Calendar Advent Calendar 2019](https://qiita.com/advent-calendar/2019/tomowarkar)
# 参考
https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API
言葉を使ってプロダクトに生命を吹き込む

[テックタッチアドベントカレンダー](https://qiita.com/advent-calendar/2019/techtouch) 13日目を担当する @oyoshikeita です。
12日目は @takakobem による [Create React Appで始めるChrome拡張](https://qiita.com/takakobem/items/64c37a4f35cadd712907) でした。
アドベントカレンダーを見てると、この1年で仲間が増えたなー、と感慨深い思いにふけりながら、やっぱり @terunuma の [4Kモニタ環境で1年間Web開発してみた所感](https://qiita.com/terunuma/items/3eede74b6354da113d66) を見たらちょっと欲しくなる気持ちあるよね、と。

ところで！エンジニアは増えたけど、デザイナーは私ひとり。
まさに孤立無援の花状態です。
では参ります。

## はじめに

「生命を吹き込む」などと仰々しいタイトルをつけましたが、この記事ではプロダクトにおける**言葉**の重要性について、自分の考え・実践してきたこと・特に関係ないことをつらつらとまとめてみました。
軽い感じでお付き合いください。

## UIにおける言葉のパワー
デジタルプロダクトを作る際（デジタルじゃなくてもそうかも）には、大きくわけて情報設計とビジュアルデザインという2つのデザインがあると考えています（インタラクションについてはビジュアルのほうに含ませてください）。
どちらも、ユーザーの期待を裏切らない（ユーザーが意図したとおりに動く）ための重要な要素です。
この2つがしっかりと設計できていれば、プロダクトが違和感のあるものにはならないと思います。

そのうえで、ユーザーに「なんか使いやすい」とか「わかりやすい」「使っていて気持ちいい」と感じさせる、UIにおける重要な要素が**言葉**です。

## 言葉の選び方
どんな言葉を使うべきか考えるとき必要なのが、**プロダクトの人格**です。
「まじめで頼り甲斐がある」「仲のいい友達」「かっこいい男前キャラ」「かまってあげたくなる妹みたいな存在」など、考えだすと色々でてくると思います。
競合他社のこともあるので詳細は書けませんが、私が考える弊社プロダクトの人格は**「一見スマートで感情の起伏がなさそうだけど、実は心優しい紳士」**かな、、、違うか笑
完全に主観です笑
今度みんなでディスカッションしたい！

そんな人格を念頭におきながら、実際にどんなことに気をつけて言葉を選んでいるかを書いていきます。

### 体言止め（名詞）と用言止め（動詞）を使い分ける

これはよく議論になる点ですよね。
個人的には正解も不正解もないのかなと思っています。
プロダクトのなかで意図して使い分けができていることが重要なのかなと。

弊社プロダクトの場合は基本的には**体言止め**で統一しています。
シンプルで視認するまでの時間が短くなる、と考えているからです。
ボタンの文言を例に出すと

⭕確定
❌確定する

のように統一しています。

ただ、例外的に用言止めを使っている場面があります。
それは、新規に何かを作成したり、注意を促したりするときのモーダルダイアログ内のボタンです。
システムが特定の機能の使用に制限された状態であるモーダルダイアログは、OOUIにおいては非推奨とされていますが、弊社プロダクトでは重要な意思決定の場面でのみ使用するようにし、そのときに**ユーザーにより主観的に捉えてもらえるように**用言止めを使用しています。

例えば「このページを削除しますか？」というようなモーダル内では

❌削除
⭕削除する

としています。

### シンプルな表現を使う

これはどういうことかというと

⭕もどる
❌戻る
❌Back

こういうことです。

これもどれが正解でどれが不正解、というものではありません。
弊社プロダクトの特性上、**複雑さや難しさを極力減らしたい**と考えているので、上記の場合、よりシンプルで簡単な印象を与えられるひらがなを採用しています。

もちろん、ひらがなだと逆に意味が伝わりにくくなってしまう言葉では漢字を採用します。

❌へんしゅう
⭕編集
❌Edit

### 適切な距離感をとる

デジタルプロダクトは、特にtoB向けのものほど無機質で機械的、そして一方的な表現が多い印象があります（主観です）。
弊社プロダクトもtoB向けですが、「もっと使いたい！」と思い続けてもらえるようなプロダクトを目指しているので、細かなコミュニケーションを大切にしています。

例えば、初期セットアップが完了した画面で表示させるメッセージです。

❌以上でセットアップは完了です。
⭕お疲れさまでした。以上でセットアップは完了です。

「以上でセットアップは完了です。」でも問題ないですが、「お疲れさまでした。」と一言添えることで、プロダクトにより**人間味**がでてきます。

次はエラーのメッセージの例です。

❌ログインできませんでした
⭕ログインできませんでした...

エラーメッセージは無機質で冷たくなりがちです。
ユーザーの行動意欲をゼロにするにはうってつけのポイントです。
「ログインできませんでした」と突き放すのではなく、「...」をつけることで、ユーザーの失敗に対する同情を表現し、もう一度トライしてもらえるようコミュニケーションを図っています。

これらは本当に些細なことで、「そんなことで...」と感じる方もいると思いますが、このような細かな言葉の積み重ねがプロダクトの人格に影響してくるのではないかと私は考えています。

## 最後に

久保田利伸さんはMissingで「言葉にできるなら 少しはましさ」と歌い、
小田和正さんは「言葉にできない」と歌っています。

言葉ってほんと難しいものですね。

14日目の担当は @ihiroky です。
乞うご期待！
PHP超初学者がPHP Conferenceに行ってきた話

## はじめに
普段PL/Iというレガシー言語を扱う仕事しかしていない私ですが、
最近友人に引っ張ってもらいながらweb開発の勉強を始めました。
その一環で12/1(日)に蒲田で開催された[PHP conference](https://phpcon.php.gr.jp/2019/)に行ってきたので、
当日学んだことのアウトプットも兼ねてその所感を書きたいと思います。
初投稿ということもあり読みづらいとは思いますがサラッと流し読みしてくれればと思います。

## PHP conferenceとは
日本のPHPのユーザー会によって2000年に始まったPHPユーザーのための大規模カンファレンスで、
毎年1500人以上のPHPerがチャレンジ・成長、そしてその先へと進むための原動力を高めるために参加しています。
-PHP conference HPより抜粋-

本カンファレンスでは多くの講演が並行して実施されるのですが、
その中でも初学者向けのものと思われるものを中心に聞いてきました。

## 講演その①[PHP初心者セッション](https://fortee.jp/phpcon-2019/proposal/465ddfc4-cbdb-43a1-9bb0-c6862633617a)
前半30分でPHPを使う開発に必要な環境やツールの紹介、
後半30分で実際PHPを使った開発の方法や構文・お作法の解説という流れ。
つい２週間前にネットに書いてある手順と友人の手助けを元によく理解しないまま
自PCにXAMPP環境を導入した私にとって、開発環境まわりの話は非常に興味深かったです。

## 講演その②[思想と理想の果てに](https://fortee.jp/phpcon-2019/proposal/83963c84-1f47-4cf7-8b6e-4112a2360cd8)
今の自分にはレベルが高すぎた...MVCモデルやLaravelといった当時まだよく知らない用語が既知のものとして飛び交いとてもレベルの高い講義が展開されていました(一緒に行った友人はとても興味深そうに聞いていました)。
話としては互換性に依存しない開発手法の紹介的な感じだった気がします(難しすぎて良く覚えてない…)。

## 講演その③[PHPを学ぶということ](https://fortee.jp/phpcon-2019/proposal/d87ffabf-4532-4b3b-aa44-61e42abe2aa1)
webを作ろうとした際にPHPの他にもHTML,Javascript,CSS,SQLと学ばなければならない言語が多い。
そこでwebアプリにおけるそれぞれの言語の立ち位置と主な役割について簡単に解説していました。
講演時間も20分程度と短いものでしたがPHP初学者の私でもわかりやすくまとまってたと思います。

## 所感
プログラム言語のカンファレンス…と聞くと初めはスーツを着たやり手サラリーマンみたいな人がたくさんいて高度な技術トークを繰り広げているところなのかなと思っていましたが(実際そういう人もたくさんいました)、初心者向け講演も意外と多く想像以上に門戸が広くされていて安心しました。
また会場内も思っていたより活気があり、ブースを出している人も来場している人も大勢いて、みなさんの賑わいで自分の学習意欲も掻き立てられたなと思います。
今後はPHPだけでなく他の言語のカンファレンスにも足を運んでみたいと思うくらいには初学者にも良い刺激になるイベントでした。

## とはいえ...
イベント参加当日で言語初学者の私的に一番ためになった＆楽しかったのはPHP Conference終了後に友人とやった復習作業です。(プログラミング知識レベルをポケモンで例えるなら友人が75くらいで私が5くらいなので私の復習作業に付き合ってもらっただけなのですが...)
会場近くのカフェで友人と一緒にconference内で飛び交ったわけのわからない単語を調べたり、実際にフレームワークを導入してMVCモデルを作って動かしてみたりといった作業が本当に楽しかったし勉強になりました。
PHP Conferenceに行ってみた所感としてはどうかと思いますが、こういったイベントに参加することは学習のきっかけであり、大事なのはイベントの後の復習や学んだことのアウトプットなのだと身をもって知りました。

## 最後に
今までレガシー言語しか触ったことがない私からみてもPHPは非常にわかりやすく、普段私が意識しなければならないような内部的な部分がブラックボックス化され、言うなれば美味しい部分だけを考えてコーディングできるようになっていると感じます。
これから学習していく中で美味しくない部分もきっと見えてくるんでしょうが、それでもPHPはプログラム言語初心者が最初に触るにふさわしい言語だと思います。
（いないと思いますが）私のようにレガシー言語しか普段触っていないけどせっかくIT従事者になったんだからちゃんと今風のプログラムを学びたいと思っているそこの君、PHP、おすすめです。
RailsにてerbファイルをHamlに変換する方法

備忘録としてerbファイルをHamlに変換する方法をまとめました。
手順は下記の通りです。

#**1.Gemfileにgem 'haml-rails'を記述**


```Gemfile
gem 'haml-rails'
```

#**2.bundle installをする**
記述後、bundle installをする

#**3.拡張子がerbのファイルをhamlに変換**
```
$ rails haml:erb2haml
```
コマンドを実行すると...

```
--------------------------------------------------------------------------------
Generating HAML for app/views/home/top.html.erb...
Generating HAML for app/views/home/about.html.erb...
Generating HAML for app/views/layouts/application.html.erb...
Generating HAML for app/views/layouts/mailer.html.erb...
Generating HAML for app/views/layouts/mailer.text.erb...
--------------------------------------------------------------------------------
HAML generated for the following files:
	app/views/home/top.html.erb
	app/views/home/about.html.erb
	app/views/layouts/application.html.erb
	app/views/layouts/mailer.html.erb
	app/views/layouts/mailer.text.erb
--------------------------------------------------------------------------------
Would you like to delete the original .erb files? (This is not recommended unless you are under version control.) (y/n)
y
Deleting original .erb files.
```

変換完了です！
TypeScript×Nodeを勉強した時に参考にしたソースまとめ

# はじめに
TypeScriptのおすすめ記事をまとめました。
## 言語仕様
[TypeScriptの型入門](https://qiita.com/uhyo/items/e2fdef2d3236b9bfe74a)
## JavaScript
[イマドキのJavaScriptの書き方2018](https://qiita.com/shibukawa/items/19ab5c381bbb2e09d0d9)

## webpack
[webpack 4 入門](https://qiita.com/soarflat/items/28bf799f7e0335b68186)

# 終わり
TypeScriptの標準のAPIはJavaScriptと同じなので、やりたい処理はJSで調べて書き方をTSの記事をみて修正するというフローで勉強していました。
TSの書き方がわかるとフロントのVueとかReactでも使えるのでコスパが良いかなと思いました！
それでは！！
テスターの実施漏れを未然に防ぐテストケースづくり

#はじめに
皆様、今年も繁忙期のこの時期がやってまいりました。
どこのゲームQA業界でも、テスト実施漏れの対策については永遠の課題かなと思っています。
今回はQAの現場で、実施漏れを未然に防いでいくテストケースづくりについて纏めていきます。
こちらは個人的な好みや性格も内容に反映されているかと思うので、あくまで1つの考え方として参考になれば幸いです。

#テスト実施漏れはなぜ起きてしまうのか
まずはじめに、テスト実施漏れがなぜ起きてしまったかを考えてみます。
原因を以下のように書き出してみました。

**①テストケースの読み違い/見間違い**
**②テストケース内容の勘違い**
**③テストケースの見る箇所がずれていた**
**④確認個所が間違っていた**

まだまだありますが、書き出してみるとテストケース要因のヒューマンエラーが多いと思います。


#原因を深堀してみる
ここからは書き出した内容がなぜ起きてしまったかを深堀していこうと思います。

**「①テストケースの読み違い/見間違い」**はなぜ起きたか？
・テストケースのフォントが見づらかったり、文字の大きさが小さいなどで読み違える

**「②テストケース内容の勘違い」**はなぜ起きたか？
・1つの確認項目で複数の確認をするようなテストケースになっていて勘違いを引き起こす

**「③テストケースの見る箇所がずれていた」**はなぜ起きたか？
・テストケース内の項目の見通しが悪く見る箇所がずれてしまった

**「④確認個所が間違っていた」**はなぜ起きたか？
・確認内容などの文章が冗長的で間違えてしまう

個人的な体感ですが、このようにテスターにとって不親切な内容の確認項目は多くあり、
テスト実施漏れに誘導してしまっていることがあるのではないかと思っています。

#テスト実施漏れの未然防止案の紹介
以下は自身が未然防止の為に対策として実施したテストケース改善を紹介していきます。

**①テストケースの読み違い/見間違い**の対策/改善
・テストケースのフォントを見やすくし、文字の大きさを適切にすることで見落としを防いでいく
![6390481-aa434f52d466ff545a6366dafd39c1ced18ad2ce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541190/f0a53d2a-62d1-129f-9eb2-be25f3d372c7.png)

**「②テストケース内容の勘違い」**の対策/改善
・複数の確認をするような箇所は1つに纏めず項目細分化して見落としを防いでいく
![6390831-9ccbb52ab56fc0321e45a98cb49af1526cc1d7dc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541190/0cfd3023-310d-5cdd-9630-607e1ba0ae16.png)

**「③テストケースの見る箇所がずれていた」**の対策/改善
・重複している確認内容の羅列を無くし、テストケース内の項目の見通しを良くすることで見誤ることを抑制していく
![6390859-6734b878e48369c4a3a0b09abf85bf98f2931336.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541190/f2242c44-2861-ba3a-4188-82f140bd396f.png)

**「④確認個所が間違っていた」**の対策/改善
・確認内容や確認手順を段落番号などを使い、冗長的にならないようにすることで間違いを防いでいく
![6390863-e5dc2b7e458ca474d2cedc1a7d3c158da3a03896.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541190/be157cb2-c3e7-19f5-d7b4-afb3666b7213.png)

このようにテスターに見やすく分かりやすいテストケース作成を意識することで、テスト実施漏れの未然防止を図っています。
#まとめ
テスターに親切なテストケースづくりはテスト実施漏れを未然に防いでいける最大の近道だと考えています。
テストケース作成業務以外にも通じていることですが、何事も親切な心を忘れないことが大事な秘訣だと思います。

この記事が少しでも皆様の参考になれば幸いです。
最後までご覧いただきまして、ありがとうございました。
低品質Jpegを作るプログラム


DPZ
[写真を限界までJPEG圧縮すると見えてくる世界](https://dailyportalz.jp/kiji/jpeg-asshuku-genkai)

に触発されて、低品質Jpegを作るプログラム


```C#:JpgQlyZero.cs
//c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /target:winexe JpgQlyZero.cs

using System.Drawing;
using System.Drawing.Imaging;

public class JpgQlyZero
{
 public static void Main(string[] args)
 {
	if(args.Length==2){

		string path1; //in file name
		string path2; //out file name
		path1 = @".\" + args[0];
		path2 = @".\" + args[1];

		Bitmap image1;
		image1 = new Bitmap(path1, true);

		// Jpenの保存品質。小さいほど悪い
		int quality = 0; 
		ImageCodecInfo je = null;

		foreach (ImageCodecInfo ici in ImageCodecInfo.GetImageEncoders()) {
			if (ici.FormatID == ImageFormat.Jpeg.Guid) {
			je = ici;
			break;
			}
		}
		EncoderParameter ep= new EncoderParameter(Encoder.Quality, quality);
		EncoderParameters eps = new EncoderParameters(1);
		eps.Param[0] = ep;

		image1.Save(path2, je, eps);
	}
 }
}

```

（※画像は、Windows10のデスクトップ壁紙画像から）

劣化後
![bb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107418/439106d7-38f2-cc72-c7d1-9ad58950193f.jpeg)


劣化前
![A1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107418/c9e0f7bf-b3d4-e8c6-a168-21797130a24c.jpeg)


※以下のソースを参考、利用してます

[品質を指定してJPEG画像を保存するには？](https://www.atmarkit.co.jp/fdotnet/dotnettips/533jpgquality/jpgquality.html)
AndroidStudio4.0 Canaryでgradleを4.0.0にするとエラーになった

# はじめに
タイトルの通りです。
エラーになったので解消までの手順を備忘録として書いておきます。

# 何をしたか
「AndroidStudioの右下に、gradleの最新があるからupdateする？」
と出たのでアップデートしたらエラーが出ました。

```
Could not find org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.60-eap-25
```

こんな感じでエラーが出ました。

# 解消方法
https://androidstudio.googleblog.com/2019/10/android-studio-40-canary-1-available.html

ここを読め！なんですが、以下な感じです。

TopLevelのbuild.gradleに以下を追記しましょう。

```:./build.gradle
buildscript {
    repositories {
　　　　　・・・
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
    }
}

allprojects {
    repositories {
　　　　　・・・
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
    }
}
```

Syncしましょう。

以上！

# 所感
わからないことはすぐに調べて解消しないと挫折しちゃう。
日本語Webフォントをサブセット化してCSSで使用する

（前日だけ空いてしましましたが）パーソンリンクアドベントカレンダー、折り返し地点を超えた13日目の投稿です。
今回はwebサイトでのカスタムフォントのサブセット化について書きます。

# フォントのサブセット化とは
フォントを特定の文字のデータだけ抽出したフォント(サブセット)に分割する事をサブセット化と呼んでいます。
たとえば、英文字しか使ってないページでは、英数字のサブセットフォントのみ使用する、といった事が考えられます。
最小限のサブセットのみ使うようにすれば、ページ表示時間短縮や通信データ量の短縮が期待できます。

Googleによる詳細な解説
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization


# サブセット化のパターン
サブセットの分け方としてはおおよそ以下の３つが考えられます

1. 英数字、記号、かな・カタカナ、第１水準漢字、第２準漢字といった文字としての意味をもったサブセット
 英字はいいけど、漢字の容量が大きいのは変わらない・・・

2. サイト内で実際に使用している文字のみを持つサブセット
 使用する文字が決まっている、すなわちテキスト部分が静的なサイト向け。

3. 出現頻度や同時に出現する確率で分けたサブセット
動的コンテンツのサイトで特に有効。
すべての文字をカバーしつつ、ページごとに最小限のフォントファイルの読み込みを行おうとします。

# 実際にやってみる
今回は3の方法でサブセットを作成するために、簡単なスクリプトを用意してみました。
[font-google-subset](https://github.com/shg-shg/font-google-subset)
以下、スクリプトの内容と実行手順です。

## フォントのサブセット範囲を決める
Google FontsのNoto Fontのcssを見ると、`unicode-range` を使って読み込むサブセットを細かく指定しています。
どういうアルゴリズムで算出した分け方なのかは公開されていないようですが、恐らく使用頻度や文字の種類、漢字の部首グループなどで分けれているのだと思います。
今回はこのunicode-rangeの分け方を拝借します。
https://fonts.googleapis.com/css?directory=3&family=Noto+Sans+JP
![Google FontsのCSS](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541329/befe5e1c-dfdc-7302-66ea-9e6d4d8ee72b.png)

## フォントのサブセットを作成
[font-ranger](https://github.com/doasync/font-ranger)を使い、全パターン分のサブセット作成と、サブセットに対応した@font-faceのリストを持つCSSファイルの生成を行います。

## サブセット化したフォントを読み込むCSSを作成
[font-ranger](https://github.com/doasync/font-ranger)でサブセットと同時に出力されたCSSを１つのファイルに統合して、Google FontsのCSSと同様のものを作成します。

あとは作成したCSSとサブセットフォントをサイトに配置するだけで、各ページで必要に応じたサブセットをブラウザが読み込んでくれます。

なお、@font-faceは古いブラウザだと対応していませんので、そういう環境でもフォントを使いたい場合はfallbackとしてttf/woffを用意する必要があります。

## 実際に実行してみる
以上の手順を実行する簡単なスクリプトを用意してみました。
[font-google-subset](https://github.com/shg-shg/font-google-subset)（実行手順はREADME.md参照 / 一部ttfなどは動かないようです）

なお、実際にサイトで使用する際は使用するフォントの利用規約に注意してください。
フォントのサブセット化は、各フォントの規約における**改変**にあたる可能性があります。

## 参考にさせていただいた記事
[日本語 Web フォントの読込み速度を改善する - その1] (https://qiita.com/megurock/items/da484d4ec44577ae7f95)

---
以上となります。明日は@shothymさんの記事ですね。お楽しみに！
リモートデスクトップで GNU/Linux に接続する

## はじめに

GNU/Linux はデスクトップ環境を入れず CUI で利用するのが基本でした。

しかし、最近では GUI な GNU/Linux 環境にリモートデスクトップ接続できると何かと便利と感じることが多いためその方法をメモ。

## 環境設定

xrdp を使います。

### パッケージのインストール

```sh
sudo apt install xrdp lxde
```
## 

### 設定ファイルの編集

/etc/xrdp/xrdp.ini を編集。

```
[Xorg]
name=Xorg
lib=libxup.so
username=ask
password=ask
ip=127.0.0.1
port=-1
code=20
```

Xorg 以外のセクションはコメントアウト。

### セッションを指定

~/.xsession にて指定。

```
cinnamon-session
```

### 暗号化を無効にする

[これ](https://kokufu.blogspot.com/2018/07/vino-windows-vnc.html)の対策。

```sh
gsettings set org.gnome.Vino require-encryption false
```

### サービス起動

```sh
sudo service xrdp restart
```

### ポートを開放

iptables を変更して 3389 番ポートを開放する。

## 完了


成功するとこのような感じになります。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38501/c3c649e1-9161-5fff-29a5-ea6e3466bdde.png)


別の Windows 環境にリモートデスクトップすることがよくあるため、同じノリで GNU/Linux にも接続できて便利です。

なお LAN 内での使用を想定。
laravelでbootstrap-vueを使う

1.ターミナルにて下記コマンド実行

```
npm install vue bootstrap-vue bootstrap
```

2.src/resources/js/app.jsに下記コード追加

```src/resources/js/app.js
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue)
```

3.もっと気軽に使いたい場合はCDNで
①head内に下記を記述

```
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css">
```

②bodyの最後に先下記を記述

```
<script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
```