OmniAICreator/Qiita-1.07M huggingface dataset:
【JavaScript】ネストされたJSONデータの値取得について

#経緯
2ヶ月くらい前、JSONデータを全て抜き出して、値を取り出さなければならない依頼がありました(何故かは伏せておきます…)。

一次元ならまだしも、二次元配列の処理となるとちょっと骨が折れます。
どうしようかと考えたのですが、再帰的に動く処理を使って対応することにしました。

#コード
以下、対応に対して組んだJSです。


```javascript:JsonDetaileOutput.js
// Jsonの中身
var jsons ={
    "masterNumber": 10000,
    "code": "m-001",
    "customerData": {
        "name": "Jiro",
        "age": 45
    },
    "Address": [{
        "name": "testAreport",
        "email": "tA@sample.co.jp"
    }],
    "items": [{
        "itemId": "item01",
        "itemName": "商品01"
        },
        {
        "itemId": "item02",
        "itemName": "商品02"
        },
        {
        "itemId": "item03",
        "itemName": "商品03"
    }]
};

// jsonを分解する処理
function getValue(obj) {
    if (typeof obj === 'object') {
        var strValue = '';
        for (key in obj) {
            strValue += getValue(obj[key]);
        }
        return strValue;
    } else {
        return obj;
    }
}

// 出力結果
console.log(getValue(jsons));

```
オブジェクトの中を検索して、更にオブジェクトがあった場合はgetValueを再度呼んでその中身をチェックして値を読み出しています。

#実証
実行した時の出力結果です。
実行はnode.jsで行っております。

```console
$ node JsonDetaileOutput.js
10000m-001Jiro45testAreporttA@sample.co.jpitem01商品01item02商品02item03商品03
```
ちゃんと出力されました。
後は、このデータを煮るなり焼くなりして加工するのみです。

#おわりに
これで終わりになります。
同じような問題に苦しむ方の手助けとなりましたら幸いです。

実は、以前に質問サイトに投稿していた内容がありまして、こちらが元ネタとなっております。
https://teratail.com/questions/136359
Go言語でk8sならMakefileよりdocker-composeの方が便利かもしれない

# はじめに
Go言語のコンパイルを[multi stage build](https://docs.docker.com/develop/develop-images/multistage-build/)で書けるようになったので、いちいちMakefileでクロスコンパイル記述を書く必要が無くなったということです。

**MakefileでGo言語をコンパイルするのをdisる意図はないです**

# Makefileの場合
こんな感じのMakefileを書いてアレするのが普通だと思います。

```makefile
build:
    go build -o binary_hoge -v

build-linux:
    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bainary_hoge
```

# Makefileを使いたくない理由

僕がCIツールで使っているCircleCIはビルド時の環境をコンテナイメージとして指定することができます。

https://circleci.com/docs/2.0/configuration-reference/#docker--machine--macosexecutor

これと併用する場合に、選択するイメージによってはmakeが入ってない場合があります。
CI上でmakeインストールすればいいんですが、下記の理由によりそれは選択したくないです。

- makeのインストールに地味に1分くらいかかる
- workflowでビルドを分割しているが、makeでやってることが多いと各ビルドでmakeインストールを書く必要ある
- makeをインストールしたコンテナイメージを作ればいいけど、イメージのメンテナンスは極力避けたい

# docker-composeとmulti stage buildを使う

下記のようにdocker-compose.ymlとDockerfileを書きます。

```yaml:docker-compose.yml
version: "3"
services:
  app:
    build: .
    image: hogehoge-image
```

```dockerfile:Dockerfile
FROM golang:alpine AS build-env
WORKDIR /work
RUN apk update && apk add git
ADD . /path-to-go-source/
RUN go build -o /work/api

FROM alpine
COPY --from=build-env /work/api ./api
EXPOSE 8080
ENTRYPOINT ./api
```

ビルドします。pushします。

```shell
docker-compose build
docker-compose push
```

# まとめ
上記のようにすることで、**docker multi stage buildでクロス、ローカルのdocker-machine向けのコンパイルが一括管理される**メリットを受けることができるようになります。

docker-machineを介さないローカルでの確認は今まで通り、Makefileを使えばいいかと思いますが、そもそも`go build hoge/`で済むならローカルでもMakefileはいらないんじゃないかと思います。

**あくまで僕自身のニーズではそうでした。という話です。みなさん良いコンテナライフを〜**

以上
Vueコンポーネントを Webpack+babel で扱うための設定

「.vue」ファイルを作成してコンポーネントを扱う際に、「.vue」ファイルをトランスパイルするための設定がないとWebpackでエラーになってしまうので、以下の設定をした。

## Vueのインストール

```
yarn add vue
```

## 必要なパッケージをインストール

vue-loader, vue-template-compiler を開発用にインストール

```
yarn add -D vue-loader
yarn add -D vue-template-compiler
```

# webpack.config.babel.js の設定を追記

### vue-loader プラグインを読み込む

vue-loader を使用するために必要なプラグイン。このプラグインを読み込まないと vue-loader が使用できない。

```javascript
import VueLoaderPlugin from 'vue-loader/lib/plugin';

export default {
plugins: [
        new VueLoaderPlugin(),
    ],
}
```

[vue-loader 公式ページ](https://vue-loader.vuejs.org/guide/#manual-configuration)

### modules の設定

「.vue」ファイルを変換して Babel を適用するための設定

```javascript
module: {
    rules: [
        {
            test: /\.vue$/,
            use: ['vue-loader'],
            exclude: /node_modules/,
        },
    ]
},
```

### etensions　と　alias の設定

extentionsに「.vue」を追加することでimportの際に拡張子を省略して記述できるようにる。
[webpack 公式ページ](https://webpack.js.org/configuration/resolve/#resolve-extensions)

```javascript
resolve: {

        extensions: [..., '.vue'],

        alias: {
            vue$: 'vue/dist/vue.min.js',
        },
    },
````

また、aliasの設定をすることで

```javascript
import Vue from 'vue/dist/vue';
```

を

```javascript
import Vue from 'vue';
```

とかけるようになる。
cakephp3でsitemap.xml作成

いろんなサイトを見てきたが、自分が求めてるものと違ってたので書きました。

itmesの中身と
TabelNameをコンテンツのテーブル
に書き換えれば、使えます。


``` xml.php
        $xml_head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><urlset></urlset>";
        $xml = new SimpleXMLElement($xml_head);
        $xml->addAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');

        $itmes = [
            ['url' => "url_1"],
            ['url' => "url_2"],
            ['url' => "url_3"],
            ['url' => "url_4"],
        ];

        $tab_data = $this->TabelName->find();
        foreach ($tab_data as $data) {
            $itmes[]['url'] = "{$data->id}";
        }

        foreach ($itmes as $itme) {
            $urlSxe = $xml->addChild('url');
            $urlSxe->addChild('loc', $itme['url']);
        }

        $this->response->body($xml->asXML());
```

$this->TabelName、各コンテンツ配下にあるアイテムなどある場合は使ってください。
全部直接書くよ！ってかたは,下記を消してください。

```xml.php
        $tab_data = $this->TabelName->find();
        foreach ($tab_data as $data) {
            $itmes[]['url'] = "{$data->id}";
        }
```

##myブログ　内容は同じです
https://keikun.hatenablog.com/entry/2018/09/18/164200
Mi Band 3からデータをエクスポートする(要Android)

## TL;DR
1. [Mi band master](https://play.google.com/store/apps/details?id=blacknote.mibandmaster&hl=ja)というアプリの「設定」>「Data」>「データのエクスポート」
2. db.sqliteが吐かれる
3. timeがUnixtimeなので注意

## アプリでの手順
![Screenshot_20180918-143845.png](https://qiita-image-store.s3.amazonaws.com/0/26440/80822fcb-37a3-18f0-1f64-9ec96d53884e.png)
Mi band masterより設定を選び

![Screenshot_20180918-143850.png](https://qiita-image-store.s3.amazonaws.com/0/26440/6f61909c-35cd-af5f-12a6-113033235869.png)
データのエクスポートを選択します。

その後どこに保存するか聞かれるので適宜。

## Unixtimeの変換
とりあえずデータがちゃんと取れているのかを確認したいので

```sql:miband.sql
.open db.sqlite
.headers on
.mode csv
.output miband_hr.csv
select datetime(time,'unixepoch','localtime') as Time,hr from heartrate;
.quit
```
このようなSQLを実行します。
これで可読性のある時間に変換できるので、確認することができます。

Pythonとかでこの後処理を行う場合は、一旦`Integer`でUnixtimeのままインポートしてからプログラム側で時間の変換を行ったほうが良いでしょう。
ffmpegでアニメーションGIFを作る場合は必ずカラーパレットを指定するべき

メモがてら。

アニメーションGIFをきれいに作る方法、とかで調べると色々出てくるけど、最低限で良ければカラーパレットを指定するだけで済むので、そのことのメモ。

```console
$ ffmpeg -i src.file -vf "palettegen" -y palette.png
$ ffmpeg -i src.file -i palette.png -lavfi "paletteuse" dst.gif
```

結果

|  カラーパレットなし | カラーパレットあり |
|:----:|:----:|
| ![without.gif](https://qiita-image-store.s3.amazonaws.com/0/9926/38888dd9-286e-b224-f089-b758a7103583.gif) | ![with.gif](https://qiita-image-store.s3.amazonaws.com/0/9926/dabfbd48-7926-0b2e-6dec-25cb75a341b7.gif) |

色がおかしくなったのがなくなりましたね。
Three.jsでglTFのアニメーションを複数再生する

three.jsでglTFのアニメーションを再生する記事はあったのですが複数のアニメーションを切り替える方法は書かれていなかったのでなかったので書いてみました
複数のアニメーションがあるglTFの3Dモデルが前提に書かれています。

まずglTFを読み込んでシーンに配置してアニメーションを再生します。
シーンの作成等は省略します

```javascript:main.js

const loader = new THREE.GLTFLoader();
const model = 'hoge.gltf';

//glTFの読み込み
loader.load(model, (data) => {
  const gltf = data;
  const object = gltf.scene;

//アニメーションの読み込み
  const animations = gltf.animations;
  mixer = new THREE.AnimationMixer(object);

  const anime = mixer.clipAction(animations[0]);
  anime.play();

//シーンに追加
  scene.add(object);

});
```
この
`mixer.clipAction(animations[0]);
`の`[]`の数字を書き換えれば別のアニメーションが再生されます。
glTFの`animations`の上から0から順に指定できるみたいです。

このままじゃ条件分岐で別のアニメーションを指定しても一度再生したアニメーションはループ再生しっぱなしになって他のアニメーションと混ざるので関数に切り離します。

```javascript:main.js
const loader = new THREE.GLTFLoader();
const model = 'hoge.gltf';

//glTFの読み込み
loader.load(model, (data) => {
  const gltf = data;
  const object = gltf.scene;
  const animations = gltf.animations;


  mixer = new THREE.AnimationMixer(object);

//シーンに追加
  scene.add(object);

  //アニメーションの切り替え
  function chengeanime(num) {
    mixer.stopAllAction();
    const anime = mixer.clipAction(animations[num]);
    anime.setLoop(THREE.LoopOnce)
    anime.clampWhenFinished = true

    anime.play();
  }
});

```

`stopAllAction()`を使ってすべてのアニメーションを一旦ストップし`setLoop(THREE.LoopOnce)`でループを無効、`clampWhenFinished`を`true`にすればアニメーションの最後のフレームでアニメーションが終了します。
これで条件分岐でアニメーションが切り替えられるようになったと思います。


`setLoop(THREE.LoopOnce)`を書かなければループしつつアニメーションが混ざりません。


---

VScodeの拡張機能でglTFをプレビューするとアニメーションの名前も一緒に表示されていたのでおそらく名前で指定する方法もあると思いますが調べてもわからなかったので断念。
SkyWay WebRTC Gatewayハンズオン Chapter0

[ハンズオン](https://qiita.com/nakakura/items/faeb4f6df82677139761) のChapter0

# 前置き

まず簡単なLチカアプリケーションを作成します。
UDPでメッセージを送ってON/OFFします。
慣れているという方がいらっしゃったら、UDPで操作できるものであれば、LEDに限らず凝ったものを作っていただいても構いません。
また例はrubyで実装していますが、ruby以外の言語でも構いません。
(但し、講師が知らない言語で実装した場合サポートが受けられない可能性がありますのでご了承ください)

# 想定環境

## RaspberryPi
- RASPBIAN 4.14
- Raspberry Pi HDカメラボードV2

## Web
- Chrome M69が動作する環境

## 回路
- ブレッドボード
- LED, 抵抗
- ジャンパ線(メス-オス2本、オス-オス2本)

LEDと抵抗は、ハンズオン貸出機材としては[こちらのものを利用します](https://www.amazon.co.jp/ELPA-LED-5mm-%E3%83%AC%E3%83%83%E3%83%89-HK-LED5H/dp/B00940YRLA)。
持ち込み参加の方は他のものでも構いませんが、Raspberry PiのGPIO(3.3V)で動作するものをお持ち下さい。

お貸し出ししたRaspberry Piは基本的な設定は完了しています。
またカメラについては別のものでも可能ですが、後述するgStreamerでのカメラからの映像取得において、オプションが変わる可能性があります。

# 必要なアプリケーションのインストール

```shell
# ライブラリのビルド環境のインストール
$ sudo apt install autoconf automake libtool
# 映像伝送用アプリケーションのインストール
$ sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
# サンプルプログラムはRubyで書くのでRubyの開発環境をインストール
$ sudo apt install ruby-dev libssl-dev
# Raspberry PiのピンをRubyで使うためのgemをインストール
$ sudo gem install pi_piper
```
# 物理構成

この演習ではGPIOの21番を利用します。
https://www.raspberrypi.org/documentation/usage/gpio/
を参照すると、右上のピンです。あとは適当なGNDのピンを選んで配線しましょう。
この2つの線の間にLEDと抵抗を挟んでください。
3.3Vの電圧をかけますので、LEDのspecに合わせて適切な抵抗をはさんでください。

![eeb23aaf-9ebe-5e73-2021-5886d9d87a74.png](https://qiita-image-store.s3.amazonaws.com/0/104451/ae416735-9171-5209-38fd-8beaf0ed4125.png)



# カメラのセットアップ

まずカメラモジュールをraspberry piのカメラ端子に装着して下さい。
電源OFFの状態で、プリントケーブルを奥まで差し込み、ストッパーをガッチリ下まで押し込んで下さい。
その後、raspberry piを起動し、設定を行います。

```shell
$ sudo raspi-config
```

メニューが表示されるので、5. Interfacing Options > P1 Camera からenableにしてください。
Raspberry Piが再起動されます。

あとで使うのでカメラにアクセスするためのモジュールもインストールしておきます。

https://github.com/thaytan/gst-rpicamsrc.git
のClone or Downloadからzipをダウンロードして展開して下さい。
gitで入れてもらってもいいです。

```shell
$ cd gst-rpicamsrc-master
$ ./autogen.sh --prefix=/usr --libdir=/usr/lib/arm-linux-gnueabihf/
$ make
$ sudo make install
```

# Lチカアプリケーション

```ruby
#!/usr/bin/ruby
require "socket"
require "pi_piper"

def pin(pin, message)
  case message
  when "on"
    pin.on
  when "off"
    pin.off
  end
end

if __FILE__ == $0
  gpio_21 = PiPiper::Pin.new(:pin => 21, :direction => :out)

  udps = UDPSocket.open()
  udps.bind("0.0.0.0", 10000)

  loop do
    data = udps.recv(65535).chomp
    pin(gpio_21, data)
  end

  udps.close
end
```

UDPで受信したテキストメッセージが"on"であれば電圧をかけ、"off"であれば止めます。

# 実行
これを遠隔制御しましょう。

Lチカプログラムを起動します。Raspberry PIのハードウェアを触るので今回はroot権限で実行します。実用するときは適宜権限設定を変更してください。

```shell
$ sudo ruby rasbpi.rb 
```

↓RASPBERRY_PI_IP_ADDRESSの部分にはラズベリーパイのIPアドレスを入れて下さい

光らせる場合

```shell
$ echo "on" | nc -u RASPBERRY_PI_IP_ADDRESS 10000
```

止める場合

```shell
$ echo "off" | nc -u RASPBERRY_PI_IP_ADDRESS 10000   
```

以上で完了です。
これをインターネット越しに操作してみましょう。

[次章](https://qiita.com/nakakura/items/555fe01941c54b698fcf)ではWebRTC Gatewayの起動処理を行います。
SkyWay WebRTC Gatewayハンズオン

この資料は[WebRTC初心者歓迎！WebRTC Gatewayハンズオン@NIFcLounge](https://skyway.connpass.com/event/101506/)で使用する資料です。

#実施内容

![ba12fbb3-b89a-2690-9b0a-a74b2d21ea0d.png](https://qiita-image-store.s3.amazonaws.com/0/104451/5338e04e-ed98-bd87-2aa9-fe4d2cf88ea3.png)


カメラモジュールを制御し遠隔地のLEDを撮影してブラウザに表示する。
ブラウザからLEDの制御信号を送って光らせると、遠隔地のLEDが光っている様子がブラウザで確認できる

#物理構成

![119af388-0c90-9bc9-eb1d-e2c0daf473f2.png](https://qiita-image-store.s3.amazonaws.com/0/104451/30be9667-dc61-45da-5c69-a005e1255073.png)

# マニュアル

当日はこの順番で説明していきます。

[Chapter0 まずプログラムからRaspberry Pi基盤を操作してLEDを光らせてみよう](https://qiita.com/nakakura/items/9d5fb1ff43c40c97c244)
[Chapter1 WebRTC Gatewayを起動してSkyWayサーバへ繋いでみよう](https://qiita.com/nakakura/items/555fe01941c54b698fcf)
[Chapter2 MediaStreamで映像を取得してみよう](https://qiita.com/nakakura/items/e64e5aaa9ffed7b89aeb)
[Chapter3 DataChannelで信号を送ってRaspberry Pi基盤を操作してみよう](https://qiita.com/nakakura/items/c3c31bb7f2854c2b10f9)
高校数学の公式

# 2次関数
## 解の公式
2次関数を次式のように定義する。
$ax^2 + bx + c = 0 (a\neq 0)$

この時の解は次の公式で求められる。
$x = \frac{-b\pm{\sqrt{b^2 - 4ac}}}{2a}$

## 判別式
$D = b^2 - 4ac$としたとき、下記が成り立つ。
$D > 0$で異なる2つの解を持つ。
$D = 0$で重解を持つ。
$D < 0$で虚数解を持つ。
（レポート）契約書データ関連のAI開発に伴う、前処理及び匿名化処理についての実例

- GVA TECH 株式会社
    - AI-CON
        - クラウドとAIを活用した契約リスク判定
            - 契約書のトラブルが。。。
        -　契約書の不利な内容がレコメンドされる。
     - AI-CONドラフト
        - 契約書ダウンロードサイト 
- 匿名化処理
    - 学習データとして利用するためにそのままでは使えないので匿名化しなければならなかった
    - フロー
        - 正規化
        - 不要データの削除
        - タグ付け
            - すだちを利用
        - リーガルサイドでの確認
- 契約書にも流行りがある。
[Python] 前まで動いていたが、余計なライブラリを入れてKerasが急にImportErrorになった

<font color="DeepPink">※結果的には単なる仮想環境指定のミスでした。しかし解決に繋がる事も書いてあります。</font>

## 起こったこと
Kerasを用いた開発を前からやっていたのですが、新しいことをやりたくなって、とある記事(どの記事か思い出せない)通りに色々pipで入れてたら、今まで動いてた機械学習系の成果物が動かなくなってしまった
### 目次

1. 原因
2. 対策

## 何が原因なのだろう

### pipで余計なものを入れすぎた
数日間エラー解決できず、どこのページを参考にしてライブラリとか入れたのか思い出せないが、とにかく"何かしらのライブラリが邪魔をしてしまってる"と考えた。

## 解決までの道のり
ざっくり言うと、anacondaのコマンドとかpipとかでモジュールいれて、sysとかpythonpathでパスを通せばいい。下記は、いろいろ試行錯誤した流れ。

成果物のpythonプログラムを実行したら、「importerror: cannot import name keras.models」みたいなエラーが出て、「え、今まで動いてたやん、、、Keras入ってるんだけど」って思った。

動いてた時点のtensorflowやkerasのバージョンを戻したり、それ関係のものをインストールし直したりした。
↓
pythonを起動
↓
anacondaに入れたkerasのパスを、sysでパスを通した
↓
コマンドでkerasをインポートして、kerasのパスを調べた。
↓
おそらく、pipで色々入れまくった影響でパスがおかしくなってた。
↓
そのkerasフォルダの中にmodelsフォルダがなかったので、他のkerasフォルダからmodelsフォルダをコピーして、そのフォルダの中に入れた。
↓
「importerror: cannot import name 'clone_model'」と新たにエラーがでた。ググってもわからなかったけど、予想ではさっきmodelsフォルダをコピーして入れたから、cloneと言われた？？(わからないけど名推理)
↓
さっきコピーしたフォルダに問題があるなら取り除くか〜って思って取り除いて再度成果物を実行してみたら何故か動くようになった。(どこかのタイミングでエラー改善のきっかけになったのかな、、、)

~~トライアンドエラーしまくって色々試しまくったので、何故うまくいったのか説明できないのが情けないです、、、(すいません)~~

## 原因が分かった。
最初に普通にPython起動して普通にkerasインポートしてエラー出てたので、パスを通した時点で直ったと思います。

ただ、僕の場合は恥ずかしながらpython実行する際の仮想環境指定が間違ってただけのイージーミスでした・・・
このエラーが出た時は、関係のない仮想環境を指定して、実行してた。そりゃその仮想環境にはKerasとか入れてないから、importError出るよなって思った。

今回のエラーと戦ってる際は、関係のないとある仮想環境が正しいと誤って思い込んでしまって再度いろんなモジュールとか入れたり無駄なことをしてしまいました。。。(1ヶ月pythonから離れただけで忘れた)

なので、**今まで普通に動いてたのに、なんで急にimportできなくなった！？って時は、正しい仮想環境を指定しているかを確認するのもいいかもしれません**(僕の場合はこのイージーミスで2日間ぐらい戦ってました、、、)

## 感想
違う仮想環境にまた同じモジュールを入れてしまったみたいで、つら。。。動くようになったから嬉しいけど。。。
Pythonは厄介
macOS で暗号化ZIPを作成する方法

## 圧縮
```bash
zip archived.zip source1.txt source2.txt
```
Finder で圧縮すると `__MACOSX/` という Windows では不要なメタデータのディレクトリが生成されるので `zip` コマンドなどで圧縮する方が無難。

## パスワード生成
`zipcloak` コマンドで ZIP ファイルを暗号化することができるが、パスワードは自動生成してくれないので、自前で生成する必要がある。

### パスワードアシスタントで生成
```bash
open -a 'Keychain Access'
```
「キーチェーンアクセス」を起動し、<kbd>Ctrl</kbd> + <kbd>N</kbd> で新しいキーチェーンを作成するダイアログを表示し、鍵アイコンをクリックすると指定条件で生成されたパスワードが表示される。コマンドラインからこれを利用する方法は知られていない。

### コマンドラインで生成
```bash
openssl rand -base64 12
```
```bash
openssl rand -hex 8
```

## 暗号化
```bash
zipcloak archived.zip
```
`zipcloak` コマンドで ZIP ファイルを暗号化することができる。
linuxでプロセスをまとめてkill

たくさんのプロセスをいちいちkill -9で殺していくのはめんどくさいので一気にkillしたいときのコマンド。
(たまに使うがその度にノートのメモを探すのがめんどい)

```shell:
pgrep -f 'コマンド名' | xargs kill -9
````

コメントをいただきました。プロセス名指定であれば以下でも行けます！

```shell:
killall -9 <procname>
```
Elixirで小説を読もう!をスクレイピングしてみた

#はじめに

前回[Elixir入門やってみた](https://qiita.com/niya1123/items/632be2cbd19a5a5e1aff)という記事を書いたのですが,その際Webスクレイピング作って見ますーって言ったので作って見ました.

で、今回のWebスクレイピングの対象としたのは,[小説を読もう!](http://yomou.syosetu.com/)というサイトです.

ここでは素人からプロまで様々な人が無料で小説を書いたり,読んだりできるサイトです.

なぜここをスクレイピングしようと思ったかは,自分が読んでる小説が度々削除されたりして読めなくなる場面に結構出くわすので,ローカルに保存しとけば消されたとしても見れるんでここを対象にスクレイピングしました.

#コード諸々

では早速、コードを書いて行きたいと思いますが大体のことはコード内のコメントに書いてます.ここでは補足的なことを書いて行きます.

```elixir
defmodule Webscraping do
  @moduledoc """
  なろう小説をダウンロードするやつ.
  使用ライブラリはmix.exsを参考に.
  """
  require HTTPoison
  require Floki
  require Logger

  @doc """
  ここでhtmlをパースしていく.
  """
  def narou do
    # 基本的なurlで,ncodeを付与することにより特定の作品のUrlとなる.
    url = "https://ncode.syosetu.com/"
    ncode = IO.gets "Nコードを入力してください: "

    # 作品のurlのHTTPoisonによるresponse
    res = url <> ncode
    |> HTTPoison.get!
    
    # 小説のタイトル.Flokiを用いてパースしている.
    title = res.body
    |> Floki.find("p.novel_title")
    |> Floki.text

    #ダウンロードしている小説のタイトルを表示.この時点ではまだDLしている訳ではない.
    IO.puts "Now Downloading #{title}"

    #各話のサブタイトルを取得. Enum.mapを用いてListで情報を所持する.
    subtitle = res.body
    |> Floki.find("div.index_box")
    |> Floki.find("dd.subtitle")
    |> Enum.map(fn(t) -> Floki.text(t) end)
    
    #各話の本文を取得.Enum.mapを用いてListで情報を所持する.
    honbun = res.body
    |> Floki.find("dl")
    |> Floki.find("a")
    |> Floki.attribute("href")
    |> Enum.map(fn(num) -> HTTPoison.get!("https://ncode.syosetu.com"<>num).body
    |> Floki.find("div#novel_honbun") 
    |> Floki.text() end)
    
    #小説のタイトルの名前を持つディレクトリの作成.すでに存在していれば,新しく作成せずメッセージを出力.
    if File.exists? ("./"<>title) do
      IO.puts "フォルダがすでに存在します"
    else
      File.mkdir!(title)
    end

    # カレントディレクトリを先ほど作ったディレクトリに移動.
    File.cd!("./#{title}")

    # Enum.atを用いて各話を.txt形式で作成.2重for文では失敗するので注意.
    for i <- 0..length(subtitle)-1 do
      File.write "#{i+1}"<>Enum.at(subtitle,i)<>".txt", Enum.at(honbun,i)
    end

    # メッセージ
    IO.puts "Done!"
  end
```

##コード解説

さて,このコードははっきり言ってElixirをしっかりと学んでいる人からすれば稚拙もいいところかもしれないんですが,これ書いたのElixir知ってから１週間くらいで書いたので,その辺の稚拙な部分はお許しを...

と前置きはこれくらいにして,解説して行きます.

フローとしては

ncodeを聞く 
→ urlからHttpの情報をHTTPoisonから取得しそれをresとして所持　

→ resはheaderとbodyの情報を所持しているので,res.bodyとしbodyの情報からFlokiを使って小説のタイトルを探して,titleに所持させる.

→ 先ほど見つけたタイトルをダウンロードしているよという旨のメッセージをコンソールに表示.

→ 次にFlokiとEnum.mapを使ってres.bodyから小説のサブタイトル(各話のタイトル)をsubtitleに所持.

→ 同じくFlokiとEnum.mapを用いて各話の小説の本文をhonbunに所持.

→ titleを使って,このファイルが置かれているディレクトリ内にFile.mkdir!()を使ってtitleの所持している小説の名前のディレクトリを作成します.その際はFile.exists?()を使ってすでにそのディレクトリが存在していれば新しく作らないようにします.

→ カレントディレクトリをFile.cd!()を使って,titleのディレクトリに移動します(次の作業に必要です)

→ forを使ってファイルに書き込みします.File.writeを使います.ここで二重for文でsubtitleとhonbunを回すとElixirの仕様上書き出されるファイルがおかしくなるので,Enum.atを使ってindexを使います.

→ ダウンロードを終了したという旨を表示.

#終わりに
いかがだったでしょうか.どこまで説明した方がわからないので中途半端かもしれませんがお許しを.次回の内容は未定ですが何かしらを今月中か来月のはじめに書きます。何かあったらコメントください.それでは,今回はお疲れ様でした.
iOS 12のWKWebViewでcustomUserAgentの設定に失敗する問題の対処法

## 起きた問題
`WKWebView` を使ってウェブページを表示している箇所で、デフォルトのuserAgentの末尾に独自の文字列を付加したuserAgentを使ってリクエストを送る実装を採用していました。
しかし、この箇所をiOS 12.0で実行すると、ウェブページ側には独自の文字列が付加されていない、デフォルトのuserAgentが届いてしまっていました。

## 修正前の実装
```swift
// `WKWebView`型のwebViewというメンバー変数が宣言されているものとする
func load(url: URL) {
    guard let request = URLRequest(url: url) else {
        return
    }
    webView.evaluateJavaScript("navigator.userAgent") { (userAgent, error) in
        if let defaultUserAgent = userAgent {
            self.webView.customUserAgent = "\(defaultUserAgent) SomeCustomUserAgent"
        }
        self.webView.load(request)
    }
}
```

## 修正後の実装
デフォルトのuserAgentの取得元を別のWKWebViewインスタンスにすれば、問題なくuserAgentが上書きされました。

```swift
// `WKWebView`型のwebViewというメンバー変数が宣言されているものとする
func load(url: URL) {
    guard let request = URLRequest(url: url) else {
        return
    }
    var dummyWebView: WKWebView? = WKWebView() // デフォルトのUserAgentを取得するための別インスタンスを作る
    dummyWebView.evaluateJavaScript("navigator.userAgent") { (userAgent, error) in
        dummyWebView = nil // evaluateJavaScript()が完了するまでdummyWebViewが開放されないよう、クロージャ内で参照しておく
        if let defaultUserAgent = userAgent {
            self.webView.customUserAgent = "\(defaultUserAgent) SomeCustomUserAgent"
        }
        self.webView.load(request)
    }
}
```

### 上記の実装にした理由
推測の域を出ないのですが、iOS 12からWKWebViewの仕様が変わって一度userAgentのフィールドを参照すると（＝ `WKWebView#evaluateJavaScript()` で `navigator.userAgent` フィールドにアクセスすると）、直近のリクエストが終了するまでの間userAgentの値をキャッシュする仕組みが入ったのでは無いかと予想しました。
その仮設を基に、 `navigator.userAgent` にアクセスしないままcustomUserAgentに値を設定する方法を探った結果、上記のように `WKWebView#load()` を実行したいインスタンスとは別のインスタンスで `WKWebView#evaluateJavaScript()` を実行する方法を見つけました。

## 参考リンク
[iOS 12 WKWebview set customUserAgent not work? - Stack Overflow](https://stackoverflow.com/q/51356476)
Amazon S3 内のCSV ファイル群に外部アプリから直接双方向アクセス（CData Drivers）

CData CSV Drivers 2018版では、Amazon S3、Box、Google Drive、SharePoint Online などに格納されているCSV ファイルに外部アプリケーションからアクセスできるようになりました。

各種ログデータやセンサーデータをS3 などのクラウドストレージに格納するケースは多いと思います。ただし、格納したデータをBI やアナリティクスツールで使う際には、ファイルをツールからアクセスできる別の場所にダウンロード・保管しなおしてから使うという手間がありました。特に日次以上の頻度で更新されるファイルとなると負荷が大きくなります。

CData CSV Drivers の2018版では、S3 などに格納されたCSV ファイルに直接BI、帳票、ETL、カスタムアプリケーションからSQL でアクセスすることが可能になります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/116843/390a4669-344c-23e8-f142-55898a2929ed.png)


#CData CSV JDBC Driver をダウンロード
CData Website から[CData JDBC Driver for CSV](https://www.cdata.com/jp/drivers/csv/jdbc/)をダウンロードします。30日の試用版があります。他にもODBC/ADO/NET/Excel Add-in/PowerBI/SSIS/FireDAC などのテクノロジーに対応しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/116843/f4d2f312-d4fa-fa56-c2b4-dc63f2f5537e.png)


#Amazon S3 の接続設定
JDBC 接続のデータを確認するツールとして[DB Visualizer](https://www.dbvis.com/) というツールを使います。JDBC をサポートするツールならどこでもドライバーは動かせるので、Eclipse、IntelliJ などのIDE でも構いません。

##Driver の指定
「Tools」タブから「Driver Manager」を選択します。
Driver Manager で左上の「＋」マークをクリックして、新しいドライバーを登録します。
・ドライバー名：任意
・URL Format：jdbc:
・Driver File Path：フォルダマークをクリックして、インストールしたCData JDBC Driver から「cdata.jdbc.csv.jar」ファイルを指定します

ディレクトリパスはCData\CData JDBC Driver for CSV 2018J\lib です。

Driver Class に「cdata.jdbc.csv.CSVDriver」と表示されればDriver 指定は完了ですので、Driver Manager を閉じます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/116843/51beb725-c1de-5e44-3db1-d2b48d3bbea1.png)



#DB Visualizer でAmazon S3 上のCSV ファイル群に接続を確立
##接続するAmazon S3 の対象フォルダ
以下に保存されているCSV ファイルをJDBC 接続で利用します。
データソースとして指定できるのはフォルダ単位です。

バケット：csvdrivertest
フォルダ：CSVTest1

![image.png](https://qiita-image-store.s3.amazonaws.com/0/116843/49ae6099-7581-31f4-7ea2-4b2f680f1c72.png)

##CSV への接続設定
DB Visualizer の左ペインで新しい接続を追加します。今回はウィザード無しを選択します。

| 項目      |       Note |  
|:--------------------|:-----------------------|
| Name             |任意|
|Database Type|Generic|
|Driver(JDBC)|先ほどDriver Manager で登録したドライバーを選択|
|Database URL|以下の接続文字列を入力|

接続文字列：jdbc:csv:URI=s3://MyBuket/MyFolder;AccessKey=MyAccessKey;SecretKey=MySecretKey;

この例では、URI は、URI=s3://csvdrivertest/CSVTest1; です。
通常のブラウザのURL とは異なりますので注意してください。

「Connect」をクリックすると」接続ができます。

##DB Visualizer からCSV データをクエリ
Amazon S3 上のフォルダへの接続が成功すると、左側のConnection ペインにCSV フォルダができ、Amazon S3 のフォルダ内のCSV ファイルがすべてテーブルとして表示されます。
あとは通常のDB と同じように、SELECT * from CSV ファイル名などでCSV データがクエリ可能です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/116843/8c9a2e48-ce5d-2dbb-aa22-fce88c91a970.png)

このように、JDBC をサポートするツール・アプリからAmazon S3 上のCSV にリアルタイム接続ができました。

BI、アナリティクス、ETL などでクラウドストレージ上のCSV データを扱う際に是非活用してください。
Rails5で画像が表示されない。

# ローカルで画像が表示されない
調べても調べてもproductionでみたいなので

公式ドキュメント読めばよかったのかもしれないけれど結局いろいろ試した結果

```:フォルダ
#不必要な部分は割愛してます。
- app
  └-assets
   └-images
    └-icons
     └-✗✗✗.png
```

```:NG
background: url('images/icons/✗✗✗.png');
background: url('/assets/images/icons/✗✗✗.png');
その他いろいろなPath
```

```:OK
background: url('icons/✗✗✗.png');
```
※image_tagでも同じです。
【PostgreSQL】SELECTの結果をINSERTする

#VALUESが要らない
何度も同じ過ちを繰り返している。。。

```sql:誤りのある構文
INSERT INTO table (...)
VALUES (SELECT...);
```
結果は、

```sql
ERROR:  syntax error at or near "SELECT"
```

正しくは、

```sql:正しい構文
INSERT INTO table (...)
SELECT...;
```

これでSELECTの結果をINSERTできます。
MongoDBのC言語ドライバのビルド方法

# 概要

MongoDBのC言語ドライバのビルド方法です。
日本語の情報が少なかったのでまとめておきます。

# 前提条件

* Visual Studio 2010 以降がインストールされている環境 (または Visual Studio 2015 Express)

# ビルド方法

MongoDBのC言語ドライバはバイナリが配布されていないためソースからのビルドが必要となります。

## 1. CMakeのインストール

[CMake](https://cmake.org/) へアクセスしてdownloadのページから **Windows win64-x64 Installer** をダウンロードします。
ダウンロード後、msiパッケージを実行してインストールします。

## 2. mongo-c-driverのダウンロード

[mongo-c-driver](https://github.com/mongodb/mongo-c-driver) へアクセスしてソースをダウンロードします。

## 3. CMake によるビルド

コマンドプロンプトを起動後、ソースのルートディレクトリへ移動して以下のコマンドを実行します。

```
set PATH="C:\Program Files\CMake\bin";%PATH%
mkdir cmake-build
cd cmake-build
cmake -G "Visual Studio 14 2015 Win64" "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" "-DCMAKE_PREFIX_PATH=C:\mongo-c-driver" ..
```

## 4. MSBuild によるビルド

引き続き以下のコマンドを実行します。

```
set PATH="C:\Program Files (x86)\MSBuild\14.0\Bin";%PATH%
msbuild.exe /p:Configuration=Release ALL_BUILD.vcxproj
msbuild.exe /p:Configuration=Release INSTALL.vcxproj
```

警告が大量に表示されますが、ビルドに成功すると **C:\mongo-c-driver** に以下のバイナリが生成されます。

* DLLファイル
* インクルードヘッダファイル
* ライブラリファイル

# ビルド構成について

上記の手順ではリリース構成でビルドを行っていますが、 **/p:Configuration=** で指定する値を以下の値に変更することで異なるビルド構成でビルドすることも可能です。

|値|説明|
|:---|:---|
|Debug|デバッグ構成でビルド|
|Release|リリース構成でビルド|
|MinSizeRel|最小サイズ構成でビルド|
|RelWithDebInfo|デバッグ情報付きリリース構成でビルド|

※ **/p:Configuration=** を指定せずにビルドした場合、デバッグ構成としてビルドされます。実行環境に **ucrtbased.dll** [^1] が存在していないとリンクしたプログラムの実行時に以下のエラーが表示されるため注意が必要です。

![error.png](https://qiita-image-store.s3.amazonaws.com/0/278145/349250d7-206d-aafb-4e94-45350e8151d4.png)

[^1]: [Cランタイムライブラリ](https://msdn.microsoft.com/ja-jp/library/abx4dbyh.aspx) のデバッグ版です。VisualStudioの再頒布パッケージではインストールされません。
Facebook Messenger botのm.meリンクの確認方法

WebからFacebook Messenger botへ遷移させる際に使用する短縮URL「m.meリンク」の確認方法です。

> m.meはFacebook側でURLを短縮させるサービスであり、利用者、ページ、Messengerのボットに利用者をリダイレクトすることができます。ウェブサイトやメールニュースレターなどで使用できます。
>
>利用者がm.meリンク経由でボットと新しいスレッドを開始したり、既存のスレッドを続行した場合は、次のメッセージがスレッドに表示されます。「You have entered this conversation by following a link. (リンクからこの会話に参加しました)We've let PAGE_NAME know you're here. (この会話に参加していることはPAGE_NAMEに通知されます)」
>
>
> [m.meリンク - Messengerプラットフォーム](https://developers.facebook.com/docs/messenger-platform/discovery/m-me-links/?locale=ja_JP)

# m.meリンクの確認方法
Facebookビジネスマネージャーを開き、対象のFacebookページを選択。画面右上の「設定」を選択します。
![_スクリーンショット_2018-05-10_11_59_31.jpg](https://qiita-image-store.s3.amazonaws.com/0/6380/20abf9b4-5f7b-24ab-1e59-80b279f4e663.jpeg)

画面左のサイドメニューから「Messengerプラットフォーム」を選択。
![スクリーンショット_2018-05-10_12_01_17.jpg](https://qiita-image-store.s3.amazonaws.com/0/6380/3e44401e-41dd-5f13-097d-b6964278950b.jpeg)

「Your Messenger Link」でメッセンジャーbotのm.meリンクが確認できます。
![_スクリーンショット_2018-05-10_12_01_35.jpg](https://qiita-image-store.s3.amazonaws.com/0/6380/50bd19b8-8eb8-db63-fe96-d3e8ba6a45ed.jpeg)
FacebookのIDマッチングAPIでPage scoped IDを取得する方法

事前にApp scoped user IDが取得できてる前提。

# Page Scoped ID の取得手順

FacebookのIDマッチングAPI `GET /{app_scoped_user_id}/ids_for_pages`を使って、ユーザーのPage Scoped IDが取得できる。
[IDマッチングAPI - Facebookログイン](https://developers.facebook.com/docs/facebook-login/connecting-accounts)

リクエストURL&パラメータは以下

```
GET /{app_scoped_user_id}/ids_for_pages
	?access_token={app_access_token}
	&appsecret_proof={appsecret_proof}
```

## パラメータ
{app_scoped_user_id}：対象アプリのApp scoped user IDを指定
{app_access_token}：[Facebookアプリのapp_access_tokenの生成手順 - Qiita](https://qiita.com/unsoluble_sugar/items/8fcb8ca7d76eca8fa571)
{appsecret_proof}：[Facebookアプリのappsecret_proofの生成手順 - Qiita](https://qiita.com/unsoluble_sugar/items/eb73f0f7035da8d4d3fa)
express-validatorを使った際のまとめ

express-validatorを使って基本的なバリデーションのまとめ

## 環境
・node:8.10.0
・express-validator:5.3.0

## epress-validator

https://express-validator.github.io/docs/index.html

## npm
```bash
$ npm install --save express-validator
```

## サンプルコード

```app.js
// ...rest of the initial code omitted for simplicity.
const { check, validationResult } = require('express-validator/check');

app.post('/user', [
    check('name').isString(),
    check('name').isLength({ max: 30 }),
    check('password').isLength({ min: 7 })
], (req, res) => {
  // Finds the validation errors in this request and wraps them in an object with handy functions
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        return res.status(422).json({ errors: errors.array() });
    }

    User.create({
        username: req.body.name,
        password: req.body.password
    }).then(user => res.json(user));
});
```

### routeメソッド内でもOK
```app.js
router.post('/user', [
    check('name').isString(),
    check('name').isLength({ max: 30 }),
    check('password').isLength({ min: 7 })
], (req, res) => {
// ~~~~~~~~~~~~~~
});
```

```
{
    "errors": [
        {
            "location": "body",
            "param": "name",
            "value": “foo&%$#*”,
            "msg": "Invalid value"
        },
        {
            "location": "body",
            "param": "password",
            "value": “Foo”,
            "msg": "Invalid value"
        }
    ]
}
```


### オプション引数が長くなるのが嫌だったので別ファイルに移動
```validator.js
import {check} from 'express-validator/check';

export const checkUser = [

    // こんな感じでバリデーションが設定できる
    check('name').isString(),
    check('name').isLength({ max: 30 }),
    check('email').isEmail(),
    check('email').isLength({ max: 255 }),
    check('password').isLength({ min: 7 , max: 128 }),
    check('password').isAlphanumeric()
];
```

## カスタマイズする
既に登録済みの際はエラーを出したいとかありますよね、

```validator.js
check('email').custom(email => {
	// 適当な処理
	if {
		// OK
	} else {
		return Promise.reject('');
	}
 }).withMessage('Error. Foo'),
```

```
{
    "errors": [
        {
            "location": "body",
            "param": "email",
            "value": “foo@foo.com”,
            "msg": “Error. Foo”
        }
    ]
}
```
Facebookアプリのappsecret_proofの生成手順

# appsecret_proof の説明
> グラフAPIコールは、クライアントから、またはクライアントの代わりにサーバーから実行できます。 サーバーからの呼び出しは、appsecret_proofと呼ばれるパラメーターを追加することによって、セキュリティを強化できます。
> [Graph APIリクエストの保護 - グラフAPI](https://developers.facebook.com/docs/graph-api/securing-requests/?translation)

# 生成方法
Railsでの呼び出し例。Macのターミナルでsha256のハッシュを生成する。

```
$ rails console
OpenSSL::HMAC.hexdigest('sha256', [app_secret], [app_access_token])
=> "xxxxxxxxxxxxxx|yyyyyyyyyyyyyyyyyyyyyyyyyyyy"
```

ドキュメントにはPHPでの呼び出し記述例あり。

```
$appsecret_proof= hash_hmac('sha256', $access_token, $app_secret); 
```

[Graph APIリクエストの保護 - グラフAPI](https://developers.facebook.com/docs/graph-api/securing-requests)

# 参考
[Facebookアプリのapp secretの確認方法 - Qiita](https://qiita.com/unsoluble_sugar/items/70496f1dcc089e67f01a)
[Facebookアプリのapp_access_tokenの生成手順 - Qiita](https://qiita.com/unsoluble_sugar/items/8fcb8ca7d76eca8fa571)
Facebookアプリのapp_access_tokenの生成手順 

以下のGraph API呼び出しを行う。

```
GET /oauth/access_token
    ?client_id={app-id}
    &client_secret={app-secret}
    &grant_type=client_credentials
```

{app-id}：アプリID（[Facebook for developers](https://developers.facebook.com/apps/)で確認）
{app-secret}：[Facebookアプリのapp secretの確認方法 - Qiita](https://qiita.com/unsoluble_sugar/items/70496f1dcc089e67f01a)

responseにaccess_tokenが入ってる。
【C#】言語バージョン指定 

Visual StudioでC#の言語バージョンてどこで設定するの？が分かりにくかったのでメモです。


プロジェクトのプロパティ->ビルドタブ->詳細設定クリック
![projectproperty.png](https://qiita-image-store.s3.amazonaws.com/0/241416/a8b321ed-67ea-ca01-2cb0-963f1316dc85.png)



詳細設定ポップアップの言語バージョンのプルダウンから対象のバージョン選択
![summary2.png](https://qiita-image-store.s3.amazonaws.com/0/241416/24a2b589-1857-df8f-e955-534bcbc0f5ee.png)


[参考 : How do I disable C# 6 Support in Visual Studio 2015?](https://stackoverflow.com/questions/30461640/how-do-i-disable-c-sharp-6-support-in-visual-studio-2015)


とある事情でVS2012で編集できる状態を保つ必要があったが、私はVS2017を使いたかった為。
Xcode10からマルチカーソル機能が使えるようになったぞ

タイトルの通りなのですが、Xcode10からついにマルチカーソル機能が使用できるようになりました。
今までも `⌘+Control+E` (Use Selection for Replace) でマルチカーソルもどきは使用できたのですが、本格的なマルチカーソルは今回が初です


## コマンド

#### Select Column Up(Down)  `Shift+Control+↑` `Shift+Control+↓`
![Untitled.gif](https://qiita-image-store.s3.amazonaws.com/0/121299/c9bf1274-2118-f151-cda8-ef87090d9497.gif)

（ダブルクォーテーションの補完が1行目のほうしかできてない😅）

上または下の行にカーソルを複製する。

このコマンドだけ唯一デフォルトでショートカットキーが設定されています。**他のに関してはデフォルトだと設定されてないので自分で設定しないといけません**。

#### Select All Symbols
![Untitled2.gif](https://qiita-image-store.s3.amazonaws.com/0/121299/10562418-60af-8e24-9ded-d9d98626f274.gif)

同じシンボルをすべて選択してカーソルを割り当てる。

これによる選択はただ文字列が一致しているかを見ているのではなく、コードとして別の意味を持ったシンボルであれば選択されないようになっています。
例えば、上の例だと`textLabel.text`の`.text`部分でこのコマンドを実行しても、下の`.textColor`のtextは選択されません。
つまるところ既存の `⌘+Control+E` (Use Selection for Replace) と同じように見えます。どこに差分があるのだろう？


#### Split Selections By Lines
![Untitled3.gif](https://qiita-image-store.s3.amazonaws.com/0/121299/081841c6-8102-08bd-cb01-40008c685093.gif)


選択されている範囲を行ごとに分割する感じです。どういうときに使うんだろう？画像ではCSVとかから雑多にコピペした想定で行末が揃ってない文字列をトリムしてみましたが、あんまり使う機会ないような？



#### Balance Delimiters

![Untitled4.gif](https://qiita-image-store.s3.amazonaws.com/0/121299/f0886f84-7228-d33f-2357-760d1718ece1.gif)

字面からは意味がよくわからないですが、現在のカーソル位置の外側にある括弧を選択するっぽい挙動をします。これはマルチカーソル関係ないですね。

これもどういった場面で有用なのでしょう？長い関数があってその始点を知りたいときとか、まるっと削除したいときとか？



## おわり

Xcode10で追加されたカーソル選択範囲まわりの機能を紹介しました。ようやく実装されたマルチカーソル、便利なのでぜひ使って開発効率向上させましょう。

ちなみにXcodeSourceEditorExtensionでは以前から `XCSourceTextBuffer` に複数の選択範囲（`XCSourceTextRange`) を渡すことができましたが、Xcode9以前では渡しても意味がありませんでした。
ところがXcode10では渡した部分がきちんとカーソルに反映されるようになったため、Sublimeなどのような押した回数だけ選択部分が増えるタイプのマルチカーソルもXcodeSourceEditorExtensionを用いれば作れそうでした。
2泊3日でワークショップをした話(2回目)

# 目的
 - 1箇所に集まり全員で一つのものを期間内に作り上げる

# ルール
 - 期間内にリリース(完成)まで持っていくことが主題として、勉強も兼ねる
 - 期間内でリリース(完成)まで持っていけるアイデアをメンバーが出して、その中からみんなで決める
 - アイデア出した人がある程度やりたいこと(仕様)を決めてメンバーに伝える
 - できるだけ費用がかからないようにする

# 今回作るもの
 - slackで行う対戦ゲーム

# 作業環境
 - 期間: 2018/9/15 - 2018/9/17
 - 時間: 11 - 21時
 - 場所: コワーキングスペースを３日間利用
 - 宿: 各々確保

# 開発環境
 - タスク管理: trello
 - ソース管理: github
 - API: GCP(無料インスタンス)
 - database: redis(redis labs)
 - nodejs(v8.12.0) / typescript(3.0.3) / express(4.16.0)
 - slack api

# できたこと
 - slack bot への入出力
 - ゲームのコアロジックの一部
 - redisとのio

# できなかったこと
 - 各々作った部品の結合
 - サーバーへデプロイしての稼働
 - ゲームとして成立させるための調整・拡張
 - 振り返り・反省会

# 反省点
 - 目的・ルールが共有できてなかった
 - 結局使わなかったサーバーセットアップ・デプロイに時間を費やした
 - どんな形でも完成まで持っていけなかった

# 改善点
 - 目的がちゃんと共有されているメンバーでやる
 - 完成まで持っていくことを前提に進めるようにする
 - 最終日は作ったもののアップデートと振り返りに使えるように仕様の必要最小限を見極めることとその共有

# 所感
 - １回目と同じメンバーだったので目的・ルールが共有されていると思い込んでいたのがダメだった
 - 完成まで持っていけないと良くないとは思っていたが、体験すると改めてダメだと感じた
 - すごくモヤモヤした結果になったけど、これも良い経験だと割り切り次を考えよう

# １回目のログ
 - [一泊二日でワークショップをした話](https://qiita.com/taka10257/items/12d8548d6aa5e4217d13)
ChromeでMediaQueryの値と実画面サイズがずれるときは

Chrome　DevToolsにはCSSで設定されたMediaQueryを表示する機能があります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/127934/a8f2eae8-57f1-b9dc-0b81-099e12086be8.png)

しかし、画面が拡大されている場合にMediaQueryと上記の画面サイズの値とがずれてしまうことがあります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/127934/36e5cf80-78c6-bc4a-18fb-b19103f38de7.png)

**Media Queryと画面サイズがずれてしまう場合は、拡大率をリセットしてみてください**
【PHP】名前が動的に変化する変数を定義する【可変変数】

# はじめに
最近ちょっとPHPを触っています。
諸事情によりノンフレームワークのため、いわゆるメタプロっぽいものが必要になる機会があったので、可変変数についてまとめます。

利用しているPHPのバージョンは5系です。
※5系と7系では挙動の違いがあるようです。
詳細は以下
http://php.net/manual/ja/migration70.incompatible.php#migration70.incompatible.variable-handling.indirect

# 可変変数とは
名前をそのまま読むと、変化できる変数ということになりますが、変数はもともと中身を変えられるものなので何が？？？ってなりますよね。

可変変数は、値ではなく、「名前」を動的に変化させることができます。
受け取った文字列で、変数を定義する、などですね。

# 具体例

```php5
$fruits = Array
(
    'banana' => 'ばなな',
    'apple' => 'りんご',
    'peach' => 'もも',
    'pear' => 'なし',
    'orange' => 'みかん'
);
```
上のような、フルーツを格納する連想配列があるとします。
これを、それぞれのキーの変数に再格納したい、というときに、

```php5

foreach ($fruits as $key => $value){
  $$key = $value;
}
```
上のように書くことができます。
上記のコードで、
```$banana```
```$apple```
```$peach```
```$pear```
```$orange```
が定義され、それぞれ値が格納されます。

なので、

```php5
print $banana; // ばなな
print $apple; // りんご
print $peach; //　もも
print $pear; //　なし
print $orange; //　みかん
```
というように出力できます。

$のあとに、文字列を渡すと、その変数が定義されるイメージです。
ただし、文字列リテラルをそのまま渡す場合、{}で囲む必要があるので注意です。

```php5
// これはだめ
// $'cherry'

// これなら、$cherryが定義される
${'cherry'};
```


また、呼び出し側も動的にできます。

```php5
// 通常の変数定義
$cherry = 'さくらんぼ';

// 動的な呼び出し
echo ${'cherry'}; //文字列を直接
echo ${'che'.'rry'}; //文字列結合でもok
// 一回変数に入れる場合
$name = 'cherry';
echo $$name;

// 定義と同じく、これはだめ
// echo $'cherry'
```

# おわりに
これは、いわゆるメタプログラミングなどで利用されるもので、乱用するとコードが非常に読みづらくなります。
利用する際は、きちんとコメントをいれて、中のコードの詳細を読まなくても使えるようにしないと、負債になる可能性が高いです。用法用量を守って正しく利用しましょう。

# 参考記事
https://qiita.com/andrew954/items/b7e3b3f6d595cc655923
http://php.net/manual/ja/language.variables.variable.php
Facebookアプリのapp secretの確認方法

1.[Facebook for developers](https://developers.facebook.com/apps/)で対象アプリを選択。
2.「設定」>「ベーシック」を選択。
![スクリーンショット 2018-09-18 12.24.44.png](https://qiita-image-store.s3.amazonaws.com/0/6380/a782c06f-6d09-795a-013a-a3b1e3f708e1.png)
3.app secretの「表示」をクリックしてパスワード入力で確認できる。
![スクリーンショット_2018-05-14_12_44_15.jpg](https://qiita-image-store.s3.amazonaws.com/0/6380/2f05fa8e-7160-77fe-8555-5b892ba9cb38.jpeg)
WEBフォント サブセット用 第一水準+アルファベット+記号

#サブセット化の際のコピペ用 第一水準+アルファベット+記号

googleでヒットするページがアルファベットが足りないなど問題のある情報も多いので自分用に備忘録。

```plaintext
亜哀挨愛曖悪握圧扱宛嵐安案暗以衣位囲医依委威為畏胃尉異移萎偉椅彙意違維慰遺緯域育一壱逸茨芋引印因咽姻員院淫陰飲隠韻右宇羽雨唄鬱畝浦運雲永泳英映栄営詠影鋭衛易疫益液駅悦越謁閲円延沿炎怨宴媛援園煙猿遠鉛塩演縁艶汚王凹央応往押旺欧殴桜翁奥横岡屋億憶臆虞乙俺卸音恩温穏下化火加可仮何花佳価果河苛科架夏家荷華菓貨渦過嫁暇禍靴寡歌箇稼課蚊牙瓦我画芽賀雅餓介回灰会快戒改怪拐悔海界皆械絵開階塊楷解潰壊懐諧貝外劾害崖涯街慨蓋該概骸垣柿各角拡革格核殻郭覚較隔閣確獲嚇穫学岳楽額顎掛潟括活喝渇割葛滑褐轄且株釜鎌刈干刊甘汗缶完肝官冠巻看陥乾勘患貫寒喚堪換敢棺款間閑勧寛幹感漢慣管関歓監緩憾還館環簡観韓艦鑑丸含岸岩玩眼頑顔願企伎危机気岐希忌汽奇祈季紀軌既記起飢鬼帰基寄規亀喜幾揮期棋貴棄毀旗器畿輝機騎技宜偽欺義疑儀戯擬犠議菊吉喫詰却客脚逆虐九久及弓丘旧休吸朽臼求究泣急級糾宮救球給嗅窮牛去巨居拒拠挙虚許距魚御漁凶共叫狂京享供協況峡挟狭恐恭胸脅強教郷境橋矯鏡競響驚仰暁業凝曲局極玉巾斤均近金菌勤琴筋僅禁緊錦謹襟吟銀区句苦駆具惧愚空偶遇隅串屈掘窟熊繰君訓勲薫軍郡群兄刑形系径茎係型契計恵啓掲渓経蛍敬景軽傾携継詣慶憬稽憩警鶏芸迎鯨隙劇撃激桁欠穴血決結傑潔月犬件見券肩建研県倹兼剣拳軒健険圏堅検嫌献絹遣権憲賢謙鍵繭顕験懸元幻玄言弦限原現舷減源厳己戸古呼固股虎孤弧故枯個庫湖雇誇鼓錮顧五互午呉後娯悟碁語誤護口工公勾孔功巧広甲交光向后好江考行坑孝抗攻更効幸拘肯侯厚恒洪皇紅荒郊香候校耕航貢降高康控梗黄喉慌港硬絞項溝鉱構綱酵稿興衡鋼講購乞号合拷剛傲豪克告谷刻国黒穀酷獄骨駒込頃今困昆恨根婚混痕紺魂墾懇左佐沙査砂唆差詐鎖座挫才再災妻采砕宰栽彩採済祭斎細菜最裁債催塞歳載際埼在材剤財罪崎作削昨柵索策酢搾錯咲冊札刷刹拶殺察撮擦雑皿三山参桟蚕惨産傘散算酸賛残斬暫士子支止氏仕史司四市矢旨死糸至伺志私使刺始姉枝祉肢姿思指施師恣紙脂視紫詞歯嗣試詩資飼誌雌摯賜諮示字寺次耳自似児事侍治持時滋慈辞磁餌璽鹿式識軸七𠮟失室疾執湿嫉漆質実芝写社車舎者射捨赦斜煮遮謝邪蛇尺借酌釈爵若弱寂手主守朱取狩首殊珠酒腫種趣寿受呪授需儒樹収囚州舟秀周宗拾秋臭修袖終羞習週就衆集愁酬醜蹴襲十汁充住柔重従渋銃獣縦叔祝宿淑粛縮塾熟出述術俊春瞬旬巡盾准殉純循順準潤遵処初所書庶暑署緒諸女如助序叙徐除小升少召匠床抄肖尚招承昇松沼昭宵将消症祥称笑唱商渉章紹訟勝掌晶焼焦硝粧詔証象傷奨照詳彰障憧衝賞償礁鐘上丈冗条状乗城浄剰常情場畳蒸縄壌嬢錠譲醸色拭食植殖飾触嘱織職辱尻心申伸臣芯身辛侵信津神唇娠振浸真針深紳進森診寝慎新審震薪親人刃仁尽迅甚陣尋腎須図水吹垂炊帥粋衰推酔遂睡穂随髄枢崇数据杉裾寸瀬是井世正生成西声制姓征性青斉政星牲省凄逝清盛婿晴勢聖誠精製誓静請整醒税夕斥石赤昔析席脊隻惜戚責跡積績籍切折拙窃接設雪摂節説舌絶千川仙占先宣専泉浅洗染扇栓旋船戦煎羨腺詮践箋銭潜線遷選薦繊鮮全前善然禅漸膳繕狙阻祖租素措粗組疎訴塑遡礎双壮早争走奏相荘草送倉捜挿桑巣掃曹曽爽窓創喪痩葬装僧想層総遭槽踪操燥霜騒藻造像増憎蔵贈臓即束足促則息捉速側測俗族属賊続卒率存村孫尊損遜他多汰打妥唾堕惰駄太対体耐待怠胎退帯泰堆袋逮替貸隊滞態戴大代台第題滝宅択沢卓拓託濯諾濁但達脱奪棚誰丹旦担単炭胆探淡短嘆端綻誕鍛団男段断弾暖談壇地池知値恥致遅痴稚置緻竹畜逐蓄築秩窒茶着嫡中仲虫沖宙忠抽注昼柱衷酎鋳駐著貯丁弔庁兆町長挑帳張彫眺釣頂鳥朝貼超腸跳徴嘲潮澄調聴懲直勅捗沈珍朕陳賃鎮追椎墜通痛塚漬坪爪鶴低呈廷弟定底抵邸亭貞帝訂庭逓停偵堤提程艇締諦泥的笛摘滴適敵溺迭哲鉄徹撤天典店点展添転塡田伝殿電斗吐妬徒途都渡塗賭土奴努度怒刀冬灯当投豆東到逃倒凍唐島桃討透党悼盗陶塔搭棟湯痘登答等筒統稲踏糖頭謄藤闘騰同洞胴動堂童道働銅導瞳峠匿特得督徳篤毒独読栃凸突届屯豚頓貪鈍曇丼那奈内梨謎鍋南軟難二尼弐匂肉虹日入乳尿任妊忍認寧熱年念捻粘燃悩納能脳農濃把波派破覇馬婆罵拝杯背肺俳配排敗廃輩売倍梅培陪媒買賠白伯拍泊迫剝舶博薄麦漠縛爆箱箸畑肌八鉢発髪伐抜罰閥反半氾犯帆汎伴判坂阪板版班畔般販斑飯搬煩頒範繁藩晩番蛮盤比皮妃否批彼披肥非卑飛疲秘被悲扉費碑罷避尾眉美備微鼻膝肘匹必泌筆姫百氷表俵票評漂標苗秒病描猫品浜貧賓頻敏瓶不夫父付布扶府怖阜附訃負赴浮婦符富普腐敷膚賦譜侮武部舞封風伏服副幅復福腹複覆払沸仏物粉紛雰噴墳憤奮分文聞丙平兵併並柄陛閉塀幣弊蔽餅米壁璧癖別蔑片辺返変偏遍編弁便勉歩保哺捕補舗母募墓慕暮簿方包芳邦奉宝抱放法泡胞俸倣峰砲崩訪報蜂豊飽褒縫亡乏忙坊妨忘防房肪某冒剖紡望傍帽棒貿貌暴膨謀頰北木朴牧睦僕墨撲没勃堀本奔翻凡盆麻摩磨魔毎妹枚昧埋幕膜枕又末抹万満慢漫未味魅岬密蜜脈妙民眠矛務無夢霧娘名命明迷冥盟銘鳴滅免面綿麺茂模毛妄盲耗猛網目黙門紋問冶夜野弥厄役約訳薬躍闇由油喩愉諭輸癒唯友有勇幽悠郵湧猶裕遊雄誘憂融優与予余誉預幼用羊妖洋要容庸揚揺葉陽溶腰様瘍踊窯養擁謡曜抑沃浴欲翌翼拉裸羅来雷頼絡落酪辣乱卵覧濫藍欄吏利里理痢裏履璃離陸立律慄略柳流留竜粒隆硫侶旅虜慮了両良料涼猟陵量僚領寮療瞭糧力緑林厘倫輪隣臨瑠涙累塁類令礼冷励戻例鈴零霊隷齢麗暦歴列劣烈裂恋連廉練錬呂炉賂路露老労弄郎朗浪廊楼漏籠六録麓論和話賄脇惑枠湾腕あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをんがぎぐげござじずぜぞだぢづでどばびぶべぼぱぴぷぺぽぁぃぅぇぉっゃゅょアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨャュョラリルレロワヲンガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポヵヶァィゥェォッヴabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ＡＢＣＤＥＦＧＨＩＪＫＬＭＮＯＰＱＲＳＴＵＶＷＸＹＺａｂｃｄｅｆｇｈｉｊｋｌｍｎｏｐｑｒｓｔｕｖｗｘｙｚ０１２３４５６７８９!@~`#$%^&*()_-+=|}{]['";:/?.,<> 　！＠〜｀＃＄％＾＊（）＿ー＝＋｜￥｝｛’”：；・？＞。、＜「」『』
```
Arduino Nano, ATmega328P マイコンボードに書き込みエラー対処

# Arduino Nano マイコンボードに書き込みエラー発生
## Arduino Nano が、デバイスマネージャーで「CH340」になっている。
![デバイス](https://qiita-image-store.s3.amazonaws.com/0/77496/0af6007b-4bfe-b6ba-b83c-4818edf13783.png)

## 書き込もうとするとエラーが発生
```
Arduino：1.8.7 (Windows 10), ボード："Arduino Nano, ATmega328P"

最大30720バイトのフラッシュメモリのうち、スケッチが994バイト（3%）を使っています。
最大2048バイトのRAMのうち、グローバル変数が9バイト（0%）を使っていて、ローカル変数で2039バイト使うことができます。
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x46
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x31
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x2c
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x31
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x37
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x30
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x20
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x73
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x65
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x63

```
マイコンボードに書き込もうとしましたが、エラーが発生しました。
このページを参考にしてください。
http://www.arduino.cc/en/Guide/Troubleshooting#upload

「ファイル」メニューの「環境設定」から
「より詳細な情報を表示する：コンパイル」を有効にすると
より詳しい情報が表示されます。


## プロセッサを、「Old」に変更すると正常に書き込めます。

![Arduino](https://qiita-image-store.s3.amazonaws.com/0/77496/02a16886-474c-3eb9-7e28-9b1b301e7f81.png)
rails version 5.1でjqueryを使う方法

前まで、railsで普通に使えていたjavascriptのjqueryが突然動かなくなりました。

なにやら、バージョンをあげてしまったことが要因かと思います。（前までrails 4系だった）
使おうとすると、$ is not defined のエラーが吐かれました。

で、rails5系でjqueryを使う方法。調べました！！

１
`<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>`

`<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>`

以上の、どちらかの記述をapplication.htmlのheadに書けば動く。
https://developers.google.com/speed/libraries/devguide#jquery

２
gem 'jquery-rails' 
gem 'jquery-ui-rails'
を記述後,application.jsに
//= require jquery
//= require jquery-ui
//= require rails-ujs
//= require turbolinks
//= require_tree .
を書けば動く。
Rails5.1では脱jQueryを図っており、今までjquery-ujsが担っていたremote:true等の働きをrails-ujsが担ってくれているみたいです。
以下参照
https://rails-school.net/rails51-jquery/
【swift】アプリを削除してもデータを残す方法 （KeyChain）

iOSアプリでデータを端末に保存する方法でよく利用されるのが、`UserDefaults`だと思われます。
ただ、UserDefaultsは、アプリを削除するとデータが消えてしまうので、アプリ削除を繰り返すと不正が行われてしまう場合などは、KeyChainを使ってデータを保存した方がいいです。

# 実装方法
swiftでKeyChainに保存する場合は、以下のようなコードになります。

## 保存

```swift:ViewController.swift
// 保存
func saveKeyChain() {
    // 保存する文字列
    let str = "hoge"
    let data = str.data(using: .utf8)
    
    guard let _data = data else {
        return
    }
    
    let dic: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                              kSecAttrGeneric as String: "key",
                              kSecAttrAccount as String: "account",
                              kSecValueData as String: _data]
    
    var itemAddStatus: OSStatus?
    // 保存データが存在するかの確認
    let matchingStatus = SecItemCopyMatching(dic as CFDictionary, nil)
    if matchingStatus == errSecItemNotFound {
        // 保存
        itemAddStatus = SecItemAdd(dic as CFDictionary, nil)
    } else if matchingStatus == errSecSuccess {
        // 更新
        itemAddStatus = SecItemUpdate(dic as CFDictionary, [kSecValueData as String: _data] as CFDictionary)
    } else {
        print("保存失敗")
    }
    // 保存・更新ステータス確認
    if itemAddStatus == errSecSuccess {
        print("正常終了")
    } else {
        print("保存失敗")
    }
}
```
## 取得

```swift:ViewController.swift
// 取得
func getKeyChain(key: String) -> String? {
    
    let dic: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                              kSecAttrGeneric as String: key,
                              kSecReturnData as String: kCFBooleanTrue]
    
    var data: AnyObject?
    let matchingStatus = withUnsafeMutablePointer(to: &data){
        SecItemCopyMatching(dic as CFDictionary, UnsafeMutablePointer($0))
    }
    
    if matchingStatus == errSecSuccess {
        print("取得成功")
        if let getData = data as? Data,
            let getStr = String(data: getData, encoding: .utf8) {
            return getStr
        }
        print("取得失敗: Dataが不正")
        return nil
    } else {
        print("取得失敗")
        return nil
    }
}
```
## 削除

```swift:ViewController.swift
// 削除
func deleteKeyChain() {
    // 削除するqueryを設定
    let dic: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                              kSecAttrGeneric as String: "key",
                              kSecAttrAccount as String: "account"]
    
    if SecItemDelete(dic as CFDictionary) == errSecSuccess {
        print("削除成功")
    } else {
        print("削除失敗")
    }
}
```
Laravel日記2 - CSSを適用してみる- 

Laravel日記その２を書いてみたいと思います。

前回の記事→ [Laravel日記1](https://qiita.com/kotsuban-teikin/items/26da7e204eaeb6cbd51e)

今回はCSSを適用してみたいと思います。

ちなみに前回までの状態は以下の通りです。

***トップページ***
<img width="294" alt="スクリーンショット 2018-12-13 11.40.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/250202/c6835d79-19da-910c-9de1-7bb285be8533.png">


***新規登録ページ***
<img width="344" alt="スクリーンショット 2018-12-13 11.40.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/250202/fd85635a-1bc7-6a0f-0be1-62311d0ae618.png">


## LaravelプロジェクトにCSSを追加する

今回は自作でstyle.cssというファイルを作成し、Laravelプロジェクトに適用するところをやってみたいと思います。

下記内容が記載されたstyle.cssというファイルを、public/cssフォルダ内に追加します。

``` css:style.css
@charset "utf-8";

html{
    font-size: 62.5%;
}

body{
    color: #333;
    font-size: 1.6rem;
}
```

Laravelでは単純にCSSを適用したい場合は、publicフォルダ内のcssフォルダ内にファイルを突っ込んで、読み込んでしまえばOKです。

## CSSを読み込んでみる

それでは先ほど作成したを読み込んでみたいと思います。

```html
<link rel="stylesheet" href="{{ asset('css/style.css') }}">
```
上記をindex.blade.phpおよびnew.blade.phpに追加します。
asset()というものを使うと、publicフォルダ内のリソースを読み込めるようになっています。

この辺はHTMLの相対パスの知識が使えます。

せっかくなので、HTMLのファイルっぽくしてみましょう。

```html:index.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="{{ asset('css/style.css') }}">

</head>
<body>
<header>
    <h1>Laravel Blog</h1>
</header>
    <p>Laravel Blogです。</p>
    <a href="{{url('/new')}}">新規登録</a>
<footer>
<small>copyrights &copy; 2018 kotsuban-teikin All rights Reserved.</small>
</footer>
</body>
</html>
```

```html:new.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="{{ asset('css/style.css') }}">

</head>
<body>
<header>
    <h1>Laravel Blog</h1>
</header>
    <p>Laravel Blog新規登録ページです。</p>
    <a href="{{url('/')}}">トップページへ戻る</a>
<footer>
<small>copyrights &copy; 2018 kotsuban-teikin All rights Reserved.</small>
</footer>
</body>
</html>
```
## HTTPS環境オンリーの場合は

調べてみると、HTTPS環境オンリーの場合はsecure_asset()というものを使うんだそうな。下記参考にさせていただきました。

[Laravelのアセットに関するTips](https://qiita.com/sakuraya/items/411dbc2e1e633928340e)

## まとめ
ということで今回はCSSを適用してみました。SCSSを使ったり、Bootstrapを読み込んだりする場合はまた色々あるようですが、それは別の機会にでもやりたいと思います。

ちなみにJavaScriptについても同じようなやり方で、public/jsフォルダ内にjsファイルを読み込みして、それをblade.php側で読み込みすれば適用されるようになります。

現時点では下記のような形になります。

<img width="614" alt="スクリーンショット 2018-12-13 11.59.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/250202/55a7dd4d-d279-f805-9485-ecaccddb1ed2.png">


<img width="550" alt="スクリーンショット 2018-12-13 11.59.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/250202/d76eaa0d-79a5-8338-a9b2-659af7eb6d91.png">


次回は共通部分の作成を行いたいと思います。
Raspberry Piでkubernetesクラスタを組んでみる③

## Master/Worker Nodeの準備
まずはMasterの初期化を行います

```
kubeadm init
```

なんか色々ログが出てくるけど、最後の方にこんなコマンドが出てくると思います。

```
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
```

言われた通り、このコマンドを実行してみます。
で、さらにノードを追加するためのコマンドも出てくるのでこれをコピっておいて、残り2台のworkerで実行してやります。

```
kubeadm join xxx.xxx.xxx.xxx:6443 --token xxxxxxxxxxxxxxxx
```

しばらく待って、ノードの様子を見てみます

```
$ kubectl get nodes
NAME           STATUS     ROLES     AGE       VERSION
raspberrypi0   NotReady   master    1d        v1.11.1
raspberrypi1   NotReady   <none>    1d        v1.11.1
raspberrypi2   NotReady   <none>    1d        v1.11.1
```
あ、困った！ノードは追加できてるけどNotReadyだ！！
では、まずMasterNodeの様子を見てみましょう。

```
$ kubectl describe node raspberrypi0 
  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----             ------  -----------------                 ------------------                ------                       -------
  Ready            False   Sun, 16 Sep 2018 04:47:34 +0000   Tue, 11 Sep 2018 15:01:33 +0000   KubeletNotReady              runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized. WARNING: CPU hardcapping unsupported
```
ほんとは他にも色々出てくるけど、とりあえずReady状態になっていないのはネットワークの問題のようです。

## StatusをReadyにしよう
[こちら](https://qiita.com/dtan4/items/8f9cf40aabd2e6c9a494)の記事なんかを見ているとflannelを入れてコンテナ同士（Pod同士）の通信をさせれば良いとのことでした。
そのへんはKubernetesがよしなにやってくれるのかと思っていたのですが、GCE上でしか使えないとか（まじかよ・・・）

ということでflannelを入れてみました。

```
kubectl apply -f <(curl -s https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml |sed 's/amd64/arm/g')
```

そうするとうまくいきました

```
$ kubectl get nodes
NAME           STATUS    ROLES     AGE       VERSION
raspberrypi0   Ready     master    4h        v1.11.1
raspberrypi1   Ready     <none>    4h        v1.11.1
raspberrypi2   Ready     <none>    4h        v1.11.1
```