OmniAICreator/Qiita-1.07M huggingface dataset:
ssh接続の設定

# 背景  
sshコマンドを叩くと、様々な理由でWarningが出ることがある。  
# 概要
致命的なエラーではないものの、ノイズになってしまい作業の邪魔になってしまうことがあるので、これらを非表示にする方法について記載します。

# Warningの原因  
まず自分がよく遭遇するWarningとその原因について紹介します。

1つ目

```
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
```
原因：sshサーバ証明書リストというのがあり、.ssh/known_hostsに保存されているのですが、ここの情報が違う時に出るWarningです。

2つ目

```
Warning: Permanently added 'xx.xx.xx.xx' (ECDSA) to the list of known hosts.
```
原因：初めて接続する場合や、以前接続したことのあるホストの証明書が変更された場合に出力されます

# 解決方法  
### UserKnownHostsFile
`.ssh/config`にUserKnownHostsFile=/dev/nullと設定するとknown_hostsに書き込むという処理をスキップできます。
`WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!`のWarningを削除するのに設定しました。

### Loglevel
`.ssh/config`にLoglevelを設定することで表示内容を制御することができます。
デフォルトではINFOが設定されているので、`Loglevel ERROR`と設定すると`Warning: Permanently added`の出力は非表示になります。

# まとめ 
* 一部ではありますが、Warningの内容と、原因、解決方法についてまとめてみました。
* 設定の際はセキュリティ等を考慮して正しく制御してください。
VisualStudio2022拡張機能の紹介

# Visual Studio で使用している拡張機能

初投稿です。
テストも兼ねて、私が Visual Studio で使用している拡張機能を紹介します。

## 環境

- Visual Studio Community 2022

## 拡張機能

- [XAML Styler](https://marketplace.visualstudio.com/items?itemName=TeamXavalon.XAMLStyler)
  UWP や WPF で使用する XAML というマークアップ言語を整形してくれる拡張機能です。
  GUI を伴うアプリケーションの開発において、とても重宝します。
  下記のように整形されます。

```xaml:Sample_before.xaml
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBox Grid.Row="0" Text="Sample" Height="50" Width="100" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>
    <Label Grid.Row="1" Content="Sample" Height="50" Width="100" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>
    <Button Grid.Row="2" Content="Sample" Height="50" Width="100" Click="Button_Click"/>
</Grid>
```

```xaml:Sample_after.xaml
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <TextBox
        Grid.Row="0"
        Width="100"
        Height="50"
        HorizontalContentAlignment="Center"
        VerticalContentAlignment="Center"
        Text="Sample" />
    <Label
        Grid.Row="1"
        Width="100"
        Height="50"
        HorizontalContentAlignment="Center"
        VerticalContentAlignment="Center"
        Content="Sample" />
    <Button
        Grid.Row="2"
        Width="100"
        Height="50"
        Click="Button_Click"
        Content="Sample" />
</Grid>
```

- [Toggle Comment 2022](https://marketplace.visualstudio.com/items?itemName=techhypno.ToggleComment)
  Ctrl + / でコードをコメントアウト／解除出来るようになります。
  デフォルトでは、コメントアウトが Ctrl + k → c で、コメント解除が Ctrl + k → u なので、コメントアウト／解除が非常に楽になります。

- [Format document on Save](https://marketplace.visualstudio.com/items?itemName=mynkow.FormatDocumentOnSaveLegacy)
  コードを保存するタイミングで、コードの整形が実行されます。
  Visual Studio の場合、設定次第で、コードの終了を表す ; を入力したタイミングや、コードを貼り付けたタイミングでコード整形が実行されます。保存時にコード整形を実行する設定はなかったと記憶しています。

## まとめ

以上となります。数は少ないですが、参考になれば幸いです。
皆さんが使用している拡張機能も教えて頂けると嬉しいです！
pycodestyleを使ってPEP8に平伏する

こんにちは、夜ご飯は納豆です。

納豆単体でも料理として成立しているのに、キムチやオクラなんかと一緒に食べるとさらにおいしいのでつい連日食べてしまうんですよね。

しかも三パックとかでしか売ってないので続けて食べさせようとしているんじゃないかとか疑ってしまいます。

さて、、納豆を食べ続けていくよりも、Qiitaにまとめていくのを続けていきたいです。

今日は、コーディング規約を守りながら書いていく際に自分的に怒られがちなものを書き連ねていきたいと思います。
※備忘録として書くので詳しいことは実際にコーディング規約を見るのが早いと思います。


# コーディング規約について
* コーディング規約は、必ずしも順守しなくてはいけない(守らなかったら罰金！とかではなく)ものではないが守ることでより読みやすく、一貫性のあるコードを書くためのものです。
* 各プログラミング言語のコーディング規約
どの言語にもコーディング規約なるものが存在します。[^1]
* Pythonでは通称PEP8(ペップエイト)と呼ばれる[ドキュメント](https://www.python.org/dev/peps/pep-0008/)にまとめられています。
* 近々PEP8の理解度が計れる[PythonZen & PEP 8 検定試験](https://www.pythonic-exam.com/exam/pythonzen-pep-8)が、無償で始まるようです！
* 規約の存在意義としては、コードを読みやすくするとともに、Pythonで書かれた幅広いコードのスタイルを一貫させることにあるようです。
* [PythonZen](https://www.python.org/dev/peps/pep-0020/)にも以下のように書いてあります。(訳は自分でつけました。)

```
Readability counts. 
"読みやすさは配慮しよう"

(中略)

There should be one-- and preferably only one --obvious way to do it.
"誰が見ても良い方法がなにかあるはずだ"

(以下略)
```
可読性と一貫性を大事にしていきたいです。

# pycodestyleについて
* 自分で開発したプログラムがPEP8に違反していないかどうかをチェックしてくれます！
* 以下、インストール方法

> 開発環境はos:Windows / Python: 3.10.2 64-bit / IDE:Microsoft VS Codeです。
> Pythonのインストールは割愛させてください。

```
# 最新版をインストール 
pip install pycodestyle

# バージョンを確認
pycodestyle --version
>>> 2.8.0
```
上記で、pycodestyleはインストール完了です。

実際に開発したプログラミングをチェックしてみます。

```
# チェック
pycodestyle プログラミング名.py
>>> プログラミング名.py:26:1: E265 block comment should start with '# '
    プログラミング名.py:29:1: E265 block comment should start with '# '
    プログラミング名.py:32:80: E501 line too long (84 > 79 characters)
    プログラミング名.py:38:9: E265 block comment should start with '# '
    プログラミング名.py:43:22: E711 comparison to None should be 'if cond is not None:'
    プログラミング名.py:46:9: E265 block comment should start with '# '
    プログラミング名.py:46:24: W291 trailing whitespace
```
👆こんな感じで規約にのっとっていない箇所を返してくれます。(#の後ろ半角空け怠けすぎ...)


# 違反備忘録

## CASE1 「Noneの場合の比較演算子」

```
E711 comparison to None should be 'if cond is not None:'
```
```if i != None:```の場合など比較演算子使う際に、```!= None```ではなく```is not None```って書く。

## CASE2 「お尻一行は空行」

```
W292 no newline at end of file
```
そ、そんな。。

## CASE3 「importは一番はじめに書こう」

```
E402 module level import not at top of file
```
たしかに、VBAとかでも上に書いてたよなって思いました(小並感)

# Tips
Python のソースコードを自動で PEP8 に準拠させるツールとして<b>autopep8</b>というものがあるようです。違反している箇所が多ければ便利そうです。。が、まずはコーディング規約の所作(?)を身に付けたいので使いたい気持ちをちょっと抑えておこうと思います(笑)


# 参考にさせていただいた記事
* [プログラマが持つべき心構え (The Zen of Python)](https://qiita.com/IshitaTakeshi/items/e4145921c8dbf7ba57ef)



[^1]: Rubyなど正式なコーディング規約がないものも存在します。正式なコーディング規約はないものの[規約](https://www.ruby.or.jp/ja/tech/development/ruby/050_coding_rule.html)としてまとめられていることが多い認識です。
ESLint + Prettierの競合を回避する(2022年2月版)

## はじめに

eslintとprettierを共存させる時の設定を調べたのでまとめます。

## 環境

- Node v14.18.0
- React v7.17.0.2
- ESLint v7.32.0
- Prettier v2.5.0

## 結論

色々あるけど、現在（**2022年2月**）は[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)を導入するのがベストプラクティスらしい。
[eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier)を紹介している過去の記事があるが、現在は**非推奨**なので要注意。

### ESLint vs Prettier

雑談程度に..

Linterには2つの大きな目的（ルールカテゴリ）がある。

- コードをフォーマットする（インデント幅や改行など）
- コードの品質を維持する（未使用変数や未使用importなど）

Prettierは「コードをフォーマットする」に徹し、ESLintは「コードの品質を維持する」徹すべきらしい。
（[Prettierの公式がそう言っている](https://prettier.io/docs/en/comparison.html)）

前述した非推奨の`eslint-plugin-prettier`は、ESLintでフォーマットもしてしまおう的なやつなので、非推奨なのだと思われる。
ちなみに`eslint-config-prettier`は、ESLint側のフォーマットに関するルールをoffにするというもの。


## 導入手順

eslintとprettierの導入は割愛します。

①ESLint内でpluginを使うにはnpmパッケージが必要なのでインストール

```
npm install --save-dev eslint-config-prettier
```

②.eslintファイルに設定を追加

```.eslint.js
{
  extends: [
    "some-other-config-you-use",
    "prettier" // これを追加
  ]
}
```

③(必要であれば)VSCodeの設定を変更する

設定例:

```settings.json
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
}
```

他にも`editor.codeActionsOnSave`のoptionはあるので、[拡張機能: ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)を参考に設定する

## 終わりに

普段何気なく使っているけど、いざ自分が設定するという立場になって、やっと仕組みを理解できた！
mac-ショートカットキー

## ブラウザで使用するもの
新しくMacbookProを購入したので備忘録的に

1 **command + T**
新しい(別)タブを立ち上げる

2 **command + shift + T**
直近で閉じたタブを立ち上げ直す

3 **command + N** 
新しい(別)ウィンドウを立ち上げる

4 **command + shift + N** 
シークレットウィンドウを立ち上げる

5 **command + W** 
タブを閉じる（タブが1つの場合はウィンドウを閉じる）

6 **command +  [** 
(前のページへ)戻る

7 **command + ]** 
(次のページへ)進む

8 **command + R** 
ページを再度読み込み(更新)

9 **command + +** 
画面を拡大(ズーム)する

10 **command + -** 
画面を縮小(ズームアウト)する

11 **command + 0** 
画面表示をデフォルト(100％)にする

12 **command + クリック** 
リンク先を別タブで開く

13 **control + tab** 
右のタブへ移動する

14 **control + shift + tab** 
左のタブへ移動する

15 **command + 1,2,3,4...** 
左から順に1､2､3...のタブを開く

16 **command + ↑or↓**
一番上or下までスクロール

## 基本操作で便利なもの

1 **command + tab** 
アプリケーションの切り替え（右送り）

2 **command + shift + tab** 
アプリケーションの切り替え（左送り）

3 **command + C** 
コピー

4 **command + V** 
貼り付け

5 **command + X** 
切り取り(カット)

6 **command + A** 
全てを選択

7 **command + S**
保存

8 **command + Z** 
元に戻す

9 **command + shift + Z** 
やり直す

10 **command + delete** 
ファイルをゴミ箱移動

11 **command + N** 
新規Finderを開く（Web版でも紹介した）

12 **command + shift + N** 
新規フォルダを作成する

13 **command + Q** 
アプリケーションを終了

14 **command + M** 
ウィンドウをDockにしまう（左上の黄色のボタンの役目）

15 **command + space** 
Spotlightを開く

16 **command + option + D** 
Dockの表示/非表示

17 **command + Shift + 3**
スクリーンショット

18 **command + Shift + 4**
選択箇所のスクリーンショット
[SpringBoot][Vue.js]axios通信のレスポンスヘッダの項目が一部不足していて取得できない

## 環境
Amazon EC2
Spring Boot
kotlin
Vue.js
Apache
Tomcat

## 何が起きたか
・EC2上にデプロイしたVue.jsからAPIにアクセスしてAuthorizationヘッダーに設定したトークンを取得しようとしたが、取得できなかった
・console.logで確認したところ、headerの一部の項目が欠落している（Access-Control-Expose-Headersで許可されている項目しか取得できない）
　https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
・run serveしたローカル環境では取得出来ていた

## ハマったポイント
・Apacheでhttpd.confおよび.htaccessにheaderに関する設定は正しく行っていた（何度も確認）
・JavaScriptでheaderの情報が一部しか取れない
・DevToolsのネットワークからレスポンスを見るとheaderの情報は設定されている

## 原因
・API側でAccess-Control-Expose-Headersに対する許可設定をしないと、JavaScriptで許可されている項目以外は取得できない（Apacheの設定だけでは足りていなかった）


## 解決方法
・SpringBootでCORSを設定する箇所に以下を記述する

``` kotlin
.addExposedHeader(CorsConfiguration.ALL)
```
Pythonなどを学べるサイト備忘録

Pythonや機械学習などのコンテンツについて自分が学ぶ際の参考にしているサイトについて、ふとまとめたくなったのでまとめます。
随時追加予定

####東京大学　数理・情報教育研究センター　「Pythonプログラミング入門」
Pythonの基礎を押さえた上で、代表的なライブラリから機械学習の基礎まで扱っています。
リンク先のページでは、HTML版やColab版、Jupyter版も提供されているので、好きな形で閲覧できます。
Google Colabという無償の実行環境でPythonコードを手軽に実行できるので、Pythonの環境を作らずともPythonについて学ぶことができます。

[東京大学　Pythonプログラミング入門](https://sites.google.com/view/ut-python/%E3%83%9B%E3%83%BC%E3%83%A0)

####京都大学　「Pythonプログラミング演習」
東大のものと比べると文字が大きくて図版が豊富であり見やすい印象です。
Colabノートなどは用意されていませんが、環境構築から説明されているので、Python及びプログラミング初学者でも安心して学べます。

[京都大学　Pythonプログラミング演習](https://repository.kulib.kyoto-u.ac.jp/dspace/handle/2433/265459)

####Python Japan 「ゼロからのPython入門講座」
プログラミング未経験者を対象に、Pythonに必要な基礎知識を学ぶことができます

[Python Japan ゼロからのPython入門講座](https://www.python.jp/train/)

####東京工業大学　機械学習帳
東京工業大学情報理工学院 機械学習の講義で使用した講義ノート「機械学習帳」が無料公開されています。
機械学習の理論と実装を一緒に説明することで、理論の実装や応用に触れています。

[東工大　機械学習帳](https://chokkan.github.io/mlnote/index.html)

####Chainer ディープラーニング入門
ChainerはPythonの深層学習フレームワークです。
環境構築の方法やディープラーニングで使われる数学など、 ディープラーニングを学び始めるのに必要な前提知識を可能な限りスキップせず解説されています。
開発が終了していますが基本的な内容のため参考になります。

[Chainer ディープラーニング入門](https://tutorials.chainer.org/ja/)

とりあえず思いついたサイトについて軽く列挙しました。
Python関連の内容を学びたいときは基本的にはここで紹介している東大と京大のコンテンツで十分に学べると思います。
dpkg: error processing archive /var/cache/apt/archives/libc6_2.27-3ubuntu1.4_amd64.deb (--unpack): のエラー対応

CodeBuildのbuildspec.ymlで実行した

```
apt-get upgrade -y
```

で以下エラーが発生した際の対応を残します

```
ERROR: Your kernel version indicates a revision number
of 255 or greater.  Glibc has a number of built in
assumptions that this revision number is less than 255.
If you\'ve built your own kernel, please make sure that any
custom version numbers are appended to the upstream
kernel number with a dash or some other delimiter.

dpkg: error processing archive /var/cache/apt/archives/libc6_2.27-3ubuntu1.4_amd64.deb (--unpack):
 new libc6:amd64 package pre-installation script subprocess returned error exit status 1
Errors were encountered while processing:
 /var/cache/apt/archives/libc6_2.27-3ubuntu1.4_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
```

対応内容

ビルドを行う環境を最新のイメージにアップデート
アップデート前はstandard:4系でした

![スクリーンショット 2022-02-10 19.18.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356664/f4f645c0-5f62-95a1-97d4-744c72199fa9.png)

ビルドを再実行したらエラーは解消されました
【Excel】行番号の上ずれ

以下のような現象。行番号が上ずり、上部分が欠けてしまっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501146/c5051091-4502-4dc7-6042-93c6e2c311c7.png)
これは「標準」のスタイルのフォントサイズに依存するみたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501146/3f7481f7-20c4-80b0-f7eb-14f21d784297.png)
「標準」を右クリックから「書式設定」でフォントサイズを小さくすれば修正できます。
Unityアニメーターすぐに遷移してくれない時の対処方法(備忘録)

# はじめに
Unityのアニメーターのトランジションでアニメーションを遷移させるときすぐに遷移してくれない時があるのでメモ程度に残していきたいと思います。

# 原因
## 1.HasExitTimeの設定がONになっている
遷移条件をTriggerにしてTriggerがOnになった時にすぐにアニメーションを遷移させたい時はこちらの設定はOffにする必要があります。
逆にアニメーション終了まで待ちたかったり、アニメーションをブレンドしたいときはOnにする必要があります。

## 2.ExitTimeが0(ぴったり)になっている
こちらが落とし穴でした。
長さが１フレームしかないアニメーションを作成して、そのアニメーションが終了したいときに遷移したい時以下のように設定したとします。
![Screen Shot 2022-02-10 at 18.55.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188476/a2e1f06d-eb23-177a-b34f-9ab032d45d9a.png)
しかし、こちらの設定ではすぐに遷移してくれません。
ExitTimeを限りなく0に近い値で設定するとすぐに遷移してくれました。
![Screen Shot 2022-02-10 at 18.56.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188476/04a09230-feb8-c59b-da5e-0756bd25e16a.png)

1e-10 = 0.0000000001

# 最後に
HasExitTimeがOnになっていてすぐに遷移しないことはよくあることだと思いますが、２個目のExitTimeを0に設定した時にすぐに遷移できなくなるのは落とし穴ですね。
すぐにアニメーションが遷移されなくて困っている方の参考になれば幸いです。
他にも何かあれば追記していきたいと思います。
40 代おっさん Laravelのモデルクラスでメソッドを使ってみる。

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 構築環境

・EC2:Amazon Linux2
・PHP7.3
・Laravel 5.8
・mariadb

前回の記事からの続きですので、こちらを見てくださるとうれしいです。

<https://qiita.com/kou1121/items/a7328f639bfb615d5f74>

### クラスの拡張

以前Personクラスを作ったのでそちらを拡張

```php
public function getData()
{
   return $this->id . ':' . $this->name . ' (' . $this->age . ')'; 
}
```

上を書き加える。

次に
index.blade.phpを修正

```php
<table>
    <tr><th>Data</th></tr>
    @foreach ($items as $item)
        <tr>
            <td>{{$item->getData()}}</td>
        </tr>
    @endforeach
</table>
```

これで見て見るとid,name,ageがまとまったはずです。

### IDによる検索

findメソッドはIDによるレコード検索を行うのに用意されたメソッド

<font color="Red">$変数 = モデルクラス :: find( 整数 );</font>

テーブルのプライマリーキーは「id]という整数値のフィールドであるという前提で実行している。

#### findアクションを作る

##### find.blade.phpを作成

viewaファルダのpersonフォルダ内に作ってください。
コードは

```php
<form action="/person/find" method="post">
    @csrf
    <input type="text" name="input" value="{{$input}}">
    <input type="submit" value="find">
</form>
@if (isset($item))
<table>
    <tr><th>Data</th></tr>
    <tr>
        <td>{{$item->getData()}}</td>
    </tr>
</table>
@endif
```

##### PersonControllerの修正

```php
    public function find(Request $request)
    {
        return view('person.find',['input' => '']);
    }
    
    public function search(Request $request)
    {
        $item = Person::find($request->input);
        $param =['input' => $request->input, 'item' => $item];
        return view('person.find', $param);
    }
```

find　　　/findにGEtアクセスしたときの処置
search　　送信されたinputフィールドの値を引数に指定してfindメソッドを呼び出す。

$item = Person::find($request->input);
IDによる検索

##### ルート情報の追加

web.phpに

```php
Route::get('person/find', 'PersonController@find');
Route::post('person/find', 'PersonController@search');
```

### whereによる検索

ID以外の検索は
whereメソッドを使う

複数のレコードを得る
<font color="Red">$変数 = モデルクラス :: where( フィールド名 , 値 )->get();</font>

最初のレコードだけを得る
<font color="Red">$変数 = モデルクラス :: where( フィールド名 , 値 )->first();</font>

whereで検索の条件を設定し、getまたはfirstを使ってレコードを取得

#### nameを検索

searchを書き換え

```php
public function search(Request $request)
    {
        $item = Person::where('name',$request->input)->first();
        $param =['input' => $request->input, 'item' => $item];
        return view('person.find', $param);
    }
```

$item = Person::where('name',$request->input)->first();
nameの値でレコードを収得しています。

## 参考資料

<https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF-Laravel%E5%85%A5%E9%96%80-%E6%8E%8C%E7%94%B0%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798052582>
mbed CLI

# CLI1

##　ツールチェインの場所
```
# グローバルに設定
mbed config -G GCC_ARM_PATH /Application/ARM/bin
# 削除　unset
mbed config -G GCC_ARM_PATH -U
# help
mbed config -h
```

## コンパイル
```
#コンパイル
mbed compile -t MAX32625PICO -m GCC_ARM
#クリーン
mbed compile -c
#ヘルプ
mbed compile -h
```
## ターゲット
```
# グローバル設定
mbed target -G MAX32625PICO
# ローカル設定
mbed target MAX32625PICO
```
## 設定
```
# 表示
mbed config --list
# 削除
mbed config TARGET -U
```

# CLI2
gcc-armへのパスが通っている必要がある。
## 初期
```
# mbed-osをディプロイしない
mbed-tools new project_name -c
```
##コンパイル

```
# -t -m 指示は必須
mbed-tools compile -t GCC_ARM -m MAX32625PICO
```

## cmakeを利用する
サポートされているターゲットはK64F, DISCO_L475VG_IOT01A, NRF52840_DK

```
# -t -m 両方同時に指示
mbed-tools configure -t GCC_ARM -m K64F

# -S : ソースフォルダ　、　-B mbed_config.cmakeのフォルダ
cmake -S . -B cmake_build/K64F/develop/GCC_ARM -GNinja

# バイナリ作成
cmake --build cmake_build/K64F/develop/GCC_ARM
# or
ninja -C cmake_build/K64F/develop/GCC_ARM
```
ubuntuのポートのすべて

初めての投稿なので間違っている部分があるかもしれません。もし間違っている部分があればコメントください。

##現在のポート状況
```
$ sudo ufw status
```

##設定のリロード
```
$ sudo ufw reload
```

##ポート開放
```
$ sudo ufw allow [ポート番号]
```

##ポート閉鎖
```
$ sudo ufw deny [ポート番号]
```

##すべてのポートを開放
```
$ sudo ufw default ALLOW
```

##すべてのポートを閉鎖
```
$ sudo ufw default DENY
```

##すべてのルール番号表示
```
$ sudo ufw status numbered
```

##ルールを削除する
```
$ sudo ufw delete [ルール番号]
```

##システムでファイアーウォールを有効にするか
```
$ sudo ufw enable
```

##システムでファイアーウォールを無効にするか
```
$ sudo ufw disable
```

##ポート一覧
| 基本的な使用ポート | ポート番号 |
|:-----------|------------:|
| ftp | 20,21 |
| ssh | 22 |
| http       | 80 |
| https | 443 |
【Laravel】「 One To One （1対1）」リレーションを学ぶ

# 「One To One 」リレーションを学ぶ

Laravel で使用できるデータベーステーブルのリレーションについて、今回は、「One To One」（１対１）の連携方法について記事を書きたいと思います。

## 基本的で理解しやすい「 One To One 」

基本的なリレーションとして「 `One To One` 」（1対1）の連携方法を勉強していきます。今回は例として、ユーザー情報を管理する `User` モデルと、ユーザー情報に関連付けられた個人情報を管理する `Profile` モデルを使って、双方の関係性について考えていきましょう。

## `User` モデルと `Profile` モデルの関係

`User` モデルと `Profile` モデルの関係性を以下に表します。
`Users` テーブル と `profiles` テーブルがあり、双方の関係性は「 1対1 」となっています。`profiles` テーブルの `user_id` が `users` テーブルの外部キーとなっています。


![Untitled Diagram(3).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106716/928e7d4e-97eb-e319-aff4-4cbda5b8f318.jpeg)

## リレーションを定義して、モデル情報を取得する

両方のデータベースを横断して目的のデータを取得するために `リレーション` を定義してモデル情報を取得するための `メソッド` を書いていきます。

まずは、`User` モデルが `Profile` モデルの情報を取得するために、`User` モデルに `profile` メソッドを定義していきます。以下のような感じです。

```php:user.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * User に関連する Profile 情報を取得するメソッド
     */
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }
}
```

`profile` メソッドで、`hasOne` メソッドを呼び出しています。このメソッドの引数に、関連するモデルクラス（ここでは、`Profile` モデルクラス）を定義することで、目的のモデル情報を取得できるようになります。

例えば、**User モデルでユーザーIDを絞って、そのユーザーIDに関連する Profile モデルを取得したい場合** は、

```php
$profile = User::find(1)->profile;
```
という感じで、User モデルで ID を絞り込んでから、Profile モデルの情報を取得することができます。

一例として、`usersテーブル` の主キーのIDを絞ることができる `find` メソッドを使用後、`profilesテーブル` の各カラムの情報を得たい場合は、以下のようなコードになります。

```php
// 指定した User モデルに関連する birthday 情報を得たい場合
$profile_birthday = User::find(1)->profile->birthday;

// 指定した User モデルに関連する phone 情報を得たい場合
$profile_phone = User::find(1)->profile->phone;

// 指定した User モデルに関連する address 情報を得たい場合
$profile_address = User::find(1)->profile->address;
```

先ほどの、リレーション定義によって、User モデルから Profile モデルへの橋渡しができていることが分かりますね。

## 逆に、「Profile」から「User」モデルの情報を取得したい場合

Profile モデルから User モデルへの関係性を定義する場合は **従属している意味をあらわす `belongsTo` メソッド** を使用します。

```php:profile.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Profile extends Model
{
    /**
     * この電話を所有しているユーザーの取得
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
```

`user` メソッドを新しく追加して、`Userモデル` との関係性を定義しています。ここで先ほどと同じく、2つのモデルのリレーションによって、`Profiles` テーブルから、`Users` テーブルの情報を得る例を見てみましょう。

```php
// 指定した Profile モデルに関連する name 情報を得たい場合
$user_name = Profile::find(1)->user->name;

// 指定した Profile モデルに関連する email 情報を得たい場合
$user_email = Profile::find(1)->user->email;
```

`Profile::find(1)` で `profile` テーブルの主キーである `id` を対象に絞り込みを行い、その後、絞り込んだレコード `user_id` と `User` モデルに対応する情報を取得します。
JavaScript ループ 「break」「continue」

JavaScriptでループする意味のコードを記述するとき
「for文」か「while文」を使用するかと思います。

_for文コード_

```
for(let i=0;i<5;i++){
 document.write(i);
}
```
_出力_

```
01234
```

_while文コード_

```
let i=0;
while(i<5){
 document.write(i);
 i++;
}
```
_出力_

```
01234
```
上記のfor文とwhile文は同じ意味です。
この２の文に共通して使える「break」、「continue」という２つの命令があります。
簡単にいうと
「break」は、その時点で強制的にループを抜ける
「continue」は、後の処理をせずにループする
という意味です。どういうことかというと、

_for文「break」コード_

```
for(let i=0;i<5;i++){
 if(i===3)break;
 document.write(i);
}
```
_出力_

```
012
```
「document.write(i);」の前に、「if(i===3)break;」を記述することによって、
「もしiが３になったら、強制的にループを抜ける」
という意味になりブラウザへの出力は「３」の時点でループが停止した「０１２」になり、

_for文「continue」コード_

```
for(let i=0;i<5;i++){
 if(i===3)continue;
 document.write(i);
}
```
_出力_

```
012４
```
「document.write(i);」の前に、「if(i===3)continue;」を記述することによって、
「もしもiが３の時だけ、continueから後の処理を飛ばしてループを続行する」
という意味になりブラウザへの出力は「３」を飛ばした「０１２４」になるわけです。
ただこの「continue」は注意が必要で、

_while文コード_

```
let i=0;
while(i<5){
　　if(i===3)continue;
 document.write(i);
 i++;
}
```
_出力_

```
無限ルーーーーープ！
```
このように記述をしてしまうと、コードは上から順に読み込んでいくので、
「０」「１」「２」までは問題なくループし、
「３」の時のループでは「continue」が先に読み込まれて、
「i++;」により「i」が１増える前に次のループに行ってしまうので、
どれだけループしても一生「i」は「３」のままということになってしまいます。

_while文コード_

```
let i=0;
while(i<5){
 i++;
 if(i===3)continue;
 document.write(i);
}
```
_出力_

```
1245
```
このように命令文の順番を変えると、無限ループではなくなりました。
命令の最初に「i++;」があることによって
「０」からの出力ではなく「１」からの出力になってしまいますけどね。
【Kotlin】SJIS変換

#変換方法
toByteArray(charset("SJIS"))でSJIS変換可能。ByteArray型で出力。

```Kotlin
val text = "abcあいう"
val sjis = text.toByteArray(charset("SJIS"))
```

#補足

ByteArray型が扱いづらい場合、Int型に変換。

```Kotlin
fun String.toSjis(): Int {
	val byteArray = this.toByteArray(charset("SJIS"))

	var value = 0
	byteArray.forEach { byte ->
		value *= 0x100
		//符号なしの値に変換してから加算
		value += byte.toInt() and 0xFF
	}

	return value
}
```
筑波大enPiTに参加してみて

この記事は2021年度の筑波大学の[enPiT](https://enpit.coins.tsukuba.ac.jp/)という授業でチーム開発をした時の個人レポートです。
作成したプロダクトの紹介や、開発を通して感じたことを書いていこうと思います。

# そもそもenPiTとは
enPiTとは文部科学省が推進する以下のようなプロジェクトです。
> 「成長分野を支える情報技術人材の育成拠点の形成(enPiT)」は、4分野における高度IT人材の育成を目指しています。大学・企業界の協力体制のもとで推進されるリアリティの高い講義や演習など、特色あるプログラムを通じて実社会においてイノベーションを起こすことができる人材を輩出します。
([https://www.enpit.jp/](https://www.enpit.jp/)より引用)

今回私が参加したのは分野は[ビジネスシステムデザイン分野](https://bizsysd.enpit.jp/)であり、以下のようなことを目的としています。他にもビッグデータ分野などが存在しますが、詳しくは[ホームページ](https://www.enpit.jp/)をご覧ください。

> enPiTビジネスシステムデザイン分野(通称:BizSysD)は、社会やビジネスニーズに対する
実用的なソリューションとしてのビジネスアプリケーションやシステムデザインを
自ら提案、開発し、顧客の潜在的要求を満たすことのできる人材育成を目指します。
([https://bizsysd.enpit.jp/](https://bizsysd.enpit.jp/)より引用)

# 開発したプロダクト
今回、私達が開発したプロダクトは、「[シケタイ](https://hanashiainokairegistration.herokuapp.com/)」です。(※登録は筑波大生限定です)
これは、課題・試験対策をサボってしまう、1人で進められない筑波大生向けのWebアプリケーションです。
同じ課題を抱える人が集まれる場所を提供することによって、ClosedSNS(LINEや通常のDiscord)とは違って、同じ課題を抱える友人の少ない人でも同じ課題を抱えいる人と出会って課題を進めることができます。

# リーンキャンバス
### 顧客の課題
* (入学時から授業がオンラインで行われているため)大学内に友達が少なく、1人で課題・試験対策を進める際に、集中力が続かずすぐにサボってしまう
* (入学時から授業がオンラインで行われているため)大学内に友達が少なく、過去問を入手することができなくて試験対策が捗らない

### ソリューション
* 同じ課題を抱える人が集まれる場所の提供
* 過去問をみんなで共有できるクラウドの提供

### 独自の価値提案
* 同じタスクを持った人と一緒に課題・試験対策ができる

### 顧客セグメント
* 課題を溜めてしまっていて1人であまり進められない学生

### アーリーアダプター
* 筑波大の友達が少なくて、テスト直前に過去問を友達から入手することが困難な筑波大生

# 使い方
### 流れ
まずシケタイの[URL](https://hanashiainokairegistration.herokuapp.com/)をクリックすると、Discordサーバーへのリンク、プロダクトの概要、スケジュールカレンダーを見ることができます。
Discordサーバー内で、私達が開発した独自のDiscord botによって、快適に共同作業をするという流れです。

### 機能
* スケジュールカレンダー
    * 開かれる勉強会の把握・管理(登録・編集・削除)に用いられます
    * カレンダーに勉強会を登録すると、開始15分前にDiscord上で参加者者へ通知が送られます
![スケジュールカレンダー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525370/9f688be9-a7e4-67f6-5ffc-85b72c13be6c.png)
* 勉強会タイマー
    * 勉強会は勉強と休憩を1セットとし、それを繰り返すことで行われることを想定しています
    * 勉強会タイマーで、勉強時間・休憩時間・繰り返し回数を設定することができます
![勉強会タイマー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525370/4da590e5-9123-5718-966f-25fe63009f94.png)
* ファイル共有
    * 過去問などのファイルを勉強会の参加者同士で共有することができる

# 開発における自分の主な役割
私は、シケタイのサーバーの開発を担当しました。
もう1人と2人で、ペアプログラミングなどで協力してDjangoで開発を行いました。

# 期間を通した個人的振り返り
### enPiTを通じた学びと改善点
* PBL及びタスクボード作成能力
    * 初めは開発者目線でPBLを作成していましたが、ユーザーストーリーの見直しなどを行い、ユーザー目線でPBLを作成するようになりました
* タスクの細分化
    * 初めはタスクをざっくりと分けすぎて、チームメンバーによってタスクの解釈に差が出てしまっていましたが、タスクを細分化することによって共通認識をとることができるようになりました
    * また、自分たちが進められる量を徐々に見極められるようになりました
* 考えを言語化しないと伝わらない
    * スプリントプランニング、PBLリファインメント時に徐々に各自が意見を出すようになりました
AutifyのテストプランをGitHubActionsで動かす

Autifyの2022年1月25日のリリースで、Autify公式のGitHub Actions・Circle CI Orbがリリースされました。
私自身GitHub ActionsもCircle CI Orbあまり触ったことがないので、練習がてら触って、ちゃんと動いた方法を書いておきます。
Atutifyは基本的に公式のドキュメントが充実していますが、
少し技術的なこと（JSステップとかCI/CDツールとの連携とか）になると記載の仕方が、触ったことがない人にとっては少しだけ難しい気がします…
※あくまで個人の感想です。
なので公式ドキュメントを見て、はて？と思った方がここを見て解決できればいいな、と思います。

今回はGitHub Actionsとの連携についてです。
CircleCIは別の機会に書きます。

# はじめに

## 実現したこと
対象のリポジトリにPushがある毎にAutifyのテストプランを動かす。

## 環境について
Autifyを使用するには下記を準備する必要があります。

- Autifyのユーザー
- Google Chromeと拡張機能「Autify Recorder」

これらについては公式ページが詳しく書いていますので、[ユーザー登録と環境セットアップ](https://autify.zendesk.com/hc/ja/articles/900003243946-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E7%99%BB%E9%8C%B2%E3%81%A8%E7%92%B0%E5%A2%83%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97)をご確認いただくのが良いと思います。

## テストプランについて

テストプランについても動かしたいものを作成しておいてください。
今回私はYamamotoTestというテストプランを作成し、こちらを動かしていこうと思います。

![テストプラン.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121319/82a7d033-40dc-47aa-be61-49d8abdd5621.png)

## GitHubについて
今回はプライベートリポジトリを作成しました。
このリポジトリにpushがあったら、Autifyのテストが走る感じです。
![リポジトリ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121319/2053a337-7b89-2602-5463-21699b923518.png)



## 手順
AutifyをGitHub Actionsと連携する手順はざっくりと下記のような手順です。

1. Autifyでパーソナルアクセストークンを生成する（Autify側の準備）
1. ymlファイルを作成する（GitHub Actions側の準備）
1. 動かしてみる

### 1. Autifyのパーソナルアクセストークンを生成する

この発行はAutifyのアカウント設定 > 個人設定のページから可能です。
個人設定の真ん中に新しいパーソナルアクセストークンを生成がありますので、こちらに任意の名前を入力し、作成ボタンを押下します。
そうするとパーソナルアクセストークンが生成されます。
これは生成した際に赤字で書かれている通り、ページのリロードやページ移動してしまうと見れなくなってしまうため、
**必ずどこかにメモをして、保管**してください。

発行されたあとはこんな感じになります。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121319/40f7529e-9a88-cd62-fadf-6cba5f91f00c.png)

これでAutify側の準備はOKです。

### 2. ymlファイルを作成する
次に下記のようなymlファイルを準備します。
準備はMyRepoの直下に\\.github\workflowsというフォルダを自分で作成し、その中にymlファイルを格納しました。

```action.yml

name: "example"
# トリガーを決める
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Funtional test
        id: functional-test
        uses: autifyhq/web-run-test-plan-action@v1.0.0
        with:
          autify_for_web_api_token: #1.で生成したパーソナルアクセストークンを記載
          test_plan_id: # テストプランのIDを記載※
```

※テストプランのIDについて
作成したテストプランを選択し、テストプランの詳細を決めるページに飛ぶ。
その際のURLの末尾にある数字がテストプランのIDになる。
今回の私のテストプランだと**129932**。
![テストプランのIDEA.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121319/075ce00c-a854-07a2-4714-954742c3ee84.png)

上記が記載できて、リポジトリにpushできたらOKです。

### 3. 動かしてみる

試しに適当なテキストなり、何かを作成し、pushしてみましょう。
pushしたら、Autifyのテスト結果を見に行きましょう。
設定したテストプランが動いていたらOKです。
sonarcube API powershell

# Generate a token for a user with instance level "Adminster" permission and supply it to the $user variable
$user = 'TOKEN'
$pass = ''

$pair = "$($user):$($pass)"

$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))

$basicAuthValue = "Basic $encodedCreds"

$Headers = @{
    Authorization = $basicAuthValue
}

# Base URL of your SonarQube instance
$sonarQubeInstance = "http://localhost:9000"

# Existing identity provider, in this case "sonarqube" is used as the existing identity provider is LDAP
$currentExternalIdentityProvider = "sonarqube"

# Target identity provider, in this case "saml" is used as the existing identity provider is SAML
$targetExternalIdentityProvider = "saml"

## Get the first page of all users
$usersResponse = Invoke-RestMethod -Uri "$sonarQubeInstance/api/users/search?ps=500" -Headers $headers -Method GET
$users = $usersResponse.users

foreach($user in $users){

    $login = $user.login
    $isLocal = $user.local
    $email = $user.email
    $externalIdentity = $user.externalIdentity
    $externalProvider = $user.externalProvider

    # Assumes the external identity in SAML is the user's e-mail address
    $newExternalIdentity = $email

    # Prevents local users from being locked out of the SonarQube instance
    if($isLocal -eq $false){
        # Only migrate users of the exsiting identity provider
        if($externalProvider = $currentExternalIdentityProvider){
            Invoke-RestMethod -Uri "$sonarQubeInstance/api/users/update_identity_provider?login=$login&newExternalProvider=$targetExternalIdentityProvider&newExternalIdentity=$newExternalIdentity" -Headers $headers -Method POST
            Write-Output "Migrated user with login $login and external identity $externalIdentity from $currentExternalIdentityProvider to $targetExternalIdentityProvider with new external identity $newExternalIdentity"
        }
    }
}
Typescript勉強ノート #2_Narrowing編

## はじめに
Typescriptを使いこなせるようになるためにドキュメントを読んで勉強する。
typescript Documentation: https://www.typescriptlang.org/docs/handbook/intro.html
自分用なのであるていど把握できていると思う部分はスキップしていく。

今回は、ドキュメントのNarrowingを参考にしてまとめる。
https://www.typescriptlang.org/docs/handbook/2/narrowing.html


## typeof type guards
tyoeofを使って型を知ることができる。型よる絞り込みを行える。

```ts
const hoge = ( fuga : string | number ) => {
  if ( type of fuga === "string" ) {
     alert( "これはstringです！" )
     return;
  }
  alert( "これはnumberです！" )
  return; 
}
```

## The in operator narrowing
inを使うことでオブジェクトに指定したプロパティがあるがどうか判断することができる。
これによって絞り込みを行える。

```ts
type Fish = { swim: () => void, place: "sea" };
type Bird = { fly: () => void, place: "sky" };

const move = (animal: Fish | Bird) => {
  if("swim" in animal) {
    console.log(animal.place); // sea
  }
  console.log(animal.place); // sky
}
```

## The instanceof narrowing
指定したインスタンスであるかどうかを判断することができる。これによって絞り込みを行える。インスタンスとはクラスから生成したオブジェクトのこと。

```ts
class Animal {
  name: string;
  constructor(name) {
    this.name = name;
  }
}

const pet = new Animal('taro'); // petがインスタンス
 if (pet instanceof Animal) {
   alert("Animalです!");
 }
```

## Using type predicates
isを使って直接的な表現で型の制御ができる。
あまり実用するイメージがわかなかったが、こんなものがあるというのを知っておくためにメモ。

```ts
// ドキュメントよりそのまま引用
function isFish(pet: Fish | Bird): pet is Fish { // petがFishであるかどうか
  return (pet as Fish).swim !== undefined;
}

let pet = getSmallPet();
 
if (isFish(pet)) {
  pet.swim();
} else {
  pet.fly();
}
```

## おわり
次は、https://www.typescriptlang.org/docs/handbook/2/functions.html
Mongoose 6 で meow

## 認証エラーが出た

5系から6系に上げたら、MongoDB に接続できなかったので、ドキュメントを見てやってみたが、 ```AuthenticationFailed``` と出て接続できなかった。


## 解決策

```?authSource=admin``` を付ける。

```javascript
const mongoUrl = `mongodb://${user}:${password}@${host}:${port}/${dbname}?authSource=admin`;
mongoose.connect(mongoUrl);
```

## 猫がなくコード一式

```docker-compose.yml
version: "3.1"

services:
  mongo:
    container_name: mongo-dev
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASS}
      MONGO_INITDB_DATABASE: ${MONGO_DBNAME}
    ports:
      - 27017:27017
    volumes:
      - ./configdb:/data/configdb
      - mongoStore:/data/db

volumes:
  mongoStore:
    driver: local
```

```app.js
const mongoose = require('mongoose');

require('dotenv').config();
const mongoUrl = `mongodb://${process.env.MONGO_USER}:${process.env.MONGO_PASS}@localhost:27017/${process.env.MONGO_DBNAME}?authSource=admin`;

mongoose.connect(mongoUrl);

const Cat = mongoose.model('Cat', { name: String });

const kitty = new Cat({ name: 'Zildjian' });
kitty.save().then(() => console.log('meow'));
```

``` ".env"
MONGO_USER=xxx
MONGO_PASS=xxx
MONGO_DBNAME=xxx
```

```bash
$ npm init
$ yarn install mongoose dotenv
$ node app.js
meow
```
DockerでRails7プロジェクト作成する方法 Rails7 +  Mysql + esbuild + tailwind + pry-rails(デバッグツール)

# Dockerfile作成

まずはruby3とnodejsを使えるようにする

```
FROM ruby:3.0

ENV APP /app
RUN mkdir -p $APP && \
    apt-get update -y && \
    apt-get install default-mysql-client nodejs npm -y && \
    npm uninstall yarn -g && \
    npm install yarn -g -y
COPY . $APP/

WORKDIR $APP
```

# docker-compose.yml作成

```docker-compose.yml
version: '3'
services:
  app:
    restart: always
    build:
      context: .
    volumes:
      - .:/app
```

# イメージビルド実行

```
docker-compose build
```

# イメージビルドの確認

```
docker images
```

イメージが作成されていればOK

# dockerにRails7インストール

```
# コンテナに入る
docker-compose run app sh

# Rails7インストール
gem i -v 7.0 rails
```

# プロジェクト作成

ディレクトリ名を ``` . ``` とすると現在のディレクトリ直下にプロジェクト作成可能

```
rails new . -d mysql --javascript esbuild --css tailwind
```

これでプロジェクトが作成されればOK

# Procfile.devを修正

esbuildを使う場合は ```rails s``` の代わりに./bin/devを使うように変更されており、
./bin/devを実行すると、Procfile.devに記述されているコマンドが実行されます。

Procfile.devを以下のように修正 
docker上で ```./bin/dev``` した場合にrailsサーバにアクセスできるように　Procfile.devに -b 0.0.0.0 を追加

```
web: bin/rails server -b 0.0.0.0 -p 3000　
js: yarn build --watch
css: yarn build:css --watch

```
# mysqlを入れる
バージョンは8.0.27になっているが入れたいバージョンを入れる

docker-compose.ymlを以下に修正
※mysqlのDB情報はプロジェクト毎に修正してください

```
version: '3'
services:
  app:
    restart: always
    build:
      context: .
    volumes:
      - .:/app
    command: sh -c "rm -f tmp/pids/server.pid && ./bin/dev"
    stdin_open: true
    tty: true
    ports:
      - 3000:3000
    depends_on:
      - db
  db:
    restart: always
    image: mysql:8.0.27
    platform: linux/amd64
    environment:
      MYSQL_DATABASE: rails_seven_sample_db
      MYSQL_USER: rails_seven_user
      MYSQL_ROOT_PASSWORD: seven_pass
      MYSQL_PASSWORD: seven_pass
      TZ: 'Asia/Tokyo'
      MYSQL_ROOT_HOST: "%"
    tty: true
    command: mysqld --character-set-server=utf8mb4 --explicit_defaults_for_timestamp=true --default-authentication-plugin=mysql_native_password    
    ports:
      - 3306:3306
```

commandに```rm -f tmp/pids/server.pid```を追加しないとdocker compose upで２回目以降に上手く起動しないので注意。

### pry-railsを使う設定
今回は開発時のデバッグツールとして、pry-railsを使う想定にしているのでapp:に以下記述も必要

```
stdin_open: true
tty: true
```


# Dockerfileを修正

イメージが作成されるときにbundleを最新の状態にするため
Dockerfileにbundle installを追加しておく

```
FROM ruby:3.0

ENV APP /app
RUN mkdir -p $APP && \
    apt-get update -y && \
    apt-get install default-mysql-client nodejs npm -y && \
    npm uninstall yarn -g && \
    npm install yarn -g -y
COPY . $APP/

WORKDIR $APP

RUN bundle install
```

# config/database.ymlでDB設定

docker-compose.ymlの dbのところに書いた設定を記述

hostにはdocker-compose.ymlのサービス名はdbに修正。

```
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: rails_seven_user
  password: seven_pass
  host: db
  
development:
  <<: *default
  database: rails_seven_sample_db  
```

# イメージ再作成

いままでのイメージは削除して再ビルド

```
docker-compose build
```

# サーバ起動

```
docker-compose up
```

サーバが起動したら完了


# esbuildの設定

特に設定不要。application.jsにjsファイルをimportして使えばOK


# tailwindの設定

特に設定不要。viewにtailwindクラスを設定してあげればOK
bind9でのforwarders設定

# bind9での転送設定

軽くハマったのでメモしておきます。


## 環境
### バージョン

~~~bash
# named -V
BIND 9.16.1-Ubuntu (Stable Release) <id:d497c32>
~~~

### 構成

- 外部に社内DNSあり(172.16.0.2)
- private NW(192.168.4.0/24, Domain:hoge.localdomain)を作り、DNS(bind9)も建てる
- DNSはprivate NW内からhoge.localdomainのnodeを名前解決する
- hoge.localdomain以外の名前は社内DNSへforwardする

## 設定

/etc/bind/named.conf.optionsを修正する。  
  
デフォルト
~~~named.conf.options
options {
        directory "/var/cache/bind";
        dnssec-validation auto;
        listen-on-v6 { any; };
};
~~~

修正後
~~~named.conf.options
options {
        directory "/var/cache/bind";
        forwarders {
                172.16.0.2;
        };
        dnssec-validation no;
        allow-recursion {127.0.0.1; 192.168.4.0/24; };
        listen-on-v6 { any; };
};
~~~

環境次第でしょうが、私の利用環境ではforwardersで転送先DNSサーバを設定するほかに、dnssec-validationは明示的に"no"設定にしないとforwardされませんでした(コメントアウトではダメ)。
forwarders設定したのに外部ノードの解決がされない場合は試してみてください。
RLE形式（Run Length Encoding）のフルオンチェーンNFTのコントラクト解説

BlockBaseエンジニアのぽんたです。

誰でもフルオンチェーンNFTを作れるサービスをリリースしたところ、反響がありました。

https://twitter.com/suhara_ponta/status/1491404327336165384?s=20&t=UffVjdLc7gVgXKkY6ct6sg

この記事では、そのコントラクトの一部を解説しようと思います。
githubはこちらです。

https://github.com/ksuhara/pixel-onchained

## Nounsのピクセルアートの仕組み
このコントラクトはNounsDAOのコントラクトを参考に（ほぼコピーして）作っています。
NounsDAOについての解説はこちらの記事が詳しいのでオススメです！
https://ethereumnavi.com/2021/11/27/nouns-dao/

### 参考
- [Nounsの公式ドキュメント（コントラクト解説部分）](https://nouns.notion.site/Noun-Protocol-32e4f0bf74fe433e927e2ea35e52a507)
- [github](https://github.com/nounsDAO/nouns-monorepo)

### RLE (Run Length Encoding) について
NounsではRun Length Encoding（連長圧縮）という手法を採用してオンチェーンに書き込むピクセルアートのデータ量を圧縮しています。Wikipediaからの引用ですが、

> 連長圧縮では、ある連続したデータを、そのデータ一つ分と連続した長さで表現することで圧縮している。例えば、「A A A A A B B B B B B B B B A A A」は「A 5 B 9 A 3」と表せる。

ということです。Nounsは32×32のピクセルアートで、左上から数えて1色目が何マス続いて、2色目が何マス続いて、3色目が何マス続いたあとにまた1色目が何マス続いて... というようなデータと、1色目は黄色、2色目は青色という情報のカラーパレットをブロックチェーン上に書き込み、プログラム上で画像を生成しています。

### コントラクトを読み解く

まずNFTのコントラクトはこちらです。
[NounsToken.sol](https://github.com/nounsDAO/nouns-monorepo/blob/master/packages/nouns-contracts/contracts/NounsToken.sol)

```solidity:NounsToken.sol 
function tokenURI(uint256 tokenId) public view override returns (string memory) {
    require(_exists(tokenId), 'NounsToken: URI query for nonexistent token');
    return descriptor.tokenURI(tokenId, seeds[tokenId]);
}
```
seedsにはパーツごとにRLEエンコードしたピクセルアートの情報が入っています。

```solidity:INounsSeeder.sol
struct Seed {
    uint48 background;
    uint48 body;
    uint48 accessory;
    uint48 head;
    uint48 glasses;
}
```
これをNounsDescriptor.solとNFTDescriptor.solでレンダリングしています。

https://github.com/nounsDAO/nouns-monorepo/blob/master/packages/nouns-contracts/contracts/libs/NFTDescriptor.sol
↑ここではフルオンチェーンあるあるのbase64にエンコードしてmetadataを返しています。

一番重要なのがこの
[MultiPartRLEToSVG.sol](https://github.com/nounsDAO/nouns-monorepo/blob/master/packages/nouns-contracts/contracts/libs/MultiPartRLEToSVG.sol) というライブラリです。

_generateSVGRectsという関数にパーツの情報と背景色とカラーパレットを渡すと、SVGの<rect>を生成してstringで返してくれます。heightは10で固定、widthとx,y,fill(色)が可変になっています。

```solidity:MultiPartRLEToSVG.sol
function _getChunk(uint256 cursor, string[16] memory buffer) private pure returns (string memory) {
    string memory chunk;
    for (uint256 i = 0; i < cursor; i += 4) {
        chunk = string(
            abi.encodePacked(
                chunk,
                '<rect width="', buffer[i], '" height="10" x="', buffer[i + 1], '" y="', buffer[i + 2], '" fill="#', buffer[i + 3], '" />'
            )
        );
    }
    return chunk;
}
```

### Seedはどうやって作るのか

seedを作っているのはここです！

https://github.com/nounsDAO/nouns-monorepo/blob/master/packages/nouns-sdk/src/image/png-collection-encoder.ts

このテストのように32×32の透過pngを引数に入れて関数を実行すると、rleでエンコードされた値が返ってきます。
https://github.com/nounsDAO/nouns-monorepo/blob/04c96bd35e9dcebd983db37dfd59248b0c90284a/packages/nouns-sdk/test/png-collection-encoder.test.ts#L24


以上です！
Goで日本語曜日を含む日付format


## 参考元
以下記事にて記載されてますが、少しだけ改良？よくしたので共有。

https://qiita.com/Hiraku/items/863df86d3bbc5fb15964


改良点
・レシーバーにした

```golang
package main

import (
	"log"
	"strings"
	"time"
)

type Time struct {
	time.Time
}

const (
	yyyym   int = 1 // 2009年11月
	yyyymdw int = 2 // 2009年11月10日(火曜日)
)

func (t Time) GetJpnFormatTime(layout int) (jft string) {
	weekdayja := strings.NewReplacer(
		"Sun", "日",
		"Mon", "月",
		"Tue", "火",
		"Wed", "水",
		"Thu", "木",
		"Fri", "金",
		"Sat", "土",
	)

	var l string
	switch layout {
	case yyyym:
		l = "2006年1月" // 2009年11月
	case yyyymdw:
		l = "2006年1月2日(Mon曜日)" // 2009年11月10日(火曜日)
	}
	jft = weekdayja.Replace(t.Format(l))
	return jft
}

func main() {
	t := Time{}
	t.Time = time.Now()
	yyymmdd := t.GetJpnFormatTime(yyyym)
	log.Print(yyymmdd)
}
```

それだけ
TeamsにPerlからメッセージを送る

初めて 作成してみて困ったのでまとめです。

## コネクタの作成
送信したいチャネルの ･･･ を選択して、コネクタを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13840/d835e68f-1a07-5316-8b1d-6a103bd42a7c.png)
---
Incoming Webhookを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13840/0a4835bf-619e-79fc-11e4-3091ad188285.png)
---
必要な設定をして作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13840/f1833a36-d09f-f3bd-7c55-6b976c991a48.png)
---
作成後、変更が必要な場合は 構成済みを選択すると出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13840/eb14faa9-cbd4-c10e-4e96-bb90403692b7.png)
---
コネクタの作成は完了です。


## Perlのソース作成

```perl:test.cgi
use utf8;
use Time::Local;
use Encode qw/encode decode/;
use LWP::UserAgent;

# アドレス
my $url = 'https://';　# コネクタ作成で取得したアドレス。

#-------------------------------------------
# 	送信用JSONヘッダ
#-------------------------------------------
my $poststr = '{';
$poststr = $poststr . '   "type":"message",';
$poststr = $poststr . '   "attachments":[';
$poststr = $poststr . '      {';
$poststr = $poststr . '         "contentType":"application/vnd.microsoft.card.adaptive",';
$poststr = $poststr . '         "contentUrl":null,';
$poststr = $poststr . '         "content":{';　　　　　# ここから
$poststr = $poststr . '    "type": "AdaptiveCard",';
$poststr = $poststr . '    "version": "1.2",';
$poststr = $poststr . '  "body": [';
$poststr = $poststr . '        {';
$poststr = $poststr . '            "type": "TextBlock",';
$poststr = $poststr . '            "size": "Large",';
$poststr = $poststr . '            "weight": "Bolder",';
$poststr = $poststr . '            "text": "今日の予定"';
$poststr = $poststr . '        },';
$poststr = $poststr . '    ]';
$poststr = $poststr . '}';
$poststr = $poststr . '';
$poststr = $poststr . '      }';　　　　　　　　　　　　# ここまで
$poststr = $poststr . '   ]';
$poststr = $poststr . '}';
$poststrB = encode('UTF-8', $poststr);

my $ua = LWP::UserAgent->new;
$ua->default_header('Content-Type' => 'application/json; charset=utf-8 ');

my $res = $ua->post(
	$url,
	Content => $poststrB
);
```

Perlがよくわかってないので この段階に来るのにしばらくかかりました。

## デザイン
デザインするのには
https://adaptivecards.io/designer/
が いいかと思います。

変更する場合、ソース中の # ここから # ここまで の中を変更する感じになります。
Microsoft Graph APIを使ってTeamsの会話のログを取得する

ある日の弊社
人事さん「退職予定の人とTeamsのプライベートチャットでやり取りしてたんだけど」
　　ぼく「はぁ」
人事さん「退職するとアカウント消えるじゃない？だからログ取りたいの」
　　ぼく「そうですか」
人事さん「で、コピペするのが面倒なんだけど、サラッと取得できない？」
　　ぼく「（そんなん知らんな・・・）まぁ取り敢えずやってみます」

##### そんなぼくでも安心。そう、Microsoft Graph Explorerならね。
https://developer.microsoft.com/en-us/graph/graph-explorer

##### 結論から言うと

```
https://graph.microsoft.com/v1.0/chats/{chatID}/messages/
```

で取れました。Graph Explorerの左のpaneからログインして、アクセス許可を適切に与えれば取れます。

##### Q.プライベートチャットのIDが分からん！

Teamsのプライベートチャットにブラウザでアクセスして出るURLの```conversations/```の後ろがIDです。

##### ちなみに
Azureが特に制限無く使える人はAzureでアプリケーション連携するとかの方法もあるみたいですよ？知らんけど。弊社は無理なのでこうしました。
あとGraph Explorerでログイン中に出ているアクセストークンを使えばcurlとかでも情報を取得できます。

```
curl -H "Authorization: Bearer {tokenの値}" https://graph.microsoft.com/v1.0/me
```

##### 後日
人事さん「教えてもらった方法やったら途中で切れてたんだけど」
　　ぼく「!?」

どうも普通にやると$topが20程度に設定される様です。
https://docs.microsoft.com/ja-jp/graph/api/chat-list-messages?view=graph-rest-1.0&tabs=http

その場合、`@odata`の`nextLink`パラメータにURLが設定された状態でjsonが返ってくるようです。
めんどくさいのでjQuery使ってnextLinkが有る場合に再帰で全てのメッセージを取得する様なJS書きました。

```JavaScript
function getChatMessage(apiUrl, accessToken){
	$.ajax({
		url: apiUrl,
		headers:{'authorization':'Bearer '+ accessToken},
		type:'GET',
		dataType:'json',
		success: function (results) {
			if(results["@odata.nextLink"] !== undefined){
				getChatMessage(results["@odata.nextLink"],accessToken);
			}
			resultRenderer(results.value);
		},
		error: function (error) {
			console.log("Error in getting data: " + error);
		}
	});
}
function resultRenderer(values){
	//Do Something for Rendering Messages
}
```

ちなみに
```
chats/{chatID}/getAllMessages
```
とかは2022/4/11現在できませんでした。

以上
vs2010でassimp その2

#概要

vs2010でassimpやってみる。
fbxファイルをdaeファイルに変換してみる。






#サンプルコード


```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Reflection;
using Assimp;
using Assimp.Configs;
using Assimp.Unmanaged;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            String path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "untitled.fbx");
            String outputPath =  Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "fbx2.dae");
            AssimpContext importer = new AssimpContext();
            importer.ConvertFromFileToFile(path, outputPath, "collada");
            ExportDataBlob blob = importer.ConvertFromFileToBlob(path, "collada");
            Console.Write("ok ");
            var str = Console.ReadLine();
        }
    }
}

```


以上。
[nodejs] AWS IAM ユーザの secret_access_key から SES 用の SMTP パスワード を生成する

## TL;DR
 - SES で生成した IAM ユーザ ses-smtp-user.YYYYMMDD にポリシーを足して、他の用途に流用しようと考えたが、どうも上手くいかない。
 - 原因は、secret_access_key と SMTP 用のパスワードが異なるためだった。
 - secret_access_key から SMTP 用のパスワードは生成できるようだ。逆はだめ。
 - 公式のドキュメントには python 版が記されている  
   https://docs.aws.amazon.com/ses/latest/dg/smtp-credentials.html
 - nodejs 版を記しておく

```js
const crypto = require('crypto');

const smtp_credentials_generate = (secret_access_key, region) => {
    const version = 0x04;
    const kMessage = [
        '11111111', // date
        region,
        'ses', // service
        'aws4_request', // terminal
        'SendRawEmail', // message
    ].reduce(
        (secret, text) => crypto.createHmac('sha256', secret).update(text).digest(),
        'AWS4' + secret_access_key,
    );
    const signatureAndVersion = Buffer.concat([Buffer.from([version]), kMessage]);
    const smtpPassword = signatureAndVersion.toString('base64');

    return smtpPassword;
};
```

## 使い方
 - ログインする SES　の region を指定する

```js
const secret_access_key = 'xxxxxxxxxxxxxxxxxxxxxxxx';
const smtp_password = smtp_credentials_generate(secret_access_key, 'us-west-2');
console.log(smtp_password);
```

## 補足
 - ses が使えるようにポリシーを足しておくこと

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ses:SendRawEmail",
            "Resource": "*"
        }
    ]
}
```

## テスト
- テスト送信


```bash
#!/bin/bash

user='AKI... アクセスキーID'
pass='上記で生成したSMTP用のパスワード'

from='exabugs@hoge.com'
rcpt='exabugs@hoge.com'

cat > input.txt <<EOT
EHLO hoge.com
AUTH LOGIN
$(echo -n $user | openssl enc -base64)
$(echo -n $pass | openssl enc -base64)
MAIL FROM: $from
RCPT TO: $rcpt
DATA
From: $from
To: $rcpt
Subject: Amazon SES SMTP Test

This message was sent using the Amazon SES SMTP interface.
.
QUIT
EOT

openssl s_client -crlf -quiet -connect email-smtp.us-west-2.amazonaws.com:465 < input.txt
```
vistaでphotoshop その9

#概要

vistaでphotoshopやってみる。
キャンバス作って、マンデルブロー書いて、pngで出力やってみる。

#写真

![test8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ebc1f42a-1a4b-4452-507f-982df4e2dee5.png)


#サンプルコード

```
var v = [];
var pixelSize = 1;
var width = 300;
var height = 300;
var maxIterations = 100;
var mandelMin = -2.5;
var mandelMax = 2.5;
var infinity = 2;
var brightness;

function draw() {
	for (var y = 0; y < height; y++) 
	{
		for (var x = 0; x < width; x++) 
		{
			var map = function(num, in_min, in_max, out_min, out_max) {
				return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
			};
			var a = map(y, 0, height, mandelMin, mandelMax);
			var b = map(x, 0, width, mandelMin, mandelMax);
			var initialA = a;
			var initialB = b;
			var iterationCount = 0;
			while (iterationCount < maxIterations)
			{
				var aa = (a * a) - (b * b);
				var bb = (2 * a * b);
				a = aa + initialA;
				b = bb + initialB;
				var result = Math.abs(a + b);
				if (result >= infinity)
				{
					brightness = 255;
					break;
				}
				else
				{
					brightness = 0;
				}
				iterationCount++;
			}
			if (brightness == 0) v.push([x, y]);
		}
	}
}
draw();
preferences.rulerUnits = Units.PIXELS;
var docObj = app.documents.add(300, 300);
var myColor = new SolidColor();
myColor.rgb.red = myColor.rgb.green = myColor.rgb.blue = 0;
myColor.rgb.red = 255;
for (var i = 0; i < v.length; i++) 
{
	var x = v[i][0];
	var y = v[i][1];
	var selReg = [[x, y], [x + 1, y], [x + 1, y + 1], [x, y + 1], [x, y]];
	activeDocument.selection.select(selReg);
	activeDocument.selection.fill(myColor, ColorBlendMode.NORMAL, 100, false);
}
var pngOpt = new ExportOptionsSaveForWeb();
pngOpt.format = SaveDocumentType.PNG;
pngOpt.optimized = true;
pngOpt.interlaced = false;
pngOpt.PNG8 = false;
var filePath = new File("/Users/ore/test8.png");
app.activeDocument.exportDocument(filePath, ExportType.SAVEFORWEB, pngOpt);
alert("ok");



```



以上。