OmniAICreator/Qiita-1.07M huggingface dataset:
EntityFramework のテーブル名を複数形化せずモデルクラス名をそのまま使う


1個ずつ指定するならTable属性でモデルクラスに指定

``` BUSHO.cs
    [Table(nameof(BUSHO))]
    public class BUSHO
    {
      .....
    }
```

ただ、いちいちTable属性を指定するのは面倒なので、名前の変更を行っている`PluralizingTableNameConvention`を無効化する。
`DbContext`の`OnModelCreating`の中で行えばよい。

``` AppDbContext.cs
    public class AppDbContext : DbContext
    {
        public AppDbContext()
            : base("name=AppDbContext")
        {
        }
        // Table
        public virtual DbSet<BUSHO> BUSHOs { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //テーブル名を複数形化せずモデルクラス名をそのまま使う
            modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
        }

    }
```
CentOS7にNginx（SSLアクセラレータ）+Apache（リバースプロキシ）を入れたら動かない

自分用の備忘録です。多分お役に立てない。

# 作りたい環境
▼OS
CentOS7.6

▼ミドルウェア
Apache（リバースプロキシ）
Nginx（SSLアクセラレータ）

# 行った作業
1. CentOS7インストールおよび初期設定
2. yumアップデート
3. Nginxインストール（80番ポートに自動設定）
4. mod_sslインストール
5. Nginx SSL設定（443番ポートに設定）
6. Apacheインストール（8080番ポートに手動設定）
7. 同時にphp、php-mbstringインストール
8. Apache再起動（設定反映のため）

# ここで問題発生
Apacheが再起動出来ず。

たちけて。

# 原因は？
journalctlで確認すると・・・

```:console
# journalctl -u httpd.service

 (98)Address already in use: AH00072: make_sock: could not bind to address [::]:443
 (98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:443
```

Apacheの再起動時、自動的にhttpsの接続も実行され443番ポートへアクセスを試みていたため、先に443番ポートを使用しているNginxとぶつかってしまい再起動を実行出来なくなっていた。

そりゃそうだよね。



# 試した解決策
Apacheが443番ポートに接続しようとしてるのが原因なら、それを止めちゃえばいいんだよね。

```:console
# vi /etc/httpd/conf.d/ssl.conf
```

```:/etc/httpd/conf.d/ssl.conf
# When we also provide SSL we have to listen to the
# the HTTPS port in addition.
#
Listen 443 https
↓書き換え
Listen 444 https


##
## SSL Virtual Host Context
##

<VirtualHost _default_:443>
↓書き換え
<VirtualHost _default_:444>


# General setup for the virtual host, inherited from global configuration
DocumentRoot "/var/www/html"
#ServerName www.example.com:443
↓書き換え（コメントアウトしてるけど念のため）
#ServerName www.example.com:444
```

で、とりあえず動いた。
今のところ不具合は出ていないが、今後作業を進めて行った時どうなるか分からない。

細かいところは随時調べていく予定。
多階層カテゴリーの実装

# 多階層カテゴリーの実装
多階層カテゴリー...
rails初心者の方にとっては中々高い壁ではないでしょうか。
そこで、rails初心者である私が実装した三層のカテゴリー検索機能について、説明させて頂ければと思います。
少しでも参考になれば幸いです。

# 必要なテーブル、カラム
categoriesテーブル
・nameカラム
・parent_idカラム

上記テーブル、及びカラムが必要となります。
parent_idという謎のカラムが存在しますが、説明は後程。

# アソシエーション
今回は一つのテーブルで、一層目のカテゴリー、二層目のカテゴリー、三層目のカテゴリーと、全てのカテゴリーを取得出来るよう実装します。

そのためにまず、下記のようなアソシエーションを組みます。

```category.rb
class Category < ApplicationRecord
  belongs_to :parent, class_name: :Category
  has_many :children, class_name: :Category, foreign_key: :parent_id
end
```

...上記を見てこう思わないでしょうか。

・なんでcategoryモデルからcategoryモデルにアソシエーション組んでんの？
・そもそもparentとchildrenって何？

これは自己結合モデルというアソシエーションの組み方で、一つのデータベースモデルに全カテゴリーを格納したいけれども、親カテゴリーと子カテゴリーの関係も追えるようにしたい...
そういった時に使用することで、任意のデータの取得が可能になります。

# データベース

次に下記のように

###### categoriesテーブルのデータベース
|id|name|parent_id|
|------|----|-------|
|1|レディース|""|
|2|トップス|1|
|3|パンツ|1|
|4|靴|1|
|5|Tシャツ|2|
|6|セーター|2|
|7|パーカー|2|

parent_idに親カテゴリーのidを入れるよう、データベースにカテゴリーを登録してください。seedファイル等を利用して登録すれば良いと思います。

# データの取得

上記アソシエーションの定義、及びカテゴリーの登録によって

```
@category = Category.find(1)
# 下記でレディースに紐付く子カテゴリーであるトップス、パンツ、靴を全て取得出来る
@category.children
----------------------------
@category = Category.find(2)
# 下記でトップスに紐付く子カテゴリーであるTシャツ、セーター、パーカーを全て取得出来る
@category.children
# 下記でトップスの親カテゴリーであるレディースのカテゴリーを取得出来る
@category.parent
----------------------------
@category = Category.find(5)
#　下記でTシャツの親カテゴリーであるトップスのカテゴリーを取得出来る
@category.parent
# 下記でTシャツの親の親のカテゴリーであるレディースのカテゴリーを取得出来る
@category.parent.parent
```

任意のカテゴリーを引っ張ってこれるようになります。

また、少し発展的な話をすると

```
@category = Category.find(params[:id])
  @categories = [
    # 下記で@categoryを取得
    @category,
    # 下記で@categoryの子カテゴリーを全て取得
    @category.children,
    # 下記で@categoryの子カテゴリーの子カテゴリーを全て取得
    @category.children.map { |category| category.children }
  ].flatten.compact
```

この記述で、idの部分に任意のidを入れると、そのidに関連した全ての子カテゴリーを取得することが出来ます。
例えば、上記の例だとidに1を入れることで、レディース関連のカテゴリーを全て取得することが可能です。

※一番下に記述されているflattenメソッド、compactメソッドはそれぞれ
・複雑化した配列を平坦に返す
・配列の中で発生するnilを取り除いた新しい配列を返す
という機能を持っています。

これらのメソッドを応用することで、何とか三層のカテゴリー検索機能を実装することが出来ました！

# 参考
https://jvvg0oynveolxikm.qrunch.io/entries/3JG4bNOVyRgNxVGt
Webpack4 + Vue.jsの設定手順

久しぶりにWebpackから設定したら忘れていることが多かった。
今後設定をする機会のために手順をメモした。

今回はVue.jsだったがReactなどでも設定をする機会がありそうなので、
そのときはここに追記しようと思う。

## Webpack
### webpackをインストール

```bash
# use yarn
yarn add --dev webpack

# or npm
npm install --save-dev webpack
```

### webpack-cliをインストール
webpack4から必要になった。

```bash
yarn add --dev webpack-cli
```

### webpack-dev-serverをインストール
Webサーバを提供。
ライブローディングに対応する。

```bash
yarn add --dev webpack-dev-server
```

```js:webpack-config.js
+  devServer: {
+    contentBase: './dist'
+  },
```

コマンドを追加
```json:package.json
```

## Vue.jsを導入する
### vueをインストールする

```bash
yarn add vue
```

### vue-loaderをインストールする
単一コンポーネントをコンパイルするために必要。
vue-loaderと依存関係があるvue-template-compilerの一緒にインストールする。

```bash
yarn add --dev vue-loader vue-template-compiler
```

拡張子がvueのときは、vue-loaderでトランスパイルするための設定を追加する。

```js:webpack-config.js
module: {
  rules: [
    {
      test: //.vue$/,
      loader: 'vue-loader'
    }
  ]
}
```

### babelをインストールする
ES6, 7をES5にトランスパイルするためにbabelを使う。

```bash
yarn add --dev babel-loader @babel/core @babel/preset-env
```

webpack-config.jsにjsファイルはbabel-loaderでトランスパイルするという設定を追加する。

```js:webpack-config.js
  module: {
    rules: [
      {
        test: //.js$/,
        exclude: /node_modules/,
        loader: "babel-loader"
      }
    ]
  }
```

babelrcでは対象に含めるブラウザなどを設定できる。
今回は最小限の設定。

```js:.babelrc
{
  "presets": ["@babel/preset-env"]
}
```

### SASSを使えるようにする
単一コンポーネントのstyleでSASSを使えるようにする。

SASSをコンパイルするために必要なloaderをインストールする。

```bash
yarn add --dev sass-loader node-sass css-loader
```

webpack-config.jsにSASSをコンパイルするための設定を追記する。

```js:webpack-config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.sass$/,
        use: [
          'vue-style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              indentedSyntax: true
            }
          }
        ]
      }
    ]
  }
}
```

### svgを使えるようにする
```bash
yarn add --dev vue-svg-loader
```

webpack-config.jsに設定を追加する。

```js:webpack-config.js
module.exports = {
  module: {
    rules: [
      {
        {
          test: /\.svg$/,
          loader: 'vue-svg-loader'
        }
      }
    ]
  }
}
```

## 拡張子を省略する
importするときのファイル名から拡張子部分を省略できるようになる。
この例では、`.js`と`.vue`拡張子を省略できるようにしている。

```js:webpack-config.js
  resolve: {
    extensions: ['.js', '.vue']
  }
```
Windows10 Bitnami Redmine バックアップ mysqldump でやったこと

#目的・やりたいこと
- Bitnami RedmineをPC①(Windows10)にインストールして、諸々の設定をした後、PC②(Windows10)のBitnami Redmineにリストアしたい。

# 参考サイト
* [windowsでRedmine (bitnami) バックアップとリストア](http://manbou404.blogspot.com/2014/03/windowsredmine-bitnami.html)
* ↑ほぼこのサイトの手順通り

# やったこと
## データベースのバックアップ（MySQLのdump）
### サービスの停止
* Bitnami Redmineインストールフォルダ直下のmanager-windows.exeを起動する。  
 (私の場合は、C:\Bitnami\redmine-4.0.1-0\manager-windows.exe)
* MySQL Database以外のサービスをStopする。  
![サービス停止.png](https://qiita-image-store.s3.amazonaws.com/0/281492/c066eaa5-b844-bdc9-cc4f-f87597ca3cfa.png)

### productionのデータベース名、ユーザ名、パスワードを調べる
```(インストールフォルダ　\Bitnami\redmine-4.0.1-0\apps\redmine\htdocs\config\database.yml)
production:　　←productionであることを確認
  adapter: mysql2
  database: bitnami_redmine  ← データベース名
  host: 127.0.0.1
  username: bitnami　　　←ユーザ名
  password: XXXXXXXXXX　←パスワード
  encoding: utf8
  port: 3306
```

### データベースのバックアップ
* インストールフォルダにある、use_redmine.batを実行し、コマンドプロンプトを起動
* MySQLのdumpを取得  
先に調べたユーザ等から、下記のようにコマンド実行  
-u にユーザ、-p の直後にスペース無しでパスワード、パスワードの後にデータベース名、-r にファイル名を含めた任意の出力先パス  

```
C:\Bitnami\redmine-4.0.1-0>mysqldump -u bitnami -pc193d98a49 bitnami_redmine -r D:redmine_backup.sql
Warning: Using a password on the command line interface can be insecure.
```

### 添付ファイルのバックアップ
* C:\Bitnami\redmine-4.0.1-0\apps\redmine\htdocs\files をフォルダごとバックアップ

# 続きは参考サイトの通り・・・
配列のポインタとポインタのポインタ


配列のポインタというかポインタのポインタというかポインタでハマったので忘れないうちに簡単にまとめてみます。

# 配列のポインタとは
ポインタの配列ではなく配列のポインタ。
例えば

```C
char hoge[] = "fuga";
```
と宣言します。
すると配列のポインタは`&hoge`です。

# 配列と配列のポインタ
ここで配列には配列のポインタが存在するので`&hoge`、すなわち配列のポインタを参照することができます。
ここで`hoge`と`&hoge`のポインタを見てみると

```c
  printf("hoge = %p\n", hoge);
  //=> hoge = 0061FF2B
  printf("&hoge = %p\n", &hoge);
  //=> &hoge = 0061FF2B
```
このようになります。

結局同じアドレスを指しています。
これは配列の先頭アドレスになるので結局配列のポインタも配列の文字列の先頭アドレスを指します。

じゃあ何が違うんだ！というと型が違います。
`hoge`は`char*`型ですが`&hoge`は~~`char**`型になります~~(訂正:追記参照)。
つまり型違いで同じアドレスを指しているわけです。

---
追記(1/25)

`&hoge`は`char**`型ではありません。
配列のポインタ型であり、`char* []`型になります。

shiracamusさんコメントありがとうございました。

# ポインタのポインタと配列のポインタ
私が陥った罠はこれです。
関数間で配列を受け渡すとき、配列のアドレスを仮引数で宣言したポインタへ受け渡します。
`hoge`を`piyo`の引数として渡すと、

```c
void piyo(char* foo)
{
  printf("foo = %p\n", foo);
  //=> foo = 0061FF2B
  printf("foo = %p\n", &foo);
  //=> foo = 0061FF10
}
```
このようになります。
配列のポインタと思い込んで`&foo`を参照したところ全く違うアドレスを参照してしまいました。

つまりこのときの`foo`は配列ではなくポインタであるため、`&foo`は配列`hoge`のポインタではなく配列`hoge`のアドレスを持ったポインタ`foo`のポインタになります。
つまり配列とはまったく別物で、変数`foo`のアドレスを指しています。
ポインタを理解していないせいでここでハマりました…

ここで`&foo`は`char**`型なので例えば`char* pに`アドレスを渡すときは`&foo`を`char*`型にキャストしなければ型が競合します。

ポインタとはアドレスを保持することのできる変数、と理解しておくとこのようなミスがなくなるのではと思います。

# 考察
ここからは考察になりますが、ポインタとはアドレスを保持することのできる変数、であり、`*p`のようなポインタの指す変数の中身を参照するときの挙動としては、保持している先のアドレスを参照し、そこにある値を見ているのではと思います。というかそれしか説明つかない…

# おわりに
仮引数で宣言したポインタに配列を渡すときはアドレスが渡されていて配列は渡されているわけではないという理解が大事だったんだなぁと感じました。
windows10でpipができない

TwitterのＡＰＩを使ってみたくて、
Windowsにpythonを入れてみました。

tweepyというライブラリが使いやすと聞き、
コマンドプロンプトで
>python

を立ち上げ、

> pip install tweepy

と、入れてみたところ

>  File "<stdin>", line 1
>    pip install tweepy

ヨクワカラナイが、ライブラリがインストールできてないことだけはわかる。
※勘違いしていました。下記追記をみてください。

色々調べてみて、
権限の問題かも？ということで

Windows下のメニューで
>cmd 
でコマンドプロンプトを出して右クリック
>管理者として実行
をクリック。

こちらのコマンドプロンプトで
>python

を立ち上げ、
> pip install tweepy

を入れたところ

>Collecting tweepy

からはじまり、

>Successfully installed ～

成功した！！

>You are using pip version 10.0.1, however version 19.0 is available.
>You should consider upgrading via the 'python -m pip install --upgrade pip' command.

さらに、この「pipのバージョンが低いよ」というメッセージが出たので、
>python -m pip install --upgrade pip

を入れてみる。

>Successfully installed pip-19.0.1

こちらも成功！

----

追記
そもそも、

>python

を立ち上げ、

> pip install tweepy

すること自体が間違ってました。
pythonを入れずに、そのままコマンドプロントに

> pip install tweepy

と入れる、が正解。

それでも、

>Command ""c:\program files\python37\python.exe" -u -c "import setuptools, tokenize;file='C:\Users\ユーザー名\AppData\Local\Temp\pip-install-ig875ep4\simplejson\setup.py';f=getattr(tokenize, 'open', open)(file);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, file, 'exec'))" install --record C:\Users\ユーザー名\AppData\Local\Temp\pip-record-156tbm1v\install-record.txt --single-version-externally-managed --compile" failed with error code 1 in C:\Users\ユーザー名\AppData\Local\Temp\pip-install-ig875ep4\simplejson\

とエラーが。
上記「管理者として実行」だと通る。

C:\Program Filesにpythonがインストールされていたため、権限がない？
というわけでして
Install for all users のチェックを外して再インストールしたところ
pipできるようになりました！

ご指摘ありがとうございます。
Gitでgpg署名付きcommitをするまで

ふとgitでcommitする際に署名をつけてみたいと思いやってみました。
[GitHubにgpg署名付きのコミットをする](https://qiita.com/kentfordev/items/0e44f563caf39cd3eb9e)を参考にしましたが、現在では一部うまく動かなかったところがあったので一部変更しながら紹介します。
Mac環境(macOS Mojave)で検証しました。

# TL; DR
``` sh
# 必要なツールをインストール
$ brew install gpg2 pinentry-mac

# 鍵を生成
$ gpg --full-gen-key

# 生成した鍵のIDを調べる
$ gpg --list-secret-keys --keyid-format LONG

# Gitの設定
$ git config --global gpg.program gpg
$ git config --global user.signingkey {鍵のID}

# gpgの設定
echo "pinentry-program /usr/local/bin/pinentry-mac" > ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent

# 署名付きでコミットする
git commit -S
```

# gpgをインストールする
gitではgpgを使ってコミットに署名をつけることができます。([詳細はこちら](https://git-scm.com/book/ja/v2/Git-のさまざまなツール-作業内容への署名))
必要なツールをbrewでインストールします。

``` sh
$ brew install gpg2 pinentry-mac
```
以前はgpg-agentもインストールしていましたが、現在はgpg2の中に統合されたようです。
[No available formula with the name "gpg-agent"](https://github.com/pstadler/keybase-gpg-github/issues/30)
# 鍵生成
署名に使う鍵を生成します。

```
$ gpg --full-gen-key
```
その後色々と聞かれるので適宜設定していきます。
オプションを細かく設定したかったので`--full-gen-key`を指定しましたが、こだわりがなければ`--gen-key`でも構いません。
名前とメールアドレスはgitで設定しているものと同じにしましょう。下記のコマンドで確認できます。

```
$ git config --get user.name
$ git config --get user.email
```

# gitの設定を変更する
はじめに生成した鍵のIDを確認します。

```
$ gpg --list-secret-keys --keyid-format LONG
/Users/ユーザ名/.gnupg/pubring.kbx
--------------------------------
sec   rsa4096/{鍵のID} 2019-01-25 [SC]
      ***
uid                 [ultimate] 名前 <メールアドレス>
ssb   rsa4096/*** 2019-01-25 [E]
```
確認した鍵のIDをgitに登録します。

```
$ git config --global gpg.program gpg
$ git config --global user.signingkey {鍵のID}
```

# gnupgの設定をする
`~/.gnupg/gpg-agent.conf`に設定します。

```plaintext:~/.gnupg/gpg-agent.conf
pinentry-program /usr/local/bin/pinentry-mac
```
その後設定を反映するためにgpg-agentを一度終了させます。

```
gpgconf --kill gpg-agent
```
署名時に自動起動するので再び起動する必要はありません。
[How can I restart gpg-agent?
](https://superuser.com/questions/1075404/how-can-i-restart-gpg-agent/1150399)

上記の手順を行わなかったため、コミット時に

```sh
error: gpg failed to sign the data
fatal: failed to write commit object
```
とエラーが出て署名付きでコミットできませんでした。

# 署名付きでコミットする
```
git commit -S
```
`-S`オプションをつけることで署名できます。

# GitHubに鍵を登録
```sh
$ gpg --armor --export {鍵のID} | pbcopy
```
pbcopyは出力をPasteboard(クリップボード)にコピーします。
あとは[GitHubの鍵の設定](https://github.com/settings/keys)からNew GPG Keyをクリックし、
出てくるテキストボックスに貼り付け、Add GPG Keyをクリックします。

# あとがき
以上で署名付きでコミットができるようになるはずです。
もし間違いなどがあればご指摘いただければ幸いです。

# Reference
https://qiita.com/kentfordev/items/0e44f563caf39cd3eb9e
https://git-scm.com/book/ja/v2/Git-のさまざまなツール-作業内容への署名
https://github.com/pstadler/keybase-gpg-github/issues/30
https://superuser.com/questions/1075404/how-can-i-restart-gpg-agent/1150399
VirtualBoxにインストールしたCentOS7.5が異様に遅い

メモです。

WindowsのVirtualboxにCentOS7.5をインストールしました。

CentOS7.5のGUIでWindowの切り替えをしようとしても反応がなく、
ものすごく反応が遅かった時の話。

いろんなサイトを回って見ましたが、
あれこれ試してもだめでした。

どのタイミングで遅くなったかというと、
`yum update`してからでした。

結論

```
CentOS Linux (3.10.0-957.1.3.el7.x86_64) 7 (Core)　←コレだと遅い
CentOS Linux (3.10.0-862.el7.x86_64) 7 (Core)
```

![kernel.PNG](https://qiita-image-store.s3.amazonaws.com/0/213689/f5983c6b-c7fe-b3da-c7ff-25e21abdf0de.png)


新しいKernelと相性が悪いんでしょうか。。。
システム構成 応用情報技術者試験 対策日記@10

#システムの構成

##1.システムとは？
複数のコンピュータやサーバ、プリンタなどが集まった時の全体の構成のこと。一つ一つのハードウェアを組み合わせることによってシステムが成り立っている。

##2.デュアルシステムとデュプレックスシステム
###デュアルシステム
二つのシステムを用意し、並列して同じ処理を走らせて、結果を比較して照合する方式。高い信頼性が得られるほか、一つのシステムに障害が生じても処理を続行することができる。

###デュプレックスシステム
二つのシステムを用意し、普段は片方のみ稼働させて、もう一方は待機させておく方式。主系システムに障害が起きたら従系システムに切り替える。従系の待機のさせ方によって三つのスタンバイ方式がある。

**ホットスタンバイ** 従系のシステムを常に稼働可能な状態で待機させておく。障害発生時に自動的に従系に切り替えて処理を継続することを**フェールオーバ**と呼ぶ。

**ウォームスタンバイ** 従系のシステムを本番と同じような状態で用意してあるが、すぐには稼働できない状態で待機させておく。切り替えに少し時間がかかる。

**コールドスタンバイ** 従系のシステムを機器の用意だけして稼働させずに待機させておく。

##3.RAID
複数台のハードディスクを接続して全体で一つの記憶装置として扱う仕組みを**RAID(Redundant Arrays of Inexpensive Disks)**と呼ぶ。
###RAID0
複数台のハードディスクにデータを分散することで高速化したもの。これを**ストライピング**という。

###RAID1
複数台のハードディスクに同時に同じデータを書き込むもの。これを**ミラーリング**という。

###RAID0+1, RAID1+0
RAID0、RAID1は速度、信頼性のどちらか一方しか向上しない。そのため、この二つを組み合わせた技術がRAID0+1, RAID1+0である。RAID0+1はストライピングしたディスクをミラーリングする。RAID1+0はミラーリングしたディスクをストライピングする。どちらも最低ディスクが4台必要になる。

###RAID3, RAID4
複数台のディスクのうち一台を誤り訂正用のパリティディスクにするもの。パリティディスクには他のディスクの偶数パリティを保存しておく。一つのディスクが故障した場合、パリティを用いて復元ができる。これをビット毎に行う方式がRAID3、ブロック毎に行う方式がRAID4である。

###RAID5
RAID4のパリティディスクは誤り訂正専用であるため、通常は使われない。しかし、データを分散させた方がアクセス効率は上がるので、パリティをブロック毎に分散し、通常時にも全てのディスクを使うようにした方式。

###RAID6
RAID5においてディスクが二種類同時に壊れても大丈夫なように、冗長データを二種類作成したもの。

##4.信頼性設計
**フォールトトラレンス** システムの一部で障害が起こっても、機能停止を防ぐ設計手法。

**フォールトアボイダンス**　個々の機器の障害が起こる確率を下げて、全体的信頼性を向上させる考え方。

**フェールセーフ** システムに障害が発生した時、安全に制御する方法。

**フェールソフト** システムに障害が発生した時、当該部分を切り離すなどして最低限のシステムの稼働を続ける方法。この時限定的に稼働を続ける操作を**フォールバック**という。

**フォールトマスキング** 障害発生時にその影響が外部に出ない様にする方法。

**フールプルーフ** 利用者が間違った操作をしても危険な状況にならない様にするか、そもそも間違った操作ができない様にする設計手法。

##5.色々なシステム構成
**クラスタ** 複数のコンピュータを結合してひとまとまりにしたシステム。

**シンクライアント** クライアントの端末では最小限の処理しか行わず、ほとんどの処理をサーバで行う方式。

**P2P(ピアツーピア)** 端末同士で対等に通信を行う方式。サーバを介さずクライアント同士で直接アクセスする。

**分散処理システム** 複数台のコンピュータが通信しあって複数のプログラムを並列的に実行し、一つの処理を行うシステム。複数の場所で処理を行うが、場所にかかわらず利用者が同じ方法でアクセスできる**アクセス透過性**が重要になる。

**CDN** 動画などの大容量のデータを利用する際に、インターネット回線の負荷を軽減するためにサーバを分散配置する手法。

##6.仮想化技術
サーバの仮想化方式には、OSの上にアプリケーションをインストールして仮想マシンを実行する**ゲストOS方式**と、物理マシンに仮想OSを直接インストールする**ハイパーバイザ方式**がある。

サーバの性能を上げるためには、サーバのハードウェアを高性能なものにする**スケールアップ**と、サーバの数を増やす**スケールアウト**がある。仮想サーバではこの二つの手法を同時に用いている。

**シンプロビジョニング** サーバではなく、ハードディスクなどのストレージを仮想化する技術。

**ライブマイグレーション**　仮想サーバで稼働しているOSやソフトウェアを停止させることなく、他の物理サーバへ移し替える技術。

------
[ホームへ](https://qiita.com/k-y/items/dc2c9a3a8425712253e8)
Heroku上のRails環境にnatto(mecab)を導入する手順

# 目的
Heroku上のRails環境にnatto(mecab)を追加したときに、Herokuのデプロイ中にmecabに関連するライブラリが見つからずビルドが失敗するようになったので対応方法を記録しておきます。
また、Circle CIを利用していてCircle CIのビルドに失敗するようになったので、この対応方法についてもメモ。

# 対象読者
- Heroku上のRails環境でnatto(mecab) gemを使いたい人
- natto(mecab)を導入したことで、Circle CIのテストに失敗するようになった人

# Herokuのデプロイ中にnatto(mecab)をインストールする設定をする
以下の記事を参考に設定をする
https://qiita.com/shouta-dev/items/cd538a77f2b729333025

上記の記事でやっていることをまとめると

- heroku-buildpack-multi を導入し、linuxbrewのインストールをする
- (linuxbrewでbrewコマンドが使えるようになるので)brewでmecabをインストールをする
- Ruby、Railsのインストールをする

# Gemfileにnattoを追加
```ruby:Gemfile
gem 'natto'
```

# Circle CIのyamlにmecabをインストールする設定を書く
```yaml:.circleci/config.yaml
...略
jobs:
  test:
      docker:
         - image: circleci/ruby:2.4.1-node-browsers
           environment:
             RAILS_ENV: test
      working_directory: ~/project
      steps:
        - run:
            name: Install MeCab
            command: |
              sudo apt-get update;
              sudo apt-get -y install mecab libmecab-dev mecab-ipadic-utf8
     　 ここ以降にテストを実施タスクを書くを書く
...略
```

Circle CIのビルド時にmecabがインストールされるようになります。
ただ、問題点としてmecabを毎回インストールするのでビルド時間が遅くなってしまいます。
キャッシュする方法があれば知りたいです。。


以上です。
勾配降下法について勉強

# 勾配降下法 とは
機械学習や深層学習で利用されるパラメータの最適化の方法のひとつ。
モデル式の誤差を小さくなるような、パラメータを探したい。

<img src="https://qiita-image-store.s3.amazonaws.com/0/333838/54511e66-bf17-3f14-4073-222da2d11c47.png" width=70%>
図：パラメータが一つの場合

パラメータを少しずつ動かして、誤差の小さくなる場所を探していく。

1. 適当なパラメータを設定して、誤差の式を微分 → 傾きを求める → 傾きが右下がりだったので、グラフは減少傾向にある、とわかる
2. パラメータを少し右に動かしてみる
3. 傾きを求める

これを繰り返して傾きが0になる点を探していくことで、誤差の最小値を探していく。
<img src="https://qiita-image-store.s3.amazonaws.com/0/333838/2396e5cf-7a47-1b9b-5bac-2f37785ce87e.png" width=70%>

# 問題点
1. データ量が多いと計算量が増え、１回の重み更新に時間がかかってしまう
2. **ローカルミニマム**に陥ってしまう

### ローカルミニマム
誤差が小さくなるようにパラメータを変更していくので、小さな谷を抜け出すことができない。
<img src="https://qiita-image-store.s3.amazonaws.com/0/333838/be17dd1d-79f2-f0ba-c089-bbe031f49e14.png" width=70%>

# 確率的勾配降下法
上の２つの問題の解決策が**確率的勾配降下法**。
全データから数十件~数百件のデータセット(ミニバッチ)を作成し、計算する。
→ 計算量の問題は解決

全データで計算したときのようにまっすぐ極小値へ向かわないこともあるが、ローカルミニマムから出られない、ということはなくなる。
何度も試行することで確率的に最小の誤差に向かっていく。

# 参考

- 新村 拓也. TensorFlowではじめるDeepLearning実装入門 impress top gearシリーズ . Kindle 版. 
- https://shironeko.hateblo.jp/entry/2016/10/29/173634
Vue.js+PHP+Slim Frameworkでログイン認証（コンパイルなしSPA）

# はじめに

このアプリは、クライアントサイドは、Vue.jsを使ってSPA（シングルページアプリケーション）を実現し、サーバーサイドは、Slim Frameworkを使ってログイン認証を実現させています。

[:link: https://github.com/isamusuzuki/vue-slim-auth](https://github.com/isamusuzuki/vue-slim-auth)

![vue-slim-auth-demo.gif](https://qiita-image-store.s3.amazonaws.com/0/48056/c3f8344e-f6cf-ecd9-1304-6b359af46961.gif)

## 何を作ったのか？

- `Top`ページは、誰でも見ることができます。
- `Login`ページでは、`user / user@123`でログインできます。
- `Secret`ページは、ログイン後でないと見られません。
- `Secret`ページでは、認証トークンをつけてAPIを叩いています。
- ログインしていない状態で`Secret`ページに行くと、`Login`ページに遷移します。
- 遷移された状態でログインに成功すると、元のページに戻ります。

## クライアントサイドの特長

- JavaScriptコードは、Webpackなどでコンパイルしていません。
- scriptタブに`type=module`を指定し、importコマンドを使って別ファイルを読み込んでいます。（よって、IEでは動作しません）
- Bulma, FontAwesome, Vue.js, axios, Vue-Router, Vuexを組み込んでいますが、コンパイルしていないので、すべてCDNを使っています。

## サーバーサイドの特長

- サーバーは、静的ファイルを吐き出すか、APIとして働くかの二通りのみで、テンプレートは使っていません。
- `/auth`APIは、ログイン認証に成功すると、JWT(JSON Web Token)を返します。
- `/auth`以外のAPIは、Authorizationヘッダーにトークンを入れないとエラーを返します。

## なぜ作ったのか？

インストール方法・ファイルディレクトリ構成については、GitHubの[README](https://github.com/isamusuzuki/vue-slim-auth)をご覧いただくとして、ここでは、なぜこのような構成になったのか、経緯と意図を説明してみたいと思います。

### なぜPHPなのか？

職場の上司から「LAMPを使え」と言われたからです。PythonもNode.jsも担当者が辞めたとたんにブラックボックスになるからという理由でNGでした。

### なぜローカル開発環境がXAMPPなのか？

職場のPCにはウイルスバスターコーポレートエディションがインストールされており、Hyper-VもVirtualBoxも動かすことができなかったからです。したがってDockerを選択肢に入れることができませんでした。

### なぜSlim Frameworkなのか？

LaravelとSlim Frameworkでどちらにするか迷いましたが、C言語しか経験がない同僚にも使ってもらうためには、なるたけ簡易なものがいいと考え、独断でSlim Frameworkを採用しました。

### どうやってログイン認証を実現しているのか？

ここで強調しておきたいことは、「Slim Frameworkでもログイン認証はできる」ということです。[tuupola/slim-jwt-auth](https://github.com/tuupola/slim-jwt-auth)というミドルウェアを1個追加するだけです。

このミドルウェアのREADMEには「俺は認証トークン生成／判定／保管はしないぜ」と書いてあったのですが、実は問題ありません。そのことを詳しく説明した記事（英語）はこれです。

[:link: Slim3 Framework Authorization with JWT \(JSON Web Tokens\)](https://arjunphp.com/secure-web-services-using-jwt-slim3-framework/)

### なぜSPA（シングルページアプリケーション）なのか？

ログインに成功すると有効期限付きのトークンが返ってきますが、これはセッション／クッキー／ローカルストレージのどこにも保存していません。JavaScriptが変数として保持しているだけです。でもSPAなので、ログイン後のページをユーザーに見せることができます。

したがって、F5キーを押してリロードするとログイン前の状態に戻ってしまいますが、とりあえず簡単に確実なセキュリティを実現しているのはSPAだからなのです。

### なぜVue.jsなのか？

私が勉強した中で一番グッときたJSフレームワークだったからです。

### なぜCDNなのか？ なぜコンパイルしないのか？

C言語しか経験がない同僚も短期間で戦力にするには、とにかく敷居を下げることが大事だったからです。今回の経験で、読みやすいサンプルコードと簡単に作れるローカル開発環境があれば、どのレベルの開発者でも巻き込めると確信を得るに至りました。

### どうしてVue-RouterとVuexを使っているのか？

これがないとSPAを実現できませんので。必要に迫られると理解も進みます。

前に自分が書いた投稿が、いい意味でブーメランのように自分に返ってくるとは、お釈迦様でも驚くことでしょう。

[:link: Nuxt.jsにBulmaを組み込んだら、Vuexストアが理解できた件](https://qiita.com/isamusuzuki/items/5ec800e423a3a56ef03d)

### どうしてBulmaなのか？

CSSファイルオンリーのCSSフレームワークだからです。

### どうしてFont Awesomeなのか？

Bulmaと相性がいいからです。

## 最後に

ソースコードはGitHubに載せています。C言語しか経験がない同僚が完全に理解しているのかどうかは怪しいのですが、これを元にWebアプリを開発していますので、ニーズに合う方は、是非ソースコードを見てみてください。

[:link: https://github.com/isamusuzuki/vue-slim-auth](https://github.com/isamusuzuki/vue-slim-auth)
pyaudioをインストールしようとしたら詰まった話

# Pyaudioの時の備忘録

Pyaudioをインストールしようとしたら


```ターミナル
$ pip install pyaudio
---略---
xcrun: error: active developer path ("/Applications/Xcode.app/Contents/Developer") does not exist
    Use `sudo xcode-select --switch path/to/Xcode.app` to specify the Xcode that you wish to use for command line developer tools, or use `xcode-select --install` to install the standalone command line developer tools.
    See `man xcode-select` for more details.
    error: command 'clang' failed with exit status 1
```

という風に怒らました。

おそらくXcodeを消したのが原因かと。

そこでググって、

```ターミナル
$ xcode-select --install
$ sudo xcode-select -switch /Library/Developer/CommandLineTools
```

これで解決！

無事にpyaudioをインストールすることができました。
人生初めてのプログラミング　Java 第1回　Hello World

#なぜ？Javaなの？
- androidのアプリ作りたい思ったから。。。。。と安易な考え<br>
でもC言語は難しそうと勝手な偏見とイメージで思ったから
<br>実行環境は、webでも実行できるので簡単なプログラムはそちらで試したほうが<br>楽だとおもいます。

##paiza.io

https://paiza.io/ja/projects/new

##はじめてみた
まず始めのプログラムと言ったら<strong>Hello World</strong>さん！！
<h6>大変みずらいコード内容となっています</h6> すみません！

``` Test.java
 
public class Test {
    public static void main ( String[] args ) {
        System.out.println("Hello world");
    }
}
```
実行！！
結果　→　Hello World
 
###配列を生成してみよう！！
配列とは？？
>変数は「プログラミング言語における『値を入れておく箱』」です。
処理の途中で値を入れたり、逆に取り出したりできます。
数学で出てくる変数（xとかyとか）と考え方は一緒です。
以上を踏まえて「複数の変数をくっつけたもの」が「配列（ハイレツ）」です。
参考URL
>>https://wa3.i-3-i.info/word11924.html

配列の定型文

<strong>配列名　＝　new 型[個数]</strong>

```Main.java
 
public class Main{
    public static void main (String[] args){

        int [] retu; //配列を宣言(配列をこれから始めますよお知らせ)

        retu = new int [3];//生成(どのくらいの長さの箱なの？？をお知らせ)

        retu[0] = 1; //１をretuの0番目に代入する
        retu[1] = 2; //2をretuの1番目に代入
        retu[2] = 10; //10をretuの２番目に代入

        System.out.println(retu[0]);
        System.out.println(retu[0] + retu[2]);

    }
}
```
とこんな感じ

<h6>配列は0番目から始まります。なので１番目からは始まりません</h6>
配列の中身を取り出すときは、配列の名前指定をしてあげて、その配列の要素を指定してあげる

でもこの書き方でもいいと思う...........

```Main1.java

   public class Main1{ //配列の書き方　出力の仕方
    public static void main(String[] args){
        int a[] = {1,2,3};
        System.out.println(a[1]);
    }
}
 
```
##終わり
Java初心者が忘れないように書いてる記事なのでこれが正しいということは、
絶対にないと思います。
書き方、非推奨、文法などが間違っている場合もありますので、あくまで参考程度で！！
各バージョンのMSBuildのパスを解決するPower Shellスクリプト


# TL;DR

- 複数のバージョンのVisual Studioをインストールしている環境下において、使用したいバージョンのコマンドラインビルドに使用するMSBuild.exeを探すスクリプトを作成した

※ 本記事は、2019/01/25に[弊社スタッフブログ](https://www.northtorch.co.jp/archives/465)に投稿した記事をQiitaに転載しています。

（2019.01.26追記）
[nukie_53](https://qiita.com/nukie_53)さんから編集リクエストいただき、PowerShellスクリプトにシンタックスハイライトが適用されるように修正しました！

（2019.03.10追記）
下記バージョンのMSBuild.exeのパスを追加
- Visual Studio 2013
- Visual Studio 2017 Professional

# 参照URL

- [Powershellを楽に実行してもらうには](https://qiita.com/tomoko523/items/df8e384d32a377381ef9)

# 概要

かなりニッチな状況ですが、
- Visual Studioで作成したツール類をコマンドラインからビルドしたい
- Visual Studioのバージョンは特に指定しないけど、特定バージョン以降じゃないとビルドが通らない
- ビルドする環境が32bit/64bit混在
という状況になった際に、Power Shellスクリプトで解決したので、まとめておきます。

# 解説

## スクリプト

スクリプトは、下記よりダウンロードできます。

[https://github.com/rot-z/MSBuildSearch](https://github.com/rot-z/MSBuildSearch)

## スクリプト起動用のバッチ

Power Shellはデフォルト設定だと実行が禁止されていますので、権限指定してバッチファイルから指定します。

```cmd
@echo off

cd /d %~dp0

powershell -NoProfile -ExecutionPolicy Unrestricted .\MSBuilsSearch_impl.ps1

pause
```

## MSBuild.exeを探すPower Shellスクリプト

単純に、あらかじめリストで持っておいた"Program Files"フォルダ配下のパスにMSBuild.exeを探しています。  
"Program Files"フォルダはOSのアーキテクチャによって"Program Files"(32bit), "Program Files (x86)"(64bit)と名前が異なりますので、そのあたりは勝手に解決しています。


```powershell
# =============================================================================
#     search MSBuild.exe 
# =============================================================================

# folder paths of Visual Studio
$MSBUILD_12_PATH = "MSBuild`\12.0`\Bin"                                                             # Visual Studio 2013
$MSBUILD_14_PATH = "MSBuild`\14.0`\Bin"                                                             # Visual Studio 2015
$MSBUILD_15_COMMUNITY_PATH = "Microsoft Visual Studio`\2017`\Community`\MSBuild`\15.0`\Bin"         # Visual Studio 2017 Community
$MSBUILD_15_PROFESSIONAL_PATH = "Microsoft Visual Studio`\2017`\Professional`\MSBuild`\15.0`\Bin"   # Visual Studio 2017 Professional

# target paths for MSBuild
# sort by priority
[array]$SEARCH_PATHS = @(
        $MSBUILD_14_PATH, 
        $MSBUILD_15_COMMUNITY_PATH,
        $MSBUILD_15_PROFESSIONAL_PATH,
        $MSBUILD_12_PATH
    )

# get full path of "Program Files" folder from OS archtechture
$arch = (Get-WmiObject win32_operatingsystem | Select-Object osarchitecture)
$archName = $arch.osarchitecture
$programFilesDir = ""
if ($archName.StartsWith("64"))
{
    $programFilesDir = ${env:ProgramFiles(x86)}
}
else
{
    $programFilesDir = ${env:ProgramFiles}
}

# search MSBuild.exe
$msbuildPath = ""
foreach($p in $SEARCH_PATHS)
{
    # is folder exists?
    $targetPath = Join-Path $programFilesDir $p
    if (!(Test-Path $targetPath)) 
    {
        continue
    }

    # select the most shortest (shallowest) path
    $results = (Get-ChildItem $targetPath -Include MSBuild.exe -Recurse).FullName | Sort-Object -Property Length
    if ($results.Length -gt 0)
    {
        $msbuildPath = $results[0]
        Write-host $msbuildPath
    }
}
```

無償版のパスしか埋めてないのは、手元の環境で調査したからです。  
適宜自分の環境に合わせてパスの追加を行ってください。
(小ネタ)ROCｍ環境でRStudio/Kerasを利用する

以前、このような事がありました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">こうなった（未経験のR触り始めた）経緯:<br>（某フォーラムにて）<br>「AMDはクソ！TF移植したと言ってもkerasみたいな高級インターフェース無いじゃん！」<br>私「ご冗談を。kerasなんてただのラッパーなんだからTF動けば動くでしょ？」<br>「んなわけない、kerasOnRにドキュメントが無いじゃん！」<br>私（Rか…）</p>&mdash; こぎつねまる@C95の次は…？ (@kz_lil_fox) <a href="https://twitter.com/kz_lil_fox/status/1067673794347642880?ref_src=twsrc%5Etfw">2018年11月28日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

現在、RStudioのページにはGPUを利用する項目としてはNvidia環境のものしか記述されていないため、AMD環境で利用できないと思うのは当然だと思います。
とは言え、Python環境でのTensorFlow(Keras)をラッピングして利用するRStudio/tensorflowでROCm版Tensorflowが利用できないとはとても思えないため、ちょっと調査しました。

# TL,DR;

RStudioで利用するKerasはシステムのPythonを利用してTensorflowをインストールする仮想環境を作成し、その上にKerasをラッピングしているため、Rstudio/Tensorflowにてコンパイル済みWheelをインストールすればAMDGPU環境でもKerasをGPUから利用することが出来ます。

## Rstudio環境にTensorflowをインストールする

RStudioでTensorFlowをインストール場合、Tensorflowライブラリーの関数install_tensorflow()を利用します。
通常は関数内の引数から数値をパースしてインストールするパッケージを決定していますが、コンパイル済みWheelパッケージを
引数に与える事もできます

```Rstudio

library(tensorflow)
install_tensorflow(version = "https://files.pythonhosted.org/packages/27/5a/bb674108c94a2e5ac2ad0c2aa6cbec6de9ae248c3d1858424b3eea38eddf/tensorflow_rocm-1.12.0-cp27-cp27mu-manylinux1_x86_64.whl")

```

その後、Kerasを実行するとAMD環境にて、RStudio/Kerasを利用することが出来ます。

## はまりどころ、その他注意点

RStudioが利用するPython仮想マシンは、引数を与えない限りシステム環境のPythonを(RStudio向けの仮想環境を作ったうえで)利用します。
システムのPythonバージョンに気を付けてWheelを選択してください。

また、今回はインストールまでで動作の検証は不十分である点、ご理解ください。

## ハックしてみた

なお、install_tensorflow()関数をハックすることでWheelを直接渡さずともインストールする改造をされた方もおりました。


<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">とりあえず、こんな感じで実装しました。インストールできること以外何も確認していませんがvenvとcondaどちらでもインストールできると思います。<a href="https://t.co/MrMMCGno6v">https://t.co/MrMMCGno6v</a></p>&mdash; StarCraft (@Star_Craft) <a href="https://twitter.com/Star_Craft/status/1068462077080068096?ref_src=twsrc%5Etfw">2018年11月30日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


### 続きは…？

以下Rで何かやってみようかと思います
deviseのメッセージにtoastrを反映させる

# toastrを導入
####①まずはGemfileに記述する。
(deviseは導入済みと仮定します)

```Gemfile.
gem 'toastr-rails'
```
`bundle install`

####②toastrをapplication.cssとapplication.jsに追加する。

```application.css
*= require toastr
```
scssの場合は

```application.scss
@import "toastr";
```
jsファイルにも

```application.js
//= require toastr
```

####③jQueryのCDNをapplication.html.erbに記述する

```application.html.erb
<head>
<!-- 省略 -->
<script src="https://code.jquery.com/jquery-3.3.1.js"
  integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
  crossorigin="anonymous"></script>
<!-- 省略 -->
</head>
```

hamlの場合は

```application.html.haml
%head
/省略
  %script{:crossorigin => "anonymous", :integrity => "sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=", :src => "https://code.jquery.com/jquery-3.3.1.js"}
/省略
```
#deivseの各ビューに記述する

app/views/devise/〇〇.html.erbの
<%= devise_error_messages! %>を全て下記の記述に変える。
この際、部分テンプレートの方が良いので部分テンプレートを作成する。
ファイル名はお任せします。

```_messages.html.erb
<% unless resource.errors.empty? %>
  <script type= "text/javascript">
    <% resource.errors.full_messages.each do |msg| %>
      toastr.error('<%= msg %>');
    <% end %>
  </script>
<% end %>
```

部分テンプレートを作成したら、app/views/devise/〇〇.html.erbの
<%= devise_error_messages! %>を<%= render "部分テンプレートのファイル名" %>に編集する

# 日本語化したい場合

こちらの記事を参考にすると簡単に日本語化が可能かと思います。
https://qiita.com/shizuma/items/a52fd0ef5b60d61fa330
Python パッケージの作り方メモ



# 概要

はじめての Python です。
社内向けにちょっとしたコマンドラインツールを作ったので、流れをまとめておきます。
だいたい良くある面倒なネタにはツールが用意されていて、さっと開発に入れる気がしました。

# テンプレートから作成

[Cookiecutter](https://github.com/audreyr/cookiecutter) はテンプレートからプロジェクトを作成してくれるツールです。

```
$ sudo pip install cookiecutter
```

sudo が必要かどうかは、pythonのインストールパスによる模様です。
テンプレートは、pypackage というのを使いました。

```
$ cookiecutter https://github.com/audreyr/cookiecutter-pypackage
```

作者やパッケージの名前などいろいろ質問されるので、答えていきます。

質問に答え終わると「project_slug:」で入力した名前でプロジェクトディレクトリが作成されます。
大事なところはこんな感じでしょうか。

```
my_tool
├── docs     # ドキュメント
├── my_tool  # ソースコード
├── tests    # テストコード
├─ README.rst  # 他にもrstがたくさん
└─ setup.py    # インストールスクリプト
```

ここでプロジェクトディレクトリに移動して、git init しておくのが良いでしょう。


# 実装

## CLI

コマンドを作るときは、前記のテンプレート作成時に「Select command_line_interface:」で「1 Click」を選びます。

[Click](https://click.palletsprojects.com/en/7.x/
) はコマンドライン・インターフェースを作成するためのパッケージです。
コマンドライン引数やオプションのパースはもちろん、グループ化とかサブコマンドとか、テストのお世話までしてくれます。

テンプレ作成時に CLIを選んでいれば、/my_tool/cli.py が出来ているので、コマンドラインの制御はここに実装します。



## モジュール

/my_tool/my_tool.py をメインモジュールとして実装していきます。
もちろん役割ごとにファイル（モジュール）を分けた方が良いでしょう。

別モジュール（別ファイル）の関数を参照したいときは、import を書きます。

たとえば、my_tool.py で hoge.py に書いた関数を使いたいときは、こんな感じです。

```hoge.py
def koge()
  pass
```

```my_tool.py
import my_tool.hoge as hoge

def main()
  hoge.koge()
```

## 外部パッケージの読み込み

依存するパッケージは setup.py に書いておきます。

```setup.py
requirements = ['Click>=6.0', 'pandas', ]
```

[Pandas](https://pandas.pydata.org/) を追記した例です。
Click は作成時に書かれているので、その後ろに追加するだけです。
依存パッケージを開発環境に適用するには、setup.py を実行します。

```
$ python setup.py install
```


## クラスとか

オライリー本を読んだ限りだと、Python はクラスを作るのには消極的な文化のようです。
組み込みのデータ型（リスト、タプル、辞書、集合などなど）がかなり便利なので、確かにあんまり必要ないかも。


## テスト

前記のテンプレート作成時に「use_pytest:」で「y」を選べば、テストコードのテンプレートも出来ます。

Click を利用したCLIのテスト例がお役立ちです。

# ドキュメント

rst(reStructuredText) という形式で書きます。

[Sphinx](http://www.sphinx-doc.org/ja/stable/) でhtml化出来ます。

```
$ pip install sphinx
```

Anaconda で python を入れた場合は、Sphinxはすでに入っていたようでした。



# デプロイ

pip でインストールできます。
リポジトリからインストールするならこんな感じ。

```
$ pip install git+https://git.repos/my_tool
```

git+ の後ろにリポジトリのパスを書きます。
このコマンドだと、masterブランチの最新がインストールされますが、ブランチなどなどいろいろ指定もできるようです。


パッケージを圧縮ファイルにまとめて持っていく方法もあります。
まず、ソースからパッケージファイルを作成します。

```
$ python setup.py sdist
```

実行すると、dist/ 配下に my_tool-X.X.X.tar.gz が作成されます。
my_tool-X.X.X.tar.gz をインストール先に配置し、pip コマンドでインストールします。

```
$ pip install my_tool-X.X.X.tar.gz
```

# パッケージのバージョンを上げる

bumpversion というツールでバージョン番号の管理をします。

```
$ sudo pip install bumpversion
```

```
$ bumversion patch # major / minor / patch のどれかを指定する 
```

実行すると以下をまとめてやってくれます。

* ソースコード内のバージョン番号を書き換える
* git commit する
* コミットにバージョンのタグを設定する
curlでContent-Encoding HTTP圧縮転送 リクエスト レスポンス

この記事の内容は
curl 7.52.1
gzip 1.6
GNU bash, version 4.4.12(1)-release
で動作することを確認しました。

curlコマンドオプションの説明
[curl - How To Use](https://curl.haxx.se/docs/manpage.html)

## レスポンス
```
curl --compressed url
```
- curlはwebサーバーへ`Accept-Encoding`ヘッダーを設定してリクエストを送る
 - `Accept-Encoding`ヘッダーには、curlが対応する圧縮方式のリスト(gzip, deflate,...など)が書かれている
- サーバーは対応していれば、コンテンツ(レスポンスボディ)を圧縮して応答を返す
 - サーバーはレスポンスに`Content-Encoding`ヘッダーを含める
 - `Content-Encoding`には使用された圧縮形式が書かれる
- curlは圧縮されたコンテンツを解凍して出力する

#### サーバーから送信されたgzipを解凍せずそのまま欲しい
```
curl --compressed --raw url
```
圧縮されたままのレスポンスデータが欲しい場合は、rawオプションを追加すればcurlは自動で解凍しない。
  

## リクエスト
```
gzip -c src | curl -X POST --data-binary @- -H "Content-Encoding: gzip" url
```

POSTするデータが大きすぎる場合は、Argument list too longエラーになる場合がある。そのときは標準入力から渡す。
`--data-binary @-`
https://qiita.com/aosho235/items/d89bb027db0c5662d8c5
`@`ファイルから渡す
`-`標準入力
Install Mattermost 5.7.0 on CentOS 7

![Mattermost](http://www.mattermost.org/wp-content/uploads/2016/03/logoVertical_WS.png)

# 2020/10/23 追記

記事内容は、[Zenn.dev](https://zenn.dev/ymasaoka/articles/install-mattermost-570-centos-7) へ移すことにしました。
~~当面の間、内容はこちらにも記載しておきますが、そのうち削除するつもりです。~~

Qiita での記事内容は削除しました。
Zenn.dev 側で掲載していた内容と同じものを公開しているので、そちらをご確認ください。

- [Install Mattermost 5.7.0 on CentOS 7](https://zenn.dev/ymasaoka/articles/install-mattermost-570-centos-7)
Install MySQL 8.0 on CentOS 7

![MySQL](https://www.mysql.com/common/logos/logo-mysql-170x115.png)

# 2020/10/23 追記

記事内容は、[Zenn.dev](https://zenn.dev/ymasaoka/articles/install-mysql-8-centos-7) へ移すことにしました。
~~当面の間、内容はこちらにも記載しておきますが、そのうち削除するつもりです。~~

Qiita での記事内容は削除しました。
Zenn.dev 側で掲載していた内容と同じものを公開しているので、そちらをご確認ください。

- [Install MySQL 8.0 on CentOS 7](https://zenn.dev/ymasaoka/articles/install-mysql-8-centos-7)
Docker超入門という動画を作りました。

Docker使ってますか？

私はバリバリ使っているんですが、
そこらの本を見ると、**本番環境を見据えて使いなさい！** とか
書いててそんなに敷居あげなくてもいいのになぁ・・・
と側からみてたわけです。


正直本番運用でDockerを使うノウハウは私にはほとんどありません。
Dockerの恩恵は普通に開発環境として使うだけでも十分あると思います。


Vagrantを使った経験のある方の方がまだ多いんですかね？
私はVagrantからDockerに鞍替えした人間でして、
ほぼVagrantの代わりとして使ってしまっています。

ただ、Vagrant単体ではできなかった、もろもろの初期設定などは
Dockerfileに書いておくだけ（それも慣れてる普通のコマンドで）で
まるっと一括でやってくれますし、
Dockerの特性みたいなのがある程度わかれば、
起動が遅いVagrantより全然Dockerの方がいいやーん
ChefとかAnsibleも忘却の彼方にとんでけーとなるわけです。


と、前置きが長くなりましたが、
Docker超入門と題して、Youtubeに動画を公開しています。
全4回で、Dockerを **開発環境** で使うには？
というのを前提に超割り切って不要な知識一切抜きにRails+mysqlの環境を作る
ってのを動画内で実演しています。

[![Docker超入門 プレイリスト](http://img.youtube.com/vi/7mwoTs0LoYA/0.jpg)](https://www.youtube.com/playlist?list=PLp_EUEO9JJP24hkHvRbS9hTLsjSMzbJrM)

チュートリアルでただコマンドが羅列されるのを実行してみるよりは、
動画で細かい説明されつつ、一緒に進めていけるので圧倒的にわかりやすいです！

ご覧いただければと。
その他の構成装置 応用情報技術者試験 対策日記@9

# バス
バスとは、コンピュータ内部でデータをやりとりする為の伝送路のこと。
1ビットずつ順番にデータを転送するものを**シリアルバス**、複数ビットを一度に複数本の伝送路で送るものを**パラレルバス**という。

**USB**や**Bluetooth**の他に、IEEE1394やATA、シリアルATAなどの規格がある。
USB2.0はハイスピードモードで480Mps、USB3.0はスーパースピードモードで5Gps。

#出入力デバイス
## 1.制御方式
出入力制御は通常CPUを通して行われるが、効率を良くするためにCPUを通さない制御方式も存在する。
**DMA(Direct Memory Access)方式は**CPUの指示のもとでCPUを通さずにメモリと出入力装置間のデータ転送を行う。一方、**チャネル制御方式**は専用ハードウェアのチャネル装置がCPUを通さずに独自にデータ転送を行う。

##2.ディスプレイ
CRTディスプレイ　ブラウン管を利用したディスプレイ
STN液晶ディスプレイ 単純マトリクス方式を採用
**TFT液晶ディスプレイ** 高輝度が特徴
**有機ELディスプレイ** 低電力が特徴
**プラズマディスプレイ** 大型化が可能

------
[ホームへ](https://qiita.com/k-y/items/dc2c9a3a8425712253e8)
【ActiveModelのクラスを読み込めない】 uninitialized constant Tweet::ActiveModel (NameError)

はじめてActiveModelを使おうと思って、とりあえずモデルファイルを作成。
(putsは読み込めているか確かめようと思い書いてみた）

```ruby
class Tweet
  include ActiveModel::Model
  puts "hello"
end
```
#エラー
コマンドプロントで読み込んでみるも失敗。読み込めていなかった

```ruby
Traceback (most recent call last):
        1: from tweet.rb:1:in `<main>'
tweet.rb:2:in `<class:Tweet>': uninitialized constant Tweet::ActiveModel (NameError)
```

#対策

[このサイト](https://github.com/rails/rails/issues/5768)の通りに`reauire 'active_model'`と追加してみた。

> You have to require the whole of active_model since it uses autoload to "lazily require" classes as needed.
The following code works fine:

```ruby
require 'active_model'


class Person
  include ActiveModel::Validations
end
```

#結果

```
$ ruby tweet.rb
=> hello
```

成功かな
GoogleBigQueryでFQ別のDAUを集計する

### 目的
 - プロダクト分析（特にゲーム業界が多い？）で用いられるFQ（Frequency）のQueryサンプルを書きます
 - ユーザーの定着状況を図る指標の1つです

### FQを取得するメリット
 - KPIには、`良質なKPIだけでなくノイズの多いKPI`などもあり、`大きな粒度の数値だけでは判断を誤る`ことが多々あります
 - 特にDAUの数値はpush通知を送りまくる、SNSでバズってたなどで変動することが多い数値です
 - プロダクトとしては定着するユーザーを増やすことが重要施策の1つであるはずなので、`定着ユーザーを定量的に把握するための1つの手段としてFQ`を用いることができます

### 注意事項 
 - プロダクトやサービスによっては1週間で見ない場合もありますし、毎日使ってもらう必要がないものもあるのですべてのプロダクトで必要な概念ではないです
 - 連続を問う問わないなどのように定義が異なる場合があるので気をつけてください
 - `概念がややこしい` です

### FQの概念
 - DAUをFQで分解する考え方です
 - 当日を含む過去7日間のうちに何日間アクセスしていたかを集計する指標でユーザーの利用頻度（≒定着状況）を把握するのに用います
    - 今回は連続性は考慮しない定義としています

![image.png](https://qiita-image-store.s3.amazonaws.com/0/45434/298a2da7-23fb-30d8-8041-c1a3b71a0d70.png)

### アウトプットのイメージ
 - グラフにするときはFQの高い（定着している）数値を下にすることで、施策をすることでユーザーが積み上がっていっていることがわかるようにします
 - バズったりしてユーザーが増えるときを考慮し、場合によってはFQ1,2は見ないなどの判断もあります

![image.png](https://qiita-image-store.s3.amazonaws.com/0/45434/36fb0d3c-8881-ba70-c6b1-fbd55b8f4cd3.png)

### データソース
こんな感じのログイン日とuser_idが入ってるdaily_active_usersのtableから集計します

| dt | user_id |
|:--|--:|
| 2019-01-01 | 100 |
| 2019-01-01 | 101 |
| 2019-01-02 | 101 |
| 2019-01-02 | 103 |
| 2019-01-03 | 100 |


### Query
#### 考え方
 - user_idに対して、当日を含む過去7日間で何回ログインしているか（FQ）のflgを付与し、そのFQのflg別のuser数を集計します
 - そのために、同じテーブルをjoinし、基準日（DAUのDに当たる日）に対して、過去7日間のうちに何日間該当ユーザーがいたかを判断しています


```SQL
COUNT(distinct(CASE WHEN t1.dt BETWEEN t2.dt AND t2.dt + integer '6' AND t1.user_id = t2.user_id THEN t2.dt ELSE NULL END)) AS FQ
```


```SQL
SELECT
    dt,
    concat('FQ',FQ) AS FQ,
    COUNT(distinct user_id) AS uu
FROM
    (
    SELECT
        t1.dt,
        t1.user_id,
        COUNT(distinct(CASE WHEN t2.dt BETWEEN DATE_SUB(t1.dt,INTERVAL 6 DAY) AND t1.dt AND t1.user_id = t2.user_id THEN t2.dt ELSE NULL END)) AS FQ /*FQを計算*/
    FROM
        (
        SELECT
            dt,
            user_id
        FROM daily_active_users
        )t1
        LEFT OUTER JOIN
        (
        SELECT
            dt
            ,user_id
        FROM daily_active_users
        )t2
        on t1.user_id = t2.user_id
    GROUP BY
        t1.dt
        ,t1.user_id
    )t
GROUP BY
    dt
    ,concat('FQ',FQ)
```

### さいごに
今後もこういったPM向けの分析の記事をちょこちょこ書くので、よかったらQiitaとかTwitterとかフォローしてもらえると嬉しいです！
ツイッターアカウント：https://twitter.com/ysk_ur

こういうのもありかもしれないです。型と日付にはまる、、、

```SQL
COUNT(distinct(CASE WHEN t1.dt BETWEEN DATE_SUB(t2.dt,INTERVAL 6 DAY) AND t2.dt AND t1.user_id = t2.user_id THEN t2.dt ELSE NULL END)) AS FQ /*FQを計算*/
Nuxt.jsの概要


Nuxt.jsについて概要を調査しました。

## その前に、SSRとは？
サーバー側でJavaScriptを使って、HTMLを生成する。
そのため、CSRと比べて、ユーザー側でHTMLを生成する待ち時間がなくなる。

またSEOの観点から、SPAの場合、
JSで動的に変えた箇所をGoogleのクローラーが正しく評価できない。
SSRでは、クローラーが解釈する前に生成しているので、その問題を解決できる。

デメリット：開発コストが高い、CPU処理能力が必要

## Nuxt.jsとは？

Vue.js
VueRouter
Vuex
VueServerRenderer
VueMeta
を一つのパッケージとして提供しているフレームワーク。

これによって、
通常webpackなどの細かい設定が必要な開発環境の構築を簡略化できたり、
直感的なディレクトリ構成、
SPA・SSR・静的化をサポートしている。

また、クライアントサイドとサーバーサイド間の開発を手助けするたくさんの機能を備えている。
例えば、
非同期でのデータのやり取りや、
ミドルウェアとしての利用、
レイアウト機能
などがある。

# Nuxtのビルドの選択肢は３つある。
SPA・SSR・静的化の中から、好きなものを選んで開発できる。

- SSR モード（初期設定済み、nuxt startでSSRできる）
メリットは上記に記載

- SPA モード（nuxt --spa）
サーバーサイドレンダリングを使いたくない、
あるいはアプリケーションを静的にホスティングする必要があるときに使用。

- 静的出力（nuxt generate 静的ファイルのホスティングに利用）
Node.jsを使用せず、静的サイトとして出力できる。
更新のたびに再生成が必要。
※生成時にはサーバーサイドでレンダリングすることになるので、SSRを考慮した実装が必要

## Nuxt.jsの基本ルール
### ディレクトリ構成
参考：https://luftgarden.work/tut-nuxt-dog-part1/

### ルーティングの仕組み
→　pagesディレクトリの構成によってvue routerを自動生成することで実現
https://ja.nuxtjs.org/guide/routing/

### Nuxt.jsでの非同期の仕組み
Vue.jsライフサイクルに入る前に、事前処理を**ページ単位**で行うことができます。

#### ページ単位（pageコンポーネント）で使用できるキー
- headメソッド
 - HTML の head タグを設定
- asyncDataメソッド　
 - https://ja.nuxtjs.org/guide/async-data/
 - コンポーネントにデータをセットする前に、非同期処理を行う
- fetchメソッド　
 - https://ja.nuxtjs.org/api/pages-fetch/
 - ページがレンダリングされる前に、データをストアに入れるために使われます。

asyncData？　fetch？

#### asyncDataとfetchの違い
- asyncDataは、取得したデータをページコンポーネント内で使用する場合に使うメソッド。
- fetchは取得したデータをvuexストアに入れる場合に使うメソッド。

具体的には、ページ読み込み時にstoreのdispatchを呼び出して、
vuexにデータをセットする場合にはfetchメソッドを使うべきだということです。

それに対して、ページ読み込み時に取得したデータを、
そのままそのページのプロパティとして使うような場合はasyncDataを使うべきです。

```Pageコンポーネント　例）pages/pref.vue

<template>
    <section class="container">
        <h2>都道府県</h2>
        <div class=“red”>{{ pref }}</div>
    </section>
</template>

<script>
import axios from 'axios'

export default {
    // asyncDataメソッド
    asyncData ({ query }) {
        // コンポーネントをロードする前に毎回呼び出されます
        return axios.get(`http://vue.localhost/pref.php?id=${query.id}`)
        .then((res) => {
            return { 
                pref: res.data.prefecture 
            }
        })
    },
    // fetchメソッド
    fetch () {
        // `fetch` メソッドはページの描画前にストアを満たすために使用されます
    },
    // headメソッド
    head () {
        return {
            title: 'Hello World!',
            meta: [
                { hid: 'description', name: 'description', content: 'My custom description' }
            ]
        }    // このページ向けにメタタグを設定します
        // 共通設定はnuxt.configに記載
    },
}
</script>
<style scoped>
.red {
	color: red;
}
</style>
```

## 参考記事
Nuxt概要
https://techblog.scouter.co.jp/entry/2017/11/13/120000

SPA、SSR、静的化の比較
https://qiita.com/noplan1989/items/f42e2f03663b00b5886d

asyncData、fetchについて
https://ja.nuxtjs.org/guide/views
https://webxreal.com/js_nuxt-axios-asyncdata/
https://zen-web.net/blog/nuxtjs-asyncdata-fetch/

Vue.jsを使ったSSR比較　プリレンダリング含む　
https://qiita.com/r548/items/cc3600287f635ecdf9f8


## その他調査したいこと
・render使い方
・PC、スマホ判別方法
・適したバージョン
nodeバージョン
npmバージョン
vueバージョン
・ミドルウェア周り
・GA設定
・Nuxtに適したネットワーク構成
・インストール時のフレームワーク比較
・開発、本番環境の切り替え方法
select2を使って使えるsuggestの作成

#はじめに
[Select2](https://select2.org/)は簡単に suggest を実現してくれるライブラリなんですが、どうせならもっと便利にしたいなと。
macherをカスタマイズして半角全角、大文字小文字、ひらがなカタカナの差分をカバーして検索できるようにします。

#利用するライブラリ
以下のライブラリを読み込んで下さい。
- JQuery v3.3.1
- Bootstrap v4.2.1
- Select2 v4.0.6-rc.0
- [Select2日本語ライブラリ](https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/i18n/ja.js)
- [Moji.js](https://github.com/niwaringo/moji)

#サンプル
サンプルでは「フリガナ」データを`<option>`タグの`data-search`アトリビュートに記述し、`ＪＱuery`の`data('search')`メソッドでアクセスしています。多くの場合、大量の選択データはデータベースから出力されることが多いので、フリガナデータなども存在することと思います。
`Ｍｏｊｉ．ｊｓ`ライブラリにて、大文字変換→全角カタカナ変換を行うことで、マッチング率を上げています。
サンプルでは比較時に`data-search`の値を変換していますが、効率の面から鑑みて記述時の時点であらかじめ変換しておくのが良いと思います。

```html
<!DOCTYPE html>
<html lang="Ja">
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.css" />
  </head>
  <body class="p-3">
    <div class="form-group">
      <select class="form-control w-25" id="testSelect">
        <option data-search="リンゴ">林檎</option>
        <option data-search="ミカン">蜜柑</option>
        <option data-search="スイカ">西瓜</option>
      </select>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/i18n/ja.js"></script>
    <script src="https://github.com/niwaringo/moji/releases/download/V1.2.0/moji.js"></script>
    <script>
$(function(){
 function customMatcher(params,data){
   if ($.trim(params.term) === '') {
     return data;
   }

   if (typeof data.text === 'undefined') {
     return null;
   }
   /*
   ZEtoHE 英数字を半角に
   HKtoZK 半角カタカナを全角カタカナに
   HGtoKK ひらがなをカタカナに
   */
   let term = moji(params.term.toUpperCase())
     .convert("ZEtoHE").convert('HKtoZK').convert('HGtoKK').toString();

   let text = moji(data.text.toUpperCase())
     .convert("ZEtoHE").convert('HKtoZK').convert('HGtoKK').toString();

   if (text.indexOf(term) > -1) {
     return data;
   }

   let searchText = $(data.element).data('search');
   if(searchText){
     //ホントはdata-searchに記載前にconvertしておく方が良い。
     searchText = moji(searchText.toUpperCase())
       .convert("ZEtoHE").convert('HKtoZK').convert('HGtoKK').toString();
     if (searchText.indexOf(term) > -1) {
       return data;
     }

   }
   return null;
 }
 $("#testSelect").select2({
   language:"ja",
   matcher:customMatcher
 });
});
    </script>
  </body>
</html>
```

#雑記
Select2はＢootstrap4での見た目が気に入らないので、以下のCSSを足して利用してます。

```css
.select2-container--default .select2-selection--single {
    height: calc(2.25rem + 2px);
    padding: .25rem 0;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
    height: calc(2.25rem + 2px);
}
```
Android dexコンパイラ と desugar

Android Studio 3.3がリリースされたのに今更感がありますが、AndroidでGradle Plugin 3.2.0からD8のDesugaringがデフォルト有効になっています。
そこで改めて、dexコンパイラのDXとD8それぞれでdesugarする場合にどのようにAPKが生成されるかを簡単にまとめました。

公式ページは以下の通りです。

- [Java 8 言語機能の使用](https://developer.android.com/studio/write/java8-support?hl=ja)
- [D8 desugaring - Android Studio release notes](https://developer.android.com/studio/releases/#d8_desugaring)

`gradle.properties`は意図的に表現しています。
実際は`Compatibility`の指定や`Gradle Plugin`のバージョンによってデフォルト値が以下のように決まっています。
  
```groovy:gradle.properties
android.enableDesugar = true        // Compatibility で Java8 を指定していればデフォルトtrue
android.enableD8 = true             // Gradle Plugin 3.1.0 以降であればデフォルトtrue
android.enableD8.desugaring = true  // Gradle Plugin 3.2.0 以降であればデフォルトtrue
```

# DXでJava7を使う場合

```groovy:app/build.gradle
android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}
```

```groovy:gradle.properties
android.enableDesugar = false
android.enableD8 = false
```

![DX & Java7.png](https://qiita-image-store.s3.amazonaws.com/0/189865/043630e2-6ae5-8d86-3a52-88532389d168.png)

# DXでJava8を使う場合

```groovy:app/build.gradle
android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
```
  
```groovy:gradle.properties
android.enableDesugar = true
android.enableD8 = false
```

![DX & Java8.png](https://qiita-image-store.s3.amazonaws.com/0/189865/411678fe-1139-7cf5-7155-3f642ed03d14.png)

# D8でJava8を使う場合（Desugaring in D8がOFF）

```groovy:app/build.gradle
android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
```

```groovy:gradle.properties
android.enableDesugar = true
android.enableD8 = true
android.enableD8.desugaring = false
```

![D8 & Java8.png](https://qiita-image-store.s3.amazonaws.com/0/189865/d702a000-6ec1-7778-b5ed-fa7c7ae10cee.png)

# D8でJava8を使う場合（Desugaring in D8がON）

```groovy:app/build.gradle
android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
```

```groovy:gradle.properties
android.enableDesugar = true
android.enableD8 = true
android.enableD8.desugaring = true
```

![Desugaring in D8 & Java8.png](https://qiita-image-store.s3.amazonaws.com/0/189865/c775d928-b532-4b55-9cd8-7ff64df218dc.png)

# まとめ

この辺は普段はあまり意識してなかったんですが、ちょっと調べる機会があったのでまとめてみました。
もしおかしなところがあれば、コメントいただけると幸いですm(_ _)m

dexコンパイラもDXからD8になって高速化し、生成されるdexファイルも軽量化されているようです。さらにDesugaring in D8により、効率的なビルドができるようになっているようです。

しかし、アプリを作っているとどんどん機能追加もされ、ファイル数も多くなりビルド時間はさらに長くなっていきがちです・・・。
こういったサポートはかなりうれしいですが、それだけでなく日々の開発でもビルド時間は意識して、自分たちで改善をしていく必要があると改めて感じます。