OmniAICreator/Qiita-1.07M huggingface dataset:
くもん式の英語学習デバイス"E-Pencil"をハックする[2]

#実際にドットを配置して出力してみる
[前回](https://qiita.com/Ogawan/items/f25988a0187eadac7bd4)の続き。
1つの格子を64*64として、ドットの相対的な位置を以下のように定義した。

```c++:
int data_pos[8][2] = {
     {18,18},	//0 左上
     {32,16},	//1 上
     {46,18},	//2 右上
     {16,32},	//3 左
     {48,32},	//4 右
     {18,46},	//5 左下
     {32,48},	//6 下
     {46,46},	//7 右下
};
```

これで3bitのデータを座標で表現出来るようになったので、
適当な3bitのデータ配列を用意して、9個の格子に格納してみる。

```c++:
int data[9] = {0,1,2,3,4,5,6,7,0};
POINT DotPos[9];
for(int i=0; i<9; i++){
	int x = 64 * (i%3) + data_pos[data[i]][0];
	int y = 64 * (i/3) + data_pos[data[i]][1];
	DotPos[i].x = x;
	DotPos[i].y = y;
}
```

※ちゃんと実装するときには作った配列の外側を指定しないように注意する。

で、実際にドットを描くときには、64x64の相対位置から
実際に描きたい大きさのキャンバスに描画する。
今回はWin32APIのHDCを使ったので、円を描く関数Ellipseを使って、

```c++:
	double scale = 2.5;
	int r = 7;
	for (int i = 0; i<9; i++) {
		int left   = (int)((DotPos[i].x - r) * scale);
		int top    = (int)((DotPos[i].y - r) * scale);
		int right  = (int)((DotPos[i].x + r) * scale);
		int bottom = (int)((DotPos[i].y + r) * scale);
		::Ellipse(hDC, left, top, right, bottom);
	}
```

のようにすれば、64*64の格子に対して半径7の円を描くイメージになるが、
実際には2.5倍の160*160ピクセルに半径17.5(intにキャストされるので17)の円が描かれる。

キードットや格子ドットも描画するとこんな感じになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/b3c962f4-ff29-dc2f-39ed-113986d0e969.png)


これで3*3の格子データが画像に出来るので、
これをx方向に7回、y方向に5回繰り返すことでオリジナルに近いドット画像が作れた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/96fba93a-2b8c-e237-58d0-5e007c41a943.png)

簡易的にドットパターンジェネレーターを作ったので、
任意の9桁の整数(27bitコード)からドットパターンを生成できる。


#印刷してみる
さて実際に印刷してみたわけだが…。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469946/067efaa1-cac0-3f3a-58d7-a0be8f050b0d.png)

うーん、ドットが潰れてしまった。E-Pencilも反応なし。
この画像が約10.0mm * 7.0mmなので、相当細かいのは間違いないのだが、プリンターの限界なのだろうか？
しかしプリンターの公称スペックでは9600DPIで出せるはずなので、
プリンタに出力する側のソフトの問題かもしれない。

もう少し印刷環境を整えてから再チャレンジが必要と思われるので、
続きはまた今度ということに。なかなか進まない。
GitHubのチュートリアルで詰まった記録

#チュートリアルでつまずくとやる気がゼロになる
そうなった筆者が発狂しながら書いている




##Tutrialの波に乗れなかったところ

1. projectの作成 早速詰まった。Readmeを作らないと、tutorial通りに進まない様子。初見殺し…。

歯車マークからレポジトリを削除してやりなおせる
　
2. Branchの作成　さくさく

3.Commit　Change　サクサク

4.Pull Reqest 

Newを押せ
Base　ベース

5.Merge アップルパイ

#総論
##１のProject作成でReadmeにチェックを入れさえすればなんとかなる
Railsで起きたRoutingErrorの対処について


RailsでRoutingErrorが起きた。

##今回の対処法

至って問題はシンプルで、<%= %>内のpathに問題があった。

具体的には

```example.html.erb
<%= link_to "Delete", post_path(@post), method: :delete, data:{confirm: "Are you sure?"}, class:"button is-danger" %>
```
としないといけなかったところで、

```example.html.erb
<%= link_to "Delete", edit_post_path(@post), method: :delete, data:{confirm: "Are you sure?"}, class:"button is-danger" %>
```
としてしまっていた。

##今後の対策
RoutingErrorが起きたら、まずPathを確認する。
AWS Amplify フレームワークの使い方Part5〜GraphQL Transform @model編〜

# はじめに
Amplifyでの肝の部分であるAPI(AppSync = GraphQL)のスキーマ設計についてまとめていきます。その第一弾として、まず基本的な`@model`の解説から行っていきます。

# 定義
`@model`は以下のように定義されています。

```
directive @model(
    queries: ModelQueryMap,
    mutations: ModelMutationMap,
    subscriptions: ModelSubscriptionMap
) on OBJECT
input ModelMutationMap { create: String, update: String, delete: String }
input ModelQueryMap { get: String, list: String }
input ModelSubscriptionMap {
    onCreate: [String]
    onUpdate: [String]
    onDelete: [String]
    level: ModelSubscriptionLevel
}
enum ModelSubscriptionLevel { off public on }
```

# 解説
`@model`の宣言をすることで、DynamoDBにテーブルが作成することができ、AppSyncで呼び出しができるように設定してくれます。
`graphlql`フォルダが自動生成され、その中に`queries.js`、`mutations.js`、`subscriptions.js`が作られることで、CRUDが簡単に行えるようになります。

## 基本設定
下記の例では、idをプライマリーキーとして、Postテーブルが作成されます。

```
type Post @model {
    id: ID!
    title: String!
    tags: [String!]!
}
```
PostデータのCRUDするために、`queries.js`には`getPost`と`listPost`。`mutations.js`には`createPost`と`updatePost`、`deletePost`。`subscriptions.js`には`onCreatePost`と`onUpdatePost`、`onDeletePost`がそれぞれ自動生成されます。

具体的な使用方法については、別記事でまとめていますので、下記の記事をご確認ください。
[AWS Amplify フレームワークの使い方Part4〜API実践編〜](https://japan-port.qiita.com/too/items/9af244afa33b6dbb3208) 

## 詳細設定
`@model`のあとに、記述を追加することで自動生成されるCURDを制御することができます。
下記のように記述した場合は、`mutations.js`と`subscriptions.js`内に自動生成なしで`queries.js`内に`getPost`のみが生成されます。

```
type Post @model(queries: { get: "post" }, mutations: null, subscriptions: null) {
    id: ID!
    title: String!
    tags: [String!]!
}
```
# おわりに
もう少し細かい事もできるようですが、現状試しているのはここまでになります。`@model`さえ使えれば、簡単なアプリはできてしまうので、一度は触ってもらうとわかりやすいと思います。

# 参考
[GraphQL Transform(公式ドキュメント)](https://aws-amplify.github.io/docs/cli-toolchain/graphql?sdk=js) 

# 関連記事
[AWS amplify フレームワークの使い方Part1〜Auth設定編〜](https://qiita.com/too/items/fc961283dcbef3aafdeb)
[AWS Amplify フレームワークの使い方Part2〜Auth実践編〜](https://qiita.com/too/items/54992bb871fc1a2ab101)
[AWS Amplify フレームワークの使い方Part3〜API設定編〜](https://qiita.com/too/items/c0ce14d16772b9f71223)
[AWS Amplify フレームワークの使い方Part4〜API実践編〜](https://qiita.com/too/items/f9078803ea394c35df7d)
[AWS Amplify フレームワークの使い方Part6〜GraphQL Transform @auth編〜](https://qiita.com/too/items/fae2879ea36f00c3ae10)
[AWS Amplify フレームワークの使い方Part7〜GraphQL Transform @key編〜]
(https://qiita.com/too/items/cb1dfb4f44536a3e9855)
[AWS Amplify フレームワークの使い方Part8〜GraphQL Transform @connection編〜](https://qiita.com/too/items/c77f1e5487d2497b5061)
[AWS Amplify フレームワークの使い方Part9〜Function 基礎編〜](https://qiita.com/too/items/d2732b3ec625011f4567)
[AWS Amplify フレームワークの使い方Part10〜Storage編〜](https://qiita.com/too/items/361bc10b6d27f133e9f8)
[AWS Amplify フレームワークの使い方Part11〜Function 権限管理編〜](https://qiita.com/too/items/b34cbfd7e96a01e33f23)
[AWS Amplify フレームワークの使い方Part12〜ENV編〜](https://qiita.com/too/items/5c1e28cf95fc6229547e)
[AWS Amplify フレームワークの使い方Part13〜Auth 設定更新編〜]
(https://qiita.com/too/items/52f35860bcb5bdf5e667)
[AWS Amplify フレームワークの使い方Part14〜Lambda レイヤー編〜]
(https://qiita.com/too/items/54de781085bd9a3a66d0)
[Python3 入門 11日目]6章 オブジェクトとクラス（6.1〜6.2）

#6.1 オブジェクトとは何か
- Pythonに含まれるオブジェクトは全てオブジェクト
- オブジェクトはデータ（変数、属性と呼ばれる）とコード（関数、メソッドと呼ばれる）の両方が含まれている。
- オブジェクトは何らかの具体的なものの一意なインスタンス(実体、実例)を表している。 
- オブジェクトは名詞、オブジェクトのメソッドは動詞と考えることができる。オブジェクトは個別のものを、メソッドは他のものとどのようなやりとりをするかを定義する。

#6.2 classによるクラスの定義
- オブジェクトはプラスチックのボックスに喩えたが、**クラス**はそのような**ボックスを作るための鋳型**のようなもの。


```py

#Personクラスの定義
>>> class Person():
...     pass
... 
#オブジェクトはクラス名を関数のように呼び出して作る。
>>> someone=Person()
>>> class Person():
...     def __init(self):
...         pass
... 

#__init__()はクラス定義から個々のオブジェクトを作るときにそれを初期化するメソッドにつけられた特殊名である。また、クラス内で定義する場合、第一引数はselfでなければならない。

#self引数は作られたオブジェクト自体を参照する。

#新しく作ったオブジェクトをself、もう一つの引数("Elmer Fudd")をnameとして渡してオブジェクトの__init__()メソッドを呼び出す。
>>> class Person():
...     def __init__(self,name):
...         self.name=name
... 
>>> hunter = Person("Elmer Fudd")
>>> print("The mighty hunter:",hunter.name)
The mighty hunter: Elmer Fudd

```

- Personクラスの内部では、name属性にはself.nameという形で、オブジェクト（hunter）の外部からはhunter.nameと呼ぶ。



#感想
オブジェクトとクラスは概念はまずまず理解できたが文法が慣れるまで大変だ、、、

######参考文献
「Bill Lubanovic著 『入門 Python3』(オライリージャパン発行)」
TCP/IPとは

#TCP/IPとは
Transmission Control Protocol/Internet Protocolの略。
4階層から構成されている。

| 階層      |      名前 |    OSI参照の対応    |
|:-----------------:|:------------------:|:------------------:|
| 第4層     　　   |              アプリケーション層 |   アプリケーション, プレゼンテーション, セッション    |　　
| 第3層          |            トランスポート層 |       トランスポート       |
| 第2層             |               インターネット層 |        ネットワーク        |
| 第1層     　        |                 ネットワークインターフェース層 |         データリンク, 物理        |


OSI参照についてちょっとよくわからないと言う方はこちらを⬇︎⬇︎
[OSI参照についてくそざっくり学んだ](https://qiita.com/TaitoAjiki/items/9640081a28ae3377fcd8)

ただOSI参照とは関係なく、役割からこの辺一緒って決めたそう。

#各層について簡単に
まず、簡単に全体の概要を説明すると相手のコンピュータにデータを送るときに
ちゃんと手順とかルールを決めて、それをデータに付加させて、手順をもとに送ろうって感じ。

それで各層でどこらへん担当かを決めている。

###アプリケーション層
<b>データを表示したり、データを扱うために文字コードとかの変換、
通信の手順などを定めている。</b>
###トランスポート層
<b>ポート番号を決めている。</b>
ポート番号を決めることによって、相手側に通信内容のプロトコルや、
機器上どのようなプログラムを使って解釈すればいいかが決められる。
また、通信路の確立やエラーの検出と通信路の回復などの役割もある。

###インターネット層
<b>IPアドレスをもとにデータをお届けする役割。</b>
ルーティング(伝送する道を決める)を行う。
実際にはルーターまで届けてルーターが
次の道まで(ルーターまで)決めている。


###ネットワークインターフェース層
ネットワークハードウェアが通信するための層。
ARPでMACアドレスという物理アドレスからIPアドレスを取得する。
そして該当するIPアドレスのマシンが応答する。
簡単にいうと、
<b>同じネットワークに接続された複数のコンピュータを区別し、
対象のコンピュータへデータを伝送する。</b>
またデータを電気信号に変換する。

##TCPとUDPとは
トランスポート層で動作するプロトコルである。
###TCPとは
通信前の準備をしたり、受信の確認、再送要求や、通信の最適化など
色々と手広くやっている。
そのために、UDPと比較して負荷もかかってしまう。
用途の例:<b>webの閲覧、メール</b>が該当する。

###UDPとは
送信時のロスが多少あってもよかったり、再送処理などは行わない。
ただ、その分速い。
用途の例:<b>電話、動画</b>が該当する。
<br>


役割やプロトコルの種類が多いために詳細に理解するのは困難だと感じました。
違う点はご指摘を。。

#はてなブログもやってます
はてなブログ⬇︎ぜひご覧ください！
https://taitoajiki.hatenablog.com/
反復で復習html(haml)の機能

hamlで今日までで学んだこと
以下、

html
haml

の順で書き換えをどんどん書く。

```html
<h1>Messages#index</h1>
```

```haml
%h1 Messages#index
```

```html
<div class="font-box">
```

```haml
.font-box
```

```html
<span class="class_value1"></span>
```

```haml
.span.class_value1
```

fontAwesomeからアイコンを取得したい場合。

```html
<i class="far fa-image"></i>
```

```haml
%i.far.fa-image
```

link_toメソッド

```html
<a class="yahoo_link_btn" href="http://www.yahoo.co.jp/">Yahoo</a>
```

```haml
= link_to "http://www.yahoo.co.jp/", class: "yahoo_link_btn" do
  Yahoo
```

hamlはインデントがとても大事。
学んだらこれからも追記する予定。
3秒でPHPのコードをデバッグする方法


こちらのPHP SandboxというサイトからPHPをお手軽実行できます
PHPのバージョンも選べるので最高ですね
[http://sandbox.onlinephpfunctions.com/](http://sandbox.onlinephpfunctions.com/)

先輩に教えてもらいました

<img width="1249" alt="スクリーンショット 2020-01-17 23.19.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275540/4c7b4f1c-c1ef-b53d-23c7-7541713559a3.png">
TypeScript+ReactでCSSにtextAlignを使う

以下のように指定してあげればOK。
毎回これで書くのも面倒なのでいい感じの方法が知りたい。

```
textAlign: "center" as "center"
```

## 参考記事
TypeScript type inference issue with string literal - Stack Overflow https://stackoverflow.com/questions/43121661/typescript-type-inference-issue-with-string-literal/43124412
Option型は長さ１のリスト

# はじめに
「Option型は長さ１のリスト」と解釈すると，ScalaのOptionに関する理解が深まったのでメモ．間違ったことが書かれていたりしたら，指摘お願いします．

# Option型
まず，Option型について説明します．Optionは抽象クラスであり，サブクラスはSomeとNoneの２つです．また，リストと同様に，Option型はmapメソッドやfilterメソッドなどのコレクションメソッドを所持しています．そのため，Option型は構造的には長さ１のリストと考えることができます．

以下，Option型とList型の類似性をコードによって示します．
# (例)map

Listのmapと同様に、Optionのmapは、内包する要素に対して関数を適用します。

```scala
    val opt: Option[String] = Some("some")
    opt.map(_.toUpperCase).foreach(println) // SOME
    
    val lst: List[String] = List("list")
    lst.map(_.toUpperCase).foreach(println) // LIST
```

# (例)flatten

```scala
    val optionNums: List[Option[Int]] = (1 to 10).map(Some(_)).toList
    println(optionNums.flatten) // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    val listNums: List[List[Int]] = (1 to 10).map(List(_)).toList
    println(listNums.flatten) // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
```

# (例)畳み込み

```scala
    val opt: Option[String] = Some("some")
    println(opt.fold("NONE")(_.toUpperCase)) // SOME
    
    val lst: List[String] = List("list")
    println(lst.foldLeft("LIST")(_ + _)) // LISTlist
```

# 結論
Option型を長さ１のリストと解釈すると，Option型について理解しやすい気がします．
JSON Serverでオブジェクト以外を返す方法

# JSON Serverで文字列を返す方法 

公式の[Getting started](https://github.com/typicode/json-server#getting-started)をもとに、
/profileにリクエストが来た場合、nameの値を文字列として返却する方法を紹介する。
文字列として返したい箇所には、**"type": "string"**を記載している。

```json:db.json
{
    "posts": [
      { "id": 1, "title": "json-server", "author": "typicode" }
    ],
    "comments": [
      { "id": 1, "body": "some comment", "postId": 1 }
    ],
    "profile": { "type": "string", "name": "typicode" }
  }
```

以下のように、JSON Serverをモジュールとして使用することで、上記内容を返却する前に後処理を行えるようにする。

```js:server.js
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()

// Middleware(前処理)
server.use(middlewares)
server.use((req, res, next) => {
    // 受け取ったリクエストに前処理を行う場合はここに書く
    // POSTをGETに変換する例
    if (req.method === 'POST') {
        req.method = 'GET'
    }
    // リクエストURLを書き換える例
    req.url = req.url.replace(/\./g, "")
    console.log(req.url)
    next()
})

// ルーティングを使用する場合はここに書く
server.use(jsonServer.rewriter({
    "/api/*": "/$1",
    "/posts\\?id=:id": "/posts/:id",
}))
server.use(router)

// 後処理
router.render = function (req, res) {
    // レスポンスに後処理を行う場合はここに書く
    // db.jsonの返却値に"type":"string"がある場合、nameの値を文字列として返却する例
    if (res.locals.data.type && res.locals.data.type === 'string') {
        res.send(res.locals.data.name)
    } else { // それ以外はdb.jsonに記載したとおり返却する
        res.send(res.locals.data)
    }
}

// モックサーバ起動
server.listen(3000, () => {
    console.log('JSON Server is running')
})

```

あとは、nodeコマンドで実行する

```bash
$ node server.js
```

# 参考
https://github.com/typicode/json-server/issues/410
ナチュラルソート

以下の変数を並び替える状況があるとする。

```py
sample = ["a_12", "a_2", "a_0",  "a_10", "a_4"]
```

例えば組み込み関数の `sorted` を利用すると

```py
sorted(sample)

# ['a_0', 'a_10', 'a_12', 'a_2', 'a_4']
```
という結果が得られる。これは人間の直感には反する結果だろう。

`['a_0', 'a_2', 'a_4', 'a_10', 'a_12']` という結果が得られる方が自然な感じがする。
この自然な感じがする並びは、 [Natural Sort Order](https://en.wikipedia.org/wiki/Natural_sort_order) と呼ばれ、そのソート方法はHuman Sortingとも呼ばれる。

この並び順をpythonで再現する。

## ライブラリを利用する場合

`natsort`を利用する。

https://pypi.org/project/natsort/

```
$ pip install natsort
```

```py
sample = ["a_12", "a_2", "a_0",  "a_10", "a_4"]
print(sample)
print(natsorted(sample, key=lambda y: y.lower()))

# ['a_12', 'a_2', 'a_0', 'a_10', 'a_4']
# ['a_0', 'a_2', 'a_4', 'a_10', 'a_12']
```



## 自分で関数を書く場合

組み込み関数の `sorted` にkeyを指定すれば良い。

```py
def natural_sort(l):
    def alphanum_key(s):
        return [int(c) if c.isdecimal() else c for c in re.split('([0-9]+)', s) ]
    return sorted(l, key=alphanum_key)

print(sample)
print(natural_sort(sample))

# ['a_12', 'a_2', 'a_0', 'a_10', 'a_4']
# ['a_0', 'a_2', 'a_4', 'a_10', 'a_12']
```
Vue.jsでスライドショーを作成したお話

## 結論

- Vue.js上にスライドショーを実装するフレームワーク[eagle.js](https://github.com/zulko/eagle.js/)を使うだけでそれっぽいスライドショーができる
- ホスティングはFirebaseで爆速アップロード
- 出来上がったサイトは [これ](https://messages-benext.firebaseapp.com/)  ※レスポンシブ対応していません
- ソースは[ここ](https://github.com/kidoto/messages)
 
### 発端
弊社では新入社員のサポートとして、一年間先輩社員のメンターがアサインされ、月次で状況把握（カフェーで雑談）を行っている。
年末に新入社員の親御さんに向けてお宅のお子さんこんなことやってるんすよ。という先輩からのメッセージを載せた色紙を送り付けるサプライズイベントが行われる。
~~これが原因で転職する人がいそう~~
ただメッセージを書くのはナンセンスなのでどうせならウェブアプリの形で公開してやろうと思いつき実装。
結果として謎のQRコードとここにアクセスしろというメッセージが親御さんに届いた。

### 技術セット
- Vue.js
- eagle.js
- Firebase

### eagle.jsのポイント
#### <slide>タグで区切るだけで1ページ作成できる
```vue
  <slide :steps="1" enter="slideInDown">
    <eg-transition enter="fadeInDown" leave="fadeOut">
      <div v-if="step >= 1">
       スライドだよ！
      </div>
    </eg-transition>
  </slide>
```
![slide1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215082/b23efb3b-80d4-8d86-c61d-33d80035718f.gif)

#### ページめくりのアニメーションも柔軟に設定可能
![slide2a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215082/33d8a6ca-ac84-979f-dde4-667f79409c68.gif)

### 感想
それなりに好評でした。どうせなら文字じゃなくて成果物で語りたいよね。
コンポーネントとして分離できるしちょっとした動きをつけたい時に使えそう。
WSL2上のUbuntuで最初にする作業まとめ

もう何回検索したかも分からんくらいなので、書き残しておく。
ちょくちょく追記していく。（自戒）

## まずはProxy

aptのProxy設定。冒頭に書く。

```conf:/etc/apt/apt.conf
Acquire::http::proxy "http://id:pass@proxysrv:port/";
Acquire::https::proxy "https://id:pass@proxysrv:port/";
```

## 基本的なものインストール

```sh:aptのupdate
$ sudo apt-get update
```

```sh:基本ツール(スリムアップ中）
$  sudo apt-get install -y make build-essential llvm \
libssl-dev zlib1g-dev libbz2-dev libreadline-dev \
libsqlite3-dev libncurses5-dev libncursesw5-dev \
net-tools wget curl
```

```sh:日本語ロケール
$ sudo apt install -y language-pack-ja-base language-pack-ja
```

```sh:python3
$ sudo apt install -y python3 python-is-python3 python3-pip python3-venv
$ sudo pip3 install pip -U
````

```sh:golang
$ sudo apt install -y golang-go
```

```sh:基本？ツール。削除予定
$  sudo apt-get install -y xz-utils tk-dev libffi-dev ibus-mozc
```

## gitの個人設定

dotfilesダウンロードして、アドレスと名前は自分のに変更しとく。

```
$ cd ~
$ git clone https://github.com/<id>/dotfiles.git
$ git config --global user.email "you@example.com"
$ git config --global user.name "Your Name"
```

## Vimをビルドする

デフォだと大抵古いバージョンなので手動でビルドする.vim使わない人はパスで。

まずビルドに必要なものインストール

```:vimのビルドに必要なもの
$ sudo apt install -y libperl-dev python3-dev ruby-dev \
lua5.2 liblua5.2-dev luajit \
autoconf automake cproto
```

vimのソース取得〜インストール

```:vimのソース取得〜インストール
$ git clone https://github.com/vim/vim.git
$ cd vim
$ ./configure \
  --prefix=/usr \
  --enable-python3interp \
  --enable-luainterp \
  --enable-xim \
  --with-x
$ make
$ sudo make install
$ make clean
```

上記で--prefixを指定しなかった場合は、バイナリの場所が`/usr/local/bin/vim`なので、エイリアス張っておく
(--prefixを設定した場合は不要)


```:vimにalias張る
alias vim='/usr/local/bin/vim'
alias vi='/usr/local/bin/vim'
alias view='/usr/local/bin/view'
```

## pyenvからのpythonをインストール

システムデフォルトのと共存したいのでpyenvで管理する

```:pyenvをインストール
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
```

必要なバージョンのpythonをインストール
pyenvが見つからない場合はだいたいパスの問題

```:例：3系列の一覧表示してインストール
$ pyenv install --list | grep ^\ *3
$ pyenv install 3.8.3
```

ローカルディレクトリにバージョンを設定する場合の例

```:例：tmpディレクトリ以下に特定バージョン設定
$ mkdir tmp
$ cd tmp
$ pyenv local 3.7.6
```

## ssh接続できるようにする

WSLのデフォルトのウィンドウマネージャーは文字化けが激しいのでお好みのsshクライアントから接続できるようにする

初回のみキー作成

```sh:キー作成
$ sudo ssh-keygen -A
```

パスワード認証をyesにしておく

```:/etc/ssh/sshd_config
PasswordAuthentication yes
```

```sh:sshサービス起動
$ sudo service ssh start
```

サービス起動後はwslの画面はクローズしてOK。
あとはRLoginなどで接続する。ホスト名はlocalhostでOK


## sshサービスを自動起動

参考：[Windows10のWSL上にあるServiceを簡単に自動起動させる \- Qiita](https://qiita.com/nashi2603/items/d0645305b137017b91b0)

`Win＋R`押して、`shell:startup`を入力して`Enter`して表示されるディレクトリに下記ファイルを保存する。
以後、再起動するたびに自動でsshサービスが起動される。

```bat:wslssh.bat
@echo off
wsl -u root -- service ssh start
```

## 実験中

ファイラーranger

```
sudo apt-get install ranger
```

ターミナルに画像を表示する

```
sudo apt install -y libsixel-bin
```

## リンク

- [aptコマンドチートシート \- Qiita](https://qiita.com/SUZUKI_Masaya/items/1fd9489e631c78e5b007)
CakePHPでredirect後、即actionを停止する方法


普段はaction内で`return $this->redirect(...)`とやるのであまり気になりませんが、
例えば特殊な権限周りを別関数やComponentでチェックして、ダメなら呼び出し先で即redirectで飛ばしてしまいたい場合があります。
(毎回毎回action側で返り値見てif文でredirect...は面倒だし冗長)

その場合、[https://github.com/cakephp/cakephp/issues/11197](https://github.com/cakephp/cakephp/issues/11197) で提案されている、Exceptionを使う実装が良さそうです。
以下のようなコードをAppController.phpに書いて、redirect()の代わりにredirectWithException()を呼ぶだけで実装できます。

ただし、この場合actinoがその場所で本当に止まるため、DBやファイル編集中に使わないよう注意が必要。
多分afterFilterやbeforeRedirectも動かない。

↓サンプル (上リンクで提案されてる例から少し変更(RedirectExceptionやRouterの場所追加した))

~~~php
// redirect()の代わりにredirectWithException()を使う
// AppController.phpにコピペでOK。

    public function redirectWithException($url, $status = 302) {
        throw new \Cake\Routing\Exception\RedirectException(\Cake\Routing\Router::url($url, true), $status);
    }

    public function startupProcess() {
        try {
            return parent::startupProcess();
        } catch (\Cake\Routing\Exception\RedirectException $e) {
            return $this->redirect($e->getMessage(), $e->getCode());
        }
    }

    public function invokeAction() {
        try {
            return parent::invokeAction();
        } catch (\Cake\Routing\Exception\RedirectException $e) {
            return $this->redirect($e->getMessage(), $e->getCode());
        }
    }

    public function shutdownProcess() {
        try {
            return parent::shutdownProcess();
        } catch (\Cake\Routing\Exception\RedirectException $e) {
            return $this->redirect($e->getMessage(), $e->getCode());
        }
    }
~~~
Apache2.4でSSIを動かすときの後方参照でハマった話

##はじめに
SSI(Server Side Include)を利用して、画面の表示をそこそこディープに制御する必要があった。
その際、後方参照を用いた手法に難儀した話である。
~~枯れた技術かもしれないが、目をつむってほしい。~~

##環境
- Apache2.4
- httpd.conf には IncludesNoExec

##後方参照という言葉について
正直はっきり理解できていないが、ここでは正規表現等を用いて条件マッチした際、特定の箇所を抜くときに利用する特殊変数(\$1、$2...)のことを指す。

##$1がうまく機能しない？
さて、ハマった記述は以下の形である。

```html:false.shtml
<!--#If expr="%{QUERY_STRING} =~ /age=([^&]+)/" -->
<!--#set var="age" value="$1" -->
<!--#Endif -->
```

期待する$1の返却値はクエリストリング内のage=に記載される数値だが、これで**変数ageをechoすると(none)が返される。**
Apacheの[公式ドキュメント](https://httpd.apache.org/docs/2.4/ja/mod/mod_include.html)にサンプルとしてほぼ同一の記載があるのに、だ。

##$0にはなにがある？
上記コードの\$1を\$0にしechoすると、`age=数値`が表示される。
つまり、まったく後方参照が利用できないというわけではなさそうだ。

##結論
以下の記述であれば、期待する値を取得できることが分かった。

```html:true.shtml
<!--#If expr="%{QUERY_STRING} =~ /age=([^&]+)/" && $1 =~ /([^&]+)/" -->
<!--#set var="age" value="$0" -->
<!--#Endif -->
```
>http://~~~/?age=123
>>123

読解してみると、If文に合致する箇所は数値の部分であり、
\$0は条件合致した内容をすべて表示するため、これで数値箇所のみを取り出せることが分かった。

##なぜこうなるか（考察）
**\$1以降の後方参照は、If文と同列でないと取り扱えないようである。**
※濁した書き方なのは、正式な仕様がどこにも見つからないからだ。

調査にだいぶ時間がかかったのは、日本語のドキュメントで本問題を取り扱ったものが見当たらなかったからである。
（stackoverflow には似たような質問が散見された）
何らかの事由で、SSIを利用し条件マッチによる制御を行う必要がある諸兄の一助になれば幸いである。

###補足
Apache2.2では、If文と同列でなくとも後方参照は動作するようである。
そもそもApache2.4になってからSSIにおける変数の記述や正規表現マッチの書き方が微妙に変わっており、
日本語のナレッジも少ない為、ディープに利用している諸兄は是非発信していって欲しい。
DJI TelloでOMPLを用いた自律飛行ドローンのナビゲーション - 6.3. ARdroneのシミュレーターをGazeboで動かす

DJI Tello等ドローンの自律飛行を実現するには、3D環境でナビゲーション経路を計画としてOMPL（Open Motion Planning Library）を試してみます。


# 目次
1. [OMPLのインストール](https://qiita.com/k-koh/items/4f7e441d1225e6580f82)
2. [OMPLの基礎](https://qiita.com/k-koh/items/9933cd29599c859cac45)
3. [OMPL.appの入門](https://qiita.com/k-koh/items/fe1f05313045ed729c8b)
4. [OMPLの使用](https://qiita.com/k-koh/items/3a8b372537aa29e17863)
5. DJI Telloの使用
    1. [DJI Telloのフロントカメラのcamera_calibration](https://qiita.com/k-koh/items/094631646931ea5bc2bb)
    2. [Visual SLAM ORB_SLAM2 用のカメラキャリブレーションYamlファイルの作成](https://qiita.com/k-koh/items/b524fc175198e701bdff)
    3. [DJI Telloのカメラ でVisual-SLAMのORB-SLAM2 を動かしてみた](https://qiita.com/k-koh/items/98b5f079f784b22dcd01)
6. navigationスタックの使い方
    1. [Turtlebot3 NavigationをGazebo Simulationで動かしてみた](https://qiita.com/k-koh/items/1a4fbc175ca37be6206b)
    2. [Turtlebot3 Navigationでmap_fileの代わりにSLAMを使用](https://qiita.com/k-koh/items/1ec9097e4afedd0b43ca)
    3. [ARdroneのシミュレーターをGazeboで動かす](https://qiita.com/k-koh/items/feccbaee7c11c43c3ab4)　← いまココ
    4. [AirSimのシミュレーターを動かす](https://qiita.com/k-koh/items/52122fb5e96336ac8d33)
    5. [octomapのインストール](https://qiita.com/k-koh/items/c9a3a87e043934456842)
    6. [単眼カメラでORB_SLAM2から3D point clouodの生成](https://qiita.com/k-koh/items/1e069c9dda43b85e2fa0)
    7. [point_cloud2から3D octomapの生成](https://qiita.com/k-koh/items/01e34f353487eb8a6e26)
7. OMPLで3D 経路計画
    1. [状態空間環境のセットアップ](https://qiita.com/k-koh/items/e19ac08bb0a16975081e)


## 動作環境
- Ubuntu 18.04
- ROS Melodic
- Tello EDU

# ARdroneのシミュレーターをGazeboで動かす

## ドライバのインストール(ardrone_autonomy)
```console
sudo apt install g++-5
sudo apt install gcc-5
cd ~/catkin_ws/src/
git clone https://github.com/AutonomyLab/ardrone_autonomy.git
cd ../
catkin_make
```

```console
[ 89%] Built target point_grid
In file included from /usr/include/c++/7/bits/char_traits.h:39:0,
                 from /usr/include/c++/7/string:40,
                 from /opt/ros/melodic/include/ros/platform.h:38,
                 from /opt/ros/melodic/include/ros/time.h:53,
                 from /opt/ros/melodic/include/ros/ros.h:38,
                 from /home/k-koh/catkin_ws/src/ardrone_autonomy/include/ardrone_autonomy/ardrone_driver.h:31,
                 from /home/k-koh/catkin_ws/src/ardrone_autonomy/include/ardrone_autonomy/ardrone_sdk.h:70,
                 from /home/k-koh/catkin_ws/src/ardrone_autonomy/include/ardrone_autonomy/video.h:28,
                 from /home/k-koh/catkin_ws/src/ardrone_autonomy/src/video.cpp:25:
/usr/include/c++/7/bits/stl_algobase.h:243:56: error: macro "min" passed 3 arguments, but takes just 2
     min(const _Tp& __a, const _Tp& __b, _Compare __comp)

```

コンパイルエラーになります。


Next: 6.4. [AirSimのシミュレーターを動かす](https://qiita.com/k-koh/items/52122fb5e96336ac8d33)

Prev: 6.2. [Turtlebot3 Navigationでmap_fileの代わりにSLAMを使用](https://qiita.com/k-koh/items/1ec9097e4afedd0b43ca)
[React] makeStyles / createStyles の使い方

makeStyles,
createStyles
をimportし、useStylesを定義

```js

import { makeStyles, createStyles } from '@material-ui/core/styles';   //style関連のimport



const useStyles = makeStyles((theme) => createStyles({  //useStylesを定義
    card: {
        margin: theme.spacing(5),
        padding: theme.spacing(3),
    },
}));

function Home() {

    const classes = useStyles();  //コンポーネント内でuseStylesを使用し、classesを定義

```

classesをreturnの中のjsxで使用する

```js
    return (
        <div className="container">
            <div className="row justify-content-center">
                <div className="col-md-8">
                    <div className="card">
                        <h1>タスク管理</h1>
                        <Card className={classes.card}>     //return内でstyleを呼び出す



```


以上、備忘録

ReactではComponentごとにstyleを定義するのが一般的かと思います。
[Python3]datetimeにタイムゾーンを指定するawareな方法

PCでコーディングしたプログラムをAWSのLambda関数で実行したら、`datetime.now()`で取得される時刻が異なることに気づきました。PCはJST時間、AWSはUTC時間のため9時間の差があることが原因です。
プログラムを変えずにPCでもAWSのLambda関数でも同じ結果を得るために、datetimeにタイムゾーンを指定する方法を調べました。

#環境
- Python 3.7.4

#問題の事象
例えば次のプログラムを実行すると、PCで取得される現在時刻と、AWSのLambda関数で取得される現在時刻に9時間の差異が発生します。9時間の差異なので、Lambda関数で実行するときには` + timedelta(hours=+9)`として9時間足せばいいのだけれど、それではPCからLambda関数に持っていくときにプログラムの修正が発生するので望ましくないため、プログラムを変更せずに同じ結果が得られるようにしたいと考えました。

```python:lambda_function.py
from datetime import datetime, timezone, timedelta

def lambda_handler(event, context):
    print(datetime.now())
    #PCとAWSのLambda関数で取得される時刻に9時間の差異が発生
    return

if __name__ == "__main__":
    event = None
    context = None
    lambda_handler(event, context)
```

#解決策
datetimeにタイムゾーンを指定することで解決できます。Python3では標準ライブラリの`datetime`だけで解決できます。具体的には、`datetime`オブジェクトを生成する際に`timezone`を指定します。
ただし、`timezone`も`timezone`サブクラスから生成する必要があるため、そこでちょっと戸惑いました。
`timezone = "Asia/Tokyo"`とかではないということです。
「Pythonでは、すべてがオブジェクト」とかたまに見かけますが、こういうことなんですかね。

```python
    JST = timezone(timedelta(hours=+9)) #timezoneの生成
    print(datetime.now(JST)) #タイムゾーンを指定して現在時刻を取得
```

#注意点
`datetime`オブジェクトを使った引き算、足し算をしている場合は、タイムゾーンを揃えておかないと`TypeError`が発生します。

```
TypeError: can't subtract offset-naive and offset-aware datetimes
```

こんな感じにすればOK

```python
    JST = timezone(timedelta(hours=+9)) #timezoneの生成
    datetime.datetime(2020, 1, 31, tzinfo=JST) - datetime.datetime.now(JST)
    #tzinfoにタイムゾーンを設定
```


#もうひとつの解決策
ここまで調べた後で、もう一つの解決策があることを発見しました。
AWSのLambda関数の環境変数を変更する方法です。いろんなやり方があるのですね。

[AWSのLambdaのタイムゾーンをUTCからJST(東京)に変更](https://qiita.com/seisyu1985/items/2f3af4188a61dccf44b2)

なお、

[Python3のdatetimeはタイムゾーンを指定するだけで高速になる](https://qiita.com/mattsu6/items/5511c5631e7a54550f7f)

そうです。


#「awareなdatetime」と「nativeなdatetime」
datetimeを調べる過程で、「awareなdatetime」や「nativeなdatetime」という言葉が出てきて「なんのこっちゃ」と戸惑いましたが、大まかには、

- `datetime`オブジェクトにタイムゾーンを指定する方法は、「awareなdatetime」
- 実行環境(PC、AWSのLambda関数)のタイムゾーンを合わせる方法は、「nativeなdatetime」

ということみたいです。

言葉だけだと少々理解しにくいですが、実際にプログラムを動かしてみて結果の差異を見ることで実感できました。
groupbyしてダミー変数化する方法

以下のようなデータを

```
user_id,item_id
A,1
A,1
A,2
A,12
B,1
B,4
```

以下のようなデータの形状に変換したい。

| | item_id_1 | item_id_2 | item_id_3 | item_id_4 | item_id_5 | item_id_6 | item_id_7 | item_id_8 | item_id_9 | item_id_10 | item_id_11 | item_id_12 |
|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|
| A | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| B | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |

データとしては、`item_id`の列に出てきた最大最小の値を両端として、その間の数値をカラム名として補完しながら、出現回数をカウントしたものである。

## csvの読み込み

```py
import pandas as pd
df = pd.read_csv("user_item.csv")

df_dummies = pd.get_dummies(df, columns=['item_id']).groupby(['user_id']).sum()


```

`df_dummies`は以下のようになる

|user_id|item_id_1|	item_id_2|	item_id_4|	item_id_12|
|---|---|---|---|---|
|A|	2|	1|	0|	1|
|B|	1|	0|	1|	0|

## 足りないカラムを補足する

前段のステップだと、item_idが1,2,4,12のものはできたが、その間のカラムができていない。そこでここで準備する。

```py
# カラムの生成
columns = [f"item_id_{i}" for i in range(min(df["item_id"]), max(df["item_id"])+1)]

df_base = pd.DataFrame(columns = columns)
```

## 補足のカラムと元データを合わせる

補完したカラムをもつデータフレームと元のデータを合わせることで、目的のカラムを持つデータフレームが生成できる。ただ、補完したカラムのデータが`NaN`になるため、0で書き換える。

```py
df_target = pd.concat([df_base, df_dummies], sort=True).fillna(0)
```

さらに、これだとカラムの順番がバラバラなので順番を並び替える。

```py
df_target = df_target[columns] # columnsにはhuman sortingの順序で入っている。
df_target
```

## 関数にしてみたもの

```py
def complementedDummies(df, column_a, column_b):
    df_dummies = pd.get_dummies(df, columns=[column_b]).groupby([column_a]).sum()
    columns = [f"{column_b}_{i}" for i in range(min(df[column_b]), max(df[column_b])+1)]
    df_base = pd.DataFrame(columns = columns)
    df_target = pd.concat([df_base, df_dummies], sort=True).fillna(0)
    return df_target[columns]

df_changed = complementedDummies(df_a, "user_id", "item_id")
```
【CentOS7】juman++ のインストール

## 概要
CentOS7にjuman++ を導入したときのメモ

## 環境

- CentOS 7.6.1810
- Python 3.7.4


### gcc

```bash
 yum -y install gcc gcc-c++
```

### cpu コア確認

```bash
cat /proc/cpuinfo
```

**コマンドで出た processor の数を次の-j 〇オプションに適用**

### Boost C++
juman++ のインストールに必要なBoost C++を導入。

```bash
cd /usr/local/src
wget https://dl.bintray.com/boostorg/release/1.69.0/source/boost_1_69_0.tar.gz
tar xzvf boost_1_69_0.tar.gz
cd boost_1_69_0/
./bootstrap.sh
./b2 install -j4 #(プロセッサ数)
```

### juman
本体のビルドインストール。

```bash
cd /usr/local/src
wget 'http://nlp.ist.i.kyoto-u.ac.jp/DLcounter/lime.cgi?down=http://lotus.kuee.kyoto-u.ac.jp/nl-resource/jumanpp/jumanpp-1.02.tar.xz&name=jumanpp-1.02.tar.xz' -O jumanpp-1.02.tar.xz
tar Jxfv jumanpp-1.02.tar.xz
cd jumanpp-1.02/
./configure
make
make install
```

## 確認

```bash
$ echo "すもももももももものうち" | jumanpp
```



## 参考

- CentOS7 の Python3 で JUMAN++のインストールと利用 - デベロッパー・コラボ
  https://developer-collaboration.com/2019/01/29/centos7-python3-juman/

- メモ帳という名の備忘録\_ Python3 から JUMAN++を使う@CentOS7
  https://umiushizn.blogspot.com/2017/09/python3jumancentos7_9.html
Stripeの有料プラン変更時の挙動のまとめ

Stripeの実装にあたって、実際に自分で開発しているサービスのケースに合わせた場合のユースケースメモ。
参考: https://qiita.com/AkihikoNambu/items/bb496612f3044b2b3e1e

************************************************
有料プランをアップグレードするケース(前払い制)

(例) ライトプラン(¥980) -> ベーシックプラン(¥2980)に変更するケース
4/1 ライトプランの料金(¥980)を支払う
4/15 ベーシックプランへ変更
    差分を計算
    ベーシックプラン => 4/15 ~ 4/30 => (2980 * (15/30)) => 1490
    ライトプラン 4/1 ~ 4/15 => (980 * (15/30)) => 490
    差分: 1490 - 490 = 1000
5/1 プレミアムプランの料金 + 差分を請求 = 2980 + 490 = 3470円が請求される

************************************************
有料プランをダウングレードするケース(前払い制)


(例) ベーシックプラン(¥2980) -> ライトプラン(¥980)に変更するケース
4/1 ベーシックプラン(¥2980)を支払う
4/15 ライトプランへ変更
    差分を計算
    ライトプラン 4/1 ~ 4/15 => (980 * (15/30)) => 490
    ベーシックプラン => 4/15 ~ 4/30 => (2980 * (15/30)) => 1490
    差分: 490 - 1490 = ¥-1000
5/1 ライトプラン(¥980)の料金 + 差分を請求 = 980 + (-1000) = 0円が請求される（差額残り ¥-20)
6/1 ライトプラン(¥980)の料金 + 残りの差分を請求 = 980 + (-20) = ¥960が請求される(差額残り ¥0)
7/1 ライトプラン(¥980)の料金が請求される

************************************************
定期課金終了時に未払いの差額が残っているケース(前払い制)


(例) ライトプラン(¥980) -> ベーシックプラン(¥2980)に変更するケース
4/1 ライトプランの料金(¥980)を支払う
4/15 ベーシックプランへ変更
    差分を計算
    ベーシックプラン => 4/15 ~ 4/30 => (2980 * (15/30)) => 1490
    ライトプラン 4/1 ~ 4/15 => (980 * (15/30)) => 490
    差分: 1490 - 490 = 1000
4/20 キャンセル手続き
    差分: ¥750が残っている
5/1 差額分はStripeによって自動で決済される。
リモートブランチをローカルにチェックアウトしたい

```bash
git checkout -b LOCAL_BRANCH_NAME origin/REMOTE_BRANCH_NAME
```

でチェックアウトできます。
LOCAL_BRANCH_NAMEとREMOTE_BRANCH_NAMEを変えればローカルとリモートでブランチ名が変えられます。
自分は基本リモートブランチとローカルブランチの名前を変えたいことがないので、

```bash
$ git config --global --edit
```

```bash
[alias]
        new = !sh -c 'git checkout -b $0 origin/$0'
```

とエイリアスに登録しています。
これで登録していると、以下でリモートブランチをローカルにチェックアウトできます。

```bash
$ git new REMOTE_BRANCH_NAME
```
Android アプリのビルド時に GC overhead limit exceeded が出たときに確認すること

# 概要
macOS を Mojave から Catalina へアップデート後、 Android アプリをビルドすると

```
GC overhead limit exceeded
```

というエラーが出るようになってしまいました。。。🤔

原因を突き止めたので書き残しておきます。

# 原因（ぼくの環境の場合）

いきなり結論を。

Android Studio の Memory Settings が初期化されていたせいでした…

* Android Studio - Preferences
![スクリーンショット 2020-01-17 20.19.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34926/496b582a-9acd-ce2d-fd71-706a3a4517a7.png)


赤枠の項目が 空白 になっていました。

こちらを設定したら無事ビルドできるようになりました！ 🎉

# 他に確認したこと

「GC overhead limit exceeded」 で調べるといろいろヒットすると思います🔎

## build.gradle に javaMaxHeapSize を定義しているか

```gradle:build.gradle
android {
    dexOptions {
         javaMaxHeapSize "2g"
    }
}
```

[Android開発中にGC overhead limit exceededで逝く](https://qiita.com/satof7211/items/fb7e5e20203cda1f0d50)

こちらの記事に詳しく書かれています。

ぼくの build.gradle には既に定義されていました…。

## gradle.properties に jvmargs を定義しているか

[[stackoverflow] java.lang.OutOfMemoryError: GC overhead limit exceeded on Android 1.4](https://stackoverflow.com/questions/32133013/java-lang-outofmemoryerror-gc-overhead-limit-exceeded-on-android-1-4/32133048)

途方に暮れていたらこちらの stackoverflow にたどり着きました。

```gradle:gradle.properties
org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError
```

確認してみると定義されていませんでした❗️キタ❗️これでビルドできるー🙌

ウキウキで gradle.properties に追記してビルドボタンぽちっ❗️

ダメでした…。

各値を書き換えてみたりしましたがビルドできずでした。。

# おわりに

こちらの記事が誰かの助けになると幸いです🙏


# 参考

* [Android開発中にGC overhead limit exceededで逝く](https://qiita.com/satof7211/items/fb7e5e20203cda1f0d50)
* [[stackoverflow] java.lang.OutOfMemoryError: GC overhead limit exceeded on Android 1.4](https://stackoverflow.com/questions/32133013/java-lang-outofmemoryerror-gc-overhead-limit-exceeded-on-android-1-4/32133048)
JSON.Stringifyで循環オブジェクト参照構造体が処理できないのをcycle.jsで処理する方法

# 概要

<https://qiita.com/saitoeku3/items/9e9a608e53029d541a8f>
と同じエラーにあったので、cycle.jsで処理したサンプルコードを紹介するよというお話

## cycle.js

<https://github.com/douglascrockford/JSON-js/blob/master/cycle.js>

## インストール

```bash
npm install json-cyclic
```

## サンプルコード

```js
//import
const decycle = require('json-decycle').decycle;
const retrocycle = require('json-decycle').retrocycle;
...

...
//文字列に変換
receiveNewAcString = JSON.stringify(receiveNewJson, decycle());

//JSONオブジェクトに変換
receiveNewAc = JSON.parse(receiveNewAcString, retrocycle()).data;
```
WSL(Windows Subsystem for Linux)をPower Shellだけでインストールする

会社のパソコンを使ってたりしてセキュリティの関係でGUIからうまくWSL追加できなかったり、Microsoft Storeがそもそも使えない場合の手順のメモ。

# Power Shellを起動する
Windowsボタンを押して「PowerShell」って入力する、とPowerShellが候補に出てくる。
このままクリックすると管理者権限なくてこの先の作業ができない。なので項目の上で右クリックして「管理者として実行」を選択するとPowerShellが管理者権限で起動する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/4191a54c-a493-659e-ad3b-b53086859981.png)


# WSL機能を有効にする
PowerShellで以下のコマンドを実行

`Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux`

再起動を求めてくるのでYを入力して再起動する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/d81c35ae-f8c0-4f6e-ea11-ffebf1a80c02.png)


# ディストリビューションのダウンロード
再起動が終わったら、再びPowerShellを管理者として実行する
以下のコマンドでディストリビューションが「ダウンロード」フォルダに保存される。

`Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1804 -OutFile C:\Users\$env:USERNAME\Downloads\Ubuntu.appx -UseBasicParsing`

他のディストリビューションのURLは以下のページから確認できる。
[Windows Subsystem for Linux (WSL) ディストリビューションを手動でダウンロードする | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/wsl/install-manual)

# ディストリビューションのインストール
以下のコマンドでダウンロードしてきたディストリビューションをインストール。

`Add-AppxPackage C:\Users\$env:USERNAME\Downloads\Ubuntu.appx`

これで完了です。

# 参考にしたページ

- [Windows Subsystem for Linux (WSL) を Windows 10 にインストールする | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10)
- [Windows Subsystem for Linux (WSL) ディストリビューションを手動でダウンロードする | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/wsl/install-manual)
HTMLマイテンプレート

自分用です。

```html
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
  <script src="javascript.js"></script>
  <link rel="stylesheet" type="text/css" media="screen, tv" href="browse.css"></link>
　<script></script>
  <style></style>

  <title>マイテンプレート</title>
</head>
<body>

</body>
</html>

```
Lightning Web ComponentのDatatableでSortする方法_1

# lightning-datatableでソートするには

## 罠

<https://developer.salesforce.com/docs/component-library/bundle/lightning-datatable/documentation>
によると、

```js
        // The method onsort event handler
        updateColumnSorting(event) {
            var fieldName = event.detail.fieldName;
            var sortDirection = event.detail.sortDirection;
            // assign the latest attribute with the sorted column fieldName and sorted direction
            this.sortedBy = fieldName;
            this.sortedDirection = sortDirection;
            this.data = this.sortData(fieldName, sortDirection);
       }
```

で完成しそうであるかのように書いてあるが、これが罠で、sortDataメソッドを作成する必要がある。
んじゃ、sortDataはどう作ればいいのというと、aura componentのドキュメントにsortDataの中身の記載がある。

<https://developer.salesforce.com/docs/component-library/bundle/lightning:datatable/documentation>

```js
({
    sortData: function (cmp, fieldName, sortDirection) {
        var data = cmp.get("v.data");
        var reverse = sortDirection !== 'asc';
        //sorts the rows based on the column header that's clicked
        data.sort(this.sortBy(fieldName, reverse))
        cmp.set("v.data", data);
    },
    sortBy: function (field, reverse, primer) {
        var key = primer ?
            function(x) {return primer(x[field])} :
            function(x) {return x[field]};
        //checks if the two rows should switch places
        reverse = !reverse ? 1 : -1;
        return function (a, b) {
            return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
        }
    }
})
```

## サンプルコード

auraのコードしか載ってないじゃん、lightning web componentでどう作るんですか？
という私のコピーみたいな人のためにサンプルコードをあげておきます。


```js
    sortData(fieldName, direction) {
        let sortingData = JSON.parse(JSON.stringify(data));

        let keyValue = (a) => {
            return a[fieldName];
        };

        let isReverse = direction === 'asc' ? 1 : -1;

        sortingData.sort((x, y) => {
            x = keyValue(x) ? keyValue(x) : '';
            y = keyValue(y) ? keyValue(y) : '';

            return isReverse * ((x > y) - (y > x));
        });
        this.data = sortingData;
    }
```

## 注意

このヘルパー関数でソートする際に注意点があり、日付のfieldでソートする場合は、

```js
const data = [{
    lastLogin: '2019-10-10'
}
```

このような形式にする必要がある。
筆者は、

```js
const data = [{
    lastLogin: '2019/10/10'
}
```

このようにしてソート機能が正常に動かないバグに10時間くらい時間を食われたので、参考までに…。

## 追記

salesforceでのプログラミングをする際は必ずsalesforceのフォーマットに合わせたデータを作らないと正常に動作しないので、必ず、salesforceでどのようなフォーマットが使われているのかを調査したのちにプログラムを作ることをオススメする。
主に、コンポーネントで使われるフォーマットはそのコンポーネントのドキュメントに記載があるので、参照すると良い。
【メモ】条件分岐

if maxmin.to_i <= 14
Auter hoode-f pant shose

==================================================================
maxmin.to_i <=14
1 2 3 4 5 
TOP   auter-f,  
TOP2  jaket-s         
inner t-long    
pant                   
shose 

6 8 10 12 14
TOP auter-f
inner t-long
pant
shose

7 9 11 13
TOP auter
innner Hoode-f t-long
pant
shose 

15 16 17 18 
TOP Jaket-s Jaket-m
inner  hoode-f t-long
pant
shose

19 20 21 22 24 26 
TOP Jaket-s Jaket-m hoode-j
inner t-long t-short
pant
shose
23 25 27 28
TOP hoode-f t-long
pant
shose

29以上
TOP t-short
pant
shose
スナップショットからRDSインスタンスを作成する方法

# はじめに

"出来合いのDB"のスナップショットからクローンとなるRDSインスタンスを作る機会があったので、その手順をまとめてみました。

# スナップショットの選択

* AWSマネジメントコンソールのトップ画面から、［サービス］>［RDS］と進みます。
* RDSの画面の左側のパネルで、［スナップショット］を選択します。

![rds_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/ce037d02-4b82-a9bb-ab82-c82b35ea0820.png)

* スナップショット画面が開いたら、所望のスナップショットにチェックを入れます。
* その後、スナップショット画面上部の［スナップショットのアクション］のリストをクリックして、［スナップショットの復元］を選択します。

![rds_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/0adc4a7c-f098-89d4-db95-c7d9e3808685.png)

# スナップショットの復元

DBインスタンスの復元画面で、以下の事項を設定します。
設定が完了したら、画面最下部の［DBインスタンスの作成］ボタンをクリックして、スナップショットからRDSインスタンスを作成します。

![rds_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/3f7dbd3a-c56b-fb0a-c8c4-e21f2151500c.png)

## インスタンスの仕様

* DBエンジン
* ライセンスモデル
 * ライセンス込み（ライセンス料はRDSの利用料に含まれている）
 * BYOL（自分のライセンス使用）
* DBインスタンスのクラス
 * db.t3.micro～db.t3.2xlargeなど、20種類程度の中から選びます。
* マルチAZ配置
* ストレージタイプ
 * 汎用SSD/プロビジョンドIOPS/マグネティックの3種類から選びます。

## 設定

* DBインスタンス識別子
 * RDSの画面では"DB インスタンス ID"の欄に表示されます。

## ネットワーク&セキュリティ

* VPC
* サブネット
* パブリックアクセシビリティ
 * デフォルトは「いいえ」。
 * DBを外部に公開する場合は「はい」に設定します。（※[参考にした記事はこちら](https://qiita.com/ksugahara08/items/c5e76e400d1fbf736416)）
* アベイラビリティ―ゾーン
* VPCセキュリティグループ
 * デフォルトは［新規のVPCセキュリティグループを作成］となっているので、このRDSインスタンス用に新しいセキュリティグループが作られます。
 * ［既存のVPCセキュリティグループの選択］を選択すると、既存のセキュリティグループを選ぶことも可能です。

## データベースの設定

* データベースの名前
 * RDSの画面では"DB 名"の欄に表示されます。
* データベースのポート
 * DBエンジンがOracleの場合、デフォルト値は1521となっています。
* DBパラメータグループ
* オプショングループ

## バックアップ

* タグをスナップショットへコピー

## 暗号化

## ログのエクスポート

* アラートログ/監査ログ/リスナーログ/トレースログの中から、CloudWatch Logsに発行するログを選択します。
 * 上記の中から複数個選択可能です。

## メンテナンス

* マイナーバージョン自動アップグレード
 * リリースと同時にDBエンジンのバージョンアップを自動的に行う場合は「はい」に設定します。

# まとめ

* スナップショットからの復元には数分～の時間を要するようです。
 * 当たり前の話ですが、復元が完了するまではRDSインスタンスの設定を変更できません。
* DBを外部に公開する場合は、`パブリックアクセシビリティを有効化する`だけでなく、`セキュリティグループ`にも気を付ける必要があります。
 * セキュリティグループで、インバウンドの欄に`接続元となる信頼できるIP`が設定されていることを必ず確認すること。
 * スナップショットからの復元時に`新規のVPCセキュリティグループを作成` が選択されている場合、余計なセキュリティグループが出来てしまって、それを削除する手間がかかるかもしれません。
* スナップショットからの復元は、新しいRDSインスタンスを作ることに等しいです。
 * [こちらの記事](https://qiita.com/niisan-tokyo/items/c54bdaffc916330796b8)にも書かれているように、「スナップショットを使って、ある時点まで既存のDBをロールバックする」のではなく、「スナップショットを使って、ある時点のDBインスタンスを新たに作る」ということになります。

# 参考URL

* [AWS RDSを外部接続可能にする手順](https://qiita.com/ksugahara08/items/c5e76e400d1fbf736416)
* [RDSでDBをスナップショットから復元する](https://qiita.com/niisan-tokyo/items/c54bdaffc916330796b8)
シェルスクリプト テーブル形式っぽく出力する

最初に変数 output にフィールド名をスペース区切りで格納しておきます。
改行したい位置には、$'\n' をセットします。
後は各フィールドの値をスペース区切りでセットしていきます。
出力時には printf で書式を指定しています。

```table_output.sh
students=("1 Tom 70" "2 Keiko 80" "3 Peter 65" "4 Risa 100")
output="id name score"

for student in "${students[@]}"
do
  set -- $student
  output="${output}"$'\n'"$1 $2 $3"
done
# 書式指定なし
echo "${output}"
# 書式指定あり
echo "${output}" | awk '{printf "%-5s|%-10s|%-5s\n",$1,$2,$3}'
```

###### 書式指定なし

```
id name score
1 Tom 70
2 Keiko 80
3 Peter 65
4 Risa 100  
```

###### 書式指定あり

```
id   |name      |score
1    |Tom       |70   
2    |Keiko     |80   
3    |Peter     |65   
4    |Risa      |100
```
Adobe PDF to jpg 高品質

Adobe PDF（Portable Document Formatと略します。「Portable Document Format」を意味します）は、アプリケーション、オペレーティングシステム、ハードウェアに依存しない方法でファイル交換によって開発されたファイル形式です。 Adobe PDFファイル形式では、デバイス、解像度に依存しないテキスト、フォント、形式、色、グラフィック、画像を単一のファイルにカプセル化できます。 私たちの仕事でよく使用されるファイル形式です。 ただし、テキストや写真を処理する場合、作業要件により、Adobe PDFをJPG形式に変換する必要がある場合があります。 Adobe PDFをjpgに変換する方法は？ 仕事でAdobe PDFファイルをJPGに変換する問題に遭遇したことはありますか？ Adobe PDFをJPG画像形式に変換する方法について話しましょう。
Sanpdf –無料のAdobe PDFからjpgへのコンバーター拡張機能は、Adobe PDFをjpgに変換するのに役立ちます。わずか数ステップで簡単に行えます。

1. Google Chromeを開き、Sanpdfを検索し、Sanpdfの公式Webサイトにアクセスします![1png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560346/c968370d-a8df-3bde-2c74-13b0f307ced8.png)
2. ナビゲーションバーの「変換」で「Adobe PDFからJPG」を選択して、変換ページに入ります。 ダウンロードボタンをクリックしてインストールします。![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560346/89f7550f-a844-1561-1781-0fe644f82d33.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560346/e5e16a50-0295-c396-da6d-9b5d3f9669ec.png)
3.SanPDFをインストールすると、Sanpdf PDFインターフェイスが表示されます。 Adobe PDFからjpgへの変換ツールをクリックして選択します。![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560346/3e33f704-479f-76a2-ca88-43183c6b8ee3.png)
4. 「保存リスト」をクリックして、保存する場所を選択します。 「ファイルを追加」をクリックして、変換するAdobe PDFファイルを選択します。 次に、「変換を開始」をクリックします。![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560346/30f47a39-9fec-719e-63b2-282fb2e91a3f.png)![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560346/614e1282-d248-47a4-9cc9-63b269c25a2b.png)
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560346/ed95b2b7-2b3a-6dbc-bbc4-1c175ca27dfd.png)
5. 「保存リスト」をクリックして、保存する場所を選択します。 「ファイルを追加」をクリックして、変換するAdobe PDFファイルを選択します。 次に、「変換を開始」をクリックします。![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560346/307c0770-d242-cf2b-6da5-c3784b8781a3.png)
6. 変換が完了したら、[ファイルの参照]をクリックします。 変換されたファイルを表示できます。
7. 上記は「Adobe PDFからJPG」への変換方法です。 変換された画像はすべて高品質です。 写真の品質について心配する必要はありません。 変換する必要がある場合、上記のメソッドを参照として使用できます。 プライバシーが心配な場合は、変換後に「サーバーからファイルを削除」をクリックすると、元のファイルと出力ファイルが削除されます。
HTTPのこと~

# HTTPについて
- Hypertext Transfer Protocol（ハイパーテキスト転送プロトコル）の略称である
- ブラウザとWebサーバーの間でデータを通信するプロトコルのことをいう


## HTTP リクエストメソッド
- クライアントがサーバーにしてほしいことを依頼（＝リクエスト）するための手段のこと
- HTTPはメソッドを持っている（GET, POST, PATCH, DELETE, PUT, OPTIONS等）

##  基本的な４つの操作
- HTTPリクエストメソッドには４つの基本的な操作があり、それぞれ動詞に対応づけられている
    1. GET
        - 最も多く使われるHTTPリクエスト
        - 主にWeb上のデータを読み取るとき（データの取得）に使う
        - クライアント（Wedブラウザ）は https://qiita.com などのWebサイトを開くたびにGETリクエストをサイトに送信している
    2. POST
        - データを送信する時に使う
        - また、何かを作成するときに多く使う（新しいユーザー、新しい投稿等）
    3. PATCH
        - サーバー上の何かを更新するときに使う（記事のタイトルだけ更新、本文だけ更新等）
    4. DELETE
        - 既存データを削除したいときに使う（アカウントの削除、投稿の削除等）
- Railsを含む多くのフレームワークは、HTTPの各操作を発展させたRESTアーキテクチャの影響を受けている（RESTアーキテクチャについて書こうとおもってた！)

## 最後に
Rails tutorial コラム 3.2を参考にしました。
https://railstutorial.jp/chapters/static_pages?version=5.1#aside-get_etc
【Next.js/Nuxt.js】Nuxt.jsで言うasyncData()のNext.js版→getInitialProps()

# Next.jsのgetInitialProps()

Next.jsでも、Nuxt.jsで言うところのasyncData()にあたる処理と思われる処理を見つけました。
`getInitialProps(context)`です。

詳しくは、[getInitialProps | 公式サイト（英語)](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps)に記載があります。
画面表示前にfetchができるとのことです。


※もし認識に誤りがある場合はコメント頂けるとありがたいです。


# 説明

getInitialProps()の引数は、[Context Object | 公式サイト（英語)](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps#context-object)です。

jsxの`this.props`に`getInitialProps()`でreturnしたオブジェクトのプロパティが入ってきます。

以下は、上記の公式サイトより簡素に書き直したものです。


```react
import React from 'react'

class Page extends React.Component {
  // 引数「context」については上述
  static async getInitialProps(context) {
    return { name: 'Hanako' }
  }

  render() {
    // this.propsにプロパティ「name」が入ってくる
    return <div>Name is {this.props.name}</div> 
  }
}

export default Page
```

# 参照URL
- [getInitialProps | 公式サイト（英語)](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps)

- [Context Object | 公式サイト（英語)](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps#context-object)
Q10.セルの文字色を変えるには？

今回は、セルの文字色について考えていきます。
以下の画像をご覧ください。

![Q9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560479/cd81e0d1-ea18-173d-0cd5-1ea58c3486e6.png)

前回のQ9の結果の画像です。
今回はこちらの画像を加工していきましょう。

どのように加工していくかというと、セルの文字色は変えます。
80点以上を青色に、30点未満を赤点に変えるマクロを作ってみましょう。



###■ポイント
ポイントはもちろんセルの文字色をどうやって変えるかというところ。
セルの文字色はRangeオブジェクトのFontプロパティのColorIndexプロパティを使うことが変えることが
できます。
ただし、ColorIndexプロパティの番号に対応する色を事前に調べておかなければいけません。

ちなみに今回使用する青色は5で赤色は3となります。


###■回答
```VB
Sub Q10_Answer()
    Dim r As Range
    For Each r In Range("C3:E15")
        If r.Value > 79 Then
            r.Font.ColorIndex = 5
        End If
        If r.Value < 30 Then
            r.Font.ColorIndex = 3
        End If
    Next r
End Sub
```

###■解説
今回は、ForEach文を使用して、データが記入されているセルを
ダイレクトに指定しております。
該当セル範囲内の値をひとつひとつ見ていき、
If文で条件分岐しています。

r.Font.ColorIndex = 5

上記のように記載することで、セルの文字色を変えることができます。
この場合は青色になります。

最後に実行結果はこちらになります。

![Q10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560479/1c4ca26a-d3af-ba8b-808e-ff3781890cf7.png)
Goの環境構築

# Go 開発環境構築

最近Goの勉強をはじめました。
このあたりは、ググったら同じような記事が出てくるので、自分の備忘録も兼ねて記事にしています。
便利なパッケージ等があったら更新していくかもしれません。
ほんの少しでも、Goを始めようと思っている方への力になれたら幸いです。

## 環境

- macOS Mojave (10.14.6)
- zsh
- Homebrew 2.2.1
- IntelliJ IDEA

## Go のインストール

1. Homebrew でインストール

```
% brew install go
```

2. バージョン確認

```
# バージョンの確認
% go version
go version go1.13.5 darwin/amd64

# GOROOTの確認
% go env GOROOT
/usr/local/Cellar/go/1.13.5/libexec

# GOPATHの確認
% go env GOPATH
/path/to/gopath
```

## IntelliJ の設定

1. プラグインのインストール
   `Preferences > Plugin`から、JetBrains 製の、Go のプラグインをインストール

1. GOROOT の設定
   `Preferences > Language & Frameworks > GO > GOROOT` で設定する。

1. [GOPATH の設定](https://github.com/golang/go/wiki/SettingGOPATH)
   `Preferences > Language & Frameworks > GO > GOPATH` で設定する。<br>
   `go get`のパッケージダウンロード先を指定する。<br>
   デフォルトは`$HOME/go`が自動的に指定される。

## パッケージを探す

Goのパッケージは以下のサイトなどでドキュメントが見れるので、検索すると良さそう。
https://godoc.org/

# Docについて

いろいろ調べてまとめようとしたが、この記事を読んでおいたら良さそう。
とても勉強になりました。ありがとうございます🙏
[チョットできるGoプログラマーになるための詳解GoDoc](https://qiita.com/shibukawa/items/8c70fdd1972fad76a5ce)

# 最後に

Goの環境構築、思っていたよりも簡単にサクッとできました。
環境構築の際にぶつかる壁がほとんどないので、よかったら始めてみてください！
IBM Cloud Schematicsの困ったところ

[前回](https://qiita.com/teruq/items/c05ccbecc381a514af54)紹介のとおりIBM Cloud SchematicsサービスはIBM CloudでTerraformを使うためのサービスです。この数日いじってみて、困ったことがいくつかあったので書きます。

## ワークスペース作成時にリポジトリとしてGitLabを使用する場合、パブリックにしてもアクセストークンが要求される

パブリックなので要らないはずなのですが、アクセストークンを要れないとリポジトリにアクセスできずエラーとなりました。ちなみにGitHubだとこんなことは起きませんでした。

この件はIBMさんのサポートに連絡済です。

## ワークスペース作成時にリポジトリとしてGitLabを使用し、かつサブディレクトリを指定すると、変数の取得に失敗する

これもGitLabの場合ですが、テンプレートをリポジトリのサブディレクトリに配置し、変数の取得を行うと変数定義がないと言われます。さらに、リポジトリのルートにテンプレートがある場合、なぜかそちらの変数が取得され表示されてしまいます。ちなみにGitHubでは起きませんでした。

この件もIBMさんのサポートに連絡済です。

## Terraformのバージョンが0.11.4と古い

Terraformは0.11と0.12でテンプレートの構文が変わってしまったので、基本的に0.12向けのテンプレートは使えません。

しかし困ったことに、IBMさんが公開しているTerraformのテンプレートサンプルがなぜか0.12準拠のものが多いんですよね。なので現在はそのまま使えません。

IBMさんのサポートには0.12にする予定があるかどうかは聞いています。

## tfstateファイルを見れない、いじれない

Schematicsサービスではクラウドサービス側でTerraformが実行されますが、その際に生成されるtfstateファイルを我々は見ることもいじることもできません。

## クラウドのリソースがすでに存在している場合にリソースが重複する

あるリソースをあらかじめSchematics以外で作成済とします。次にそのリソース名を使用したテンプレートを作り実行すると、tfstateがないので、Terraformはそのリソースの新規作成を試みます。

例えばリソースグループの場合は重複でエラーとなります。アクセスグループの場合は名称の重複が（なぜか）IBM Cloud的に許容されているので、アクセスグループがもう1つできてしまいます。

これが何を意味するかというと、Schematicsで管理したいリソースは新規作成時点からSchematicsを使わないといけないということになります。しかし既存のリソースも管理下に置きたいですよねぇ。