OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntu環境にModelSimをインストールする手順

Ubuntu環境にModelsimをインストールして実行できるようにする手順について紹介します。

Intelのサイトからインストール用のファイル(〜.runファイル)を入手したけれど「その先が分からない！！」

そんな方の参考になれば幸いです！

# インストール手順
ModelSimをUbuntuにインストールする手順を手短に三行で説明すると以下の通り！
1. .runファイルに実行権限を付けインストール
1. vsimを実行して怒られたらi386パッケージをインストール
1. .bashrcにパスを通したら、どこに居ても”vsim”でModelSimが起動できるぜ！

## 実行権限の付与
```bash
chmod +x ModelSimSetup-20.1.1.720-linux.run/
```

ダウンロードしたファイル（例：ModelSimSetup-20.1.1.720-linux.run）に実行権限を与えてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204268/62faeaf1-b797-07f4-e23c-a2943740ac31.png)

# インストーラーの実行
.run ファイルを実行するとインストーラのUIが起動します。　ご自身の用途に合わせてオプション設定してインストールを進めてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204268/5bcaf2ef-583d-03d4-5572-a566ffd56d50.png)

# 起動方法（ModelSimの実行ファイルは …/modelsim_ase/bin/vsim）

インストールディレクトリ配下のディレクトリ「modelsim_ase/bin」へ移動します。

ここにある「vsim」を叩くとModelSimが立ち上がります。


# 起動エラーの処置(i386パッケージのインストール)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204268/710d2c19-736b-feed-6754-e2a5c883830a.png)

つぎのコマンドを打って、i386パッケージをインストールしてください。

```bash
sudo apt-get install libxtst6:i386
```
これで「vsim」を打てばModelSimが起動します！　👏


# パスの設定方法(.bashrcの編集)

使い勝手が良くなるようにvsimへのパスを通して置きましょう！

nano　でも　gedit　でも　vi　でも構いませんので、「.bashrc」を開きます。

```bash
gedit ~/.bashrc
```
以下のように環境変数”PATH”に vsimのあるディレクトリパスを追記します。

```bash
PATH="$PATH":<vsimへのパス>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204268/790be1e4-a70e-b0c7-4f00-92587ccd90d3.png)

これでどこからでもターミナルから「vsim」を叩くことでModelSimが起動します。

**vsim の引数にプロジェクトファイル「〜.mpf」ファイルを渡すことでプロジェクトを読み込んだ状態で起動します。**
Javaのクラスのアクセス制御と複数クラスの宣言

Javaを基礎から復習していて、クラスについて理解が曖昧だった部分があったのでまとめておきます！
注意して書いているつもりですが、誤りがあればご指摘いただければと思います🙇‍♂️

## クラスに対するアクセス制御レベル
クラスに対するアクセス制御のレベルとしては２つのみです。(⚠️メンバに対しては４つある)  
以下にまとめます。  
| 名前 | 指定方法 | アクセス許可の範囲 |
| :---: | :---: | :---: |
| package private | 何も書かない | 自分と同じパッケージに属するクラス |
| public | public | どこからでも |  

なので、クラスを宣言するときは、publicをつけるか何もつけないかの2択になります。
クラスだけでなく、列挙型である`enum`を宣言するときも同じです。  
`private class Hoge`　とかやってjavacすると、
> 修飾子privateをここで使用することはできません  

って怒られます。

## １つのファイルに複数のクラスを宣言する
1つのファイルに複数のクラスを宣言するとき、大きく分けて２つ方法があります。
- 入れ子構造にせずに宣言する
- 入れ子構造にして宣言する  

まず入れ子構造にせずに宣言する方から。
### 入れ子構造にせずに宣言する
Javaのルールとして、
- １つのファイルに１つのpublicクラス
- ファイル名 = publicクラス名  

があります。  
なので、これを守っていれば１つのファイルに複数のクラスを宣言することができます。  

いくつか例を見ます。  

①  
以下のような、public classが１つ、package private class が複数ある`Hoge.java`はOKです。

```java:Hoge.java
public class Hoge {} // public class

class Fuga {} // package private class 

class Piyo {} // package private class
```
  
  
②  
以下のようなpublic class が１つのファイルに複数あるファイルはNGです。  
> クラス Fugaはpublicであり、ファイルFuga.javaで宣言する必要があります  

とエラーが出ます。  
publicなenumとpublicなclassを１つのファイルに同居させるのもNGです。 
```java:
public class Hoge {} // public class

public class Fuga {} // ⚠️public class２つめ！

class Piyo {} // package private class
```


③  
以下のようなpublic classが１つもなく、package private class が複数あるファイルは…**OKです！**  
しかも、ファイル名は自由に決められます！`Hoge.java`でも`Fuga.java`でも`Yakiniku.java`でもOKです！  
ただこのケースはあまり一般的ではないと思います！！
```java
class Hoge {} // package private class

class Fuga {} // package private class

class Piyo {} // package private class
```

### 入れ子構造にして宣言する
入れ子構造にして複数クラスを宣言する方法は３つあります。またクラスの内部に宣言されたクラスのことをインナークラスと呼びます。  
なので、インナークラスの種類が３つとも言えます。
- メンバクラス（staticあり、staticなし）
- ローカルクラス
- 匿名クラス  

インナークラスはあまり登場頻度が高くないらしいので特徴をちょろっと箇条書きしておくにとどめておきます。

#### メンバクラスの特徴
- クラスブロックの内部で宣言される
- staticありで宣言した場合
  - 外部クラスのstaticなメンバにのみアクセスできる
  - 利用するときは、 `Outer.Inner oi = new Outer.Inner();`
- staticなしで宣言した場合
  - 外部クラスのstaticでないメンバにもアクセスできる
  - 外部クラスのインスタンスを生成してからでないと利用できない
  - 利用するときは `Outer o = new Outer; Outer.Inner i = o.new Inner();`

#### ローカルクラスの特徴
- クラスの中のメソッドの中で宣言される(そのメソッド内でのみ利用可能)
- 利用するときは(宣言されたメソッド内で)`Inner i = new Inner();`

#### 匿名クラスの特徴
- 文の中で（式の一部として）宣言(と利用)される
- 利用するときは`Object o = new Object() { ... }`


## 終わり
以上です。 
何か誤りがあれば教えていただけると嬉しいです🙇‍♂️
Cypress と Jest の TypeScript での設定

# Cypress と Jest の TypeScript での設定

Jest が既存で存在するプロジェクトに Cypress を導入しようとしたところ型の問題で詰まりました。
以下のような以前見られていた問題となります。

https://github.com/cypress-io/cypress/issues/22059

結論としては Jest の TypeScript 設定を確認せずに進めようとしたことが問題だった模様です。

[TypeScript を使用する](https://jestjs.io/ja/docs/getting-started#typescript-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B)

Nuxt.js の設定により Jest が含まれる状態から進めたので以下の手順のみを追加で行っています。

追加のインストール

```bash
yarn add -D @types/jest ts-jest
```

- `tsconfig.json` の `types` に `@types/jest` を追加

https://github.com/ysKuga/nuxt-cypress-jest

こちらのリポジトリにて Cypress の設定がある状態で型を確認できることを確認しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/535925e4-258f-0c66-3b8b-4429e11875fa.png)

## tsconfig.json での指定でない場合

`global.d.ts` などで使用する型を指定している場合、
`tsconfig.json` の `types` 指定によりそれを上書きしてしまうっぽいので
どちらかに統一したほうが良い模様

```ts:global.d.ts
/// <reference types="@types/jest" />
```

## ESLint について

`cypress/tsconfig.json` を設置した際に `.eslintrc.js` でのエラーが発生する模様

```md
Parsing error: ESLint was configured to run on `<tsconfigRootDir>/cypress/support/auth-provider-commands/auth0.ts` using `parserOptions.project`: <tsconfigRootDir>/tsconfig.json
However, that TSConfig does not include this file. Either:
- Change ESLint's list of included files to not include this file
- Change that TSConfig to include this file
- Create a new TSConfig that includes this file and include it in your parserOptions.project
See the typescript-eslint docs for more info: https://typescript-eslint.io/linting/troubleshooting##i-get-errors-telling-me-eslint-was-configured-to-run--however-that-tsconfig-does-not--none-of-those-tsconfigs-include-this-fileeslint
```

これに対し `cypress/tsconfig.json` を使用するよう `cypress/.eslintrc.js` を設置し、
`parserOptions.tsconfigRootDir` を設定することで解決できる模様

```js:cypress/.eslintrc.js
module.exports = {
  extends: ['../.eslintrc.js'],
  parserOptions: {
    tsconfigRootDir: __dirname,
  },
}
```
PowerAutomate: *.xlsm ファイルを利用するなら、metadata を取得して ID を File に指定

# 背景
Office Script 全盛だったので、*.xlsm はほぼ使わなくなってたんですが、
使いたいって人がいたので、え？そのまま読み込めば？と思ったところ・・

- *.xlsm ファイルは、Excel コネクターの読み込み対象には出てこない

ってことに気付きました。

とはいえ、普通に読み込める方法があったので、記録と紹介

# 結論
1. ファイルID を取得してくる
1. ファイルID を利用して、Excel コネクターを使う

# 詳細
## [ファイル メタデータを取得: GetFileMetadata](https://learn.microsoft.com/ja-jp/connectors/sharepointonline/#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB-%E3%83%A1%E3%82%BF%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E5%8F%96%E5%BE%97) で、ファイルIDを取得
特に難しいこともなく、*.xlsm を選択すればOK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/0285b9c5-9dea-bba4-801d-5834cf84d503.png)


### OneDrive 用 [GetFileMetadata](https://learn.microsoft.com/en-US/connectors/onedriveforbusiness/#get-file-metadata)
使い方は一緒

## [テーブル内に存在する行を一覧表示する: List rows present in a table](https://learn.microsoft.com/ja-jp/connectors/excelonlinebusiness/#%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E5%86%85%E3%81%AB%E5%AD%98%E5%9C%A8%E3%81%99%E3%82%8B%E8%A1%8C%E3%82%92%E4%B8%80%E8%A6%A7%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B) を使った例

- 取得した Id を利用して File を指定する

```json: Set ID
outputs('Get_file_metadata_2')?['body/Id']
```

- テーブル名を指定：今回は固定で指定してるが、たぶんテーブル一覧からやれるんじゃないかな。（試しては無い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/26f7d66e-eda6-b214-e391-375463ff42df.png)

# あとがき

マクロ付きファイルにせずに、Office Script を使うことも検討しましょう

# keyword
how to read *.xlsm in Power Automate
草莽Erlang ── 09. モジュール

口で言うより行うことがErlang習得への近道と信じています。

https://qiita.com/mnishiguchi/items/9237780e849d80a85e11

## モジュールとは

Erlangのコードはモジュールに分割されています。モジュールは属性と関数の宣言の列で構成されます。属性も関数も最後にピリオド（`.`）を打ち終端を示します。

モジュールには関数を1つのファイルにまとめる役割があります。

モジュールで定義された関数は、`Module:Function(Arguments)` という形で呼び出します。

例としてioモジュールのformat/2関数を呼び出してみます。

```erlang
> io:format("~ts~n", ["闘魂"]).
闘魂
ok
```

https://www.erlang.org/doc/reference_manual/modules.html

https://learnyousomeerlang.com/modules#what-are-modules 

https://github.com/erlang/otp/blob/master/lib/stdlib/src/io.erl

## モジュールの作り方

1. `.erl`ファイルを作る
1. `.erl`ファイルの中で`module`属性にモジュール名をアトムで指定
1. `.erl`ファイルの中で`export`属性にエクスポートしたい関数を明示
1. `.erl`ファイルの中で関数を定義

モジュール名は`.erl`ファイルの名前と一致している必要があります。

```erlang
%% モジュール名を指定
-module(toukon).  
 
%% このモジュールからエクスポートしたい関数を明示              
-export([aisatsu/0, setsumei/0]). 

%% 関数を定義
aisatsu() -> 
  io:put_chars(["元気ですかーーーーッ！", $\n]).

setsumei() -> 
  io:put_chars(["「闘魂」とは己に打ち克ち、闘いを通じて自分の魂を磨くことである", $\n]).

```

試しに上述のモジュールを実際に作ってみます。

OSのシェルを開きます。

```bash
# 遊び用に一時ディレクトリを作成
$ mkdir tmp

# 一時ディレクトリの中に入る
$ cd tmp

# toukon.erlファイルを作ってtoukonモジュールを定義
$ cat <<EOF > ./toukon.erl
-module(toukon).  
-export([aisatsu/0, setsumei/0]). 

aisatsu() -> 
  io:put_chars(["元気ですかーーーーッ！", $\n]).

setsumei() -> 
  io:put_chars(["「闘魂」とは己に打ち克ち、闘いを通じて自分の魂を磨くことである", $\n]).
EOF

# toukon.erlファイルをコンパイル
$ erlc toukon.erl

# toukon.beamファイルが生成されたことを確認
$ ls
toukon.beam toukon.erl
```

Erlangシェルを開きます。

```erlang
$ erl
Erlang/OTP 25 [erts-13.1.3] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]

Eshell V13.1.3  (abort with ^G)
1> toukon:setsumei().
「闘魂」とは己に打ち克ち、闘いを通じて自分の魂を磨くことである
ok
2> toukon:aisatsu().
元気ですかーーーーッ！
ok
```

自作モジュールの関数がイゴきました [^1] :tada:

## Elixirにも挑戦したい

闘魂ElixirシリーズとElixir Schoolがオススメです。

https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e

https://elixirschool.com/ja

https://qiita.com/piacerex/items/09876caa1e17169ec5e1

[^1]: https://qiita.com/torifukukaiou/items/21df3c512308832c4a15#-%E3%82%A4%E3%82%B4%E3%81%8B%E3%81%99
data.frameを引数としてdata.frameを出力する関数をgroup毎に実行する方法


# 問題

まず、以下のようなdata.frameを作成します。
```R
set.seed(2)

df <- 
  tibble(
    group = c('A','A','A','A','B','B','B'),
    period = c(1,2,3,4,1,2,3),
    unif = runif(7)
  )
```

次に、data.frameを引数とし、data.frameを出力とする自作関数を作成します。この関数をgroup毎に実行し、 出力された結果を縦につなげたdata.frameを得たいとします。

```R
example_func <- function(df) {
  num_row <- nrow(df)
  df <- df %>% 
    dplyr::mutate(step = 1)
  for (i in 1:(num_row-1)) {
    df$step[i+1] <- (df$unif[i] > 0.5) + df$step[i]
  }
  return(df)
}
```

# 解決策

group_splitとmap_dfrを組み合わせることで求めた結果が得られます。

```R
df %>%
  dplyr::group_split(group) %>%
  purrr::map_dfr(example_func)

# A tibble: 7 × 4
# group period  unif  step
# <chr>  <dbl> <dbl> <dbl>
# 1 A          1 0.185     1
# 2 A          2 0.702     1
# 3 A          3 0.573     2
# 4 A          4 0.168     3
# 5 B          1 0.944     1
# 6 B          2 0.943     2
# 7 B          3 0.129     3
```

# 別解

また、以下の方法でも同様の結果が得られます。

```R
df %>%
  split(.$group) %>%
  purrr::map_dfr(example_func)
```

```R
df %>%
  dplyr::group_nest(group) %>%
  dplyr::mutate(data = purrr::map(data, example_func)) %>%
  tidyr::unnest(data)
```

```R
df %>%
  dplyr::group_by(group) %>%
  dplyr::group_modify(~example_func(.x))
```

# 謝辞

本内容は、[r-wakalang](https://qiita.com/uri/items/5583e91bb5301ed5a4ba)にて教えていただきました。heavywatalさん、atusyさんありがとうございました。
R Shiny-server を使って、パブリックなBIツールの構築は可能だろうか

# はじめに

shiny server を使って、パブリックなBIダッシュボードをプログラミングできないか、と考えた。ShinyServerってマルチユーザーアクセスできるのかどうか、が後々ポイントにもなりそうだが、まずは黙ってサーバー構築してみる。

# 方法

こちらの手順に従い、Rをセットアップする。
https://ciksiti.com/ja/chapters/11357-how-to-install-r-and-rstudio-on-ubuntu-22-04

・・・が、記事の一部が間違っているのではないだろうか。この記事はFocal（20.04）のリポジトリからインストールしているが、本稿執筆時点では Jammy（22.04）のリポジトリがすでに存在している。

https://cran.r-project.org/bin/linux/ubuntu/


よって、次のコマンドでレポジトリを追加するほうが、より適切。

```shell
＄sudo add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/"
```

次に Shiny と Shiny Server をインストールする。公式サイトを参考に。Ubuntu 18.04+ を選べばよい。
	
https://posit.co/download/shiny-server/

なお、合わせて R に rmarkdown パッケージをインストールしておく。

```shell
$ sudo su - -c "R -e \"install.packages(‘rmarkdown’, repos='https://cran.rstudio.com/')\""
```

### ShinyServerの設定

公式サイトの説明等で確認。重要なのは、サイトのポート番号（listen）とルートディレクトリ（site_dir）がどこであるか、ということ。
https://docs.posit.co/shiny-server/#default-configuration

```shell
$ cat /etc/shiny-server/shiny-server.conf
```

＜AWSを使っている場合＞
サイトの listen ポートをセキュリティグループの設定ルールでアクセス可能にする。（AWSのセキュリティルール入力方法に従うこと）


### 接続テスト

```
http://（EC2インスタンスのパブリックIPアドレス）:（サイトの listenポート番号）/
```

次のように表示されれば、構築成功。
![Screenshot from 2023-01-06 21-09-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/155f46a5-4083-ad8a-2d81-2860073d1485.png)



### shiny-appをサイトのルートディレクトリに設置する。

サイトのルートディレクトリ（site_dir）を開くと、サンプルがつぎのように配置されているはず。
![Screenshot from 2023-01-06 18-15-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/fa38a4e6-5151-dc67-4243-641a1ad24fa5.png)



index.html を読むと、その中で \<iframe src=”./sample-apps/hello”> および \<iframe src=”./sample-apps/rmd/”>で呼び出していることがわかる。src=””で呼び出せるのであれば、このリンクに直アクセスして画面が描画できるはず、とわかる。

そこで、サイトのルートディレクトリに 自分の shiny-app 用のフォルダを作ってファイルを配置し、そのリンクを公開すればよい。

shiny-app の作り方はここでは触れないが、ローカル環境など別環境で開発してファイルをアップロードするのが普通だろう。当然、開発環境で必要としたライブラリのインストールを構築したサーバーに行い、Rの動作環境を同じにしなければ、shiny-app は動作しない。この環境整備のほうが大変かもしれない。


# おわりに
shiny-server の構築を行った。shiny-serverのセットアップよりも、Rの動作環境構築のほうが面倒かもしれない。
しばらくshiny-serverへの複数ユーザー同時アクセス時の動作状況などをみながら、パブリックなBIツールの構築ができるかどうか検証してみることとする。
Specification of Default Error Tracer, AUTOSAR R22-11, CP, No.17(2)

Specification of Default Error Tracer, AUTOSAR R22-11, CP, No.17


AUTOSARが、2022年の版、R22-11公開しました。公開行事の模様は

AUTOSAR R22-11 Release Event 20221208

https://qiita.com/kaizen_nagoya/items/18471d0b340480fdcd42

下記は想定URLです。順次確認中です。

https://www.autosar.org/fileadmin/standards/classic/21-11/AUTOSAR_SWS_DefaultErrorTracer.pdf

間違っていたら、いいね　を押していただいて、コメント欄にご報告くださると幸いです。
編集リクエストが、構造的な変更をしている最中に、構造的な編集リクエストをしていただくと、
何をどう直したらいいかわからなくなってしまいます。自動修復ツールがつくれていません。ごめんなさい。

https://www.autosar.org/

文書は検索してダウンロードすることができます。
クラウドサービスにありがちな、あるのにないかのような検索結果が出ることがあります。

https://www.autosar.org/nc/document-search/


AUTOSAR R22-11 Classic Platform 一覧はこちら。

Classic Platform Release Overview, AUTOSAR R22-11, CP, No.0(2)

https://qiita.com/kaizen_nagoya/items/80636f4ca7c16501803b


AUTOSAR R22-11 マラソン

https://qiita.com/kaizen_nagoya/items/988aa405a6fdd794fe53



Qiitaの記事の一覧は作成中です。

AUTOSAR R22-11 一覧（２）

https://qiita.com/kaizen_nagoya/items/6b0615884e954c65fb43


# Abstract Platformとの関係
Log and Traceに統合するとよい。

 <この項は書きかけです。順次追記します。>
## 文書変更(Document Change) 
>Inconsistency between SWS_Det_00024 and SWS_Det_00009 solved. Also SWS_Det_00208 adapted.
 Clarification of APIs defined as "Synchronous /Asynchronous" (Det_ReportError)
 Editorial change

# 用語(terms)
no

## 英日単語帳
日本語は仮訳

T.B.D.

# 参考(reference)

[1] Glossary, AUTOSAR_TR_Glossary
https://www.autosar.org/fileadmin/standards/foundation/22-11/AUTOSAR_TR_Glossary.pdf
[2] General Specification of Basic Software Modules
AUTOSAR_SWS_BSWGeneral
[3] Requirements on Diagnostics
AUTOSAR_RS_Diagnostics
[4] General Requirements on Basic Software Modules
AUTOSAR_SRS_BSWGeneral


# 関連文書(Related document)

2023年1月　記事数一覧

https://qiita.com/kaizen_nagoya/items/78153968c5de76a7fd83

年末100記事を30点に仕上げる。

https://qiita.com/kaizen_nagoya/items/3ffdc82caee3a325d1d7

2023 書き初め

https://qiita.com/kaizen_nagoya/items/d494737e2627127b530d

「はじめてのCAN/CANFD 」 ベクタージャパン ＜エンジニア夏休み企画>【読書感想文】

https://qiita.com/kaizen_nagoya/items/1fee270be00ef90ca4ec


三方良し　Udemy 車載LAN入門講座 CAN通信編

https://qiita.com/kaizen_nagoya/items/bed038c52510fea72c0a


詳解 車載ネットワーク CAN, CAN FD, LIN, CXPI, Ethernetの仕組みと設計のために(1) 著者　 ＜エンジニア夏休み企画 読書感想文＞

https://qiita.com/kaizen_nagoya/items/e9971698a108c3dba794

詳解 車載ネットワーク CAN, CAN FD, LIN, CXPI, Ethernetの仕組みと設計のために(2)参考文献 ＜エンジニア夏休み企画>【読書感想文】

https://qiita.com/kaizen_nagoya/items/e156cbdd5fce9263776e

詳解 車載ネットワーク CAN、CAN FD、LIN、CXPI、Ethernetの仕組みと設計のために

https://qiita.com/kaizen_nagoya/items/44a9e6b0f5363b4a5b35


# 最新URL変更記事


Specification of Default Error Tracer, AUTOSAR 17, R22-11, CP 20230421

https://qiita.com/kaizen_nagoya/items/30c5b54ee8f6e311c5ca

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20230106
ver. 0.02 ありがとう追記 20230503

## 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
VueでHTML既存の<button>をラップするとき全てのpropsを再定義している人いる‥？

## React（tsx）でよくみる下記の記述
下位レベルのコンポーネント（アトミックデザインで言うatom）を定義するときいちいちpropsを再定義するのは面倒なので、もとの`<button>`が持っている属性の定義をそのまま使って、受け取ったpropsをそのままスプレッド演算子で再代入する方法。

```tsx
const MyButton = (props: JSX.IntrinsicElements['button']) => <button {...props} />
```

※コード補完が効いてるぞ、というスクリーンショット
![スクリーンショット 2023-01-06 20.19.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62209/5096c90e-dbba-e391-5878-998f301f8c42.png)

## これVueでもできないの？
と思って調べたんですが、下記のように「ButtonHTMLAttributes」など@vueのパッケージに含まれている`runtime-dom.d.ts`に定義されている型定義使うと同じように、面倒なpropsの再定義を回避することができそうです。

```vue
<template>
  <button class="button" v-bind="props"><slot></slot></button>
</template>

<script setup lang="ts">
import { ButtonHTMLAttributes } from 'vue'

interface Props extends ButtonHTMLAttributes {}
const props = defineProps<Props>()
</script>
```

※コード補完が効いてるぞ、というスクリーンショット
![スクリーンショット 2023-01-06 20.21.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62209/b23dc6e8-fc50-f4d7-18ae-4f9ed7d88cea.png)

ちなみに、空のinterfaceがeslintで勝手にtypeに変換されて、vueのコンパイラに怒られるという人は以下のように`@typescript-eslint/no-empty-interface`をeslintの設定に指定すると回避できました。

これが
```ts
interface Props extends ButtonHTMLAttributes {}
```

これに変換されて怒られる場合は
```ts
type Props = ButtonHTMLAttributes
```

eslintの設定をこう。
```.eslintrc.js
/** @type {import("eslint").Linter.Config} */
module.exports = {
  env: {
    browser: true,
    es2021: true
  },
  extends: [
    'plugin:vue/vue3-recommended',
    'eslint:recommended',
    '@vue/typescript/recommended',
    'prettier'
  ],
  parserOptions: {
    ecmaVersion: 12
  },
  plugins: ['vue', '@typescript-eslint'],
  rules: {
    'vue/multi-word-component-names': 'off',

// ここから
    '@typescript-eslint/no-empty-interface': [
      'error',
      {
        allowSingleExtends: true 
      }
    ]
// ここまで
  }
}

```

検証浅めなので、もっと良い方法あったらコメントで教えて下さい🎍
Collection.sortを勉強するその2

original classを定義してsortする。
デフォルトはsorteditemに定義したcompareToでソートされる。
comparatorを切り替えることによりsort順をコントロールできる

```java
public class Outer {
    public static void main(String[] args) {
        Outer o = new Outer();
        SortedItem s = o.new SortedItem("sato",1);
        List<SortedItem> sl = new ArrayList();
        sl.add(o.new SortedItem("aoyama",3));
        sl.add(o.new SortedItem("yamada",2));
        sl.add(o.new SortedItem("sato",1));
        Collections.sort(sl);   //name,ascending
        for(SortedItem si : sl) {
            System.out.println(si.name + ":" + si.price);
        }
        System.out.println("---------------------");
        Comparator c = o.new DecendingStringComparator();
        Collections.sort(sl,c);    //name,decending
        for(SortedItem si : sl) {
            System.out.println(si.name + ":" + si.price);
        }
        System.out.println("---------------------");
        c = o.new DecendingIntComparator();
        Collections.sort(sl,c);    //price,decending
        for(SortedItem si : sl) {
            System.out.println(si.name + ":" + si.price);
        }
    }
    class DecendingIntComparator implements Comparator<SortedItem> {
        @Override
        public int compare(SortedItem s1,SortedItem s2) {
            return new Integer(s2.price).compareTo(new Integer(s1.price));
        }
    }
    class DecendingStringComparator implements Comparator<SortedItem> {
        @Override
        public int compare(SortedItem s1,SortedItem s2) {
            return s2.name.compareTo(s1.name);
        }
    }
    class SortedItem implements Comparable<SortedItem> {
        String name;
        int price;
        SortedItem(String name, int price) {
            this.name = name;
            this.price = price;
        }
        @Override
        public int compareTo(SortedItem s) {
            return name.compareTo(s.name);
        }
    }
}
```
```
aoyama:3
sato:1
yamada:2
---------------------
yamada:2
sato:1
aoyama:3
---------------------
aoyama:3
yamada:2
sato:1
```
[Swift UI]共通化したテキストフィールドで値の変更を検知方法


結論から書くと共通化したテキストフィールドを呼んだ後にonChangeを追加すればokです。

## 共通化したテキストフィールド（コピペok）
 いらない部分もあるので必要ない方は後で消してください

    let bounds = UIScreen.main.bounds

    struct common_textField: View {
        
        @Binding var text: String
        
        var body: some View {
            
            // 表示
            TextField("入力してください", text: self.$text)
                .frame(maxWidth: bounds.width * 0.5, alignment: .leading)
                .font(.system(size: 36))
                .overlay(
                    RoundedRectangle(cornerSize: CGSize(width: 8.0, height: 8.0))
                        .stroke(Color.black, lineWidth: 1.0)
                        .padding(-8.0)
                )
            
        }
        
    }

呼び出し

    struct view1: View {

        @Binding var changeText:String
    
        common_textField(text: $changeText)
            //↓これ
            .onChange(of: changeText) { newValue in
                print("newValue = [\(newValue)]")
                changeText = newValue
            }
    }

あとは画面遷移のタイミングでchangeTextのデータを更新させればokです

共通化した部品の場合にうまく更新されないみたいなことが結構あり、自身の忘備録も兼ねて残しておきます。

共通化したTextFieldを作ったけど、値を検知して更新する方法がわからないという方はこちらを参考にしてもらえたら幸いです。
【ルール説明・basic】jinja

こちらの記事は [Ansible lint Advent Calendar 2022 カレンダー2](https://qiita.com/advent-calendar/2022/ansible-lint) 9日目の記事になります。


今回はルール [jinja](https://ansible-lint.readthedocs.io/rules/jinja/) について説明します。

### jinja

[jinja](https://ansible-lint.readthedocs.io/rules/jinja/) は Ansible コンテンツで jinja2 テンプレートが利用されている時にテンプレートの記述に違反がないか検証します。

現在のところ次のような項目が検証されます。

#### jinja[spacing]

`{{var_name|filter}}`のように変数と演算子（フィルタを含む）の間に空白がない場合、エラーが出力されます。Ansible では`{{ var_name | filter }}`のように記述します。

#### jinja[invalid]

`"{{ & }}"`のようにテンプレートの記述が妥当でない場合、エラーが出力されます。Ansible では`"{{ '&' }}"`のように記述します。

#### 問題のあるコード

```yaml
---
- name: Example playbook
  gather_facts: false
  hosts: all
  vars:
    bar: "{{ & }}" # <- 記号がエスケープされていない
    dict: "{name:Ansible, github:https://github.com/ansible/ansible}" # <- key と value の間にスペースがない
    foo: "{{ dict|dict2items(key_name='name', value_name='github') }}" # <- 演算子との間にスペースがない
  tasks:
    - name: Debug 1
      ansible.builtin.debug:
        var: bar

    - name: Debug 2
      ansible.builtin.debug:
        var: foo
```
#### 修正されたコード

```yaml
---
- name: Example playbook
  gather_facts: false
  hosts: all
  vars:
    bar: "{{ '&' }}" # <- 記号はエスケーブする
    dict: "{ name: Ansible, github: https://github.com/ansible/ansible }" # <- key と value の間にスペースを入れる
    foo: "{{ dict | dict2items(key_name='name', value_name='github') }}" # <- 演算子にスペースを入れる
  tasks:
    - name: Debug 1
      ansible.builtin.debug:
        var: bar

    - name: Debug 2
      ansible.builtin.debug:
        var: foo
```

### その他

現在のところ [jinja](https://ansible-lint.readthedocs.io/rules/jinja/) には次のような制限があります。

* 改行がある Jinja2 ブロックは検証されない。
* チルダを二項演算子として使用する Jinja2 ブロックは検証されない。`例 {{a ~ b }}`
* 数字にドット記法を使用する Jinja2 ブロックは検証されない。`例 {{ foo.0.bar }}`

[jinja](https://ansible-lint.readthedocs.io/rules/jinja/) により Ansible コンテンツでのテンプレートの記述の不具合をすべて検出できるわけではありません。しかし最終的には Ansible 実行時にエラーになり処理が停止されるためテンプレートの記述の不具合がコンテンツに存在しても問題にならないかとは思われます。

### 参考サイト

* [jinja — Ansible Lint Documentation](https://ansible-lint.readthedocs.io/rules/jinja/)
WAN種類

WANに携わることも増えてきたので自分なりの理解している範囲で解説。


## 広域イーサネット(閉域網)
通信事業者が独自に用意した閉域網を利用するL2、L3のVPN接続サービス。
複数の拠点をデータリンク層(レイヤ2)で接続する
閉域網上で通信するので限られた人しか利用しない為インターネットVPNよりは安全。


* 広域イーサネット(L2網)
キャリア側でデカいHUBを用意してあるので顧客の拠点接続用ルータで任意のIPを割り振って通信するやり方。
特徴として顧客が自由にipを決められる、その代わりキャリアが提供するserviceを利用できずL3網にL2網を接続する必要有り。


* 広域イーサネット(L3網)
キャリア側でルータを用意してあるイメージ、キャリアから送られてきたルータを設置して通信する。
申し込みの時に利用したいipを提示されるので選んだipが設定されたルータが顧客の所へ送付される。
顧客で自由にipを決められないが、キャリアが提供するserviceなど利用できる。



## インターネットVPN
公衆網を利用しL3（レイヤ3）の階層で通信をする。
(インターネット上でVPNを通し通信を行う)
VPNルータの用意と設定さえ出来れば容易に、また比較的安価に導入が実現するVPN。

インターネットへ接続する前に以下の2つが必要になる。
・pppoeかipoeでプロバイダーと認証を済ませる。
・動的か固定かでグローバルipを取得しておく。(L3で通信を行うので)

インターネットへの認証方式の説明。
・pppoe認証はプロバイダーからくる認証要求をユーザid、パスワードで返し認証してもらう。
・ipoe(ip over ethernet)はONUが不要でインターネットプロバイダーと直接接続する。

pppoe,ipoe認証時に動的にグローバルIPとDNSサーバIPを取得できる。
固定でグローバルIPを設定したいときはルータに設定が必要。


■PPPoE方式とIPoE方式の違い　参考サイト
https://www.nttpc.co.jp/column/network/pppoe_ipoe.html


## 専用線
拠点間を1本の専用ケーブルで接続する。
Collection.sortを勉強する

デフォルトはacending
acending以外にしたい場合、comparatorを作って渡す
sortは、comparatorのcompare結果が0以下となるように並び替える
昇順にしたければp1-p2、降順にしたければp2-p1
```java
    public static void main(String[] args) {
        List<Integer> li = new ArrayList();
        li.add(1);
        li.add(100);
        li.add(3);
        Comparator c = new Outer().new DecendingComparator();
        Collections.sort(li);
        for(Integer i:li) {
            System.out.println(i);
        }
        System.out.println("----------------------");
        Collections.sort(li, c);
        for(Integer i:li) {
            System.out.println(i);
        }
    }
    class DecendingComparator implements Comparator<Integer> {
        @Override
        public int compare(Integer i,Integer j) {
            return j - i;
        }
    }
```
```
1
3
100
----------------------
100
3
1
```
viで複数行末に文字を結合

viを使って、行末に文字を結合する方法です。
業務で数十万行あるテキストファイルに文字を結合する必要があり、
1時間ほど調べてしまったので忘れないためのメモです。


```Bash
$ cat sample.txt
1:sample text
2:sample text
3:sample text
4:sample text
5:sample text
```
上記の中身を以下の中身に書き換えます。
```Bash
$ cat sample.txt
1:sample text_hoge
2:sample text_hoge
3:sample text_hoge
4:sample text_hoge
5:sample text_hoge
```

viで対象ファイルを開いて、
```Bash
$ vi sample.txt
```
コマンドモードで
```
:%s/$/_hoge
```
と入力しエンターを押します。
処理的には、末尾を「_hoge」に置換です。

コマンドとしては以下です。
```
:%s/[置換前文字列]/[置換後文字列]
```

### おまけ
合計で200万行ほど行う必要ありましたが、
for文でぐるぐる回すより圧倒的に早かったです。
macで"illegal byte sequence"を出さない自作unzipコマンド

環境：MacOS Monterey, 2022

# Macのunzipコマンド
最近よく使うTeamsアプリですが、ファイルを一括ダウンロードするとzipファイルでダウンロードされます。それをTerminalなどで`unzip ~~.zip`すると、`illegal byte sequence`のエラーが出てしまいます。

ありがたいことに[それを解決するコマンド](https://qiita.com/koki_h/items/b82fbea16817e605bee5) の記事はあります。しかし毎度忘れる頃にこの問題に直面してしまい、ストック先ページを見に行くのがわりと手間です…

# 自作コマンド
長いコマンドはaliasにしてしまえ、と思いましたが引数を2つ入力するのも面倒です。
ということでzshの自作コマンドをちょこっと書き、zipファイル名だけ入力すればいい方式にしました。

```zsh:.zshrc
muz(){
    local fname

    # 引数は解凍したい ~~~.zip が入る
    fname=$1

    # 拡張子削除
    fname="${fname:r}"

    # 展開先作成
    eval "mkdir $fname"

    # 展開
    eval "ditto -V -x -k --sequesterRsrc --rsrc $1 $fname"
}
```
`muz AAA.zip`と入力するとAAAディレクトリが作成され、その中にzipの中身が展開されます。

muz = MacUnZipからつけたもので、コマンド名が衝突しないなら何でも良いです。
好きな名前をお付けください。

# ちょっと細かい話
これはファイル名に日本語が入っていると起きる問題です。
Windows系で圧縮したファイルをMacで解凍、またはその逆のパターンで発生します。
TeamsアプリのサーバサイドがAzure等のWindows系のサーバで、今回は手元がMacだから起こった問題ですね。

# 参考元
[Macのunzipで "illegal byte sequence "](https://qiita.com/koki_h/items/b82fbea16817e605bee5)

蛇足
シェルスクリプトは得意じゃないので、最近流行りのChatGPT君に監修してもらいました。
wordpressのCSS、JSのキャッシュクリアのオススメ

CSS、JSのキャッシュをクリアする方法は色々あります。CSSを更新したタイミングでのみ、キャッシュクリアする記述方法を見つけたのでメモします。

先にコードから
~~~ php
function theme_enqueue_styles() {
    wp_enqueue_style( 'style', get_stylesheet_directory_uri() . '/style/style.min.css', array(), date("ymdHis", filemtime( get_stylesheet_directory().'/style.css')) );
}
add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
~~~
仕組みは`wp_enqueue_style`関数の第４引数でバージョンを変化させます。対象のファイルの更新日を取得しているのでCSSのファイルを変えたタイミングで更新されるようになっています。
なので、そのページを再読み込みをしてもちゃんとキャッシュが残りますし、あとで、変更などもする必要もないです。
最初は日付でキャッシュクリアをしていました。(あとで消す必要がある)なので、もっと便利な関数を知れてよかったです。
#### 参考
https://creazy.net/2022/01/wordpress-style-css-cache-clear.html
Arrays.asListを勉強する

Arrays.asListは、配列をArrayListに変換
プリミティブ型(下記int)は配列として登録されるため要注意。
```java    
public static void main(String[] args) {
        List<String> sl = Arrays.asList("a","b");
        for(String s:sl) {
            System.out.println(s);
        }
        String[] strarray = {"c","d"};
        System.out.println("--------------------------");
        sl = Arrays.asList(strarray);
        for(String s:sl) {
            System.out.println(s);
        }
        System.out.println("--------------------------");
        List<Integer> li = Arrays.asList(1,2);
        for(Integer i:li) {
            System.out.println(i);
        }
        System.out.println("--------------------------");
        int[] intarray = {3,4};
        List<int[]> li2 = Arrays.asList(intarray);
        for(int[] i:li2) {
            System.out.println(i);
```
```
a
b
--------------------------
c
d
--------------------------
1
2
--------------------------
[I@15db9742
```
class typeを確認する。普通のArrayListではないことがわかる。
```java
        List<String> sl = Arrays.asList("a","b");
        System.out.println(sl.getClass());
```
```
class java.util.Arrays$ArrayList
```
asListで作成したListはaddできない
```java
    public static void main(String[] args) {
        List<String> sl = new ArrayList();
        sl.add("a");
        List<String> sl2 = Arrays.asList("a","b");
        sl2.add("a");              //ここで下記の例外が発生
    }
```
```
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at com.mycompany.mavenproject1.Outer.main(Outer.java:22)
```
秘密鍵・公開鍵の作成方法について　～ssh-keygen～

## 前提
秘密鍵・公開鍵の作り方には複数の方法がありますが、今回はssh-keygenを用いた方法で作成したのでご紹介します。

## コード全体
```
$ cd .ssh
$ssh-keygen -b 2048 -t rsa -f cloudshellkey

Generating public/private rsa key pair.
cloudshellkey already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in cloudshellkey.>Your public key has been saved in cloudshellkey.pub.
The key fingerprint is:
SHA256:u7kjkwEYeHGuWk0/nkPwA6IAtzSB/nLf0fk+VZI1B9s  
yo@ba7195bd66e9
The key's randomart image is:
+---[RSA 2048]----+
|.o*o.         .. |
|+oo=           =.|
|o.oo=         + E|
|.o.=.=       o . |
|. + ..* S .   o  |
| + o o.= +   .   |
|. o . =oo . .    |
|     .+o.o o     |
|       o+o...    |
+----[SHA256]-----+


$ls
cloudshellkey  cloudshellkey.pub  known_hosts


$cat cloudshellkey.pub

```
## 各コードの説明

①sshディレクトリに移動します。
``` 
$cd.ssh
```

②公開鍵・秘密鍵の生成を行います。
```
$ssh-keygen -b 2048 -t rsa -f cloudshellkey
```
-b 2048 　　　    2048ビットで作成する
-t RSA　　　　    RSA形式で暗号化することを表します
-f cloudshellkey どのファイルに出力するかを表します

鍵作成の際のオプションは任意です。以下の資料を参考にしました。
（参考）
https://atmarkit.itmedia.co.jp/ait/articles/1908/02/news015.html


③以下のコマンドでファイルをリスト化すると「cloudshellkey」「cloudshellkey.pub」が出来上がっていることがわかります。
```
$ls
cloudshellkey  cloudshellkey.pub  known_hosts
```

以下のコマンドでファイルの中身を見ることもできます
```
$cat cloudshellkey.pub
```



## 終わりに
秘密鍵・暗号鍵の説明を文字で読んだ時に難しいと感じていましたが、実際に手を動かしてみると意味が少しずつ分かってきました。
他にも鍵の生成方法はあるので時間がある時に試してみたいと思います。
TypeScript: satisfiesオペレーターの使い所のひとつとして

TypeScript 4.9で追加された`satisfies`オペレーターですが、「これ何に便利なの？」「使いみちある？」という声を聞くところですが、使いどころのひとつとして、あるかなと思ったのがあったので紹介したいと思います。

僕も`satisfies`オペレーター自体、使い所を模索しているところなので、いちアイディアとして読んでいただければと思います。そのうえで、感想やツッコミなど頂けると嬉しいです。

## JavaScriptで書いてた頃

一旦、TypeScriptは忘れて、JavaScriptを書いてた頃のマインドセットでコードを考えてみます。

たとえば、次のようなオブジェクトリテラルをJSONにしたいと考えたとします。

```js
{ id: 1, name: "foo" }
```

JavaScript脳ならこう書くと思います。

```js
const json = JSON.stringify({ id: 1, name: "foo" });
```

オブジェクトリテラルを`JSON.stringify`関数の引数に直接渡しています。

## TypeScriptではどう書きたいか

上のようなコードをTypeScriptで書くならどうするかを考えてみます。

上のJavaScriptコードのままでもいいのですが、`JSON.stringify`関数の引数の型は`any`型です。そのため、オブジェクトリテラルには型チェックが働いていません。TypeScriptで書いていると、型をどこかで注釈してあげたくなります。そのために、一旦はオブジェクトリテラルを変数にする必要があります。

```ts
// 一旦変数にする
const foo: Foo = { id: 1, name: "foo" };
//         ^^^型注釈
const json = JSON.stringify(foo);
```

ここで言いたいのは、JavaScriptでは、オブジェクトリテラルを引数に直接書くのが自然だったのに、TypeScriptになると一時的な変数を書くのが好ましくなる、というケースあるということです。TypeScriptでゼロから書いていると、気にもしないところかもしれませんが、JavaScriptをTypeScriptに移植する場合は、気になってくるところかもしれません。

## `satisfies`オペレーターの使いみち

TypeScript 4.9からは新たな道具として、`satisfies`オペレーターが追加されました。これをごくごく単純に説明すると、「型推論を活かしながら型を注釈できる機能」です。

話を戻して、上の話を振り返ると、JavaScript脳で書いたコードはこれでした。

```js
const json = JSON.stringify({ id: 1, name: "foo" });
```

これをTypeScriptに書き換えると、こうなりました。

```ts
const foo: Foo = { id: 1, name: "foo" };
const json = JSON.stringify(foo);
```

少ない書き換えではありますが、一時的な変数ができたりと、型チェックのために処理がちょっと変わっています。

処理を一切変えずに、型チェックしたいところですが、今まではできませんでした。

TypeScript 4.9からは、`satisfies`オペレーターを使うと、セマンティクスを変えずに型チェックを効かせられるようになります。次のコードが`satisfies`オペレーターを使った例です。

```js
const json = JSON.stringify({ id: 1, name: "foo" } satisfies Foo);
//                                                 ^^^^^^^^^^^^^
```

このようにJavaScript風の書き方を崩さずにTypeScriptで書けるところが、`satisfies`オペレーターの使いみちの1つとしてあるのではないかと思いました。「JavaScriptとTypeScriptは別言語だから、それぞれ都合に合わせた書き方をしたほうがいい」という考え方もあると思いますが、個人的には「TypeScriptはJavaScriptに型注釈を追加するための言語で、できる限りJavaScript wayで書きたい、型のために実行時の処理を歪めるのは可能なら避けたい」という思いがあるので、それを実現するひとつのアイディアとして本稿を投稿してみました。
[Python]webページのHTMLソースをディレクトリそのままにまとめてスクレイピング

## 背景
WebページのHTMLソースをディレクトリそのままにまとめてスクレイピングしたいと思いました

例えば、`https://www.hoge.com/huga/hoge/index.html`と`https://www.hoge.com/huga/index.html`のソースをまとめて取得するとき、ローカルにドメイン名をトップディレクトリとして
```
└── www.hoge.com
     └── huga 
          ├── hoge ── index.html
          └── index.html
```
の形で取得したいです

## 準備
基本のやり方は

https://qiita.com/akira-hagi/items/d0cfbc5af0806df00467

を踏襲します

取得したいページのURLのリストをテキストファイルとかで用意します
（実際は存在するURLでやりましたがぼかしています）
```txt:hoge.txt
https://www.hoge.com/huga/hoge/index.html
https://www.hoge.com/huga/index.html
```

## 実装
### ライブラリの読み込み
```python
import os
import time
import requests
```

※ベーシック認証があるサイトの場合は
```python
from requests.auth import HTTPBasicAuth
```
も追加

### 作成したテキストファイル読み込み
```python
with open('./hoge.txt') as f:
```

### 1行ずつ読み込み
```python
for url in f:
 url = url.rstrip('\n') 
```

### request投げる
```python
 res = requests.get(url=url,timeout=1.5)
```

※ベーシック認証があるサイトの場合
```python
 res = requests.get(url=url,auth=HTTPBasicAuth("ユーザー名","パスワード"),timeout=1.5)
```

### URLをパスに加工する
```python
 url = url.replace('https://','./')
```

### ファイル作成
```python
  if res.status_code == 404:
   filePath = os.path.dirname(url)
   if not os.path.exists(filePath):
    os.makedirs(filePath)

   with open(url,'w',encoding='UTF-8') as f:
    f.write('404')
   time.sleep(2)   
   continue

  filePath = os.path.dirname(url)
  if not os.path.exists(filePath):
   os.makedirs(filePath)

  with open(url,'w',encoding='UTF-8') as f:
   f.write(res.text)
  time.sleep(2)
```
加工したパスをもとにHTMLファイルを作成します
作成する前に、`os.path.exists`でパスのディレクトリの存在確認をして、
あればそのままHTMLファイル作成、なければディレクトリを作成してからHTMLファイル作成をしています
ステータスコードが404の場合はファイルに404と記載するようにします
作成が完了したらサーバーの負荷を抑えるため2秒待ちます

## 実装全体
```python
import os
import time
import requests

with open('./hoge.txt') as f:
 for url in f:
  url = url.rstrip('\n')       
  res = requests.get(url=url,timeout=1.5)
  url = url.replace('https://','./')
  if res.status_code == 404:
   filePath = os.path.dirname(url)
   if not os.path.exists(filePath):
    os.makedirs(filePath)

   with open(url,'w',encoding='UTF-8') as f:
    f.write('404')
   time.sleep(2)   
   continue

  filePath = os.path.dirname(url)
  if not os.path.exists(filePath):
   os.makedirs(filePath)

  with open(url,'w',encoding='UTF-8') as f:
   f.write(res.text)
  time.sleep(2)
```
## 出力結果
```
└── www.hoge.com
     └── huga 
          ├── hoge ── index.html
          └── index.html
```
できまスタ（実際は存在するURLでやりましたがぼかしています）
## 反省
### ファイル出力部分が冗長
関数にしたほうがスマートな気がします
```python
import os
import time
import requests

def mkfile(fileName, text):
    filePath = os.path.dirname(fileName)
    if not os.path.exists(filePath):
        os.makedirs(filePath)

    with open(fileName,'w',encoding='UTF-8') as f:
        f.write(text)

with open('./hoge.txt') as f:
 for url in f:
  url = url.rstrip('\n')       
  res = requests.get(url=url,timeout=1.5)
  url = url.replace('https://','./')
  if res.status_code == 404:
   mkfile(url,'404')
   time.sleep(2)    
   continue
  print(url)
  mkfile(url,res.text)
  time.sleep(2)
```

### sleep2秒もいらない
1.5か1くらいが適切だと思いました

## まとめ
URLのリストがあれば簡単なのでオススメです
C++ 文字列置換える

```cpp
#include <regex>
regex_replace(wordToReplace, std::regex(getFileName(i)), "");

// or

std::string ReplaceString(std::string line, std::string wordToReplace, std::string wordToReplaceWith) {
    size_t len = wordToReplace.length();
    size_t pos = line.find(wordToReplace);
    if (pos != std::string::npos)
        line.replace(pos, len, wordToReplaceWith);
    return line;
}
```
ベイズ推論における学習と予測

# <font color = 'forestgreen'>1.機械学習とベイズ推論における学習の違い</font> 
* 機械学習における学習 
  →モデルの持つパラメータの値をデータから決定すること。 

* ベイス推論における学習　
　→確率計算によってデータを観測した後のパラメータの<font color = 'Royalblue'>**事後分布**</font>を求めること。

# <font color = 'forestgreen'>2.ベイズ推論における学習</font> 
* ベイズ推論においてデータとパラメータの**同時分布**を考えることでデータを表現するモデルを構築する。
$$
p(D, \theta ) = p(D\ |\ \theta)p(\theta) \\\\
[D:観測データ, \theta:パラメータ]
$$
◆ $p(D\ |\ \theta)\cdots \theta $からどのような観測データが発生するかを記述する役割を持ち、<font color = 'Royal blue'>尤度関数</font>と呼ばれる。　
#### [更新方法] 
* 上の式において$p(\theta)$は事前分布とよばれ、この分布を観測データをもとに更新し事後分布を作成することをベイズ推論における学習としている。
また、この更新においてはベイズの定理が用いられる。 
$$
p(\theta \ |\ D) = \frac{p(D\ |\ \theta)p(\theta)}{p(D)}
$$
実際の計算においては$\theta$に関係ない関数である$p(D)$は無視し、比例関係をもとに計算する。
# <font color = 'forestgreen'>3.ベイズ推論における予測</font> 
ベイズ推論のおいては学習のみならず、学習されたパラメータの分布を用いて未観測のデータを予測し、知見を得たい場合がある。 
その場合、以下の式で表される<font color = 'Royalblue'>**予測分布**</font>を計算することで求めることができる。　
$$
p(x_\*\ |\ D) = \int p(x_\*\ |\ \theta)p(\theta\ |\ D)d\theta \\\\
[x_\*:未観測データ]
$$
# <font color = 'forestgreen'>4. まとめ</font>
ベイズ推論はパラメータそのものを学習によって求めるわけではなく、パラメータの不確実性を扱うものだということが分かりました。　
この後からは学習過程であったり予測過程のシミュレーションを作成して視覚的に理解を深めていこうと思います。
## <font color = 'forestgreen'>5. 参考資料</font>  
◆ [**機械学習スタートアップシリーズ ベイズ推論による機械学習入門**](https://bookclub.kodansha.co.jp/product?item=0000148222)
【ルール説明】internal-error

こちらの記事は [Ansible lint Advent Calendar 2022 カレンダー2](https://qiita.com/advent-calendar/2022/ansible-lint) 23日目の記事になります。

今回はルール [internal-error](https://ansible-lint.readthedocs.io/rules/internal-error/) について説明します。

### internal-error

[internal-error](https://ansible-lint.readthedocs.io/rules/internal-error/) は Ansible コンテンツに Ansible を実行できないようなエラーが含まれていた時にエラーを出力します。ただしほとんどの場合は Ansible 実行時に Ansible からより詳細なエラーメッセージが出力されます。

[internal-error](https://ansible-lint.readthedocs.io/rules/internal-error/)  をあえて利用する理由はないのですが無効化すべき場面があるとしたら`機能しないような Ansible コンテンツをテストファイルとして含み、それを修復するようなテストケースが書かれている時`と言うのがありそうです。

#### 問題のあるコード

以下の playbook に対して`ansible-playbook`コマンドを実行してもエラーになります。[internal-error](https://ansible-lint.readthedocs.io/rules/internal-error/) でもエラーが検証できると言う程度になりそうです。

```yaml
---
- name: Some title {{ # <- Ansible で jinja2 テンプレートの記述ミスと解釈されるためエラーになる
  hosts: localhost
  tasks: []
```

#### 修正されたコード

```yaml
---
- name: Some title
  hosts: localhost
  tasks: []
```

### 参考サイト

* [internal-error — Ansible Lint Documentation](https://ansible-lint.readthedocs.io/rules/internal-error/)
【AWS/お名前.com】お名前.comでドメイン取得＆AWSでSSL証明書発行し、既存ELBに紐づける方法（新規ELBパターン・サブドメイン発行パターンも）

# お名前.comでドメインを取得し、AWSでSSL証明書を発行、AWSの既存ELBで使用する方法

## 前提
* サーバーは顧客Aが利用しているステージング環境を利用する
* 「HTTPS:443ポート」からのトラフィックを受けるELBが既にある（SSL登録済）
    * ない場合は【補足1】に新規作成するパターンを記載しています
* 参考記事：[お名前.com管理のドメインをAWSのALBで使用する](https://shigeo-t.hatenablog.com/entry/2021/07/09/050000)

## 実施内容
1. お名前.com：ドメイン取得
2. AWS(ACM)：SSL証明書取得
3. お名前.com：DNSレコード設定
4. AWS(ELB)：既存ELBへのSSL追加

## 設定手順
### 1.　ドメイン取得手順
* お名前.comでドメイン取得
    * レンタルサーバーとのパックになっている契約もあります。今回は前提で記載したように顧客Aのサーバーを利用するので、ドメインのみの取得になりますが、サーバーも一緒に契約する場合は「[ドメインとレンタルサーバーを用意する](https://www.onamae.com/server/bepossible/ready/)」をよく読んでから契約されてください。

### 2.　SSL証明書取得手順
* 顧客AのAWSアカウントにログインし、AWS Certificate Manager（ACM）にアクセス
    * 「パブリック証明書のリクエスト」を選択し、「次へ」をクリック
    * ドメイン名に証明書を適用するドメイン名を入力、検証方法は「DNS 検証 - 推奨」を選択し、「リクエスト」をクリック
    * 「ステータス」が「検証保留中」になることを確認する

### 3.　DNSレコード設定手順
* AWS→EC2→ロードバランサー→対象のELBを選択し、DNSネームをコピーしておく
* お名前.comで「ドメインのDNS設定」→「DNSレコード設定」→「●入力」の下の以下項目を記入する
    * ホスト名：ドメイン名を入力
    * TYPE：CNAME　を選択（先に選ばないとホスト名が消えるので、これを先に選択するのが良い）
    * TTL：3600
    * VALUE：ELBでコピーしたDNSネームを貼り付ける。
* AWS→ACMにアクセス→ステータスが「発行済み」になるまで待機・更新されたを確認する（すぐ反映されると思います。15分以内には終わるらしい）

### 4.　既存ELBへのSSL追加手順
* AWS→EC2ダッシュボード→ロードバランサーを開いて対象のELBを選択し、リスナータブを開く
* 「HTTPS:443 listener」で新規タブを開き、「Certifiate(証明書)」タブをクリック
* 「Add certificate」→該当の証明書を選択して「Import certificate」で追加完了
    * ACM または IAM が管理していない証明書がある場合は、その証明書を ACM にインポートする必要がある。詳細は [公式ドキュメント](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/listener-update-certificates.html) 参照


# 補足１：ELBを新規作成する場合（DNSレコード設定時に紐づけるELBがない場合）
* SSL証明書取得時に「DNS 設定をファイルにエクスポート」からCSVファイルを出力しておき、DNSレコード設定でホスト名とVALUEにCSVの情報を入力してあげればOKです。ELBが作成できたら、DNSレコード設定でCNAMEにDNSネームを貼り付けます。
    * 参考記事：[お名前.com管理のドメインをAWSのALBで使用する](https://shigeo-t.hatenablog.com/entry/2021/07/09/050000)
*  新規作成したELBにSSL設定をしてあげる必要があります。上記は「追加」の場合の手順だったので、「設定」する場合は以下手順を参照してください。
    *  [公式ドキュメント](https://aws.amazon.com/jp/premiumsupport/knowledge-center/associate-acm-certificate-alb-nlb/) から引用↓

> [リスナーの追加] を選択します。
> [プロトコル] には、[HTTPS] を選択します。
> [ポート] には 443 を選択してください。
> [デフォルトアクション] で、[転送先] を選択し、ドロップダウンリストから ALB ターゲットグループを選択します。
> デフォルト SSL 証明書で、[ACM から (推奨)] を選択してから ACM 証明書を選択します。
> [保存] を選択します。


# 補足２：お名前.comでサブドメインを取得し、AWSの既存ELBで使用する方法
* 親ドメインはお名前ドットコムで取得済・ACMでSSL証明書も発行済でELBに紐づいている場合は、作業がだいぶ楽です。
    * EC2→Load balancers→対象のELBを選択→DNSネームをコピーしておく
    * お名前.com Naviにアクセス→ドメインのDNS設定→親ドメインを選択して「次へ」をクリック
    * DNSレコード設定をクリック→「●入力」のホスト名・TYPE・TTL・VALUEにそれぞれ以下を記入
        * ホスト名：希望のサブドメイン名
        * TYPE：CNAME　を選択（先に選ばないとホスト名が消えるので、これを先に選択するのが良い）
        * TTL：3600
        * VALUE：上記で取得したELBのDNSネームを貼り付ける
* 項目入力が終わったら「追加」→「確認画面へ進む」→「設定する」で完了
AWS CLIで現在のAWSアカウントIDを取得する

# 記事の目的
いろんなAWSアカウントの環境をプロファイルを切り替えながら操作していて、うっかり想定外の環境を操作していたなんてことが無いように、現在操作対象となっているAWSアカウントをこのコマンドでマメに確認する

# 前提
AWS CLIバージョン `1.10.18` 以降が使えること


# コマンド

```shell:shell
aws sts get-caller-identity
```

```json:実行結果の例
{
    "UserId": "XXXXXXXXXXXXXXXXXXXXXX",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/hoge"
}
```


## アカウントIDのみを取得したい場合
```shell:shell
aws sts get-caller-identity --query 'Account' --output text
``` 

```text:実行結果の例
123456789012
```
【github】公開リポジトリをforkし、プライベートリポジトリを作成する。

## はじめに
githubで公開中のリポジトリをforkして、privateリポジトリを作成する方法です。
GUIで操作すると、プライベートリポジトリにできないので、備忘録程度にやり方を記載しておきます。
ちなみに、GUIで操作すると下記画像のように、リポジトリをprivate化できません。
![スクリーンショット 2023-01-06 17.18.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/6b7c7fad-d570-5068-fca5-48ce3f280ae2.png)

## やり方
①あらかじめプライベートリポジトリを作成しておきます。
②gitコマンドでfork対象のリポジトリをローカルインストールします。
```git:forkしたいリポジトリをローカルインストール
git clone --bare https://github.com/ユーザ名/対象リポジトリ
```
③作成したプライベートリポジトリにPushする。
```git:
git push --mirror https://github.com/kouji0705/XXXX.git
```
これでOK！！
SpringBoot(Kotlin)でアクセスするとログイン画面が表示されてしまう

# はじめに

以下の書籍を行っていたときに遭遇したエラーについてまとめています

https://www.amazon.co.jp/-/en/%E7%AB%B9%E7%AB%AF-%E5%B0%9A%E4%BA%BA/dp/4297118599/ref=sr_1_5?crid=371ME1UOXSQHP&keywords=kotlin&qid=1672993415&sprefix=kotli%2Caps%2C196&sr=8-5

試行錯誤の段階で発生したもので、参考になる方は少数かとは思います

# 問題

書籍の一覧を取得するAPIを作成しました

```
watanabejin@watanabejin-Latitude-3520:~$ curl http://localhost:8080/book/list
{"book_list":[{"id":100,"title":"Kotlin","author":"taro","is_rental":false},{"id":200,"title":"Java","author":"judy","is_rental":false}]}
```

そしてこのAPIを使ってVue.jsから画面に表示しようとしたところ`CORSエラー`になりました

そして、CORSを解決しようと試行錯誤していると、いままでアクセスできていたAPIが何も表示しなくなりました

```
watanabejin@watanabejin-Latitude-3520:~$ curl http://localhost:8080/book/list
```

そこで、`localhost:8080/book/list`にブラウザでアクセスしたところ見覚えのないログイン画面が表示されるようになりました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/78f40d2a-6b0f-768b-b19e-6b179aafe5f7.png)

URLは`localhost:8080/login`なのでリダイレクトされてこのページに飛ばされてしまっているようで、それが原因でレスポンスが正しく帰ってきていないようです

ログイン画面を作成した記憶はなかったのでとても不思議でした
また作成したAPIを停止するとアクセスできなくなるため、何かしらKotlin側に問題がありそうでした

# 解決方法

以下の記事を読んで判明しました

https://www.tenohira.xyz/tech/spring-firstpage-issue1/

CORSを解決するために試行錯誤している段階で`spring-boot-starter-security`を依存関係に追加していたのが原因だったようです

```kotlin:build.gradle.kt
implementation('org.springframework.boot:spring-boot-starter-security')
```

依存関係から削除したところAPIが通常通り動きました

# CORSはどう解決したか

CORS問題ですが以下の記事を参考にしたところ正常に動きました

https://qiita.com/dhirabayashi/items/1c4e5c4bd5ef64992f70

```
@CrossOrigin
↓
@CrossOrigin(origins = ["http://localhost:8081"], allowCredentials = "true")
```

# おわりに

CORSの箇所はかなり時間がかかって調べていてもよくわからず途方に暮れていました
ダメ元でQiitaをちょくに検索したら見覚えのある本の記事があり、本当に助かりました
書籍のつまづいたポイントを記事にすることは価値があるんだなとあらためて思いました

# 参考

https://qiita.com/dhirabayashi/items/1c4e5c4bd5ef64992f70

https://www.tenohira.xyz/tech/spring-firstpage-issue1/
フォトリアルを目指して3DF Zephyr（試用版）を試してみた【スキル不足】

音声認識に関わらないビジュアル部分は、なるべく外からもってこようとしたのですが
どうしても建物がフォトリアルな素材が見つかりません。

ないなら作ってしまえ、と思い、3DF Zephyr（試用版）を試してみました。

https://www.opt-techno.com/opt-zephyr/

メールで申請したところ、試用版のライセンスキーがわずか1時間未満で送られてきました。
感謝です。

## 要したもの
今回用意したのは、近所にある小休憩できるところでした。
近くをウロウロしつつ、枚数は約260枚ほど撮影。

使ったのはiPhoneXです。

![IMG_2899.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3009807/2ce51a3d-3892-df06-fd13-4e35a0b4e2c5.jpeg)


今日、この小屋ずっとウロウロしてたから変質者に間違われていたかもしれませんが
基本的に家にこもっている人間なので大丈夫でしょう。多分。

## 取り込んでみる
ソフトをDL後、起動するとライセンスキーを求められるのでポチポチ追加します。
そして撮影したファイルを指定し、後はソフトへお任せしました。

![bb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3009807/da43f3b0-d6ec-5edd-fd1a-352e247b4c70.png)

## 結果
自分の撮影技術とiPhoneXじゃ色々足りなかったようで、使えるレベルにはできませんでした...。

![cc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3009807/4075ec3c-b8c6-643b-b72f-25b6a3df6e92.png)

撮影者の腕もさることながら、恐らく枚数もカメラ性能も必要そうです。
それとも枚数が足りなかったんだろうか（悩

しかし、すごく簡単に生成ができるので慣れたら楽しく作品が作れそうな気がします。
（実際ものすごく楽しかったです）
【Xcode】Previewを更新する

# はじめに
iOS13からだとPreviewが使用できるので、Previewを使用して開発することがあると思います。
Previewを使用する上で知っておかないと不便なコマンドショートカットがあるので紹介します。

# ツールバーから使用する
① 「Editor」を選択します
② 「Canvas」を選択します
③ 「Refresh Canvas」を選択します
![スクリーンショット 2023-01-06 16.55.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d47de142-996e-e921-d700-4fe8933ff4b8.png)

しかし毎回これをやるのは面倒なのでキーボードショートカットを覚えましょう。

# キーボードショートカット
`command` + `option` + `p`

# おわり
これを使用しないと快適にPreviewを使えないと思います。
ECR のレジストリとリポジトリの違い

# レジストリとリポジトリって何が違うの？
AWS の学習を進めていて ECR についての情報を集めていると出てくる単語
* レジストリ
* リポジトリ

最初は同じ意味なのかと、表記がブレているのかと思っていたが違った。

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/what-is-ecr.html

上記のドキュメントを見ると以下のように説明がある

> レジストリ
Amazon ECR プライベートレジストリは各 AWS アカウントに 1 つ提供され、レジストリ内に 1 つ、または複数のイメージリポジトリを作成して、それらにイメージを保存することができます。

> リポジトリ
Amazon ECR リポジトリには、Docker イメージ、Open Container Initiative (OCI) イメージ、および OCI 互換アーティファクトが含まれます。

つまりこんな感じ

AWS アカウント
└ レジストリ (1個)
　　└ リポジトリ (複数)
　　　　└ イメージ (複数)

ちなみにレジストリにはプライベートレジストリとパブリックレジストリが存在するが、パブリックレジストリは通常使用しない。

名前が似ていて紛らわしいが、概念を知ってから読むとそれが当たり前のように感じるので不思議。
頭がこんがらがって検索する、自分みたいな初級者が他にもいると思うので情報を残しておきました。
Hasura・GraphQLについて勉強してみた

年始に時間を取れたので、Hasura・GraphQLについて学んでみました。
Hasuraは初見、GraphQLは業務(AWS・AppSync)で少し使った程度で、
勉強を進めるにあたって、Next.jsのアプリケーションを通じてCRUDなどを体感してみたものになります。

## 勉強に使ったアプリ構成
- アプリケーション
  - TypeScript: 4.2.4
  - React: 17.0.2
  - Next: 11.1.2
  - graphql: 15.5.0
  - apollo/client: 3.3.15
- バックエンド・DBサーバ
  - Hasura
- デプロイサーバ
  - Vercel

## 勉強で作成したもの
簡単な顧客管理機能みたいなものを作成しました。
（ユーザーの追加・削除・ユーザー名変更・詳細表示など）

## Hasuraってなに？
[Hasura](https://hasura.io/)とはGraphQLサーバーをコードレスで準備できるサービスみたいです。
またロールを使ってPermission機能も備わっています。
データソース自体はPostgreSQLのようです。
[Githubのスター数推移](https://star-history.com/#hasura/graphql-engine)からみても注目度の高いOSSだと思っています。

## Hasuraは何がいいの？
### サーバの準備の負担がかなり少ない
大規模開発のようなサービスなら、大変な部分もあるかもしれませんが、個人開発（もしくは小・中規模くらいのもの）であればすぐサーバの準備ができます。
私はGithubのアカウントで連携しすぐに使用することができました。
また、データソースとして PostgreSQLを使用していることもあり、RDBMSのような感覚で使用できるので、導入時の学習コストもかなり要らなかった印象です。

### GraphQLサーバーをすぐに使用できる
上の内容と重複している部分もありますが、Tableを定義するだけでクエリも含めてHasuraが用意してくれるので、サーバ処理をほとんど実装せずに使用可能です。

### 集計クエリやページングなどのクエリも用意してくれる
これ結構驚いたのですが、定義したテーブル情報からpkでの取得用のクエリや集計用のクエリを
Hasura側で自動で生成してくれます。
項目の変更等はGUIでぽちぽちいじるだけでできてしまいます。
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486966/14f0f110-65e7-5b29-6806-94f60918ca59.png">


```
query lookupCustomerOrder {
  users_aggregate(distinct_on: group_id) {
    aggregate {
      count
    }
  }
}
```
```
{
  "data": {
    "users_aggregate": {
      "aggregate": {
        "count": 3
      }
    }
  }
}
```
またCRUDに関しても簡単に生成してくれます。
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486966/814b4d8a-9ca7-4d90-3821-996a65f084c9.png">
```
mutation MyMutation {
  insert_users_one(object: {name: "testです"}) {
    id
  }
}
```
```
{
  "data": {
    "insert_users_one": {
      "id": "fabb1ca3-5f5b-4784-86d3-bf58153951b2"
    }
  }
}
```
APIの実装が不要などころか、定義を作るだけですぐにデータのやり取りができそうな感じです。

### ロールでの制御をかけることができる
管理者・編集者・参照者などのロールを作った場合でも、各ロールごとに機能の権限を
Hasura側で制御をかけることができます。
<img width="650" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486966/ccec2a7a-6290-1640-9624-2a99c42f5d93.png">
また自分のIDのデータのみしか表示させない、みたいな制御もかけられるようです。（便利！）

## 総括
個人開発をする際のDBはFirebaseのfirestoreを使うことが多いのですが、NoSQLは便利なことも多いのですが、RDBで普段開発している自分としてはDBはこっちの方が便利な印象でした。
データ取得周りをほとんどになってくれるのも好印象です。
認証基盤はFirebaseのAuth、DBはHasuraで作るのもありだなぁと勉強になりました。
記載内容に不備ありましたらご指摘ください。
お読みいただきありがとうございました！！