OmniAICreator/Qiita-1.07M huggingface dataset:
GoogleSpreadSheetで和暦から西暦へ変換する

西暦から和暦(YYYY-MM-DD)への変換にGoogleSpreadSheetを利用する際の関数を作ったので残しておきます（昭和・平成・令和のみ対応）。
例）
平成29年10月13日 => 2017-10-13
令和1年7月10日 => 2019-07-10

注：適当に参照セルは変更してください（変更3箇所:初期値A1）。

```
=SUBSTITUTE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(SWITCH(REGEXEXTRACT(A1,"[^0-9]+"),"昭和",1925,"平成",1988,"令和",2018)+REGEXEXTRACT(A1,"[0-9]+")&REGEXEXTRACT(A1,"[0-9]+(.+)"), "年([0-9])月","年0$1月"), "月([0-9])日","月0$1日"), "[年月]", "-"), "日", "")
```

空白セルで「N/A」を返さないようにするバージョンは以下で（変更4箇所:初期値A1）。

```
=IF(ISTEXT(A1),SUBSTITUTE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(SWITCH(REGEXEXTRACT(A1,"[^0-9]+"),"昭和",1925,"平成",1988,"令和",2018)+REGEXEXTRACT(A1,"[0-9]+")&REGEXEXTRACT(A1,"[0-9]+(.+)"), "年([0-9])月","年0$1月"), "月([0-9])日","月0$1日"), "[年月]", "-"), "日", ""),"")
```

なお、年号の変換は[こちらの記事のコード](https://www.officeisyours.com/entry/2019/06/30/021446)をそのまま使わせていただきました。感謝。

以下、インデント版もついでに貼っておきます。

```
=IF(ISTEXT(A1),
  SUBSTITUTE(
    REGEXREPLACE(
      REGEXREPLACE(
        REGEXREPLACE(
          SWITCH(REGEXEXTRACT(A1,"[^0-9]+"),"昭和",1925,"平成",1988,"令和",2018)
            +REGEXEXTRACT(A1,"[0-9]+")
            &REGEXEXTRACT(A1,"[0-9]+(.+)")
        , "年([0-9])月","年0$1月") 
      , "月([0-9])日","月0$1日")
    , "[年月]", "-")
  , "日", "")
,"")
```
Rubyでgemパッケージアプリを作成する

# gemアプリを作ろう

ruby でアプリケーションを作成して配布するとき、rb ファイルをzipで固めて配布するよりも gem化して配布した方がなんだかカッコイイ。rubygems に登録しないにしてもgem化しておけば、導入と破棄がとても簡単になる。gemパッケージを作る方法はいくつかあるが、ここではとてもシンプルな方法で作成してみている。

# gemspec を作成する
hoge アプリを作ってみる。最初に用意するのは gemspec ファイルだ。

```ruby:hoge.gemspecより
require 'rubygems'

spec = Gem::Specification.new do |spec|
  spec.name = "hoge"
  spec.version = '0.1.0'
  spec.summary = "ruby package test."
  spec.description = %{ ruby package test examples.}
  spec.author = 'Iwao Watanabe'
  spec.email = 'iwao@users.sf.net'
  spec.homepage = 'http://sourceforge.net/users/iwao/'
  spec.files = Dir["lib/hoge.rb", "lib/hoge/*.rb"]
  spec.files.reject! { |fn| fn.include? "~" or fn.include? "CVS"}
  spec.required_ruby_version = '>= 1.9.0'
  puts spec.files
end

```

ここで重要なのは name と version と files だ。
name がパッケージ名で versionが世代を意味する。

filesで指定するファイルが用意すべきファイルだ。
取り急ぎはコマンドラインからサクッと作成する。

```bash
$ mkdir -p lib/hoge
$ echo 'puts "aa!"' >> lib/hoge/aa.rb
$ echo 'puts "hello!"' >> lib/hoge.rb
```

# gemファイルを作成する

gemファイルを作成する。build コマンドでこのgemspecs を実行するだけだ。

```bash
$ gem build hoge.gemspec
```

hoge-0.1.0.gem が生成されたら成功だ。

# 開発向けにgemをローカルインストール

作成したら早速インストールしよう。ただし開発のためにシステムには組み込まない。
作業ディレクトリ直下の vendor ディレクトリに組み込もう。

```bash
$ gem install hoge-0.1.0.gem -i vendor
```

gem installed  と表示されたら導入されている。
hogeパッケージが組み込まれていて動作するか確認してみよう。

```bash
$ GEM_HOME=vendor ruby -rhoge -e ''
hello!
$
```

環境変数 $GEM_HOME に gem のインストール先の vendor を指定して、
 -r オプションでパッケージロードを指定している。　-e '' で空文字を渡して実行している。
hoge.rb が読み込まれて hello!  が出力された。

ちなみに hoge/aa.rb を動かすには　-r で次のように呼び出す

```bash
$ GEM_HOME=vendor ruby -rhoge/aa -e ''
aa!
$
```

# gem導入先のvendor以下のファイルを編集
動作しているファイルをls で確認してみよう。

```bash
$ ls -R vendor/gems/hoge-0.1.0/lib
hoge	hoge.rb

vendor/gems/hoge-0.1.0/lib/hoge:
aa.rb
$
```

このhoge.rb や hoge/aa.rb ファイルを編集して開発を進める。
次のような内容に修正してみよう。

```ruby:hoge.rbより
def args(args=nil)
  args = ARGV unless args
  args.each_with_index do |arg, i|
    puts "#{i}: #{arg}"
  end
end
```

args を定義してみた。これを動かすには -e オプションで指定すればよい

```bash
$ GEM_HOME=vendor ruby -rhoge -e args aa bb cc
0: aa
1: bb
2: cc
$
```

コマンドラインから渡されたパラメータが表示できている！

# 動作確認が終わったら..

vendor/gems 以下での振る舞いが満足のいく状況になったら、手元に戻してgemを再作成して確認しよう

```bash
$ cp -pr vendor/gems/hoge-0.1.0/lib/ lib/
$ gem build hoge.gemspec
$ gem install hoge-0.1.0.gem -i vendor2
$ GEM_HOME=vendor2 ruby -rhoge -e args aa bb cc
0: aa
1: bb
2: cc
```

２回目のインストールはさりげなく　vendor2 に変えてます。
あとはgitにコミットするなり、gemファイルを知人に配布するなり、ご自由にどうぞ。

あっ。知り合いに渡すときには、使い方を説明するのは忘れないでくださいね
PHP boolに変換するときにfalseとみなされる値

# 目的

- boolに変換するときにfalseとみなされる値をまとめる

# 補足

- 紹介する値はboolに変換するときにfalseとみなされる。したがってif文などの条件式に紹介する値が入るとfalseとして扱われる。

# bool変換後にfalseとみなされる値

1. integer型の`0`（ゼロ）
1. float型の`0.0`
1. float型の`-0.0`
1. 空の文字列
1. 文字列の`0`（ゼロ）
1. 要素の数がゼロの配列
1. NULL
1. 値がセットされていない変数

# 参考文献

- [https://www.php.net/manual/ja/control-structures.if.php](https://www.php.net/manual/ja/control-structures.if.php)
- [https://www.php.net/manual/ja/language.types.boolean.php#language.types.boolean.casting](https://www.php.net/manual/ja/language.types.boolean.php#language.types.boolean.casting)
Windows10 HomeからProにアップグレードする方法

Windows10　について最近Home版からPro版へアップグレードしたいです。そのMicrosoft Storeでアップグレードすると値段は安くできます。
但し、最初はStoreはなかな起動できない、起動したらアップグレードの画面へ行かないです。

その解決方法をとても簡単です。
　・まずは管理者権限でPowerShellを起動する。
　・wsreset.exeを実行する。
![temp.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402505/983e8153-f05c-a90c-8dc1-23ebfa061e0e.jpeg)
　・Microsoft　Storeを開く。
　・Windows 10 Proを探す。
![temp1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402505/8512bbef-9b59-13bc-7bc1-27023dc7eaa2.jpeg)
　・Upgradeページで購入する。
![temp2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402505/81854a6d-dbde-1599-9155-2ff7b3d133d9.jpeg)
　・Microsoftアカウントを登録してから購入可能、クレジットカード登録要
![temp3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402505/3bb28102-232e-3f57-71bb-f479b5790bc1.jpeg)

　上記内容を見るとまだ分からないですが、:point_right_tone2:ポイントは全部英語です:point_left_tone2:。ということは日本語版（英語以外と思います。）は多少問題があります。
　・その場合はシステムの設定の中に時刻と言語を選択して
![temp4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402505/6eb8c465-2819-313e-f340-31a50931e90d.jpeg)
　・優先する言語に英語を追加して、
　・Windowsの表示言語を英語に切り替える。
![temp6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402505/044b1d58-9e3e-8ca2-7e24-e0b16bf04cfc.jpeg)
　・PCを再起動して
　・ここから文章の最初の手順と繋がります。
　・Window10Proをアップグレードしてから言語を戻れば終わります。
オンラインストレージ個人向け主要サービス比較 2021春

# Online storage 2021 for personal

|Service|Plan|Price|Storage|Note|
|-|-|-:|-:|-|
|[Dropbox](https://www.dropbox.com/buy?_tk=individual_hero_button)|Basic|free|2GB||
|^|Plus|￥1,200|2TB|2TB最安|
|[GoogleDrive](https://one.google.com/about?utm_source=drive&utm_campaign=marketing_header&hl=ja)|Personal 15GB|free|15GB|無料最安|
|^|Google One 100 GB|   ￥250|100GB||
|^|Google One 200 GB|  ￥380|200GB|200GB最安|
|^|Google One   2 TB|  ￥1,300|2TB||
|[OneDrive](https://www.microsoft.com/ja-jp/microsoft-365/onedrive/compare-onedrive-plans?activetab=tab:primaryr1)|OneDrive Basic 5 GB|free|5GB||
|^|OneDrive Standalone 100 GB|  ￥224|100GB|100GB最安|
|[iCloud Storage](https://support.apple.com/ja-jp/HT201238)|Basic|free|5GB|（Windowsアプリもある）|
|^|50 GB|   ￥130|50 GB|価格が手頃でバランスが良い|
|^|200 GB|  ￥400|200 GB||
|^|2 TB|  ￥1,300|2 TB||
|[Box](https://www.box.com/ja-jp/pricing/individual)|Individual|free|  10GB|無料２番手|
|^|Personal Pro|  ￥1,200|  100GB|とても高い。選択する意味がない。|



#### 関係ないけど
QiitaのMarkdownは表の結合できないのかな。。面倒だな。

<table>
<tr>
  <td rowspan=2>A</td>
  <td>B</td>
  <td>C</td>
</tr>
<tr>
  <td colspan=2>D</td>
</tr>
</table>
```html
<table>
<tr>
  <td rowspan=2>A</td>
  <td>B</td>
  <td>C</td>
</tr>
<tr>
  <td colspan=2>D</td>
</tr>
</table>
```
Pythonのrequestsを利用してmultipart/form-data形式のデータを送信するときにContent-Typeを「multipart/form-data」としたheadersを渡してはいけない

地味にハマったポイントだったのでメモ。

## 経緯

外部APIでAuthorizationヘッダを利用する必要があったのでヘッダ取得用関数的な汎用関数を作成して使いまわしていました。
APIは基本的にContent-Typeが「application/json」、一部「application/x-www-form-urlencoded」や「multipart/form-data」が必要という感じだったので、ヘッダー取得用関数は引数でContent-Typeを上書きできるようにしていました。

以下は実際の実装では無い雰囲気コード

```python:example.py
import requests

...

def get_headers(content_type='application/json'):
  return {
    'Authorization': f'Bearer {fetch_bearer()}',
    'Content-Type': content_type,
    'SecretKey': fetch_secret_key(),
  }

...


url = 'https://httpbin.org/post'
files = {'file': open('image.png', 'rb')}
r = requests.post(
  url,
  files=files,
  headers=get_headers(content_type='multipart/form-data')
)
print(r.text)
```


headersが追加されている以外は[requests 公式のサンプルコード](https://docs.python-requests.org/en/master/user/quickstart/#post-a-multipart-encoded-file)と同じ書き方のはずですが、エラーが発生したという旨のレスポンスが返ってきました。

そのAPIでは認証エラーとなっていたこともあり、ヘッダーのAuthorizationやSecretKeyを生成している関数に何か問題が？と思って調べたのですが、Postmanやcurlで同様の関数で生成したトークンをヘッダーに埋め込み、multipart/form-data形式でAPIにPOSTした場合は、特にエラーは発生しませんでした。

## 原因

原因はAuthorizationやSecretKeyではなく、Content-Typeの方にありました。
上記のget_headersでは以下のようなヘッダーの辞書が生成されます。

```python
{
  'Authorization': 'Bearer xxxxx',
  'Content-Type': 'multipart/form-data',
  'SecretKey': 'xxxxx',
}
```

このヘッダーを使用してしまうと**Content-Typeにboundaryが付与されません**。
boundaryとは、メッセージの複数パートの境界を囲むために使用するもので、multipart/form-dataのデータを送信する際に必要となるものです[^1]。
例えばPostmanでmultipart/form-dataのデータを送信する際のヘッダーはこんな感じで勝手に計算して送信時に付与してくれるようになっています。

![スクリーンショット 2021-04-27 16.54.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303105/401299cd-096b-6fb7-81b0-4634dff9f5ce.png)

requestsの場合も同様で、boundaryの設定はこちらが一々何か計算して設定する必要はなく勝手に付与してくれます。
ただし、今回はContent-Typeを単なる「multipart/form-data」で設定してしまったため、
requestsが付与したデフォルトのContent-Typeが上書きされ、boundaryが無い状態になってしまっていました。
これを解決する方法は簡単で、単純にheadersからContent-Typeを削除するだけです。
(get_headersを書き換えるという手もありますが、multipart/form-dataのAPIが必要だったのはコード上一箇所だけだったのでここはシンプルな方法で)

```python:example.py
url = 'https://httpbin.org/post'
files = {'file': open('image.png', 'rb')}

# headerの辞書からContent-Type削除する
headers = get_headers()
headers.pop("Content-Type")

r = requests.post(url, files=files, headers=headers)
print(r.text)
```

これでエラーは発生しなくなり、正常にデータが送れるようになりました。


知っている人からすれば当たり前では、と思われそうですが普段フォームや便利なクライアントツール経由でデータを送信しているとboundaryは勝手に付与されているものなので意識する機会がなく、結構ハマりました...

## 参考

[^1]: [Content-Type - HTTP \| MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Type)

- [Quickstart — Requests 2.25.1 documentation](https://docs.python-requests.org/en/master/user/quickstart/#post-a-multipart-encoded-file)  
- [【HTTP】multipart/form-data の boundary って何ぞや？ - Qiita](https://qiita.com/kunihiros/items/e11daacfd62d85d83c06)
'v-slot' directive doesn't support any modifierエラーの対処方法。

'v-slot' directive doesn't support any modifierとエラーが出たときの対処方法。

[vue/valid-v-slot]
'v-slot' directive doesn't support any modifier.

```vuejs:xxx.vue
 With Eslint error

<template v-slot:item.name="{ item }">
```

```vuejs:xxx.vue
Without error:

<template v-slot:[`item.name`]="{ item }">
```


で解決
配列と繰り返し処理

#概要
配列についての復習と配列の取り出し方。
for文での配列の繰り返し処理について。

#配列について
データが順番に並んだ１つのデータを指します。
例えば、以下のようにフルーツデータがあるとします。

```index.js
 const fruits1 = "りんご";
 const fruits2 = "バナナ";
 const fruits3 = "ぶどう";
 const fruits4 = "なし";
 const fruits5 = "みかん";
```

データが膨大で、管理するのに苦労します。
そこで、同じ意味合いのデータとして管理していきます。
以下になります。


```index.js
const fruits = ["りんご","バナナ","ぶどう","なし"];

```

定数フルーツにりんごなどの要素が配列として格納されています。
コンソールで確認すると以下のような結果になります。

![スクリーンショット 2021-04-28 12.57.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/6805ba0a-548c-2adc-834f-cb61bc52474b.png)

配列は0番始まりになります。
lengthは要素の数を表すプロパティになります。



#for文使わない場合
配列の要素を取り出す際には以下のようになります。

```index.js
console.log(fruits[0]);
console.log(fruits[1]);
console.log(fruits[2]);
console.log(fruits[3]);
console.log(fruits[4]);
```
![スクリーンショット 2021-04-28 13.02.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/08535d94-3886-8270-a73d-222e9b0b504d.png)
要素をとりだすことができました。

しかし、要素数が増えたときにコード量が膨大になってしまいます。
そこで、ループ処理を使って行きます。

#for文

```index.js
    for (let i = 0;i <= fruits.length;i++) {
      console.log(fruits);
    }
```
![スクリーンショット 2021-04-28 13.35.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/63df6575-01c8-8691-2573-9c76afc2f1b6.png)




```index.js
    for (let i = 0;i <= fruits.length;i++) {
      console.log(`フルーツ${i}: ${fruits[i]}`);
    }
```

![スクリーンショット 2021-04-28 6.48.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/ea780da7-0e4d-7c38-a02b-b77adc7309a7.png)

変数は0~始まります。上記のコードは実質6つ取り出すことになっています。
undifeunedは要素がありませんという意味です。

よってコードを、以下のように変更しました。

```index.js
    for (let i = 0;i < fruits.length;i++) {
      console.log(`フルーツ${i}:${fruits[i]}`)
    }
```
iは要素数5未満。つまり0~4の繰り返しになります。
よって要素数とiの変数が合致したことになります。


![スクリーンショット 2021-04-28 13.54.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/7b402f25-7238-fa84-cc55-ceb339ba65da.png)





#forEach

forEachを使用するとコードが更にわかりやすくなります。

```index.js
    fruits.forEach((fruit,index) => {
      console.log(`フルーツ${index}:${fruit}`)
    });
```

引数は自由に決めることができます。
配列の要素を１つずつ受け取って、要素数がなくなるまで繰り返し処理を実行してくれます。
このforEachを使うことで、配列要素が増えたとしてもforEach内を修正することなく使うことができます！
manimの作法 その52

#概要

manimの作法、調べてみた。
複素数、使ってみた。

#参考にしたページ。

https://qiita.com/masudaryo/items/2b072b6c43a9ee76f933

#サンプルコード

```
from manimlib.imports import *

def f3(t):
	i = 0 + 1j
	c = (t / 100) * (i ** (t / 0.110025))
	return np.array((c.real * 100, c.imag * 100, 0))

class test(Scene):
	def construct(self):
		grid = NumberPlane()
		self.add(grid)
		func3 = ParametricFunction(f3, t_min = 0, t_max = 3, fill_opacity = 0)
		self.add(func3)
		self.wait()


```

#生成した動画

https://www.youtube.com/watch?v=2M2RKVckXcQ

以上。
Hyper-VにCentOS８を構築

#はじめに
先日、社内サーバー（Hyper-V）にCentOS8を構築しました。
備忘録として。

#①Hyper-V上に仮想PCを作成
新しい仮想マシンを作成するには、右側のペインから［新規］［仮想マシン］をクリックして仮想マシンの新規作成ウィザードを起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/c0a5781b-cda7-65d8-682c-cf2365494dfd.png)

このウィザードでは次へを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/6db8c376-588e-09d3-3cad-c77f3f951045.png)

作成する仮想マシンの名前と仮想マシンの情報を保存する場所を指定して［次へ］をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/f2ff6eef-d953-f498-29ac-cb94801c8724.png)

仮想マシンに割り当てるメモリ量を指定して［次へ］をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/5846701d-0d36-cd7e-b5a1-6effa993a79c.png)

接続するネットワークを選択して［次へ］をクリックします。
（後からでも変更可能です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/71163399-2891-1095-8945-2ad25f88ba14.png)

仮想マシンに認識させる仮想ハードディスクの名前や保存場所、サイズを指定して［次へ］をクリックします。
（後からでも変更可能です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/17f5d1e3-5156-b009-5632-6990b6d9a55f.png)

仮想マシンにOSをインストールさせるためにCDドライブやISOファイルをマウントする場合は指定して［次へ］をクリックします。
（後からでも変更可能です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/e2438cc3-9988-cd31-cb87-9ea410f46000.png)

［完了］をクリックすると仮想マシンの作成が開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641744/4827214c-5019-2a5b-9497-352816f63ac9.png)

#おわり
クラウドもそうですがあとから気軽にスペックを変更できるのは仮想マシンの強みですね。
次回はOSインストール編です。
実機とGNS3でのコマンドの違いについて

NWを学習中のインフラエンジニア（NW）

GNS3だと少し実機とは異なるコマンドのようなので、自分用の備忘録として残す。
やりながら随時更新する。

# VLANの作成と名前の変更
実機の場合

```
SW#conf t
SW(config)#vlan 10
SW(config-vlan)#name hogehoge
SW(config-vlan)#end
SW#show vlan
```

GNS3の場合（※実機でも下記のコマンドは使える）

```
SW#vlan database
SW(vlan)#vlan 10 name hogehoge
SW(vlan)#exit
// applyでもOK
SW#show vlan-switch brief
```
# VTPの設定

実機の場合（推奨）

```
ESW1#conf t
ESW1#(config)#vtp domain cisco
ESW1#(config)#vtp mode server
ESW1#(config)#vtp password cisco
ESW1#(config)#exit
```

GNS3の場合

```
ESW2#vlan database
ESW2(vlan)#vtp transparent
Setting device to VTP TRANSPARENT mode.

ESW2(vlan)#vtp domain cisco
Changing VTP domain name from NULL to cisco

ESW2(vlan)#vtp password cisco
Setting device VLAN database password to cisco.

ESW2(vlan)#exit
```

タグVLANには802.1QとCiscoのISLがあるが、GNS3のNW-16ESWでは.1Qのみサポート。
dnf system-upgrade download が失敗するときのお話

# 結論
```
sudo dnf system-upgrade download --releasever=xx(リリースの数字) --allowerasing --skip-broken
```

# で、何が？
`skip-broken`と`allowerasing`がないと大体上手くいかないよ、というお話。

## `skip-broken`
これは依存関係が壊れている（？）ときにオプションを足すように促される。促されたら入れたらいいけど別に最初から入れてもいい気はする。

## `allowerasing`（最重要）
ここでつまづきました。何がってfedoraのリリースでは古い機能が切り捨てられる（サポートされなくなる）のは日常茶飯事なので`allowerasing`が要るんですわ。しかもこれはエラーメッセージで教えてくれない（常識なの？）ので気づかない。
実はこのことは[公式docs](https://docs.fedoraproject.org/en-US/quick-docs/dnf-system-upgrade/)に書いてたりはする。
ちなみにまあこのコマンド走らせる前に

```
sudo dnf update --refresh --allowerasing
```

するときも同様ね。

# 雑談
Fedora34リリース今日されましたね。日付変わってる？うるせぇ俺はUTCで生きてるんだ
[Unity Editor拡張] File IDの取得、シーン上のローカルIDの取得

##File IDとは？
UnityのアセットはGuidで管理されています。SceneやPrefab内(Hierarchy上)ではFile IDで管理されています。


```YAML:samle.unity
--- !u!4 &1781688880
Transform:
  m_GameObject: {fileID: 1781688879}
```

##2019.2以降でのFile IDの取得
[GlobalObjectId](https://docs.unity3d.com/2019.3/Documentation/ScriptReference/GlobalObjectId.html?_ga=2.30360763.540265285.1619513719-2103194323.1613464900)を使うと楽です。もちろんエディタ上でしか動作しません。

```C#
UnityEngine.Object targetObject = Selection.activeObject;
// GlobalObjectIdに変換
var id = GlobalObjectId.GetGlobalObjectIdSlow(targetObject);
// File ID
id.targetObjectId
// PrefabならInstance IDが入る Prefabで無ければ0
id.targetPrefabId

// GUID Prefabなら参照元(親)のGuidがIDが入る
id.assetGUID
// アセットの種別 0 = Null, 1 = Imported Asset, 2 = Scene Object, 3 = Source Asset
id.identifierType
```

### シリアライズ、デシリアライズ

#### シリアライズ
`ToString()`がオーバーライドされていて`GlobalObjectId`を文字列にしてくれるので便利。Editor拡張に優しいですね。

下記のようなフォーマットで出力されます。
`GlobalObjectId_V1-{identifierType}-{assetGUID}-{targetObjectId}-{targetPrefabId}`
デフォルト
`GlobalObjectId_V1-0-00000000000000000000000000000000-0-0`

```C#
var id = GlobalObjectId.GetGlobalObjectIdSlow(targetObject);
var idString = id.ToString();
Debug.Log(idString);
// [Console] GlobalObjectId_V1-x-x-x-x
```

#### デシリアライズ

上記で言う`idString`を`TryParse`にそのまま突っ込むだけでOK。便利

```C#
if (GlobalObjectId.TryParse(idString, out GlobalObjectId result))
{
    switch (result.identifierType)
    {
        // プロジェクト内のアセッは簡単
        case 1:
            var obj = GlobalObjectId.GlobalObjectIdentifierToObjectSlow(result);
            Debug.Log(obj.name);
            break;

        // シーン上のアセットは取得が面倒だし重い
        case 2 :
            // 多分、シーンが開いていないと取得できません。
            // 1. シーン上のすべてのgameObjectをGlobalObjectIdに変換
            var sceneObjects = GameObject.FindObjectsOfType<GameObject>();
            var sceneObjectIds = new GlobalObjectId[sceneObjects.Length];
            GlobalObjectId.GetGlobalObjectIdsSlow(sceneObjects, sceneObjectIds);

            // 2. 一致するものを探す
            for (var i = 0; i < sceneObjectIds.Length; i++)
            {
                if (sceneObjectIds[i].Equals(result))
                {
                    Debug.Log(sceneObjects[i].name);
                    break;
                }
            }
            break;
    }
}
```

##2019.2未満でのFile IDの取得
取得できるだけありがたいですが、触れてはいけない部分から取得してる気がして若干怖いです。
`m_LocalIdentfierInFile`がスペルミスしてるので気をつけてください。

```C#
var inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
var serializedObject = new SerializedObject(Selection.activeObject);
inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);
var localIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile");

//File ID
Debug.Log(localIdProp.intValue);
```

## 参考
[How to get the Local Identifier In File for scene objects - Unity Foru](https://forum.unity.com/threads/how-to-get-the-local-identifier-in-file-for-scene-objects.265686/#post-1755771)
git resetで間違ってコミットしてしまったミスを取り消す

下記を参考にさせていただきました。
[困ったときの git reset コマンド集
](https://qiita.com/ChaaaBooo/items/459d5417ff4cf815abce)

##Gitの階層構造
Gitは以下の順番でアップロードされている

**ワーキングツリー**
     ↓
**インデックス**
     ↓
**ローカルリポジトリ**
     ↓
**リモートリポジトリ**

* ワーキングツリー : 作業場所
* インデックス : コミットする変更を準備する場所
* ローカルリポジトリ : 変更履歴を記録(ローカル環境)
* リモートリポジトリ : 変更履歴を記録(共有できる)

またgitのコマンドは下記のようにアップロードしていく

* git add : 「ワーキングツリー → インデックス」
* git commit : 「インデックス → ローカルリポジトリ」
* git push : 「ローカルリポジトリ → リモートリポジトリ」

**※インデックスがワークツリーとリポジトリの間にある理由**
理由は、以下の2つです。

* ワークツリー内の必要ないファイルを含めずにコミットを行える。
* ファイルの一部の変更だけをインデックスに登録してコミットが可能)

## git reset
`git add`や`git commit`した時に`git reset`を使えば取り消すことができます。

```
$ git reset --soft HEAD^　#直前のコミットをなかったことにする

$ git reset --hard HEAD^　#直前のコミットを取り消す

$ git reset --hard HEAD　#コミット後の変更を全部消す

$ git reset --mixed HEAD　#addを取り消す

$ git reset --hard ORIG_HEAD　#git resetをなかったことにする
```
またHEAD^の「^」を二つにしてHEAD^^にすると２つ前のコミットまで戻ります。

**オプションの説明**

 * reset --hard ：add、commit、ワーキングツリーを取り消す
 * reset --mixed：commitとaddを取り消す。
 * reset --soft ：commitのみを取り消す。


`$ git status -s`で確認

```
$ git status -s
```
[Chapter-1]VPCの設定

| タイトル |
|:-|
|  [[Chapter-1]VPCの設定](https://qiita.com/Jackson123/items/c7b0a7a6ae659fe48a3b) |
|  [[Chapter-2]EC2の設定](https://qiita.com/Jackson123/items/53cc698b1b7cfdbfe368) |
| [[Chapter-3]EC2のサーバー環境構築](https://qiita.com/Jackson123/items/821d89184d87b6020df5)  |
|  [[Chapter-4]EC2にRailsアプリの配置](https://qiita.com/Jackson123/items/e91eec2f76774717bdee) |
|  [[Chapter-5]ロードバランサー(ELB)の作成](https://qiita.com/Jackson123/items/a739525d0084747405d7) |
| [[Chapter-6]ACM(AWS Certificate Manager)でSSL証明書を取得](https://qiita.com/Jackson123/items/eb586c33fe3c5b7d9dad)  |
|  [[Chapter-7]Route53の設定](https://qiita.com/Jackson123/items/6b41ebde0eec072a283e) |
|  [[Chapter-8]https化に向けたロードバランサーの設定](https://qiita.com/Jackson123/items/d6819d3dbf304aebd459) |
|  [[Chapter-9]https化によるRoute53の設定](https://qiita.com/Jackson123/items/9ceae188a53f646e55e9) |
|  [[Chapter-10]https化によるNginxの設定](https://qiita.com/Jackson123/items/255263a260f7a833bf1d) |
## はじめに
今回はVPCの設定をしていきます
自分の手順書としてのメモですので画像はありません。あしからず。

## VPCを作成
AWSページの上部にあるサービス検索欄で「VPC」と入力し「VPC」をクリックします。
※ここでリージョンを「東京」にしていない方は右上のリージョンを選択して「アジアパシフィック(東京)」に変更しましょう

以下の通りに入力します。
1. 名前タグ： VPC_for_アプリ名
2. IPv4 CIDR ブロック： 10.0.0.0/16
3. IPv6 CIDR ブロック： IPv6 CIDR ブロックなし
4. テナンシー：「デフォルト」
5. タグ： キー: Name 値: VPC_for_アプリ名

「VPCを作成」を選択

## サブネットを作成
画面の左から「サブネット」を選択して遷移したページから「サブネットを作成」をクリックします。
以下の通りに入力します。
1.VPC ID: 「先ほど作成したVPC」
2.サブネット名: 「アプリ名-Subnet-1a」
3.アベイラビリティーゾーン： 「ap-northeast-1a」
4.IPv4 CIDR ブロック： 「10.0.0.0/24」
5.タグ: キー:「Name」, 値:「アプリ名-Subnet-1a」

## インターネットゲートウェイを作成
画面左「インターネットゲートウェイ」をクリックして、「インターネットゲートウェイの作成」を選択します。
以下の通りに入力します。
1.名前タグ：「Gateway_for_アプリ名」
2.タグ： キー:「Name」, 値:「Gateway_for_アプリ名」
「インターネットゲートウェイの作成」を選択します。

## ゲートウェイをVPCと紐付ける
先ほど作成したゲートウェイとVPCを紐付けます。
ゲートウェイを選択した状態で「アクション」をクリックして、「VPCにアタッチ」を選択します。
そして「VPCを選択」から作成した「VPC_for_アプリ名」を選択して
「インターネットゲートウェイをアタッチ」を選択します。

## ルートテーブルの作成
次にルートテーブルを作成します。
画面左の「ルートテーブル」を選択して、「ルートテーブルの作成」を選択します。

1.名前タグ：「Table_for_アプリ名」
2.VPC：「VPC_for_アプリ名」
3.キー：　キー:「Name」、値:「Table_for_アプリ名」
作成をクリック

作成したルートテーブルの「ルートの編集」を行います。
作成したテーブルを選択した状態で、下のタブの「ルート」を選択し、「ルートの編集」を選択します。
以下の通りに記述
1.送信先：「0.0.0.0/0」
2.ターゲットの項目を選択し、「Internet Gateway」を選択、先ほど作成したゲートウェイを選択
3.「ルートの保存」をクリックします。

次にサブネットとの紐付けをします。
画面左から「サブネット」を選択し、先ほど作成したサブネットを選択して画面下の「ルートテーブル」から「ルートテーブルの関連付けを編集」を選択します。

「ルートテーブル ID」から作成したテーブル「Table_for_アプリ名」を選択します。
「保存」をクリックします。

## セキュリティグループを作成
セキュリティグループを作成します。
画面左から「セキュリティグループ」を選択して「セキュリティグループの作成」をクリックします。
以下の通りに記述します。
1.セキュリティグループ名：「アプリ名-SecurityGroup」
2.説明：「Security for アプリ名」
3.VPC：「VPC_for_アプリ名」(作成したVPC)
下のインバウンドルールで「ルールの追加」をクリック
以下の通りに記述
1.タイプ：「SSH」
2.プロトコル：「TCP」※自動選択
3.ポート範囲：「22」※自動選択
4.ソース：「マイIP」（自分のグローバルIPが表示）
さらにルールを追加します。再度「ルールの追加」ボタンを選択
以下の通りに記述
1.タイプ：「HTTP」
2.プロトコル：「TCP」※自動選択
3.ポート範囲：「80」※自動選択
4.ソース：「任意の場所」（0.0.0.0/0, ::/0）

「セキュリティグループを作成」をクリック
※ここでインバウンドルールを設定しなかった場合はセキュリティグループの画面からインバウンドルールを変更できます。
以上でVPCの作成は終わりです。
草野球の出欠確認Webアプリを作ろう！　part.3

これから作っていく簡単なWebアプリの作成メモ（自分の備忘）です。
自分用なのであまり凝りすぎないように書いていきたい。

[<<前回の記事](https://qiita.com/tomodachi_uec/items/9ed563516f4d0435c385)

##今回やったこと

###スケジュールコントローラーほかの生成

前回作成した`Schedule`モデルに対応するコントローラーやビューを作成していく。
あまりまとまった作業時間をとれていないので、ひとまず見た目や機能は気にしないで動くものを作っていこう。
（でも思いつきや寄り道は大事にしたいジレンマ、、、）

```bash
$ bin/rails g controller Schedules index show new create edit update delete
```

生成されたルーティングを以下のように書き直す（個人の好みの問題）。

```rb:config/routes.rb
Rails.application.routes.draw do
  # ルート
  root "users#index"

  # Users
  resources :users

  # Schedules
  resources :schedules
end
```

`Users#index`のビューを作った時とほぼ同じものをコピペで作成した。
（以前`views/users/index.html.erb`を作った際にはif文の条件を`@users.empty?`としていたが、何か新しいアクションを追加したときに`NoMethodError`でシステムエラーを起こしたくないので`@schedules.blank?`として`@schedules`が`nil`になってしまうことに備えた。）
（本当は業務アプリでは上記のような「想定外を想定してゆるく作る」のはNGだと思うが、今回は遊びの面が強いのでなるべく作りの甘さが出ても動いてくれるようにしていきたい）

```erb:views/schedules/index.html.erb
<h1>チームの予定一覧</h1>
<% if @schedules.blank? %>
  <div><%= "表示できる予定がありません。" %></div>
<% else %>
  <div class="table_card">
    <table align="center">
      <thead>
        <tr>
          <th>件名</th>
          <th>予定日</th>
        </tr>
      </thead>
      <tbody>
        <% @schedules.each do |lst| %>
          <tr>
            <td><%= lst.title %></td>
            <td><%= lst.date_of %></td>
          </tr>
        <% end %>
      </tbody>
    </table>
  </div>
<% end %>
```

コントローラーも以下のように追記した。

```rb:controllers/schedules_controllers.rb
def index
  @schedules = Schedule.all
end
```

ぎりぎり動く程度の実装はできたので、動作を確認する。
以下は動作確認のための`root`変更。

```rb:config/routes.rb
# ルート
# root "users#index"
root "schedules#index"
```

上記によって、Railsサーバーに最初に接続したときのページが`schedules/index.html.erb`になる。

![予定一覧の試作１](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534558/41feea95-fdd8-794f-0490-6e244095d260.png)

Rails6のデフォルトで、development環境ではプロファイラが表示される。
画面ハードコピーを取得する際に邪魔だったので、以下の記事を参考に`Alt+p`で非表示にした。
[rails viewのプロファイラを非表示](https://qiita.com/sakura1116/items/2acc823a6825a7936b91)

他にも以下の記事のように、Railsサーバー起動時にデフォルトで表示されないようにできるらしい。
[rack-mini-profilerの計測結果がWebページに表示しないようにする](https://qiita.com/kadoppe/items/6ce36a21d829585dd319)

ふだんメインで使っているのはRails5.2.5なのでrack-mini-profilerを意識することがなかったが、かなり便利そうなので常時非表示にするのは惜しいと思いました。
そのため、[rack-mini-profilerのREADME](https://github.com/MiniProfiler/rack-mini-profiler#configuration-options)を参考に、以下のようにして表示位置を右下にしてみた。

```rb:config/environments/development.rb
require "active_support/core_ext/integer/time"

Rails.application.configure do
 （中略）
  # rack-mini-profilerを右下に置く
  Rack::MiniProfiler.config.position = 'bottom-right'
end
```

![1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534558/7c3b6ca9-da47-3a94-2980-368956e42173.jpeg)

気に入ったので、しばらくこれでいってみようと思います。
（development.rbに記述した内容が反映されるのは、Railsサーバーの再起動時という点に注意）

今日も短いけどここまで。
[次回の記事>>](https://qiita.com/tomodachi_uec/items/558c48acf7ffc2efeefe)
【Webpack】jsファイルのimportがうまくいかない時のエラー2連続と対処

typescriptのコンパイルをwebpack経由でコンパイルを試しているときにエラーが発生。
発生エラーと対処内容が順番を追ってのものとなりました。

##環境
・ローカル環境で動作確認。
・webpack5系


typscriptで書いたコードをwebpackでjsにコンパイルし、そのコンパイル後のjsファイルをindex.htmlで読み込んでいます。
で、読み込んでいるhtmlファイルのコンソールに出たエラーと対処方法です。

##発生エラー1
```
SyntaxError: import declarations may only appear at top level of a module
```

モジュールではimportはトップレベルで宣言してね、というもの
コンパイル後のjsファイルでも最初に宣言していたのですが。。
少し調べてみるとそもそものhtmlから、スクリプトファイルを読み込むtypeにmoduleを指定している必要があったようです。

参考：https://stackoverflow.com/questions/42237388/syntaxerror-import-declarations-may-only-appear-at-top-level-of-a-module

こちらを参考に

```
<script type="module" src="./index.js"></script>
```
と指定。
すると、今度は下記のエラーとなりました。
##発生エラー2

```
クロスオリジン要求をブロックしました:
 同一生成元ポリシーにより、file:///Users/xxxx/プロジェクトフォルダ/dist/index.js
 にあるリモートリソースの読み込みは拒否されます (理由: CORS 要求が http でない)。
```

これはいろいろ調べていると、
ローカル環境でもサーバー起動上での動作ではない場合、クロスオリジン要求になってしまうみたいですね。。。
ここ最近のブラウザにセキュリティ対策の高まりによるものっぽい。

参考：https://qiita.com/terufumi1122/items/39b2a3659bc585c07f64

ということでwebpack-live-serverでローカルサーバを起動し正常に読み込めました。
Swift 構造体について

##構造体について

##構造体
```swift:構文
struct 構造体名 {
    var プロパティ名 = 初期値
    func メソッド名() {
       処理
    }
}
```

以下は例。

```swift
struct Item {
    var name = "メロン"
    var price = 400
    func showName() {
       print("これは\(name)です")
    }
}
// インスタンスの作成
let item = Item()
// メソッドの呼び出し
item.showName() // 結果 これはメロンです
// プロパティの参照
print(item.price) //　結果 400
```

変数にインスタンスを作成する事なくメソッドを呼び出す事も可能です。

```swift
Item().showName() // 結果　これはメロンです
```

プロパティの値の書き換えは再代入で行う。

```swift
item.name = "スイカ"
print(item.name) // 結果 スイカ
```

###プロパティ

####ストアドプロパティ
値を保持する為のプロパティ

```swift
struct Item {
    var name = "メロン" // ストアドプロパティ
    // 略
}
let item = Item()
print(item.name) // 結果　メロン
```

####コンピューテッドプロパティ
値を計算する為のプロパティ。
以下のような注意点があります。

- 値が可変である為、変数(var)として定義する必要がある
- 型の指定が必須

```swift
struct Item {
    var price = 100
    // 税込価格を計算するコンピューテッドプロパティ
    var priceWithTax:Int {
        let result = price * 1.1
        return result
    }
    // 略
}
let item = Item()
print(item.priceWithTax) // 結果 １１０
```
内部では関数的な処理が行われているのですが、呼び出しの部分だけ見るとまるでストアドプロパティであるかのように参照することが出来ます。

ちなみに上のコンピューテッドプロパティは以下のようにシンプルに書くことが出来ます。

```swift
var priceWithTax:Int {
    price * 1.1
}
```

これはSwiftの、ブロック内({ })の式が一つしかない場合、returnを省略することが出来るというルールを利用した書き方です。
中間変数resultに計算結果を代入する処理を省略し、ブロック内のコードを一行して、上記のルールに則ってreturnを省略したというわけです。

###イニシャライズ
インスタンス作成時に構造体の初期処理を行います。

```swift
struct Item {
    var name: String
    var price: Int
    init(name: String, price: Int) {
        self.name = name
        self.price = price
    }
    // 略
}
let item = Item(name: "メロン", price: 400)
print(item.name) //結果　メロン
```

インスタンス作成時の引数は以下のようになっていますが、

```swift
let item = Item(ラベル名:引数, ラベル名:引数,)
```

注意する点は、このとき指定しているのでは引数名ではなくラベル名だということです。
先ほどのコードは呼び出しの際に引数名を指定しているように見えますが、

```swift
let item = Item(name: "メロン", price: 400)
```

これはSwiftにラベルを省略すると引数名と同じ名前のラベルが自動で補完されるルールがあります。
先ほどのコードはinit（）でラベルを省略しているのでこのルールが適応されているというわけです。

###プロトコル

```swift:構文
protocol プロトコル名 {
    var ストアドプロパティ名: 型名 { get set }
    var コンピューテッドプロパティ名: 型名 { get }
    func メソッド名()
}
```
構造体に実装しなければならないプロパティやメソッドの約束事を決める機能です。
あるプロトコルを適合させた構造体は、そのプロトコルに書かれているプロパティやメソッドを実装することが義務付けられます。

エナジードリンクを例に実際に書いてみます。

```swift
// プロトコルの定義
protocol energyDrinkProtocol {
    var amountOfArginine: Int { get set } // 保有するアルギニンの量を表すプロパティ
    func replenishEnergy() // エネルギーを補充するメソッド
}
```
構造体に適合させてみます。

```swift
struct redbull: energyDrinkProtocol {

    var amountOfArginine = 125
    var amountOfCaffeine = 40

    func replenishEnergy() {
        print("元気百倍!!")
    }

    func stimulateTheBrain() {
        print("脳が活性化したよ！!")
    }
}
```

energyDrinkProtocolに従い、monster構造体はamountOfArginineプロパティとreplenishEnergy()メソッドを持っておりプロトコルの約束通りの実装です。なのでエラーは出ません。
これがもし、

```swift
struct redbull: energyDrinkProtocol {
    var amountOfCaffeine = 40
    func stimulateTheBrain() {
        print("脳が活性化したよ！!")
    }
}
```
のようになっていると、プロトコルとの約束事に反する為エラーが出ます。
まとめると、プロトコルは構造体の仕様書のようなもので、構造体の実装内容をある程度保証する役割があります。
macOS Big Sur 11.3でAndroid Emulatorが起動しない

# Big Sur 11.3にアップグレードしたら、Android Emulatorが起動しなくなった

かなり悩んだ結果、以下のTwitterの書き込みにたどり着きました。

https://twitter.com/davemurdock/status/1386878240128651266

以下のURLに誘導されたので、その通りにやってみました。

https://www.arthurkoziel.com/qemu-on-macos-big-sur/

## まず、`entitlements.xml`を準備

/tmp/entitlements.xml を作成します。

```xml:/tmp/entitlements.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.hypervisor</key>
    <true/>
</dict>
</plist>
```

## これを使って`codesign`を実行

Android SDKのパスは違う場合があるので、そこは適宜読み替えてください。

```bash:terminal
$ codesign -s - --entitlements /tmp/entitlements.xml --force /Users/{ユーザー名}/Library/Android/sdk/emulator/qemu/darwin-x86_64/qemu-system-x86_64
```

これでEmulatorが起動するようになりました。

## まとめ

OSのアップデートに追従するのは辛みがありますね、、、
DB設計時のカテゴリのジレンマ【考察】

# 【カテゴリのジレンマとは】

カテゴリのジレンマとは、あるものに関連付ける「カテゴリ」が存在する。
その「カテゴリ」をユーザが追加でき、「カテゴリ」がネストする（階層化できる）場合の
DB設計をした際に生じる問題。

---
# 今回のテーマ
今回は、

`食べ物テーブル`　と　`カテゴリテーブル`

の　`カテゴリのジレンマ`　について考える。

---

# DBイメージ

`食べ物テーブル`　と　`カテゴリテーブル`　
のDBイメージは以下の通りである。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/dbd1b22e-9dfb-f8fd-528e-3d0c6f533ab1.png)

---

# カテゴリテーブル登録イメージ

`カテゴリテーブル`　
の登録イメージは以下の通りである。

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/af202761-097e-b59e-0ee2-e4290a56def9.png)


---

# 食べ物テーブル登録イメージ

`食べ物テーブル`
の登録イメージは以下の通りである。

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/c80613d7-c457-40ce-1959-8b10f2f89a4e.png)


---

# 【考察①】とりあえず表のようにDBを作る

DBを表のように作ります。

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/6f9172d5-d603-dd75-932b-c4751fc4059c.png)

---

# カテゴリ登録を行うと・・・

カテゴリ登録を行うとなぜか「カテゴリテーブル」のようにDB登録されます！！
（1つずつ登録しているので当たり前）

![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/c10e2d0c-bf35-0e96-468b-367bf4b68ab5.png)

---

# え？一括登録すればいいって？

カテゴリ登録を一括で行ったとしても
正規化されていないDBは見るに堪えない・・・。
（毎回「和食」を登録するのか・・・）

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/91efd7e0-50fd-3488-2463-be9be5bcb617.png)

---

# 【考察②】カテゴリ毎にテーブルを分ける

カテゴリを正規化して、DBを表のように作ります。

![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/a25b1679-df29-dd9c-0783-1cb0461674e4.png)

---

# 食べ物登録を行うと・・・

何を選んでもカテゴリが全表示されるバグが発生。
（カテゴリテーブル間の関係が決まっていないため）

![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/7b92ba6b-2edf-7fc1-be9b-e79fd2d6381c.png)

---

# カテゴリテーブル間に関係を作ると・・・

ねじれ過ぎてて読み解きにくい・・・
（もう少しシンプルに設計したい・・・）

![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/80fae87c-4d82-fe41-d7c6-7ee78d124e00.png)

---

# 【考察③】カテゴリまとめテーブルを作る

正規化したカテゴリテーブルに
カテゴリをまとめる「カテゴリまとめテーブル」を追加する。

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/165319f7-8908-9813-3da5-6195e67e858b.png)

---

# デジャブ！？・・・

DBを表の通り作成したときと同じことが起こります。
また、一括登録では途中で登録をやめた際に
そこまでのデータが残らないのがネックです。

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/a026fca1-6bae-4389-a397-2213aaec426e.png)

---

# 【考察④】カテゴリに親子関係を作る

カテゴリに親子関係を追加して、DBを表のように作ります。

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/ee4266d5-f28d-d4f6-ab26-97f268e89036.png)

---

# カテゴリ登録を行うと・・・

親カテゴリIDで制御されているので、
不要なカテゴリは表示されません！！

![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/1b8bce6d-b1b5-c60d-8800-96c33d177637.png)

---

# 食べ物登録を行うと・・・

[イメージ通り](#食べ物テーブル登録イメージ)カテゴリが表示されます。
しかし、1つのテーブルで3テーブル分管理
しているようなものなのでDBの肥大化が怖い・・・

![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/150148be-2a6f-93fd-afc4-17f88e63e2e2.png)

---

# 最後に

以上、`DB設計時のカテゴリのジレンマ`でした！

カテゴリを考えるだけで
こんなに発想が出てくるなんて
面白いですよね。

もし、より効率的にカテゴリ管理をする方法を
ご存知の方がいましたらコメントお願いします。
Vitis HLS と Vivado で作った回路を PYNQ を使って FPGA 上で動かすまで ー③Vivado で回路を組むー

諸事情あり，このページは以下のページに移行しました．
ご愛読ありがとうございます．

https://blog.n-hassy.info/2021/05/vitis-hls-to-fpga-3/
linuxのiptablesでproxyサーバーを簡単に実現する方法

#概要
linuxのiptablesでproxyサーバーを簡単に実現します。ローカルネットワーク内のpc1は、proxyサーバーを経由して、外部インターネットにアクセスします。

pc1(public ipなし) ----> proxy server(public ipあり) ---> インターネット

**##pc1##**
private ip: 172.31.8.4

**##proxy server##**
private ip: 172.31.11.10
auto public ip: 13.231.116.234

#環境
- **AWS VPC**
- **AWS EC2**　`(proxyサーバ：1台、pc1：1台)`

 - Debian 10 (HVM), SSD Volume Type - ami-0ac97798ccf296e02 (64-bit x86)

 - t2.micro
 
#手順
## 1. AWS EC2インスタンスの作成(proxyサーバ)
・ **Auto-assign Public IP：Enable**
・ **送信元/送信先チェックを無効にする**
作成したEC2インスタンスを選択して --> Actions --> Networking --> Change source/destination check --> Stopにチェックを入れて、Saveボタンを押下します。
・**IP forwardを有効にする**

```
admin@ip-172-31-11-10:~$ cat <<EOF | sudo tee /etc/sysctl.d/ipforward.conf
> net.ipv4.ip_forward=1
> EOF
net.ipv4.ip_forward=1
admin@ip-172-31-11-10:~$ 
admin@ip-172-31-11-10:~$ sudo sysctl --system
* Applying /etc/sysctl.d/99-sysctl.conf ...
* Applying /etc/sysctl.d/ipforward.conf ...
net.ipv4.ip_forward = 1
* Applying /etc/sysctl.d/protect-links.conf ...
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
* Applying /etc/sysctl.conf ...
admin@ip-172-31-11-10:~$ 
```
・**iptablesにルールを追加する（source ip: 172.31.8.4 --> 172.31.11.10）**

```
〜〜外部に送信する前に、source ip（pc1のip）を自動的にproxyサーバのeth0のipに設定する〜〜
admin@ip-172-31-11-10:~$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
admin@ip-172-31-11-10:~$ 
admin@ip-172-31-11-10:~$ sudo iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P POSTROUTING ACCEPT
-P OUTPUT ACCEPT
-A POSTROUTING -o eth0 -j MASQUERADE
admin@ip-172-31-11-10:~$
```
## 2. AWS EC2インスタンスの作成(pc1)
・ **Auto-assign Public IP：Disable**
・ **Kernel IP routing tableを変更する**

```
〜〜default Gatewayを削除する〜〜
admin@ip-172-31-8-4:~$ sudo ip route del default
〜〜新しいdefault Gateway（proxyサーバー）を追加する〜〜
admin@ip-172-31-8-4:~$ sudo ip route add default via 172.31.11.10 dev eth0
```


変更前：

```
admin@ip-172-31-8-4:~$ sudo route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.31.0.1      0.0.0.0         UG    0      0        0 eth0
172.31.0.0      0.0.0.0         255.255.240.0   U     0      0        0 eth0
admin@ip-172-31-8-4:~$ 
```
変更後：

```
admin@ip-172-31-8-4:~$ sudo route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.31.11.10    0.0.0.0         UG    0      0        0 eth0
172.31.0.0      0.0.0.0         255.255.240.0   U     0      0        0 eth0
admin@ip-172-31-8-4:~$ 
```
## 3.結果を検証する

```
admin@ip-172-31-8-4:~$ curl yahoo.co.jp
<HTML>
<HEAD>
<TITLE>Document Has Moved</TITLE>
</HEAD>

<BODY BGCOLOR="white" FGCOLOR="black">
<H1>Document Has Moved</H1>
<HR>

<FONT FACE="Helvetica,Arial"><B>
Description: The document you requested has moved to a new location.  The new location is "https://www.yahoo.co.jp/".
</B></FONT>
<HR>
</BODY>
admin@ip-172-31-8-4:~$ 
admin@ip-172-31-8-4:~$ 
```
jQueryでふわっとさせる(コピペ可)

###1.ふわっとさせたいHTMLの要素にクラスをつける

```index.html
<div class="他クラスとも共存可 effect-fade">
//処理
<div>
```
###2.CSSにふわっとさせる処理を書く
```style.css
.effect-fade {
  opacity: 0;
  transform: translate(0, 100px); /* ふわっとさせる高さ */
  transition: all 1500ms; /* ふわっと仕切るまでにかかる時間 */
}
.effect-scroll {
  opacity: 1;
  transform: translate(0, 0);
}
```

###3.Jqueryでふわっと詳細を書く
```script.js
$(function () {
  $(window).scroll(function () {
    $(".effect-fade").each(function () {
      var elemPos = $(this).offset().top;
      var scroll = $(window).scrollTop();
      var windowHeight = $(window).height();
      if (scroll > elemPos - windowHeight) {
        $(this).addClass("effect-scroll");
      }
    });
  });
  jQuery(window).scroll();
});
```
VSコード上で方向キーショートカットを設定する

## やりたい事
VSコード上でもVim操作のようなカーソル移動をしたい。
出来る限り、方向キーは使いたくない。

そこで、VSコード上でキーボードショートカットを編集する事でVim風な操作が出来るようにしてみました。

##手順
### keybindings.jsonを開く
`command + shift + p`で`key`と検索する

![スクリーンショット 2021-04-28 0.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794864/d94617ed-9aef-b357-1c50-517a1393f5de.png)

### ファイルに以下のコードを追記

```keybindings.json
[
  { "key": "ctrl+l", "command": "cursorRight", "when": "textInputFocus" },
  { "key": "ctrl+h", "command": "cursorLeft", "when": "textInputFocus" },
  { "key": "ctrl+k", "command": "cursorUp", "when": "textInputFocus" },
  { "key": "ctrl+j", "command": "cursorDown", "when": "textInputFocus" }
]
```

## まとめ
保存すれば、Vim風なカーソル操作が出来るはずです。
アプリの一括削除

##初めに
アプリケーションを作成している際に、DBに何かのエラーが出たが解決できず、一度全て削除し、再作成を試みました。


##1.アプリケーションフォルダ内でDBの削除

```rb
$ rails db:drop
```

##２.一つ上のフォルダに移動し、アプリの削除

```rb
$ cd ..
$ rm -rf [削除したいアプリ名]
```

以上です。
PAYJP 設定引き数一覧　リファレンスより



引数

|カード番号|card[number]|String|必須|
|:--:|:--:|:--:|:--:|
|有効期限月|card[exp_month]|String|必須|
|有効期限年|card[exp_year]|String|必須|
|3~4桁のCVCコード|card[cvc]|String||
|都道府県|card[address_state]|String||
|市区町村|card[address_city]|String||
|番地など|card[address_line1]|String||
|建物名など|card[address_line2]|String||
|郵便番号|card[address_zip]|String||
|2桁のISOコード(e.g. JP)|card[country]|String||
|カード保有者名(e.g. "YUI ARAGAKI”)|card[name]|String|
Githubのリポジトリを共有する(collaboratorとして登録する)

以下の記事を参考にさせていただいてます。

https://docs.github.com/ja/github/setting-up-and-managing-your-github-user-account/inviting-collaborators-to-a-personal-repository

## リポジトリを共有する
Githubにログインして、リポジトリのメインページにアクセスしてください。
リポジトリ名の下の`Settings`を選択してください
![スクリーンショット 2021-04-27 23.38.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/edcdb993-32aa-834c-d7da-33641f90e48f.png)

次に左のバーから`Manage access`を選択します
![スクリーンショット 2021-04-27 23.41.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/4d71d33c-7f55-6e2e-83de-9a0c34c98332.png)
選択するとパスワードを要求されるので入力してください

`Manage access`の画面に入ったら`Invite a collaborator`を選択します。
![スクリーンショット 2021-04-27 23.44.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/6dfddf5e-b095-f889-9a09-893416b87e4b.png)

検索フィールドで共有したいユーザーの「gitアカウント名」か「メールアドレス」を入力し`Add NAME to REPOSITORY`を選択します
![スクリーンショット 2021-04-27 23.55.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/94bf4d69-5ce3-ee8b-e0e7-a01a0a803390.png)

すると`Manage access`に招待されたユーザーが表示されます。
![スクリーンショット 2021-04-28 0.00.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/2c5948e5-ef72-b429-e4eb-f96237241bfb.png)

そのユーザーに招待メールが送られるので、メールを確認してもらってinvitationsをクリックして認証してもらえばそのユーザーはそのリポジトリにアクセスできるようになります。

以上でGithubのリポジトリの共有は完了です
【M1 Mac】nodebrew v1.1.0が公式にAppleSiliconに対応したのでNode v16.0.0をインストール

# はじめに
M1 Mac nodebrewが公式にAppleSiliconに対応したらしい(2021-04-23)
https://github.com/hokaccha/nodebrew/blob/master/History.md#110---2021-04-23

## 遭遇したエラー
以下のコマンドで簡単にNodeがインストールできるということで、実行してみたところ

```
$ nodebrew install v16.0.0
```

なんかたくさんエラーでてる〜〜！！！
対応したちゃうんか〜！！！😂

```
Fetching: https://nodejs.org/dist/v16.0.0/node-v16.0.0-darwin-arm64.tar.gz
Warning: Failed to create the file 
Warning: /Users/merarli/.nodebrew/src/v16.0.0/node-v16.0.0-darwin-arm64.tar.gz:
Warning:  No such file or directory

curl: (23) Failed writing body (0 != 978)
download failed: https://nodejs.org/dist/v16.0.0/node-v16.0.0-darwin-arm64.tar.gz

```

理由はわかりませんが、`Homebrew`経由で`nodebrew`をインストールしたのが原因っぽい

# nodebrew インストール
Homebrew経由のインストールが悪いと思ったので、`homebrew`でインストールした`nodebrew`をアンインストール後、

```
$ brew rm nodebrew
```


公式のGitHubに書いてある`curl`コマンドでインストール
https://github.com/hokaccha/nodebrew
**初めてインストールする人はここから始めてください**

```
$ curl -L git.io/nodebrew | perl - setup
```

インストール完了後、以下のパスを`~/.zshrc`の下部に記述してください。

```
export PATH=$HOME/.nodebrew/current/bin:$PATH
```

以下のコマンドで変更した`~/.zshrc`を再読み込みします。
※ターミナル再起動でもOKです！

```
$ source ~/.zshrc
```

以下のコマンドでバージョンを確かめると

```
$ nodebrew -v
```

最新の`v1.1.0`になっていることがわかります。

```
$ nodebrew -v
nodebrew 1.1.0

Usage:
    nodebrew help                         Show this message
    nodebrew install <version>            Download and install <version> (from binary)
    nodebrew compile <version>            Download and install <version> (from source)
    nodebrew install-binary <version>     Alias of `install` (For backward compatibility)
    nodebrew uninstall <version>          Uninstall <version>
    nodebrew use <version>                Use <version>
    nodebrew list                         List installed versions
    nodebrew ls                           Alias for `list`
    nodebrew ls-remote                    List remote versions
    nodebrew ls-all                       List remote and installed versions
    nodebrew alias <key> <value>          Set alias
    nodebrew unalias <key>                Remove alias
    nodebrew clean <version> | all        Remove source file
    nodebrew selfupdate                   Update nodebrew
    nodebrew migrate-package <version>    Install global NPM packages contained in <version> to current version
    nodebrew exec <version> -- <command>  Execute <command> using specified <version>

```

# node v16.0.0 インストール
nodebrewのインストールが正常に完了したので、次に`node v16.0.0`をインストール

```
$ nodebrew install v16.0.0
```

以下のような文字が出力されたらインストールが完了します。

```
Fetching: https://nodejs.org/dist/v16.0.0/node-v16.0.0-darwin-arm64.tar.gz
####################################################################################################################### 100.0%
Installed successfully
```

以下のコマンドでインストールされたNodeのバージョンを確かめると

```
$ nodebrew ls
```

以下のようにでるので、

```
use v16.0.0
```

`v16.0.0`を使用する以下のコマンドを入力

```
$ nodebrew use v16.0.0
```

最後にNodeのバージョンを以下のコマンドで確認

```
$ node -v
```

以下のようにでれば成功です！

```
v16.0.0
```
Composerによるプロジェクトの作成(Laravelでウェブアプリを作ろう①)

PHPのフレームワークであるLaravelの環境設定について記載します

##利用環境
- MacOS Big Sur MacBookAir(13-inch, Mid2013)

##始める前に
まず、Laravelは通常のアプリケーションのようにダウンロードボタンからダウンロードするのではなく、ターミナルからコマンドを打って実行します。そのコマンドを打つために必要になるのが、composerというプログラムを利用します。そのため、まずはcomposerのインストールから始めます。

##homebrewの導入

###導入

```terminal:homebrewの導入
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
エラーが出なければOK

###確認

```terminal:homebrewの確認
brew -v
```
バージョンが正しく表示されればOK

##composerの導入

###導入

```terminal:composerの導入
brew install composer
```

エラーが出なければOK

###確認
```terminal:composerの確認
composer -V
```
バージョンが正しく表示されればOK
※「V」は大文字じゃないとダメ

##Laravelの導入

###導入

```terminal:Laravelの導入
composer global require "laravel/installer=~1.1"
```

###環境変数PATHの設定
このままでは入ってはいてもコマンドが有効になっていないため、下記を実行して有効にする

```terminal
echo "export PATH=~/.composer/vendor/bin:$PATH" >> ~/.bash_profile source ~/.bash_profile
```


##Laravelを使ってみる
###プロジェクトの作成

プロジェクトを作成したいディレクトリまで移動してから下記を実行

```terminal
composer create-project laravel/laravel プロジェクト名 --prefer-dist
```

###アプリケーションの実行

設定したプロジェクト名のディレクトリに移動してから下記を実行

```terminal
php artisan serve
```

表示されたURLにリクエストして、Laravelのページが表示されればOK
nuxt-i18nで、同じ言語・パスに対して違う単語を割り当てる

nuxt-i18nを使って、同じ言語・パスに対して違う単語を割り当てる方法を記載します。

# motivation

なぜそんな事をする必要があるのか？という不思議があると思います。これはOEM提供等によって、環境によってある特定の単語を読み替える必要がある、というような場合に利用するためのものです。

# 概要

- pluginsで`$t`の代替となる関数を定義する（ここでは`$gt`）
    - `$gt`の中では、設定に応じてパスの接尾辞を付加して`$t`を呼び出す
- テンプレートでは`$t`のかわりに`$gt`を呼び出す
- i18nタグ等では、接尾辞にあわせてデータを保存する

# plugins

以下の内容のファイルを作成します。ここではtsですがjsでもOKかと思います。

```gettext.ts
import VueI18n from 'vue-i18n'
import Vue from 'vue'

const env = localStorage.getItem('i18nType') || ''

Vue.use({
  install(Vue) {
    Vue.prototype.$gt = function(key: VueI18n.Path, values?: VueI18n.Values) {
      return this.$t(key + env, values)
    }
  }
})

declare module 'vue/types/vue' {
  interface Vue {
    $gt: typeof Vue.prototype.$gt
  }
}
```

ここでは、localStorageを直接使って適当にデータを取得しています。アプリケーションの仕組みに応じて、この部分を適宜書き換えるとよいと思います。
また、nuxt.config.jsに追記します。

```nuxt.config.js
export default {
  ...
  plugins: ['plugins/gettext.ts'],
  ...
}
```

# 実際の呼び出し方法

```some-page.vue
<template>
  <div>{{ $gt('Hello') }}</div>
</template>
<script>
// 省略
</script>
<i18n>
  {
    "ja": {
      "Hello": "やあ",
      "Hello_v2": "こんにちは！！！"
    },
    "en": {
      "Hello": "Hi",
      "Hello_v2": "Hello!!!"
    }
  }
</i18n>
```
これで、localStorageのi18nTypeに空文字列をセットすればHelloの内容が、_v2をセットすればHello_v2の内容が、それぞれ出力されるようになります。
laravelのよく使うmakeコマンド(メモ)

##コントローラを作成--


```
$ php artisan make:controller コントローラ名
```


##モデルを作成
※補足ですがモデル名は単数形にするのが慣例らしいです

```
$ php artisan make:model モデル名
```

末尾に`-m`を付けるとマイグレーションも一緒に作成してくれる

```
php artisan make:model モデル名 -m
```

##マイグレーションを作成

```
$ php artisan make:migration create_テーブル名_table --create=テーブル名
```

##シーダーを作成

```
$ php artisan make:seeder シーダー名
```

##Authのあれこれを自動生成する

```
$ php artisan make:auth
```
FireFoxプロファイルを目的によって使い分け

つい最近まで、FireFoxを１プロファイルで使っていた筆者。
ただ、
・（主に金融関係の）記事をクリップしたり
・ネットバンクやネット証券使ったり
・SNSに画像やコメント投稿したり
とやってると、アドオンは膨大になるわ履歴の掃除は大変だわで、けっこうメンテナンスに苦労してまして:cry:

で、ある日、１つのインストールで複数プロファイルを切り替えて使える方法があるとのことを知り、さっそくやってみます。


1)用途別プロファイルの作成
　DOSコマンドラインから
　　　Firefox -p
　とタイプすると、プロファイル管理画面が開きます。
　ここで、「新しいプロファイルを作成」を選び、設定保存場所を選び"XeroxUser"という名前で保存。
　![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/84636ca3-67c4-ac27-6fba-35bab301685c.png)


2)FireFoxのExeファイルに対してショートカットを２つ作成。
　リンク先の欄に
　　（FireFoxのインストールパス）\Firefox.exe -P （使いたいプロファイル名）
　を指定する。
　※筆者の場合、RAMディスクにインストールしているため、変なインストールパスとなっております・・・
　![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/7b5350c8-6bd2-ed53-a7e8-67c9ccc1b66e.png)


3)あとは、各々のプロファイルで起動して、設定やアドオンをいじってください。
　筆者の例です。

　■メインプロファイル：履歴やCookieは残したくない＆快適にブラウジング
　○about:configの指定："places.history.expiration.max_pages=30"：必要最低限の履歴を保持
　○アドオン：
　　・~~Adblock Plus　Web広告のブロック~~
　　　~~https://addons.mozilla.org/ja/firefox/addon/adblock-plus/~~
　　・uBlock Origin　Web広告のブロック：Adblock Plusよりも明らかに動きが軽い
　　　https://github.com/gorhill/uBlock#ublock-origin
　　・Disconnect　トラッキングのブロック
　　　https://addons.mozilla.org/ja/firefox/addon/disconnect/

　■サブプロファイル：ネットの記事をたくさんクリップしたい
　○about:configの指定："places.history.expiration.max_pages=9999999"：履歴たっぷり記憶する
　○アドオン：
　　・ScrapBee　Webページをローカルディスクにクリップ
　　　https://addons.mozilla.org/ja/firefox/addon/scrapbee/
　　・Link Status Redux　過去に訪問済みのリンク先を通知
　　　https://addons.mozilla.org/ja/firefox/addon/link-status-redux/
　　・HistoryBlock　アフリエイトなど意図しないサイトの履歴化をブロック
　　　https://addons.mozilla.org/ja/firefox/addon/historyblock/
　　・Delete History　指定した履歴を一括削除
　　　https://addons.mozilla.org/ja/firefox/addon/delete-history/