OmniAICreator/Qiita-1.07M huggingface dataset:
RasPi でNゲージ模型

ラズパイでNゲージ模型を制御してみる

《やりたいこと》
・電車のON/OFF - 2019/11月 完了
・電車のスピードを変えたい - 2019/11月 完了
・電車の前進／後進を変えたい - 2019/11月 完了
・Python つかって制御したい - 2019/11月 完了
・自動運転したい - 2019/12月 完了
・Nゲージ制御サーバ（TCP/IPパケット通信)にしたい（コマンドを受け取って上記を実行）-未
・電車通過センサーを自作したい- 2019/11月 完了
・ポイントを切り替えたい- 2019/11月 完了
　→ポイント切り替えは別回路にすることを検討中 12V対応 PWM以外のモータドライバ
・スピードと通貨センサをキャラLCD表示したい - 2019/12月 完了
・温度センサ:(ADT7310 spi)で温度を測りたい - 2019/11月 完了
・通過、ポイント切り替えを含めた自動運転をしたい-未

《部品》
・Raspberry Pi
 ※Pi 2 Model B 以上。下記のモジュール基板を使うから
・MC33926搭載デュアルモータードライバ for Raspberry Pi_PWM
　※スイッチサイエンス
　コード番号:POLOLU-2756
　税込単価 4,609 円
・ACアダプタ DC 出力12V 1000mA
　※家に転がってたACアダプタを使用した

【デメリット】
値段が高い
【メリット】
モーター2個別々にスピ―ド制御できる
前進、後進ができる
PWM なのでI2C,SPIとか面倒なインタフェースがいらない
Nゲージの電源に市販のACアダプタ12Vが使える
Nゲージでありがちな電源ショートに回路で対応している
RasPiコネクタにのっけるだけで配線がいらない
Python で制御できる
![IMG_0618.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531059/d2b34545-8a9c-d80a-9933-a09bee1af778.jpeg)
![IMG_0617.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531059/f0176bcf-3d5e-f5a4-fd71-4eb96748a83a.jpeg)
![IMG_0619_2.jpg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531059/6e8a176d-0a1d-ecd1-cf47-cd7f296ffc8e.png)
![IMG_0620_2.jpg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531059/aa57e751-36f7-5a4e-86d6-cb6b8e0cc038.png)
自分用ngrokをauthtoken対応にする(self hosted ngrok)

#はじめに
前回、[自分用ngrokを構築する(self hosted ngrok)](https://qiita.com/kmitsu76/items/6cd8b3217c9adad77812)でドメイン取得し、自分専用のngrokを立ち上げたが、もともとのソースではngrokクライアントに対する認証が無い状態だった。
これでは、不特定のngrokから接続できる状態でセキュリティ上まずい。

ngrokクライアントから渡せるauthtokenを使ったクライアント認証を実装したい。

#どう実現するか
すでに実現した例が紹介されているので、下記を参考にする。
[Linux搭建Ngrok服务器及身份认证实现内网穿透](https://studygolang.com/articles/15122)

#改修ポイント
サーバーの下記コードを改修し、authtokenを受けるようにする。
ngrok/src/ngrok/server/control.go

```
diff -up ../ngrok/src/ngrok/server/control.go src/ngrok/server/control.go

--- ../ngrok/src/ngrok/server/control.go        2019-10-30 18:45:30.153107856 +0900
+++ src/ngrok/server/control.go 2019-11-12 05:20:31.559657500 +0900
@@ -10,6 +10,8 @@ import (
        "runtime/debug"
        "strings"
        "time"
+       "os"
+       "bufio"
 )

 const (
@@ -82,6 +84,37 @@ func NewControl(ctlConn conn.Conn, authM
                ctlConn.Close()
        }

+
+
+
+       readLine := func(token string, filename string) (bool, error) {
+       if token == "" {
+               return false, nil;
+       }
+       f, err := os.Open(filename)
+       if err != nil {
+            return false, err
+       }
+       buf := bufio.NewReader(f)
+       for {
+               line, err := buf.ReadString('\n')
+               line = strings.TrimSpace(line)
+                       if line == token {
+                               return true, nil
+                       }
+                       if err != nil {
+                               if err == io.EOF {
+                                       return false, nil
+                               }
+                       return false, err
+                       }
+               }
+               return false, nil
+       }
+
+
+
+
        // register the clientid
        c.id = authMsg.ClientId
        if c.id == "" {
@@ -101,6 +134,13 @@ func NewControl(ctlConn conn.Conn, authM
                return
        }

+       authd, err := readLine(authMsg.User, "authtokens.txt")
+
+       if authd != true {
+       failAuth(fmt.Errorf("authtoken %s invalid", "is"));
+       return
+       }
+
        // register the control
        if replaced := controlRegistry.Add(c.id, c); replaced != nil {
                replaced.shutdown.WaitComplete()
```

#設定
ngrokdを実行するディレクトリにauthtokens.txtを作り、トークンを書き込む。
自分の場合は、適当な文字列をSHA512ハッシュにして配置した。

#接続

クライアント側の設定ファイル.ngrokへ、auth_token行を追加し、設定したSHA512列を記入し起動、接続できればOK。
Vue.js + axios でヘッダーにログイン情報を毎回セットする。

plugin を自作して axios の create() と interceptors() を使ってラップした http plugin を作ると良いかもしれません。

~~~src/plugins/http.ts
import _Vue from 'vue';
import axios from 'axios';

export default {
  install(Vue: typeof _Vue): void {
    const http = axios.create({
      // URL は環境変数とかで変えられるにする
      baseURL: 'http://localhost:3000/',
      timeout: 10000,
    });
    http.interceptors.request.use((config: any) => {
      // $stores.auth.show に認証情報が入っているとする
      config.headers = Vue.prototype.$stores.auth.show;
      return config;
    });
    Vue.prototype.$http = http;
  },
};
~~~

Typescript で書いているため、上記 plugin の型ファイルを *.d.ts という拡張子にしてどこかに置きます。

~~~src/types/http.d.ts
import Vue from 'vue';
import { AxiosStatic } from 'axios';

declare module 'vue/types/vue' {
  interface Vue {
    $http: AxiosStatic;
  }
}
~~~

あとは main.ts のどこかに下記を書きます。
すると、自作 plugin が使えるようになります。

~~~src/main.ts
// 略

import http from '@/plugins/http';
Vue.use(http);
~~~

認証情報の store はこんなイメージです。
vuex-module-decorators を使っています。

~~~src/stores/AuthStore.ts
import Vue from 'vue';
import { Module, Mutation, VuexModule } from 'vuex-module-decorators';
import LoginInterface from '@/interfaces/LoginInterface';
import { AuthStoreInterface } from '@/interfaces/StoresInterface';
import { AuthResponseInterface, ErrorResponseInterface } from '@/interfaces/ResponseInterface';

@Module({ name: 'auth' })
export default class AuthStore extends VuexModule implements AuthStoreInterface {
  public token = '';
  public user_id  = 0;

  public get show(): object {
    return {
      Authorization: `Token ${this.token}`,
      'User-Id': this.user_id,
    };
  }

  @Action
  public create(users: LoginInterface): void {
    Vue.prototype.$http.post('/users/auth', { user: users })
    .then((res: AuthResponseInterface): void => {
      this.set_token(res.data.token);
      this.set_user_id(res.data.id);
    })
    .catch((err: ErrorResponseInterface): void => {
      // エラー処理
    });
  }

  @Mutation
  private set_token(token: string): void {
   this.token = token;
  }

  @Mutation
  private set_user_id(user_id: number): void {
    this.user_id = user_id;
  }
}

~~~

そうすると Store 内で`Vue.prototype.$http.get()`や`Vue.prototype.$http.post()`すると AuthStore のログイン情報を毎回見に行ってくれます。
vue ファイルから呼び出す際は `this.$http.get()`や`this.$http.post()`でリクエストできます。

もし vuex-persist を使っていれば、リロードしても消えません。
LDCで無限ループが動かなくて困ったとき

(2023/12/14追記: LLVM12 で https://reviews.llvm.org/D95288 の修正が入ったためにこの記事の内容は古くなっています。同様の内容を出力したい場合はinfiniteLoop関数に`@llvmAttr("willreturn")`属性を付与することで未定義動作を楽しむことができます。

```d
import ldc.attributes;

@llvmAttr("willreturn")
ubyte infiniteLoop()
{
    for (;;) {  }
}

void main()
{
    auto x = infiniteLoop();
}
```

llvm irの出力:

```console
ldc2 -O3 --output-ll infiniteloop.d
```

```llvm
(...)
; [#uses = 0]
; Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none) uwtable
define zeroext i8 @_D12infiniteloop12infiniteLoopFZh() local_unnamed_addr #0 {
  unreachable
}

; [#uses = 1]
; Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none) uwtable
define i32 @_Dmain({ i64, { i64, i8* }* } %unnamed) #1 {
  unreachable
}
(...)
```

)

## 以下、古い内容の記事

みなさんもLDCで無限ループを含む関数を使っている場合、最適化フラグを渡していると予期しない挙動となることがよくあるんじゃないかと思います。

```d
ubyte infiniteLoop()
{
    for (;;) {  }
}

void main()
{
    auto x = infiniteLoop();
}
```

```console
$ ldc2 -version| head -1
LDC - the LLVM D compiler (1.18.0):
$ ldc2 -O3 -run infiniteloop.d  # 本来は無限ループなので返ってこないことを期待
Error: /tmp/infiniteloop-b2ee371-8ab556 failed with status: 1
```

これはLLVMが最適化を行った結果として空のループを未定義動作にしてしまうのが問題なのですが、ときには困ることもあるわけです。

じゃあどうすればいいかというと、まさにその状態を回避するためにある[`llvm.sideeffect`](https://llvm.org/docs/LangRef.html#llvm-sideeffect-intrinsic)を使うことで回避できます。

```d
pragma(LDC_intrinsic, "llvm.sideeffect")
void llvm_sideeffect();

ubyte infiniteLoop()
{
    for (;;) {
        llvm_sideeffect();
    }
}

void main()
{
    auto x = infiniteLoop();
}
```

ちゃんとループが動いてますね。

```console
$ ldc2 -O3 -run infiniteloop.d
(...) # 諸君らの環境でも無限ループが実行されているはずだ
```
Scalaで日時の範囲を表すクラス群をつくる

# Scalaで日時の範囲を表すクラス群をつくる
## きっかけ
Javaで開発をしていて、日時の範囲を表すクラスがなかったので少し不便に感じました。`java.time.Period`と`java.time.Duration`は範囲というより2点間の距離に関心があるクラスなので違うんですよね。
よく使いそうなので私的メモとして残しておきます。

## 基底クラス
本筋とはそれますが、`java.time.LocalXxx`のラッパーも用意しました。始端、終端をラッパークラスにするイメージです。

### 日時を表すTrait

継承先クラスは型引数で受け取り、内部で保持する値の型はtypeで受け取るというダブルスタンダードになりました。継承先クラスの情報を型引数で受け取っている理由は、`Ordered`を継承する際に型引数を指定する必要があったからです。この型に大小関係がなければ、この型を始端と終端にした範囲という概念があり得ないと考えたのでTraitでOrderedを継承しました。

```Chronology.scala
trait Chronology[ClassType <: Chronology[_]] extends Ordered[ClassType]{
  type ValueType //LocalTimeとかが指定される想定

  val value: ValueType

  def isAfter(other: ClassType): Boolean

  def isEquals(other: ClassType): Boolean

  final def isAfterOrEqual(other: ClassType): Boolean = isAfter(other) || isEquals(other)

  def isBefore(other: ClassType): Boolean

  final def isBeforeOrEqual(other: ClassType): Boolean = isBefore(other) || isEquals(other)
}
```

### 範囲を表すTrait
日時の型を受け取り、受け取った型を始端と終端にもつTraitです。
始端と終端の大小関係を事前条件として指定しています。

```ChronologyRange.scala
trait ChronologyRange {
  type ChronologyType <: Chronology[_]

  type ClassType <: ChronologyRange

  val start: ChronologyType

  val end: ChronologyType

  require(start <= end)

  def overlaps(other: ClassType): Boolean
}
```

## 使い方

### 例:Date

```Date.scala
case class Date(value: LocalDate) extends Chronology[Date] {
  override type ValueType = LocalDate
  def toInstant: Instant = value.atStartOfDay(ZoneId.systemDefault()).toInstant

  def isAfter(other: Date): Boolean = value.isAfter(other.value)

  def isBefore(other: Date): Boolean = value.isBefore(other.value)

  override def isEquals(other: Date): Boolean = value.isEqual(other.value)

  override def compare(that: Date): Int = value.compareTo(that.value)
}
```

```DateRange.scala
case class DateRange(start: Date, end: Date) extends ChronologyRange {
  override type ChronologyType = Date
  
  override type ClassType = DateRange

  override def overlaps(other: DateRange): Boolean = ???
}
```

## 学び
+ Traitにもフィールドを宣言できること
+ Traitにもイニシャライザを書けること
+ Orderedを継承したクラスのインスタンス同士を不等号で比較できること

## あとで調べること
+ typeとtype parameterってどう違うの
+ TraitとAbstract Classってどう使い分けるの
EC-CUBE4で会員データを大量に作成する

###環境
・EC-CUBE4.0.3
・PostgreSQL10

##はじめに
EC-CUBEで会員データや商品/受注データを大量に作るときには、EC-CUBE3系の頃から[nanasessさん](https://qiita.com/nanasess)作成の Fakerを使った` GenerateDummyDataCommand ` コマンドに大変お世話になっています。
基本的に言って、` GenerateDummyDataCommand `で事足りますが、今回は別の方法で、50万件、100万件の会員データをサクッと作る方法を載せます。

###概要
50万件の会員データを作るということは、50万行のCSVファイルを作り、' \COPY 'コマンドを流す(PostgreSQLの場合)ということに帰着します。
今回は、数万のファイルもすぐに書けるPythonでCSVファイルを作ります。

##Google Colaboratoryでの実行
Jupyter Notebookのコードは[こちら](https://colab.research.google.com/drive/1PoTuI9iGbjwW8mDYInLSRxw9ksridKVf)になります。
Playgroundで開く をクリックし、「ドライブにコピー」 のリンクを押すと各自の環境で実行できます。

![jupyter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51562/a605aa8f-3dbb-bc50-33ab-427a0d1af510.png)

##Jupyter Notebookの流れ

```python:ec-cubecreatecustomer.ipynb
# まずはインポート
import numpy as np
import pandas as pd
import random, string
```
この辺はいいですねｗ Google Colabで最後にCSVをダウンロードするための` files `もこの後インポートしています。

```python:
sample_customer_ja = pd.DataFrame([
["髙﨑","棗","タカサキ","ナツメ","takasaki@example.com","2","1993/10/25",
["𠮷田","景子","ヨシダ","ケイコ","yoshida+110@example.com","2","1952/4/30",
["草彅","剛","クサナギ","ツヨシ","kusanagi@example.com","1","1975/8/31",
["坪内","柚月","ツボウチ ユヅキ","ユヅキ","I73WwXd@example.com","2","1991/8/30",
["奥平","克洋","オクダイラ カツヒロ","カツヒロ","viDF89@example.com","","1986/12/29",
["藤代","敏嗣","フジシロ トシツグ","トシツグ","lxm5oVZqy@example.com","1","1967/7/4",
```
サンプルのデータを列挙しています。はしご高とか下の棒が長い吉とか、英語名だと,(カンマ)とかテストデータとして入れています。

これらのテストデータを ` np.random.randint ` で抽出し、dtb_customerの各フィールドに `map` で入れていきます。

```python:
import time
start = time.time()

customer_data['name01'] = customer_data['zseed'].map(random_name01)
customer_data['name02'] = customer_data['zseed'].map(random_name02)
customer_data['kana01'] = customer_data['zseed'].map(random_kana01)
customer_data['kana02'] = customer_data['zseed'].map(random_kana02)

customer_data['postal_code'] = customer_data['zseed'].map(random_zip)
customer_data['pref_id'] = customer_data['zseed'].map(random_prefid)
customer_data['addr01'] = customer_data['zseed'].map(random_addr01)
customer_data['addr02'] = customer_data['zseed'].map(random_addr02)
customer_data['email'] = customer_data['zseed'].map(random_addr02)
customer_data['birth'] = customer_data['zseed'].map(random_birth)

end = time.time()
print(end-start, '秒')
```
時間を計測すると、10万件で3分でした。

```python:
customer_data = customer_data.drop('zseed', axis=1)
customer_data = customer_data.drop('language_cd', axis=1)

customer_data.to_csv('dtb_customer.csv', encoding="UTF-8", index=False)
files.download('dtb_customer.csv')
```
出来上がったデータには"seed"を入れていましたので、不要な列を削除し、CSVを出力します。


###Copyコマンド
最後に`\COPY`コマンドを流します。

```
ec403_db=# \COPY dtb_customer ( customer_status_id,sex_id,job_id,country_id,pref_id,name01,name02,kana01,kana02,company_name,postal_code,addr01,addr02,email,phone_number,birth,password,salt,secret_key,first_buy_date,last_buy_date,buy_times,buy_total,note,reset_key,reset_expire,point,create_date,update_date,discriminator_type) from '/var/www/html/dtb_customer.csv' CSV HEADER
```

こちらは一瞬でした。

以上で、dtb_customerに大量データが作られました。
Swift ハッシュ関数 SHA-256

<h3>ハッシュ関数 SHA-256</h3>
Secure Hash Algorithm 256 bit
入力データサイズに関わらず256ビットのハッシュ値を生成。
NIST(National Insitute of Standards and Technology)(アメリカ国立標準技術研究所)で標準化。
<h3>コード</h3>

<h4>Example</h4>

```swift
import CryptoKit

var hello = "hello"
var data = hello.data(using: .utf8)

print(SHA256.hash(data: data!))
```

<h4>結果</h4>

```text
SHA256 digest: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
```

<h3>memo</h3>
<ul>
	<li><a href="https://developer.apple.com/documentation/cryptokit/sha256/3237799-hash">Document</a></li>
	<li>対応：iOS 13+、macOS 10.15+</li>
	<li>SHA512、SHA384もある</li>
</ul>
C#大統一理論

# C#大統一理論とは

CySharpのneueccさんが提唱している理論で、ザックリ言えば

***サーバーサイドもクライアントサイドもC#で完結できるとよくね？***

という理論です。

そして現状サーバーサイドとクライアントサイドの両方で使える言語はC#を除くとJavaScriptくらいだと思います（なんかあったら教えてください）

C#でクライアントサイドを作るにはXamarinやゲームエンジンのUnityが筆頭になります。

## C#のよさ

　いろいろありますが、個人的に上げるなら

- 比較的言語が若く（C++と比較して）、LINQなどモダンな文法仕様が遂次追加されている（というかLINQは単独で良い）。
- 単純に.NET Coreがクラスプラットフォームで安定して動作する。マイクロソフトが本気を出してるからサーバーサイド、クライアントサイドから機械学習まで使える範囲がめちゃくちゃ広い。
- decimalみたいな型までサポートしていて、業務利用での実用性を重視している。

静的型付けは義務であり利点ではありません。

## C#に統一することのメリット

- 単純に言語を統一したほうが楽
　一時期はやったMEAN(すべてJavaScriptに統一する奴)みたいなやつです。MEANと違って.NET Coreで環境を統一できればクライアントサイドエンジニアがサーバーサイドエンジニアのプログラムに携わることも比較的容易です（学習コストが０というわけではありません）

- サーバーサイドとクライアントサイドでデータを受け渡す方法に悩まない

　これは完全にMagicOnionの受け売りです。jsonで渡す？postに載せる？REST?gRPCってめっちゃだるくね？みたいな問題をある程度マシにしてくれます。

## なぜ広まらないのか

- .NET Core以前の.NET環境がWindows依存

　LAMP環境が流行ったころにMicrosoftはWISP(Windows, Internet Information Services, SQL Server, なんかの言語)を提唱していたり、完全にWindows依存な環境の時代が長かったのが原因の一つとして挙げられると思います。


## C#に入門するなら

プログラミング経験者は「実戦で役立つ C#プログラミングのイディオム/定石&パターン」https://gihyo.jp/book/2017/978-4-7741-8758-7 を買いましょう。とても良き
SSH Tectia ServerとOpenSSH(client)の公開鍵接続設定

#はじめに
自分は現在とある大学に通っているのですが、そこのsshサーバがOpenSSHでなくTectia Serverとかいうもので、公開鍵設定が簡単にはできませんでした。（丸2年かかった。）
自分と同じように困る人がいるかもしれないので書いておきます、
#前提
そのTectia Serverにsshで接続できるようにしてください。password認証が使えればOKdesu.
そのサーバーがTectia Serverかどうかは`ssh -vvv`の出力を見ればわかります。

```
debug1: Remote protocol version 2.0, remote software version 6.4.17.188 SSH Tectia Server
```
こんな行があればTectiaです。
#手順
そのサーバーにssh接続して`ssh-keygen-g3`を実行しましょう。
（普通、OpenSSH同士ならClient側で鍵を生成しますが、Tectia用の鍵をOpenSSHで作成する方法がわかりませんでした。ちょっと危険かも）
やってみると

```
$: ssh-keygen-g3
Generating 2048-bit rsa key pair
   6 Oo.oOo.ooOo.
Key generated.
2048-bit rsa, UserID@hostname, Tue Nov 12 2019 04:06:55 +0900
Passphrase :
Again      :
Key is stored with NULL passphrase.
 (You can ignore the following warning if you are generating hostkeys.)
 This is not recommended.
 Don't do this unless you know what you're doing.
 If file system protections fail (someone can access the keyfile),
 or if the super-user is malicious, your key can be used without
 the deciphering effort.
Private key saved to ~/.ssh2/id_rsa_2048_a
Public key saved to ~/.ssh2/id_rsa_2048_a.pub
```
と出るはずです。
自分はPassphraseを設定しませんでしたが、危険なので設定した方がいいかもしれません。（警告も出てるし）
`Passphrase : `と出たら好きなものを入力し、`Again :`と出たら同じものを入力しましょう。(何も入力せずにEnterをおせばlogin時にPassphraseを求められなくなります。）

次に`$ chmod 700 .ssh2/`で公開鍵の保存してあるディレクトリのパーミッションを変更しておきます。多分やらないと接続時にエラーが出ます。

次に`cat >> ~/.ssh2/authorization`を実行して

```
Key     id_rsa_2048_a.pub
```
と打って`Ctrl-D`で入力終了します。

これでOpenSSHでいうauthorized_keysの設定が終了し、あとはクライアント側の作業に移ります。

```
$ scp UserID@Hostname:~/.ssh2/id_rsa_2048_a 
```
で秘密鍵をダウンロードしてください。

次に

```
$ ssh-keygen -i -f id_rsa_2048_a > ~/.ssh/sshgate.key
$ chmod 600 ~/.ssh/sshgate.key
```
でtectiaの鍵をOpenSSH用の鍵に変換します。（こんなことができるなら2年前に知りたかった。）

最後に

```
ssh UserID@Hostname -i ~/.ssh/sshgate.key
```
で接続テストしてみてください。
接続できれば今日からあなたはsshやscpの使用時に一々passwordを打たなくても良くなります。
やったね！！

あとserver側の`~/.ssh2/id_rsa_2048_a`は削除しておいてね
#まとめ
`ssh-keygen -i -f`でtectia server用の鍵をOpenSSH用の鍵に変換できます。

#追記
ついに我が大学のsshサーバーもOpenSSHになりました。他にも潜在していたセキュリティの問題も解決されそうです。
pip uninstall setuptoolsをやってしまった方へ

# おそらくそんなバカは自分だけだと思いますが
`pip uninstall setuptools`を実行してしまうと次からpipの使用時に

```
Traceback (most recent call last):
  File "/usr/local/bin//pip", line 6, in <module>
    from pkg_resources import load_entry_point
ImportError: No module named pkg_resources
```
というエラーを吐き、何もできなくなります。
#対処法
```python -m pip install setuptools```
と打ちましょう
#まとめ
setuptoolsは消しちゃダメ

ちなみにqiita初投稿です。
0からプログラミングの勉強を始めて100日が経ったので、できるようになったこと/よかったこと/改善点。

2019年8月にプログラミングを勉強しようと決めて始めてから、今日でちょうど100日目。
完全に何も知らない0の未経験な状態から、プログラミングの勉強を続けてきて、何ができるようになったのか、よかったことや改善点をまとめた。

## わたしの前提
- IT企業にてフルタイムで働いているビジネス職（カスタマーサクセス）
- プログラミングは完全に未経験
- やったことあるのは、Paizaとドットインストールくらい。どちらも途中で挫折している。
- 自分が欲しいサービスを作りたいと思って、2019年8月からプログラミングスクールに通い出す。

ちなみにtwitter（プログラミング垢）はこちら↓
[ぴろり@プログラミング勉強103日目 (@piro_gramming) / Twitter](https://twitter.com/piro_gramming)


## こんな人に読んでほしい
- これからプログラミングの勉強を0から始めるひと
- 同じように0からプログラミングの勉強を初めてがんばっているひと
- 20代後半でプログラミングを勉強し始めると、どんな変化があるのか知りたいひと

## 100日間で学んだこと

- HTML/CSS
- Ruby
- Ruby on Rails
- Java Script
- Git,GitHub
- SQL

主に100日間で学んだことは下記の通り。
全て同じ量をやっているわけではなく、HTML/CSS、Ruby、Railsをやっている割合がほとんどだった。

## 100日間でできるようになったこと
- ターミナルがつかえるようになった！
- テキストエディタが使えるようになった！
- めっちゃ簡単なHTML/CSSの実装ができるようになった！
- めっちゃ単純なRubyのプログラムを書けるようになった！
- Railsのエラーが出たら何が原因か仮説を立てられて50%くらいはあってる！
- GitHubでマージとかプルリクとかできるようになった！

はじめたての頃は、

- ターミナルとテキストエディタって何が違うんだ・・・そもそもどっちにコード書くの？
- テキストエディタにどうやってファイル開くの？
- コマンド多すぎ…メソッド多すぎ…カタカナ多すぎ無理…

という状態だったので、著しい成長を遂げた（笑）

ただ、未だにわからないことばかりなので、
もっと勉強してできることを増やしていきたい。

## よかったこと
100日間勉強を続けてこれは良かったなと思うことが3つあるのでシェア。

### 1.周りに宣言＆毎日output

プログラミングの勉強を始めると決めた際に、自社のエンジニア全員が入ってるslackチャンネルに入り、「今日から毎日勉強します。見ててください！」と勝手に宣言をした。

私は自分に甘いので、誰かに宣言することで継続できると思ったからだ。
そこから毎日、勉強したことをエンジニアのアウトプットチャンネルで投稿し続けた。

誰かに見られているという緊張感で継続できたし、どんなレベルの低いことでもoutputすると学びの整理になったのでよかった。

初めて書いたQiitaはタイミングよくトレンド入りしてくれた。
[【Ruby】今日のプログラミング学習時間を入力すると、学習進捗を教えてくれるプログラム - Qiita](https://qiita.com/Pirori3182/items/1fe197f30af66911e9e9)

### 2.パラシュート学習法「まずやってみる」
私の通っているプログラミング教室が提唱しているパラシュート学習法。
[パラシュート勉強法のやり方](https://study-matome.net/efficiency/parachute.html)

教科書の1ページ目からこつこつとやるのではなく、作りたいもの（ピンポイント）に的を絞ってやりたいことから学習していく方法。まずやりたいことからやってみて、詳細は後から学んでいくというやりかただ。

具体的にいうと、HTMLやCSSの大枠をざっと学んだあと、やりたいビューを実装していると、自然とBEMやリファクタリングの概念がわかってきたのがよかった。

多分BEMやリファクタリングをコツコツ学んでても理解にかなり時間がかかったと思う。プログラミングにおいても「まずやってみる」という大事さがわかった。

### 3.一緒に勉強する仲間をつくる

一緒にプログラミングをする仲間ができたのは、プログラミング教室に通ってよかったことのひとつだ。
辛い時も、モチベーションが下がってる時も、仲のいい同期が頑張っているといい焦りになった。

たまたま一番仲良くなった女の子が、アウトプットをめちゃくちゃがんばる子なので私もそれに触発されている。一人じゃ頑張れないので一緒に頑張る仲間がいると心強い。

## 改善したいこと
いいことばかりじゃなくて、反省点もいっぱいある。

### 1.わからないことを調べず進めた。
パラシュート学習法を意識して、どんどん次に進めようとするあまり、ひとつひとつをしっかり理解していないまま次の学習に移っていた。
例えばRubyのクラスとインスタンスや引数に関して、しっかり理解しないまま進めていたので、今絶賛つまづき中。

基礎ができていないのに応用はできないので、今必死にProgateで基礎をやり直している最中だ。
もし１００日前に戻れるならちゃんと基礎をやれ！と言いたい。


### 2.時間の確保
フルタイムで働いているのでなかなか平日の学習時間の確保が難しかった。100時間/月の学習目標に対してだいたい80〜90時間/月しか勉強ができなかった。

朝から起きてやればいいんだけど、それもなかなか続かず。。
朝から早起きして一緒にプログラミングの勉強をしてくれる人を募集しています。


### 3.自分で何のサービスも作れなかった。
自分の欲しいサービスを作りたい！と言って始めたわりには、なにもアウトプットするものを作れなかった。
自分の欲しいものから作るともっとプログラミングの勉強が楽しくだろうとわかっているのに…！

プログラミングの学習時間を計測する簡単なWebアプリくらいは年内に作りたいとおもう。


## 総括
プログラミング向いていないなと思うこともあるが、前に比べるとできることが多くなっているのが嬉しい。私でもちょっとはコードが書けるようになったので、ホリエモンがいう通り「プログラミングは簡単、だれでもできるもの」なのかもしれない。

ねむいのでここまで！引き続きがんばる！
【Ruby】selectメソッドとinclude?メソッドで検索機能を実装する！

# はじめに
プログラミング学習中に出会った、
selectメソッドとinclude?メソッドについて簡単にまとめました。
そしてこの2つのメソッドを使って簡単な検索機能の実装します。

# selectメソッド
配列やハッシュなどから、ある条件にあった要素だけを取り出します。

####例１　色が入ったリストからある条件にあう要素のみ取り出す

```ruby

list = [ "blue", "red", "yellow" ]

color = list.select do |x|
  x == "red"
end

puts color
# redが書き出される 
```

####例２　do-endを使わずに書く

```ruby
list = [ "blue", "red", "yellow" ]

color = list.select{|x| x == "red" }

puts color
# redが書き出される 
```

# string＃include?メソッド
文字列の中に指定した文字列（引数で指定）が含まれているか確認できます。
含まれていればtrueを、なければfalseを返します。

####例　文字列の中に引数に指定した文字列が含まれているか確認

```ruby

color = "red"

puts color.include?("e")
# 文字列"red"の中に"e"が含まれているため、trueが返される
```


# 2つのメソッドを利用して検索機能を持った簡易アプリを作る

```ruby

list = [ "blue", "red", "yellow" ]

puts "blue"
puts "red"
puts "yellow"
puts "３色のうち好きな色を入力してください"

index = gets.chomp
# ユーザーの入力

color = list.select{ |x| x.include?(index)}
# index（入力された文字列）を含む要素を取り出して変数に入れる。

puts color
# 入力した文字列を含む色が書き出される。
# 「e」と入力すれば「blue」「red」「yellow」全て書き出される

```

#補足　Array#include?メソッド
上記で紹介したinclude?メソッドは文字列の中に要素が含まれるか確認するメソッドでした。
これは、文字列に関するオブジェクトを提供するStringクラスに定義されているメソッドです。

include?メソッドは、Arrayクラスにも定義されています。
こちらは配列の中に引数にて指定する要素が含まれるか確認できるメソッドです。

####例　配列の中に引数に指定した要素が含まれているか確認
```ruby

list = [ "blue", "red", "yellow" ]

color = list.include?("red")

puts color
# 配列の中に"red"が含まれるため、trueが返される
```

# まとめ
selectメソッドは条件にあった要素を取り出し、
include?メソッドは、指定した文字列が対象に含まれるかを確認します。
これにユーザーの入力機能を組み合わせることで検索機能を実装できました。
Ubuntuのインストール(ブートUSB作成から)

#今回の目的
Ubuntu18.04.3をUSBからブートして、Ubuntuに再インストールすること

##ブートUSBを作ろう
　今回は、UbuntuOSが元々ある前提になります。
まずは、[このページ](https://qiita.com/K-Kachi/items/3e461b10846eee6539cd)を参考にブートUSBを作成しましょう。(自分も参考にさせてもらいました)
まあ、結局isoイメージなんでDVDに書き込んでも同じですね。

##ブート順序を変更してUSBからブートさせるようにしよう
　では、シャットダウンさせBIOS(UEFI)を起動させましょう。
![IMG_0227.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191249/bd6ffa73-e895-1c57-1c00-8871ec90df64.jpeg)
↑上の画面ですね。ベンダーによって開き方違いますがThinkPadは最初にEnterでした。そして、ブート順序を変えてUSBを1番にしましょう。これを変更しないと永遠とディスクからOS起動しちゃいます笑
![IMG_1943.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191249/2ce5bd3b-ab8a-4023-5205-e6368068bffd.png)

##再インストール開始！
　あとは、USBを刺して再起動を行うだけですね。
ここで、自分は「gfxboot.c32: not a COM32R image」というメッセージに出くわしました
メッセージを読むと「一度tabキーを押して、helpと入力」すると次に進めるみたいです。
もし出てきた方は試してみてください。

OSが起動しましたら、GUI操作でインストールするだけです。
デスクトップにインストール用のアイコンがあるのでクリックすれば始まります。
再インストールするとOS上のデータは無くなりますのでバックアップは取っておきましょう。

##ログインしましょう
デフォルトで「ubuntu」というユーザーがあるので、ログインしましょう。
パスワードは空白ですので何も入力しなくて大丈夫です。

##完成
ここまででUbuntuのインストールは完了です。
最初に使うだろうコマンドを記載しておきますね。

・rootのパスワードの変更(これをしないと、suでrootになれない気が？)

```
$ sudo su -
# passwd root
```

・CLIモードに変更

```
# init 3
```
openframeworksでlibtorchを使うための設定(Windows / Mac)

# あとでちゃんと書く

LibTorchをopenframeworksで使うための設定
https://pytorch.org/tutorials/advanced/cpp_export.html
このチュートリアルをopenframeworks上で行う

# 環境
Win(on GPU)
visual studio 2015
openframeworks: 0.10.1
cuda: 10.1
cudnn: 7.6.4

Mac(on CPU)
xcode: 11.2
openframeworks: 0.10.1

# Pytorchでの前準備
torchvisionのMobileNetV2とResNet50をTorchScriptに変換する

``` convert_torchvision.py
import torch
import torchvision

model1 = torchvision.models.resnet50(pretrained=True)
model1.eval()
print(model1)
traced1 = torch.jit.trace(model1, (torch.rand(1, 3, 224, 224)))
traced1.save('./resnet50.pt')

model2 = torchvision.models.mobilenet_v2(pretrained=True)
model2.eval()
print(model2)
traced2 = torch.jit.trace(model2, (torch.rand(1, 3, 224, 224)))
traced2.save('./mobilenetv2.pt')
```

# openframeworksのプロジェクト設定
projectGeneratorで生成したプロジェクトの設定を変更していく

## Win
まとめたプロパティシートは[こちら](https://github.com/chatflip/libtorch_helper)
表示 -> その他のウィンドウ -> プロパティシートでこのプロパティシートを追加すれば(LibTorch + GPU)設定完了


ユーザーマクロ
``` LIBTORCH_ROOT = C:\Users\UserName\Documents\libtorch ```
UserNameは適宜変更

C/C++ -> 追加のインクルードディレクトリ
``` $(LIBTORCH_ROOT)\Release\libtorch\include ```
``` $(LIBTORCH_ROOT)\Release\libtorch\include\torch\csrc\api\include ```

リンカー -> 入力 -> 追加の依存ファイル
``` $(LIBTORCH_ROOT)\Release\libtorch\lib\c10.lib ```
``` $(LIBTORCH_ROOT)\Release\libtorch\lib\caffe2_nvrtc.lib ```
``` $(LIBTORCH_ROOT)\Release\libtorch\lib\c10_cuda.lib ```
``` $(LIBTORCH_ROOT)\Release\libtorch\lib\torch.lib; ```


libtorch\libにある*.dllをproject\binに移動


## Mac
target
Architectures ->Architectures
``` $(ARCH_STARNDARD_64_BIT) ```

Project.xcconfig
``` LIBTORCH_ROOT = /Users/UserName/Documents/libtorch ``` 
UserNameは適宜変更

Linking -> Other Linker Flags
-L/usr/local/opt/opencv@3/lib
``` $(LIBTORCH_ROOT)/lib/libc10.dylib ```
``` $(LIBTORCH_ROOT)/lib/libtorch.dylib ```

Linking -> Runpath Search Paths,  Library Search Path
``` $(LIBTORCH_ROOT)/lib ```

Search Paths -> System Header Search Paths
``` $(LIBTORCH_ROOT)/include ```
``` $(LIBTORCH_ROOT)/include/torch/csrc/api/include ```


ofAppのsetupを書き換える

``` ofApp.cpp
#include <torch/script.h>

void ofApp::setup(){
    torch::jit::script::Module module;
    ofFilePath file;
    std::cout << std::filesystem::exists(file.getAbsolutePath("./mobilenetv2.pt"));
    ofLogNotice() << file.getCurrentWorkingDirectory();
    try {
      // Deserialize the ScriptModule from a file using torch::jit::load().
      module = torch::jit::load(file.getAbsolutePath("./mobilenetv2.pt"));
    }
    catch (const c10::Error& e) {
      std::cerr << "error loading the model\n";
      return -1;
    }

    std::cout << "ok\n";
    
    // Create a vector of inputs.
    std::vector<torch::jit::IValue> inputs;
    inputs.push_back(torch::ones({1, 3, 224, 224}));
    
    // Execute the model and turn its output into a tensor.
    at::Tensor output = module.forward(inputs).toTensor();
    std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
}
```
【Ruby】`inject(:+)`によるリファクタリングと`:+`の意味

## はじめに

配列の各要素を加算する際によく使われる`inject`メソッド。

その中でも、`inject(:+)`によるリファクタリングと、`:+`の意味について解説します。

## この記事が役に立つ方
- もっとスッキリコードを書きたい
- Ruby初心者

## この記事のメリット
- `inject(:+)`の意味がわかる
- 配列の各要素の演算をする際の引き出しが増える

## 環境
* Ruby 2.6.3

## `inject`メソッドとは？

リストの**たたみこみ演算**を行ってくれるメソッド。

詳細はRubyリファレンスマニュアルをご確認下さい。
[instance method Enumerable#inject (Ruby 2.6.0)](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/inject.html)

### 基本構文

```ruby
inject(init){ |result, item| result + item }
# or
inject(symbol)
```

２通りあります。
`inject(:+)`は後者です。

## よく使われる用法
主に配列に対して、要素の合計を算出したい場合に用いられます。
一番よく見る記法は、タイトルにもある`inject(:+)`です。

### 前提
整数のみの配列`array`を以下のように定義します。
こちらの`array`の総和`result`を求める記法を比較します。

```ruby
array = [1, 4, 6, 34, 235]
```

---
### `each`

```ruby
result = 0
array.each{ |i| result += i }
p result
=> 280
```
3行。無駄に長い。

---
### `inject`（通常の記法）

```ruby
result = array.inject{ |sum, i| sum + i}
=> 280
```
`each`と比べて**2行**削減出来ました。

---
#### `inject(:+)`（シンボルを用いた記法）

```ruby
result = array.inject(:+)
=> 280
```
スッキリ！
逆に何が起こっているのか理解しづらいので、後ほど説明します。

---
### `sum`

```ruby
result = array.sum
=> 280
```
最高にシンプル！

## `:+`の意味
`inject(:+)`の`:+`は、Symbolオブジェクトです。

自分は最初何をやっているのか全然理解出来なかったので、以下でも試してみました。

きっとこれで**「なるほどね！」**と理解出来ると思います。
**演算子で配列の各要素をつないでくれる**イメージですね。

### `:*`の場合

```ruby
result = array.inject(:*)
=> 191760
# 1 * 4 * 6 * 34 * 235 = 191760
```

### `:-`の場合

```ruby
result = array.inject(:-)
=> -278
# 1 - 4 - 6 - 34 - 235 = -278
```


## 各記法ごとの処理速度
こちらの2つの記事で詳細が記載されていました。
具体的でわかりやすい。

[Rubyいろんな処理のベンチマーク選手権 - Qiita](https://qiita.com/1060ki/items/8a60b94358350cce5ede)
[Rubyで配列の要素を合計するベストな方法 - Qiita](https://qiita.com/takaram/items/b62466c76fced4e40dd1)

`sum`が**爆速！**
`inject(:+)`はその次なんですね。参考になります。

## 【余談】`reduce`との違いは？
Rubyでは`inject`メソッドと`reduce`メソッドは同じ働きをします。

英単語の意味は、
`inject`　**「注射する・注入する」**
`reduce`　**「減らす・減少させる」**

このせいで、最初なんで一緒なの？とすごく疑問だったのですが、以下記事の**「reduceとinjectの発想の違い」**という箇所で解説されていました。

図まで用意されていて超わかりやすかったです。
気になった方は是非ご確認下さい。

> reduce は「あるルールに従ってデータ構造内の要素数を縮小していき、最後に残った値を返す」という発想になります。
> 
> inject は「値をプールしておくバケツを用意しておき、データ構造内の全ての要素をひとつずつ、ある処理にしたがってバケツに注入していく」という発想になります。

[map と collect、reduce と inject ―― 名前の違いに見る発想の違い](https://magazine.rubyist.net/articles/0038/0038-MapAndCollect.html)

## おわりに
`(:+)`ってクマに見えませんか？笑:relaxed:

## 参考にさせて頂いたサイト（いつもありがとうございます）
[instance method Enumerable#inject (Ruby 2.6.0)](https://docs.ruby-lang.org/ja/2.6.0/method/Enumerable/i/inject.html)
[map と collect、reduce と inject ―― 名前の違いに見る発想の違い](https://magazine.rubyist.net/articles/0038/0038-MapAndCollect.html)
[Rubyいろんな処理のベンチマーク選手権 - Qiita](https://qiita.com/1060ki/items/8a60b94358350cce5ede)
[Rubyで配列の要素を合計するベストな方法 - Qiita](https://qiita.com/takaram/items/b62466c76fced4e40dd1)
SQLのインデックスについて

#インデックスについて
参考にし、自分の解釈をしてみました。
参考にしたサイト
https://sikushima.hatenablog.com/entry/20100625/1277459546


##インデックスとは
まずインデックスについて知る必要があります。
インデックスとは、「索引」です。
目次という方は多いですが、一度Google翻訳にてしらべてください。
目次はTOC(table of contents)で、索引(Index)になります。

・目次 ＝ Table of contents（略称：TOC）

見出しや項目、章立てなどを箇条書きにしたもの

・索引 ＝ Index

項目や用語を探しやすくするために五十音順やアルファベット順に並べたもの

今回一例として、
dアニメストアでアニメを探すときの「さがす」がインデックス。
アニメと結びついている固有IDが主キー、アニメ内容が実レコードです。
「さがす」は、「作品50音順」と「監督名順」の2つは最低限あると考えます。
これらは、
作品50音順は、「アニメ名・監督名」の組み合わせの複合インデックス。
監督名順は、「監督名・アニメ名」組み合わせの複合インデックス。
と考えることができます。

## インデックスのリビルドとは
リビルドとは、再構築という意味です。
最近のアニメは、昔と違ってひとつの作品をながくではなく、人るの作品をワンクール続けばいいという考えてで作られています。
少し話が反れました。
戻しましょう。
アニメ一覧を見たときに、一番初めに出てきますが、検索した際に、ワンクールごとにアニメ一覧の一番初めに出てきたら、もう一度作り直せよ！！って思うますよね。

## インデックスが多いと更新が遅い
インデックスが多いと更新が遅いというのも、よく言われることです。
例えば、「作品50音順」と「監督名」以外に、「決め台詞」や「出演する声優名」、「アニメのオープニング曲」や「アニメのエンディング曲」など複数のインデックスを作成した際に、「決め台詞」をまとめる容量が必要です。
そのうえ、新しいアニメが出たら、その都度更新すると遅くなります。
インデックスを過剰につけると、このように更新が遅くなりますけれど程度の問題です。最近のハードウェア環境では、メモリーが非常に大量にあることが多いので、インデックスを作った方が良いことが多いと思います。

## LIKE検索でインデックスを使わないとは
最近のアニメでは、「俺の妹がこんなにかわいいわけがない」などをはじめとする文章系タイトルがあります。
アニメ名で探すとしても「妹」で「俺の妹がこんなにかわいいわけがない」を探すには、1ページめから見ていくしかないですね。
つまり、LIKE検索で、一部一致、後方一致の場合はインデックスがあっても使えません。

逆に「俺の妹」までは分かっているときは、善寳一致になりますので、「俺の妹」まではインデックスが使えます。「作品50音順」でも「俺の妹」のとを　忘れていても検索できるでしょう。

LIKE検索は、ハードが高性能であれば便利ですけれど、レコード数や検索頻度の兼ね合いで十分に考慮して設計しないと、将来、大きな問題になることがあります。
IE11でpointer-events: none;が効かない 

[pointer-events: none;が効かない。Edge + a要素 + display:inline;の組み合わせは要注意。](https://stella-design.biz/2018/07/27/001601.html)

[「pointer-events: none;」がIEで効かない時](https://qiita.com/mst_7colors/items/58cd42de204c45b2cc3c)

その要素に`display:block`とか`display:flex`とか`display:inline-block`をかけてあげれば解決する。

とりあえず`display:inline`だとだめ。

今回自分でやっていてバグが発生した箇所はaタグに対してだったので、デフォルトが`display:inline`だった。
Processingでインスタグラム風グラデーションを描く

学校のProcessingの自由課題でインスタグラム風のグラデーションを描いてみました。

# インスタのロゴってどんなのだっけ
インスタグラムのロゴは2016年4月に、リアルなポラロイドカメラ風のロゴから、青・黄色・赤・ピンクのグラデーションロゴになりました。今回は変更後の新ロゴのグラデーションを描いてみます。
![shutterstock_419396584-800x640.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223109/31137eed-8dbb-2bc8-e79b-ba7a28711c6f.jpeg)


Processingで x方向や y方向の単方向グラデーションを描くのは `for` と `line()` で比較的簡単に描くことができます（色を変えながらlineを１本ずつ引いていく）が、こういった色がまだらに分布したグラデーションはむずかしそうです。

# 描いてみた
```java
size(255, 255);

for (int y = 0; y < height; y++) {
  for (int x = 0; x < width; x++) {
    float R = y * 2.0 + x * 0.9;
    float G = (y - 50) * 1.5 - x * 1.2;
    float B = 255 - y * 0.9;
    stroke(R, G, B);
    point(x, y);
  }
}

save("instagram.png");
``` 
![instagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223109/6d3c75e4-d7bb-e912-dcbf-dacd18a81b8f.png)
`point()` で65,000個ドットを打ちまくる力技ですが、きれいに描けたと思います。
（もっとスマートな書き方があったら教えてください）
（・・・ちょっと青とピンクの境界が直線的かな）

# もっと描いてみた
```java
size(255, 255);
noFill();

// gradation
for (int y = 0; y < height; y++) {
  for (int x = 0; x < width; x++) {
    float R = y * 2.0 + x * 0.9;
    float G = (y - 50) * 1.5 - x * 1.2;
    float B = 255 - y * 0.9;
    stroke(R, G, B);
    point(x, y);
  }
}

// init
int centerX = width / 2;
int centerY = height / 2;
stroke(255);
rectMode(CENTER);

// outer frame
strokeWeight(25);
int outerFrameSize = 276;
rect(centerX, centerY, outerFrameSize, outerFrameSize, 80);

// inner frame
strokeWeight(17);
int innerFrameSize = 180;
rect(centerX, centerY, innerFrameSize, innerFrameSize, 55);

// circles
int ellipseSize1 = 88;
int ellipseSize2 = 10;
ellipse(centerX, centerY, ellipseSize1, ellipseSize1);
fill(255);
ellipse(centerX + 53, centerY - 53, ellipseSize2, ellipseSize2);

save("instagram2.png");
```
![instagram2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223109/de9417f9-a71a-aefb-a51a-9ceb92ddd194.png)
完全にInstagram™です。
Unityでプロジェクトを作成する

# はじめに
本章ではUnity Hubでプロジェクトを作成する手順を説明する。

# Unity Hubからプロジェクトを作成する

1. Unity Hubを起動。
2. [新規作成]をクリック。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/fba1966e-268a-df25-8ced-1863f1d84693.png)
3. 作成したいUnity のバージョンが表示されるため、バージョンを選択(本環境では単一のUnity Editorしかインストールしていない)。![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/cb82683c-ce09-9739-04f6-80ab13751d5d.png)
4. 新しいプロジェクトの作成画面が表示される。プロジェクト名、テンプレート、プロジェクトの保存先を決定し、[作成]をクリック。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/dd9c5ce6-892c-a49d-ed34-02ed6dd86152.png)
5. Unity Editorが起動し、新しく作成したプロジェクトが表示されます。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/b6c21d9a-388f-da46-3fa7-4472bd62947e.png)



# Unity Editorからプロジェクトを作成する

1. Unity Editorを起動。
2. Unity Editorの上部メニューより[File]-[New Project]を選択します。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/872aa36c-5aa2-bf87-9f47-c64e82118750.png)
3. 新しいプロジェクトの作成画面が表示される。プロジェクト名、テンプレート、プロジェクトの保存先を決定し、[作成]をクリック。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/c2488aec-aa34-6f4e-fb56-938fb192c7cf.png)
4. Unity Editorに新しいプロジェクトが表示される。


# バージョン
ここで解説するUnity Hubのバージョンは2.1.3.0です
<font color="red">※Unity Hub.exeの[プロパティ]-[詳細]-[製品バージョン]で調べることができる。</font>
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/06d80f94-114c-6154-f01c-657eb01a103e.png)
jupyter でNotebook changedが出まくるバグ？

jupyterでcodingしてると、定期的に５分に一回くらい、

**Notebook changed**

という表示が出て[×]　を押しに行かなきゃいけなくなるという不具合が発生。

この、すごく辛い修行によって、マウスパッドの操作力を鍛えていたのですが、
流石にこれからのAI時代に不要なスキルなのではないかと考えなおしまして調べました。

少々マニアックな症状だったためか、日本語で検索しても引っかからず、
いよいよエンジニア英語力が試される！

https://github.com/jupyter/notebook/issues/484

結論を言いますと、
https://github.com/jupyter/notebook/pull/3273

上記のようにバグフィックスされていて、
~/.jupyter/nbconfig/notebook.json

```json
{
  "Notebook": {
    "Header": false,
    "Toolbar": true
  },
  "Cell": {
    "cm_config": {
      "lineNumbers": false
    }
  },
  "last_modified_check_margin": 10000 
} 
```

とすると良いらしい。
last_modified_buffer
より良い名前はないかい？

→last_modified_check_margin
はどうだ？

みたいな、おしゃれな会話がなされているのですが、
私のようなヒヨッコエンジニアからすると、答えをもう少し丁寧に書いて欲しい涙

ー＊ー＊ー
ちなみに自分の環境は、以下です。docker使ってる結構出るっぽいですね。
仮想環境とサーバーの時間のズレが発生しやすい？

gcp
dockerのnotebook/datascience-notebook
mac catalina
[Unity] モデルの特定の場所のテクスチャの色を調べる

モデルの特定場所の色を調べたい場合は、
・モデルにMeshColliderがついている
・Convexがoffになっている
・マテリアルに使用されているメインテクスチャがRead/Wrightableになっている
必要があります。

![2019-11-12_003151.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/50dfb4f3-6937-a50f-7bbc-532bb61b70a3.png)
![2019-11-12_004141.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/abd8343d-fb15-19fa-69f6-f03e4a4c2b5c.png)

その状態で
```Physics.Raycast()```でヒットしたときに返ってくる```RaycastHit.textureCoord```を調べるとテクスチャの場所(uv)が返ってきます。

かなり特殊な場合になると思いますが、マテリアルにタイリングやオフセットがかかっている場合があります。

![2019-11-12_004840.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/5feeba21-7ad6-1f5e-6e18-c668c7e39733.png)

そんな時は

```
Vector2 ofs = m_mat.GetTextureOffset("_MainTex");
Vector2 scl = m_mat.GetTextureScale("_MainTex");
uv = Vector2.Scale(uv,scl);
uv.x = Mathf.Repeat(ofs.x + uv.x,1f);
uv.y = Mathf.Repeat(ofs.y + uv.y,1f);
```

でuvを補正します。

あとはメインテクスチャの指定個所の色を```tex2d.GetPixelBilinear(uv.x,uv.y)```で取得します。

![gif_animation_004.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/33fdff7e-82a1-4898-196f-2c724a326fe0.gif)
【初心者】AWS VPC Traffic Mirroring を使ってみる

# 目的
- オンプレ時代にネットワークにTAPを入れてwireshark等でパケットキャプチャするような仕事があったが、同じようなことをAWSでできると聞いたため、どんなものかを確認してみることにした。

# VPC Traffic Mirroring とは（自分の理解）
- 特定のENIを通るトラフィックをミラーリングして、別のENIもしくはNLBに出力できる。

# やったこと
- インスタンス1(Amazon Linux2) と インスタンス2(WS2019) を作成する。インスタンス2には、RDP用のENIとミラーリングを受ける用のENIの2つをアタッチする。
- インスタンス1にアタッチしたENIをミラーリングのSource、インスタンス2にアタッチしたENIをミラーリングのTargetに設定する。
- インスタンス1にssh接続する。そのパケットをインスタンス2のwiresharkでキャプチャして、sshの通信を表示する。

# 構成図

![vpc-trafficmirror.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/98e88d09-3435-9193-4000-c6eb9201998f.png)

# 作業手順

## インスタンス作成
- インスタンス1(Amazon Linux2),インスタンス2(WS2019) を作成する。VPC Traffic Mirroringを行うには、SourceとなるENIをアタッチするインスタンスがNitro世代である必要あり(2019/11時点)。そのため、今回はインスタンス1は、t3.nanoを使用する。インスタンス2は何でもよい。
- インスタンス2には追加のENIをアタッチする。追加したENIはOS上ではethernet 3として認識された。
- インスタンス2にWireshark(パケットキャプチャ用ツール)をインストールする。

## VPC Traffic Mirroringの設定
VPCのメニュー画面にて、以下の順で設定を行う。

- Targetの設定：　
    - ミラーリングの出力先となるENIもしくはNLBをTargetとして設定する。
    - 今回は出力先はインスタンス2の追加ENI(RDPに使わないほう)を指定する。
- Filterの設定：　
    - Sourceのトラフィックに対し、ミラーリングに出力させる前にFilterをかけることができる。
    - 今回はtcp全てを取得するよう設定する。
- Sessionの設定：　
    - 「SourceのENI」、「Filter」、「Target」の3つを組み合わせて、Traffic MirroringのSessionを作成する。
    - 今回はSourceはインスタンス1のENIとし、FilterとTargetは先に作ったものを使用する。
    - ミラーリングを行う際、元のパケットがVXLANでカプセル化される。VXLANのVNI(識別用ID)が自動設定される。

## ssh トラフィックのミラーリングとパケットキャプチャ
- インスタンス2でWiresharkを起動し、ethernet 3の通信をキャプチャする設定にした上で、手元のPCからインスタンス1へssh接続を行う。

![gamen04a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/8f139551-111b-8382-1bff-d88067bfe446.png)

- x.x.x.233(手元のPC)から、10.0.1.249（インスタンス1のENI）へのssh通信が、インスタンス2にてキャプチャできている。また、パケットがVXLANでカプセル化されていることも確認できる。 

# 所感
- 今までNetwork型IDSはAWSには設置不可という考え方だったが、TargetとしてIDSを指定すればそれも可能になりそう。

# 参考
- [(公式ブログ)最新 – VPC トラフィックミラーリング – ネットワークトラフィックを捉えて検査する](https://aws.amazon.com/jp/blogs/news/new-vpc-traffic-mirroring/)
- [[新機能] EC2 インスタンス(Nitro)の通信内容をVPC側からミラーする VPC Traffic Mirroring が発表されました！](https://dev.classmethod.jp/cloud/aws/201906-release-vpc-traffic-mirroring/)
    - GUIの画面付きで説明してあり分かりやすい。
- [AWS re:Inforce2019 re:Cap LT](https://www.slideshare.net/hibinohisashi/aws-reinforce2019-recap-lt)
    - Traffic Mirroringの仕組みが図解されており分かりやすい。
grafana-reporterで日本語が表示されないので、LaTeXの日本語フォントを入れる

# やりたいこと
同僚がGrafanaの内容を出力するツール「grafana-reporter」を試していて、
はまった部分があり、その解決を手伝ったときのメモ。

GitHub
https://github.com/IzakMarais/reporter
Qiita事例
https://qiita.com/ksawada1979/items/20e8ba0f3b2d09cde73d

# grafana-reporterインストール
インストール方法は、上記のQiitaの事例そのまんまで下記で入れられるっぽい。
ここらへんは同僚がやっていたので詳細知らないが、history見た感じ、そのまんまだった。

LaTeX関連のインストール

```
# yum install texlive-pdftex texlive-latex-bin texlive-texconfig* texlive-latex* texlive-metafont* texlive-cmap* texlive-ec texlive-fncychap* texlive-pdftex-def texlive-fancyhdr* texlive-titlesec* texlive-multirow texlive-framed* texlive-wrapfig* texlive-parskip* texlive-caption texlive-ifluatex* texlive-collection-fontsrecommended texlive-collection-latexrecommended texinfo-tex
```

パッケージ取得と解凍

```
# wget https://dl.google.com/go/go1.10.2.linux-amd64.tar.gz
# tar -C /usr/local -xzf go1.10.2.linux-amd64.tar.gz
# export PATH=$PATH:/usr/local/go/bin
```

インストールと起動

```
# go get github.com/IzakMarais/reporter/...
# go install -v github.com/IzakMarais/reporter/cmd/grafana-reporter
# grafana-reporter
```

GitHubの方を見れば、
起動時のコマンドオプションが書いてあるし、
Qiitaの事例の方にはsystemdの起動方法が書いてある。

# 日本語が表示されない

PDFでレポートが出力されるようになったが、
レポートの中身で日本語の箇所が表示されないという。
文字化けではなく、表示されないという事象

# 切り分け

最初はLaTeXの文字コードとかを同僚と一緒に疑ったが、

- 文字化けではない
- Grafanaの設定をエクスポートしてさくらエディタで見たら、UTF-8でちゃんと日本語が表示されていたこと
- 同僚がCLIでgrafana-reporterからレポート出力しても同様だった

ということから、下記の事例に行き着いた。
https://github.com/IzakMarais/reporter/issues/46

同じような悩みはありそうなので、
GitHubのGrafana-reporterのIssueを見て回っていたところ、見つけた。
散々ググッタが、こうして公式のIssueに解決策があると、
やはり公式を見るのが近道というのを実感する

# 日本語フォントのインストール
LaTeX用に日本語フォントを入れる方法を検索して下記がヒット
https://water2litter.net/gin/?p=1738

同僚は下記をインストールしたら、無事にgrafana-reporterが日本語出力された模様。

```
# yum install texlive
# yum install texlive-xetex
# yum install texlive-xecjk
# yum install texlive-euenc
# yum install ipa-gothic-fonts ipa-mincho-fonts
# yum install ipa-pgothic-fonts ipa-pmincho-fonts
```
Rubyでトランプの山札からカードを引くアプリを作った(2)

以前作ったアプリを色々仕様追加や改修をしました。

##仕様変更
・全てのカードが重複しないようにする。
　→「ジョーカーの追加」を設定したら53枚になり、「なし」にすると52枚になる。
・山札からカードを引く。
　→カードを引く枚数を指定できる。
・手札の上限枚数までカードを引けるようにする。
・手札を捨てることができる。
　→捨てる枚数を指定できる。
・山札を使い切る、もしくはカードを引くことやめると終了する。
　→捨て札から山札に戻すことができる。

・三項演算子などを用いて行数を短くする。
・何度か行う処理ならメソッド定義化にする。
・for文が流行っていないそうなので、each文を使ってみたりする

##実際のコード

```ruby:playing_card.rb
# カード判定メソッド
def card_judge(i)
  # 記号判定
  mark_no = (i % 13 == 0) ? (i / 13) - 1 : i / 13

  # マーク番号：0スペード/1ハート/2ダイア/3クラブ
  card_mark = case mark_no
  when 0 then "♠️"     #SPADE
  when 1 then "♥️"     #HEART
  when 2 then "♦️"     #DIAMOND
  when 3 then "♣️"     #CRAB
  when 4 then "JOKER" #JOKER
  end

  # 数字判定
  card_no = i - ( 13 * mark_no )

  # 表示判定
  disp_list = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"]
  if card_mark == 4
    disp_num = nil
  else
    disp_num = disp_list[(card_no - 1)]
  end

  # 戻り値：カードナンバー/カードのマーク/表示される文字
  return card_no, card_mark, disp_num
end

# ドロー処理
def card_draw
 # デッキから手札に移す
 draw_card = DECK.shift(1)

 # ドローしたカードの表示設定を行う
 disp_joker(draw_card[0])

 # カードナンバーを返す
 return draw_card[0]
end

# ジョーカー表示処理
def disp_joker(n)
  if card_judge(n)[1] == "JOKER"
    puts "JOKER"
  else
    puts "#{card_judge(n)[1]} #{card_judge(n)[2]}"
  end
end

# 手札の表示
def disp_hand
  # 手札の表示させる
  puts "\n手札一覧（#{HAND.length}枚）："
  HAND.each{|i|
    disp_joker(i)
  }
end

# 捨て札の表示
def disp_trash
  # 捨て札の表示させる
  puts "\n捨て札（#{TRASH.length}枚）："
  TRASH.each{|i|
    disp_joker(i)
  }
end

# 手札を捨てる処理
def hand_trash(i)
  i.times do |n|
    TRASH.push(HAND[0])
    HAND.delete_at(0)
  end
end

# デッキのシャッフル
def deck_shuffle
  DECK.shuffle!
end

# 捨て札をデッキに戻す処理
def deck_rebuild
  TRASH.length.times do |m|
    DECK.push(TRASH[0])
    TRASH.delete_at(0)
  end
  deck_shuffle
  puts "デッキの残り枚数は、#{DECK.length}枚\n"
end

# 初期設定
HAND = []   #手札のセットアップ
TRASH = []   #捨て札のセットアップ
hand_limit = 7  #手札上限枚数
card_max = 52  #トランプのセットアップ(52=デフォルト)
joker_use = 1  #ジョーカーの利用(0=利用しない)

# デッキのセットアップ
DECK = [*(1..(card_max + joker_use))]

# デッキをシャッフルする
puts "デッキをシャッフルします\n"
deck_shuffle

# ドローのループ
loop {
  # 手札の表示させる
  disp_hand

  # 捨て札の表示させる
  disp_trash

  if DECK.length == 0
    # デッキを使い切ったときの挙動
    puts "デッキを使い切りました\n捨て札をデッキに戻しますか？(Nで終了)[Y/N]"
    case gets
    when /^[yY]/
      deck_rebuild
    when /^[nN]/ then break
    end
  elsif HAND.length >= hand_limit
    # 手札上限チェック
    puts "上限を超えているのでドローできません\n手札を古い順から何枚捨てますか？(0で終了)[1～#{HAND.length}]"
    trush_cnt = gets.to_i
    case trush_cnt
    when 1..HAND.length
      hand_trash(trush_cnt)
    when 0 then break
    end
  else
  # カードをドローして手札に加える
  hand_possible = hand_limit - HAND.length

  # ドロー最大数の設定
  if DECK.length <= hand_possible
    hand_possible = DECK.length
  end

  # 何枚ドローするか指定して、デッキからドローする
  puts "デッキからカードを何枚ドローしますか？(0で終了)[〜#{hand_possible}/0]"
  draw_num = gets.to_i
  case draw_num
  when 1..hand_possible
    draw_num.times{
      HAND.push(card_draw)
    }
  when 0 then break
  end

  puts "デッキの残り枚数は、#{DECK.length}枚\n"
  end
}

exit
```

##ソースコードで使用したもの

後でまとめます
SQLiteでUpdate( 他のテーブルの値を使って更新する）

# Summary

SQLiteでUpdateするさい他のテーブルの値を使って更新する

### こんな感じ

upsertを使う

```sql
-- SalaryIDはSalaryテーブルのプライマリキー（⇐これで動作するかどうかを判断する）
with foo as (
  select
     s.SalaryID
    ,s.PayDate
    ,s.Amount + (2007 - emp.HireFiscalYear) * 1000 as Amount
    ,s.EmployeeID
  from Salary as s
  inner join Employees as emp
    on s.EmployeeID = emp.EmployeeID
  where
    s.PayDate = '2008-02-14'
)
insert into Salary
  select * from foo where true
on conflict ( SalaryID ) do update set
  Amount = excluded.Amount
```

### ポイント

```sql

with foo as (

  -- ここにテーブル

)
insert into bar
 -- where true がポイント
 select * from foo where true
on confilict ( key ) do update set
 -- excluded がテンポラリーテーブル
 baz = excluded.baz
```

### 参考

ここの文章は英語が読めなくても雰囲気でいいので端から端まで読むべし！

[SQL As Understood By SQLite](https://www.sqlite.org/lang_UPSERT.html)

### thanks

rfさん ( twitter id @rf0444 )
バイナリアップロードでInvalid Toolchain. Your app was built with an unsupported version of Xcode or SDK...

## 結論
Xcode 11.2でアーカイブしたバイナリをアップロードしようとすると、最後に、`Invalid Toolchain. Your app was built with an unsupported version of Xcode or SDK...` というエラーが表示されてアップロードできなかった。

Apple側がXcode 11.2のビルドの審査提出を不能としているために表示されるエラーである。

Xcode 11.2.1でアーカイブし直すと、いつも通り提出できた。

## 感想
UITextViewを利用しているアプリがiOS13未満のOSでクラッシュする不具合は看過できないため、Xcode 11.2でのビルド提出を封じたのは懸命な措置だと思う。Xcodeのダウンロードは時間がかかるけど。

## 参考リンク
https://stackoverflow.com/questions/44323009/cant-submit-apps-to-appstore-error-itms-90534-invalid-toolchain
UnityでAdMobを利用する（テスト広告）

# はじめに
この内容は Google AdMob を利用してテスト広告を表示し
全体の流れを把握する目的で調査した内容のメモ書きです。

Google AdMob のガイドがわかりやすいので、そちらを参照すれば解決します。
テスト広告表示までのポイントと詰まった個所を投稿します。

- 環境
    - Unity 2019.1.14f1
    - Windows10 1903

# Google AdMob の ガイド

- スタートガイド https://developers.google.com/admob/unity/start?hl=ja
    - バナー広告　https://developers.google.com/admob/unity/banner?hl=ja
    - テスト広告　https://developers.google.com/admob/unity/test-ads?hl=ja

# ポイント
- IDはアプリIDと広告ユニットIDの2つあります。
- アプリはその名の通り、アプリに対して１つです。(AndroidとiOSは個別に取得)
    - Unityのエディタで登録（Assets > Google Mobile Ads > Settings... ）できます。
- 広告ユニットは、アプリに対して登録できます。（アプリに対して複数登録できます）
    - 広告の種類は４パターンあります。（下のコードはバナー広告）
    - 広告ユニットID は 広告クラスのコンストラクタの引数で指定します（adUnitId）
- アプリ・広告ユニットはAdMob の管理サイトで管理します
    - 開発目的では、広告ユニットIDは***テスト広告***専用のIDを利用します。
        - 実際のIDを使った場合は規約違反となるため注意します。

# 詰まった点
バナー広告のガイドを参照しながら、モバイル広告の初期化 MobileAds.Initialize() に
appId を引数に与えると動作しませんでした。
Assets > Google Mobile Ads > Settings... で指定しており
コードで指定するのも冗長で妙だと思い、スタートガイドの初期化に変更したら正常に動作しました。
（appId を引数として与えるコーディングは古いバージョンのものだろうか？）

```c#:
using UnityEngine;
using GoogleMobileAds.Api;

public class GoogleMobileAdsDemoScript : MonoBehaviour
{
    private BannerView bannerView;

    // Start is called before the first frame update
    void Start()
    {
        MobileAds.Initialize(initStatus => { });

        this.RequestBanner();
    }

    private void RequestBanner()
    {
#if UNITY_ANDROID
        string adUnitId = "ca-app-pub-3940256099942544/6300978111";
#elif UNITY_IPHONE
        string adUnitId = "ca-app-pub-3940256099942544/2934735716";
#else
        string adUnitId = "unexpected_platform";
#endif
        
        bannerView = new BannerView(adUnitId, AdSize.SmartBanner, AdPosition.Top);
        
        AdRequest request = new AdRequest.Builder().Build();
        
        bannerView.LoadAd(request);
    }
}
```
Xamarin.Androidのアーカイブで「デバッグを有効にしてビルドされたアーカイブ」と表示される

XamarinでAndroidアプリを発行した時、ビックリマークが表示されて「デバッグを有効にしてビルドされたアーカイブ」と警告が表示されることがあります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201603/f92b7536-8e62-56af-e8c5-d8ecd6972670.png)

原因は　「Androidプロジェクトをダブルクリック」　→　「コンパイラ」で表示される以下を確認してみてください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201603/3d11d4be-6839-812d-56aa-26286d8fc6e5.png)

これを「なし」に変更すると警告は消えます
VeturにTypeScript3.7のOptional Chainingを適用してみる

# TL;DR

```json:settings.json
{
    // Use dependencies from workspace. Currently only for TypeScript.
    "vetur.useWorkspaceDependencies": true, 
}
```

# 概要

TypeScript 3.7のOptional Chainingは最高！！
いつも「なんで`?.`で書けないんだ」って思っていたけど、ついに来た！

ただ...VueというかVeturで使うには...
Veturは固定のTypeScriptバージョンに依存している[^1]。
最新サポートしているバージョンはVetur0.22.3のTypeScript3.6.3。
このままTypeScript 3.7のOptional Chainingを書いたら、Veturに**怒られる**！
![コメント 2019-11-11 232438.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57546/b9e17e7f-6b93-f364-6614-ff97d7353f64.png)
トランスパイルしているのはあくまで`tsc`なので、実害があるわけじゃないが、Intelligenceが効かなくなるのは相当な痛手だ。

# 解決策

探してみたらちゃんとあった、

[Allow using workspace typescript version#682](https://github.com/vuejs/vetur/issues/682)
[how can i use optionalChaining?#1438](https://github.com/vuejs/vetur/issues/1438)

Vetur 0.17.0以降、`"vetur.useWorkspaceDependencies"`のオプションを設定できるらしい。
字面通りの意味なら、この設定をしたら、ワークスペースのTypeScriptバージョンを使ってくれるみたい！

ワークスペースの`TypeScript`のバージョンを3.7.2に上げて、

```bash
$ npm install typescript@3.7.2 --save-dev
```

ESLintのparserの`@typescript-eslint/parser`を最新バージョンの2.7.0に更新する。（3.7.2対応のparserにしないと表示が色々おかしくなる）

```bash
$ npm install @typescript-eslint/parser@2.7.0 --save-dev
```

VSCodeの`settings.json`に

```json:settings.json
{
    // Use dependencies from workspace. Currently only for TypeScript.
    "vetur.useWorkspaceDependencies": true, 
}
```

を追加したら、Optional Chainをちゃんと認識してくれるようになった！（VSCodeの再起動必須）
![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57546/da4dc77b-5f6e-c989-24ea-97025eea85da.png)

# 使用環境

TypeScript 3.7.2
VSCode 1.40.0
Vetur 0.22.6
ESLint 5.16.0

## ESLint 設定

```javascript:.eslintrc.js
module.exports = {
    parserOptions: {
        parser: '@typescript-eslint/parser',
    },

    extends: [
        // ...
    ],
};
```

[^1]: how can i use optionalChaining?#1438 Comment https://github.com/vuejs/vetur/issues/1438#issuecomment-533952010
[^2]: Vetur - linting https://vuejs.github.io/vetur/linting-error.html#linting