OmniAICreator/Qiita-1.07M huggingface dataset:
HiveとPrestoの違いについて調べてみた

近年、分散型SQLクエリエンジンとして注目を集めている「**Hive**」と「**Presto**」
それらの性質の違いに目を向けて、白黒つけてやろうじゃないかという記事です

#そもそもHiveって？
簡単に言ってしまえば、MapReduce処理を可能にする分散型SQLクエリエンジンです
MapReduce処理とは大量のデータを高速に処理するための分散処理フレームワークで、HiveQLというSQLライクな言語を用いてHadoop上で実行できるという優れものでした

とまあその辺りで、Hiveに関する詳細は諸事情により割愛させていただきます（書き出したらキリがないので…）
そんなんじゃ理解できねえよ！という方は、「Hadoop Hive MapReduce」などのキーワードで検索して頂けるとご納得いくかと思います

Hiveはそもそもバッチ処理を目的としており、クエリを実行してからのレスポンスの遅さがネックとなっていました
そこで登場するのが、Prestoなのです


#そもそもPrestoって？
> Presto is an open source distributed SQL query engine for running interactive analytic queries against data sources of all sizes ranging from gigabytes to petabytes.
> Presto was designed and written from the ground up for interactive analytics and approaches the speed of commercial data warehouses while scaling to the size of organizations like Facebook.
*公式サイト(http://prestodb.github.io/) より*

(-"-;)ﾑﾑ…英語…
要約すると、

- Facebookが開発している分散型SQLクエリエンジン
- あらゆる大きさのデータサイズに対しても、インタラクティブ（対話的）な処理が可能

インタラクティブというだけあってクエリ処理が高速で行われ、実行結果をリアルタイムに取得できるという点で優れているとのこと（Facebookすげぇ）

# じゃあ、なぜそんな高速処理ができるのか
っていう疑問になりますよね
それは、Hiveと計算の仕組みが根本的に異なるからです

上で述べたように、Hiveはクエリが実行された際にMapReduce処理がなされるのに対し、
Prestoはクエリが実行された際、ジョブをタスクに分割し、タスクが並行して処理されるのです
また、中間データをメモリに持つことでデータのやりとりが高速になり、素早いレスポンスを得ることが可能となっているのです
（※しかし、これは裏を返せば、中間データがメモリ上に乗り切らない場合は処理が失敗する可能性もあるということになります）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/304818/d220a1f5-3a57-81b4-4c2b-ed7d9cd3bd74.png)
(トレジャーデータのブログより引用: https://tug.red/entry/2014/07/10/150250/)

# どっちが優れてるって訳じゃない！
それなら、HiveではなくPrestoだけ使えばいいじゃん！
と結論づけてしまってはいけません

PrestoとHiveの使い分けを簡単に説明している方がいたので引用させていただきました
(引用: https://www.slideshare.net/y-ken/bullet-hadoop-query-engine-presto)

> - Presto
    - 長くても2~3分で終わる集計に最適
    - コンパクトな処理をすばやく実行したい時
> - Hive
    - 数分以上〜数時間掛かるバッチクエリ
    - メモリに乗り切らないオーダーの処理
        - JOIN数が多い時ないし、JOINの条件が文字列である時
        - 結果セットが数百万行、文字列型カラム多数の時

処理時間だけではなく、メモリに乗り切る処理かどうかも判断基準になりますね
中間データが大きくなる並列処理の場合はHive、小さくて済む並列処理の場合はPrestoといった辺りでしょうか

# 補完しあうHiveとPresto
とまあ、簡単ではありますが、HiveとPrestoはどちらが優れているというわけではなく、お互いが補完しあっているということがお分り頂けたでしょうか
その時々に応じた使い分けが求められますね

めでたしめでたし :relaxed:
forEachを使わずフラットなデータをツリーデータにする

なんとなく**Array.prototype.forEach**やjQueryの**each**を使って再帰関数を回していたのですが、「[JavaScript で forEach を使うのは最終手段](https://qiita.com/diescake/items/70d9b0cbd4e3d5cc6fce)」という記事を読み、少し考えを改めてみようと思いました。

しかし``parent_id``というプロパティを持つフラットなデータを読み込み、それをツリー型にしてみたいと思った時、あれ？と考え込みました。
うーん、**forEach**つかわず再帰処理させつつデータを作り直すってどうやるんだ・・・

```javascript:とりあえず何も考えず書いたコード
let func = (obj) => {
    obj.items = Object.assign([], master_categories.filter(category => 
        category.parent_id === obj.category_id))
    obj.items.forEach(func)
}
let categories = Object.assign([], master_categories.filter(category => !category.parent_id))
categories.forEach(func)
//読みにくいかもですが、filter()は実体参照するのでassign()でオブジェクトを複製してます
```

##Array.prototype.mapを使う
**forEach**よりはマシなのだろうか？
本来はこんな使い方をする関数ではなさそうですが、ひとまずはperlっぽく**map**を使うことに。

```javascript
let func = (obj) => {
    let robj = Object.assign({}, obj)
    robj.items = master_categories.filter(category =>
        category.parent_id && category.parent_id === robj.category_id).map(func)
    return robj
}
let categories = master_categories.filter(category => !category.parent_id).map(func)
```

もっと賢いやり方がありそうですが、ひとまずこれで妥協することに。

##追記
一応それっぽいですが、なにか優位だと言える証拠をみつけたかったのでGoogle(他力)にすがってみました。
参考：[JavaScript — Map vs. ForEach(codeburst.io)](https://codeburst.io/javascript-map-vs-foreach-f38111822c0f)
このサイトの検証結果では**forEach**は**map**より70%も遅いという結果がでたそうです。
Raspberry Pi 3 Model B+にDebian(64bit)をモニタ・キーボードなしでインストールする

#初めに
一般的にはRaspbianをインストールしますがRaspbianは32bitであるため、64bitしか対応していないソフトウェアは動かないことがあります。そこで、64bitに対応しているDebianをインストールします。ただし、Raspberry Pi 3用のDebianはPREVIEW版となっており正式リリースはまだされていません。
#用意するもの
・PC（今回はWindows10で作業します。）
・Raspberry Pi 3 Model B+
・MicroSDカード
#インストール手順
1.Raspberry Pi 3用のDebianをダウンロード
https://wiki.debian.org/RaspberryPi3#Preview_image

以下のhttps://~をコピーしてブラウザのアドレスバーに貼り付けるとダウンロードが始まります。
xzで圧縮されているため、7zip等のソフトで解凍してください。
![dd.PNG](https://qiita-image-store.s3.amazonaws.com/0/217010/45245ad3-7b31-6138-3a11-57489cfb7864.png)


2.Etcherのダウンロード
OSイメージをSDカードに書き込むためのフリーソフトです。
https://www.balena.io/etcher/

Portable版を選択すればexeをダウンロードするだけで使用できます。
![ec.PNG](https://qiita-image-store.s3.amazonaws.com/0/217010/0f1f0569-c1bd-0d2d-5bf0-a49347575e06.png)

3.SDカードをパソコンに接続します。

4.Etcherを起動しダウンロードしたOSイメージをSDカードに書き込む。

Etcherを起動し
![ec2.PNG](https://qiita-image-store.s3.amazonaws.com/0/217010/b94d4c53-243c-d807-e9e9-420db3b4bcd5.png)

ダウンロードしたOSとSDカードを選択し書き込み開始。
![on.PNG](https://qiita-image-store.s3.amazonaws.com/0/217010/cd5d0bda-7e2e-0509-9237-540c4c79129a.png)

この画面が出れば完了です。SDカードが自動でパソコンから非接続の状態になります。
![ok.PNG](https://qiita-image-store.s3.amazonaws.com/0/217010/76b25e4f-9c76-91a1-02d0-479e4cbf68a8.png)

5.Raspberryを起動する。
SDカードをパソコンから抜き、Raspberryに挿します。
その後、Raspberryを起動します。

6.SSH接続を行う。
コマンドプロンプトやPowerShellを使ってSSH接続を行います。
　ssh root@rpi3
　パスワード：raspberry

もしrpi3でホスト名が解決できない場合はIPアドレスを調べる必要があります。
Androidをお持ちの方はFingというスマホアプリを使えば簡単に調べることができます。
https://play.google.com/store/apps/details?id=com.overlook.android.fing&hl=ja

![ok.PNG](https://qiita-image-store.s3.amazonaws.com/0/217010/79c268a3-c6f0-dc00-f687-fe4456dcb528.png)
![arc.PNG](https://qiita-image-store.s3.amazonaws.com/0/217010/c8f1a1a9-2826-cf2e-b9de-cac29435c339.png)
gulpの導入から実行までにハマったためメモ

初めての記事更新。
仕事でgulpを導入する際にハマったため自分用にメモ。

## 環境

- homebrew nodebrewはインストール済

こちら参考にしました。ありがとうございました:relaxed:
[Node.jsをMacにインストール！（Homebrew→Nodebrew→Node.js順にインストール）](http://mmorley.hatenablog.com/entry/2016/11/22/233034)

## gulpのインストール(グローバル)
```
$ sudo npm install -g gulp
```
パスワードを入力してバージョンの確認

```
$ gulp -v
```

```
CLI version 2.1.0
Local version 4.0.0
```

できてた(⌒▽⌒)

## package.jsonの作成
```
$ npm init
```
一旦全部yesで進めた

```
package name: (gulp-test)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
```

## gulpのインストール(プロジェクト内)

```
$ sudo npm i -D gulp
```

実行してみる

```
$ gulp
```

```
Error: Cannot find module 'gulp-sass'
```

モジュールがないって怒られた。

```
sudo npm install --save-dev gulp-sass@2
```

入れた！！！
もう一回実行してみる

```
AssertionError [ERR_ASSERTION]: Task function must be specified
```

エラーが出た。
調べてみるとgulpのバージョン4で変更点があるらしい

[gulp v4.0.0がプレリリース！ 移行方法と変更点まとめ](https://satoyan419.com/gulp-v4/)

ここに詳しく書いてあった:relaxed:
```gulpfile.js```の記法がバージョン3の時の書き方だったからエラーが起きたみたい。
一旦、gulpのバージョンを```3.9.1```に下げてみた。

```
$ sudo npm install --save-dev gulp@3.9.1
```

実行してみた。

```
$ gulp
```

gulp動いた＼(^o^)／


以上、メモでした。


## 追記(2019/10/07)
5月末にgulp4にアップデートしたよ。(超今更)
また自分用のメモがてら、(多分)更新します。
[Unity] Assetsのインポート、問題点と修正方法

#Assetとは

アセットは、ゲームやプロジェクトで使用できるアイテムの表現です。アセットは、3Dモデル、オーディオファイル、イメージ、またはUnityがサポートする他の種類のファイルなど、Unityの外部で作成されたファイルから取得できます。
以下Unityのアセットのエクステンション

- ３Dモデル：..fbx, .dae, .3DS, .dfx, .obj
- サウンド: mp3, wav, .ogg, .aiff, .mod, .it, .s3m, .xm
- 2Dイメージ：.bmp,  .exr, .gif, .hdr, .iff, .jpg, .pict, .png, .psd, .tga, .tiff
- フォント

#Assetのインポートする方
AssetをUnityプロジェクトにインポートする方法は2つあります。

##直接
1. プロジェクトにAssetを直接にインポートする。
- UnityプロジェクトにAssetメニューを選んで、Import New Asset/Import Packageクリックして。
- Asset/Packageを選びます
Unityは自動的にすべてのファイルを読み、そのファイルをUnityプロジェクトに入れます

2. AssetのフォルダーのUnityに直接にコピーする。

##Assetストアーからインポートする。
アセットストアには、Unity Technologiesとコミュニティのメンバーの両方によって作成された、無料で商業的なAssetのライブラリです。
- **Assetストア**ー場面をオープンして。
   ```Window > General >  Asset Store```
   UnityプロジェクトにUnityAsset Store Windowを表示された
- Asset Storeアカウントをログインします。
- Assetを探して、選んで、とダウンロードします。
- Asettをインポートします。

#問題点と修正方法
1. 問題
パッケージのインポートのエラー
このエラーは、パッケージのインポートに失敗したときに表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/293090/bc51d0de-1161-4dbf-ad46-6e2876d103ff.png)

2. 修正方法
- アセットストアに行きます。
- ダウンロードマネージャーのボタンをクリックして、ダウンロードしたリストファイルを表示された。
- Assetにダウンロードボタンして自動的にAssetをインポートします。
Vaporのルーティングについて

Vapor のルーティング周りについて詰まったことが多かったので、まとめてみました。
Vapor のルーティングは `routes.swift` に記述していきます。

#### 環境
この記事では以下の環境で動作を確認しています。

- swift 5.0
- vapor 3.3.0


#### 基本的なルーティング
```swift
// GET /user
router.get("user") { req in
    return "/user"
}
``` 

#### パラメータの型を指定（String）
```swift
// GET /onetime/:key
router.get("onetime",  String.parameter) { req -> String in
    let key = try req.parameters.next(String.self)
    return "/onetime/\(key)"
}
``` 

#### パラメータの型を指定（Int）
```swift
// GET /users/:userId
router.get("user",  Int.parameter) { req -> String in
    let userId = try req.parameters.next(Int.self)
    return "/user/\(userId)"
}
```

`/user/xxxx`のような `Int`に変換できないパラメータを渡すと以下のレスポンスが返ります。

```json
{
  "error": true,
  "reason": "The parameter was not convertible to an Int"
}
```

#### パラメータの後ろにエンドポイントを設定
```swift 
// GET /user/:userId/profile
router.get("user",  Int.parameter, "/profile") { req -> String in
    let userId = try req.parameters.next(Int.self)
    return "/user/\(userId)/profile"
}
``` 

#### 複数のパラメータ
```swift
// GET /user/:userId/post/:postId
router.get("user",  Int.parameter, "/post", Int.parameter) { req -> String in
    let userId = try req.parameters.next(Int.self)
    let postId = try req.parameters.next(Int.self)
    return "/user/\(userId)/post/\(postId)"
}
``` 


#### グループによるルーティング
```swift
// GET /api/v0/user
router.group("api") { api in
    api.group("v0") { v0 in
        v0.get("user") { v0 in
            return "/api/v0/user"
        }
    }
}
``` 




###参考
- [Vapor Routing](https://api.vapor.codes/routing/latest/Routing/index.html)
- [Introduction to Routing in Vapor 3, Part 1](https://www.vaporforums.io/viewThread/33)
- [Vaporのルーティングについて(基礎編)](https://qiita.com/SatoTakeshiX/items/33515c41ff600732b151)
- [Vaporのルーティングについて(応用編)](https://qiita.com/SatoTakeshiX/items/ca3134c153143dd57b86)
PythonでIBMの最適化ソルバ CPLEXを使う

最近研究で最適化ソルバを使う機会が増えたので，そのメモ
（英語を読むことが苦手なので，毎回英語で説明を読むくらいなら日本語で書いておくという気持ち）

間違えているところがあれば指摘していただけると幸いです．

>今回の記事では線形計画問題(LP)の解き方しか書かないが，CPLEXでは整数計画問題(IP), 混合整数計画問題(MIP), 凸二次計画問題(CQP), 凸二次制約つき凸二次計画問題(QCQP)など，様々な問題を解くことができる．

前提条件として，CPLEXはインストール済み，Pathも通してあるとする．
> 学生はAcademic版が無料で手に入る？

たとえば，以下の問題を解く時を考える：

```math
\min 3 x_1 + 24 x_2 + 13 x_3 \\
\text{ subject to }
\begin{cases}
110 x_1 + 205x_2 + 160 x_3 \geq 2000 \\
4 x_1 + 32 x_2 + 13 x_3 \geq 55 \\
x1, x2, x3 \geq 0
\end{cases}
```

$\min$の後ろを「目的関数」，subject to の後ろを「制約式」という．
目的関数が線形，制約式も線形なので，これは線形計画問題(Linear Programming, LP)とよばれる問題の一種．
>余談: この最適化問題が解をもつならば，双対定理より，双対ギャップ 0 で双対問題も解をもつことが知られている．

まずは，この問題をLPの標準形に直す．
LPの標準形は，以下の形で表される：

```math
\min \mathbf{c} \cdot  \mathbf{x}  \\
\text{subject to } 
\begin{cases}
\mathrm{A} \mathbf{x} \leq \mathbf{b}, \\
\mathbf{x} \geq \mathbf{0}
\end{cases}
```
ここで，$\mathrm{A} \in \mathbb{R}^{m \times n}, \mathbf{b} \in \mathbb{R}^{m}$は制約を行列の形で表したもので，不等号は各要素について成り立つという意味で用いられる：

```math
\forall i \in \{ 1, 2, .., m \},\\
(\mathrm{A} \mathbf{x})_i \leq b_i 
```
もともと解きたかった問題をこの形に直すと，

```math
\min \begin{bmatrix} 3 & 24 & 13 \end{bmatrix} 
\begin{bmatrix} x_1 \\ x_2 \\ x_3 \end{bmatrix} \\
\text{subject to }
\begin{cases}
\begin{bmatrix}
-110 & -205 & -160 \\
-4 & -32 & -13
\end{bmatrix}
\begin{bmatrix}
x_1 \\ x_2 \\ x_3
\end{bmatrix}
\leq
\begin{bmatrix}
-2000 \\ -55
\end{bmatrix} \\
x_1, x_2, x_3 \geq 0
\end{cases}
```

この式のうち，

```math
c = \begin{bmatrix} 3 & 24 & 13 \end{bmatrix}, 
\mathbf{x} = \begin{bmatrix} x_1 & x_2 & x_3 \end{bmatrix}, 
\mathrm{A} = \begin{bmatrix}
-110 & -205 & -160 \\
-4 & -32 & -13
\end{bmatrix}, 
\mathbf{b} = \begin{bmatrix} -2000 \\ -55 \end{bmatrix}
```
と置けば，LPの標準形になることがわかる．
この問題をIBMの最適化ソルバCPLEXを用いて解く．

> CPLEXを使う上で$ \mathrm{A} \mathbf{x} \leq \mathbf{b} $の形にする必要はないが，個人的にこの形が好きなのでこの形にした

```python
import cplex

# ときたい最適化問題の定数部分を行列，ベクトルに変形する
# min c x
# s.t. A x ≤ b
#      x ≥ 0

c = [3, 24, 13]
x =  ["x{}".format(i) for i in range(1, 4)] # ["x1", "x2", "x3"]
A = [[-110, -205, -160], \
     [-4, -32, -13]]
sense = ['L', 'L'] # Ax ≤ b の不等号部分の配列
                   # 'L' : (Ax)_i ≤ b_i のときに書く
                   # 'G' : (Ax)_i ≥ b_i のときに書く 
                   # 'E' : (Ax)_i = b_i のときに書く
b = [-2000, -55]

lb = [0, 0, 0] #x1, x2, x3 ≥ 0 という意味

# インスタンスを作る
# Problem(問題)の頭文字をとって P とした
P = cplex.Cplex()
P.objective.set_sense(P.objective.sense.minimize) # 最小化問題か最大化問題かを表す文
                                                  # 最大化ならP.objective.sense.maximize
P.set_problem_type(P.problem_type.LP) # 線形計画問題であるという文
P.variables.add(obj=c, lb=lb, names=x) # 目的関数，変数を追加

for i in range(len(A)):
    expr = cplex.SparsePair(ind=x, val=A[i])
    P.linear_constraints.add(lin_expr=expr, senses=sense[i], rhs=[b[I]]) # 線形制約を一つずつ追加

P.solve() # 最適化問題を解く
P.solution.get_values() # 最適値を表示
P.solution.get_objective_value() # 最適解 [x1, x2, x3] を表示
P.solution.get_dual_values() # 双対問題の最適解を表示

```

CPLEXではデフォルトで途中計算がコンソールに表示されるが，これをなくすには

```python

P.set_results_stream(results_file=None)
```
と書けば良い．

# おわりに
気が向いたり，要望があればQPを解くとき等の書き方ものせます．
Three.jsとシェーダー　〜実際に描画してみる〜

ドキュメントを読んでなんとなく雰囲気がわかってきたので実際に描画してみようと思います。

適当にカメラとシーンとライトを用意して、三角形のポリゴンを描画してみたいと思います。
カメラとかシーンの準備は割愛してジオミトリとマテリアルを用意するところだけになります。

まずはジオミトリの準備。

```.js
function geo(){
 let g = new THREE.BufferGeometry();
 let vert = new Float32Array([
    1.0,0.0,0.0,
    0.0,1.0,0.0,
    0.0,0.0,1.0 
 ])
 g.addAttribute('position',new THREE.BufferAttribute(vert,3))
 return g;
}
```

関数化してあるのはいじるときに見やすくしやすかったからです。
自作シェーダーを使うためにはBufferGeometryを使用することになります。
また、BufferGeometryにattribute(頂点ごとに異なった値を持つデータ)を追加するときにはaddAttributeメソッドを使う必要が出てくるので使用しています。

次にShaderの方です。

```.js
let shade_par={
    uniforms:{
        "time":{value:1.0}
    },
    vertexShader:[
        "precision mediump float;",
        "void main(){",
        "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
        "}"

    ].join("\n"),
    fragmentShader:[
        "precision mediump float;",
        "void main(){",
        "gl_FragColor = vec4(0.0,1.0,0.0,1.0);",
        "}"

    ].join("\n"),
    side: THREE.DoubleSide,
    transparent: true
}
```

uniformsにtimeをなんとなく渡していますが今回は使っていません(そのうち時間変化とかをさせようと思っています。)
今回は特に処理はせず、色を緑にする処理だけしています。

#できたもの

<img width="910" alt="スクリーンショット 2019-04-07 20.53.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/244678/9d437cd8-0d3a-99fe-20a4-ab42c5410dec.png">


予想通りの結果です。基礎はこれでなんとか確認できたので次は時間で見た目を変えたり座標によるグラデーションを試したりしたいと思います。
[ポエム]　書いた通りに動いているぜ☆（＾～＾）

```
{何か}
```

こうなることを期待して

```C#
var content = "何か";
content = string.Join("{", content, "}");
```

カタカタ　タン。

```
何か{}
```

２時間３０分ぐらい考えていたが

```C#
var content = "何か";
content = string.Concat("{", content, "}");
```

今さっき　気づいた。
FastAPIでPOSTされたJSONのレスポンスbodyを受け取る

# はじめに
FastAPIはPOSTやPUTで簡単にクエリを受け取ることができるのですが、
Bodyを受け取るとき、どうやってやるんだろうと疑問に思ったので、
メモとして残したいと思います。

# やりたいこと
連想配列のような、シンプルなBodyはもちろん、
一気にデータをMySQLに流したいときなど、
配列に連想配列が入っているようなBodyをよく扱うので
今回は、この２つをPOSTで受け取ることを目標にします。

- シンプルなJSONデータ

```json
{
  "user_id": 1,
  "name": "太郎"
}
```


- ネストされたJSONデータ

```json
[
  {
    "user_id": 1,
    "name": "太郎"
  },
  {
    "user_id": 2,
    "name": "次郎"
  }
]
```

# 実装

```main.py
from fastapi import FastAPI
from pydantic import BaseModel  # リクエストbodyを定義するために必要
from typing import List  # ネストされたBodyを定義するために必要

app = FastAPI()


# リクエストbodyを定義
class User(BaseModel):
    user_id: int
    name: str


# シンプルなJSON Bodyの受け取り
@app.post("/user/")
# 上で定義したUserモデルのリクエストbodyをuserで受け取る
# user = {"user_id": 1, "name": "太郎"}
def create_user(user: User):
    # レスポンスbody
    return {"res": "ok", "ID": user.user_id, "名前": user.name}


# ネストされたJSON Bodyの受け取り
@app.post("/users/")
# 上で定義したUserモデルのリクエストbodyをリストに入れた形で受け取る
# users = [{"user_id": 1, "name": "太郎"},{"user_id": 2, "name": "次郎"}]
def create_users(users: List[User]):
    new_users = []
    for user in users:
        new_users.append({"res": "ok", "ID": user.user_id, "名前": user.name})
    # 整形したデータをレスポンスbodyを送信
    return new_users

```

### 実行

```bash
$ uvicorn main:app
```

### ドキュメントにアクセスしてみる
http://localhost:8000/docs

#### シンプルな方
![Screenshot from 2019-04-07 20-02-41.png](https://qiita-image-store.s3.amazonaws.com/0/130670/c0f5704e-39db-3de6-c8d4-7f828227839a.png)

#### ネストした方
![Screenshot from 2019-04-07 20-34-38.png](https://qiita-image-store.s3.amazonaws.com/0/130670/f5c884aa-49e3-efba-3ea1-4de825b31487.png)


定義した、UserモデルがBodyの雛形として記載されているので、
試しに、valueを編集して実行してみましょう。

### 実行結果

#### シンプルな方
![Screenshot from 2019-04-07 20-14-43.png](https://qiita-image-store.s3.amazonaws.com/0/130670/bec74f7b-293c-d4a8-c07f-d9776204c74d.png)

#### ネストした方
![Screenshot from 2019-04-07 20-38-32.png](https://qiita-image-store.s3.amazonaws.com/0/130670/a33946f0-c48c-5b08-ef8c-f5ec05cf357d.png)


期待したとおりの結果が返ってきていると思います。

# おわりに
モデルを定義するだけで、Swaggerの方にも反映されることに驚きました。
また、モデルにモデルを入れるような複雑なこともできるようなので、
結構柔軟にいろいろできそうです。


# 参考にしたサイト
ほぼほぼ公式を参考にしました。
> https://fastapi.tiangolo.com/tutorial/body/
Oracle Java Bronzeに合格したので、試験の概要とかをまとめてみた。

こんにちは。
18卒SEのむらたゆうこと申します。

そんなやつが最近、
「Oracle Java Bronze」という資格に合格いたしました。
以下、Oracle Java Bronzeを受験して感じたことを書きなぐります。

# 試験概要
Oracle認定Javaプログラマ試験(Oracle Certified Java Programmer)という資格の1つです。
その資格はJavaの開発元であるOracle社が運営しており、
基礎的なものから、「Bronze(今回取得したもの)」「Silver」「Gold」に試験区分が分かれています。
　
Bronzeの詳細は、以下のとおりです。　
試験時間　：65分
出題数　　：60問
出題形式　：CBT(選択問題)
合格ライン：60%

もっと知りたい方は、このサイトがおすすめかもしれません。
URL：https://aithii.com/2018/12/15/post-1144/

#私のスペック
18卒 新卒で中堅SIerに開発系SEとして入社いたしました。
プログラミング経験がわずかにある文系です。
実務でJavaは触ったことはありません。

#受験の理由
全体の技術研修では業務に直接関係のない技術を学習しており、長期間プログラミングから遠ざかっていたためです。
※弊社が開発系を主業務としていないかららしいです。
また、内定辞退先のSIerから入社前に
「Oracle Java Bronze」と「ITパスポート試験(昨年に合格済)」を取得するようにという話があり、
興味本位で受けてみたいという願望があったためです。

#勉強日数等
実質1ヶ月
　→平日：1～3時間
　→休日：2～5時間
※私の場合、平日のほうが
モチベーションが上がるので、
出社前、出社後に
勉強することがよくありました。

#勉強方法
この試験に関しては過去問の内容がそのまま試験に出るため、過去問中心に勉強を進めました。
→実試験でも、過去問の内容が出てきたので、この勉強法でよかったと思います。

###重要事項の学習
最初は[2週間でJava SE Bronze の基礎が学べる本 (徹底攻略)](https://book.impress.co.jp/books/1116101147)で重要事項を学習しました。
　→その後過去問を解いた際に解けないものが多かったので、過去問中心の勉強方法に方向変換をしました。


###過去問演習[初期段階]
[徹底攻略 Java SE 7/8 Bronze 問題集 ［1Z0-814］対応](https://book.impress.co.jp/books/1114101134)、所謂「黒本」で過去問を解きました。
間違えた場所は復習し、過去問の答えが「なぜそうなったのか」というのを頭で理解しました。
　→黒本の解説を読んで分からなかった場所は、インターネットで調べたり
実際にコードを書いて「どのように動いているのか」ということを理解しました。

###過去問演習[直前]
苦手な部分を中心的に学習しました。(私の場合は「オブジェクト指向」全般でした。)
  →このころから、黒本に直接解き方を書き、暇なときに眺めて理解するように努めました。

#試験結果
7割弱で合格しました。
※覚えるのが速かったり、元からJavaの知識があったりする方なら1月で8～9割はいけるかもしれないですね。

#所感
Oracle Java Bronzeから受けてよかったです。
ネット上では「Oracle Java Bronzeは無駄だから、(上位資格の)Silverから受けるべき」という意見もありますが、
私の場合はJavaの基礎知識が怪しかったため、まずはBronzeを受験しようと決めていました。
　
あと、受験したことにより前よりJavaのことが理解できた気がします。

#ここには注意
###試験の時間配分
試験時間が65分で、問題数が60問あります。
そのため、1分ほどで1問を解くぐらいのスピードを求められます。
私の場合、簡単な問題は即時に解くように心がけました。
その結果、本番では10分ほど時間が余りました。

###1番下のレベルだからってなめちゃいけないと思った
Bronzeの問題を解いた感想ですが、私自身は難しいと感じてしまいました。
Javaを学習サイトであるProgateやPaizaラーニングで学習していたことがありますが、
それで一通り学習しても太刀打ちできないレベルだと思いました。
※逆に、試験勉強中にPaizaラーニングの演習問題を解いてみたことがあるのですが、
そこではすらすらと解けたので、とてもうれしかったです。

###受験の申し込みがややこしい
受験の申し込みは以下のサイトが分かりやすいと思います。
URL：https://csmajors.net/how-to-apply-for-oracle-certified-programmer-exam/

このように、試験を運営しているOracle社と
実際に試験を受ける場を提供するピアソンVUE社の手続きが必要でしたので、
ちょっとややこしかったなというのが本音です。
　
####これは私自身の話です...。
また、受験料の支払いでは「クレジット払い」が基本なのですが、
私の場合は、会社側からクレジット払いは許可されておらず、
「バウチャーの購入」と「銀行振込」、「現地で現金払い」の3つしかできませんでした。
支払いの詳細は以下のとおり。
URL：https://www.pearsonvue.co.jp/test-taker/Tutorial/Payment.aspx

私自身は、一番シンプルそうな「現地で現金払い」という方法を選択しましたが、
限られた場所しかないので、あまりお勧めできません。
(私が調べたところ、東京都・神奈川県・愛知県・福岡県しかありませんでした。)
URL：https://www.pearsonvue.co.jp/Documents/Japan-Downloads/TC_List/pvue_jp_TC_all.aspx
※上記のURLでは、現金払いできる会場も掲載されています。

#最後に
まだ私自身未熟な部分があるので
今年中に上位資格である、Oracle Java Silverを取りたいです。
KNPを利用して述語項構造を抽出

#概要

京大黒橋河原研究室による[係り受け解析エンジンKNP](http://nlp.ist.i.kyoto-u.ac.jp/index.php?KNP)。非常に情報量の多い結果が出力されるのが特徴だが、今日はそれを使って述語項構造を抽出することを試みた。

# pyknp を使用して述語項構造を抽出してみる
```python
import re
from pyknp import KNP


def analyze_pas(sentence):
    knp = KNP(option = '-tab -anaphora', jumanpp=False)
    result = knp.parse(sentence)
    for b in  result.bnst_list():
        match = re.search(r"<項構造:(.+)>", b.spec())
        if match:
            pas =  match.group(1)
            items = pas.split(":")
            print(b.bnst_id, items)
```

[Jupyter Notebook(Github)](
https://github.com/elm200/jupyter-notebooks/blob/master/nlp/notebooks/20190407_KNP_01_predicate_argument_structure.ipynb)

# 結果

```
sentence = '今日太郎は昨日花子が読んでいた本を次郎に渡した'
analyze_pas(sentence)

4 ['読む/よむ', '動2', 'ヲ/N/本/5;時間/C/昨日/2;ガ/C/花子/3']
5 ['本/ほん', '名1', 'ノ/O/太郎/1']
7 ['渡す/わたす', '動2', '時間/C/今日/0;ガ/N/太郎/1;ヲ/C/本/5;ニ/C/次郎/6']
```

```
sentence = "昨日私が彼を駅まで迎えに行ったとき、小雨が降っていた"
analyze_pas(sentence)

3 ['駅/えき', '名1']
4 ['迎える/むかえる', '動3', 'ガ/O/私/1;ヲ/O/彼/2']
5 ['行く/いく', '動9', '外の関係/N/とき/6;ガ/C/私/1;ヲ/C/彼/2;マデ/C/駅/3']
8 ['降る/ふる', '動1', '時間/C/昨日/0;ガ/C/小雨/7']
```

```
sentence = "非常に情報量の多い結果が出力されるのが特徴だが、今日はそれを使って述語項構造を抽出することを試みた"
analyze_pas(sentence)

0 ['非常だ/ひじょうだ', '形1']
1 ['情報/じょうほう+量/りょう', '名1']
2 ['多い/おおい', '形11', '外の関係/N/結果/4;修飾/C/非常に/0;ガ/N/情報量/2']
5 ['特徴/とくちょう', '判2', 'ガ/C/の/6']
8 ['使う/つかう', '動3', 'ヲ/C/それ/9']
10 ['抽出/ちゅうしゅつ', '動2', '外の関係/N/こと/15;ヲ/C/述語項構造/13']
12 ['試みる/こころみる', '動2', '時間/N/今日/8;ヲ/C/こと/15']
```
# 感想

短い文章に関しては、綺麗に述語項構造が抽出できた。ただ、長い文章になると、単純な項構造の切り出しだけだと、文節が分かれることで意味が取りづらい（例：3番目の例の文節10と文節12)こともあるようだ。引き続きいろいろ調べてみようと思う。
Vue CLI のサンプル（カウンター）

こちらと同じプログラムを vue-cli で書いてみました。
[vue.js のサンプル　(button クリック)](https://qiita.com/ekzemplaro/items/10b115c869308517974d)

![counter_apr0701.png](https://qiita-image-store.s3.amazonaws.com/0/179446/2551f958-0877-7d4b-cc11-4156f9b9c41e.png)

```vue:src/App.vue
<template>
<div>
<button @click="green()">Green</button> {{counter_green}}<p />
<button @click="yellow()">Yellow</button> {{counter_yellow}}<p />
<button @click="red()">Red</button> {{counter_red}}<p />
<p />
<button @click="clear()">Clear</button><p />
Apr/7/2019<p />
</div>
</template>

<script>
export default {
  data () {
    return {
	counter_green: 0,
	counter_yellow: 0,
	counter_red: 0,
    }
  },
  methods: {
    green () {
      this.counter_green += 1
    },
    yellow () {
      this.counter_yellow += 1
    },
    red () {
      this.counter_red += 1
    },
    clear () {
      this.counter_green = 0
      this.counter_yellow = 0
      this.counter_red = 0
    },
  }
}
</script>
```

src/App.vue の使い方はこちら
[Vue CLI の簡単な使い方](https://qiita.com/ekzemplaro/items/73f5bf76ef4912b7a0ea)
PDOでSQLite3と接続すると、「could not find driver」と表示されるときに確認したこと

# 環境
- Windows 10
- PHP 7.2.11
- Apache 2.4.39
- SQLite 3.27.2

# 現象
1. PDO を使ってデータベースに接続、データを取得する処理を記述
2. ブラウザから該当ファイルにアクセスすると、_could not find driver_ と表示される

# 原因
パスが間違っていました...

# やったこと
### 1.事前に
アプリケーションから SQLite を利用するためには sqlite3.dll を利用しなければならないようなので、サイトからダウンロードしてきて _C:¥Windows¥System32_ に配置しました。
さらに、_php.ini_ の下記の記述のコメントアウトを外して有効化しました。(なければ追記)

```php.ini
extension=php_pdo.dll
extension=php_sqlite.dll
```
そしてブラウザからアクセスすると、_could not find driver_ (ドライバが見つからない)と言われてしまうのでした。

### 2._phpinfo_ を確認
以下のように、 _PDO drivers_ が _no value_ となっています。
![キャプチャ1.PNG](https://qiita-image-store.s3.amazonaws.com/0/191037/eb923ad5-7cd3-7487-695f-f2f8d752c088.png)

### 3._extension_dir_ を絶対パスにする
_extension_ フォルダの指定を絶対パスにすると、拡張モジュールをきちんと読み込んでくれるっぽいので、

```php.ini
extension_dir = "ext"
```
を

```php.ini
extension_dir = "C:/php-7.2.11/ext"
```
と修正したが、現状は変わらず。

### 4.再度 _phpinfo_ を確認
記載されている _extension_dir_ のパスが、先ほど指定したものと違うことに気づく。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/191037/5448b83f-47a3-c0a0-26eb-3f14f9b1a939.png)
本当は _C:/php-7.2.11/ext_ を参照してほしいのだが、_C:/php/ext_ を参照している。(_C:/php/ext_ というフォルダは存在しない)

### 5._httpd.conf_ を確認
どこかに _C:/php/ext_ を参照する、という記述があるはず。
調査してみると、_Apache_ の設定ファイルに以下の記述を発見。

```httpd.conf
PHPIniDir "C:/php"
```
これを以下に変更。

```httpd.conf
PHPIniDir "C:\php-7.2.11\ext"
```
### 6._Apache_ を再起動
再起動すると、変更したパスがきちんと反映され、ドライバも表示 (SQLiteが追加)されている。
![キャプチャ3.PNG](https://qiita-image-store.s3.amazonaws.com/0/191037/e58d9570-4b9e-377c-7761-78b8a0c556f3.png)
![キャプチャ4.PNG](https://qiita-image-store.s3.amazonaws.com/0/191037/d1b41607-197d-2df6-ce4a-ae26cc067439.png)

最初は「php」というフォルダ名でインストールしたが、後から「php-7.2.11」と名前を変更した微かな記憶がよみがえる...


# 最後に
エンジニア歴1年の初心者が、初心者の方の出助けになればと思い、記事を書いています。
間違いがあれば、忌憚なくご指摘いただけると嬉しいです。

# 参考
- [sqlite3.dllのダウンロード](https://www.dbonline.jp/sqlite/install/index3.html)
- [インストール手順](https://www.php.net/manual/ja/sqlite.installation.php)
- [Windows版PHPでPDOを有効にする](http://kashi.way-nifty.com/jalan/2015/07/windowsphppdo-4.html)
- [「PHPINIDir」でphp.iniのパスを指定](https://www.deep-blog.jp/engineer/archives/4132/)
git logをjson形式で吐き出させるCLI


```
git log -1 --pretty=format:'{%n  "commit": "%H",%n  "abbreviated_commit": "%h",%n  "refs": "%D",%n  "subject": "%s",%n  "author": {%n    "name": "%aN",%n    "email": "%aE",%n    "date": "%aD"%n  },%n  "commiter": {%n    "name": "%cN",%n    "email": "%cE",%n    "date": "%cD"%n  }%n},'
```

`-1`を消すとgit logの分だけ出てくる。

これはhttps://gist.github.com/varemenos/e95c2e098e657c7688fd のcliをちょっとスリムにしたやつ。もっと情報だせるみたいなのでそれはリンク先を参照。
NVIDIA Jetson Nano 開発者キットで X11 フォワーディングを利用する

# Jetson Nano で動作する GUI アプリケーションを Windows に表示する
Jetson Nano 開発者キットにディスプレイ、キーボード、マウスを接続すれば Ubuntu ベースのデスクトップ環境がかなり快適に利用できるので、Windows 上に Jetson Nano の GUI を表示する必要性は比較的少ないと思います。それでもやっぱり使い慣れた Windows から Jetson Nano を操作できるのはプログラミングのときなどに便利です。

## Windows 用 X サーバのインストール
まず、Windows 側に X サーバ・ソフトウェアが必要です。複数の選択肢があると思いますが、私は [VcXsrv](https://sourceforge.net/projects/vcxsrv/) を利用させていただきました。

## Windows から Jetson Nano へ SSH でログイン
Windows から SSH でログインするためのソフトウェアも必要です。これも複数の選択肢がありますが、私は [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/index.html) を利用させていただきました。
SSH で Jetson Nano の IP アドレスを指定してログインします。私はネットワーク・ルータの設定によっていつも同じ IP アドレスが Jetson Nano に割り当てられるようにしています。
PuTTY を使う場合は **SSH -> X11** 設定で **Enable X11 forwarding** をチェックします。

## 表示先の設定
SSH で Window から Jetson Nano へログインしたら **DISPLAY** 環境変数を以下のように設定します。[^1]

```
$ export DISPLAY=:10
```

## 動作確認
動作確認してみます。Windows 上に X サーバが起動している必要があります。

```
$ xcalc&
```

![x11fwd.png](https://qiita-image-store.s3.amazonaws.com/0/384208/8430f3e6-ebe5-7bd9-aa44-bf283d8a56ff.png)


# Windows から Jetson Nano 上の GUI アプリケーションを起動する
上記と同じく Windows から Jetson Nano 上の GUI アプリケーションを起動しますが表示は Jetson Nano に接続されたディスプレイからというときの表示先設定は以下のとおりです。

```
export DISPLAY=:0
```

![x11fwd2.png](https://qiita-image-store.s3.amazonaws.com/0/384208/1696bd20-d7be-7d6b-f62f-7ef06b71913d.png)

# Jetson Nano と Windows の間でファイル転送
Jetson Nano と Windows の間でファイル転送ができるととても便利です。この用途では [WinSCP](https://winscp.net/eng/index.php) が有名です。

![winscp.png](https://qiita-image-store.s3.amazonaws.com/0/384208/0b1b0bb4-3c73-aa63-2fda-d7e4b8dd2f74.png)

以上です。

[^1]: [NVIDIA Developer Forum : "remote desktop control if jetson tx2"](https://devtalk.nvidia.com/default/topic/1021756/jetson-tx2/remote-desktop-control-if-jetson-tx2/post/5200395/#5200395)
きれいな四角


座標を二倍した上で、四角形をなぞっています。
申し訳程度にstd::futureによる並列化を図っています。
OpenMPよりもreductionしやすいですね。

```cpp:tyama_henae32.cpp
//http://nabetani.sakura.ne.jp/hena/orde32rects/
//https://qiita.com/Nabetani/items/bd16f3fa1d9e4d0d60ae

#include <iostream>
#include <string>
#include <set>
#include <vector>
#include <future>
#include <cstdio>
using namespace std;

const int B=36;

set<int> split_int(string &str, const char *delim){
	set<int> result;
	int cutAt;
	while( (cutAt = str.find_first_of(delim)) != str.npos ){
		if(cutAt > 0){
			result.insert(strtol(str.substr(0, cutAt).c_str(),NULL,B));
		}
		str = str.substr(cutAt + 1);
	}
	if(str.length() > 0){
		result.insert(strtol(str.c_str(),NULL,B));
	}
	return result;
}

int f(const vector<vector<int>> &v,int y1,int x1,int y2,int x2){
	for(int i=x1;i<=x2;i++)if(!v[y1][i])return 0;
	for(int i=x1;i<=x2;i++)if(!v[y2][i])return 0;
	for(int i=y1;i<=y2;i++)if(!v[i][x1])return 0;
	for(int i=y1;i<=y2;i++)if(!v[i][x2])return 0;
	for(int j=y1+1;j<=y2-1;j++)for(int i=x1+1;i<=x2-1;i++)if(v[j][i])return 0;
	//printf("%d %d %d %d %d\n",x1/2,y1/2,x2/2,y2/2,(y2-y1)/2*(x2-x1)/2);
	return (y2-y1)/2*(x2-x1)/2;
}

int main(){
	string line;
	for(;getline(cin,line);){
		vector<vector<int>>v(2*B-1);
		for(auto &e:v)e.resize(2*B-1);
		set<int>a=split_int(line,"/");
		for(auto &e:a){
			int l=e/B/B/B*2;
			int t=e/B/B%B*2;
			int r=e/B%B*2;
			int d=e%B*2;
			for(int i=l;i<=r;i++)v[t][i]=1;
			for(int i=l;i<=r;i++)v[d][i]=1;
			for(int i=t;i<=d;i++)v[i][l]=1;
			for(int i=t;i<=d;i++)v[i][r]=1;
		}

		// 全部のスレッドに均等に処理を与えられない以上、スレッド数は適当に増やしたほうが良いか？
		int num_threads=thread::hardware_concurrency(); //*2;
		auto g=[&](int start)->multiset<int>{
			multiset<int> se;
			for(int y1=start*2;y1<=2*B-4;y1+=2*num_threads)for(int y2=y1+2;y2<=2*B-2;y2+=2){
				for(int x1=0;x1<=2*B-4;x1+=2)for(int x2=x1+2;x2<=2*B-2;x2+=2){
					if(v[y1][x1] && v[y1+1][x1] && v[y1][x1+1] && v[y2][x2] && v[y2-1][x2] && v[y2][x2-1]){
						int r=f(v,y1,x1,y2,x2);if(r)se.insert(r);
					}
				}
			}
			return se;
		};

		vector<future<multiset<int>>>task;
		for(int i=1;i<num_threads;i++)task.push_back(async(launch::async,g,i));
		multiset<int>se=g(0);
		for(auto &t:task)for(auto &e:t.get())se.insert(e);
		bool first=true;
		for(auto &e:se){
			if(!first)putchar(',');
			first=false;
			printf("%d",e);
		}
		puts("");
		fflush(stdout);
	}
}
```
AWS_REGIONとAWS_DEFAULT_REGION

Lambdaでは、実行されるリージョンが`AWS_REGION`という環境変数に入っていると、公式ドキュメントに書かれています。

![Lambda環境変数.png](https://qiita-image-store.s3.amazonaws.com/0/269194/9c9214de-e333-9bd0-f2f6-971faa81ce87.png)

一方、AWS SDKでは`AWS_DEFAULT_REGION`という環境変数にリージョンを設定してくれると、`~./aws/config`よりも優先して読み込んでClientやResourceを作成します。

```python:AWS_DEFAULT_REGIONの場合
import os
import boto3

os.environ['AWS_DEFAULT_REGION'] = 'ap-northeast-1'
dynamodb = boto3.resource('dynamodb')
```

`AWS_REGION`だとエラーになります。

```python:AWS_REGIONの場合
import os
import boto3

os.environ['AWS_REGION'] = 'ap-northeast-1'
dynamodb = boto3.resource('dynamodb')
```

```console:コンソール出力
botocore.exceptions.NoRegionError: You must specify a region.
```

でも、LambdaでClientやResourceを作成する時にリージョンを指定しなくてもエラーにはなりませんよね。何故か？

```python:lambda_function.py
import os
import boto3

def lambda_handler(event, context):
    print('AWS_REGION = {}'.format(os.getenv('AWS_REGION')))
    print('AWS_DEFAULT_REGION = {}'.format(os.getenv('AWS_DEFAULT_REGION')))
```

```console:ログ出力
AWS_REGION = ap-northeast-1
AWS_DEFAULT_REGION = ap-northeast-1
```

実は`AWS_DEFAULT_REGION`にもリージョンが入っているようです。なーんだ！
プログラミング学習記録50〜インプットしなくてもアウトプットできる状態が理想〜

##今日やったこと
- Progate React1

今日は昨日思った通り、燃え尽きた感が強く、あまりプログラミング学習に集中することができませんでした。

ただ、100DaysOfCodeは最低でもやり続けるつもりなので、何か1つはやらないとなということで、ProgateのReactをやってみました。

この前確認した時にReact1しか出てなかったのですが、今日見たらReact2も出ていました。
明日やってみようと思います。

Reactには今日初めて触れたのですが、「HTMLと同じように書けて、JavaScriptも埋め込める」というところだけは理解できました。
便利そうです。

さらっと１周してRailsのアプリと同じようにまた何か作りたいですね。

Udemyの講座が値下がりしていないので、それまではReactの基礎学習をするかRuby、Railsの学習を深めるかのどっちかですね。

まだプログラミング初心者ではありますが、プログラミング始めたばかりの人には話せることもあるので、そういう人達向けの情報発信をどんどんやっていきたいです。

行動する→成功or失敗する→成功しても失敗しても次挑戦する人がちょっとでも楽に挑戦できるように情報発信する→行動する→…
の循環がまだまだなので、この流れを速くしていきたいです。

定期的に自分のやっていることが本当にこれでいいのか？と不安になってしまう癖が抜けないので、自分と向き合う（自分会議）をしっかりやりながら進んでいこうと思います。

あと、部屋も散らかっていると行動に迷いが生じることがわかったので、迷いを減らすためにも部屋の片付けは徹底して毎日やっていかなければダメだなと思いました。

今週の一週間は燃え尽きから戻ってくるのが課題になりそうですが、明日からも引き続きプログラミング学習頑張ります。

おわり
ポートフォリオ公開テスト

# ポートフォリオ公開
Github Pagesを使用してポートフォリオ公開しました。

https://h4n24w4.github.io/portfolio/

あまり作成に時間をかけたくはなかったので、以下のサイトからテンプレートをお借りしました。
> ポートフォリオHTMLテンプレート
https://webdesigner-go.com/template/portfolio/

全体的なデザインなどほぼ変えていないのと、自己紹介やスキル記載部分などがまだ荒いので
しばらく更新かけていく予定です。
レスポンシブデザイン対応させるの忘れていたので今後やらなきゃ...

# [参考] Github Pagesについて
https://pages.github.com
リーダブルコード:第1部 表面上の改善

## 1章　理解しやすいコード

コードを書く上で一番大切な原則。
> コードは理解しやすくなければならない。

読みやすさの基本定理
> コードは他の人が最短距離で理解できるように書かなければいけない。

## 2章　名前に情報を詰め込む

- 明確な単語を選ぶ
    - 悪い例) getPage(), int Size(), Stop()
    - 良い例) FetchPage(), Height(), Kill()  

- 名前に情報を追加する
    - 悪い例) int delay, int size, float limit, float angle
    - 良い例) int delay_secs, int size_mb, float max_kbps, float degrees_cw

- 不要な単語を投げ捨てる
    - 例) ConvertToString() → ToString()
    - 例) DoServeLoop() →　ServeLoop()

## 3章　誤解されない名前

> 名前が「他の意味と間違えられることはないだろうか？」と何度も自問自答する。

- 曖昧な言葉を避ける
    - 悪い例) `results =Database.all_objects.filter("year <= 2011")`
    - 良い例) 選択する場合は select(), 除外する場合は exclude()

- 限界値を含めるときは max_ と min_ を使う
    - 悪い例) CART_TOO_BIG_LIMIT = 10
    - 良い例) MAX_ITEMS_IN_CART =10　

## 4章　美しさ
> ３つの原則
> ・読み手が慣れているパターンと一貫性のあるレイアウトを使う
> ・似ているコードは似ているように見せる
> ・関連するコードはまとめてブロックする

## 5章　コメントすべきことを知る
> コメントの目的は書き手の意図を読み手に知らせることである。

- コメントするべきでは「ない」ことを知る
 
``` 悪い例.txt
//このAccountからprofitを返す
double GetProfit();
```
- 自分の考えを記録する

| 記法 | 典型的な意味 |
|:----|:------------|
| TODO:  | あとで手をつける       |
| FIXME: | 既知の不具合があるコード |
| HACK:  | あまりキレイじゃない解決策 |
| XXX:   | 危険！大きな問題がある |
- 質問されそうなことを想像する

## 6章　コメントは正確で簡潔に

- 曖昧な代名詞を避ける
    - 悪い例) それ、これ
    - 良い例) データ、キャッシュ　
- 歯切れの悪い文章を磨く
- 関数の動作を正確に記述する

```
//　このファイルに含まれる行数を返す
int CountLines(string filename){ ... }

//　このファイルに含まれる改行文字('¥n')を数える
int CountLines(string filename){ ... }
```
LayerMaskに存在するGameObjectを取得する[Unity脱初心者への道]

親子で結んだり共通のTagを持っているGameObjectは簡単にScene中から探し出せますが、Layerに属するGameObjectを見つけてくるものが探しても無かったので、作ってみました。

#LayerMaskでGameObjectを探す

最初にScriptを出すと、こういう感じです。

```Csharp
    public static GameObject[] FindGameObjectsWithLayerMask(LayerMask layerMask)
    {
        GameObject[] goArray = GameObject.FindObjectsOfType<GameObject>();
        List<GameObject> goList = new List<GameObject>();
        foreach (GameObject go in goArray) {
            // LayerMask bit check
            if (((1 << go.layer) & layerMask.value) != 0) {
                goList.Add(go);
            }
        }
        if (goList.Count == 0) {
            return null;
        }
        return goList.ToArray();
    }

```

## 探す方法の解説

1.　とりあえず、Findで先ず、全てのGameObjectを拾ってきます
2.　その中で、LayerがLayerMaskでビットが立っているかを確認します
3.　立っていたGameObjectをListに突っ込みます
4.　発見が出来なくてListが空なら`null`、発見が出来でListの要素があったら配列にして返します。

## LayerMaskの解説

###`GameObject.layer`はint型
単純な整数型になっていて、どのLayerか一つ、指定されます。エディタの画面を見ると、こういう感じです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/72979/8b3d6378-9dec-21b1-9119-5b42773b2b5b.png)
例えばこの例では、`Player`を指定していると、`gameObject.layer=13`になります。

参考：[UnityリファレンスGameObject.layer
https://docs.unity3d.com/jp/current/ScriptReference/GameObject-layer.html]( https://docs.unity3d.com/jp/current/ScriptReference/GameObject-layer.html)

### `LayerMask`はビット列

それに対して、`LayerMask`は同じくint型なのですが、これの中で複数のLayerを指定できています。これはどういう仕組みなのかというと、
**右から数えたビット数のところが`1`のところが有効なLayer**

という仕組みです。例えば、上記の`Cover=8`と`Ground=10`が有効な場合は以下のようになります。

|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|0|0|0|0|0|1|0|1|0|0|0|0|0|0|0|0|

### 指定位置のビットが`1`かをみる方法

この仕組みを理解すると、シフト演算と論理積で確認ができます。

```csharp
if (((1 << go.layer) & layerMask.value) != 0)
```
の部分です。

- `1 << go.layer`で左シフトし、`LayerMask`の位置に合わせます。
- その値と論理積をとり、指定位置が`1`の場合は同じ値、`0`の場合は演算結果が`0`になります。

### 補足
これが簡単と思って実装していますが、今のC#なら`BitArray`を用いることも可能です。試してみた人はどうぞ！
やってない理由は、バイナリレベルで考えるとほぼ同じビット操作になるので、CPUリソースで差が無さそうと思ったからです。まあ、やってないので気になる方はどうぞｗ
Emacsのibufferでcounselを使ってibuffer-find-fileのようなことをする

# モチベーション

ibufferで`C-x C-f`すると、実は`find-file`ではなく`ibuffer-find-file`が呼び出されている。
これは普通の`find-file`と違い、ibufferの現在のカーソル位置のディレクトリで`find-file`をする。
たとえば、`~/project/test.c`の上にカーソルをおいて`ibuffer-find-file`すると、`~/project`を初期値として`find-file`が走る。

一方で、`counsel-find-file`という便利な関数がある。
これはcounselパッケージが持つ関数の1つで、counselの便利なUIと補完環境の上で`find-file`と同様のことができる。

そこで、ibufferの上で、しかもibufferでのカーソル位置のディレクトリを認識して`counsel-find-file`できると便利である。
これを行う関数を今回作った。

# コード

`use-package`を使っている。
使わない場合は、関数を抜き出して、`define-key`などで好きなキーバインドに設定すればよい。

```elisp
(use-package ibuffer
  :config
  ;; ibuffer-find-fileを使わずにcounselを使う
  (defun ibuffer-find-file-by-counsel ()
    "Like `counsel-find-file', but default to the directory of the buffer
at point."
    (interactive)
    (let ((default-directory
            (let ((buf (ibuffer-current-buffer)))
              (if (buffer-live-p buf)
                  (with-current-buffer buf
                    default-directory)
                default-directory))))
      (counsel-find-file default-directory)))
  :bind (("C-x C-b" . ibuffer)
         :map ibuffer-mode-map ("C-x C-f" . 'ibuffer-find-file-by-counsel)))
```

# 参照

- [Github - emacs/mirrorにおけるibuffer-find-fileの実装](https://github.com/emacs-mirror/emacs/blob/master/lisp/ibuffer.el#L1004)
Excel VBAプログラミング環境構築

# VBE(Visual Basic Editor)開き方からソース保存まで

##### 1.Excelのシートを右クリックし、コードの表示を選択する。
![Screen Shot 2019-04-07 at 18.38.22.png](https://qiita-image-store.s3.amazonaws.com/0/155403/4d7a0420-19e3-d7c6-e593-1f3b68eaaf5b.png)
##### 2.VBEの画面を表示し、VBA Projectプロジェクトを右クリックし、挿入選択する。
![Screen Shot 2019-04-07 at 18.42.11.png](https://qiita-image-store.s3.amazonaws.com/0/155403/9257e26e-2f52-ee27-6252-9241400c2c8f.png)
##### 3.右側のソース欄にソースを記載し、上書き保存する。
![Screen Shot 2019-04-07 at 18.43.34.png](https://qiita-image-store.s3.amazonaws.com/0/155403/564a022e-39ee-f645-6bac-6997692e3e01.png)
##### 4.ファイルの種類に「Excelマクロ有効ブック（＊.xlsm）」を選択し、保存する。
![Screen Shot 2019-04-07 at 18.44.17.png](https://qiita-image-store.s3.amazonaws.com/0/155403/b3145f95-3cdf-3866-38cc-4cccc57cee2f.png)

# VBE(Visual Basic Editor)ソース実行方法
##### 1.カーソルフォーカスをサププロシージャの間に移動し、実行ボタンを押下する。
![Screen Shot 2019-04-07 at 18.46.40.png](https://qiita-image-store.s3.amazonaws.com/0/155403/4da9b46d-6ac5-93f9-8b9e-7053301cfb7c.png)
##### 2.実行結果
![Screen Shot 2019-04-07 at 18.51.40.png](https://qiita-image-store.s3.amazonaws.com/0/155403/54950090-68d0-e429-bfee-276dd7ce4346.png)

# VBE(Visual Basic Editor)デバッグ方法
##### 1.ツール欄の空白位置に右クリックし、デバックを選択し、デバッグツール欄が表示する。
![Screen Shot 2019-04-07 at 18.52.19.png](https://qiita-image-store.s3.amazonaws.com/0/155403/8fcba348-d7da-4a84-e20b-83560aa7e745.png)
##### 2.デバック箇所にストックポイントをクリックし、実行ボタンを押下する。
![Screen Shot 2019-04-07 at 18.54.11.png](https://qiita-image-store.s3.amazonaws.com/0/155403/84adb94a-52e2-4bb7-844c-bf69bd5bc7e6.png)

#ボダンを追加方法
##### 1.開発タブを表示する。
![Parallels Picture1.png](https://qiita-image-store.s3.amazonaws.com/0/155403/aa4631ef-81c1-3919-b66b-daf682fe543a.png)
##### 2.Excelの開発タブから挿入を選択し、ボタンを選択する。
![Screen Shot 2019-04-07 at 18.55.06.png](https://qiita-image-store.s3.amazonaws.com/0/155403/30c50526-8993-187b-87c3-0b40a9566829.png)
##### 3.マクロの登録のパップアップ画面に「OK」を押下する。
![Screen Shot 2019-04-07 at 18.57.04.png](https://qiita-image-store.s3.amazonaws.com/0/155403/403e59ea-8cc5-8868-8b11-f86c330bd6d7.png)
##### 4.ボタン１を右クリックし、マクロの登録を選択する。
![Screen Shot 2019-04-07 at 18.57.57.png](https://qiita-image-store.s3.amazonaws.com/0/155403/a2cf5507-e1d6-8501-6f2e-5c9a507b0286.png)
##### 5.マクロの登録のパップアップ画面に紐付きマクロを選択し、「OK」を押下する。
![Screen Shot 2019-04-07 at 18.58.33.png](https://qiita-image-store.s3.amazonaws.com/0/155403/7d7ba282-954a-a0e3-8d53-beb1ab46272f.png)
GCPのCloud ShellでLaravel動かす際のメモ

#下準備

まずは、PHPをインストールしてHello Worldを出してみます。
https://console.cloud.google.com/cloudshell/editor?project=[プロジェクト名]
を開いて、下のターミナルを開きます。
ローカル（GCPと同じGoogleアカウントでログインしているブラウザ）で表示するまでのコードが下記。

```
$ git clone https://github.com/GoogleCloudPlatform/getting-started-php.git
$ cd getting-started-php/1-hello-world
$ composer install
$ php -S localhost:8000 -t web
```

下記のコマンドで、[project名]-appspot.comとしてデプロイできます。これで世界中の人がアクセスできるようになります。

```
$ gcloud app deploy
```

# Laravelをインストール
もうすでにPHP7.2が入っているので、あとはコマンドで階層を一番前にして、Laravelフレームワークを一式インストールするだけです。

```
$ cd
$ composer create-project laravel/laravel [project名]
$ cd [project名]
$ php artisan serve 
```
これで、

```
$ php -S localhost:8000 -t web
```
の時にでたURLをリロードすると、Laravelが起動されていると思います！
Amazon の商品URLをきれいにするAppleScript

## Amazon の商品URLをきれいに
Amazonで商品を表示するURLは、URLエンコードされた商品名や、アフェリエイト情報、参照情報などが付いていて、ものすごく長かったりしますね。
良い商品をみつけて、SNSなどで紹介しようとするときに、それらの邪魔な情報を消すのに手作業でテキストエディタなどで編集するなどしていました。

## きっかけ
シェルスクリプトマガジンが始めた連載「[シェルスクリプトを書いてみよう](https://shell-mag.com/rensai-shellscript1/)」の第1回のテーマ「[Amazonの商品ページURLをきれいにする](https://shell-mag.com/rensai-shellscript1-1/)」で、シェルスクリプトのコードが公開されていました。お、これだ！と思いました。
もちろん、OS X はシェルスクリプトが動くので、このソースをそのまま使うこともできるのですが、AppleScriptならクリップボードが扱えるので、テキストファイルにする手間も省けるし、メニューバーから起動もできて便利なので、書いてみようと思ったのでした。

## AppleScript 作成
**【AppleScript 化の仕様】**
* クリップボードからURLを取り出す
* "/" で分割
* "dp" or "product" の後の商品番号を取り出す
* 商品番号の後ろに"?"が付いていたら、？以降を無視する
* 以上のデータでURLを組み立てる（https://www.amazon.co.jp/dp/商品番号）
* 組み立てたURLをクリップボードにセットする

**【ソースコード】**

```applescript:AmazonURL.scpt
-- クリップボードのAmazon URL から余分な部分を取り除いた結果をクリップボードにセットする
set urlData to the clipboard as text
set tmp to text item delimiters
set text item delimiters to "/"
set urlItems to text items of urlData -- URLを”/" で分割
set text item delimiters to tmp
-- プロダクト番号を取り出す
repeat with i from 3 to number of urlItems
	if item i of urlItems = "dp" then set itemNumber to item (i + 1) of urlItems
	if item i of urlItems = "product" then set itemNumber to item (i + 1) of urlItems
end repeat
-- プロダクト番号に？がついていたら？以前だけにする
set tmp to text item delimiters
set text item delimiters to "?"
set itemNumber to text item 1 of itemNumber
set text item delimiters to tmp
--結果のURLを組み立てる
set rst to item 1 of urlItems & "//" -- "ex: "http:" + //
set rst to rst & item 3 of urlItems & "/" -- ex: "www.amazon.co.jp" + /
set rst to rst & "dp/" & itemNumber
set the clipboard to rst as string
```
## メニューバーからの起動
このスクリプトを ライブラリー、Scripts に置いて、スクリプトエディタの設定で「メニューバーにスクリプトメニューを表示」をチェックすると、メニューバーから起動できます。

後はブラウザーで表示された Amazon の商品のURLを全部選択してコマンド + C（コピー）した後、メニューからスクリプトを起動し、紹介記事にペーストするだけです。

お気に召していただければ幸いです。
（スクリプトへのツッコミ、リファクタリングなどのご意見を歓迎します）
[WIP] Vimコマンド（基本編）

#Vim
備忘録として随時追加．

## モード
- ノーマルモード
    - `esc`
- 入力モード
    - `i`
- 選択モード
    - `v`
- コマンドモード
    - `:`

## カーソル移動
`h`：左に移動
`j`：下に移動
`k`：上に移動
`l`：右に移動

`w`：次の単語に移動
`e`：次の単語の末尾に移動
`b`：手前の単語の先頭に移動

`^`：行の先頭に移動
`$`：行の末尾に移動

## 編集
`y`：コピー
`yy`：一行コピー
`p`：ペースト
`:dd`：一行削除
`:daw`：一単語削除
`:%d`：全削除
`x`：カーソルの下の文字を削除
`i`：カーソルの左に挿入
`:w`：保存
`:q`：終了
`:wq`：保存して終了
`:q!`：保存せずに終了

## 複数行コピー，カット
1. コピーしたい先頭にカーソルを移動
2. `ms`と入力し範囲指定開始
3. コピーしたい終端にカーソルを移動
4. コピーなら`y's`，カットなら`d's`と入力し範囲指定終了
5. 目的の箇所で`p`を入力しペースト
pythonのlogクラスについて 連続実行時に重複させない方法

# logクラスの例 
## 概要
ほかの[記事](https://qiita.com/snowp/items/9734028cecb68b9940a1)で使っているログクラスを改修したことに触れていなかったのでこちらで触れておきます。
最初に出していた方法だと同じログが呼び出されるたびに出力されていたので、ユニットテストの際に重複してしまったので改修しました。


## 必要なもの

* python 3.7.2

## 公開場所
[github](https://github.com/snowpff14/seleniumSample)で公開しいます。


## 使い方

ログ出力用のクラスを使ったらあとは`createLog`メソッドでログのオブジェクトを取得します。

以下のように一度作成したログと同じログの場合は作成済みのものを返却しています。

```
        if len(self.loggers)!=0:
            if name in self.loggers:
                # すでに作成済みなら重複して作成しないようにする
                return self.loggers[name]
```

作成していないものなら作成後にdictionaryに登録ます。

```
        self.loggers[name]=self.logger
        return self.logger
```
Unityでテストコードから自作クラスの参照が出来ない場合の対処法

# ぶつかった問題
UnityでAssets配下に置いたC#スクリプトのテストを書こうとしてややハマりました。

自作の`Hoge`クラスをテストしようとして、テストコードから`Hoge`を呼び出したところ
<img width="481" alt="Screen Shot 2019-04-07 at 18.16.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/37417/7a39aae7-c564-bc93-fcfd-0f1e1b188416.png">

***The type or namespace name 'Hoge' could not be found (are you missing a using directive or an assembly reference?)***

お前は何を言っているんだという感じですが、自作クラスへの参照がうまくいかないようです。
テストコード以外からは参照できているのになぜ。。。

# 解決方法
1. テストしたいスクリプトを置いているフォルダで`右クリック → Create Assembly Definition`を実行、名前を入力してAssembly Definitionを作成
2. テストコードを置いているフォルダ内のImport Settings(`Tests`フォルダなら`Tests`という名前でフォルダ内に生成されているはず)の`Assembly Definition References`で`1`で作成したAssembly Definitionを追加してApply

これで無事に自作クラスがテストコードから参照できるようになりました。

# 所管
これぶっちゃけ超わかりにくいと思うんだけど、この件に言及している記事はなかなか見つけられず…
Unityに慣れてる人たち的には困らない案件なのか。。または最近のバージョンアップで追加された仕様でまだ被害者が少ないだけなのか。。。
vim-surround でシングル・ダブルコーテーションどちらで囲むかを切り替えやすくする

## はじめに

ruby を使っていると、文字列をコーテーションで囲むとき、場合によってシングルコーテーション・ダブルコーテーションを使い分けることがあると思います。

その際僕は毎回手動で始端と終端のコーテーションを切り替えていたのですが、[vim-surround](https://github.com/tpope/vim-surround) という Vim プラグインを使うと簡単にできそうだったので、試してみました。

## vim-surround とは

カッコやコーテーションといった記号で囲まれた文字列について、囲んでいる記号を簡単に編集できるプラグインです。

例えば以下のようにダブルコーテーションで囲まれた文字列をシングルコーテーションに変更したい時は、

```
"Hello world!"
```

プラグインをインストールした上で `cs"'` とコマンドを打つと、シングルコーテーションに変更してくれます。`cs` は ChangeSurroundings の略です。

```
'Hello world!'
```

## よりキー入力を少なくしたい

vim-surround の基本コマンドを使うだけでやりたいことはほぼ実現できたのですが、
せっかくなのでよりキー入力を短くしたかったので、以下のコマンドで切り替えられるように設定します。

* シングル→ダブルへの切り替えを `ff` で
* ダブル→シングルへの切り替えを `tt` で

## 手順

### vim-surround インストール

vim-surround をインストールします。この例では [dein.vim](https://github.com/Shougo/dein.vim) を使っています。

```vim:.vimrc
call dein#add('tpope/vim-surround')
```

### キーマップ設定

次に、vim-surrond の関数をキーマップに指定します。`Csurrond` というのが `cs` というコマンドにマッピングされた関数にあたるのですが、それを新たに`ff`、`tt`というコマンドにマッピングしています。

```vim:.vimrc
" ダブルコーテーション→シングルコーテーション
nmap ff <Plug>Csurround"'
" シングルコーテーション→ダブルコーテーション
nmap tt <Plug>Csurround'"
```

こちらで以上です。これで `ff` か `tt` を打つと文字列を囲んでいるコーテーションの種類を切り替えることができます。
キーマップはお好みで変えても良いと思います。

## おわりに

今回はコーテーションの切り替えだけでしたが、 vim-surround には他にも機能がありそうなので、チェックしてみようと思います！

## 参考

* [vim plugin - Is there anyway to change VIM Surround's keymapping? - Stack Overflow](https://stackoverflow.com/questions/17537182/is-there-anyway-to-change-vim-surrounds-keymapping)
Wantedly探訪  株式会社ポテパン ( Twitter @potepan0901 ) #エンジニア #就職 #転職


# まとめ

週10時間から出来る副業可能、リモート可能なプログラミング講師、プログラミングスクールのオンラインレビューの仕事。

- 人に教えるのが好きな人
- エンジニア業界自体を良くしたい人
- 週に細切れの時間で有意義なアウトプットしたい人

には良いかなと思った。

本業をおこないつつ、なおかつエンジニア講師やオンラインレビューなどをして、今後未来を創るであろう、ナウなヤングにバトンを渡していくというのは、ミッションを感じられる仕事かもしれない。

おそらく大量のレビューをおこない、色々なタイプのプログラマに対して教えることになると思うので、限られたメンバーでペアプロなどをするよりも、ずっと教える経験というものがつけられるかもしれない。

# Wantedly

[リモート副業可能！Web系開発経験あればOK！オンラインレビュワー募集 - 株式会社ポテパンのWeb エンジニア契約・委託の求人 - Wantedly](https://www.wantedly.com/projects/243979?ql=gaJpZM4AZcG0)

# Twitter

[ポテパン＠エンジニアをサポート (@potepan0901) / Twitter](https://twitter.com/potepan0901)

# Face

![image](https://user-images.githubusercontent.com/13635059/55680432-7f565500-5954-11e9-880a-261ebfc55e61.png)

# 未経験エンジニアと企業側のエンジニア不足の溝に橋渡しをするサービスらしい

今後どんどん需要は拡大しそうな気もする。

>それから次に転職支援付きのプログラミングスクールを立ち上げました。企業側のエンジニア不足は深刻ではあるもののエンジニア未経験者の採用には踏み込めておらず、そこには大きな溝がありました。

# 週10時間からリモートで働けるらしい

![image](https://user-images.githubusercontent.com/13635059/55680378-b2e4af80-5953-11e9-8e79-b55baa9045c1.png)

# プログラミングスクールのオンラインレビュアーの仕事らしい

>ポテパンキャンプのオンラインレビュワーを募集しています。

>ポテパンキャンプには毎月120名以上の応募があり、その応募者の中からポテンシャルやモチベーションの高い方を選抜させていただき受講していただいてます。

# 社員3人に対して副業メンバーが30人ほどもいるらしい

>そして弊社はまだ役員含めてフルタイムメンバー3名の会社ですが、優秀な副業メンバー20-30名に日々手伝ってもらっています。

# UNLOCK YOUR POTENTIAL !

他にもWebエンジニア講師も募集しているらしい。

![image](https://user-images.githubusercontent.com/13635059/55680438-9b59f680-5954-11e9-8d0c-9938999ce205.png)

# 公式

ひとつの学びとして、募集概要ではなくて公式サイトなりを見たほうがずっと、サービス内容などのイメージが把握しやすいように思った。

Wantedlyのインターフェイスで業務やサービス全てを表現するのには限界があるだろうなあ。

![image](https://user-images.githubusercontent.com/13635059/55680481-ec69ea80-5954-11e9-8b88-f08a4410c7b3.png)
![image](https://user-images.githubusercontent.com/13635059/55680491-0efc0380-5955-11e9-8a6a-6f9231537d5e.png)


# By 稲浦悠馬

[稲浦 悠馬 プロフィール - Wantedly](https://www.wantedly.com/users/93140896) (つながり申請など歓迎)

# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->