OmniAICreator/Qiita-1.07M huggingface dataset:
発掘:２ＧＢ以上のディスクの容量、空き容量を得る　　（Win95 OSR2以降、98,NT）

# 発掘の趣旨
##この記事の元のURL
http://ww3.enjoy.ne.jp:80/~kazu.ohara/SampleCode.html
##存在していた時期
2002年1月24日から2005年9月24日まで存在はしていたようだ。
##状況
　ホームページの構造から、本来VB5.0のサンプルを掲載する予定だったが、途中で断念し、GetDiskFreeSpaceExだけ存在していたようだ。
##価値
この記事はGetDiskFreeSpaceExをVB5にしており、VBAに使える。しかしこのサンプルは実はここ以外見つからない。このため発掘する価値があると判断した。

#Visual Basic サンプルコード集　VB5.0(SP3)
 以降のサンプルコードは、すべて、Visual Basic 5.0(SP3)で確認しています。（現在これしか、使っていないもので）　　※すべて・・といってもまだ１つしかありませんが(^^;

##２ＧＢ以上のディスクの容量、空き容量を得る　　（Win95 OSR2以降,98,NT）
###２ＧＢ以上のディスクの容量、空き容量を得るコード（Win95 OSR2以降、98,NT）

ドライブなどの容量を得るのに通常は、ＡＰＩ関数のGetDiskFreeSpace関数を使用しますが、2GB以上の大容量では、正しくない値が返されます。
そこで、２GB以上の容量を得るには、Win95 OSR2以降のOSを使用しているなら、GetDiskFreeSpaceEx関数を使用します。

####宣言文

```vb

Public Declare Function GetDiskFreeSpaceEx Lib "kernel32" Alias _ "GetDiskFreeSpaceExA" (ByVal _
lpDirectoryName As String, _
lpFreeBytesAvailableToCaller As Double, _
lpTotalNumberOfBytes As Double, _
lpTotalNumberOfFreeBytes As Double) As Long
```

####引数
lpDirectoryName 　　　　ディレクトリ名（０の時、カレントディレクトリ）
lpFreebytesAvailableToCaller　　（戻り値）ユーザーが使用出来るディスクの空き容量（バイト数）
lpTotalNumberOfBytes　　　　　 （戻り値）指定のディスクの全バイト数
lpTotalNumberOfFreeBytes　　 （戻り値）同、空き容量（バイト数）

####戻り値
正常終了の時　　０以外
エラーの時　　　　０

####備考
lpDirectoryName で、ディレクトリ名を指名するとき、最後尾に"\"をつける。（例：　C:\)
lpFreebytesAvailableToCaller は、複数のユーザーがコンピュータを使用する場合、ユーザー毎にディスクを割り当てるので、使用可能容量とは異なる戻り値が入るようだ。（わたしは、１人で使っているので、lpTotalNumberOfFreeBytes と同じ値になるので、複数使用の場合の戻り値の実際が分かりませんが・・）
戻り値の型がDouble（倍精度浮動小数点型）である点に注意。

####使用例

```vb

Dim Re As Long
Dim lpFreeBytesAvailableToCaller As Double
Dim iTotalBytes As Double
Dim iFreeBytes As Double
Dim TotalBytes As Double
Dim FreeBytes As Double
'Ｃドライブの容量を得るとすると、
Re = GetDiskFreeSpaceEx( "c:\", lpFreeBytesAvailableToCaller, iTotalBytes, iFreeBytes)
'全容量
Totalbytes = iTotalBytes / 4.94065645841247E-324
'空き容量
FreeBytes = iiFreeBytes / 4.94065645841247E-324

```


変数に格納された数値を取り出すのに、ちょっと荒技を使っていますが、上記の方法で、バイト数が取り出せる筈です。試してみてください。この手法は、自作ソフトFileGearWに使っています。FileGearWのメニューの各ドライブ情報をクリックしてみて下さい。


#実証コード VBA

```vb
''標準モジュール
Option Explicit
#If VBA7 Then
Public Declare PtrSafe Function GetDiskFreeSpaceEx Lib "KERNEL32" Alias _
"GetDiskFreeSpaceExA" (ByVal _
lpDirectoryName As String, _
lpFreeBytesAvailableToCaller As Double, _
lpTotalNumberOfBytes As Double, _
lpTotalNumberOfFreeBytes As Double) As Long
#Else
Public Declare Function GetDiskFreeSpaceEx Lib "KERNEL32" Alias _
"GetDiskFreeSpaceExA" (ByVal _
lpDirectoryName As String, _
lpFreeBytesAvailableToCaller As Double, _
lpTotalNumberOfBytes As Double, _
lpTotalNumberOfFreeBytes As Double) As Long
#End If
Sub Freetestt()
Dim Re As Long
Dim lpFreeBytesAvailableToCaller As Double
Dim iTotalBytes As Double
Dim iFreeBytes As Double
Dim TotalBytes As Double
Dim FreeBytes As Double
'Ｃドライブの容量を得るとすると、
Re = GetDiskFreeSpaceEx("c:\", lpFreeBytesAvailableToCaller, iTotalBytes, iFreeBytes)
'全容量
TotalBytes = iTotalBytes / 4.94065645841247E-324
'空き容量
FreeBytes = iFreeBytes / 4.94065645841247E-324
Debug.Print FreeBytes & "/" & TotalBytes
End Sub

```
eslintの設定

流行りのJavaScript検証の設定メモ

# 参考

@mysticatea さんの記事を参考させていただきました。

- [ESLint 最初の一歩](https://qiita.com/mysticatea/items/f523dab04a25f617c87d)

# 準備

今の自分の環境

- node.js v8.9.4
- npm 5.6.0


# ESlint設定

## インストール

今回はグローバルではなくローカル環境

```
npm init //package.jsonを作成
npm install eslint //作成したpackage.jsonにeslintがあることを確認 
```

## ルール設定 

.eslintrc.jsonを作成して各ルールをかく
ルールを細かく書くと長くなるので大雑把に

ECMAScript 2015 (ES6)はtrue

```json

  "env": {
    "browser": true,
    "es6": true
  }
```

jQueryを使用するので設定追加
https://www.npmjs.com/package/eslint-plugin-jquery

```
npm install eslint-plugin-jquery --save-dev
```

.eslintrc.json

```json

{
  "plugins": [
    "jquery"
  ],
  "rules": {
  }
}
```

このままだとjQueryで怒られた

```js

$(function () {
});
// "$" is not defined no-undefと怒られた
```

.eslintrc.jsonにjQueryの記述を追加

```json
{
  "env": {
    "jquery": true
  }
}
```

これで解消

ルールは共有設定を使用@mysticatea さんのとおりにeslint-config-eslint
他にもgoogleの[eslint-config-google](https://www.npmjs.com/package/eslint-config-google)がある。
[Unity]OVRLipSyncでAudioSourceからの音が再生されないときの対処法

#OVRLipSync導入時に参考にしたサイト
https://qiita.com/ngron/items/b2c02a0f8133aac2ad9a
#困ったこと
今まで再生できていた音が、OVRLipSyncにより出力されなくなってしまった。
ちなみに口は動くが、音は全く出力されない。
#対処法
##見つけるまでの経緯
まず、参考サイトに何か記載があると思ったが特になく途方に暮れる。
検索するも全く出てこずお手上げ状態になってしまった。
その後、公式のドキュメントを見ると書いてあることに気が付く。
[公式ドキュメント]https://developer.oculus.com/documentation/audiosdk/latest/concepts/audio-ovrlipsync-sample-details/
このページの一部に
```Audio Loopback replays received audio as output.```
と書かれていた。
つまり、LoopBackに関する項目があるはず・・・
こんなところにありました
![スクリーンショット (3).png](https://qiita-image-store.s3.amazonaws.com/0/250596/90b6cb40-943f-b72a-8fd3-b2e930dc88f9.png)
##対処法
このAudio Loopbackにチェックを入れると
![スクリーンショット (4).png](https://qiita-image-store.s3.amazonaws.com/0/250596/6eaf32cc-9e57-ba77-1d77-0ae23f6357b9.png)
無事AudioSourceからの音が再生されながら口も動きました。
#今回思い知ったこと
***どうしてもわからないときはとりあえず公式のドキュメントを見よう***
最後までご覧いただきありがとうございました。
打ち込み①とその他２つの打ち込みを比較する

Scanner sc = new Scanner(System.in);
		String inputStr1 = sc.nextLine();
		String[] dataSet1 = inputStr1.split(" ");
		int suziHennkann1 = Integer.parseInt(dataSet1[0]);
		int suziHennkann2 = Integer.parseInt(dataSet1[1]);

		//何個打ち込まれるか⇨num
		String inputStr2 = sc.nextLine();
		int num = Integer.parseInt(inputStr2);
		int[] dataSet3 = new int[num];

		for(int i = 0; i < num; i++) {
			String inputStr3 = sc.nextLine();
			String[] dataSet2 = inputStr3.split(" ");
			dataSet3[i] = Integer.parseInt(dataSet2[0]);
			
		}
		if(suziHennkann1 > dataSet3[0]) {
			System.out.println("High");
		}
		else if(suziHennkann1 < dataSet3[0]) {
			System.out.println("Low");
		}

//		5 1 //打ち込み①
//		2　//何個打ち込まれるか(例2個)
//		7 2 //打ち込み1回目
//		1 4 //打ち込み2回目

打ち込み①と打ち込み1回目は比較できていると思うのですが、
打ち込み①と打ち込み2回目の比較ができません。
わかる方教えてください。
jqGrid：セルの属性値を設定したいとき

# JQGRID使用方法
Jqgridバージョン：v5.3.0

## セルの属性値を設定したいとき
ある特定の値の時に文字色を赤色にしたい。背景色を変更したいという要望がると思います。
こういったときに使用するのが、「cellattr」です。

### サンプル1(文字を赤に変更)
では、サンプルを見ていきます。
ここでは、rowIdが20のときのみcityの文字色を赤色にしています。

```js
$(document).ready(function () {
    "use strict";
    var mydata = [
            {rowId: "10",  pref: "大阪府",  city: "大阪市"},
            {rowId: "20",  pref: "兵庫県", city: "加古川市"},
            {rowId: "30",  pref: "山梨県", city: "甲府市"},
            {rowId: "40",  pref: "北海道", city: "札幌市"},
            {rowId: "50",  pref: "沖縄県", city: "那覇市"},
        ];
    var $grid = $("#list");
    $grid.jqGrid({
        datatype: "local",
        data: mydata,
        colNames: ["ID", "都道府県名", "都市名"],
        colModel: [
            {name: "rowId", width: 70},
            {name: "pref", width: 70},
            {
                name: "city",
                width: 70,
                cellattr: function(rowId, value, rawObject, cm, rdata) {
                    // rowId：行ＩＤ
                    // value：セルの表示する予定の値（formatterで編集された値）
                    // rawObject：編集していない行のオブジェクト
                    // cm：対象のカラムのカラムモデル
                    // rdata：行のオブジェクト
                    if (rawObject.rowId === "20") {
                        return "style='color: blue' title='テスト' class='aaa'";
                    }
                    return "";
                },
            },
        ],
        height: "auto",
        width: 500,
    });
});
```

#### サンプル1(画面)
![サンプル画面_cellattr.JPG](https://qiita-image-store.s3.amazonaws.com/0/159893/f7ac5aad-acab-3276-06d1-0b504c17152f.jpeg)


この方法で、特定の条件の時にセルの属性を設定することができます。
styleを記述することができますし、title, classも同様に設定できます。
ただし、注意しないといけないのは、文字列で返却しないといけない点です。
Object形式で返却しても属性は反映されません。
【メモ】TwitterKitを使ってサインイン処理をする




#Podinstall

`pod init`
↓
Podfileに
` pod 'TwitterKit'`
↓
`pod install`


#APIキーの取得

https://apps.twitter.com/

#スキームの追加

info.plist ファイルをSourcezCodeで開き,以下を記載する


![image.png](https://qiita-image-store.s3.amazonaws.com/0/185109/9dd6ea28-b9dc-d9f5-42cb-65db46b08e7b.png)

ConsumerKeyを記載するのを忘れずに

```swift:info.plist
<array>
		<dict>
			<key>CFBundleURLSchemes</key>
			<array>
				<string>twitterkit-ここにConsumerKeyを記載</string>
			</array>
		</dict>
	</array>
	<key>LSApplicationQueriesSchemes</key>
	<array>
		<string>twitter</string>
		<string>twitterauth</string>
	</array>
```

表示をPropertyListに戻した際に、URLtypes→item０→URLSchemeｓ→item0に変更が反映されてることを確認する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/185109/3f463103-dfca-46ba-c0da-fe8a08e49d36.png)

#ApiKeyの記載

```Swift:AppDelegate.Swift
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        if TWTRTwitter.sharedInstance().application(app, open: url, options: options) {
            return true
        }
        // Your other open URL handlers follow […]
        return false
    }
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        TWTRTwitter.sharedInstance().start(withConsumerKey: "ここにConsumerKeyを記載", consumerSecret: "ここにConsumerSecretを記載")
        return true
    }
```

#Login処理の実行

```Swift:（ログイン処理を実行したい）ViewController.Swift

TWTRTwitter.sharedInstance().logIn(completion: { (session, error) in
            if let sess = session {
                print("signed in as \(sess.userName)");
                print(self.username)
            } else {
                print("error: \(error?.localizedDescription)");
            }
        })

```


#わーい！！！

![IMG_6525.PNG](https://qiita-image-store.s3.amazonaws.com/0/185109/92481762-2192-d265-1190-e7b3912f3801.png)
[@Satopppy_](http://twitter.com/Satopppy_)
Amazon Linux WorkSpaces で既定のフォントを Noto にする

Amazon WorkSpaces (Amazon Linux 2) で既定のフォント (sans-serif・serif・monospace) を Google Noto フォントに設定しました。Amazon Linux だからと言って、手順にどうという違いはなかったのですが、一応備忘録として残しておきます。

## フォントをダウンロード

[Google Noto Fonts のサイト](https://www.google.com/get/noto/)から次のフォント (zip ファイル) をダウンロードします。

* Noto Sans CJK JP[^1]
* Noto Serif CJK JP

## zip ファイルを展開

ダウンロードした zip ファイルを展開します。

ここでは zip ファイルが ~/Downloads ディレクトリにあると仮定します。

```
cd ~/Downloads
unzip NotoSansCJKjp-hinted.zip
unzip NotoSerifCJKjp-hinted.zip
```

LICENSE_OFL.txt または README を上書きするかきかれたときの選択肢はどれでもかまいません。(この 2 つのファイルは不要なため。)

## フォントをコピー

展開された otf ファイルをシステムディレクトリにコピーします。

```
sudo mkdir -p /usr/share/fonts/opentype/noto
sudo cp *.otf /usr/share/fonts/opentype/noto
sudo chmod 755 /usr/share/fonts/opentype/noto/*.otf
```

## 既定のフォントを Noto にする

以下の内容で /etc/fonts/local.conf ファイルを作成します。

```:/etc/fonts/local.conf
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
  <match target="pattern">
    <test qual="any" name="family"><string>sans-serif</string></test>
    <edit name="family" mode="prepend" binding="same"><string>Noto Sans CJK JP</string></edit>
  </match>
  <match target="pattern">
    <test qual="any" name="family"><string>serif</string></test>
    <edit name="family" mode="prepend" binding="same"><string>Noto Serif CJK JP</string></edit>
  </match>
  <match target="pattern">
    <test qual="any" name="family"><string>monospace</string></test>
    <edit name="family" mode="prepend" binding="same"><string>Noto Sans Mono CJK JP</string></edit>
  </match>
</fontconfig>
```

## 設定を有効化

```
sudo fc-cache -f
```

## 確認

```
fc-match "sans-serif"
fc-match "serif"
fc-match "monospace"
```

出力:

```
NotoSansCJKjp-Medium.otf: "Noto Sans CJK JP" "Medium"
NotoSerifCJKjp-Medium.otf: "Noto Serif CJK JP" "Medium"
NotoSansMonoCJKjp-Regular.otf: "Noto Sans Mono CJK JP" "Regular"
```

できました:tada:

## おまけ

Noto を既定にすると、私にはターミナルのフォントがかなり小さく感じられます。このため、私はいつもフォントサイズを 11 pt に設定しなおしています。



## 参考
* [How to install fonts](https://www.google.com/get/noto/help/install/)

[^1]: yum のリポジトリにもありましたが、今回は公式サイトからダウンロードします。
[^2]: ユーザーディレクトリにインストールすることもできますが、今回はシステムディレクトリにインストールしています。
メール通知機能（あとで通知用のアドレスを入力させる）

# 目的

teapotというランチ募集サービスを作ってその際多かったメールでの通知機能をつける。ただ登録時はtwitterログインのみにしたいのと募集した側が応募が来た際にのみ使いたいので募集投稿時にメールアドレスを後で入れる形にする。

# 仕様

## メールフォーム

ユーザーの情報にemailを更新する形で登録する。

```ruby
@current_user = User.find_by(id: session[:user_id])
@current_user.update(email: params[:email])
```

現在のログインユーザーの情報を@current_userに入れ、そのユーザー情報にupdateでemail情報を入れる。

```ruby
  <%= form_tag("/post/notification_email") do %>
  <div class="form-group">
    <label class="post_form_label bmd-label-floating">email</label>
    <textarea name="email" class="form-control" ></textarea>
  </div>
  <input type="submit" value="投稿" class="btn btn-raised btn-info post_form_submit">
  <% end %>
```

## メール送信機能

https://qiita.com/you8/items/a386578836c5f155e984

このやり方でactivejobを使ってメール送信。

### メールのバリデーション

```ruby
validates :email, format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i }
```

メールアドレスの型はstring。メールアドレス全体の長さの最大値は254文字なので256文字以上じゃないのでtextではなくstring。

### 独自ドメインのメールアドレスの準備

ムームードメインでムームーメールを使ってgmailで管理という方法を取りました。gsuiteだと月600円でムームーメールだと複数メールアドレス作成できて年600円なんで複数サービス作る人にはおすすめ。

https://univ.peraichi.com/52

ここがやり方詳しかった。
Bash on Windowsで"gem install" がエラーしたのでipv6接続を切ったら成功した

# 三行で説明すると
- Bash on Windowsでgithub-pages(gemパッケージ)をインストールしようとしたら
- gemで原因不明のエラーに直面して
- Windowsのipv6設定を切ったら成功した

# 背景
無料で静的ページおよび**[jekyll][1]**がホスティング可能な**[github pages][2]**というサービスを使いたいと思い，作業を開始しました．
メインマシンでWindows 10を使っていたこと，jekyllによるページ構築およびgithubとの接続のみならGUI処理が無いので**[Bash on windows (Windows Subsystem for Linux)][3]**が使えるだろうということで，以下のことを実現しようと思い作業を開始しました．

**Bash on Windows上でjekyllのコンパイル（ローカル環境構築）を可能とし，github-pagesへのデプロイ（グローバル環境構築）も可能にする**

# 課題
基本的には@takuya0301さんの[記事][4]を参考に以下の手順で進めていました．

1. Bash on Windowsの有効化
2. Rubyインストール
3. github-pagesのインストール　**←ここでエラー**
4. Jekyllプロジェクトの生成
5. Jekyllプロジェクトの公開

しかし，gemとして用意されているgithub-pagesをインストールしようとしたところで以下のようなエラーが発生しました．

```
$ sudo gem install jekyll github-pages
ERROR:  Could not find a valid gem 'jekyll' (>= 0)
ERROR:  Could not find a valid gem 'github-pages' (>= 0)
```

# 解決法
調査した結果，この問題は参考文献\[1\]のronnelson氏のコメントによれば，

"For me the problem was that the attempted connection/download from https://rubygems.org/ was trying ipv6. disabling that protocol cleared the problem up completely." by ronnelson

翻訳すると，gem installを使用した場合デフォルトアクセス先となっている**https://rubygems.org/**へのアクセスは，自動的にipv6を使用して行う仕組みになっていたそうです．このため，ipv6のプロトコル設定を切ることで，問題が解決したということでした．

実際に，自身の環境でもWindowsの「ネットワークと共有センター」の「イーサネットのプロパティ」から「インターネットプロトコル　バージョン6(TCP/IPv6)」をオフにして，ターミナルを再起動したところ，無事以下のコマンドで必要なgemがインストールできるようになりました．

```
gem install jekyll bundler
gem install github-pages -v 191
```

# 参考文献
\[1\] https://github.com/Microsoft/WSL/issues/2525

[1]:https://jekyllrb.com/
[2]:https://pages.github.com/
[3]:https://docs.microsoft.com/ja-jp/windows/wsl/about
[4]:https://qiita.com/takuya0301/items/374b2ab5be407b138ef9
ソフトウェア設計についてのつぶやき

# ソフトウェア設計で大切なこと

同僚が書籍を読んだアウトプットとしてものすごく重要で核心的なことを言っているので引用します。

ソフトウェア設計において重要なのは下記の３つのこと。

```
概念: 責務を考える
仕様: インターフェースを考える
実装: 実装を考える
```

書かれたのをみて、**それ！**って思いました。実際に自分が行っているのはこういうプロセスです。
ただ自分なら少しだけタイトルを修正します。

```
分析: 責務を考える
設計: インターフェースを考える
実装: 実装を考える
```

自分の場合は開発ターゲットによりますが、全体のアーキテクチャーを考えて責務を決めて行くフェーズは分析が主でクラス図などを多用し、それに加えてモジュール間メッセージシステムなどの基本的な仕組みを検討していきます。
モジュールレベルの場合は、分析と設計はほぼ同時に行い外部インターフェイスを定義してシーケンス図を検討します。

分析・設計は、経験を積んだエンジニアは無意識に行っている場合もあるでしょうが、このようなプロセスの結果をドキュメント化したものを下記のように呼びます。

```
基本設計書
```

基本設計書には、システム全体に適用されるような基本的なインターフェイスなども含むこともありますし、その他要件に対する諸々の項目も必要でしょう。
（あるいはアーキテクチャー設計書。その他呼び方は色々ありそうです。）

また実装を考えた結果のドキュメントを

```
詳細設計書
```

と呼びます。
設計書って書いていますでしょうか？
また書いていたとしてその設計書は本当に価値があるものなのでしょうか？

詳細設計書に記載された内容の多くはソースコードを見ればほぼ分かります。設計書を見た方が圧倒的に早いですが、それでも適切なソースコードであればリバースエンジニアリング的に理解することはできるでしょう。しかしながら設計者がその責務の切り分けが**なぜ重要だと思ったか**「考えた」部分はなかなか読み取ることができません。
これを可能にするのが基本設計書ではないかと思います。したがって基本設計書には設計者の思想が織り込まれていることが望ましいと思います。

```
なぜそう考えたのか？
根拠は何か？
参照したアーキテクチャーはどれか？
この設計で非機能要件はなぜ満たされると考えているのか？
```

これに対して

```
Dependency Injectionがいいみたいなので試しに入れてみました
RxSwiftは良さそうだし使えるからいいんじゃない
```

などは設計とは言わないです。どちらかと言うとFeasibility studyとでもいうべきもので製品・商品に取り入れるのはとてもリスキーです（将来負債になる可能性が高い）。


# 分析・設計

話は変わりますが、別の同僚がQiita記事
[Clean Architecture 達人に学ぶソフトウェアの設計と構造](https://qiita.com/powerispower/items/f71cf88e77b55783ac66)
で読書した学びを発信しています。
自分も読み進めている途中で感想文を近日中に書く予定ですが、↑こちらの記事もぜひ読んでみて下さい。

Amazon書籍へのリンクはこちら
[Clean Architecture 達人に学ぶソフトウェアの構造と設計](https://www.amazon.co.jp/Clean-Architecture-達人に学ぶソフトウェアの構造と設計-Robert-C-Martin/dp/4048930656/ref=sr_1_1?ie=UTF8&qid=1536377271&sr=8-1&keywords=clean+architecture)



その中で、

```
「オブジェクト指向とは？」

① データと関数の組み合わせ：☓
② 現実の世界をモデル化する方法： ☓
③ カプセル化・継承・ポリモーフィズム: △

結論どれもちがーうw
```

って書いてあるんですが、全く同意です。

理由は「オブジェクト指向分析・設計は言語仕様でもコンパイラの機能でもなく**世界（モノ・コト）の捉え方（分析）であり、その結果をソフトウェアに再構成する力（設計）**」だと思っているからです。

C++、Java、Swiftその他の言語ができるのは、実装とせいぜいインターフェースの記述方法をカッコ良く（またはカッコ悪く？）することくらいです。
なぜそれの責務とインターフェイスを選んだかという思索の部分に関してはあまり役に立っていません。（**Swift脳**や**Java脳**になることで思考が**分析脳**に近づくことは認めます）

分析・設計は「モデリング」と言い換えても良いと思いますが、この「モデリング」を行う際の寄って立つ考え方の中で現在の主流が「オブジェクト指向分析・設計」です。
昨今は関数型分析・設計というものもあるようですが、すいません、こちらは理解していません。

# モデリング

モデリング、特にオブジェクト指向分析・設計のモデリングに関する説明をするのはかなり難しいのでここは[オージス総研のページ](https://www.ogis-ri.co.jp/otc/hiroba/technical/StrangeClass/index.html)を読んで下さい。

しかし言えるのは、繰り返しますが

```
世界（モノ・コト）の捉え方（分析）であり、その結果をソフトウェアに再構成する力（設計）
```

です。
モデリングに本質的にプログラミング言語は（実装技術として関連があるものの）関係ありません。
UMLも関係ありません。

- Java、Swiftなどの言語はモデリングを具体化する際の言語であり手段
- UMLはモデリングの結果を表記する言語

そして「世界（モノ・コト）の捉え方」「再構成する力」である以上、結果は**人によって異なります**
経験がある人とない人、トレーニングを受けた人と受けていない人ではモデリングの結果は異なります。この異なる考え方をして異なる結果になった設計を、関係者（開発チームならば、それらの全員に）に理解してもらうのが「設計書」だと思います。

そしてUMLはこの結果を皆で共有するための（今のところ主流の）共通言語です。これが読めなければ設計を効率的に共有することは難しいと思います。

しかしUMLは結果を記述するだけなので、なぜそこに到達したかを共有することが大事だと思う！ということを念押ししてひとまず「つぶやき」終了します。
gcloudコマンドでGCEスナップショット取得→インスタンス作成をやってみた


最近ちょっとGCPを使う機会が増えてきたんだけれど
データ消えたら嫌だなあ．定期的にバックアップとって，ついでにDB系ならバックアップからインスタンスを作成っていうのをスクリプトで自動でやってくれたら楽だなあ
と思ったのでgcloudコマンドでやってみた．忘備録として使用したコマンドを以下にまとめていく．

## 前提条件
- gcloudは設定済み（ComputeEngineを操作できる権限が付与されている）
- GCEにインスタンスが立ててある

## 使用したgcloudコマンド

### スナップショットの作成
まずインスタンスを作成する際に元となるスナップショットを作成する．

```
$ gcloud compute disks snapshot バックアップ対象のインスタンス名 --zone=ゾーン名 --snapshot-names=スナップショット名

例）
$ gcloud compute disks snapshot instance-01 --zone=asia-northeast1-a --snapshot-names=snapshot-01
```

コンソール上からスナップショットをとる時にはインスタンスを一旦止めないと取れない様になっていたけど，gcloudコマンドだとインスタンスを停止しなくてもスナップショットが取れるらしい（←公式ドキュメントより）．実際にコマンドを走らせてみたけど，特にインスタンスが停止した様子もなく起動状態のまま取れた．

### ディスクの作成
インスタンスを立てる際にブートディスクになるディスクをスナップショットから作成する．

```
$ gcloud compute disks create ディスク名 --source-snapshot=スナップショット名 --zone=ゾーン名

例）
$ gcloud compute disks create disk-01 --source-snapshot=snapshot-01 --zone=asia-northeast1-c
```

### インスタンスの作成
先ほど作成したディスクを元にインスタンスを作成する．

```
$ gcloud compute instances create 新しく作成するインスタンス名 \
　　--disk name=ディスク名,boot=yes,auto-delete=yes \
　　--zone=ゾーン名 --machine-type=インスタンスタイプ --tags=タグ名

例）
$ gcloud compute instances create instance-02 \
　　--disk name=disk-01,boot=yes,auto-delete=yes \
　　--zone=asia-northeast1-c --machine-type=n1-standard-2 --tags=http-server,https-server
```

`auto-delete=yes`でインスタンスを削除する時にディスクも一緒に削除してくれる．デフォルトでは，インスタンスを削除してもディスクは残ったままで，いちいち消しに行くのがめんどくさいので設定しておく．逆にインスタンスを削除してもディスクは残して置きたいという場合は`auto-delete=yes`はいらない．

### スナップショットの削除
定期的にスナップショットを取るとすると，不要なスナップショットまで溜まっていくので削除する．

```
gcloud compute snapshots delete スナップショット名

例）
gcloud compute snapshots delete snapshot-01
```

## 使えそうなコマンド

### インスタンスの削除

```
gcloud compute instances delete インスタンス名 --zone=ゾーン名 --quiet
```

インスタンスを削除する際に，コマンドライン上でディスクも削除するか[y,n]聞かれる．`--quiet`をつけておくと聞かれなくなるのでスクリプト化する際とかに楽．インスタンス作成時に`auto-delete=yes`を選択した（上記の）コマンドを使用した場合だと，期待通りディスクも削除してくれた．

### 外部IPアドレスの取得
外部IPアドレスを取得したいインスタンスのネットワークの構成を表示．

```
$ gcloud compute instances describe インスタンス名 --zone=ゾーン名
...
networkInterfaces:
- accessConfigs:
  - kind: compute#accessConfig
    name: hogehoge
    natIP: 35.27.31.54 //外部IPアドレス（例）
　...
  name: nic0
  network: default
  networkIP: 10.0.0.1 //内部IPアドレス（例）
  subnetwork: default
...
```

上記のネットワーク構成の際に外部IPアドレスだけ取りたい時は，

```
$ gcloud compute instances describe インスタンス名 --format="get(networkInterfaces[].accessConfigs[0].natIP)
35.27.31.54
```
で取れる．


## AWS-CLIとの比較
aws-cliコマンドではインスタンスやAMIに対して何かしらコマンドで操作する時はIDを指定していたけど，gcloudコマンドでは最初につけた名前を指定するらしい．AWSだとインスタンスやAMIを操作するのに，条件指定してIDを取ってきてから操作していたけど，GCPだと自分で名前決められるので楽だった．その代わりそれぞれの名前は，ゾーンごとに一意である必要がある，後から変更できないっていう制約は付いてくるけど．
あと，スクリプト化するのにおいてスナップショットやインスタンスが作成中だったら待つみたいなコマンドを必要がない．例えばaws-cliだとAMIを取得するコマンドの後に作成したAMIからインスタンス作成を実行しようとすると，AMIが作成途中なのでインスタンス作成コマンドが失敗してしまう可能性がある．その為にAMIの作成が終了するまで待つコマンドを実行する必要がある．それに比べて，gcloudだとスナップショットを作成するコマンドを打つと実際にスナップショットが作成中であることがプロンプトに表示され，作成が終了するまで次のコマンドが実行できないので順々に実行できて楽だった．
vim 命令集

上移動:k
下移動:j
右移動:l
左移動:h
最初移動:gg
最後移動:G
通常状態:Esc
挿入状態:i
一文字追加&挿入状態:a
一行追加&挿入状態:o
編集状態:v
部分編集状態:Ctrl&v
復写:y
現在行復写:y
現在行消去:dd
次行貼付:p
一文字置換:r
複数文字置換:R
戻前状態:u
進次状態:Ctrl&r
保存::w
閉鎖::q
保存&閉鎖::wq
Rubyに関する質問です。

rails sコマンドを使用したら、pumaと呼ばれるアプリケーションサーバーが起動します。って、本に書いてありましたが、うまくいきません。どうすれば、起動するのでしょうか？![image.jpg](https://qiita-image-store.s3.amazonaws.com/0/282633/d03544f5-e795-8407-3db6-9f219bdd832d.jpeg)
AnacondaのSpyderでspyder_line_profilerを使用して実行時間の解析

# この記事は
Pythonのパッケージ管理ツールにAnacondaがあります．
このAnacondaではPythonの統合開発環境，Spyderが提供されています．
本記事ではSpyderでプラグインで利用できる"spyder-line-profiler"の使い方を簡単にまとめます．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/259451/9a400d64-5bf4-fab6-592e-ab64900c7b68.png)
https://github.com/spyder-ide/spyder-line-profiler

# 実行環境
- Ubuntu 16.04
- Python 3.5.4
- Anaconda 1.6.6
- Spyder 3.2.4


# インストール
## Anaconda
以下のようなサイトを参考にして，Anacondaを利用したPython環境の構築を行います．

https://pythondatascience.plavox.info/python%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/anaconda-ubuntu-linux

## spyder-line_profiler
[本家github](https://github.com/spyder-ide/spyder-line-profiler)にあるように，condaコマンドもしくはpipコマンドでインストールします．

```bash
# conda
$ conda install -c spyder-ide spyder-line-profiler
# or pip
$ pip install spyder-line-profiler
```

pipの方があっさり．


# 実行例
今回は以下のtest_profile.pyの実行時間を計測します．
100x100のarrayの和を計算する2つの関数（func1, func2）を使用します．
ポイントはプロファイリングしたい関数の前に@profileと書き加えることです．

```python:test_profile.py
import numpy as np

@profile
def func1(hoge):
    s = 0
    for i in range(hoge.shape[0]):
        for j in range(hoge.shape[1]):
            s += hoge[i, j]
    print(s)

@profile
def func2(hoge):
    print(hoge.sum())

@profile
def main():
    a = np.ones((100, 100))
    
    func1(a)
    func2(a)

if __name__ == "__main__":
    main()
```

このファイルをspyder上で開き，ツールバーの[実行]->[Profile line by line]をクリックすることでプロファイリングできます．
プロファイリングが終了すると，以下のスクリーンショットのようなタブが現れます．（[ヘルプ]や[変数エクスプローラー]タブの隣に）
プロファイリング結果は，ホームディレクトリ下の.config/spyder-py3/lineprofiler.resultsに保存されるようです．
![Screenshot from 2018-09-08 18-48-56.png](https://qiita-image-store.s3.amazonaws.com/0/259451/a3d2a786-e463-dfbe-7481-76958aa9ecd8.png)
それぞれの列は，

- Line：行
- Hits：呼び出された回数
- Time：その行の総実行時間 (ms)
- Per hit：1回当たりの実行時間 (ms)
- % Time：その行の実行時間が，関数の実行時間に占める割合

% Timeによって行が色付けされていて，視覚的にも分かりやすい．
navigationBar.isTranslucentによってself.viewのy座標が変わるのの対策まとめ

# パターンは4パターン
`isTranslucent`を`true`にしたいか`false`にしたいかの２パターンと
viewをnavigationBarの上から始めたいか、下から始めたいかの2パターンの掛け合わせ.
よって一つずつ対策を見ていこう

# `isTranslucent = true`にしたい時
## viewをnavigationBarの上から始めたい
何もしないでただtrueにすればいい. 

```swift
   navigationBar.isTranslucent = true
```

## viewをnavigationBarの下から始めたい
edgesForExtendedLayoutをいじる

```swift
   navigationBar.isTranslucent = true
   edgesForExtendedLayout = .bottom//多分NavigationBarのどこまでViewを伸ばすかというプロパティ
```



# `isTranslucent = false`にしたい時
## viewをnavigationBarの上から始めたい
`extendedLayoutIncludesOpaqueBars`を`true`にする必要がある

```swift
   self.navigationController?.navigationBar.isTranslucent = false
   extendedLayoutIncludesOpaqueBars = true
```


## viewをnavigationBarの下から始めたい
`extendedLayoutIncludesOpaqueBars`を`false`にする必要があるが、何もいじってなければ元から`false`

```swift
   self.navigationController?.navigationBar.isTranslucent = false
   //extendedLayoutIncludesOpaqueBars = false
```
Perlのreturnとreturn undefとOdd number of elements in hash assignmentの話

# 概要
たまたまハマったのでPerlと`return;`と`return undef;`の違いと、
それによって発生するエラー`Odd number of elements in hash assignment`の話。

# はじめに
はじめに、このコードと結果を見てください。

```test1.pl
use warnings;
use utf8;
use DDP;

sub test1 { return; }
sub test2 { return undef; }

my %a1 = ( now => test1() );
p %a1;

my %a2 = ( now => test2() );
p %a2;
```

```console
Odd number of elements in hash assignment at test1.pl line 8.
{
    now   undef
}
{
    now   undef
}
```

これをみてわかるように、`return;`をしている時は、
`Odd number of elements in hash assignment`のエラーが出ています。

# `return;`と`return undef;`
こちらを参考にそれぞれの違いを確認しました。
参考: http://www.perlplus.jp/perl/sub/index7.html

## `return;`の動作
>「return」文が実行されると呼び出し元に処理が戻ります。
「return」文でサブルーチンが終了した場合には、戻り値として空の値が設定されます。
空の値とは呼び出し元が値を求めている場合は未定義値「undef」となり、リストを求めている場合は空のリストとなります。

つまり、呼び出し元によって以下のような動作になります。

```test2.pl
use warnings;
use utf8;
use DDP;

sub test1 { return; }

my $a = test1(); # undef
my @b = test1(); # 空のリスト
my %c = test1(); # 空のリスト

p a;
p b;
p c;
```

```
undef
[]
{}
```

## `return undef;`
>また「return」文が実行される時に戻り値を指定することも可能です。この場合の書式は次のようになります。
この場合、呼び出し元に処理が戻ると共に戻り値が指定した値に設定されます。

つまり、呼び出し元によって以下のような動作になります。

```test3.pl
use warnings;
use utf8;
use DDP;

sub test2 { return undef; }

my $a = test2(); # undef
my @b = test2(); # undef
my %c = test2(); # undef

p a;
p b;
p c;
```

```
undef

[
    [0] undef
]

Odd number of elements in hash assignment at test3.pl line 9.
Use of uninitialized value in list assignment at test3.pl line 9.
{
    ''   undef
}
```

# 結論
以上の`return;`と`return undef;`の違いから、最初のコードは次のような動作になることがわかりました。

```test.pl
use warnings;
use utf8;
use DDP;

sub test1 { return; }
sub test2 { return undef; }

# 空のリストが返るので、 
# %a2 = ('now', ())
# になり、 Odd number of elements in hash assignment のエラーが出る。
my %a1 = ( now => test1() );
p %a1;

# undefが返るので、 
# %a2 = ('now', undef)
# になり、正常に動作する。
my %a2 = ( now => test2() );
p %a2;
```
Alexaスキルのポリシーガイドライン（第三者の知的財産権）に対応する

「ポッドキャストを再生するAlexaスキルを公開したので知見を公開する」シリーズの最初はポリシーガイドラインについて。

[システム構成](https://qiita.com/snaka/items/ae170578703a27063475#%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A7%8B%E6%88%90)等は予告編を参照

# スキル公開の前に立ちはだかる壁

Alexa スキルを公開するには、まずスキル審査に合格しなければならないが、そこには大きな壁が存在する。
それは、Alexaスキルの[ポリシーガイドライン](https://developer.amazon.com/ja/docs/custom-skills/policy-testing-for-an-alexa-skill.html)だが、第三者が公開しているポッドキャストを再生するスキルについては「1.商標、知的財産、およびブランド」に記載されている以下の要件をクリアしなければならない。

> スキルに商標、知的財産、ブランドを法的に使用する権利がある場合、そのスキルの認定を申請する際に、これらを使用する許諾を得ていることを示し、明示的に証明する必要があります。開発者ポータルの公開ページのプライバシーとコンプライアンスの項目にあるテストの手順を使用してこの情報を提示してください。必要に応じて、知的財産を使用する権利を証明する文書（登録商標や権利所有者との間のライセンス許諾の証明書など）への外部リンクを記載します。この情報をもとに、Amazonの認定チームがスキルが必要な許諾を得ているかどうかを判断します。


実際、審査をリジェクトされたときに返ってきたフィードバックを引用する。

> 1.  Amazonにとって知的財産権の保護は非常に重要です。第三者が作成して音声ファイルが使用されている可能性がございます。音声ファイルを使用する権利を持っていることを示す文書を提示してください。この文書は、知的財産権の権利者からの確認状または適用されるライセンスの写しである必要があります。
>
> 必要な文章をお持ちの場合、該当する文面へのリンクを次回の申請で提供してください。もしBox、Dropbox、S3等のファイル共有サービスを利用する場合、開発者ポータル内の「プライバシーとコンプライアンス」タブにある「テストの手順」にてリンクを貼付してください。リンクと、スキルの知的財産の情報がリンクに含まれている事を合わせて記載し、再申請してください。 もし、文章の提供が不可能な場合、スキルから音声コンテンツを削除してください。

要するに

* 第三者が作成した音声ファイルを使用する権利を持っている文書を提示する必要がある
* その文書へのリンクをスキル申請時の「テストの手順」の中で示すこと
* それが提示できない場合は該当音声はスキルで使用することはできない

ということらしい。

# 要件に対応するためにやったこと


* Twitter のDM等で配信者にコンタクトを取る
* DM で Alexa スキルを作っていること、スキルの公開のためにポッドキャストの音源や名称の使用の許諾が必要であることを説明する
* DM ある程度 OK をもらったら Google Document 審査に提出するための文書を作成
* 配信者に Google Document を確認してもらって、その文書の内容について問題無いことを確認してもらう
* スキル審査申し込みのフォーム「テストの手順」で Google Document の参照用リンクを提示


# どのような文書を作ったか？

実際には、以下のような文書を作って配信者の許諾の意思を確認した。

[![Image from Gyazo](https://i.gyazo.com/c134aee01363e420c67612bb3812ba8c.png)](https://gyazo.com/c134aee01363e420c67612bb3812ba8c)

Google Document へのリンクも貼っておくのでコピーするなり参考にするなり自由に使ってもらっても問題無い。

https://docs.google.com/document/d/12Q54KLjryUgKYYfgaeMDUhyj-tnjQ-ANHd2yWsgkbx4/edit?usp=sharing


# さいごに

以下、Alexa スキルのソースコード一式を公開しているが、それぞれの `/skill.json` を見れば、実際に使用した Google Document のリンクも見つけられると思う。

* https://github.com/snaka/skill-backspace.fm
* https://github.com/snaka/skill-tcfm-player

Amazon Echo のユーザーとしては、この記事が参考になってポッドキャスト対応の Alexa スキルがもっともっと増えていってくれると嬉しい（他人任せ）
mkdirやtouchとchmod, chown, chgrpあたりを1つのコマンドでまとめてやる


構築手順書をせっせと作ったり()、dockerfile書いたり、こういう記事書いたりするときに、
`mkdir`したり`cp`や`touch`したものに対して、`chmod`, `chown`, `chgrp`を実行する、というのはよくやりがちだと思うのですが、
それをそれぞれ個別にやってるケースを見かけるので、一気にやる方法をまとめてみます。
(dockerfileで`&&`で複数コマンド繋ぐよりはスマートかな？)

(基本的にGNU系(centosで確認しました)でもBSD系(Mac OSXで確認しました)でもどちらでもいけると思ってますが、何かあればコメントいただければと思います。)

# `chown`と`chgrp`

グループの変更は`chown`でもできます。
(なので実質`chgrp`って使うこと滅多にない気が……)

```bash
chown user:group path/to/file
```
これで、所有者が`user`に、グループが`group`に変更されます。
`:`(コロン)は`.`(ドット)でもいける環境もあるようですが、これは古い形式で非推奨のようです。
- [GNU Coreutils: chown invocation](https://www.gnu.org/software/coreutils/manual/html_node/chown-invocation.html#chown-invocation)
- [chown - FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=chown&manpath=FreeBSD+8.0-RELEASE)

以下のように、`group`を省略して`:`だけ置けば、所有者と合わせて、グループも所有者の(プライマリ)グループに変更されます。
※これはGNU系版だけで、BSD系版では単にuserが変更されるだけのようです

```bash
chown user: path/to/file
```

ちなみに`user`を省略して、`:`を前に置けば、グループだけの変更も可能です
(`chgrp`の立場は… :thinking: )

```bash
chown :group path/to/file
```

# `mkdir`と`chmod`, `chown`, `chgrp`

`mkdir`は`-m`オプションでmodeを指定できます。
※`-p`オプションは今回の話とは関係ないですが、付けといた方いいので付けときます(以下同様)

```bash
mkdir -p -m 777 path/to/dir
# 権限を持ってない場合
sudo mkdir -p -m 777 path/to/dir
```

`chown`, `chgrp`もまとめてやりたい場合は2通りの方法があります。

指定するユーザーが、作成する場所の書き込み権限を持っている場合
(かつ、指定するグループが指定するユーザーのプライマリグループの場合)

この場合は、`sudo`で別のユーザーとして実行しちゃえばいいですよね。

```bash
sudo -u user mkdir -p -m 777 path/to/dir
```
ただし、この方法だと、`user`が書き込み権限を持っていない場合は失敗してしまいます。

なのでこの場合はもう1つの方法として、権限を持っているユーザー(主に`root`)で、`install`コマンドを使い、オプションでモード、所有者、グループをそれぞれ指定します。

```bash
sudo install -m 777 -o user -g group -d path/to/dir
```
(`mkdir`の`-p`オプションと同等のことをしてくれます。)
`mkdir`と同じように、複数ディレクトリをまとめて作成することもできます。
(ただし、`-p`オプション分の部分のディレクトリは、オプションが反映されず、所有者は`root`で権限は`755`になります><)


参考： [installコマンドでコマンド数を減らす - @znz blog](https://blog.n-z.jp/blog/2014-02-14-install.html)


# ファイルと`chmod`, `chown`, `chgrp`

先ほど挙げた記事にも書かれていますが、`install`コマンドは、ファイルのコピーにも使えます。
(というかこっちが本業)
この場合は、途中までのディレクトリは作成してくれません。

## `cp`と`chmod`, `chown`, `chgrp`をまとめて

```bash
sudo install -m 0644 -o user -g group other/path/to/source path/to/dist
```

## `touch`と`chmod`, `chown`, `chgrp`をまとめて


```bash
sudo install -m 0644 -o user -g group /dev/null path/to/file
```



# 補足：installコマンドについて

なんで`install`なんて名前のコマンドでこんなことができるんだ？って感じですが、
これは元々make内で使用するためのコマンドのようです。
なので、パーミッションや所有者を指定してディレクトリを作ったりファイルをコピーしたりする機能があるんですね。

他にもバックアップを取るオプションなどもありますので気になる方は以下などをご覧ください。
- [GNU Coreutils: install invocation](https://www.gnu.org/software/coreutils/manual/html_node/install-invocation.html)
- [install - FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=install&manpath=FreeBSD+12-current)


--------------------

それでは良きサーバー構築ライフを :exclamation:
ポッドキャストを再生するAlexaスキルを公開したので知見を公開する（予告編）


2017年に Amazon Echo を手に入れた当初から

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">いつも聴いているPodcastがEchoで聴けるようになった最高だけど、自分でSkill実装したら実現できるのかな？</p>&mdash; snaka (@snaka) <a href="https://twitter.com/snaka/status/936817273372778497?ref_src=twsrc%5Etfw">2017年12月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

と思っていて、この7月末ごろからAlexスキル開発はじめてやっとストアへの公開にこぎつけたのでその知見を少しづつ公開していこうと思う。[^1]


# システム構成

ポッドキャストを再生する Alexa スキルは以下のようなシステム構成となっている

![Podcasting Skill .png](https://qiita-image-store.s3.amazonaws.com/0/8219/1e88f4ac-7276-9776-aa0f-e6a691a22a02.png)

当初は Lambda 1個でフィードの取得からそのフィードからURLを取り出して Echo にレスポンスを返すのまでやっていたが、ポッドキャストによってはフィードの読み込みに4～6秒程度待たされることがあり、無音状態で数秒待たされるとかなり不安になることがわかった。

そこで、フィードの取得とリクエストに対して音源のURLを返す部分を分離して、そのLambda間の中継兼キャッシュとして DynamoDB を利用する構成とした。

それによって、だいたい1秒以内でレスポンスを返せるようになった。[^2]

# index

今後、以下のような記事を順次アップする予定（長くなりそうなので個別に）

* [Alexaスキルポリシーガイドラインへの対応](https://qiita.com/snaka/items/a91b6bdb8bc478030678)
* AudioPlayer インターフェースに関する Tips
* ask-cli の Tips
* aws-sdk node v2 の Tips
* Alexa Skill のテスト
* Alexa Skill のバージョン管理
* X-Ray によるプロファイリングとパフォーマンス改善 
* Alexa Skill の CI/CD

Alexa Skill を作ってみよう的な記事は多いと思うので、それ以外をテーマに書いていこうと思う。


# ストアへのリンクとソースコード

公開したスキルへのリンクと Github で公開しているリポジトリへのリンクを貼っておく。

※以下の画像は Amazon のスキルストアへのリンクとなってます。
※以下のスキルは各配信者様の許諾を得て公開しているものですが、各配信者様はスキルの開発には関わっておりません。スキルに対する問い合わせは私(@snaka)までお願いします。

**Turing Complete FM プレイヤー**
Alexaスキル: https://www.amazon.co.jp/dp/B07GJSG572
[![Image from Gyazo](https://i.gyazo.com/ab7444f6d2ece6a2bb745818e8a746a1.png)](https://www.amazon.co.jp/dp/B07GJSG572)
GitHub: https://github.com/snaka/skill-tcfm-player

**backspace.fm プレイヤー**
Alexaスキル: https://www.amazon.co.jp/dp/B07H294SKT
[![Image from Gyazo](https://i.gyazo.com/eb9dfc6204ec1eba315a83738e733bf9.png)](https://www.amazon.co.jp/dp/B07H294SKT)
GitHub: https://github.com/snaka/skill-backspace.fm


[^1]: 時間がかかったのは、審査への対応やストア公開後に突然スキルが呼び出せなくなったりなど、開発以外の要素が大きかった。
[^2]: ただし、コンテナの初期化時間を除く。
VS Code　キーボードのショートカット

# VS Code キーボードのショートカット
- vscodeでキーボードのショートカットは簡単に設定できます
- [ファイル][基本設定][キーボードのショートカット]で「keyboard Shortcuts」を開く
- 左の鉛筆ボタンを押下するとダイアログが開く
- そこで設定すればOK
- お試しください。
【初心者向け】PHPによるバッチ処理プログラム開発

# はじめに
担当サービスが育ってきて、自動化、非同期処理を作成する必要が高まりバッチ処理を書くことが増えてきた。
これまで3回バッチ処理を書いてきて、何回もハマってしまい、案件進行の遅延、不具合の発生など様々なトラブル引き起こしてしまった。
その反省と今後の対処、他の開発者には同じ過ちを犯さないでもらうためにPHPのバッチ処理作成のポイントをまとめることにした。

# バッチ処理作成のハマりどころ
だいたい自分のように画面表示があるシステムの開発者が初めてバッチ処理を作成する時にハマるポイントは次の点だと思われる。

- バッチ処理特有のエラー
- サーバー間通信
- 失敗した時の原因探索

## バッチ処理特有のエラー
PHPでバッチ処理を作っていざ実行してみると、途中で急に落ちてしまうことがある。
大抵のバッチ処理は、半日〜数日に渡る処理を実行するため、テストでは完全には同じ時間の実行をできないというのはありがちな話だ。例えば10,000件のレコードの加工・更新処理を行う時、テストでは1000件程度しか実行しないということが起こりうる。

しかしこれは結構危険で、10,000件のデータ更新と1,000件のデータ更新では全く意味合いが違う。
バッチ処理あるあるのメモリ管理問題だ。
PHPのデフォルトのメモリ割り当ては128MBとなっているため、これを超えると途端にPHPが落ちてしまう。(メモリリーク)
1,000件ではメモリリークが起きなくても、10,000件ではメモリリークが発生してしまう可能性がある。

### 対策
対策方法としては当然だが、メモリを食いまくる書き方をやめること。
具体的にはforeachなどでループ処理をする際に変数を解放しないと起こるので、使い終わった変数をunsetしてあげることが重要となる。

```php  
  $records1 = get_records1();
  $records2 = get_records2();
  foreach($records1 as $record1) {
    foreach($records2 as $record2) {
      //なんか色々加工処理
    }
  }
```

メモリを大量に確保する可能性がある処理を書くときは、現在の使用メモリ量を出力するなどして、メモリ使用量が増大し続けていないかチェックするようにすること。
以下の関数でチェックできる。

```php
echo memory_get_usage();
```
詳しくは以下参照。
http://kameryo.hatenablog.com/entry/2015/06/24/110559


上記の方法でもメモリが不足してしまう場合、以下のようにバッチ処理のはじめに記述しておけば、メモリの使用量を変更することができる。

```php
ini_set("memory_limit", [適当なメモリ数]);
```
例えば自分は以下のように設定したりする。

```php
ini_set("memory_limit", "512MB");
```

## サーバー間通信
画面があるアプリケーション開発をしていると普段あまりサーバー間通信を意識することがない。
しかし、バッチ処理では複数のwebまたはDBサーバーへの通信を行う場合が頻繁にある。
接続するために書くことはIPやパスワードを間違えずに書けばいいだけなので、特段難しいわけではないが、
Apache等webサーバーの設定でハマったり、DBにユーザー作成を忘れていたり、地味に失敗することがある。

### 対策
ローカル環境やテスト環境でテストして上手くいったからって本番環境と差異が少しでもあるのなら、本番環境でも接続面で問題がないかテストをすること。

## 失敗した時の原因探索(ロギング)
多分もっとも大事なポイントかもしれないロギング。画面のあるアプリケーションでももちろん大事だが、それ以上に気をつけてログをどう吐くか設計したほうがいい。
少なくとも自分がした失敗の多くはロギングをちゃんとすればすぐに解決できるものが多く、今まで述べてきたハマりどころもここさえしっかり作っておけば、即座に解決できるはずだ。

### 対策
- 処理の各ポイントの完了部分でログを吐くこと(必要があればどのデータをどのように更新したのかログを吐く)
- エラー時にログを吐くこと
- 処理の開始、完了時にログを吐くこと
- 時間を必ず記録すること
- 当たり前だが改行すること

以上を守れば失敗した場合も調査が楽になるはず。
ちなみにログ出力は時間出力や改行を入れるようにロギング用のラッパー関数を作っておくと、捗るのでおすすめ。
例えば以下のようなstatic関数を作っておく。

```php
/**
* ログ出力のラッパー関数 LOG_PATHには任意の出力先ファイルのパスが格納されている
* @param string $message
*/
public static function get_log($message) {
  $log .= date( "Y年m月d日 H時i分s秒" )
  $log .= " ";
  $log .= $message;
  $log .= "\n";
  error_log($log, 3, LOG_PATH);
}
```

## その他
普通はないと思うが、[curl URL]という叩き方でバッチを実行する場合、PHP実行時間が長いと途中で終了させる設定により、バッチ処理が終了させられてしまうことがある。
これはPHPのmax_execution設定がデフォルトで60秒になっていることが原因である。

### 対策
バッチ処理で初期設定として、

```php

php_ini("max_execution",[適当な秒数]);
```
と書いておくとそのバッチ処理の実行時間を伸ばすことができる。


# おわりに
ここまで書いてきた内容はバッチ処理を数回書いた程度の浅い経験に基づくものだが、おそらく同じような点で失敗する人が多いと思われる。
さらに大事な点やいいまとめ方がわかってきたら今一度バッチ処理についてまとめようと思う。
間違っている点やもっとここが大事だろっていう点があればコメントお願いします。
Git初心者だった過去の自分に伝えたい本当に一番最初に覚えるべきコマンド

`reflog` と `reset --hard` この2つです。

`git reflog -10` で履歴がでるので `git reset --hard xxxxxxx` とすればその時点に戻すことができます。

私はこの reflog をあとで知って、いくらでも試行錯誤できるようになったことで急に理解できるようになりました。そしてもっと早く知っていればと後悔しています。

なので初めての方はこの2つのコマンドを真っ先に覚えるのがおすすめです。

失敗しても何度でもやり直せるんだからもう Git は恐くありません。
IBM Cloud Visual RecognitionとLINE Messaging APIを使って画像認識LINE BOTを作る

# 概要
[IBM Cloud Visual Recognition](https://console.bluemix.net/docs/services/visual-recognition/index.html#-)と[LINE Messaging API](https://developers.line.me/ja/reference/messaging-api/)を使って画像認識LINE BOTを作ります。
こちらの[リポジトリ](https://github.com/hidehiro98/line-messaging-api)にコードと使い方があります。
またこちらから友達登録してもらえると使えるので、是非画像を送ってみてください。
![xhack_nagaoka.png](https://qiita-image-store.s3.amazonaws.com/0/68213/0fcddea9-8955-471b-ae04-3b4194d62c6b.png)

## イメージ
<img width="375" alt="IMG_1014.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/68213/533673e2-b7a3-f264-0998-9045ec5309b1.png">

# 使うもの

## IBM Cloud Visual Recognition
https://www.ibm.com/watson/developercloud/visual-recognition/api/v3/node.html?node#general-api

## LINE Messaging API
https://developers.line.me/ja/reference/messaging-api/

## Heroku
https://id.heroku.com/login

## codenvy（開発環境がある方はなしで可能）
https://codenvy.io/site/login

# BOTの流れ

LINE BOTにメッセージがくる
↓
LINE Messaging APIのWebhook URLが呼ばれる（以下Herokuのnodeアプリ内での動き）
↓
Herokuにデプロイされたアプリが画像データを取得するためにLINE Messaging APIにリクエストを投げる
↓
LINE Messaging APIから画像のバイナリ（Buffer）が返ってくる
↓
IBM Cloud Visual Recognitionにバイナリと共に分類のリクエストを投げる
↓
レスポンスをLINE Messagin APIを通して返す

# IBM Cloud Recognition API Key入手手順
- IBM Cloudのアカウントを作成
- [こちら](https://console.bluemix.net/catalog/services/visual-recognition)から価格プランでライトを選択して作成
- 作成して移動した先でAPI 鍵をコピー
- [こちら](https://console.bluemix.net/dashboard/apps)で後から作ったサービス一覧が確認できます

# はまったところ
[LINE Developers API Reference](https://developers.line.me/ja/reference/messaging-api/#anchor-fcc6cd7ad966ea05230c564c2be362df80c0739d)にある `node.js` のコードで、

```javascript

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

const client = new line.Client({
  channelAccessToken: '<channel access token>'
});

client.getMessageContent('<messageId>')
  .then((stream) => {
    stream.on('data', (chunk) => {
      ...
    });
    stream.on('error', (err) => {
      // error handling
    });
  });
```

コンテンツを取得して `chunk` をそのまま送ると、

```
Invalid/corrupted image data. Supported image file formats are GIF, JPEG, PNG, and TIFF. 
Supported compression format is ZIP.","error_id":"input_error" ibm visual recognition
```

というエラーが出た。 `chunk` にreponseとbodyが一緒になっている？[ここ](https://stackoverflow.com/questions/5083914/get-the-whole-response-body-when-the-response-is-chunked)のやり方とかで分ける必要があるのかも（未検証）。

[ここ](https://qiita.com/n0bisuke/items/17c795fea4c2b5571ce0)にあるこのコードを使って、bodyだけを送ることで解決。

```javascript
app.post('/webhook', (req, res) => {
    if(req.body.events[0].message.type !== 'image') return;

    // 略

    Request(options, function(error, response, body) {
        if (!error && response.statusCode == 200) {
            // bodyをIBM Cloud Visual Recognitionに送る
        } else {
            // @todo handle error
        }
    });
});
```

# ワークショップ
https://connpass.com/event/99191/ で行ったワークショップでは5人の方に参加いただき、全員がBOTを動かすところまで出来ました！
ワークショップの[様子1](https://www.facebook.com/hidehiro98/videos/567409730341727/)、[様子2](https://www.facebook.com/hidehiro98/videos/1096878307145657/)。

# 参考
https://qiita.com/n0bisuke/items/17c795fea4c2b5571ce0
https://github.com/ippei0605/line-bot
【初心者向け】Unityで3Dシューティングを作るチュートリアル

引っ越しましたので[こちら](http://getabakoclub.com/2018/09/08/%E3%80%90%E5%88%9D%E5%BF%83%E8%80%85%E5%90%91%E3%81%91%E3%80%91unity%E3%81%A73d%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%92%E4%BD%9C%E3%82%8B%E3%83%81%E3%83%A5%E3%83%BC/)を御覧ください
【随時更新】プルリクエストを出す前のチェック項目

# 概要

完全に個人でも使っているものなので、見苦しいものもあるかもしれませんが、公開します。
他の方にも役立てば幸いです。

# チェック項目

## 変数

- [ ] マジックナンバーを使っていないこと→クラス定数などで置換

## メソッド

- [ ] メソッドが使われるときのことを想定した命名となっていないこと
- [ ] 引数で型が決まっている場合は、タイプヒンティングを使っているか
- [ ] メンバ変数にアクセスしないことを明示するためにstaticを使っているか
- [ ] returnはif文を使ってやる意味があるのか
- [ ] 引数がarrayのみである場合はタイプヒンティングを使っているか(現在のNEのバージョンだとobjectかarrayとか)
- [ ] 

## コメント

- [ ] メソッド名で自明なことをコメントで書いていないか
- [ ] コメントの日本語に違和感はないか→「頭痛が痛い」のようなコメントはないか
- [ ] 作成した処理を変更する際に必要なことがあれば、ナレッジとしてコメントを残しているか
- [ ] 突然出てきた値に対してコメントでの補足はあるか(そもそもその値がそれで良いかもチェック)
- [ ] コメントにタイポはないか
- [ ] メソッドのドキュメント(php: PHPDoc)は書くべき値となっているか
- [ ] プロパティのコメントは、phpなら　「/** var {型名} {変数名} */」の形式となっているか
- [ ] コメントの書き方は統一されているか


## 記述場所

- [ ] クラスプロパティで管理した方が良いものはないか

## 記述方法

### ソースコード

- [ ] 定数名は意味がわかるようにつける
- [ ] for文で書いているのにcountを取っているところはないか→foreachに書き換え可能な箇所はないか
- [ ] 文字列の連結が複数の場合には、implodeなどの関数でまとめているか
- [ ] 返り値がboolのメソッドを使った判定に対してif文でtrue, falseを使っていないか→ブロック文で書けるはず
- [ ] 入っているプロジェクトに多い書き方に対して違う書き方をしていないか
- [ ] in_arrayなどを使っている場合は、厳密比較となっているか
- [ ] 定数で、かつ条件式にも入力されるような値は外だししているか
- [ ] ガード節を使った方が綺麗に読みやすくなる箇所はないか
- [ ] 再代入している箇所はないか
- [ ] 1行が横に長くなり過ぎていないか。(80文字以上であれば、長すぎると言える)


### ユニットテスト

- [ ] ユニットテストはなるべく単一目的のテストになるように設計されているか
- [ ] ユニットテストのメソッド名は命名規則に沿っているか
- [ ] エラーの場合のテストはあるか
- [ ] Mockのメソッド名が意味もなく、違うメソッド名になっていないか


## コードリディング

- [ ] 親のクラスがある場合は子クラスで少なくとも子クラスで使っている箇所は適切に使われているか


## その他

- [ ] 余計なvar_dumpなどデバッグした跡が残っていないか
- [ ] インフラで一挙変更をお願いする場合は、例外的な設定がないかを先に調査し、ある場合は一挙変更をそこからのぞいてもらう必要がある旨を伝える。
- [ ] ログを出す箇所の権限が変更によって書き変わったりしていないか


# 参考リンク

- [Python 1 行が 79 文字以内である理由と 1 行を最大 79 文字以内に抑える方法](http://nihaoshijie.hatenadiary.jp/entry/2018/01/01/110921)
MSX Cとアセンブラの実験

Cでオブジェクトを作ってアセンブラのように実行してみるテスト。

```hello1.c
/*
z88dk / WebMSX
zcc +msx -lndos -ohello1.bin --list -create-app hello1.c
*/

void main()
{
	puts("hello,\r\nworld one");
}
```

```hello2.c
/*
z88dk / WebMSX
zcc +msx -c --list hello2.c
z80asm -b -r=0xd000 hello2.o
appmake +msx -b hello2.bin --org 0xd000 --fmsx
*/

void __FASTCALL__ myputs(char *str);

void mymain()
{
	myputs("hello,\r\nworld two");
}

void __FASTCALL__ myputs(char *str)
{
#asm
.loop
	ld	a, (hl)
	inc	hl
	or	a
	jr	z, exit
	call	$00a2		; CHPUT
	jr	loop
.exit
#endasm
}
```

hello1.bin 651バイト
hello2.bin 38バイト

```hello2.dmp
 ADDRESS   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F   0123456789ABCDEF 
------------------------------------------------------------------------------
 00000000  21 14 D0 CD 07 D0 C9 E5 7E 23 B7 28 05 CD A2 00   !.ﾐﾍ.ﾐﾉ蛬#ｷ(.ﾍ｢. 
 00000010  18 F6 C1 C9 68 65 6C 6C 6F 2C 0D 0A 77 6F 72 6C   .ﾉhello,..worl 
 00000020  64 20 74 77 6F 00                                 d two.           
```

```hello2.c.lis（抜粋）
16    0000              	SECTION	code_compiler
17    0000              
18    0000              ; Function mymain flags 0x00000200 __smallc
19    0000              ; void mymain()
20    0000              ._mymain
21    0000  21 00 00    	ld	hl,i_1+0
22    0003  CD 07 00    	call	_myputs
23    0006  C9          	ret
24    0007              
25    0007              
26    0007              
27    0007              ; Function myputs flags 0x00000208 __smallc __z88dk_fastcall
28    0007              ; void myputs(char *str)
29    0007              ; parameter 'char *str' at 2 size(2)
30    0007              ._myputs
31    0007  E5          	push	hl
32    0008              .loop
33    0008  7E          	ld	a, (hl)
34    0009  23          	inc	hl
35    000A  B7          	or	a
36    000B  28 05       	jr	z, exit
37    000D  CD A2 00    	call	$00a2		; CHPUT
38    0010  18 F6       	jr	loop
39    0012              .exit
40    0012  C1          	pop	bc
41    0013  C9          	ret
```

![WMSX Screen (1).png](https://qiita-image-store.s3.amazonaws.com/0/257554/f0e22383-046b-23de-4ece-456b914c1f03.png)
【Wordpress】トップページ記事一覧の「もっと見る」リンクの設置の方法

トップページにページャー(前へ/1/2/3/・・・次へ)を設置せず、
「もっと見る」リンクで次ページの内容を追加読み込みをする方法です。

投稿記事一覧の取得方法は「pre_get_posts」を使います。
「WP_Query」で取得すると、/page/2が４０４エラーになってしまうので、「pre_get_posts」を使うことをおすすめします。

### pre_get_postsでの記事一覧取得方法
【【wordpress】pre_get_postsを使ってみませんか？】
https://qiita.com/_ruka_/items/e14280d34eddf49efad1#pre_get_postsのご提案

【pre_get_postsでメインクエリを制御する ｜ Tips Note by TAM】
https://www.tam-tam.co.jp/tipsnote/cms/post9420.html


### 「もっと見る」リンク部分

```php
<?php if($paged < $wp_query->max_num_pages): ?>
<div id="next">
    <p><a href="<?php echo next_posts($wp_query->max_num_pages, false); ?>">もっと見る</a>
    </p>
    <p><img id="loading" src="<?php echo get_stylesheet_directory_uri() ?>/images/loading.gif" alt="読み込み中">
    </p>
</div>
<?php endif;?>


<script>
    var maxpage = <?php echo $wp_query->max_num_pages; ?>;
    jQuery( '#loading' ).css( 'display', 'none' );　 // ローディング画像は一旦消す。
    jQuery.autopager( {
        content: '.itiran dl', // 読み込むコンテンツ
        link: '#next a', // 次ページへのリンク
        autoLoad: false, // スクロールの自動読込み解除
        start: function ( current, next ) {
            jQuery( '#loading' ).css( 'display', 'block' );
            jQuery( '#next a' ).css( 'display', 'none' );
        },
        load: function ( current, next ) {
            jQuery( '#loading' ).css( 'display', 'none' );
            jQuery( '#next a' ).css( 'display', 'block' );
             if( current.page >= maxpage ){ //最後のページ
            　　 jQuery('#next').hide(); //次ページのリンクを隠す
      　　　　     }
        }
    } );
    jQuery( '#next a' ).click( function () { // 次ページへのリンクボタン
        jQuery.autopager( 'load' ); // 次ページを読み込む
        return false;
    } );
</script>

```
CloudReadyにflatpakでVSCodeをインストール

# 序
CloudReady v68.3.26でCtrl+Alt+Tでcroshを開いて、shellに入って、/usr/binとか眺めてたらflatpakが入ってたのでVSCodeが入れられないかなと試してみたらあっさりインストールできました。

# インストール手順
[flathub](https://flathub.org/)に行って、インストールしたいアプリのページを開いてINSTALLボタンをクリックすると～.flatpakrefファイルが保存されます。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/23513/f463dd31-3804-564d-6ace-43acc30d318e.png)
ファイルアプリから～.flatpakrefファイルを開くとインストールが開始されるので、あとは終わるのを待つだけ。

# インストール手順(手入力)
flatpak remote-addでflathubを追加してflatpak installでVSCodeをインストールするだけというお手軽さ。
```追記:
最初はこの方法でやったけど、実はターミナル開くまでもなく上記の方法で良かったという落ち。
消すのもなんなので残しておきます。
```

> sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
> sudo flatpak install flathub com.visual.studio.code

途中で何やら聞いてきますが全部yでok。

![Screenshot 2018-09-08 at 16.50.34.png](https://qiita-image-store.s3.amazonaws.com/0/23513/47bad28d-c46c-859f-d2d5-3cd644548e6e.png)

以上でインストール完了。

# 起動方法
ランチャーにVSCodeのアイコンが追加されるのでごく普通に起動。

![Screenshot 2018-09-08 at 16.51.09.png](https://qiita-image-store.s3.amazonaws.com/0/23513/5597f63e-4f26-c62c-aeb5-950369f0fecc.png)

各種拡張機能入れて日本語化も問題なし。
![Screenshot 2018-09-08 at 17.png](https://qiita-image-store.s3.amazonaws.com/0/23513/10999d33-b2de-8a01-0893-28cfc74b952c.png)

# 問題点
動くことは動くんですけど、いろいろと不満な点も多々。

## シェルフに固定できない&アイコンがVSCodeじゃない
chromeアプリだとシェルフに固定できますが、
![Screenshot 2018-09-08 at 17.09.33.png](https://qiita-image-store.s3.amazonaws.com/0/23513/31b7e3a7-b4de-eeb9-f4e3-96a1e17401c9.png)
linuxアプリだとシェルフに固定できないみたいです。あと、アプリアイコンが(O)になってる。
![Screenshot 2018-09-08 at 17.09.41.png](https://qiita-image-store.s3.amazonaws.com/0/23513/f922b464-c620-7a36-d756-5401f921bd7f.png)

## 起動オプションをどうにかしたい
**ルートフォルダを開いた状態**で起動するので、こんなに管理しきれないって文句言われます。
VSCodeの起動設定は**/var/lib/flatpak/exports/share/applications/com.visualstudio.code.desktop**の中の

> Exec=/usr/bin/flatpak run (略) --reuse-window @@ %F @@

という行に記述されていて、どうも最後の"**@@ %F @@**"が悪さしてるみたいなのでそれをsudo viとかで削除したのちログインしなおせば適用され、毎度ルートフォルダを開くことはなくなります。
が、VSCodeが更新されると上記ファイルも書き換わって元に戻るらしく、ルートフォルダ開くのが再発します。

回避方法が何かないかなと調べてみたら、環境変数XDG_DATA_DIRSに*.desktopファイルの置き場所が設定されていて、個人用だと ~/.local/share/flatpak/exports/share/ が置き場所みたいなので、なければ適宜作って、/var/lib/(略)/com.visualstudio.code.desktop をそこにコピーして中身の余計なパラメータを削除してやれば良さそう…ではあるんだけど、どうにもうまく行かない。
そもそもcom.visualstudio.code.desktopなんて長い名前の必要もないからvscode.desktopに変更して、中身の名前定義もName=VSCodeにしてやればランチャーに"VSCode"って名前のアイコンが追加されるはずだよねと思ったんだけど再起動してもさっぱり出てこない。
freedesktopを利用してるのだからupdate-desktop-databaseで情報更新したいところだけど実行ファイルが入ってないので無理。一体どうやってランチャーの更新をしてるのやら。
VS Codeでエンコーディングを自動判別する

# VS Code でエンコーディングを自動判別する方法
## ここで記載すること
- VS Codeでファイルを開く文字化けすることがありますよね。
- これは、UTF-8　がデフォルトなので、ShiftJISなどだと文字化けしちゃうことが理由になっていることがあります。
- 手動で文字コードを変更する方法もありますが、それは面倒ですね。
- ここでは、自動で判別する設定を記載します。

## 設定方法
- [ファイル]⇒[基本設定]⇒[設定]を選択します
- すると[User Settings]タブが開きます
- ここで検索ボックスに「encoding」と入力する

> // 有効な場合、ファイルを開くときに文字セット エンコードをエディターが推測します。言語ごとに構成することも可能です。
>   "files.autoGuessEncoding": false,

- が表示されますね。
- "files.autoGuessEncoding": false,　の部分を選択して
- true にすればOK
- お試しください
Rails Capistrano deployエラー　SocketError: getaddrinfo: Temporary failure in name resolution

# Capistrano deploy時に発生する SocketError: getaddrinfo: Temporary failure in name resolutionのエラーの原因と解決方法

## エラーメッセージの意味
ソケットエラー： 名前解決のために一時的に失敗しました。

## エラー原因
~/.ssh/know_hostsファイルに記載されているリモートサーバーへのsshによる接続情報が古くなっているために、ssh接続できずにエラーになってしまいます。

## 解決方法
`ssh-keygen -R remote_host_name`
上記コマンドにより古いssh接続情報を削除する。
(又は手動で `vi  ~/.ssh/known_hosts`でファイルを開いて、対象のリモートサーバーのhostnameが書かれた該当の1行を削除する。)
その後再度sshコマンドを実行する。
これにより、新規ssh接続とみなされて、再びssh接続用の情報を known_hostsファイルに保存するか確認するメッセージが表示されるので 'yes'と答えて保存する。

↓古いssh情報削除後にsshを再度実行した時のターミナルの出力表示例

```
$ ssh ***.**.***
The authenticity of host ' ()' can't be established.
RSA key fingerprint is .
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '' (RSA) to the list of known hosts.
's password: 
```

## 参考
[Qiita:SSH接続エラー回避方法：.ssh/known_hostsから特定のホストを削除する/削除しないで対処する3つの方法](https://qiita.com/grgrjnjn/items/8ca33b64ea0406e12938)