OmniAICreator/Qiita-1.07M huggingface dataset:
LINE botをFirebaseで動かしたらつまづいた

FirebaseとかNode.jsとか全く触ったことないけど、なんとなくLINE bot触りたくなったので色々見ながら動かしてみた。

散々エラー出たので同じことにならないようにメモ。

# 環境

* Node.js v10.15.3
* npm v6.4.1
* firebase-tools v6.10.0
* Windows10(Macでも動いた)

(2019/05/24時点)

# 構築手順
手順は他の参考にした記事が下記。
同じことを書いても仕方ないので。

* [FirebaseでNode.jsを動かしてLINE BOTを作る](https://qiita.com/n0bisuke/items/909881c8866e3f2ca642)
* [1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)
* [Filebase FunctionでLineBotを作ろう（失敗）](https://qiita.com/ranran/items/5a9427636b35801bfba7)
* [FirebaseでLINE botを作ってみた](https://qiita.com/dq-ny/items/e996d7e2d5e8baa93dac)

# 行き詰まったところ
line.middlewareをapp.postより前にしないとエラー？ワーニング？が出てしまってダメだった。
シグネチャって言われてもどうしろと状態。

```
(node:3664) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be one of type string, TypedArray, or DataView. Received type object
      at Hmac.update (internal/crypto/hash.js:58:11)
      at Object.validateSignature [as default] (C:\mylinebot\functions\node_modules\@line\bot-sdk\dist\validate-signature.js:37:10)
      at getBody.then.body (C:\mylinebot\functions\node_modules\@line\bot-sdk\dist\middleware.js:37:46)
      at process._tickCallback (internal/process/next_tick.js:68:7)
```



# 最終的なindex.js

前述の参考ページを見て、line.middleware(config)を前に持っていった。

```index.js
'use strict';

const functions = require('firebase-functions');
const express = require('express');
const line = require('@line/bot-sdk');

const config = { 
    channelSecret: '', // LINE DeveloperからChannel Secretをコピペ
    channelAccessToken: '' // LINE Developerからアクセストークンをコピペ
};

const app = express();

let middle = line.middleware(config); //★ここ
app.post('/webhook', (req, res) => {

  console.log(req.body.events);
  Promise
    .all(req.body.events.map(handleEvent))
    .then((result) => res.json(result))
    .catch((result) => console.log('error!!!'));
});

const client = new line.Client(config);

async function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: event.message.text
  });
}

exports.app = functions.https.onRequest(app);
```

# リンクやメモ

* [Firebase](https://firebase.google.com/?hl=ja)
* [LINE Devlopers](https://developers.line.biz/ja/)
* [LINE Developer Documents - middleware()](https://line.github.io/line-bot-sdk-nodejs/api-reference/middleware.html#usage)

## ngrokでトンネル

``` 
$ npm i -g ngrok
$ npm http 5000
```

## firebase

```
$ firebase serve --only functions,hosting // ngrokで試験
$ firebase deploy --only functions,hosting // デプロイ
```
WAF を使って hot-linking 対応


streampack の Tana です。

## 概要

動画や画像などを配信しているリンクなどがあると思いますが、外部サービスにリンクを貼られるなど、使われたくないケースがあるかと思います。サーバサイドでは nginx などで制御できますが、急激なスパイクやトラフィックなどを意識したくないので、CDN(CloudFront) できればなぁっと思ってたら、AWS WAF で制御することができることをつい最近知りました(汗)

AWF WAF
https://console.aws.amazon.com/waf/home

細かな IP制限、パラメータ制限、地域制限なども可能ですし、
対象リソースを **CloudFront** だけでなく、**ALB** や **API Gateway** も連携対象にすることができます。

**今回は直リンク(Hot-linking防止)ではアクセスできないようにし、s3のドメインからのみ許可してみます。**

## 設定方法

Web ACLs から作成するとわかりにくいので、String and regex matching から作成します。

### String and regex matching: 条件設定

どういう条件を対象にするかを設定します。
URLやパラメータ、Header など細かな条件を指定できます。
**domain-check** という名前で作成し、今回はHeaderのリファラーをチェックします。

<img width="1225" alt="String and regex matching.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/9baa1c52-e952-818d-dd6f-4cfd769577af.png">

### Rule

ルールを作成します。複数の条件を紐づけることができます。
**domain-rule** という名前で新規に作成、先ほど作成した条件の **domain-check** というのを紐付けます。

<img width="1249" alt="rule.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/8bc1c4f7-a982-8c42-cf4e-e63eae93646d.png">


### Web ACLs 設定
**domain-rule** を紐付けし、今回事前に作成しておいた、CloudFrontを指定します。

<img width="1342" alt="web-acls.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/0276d04c-4969-1cd0-1264-ca4be9b713eb.png">


### Edit ACLs

Edit ACLs にて、条件を指定します。
**条件にマッチしたもののみ許可!** という設定にしてます。
つまり、s3 経由でないとアクセスさせません。

<img width="1367" alt="edit-web-acl.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/6e8f7d46-8847-7061-4e90-05d6049ed572.png">


### 直リンクでアクセスしてみる

<img width="950" alt="404-error.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/63c61001-5e87-4ef6-904b-ade346916c51.png">

期待通りに、アクセスできません。


### s3 経由で html にアクセス

下記の html を作成し、CloudFront の動画を参照してみます。

``` test.html
<video width="640" height="360" controls>
  <source src="http://xxxxx.cloudfront.net/tmp/test.mp4" type="video/mp4">
</video>
```

動画にアクセスすることができました。

<img width="658" alt="s3-test_html.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/2531f7ea-297e-e982-3fd3-56f50ceb463d.png">

## 結論

WAFを使えば、UI上で簡単に登録し、制限をかけることができました。
もっと細かにルール・条件を作成すれば、より強固なものが提供できそうです。
リクエスト数によって課金されるようなので、必要なリソースのみ制限をかけるのが良さそうです。
Pythonにおけるクラスとインスタンスの関係

[Progate](https://prog-8.com/)でPythonの基礎的なコードの学習を修了したので、個人的にややこしいと感じた部分を復習を兼ねてまとめます。


#クラスからインスタンスを生成

```python:menu.py
class MenuItem:
   pass

menu_item1 = MenuItem()
menu_item.name = 'メロンパン'
menu_item.price = 150
```

「クラス名()」でインスタンスが生成されます。
また、「インスタンス名.インスタンス変数」で情報を追加することができます。
ここでは「name」がメロンパンであるという情報と、「price」が150であるという情報を追加しました。

#インスタンスメソッド
```python:menu.py
class MenuItem:
   def info(self):
      print('こちらがメニューです。')
      print(self.name + ':' + str(self.price) + '円')

menu_item1 = MenuItem()
menu_item1.name = 'メロンパン'
menu_item1.price = 150
menu_item1.info()
```
クラス内で定義したメソッドは、「インスタンス名.メソッド名」でインスタンスに対して呼び出せます。
(インスタンス自体を代入させるため引数selfは必須)

実行結果は以下のようになります。

---
*こちらがメニューです。
メロンパン：150円*

---

#__init__メソッド
```python:menu.py
class MenuItem:
   def __init__(self):
      print("こちらがメニューです。")

menu_item1 = MenuItem()
```
このメソッドは、インスタンスを生成すると自動で呼び出されるようになっています。
そのためここでは、インスタンスを生成しただけで「こちらがメニューです」が表示されます。

#まとめ
クラスからインスタンスを生成、インスタンス、initに関してまとめてみました。
ここがPythonで最初につまずいたポイントだった人も多いのではないでしょうか。
私もまだまだアウトプットを完璧にするには練習が必要なので、修行を積んでいきます。
serverless-framework + serverless-offline で binaryデータを送受信する

# アップロード(multipart)

- lambda-multipart-parser

追加

```
yarn add lambda-multipart-parser
```

## functionへ追加
```handler.ts
export const hoge: APIGatewayProxyHandler = async (event, _context) => {
	const MultipartParser = require("lambda-multipart-parser");
	const parsed = await MultipartParser.parse(event);
	const file0 = parsed.files[0];
	const content: Buffer = file0.content;
	...
);
```

# ダウンロード
## 設定

- serverless-apigw-binary
- serverless-apigwy-binary
- 
をインストールし、設定する

```
yarn add serverless-apigw-binary
yarn add serverless-apigwy-binary
```

```serverless.yml
plugins:
  - serverless-apigw-binary
  - serverless-apigwy-binary
  
custom:
  apigwBinary:
    types:
      - "image/jpeg"
      - "image/png"
      
functions:
  hoge:
    handler: handler.hoge
    events:
      - http:
          method: get
          path: hoge
          contentHandling: CONVERT_TO_BINARY
```

## functionへ追加
  
``` handler.ts

export const hoge: APIGatewayProxyHandler = async (event, _context) => {
	const img64: string; //image as base64
	return { statusCode: 200, headers: { "Content-Type": "image/png" }, isBase64Encoded: true, body: img64 };
};
```
Go言語 配列の宣言の時に30秒間つまずいたこと

# はじめに
記述するGo言語の配列については一部のみです。

# 配列の宣言方法
角括弧内`[]`に長さを宣言し、その後ろに型を宣言します。
配列の要素にアクセスするには、配列の変数の後ろに角括弧`[]`を付けその中に添字を記述します。
※ 添字は`[0]`から始まります。

```.go
package main

import (
	"fmt"
)

func main() {
    var number [3]string
    number[0] = "zero"
    number[1] = "one"
    number[2] = "two"

    fmt.Println(number)        // => [zero one two]
    fmt.Println(len(number))   // => 3
}
```

# 配列の宣言時に値を代入
変数に`:=`で代入できます。上記の宣言の後ろに`{}`を付け、その中に代入したい値を`,`で区切り記述します。

```.go
package main

import (
	"fmt"
)

func main() {
    number := [3]string{"zero", "one", "two"}

    fmt.Println(number)        // => [zero one two]
    fmt.Println(len(number))   // => 3
}
```

## ここでつまずいた
`{}`の中の要素を見やすく複数行に分けて記述したいことがあると思います。しかし以下の場合はコンパイルエラーが発生します。


```.go
func main() {
    number := [3]string{
        "zero",
        "one",
        "two"
    }

    fmt.Println(number)
    fmt.Println(len(number))
}
// syntax error: unexpected newline, expecting comma or }
```

原因は`{}`の要素の最後にも`,`を付けないといけないからです。

```.go
package main

import (
	"fmt"
)

func main() {
    number := [3]string{
        "zero",
        "one",
        "two",    // <= , が必要
    }

    fmt.Println(number)
    fmt.Println(len(number))
}
```

## `;`の自動挿入
Go言語は多言語によくある文末の`;`を省略できます。コンパイル時にGoコンパイラによって`;`を挿入されます。上記のコンパイルエラーはこの自動挿入によって発生しているようです。

```.go
package main;

import (
	"fmt"
);

func main() {
    number := [3]string{
        "zero",
        "one",
        "two";    // <= ここに ; が挿入される
    };

    fmt.Println(number);
    fmt.Println(len(number));
};
```
参考： (https://github.com/tsurubee/golang-study/issues/1)

# 最後に
参考サイトはスターティングGo言語についてのでした。
買ってみようかなぁ～。
[スターティングGo言語] (https://www.amazon.co.jp/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0Go%E8%A8%80%E8%AA%9E-CodeZine-BOOKS-%E6%9D%BE%E5%B0%BE-%E6%84%9B%E8%B3%80/dp/4798142417/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=Go%E8%A8%80%E8%AA%9E&qid=1558664315&s=gateway&sr=8-1)
Capistranoデプロイしようとしたら突然ed25519エラーが出たときの解消法

## 状況
長らく触っていなかったRails5のプロジェクトをデプロイしようとしたら、下記のエラーでデプロイできなかった。

```shell_session
OpenSSH keys only supported if ED25519 is available (NotImplementedError)
net-ssh requires the following gems for ed25519 support:
 * ed25519 (>= 1.2, < 2.0)
 * bcrypt_pbkdf (>= 1.0, < 2.0)
See https://github.com/net-ssh/net-ssh/issues/565 for more information
Gem::LoadError : "ed25519 is not part of the bundle. Add it to your Gemfile."
(Backtrace restricted to imported tasks)
cap aborted!
NotImplementedError: OpenSSH keys only supported if ED25519 is available
net-ssh requires the following gems for ed25519 support:
 * ed25519 (>= 1.2, < 2.0)
 * bcrypt_pbkdf (>= 1.0, < 2.0)
See https://github.com/net-ssh/net-ssh/issues/565 for more information
Gem::LoadError : "ed25519 is not part of the bundle. Add it to your Gemfile."

Tasks: TOP => rbenv:validate
(See full trace by running task with --trace)
```

## 解決方法
development用にこちらを追加し `bundle install` したら解決しました。

```diff
diff --git a/Gemfile b/Gemfile
index 0898d25..067fd75 100644
--- a/Gemfile
+++ b/Gemfile
@@ -68,6 +68,9 @@ group :development do
 group :development do
   gem 'capistrano-rails'
   gem 'capistrano-rbenv'
   gem 'capistrano-bundler'
   gem 'capistrano-yarn'
   gem 'capistrano-passenger', '>= 0.1.1'

+  gem 'ed25519'
+  gem 'bcrypt_pbkdf'
+
```
[Vue.js] input type="file"で画像のuploaderを作る

## やりたいこと

画像をアップロードしたら、それが表示されるものを作りたい。（以下のようなもの）

<img width="600" alt="スクリーンショット 2019-05-24 11.01.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224077/68f7ec77-92fc-2393-fac3-6d0749c42aea.png">


## component


```html

<template>
  <div>
    <img v-show="uploadedImage" :src="uploadedImage" />
    <div class="c-btn--file">
      ファイルを選択
      <input type="file" @change="onFileChange" />
    </div>
  </div>
</template>

<script>
export default {
  name: 'BaseFileUpload',
  data() {
    return {
      uploadedImage: '',
    }
  },
  methods: {
    onFileChange(e) {
      let files = e.target.files || e.dataTransfer.files
      this.createImage(files[0])
    },
    // アップロードした画像を表示
    createImage(file) {
      let reader = new FileReader()
      reader.onload = e => {
        this.uploadedImage = e.target.result
      }
      reader.readAsDataURL(file)
    },
  },
}
</script>


```
PHP: 配列が添字配列か連想配列かを判定する

PHPで、配列が添字配列か連想配列を判定する関数です。


```php
// 判定する関数
function is_sequential(array $array): bool
{
	$keys = array_keys($array);
	return $keys === array_keys($keys);
}

// 以下テストコード

// 添字配列
assert(is_sequential([]));
assert(is_sequential([1, 2, 3]));
assert(is_sequential(['a', 'b', 'c']));
assert(is_sequential([0 => 'x', 1 => 'x', 2 => 'x']));
assert(is_sequential(['0' => 'x', '1' => 'x', '2' => 'x'])); // 後述1

// 連想配列
assert(!is_sequential([1 => 'x', 2 => 'x', 3 => 'x'])); // 1始まりなので連想配列
assert(!is_sequential([0 => 'x', 2 => 'x', 4 => 'x'])); // 0始まりだけど、0,1,2と連続しているわけでないので連想配列
assert(!is_sequential(['a' => 'x', 'b' => 'x', 'c' => 'x'])); // キーが0,1,2と連続しているわけでないので連想配列
```

## 後述1

PHPの仕様上、キーが文字列でも、添字配列になる場合がある。

```php
var_dump(['0' => 'x', '1' => 'x', '2' => 'x']);
```

```
array(3) {
  [0]=>
  string(1) "x"
  [1]=>
  string(1) "x"
  [2]=>
  string(1) "x"
}
```
【Homebrew】brew cleanupがこける【Warning: Skipping XXX】


# 事の発端

先日、Homebrewでとあるパッケージを新規インストールした際、「30日以上`brew cleanup`してないやんけ！」と怒られました。
「確かに2ヶ月くらいサボってるなぁ」と思い、`brew cleanup` コマンドを実行したんですよ。
そしたらなぜかできないんですよね。

```bash
$ brew cleanup

Warning: Skipping XXX: most recent version X.X.X not installed
<中略(２０件くらい)>
Warning: Skipping XXX: most recent version X.X.X not installed
```

内容としては**「XXXの最新バージョンがインスコされてません！！」**って感じらしいです。

# 下調べ

色々情報を漁っていると、

1. Homebrewのパッケージインストール先である`Celler` 配下にある下位バージョンのパッケージを丸っと削除
2. 対象のパッケージのリンクを解除してインストールし直す

という手法がありました。

しかし僕は以下の手順で解決しました。
(状況によっては解決しない場合もあります)

# とりあえず解決策

「最新バージョン入れればいいのよね。」って事で以下を実行。

```bash
## パッケージ更新
$ brew update
$ brew upgrade
```

```
## 更新完了後
$ brew cleanup
Pruned 0 symbolic links and 21 directories from /usr/local
```

パッケージ更新後、`brew cleanup`は問題なく実行できましたが、想定してたログと違うんですよね。
削減された容量が表示されるはずなのに。。。

# 詳しく

どうやら30日以上`brew cleanup`していないと、`brew upgrade`時に勝手に`brew cleanup`されるようです。
なのでおそらく`brew upgrade`の実行前後で容量に差があるはずなのですが、確認できず。。。w

他の方が遭遇された事象についても、意図的に古いバージョンを利用したい方以外は、おそらくこの手順で解決できると思ってます。
※できなかった場合はコメ欄にて情報提供お願いしますm(_ _)m

# まとめ

みんな定期的に`brew upgrade(update)`と`brew cleanup`しましょう。


## 参考リンク

- https://www.labohyt.net/blog/apple/post-3452/
- https://zunermuka.blogspot.com/2016/02/memo-brew-cleanup-warning-skipping.html
CakePHP3にてセッションタイムアウトの時間を変更する方法

# はじめに
CakePHP3にてセッションタイムアウト時間の変更方法についてまとめました

# 環境
CakePHP 3.5.17

# TL;TD
- config/app.phpのSessionにtimeoutを設定します
- 設定しないと、php.iniの「gc_maxlifetime」の値となります

# 設定方法
- Sessionにtimeoutの設定を追加する、単位は「分」
- 以下は10分でタイムアウトするように設定しています

```config/app.php

    'Session' => [
        'defaults' => 'php',
        'timeout' => 10
    ],
```

# セッションの設定を追いかけてみた
- timeoutを設定すると、gc_maxlifetimeを更新しているため、設定しないと、gc_maxlifetimeの設定値が有効になります

```vendor/cakephp/cakephp/src/Network/Session.php
    public function __construct(array $config = [])
    {
        if (isset($config['timeout'])) {
            $config['ini']['session.gc_maxlifetime'] = 60 * $config['timeout'];
        }
    }
```

- ちなみに、gc_maxlifetimeのデフォルトは以下となっています
  - session.gc_maxlifetime = 1440
  - 単位は秒なので、24分となります


# まとめ
- CakePHP3でセッションタイムアウトを変更したい方は参考にしてみてください

# 参考
[PHP:実行時設定](https://www.php.net/manual/ja/session.configuration.php)
[Cookbook セッション](https://book.cakephp.org/3.0/ja/development/sessions.html)
ドット記法で値にアクセスできない…

RailsのActive Recordにおいて、例えば、Userモデルのインスタンスはドット記法を用いてその属性値にアクセスできることはご存知かと思います。

```
例)
>> user = User.new(name: "hoge", email: "hoge@example.com")
>> user.name
=> "hoge"
```

ですが、ドット記法を用いて属性値にアクセスできないことがあったので、シェアしたいと思います。

#バージョン
Rails：5.1.4
ruby：ruby 2.6.0p0

#状況

例えば、勤怠を管理するモデルでAttendanceモデルがあるとする。

|id| time_in | time_out | time_in_change | time_out_change |
|:--:|:-------:|:--------:|:--------------:|:---------------:|
|1|  09:00  |  18:00   |     10:00      |      19:00      |
|︙|   ︙    |  ︙   |     ︙     |     ︙    |

この時、

```
例)
>> attendance = Attendance.find(1)
>> attendance.time_in
=> "09:00"
```

となり、ドット記法でアクセスできるが、time_in_change及びtime_out_changeカラムの場合は、

```
例)
>> attendance = Attendance.find(1)
>> attendance.time_in_change
=> nil
```
でドット記法で属性値にアクセスできない現象が発生しました。

似たような現象が起こっている記事を発見し、→　[参考記事](https://ja.stackoverflow.com/questions/5725/activerecord%E3%81%A7%E4%BF%9D%E5%AD%98%E3%81%97%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AEid%E3%81%AE%E5%8F%96%E5%BE%97%E3%81%AE%E6%96%B9%E6%B3%95%E3%82%92%E6%95%99%E3%81%88%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84)

試しに、

```
例)
>> attendance = Attendance.find(1)
>> attendance.attributes['time_in_change']
=> "10:00"
```
でドット記法で値にアクセスできるが、なぜなのか原因が分からず…

さらに、試みて

time_in_change　→　change_time_in
time_out_change　→　change_time_out
とカラム名を変更すると、

```
例)
>> attendance = Attendance.find(1)
>> attendance.change_time_in
=> "10:00"
```
となり、attributesを使用しなくても値にアクセスできるようになりました。
カラム名の命名に問題があるのでしょうか？

#最後に

 ~~今回の現象について、原因が何であるか分からないため、この記事を読んでくださった方で
何か原因が思い当たるようでしたら、アドバイス頂けると幸いです。
よろしくお願いします。~~

@sakuro さん
@scivola さん
よりご指摘頂きました。

どうやら、
今回の場合、time_inカラムが存在していて、
.time_in_changeとすると、.time_in_changeカラムの属性値に
アクセスするのではなく、ActiveModel::Dirtyモジュールに定義されている
time_in_changeメソッドが呼び出されるみたいです。
※カラム名_changeで呼び出される。

今回の属性値にアクセスできるか否かの件とは関係ありませんが、
ActiveModel::Dirtyは、変更前の値を追跡できたりするので、
かなり便利ですね！

[参考記事](https://api.rubyonrails.org/classes/ActiveModel/Dirty.html)

@sakuro さん
@scivola さん
ご指摘ありがとうございました！
WordPressでYouTubeのoEmbed埋め込みをカスタマイズ

# 内容

WordPressで外部コンテンツ埋め込みに使われるoEmbedはパラメーターを自由に設定できません。
ここではYouTube動画をiOSでインライン再生されるようにする`playsinline`パラメーターを追加してみます。
`array_merge()`の第二引数を調整することで関連動画の設定なども簡単にできます。

# コード

```PHP:functions.php
function embed_oembed_html_custom($cache, $url) {
  if (strpos($url, 'youtube.com') !== false || strpos($url, 'youtu.be') !== false) {
    return preg_replace_callback(
      '/<iframe.*?src\s*=\s*["|\'](.*?)["|\'].*?>/i',
      function($matches) {
        $url_query = parse_url($matches[1], PHP_URL_QUERY);
        if (empty($url_query)) {
          $query = array();
        } else {
          parse_str($url_query, $query);
        }
        $new_query = array_merge($query, array('playsinline' => '1'));
        $new_src = add_query_arg($new_query, $matches[1]);
        return str_replace($matches[1], $new_src, $matches[0]);
      },
      $cache
    );
  }
  return $cache;
}
add_filter('embed_oembed_html', 'embed_oembed_html_custom', 10, 2);
```
プロジェクト毎に複数サーバある場合のssh configの管理方法

## 対象

- 複数プロジェクトあったりしてssh configが膨大になってる人
- `Include`キーワードが使える2016-08-01リリースのOpenSSH 7.3以上を利用している人
- ssh設定の一つ一つの項目自体は理解している人（本記事で説明を省きます）

## ディレクトリ構造

まずはディレクトリ構造を記載します。
プロジェクトによっては踏み台サーバを経由する場合があったり、鍵環境毎で分かれてなかったりするので適宜置き換えてください。
本内容はあくまで一例ということで。

```sh:tree
~/.ssh
├  conf.d                   --- プロジェクト毎のディレクトリを入れるためのディレクトリ
│   ├ project1              --- プロジェクト1つ目のディレクトリ。プロジェクト名を仮にproject1とする 
│   │   ├ config            --- project1で使用するssh設定をここに記載する（内容を後述）
│   │   ├ project1-prod.pem --- project1の本番サーバで使う秘密鍵
│   │   └ project1-dev.pem  --- project1のの開発サーバ使う秘密鍵
│   └ project_2             --- プロジェクト２つ目のディレクトリ。プロジェクト名を仮にproject2とする
│       └ config            --- project2で使用するssh設定をここに記載する(project1のconfigと同じなので説明省略)
├  config                   --- 全体に適用するssh設定をここに記載する（内容を後述）
├  id_rsa                   --- config内でキーを指定してない場合にデフォルトで使われる秘密鍵
└  id_rsa.pub               --- 上記id_rsaの公開鍵
```

## 説明
ファイル内容を具体例を書きながら説明します。


```config:~/.ssh/config
# 以下のIncludeで各プロジェクトのconfigが全てIncludeされる
Include ~/.ssh/conf.d/*/config

# *を指定してすべてのssh設定で適用したい項目を入れる
Host *
  UseKeychain yes
  StrictHostKeyChecking no
  AddKeysToAgent yes
  ForwardAgent yes
  ServerAliveInterval 60
  ServerAliveCountMax 60
  TCPKeepAlive yes
  IdentitiesOnly yes

```
大元の全体に適用されるssh設定と各プロジェクトのconfigのincludeを行います。


```config:~/.ssh/project1/config
# project1に関わるサーバの情報はここにすべて記載する。
# 以下のような命名規則にする。
# Host <環境名>_<プロジェクト名>_<サーバ固有名>

Host dev_project1_api
    HostName api.dev.project1.com

Host dev_project1_admin
    HostName admin.dev.project1.com

Host prod_project1_admin
    HostName admin.project1.com

Host prod_project1_api1
    HostName api1.project1.com

Host prod_project1_api2
    HostName api2.project1.com

Host prod_project1_api3
    HostName api2.project1.com

# project1の開発環境で共通して使う設定項目を記載
Host dev_project1_*
    IdentityFile ~/.ssh/conf.d/project_1/project1-dev.pem

# project1の本番環境で共通して使う設定項目を記載
Host prod_project1_*
    IdentityFile ~/.ssh/conf.d/project_1/project1-prod.pem

# project1で共通して使う設定項目を記載
Host *_project1_*
    User amasok
    Port 2222
```

上記は管理サーバとAPIサーバがあり、開発環境と本番環境で鍵が分かれているパターンで記載しています。
もし鍵が本番と開発で同じであった場合は`*_project1_*`に`IdentityFile`を記載します。
プロジェクト毎の規則によって変わるかと思いますが、だいたいこんな感じで僕は対応しています。
Windows 10上のVirtualBoxのNATが正常に動作しなくなった（不具合が発生した）際の解決方法

Windows 10の一部の端末でVirtualBoxのネットワークが正常に動作しなくなる現象が発生したため、その解決方法をメモとして記載します。

## 現象
Windows 10環境上のVirtualBox上で動作するゲスト（VM）のネットワークアダプターがNATの場合に、インターネットやイントラネットに繋がらない状態となる。具体的には、NAT外に対して、TCP/UDP接続が一切行えなくなる。ただし、pingは疎通可能。
これにより、ゲストから、Webブラウザ、cURLなどのHTTP/HTTPSクライアントソフトウェアからのアクセスや、yum、apt-getなどのパッケージマネージャの利用が行えなくなる。
OSの再起動や、VirtualBoxの再インストールを行っても現象が解消されない。

### 詳細

- NATで接続できない
    - NAT外へのpingは通る
    - TCPやUDPが疎通不能
        - DNSで名前解決できない
            - DHCPで設定されたDNS、Google Public DNS(8.8.8.8)、いずれも名前解決できない
        - NAT外のHTTP/HTTPSサーバへ接続できない
            - 接続先（LAN内, WAN）に関係なく事象が発生する
                - インターネット上のリソースへアクセスできない
                    - Yahoo!JapanやGoogleなどへアクセスできない
                    - yumやapt-getなどのパッケージマネージャーが利用できない
                - LAN内のリソースへアクセスできない
                    - ルーターや無線LAN APの管理UI、自宅サーバなどへアクセスできない
            - Webブラウザ、cURLなど、クライアント環境に関わらず発生する
        - NAT外のSSHサーバへ接続できない
    - ホストオンリーアダプターは問題なく利用可能
        - ホスト－ゲスト、ゲスト－ゲストともにpingも通るし、TCPやUDPも通る
            - ホストオンリーアダプターのセグメント内であれば、そのセグメント内に存在するHTTP/HTTPSサーバも、SSHサーバも問題なく接続できる
    - ブリッジ接続は問題なく利用可能
        - pingもTCPもUDPも通る
            - HTTP/HTTPSサーバも問題なく接続できる
            - SSHも問題なく接続できる
            - yumやapt-getも問題なく行える
        - LAN内（ホストと同一セグメント）にDHCPサーバが存在する場合は、DHCPサーバからゲストに対するIPアドレス払い出しも問題なく行われる
- Windows 10でのみ当該問題が発生
    - macOSやLinuxでは同様の現象は発生せず
    - ただし、Windows 10でも発生する端末とそうでない端末が存在する
- OSを再起動したり、端末の電源を入れなおしても現象が解消されない
- VirtualBoxを再インストール（上書き、アンインストール→インストール）しても現象が解消されない

## 対応

Windows 10のコマンドプロンプトを管理者権限で開き、以下のコマンドを実行することで現象が解消されました。

```
netsh winsock reset
```

※参考URLでは一時的に解消される旨記載されていましたが、現在のところ再起動後も現象が再発することなく利用できています。

## 参考
- VirtualBox NAT Issue - Able to Ping and Lookup. Unable to Browse
    - https://unix.stackexchange.com/questions/298647/virtualbox-nat-issue-able-to-ping-and-lookup-unable-to-browse
Windows10 Pycharmの日本語化

# Pycharm日本語化

備忘録として

- 環境
  OS : Windows 10 64bit

- インストール
  1. https://www.jetbrains.com/pycharm/ へアクセス
  2. DOWNLOAD NOW
  3. Community(コミュニュティ:無償) Downloadを選択
  4. インストーラのダウンロード(pycharm-community-2018.2.5.exe)
  5. インストーラーの実行

- 日本語化
  1. http://mergedoc.osdn.jp/　へアクセス
  2. Pleiadesプラグイン・ダウンロード(Windows)を選択
  3. pleiades-win.zipのダウンロード及び解凍
  4. pleiades-winフォルダ内のsetup.exeの実行
  5. 日本語化するファイルを選択（pychram.exe）
     ex: C:\Program Files\JetBrains\PyCharm Community Edition 2018.2.5\bin\pycharm64.exe
  6. PyCharmを再実行する
  7. 日本語化されていることを確認する


- ライブラリのインストール
  1. ファイル→設定→プロジェクト→プロジェクト・インタープリタ→+ボタン→インストールしたいパッケージの検索→パッケージのインストール
統計学とディープラーニングにおける基礎理論の学習記録

### 自己紹介と概要
普段は会社のR&D部門で業務委託として、データエンジニアをやっています。与信系のモデルを組んだり、RDS→BigQueryのデータパイプラインを整えたりしてます。

これから、同部署で引き続きデータパイプラインとウェアハウスの整備をしながら、データ分析も行っていくということで統計学とディープラーニングの基礎理論を学び直そうかなと。

学習記録としてアウトプットを残すことで、学習の質向上を主な目的として使っていきます。間違い等は当然あるので、ご指摘ください。

#### 数学レベル
学部時代に、数学や物理の演習が多かったので、数学の前提知識に関しては機械学習レベルであれば割と抑えています。もちろん、忘れている部分も多々あるかと思いますが、すぐに思い出せるレベルかなと考えています。

### 使う教材
- 統計学入門
- はじめてのパターン認識

という王道の２つの基礎的な教科書をしっかり勉強していきます。
教材選びでは、以下の記事を参考にさせていただきました。
https://qiita.com/shu_marubo/items/1066ea6e853d46a77696

### 記事一覧(随時更新)
自分のメモ用も兼ねて、学習記録の記事をここに随時更新していきます。
検索結果のトップから公式のページを取り戻す

# 問題
グーグルで検索していると、公式ページより、個人が適当にまとめたページが上に来てしまう場合が稀によくあります。
たとえば「VisualStudio Test」を調べてみると、本来であればMicrosoftのページがトップに来てほしいですが、実際は以下のように個人のまとめた記事がトップに来てしまいます。

![qiita1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/5c1c6206-cf63-6943-a618-71730ea096dc.png)

~~さすがにQiitaがMicrosoftのページより上に来ちゃあかんだろ。~~

サイトごとブロックはしたくないが、なるべく公式ページが上に来るように考えてみました。

## 対策
アメリカの検索エンジンを使う。


###Chromeの設定方法
(1)設定画面」から「検索エンジンの管理」をクリック
![qiita2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/dbeaf177-e7c8-c365-b5d6-0b32e4ee88f1.png)

(2)追加ボタンをクリック
![qiita3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/26aedc05-affa-42f9-3233-5323881ff266.png)


(3)検索エンジンの追加にて必要項目を入力して追加を押下
![qiita4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/7a194fca-23c3-7ddf-ff25-2f19331ab67d.png)

検索エンジン：任意の文字
キーワード：任意の文字
URL:{google:baseURL}search?gl=us&hl=en&gws_rd=cr&pws=0&q=%s

(4)追加した検索エンジンをデフォルトに設定する。
![qiita5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/3e303f1d-f04e-a5ae-a71f-46c2fc2477d6.png)

##やったぜ
![qiita7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/fd61f3fe-bd07-3e1b-9732-ae3c98188f07.png)

なお、キーワードに日本語を混ぜるとダメみたいです。
「Visual Studio テスト」の例

![qiita8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/a7983b6f-98d6-9acc-ad94-337d0fc3d1a4.png)

今回は英語を優先したかったので「gl=us&hl=en」となりましたが、「gl=ru&hl=ru」に変更してロシア優先とかもできます。
![qiita9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47856/ef8587b5-5d03-e496-b493-349a61266ea4.png)


##　参考
日本からアメリカのGoogle (google.com) で英語で検索する方法
https://www.suzukikenichi.com/blog/how-to-search-on-google-com-in-english-from-japan/
php-master-changes 2019-05-23

今日は run-tests.php で memcheck 以外の valgrind の tool 指定ができるようにする修正、opcache のバグ /race 修正と最適化処理の修正、リンクの済んでないクラスを利用しようとして SEGV が出るケースがあった問題の修正、socket_select() が参照を含むリソースの配列を渡した際に正常動作しない問題の修正、テストの並列実行対応の改善、php-fpm からの利用の際ランダムに SEGV が出る問題の修正があった！

# 2019-05-23
## krakjoe: add support for valgrind tools to run-tests.php
- https://github.com/php/php-src/commit/536532c57255b8c616d25251031427c5aa8d7d42
- [7.4~]
- run-tests.php で、memcheck 以外の valgrind の tool 指定ができるよう修正

## dstogov: Fixed dump of constant flags
- https://github.com/php/php-src/commit/aa9c76d027d65467b4cd8db16fea8053d926e846
- [7.3~]
- ext/opcache で、デバッグ用の zend_dump_unused_op() のコードで定数のフラグの扱いを修正

## dstogov: Fixed race condition in opcache restart
- https://github.com/php/php-src/commit/fa6a4483e63d87608a839d04c6e1b9eed9a0430f
- [7.2~]
- ext/opcache で、リスタート時の race を修正

## nikic: Don't require NO_ESCAPE for partial arrays in SCCP
- https://github.com/php/php-src/commit/dcccdc471d7c6794ff9b13d3dc9c248bf7c16da9
- [7.4~]
- ext/opcache で、SCCP 最適化での部分配列の扱いを修正
- 最近のバグ修正で NO_ESCAPE の制限なしでも最適化できる範囲が広がった、という奴かな

## dstogov: Fixed double mutex unlock
- https://github.com/php/php-src/commit/fdb7fc6153cfa8788d11e3dc74bc4f899bcdd42a
- [7.4~]
- ext/opcache で、accel_finish_startup() 時に二重に mutex を解放する箇所があったのを修正

## nikic: Forbid use of not fully linked classes
- https://github.com/php/php-src/commit/64918c770282c0f60b407e8de3201a6b68c88e78
- [7.4~]
- リンクの済んでないクラスを利用しようとして SEGV が出るケースがあった問題の修正

## krakjoe: run-tests improvements:
- https://github.com/php/php-src/commit/e1151c9549cf5a7235c1609019f79bbb1bbcdbea
- [7.4~]
- run-tests.php の改善
- memcheck 以外の valgrind ツールを使うため XLEAK セクションを追加
- XLEAK はリークのテスト用に使う

## nikic: Fixed bug [#78038](https://bugs.php.net/bug.php?id=78038) socket_select with references
- https://github.com/php/php-src/commit/9a74b23297167ca7956fd21428c8b987e7d99aa5
- [7.2~]
- ext/sockets で、[socket_select()](https://www.php.net/manual/ja/function.socket-select.php) が参照を含むリソースの配列を渡した際に正常動作しない問題の修正

## cmb69: Prevent potential test conflict
- https://github.com/php/php-src/commit/ced8760ca8533339ba8336b9ee32cbea3c873683
- [7.4~]
- テストの一時ファイルのファイル名衝突を回避して並列実行対策

## krakjoe: fix notice in run-tests
- https://github.com/php/php-src/commit/979e7d0feeb3995fde84bdc4e60ba856d6056954
- [7.4~]
- run-tests.php で、配列の要素チェックが足りなかったのを追加

## cmb69: Prevent further potential test conflicts
- https://github.com/php/php-src/commit/c70975e0a545b0df6bf5746067ff7c4c5cd6bbf7
- [7.4~]
- windows_links のテスト用の並列実行対策でとりあえず CONFLICTS を用意

## nikic: Fix bug [#77955](https://bugs.php.net/bug.php?id=77955)
- https://github.com/php/php-src/commit/6f9dfd947302f9a0d2fa6a78bf385b1ca7dafdf3
- [7.3~]
- ext/mysqlnd で、php-fpm からの利用の際ランダムに SEGV が出る問題の修正
urllib3を用いたリクエストの手法の自分用メモ

# urllib3を用いたリクエストの方法

```Python3

import urllib3
from bs4 import BeautifulSoup

url = '適当なURL'
req = urllib3.PoolManager()
get_result = req.request('GET',url)

soup = BeautifulSoup(get_result.data, 'html.parser')


```

これでsoupにrequestの結果が取得できたので,BeautifulSoupなどで整形したりする.
便利なNetBeansショートカットキーまとめ

NetBeansの便利なショートカットキーです。
本当によく忘れるので自分用メモも兼ねています。

##バージョン
NetBeans IDE 8.2 RC

##ショートカットキー

|コマンド|説明|
|:-:|:-:|
|Alt + Shift + F|フォーマット成形|
|Ctrlキー + Shift + F|プロジェクト内検索|
|Ctrlキー + Shift + F|ソース内検索|
|Ctrlキー + スペース|コード補完|
|Ctrlキー + Shift + スペース|ドキュメント表示|
|Ctrlキー + /|コメントアウト追加/削除<BR> Ctrlキー + Shift + Cでも可。|
|Ctrlキー + Shift + ↑または↓|上に複製/下に複製 <BR>現在選択した行をコピー<BR>範囲選択も可能|
|Alt + Shift + ↑または↓|行を入れ替え<BR>範囲選択も可能|
データマートについて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257568/05859438-7f02-691c-93a5-9ac1dc0114e1.png)

こちらを読んで

データマートについて

## データマートとは
組織の単一の機能領域に焦点を当て、データウェアハウスに格納されたデータの一部分が含まれたデータベース

- 組織において、**特定のチームや部署 (財務、マーケティング、営業など) のニーズに対応した**データウェアハウス
- 縮小版データウェアハウス

### データマートの特徴
データマートのデータの定義は、**単一の主題エキスパートによって**される

### メリット
- 組織内の**特定のグループにとって**有益
- データウェアハウスと比較して**データ量が削減されていて**レスポンスが速い
- データウェアハウスと比較して構成がシンプル
- データウェアハウスと比較して構築コストが低い
- データウェアハウスと比較して変更が容易

### デメリット
- 多くの場合、企業は利益を得ることなく異種で無関係なデータマートを作成するので維持に大きなコストがかかる
- データセットが限られているため全社的な分析を行うことはできない

## データマートの種類
大別すると3つ

- 従属データマート
- 独立データマート
- ハイブリットデータマート

### 従属データマート
単一のデータウェアハウスから組織のデータを調達する

1つ以上を構築する場合はそれぞれがデータウェアハウスと依存関係にあるデータマートとして構築する

### 独立データマート
中央のデータウェアハウスを使用せずに構築する

- 組織内の小さなグループにとっては理想的
- 入力も分析も自律的

### ハイブリットデータマート
データウェアハウスとは別にソースからの入力を組み合わせる

- 新しいグループや製品を組織に追加した後などに役立つ
- より特定の用途でデータをまとめ上げたい時等

## データマートの作成手順
### 全体フロー
- 設計
- DB構築
- ETL
- インターフェース構築
- 運用

### 設計
ビジネス、技術要件を収集し、データソースを特定する。

- タスク
  - データの適切なサブセットを選択する。
  - データマートの論理的および物理的構造を設計する。

- データの分類基準
  - 日付
  - ビジネスユニットまたは機能ユニット
  - 地理
  - 上記の組み合わせ

- 必要なもの
  - 紙とペン
  - UMLやER図を作成し論理->物理と設計しメタデータを設定する

### DB構築
物理データベースと論理構造を作成する

- タスク
  - 設計に基づいたテーブル、インデックス、ビューなどを作成する

- 必要なもの
  - RDBMS

- 必要機能
  - ストレージ管理
  - 高速・データアクセス
  - バックアップ・復元機能
  - マルチユーザー・サポート(複数アクセス考慮)
  - セキュリティ(アクセス権限制御)

### ETL
データマート内にデータを移入する

- タスク
  - ソースデータの抽出
  - ソース・データからターゲット・データへのマッピング
  - データのクリーニングと変換操作
  - データマートへのデータのロード
  - メタデータの作成と保存

- 必要なもの
  - ETLツール

### インターフェース構築
データを照会し、レポート、チャートを作成できるようにする
エンド・ユーザーがデータベースにクエリーを送信し、クエリーの結果を表示できるようにする

- タスク
  - データベース構造とオブジェクト名をビジネス用語に変換するメタレイヤーを設定する
  - 必要に応じてAPIやインターフェースをセットアップする

### 運用
継続的に利用できるようにする

- タスク
  - ユーザー・アクセス管理
  - 最適化・調整によるパフォーマンスの向上
  - 新しいデータの追加、メンテナンス
  - 可用性確保(復旧計画)

## データマートの非機能要件
- データマートのソースは、部門別に構成されている必要がある
- データマートの実装サイクルは数週間、数ヶ月の短期間で測定する必要がある
- データマートの実装が複雑になる可能性があるため、計画と設計段階ですべての利害関係者を関与させることが重要
- ハードウェア/ソフトウェア、ネットワーキング、インプリメンテーションのコストを計画に正確に計上する必要
- 追加のソフトウェアを必要とすることが多いので、追加分の処理能力とディスク・ストレージ要件を評価する
- データマートにデータを転送するために必要なデータ量を処理するのに十分なネットワーク容量を確保する

## 書籍情報
クリシュナルンタ, データウェアハウジングを1日で学ぶ
https://amzn.to/2VNt4f0

## 雑感
この人の書いている本が色々と入りに良さそう
【Vue Test Utils】`shallowMount + stubs` で子コンポーネントを含めてテストを良い感じにする

# はじめに
vue-test-utils で子コンポーネントも見たかったので `mount` を使ってテストしていましたが、やたら時間がかかってタイムアウトになってしまいます。

なので、渋々 `shallowMount` に変更して子コンポーネントも一緒に使えないか調べました。

#`shallowMount + stubs` で良い感じになる


```js

import Foo from './Foo.vue'

mount(Component, {
  stubs: ['registered-component']
})

shallowMount(Component, {
  stubs: {
    // 特定の実装によるスタブ
    'registered-component': Foo,
    // デフォルトのスタブを作成します。
    // このケースではデフォルトのスタブのコンポーネント名は another-component です。
    // デフォルトのスタブは <${デフォルトのスタブのコンポーネント名}-stub> です。
    'another-component': true
  }
})
```
>引用元：https://vue-test-utils.vuejs.org/ja/api/options.html#stubs
Pythonでmarkdownをhtmlにコンバートする

マークダウンをhtmlにコンバートする方法を探していた。pipで入れられる[markdown](https://github.com/Python-Markdown/markdown)がよさそうなので少し試してみる。

pyenvで入れた環境

```shell
$ python --version
Python 3.6.5
$ pip --version
pip 19.1.1 from /Users/ito_masakuni/.pyenv/versions/3.6.5/lib/python3.6/site-packages/pip (python 3.6)
```

インストール

```
$ pip install markdown
Collecting markdown
  Downloading https://files.pythonhosted.org/packages/c0/4e/fd492e91abdc2d2fcb70ef453064d980688762079397f779758e055f6575/Markdown-3.1.1-py2.py3-none-any.whl (87kB)
    100% |████████████████████████████████| 92kB 5.8MB/s
Requirement already satisfied: setuptools>=36 in /Users/ito_masakuni/.pyenv/versions/3.6.5/lib/python3.6/site-packages (from markdown) (39.0.1)
Installing collected packages: markdown
Successfully installed markdown-3.1.1
```

下記のスクリプトを書いた。

<pre>
import markdown

sample_text = '''
# h1の文字が出てくると嬉しい

---

## h2の文字はでてくるだろう

* リスト1
* リスト2
* リスト3

> 引用してくれ

本文で **太字にもなるし**、*斜体にもなるはず* 。

```
まさかコードも入れられるんですか？
if (!lie) {
    return true;
}
```

| header1 | header2 | header3 |
|:-----------|------------:|:------------:|
| 左寄せ | 右寄せ | 中央寄せ |

すごい！
'''

md = markdown.Markdown()
print(md.convert(sample_text))
</pre>

で、アウトプットはこうなった。

```
$ python md.py
<h1>h1の文字が出てくると嬉しい</h1>
<hr />
<h2>h2の文字はでてくるだろう</h2>
<ul>
<li>リスト1</li>
<li>リスト2</li>
<li>リスト3</li>
</ul>
<blockquote>
<p>引用してくれ</p>
</blockquote>
<p>本文で <strong>太字にもなるし</strong>、<em>斜体にもなるはず</em> 。</p>
<p><code>まさかコードも入れられるんですか？
if (!lie) {
    return true;
}</code></p>
<p>| header1 | header2 | header3 |
|:-----------|------------:|:------------:|
| 左寄せ | 右寄せ | 中央寄せ |</p>
<p>すごい！</p>
```

テーブルが変換されていないので少し調べる。どうやら[エクステンション](https://python-markdown.github.io/extensions/)指定して実行しないとならないみたい。[オフィシャルでサポートされているエクステンション](https://python-markdown.github.io/extensions/#officially-supported-extensions)は、実行時に指定するだけでコンバートしてくれるみたい。テーブルはオフィシャルに含まれている。その他[サードパーティ](https://github.com/Python-Markdown/markdown/wiki/Third-Party-Extensions)もたくさんある模様。

呼び出しのところにエクステンションを持たせる。

```
md = markdown.Markdown(extensions=['tables'])
print(md.convert(sample_text))
```

実行する。

```html
<h1>h1の文字が出てくると嬉しい</h1>
<hr />
<h2>h2の文字はでてくるだろう</h2>
<ul>
<li>リスト1</li>
<li>リスト2</li>
<li>リスト3</li>
</ul>
<blockquote>
<p>引用してくれ</p>
</blockquote>
<p>本文で <strong>太字にもなるし</strong>、<em>斜体にもなるはず</em> 。</p>
<p><code>まさかコードも入れられるんですか？
if (!lie) {
    return true;
}</code></p>
<table>
<thead>
<tr>
<th align="left">header1</th>
<th align="right">header2</th>
<th align="center">header3</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">左寄せ</td>
<td align="right">右寄せ</td>
<td align="center">中央寄せ</td>
</tr>
</tbody>
</table>
<p>すごい！</p>
```

すごい！
Pythonで１行の標準入力を１行で展開する

小ネタです。

AtCoderやPaizaなど、Web上のプログラミングテストみたいなものを受けるとき、

> 標準入力に半角スペース区切りで入力が渡される

みたいな場合が多いです。そのときに１行で標準入力を展開する方法を書いてみます。

## 例題
半角スペース区切りで

```
N M
S-1
S-2
…
S-n
```

という形式で入力が渡される。`N`と`M`は数値とする。

`S`は文字列で、`N`の数値回数分だけ渡される。

`M`は、問題のどこかで使う値ということにしましょう。この記事では使いません。

## 入力を受け取る

```python
n, m = (int(x) for x in input().split())
```

これでいけます。

さらに、`S`も受け取るなら

```python
n, m = (int(x) for x in input().split())
for i in range(n):
    s = input()
    # 問題を解く
```

という感じで受け取れます。

## 解説

処理は、以下の順で行われています。

### input関数

`input()`は、入力から１行取り、文字列で返します。改行は含まれません。

上記の問題だと、

`N M`という、半角スペースで区切られた文字列を返してきます。

### split関数
文字列を、引数で指定した文字があるところで分割した`list`を返します。

引数を指定しないと、だいたい半角スペースで区切ってくれます。よって、今回のケースだと引数を指定する必要がありません。

参考：https://docs.python.org/ja/3/library/stdtypes.html#str.split

### 内包表記

```python
(int(x) for x in input().split())
```

というような、`(... for ... in list)`みたいな表記を、**内包表記**といいます。

あえて別のソースで書くなら、

```python`
str_list = input().split()
for x in str_list:
   yield int(x)
```

という処理に近いです。`x`に、元のリスト内の要素（今回だと文字列が渡されているので、個々の文字を示す文字列）が入ってきます。

`[... for ... in list]`と、`[]`で括るとリストが返ってきて、`()`で括るとタプルが返ってきます。

### キャスト
上で書いたように、内包表記で個々の文字が文字列で返ってくるので、それをそのまま`int`に型変換しています。

`int(x)`みたいに数値に変換したい値を渡すと、いい感じに数値に変換してくれます。

### タプル、リストのアンパック
公式ドキュメントの以下のページに記載があります。

https://docs.python.org/ja/3/tutorial/datastructures.html#tuples-and-sequences

例えば、要素数が２のタプル（変数`t`）があったとすると、

```python
a, b = t
```

と書くと、ループやインデックスでのアクセスを行わなくても中身を展開して取り出せます。上記の書き方で、要素数が2ではない場合、エラーが発生します。（画像はVisual Studio Codeのもの）

![toomanytuple.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15429/4aa3ee5a-383b-6093-816c-c843d05e3d3e.png)

要素数が決まっていない場合は扱えませんが、競技プログラミングのように、どのような入力が渡ってくるか決まっている場合は問題なく使えます。

余談ですが、アンパックはタプルでもリストでも可能です。どちらも`Sequence`だからです。

### 解説まとめ
１行で書かれていた標準入力を展開する処理ですが、処理は以下の順で行われています。

* 標準入力をそのまま受け取る
* 半角スペースで区切ってリストにする
* リストの中身を内包表記の中で数値に変換する
* 内包表記をアンパックして変数に格納

## おわりに
今回のコードは、定型文として覚えておくとそのまま使えますが、仕組みを知っておくと応用が利きます。
特に内包表記はPythonで多用する（というより使わざるを得ない場合が多い）ので、慣れておくとできることが増えて楽しいです。
JavaでJWTを使ってみた

# 概要
Javaのライブラリを使ってJWTを導入した際の事をメモとして残しておく。

# JWTとは
- Web Tokenの略称で「署名の出来るJSONを含んだURL Safeなトークン」です。
- JWTはHeader、Payload、Signatureで構成されていて、Header、PayloadはJsonをBase64エンコードした情報なので、ユーザー情報やパスワードなど外に公開したくないものは入れないようにするのがいいみたい。
- 署名されているのでJson部分を改ざんしても検証時にチェックできる

# トークンの例
- トークン全体はこんな感じ

```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.izVguZPRsBQ5Rqw6dhMvcIwy8_9lQnrO3vpxGwPCuzs
```

- Header部分

```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
```

- Headerをデコードすると

```
{"typ":"JWT","alg":"HS256"}
```

- Payload部分

```
eyJpc3MiOiJhdXRoMCJ9
```

- Payloadをデコードすると

```
{"iss":"auth0"}
```

# 実際にJavaで書いてみた
- 環境
    - java8
    - java-jwt（jwt.ioでも公開されてるjwtを扱うjavaライブラリ）
- 今回はIssuerとExpireTime付のJWTを作ってみて動作を確認した
- アルゴリズムはHS256を採用
- いざトークン生成

```java
try {
    Date expireTime = new Date();
    expireTime.setTime(expireTime.getTime() + 600000l);

    Algorithm algorithm = Algorithm.HMAC256("secret");
    String token = JWT.create()
            .withIssuer("auth0")
            .withExpiresAt(expireTime)
            .sign(algorithm);
} catch (JWTCreationException exception){
    //Invalid Signing configuration / Couldn't convert Claims.
}
```

- トークンの検証

```java
String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.izVguZPRsBQ5Rqw6dhMvcIwy8_9lQnrO3vpxGwPCuzs";
try {
    Algorithm algorithm = Algorithm.HMAC256("secret");
    JWTVerifier verifier = JWT.require(algorithm)
            .withIssuer("auth0")
            .build(); //Reusable verifier instance
    DecodedJWT jwt = verifier.verify(token);
} catch (JWTVerificationException exception){
    //Invalid signature/claims
}
```

# 使った感じ
- java-jwtの公式ページに書いてあるコードを拝借すれば動作確認は簡単にできた。
- ちゃんとJson部分(HeaderやPayload部分）が改ざんされた場合に`JWTVerificationException`が投げられチェックされている。
配列とループ処理について質問

質問です。

要素数が20の1次元配列に整数１００～１１９を順に格納するには
どのようなコードを書けばよいでしょうか？

ループ処理は必ず使いたいです。

ちなみに、以下のようなコードを書きましたが、そこから先が
でてこず困っています。

int num = new int[20];

for(int i=100; i<120; i++)
{
　　num[]=i;
}
Console.WriteLine(num[]);
【OculusQuest】開封レビュー&比較

#本記事の概要
OculusQuestが届いたので、開封して中身を確認する記事になります。

#現在、持っているVR/MR機器
*HoloLens
*Fove
*Oculus Rift DK1
*Oculus Go
*Oculus Quest←New！
(※一時期、VIVEも持っていた経験あり。PSVRも遊んだことあります)

#箱
OculusRiftDK1の箱よりかは小さく、OculusGoの箱よりは大きい感じ。
![IMG_-6oipv0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/7dfebc95-e765-b399-bf3a-7a545eb5699e.jpeg)
![IMG_20190524_055937.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/60cbc674-e8a8-c729-2624-1b4a405d5fa5.jpeg)
![IMG_20190524_073518.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/9688a76a-3771-0e5d-6d7e-12a187142260.jpeg)


#中身
##入っているもの
*本体
*コントローラー(電池付属)
*充電ケーブル(USB-typeC)
*スペーサー(おそらく眼鏡用)
*説明書

![IMG_20190524_060016.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/df42955e-641b-4b30-8bf4-1d26fe61dbc9.jpeg)
![IMG_20190524_060152.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/a295b8af-9129-3fd8-e7ee-0f8764b7612c.jpeg)

##コントローラー
OculusRiftのコントローラーと比べて、持つ向きがわかりにくいですが、
やはり、VIVE系のものと比べてかなり持ちやすく、手に馴染む構造。
(電池はRiftやGoと同様に蓋を滑らせて外してから入れるタイプ)

![IMG_20190524_060228.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/d5eb2219-64a0-f1fa-f415-a5c2757d5a53.jpeg)
![IMG_20190524_060316.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/edf60ab3-47ee-57c9-9f0a-0c7e4f2b168a.jpeg)
![IMG_20190524_073556.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/6ba74166-3983-e3f8-fecd-97ad1d11a428.jpeg)

##本体
OculusGoとほとんど同じ外見。ただ、3DoF(Degrees of Freedom)のGoとは違い、6DoFになったため、フロントに４つカメラが搭載されている点が異なる。ちなみにスペーサーのおかげか、眼鏡しながらでも余裕でプレイできました(※縁の細い眼鏡です)
![IMG_20190524_073650.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/5d148a83-ca12-fcab-855d-43595329d9b4.jpeg)
![IMG_20190524_073721.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409659/eb66faac-cbbf-3b26-096a-f21f6936de35.jpeg)

#初期ペアリング時の注意
Oculusアプリで「設定」からペアリングをする際、Questが表示されておらず、少しハマりましたが、
スマホを再起動したら普通に表示されて問題なくペアリングできました。

#所感
大きく言えば、Riftの良さ(６DoFで酔いにくく、自由に動ける点)とGoの良さ(ケーブルがなく、煩わしさがない点)が合体した感じ。
コンテンツはRiftで人気だった、ビートセーバー、ロボリコール、ジョブシミュレーター、VRチャット、ビッグスクリーンベータあたりがある感じ。(Oculusはエピックローラーコースターを勧めてくるけど、酔うのでやらない方が良いです)
VS Code 用の MEL スクリプト拡張

だいぶ前に作った、Visual Studio Code で MEL スクリプトのシンタックスハイライトをする言語拡張。コマンドのオートコンプリートも。


TextMate のヤツを丸コピからの、ちょい修正。




<!--
https://qiita.com/sator_imaging/items/fe51a29a4bfdbe5e955c
-->



## インストール方法

VS Code のコマンドパレット（Ctrl+P）で、``ext install mel`` を実行すると見つかる。


その他のダウンロード ↓



### Visual Studio Marketplace

- [MEL - Maya Embedded Language - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=sator-imaging.mel)
   <iframe
      class="embed-card embed-webcard"
      scrolling="no"  frameborder="0"
      style="
         display: block;  border: none;
         margin: 10px 0px;
         width: 100%; height: 155px;
         max-width: 500px;
      "
      src="https://hatenablog-parts.com/embed?url=https://marketplace.visualstudio.com/items?itemName=sator-imaging.mel">
   </iframe>




### GitHub

- [sator-imaging/Visual-Studio-Code-MEL-Language](https://github.com/sator-imaging/Visual-Studio-Code-MEL-Language)
   <iframe
      class="embed-card embed-webcard"
      scrolling="no"  frameborder="0"
      style="
         display: block;  border: none;
         margin: 10px 0px;
         width: 100%; height: 155px;
         max-width: 500px;
      "
      src="https://hatenablog-parts.com/embed?url=https://github.com/sator-imaging/Visual-Studio-Code-MEL-Language">
   </iframe>
ファミコンのエミュレータをRustで書いた

男もすなるNESエミュ作成といふものを、女もしてみむとてするなり。

# 概要

いろいろな人がやっているエミュレータ作成を、何番煎じかわからないけどやってみました。
ひとまずそこそこ動いたので公開し、ハマったポイントなどを紹介します。

# 成果物

[githubリポジトリ](https://github.com/chalharu/nerust)

# 参考にすべきサイト

[Nesdev](https://wiki.nesdev.com/w/index.php/Nesdev_Wiki)
ここを見ましょう。ほぼ全て載っています。テストROMもあります。

[NES on FPGA](http://pgate1.at-ninja.jp/NES_on_FPGA)
書き始めはこのサイトにおせわになりました。

# 実装にあたり検討すべき事項

## CPU命令の実装粒度

1クロック毎の動作を実装するか、命令毎に実装する（数クロック分を１つの処理として実装）か検討する必要があります。
よくある日本語の記事では、命令毎に実装していますが、厳密なエミュレーションはできないと思われます。
厳密に実装するのであれば、ダミーの読み書きや、IRQのタイミングなども制御できるメリットがありますが、
実行速度が犠牲になるので、要検討事項だと思われます。

今回は次のような実装としました。

```rust
pub(crate) enum CpuStepStateEnum {
    Continue,
    Exit(CpuStatesEnum),
}

pub(crate) trait CpuStepState {
    fn exec(
        core: &mut Core,
        ppu: &mut Ppu,
        cartridge: &mut Cartridge,
        controller: &mut Controller,
        apu: &mut Apu,
    ) -> CpuStepStateEnum;
}

pub(crate) enum CpuStatesEnum {
    FetchOpCode,
    Reset,
    Irq,
    AbsoluteIndirect,
    AbsoluteXRMW,
    AbsoluteX,
    // 以下同様にアドレッシングモード関連が続く
    And,
    Eor,
    Ora,
    // 以下同様に命令が続く
}
```

次のように利用します

```rust
while let CpuStepStateEnum::Exit(s) = machine(self, ppu, cartridge, controller, apu) {
    // 次の実装を呼び出す
}
```

書いて見たところ、あまり綺麗な実装とは言い難いので、要検討事項でしょう。

## DMA転送とAPU DMCと例外の取り扱い

競合します。どう実装するか考えておいた方がよいかと思います。
今回の実装では後から追加したため、実装上の課題事項として残ってしまってます。

## 例外のタイミング

厳密に作ろうとするとかなり厄介です。NesDevを見たりしながら実装し、テストケースは通過しておりますが、
いまだによくわかっていません。

## オープンバスの取り扱い

オープンバスに書き込んだ内容は時間経過と共に減衰します。
今回は次のような実装にしました。

```rust
struct DecayableOpenBus {
    data: u8,
    decay: [u8; 8],
}

impl DecayableOpenBus {
    pub fn new() -> Self {
        Self {
            data: 0,
            decay: [0; 8],
        }
    }

    pub fn unite(&mut self, data: OpenBusReadResult) -> u8 {
        for i in 0..8 {
            if (data.mask >> i) == 1 {
                self.decay[i] = 20;
            }
        }
        let result = (self.data & !data.mask) | (data.data & data.mask);
        self.data = result;
        result
    }

    pub fn write(&mut self, data: u8) -> u8 {
        self.data = data;
        self.decay = [20; 8];
        data
    }

    pub fn next(&mut self) {
        let mut result_mask: u8 = 0;
        for i in 0..8 {
            if self.decay[i] > 0 {
                self.decay[i] -= 1;
                result_mask |= 1 << i;
            }
        }
        self.data &= result_mask;
    }
}
```

## 実行速度の基準

60FPSを基準に実行速度を考えた場合、サウンドにズレが発生します。
サウンドの再生速度については、ハードウエア側で制御されることから、
そちらを基準にしてもよいかもしれません。

## NTSCとPALの違い

対応するか事前に検討しておく方が良いかと思います。
特に1CPUクロック=3.2PPUクロックとなってしまうことから、
どちらかというとPALの方が実装が厄介そうです。
今回は対応しておりませんが。

## ステートマシン

CPUはステートマシンであることから、実装においても念頭に置く必要があると思われます。ステートマシンの種類にはミーリマシンとムーアマシンがありますので理解しておいたよいかと思います。

## GTK+

macにおけるOpenGL WidgetであるGLAreaにはv3.24現在、リサイズが正しく動作しない不具合があるようです。
mac自体がOpenGLを非推奨としていることもあり、どうしたものか検討中です。

## OpenAL

実装をmacで実施したことから、CoreAudioをOpenALで叩いております。
OpenALはかなりお手軽なのでこのまま行きたいのですが、
Androidだと遅延が激しいと聞いています。
今後Android等で実装する場合はせめてOpenSL ESを利用した方がよいと思われます。

# おわりに

とりあえず書いて見ましたが、ここの解説が欲しい、ここが間違っているなどがありましたら、気軽にコメントください。
plunkerでjor1k その6

#概要

plunkerでjor1kやってみた。
risc-vで九九をインラインアセンブラでやってみた。

#サンプルコード

```
#include <stdio.h>

int kakeru(int a, int b)
{
	int result;
	asm ("mul   %0,%1,%2"
		: "=r" (result)
		: "r" (a), "r" (b));
	return result;
}
int main(void)
{
	int i,
		j;
	printf ("   ");
	for (i = 1; i < 10; i++)
	{
		printf ("%2d ", i);
	}
	printf ("\n");
	for (j = 1; j < 10; j++)
	{
		printf ("%2d ", j);
		for (i = 1; i < 10; i++)
		{
			printf ("%2d ", kakeru(i, j));
		}
		printf ("\n");
	}
}
```

#結果

```
~ $ gcc test.c                                                                  
~ $ ./a.out                                                                     
    1  2  3  4  5  6  7  8  9                                                   
 1  1  2  3  4  5  6  7  8  9                                                   
 2  2  4  6  8 10 12 14 16 18                                                   
 3  3  6  9 12 15 18 21 24 27                                                   
 4  4  8 12 16 20 24 28 32 36                                                   
 5  5 10 15 20 25 30 35 40 45                                                   
 6  6 12 18 24 30 36 42 48 54                                                   
 7  7 14 21 28 35 42 49 56 63                                                   
 8  8 16 24 32 40 48 56 64 72                                                   
 9  9 18 27 36 45 54 63 72 81                                                   

```

#成果物

https://embed.plnkr.co/C1BoW7lPIaKzXehzeKQ6/

以上。
Docker 初学　~imageとcontainer~

# Docker 初学 ~ imageとcontainer~
Dockerについて学習したのでDocker imageとcontainerについての知見を深めるために、
自分が学んだことをアウトプットしていきます。

## Dockerとは
Dockerとはコンテナ型仮想化技術を実現したプロダクトです。
簡単にいうと、自分のローカル端末の環境を他の人に簡単に渡せるようになるという感じです。
コンテナ型仮想化技術についての詳細はここでは割愛します。
Dockerの基礎的な動作は「Docker image」と「Docker container」に分けられます。

## 「Docker image」と「Docker container」の関係性
imageとcontainerがどんな関連性を持つか簡単なイメージを作成しました。

<img width="644" alt="スクリーンショット 2019-05-23 21.29.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325856/36efd3ca-a162-28bf-c6e3-b1d8c5e69012.png">

**Docker image**
実行するアプリケーションやOSなどの設定をまとめたもので、コンテナを作成するもとになるものです。
**Docker container**
imageをもとにcontainerを作成して、アプリケーションやOSを実行状態にしたものです。

**まとめ**
すごく簡単にいうとimageはあくまで設定をまとめたもので、containerはimageを実行している状態のものです。
**補足情報**
一つのimageから複数のcontainerを作成することができます。

## Docker imageについて
「Docker image」の作成は、とてもシンプルです。「Docker File」と言われる定義ファイルにOSなどを設定していけば「Docker image」を作成できます。

ここで簡単なDockerfileを作成してみます。ファイル名は「Dockerfile」です。拡張子もいりません。

```dockerfile:Dockerfile
# From句 必須項目 DockerHubから元となるイメージを取得する。
# Dockerfileは必ずFrom句から始まります。そして、DockerHubからイメージをダウンロードしてきます。
From debian:stable-slim
# CMD句 任意項目 Docker image 作成時に実行するコマンドを定義する。
CMD ["echo","Hello World!"]
```
何をしているかというと、DockerHubにあるdebianのimageをもとにDockeriamgeを作成しているだけです。
（OSを設定しているだけでアプリケーションは乗せてないです。）

そして、以下のコマンドを実行すると、Dockerimageができると思います。

```console
docker image build -t example/echo:latest .
```

Docker imageが作成できた確認として以下のコマンドを実行してください。

```console
docker images
# example/echoとdebianのimageが表示されるはずです。
```

今回作成した「Docker image」のイメージ図は以下の感じです。
debianを内包しているような感じです。
<img width="275" alt="スクリーンショット 2019-05-23 22.08.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325856/a2579c7f-994f-e764-3f82-f37b0b3f0b78.png">

ここにjavaだとかgoとか様々なアプリをカスタマイズしていきます。
（プログラミング言語を内包したDockerimageは公式として提供されているケースが多いです。）
**まとめ**
Dockerfileを作成して「Docker image」を作成する。
自作の「Docker image」は別の「Docker image」に依存するケースがある。
（From 句でscrachと指定されているのは違いますが、話が難しくなるので割愛します。）

## Docker containerについて
それでは、イメージからコンテナを作成してみましょう。

```console
docker container run example/echo
```
Hello Worldと出力されたと思います。

今回作成したコンテナはコマンド実行だけですが、httpリクエスト受付やできることが
もっとありますので、今度試してみたいと思います。
laravelのインストール

laravelのインストール
composer　が入った後Laravelを作成する際
通常の解説では

```
laravel new hogehoge
```
としてたが、うまくいかないことがある事とダウングレードすることから

```
composer create-project laravel/laravel:5.5 hogehoge
```
にしたほうがいい。
plunkerでjor1k その5

#概要

plunkerでjor1kやってみた。
risc-vやってみた。

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/9033ce23-8147-2522-f81b-cf2cc8fcc460.png)


#成果物

https://embed.plnkr.co/C1BoW7lPIaKzXehzeKQ6/

以上。