OmniAICreator/Qiita-1.07M huggingface dataset:
AtCoder 生活102日目

[前回](https://qiita.com/flandrescarlet237/items/377ff9ee20d4a2c60443)

#102日目
今日はc問題1問と、b問題を2問ときました

|問題|難易度|自力で解けた|かかった時間|
|:-:|:-:|:-:|---|---|
|ABC151|C|◯|28分10秒|
|CODE FESTIVAL 2016 qual B|B|◯|6分44秒|
|キーエンス プログラミング コンテスト 2019|B|◯|21分37秒|

##[ABC151_C](https://atcoder.jp/contests/abc151/tasks/abc151_c)

```c++

#include <bits/stdc++.h>
#define rep(i,n) for(int i = 0;i < (n);i++)
using namespace std;
using ll = long long;
using pii = pair<int,int>;

const int INF = 2e9;

int main(){
    int n,m;
    cin >> n >> m;
    vector<bool> as(n+1,false);
    vector<int> wa(n+1,0);
    int acn = 0;
    int wan = 0;
    rep(i,m){
        int a;
        string b;
        cin >> a >> b;
        if(as[a]) continue;
        if(b == "AC"){
            acn++;
            wan += wa[a];
            as[a] = true;
        }
        else wa[a]++;
    }
    cout << acn << " " << wan << endl;
}


```

解くのにかかった時間：28分10秒
感想：ACなっていない問題のペナもしばらくカウントしていた

##[CODE FESTIVAL 2016 qual B _B](https://atcoder.jp/contests/code-festival-2016-qualb/tasks/codefestival_2016_qualB_b)

```c++

#include <bits/stdc++.h>
#define rep(i,n) for(int i = 0;i < (n);i++)
using namespace std;
using ll = long long;
using pii = pair<int,int>;

const int INF = 2e9;

int main(){
    int n,a,b;
    cin >> n >> a >> b;
    string s;
    cin >> s;
    int ca = 0;
    int cb = 0;
    rep(i,n){
        if(s[i] == 'a'){
            if(ca < (a+b)){
                cout << "Yes" << endl;
                ca++;
            }
            else cout << "No" << endl;
        }
        else if(s[i] == 'b'){
            if(ca < (a+b) && cb < b){
                cout << "Yes" << endl;
                ca++;
                cb++;
            }
            else cout << "No" << endl;
        }
        else cout << "No" << endl;
    }
}

```

解くのにかかった時間：6分44秒

##[キーエンス プログラミング コンテスト 2019_B](https://atcoder.jp/contests/keyence2019/tasks/keyence2019_b)

```c++

#include <bits/stdc++.h>
#define rep(i,n) for(int i = 0;i < (n);i++)
using namespace std;
using ll = long long;
using pii = pair<int,int>;

const int INF = 2e9;

int main(){
    string s;
    cin >> s;
    string r = "keyence";
    int n = s.size();
    rep(i,(n + (7-n) - 1)){
        string rs = s.substr(0,i+1) + s.substr(i+1 - (7-n));
        if(rs == r){
            cout << "YES" << endl;
            return 0;
        }
    }
    cout << "NO" << endl;
}

```

解くのにかかった時間：21分37秒
感想：(7-n)が正数であると勘違いしてしばらくエラーをはいていた。

###最後に
間違えたあとの修正にすごい時間をとってしまうのでいかにどこで間違えたのかを素早く発見していくことと、その修正を素早く実装していくことが課題になっていきそう
現場で使われるディープラーニング手法8選を一切コードを使わず解説 画像分類編


# 画像認識と転移学習(VGG16)
このpartでは、

- VGG16
- 転移学習
- ファインチューニング
- 画像認識の流れ

の4つを解説します。

## VGG16
ImageNetデータセットで事前にパラメータ学習されたモデル。1000クラスを分類可能。
Input:(channel,height,width)=(3,224,224) Output:1000
![VGG16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935441/e6c0a28a-397b-a3b8-490e-505230cd8d41.png)


## 転移学習
パラメータ学習済みモデル(VGG16など)をベースに、最終出力層を分類したいクラス数に付け替え、さらにその数層手前までを自前のデータセットで学習し直す手法。少ないデータセットで高い精度を出すことが可能。

## ファインチューニング
学習済みモデルを利用するという点で転移学習に近い手法だが、違いとして出力層だけでなく全層自前のデータセットで学習し直す（チューニングする）という点が挙げられる。一般的には入力層付近の学習率は小さめに、出力層に近づくに連れて大きくしていく。

## 画像認識の流れ
1.前処理クラス…画像をリサイズしたり反転・回転させたり標準化したりすることで、

- モデルの入力サイズに調整
- データの水増し
- 精度の向上

などが期待される。
2.パスリスト作成クラス…今いる階層から自前のデータまでのアクセスルートをパスとして取得し、リスト化する。

3.データセットクラス…上記1と2を組み合わせ、（前処理済み画像,正解クラス）のタプルを作る。

4.データローダークラス…3で作成した（前処理済み画像,正解クラス）が画像枚数分あるリストから、ミニバッチサイズに応じてデータを抽出する。

5.モデルを学習させる関数…実際に学習を行う場所。

- ネットワークの定義(or既存モデルのロードと層の付け替え）
- 損失関数の定義（分類→交差エントロピー、回帰→平均二乗誤差が一般的）
- 最適化手法の定義
- エポック数の定義
WSL2でカスタムカーネルをビルドして使う

[WSL Advent Calendar 2020](https://qiita.com/advent-calendar/2020/wsl)の12/6分です。

## 環境

Ubuntu-18.04 LTS

## カーネルソースの入手

https://github.com/microsoft/WSL2-Linux-Kernel をクローン

```
$ git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
```

デフォルトではないブランチをビルドしたい場合はチェックアウトしておきます。

```
$ git checkout -b linux-msft-wsl-4.19.y origin/linux-msft-wsl-4.19.y
```


## ビルドツールのインストール

[README-Microsoft.WSL2](https://github.com/microsoft/WSL2-Linux-Kernel/blob/master/README-Microsoft.WSL2)にある通り。

```
$ sudo apt install build-essential flex bison libssl-dev libelf-dev
```

## カーネルパラメータを設定する

WSL用のカーネルパラメータは `./Microsoft/config-wsl` にあるので、設定変更したい場合はこのファイルを修正します。

## ビルド

```
$ make KCONFIG_CONFIG=./Microsoft/config-wsl
```

ブランチによっては、ビルド中にオプションについて聞かれることもあります。

## カーネルとカーネルモジュール

カーネルモジュールは、コマンドをたたくことで `/lib/modules/<version>` にインストールされます。

```
$ sudo make modules_install
```

カーネルはひと手間必要です。まずは`vmlinux`をWindowsのドライブのどこかにコピーします。場所は任意ですが、下の例では `%TEMP%` にします。

```
$ cp vmlinux /mnt/c/Users/<username>/AppData/Local/Temp
```

そして、WSLの設定ファイルである `%USERPROFILE%\.wslconfig` にカーネルの場所を指定します。ファイルがなかったら新規作成します。

```%USERPROFILE%\.wslconfig
[wsl2]
kernel=C:\\Users\\<username>\\AppData\\Local\\Temp\\vmlinux
```

## 起動

一旦WSLをシャットダウンしてから起動しなおします。

```
> wsl.exe --shutdown

> wsl.exe

$ uname -a
Linux DESKTOP-4376RCU 4.19.128-microsoft-standard+ #2 SMP Mon Dec 7 06:37:33 JST 2020 x86_64 x86_64 x86_64 GNU/Linux
```
PythonでGoogle Cloud Loggingへログ出力

# 概要

Pythonから、Google Cloud のLoggingにログを出力する方法です。

# 手順

## GCP内(Compute Engineなど)からのログ出力

Compute Engineなど、暗黙的に認証が行われる環境であれば、ログ出力は簡単です。
まず、モジュールを ```pip install google-cloud-logging``` でインストールした後、以下のコードを実行します。

```python
from google.cloud.logging import Client

logging_client = Client()
logger = logging_client.logger('mylogname')
logger.log_text("Hello, world!")
```

Pythonのloggingモジュールでログ出力するには専用のハンドラーが使えます。

```python
import logging
from google.cloud.logging import Client
from google.cloud.logging.handlers import CloudLoggingHandler

logging_client = Client()
handler = CloudLoggingHandler(logging_client, name='mylogname')
cloud_logger = logging.getLogger()
cloud_logger.setLevel(logging.INFO)
cloud_logger.addHandler(handler)
cloud_logger.error('Hello, world!')
```

細かいことですが、loggingから出力した場合はjsonPayloadで出力されます。textPayloadで出力することはできないと思われます。textPayloadが必要な場合は、最初の例のように、loggingモジュールを介さず直接 `log_text()` で出力する必要があります。

## GCP外からのログ出力

GCP外からは明示的に認証を行う必要があります。
今回はサービスアカウントを使って認証させます。(多少手順は異なりますが、通常のユーザーアカウントを使ってもできるはずです)

### クラウド側の設定
IAMでサービスアカウントを作成して、Logs Writerの権限を付与します。
作成したアカウントのキーをダウンロードしておきます。以下の例では `service-account.json`とします。

### ローカル(Python実行環境)の設定

上記のコードに少し認証の手順を追加することで、ログを出力できます。

```python
import logging
from google.cloud.logging import Client
from google.cloud.logging.handlers import CloudLoggingHandler
from google.oauth2 import service_account

credentials = service_account.Credentials.from_service_account_file('service-account.json')
logging_client = Client(project='my-project-id', credentials=credentials)
handler = CloudLoggingHandler(logging_client, name='mylogname')
cloud_logger = logging.getLogger()
cloud_logger.setLevel(logging.INFO)
cloud_logger.addHandler(handler)
cloud_logger.error('Hello, world!')
```
【JavaScript】超簡単なお絵かきアプリを作りました

完成物
![demo](https://gyazo.com/602a39439535e86ec58064393cf198b4/raw) 

```html:index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="./style.css">
  </head>
  <body>
    <div id="black"></div>
    <div id="red"></div>
    <div id="green"></div>
    <script src="./main.js"></script>
  </body>
</html>
```

```css:style.css
.dot {
  position: absolute;
  width: 10px;
  height: 10px;
}

#black {
  width: 100px;
  height: 100px;
  background-color: black;
}

#red {
  width: 100px;
  height: 100px;
  background-color: red;
}

#green {
  width: 100px;
  height: 100px;
  background-color: green;
}
```

```JavaScript:main.js
let clicking;
let color = 'black';
const black = document.getElementById('black');
const red = document.getElementById('red');
const green = document.getElementById('green');

black.addEventListener('click', () => {
  color = 'black';
});
red.addEventListener('click', () => {
  color = 'red';
});
green.addEventListener('click', () => {
  color = 'green';
});

document.addEventListener('mousedown', () => {
  clicking = true;
});

document.addEventListener('mouseup', () => {
  clicking = false;
});

document.addEventListener('mousemove', (e) => {
  if (!clicking) {
    return;
  }
  const dot = document.createElement('div');
  dot.className = 'dot';
  dot.style.left = `${e.clientX}px`;
  dot.style.top = `${e.clientY}px`;
  dot.style.backgroundColor = color;
  document.body.append(dot);
});
```

![スクリーンショット 2020-12-06 23.33.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635852/a4e04172-1203-c8ab-1b38-64e17e2dfa5b.png)

楽しい・・・
時間かけたらもっと本格的なものが作れそうです。
【Flutter】FlutterでCupertinoThemeDataを使用したiOSテーマスタイルの作成

この記事は「[HTC Advent Calendar 2020](https://qiita.com/advent-calendar/2020/htc)」の6日目の記事です。
今回は、FlutterのWidgetsの１つである「Cupertino widegets」について書いていきます。

FlutterでiOSライクなアプリを作ろうとした際に、`CupertinoApp`ウィジェットの`CupertinothemeData`について調べた内容になります。

#Cupertino ウィジェット
Flutterといえば、マテリアルデザインを想像する方が多いと思いますが、実はCupertinoというiOS風のウィジェットも提供しています。
読み方は「クパチーノ」で、Apple本社のあるクパチーノ由来の命名のようです。

#Flutterにおけるテーマ
簡単に説明すると、Flutterでアプリ全体を統一感のあるデザインにできる仕組みです。
この仕組みを使うことで、デザインを一箇所で統一的に管理できます。例えば、iOSのステータスバーの色やテキストの色が気に入らなければカスタマイズできます。また、ダークモード用のプロパティも用意されており、簡単に実装できるようになっています。

#iOSテーマスタイルの作成

Cupertinoウィジェットを使用するために、パッケージの導入を行います。

```dart:main.dart
import 'package:flutter/cupertino.dart';
```
`CupertinoApp`ウィジェットを作成し、`CupertinoThemeData`でテーマの指定を行います。
`CupertinoApp`ウィジェットは、Material Componentの`MaterialApp`ウィジェットの代わりになるウィジェットです。`MaterialApp`ウィジェットとほとんど同じプロパティを持ちます。

```dart:main.dart
import 'package:flutter/cupertino.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
        theme: CupertinoThemeData(
            barBackgroundColor: CupertinoColors.lightBackgroundGray,
// ・・・省略
  }
}
```

上記のコードの例では、`barBackgroundColor`を変更することでナビゲーションバーの背景色をライトグレーに変更しています。
`CupertinoThemeData`の主なプロパティは以下に記載しておきます。

`barBackgroundColor`: 上部のナビゲーションバーと下部のタブバーの背景色を変更できます。
`brightness`: アプリの全体の明るさを変更できます。
`primaryColor`: アプリの基本となる色を変更できます。
`textTheme`: Cupertinoウィジェットで使用されるテキストのスタイルを変更できます。

画面上ではこのような色になります。
他にも`CupertinoIconThemeData`を使用すれば、アイコンのテーマ変更も可能となります。
![ss 2020-12-06 23.31.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/917920/bc9ae97d-3782-4dd0-bcb5-a4464198b535.png)
「Factoryクラスでドメインオブジェクトを生成する」という規約をArchUnitでテストする

[「Factoryメソッドでドメインオブジェクトを生成する」という規約をArchUnitでテストする](https://qiita.com/logy0704/items/9985402e1e8bb8bcd326)の続き。

「ドメインオブジェクトの生成を責務とするFactoryクラスが存在するかどうか」テストしてみる。


## テスト対象のイメージ

```java

public class Hoge {
    Hoge() {} 
}

public class HogeFactory {
    public Hoge create() {
        return new Hoge();
    }
}

```
## テストコード

```java

@AnalyzeClasses(packages = "com.example")
public class DomainObjectTest {

    @ArchTest
    static ArchRule domain_object_has_no_public_constructors =
        constructors()
            .that().areDeclaredInClassesThat().haveSimpleName("Hoge")
            .should().bePackagePrivate();

    // FactoryクラスにHogeを返すcreateというメソッドが存在すること
    @ArchTest
    static ArchRule factory_class_exists =
        methods().that().areDeclaredInClassesThat().haveSimpleName("HogeFactory")
            .should().haveName("create")
            .andShould().haveRawReturnType("Hoge");
}
```

FactoryクラスからHogeコンストラクタを呼ぶため、コンストラクタがパッケージプライベートであることをテストしている。

前回のFactoryメソッドのテストの場合は`bePrivate()`を使用していたが、今回は、同じくArchUnitに用意されている`bePackagePrivate()`を使用してテストした。

このあたりの基本的なアサーションは一通り利用できるほか、それらを組み合わせて新たな判定ロジックを定義することもArchUnitでは宣言的に実施できる。
Nodistコマンド覚書

すぐに忘れてしまうのでメモしておく

# npm

* インストールしたもの一覧

```
npm ls --depth=0
npm ls -g --depth=0
```

* npxインストール

Nodistだとnpxがインストールされないので個別にインストールが必要

```
npm i npx -g
```

* インストールとpackage.jsonの関係

```
// package.json（dependencies）に追記
npm i %パッケージ%
npm i %パッケージ% --save
npm i %パッケージ% -S

// package.json（devDependencies）に追記
npm i %パッケージ% --save-dev
npm i %パッケージ% -D

// package.jsonに追記しない
npm install %パッケージ% --no-save
```

# Nodist

* Node.jsとnpmの対応
 * https://nodejs.org/ja/download/releases/

* インストール済みバージョン一覧

```
nodist ls
nodist npm ls
```

* インストール可能バージョン一覧

```
nodist dist
```

* バージョンのインストール

```
nodist + %バージョン番号%
```

* バージョン指定（グローバル）
 
```
nodist %バージョン番号%
nodist npm %バージョン番号%

nodist global %バージョン番号%
nodist npm global %バージョン番号%
```

あまり意識することはないが、インストールディレクトリ（C:\Program Files (x86)\Nodist\）の
.node-version-global、.npm-version-globalに、現在のバージョンが設定される。

* バージョン指定（ローカル）

```
nodist local %バージョン番号%
nodist npm local %バージョン番号%
```

ディレクトリに.node-version、.npm-versionが作成され、ディレクトリ単位でnodeのバージョンを設定できる。
直接ファイルを作成しても良い。


* 現在のNode.jsのバージョンにnpmのバージョンを合わせる

```
nodist npm match
nodist npm local match
```
ドキュメント書くと気をつけること

#誤字・脱字等
##誤字・脱字
##整合性
ファイル名
タイトル
シート名
#フォント
#半角とか全角とか
##半角　空き
省略
##半角の数字
1234567890
##半角の記号
 !"#$%&'()-^\@[;:],./\=~|`{+*}<>?_
##半角英語小文字
abcdefghijklmnopqrstuvwxyz
##半角英語大文字
ABCDEFGHIJKLMNOPQRSTUVWXYZ
##半角カタカナ
ｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜｦﾝ
ｧｨｩｪｫｯｬｭｮｰ
ｶﾞｷﾞｸﾞｹﾞｺﾞｻﾞｼﾞｽﾞｾﾞｿﾞﾀﾞﾁﾞﾂﾞﾃﾞﾄﾞﾊﾞﾋﾞﾌﾞﾍﾞﾎﾞﾊﾟﾋﾟﾌﾟﾍﾟﾎﾟｳﾞ

##全角　空き
省略

##全角の数字
０１２３４５６７８９

##全角の記号
、。，．・：；？！゛゜´｀¨＾￣
＿ヽヾゝゞ〃仝々〆〇ー―‐／＼～
∥｜…‥‘’“”（）〔〕［］｛｝
〈〉《》「」『』【】＋－±×÷＝
≠＜＞≦≧∞∴♂♀°′″℃￥＄￠
￡％＃＆＊＠§☆★○●◎◇◆□■
△▲▽▼※〒→←↑↓〓∈∋⊆⊇⊂
⊃∪∩∧∨￢⇒⇔∀∃∠⊥⌒∂∇≡
≒≪≫√∽∝∵∫∬Å‰♯♭♪

##全角英語小文字
ａｂｃｄｅｆ
ｇｈｉｊｋｌｍｎｏｐｑｒｓｔｕｖ
ｗｘｙｚ

##全角英語大文字
ＡＢＣＤＥＦＧＨＩＪＫＬＭＮＯＰ
ＱＲＳＴＵＶＷＸＹＺ

##全角カタカナ
ァアィイゥウェエォオカガキギクグ
ケゲコゴサザシジスズセゼソゾタダ
チヂッツヅテデトドナニヌネノハバ
パヒビピフブプヘベペホボポマミム
メモャヤュユョヨラリルレロヮワヰ
ヱヲンヴヵヶ

##全角ひらがな
ぁあぃいぅうぇえぉおかがきぎくぐ
けげこごさざしじすずせぜそぞただ
ちぢっつづてでとどなにぬねのはば
ぱひびぴふぶぷへべぺほぼぽまみむ
めもゃやゅゆょよらりるれろゎわゐ
ゑをん

##全角漢字
省略

# サンプル
##説明
タイトル
１行空き
段落ごとに２行あき
##本文
おはようございます

お
は
よ
う


ご
ざ
い
ま
す

##箇条書きについての参考
https://tsutawarudesign.com/yomiyasuku5.html

##付記
一文が４０文字程度
##図解
比較・変化・プロセス・列挙
A B  A→B  A→B→C A,B,C
スペース内要素の中央揃え


# はじめに
2019年のAdvent Calendarで公開した[いいね！プラグイン EX](https://qiita.com/potara/items/5e4d4408576b61fc56c9)で選択できるアイコンを増やしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480759/6c098f71-0dfa-2cfc-810e-5c20b4b4cc24.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480759/0d997f86-356c-556f-65b3-d7a677ead01b.png)



アイコンをスペース要素内に表示する場合に縦位置を中央揃えするのに戸惑ったのでメモしておきます。

例えばこんなコードです。このとき縦位置が中央揃いになりません。

```javascript
(($) => {
  kintone.events.on("app.record.detail.show", (event) => {
    const element = kintone.app.record.getSpaceElement("space");
    $(element).append("<span><button>ボタン</button></span>");

    return event;
  });
})(jQuery);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480759/40420890-cb16-9179-74a5-4d4bea91fe8e.png)



# heightが指定できる場合

親要素のspanに以下を設定すれば中央揃えにできます。



```css
display: inline-flex;
height: 66px;
justify-content: center;
align-items: center;
```

![button3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480759/c5d849f9-06f0-81d4-2237-2ce3400feef6.gif)



# heightが指定できない場合

親要素のspanに以下を設定すれば中央揃えにできます。

```css
position: absolute;
transform: translateX(-50%) translateY(-50%);
top: 50%;
left: 50%;
```

![button4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480759/2ed03deb-f7fe-5520-7dd3-e7c0f8c4df92.gif)
人材市場的な視点からソフトウェアパッケージングスキルを考えてみる

## TL; DR

- バイオインフォのソフトウェアパッケージを作る研究者は多くない
- 多くないということはそのスキルはキャリア形成に有利
- みんな BioPackathon 入ろうぜ

## はじめに

「とにかく論文を書かないといけない、ソフトウェアパッケージングスキルなんて学習してる暇は無い」っていう感じの方が多いかと思います。

でもそういうのって基本的に「修羅の道のトラディショナルな研究者のキャリアパスしか自分は考えてない」って感じそうで、そんな能力・自信の無い僕には自分に関係のある話に聞こえませんでした。

しかしそういう人が多いというのは(逆にソフトウェアパッケージングなんてもんができる人の)「人材の価値が大きく、キャリア形成において有利」(になるかもしれない)ということであり、「生きていく上で美味しい技術」ということでもあります。なので、若手のキャリア形成とか専門性の選択といった文脈で「ソフトウェアパッケージングスキル」が出てもいいのかな、と思っています。

本記事では、[Bioconductor Community Advisory Board](http://bioconductor.org/about/community-advisory-board/)という立場から「Bioconductor(バイオインフォマティクスの最重要Rパッケージ集)の貢献者が(日本で)足りてない」問題について考えていこうと思います。

### 本記事の主なターゲット
- 生命系の研究しながらある程度プログラミングもやってるけど、「トラディショナルな研究者の道」に進む自信は無い、ぐらいの人
- バイオインフォ興味あるしやってみたいけどとっかかりがない人たち
- キャリアに漠然とした不安抱える生物系の学生

### 以下の話題は対象外
- 「そもそもソフトウェアパッケージ(ング)とは何か」
- Bioconductorとは何か
- BioPackathonとは何か
- ソフトウェアパッケージのネタはどうやって得るか、みたいな話

## そもそもソフトウェアパッケージ作者が足りていない問題

### Bioconductorのパッケージ作者数を例に

研究のソフトウェアをパッケージとしてまとめる人は少ないんですが、その具体例として日本のBioconductorのpackageメンテナーの数は海外と比較して圧倒的に少ないです。

https://www.bioconductor.org/packages/release/BiocViews.html#___Software をひたすら目grepした感じでは、おそらく日本にお住まいのメンテナーは3名+数人(確認漏れてたらすみません!)程度だと思います。(アノテーションや実験データのパッケージを除いたもので)全パッケージ数が1974なので日本の貢献は1974分の3しかないということです。

### バイオインフォの人材数とBioconductorのパッケージ作者数

@Yohei__K さんの [人材市場的な視点からバイオインフォを考えてみる](https://qiita.com/Yohei__K/items/db917738769bf79141a5) によると、「バイオインフォ人材はおそらく数千人程度のオーダーです。」とのことです。
数千分の3ってどんだけだよって話かと。

## みんな BioPackathon 入ろうぜ

今までの話を踏まえた学生へのメッセージがこちらになります。

- 人材の足りなさがすごいので、目立ちやすい
- 将来が不安な生命系の学生は、大学院時代でソフトウェアパッケージ作成スキルを身につけるのは一つの選択肢
- コロナで地理的束縛が無くなってきており(外国のソフトウェアコミュニティのZoomに参加する機会があれば)、リアル英語を強制(矯正?)的に学習できる
- パッケージ作成をピアサポートするコミュニティ(==[BioPackathon](https://twitter.com/biopackathon)) もある
    - 一人で悩むより時間を節約できる

## 終わりに

「自分は生命科学の研究職になるんじゃ！」って方がほとんどかと思いますが、一風変わった(生命科学の)ソフトウェア技術の専門家になるってのも(今んとこ日本では相手にされないかもですが)なくはないんじゃないでしょうか。
(まともに就職したことが無く)民間企業のことはわからないのですが、もしかしたら注目されるかもしれません。

といっても「どうやってソフトウェア技術を身につけていけばわからない」っていう事情もあるかと思うので
[BioPackathon](https://twitter.com/biopackathon) というソフトウェアパッケージングに関するコミュニティでは[月1のZoom](https://biopackathon.connpass.com/event/195344/) のミートアップ以外に
[統合TV](https://www.youtube.com/channel/UCyftgRDCOa09RYl63QBFPdg) にそのあたりをサポートする動画も投稿していこうとしてます(何かリクエストがあれば twitter なりでお気軽にご連絡を！)。

それではみなさん良いお年を、ちなみにすでにリンクを挙げましたがこのエントリーのプロットは
@Yohei__K さんの [人材市場的な視点からバイオインフォを考えてみる](https://qiita.com/Yohei__K/items/db917738769bf79141a5)
の丸パクリです:)
DjangoでGoogleのアバター画像を扱う


いくつか参考記事があったが、記事の通りやっても下記エラーとなり詰まってたのでメモ。

### エラー内容
```
KeyError at /oauth/complete/google-oauth2/
'image'
```

### 解決策
```
def get_avatar(backend, strategy, details, response,
        user=None, *args, **kwargs):
    url = None
    if backend.name == 'facebook':
        url = "http://graph.facebook.com/%s/picture?type=large"%response['id']
    if backend.name == 'twitter':
        url = response.get('profile_image_url', '').replace('_normal','')
    if backend.name == 'google-oauth2':
        url = response["picture"]  #ここが「image」だと✗だったが、pictureで無事表示できた
    if url:
        user.profile_icon = url 
        user.save()
```

参考記事：
https://hodalog.com/python-social-auth-get-google-avatar/

https://stackoverflow.com/questions/25734611/python-social-auth-get-google-avatar
続やさしめのGo Quiz

# 問題

つぎのコードを実行するとどうなるでしょう。

```go
package main

func hello() {
	hello := func() {
		hello := func() {
			print("hello")
		}
		hello()
	}
	hello()
}

func main() {
	hello := hello
	hello()
}
```

A. `hello` と出力される
B. `hellohello` と出力される
C. コンパイルエラー
D. 実行時エラー(panic)

# 解答

<details><summary>ここを開いてください</summary><div>

**正解はAです。**

3行目から定義が始まる関数hello(以下hello3)が単純に呼び出されて場合については、[昨日の問題](https://qiita.com/drafts/cae9ec5e0497cfb3ddb6)と同様です。
くせものは14行目の変数hello(以下hello14)にhello3を代入しているところですが、これは許されます。つまり15行目で実行されているのはhello14です。

この代入が許されるのは、関数名(`FunctionName`) は `identifier` であり、`identifier` は `:=` の右辺にとれるものの一つだからです。
詳しくは仕様の [Short variable declarations](https://golang.org/ref/spec#Short_variable_declarations)と[Function declarations](https://golang.org/ref/spec#Function_declarations)からたどっていくとよいでしょう。
</div></details>
[AWS] EC2インスタンスにApacheをインストール

#EC2インスタンスにApacheをインストール

今回も、本日（2020/12/06）、AWSのEC2インスタンスにApacheをインストールしましたよ、というだけの投稿です。

SSHでApacheをインストールしました。（下記のコマンド）

>sudo yum -y install httpd

超個人的なメモでしかない投稿ですね。すみません。
Kotlin の関数

Kotlin を勉強中なので、自分用まとめ

## 関数
```
// 関数定義
fun 関数名 (仮引数: 型, ...): 戻り値の型 {処理}

// 関数の使用
関数名(実引数, ...)
```

```kotlin
fun addThree(a: Int): Int {
    return a + 3
}

println(addThree(2))  //=> 5
```

戻り値がない場合は、戻り値の型を `Unit` にする（`Unit` は省略可）

```kotlin
fun printHello(name: String): Unit {
    println("Hello, ${name}")
}
```

### ローカル関数

関数内に関数を定義することが可能

```kotlin
fun main() {
    fun addThree(a: Int): Int {
        return a + 3
    }
    
    println(addThree(2))
}
```

### 省略した記述

処理が単一の式の場合、1行で記述可能

```kotlin
fun addThree(a: Int): Int = a + 3

println(addThree(2))
```

## 引数

デフォルト値の指定

```kotlin
fun addThree(a: Int=1): Int = a + 3

println(addThree())  //=> 4
```

名前付き引数

```kotlin
fun add(a: Int=1, b: Int=2): Int = a + b

println(add(a=3, b=4))  //=> 7
println(add(b=4))       //=> 5
```

可変長引数

* `vararg` キーワードを用いる
* 内部的には配列とみなされる

```kotlin
fun sum(vararg values: Int): Int {
    var result = 0
    for (value in values) {
        result += value
    }
    return result
}

println(sum(1, 2, 3))  //=> 6
println(sum(1, 2, 3, 4))  //=> 10
```

スプレッド演算子

* 配列の値を、可変長引数に渡す

```kotlin
val a = intArrayOf(1, 2, 3)
println(sum(a))  // Error
println(sum(*a)) // OK
```

## 戻り値

引数を2つ持つ場合 `Pair` を使う

```kotlin
fun getAddDiff (a: Int, b: Int): Pair<Int, Int> {
    var add = a + b
    var diff = a - b
    return Pair(add, diff)
}

val (add, diff) = getAddDiff(2, 4)
println(add)  //=> 6
println(diff) //=> -2
```

引数を3つ持つ場合

* `Pair` としていたところを `Triple` とする



## 高階関数

引数や戻り値に関数を取る関数

```kotlin
fun printNum(n: Int) {
    println(n)
}

val a = arrayOf(1, 2, 3)
a.forEach(::printNum)  // forEach は高階関数
```

#### 匿名関数（ラムダ式）

* 名前のない関数
* ラムダ式は匿名関数の実装方法の一つ

```
{引数 -> 処理}
```

```kotlin
val a = arrayOf(1, 2, 3)
a.forEach({ n: Int -> println(n) })
```

引数の型が推論可なら省略可

```kotlin
a.forEach({ n -> println(n) })
```

高階関数の引数がラムダ式1つなら、カッコを省略可

```kotlin
a.forEach{ n -> println(n) }
```

ラムダ式の引数が単一の場合、引数 `it` で受け取れる

```kotlin
a.forEach{ println(it) }
```

#### ラムダ式の return 

ラムダ式の中で return を使うと、ラムダ式ではなく呼び出し元の関数を抜けてしまう

```kotlin
fun main() {
    val a = arrayOf(1, 2, 3)
    a.forEach{
        if (it == 2) return  // この return で main 関数を抜けてしまう
        println(it)
    }
    println("end")
}
// [出力]
// 1
```

ラムダ式で return するときは **ラベル構文** を使う

```kotlin
fun main() {
    val a = arrayOf(1, 2, 3)
    a.forEach loop@ {
        if (it == 2) return@loop
        println(it)
    }
    println("end")
}
// [出力]
// 1
// 3
// end
```
Visual Studio (VC++)で std::thread を使って、メンバ関数でスレッドを立てて、その優先度を変更するサンプルコード

こういう情報は、サクッと欲しいですよね。
クラス内でスレッドを立てて、さらにそのスレッドを優先度を上げたり下げたりバックグラウンドで動かしたい時のサンプルです。

ミソは、以下のポイント。
・メンバ変数にスレッドを持っているので、このクラス単体でスレッド管理していること
・std::thread の第2引数に "this" を投げることで、メンバ関数でもスレッド立てられること
・.native_handle() により環境依存のハンドルを取得し、Windowsなら SetThreadPriority() 関数で優先度を変えられること

余談ですが、メンバ変数std::thread th ＆ swap() がダメなら、ポインタメンバ変数std::thread *th ＆ コンストラクタや初期化関数で th = new thread～ でもありだと思います。（その際デストラクタ等で delete を忘れないこと）

なお、こちらの環境はVisual Studio 2017です。


```C++:main.cpp
#include <iostream>
#include <Windows.h>
#include "ThreadStart.h"

int main(void) {
	ThreadStart tst;
	Sleep(2000); // 2秒待つ
	std::cout << "bye at main()\n";
	return 0;
}

```

```ThreadStart.h
#include <iostream>
#include <string>
#include <thread>
#include <Windows.h>

class ThreadStart
{
public:
	ThreadStart();
	~ThreadStart();
private:
	void newThread();
	std::thread m_th;
};
```

```ThreadStart.cpp
#include "ThreadStart.h"
using namespace std;

ThreadStart::ThreadStart()
{
	// スレッド起動
	thread th(&ThreadStart::newThread, this);
	// 優先度を変更
	int ret;
	ret = SetThreadPriority(
		th.native_handle(),
		THREAD_PRIORITY_BELOW_NORMAL // 通常以下
	);
	// エラー表示
	if (ret == 0) {
		string str;
		str = "Failed change priority err:";
		str += to_string(GetLastError());
		str += "\n";
		cout << str;
	}
	// スレッド管理をメンバ変数に移譲
	th.swap(m_th);
}

ThreadStart::~ThreadStart()
{
	cout << "bye at thread\n";
	m_th.join();
}

void ThreadStart::newThread()
{
	cout << "hello thread!\n";
}
```
Kotlin の制御構文

Kotlin を勉強中なので、自分用まとめ

## if

```kotlin
val a = 10

if (a <= 5) {
  println("a <= 5")
} else if (a <= 10) {
  println("5 < a <= 10")
} else {
  println("10 < a")
}
```

if 式は値を返すことが可能（この場合、else は必須）

```kotlin
val a = 10

val msg = if (a <= 5)
  "a <= 5"
else
  "5 < a"

println(msg)
```

## when

```kotlin
val a = 1

when (a) {
  1 -> println("a=1")
  2 -> println("a=2")
  else -> println("other")
}
```

条件のバリエーション

```kotlin
val a = 3

when (a) {
1,2 -> println("1 or 2")
in 3..5 -> println("3 から 5")
!in 1..5 -> println("1 から 5 以外")
else -> println("その他")
}
```

is 演算子

```kotlin
val a: Any = "abc"

when (a) {
  is String -> println("Length = ${a.length}")
  else -> println("Not String")
}
```

When 式で if を代替できる

```kotlin
val a = 10

when {
  a <= 5 -> println("a <= 5")
  a <= 10 -> println("5 < a <= 10")
  else -> println("10 < a")
}    
```

## for

```kotlin
val items = arrayOf(1, 2, 3)

for (item in items) {
  println(item)
}
```

map の for 文

```kotlin
val items = mapOf("a" to 1, "b" to 2, "c" to 3)

for ((key, value) in items) {
  println("${key}: ${value}")
}
```

配列でインデックスを取得しながら for を回す

```kotlin
val items = listOf("a", "b", "c")

for ((index, value) in items.withIndex()) {
  println("${index}: ${value}")
}
```

範囲演算子

```kotlin
for (i in 1..3) {
  println(i)  //=> 1, 2, 3
}

for (j in 1 until 3) {
  println(j)  //=> 1, 2
}

for (k in 3 downTo 1) {
  println(k)  //=> 3, 2, 1
}

for (l in 1..10 step 3) {
  println(l)  //=> 1, 4, 7, 10
}
```

## while / do

```kotlin
var i = 1
while (i < 3) {
  println(i)
  i ++
}
```

```kotlin
var i = 1
do {
  println(i)
  i ++
} while (i < 3)
```
Kotlinでscriptを書ける機能について軽く調べてみた

この記事は [Kotlin Advent Calendar 2020](https://qiita.com/advent-calendar/2020/kotlin)の11日目の記事です。
普段使わないKotlinの機能について調べてみようと思い、kotlinでscriptを書ける機能について調べてみました。

# ”scriptを書ける” とは？

Kotlinコードをテキストファイル or 文字列で受け取り、それを実行するという意味になります。
例えば、コマンドライン経由でKotlinコードのファイルを指定して処理を動かしたいときであったり、ユーザが入力したKotlinコードを実行したいケース（IPython/Jupyter notebookのようなイメージ）などが具体的なユースケースになります。

特に前者は、ローカルで動かすちょっとした処理を書きたいけど、shell scriptを書きたくない…とかのケースで有用になります。

# メジャーなライブラリ

[kscript](https://github.com/holgerbrandl/kscript/)というライブラリが、kotlincをWrapして便利に使えるようにしてくれているそうです。
どうやら2016年頃からあるらしいです。

実際に使ってみましたが、かなり手軽に使えました。

インストールは、kscriptのドキュメントに記載されているように、以下コマンドでできます。

```shell
curl -s "https://get.sdkman.io" | bash     # install sdkman
source "$HOME/.sdkman/bin/sdkman-init.sh"  # add sdkman to PATH
sdk install kotlin                         # install Kotlin
sdk install kscript
```

以下のように直でKotlinコードを渡して実行することもできるし（初回実行時間が体感3sくらいで、2回目以降が体感0.5sくらいになる）

```shell
kscript 'println("hello world")'
```

以下のようなshell scriptっぽいファイルをファイル名`sample.kts`で作成し、`kscript sample.kts foo bar`コマンドで実行することもできます。

```shell
#!/usr/bin/env kscript

println("Hello from Kotlin!")
for (arg in args) {
    println("arg: $arg")
}
```

※ 実行結果

```
Hello from Kotlin!
arg: foo
arg: bar
```

wrapperライブラリなだけあって、以下のような色々な便利機能もあるようです。

* scripts caching: 2回目以降の実行速度が速くなる
* maven dependencies: `@file:DependsOn("com.squareup.okhttp3:okhttp:4.7.2")` といったようにscript内に依存ライブラリを宣言できる。（curlやwgetを使わずにすむ。）
* IntelliJ support: 何かしらあるらしい

後述する、公式がサポートしている機能と比較した際の欠点は、kscriptをローカルにinstallする必要がある点です。

# 公式のサポート状況

[Kotlin1.3.70のリリースブログ](https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-released/)や、[Kotlin1.4のリリースノート](https://kotlinlang.org/docs/reference/whatsnew14.html#new-dependencies-resolution-api)に、script機能の強化について記載されているため、順調に改善されていっているようです。

先程kscriptの説明で紹介したような使い方であれば、kscriptを使わなくても問題なくできるようで、
以下はコマンドライン経由でKotlinコードを実行する例です。（`74`という実行結果が得られます）

```
kotlin -e "1 + 3 + 70"
```

また、ファイル経由で実行する場合は、以下のファイルを `sample.main.kts` という名前で保存し、`kotlinc -script sample.main.kts foo bar`コマンドで実行することができます。

```shell
#!/usr/bin/env kotlin

println("Hello from Kotlin!")
for (arg in args) {
  println("arg: $arg")
}
```

こちらも公式サポート機能ということもあり、IntelliJ IDEAによるサポートがありました。
kscriptに比べて機能は少ないけれども、kotlin以外はインストールする必要がない点がメリットのようです。

なおkscriptと違ってartifactの依存関係を探索的に解決してくれないという欠点がいま時点ではあるようなので、もし今自分が選ぶならkscriptを使うだろうと思います。

# 最後に

kscript、機会があれば使ってみたさ…。
といいつつ、ローカルで簡単にKotlinコードの動かすだけなら、IntelliJ IDEAのscratchファイル機能を使ってできるので、しばらくは使う機会はないかも。
AWSをコマンドラインで扱うときに--profileってるけるのが面倒なのでdirenvをつかったほうがいい

aws cliを使うときに複数のprofileを使っていると時々間違えた環境に対して操作を行ってしまったりしてヒヤッとすることがある

--profileをつけわすれてワーみたいな

なのでdirenvという該当のディレクトリの中だけで環境変数を設定できるツールをつかっている
https://github.com/direnv/direnv



該当のディレクトリに「.envrc」というファイルを作成して
以下のコマンド

```
direnv edit .
```


中身をこんなふうにしておく⇣

```
export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxx
```

そうしたらawsコマンドを使う前に

```
direnv arrow
```

とすると.envrcの中の変数が該当ディレクトリ内だけで反映されるので
「--profile」ってつけなくても大丈夫になるのでヒューマンエラーを防げる

おしまい
Kotlin の変数

Kotlin を勉強中なので、自分用まとめ

## 変数宣言

```
var 変数名: 型 = 初期値
val 定数名: 型 = 初期値  // read-only
```

```kotlin
var a: Int = 1
val b: Int = 1
var c = 2  // 初期値を与える場合は、型は省略可能

a = 3  // OK
b = 3  // Error
```

| 型      | 説明                |
| ------- | ------------------- |
| Double  | 64 bit 浮動小数点数 |
| Float   | 32 bit 浮動小数点数 |
| Long    | 64 bit 整数         |
| Int     | 32 bit 整数         |
| Short   | 16 bit 整数         |
| Byte    | 8 bit 整数          |
| Boolean | 真偽値              |
| Char    | 文字                |
| String  | 文字列              |
| Any     | 任意                |

### 文字列

```kotlin
var a = "Hello\nWorld"  // エスケープ文字を含む
var b = """Hello
World"""                // 改行やタブを含む
var c = "Kotlin"
var d = "Hello, ${c}"   // 変数を含むことができる
var e = "1+2は、${1+2}" // 式を含むことがｋできる
```

### nullable 型

Kotlin ではデフォルトでは null は許容されない
明示的に null を許容したいときは、型の後ろに ? を付ける

```kotlin
var a: String? = "aaa"
a = null // OK
```

## 型変換

同じ型の中で、値範囲が狭い型から広い型へ変換できる

* toLong()、toByte()、toFloat()  など

  ```kotlin
  var a = 10
  var b: Long = a.toLong()
  ```

## 配列

```kotlin
var a = arrayOf(1, 2, 3)
var b = intArrayOf(1, 2, 3)  // Int 型を指定
```

## コレクション

* List
  * 配列と同じようなもの
  * インデックスで値を取得する
* Set
  * 重複した要素は登録されない
  * 順序は持たないので、インデックスは使えない
* Map
  * キー、バリュー 型
  * オブジェクト型のようなもの

```kotlin
var a = listOf("a", "b", "c", "a", "b")
var b = setOf("a", "b", "c", "a", "b")
var c = mapOf("a" to 1, "b" to 2, "c" to 3)
    
println(a)  //=> [a, b, c, a, b]
println(b)  //=> [a, b, c]
println(c)  //=> {a=1, b=2, c=3}
  
var d = mutableListOf("a", "b", "c")  // 変更可能な list
a[0] = "d"  // Error
d[0] = "d"  // OK
```
Sequelizeでビット演算を使った検索を行う

以下のようなテーブルがあるとします。
statusの値は10進数ですが、アプリケーションではビット演算で管理されてることがわかると思います。

```
id:1, status:1 // 1つめのフラグが立っている
id:2, status:4 // 3つめのフラグが立っている
id:3, status:1023 // 全てのフラグが立っている
```

## SQLでの書き方

3つめのフラグが立っているかどうかのクエリーは以下になります。

``` xxx.sql
SELECT * FROM xxx WHERE (status & 4) = 4;
```

idが2,3が出力されます。

## Sequelize.whereを使った書き方

``` xxx.ts
Model.findAll({
    where: sequelize.where(sequelize.literal('status & 1023'), 1023)
})
````

## 参考
https://github.com/sequelize/sequelize/issues/5207
https://lambdalisue.hatenablog.com/entry/2013/12/22/041347
https://sequelize.org/master/manual/model-querying-basics.html
【具体例あり】ポートフォリオの案出しの方法【２種類の思考法】

<br>

## はじめに
今日から転職活動に向けたポートフォリオの制作過程を、記事にして残して行こうと思います。

初日の今日は、案出しについてです。

ここで詰まって、なかなかポートフォリオの制作に移れない方も、結構おられるのではないかな？と思うので、そう言う方は是非、参考にして頂ければと思います。
<br>

結論から言いますと、案出しを考える際は、

<ul>
  <li>ソリューション型思考</li>
  <li>イノベーション型思考</li>
</ul>

このどちらかの思考法がオススメです。

<br>
<br>

## ソリューション型思考
まず1つ目は、企業や個人が抱えてそうな問題を、ITの力で解決する、ソリューション型(問題解決型)の思考で案出しする方法です。
<br>


### 企業や職場の悩みを解決
簡単に言うと、今働いている企業や職場などで、人力で作業している部分をIT化するようなイメージです。

例えば僕の場合、過去に派遣で働いていた事があるのですが、シフトの提出や打刻が、毎回メールを作成して送信すると言う形でした。それで働いてる時から思っていたのが、

>「メールの作成が面倒。」
「たまにメール送るの忘れてしまう。」
「原始的なやり方だな〜。」

と言う感じです。
<br>
<br>

さらに、この時は送信する側の労力しか考えていなかったのですが、この例で言うと受信側にも以下のような労力が掛かっていると考えられます。

>「毎回送信される情報をエクセルなどに入力するのが手間。」
「人数が多いと、その作業だけで膨大な時間がかかる。」
「その結果、人件費が掛かってしまう。」

そこで思いついたのが、今僕がポートフォリオとして作成している、人材管理のIT化で経費削減。と言うアプリケーションです。
<br>
<br>

このように、職場の悩みを解決に焦点を当てた案出しは、仕事をしている人でしたら割と簡単に思い浮かびやすいですし、尚且つ作成したポートフォリオが良ければ、実際にそれを活用してくれる企業なども出てくる可能性が出てきます。

また、こう言うソリューション型の思考で作られたポートフォリオは、採用する企業側からみても、

>「この人は問題解決のための思考力がありそう。」

と、アピールすることもできるはずなので、例えユーザがつかなかったとしても、制作する価値は高いと思います。
<br>
<br>
<br>

## イノベーション型思考
そして2つ目は、これまであまりメジャーではなかった、新しい切り口のサービスを考案する、イノベーション型(革新型)の思考で案出しする方法です。
<br>

### ニッチな市場で便利な機能を
簡単に言うと、「こう言う機能あったらいいな〜」と思いついた事、または求めてる人が居そうなサービスを、実際にITの力でアプリケーションとして作る感じです。

では実際に、どう言う流れてイノベーション型の思考で、案出しをすればいいのかですが、オススメはニッチ(限定的)な市場での便利な機能を考えると言う方法です。
<br>
<br>

例えば僕が思いついた中でご紹介させて頂くと、

>「転売者向けに各種ECサイトの料金比較アプリケーションの作成」

>「何かのアイディアを投稿して、それを実際に誰かに作ってもらう、アイディアとサービス作成のマッチングプラットフォームの作成」

>「ツイッターのハッシュタグがリアルタイムでどのくらい使用されているのかわかるアプリケーション」

などになります。

*(ただこれらのサービスは、他サイトの情報を取り扱ったりするので、情報の取り扱いに制限が設けられ、自由にサービスの公開が難しそう。と言うことで、お蔵入りにしました。)*
<br>
<br>

また上記以外に、これまで僕が見てきたポートフォリオの具体例を挙げると、

>「筋トレをしたい人と筋トレを教える人のマッチング型プラットフォーム」

>「あるアプリの機能を拡張した、分析系アプリケーション」

>「特定の活動をする人が集う為の、コミュニティ型プラットフォーム」

などになります。
<br>
<br>

このように、*"利用する人は少ないかもしれないけど、あったら便利"* と言う機能の案出しを行えば、先ほどのソリューション型の思考で案が思い浮かばない方(または大学生などで仕事をしていない方)でも、趣味や自分の好きな事で案出しが簡単にできるので、オススメです。

しかもニッチな市場を狙ったアプリは、マスな市場(不特定多数)を狙ったアプリよりも、マーケティング的にユーザが付きやすいと言う特徴もあります。

実際に、僕が知る中でもニッチな市場を狙ったポートフォリオで、転職前に既にユーザが付き、それをアピールして転職や、逆に企業からオファーをもらって、転職する事ができたなどの話をいくつか聞いた事があります。

そのため、転職と言う目標で見ても、イノベーション型の思考でニッチな市場を狙ったポートフォリオは、割と価値の高いポートフォリオになると思います。

>また余談ですが、今は世界中で利用されているFacebookのアプリも、元はFacebook社の創業者でマーク・ザッカーバーグ氏の在学していた大学内だけで、実名かつ顔写真などの情報を元に学生間の交流を図ると言う、ニッチなテーマから始まったものになります。

<br>
<br>

## まとめ
少し長くなりましたので、最後にまとめておきます。
ポートフォリオの案出しをする際の、オススメの思考法は以下の通りです。

<ul>
  <li>ソリューション型思考
    <ul>
      <li>企業や職場の悩みを解決</li>
    </ul>
  </li>
  <li>イノベーション型思考
    <ul>
      <li>ニッチな市場で便利な機能を</li>
    </ul>
  </li>
</ul>

個人的に思うのは、社会人ならソリューション型思考で、大学生やコアなお仕事をされている方はイノベーション型思考が、オススメかと思います。

それでは、今回も最後まで読んでいただき、ありがとうございました！
<br>
<br>
<br>

筆者：yuki｜IT業界のリアルな転職事情など発信｜元トップ営業マン(訪販)→未経験からエンジニア転職へ
Qiita：https://qiita.com/yuki4839
Twitter：https://twitter.com/yukifullstack
<br>
sessionについて【アウトプット】

sessionについて自分用のアウトプットとして書いていく。
まずsessionとは何か
＊変数session：サイト内でページを移動しても情報を維持し続けることができる。また、sessionで代入された値は、ブラウザに保存される。ブラウザとはGoogoleChromeとかである。

どんな感じに書くのか。
session[:キー名]　=　値

【users.controller.rb】
def login
@users = User.find_by(...)
if @user
session[:user_id] = @user.id

もし、＠userがあるならsessionに＠user.idを代入する。
これで＠user.idの情報が保持され続ける。

これがあればその人専用のサイトを見れたり、ログインできるのではないかなと個人的には考えている。

ログイン状態を解除したいときはログアウトができるようなリンクを作りsessionにnilを代入させてあげる。

こんな感じかな
session[キー名] = nil

【users.controller.rb】
session[:user_id] = nil
end

今日は久々に投稿したけどノートにはまとめてあるからアウトプットはできているはず
時間あるときに今日見たく書いていきたい。

では以上
[Python]bit全探索 ABC045C,ARC061C

#[ABC045C](https://atcoder.jp/contests/arc061/tasks/arc061_a)

**$2^n$通りを探索する場合は、bit全探索が便利**である。

下は、けんちょんさんのビット演算のまとめ表
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568274/9f609759-9df5-19a3-1759-270b9c4ccf6b.png)
**[Python ビット演算 超入門](https://atcoder.jp/contests/arc061/tasks/arc061_a)**

```python:サンプルコード
s = input()
n = len(s)

ans = 0

for bit in range(1 << (n - 1)): # n-1左シフト
    f = s[0]

    for i in range(n - 1):
        # フラグが立っている所に+を挿入
        if bit & (1 << i):
            f += "+"
        f += s[i + 1]

    ans += sum(map(int, f.split("+")))

print(ans)
```
Allied TelesisのAPの単体試験の手順

#Allied TelesisのAPの単体試験の手順

##【製品紹介】
今回扱うのは、「AT-TQ5403」です。
![AT-TQ5403 (RoHS).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634845/e215923f-fc2e-fdda-e522-d60f6d1bcd18.jpeg)
お値段:73,000円　https://kakaku.com/item/K0001081418/

##【試験前準備】
まずは、試験準備を行います。
◆接続に使う端末のイーサネット部分に、そのNWで使うIPアドレスとサブネットマスクを割り当てます。
https://www.allied-telesis.co.jp/support/list/wireless/at-tq/rel/5.0.0/613-002599_A/user/doc00005.html

以下、手順になります。
①「ネットワークとインターネットの設定」から、
<img width="600" alt="IPの設定方法③" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634845/64b9e822-609e-c804-96df-3180e621cced.png">

②インターフェース名から、該当する「イーサネット」を選択
<img width="400" alt="IPの設定方法③" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634845/ce5ee854-2c37-c40b-7f3f-5de4dc76c5f7.jpeg">

③「インターネット プロトコル バージョン4（TCP/IPv4）」を選択
<img width="400" alt="IPの設定方法③" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634845/c0d9ddec-fbf4-2443-2ef8-7657539116d6.jpeg">

④プロパティに、IPアドレス、サブネットマスク、デフォルトゲートウェイをそれぞれ設定する
<img width="400" alt="IPの設定方法④" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634845/6245cb25-c2d1-9b6c-f0b2-36460c57d0e1.jpeg">

⑤「詳細設定」から、運用時に用いられる想定のIPアドレスも割り当てておく
<img width="400" alt="IPの設定方法⑤" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634845/8938e804-0552-723d-7ca1-4217463cca7c.jpeg">
※初期アクセス用のIPアドレスは、「192.168.1.230/24」になります。

IPアドレスの設定手順は、以上となります。

##【接続方法】
次に、接続方法を確認します。
◆ケーブルの接続とログイン画面へのアクセス
①中央のポートにLANケーブルを接続する（PoEで給電できる）
![AT-TQ5403 (RoHS) POE説明①.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634845/7c93e2eb-01fe-ec17-19c9-d4194d024344.jpeg)

②電源とLAN1(PoE)がグリーンになるまで待つ
![AT-TQ5403 (RoHS) POE説明②.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634845/01253c0d-d374-0b50-a1c2-f452ec1dba41.jpeg)

③ブラウザで「192.168.1.230」にアクセスし、ログインする
![AT-TQ5403 (RoHS) POE説明③.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634845/aba84a3b-7e0a-3559-36eb-42eb05931080.jpeg)

接続方法は、以上となります。

【単体試験項目】
ここから、単体試験項目を確認していきます。
・言語を日本語へ変更↓
https://www.allied-telesis.co.jp/support/list/wireless/at-tq/rel/5.0.0/613-002599_A/user/doc00007.html
・タイムゾーンを変更↓
https://www.allied-telesis.co.jp/support/list/wireless/at-tq/rel/5.0.0/613-002599_A/user/doc00019.html
・ホスト名等の変更↓
https://www.allied-telesis.co.jp/support/list/wireless/at-tq/rel/5.0.0/613-002599_A/user/doc00018.html#S5.1.1
・ファームウェアアップデート↓
https://www.allied-telesis.co.jp/support/list/wireless/at-tq/rel/5.0.0/613-002599_A/user/doc00038.html
・実施証跡のための、画像キャプチャ↓
https://www.allied-telesis.co.jp/support/list/wireless/at-tq/rel/5.0.0/613-002599_A/user/doc00011.html#S4.1
・Configファイルなどのログ取りを行う↓
https://www.allied-telesis.co.jp/support/list/wireless/at-tq/rel/5.0.0/613-002599_A/user/doc00037.html

単体試験項目は以上となります。

##【所感】
アライドテレシスは日本のメーカーいうことなので、製品のリファレンスも読みやすく、初学者には扱いやすいものである。今度ともNWの知識を高めていきたい。
WKWebViewの完了ボタンを消した話

<img width="320" alt="donebutton.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935288/707b2bbc-751d-06f6-5ccb-a67972c34f9c.png" />
これのこと
WebView内で入力が必要になったときに自動的についてくるらしい、タップするとキーボードを閉じてくれるが、この手のボタンはカスタムで配置するので邪魔だったので消せるようにした
やり方は以下

```swift
//
//  WKWebView+removeDone.swift
//  WebViewDone

import Foundation
import WebKit

extension WKWebView {
    func removeDoneButton() {
        guard let target = scrollView.subviews.first(where: {
            String(describing: type(of: $0)).hasPrefix("WKContent")
        }), let superclass = target.superclass else {
            return
        }

        let noInputAccessoryViewClassName = "\(superclass)_NoInputAccessoryView"
        var newClass: AnyClass? = NSClassFromString(noInputAccessoryViewClassName)

        if newClass == nil, let targetClass = object_getClass(target), let classNameCString = noInputAccessoryViewClassName.cString(using: .ascii) {
            newClass = objc_allocateClassPair(targetClass, classNameCString, 0)

            if let newClass = newClass {
                objc_registerClassPair(newClass)
            }
        }

        guard let noInputAccessoryClass = newClass, let originalMethod = class_getInstanceMethod(NoInputAccessoryView.self, #selector(getter: NoInputAccessoryView.inputAccessoryView)) else {
            return
        }
        class_addMethod(noInputAccessoryClass.self, #selector(getter: NoInputAccessoryView.inputAccessoryView), method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
        object_setClass(target, noInputAccessoryClass)
    }
}

fileprivate final class NoInputAccessoryView: NSObject {
    @objc var inputAccessoryView: AnyObject? { return nil }
}

```
WKWebViewにinputAccessoryViewプロパティがあるがread-onlyなため、自分で作った`NoInputAccessoryView`にSwizzleする感じ
あとはWebViewから呼ぶだけ

```swift
webView.removeDoneButton()
```

<img width="320" alt="remove.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935288/d8cca859-16c5-11bb-15b3-21b0e1fde918.png" />

消えた。あとはOSのアップデート等でこの辺が変更にならないことを祈るのみ。
[python][selenium]エラー「selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable may have wrong permissions.」

# エラー内容
pythonにて　seleniumを実行しようとしたところ、下記エラーが発生。

```
selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable may have wrong permissions.
```

# 原因
`permissions`と書かれているので、権限を確認してみる。

```
mba:scraping kk$ ls -l
total 49720
-rw-r--r--  1 konoken  staff  15720316 Dec  6 22:24 chromedriver
```
実行権限である`x`が振られていないのが原因。

# 解決法
以下コマンドで実行権限をファイルに付与する。

```
chmod ugo+x chromedriver
```
STAC2020から考える、さいきょうのバーチャルカンファレンス運営

https://testautomationresearch.connpass.com/event/191996/

先日こちらに参加してきました。内容も非常に良かったのですが、何より僕が参加したバーチャルカンファレンスの中で一番良かったと思えるほど、運営が素晴らしかったです。その要素がどこにあるのか、ちょっと解きほぐしてみたいと思います。



## 主催者が「ゆるい」
何が一番すごかったか、と問われるならば、これを答えます。主催者がゆるいんです。もちろん、いい意味でです。それを象徴していたのが、Zoomを閉じる際の最後の言葉「じゃーねー」です。これまで1000人規模のバーチャルカンファレンスで、「じゃーねー」で切っちゃう主催者がいたでしょうか。（本当に、いい意味で言っています）

オープニングでも同じような雰囲気で、ゆるく、だれでも発言しやすい雰囲気を作ってくれていました。このことが、後述する参加者の活発な意見交換につながっていたと思います。



##ツール構成が良かった
当日はZoom/Discordで運営されていました。Zoomではほぼ一方向配信、Discordでは参加者同士、参加者*スピーカーのコミュニケーション、あとは主催者からの連絡が行われていました。

Discordのチャンネルがプログラムになっていたのがとてもわかりやすかったです。



##参加者のリテラシーが高かった
これはリモート会議におけるリテラシーや、カンファレンス参加へのリテラシーなどいろんなものが含まれます。

事例としては、Zoom荒らしに対してみんな（当然主催者の対応は完璧）が冷静に対処したこと。そして、発表者までがうまく対処したこと（ありえないほど！）。

もう一つの事例としては参加者が能動的にカンファレンスを盛り上げるということを理解し、Discordでポジティブな意見を発信しまくったこと。

この半年でリテラシーがあがってきたのかもしれませんが、このカンファレンスに参加する人たちの平均リテラシーが高いというのも少なからずありそうです。



##これらから何が生まれたか
そして、こんな素晴らしい運営から生まれたのは、

活発なコミュニケーションにより、参加者の得た価値がリアルカンファレンスより増えた

という事実です。（推測ですけど、たぶん正しい）

感動すら覚えるレベルです。見習いたい。



##これもあったらもっとよかったなという点
些細なところなので蛇足ですが、もっと良くするためは、

・TwitterとDiscordの役割分担（Twitterの流量が減り、世の中への発信は減った）

・Discordで重要な質問が拍手により流れた

・Zoom荒らし対策

ぐらいが問題/課題として思いつきます。

自分が主催者になるときは、まずSTAC2020のレベルに追いつき、さらに良くする手段を試してみようと思います。
Ruby の Hash における keys.each と each_key の違い

# はじめに
*[AtCoder Problems](https://kenkoooo.com/atcoder/#/)* の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

# 今回のお題
*[AtCoder Typical DP Contest A - コンテスト](https://atcoder.jp/contests/tdpc/tasks/tdpc_contest)*
Difficulty: ---

今回のテーマ、動的計画法

問題自体は`動的計画法`の基本だと思われます。
# Hash#keys
```ruby.rb
gets
p = gets.split.map(&:to_i)
dp = Hash.new(0)
dp[0] = 1
p.each do |x|
  dp.keys.each do |y|
    dp[x + y] = 1
  end
end
puts dp.size
```
やっていることは、@kakudaisuke さんの [AtCoder Typical DP ContestのA - コンテストを絵で理解してみたい（PHP）](https://qiita.com/kakudaisuke/items/0af35aa9490b27ed5679) の通りです。
# Hash#each_key --失敗--
```ruby.rb
gets
p = gets.split.map(&:to_i)
dp = Hash.new(0)
dp[0] = 1
p.each do |x|
  dp.each_key do |y|
    dp[x + y] = 1
  end
end
puts dp.size
```
```error.rb
can't add a new key into hash during iteration (RuntimeError)
```
反復中にハッシュに新しいキーを追加できません
ああ、似ているけど`keys.each`と`each_key`は違うのですね。
# Array コピー
```ruby.rb
gets
p = gets.split.map(&:to_i)
dp = Array.new(p.sum.next, 0)
dp[0] = 1
p.each do |x|
  dt = dp.dup
  dp.each_index do |i|
    next if dt[i].zero?
    dp[x + i] = 1
  end
end
puts dp.count(1)
```
配列の場合、代入はできるのですが、正解を得るには`clone`又は`dup`にて配列をコピーする必要があります。
# Array 後ろから
```ruby.rb
gets
p = gets.split.map(&:to_i)
dp = Array.new(p.sum.next, 0)
dp[0] = 1
p.each do |x|
  p.sum.downto(0) do |i|
    next if dp[i].zero?
    dp[x + i] = 1
  end
end
puts dp.count(1)
```
`downto`や`each_index`を使用し、後ろから探索すると、配列のコピーが不要となります。
# まとめ
+ Typical DP A を解いた
+ Ruby に詳しくなった
【R】readrでの固定長データ読み込みでデータが抜け落ちる

固定長データの読み込みについて[過去の記事](https://qiita.com/kensukesuzuki04/items/f72f78ef9358c9df02d5)で紹介しました。例えば、固定長データの1行目とn行目が以下のようだとします。

1行目：aaabbccc
　　$\vdots$
n行目：aaabbcccdd

すなわち、最初の3文字が変数a、次の2文字が変数b、続き3文字が変数cという具合です。このとき、radrパッケージを使って読み込むとすれば

```R:readr_fwd.rb
d <- read_fwf(datafilename.txt, fwf_widths(c(3, 2, 3, 2), col_names = c("a", "b", "c", "d")))
```

となるわけです。

例えば、変数dが、1～(n-1)行目までは現れず、n行目で初めて現れるとします。そうしたときに、nが1,000よりも大きいとき、readrパッケージでは（デフォルトで）最初の1,000行を使ってデータ形式を予測（guess）するため、変数dがうまく読み込めず、抜け落ちてしまうことがわかりました。

こんなエラーが出ます


```
Warning: *** parsing failures.
row      col    expected actual         file
1000     d      1/0/T/F/TRUE/FALSE      3 'datafilename.txt'
```

この問題を回避するために、read_fwfのオプションで、guess_maxを指定してやると、うまくいくことがわかりました。たとえば、guess_maxを10,000とかにしてやるとうまくいきます。

```R:readr_fwd_guess_max.rb
d <- read_fwf(datafilename.txt, fwf_widths(c(3, 2, 3, 2), col_names = c("a", "b", "c", "d")), , guess_max = 10000 ) 
```
やさしめのGo Quiz

# 問題

つぎのコードを実行するとどうなるでしょう。

```go
package main

func main() {
	hello := func() {
		hello := func() {
			print("hello")
		}
		hello()
	}
	hello()
}
```

A. `hello` と出力される
B. `hellohello` と出力される
C. コンパイルエラー
D. 実行時エラー(panic)

# 解答と解説

<details><summary>ここを開いてください</summary><div>

**正解はAです。**

4行目の変数hello(以下hello4)と、5行目の変数hello(以下hello5)は異なるスコープで定義されており、つまりは別の変数です。
8行目で呼び出されているのはhello5で、10行目で呼び出されているのはhello4です。

hello4のやっていることを整理すると、以下のようになります。

1. `print("hello")` を呼び出す関数を変数hello(hello5)に代入する
2. 変数hello(hello5)を呼び出す

これを10行目で呼び出しているため、`print("hello")` は一度だけ呼び出されるため、 `hello` と出力されます。

同名の変数を再度宣言して代入することをシャドーイング(shadowing)と呼ぶそうです(Go固有ではなくプログラミング言語一般の用語)。
Effective Goの[Channels](https://golang.org/doc/effective_go.html#channels)で少しだけ触れられています。
Goは変数名が短いことが多いためか、シャドーイングをよく見かける気がします。
</div></details>

[明日](https://qiita.com/kmtr/items/d93e1c7eb175412fd638)へ続く
gnuplotでのエラー" warning: Skipping data file with no valid points"

`gnuplot`でファイル`OOO.txt`からx座標,y座標を読み込んで描画したい。

```txt
0 0
4 2
5 5
7 8
```
というファイル`point.txt`用意しました。
さっそく`gnuplot`で以下を実行しました

```
 gnuplot> set xrange [-1:5]                          
gnuplot> set yrange [-1:5]                          
gnuplot> plot 'point.txt' using 1:2 with linespoints
```
そうしたら以下のようなエラーがでてきました。

```
warning: Skipping data file with no valid points
```
原因をしばらく考えてみましたがわからなかったのでネットでいろいろ調べてみましたがあまり参考になるものは見つからず、、、
作成元が`VScode`だったのでそこをいろいろいじってみました。

`VScode`では簡単に**文字コード**,**改行コード**が選べると思います
どうやらこれが原因だったようで文字コードを`UTF-8`,改行コードを`LF`と設定したら無事に実行できました!




`gnuplot`はできることがいっぱいみたいなのでこれから学習していろいろなものを作っていきたいです！
[自分用メモ]ローカルのXAMPP環境で複数サイトを制作する方法

### 0. やりたいこと
- PHP学習用にxamppをローカル環境に入れているが、デフォルトの設定だと複数のWebサイトの制作ができない。
そこで、複数サイト制作を可能にするために、「バーチャルホスト」の設定をして、複数のドメインを使う設定を行った。
本記事はその作業の際の忘備録として残しておく。

### 1. 環境
- Windows10 
- xampp環境構築済み

### 2. そもそも「バーチャルホスト」って何？
#### バーチャルホストって何？  
> Apache バーチャルホスト説明書　https://httpd.apache.org/docs/2.4/ja/vhosts/  
> バーチャルホストという用語は、1 台のマシン上で (www.company1.com and www.company2.com のような) 二つ以上のウェブサイトを扱う運用方法のことを指します。
  
test1.comやtest2.com等、複数のドメインを運用していた場合、それぞれドメインごとにサーバを建てるのではなく、1台のWebサーバで複数のドメインのサービスを構築しよう！ということが出来る。

#### 図はこちら
> 【Apache】virtual hostでの複数URL運営
> https://www.toyo104-memo.com/entry/apache-virtual-host
> ↓↓図の画像リンク
> https://cdn-ak.f.st-hatena.com/images/fotolife/t/toyo--104/20180610/20180610001649.png

早速、やってみよう。

### 3. 手順
- **「localhost」とは別の"2つ目のドメイン"用のルートフォルダを作成する。**
  - xamppのインストールフォルダが「C:\xampp」なので、「C:\xampp\htdocs」以下に新しいフォルダを作成する。
  - 今回作成するドメイン名は「example.com」とします。

- **バーチャルホスト設定ファイル編集の有効化：「C:¥xampp¥apache¥conf¥httpd.conf」の編集**
  - バーチャルホストの編集ファイルが有効になっているか確認  
  - 「Include conf/extra/httpd-vhosts.conf」部分の先頭のコメントアウト「#」があったら削除しておく


```
# Virtual hosts
Include conf/extra/httpd-vhosts.conf
```
- **バーチャルホストを有効化：「C:\xampp\apache\conf\extra」配下の「httpd-vhosts.conf」を編集**
  - 20行目付近: ```##NameVirtualHost *:80```の##をコメントアウト
  - ファイルの一番最後に有効にしたいドメインの情報を記述  

```
<VirtualHost *:80>
    DocumentRoot "C:\xampp\htdocs\example.com"
    ServerName example.com
</VirtualHost>
```

・DocumentRoot：ドメインの一番上のルートフォルダのパス
・ServerName：ルートフォルダに紐づけられるドメイン名

- **hostsファイル＜host＞にドメインを追加**
  - 「C:\WINDOWS\system32\drivers\etc」下の「hosts」ファイルを編集し、新しく追加したドメインを記述
   
```
127.0.0.1 example.com
```
XAMPPを再起動すると、ドメインが有効になる。

### 4. まとめ
複数のサービスを同時に開発することもあるので、この手順はよく使う。
自分用メモです。
rails APIモード　devise

手順だけ

```terminal:ターミナル
rails new devise_token_auth --api -d mysql
```

```terminal:Gemfile
# トークンベースの認証を行うためのgem
gem 'devise'
gem 'devise_token_auth'
```

```terminal:ターミナル
$ bundle install
$ rake db:create
$ rails g devise:install 
```

```
$ rails g devise_token_auth:install User auth
```
```
$ rails g controller api/auth/registrations
```

```ruby:api/auth/registrations_conroller.rb
module Api
  module Auth
    class RegistrationsController < DeviseTokenAuth::RegistrationsController
      private
      def sign_up_params
        params.permit(:first_name, :last_name, :email, :password, :password_confirmation)
      end
      def account_update_params
        params.permit(:first_name, :last_name, :email)
      end
    end
  end
end
```

```ruby:config.eb
Rails.application.routes.draw do
  namespace :api do
    mount_devise_token_auth_for 'User', at: 'auth', controllers: {
        registrations: 'api/auth/registrations'
    }
  end
end
```
リクエストごとに token を新しくしない、変更頻度の設定を決める

```ruby:config/inizialize/devise_token_auth.rb
  ...
  config.change_headers_on_each_request = false
  config.token_lifespan = 1.month
  config.headers_names = {:'access-token' => 'access-token',
                          :'client' => 'client',
                          :'expiry' => 'expiry',![スクリーンショット 2020-12-06 23.13.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/9812bd33-0c32-b768-4e99-e2544876a1a7.png)

                          :'uid' => 'uid',
                          :'token-type' => 'token-type' }
 ...
```

```ruby:model/user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  include DeviseTokenAuth::Concerns::User
end
```
:trackableがあるとSessionのcreateがうまく行かないので一応削除。

postmanで確認してみる
#### 新規登録
![スクリーンショット 2020-12-06 22.51.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/f12e4dd9-b0f6-98fe-06a5-52a29d64b13d.png)
####ログイン

Headerに```Content-Type```を```application/json```として登録
そして確認
![スクリーンショット 2020-12-06 23.12.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/9231c28a-844d-87be-ca29-78469050e900.png)