OmniAICreator/Qiita-1.07M huggingface dataset:
リネームしたい？任せときー。

え？ファイル名をリネームしたいって？

#そんなの朝飯前。コマンドで一発だよね。

```
#標準的なリネームコマンド
rename s/aaa/bbb/ ./*
#centosはこう
rename aaa bbb *

$ a.txt  bbb.txt  kkk.txt
```

お礼は要らないよ。
#え？先頭に連番がつけたいんだって？い、いいよ？

```
#ここからechoで確認する。実行するときは | sh　を最後につける。
#cat -n で番号を付けてそれを利用する。
ls | cat -n | while read n f ; do echo "mv -n ${f} ${n}_${f}"; done 

mv -n a.txt 1_a.txt
mv -n bbb.txt 2_bbb.txt
mv -n kkk.txt 3_kkk.txt

```

どや？楽勝でしょ。
#え？え？先頭に0で埋めた４桁の数字を付けたかったって？

```
#printf で桁数指定で出力する。
ls | cat -n | while read n f ; do echo "mv -n ${f} $(printf %04d $n)_${f}"; done;

mv -n 1.txt 0001_1.txt
mv -n 10.txt 0002_10.txt
mv -n 11.txt 0003_11.txt
mv -n 2.txt 0004_2.txt
```


出来たよ。え？違う？ 

#1.txtの次は2.txtが自然だって？ああナチュラルソート順ね。

```
#"える"ではなく"いち",vでバージョンソート,
 ls -1vp | cat -n | while read n f ; do echo "mv -n ${f} $(printf %04d $n)_${f}"; done;

mv -n 1.txt 0001_1.txt
mv -n 2.txt 0002_2.txt
mv -n 10.txt 0003_10.txt
mv -n 11.txt 0004_11.txt
mv -n oh my file.txt 0005_oh my file.txt

```
できたよ？

#え、上手く行かない？ファイル名にスペースが入ってるのね。。

```
 ls -1vp | grep -v "/$" | cat -n | while read n f ; do echo "mv -n  '"${f}"' '$(printf %04d $n)_${f}'"; done;

mv -n  '1.txt' '0001_1.txt'
mv -n  '2.txt' '0002_2.txt'
mv -n  '10.txt' '0003_10.txt'
mv -n  '11.txt' '0004_11.txt'
mv -n  'oh my file.txt' '0005_oh my file.txt'

```

これでいいんじゃない？

#え、やっぱり時間順だって？
```
ls -1ptr | grep -v "/$" | cat -n | while read n f; do echo "mv -n '"${f}"' '"$(printf %04d $n).${f#*.}"'"; done
mv -n '2.txt' '0001.txt'
mv -n '11.txt' '0002.txt'
mv -n '10.txt' '0003.txt'
mv -n '1.txt' '0004.txt'
mv -n 'oh my file.txt' '0005.txt'

```

ど、どや？
え、自分でやりたい？

#コマンドより安全にリネームできるツールを作ったからそっちを使ってくれー。

リネム
https://rinemu.com/

はい、ということで、ファイルAPIとjavascriptで作ったリネームツールです。
リネームしたものはZIP圧縮されてダウンロードするので、うっかりコマンド上書きされる心配がないです。

これは nuxt.js で出来ているので、また次回の記事で紹介したいと思いますー。

#おわり
簡単と思ってたら意外と手こずって、スタックオーバーフローを漁ることになり、
それでも中途半端にしか載っていないので、まとめてみました。
ツールを作る羽目にならないように、次はサクッと決めたいですねー。

参考

https://stackoverflow.com/questions/3886295/how-do-i-list-one-filename-per-output-line-in-linux
https://stackoverflow.com/questions/22948042/bash-sort-like-windows-natural-sort-order
Kotlinのクラス委譲の使い所

Kotlinのクラス委譲（class delegation）機能について、今まで文法的には理解していつつも使い所がイマイチわかっていなかったんですが、今回一つの使い所がわかったので紹介します。

[Kotlinドキュメント（本家）](https://kotlinlang.org/docs/reference/delegation.html)
[Kotlinドキュメント（日本語版）](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/delegation.html)

※ 余談ですがクラス委譲という呼び名の他に、インターフェース委譲という呼び名もあるようです。意味的にはそちらのほうがしっくり来ますが、よく聞くクラス委譲という呼び名をここでは採用します。

# クラス委譲の文法

詳細は前述の本家ドキュメントに書かれているので、ここでは超簡単に紹介します。
以下のようなやつです。

```kotlin
interface UserRepository {
    fun list()
}

class UserRepositoryImpl(val companyId: Long) : UserRepository {
    override fun list() { TODO() }
}

class UserService(repo: UserRepository) : UserRepository by repo

fun main() {
    val repo = UserRepositoryImpl(10)
    //UserServiceクラスで定義していないlistというメソッドが使える！！（このメソッドはUserRepositoryImplのものが呼び出される）
    UserService(repo).list()
}
```

※ 注：頭に入ってきやすくするため`Repository`,`Service`等の命名をしていますが、本来的にはこういう単にコード行数を短くするためだけにクラス委譲を使うのは実装として微妙だと思います。

# 使い所

結論から言うと、**ライブラリにあるインターフェースを継承し、何かしらの機能拡張したクラスを作るケース**が一つの使い所になると思います。

例えば標準ライブラリにあるListインターフェースを継承したIdListクラスというものを独自で作って、ただの`List<Int>`とは違った挙動にしたいと考えたとします（Idならではの制約を入れたり、新しいメソッドを生やしたり…etc）。

まずは以下のように書くと当然コンパイルエラーになります。

```kotlin
//ERROR：コンパイルエラー！！
class IdList : List<Int>
```

Listインターフェースに定義されている必要なメソッドがないからですね。
実装してみましょう。

```kotlin
class IdList : List<Int> {
    //LinkedListを使っているのに深い意味はない。emptyListOfだとList<Int>型になり、後の説明でややこしくなるため。
    private val idList = LinkedList<Int>()

    override val size: Int
        get() = idList.size

    override fun contains(element: Int): Boolean {
        return idList.contains(element)
    }

    override fun containsAll(elements: Collection<Int>): Boolean {
        return idList.containsAll(elements)
    }

    override fun get(index: Int): Int {
        return idList.get(index)
    }

    override fun indexOf(element: Int): Int {
        return idList.indexOf(element)
    }

    override fun isEmpty(): Boolean {
        return idList.isEmpty()
    }

    override fun iterator(): Iterator<Int> {
        return idList.iterator()
    }

    override fun lastIndexOf(element: Int): Int {
        return idList.lastIndexOf(element)
    }

    override fun listIterator(): ListIterator<Int> {
        return idList.listIterator()
    }

    override fun listIterator(index: Int): ListIterator<Int> {
        return idList.listIterator(index)
    }

    override fun subList(fromIndex: Int, toIndex: Int): List<Int> {
        return idList.subList(fromIndex, toIndex)
    }
}
```

・・・思いの外長くなってしまいました。
（正直筆者も夜中にこれを書いていて、何をやっているんだろうという気になりました）
この中のどれが独自メソッドで、どれがIdListならではの特殊な処理を行っているメソッドなのか、パッとはわからないですね。


ときめかないので、こんまりしましょう。
クラス委譲を使います。

```kotlin
class IdList(private val idList: LinkedList<Int>) : List<Int> by idList
```

見事キレイに掃除が完了しました。

# 考察

このクラス委譲という機能は**自身が拡張機能として書きたいロジックに集中するための機能**だという理解をしています。
上の例だとListインターフェースが持つ振る舞いは**基本的に`idList: LinkedList<Int>`のものをそのまま使い、自身で定義したいロジックだけを追加で定義する**ことができます。
`クラス委譲`の名前のとおり、基本的な振る舞いは`idList`インスタンスに委譲しているわけですね。

# 参考

[Effective Kotlin Item 36](https://blog.kotlin-academy.com/effective-kotlin-beta-release-bbf2e0cb9c3f)
【初心者向け】FrisbyとJESTを使ってAPIのテストを書いてみる

# はじめに

【Attention】
私はQAエンジニア（SETではない）なので、コーディングは専門外です。
適当な事を言っていると思います。
間違っている事、もっと「こうしたらいい」色々あると思いますが、ご容赦ください。


# なんでAPIでテストしようと思ったか
テスト自動化したいなと思ったのと、テストピラミッドを勉強してE2Eだけでは今後の運用に耐えられそうにないと思っていたのと、文字数制限のテストや、メールアドレスの形式テスト、文字種のテストとか正直めんどくさいと常々思っていたからです。
人しかできないことを人がやった方がずっとずっとコスパがいいので、人がやらなくていいことはコードにおまかせしたかったので


#なぜFrisby？
一人ではメンテをしていけないと思ったのと（エンジニアの協力が必須）、社内に聞ける人がいっぱいいたからです！
karateが最近流行っていますが、BDD的な書き方がチーム内エンジニアの人があまり好かなかったというのもあります。みんなでメンテをしていかなければならないので、JSで書けるFrisbyを選択しました。


#準備した環境
PC：MacBook　Pro
OS：macOS Catarina10.15.1

node.js v12.7.0
VisualStudioCode

あとnpm？？　（このあたりは前になんかしたときに入っていた（かも）なので必要でしたらいれてください）



#環境準備
まず、nodeをインストールする必要があります。
nodeのインストールには以下の２つを用意する必要があります

- HomeBrew
- nodeBrew

HomeBrewは、Macに色々なものをコマンド１発でインストールしてくれるすごいやつ
nodeBrewはnodeのバージョン管理してくれるやつ

##HomeBrewをインストール
ターミナルを立ち上げて以下のコマンドを貼り付けて実行
`/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`


※HomeBrewがインストールされているかわからない方は、ターミナルを開いて`brew -v`と打ってください。HomeBrewをインストールしたことがない人はターミナルを開いて以下のコマンドを実行してください。インストールされていたらバージョンが表示されます


##nodeBrewをインストール
ターミナルで以下のコマンドを実行
`brew install nodebrew`


##nodeのインストール
ターミナルで以下のコマンドを実行（最新版のインストール）
これでnpmもインストールされているらしい・・・？
`nodebrew install-binary latest`


##インストールが出来ているか確認する
以下のコマンドを実行してバージョンが表示されていれば、ダウンロードができています
`node -v`
`npm -v`


#環境構築
FrisbyとJESTをインストールしていく

１.　とりあえず、ホームディレクトリ配下にディレクトリ（フォルダ）を作成する
`mkdir hogehoge`

２.　作成したディレクトリに移動する
`cd hogehoge`

３.　作成したディレクトリにFrisbyというディレクトリ（実際フリスビーをインストールするところ）とtestというディレクトリ（テストケースを入れる場所）を作成する
`mkdir frisby`
`mkdir test`

4.　作成したfrisbyディレクトリに移動する
`cd frisby`

5.　FrisbyとJestをインストールする
`npm install frisby`
`npm install `

6.　`__tests__`ディレクトリを作成する
　　※JESTは`__test__`ディレクトリ配下のテストを実施してくれるらしいです。なので__test__ディレクトリを作成していく

`cd..`　　　　          //一つ上のディレクトリに移動
`mkdir __test__` 　　 //`__test__`ディレクトリの作成



これで環境構築は多分できました。


#テストを書いてみる
VisualStudioCodeで、`test`ディレクトリを開き、`__test__`配下に`hogehoge.spec.js`というファイルを作成する

※間違えて`__test__`ディレクトリを開いてしまうと、テスト走らない(´；ω；｀)と一時間迷う事になります


#ステータスコードのアサーション
アサーションとは期待値と結果を書くところだと認識しています。



```javascript:hogehoge.spec.js
const frisby = require("frisby");

it("テストをする内容を自由に記載できる箇所", function(){
  frisby.post("https;//hogehoge", {"hoge":"hogeo"}).expect("status", 200);
//frisby.post("APIが叩いてるURL", 送るJSONボディ).expect("status", 返ってくる予定のステータスコード)
});

```

##Responseの内容のアサーション

```javascript:hogehoge.spec.js
const frisby = require("frisby");

//返ってくる予定のJSON
{
    "hoge1": "ほげ１",
    "hoge2": "ほげ2"
}

//ここからがテスト
it("Responseのアサーション", async function(){
    const res = await frisby.get("https;//hogehoge"); 
　　//Responseを定数resに代入（Responseが帰ってくる前に下のテストを実行すると失敗するのでasync　awaitをつかう）
    expect(res.json.hoge).toBe("ほげ１");
   //定数resの中のjsonの中のキーホゲの中身はほげ１である
});

```

##テストの実行
VisualStudioCodeを使っている場合、左下にnpmスクリプトとというツリー？がでてきて、その下のtestという押すと自動的に流れてくれました。



#終わりに
大体この２つを書ければ、やりたい事は出来ました。（まずはスモールスタート方針）
悩んだのは、リクエストのBODYを定義したり継続してテストを実施したいので、返ってきた値を次のテストに利用したりすることでした。

テストについては一旦スモールスタートをしてみてどういう結果になるか試してみたいと思います！


##追記
APIのテストのサンプルを記載するのめちゃくちゃ難しかった・・・
説明するのに使えるなんかいいのないかなー(ﾟＡﾟ;)

そしてやっぱり環境構築が一番の難敵。
frisbyをインストールするときにWARNがいっぱい出てあわあわしていました。
（別に無視していいやつだったらしく、解決するまでに2時間ぐらい時間を使いました（｀ェ´））
ルーブル美術館よりも満足度が高かったフライングタイガーという雑貨屋

アドベントカレンダーを初めて書く新参者ですがどうぞよろしく。

>WEBデザイナーだが美術館が苦手で昔から興味が持てない。フランスのルーブル美術館も秒で回ってすぐ帰る:rolling_eyes:でもデザインは好き…

という私が、先日「[フライングタイガー](https://blog.jp.flyingtiger.com/)」という雑貨屋に行ったのだけど、そのヘンテコなアートやクリエイティブに衝撃を受けたっていうお話。

##フライングタイガーとは
>デンマークを中心にヨーロッパ16カ国および日本で約150店舗を展開する雑貨店である（2012年7月時点）家庭用品、文房具、食品などを扱う。1995年にデンマーク・コペンハーゲンにて開業。
デンマーク語のTIGERが「ティアー(TIGER)」と発音され、10クローネを意味する「ティアー(TIER)」に類似していることから、10クローネストアとして認識されるようになった。上記のエピソードから日本のメディアでは「北欧の100円ショップ」と紹介されることがある。（wikipediaより）

要するにデンマーク発のリーズナブルな雑貨屋さん。本当に安い。

ただ、普通の雑貨ではない。店舗によってレイアウトは違うと思うけど、入ってすぐに商品が普通じゃないことに気付く。

![b1f88d4115afdb183e9f7c34964fb4ea.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162913/b8f64da6-a8c8-899f-f69c-ca4a4f783a60.jpeg)
<font color="Gray">Copyright © Zebra Japan K.K. All rights Reserved.</font>

↑ユニコーンのようなリス（多分）

![85a6a7c8d48726b497bff6ebe0520838.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162913/5a77ef22-f192-de1f-597a-f32dba36ed8a.jpeg)
<font color="Gray">Copyright © Zebra Japan K.K. All rights Reserved.</font>

↑クモが刺さっているペン。

![425116b82da35691e81e2fa1058e658e.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162913/bf4292ef-318f-fe7b-5718-397ec09d1e5a.jpeg)
<font color="Gray">Copyright © Zebra Japan K.K. All rights Reserved.</font>

↑！？（ちょっと欲しい）

###「どうしてこうしちゃったの・・・！？」

ツッコミどころ満載で、とにかくずっとワクワクしっぱなしだった。
「こんなの売れるの？日本人受けしないのでは？」と思いつつも自然と笑顔になってしまい、帰る頃にはもの凄く満たされていることに気付いた。高い満足度。こんなの久しぶり。すばらしい:clap:

「フライングタイガー」のデザイナーはどんな想いでこれらのデザインを作成しているのか。気になったので少し調べてみた。

##ミッション
>私たちは、人々に必要なもの、夢見ているもの、存在すら知らなかったものを与えながら、人々の顔に笑顔を置くのが大好きです。すべて手頃な価格で。
私たちは、人々が一緒に時間を過ごすように促す製品を設計します。これが、お客様にユニークで関連性のある製品を探し続け、ブランドを洗練させ、コンセプトをさらに発展させるために努力する理由です。

##クリエイティブについてのこだわり
以下は[本家の公式サイト](https://corporate.flyingtiger.com/en)などから一部引用。

####想定外のデザイン
>あらゆる機会にユニークで関連性のある楽しい製品を販売しながら、予期せぬものを提供します。

####新しい概念の作成
>私たちは人々の夢やアイデアの触媒になりたいです。そのため、素材、色、グラフィックスを使用して機能オブジェクトに感情的な価値を追加し、選択および設計する各製品に多大な考慮を払っています。

####斬新なアイデア
>私たちにとって、製品が個人的な関係を刺激することが不可欠です。機会が何であれ、私たちはアイデアに命を吹き込みます。

####超ユニーク
>トレンドをコピーするのではなく、トレンドを作成することで製品範囲を更新します。

####価格ではなく経験
>豊かな生活は大金を必要としません。
少なくともフライングタイガーコペンハーゲンでは。



…なるほど。サービスのミッションやこだわりが全てに反映されているから、私はこの店に満足感を感じたのだと思う。

普段自分が担当しているWEBサービスの顧客満足度をもっとあげたいと思ったこと。自分がデザイナーとしてこれからどんなことを提供できるのか。偶然入ったお店から様々なことを考えさせられた気がする。

機会があったら是非とも行ってみてください:thumbsup:
enebularで作ったフローがデプロイできるマイコンボード「RAVEN」

enebularの特徴の一つとしてはenebular上で開発したフローを遠隔でデバイスにデプロイできることですよね。
しかもバージョンアップしたenebularでは、たくさんのデバイスを一括で管理し、デバイスで動作しているフローを同時にデプロイできるようになっています。
enebularからフローをデプロイできるデバイスはLinux上で動作する「[enebular-agent](https://docs.enebular.com/ja/EnebularAgent/Overview.html)」とArmのmbed-os上で動作する「[enebular-edge-agent](https://docs.enebular.com/ja/EnebularEdgeAgent/Introduction.html)」を対象としています。
この記事でお話しするのは「[enebular-edge-agent](https://docs.enebular.com/ja/EnebularEdgeAgent/Introduction.html)」のリファレンスボードである「[RAVEN](https://docs.enebular.com/ja/Board/RAVEN.html)」となります。

　
enebular-edge-agentリファレンスボード「RAVEN」![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/acb5ead1-2e9b-22d9-3c13-0ee5b9e0a821.png)


# RAVENとは
RAVENはenebularで作ったフローをマイクロコントローラレベルのデバイス上で動作を可能としたマイコンボードです。このボードでの動作をサポートしている「[enebular-edge-agent](https://docs.enebular.com/ja/EnebularEdgeAgent/Introduction.html)」は、フローの動作だけではなく、enebularの[デバイス管理機能](https://docs.enebular.com/ja/device/devicelist)にも対応しています。
RAVWNにはセンサーやアクチュエータなどのモジュールを4つ接続できるようになっているので、IoTのエッジデバイスとして扱えるようになっています。
RAVENは[Arm Mbed](https://www.mbed.com/en/)や[Pelion](https://www.arm.com/ja/products/iot/pelion-iot-platform)のプラットフォームとしても登録されているので、mbed-osやPelionのリファレンスボートとしても使用できます。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/b266bcbc-7018-2ded-987f-6f7c06fb0f99.png)](https://os.mbed.com/platforms/UH-ENE01/)

RAVENはenebularのメニューから購入することができます。enebular-edge-agentは書き込み済みで、Pelionのサービス込みで提供されます。そのため、enebularからすぐにフローのデプロイが可能となっています。


詳しくは以下のリンクを参照してください。

* [RAVENの購入方法](https://docs.enebular.com/ja/Board/RAVEN.html#flow)
* [Getting Started](https://docs.enebular.com/ja/EnebularEdgeAgent/GettingStarted.html)
* [RAVENで使用可能なノード](https://docs.enebular.com/ja/EnebularEdgeAgent/Nodes.html)
* [RAVEのサンプルフロー](https://docs.enebular.com/ja/EnebularEdgeAgent/SampleFlows.html)
* [Wi-Fi等の設定方法](https://docs.enebular.com/ja/EnebularEdgeAgent/Configuration.html)
GoでtwitterAPI触ってみた

Goの勉強も含めて、Twitter APIを利用して、`「アオキ大好き！最高！」`とツイートしている人を`全員フォロー`してみせます。

`anaconda`というパッケージを使います。

##anacondaとは
Pythonの[あれ](https://www.python.jp/install/anaconda/index.html)じゃないです。

`anaconda`とは、**Twitter APIにアクセスするためのGoパッケージ**です。便利！

## Twitter APIの利用申請
間違いなく一番めんどくさい過程。
[こちら](https://qiita.com/kngsym2018/items/2524d21455aac111cdee)を見ながら頑張りましょう。結構テキトーでも通ります。

##実装

```golang:main.go
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/url"
	"strconv"

	"github.com/ChimeraCoder/anaconda"
)

type TwitterAccount struct {
	AccessToken       string `json:"accessToken"`
	AccessTokenSecret string `json:"accessTokenSecret"`
	ConsumerKey       string `json:"consumerKey"`
	ConsumerSecret    string `json:"consumerSecret"`
}

func main() {
	raw, error := ioutil.ReadFile("./twitterAccount.json")
	if error != nil {
		fmt.Println(error.Error())
		return
	}

	var twitterAccount TwitterAccount
	json.Unmarshal(raw, &twitterAccount)

	api := anaconda.NewTwitterApiWithCredentials(twitterAccount.AccessToken, twitterAccount.AccessTokenSecret, twitterAccount.ConsumerKey, twitterAccount.ConsumerSecret)
	v := url.Values{}
	v.Set("count","10000")
	// v.Set("exclude","retweets")
	searchResult, _ := api.GetSearch(`"アオキ大好き！最高！"`, v)
	fmt.Println(strconv.Itoa(len(searchResult.Statuses))+"件ヒットしました！！")
	for _, tweet := range searchResult.Statuses {
		fmt.Printf("%d\n", tweet.User.Id)
		api.FollowUserId(tweet.User.Id,v)
		fmt.Println("--------------------------------------------------------------")
	}
}

```
```golang:twitterAccount.json
{
  "accessToken": "*****************",
  "accessTokenSecret": "*****************",
  "consumerKey": "*****************",
  "consumerSecret": "*****************"
}
```

```:結果
   0件ヒットしました！！
```


今回作成したリポジトリは[こちらから](https://github.com/katsuomi/followSomeOne)

参考: 
[anaconda github](https://github.com/ChimeraCoder/anaconda)
[anaconda Doc](https://godoc.org/github.com/ChimeraCoder/anaconda)
Express × TypeScript にてError ['req' is declared but its value  is never read.]

ExpressをTypeScriptを用いて書いた時にでたエラーの回避方法について。

初心者向けです。

#環境

express :4.17.1
@types/express 4.17.2
typescript: 3.7.2

#エラーの内容
```javascript

import Express from 'express';

const app = Express();

app.get('/', (req, res) => res.send('API Running'));

const PORT = process.env.PORT || 5000;

app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

 ```

上記のような際にapp.getを呼び出した際にreqを呼び出していませんという意味のエラーです。

```terminal
Unable to compile TypeScript:
'req' is declared but its value  is never read.
```

コンパイルに失敗します。


（呼び出しているのはresだけ。reqは呼び出されることはない。）

このように、フレームワークの設定上どうしても呼び出さないメソッドが現れることも多くあると思います。
（Expressはreqを記述したあとでないと、resを呼び出すことができない。)

#解決法

解決方法は簡単でtsconfig.jsonにて、noUnusedParametersをfalseにしてあげます。

```terminal:tsconfig.json
{
  "compilerOptions": {
     .
     .

    "noUnusedParameters": false,
     .
     .
   
}

```


**noUnusedParameters**
未使用のパラメータに対して警告をします。
初期値はfalseなのですが、なぜかtrueになっていました。。。。
tsconfigは意味を理解してちゃんと設定しましょう。。。

#その他の解決方法

##@ts-ignoreを記述する

@ts-ignoreをコメントで記述すると、コンパイルのチェックをパスすることができます。明示的にパスした理由をコメントに残しておきましょう。

```javascript

import Express from 'express';

const app = Express();

//@ts-ignore TS6133: 'req' is declared but its value is never read.
app.get('/', (req, res) => res.send('API Running'));

const PORT = process.env.PORT || 5000;

app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

 ```

上記のようにエラーメッセージを記述すると良いそうです。


##無視したい部分に_をつける

```javascript

import Express from 'express';

const app = Express();

app.get('/', (_req, res) => res.send('API Running'));

const PORT = process.env.PORT || 5000;

app.listen(PORT, () => console.log(`Server started on port ${PORT}`));


 ```

上記のようにreqの先頭に_をつけることによって、コンパイルチェックを回避することができます。
ただ、reqが呼び出されているのか、いないのか見通しが悪いですね。。。

#まとめ
コンパイルの設定についてちゃんと調べましょう。（戒め）
ts-ignoreによるコンパイルチェックの回避は
型定義がされていないパッケージのコンパイルチェックを回避するシーンで使うと思いますので、覚えておきましょう！
設計とアーキテクチャ&FW

#設計とは
作業する範囲を決定し、何を作って何を作らないかを明確にすること。
大まかな流れとして外部設計→内部設計→開発となる。
#設計の種類
##サービス設計
システムだけでなく、サービスに関する全てを設計する。
##UI/UXデザイン設計
システムにおいてはユーザが見ることができる、および触ることができる部分に関する設計をする。
##データ設計
システムで使用するデータを設計して定義する。アプリの中ではModelを作り意味に近い。
##機能設計
システムが持つ機能を設計して定義する。アプリの名ではView以外の開発がこれにあたる。
##テスト設計
機能設計で決めた機能が正しく動くかテストを行う。
#アーキテクチャとは
システムにおいて論理的構造や設計思想のことで、スマートフォンアプリケーションの開発で「アーキテクチャ」というと設計思想や構造のことをさす。
代表的なアーキテクチャとしてMVC,MVP、MVVM、Clean、Architectureなどがある。
プログラムやシステムは自由に作っていると、自分にしか理解できないものになるため、アーキテクチャを用い、アーキテクチャを知ることが重要となる。
##フレームワークとは
０からプログラミングするを大変なためフレームワークを用いて楽にするもの。
フレームワークを使うことで自分のレベルをあげることができる
秋月L6470使用ステッピングモータドライバをPython3で動かしてみた

### 概要

秋月電子で販売している**L6470使用ステッピングモータドライブキット**を**JetsonNano**で動かしてみた

### 使用ハード
- [**AE-L6470DRV（秋月電子）**](http://akizukidenshi.com/catalog/g/gK-07024/)
- [**Jetson Nano 開発者キット（NVIDIA）**](https://developer.nvidia.com/embedded/jetson-nano-developer-kit)
- [**P-PMSA-B60D3 (Plexmotion)**](http://www.plexmotion.com/products/detail.php?q=P-PMSA-B60D3)

![](https://user-images.githubusercontent.com/26181834/69914558-12667100-1489-11ea-8e1e-1d98323d2cdb.jpg)

### 結線

|Jetson Nano | |AE-L6470DRV |
|---|---|---|
|Pin 19 (SPI_MOSI) |--> |CN4-7 (SDI) |
|Pin 21 (SPI_MISO) |<-- |CN4-5 (SDO) |
|Pin 23 (SPI1_SCK) |--> |CN4-6 (CK) |
|Pin 24 (SPI1_CS0) |--> |CN4-8 (#CS) |
|Pin 25 (GND) |<-> |CN4-3 (GND) |

### ソフトウェア設定

- **JetsonNano SPI有効化**

    参考：[Jetson NanoのSPIを有効にする](https://www.rt-shop.jp/blog/archives/11277)

    ```bash
    $ git clone https://github.com/rt-net/JetsonNano_DT_SPI.git
    $ cd JetsonNano_DT_SPI
    # 注意：JetsonNanoで使用しているイメージバージョンに合わせること
    $ git checkout R32.2.1
    ```

- **L6470コントロールライブラリ インストール**

    ```bash
    $ git clone https://github.com/DaiGuard/l6470
    $ cd l6470
    $ sudo python3 setup.py install
    ```

### 動作テスト

ライブラリに同封されているサンプルを実行してみる

```bash
$ cd l6470/samples
$ python3 sample_run.py
```
メモ

#ストロングパラメータ
指定したキーのみを受け取るので、データをDBに入れるかどうかを判別させるために使う。
ex params.permit(:キー名,キーの値）

#java script

list.push(***);  配列に要素を追加する。

list.pop();　配列の最後の要素削除
⇅　逆の関係
list.shift(); 配列の最初の要素削除

オブジェクトの作成
let object = {};

関数を使うとき
returnを記述する。
　returnは関数内で処理をした結果戻り値として返す。

関数とは
入力された　値に対して　出力して　返すこと

引数　→　関数　→　戻り値

function calc(num1,num2){
  return num1*num2;
}

let num1 = 5;
let num2 = 7;
console.log(calc(num1,num2));


DOM (document object model)

htmlを階層上に表現したデータでjava script 

body ---------header
         |
         |
         ------content
         |
         |
         -------footer

body header content footer をノードと言う
ArangoDBとJavaのデータマッピングを調べてみた

# はじめに
オークファンでは一部でArangoDBを使用しています。
ArangoDBとは、DocumentDBとGraphDBのいいとこ取りした、ハイブリッドなNoSQLのデータベースです。

*＊DocumentDBやGraphDBがなんぞやというのは置いておきます。*

オークファンでは、商品の情報や販売情報などのデータを活用したサービスづくりをしています。

私が所属しているチームでは、商品ごとに異なる性質の情報(スペックなど)や、メーカーやカテゴリーといったデータの関連を考慮したデータを扱いたい場合に、ArangoDBのようなデータベースが適していると考え、使用しています。

一方で、それらのデータを参照したり集計したりするソフトウェアを作成する場合には、JavaもしくはKotlinを採用しています。
そのためArangoDBに対してプログラムからアクセスする場合には、ArangoDBから提供されているJavaAPIを介して行います。

ArangoDBはJavaではないです。扱うデータは基本的にJSONの形式となります。
当然ですがデータ型の定義はプログラムと異なることになります。

Javaで自然に使用しているデータ型がArangoDBに入れた場合に、ArangoDBが扱える型(JSONの形式)に変わってしまい、データ利用時に意図しない型変換に悩まされないよう、テストしてみました。


# 前提
各種バージョンについては下記のとおりです。

- Java：11
- ArangoDB：3.4.1


# Java → ArangoDB
ArangoDBへ格納は、`BaseDocument`クラスを使用し、`addAttribute()`メソッドでデータをセットします。

格納したデータをArangoDBのWebUIで確認し格納された状態を確認します。

| Javaの型 | →ArangoDBの型 | 備考 |
| --- | --- | --- |
| int | 数値(整数) | 
| Integer | 数値(整数) | 
| long | 数値(整数) |
| Long | 数値(整数) | 
| float | 数値(小数) | ※ データが崩れた
| Float | 数値(小数) | ※ データが崩れた
| double | 数値(小数) | 
| Double | 数値(小数) | 
| BigDecimal | 文字列 | 
| boolean | 真偽値(true/false) | 
| Boolean | 真偽値(true/false) | 
| LocalDate | 文字列 | ISO8601形式
| LocalDateTime | 文字列 | ISO8601形式
| OffsetDateTime | 文字列 | ISO8601形式
| ZonedDateTime |文字列 | ISO8601(拡張)形式
| List | 配列 | 
| Map | オブジェクト | オブジェクト内の型は上記マッピングと同様


# ArangoDB → Java
ArangoDBにWebUIからデータを格納し、Javaで取得したときのデータ型は下記のようになりました。


| ArangoDBの型 | →Javaの型 | 備考
| --- | --- | --- |
| 文字列 | String | 
| 数値(整数) | Long | 
| 数値(小数) | Double | 
| 真偽値(true/false) | Boolean | 
| 配列 | ArrayList | 中の型は他と同様
| オブジェクト | HashMap | 中の型は他と同様

# Java → ArangoDB → Java
JavaでArangoDBに格納したデータを、Javaで取得したときのデータ型の変化の流れは下記のようになりました。

| Javaの型 | →ArangoDBの型 | →Javaの型 | 備考 |
| --- | --- | --- | --- |
| int | 数値(整数) | Long
| Integer | 数値(整数) | Long
| long | 数値(整数) | Long
| Long | 数値(整数) | Long
| float | 数値(小数) | Double | ※ データが崩れた
| Float | 数値(小数) | Double | ※ データが崩れた
| double | 数値(小数) | Double
| Double | 数値(小数) | Double
| BigDecimal | 文字列 | String
| boolean | 真偽値(true/false) | Boolean
| Boolean | 真偽値(true/false) | Boolean
| LocalDate | 文字列 | String | ISO8601形式
| LocalDateTime | 文字列 | String | ISO8601形式
| OffsetDateTime | 文字列 | String | ISO8601形式
| ZonedDateTime |文字列 | String | ISO8601(拡張)形式
| List | 配列 | ArrayList | 中の型は他と同様
| Map | オブジェクト | HashMap | オブジェクト内の型は上記マッピングと同様

# まとめ
JavaAPIでArangoDBを使う場合は、ちょっと注意が必要だと分かりました。

気にせず使えるのは

- 整数はLong型
- 小数はDouble型
- 真偽値はBoolean型
- ListやMapのコレクションクラス

ちょっと拡張したくなるのは

- BigDecimalで扱いたい場合
  - ArangoDBに入れる場合には文字列にシリアライズされる
  - ArangoDBから取得する場合は文字列として取得されるので、文字列をデシリアライズする
- Java8以降のDateTimeAPIを使用する場合
  - ArangoDBに入れる際は文字列にシリアライズされる
  - ArangoDBから取得する場合は文字列として取得されるので、文字列をデシリアライズする

実は小数の計算はもっとややこしかったりします。。。興味のある方は(￣ー￣)ﾆﾔﾘ
勉強記録　9日目 〜関数の引数にconst修飾子〜 - Effective C++ 第3版 -

#　はじめに

Effective C++ 第3版の3項9ページから勉強していきます。
今回は、「関数の引数にconst」についです。

# Effective C++ 第3版 - 3項　可能ならいつでもconstを使おう -

## 関数の引数にconst

### const修飾子をつける位置

前回の投稿で、
const修飾子がアスタリスク(＊)の左にあるときには、「ポインタが指し示すデータ」が不変、
const修飾子がアスタリスク(＊)の右にあるときには、「ポインタそのもの」が不変となると書きました。

```cpp
int x  = 5;
int x2 = 3;

// const修飾子がアスタリスク(*)の左
const int *p2_x = &x;        // ポインタは非const
                             // データはconst
*p2_x = x2; // コンパイルエラー
 p2_x = &x2;

// const修飾子がアスタリスク(*)の右
int *const p3_x = &x;        //  ポインタはconst
                             // データは非const
*p3_x = x2;
 p3_x  = &x2; // コンパイルエラー
```

そのため「ポインタが指し示すデータ」を不変とする場合、
const修飾子は、型名の前に付けても後(アスタリスクよりは前)に付けても問題ない。

```cpp
// const修飾子を、引数の型(int 型)の前に付けた場合
void func1(const int *a) {   // ポインタは非const
                             // データは非const
 int b = 5;
 *a    = b; // コンパイルエラー
  a    = &b;
}     

// const修飾子を、引数の型(int 型)の後に付けた場合
void func2(int const *a) {   // ポインタは非const
                             // データは非const
 int b = 5;
 *a    = b; // コンパイルエラー
  a    = &b;
}
```

そのため、上のコードは同じ引数型を持つ関数となる。

以下に、勉強で使用したコードを示します。

### サンプルコード

```cpp:3_const_tutorial2.cpp
#include <iostream>

void func1(const int *a) {
  int b = 5;
  // *a    = b; // コンパイルエラー
  a = &b;

}

void func2(int const *a) { // データはconst, ポインタは非const
  int b = 5;
  // *a    = b; // コンパイルエラー
  a = &b;
}

void func3(int *a) {
  std::cout << a << std::endl;
  *a = 11;
}

int main(int argc, char *argv[]) {
  std::cout << "3_const_tutorial2.cpp" << std::endl;
  int  x = 3;
  int *px = &x;
  func1(px);
  func2(px);
}
```

### 実行結果


## 参考文献

・https://www.amazon.co.jp/gp/product/4621066099/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0
[iOS] アプリクラッシュでリジェクトされた際のクラッシュレポート復元方法

# はじめに
iOSアプリのストア申請時、アプリがクラッシュするとリジェクトされますよね。
そこで添付されたクラッシュログを復元する方法に手間取ったので、どのように解決したかを紹介します。

# なぜ手間取ったか
調べると、dSYMからクラッシュログを復元する方法はたくさん出てきます。
私の環境では、CIでビルドからAppStoreConnectへのアップロードまで行っていた為、dSYMはAppStoreConnectからダウンロードしていました。
そのdSYMとアップルが送ってくれたクラッシュログの紐付けうまくいかず、手間取ってしまいました。

### 一般的には
クラッシュログ(xxx.crash)と、予め保存しておいたdSYM（アプリ名.app.dSYM）を、`symbolicatecrash`に食わせてやると、復元できます。

### 私の環境
AppStoreConnectからダウンロードしたdSYMは、`appDsyms.zip`というZIPファイルで、解凍すると中には`[ランダムな文字列？].dSYM`というファイルが多数入っています。
つまり、dSYMが複数あるような状況で、どのdSYMを`symbolicatecrash`に食わせれば良いかが判断できなかった訳です。

# 手順

アップルが送ってくれたクラッシュログを確認すると、以下のような文字列が一番上に記述してあると思います。

```
{
"app_name":[アプリ名],
"timestamp":[日付],
"app_version":[アプリバージョン],
"slice_uuid":"f1a3f12a-gca0-3ad8-97d1-f450de9a6a9b", ←ランダムな文字列？
　〜 以下、略 〜
}
```

ここの`slice_uuid`に記載された文字列がキモです。
ダウンロードした`appDsyms.zip`を解凍すると、`f1a3f12a-gca0-3ad8-97d1-f450de9a6a9b.dSYM`というファイルが存在していると思いますので、そのdSYMとクラッシュログを`symbolicatecrash`で食わせてあげればクラッシュした箇所を特定することができます！


クラッシュログの復元方法（`symbolicatecrash`の使い方）については、以下の記事を参考にさせていただきました。
https://qiita.com/ruwatana/items/cc470eb229d267d693b0

# おわりに
手元にdSYMが無く、ダウンロードしてきたdSYMも複数あって絶望したのですが、なんとか解決できました。
私と同じように、手元にdSYMファイルがないような状況に陥っている方の参考になれば幸いです。
GoogleAnalyticsの複数のビューを日別に合算して、自動でレポーティングする方法

本記事は[GoogleAnalytics Advent Calendar 2019](https://qiita.com/advent-calendar/2019/google_analytics) ３日目の記事になります。

複数のWEBサイトを運営していて、**「全サイト合算で、どれくらい集客出来ているか知りたい」**といった要望を上長やクライアントから受けたことはないでしょうか？個別にデータをダウンロードして集計しても良いのですが、提出頻度が多いほど手間が掛かります。今回はGoogleスプレッドシートで利用出来るGoogleAnalyticsアドオンを使い、簡単に日毎の合算レポートを作成する手法をまとめました。

## 課題

GoogleAnalyticsの複数のビューに存在するページビューなどの指標を１つに合算して、日毎の集計を出したい。

## 概要

Google Analyticsアドオンを使い、スプレッドシートへGAの値を集約し、スプレッドシート上でレポート化します。アドオンは設定した期間で自動更新可能なため、動的に更新されるレポートを作成することが出来ます。

## 手順

### 1) GoogleAnalyticsアドオンに複数のレポート取り込みを設定する
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543083/e7f59e29-3852-d2fd-87ef-571d2a4a6853.png)

複数のビューからデータを取得出来るように、スプレッドシートに設定を入力します。
B列以降、各列毎に設定したデータが、それぞれ別のシートに分かれて保存されます。

今回取得する内容は下記のように設定しています。

- 「昨日」から「過去62日分」の期間 (2ヶ月分)
- 取得するデータは「セッション」「ページビュー」「収益」「トランザクション数」の４項目
- ディメンションは「日付」と「デバイス」




### 2) 合算シートを作成する
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543083/011154d3-f320-d363-acce-12d63ef3f0ef.png)
アドオンを実行すると、各シート毎に画像のようにデータが保存されます。
次にシート毎へ分かれたデータを集約するためのシートを作成します。

#### QUERY関数で日付の取得
シートを作成したら、1行目にヘッダーを追加し、2行目にQUERY関数を追加します。
QUERY関数は条件に合ったデータをまとめて取得するための関数です。

先ずはA列のデータを取得するためにA2セルへ下記のように入力します。
シートの分だけQUERY('シート名'!A列のデータ範囲,"where A is not null")をセミコロンで繋ぎます。
 ` ={QUERY('シート名'!A列のデータ範囲,"where A is not null";'シート名'!A列の範囲,"where A is not null")} `

これでA列の指定範囲内に値が入っているものを全て拾います。2行目以降に関数を入れる必要はありません。
同じ作業を列ごとに繰り返します。その際、Whereの「A」の部分は列ごとに変更します(B列であれば「B」、C列であれば「C」です)
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543083/667ca546-f756-83c5-0662-5eee3951575f.png)

### 3) レポート用のシートを作成する
最後にレポート用のシートを作成し、SUMIFS関数で数値をレポートにまとめます。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543083/8fa3c68f-fdd3-4377-0f3c-ef1cc2301da5.png)

#### UNIQUE関数で日付の取得
まずはじめにUNIQUE関数で重複を除外した日付の一覧を作成します。
日付を入力したい一番上のセルへ下記のように入力します。
` =UNIQUE(シート名!範囲) `

こうすることで、複数のシートにある重複する日付の中から重複しない値だけが並ぶようになります。
UNIQUE関数もQUERY関数のように2行目へ関数を入力する必要はありません。

#### SUMIFS関数で日毎の数値を合算
最後にSUMIFS関数を使い、A列の日付をキーにして合算値を出します。
``` =SUMIFS(合算シートのシート名!合計したい列の範囲,合算シートのシート名!日付を含む列の範囲,同じ行にある日付のセル) ```

同じ作業を各列ごとに繰り返せば、レポートの完成です。
今回は割愛していますが、元データはデバイスごとにデータを分けていますので、同じレポートをPC、モバイルで分けることも可能です。

GoogleAnalyticsアドオンは指定した周期で自動的にデータを取得するため、一度作成してしまえば、あとはスプレッドシートを開くだけで最新のレポートを確認することが出来ます。
MongoDB の null, empty を整理する

https://qiita.com/risou/items/d1d0b0173039d68ed81c で `$exists` の挙動について触れたが、他のケースについてもまとめておく。

まず、以下のようなデータを想定する（前回と同じ）。

```js
> db.items.find()
{ "_id" : ObjectId("5de50feab2e406088d483c44"), "name" : "item01", "color" : "red", "size" : "M" }
{ "_id" : ObjectId("5de51001b2e406088d483c45"), "name" : "item02", "color" : "blue", "size" : "S", "memo" : null }
{ "_id" : ObjectId("5de51012b2e406088d483c46"), "name" : "item03", "color" : "yellow", "size" : "L", "memo" : "" }
{ "_id" : ObjectId("5de51029b2e406088d483c47"), "name" : "item04", "color" : "green", "size" : "M", "memo" : "hoge" }
```

それぞれのドキュメントの `memo` は以下のようになる。

name | memo
:--: | :--:
item01 | （存在しない）
item02 | null
item03 | empty（空文字）
item04 | "hoge"

# `memo` が null のドキュメントを取得する

普通に条件に `memo: null` を追加すると以下のようになる。

```js
> db.items.find({memo: null})
{ "_id" : ObjectId("5de50feab2e406088d483c44"), "name" : "item01", "color" : "red", "size" : "M" }
{ "_id" : ObjectId("5de51001b2e406088d483c45"), "name" : "item02", "color" : "blue", "size" : "S", "memo" : null }
```

null を指定すると **対象フィールドが存在しないドキュメント・対象フィールドの値が null のドキュメント** の両方がとれる。

# `memo` が empty のドキュメントを取得する

そのまま指定すると意図通りの挙動になる。

```js
> db.items.find({memo: ""})
{ "_id" : ObjectId("5de51012b2e406088d483c46"), "name" : "item03", "color" : "yellow", "size" : "L", "memo" : "" }
```

ここまでの情報を整理すると以下のようになる。

name | memo | `$exists: true` | null | ""
:--: | :--: | :--: | :--: | :--:
item01 | （存在しない） | :x: | :o: | :x:
item02 | null | :o: | :o: | :x:
item03 | empty（空文字） | :o: | :x: | :o:
item04 | "hoge" | :o: | :x: | :x:

この情報を元に、それぞれを正確に抽出したい。

# 対象フィールドが存在しないドキュメントを抽出する

これは簡単で `$exists: false` を設定してあげれば良い。

```js
> db.items.find({memo: {$exists: false}})
{ "_id" : ObjectId("5de50feab2e406088d483c44"), "name" : "item01", "color" : "red", "size" : "M" }
```

# 対象フィールドが null のドキュメントを抽出する

先に書いたように `memo: null` では対応できないので `$and` を使って条件を絞る必要がある。

```js
> db.items.find({$and: [{memo: {$exists: true}}, {memo: null}]})
{ "_id" : ObjectId("5de51001b2e406088d483c45"), "name" : "item02", "color" : "blue", "size" : "S", "memo" : null }
```

# 対象フィールドが空のドキュメントを抽出する

これは先に書いたように `memo: ''` でいける。

```js
> db.items.find({memo: ''})
{ "_id" : ObjectId("5de51012b2e406088d483c46"), "name" : "item03", "color" : "yellow", "size" : "L", "memo" : "" }
```

# 対象フィールドが null でも空でもないドキュメントを抽出する

Ruby の `present?` のような条件だ。
これも `$and` を使って実現できる。

```js
> db.items.find({$and: [{memo: {$exists: true}}, {memo: {$ne: null}}, {memo: {$ne: ''}}]})
{ "_id" : ObjectId("5de51029b2e406088d483c47"), "name" : "item04", "color" : "green", "size" : "M", "memo" : "hoge" }
```

# 対象フィールドが存在しないか値が null か空のドキュメントを抽出する

こちらは Ruby の `blank?` のような条件。
先の条件の逆なので難しくない。

```js
> db.items.find({$or: [{memo: null}, {memo: ''}]})
{ "_id" : ObjectId("5de50feab2e406088d483c44"), "name" : "item01", "color" : "red", "size" : "M" }
{ "_id" : ObjectId("5de51001b2e406088d483c45"), "name" : "item02", "color" : "blue", "size" : "S", "memo" : null }
{ "_id" : ObjectId("5de51012b2e406088d483c46"), "name" : "item03", "color" : "yellow", "size" : "L", "memo" : "" }
```

上で整理した `$exists` と null の挙動をきちんと把握すれば、あとは条件を組み合わせればできることがわかる。
自動取得されたRDSのスナップショットが削除できない場合

自動取得されたRDSのスナップショットを削除しようとしたら、「システムスナップショットを削除することはできません」と言われて困惑している人向け。

# 状況
OracleのRDS環境を動作確認のために作ったら、知らぬ間に自動スナップショットが取得されていました。
RDSのインスタンスを削除してもそのスナップショットは削除されなかったので、手動で削除しようと思ったらこんなメッセージが出て削除できませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369844/d9c57974-e637-68c7-8dea-0e9a2b252ac0.png)

# 削除方法
左側メニューの「Automated backups」からバックアップを削除すると、連動して削除されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369844/6710fb9f-e2f0-11e7-1522-9aa6dbe295e0.png)

よくよく見てみれば、エラーメッセージの末尾にちゃんと書いてありますね。**「削除されたインスタンスのシステムスナップショットを削除するには、保持されている自動バックアップを削除します」**って。バックアップとスナップショットは別物。

エラーメッセージはちゃんと読みましょうという教訓でした。
【AWS】 fargate間のレスポンスタイムとサイドカー

## はじめに

fargateで複数のコンテナ間通信が発生する場合fargate間のレスポンスタイムがどのくらいかかるのか気になったので参考までに測定してみたメモ。

#### 構成

比較用に同一タスク上に複数コンテナ(サイドカー)を構築した場合と別タスクからELB経由でアクセスした際で比較を行った。
![レイテンシ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485398/62f8d1d5-b4ab-110f-03d6-70813a7c71aa.png)

#### 計測条件

別タスクのコンテナからELB経由でAPI Serverにアクセスした場合と、
同一タスクのコンテナからlocalhostでAPI Serverにアクセスした場合を
下記curlで測定した(localhostの場合のコマンド例)。

~~~
curl -kL -s -o /dev/null -w "%{time_total}\n" http://127.0.0.1/api
~~~

:information_source: ここでは `time_total` をレスポンスタイムとする

またそれぞれのコンテナ内で `lscpu` を見たところ別ものだったため別インスタンス上に配置されているものとする。

#### 計測結果

10回測定し最速と最遅を切り捨て8回の平均値とする。


||別タスク  |同一タスク  |
|---|---|---|
1|~~8~~|2  |
2|~~9~~|~~3~~  |
3|8|2  |
4|9|2  |
5|8|2  |
6|8|~~1~~  |
7|9|1  |
8|8|2  |
9|9|1  |
10|8|1  |
Ave.|8.4|1.6  |

(msec)

別タスクにすることで2者間の差である **6.8msec** が乗ってくることになる。

### スループット

同様に大きめのペイロードサイズ(100MB弱)を転送するときのスループットについても計測


||別タスク  |同一タスク  |
|---|---|---|
1|~~4,925~~|~~386~~  |
2|3,611|379  |
3|4,484|377  |
4|2,925|380  |
5|3,865|353  |
6|4,205|353  |
7|~~2,828~~|359  |
8|3,944|~~352~~  |
9|3,325|363  |
10|4,353|358  |
Ave.|3,839|365|

(msec)

2者間の差とペイロードサイズ(88,099,412byte)から **約200Mbps** 程度と推定される

## まとめ

このレイテンシーが許容されるのか否かで同一タスク上に構成すべきか検討材料になるであろう。
ただしスケールさせる場合はタスク単位となるためトレードオフである。
また本計測値はfargateのvCPUタイプやその他構成など条件によって変わってくるため参考値程度にとどめておく。
.gitignoreファイルを設定した

## きっかけ
ポートフォリオ作成中に、/vendor/bundle配下のファイルはgitの管理下から外すように教えてもらったため
## 方法
アプリのルートディレクトリ内に**```.gitignore```**ファイルを作成する

具体的なディレクトリは```/app名/.gitignore```

ファイル内に```、/vendor/bundle```と記述する
## 参考URL
https://wiseloan-cash.com/gitignore/
API等で取得した情報をMySQLのデータベースに格納するときに、2バイト文字が文字化けしてしまったときに確認すること


#はじめに

取得した2バイト文字が文字化けしてしまい、色々確認して解消したというメモに近いものです。


#環境

- MySQL
- Java

JavaのHttp Clientを利用してAPIを取得したデータを、
JDBCドライバーを利用してMySQLに接続し、DBに入れようとしています。

#そのいち

テーブルを作成した際に、お決まりの呪文を唱えているか。
お決まりの呪文は、以下の通りです。

```SQL
set character_set_client = utf8;
set character_set_connection = utf8;

CREATE TABLE `TABLE_NAME` (

(略)

) DEFAULT CHARSET=utf8';

```

ポイントはSQLを流す前に呪文を唱えることですが、
心配性な方は、CREATE TABLE文の終わりでも呪文を唱えましょう。


#そのに

HttpClientでリクエストをビルドする際、呪文を唱えているか

```Java
HttpClient client = HttpClient.newBuilder().version(Version.HTTP_2).build();
Builder requestBuilder = HttpRequest.newBuilder().uri(uri).setHeader("Content-type","application/json; charset=UTF-8");
HttpRequest request = requestBuilder.build();
```

setHeaderの後ろあたりの、`charset=UTF-8` が、呪文です。

#そのさん

JDBCドライバーの設定情報で、呪文を唱えているか

```properties:dbconnection.properties
driver.class.name=com.mysql.jdbc.Driver
uri=jdbc:mysql://mysql.test.com/mydb?useUnicode=true&characterEncoding=utf8
```

上記の`mysql.test.com`が接続先で、`mydb`がデータベース名です。
その後の`?useUnicode=true&characterEncoding=utf8` に注目してください。
呪文を唱えています。


#さいごに

私の場合は、[そのさん](https://qiita.com/wakiwaki/items/6a131636c2c3b9d91b43#%E3%81%9D%E3%81%AE%E3%81%95%E3%82%93) で解決しました。
似たようなことを、まったく同じ環境で実装したことがあるのですが、その時は文字化けしなかったです・・・
JavaScriptでカレンダーを作ってみた

JavaScriptの基本を勉強したのでなにか作ってみようと思い、
カレンダーの制作を行いました。

<img width="306" alt="スクリーンショット 2019-12-03 21.21.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528800/a35e40a2-e5a0-9564-54c7-04af1b4c00cd.png">

<img width="610" alt="スクリーンショット 2019-12-03 21.25.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528800/c80d370b-5b6c-c5ad-d71a-2e49a1b912f7.png">

どこで何をしているかをコメントで書いておかないとわからなくなるので
コメントを書くことを意識しようと思いました。

参考にしたサイト
http://cly7796.net/wp/javascript/create-a-calendar-with-javascript/
三項演算子で break や continue は使えない

三項演算子は『式』("expression") に対して使うもの。
break や continue は『式』ではなく『文』("statement") なので下の例のような横着はできませんよ、という話.

```python:ダメな例
for i in range(100):
     break if i > 20 else continue
```
Ionic4でPWA対応してみたので、注意点を２つ述べる

この記事は、Ionic Frameworkアドベントカレンダー3日目の記事です。

個人でIonicを使って開発している、[Googleカレンダーと連携する日程調整アプリ「アイテマス」](https://aitemasu.me/)をPWA対応しました。その際に、はまったり忘れがちな設定が２つあるので、それらについてまとめます。
Ionicのバージョンは下記のとおりです。

>   Ionic CLI                     : 5.4.5 (***)
>   Ionic Framework               : @ionic/angular 4.11.2

基本的に[公式のドキュメント](https://ionicframework.com/jp/docs/angular/pwa)通りに行えばとりあえずPWA化します。その他の細かい調整はGoogle Chromeの開発者ツールを使って行ったらOKです（[Lighthouse](https://www.suzukikenichi.com/blog/lighthouse-validates-progressive-web-app/)というよさげなツールもあるみたいですね）。




## スプラッシュスクリーン対応

[こういうGenerator](https://appsco.pe/developer/splash-screens)を使っておけば問題なくいけると思いきや、iOSで表示されませんでした。どうやらしっかりとorientationパラメータなどもセットしないといけないようです。

[PWAのSprach Screen対応メモ](https://qiita.com/fluflufluffy/items/506422821c675b61c8fc)

スプラッシュスクリーンがないと、PWAとしてホーム画面に設置し、しばらくしてからアプリを起動したときなど、画面全体が白い状態がしばらく続いて不具合のようにみえてしまいます。体感速度を上げるためにも、必ずスプラッシュスクリーンを設定して、きちんと表示されているか確認しましょう。

## 更新検知の仕組み

僕の設定がおかしいのかもしれませんが、PWAとしてホーム画面に設置したアプリはかなり強力なキャッシュが作られるので、サーバーに再ビルドしたPWAアプリを設置してもなかなか更新されません。さらに、ホーム画面に設置するとブラウザの更新ボタンも押すことができなくなるので、ユーザーに手動更新してもらうのも難しいです。

というわけで、サーバー側のコードが更新されたらPWAの方で更新通知アラートを表示し、それをタップしたらプログラム側から強制的に更新処理が走るようにします。

具体的には[この記事](https://alligator.io/angular/service-worker-updates/)を参考に、下記のようなserviceを作って、app.module.tsのprovidersに設定しておけばOKです。

```typescript:pwa-update.service.ts
import { Injectable } from '@angular/core';
import { SwUpdate } from '@angular/service-worker';

import {
  AlertController
} from '@ionic/angular';

@Injectable({
  providedIn: 'root'
})
export class PwaUpdateService {

  constructor(
    private swUpdate: SwUpdate,
    private alertCtrl: AlertController,
  ) {
    this.swUpdate.available.subscribe(evt => {
      // an update is available, add some logic here.
      this.showUpdateToast();
    });
  }

  async showUpdateToast() {
    const alert = await this.alertCtrl.create({
      header: 'アプリの更新通知',
      message: 'アプリの新バージョンがあります。ページを更新してください。',
      buttons: [{
        text: '更新する',
        handler: () => {
          window.location.reload();
          return true;
        }
      }]
    });
    await alert.present();
  }
}

```


このコードによって、サーバー側でPWA用のソースコードが更新されたら、「アプリの新バージョンがあります。ページを更新してください。」といったアラートが表示されるようになります。

以上になります。
これらのふるまいは、[Googleカレンダーと連携する日程調整アプリ「アイテマス」](https://aitemasu.me/)で確認できると思うのでぜひお試しください。
東京大学2019年数学入試第1問をpython sympyに解かせてみた


東京大学2019年数学入試第1問をpython sympyに解かせてみた。
何秒で解けるかを測定するために、時間も測ってみました。

問題は、こちらを参照ください。
https://sokuho.yozemi.ac.jp/sokuho/k_mondaitokaitou/1/kaitou/kaitou/1306831_5342.html

私のPCでは、23秒で計算できました。

```py
import sympy as sym
import datetime
(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z) = sym.symbols('a b c d e f g h i j k l m n o p q r s t u v w x y z')

f = (x**2 + x/sqrt(1+x**2))*(1+ x/((1+x**2)*sqrt(1+x**2)))

#start time
start_t = datetime.datetime.now()

#calc
answer=sym.integrate(f,(x,0,1))

#end time
end_t = datetime.datetime.now()

#elapse time
elapse_t = end_t - start_t

print(answer)
print(elapse_t,"秒かかりました")
```
![SnapCrab_NoName_2019-12-3_21-15-30_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544946/1b739f4a-d4eb-1af3-489e-131087453721.png)
手軽にPC上でチャットボットの開発環境を作る

創作意欲が湧き、チャットボットを新たに作ろうと思い立ち、まずは環境どうしようかと試行錯誤した結果、Botpressで構築してみることにしました。

探し始めるとBotkitが有名だったようですが調べたらMicrosoftに買収されてたんですね。
他にないかと探してみたら、Botpressにたどり着きました。

詳細はこちらで
https://botpress.io/

では、インストールをしていきましょう。
その前にDockerを動くようにしておいてください。
私はWindows10 Proで構築しています。

# PowerShell起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/11e37152-1aea-0944-a6be-b07e2fcc3a9a.png)

Windows Terminalで起動してみました

# BotpressのDockerコンテナを作成
＞docker run --detach --name=botpress --publish 3000:3000 --volume botpress_data:/botpress/data botpress/server:latest

Unable to find image 'botpress/server:latest' locally
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from daemon: manifest for botpress/server:latest not found: manifest unknown: manifest unknown.
See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.

あれ？エラーになる。。。

docker hubで探して最新のタグ名を取得
https://hub.docker.com/r/botpress/server/tags

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/da8e3f58-9117-6def-a77a-b15f6fd81515.png)

docker run --detach --name=botpress --publish 3000:3000 --volume botpress_data:/botpress/data **botpress/server:2019-11-28-misunderstood**

無事起動しました。

＞docker ps
CONTAINER ID        IMAGE                                      COMMAND                  CREATED             STATUS              PORTS                    NAMES
aec2835d2e79        botpress/server:2019-11-28-misunderstood   "/bin/sh -c './duckl…"   11 minutes ago      Up 11 minutes       0.0.0.0:3000->3000/tcp   botpress

起動も確認できました。

# ブラウザでBotpressを呼び出す
http://localhost:3000/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/e558ea52-aba8-9022-8111-a7febaa4e190.png)

ボットを作成してみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/a4b196b3-5ac1-f2c1-e551-734c877ac2dc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/b8a5e2f9-37d4-f90e-c23a-30d2c86d6e84.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/718cb9ac-9398-6042-4e11-d1c17584c1da.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/cb7aa88d-1323-320f-bbce-699486b16033.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/446cc6b1-d2d8-8906-2d19-f3ba2466bfb3.png)

動きました。
フローで視覚的に見れて、エミュレーターもあるので便利だと思いました。

今回はここまで。
その技術選択は正しいか？ - React、SPA、Flux、Redux

# はじめに
近年Web技術は様々な選択肢が存在しています。その中でユースケースに応じて適切に技術選択することがプロダクトのためにはとても大切です。

エンジニアの興味関心だけで不要な技術選択をして、開発速度やユーザ体験の低下は起きていないでしょうか？

また技術選択をするときに正しい言語化をできているでしょうか？

- コンポーネント開発をしたいから、Reduxを採用する
- SPAにしたいから、Reduxを採用する
- 単一フローを採用したいから、Reduxを採用する
- React Hooksの登場でReduxは必要なくなった

これらはすべて適切な説明ではありません。

今回は、React、SPA、Flux、Reduxをそれぞれ採用している方が、改めてその技術選択をしていることを言語化できているかの確認になればと思います。

## Reactを採用するべきか？

Reactの価値は宣言的UI、コンポーネント開発にあります。
宣言的UIではないことで発生する問題を実際に感じたことがあるのでしょうか？
もしこれらの価値を自身で説明することができなければ、Reactに限らずVue.jsやAngularなどの宣言的UIフレームワークが不要かもしれません。

また単方向バインディングもReactの特徴です。
もしこれの価値を自身で説明することができなければ、ReactとVue.jsの選択を適切にできていないかもしれません。



## SPAを採用するべきか？
宣言的UIでかつコンポーネント開発が必要だからといって、SPAにしなければいけないというわけではありません。
ここには明確に技術的な境界が存在します。

名前の通り「単一ページのアプリケーション」である必要があるのでしょうか？
通常のWebページのように画面遷移してはいけないのは何故でしょうか？

あなたはSPAがないことで発生する問題を実際に感じたことがあるのでしょうか？
もしこれらを自身で説明することができなければ、SPAは不要かもしれません。

## Fluxを採用するべきか？
ReactやSPAを採用したからといってFluxにする必要はありません。
ここには明確に技術的な境界が存在します。

Fluxの価値は単方向フローです。
単方向バインディングと区別せずに議論されていることがあります。
単方向バインディングと単方向フローの違いを説明できるでしょうか？

またFluxはどのように単方向フローを実現しているのでしょうか？
また単方向フローはどのような課題を解決しているのでしょうか？
単方向フローにしないとどのような実装になり、どのような問題が起きるのでしょうか？

あなたはFluxがないことで発生する問題を実際に感じたことがあるのでしょうか？
もしこれらを自身で説明することができなければ、Fluxは不要かもしれません。

## Reduxを採用するべきか？
Fluxを採用したからといってReduxにする必要はありません。
ここには明確に技術的な境界が存在します。

Fluxで実現できておらずReduxで実現していることはなんでしょうか？
Reduxの三原則は、Single source of truth、State is read-only、Changes are made with pure functionsにあります。
これらの三原則がもたらすメリットはなんでしょうか？


またReduxはFluxで解決できていないProp Drillingの問題をConnect(Selector)で解決しています。

あなたはReduxがないことで発生する問題を実際に感じたことがあるのでしょうか？
もしこれらの価値を自身で説明することができなければ、Reduxは不要かもしれません。



## React Hooksの登場でReduxは不要になるのか？

React Hooksの登場により、Reduxの三原則の価値はなくなるのでしょうか？
それともReact HooksのuseReducer、useState、useContextなどを利用して、Redux相当のものを自作できるということでしょうか？

もしこれらを自身で説明することができなければ、Reduxは必要かもしれません。



# まとめ
Fluxを提案したReact Coreチームに所属しているDan Abramovは以下のように主張しています。

> もしFluxが解決する問題をあなた自身が解決しようとしたことがない場合、Fluxが何を解決するかを理解することは難しいです。
> 私は人々がトレードオフを理解しないがために、Fluxの最悪な特徴を獲得して、最高の特徴を見逃すのを見てきました。
> https://medium.com/swlh/the-case-for-flux-379b7d1982c6


またDan AbramovはRedux作者でもあり、別の記事では以下のように主張しています。

> 人々はReduxを必要とする前からReduxを使おうとします。
> しかしながら、あなたが今まさにReactを学習中なのであれば、Reduxを最初の選択にしてはいけません。
> その代わりReactで考えることを学びましょう。本当に必要になったら、または何か新しいことに挑戦したくなったらReduxに戻って来てください。
> https://mae.chab.in/archives/2937



課題を解決するためにフレームワーク使うことが大切です。フレームワークの必要性を言語化できていない状態で採用してもフレームワークが解決している目的を達成できない可能性があります。そうなるとただ冗長なコードが増えただけという結果になりかねません。

そうならないためにも一度はフレームワークを使わずに挑戦して、フレームワークが解決しようとした課題を自分で体験することがとても大切です。


また新しく登場して流行しているフレームワークは素晴らしく見えます。
そこで新しいフレームワークを導入する際には、一度立ち止まりこのフレームワークの価値を表面的にではなく何回も深堀りして考えてみてください。

それを踏まえてプロダクトと組織のことを考え、長期的に負債を生まないように適切な解決手段を提案しなければなりません。

これらのバランスを考え技術選定できることがアーキテクトの実力の見せ所であり、本当のスキルではないでしょうか。
#Rails OR #Ruby + ActiveSupport の String#in_time_zone で 2月29日 30日 31日 が3月にずれるのだが

Rubyとか言語使用に関わる、深い事情ありの話かと思った。

Date.new を利用した方が良いかな。

```rb
require 'active_support/core_ext'

'2019-2-29'.in_time_zone('Tokyo').to_s
# => "2019-03-01 00:00:00 +0900"

'2019-2-30'.in_time_zone('Tokyo').to_s
# => "2019-03-02 00:00:00 +0900"

'2019-2-31'.in_time_zone('Tokyo').to_s
# => "2019-03-03 00:00:00 +0900"

'2019-2-32'.in_time_zone('Tokyo').to_s
# ArgumentError: argument out of range


Date.new(2019, 02, 28).in_time_zone('Tokyo')
# => Thu, 28 Feb 2019 00:00:00 JST +09:00

Date.new(2019, 02, 29)
# ArgumentError: invalid date
```



# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2804








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
AWS CLIを利用した、サービス監視について(Windows)

#概要
　AWS CLIを利用したWindowsサービス監視について記載します。
　CloudWatch Agentでは、プロセス監視が可能ですが、サービス監視を行う事が出来ません。
　そこで、Windowsのコマンドでサービスの起動状態を確認し
　結果をCloudWatchに出力するといった内容となります。※
　※出力=put　の意味となります。

#事前設定
　本内容では、下記項目が必要となるので先事前に準備をお願いします。
　①CloudWatch メトリクス 出力用 IAMユーザ作成 ※1
　②AWS CLIインストール,初期設定(IAMユーザ設定含む) ※1
　※1 上記内容は、AWSに公式手順がある為参照してください。
#設定内容
　今回の設定内容については、2フェーズに分け作業を実施します。
　★設定フェーズ
　　①監視サービス名確認作業
　　②監視サービス確認用バッチファイル作成

##サービス名確認作業
　まず、初めにサービス名の確認を行います。
　Windowsのサービスより、対象のサービス一覧を確認して下さい。※2
　対象のサービスをダブルクリックし、プロパティ情報を表示してください。
　表示完了後、【サービス名】を確認してください。今回サービス名に記載されていないようを利用します。
　※本例では、Task Schedulerのサービス確認を実施しています。
　※2 ファイル名を指定して実行【services.msc】を起動する事により表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527985/65889a3c-e4de-e934-820d-dfbb131aa535.png)

##サービス確認用バッチファイル作成
　次にバッチファイルを作成します。
　まず、メモ帳を開き下記内容を入力してください。
　一部内容は、可変となるため入力をお願いします。

```bash:win_service.bat
@echo off

rem AWSインスタンスメタデータ取得
rem 取得後、【instanceid】に代入
for /f "usebackq tokens=*" %%a in (`PowerShell.exe -Command invoke-restmethod -uri http://169.254.169.254/latest/meta-data/instance-id`) do @set incetanceid=%%a

rem サービス稼働確認(errorlevel の結果により、Processesの値を変更)
sc query 【###確認したサービス名を入力###】 | findstr STATE | findstr RUNNING >null
if %errorlevel% == 0 (
echo errorlevel=%errorlevel%
set Processes=1
) else (
echo errorlevel=%errorlevel%
set Processes=0
)
echo Processes=%Processes%

#Putコマンドを利用し、CloudWatchに送信
aws cloudwatch put-metric-data --metric-name "【###メトリクス名###】" --namespace "【###ネームスペース名###】" --region 【###リージョン名###】 --value %Processes%  --unit "Count" --dimensions "InstanceId=%incetanceid%"
```
★スクリプト説明
　本スクリプトは、sc queryの結果を確認し正であれば、Processes変数に1を代入
　誤であれば0を代入します。その後、CloudWatchにProcessesの値が送信されます。
　※稼働しているサービスのみ表示されるので、STOP等の場合は表示されない。すなわち誤となります。

後は、タスクスケジューラで繰り返しスクリプトを起動させれば完了です。

#結果
今回は、例として下記設定で実施しました。
★本例での設定

 ```bash:設定内容
　監視サービス名 "schedule"
　metric-name "schedule"
　namespace "Windows"
  ```

★出力結果(CloudWatch内の出力結果です。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527985/9b6ec657-7a94-d6a4-df81-bd1f8b7dc9ce.png)

CloudWatch 内にカスタムメトリクスが作成されています。
後は、本スクリプトを定期間隔で実行すれば完了となります。
※タスクスケジューラによる定期間隔設定方法については、[batファイル定期実行方法について](https://qiita.com/0HY4/items/f5953721712a76e24e37)に記載しています。

以上が、今回の内容となります。

#参考URL
　下記内容を参考にし本スクリプトを作成しております。

　・CloudWatch メトリクス 出力用IAMユーザ作成方法
　　(https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/create-iam-roles-for-cloudwatch-agent.html)

　・Windows AWS CLIインストール
　　https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-windows.html

　・sc queryコマンド説明資料
　　https://win.just4fun.biz/?%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88/%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E4%B8%80%E8%A6%A7%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B%E3%83%BBsc%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89
自然に動画を繋げたい

#はじめに
この記事はSFC Advent Calendar 2019の5日目の記事です! 
初めまして、来年からSFC20として入学する予定のしまだしおり（@sfc_shiori）と申します。
本当はディズニーのことを書こうと思っていたのですが、情報技術じゃないとバンされてしまうそうです、、、苦肉の策に思いついたのが動画編集(動画編集も大丈夫なのか不安)のことだったのでそのことを書こうと思います！（低レベで申し訳ないです）
では、行きましょう！！

###動画編集なれそめ
今年の未来構想キャンパス「WS03：映像づくりワークショップ ～考えながら撮る・撮りながら考える～」に参加するための課題として初めて映像編集をしました。（未来構想キャンプの他の課題は私に出来そうになかった）
そこで提出した課題は↓でした。
https://youtu.be/qFuxF8rHoc0

（え、だんだん傾いてる、画質荒すぎだって！？！！！そんなん知ってるよ！！！
え、机とパソコン汚すぎだって？！！！そんな所見んな、のび太さんのえっち！！）

ごめんなさい、取り乱しました。
12時間かけて私なりに頑張った結果でした。

これは、TikTokとiMovieを駆使して作られています。
個人的に私はどうも動画と動画の繋げ方にこだわりがあるらしく、スライドショーのようには繋げたくないし、ブチ切れで繋げるのもあまり好きじゃない。
今日は、その悩みを解決するために私がやっている動画繋げを紹介します。

##TikTokで動画で撮る
TikTokというとパリピが使っているイメージですが、本当に動画自体も面白いと思いますし、何より初心者への動画編集が適していると思います。

その一番のポイントは
・倍速変更がめっちゃ楽！！！！

0.3×　0.5×　1.0×　2.0×　3.0×
が動画を撮りながらすぐ変更できます。
ちなみにわかりづらいですが、「◯◯×」というのは、音源が〇〇倍速になるのではなく、撮った後の動画が◯◯倍速になります。
（ex 2.0×ボタンを押すと音源は0.5倍速でゆっくりになり、それで撮った動画を再生すると2倍速になります）
これが使えるようになると先ほどの動画のように、動画と動画の切れ目を意識させないで手から物を出せるようになります。
※TikTokは画質が落ちるのでそこは難点



##オシャンな動画の繋げ方
個人的にとても好きでよく使っているやり方です。
手でレンズを隠すのでなるべくレンズが小さいスマホでやるのがオススメです。

🔴好きに撮る
🔴手をカメラのレンズに近づけてる
↓
🔴手のせいで画面が暗くなる
⚫️動画を切る
↓次のシーンの場所に移る
🔴再度カメラのレンズを手で隠す
🔴カメラのレンズから手を遠ざけていく。
分かりづらいですね、百聞は一見にしかず、どんな動画になるのか見ましょう。↓
https://youtu.be/l4hfFMiVOUQ

ね？ちょっと瞬間移動感でるような気がしませんか？(私だけでしょうか、、、)

この動画は
外カメラ→外カメラ
ですが、
内カメラ→外カメラ
でやったりすると動画がスマホを通り抜けたようになります。
ぜひ試してみてください！


#終わりに
貴重なお時間を費やして頂きありがとうございます。もう知ってるしもっと色んなこと出来るよって方は、私も勉強したいのでぜひぜひDMでも話しかけて頂きたいです。
ほぉーなるほど！って思ってくれる方が1人でもいてくださると嬉しいです。

####おまけに
そして、この未来構想キャンプに参加した時に石川初教授がおっしゃっていた言葉です。
「始めることは誰にでも出来る、でも逆に終わらせる事が出来る人は、ほとんどいない」
そう、何かどこかに旅行にいったり、何かした事だったり、終わりにするのって凄く難しいですよね。その一つの終わりとして動画があっても良いのかもしれないです。私も高校生活があと少しで終わりなので、ゆるーく友達と動画を撮ったりしています。ぜひ「終わり」を作ってみませんか？