OmniAICreator/Qiita-1.07M huggingface dataset:
Raspberry Pi用個人的コマンドリスト

Raspberry piのコマンドプロンプトで個人的に頻繁に使用するコマンドをまとめる。

#SDカードをアンマウントする
```
diskutil list
```
####listで出てきた該当のディスク番号に変更する
:::note warn
disk４とは限らない
:::

```
diskutil umountDisk /dev/disk４　
```

#SDカードにimgファイルを書き込む
:::note warn
imgファイルがあるディレクトリを指定
:::
```
sudo dd if=/Users/ディレクトリ/ほにゃらら.img of=/dev/rdisk4 bs=32m 
```

#SDカードバックアップ
:::note warn
rdisk4のように"r"とつけると速くなる
:::
```
sudo dd bs=32m if=/dev/rdisk4 of=~raspi.img
```

#config.txtの設定
```
sudo nano /boot/config.txt
```

#接続先設定
```
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
```

#固定IPアドレス設定
```
sudo nano /etc/dhcpcd.conf
```

#AP化したサーバーのSSIDとPASSの設定
```
sudo nano /etc/hostapd/hostapd.conf
```

#Pythonを起動時に実行するための保存設定
```
cd ../ 
cd ../ 
sudo cp home/pi/Desktop/test.py opt/test.py
sudo reboot 
```

#起動中のサービスの状態
```
sudo systemctl status a.service
```

#時間の設定
```
sudo nano /etc/chrony/chrony.conf
sudo systemctl restart chrony.service
chronyc sources
sudo chronyc -a makestep
sudo systemctl status chronyd -l
```

#現在のCPUクロックを表示 
```
vcgencmd measure_clock arm
```

#現在の温度を表示
```
vcgencmd measure_temp
```

#各種設定確認
```
vcgencmd get_config int　
```

#スロットル情報の表示
```
vcgencmd get_throttled
```

#書き込み許可
```
#!/bin/sh

if [ -e /mnt/boot-ro/config.txt ]; then
    sudo mount -o remount,rw /dev/mmcblk0p1
    sudo grep -v initramfs /mnt/boot-ro/config.txt >/tmp/config.txt
    sudo cp /tmp/config.txt /mnt/boot-ro/config.txt
    sudo reboot
else
    echo Already write enabled
fi

```

#書き込み禁止
```
#!/bin/sh

if [ -e /mnt/boot-ro/config.txt ]; then
    echo Already write protected
else
    sudo grep -v initramfs /boot/config.txt >/tmp/config.txt
    sudo echo initramfs initrd.gz >> /tmp/config.txt
    sudo cp /tmp/config.txt /boot/config.txt
    sudo reboot
fi
```

#日付設定
```
sudo date --set "2021-09-19 10:40:00"
```
【覚書】ReactDOM.render がコケたかどうかを取得する

React のレンダリングがエラーで失敗したときに
代わりの DOM を表示したいと思ったので調べた

どうやら ReactDOM そのものに
そういうエラーハンドリング機能はなさそうなので、App を細工する。

# というわけでこうした

```jsx
class App extends React.Component {
  constructor() {
    super();
  }
  componentDidCatch(error, errorInfo) {
    // ここにエラー時の処理
    console.log({ error, errorInfo });
  }
  render() {
    return (
      <p>Hello!</p>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("app"));
```

hooks とかはないもよう
【Stylus】Twitterの気に入らない部分を抹消してみた（保存用）


#はじめに
あれ？浮上やめた？と思ったそこのあなた、どうもカラボンです。
今回はTwitterの邪魔？な部分を消してみたので紹介します。

#目次
・[はじめに](#はじめに)
・[使った拡張機能](#使った拡張機能)
・[コード](#コード)
・[スクリーンショット](#スクリーンショット)
・[おわりに](#おわりに)

#使った拡張機能

使った拡張機能:<a href="https://addons.mozilla.org/ja/firefox/addon/styl-us/">Stylus</a>

まあ、いつものやつです。

#コード
```css:twitter.com/*

div[aria-label="タイムライン: トレンド"] {display:none;}
aside[aria-label="おすすめユーザー"]{display:none}
nav[aria-label="フッター"]{display:none}
div.Footer{display:none !important}
li.promoted-trend{display:none}
div[class="css-1dbjc4n r-1p6iasa r-e7q0ms"]{display:None}
div[class="css-1dbjc4n r-1uaug3w r-1uhd6vh r-1867qdf r-1phboty r-rs99b7 r-1ifxtd0 r-1bro5k0 r-1udh08x"]{display:None}
a[aria-label="調べたいものを検索"]{display:None}

```

これをTwitterの画面でStylusの拡張機能をクリック→管理→さっきのコードをコピペ
で大体消せます。

#スクリーンショット
![Twitter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1086026/bf7a36c5-520d-7ba2-2ffb-3048a1b4be56.png)
こんな感じ。

#おわりに

この拡張機能便利すぎ。
Pythonのpandasで複数csvファイルを読み込みunionする

スクレイピングで出力した、複数csvファイルをunionして、pandasのデータフレームにして分析に用いたときのpythonコードメモ。

```python
import pandas as pd
import glob

csv_files = glob.glob('data/*.csv')

data_list = []

for file in csv_files:
    df = pd.read_csv(file)
    # 列名の.を_に変更
    df = df.rename(columns=lambda x: x.replace('.', '_'))
    data_list.append(df)

df = pd.concat(data_list, axis=0, sort=True)
```
firebaseのTimestamp型の日付をnuxtで表示する

firebaseからデータ取得するとtimestamp型で帰ってくるので2021/1/11 00:00:00の形式に変換します。
絶対わすれるのでメモ

```javascript:index.vue
<div v-for="comment in comments" :key="comment[0]">
    <div>{{ comment[1].name }}</div>
    <div>{{ comment[1].comment }}</div>
    <div>{{ postedDay(comment[1].posted) }}</div>
</div>

  methods: {
    postedDay (timestamp) {
      return (
        timestamp.toDate().toLocaleString('ja-JP')
      )
    }
  }

```
SSHを切断すると実行したコマンドはどうなるのか

SSHを切断すると実行したコマンドはどうなるのか気になって試してみた。


#検証 
検証は、Amazon Linuxで行った。
## 順序
①以下コマンドをsshログインしたリモートホストで実行。

```bash:test.sh
#!/bin/bash
current_dir=$(dirname $0)
sleep 60 &
wait
echo -e "実行終了！" >> "${current_dir}/test.log"
exit $?

```

②ローカルPCでsshプロセスをkill

③60秒後再度sshログイン

```sh
cat test.log
=> 
```
何も出力されていない。。。

④ ①を600秒にし、600秒以内にログイン
以下を実行。
プロセスが消えている。

```
ps aux |grep test
=> 
```
##結果
SSHを切断すると実行したコマンドは、実行終了する。

##考察
なぜSSHを切断するとコマンドが止まるのか、

SSHログインして実行したコマンドは、sshdプロセスの子プロセスとして起動される訳だが(以下コマンド参照)、
~~おそらくsshdデーモンはkillされるとforkした子プロセスに対してkillシグナルを出すように設計されているのではないだろうか。~~

と思っていたのだが、コメント欄でそれは違うよとご指摘いただいたので以下で再度検証する。
@angel_p_57 さんありがとうございます！

```sh
pstree -p | grep sshd
        |-sshd(1560)---sshd(7877)---sshd(7881)---bash(7882)-+-grep(8020)
```


sshが切れてもコマンドを止めないようにするには、以下の記事のが参考になりました。

https://qiita.com/f0o0o/items/7f9dfaf3f7392c0ce52f


##コメントをいただき再度検証
以下コメント引用。

つまり、sshdが終了するから遠隔コマンドが終了する訳ではない。
その例として、非対話型でコマンドを実行した場合は遠隔コマンドのプロセスは残るとのこと。
実際にやってみる。

>デーモンsshdは直接手を下しません。sshがkillされることで、対向のsshdは静かに終了するだけです。
実際、今回は sshでログイン→遠隔のログインシェルと対話処理→対話処理の途中で手元のsshをkill という環境で試されているようですが、ssh ユーザ@ホスト 遠隔コマンド で遠隔コマンド起動→遠隔コマンド実行中に手元のsshをkill だと、sshdは終了して実行されている遠隔コマンドは残ります。
ここでキーとなるのが、対話処理かどうかという点です。sshのコマンドラインオプション-tの有無と言っても良いです。( 遠隔ログインならデフォルトで-t有効 )


###　検証
①以下コマンド実行

```bash
ssh -i ****.pem host sh /***/test.sh
```


```bash:test.sh
#!/bin/bash
current_dir=$(dirname $0)
sleep 600 &
wait
echo -e "実行終了！" >> "${current_dir}/test.log"
exit $?

```
②手元のsshをkill

③sshログインしプロセスを確認
ほんとだ、プロセスが残ってる。。
じゃあなぜ、対話処理なら実行中のコマンドが終了するのか。。
それもコメントで解説してくださった。

```sh
ps aux | grep test.sh
=>
*** 29953  0.0  0.0 113148  2708 ?   Ss   17:39   0:00 sh /***/test.sh
```


### なぜ、対話処理なら実行中のコマンドが終了するのか

以下コメント引用。
自分なりにまとめると。
sshdとログインシェルの間のOSが終了させている。
OSが回線切断(Hang UP、略してHUP)と判断することにより、管理下のジョブを終了させている。

難しい。。

>なぜ対話処理なら実行中のコマンドが終了するのか、それは「[TTY/PTYに関するクイズ](https://qiita.com/angel_p_57/items/ff1c0d054714b7982ca5#a1-%E5%88%B6%E5%BE%A1%E7%AB%AF%E6%9C%AB)」の「A1」の話題と深い縁があります。
このA1の内容をざっくり言うと、「対話処理用のPTYを扱うkernelドライバが、Ctrl-Cの入力を横取りして、コマンドへのシグナル送信に替えて処理する」ということになります。
今回の場合は、sshdの終了によりPTYでのデータの遣り取りも終わるということで、kernelドライバが「回線切断(Hang UP、略してHUP)」と判断することによります。
HUPという判断により、kernelドライバがログインシェルにHUPシグナルを送り、それを受けてシェルが管理下にある各ジョブへHUPシグナルを送る、それでジョブも終了になる、というのが基本路線になります。
livewireが動かない時の対処法その１

ルートエレメントを一つにする

```php:hoge.blade.php
<div　wire:click="inc">+</div>
<div wire:click="dec">-</div>
```
↓

```php:hoge.blade.php
<div>
  <div　wire:click="inc">+</div>
  <div　wire:click="dec">-</div>
</div>
```

気付くのに３０分かかりました笑
MediaWikiでパスワードをリセットが出てこないときのメモ

ちょっとだけ戸惑ったのでメモとして

``` php:LocalSettings.php 
//いろいろ
$wgEnableEmail = true;
//いろいろ
$wgPasswordSender = "password-resetとか@SPF通るドメイン";
//いろいろ
```
ファイルの中に紛れ込んだIPアドレスを探すスクリプト

# モチベーション
サーバへのアクセスログを眺めている際、「このIPどこかで見たよな、、」となるケースがちょこちょことあります。
最近はWAFの面倒を見ることが多く、遮断ログに正常通信の誤遮断が結構混ざる関係でちょこちょこと調べないといけないのですが、「これ前にシステム関連系で使うって言われてホワイトリストに入れたやつじゃなかったっけか、、？」となることがあります。
そういった情報は構成管理の一環できちんとまとめて常時検索できるようにしておけ、、という話ではあるのですが、開発と運用でチームが別れてるとなかなか面倒なわけで。

そういうときのために、コンフィグなどのファイルに含まれているIPアドレスを引っこ抜くスクリプトを作ることにしました。

# 普通にGREPじゃだめなん？
grep -nrIe <IP> <対象ファイル>とかとすればいいのでは、、？と言われる気はします。
IPドンピシャならそれでいいのですけれど、configファイルの中で登録するときは/24などのレンジで登録しているので、ログ監視などで見つけた/32のIPをそのまま調べるとうまく行きません。
なら"192.168.0."とかキーワードを工夫すりゃいいのでは？というのもまぁありなのですが、その場合/8,/16,/24のように切りがいいレンジじゃないとゴミを巻き込みます。
いうほどめんどくさくもないのでは、、？と言われるような気はしますが、ちょこちょこと痒いところに手がどく動作をさせたいという事もありますので、スクリプトとして実装してみることにします。

# 作ってみたもの
こんな。

https://github.com/nfwprod/iptools-nfw

一個前に投稿したレンジ集約スクリプトとセットでまとめてます。
基礎技術は似てるんで。

# 使ってみると

```
% python3 ~/iptools-nfw/ipgrep.py -v 192.168.0.0/24 ${HOME}/iptools-nfw/tests/sample01.txt
/home/uname/iptools-nfw/tests/sample01.txt:1,0:192.168.0.0
/home/uname/iptools-nfw/tests/sample01.txt:2,0:192.168.0.1
/home/uname/iptools-nfw/tests/sample01.txt:3,0:192.168.0.255
```

はい。まぁ、シンプルに意図通りに動くものですね。

一応　-m という検索モードを絞るオプションもつけてます。
通常だと、第１引数のレンジに含まれるもの(include)と、第１レンジを含むもの(included)の両方を出力します。
例えば、192.168.0.0/24を第１引数にしている場合、検索対象の中に含まれる192.168.0.0/25（include)、192.168.0.0/16(included)の両方を出力します。
これを制限して出力したい場合、-mのオプションを使います。

# 実装してみてのいろいろ
本来用途以外にも、ファイル内のIPアドレスをマスクしないといけないときに 0.0.0.0/0を検索するという方法で使う、というようなこともできます。

現状はそこまで便利という感じはしないのは事実なのですが、dnsを引くと該当IPに相当するFQDNを検索する、といような応用機能は作ってみてもいいかもしれません。

これも、つかいながらおいおい修正していきたいと思います。

とりあえず今のところはそんなで。
YAMAHA RTX1100 でNAT64/DNS64を試してみた話

はじめに
-------------
自宅のインターネットアクセスルーターとしてYAMAHA RTX1100を、もうかれこれ15年以上利用しております。

今までIPv4のPPPoEで接続していましたが、だいぶ前にプロバイダーから以下の連絡が
来ていたことを思い出し、そろそろIPv6接続を試してみようかと思い立ち
IPv6接続の設定を行いましたが「NAT64/DNS64」の利用で、ちょっとハマったのでそのお話です。
(ユーザ側での「設定変更は必要ありません」との事でしたが、落とし穴がありました)

```
インターネットをより快適に利用できる新しいインターネット接続機能
「NAT64/DNS64」を提供開始いたします。

NAT64/DNS64を有効にすると、専用機器不要でIPoE方式でインターネットに接続し、
快適にご利用いただけるようになります。

ご利用にあたり、追加料金や設定変更は必要ありません。

NAT64/DNS64の設定が完了いたしました。
```

NAT64/DNS64とは？
----
NAT64/DNS64は、IPv4で提供されているサービスにも、IPv6のネットワークを通して
アクセスできるようにする技術です。

IPv6通信に対応していない端末や、NAT64/DNS64が利用できないサイトは
従来通りIPv4 PPPoE方式で接続します。

RTX1100のconfig変更
----
IPv6 IPoE方式でのインターネット接続については、ヤマハの公式サイトにあった設定例を参考に
config設定し、IPv6接続確認サイトでIPv6接続が、問題なくできていることが確認できました。

これでOKと思いきや、「NAT64/DNS64」正常性確認ページで確認すると
NAT64/DNS64機能は「無効」との結果・・・

nslookupでyahooのページを確認するとIPv4のIPしか、返ってこないので
確かにDNS64は効いていない感じです。

```
C:\>nslookup www.yahoo.co.jp

権限のない回答:
名前:    edge12.g.yimg.jp
Address:  182.22.16.251
Aliases:  www.yahoo.co.jp
```

configを眺めて大分悩んでいましたが、以下の設定がしたままであったことが結果原因でした

```
dns server select 2 pp 1 any . restrict pp 1
```
これはDNSサーバのIPは、IPv4のPPPoE接続の方へ問いあわせをするという定義でしたので
IPv6 IPoE接続の方にDNS問い合わせが行っていなかったという訳です。
(そりゃそうだよね・・・)

```
no dns server select 2 pp 1 any . restrict pp 1
dns server dhcp lan2
clear dns cache
```
上記の設定変更後、改めて「NAT64/DNS64」正常性確認ページで確認すると
今度は、NAT64/DNS64機能は「有効」の結果でした。

そして、nslookupでyahooのページを確認すると、以下の様にDNS64によりIPv6のアドレスも
結果が返ってくるようになりました。

これで、IPv4のIPしかないサイトもIPv6 IPoEで接続ができる様になる訳ですね。

```
C:\>nslookup www.yahoo.co.jp

権限のない回答:
名前:    edge12.g.yimg.jp
Addresses:  2001:260:306:b::b616:1cfc
          182.22.16.251
Aliases:  www.yahoo.co.jp
```

NAT64/DNS64移行後の使用感
----
これで、IPv6 IPoEとIPv4のPPPoEでのハイブリッドアクセス環境が出来ました。

変更後は夜間などの時間帯で、サイトのページが開くのが幾分早くなった気がしています。

本当は、V6プラスが利用できれば良いのですが、RTX1100は未対応なので
取り合えずは、このNAT64/DNS64を使いたいと思います。
(ユーザ側での新たな機器購入が不要なのは、メリットですね)
iPadでポートフォワーディングしてJupyterLabに接続する方法

　深み皆無なメモ。[junoconnect](https://juno.sh/junoconnect/)がJupyterLabに対応してくれれば無用。

# 環境
- local machine: iPad pro11
- local OS: iPadOS 14.7.1
- SSH cliant: Blink
- remote machine: mac mini
- remote OS: OSX 11.5.2

　iPad用のSSHクライアントアプリは[こちらのブログ](https://xckb.hatenablog.com/entry/2019/01/19/194952)に大変よくまとまっています。

# 成功した方法


```
ssh -p SSHサーバーのポート -L 転送元のポート:転送先のIPアドレス:転送先サービスのポート SSH接続のユーザー名@SSHサーバーのIPアドレス
```
　SSH接続の部分を最初にする情報が多かったけどそれらは全部失敗した。ポートを指定しない場合はそれでもいけるのかもしれない。`Blink/.ssh/config`に記述する方法も試したけどSSH接続はできてもポートフォワードはできなかった。
　SSH接続さえできてしまえばあとは`tmux`でセッションを作成して`jupyterlab`を起動する。これでiPadのsafariでjupyterlabに接続できた。
　ただ操作性は悪く、**セルを実行しても全然結果が返ってこないことが度々ある**。そういう場合はSSHクライアントをslide overなどで再表示すると更新される。おそらくこれはi(Pad)OSではバックグラウンドでの実行に制限があるから。スクリプトの実行結果（特に画像出力）を残すという使い方ならまだ使えるかもしれない。マークダウンやTOCが標準で使えるのはやっぱり強い。

## 失敗例

```.ssh/config
host 好きな名前
    HostName SSHサーバーのIPアドレス
    Port SSHサーバーの待受ポート
    User SSH接続するユーザー名
    LocalForward 転送元のポート 転送先のIPアドレス:転送先サービスのポート
```
　mac miniからwindows機へのポートフォワーディングは`.ssh/config`にこれを記述してできてるけどiPadのBlinkでは失敗。これを`sftp`でmacからパクってこようとしたらこれも失敗してる。
Pythonで「年」と「月」の情報を抽出する。

## やりたいこと
2021-04-01のような日付の表記から「年」や「月」の情報を抽出する

## 環境
Google Colaboratoryを使用しました。

## 使用した関数
・pandas.Series.apply()
　→Pandasの各要素に関数を適用する

・str.split()
　→Pandasの文字列を区切り文字で分割

##　コード

###Step1:DataFrameの作成

```python:
#日付型のカラムの作成
import pandas as pd 

list1=["2021-04-01","2021-04-01","2021-04-01"]
columns1=["日付"]
df=pd.DataFrame(data=list1,columns=columns1)
df
```

###Step2:-(ハイフン)で日付を分割し、「年」と「月」のカラムに代入する。
```python:
df['年']= df['日付'].apply(lambda x: x.split('-')[0])
df['月']= df['日付'].apply(lambda x: x.split('-')[1])

df.head()
スクラム開発における”調整”を考える

# モチベーション
我々のチームは、すべてスクラムに準拠した開発では有りませんでしたが、スクラムの要素を取り入れながら日々業務をしていました。自らも開発業務の中で、ゴールの達成のためには様々な障害が存在し、自身もチームでゴールを達成するために四苦八苦してきました。例えば、想定外のことが起き、リリースするアイテムのスケジュールに影響がありそうなときは、その時々に応じて様々な議論や意思決定を皆でしてきました。

一方で、そうした場面で**自分の中で基礎となるような考え方や思想**が存在していないことを課題に感じていました。

今回は、そうした課題感の一助になった[SCRUM BOOT CAMP THE BOOK](https://www.amazon.co.jp/SCRUM-BOOT-CAMP-BOOK-%E8%A5%BF%E6%9D%91/dp/4798129712)から、開発における「調整」について取り上げます。

# どのようにゴールに近づくか
まずゴールに近づくための主だった手法について記載します。
スクラム開発のゴールに近づいていくための方法は以下の2つです。
1. スクラムチームの仕事の進め方を改善していく
2. **何かを調整して、ゴールに近づく**

1.については、デイリースクラムやスプリントプロスペクティブを通して各スプリントやスクラムの進行方法を改善することが出来る方法論だと解釈しています。

今回は、2. の”調整”について取り上げてみました。

# なぜ調整が必要なのか？
ここでは、かんたんな例で考えてみます。
例えば、4人の開発チームで、「〇〇が出来るようになる」というゴールを定めたとします。〇〇を達成するためにはAとBとCという機能を実装しなければなりません。しかしながら、みんなで見積もりをした結果、スケジュール的に厳しい状況が判明しました。

といったときに、「調整」の出番です。

ゴールに近づく上で、変更可能な要素に手を加えることでゴールに近づいていくのです。
実際の業務においても、日常的な改善業務はもちろん必須ですが、このような調整に迫られる場面は多いのではないでしょうか？

# 何を「調整」できるのか？
開発において調整できるものは以下の4つです。それぞれの定義を見ていきます。
## 1. 品質
リリース時に満たす様々なこと。
例：金額計算ロジック・セキュリティ機能等

## 2. 予算
お金の話。
例：スクラムチームの人件費・開発環境整備費用・人的リソース等

## 3. 期間
リリース予定日までの期間。
例：ステークホルダーと合意したリリース日までの日数、デモデーまでの日数等

##4. スコープ
リリースに含めたいもの
例：機能等

# どれを調整するべきか？
###本書の結論から言うと、「スコープ」を調整するべき。
なぜなら、リリースしてほしいと言われているアイテムや機能の中には削れるものが存在していることが多いからです。
ゴールを達成するに値する要素のみを残し、無駄を削ぎ落とすということだと思います。

それ以外の3つに関しては、調整が難しいとのことです。
それぞれが難しい理由を記載していきます。

### 1. 品質：
実際に提供するものの品質は一定でなければなりません。例えば使う人や、場面に応じて品質の善し悪し、（例えば計算結果が違う等）が存在することは責任を持って提供する以上は妥協できない点です。
### 2. 予算：
お金に余裕があるプロジェクトであれば、予算を調整することは可能でしょう。追加の予算があれば即効性のある施策や手段が取れる可能性がありそうです。ただし、承認等のプロセスが複雑・長期化する場合は短期的な許可を得ることは難しいです。また、人を増やしたとしてもベロシティ(開発速度)が上がるとは限りません。スクラムの考え方や進め方等を理解して貰う必要があるからです。
### 3. 期間
リリース日をずらせば、それだけ開発に充てられる時間を増やすことができます。一方でリリース日が重要な場合はずらすことが難しいです。さほどリリース日が重要でない場合はずらすことができますが、再現性の高い手法ではないでしょう。

## 自分の考え
上述の理由に関しては、[SCRUM BOOT CAMP THE BOOK](https://www.amazon.co.jp/SCRUM-BOOT-CAMP-BOOK-%E8%A5%BF%E6%9D%91/dp/4798129712)の考えに基づくものです。（おそらく、スクラムはこの考えに則られているはず）
一方で自分は、**「予算」「期間」についても「スコープ」と同様に、場面によっては調整できるものが変わるのではないか**という仮説を持っています。

### 予算調整について
特に人的な投資を行う場合、経験豊富な人材やスキルフルな人材がいる場合については予算が調整可能ではないでしょうか。なぜなら、チームやプロセスに順応がはやく、ベロシティを下げることなく、むしろ純増できる可能性を有しているからです。

### 期間調整について
特に自社プロダクト・社内システム等においてですが、リリース期限がさほど重要でない場合というのが一定存在していると思います。例えば曖昧な見積から予測した、リリース日になっているケース等もあるのでそれ自体に意味がないケースです。もちろん、関係各所に確認は必要ではありますが、スコープを削らずにリリースにたどり着くという点においては期間調整は有効な一手になりうると思います。

# まとめ
各項目についての特徴と、調整の可能性についてまとめました。
まず、このような調整項目について、ある程度自分の中で言語化されていること自体が、決断や議論を行う場面では非常に有益であると思います。

自分自身の経験からも”調整”を行う上では、**「絶対的な正解はないが、各場面に応じてどういう判断をするべきかという判断力と説明を行う」**が何よりも重要であると思います。
【Android】 SpannableStringBuilderで箇条書きを実装する

# 【Android】 SpannableStringBuilderで箇条書きを実装する
## はじめに
Androidアプリを開発している時に、箇条書きで表現する箇所が出てきたので備忘録がてらまとめました。

## 環境
```
Android Studio: 4.2.2
Kotlin: 1.4.31
OS: Mac OS X 11.5.2 x86_64
```

## 実装

```Kotlin
val text = "aaa"
val spannableStringBuilder = SpannableStringBuilder("")
spannableStringBuilder.append(
    text,
    context?.let { ContextCompat.getColor(it, R.color.black) }?.let {
        BulletSpan(20,it)
    },
    SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE
)
```

> ```Kotlin
> context?.let { ContextCompat.getColor(it, R.color.black) }?.let {
>    BulletSpan(20,it)
> },
> ```

箇条書きの`・`の色を宣言します。自由に設定できるので箇条書きにする文の文字色に合わせたり、好きに設定してください。

> ```Kotlin
> spannableStringBuilder.append(
>     text,
>     context?.let { ContextCompat.getColor(it, R.color.black) }?.let {
>         BulletSpan(20,it)
>     },
>     SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE
> )
> ```

String型で宣言した textに`・`を追加していきます。

最後に`builder`をtextViewに入れることで箇条書きで反映されます。

## デモ
[実装](#実装)に記載したコードをfor文で繰り返して各textに反映させることで以下のように表示されました。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1257046/e6430daa-8f8f-b655-861c-aff1cdc63747.png">

改行もうまく動作しています。
<img border="1" width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1257046/5eb99462-f90b-8e63-8752-6c1cbd25fa46.png">　　<img  border="1" width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1257046/294ff1d8-4839-0f55-c855-8419f622b60c.png">

## 参考文献
Spans - Android Developers
https://developer.android.com/guide/topics/text/spans

BulletSpan - Android Developers
https://developer.android.com/reference/android/text/style/BulletSpan
自前で行列同士の積を実装した時の、検算方法

# 概要
Excelの行列関数でチェックするだけなんですが。。。
結構、忘れてしまうので。

# 手順
空のExcel起動 → 適当に4x4の行列をA1:D4に入力。 → 適当に4x4の行列をA6:D9に入力。 → A11:D14を選択 → ”=MMULT(A1:D4,A6:D9)”を入力(Enter押さない) → shift+ctrl+enterを押下。
これで、答えが表示される。

#### 手順1 空のExcel起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723966/ffd5f83a-3c0a-071d-bec2-5651b629a280.png)

#### 手順2 適当に4x4の行列をA1:D4に入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723966/e59eba76-3b19-4943-e205-f8818b1e003d.png)

#### 手順3 適当に4x4の行列をA6:D9に入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723966/65ff203b-21cd-5e67-9b64-a09b434a5fb6.png)

#### 手順4 A11:D14を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723966/4512ec86-2758-1f80-cf87-e7b0c87f8a6e.png)

#### 手順5 ”=MMULT(A1:D4,A6:D9)”を入力(Enter押さない)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723966/4e90b84e-bffa-6e2d-e6f3-f87d6b586af9.png)

#### 手順6 Shift+Ctrl+Enterを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723966/9cb24aa6-f334-a880-891f-7851be53ade5.png)

できた。!!
今回は、4x4行列同士の積をやったけど、この方法で、3x3も4x4@4x1もできるはず。



---
gluPerspective()の実装でいい記事見つけたので共有
[gluPerspectiveを自前実装する](https://suzulang.com/my-implement-gluperspective/)
VRChatで勝手に視点が左に移動する

# VRChatで勝手に視点が左に移動する

デスクトップモードでVRChatを起動してみたところ、視点が左に回転するようになりました。
![2021-09-19 14-19-16.mkv.mp4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/648c7fd0-c24e-d37f-4c98-2d897aa06387.gif)
ESCを押してもメニューを表示することができません。

また、VRモードだと、アバターが勝手に左に移動するようになりました。

このままだとVRChatがまともにプレイできないため、解決法を調べてみることにしました。



# 調査

ここからは、どのような順番で調べたのかを書いていきます。解決法だけ知りたい方は、 `原因と解決法` まで読み飛ばしてください。



## Debugで症状を確認してみた

デスクトップモードで `R` ボタンを押すことで、アクションメニューを出すことはできました。
（ちなみに、アクションメニューを出すと、症状が変化し、「左回転」ではなく「左前進」になりました。）

アクションメニューの `Options > Config > Debug` を開いてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/dccf7699-93d6-2b7d-0e82-c4fa816c5c01.png)

キーボード・マウス等、何も操作をしてないにも関わらず、速度の値が常に以下のようになっていました。

- `VelocityX` : `-2.04`
- `VelocityZ` : `2.20`

常に左前へ移動する症状と、値は一致していそうです。



## BUTTONLESS GAZE を探してみたがなかった

解決法を調べたところ、 `Settings > Other Options > BUTTONLESS GAZE` を有効にすれば、症状が改善するという情報を見かけました。

しかし、この項目は過去バージョンのVRChatのものであり、2021年9月現在のVRChatにはありませんでした。



## USBを全部抜いてみたら、症状が改善した

「ゲームパッドを抜いたら解決した」「ペンタブレットを抜いたら改善した」といった情報を目にしました。どうも入力デバイスがVRChatに影響を与えることがあるようです。

ためしにPCに接続しているUSBをすべて抜いてみたところ、症状が改善しました！

具体的にどのUSBデバイスが問題なのか調べてみることにしました。



# 原因と解決法

昔使っていた無線マウスのUSBドングルが、USBハブ経由でPCにつながっていたことが原因でした。

USBハブからUSBドングルを外すことで、症状が改善しました！

先週、USBポートを増やしたくて、むかし使っていたUSBハブをPCにつなげたので、その際に、このドングルもついてきてしまったようです。



# さいごに

本記事作成にあたり、以下の情報を参考にしました。ありがとうございました。

- [View moving up and left or can't control my view](https://help.vrchat.com/hc/en-us/articles/360062658733-View-moving-up-and-left-or-can-t-control-my-view)
- [Character keeps moving backwards and turning right.](https://www.reddit.com/r/VRchat/comments/c3qyms/help_character_keeps_moving_backwards_and_turning/)
- [デスクトップ版で起動した時、視点が勝手に移動するんですが対処法などあるでしょうか?](https://twitter.com/vtubery/status/987646216094691328)
- [デスクトップモードで永遠に視線が回転し続けるのですが？？？](https://twitter.com/nqimo/status/1273509077595742210)
（WSL2の）debianでRails6.1のsystem testを動かす

# 実行するコマンド

```shell
# headless chrome のインストール
curl https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb # エラーが出るけどそのまま進む
sudo apt install -fy
```

# テストコードの変更

```test/application_system_test_case.rb
require "test_helper"

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  # driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
  driven_by :selenium, using: :headless_chrome
end
```

# 解説

## 前提: system testの仕組み

- Railsアプリとブラウザを実際に動作させて、テストプログラムからブラウザを操作してテストを行う
- なので、ブラウザが必要である
- ブラウザをテストで操作するためのプログラムも必要である、これをドライバと呼ぶ
- どのブラウザ（ドライバ）を使うかは指定する（する必要がある）

## ドライバは自動で用意される

ぐぐると様々な情報が出てきますが、Rails6.1においては、特別に何かの設定をする必要はありません。

Rails6.1のGemfileには最初からwebdriversというgemが入っていて、このgemがsystem testの実行時に（なければ）自動的に必要なドライバをインストールしてくれます。

## WSL2環境においては、ブラウザはheadless chromeが楽

[webdrivers gemのREADMEに書いてある](https://github.com/titusfortner/webdrivers#wslv2-support)とおりです。windows上のchromeを利用するためには特殊な設定が必要になるので、特別な理由がなければheadless chromeが良いでしょう。

ちなみにheadというのは画面のことで、画面無しで（コマンドラインで）動くからheadlessと呼びます。

## chromeはaptから直接はインストールできない

`apt search chrome` とかで探すとわかりますが、aptのパッケージにはなっていないようです。

googleのサイトからダウンロードする方法が[3年前の先人による記事で見つかった](https://rooter.jp/web-crawling/setup-headless-chrome-ubuntu/)のでその方法を採用して、うまく行きましたが、ブラウザから[chromeのダウンロード用サイト](https://www.google.com/chrome/?platform=linux)を見てもcurlなどでダウンロードする場合のURLは見つけられませんでした。なので、いつまでこの方法でできるかはわかりません。

`dpkg` はaptのより基本的な部分のインストール処理を行うコマンドですが、実行しても依存関係を解決できませんでした（理由は未確認）。なので続く `sudo apt install -fy` で依存関係の解決を後出しで行って、chromeを動くようにしています。

## chromeはheadlessかどうかで使うドライバ（の設定）が異なる

デフォルトでもsystem testはchromeを使う設定になっていますが、これは画面があるchromeを使う設定なので、画面があるchromeを起動できない環境（WSL2はこれに該当します）ではテスト実行が失敗します。

headless chromeを使うには、冒頭に記載したようにテストコードの設定変更を行えば良いです。このこと自体は[Railsガイドに記載があります](https://railsguides.jp/testing.html#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E8%A8%AD%E5%AE%9A%E3%81%AE%E5%A4%89%E6%9B%B4)。
【JavaScript】値を重複させずに配列をマージする

#はじめに
キーをもたない配列をマージする際、同じ値が重複してしまいます。
最初から連想配列(オブジェクト)を使えよ！という話な気もするのですが、念のため、通常の配列で値を重複させずにマージする方法をメモとして残します。

#問題
配列をマージする際に同じ値が重複してしまう。

```js:array.js
const array1 = [1, 2, 3];
const array2 = [3, 4, 5];
const array3 = [...array1, ...array2];

console.log(array3);
```

```
$ node array.js
[ 1, 2, 3, 3, 4, 5 ]
```

#解決策
マージした配列を`new Set([...array1, ...array2])`でSetオブジェクトにし、一意な値が格納されるようにします。
さらに`Array.from`メソッドでラッピングすることで、オブジェクトから新しいArrayインスタンスを生成します。

```js:array.js
const array1 = [1, 2, 3];
const array2 = [3, 4, 5];
const array3 = Array.from(new Set([...array1, ...array2]));

console.log(array3);
```

```
$ node array.js
[ 1, 2, 3, 4, 5 ]
```

#参考資料

https://www.delftstack.com/ja/howto/javascript/javascript-merge-arrays/
【M1,Xcode12】ライブラリ 利用方法 備忘録

# M1 ライブラリ 利用方法 あくまで備忘録

M1の場合，ターミナルはRosettaで開く。
【設定方法】
1，Finderからターミナルを探す。パス: /System/Applications/Utilities/Terminal.app
2，右クリックから「情報を見る」
3，「Rosettaを使用して開く」にチェック

```
//cocoapodsのインストール
$ sudo gem install cocoapods
$ cd {.xcodeprojファイルがあるディレクトリへのパス}    //Finderから option+cmd+c または D&D
$ pod setup

//podfileの生成
$ pod init

```
###Podfileの編集
``` 
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target '{プロジェクト名}' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for {プロジェクト名}
  pod '{ライブラリ名}'                   //この行を書き加える

end

```
###  ライブラリのインストール
```
$ sudo gem install ffi             //M1の場合
$ pod install
$ exit
[プロセスが終了しました]                //バツで閉じる
```
Podsディレクトリが追加されていればOK
###Xcodeを起動
.xcworkspaceファイル(白いやつ)をFinderから開く.
今までの.xcodeprojファイルでないことに注意(ここを間違え1日潰れました)

##ここからは追加するライブラリによって違うっぽい
(ここは後から追記していきます。わかる方コメントで教えてほしいです。。)
###Realm
>https://qiita.com/dieKn/items/ebec40c6d0d6b64a5b16

###Google Admob
Google-Mobile-Ads-SDK
>【SWIFT5,XCODE12】超入門クイズアプリ開発講座~自分のアプリをリリースしてみよう~：自分のオリジナルアプリが作れる参考書
>M1のため(cf. 190ページ) https://zenn.dev/akeome/articles/2433d792db022835c7e7

###Parchment
わかり次第追記

#Tips
###Podfileでのライブラリのバージョン指定
```
//最新版
pod '{ライブラリ名}'

//完全一致
pod '{ライブラリ名}','1.0'

//超過
pod '{ライブラリ名}','>1.0'

//以上
pod '{ライブラリ名}','>=1.0'

//未満
pod '{ライブラリ名}','<1.0'

//以下
pod '{ライブラリ名}','<=1.0'

//マイナーバージョン(1.0.1以上1.1未満)
pod '{ライブラリ名}','~>1.0.1'
```
#pod try
以下に関してはビルドしてもエラーが起きる，もしくはビルド成功しても立ち上がらない，などでよくわからず。
ライブラリがcocoapodsに登録されているかの確認はhttp://cocoapods.org/
>ターミナルから、任意のディレクトリで
>$ pod try 'MPFlipViewController'
>XcodeでMPFlipViewController.xcodeprojが立ち上がるので、Runするとシミュレータが立ち上がります
>>http://smsurf.app-rox.com/iosl/get_lib.php

#参考
>https://qiita.com/dieKn/items/ebec40c6d0d6b64a5b16
>http://smsurf.app-rox.com/iosl/get_lib.php
>https://note.com/iga34engineer/n/nf1930c395730
>https://note.com/iga34engineer/n/nf1930c395730
>https://note.com/iga34engineer/n/ne0e57ee34c76

#環境
Xcode Version 12.5.1 (12E507)
Macbook Air M1,2020
macOS Big Sur バージョン11.5.2
SSL証明書発行時に詰まったところ ：〜ファイヤーウォールの設定〜

#○はじめに
SSL証明書発行時に詰まった箇所について記載しておきます。

##環境

| インフラ・開発言語・環境 |
|---|
| ConoHa VPS |
| CentOS 8 |
| Apache 2.4.37 |

#○【結論】：ポート・ファイヤーウォールが分からなくて進まなかった。

```
The Certificate Authority failed to verify the temporary Apache configuration changes made by Certbot.
```

1日に5回までしか発行を試みることができないので、かなり詰んでいました。

**私の場合は、「ポートが開放できていなかった事」が原因でした。**

というよりも、ファイヤーウォールの設定でポートが解放したくても出来なかった事が原因でした。

##●＜httpd.confを確認する＞

```
# vi /etc/httpd/conf/httpd.conf

Listen 8080
Listen [IPアドレス]:80

<VirtualHost *:80>
ServerAdmin [ドメイン]
DocumentRoot /var/www/html/
ServerName [サーバー名]
RewriteEngine on
RewriteCond %{SERVER_NAME} =[サーバー名]
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
```

###```Listen ディレクティブ```

Apache がクライアントからリクエストを受け付けるポート番号の事。

```
Listen 8080
Listen [IPアドレス]:80
```

・ポートは複数指定できます。
・ポートのみ記載の場合、全てのインターフェースからのリクエストを受け付ける
・特定のインターフェースのみ受け付ける場合、IPアドレスを記載する

https://www.javadrive.jp/apache/ini/index3.html

###```VirtualHost```

```
<VirtualHost *:80>
ServerAdmin [ドメイン]
DocumentRoot /var/www/html/
ServerName [サーバー名]
RewriteEngine on
RewriteCond %{SERVER_NAME} =[サーバー名]
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
```

1つのサーバーで、2つ以上のWebサイトやWebアプリを運用する際に使います。
その際に、それぞれにドメインを割り当てます。

・```DocumentRoot```
ブラウザから直接アクセス可能なファイルを設置する場所

```
# systemctl restart httpd
```

##●＜ファイヤーウォールの設定を変更：ポートを開放してあげる＞

**私は、ファイヤーウォールが有効だったため、詰まりました。**

ファイヤーウォールの状態を確認してください。

```
# systemctl status firewalld

Active: active (running)
```

ファイヤーウォールが有効になっている人は、```active```とか書かれた文言が出てきます。その場合は、設定が必要です。

###設定します

現在の状況を確認。```firewall-cmd```コマンドでファイヤーウォールの設定を行います。

```
# firewall-cmd --list-all

public (active)
  services: cockpit dhcpv6-client ssh
  ports: 8000/tcp
```

ここでは、```8000```のポートが登録されています。

```
# firewall-cmd --add-service=https --zone=public --permanent
# firewall-cmd --list-all

public (active)
  services: cockpit dhcpv6-client https ssh
  ports: 8000/tcp
```

httpd.confの設定と同じポートを有効にします。```80```を例にします。

```
# firewall-cmd --zone=public --add-port=80/tcp
# firewall-cmd --list-all

public (active)
  services: cockpit dhcpv6-client https ssh
  ports: 8000/tcp 80/tcp
```

portsに、80が表示されれば発行ができます。

**表示されない場合は、```httpd.confのListen```を消してからもう一度行ってみてください。**

##●＜SSL証明書を発行する＞

```
# certbot --apache -d [ドメイン]
```
WKWebViewでGet/Postリクエストを送信するには

webViewではGetリクエストを行うだけではなく、POSTリクエストを行なってサーバー側に様々な情報を送信することができます。

```swift:Getリクエスト
guard let url = URL.init(string: "https://www.google.com/?hl=ja") else { return }     
let request: URLRequest = URLRequest.init(url: url)
webView.load(request)
```

```swift:Postリクエスト
guard let url = URL.init(string: "https://www.google.com/?hl=ja") else { return }     
var request: URLRequest = URLRequest.init(url: url)
request.httpMethod = "POST"
let httpBody = "test1=test&test2=test"
request.httpBody = httpBody.data(using: .utf8)
webView.load(request)

```

以降の記載は上記コードに対する説明になります。

**リクエスト設定**
URL型の変数を引数に渡してURLRequestを生成します。
URL型を生成する際はオプショナル型で返却される為、強制アンラップは行わないようにしましょう。
キャッシュポリシーやタイムアウトのデフォルト設定を変更したい場合は以下のメソッドを使用しましょう。

```

URLRequest.init(url: ~, cachePolicy: ~, timeoutInterval: ~)
```
指定しない場合のデフォルト設定は以下の設定値になります
キャッシュポリシー：useProtocolCachePolicy (プロトコルの規約に従い、キャッシュを使用する)
タイムアウト：60秒


**HTTPメソッドの設定**
Get：デフォルト設定となる為、設定不要
POST：String型で「POST」と設定する

**クエリーの設定**
▼GETリクエスト
GETリクエストは基本的にBody部を持たない為、クエリーはURLに付与する必要があります。
URLの末尾に
?test1=test&test2=test
のような形式で文字列を結合しましょう。

▼POSTリクエスト
URLRequestのhttpBodyプロパティに「&」で繋げた文字列をエンコードしてバイナリ化させたものを設定します。

**リクエストの送信**
WKWebViewのloadメソッドを使用して作成したRequestを設定することで送信することができます。
SolanaのScaffoldでUnhandled Rejection (error): Not a valid Mintの対処法


[SolanaのScaffold](https://github.com/solana-labs/dapp-scaffold "Qiita Home")をcloneしてyarn startすると

```
Unhandled Rejection (error): Not a valid Mint
```

上記のエラーが出る場合があります。

その場合は、accounts.tsxの以下の行を

```accounts.tsx
const account = deserialize(new PublicKey(address), obj);
```

以下のように変更すると正常に動くようになります。

```accounts.tsx
let account; try { account = deserialize(new PublicKey(address), obj); } catch(e) { console.error(e); }
```
このプルリクがマージされたあとのバージョンで出てるエラーに関しては別の原因かもしれません。

https://github.com/solana-labs/dapp-scaffold/pull/53
【初学者向け】JavaScriptの三項演算子『?』について

今回はJavaScriptの三項演算子について解説していきます。


#三項演算子とは

三項演算子とは**if文(if~else)の記述を省力して使えるようにした演算子です。**

省略できるといっても
『<font color="GoldenRod">条件式</font>』『<font color="DodgerBlue">trueの場合の処理</font>』『<font color="Crimson">falseの場合の処理</font>』は**必ず必要**になってきますのでご注意ください。

##if文と参考演算子の記述する際のイメージ

**①if文の場合**

if (<font color="GoldenRod">条件式</font>) {
    <font color="DodgerBlue">trueの場合の処理</font>
} else {
    <font color="Crimson">falseの場合の処理</font>
}

[解説]<font color="GoldenRod">条件式</font>が
trueなら→<font color="DodgerBlue">trueの場合の処理</font>
falseなら→<font color="Crimson">falseの場合の処理</font>


**②三項演算子の場合**

<font color="GoldenRod">条件式</font> ? <font color="DodgerBlue">trueの場合の処理</font> : <font color="Crimson">falseの場合の処理</font>;

[解説]
**☆条件式の後に「？」を記述**
**→trueなら直後の<font color="DodgerBlue">trueの場合の処理</font>**
**→falseなら「:」の後の<font color="Crimson">falseの場合の処理</font>**
となります。
だいぶ短くなりましたね！ このように三項演算子を使えば**スッキリと一行で記述**できるようになります。

##コードで確認
最後に三項演算子のいろんなパターンに記述を確認していきましょう

**①シンプルな記述**
console.log内で三項演算子を記述

```javascript
console.log( 10 > 0 ? "trueです" : "falseです" );
// trueです

```

今回の場合、それぞれ
『<font color="GoldenRod">条件式</font>』10 > 0
『<font color="DodgerBlue">trueの場合の処理</font>』trueです
『<font color="Crimson">falseの場合の処理</font>』falseです
となります。

**②変数に代入して文字列を返す記述**

```javascript
//まずは変数定義
const numCheck = 10 > 0 ? "trueやで" : "falseやで"; 
//console.logで表示
console.log(numCheck);
// trueやで
```

**③改行して見やすくした記述**

```js
const num = 10 

num > 0 
    ? console.log("trueやで")
    : console.log("falseやで") 
/// trueやで

```

**④数値がどうかチェックする記述**

```js
const num = "10";

const typeCheck = typeof num === 'number' ? "数値です" : "数値ではないです";
console.log(typeCheck);
/// 数値ではないです。
/// const num = 10  なら　"数値です"が表示
```

**⑤関数のreturn部分に記述**

```js
const sum = (num1, num2) => {
    return num1 + num2 > 10 ? '10を超えています！' : '10を下回っています';
}

console.log(sum(8,3))  /// 10を超えています！
console.log(sum(8,1))  /// 10を下回っています
```

##まとめ
『<font color="GoldenRod">条件式</font>』『<font color="DodgerBlue">trueの場合の処理</font>』『<font color="Crimson">falseの場合の処理</font>』の位置をしっかり把握できれば
シンプルに記述できることがわかったと思います。
【Python・Jupyter】プログラミング問題のデバッグをJupyterで行う。【マジックコマンド編】

# はじめに
AtCoderなどの競技プログラミングやPaizaスキルチェックなどプログラミング問題といった入力に対して特定の出力を導く問題には、たいてい時間制限がついていますよね。
ちょっとした動作確認に時間を割いている余裕はないのです。

以前、この問題を解決するべく以下の記事を書きました。
[Paizaのスキルチェックの例題のデバッグをJupyterとかのローカル環境でやるときの入力の手間を省きたい【Python】](https://qiita.com/Cartelet/items/1b351f3674dfa7d2fef3)

しかし、これでもまだ微妙に使い方がスッキリしていないですし、しばらく使わないと使い方を忘れてしまいそうです。

そこで今回は、
**折角のJupyter。マジックコマンドを使わない手はない！**
という方針で解決してみることにしました。

# マジックコマンドとは？
Jupyterにおけるマジックコマンドとは、`%`や`%%`から始まる特殊機能の呼び出しのことを指します。
`%time`や`%%timeit`、`%matplotlib notebook`などのコマンドは馴染み深い方も多いのではないでしょうか？

これ、実は**自分で作れます**。

詳しい？方法は以下で紹介していますのでよろしければ見ていってください。
[【Python・Jupyter】ライブラリを自動インポートする方法・マジックコマンドの作り方](https://qiita.com/Cartelet/items/0ce6e652a8dae9b9a4a4)

# 作ったもの
以下をセルに入れて実行するか、`C:\Users\%USERNAME%\.ipython\profile_default\startup`(Windows) 下に置くことで（上記リンク参照）マジックコマンドが使えるようになります。

```python 
from IPython.core.magic import Magics, magics_class, cell_magic, line_magic


@magics_class
class MyMagics(Magics):
    lines = ""
    @cell_magic
    def input_magic(self, line, cell):
        global input
        assert line in ('input', 'test'), "Please specify the command after the magic command: 'input' or 'test'."
        if line == 'input':
            self.lines = cell.strip('\n').splitlines()
            self.stdin = self.__stdin()
        else:
            input = self.input
            self.shell.run_cell(cell)
            input = __builtins__.input
    
    @line_magic
    def reload_input(self, line=None):
        self.stdin = self.__stdin()

    def input(self, arg=""):
        if arg:
            print(arg, end="    ")
        return next(self.stdin)

    def __stdin(self):
        assert self.lines, "Input lines are not defined."
        for line in self.lines:
            yield line
        else:
            raise EOFError("EOF when reading a line")


get_ipython().register_magics(MyMagics)
```

# 使い方
`%%input_magic`に続いて、「`input`」で入力の設定、
　　　　　　　　　　　　　「`test`」で実行ができます。

[AtCoder Beginner Contest 219 :  H - Candles](https://atcoder.jp/contests/abc219/tasks/abc219_h)より

```python 
%%input_magic input

5
0 1000000000
0 1000000000
1 1000000000
2 1000000000
3 1000000000
```

```python 
%%input_magic test

hogehoge
```

```:out
4999999994
```

また、実行時は毎回`%%input_magic input ~`のセルを実行する必要がありますが、おまけとして入力をリセットするコマンドも用意していますので、
`%reload_input`コマンドを挟んでおけば、その行の時点で入力を始めからにすることができます。

```python:example
%%input_magic test
%reload_input

fugafuga
```

# さいごに
環境によっては`asyncio`周りのエラーが出ることがあります。原因はよく判りません。
Colabや、Dockerで作った仮想環境では正常に動きました。
【覚書】React.lazy で import を使わない

Dynamic import を何が何でも使いたくなかったので調べた。

# こうする

```jsx
const Hello = React.lazy(() =>
  Promise.resolve({ default: () => <p>Hello!</p> })
);
```

# async/await を使いたいならこう

```jsx
const Hello = React.lazy(() =>
  (async () => {
    return { default: () => <p>Hello!</p> };
  })()
);
```

# API からデータを持ってくるときはこう

```jsx
const Response = React.lazy(() =>
  (async () => {
    const res = await (await fetch(API_URL)).json();
    return { default: () => <pre>{JSON.stringify(res, null, 2)}</pre> };
  })()
);
```

# 面倒くさいので関数化

```jsx
const laze = (fn) =>
  React.lazy(() =>
    Promise.resolve(fn()).then((module) => Promise.resolve({ default: module }))
  );

const Hello = laze(() => () => <p>Hello!</p>);

const Response = laze(async () => {
  const res = await (await fetch(API_URL)).json();
  return () => <pre>{JSON.stringify(res, null, 2)}</pre>;
});
```
AWSのMicrosoft Active Directory関連サービスの整理

# はじめに
AWS Active Directoryについての整理
# AWS Directory Service
https://aws.amazon.com/jp/directoryservice/
> AWS Directory Service によって、AWS クラウド内にディレクトリをセットアップして運用することや、AWS リソースを既存のオンプレミス Microsoft Active Directory に接続することが簡単に行えます。

### ユースケース：
- 1. ADの認証情報でAWSにサインインしたい
- 2. AD管理ツールを使ってEC2を管理したい
- 3. Remote Desktop Licensing Manager and Microsoft SharePointやMicrosoft SQL Server Always OnのようなアプリケーションをEC2で走らせたい。
- 4. Office365へのSingle-Sign-On
- 5. オンプレミスADのAWSへの拡張
- 6. AWSアカウントを跨ぐドメインにEC2を参加させる
iOSデバイスからcode-serverに接続するために、自己証明書を作成する

ローカルネットワークにcode-serverを立てようとしたところ、iPhone(iOS)やiPad(iPadOS)で警告が出ない証明書作成に手間取ったため、共有します。

# apple証明書の要件
証明書の要件については、appleの公式サポートページを参照してください。
[iOS 13 および macOS 10.15 における信頼済み証明書の要件](https://support.apple.com/ja-jp/HT210176)
[信頼済み証明書に関する今後の制限について](https://support.apple.com/ja-jp/HT211025)

# 内部IPアドレスの固定

内部IPアドレスを固定していない場合は固定します。
固定方法は割愛します。「OS名 + 固定IP」などで検索してください。

固定したIPアドレスで「~/.config/code-server/config.yaml」のbind-addrを変更します。

``` txt
bind-addr: 固定したIPアドレス:ポート番号
```

# 証明書作成

証明書を適用するサーバーで証明書を作成します。
証明書の作成には[OpenSSLの自己署名証明書の生成の省力化の試み](https://qiita.com/Nanigashi_Uji/items/88f3e01c6164fdd1e8fa)を使わせていただきました。
Makefileに以下の変更を行いました。

## Subject names

「Subject names for cert」の変数値を自身に合う設定に変更します。

``` txt
#
# Subject names for cert
#
INFO_C  ?= JP
INFO_ST ?= My Prefecture
INFO_L  ?= My City
INFO_O  ?= My organization name
INFO_OU ?= My branch name
```

## hostname

hostnameに「.local」を追加します。

``` txt
#
# Hostname and IP address
#
HOSTNAME          ?= $(shell hostname -f).local
HOSTNAME_S        ?= $(shell hostname -s).local
```


# 証明書配置

## サーバー

「~/.config/code-server/config.yaml」のcertをtrueに変更します。

``` txt
cert: true
```

「~/.local/share/code-server/」に作成したservice.keyをlocalhost.keyに、service.crtをlocalhost.crtにリネームしてコピーします。
※起動確認のための仮置きです。確認後に権限管理など適宜行ってください。

起動時に「--cert」, 「--cert-key」の引数設定でそれぞれ任意のファイルを指定可能です。


## iOS, iPadOS

ホスト名+.local_ca.crtとservice.crtをiOS(iPadOS)にコピーします。
各プロファイルをインストールし、証明書を信頼させます。

[iOS や iPadOS で手動でインストールした証明書プロファイルを信頼する](https://support.apple.com/ja-jp/HT204477)

# 接続確認
「ホストネーム.local:ポート番号」でsafariからアクセスし、警告が出なければ成功です。
Reactでnpm startしたときのエラーの対処

![error111-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/6f3514e7-17fa-34d8-6216-4ffcaf081a8a.jpeg)
React.jでnpm strat時にCommand failed with exit code 1.が出た時の対処法

npm start時に以下の画像のようなエラーが出てきました。
1から4まで削除したり書いている通りにしたがうまく行かず…

#解決法
ディレクトリの構成通りに.envファイルを追加し以下を記述し再度npm startを実行することで解決できました。
``` SKIP_PREFLIGHT_CHECK=true
```

![success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/77ec3713-0216-cf7f-ad42-0c88b001b93f.png)
matplotlib(pyplot)でグラフをPDFで保存したら真っ白だった話

# 問題発生
以下のプログラムでPDFを保存した
そのPDFを見たら、、、真っ白、、、
わずかスプーン1杯で驚きの白さに！！！

```ruby:qiita.rb
import matplotlib.pyplot as plt
省略
plt.show()
plt.savefig("test.pdf")#グラフを保存
```

#解決方法

```ruby:qiita.rb
import matplotlib.pyplot as plt
省略
plt.savefig("test.pdf")#グラフを保存
plt.show()
```

一番下の2行の順番を変えただけ
plt.show()の後にplt.savefig()をやったらだめなのね
[Python3]　初心者の初心者による「ユーザー定義関数」解説

#ユーザー定義関数とは
繰り返し使用する処理や、コード全体を見やすくするために使用します。
また、**「自作関数」**とも呼ばれ、自分で作成する関数です。

#ユーザー定義関数の書式
```python:書式
def 関数名(引数):
    # インデント(半角空白4個)が必要
    処理1
    処理2
    処理3
    return 戻り値

# 戻り値の取得
変数 = 関数名(引数)
```

上記が、ユーザー定義関数の書式です。

では、実際の使用方法について説明いたします。

# 使用方法
randomモジュールを使用し足し算の計算問題を10個作成するプログラムのコードを作成しました。
以下のコードを使用し説明いたします。

```python:例
# randomモジュールをインポートする
from random import randint

# ユーザー定義関数の作成
def getnum():
    num = randint(1,100)        # random関数を使用し、値を取得
    return num                  # numに格納された値を戻り値とする

# 10個作成するため、For文で10回ループ
for i in range(10):
    num1 = getnum()             # ユーザー定義関数の戻り値(num)の取得
    num2 = getnum()             # ユーザー定義関数の戻り値(num)の取得
    print(f"{num1}+{num2}=?")
```

まず、ユーザー定義関数の部分について説明します。

```python:
# ユーザー定義関数の作成
def getnum():
    num = randint(1,100)        # random関数を使用し、値を取得
    return num                  # numに格納された値を戻り値とする
```

**def getnum():**で関数名を定義しています。
この関数名「getnum()」は、関数を呼び出すときに使用します。
**変数(num)**には、randomモジュールから取得した1~100のランダムな数値が格納されます。
取得した数値を、渡したいので**returnの戻り値にはnum**を記載しています。

```python:
# 10個作成するため、For文で10回ループ
for i in range(10):
    num1 = getnum()             # ユーザー定義関数の戻り値(num)の取得
    num2 = getnum()             # ユーザー定義関数の戻り値(num)の取得
    print(f"{num1}+{num2}=?")
```

取得したユーザー定義関数の戻り値は
**num1 = getnum()**　
で取得しています。
その為、変数(**num1**、**num2**)には、randomモジュールで取得した数値が格納されます。

プログラムの実行結果は、以下になります。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1773587/cc990048-cb5f-47aa-9679-78ac5cb26479.png)
#最後に
ユーザー定義関数の説明は以上になります。
自分で関数を作成し、コードを見やすくしたり
処理を部品化することで、他のプログラムにも使用できたりなど
プログラムを作成するには、便利で知っておいたほうがいい情報だと思います。
まだまだ、pythonに関しては初心者ですが皆様の役に立てれば幸いです。
パスワードの表示/非表示の切り替えボタンを作成

# パスワードの表示/非表示の切り替えボタンを作成する


## やりたいこと
簡易的なパスワードの表示ボタンを作成したい
HTMLのみに記述

## 概要
調べまくった結果、JavaScriptを使用しないと厳しい...
が、記述としてはあまり良くないかもしれないがHTMLに記述しても作成できる。
deviseのパスワードに追加して記述していく。

## 具体例
```
<%= f.password_field :password, ... , id: "pass"　←追加(好きな名前で)
<input type="checkbox" onChange="document.getElementById('pass').type = (this.checked) ? 'text' : 'password';">
パスワードを表示する
```
パスワードはtype="password"からtype="text"に変換させれば表示することができるので、onChangeを使用して変換させる。
その際、ById('この部分')をパスワードのidと同じにしておく。

## 結果
![](https://i.gyazo.com/81e618a168422fe6569044265353bda8.png)
inputのtypeをcheckboxにして(this.check)とすることで、チェックボックスをクリックした時にパスワードが表示されるようになる。

## 終わりに
忘れないためと、同じことで悩んでいる人の力に僅かでもなれればと思い投稿しました。自分では簡潔に表示することができたと思っていますが、まだまだ学習中の身ですのでもっと良い記述方法があるかも知れません。
【React】改行コード\n入り文字列を改行して表示する

#はじめに
APIアクセスで返ってきたエラーメッセージに改行コード`\n`が入っているとき、そのままメッセージを出力しても改行が反映されていませんでした。
`\n`を`<br>`に変換すればええんやろ！と思っていたら、`<br>`がただの文字列として出力されただけでした。
問題解決に少々詰まったのでメモとして残します。

#問題点
改行コード入りのメッセージを出力しても改行が反映されない。

```tsx
export const Body = () => {
  const body =
    'ユニコーンガンダム\nクスィーガンダム\nガンダムF91\nクロスボーンガンダムX1';

  return (
    <div>
      {body}
    </div>
  );
};
```

![スクリーンショット 2021-09-19 16.27.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/49eca1a1-28c8-e2a7-072e-161a8ce15349.png)

#解決策
`<br>`タグをJSXで認識できる形にします。
メッセージを改行コード`\n`で分割して配列にし、mapメソッドで配列をループすることで`<br>`を含んだJSX要素を返すようにします。

```tsx
export const Body = () => {
  const body =
    'ユニコーンガンダム\nクスィーガンダム\nガンダムF91\nクロスボーンガンダムX1';

  return (
    <div>
      <MultiLineBody body={body} />
    </div>
  );
};

const MultiLineBody = ({ body }: { body: string }) => {
  const texts = body.split('\n').map((item, index) => {
    return (
      <React.Fragment key={index}>
        {item}
        <br />
      </React.Fragment>
    );
  });
  return <div>{texts}</div>;
};
```

以下のように改行コードが反映されるようになります。
![スクリーンショット 2021-09-19 16.29.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/b2b6fe44-eef3-1368-5957-6237e091b377.png)

#参考資料

https://chaika.hatenablog.com/entry/2020/07/12/083000

https://www.digitalocean.com/community/conceptual_articles/understanding-how-to-render-arrays-in-react-ja
JavaScriptで外部画像ファイルを一括ダウンロード

chromeのみで確認
外部ファイルを表示させているサイトから画像をダウンロードしたい時、download属性だけでは機能しないので
クロスドメイン制限回避の為にこれを使うといいかも

https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf

```javascript:sample.js
function geturl(index) {
  const gallery = document.getElementsByClassName("classname");
  let url = gallery[index].getAttribute("href");
  return url;
}

function galleryDownload(i) {
  return new Promise((resolve) => {
    setTimeout(() => {
      let url = geturl(i);
      console.log(url);
      let xhr = new XMLHttpRequest();
      xhr.open("GET", url, true);
      xhr.responseType = "blob";
      xhr.onload = function () {
        const dataurl = (window.URL || window.webkitURL).createObjectURL(
          this.response
        );
        let a = document.createElement("a");
        a.href = dataurl;
        a.setAttribute("download", url);
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        window.URL.revokeObjectURL(dataurl);
        resolve("wait");
      };
      xhr.send();
    }, 1000);
  });
}

const gallery = document.getElementsByClassName("classname");
let length = gallery.length;
console.log(length);

async function Download() {
  for (let i = 0; i <= length; i++) {
    await galleryDownload(i);
  }
}

Download();
常用正規表現

よく使う正規表現です。
参考として使ってください。
引き続き更新～～～

* 数字表現

```markdown
3桁の数字　: ^\d{3}$
最低3桁の数字：^\d{3,}$
3桁～6桁までの数字：^\d{3,6}$
0か0以外で始まる数字：^(0|[1-9][0-9]*)$
```

* 文字列表現

```markdown
漢字　: \u3400-\u9FFF\uF900-\uFAFF]|[\uD840-\uD87F][\uDC00-\uDFFF
ひらがな : \u3041-\u3096
かたがな : \u30A1-\u30FA
半角英字列 : [a-zA-Z]+
半角・全角英字列 : [a-zA-Zａ-ｚＡ-Ｚ]+
全角文字 : [^\x01-\x7E]+
英字と数字 : ^[A-Za-z0-9]+$
半角または全角のスペース : [\s　]
3~20桁の任意の文字列 : ^.{3,20}$
英字の文字列 : ^[A-Za-z]+$
数字、英字、アンダーバーの文字列 : ^\w+$ (または^[A-Za-z0-9_]+$)
ダブルコーテーションで囲まれた部分 : \x22(.+?)\x22*
行末から / 以外の文字列 : [^/]+$
~を含まないの文字列(~を含まれる文字列禁止) : [^~\x22]+
^%&',;=?$\"を許可する文字列 : [^%&',;=?$\x22]+
```

※ \x22　 とは　" です


* 特殊表現

```md
XMLファイル : ^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
空白行 （空白行削除時に使う）: \n\s*\r
郵便番号（例：1234567）　:　^\d{7}$
郵便番号（例：123-4567）　: ^\d{3}-\d{4}$
電話番号（例：0001112222）　: ^0\d{9,10}$  
電話番号（例：000-1111-2222）: ^0\d{2,3}-\d{1,4}-\d{4}$
暗証番号(弱) (アルファベットで始まり、半角6けた以上18けた以内でアルファベット、数字とアンダーバー) :
　^[a-zA-Z]\w{5,17}$
暗証番号(強) :　
日付(弱)（例：2021-09-27）　:　^\d{4}-\d{1,2}-\d{1,2}
日付(月) (例：01~09か1~12)　: ^(0?[1-9]|1[0-2])$
日付(日) (例：01~09か1~31)  : ^((0?[1-9])|((1|2)[0-9])|30|31)$
毎月の25日にマッチ (例：2014-1-25) : \d{4}-\d{1,2}-25
URL　　:　^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
ドメイン　　:　[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
Email　:　^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
HTMLタグ : <TABLE.*?>
IPアドレス : \d+\.\d+\.\d+\.\d+
IPアドレス : ((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))
IPv4 : \\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b
IPv6 : (([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])) 

```
【Java】 spullara/mustacheを使ってRuby風の文字列の式展開を行う

## 概要
Javaで文字列中に変数の値を埋め込みたいという場合、+演算子でつなぐか`String.format`を使うかと言ったところが、主な選択肢になるような気がします。ただ、どちらの方法も個人的にはあまりソースの可読性が良いとは感じず、できれば[【Ruby】 式展開を使って文字列の中で変数を使おう](https://pikawaka.com/ruby/formula-expand)の記事にあるような形で、変数を埋め込みたいところです。
ということで、今回はなんとかRubyのような感じでJavaでも書けないかということで、記事を書いてみます。

## 対応方針
* [こちら](https://ja.stackoverflow.com/a/2974)のstackoverflowの記事にあるように、`Mushtache`というテンプレートエンジンを使えば、それっぽく書けるように感じました。ということで、Mushtacheを使って実装してみる方針とします。

## 前提など
* Mushtacheについて、調べるといくつかライブラリが存在するようですが、今回は[spullara/mustache.java](https://github.com/spullara/mustache.java)を使用してみます。2021年9月時点で、直近で更新もされているように見受けられるので。
* spullara/mustacheのバージョンについては`0.9.10`を前提とします。

## 実装サンプル
`spullara/mustache`のドキュメントによると、クラスのプロパティを埋め込む方式と、Mapオブジェクトに設定したkey・valueで埋め込む方式があります。実装サンプルでは2つの方法を試してみてます。
また、文字列を変数で使用することも想定し、StringWriterに出力しています。

```java:StringInterpolation.java
public class StringInterpolation {

    @Builder
    static class Item {
        String id, name;
        Item(String id, String name) {
            this.id = id;
            this.name = name;
        }
    }

    public static void main(String[] args) {
        try {
            // クラスの変数で式展開
            StringWriter sw = new StringWriter();
            MustacheFactory mf = new DefaultMustacheFactory();
            Mustache mustache = mf.compile(new StringReader("id:{{id}}、name:{{name}}"), "exampleClass");
            mustache.execute(
                    new PrintWriter(sw),
                    Item.builder().id("classId").name("className").build()
            ).flush();
            System.out.println(sw.toString());

            // Mapで式展開
            HashMap<String, String> scopes = new HashMap<String, String>();
            scopes.put("id", "mapId");
            scopes.put("name", "mapName");
            sw = new StringWriter();
            mf = new DefaultMustacheFactory();
            mustache = mf.compile(new StringReader("id:{{id}}、name:{{name}}"), "exampleMap");
            mustache.execute(new PrintWriter(sw), scopes).flush();
            System.out.println(sw.toString());
        } catch (IOException e) {
            System.out.println("IOException");
        }

    }
}

```
【勉強メモ】SSL/TLSとhttp/httpsの違い

分かったつもりでも違いを理解できていなかったので、
調べてみたときのメモです。

# HTTP（Hypertext Transfer Protocol）とは
WebサーバとWebブラウザの間で、Web情報をやりとりするためのプロトコル（通信規則）。

# HTTPS（Hytertext Transfer Protocol Secure）とは
HTTP通信よりもセキュリティを高めたもので、
SSL/TLSの仕組みを使い、SSLサーバ証明書をインストールすることで、以下を実現している。

* 通信の暗号化（盗聴を防ぐ）
* サーバの正当性の確認（なりすましを防ぐ）
* メッセージ認証（改ざんを防ぐ）

# SSL（Secure Sockets Layer）とは
HTTPSにある、3つのセキュリティを実現するための仕組み。
セキュリティの脆弱性が判明し、現在では使われていないが、名称は残っている。

# TLS（Transport Layer Security）とは
SSLに代わって新たに登場した仕組み。
現在はこちらが使われているが、SSLと呼ばれることが多い。

# SSL/TLSサーバ証明書の仕組み
[SSLって何？意味や仕組みをわかりやすく解説！ | さくらのSSL](https://ssl.sakura.ad.jp/column/ssl/)
[【図解】よく分かるデジタル証明書(SSL証明書)の仕組み 〜https通信フロー,発行手順,CSR,自己署名(オレオレ)証明書,ルート証明書,中間証明書の必要性や扱いについて〜 | SEの道標](https://milestone-of-se.nesuke.com/sv-advanced/digicert/digital-certification-summary/)
[SSL証明書とは？仕組みや種類についてわかりやすく解説 | システム運用ならアールワークスへ](https://www.rworks.jp/system/system-column/sys-entry/21283/)

[HTTPとは？HTTPSとの違いをサイト移行で実施するリダイレクト設定などをもとに解説 | ITコラム｜アイティーエム株式会社](https://www.itmanage.co.jp/column/about-http-https/)
[HTTPS と SSL と TLS：その違いを５分でわかりやすく解説！ | キュービストブログ](https://blog.qbist.co.jp/?p=1441)
Raspberrypi Pi4にgo言語のインストール

# はじめに

RaspberryPi4にGo言語のインストールをする必要が出たので最新版をインストールして動作テストしてみる

なお、OSは[64biのRaspberryPi OS](http://downloads.raspberrypi.org/raspios_arm64/images/)を使用している

# インストール

以下のコマンドで、Go言語をインストールする

```bash
wget https://golang.org/dl/go1.17.1.linux-arm64.tar.gz
tar -xzf go1.17.1.linux-arm64.tar.gz
sudo mv go /usr/local
rm -rf go1.17.1.linux-arm64.tar.gz
echo "export PATH=\$PATH:/usr/local/go/bin" >> ~/.bashrc
sourc ~/.bashrc
```

# 動作テスト

goのパスが通っていることを確認

```bash
$ go version
go version go1.17.1 linux/arm64
```

以下の簡単なプログラムを使用してビルドできるかの確認

```golang:main.go
package main

import "fmt"

func main() {
	fmt.Println("test")
}
```

以下のコマンドでビルドをが通ることを確認

```bash
go build main.go
```

実行すると以下の通りになる

```bash
$ ./main 
test
```

もしフォルダ指定でビルドする場合は以下の通り初期化を行う

```bash
go mod init hello
go mod tidy
```

初期化後以下のコマンドでビルド可能

```bash
go build ./
```

# 終わりに

とりあえず、簡単にインストールができたので、
Go言語を使用してセンサー制御のプログラムを開発する続きに入る