OmniAICreator/Qiita-1.07M huggingface dataset:
作成したGit Repositoryにブランチを作成する（Visual Studio 2017を使用）

[こちら](https://qiita.com/misuzoo/items/2e6811d7e95af812dfdd)の続きです。
「develop」ブランチを作成してみます。

#####1.チームエクスプローラーの[ブランチ]を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/6f9bb27a-aa37-4f71-a3c5-b51073ca4fbb.png)

#####2.[新しいブランチ]を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/af993f31-bf35-0003-c8c2-6c64c6ac633f.png)

#####3.上のboxには「develop」を入力、下のboxは「master」を選択し[ブランチの作成]を実行
上のboxが新しく作成したいブランチ、下のboxで選択したものが新しく作成するブランチの元ブランチになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/371a353d-c6a2-c44e-ff42-8fe566b97229.png)

developブランチが作成されました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/9005bb2f-4640-2985-cec7-b273bee31836.png)

まだリモートリポジトリへ反映されていないため、リモートリポジトリへプッシュします。

#####4.チームエクスプローラーの[同期]を選択し、[プッシュ]を実行
リモートにも作成したブランチが反映されました。remotes/originの下に一覧されているものが、リモートのブランチになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/7daa5088-1c04-26f4-a4c0-6e3dae12ea27.png)
「WebRTC入門者LT会 #3」に参加してきました！

WebRTCはあまり詳しくないですが、リモートワークが活性化される昨今、
この技術は広がりがあると考え、またビデオチャットアプリを作ってみたい気持ちで参加しました。
https://webrtc.connpass.com/event/98122/

## ゲスト講演1『ライブ配信・ビデオ通話SDKチュートリアル』Agora.io SDK
発表資料：https://qiita.com/fu-jimoto/items/50d4cea6eee8626e4dc3

・WebRTCの技術に詳しくなくても、比較的簡単に実装できそう。
・サンプルコード豊富（JS以外の言語にも対応）←これは有り難い。
　https://github.com/AgoraIO
・有料（受信する時の時間によって発生）※無料版のトライアルもあるらしいです
・サポートがしっかりしてそう
・事例：チャットワーク
　→最近、ビデオチャットがきれいになったと感じていましたが、この技術に変更されたみたいです！


## ゲスト講演2『プログラミング歴1.5ヶ月の初心者がweb会議システムを作った話』
発表資料：https://speakerdeck.com/kolife01/web-conferencing-system2

skywayやfirebaseを使ったライブコーディングをビデオチャットを作成。
ほんの10分ぐらいでした。ライブコーディングはナマものなので緊張するし、凄いです。
skyway使いたくなりました！


後半はLT4本

## LT1 PinP機能をWebRTCで実現できるか検証してみた
https://www.slideshare.net/ssuser129146/pinpwebrtc

## LT2 WebRTCを使ったtoCサービスにおけるBaaS選定と、運用上のトラブル紹介
https://speakerdeck.com/p__oka/webrtcwoshi-tutatocsabisuniokerubaasxuan-ding-to-yun-yong-shang-falsetoraburufalseshao-jie
BaaS選定は気になっていたので、とても勉強になりました！

##LT3 Unified Plan時代のWebRTC（半）手動シグナリング

##LT4 WebRTCにおけるオーディオとの付き合い方
作成したGit Repositoryのリモートリポジトリへのプッシュ（Visual Studio 2017を使用）

[こちら](https://qiita.com/misuzoo/items/1fafb79d2f71e64c3ecb)の続きで、今度はリモートリポジトリへプッシュしてみます。

#####1.チームエクスプローラーの[同期]を選択

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/f7a69f6f-38a4-6c00-0738-ed07b223fe40.png)

#####2.[プッシュ]を実行
[出力方向のコミット]の下にはローカルコミットの一覧が表示されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/123788f3-ae19-20ca-5439-c8a86a212aee.png)

しばらく待つとプッシュが完了します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/1fd0c14a-64c9-3874-b388-6f6f6f61eca0.png)

Azure DevOps上のプロジェクトにブラウザからアクセスすると、リモートリポジトリへプッシュされていることが確認できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/9a113c7f-0e69-3b7e-128b-a7b67a746c47.png)
作成したGit Repositoryへのローカルコミット（Visual Studio 2017を使用）

[こちら](https://qiita.com/misuzoo/items/b11817629b286e0840f7)で作成したプロジェクトにサンプルコードをコミットしてみます。

#####1.チームエクスプローラーの接続の管理を選択して、先ほど作成したプロジェクトを選択

   ![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/2d256e99-3f9c-fe52-072e-8a5202853e71.png)

#####2.ローカルに作成したプロジェクトのリポジトリを登録

#####3.新しく登録したいプロジェクトのファイルを2で登録したリポジトリ内に配置

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/e6ecbb34-75c2-ac26-a4b3-ffaf81c92d7e.png)

#####4.チームエクスプローラーを開いてプロジェクトの[変更]を選択

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/2a3dda47-35e4-20aa-6228-43bbdd8d12ec.png)

#####5.コメント欄にコメントを記載し、[すべてをコミット]を実行

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/d9a33895-af21-472d-2c3e-c7e10e9993cf.png)

#####6.以下のエラーが出てしまい、コミットに失敗

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/6fa959f4-4639-13a5-3c90-c4b277adaef3.png)

#####7.[こちら](https://stackoverflow.com/questions/47460039/vs-2017-git-local-commit-db-lock-error-on-every-commit)のサイトを参考に「無視および属性ファイル」の設定を実施
<img src="https://qiita-image-store.s3.amazonaws.com/0/232585/704736cf-f3a9-c614-8353-07a115254500.png" width="300">

#####8.再度、プロジェクトの[変更]を選択すると以下のように対象ファイルが減り、
自分が作成したプロジェクトファイルだけになっています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/fd8918dc-f1f8-34a3-4c9c-220ab8f7cf38.png)

#####9.[ステージング済みをコミット]を実行
今度はローカルコミットに成功しましたただ、ステージング済みの変更のほうしかコミットされていなかったので、コメント入力し、[すべてをコミット]を実行し再度コミットしました。

この時点ではローカルにコミットしただけなので、作成したAzure DevOps上のプロジェクトを参照すると以下のようにまだcodeは登録されていません。
次はリモートリポジトリにローカルコミットの内容をプッシュしてみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/232585/ee8d635f-7d45-3d2e-5da6-21cde566b942.png)
bootstrap3のmodalウィンドウを横スクロールできるようにする

bootstrap3のmodalにテーブルを表示したら、横スクロールできなかった。
縦スクロールバーを表示する方法はドキュメントにあったけど、横スクロールはなかったのでメモ。
![スクリーンショット 2018-10-30 8.54.00.png](https://qiita-image-store.s3.amazonaws.com/0/124609/a2f149be-2c9c-0d20-6191-dfdd5f16f2a8.png)

```html
<!-- Modal -->
<div class="modal fade bd-example-modal-lg" id="{{ $primaryKey }}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog　modal-xl modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">primaryKey： {{ $primaryKey }}</h5>
                <h5 class="modal-title" id="exampleModalLabel">rowNo： {{ $rowNo }}</h5>
            </div>
            <div class="modal-body">
                <table class="table table-bordered">
                    <thead>
                        <tr>
                            <th>{{ $header }}</th>
                        </tr>
                    </thead>
                    <tbody>
                    <tr>
                        <td>{{ $col }}</td>
                    </tr>
                    <tr>
                        <td>{{ $col }}</td>
                    </tr>
                    </tbody>
                </table>
                <small>青いセルは旧テーブルに存在しないカラムです</small>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>
```

modal-bodyにwithとoverflow-xの設定を追加する

```diff
</div>
- <div class="modal-body">
+ <div class="modal-body" style="width: 100%; overflow-x: auto;">
    <table class="table table-bordered">
        <thead>
```

laravel5.5で作ったdiffツールです
初めは新のデータが一覧表示されていて、行番号をクリックすると新旧の比較がmodalで開きます

```html
modal呼び出し部分
<td>
    <a href="#bannerformmodal" data-toggle="modal" data-target="#{{ $primaryKey }}">{{ $rowNo }}</a>
</td>
```
DataURIとBlobURLの違い

# Blobとは

「Blob」は一般的なバイナリデータをJavaScriptで扱えるようにしたり、新しく生成することができます。FileAPIを用いてデータを読み込むこともできる。

# バイナリファイルをURLにする

## DataURL

データをURL(data:で始まる文字列)で表現するための仕組み。バイナリファイルの場合はBase64という形式でエンコードする。形式はURLなのでimg要素のsrc属性に入れると画像として表示できる。cookieに保存したりサーバーに渡したりできる。

## BlobURL

DataURLを軽量化したもの。それ自体がデータなわけではなくブラウザに保存したものにアクセスするためのもの。
AWS(ECS)でスケジューリングするときに注意すべき、通常のcronとの違い

# 背景

cronは使い慣れてるつもりだったが、ECSのFargateでスケジューリングタスクを実行しようとしたときに、ハマったので、備忘録として。


# 曜日の項目
```
Parameter ScheduleExpression is not valid
```
このエラーでハマりました。


普通にLinuxでcronを動作させるとき、

例えば9時30分に実行させたい場合、

```
30 9 * * *  command
```

となると思いますが、

AWSのcron表現では、

```
cron(30 9 * * ? *)
```
という形になります。

左から、分、時、日、月、曜日、年を表します。

注意すべき点は、
- スペースで区切られた項目が、**6つある**
- 曜日の部分を任意にしたい場合は、**\*ではなく?を**入力する

の二点です。

# JST(日本時間)ではなく、UTC(協定世界時)になっている
リージョンが東京であっても、cronの書式の単位はUTCになっています。

なので、日本時間から9時間遅れているに注意が必要です。

計算は、例えば

```
9:30(JST) ⇔ 0:30(UTC)
2:00(JST) ⇔ 17:00(UTC)
```
のようにすれば良いです。


## おまけ

[ここ](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html)に全部書いてある。
BluetoothのSPPを使ったソフトではまった

#Bluetoothを使ってシリアル通信するソフト
作ってたんだけど、なんでかCreateFileで失敗する。
エラーコードは「セマフォがタイムアウトした」みたいなやつ

#試行錯誤
PCやデバイスを再起動してみたり、
いろいろしたけど解決しない

#解決？
同じ症状で困っている人がいて、
その人はCreateFileを繰り返し実行していた。
僕もやってみたらなぜかつながるようになった…

リトライするときに1秒sleepしてるけど
いらないかもしれない
ReactNativeで引っ張ってデータ更新


### APIの準備

とりあえず/api/whattimeというリクエストで現在の時間を返すAPIを実装します。言語は何でも。

```json
{"status":"OK","date":"2018-10-29 23:37:59"}
```

### Laravelでのサンプル

私はLaravelで下記のように実装してみました。

```php:web.api
Route::get('/whattime',function(){
    $res['status'] = 'OK';
    $res['date'] = date('Y-m-d H:i:s');
    return \Response::json($res);
});
```


### ReactNativeでの実装

Mountされたときの日時になっていますが、引っ張ると更新されます。
ポイントはonRefresh()が実装されたコンポーネントを利用すること。FlatListとかでもいいのですが、今回はListではなく普通のテキストを更新したかったのでScrollViewを利用してみました。

```js:App.js
import React from 'react';
import { StyleSheet, Text, View, ScrollView, RefreshControl } from 'react-native';

export default class App extends React.Component {

  state = {
    refreshing: false,
    status: 'N/A',
    datetime: '0000-00-00'
  }

  componentDidMount(){
    this._fetch();
  }

  _fetch = () => {
    fetch('http://localhost:8000/api/whattime')
      .then((response) => {
        this.setState({
          refreshing: true
        });
        return response.json();
      })
      .then((responseJson) => {
        this.setState({
          refreshing: false,
          status: responseJson['status'],
          datetime: responseJson['date']
        });
      })
      .catch((error) => console.log(error));
  }

  render() {
    return (
      <View style={styles.container}>
        <ScrollView
          refreshControl={
            <RefreshControl
              refreshing={this.state.refreshing}
              onRefresh={() => this._fetch()}
            />
          }
        >
          <Text>Status:{this.state.status}</Text>
          <Text>DateTime:{this.state.datetime}</Text>
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingVertical:60,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

```

## 確認

こんな感じ。（○がでてるのが関係ないです）。

![スクリーンショット 2018-10-30 8.45.13.png](https://qiita-image-store.s3.amazonaws.com/0/55188/f6617954-827b-244b-c37b-3edc8da6ce6a.png)


## メモ

[最後まで来たら追加ロード](https://qiita.com/zaburo/items/a39c071ea2dab0dcec8b)とかも簡単にできます。便利。
新しい画面になったhomeアプリからgooglehomeのIPアドレスがわかる

# IPアドレスどこやねん。。。

2018/10/28
googlehomeのhomeアプリのインターフェスが変わってIPアドレスの場所がわからなくなってしまった人へのTips。ヘルプにもなかったので...。

# この記事を見てできること
新しい画面になったhomeアプリからgooglehomeのIPアドレスがわかる


1. デバイスのgooglehomeの絵を選択。
<img width="768" alt="Screenshot_20181028-130207_1.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/171011/ccb6fae5-a37b-46fe-2aab-4ba28eb7bff8.jpeg">


2. 音量の画面が出たら右上の歯車マークを選択
<img width="768" alt="Screenshot_20181028-130210_1.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/171011/7d39f613-d1f9-b6a8-a406-4ff5615ed5e4.jpeg">

3. 最下部にIPアドレスが見つけられる
<img width="768" alt="Screenshot_20181028-130218_1.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/171011/a3179665-bdc9-ba8f-6f32-b74f93140a11.jpeg">

以上。


# あとがき
地味にラトックスと連携してる素振りを見せている...(電気とかを消せるようになっている)
次期googlehomeでの赤外線とネットブート系のシステム実装はよ
Slackのファイル共有を利用するとBOMが消える

会社でSlackを経由してファイル共有すると、
BOM付きファイルからBOMが消える事件を見かけたので、自分でも再現するか試してみる。

## 動作環境

2018年10月30日時点でのChrome経由でのSlack

## 手順

BOM付きファイル作成

```
$ cat <(printf "\xEF\xBB\xBF sample text.") > BomTest.txt
$ file BomTest.txt
BomTest.txt: UTF-8 Unicode (with BOM) text, with no line terminators
```

Slackにテキストをアップロード

![スクリーンショット 2018-10-30 8.00.40.png](https://qiita-image-store.s3.amazonaws.com/0/25578/9bee135d-e1fd-a784-83f0-0533869f9bce.png)

Slackにアップロードしたテキストをダウンロード

![スクリーンショット 2018-10-30 8.01.21.png](https://qiita-image-store.s3.amazonaws.com/0/25578/bf2d05b9-e8aa-606b-cae6-741f5239e4b1.png)

ダウンロードしたファイルのBOMを確認

```
$ file  ~/Downloads/BomTest.txt
/Volumes/MHDD/Users/mitsuaki1229/Downloads/BomTest.txt: ASCII text, with no line terminators
```

ASCIIに変換されてる...🤔

## 感想

Excelのために、BOM付きUTF-8で文字化けしないCSVを作成してる場合、共有方法には気をつけよう。
.zshrcにコマンドエイリアスを定義してbundle execをbeと省略可能にする方法

Zsh導入のついでに、`bundle exec`を省略させたいと思いコマンドエイリアスを設定しました。その際に、直感的に自分がわかりやすかった設定方法を書きます。

---

#### 目的
`bundle exec rails s`とか毎回`bundle exec`と入力するのが面倒くさいので、
Zshでコマンドエイリアスを設定して`be rails s`だけで、サーバーを立ち上げられたりできるようにする。

Zsh公式　http://zsh.sourceforge.net/

---

#### 1. 隠しファイル、フォルダの表示させる(***.zshrc***を表示させる)
環境 / macOS High Sierra -v 10.13.6

Finderのホームへ移動
`command + shift + .`
を同時押しすると、

![IMG_0019.jpg](https://qiita-image-store.s3.amazonaws.com/0/277090/d189c926-3b76-cfe8-aea6-1c3d56751b82.jpeg)

#### 2. Zshの設定ファイルである***.zshrc***を開く
今回は`bundle exec`を`be`のように、省略して入力できるようにすることが目的のため、
`alias be='bundle exec'`
と最終行に入力して保存。その際、`=`の前後にスペースは空けないように注意してください。

`exit`と入力して、Zshを再起動をさせて設定を反映させる。

#### 3. お試しあれ
`be rails s`など`bundle exec`の入力が求められる任意のコマンドを入力して、無事に動けば成功です。

---
ご指摘などあれば、ご教授いただけると幸いです。
ご一読ありがとうございました。
なぜTypeScript（またはその他の型付できるAltJS）を使うのか？

TypeScript + webpack で kintone カスタマイズ環境を構築する際の覚書です。

#なぜTypeScriptを使うのか？
kintoneのカスタマイズをJavaScriptでやっていると、単純なところで思ったように動かなくて時間がかかる。

例えば下記のようなところ。

1. 一覧画面のViewIDを取得する場面で、レコード一覧画面の表示後イベントのeventプロパティ中のviewIdは数値。
2. 一覧の設定の取得APIを使って取得する一覧のID（views.（一覧名）.id）は文字列。

```javascript
// views.一覧名.id は文字列。 record.viewIdは数値
if (views.一覧名.id === record.viewId) { return; } // 特にエラーは出ない。常にfalseなのでreturnすることは無い。

```

1.と2.をif文で比較しようとしても、エラーにもならず何か上手くいかないな？と結構悩む。
しばらくして、多分型が違うのかな？と気づいてドキュメントを確認して、型変換して。。。
それなら、型付できる言語で書きたいですよね。

次のコードの様に、自身で値を設定しているのなら間違いに気づくと思いますが、外のライブラリなどから値をセットしてとなると、なかなか気づけない。

```javascript
const num = 100;
const str = "100";
if (num === str) {
    console.log("match!");
} else {
    console.log("unmatch!");
}
```
TyepScriptのコンパイラを通すと、上記もエラーとして知らせてくれます。

```
$ ./node_modules/.bin/tsc ./ts/test01.ts
ts/test01.ts:3:5 - error TS2367: This condition will always return 'false' since the types '100' and '"100"' have no overlap.

3 if (num === str) {
      ~~~~~~~~~~~
```

例があまり良く無いですが、もっと言うとこの様に書いてコンパイラを通さなくても分かる方が気持ち良い。

```javascript
const num: number = 100;
const str: string = "100";

let matchStr = function testMatch (num: number, str: number) :string {
    if (num === str) {
        return "match";
    } else {
        return "unmatch";
    }
}
console.log(matchStr(num, str));
```
```
./node_modules/.bin/tsc ./ts/test02.ts
ts/test02.ts:11:27 - error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

11 console.log(matchStr(num, str));
```
こんな感じで、お知らせしてくれると嬉しい。


#参考リンク
- [Visual Studio Codeを使いこなせ! フロントエンジニア必須の拡張機能7選](https://ics.media/entry/18544)
- [最新版TypeScript 3.0+Webpack 4の環境構築まとめ(React, Vue.js, Three.jsのサンプル付き)](https://ics.media/entry/16329)
- [TypeScript チュートリアル](https://qiita.com/EBIHARA_kenji/items/31b7c1c62426bdabd263)
- [最新版で学ぶwebpack 4入門 – JavaScriptのモジュールバンドラ](https://ics.media/entry/12140?gclid=Cj0KCQjwguDeBRDCARIsAGxuU8ZTtzolixJ-2P6atufheE18RLkcVWExEcNzxK_VLzeRrZNr6IMSX7gaAvjlEALw_wcB)
- [webpack 4 入門](https://qiita.com/soarflat/items/28bf799f7e0335b68186)
- [最新版で学ぶwebpack 4入門 – Babel 7でES2018環境の構築(React, Vue, Three.js, jQueryのサンプル付き)](https://ics.media/entry/16028)
- [Revised Revised 型の国のTypeScript](http://typescript.ninja/typescript-in-definitelyland/index.html)
Spring Bootでクラスパスを追加する方法

前回、MessageSource関連を調査しているときに、メッセージを管理しているプロパティファイルを、Spring Boot プロジェクトの外に配置する必要がありました。
[SpringのMessageSourceをリロードする](https://qiita.com/d-yosh/items/d03866e4c2b9f1516903)

その際、Spring Bootでクラスパスを追加する方法を調べたところ、方法がいくつかあったのでまとめてみようと思います。

起動方法によって設定が違ったり、設定方法がいくつかあったりします。

# 環境
* Spring Boot 2.0.6.RELEASE

# `mvn spring-boot:run` で起動する場合
Spring Boot Maven Plugin を利用して、アプリケーションを起動する場合です。
以下のいずれかの方法で追加できます。

## 起動引数で指定する
パスはカンマ区切りで複数指定することができます。

```
mvn spring-boot:run -Dspring-boot.run.folders=[パス]
```

## pom.xmlに書く

```xml:pom.xml
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <folders>
            <folder>[パス]</folder>
        </folders>
    </configuration>
</plugin>
```

# Executable Jar の場合
Executable Jar を作成し、`java`コマンドで実行する場合です。
ちなみに以下のようにしてもクラスパスは追加されません。

```:ダメな例
java -cp [パス] -jar jarFile
```
`java`コマンドは`-jar`が指定された場合、`-cp`を無視します。

## Mainクラスを変更する

Mainクラスとして`PropertiesLauncher`を利用すれば、クラスパスを追加することが可能です。

Spring Boot Maven Pluginを利用している場合は`layout`に`ZIP`か`DIR`を設定することで、`PropertiesLauncher`を利用することができます。

```xml:pom.xml
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <layout>ZIP</layout>
    </configuration>
</plugin>
```


続いて、追加するクラスパスに関する設定ですが、いくつかの設定方法があります。
優先順位が高い順に記載していきます。

## システムプロパティで指定する
起動時に`-Dloader.path`でクラスパスを追加できます。

```
java -Dloader.path=[パス] -jar jarFile
```

ちなみに、`-jar` より後ろに`-Dloader.path=[パス]`のように実行してうまく行かず、しばらく悩みました。
`java`コマンドは`java [-options] -jar jarFile [args...]`という順序で指定しないといけません。

## 環境変数で指定する
環境変数`LOADER_PATH`に設定します。
起動は普通に`java`コマンドを利用すればOKです。

```:windows
set LOADER_PATH=[パス]
```

```:linux
export LOADER_PATH=[パス]
```



## プロパティファイルで指定する
resources直下に`loader.properties`というファイル名で設定ファイルを配置します。
こちらも起動は普通に`java`コマンドを利用すればOKです。

```properties:loader.properties
loader.path=[パス]
```

なお、ファイル名や配置場所は設定によって変更することもできます。


## マニフェストファイルで指定する
マニフェストファイルに`Loader-Path`を指定することで、クラスパスを追加できます。
起動は普通に`java`コマンドで。

Maven Jar Plugin を使うなら以下のように設定すればOKです。

```xml:pom.xml
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <archive>
      <manifestEntries>
        <Loader-Path>[パス]</Loader-Path>
      </manifestEntries>
    </archive>
  </configuration>
</plugin>
```

# まとめ
Executable Jar を利用する場合には、いくつか方法がありますが、起動時に設定が可能なシステムプロパティか環境変数がいいのかなーと思いました。

プロパティファイルやマニフェストファイルの場合、コードにパスがべた書きされてしまうので、環境ごとに設定が違うとかだとやりづらい気がします。

もしくは、プロパティファイルを環境ごとに作成して、起動時にシステムプロパティでプロパティファイル名を指定するとかですかね。
離散フーリエ変換，高速フーリエ変換，標本化定理

# 離散フーリエ変換 (DFT : Discrete Fourier Transform)
非連続（離散）なデジタル信号の周波数解析に使われる．コンピュータで扱う波形データは数の配列であるので，DFTによって解析することができる．

```math
f(t) = \sum_{n=-∞}^{∞} a_ne^{j\frac{2\pi}{N}nt}
```

# 高速フーリエ変換 (FFT : Fast Fourier Transform)
離散フーリエ変換を高速に行うためのアルゴリズム．

# 標本化定理
 - サンプリング周波数`f_s`は原信号に含まれる最大周波数`f`の2倍以上でなければならない．
 - 復元可能な最大周波数`f_s`をナイキスト周波数と呼ぶ．
 - 高周波を含む源信号を低いサンプリング周波数で標本化した場合，高周波がアンダーサンプリングされて低周波の折り返し雑音となる．これをエイリアシングと呼ぶ．  

例えばサンプリング周波数が44100Hzのとき，原信号の復元可能な最大周波数は22050Hzである．最大周波数22050Hzの原信号についてサンプリング周波数36000Hzで標本化すると，原信号には存在しない36000-22050=13950Hzが折り返し雑音として現れてしまう．

# 短時間フーリエ変換 (STFT : Short-Time Fourier Transform)
本来，理論上フーリエ変換は無限区間について処理されるべきだが，実験値等からフーリエ係数を求める際に窓関数をずらしながらかけて，有限区間についてDFTを行うこと．
Lem のビルド方法

### Lem のビルド

Lem は初回起動時に自動でビルドが行われます。
そのため、基本的には手動でビルドを行う必要はありません。

````sh
$ lem
Making core for Roswell...
building dump:/Users/me/.roswell/impls/x86-64/darwin/sbcl-bin/1.4.12/dump/lem-ncurses.core
````

ビルドに使用するソースコードは `~/.roswell/local-projects/cxxxr/lem` から取得されます。
このソースコードは `ros install cxxxr/lem` した際にインストールされたものです。
`ros update lem` した際も、このソースコードが更新されます。

ビルドされたイメージは、`~/.roswell` 以下に出力され、2 回目以降の起動時にはこのイメージが使用されます。

````sh
~/.roswell/impls/x86-64/darwin/sbcl-bin/1.4.12/dump/lem-ncurses.core 
````

このイメージを削除してから Lem を起動すると、再びビルドが実行されます。

````sh
$ rm ~/.roswell/impls/x86-64/darwin/sbcl-bin/1.4.12/dump/lem-ncurses.core
$ lem
Making core for Roswell...
building dump:/Users/me/.roswell/impls/x86-64/darwin/sbcl-bin/1.4.12/dump/lem-ncurses.core
````

イメージの削除は `ros delete dump` コマンドでも実行できます。

````sh
$ ros delete dump lem-ncurses
````

ビルドは `ros build` コマンドで明示的に実行することも可能です。
その場合は、`.ros` ファイルを指定する必要があります。

````sh
$ cd ~/.roswell/local-projects/cxxxr/lem
$ ros build roswell/lem-ncurses.ros
Making core for Roswell...
building dump:/Users/me/.roswell/impls/x86-64/darwin/sbcl-bin/1.4.12/dump/lem-ncurses.core
````

`ros dump executable` コマンドを使用して、実行ファイルを作成することも可能です。
この場合も `.ros` ファイルを指定します。

````sh
$ ros dump executable roswell/lem-ncurses.ros -o /tmp/lem.bin
$ /tmp/lem.bin
````
VSCodeの統合ターミナルでもターミナルのUndoを使いたい

iTermなどでは`Ctrl + _`でUndoができますが、VSCodeの統合ターミナルではうまく動きませんでした。
ただ、VSCode v1.28から`workbench.action.terminal.sendSequence`というコマンドが使えるようになったらしく、この機能でエスケープシーケンスを送ることでUndoのショートカットを作ることができました。
https://code.visualstudio.com/docs/editor/integrated-terminal#_send-text-from-a-keybinding

```json:keybindings.json
{
  "when": "terminalFocus",
  "key": "ctrl+[IntlRo]",
  "command": "workbench.action.terminal.sendSequence",
  "args": { "text": "\u001f" }
},
```
`when`には`terminalFocus`を指定して、ターミナルにフォーカスしているときだけショートカットを有効にします。

日本語キーボードだと、`_`のキーは`IntlRo`になるみたいなので、`key`には`ctrl+[IntlRo]`を指定します。英字配列だとまた別のキーになると思います。
https://www.w3.org/TR/uievents-code/#code-IntlRo

`Ctrl + _`が押されたときに送信されるエスケープシーケンスは`US`の`0x1f`なので、`args`の`text`には`\u001f`を指定します。textには`\u0000`のような形式で書く必要があるみたいです。

VSCodeの統合ターミナルでは一部のエスケープシーケンスが送信されないことがあるみたいなので、`workbench.action.terminal.sendSequence`を使ってショートカットを作ることで作業効率を上げることができそうです。
Railsで外部キー制約を貼る方法

Railsで新規のテーブルを作成したり、カラムを追加したりするときには、マイグレーションを作成しますが、マイグレーションについてはついつい忘れがちなので、今回は外部キー制約の貼り方についてまとめてみました。

ちなみに外部キー制約とは
> 外部キー制約とは、テーブルの指定したカラムに格納できる値を他のテーブルに格納されている値だけに限定するものです。

ということらしいです。

※環境
Rails  **5.2.1**
Ruby   **2.5.0**
DB     **sqlite**

### references
`references`はインデックスは貼ってくれるが、外部キー制約にはならないようです。

```db/migrate/20181029160103_create_children.rb
class CreateChildren < ActiveRecord::Migration[5.2]
  def change
    create_table :children do |t|
      t.references :parent

      t.timestamps
    end
  end
end
```

```sql
CREATE TABLE IF NOT EXISTS "children" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "parent_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
CREATE INDEX "index_children_on_report_id" ON "children" ("parent_id");
```

### index:true
index: trueを加えてもSQL自体に変化はないらしい。

```db/migrate/20181029162344_create_children.rb
class CreateChildren < ActiveRecord::Migration[5.2]
  def change
    create_table :children do |t|
      t.references :parent, index: true

      t.timestamps
    end
  end
end
```

```sql
CREATE TABLE IF NOT EXISTS "children" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "parent_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
CREATE INDEX "index_children_on_parent_id" ON "children" ("parent_id");
```

### foreign_key: true
これでようやく外部キー制約がつきます
CONSTRAINT オプションでForeign keyに名前がつけられます

```db/migrate/20181029162344_create_children.rb
class CreateChildren < ActiveRecord::Migration[5.2]
  def change
    create_table :children do |t|
      t.references :parent, foreign_key: true

      t.timestamps
    end
  end
end
```



```sql
CREATE TABLE IF NOT EXISTS "children" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "parent_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, CONSTRAINT "fk_rails_554cba9b33"
FOREIGN KEY ("parent_id")
  REFERENCES "parents" ("id")
);
CREATE INDEX "index_children_on_parent_id" ON "children" ("parent_id");
```
LeapMotionでparticleを制御する

LeapMotionでつくるコンテンツのメモです。


#LeapMotionの手の動きの取り方
スクリプトによる制御方法を知る場合，以下のドキュメントをみるほうがよいです。
https://leapmotion.github.io/UnityModules/namespaces.html
![image.png](https://qiita-image-store.s3.amazonaws.com/0/282960/76529c82-ea35-9994-a8a1-546d6d3a596c.png)
SDKがアップデートされていて，過去の記事のコードが参考にならない場合もあるのでドキュメントも目を通すといいと思います。


基本的に使うのはController,Frame,Hand,Fingerだという印象を受けました。

以下のスクリプトで，手の握った角度と強さがわかるようなので，ひとまずはこの値を使うと便利そうです。
GrabStrengthは[0,1]のfloat値で，実用上はこっちを使うほうがよさそうという印象。

```
   Controller controller = new Controller();
   private Frame frame;    
	void Update () {
        if (controller.Frame() != null)
        {
            frame = controller.Frame();
            foreach (Hand mhand in frame.Hands)
            {
                Debug.Log(mhand.GrabAngle+":"+mhand.GrabStrength);                
            }
        }
```

#手を広げかたでparticleの動作を制御

```
  Controller controller = new Controller();
    private Frame frame;
    [SerializeField] ParticleSystem particle;
    private void Start()
    {
        particle.Stop();
    }

    void Update () {
        if (controller.Frame() != null)
        {
            frame = controller.Frame();
            foreach (Hand mhand in frame.Hands)
            {
                Debug.Log(mhand.GrabAngle+":"+mhand.GrabStrength);

                if (mhand.GrabStrength < 0.2)
                {
                    particle.Play();
                }
            }
        }
```
最終的に上記のようにすることでparticleの制御を手の動きでできるようにしました。

#参考
- LeapMotionプログラミングガイド
PlayFrameworkで他のWebAPIと連携をするやり方

# 概要
WeekendEngineerというグループの中で9月にPlayFrameworkを使ったTwitterツールの開発をしました。レスポンスが遅くて辛い。。。
[GitHub/ochiai_auto_tweet](https://github.com/seven0525/ochiai_auto_tweets)

![○○っぽいツイートジェネレータ.gif](https://qiita-image-store.s3.amazonaws.com/0/241675/960f1e62-6cf4-e6c7-1a5c-7f48addc8851.gif)


その際にPythonを使ったWebAPIと連携をするためにWSClientを使いました。備忘録のためにもPlayFramework2.6のWSClientを使って外部のWeb APIとやりとりをする方法を残しておきます。


## やりたいこと
+ 以下の仕様のAPIを叩く。
 
| url | response |
|:-:|:-:|
| generate_tweet/:twitter_id | {"tweet": "texttext..."} |

+ 生成されたテキストを取得する

# 実装方法

## コード
```client.TweetGeneratorClient.scala

@Singleton
class TweetGeneratorClient @Inject()(ws: WSClient) extends ITweetGeneratorClient {
  def generateTweet(twitterId: String): Tweet = {
    val request: WSRequest = ws.url("http://127.0.0.1:5000/generate_tweet/" + twitterId)
    val futureResult: Future[String] = request.get().map{
      response => (response.json \ "tweet").as[String]
    }
    val tweetText: String = Await.result(futureResult, Duration.Inf)
    return Tweet.createNewTweet(tweetText)
  }
}

```


## 解説
### wsclientにAPIのURLを設定
WSClientクラスのインスタンスをDIします。

```client.TweetGeneratorClient.scala
@Singleton
class TweetGeneratorClient @Inject()(ws: WSClient) extends ITweetGeneratorClient {
}

```

`ws#url(url: String)`の引数にAPIのURLを指定します。

```client.TweetGeneratorClient.scala
  def generateTweet(twitterId: String): Tweet = {
    val request: WSRequest = ws.url("http://127.0.0.1:5000/generate_tweet/" + twitterId)
  }
```

### レスポンス(JSON)から文字列を抽出
`request#get()`メソッドで取得したresponseのjsonから、"tweet"というキーの値を取得します。
`(response.json \ "key名").as[String]`で、指定したキーを文字列で抜き出せるみたいです。

```client.TweetGeneratorClient.scala
  def generateTweet(twitterId: String): Tweet = {
    val request: WSRequest = ws.url("http://127.0.0.1:5000/generate_tweet/" + twitterId)

    val futureResult: Future[String] = request.get().map{
      response => (response.json \ "tweet").as[String]
    }
    val tweetText: String = Await.result(futureResult, Duration.Inf)
    return Tweet.createNewTweet(tweetText)
  }
```

###ちなみに
以下のコードは`{person: {name: ""}}`のようなネストしたJSONから文字列を取得する例です。
（公式ドキュメントより拝借）

```scala
val futureResult: Future[String] = ws.url(url).get().map {
  response =>
    (response.json \ "person" \ "name").as[String]
}
```

他にもJavaでおなじみJacksonの[scala-module](https://github.com/FasterXML/jackson-module-scala)も使えます。

# 最後に
これでPluginの出ていないような外部APIを叩いて、レスポンスを受け取ることができますね。Webサービスから提供されるAPIのレスポンスは複雑なJSON配列であることが珍しくないので、jackson-module-scalaにも挑戦してみようかなと思います。

## 参考文献
[Play2公式ドキュメント-ScalaWS](https://www.playframework.com/documentation/2.6.x/ScalaWS)
UNITYバシス機能

## 3Dキューブを作る
・GameObject→3d Object→CUBEを選ぶことです。
　　選ぶ後で新しいキューブオブジェクトを出てくる。
　　この新しいューブオブジェクト3つプロパティを変更することができる。
　　　・Position
　　　　ーオブジェクトの場所はこのプロパティで設定することです。
　　　・Rotation
　　　　ーオブジェクトの大きこのプロパティで設定することです。
　　　・Scale
　　　　ーオブジェクトの大きこのプロパティで設定することです。

## オブジェクトの色を設定する
初めには新しいマテリアルを作る。
・Assets→Create→Materialを選ぶことです。
  Assetsの画面で新しいマテリアルを出てくる。
　このマテリアはいろいろの設定ができる。
　設定終わった後でこのマテリアルをクリックしてオブジェクトまでにドラッグすることです。

##オブジェクトにフィジカルを上げる
　　・3Dオブジェクトをクリックする。
　　・Inspector画面にAddCompenentのボタンをクリックしてPhysics→RigidBodyをクリックする。
　　・自動でその3Dオブジェクトは3つのComponentは出てくる。
　　　１．Box　Collider
　　　２．Mesh　Renderer
　　　３．Rigid　Body

##スカイの背景を設定する
　　初めにMain　Cameraのオブジェクトをクリックする。
　　Inspectorの画面でCameraのプロパティを変更することができる。
　　例えば：
　　　　・Clear　FlagsはSolid　Colorを変更する。
　　　　・Backgroundは赤色を変更する。
　　　　・スカイの色は自動で赤色になります。

ビデオチュートリアル：https://www.youtube.com/watch?v=IlKaB1etrik
Slackに気象庁の情報（災害情報）を投下するHubotを作った（JavaScript）

# はじめに
ちょっとした地震などの時にどこが揺れたんだろうとかをわざわざ調べに行かなくていい様に、Slackに気象庁から災害情報を取ってきて投稿するBotを作りました。
意外と気象庁が配っている情報をPubSubHubbub（現：WebSub？気象庁の表記に合わせてPubSubhubbubと表記）で取得する方法について情報がなかったので書きます。
今回のコード : https://github.com/kakudo415/disasterbot

## おしながき
- Subscriberを書く（登録部分）
- 気象庁にSubscriberを登録する
- Subscriberをさらに書く（受け取り部分）

## 環境
- JavaScript
- Hubot

# つくる
今回はPubSubHubbubをいかに受け取るかがメインなので投稿部分などは省かせていただきます（詳細はコードを見てください）。

## Subscriberを書く（登録部分）
URLの最後に `/sub` をつけて運用してます（正直いらなかった）
とりあえず登録処理を正しく返せるとこまで書きます。やってることとかは下で書きます。
出来たらデプロイして登録リクエストに備えます。
気象庁が出してる仕様 : http://xml.kishou.go.jp/open_trial/detailinformation.pdf

```javascript
'use strict';

 const verifyToken = process.env.JMA_VERIFY_TOKEN;

 module.exports = (robot) => {
  robot.router.get('/sub', (req, res) => {
    const query = req.query;
    if (query['hub.mode'] !== 'subscribe') {
      res.status(404).send('MODE ERROR').end();
      return;
    }
    if (query['hub.verify_token'] !== verifyToken) {
      res.status(404).send('VERIFY_TOKEN ERROR').end();
      return;
    }
    res.status(200).send(query['hub.challenge']).end();
  });
};
```

### なにがしたいか
気象庁から情報をもらうにはPubSubhubbubを利用する必要があります。
これは情報が更新されたら気象庁からHUBと呼ばれるサーバーに情報を伝え、HUBから利用者のサーバーへHTTPリクエストで情報へのリンクを送るものです。
なので使うためにはまずHUBに自分のサーバーを登録してもらう必要があります。

### やってること
HubotにはExpressが備えつけられてるらしいので、それを使ってHUBからのアクセスを受け付けます。
登録手続きをするとHUBから確認のGETが飛んできます。
そこに登録に必要なクエリが付いてくるので、適切に返してやる必要があります。

- hub.verify_token
- hub.challenge
- hub.topic
- hub.mode
- hub.lease_seconds

以上５つのクエリが来るので一つずつ説明していきます。

#### hub.verify_token
Subscriberはサーバー上で動くので当然他の人からいたずらなどで登録を装ったリクエストが送られてくる可能性があります。
それを防ぐために気象庁への登録時にパスワードのようなものを登録しておくことができ、それを毎回送ってこさせることが可能です。
それを照合することで本物のリクエストかどうか判別できます。（合わなければリクエストを捨てればいい 404を使うようにPubSubHubbubの仕様で決まってたはず）。
ちなみに、あまりえげつない文字列にすると気象庁の職員さんでハマる可能性があるとのこと（メールで登録なので打ち間違える可能性が・・・）。

#### hub.challenge
これは逆にSubscriberを確かめるための文字列です。
SubscriberはこれをそっくりそのままHUBに返してやる必要があります。 **レスポンスの最後の改行とか入ると駄目なので注意！**
登録時の処理のメインはこれ

#### hub.topic
このリンク以下で情報を送ります的な意味だと思われる（どう使えばいいのか不明）。

#### hub.mode
登録時は **subscribe** 登録解除時は **unsubscribe** が入る。

#### hub.lease_seconds
HUBはちゃんと利用者のサーバーが正しく動作しているか定期的に登録時と同じリクエストを送ってきます。
その確認用の次のリクエストが何秒後かを表しています。

## 気象庁にSubscriberを登録する
とりあえずSubscriberが出来たら「気象庁」に登録申請を投げます。
5日とかかかるので登録処理が受けられるようになった時点で申請を投げておいたほうがいいです。
http://xml.kishou.go.jp/open_trial/registration.html
このページにあるように、登録したい情報の種別や個人情報などを気象庁へ決められたフォーマットでメールします（テンプレートが置いてあります）。
メール送って数日すると唐突に確認リクエストがSubscriberに飛んでくるので常時起動しておいてください。

## Subscriberをさらに書く（受け取り部分）
登録が完了したら、登録したジャンルの情報が更新されるたびにPOSTでAtomフィードが送られてきます。
feed内のentry内のlinkのhref属性に個々の情報へのリンクがあります（だいたい24時間で消えるので早めに取りに行きましょう）。
情報はXMLなのでパースしないといけませんが、当然情報の種類が違うと構造も違います。
Report内Head内InfoKindが情報の構造の種類を表しているのでこれで分岐すると良さげです。
http://xml.kishou.go.jp/tec_material.html
このサイトからXMLの構造などについての情報が得られます。
パース出来たら後はそのままHubotで投稿するだけですね。

## さいごに
そこそこN高Slackでお役に立てている模様でありがたいです。
初めて作ったBotなので間違いがあれば指摘していただけると嬉しいです。
atcoder ABC70 D問題

条件より、ワーシャルフロイドを使えず、DFSの実装、隣接リストの実装が必要な問題だったので、解法をメモる

https://beta.atcoder.jp/contests/abc070/tasks/abc070_d

まず、典型的なワーシャルフロイドについて考える。
ワーシャルフロイドは、グラフがある時に(距離が全て正の値)全ての頂点について、二点間最短距離を簡単に求めるアルゴリズムである。
実装例は下の通り

```java

		int[][] dp = new int[n][n];
		
		for(int i = 0;i < n;i++){				//入力
			for(int j = 0;j < n;j++){
				int x = sc.nextInt();			//xはiからjまでの距離
				dp[i][j] = x;
			}
		}

		for(int k = 0;k < n;k++){				//ワーシャルフロイド
			for(int i = 0;i < n;i++){
				for(int j = 0;j < n;j++){
					dp[i][j] = Math.min(dp[i][j], dp[i][k]+dp[k][j]);   //各頂点の二点間最短距離を更新していく
				}
			}
		}

```

これは実装がすごく簡単だが、一つ難点があって、時間計算量がO(N^3)なので、頂点数が多いとすぐにTLEになってしまう。この問題でも余裕でTLEを起こしてしまうので、違う方法で最短距離を求める方法を考える。
冷静に考えると、この問題の答えは、絶対通らなければならない頂点kというものがあるので、kからの各頂点間最短距離をdfsで求めていけば良いと気づく。時間計算量も、結局全て数えてもN(全頂点数)なので、dfsの時間計算量はO(N)になる。よって、全体の時間計算量は答えなければならない問題数回+O(N)なので、O(Q + N)となり余裕で間に合う。

dfsの実装例は下の通り、

```java

static void dfs(int p,long d){
		depth[p] = d;

		for(int i:graph.get(p).keySet()){				//現在の場所からいける場所のうち、訪れていないところならいく。
			if(!(used[i])){
				used[i] = true;
				dfs(i,  d + graph.get(p).get(i));
			}
		}
		return ;
	}
}

```

また、今回はグラフを作る時、隣接行列(dp[][]みたいな)を最初は考えたが、それは、明らかに問題条件よりMLEになるのでArrayListの中に、Hashmap<隣接頂点、距離>を入れることで、隣接リストを作った。このリストは、ArrayListのindexを現在の頂点とすることで、各頂点に、Hashmapを入れることで、隣接リストとして機能するようになっている。このリストの注意点としては、まずArrayListにとりあえずなんでもいいので、全てのindexにHashmapを一つ入れること。そうせずに、

```java
graph.get(a).put(b, c);		//getで始点を指定、putで<隣接点、距離>を入れていく

```
のようにすると、エラーが発生する。また、この最初にHashmapを入れる際も気をつける必要がある。

```java

 HashMap<Integer, Integer> zero = new HashMap<Integer,Integer>();
	for(int i = 0; i <= n;i++){
			zero.put(0, 0);
			graph.add(i, zero);					//getで始点を指定、putで<隣接点、距離>を入れていく
	}

```
このようにArrayListの各indexに同じHashmapを入れてしまうと、どのindexに新たにHashmapを追加しても、全てのindexに対してこのHashmapが追加されることになる。よって、下のようにしなければいけない

```java
		for(int i = 0; i <= n;i++){
			HashMap<Integer, Integer> zero = new HashMap<Integer,Integer>();
			zero.put(0, 0);
			graph.add(i, zero);					//getで始点を指定、putで<隣接点、距離>を入れていく
		}
```
PHP初学者備忘録

## 0埋めについて
sprintf文字列を返す
printf文字列を出力する

<?php
$int = 315;
printf('%05d', $int);
?>

「%」から始まる部分を特殊な文字として定義しており、
「%d」は10進数の整数、「%s」は文字列を表すことになっている。
%05dで０埋め５桁00315の表示になる。



- %dや%sのみで使う場合もある。

  例
　<?php
　$num = 5;
　$location = 'tree';

　$format = 'There are %d monkeys in the %s';
　echo sprintf($format, $num, $location);
　?>
結果
　"There are 5 monkeys in the tree"

- %1というのは何番目のパラメータを表示させるかということ

例
　<?php
　$format = 'The %2$s contains %1$d monkeys';
　echo sprintf($format, $num, $location);
　?>
結果
　'The tree contains 5 monkeys'

###その他まとめ

- PHPはHTMLへの埋め込みが可能
ソース上ではphpは表示されない。
<p>ようこそ<?php print $name; ?>さん。</p>

- echoとprintの違い
echoはデバイス（プリンターやUSB）に文字を送ることができる。様々な機能に使えるが、
printは画面表示のみ。使い分けてわかりやすくするためにも、画面表示の時のみはprintを使うのがベスト。

- PHPはJSと違って、変数宣言は必要ない
$hp = 200;
と直接入力すればいい。

- データ型について
整数型、文字列型、NULL、論理型
※同じ文字列型でも['']を使うと変数や改行の\nも文字として認識される
[""]は変数や\nもきちんと認識してくれる。文字の場合は''がベスト
「数字->新名」の対応を元に、「Bone_L.数字」を「新名_L」に改名する（正規表現） (Python for Blender クックブック)

# 「数字->新名」の対応を元に、「Bone_L.数字」を「新名_L」に改名する（正規表現）

Pythonを使ってBlenderでできる事をまとめています。解説もあります。

[はじめに](https://qiita.com/KTakahiro1729/items/5de5f60982af37d23aa0)
[レシピ一覧](https://qiita.com/KTakahiro1729/items/57f4e1f5495c5e54d431)

Pythonの難易度: ★★★★★

### 動機
左右対称のリグを作るとき、ボーンの名前に左右を表す`_L`や`_R`が付いていると便利です。
しかし、`X-Axis Mirror`を有効にボーン編集をしても、`Bone_[LかR].[三桁数字]`というボーンが作られてしまいます。（「001」のように0埋めがされた数字も三桁数字と表現しています）
これを`Bone.[三桁数字]_[LかR]`に名付け直せると便利ですね。
また、`.001`が付いているボーンは`Sholder`に、`.002`なら`Arm`のように、数字に基づいて改名してみましょう。

### 細かい仕様
- 名称変更を施したいアーマチュアがオブジェクトモードでアクティブだとします。
- アーマチュアのボーンの名称は「`Bone_L.[三桁数字]`／`Bone_R.[三桁数字]`／その他」のいずれかが含まれています。この内、`.[三桁数字]`は省略されている時もありますが`.000`と同じとみなします。
- `["Sholder", "Arm", ...]`のような、新しいボーンの名称がリストの形式で定義されています。（以下、`name`）
- `Bone_L.i`は`[nameのi番目の要素]_L`に、`Bone_R.i`は`[nameのi番目の要素]_R`に改名してください。ただし、`len(name) <= i`の`i`に関しては`Bone.i_L`のようにして下さい。
- `_L`や`_R`の一方しかない場合も、改名してください。
- その他のボーンは名前を変えないでください。

## サンプルコード

```python
name = ['Sholder', 'Arm', 'Hand', 'Finger']

import re
pattern = re.compile(r"Bone_(?P<lr>L|R)($|\.(?P<count>\d{3}))")

import bpy
obj = bpy.context.active_object
if obj.type != "ARMATURE":
  raise Exception("active object is not an armature")
bones = obj.data.bones
for bone in bones:
  match = re.match(pattern, bone.name)
  if match is None:
    continue
  bone_lr = match.groupdict()["lr"]
  if match.groupdict()["count"]:
    bone_count = int(match.groupdict()["count"])
  else:
    bone_count = 0
  if bone_count < len(name):
    trunk = name[bone_count]
  else:
    trunk = "Bone.{0:3d}".format(bone_count)
  bone.name = "{0}_{1}".format(trunk, bone_lr)
```


上記サンプルコードを、Blender内蔵のテキストエディタに貼り付けた後、<kbd>Alt</kbd>-<kbd>P</kbd>を実行してください。

## 解説

### 正規表現
文字列があるパターン(`a`から始まるとか)に一致しているかを調べる方法に正規表現というのがあります。
詳細はググって欲しいですが、`a+b*`のように普通の文字に特殊文字を混ぜることでパターンを定義します。
たとえば、`a+b*`というのは「`a`を1個以上のあと`b`を0個以上含むパターン」を指します。
そのため、`aaaabbb`,`a`,`ab`は`a+b*`という正規表現に一致しますし、`cb`は一致しません。

今回、`Bone_(L|R)(^|\.\d{3})`という正規表現にマッチしています。（`?P<lr>`などは後で説明するので一旦無視してください）
`Bone_(L|R)(^|\.\d{3})`はどのようなパターンを指すのでしょうか？
`(L|R)`は「`L`か`R`のどちらか」というパターンを指します。つまり、`Bone_(L|R)`というパターンは`Bone_L`か`Bone_R`のどちらかが一致します。
同様に、`$`は「文字列の終端」を、`\.`は「`.`という文字[^1]」を、`\d`は「0\~9の数字のどれか一文字」を、`{3}`というのは「直前の文字3文字」を指します。
したがって、`Bone_(L|R)($|\.\d{3})`というのは「BoneのあとにLかRがあって、そこで文字列が終了するか、.とそのあと数字を3文字」というのを指します。まさに`Bone_L.001`などが一致しますね。

[^1]: `.`というのは「なにか一文字」を指します。

正規表現をpythonで使うには`re`という標準モジュールを使います。

まず、`pattern = re.compile(正規表現)`で正規表現をコンパイルします。あまり気にしないでください。
`match = re.match(pattern,文字列)`を実行すると、matchには専用のオブジェクト（一致した場合）かNone（一致しなかった場合）が代入されます。

ここで、先ほど飛ばした`?P<lr>`を説明します。
これは、`match.groupdict()`と一緒に使うことで「一致した文字列を後から辞書型で取得」できます。

例えば、文字列が`Bone_L.001`だった場合を考えてみましょう。
すると、`match.groupdict()["lr"]`は`L`です。
このように`?P<キー>パターン`を指定すると、パターンに一致した文字列を後から辞書型で取得できます。


### bpy.context.active_object
PythonからBlenderを使うには`bpy`というライブラリを使います。
例えば、`bpy.data`にはBlender内の様々な変数（オブジェクトのインスタンス）が、`bpy.context`にはBlenderの現在の状態（選択中のオブジェクトなど）が格納されています。
選択中のオブジェクトを取得するには`bpy.context.selected_objects`が使えます。

今回はアクティブなオブジェクト（最後に選択したオブジェクト）が対象なので、`bpy.context.active_object`を使用します。
curl経由でSlackにメッセージを飛ばす

# 【経緯】
[これ](https://qiita.com/siroykht/items/81d5068fa97a34750b2a)の派生のような感じです。
上記でせっかくSlack APIについて軽く触れてみたので、第二弾としてサーバーからcurlコマンドでSlackのチャンネルにメッセージを投げてみました。
※基本的に参考にさせていただいた方の記事で手順は確認出来るので、簡単にメモ&はまったところだけ記載します。

# 【Tokenの取得】
1. [Slack API](https://api.slack.com/)にアクセス
2. 「Generate test tokens」をクリック
3. 「Create token」をクリック
4. 作成されたTokenをコピーする

# 【サーバーからのcurl実行(chat.postMessage)】
■特定のユーザに飛ばすとき

~~~:command
$ curl -XPOST -d "token={作成したToken}" -d "channel={メッセージを飛ばしたいチャンネル名}" -d 'text=<@user_id> メッセージだよ！！！' -d "username={メッセージ通知元}" -d "icon_url={アイコン画像のURL}" "https://slack.com/api/chat.postMessage" 
~~~

■@channelに飛ばすとき

~~~:command
$ curl -XPOST -d "token={作成したToken}" -d "channel={メッセージを飛ばしたいチャンネル名}" -d 'text=<!channel> メッセージだよ！！！' -d "username={メッセージ通知元}" -d "icon_url={アイコン画像のURL}" "https://slack.com/api/chat.postMessage" 
~~~

# 【はまったところ】
textだけシングルクォーテーションという記述からお察しの通り、もともとtextも全部ダブルクォーテーションで囲んでました。

~~~:NG
$ curl -XPOST -d "token={作成したToken}" -d "channel={メッセージを飛ばしたいチャンネル名}" -d "text=<!channel> メッセージだよ！！！" -d "username={メッセージ通知元}" -d "icon_url={アイコン画像のURL}" "https://slack.com/api/chat.postMessage" 
~~~

そしてエラーでコマンドがこける。当然ですね（ヤケクソ）

~~~:エラー
-bash: !channel: event not found
~~~

# 【まとめ】
サーバーサイドのエンジニアという訳ではないですが、これくらいは知っとこうねっていう内容にはまったので精進します。
（実際過去にcurl経由ではないですが同じような現象には発生したことがある）

# 【参考】
・https://qiita.com/mizuki_takahashi/items/3f77c2e5b6142563ce66
・https://qiita.com/daigon/items/474064e484dcd7136bae
・https://nj-clucker.com/single-double-back-quote-on-shell-script/
【WinActor】ブラウザ操作を高速にする方法

WinActorでブラウザに表示されたWebサイトの画面要素をなるべく高速でつかんで操作するための方法をまとめたメモです。
UiPathのセレクタに近いので、慣れれば直感的に分かると思います。

##手順
IEの開発者ツールで操作したい部分のタグ要素を調べます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/186221/b6ceb3c9-5c9a-5ce5-ccce-af5cd24da580.png)

ChromeのDeveloper toolsの方がタグ表示が早いので、僕はこっちを使ってますw
![image.png](https://qiita-image-store.s3.amazonaws.com/0/186221/ddff95d8-69fa-a2ca-b165-059c825452d9.png)


使用するライブラリは「文字列設定（IE）」です。
ここで設定する**「対象特定種別」**については後述します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/186221/eb692ecb-e781-3c99-0b0a-818cf08b368a.png)

##対象特定種別の設定について
![image.png](https://qiita-image-store.s3.amazonaws.com/0/186221/614d006c-d019-4539-2448-4b4ed7ee2b2e.png)
文字列設定（IE）の詳細設定タブに列挙されている「対象特定種別」ですが、上から優先的に設定することで、要素をつかむ速度がかなり変わります。

例えば、以下のように、Yahoo!路線検索でFrom/Toを入力して、検索ボタンをクリック。その後5秒後にブラウザを閉じる、という操作を実行するとします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/186221/7dc98891-447e-6238-2ade-62e2d1c074e4.png)

**「出発駅入力」「到着駅入力」「クリック（IE）」**アクションにおいて、対象特定種別を
①　**name, type, id**を設定した場合（tag, index系指定なし）
②　**tag, name, type, id**を設定した場合（tag指定あり, index系指定なし）
③　**tag, frame index, tag index, name, type, id**を設定した場合（tag, index系指定あり）
で、画面の操作速度を比較してみます。

①の場合
![winactor_デバッグデモ2.gif](https://qiita-image-store.s3.amazonaws.com/0/186221/ed12d289-6d5e-3f88-f665-33fd5421bb0e.gif)

②の場合
![winactor_デバッグデモ3.gif](https://qiita-image-store.s3.amazonaws.com/0/186221/34da25b1-6ee9-0815-3c94-0ecee94fa423.gif)

③の場合
![winactor_デバッグデモ1.gif](https://qiita-image-store.s3.amazonaws.com/0/186221/50ee66b9-4a88-0acd-b44c-30a143af7e4e.gif)

操作速度は、③（めちゃ速い） > ②（速い） >>>>>>> ①（めちゃ遅い）ですね。

**tag**を設定するかしないかだけで、速度が全然違います。
また、tagのパラメータは**大文字で指定すること**に注意してください。（例：input ⇒ ×　INPUT ⇒ 〇）

index系はなるべく設定したほうが良い、といった感じ。
ただし、**frame index, tag index**は[【WinActor】Webサイトのタグ一覧をExcelに出力する](https://qiita.com/irohamaru/items/d8d908af4d4537e3bcbd)で紹介した**「IE操作(Debug全タグ情報簡易版)」**ライブラリでタグ抽出しないと分からないパラメータです。~~面倒くさい。。。~~
Chromeのデベロッパーツールなどで簡単に分かる方法があれば誰か教えてください＞＜

##まとめ
よほどのことがない限り、**tag, frame index, tag index**は設定必須と言えそうです。
postgresのwebguiを使いたい

## なぜやるか?
現在の状態,
dbはk8sに乗っている.安全のために(maybe)外部に公開していない->loadbalancerを使わずにClusterIPを設定している.
ただ開発者はDBの中身を見たいときがあるだろう.
そこでweb経由で見ることができるGUIをし設定してあげたい

## どうやるか?
pgwebをk8sに乗っけてこれにIngressを付けることにより問題の解決をはかる

- pgwebとは?
- pgwebをdockerで動かす
- k8sに乗っける


## pgwebとは?
golangで書かれた管理インタフェース(だと思っている)
クエリの結果をCSV,JSON,XMLに吐き出すことができる,そしてクエリの履歴を保存している.
画像のようにとてもシンプルなUI(一目惚れした)
シンプルなUIである![pg.png](https://qiita-image-store.s3.amazonaws.com/0/242318/c0d71b4d-bb8b-9bcd-7762-3765f2938b7f.png)


## pgwebをdockerで動かす
「pgweb docker hub」で調べた感じあまりいいimageが中ってので自分で作成する

```dockerfile

FROM alpine:latest as build
ADD https://github.com/sosedoff/pgweb/releases/download/v0.9.12/pgweb_linux_amd64.zip  ./
RUN apk add unzip && unzip pgweb_linux_amd64.zip

FROM alpine:latest
COPY --from=build ./ ./app
EXPOSE 8080
CMD [ "./app/pgweb_linux_amd64", "--sessions" ,"--bind=0.0.0.0", "--listen=8080" ]
```
少し解説すると
ADDでpgwebのzipをダウンロードして,それをunzipで解凍する
このままではunzipが邪魔なのでCOPY --from=buildを使用することでimageサイズを小さくしている.
これで私の環境では16 MBに抑えることができた.

## k8sに乗っける

```yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: pgweb
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: pgweb
    spec:
      containers:
        - name: pgweb
          image: pgweb:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
```
imageのところは自分が作成したimageの名前を設定してあげると動くだろう
尚,我々が使用するときは.gitlabのレジストリにdocker imageを持たせているため
最終行に

```yaml
imagePullSecrets:
        - name: gitlab

```
が必要になる,またimageではgitlab registryに設定しているimageの名前が必要になる

次にserviceを定義していく

```yaml
apiVersion: v1
kind: Service
metadata:
  name: pgweb-svc
spec:
  type: NodePort
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: pgweb
```
selectorを使用して先ほどのdeploymentを設定する
次にingressを設定する.

```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: postgres-web-ing
  
spec:
  backend:
    serviceName: pgweb-svc
    servicePort: 8080

```
必要最低限これで動くと思う.
実際にはこれにnamespaceとか,ingresだとドメインとtlsの設定とかをやった方が良いと思う.....
これが成功するとglobalIPが設定される


アクセスしてみると↓
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242318/aa8fda3b-b815-966a-c952-d108120024d3.png)


## まとめ
pgwebのUIはシンプルでかっこいい
開発者はDBの中身を見たいときpgweb経由で見ることができる
ちなみにk8sに乗っているDBにアクセスしたいときは
HOSTを

```
[サービス名].[ネームスペース名].svc.cluster.local
```
に設定するとつながってくれるはず
これには問題が一つあり,今の状態だとDBが外部に露出してないので
マイグレーションができないということだ.解決する手段として二つ考えた

- DBを外部にさらす
- GCPのポートフォワード機能を使う

一つ目は外部にさらすのは少し怖い
二つ目はGCPしかできないという問題がある

また解決案を考えるとする

ありがとうございました.

## 参考
- [pgweb](http://sosedoff.github.io/pgweb/)
Microsoft Hyper-V Server 2016のインストール時にパスワードが指定できなかった件

#問題
インストールした時にパスワードの再確認が入力できない。エンターしてもパスワードが確定できない。

```
Administratorの資格情報を入力するか、うんぬん....
```

#解決策
エンターキーではなく、下矢印キーを押して確認入力

#まとめ
参考記事のオチも、「30分格闘した」ことが書かれています。
謎設計ですねｗ伝統なのかな（）

#ref
https://techcommunity.microsoft.com/t5/Windows-Server-Insiders/Cannot-enter-new-credentials-after-fresh-installation/td-p/110554
SQL でプライマリーキーなどの連番の範囲を開始と終了で取得

# SQL でプライマリーキーなどの連番となっている範囲を開始と終了で取得したい

テーブルに存在するプライマリーキーなどで
`DELETE` や論理削除により歯抜けとなっているものに対し
値が連続している「範囲」がほしくなることがあるかもしれません。

## 実例

MySQL の事例です。
`test.test` (スキーマと) テーブルの `id` カラムのなかで
`1, 2, 3` や `4, 5` などを
`1 - 3`, `4 - 5` で取得できたら・・・という SQL です。

```sql:範囲の開始と終了・・・？

SELECT 
    CASE
        WHEN
            -- 「前」がなく「次」があるものは「範囲の開始」
            previous.id IS NULL
                AND next.id IS NOT NULL
        THEN
            current.id
        -- 「前」も「次」もないものも「開始」にカウント
        WHEN previous.id IS NULL AND next.id IS NULL THEN current.id
        ELSE NULL
    END AS range_start,
    CASE
        WHEN
            -- 「前」があり「次」がないものは「範囲の終了」
            previous.id IS NOT NULL
                AND next.id IS NULL
        THEN
            current.id
        -- 「前」も「次」もないものも「終了」にカウント
        WHEN previous.id IS NULL AND next.id IS NULL THEN current.id
        ELSE NULL
    END AS range_end
FROM
    -- 「現在」値
    test.test AS current
        LEFT JOIN
    -- 「.id」より - 1 した結合により「前」を求める
    test.test AS previous ON current.id - 1 = previous.id
        LEFT JOIN
    -- previous と同様に「次」を求める
    test.test AS next ON current.id + 1 = next.id
WHERE
    -- 「前」か「次」が NULL であることで絞り込むことにより
    -- 「開始」か「終了」を絞り込む
    (previous.id IS NULL OR next.id IS NULL)
-- これ以上は結果の自己結合するかなにかしないとだめだったので
-- 苦肉の策で「開始」と「終了」の関係性を担保
ORDER BY current.id
```

`test.test` テーブル (`name` カラムはおまけです)

| id | name |
|:--:|:----:|
|1|	a|
|2|	b|
|3|	c|
|5|	e|
|6|	f|
|7|	g|
|8|	h|
|9|	i|
|10|	j|
|11|	k|
|12|	l|
|13|	m|
|16|	p|
|18|	r|
|19|	s|
|20|	t|
|21|	u|
|22|	v|
|24|	x|
|26|	z|

SQL の実行結果

- `range_start` のみ入っている列が開始 (行)
- `range_end` のみ入っている列が終了 (行)
- `range_start` と `range_end` の関係は `ORDER BY current.id` により担保
- `range_start` と `range_end` の両方が入っている行は連続していない値

| range_start | range_end |
|:-----------:|:---------:|
| 1|	|
|             |3|
| 5|	|
|             |13|
| 16|	16|
| 18|	|
|             |22|
| 24|	24|
| 26|	26|

開始と終了を結果の結合をしようせずになんとかしたかった・・・
【RSpec】で書く「Rails Tutorial　９章（前半：〜9.19まで）」のテスト

<br>
またまた前回に引き続き↓
[【RSpec】で書く「Rails Tutorial　８章（後半：8.3）」のテスト](https://qiita.com/Goi350ml/items/622ae9539e51913bb656)

Rails Tutorialを進めました。

今回はその９章の途中までになります。

***
###Rails Tutorialですること
 - Remember機能の実装
   - ユーザーが明示的にログアウトを実行しない限り、ログイン状態を維持することができる
 - Remember機能を実装するに際してバグが２つ発生
   - 1.ユーザーが1つのタブでログアウトし、もう1つのタブで再度ログアウトしようとするとエラーになる
   - 2.ユーザーが複数のブラウザ (FirefoxやChromeなど) でログインしていたときに発生。
    （例えば、Firefoxでログアウトし、Chromeではログアウトせずにブラウザを終了させ、再度Chromeで同じページを開くと、この問題が発生） 

***
###今回使用するファイル
 - Spec（Request）
 - Spec（Models）
 - Controller（Session）
 - Model（User）

***


####▼Rails TutorialのMinitest
![スクリーンショット 2018-10-30 0.09.07.png](https://qiita-image-store.s3.amazonaws.com/0/260354/cbfa33c1-6aa8-083d-a88e-5665e9615076.png)

####Controller（Session）
```ruby:app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
・
・
  def destroy
    log_out  if logged_in?
    redirect_to root_url
  end
end
```

####Spec（Request）

```ruby:spec/requests/users_login_api_spec.rb
  #9.14
  #ユーザーログアウトのテスト
  describe "<sessions#destroy>" do
    context "" do
      before do
        @user = FactoryBot.build(:user)
      end
      it "" do
        get login_path
        post login_path, params: { session: { email: @user.email, password: "password" } }

        expect(response).to have_http_status(200)
        redirect_to(@user)
        #expect(response).to redirect_to("users/show")
        expect(response).to have_http_status(200)

        delete logout_path
        expect(response).to redirect_to(root_path)

        # 2番目のウィンドウでログアウトをクリックするユーザーをシミュレートする
        delete logout_path
        follow_redirect!

        expect(response).to have_http_status(200)
      end
    end
  end
```

***

####▼Rails TutorialのMinitest

![スクリーンショット 2018-10-30 0.14.15.png](https://qiita-image-store.s3.amazonaws.com/0/260354/02986e51-672b-405e-39b1-32bcb16f57cc.png)

####Model（User）
```ruby:app/models/user.rb
  #渡されたトークンがダイジェストと一致したらtrueを返す
  def authenticated?(remember_token)
    return false if remember_digest.nil?
    BCrypt::Password.new(remember_digest).is_password?(remember_token)
  end
```

####Spec（Models）
```ruby:spec/models/user_spec.rb
  #9.17
  it "authenticated? should return false for a user with nil digest" do
    user = User.new(name: "Example User", email: "user@example.com",password: "foobar", password_confirmation: "foobar")
    user.authenticated?("")
    expect(user).to be_truthy
  end
```

***

####まとめ＆反省点
Request Specのテストに関しては正直まだまだ不安が残っています。
果たしてMinitestのインテグレーションテストをRequestSpecに書いていいのかすごく悩みました。
ただ、自分の知識では**Featureでの記述が分かりませんでした。**

こちらに関してはFeatureに書くべきかRequestに書くべきか意見いただけると幸いです。

少しずつ進めていますが、RailsTutorialの難易度も上がり、
何をテストするのかが見極められなくなってきました。

少しでもおかしな部分があれば
ご指摘＆アドバイスお願いします。
<br>
[python] 時刻の範囲の重複チェックについてのメモ

# 概要
6:00-7:00のような時間が複数与えられたときに時間が重なるかチェックしたい。重なる場合は2つの時間をまとめて一つの時間としたい。
以下のようなイメージ
### 例１
　　　　　|--------------|
|-----------------|
5:30　　6:00　6:30　　7:00

>重なっていると判定して、"5:30-7:00"を得たい


### 例２
　　　　　　　　|----------|
|----------|
5:30　　6:00　6:30　　7:00
>重なっていないと判定

## コード
まず重なっているかどうかを判断して、重なっていた場合は最早時間-最遅時間を導けば良い。
そのため以下の２つのモジュールで解決する。
* 時間が重なっているかどうかを判定
* 最も早い/最も遅い時刻を取り出す

pythonのdatetimeでは、datetime/date/timeの型さえ同じであれば、><=比較演算子が使えるので比較的容易にかけた。
※追記：min()/max()も使えるようなので書き直しました。凄いぜpython....

``` python
import datetime

def is_overlap_time(starttime1, endtime1, starttime2, endtime2):
    return starttime1 <= endtime2 and endtime1 >= starttime2

def get_earliest_time(*times):
    return min(times)

def get_latest_time(*times):
    return max(times)

# usage
six_oclock = datetime.time(6, 0, 0)
five_thirty = datetime.time(5, 30, 0)
six_thirty = datetime.time(6, 30, 0)
seven_oclock = datetime.time(7, 0, 0)

print(is_overlap_time(six_oclock, seven_oclock, five_thirty, six_thirty))
print(is_overlap_time(five_thirty, six_oclock, six_thirty, seven_oclock))

print(get_earliest_time(six_oclock, five_thirty, six_thirty, seven_oclock))
print(get_latest_time(six_oclock, five_thirty, six_thirty, seven_oclock))


# output
# -> True
# -> False
# -> 05:30:00
# -> 07:00:00
```

### おまけ
時刻の集合から特定の条件で取り除きたい場合はリスト内包表記のフィルタ機能を利用し、比較演算子が使える。
例えば…

``` python
eject_before6 = [t for t in times if t >= datetime.time(6, 0, 0)]
```