OmniAICreator/Qiita-1.07M huggingface dataset:
iOS11.0でUINavigationBarの高さが正しく表示されない現象について

# はじめに
こんにちは :leaves:
実装としてはあまり良くないのかもなのですが、アプリ画面を作成する際に
UINavigationControllerのような左右の遷移関係が無くても上側にNavigationBarが欲しい時があり、
私はNavigationItemのようなボタンがいい感じに収まるという理由で**UINavigationBar**を生成して使ってしまっています。
そこで、Xcode9.0にて**UINavigationBar**をStoryboardまたはコードで生成すると以下のようになってしまいます。

<img width="450" alt="sketch222.png" src="https://qiita-image-store.s3.amazonaws.com/0/128250/1149362d-a5d4-6420-5096-d306746a3154.png">

# 解決方法
今回はカスタムクラスを作ってそれを充てて利用するようにしました。
Storyboardで正しく表示される方法などもカスタムクラスを作らずとも解決したかったのですが、少し厳しかったです...

```CustomNavigationBar.swift
import UIKit

@IBDesignable class CustomNavigationBar: UINavigationBar {
    
    override func layoutSubviews() {
        super.layoutSubviews()
        if #available(iOS 11.0, *) {
            for subview in self.subviews {
                let stringFromClass = NSStringFromClass(subview.classForCoder)
                if stringFromClass.contains("BarBackground") {
                    subview.frame = self.bounds
                } else if stringFromClass.contains("BarContentView") {
                    subview.frame.origin.y = UIApplication.shared.statusBarFrame.height
                    subview.frame.size.height = self.bounds.height - UIApplication.shared.statusBarFrame.height
                }
            }
        }
    }
}
```

※ `@IBDesignable`をつけることでStoryboardにて高さが正しく表示されました。
ただ、描画させるものが特にないため、**本来の目的とは異なる**ので注意が必要です。

※ UINavigationBarの見た目の高さなどを調節しているようです。(UINavigationBarのsubviewsを表示させてみましたが、どれがどのような役割なのか詳しくは調べられませんでした...すみません)

```
UINavigationBar
  ├── UIBarBackground
  ├── UINavigationBarLargeTitleView
  ├── UINavigationBarContentView
  └── UINavigationBarModernPromptView
```

# さいごに
Xcode9.0にてUINavigationBarの細かい変更点を完全には確認できなかったので、
今回は動かすための、とりあえずの回避のようになってしまいました...
`safeAreaLayoutGuide`など今後もう少し確認していきたいなと思いました。

# 参考にさせていただいた記事
- [How to change navigationBar height in iOS 11? - stackoverflow](https://stackoverflow.com/questions/46138245/how-to-change-navigationbar-height-in-ios-11/46138389?noredirect=1)

- [iOS 11 navigation bar height customizing - stackoverflow](https://stackoverflow.com/questions/44387285/ios-11-navigation-bar-height-customizing)

見て頂いてありがとうございます。
PyTorchを使っているときに起きたGPU周りのトラブル

小ネタです

## 確保したGPUメモリが迷子になってしまった

- Notebookでプロセスの実行中に、Juypyter Kernelを再起動してしまう（よくある 
- Ctrl+C を連打して、メモリの開放処理が正しく行われなかったとき

気をつけましょう

## CUDAの初期化で失敗する

```
python -c "import torch; print(torch.cuda.is_available())"
```

が `False` になってしまう状態です。僕の場合は、notebookでPyTorchを使っているまま、Ubuntuをスリープして、再開した際に、たまに（毎回ではない）CUDAが使えなくなってしまうことがありました。こうなってしまったら、僕は再起動しています…つらい。より良い方法があれば、どなたか教えてください。

以上です。ここに書いたことは、PyTorchに限らず、GPUを使う数値計算のライブラリでは避けた方がよいですね。
Salesforce 開発で試している git フロー (rebase & force push)

git での管理が当然のようになっている昨今ですが、直近携わっている Salesforce の開発ではどうしたら良いか・・・ベストプラクティスが分からずにおります。
そこで、直近 Salesforce の開発で試しているフローを簡単にまとめて晒してみることにしました。
(そして、もっと良い方法をご教示頂ければ幸いですmm)

# 1. 前提

## ブランチ構成がこんな感じ

```
master   (リリース用)   1 ---> 2 ---------> 3
topic    (バグ修正用)          |\---> @ ---/
feature1 (機能1追加用)         |\--------------> A ---> B
feature2 (機能2追加用)          \--------------> C ---> D
```

### 補足

* 状況・開発体制・ルールなど
    * Salesforce 組織は本番稼働中。運用保守業務 + 機能追加開発 のため、Sandbox (適宜リフレッシュ済) のソースを git 管理
    * 少数 (数名規模)
    * マージはプルリクベース。マージできるのは一人 (レビュアー) のみ
* ブランチ
    * feature1, 2 が master にマージされるのは、大分先である（ブランチの生存期間が長い。両方共1ヶ月以上とか）
    * その間 master には、保守作業により topic ブランチが複数作成・マージされる

# 2. 結論

* feature ブランチの生存期間が長いなら、master の最新コミットから rebase する
* そして、force push する

```shell-session
$ git checkout feature1
$ git rebase master
$ git push origin -f feature1
(feature2 についても同様)
```

こうなる

```
master   (リリース用)   1 ---> 2 ---------> 3
topic    (バグ修正用)           \---> @ ---/|
feature1 (機能1追加用)                      |\---> A ---> B
feature2 (機能2追加用)                       \---> C ---> D
```

# 3. なぜこのように (rebase & force push) しているのか

## topic を feature1, 2 にマージするのはダメなの？

* [トピックブランチと統合ブランチでの運用例【ブランチ】 | サルでもわかるGit入門](https://www.backlog.jp/git-guide/stepup/stepup1_5.html) の [A successful Git branching model] のように、ツリーが複雑な形になるのでは・・・
* そして、いざ feature を master にマージする時点で、予期しないバグ (topic で修正したはずの箇所が、マージミスによって再発してしまった等) が紛れ込んだ場合、追跡するのが大変になるのでは・・・
* 
と懸念しました。

一方 rebase ならば、ツリーの形がすっきりしている (常に最新から派生していることがわかる) ため、そのような事態になっても比較的なんとかなりそうです。

マージも rebase も、コンフリクトが発生する時は発生するわけですが、rebase 時は各コミットに対してコンフリクトの解決を迫ってくれるのもポイント高いです。
(feature1 を、コミット 3 から rebase する際 A, B 両方共コンフリクトしたとして、まずは A に対してコンフリクト箇所を提示。次は B に。B が解決したら rebase 完了)

## force push は危険と聞いたことがあるので、基本的にしない方が良いのでは？

feature ブランチは生存期間が長い & 複数人で開発しているという背景があり、origin へ push は既定路線という事情です。
これを rebase するわけですから、force push は避けられません。

できれば、force push せずにやれたらいいなと思います。しかし、携わっているプロジェクトについては、ツリーをシンプルに保つことで品質を上げること優先と考えています。
このため、force push もやむなし (代わりに、slack でメンバーに「rebase しといたから stash, fetch, pull 等よろしくオナシャス」通知して、何かあったらヘルプを求める運用) にしています。

# 4. まとめ
今の所、この方式でとくに大きな問題は起きていません。(メンバーのスキルが高いおかげもめっちゃある)
また色々改善点が見えたら、追記していこうと思います。

ちなみに、Salesforce の開発では Apex や Visualforce ページ, コンポーネントだけでなく、メタデータも管理する必要があります。また、年3回 (だったような・・・) のバージョンアップに伴い、担当した箇所以外の差分も発生します。さらに、本番・fullsand, sandbox といった環境毎に微妙にメタデータが異なっている (要素の並び順が違う・バージョンが違う・・・など) ようなこともあります。
このため、「本番で動いているものが正。ソース管理もそのへんに気をつけて」ということがあったりします。(そうでもない...?)

Docker のように「ソースを完全に git に管理し、これベースにデプロイ」という環境に慣れた身には、手順書ベースで業務を行っていた遠い昔に戻ったようで何とも切ない感じを覚えることがあります。。。
が、SalesforceDX もボチボチ GA になりそうな雰囲気になってきましたので、「ソースベース」で楽しく開発できる日を期待していきたいところです:laughing:
Ubuntuのバージョン確認

```
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="14.04, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
```
PowerShellスクリプトを簡単実行

PowerShellスクリプト(.ps1ファイル)の実行はちょっと手間。
一般的な実行方法は、

1. Windows PowerShellを起動
2. Set-ExecutionPolicyコマンドで実行ポリシーを変更
3. ps1ファイルを実行
4. Set-ExecutionPolicyコマンドで実行ポリシーを戻す

と少々面倒くさい。

バッチファイル(.batファイル)を使えば、
Windows PowerShellの起動も実行ポリシーの変更もすることなく
PowerShellスクリプトを実行できる。

```bat:powershell.bat
powershell -ExecutionPolicy RemoteSigned -File D:\temp\powershell.ps1
pause
```
```ps1:powershell.ps1
Write-Host "PowerShell実行"
```

上記のようなバッチファイルを管理者として実行すればよい。

【補足】
- **-ExecutionPolicy**の設定は当該セッションのみで有効なので、設定を戻す必要なし。

【参考】
[Windows PowerShell: PowerShell.exe](https://technet.microsoft.com/ja-jp/library/hh987044.aspx)
[Windows PowerShell スクリプトを実行する](https://technet.microsoft.com/ja-jp/scriptcenter/powershell_owner05.aspx)
ちょっとずつ読むドメイン駆動設計 第ニ部 モデル駆動設計の構成要素 第五章 ソフトウェアで表現されたモデル9(サービス)

# サービス

正直、ほとんど使ったことがないです。

ふるまいは大方適切なオブジェクトに収まるし、それで困ったことがないですね。。。

とはいえ、今後も使わない可能性がないわけでもないので、特徴を押さえておきます。

## 注意1

> ふるまいを適切なオブジェクトに当てはめることをあまりに早くあきらめ、徐々に手続き型プログラミングへと滑り落ちてしまうことだ。(第二部 第五章 より)

手続き型になってしまうのはDDDを諦めるということ。。。まずは、本当に、エンティティやバリューオブジェクトに当てはめるのが不自然かどうか・・・本当にサービスで良いのか考えましょう。

## 注意2

このサービスは**ドメイン層**の一部です。ドメインの一部であり、モデルの一部です。

[レイヤーアーキテクチャのアプリケーション層](https://qiita.com/YasuhiroKimesawa/items/367d0ab40433cfe2d57a)をサービスと呼ぶことがありますが、それとは違うということに注意しましょう。

逆に、アプリケーション層にビジネスロジックが書かれてしまうことがないかも注意しましょう。そのロジックはドメイン側のサービスではないか、それ以前にエンティティやバリューオブジェクトに適用できないか、検討しましょう。

## 特徴
- 実態よりも活動。名詞より動詞で命名される事が多い。
- 操作名はユビキタス言語を使う
- 引数と結果はドメインオブジェクトであるべき
- 状態はもたない

改めてサービスにするかどうかは慎重に検討しましょう。
awkによるcsvファイル結合スクリプト

### 用途/特長
同じ行数のcsvファイルが前提ですが、任意の数のcsvファイルを水平方向に結合するスクリプトを作成しました。
Unix/Linuxのpasteコマンドでも同様の事が可能ですが、大きな違いとして、file1, file2, file3, ... で
最初の1列目が共通な場合、file2以降では共通列を除いて結合していきます。

### 使用例
 ./concat_csv.awk -v com_column=1 file1 [file2] ...

com_column: 共通列の数 (file1, file2... の第1列が共通の場合、com_column=1と設定します)

### スクリプト

``` awk:concat_csv.awk

#!/usr/bin/awk -f

BEGIN{
    FS ="," 
    if(com_column == "" ){
        com_column = 5
    }
    for(i=1; i<ARGC; i++){
        file_index[ARGV[i]] = i
    }
}
{
    for(i=1; i<=NF; i++){
        arr[ file_index[FILENAME] , FNR , i ] =$i
        # printf("debug file=%s:arr[%d, %d, %d] = %s\n", FILENAME, file_index[FILENAME], FNR, i, $i)
    }
    file_nf[FILENAME] = NF
}
END{
    # printf("debug com_column=%d\n", com_column)
    for(i=1; i<=FNR; i++){
        for(j=1; j<=ARGC; j++){
            if(j==1){
                for(k=1; k<=file_nf[ ARGV[j] ];k++ ){
                    printf(arr[ file_index[ARGV[j]] , i , k])
                }
            }
            else{
                for(k=com_column+1; k<=file_nf[ ARGV[j] ];k++ ){
                    printf(arr[ file_index[ARGV[j]] , i , k])
                }
            }
        }
        printf("\n")
    }
}
ReactNative0.49からreact-native initで生成されるファイルの構成が変わった

## 背景

- `react-native init`したら構成が変わってた
- react-nativeのバージョンが0.48から0.49に上がっていたのでそこでのアップデートのよう

## 変更内容

### 変更前

- `index.android.js`と`index.ios.js`がありそれぞれHelloWorld的な画面が用意されていた
- 以下は`index.ios.js`
- androidもほぼ同じ

```js:index.ios.js
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

export default class Sample extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.ios.js
        </Text>
        <Text style={styles.instructions}>
          Press Cmd+R to reload,{'\n'}
          Cmd+D or shake for dev menu
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('Sample', () => Sample);
```

### 変更後

- 二つのファイルがほとんど同じで冗長だったのが共通化された

```js:index.js
import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('Sample', () => App);
```
```js:App.js
import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';

const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' +
    'Cmd+D or shake for dev menu',
  android: 'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});

export default class App extends Component<{}> {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit App.js
        </Text>
        <Text style={styles.instructions}>
          {instructions}
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});
```

## まとめ

- 変更前の構成で作ったアプリもこの形式に寄せた方が当然だけどDRY
- OS固有の処理が出てきたらそのときに各OS用のファイルを作る感じでよさそう
AngularCLIの画面を眺める

AngularCLIをVScodeで開き、構成を見てみます。

<img width="960" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/201155/68e0fdaa-874e-1da1-62ea-55a95e854a59.png">

**app>menu>header**
app全体に適応されるheader部分を定義
※後日中身を詳しく見る

**app>menu>navbar**
app全体に適応されるheader部分を定義
※後日中身を詳しく見る

**app>pages**
アプリケーションのコアとなる部分
画面のソースコードが詰まっている
css,html,spec.ts,tsの構成
ちなみにspec.tsはテストクラス
実際に見るのはts



<img width="960" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/201155/7eae6166-175b-69d1-105d-96a28befc372.png">

**service**
componentsよりも汎用的かつ裏で動くような処理

**app-routing.module.ts**
URLからコンポーネントを呼び出すよ！という指示を書く
import { コンポーネントの変数 } from './pages/コンポーネントの格納先';
{ path: 'pathの変数', component: コンポーネントの変数 },

**app.module.ts**
新しいModuleを作ったら書く(componentもserviceも)
import { サービスの変数 } from './service/サービスの格納先';
import { コンポーネントの変数 } from './pages/コンポーネントの格納先';
@NgModule({
  declarations: [
    コンポーネントの変数,
  ],
  providers: [
    サービスの変数
　],})
Goのstring型が思ったより容量食いだった話

表題の通り、Goのstring型を何の気なしに使っていたら思ったよりバイナリサイズ・消費メモリサイズが大きくなっていたという話題です。

Goプログラミングでバイナリサイズやメモリ消費量をカリカリにチューニングすることは多くないと思われるので、本稿の内容が重要になることは滅多にないだろうことを最初にお断りしておきます。

# mapのサイズが案外大きい

ある日、筆者は次のようなGoコードを書いていました。

```go
var oui = map[string]string{
	"AAAB": "Xerox",
	"AAAC": "Xerox",
	"AAAD": "Xerox",
	"AAAE": "Xerox",
	"AAAF": "Xerox",

	/* snip */

	"/Pv7": "Cisco",
	"/PxI": "Apple",
	"/P53": "HitachiR",
	"/P7C": "Invensys",
	"/P+q": "IeeeRegi",
 }
```

このmapは要素数が約2.4万、キーはASCII4文字固定、値はASCII2〜8文字というものです。これをビルドしてみると、このmapがバイナリサイズのうち950KBほどを占めていることに気づきました。

1要素あたりASCII6文字〜12文字しか情報が無いはずなのに、950KB/2.4万=約40バイトということで案外サイズが大きいと感じます。

# mapのキーの型を`string`から`int32`に変えてみた

思ったよりサイズを食っていると感じたので、mapのキーの型を`string`から`uint32`に変更してみました。キーはASCII4文字固定[^1]なので1:1対応で32bit整数に変換できます。

[^1]: もともと3バイト整数をBase64でASCII4文字にしていた

```go
var oui = map[uint32]string{
	0x1: "Xerox",
	0x2: "Xerox",
	0x3: "Xerox",
	0x4: "Xerox",
	0x5: "Xerox",

	/* snip */

	0xfcfbfb: "Cisco",
	0xfcfc48: "Apple",
	0xfcfe77: "HitachiR",
	0xfcfec2: "Invensys",
	0xfcffaa: "IeeeRegi",
}
```

このように変更したところ、バイナリサイズが380KBほど減少しました。計算してみると、1要素あたり16バイトほど減った計算になります。

いくらなんでも減りすぎではないか？と感じたので原因を調べてみました。

# `string`型はどう実現されているか

今回の現象の原因は`string`型の実装にあります。`string`型に対応する構造体は次のようなものです。

```go
type stringStruct struct {
	str unsafe.Pointer
	len int
}
```

（ [src/runtime/string.go](
 https://github.com/golang/go/blob/229aaac19e041ac74ab043d6ef09c8406bb0a9e7/src/runtime/string.go#L209-L212) より）

つまり、`string`型は文字列実体へのポインタと文字列長を表す`int`型とで構成されています。64bit環境であればポインタで8バイト、文字列長で8バイト、さらに文字列の実体の分もディスクまたはメモリが必要になります。mapのキーを`string`型(8+8+4文字=20バイト)から`int32`（=4バイト）に変更することで1要素あたり16バイト節約できたのは当然ということになります。

# 8バイト以下の`string`を`uint64`にする

同じノリでmapの値の型も`uint64`にしてみました。

```go
var oui = map[uint32]uint64{
	0x1: 0x0000005865726f78, // Xerox
	0x2: 0x0000005865726f78, // Xerox
	0x3: 0x0000005865726f78, // Xerox
	0x4: 0x0000005865726f78, // Xerox
	0x5: 0x0000005865726f78, // Xerox

	/* snip */

	0xfcfbfb: 0x000000436973636f, // Cisco
	0xfcfc48: 0x0000004170706c65, // Apple
	0xfcfe77: 0x4869746163686952, // HitachiR
	0xfcfec2: 0x496e76656e737973, // Invensys
	0xfcffaa: 0x4965656552656769, // IeeeRegi
}
```

容量削減のために無理をしている分、値を取り出すのに多少頑張る必要があります。

```go
	abbr64, ok := oui[oui24hash]
	b := make([]byte, 8)
	binary.BigEndian.PutUint64(b, abbr64)
	abbr := string(bytes.TrimLeft(b, "\x00"))
```

これをビルドすると更に290KB減となり、期待通りバイナリサイズ削減効果が得られました（同じ値を持つ要素があるため、キーのときより削減幅が小さくなっています）。当初のサイズと比較すると約950KBから約280KBと1/3以下になったわけで、私の用途には非常に良い結果が得られました。
SQL Server 2016にVisual Studio 2017で接続する方法

#SQL Server 2016 EnterpriseにVisual Studio 2017 Communityで接続する方法

私がいろいろ調べていった中で、まだ新しいSQL Server 2016を取り上げた記事がほぼ無いのと忘備録として記載する。

##環境
###Server
- Windows Server 2016 [Datacenter]
- SQL Server 2016 [Enterprise]
- Microsoft SQL Server Mabagement Studio(MSSMS)

###Client
- Windows 10 Pro
- Visual Studio 2017 [Community]

###事前準備
この[サイト](https://github.com/Implem/Implem.Pleasanter/wiki/SQL-Server-2016-Express%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E5%8F%8A%E3%81%B3%E8%A8%AD%E5%AE%9A)でSQL Server 2016のインストール作業を終わらせてあることとする

##FWの許可設定
- TCP:1433
- UDP:1434

##ログインアカウントの作成
MSSMSを起動すると以下のようなGUIが表示されていると思われる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152941/f263065e-1282-1cd6-c0d9-367c17e9e5b6.png)

オブジェクトエクスプローラー上で
セキュリティ　－＞　ログイン
の順番で開く
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152941/60f50181-0305-c9a1-8907-240707a555fe.png)

ログインで右クリックをし、新しいログインを選択する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152941/23f5a349-cf84-8aa6-4e26-739073c370f8.png)

以下の必要な情報を入力する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152941/a52a1619-debd-49cc-678c-baddf484aeed.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152941/b5916b73-abe2-10de-8a32-7476a3567f6f.png)

これで新しいユーザーの登録が完了した。

##Visual Studio 2017接続設定
SQL Serverオブジェクトエクスプローラーを開く
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152941/3da51f6d-b16f-69ae-0942-f539b7d9b4bd.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152941/de2ce00f-29be-97a7-b509-6fc6c99b0b97.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/152941/80288ab0-2aea-d1f2-3ee0-a7e3e8457d7b.png)

最後に接続することでSQL Serverに接続することが可能である。

##最後に
今回SQL Serverを利用するのは初めてということもあり、つまづきながら設定を行っていた。
最初はユーザーの登録をする方法につまづき、次にFWを開けるのを忘れ・・・
とまぁ初心者すぎるだろみたいなつまづきばかりをしてしまった。

しかし、これで思う存分SQL Serverで遊べる
Fabricを使ってリモートホスト上にDockerコンテナを立ち上げてその中でsshを任意のユーザーで実行する方法

タイトルが長い。
こんな長いタイトルでも伝えたいことの1/3も伝わらない。
もう少し正確にしたいことを書くと、

**Fabricを使ってリモートホスト上で立ち上げたdockerコンテナ上でagent forwardした鍵を使って任意のユーザーでsshをしたい**

だ。
まぁ一つづつ見ていきたい

#### fabricでagent forwardをする方法
```fabfile.py
env.forward_agent = True
...
```
Done

#### docker内でagent forwardしたソケットを利用する方法
このforwardした秘密鍵は通常、環境変数の```SSH_AUTH_SOCK```にソケットのパスが設定されている
つまりdockerコンテナ内からこの環境変数内で定義されているソケットを見ることができればそのまま使えそう。

```
sudo('docker run --rm -v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent -v  ~/:/var/tmp/ <image id> ssh-add -l)
```

```result
[<remo_tehost>] Executing task 'run_ssh'
[<remote_host>] sudo: docker run --rm -v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent -v  ~/:/var/tmp/ 568c07941a38 ssh-add -l
[<remote_host>] out: sudo password:
[<remote_host>] out: /usr/bin/docker-current: Error response from daemon: Invalid volume spec ":/ssh-agent": Invalid volume specification: ':/ssh-agent'.
[<remote_host>] out: See '/usr/bin/docker-current run --help'.
[<remote_host>] out: 

Fatal error: sudo() received nonzero return code 125 while executing!

Requested: docker run --rm -v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent -v  ~/:/var/tmp/ 568c07941a38 ssh-add -l
Executed: sudo -S -p 'sudo password:'  /bin/bash -l -c "docker run --rm -v \$SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent -v  ~/:/var/tmp/ 568c07941a38 ssh-add -l"

Aborting.

```

どうも環境変数であるSSH_AUTH_SOCKがうまく渡ってないようである。ちなみに```run()```で環境変数が渡っていることは確認済み。つまり```sudo()```でうまいこと環境変数が渡っていないようである

#### fabric sudo
fabricではenv.*に環境変数として色々な設定がされている。その中で```env.sudo_prefix```という変数がある。そのままで```sudo()```実行時のオプションとかが設定されている。ちなみにデフォルトは```sudo -S -p '%(sudo_prompt)s'```なのでこれではsudo実行時にAUTH_SSH_SOCK環境変数が使用できるわけがなかったので

```fabfile.py
env.sudo_prefix = "sudo -E -S -p '%(sudo_prompt)s'"
```
と-Eを追加してやれば

```
...
[<remote_host>] sudo: docker run --rm -v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent -v  ~/:/var/tmp/ 568c07941a38 ssh-add -l
[<remote_host>] out: 2017/10/05 23:11:10 [ssh-add -l]
[<remote_host>] out: 4096 ec:15:14:fd:0b:76:d5:44:b4:48:d0:78:c9:33:f2:d8 /Users/user/.ssh/id_rsa(RSA)
[<remote_host>] out: 2048 63:4c:f5:47:cd:f8:60:2d:78:98:15:8b:9b:a4:2e:5a /Users/user/.ssh/id_rsa_git (RSA)
・・・
```
おお見えとる見えとる

とりあえずこれでdockerコンテナ内のrootユーザーがsshagentにおいてある秘密鍵を使えるようになりました。

#### コンテナ内のroot以外のユーザーからsshできるようするには。
デフォルトの設定はコンテナを起動してコマンドを実行しようとするとrootユーザーで実行される。(確か)
多分、コンテナ内で別ユーザーに変更してそのユーザーを使用してsshをしたいはずだ・・・。そんなことはしたくないか。そうか。

そのような場合ざっくりコンテナ内でこんな感じでユーザーを作ってみた

```container_setup.sh
user=test
useradd $user
su -c 'ssh-add -l' $user
```

```setup_result
Could not open a connection to your authentication agent.
```

むぅ
そこで該当のsocketの権限を見ると

```
srwxr-xr-x 1 18650 users 0 Oct  5 23:41 /ssh-agent
```

あーwriteがその他のユーザーにないのがだめか?
というわけで```chmod -R 666 /ssh-agent```(*危険です。用法用量は守って注意して使ってください*)で権限を変更すると

```
4096 ec:15:14:fd:0b:76:d5:44:b4:48:d0:78:c9:33:f2:d8 /Users/user/.ssh/id_rsa.2015-12-16 (RSA)
2048 63:4c:f5:47:cd:f8:60:2d:78:98:15:8b:9b:a4:2e:5a /Users/user/.ssh/id_rsa_git (RSA)
```

見れるようになりましたとさ。

まぁもうちょっと他に方法があるかなとは思うけど覚書程度に。
Dynalistからmarkdownへの変換 Textwellアクション（8つを順番に実行）

## Dynalistからmarkdownへの変換 Textwellアクション（8つを順番に実行）
段差のレベルを自動的にmarkdownに変換します。

しかし、技術力不足のため、「8つのアクションを順番どおりに実行する」という形になってしまいました。

でも、きっと便利。

## Dynalist Export
Dynalistで、markdownにしたいdocをexportする。

- exportでは”Plain text”を選択する。

## Textwell Action
Textwell に貼り付ける。

それから、あらかじめつくっておいた以下の8つのアクションを順番に実行すれば、markdown変換ができます。

見出しはH3(### )になっていますが、#をすべて2つで書けばH2(## )になります。

***

## Action1 先頭に###をつける

```
a=T.text;
T('replace',{text:'### '+a});
```

## Action2 アウトラインレベル1 

```
s=T.text.replace(/\n/g, "\n### ");
T("replace",{text:s});
```

## Action3 アウトラインレベル4

```
s=T.text.replace(/\n###\s\s\s\s\s\s\s\s\s\s\s\s\s/g, "\n \- ");
T("replace",{text:s});
```

## Action4 アウトラインレベル3

```
s=T.text.replace(/\n###\s\s\s\s\s\s\s\s\s/g, "\n\- ");
T("replace",{text:s});
```

## Action5 アウトラインレベル2

```
s=T.text.replace(/\n###\s\s\s\s\s/g, "\n\n");
T("replace",{text:s});
```

## Action6 見出しの前を2行空ける

```
s=T.text.replace(/\n+#/g,"\n\n\n#");
T("replace",{text:s});
```

## Action7 リストの前を1行空ける

```
s=T.text.replace(/\n-/g,"\n\n-");
T("replace",{text:s});
```

## Action8 空行削除(これだけ範囲選択後にアクション)
Action6,7で行を空けることで、かえって見づらくなった部分だけを選択してから、アクションを押すと、空行が削除できる

```
s=T.whole.replace(/\n\n/g,"\n");
T("replaceWhole",{text:s});
```

アクションは以上。
自作クラスのArrayから順番を保証して重複を取り除く

まだまだSwift情弱なので新しく覚えたことはとりあえず残していってます

この辺を参考にしました

[配列から重複要素を削除する](https://qiita.com/su_k/items/157e4c6e390944237253)
[Swift 3でオブジェクトの配列の中にプロパティが同一なオブジェクトがすでに存在するか調べる](https://qiita.com/keisei_1092/items/b09c73e78ae5acfc75e5)

#使い方

```swift

//元のクラスがこんな感じだとして
//下のextensionを追加した場合の動き
class Test{
  var id = ""
  init(id:String){
    self.id = id
  }
}




//idを持ってる何かしらのクラスを２つ用意
let test1 = [Test(id:"aaa"), Test(id:"ccc"), Test(id:"bbb"), Test(id:"ddd")]
let test2 = [Test(id:"eee"), Test(id:"bbb"), Test(id:"fff")]

//混ぜる
// ** id=bbbをもつものがふたつできちゃう **
//[{id "aaa"}, {id "ccc"}, {id "bbb"}, {id "ddd"}, {id "eee"}, {id "bbb"}, {id "fff"}]
let test3 = test1 + test2

//idでユニークにする
//[{id "aaa"}, {id "ccc"}, {id "bbb"}, {id "ddd"}, {id "eee"}, {id "fff"}]
let unqTest3 = test3.unique
```

#extension
元のクラスを比較できるように拡張

```swift
extension Test: Equatable {
  static func == (lhs: Test, rhs: Test) -> Bool {
    return lhs.id == rhs.id
  }
}

```

配列をユニークできるように拡張

```swift
extension Array where Element: Equatable {
  var unique: [Element] {
    return reduce([Element]()) { $0.contains($1) ? $0 : $0 + [$1] }
  }
}
```
NginxでRubyのCGIを動かす

# はじめに

NginxはCGIを標準では実行できませんが、[FCGI Wrap](https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/)を使うとCGIをFastCGIとして実行してくれます。

大昔に作ったRubyのCGIのアプリをNginxのサーバ上で動かしたかったので、FCGI Wrapを試してみました。

注意点として、FCGI WrapはFastCGIのインターフェースを提供してくれるだけなので、CGIと同様にユーザーから要求がある度に、プロセスの生成と破棄が行われるため、パフォーマンスは悪いみたいです。

# 環境
今回試した環境です。

- Conoha VPS
- Ubuntu 16.04.3 LTS (Xenial Xerus)
- Nginx/1.10.3
- Ruby 2.3.1p112 (2016-04-26)

タイトルにはRubyのCGIと書きましたが、設定のlocationの拡張子さえ変えれば、PerlやPythonやPHPなど他の言語でも同じように設定できると思います。

# 設定手順

[FCGI Wrapの公式ページ](https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/)を参考にセットアップしました。

## FCGI Wrapのインストール

```bash
sudo apt install fcgiwrap
```

## 設定

### `/etc/nginx/fcgiwrap.conf` の作成

```bash
cp /usr/share/doc/fcgiwrap/examples/nginx.conf /etc/nginx/fcgiwrap.conf
```

今回はRubyのCGIを動かしたかったので、以下のように修正しました。

```diff
diff --git a/usr/share/doc/fcgiwrap/examples/nginx.conf b/etc/nginx/fcgiwrap.conf
index 5bdfdf1..e218726 100644
--- a/usr/share/doc/fcgiwrap/examples/nginx.conf
+++ b/etc/nginx/fcgiwrap.conf
@@ -1,13 +1,13 @@
 # Include this file on your nginx.conf to support debian cgi-bin scripts using
 # fcgiwrap
-location /cgi-bin/ {
+location ~ .rb$ {
   # Disable gzip (it makes scripts feel slower since they have to complete
   # before getting gzipped)
   gzip off;

   # Set the root to /usr/lib (inside this location this means that we are
   # giving access to the files under /usr/lib/cgi-bin)
-  root /usr/lib;
+  #root /usr/lib;

   # Fastcgi socket
   fastcgi_pass  unix:/var/run/fcgiwrap.socket;
@@ -16,5 +16,5 @@ location /cgi-bin/ {
   include /etc/nginx/fastcgi_params;

   # Adjust non standard parameters (SCRIPT_FILENAME)
-  fastcgi_param SCRIPT_FILENAME  /usr/lib$fastcgi_script_name;
+  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 }
```

### `/etc/nginx/fcgiwrap.conf` のインクルード

Nginxの設定ファイル構成によりますが、普通は `/etc/nginx/sites-available/default` の server ブロック内で読み込んでおけばいいと思います。

```diff
server {
+    # fast cgi support
+    include /etc/nginx/fcgiwrap.conf;
}
```

## RubyのCGIスクリプト

まずは単純なスクリプトでテストしました。

適当な場所にパーミッションを正しく指定して配置してください。

```ruby
#!/usr/bin/ruby

puts "Content-Type: text/html\n\n"
puts "<html>"
puts "<head><title>Test</title></head>"
puts "<body>"
puts "<h1>Hello CGI World!</h1>"
puts "</body>"
puts "</html>"
```

# トラブルシューティング

躓いたポイントを紹介します。

## SCRIPT_FILENAMEの設定

パーミッションは正しいのに403エラーとなってしまいました。

エラーログ `/var/log/nginx/error.log` を見ると以下のようになっていました。

```text
2017/10/05 11:49:03 [error] 9728#9728: *45 FastCGI sent in stderr: “Cannot get script name, are DOCUMENT_ROOT and SCRIPT_NAME (or SCRIPT_FILENAME) set and is the script executable?” while reading response header from upstream, client: xxx.xxx.xxx.xxx, server: _, request: “GET /app/test.rb HTTP/1.1", upstream: “fastcgi://unix:/var/run/fcgiwrap.socket:“, host: “xxx.xxx.xxx.xxx”
```

これは `/etc/nginx/fcgiwrap.conf` の `SCRIPT_FILENAME` を修正したら動きました。

```diff
-fastcgi_param SCRIPT_FILENAME  /usr/lib$fastcgi_script_name;
+fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
```

# 参考記事
- [NginxでCGIを動かそうと頑張った話](https://qiita.com/hmikisato/items/c793ced0ba2695a89de6)
scikit-learnのLabelEncoderの使い方

## はじめに

分類器にかける前に文字データを離散の数値に変換するときに使われる。細かい処理などはできないが、とりあいず離散数値にして分類器にかけたいときによく使います。

## 使い方

```py
>>> le = preprocessing.LabelEncoder()
>>> le.fit(["paris", "paris", "tokyo", "amsterdam"])
LabelEncoder()
>>> list(le.classes_)
['amsterdam', 'paris', 'tokyo']
>>> le.transform(["tokyo", "tokyo", "paris"]) 
array([2, 2, 1]...)
>>> list(le.inverse_transform([2, 2, 1]))
['tokyo', 'tokyo', 'paris']
```

`le.fit()`の部分で変換したいデータを選択します。そして`le.transform()`で数値へ変換します。

実際にタイタニックのデータを変換してみたいと思います。タイタニックのデータはseabornの中にあるのでそれを使います。

```py
import seaborn as sns
import pandas as pd
from sklearn import preprocessing

titanic = sns.load_dataset("titanic")

for column in ['sex','class']:
#     print(titanic[column].shape)
    le = preprocessing.LabelEncoder()
    le.fit(titanic[column])
    titanic[column] = le.transform(titanic[column])

titanic
```

今回は`sex`,`class`を変換してみました。便利なので皆さんもぜひ使ってみてください。

## 参照

http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html
Gitを少しずつ覚える

この記事は今から30分の時間制限で書き，時間が終わったら公開します．
後から見直して，修正することになると思います．

この記事ではGitを知らないけど，Gitがどうなっているかを知りたい人が，使いながら理解する方法を書きます．

## Gitの簡単な説明

Gitはバージョン管理ソフトです．
あるフォルダを「バージョン管理下」に指定すると，そこにあるファイルの変更を追跡・記録してくれるようなソフトになります．
他のバージョン管理ソフトとして，Subversionとかがあります．

## Gitのインストール

Windowsだったら「Git for Windows」をダウンロード・インストールします．
[公式ページ](https://git-scm.com)からダウンロードできます[^1]．
インストーラを起動するとインストールできます．インストールの設定ではautoCRLFを無効にした方がいいでしょう．

## Gitクライアントについて

Gitの使い方としてはターミナルからコマンドを打ち込んで使うのをおすすめします．GitのGUIクライアントもありますが，Gitがどうなっているかを理解するためには，CUIの方がいいと思います．

## バージョン管理するデータを決める

Gitを使って覚えるためには，あなたの普段使っているデータをバージョン管理してみるのがいいです．毎日開くフォルダを，1つ選んでください．容量は，数千ファイル,数百MBぐらいだったらあまり重くならないと思います[^2]．
ソースコードなど，テキストファイル中心だといいのですが，エクセル等，バイナリファイルでも大丈夫です．
大事なのは普段使うデータをGitで管理しようとすることです．

そのフォルダを開いて，右クリックして「Git Bash Here」を押してください．
次に，`git init`を実行してください．これによってリポジトリが作成され，カレントディレクトリが作業ツリーになります．

## 最初に覚えるコマンド

現在のフォルダの状態を記録（コミット）するコマンドを最初に覚えましょう．次のコマンドです．

`git add --all`
`git commit -a -m [メッセージ]`

メッセージが思いつかなかったら1005みたいな日付でもいいです．これを最低でも1日に1回はやってみましょう．

## 次に覚えるコマンド

最後のコミットと現在のフォルダの状態の差分を確認してみましょう．次のコマンドです．
`git diff`

また，`git status`で「working tree clean」と出れば「最後のコミットと現在のフォルダの状態が同じ」です．これは「仕事してない」という意味ではなく，「準備完了」ぐらいの意味です．

## 次に覚えるコマンド

次は履歴を表示するコマンドです．

`git log`と入力すると，コミットの一覧が表示されます．コミットの日付，メッセージ等が表示されます．
各コミットの変更したファイルを表示するには`git log --name-only`とします．
各コミットの差分を表示するには`git log -p`とします．

## 次に覚えるコマンド

（必要がなかったら飛ばしてください）過去の状態のファイルを取得してみましょう．

`git checkout [ハッシュ] -- ファイル名`

で，特定のコミットの特定のファイルを復元できます．「working tree clean」の状態からはじめるとよいと思います．

## 次に覚えるコマンド

次はブランチを使ってみましょう．ブランチとは，作業ディレクトリの複数の状態を切り替える機能です．新しいブランチを作るには次のコマンドを実行します．

`git checkout -b [ブランチ名]`

Git Bashの場合はプロンプトに現在いるブランチ名が表示されます．
ブランチの切り替え（作業ツリーをブランチの状態にする）は「working tree clean」から次のコマンドを実行します．
`git checkout [ブランチ名]`

[^1]: scmはsource code managementの略だと思います
[^2]: マシンスペックと使う人の時間感覚による
pythonをはじめる。自分の意思表示みたいなもの。

しばらくROM専をやっていましたが、これからは自分で発信していこうと思います。
私は、社会人になってから、Java、Javascript、sqlを使用するプロジェクトばかり担当させられていました。
ここにきて、今まで経験していない言語をなんかやりたいなーと思い、今はやっているpythonを勉強しようと決心しました。
何を作るのか、決まっていませんが機械学習を利用したアプリを作れたらなと思っています。
たとえば、株価予想とか。。。
Raspberry piを使用した何かか。。

とくに決まっていませんが、まずはpythonを使用できるようになるまで、備忘録を書いていこうと思います。

##**まず、pythonとは？**
世界中で使用されているスクリプト言語のひとつ。
スクリプト言語って何？と思う人がいるかもしれないが、簡単にかけて実行できるプログラムっていうイメージでよいかな。
詳しく言うなら、事前にコンパイルが必要でない言語。javaScriptとかphpとかもスクリプト言語にあたる。

##**特徴**
1. シンプルで読みやすいコードが書ける
同じような機能をもつプログラムは同じようなコードになると言われている。
これはホントにありがたいことだと思う。
基本的にプログラムを書くときには、より単純によりきれいに書くべきなので、それが自然とできるってこと。
そのため、初心者にも結構進められたりするみたい。

1. 数学に関連する分野が得意
数値処理が高速で化学計算用、統計用、機械学習等のライブラリが豊富なので数学処理の分野に向いている

1. インデント
ブロック構造をインデントで表現する。Javaをやっていた私にとっては結構衝撃的です。
ただ、インデントが強制されるので可読性が上がり、メリットはかなりある。
例）

```java:Java
if (true) {
    ～ // ここにtrueのときの処理を記述
}
```

```py:Python
if True :
    ～ # ここにtrueのときの処理を記述
```

今日はここまでで。
次は、Javaとpythonを比べながら、文法を勉強しようと思います。
フレッツ網内でDDNSを使ってIPv6通信する


# はじめに

自宅と実家間をVPNでつないでリモートサポート・写真データの共有等している方は多いと思いますが、双方ともNTTのフレッツ網内（光ネクスト）であればISP契約をせずともIPv6を使った折り返し通信が出来ます。

※インターネットを経由する通信には従来通りISP契約が必要です。

NTT東日本管内ではソフトイーサ株式会社が [OPEN IPv6 ダイナミック DNS for フレッツ・光ネクスト](https://i.open.ad.jp/) を提供しており、ホスト名を使用したDDNSアクセスが出来るようになるので便利です。企業の拠点間通信にも応用できそうです。

![OPEN IPv6 ダイナミック DNS for フレッツ・光ネクスト](https://i.open.ad.jp/images/top.jpg)

# 注意事項

- この記事はフレッツ光ネクスト、ヤマハ製ルーターNVR700W/NVR500の組合せで確認をしています
- [OPEN IPv6 ダイナミック DNS for フレッツ・光ネクスト](https://i.open.ad.jp/) は現在ベータ版です。今後もサービスが継続される・無償で提供される保証はありません
- NTT東日本向けのサービスとなっているようですので、西日本で使えるかは不明です
- 拠点間通信に耐えうるだけの信頼性があるかは、各自の用途に応じた検証で判断してください

# ホストの登録

[OPEN IPv6 ダイナミック DNS for フレッツ・光ネクスト](https://i.open.ad.jp/) にアクセスし、ページ下部の「DDNS ホストの新規作成」フォームからIPv6アドレスとホスト名を登録するだけです。ユーザー登録等は現状、必要ありません。

注意が必要なのが、IPv6アドレス欄の初期値はPCからアクセスしている場合そのPCのものであってルーターのものではない、という点です。ルーターのIPv6アドレスを確認して入力する必要があります。

YAMAHA製ルーターであれば

```bash
show ipv6 address
```

でIPv6アドレスが確認できるので、外部向けのアドレス（PP/ONU 等）を調べてください。

# IPv6アドレスの更新

ホストを登録するとアドレス更新用の ホスト名/アドレス/URL が発行されます。
ここにアクセスすることで対象ホストのIPv6アドレスを更新することが出来ます。

スケジュール機能のあるルーターであれば下記のように自動更新を設定できます。市販のブロードバンドルーターなどスケジュール機能が無い・DDNSを任意に指定できないルーターだと自動更新は難しいと思います。

1. 簡易的な更新

    ping/httpで専用アドレス/URLにアクセスします。
    　
    コマンド実行を、アドレス変動の頻度に合わせてスケジュール登録します。以下、YAMAHA製ルーターからpingを使ったバッチアクセスの例です。
    
    ```bash
    schedule at XXX */* *:05:00 * lua -e "rt.command(\"ping6 -c 4 update-?????.i.open.ad.jp\")"
    ```
    
    XXXにはスケジュールIDを（既にスケジュールの登録がある場合は上書きに注意）、`update-?????.i.open.ad.jp` には発行された専用アドレスを指定してください。 `-c` オプションでping実行回数を指定しないとうまく更新されません。
    　

2. スクリプトを使って更新

    IPv6アドレスの変更をトリガーとして処理実行するスクリプトを作成し、常駐または定期実行させます。
    YAMAHA製ルーターであれば [別記事](https://qiita.com/taka-tactical/items/214eca769f972620d0e7) のDDNS更新用luaスクリプトを改造して、アドレス変動を検知したタイミングでpingを実行するのが簡単です。

# 参考情報

- [OPEN IPv6 ダイナミック DNS for フレッツ・光ネクスト サービス概要・使い方](https://i.open.ad.jp/howto/)
- [YAMAHAルーター DDNS更新用luaスクリプトを作ってみた](https://qiita.com/taka-tactical/items/214eca769f972620d0e7)
【MySQL】プロシージャの内容を確認する方法【information_schema.ROUTINES 】

プロシージャの更新日付を見るときによく使うselect文なので、メモっておく:pencil2:
業務で、一時やたらとプロシージャがデグレることがあり、しょっちゅう使ってた・・・。

# プロシージャの内容を確認する
もっといろんな情報が（文字コードとかプロシージャの内容とか）見れるけど、たくさんありすぎるので、個人的に普段はこれくらいまでカラムを絞ることが多いです。

```SQL
select
  ROUTINE_NAME -- プロシージャ名
  , ROUTINE_SCHEMA -- スキーマ名
  , LAST_ALTERED -- 最終更新日時
from information_schema.ROUTINES
where
  ROUTINE_SCHEMA = 'testSchema'       -- スキーマ名を指定する
  and ROUTINE_TYPE = 'PROCEDURE'   -- プロシージャだけを検索する
  and ROUTINE_NAME like 'p_%'      -- プロシージャの名称部分一致
order by ROUTINE_NAME
;
```

# information_schema.ROUTINESとは
プロシージャやファンクションの一覧を保持しているテーブル。
普通のselect文なので、whereもorder byなどが使えるのが便利:pig:

プロシージャの一覧を見るには

```SQL
SHOW FUNCTION STATUS;
```
も十分使えるけど、やっぱりwhere句が使える方が捗る:bangbang:
運用で使うMySQLコマンド【メモ】

# サーバ運用でよく使うMySQLコマンド集

## ログイン
```shell-session:shell
$ mysql -u${USER} -p ${DATABASE} -h${HOST}
```

## テーブルのテキストデータダンプ
```shell-session:mysql-command-line
mysql > SELECT * INTO OUTFILE '/tmp/${TABLE_NAME}.txt' FROM ${TABLE_NAME};
```

## テーブルのテキストデータ取り込み
```shell-session:mysql-command-line
mysql > LOAD DATA LOCAL INFILE '/tmp/${TABLE_NAME}' REPLACE INTO TABLE ${TABLE_NAME};
```

## データベースバックアップ
```shell-session:shell
$ mysqldump -uroot -p ${DATABASE} --skip-lock-tables > /tmp/${DATABASE}.sql
```

## データベースリストア
```shell-session:shell
$ mysql -uroot -p ${DATABASE} < /tmp/${DATABASE}.sql
```

## テーブルカラム追加
```shell-session:mysql-command-line
mysql > ALTER TABLE ${TABLE_NAME} ADD ${COLUMN} column_definition AFTER ${COLUMN_NAME};
```
column_definition: varchar(32)とか

## テーブルにINDEX追加
```shell-session:mysql-command-line
mysql > ALTER TABLE ${TABLE_NAME} ADD INDEX ${INDEX_NAME}(${COLUMN_NAME});
```

## テーブルのリネーム
```shell-session:mysql-command-line
mysql > RENAME TABLE ${TABLE_NAME} TO ${TABLE_NAME}_tmp, ${TABLE_NAME}_shadow TO ${TABLE_NAME}, ${TABLE_NAME}_tmp TO ${TABLE_NAME}_shadow;
```

## プロセスリスト
```shell-session:mysql-command-line
mysql > SHOW PROCESSLIST;
```

## プロセスkill
```shell-session:mysql-command-line
mysql > KILL ${PROCESS_ID};
```

## レプリケーション設定
```shell-session:mysql-command-line
mysql > CHANGE MASTER TO
MASTER_HOST='${HOST}',
MASTER_PORT=${PORT},
MASTER_USER='${USER}',
MASTER_PASSWORD='${PASSWORD}',
MASTER_LOG_FILE='${BINLOG}',
MASTER_LOG_POS=${BINLOG_POSITION};
```

## レプリケーションのステータス確認
```shell-session:mysql-command-line
mysql > SHOW SLAVE STATUS\G
```

## レプリケーションの停止
```shell-session:mysql-command-line
mysql > STOP SLAVE;
```

## レプリケーションの開始
```shell-session:mysql-command-line
mysql > START SLAVE;
```

## レプリケーションのポジションスキップ
```shell-session:mysql-command-line
mysql > SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
```

## データベースロック
```shell-session:mysql-command-line
mysql > FLUSH TABLES WITH READ LOCK;
```
※quitするとロックが外れます

## ロック解除
```shell-session:mysql-command-line
mysql > UNLOCK TABLES;
```

# 以下は稀に使う（できれば使いたくないｗ）コマンド

## binlog展開
```shell-session:shell
$ mysqlbinlog --no-defaults ${BINLOG_FILE} > /tmp/${BINLOG_FILE}.sql
```

## binlog削除
```shell-session:mysql-command-line
mysql > SHOW MASTER LOGS;
mysql > PURGE MASTER LOGS TO '${BINLOG}';
```
awsでUbuntu, windows 環境構築時のメモ

リンク集ですが・・。

# ipv6設定
https://ameblo.jp/hackerbobchan/entry-12243285385.html

# ubuntuを立ち上げ、VNCでデスクトップに繋ぐ
http://juncollin.hatenablog.com/entry/2017/02/19/150423
http://dev.classmethod.jp/cloud/aws/vpc-ipv6/

# windows構築時エラー
## XINPUT1_3.dll がない
http://chimolog.co/2016/08/treeofsavior-xinput1_3.html
Twitterのsearch/tweetsで取得したツイートからメンションやリツイートを除外する方法

レスポンスJSONの中で、retweeted_statusプロパティのあるレコードを除外していけばよい。

| プロパティ名            | 型       | 詳細                                           |
|:-----------------------:|:--------:|:----------------------------------------------:|
| in_reply_to_screen_name | ?string  | メンションする先のスクリーンネーム             |
| in_reply_to_user_id     | ?int     | メンションする先のユーザID                     |
| in_reply_to_user_id_str | ?int     | メンションする先のユーザID                     |
| is_quote_status         | bool     | 引用リツイートの場合にtrue                     |
| retweeted_status        | (object) | ツイートが公式リツイートの場合、リツイート元Tweet Object |

# 参考
http://blog.takuros.net/entry/20100505/1273061790
https://syncer.jp/Web/API/Twitter/REST_API/Object/Tweet/
関数型言語の入門勉強会メモ

関数型プログラミングとはなんぞや？ という勉強会で走り書きしたメモを起こしてみました。
正直、情報の精度としては怪しいの。
間違いがあったらご指摘ください。（他力本願）

# 関数型プログラミングとは
プログラミングパラダイムの1つ。
（パラダイム：考え方、捉え方）

パーツがコンパクトになり、再利用性が高い。

##用語
###副作用
関数呼び出し前後で「状態」を書き換えること。
同じ引数でも必ず同じ結果にならない。

###純粋関数
副作用のない関数のこと。
同じ引数なら、いつでも同じ結果を返す。

##特徴
関数プログラミングには~~if文、~~for文などがなく、関数を定義する。
（if式あります。詳細はコメント参照）

一般的なfor文の例
```total = 0;
for (i = 0; i <= 10; i++){
  total = total + i;
}```

```Haskell:sample.hs
total 0 = 0
total n = n + total (n - 1)

main = do
    print $ total 10
```

基底部と再帰部を書いたらやってくれる。
関数はすべて部分適用が可能。詳しくは「カリー化」。

#まとめ
関数をオブジェクトとして考える必要はなく、オブジェクト指向は他の言語でやればいい。
あくまでもパラダイムの一つとして付き合うと他の言語でも広がりを与えてくれる。
純粋のものと副作用のものは分けるべきで、副作用を触る場合はそれ専用のレイヤーを用意する。
設計するときは関数言語の本質はなんだっけと立ち直ってやっていくと良い。
最近jsで地味につまずいたところをメモしました

#前置き
タイトル通り。ここ最近で地味につまずいたところをメモ（しただけ）

#mouseoverとmouseout
以下のようなhtmlがあって、

```html:index.html
<div>
<p>Javascript</p>
</div>
```

div要素にmouseover、mouseoutイベント登録すると・・・

```JavaScript:test.js
const div = document.querySelector('div');
const p = document.querySelector('p');

div.addEventListener('mouseover', e => {
  div.style.transform = 'scale(1.5)';
});

div.addEventListener('mouseout', e => {
  div.style.transform = 'scale(1.0)';
});
```

divだけでなく、子要素であるpでもイベントが発火してしまう。。
stopPropagation()で止められるかと思ったが、これは子→親を止めるもので、
親→子は止めてくれない・・・

###解決策
mouseover　→　mouseenter
mouseout　→　mouseleave

```JavaScript:test.js
const div = document.querySelector('div');
const p = document.querySelector('p');

div.addEventListener('mouseenter', e => {
  div.style.transform = 'scale(1.5)';
});

div.addEventListener('mouseleave', e => {
  div.style.transform = 'scale(1.0)';
});
```

:ok_woman_tone1:

#HTMLCollectionは配列じゃない！
そもそもHTMLCollectionとは？

```JavaScript:test.js
document.getElementsByClassName('test');　//HTMLCollection
```

上記のように取得できるDOM要素ですね。
一見したところ、配列っぽいのですが、forEachとかfilterとか配列の便利メソッドが使用できません。。

ところがどっこい！下記だと配列のメソッドが使える！

```JavaScript:test.js
document.querySelectorAll('.test'); //NodeList
```

これ！最近気づいて感動しました！！！
便利すぎて今まで私はどうやってDOM操作をしていたのか忘れました・・・
と思っていたのですが、調べてみるとchrome以外ではエラーになってしまうようです。。（知らなかった・・・ショック・・・）
ということで、配列のメソッド使いたい場合は、以下のような感じで配列に変換しましょう～～～

###解決策
####その１
```JavaScript:test.js
[].slice.call(document.querySelectorAll('.test')).forEach(element => {
  console.log(element);
});
```

####その２
```JavaScript:test.js
Array.prototype.slice.call(document.querySelectorAll('.test')).forEach(element => {
    console.log(element);
});
```

:ok_woman_tone1:


##まとめ（るまでもない）
もっと書けるかと思ったけど、案外書けることなかった・・・:angel_tone2:
勉強します・・・
Google Calendarの予定をSlackのステータスと同期する

# 概要
[Sync Google Calendar to Slack](https://github.com/okamos/sync-google-calendar-to-slack)
ここの画像を見てもらえばわかる通り、Google Calendarに入れた予定に応じてSlackのステータスが変わります

## 設定
READMEに書いてある通りなんですが、ステータスとして表示させたい予定・テキスト、アイコンは人によって全然違うと思います
Github上でForkして`dict.json`を編集してお使いくださいませ

GithubへPushするとCircleCIが勝手にデプロイするように設定することも可能で、ローカルでいちいちビルドしたりする必要がありません

## あとがき
Google Apps Scriptはサーバーいらずで、かなりいろんなことができるので良さそうだなぁって思いました
スプレッドシートと絡めて何かしたいとかって人はこのプロジェクトをブループリント的に使える部分もあるかと思うのでもしよければ見て見てください。特に難しいことは書いていないので（つもり）
Unity Android FullScreen


Android側のソースを修正：

```java
	public void onWindowFocusChanged(boolean hasFocus) {
		super.onWindowFocusChanged(hasFocus);
		............
		if (hasFocus)
			hide();
	}

	private void hide() {
		if (Build.VERSION.SDK_INT >= 19)
			getWindow().getDecorView()
					.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
							| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 
                                                        |View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
							| View.SYSTEM_UI_FLAG_LOW_PROFILE
                                                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
							| View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
							| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
	}
```
PyQt5:ウィンドウを表示してなくてもキーに反応させる

「関連する専門用語を知らなすぎてググれない」状態に苦労させられた．

#やったこと
「グローバルホットキー」により，「非アクティブなウィンドウ」で「キーボードフック」させる．

要するに「Ctrl + Cみたいなキー入力」により，「最小化とかタスクトレイに格納とかしてるウィンドウ」でも「キー入力に反応」させる・・・てな感じ．

実際に，Ctrl+Shift+Altでタスクトレイに格納or再表示を繰り返すアプリを作った．
![global_hotkey.gif](https://qiita-image-store.s3.amazonaws.com/0/201962/3f2e60d0-e424-3fe5-a998-361af16534db.gif)
ブラウザをアクティブにしたまま，アプリを隠したり再表示したりできる．
おまけで，タスクトレイのアイコンをクリックしても同じ挙動をする．

- アプリが最前面にあるが，わざとそうなるプログラムにした
- 普通だと，トレイに格納→再表示しても，アプリは最前面に来ない
- つまり，トレイから呼び出すと即アクティブ・・・ができない  
（上のgifでも，再表示されたアプリは非アクティブのまま）

#環境
- Windows10
- Python3.6 + PyQt5

決まり手：keyboard（ライブラリ名）
>[boppreh/keyboard](https://github.com/boppreh/keyboard)
##keyboard
Take full control of your keyboard with this small Python library. Hook global events, register hotkeys, simulate key presses and much more.

グローバルホットキーをフックできたのは全部これのおかげ．
PyQtはグローバルキーボードフックをサポートしていないため，諦めるか外部ライブラリに頼るしか手はない．

※最有力に[PyGlobalShortcut](https://pypi.python.org/pypi/PyGlobalShortcut/0.2.3)があったものの，WindowsでもLinuxでもインストールできなかったため採用見送り．

#ソースコード

```python3:show_or_hide.py
# -*- coding: utf-8 -*-
import sys
import keyboard
from PyQt5.QtWidgets import QWidget, QApplication, QSystemTrayIcon
from PyQt5.QtGui import QIcon
from PyQt5.Qt import Qt


class Window(QWidget):
	tray = QSystemTrayIcon()
	
	def __init__(self):
		super().__init__()
		iconPath = 'sample_icon.png'
		
		self.setWindowFlags(Qt.WindowStaysOnTopHint)  # 常に最前面に表示
		self.setWindowTitle('PyQt5 Window Show or Hide')  # ウィンドウタイトル
		self.setWindowIcon(QIcon(iconPath))  # ウィンドウアイコン
		
		self.tray.setIcon(QIcon(iconPath))  # トレイアイコン
		self.tray.activated.connect(self.ShowOrHide)  # トレイクリック時
		self.tray.show()
		
		# グローバルホットキー：Ctrl+Shift+Altを押した場合
		keyboard.add_hotkey('ctrl+shift+alt', lambda: self.ShowOrHide())
	
	def ShowOrHide(self):
		# ウィンドウの表示or非表示
		if self.isHidden():
			self.show()
		else:
			self.hide()


if __name__ == '__main__':
	app = QApplication(sys.argv)
	execute = Window()
	execute.show()
	sys.exit(app.exec_())
```
SRE本まとめ（10章 時系列データからの実践的なアラート）

自分の理解を深めるためにまとめてみました。[9章](https://qiita.com/bassbone/items/9372ddd967c940c3fb3b)の続きです。

## 10章 時系列データからの実践的なアラート

### Borgmon
BorgをモニタリングするためのBorgmonが構築された。共通のフォーマットでデータを収集し、グラフの描画やアラート通知に利用されている。Borgmonがモニタリングするシステムは動的に変わるものなので、サービスディスカバリを利用し自動更新されている。収集しているデータは一旦インメモリデータベースに保存し、定期的にディスクに書き込みしている。時系列データと呼ばれる時間順のリストとして保存され、ラベル群が名前として与えられている。構造は時系列アリーナと呼ばれる固定サイズのメモリブロックになり、アリーナが一杯になると時系列の古いものから削除される。（最新と最古のエントリに時間差はホライズンと呼ばれる。）時系列データは数値とタイムスタンプの並びとして保存され、ベクタと呼ばれている。時系列データの名前はラベルセットと呼ばれる。Borgmonルールと呼ばれるプログラムコードは時系列データから別の時系列データを算出するシンプルな台数式で構成される。Borgmonはホワイトボックスモニタリングシステムであるが、ブラックボックスモニタリングも必要である。GoogleではProberというツールを使い、ターゲットに対するプロトコルチェックを行い、成否をレポートする。

### まとめ
メンテナンスコストがサービスのサイズに比例しないようにすることがモニタリングをメンテナンス可能にするための鍵である。SREは自分たちのあらゆる作業をグローバルな規模にまでスケールさせるために働くので、このテーマはSREのあらゆる作業について繰り返される。

（[11章](https://qiita.com/bassbone/items/b603435e37c72641062f)に続く）
ionicでnedb使ってみた


## what is nedb

JavaScirptで書かれたファイルデータベース
JSONテキストがそのままテキストファイルとして保存されるという剛毅なDB
https://github.com/louischatriot/nedb


## ionicで使うって正気ですか

予めionicプロジェクト展開したディレクトリで、 `npm` で入れる

```sh
$ npm install nedb --save
$ ionic serve
```

以下コード
ionicでProviderとして使う想定で書いてみた
importはめんどくさいんで `as` にしたけどd.tsあるはずなのでちゃんと名前使えるかも


```typescript
import { Injectable } from "@angular/core";
import * as Datastore from "nedb";

@Injectable()
export class NedbProviderSample {
  filename: string = "data/database.db";
  dataStore: Datastore;
  constructor() {
    console.log("Hello ChatLogProvider Provider");
    this.dataStore = new Datastore({ filename: this.filename, autoload: true });
  }

  /**
   * レコードの新規作成
   * @param document Object 書き込むドキュメントをJSONオブジェクトで指定
   * @return targetKey:string 発行されたレコードキーをstringで返す
   */
  public create(document: object): Promise<object> {
    return new Promise((resolve, reject) => {
      this.dataStore.insert(document, (error, result) => {
        if (error) {
          reject(error);
        } else {
          resolve(result);
        }
      });
    });
  }

  /**
   * レコードの削除
   * @param targetKey 削除対象のレコードキー
   * @return bookean 削除の成否をbooleanで
   */
  public delete(targetKey: string): Promise<boolean> {
    return new Promise((resolve, reject) => {
      this.dataStore.remove({ _id: targetKey }, {}, (error, result) => {
        if (error) {
          reject(error);
        } else {
          resolve(result);
        }
      });
    });
  }

  /**
   * レコードの検索
   * @param param0 {
   *  targetFieldName : 検索対象のフィールド名
   *  queryString: 検索に使用されるクエリ文字列
   * }
   * @return Array<object> 検索結果をドキュメントObjectのArrayで
   */
  public findRecords({ targetFieldName: targetFieldName, queryString: queryString }): Promise<Array<object>> {
    return new Promise((resolve, reject) => {
      let queryObject;
      if (queryObject) {
        queryObject = { targetFieldName: queryString };
      } else {
       // find()に渡す検索オブジェクトを空っぽにすると、全件返ってくる
        queryObject = {};
      }
      this.dataStore.find(queryObject, (error, result) => {
        if (error) {
          reject(error);
        } else {
          resolve(result);
        }
      });
    });
  }
}
```

こんな感じで読み書き検索できる
実際に使うとなると都度 findRecord() して全件取り直さないといけないのですごい遅いと思う

## 実用性？

さあ....？
mongodbみたいなAPI経由でのnoSQL使いたいんだけどサーバプロセス立てるのめんどくさい、みたいな時に使う程度だと思う
堅牢性とか速度とか言い出してはいけない

## todo
**ファイルが実際にはどこに書き込まれているのか調べる**
~~セキュリティホール作り放題の可能性あり~~
[メモ]Laravel5.4でブログシステムを作る04(ルート、コントローラとデータベースの設定)



##ルートとコントローラの雛形
今回から実際にブログシステムを開発する。
第一回の文章モジュールの要件定義に沿ってルートをコントローラの雛形を作る。

まずは、コントローラをLaravelのコマンドラインで生成する。
文章モジュールに関する部分をPostとし、文章を扱っているコントローラをPostControllerにしよう。

```
$ php artisan make:controller PostController
```

コントローラを使用するには、Controllerクラスを継承することが必要

```php
class PostController extends Controller
{
    // 文章リストを表示
    public function index(){}
    // 文章の詳細を表示
    public function show(){}
    //文章を作成
    public function create(){}
    //作った文章を保存、投稿
    public function store(){}
    //作った文章を編集
    public function edit(){}
    //文章を更新し、投稿
    public function update(){}
    //文章を削除
    public function delete(){}
}
```
続いて、routes/web.phpのルートを編集する。
ご注意：{}が含まれるものを後ろに置く。


```php
// 文章リストを表示
Route::get('/posts','PostController@index');


//文章を作成 1.作成画面 
Route::get('/posts/create','PostController@create');
//文章を作成 2. 投稿
Route::post('/posts','PostController@store')

//文章を削除
Route::get('/posts/delete','PostController@delete');
//文章の詳細を表示
Route::get('/posts/{post}','PostController@show');
//作った文章を編集 1.画面 
Route::get('/posts/{post}/edit','PostController@edit');
//文章を作成 2. 更新を投稿
Route::put('/posts/{post}','PostController@update');
```

#データベースの基本情報を設定
ルートディレクトリの直下で.envファイルを探す。使っているデータベースはmysqlで以下のように修正する：
各項目に実際のデータベースの設定を入れる。

```DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=jianshu
DB_USERNAME=xxxxxx
DB_PASSWORD=xxxxxx
```

##マイグレーションを使ってテーブルを生成
###マイグレーションについて:

マイグレーションとはチームでアプリケーションデータベースのスキーマを更新し共有できるようなもので、
今回はまずマイグレーションを生成する。

```
$ php artisan migrate:install
```
実際のデータベースを調べたら、jianshuというデータベースの中にmigrationsのテーブルが生成したら、.envの設定が正しいと証明。



文章のテーブルの構成を考える：

|description       | Field |    TYPE            |    LENGTH           |
|:-----------------|------------------:|:------------------:|:------------------:|
| 記事文章を記録するid |id  |        INT      |      10        |
|記事文章のタイトル|            title  |      VARCHAR     |  100      |
|   記事文章の内容、本文|           content |        TEXT        |
| 記事文章の作者を記録するid  |     user_id |        INT          |11
| 文章が投稿された日時   |             create_at |      TIMESTAMP      |
| 文章が更新された日時  |           updated_at |     TIMESTAMP      |


表名をLaravelが推奨された通り、英文名＋複数型とする。
モデルとテーブルの対応関係を考えた上で、モデル名はpostだとしたら、テーブル名をpostsとする。

次に、マイグレーションを使ってテーブルを生成する：

```$ php artisan make:migration create_posts_table
```

database/migrationsディレクトリの中に生成日時＋create_posts_table.phpが生成される。
このファイルに入って、CreatePostsTableのクラスに以下のようにメソッドを追加する。

```php
  public function up()
    {
        //テーブルを作成
        Schema::create('posts',function(Blueprint $table){
            //idを自動的に増加
            $table->increments('id');
            $table->string('title',100)->default('');
            $table->text('content');
            $table->integer('user_id')->default(0);
            $table->timestamps();
        });


    }
    public function down()
    {
        //ロールバック
        Schema::dropIfExists('posts');
    }

```

テーブルを設定し終わったら、以下のように執行し、postsテーブルが生成される。

```
＄　php artisan migrate
```
ロールバックする

```
$　php artisan migrate:rollback    
```