OmniAICreator/Qiita-1.07M huggingface dataset:
【KMapper】プロパティにエイリアスを貼る

自作の`Kotlin Object` to `Kotlin Object`マッパー、`KMapper`の機能紹介です。

- [GitHub ProjectMapK/KMapper: Mapper Libraly for Kotlin\.](https://github.com/ProjectMapK/KMapper)
- [JitPack ProjectMapK / KMapper](https://jitpack.io/#ProjectMapK/KMapper)

バージョンは`KMapper 0.15`で書いています。

# プロパティにエイリアスを貼る
`KMapper`ではゲッターやパラメータにマッピング時にのみ使う名前（= エイリアス）を付けることができます。
この機能により、ソースとマップ先で名前が異なるフィールドへのマッピングや、バッキングプロパティを用いて初期化[^hosoku]を行うことができます。

[^hosoku]: 機能としては提供していますが、基本的にはファクトリーメソッドを利用する方が効率的です。

## ゲッターにエイリアスを貼る
`KGetterAlias`アノテーションをゲッターに振ることで、ソースのプロパティ名にエイリアスを貼ることができます。
以下の例では、`Src`と`Dst`でそれぞれプロパティ名が異なりますが、エイリアスによってマッピングを行うことができます。

```kotlin
data class Src(@get:KGetterAlias("barArg") val fooArg: String)
data class Dst(val barArg: String)

val src: Src = /* 生成処理 */
val dst: Dst = KMapper(::Dst).map(src)
```

## パラメータにエイリアスを貼る
`KParameterAlias`アノテーションをパラメータに振ることで、マップ時の引数にエイリアスを貼ることができます。
以下の例では、バッキングプロパティ`_fooArg`に引数を受け、それを用いて外部向けに公開する`fooArg`を初期化しています。

```kotlin
data class Src(val fooArg: String)
data class Dst(@param:KParameterAlias("fooArg") private val _fooArg: String) {
    val fooArg = /* _fooArgを用いた初期化処理 */
}

val src: Src = /* 生成処理 */
val dst: Dst = KMapper(::Dst).map(src)
```

### プロパティ名変換との関係
[`KMapper`ではプロパティ名の変換機能を提供しています](https://qiita.com/wrongwrong/items/5b915354e10c5781102a)が、パラメータにエイリアスを貼った場合、エイリアスもプロパティ名変換の影響を受けます。
以下の例では、エイリアスはキャメルケースで書き、変換関数によってスネークケースの引数と一致を取っています。

```kotlin
data class Src(val foo_arg: String)
data class Dst(@param:KParameterAlias("fooArg") private val _fooArg: String) {
    val fooArg = /* _fooArgを用いた初期化処理 */
}

val src: Src = /* 生成処理 */
val dst: Dst = KMapper(::Dst) { /* camel -> snake */ }.map(sc)

```

# 参考にさせて頂いた記事
- [プロパティとフィールド \- Kotlin Programming Language](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/properties.html#%E3%83%90%E3%83%83%E3%82%AD%E3%83%B3%E3%82%B0%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3)
【Kotlin】リフレクションでデフォルト引数を用いて関数を呼び出す

`kotlin-reflect`無しで呼び出しを行いたい場合は以下の記事をご参照ください。

https://qiita.com/wrongwrong/items/1906522f3ca758cf84d8

---

# TL;DR
- `isOptional`が`true`の`KParameter`を抜いて`callBy`することでデフォルト引数が用いられる
- `null`を登録した場合、パラメータの`nullability`に関わらず引数にそのまま`null`が渡されてしまい、デフォルト引数は用いられない

# サンプルコード
以下の通り`Sample`クラスのコンストラクタを、デフォルト引数有りで呼び出します。
サンプルコードでは、`isOptional == true`な`KParameter`を抜いた状態でコンストラクタを呼び出しています。

```kotlin:呼び出し対象クラス
data class Sample(
    val arg1: String,
    val arg2: String,
    val arg3: String = "default"
)
```

```kotlin:デフォルト引数を用いて対象のコンストラクタを呼び出す様子
val constructor = ::Sample
val argumentsMap = constructor.parameters
    .filter { !it.isOptional }
    .associateWith { it.name!! }

val result = constructor.callBy(argumentsMap)

println(result.arg3) // -> default
```

## 引数にnullを渡した場合
以下のように、引数に`null`を渡した場合は`IllegalArgumentException`になり、デフォルト引数は用いられません。

```kotlin
val constructor = ::Sample
val argumentsMap = constructor.parameters
    .associate {
        if (it.isOptional) {
            it to null
        } else {
            it to it.name
        }
    }

// java.lang.IllegalArgumentException: Parameter specified as non-null is null: ...
val result = constructor.callBy(argumentsMap)
```
VSCユーザーがLaravelのデータベース接続設定でエラーが出た時、確認すべきこと

こんにちは！今回がエンジニア初学者がついうっかり詰まってしまった初歩的なエラーとその原因をご紹介していきたいと思います。
#LaravelのDB接続設定エラー
入力した項目は合っているはずなのに、なぜかDB接続できない。

そんな時は、もう一度書き込んでいるファイルが正しいか確認してみてください！
もしかしたら`.env`ファイルではなく`.env.example`に設定を書き込んでいるかもしれません。
DB接続設定を書き込むのは`.env`ファイルです！

#なぜこのエラーにハマったのか
原因は、普段使用しているVisualStudioCode（以下VSC）のクイックオープン（Cmd + P）でファイル検索をした時に、`.env`が引っ掛からず、ついうっかり検索結果に出ていた`.env.example`を私が`.env`だと誤認したからでした。

#対応策
なぜ`.env`ファイルが検索結果に出なかったのか。
それはVSCの設定で.ignoreファイルと.gitignoreファイルを検索対象から外すようにしていたからです。
検索対象に入れたい場合は、VSCの環境設定に入って検索ボックスから`Search:Use Ignore Files`を検索し、**チェックを外しておくようにしましょう。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394234/53cdc369-58d7-8a4d-d642-73932fad623b.png)
Jupyter Notebook 使い方基礎

#Jupter Notebook概要

本記事では対話型シェルのうち最も広く使われていると思われるJupyter Notebookの基礎をメモします。

対話型シェルは以下の様な点からコーディング環境に優れている。

1. コマンドの履歴を簡単に追える
2. インプットとアウトプットが簡単に反映、確認できる　（グラフ、画像の組み込みも容易)
3. コード内容の説明が容易

Jupter NotebookではUI elementやHTML, JavaScriptに至るまでウィジェット機能を用いることでコードファイル内に組み込むことができる。

インストール方法参考 -> [図解！Jupyter Notebookを徹底解説！(インストール・使い方・起動・終了方法)](https://ai-inter1.com/jupyter-notebook/)


#Cell Type

Jupter Notebook上では以下のようなCell Typeが選択できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560775/b443470f-e95e-b4dc-6951-fb47b49457c2.png)


**CODE CELL**

任意のPython Codeを記入することができるCell。Shift+Enterでコード内容を実行することができ、対応する結果がOutput Cellに出力される。

**MARKDOWN**

Jupyter Notebookはコード内容の説明に優れており、その理由はこのMarkdown Cellにある。
Markdown CellではMarkdown用のコマンドまたはHTMLを用いてコード内容の説明を記載できる。また、MathJaxを用いたLaTex形式の数式も記載可能であるため、汎用性が高い。

**RAW**
特に何のコマンドもなく、フラットにテキストを記載できる。

**HEADING**
コード説明の上でのヘッダー構造を簡単に作成できる。MARKDOWN CELLでも同様に記載可能。


#キーボードショートカット

Jupyter Notebookを用いる上でのショートカットは以下のノートブック上のキーボードを押すことで確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560775/621d6c41-6561-4c9a-edeb-1062973fb973.png)

使用頻度が高いものを以下にメモする。

|キーボード|ショートカット内容|
|:---|:---|
|Shift+Enter|選択cellを実行する。|
|b|現在選択しているCellの下に新規にcellを追加する。|
|a|現在選択しているCellの上に新規にcellを追加する。|
|d-d|現在選択しているCellを削除する。|
|1-6|自動的に#を数字の数だけマークダウンセルに記載し、ヘッダーを作成する。|
|m|選択CellをMARKDOWN CELLに変更する。|
|y|選択CellをCODE CELLに変更する。|
|c|選択Cellをコピーする。|
|v|コピーしたCellを貼り付ける。|
|0-0|kernelをリスタートする。|
|i-i|コードの実行を停止する。|
|s|Notebookを保存する。|

# Markdown cellの書き方

ほとんどの記載方法はQiitaでの表現と同じ。

|記載表現|Markdown記法|
|:------|:-------|
|イタリック体 / *Hello*|\*Hello*|
|ボールド / **Hello**|\**Hello**|
|取り消し線 / ~~Hello~~|\~~Hello~~|
|URL /[Google](http://www.google.com)|\[URL text](http://www.google.com)|
|Latex体/$\LaTeX$ |\$\LaTeX$|
|改行 |改行したい文章の下に空白ラインを1行追加する。|
|ヘッダ | ヘッダーに記載したい文章の最初に"#"を付ける。"#"の数でLevelを変更可能。1-6のキーボードショートカットでも同様の記載が可能。|
|引用、転載 | 文章の初めに"**>**"を記載する|
|リスト | 文章の初めに"*"を記載すると●表記でのリスト。文章の初めに"1."等数字を記載すると数字表記でのリスト。それぞれキーワードの後ろに空白が必要であることに注意。|
【LINE】LIFFアプリを試してみる~セットアップまで~

## 概要

- LIFFアプリとはLIFF(LINE Frontend Framework)を使ったアプリのことでLINEのトーク画面にWebアプリを表示することができます
- さらにそのWebアプリからLINEの情報を取得したりメッセージを投稿するなどLINEと連携することができます
- この記事ではLIFFを使った実装まではふれずアカウントの設定などの事前準備までを紹介します
- 公式ドキュメント
    - https://developers.line.biz/ja/docs/liff/overview/

## 手順

- まずはLINEのIDでLINE Developperにログインします
    - https://developers.line.biz/ja/
    - 初回の人は必要事項を入力して登録してください

<img width="864" alt="スクリーンショット 2020-03-20 23.24.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/607e38ad-5571-0263-124b-de099e3abc83.png">

- ログインできたら「新規プロバイダー作成」からプロバイダーを作成します

<img width="683" alt="スクリーンショット 2020-03-20 23.27.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/49594c9c-bcc3-93e5-abfd-17442bb0d218.png">

- 次にチャネルを作成します
- 「LINEログイン」を選択してください

<img width="742" alt="スクリーンショット 2020-03-20 23.34.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/dcee1e80-8853-86c7-7854-cb5939f6bc9a.png">

- 必要事項を入力して作成します

<img width="503" alt="スクリーンショット 2020-03-20 23.40.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/4c28a234-b9d7-7a59-b2bb-f23bd034e7cb.png">
<img width="502" alt="スクリーンショット 2020-03-20 23.40.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/b4508d87-1929-30aa-7f40-2324f31c5cd5.png">

- チャネルができたらLIFFタブからLIFFの設定を追加します
    - 「サイズ」はLINEのトーク画面に表示する時のサイズです
        - 後からでも変えられるのでそれぞれ試してみてください
    - 「エンドポイントURL」はトーク画面に表示するLIFFアプリ(Webページ)のURLです
        - 今回はまだ作っていないのでとりあえずQiitaのページを出してみます
    - 他の項目の詳細は公式のドキュメントをご参照ください
        - https://developers.line.biz/ja/docs/liff/registering-liff-apps/#registering-liff-app

<img width="708" alt="スクリーンショット 2020-03-21 0.02.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/19954ea6-3b14-6b96-79a1-5e25e1b30613.png">

- 必要事項を入力して追加を押します

<img width="503" alt="スクリーンショット 2020-03-21 0.09.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/b2288af3-7751-6201-6d8f-0268b844f901.png">

- 作成が完了するとURLスキームが表示されます
    - これにアクセスすることでLIFFアプリにアクセスできます

<img width="542" alt="スクリーンショット 2020-03-21 0.13.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/c1ce31fa-1897-0c20-f666-9f206806cf94.png">

- LINEのトーク画面にURLスキームを投稿しアクセスしてみましょう

![Screenshot_20200321-001834.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/e26dcc8c-81d2-a27a-f3f2-69652df3c747.png)

- 初回の場合アクセス許可が求められるので許可します

![Screenshot_20200321-001931.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/4bf79c90-d5cf-3da4-2998-b7738f86f037.png)

- うまくいけばQiitaのページが表示されるはずです

![Screenshot_20200321-001953.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/cd8da3f5-cb02-c0ad-396c-54160e2b3ac3.png)

## まとめ

- 今回はセットアップのみで暫定でQiitaのページを出すところまでできました
- 次回以降でLIFFアプリを作成しトーク画面に表示できるようにしてみます

## 続編

- [【LINE】LIFFアプリを試してみる~ユーザ情報の取得とトークへの送信~](https://qiita.com/ozaki25/items/63b9dd5e3bc2f9224b3e)
Nimpyでnimからpythonを呼ぶ

# 概要
前提として。
Nimの開発案件が立ち上がったが、統計処理を簡単に扱いたい要件があるのでpythonを気軽につかいたい需要が生まれたのでnimpyでなんとかならないか技術要求が生まれた。だがいろいろ辛かったのでそれについてまとめた。苦心した人の助けになれば。という記事です。

# nimpyとは
> Native language integration with Python has never been easier!

nimからpythonを呼んだり、pythonからnimを呼べるインターフェイスを提供するライブラリです。
pythonからnimを呼ぶ事例はたくさんみつかったけど、nimからpythonを呼ぶ実例がなかったので試してみた。というか必要になったので試してみた。
どうやら `pyImport` で呼べるようだ。

# pyImport
nimpyは `nimble install nimpy` すると以下のように標準にインストールされたpythonモジュールが利用できる。（macではなぜかnumpyが標準モジュールで入っている）

```nim
pyImport("numpy")
```

だが、sklernなどのライブラリを利用したくてもOS標準のpythonを利用するのでできない。
そんなときは、pythonのPATHを通す他ない。
そのためのメソッドがある。

```nim
import nimpy
import nimpy/py_lib as pyLib
pyLib.pyInitLibPath("python path")
discard pyBuiltinsModule()
```
この構文で呼び出すことで呼び出すpythonを指定できる。だがこれは、lipythonのPathを指定する必要がある。
nimpyのコードを読むと、こちらで読み取るには `dylib` で生成されたpythonの指定が必要らしい。
pyenvでインストールした環境では、 `libpython**m.dylib` という 形で生成されたlibpythonというものがなかった。
まずは、生成する必要があったので以下を実行。

```bash
CONFIGURE_OPTS="--enable-shared" pyenv install {version}
```

すると `libpython**m.dylib` のようなファイルが生成されるのでそのパスを `pyLib.pyInitLibPath`
で指定すると、要求したPythonのモジュールの挙動や pip でインストールしたモジュールの利用ができた。

Docker環境などで実行すれば滞りなく立ち上げられたかもしれませんが、ローカルでの実行で詰まってしまったのでそのための知見になればです！

# まとめ
Nimっていいなと思いました。
Android StudioのFlutterに関するPreferencesについて

# 各項目について
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30620/b324e1be-fafc-bcf9-c8bc-d83f4118ccef.png width="400px">

## General
### Report usage information to Google Analytics
Google Analyticsに使用状況を送信するかどうか。

## App Execution
### Enable verbose logging
詳細なログを出力するかどうか。
ONにすると、ビルド時とかにも膨大な量のログが出力されるようになる。

### Perform hot reload on save
保存時にホットリロードする。

### Show structured errors for Flutter framework issues
TBD

### Open Flutter inspector view on app launch
シミュレーターなどでアプリを実行させたときに、右サイドにあるFlutter Inspector画面を表示させるかどうか。

### Disable tracking widget creation locations
TBD

## Editor
### Show UI Guides for build methods
Widgetの階層のラインを表示するかどうか。
↓このライン。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30620/77ed6ecf-3386-8fdc-cd84-d9e8ac950b45.png width="40px">


### Show closing labels in Dart source code
閉じ括弧のあとにラベルを表示するかどうか。
↓このラベル。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30620/2909e458-aa57-bf96-ed08-6aaeeb1e73c7.png width=250px>


### Format code on save
保存時にコードフォーマットをかける。

#### Organize imports on save
TBD

## Bazel
### Always suggest multiple run configurations for test code


## Experiments
### Enable code completion, navigation, etc. for Java / Kotlin (requires restart to do Gradle build)
TBD

### Enable Hot UI (an early preview of property editing in the outline view)
TBD
Vue.jsのコンポーネントでv-modelを使う

自作したコンポーネントにもv-modelを実装できる。
その実装方法を説明する。

[公式ドキュメント](https://jp.vuejs.org/v2/guide/components.html#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%A7-v-model-%E3%82%92%E4%BD%BF%E3%81%86)を参考に[サンプル](https://github.com/usuba-777-314/vue-checkbox-sample)を作成した。

文字入力UIのデザインを統一する想定で、UiTextInputというコンポーネントを作成する。
文字入力UIのデザインを統一するために実装する機会は多そう。そうでもない？Vuetifyを使う？

完成イメージ
![サンプル.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114918/3112c9da-43e7-27ad-2ef6-c24217afa14e.gif)

結論は[こちら](#結論)

# UiTextInputの実装

v-modelを実装するには、

* propsプロパティにvalueを設定して、親コンポーネントから値を受け取る。
* inputイベントを$emit（通知）して、親コンポーネントに変更後の値を渡す。

必要がある。

そのため、computedにgetter/setterを作成し、inputのv-modelとの値の受け渡しを行うようにした。

* getterでpropsのvalueを返却して、親コンポーネントから値を受け取る。
* setterでinputイベントを$emitして、親コンポーネントに変更後の値を受け渡す。

実装したソースコードが以下である。

```vuejs
<template>
  <input v-model="text" placeholder="入力してください">
</template>

<script>
export default {
  props: {
    value: {
      type: String
    }
  },

  computed: {
    text: {
      get() {
        return this.value;
      },
      set(text) {
        this.$emit("input", text);
      }
    }
  }
}
</script>

<style scoped>
input {
  display: block;
  border-width:0px;
  border-style:None; 
  font-size: 18px;
  background-color: rgba(0,0,0,0);
  outline: 0;

  border-bottom: 1px solid #d0d0d0;
}
</style>
```

# 使い方
通常のinputのv-modelと同様に使用できる。
UiTextInputコンポーネントを呼び出して、v-modelに値を指定する。

```vuejs
<template>
  <div>
    <h2>v-modelのサンプル</h2>

    <div class="field">
      <label>名前 </label>
      <UiTextInput v-model="text" class="input" />
    </div>

    <p v-if="text">こんにちは、 {{text}} さん！</p>
  </div>
</template>

<script>
import UiTextInput from "./UiTextInput.vue";

export default {
  components: {
    UiTextInput
  },

  data() {
    return {
      text: ""
    };
  }
}
</script>

<style scoped>
.field {
  display: flex;
}

label {
  flex-basis: 100px;
}

.input {
  flex-grow: 1;
}
</style>
```

# データフロー

文章とソースコードによる説明だとイメージしづらいかもしれないので、補足としてデータフローで図解する。

__使用する側（親コンポーネント）からUiTextInput（子コンポーネント）へ値を渡す__

![コンポーネントのv-model-親から子へ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114918/1211fdee-143e-7a4b-1bc8-40de686816ef.jpeg)

__UiTextInput（子コンポーネント）から使用する側（親コンポーネント）へ値を渡す__

![コンポーネントのv-model-子から親へ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114918/81318416-9c5f-d099-6c51-c06d4dabe445.jpeg)

# 結論

コンポーネントでv-modelを実装する際は、

* propsのvalueで、親コンポーネントから値を受け取る。
* inputイベントを$emit（通知）して、親コンポーネントに値を渡す。

をすれば良い。
【Laravel】Herokuでファイルアップロードのサイズ上限値を変更する(Apache)

# 事象確認

post_max_sizeはデフォルトで8Mが設定されているようです。

```shell

$ heroku logs -t
2020-03-20T14:58:54.361490+00:00 app[web.1]: [20-Mar-2020 14:58:54 UTC] PHP Warning:  POST Content-Length of 9423684 bytes exceeds the limit of 8388608 bytes in Unknown on line 0
```

# 手順

公式ドキュメントによると、`.user.ini`ファイルを作成してあげれば良いようです。

> Customizing Web Server and Runtime Settings for PHP
https://devcenter.heroku.com/articles/custom-php-settings#php-runtime-settings

publicディレクトリに`.user.ini`ファイルを作成し、POSTの最大サイズとファイルの最大サイズを設定します。
git pushして変わっていることを確認しましょう。

```public/.user.ini
post_max_size = 20M
upload_max_filesize = 5M
```
html5のmeta tag 

#ドキュメント・タイプ・デクレア
<!DOCTYPE html>
これは、XMLとHTMLが合わさって形成された、新時代のハイパー・テキスト・マークアップ・ラングエッジの、html5、を意味する、DTDで、XHtmlや、HTML4.0などでは、他に、XMLリンクなどを描いた方が良かったのに対し、簡素に簡略化した、上記のタイプが、何も纏わない形で、html5を表すこととなることを、W3Cで決めたためである。
これには、html4.0 strict(厳格モード、トランジションなど動きのあるものを排除）とHTML4.0Transitional（少し間違いがあっても動く、トランジション可能）や、XHTML1.0Basic、XHTML1.0Strictなど、より幻覚になったモードを表す、DTD、をより、大きな間口で、CSSや、Javascriptと連携の取りやすいものとして、動作する宣言となった。

#meta charset tag 
![スクリーンショット 2020-03-21 0.08.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606144/2eecdcfa-4a6a-ec0c-4989-2a061ae2e5a3.png)
上記の他に、utf-8を、Shift_JISに直すと、Windows、互換で動くほとんどの、テキストエディタに対応する、文字コードとなる。utf-8は、OSXに標準の文字コード。

#meta name tag
![スクリーンショット 2020-03-21 0.14.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606144/a1bcdcfa-7c98-c366-9391-9212983bed40.png)
これは、ロボット型検索エンジンに、index目次に、follow、ピックアップしてくれ、というオーダーを出すタグ。反対に、ページが多かったり、iframeの中身だったりして、拾われたくない場合は、index,nofollow or noindex,nofollow、などとすること有効。
![スクリーンショット 2020-03-21 0.29.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606144/a4b00283-40b3-39c1-5b1e-3edf133c6bff.png)
サイトの持ち主、出版者、コピーライト、サイトの説明、キーワードなどを記す。
viewportタグは、モバイル・ブラウザーに完全対応するための必須タグで、width=device-widthは、デバイスの幅に合わせて、initial-scale=1は、初期設定の倍率を、1：1にする。他、initial-scale=0.7などと縮小したり、initial-scale=2.0と拡大したりできる。minimum-scale, maximum-scaleは、ピンチイン・ピンチアウトの最小値/最大値、user-scalable=noは、拡大縮小できない、user-scalable=yesは拡大縮小可能にするタグ。

#meta http-equiv tag
![スクリーンショット 2020-03-21 0.46.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606144/76e62230-3b97-4042-0a42-1896344dba60.png)
テキストで書かれた、HTML文書に書いた方がいい、それぞれの、mime-typeを表す文字列。
![スクリーンショット 2020-03-21 0.55.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606144/731c68c0-82bc-bd06-7b41-12db3e968f4d.png)
X-UA-Compatibleは、IEでは、edge、搭載されていなければ、それに準ずる、インターネット・エクスプローラーのバージョン、chrome=1、はchromeにも準拠する。
Expiresは、キャッシュする時間（秒）、Page-Enterは、ページの開き方、0.8秒間で、中が最後に開くが上記。
最後は、セキュリティー、ポリシー。他のサーバーから、スタイルや、スクリプトを呼ぶときは、ドメイン名を、それぞれのタイプにあったものを入れておく、'self'は自分のサイトないで完結という意味。ワイルドカードは、＊;で、Anyとなる。
yukicoder No.1013 〇マス進む

問題URL : [yukicoder.me/problems/no/1013](https://yukicoder.me/problems/no/1013)
####解説
頂点 $i$ から頂点 $i+T_i$ へ辺を張ったグラフを考える。
求めるものは $k=1, 2, \dots, N$ それぞれについて、頂点 $k$ から辺に沿った移動を $K$ 回して着く頂点である。
このグラフは周期 $N$ で同じパターンが繰り返されるので、頂点 $1, 2, \dots, N$ にだけ注目すればよい。
$K$ 回移動した後の位置はダブリングで求まり、計算量は $O(N\log K)$ である。

提出コード : [yukicoder.me/submissions/447245](https://yukicoder.me/submissions/447245)
Synology Dockerでのjenkinsの起動オプション

# 前提
Synology NAS DS218+で遊んでいます。
NAS ：Synology DiskStation 218+
　　　 RAM：10GB（2GB+8GB）
　　　 HDD：4TB + 3TB

8GBはインストールはできるけどサポート外になるのでお気をつけて
Synology Docker では、使えないオプションを設定するので、sshで接続してコマンドを叩いてやります。

# 概要
Synology Docker での jenkins 起動オプションを考えてみた

# 詳細
## Docker jenkins から Docker コンテナを起動するための設定

`sudo`
`-u root`
`-v /var/run/docker.sock:/var/run/docker.sock`


## jenkinsの時間を日本時間にしたい

`-e TZ=Asia/Tokyo`


## 8080ポートと50000ポートをbridgeの別ポート番号に設定

`-p xxxxx:8080 -p zzzzzz:50000`

## jenkinsのjenkins_homeをSynology NASの共有フォルダ[docker]以下に設定する
事前に[docker/jenkins_home]を[volume1]に作成し(もちろんその他のvolumeでも良い)

`-v /volume1/docker/jenkins_home:/var/jenkins_home`
`-v /volume1/docker/jenkins_home/workspace:/var/jenkins_home/workspace`

work_spaceもNASのフォルダに保存しておく( jenkins_home以下なので、本来要らないはずなのになぁ... )


# まとめるとこんな感じ

`sudo docker run -u root -d  -e TZ=Asia/Tokyo -p xxxxx:8080 -p  zzzzz:50000 --name jenkins-blueocean_Test -v /volume1/docker/jenkins_home:/var/jenkins_home -v /volume1/docker/jenkins_home/workspace:/var/jenkins_home/workspace -v /var/run/docker.sock:/var/run/docker.sock jenkinsci/blueocean`

それでは、すばらしいSynology NASライフを
Next.js(React)でCSSとSASS(SCSS)、Bootstrapを使う

# Next.jsでCSSとSASS(SCSS)、Bootstrapを使う

next.jsでreactのSPAを作り始めたのですが、css, sass, bootstrapの設定周りですこしつまづいたのでメモ。

## Next.jsのプロジェクト作成
プロジェクト作成

```
yarn craete next-app
```

これでNext.jsのプロジェクトが作成されます。 `yarn dev` で起動できます。

## CSS, SASSの設定
css, sass(scss)ファイルをimportできるようにします。

まずはパッケージインストールします。

```
yarn add @zeit/next-css

yarn add @zeit/next-sass node-sass
```

### next.config.jsの作成
プロジェクトのルートに `next.config.js` ファイルを作成します。これはnext.jsの設定ファイルです。

以下はcssとsassどちらもimportできるような設定です。

```next.config.js
const withSass = require('@zeit/next-sass');
const withCSS = require('@zeit/next-css');
module.exports = withCSS(withSass());
```

## Bootstrapの設定

Bootstrapを入れます。

```
yarn add bootstrap

yarn add react-bootstrap
```

Bootstrapを適用します。
アプリ全体に適用したいので、グローバルに設定したいです。

まず、`/pages/_app.js` を作成します。
next.jsでは、全体設定のためのインターフェースとして `_app.js` で設定できるようになっています。

`_app.js` でbootstrapをimportすることでアプリ全体に適用していくのです。

```/pages/_app.js
import 'bootstrap/dist/css/bootstrap.min.css';

function MyApp ({ Component, pageProps }) {
  return <Component {...pageProps} />
};

export default MyApp;
```


## ページを作ってみる
では正しく設定できているか実際にページを作って確認してみましょう。

```jsx:/pages/login.js
import {Container, Row, Col, Form, Button} from 'react-bootstrap';

const Login = () => {
  return (
    <Container className='login'>
      <Row>
        <Col className='text-center'>
          <h2>ログイン</h2>
        </Col>
      </Row>
      <Row>
        <Col>
          <Form className='col-6 offset-3'>
            <Form.Group>
              <Form.Control type='text' name='id' />
            </Form.Group>
            <Form.Group>
              <Form.Control type='password' name='password' />
            </Form.Group>
            <Form.Group>
              <Form.Control type='submit' name='submit' value='ログイン' className='btn btn-primary' />
            </Form.Group>
          </Form>
        </Col>
      </Row>
    </Container>
  );
};

export default Login;
```

### 確認してみる
起動します

```
yarn dev
```

`localhost:3000/login` にアクセス。

![スクリーンショット 2020-03-20 23.55.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265038/524e9159-d97e-714e-612c-355526cd2d4e.png)

わあい
Python の SQLite3 データベースで LIST型 や BOOL型 を扱う方法

## はじめに
sqlite3 にbool型 や list型 は存在しない。このままだと、JSONを読み込む際などに不都合がある。それらをsqlite3の組み込みの関数を用いて解決する

## 実装

Pythonの型をSQLiteで使える型に変換するためには`sqlite3.register_adapter`を使う。これはユーザ定義型でも扱うことができる。反対に、SQliteからPythonに変換するためには、`sqlite3.register_conveter` を使う。`sqlite3.register_adapter` と `sqlite3.register_conveter` はペアになっており、片方だけでは相互に変換することができない。この2つを合わせて適合関数と呼びます。

```python
import sqlite3

# ユーザ定義型 その1
# データベース内部ではセミコロン区切りのテキストになっている、。区切り文字は変更してもいい
sqlite3.register_adapter(list, lambda l: ';'.join([str(i) for i in l]))
sqlite3.register_converter('LIST', lambda s: [item.decode('utf-8')  for i in s.split(bytes(b';'))])

# ユーザ定義型 その2
sqlite3.register_adapter(bool, lambda b: str(b))
sqlite3.register_converter('BOOL', lambda l: bool(eval(l)))
```

## 使用例

データベースに接続する際の、`detect_types=sqlite3.PARSE_DECLTYPES` は必須(カラムの型を読み取るようになる)

```python:test.py
import sqlite3

sqlite3.register_adapter(list, lambda l: ';'.join([str(i) for i in l]))
sqlite3.register_converter('List', lambda s: [item.decode('utf-8')  for item in s.split(bytes(b';'))])

sqlite3.register_adapter(bool, lambda b: str(b))
sqlite3.register_converter('Bool', lambda l: bool(eval(l)))

def main():
    conn = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
    conn.execute('''
    CREATE TABLE IF NOT EXISTS test_table (
        id      INTEGER PRIMARY KEY,
        list    LIST,
        flag    BOOL
    );
    ''')

    insert_data = [([1, 2, 3], True), ([4, 5, 6], False), (['hoge', 'fuga'], True)]
    conn.executemany('INSERT INTO test_table(list, flag) VALUES(?, ?)', insert_data)
    conn.commit()

    c = conn.cursor()
    for row in c.execute('SELECT * FROM test_table WHERE flag = "True"'):
        print(row)
        for item in row:
            print(f'{str(type(item)):15}:{item}')

if __name__ == '__main__':
    main()
```
```:out
(1, ['1', '2', '3'], True)
<class 'int'>  :1
<class 'list'> :['1', '2', '3']
<class 'bool'> :True
(3, ['hoge', 'fuga'], True)
<class 'int'>  :3
<class 'list'> :['hoge', 'fuga']
<class 'bool'> :True
```


## 参考文献
(Py2バージョン)
https://qiita.com/maueki/items/4aae7b2d9a34758ef465
(公式Docs)
https://docs.python.org/ja/3/library/sqlite3.html#using-adapters-to-store-additional-python-types-in-sqlite-databases
Rubyでシーザー暗号の解読

Rubyでシーザー暗号を解読して見た時のコードと解説をします。
##シーザー暗号とは？

そもそもシーザー暗号とはなにかなんですが、単一換字式暗号の一種らしいのですが、
簡単に言うと文字を特定数の文字ずらした際にそれが暗号鍵になる暗号の事です。


例)
暗号
hsnvld
2文字進めた文字が答えとなると
jupxnf
になります。

これをRubyですぐ表示できる様にアルゴリズムを書いてみました。

##Rubyでシーザー暗号の解読
暗号文に対して3文字進めるのが答えとします。
暗号文 hgmgkrd

```ruby
def decryption(char)
  char_ary = char.split("")#1文字ずつに分割する
  changed_char_ary = []#空の配列を用意する
  char_ary.each do |char|
    changed_char_ary << (char.ord - 3).chr
     #ordメソッドで整数にしchrメソッドで文字に変換する
　　　#空の配列に入れる
  end
  puts changed_char_ary.join
     # =>edjdhoa
     #joinメソッドで配列を連結して文字列にする
end

char = "hgmgkrd" #暗号文を変数に入れる
decryption(char)
```
[Rust] tuple struct, enumは暗黙にコンストラクタをクロージャとして定義する

__2020-03-21 追記__ tric さんが詳しいコメントをくださいました ([こちら](https://qiita.com/osanshouo/items/cad7fb3dc91a5e95e578#comment-8e12d4a1758aac3995e1)) ので, そちらもご覧ください. 本記事の用語法は不適切で, クロージャというより関数ポインタと呼ぶべきでした.

---

何が言いたいかというと, 次のコードを見てください ([PlayGround](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=%23%5Bderive(Debug)%5D%0Astruct%20Data(i32)%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20data%20%3D%20vec!%5B%202020%20%5D%3B%0A%20%20%20%20let%20data%20%3D%20data.into_iter().map(Data).collect%3A%3A%3CVec%3C_%3E%3E()%3B%0A%20%20%20%20println!(%22%7B%3A%3F%7D%22%2C%20data)%3B%0A%7D)).

```rust
#[derive(Debug)]
struct Data(i32);

fn main() {
    let data = vec![ 2020 ];
    let data = data
        .into_iter()
        .map(Data) // <- ここに注目!
        .collect::<Vec<_>>();
    println!("{:?}", data); // 出力: [Data(2020)]
}
```

`Data` はここで定義した struct の名前ですが, 同じ名前のクロージャ `Fn(i32) -> Data`として使うことができます. `struct Data(i32, f64)` だったら `Fn(i32, f64) -> Data` です.

enum でも同じようなことができます ([PlayGround](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&code=%23%5Bderive(Debug)%5D%0Aenum%20Data%20%7B%0A%20%20%20%20Number(i32)%2C%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20nums%20%3D%20(0..4).map(Data%3A%3ANumber).collect%3A%3A%3CVec%3C_%3E%3E()%3B%0A%0A%20%20%20%20println!(%22%7B%3A%3F%7D%22%2C%20nums)%3B%0A%7D)).

```rust
#[derive(Debug)]
enum Data {
    Number(i32),
}

fn main() {
    let nums = (0..4).map(Data::Number).collect::<Vec<_>>();
    println!("{:?}", nums); // 出力: [Number(0), Number(1), Number(2), Number(3)]
}
```

周知の事実だったらごめんなさい. 以上, 今日の収穫でした.


# 参考文献

* [WebとNativeのはざま: C++プログラマー向けRust 翻訳シリーズ12](http://hazama1616.blogspot.com/2016/03/crust-12.html)

## 追加分 (2020-03-21)

* https://doc.rust-lang.org/reference/expressions/struct-expr.html
[漏洞通告]CVE-2020-10673/jackson-databind JNDI注入导致远程代码执行

### 漏洞描述
近日,亚信安全网络攻防实验室跟踪到jackson-databind更新了1个jndi注入的黑名单类.如果在项目包中存在该类的jar包且JDK版本满足注入版本,则可以使用JNDI注入的方式导致远程代码执行.该类为`com.caucho.config.types.ResourceRef`.

### 漏洞编号
CVE-2020-10673
Jackson内部编号2660

### 漏洞威胁等级
中危

### 不受影响范围
jackson-databind >= 2.9.10.4
jackson-databind >= 2.10.0

### 漏洞验证
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/2c2f6ac0-76f8-75b7-d968-0836da7f9b23.png)

老邻居fastjson在1.2.66版本受影响
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/fc227b45-4620-ffa4-da36-1950658e6c6e.png)


### 修复建议
1.更新到最新版本
2.使用高版本JDK

### 时间轴
[0] 2020/03/17 FasterXML官方修复该漏洞
[1] 2020/03/20 亚信安全网络攻防实验室分析&复现该漏洞并发布漏洞通告

### Reference
https://github.com/FasterXML/jackson-databind/issues/2660
【今日のアブストラクト】Proving the Lottery Ticket Hypothesis: Pruning is All You Need【論文 DeepL 翻訳】

1 日 1 回 (努力目標) 論文の Abstract を DeepL 翻訳の力を借りて読んでいきます.

この記事は自分用のメモみたいなものです.
ほぼ DeepL 翻訳でお送りします.
間違いがあれば指摘していだだけると嬉しいです.

翻訳元
[Proving the Lottery Ticket Hypothesis: Pruning is All You Need](https://arxiv.org/abs/2002.00585)

# Abstract

### 訳文

宝くじ仮説 (Frankle and Carbin, 2018) は, ランダムに初期化されたネットワークが, 分離して訓練された場合, 元のネットワークの性能と競合することができるような小さなサブネットワークを含んでいると述べている. 我々は, さらに強い仮説を証明する (Ramanujan et al., 2019 でも推測されていたように), すべての有界分布と有界重みを持つすべてのターゲットネットワークに対して, ランダムな重みを持つ十分にオーバーパラメータ化されたニューラルネットワークは, それ以上の訓練を行わなくても, ターゲットネットワークとほぼ同じ精度を持つサブネットワークを含むことを示す.

### 原文

The lottery ticket hypothesis (Frankle and Carbin, 2018), states that a randomly-initialized network contains a small subnetwork such that, when trained in isolation, can compete with the performance of the original network. We prove an even stronger hypothesis (as was also conjectured in Ramanujan et al., 2019), showing that for every bounded distribution and every target network with bounded weights, a sufficiently over-parameterized neural network with random weights contains a subnetwork with roughly the same accuracy as the target network, without any further training.
[漏洞通告]CVE-2020-3761/CVE-2020-3794/Adobe ColdFusion 任意文件读取和任意文件包含

### 漏洞描述
2020年3月18日,Adobe官方发布针对Adobe Coldfusion的安全更新补丁,编号为APSB20-16.该漏洞同样为之前tomcat爆出过漏洞的AJP协议导致.

### 漏洞编号
CVE-2020-3761
CVE-2020-3794

### 漏洞威胁等级
高危

### 影响范围
ColdFusion 2016 Update13及之前版本
ColdFusion 2018 Update7及之前版本

### 漏洞验证
使用之前自研的AJP利用工具验证即可

文件读取验证

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/3ceb2551-d3ef-30e9-14d6-2513ab039bb6.png)

文件包含验证
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/b20a7e56-b8e7-68a1-f00b-4ae2d4c941ae.png)

### 修复建议
升级最新补丁APSB20-16
### 时间轴
[0] 2020/03/03  Adobe官方确认漏洞存在并开始着手修复；
[1] 2020/03/18  Adobe官方发布安全补丁。
[2] 2020/03/20  亚信安全网络攻防实验室分析&复现该漏洞并发布漏洞通告

### Reference
https://helpx.adobe.com/security/products/coldfusion/apsb20-16.html
Ubuntu 18.04 ネットワーク接続の完了待ちのために起動が遅い問題の対処

Ubuntu Server 18.04 LTS

```
$ lsb_release -a
(略)
Description: Ubuntu 18.04.4 LTS
(略)
$ uname -a
Linux kaen 4.15-0-88-generic #88-Ubuntu SMP Tue Feb 11 20:11:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
```
上記の環境で

`A start job is running for wait for network to be configured.`
が出て起動が遅い問題への対処法

#対処法1

```
~# systemctl disable systemd-networkd-wait-online.service
~# systemctl mask systemd-networkd-wait-online.service
```
を実行する(https://qiita.com/hatayan1126/items/c67f87a86f1538bb86af より引用)

#対処法2

https://askubuntu.com/questions/972215/a-start-job-is-running-for-wait-for-network-to-be-configured-ubuntu-server-17-1

によると、対処法1は望ましくなく以下のようにするべきであると記載されている。(記載は自身の環境に合わせて調整済み)

```
$ cat /etc/netplan/10-netcfg.yml
network:
    renderer: networkd
    version: 2
    ethernets:
        enp1s0:
            optional: true
        wlp2s0b1:
            optional: true
$ sudo netplan apply
```
上記により、起動時にOSが認識しているネットワークインタフェースは必ずしもネットワークに接続されている訳ではなく、接続を待つ必要が無い事をOS側に設定できると記載されている。
Python+OpenCVで品質を指定してJPEG画像生成

### 参考文献

本記事は以下のページを参考にしています。 

- [Python cv2.IMWRITE_JPEG_QUALITY() Examples](https://www.programcreek.com/python/example/70397/cv2.IMWRITE_JPEG_QUALITY)

### 1. データ準備
BSDS500というデータセットを使用するため、以下のサイトからダウンロード。

> https://github.com/BIDS/BSDS500
> P. Arbelaez, M. Maire, C. Fowlkes and J. Malik, "Contour Detection and Hierarchical Image Segmentation," *IEEE TPAMI*, Vol. 33, No. 5, pp. 898-916, May 2011.

今回使用するのは、`BSDS500/data/images`だけなので、必要なもののみ取り出す。
test内のファイルをtrainに移動する。

```:./data
.
└── BSDS500
    └── images
        ├── train   # train + test = 400 images
        └── val     # val          = 100 images
```

### 2. OpenCVによるJPEG画像の生成（保存）
OpenCVのimwrite関数を使用する。

```python
cv2.imwrite(<save_path>, <img>, [int(cv2.IMWRITE_JPEG_QUALITY), <jpeg_quality>])
```
**save_path**: 保存先のパス、**img**: 画像、**jpeg_quality**: JPEG画像の品質

### 3. サンプル
```
.
├── create_jpeg_image.py
└── data
    └── BSDS500
        └── images
            ├── train
            │   └── gnd
            └── val
                └── gnd
```

```python:create_jpeg_image.py
import os
import cv2
import argparse


def save_jpeg_images(src_path, dst_path, q=100):
    file_list = os.listdir(src_path)
    dst_path  = os.path.join(dst_path, 'q{}'.format(q))
    os.makedirs(dst_path, exist_ok=True)

    for file_name in file_list:
        im = cv2.imread(os.path.join(src_path, file_name))
        cv2.imwrite(os.path.join(dst_path, file_name), im, [int(cv2.IMWRITE_JPEG_QUALITY), q])

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--src_path', default='./data/BSDS500/images/val/gnd')
    parser.add_argument('--dst_path', default='./data/BSDS500/images/val')
    parser.add_argument('--q', type=int, default=10)
    args = parser.parse_args()

    save_jpeg_images(args.src_path, args.dst_path, args.q)
```
以上
Vimコマンド集

# 個人的Vim集（初心者向け）
最近Vimを操作することが多くなってきて、マウス操作にあぐらをかいてきた僕はまだまだ便利なコマンドを知らず都度都度調べながらやっていることが多いため、個人的メモとしてまとめていきたいと思います。

また、調べていて気づいたのですが、同じ操作でもコマンドが複数あるんです！なにがいいのか、などがまだまだわかんないので、とりあえず自分の得たものをまとめていきたいと思います。

[補足]コマンドが増えてきたらカテゴリでテーブルをわけていきたいと思います。

# 普段使うコマンド一覧（環境：Mac）

| 操作               |コマンド             |左記以外のコマンド     |
|:-----------------:|:------------------:|:------------------:|
|行を追加してInsertモード| o |                |
|最初の行に移動|gg  | |
|最後の行に移動| G |           |
| 指定の行に移動|　{num}G (num: 数値)|：{num}   |
| 行先頭に移動 | 0|       |
| 行末尾に移動 | $ |  |
|1単語先に移動| w | |
|1単語前に移動| b | |
|操作のやり直し|u|  |
|一行コピー| yy | |
|複数行コピー| {num}yy | [※補足1] |
|一単語コピー| yw |
|次の行にペースト|p| |
|前の行にペースト|P| |
|コピーしたものを複数回ペースト|{num}p|  |
| 一行削除(「コピー」に対して「カット」に位置する) | dd | |
| 複数行削除 | {num}dd | [※補足1] |
| 全て削除 | ggVGd | :%d |
| 一単語削除 | dw | |
| カーソル位置の単語削除 | x | |
| カーソル位置の前の単語削除 | X | |
| カーソル位置より後を削除| D | |

削除、コピーの操作は特に、コマンドを組み合わせて使っていますね。一つ一つのコマンドの意味を理解すると、理解が早くすすむと思いました。
思ったより複数のコマンドないじゃないか！と自分にツッコミました。。新しいものを使い次第どんどん更新したいと思います！！

### ※補足1：複数行を指定する方法

`{num}yy`や`{num}dd`は、指定したい行数がはっきりわかる時に便利です。ただ、指定したい行数がわからない時には、別の方法を用います。

 - ビジュアルモードで指定する
 1.指定したい最初の行にカーソルを移動する
 2.`shift + v`でビジュアルモードに変更
 3.コピーしたい範囲を選択する
 
 - 選択したい部分をマークする
 1.指定したい最初の行にカーソルを移動する
 2.`ms`と入力し、開始位置をマークする
 3.指定したい最後の行までカーソルを移動する
 4.コピーしたい場合は`y’s`、カットしたい場合は`d‘s`と入力

マークは、mコマンドというVimのマーク機能を使っています。

## 以前にコピーした履歴からペーストする
先に紹介したコマンドで可能なのはペーストの直前にコピーしたものが対象となっていています。そこで、「履歴一覧みたいなのあったらなぁ」と調べていたところ、ありました！！`:reg`と入力をしてみてください。すると以下が表示されると思います。

```
--- Registers ---
""   hoge1
"*   hoge2
"+   hoge3
"-   hoge4
"/   hoge5
"0   hoge6
"1   hoge7
"2   hoge8
"3   hoge9
"4   hoge10
"5   hoge11
"6   hoge12
"7   hoge13
"8   hoge14
"9   hoge15
":   hoge16
```
これは履歴一覧ですが、それぞれに役割があります。細かくは、わかりやすく書いてくださっているサイトがいくつかあったのでそちらを参考にしていただければと思います。

vimでは、yyでコピーをすると、レジスタに登録されます。現在のコピー情報は`0`というレジスタにコピーされるみたいで、上の例でいうと`"" hoge1`に該当するところに格納されます。

この履歴の中から貼り付けをしたい場合は、`p(P)`の前にレジスタを指定してあげるといいです。上の例で行くと、hoge3をコピーしたいと思った場合は、`"+p`と入力してあげます。

また、上記のレジスタ以外にもa-zを用いて指定してあげることができます。

```vim

# 「a」のレジスタをコピー時に指定
"ayy
# 「a」のレジスタからペースト
"ap
```
また、「a」のレジスタを指定した場合、`:reg`でみてみると、下に`"a   hoge`が追加されています。
# 更新情報
2020.3.20  記事の作成
2020.3.24  レジスタの利用
GitHubレポジトリ作成からpushまでを1コマンドで実行する

# 1. はじめに
- 新しく開発を始める際のGit関連の手順を簡略化したかった
- `~/.gitconfig`にレポジトリ作成からpushするコマンドを登録し、拡張サブコマンドとして実行できるようにした
- やってること
  1. GitHubにレポジトリ作成（Private or Public）
  2. `README.md`を作成
  3. `.gitignore`を作成（空ファイル）
  4. `git init`を実行
  5. `git add.`を実行
  6. `git commit -m "first commit"`を実行
  7. `git remote add origin XXXXXXXX`を実行
  8. `git push origin master`を実行



# 2. 準備

- `~/.gitconfig`に下記を追加する
  - init-ext-public: GitHubにpublicレポジトリを作成するサブコマンド
  - init-ext-private: GitHubにprivateレポジトリを作成するサブコマンド

```
[alias]
    init-ext-public = "!REPO=$(basename $PWD) GHUSER=$(git config --get user.name); curl -u $GHUSER https://api.github.com/user/repos -d {\\\"name\\\":\\\"$REPO\\\"} --fail; echo \"# $REPO\" >> README.md; git init; touch .gitignore; git add .; git commit -m \"first commit\"; git remote add origin https://github.com/$GHUSER/$REPO.git; git push origin master"
    init-ext-private = "!REPO=$(basename $PWD) GHUSER=$(git config --get user.name); curl -u $GHUSER https://api.github.com/user/repos -d {\\\"name\\\":\\\"$REPO\\\"\\,\\\"private\\\":\\\"true\\\"} --fail; echo \"# $REPO\" >> README.md; git init; touch .gitignore; git add .; git commit -m \"first commit\"; git remote add origin https://github.com/$GHUSER/$REPO.git; git push origin master"

```


# 3. 使い方例
- 新しく`testrepo`プロジェクトの開発を開始する場合（GitHubレポジトリはprivate）

```
$ cd /path/to/repo
$ mkdir testrepo && cd testrepo
$ git init-ext-private
```


# 参考
- [Is it possible to create a remote repo on GitHub from the CLI without opening browser?](https://stackoverflow.com/questions/2423777/is-it-possible-to-create-a-remote-repo-on-github-from-the-cli-without-opening-br)
- [コマンドラインでGitHubのリポジトリを公開もプライベートも作成する](https://2017.l2tp.org/archives/264)
GradleでJDKをダウンロードしてJREを作る

Javaのスタンドアロンアプリケーション配布をする場合、JREを同梱しておくと環境設定が要らなくなるのですが、そのためには各プラットフォーム向けのJREをアプリケーションに同梱する必要があります。
フルサイズのJREを同梱してもいいのですが、Java9以降はモジュールがサポートされているので、せっかくなら必要な分だけを入れたJREを作る方が望ましいわけですが、その場合には各プラットフォーム向けのJDKに入っているjmods以下のファイルが必要になります。

セットアップのために手動でJDKをダウンロードするのは意外と手間なので、build.gradleに以下のようなスクリプトを追加してみました。

```groovy
plugins {
  id "de.undercouch.download" version "4.0.4"
}

task prepareJDK{
  downloadAndExtractJDK("jdk/win",'http://download.bell-sw.com/java/11.0.6+10/bellsoft-jdk11.0.6+10-windows-amd64-full.zip')
  downloadAndExtractJDK("jdk/mac",'http://download.bell-sw.com/java/11.0.6+10/bellsoft-jdk11.0.6+10-macos-amd64-full.zip')
}
void downloadAndExtractJDK(jdkDir,url){
  def zipFile = "${jdkDir}/jdk.zip"
  if(file(zipFile).exists()==false){
    download {
      src url
      dest zipFile
    }
  }
  if(file("${jdkDir}/LICENSE").exists()==false){
    copy{
      from( zipTree(zipFile) ){
        include "**"  
        eachFile { fcd ->
          fcd.relativePath = new RelativePath(true, fcd.relativePath.segments.drop(1))  
        }
        includeEmptyDirs = false  
      }
      into jdkDir      
    }
  }
}
task buildJRE(type: Exec,dependsOn:prepareJDK) {
  commandLine './buildJRE.sh'
}
```

これを

```shell
gradle buildJRE
```

とすると、JDKがダウンロードされて、各プラットフォーム用のJREがbin/jreに生成されます。

prepareJDKのタスクで、Win/MacのLiberica JDK11をダウンロードして展開します。
タスク自体は単純なものですが、zip展開の際にRelativePathを使って、1階層ファイルパスを引きあげています。
普通にJDKのzipを展開すると、"jdk/win/jdk-11.0.6"という形でJDKのバージョンが入ったフォルダが作られてしまうのですが、JREを作る際にバージョンが入るとちょっと使いにくいかったため、フォルダ内のファイルを1階層引きあげています。

またJREを生成するシェル（buildJRE.sh)は、jlinkを呼び出すシェルになっています。

```shell
#!/usr/bin/env sh
MODULES="java.base,java.desktop,javafx.controls"
for PLATFORM in win mac
do
  OUTPUT_DIR=build/jre/$PLATFORM
  JMODS_DIR=jdk/$PLATFORM/jmods
  if [ -d $OUTPUT_DIR ]; then
	echo "JRE for $PLATFORM exits in $OUTPUT_DIR"
  else
	echo "creating JRE for $PLATFORM in $OUTPUT_DIR"
	jlink --compress=2 --module-path $JMODS_DIR --add-modules $MODULES --output $OUTPUT_DIR	
  fi	
done
```

MODULESのところに、利用するモジュールをならべて書いておきます。Librica JDKはJavaFX同梱なので、JavaFXアプリには大変便利です。

開発が本格的にOpenJDKに移行し、各種JDKがダウンロードでき、必要な分のモジュールだけが作れるようになったのは大変喜ばしいことですね。
breadcrumbs_on_railsを使ったパンくず実装　その②　オリジナルviewを使おう

パンくず実装の続きです。
といっても備忘録としての記事ですので、ほぼほぼサイトを参照してやったことを思い返すつもりで書いています。

ちなみに今回は、lib直下をいじりますので、少し習ったことがないことをしました。
ではでは、やっていきましょうか

まずは、custom builder を作りましょう。
といってもこの名称はなんでも良いです。
ただし、ほぼほぼコードの直打ちで作りますよ。



```ruby:/lib/custom_breadcrumbs_builder.rb
class CustomBreadcrumbsBuilder < BreadcrumbsOnRails::Breadcrumbs::Builder
  def render
    @context.render '/shared/breadcrumbs', elements: @elements
  end
end
```

これは、views/sharedフォルダにオリジナルのviewを呼びにいっているという記述です。
render形式のため、elements:@elementsの要素をbreadcrumbs.html.hamlへ送っています。
shardフォルダにrenderさせるファイルを纏めているので、そこを呼んでいますが、別に場所はどこでも良いです。

```ruby:/view/breadcrumbs.html.haml
- if elements.present?
  %ul.l-gretel-brock
    - elements.each do |element|
      %li.l-gretel-inline
        - if element.path.present?
          = link_to element.name ,element.path, class: 'l-gretel-link u-deco-none'
          = fa_icon 'chevron-right', class: 'l-gretel-icon'
        - else
          = element.name
    = elements.last.name
```
と書きますわね。CSSは適当煮付けてくださいな。
（gretelって名称使ってるけどむしろわかりづらいような・・・）

そして、使いたいところに、以下の一文を追加する。

```ruby:test.html.haml
  = render_breadcrumbs builder: ::CustomBreadcrumbsBuilder
```

最後に、config/application.rbに以下の一文を追加しよう。

```ruby:config/application.rb
module Test
  class Application < Rails::Application
    config.autoload_paths += %W(#{config.root}/lib) #ここの一文だけだよ！
end

```
これはローカル上で、lib直下にあるファイルを呼びに行きますよということです。

ここまでできれば一安心、早速みてみよう！
いかのように表示されました。
fa_iconが良い感じです。

[![Screenshot from Gyazo](https://gyazo.com/05e01b1ea6092e687f210b1ac9f66b39/raw)](https://gyazo.com/05e01b1ea6092e687f210b1ac9f66b39)

ここまでやってみてダメだった人は、`rails s`して再起動、もしくは` bandle install`を試してみよう。
私は意外と忘れるアプリケーションサーバーの再起動は盲点でした。

あ、あと本番環境は、以下の一文追加必要ですので、ご注意ください。
いくつか文章探しましたが、これでやっと通った感じです。

```ruby:config/environments/production.rb
Rails.application.configure do
###いっぱい文章ありましたが省略
  config.eager_load_paths += %W( #{config.root}/lib )
end
```

これで、デプロイしても問題ないはず！

試してみてください。
ちなみに参考した記事は以下の通り、私もtech:expert生です。
https://pg-happy.jp/rails-pankuzu-list.html
Laravel 検索機能サンプル


searchアクションで検索結果があれば表示するサンプル

```routes.php
Route::get('/person/{id}', 'PersonController@find');
Route::post('/person/{id}', 'PersonController@search');
```

```controller.php

  public function find(Request $request){
    return view('person.find', ['input' => '', 'id' => $request->id]);
  }

  public function search(Request $request){
    $input_val = $request->input;
    $item = Person::find($input_val);
    return view('person.find', ['input' => $input_val, 'id' => $request->id, 'item' => $item]);
  }
```

```view.blade.php
  <form action="/person/{{$id}}" method="post">
    {{ csrf_field() }}
    <input type="text" name="input" value="{{$input}}">
    <input type="submit" value="find">
  </form>

  @if (isset($item))
    <table>
      <tr>
        <th>Data</th>
      </tr>
      <tr>
        <td>{{ $item->getData() }}</td>
      </tr>
    </table>
  @endif
```
YiiのデバッグツールにGitのbranchを表示してみた

# 概要
Yiiのデバッグツールに現在のbranchを表示するようにしてみた。

## デバッグツールのカスタマイズ
[デバッグツールバーとデバッガ](https://yii2-framework.readthedocs.io/en/stable/guide-ja/tool-debugger/#_4)の あなた自身のパネルを作る を元にカスタマイズしました。

### ファイル作成
`yiisoft/yii2-debug/src/panels` に GitPanel.php を作成します。
ベースは [こちら](https://yii2-framework.readthedocs.io/en/stable/guide-ja/tool-debugger/#_4)の ViewsPanel.php。

### 現在のbranchを取得する処理
[PHPで現在のgitブランチを取得する](https://co.bsnws.net/article/78) こちらの記事から処理を実装。

```php
<?php
namespace yii\debug\panels;

use Yii;
use yii\debug\Panel;

class GitPanel extends Panel
{
    private $currentBranch;

    public $dotGitPath;

    public function init()
    {
        parent::init();
        $this->setGitPath();
        $this->currentBranch = $this->getCurrentBranch();
    }

    /**
     * git関連のファイルパス設定
     */
    private function setGitPath()
    {
        Yii::setAlias('@gitHEAD', $this->dotGitPath . '/HEAD');
    }

    /**
     * 現在のbranchを取得する
     *
     * @return string
     */
    private function getCurrentBranch(): string
    {
        $gitPath = Yii::getAlias('@gitHEAD');
        return trim(implode('/', array_slice(explode('/', file_get_contents($gitPath)), 2)), "\n");
    }
}
```

### Yiiのデバッグツールにブランチ名を表示させる

GitPanelクラスに下記の関数を追加する。

```php
    /**
     * {@inheritdoc}
     *
     * @return string
     */
    public function getSummary(): string
    {
        $url   = $this->getUrl();
        $html  = '<div class="yii-debug-toolbar__block">';
        $html .= '<a href=' . $url . '>';
        $html .= '<span class="yii-debug-toolbar__label yii-debug-toolbar__label_info">';
        $html .= $this->currentBranch;
        $html .= '</span></a></div>';
        return $html;
    }

    /**
     * {@inheritdoc}
     */
    public function save()
    {
        return $this->currentBranch;
    }
```

`getSummary()` がツールバーに表示されるhtmlを作成する処理。
`save()` が実行されることで内容がデータファイルに保存される。

## 設定

デバッグツールの拡張機能を利用するために `main-local.php` に以下の設定を記述。

```php
    'modules'=>[
        'debug' => [
            'class' => 'yii\debug\Module',
            'panels' => [
                'git' => [
                    'class' => 'yii\debug\panels\GitPanel',
                    'dotGitPath' => '.gitディレクトリのパスを記述 例) /var/www/html/.git',
                ],
            ],
            'allowedIPs' => ['*']
        ],
    ]
```

## 参考
- [デバッグツールバーとデバッガ](https://yii2-framework.readthedocs.io/en/stable/guide-ja/tool-debugger/)
- [PHPで現在のgitブランチを取得する](https://co.bsnws.net/article/78)
[Swift] @_exportedの挙動調査

# はじめに

Swiftの`@_exported`について、その挙動を調査したのでまとめる。

# `@_exported`とは

 - _がプレフィックスとしてついており、Swiftで公式には公開されていないAttribute
 - 以下のようにimport文で利用可能

```swift
@_exported import Foo
```

# 挙動調査

## 前提

以下のような3階層のモジュール構成を考える。

```swift
├── Main
│   └── Main.swift
├── SubModule
│   ├── SubModule1.swift
│   └── SubModule2.swift
└── SubSubModule
    └── SubSubModule.swift
```

## 同一モジュール内への影響調査

SubModule1.swiftにて、`@_exported import SubSubModule`を記述する。
ファイルをまたいでSubModule2.swiftでもSubSubModule.swiftのAPIが利用できる。

```swift
├── Main
│   └── Main.swift
├── SubModule
│   ├── SubModule1.swift // @_exported import SubSubModuleを記述
│   └── SubModule2.swift // SubSubModule.swiftのAPIが利用できる
└── SubSubModule
    └── SubSubModule.swift
```

## 上位モジュールへの影響調査

さらに、Main.swiftにて、`import SubModule`を記述する。
モジュールをまたいでMain.swiftでもSubModule.swiftのAPIが利用できる。

```swift
├── Main
│   └── Main.swift // import SubModuleを記述、SubSubModule.swiftのAPIが利用できる
├── SubModule
│   ├── SubModule1.swift // @_exported import SubSubModuleを記述
│   └── SubModule2.swift
└── SubSubModule
    └── SubSubModule.swift
```

# おわりに

 - `@_exported`をimportに付与すると、同一モジュール内でのimportが不要になる
 - また、上位モジュールが下位モジュールをimportでインポートした場合、下位モジュールで`@_exported`でimportされている孫関係にあたる下位モジュールもimportされる
 - 以下のように、UIKitをimportするだけで、FoundationをimportしなくてもFoundationのAPIが利用できることから、UIKit内部で`@_exported import Foundation`が定義されていると推測される

```swift
import UIKit
import Foundation // import不要
```

# 参考

 - https://forums.swift.org/t/exported-and-fixing-import-visibility/9415
 - https://stackoverflow.com/questions/41000256/what-is-import-func-struct-class-and-exported-in-swift
 - https://stackoverflow.com/questions/33558995/what-is-the-exported-attribute-in-swift
 - https://medium.com/eureka-engineering/create-merged-framework-to-cut-appstartuptime-72ee67b2bbab
【感想】Laravel(+Vue.js)でSNS風Webサービスを作ろう！を終えて

<h1>Laravel(+Vue.js)でSNS風Webサービスを作ろう！を終えて</h1>
<h2>教材のご紹介</h2>
今回、私が学習した教材はこちらです。
<p class="course-title course-small">Laravel(+Vue.js)でSNS風Webサービスを作ろう！
<a href="https://www.techpit.jp/p/laravel-vue-sns">https://www.techpit.jp/p/laravel-vue-sns</a></p>
★参考までに今までのTechpit歴
・Techpitの学び放題会員2か月
<del>・(残念ながら)</del>学び放題に入っていない教材5個くらい単発購入<del>(してやられた)</del>

ちなみにRails、Laravel、Python、Vue.jsなど含め、Techpit教材はかなり漁ってきました。その中でも<span style="color: #ff0000;"><strong>かなりおすすめの教材</strong></span>です。

<span style="color: #ff0000;"><strong>初学者がポートフォリオ作成で躓く(私含め)であろうミドルウェア、リクエスト、認可、ポリシー、さらにはフロンドエンドフレームワーク(Vue.js)との連携まで、実際にアプリを作りながら体験できます。</strong></span>

(他にもLaravelに関しては、AWSを用いた教材やVue.jsのSPAまで実装できる教材もあるので、そちらもおすすめです。<del>(回し者ではありません。)</del>)

教材通り、herokuでデプロイも完了しております。参考までに。
<a href="http://laravel-vue-sns.herokuapp.com/">http://laravel-vue-sns.herokuapp.com/</a>
<h2>学習を終えて</h2>
この教材では、Mac&amp;Laradockを用いた開発になりますが、私はWindows&amp;XAMPPに置き換えて挑戦しました。

※というよりも、いつもこの環境で頑張って乗り切っています。(Mac環境の教材多すぎて辛い)

最終的に、Mailhogだけどうしても実装できませんでしたが、それ以外は問題なく実装できました。

また、今回XAMPP環境にPostgreSQLを紐づける方法も理解できたので、herokuも今後は積極的に利用していこうかなと思いました。(※herokuはPostgreSQLを推奨。かつFTPでデプロイするのは時間がかかりすぎるので。。。)

⇓参考までにXAMPPでPostgreSQLを使う方法に関しては、下記でまとめています。

https://chobimusic.com/laravel_xampp_postgresql/
<h2>今後に関して</h2>
今回のMailhogの実装失敗などを踏まえ、Laradockでのアプリ制作ができたほうが良いなと痛感しました。

また、この教材を参考にしながらVue.jsまで連携させたポートフォリオ制作に挑戦していこうと思います。

引き続き頑張ります✌

P.S.

独学中の身として、Twitterで執筆者の方々や学習者の方々とやり取りできるのがとても励みになっています。ありがとうございます。
PHPのisset()と等価な条件式を書いてisset()への理解を深めたい

# 問い

`$hoge` を変数とする。 `$hoge` は定義されていて、かつ配列型であるとする。

このとき、 `isset($hoge['fuga']['piyo'])` と等価な条件式を書け。

ここで「2つの条件式が等価である」とは、「条件を満たすどのような `$hoge` に対しても2つの条件式の真偽が一致する」ことを意味することとする。

また、条件式を書くにあたっては論理演算子と以下の関数のみを用いることとする。

- `array_key_exists()`
- `is_array`
- `is_null`

# 答えの例

```php
array_key_exists('fuga', $hoge)
&& !is_null($hoge['fuga'])
&& is_array($hoge['fuga'])
&& array_key_exists('piyo', $hoge['fuga'])
&& !is_null($hoge['fuga']['piyo'])
```

# 証明

省略
毎月積み立てと毎日積み立てどっちがお得なのよ？　2019年のビットコイン価格で比較

![asf1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253878/e6fb3ff1-e526-4903-f2e9-569431a36ce6.png)
[Coincheckが毎日積み立てっての始めたようで](https://coincheck.com/ja/article/49)。ドルコスト平均法もリスクが分散されることも分かってるけど、純粋に2019年1年間の価格推移で実際にやってたらどうなってたんだろうね？ってのを知りたくてシミュレーションしてみました。

#2019年のビットコイン価格推移
[Investing.comなるところ](https://jp.investing.com/crypto/bitcoin/btc-jpy-historical-data)でデイリー履歴は分かるようで。よくよく見たら取引所指定も出来るみたいですが、初期値のBitflyer価格推移にしちゃいました。まぁ大差ないでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253878/129e0acb-0012-f980-8584-8b839e033cff.png)

高値・安値、始値・終値は明確なんだけど、いつの価格使えばいいか分からんのでとりあえず高値と安値の真ん中にしときます(適当)。毎月積み立ての場合は[大体毎月7日](https://faq.coincheck.com/s/article/50700?language=ja)に買うようなのでそう指定。曜日は無視。

すると毎日積み立て・毎月積み立てのタイミングと価格はこんなプロットになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253878/06742569-2cea-7af1-8bb8-a33a916bb409.png)

#計算してみる
最小額の毎月10,000円にしときましょか。何もしなかったらただの12万円/年。これを毎月1万円ビットコインを買うか、毎日買うか。
![asf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253878/ecdf17c5-de42-1e98-d54e-c3d48c4025fc.png)
日割りにすると、約330円。[1ビッグマック](http://www.mcdonalds.co.jp/menu/burger/)弱/日。

累積するとこう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253878/e8359358-044e-9979-ef1c-01fe0b034c54.png)
**誤差かよ**。
正確には以下の値。
![ag.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253878/9905101f-5948-d6bb-05ee-ec49ef56ea66.png)
月次積み立ての方が1%程度上回る結果でした。ていうかこんなに変わらないのか。

先日50万割りましたが、また70万越えてるので昨年積み立ててる人は今プラスで良いですね～。

#締め
年間の投資額を12分割するか365分割するかっちゅー話。悪いタイミングを引いてしまうことはいつかあるはずなので、そのダメージを軽減させるものと認識するなら日積み立ての方がマイルドでいい気がします。

おしまい。