OmniAICreator/Qiita-1.07M huggingface dataset:
SwiftUIのListの背景色が灰色にならないようにする

SwiftUIのListの背景色が勝手に灰色になってしまって、ここ2日ほど困っていたのですがようやく解決できたのでメモしておきます。

```
Xcode 14.2
```

```swift
List {
    // do something here
}
.scrollContentBackground(.hidden) // <= 追加
```

このListはNavigationViewの下に入っていたのでNavigationViewを疑っていたのですが、違いました。NavigationViewを取り除いても灰色が消せなかったので、Listの方を疑いました。

[SwiftUIでNavigationViewのタイトルやテーブルビューの背景を変える](https://gist.github.com/takoikatakotako/4493a9fd947e7ceda8a97d04d7ea6c83)

他の解決策があるような気がして追加で調べると、記事も見つかりました（困っている間はこの記事に辿り着けなかった）。

[【SwiftUI】Listの背景色を変更する | DevelopersIO](https://dev.classmethod.jp/articles/swiftui-list-background-color/)

## References
1. [scrollContentBackground(_:) | Apple Developer Documentation](https://developer.apple.com/documentation/swiftui/text/scrollcontentbackground(_:))
2. [swift - iOS 16 SwiftUI List Background - Stack Overflow](https://stackoverflow.com/questions/72649907/ios-16-swiftui-list-background/72888510#72888510)
vue3 vite npm run build で 画像が見つからないエラー

npm run dev ならエラーにならないが、
npm run build だとエラーになる。

原因は以下のコード
```
<img src="/img/seiya.jpg">
```

画像が見つかりませんよエラー

```
[vite]: Rollup failed to resolve import "/img/seiya.jpg" from "/var/www/html/renkatu.club/resources/js/components/Home.vue?vue&type=script&setup=true&lang.ts".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
error during build:
Error: [vite]: Rollup failed to resolve import "/img/seiya.jpg" from "/var/www/html/renkatu.club/resources/js/components/Home.vue?vue&type=script&setup=true&lang.ts".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
    at onRollupWarning (file:///var/www/html/renkatu.club/node_modules/vite/dist/node/chunks/dep-79892de8.js:46368:19)
    at onwarn (file:///var/www/html/renkatu.club/node_modules/vite/dist/node/chunks/dep-79892de8.js:46138:13)
    at Object.onwarn (file:///var/www/html/renkatu.club/node_modules/rollup/dist/es/shared/node-entry.js:25149:13)
    at ModuleLoader.handleInvalidResolvedId (file:///var/www/html/renkatu.club/node_modules/rollup/dist/es/shared/node-entry.js:23784:26)
    at file:///var/www/html/renkatu.club/node_modules/rollup/dist/es/shared/node-entry.js:23744:26
```

まじかよ

# 解決策

https://laracasts.com/discuss/channels/vite/vite-cannot-find-images-on-build

# vite.configを以下のように書き換えるだけ

```
vue({
    // This is needed, or else Vite will try to find image paths (which it wont be able to find because this will be called on the web, not directly)
    // For example <img src="/images/logo.png"> will not work without the code below
    template: {
        transformAssetUrls: {
            includeAbsolute: false,
        },
    },
}),

```
GitHubのリポジトリを追加からPushまで

## 前書き
本記事は個人のメモ用です。<br>
何回も手順を間違ったので、毎回検索して作業するのも面倒になってきたから、メモを残すことにしました。

## はじめに
GitHubのサイトからリポジトリを作成済みを前提に書いています。<br>
まだ作成してない場合は先にGitHubのウェブサイトにアクセスして、リポジトリの新規作成を行って下さい。<br>
ここでは my-git-practice とします。

#### 1.名前とメールアドレスを登録する
初めてGitHubにアクセスする端末やリセットした端末には git config を実行し、名前とメールアドレスを登録します。<br>
```bash:bash
ユーザー名を登録
git config --global user.name "User"
メールアドレスを登録
git config --global user.email "User@sample.com"
```
登録した名前とメールアドレスは後ほど登録するリポジトリに公開されます。<br>
登録した名前とメールアドレスの確認は git config --global -l で確認出来ます。<br>
```bash:bash
$ git config --global -l
$ user.name=User
$ user.email=User@sample.com
```
#### 2.初期化
プロジェクトのディレクトリ下で git init を実行する
```bash:bash
$ git init
  hint: Using 'master' as the name for the initial branch. This default branch name
  hint: is subject to change. To configure the initial branch name to use in all
  hint: of your new repositories, which will suppress this warning, call:
  hint: 
  hint:   git config --global init.defaultBranch <name>
  hint: 
  hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
  hint: 'development'. The just-created branch can be renamed via this command:
  hint: 
  hint:   git branch -m <name>
  Initialized empty Git repository in /home/kibwwen/my-git-practice/.git/
```
#### 3.リポジトリにファイルの追加
```bash:bash
$ git add .
又は
$ git add ファイル名
```
#### 4.最初のコミット
```bash:bash
$ git commit -m "first commit"
git commit -m "コミットのメッセージ"
```
#### 5.ブランチの作成と切り替え
```bash:bash
$ git branch -M main
```
#### 6.リモート先の追加
```bash:bash
$ git remote add origin git@github.com:アカウント名/my-git-practice.git
```
#### 7.GitHubにプッシュする
```bash:bash
$ git push origin main
```
プッシュ出来ない場合はSSHが設定したか、パスワード間違ってませんかを確認して下さい。
計算量の見積もりについての学びをまとめる(1)

# はじめに
&emsp;Paizaの問題で実行時間オーバーで突破できない問題が出てきてしまい、悔しいのでアルゴリズムを勉強しようと思い立ち、「**問題解決のためのアルゴリズムx数学が基礎からしっかり身につく本**」で勉強中。学びをメモ程度でもアウトプットしてまとめたいので書く。
&emsp;今回は**計算量について、その見積もり**、について学んだことを書いていく。
# 目次
[1.計算量とは](#1-計算量とは)
[2.定数時間](#2-定数時間)
[3. 線形時間](#3-線形探索)
[4. 全探索](#4-全探索)
[5. まとめ](#5-まとめ)


# 1. 計算量とは
&emsp;結論、答えにたどり着くまでの計算回数。
ただし正確に何回と求めるわけではなく、「**ざっくりN回**」って感じで求める。よく***O(N)*** のランダウ記法で見かけるよね。
# 2. 定数時間
&emsp;例えば「1+1は？」のように「**ざっくり1回の計算**」のようなものは定数時間。***O(1)*** の記法でよく見ますね。
下記の例題は入力の処理と計算し出力の処理で正確に1回ではないが**ざっくり1回**なんで定数時間です。
(例)
「整数Nが入力として入った時$2N+1$の答えは何ですか？」
```diff_python
N = int(input())
print(2*N+1)
```
# 3. 線形探索
&emsp;一言でいうと「**for１個で済む処理**」
(例)
「$1 \leqq N \leqq 100$までで$2$で割り切れる数字はいくつありますか？」
```diff_python
counter = 0
for n in range(1, 101):
    if n % 2 == 0:
        counter += 1
print(counter)
```
# 4. 全探索
&emsp;線形探索と違い「**forが二重三重になっている**」そのため計算量が**指数関数的**に増える。
個人的に実装の際に直感的でわかりやすくfor使いがちになっちゃうけど**データ量の多いタスク**ではダメだよねってことで気を付けたい。
&emsp;forでも実行時間に問題なければいいのかもだけどやっぱより速くしたいよな。。。
(例)
「二枚のカードの値を組み合わせて合計Sになるものを探そう」
```diff_python
# 前提としてカード情報がAとBの変数に配列で、合計値Sはintとして渡ってくることとする
flag = False  # 見つかればTrueにする
for a in A:
    for b in B:
        if S == (a+b):
            flag = True
if flag:
    print('Yes')
```
# 5. まとめ
&emsp;**結果、全探索遅くね？**(ただしデータ量との兼ね合いみようね)
今まで**for**いっぱいもりもりで書いちゃってたので反省、反省(-_-;)
次は残りの二分探索やほかの計算量について書こうと思う。
その次から基本的なアルゴリズムとステップアップしていこう。

# 追記
&emsp;続きを書きました。よければ見てください。
- **[続きの記事](https://qiita.com/yuyatuta/items/930558528b1c6b04dba9 "続きの記事")**
Excel VBA（マクロ）でセルの内容を声を変えて読上げ -その７- XMLタグについて

[Excel VBA（マクロ）でセルの内容を声を変えて読上げ -その１](https://qiita.com/tom-sobue/items/aac051de117a45f9fecf)
`Windowsに標準で組み込まれている読上げの声で、Harukaの声以外を使って読上げる方法 `
[Excel VBA（マクロ）でセルの内容を声を変えて読上げ -その２](https://qiita.com/tom-sobue/items/319c1943df9dd30c081a)
`読上げ内容を音声ファイルに保存する方法`
[Excel VBA（マクロ）でセルの内容を声を変えて読上げ -その３](https://qiita.com/tom-sobue/items/3e02e7569cfbe8a90f12)
`スピード、ピッチ（声の音程）、更には、強調の指示方法`
[Excel VBA（マクロ）でセルの内容を声を変えて読上げ -その４](https://qiita.com/tom-sobue/items/e51cbdec59af545b232a)
`実際のシートに書いた内容で読上げする事例`
[Excel VBA（マクロ）でセルの内容を声を変えて読上げ -その５](https://qiita.com/tom-sobue/items/60573cd3c0e786d82e69)
`シートに書いた内容を録音（音声ファイルに保存する）事例`
[Excel VBA（マクロ）でセルの内容を声を変えて読上げ -その６](https://qiita.com/tom-sobue/items/fd35a4259bfb7291dc1c)
`読上げる内容を調整し易くする事例`

について、紹介しました。

今回は、XMLタグについては、[**その３**](https://qiita.com/tom-sobue/items/3e02e7569cfbe8a90f12)で説明しましたが、もう少し説明します。

現在、一般的になっているのが、
[W3C(World Wide Web Consortium)のSSML(Speech Synthesis Markup Language)](https://www.w3.org/TR/speech-synthesis11/)
という規格です。

Windowsに組み込んであるSpeechAPIは、この前身で開発されたものを見直したものです。
MicrosoftもWeb上では、SSMLがサポートされていますが、ここで説明している内容は
レガシー(長年使っているので捨てられない)としているものです。

使用するXMLは、[Microsoft Speech API (SAPI) 5.3](https://learn.microsoft.com/ja-jp/previous-versions/windows/desktop/ms723627(v=vs.85)) の中の
[**XML TTS Tutorial (SAPI 5.3)**](https://learn.microsoft.com/ja-jp/previous-versions/windows/desktop/ms717077(v=vs.85)) 
に書かれています。

|タグ|属性|事例|説明|
|:--:|:--:|:--:|:--:|
|Volume|level|\<Volume level="100"> \</volume>|音量調整で0～100で指定|
|Rate|speed|\<rate speed="-3"> \</rate>|読上げ速度を±10で加減速|
|Pitch|middle|\<pitch middle="6"> \</pitch>|声の高さを±10で上げ下げ|
|emph||\<emph> \</emph>|強調して話す|
|spell||\<spell> \</spell>|スペル読上、日本語はかなで読上|
|silence|msec|\<silence msec="500"/>|ミリ秒指定で黙る|

*以下省略します。*

この書式が分かっていれば、Excelシートのセルに読上げさせる内容にも直接書くこともできます。
|   |D   |E   |F|
|:-:|:--:|:--:|:--:|
|1  |話し手|内容|1|
|2  |一郎  |いつもお世話になっています。\<emph>早急なご対応を\</emph>お願いします。||
|3  |あゆみ|ありがとうございます。\<pitch middle="-5">でも、遠慮します。\</pitch>||
|4  |      | ||

2行目の例は、「早急なご対応を」の部分を強調し、3行目の例では、「でも遠慮します」を低い声で言います。

読上げソフトの[**Balabolka**](http://www.cross-plus-a.com/jp/balabolka.htm)も、このSAPIを使っていますので、同じように途中でタグを記述すると、対応してくれます。

Excelのシートにしておけば、次の行に分けて書けますので、便利かと思います。

[その８ -選択範囲を読上げる- へ続く](https://qiita.com/tom-sobue/items/9c68275b925627c378ed)
Rubyでパフォーマンス計測

# はじめに

Rubyでコードのパフォーマンスを計測する際に便利なツールである`benchmark`について解説します。`benchmark`メソッドを使用することで、コードの実行時間を簡単に計測できます。

# 目次

1. `benchmark`メソッドの使い方
2. 複数のコードブロックを比較する
3. 測定回数を指定してパフォーマンスを計測する

## 1. `benchmark`メソッドの使い方

以下の例では、`benchmark`メソッドを使用して、実行時間を計測しています。

``` ruby
benchmark('Benchmarking: unzip') do
    #測定したい処理を実装
end
```

実行結果は以下のように表示されます。

```
       user     system      total        real
Benchmarking: unzip  0.010000   0.000000   0.010000 (  0.011987)
```

出力の内容は以下の通りです。

- ラベル "Benchmarking: unzip"
- ユーザーCPU時間 (この例では 0.010000秒)
- システムCPU時間 (この例では 0.000000秒)
- 合計CPU時間 (ユーザーCPU時間 + システムCPU時間、この例では 0.010000秒)
- 経過実時間 (この例では 0.011987秒)

## 2. 複数のコードブロックを比較する

複数のコードブロックのパフォーマンスを比較する場合、`Benchmark.bm`または`Benchmark.benchmark`を使用できます。以下の例では、`task1`と`task2`のパフォーマンスを比較しています。

```ruby
require 'benchmark'

array = (1..10000).to_a

task1 = Proc.new { array.count(&:even?) }
task2 = Proc.new { array.select(&:even?).size }

Benchmark.bm do |x|
  x.report("Array#count:") { task1.call }
  x.report("Array#select + size:") { task2.call }
end
```

実行結果は以下のように表示されます。

```
       user     system      total        real
Array#count:        0.001000   0.000000   0.001000 (0.001000)
Array#select + size: 0.002000   0.000000   0.002000 (0.002000)
```

出力の各部分は以下の通りです。

- ラベル（この例では "Array#count:" と "Array#select + size:"）
- ユーザーCPU時間（この例では 0.001000秒 と 0.002000秒）
- システムCPU時間（この例では 0.000000秒 と 0.000000秒）
- 合計CPU時間（ユーザーCPU時間 + システムCPU時間、この例では 0.001000秒 と 0.002000秒）
- 経過実時間（この例では 0.001000秒 と 0.002000秒）

この出力から、`Array#count`メソッドを使った方法（`task1`）が、`Array#select`と`Array#size`メソッドを使った方法（`task2`）よりも高速であることがわかります。

## 3. 測定回数を指定してパフォーマンスを計測する

測定回数を指定してパフォーマンスを計測する場合、`Benchmark.bmbm`または`Benchmark.measure`を使用できます。以下の例では、`task1`と`task2`を1000回実行し、そのパフォーマンスを計測しています。

```ruby
require 'benchmark'

array = (1..10000).to_a
n = 1000

task1 = Proc.new { array.count(&:even?) }
task2 = Proc.new { array.select(&:even?).size }

Benchmark.bm do |x|
  x.report("Array#count (#{n}回):") { n.times { task1.call } }
  x.report("Array#select + size (#{n}回):") { n.times { task2.call } }
end
```
GitHub Actions で workflow_dispatch と workflow_call で処理を分岐する

# はじめに

GitHub Actions の機能でワークフローの再利用があります。ワークフローの再利用では、ワークフローから別のワークフローを呼び出すことができます。

https://docs.github.com/ja/actions/using-workflows/reusing-workflows

その際に、呼び出された側のワークフローで別のワークフローから呼び出されたのか、もしくは、ワークフローを単体実行したのかで分岐したいことがあったため、そのやり方を記載します。

# やり方

GitHub Actions では、実行時にコンテキストから様々な情報を取得することができます。

https://docs.github.com/ja/actions/learn-github-actions/contexts

その中に、`github.event.workflow` というキーが存在します。この値には、workflow のファイルパスが記載されています。

呼び出し方によって呼び出された側のワークフローでは、以下のような値が取得できます。（workflowA から workflowB を呼び出す場合）

- workflowB を直接実行（`workflow_dispatch`）した場合の `github.event.workflow`
    - workflowB のファイルパス（`.github/workflows/workflow-b.yaml`）
- workflowA から実行（`workflow_call`）した場合の `github.event.workflow`
    - workflowA のファイルパス（`.github/workflows/workflow-a.yaml`）

これによって処理やステップを分岐することができます。

例えば、workflowB を直接実行した際のみステップを実行したい場合は、以下のような条件を追加します。

```
if: github.event.workflow == '.github/workflows/workflow-b.yaml'
```

`github.event_name` もあるので、こちらでも分岐できないか試してみましたが、workflowB を直接実行した場合も、workflowA から実行した場合も、`workflow_dispatch` と同じ値になっており、分岐に利用できませんでした。

# type: environment について

実際には、以下のように同じ名前で input を定義することで、分岐なく同じワークフローを利用できるかと思いますが、`type: environment` は `workflow_dispatch` のみにしか存在しないため、これを利用している場合、差を吸収するステップを追加する必要があるかと思います。

```yaml
on:
  workflow_dispatch:
    inputs:
      input1:
        required: true
        type: string    
  workflow_call:
    inputs:
      input1:
        required: true
        type: string
```

environment に入っている値（environment_name）は文字列としてそのまま利用できますが、上記のような差分となってしまいますので、`workflow_call` する際には、避けておいた方が良さそうです。

# まとめ

方法は色々ありそうですが、`github.event.workflow` を確認することで、ワークフローの実行方法で分岐することができました。
富士通メインフレームは○×□が不便　〜PFD〜

富士通のPFDは、IBMの[ISPF](https://ja.wikipedia.org/wiki/ISPF)の前身である[SPF](https://ja.wikipedia.org/wiki/SPF/PC)互換として提供されたと理解しているのですが、今回はこのPFDについてです。

---
#### PFD-1(BROWSE)
ISPF-1はVIEWですが、PFD-1はBROWSEのままです。
ご存知のようにVIEWはメモリ上での更新はできますが、データセットに上書き保存はできません。保存できないのはBROWSEと同じですが、一時的に修正できるところが魅力です。

#### OUTLIST
ISPFでは実行時のJCLを[SPOOL](https://ja.wikipedia.org/wiki/スプーリング)から取り出し、SUBMIT時のJCLを復元できるのが羨ましいです。

#### PFD-3.4(CATALOG), PFD-3.7(VTOCLIST)
PFD-3.4ではカタログされたデータセット一覧が表示されます。
PFD-3.7では指定したVOLUMEにあるデータセット一覧が表示されます。
どちらも表示のみで、データセットを選択してEDITやBROWSE、VIEWにすることはできません。
カタログされたデータセット一覧からEDIT等のアクションが可能なPFDＥというものが、PFDとは別にあります。
PFDはまずアクション次にデータセットという順ですが、PFDEは逆です。

#### PFD-3.8(OUTLIST)
PFD-3.8は、SPOOLに出力された実行結果をOUTPUTコマンドでデータセットに出力しこれをBROWSEで表示しているようなものです。この時のデータセットのレコード形式が[FBS](https://ja.wikipedia.org/wiki/データセット_(IBMメインフレーム)#レコードフォーマット_%28_Record_Format%2C_RECFM_%29)（固定長標準形式）、レコード長は137バイトです。
そのため、137バイトより長いレコードは画面上２行に分割表示されます。日本語（2バイト文字）の部分で２行に分割されると２行目の先頭に表示されるのは日本語ではなく文字化けになります。当該行にX’28’(z/OSはX'0E')がないからです。

---
富士通メインフレームはIBM互換路線を止めたため、このような機能差が生じているのだと思います。当時富士通はProprietaryという言葉を使ってマスコミに説明していました。
Colossal-AIをGoogleColaboratoryで動作させてみる

# はじめに

今の所、チャットの行うところまでできていません。
なんとかトレーニングさせるところまではできました。
色々、バージョンアップが行われているようなのでその辺りで詰まった箇所を書いていこうかと思います。
（ベースとなる記事は https://qiita.com/walnut-pro/items/32f8fb04645a36daea93 ）

# ハマった箇所と治し方

## 'ColoInitContext' from 'colossalai.zero' 

colossalai.zeroを含む必要なモジュールがインストールされていないようです。

__解決方法__
ColossalAIのフォルダに移動してpip　installを行いましょう
[元記事](https://github.com/hpcaitech/ColossalAI/issues/3447)
```
%cd /content/drive/MyDrive//work/ColossalAI/
pwd = %pwd
print(pwd)
!pip install .
```

## ModuleNotFoundError: No module named 'colossalai._analyzer'

ある更新から必要なファイルがなくなったそうです。

__解決方法__
site-package（多分、Pythonが読み込むライブラリが入っているフォルダ）に必要なファイルをコピーする
[元記事](https://github.com/hpcaitech/ColossalAI/issues/3540)
```

# https://zenn.dev/tamanobi/articles/7a4608992548dd
# 自分の環境のsite-packageを検索
import site
site.getsitepackages()
%cd /usr/local/lib/python3.10/dist-packages/colossalai/

# https://qiita.com/mriho/items/42109231d25e7a0ce8c1
# フォルダの中身を確認
%ls

# 必要なファイルをコピー
%cp -r /content/drive/MyDrive/work/ColossalAI/colossalai/_analyzer/ .

# コピーされたか確認
%ls
```
EC2の起動ができない？必要な権限はこれ！

# はじめに
EC2の起動ができないという事象があったので、必要な権限をまとめていきます。
とりあえず多めに権限つけておけば？というのでも開発環境はいいかもですが、本番環境などで、起動停止権限だけ付与したいよという方は必須です。

# 普通に必要な権限
以下です。
Describeが必要かは状況によりけりです。
```
"ec2:DescribeInstances"
"ec2:StartInstances"
"ec2:StopInstances"
```

この場合でも起動できないという事象が発生します。
それはEBSを暗号化しているケースです。
次に、EBSを暗号化しているケースに必要な権限を紹介します。

# EBSを暗号化している場合に追加で必要な権限
以下を追加します。
```
"kms:Encrypt"
"kms:Decrypt"
"kms:ReEncrypt*"
"kms:GenerateDataKey*"
"kms:DescribeKey"
```

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/key-policy-requirements-EBS-encryption.html

ところが・・・・
この権限で起動しようとすると、EC2が一瞬起動するものの、すぐに停止状態になるという事象が発生します。
調査したところ、以下の権限も追加で必要とのこと。
```
"kms:CreateGrant"
```
CreateGrantとは、KMSキーの仕様を指定したプリンシパルつまり別のサービスに使用を許可するということです。EC2は、KMSで暗号化されたEC2インスタンスを起動する際に、CreateGrantにより、EBSにKMSキーの使用を許可しているので必要ということですね。

https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/grants.html

# 参考ポリシー
```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "ec2:DescribeInstances",
        "ec2:StartInstances,
        "ec2:StopInstances"
      ],
      "Resource": "arn:aws:ec2:XXX",
      "Effect": "Allow"
    },
    {
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "arn:aws:kms:XXX",
      "Effect": "Allow"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kms:CreateGrant"
      ],
      "Resource": [
        "arn:aws:kms:XXX"
      ],
      "Condition": {
        "Bool": {
          "kms:GrantIsForAWSResource": true
        }
      }
    }
  ]
}
```

# まとめ
CreateGrantが必要なのをよく忘れがちです。
EC2を起動する際にはCreateGrantが必要！覚えておきます。
弾性棒に係る不静定系の力学 基本例題2.11 P38 「材料力学演習(20221021)」をsympyでやってみた。

# オリジナル
基本例題2.11 P38
http://zairikiweb.starfree.jp/zai_enshuh/zai_enshuh_ver.3.3.pdf#page=43

「材料力学演習(20221021)一括(ver.3.3)」を勉強したい。＞sympy
https://qiita.com/mrrclb48z/items/c3274daf5f7a99cfe027#%E4%BD%9C%E6%A5%AD%E4%B8%AD%E7%A7%81%E3%81%AE%E8%A7%A3%E7%AD%94sympy

# sympyで
```python
from sympy import *
N1,N2  =symbols('N1  N2' ,real=True)
P      =symbols('P'      ,real=True)
l      =symbols('l'      ,real=True) 
A1,A2  =symbols('A1  A2' ,real=True)
EE1,EE2=symbols('EE1 EE2',real=True)
myTikara  =Eq(2*N1+N2      ,2*P)
myHenkaryo=Eq(N1*l/(A1*EE1),N2*l/(A2*EE2))
ans=solve([myTikara,myHenkaryo],(N1,N2))
print("#",ans)
#
N1=P*(A1*EE1)/(2*A1*EE1+A2*EE2)
N2=P*(A2*EE2)/(2*A1*EE1+A2*EE2)
print("#?????",(2*N1+N2).simplify())
print("#?????",(N1*l)/(A1*EE1)-(N2*l)/(A2*EE2) )
# {N1: 2*A1*EE1*P/(2*A1*EE1 + A2*EE2), N2: 2*A2*EE2*P/(2*A1*EE1 + A2*EE2)}
#????? P
#????? 0
```
①私の環境は,pycharmです。
②よく聞くのは、Jupyterです。
③web上で、上記のソースを「SymPy Live shell」に、コピー貼り付けでもできました。
黒背景の右上に、マウスを移動すると、コピーマークが発生します。
???　タブレット環境で、コピー貼り付けが実行できませんでした。???

https://live.sympy.org/

# Mathematicaで
勉強中

# 作図
勉強中
GitHub Educationに登録してGithub copilotを使えるようにした

Github Educationの登録が結構面倒で、避けていたんだけど、「Github copilot使えるなら頑張るか！」
と思い腰を上げた。

使えるようになるのに、審査に10回くらい落ちたので2023年5月時点でどのように通したかを記録する。
まず参考にしたサイト
https://inouelog.com/github-student-id/
このサイトで、学生書に英語表記の
・大学名
・氏名
・有効期限をかけ
と書いてある。
同様に学生書を取り込んで英語で情報を追記したが全然通らなかった。

そこからさらに自分がやったことは、
・なんちゃって国際学生証を使う
・画像アップロードを使わずLiveカメラで見せる
この２つでなんとか通過した。

## ■なんちゃって国際学生証を使う
大学ごとに学生証のレイアウトは違う。
ひょっとして自分が所属している大学の学生証は通りにくいデザインなのではないだろうか？
という疑心暗鬼に囚われ始めるので、固定のデザインのものを使える。
そして、審査に使われていない日本語の有効期限やら大学名が書かれていないのできっと解析も楽になるだろう。
なんちゃって国際学生証は、
https://cocosho.com/isic-apply/
このサイトで発行できる。しかし本当に発行してしまうと年1万円ていどお金がかかり、それだったら普通にGithubのProに加入できてしまう。
このサイトは、学生書を作っていく過程で発行予定のカードを画像で画面に表示してくれる。
なのでその画像をスクリーンショットでいただいてそのまま画像として使用した。



## ■画像アップロードを使わずLiveカメラで見せる
こちらは、スマホに画像を表示して画面いっぱいに表示してMaxのface　Time HDで映した。
本来の画像のアップロードよりも画質が悪くなるだけで同じものを見せているのだが、Liveでの認証の方が信憑性が高いらしい。
【ChatGPT】エンジニアの生産性を爆上げする活用術

**ChatGPTを使ってエンジニアの生産性を爆上げする活用術**をまとめました！

今回はGPT-4を使用しています。
# コードの生成
ChatGPTにやりたいことを伝えるだけで良い感じのコードを書いてくれます。

試しに「はてなブックマークの昨日の人気記事TOP10をスクレイピングするコード」の生成をお願いしてみたところ、1分かからないくらいでサンプルコードを生成してくれました！

![スクショ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/a9c15358-01f4-974e-25cc-f0c491e50fe3.png)

ちなみに、コードが長くなる場合は会話の途中で途切れてしまいますが「続けて」と言えば続きを書いてくれます。

# エラーの原因特定

上で作成してもらったコードですが、エラーが出たのでエラーの原因を特定してもらいました。

![FireShot Capture 002 - New chat - chat.openai.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/7f1b44fe-45e7-37c3-7ddd-bf15c0fed429.png)

最初から正しいコードを書いてくれよというのはさておき、エラーメッセージを貼り付けるだけで原因特定と修正コードを教えてくれるのはありがたいです。

何より自分の非を認めて謝れる部分も素晴らしい

これまで時間のかかっていたエラーの原因特定ChatGPTを使うことでは大幅に時間短縮できそうです。

今回はChatGPT自身が書いたコードだったのでスムーズでしたが、自分が書いたコードのエラーの原因を特定してもらうときはもう少し状況を詳細に伝えるとより良い回答が返ってきます。

# コードレビュー

コードレビューもお願いできるので試してみました。

![FireShot Capture 003 - New chat - chat.openai.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/d10a4986-53e5-339d-eb56-ea066e35ec83.png)
今回は自作自演も良いところですが、先ほどChatGPTに生成してもらったコードのレビューをお願いしたところ、良い感じに修正してくれました。

最初からそのコードで書いてくれよというのはさておき、レビューをするだけでなくコードの修正・改善までやってくれるのはすごいですね。

近いうちにレビュアーは要らなくなりそうです。

# コードの解説

コードの解説なんかもお願いできます。
![FireShot Capture 005 - New chat - chat.openai.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/d7ad11f7-7d3c-9152-f204-d546224b954b.png)
ちゃんとドキュメントの残っていないコードを読んで理解するのは時間がかかるので、ここら辺を助けてくれるのはありがたいです。

# コメント追加

コードの解説ができるくらいなので、コメント追加も当然できます。
![FireShot Capture 004 - New chat - chat.openai.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/5df46d06-f456-433d-e70f-eabf2e187ab0.png)
自分が書いたコードにコメントを追加してもらうのはもちろん、他人が書いたコードにもコメントを追加してくれるので、コードの理解が容易になります。

日本語でも英語でもお願いできます。

# リファクタリング

リファクタリングも文句を言うことなくやってくれます。
![FireShot Capture 006 - New chat - chat.openai.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/7a436db0-fd18-e8f2-864b-e7a349bc69a1.png)

これで世の中から汚いコードを一掃できますね。

# バグの修正
なんとコード中からバグを発見することもできます。

![FireShot Capture 007 - GA APIバックアップ方法 - chat.openai.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/c63bd4f1-13e6-9d60-e37e-7db269759756.png)
今回は簡単なバグなのですぐ直してもらえましたが、実際にはもう少し細かく状況を伝えると複雑なコードでもバグを発見してもらえる可能性が上がります。

# 関数名の作成
地味に考えるのがめんどくさい関数名の提案もしてもらえます。
![FireShot Capture 005 - New chat - chat.openai.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/ad7417dc-a6d6-be89-820f-2510b33809e2.png)
複数の候補とその名前の由来も出してもらうこともできるので、その中から良さげなのを選ぶこともできます。

# おまけ
2023年4月末頃から一部のユーザーにアルファ版の利用が開始したChatGPTの公式プラグイン「code interpreter」はもっとヤバいです....！

このプラグインを使うとChatGPTが提供するプラグインの1つで、このプラグインを利用することで、ChatGPT上でPythonを使ったコードの実行や、ファイルのアップロード・ダウンロードができるようになります。

詳細や始め方は以下の記事を参考にしてください

https://generativeinfo365.com/?p=178

https://generativeinfo365.com/?p=192
Gitで不要なローカルブランチを削除する方法

## はじめに
gitで、ローカルに変更ごとにブランチを作成して実装していく中で、使わなくなったローカルのブランチを一気に削除するため、よく使うコマンドがあります。
それをメモのために記しておきます。

## 結論
結論からいうと、こちらのコマンドです。
今いるブランチ以外のローカルのブランチを削除してくれます。
```
git branch | xargs git branch -D
```

## 解説
一応順を追って、解説しておきます。
1. `git branch`
このコマンドは、リポジトリ内のすべてのローカルブランチのリストを表示します。
2. `|`
この記号は、パイプと呼ばれます。パイプは、一つのコマンドの出力を別のコマンドの入力として渡すために使用されます。この場合、`git branch` の出力（ブランチ名のリスト）が次のコマンド `xargs git branch -D` の入力として渡されます。

3. `xargs`
このコマンドは、標準入力から受け取ったデータを、引数として別のコマンドに渡すために使用されます。

4. `git branch -D`
 このコマンドは、指定されたブランチを強制的に削除します。`-D` オプションは、強制的に削除するためのオプションで、まだマージされていないコミットがあってもブランチを削除します。
`-d` オプションでは、マージされていないコミットがある場合は削除を拒否しますが、`-D` オプションでは、マージされていないコミットがあってもブランチが削除されます。

## 終わりに
何かの参考になれば幸いです。

## 参考記事

https://qiita.com/mather314/items/a1536c52a2eb0426b2b5
各国の名目GDPの推移（静的グラフ）

各国の名目GDPデータをWorld Bankから取得してグラフ化するpythonプログラムがとりあえずできたので、備忘録として保存。

データの取得はwbdataを使いたかったが、どうしてもうまくいかなかったので、それは別の機会に。

グラフは、matplotlib.pyplotを使った静的なグラフ。plotlyを使ったインタラクティブなグラフも別の機会に。


```python
import requests
import json
from datetime import datetime
import pandas as pd
import matplotlib.pyplot as plt

def fetch_gdp_data(country_code):
    gdp_data = {}
    for page in range(1, 3):  # ページを指定してデータを取得
        url = f"https://api.worldbank.org/v2/country/{country_code}/indicator/NY.GDP.MKTP.CD?format=json&page={page}"
        response = requests.get(url)
        data = json.loads(response.text)
        
        for entry in data[1]:
            date = datetime.strptime(entry["date"], "%Y")
            value = entry["value"]
            if value is not None:
                gdp_data[date] = value
                
    return pd.Series(gdp_data)

# 国のISOコードを設定（G7＋中印）
countries = {
    'USA': 'United States',
    'CHN': 'China',
    'JPN': 'Japan',
    'DEU': 'Germany',
    'IND': 'India',
    'GBR': 'United Kingdom',
    'FRA': 'France',
    'ITA': 'Italy',
    'CAN': 'Canada',
}

# データフレームの作成
gdp_data = pd.DataFrame({code: fetch_gdp_data(code) for code in countries.keys()})

# インデックスを datetime 型に変換
gdp_data.index = pd.to_datetime(gdp_data.index)

# 欠損値の処理
gdp_data_filled = gdp_data.fillna(method='ffill').fillna(method='bfill')

# グラフを描画
plt.figure(figsize=(14, 8))
for country in countries:
    plt.plot(gdp_data_filled[country], label=countries[country])

plt.title('Nominal GDP (current USD) of G7 countries, China, and India (1960-2021)')
plt.xlabel('Year')
plt.ylabel('GDP (current USD)')
plt.legend()
plt.grid()
plt.show()

```

Google Colabでこのコードを実行すると、以下のグラフが出来上がった。

![nominal GDP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3305624/dda1e52d-ed2b-d5ef-9072-989a95e3ee7b.png)
【Flutter】ローカルにファイルを保存したり読み込んだり

# ローカルファイルに書き込む

```dart
void write() async {
  final directory = await getApplicationDocumentsDirectory();
  final path = directory.path;
  final file = File('$path/hoge.txt');

  // ファイルがなかった時だけ書き込む
  if (!await file.exists()) {
    await file.create();
    await file.writeAsString('aiueo');
  }
}
```

# ローカルファイルから読み込む

```dart
void read() async {
  final directory = await getApplicationDocumentsDirectory();
  final path = directory.path;
  final file = File('$path/hoge.txt');

  // ファイルがあった時だけ読み込む
  if (await file.exists()) {
    final data = await file.readAsString();
    print(data);
  }
}
```

# これらを使うにあたって
## pubspec.yaml を修正する
`getApplicationDocumentsDirectory()` を使用するには `path_provider` パッケージが必要なので、 `pubspec.yaml` に

```yaml
dependencies:
  flutter:
    sdk: flutter
  path_provider: ^2.0.14
```

のように `path_provider` を追記する必要がある
バージョン部分は [path_provider](https://pub.dev/packages/path_provider) などを見て設定する

## import文の追加
`getApplicationDocumentsDirectory()` を使うには

```dart
import 'package:path_provider/path_provider.dart';
```

が、

`File()` を使うには

```dart
import 'dart:io';
```

が、必要なのでそれぞれ記載する

# ちょっと補足

`path_provider` には `getApplicationDocumentsDirectory()` の他にも用途に応じて様々なディレクトリパスを取得できるメソッドが用意されている。

[path_provider library](https://pub.dev/documentation/path_provider/latest/path_provider/path_provider-library.html) を見て用途に応じたメソッドを使い分けるのが良さそう
(なのですが、、明確な違いがよくわからずなので割愛。。。)
Kotlinでfor文を実装してみた

# 概要
Kotlinでfor文を実装してみました。以下のページを参考にしました。
https://hirauchi-genta.com/kotlin-for/

# ソースコード
for文で使う構文の動作を確認してみました。
```hello-for.kt
fun main() {
    for(i in 3..8){
          println("(A) Hello, World!: "+i)
    }
    for(i in 3 until 8){
          println("(B) Hello, World!: "+i)
    }
    for(i in 3 until 8 step 2){
          println("(C) Hello, World!: "+i)
    }
    for(i in 5 downTo 0){
          println("(D) Hello, World!: "+i)
    }
    val list = arrayOf("みかん", "りんご", "もも")
    for( i in list ){
          println("(E) Hello, World!: "+i)
    }
    for( i in list.indices ){
          println("(F) Hello, World!: "+i+" : ${list[i]}")
    }
    for((index, value) in list.withIndex()){
          println("(G) Hello, World!: $index : $value")
    }
    val map = mapOf("りんご" to 80, "みかん" to 100, "メロン" to 1000)
    for((name, price) in map){
          println("(H) Hello, World!: $name は $price 円です。")
    }
}
```

# 実行結果
コンパイルして、実行してみました。
```
$ kotlinc hello-for.kt -include-runtime -d hello-for.jar
$ java -jar hello-for.jar 
(A) Hello, World!: 3
(A) Hello, World!: 4
(A) Hello, World!: 5
(A) Hello, World!: 6
(A) Hello, World!: 7
(A) Hello, World!: 8
(B) Hello, World!: 3
(B) Hello, World!: 4
(B) Hello, World!: 5
(B) Hello, World!: 6
(B) Hello, World!: 7
(C) Hello, World!: 3
(C) Hello, World!: 5
(C) Hello, World!: 7
(D) Hello, World!: 5
(D) Hello, World!: 4
(D) Hello, World!: 3
(D) Hello, World!: 2
(D) Hello, World!: 1
(D) Hello, World!: 0
(E) Hello, World!: みかん
(E) Hello, World!: りんご
(E) Hello, World!: もも
(F) Hello, World!: 0 : みかん
(F) Hello, World!: 1 : りんご
(F) Hello, World!: 2 : もも
(G) Hello, World!: 0 : みかん
(G) Hello, World!: 1 : りんご
(G) Hello, World!: 2 : もも
(H) Hello, World!: りんご は 80 円です。
(H) Hello, World!: みかん は 100 円です。
(H) Hello, World!: メロン は 1000 円です。
```

何かの役に立てばと。
RubyでAtCoder ABC267(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC267のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - Saturday
https://atcoder.jp/contests/abc267/tasks/abc267_a
```ruby:a-267.rb
array = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
puts 5 - array.index(gets.chomp)
```
## 解説
基準が土曜日なので5からインデックスを引いています。

# B - Split?
https://atcoder.jp/contests/abc267/tasks/abc267_b
```ruby:b-267.rb
# 修正前
s = gets.chomp
if s[0] == "1"
  puts "No"
else
  col3 = s[1] == "0" && s[7] == "0" ? "0" : "1"
  col4 = s[4] == "0" ? "0" : "1"
  col5 = s[2] == "0" && s[8] == "0" ? "0" : "1"
  s = s[6] + s[3] + col3 + col4 + col5 + s[5] + s[9]
  4.times do |i|
    for j in i + 2..6
      t = s[i..j]
      if t[0] == "1" && t[-1] == "1"
        if t[1..-2].include?("0")
          puts "Yes"
          exit
        end
      end
    end
  end
  puts "No"
end
```
```ruby:b-267.rb
# 修正後
s = gets.chomp
if s[0] == "1" || s == "0" * 10
  puts "No"
else
  cols = Array.new(7, false)
  [3, 2, 4, 1, 3, 5, 0, 2, 4, 6].each_with_index do |col_index, i|
    cols[col_index] = true if s[i] == "1"
  end

  left = cols.index(true) + 1
  right = cols.rindex(true) - 1
  if cols[left..right].include?(false)
    puts "Yes"
  else
    puts "No"
  end
end
```
## 解説
最初にそれぞれの列に対してピンが１つでも倒れているか調査し、sを置き換えています。そして、ピンが少なくとも１つ倒れている異なる２つのピンに対してその間の列にピンがすべて倒れている列があればYesを出力して終了、最後までスプリットがなければNoを出力します。

# C - Index × A(Continuous ver.)
https://atcoder.jp/contests/abc267/tasks/abc267_c
```ruby:c-267.rb
n, m = gets.split.map(&:to_i)
a = gets.split.map(&:to_i)
b, sum = 0, 0
m.times do |i|
  b += a[i] * (i + 1)
  sum += a[i]
end

ans = b
(n - m).times do |i|
  b = b - sum + (m * a[i + m])
  sum = sum - a[i] + a[i + m]
  ans = [ans, b].max
end
puts ans
```
## 解説
[公式解説](https://atcoder.jp/contests/abc267/editorial/4727)を参考にしました。
```math
\sum_{i=1}^{m}i×A_i-\sum_{i=1}^{m}i×A_{i+1}=\sum_{i=1}^{m}A_i-M×A_{M+1}
```
であることを利用しています。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
ChatGPT4で中規模プログラムを修正する際の注意点

# あらまし
ChatGPT4は小規模(70行以下程度)プログラムなら1分程度で書いてくれるし、それなりのものを仕上げてくる事が多い。
しかし、中規模(数百行とか複数ファイルにまたがる)プログラムだとなかなか手こずる。その対策、落としどころについて考える。
※3.5はそもそも対象外としています

# 想定
#### 想定しているシチュエーション
- 既にそこそこ複雑な数百行のプログラムが存在している
- それを良い感じに修正する(リファクタリング、エラー修正)


# 中規模以上の修正は何が問題か？
前回の記事から抜粋する。

https://qiita.com/kakari8888/items/a0800d34f04cfe7e4ed4#chatgpt%E3%81%A7%E3%81%9D%E3%81%93%E3%81%9D%E3%81%93%E3%81%AE%E8%A1%8C%E6%95%B050%E8%A1%8C%E4%BB%A5%E4%B8%8A%E3%81%A8%E3%81%8B%E3%82%92%E6%9B%B8%E3%81%8B%E3%81%9B%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

> しかし修正は状況による。50行のコードで一部エラーが出たり、挙動の一部を変えるように指示してもコスパはそれほど良くない。
今まで動いてた部分を動かなくして返してくる(ポンコツ)
同じ箇所で何度も修正作業が発生して、しかも改善されない。例えばpolarsの修正で存在しないメソッドを使ってきて、修正するように言うと、また別の存在しないメソッドを出してくる。polarsの日付関連で多い印象。
全行書き直す時間を待つのがだるいし、途中で途切れることもある。つなぐ際にインデントズレが起きたりする。
部分的に書き直してくる場合、該当箇所を探すのがだるい。
以上から、最初から自分で修正した方が良いこともある。この見極めがまだ難しい。

をリストにすると、
- 改悪してくることがある
- 同じ箇所で修正のループ(何度やっても躓く)
- 全行出力は時間の無駄(1行修正しただけなのに50行吐いてくる)
- 修正コードがどこに当たるのか、探すのが手間(何行目を差し替えるのか)

# わりとこうなる(辛い…)
関数を1つだけ取り出してリファクタリングさせる
　→エラー吐く(改悪スタート)
　　→(エラー文を渡して)「修正して」
　　　→修正前はこれです。修正後はこれです
　　　　→「え、そもそも**修正前のコードが違う**んだが？」
　　　　　→失礼しました。修正前を修正して、書き直しました
　　　　　　→「またエラー吐いたんだが…」
　　　　　　　→失礼しました。修正したコードはこちらです
　　　　　　　　→「え、いやいや、そもそも**また修正前のコードが違う**んだが？」
　　　　　　　　　→失礼しま(ry
**※以下、無限ループ**

# どう使い分けるか
「一発でサクッと修正」というパターンもそこそこあるため、「修正に使えない」と断じるのは早い。
ただ、「いつまで経っても良くならない」も珍しくない。これを試すコストは**わりと高くつく**(精神的な疲労も含め)。
以下、シーン別での評価をしてみた。

#### 初回の叩き台
**超優秀(95/100点)**
コードが何もないところから、「とりあえず何か用意して」というアバウトな指示に対しては超優秀で、現状このフェーズでは世界一役立つツールと言えるのではないだろうか。とにかく速い。「指示通りに動いてない」ということはあるけれどが、「叩き台として」は超優秀。何十行もの退屈なテンプレを用意しなくて良くなる。

#### 「簡単で短め」のコードの修正
**非常に優秀(90/100点)**
コードレビューをしてもらうのはかなり良い使い方だと思う。
また、短いのであれば「**全行書き直させて貼り付けるだけ**」と修正も簡単。
長いと「どこを差し替えるか」読んでいく必要があり面倒。

#### 「複雑で長め」のコードの修正
「わりとこうなる」で書いたようなパターン。
**結構微妙(40/100点)**
以下、経験則より。
・2回修正させて駄目だったら、3回目も駄目な可能性が高い
・長文で返してきた割にエラーを吐かれると辛い。待たされるわ、色々読まされるわと。
・「長いコードが扱いづらいなら関数を細かく分けたら良い」が、GPTは記憶力がお馬鹿。関数がたくさんあると名前を間違えてきたり、存在しない関数を呼び出したりする。
・「指示を正確にわかりやすく」はよく言われているが、1つの修正をするために何行にも渡って長文指示を書くのであれば、最初から自分で手直しした方が早いよね問題。

## 「複雑で長め」のコードの修正時にどう使うと良いか
**「2回、短めの修正をさせて駄目なら自分で手直し」と割り切る**
この辺りが現実的な気がしてきた。ここまでは試す価値があると言って良いライン。
それ以上はコスパがどんどん悪くなってくる、というのが現状の感想。
AI使って逆に効率が落ちていたら本末転倒。

# まとめ
「**あ、これGPTに任すとヤバいパターンだ**」という嗅覚を鋭くして**諦める判断**をより早く正確に出来るようになるとハッピーになれる(と思う)。
特定のJiraプロジェクトに含まれるすべての課題において、特定のカスタムフィールド（数値）に最新コメントからの経過日数を設定する

税理士試験消費税法の理論暗記の管理に、Jiraのかんばんボードを使っています。
最後に触れてからどのくらい経過したかをボード上で見たかったので、スクリプトを作成してみました。

使用方法
1. スクリプトにサイト名、プロジェクトキー、経過日数を設定するカスタムフィールドキーを設定する
2. Jiraの画面に対する、ブラウザのデバッグコンソール画面を開き(F12)、そこにスクリプトを貼り付けて実行する
3. エラーが出なければ完了


``` js
const site = 'xxx.atlassian.net';
const project = 'CTT'; // プロジェクトキー
const customFields = 'customfield_10851'; //カスタムフィールドID

const elapsedDays = (datetime) => {
    const currentDate = new Date();
    const updatedDate = new Date(datetime);
    const differenceInMs = currentDate.getTime() - updatedDate.getTime();
    const differenceInDays = Math.floor(differenceInMs / 86400000);
    return differenceInDays;
}

const foo = async () => {
    const res = await fetch(`https://${site}/rest/api/2/search?jql=project=${project}&maxResults=1000&fields=comment`);
    const json = await res.json();
    json.issues.forEach((issue) => {
        const comments = issue.fields.comment.comments;
        const lastComment = comments[comments.length - 1];
        const days = elapsedDays( lastComment ? lastComment.updated : issue.fields.created);

        const data = {
            fields: {
            }
        };
        data.fields[customFields] = days;

        fetch(`https://${site}/rest/api/2/issue/${issue.key}`, {
            method: 'PUT',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(data)
        }).catch(err => console.error(err));
    });
    console.dir(json);
};

foo();
```

こんな感じで経過日数が見れます。
![kanban.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56104/966d6d9e-8429-2fec-b56f-392769cc018f.png)

経過日数の計算方法は、ChatGPTに教えてもらいました(thanks)。
postgresql(13)でjson_aggをfilterする方法

# postgresql(13)でjson_aggをfilterする

json_aggとjson_build_objectを利用して、postgresqlでjson化したデータをSELECTしようとした時にハマったのでメモ書き。

## TL;DR

FILTERを利用してrelation先が存在がない場合に、nullを返却する。
返されたnullをCOALESCEで'[]'::jsonを利用してjsonのarray型で返却をする。

## 0. 想定テーブル

```table.sql
CREATE TABLE users (
    user_id UUID PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);

CREATE TABLE teams (
    team_id UUID PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);


CREATE TABLE team_users(
    team_id UUID NOT NULL,
    user_id UUID NOT NULL,
    FOREIGN KEY(user_id) REFERENCES users(user_id),
    FOREIGN KEY(team_id) REFERENCES teams(team_id),
    PRIMARY KEY(team_id, user_id)
);
-- Indexはサボった
```

## 1. 脳死で書いたSQL

team_usersが存在しない場合に、`{"user_id" : null, "user_name" : null}`として返却される。

```not-working.sql
SELECT
    t.name,
    t.team_id,
    JSON_AGG(json_build_object(
        'user_id', tu.user_id,
        'user_name', u.user_name
    )) as users
FROM teams t
    LEFT OUTER JOIN team_users tu ON t.team_id = tu.user_id
        LEFT JOIN users u ON u.user_id = tu.user_id
WHERE t.team_id = 'b4d27fd8-8ad1-4468-8df9-6bb2279b96da'
    GROUP BY t.team_id;

```

```return.json
[
  {
    "name": "team_1",
    "team_id": "b4d27fd8-8ad1-4468-8df9-6bb2279b96da",
    "users": [{"user_id" : null, "user_name" : null}]
  }
]
```

## 2. COALESCE使えばいいんだろ。と思ってダメだった

null => COALESCEだよなと思ったけど、そもそもjsonのkey-valueが入っているので、使えない。

```not-good.sql
SELECT
    t.name,
    t.team_id,
    COALESCE(JSON_AGG(json_build_object(
        'user_id', tu.user_id,
        'user_name', u.name
    )), '[]'::json) as users
FROM teams t
    LEFT OUTER JOIN team_users tu ON t.team_id = tu.user_id
        LEFT JOIN users u ON u.user_id = tu.user_id
WHERE t.team_id = 'b4d27fd8-8ad1-4468-8df9-6bb2279b96da'
    GROUP BY t.team_id;
```

```result.json
[
  {
    "name": "team_1",
    "team_id": "b4d27fd8-8ad1-4468-8df9-6bb2279b96da",
    "users": [{"user_id" : null, "user_name" : null}]
  }
]
```

## 3. FILTERを利用してきれいにする

```with-filter.sql
SELECT
    t.name,
    t.team_id,
    COALESCE(JSON_AGG(json_build_object(
        'user_id', tu.user_id,
        'user_name', u.name
    )) FILTER(WHERE tu.user_id IS NOT NULL), '[]'::json) as users
FROM teams t
    LEFT OUTER JOIN team_users tu ON t.team_id = tu.user_id
        LEFT JOIN users u ON u.user_id = tu.user_id
WHERE t.team_id = 'b4d27fd8-8ad1-4468-8df9-6bb2279b96da'
    GROUP BY t.team_id;
```

```result.json
[
  {
    "name": "team_1",
    "team_id": "b4d27fd8-8ad1-4468-8df9-6bb2279b96da",
    "users": []
  }
]
```

## 4. sub queryを利用したパターン

```sub-query.sql
SELECT
    t.name,
    t.team_id,
    COALESCE((SELECT JSON_AGG(JSON_BUILD_OBJECT(
        'user_id', tu.user_id,
        'user_name', u.name
        )) from team_users tu
              INNER JOIN users u ON u.user_id = tu.user_id
              WHERE tu.team_id = t.team_id
    ), '[]'::json) as users
FROM teams t
WHERE t.team_id = 'b4d27fd8-8ad1-4468-8df9-6bb2279b96da';
```

他のやり方は思いつかない。。。(なんかあるのかな)
【Rust】VSCodeでauto format時のtab space sizeを2にする

`rust-analyzer`を使用している前提で、`settings.json`に以下を追加する。

```json:settings.json
"[rust]": {
  "editor.defaultFormatter": "rust-lang.rust-analyzer",
  "editor.formatOnSave": true,
  "editor.tabSize": 2
},
"rust-analyzer.rustfmt.extraArgs": ["--config", "tab_spaces=2"]
```

https://github.com/rust-lang/rust-analyzer/issues/1191#issuecomment-1334676220

---
### おまけ
エディター上に型ヒントを表示したくない場合は、以下を設定する。
```json:settings.json
"[rust]": {
  "editor.inlayHints.enabled": "off"
},
```
Active Directory 脆弱性検証環境の構築 (予告のみ)

ActiveDirectoryの環境を作成し、ペネトレーションテストの自習しようとした際の忘備録です。おそらくHacktheBoxで[Dante](https://ad-lab.gitbook.io/building-a-windows-ad-lab/)に挑戦できるぐらいの知識は獲得できると思います。

詳細は以下を利用しました。ネットワークが安定的で、安いクラウドプロバイダーがあれば試したいと思っていました。

https://mayfly277.github.io/posts/GOAD-on-proxmox-part1-install/

もっと手動で構築したい方は以下がおすすめです。このサイトは脆弱な設定をしてから攻撃する構成をとっているので、Active Directoryのペネトレーションテストの経験がない人でも気軽に始められます。

https://ad-lab.gitbook.io/building-a-windows-ad-lab/

## 環境構築

目次は以下となります。

1. Proxmoxとpfsenseのインストールと設定
2. ISOファイルとパッカーの準備
3. Teraformの準備
4. Ansibleでプロビジョニング
5. VPNアクセスとopenvpn

## アクティブディレクトリ攻撃

参考にしたのは以下のサイトです。

https://book.hacktricks.xyz/windows-hardening/active-directory-methodology

また攻撃は以下の詳細を予定しています。

1. スキャン
2. ユーザ名取得へ向けた偵察(Reconnaissance)
3. ユーザ名でパスワードスプレー攻撃
4. ユーザパスワード取得へ向けたNTLM Relay & mitm6
5. ユーザ名とパスワードで攻撃 - ドメイン管理者へ
6. ADCSへの攻撃
7. MSSQLへの攻撃
8. 権限昇格
9. Lateral Movement
10. Delegation
11. ACL Abuse
12. Trust Abuse (Golden Ticket, etx.) 

攻撃パターンはもっとあるので更新していきます。

リンク先は順次アップロードしていきたいと思います。

ハッピーハッキング
【Github】鍵認証の設定をする


鍵を設定する方法を記す。

chatgptで聞いた「githubの鍵認証のステップを簡潔に知りたい」
↑これはほぼ合ってます。

```
1. SSHキーの生成
ssh-keygen -t ed25519 -C "your_email@example.com"
2. 公開鍵の追加
GitHubのWebサイトから公開鍵を追加する。
```


### 1.SSHキーの生成（mac）

```

#-fで名前指定しないと.sshに元から他のキーがあるかもしれない
#ssh-keygen -t rsa -b 4096 -C "hoge@mail.com" -f ~/.ssh/git
 # -t 暗号化方式を指定
 # -b 暗号化強度を指定
 # -C コメントを設定 

ssh-keygen -t rsa -b 4096 -C "hoge@mail.com" -f ~/.ssh/git

ssh-keygen -t rsa -C "hoge@mail.com" -f ~/.ssh/git

```


### 2.公開鍵の追加

![スクリーンショット 2023-05-05 13.25.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64334/3257b6da-5b7f-f8e8-5cf4-ef16807eaf70.png)



```
SSH 秘密鍵を ssh-agent に追加
~/.ssh/git.pubを確認してgitに登録

cat ~/.ssh/git.pub

```

自分のプロフィールの設定。（リポジトリではない）
public keyの保存

![スクリーンショット 2023-05-05 13.51.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64334/143b3759-56fb-ab6f-3ef2-54a41da00c06.png)



```
eval "$(ssh-agent -s)"

#mac
ssh-add -K ~/.ssh/git
#linux
ssh-add -k ~/.ssh/git


ssh -T git@github.com
```


### 「エラー解消」fatal: Could not read from remote repository.  Please make sure you have the correct access rights

エラーが出てる時

```
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```


そもそも自分のgitにキーが登録されてないか、
あるいは登録されてるけど繋がってないのでssh-addする。


```
eval "$(ssh-agent -s)"
ssh-add -k ~/.ssh/hoge
ssh -T git@github.com
```



### git configを設定

設定はlocal, global, systemの順で優先される。

```
git config --list
git config --system --list
git config --global --list
git config --local --list
```

localはリポジトリ内の .git/configに記載されている。
globalはログインユーザのHOMEディレクトリ配下の .gitconfigに記載されている。
参考になるページ。

https://qiita.com/shionit/items/fb4a1a30538f8d335b35


```
設定一覧
git config --list

systemの設定を消す。(全ユーザーの全リポジトリ)
git config --system --unset user.name
git config --system --unset user.email
globalの設定を消す。(使用ユーザー)
git config --global --unset user.name
git config --global --unset user.email
localの設定を消す。(設定したリポジトリ)
git config --local --unset user.name
git config --local --unset user.email

localの設定をする。
git config --local user.name "xxx"
git config --local user.email xxx@example.com

globalの設定をする。
git config --global user.name "xxx"
git config --global user.email xxx@example.com

```


### コミットログ修正

git configのuserを修正した上でrebaseする。


```
git rebase -i コミットID
or
git rebase -i HEAD~3 # 3つ前まで編集

↓ 時間かかる
git commit --amend --author="xxxx@xxxxx.com"


git rebase --continue
```
CentOS7にPostgreSQL14をインストール

## 事前確認
LinuxのOSやバージョンの確認（RedHat系の場合）

```shell
cat /etc/redhat-release
```

## PostgreSQL14のインストール

https://www.postgresql.org/download/linux/redhat/
でダウンロードモジュールを確認。

■Select version: でPostgreSQLのバージョンを選択

■Select platform: でプラットフォームを選択

■Select architecture: でCPUの種類を選択。
※architectureがわからない場合は下記コマンドで確認。

```shell
uname -m
```

PostgreSQLのリポジトリRPMのインストール
```shell
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
```

```shell
yum install -y postgresql14-server
```
インストールできたか確認
```shell
yum list installed | grep postgre
```

こう出ればOK
postgresql14.x86_64                  14.7-1PGDG.rhel7               @pgdg14
postgresql14-libs.x86_64             14.7-1PGDG.rhel7               @pgdg14
postgresql14-server.x86_64           14.7-1PGDG.rhel7               @pgdg14


## データベースの初期化と起動

データベースの初期化
```
/usr/pgsql-14/bin/postgresql-14-setup initdb
```

ただし今回は文字コードとロケール指定して実行。
※--encodingは、データベースのデフォルトの文字エンコーディングを設定するオプションです。
※--no-localeは、ロケールを使用しないことを設定するオプションです。ロケールとは、言語や文化に応じた処理をするOSの機構です。 
```
PGSETUP_INITDB_OPTIONS='--encoding=UTF-8 --no-locale' /usr/pgsql-14/bin/postgresql-14-setup initdb
```

```shell
systemctl enable postgresql-14
```

postgreSQL起動
```shell
systemctl start postgresql-14
```

## postgresユーザの設定
yumでinstallすると自動でOSにpostgresユーザが作成されている。
OSユーザのパスワード設定を行う。

```shell
passwd postgres
```
Changing password for user postgres.
New password:
BAD PASSWORD: The password contains the user name in some form
Retype new password:
passwd: all authentication tokens updated successfully.

## ユーザ追加（必要であれば）

ユーザ切り替え
```shell
su - postgres
```

```
psql
```

登録ユーザの確認
```sql
select * from pg_user;
または
\du
```
結果↓
```
 usename  | usesysid | usecreatedb | usesuper | userepl | usebypassrls |  passwd  | valuntil | useconfig
----------+----------+-------------+----------+---------+--------------+----------+----------+-----------
 postgres |       10 | t           | t        | t       | t            | ******** |          |
(1 行)
```

PostgreSQLのインストール時にデフォルトでpostgresというユーザが作成されていることがわかる。
※WindowsでPostgreSQLをインストールした場合、Linuxの場合と異なり、PostgreSQLのためのOSユーザーは作成されない。PostgreSQL内でのみ有効なユーザーとして「postgres」（デフォルト値）が作成される。

postgres以外のユーザでアクセスするためには新規にユーザを登録する必要がある。

新規ユーザの登録
```sql
CREATE USER sampleuser;
```

登録ユーザの確認
```sql
select * from pg_user;
または
\du
```

これでsampleuserからも接続できるようになった。

## データベースの作成と接続

データベースを作成
※注意点として、PostgreSQLの識別子に大文字は推奨されないため、すべて小文字にすべき。
```sql
CREATE DATABASE sampledb;
\l
```

データベースに接続
```sql
\c sampledb
```

## 補足：ミスって最初からやり直したい場合

下記で削除できる。
```shell
yum list installed | grep postgre
yum remove postgresql14-server.x86_64
yum remove postgresql14-libs.x86_64
yum list installed | grep postgre
ls /usr | grep pgsql-14
ls /var/lib | grep pgsql
rm -rf /usr/pgsql-14
rm -rf /var/lib/pgsql
```
Vue3 + laravel10でSPA作成　①環境構築

## はじめに
全3回にわたり、簡単なToDoリストの作成を行っていきます。
今回の目標はプロジェクト作成～トップページにアクセスするところまでとなります。
[ソースコード](https://github.com/WMinsane/todoApp.git)はUP済ですので、動かない場合にはご参照ください。

## 前提
・`php`, `npm`, `composer`のパスが通っていること
・`xampp`のインストール（任意）
※`mysql`でローカルホストにDBをたてるために使用します。

## プロジェクト作成
### １．作成コマンド
任意のディレクトリで以下のコマンドを実行し、プロジェクトを作成します。
```console
composer create-project --prefer-dist laravel/laravel TodoApp
```
### ２．各種ライブラリ追加
プロジェクトのルートディレクトリに移動し、以下のコマンドを実行します。
今回はCSSフレームワークに`Vuetify`を使用します。一番下のコマンドは`Vuetify`でiconを使用する場合に追加します。
```console
composer require laravel/ui
npm i @vitejs/plugin-vue
npm i vite-plugin-vuetify
npm i vue-router
npm i @mdi/font 
```
### ３．vite.config.jsの編集
`vite`(ビルドツール)の設定。
`hmr`はhot module reloadの略で、コードを修正すると再ビルドをしなくても自動で画面に反映させる仕組みになります。
```diff_javascript:vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
+ import vue from '@vitejs/plugin-vue';
+ import vuetify from 'vite-plugin-vuetify'

export default defineConfig({
+     server: {
+         hmr: { host: 'localhost' },
+         host: 'localhost',
+     },

    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
+         vue(),
+         vuetify(),
    ],
});

```
### ４．app.jsの編集
エントリポイントとなる`app.js`で使用ライブラリの読み込みを行います。
`resources\js\app.js`を開き、以下のように編集します。

```diff_javascript:app.js
import './bootstrap';
+ import { createApp } from 'vue';
+ import{ createVuetify } from 'vuetify'
+ import App from "../views/App.vue"
+ import '@mdi/font/css/materialdesignicons.css'
+ import 'vuetify/dist/vuetify.min.css'

+ const app = createApp(App);
+ const vuetify = createVuetify();

+ app.use(vuetify) 
+ app.mount('#app');

```
### ５．web.phpの編集
`localhost:8000`以下のURLが何であっても`app.blade.php`を返すように`routes\web.php`を編集します。
```diff_php:web.php
- Route::get('/', function () {
-     return view('welcome');
- });
+ Route::get('/{any?}', fn() => view('app')) -> where('any', '.+');
```

### ６．app.blade.phpの作成
`resources\views\welcome.blade.php`を削除し、同フォルダに`app.blade.php`を作成します。
手順５で同一のものを返すように設定した`blade`ファイルの中身になります。
```php:app.blade.php
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    @vite(['resources/css/app.css','resources/js/app.js'])

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Vue Laravel SPA') }}</title>

    <!-- Styles -->
</head>
<body>
<div id="app">
</div>
<!-- Scripts -->
</body>
</html>
```

### ７．App.vueの作成
`resources\views\App.vue`を作成します。
手順６で作成した`blade`のdivタグの箇所に埋め込まれます。
```vue
<template>
    test
</template>
```
## 動作確認

以下のコマンドでサーバとクライアントを起動します。
※私はコマンドプロンプトとVSCodeのターミナルで同時に起動しております。

・`npm run dev`
・`php artisan serve`

ブラウザを開きアドレスバーに`http://localhost:8000`を入力し、ページに`test`の文字が表示されれば完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410887/0a4f1ae7-8210-24b3-b2e8-9201765d5ea6.png)

#参考にしたサイト
[Vue.js + LaravelでシンプルなSPA構築チュートリアル：概要編](https://qiita.com/minato-naka/items/2d2def4d66ec88dc3ca2)
Visual Studio2022のコメントアウト操作を楽にする

# 目的
・コメントアウトを楽にしたい(キーボードのみで完結させたい)
・既存の「Ctrl + K, Ctrl + C(Ctrl + U)」は慣れないのでコンテキストメニューに追加させたい※未達

# ゴール
http://officetanaka.net/excel/vba/tips/tips04.htm

本当はこれをやりたい
やり方知ってる方がいらっしゃったら教えてください…

# 妥協案
「Ctrl + K, Ctrl + C(Ctrl + U)」に頼らない、やり方で何とかする

# 下準備
1\. 拡張機能＞「メニューのカスタマイズ」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331961/c9d69766-abc7-b97a-982b-d6ccbbc0486c.png)
2\. ツール バータブ＞「新規」ボタンを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331961/77d82f0a-e3f5-ac61-0287-3a4b124ebe3d.png)
3\. ツール バーの名前を入力して「OK」ボタンを押下(御好みで変更してください)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331961/1df987e8-4b4d-b71f-3161-edc3887e85a5.png)
4\. コマンドタブ＞ツール バーを3.で追加した物を選択し、「コマンドの追加」ボタンを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331961/cad1389e-de35-eafc-bdeb-a6c8ae73062f.png)
5\. カテゴリ：編集＞コマンド「選択範囲をコメント化」と「選択範囲のコメントを解除」を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331961/8885d550-3dc8-41ce-e664-457833d06dce.png)
(注意)複数同時追加出来ないので、１回ずつ「OK」ボタンを押下しなければならない
6\. 追加したツールバーをメニュー「ファイル」直下辺りに移動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331961/16f26141-12ff-648b-a795-895bcc8de561.png)

# 実際の操作は？
・ALT ＞ Ctrl + Tab で下準備の6.に追加したツール バーにフォーカスが移る、十字キーで其々したい方を選ぶ
　※手順が増えているじゃないか！というツッコミは御尤も

# 利点：「Ctrl + K, Ctrl + C(Ctrl + U)」に勝る点
・連続してコメントアウトしたい場合は「Ctrl + K, Ctrl + C(Ctrl + U)」を毎回繰り返しキータイプしなくて済む
　▶ツール バーにフォーカスが維持されるので、以降はEnterキーだけをタイプすればOK
　　※但し、この様な操作をするプログラマーが居るかは不明
【RSpec】Failure/Error: _query(sql, @query_options.merge(options))ActiveRecord::ConnectionNotEstablished:MySQL client is not connected

### 環境
MacOS ventura 13.3.1
ruby 3.2.1
rails 6.1.3.7
mysql 5.7
rspec-rails-6.0.1
rspec-core-3.12.1
factory_bot_rails-6.2.0

## はじめに
RSpecを使用している際に以下のエラーが発生しました。
```
Failure/Error: _query(sql, @query_options.merge(options))
      
ActiveRecord::ConnectionNotEstablished:
MySQL client is not connected
```
私の場合、ActiveStorageでプロフィール画像を実装した直後にこのエラーが発生しました。

## 原因
ActiveStorageではファイルのアップロード処理が非同期で行われており、DBのコネクションに影響を与えているそうです。
私はユーザー生成と同時にデフォルトのプロフィール画像をアタッチしていたので、FactoryBotでユーザーを作成するたびにエラーが発生しました。

## 解消法
`config/environment/test.rb`に`config.active_job.queue_adapter = :inline `を追記する。
```ruby:config/environments/test.rb
Rails.application.configure do
  config.active_job.queue_adapter = :inline 
end
```
非同期処理はActive Jobで行われていて、上記の設定は非同期処理を同期的に処理する設定です。

## 参考
[rspecでDBコネクションエラーが発生するようになった話](https://qiita.com/ham0215/items/acccaf6023807a7518b6)
[【Rails】ActiveStorageでたまに落ちるテストの解消](https://blog.aiandrox.com/posts/tech/2021/06/21/)