OmniAICreator/Qiita-1.07M huggingface dataset:
RPi4 に NetworkManager を導入し、wlan0 を ap にしたら嵌った

Raspberry Pi4(Buster) に NetworkManager を導入して wlan0 をアクセスポイントにしようと思ったら思いの外嵌ってしまった。参考資料がほとんどなかったのでメモしておきます。

# ことの経緯
今までは hostapd やら isc-dhcp-server やらを導入してアクセスポイントを構成していたが、(デフォルトではないものの）Buster になって NetworkManager が使える様になった。（前から使えていたのかな？？）

これで Ubuntu と同様にアクセスポイントを構成できる！と思ったのもつかの間、細かな点に相異があり、気をつけるべきポイントが多々あった。

# Network Manager の導入
これ自身はパッケージになっているので簡単。

```
sudo apt install network-manager
```

# 先に行く前に
dhcpcd5 を削除しないと競合する様だ。

```
sudo apt remove dhcpcd5
```

# ```/etc/dnsmasq.conf``` の設定
```bind-interfaces``` を追加する。でも後で ```ps ax``` してみると、この設定見ていないっぽい...

```NetworkManager.conf``` にdnsmasqの項目を追加する。

```:/etc/NetworkManager/NetworkManager.conf
[main]
dns=dnsmasq
```

# とりあえず NetworkManager を上げる
```/etc/wpa_supplicant/wpa_supplicant.conf``` にクライアントモードの設定が残っていたら削除する。```/sbin/wpa_supplicant``` が上がっていたら ```kill``` で落とした方が良いかも。
後、```dnsmasq``` が上がっていたら ```kill``` しないとポート53を占有してこの後の作業に支障が出るので落としておく。

アクセスポイントを構成するには NetworkManager を上げる必要があるため、

```
sudo systemctl restart NetworkManager
```

で起動する。

# アクセスポイントを作成する
以下のコマンドでアクセスポイントを作成する。

```
sudo nmcli device wifi hotspot ifnamne wlan0 ssid "MySSID" password "MyPassword"
sudo nmcli connection modify Hotspot autoconnect yes
sudo nmcli connection modify Hotspot ipv4.addresses 192.168.211.1/24
```

# お好みで WiFi 用 DNS エントリを切る
```:/etc/hosts.internal
192.168.211.1 raspberrypi
```

```:/etc/NetworkManager/dnsmasq.d/hosts.internal.conf
addn-hosts=/etc/hosts.internal
```

# NetworkManager を再起動する

```
sudo systemctl stop NetworkManager
```

とした後、```dnsmasq``` が残っていたら ```kill``` する。

```
sudo systemctl start NetworkManager
```

で Netowrk Manager の管理下でアクセスポイントが起動するはず。

(2020/4/28追記）本当はこのあと IP パケットのフォワード設定や iptables設定等があるが、他の方の記事に詳しいのでここで終わります。

# 今回嵌った点
1. ```/etc/dnsmasq.conf``` で ```bind-interfaces``` を定義しないと ```Addresss In Use``` エラーが発生する。（見てない気はしますが。）
2. Wifi の MAC アドレスは Network Manager を起動するたびに変化する様だ。```/etc/NetworkManager/system-connections/Hotspot.nmconnection``` の ```mac-address``` は eth0 のアドレスを設定しておく必要がある。
3. ```/etc/dnsmasq.conf``` の他の項目は無視される。と言うか、```dnsmasq``` の起動オプションに ``--conf-file=/dev/null`` とか指定されてしまうので、Network Manager 側の設定ファイルをいじるしかない。また、なるべく直接いじらず、```nmcli``` コマンドを使おう。
4. ```/etc/wpa_supplicant/wpa_supplicant.conf``` にクライアント設定が残っているとうまく動作しない（当たり前か）。

## おまけ
Android 端末でつなげていると、しばらくして「インターネット接続がありません」という現象が発生する。デフォルトでは省電力モードになっているためと思われる。

```
/usr/bin/iw dev wlan0 set power_save off
```

として様子を見る。```/etc/rc.local``` に上記を設定するとリブート時に自動的に設定される。
→ダメだった。時間を置くとインターネット接続がなくなる。もう少しよく考える必要がありそうだ。

(2020/5/17 追記)
RPi4 専用のパワー制御モードがある模様。

```
> sudo su
# echo 'on' > /sys/class/net/wlan0/power/control
```
としてしばらく放っておいたら現象が発生しなくなった。
Mac でファインマン図（Feynman diagram）を書く: MacOS High Sierra 10.13.6 で jaxodraw が使えるようになるまで

一昨々日のことで既に記憶が薄れつつあるが思い出せる範囲で。
# TeX 関係
まーなんか[このへん](http://osksn2.hep.sci.osaka-u.ac.jp/~taku/osx/install_ptex.html)から適当に入れて使ってました元々。
# axodraw のインストール
[axodraw4j.sty](http://jaxodraw.sourceforge.net/download/axodraw4j.html) を TeX で使ってる然るべきところに入れる。私の場合は TeXShop で書いてる途中のノートをコンパイルしてみたらこんなのが出たので、
<img width="542" alt="image.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184901/a00b698b-ab96-1088-6395-a63c2ae3d985.jpeg">

> /usr/local/texlive/2017/texmf-dist/tex/latex/

の下に

> /usr/local/texlive/2017/texmf-dist/tex/latex/axodraw

というフォルダを作って入れといた:

> /usr/local/texlive/2017/texmf-dist/tex/latex/axodraw/axodraw4j.sty

あと [axodraw.sty](https://www.nikhef.nl/~form/maindir/others/axodraw/axodraw.html) も同じとこに入れといた。（順序としては先に jaxodraw を入れてコンパイル（後述）しようとしたら動かず、axodraw.sty を入れてもうまく動かなかったので axodraw4j.sty も入れた。axodraw.sty も必要だったのかどうかは不明。）

「ターミナル」アプリケーションで（というか上の操作もターミナルからだから今さらそう書く意味もないが）、
> sudo mktexlsr

でスタイルファイルを読み込む。（sudo が要るかどうか知らんがおまじないでこういうときはやってます。）

# jaxodraw のインストール

テキトーに jaxodraw install mac とかでぐぐって

> http://jaxodraw.sourceforge.net/download/bin.html

からバイナリーをアプリケーションフォルダに入れる。アプリケーションのアイコンを右クリックして「情報を見る」から
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184901/56b5772d-2a20-1daa-bb15-c9bae1d26eba.png">
この「32ビットモードで開く」をチェックしないと駄目なのに注意。（入れたあとふつーにダブルクリックじゃ開かなくて**右クリックしてコンテキストメニューから「開く」**を選ばないと開かないのはいつもの通り。）

# jaxodraw のセットアップ

（マック標準のメニューじゃなくて）jaxodraw の方のメニューから Options → Preferences で以下のように打ち込む:
<img width="856" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184901/3d6d6336-443d-4adf-00ba-dec3acb0f4e3.png">
コピペできず手で入れないといけない＆**左下の Save を必ず押すこと（その前に OK を押しても保存されない）**に注意！
私は TeXShop を使ってるのでこのようにしましたが、他の設定だったらしかるべくやってください。Preferred Postscript viewer は見切れてますが
> /Applications/Preview.app/Contents/MacOS/Preview

となってます。

# 実際に書いてみる

まだ終わりじゃなくて、たとえばなんかこんなかんじ
<img width="992" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184901/5f06d427-f133-a9a0-e6c4-8a177df9a8ee.png">
でファインマン図を書いて、さてコンパイル（上のメニューバーの下のアイコンバーみたいなとこの**虫眼鏡をクリック**）、としても、
<img width="755" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184901/a6dd2e7b-fe3c-f23a-a5ae-cd4620eb9cef.png">
とエラーが出る。**諦めずに再度クリック**すると、ようやく結果が得られます:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184901/6650886d-898d-930a-f6f8-627f1675c41a.png)
Anaconda環境の再構築 PlanB　（TensorFlow1.13.1用）

# 現状把握
すでに入っている環境を確認

```
dpkg -l|grep nvidia
dpkg -l|grep cuda
```
取り除く

```
sudo apt-get --purge remove nvidia-*
sudo apt-get --purge remove cuda-*
sudo apt autoremove
```
リポジトリの登録

```
sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt-get update 
```

そしてCUDA　10.0をDL（パッチも）
https://developer.nvidia.com/cuda-10.0-download-archive?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1804&target_type=runfilelocal

再起動してインストール

```
sudo sh cuda_10.0.130_410.48_linux.run
```
# ここでインストール失敗
Driverのインストールを推奨されたので素直に従う。


```
===========
= Summary =
===========

Driver:   Installation Failed
Toolkit:  Installation skipped
Samples:  Installation skipped
```

/tmp にあるログを確認すると、どうやらカーネルにDriverがはいってエラーになっている模様。
下記サイト
https://qiita.com/Orihasam810/items/020d439d0aec2d90cd73
を参考にドライバ以外をインストールし、usr/local/cuda10.0の構築を目指す

そして成功。

```
===========
= Summary =
===========

Driver:   Not Selected
Toolkit:  Installed in /usr/local/cuda-10.0
Samples:  Installed in /home/lcj001, but missing recommended libraries
↑ちょっと惜しい？

```
その後も参考サイトに従い設定は無事終了。（いろいろ参考になりました）
# Anaconda Navigatorのインストール
サイトよりファイルをDL
`Anaconda3-2020.02-Linux-x86_64.sh`

```
bash Anaconda3-2020.02-Linux-x86_64.sh
```
# pythonのダウングレード　3.7->3.6.6 (2020/4/27現在)
```
conda install python=3.6.6
``` 
#Tensorflow 2.0のインストール->1.13.13へダウングレード
GUIからKerasをインストール（tesforflowからはインストール失敗）

```
sudo apt install python3-pip
pip3 install --upgrade tensorflow-gpu==1.13.1
pip3 install --upgrade tensorflow==.13.1
インストール後
pip list
---------
tensorflow-gpu 1.13.1 <-はいった。けどGUIだと2.0のまま
```
# 
課題
結局「混ぜるな危険」になってる、、
ただ`nvidia-smi`で未だ10.1だったり、ちゃんとテストが通るか検証する
#影響がでた点
numpyのダウングレード　1.18.3->1.14.15

```
pip uninstall numpy でOK
```
# 最終決着
上の手順でも☓。で、Anacondaのブラウザで2.0->1.13.1ダウングレードしたらできました。
とりあえず環境は整ったのだが、インポートエラーは治らず、、、

# 環境
-　python 3.6
-　nvidia driver 435
-　TensorFlow 1.13　（まだ）
-　Cuda 10.0
-　cuDNN 7.5.10-1


# 参考にさせていただいたサイト

【機械学習】Tensorflow・CUDA・cuDNN環境づくりの手引き
http://dslab.work/2019/09/19/post-224/

Ubuntu18.04にNVIDIAとCUDAを入れ直すことに
https://qiita.com/Yoshitaka_Youtuber/items/bd8edcb36396df878641

【Ubuntu18.04】Tensorflow2.0.0-GPU環境構築
https://qiita.com/Orihasam810/items/020d439d0aec2d90cd73

【対処法】Python3.7ではTensorFlowを利用できない..?
https://pycarnival.com/tensorflow_python37/
Python # ソート

# ソート

## `sort`と`sorted`
リストデータをソートするときに主に用いるのが、`sort`と`sorted`である。元々の内容を変更することなくソートした結果だけを得たいときは`sorted`を用いれば良い。また、`sorted`はタプルやイテレータなどにも用いることができる。挙動の違いは以下。

~~~python
a = [4, 6, 2, 8]
b = [5, 3, 9, 7, 1]

a.sort()
print(a)
print(sorted(b))
print(b)
~~~
実行結果
>[2, 4, 6, 8]
>[1, 3, 5, 7, 9]
>[5, 3, 9, 7, 1]

## `reserved`
`reserved`は逆順にソートしする際に用いる関数である。`sorted`メソッドのように、内容そのものは変更せずにソート後の結果だけを返す関数である。

~~~python
a = [4, 6, 2, 8]
print(reserved(a))
~~~
実行結果
>[8, 6, 4, 2]

##### (スライス指定子を用いた逆順ソート)
~~~python
a = [4, 6, 2, 8]
print(sorted(a)[::-1])
~~~
実行結果
>[8, 6, 4, 2]
Python #ループ

# ループ

## ループでタプルを取得する
ループによって取得するデータがタプルであるとき、複数の変数を定義してタプルを取得することができる。

~~~python
a = [(0, 1), (2, 3), (4, 5)]

for b, c in a:
    print(b, c)
~~~
実行結果
>0 1
2 3
4 5

## 逆順でループ
逆順にソートする`reversed()`メソッドを用いて、通常通りループを行えば良い。

~~~python
d = [0, 1, 2, 3, 4]
for i in reversed(d):
    print(i)
~~~
実行結果
>4
3
2
1
0

## インデックスを取得しながらのループ
`enumerate()`メソッドを用いることで、データのインデックスとインデックスによって指定されたデータからなるタプルのイテレータを取得できる。

~~~python
e = ['apple', 'orange', 'melon', 'lemon']

for i, j in enumerate(e):
    print(i, j)
~~~
実行結果
>0 apple
1 orange
2 melon
3 lemon


## 複数のリストを同時にループ
`zip()`メソッドは複数の引数から、同じインデックスにある値を並べたタプルからなるイテレータを返す。

~~~python
e = ['apple', 'orange', 'melon', 'lemon']
f = ['label1', 'label2', 'label3', 'label4']

for i, j in zip(f, e):
    print(i, j)
~~~
実行結果
>label1 apple
label2 orange
label3 melon
label4 lemon
Python #文字列型

学習メモ、備忘録

#文字列型
`str`クラスのインスタンスとして生成される。文字と文字列の区別はない。

## 基本的なメソッド
文字列型が備えている基本的なメソッド

~~~python
a = ' Hello, World \n'
b = a.strip()    # 前後の空白削除
c = b.lower()    # 小文字に変換
d = b.upper()    # 大文字に変換
e = b.swapcase()    # 大文字小文字を反転
f = b.title()    # 単語の先頭文字だけ大文字に変換
g = b.split(' ')    # 区切り文字を指定してリストに分割
h = b.splitlines()    # 改行で区切りリストに分割
~~~

## メモリ効率を考慮した文字列の作成
ファアイルからテキストデータを読み込み、そのデータを`str`インスタンスとして保存したいときなど、ループによって複数回の文字列の追加作業が発生するときには注意する。

#####ダメな例
~~~python
text = ''

with open('test.txt') as f:
    temp = f.readline()
    while temp:
        text += temp
        temp = f.readline()
~~~
この記述の仕方ではループ一回ごとに、一行分のメモリ確保・一つ前まで使用していたメモリと新しく読み込んだ分のメモリを新しく確保・一つ前まで使用していた古いメモリの解放といった処理を行うことになるので、非常にメモリ効率が悪く、処理速度も遅くなる。

#####正しい例
~~~python
list = []

with open('test.txt') as f:
    temp = f.readline()
    while temp:
        list.append(temp)
        temp = f.readline()

text = ``.join(list)
~~~
メモリ効率を損なわないようにするには、一旦リストとして保存して後から結合すうるという方法を取れば良い。
`join`メソッドを用いることで、区切りとなる文字を指定してリストの内容の結合ができる。

## 文字列の検索
`startswith()` : 文字列が引数で指定する文字列から始まっているかどうか
`endswith()` : 文字列が引数で指定する文字列で終わっているかどうか

`find()` : 引数で指定した文字列のインデックスを取得、見つからなかったら−１
`index()` : 引数で指定した文字列のインデックスを取得、見つからなかったら`ValueError`
`in`演算子を用いて含んでいるか否かの判定も行える。

`count()` : 引数で指定した文字列が登場する回数を数える。

## 文字列の置換
`replace()` : 一つ目の引数で指定した文字列を二つ目の引数で指定した文字列で置換する、対象の文字列が複数存在する場合も全てが置換される

## 正規表現
* `re`パッケージに存在するメソッド 
 * `re.match()` : 文字列の先頭部分が引数で指定した文字列とマッチする場合は、`match()`クラスを返し、マッチしない場合は`None`を返す。
 `re.match().span()`で、マッチした場所を取得できる。  
 * `re.search()` : 引数で指定した文字列とマッチする場合は、`match()`クラスを返し、マッチしない場合は`None`を返す。    
`re.search().span()`で、マッチした場所を取得できる。  
 * 正規表現を繰り返し用いる場合は`compile()`メソッドを用いてあらかじめコンパイルしておくと良い
 * `findall()` : マッチする文字列を全て取得しリストとして保存する。

`+`は一回以上の繰り返し、`*`は0回以上の繰り返しを表す。


## 外部変数による置換
文字列の前に`f`または`F`をつけることで、`{}`で囲まれた部分は外部変数や計算式で置換されるフィールドになる。

~~~python
a = 'World'
b = f'Hello, {a}'
print(b)

c = 10
d = 20
e = F'{c} + {d} = {c+d}'
print(e)
~~~
実行結果
>Hello, World
10 + 20 = 30

## フォーマットの指定
`format()`メソッドは、引数で`{}`フィールド内のインデックスや変数を置換する。

~~~python
a = '{0} is {1}'
b = a.format('apple', 'red')
print(b)

c = '{fruits} is {color}'
d = c.format(fruits = 'melon', color = 'green')
print(d)
~~~
実行結果
>apple is red
melon is green

### 右寄せ・左寄せ・中央寄せ
`:`の後に指定する文字列で埋めて文字列を寄せる。

~~~python
a = 'Title'
b = '{:<10}'.format(a)    # 'Title     '
c = '{:>10}'.format(a)    # '     Title'
d = '{:-^10}'.format(a)    # '--Title---'
~~~
Ruby on Rails チュートリアル 15日目

##15日目
今日は、昨日詰まっていたところの解消を目的に進めていました。

```
   1) Failure:
SessionsHelperTest # test_current_user_returns_right_user_when_session_is_nil [/home/ec2-user/environment/sample_app/test/helpers/sessions_helper_test.rb:11]:
--- expected
+++ actual
@@ -1 +1 @@
-# <User id: 762146111, name: "Michael Example", email: "michael@example.com", created_at: "2020-04-27 02:58:57", updated_at: "2020-04-27 02: 58:58 ", password_digest:" $ 2a $ 04 $ ZblkO9f6bDxdsuCMYjI6q.A6tq2dIbPrVmUFcXH6 / iV ... ", remember_digest:" $ 2a $ 04 $ dxJ9bP1SpmdDwO.qCRx7NeCp3ZUU3ZKU3KK33KZ3UKK3OBKZ3UKZ3UKZ3UK3OBK.
+ nil
```
これだけは解消することが出来ませんでした。どのファイルを直せばいいのか教えていただけると嬉しいです。
もう片方の方は、別ファイルに間違えを発見できたので修正できました

もし、明日すぐに解消できるようなら11章をやりたいです。
Symfonyの構造　annotation

annotationは標準機能ではないが、rootディレクトリをYAMLで作るよりも簡単なのでしばしば使われます。

まずComposerをinstallしましょう。

```terminal
brew install composer
```
次にannotationをインストールします。

```terminal
composer require annotations
```

##annotationを使ってみる
annotationはroutes.yamlをphpコードの中に表現するやり方なので、config/routes.yamlの中身を全てコメントアウトします。
そして、下記を書き換えます。


```QuestionController.php
<?php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class QuestionController
{
    
    /**
     * @Route("/")
     */
    public function homepage()
    {
        return new Response('Hello World');
    }

    /**
     * @Route("/test/{slug}")
     */
    public function show($slug)
    {
        return new Response(sprintf(ucwords(str_replace('-', ' ', $slug))));
    }
}

```

下記を書くことで、slugの部分をURLで指定することができます。
https://localhost:8000/test/aiuoe
を指定すると
生成されたページにAiuoeと表示されます。

```php
    /**
     * @Route("/test/{slug}")
     */
```


##参考
[Annotation & Wildcard Routes > Charming Development in Symfony 5 | SymfonyCasts](https://symfonycasts.com/screencast/symfony/annotations#play)
Android StudioのLiveTemplateを使う

# 概要
Android StudioのLive Templateを導入する時の備忘録

# 手順
1. 設定 > Editor > Live Templateを開く
2. +ボタンでLive Templateを追加
3. ①の部分にトリガーになるワードを入れる
4. ②の部分に挿入したいコードを追加
5. ③の部分で何の言語か選ぶ**（ここを忘れると補完されないので注意）**
6. ※もし変数があれば④を押して変数設定へ
7. okを押して完了

<img width="1010" alt="スクリーンショット 2020-04-27 11.59.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104317/7d9918fc-981f-a1b2-6c04-09a8c25453e8.png">

## 変数設定について
下記参照
https://pleiades.io/help/idea/template-variables.html
【Node.js】nvmの導入

# nvmとは？
Node.jsのバージョン管理ツールです。
Node.jsのバージョンによっては互換性がなかったりする為、nvmで管理する。

# 環境
- macOS Catalina
- zsh

# インストール
[公式ドキュメント](https://github.com/nvm-sh/nvm/blob/master/README.md#installing-and-updating)に従いながらインストールする。
以下のコマンドを実行する。

```zsh
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
```

**.zshrc**に以下の文を追記しターミナルを再起動すると、nvmコマンドが使えるようになる。

```zsh
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"  # This loads nvm
```

バージョンを確認してみる。

```zsh
$ nvm --version
0.35.3
```
# Node.jsをインストール

インストールできるバージョン一覧を確認する。

```zsh
$ nvm ls-remote
v0.1.14
...
v14.0.0
```

v10.19.0をインストールする。

```zsh
$ nvm install v10.19.0
```

Node.jsのバージョンを確認してみる。

```zsh
$ node -v
v10.19.0
```

# Node.jsのバージョン切替

nvmでインストールされたNode.js一覧を確認する。

```zsh
$ nvm ls
->     v10.19.0
       v12.16.2
```

バージョンを切り替え、Node.jsのバージョンを確認してみる。

```zsh
$ nvm use v12.16.2
$ node -v
v12.16.2
```
tmuxを使ってサーバークライアント通信してみた

#はじめに
この記事はなんとなくJSとかをやっている学生がメモ変わりに書いているものです。内容は期待しないでください。

#1.そもそもサーバークライアント通信とは
サービスを提供するコンピュータのサーバとサービスを受け取るコンピュータのクライアントで行う通信方式。ネットワークとかはサーバから放射状にクライアントに繋がっています。これとよく対比されるのがP2P通信でP2P型は全てのコンピュータがサーバとクライアントを兼ね備えています。

#2.tmuxを起動してみる
今回はUbuntuで行うのでiTerm2で仮想環境を起動するよ。

起動したところで
1.Virtual Box(バーチャルボックス)
2.Vagrant（ベイグラント）
という2つのソフトウェアを使った仮想環境でUbuntuを使用します。
cd ~/vagrant/ubuntu
vagrant up
vagrant ssh

Ubuntuがインストールされたディレクトリに移動。vagrant upは仮想的なPCにインストールされたUbuntuを起動するコマンドで,vagrant sshはVagrantの仮想マシンがセットされている状態でSSHに接続します。

コンソールが起動したところでtmuxを起動。
```tmux```
ここでtumuxの簡単なコマンドをまとめておきます。

|コマンド|意味|記述する場所|
|:---:|:---:|:---:|
|tmux|起動|コンソール|
|control+b→d|仮想端末から離れる|仮想端末|
|tumux a|仮想端末に接続する|コンソール|
|control+b→c|ウィンドウ作成|仮想端末|
|control+b→数字|数字にウィンドウ移動|仮想端末|
|control+b→p|前の数字に移動|仮想端末|
|control+b→n|後の数字に移動|仮想端末|
|control+b→x|ウィンドウを閉じる|仮想端末|

#3.tmuxを使ってサーバークライアント通信をする

まずウィンドウを2つにしたところで片方のウィンドウに以下の内容を記述します。
```while :; do (echo "Thank you!") | nc -l 8000 ; done
```
whileというループをを行うため,while:;doとdoneの中にループする内容を記述しています。while内のncはncコマンドというもので今回は
```nc -l ポート番号```
という-lでリッスンモードとし指定したポート番号で受け待ちを行っています。今回の場合はアクセスがあった場合はechoでThank you!と表示するようにしています。

次にもう片方に以下のように記述します。
```telnet 127.0.0.1 8000
```
127.0.01は自分自身を示すIPアドレスです。この場合telnetを使ってIPアドレスの8000番ポートにアクセスしています。telnet は、リモートのコンピューターにアクセスし、ターミナルのセッションを開始するためのコマンドです。セキュリティ上の理由からsshなどの代替プロトコルを使うことが多いらしい。

先ほどの記述を実行するとechoの内容が表示されているためサーバークライアント間通信を行うことができました!!

#4.ついでにtmuxでチャットをしてみる
ncコマンドのファイルを転送する(FTP)を使ってチャットをしてみます。
サーバ側
```nc -l -p ポート番号　ファイル名```
接続側
```nc ホスト名　ポート番号　ファイル名
```
以上を記述してみます。
今回はサーバ側に
```nc -l -p 8000```
接続側に
```nc 127.0.01 8000```
を記述しました。
コンソールに文章などを記述し,サーバ側と接続側に文章が記述されていれば成功です。お疲れ様でした。




###IPアドレスとは
IPアドレスとは,0~255の整数4つで構成された32bitサイズのインターネット上の住所です。
IPはInternet Protocol（インターネット・プロトコル）の略称。
Go言語のループ中でポインタ値を更新するときの落とし穴

# 問題

スライス`ts`をイテレートして、条件（ここでは単純に`t == "c"`）に合う値のポインタを見つけたいとします。

[The Go Playground](https://play.golang.org/p/Ynz4tHXglM2)

```
func main() {
	ts := []string{"a", "b", "c", "d", "e"}
	p := &ts[0] // 初期値は"a"とする。
	for _, t := range ts {
		if t == "c" {
			p = &t
		}
		fmt.Println("current p = " + *p)
	}
	fmt.Println("final p = " + *p)
}
```

これで、

```
current p = a
current p = a
current p = c
current p = c
current p = c
final p = c
```

と出力されると思いましたか！？私は思いました。

残念ながら、こうなります。

```
current p = a
current p = a
current p = c
current p = d
current p = e
final p = e
```

ループごとに`t`を定義しているのかと思い込んでいましたが、どうやらイテレートを通して同じ変数らしく、書き換わっていってしまっているのでしょう。

# 解決

コピーが発生しますが、ポインタではなく値を保持するか、

```
func main() {
	ts := []string{"a", "b", "c", "d", "e"}
	p := ts[0] // 初期値は"a"とする。
	for _, t := range ts {
		if t == "c" {
			p = t
		}
		fmt.Println("current p = " + p)
	}
	fmt.Println("final p = " + p)
}
```

元のスライスへの参照を保持するか、

```
func main() {
	ts := []string{"a", "b", "c", "d", "e"}
	p := &ts[0] // 初期値は"a"とする。
	for idx, t := range ts {
		if t == "c" {
			p = &ts[idx]
		}
		fmt.Println("current p = " + *p)
	}
	fmt.Println("final p = " + *p)
}
```

くらいしかないですかね。

# 2020-04-30 追記

公式ドキュメントに[言及](https://github.com/golang/go/wiki/CommonMistakes#using-reference-to-loop-iterator-variable)がありました。

これに従うと、

```
func main() {
	ts := []string{"a", "b", "c", "d", "e"}
	p := &ts[0] // 初期値は"a"とする。
	for _, t := range ts {
		t := t
		if t == "c" {
			p = &t
		}
		fmt.Println("current p = " + *p)
	}
	fmt.Println("final p = " + *p)
}
```

でも良いということですね。
`t := t`ってすごい違和感ありますけどね・・・。
uGUIのDropdown

#概要
Unityのバージョンは2018.4LTS版

uGUIのDropdownについてのメモです。一通りの機能についての解説します。
Dropdown を追加すると画面上のCanvasの子に追加されます。構成は以下。

- Dropdown
 - Label（ドロップダウンを開いていないときのテキスト）
 - Arrow（ドロップダウンの右側の画像）
 - Template（ドロップダウンを開いたときの表示設定。通常は非アクティブ）  

###Dropdownコンポーネント
- Interactable（入力を受け付けるかの設定）
- Transition（アクションに関する設定）
- Navigation（ナビゲーション設定）
- Template（ドロップダウンを開いた時の表示するテンプレート）
- Caption Text（現在選択されているオプションのText）
- Caption Image（現在選択されているオプションのImage）
- Item Text（各項目のText）
- Item Image（各項目のImage）
- Value（現在選択されているオプションのインデックス）
- Options（選択したときに表示する文字とImageを設定）

参考ページ
https://docs.unity3d.com/ja/2018.4/Manual/script-Dropdown.html
https://hiyotama.hatenablog.com/entry/2016/07/10/080000

#DropdownのSprict制御
```.cs
  
  var dropdown = GetComponent<Dropdown>();

  // ドロップダウンのリストクリア
  dropdown.ClearOptions();

  // ドロップダウンのリストに要素追加
  Dropdown.OptionData data = new Dropdown.OptionData();
  data.text = "Option 1";
  dropdown.options.Add(data);

  // リストから要素削除
  dropdown.options.Add(data);

  // 選択中の要素取得
  int a = dropdown.value
```

参考ページ
https://docs.unity3d.com/ja/2018.4/ScriptReference/UI.Dropdown.html
http://fantom1x.blog130.fc2.com/blog-entry-235.html
StringIOでS3にファイルアップロードする時のエンコーディング

# io.StringIOのencodingはutf-8固定です
コンテンツには非漢字の場合、SJIS
コンテンツには漢字がある場合、UTF-8（ディフォルト）
https://gihyo.jp/dev/serial/01/pythonhacks/0004
使用fernflower反编译JAR包

垃圾jd-gui，天天崩溃，不然就是反编译出错，找了下直接用fernflower。

从这里下载：http://files.minecraftforge.net/maven/net/minecraftforge/fernflower/

然后执行命令

```bash
java -jar fernflower-390.jar -dgs=1 jdbc.jar ./src/
```

反编译后的代码会在当前src目录下，重命名为zip解压就行了。
Flipbooksを使ったプレゼンテーション

## １．はじめに
`Flipbooks`は、コードとその出力を並べて表示し、ステップバイステップでコードに対する出力を説明できるHTMLプレゼンテーションを作成する`R`のパッケージです。RMarkdownで記述するため`knitr`と表示のために`xaringan`を使用します。

`Flipbooks`を使用すると、次のようはプレゼンテーションを作成できます。
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618305/2ad0c6ae-26a3-8af0-c33e-1e33f251becf.gif)
コードを追いながら出力を確認できますから、教育関係で重宝しそうですね。

パッケージの詳細は、[Flipbooks](https://evamaerey.github.io/flipbooks/about)のページに詳しく書いてあります。ここでは、インストールから簡単な使い方までを紹介します。

## ２．パッケージのインストール
### (1) xaringanのインストール
まず、`xaringan`をCRANから取得しインストールします。`RStudio`のConsoleから次のようにインストールします。

```R:
install.packages("xaringan")
```
### (2)flipbookrのインストール
同じく`RStudio`のコンソールから次のようにインストールします。

```R:
remotes::install_github("EvaMaeRey/flipbookr")
```

### (3)RStudioを再起動します。
これでインストールは完了です。

## ３．使ってみる
続いて実際に使用してみます。
### (1)テンプレートの読込
手っ取り早いのは、テンプレートを見てみることです。
パッケージのインストールに成功していると、`RStudio`にてFile > New File > R Markdown で開くダイアログで From Templeteの中にEmbedding a Mini Flipbook / Pthon Flipbook / A Minimal Flipbook が出現します。
これらがテンプレートです。ここでは、A Minimal Flipbookを選択してみましょう。
### (2)HTMLの出力
`RStudio`で`knit`するとHTMLが出力されます。
内容を確認すると実際の使い方の紹介が実例と共に記述されています。出力の様子をコードと対比させて表示できますので、理解しやすいと思います。特に、グラフなどデータを視覚化する場面で有効そうです。
### (3)簡単な例
上に紹介した`R`のデータセットirisを使ったグラフは以下のコードで表示されます。

<pre><code>

---
title: "Presentation flipbooking"
author: "DiNOV"
date: "2020/04/27"
output:
  xaringan::moon_reader:
    lib_dir: libs
    css: [default, robot, ninjutsu]
---

```{r setup, include = F}
knitr::opts_chunk$set(fig.width = 6, message = FALSE, warning = FALSE, comment = "", cache = FALSE, fig.retina = 3)
library(flipbookr)
library(tidyverse)
```

```{r iris, include = FALSE, fig.height=5}
iris %>% 
  ggplot() +              
  aes(x = Sepal.Length) +
  aes(y = Petal.Length) +
  geom_count(
    alpha = .8,
    color = "blue" 
    ) + 
  geom_smooth(method = lm, se = FALSE) +
  coord_cartesian(xlim = range(iris$Sepal.Length),
                  ylim = range(iris$Petal.Length)) +
  theme(legend.position = c(.9, .2))
```

`r chunk_reveal("iris", break_type = "auto")`

```{css, eval = TRUE, echo = FALSE}
.remark-code{line-height: 1.5; font-size: 80%}
```
</code></pre>


## ４．最後に
Markdownnの練習と、備忘録も兼ねて`Flipbook`の紹介でした。このようなツールを使い、わかりやすいプレゼンテーションや授業をできそうです。
UdonSharp日記～ローカルプレイヤーの座標の取得～

#プレイヤーの座標を得るよ
###参考文献
[やぎりさんのUdonSharpコード走り書きメモ](https://yagiri000.hatenablog.com/entry/2020/04/04/162312)・・・プレイヤーのトラッキング情報を取得するテスト

###やったこと
VRCPlayerApiでユーザーのトラッキングデータにアクセスしてHeadの位置を取得。
それをテキストに入力してワールド上に表示
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Udon挑戦中<br>動画は頭の位置を取得するテスト<br>デスクトップモードです <a href="https://t.co/cF98qt1Xay">pic.twitter.com/cF98qt1Xay</a></p>&mdash; はんちょ (@sadimensions) <a href="https://twitter.com/sadimensions/status/1254603373392715776?ref_src=twsrc%5Etfw">April 27, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

###やり方
まずワールドにCanvasとTextを設置します。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627563/ab56a412-5081-9edf-79a4-92f484359ce1.png)

そして床のplane(cubeでも何でもよい)にUdonSharpを適用し、次のコードを記載します。

```c#:load.cs

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using UnityEngine.UI;

public class Load : UdonSharpBehaviour
{
    public GameObject prefab;//←これは使ってないよ
    public Text debugText;

    void Update()
    {
        var player = Networking.LocalPlayer;

        if (player != null)//Unityの再生ボタンで実行すると変数がnullになるらしいよ
        {
            //playerの位置を取得（位置は頭の位置を使用）
            var headData = player.GetTrackingData(VRCPlayerApi.TrackingDataType.Head);

            debugText.text = string.Format("Head-Pos: {0}\r\n", headData.position.ToString());
        }
    } 
}
```

そしてこのコードとdebugTextを繋げます。（適切な用語ってあるのかしら？）
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627563/1771ac4c-83f1-11f4-960f-0e1f1a3074f5.png)

結構簡単ですね。
【今日Javascriptを始めた人向け3】変数の代入演算子

[【今日Javascriptを始めた人向け２】](https://qiita.com/TOMARU4400/items/47ad96888709cff95685)の続きです。



変数の値の更新に変数自身の値を使用できます。
それによって**「今の値から1を足した値を代入する」**的なことも可能になります。


```javascript:sample.js
let hoge = 5;
hoge = hoge + 1;
console.log(hoge);
```


まず1行目で変数hogeを宣言・代入しています。

```javascript

let hoge = 5;
```



続いて2行目以降で
**hoge = hoge + 1;**を実行することによってhogeの値は6になります。


```javascript
hoge = hoge + 1;
console.log(hoge);
```

```:実行結果
6
```



これは、代入する時にはまず右側から実行されて、右側の結果が左側に代入されるからです。
つまり上記コードの

```javascript

hoge = hoge + 1;
```
は
hoge = 5 + 1;と同じ事なので、hogeの値は6になります。

また、

```javascript:

hoge = hoge + 1;
```

は

```javascript:
hoge +=  1;
```

と省略して書く事も可能です。以下の表は一例ですがまだたくさんの演算子が用意されています。ご自身でもぜひconsole.logで遊んでみてください！

|  演算子 | 　　使用例　　 | 　　　意味　 　　 |
| :---: | :---: | :---: |
| += | hoge += 1 | hoge = hoge + 1 と同じ |
| -= | hoge -= 1 | hoge = hoge - 1 と同じ |
| *= | hoge *= 1 | hoge = hoge * 1 と同じ |
| /= | hoge /= 1 | hoge = hoge / 1 と同じ |
| %= | hoge %= 1 | hoge = hoge % 1 と同じ |
C#のLinq to xmlでxmlの作成を行う

C#でxmlの作成を行ったので方法を残す


#属性のあるxml要素の構築
要素はXElement、属性はXAttributeを使う

```C#:xml.cs
XElement element =
    new XElement("person",  
        new XElement("person",
        new XAttribute("Type", "engineer"),
            new XElement("Name", "Yamada Taro"),
            new XElement("skill",
                new XElement("language", "C#")
           )
       )
   );
```

xml出力したもの

```xml:test.xml
<person>  
  <person Type="engineer">  
    <Name>Yamada Taro</Name>  
    <skill>  
      <language>C#</language>  
    </skill>  
  </person>  
</person>  
```

#namesapceがある場合
XNamespaceでnamespaceを定義する

```C#
XNamespace ns= "http://www.test";
```


```C#:xml2.cs
XElement element =
    new XElement("person",  
        new XAttribute(XNamespace.Xmlns + "ns", ns),
        new XElement("person",
        new XAttribute("Type", "engineer"),
            new XElement(ns + "Name", "Yamada Taro"),
            new XElement("skill",
                new XElement("language", "C#")
           )
       )
   );
```

xml出力したもの

```xml:test2.xml
<person xmlns:ns="http://www.test" >  
  <person Type="engineer">  
    <ns:Name>Yamada Taro</Name>  
    <skill>  
      <language>C#</language>  
    </skill>  
  </ns:person>  
</person>  
```

#既存のxmlに要素を追加する場合
要素を追加したいxmlを読み込み、追加したい位置を指定

```C#
 XElement xml = XElement.Load(test.xml);
 XElement child1 = xmlTree.Element("Name");  
 child1.AddAfterSelf(  
    new XElement("ID", 10)  
 );  
```
Nameの後ろにIDが追加される

```xml:test.xml
<person>  
  <person Type="engineer">  
    <Name>Yamada Taro</Name>  
    <ID>10</Id>  
    <skill>  
      <language>C#</language>  
    </skill>  
  </person>  
</person>  
```

参考
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/linq/creating-xml-trees-linq-to-xml-2

https://docs.microsoft.com/en-us/dotnet/api/system.xml.linq.xnode.addbeforeself?view=netcore-3.1
SourceTreeで別のプロジェクトの内容がクローンされる。

1.Githubの設定(2段階認証)
2.GithubにProjectA,ProjectBというリポジトリを作成済み。
3.SourceTreeにはProjectAのローカルリポジトリがある。
4.ProjectBのクローンを実行する
5.取得される情報がProjectAの内容。
6.フォルダの中もProjectAのファイルやソースが入っている。

同フォルダ内や、別フォルダに変えてみましたが、何故かProjectAのデータが取得されます。

対処方法を教えてください。

解決しました。
ターミナルで確認したところ、ターミナル全体でProjectAを使用するように
remote.origin.urlのurlがなっていました。
そのため

git config --global --unset remote.origin.url

のコマンドでセットされていたURLを削除したところ、ProjectBがクローンされました。
VueアプリケーションをDockerのNginx上で公開する

# 概要
Vue CLIのドキュメントに記載の内容ほぼそのままですが
VueアプリケーションをNginx上で公開する方法です。
https://cli.vuejs.org/guide/deployment.html#docker-nginx

# フォルダ構成
最終的なフォルダ構成は以下のようになります。

```
.
├── docker-compose.yaml
└── nginx
    ├── Dockerfile
    ├── app
    │   └── vue-app
    ├── .dockerignore
    └── nginx.conf
```

# Vueアプリケーションの作成
まずは公開するVueアプリケーションを作成します。
今回はパッケージマネージャをYarnに設定して、その他はデフォルトで作成しています。

```
$ mkdir -p nginx/app
$ cd nginx/app
$ vue create vue-app
```

作成が完了したところで一度サーバーを起動して確認してみます。

```
$ cd vue-app
$ yarn serve
```

以下のURLを開いてVueアプリケーションが表示されていればOKです。
http://localhost:8081/

# Docker上での立ち上げ
次にDocker上で立ち上げるために以下のファイルを作成していきます。
作成する場所はフォルダ構成を参考にしてください。

``` docker-compose.yaml
version: '3'
services:
  nginx:
    build: ./nginx
    ports:
      - "8080:80"
```

yarn installでキャッシュを利用するために、
先にpackage.jsonとyarn.lockをコピーしてインストールを行っています。

``` :Dockerfile
FROM node:14.0.0-alpine3.11 as build-stage

WORKDIR /app
COPY app/vue-app/package*.json ./
COPY app/vue-app/yarn.lock ./
RUN yarn install
COPY app/vue-app/ ./
RUN yarn run build

FROM nginx:1.17.10-alpine as production-stage

RUN mkdir /app
COPY --from=build-stage /app/dist /app
COPY nginx.conf /etc/nginx/nginx.conf
```

ローカルのnode_modulesとdistをDockerと干渉させないためにignoreに追加します。

``` :.dockerignore
**/node_modules
**/dist
```

ここはドキュメントの内容そのまま。

``` nginx.conf
user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
  worker_connections  1024;
}
http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;
  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
  access_log  /var/log/nginx/access.log  main;
  sendfile        on;
  keepalive_timeout  65;
  server {
    listen       80;
    server_name  localhost;
    location / {
      root   /app;
      index  index.html;
      try_files $uri $uri/ /index.html;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   /usr/share/nginx/html;
    }
  }
}
```

ファイルを全て作成したらコンテナを起動します。
（docker-compose.yamlのあるディレクトリで実行する）

```
docker-compose build
docker-compose up -d
```

コンテナが立ち上がってから以下のURLを表示するとNginx上でVueアプリケーションが公開されていることが確認できます。
http://localhost:8080/
プロジェクトのPHPライブラリの脆弱性をチェックするGithub Actionを作りました

# はじめに
こんにちは[@glassmonekey](https://twitter.com/glassmonekey)です。PHPを書く機会が増えそうなので、以前作って放置していた[php-audit-action](https://qiita.com/glassmonkey/items/ef49c91d597e684a7ae7)をcomposer.lockから脆弱性情報があればissueを立てるactionにしてみました。

この記事では、使い方や実装の紹介をします。

ソースコードなどは下記となります。バグ報告や要望などお待ちしております。よしよかったらStarください😂
[ソースコード](https://github.com/glassmonkey/actions-php-audit)
[マーケットプレイス](https://github.com/marketplace/actions/php-audit-action)

#  使い方
Github Actionの使い方そのものはこの記事では解説をしません。公式の[Getting started with GitHub Actions](https://help.github.com/en/actions/getting-started-with-github-actions)あたりを見て初めて見ると良いかなと思います。

下記のような設定ファイルを配置します。
今回はcron的に定期実行を想定したフックにしています。UTCなので要注意です。

.github/workflows/audit.yml

```yml
name: Alert Composer Audit
on:
  schedule:
    - cron: 0 15 * * 0 # At 00:00 on Monday. (JST)
jobs:
  check-validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: glassmonkey/actions-php-audit@v1
        name: php-audit
        env:
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
        with:
          ISSUE_LABELS: bugs,scheduled
          WORK_DIR: ""
```

## パラメータについて
* WORK_DIR  
脆弱性をチェックするcomposer.lockへの相対パスになります。デフォルトは空文字で、プロジェクトルートに配置している扱いとなります。

* ISSUE_LABELS
 パラメータでラベルも自動付与できるようにしています。上記の例だと`bugs`と`scheduled`のラベルを付与できるようにしています。デフォルトは空です。

# 結果
https://github.com/glassmonkey/actions-php-audit/issues/8
<img width="692" alt="スクリーンショット 2020-04-27 1.06.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152938/ac6eb11d-0123-a7ec-1896-93ca8d6d135c.png">

項目ごとにチェックボックスで状況を把握できるようにしているので、これを元に作業するもよし、放置するもよしという感じです。

なお、脆弱性が存在しない場合はv1の時点ではなにもしません。もし要望ありましたらコメントやDMをいただけると嬉しく思います。

# 実装について
[sensiolabs/security-checker](https://github.com/sensiolabs/security-checker)を利用しています。

情報源の[PHP Security Advisories Database](
https://github.com/FriendsOfPHP/security-advisories)の内容を元に教えてくれるツールになります。

詳細に関しては[sensiolabs/security-checkerでComposerライブラリの脆弱性チェック](https://qiita.com/k-holy/items/1365446217564d2b595a)で紹介されているので、興味があればそちらをご確認ください。

一部メッセージの整形にはgoを使いました。

# おわりに
突貫ではありますが、わりと実用的なActionができてわりと満足です。
脆弱性まわりのバージョンアップへの対応は必須なわりに、情報のキャッチアップが属人的だったり、優先度が見えにくいことが多い気がするので、もし仕組み化に寄与できたのなら嬉しく思います。

質問やアドバイス等があればコメントか[@glassmonekey](https://twitter.com/glassmonekey)までメッセージをいただけると嬉しく思います。
Sambaを使ったディレクトリの共有

# 目的
2台のLinuxサーバ間で簡単にディレクトリを共有します。
DNSラウンドロビンで2台のLinuxサーバを負荷分散しています。
letsencryptの証明書を更新する際、どちらのサーバにリクエストが届くか不確定のため、更新が失敗することがあります。
certbot-auto の -w (--work-dir) で指定するディレクトリを両サーバで共有することにより、更新の失敗を回避します。

# Sambaサーバ（マウントされる側）の構築
## Sambaのインストール
```shell
yum -y install samba
```

## 共有の設定
```config
# アクセスを許可するIPの追加
hosts allow = 127. <マウントする側のIP>
 
# 認証なしに設定
security = share
 
# 最終行に追記
[letsencrypt]
   path = /opt/letsencrypt/public_html # certbot-auto -w で指定したディレクトリ
   writable = no      # 書き込みOK
   guest ok = yes     # ゲストユーザーOK
   guest only = yes   # 全てゲストとして扱う
   create mode = 0777 # フルアクセスでファイル作成
   directory mode = 0777 # フルアクセスでフォルダ作成
   share modes = yes
```

## ファイアウォール(iptables)の設定追加
```config
-A INPUT -m state --state NEW -m tcp -p tcp --dport 139 -s <マウントする側のIP>/32 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 445 -s <マウントする側のIP>/32 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 137 -s <マウントする側のIP>/32 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 138 -s <マウントする側のIP>/32 -j ACCEPT
```

## smbd、nmbdの起動設定
```shell
service smb start 
chkconfig smb on
service nmb start 
chkconfig nmb on
```

# クライアント側（マウントする側）の設定
## Sambaクライアントのインストール
```shell
yum install samba-client cifs-utils
```

## 接続確認
```shell
smbclient -L <マウントされる側のサーバ名>
```

## マウント
```shell
# マウント用ディレクトリ
mkdir /opt/samba/letsencrypt

# マウント
mount -t cifs //<マウントされる側のサーバ名>/letsencrypt /opt/samba/letsencrypt -o user=root

# アンマウント
umount -l /opt/samba/letsencrypt/
```
来たるべきGmailのOAuth2対応に向けてのメモ

#これは何？

Gmailのセキュリティ設定がきつくなるので、現在平和に各種MUAからむふふんとPOP/IMAPでとってる人が気をつけておくべきところのメモです。

#Gmailとは

あえてなにかということはないですが、Googleのサービスであり、Googleのアカウントでのアクセス（または個別に発行したアプリパスワードでのアクセス）が必要です。

##サービスをまたいだアカウントのアクセスについて

アクセス先のサービスに俺のアクセスは大丈夫だと言わせて通す。

これまではアプリ経由でも要素があってたらアクセスができたけど、「そのアプリ経由のアクセス、おまえからやろな？　ええんか？」というのが厳しくなっていく。そりゃそのほうがいい。

#アプリケーションでの対応

## Gmailについて

- 安全性の低いアプリと Google アカウント,
https://support.google.com/accounts/answer/6010255

- 安全性の低いアプリへのアクセスを管理する, https://support.google.com/a/answer/6260879?hl=ja&ref_topic=7558663

## アプリケーションでの対応

それぞれのMUAとかで調査しよう。

# つながらないときに調べるところ

Googleでは下記に記載がある。

- 他のメール プラットフォームで Gmail のメールをチェックする, https://support.google.com/mail/answer/7126229?hl=ja

下記はサイボウズの例だけど、ほかのアプリケーションでも役に立つ。

- Gmailのメールアカウントが設定できません。／「Garoon クラウド版」よくあるご質問(FAQ), https://faq.cybozu.info/alphascope/cybozu/web/garoon/Detail.aspx?id=2284

ここでも挙げられているのは、Gooleアカウントから任意のアプリケーションでのアクセスを許可すること。下記URLは、作業したいアカウントでログインして同じブラウザで開く。

https://google.com/accounts/DisplayUnlockCaptcha

## アプリパスワードについて

Googleではメインのパスワードとは別に、アプリパスワードの発行ができる。

- アプリ パスワードでログイン, https://support.google.com/accounts/answer/185833?hl=ja

## Googleでログイン になっていくのかしら

Google認証でログインさせて使うアプリケーションも増えているようである。スマートフォン関係詳しくないのでよくわかってないけど。



#2020年4月27日時点での情報

- 「安全性の低いアプリによる接続」の無効化が当面延期へ , https://gsuiteupdates-ja.googleblog.com/2020/04/blog-post.html

とはありますけど、中止になることはないし、準備はしておいてセキュリティも強化できるし損はしないと思うので。
読書要点「Webを支える技術」：第2部「URI」

# 第4章 URIの仕様

### URIの重要性

URIとはUniform Resource Identifierの略で、統一リソース識別子と訳すことができる。
Web上に存在するすべてのリソースを一意に示すことができる

### URIの構文
URIスキーム・ユーザ情報・ホスト名・ポート番号・パス・クエリパラメータ・URIフラグメント

### URIの実装で気をつけること
クライアント上で相対URIを解決するには面倒な処理になるため、なるべく絶対URIを用いて実装するほうがクライアントにとって親切。
文字エンコーディングの混乱を避けるため、%エンコーディングの文字エンコーディングとしてUTF-8を用いるのが望ましい。

# 第5章 URIの設計
クールなURIとは、変わらないURIである。
クールなURIを目指しつつ、ユーザビリティの高いURIの設計・運用指針を見ていく。
### URIを変わりにくくするためには
- プログラミング言語依存の拡張子を利用しない。
- 実装依存のパス名を利用しない。
- プログラミング言語のメソッドを利用しない。
- セッションIDを含めていない。
- URIはリソースを表現する名詞にする。


URIを変更する場合はリダイレクトを行い、URIが不変なときの挙動を担保する。

### URI設計のテクニック
- 拡張子で表現を指定することで、言語情報などリソースの表現を指定する。
- マトリクスURIを用いてリソースのパラメータの表現を指定する。

### URIの不透明性
あくまでURIを提供するのはサーバ側であって、クライアント側で準備するものではない。
URIの関係性はサーバ側が準備する。
slackにオウムの絵文字をまとめてアップロードする方法

# slackにオウムの絵文字をアップロードする方法
本家のREADMEによると、
Chromeの拡張機能で楽にアップロードができるとのことです。
https://github.com/jmhobbs/cultofthepartyparrot.com

## オウムの絵文字とは
彼らです
https://cultofthepartyparrot.com/

## 手順
1. 「SPREAD THE PARTY」というボタンからダウンロードし、展開します。
https://cultofthepartyparrot.com/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248629/fe7a19ce-82bc-b22b-0e88-ffdc4f66a089.png)
大きくてわかりやすいですね

2. Neutral Face Emoji Toolsをインストールします。
https://chrome.google.com/webstore/detail/neutral-face-emoji-tools/anchoacphlfbdomdlomnbbfhcmcdmjej
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248629/77abc347-96e8-ea62-3931-1cb7af0d6373.png)
右上の青いボタンからインストールしてください。

3. slackの絵文字追加画面にBulk Emoji Uploaderが追加されているので、zipをドロップします。
https://[slackのチーム名].slack.com/customize/emoji
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248629/c0c4d3bf-d276-fdd4-cd0a-81c15dcaa846.png)

4. 無事登録されました。Error: Unsuccessful HTTP responseというエラーで一部アップロードされない場合があるので、その場合は適宜分けてアップロードしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248629/8c4353e2-b54b-b793-aab9-2c6621fd4416.png)
Emacsにkotlin-modeを導入する

[UbuntuにKotlinをインストールしてハローワールドまでやってみた](https://qiita.com/n0bisuke/items/686c1717a894713fdd06)を参照して、Ubuntu18.04にKotlin環境を構築したので、Emacsにもkotlin-modeを導入してみました。

# 手順
1. emacsを開く
2. `M-x list-packages`
3. `C-s`で"kotlin"を検索
4. "flycheck-kotlin"と"kotlin-mode"が見つかるので、インストールしたいパッケージの行にカーソルを合わせて、`i`を押下
5. `x`を押下でインストールを実行 (押下後、インストールを実行するかどうか聞かれる)

# 補足
手順3.で検索に引っかからない場合、melpaの設定が必要かもしれません。
`init.el`などのEmacsの設定ファイルに以下を追加してもう一度試してみてください。

```
;; MELPA
(require 'package)
(add-to-list 'package-archives
             '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)
```

# 参考
[UbuntuにKotlinをインストールしてハローワールドまでやってみた](https://qiita.com/n0bisuke/items/686c1717a894713fdd06)
[[Emacs] MELPAの使い方](http://sweng.web.fc2.com/ja/software/emacs/melpa.html)
[Excel]交差するセルに特定の値があった場合、同列1行目の値を返す方法

Looks like Spreadsheet, though tagged Excel : [Question](https://teratail.com/questions/256332)

```javascript
const onOpen = () => {
    SpreadsheetApp.getActive().addMenu("Custom", [
        {
            name: "q256332",
            functionName: "q256332"
        }
    ]);
}
const q256332 = () => {
  const mark = "○";
  const range = SpreadsheetApp.getActiveRange();
  let table = range.getValues();
  const header = table.shift();
  SpreadsheetApp.getActiveSheet().getRange(range.getRow()+table.length+2,range.getColumn(),table.length,2).setValues(table.map(item=>[item[0],(item.reduce((a,c,i)=>c===mark?a.concat(header[i]):a,[])).join(",")]));
}
```

- From

|   |   |   |   |
|---|---|---|---|
|   | A | B | C |
| A |   |   | ○ |
| B | ○ | ○ |   |
| C | ○ | ` |   |

- To

|   |     |
|---| --- |
| A | C   |
| B | A,B |
| C | A   |
Ubuntu 20.04 LTS に docker をインストールする

# はじめに

Ubuntu 20.04 LTS が先日リリースされました。
早速インストールしで、dockerも使えるようにしたので共有します。

## インストールコマンド

docker-compose もインストールしたほうが便利なので、インストールすると依存関係でdocker本体もインストールできます。

```
sudo apt install docker-compose
```

インストール後、そのままだとsudoが必要なので、自分のグループに docker を追加します。

```
sudo gpasswd -a $USER docker
```

## インストールされるバージョン

|コマンド名|バージョン|
|---|---|
|docker|19.03.8|
|docker-compose|1.25.0|

どちらも現時点の最新版がインストールされるようですね。

## 最後に

Ubuntu 18.04が10年サポートされるようになりました。
なので、急いで20.04に移行する必要はないのかもしれませんが、新し物好きであれば20.04を試してみてもよいかと思います。
Nuxt.jsでPageからLayoutにイベントを送る

Vue.jsで子コンポーネントから親コンポーネントへのイベントの伝播は`emit`と`on`を利用しますが、Nuxt.jsでのPage(子)とLayout(親)ではどのようにイベントをやり取りしたらよいかという記事です。

※CompositionAPIを利用してます

```js:page
export default {
  setup(_, { root }) {
    root.$emit('greet', 'hi')
  }
}
```

```js:layout
export default {
  setup(_, { root }) {
    root.$on('greet', (value) => {
      console.log(value) // hi
    })
  }
}
```

rootにある`$emit`と`$on`のAPIを利用してEventEmitterのようにデータをやり取りします。
特定ページだけlayoutの一部の文言が違うなどの対応ができそうですね。

また、rootのAPIを利用しているのでPageとLayout間に限らずどの場所からでも購読と発火が可能です。乱用には注意が必要そうです。
読書要点「Webを支える技術」：第1部「Web概論」

# 第1章 Webとは何か

###Webの用途
私たちの生活を支えているWebは主に3つの用途で使われている。

**1. Webサイト**
様々なデバイスからアクセス可能で、ショッピング、SNSをはじめ多種多様なサービスが展開されている。

**2. ユーザインターフェース**
各種デバイスの設定画面のように、ユーザインターフェースとして利用されることも少なくない。

**3. プログラム用API**
APIとしてプログラミング向けのインターフェースも提供されている。

### Webを支える技術
幅広い領域で使われるWebの背景には、Webを支え実現させるための技術がある。

##### HTTP、URI、HTML
Webを支える最も基本的な技術である。
HTTPは情報をやり取りするためのプロトコル、URIはあらゆる情報を指し示すための技術、HTMLは情報表現のためのフォーマット。
これらはシンプルな技術である。

##### ハイパーメディア
Webはハイパーメディアである。
メディアをハイパーリンクで結びつけていることで、ユーザはリンクを通じてメディアをたどることができる。
Web以前のハイパーメディアは高機能を目指したことで複雑になっている。
Webは基本的な機能を持つシンプルな技術である。

##### 分散システム
処理を1台のコンピュータではなく、複数のコンピュータに分散させる仕組みを分散システムという。
Webが持つ巨大な規模を実現させるためには必要不可欠な技術。

# 第2章 Webの歴史
Web以前にもインターネットで情報をやり取りするための技術は存在していた。
しかし、現在のWebほど広汎に使われるようになることはなかった。
それらは普及の上で問題点を抱えていた。
Webはシンプルさ故に普及することになったが、その仕様の策定で議論、競争が生じた。

### Web以前のハイパーメディアの問題点
旧来のハイパーメディアはWebと比べて多機能だった。
それに対してWebは単方向リンクしかサポートしていない、リンクが切れる可能性がある、バージョン管理やトランスクルージョンの機能がないといったように高度な機能は実装していない。
Webが持ち合わせていたのはシンプルさであり、普及の観点で言えば過去システムの欠点は複雑さ似合ったと考えられる。

### Web以前の分散システムの問題点
Web以前の分散システムは、イントラネットを中心に利用されていたが、不特定多数にひらかれたインターネットで利用する上では問題点を抱えていた。

- 性能劣化の問題
- データ型変換の問題
- インターフェースバージョンアップ時の互換性の問題
- 負荷分散の問題

### Webの誕生
Webの提案書は1990年11月12日にスイスの欧州原子核研究機構のTim Verners-Leeによって提出された。
Berners-Leeは年内に実装まで進めた。
1993年にイリノイ大学の米国立スーパーコンピュータ応用研究所が公開したブラウザMosaicにより一気に普及した。

ハイパーメディアとしても分散システムとしてもシンプルで、不特定多数を相手にしたオープンなシステムであるWebが普及することとなった。

# 第3章 REST

Webの標準化は多くの企業、集団により競争を経て進められた。
競争の末、Webのアーキテクチャスタイルとして、RESTがを採用するケースが標準化した。

RESTは、各々が作るWebサービスの設計指針となるもので、一人ひとりが作るWebサービス、APIでRESTの約束を守っていくことが重要。

RESTはRepresentational State Transferの略称で、Roy Fieldingにより発表された。

### リソース
リソースとは、Web上に存在する名前を持った情報の総称で、その名前はURIである。
一つのリソースに複数のURIをもたせることができる。
リソースの表現も多様な形態を取ることができる。

### スタイルを組み合わせてRESTを構成する

RESTは6つのアーキテクチャスタイルを組み合わせて構成されたアーキテクチャスタイルである。

- クライアント/サーバ

- ステートレスサーバ
- キャッシュ
- 統一インターフェース
- 階層化システム
- コードオンデマンド



[Webを支える技術](https://www.amazon.co.jp/dp/B07JK7FZH2/ref=cm_sw_r_tw_dp_U_x_u1oOEb2XCCEF2)
UdonSharp日記 ～インストールとチュートリアル～

#はじめに
これは1年ぶりくらいにVRChatを触った私の備忘録です。
投稿時点でUdonSharpにまつわる記事が少ないことを理由に
初めてQiitaで投稿しようってのも動機にあります。

内容については、UdonSharpを使用した記録をとることで後で見返すこと、
そして同じようにUdonSharpを触る人の入り口になれればいいなと。

###レベル感
なお、筆者の技術レベルは下記のとおりです。
・プログラミングはできるしコードも読める。
・UdonSharpは初めて。むしろUnityでのC#も初めて。
・Udon導入前のVRChatでワールド作成なんてしてない。

こんなんで記事を書くことをお許しください。とくに日記１日目は
どこを参考にして試した的なことしか書けませんし。

#UdonSharp ～インストールとチュートリアル～
VRChat触るのも1年ぶりだし、パソコンも変わったのでインストールから
スタートします。
###UnityとVRCSDK3のインストール
次の記事を参考にインストールしました。
試す場合は最新バージョンがいくつなのか確認しながらやってください。
[ケーキのPC情報集会所](https://keiki002.com/vr/vrc-unityver3/)

###Udon Sharpのインストールとチュートリアル
次の記事を参考にUdon Sharpをインストールしました。
[はつぇさんの U#入門](https://hatuxes.hatenablog.jp/entry/2020/04/05/013310)
そのほか同サイトのチュートリアルを実施。
初日は特にオリジナルなことはしていません。

###苦戦ポイント
暗黙の型変換が使用できないため、下記のコードでは値を代入できない。
```c#:example.cs
float tmp1 = 1.0     //この場合doubleをfloatに代入するためエラー'
float tmp2 = 1.0f    //fをつけるとfloat型'
```
書き込みを行いたいテキストとUdonSharpの変数との接続方法
Unityの経験が浅いため、Unity C#でpublic宣言した変数はインスペクターに
表示されることを知らず、どうやって発火するオブジェクトと書き込まれる
オブジェクトをリンクしているのかわかりませんでした。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627563/35fc4c8a-2539-de6a-130a-08178b6d30e5.png)

今回はUdonSharpのお試しなので、諸先輩の軌跡をなぞることしか
実施していませんが、これからはやりたいこと、作りたいことをやっていきますよ。



###参考文献のご紹介
下記の参考文献を見ながらいろいろと試行錯誤中です。
[はつぇさんの U#入門](https://hatuxes.hatenablog.jp/entry/2020/04/05/013310)
[黒鳥さんのUDONメモ](https://kurotori4423.github.io/KurotoriMkDoc/VRChat/UDON%20%E3%81%A7%E3%82%AE%E3%83%9F%E3%83%83%E3%82%AF/)
[やぎりさんのUdonSharpコード走り書きメモ](https://yagiri000.hatenablog.com/entry/2020/04/04/162312)
nextjsの最新のチュートリアルの実施環境を構築する（prettier + eslint + typescript） 

# 前提
nextjsの以下のチュートリアルまで実施している
[Create a Next.js App](https://nextjs.org/learn/basics/create-nextjs-app/setup)

# 概要
プロジェクトに`prettier` `eslint` `typescript` を導入し、快適にチュートリアルを実施するための環境を構築する
[参考レポジトリ ](https://github.com/activeguild/nextjsblog)

# 環境構築

## typescriptをインストールする
#### typescriptをインストールする
```bash
yarn add -D typescript
```

#### 型定義をインストールする
```bash
yarn add -D @types/react @types/react-dom
```

#### ファイルの拡張子を変更する
- `page/index.js` を `page/index.tsx` に変更する

#### プロジェクトを実行して、`tsconfig.json`を追加する
```bash
yarn run dev
```
- `tsconfig.json`が追加されていることを確認してください
- `next-env.d.ts`ファイルも追加されています
- `strict` がfalseになっていたりするので、変更する

## 型定義をインストールする
```bash
yarn add -D @types/react @types/react-dom
```

## prettierとeslintをインストールする

#### prettierとpretty-quickをインストールする
```bash
yarn add -D prettier eslint-config-prettier eslint-plugin-prettier pretty-quick
```

#### prettierの設定ファイルを追加する
```bash
touch .prettierrc.json
```

#### prettierの設定ファイルに以下を追加する
```.prettierrc.json
{
  "printWidth": 100,
  "trailingComma": "all",
  "tabWidth": 2,
  "semi": true,
  "singleQuote": true
}
```

#### eslintをインストールする
```bash
yarn add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react
```

#### eslintの設定ファイルを追加する
```bash
touch .eslintrc.json
```

```.eslintrc.json
{
  "env": {
    "browser": true,
    "es6": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  "globals": {
    "Atomics": "readonly",
    "SharedArrayBuffer": "readonly"
  },
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 2018,
    "sourceType": "module",
    "project": "./tsconfig.json",
    "useJSXTextNode": true
  },
  "plugins": ["react", "@typescript-eslint", "prettier"],
  "rules": {
    "prettier/prettier": "error"
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}

```

#### lint実行用のスクリプトをpackage.jsonに追加する
```package.json
"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "lint": "eslint --ext .ts,.tsx ./"
},
```

#### lintを実行する
```bash
yarn run lint
```

- 特にコードを変更していなければ、以下のようなエラーが出力されるはずです。

```bash
3:16  warning  Missing return type on function          @typescript-eslint/explicit-function-return-type
5:5   error    'React' must be in scope when using JSX  react/react-in-jsx-scope
...省略... 
```


## vscodeの自動整形を有効にする

#### eslintの拡張機能をインストールする
```bash
code --install-extension dbaeumer.vscode-eslint
```

#### .vscode/settings.jsonファイルを追加する
``` settings.json
{
  "eslint.nodePath": "./node_modules/eslint",
  "eslint.packageManager": "npm",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "eslint.alwaysShowStatus": true
}
```
FlickrAPIで画像ダウンロード

#はじめに
画像認識プログラムを作るために、まずは訓練させるための大量の画像データが必要。
そのために、画像データを自動で収集するプログラムを作成する。

参考教材：[【画像判定AIアプリ開発・パート1】TensorFlow・Python・Flaskで作る画像判定AIアプリ開発入門](https://www.udemy.com/course/tensorflow-advanced/)

##Flickr
画像収集サイト
https://www.flickr.com/

API
https://www.flickr.com/services/api/

##下準備
https://qiita.com/Saayaman/items/a3066697a108a7e7fc39
の「1. api登録」参照。
キーと秘密鍵(?)の取得が必要。

##インストール方法
https://stuvel.eu/flickrapi

```
pip install flickrapi
```


#ソースコード
検索した画像を指定のフォルダに保存する。`download.py`というプログラムを作成する。
例えば、

```
python download.py monkey
```

と入力すると、`monkey`で検索した画像を`monkey`というフォルダに格納する。

##インポート

```python
from flickrapi import FlickrAPI
from urllib.request import urlretrieve
from pprint import pprint
import os, time, sys
```

##APIキーの情報

```python
# APIキーの情報
key = "<<文字列>>"
secret = "<<文字列>>"
wait_time = 1
```

取得したキーと秘密鍵を格納しておく。
wait_timeは名前の通りウェイト時間。頻繁にFlickrにアクセスすると、アクセス拒否されてしまうため、画像1枚取得する度に1秒待つようにする。

##画像情報取得

```python
# 保存フォルダの指定
animalname = sys.argv[1]
savedir = "./" + animalname

flickr = FlickrAPI(key, secret, format='parsed-json')
result = flickr.photos.search(
    text = animalname,
    per_page = 400,
    media = 'photos',
    sort = 'relative',
    safe_search = 1,
    extras = 'url_q, licence'
)
```

`FlickrAPI`に、「下準備」で取得したキー、秘密鍵、フォーマットを指定(今回はjson形式)して`flickr`インスタンスを作成し、`flickr.photos.search`メソッドを呼び出す。
`result`には以下のようなデータが入っている。

```json
{'photos': {'page': 1,
            'pages': 541,
            'perpage': 400,
            'photo': [{'farm': 66,
                       'height_q': 150,
                       'id': '49823614651',
                       'isfamily': 0,
                       'isfriend': 0,
                       'ispublic': 1,
                       'owner': '14136614@N03',
                       'secret': '888c8a381a',
                       'server': '65535',
                       'title': 'LEGO Minifigures Series 19 Rainbow Bear',
                       'url_q': 'https://live.staticflickr.com/65535/49823614651_888c8a381a_q.jpg',
                       'width_q': 150},
...
```

##画像ダウンロード
`result`に入っている情報を使って画像をダウンロードする。
画像のURLを`photo['url_q']`で取得。
ダウンロードの実行は`urlretrieve`で行う。

```python
photos = result['photos']

for i, photo in enumerate(photos['photo']):
    print(i)
    url_q = photo['url_q']
    filepath = savedir + '/' + photo['id'] + '.jpg'
    if os.path.exists(filepath): continue
    urlretrieve(url_q, filepath)
    time.sleep(wait_time)
```

##確認

```
python download.py monkey
```

と実行すると、`monkey`フォルダに下記のように保存されている。
ただし、サルではない画像（サルの絵だったり、サルと全く関係が無いものなど）も含まれているため、手動で取り除くことが必要。
![monkey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571638/67dc8bb0-b37d-7b7c-b754-d7d6f497c296.png)