OmniAICreator/Qiita-1.07M huggingface dataset:
QuantLibの固定利付債のクーポン計算方法を確認する

`ql.FixedRateBond`オブジェクトがどのようにクーポンを計算するかを確認する。

```python:固定利付債を生成
import QuantLib as ql

schedule = ql.Schedule(
    ql.Date(15, 5, 2007),       # effective date    : 開始日
    ql.Date(15, 5, 2027),       # termination date  : 終了日  
    ql.Period(0, ql.Months),    # tenor             : 間隔（0は終了日のみ）
    ql.Japan(),                 # calendar          : 祝休日
    ql.Unadjusted,              # convention        : 非営業日調整
    ql.Unadjusted,              # termination date convention : 終了日の非営業日調整
    ql.DateGeneration.Backward, # rule              : 日付生成のルール
    False,                      # end_of_month      : 開始日が月末の場合に、終了日以外の利払日を月末とするか否か
)

fixed_rate_bond = ql.FixedRateBond(
    3,                  # settlement days   : 決済期間
    100.0,              # face amount       : 額面 
    schedule,           # schedule          : 利払日
    [0.015],            # coupon            : 利率（%単位ではなく少数単位）
    ql.Actual365Fixed() # day counter       : 日数計算方法
)
```

```python:キャッシュフローを確認
for cf in fixed_rate_bond.cashflows():
    print(cf.date(), cf.amount())

# May 17th, 2027 30.02054794520548
# May 17th, 2027 100.0
```

```python:クーポン計算方法を確認
cf = fixed_rate_bond.cashflows()[0]
cf: ql.FixedRateCoupon = ql.as_fixed_rate_coupon(cf)

assert cf.amount() == cf.rate() * cf.accrualPeriod() * cf.nominal()  # 30.02054794520548
assert cf.rate() == 0.03
assert cf.accrualPeriod() == cf.dayCounter().yearFraction(cf.accrualStartDate(), cf.accrualEndDate())  # 20.013698630136986
assert cf.nominal() == fixed_rate_bond.notional() # 100
assert cf.accrualDays() == cf.accrualEndDate() - cf.accrualStartDate() #7305
```
jbuilderでjson.statusとして返却しようとするとrspecでhttp response statusが0で返却された問題

原因は分かっていないが、rails, grape, jbuilderを利用している際にresponse.statusだけ0になってしまう問題に直面した。
jsonのresponse等は問題無かった。

```ruby
# grape api

class Api::V1::Order < Grape::API
  get "/status", jbuilder: "v1/order/status.jbuilder" do
    @status = true
  end
end
```

```ruby: v1/order/status.jbuilder
json.status @status
```

```ruby: order_spec.rb
describe Api::V1::Order, type: :request do
  describe '#status' do
    subject { get "v1/order/status", header: header }
    let(:header) { ... }
    it 'true' do
      subject
      # ここが0で返却される
      expect(response.status).to eq 200
      # responseのjsonはきちんと返却される
      expect(JSON.parse(response.body)[:status]).to be_truthy
    end
  end
end
```

他の問題無く動いているコードと比較してみた所、jbuilderで`json.status`という名前を使っている場合のみresponse.statusが0で返却される事がわかった。
なので、jbuilderでstatusという単語を使わないようにして解決。
問題自体は解消したが、jbuilderやgrape等何かしらの予約語に引っかかってダメなのか、rspec側なのか、問題の切り分けが調べても分からなかったのでもやもやしたままである。
statusというよくある単語で問題になるのなら調べたらすぐ出ると思うが...
Keychron K9 Proのレビュー VIAの設定等

## 購入したモデル
- [Keychron K9 Pro QMK/VIA Wireless Custom Mechanical Keyboard](https://keychron.jp/products/keychron-k9-pro-qmk-via-%E3%83%AF%E3%82%A4%E3%83%A4%E3%83%AC%E3%82%B9-%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0-%E3%83%A1%E3%82%AB%E3%83%8B%E3%82%AB%E3%83%AB%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89-us-ansi-%E9%85%8D%E5%88%97?variant=42699588534443)
- RGB Backlight
- Low Profile Gateron Mechanical (Hot-Swappable)
- Red Switch

## 選定基準
- ThinkPad TrackPoint Keyboard を使ってきたので, それにある程度近い性能のものが欲しかった.
  - 小さい (305.5 x 164 mm)
  - 薄い (13.7 mm)
  - 軽い (0.44 kg)
  - 84キー (テンキーレス)
  - キーストロークは浅め (1.8 mm)
- いわゆる高級キーボードは持ち運ぶことを考えていないらしく, あまり薄さや小ささは考慮されていない商品の方が多い.
- HHKB 等は高さが 40mm 程度で, 多分リストレストが必要になる.
  - その上前後で厚さがかなり違うので, それも持ち運ぶという点においては望ましいとは言えない.

## 良い点
- 小さい (287 x 97.5 mm)
  - ThinkPad TrackPoint Keyboard よりもかなり小さい.
- 薄い (23.5 mm)
  - メカニカルキーボードの中では薄い方ではある.
  - リストレストはなくてもなんとかなる.
- 61キー (60%)
  - これのワンサイズ上の K6 Pro (65%) は K9 Pro の右側にカーソルキーを追加して, 右下に矢印キーを埋め込んだものある.
  - この辺のキーはあまり使わない上に ANSI キーボードレイアウトを大きく乱すので私は好まない.
- 軽い (0.41 kg)
- キーストロークは 3 mmぐらい.
- Hot-Swappable
  - キースイッチを部分的に変更することは考えていないが, 長寿命化のためにこちらを選択した.
  - ユーザーが求めるのは swappable であることで, それが hot か cold かはどうでもいいとは思うが, なぜか hot が強調されている.
- コンフィギュラビリティ
  - VIAがここまで自由度の高いソフトウェアだと思っていなかった.
  - ポインタの操作等を含む, 一般的なコンピュータで可能なほぼあらゆる操作を設定できる.
  - 後述
- オープンソース
  - ファームウェアのソースコードが公開されているので, いざとなれば書き換えることができる.

## 良くも悪くもない点
- RGB Backlight
  - エフェクトモードの他に, HSV 色空間における Saturation, Hue, Brightness を調整できるようになっている.
  - 白一色にするためには, Saturation を下げることで実現するっぽいが, そんなにきれいな白色にはならない気がする.

## 良くない点
- Bluetoothのホスト切り替えのLEDが固定されている.
  - Bluetoothのホスト切り替えのキーはVIAを使って設定可能だが, LEDはそれに追従しない.
  - また, キーにも刻印が入っており, 当然これも変えられない.
  - (そもそも技適の通っていないBluetoothを使ってはいけない)
  
## このキーボードが悪いわけではないが, 良くない点
- 技適に通っていない.
  - SUPER KOPEK では, この製品は扱っていない.
  - よって技適が通っていないので, Bluetooth は使ってはいけない.
- VIA は Debian で使えない.
  - Mac か Windows で設定する必要があった.
  
## VIAの設定
- VIAは非常に自由度が高く強力なキーマップ変更ソフトウェアである.
  - このような60%程度以下のキーボードは, キーマップを変更するソフトウェアの使用を前提としているように思える.
- レイヤーは 0,1,2,3,4 の 5 つあり, 1 が Windows モードのデフォルト, fn を押すと 3, fn1 で 4 になる.
  - Mac モードでは 0 がデフォルト, fn で 2, fn1 で 4 (4 は共通)
- レイヤー 0, 1
  - caps を ctrl に変更
  - 最下段を, fn1, ctrl (command), alt (option), space, fn, alt (option), super (command), ctrlにする.
  - Esc を tilde にする.
	- UNIX では tilde の方が打つ機会が多い.
- レイヤー 2, 3
  - wasd でマウスポインタの位置を操作.
  - jkl でマウスボタンを操作.
  - np でスクロール.
  - 残ったところに RGB の操作と Bluetooth の操作を割り当て.
- レイヤー 4
  - 矢印キー, カーソルキーを Emacs と同じ配置にする.
  - 矢印キーを npfb
  - home, end, del を a, e, d
- 設定ファイル
    - https://github.com/void-hoge/viakeymaps/blob/main/keychron_k9_pro_ansi_rgb.layout.json

## 調査中の項目
- ファームウェアのビルド環境
  - Bluetooth のペアリングの LED は RGB を流用しているのではないかと思って, ファームウェアのソースコードを変更して対応しようと思った.
    - おそらく, [ここ](https://github.com/Keychron/qmk_firmware/blob/00af20f690b66b11c3c00826b5193a306b611ec4/keyboards/keychron/k9_pro/config.h#L59)で設定されている.
  - しかし, clone してウェブサイトから参照でききるコミットまでロールバックしてもうまく行かなかった.
  - ビルド環境が違う可能性があるので調査中.

## その他
- 公式サイトから注文すると中国からの輸入になるので, 注文から届くまでは1週間ほどかかった.
- なんとなくキャリングケースも買ったが, 正直これはあまりよくない.
  - 無駄に大きいし, 妙にギチギチで取り出しづらいので, よほど激しく動かすということでない限りはポーチで良いように思う.
MeCabのインストールで躓いた話(公式ドキュメントは大事)

# TL;DR
MeCabのインストール時、辞書がなくて使えなかった話です。
公式ドキュメントの重要性を理解していなかったために解決に時間がかかったという教訓もあります。

# 背景
アルバイトの研修で、Google Colab上で[自然言語処理100本ノック](https://nlp100.github.io/ja/)の4章を解いていた際、MeCabのインストールで躓いた。

# 困っていたこと
`mecab-python3`をインポートして使う際、`RunTimeError`が出る。

```python
import MeCab

tagger = MeCab.Tagger()
tagger.parse("私は自然言語処理を勉強している。")
```

```
RuntimeError: 
----------------------------------------------------------

Failed initializing MeCab. Please see the README for possible solutions:

    https://github.com/SamuraiT/mecab-python3#common-issues

If you are still having trouble, please file an issue here, and include the
ERROR DETAILS below:

    https://github.com/SamuraiT/mecab-python3/issues

issueを英語で書く必要はありません。

------------------- ERROR DETAILS ------------------------
arguments: 
default dictionary path: None
[ifs] no such file or directory: /usr/local/lib/mecab/dic/ipadic/dicrc
----------------------------------------------------------
```

# 原因
`ERROR DETAILS`に書いてある通り、デフォルトの辞書のパスがなかった。[公式ドキュメント](https://github.com/SamuraiT/mecab-python3#common-issues)に書いてあるとおりに
```sh
pip install unidic-lite
```
を実行すると動くようになった。

# 教訓:公式ドキュメントは大事
公式ドキュメントを読んでいれば一瞬で解決した問題なのに、そうしなかったために手こずる羽目になりました。

やらかしポイント
- 時間を短縮したいがために、いきなりQiita記事を読み始める
- Qiitaで解決できなくて、ChatGPTにエラーメッセージを貼り付けて質問し、結果を鵜呑みにして試す
    - 間違ったことを言われて何時間も時間を取られる

恐ろしいことに、私は今まで**公式ドキュメントの重要性を理解しないまま開発を進めてきました。**
大学/大学院の研究ではPyTorchやHugging Face Transformersなどのライブラリを用いましたが、一度も公式ドキュメントを熟読せずにコードを書き始め、問題が起こったらエラーメッセージでググって非公式の記事やStackOverflowなどを参照して解決していました。教授や先輩から読めと言われたこともなく、なんなら上記の解決方法は先輩から教わったので何の疑問も持っていませんでした。

ちゅらデータに入ってアルバイトを始めて、この問題を解決する中で社内の人に「公式ドキュメントを読むのなんて基本のきだよ、機械買ったら説明書まずは読むでしょ？」と指摘されて初めて気づきました。

私のように研究室でのつながりが希薄だったり、学外での開発経験が少ない学生は特に、公式ドキュメントの重要性を知らないまま就職する可能性が高いのではないでしょうか。

初心者の皆さん、問題が起こったらまずは公式ドキュメントを読みましょう。ライブラリを使い始める前に公式ドキュメントをある程度は読みましょう。チュートリアルがあれば回しましょう。

経験のあるエンジニアの皆様におかれましては、このようなことは当たり前すぎて言うまでもないことなのかもしれませんが、新卒の学生はもしかしたら知らないかも、と頭の片隅に置いておいていただけますと幸いです。
【学習メモ】RDS for MySQLの各種ログを調べた

# RDS for MySQLの各種ログ
・RDS for MySQL のスロークエリログと一般ログは、ファイルまたはデータベーステーブルに書き込める。
・DB パラメータグループに**log_output**のオプション（下記三つ）を設定することで、どこへ書き込むか決める。
　　TABLE： 一般クエリを mysql.general_log テーブルに、スロークエリを mysql.slow_log テーブル（デフォルトはTABLE）
　　FILE： ファイルシステム（cloudwatchに出力したい場合はFILEを選択）
　　NONE ：ログ記録が無効（ログを出さない）

## 一般ログ（General Log）
・有効にするには、パラメータグループからgeneral_logを1にする必要がある。
　　general_log：一般ログを作成するには、1 に設定。デフォルトは0。

・MySQLの実行内容（接続時間、接続元ユーザ、実行したSQLなど）を記録

## スロークエリーログ（Slow Query Log）
・有効にするには、パラメータグループからslow_query_logを1にする必要がある。
　　slow_query_log：スロークエリログを作成するには、1 に設定。デフォルトは0。 

・以下の場合、ログに記録される
　　long_query_time ：実行時間がこれを超えるクエリはログに記録される。デフォルトは**10 秒**で、最小値は**0秒**。
　　min_examined_row_limit：実行する行数がこれを超えないクエリはログに記録される。
　　log_queries_not_using_indexes：インデックスを使用しないクエリはログに記録される。

  ⇒要は、クエリーがちょっと怪しい場合かな

## エラーログ
・RDS for MySQLはmysql-error.logファイルにエラーを書き込む。
・サーバが開始や停止する時期を示す情報と、サーバーが実行中に発生したあらゆるクリティカルエラー、そのタイムスタンプなど。

## 監査ログ
・**MariaDB 監査プラグイン**を使用
・DBインスタンスには**MARIADB_AUDIT_PLUGIN**オプションを指定し、**カスタムオプショングループ**を使用する必要がある


# 参考サイト
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_LogAccess.MySQL.LogFileSize.html

https://qiita.com/leomaro7/items/f42f85e3ee2dfbcef649
Xcode15.0でcommitができない

【macOS】Ventura 13.6
【Xcode】Version 15.0 (15A240d)

前のMacBookでgithubにpushしていたソースをcommitしようとしたが
commitボタンが表示されない。
Xcode15ではソースコントロールはintegrateとメニューが変更されている。
commitの方法もステージングしてからcommitするという方法に変わっていた。

以前pushしたのはMontereyでXcodeが14.3くらいだったから
バージョン間の互換性の問題かなぁと思いつつ色々設定を変えてみる。

最終的にソースコードのフォルダ名を「XXX2」のようにして変更すると
commitボタンが表示された。
フォルダ名を戻してもcommitボタンは表示された状態になったので、
とりあえずこれでヨシとする。

ヨシ！
inputタグのreadonly属性のテスト


## はじめに
<!-- textlint-disable -->
タイトルの通り input タグで入力フォームを作る際の readonly 属性のテストにつまずくことがあったので、解決方法を共有できればなと思います。
<!-- textlint-enable -->

## 環境
```json
{
  "react": "^18.2.0",
  "@mui/material": "5.14.13",
  "@testing-library/react": "14.0.0",
  "typescript": "^5.2.2",
  "vite": "^4.4.9",
  "vitest": "0.29.8"
}
```
テストフレームワークに `vitest` と `react-testing-library` を使用しています。

https://codesandbox.io/p/sandbox/testing-input-form-readonly-282z8n?file=%2Fsrc%2FInputForm.test.tsx%3A1%2C1

## テストコード

一番最初に `readonly` 属性のテスト時の検証方法から述べます。

### readonly属性がある(trueの)場合

```App.test.tsx
render(
  <input label="入力フォーム" readonly />
);

// HTML要素を取得する
const input = screen.getByRole("textbox");

// HTML要素に`readonly`属性が付与されていることを期待する
expect(input).toHaveAttribute("readonly");
```

上記のテストコードで `<input readonly />` のように `readonly` 属性がある場合、テストが通ります。

### readonly属性がない(falseの)場合

`screen.debug()` を使って `readonly` 属性が `true` の場合と `false` の場合を見てみます。

```tsx
render(
  <input label="入力フォーム" readonly />
);

screen.debug();
```
![ 2023-10-15 20.54.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639130/0975196a-5b98-5b70-1450-53a5b55986ca.png)


```tsx
render(
  <input label="入力フォーム" readonly={false} />
);

screen.debug();
```
![ 2023-10-15 20.55.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639130/c81e1ade-95c2-79c6-34a2-0f38cb0f3516.png)

`readonly` 属性がある場合、 `readonly=""` となり、 `readonly` が `false` の場合、そもそも `readonly` 属性が存在しないこととみなされます。
なので `expect(input.getAttribute("readonly")).toBeFalsy()` というように真偽値で取得できません。 `.not.toHaveAttribute("readonly")` を使うことで `readonly=false` のテストできます。


## MUIの<TextField />を使う場合

MUI の [TextField](https://mui.com/material-ui/react-text-field/) を使う場合、`<TextField />` に `readonly` 属性を渡しても入力不可能な状態にはなりません。

```tsx
render(<TextField label="input" readOnly={true} />);
screen.debug();
```

![ 2023-10-15 21.24.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639130/6db6c0be-e423-b1ec-6cf1-10ae811582f4.png)

input タグのや要素の div タグに `readonly` 属性が付与され、 input タグには存在していません。

解決するには `<TextField />` の `inputProps` に `readOnly` を加えて渡せば OK です。

```tsx
<TextField label="入力フォーム" inputProps={{ readOnly: true }} />
```

この場合も input タグと同様のテストで検証できます。

```tsx
test("readOnly:true", () => {
    render(<TextField label="input" inputProps={{ readOnly: true }} />);

    const input = screen.getByRole("textbox");

    expect(input).toHaveAttribute("readonly");
  });
```
Python初心者がFizzBuzzやる

はじめましてQitta。
ここ数年Pythonの勉強を何度も何度も"Hello, World"から繰り返して挫折してきたのですがようやく腹も座り本格的に勉強することになりました。超初心者です。
勉強効率を上げるためにQittaで発信することにしました。

# と言うことで有名なFizzBuzz問題をやってみる

Qiitaの記述テストも兼ねて初心者らしくメジャーで簡単なものをまず記しましょう。
FizzBuzz問題は、1から順番に数えていって3の倍数だったら~~アホ~~「Fizz」、5の倍数になったら「Buzz」、3と5の倍数だったら「FizzBuzz」と数字の代わりに書き換える問題です。

なるほど、ループとif文を使えば何とか出来そうですね。
if文はまずは3と5の倍数、つまり15の倍数の条件付けを先に行って、後で3と5の倍数の場合を条件付けすれば良さそう。
たぶんこんな感じ。

```php
# 典型的なFizzBuzz
for i in range(1, 100, 1):
    if i % 15 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 ==0:
        print("Buzz")
    else:
        print(i)
```

やったね、1から100までのFizzBuzzができたよ。


# ついでに3の倍数と3が入っていたらアホになる方も作る

……と軽い気持ちで始めたのですが、結構難問ですねこれ。
上記のFizzBuzzは無量大数まで適用可能ですが、ナベアツ師匠のこれは考えれば考えるほど深みに嵌ってしまっています。

3の倍数の方は上記の方法で簡単にできるのだけど、3が入っている方の条件付けってどうやるんでしょう？？

とりあえず1の位で3が出てくる場合の条件付けは、10で割った余りが3
10の位で3が出てくるものは、100で割った余りを10で割ったものの商が3以上4未満
100の位で3が出てくるものは、1000で割った余りを100で割ったものの商が3以上4未満

と繰り返していけばできます。
こんな感じ。

```php
# 3の倍数と3が出てきたときにアホになる
for i in range(1, 1000, 1):
    if i % 3 == 0:
        print("アホ")
    elif i % 10 ==3:
        print("アホ！")
    elif 3 <= (i % 100) / 10 < 4:
        print("アホ！！")
    elif 3 <= (i % 1000) / 100 < 4:
        print("アホ！！！")     
    else:
        print(i)
```
しかしこのような条件付けだと無量大数までやるのは無理ですよね？
……何か良い方法があるのでしょうか？　できそうでできない。
これは宿題としておきます。
await userEvent.click() してるのに act() warning が止まらない原因と解決

# はじめに

React Testing Library を使ったテストにおいてクリック操作などのユーザー操作を実施する際には、testing-library/user-event を使います。例えばクリック操作なら `user.click()` のような感じ。その際、コンポーネントの状態更新の同期をとるため、戻り値の Promise を `await` することが必要です。これをしないと、`When testing, code that causes React state updates should be wrapped into act(...):` という warning が出ます。

https://github.com/testing-library/user-event/issues/497#issuecomment-729897974

しかし、これをしているにも関わらず Warning が解消されないことが多々あり、非同期関数内で状態を更新している際はだめなのかと思い長い間あきらめていたのですが、最近あらためて調べてみた結果、原因がわかったので、本記事はその記録となります。

# 原因

https://github.com/testing-library/user-event/discussions/906#discussioncomment-6165530

複数のバージョンの `@testing-library/dom` がインストールされていることが原因とのこと。User event は `@testing-library/dom` に wrapper 関数を登録するのですが、複数のバージョンの `@testing-library/dom` がインストールされていると、それが適切に機能しないのが原因だそうです。実際に、`npm ls @testing-library/dom` を実行してみたところ、8.20.0 と 9.2.0 の2つインストールされていることが確認できました。

```
├─┬ @storybook/testing-library@0.1.0
│ ├── @testing-library/dom@8.20.0
│ └─┬ @testing-library/user-event@13.5.0
│   └── @testing-library/dom@8.20.0 deduped
├─┬ @testing-library/react@14.0.0
│ └── @testing-library/dom@9.2.0
├─┬ @testing-library/user-event@14.4.3
│ └── @testing-library/dom@8.20.0 deduped
├─┬ eslint-plugin-jest-dom@4.0.3
│ └── @testing-library/dom@8.20.0 deduped
└─┬ react-select-event@5.5.1
  └── @testing-library/dom@8.20.0 deduped
```

# 修正

@testing-library/dom に依存しているライブラリを再インストール。

```
├─┬ @testing-library/react@14.0.0
│ └── @testing-library/dom@9.3.3
├─┬ @testing-library/user-event@14.5.1
│ └── @testing-library/dom@9.3.3 deduped
├─┬ eslint-plugin-jest-dom@5.1.0
│ └── @testing-library/dom@9.3.3 deduped
└─┬ react-select-event@5.5.1
  └── @testing-library/dom@9.3.3 deduped
```

これにて act warning は全て解消。
Tailscaleのインストール

# Tailscaleのアカウント作成をする
[公式サイト](https://tailscale.com/)からアカウントを作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613684/4f7dc415-aff1-1c76-bdea-acf6a46b25f2.png)

# UbuntuにTailscaleをインストールする
[公式サイト](https://tailscale.com/download/linux)の通りインストールする。

##### 1. レポジトリキーを追加する
```shell
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/focal.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/focal.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
```

##### 2. Tailscaleをインストールする
```shell
sudo apt-get update
sudo apt-get install tailscale
```

##### 3. Tailscaleの認証を通す
以下のコマンドを入力して出力されたリンクから認証を通す。
```shell
sudo tailscale up
```

##### 4. IPアドレスの確認をする
下記のコマンドからIPアドレスを確認することができる。
```shell
tailscale ip -4
```



# WindowsにTailscaleをインストールする
[公式サイト](https://tailscale.com/download/windows)からインストーラをダウンロードして、ログインする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613684/48ad620f-dab8-ee8f-2f1a-e01950724cd8.png)
ChatGPT先生を使った英語学習のWebサービスを作ってみたいなぁと思い至りました

個人で開発しながらキャッキャウフフしているnkitaoと申します。

突然ですが、ふと、こんな事思ったことありませんか？
「日本語では感想や意見を思いつくけど、英語だと赤ちゃん並みの表現になる」
「挨拶程度は英語でかっこよく反応して意識高く見られたい」
「スタバでかっこよくコーヒーを注文したい（フラペチーノとか）」

私は時々そんなことを思うのですが、その際ChatGPTを使い自分の英語表現がいい感じなのかどうかよく聞いています。
これの何が良いかというと、自分の書いた文章そのものを添削してくれるということ。
自分専属のトレーナーがついた感じですごくいい体験だったので、
「これはサービスにせな！」
と思い至り、カッとなって作りました。

# :tools: 作ったもの
:tada::tada:[ChatEPT](https://ept.nkitao.com/)（Chat English Personal Trainer）:tada::tada:

**:house: 初期画面**
![スクリーンショット 2023-10-15 19.23.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237628/68924e39-a21f-0d76-b67b-0e767559a931.png)

**:pencil: クイズ**
![スクリーンショット 2023-10-15 19.28.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237628/28c296bb-06d8-3ca6-1685-59cdf9b180e2.png)


# :wink: 何ができるの？
・あなたの英語力を0点〜100点で**ChatGPT**先生が評価します。
・**ChatGPT**先生がアドバイスをしてくれます。
・nkitaoを破産に追い込めます。
　※ChatGPT APIの費用はnkitaoのお財布と従量課金制で連携しています。

# :gear: 仕組み
![Group 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237628/96f506c9-04e4-4d48-64e0-412f31c0f3ee.png)


# :heart_decoration: 使っている言語・フレームワーク等
作成にあたってとてもお世話になりました。超リスペクト :pray: 
・Next.js
・Chakra UI
・Prisma
・NextAuth.js
※もう一度言います。超リスペクト:pray:

# :saxophone: 感想
・ChatGPTへのリクエストは、期待した答えが返答されるまでのチューニングがすごく大変だった。
・テスト中で何度か挑戦していたところ、何度かGPT先生に煽られてキレそうになった。
　→先生のコメント欄に絵文字「😄」を入れることによって少しだけマシになった。
・今後は過去の履歴を表示できるようにしたい。

皆様どうぞお気軽に使ってやってください！！:bow_tone2:
log4j

## log4j

```java:Main.java
package test;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;

public class Main {
	public static void main(String[] args) {
		System.setProperty(XmlConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "log4j2.xml");
		
		Logger logger = LogManager.getLogger(Main.class);
		logger.trace("TRACEレベルのログ");
		logger.debug("DEBUGレベルのログ");
		logger.info("INFOレベルのログ");
		logger.warn("WARNレベルのログ");
		logger.error("ERRORレベルのログ");
		

		if (args.length != 2) {
			logger.error("起動引数の数が異常：" + args.length);
		}
	}

}

```

```xml:log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
	<Appenders>
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout
				pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		</Console>
	</Appenders>
	<Loggers>
		<Root level="trace">
			<AppenderRef ref="Console" />
		</Root>
	</Loggers>
</Configuration>
```
MSX BASICでbase64デコーダを実装

## はじめに
皆さんこんにちは。最近、MSX0を入手したので、昔触れたMSX BASICを思い出しながら、再学習しながらプログラミングをしています。
MSX0ですが、ありがたいことにIP ReachableでTeraTeamで接続して作業できるんですよね。Windows端末上でプログラム組んで、コピペでMSX0に流し込んで、runして動作確認。小規模のプログラム開発はこの方法で捗りそうですね。
とはいえ、ズボラな私はもうちょっと楽したくて、画像等々のバイナリファイルもWindows端末からコピペできると理想的ではと思い、勉強の題材にとまずはbase64のデコーダを作ってみました。

（現状ある程度実装が進んでいる状況から報告しておくと、転送速度が芳しくなく、SDカード抜き出してファイル転送したほうがおそらく早いことが見えてきています…）

## デコーダ実装
以下実装コードです。
```bbcbasic
10 DIM I$, O$, B$
20 INPUT "Please input the text using base64:"; I$
30 GOSUB 100'CALL Base64 decoder (I$:Input Text, O$:Output Text, B$:Base64 table)
40 PRINT "Result:"; O$
50 END
100 'Base64 decoder (I$:Input Text, O$:Output Text, B$:Base64 table)
110 DIM B(4), OB(3)
120 DIM T$, C$
130 LET O$ = ""
140 LET B$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
150 FOR I = 1 TO LEN(I$) STEP 4
160   T$ = MID$(I$, I, 4)
170   EP = 4
180   IF I + 4 > LEN(I$) THEN IF INSTR(T$, "=") > 0 THEN EP = INSTR(T$, "=") - 1
190   FOR J = 1 TO 4
200     B(J) = 0
210   NEXT J
220   FOR J = 1 TO EP
230     B(J) = INSTR(B$, MID$(T$, J, 1)) - 1
240   NEXT J
250   OB(1) = B(1) * 4 + B(2) \ 16
260   OB(2) = (B(2) AND 15) * 16 + B(3) \ 4
270   OB(3) = (B(3) AND 3) * 64 + B(4)
280   FOR J = 1 TO 3
290     O$ = O$ + CHR$(OB(J))
300   NEXT J
310 NEXT I
320 LET O$ = LEFT$(O$, LEN(O$) - (LEN(T$) = 2) - (LEN(T$) = 1))
330 RETURN
```

## 実行結果
実行結果はTeraTeamの出力結果を採用しています。残念ながらMSX上はUNICODEは表示されませんので。
```console
run
Please input the text using base64:? 5pys5pel44Gv5pm05aSp44Gq44KK
Result:本日は晴天なり
Ok
```
MSX0上の表示は以下のようになります。なにがなにやらですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106997/96885ce5-0f8c-70f5-e595-09b58f7aa91c.png)

## MSX-BASICあれこれ
MSX-BASICの書籍を読み切れてないせいか、まだまだ疑問点多いですね。勉強せねば。
・配列の初期化、効率的な方法ないですかね
・シフト演算子は、、無いですよね
・FORループを途中で抜けるときは、GOTOとかで飛ばしちゃってよいものか


現場からは以上です！
リーダブルコード　第5章　コメントをすべきところを知る　第6章　コメントは正確で簡潔に　まとめ

# 第5章
## コードからすぐにわかることをコメントに書かない
例）次のようなコメントは、コードを読めばすぐにわかるため不要
```
# profitに新しい値を設定する
void SetProfit(double profit);
```
```
# 2番目の`*`以降をすべて削除する
name = '*'.join(line.split('*')[:2])
```

## 初めてコードを見た人は、プログラムの全体像が分からない
初めてコードを見た人でも理解できるよう、ファイルやクラスには「全体像」のコメントを書く

## コメントを書く作業
1. 頭の中にあるコメントをとにかく書き出す
2. コメントを読んで（どちらかといえば）改善が必要なものを見つける
3. 書きだしたコメントを改善する

# 第6章
## コードの意図を書く
コードの動作内容をコメントするのではなく、このコードは何の処理のために行うのかの意図を書く

## 書いたコメントが長すぎたら、長いコメントを別の単語で表現できないかを検討する
（自力でコメントを置き換えることができる単語を調べられなかったら、生成AIに書いたコメントをそのまま送信し、1単語にできないか聞いてみるのもよいと思う）
例）
a. 
```
このクラスには大量のメンバがある。同じ情報はデータベースにも保管されている。
ただし、速度の面からここにも保管しておく。このクラスを読み込むときには、メンバが存在しているかどうかを先に確認する。
もし存在していれば、そのまま返す。
存在しなければ、データベースから読み込んで、次回のためにデータをフィールドに保管する
```
b. 
`このクラスの役割は、データベースのキャッシュ層である`

a. の「データの読み込み速度を早めるために、データベースに保管している同じ情報をこのクラスに格納する」といった説明を、
b.では「キャッシュ層」と一言で表している
【Laravel / MYSQL】データベースの値を集計する方法

今回はデータベースを集計する方法について解説します。
データベースにあるデータを集計してブラウザに表示したい時の参考にしてください。

開発環境
・PHP8.0.8
・Laravel 9.52.8
・MacOS M1チップ

## SQLで集計する時の流れ
CRUD処理ができるようになると登録したデータを集計して画面上に表示させたい！と思いますよね。
基本的な流れは以下の通りです。

1.取得したデータをGROUPBY句で集計
2.集計した列をCOUNT関数で件数を取得

参考：https://readouble.com/laravel/9.x/ja/queries.html#grouping

## データの取得と集計
```php:Post.php
    public function countTodos($user_id)
    {
        return Post::selectRaw('user_id, COUNT(user_id) AS count')->groupBy('user_id')->get();
    }
```
`selectRaw`はSQl文を直接使用したい時に使用します。
今回はCOUNT関数を使用したいので、`selectRaw`を使用しています。
さらにGROUPBY句でuserが何人いるかを集計していきます。

## 注意すること
ここまでで一応集計の流れは終わりですが、ここで注意点があります。
まずGROUPBY句を使用する場合はSELECT文に同じ値が必要です。
そうしないとうまく処理されないので注意が必要です。
SQL文でも試したい方は下記に記載しておくので試しておいてください。

```sql:SQL
SELECT user_id, COUNT(user_id) AS count FROM todos GROUP BY user_id;
```

```sql:結果
+---------+----------------+
| user_id | COUNT(user_id) |
+---------+----------------+
|       1 |             13 |
|       2 |             10 |
|       3 |             10 |
|       4 |             10 |
|       5 |             10 |
+---------+----------------+
5 rows in set (0.00 sec)
```
GROUPBY句を活用することでうまく集計することが可能です。
GROUPBYについて詳しく知りたい方は下記記事も参考にしてください。

参考：https://style.potepan.com/articles/22202.html#SQLGROUP_BYCOUNT

## まとめ
集計するための流れは以下です。

1.取得したデータをGROUPBY句で集計
2.集計した列をCOUNT関数で件数を取得

注意点としてはGROUPBYの記載方法ですね。
GOUOBYを使用せずに一つ一つ取得することも可能ですが、
それだと冗長的なコードになってしまうので、うまく活用して保守性の高いコードを目指していきましょう。
【学習メモ】API GatewayがCloudWatchへ送信するメトリクスの種類

# API Gateway のメトリクス
API Gateway はメトリクスデータを**1 分**ごとにCloudWatchに送信する

## 4XXError
指定された期間に取得された**クライアント側エラー**の数

## 5XXError
指定された期間に取得された**サーバー側エラー**の数

## CacheHitCount
指定された期間内に API キャッシュから配信されたリクエストの数

## CacheMissCount
API キャッシュが有効になっている特定の期間における、バックエンドから提供されたリクエストの数
（API キャッシュから配信されていない、キャッシュがヒットしていない場合）

## Count
指定期間内の API リクエストの合計数

## IntegrationLatency
API Gateway がバックエンドにリクエストを中継してから、バックエンドからレスポンスを受け取るまでの時間
（ミリ秒）
　⇒　Lambdaファンクションとかバックエンドの応答性


## Latency
API Gateway がクライアントからリクエストを受け取ってから、クライアントにレスポンスを返すまでの時間
（ミリ秒）
（IntegrationLatencyとその他のAPI Gatewayのオーバーヘッドが含まれる）
　⇒　APIコールの応答性


# 参考サイト
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html
Mockitoまとめ

#### Mockitoについて
Javaのユニットテスト用に開発されたモックフレームワーク、テストでモックオブジェクトを直感的に操作できることを目的として開発されている

#### モックについて
外観・ユーザーインターフェイスの振る舞いを模倣したハリボテみたいなもの
言い換えると、テストしたいオブジェクト（クラス・インスタンス）の中に別のオブジェクトのメソッドが呼び出されているものの振る舞いを模倣する

#### ソースコード例
chatGPTで生成してちょこちょこ変えました、chatGPT便利

```java:UserService.java
public class UserService {
    private UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User getUserById(int userId) {
        return userRepository.findById(userId);
    }
}
```
```java:UserRepository.java
public interface UserRepository {
    User findById(int userId);
}
```
```java:UserServiceTest.java
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class UserServiceTest {

    @Test
    public void testGetUserById() {
        // UserRepositoryのモックを作成
        UserRepository userRepository = Mockito.mock(UserRepository.class);

        // モックの振る舞いを設定
        User mockUser = new User(1, "John");
        Mockito.when(userRepository.findById(1)).thenReturn(mockUser);

        // UserServiceをモックのリポジトリと一緒にインスタンス化
        UserService userService = new UserService(userRepository);

        // テスト対象のメソッドを呼び出し
        User user = userService.getUserById(1);

        // 結果の検証
        assertEquals(1, user.getId());
        assertEquals("John", user.getName());
    }
}
```

### 最後に
モックを調べたらスタブとドライバ辺りも詳しく調べてみると良さそう


#### 参考文献
https://recruit.cct-inc.co.jp/tecblog/java/mockito-primer/

https://zenn.dev/kenta123/articles/23d9496738c0d8
OpeninterpreterをAzure OpenAIで試す

Azure OpenAI環境にてopeninterpreterを試してみた。

# Openinterpreterとは
OpeninterpreterはOpenAIのchatgpt plusにて提供されている「codeinterpreter」のオープンソースクローン。
LLMに対して自然言語でアプローチして、プログラムコードを（ローカル環境にて）実行させることができる。
https://openinterpreter.com/
2023/9/26のupdateでDeveloper Featuresとしてpythonによる実行が追加されたため試してみた。（それまではコマンドラインツールのみだったはず。）

# コマンドライン実行
Azure OpenAIでの実行方法が変わっている。以前は環境変数にリソース設定をして --use-azure　で起動できたはずだが、オプションが使えなくなっている。代わりに--model(-m)にazure/デプロイ名のオプションにて実行可能。（他LLMサービスを使用する場合も同様。この拡張による変更かと。）
```bash
export AZURE_API_KEY=""
export AZURE_API_BASE="https://[AOAI-resourcename].openai.azure.com"
export AZURE_API_VERSION="2023-07-01-preview"

# gpt-4はデプロイ名
interpreter -m azure/gpt-4
```


# pythonプログラム実行
今回追加されたpythonインタフェース。
interpreter.chat()でインタラクティブモードで起動する。

```python
import interpreter
import os

os.environ['AZURE_API_KEY']     = ""
os.environ['AZURE_API_BASE']    = "https://[AOAI-resourcename].openai.azure.com"
os.environ['AZURE_API_VERSION'] = "2023-07-01-preview"

# gpt-4はデプロイ名
interpreter.model="azure/gpt-4"
interpreter.chat()
```

もしくはメッセージを直接指定する場合、
```python
interpreter.chat("Hi! Can you print hello world?")
```

実行結果
```
Sure, here's the code to print "Hello, world!" in Python:
    print('Hello, world!')
When you run this code, it will display "Hello, world!" as the output. 
```

# 実行してみる
コマンドラインを起動して、以下の指示を与えてみる。
![スクリーンショット 2023-10-15 19.37.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/9af0c64c-8732-8ac6-3957-94cc1be4c1c6.png)

実行計画を示したのち、実行するためのコードを提案してくる。
![スクリーンショット 2023-10-15 19.35.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/f37d59b5-fa0a-f77e-f861-1643eff0f2ed.png)

ただし上記のコードは失敗（tableタグを取得することができない）することがわかっており、その後深みにハマっていくため、
「> tableタグから取得するのではなく、テキスト内から探して」
とリクエストするとコードを修正してくれる。
（提案コードはランダムなため、一発でうまくいくコードを教えてくれる場合もある。）

![スクリーンショット 2023-10-15 19.36.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/f8909662-73c8-7e24-2195-59f5d7a316e9.png)

コードを実行した結果から答えを教えてくれる。
![スクリーンショット 2023-10-15 19.36.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/68e17cbd-5f12-b42e-9f03-1c767793f079.png)

※コード表示した後、コード実行に対して[Y/n]を聞かれる場合もあるが、何も出ない場合もあり、その場合は「y」と入力すると実行する。（ここらは不安定。）

# まとめ
まだ不安定だが、何かの要件を満たすためにコーディングしていくステップを代わりにやってくれるため、コーディングの教育用途にも向いていると思われる。（コードエラー時の修正、計画の見直しなど。）
極めて近い将来、自然言語で要件を伝えるだけで、人間側はノーコードで結果を得ることができるように利用できるようになりそう。
複数ファイルへのリダイレクト

## 問題：普通のリダイレクトだとファイル１つにしか出力できない。
```
kubota_akihiro:temp $ ls
kubota_akihiro:temp $ echo aaa > a1 a2
kubota_akihiro:temp $ ls
a1
```

## 解決策：teeを使う。teeは出力先を複数にできるから。
```
kubota_akihiro:temp $ rm a1
kubota_akihiro:temp $ echo aaa | tee a1 a2
aaa
kubota_akihiro:temp $ ls
a1 a2
kubota_akihiro:temp $ cat a1
aaa
kubota_akihiro:temp $ cat a2
aaa
```
可読性を上げるために気を付けること

# 初めに
今回は意外と気にしてる人が少ない可読性のために自分が普段気を付けていることを紹介していきます
### 本文
***KDocコメント***
まずはKDocコメントですKDocコメントとは下記のような形式で書かれたコメントです
中にクラス名やパラメータ名を`[]`で囲むことで検索をかけたりすることができます。
また、複雑な処理をしている関数などに軽い説明を入れることでパッと見ただけで他者がどんな関数なのかがわかりやすくなります
```kotlin
/**
*
*/
```
***ファイリング***
正式になんといえばいいのかがわからないので今回はファイリングという名前で紹介させていただきますが、やってることはとても単純で適切なパッケージや適切なクラスなどにわけることです。
例えば、データクラスを加工する処理を何か所にも同様のものを書いたり、データクラスに複雑な加工処理を何個も書くのはデータの置き場であるはずのデータクラスのコード量をファットにして非常に可読性が悪くなってしまいます
### 最後に
今回は自分が可読性を上げるために特に気を付けていることを紹介していきました
どなたかのお役に立てれば幸いです
AWS Certified Security - Specialty (SCS-C02)を更新しました

# はじめに
AWS Certified Security - Specialtyが失効間近のため更新しました。

# 教材
1. [Tech Stock | AWS WEB問題集で学習しよう](https://techstock.jp/exam/scs/)
    - 有償のおなじみのやつです。
    - 434問(62セクションx7問)です。
    - 他者の合格記を見ると好評でしたので、Udemyは受講せず、これだけ勉強しました。結構よかったかと思います。
1. [Skill Builder: WS Certified Security - Specialty Official Practice Question Set (SCS-C02 - Japanese)](https://explore.skillbuilder.aws/learn/course/15232)
    - 無料の公式問題集です。
    - 20問です。
1. [Skill Builder: AWS Certified Security - Specialty Official Practice Exam (SCS-C02 - Japanese)](https://explore.skillbuilder.aws/learn/course/15744)
    - 有料の公式問題集です。
    - 65問です。
    - "AWS WEB問題集で学習しよう"だけでも良いですが、お金があれば、より合格率を高めるために受けても良いと思います。

# 感想
- "AWS WEB問題集で学習しよう"のおかげで難しい問題はありませんでした。
iterm2で新しくタブやウィンドウを開かずに文字コードを変える方法

元々、「iterm2で新しくタブやウィンドウを開かずに文字コードを変える方法」は以下の方法がありました。
[iTerm2のプロファイルをコマンドで切り替える - Qiita](https://qiita.com/libra_lt/items/8de23165159e2f702f6b)

ただ、これだと
- ログイン先サーバーでコマンドを叩いて良いのか？わからない
- DBにログイン中だと実行できない

といった問題がありました。
今までは対策として、指定の文字コードを持つプロファイルを指定して新しくウィンドウを開くことをやっていました。
そこで、作業途中に文字コード変えられたらなあ、、と思っていたところ、以下の記事があり解決しました。
[macos - Change iTerm2 Profile - Ask Different](https://apple.stackexchange.com/questions/388558/change-iterm2-profile)

## 方法
- iterm2の画面上で右クリック　> Edit session > 変更先プロファイル選択　> Use Selected Profile

、、簡単でした。。
【メモ】Trailheadでやったことを備忘用に記録していく（Lightning Experience の取引先と取引先責任者 ））

## 顧客に関する情報を保存する

【目的】
法人取引先と法人取引先責任者とは何か、どのように関連しているのかを説明する。
個人取引先とは何かを説明する。
新規法人取引先と関連する取引先責任者を追加する。


「取引先」「取引先責任者」オブジェクトをこれまで色々いじってきたもの。改めてここで説明。

## 取引先と取引先責任者のリレーションの説明

■リレーションは複数もてる。
以下三種類の形でとらえられる。
・会社 (取引先) とその会社で仕事をする人々 (取引先責任者) のリレーション。会社 (取引先) と他の顧客 (他の取引先) のリレーション。
・取引先責任者-to-複数取引先
1 人の取引先責任者を複数の取引先に関連付ける。
各人とその人が仕事をする会社間のリレーションを追跡できる。
・顧客 (取引先) とその顧客と取引をしている同僚 (他の Salesforce ユーザー) のリレーション。




■複数の場所にある企業に対して取引先を設定する方法を決めるとき、2 つの基本的な選択肢があります。

グローバル企業取引先
場所固有の取引先
⇒salesforceでは細かく分けてレコードを作りまくった方がいいよ、とお勧めしている。
【図解】Pythonのライブラリ 24選＋α

Pythonにはライブラリが沢山あります。ライブラリとは便利な機能を持ったプログラムを集めたものを言い、このライブラリを上手く使うことで色々なことを実現できます。

今回はこのライブラリを用途別で図解にまとめました。
Pythonでプログラムを組む際の参考になりましたら幸いです。

※簡単にまとめているだけなので、詳しい中身は公式ドキュメント等をご確認ください。

**追記（2023/12/25）**
当記事がありがたいことに好評いただけたので、Pythonの基礎も図解化しました。あわせてご活用いただけますと幸いです。

https://qiita.com/python_academia/items/bde85d799e7db4936ce1

**追記（2024/8/22）**
上述の「【図解】Python基礎64選」が更にパワーアップした「Python 基礎文法の教科書」をzennにて公開しました。こちらも興味のある方はご確認いただけますと幸いです。

https://zenn.dev/python_academia/books/6df147d8b82939


## 機械学習

**機械学習 ⊃ 深層学習**という包含関係です。

ざっくり言うと、特定のタスク（分析の方向性が明確）に対して予測できるのが機械学習で、より複雑なデータも処理できるのが深層学習です。

**ただし深層学習はその分、学習に要する時間やデータは多くなります。**

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638073/e7f150fe-22f4-ef5c-7f48-84afa8815782.png)

【機械学習入門】scikit-learnを使ったアヤメの分類

https://arika-blog.com/scikit-learn/

## データ分析
データ分析には必須と言っていいほどのライブラリです。
Numpyはデータの前処理、matplotlib・seabornはデータの可視化に使います。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638073/43f1a48e-25f9-75a2-2631-bf7f9cb06bfd.png)

### 追記

NumPy2.0が2024年6月にリリースされました。2006年以来のメジャーアップデートのため、様々な改善や新機能があります。

月刊IOにその内容を書いたので、興味のある方はチェックしていただけると嬉しいです。

https://arika-blog.com/monthly-io-contribution2/


## 業務効率化
Pythonは業務効率化にも使えます。
Excelとスクレイピング、PDFとOutlookなど、複数の処理を１つのプログラム内で完結させることができます。

![図解 (50).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638073/affd8514-88ef-7dfb-f128-0638a531b069.png)


こちらにもう少し詳しい内容を載せています。

https://qiita.com/python_academia/items/96df81c3fe4094581908

**関連記事**

https://arika-blog.com/pandas-graph/

https://arika-blog.com/python-pyautogui/

https://arika-blog.com/python-mail/

## Webアプリ
Pythonにはwebアプリ開発に便利なフレームワークが存在します。これによりWebブラウザ（chrome、edgeなど）上で動くアプリを作成できます。

**フレームワークとは、システム開発が楽になるように用意された、プログラムのひな形のことです。**

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638073/f1e0f0bf-84e3-a7f4-6115-d822d9eb15a3.png)

## デスクトップアプリ
基本的にはその名の通り、デスクトップで動くアプリのことです。
自分が作成したプログラムをGUI化（マウスで操作できるアプリ化）することで、より使いやすくできます。

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638073/02016243-a869-697f-db7d-0e2204282b43.png)

PySimpleGUIに関しては基本をまとめていますので良かったらご活用ください。

https://arika-blog.com/pysimplegui/


## その他
画像処理を業務効率化に使われる方もいると思いますが、業種が限られると思ったのでその他にしました。

OpenCV・Pillowは機械学習の前処理でも使えます。場合によってはOpenCVだけでも異常検知ができます。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638073/9a344029-3579-6148-1a9a-cb8bf3661289.png)


## おまけ（よく使う標準ライブラリ）
用途別というよりかは常に使うものですが、[標準ライブラリ](https://docs.python.org/ja/3/library/index.html)から使う頻度が多いものを選出しました。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2638073/e280e112-9b73-9108-f81b-cce5f6f42124.png)

**関連記事**

https://arika-blog.com/python-sys/

## おわりに
最後までお読みいただきありがとうございました！
Pythonはライブラリが豊富なので、まずは概要だけでもおさえておくといいかもしれません。また、勉強方法にお困りの方はこちらの記事もご参考にしてください。

https://arika-blog.com/python-threestep/

YouTubeにて、Pythonチュートリアル（公式ドキュメント）を使ってPythonの基礎文法を解説しています。
こちらもよろしければご活用ください。

https://www.youtube.com/channel/UCl_e49nQhOMoYkQOo_4ew2Q
MacのOctaveでfir1

MacのOctaveでfir1関数を使おうとしたら「ないっす」と言われたので取ってくる話しです。


fir1関数はsignalパッケージに入っていて、signalパッケージはcontrolパッケージに依存しています。なので、先にcontrolパッケージをインストールします。Octaveのコマンドウィンドウで

```shell:octave
>> pkg install -forge control
```

なにやら下記のようなwarningが出ますが、とりあえず終了します。

```shell:warning
In file included from __control_slicot_functions__.cc:44:
./sl_ib01ad.cc:146:17: warning: variable 'nsmpl' set but not used [-Wunused-but-set-variable]
        F77_INT nsmpl = 0;                          // total number of samples
                ^
1 warning generated.
ld: warning: could not create compact unwind for _mb03xp_: stack subq instruction is too different from dwarf stack size
ld: warning: could not create compact unwind for _sb10yd_: stack subq instruction is too different from dwarf stack size
For information about changes from previous versions of the control package, run 'news control'.
```

次に本命のsingalパッケージ取ってきます。

```shell:octave
>> pkg load signal
```

これは下記のメッセージとともに、すんなり終わります。

```shell:octave
For information about changes from previous versions of the signal package, run 'news signal'.
```

関数実行前には、パッケージをロードする必要があります。

```shell:octave
>> pkg  load signal
```

インストールできると関数のhelpが表示できます。


```shell:octave
>> help fir1

'fir1' is a function from the file /Users/kikuchi/Library/Application Support/Octave.app/6.2.0/pkg/signal-1.4.5/fir1.m

 -- Function File: B = fir1 (N, W)
 -- Function File: B = fir1 (N, W, TYPE)
 -- Function File: B = fir1 (N, W, TYPE, WINDOW)
 -- Function File: B = fir1 (N, W, TYPE, WINDOW, NOSCALE)
....
```

pkg load signal は起動ファイル~/.octavercに書いておくと毎回実行為なくて済みます。
ブラウザのURLからメールにリンクを貼り付けるやり方です。

#
[ここをクリックすると他の技術投稿の目次に行きます](https://qiita.com/FUKUTAKA7938/items/2312362e44dbcecd11ca)

# ブラウザのURLからメールにリンクを貼り付けるやり方です。
（Office 関係やテキストエディッタなどの文字入力系のアプリもできます。）

　ブラウザでホームページを表示後、アドレスバーのアドレスの一番右の端っこの白いバーでマウスカーソルをもっていき、クリック 

または、
　クリックで範囲指定できないときは、アドレスの頭または、最後の方から必要な範囲をドラッグしたら良いですよ。

または、
　キーボードのctrl (MAC は、⌘キー) + a でアドレス 全範囲指定できたと思います。

※この方法でやるとパラメータまでコピされますので、
パラメーターは、コピー先のアドレスの ? 以降をDELキー や BSキーで削除すれば、そのページのトップが表示されます。
（まろんバロンクァッカさんからのご指摘です。ありがとうございます。）



　アドレスバーのアドレスが青いバー(範囲指定)になると思います。
　この状態で、キーボードのctrl(MAC は、⌘キー)  + c
でコピーし、

　メール（Office 関係やテキストエディッタなどの文字入力系のアプリもできます。）に移り、
ctrl(MAC は、⌘キー)  + vで、張り付けします。

　張り付いたアドレスが青い文字と青い下線（テキストエディッタはなりません）
になればOKです。

#
[ここをクリックすると他の技術投稿の目次に行きます](https://qiita.com/FUKUTAKA7938/items/2312362e44dbcecd11ca)
EC2を停止して起動すると、さっきまでアクセスできていたページにアクセスできなくなった

# 背景
EC2を停止して起動すると、さっきまでアクセスできていたページにアクセスできなくなった。
HTMLファイルをEC2を利用してブラウザで表示させていたのだが、インスタンスを停止しないと利用料金がかかるので都度停止していた。
夜に停止して翌朝起動すると、昨晩までアクセスできていたページが表示されない。
![スクリーンショット 2023-10-15 18.27.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935700/df7d9234-6f2b-5918-a41d-ee3fb2edac47.png)

# 原因
インスタンスが起動してもApacheが起動していないこと原因だった。
↓のコマンドでApacheの状態を確認する。
```
service httpd status
```
↓結果
![スクリーンショット 2023-10-15 18.30.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935700/4ba4e966-1db1-9458-262f-526913cdff66.png)
`Active : inactive`つまりApacheが起動していないことがわかる。
インスタンスが起動しているだけでApacheは起動していなかったのだ。
# 解決策
Apacheを起動する。root権限で実行しましょう。
```
systemctl restart httpd
```
同じようにアクセスする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935700/e98deb76-fd08-106e-3812-2f9f39ae78b0.png)
無事表示された。
インスタンスとApacheを一緒くたに考えてしまっていたのでハマった。

しかしインスタンスを再起動するたびに毎回Apache起動コマンドを打つのは面倒。
そんな時は、EC2インスタンス起動時に自動でApacheも起動するように設定する。
root権限で実行しましょう。
```
chkconfig httpd on
```
これでインスタンスを起動するだけでApacheも起動されるようになった。
【メモ】Trailheadでやったことを備忘用に記録していく（数式項目の使用）

---Salesforce　アドミニストレータ試験用の実施内容単元、ごとに、後で戻れるよう単元ごとにメモしていきます---

■数式項目の使用

テキストエリア入力の注意点！
>テキストエリアには数式を入力します。入力時には、次の点に注意してください。
空白文字は考慮されません。空白や改行をどれだけ挿入しても数式の実行には影響しません。
数式では、大文字と小文字が区別されます。項目名やオブジェクト名の大文字と小文字に注意してください。
数値には、標準の演算処理の順序が適用されます。

高度な数式。関数がぱっとわかりやすく出ているのはベネ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3532370/4f70d669-c27a-fcee-6a36-78965a935f61.png)

数式
EndDate - TODAY()　で残り日数を表示

■積み上げ集計項目の実装

積み上げ集計項目を作成する
標準の取引先オブジェクトにカスタム項目を追加して、すべての関連商談から総期待収益を積み上げ集計します
⇒「項目」設定からやるだけ

■入力規則の作成

・オブジェクトマネージャーから左サイドバー[入力規則] を使用。

<助かったサイト＞
https://isyourcareer.com/trailhead-suushiki/


＜CHALLENGE＞
AND( NOT( ISBLANK(  Id ) ) , MailingPostalCode <> Account.ShippingPostalCode )

これでいけると思いきや･･･対象がなくエラー

https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000K10FgSAJ
コミュニティに先駆者者が。


結局、ハンズオンまでの流れで「取引先」オブジェクトでやっていたのがダメだったってことね。
ラプラス変換で連立微分方程式「ラプラス変換と微分方程式（3）(演習問題 / 解答例) 」をChatGPTとWolframAlphaとsympyでやってみたい。

・sympyで曲線が2本でます。

# オリジナル
例）次の初期値問題を解いてみる。

https://www2.yukawa.kyoto-u.ac.jp/~norihiro.tanahashi/pdf/ODE/note_14.pdf#page=4

＜ 講義
https://www2.yukawa.kyoto-u.ac.jp/~norihiro.tanahashi/lecture.html
https://www2.yukawa.kyoto-u.ac.jp/~norihiro.tanahashi/index.html

# ChatGPT-3.5先生へ。１回目(**???わかりませんでした。???**)
```
次の初期値問題を解いてみる。
y1'(t)=y1(t)+y2(t),y1(0)=0
y2'(t)=y2(t)+1    ,y2(0)=0
```
日本語抜き
```
y1'(t)=y1(t)+y2(t),y1(0)=0
y2'(t)=y2(t)+1    ,y2(0)=0
```
(省略)
```
sympyで
```
y1(t) = 0
y2(t) = exp(t) - 1
過去に、解けなくても,sympyで解ける場合がありました。

# ChatGPT-3.5先生へ。２回目(**???わかりませんでした。???**)
```
次の初期値問題を解いてみる。
y1'=y1+y2,y1(0)=0
y2'=y2+1 ,y2(0)=0
```
数値的な微分方程式
...ステップサイズ h を調整することで解の精度を制御できます。

# Mathematicaで
いつの日か、実行してみたい。

# WolframAlphaで(できました。) 

https://www.wolframalpha.com/input?i=y1%27%28t%29%3Dy1%28t%29%2By2%28t%29%2Cy1%280%29%3D0%2Cy2%27%28t%29%3Dy2%28t%29%2B1%2Cy2%280%29%3D0&lang=ja

上と同じ。かっこ(t)なし。

https://www.wolframalpha.com/input?i=y1%27%3Dy1%2By2%2Cy1%280%29%3D0%2Cy2%27%3Dy2%2B1+%2Cy2%280%29%3D0&lang=ja

# sympyで
＞一階微分方程式系
＞一階微分方程式
勉強中です。
```python
# ver0.1
from sympy import *
var('s',real    =True)
var('t',positive=True)
y1,y2,Y1,Y2=map(Function,('y1','y2','Y1','Y2'))
def myLapDiff(f,fdash,fi):
     if   f==y1(t): Ys=Y1(s)
     else:          Ys=Y2(s)
     if   fdash==2: return s**2*Ys
     elif fdash==1: return s**1*Ys
     elif fdash==0: return      Ys
     else:          return print("#error myLapDiff")
def myLap(g):
     return laplace_transform(g,t,s)[0]
def myInvLap(g):
     return inverse_laplace_transform(g,s,t).evalf().simplify()
def myY2y(Ys):
     return myInvLap(apart(Ys))
eq1 =Eq(diff(y1(t)),y1(t)+y2(t)  )
eq1i=Eq(y1(0),0)
eq2 =Eq(diff(y2(t)),      y2(t)+1)
eq2i=Eq(y2(0),0)
print("#",eq1)
print("#",eq2)
print()
eqA =Eq(myLapDiff(y1(t),1,0),myLapDiff(y1(t),0,0)+myLapDiff(y2(t),0,0)         )
eqB =Eq(myLapDiff(y2(t),1,0),                     myLapDiff(y2(t),0,0)+myLap(1))
ans=solve( [eqA,eqB],[Y1(s),Y2(s)])
y1t=myY2y(ans[Y1(s)])
y2t=myY2y(ans[Y2(s)])
print("# y1(t)=",y1t)
print("# y2(t)=",y2t)
# Eq(Derivative(y1(t), t), y1(t) + y2(t))
# Eq(Derivative(y2(t), t), y2(t) + 1)

# y1(t)= t*exp(t) - exp(t) + 1.0
# y2(t)= exp(t) - 1.0
(st,en)=(-10,10)
plot(y1t,y2t,aspect_ratio=(1.0,1.0),xlim=(st,en),ylim=(st,en))
```
2本とも、原点を通過です。
![0png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/11d93fff-de2b-e247-fb94-d3db248f37f2.png)

# いつもの? sympyの実行環境と 参考のおすすめです。
(テンプレート)

https://qiita.com/mrrclb48z/items/00dd08b0317069be9342

# 参考

https://qiita.com/mrrclb48z/items/6b02ec9416ffd7f0c8c3
ORACLE MASTER Silver SQL 2019(1Z0-071-JPN)をオンラインで受験した話

# はじめに
Oracle Database SQL(1Z0-071)の試験を受けて、
ORACLE MASTER Silver SQL 2019の認定資格を取得できましたので備忘録として残そうと思います。
ちなみに正解率は91%でした。:raised_hands:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368839/e88a582e-4267-e7eb-f5c5-9deafba96371.png)

# 私のスキルレベル
業務でOracleを6,7年ほど使用していました。
…とはいえ業務システムで使用する簡単なSQLをたまに書くくらいです。DBAの方は全然です。

ORACLE MASTER系だと所持資格は以下のみです。
・ORACLE MASTER Bronze Oracle Database 11g

# 勉強方法・時間
1. 黒本を読み、知らなかった知識を記録しながら1周する。
1. Ping-tの問題をひたすら解く。
1. Ping-tで間違えた問題を記録する。
1. 黒本の模擬試験、Ping-tの模擬試験をやる。
1. 模擬試験で間違えた問題を記録する。

黒本はこれです↓
[オラクルマスター教科書 Silver SQL Oracle Database SQL](https://www.amazon.co.jp/dp/4798172367/)

記録はNotionに行っていました。
（最近使い始めましたがコレ便利ですね）

勉強期間は3週間ほどでした。
時間は40～60時間くらいかと思います。

# 初めてのオンライン試験に疲弊
近所にテストセンターがなかったので初めてOnVUEオンライン監督試験という形式で受験しました。
Webカメラで監視されながら自宅のPCで受験するというものです。
受験してみた結果、次回は遠くてもテストセンターで受けようと思いました。

### 環境づくりが大変だった
不正防止のため、手の届く範囲に物を置いてはいけないようなので片付けに時間がかかりました。
中には風呂場にノートPCを持ち込んで受験する人もいるようですね。

↓私はこんな環境で受験しました。
![IMG_1955.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368839/5fd243af-05ef-5c61-f500-fb23967e4748.jpeg)

試験直前に周辺環境の写真を撮影して送ったり、
Webカメラを手で持って周辺環境を写したりします。
環境によっては最悪の場合、部屋を替えてくれと言われることもあるようですが私は大丈夫でした。

「携帯電話とゴミ箱をもっと離してください。置き直した場所をWebカメラで写してください」
「PCケースの上に置いてあるものを確認させてください」
など、少々の指示はありました。


### 試験中の制約が多かった
* 他の人が写ったら失格
* 他の人の声が聞こえたら失格
* 顔がカメラ外に出たら失格
* 口元を手で隠すなどの怪しい仕草をしたら警告。連続したら失格

など試験中の制約があります。
考え事をするときに口を手で覆うのが癖になっているので神経を使いました。
本当はそこまで気にしなくてもいいのかもしれませんが、
もし高額な受験料がパーになったら…と神経質になってしまいました。

### 首が疲れた
問題のアプリケーションは全画面で表示され、
左上に問題、
右上に問題番号と残り時間、後で見返す用のチェックマーク、
右下に「次へ」「戻る」のボタンがあります。

27インチのモニタを使っていると
アッチを見たりコッチを見たりと視線移動量が多くて結構首が疲れました。
あんまり首を動かしていると怪しいとみなされて注意されるらしいです・・・

問題の文字の大きさは「Ctrl+"＋"」で変えられるようなので、
モニタと距離が取れればまだ良いかもしれません。
テストセンターが小さいモニタを使っている理由がわかりました。

↑これらの課題をクリアできる人、気にしない人にはオススメできます。

# 受験した感想
黒本、Ping-tによく似た問題がたくさん出るだろう、と勝手に楽観的に考えていましたが、
本番は問題文の言い回しなどが違っていて面食らいました。

似た問題は何問か出てきますが、大半は黒本などでは見たことのない問題でした。
でも問われている知識は共通しています。
黒本、Ping-tの問題を繰り返し解き、
各選択肢が正解／不正解である理由が述べられるくらい知識を付けておけば心配ないでしょうね。

# おまけ
この資格を取ればSQLに少し詳しくなれるかな？と
勉強を始める前は漠然と思っていましたが、いざ振り返ってみると思っていたより基礎的な部分が多かったです。
基礎を幅広く重点的に、という印象です。

ヒント句などのSQLチューニングとかウィンドウ関数とか出てきてくれると嬉しかったですが
そういった内容はありませんでした。別で勉強するしかないようです。
RTX1300のv6プラス(固定IP)環境下でIPv6を分割して複数LANに割り当てる

# はじめに
v6プラス(固定IP)環境において、IPv6のプレフィックスを分割し複数のLANインターフェースに設定する方法について記載する。

# 環境
* enひかりクロス (フレッツ光クロスコラボ)
    * IPv6 IPoE + v6プラス(IPv4 over IPv6接続) 固定IPサービス
* YAMAHA RTX1300 Rev.23.00.09

# 目標
`LAN3`をWANポートに設定し、`LAN1`と`LAN2`に分割したIPv6のプレフィックスを割り当てる。

# 問題点
v6プラス(固定IP)ではプロバイダから指定されたインターフェースIDで構成したIPv6アドレス[^1]をエンドポイントとして、IPv4 over IPv6トンネルを構築しなければならない。

[14.9 トンネルインタフェースの端点 IP アドレスの設定](http://www.rtpro.yamaha.co.jp/RT/manual/rt-common/tunneling/tunnel_endpoint_address.html) に記載されているようにローカルエンドポイントに任意のIPv6アドレスを指定することはできるが、フレッツ網から配布されるIPv6プレフィックスが変更された場合には対応できない。[^2] [^3]

またローカルエンドポイントを指定しなかった場合は上記ヘルプページにて、

> local を省略した場合は、適当なインタフェースの IP アドレスが利用される。

と記載されているが、その選択基準がヘルプページの記載から読み取れない。

## 適当なインターフェースの選択基準(RTX1300 Rev.23.00.09)
筆者の環境ではLAN3にWANポートを割り当てているとき、以下の優先度で選択される。

### LAN3にIPv6アドレスを割り当てている場合
* LAN3に割り当てたIPv6アドレス

### LAN3にIPv6アドレスを割り当てていない場合
* LAN1に割り当てたIPv6アドレス

# 設定例
かんたん設定からプロバイダ接続設定を作成した後、ipv6に関する設定を以下のように修正する。

## LAN3にIPv6アドレスを割り当てる場合

```
ipv6 prefix 1 dhcp-prefix@lan3::1:0:0:0:1/64
ipv6 prefix 2 dhcp-prefix@lan3::2:0:0:0:1/64
ipv6 lan1 address dhcp-prefix@lan3::1:0:0:0:1/64
ipv6 lan1 rtadv send 1 o_flag=on
ipv6 lan1 dhcp service server
ipv6 lan2 address dhcp-prefix@lan3::2:0:0:0:1/64
ipv6 lan2 rtadv send 2 o_flag=on
ipv6 lan2 dhcp service server
ipv6 lan3 address dhcp-prefix@lan3::[指定されたインターフェースID]/64
```


## LAN3にIPv6アドレスを割り当てない場合

```
ipv6 prefix 1 dhcp-prefix@lan3::1/64
ipv6 prefix 2 dhcp-prefix@lan3::1:0:0:0:1/64
ipv6 lan1 address dhcp-prefix@lan3::[指定されたインターフェースID]/64
ipv6 lan1 rtadv send 1 o_flag=on
ipv6 lan1 dhcp service server
ipv6 lan2 address dhcp-prefix@lan3::1:0:0:0:1/64
ipv6 lan2 rtadv send 2 o_flag=on
ipv6 lan2 dhcp service server
```
筆者はこの設定で運用している。

[^1]: インターフェースID以外にも57～64bitが`00`でなければならないようである。
[^2]: プレフィックスが変更されることは殆どないため、IPv6アドレスを固定値として設定するのも一つの解決策である。
[^3]: IPv6プレフィックスが変更された際に設定を更新するLuaスクリプトを作成する方法もある？(未検証)
リーダブルコード　第4章　美しさ　まとめ

- 「=」の位置を各行でそろえておくことで、タイプミスに気づくことができる
例）
a. 
    ```
    details = request.POST.get(`details`)
    location = request.POST.get(`location`)
    phone = equest.POST.get(`phone`)
    email = request.POST.get(`email`)
    url = request.POST.get(`url`)
    ```

    b. 
    ```
    details  = request.POST.get(`details`)
    location = request.POST.get(`location`)
    phone    = equest.POST.get(`phone`)
    email    = request.POST.get(`email`)
    url      = request.POST.get(`url`)
    ```
    a.よりもb.の方が、
    `phone = equest.POST.get(`phone`)`
    においてのスペルミス（`request`のはずが`equest`となっている部分）
    に気づきやすくなる

- 変数を定義する順番にも気を付ける必要がある
    例）以下のような変数定義があったとする
    ```
    details  = request.POST.get(`details`)
    location = request.POST.get(`location`)
    phone    = request.POST.get(`phone`)
    email    = request.POST.get(`email`)
    url      = request.POST.get(`url`)
    ```
    
    並べ方には、
    - 重要度順
    - アルファベット順
    などが挙げられる
    
    アルファベット順で並べると、
    ```
    details  = request.POST.get(`details`)
    email    = request.POST.get(`email`)
    location = request.POST.get(`location`)
    phone    = request.POST.get(`phone`)
    url      = request.POST.get(`url`)
    ```
    のようになる

- 開きかっこ、閉じかっこの位置を、プログラムごとに統一した方がよい
    括弧の位置を、
    ```
    class Logger {
      ...
    };
    ```
    なのか、
    ```
    class Logger 
    {
      ...
    };
    ```
    なのかを統一した方がよい
Struts2とMVC

# はじめに
Struts2が、どこでどう使用されているのかわからなかったので、Udemyのコースでわかりやすく説明されていた概要をまとめて記事にしました。なので、実際のコーディングなどの説明ではなく、MVCモデルと照らし合わせてStruts2がMVCのどこでどんな役割をしているのかを軽く触れた内容です。


## MVCモデルとは
プログラムの処理を「Model・View・Controller」の3つの役割に分けてコーディングを行うソフトウェア設計モデル
![MVC-Model.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335514/a48d6233-c742-7a64-43c8-4cf8247a3e83.png)

### MVCの各役割

<table>
  <thead>
    <tr>
      <th>名前</th> <th>説明</th>
    </tr>
  </thead>
  <tr>
    <td> Medel </td> 
    <td>
        データベースとやり取りする <br> 
        ビジネスロジックを実行する　</td>
  </tr>
  <tr>
    <td> View </td> 
    <td>
        ユーザーが画面で目にするもの <br> 
        UIを生成する
    </td>
  </tr>
  <tr>
    <td> Controller* </td>
    <td>
        ユーザーからのインプットを受け取る <br> 
        ModelとViewとやり取りする
    </td>
  </tr>
</table>

*Controllerに関する補足
ユーザーからのインプットはrequest parameterなどを受け取る
ModelとViewをやり取りするとは、データを画面に表示するために、Modelが扱ったデータを、Viewへ受け渡すなど。

# MVCモデルとStruts2の対応
<table>
  <thead>
    <tr>
      <th>MVCモデル</th> <th>Struts2</th>
    </tr>
  </thead>
  <tr>
    <td> Medel </td> <td>Service</td>
  </tr>
  <tr>
    <td> View </td> <td>JSP</td>
  </tr>
  <tr>
    <td> Controller </td> <td>Action</td>
  </tr>
</table>

## Struts2とは
概要図
![Struts2概要.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335514/bf65b349-1cd2-2f98-7e08-60d35dd0b8c1.png)

### ディベロッパーがやること
1\. Action classの作成
2\. JSP Pageの作成
3\. struts.xmlでアクションをマッピング

struts.xmlファイルは、Struts2の設定ファイル。

詳しいStruts2の導入方法は以下の記事が参考になります
[Struts2入門(2023年最新版)](https://qiita.com/Keichan_15/items/cf98f4ba9a61916047ce)

## リクエストの処理フロー
![ struts-architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335514/4a22f4fa-5ae8-4f1d-d95c-15782f483079.png)

### 補足
<table>
  <caption>用語集</caption>
  <thead>
    <tr>
      <th>名前</th> <th>説明</th>
    </tr>
  </thead>
  <tr>
    <td> Filter Dispacher </td> <td>Servlet filter　<br>Struts2では、StrutsPrepareAndExcuteFilterという</td>
  </tr>
  <tr>
    <td> Action class </td> <td>actionが呼ばれた時、デフォルトで、excuteメソッドが実行される。<br>excuteメソッドは、Action classのメインメソッド</td> 
  </tr>
  <tr>
    <td>  Interceptor </td> <td>アクションの前後で実行される<br>validation, ログメッセージ, パラメータ操作など、アクションの前処理や後処理を実行する。</td>
  </tr>
</table>