OmniAICreator/Qiita-1.07M huggingface dataset:
「やらなければ、はじまらない・・・」の先をやっていくための Vive + Unity VTuber 運用サンプル

# まだやってない・・・
はじめましょう。
あきらさんの「[UniVRM+SteamVR+Final IKで始めるVTuber](https://qiita.com/sh_akira/items/81fca69d6f34a42d261c)」がおすすめです。
そもそも Unity を触りたくないのであれば、バーチャルモーションキャプチャーや 3tene など無料で使えるツールもいろいろあります。

# 何があるの？
[VLVTuber](https://github.com/toiro/VLVTuber)
3D VTuber を運用していく上でのあるある課題をそこそこ解決してまとめた Unity 用のアセットと、そのサンプルプロジェクトです。
「にゃるらちゃん放送局」などで運用したシステムを公開できなくもない程度にしてあります。
ライセンスは WTFPL です。好きにしてください。
質問はなるべく答えますが、まずはサンプルを動かしてソースコードを読みましょう。

#VTuber をやっていくために
（ここから先はポエムです。暇な人だけどうぞ）
Vive 3点トラッキングでキャラクターモデルの中に入って動けるようにUnity上で実装することはそれほど難しいことではないです。今なら上で紹介したようにチュートリアルもまとまっています。手順通りにやればいいわけです。
しかしそうやってモデルを動かせるようになっても、そこから実際に VTuber を運用しようとするといろいろな課題が出てきます。
でもチュートリアルこなした程度のはじまったばかりの人にとってそうした課題を解決するというのは難しいことです。なぜなら、たいていそういう課題というのはちょっと掘っただけでもはや VTuber の V の字も出てこないような情報や知識が必要なところまであっという間に到達してしまうのが当たり前だから。

##ちょっと機能追加したいんだけど……
一つ例をあげましょう。
VTuber を収録するのに、HMD を被る必要は必ずしもありません。企画としてVR空間を必要としないのなら、むしろ普通に現実が見えている方がよいことも多いです。
というわけで、頭のトラッキングをHMDからトラッカーに変更してHMDを被る替わりに頭にトラッカーをつけて収録できるようにしたいと思うようになったとします。

するとまず、VRIK の設定を見て、頭のトラッキング元がHMDになっているので、それをトラッカーに変えます。そしてドングルをUSBにつなげてトラッカーをペアリングする……
これでOK？
いいえ。そうすると頭が明後日を向いてしまっていることでしょう。頭にトラッカーを着けたとき、そのときのトラッカーの向きにあわせて顔が向いてしまいます。
つまり、トラッカーを頭に着けた時の姿勢で顔が正面を向くように回転のオフセットを入れる必要があるのです。この時点で意味が分からない。
さらに意味が分かったとして、これをインスペクタからxyz回転をいじって合わせるのはなかなかに骨が折れる作業です。
何度か繰り返すうちに、あるいは一度やっただけでも、何とか自動化できないかと思うようになることでしょう。いろんなツールでは自動キャリブレーションは一般的になっていますからね。
というわけで、自動キャリブレーションをやるためには Quaternion なにそれおいしいの？　回転ってXYZじゃない？　え？

こういうことが次々と出てきます。
技術をのセンスがない連中がかかわってるとさらにやばいです。やつらは「このくらい簡単なんでしょ？」って気楽に投げ込んできます。収録までによろしくって収録の前日に言いますからね。
みんな「Unity なにもわからない」って言いたくなるわけです。「チョットデキル」人はほんと神ですよ。

##VTuberのよくある課題って、何？
そもそも VTuber ってどのようにはじまりましたっけ？
バーチャル YouTuber という言葉自体はキズナアイが名乗り始めたものですが、今の流れに繋がる重要なきっかけとしてバーチャルのじゃロリ狐娘YouTuberおじさんが「やらなければ、はじまらない・・・」という想いとともに動画投稿をはじめたということがあります。
そしてそうやってのじゃおじがはじめることができたのは、VTuber に必要なモーションキャプチャーと、モーションキャプチャーの動きをアバターの動きとして適用する仕組みが、個人の手の届くところまで安価で、誰でも扱えるものになったからです。
のじゃおじのところまでは技術的には今や誰でも辿り着くことができます。技術が個人の手の届くところに降りて、のじゃおじが道を示し、そこまでの道が拓かれたから。
しかしそこで終わってしまうなら、3D の VTuber はただアバターを白い空間に瓶詰しただけのとても不自由なものでしかありません。声優ラジオでもやってろってことですね。
何が不自由なのか、その不自由さにどう立ち向かえばいいのか、はじめた先にはどう進むのか、せめて一歩だけでも進めるように、

- 画面をカメラにレンダリングされた結果をもとに鏡像反転したい
- マルチディスプレイに出力して複数のアングルから収録したい
- VRIK を動的にアタッチしたい
- キャラクターのモデルを動的に読み込みたい
- 表情を切り替えるときにスムーズに補完して切り替えたい
- まばたきと表情の不自然な干渉を避けたい
- 頭のトラッキングを HMD からトラッカーに切り替えたい
- トラッキング点数を増やしたい
- トラッキング点数を簡単に変更したい
- トラッカーの割り当てを動的に行いたい
- トラッカーの位置と回転にオフセットを設定したい
- トラッカーの回転オフセットを自動でキャリブレーションしたい
- キャリブレーション結果をシーン外に保存したい
- モーションキャプチャーのブレを軽減したい
- モーションキャプチャーのシーンと背景のシーンとを分離したい
- グリーンバックをすぐに使えるようにしたい
- シーンをインスペクタ上の変数として扱いたい
- 背景のシーンごとにカメラやライトの設定を持ちたい
- キーボードへの割り当てを一か所で管理したい
- キーボードに割り当てた機能を一覧で見たい
- キーボードに割り当てた機能をマウス操作から呼びたい
- Viveコントローラーでモデルの手を動かしたい

といった数々の課題をまとめて示したものがあってほしかったので、今回 [VLVTuber](https://github.com/toiro/VLVTuber) を公開します。
catalinaでterminalがzshになったのを一旦bashに戻す方法

どれでも良いが
・ターミナル -> 環境設定 -> 一般 -> 開くシェルで```/bin/bash```
・```chsh -s /bin/bash```
・システム環境設定 -> ユーザとグループ -> ユーザを右クリックで詳細オプション -> ログインシェルを```/bin/bash```

戻すときは```/bin/bash```を```/bin/zsh```にすれば上手くいく(はず)
Nuxt (TypeScript, Pug/sass, Bootstrap) テンプレート作成

## 準備
- npm インストール
- vue-cli インストール `npm install -g @vue/cli` `npm install -g @vue/cli-init`
- npm-check-updates インストール `npm install -g npm-check-updates`（`ncu` , `ncu -u`）
- 実行時のバージョンは以下

```
node --version
v10.16.0
npm --version
6.9.0
vue --version
3.11.0
```

## プロジェクト作成
Nuxt Community から取得できる TypeScript のテンプレート取得して実行
`http://localhost:3000` で立ち上がるので確認

```
vue init nuxt-community/typescript-template project-name

cd project-name
npm install
npm run dev
```

Pug, Sass を設定

```
npm install --save-dev pug pug-plain-loader
npm install --save-dev node-sass sass-loader
npm install --save-dev sass fibers
```

Bootstrap を設定

```
npm install bootstrap-vue jquery
```

## その他
npm install がうまくいかない（node-sassでエラー）

```
# node-sass をリビルド
npm rebuild node-sass

# 表示エラー概要
Error: Missing binding /path/to/project/node_modules/node-sass/vendor/darwin-x64-64/binding.node
・
・
# node が古いバージョンでインストールを実行した場合に発生
# ex) v8 以下で実行後に v10 にあげて実行したとき
```
js > react

reactの学習を開始しました。2進数時計の例を見て、手動でDOMを効率よく更新することに限界を感じました。
そこまでの動きを求めないならjQueryで十分。それ以上の動きを求めるならreactを使う。
その境界を自分なりに見つけたいです。

### snipet
``` html:
<script src="https://unpkg.com/react@15/dist/react.min.js"></script>
<script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.min.js"></script>
```
``` JSX:
ReactDOM.render(
  <div>hello</div>,
  document.getElementById('output')
)
```
図形の位置を調整するExcelマクロ

##これは
Excelでの資料作成時に意外と便利かもしれない、ちょっとしたマクロです。
複数の図形を選択した状態で当マクロを実行すると、
一つ目に選択したものを基準にして、図形の位置や大きさを調整します。

（ [以前投稿したPowerPoint用のVBScript ](https://qiita.com/jinoji/items/94ae11cfe6cea6082806)の焼き直しです。）

##コード
```vb
Sub 図形位置調整(Optional 左 As Boolean = False, Optional 上 As Boolean = False, _
                Optional 幅 As Boolean = False, Optional 高 As Boolean = False, _
                Optional 右 As Boolean = False, Optional 底 As Boolean = False, _
                Optional 横 As Boolean = False, Optional 縦 As Boolean = False, _
                Optional 間 As Long = 5)

    Dim obj As Object, shpRng As ShapeRange
    Set obj = ActiveWindow.Selection
    If Not TypeName(obj) = "DrawingObjects" Then Exit Sub
    Set shpRng = obj.ShapeRange
    
    Dim i, l, t, w, h, r, b
    For i = 1 To shpRng.Count
        With shpRng.Item(i)
            If i = 1 Then
                l = .Left
                t = .Top
                w = .Width
                h = .Height
                r = l + w
                b = t + h
            Else
                If 左 Then .Left = l
                If 上 Then .Top = t
                If 幅 Then .Width = w
                If 高 Then .Height = h
                If 右 Then .Width = r - .Left
                If 底 Then .Height = b - .Top
                If 横 Then .Left = r + 間
                If 横 Then r = .Left + .Width
                If 縦 Then .Top = b + 間
                If 縦 Then b = .Top + .Height
            End If
        End With
    Next
End Sub
```
##使用例
よく使う作業をこんな感じでそれぞれ定義します。
クイックアクセスツールバーなどに登録しておくのもよいでしょう。

```vb
Sub 左端を揃える()
    図形位置調整 左:=True
End Sub
Sub 左端と幅を揃えて縦に整列()
    図形位置調整 左:=True, 幅:=True, 縦:=True, 間:=10
End Sub
```
Git bashでのzipコマンドの代わり

Git bashでzipコマンドがなくて困った人は多いかもしれません。

Git bashでzipを作るには様々な手段が存在すると思いますが、
下記の様にPowerShellを呼び出す方法が好きなので紹介します。

```bash
## ディレクトリ配下のファイルをすべてzipに
$ powershell -c Compress-Archive -Path "./*" -DestinationPath out.zip
```

~~なら最初からPowerShellを使えよと……~~
[Compress-Archive](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/compress-archive?view=powershell-6)便利ですね。

## zip関数をbashrcに登録

下記の関数を~/.bashrcに登録すると良いかもしれません。

```bash:~/.bashrc
zip(){ powershell -c Compress-Archive -Path "${1:-./*}" -DestinationPath "${2:-./out.zip}"; }
```

引数なしの際はカレントディレクトリをout.zipしてくれます。

```bash
$ find .
.
./file1.txt
./sub_dir
./sub_dir/file2.txt
```

```bash
$ zip 
$ zipinfo -1 out.zip
sub_dir\file2.txt
file1.txt
```

引数指定で任意のディレクトリを任意の名前でzipにできます。

```bash
//ディレクトリ自体をzipに含めたい場合
$ zip sub_dir out2.zip
$ zipinfo -1 out2.zip
sub_dir\file2.txt

$ rm out2.zip

//ディレクトリ自体はzipに含めたくない場合
$ zip sub_dir/* out2.zip
$ zipinfo -1 out2.zip
file2.txt
```

## 参考

Git Bashでzipを作るのにはさまざまな方法があるみたいです。

[git-bash for windows を快適にするためのいろいろ : zipコマンドが使えるようにする](https://qiita.com/sixpetals/items/a0784fa3933956463609#zip%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%8C%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B)
[Git for Windowsなんだけどzipコマンド入ってないんだけど💢](https://qiita.com/yukihane/items/75bdcb0f3b6aedf3a295)
https://nirajsonawane.github.io/2018/10/27/Angular-Material-Tabs-with-Router/を参考にAngularアプリにタブを追加した時にタブ名が空白

#問題
<a href="https://nirajsonawane.github.io/2018/10/27/Angular-Material-Tabs-with-Router/">ここ</a>を参考にangularでタブごとにページを切り替えることに成功したがタブ名が空白

#解決

###before

![スクリーンショット 2019-09-04 1.59.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280340/d0cc7ee0-e4c1-ac2f-f036-1ceacbf92a2b.png)


```html:app.component.html
   <a mat-tab-link
    *ngFor="let link of navLinks"
    [routerLink]="link.link"
    routerLinkActive #rla="routerLinkActive"
    [active]="rla.isActive">
    </a>
```
###after

![スクリーンショット 2019-09-04 1.58.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280340/f5fbfdcc-8e43-763f-0dde-843f0d69d577.png)


```html:app.component.html
   <a mat-tab-link
    *ngFor="let link of navLinks"
    [routerLink]="link.link"
    routerLinkActive #rla="routerLinkActive"
    [active]="rla.isActive">
    {{link.label}}
    </a>
```
【R】多項式回帰

備忘録的なメモです。

多項式回帰分析の方法。

使うデータフレームは、Rの標準データの、

**DNase**

です。

データの読み込み

```R
#データの読み込み
DF <- DNase
```

まずは、次のような2次式を回帰式とした場合、

```math
y = b_0 + b_1x_1 + b_2x_1^2
\\
```

この場合は、こんなスクリプト。

```R
LM2a <- lm(density ~ conc + I(conc^2), data = DF)
```
あるいは、こんな書き方でもいける。

```R
LM2b <- lm(density ~ poly(conc, degree = 2, raw = TRUE), data = DF)
```

**coefficients()**で回帰係数を確認すると、

```R
#回帰係数を確認
coefficients(LM2a)
coefficients(LM2b)
```

```R
> #回帰係数を確認
> coefficients(LM2a)
(Intercept)        conc   I(conc^2) 
 0.12197753  0.31807970 -0.01501489 
> coefficients(LM2b)
                        (Intercept) poly(conc, degree = 2, raw = TRUE)1 poly(conc, degree = 2, raw = TRUE)2 
                         0.12197753                          0.31807970                         -0.01501489 
```

続いて、次のような3次式を回帰式とした場合、

```math
y = b_0 + b_1x_1 + b_2x_1^2 + b_3x_1^3
\\
```

こんなスクリプト。

```R
LM3a <- lm(density ~ conc + I(conc^2) + I(conc^3), data = DF)
```

あるいは、

```R
LM3b <- lm(density ~ poly(conc, degree = 3, raw = TRUE), data = DF)
```
**coefficients()**で回帰係数を確認すると、

```R
coefficients(LM3a)
coefficients(LM3b)
```

```R
> coefficients(LM3a)
(Intercept)        conc   I(conc^2)   I(conc^3) 
 0.05779811  0.46110796 -0.05173350  0.00206439 
> coefficients(LM3b)
                        (Intercept) poly(conc, degree = 3, raw = TRUE)1 poly(conc, degree = 3, raw = TRUE)2 
                         0.05779811                          0.46110796                         -0.05173350 
poly(conc, degree = 3, raw = TRUE)3 
                         0.00206439 
```

こんな感じで多項式回帰分析をやります。

#最終的なスクリプト

```R
#Rをきれいにする
rm(list = ls())

#データの読み込み
DF <- DNase

#回帰分析(二次式)
LM2a <- lm(density ~ conc + I(conc^2), data = DF)
LM2b <- lm(density ~ poly(conc, degree = 2, raw = TRUE), data = DF)

#回帰係数を確認(二次式)
coefficients(LM2a)
coefficients(LM2b)

#回帰分析(三次式)
LM3a <- lm(density ~ conc + I(conc^2) + I(conc^3), data = DF)
LM3b <- lm(density ~ poly(conc, degree = 3, raw = TRUE), data = DF)

#回帰係数を確認(三次式)
coefficients(LM3a)
coefficients(LM3b)
```
Railsの時間処理/時間範囲の指定でActiveSupportのTimeクラスの拡張機能:TimeWithZoneを使う

## 背景
開発中のサービスにおいて、"当日分"のレコードだけを取得する必要があり、どのようにクエリに渡すべきか検討していました。

色々とググったりRailsガイドを漁ってみたりしたところ、`ActiveSupport::TimeWithZone`クラスを利用することでうまい具合にできたので共有&メモっておきます。

結論としては、`Time.current.all_day`で"当日分だけ”に該当するレコードを指定することだできました。

## ActiveSupportとは
>Active SupportはRuby on Railsのコンポーネントであり、Ruby言語の拡張、ユーティリティ、その他横断的な作業を担っています。
Active Supportは言語レベルで基本部分を底上げして豊かなものにし、Railsアプリケーションの開発とRuby on Railsそれ自体の開発に役立てるべく作られています。
引用:[Railsガイド/Active Support コア拡張機能](https://railsguides.jp/active_support_core_extensions.html)

Supportの名の通りRailsでの開発で便利な機能を提供してくれるもので、各クラス(e.g. String, Array, Integer etc)の拡張機能などを提供します。

Ruby on Railsのアプリケーションでは、基本的には全てのActive Supportがデフォルトで読み込まれていますので、特段必要な設定などはありません。

## ActiveSupportによるTimeクラスの拡張

### Time.current
ActiveSupportの提供する拡張機能にはTimeクラスに関するものもあり、その中で`Time.current`という現在時刻を返すメソッドを提供しています。
Timeクラスにおいては類似のメソッドとして`Time.now`も提供されていますが、`Time.current`はアプリケーション側でタイムゾーンの指定がある場合には指定のタイムゾーンに従った現在時刻を表示します。

```ruby:例
# 2019/09/04 00:00:00の場合

(a)タイムゾーン指定なしの場合
$ Time.now
=> 2019-09-04 00:00:00 +0900

$ Time.current
=> Tue, 03 Sep 2019 15:00:00 UTC +00:00

(b)タイムゾーンをTokyoに指定した場合
$ Time.now
=> 2019-09-04 00:00:00 +0900

$ Time.current
=> Wed, 04 Sep 2019 00:00:00 JST +09:00
```

### all_day, all_week, all_month, all_quarter, all_year
指定した期間を表す範囲を返すメソッドもActiveSupportで提供されています。
`Time.now`または`Time.current`に対して呼び出すことで、現在時刻を含む期間の範囲を返します。

```ruby:例
$ now = Time.current
=> Wed, 04 Sep 2019 00:00:00 JST +09:00

# 現在時刻を含む「1日」の範囲を返す
$ now.all_day
=> Wed, 04 Sep 2019 00:00:00 JST +09:00..Wed, 04 Sep 2019 23:59:59 JST +09:00

# 現在時刻を含む「１週間」の範囲を返す
$ now.all_week
=> Mon, 02 Sep 2019 00:00:00 JST +09:00..Sun, 08 Sep 2019 23:59:59 JST +09:00

# 現在時刻を含む「1ヶ月間」の範囲を返す
$ now.all_month
=> Sun, 01 Sep 2019 00:00:00 JST +09:00..Mon, 30 Sep 2019 23:59:59 JST +09:00

# 現在時刻を含む「四半期」の範囲を返す
$ now.all_quarter
=> Mon, 01 Jul 2019 00:00:00 JST +09:00..Mon, 30 Sep 2019 23:59:59 JST +09:00

# 現在時刻を含む「１年間」の範囲を返す
$ now.all_year
=> Tue, 01 Jan 2019 00:00:00 JST +09:00..Tue, 31 Dec 2019 23:59:59 JST +09:00
```

### その他Timeクラスの拡張
そのほかに`Time.current`を起点とした翌前日の日時を返すメソッドや翌前月を返すメソッド、などあります。
詳細はRailsガイドを参照してください。
参照: [Railsガイド AcvtiveSupport Timeの拡張](https://railsguides.jp/active_support_core_extensions.html#time%E3%81%AE%E6%8B%A1%E5%BC%B5)

## まとめ
- Active SupportはRailsにデフォルトで読み込まれている開発に役立つライブラリで、各クラスの拡張機能を提供する
- `Time.now`と`Time.current`はユーザー定義によるタイムゾーンの指定があるか否かで返す値が変わる
- タイムゾーンの指定がない場合には、`Time.current`は協定世界時(UTC)を返す
- `Time.now`のタイムゾーンは地方時
- Active Supportによる拡張機能を利用することで、特定の期間を表す範囲を返すことができる(例: `Time.current.all_**`)

## 参照
- [Railsガイド AcvtiveSupport Timeの拡張](https://railsguides.jp/active_support_core_extensions.html#time%E3%81%AE%E6%8B%A1%E5%BC%B5)
- [Ruby 2.6.0 リファレンスマニュアル/singleton method Time.new](https://docs.ruby-lang.org/ja/latest/method/Time/s/now.html)
kiitok meetup メガベンチャーEMが語る"採用市場でモテるエンジニア に行ってきた話

# 目的

- meetupで得た内容を整理してまとめ、これからのキャリアの選択時の知識落とし込もう  
※本記事はかなり筆者のとらえた情報よりの内容になっています。実際の登壇者の方々のしていただいたお話とは異なる可能性があります。すいません。。。

# 参加したmeetupの内容

- 30代以下を対象とした市場でモテるエンジニアはどんな人なのかを知る会
- 実際にメガベンチャーでお仕事をされている方からお話を伺う
- 参加人数は50人以下
- 登壇者のLTの後にSlackを用いた参加者からの生の質問に答えていただける時間があった

# 今回参加させていただいたmeetupの詳細ページ

- connpassのリンクを下記に記載する。  
[メガベンチャーEMが語る"採用市場でモテるエンジニア"U30エンジニア限定|kiitokMeetUp](https://kiitok.connpass.com/event/138743/)

# kiitokって？？

- エンジニアのためのコミュニティ
- 現職の相談に乗ってくれる
- キャリア相談にも乗ってくれる
- meetupなどを実施してエンジニアの交流の手助けをしてくれている
- 現役エンジニアに相談することができる数少ないサービス
- 筆者おすすめのサービスなので、ぜひ一度書きサイトにアクセスしてみてほしいです。
- kiitokのコミュニティの各リンクを下記に記載する  
公式ページ: [kiitok](https://kiitok.com/)  
Twitter: [https://twitter.com/kiitok_official](https://twitter.com/kiitok_official)  
connpasグループ: [https://kiitok.connpass.com/](https://kiitok.connpass.com/)  

### 登壇をされた方の情報(リンク先)にばらつきがあってごめんなさい。。。

## 池上純平(gami)さん | 株式会社プレイド　(司会)
Twitter⇒[https://twitter.com/jumpei_ikegami](https://twitter.com/jumpei_ikegami)

- 「完全Sier脱出マニュアル」の著者
- Podcastではパーソナリティのzuckeyさんと一緒に「しがないラジオ」を放送中！
- 会場提供LTと司会を担当されていました！

## 千條 吉基さん | 株式会社ディー・エヌ・エー サービスインキュベーション事業部 開発部 部長
ごめんなさい現時点でリンクを探せていません。確認次第すぐにリンクを張ります

- メガベンチャーの何たるかの説明されていました。
- また、物事を具体的に考える大切さについてお話されていました。

## 新田 智啓さん | 株式会社メルペイ Backendエンジニアリングマネージャ
Twitter⇒[https://twitter.com/t_shinden](https://twitter.com/t_shinden)

- 採用側の目線を理解することの大切さをお話しされていました
- 勉強会やmeetupは懇親会が肝心だとお話しされていました

## 白川 裕介さん | 株式会社ミクシィモンスト事業本部 開発室 室長
facebook⇒[https://www.facebook.com/yusuke0711?fref=ts](https://www.facebook.com/yusuke0711?fref=ts)

- 現在の自分のプロジェクトでの役割を理解することの重要性を話されていました
- また前述の内容を理解することでプロジェクトでの問題点やより良い環境へのアプローチも見えてくると説明されていました

## 福原 真さん | 株式会社サイバーエージェント アドテクスタジオ エンジニアリングマネージャー
Twitter⇒[https://twitter.com/fukuo33](https://twitter.com/fukuo33)

- 福原さんが在籍する企業の採用基準などをより深堀してお話されていました
- 己の強みを自覚することの大切さをお話しされていました

# 登壇された方々のお話を総合して筆者が大切に感じたこと

- モテるエンジニアを一言で言うと**自分の強みを理解し高いモチベーションを保った自律的に行動のできる人**
- 物事を具体的にみている
どうしてその設計で、どうしてそのライブライを使用して、どうしてその言をを選択したのかなどを具体的に話せるようにする
- ちょっとしたことに疑問や好奇心を持つ
自分なりに調べて深く考えてみる
- 企業の目線を理解する
- モチベーションはあげようと思って上がるものではない、自然に湧き上がるモチベーションが大切
- 知らないことを知らないという勇気を持つ、変なプライドを捨てる
自分を大きく見せていることはばれる、素直に「わかりません！」というと逆に信頼度が上がる⇒これは普段の業務でも言える
- 自分の強みの自覚とその強みをどんなことに行かせているかを具体的に説明できる
ミスマッチを防げるしマッチした企業なら信じられないくらい活躍できる、自分の強みを知らないと活躍の場もぼんやりしてしまうかも？？？
- 困難への対処法と思考プロセスとその結果どうなったか(必ずしも前向きな結果でなくてもよい)
どういったことに問題を感じて、それに対しどう対処して、結果どうなったのかを具体的に話せるとよい

# 転職活動に通ずる筆者が大切に感じたこと

- 中途採用で学歴はあまり見られていない
- 採用側はどんなアウトプットをしているかを意外と確認してくれている
- 採用側もミスマッチが怖い
- 実は採用する側もされる側も同じくらいの不安がある
- 採用する側が知りたいのは採用される側のプロジェクト内容や現職の愚痴ではない
iOSアップデートの危険性とダウングレード

#目的
本記事では、iOSアップデートに置ける開発上での危険性とダウングレードの方法について紹介します。

#iOSアップデートにおける開発上での危険性
iOSの開発現場で取り返しのつかないミスの一つに検証端末のアップグレードというものが挙げられます。
私たちが普段使っているiPhoneなどの端末で、手動・自動で行われているOSのアップグレード。iOSの開発に携わらない人であれば、この行為はなんら問題のない当たり前の行動になると思います。
しかしこのアップグレードはiOSの開発現場で不用意に行うと、大問題に繋がる重大なミスになるのです。

##なぜダメのなのか？
###1 検証ができなくなる
まず第一に挙げらるのが、開発しているアプリケーションの検証ができなくなるという点があります。開発現場ではユーザーがどのバージョンのOSでも問題なく操作できるように、検証端末と呼ばれる各OSごとに分けられた端末で実機実装して挙動を確認し、そこで問題なくパスできるかを確認します。そのため、その検証端末を最新のOSにアップグレードすると古いOS環境での挙動が正常に確認できない事態になるのです。

###2 ダウングレードができない
OSをアップデートしたなら、前のOSにダウングレードすればいいじゃないかと考える方もいると思いますが、ほとんどの場合これが不可能なのです。その理由が下記の画像になります。
<img width="1264" alt="スクリーンショット 2019-09-04 0.41.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357475/54179a17-5b7a-02e4-08a4-9d1dff983b67.png">
この画像は本日2019/09/03時点でダウングレード可能なバージョンとダウングレード不可能なバージョンを表示しているものです。
画像上部の**Signed IPSWs**と書かれている下の緑色のバージョンがダウングレード可能な物、**Unsigned IPSWs**と書かれている下の赤色のバージョンがダウングレード不可能な物になります。つまり、最新のバージョンから一つ前のバージョンまでしかダウングレードできず、ほとんどのバージョンへのダウングレードは不可能ということになります。
では、なぜこのような事が起きるのでしょう？？？
####原因はSHSHの失効
**SHSH**とは**Signature Hash.sh**の略で、Appleによって発行されるファームウェア（OS)の許可証のことです。この許可証は、iOSファームウェアを端末にインストールして良いかを判断してくれます。つまり、SHSHの著名が切れる（失効する）ともう２度とそのOSにダウンロードすることができなくなるのです。しかもその失効の周期は早く、ダウングレード可能なOSは画像の通り１つ前やよくても２つ前のものになります。そのため、iOSアプリの開発現場などで必要な半年や1年前のOSはほぼダウングレードできないということになります。

#ダウングレードの方法
上記の解説でiOSのダウングレードが困難な理由は説明しましたが、運よくまだSHSHが失効していなかった場合のダウングレードの方法を下記に記載します。

###1 IPSWファイルのインストール
IPSWとはiPhoneSoftwareの略で、iOSファームウェア(OS)をインストールするためにiTunesで使用されるファイル形式です。
これをこの https://ipsw.me/ から端末と必要なOSバージョンを選んでインストールしてください。

###2 端末をリカバリーモードにして、iTunesに繋げる
<img width="318" alt="スクリーンショット 2019-09-04 1.19.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357475/fc1560f3-d91b-9187-7698-f75f6cb6032c.png">
リカバリーモードとは上記のような状態のことで、端末によって仕方が異なります。

・iPhone XとiPhone 8/8 Plusの場合：音量を上げるボタンを押してすぐ離します。次に、音量を下げるボタンを押してすぐ離します。次に、リカバリーモード画面が表示されるまで、スリープボタンを押し続けてください。

・iPhone 7/7 Plus の場合：スリープボタンと音量を下げるボタンを同時に押します。次のリカバリモードの画面が表示されるまで両方のボタンを押し続けてください。

リカバリーモードになったらiTunesに端末を接続してください。
・iPhone 6s以前/iPad/iPod touchの場合：スリープボタンとホームボタンを同時に押します。次のリカバリモードの画面が表示されるまで両方のボタンを押し続けてください。

###3 復元
<img width="580" alt="スクリーンショット 2019-09-04 1.23.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357475/0843b911-aa6f-0844-c03a-ff2f04fe1431.png">
すると、iTunesに上記のようなウインドウが表示されます。
そして、Macならoptionキー・WindowsならShiftキーを押しながら復元ボタンをクリックします。
するとIPSWファイルの選択ができるので、先ほどインストールしたファイルを選択し実行します。これで自動的にダウングレードが行われ終了になります。

#最後に
この記事は私が現場でやらかしてしまったミスを繰り返さないようにと、記述した記事になります。
私の場合はOSが１時間後に自動アップデートの設定になっており、気付いた時にはOSが最新になってしまっていました。
次なる犠牲を出さないように、本記事を参考にしてくれたら幸いです。
ここまで読んでくれた方々ありがとうございます。
奇妙なキャストについて

# ポインタとキャストの関係について
ポインタを宣言するときとりあえず変数の型とそろえて
　int a = 0;　　
　int *hoge_p = &a; 
のように宣言しています。
この型宣言をなぜ揃えるのか。
hoge_p の型と a の型はどんな関係があるのか。

そして、サンプルコードを見るとアドレスを表示するときに
　printf("%p",(void*)hoge_p);
というのを見かけます。
これが何を表しているのかを考えます。

___
# 実験してみる

``` c
#include <stdio.h>
int main(void)
{
// 中身がint型のポインタ　hoge_p
  int a = 0;
  int *hoge_p = &a;

// 中身がint型？double型？のポインタ foo_p
  double *foo_p = &a; // warning!!!

// それぞれのポインタの中身の大きさを表示する
  printf("%d\n",(int)sizeof(*hoge_p));
  printf("%d\n",(int)sizeof(*foo_p));


// 試しに色々な型でキャストしてみる
  printf("%p\n",hoge_p); // 1
  printf("%p\n",(int*)hoge_p); // 2
  printf("%p\n",(double*)hoge_p); // 3


  return 0;
}
```

これを実行すると


```bash

warning: initialization from incompatible pointer type
```

という警告が出ます。これを無視し実行してみると
私のパソコンでは

```bash

4
8
0061FF14
0061FF14
0061FF14
```

となります。
8という結果からポインタが中身の変数の型を
int型からdouble型に置き換えたと考えられます。(警告を無視したため)

つまり、なぜポインタの型と変数の型を
同じにするかは中身の型を揃えるためでした。

次にコードの1,2,3の部分について考えると出力は同じですが
１はhoge_p の先頭アドレスを表示している
２はhoge_p の中身がint型の変数(a)の先頭アドレスを表示している
３はhoge_p の中身がdouble型の変数(a)の先頭アドレスを表示している

（注　void* は汎用的なキャストで任意の型に変わる。）

と考えられます。
よくみる表現はこのようなことをしていた？ということです。

人間から見れば、この出力は同じですが
コンピュータから見れば上の解釈をしていることになります。
人間からするととても奇妙な解釈であると思います。
CloudArmorのIP制限とGCEのファイアウォールルールで、GCPのロードバランサーのヘルスチェックが失敗する

# 2019/12/3 追記
別件で同じ構成をしたら、cloudarmorの許可IPになくても成功したので、cloudarmorの箇所は取り消し線しました。

# はまったこと
マークダウンで書けるWiki「[Growi](https://growi.org/)」をGCP上に構築している最中に、GCPのロードバランサーのヘルスチェックではまったことのメモ。
はまったポイントは2つ。
- GCEのファイアウォールにロードバランサーのIPの許可が必要だったこと
- アクセスを社内限定にしようと、CloudArmorでIP制限をしたら、ロードバランサーの許可が必要になったこと

# GCPのCloud Load BalancingのヘルスチェックのIP
GCPのロードバランサーは、下記のIPを使う
- 130.211.0.0/22
- 35.191.0.0/16

参考：https://qiita.com/munaita_/items/26469999c0d4f2ac1df8
公式：https://cloud.google.com/load-balancing/docs/https/

公式からの抜粋
> Firewall rules
You must create a firewall rule that allows traffic from 130.211.0.0/22 and 35.191.0.0/16 to reach your instances. These are IP address ranges that the load balancer uses to connect to backend instances. This rule allows traffic from both the load balancer and the health checker. The rule must allow traffic on the port your global forwarding rule has been configured to use, and your health checker should be configured to use the same port. If your health checker uses a different port, then you must create another firewall rule for that port.

## GCEのファイアウォールルール
上記のとおり、許可IPに130.211.0.0/22と35.191.0.0/16を加える。
ちなみに、ファイアウォールルールにロードバランサーの名前を入れても許可はされない。
AWSと同じようにロードバランサーの名前で許可できると思うと間違う。

## CloudArmorのIP許可
2019/12/3 別件で同じ構成をしたら、cloudarmorの許可IPになくても成功したので、下記内容は取り消し線しました。
~~CloudArmorで社内のグローバルIP以外をdenyにしたら、ロードバランサーのヘルスチェックが失敗した。~~
~~CloudArmor→Cloud Load Balancing→GCEという構造でIPを拒否しているのかと思ったら違う模様。~~

~~参考：https://apps-gcp.com/cloudarmor-ip-restriction/~~
~~参考：https://qiita.com/ikutaN/items/e29c07413b78ca8c2fb9~~
~~公式：https://cloud.google.com/armor/docs/security-policy-concepts~~

~~CloudArmorの許可IPに130.211.0.0/22と35.191.0.0/16を加えたらうまくいった。~~
~~ただ、ググッても公式でも、
CloudArmorでIP制限しているときに、ロードバランサーのIPを許可に追加するという情報が見つからない。~~
~~自分は何か勘違いしているのだろうか。~~
超A&G+の番組表をapi化する（配信編）

前回 → https://qiita.com/taittide/items/7d512492179b2b520c4b



正直前回のjsonを渡すだけなので，簡単ではある。

こちらGitHub → https://github.com/sun-yryr/agqr-program-guide



---



### サブドメインを作ってssl証明書を出す

certbot使ってワイルドカード証明書作ってたら褒められた。やったね！



### nginx からプロキシを通す

いつもどおり

```
location / {
	    proxy_set_header Host                      $host;
        proxy_set_header X-Real-IP           $remote_addr;
        proxy_set_header X-Forwarded-Host    $host;
        proxy_set_header X-Forwarded-Server  $host;
        proxy_set_header X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_pass http://localhost:1234;
}
```



###APIサーバーを立てる

「いつもexpressだけど，pythonだしpythonで簡単にしたいなぁ」

こちら神 → https://qiita.com/Yaruki00/items/efe23a0e91579aec9398 



まずインストール

```bash
pip3 install falcon
pip3 install gunicorn
```



ルーティングはall, today, nowの3つなので簡単に3リソース作る。

```python
import falcon
import json
import datetime

all_json = []
not_repeat_json = []

class AgqrAll:
    def on_get(self, req, resp):
        params = req.params
        isRepeat = params.get("isRepeat")
        if isRepeat is None:
            resp.body = json.dumps(not_repeat_json, ensure_ascii=False)
        elif (isRepeat == "True") or (isRepeat == "true"):
            resp.body = json.dumps(all_json, ensure_ascii=False)
        else:
            resp.body = json.dumps(not_repeat_json, ensure_ascii=False)

class AgqrToday:
    def on_get(self, req, resp):
        week = datetime.date.today().weekday()
        params = req.params
        isRepeat = params.get("isRepeat")
        if isRepeat is None:
            resp.body = json.dumps(not_repeat_json[week], ensure_ascii=False)
        elif (isRepeat == "True") or (isRepeat == "true"):
            resp.body = json.dumps(all_json[week], ensure_ascii=False)
        else:
            resp.body = json.dumps(not_repeat_json[week], ensure_ascii=False)

class AgqrNow:
    def on_get(self, req, resp):
        now = datetime.datetime.now()
        week = now.weekday()
        res = all_json[week]
        for i in range(len(res)):
            prog = res[i]
            tmp_dt = datetime.datetime.strptime(prog["to"], "%Y%m%d%H%M")
            if now < tmp_dt:
                resp.body = json.dumps(prog, ensure_ascii=False)
                break
```



nowだけ毎回の計算量が多くなってしまっているのでなんとかしたいなぁとも思う。（自分は使わないのでまぁ……）



### バックグラウンドで動かす

```
nohup python3 server.py &
```



### 見てみる

https://agqr.sun-yryr.com/api/today



## 終わりに

- ワイルドカード証明書の自動renewやらないとな
- safariの文字コード自動認識に苦しめられた
- これでラジオ自動録音を改良できる。
- トップページにapi利用のなんか書いておこう
CSSまとめ

# CSSまとめ
cssを毎回忘れてしまうため、自分用にまとめています。
超初心者が使うような基礎項目が多いため、cssに触れたことがある人には不向きかと。
## コメント
`/*ここにコメントを記載する*/`
CSSファイル内にコメント記載が可能。

## 文字
**文字色変更**
`color: red`
文字色の変更が可能。
`color: #ff0000`
colorコードによる指定も可能。

**文字のサイズ指定**
`font-size: 100px`
文字の大きさをpxで指定可能。

**太字指定**
`font-weight: 100px`
文字の太さをpxまたはキーワードで指定可能。
`font-weight: normal`
標準指定。400pxと同等。
`font-weight: bold`
太字指定。700pxと同等。
`font-weight: lighter`
親要素より一段階細い。
`font-weight: bolder`
親要素より一段階太い。

**フォントの種類変更**
`font-family: serif`
フォント名を指定可能。
`font-family: "Lucida Grande"`
フォント名にスペースがある場合は、""で囲う。

**ボーダーライン**
`border: 10px solid red`
線の太さ、線の種類、線の色が指定可能。

## 背景色
`background-color: #ff0000`

## 幅
**要素自体の幅の指定**
`width: 500px`
要素の横幅をpxで指定可能。
`height: 200px`
要素の縦幅をpxで指定可能

**要素の余白(内側)の指定**
`padding: 10px`
上下左右に余白を追加可能。
`padding-top: 10px`
`padding-bottom: 20px`
`padding-left: 30px`
`padding-right: 40px`
上下左右のそれぞれの余白を指定可能。
`padding: 10px 20px 30px 40px`
短縮版。

**要素の余白(外側)の指定**
`margin: 10px`
要素の外側に余白を作ることが可能。

## リスト
`list-style: none`
リストの黒点をなくす→・これ
`float: left`
リストの並べ方を指定可能。

## 要素の表示
**表示/非表示**
`visibility: visible`
表示指定
`visibility: hidden`
非表示指定。スペースは確保される。

**表示方法**
`display: block`
ブロック要素
`display: inline`
インライン要素

## 要素の配置
`position: static`
標準配置。block要素は上から、inline要素は左詰め。
`position: relative`
相対配置。本来の位置からの指定。
`position: absolute`
絶対配置。

## テーブル
`border-collapse: collapse`
セルの線を重ねる。
`table tr:nth-child(3) td:nth-child(2) {}`
3行2列目のセルのスタイルを変更。
【Rails】ビューに<script>タグを書けば、Ruby on RailsのJavaScriptでインスタンス変数を利用できる。

## hidden_fieldを使う
・DBに無い単語を入力させなくしたかった。
・JavaScriptで動的に弾きたかった。
・社内ツールであり、セキュリティより操作性を優先できる条件だった。

以上よりビューファイルで直接scriptタグを書き、
同じファイル内でJavaScriptの変数として利用しました。


## コードのイメージ
```erb:hoge.html.erb
<% @hoges.each do |hoge| %>
<%= hidden_field, value: hoge, id: 'fuga' %>
<% end %>

<script>
var hoge = document.getElementById(fuga);
</script>
```

## 最後に
思い出しながらなので曖昧ですが、こんな感じのコードでした。
本当は他にRailに乗れる、いい方法があるんでしょうけどね。
gonというGemもあるそうなので試して見たい所。
筋肉供養 ~Special Edition~

#目次
+ はじめに
+ 機能概要
+ お手製グッズの作り方
+ QRコード
+ 感想と反省点

#はじめに
　この度、拙著の記事[[LINE BOT]今日の日焼け止めクリームを教えてくれるLINE BOTを作った](https://qiita.com/zerozeronineking/items/2c482fa707870635e80d)が、思いのほか好評を博した。
　これを受けて、自分の価値観が揺らいでしまった。
　というのも、自身の感覚として、筋肉でIoTを発信していくことで、生まれ出ずるモノがあると信じていた。実際にLINE BOTを作り、発信し、筋力と技術力を高めることで素晴らしいLINE BOTを発想、開発できると思い、日々努力してきた。しかし、ありきたりな発想しか出てこないのだ。また、拙著の記事に筋肉要素が大してないことを自覚してしまった。これでは、創造性が失われかねない。
　そこで、今まで開発したLINE BOTやLIFFを組み合わせ、一つのLINE BOTにまとめ上げた。

　一先ず、自分の方針について考え直す時が来た。

　これを**筋肉供養**と称し、新たなステージに進みたい。

#機能概要
コードについては、[GitHub](https://github.com/KumaKing009/KumaKing009.github.io)に公開しているので、参考にされたし。
※API部分は、自分のキー情報などに合わせて編集してください。

タイトル：スムージーチェッカー
[LINE BOT]
画像認識(スムージー)
リッチメニュー　実装したのみ。実装方法は[拙著の記事](https://qiita.com/zerozeronineking/items/ee1083cddd1666e93ca1)を参照されたし。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/cf509a0b-abc2-c269-f445-f15e6f620f56.png" width=50%>

[LIFF]
日焼け止めクリーム推薦ページ、ARTを感じられるページを実装。
以下画像はLIFF画面
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/6430bd39-814a-c0e5-b573-b55267ae880c.png" width=50%>

日焼け止めクリーム推薦ページ
内容は[拙著の記事](https://qiita.com/zerozeronineking/items/2c482fa707870635e80d)を参照されたし。
![<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/e014138b-f6fb-617f-c133-c5de2decb7b4.png" width=50%>

ARTを感じられるページ
内容は、Custom Visionの画像認識APIを使用した、筋肉的芸術作品識別である。
webページでは動くが、Androidでは動かない。その理由は不明。どうやら、jQueryの$がAndroidで機能しないようだが、その対処法が分からない。。。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/07cd4ca1-6bbe-13be-2285-5dd942c79b32.png" width=50%>

#お手製グッズの作り方
日焼け止めクリーム推薦ページを実装する際に、以下のようなグッズを自作した。
ビーズブレスレットについて、作るには相応の技術が必要だ。
自分は、[このサイト](https://www.rys.co.jp/tangerine/howto_br1)を参考に、下画像にあるブレスレットを作った。友人や家族とともに、交流がてら作成するのも面白い。
意外と、子供は器用だということを実感した。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/eba43041-a5e8-a5f6-42ff-9f28e2c3501b.jpeg" width=50%>
~~まぁ、すぐバラバラになったけど~~
ビーズ等の情報は、[拙著の記事](https://qiita.com/zerozeronineking/items/2c482fa707870635e80d)を参照頂くとして、キーホルダータイプも作ってみた。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/2f42e23b-34e6-ee37-68d9-ebec4de3b051.jpeg" width=50%>
この機能の要点としてUVチェックビーズがある。
これを太陽の下に曝すと色が変わり、その色の濃さで紫外線の強度を計測する。
どの様に色が変わるのかは、[この動画](https://www.youtube.com/watch?v=FVdXGVOpong&feature=youtu.be)を参照されたし。


#QRコード
宜しければお使いください。

<img width="583" alt="QRCode.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341829/e4860340-06f0-12b6-1080-ba37ad3c0b3c.png">

#感想と反省点
　今回、自作LINE BOTたちの供養と、今までの知見のまとめを兼ねてこの様なLINE BOTを開発した。新要素としてCustom Vision APIを活用したが、これがとても面白い。
少数の教師データ(必要最低数は5枚)で画像認識AIを作成できる。しかも、今なら[Azureを12ヶ月無料で使える](https://azure.microsoft.com/ja-jp/free/)ので、お試し感覚で利用するのも良いかもしれない。
ただし、Custom Vision APIは従量課金のようなので、使い過ぎには注意されたし。
　また、反省点としては、筋肉についての調査が甘かったという一言に尽きる。
筋肉を突き詰めるのであれば、ネット検索だけでなく、聞き込みやジムのスタッフに取材するなど、行動するべきだった。それをしないで筋肉LINE BOTを開発しようとしても、できるはずがない。それに、巷には筋肉に纏わるサービスやアプリケーションが多く、切り込む余地がないように思われる。それらの要因があり、今回の供養に結び付いた。
　少々ヘコむ経験をしたが、これを糧に、自身の方向性を見定め、理想のアプリケーションを開発したい。
JSの関数について。

どーもです😄

Qiita初投稿です。

良い記事を書くにはどうすればいいか？はひとまず横に置いといて、、

自分の学んだことをアウトプットしようと思います。

あくまで自分目線な記事です。。

```js
function 関数名(仮引数) {
  console.log();
}
関数名(実引数);
関数名(実引数);
関数名(実引数);
```

実引数にある文字列を仮引数へ渡したい場合、仮引数に変数を宣言すると実引数の文字列をfunction関数内で実行できる。

その場合、仮引数への変数宣言にはlet(再代入可能な変数)やconst(再代入不可能な変数)を書く必要は無く、そのまま変数名を書くことができる。

コンソールに表示させたい場合はテンプレートリテラルを使うとそれぞれの実引数で宣言した文字列を表示することができる。

この場合、仮引数で宣言した変数でも表示することができるが、テンプレートリテラル`${}`では複雑な書式でも文字列として表示できるため、便利である。

あとは、実引数は無名にした場合、仮引数に変数に値を代入するコードを書くと、それが優先されて表示されるということ。

例：

```js
function showAd(message = 'hello') {
  console.log(`${message}`);
}

showAd();
```

実行結果はhelloと表示される。

自分用のアウトプット。

読まれる記事にしていきたいな😅笑
Vueの中でclearTimeoutが効かなくてハマった話

# setTimeout()をそのまま書いては解除できない

Vueの単一ファイルコンポーネント内で`setTimeout()`、`clearTimeout()`を使う機会があったのですが、`clearTimeout()`が効かなくて2時間ほどハマってしまいました。

## clearTimeout()で解除できない例

下記スクリプトでは解除されず、`hoge`と表示されます。

```vue:test.vue
<script>
const timer = setTimeout(() => {
  console.log('hoge');
}, 1000);

clearTimeout(timer);
</script>
```

## window. を付ければ解除できる

下記のように`window.`を付ければ解除できます。
こんな単純なことに2時間もハマって悔しい……！

```vue:test.vue
<script>
const timer = window.setTimeout(() => {
  console.log('hoge');
}, 1000);

window.clearTimeout(timer);
</script>
```
【Electron】nodeIntegration: falseのまま、RendererプロセスでElectronのモジュールを使用する

React + Redux + Electronでデスクトップアプリを開発していた際に、Rendererプロセス（React）の以下のコードで`Uncaught ReferenceError: require is not defined` が出て詰まってしまいました。

```
import { ipcRenderer, remote } from 'electron';
```

# 原因
ノードインテグレーションが無効だから。

Electronのバージョン5系では、`nodeIntegration`のデフォルト値`false`なっていたからでした。

# nodeIntegrationとは？

XSS対策のためのオプションで無効(`false`)にすることで、RendererプロセスからNode.jsの機能へのアクセスを制限することができます。

そのため、Rendererプロセス（React）で`require`関数が呼べずに`Uncaught ReferenceError: require is not defined`が出てしまってたようです。

ネットで検索すると、普通にimportできるような記述をみますが、

- Electronの古いバージョンでの話（昔はデフォルトtrueだったらしい）
- `nodeIntegration: true` にしている

のどちらかだと思います。


【参考】
Electron公式ドキュメント[Do not enable Node.js Integration for Remote Content](https://electronjs.org/docs/tutorial/security#2-do-not-enable-nodejs-integration-for-remote-content)

# 対応策
対応策は２つあります。

1. ノードインテグレーションを有効にする
2. preloadを使う

## 1. ノードインテグレーションを有効にする
オプションを`true`にするだけです。

```js

mainWindow = new BrowserWindow({
  width: 1000,
  height: 800,
  webPreferences: {
    nodeIntegration: true, // ココ
  },
});
```

### 有効にして良いの？

ElectronでXSS攻撃を受けた場合、ユーザのPCのデータも操作されてしまう危険もあるので、`false`のままにしておいた方が安全です。

ローカルで完結するようなアプリの場合は、`true` にしても良いと思いますが、
データベースからユーザが入力したテキストを表示するなど、リモートコンテンツを表示する機能がある場合には意識した方が良いでしょう。


## 2. preloadを使う

ノードインテグレーションを有効にしたくない場合には、preloadを使いましょう。

preloadとは、他のスクリプトが実行される前にロードするスクリプトを指定できるオプションで、指定したスクリプト内では、Node.jsのAPIにアクセスできます。

そのため、以下のようにwindowオブジェクトなどに使用したいモジュールをセットできるのです。

```js

new BrowserWindow({
  width: 1200,
  height: 800,
  webPreferences: {
    nodeIntegration: false,
    preload: `${__dirname}/preload.js`, // 読み込みたいjsファイルのパス
  },
});

// 以下preload.jsの内容
window.ipcRenderer = require('electron').ipcRenderer;
window.remote = require('electron').remote;
```

このようにしたら、あとは、Rendererプロセスで`window.ipcRenderer`を呼び出すだけです！！

【参考】

- Electron公式ドキュメント[BrowserWindow](https://electronjs.org/docs/api/browser-window#new-browserwindowoptions)
- https://github.com/electron/electron/issues/9920#issuecomment-336757899
DockerでPHP開発環境を作ってみました

ブログの同一記事
https://guldra-cranch.hatenablog.com/entry/2019/09/03/225213

# リポジトリ
https://github.com/cranch-crown/php_test

# 目的
* 業務でDockerを使わないため、Dockerを使った開発を個人で経験する
* Data Volumeの理解を進める
* 今後、個人で開発＆運用するための基盤にする

# 構成コンテナ
* PHP-FPM
* nginx
* MariaDB

# ディレクトリ構成
```
.
├── app
├── docker
|    ├── mysql
|    |    └── my.cnf
|    ├── nginx
|    |    ├── Dockerfile
|    |    └── fpm.conf
|    └── php
|         ├── Dockerfile
|         └── php.ini
├── logs
|    ├── mysql
|    ├── nginx
|    └── php
├── .env
└── docker-compose.yml
```

# docker-compose.yml
```docker-compose.yml
version: "3"

services:
  php-fpm:
    build:
      context: ./docker/php
      args:
        - TZ=${TZ}
    ports:
      - 9000:9000
    volumes:
      - ./app:/var/www/html
      - ./logs/php:/var/log/php
    working_dir: /var/www/html
    environment:
      - TZ=${TZ}

  nginx:
    build: ./docker/nginx
    depends_on:
      - php-fpm
    ports:
      - 80:80
    volumes:
      - ./app:/var/www/html
      - ./logs/nginx:/var/log/nginx
    working_dir: /var/www/html

  db-mariadb:
    build: ./docker/mysql
    volumes:
      - db-store:/var/lib/mysql
      - ./logs/mysql:/var/log/mysql
    environment:
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASS}
      - MYSQL_ROOT_PASSWORD=${DB_PASS}
      - TZ=${TZ}

volumes:
  db-store:
```

# こだわった点
* Data Volumeを使う
* MariaDBを使う
* TimeZoneをJSTにする

**Data Volumeを使う**

目的にも書きましたが、Data Volumeの理解を進める目的で今回このdocker-composeとDockerfileを書きました。`docker volume ls`や`docker volume rm`などのコマンド、Data Volumeの性質などの理解が深まりました。

**MariaDBを使う**

正直なところMariaDBとMySQLのどちらが優れているという判断は筆者は出来ません。しかし、MySQLのオリジナルのソースコードの作者がMariaDBの作者である事実と、MariaDBがOSSであることの2つの理由からMariaDBを扱っておくことにはOSSを扱うことに慣れるという意味を含んでいると判断し、今回の構成にしました。

**TimzoneをJSTにする**

コンテナ技術をより深く理解するために、JSTに設定するタスクは最適でした。筆者の開発環境がWindowsホストのためパーミッションの問題にぶち当たり、Linuxとの差を実感しつつWindows機で開発する時の注意点を実感できました。

# 今後の目標
今回のdocker-composeを更に開発し、個人的に開発するWebアプリケーションの基盤としたいという思惑があります。そのため、今後Laravelやredisなどをcompose、コンテナに追加していく予定です。

# 参考にさせていただいた記事

https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4

https://qiita.com/yugui/items/517480f4383b893e092e

https://qiita.com/gounx2/items/23b0dc8b8b95cc629f32:embed

今後とも個人での学習を継続していこうと思います！
【Django】ForeiginKey型のデータをCSVからインポートしようとした時に出たエラー

## はじめに
Djangoを使ってお酒のECサイトを作っています。
商品のデータをCSVでインポートしようとした際にエラーと戦ったので、その時に調べた解決策を書いた記事になります。

Django2 
PostgreSQL

## やりたかったこと
インポートする前に2つのテーブルを作成した。
一つは商品の分類をするCategoryテーブル。もう一つは商品情報のProductテーブル。

```python:models.py
#Metaタグなどは省略
class Category(models.Model):
    name = models.CharField(max_length=250, unique=True)
    slug = models.SlugField(max_length=250, unique=True)
    description = models.TextField(blank=True)
    image = models.ImageField(upload_to='category', blank=True)

class Product(models.Model):
    name = models.CharField(max_length=250, unique=True)
    slug = models.SlugField(max_length=250, unique=True)
    description = models.TextField(blank=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)#★今回問題のやつ★
    price = models.IntegerField()
    image = models.ImageField(upload_to='product', blank=True)
    stock = models.IntegerField()
    available = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True, null=True)
```

インポートしたいCSVファイルは以下。

1. Category.csv

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311743/e7c800b4-c6fa-a41a-b313-de3f33618506.png)
2. Product.csv
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311743/c2b193b7-9530-cb61-4e31-d70840083818.png)

このCSVファイルをインポートしてテーブルに入れることが目標

## 出てきたエラー

まずはCategory.csvをインポートした。

```
practice_db=> \copy shop_product (name,slug,description,image) FROM 'path/to/Category.csv' (DELIMITER ',', FORMAT CSV, ENCODING 'UTF8', HEADER);
COPY 3 #正常にインポート
```

次にProduct.csvをインポートをしようとするとエラーが出た。

```
practice_db=> \copy shop_product (name,slug,description,category,price,image,stock,available,created) FROM 'path/to/Product.csv' (DELIMITER ',', FORMAT CSV, ENCODING 'UTF8', HEADER);
ERROR:リレーション"shop_product"の列"category"は存在しません
```

## 解決方法
エラーが出た時にインポートしようとしたProduct.csvのcategoryのデータにはCategory.csvのnameの値が入っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311743/e7c800b4-c6fa-a41a-b313-de3f33618506.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311743/c2b193b7-9530-cb61-4e31-d70840083818.png)

これをnameの値で指定するのではなく、Categoryのidで指定しないとエラーが出てしまう。
さらに、カラム名をcategoryではなくcategory_idと変更する。
変更後のProduct.csvファイルは以下。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311743/a8dad367-7262-fa3e-e5b2-a7e296dc9918.png)



どうやら、ForeiginKey型のデータにはidが入る決まりらしい。
よく考えたら、Categoryのnameではなく、絶対に重複しないidで指定するべきだなと思った。



## 参考サイト
[DjangoでcsvファイルをアップロードしてDBにレコードを追加する方法](https://intellectual-curiosity.tokyo/2018/12/19/django%E3%81%A7csv%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E3%81%97%E3%81%A6db%E3%81%AB%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E8%BF%BD/)
コントローラ内でどのアクションに対しても一定の前処理をする

# コントローラ内でどのアクションに対しても一定の前処理をする
## アクション・コールバック
「ログインしているユーザーにだけ特定のコンテンツを表示したい」
みたいな時に使えるのがアクション・コールバック。

### 【要点】
コントローラ１で定義したアクションを、コントローラ２のはじめに呼び出す。

```ruby:sample1_controller.rb
class Sample1Controller < ApplicationController
  
  before_action :do_something

  private def do_something
     #アクションが実行される前に行う処理
  end

end
```

```ruby:sample2_controller.rb
class Sample2Controller < ApplicationController
  
  before_action :do_something

  def index
     #省略
  end      

end
```

(随時更新　2019/09/14)
取扱代理店が語らないRPAで最も重要な事

最近、セミナーに出席したり顧客訪問をしたりして、RPA導入済み企業の話を直接聞く機会があった。
事例として登壇したり訪問を受けたりするくらいだから、ある程度うまくいっている企業だと思われるのだが、そこで担当者が口々に話をするのは、**「導入に何に最も重点を置いて検討すべきか」**あるいは**「(当時は検討事項を見誤ったけれども)本来何を最優先で検討すべきだったか」**ということである。

>導入前は、ついつい**「ロボットができることの機能比較」**や**「ロボットを開発する環境の生産性」**に目が行ってしまい、これらの比較を中心に行ってしまいがちなのだが、導入してみると、本当に重要なのは**「ちゃんと運用管理できるのか」**であるというようにどの担当者も言っていた。

そして、これはRPA取扱代理店からはなかなか語られない話でもある。なぜなら彼らは運用管理は彼らに任せてもらって、**外注費用、保守費用で継続的にお金を取りたいのが本音**だからである。

運用管理をきちんと行うには、**サーバ型のRPAを導入**し、**社内の体制 (COE) をきちんと作ってRPA適用業務や方法の統制を図り**、導入開始後の**継続的な外注費用を抑える**必要がある。特に開発や運用が社内でできず、外注費用が削れずにコストがコントロールできなくなってしまっているケースもあるようである。

重要な事なので、もう一度書くが、RPAプロジェクトで本当に重要なのは**「ちゃんと運用管理できるのか」**であり、これは取扱代理店からはあまり語られない。

こちらもご参考まで。

* [サーバ型を前提にした時のRPAの最小導入費用](https://qiita.com/spaces/items/64ecdb7a8e3316f19386)
* [RPAに適した業務、適さない業務](https://qiita.com/spaces/items/056922dc7f53310a1cee)
* [【RPA】フロー系とリスト系のメリット、デメリット](https://qiita.com/spaces/items/6c6cfc5f9fd3602fac4d)
GoでCLIツールを作成してRaspberryPiで実行する

## やりたいこと
GoのCLIツールを作成してRaspberryPi上でとりあえず動かす。

IoT的な仕事が今後増えそうなので、クロスコンパイルが簡単なGoで手順を確立しておけばいろんな環境で動くツール作成に役立つのではないかという思い。

## 使う環境
＜ビルド環境＞
　Windows　　:Windows10
　WSL　　　　:ubuntu18.04 LTS(転送に使うrcp用)

＜実行環境＞
　ハード　　　:Raspberry pi 3 Model B
　OS　　　　　:2019-07-10-raspbian-buster-full

＜前提＞
　WindowsとRaspberryPi間でSSH接続できる環境であること

## 手順
1. 使うパッケージをインストールする
2. ツールを作成する
3. ビルドする
4. RaspberryPiに転送する

### 1. 使うパッケージをインストールする
今回は初心者かつ勉強用なので深く考えずにググってすぐに出てきたものを使う。
spf13/cobraというパッケージが有名そうなので、これを使う。


```
go get github.com/spf13/cobra
```

＃最近はcobraが人気っぽいけど、他にもフレームワークはいっぱいあるみたいなので、時間があったらいろいろ試してみる。

### 2. ツールを作成する
下記のサイトを参考にとりあえず動くものを作る。
わかりやすくまとめていただいて感謝。
https://qiita.com/usk81/items/df68a00c898b145faee5

### 3. ビルドする
(1) RaspberryPiのアーキテクチャを確認する(RaspberryPi上)

```
$ uname -m
armv7l
```

(2) クロスコンパイル設定を行う(Windows コマンドプロンプト上)

```
set GOOS=linux
set GOARCH=arm
set GOARM=7
```

(3) ビルドする(Windows コマンドプロンプト上)

```
go build -o [バイナリ名]

(例)　go build -o test_cli_tool
```

### 4. RaspberryPiに転送する
WSL上で下記コマンドを投入する。

```
rcp [バイナリ名] [ラズパイのユーザ名]@[RaspberryPiのIPアドレス)]:[RaspberryPi上のディレクトリ]

(例)　rcp test_cli_tool hogeuser@192.168.0.1:~/work
```

何も考えずに実行したら
(サブコマンドを"HelloCli"にしました)

```
~/work/test_cli_tool HelloCli
```

動いた！簡単だ～～

```
HelloCli was executed
```

## 参考サイト
+ cobraでのツール作成
https://qiita.com/usk81/items/df68a00c898b145faee5
+ クロスコンパイルの方法
https://qiita.com/bamchoh/items/2d21cbbfed393e47fed2
クロージャとしての関数(Swift)

##関数はクロージャの一種？
関数はクロージャの一種であり、そのためクロージャとしての利用が可能です。
関数をクロージャとして利用するためには、事前に定義した関数の関数名だけを参照します。つまり、　変数や定数に関数名を代入することでクロージャとして扱うことができます。また、前の記事でも述べたとおり「クロージャとしての関数」を別の関数の引数に渡すことも可能です。

##定義方法・使い方

**基本定義**

```
//定数に関数名を代入することで、定数名を呼び出した際に代入された関数が呼び出されます。
let 定数名 = 関数名
```
普通のクロージャのように定数名などに関数を代入するだけで、定義できます。
**引数有りver**

```
//引数名まで含めて定義が可能
let 定数名　= 関数名(引数名1:引数名2:)
```
上記のように引数名込みでの定義も可能です。このような記述は、引数名で他の関数との差別化を測りたい時などに有効です。

**型推論**

```
func half(_ x:Int) -> Int {
    return x / 2
}
let function = half  //(Int) -> Int型が省略されている
```
上記のように代入する関数に再度型を指定し直さなくても、型推論で予想してくれます。

##実用例
###クロージャとしての関数を引数に指定しない場合
**1 関数を定義しない場合**

```
let numbers1 = [1,2,3]
let doubleNumbers1 = numbers1.map { $0 * 2 }
doubleNumbers1

//実行結果
[2, 4, 6]

let numbers2 = [4, 5, 6]
let doubNumbers2 = numbers1.map { $0 * 2 }
doubleNumbers2

//実行結果
[8, 10, 12]
```
**2 関数を定義する場合**

```
func double(_ x: Int) -> Int {
   return x * 2
}

let numbers1 = [1,2,3]
let doubleNumbers1 = numbers1.map(double)

//実行結果
[2,4,6]

let numbers2 = [4,5,6]
let doubleNumbers2 = numbers2.map(double)

//実行結果
[8,10,12]
```

以上に実際に関数をクロージャとして使った場合と使わない場合のコードを記述しました。
このように関数をクロージャとして用いることで、**{$0 * 2}**の処理を関数でまとめることができ、可読性を高めることができました。

##最後に
今回は関数をクロージャとして用いるための方法と簡単な利点について紹介しました。
自分用メモなため雑な面あるので、ご了承ください。
gitでrevertしたら再revertが必要な例とその理由

[https://qiita.com/taisa831/items/c17ce15818b9f8fa26b8:title]

こちらの記事を読んで、「何が起きるか」はわかったけど「なぜこうなるか」がすぐに分からなかったのでメモ。

### 具体例

以下の例を考える。

- masterブランチからdevブランチを切った。
- devブランチでb.txtを追加してコミットを積んだ。
- masterブランチでc.txtを追加してコミットを積んだ。
- masterブランチにdevブランチをマージした。
- devブランチでの変更点に不具合があったことが判明し、masterでdevのマージコミットをrevertした。

```
* 6589fe9 (HEAD -> master) Revert "Merge branch 'dev'"
*   c7e7528 Merge branch 'dev'
|\
| * 30f185a (dev) added b.txt
* | 5169671 added c.txt
|/
* 18f28e9 added a.txt
```

### 問題が発生するパターン

- devブランチにパッチを当てて（d.txtを追加して）コミットを積んだ
- devブランチを再度masterにマージした

```
*   436c043 (HEAD -> master) Merge branch 'dev'
|\
| * ddf8924 (dev) added d.txt  # commit 1
* | 6589fe9 Revert "Merge branch 'dev'"  # commit 2
* |   c7e7528 Merge branch 'dev'
|\ \
| |/
| * 30f185a added b.txt  # commit 3
* | 5169671 added c.txt
|/
* 18f28e9 added a.txt
```

ここでマージ後のmasterがどうなっているかというと…

```
% git checkout master
% ls
a.txt	c.txt	d.txt
```

当初devブランチで追加したb.txtが見当たらない。

### 問題が発生する理由

- 上記のcommit 1とcommit 2をマージするときに、マージベースはcommit 3となる。
- commit 3からcommit 1にかけての差分は「d.txtを追加した」こと
- commit 3からcommit 2にかけての差分は「なし」(b.txtが追加され、削除された)
- commit 3ではa.txt, b.txtが存在したので、それに上記2つの差分を足して実現するのは、a.txt, b.txt, d.txtが存在する状態

### 問題を回避するやり方

いずれにせよrevert以前の内容が必要なら、revertをrevertすべし。

###### devブランチをそのまま伸ばす

- devブランチにmasterをマージする
- devブランチでrevertをrevertする
- devブランチにパッチを当てて（d.txtを追加して）コミットを積む
- devブランチを再度masterにマージする

```
*   3a746ec (HEAD -> master) Merge branch 'dev'
|\
| * e3cf889 (dev) added d.txt
| * 498e552 Revert "Revert "Merge branch 'dev'""
| *   c440eb6 Merge branch 'master' into dev
| |\
| |/
|/|
* | 6589fe9 Revert "Merge branch 'dev'"
* |   c7e7528 Merge branch 'dev'
|\ \
| |/
| * 30f185a added b.txt
* | 5169671 added c.txt
|/
* 18f28e9 added a.txt
```

こうすれば、当初devブランチで作成したb.txtも最終的にmasterブランチに残る。

```
% git checkout master
% ls
a.txt	b.txt	c.txt	d.txt
```

###### ブランチを切り直す

- masterブランチからdev2ブランチを切り直す
- dev2ブランチでrevertをrevertする
- dev2ブランチにパッチを当てて（d.txtを追加して）コミットを積む
- dev2ブランチをmasterにマージする

```
*   ea16e7a (HEAD -> master) Merge branch 'dev2'
|\
| * a87d323 (dev2) added d.txt
| * 98c5d6f Revert "Revert "Merge branch 'dev'""
|/
* 6589fe9 Revert "Merge branch 'dev'"
*   c7e7528 Merge branch 'dev'
|\
| * 30f185a (dev) added b.txt
* | 5169671 added c.txt
|/
* 18f28e9 added a.txt
```

この方法でも、当初devブランチで作成したb.txtが最終的にmasterブランチに残る。

```
% git checkout master
% ls
a.txt	b.txt	c.txt	d.txt
```
PostgreSQL関連の参考URL

個人用のメモです。
僕が初学者なので、初学者の人が読んでわかるリンクを載せています。
日々更新します。
世の中に発信してくれている人達のおかげで僕もコツコツ作品作れます。
ありがとうございます。

- *前のレコードとの差分を出したい*

[http://everything-you-do-is-practice.blogspot.com/2017/09/postgresql-lag-lead.html](http://everything-you-do-is-practice.blogspot.com/2017/09/postgresql-lag-lead.html)

- *日付取得する*

[https://zukucode.com/2017/11/postgresql-date-add.html](https://zukucode.com/2017/11/postgresql-date-add.html)


- *serial型があるテーブルにCOPYコマンドを使いたい*

[https://teratail.com/questions/163329](https://teratail.com/questions/163329)
Django メソッド ~アプリ作る時に調べたやつをメモしています~

## はじめに
DjangoでECサイトを作成する際に知らなかったメソッドを調べた。


## 調べたメソッド---現在作成途中---
### get()
オブジェクトが一つのときに使う。
なので、主にパラメーターにはpkまたはslugが入る。
オブジェクトが無いor複数のオブジェクトが存在するときはエラー

### filter()
パラメーターで指定した条件を満たすオブジェクトをリストで返す。
複数のオブジェクトを取ってくることを想定しているので、pkやslugは入らない。

### get_object_or_404()
get()と似ている。
存在しない場合は django.http.Http404(例外)を返し、複数存在する場合はMultipleObjectsReturned(これまた例外)を返す。

### get_list_or_404()
filter()と似ている。
リストが空の場合、django.http.Http404(例外)を返す。
try,exceptで条件分岐?

```python
c_page = get_object_or_404(Category, slug=c_slug)
```
https://djangoproject.jp/doc/ja/1.0/topics/http/shortcuts.html#get-object-or-404

**疑問**

```python
objects = ModelName.objects.filter()
objects = ModelName.objects.all().filter()
```
の違いは何か?
**調べた結果**
基本.all()はいらない。
 all() が必要となるのはルートクエリセットから全てのオブジェクトを取り出 したい場合だけ。
と言われても…ん?って感じ。
[参考URL](https://djangoproject.jp/doc/ja/1.0/topics/db/queries.html#id6)


### reverse()
urlを生成するメソッド

```python
from django.urls import reverse
reverse('shop:products_by_category', args=[self.slug])
```
の場合は`shop/products_by_category/self.slug`を生成
[公式ドキュメント(まだ和訳されてない)](https://docs.djangoproject.com/ja/2.2/ref/urlresolvers/#reverse)

## 調べてる途中に見つけた参考になりそうなサイト
[Modelからデータを取り出す方法まとめ](https://yaruki-strong-zero.hatenablog.jp/entry/django_model_lookup)
[Model-データアクセスの基礎](https://python.keicode.com/django/model-data-access-basics.php)
[クエリセットとは](https://codor.co.jp/django/about-queryset)
[データベースの検索](https://qiita.com/okoppe8/items/66a8747cf179a538355b#検索する)
[]()
[]()
[]()
[]()
[]()
[]()
[]()