OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】うるう年を判定する

#初学者が押さえるべきポイントが網羅

初学者が書くプログラムとして
3の倍数、5の倍数を出力するfizzbuzz問題をよく見かけますが、
if文、変数、比較演算子、型など初学者がまず学ぶのに
より実践的・実用的なプログラムとして、うるう年の判定はぴったりだと思います。

```python:leap.py
year_str = input("西暦4桁を入力")
year = int(year_str)

if year % 100 == 0 and year % 400 != 0:
    print("平年です")
elif year % 4 == 0:
    print("うるう年です")
else:
    print("平年です")
```
あとPythonはインデントに要注意ですね。
vue-metaを用いたOGPやJSON-LD用のメタタグ生成

vue-meta
https://github.com/nuxt/vue-meta

・Title and Description
・OGP
・JSON-LD
を生成するにはvue-metaが便利。
弊社ではNuxtを使わず、Vue.jsで作っています。
Vue-metaはNuxtプロジェクトの中で開発しているのでVue.jsでは使えないと思っていたのですが、Vue.jsでも使えました😍

### この記事を書いたときのバージョン
`"vue": "^2.6.10",`
`"vue-meta": "^2.3.1",`
 
### インストール
`npm install vue-meta --save`

### コードの変更箇所

```ts
// src/main.ts
import VueMeta from 'vue-meta';
Vue.use(VueMeta);
```

```js
// Page.vue
import {metatag} from ‘@/metatag/metatag.ts'
export default Vue.extend({
    data() {
        return {
            this.initialized = false;
            this.param = {hoge: ‘bar'}
        }
    },
    mounted() {
        // ここでAPI通信などの非同期処理を行う。
        this.initialized = true;
    },
    metaInfo() {
      return this.initialized ? metatag(this.param) : null; // this.initializedが変更されると検知してくれる😂
    },
});
```

```ts
// src/metatag/metatag.ts
const TITLE = ’サイト名’;

export function metatag(params: any) {
  const description = `descriptionを書くよ ${JSON.stringify(params)}`;
  return {
    title: TITLE,
    meta: [
      {name: 'description', content: description},
      {property: 'twitter:card', content: 'summary'},
      {property: 'twitter:title', content: document.title},
      {property: 'twitter:site', content: '@anonymous'},
      {property: 'twitter:creator', content: '@anonymous'},
      {property: 'twitter:description', content: description},
      {
        property: 'twitter:image',
        content: 'https://FQDN/favicon256.jpg',
      },
      {property: 'og:title', content: document.title},
      {property: 'og:description', content: description},
      {property: 'og:type', content: 'website'},
      {property: 'og:url', content: location.href},
      {
        property: 'og:image',
        content: 'https://FQDN/favicon256.jpg',
      },
    ],
    script: [
      {
        type: 'application/ld+json',
        innerHTML: JSON.stringify(
          [{
            '@context': 'http://schema.org',
            '@type': 'Organization',
            'url': location.href,
            'logo': 'https://FQDN/favicon256.jpg',
          },
            {
              '@context': 'http://schema.org',
              '@type': 'WebSite',
              'name': document.title,
              'alternateName': description,
              'url': location.href,
            },
          ], null, 2,
        ),
      },
    ],
  };
}
```

vue-headという類似ライブラリを使っていたんですけど、
`this.$emit(‘updateHead’);`
というメソッドを非同期通信完了のタイミングで実行しなければならなかったのが辛かった・・・
また、JSON-LDの書き方がすごくスッキリしました。

これで最低限のOGPとGoogle対策ができました。
とはいえ、Twitter CardやGoogleに完全対応するには、DynamicRenderingやSSRが必要です。
Vue.jsで開発しているとSSR対応は難しいので、HeaderlessChrome（puppeteer）を使ったDynamicRenderingをやることにしました。
DynamicRenderingに関しては結構長い記事なので次回更新します。
スケーリング

<img width="340" alt="キャプチャ22.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/a76155cb-85dd-1c91-aac8-978031ba2955.png">

<img width="432" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/275549ef-89b9-80be-51ef-8e60ad1e0236.png">
3σ法の適用
<img width="479" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/59fc6cae-79a6-3de9-5ca9-fe151ec8507a.png">
3σ法を用いて、外れ値除去することで決定係数が落ちてしまった。
このことを過学習という

スケーリング方法
<img width="400" alt="コメント 2019-11-12 222912.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/3048d0fb-0826-ba6b-30c1-6a9fd6dcaf12.png">
スケーリングすることで重みの確認
重要なパラメータがわかりやすくなった
<img width="433" alt="コメント 2019-11-12 222912.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/8f46606b-c1bd-d243-65f8-e1915ab552f3.png">
【salesforce】ごちゃごちゃしたリストの表示はMapよりも内部クラスの方が楽

オブジェクトを一つに限らず、二つ三つ跨いで取得してVF側で表示させる際に

Mapを使ってネストさせるのもいいんですが、

内部クラスを使うとかなり簡単に値の表示ができます。

```java:
    public class wrapperClass{
        
        public Integer i { get; set; }
        public String s { get; set; }
        public Contact c { get; set; }
        
        public wrapperClass(){
            this.i = 1;
            this.s = 'Sample';
            this.c = new Contact(
              FirstName = 'Test'
            );
        }
    }
```

書き方はシンプルで普通にクラスとコンストラクタを用意します。

親のクラスの方では、

```java:
  public class wrapperTestcontroller {
    
    public List<wrapperClass> wrapperList{ get;  set; }
    
    public wrapperTestcontroller(){
        this.conditions = new Contact();
        this.wrapperList = new List<wrapperClass>();
        wrapperList.add(new wrapperClass());
        system.debug(wrapperList);
    }
```

リストに格納してしまいましょう。
※初期化するのを忘れるとエラーで返されます。

今回はInteger,String,Contactをごちゃまぜたリストにしました。

これをデバッグでみるとどうなるでしょうか。

<img width="596" alt="スクリーンショット 2019-11-12 22.22.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472705/2c418444-3a28-c7f6-e65c-51e0c546bf1c.png">

うまく値が入っています。

これをVF側に渡してあげれば、オブジェクトなどの垣根を無視したリストが作れるので

うまく値を表示させるのに便利です。

またコンストラクタに引数を渡せばその引数を使ってSOQLを使ったりもできます。

もちろん引数を違うものを設定すれば違う処理を書くこともできます。

MapをVFで使う時ってネストされてると使いにくいイメージがあるのでこれだとかなり便利ですね。

#profile

生まれも育ちも大阪の浪速中の浪速っ子が30才未経験からITエンジニアとして生きるブログもやってます。
よかったらみてください:muscle_tone2:

<a href="https://blogmura.com/profiles/11016817?p_cid=11016817"><img src="https://blogparts.blogmura.com/parts_image/user/pv11016817.gif" alt="PVアクセスランキング にほんブログ村" /></a>
[VSCode/TypeScript] TSServerのメモリ使用量が異常に多い場合の対処法

VSCode の Remote WSL で TypeScript/React のプロジェクトを作っていたら WSL 上の node プロセス (おそらく TSServer) のメモリ使用量が異常に高くなり、tsserver が頻繁に強制再起動されたり、補完や Quick fix に 10 秒以上かかるなど作業に支障をきたしていました。

調べたところ **TypeScript のキャッシュを消せばいい**らしく、行ってみたらメモリ使用量が **1GB 以上 => 100MB 以下**と大幅に改善しました。

WSL 以外でこの現象が起きるのかはわかりませんが各OSのキャッシュの場所を記載しておきます。

- Linux (WSL) - `~/.cache/typescript`
- macOS - `~/Library/Caches/typescript`
- Windows - `~\AppData\Local\Microsoft\TypeScript`
DSP FMラジオ RDA5807FP+ATTINY85+AQM0802A その5 電源、タクトスイッチ

#はじめに
* 電池駆動DSPラジオのその5。電源とタクトスイッチについての記事です。

#電源の検討
* 電源電圧については、3.3Vで統一するか、5Vも供給するかで悩みました。LCDに一般的な1602Aを用いると5Vが必要になりますが、それ以外のパーツは3.3VでOK。ATTINY85、RDA5807FP、オーディオアンプとも3.3Vで動作可能。
* LCDをAQM0802Aにしたため、3.3Vで統一することにしました。
* 3.3Vの供給については、「1.5Vからの昇圧」「4.5Vからの降圧」「3.0Vそのまま」の３通りを検討しましたが、普通の「4.5Vからの降圧」を選びました。
* レギュレータの（最大）電流ですが、正直よくわからなかったのですが、500mAのレギュレータを選んでみました。

#電源：使用したもの
* 乾電池ケース：単4*3本用。スイッチ付き。適当に選びました。
* ３端子レギュレータ：NJU7223　出力電流 500mA。　秋月電子にて購入。
* セラミックコンデンサ：　0.47μF　２個
* 抵抗入りLED：　秋月電子にて購入。電流制限抵抗が不要になるので。

#回路
* NJU7223のデータシート通り。0.47μFのセラミックコンデンサを利用しましたが、特に問題は生じていません。
* NJU7223のピン配置が、他のレギュレータと異なっているようです。Groundピンは中央ではありません。注意して配線してください。
* LEDは抵抗入りのを選びました。値段も安価で、扱いやすいので。

#タクトスイッチについて
* SEEKの再開と、周波数調整（+0.1MHZ)のためにタクトスイッチを使うことにしました。
* チャタリング対策については何通りか検討したのですが、最終的にはスイッチの端子間にコンデンサ（0.1μF）を挟む、という簡易的な方法にしました。手元にあった表面実装品を使っています。
* 画像のタクトスイッチは2接点のものを使っていますが、1接点のものでもOKです。
* ソフトウェアの方で対応する方法もありそうですが、コードが冗長になるのが嫌だったので、ハード的な対応を選んでいます。
* 本来は、チャタリングの挙動をオシロで分析してから対策すべきでしょうが、この簡易的な方法でも特に不具合はでていません。もしかするとチャタリング対策は不要なのかもしれません。
![tact_sw.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482773/71b0b5d5-2218-1fcf-867a-d49d422f1195.jpeg)

#タクトスイッチとATTINY85の接続
* タクトスイッチの状態を、ATTINY85のデジタルピンで監視する形にしています。以下のように利用しています。
    * SEEK再開（開始）ボタン：　Ping2(PB3) 
    * +0.1MHZボタン：　Ping6(PB1)
 
#おまけ
* チャタリング対策不要の（安価な）スイッチを探してみたのですが、案外みつからないものだと思いました。Aliexpressでタッチセンサーなども買ってみましたが、上手く使えませんでした。
プロデルでjpeg画像のタグを編集したい #0

NASにたまりにたまったjpeg画像（およそ２万枚）を整理しかつ容易に探索できる、画像DBのようなものを作る必要があって、PowerShellあたりで手軽に画像ファイルのタグにアクセスできないかと調べていたら、プロデルでもCOMオブジェクトを呼び出せるのを思い出してちょこっと書いてみました。

```
COM_shellというCOM型(「Shell.Application」）を作る
shellは、COM_shellからインスタンスを作ったもの
folderは、shell:NameSpace(「C:\」)
fileは、folder:parseName(「P000.jpg」)
310回値にカウントしながら繰り返す
	「Id:[値] 」&[folder:GetDetailsOf(file,[値])]を報告
繰り返し終わり
```

これを実行すると、結果はこんな感じです。

```
Id:1 26.1 KB
Id:2 JPG ファイル
Id:3 2019/11/12 14:45
Id:4 2019/07/31 20:34
Id:5 2019/11/12 16:11
Id:6 A
Id:7 
Id:8 
Id:9 イメージ
Id:10 PC001\user001
Id:11 ピクチャ
Id:12 
Id:13 
Id:14 
Id:15 
Id:16 
Id:17 
Id:18 テスト
Id:19 評価なし
Id:20 
Id:21 
Id:22 
Id:23 
Id:24 テスト
Id:25 
Id:26 
Id:27 
Id:28 
Id:29 
Id:30 
Id:31 ‪300 x 200‬
Id:32
～以下略～ 
```

Id：18がエクスプローラーでタグとして埋め込んだ文字列です。
タグの取得はすんなりできたものの、編集は~~別のCOMオブジェクトを使うようですが~~、.NETからやるようなのですが、さてどうしたものですかね。
～続く～
asyncio を使って非同期処理をしてみた

# きっかけ

`asyncio`の良さげなサンプルコードがなかったのですが、[Python でのオンデマンド・データ, 第 3 回 コルーチンと asyncio](https://www.ibm.com/developerworks/jp/library/ba-on-demand-data-python-3/index.html)がレストランにいるウェイターが複数のオーダーに対応するといったより具体的なストーリーを交えて説明していたので一番分かりやすくて参考になります。
よく見かける[python3 の async/awaitを理解する](https://qiita.com/maueki/items/8f1e190681682ea11c98)や[Pythonにおける非同期処理: asyncio逆引きリファレンス](https://qiita.com/icoxfog417/items/07cbf5110ca82629aca0)よりも良いです。

# 開発
```python
import asyncio
import time

async def start_time(src):
	await asyncio.sleep(src)
	print("START!!!")

async def main_process(span):
	idx = 1
	while True:
		await asyncio.sleep(span)
		num_active_tasks = len([ task for task in asyncio.Task.all_tasks(loop) if not task.done()])
		if num_active_tasks == 1:
			break
		print("[run:{}]{}秒経過".format(num_active_tasks, idx * span))
		idx += 1


async def end_time(src):
	await asyncio.sleep(src)
	print("END!!!")

if __name__ == "__main__":
	loop = asyncio.get_event_loop()
	try:
		loop.run_until_complete(
			asyncio.gather(
				start_time(10),
				main_process(1),
				end_time(20)
			)
		)
	finally:
		loop.close()

```

注目点は
`len([ task for task in asyncio.Task.all_tasks(loop) if not task.done()])`
で `asyncio.Task.all_tasks(loop) if not task.done()` とすることで現在常駐しているタスクを取得することができます。

# 結果
出力結果は下記の通りです。
メイン処理のみ起動している場合はloopから抜けています。

```
[run:3]1秒経過
[run:3]2秒経過
[run:3]3秒経過
[run:3]4秒経過
[run:3]5秒経過
[run:3]6秒経過
[run:3]7秒経過
[run:3]8秒経過
[run:3]9秒経過
START!!!
[run:2]10秒経過
[run:2]11秒経過
[run:2]12秒経過
[run:2]13秒経過
[run:2]14秒経過
[run:2]15秒経過
[run:2]16秒経過
[run:2]17秒経過
[run:2]18秒経過
[run:2]19秒経過
END!!!
```

# おわりに
`asyncio.Task.all_tasks()` ですが Python3.7 以降では非推奨で3.9では削除されるとのことです。特に`asyncio`の部分でversionが上がるごとに書き方がかなり様変わりしそうです。
([Python3.8 doc Task オブジェクト](https://docs.python.org/ja/3.8/library/asyncio-task.html#asyncio.Task.all_tasks) を参照)

# 参考したリンク
- [Python3.6 doc 18.5.3. タスクとコルーチン](https://docs.python.org/ja/3.6/library/asyncio-task.html#tasks-and-coroutines)
- [Python でのオンデマンド・データ, 第 3 回 コルーチンと asyncio](https://www.ibm.com/developerworks/jp/library/ba-on-demand-data-python-3/index.html)
- [python3 の async/awaitを理解する](https://qiita.com/maueki/items/8f1e190681682ea11c98)
- [Pythonにおける非同期処理: asyncio逆引きリファレンス](https://qiita.com/icoxfog417/items/07cbf5110ca82629aca0)
Scikit-learn のさわり

<img width="578" alt="コメント 2019-11-06 140638.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/1ad7b69f-a886-caea-95ee-85850b773dcc.png">

model.coef_ = 偏回帰係数
model.intercept_ = 切片

<img width="300" alt="コメント 2019-11-06 140638.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/1cffcfa5-db15-322d-fde0-9650eb1bad8b.png">

<img width="531" alt="キャプチャ1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/efe3205c-9e5a-c64b-6f6a-d113febf75e0.png">
test_size = 0.4 訓練データ、検証データの比率
random_state = 1 再現性を高めるため乱数固定
訓練データでfit　パラメータ調整して
検証データで決定係数出力

<img width="291" alt="キャプチャ1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/ab4b47c3-049b-6e14-2528-8a78359847a4.png">

<img width="477" alt="キャプチャ1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/04ecd47c-96eb-3361-ba30-aa5dd77d11c9.png">
rails 発展その12 カラムのデータまとめかた。

コントローラーからデータをいかに処理してまとめられる
備忘録を書きます。

## groupメソッド

groupメソッドはテーブルのレコードを指定したカラムでまとめることができます。

```ruby
   モデル.group(カラム名)

# 例
  Rei.group(:product_id)
# これでproduct_idの21,22,23,などにまとめられ格product_idの先頭が出力されます。

```

## countメソッド
countメソッドは配列などの要素数を返すメソッドです。

```ruby
Rei.group(:product_id).count
=> {21=>2, 22=>1, 23=>4}
```

## order('count_カラム名').count(カラム名)
countメソッドの引数にカラム名を指定することができます。
するとorderメソッドでcount_カラム名でのソートが可能となります。
これはそのカラムを持つレコードの数でソートするという意味です。

**ここでlimitの注意点です**
count(:product_id)の時点ではハッシュになっているため
その後に付け加えるとハッシュに対してlimitメソッドを実行することになりエラーが起こります。
そのため、その直前に付け加え、下記のようにします。

```ruby
  order('count_カラム名').count(カラム名

# 例
Rei.group(:product_id).order('count_product_id DESC').limit(5).count(:product_id)
=> {23=>4, 21=>2, 22=>1}
```

## keysメソッド
ハッシュはkeysというメソッドを持っています。
これはハッシュのキーだけを取り出して配列として返すメソッドです。

```ruby
# 例
   Rei.group(:product_id).order('count_product_id DESC').limit(5).count(:product_id).keys
=> [23, 21, 22]
```

## mapメソッド
whereで値を配列にした場合、並びがid順になってしまうので。
この問題を解決するためにmapメソッドを使用します。

mapメソッドは配列オブジェクトのインスタンスメソッドです。
mapメソッドは配列の中身を１つずつ取り出してブロックという構文を繰り返し実行します。
そして、ブロックの返り値を集めた新しい配列を作成します。

```ruby
   配列オブジェクト.map {|ele| ブロックの処理}
   # eleには配列の要素が１つずつ代入される
   # ブロックの処理は配列の要素の数だけ繰り返し実行される

# 例
  class RankingController < ApplicationController
    def ranking
      product_ids = Rei.group(:product_id).order('count_product_id DESC').limit(5).count(:product_id).keys
      # これでproduct_idの多い順に並ばれました。
      @ranking = product_ids.map { |id| Product.find(id) }
      #Prodict_idsを順番に実行してproductテーブルからインスタンスを持ってきます。
    end
  end
```
WSL上でJupyter labの挙動がおかしかったのをなんとかした話

#三行で
・WSL環境上でjupyter labを起動するとおかしな挙動をしたあと画面が真っ黒になる
・jupyter labの自動でブラウザを開く機能が悪さをしてた
・jupyter の設定ファイルをいじって↑を止めたら治った



#症状
##環境
windows10
Ubuntu　18.04（Windows Subsystem for Linux　2）
Anaconda 2019.10
今まではUbuntuでlabを起動してWindowsのブラウザで使っていた
##挙動
①Ubuntuに「jupyter lab」を入力する
②ブラウザ用URLが出力されるとすぐに画面が真っ黒になる
③一瞬エラー文のようなものが表示されるが文字化けしており、またすぐに真っ黒になる
④Ubuntuのタブ名が「C://~~~~~/explorer.exe」になっている
⑤内部でjupyter labは動いているけどURL見えないから使えない（とてもつらい）
という動きをしていた。


#原因
jupyter labには「jupyter lab」と入力するだけで
①ブラウザ開いて②URL入れて③開発環境を開く
までやってくれる機能がある。今までWSL環境ではこの機能が動いていなかったので上記①～③を自力でやっていた。

何故かはわからないがWSL環境上でこの機能が動くようになった結果、ブラウザという概念がなく、CUIしかないWSLが困っちゃったのが原因。

なのでこの「自動でブラウザを開く機能」を止めてしまえばちゃんと動くようになる。

#解決法
##①jupyter の設定ファイルを作る
jupyter labの設定がいじれるようになるファイルを出力する。
CUI上に以下を入力すると`~/.jupyter`に`jupyter_notebook_config.py`というファイルが出力される。

```shell

$ jupyter notebook --generate-config
```

##②自動起動を止める文を入力する
生成された`jupyter_notebook_config.py`を開いて、先頭の行に以下の文を入力する。

```python

c.NotebookApp.open_browser = False
```
そして保存する。
##③ちゃんと起動できるか確認する
②の保存後、再度jupyter labを起動してちゃんと動くか確認する。
自分の環境下ではちゃんと動いたので良かった。

#最後に
なにかの拍子でまた同じようなことが起きるかもしれないのでメモを残して置きたかった。
~~原因究明のためにUbuntu再インストールとかしたのでまた環境構築するのめっっちゃ面倒~~

#参考にさせていただいた記事
[Jupyter Lab事始め](https://qiita.com/taka4sato/items/378782763dec3dacb1ee)
picoCTF 2019 NewOverFlow-2 - Points: 250

#問題

https://2019game.picoctf.com/problems

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/3b6b2a8a-244d-89d3-b574-17f401daea30.png)

#解いてみた

いやこの問題も前までありませんでしたよね？
オーバーフロー勉強したいのでありがたいですが。

ソースを見ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/72b3ce63-2c01-cb4d-f23a-544141e0c16b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/e0bdd501-6797-ff80-7544-8542d8a4f075.png)

ちょっと長めです。
main()から軽く見るとvuln()を呼んで終了。
呼ばれないflag()がある。

vuln()からmain()に戻るときに戻り先をflag()にすればよい？
win_fn2()とwin_fn()は必要？
何かの罠？

罠かわかりませんが、vuln()のリターンアドレスを変更する作戦でやってみます。

まずはflag()のアドレスを調べます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/3385e8a8-93a9-29d2-6eb8-f325077d64f8.png)

flag()の先頭は0x000000000040084dだということがわかりました。
桁数多いから64bitぽいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/4dc66ef2-186b-ab18-8bfc-3c3e9d54efd5.png)

やはり64bitでした。

つぎはvuln()のリターンアドレスが格納される位置を確認します。
適当に200文字入れてどうなるか確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/76ee9498-c5e3-1393-2bca-fcd9917833ca.png)

ということで0x4e6a6b50が格納されていました。
これをCyberChefで確認します。
リトルエンディアンに気を付けます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/e55354b8-cd35-e117-1563-ac869f062664.png)

PkjNです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/34cd7c7a-f0e9-4cb1-7321-3fac891fb161.png)

73文字目でした。
ではここをflag()の先頭アドレスである0x000000000040084dにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/625c541d-53f5-c0b9-5791-57b5490ae043.png)

やっぱよくわからないんですが、64bitの時は1つずらさないといけないみたいです。
そしてwin_fn2()とwin_fn()はなんだったんでしょうか？

pwnかなり苦手意識あったけど、このくらいのイージーレベルならさくっと解けるようになってきた。
タッチディスプレイ gen4-uLCD-35DT > 日本語フォント（東雲）を表示する > idea: Display Video Frameを使う

```txt:動作環境
Ubuntu 18.04 LTS 
display module: gen4-uLCD-35DT 
  Workshop 4 IDE v4.5.0.17 (on Windows 10 Pro)
MCU: STM32F446 Nuclero-64
  STM32CubeIDE v1.0.1 (on Ubuntu 18.04 LTS)
```

### 概要

- gen4-uLCD-35DTは日本語フォント表示機能がない
- 16x16の東雲フォントを使おう
- フォントはVideoとしてmicroSDに保存する
- Display Video Frameにて文字選択して任意の場所に表示

### 手順

1. 東雲フォント(BDF形式)をBMP形式に変換する
    - [Font > 東雲フォント > BDF形式をBMP形式にする (ツール: bdf2bmp)](https://qiita.com/7of9/items/a7d50851df464d20e0dc)
2. BMP形式（一覧）をImageMagickで分割する
    - [Python + ImageMagick > BMP形式の文字一覧から文字を切り出す (東雲フォントのBMP変換に対して)](https://qiita.com/7of9/items/b8b3caea9dc09c69ce17)
        - 16x16を32x32へ
        - 白黒反転も
3. animated gifの作成
    - `$convert -delay 10 wrk*.bmp anime_x2_invert.gif`
4. Graphics Composerでainmated gifを設定
    - raw形式でmicroSDへ保存
5. Display Video Frameで表示 (Workshop 4 IDEのSerial Commanderで動作確認)
    - a. Media > media_Init
    - b. Media > media_SetAdd
        - HiWord:0, LoWord:0
    - c. Media > media_VideoFrame
        - あ: offset=210, x=0, y=0
        - い: offset=212, x=0, y=32
        - う: offset=214, x=0, y=64

### 結果

左上が表示した文字。

![IMG_1358.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/8bcdfb1f-5558-d67e-38ce-97dc0c4ab88f.jpeg)
ソフトウェアのバージョニングの仕方について学んだことまとめ

# 目次
1. バージョニングとは
2. セマンティックとは
3. [セマンティック バージョニング 2.0.0](https://semver.org/lang/ja/)のまとめ
4. 今後の課題

# 今回の学習のゴール
一般的なバージョニングの仕方がわかる

# バージョニングとは
バージョン管理。作成、編集したファイルやプログラムなどの変更履歴を保存し、過去の任意の時点の状態に復元したり、変更内容の差分を表示したりできるよう管理すること。単にデータをバージョン管理システムに保存して管理することを意味することが多い。

# セマンティックとは
情報の持つ意味を適切に理解させる技術のことを指す。

# [セマンティック バージョニング 2.0.0](https://semver.org/lang/ja/)のまとめ

### バージョンの依存性について
- 厳密に依存関係を指定すると、システムはバージョン・ロックの危機に晒される
    - 全ての依存パッケージを新しくしない限り、アップグレードできないことをバージョン・ロックという
- 依存指定を緩く管理するとバージョンが複雑に絡まりあってしまう
- 依存性地獄とは、バージョン・ロックやバージョンの混乱に陥ること

### セマンティック バージョニングについて
- バージョンを変更する際には、ルールに従ってバージョン番号を上げる必要がある
- X.Y.Z（メジャー.マイナー.パッチ）のバージョン形式を遵守する必要がある
    - 後方互換性※1 のないAPIの変更は、メジャーバージョンを上げる※2
    - 後方互換性を保ちつつAPIを変更・追加した場合は、マイナーバージョンを上げる※3 
    - APIに影響を及ぼさないバグ修正は、パッチバージョンを上げる※4
- セマンティック バージョニングのスキーム（枠組み）に従えば、新しいバージョンへ変更された際に何が変更されたのかをユーザーに伝えることができる
    - GitHubのreleasesから確認することができる
        - ex. [github.com/vuejs](https://github.com/vuejs/vue/releases)

※1 後方互換性とは、新しい部品やコンポーネント（構成要素）などを古いものに置き換えても同様に動作させることができる性質のこと。新しい部品やコンポーネントが、古い部品の仕様や機能を包含している状態のこと。
※2 性能や機能を大幅に改良・向上することをメジャーバージョンアップという。大きく目立った変更を伴うバージョンアップを指す。
※3 性能や機能を小幅に改良・向上することをマイナーバージョンという。小さな変更を伴うバージョンアップを指す。
※4 プログラムの一部分を更新してバグの修正や機能の変更を行うためのバージョンアップを意味する。

### セマンティック バージョニングの仕様書
- セマンティック バージョニングを適用するソフトウェアは、パブリックAPIを宣言しなければならない
    - アカウントを取得していなくても使用できるオープンなAPIをパブリックAPIという
- バージョンナンバーは、X.Y.Z （それぞれ非負の整数）の形式にしなければならない
- 一度パッケージをリリースした場合は、そのバージョンのパッケージのコンテンツは修正せず、新しいバージョンとしてリリースしなければならない
- メジャーバージョンのゼロ（0.y.z）は、初期段階の開発用を意味する
- メジャーバージョンを上げた場合は、マイナーバージョン及びパッチバージョンを0にリセットしなければならない
- マイナーバージョンを上げた場合は、パッチバージョンを0にリセットしなければならない
- プレリリースバージョンは、パッチバージョンの直後にハイフンとドットで区切られた識別子を追加することで表現しても良い
    - 識別子は、ASCII英数字とハイフン [0-9, A-Z,a-z,-] でなければいけない
    - ex. 1.0.0-alpha, 1.0.0-0.3.7
- メジャーバージョン、マイナーバージョン、パッチバージョン、プレリリースバージョン識別子の順でバージョン同士を比較する際の優先度が決まる
    - ex. 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0-alpha <　1.0.0 < 2.0.0 < 2.1.0 < 2.1.1

# 今後の課題
- メジャーバージョンとマイナーバージョンの具体的な境目については、実務で学ぶ
初心者によるプログラミング学習ログ 158日目

# 100日チャレンジの158日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

158日目は、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>158日目<br><br>Udemyで架空のwebサイトコーディング<br><br>メンターさんの課題やろうと思ったら眠くなったからやめた<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアとつながりたい</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1193983684824584193?ref_src=twsrc%5Etfw">November 11, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【SwiftUI】画像のリサイズ


# 画像の表示

```Swift
struct ContentView: View {
    var body: some View {
        Image("Image", bundle: .main)
    }
}
```

<img width="545" alt="スクリーンショット 2019-11-12 15.03.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234348/a5acaf7f-977d-8c2d-fcf8-6e62507bb4cb.png">


## 大きすぎるのでリサイズ

```Swift
struct ContentView: View {
    var body: some View {
        Image("Image", bundle: .main)
            .frame(width: 50.0, height: 50.0, alignment: .leading)
    }
}
```

ちゃんとリサイズされません

<img width="545" alt="スクリーンショット 2019-11-12 15.05.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234348/6a01443c-0f06-1651-a10f-9109276b7fdb.png">


## `.resizable()`を付ける
`Image` をリサイズする際には `.resizable()` をつけなければならないみたいです。

```Swift
struct ContentView: View {
    var body: some View {
        Image("Image", bundle: .main)
            .resizable()
            .frame(width: 50.0, height: 50.0, alignment: .leading)
    }
}
```

<img width="545" alt="スクリーンショット 2019-11-12 15.05.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234348/86baf2f2-9190-20d2-af47-3a98dc56cc0f.png">

これでリサイズされました。
HTMLメール、各メール参照アプリで特殊仕様あり

HTMLメールってなかなかハードル高いなぁと思った出来事メモ

ざっくりいうと、各メール参照アプリ（ウェブメール等含む）で、
メール本文の編集仕様が異なるため、すべてに対応することは大変ということ。

##①メール本文のHTMLエンコードが解釈できないウェブメールあり
一部のウェブメールで、画像パスのエンコードがうまく処理されず画像が表示されなかった。

##②font-size:100%のデフォルトサイズに注意
ウェブメールにより表示が異なる。
デフォルトサイズをブラウザの文字サイズとするものもあれば、
ウェブメール側でデフォルトの文字サイズが設定できるものもある。

⇒言いたいことは、文字サイズを変更しても崩れないようなデザインにするべき
ちょっとブログ感覚でじぶんが触れたことあるものまとめ

## python
### flask
pythonのwebアプリケーション用ライブラリ。
プロトコル通信での送受信を結構簡単に行える。受信した数値に対してpython側で計算をしたり、表にまとめるなどできる。インスタグラムなどの大規模なシステム構築には向かないらしい。しかし、簡単なウェブアプリケーションを作るうえでは問題ない。
正確な情報や不正確な情報が蔓延しているので、実際に実装して確かめる必要がある。ポート開放の知識が必要。

http://python.zombie-hunting-club.com/entry/2017/11/03/223503
flaskの使い方の初歩はここから学んだ。

https://qiita.com/keimoriyama/items/7c935c91e95d857714fb
https://qiita.com/5zm/items/ac8c9d1d74d012e682b4
【クラインアント→サーバー】クライアントからファイルを貰う方法の参考に。

https://qiita.com/5zm/items/760000cf63b176be544c
【サーバー→クラインアント】プロトコル通信使って、クライアントにファイルを投げる方法の参考に。

### matplotlib,sympy
ふと思い立って、グラフ描画をしたくなったときのやつ。
matplotlibは描画用ライブラリ、sympyはシミュレーション用ライブラリ。なんかよくはわからんけど、二つとも使う。

https://qiita.com/HigashinoSola/items/2ab8894b543e0c55cfa7
このページはうまくまとめられているので初心者向けによい。

https://qiita.com/orange_u/items/8a1e285a45093857aef7
3D描画する際に参考にした。

https://matplotlib.org/3.1.0/gallery/mplot3d/text3d.html
3D描画にテキストを記述する方法。上のページ内にも書いてあるが、

~~~python
import matplotlib.pyplot as plt
fig=plt.figure()
ax=Axes3D(fig)
ax.text(x,y,z,Text,dir)
#x,y,zは座標、Textはstr型の文字、dirは(x,y,z)でカメラに対してのアングル
~~~
rails 発展その11 コントローラー

コントローラーの諸知識の軽いまとめです。

## before_action
あるコントローラのすべてのアクションで実行の前に共通の処理を行いたい場合のコード

```ruby:contoroller
  class コントローラ名 < ApplicationController
    before_action :処理させたいメソッドの名前
```

## コントローラーの継承　

コントローラーは継承元のコントローラーから内容を継承することが
可能です。継承元にbefore_actionが設定されていれば
それを行ってから現在のコントローラーで処理が実行されます。

```ruby:controller
   class コントローラ < 継承元のコントローラ
   end

  #  例　

# 継承元

class StoreController < ApplicationController
  before_action :say

  def say
    puts "Hello"
  end
end

# 継承先 sayが実行されてから以下の変数が実行される

 class PetController < StoreController
  def show
    @saru = Saru.find(params[:id])
  end
end
```

## レイアウトファイル
app/views/layouts/の下に入っているHTMLファイルです。
レイアウトファイルはURLにアクセスして対応するコントローラが呼ばれたあと、最初に表示されるHTMLのことです。

コントローラ内でlayout 'レイアウトファイル名'と書くと、そのコントローラでのアクションが呼ばれたあと表示するビューのレイアウトファイルを指定できます。

```ruby:controller
  class StoreController < ApplicationController
  layout 'レイアウトファイル名'
  # なにも指定しないとレイアウトファイルはapplication.html.erbになります。

  # 例
  layout 'pict'
  
  # StoreControllerのindexアクションが呼ばれたときに表示されるレイアウトはpict.html.erbとなります。
  def index
  end
end
   
```
JavaScriptのDateインスタンス生成用ラッパー

JavaScriptで特定の日時のDateオブジェクトのインスタンスを生成する方法には、いくつかあって、以下のように文字列を入れたり、年・月・日...を数値として渡す方法などがある。

```javascript
new Date('December 17, 1995 03:24:00');
new Date(1995, 11, 17, 3, 24, 0);
```

しかしながら、文字列を渡してインスタンスを生成する場合罠があって、例えば以下のようなフォーマットの場合、ChromeやFirefoxなら正常にインスタンス生成できても、Safariだとエラーになるということがある。

```javascript
new Date('2019-11-08 11:25')
// Firefox → Date Fri Nov 08 2019 11:25:00 GMT+0900 (日本標準時)
// Chrome → Fri Nov 08 2019 11:25:00 GMT+0900 (日本標準時)
// Safari → Invalid Date
```

以上から、文字列から直接Dateオブジェクトのインスタンスを生成するのは危険なので、文字列をパースして、```new Date(yyyy,MM,dd,HH,mm,ss,SSS)```の形式で生成してくれるラッパーを作成した。


```javascript
function constructDate (datetimeString, format){
  function extract(datetimeString, expression){
    var start = format.search(expression);

    if(start < 0){
      return '';
    }

    var extracted = datetimeString.substr(start, expression.length);
    if(expression !== 'MM'){
      return datetimeString.substr(start, expression.length);
    } else{
      var month = Number(extracted) - 1;
      return ('0' + month).slice(-2);
    }
  }

  var dt ={
    yyyy: extract(datetimeString, 'yyyy'),
    MM: extract(datetimeString, 'MM'),
    dd: extract(datetimeString, 'dd'),
    HH: extract(datetimeString, 'HH'),
    mm: extract(datetimeString, 'mm'),
    ss: extract(datetimeString, 'ss'),
    SSS: extract(datetimeString, 'SSS')
  };

  var constructCommand = 'new Date(';
  for(var key in dt){
    if(dt[key] !== ''){
      constructCommand += dt[key] + ',';
    }
  }
  constructCommand +=')';

  return eval(constructCommand);
};

// 使用例
constructDate('2019-11-26 11:25:39', "yyyy-MM-dd HH:mm:ss")
// Date Tue Nov 26 2019 11:25:00 GMT+0900 (日本標準時)
constructDate('2019/11/26 11:25', "yyyy-MM-dd HH:mm")
// Date Tue Nov 26 2019 11:25:39 GMT+0900 (日本標準時)
constructDate('20191126', 'yyyyMMdd') 
// Date Tue Nov 26 2019 00:00:00 GMT+0900 (日本標準時)
```

おそらくN番煎じかつ、適切なライブラリを使えば解決できそうな気もするけど、参考になれば。
Unity Scrollbarの使い方

#はじめに
ステージ選択の画面など、スクロールバーを使いたい状況になったので
スクロールバーを利用する上でのメモ書きを投稿します。

- 環境
    - Unity 2019.1.14f1
    - Windows10 1903

# ポイント
- スクロールバーを実装するための要素は３つあります。
    - Content：表示するコンテンツで、スクロールさせたい対象です。
    - Viewport：Cotentをマスクします。Viewportのサイズが表示領域となります。
    - Scrollbar：バーを動かすことで、Viewportの表示領域内をContentが動くようになります。
- アタッチするコンポーネント
    - Scroll Rect：スクロールバーの制御（Content,Viewport,Scrollbar）を指定する
    - Rect Mask 2D：Viewportにアタッチして表示領域とする。子要素がViewportでマスクされると理解した。

# 作り方
## UIを準備します。
UIのパーツは図のような階層構造にしました。
![スクロールバー1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500782/c3e3697a-63c1-ba78-04c0-c839f70b9667.png)
UIのパーツの種類とRect Transform  は次のように設定しました。

| 項目    |種類      |Anchor       |PosX|PosY|PosZ|Width|Height|
|:--------|:-------|:------------|---:|---:|---:|----:|-----:|
|Panel    |Panel    |middle,center|   0|   0|   0|  200|   100|
|Viewport |Panel    |middle,center|   0|   0|   0|  200|   100|
|Content  |Panel    |middle,center|   0| -50|   0|  200|   100|
|Image    |Image    |middle,center|   0|   0|   0|  100|   100|
|Scrollbar|Scrollbar|middle,right |   0|   0|   0|   20|   100|

Scrollbar は今回縦方向のスクロールバーを実装したかったので
InspectorウインドウのScrollbarコンポーネントの
***Direction を Bottom to Top に変更してください。***

UIの完成図をGameウインドウで見ると以下のようになります。
この段階では、ContentパネルがViewportをはみ出しています。
![スクロールバー2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500782/a9c47982-327b-26f9-9cda-c89c49cb8abe.png)

## ViewPort に Rect Mask 2D をアタッチします。
ViewportをInspectorウインドウからAdd Component で Rect Mask 2D を選択してください。
![スクロールバー3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500782/96a1ca00-f971-a64e-36fc-e04fb3b4474a.png)
マスクの効果で、Content が隠されたことを確認できます。

### Panel に Scroll Rect をアタッチします。
Panelを選択しInspectorウインドウからAdd Component で Scroll Rect を選択してください。
![スクロールバー4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500782/4982076b-2b25-1e2b-6a5e-8629a551f5db.png)

Hierarchy ウインドウからContent,Viewport,Scrollbar　を指定します。
今回横方向へのスクロールは不要でしたので、Horizontalのチェックは外しました。

以上の手順で、スクロールを確かめることができます。（下までスクロールした図）
![スクロールバー5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500782/4c5efcdb-610f-4871-9224-e08b6ba7aa27.png)
「スマートスピーカーを遊びたおす会 vol.8」に参加してきた

# はじめに
[スマートスピーカーを遊びたおす会 vol.8](https://kotodama.connpass.com/event/151115/)に参加してきたのでそれについてまとめます。毎度のことながらリアルタイム投稿なので内容にあまり期待しないでください笑

# Azure Functionsでのスマートスピーカースキル開発 by ちょまどさん
タイトルちょっと短縮してます。最初はスキル開発についての概要でした。ここではサーバーレスサービスの[Azure Functions](https://docs.microsoft.com/ja-jp/azure/azure-functions/)を用いて作ったスキル

- [筋肉ボイス](https://github.com/chomado/GoogleHomeHack)
- [最新のブログ記事取得](https://github.com/chomado/SmartSpeakerGetLatestArticle)
- [Microsoft Office連携「秘書さん」](https://github.com/chomado/MeetingResponseServer)
- [滑舌スキル](https://github.com/chomado/KatsuzetsuApp)

についての紹介でした。GitHubのリンクそれぞれ貼っておきました。すべて一つのバックエンドで３タイプ（Google Home, Alexa, Clova）に対応させているのが凄い。。。
[このパッケージ](https://github.com/himanago/xplat-vui)を使えばクロスプラットフォームでの開発ができるそうです。

# VUI温泉へようこそ by 温泉♨BBAさん
[スマートスピーカーでおうちハック](https://booth.pm/ja/items/1560393)の宣伝でした。背景としては、スマートスピーカーは今後需要が増加していくスマート家電のために欠かせない存在となっています。ここでは、[Voice Flow](https://www.voiceflow.com/)を用いたノンコーディングでのスマートスピーカースキル開発について紹介しているとのことです。

# VUI開発で最も大切なデザインのお話 by 松葉さん
[VUIデザインガイドブック](https://booth.pm/ja/items/1547067)についての話でした。スキルがユーザーに愛されるために大切な要素として

- 便利
- 心地よい
- 面白い

があります。この観点からVUIデザインのベストプラクティスについて解説されました。

## VUIデザインとは
どのように発話すればどのように応答するか定義すること、つまり会話設計です。VUIの特徴として、自然に触れること、手や目に拘束されないといったものがあります。この中でも特に、「学習することなく自然に操作できるVUI」をデザインすることが重要になります。
特に難しく考える必要はなく、「心地よい」会話を自分で模索していくことで良い会話をデザインすることができます。

## どのようにデザインするのか
まずはペルソナ（使うユーザーの像）を考える。そこからアシスタントの役割や性格を決める。その上でセリフを考えることが良い会話設計に繋がります。

## 失敗例
７つの例について紹介されました。

- 説明が長い
  - 起動回数に応じて説明を変える
- サポート不足
    - ロールプレイをしてみる
- 間がない
    - 心地よい間の長さを模索する
- 正確に聞き取りにくい
    - なるべく訓読みを使う
- 大量の情報を与える
    - メイン機能のみを伝えてあとをオプションとする
- 大量の情報を聞く
    - VUIを分割しない
- 発話が間違っている
    - 読みに注意する

# 我が家にスマスピを導入した話 by 加茂さん
タイトル短縮してます。このセッションは、スマートスピーカーで実際に自分の生活に生かせるスキルを開発をしたといった話でした。ここでは、時間割管理ができるスキルを開発をしたそうです。用いたツールはVoice Flowです。
実際に自分でスキルを開発をすることで、カスタマイズを自由にできたり、オリジナリティを出すことができるといった良さがあります。

# スマスピっていいな by 新さん
版権に係る内容もあったので省略します。サウンドマスキングをスマートスピーカーで実現させることを目指す話でした。

# さいごに
今回の勉強会ででてきたVoice Flowが結構気になりました。あとは、Clova以外のスマートスピーカーも開発を試してみようかなと思いました。
Django + Google Cloud Strageで、ImageFieldの画像をサーバでも正常に表示させる

HerokuやGAE(Google App Engine)などのサーバで、ImageFieldを使用しても画像が正常に表示されません。

これは、SQLが画像のアップロードに対応していないためで、これの解決にはGoogle Cloud StrageやAmazon S3などのクラウドストレージに画像をアップロードしなければなりません。

今回は、Google Cloud Storageに画像をアップロードする方法をご紹介します。

> Django Strage (Google Cloud Storage) 公式ドキュメント
> https://django-storages.readthedocs.io/en/latest/backends/gcloud.html


# Django Strage のインストール
Django で Google Cloud Strage を扱うための Django ライブラリ、 `Django Strage (Google Cloud Storage)` をpipでインストールします。

```:bash
$ pip install django-storages[google]
```

# Google Cloud Platform で認証情報の取得
Google Cloud Platform から、 Cloud Strageの認証情報の登録と、認証情報の記載された JSON ファイルを取得します。
## サービスアカウントの取得
Googleスタートガイド (https://cloud.google.com/docs/authentication/getting-started) から取得できます。

手順1
Googleスタートガイド (https://cloud.google.com/docs/authentication/getting-started) のリンクから、「[サービスアカウントキーの作成]ページに移動」を選択
<img width="1440" alt="手順1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397410/7fbf38bb-0e3c-bfbb-9487-ef80dfcb36f0.png">

手順2
新しいサービスアカウントを作成で、サービスアカウント名を入力。
<img width="1440" alt="GCS2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397410/4d3c9fb2-f7b1-65bb-c5f9-2abe4e89f6f3.png">
その後、役割から「ストレージ」 -> 「ストレージ管理者」を選択。
キーのタイプがJSONになっていることを確認して、「作成」ボタンを押下してください。
<img width="1440" alt="GCS3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397410/46f7d91f-d7ed-e452-9667-93573515ac82.png">
そうすると、JSONファイルがダウンロードされます。
<img width="1440" alt="GCS4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397410/807f579e-4043-7553-795c-06e4d5189044.png">

**ダウンロードしたJSONファイルは、Djangoプロジェクトのルートディレクトリに配置してください。**

# Google Cloud Strageのバケットの作成
Cloud Strageの単位をバケットといいます（データを入れるバケツみたいな意味）
これを作成して、データを収納します。

Google Cloud Console (Cloud Strage)
https://console.cloud.google.com/storage/browser

上記URLからアクセスすると、以下のような作成画面に遷移すると思うので、新規バケットを作成します。
<img width="1440" alt="作成画面.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397410/24277ea6-59f3-7345-1e53-00e50605bc8f.png">

完了すると以下のような画面になります。
<img width="1440" alt="作成完了.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397410/e07d9094-3392-5254-a3c0-e01be11950ac.png">

これで、Google Cloud Platform console での設定は完了です。

# Djangoでの設定
### settings.pyに設定の追加
settings.pyファイルでデフォルトのストレージとバケット名を設定します。

```python:settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage'

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
DEFAULT_FILE_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage'

GS_BUCKET_NAME = '[YOUR_BUCKET_NAME_GOES_HERE]'

from google.oauth2 import service_account

GS_CREDENTIALS = service_account.Credentials.from_service_account_file(
    os.path.join(BASE_DIR, '[YOUR_AUTHENTICATON_KEY_FILE_NAME].json'),
)
```
以上で設定は完了です。

あとは以下のコマンドを実行しましょう。

```bash:bash
$ python manage.py collectstatic
```

そして設定の変更をサーバにデプロイすると正常に機能するはずです。

お疲れ様でした。
OpenCVを使って長い動画を一部だけ保存する方法

# きっかけ
[グフ／増殖系YouTuber](https://www.youtube.com/channel/UCq1qxbk_BS66ue6-xydKmrg) の [「NHK」で増えて「ぶっ壊す」で倍になる立花孝志](https://www.youtube.com/watch?v=NcR2d8_iM9o) にsyncしました:rolling_eyes:
ちょうど良い動画素材で、領域分割・顔認識・テロップを消すには・・・などなど何かしらでopencvで出来そうです。
この動画は18分あるのですが候補者が登場する冒頭の1分だけを使いたいと思っています。
で、一部分だけ時間によって抽出する方法をpythonとOpenCVのみでやってみます。

# 元素材
- [ＮＨＫをぶっ壊す！【政見放送】 ＮＨＫから国民を守る党【立花　孝志他３名】全国比例区](https://www.youtube.com/watch?v=iRi4od_Thus&t=113s)

[![ＮＨＫをぶっ壊す！【政見放送】 ＮＨＫから国民を守る党【立花　孝志他３名】全国比例区](http://img.youtube.com/vi/iRi4od_Thus/0.jpg)](http://www.youtube.com/watch?v=iRi4od_Thus)

# 方法
- 元動画からfps(1秒あたりのフレーム数)を抽出する
- `開始時間 * fps` or `終了時間 * fps` でフレーム数を計算する

`time.time()` で計測しようとしたのですがフレーム数ベースで制御した方が成功しました。

また、`候補者が登場する冒頭の1分` なので

- 開始時間 = 30秒
- 終了時間 = 90秒

としました。

# 開発

```python
import cv2

if __name__ == '__main__':

	cap = cv2.VideoCapture('drop_out_nhk.mp4')

	cap_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
	cap_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
	fps = cap.get(cv2.CAP_PROP_FPS)

	fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
	writer = cv2.VideoWriter('one_minutes.mp4',fourcc, fps, (cap_width, cap_height))

	# 抽出したい開始or終了時間
	begin = 30
	end = 90

	for i in range(end * fps):
		ret, frame = cap.read()
		if ret:
			if begin * fps < i:
				writer.write(frame)
			
	writer.release()
	cap.release()
```

# 結果
多分これでちょうど１分になったと思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/58c8c1d4-4d20-c26f-6013-b91dd47914e9.gif" width=50%>

# おわりに
`asyncio` とか使おうと思ったのですが、割とすんなり実装できました。 画像サイズを変えるとなぜかコーデックでミスります。


# 参考にしたリンク
- [OpenCV-Python ファイルから動画を読み込む](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_gui/py_video_display/py_video_display.html)
- [OpenCV - VideoCapture / VideoWriter で動画の読み込み/書き込みを行う。] (https://www.pynote.info/entry/opencv-video-capture-and-writer)
GoogleDrive上のファイルの変更履歴をとる

# 概要

最終更新日時だけではなく、ファイル名変更や移動などをとりたい。

# sheetIdとは

`https://docs.google.com/spreadsheets/d/1234567890abcdefghijklmn`というファイルでいうなら、
`https://docs.google.com/spreadsheets/d/[ここがsheetId]`である。


# 最終更新日時をとるだけなら

`DriveApp.getFileById(id)`を使う
https://developers.google.com/apps-script/reference/drive/drive-app#getFileById(String)

ただしDrive APIをオンにする必要がある

- 「Googleの拡張サービス」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1642/c24a75ca-2393-af26-657e-f03169ee6815.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1642/9f5531e8-22d8-1bc7-3433-9a34f1f3e269.png)
↑Operaで見てるのでなんか変

```javascript:lastUpdatedがその値
var sheetId = "1234567890abcdefghijklmn";
var file = DriveApp.getFileById(sheetId);
var lastUpdated = file.getLastUpdated();
```

# その他の履歴を探索したいなら

`AppsActivity.Activities.list(hash)`を使う
https://developers.google.com/drive/activity/v1/reference/activities/list

ただしDrive Activity APIをオンにする必要がある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1642/73c53dc4-c0bf-aa35-5e52-eabffe3efb25.png)


```javascript:eventにいろんな情報が入ったハッシュが得られる
var pageToken; // 1回のリクエストで取りきれる情報では足りない時に使うらしい
var sheetId = "1234567890abcdefghijklmn";
    
var result = AppsActivity.Activities.list({
  'drive.fileId': sheetId,
  'source': 'drive.google.com',
  'pageToken': pageToken
});

// よくわからんので全部チェックして、条件に合うものがヒットしたら抜けるようにしてる
var isDone = false;
for (var actIndex = 0; actIndex < result.activities.length; actIndex++) {
  for (var evtIndex = 0; evtIndex < result.activities[actIndex].singleEvents.length; evtIndex++) {
    var event = result.activities[actIndex].singleEvents[evtIndex];
    
    if (event["primaryEventType"] != "edit" && event["primaryEventType"] != "rename") continue;

    // 時刻とユーザをとっておく    
    var dt = new Date(Number(event["eventTimeMillis"]) + 60*60*9);
    var author = event["user"]["name"];
    
    isDone = true;
    break;
  }
  if (isDone) break;
}

// dtとauthorにほしいものが入ってる
```
.pdfとか.jpegと.pngとかの違いを確認したかった

#なにこれ
一般大学生学習の備忘録。大体Wikiからだと思っていただければ。
#経緯
大学の授業中に友人が.docxと.pdfって同じじゃないの？というとんでもない発言をした。その時は「は？」という反応をして終わったのだが、よくよく考えると各々の拡張子の違いとか説明できない私が悪かったので今回ちゃんと調べることにした。
# pdfとは
では今回の発端となったpdfから。pdfはAdobe Systems Incorporatedによって開発された電子文書のファイルフォーマットである。無償で公開される仕様ではあるが今でもその一部が私有ソフトウェアとして残っている。2008年には国際標準化機構によって国際標準になった。
### 特徴
- ほぼ環境に左右されずに同じ状態で文書や画像を閲覧、印刷をすることができる。
- 文書のセキュリティ設定ができる。
- ファイルの圧縮が可能。
- 注釈、リンクの挿入のような機能が文書を画面に表示する際に設定できる。
- フォーム機能がある。
- 音声での読み上げに対応
- 動画の埋め込みなどのマルチメディアに対応

### 短所
- 仕様が複雑なせいで簡略化がされにくくソフトウェア、文書ともにサイズが大きくメモリの使用量も増大になりがち
- pdfのもとになったテキストファイルと文字列の羅列が異なってしまうためにpdfファイルからの抽出が困難
- 研究者からオンライン用の文書ではないといわれるほど計算機上での閲覧には向いていない

###技術的な面
- 前身のpostscriptをもとに作られた。postscriptほどのプログラミング言語としての機能は持ち合わせておらずHTMLのようなデータ記述言語となっている。
- 情弱性をつかれたファイルへのウイルスの埋め込みなどがありマルウェア感染の事例がある。
- 前述のとおり文書のセキュリティ設定が可能。

# doc,docx
次に友人が勘違いした形式について。pdf同様の記述をしたかったが、その仕様についての全容はいまだ公開されていないようで詳細な情報は載っていなかった。記述すべき点としては
・もともと.docはOfficeの仕様ではなく.txtのように扱われていた形式であったがMicrosoftOfficeの広い普及によって現在はこれを指すものとなった。
・.docと.docxの違いは対応するWordのバージョンの違いと他ソフトへの対応してるかしてないかの違い。.docxはしてる。
・仕様が詳細に後悔されてないのが起因して他のソフトで開こうとした時の再現性が低い。
これを見てるかもしれない友人に伝えたいこととしては.docxはMicrosoftOfficeやほかのソフトで開けるファイル形式ってことだよ。

#jpeg,png
本題に入る前にjpegとjpgの違いについてはその時代のPCの要件に拡張子の文字数制限があったせいなだけで中身の違いはないよう。
## jpeg
静止画像の圧縮方式の一つ。可逆性圧縮、非可逆性圧縮どちらにも対応はされているが通常は非可逆性の方式が採用されている。これのおかげで元のファイルよりも容量を削った状態で画像の保存が可能となる。正式なフォーマットはないがマジックナンバーで６バイト目からJFIFと記されている形式が一般的。デジタルカメラではこの形式の拡張版の形式が採用されている。
#### マジックナンバー
フォーマット識別子。
ファイルの特定の位置にあり、その数値によってファイルの形式が特定される。ほとんどの場合ファイルの先頭に数バイト程度で表される。


###非可逆圧縮方法
概要のみ
符号化方式という方式を採用している。画像を8*8画素の固定サイズブロックに分割し、各ブロックごとに周波数への変換が行われる。これにより次に行われる量子化ビット数の削減とエントロピー符号化の圧縮率向上を図っている。具体的には周波数への変換によってデータの重要な部分が局所的に集められ、これにより量子化ビット数低減による画像の劣化を防ぐことができるからである。エントロピー符号化についてもこの方が都合がよい。一般的に高周波率を粗く扱う。
###それによるノイズ
前述の形式により圧縮率を高くするとブロックの境目にブロックノイズが発生する。また高周波数を粗く扱うためにエッジ周辺ではモスキートノイズが発生する。色差を間引くために特に赤の部分に弱い。
ブロックノイズはモザイクのようなノイズ、モスキートノイズは物の輪郭や色の変化の部分で起こる画像の乱れ。

##png
コンピュータでビットマップ画像を扱うファイル形式。圧縮アルゴリズムとしてDeflateを採用しており圧縮による画質の劣化がない可逆性の画像ファイル形式。すでに普及していたGIFに対してネットワークで使われることを想定した多くの機能を有した形式として普及した。また当時のGIFの256色の制限を改善したことでも大きく注目を集めた。
####ビットマップ画像
画像情報をピクセルの二次元配列としてとらえてRGBの配列情報として扱う形式。
##png,jpegその違い
圧縮率の違い。jpegは前述のとおり非可逆圧縮のために大きなファイルを取り扱い、それを小さくするのに向いている。pngはそれと比べたいてい5~10倍まで膨れ上がる。ただし画像の劣化がないのでテキストが入っていたり色の境目が重要なファイルに関してはpngのほうが好まれる。またjpegは現在の画像を圧縮し保存するため、それを繰り返すごとに劣化していき途中段階での保存には適していない。
##おまけ
###GIFとpng
- GIFよりも圧縮率が高い
- フルカラー表現が可能
- アニメーションがサポートされていない（複数の画像の挿入が可能なため、それを使ってアニメーションを再現できる）
- 圧縮展開に時間がかかるがファイルサイズはGIFよりも小さい
- 半透明表現が可能

#おわりに
ここまでWiki様の力を借りてまとめました。普段意識していない部分まで調べられてよかったです。
#引用元
[png](https://ja.wikipedia.org/wiki/Portable_Network_Graphics)
[ビットマップ](https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%83%E3%83%88%E3%83%9E%E3%83%83%E3%83%97%E7%94%BB%E5%83%8F)
[マジックナンバー](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B8%E3%83%83%E3%82%AF%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC_(%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E8%AD%98%E5%88%A5%E5%AD%90)#cite_note-jargon-file-1)
[jpeg](https://ja.wikipedia.org/wiki/JPEG)
[pdf](https://ja.wikipedia.org/wiki/Portable_Document_Format)
[doc](https://work.lifemake.design/entry/2017/07/05/183000)
Serverless FlameworkでAPI Gatewayのバイナリメディアタイプを設定する方法

表題の件、日本語文献だと`serverless-plugin-custom-binary`を用いるパターンが散見されるが、
内容が古く、Version1系の説明が多い
現時点(2019/11)ではVersion2(それもリリースは2018/6)で、設定方法が変わっている

- Version2

```yaml
plugins:
  - serverless-plugin-custom-binary
custom:
  apiGateway:
    binaryMediaTypes:
      - image/jpeg
```
https://www.npmjs.com/package/serverless-plugin-custom-binary#usage

- Version1

```yaml
plugins:
  - serverless-plugin-custom-binary
custom:
  apigatewayBinary:
    types:
      - image/jpeg
```
rails db:migrateでforeign key mismatchが出ました。

rails db:migrateをしたのですが、エラーが出てしまい、実行できません。



StandardError: An error has occurred, this and all later migrations canceled:

SQLite3::SQLException: foreign key mismatch - "microposts" referencing "users": INSERT INTO "users" ("user_id","name","email","created_at","updated_at","password_digest","website","introduction","sex","tel","nickname","remember_digest","admin")
                     SELECT "user_id","name","email","created_at","updated_at","password_digest","website","introduction","sex","tel","nickname","remember_digest","admin" FROM "ausers"

メッセージとしてこのようなものが出ています。

このメッセージの前にも同じようにStandardError: An error has occurred, this and all later migrations canceled:が出たことから、rails db:reset rails db:drop rails db:create等を行っています。


解決法を教えて頂けないでしょうか。

よろしくお願い致します。
Python + ImageMagick > BMP形式の文字一覧から文字を切り出す (東雲フォントのBMP変換に対して)

```txt:動作環境
Ubuntu 16.04 LTS
Python 3.5.2
ImageMagick 6.8.9-9 Q16 x86_64 2018-09-28
```

### 概要

- 東雲フォント(BDF形式)をBMP形式に変換した
- BMP形式から各文字を切り出す
    - 16x16のフォント

### 実装 v0.1

枠線は2ピクセル。

```divide_191112.py

import subprocess as sb
import sys

# on Python 3.5.2
# Ubuntu 16.04 LTS

# cut out 16x16 bitmap fonts

BORDER_WIDTH = 2
INFILE = "shnmk16.bmp"
idx = 0
for lin in range(10):
    for col in range(32):
        idx = idx + 1
        xpos = BORDER_WIDTH + (BORDER_WIDTH + 16) * col
        ypos = BORDER_WIDTH + (BORDER_WIDTH + 16) * lin
        aform = "convert %s -crop 16x16+%d+%d wrk-%03d.bmp"
        acmd = aform % (INFILE, xpos, ypos, idx)
        print(acmd)
        sb.getoutput(acmd)
```

wrk-000.bmpのように文字ごとにファイルになる。
これを使ってanimated gifを作成できる。


### 切り出したファイル

- wrk-148: 数値の始まり
- wrk-158: upper case英字の始まり
- wrk-184: lower case英字の始まり
- wrk-210: ひらがなの始まり
- wrk-293: カタカナの始まり

### 実装 v0.2

- 16x16を32x32へ
    - [imagemagickで画像のリサイズ](https://qiita.com/tukiyo3/items/ba5aa7c89e1ca2c50542) by @tukiyo3 さん
        - 情報感謝です。
- 白黒反転する
    - カメラ写りが悪かったので
    - [Invert colors with ImageMagick](https://superuser.com/questions/1194468/invert-colors-with-imagemagick/1194469)

```divide_191112.py
import subprocess as sb
import sys

# on Python 3.5.2
# Ubuntu 16.04 LTS

# cut out 16x16 bitmap fonts

BORDER_WIDTH = 2
INFILE = "shnmk16.bmp"
idx = 0
for lin in range(10):
    for col in range(32):
        idx = idx + 1
        xpos = BORDER_WIDTH + (BORDER_WIDTH + 16) * col
        ypos = BORDER_WIDTH + (BORDER_WIDTH + 16) * lin
        # aform = "convert %s -crop 16x16+%d+%d wrk-%03d.bmp"  # x 1
        aform = "convert %s -crop 16x16+%d+%d -resize 32x32 -channel RGB -negate wrk-%03d.bmp"  # x2 invert
        acmd = aform % (INFILE, xpos, ypos, idx)
        print(acmd)
        sb.getoutput(acmd)

```
Automation Anywhere★基本入門「IF」★

「IF」です。
条件分岐です。
よく使用するコマンドです。
概念自体は、Excel関数の"IF"やVBA"IF"を分かっていれば、そんなに難しくはない筈です。

前回作成したデータ「A列」を起点に、C列へ文字を入力してゆきます。

まず、画像をご覧ください。

<img width="495" alt="IF_1112.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489732/e5813819-5e30-e3e0-2a07-e7726a67a5e9.png">

前回は「B列でカウンターを回し」「可愛い」を入力しました
今回は「A列にある動物名によって、C列に入力したい文字を変更させる」です。

IF　もし　なになにだったら、これこれだ。
そんな感じです(雑ですみません)

ざっくり言うと、本当にこんな感じなんですね。

IFを挿入する場所は、Counterを実行し入力を行ったExcelの下「５行目直下」です。
「IF」での条件を設定するには、サブコマンド「Valiable」をダブルクリック
下記のコマンドが開きます






<img width="214" alt="nakamidane.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489732/31e29a8a-e420-8a35-9af3-2eca0ccb33dd.png">


「Edit」をクリックすると、条件設定の画面が開きますので、条件を設定します


<img width="297" alt="nakami1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489732/02244f27-b8e7-9e37-8ae2-26e1e2bdc9f4.png">


「Valiable」→今回は「ExcelColumn(1)」※もしExcelColumn(1)：A列が
「Operator」→等しい「equal」だったら
「Fix」→判断する内容「A列の動物名」をベタ打ち

まずこれで、１つの条件が指定されます。
が、実際には複数の条件を設定する事も多いのです。

「Add more condition」をクリックすると、下記の表示が現れます。
ここで複数の条件をそれぞれ設定します。


<img width="304" alt="if中身.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489732/aa1242a1-cfdf-5862-4f8f-715a81a855ed.png">

「Add」ボタンを押すと入力項目の追加がされますので

①ExcelColumn(1)が猫と等しい
②ExcelColumn(1)がフェレットと等しい
③ExcelColumn(1)がウサギと等しい

Set Cell→好き

「Mach Any」を設定して「Save」します。
条件により、何をしたいのか？をこの後に挿入します。
設定した条件であった場合は「C列へ入力をしたい」ので、


★A列に猫がいたら「One Cell Right」してActive Cellへ文字を入力します。
ここで、疑問がでると思うんです。

「One Cell Right」※一つ右のセルへ
なのに、Botが見てるのは「A」列じゃないの？と。
確かにA列を見ていますが、この前処理で「B列でCounterを回している」事に注目。
A列を見ているが、同時にB列への入力も行っている、すなわち「ActiveになっているのはB列」なので、一つ右へゆくと「C列」に入力されます

試しに「One Cell Right」を２つにして検証してみて下さい♪

が、他にも動物はいますので、この条件以外だったら？の設定を行います。
「IF」を追加すると「End IF」が自動で挿入されますので、この間に、もう二つの設定を行います。

「End IF」の前に「Else IF」を追加して、同じように条件を設定します。

①ExcelColumn(1)がゾウと等しい
②ExcelColumn(1)が犬と等しい
Set Cell→強い

Else IFの後続処理も「One Cell Right」「Set Cell」を挿入。

まだ設定していない動物がいるので、更に「Else IF」

①ExcelColumn(1)がハムスターと等しい
Set Cell→小さい

これで３つの条件を設定しました。
Runしてみて下さい！！




以下の結果になれば成功です:relaxed:



<img width="303" alt="IFkekk.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489732/8ea5ca0e-f523-75aa-5f73-88108f01b80a.png">


IFでは「Enable　Debugging」で動きをみて欲しいです。
AAがどのようにして動いているかを見るのに「IF Command」が最適だと思っています。
IFでの複雑な条件を設定する事で、処理速度は遅くなります。
大量データの分岐の場合は「Excel VBA」VBAでの処理を組み合わせる事もおススメです。


Automation Anywhere　★基本入門★
「IF」これにて終了！
お読みいただき、ありがとうございました
次回は何にしようかな？と考え中ですが、WEB操作をやろうかな？と思ってます:hugging:
EKSで各ノードにデフォルトで割り当てられる private IPアドレスの数を制限するたったひとつの冴えたやり方

# 前置き

微妙に釣りになっていないタイトルは頑張った証です。
全然ひとつじゃないと思いますが、参考まで


EKSのノードを作成する際に、というかそれに限らずVPCやsubnetを作成する必要がありますが、net maskどんくらいにします？
なにが正しいってのはないとは思いますが、私の場合、VPCのnet maskは``/16`` 、 subnetは ``/24`` にします。


VPCは/16であれば、単純に第二オクテットでネットワークを識別できるからです。``10.1.0.0/16``とかなら、``10.1``がネットなわけですな。
VPCたくさんつくってもそれぞれ、``10.1.0.0/16 , 10.2.0.0/16, 10.3.0.0/16`` とはやっとけばそれぞれに配置しているリソースの識別も容易なわけです。
特にVPCピア接続をしたいと思った時にネットワークのIPが別である必要があるため、便利、というか必須です。

で、subnet。
``/24``にしとけば、第四オクテットが自由になる部分であり、発行できるIPアドレスは**256**。256個もIP発行することある？**ないでしょ！**
ということで、なんの迷いもなくそうやってきました。そう。**EKSを使うまでは。**


EKSにノードを立てたら、次にやるのは**scale out** ですよね。

ちなみにEKSのクラスタ構築には``eksctl``を使用しています。

> eksctl.io
https://eksctl.io/

裏でCloudFormationが走るよいツールです。普段はTerraformなのでちょっと思うところはありますが、**良いツール**です。

よっしゃー、``r5.large`` でいっきに**100個**まで**scale out**させちゃうぞ！(ただしspot instanceにかぎる)
とかやります。私はやりました。
その結果、***謎のエラー。。。。***

CloudFormationのコンソール見たら、案の定エラー終了しています。
エラーメッセージをよく見てみると、どうやらsubnetのIPアドレスが枯渇しているとのこと。。。 **え？**

なんとEKSは、``large``クラスであれば、各ノード毎に約10個程度のIPアドレスを確保していきます。いきやがるのです。

https://github.com/awslabs/amazon-eks-ami/blob/master/files/eni-max-pods.txt

によれば、なんと``r5.large``の場合1インタンスあたり最大29個のIPアドレスを消費する可能性があるとのこと。
podごとにIPをアサインする必要があるためらしいですが、いや1ノードでそんなにpod動かさないでしょ〜。

一度このエラーが発生するとCloudFormationのRollbackも至難の技で苦労しました。
Rollback時に出るエラーログを丁寧に追いながら、rollback対象外のリソースを指定していくのがポイント。
まあそもそも発生させないのがよいのでその方法を。


# デフォルトで割り当てられる private IPアドレスの数を制限する方法

- 例えば3個に制限する場合

```
kubectl set env daemonset aws-node -n kube-system WARM_IP_TARGET=3
```

こんだけです。
daemonsetとしてノードごとに起動しているaws-nodeの環境変数を変更するわけですな。

他に設定可能な値は以下参照。

> CNI 設定変数
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/cni-env-vars.html

変えたのはデフォルト値なので、たくさんpodをあげれば当然IPを確保しにいくので、枯渇の悪夢は起こりえます。
ご注意を。