OmniAICreator/Qiita-1.07M huggingface dataset:
pythonの超基礎　unique()関数

pythonでのunique()は重複しないように取り出す関数
![Book111.pdf および他 1 ページ - 個人 - Microsoft​ Edge 2023_06_09 19_32_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474582/effdc326-ea95-d04e-3a22-f452725c4d5b.png)

```Python
category=tg_df['色'].unique()
print(category)
```

tg_df['色']の中の同じにならないものを取り出す
↓
赤、青、緑、黄
個人的によく使う SQL文 簡易まとめ + 個人的なメモ

こんにちは、新米エンジニアが忘備録として書き溜めていきます。
知識が増えたらリライトします。

SQL 文でよくお世話になってるサイト

https://www.javadrive.jp/mysql/

ログイン
```
mysql -u {ユーザー名} -p
```

##  確認系

データベース一覧確認
```
show databases;
```

データベースに入る
```
use {対象DB名}:
```

テーブル一覧
```
対象データベースに入っているなら
show tables;
もしくは
show tables from {対象データベース名};
```

テーブルの中身
```
SELECT * FROM {テーブル名};
```

適当なテーブルとカラム指定して表示 、区切りは「,」
limit 5 は5行まで表示  
```
select {カラム名} from {テーブル名} limit 5;
例：mysql> select id,provider,bucket from test_table limit 5;
```

ユーザー一覧
```
select user, host from mysql.user;
```

対象ユーザーの権限確認
```
SHOW GRANTS FOR {対象ユーザー名}@{対象ホスト名};
例：mysql> SHOW GRANTS FOR root@localhost;
```

認証プラグイン確認
```
SELECT User, Host, Plugin FROM mysql.user;
```

対象ユーザーに関する情報を確認
```
select * from mysql.user where user='{ユーザー名}'\G
```

現在の接続ユーザーを確認
```
select user(), current_user();
```


##  作成系

データベース作成
https://www.javadrive.jp/mysql/database/index1.html
```
CREATE DATABASE {データベース名};
```

テーブル作成  
https://www.javadrive.jp/mysql/table/index1.html
```
create table {テーブル名}({カラム名} {データ型} {オプション})
例：mysql> create table testtable(id int, name varchar(10));
```

データ挿入
```
INSERT INTO {テーブル名}(カラム名) VALUES ('値');
例：mysql> INSERT INTO testtable(name) VALUES ('りんご');
```

カラム挿入
```
ALTER TABLE {テーブル名} ADD COLUMN {カラム名} {データ型};
例：mysql> ALTER TABLE testtable ADD COLUMN stock INT;
```

ユーザー作成
```
create user {希望のユーザー名}@{希望のホスト名} identified by '希望のパスワード';
```


##  削除系

データベース削除
```
drop database {データベース名};
```

テーブル削除
```
drop table {テーブル名};
```

カラム削除
```
ALTER TABLE {テーブル名} DROP COLUMN {カラム名};
ALTER TABLE testtable DROP COLUMN stock;
```

ユーザー削除
```
drop user {ユーザー名}@[{ホスト名};
```



##  変更系

ユーザーの権限変更 
https://www.javadrive.jp/mysql/user/index5.html
https://www.javadrive.jp/mysql/user/index6.html  
```
db_name内の全ての操作を許可する
例：mysql> GRANT ALL ON db_name.* TO {ユーザ名};

全てのデータベースの全ての操作を許可する
例：mysql> grant all ON *.* TO 'root'@'192.168.0.%';

db_name内の SELECT 権限を許可（検索、表示等、INSERT もいける）
例：mysql> GRANT SELECT, INSERT ON db_name.* TO {ユーザ名};
```

対象ユーザーの認証プラグイン変更
```
ALTER USER {ユーザ名}@{ホスト名} IDENTIFIED WITH mysql_native_password BY '{パスワード}';

認証プラグインを「caching_sha2_password」から「mysql_native_password」に変更する場合
例：mysql> ALTER USER test@localhost IDENTIFIED WITH mysql_native_password BY 'password';
```

設定反映
```
flush privileges;
```

抜け出す
```
exit;
もしくは
Ctrl + D
```


##  個人的なメモ

### USAGE権限について

> USAGE権限はグローバルレベルでのみ指定が可能な権限で、
> この権限を設定すると何も権限が無いことになります。

http://dbonline.s25.xrea.com/mysql/user/index6.html

```
mysql> show grants for test@localhost;
+------------------------------------------------------------------------+
| Grants for test@localhost                                      |
+------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `test`@`localhost`                       | |
+------------------------------------------------------------------------+
1 rows in set (0.00 sec)
```
ルートをたどる： 開発者のためのTracerouteの探求


# ルートをたどる： 開発者のためのTracerouteの探求

Tracerouteは、データパケットが送信元コンピュータから送信先サーバに到達するまでの経路を追跡することができるネットワークユーティリティツールです。この記事では、Tracerouteの概念や仕組み、利用シーン、誤解、FAQなど、このツールについて解説します。

## Traceroute とは何か、どのように動作するのか？

Traceroute はコマンドラインユーティリティツールで、ターゲットサーバーにパケットを送信し、ルート上の各ホップの IP アドレスを含む応答時間を記録することによってネットワークを調査します。パケットがターゲットサーバーに到達すると、ソースコンピューターに返され、応答時間が記録されます。

トレースルートは、TTL（Time-to-Live）値が増加するパケットを送信することで動作します。TTLとは、パケットヘッダ内のフィールドで、パケットが廃棄されるまでに何ホップ通過できるかを示すものです。パケットがあるホップに到達してTTL値がゼロになると、そのホップはパケットを破棄し、パケットがタイムアウトしたことを示すエラーメッセージを送信元のコンピュータに返します。Tracerouteは、このエラーメッセージを利用して、ホップのIPアドレスを記録します。

## トレースルートの使い方

Tracerouteは通常、コマンドラインから使用し、Windows、Linux、macOSを含むほとんどのオペレーティングシステムで使用できます。コマンドの構文はオペレーティングシステムによって若干異なりますが、基本的な構成は同じです。以下は、macOSにおけるtracerouteコマンドの例です：





```bash
traceroute google.com
```

または、He3ツールボックスのトレースルートツールを使用することもできます。([https://t.he3app.com?0krf](https://t.he3app.com?0krf) )

![Traceroute](https://he3.app/images/blog/screenshots/Traceroute.png)

## 開発者のためのシナリオ

Tracerouteは、パケットロス、遅延、ルーティングの問題など、ネットワークの問題をトラブルシューティングするために開発者がよく使用します。また、ネットワークのパフォーマンスを分析し、ネットワークのボトルネックを特定し、ネットワーク構成を最適化するためにも使用されます。例えば、開発者はTracerouteを使用して、遅いネットワーク接続の原因を特定したり、ネットワークの混雑を検出したり、目的地のサーバーへの最速ルートを特定したりすることができます。

## Traceroute の主な機能

Tracerouteには、開発者にとって有用な以下のような主要機能があります：

- ネットワークトラフィックの経路を特定する
- ネットワークの混雑やルーティングの問題の検出
- ネットワークのトラブルシューティングとパフォーマンス分析
- 目的地サーバーへの最適な経路を決定する

## 誤解とFAQ

Tracerouteはしばしば誤解され、誤解や混乱を招くことがあります。ここでは、Tracerouteに関するよくある誤解やよくある質問について紹介します：

### トレーサルートは、ネットワークセキュリティの脅威を検出するために使用できるのか？

Tracerouteは、マルウェアや侵入の試みなど、ネットワークセキュリティの脅威を検出するために設計されているわけではありません。しかし、パケットドロップや異常な応答時間など、セキュリティ上の問題を示す可能性のある疑わしいネットワーク活動を特定するために使用することは可能です。

### Traceroute は、ファイアウォールや他のセキュリティ対策でブロックできますか？

トレースルートは、ファイアウォール、特にICMPパケットのフィルタリングやパケットのホップ数を制限する厳格なセキュリティポリシーを持つファイアウォールによってブロックされることがあります。このような場合、tracerouteはルートトレースを完了できないことがあります。

## 結論

Traceroute は、開発者がネットワークトラフィックの経路を追跡し、ルーティングやパフォーマンスの問題を特定し、ネットワーク構成を最適化するのに便利なツールです。ほとんどのオペレーティングシステムで利用可能で、コマンドラインから使用することができます。Tracerouteについては、いくつかの誤解がありますが、開発者のツールキットとしては、依然として貴重なツールです。

参考文献

- [Traceroute - Wikipedia](https://en.wikipedia.org/wiki/Traceroute)
- [Traceroute Command in Linux and MacOS [With Examples]](https://www.tecmint.com/traceroute-command-examples/)
- [Traceroute - Cisco](https://www.cisco.com/c/en/us/support/docs/ip/routing-information-protocol-rip/26704-143.html)
Github Actionsのブランチ名とか取得するときのメモ

github actionsメモ
developブランチとmainブランチでいろいろ
ビルドした後、チェックだけなのかを判定したくて

# 任意のブランチにpushしたとき
```yaml
${{ github.base_ref }} # develop
${{ github.event_name }} # pull_request
${{ github.event.pull_request.merged }} # false
```

# developへのPRでのビルドチェック
```yaml
${{ github.base_ref }} # develop
${{ github.event_name }} # pull_request
${{ github.event.pull_request.merged }} # false
```

# developへPRマージしたとき
```yaml
${{ github.base_ref }} # develop
${{ github.event_name }} # push
${{ github.event.pull_request.merged }} # true
```

# 手動でマージしてmainにpushしたとき(mainにマージ)
```yaml
${{ github.base_ref }} # main
${{ github.event_name }} # push
${{ github.event.pull_request.merged }} # null
```

# repository_dispatchから起動
```yaml
${{ github.base_ref }} # main(ここはデフォルトブランチになる)
${{ github.event_name }} # repository_dispatch
${{ github.event.pull_request.merged }} # null
```
ABC304 - B - Subscribers 自己解法

# 問題
https://atcoder.jp/contests/abc304/tasks/abc304_b

# 考察
### パターン①場合分けで解く
例えば整数$N$の一の位を切り捨てて出力したい場合、C++であれば以下のコードで切り捨てることができます。($N$は整数型の変数です。)
```cpp
(N / 10) * 10
```
一度10で割ることで一の位を切り捨ててもらい、後で10を掛けて期待した値を得るという手順です。
これを応用することで十の位以下、百の位以下・・・でも切り捨てて出力することができます。
これで任意の位以下を切り捨てることができれば、Nの値に沿って場合分けを行うことで題意に沿った値を出力することができます。
### パターン②規則性から解く
この問題では、$10^3$以上になると切り捨てが発生します。この切り捨てが$(Nの桁数)-3$桁以下の部分であることが問題文からわかります。そこで最初に$N$の桁数を求め、そこから切り捨てる部分も求めていきます。$N$の桁数を求める関数を事前に用意しておくと役に立ちます。
```整数の桁数を求める関数.cpp
int countDigits(int n) {
    int res = 0;
    while(n > 0) {
        res++;
        n /= 10;
    }
    return res;
}
```
切り捨てについては$1$に$10$を$(Nの桁数)-3$回掛けた値をパターン①で示したコードに当てはめればOKです。

# 提出コード(コンテスト後)

https://atcoder.jp/contests/abc304/submissions/42097513

ご不明点などがあれば教えていただけると幸いです。
【令和最新版】Mac に LaTeX をインストールする方法

自分がインストールしたときの方法をそのまま書いただけです。

## 環境

- OS：macOS Ventura 13.4（22F66）
- プロセッサ：Apple silicon (Apple M2 Pro)
- TeX インストーラー：MacTeX 2023
- Homebrew インストール済み

## インストール

1. Ghostscript をインストール

   ```sh
   brew install ghostscript
   ```

2. [MacTeX - TeX Users Group](https://www.tug.org/mactex/mactex-download.html) を開く
3. MacTeX.pkg をダウンロード

4. ハッシュ値を比較

   ```sh
   shasum -a 512 path/to/MacTeX.pkg
   ```

   で取得したハッシュ値と、[MacTeX - TeX Users Group](https://www.tug.org/mactex/mactex-download.html) に記載されている「SHA512 sum」の値が一致することを確認
5. MacTeX.pkg を開き、インストーラーの指示に従ってインストールを進める。ただし、途中で「カスタマイズ」ボタンをクリックし、Ghostscript 関連のチェックを外してインストールを進める。「Gui-Applications」のチェックはお好みで良いですが個人的にはあって困るものでもないので、チェックを入れて TexShop などの GUI アプリケーションも併せてインストールしました

## 設定

1. Tex Live 関連パッケージを一括アップデート

   ```sh
   sudo tlmgr update --self --all
   ```

2. デフォルトの用紙サイズを A4 に設定

   ```sh
   sudo tlmgr paper a4
   ```

   Gui-Applications をインストールしていない場合はこれで設定完了
3. Gui-Applications をインストールした場合は、「アプリケーション/Tex/LaTeXiT」を開く
4. Ghostscript (gs) と ps2pdf コマンドが見付からないといったようなエラーが出る場合、以下の対応を実施する
5. `gs` と `ps2pdf` コマンドのパスを確認してメモする

   ```sh
   which gs     # /opt/homebrew/bin/gs
   which ps2pdf # /opt/homebrew/bin/ps2pdf
   ```

6. LaTeXiT の環境設定を開く
7. 「プログラム」タブの Ghostscript (gs) と ps2pdf の欄に先程メモしたパスを入力する（以下、例）
   - Ghostscript (gs): `/opt/homebrew/bin/gs`
   - ps2pdf: `/opt/homebrew/bin/ps2pdf`
8. LaTeXiT を再起動し、先程のエラーが出ないことを確認

## 動作確認

1. index.tex を作成

   ```sh
   vi index.tex
   ```

   ```tex:index.tex
   \documentclass{ltjsarticle}
   \begin{document}
   こんにちは、\LaTeX 世界！
   \end{document}
   ```

2. index.tex をコンパイル

   ```sh
   lualatex index.tex
   ```

3. index.pdf を開き、正常に変換できていることを確認

## 補足

- 最近の LaTeX (TeX Live) を用いて TeX ファイルから PDF を作成するには `lualatex` コマンドを利用するのが良さそう
- 最近の Tex Live にはデフォルトで原ノ味フォントが同梱されており、特別な設定なしに綺麗な日本語 PDF を作成できる（以前はヒラギノを埋め込めるように設定するのがなかなか面倒だった記憶があります）

## 付録：Pandoc を使って Markdown を PDF に変換

TeX の記法などは正直よく分からないので、自分の場合、直接 TeX ファイルは触らずに Markdown ファイルをソースとして PDF に変換することが多いです。そしてこれを実現するために LaTeX のフロントエンドとして Pandoc を使っています。

なお、本記事執筆時点で自分が使っている Pandoc のバージョンは 3.1.3 です。

1. Pandoc をインストール

   ```sh
   brew install pandoc
   ```

2. index2.md を作成

   ```sh
   vi index2.md
   ```

   ```md:index2.md
   ---
   title: こんにちは
   author: haru
   date: 2023-06-09
   colorlinks: true
   documentclass: ltjsarticle
   lang: ja-JP
   ---

   こんにちは、**Markdown** 世界！
   ```

3. index2.md を index2.pdf に変換

   ```sh
   pandoc --pdf-engine=lualatex index2.md -o index2.pdf
   ```

4. index2.pdf を開き、正常に変換できていることを確認

## 参考

- [MacTeX - TeX Users Group](https://www.tug.org/mactex/)
- [MacTeX - TeX Wiki](https://texwiki.texjp.org/?MacTeX)
Lifecycle of composablesを読む

## 前言

※AndroidのdevelopersサイトからUI architecture読んで、気になる部分をメモする感じです。

今回は`lifecycle`を拝見してます。
https://developer.android.com/jetpack/compose/lifecycle

## キーワード

- `Composable`：@ComposableをつけてるClass、UIのパーツ
- `Composition`：`Composable`から生成され、UIを記述するツリー構造
- `Compose`：Jetpack Composeのシステムを指してる

## メモ

### Lifecycle overview

- 唯一`Composition`を変更する方法はrecomposition。

- `Composable`のlifecycleはすごくシンプルで、以下の三つしかない。
    1. `Composition`に入場
    2. recomposeしないか、recomposeする
    3. `Composition`から退場

- recompositionは`State<T>`の変更でトリガーされる。

`Composable`が複数回に呼ばれたときに、複数のインスタンスが`Composition`に設置される。

```kotlin
@Composable
fun MyComposable() {
    Column {
        Text("Hello")
        Text("World")
    }
}
```

### Anatomy of a composable in Composition

recompositionの時、`Composable`は呼ばれたかどうかで判断される。
もし`Composable`が前回の`Composition`と今回も両方呼ばれた時はinputsが変わったかで判断される。

### Add extra information to help smart recompositions

複数回`Composable`を呼ぶ場合は実行順序を識別子として`Composable`を区別する。ただ、場合によって実行順序がうまく動作しない場合がある。

```kotlin
@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            // MovieOverview composables are placed in Composition given its
            // index position in the for loop
            MovieOverview(movie)
        }
    }
}
```

こちらを例にすると、Listの最後に新しい項目を追加する時に、最後の項目以外の項目は同じ実行順序を使ってるため、recomposeしない。
ですが、Listの最前、途中に項目を追加すると、それ以外の項目も影響され、多数の`Composable`がrecomposeすることになる。

この場合は提供されてる`key()`を使って、識別子を指定することができる。

```kotlin
@Composable
fun MoviesScreenWithKey(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            key(movie.id) { // Unique ID for this movie
                MovieOverview(movie)
            }
        }
    }
}
```

また、lazyListにもDSLで提供してる

```kotlin
@Composable
fun MoviesScreenLazy(movies: List<Movie>) {
    LazyColumn {
        items(movies, key = { movie -> movie.id }) { movie ->
            MovieOverview(movie)
        }
    }
}
```

### Skipping if the inputs haven't changed

もし`Composable`が既に`Composition`にある場合、全てのinputsが安定してるなら、recomposeがスキップできる。

そして、以下の型は`@Stable`を明示しなくても、安定性があると扱われてる。
- すべてのプリミティブ値型: Boolean、Int、Long、Float、Char など
- 文字列
- すべての関数型（ラムダ）

ただし、唯一可変型だけど安定性があるのが`MutableState`。

また`Compose`が安定性を区別できない場合がある。例えばinterface、公開プロパティが可変として、仮に実装で不変の値を使っても安定してると扱いされない。その場合は`@Stable`を使って`Compose`に指定できる。

```kotlin
// Marking the type as stable to favor skipping and smart recompositions.
@Stable
interface UiState<T : Result<T>> {
    val value: T?
    val exception: Throwable?

    val hasError: Boolean
        get() = exception != null
}
```

## 終わり

全然関係ないですけど、改行がうまく効かなくて、見にくいと改めて感じました。
【初心者】IntuneでWindows端末をワイプしたときのメモ

# 経緯
Intuneではリモートワイプができますが、オプション「デバイスをワイプして、デバイスの電源が切れてもワイプを続行します。」にチェックを入れるとどうなるか気になったので試してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/e8cfed5e-0712-d13a-6cc1-2b6b94876b35.png)



:::note info
再起動後に数分～数十分かけてワイプが進行し、もしその間に電源を切っても、またワイプが永久にループするという想定です。
:::

# 結論
想定した挙動とはちがいましたが、確かにリカバリが必要になったので、紛失対策としてはいったん機能しました。

# ワイプの実行

オプションにチェックを入れて実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/a22daf8b-d48e-d059-18e7-0f91e2505b0b.png)

即座に実行されました。他のリモートコマンドではトリガーから発動まで5分くらいかかる印象ですが。このあたりの挙動がまだつかめていません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/c0f08556-07fd-8f35-4c82-ea308a6e73a5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/8f5c31aa-ede6-11ed-3256-81373dd6c631.png)

# 再起動後

言語の選択画面になりました。日本語を選択する形になり、あまり見ない画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/3b46256a-fa3f-c2fe-3c24-4ecea90f6cfd.png)

強制的にトラブルシューティングの画面になります。ちょっと想定した動作とちがいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/9742ae42-0473-eb0b-ddbd-1abb616c6f6e.png)


スタートアップ修復を実行してみます。ちなみに他のオプションはすべてエラーとなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/869485c0-c2e9-b3a8-f628-7d7debc0fb28.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/241ab354-ae52-9765-81f9-65845a1aa8c9.png)

こちらもエラーです。復旧不可能のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/896b5ac7-b34d-f287-c9f3-b62afa7ebc27.png)

# Intune管理画面
管理画面ではデバイス自体が消えています。「完了」というステータスが出る認識でしたが、これもちょっと想定とちがいますね。仕様が変わったのでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/994185d2-ea1a-ca1c-8189-9bc37cc8ec5c.png)


# まとめ
- 想定した挙動とはちがいましたが、確かにリカバリが必要になったので、紛失対策としてはいったん機能しました。
- 企業内では、もうすこし多機種・多パターンで時間をかけてテストするのがよいとおもいます。


# 参考にさせていただいたサイト


**【Microsoft365】Windows端末の紛失・盗難時に利用できるMicrosoft Intuneの機能とは？(備忘録)**
https://qiita.com/empty948/items/7be48e65eca248b8238d

**【Microsoft365】Intune→Windows端末へのリモートワイプの仕様(備忘録)**
https://qiita.com/empty948/items/a820c9e812203586c4a0

**Intuneのワイプの挙動を確認してみる**
https://www.hondalabo.net/entry/2021/12/11/180000
WordPress ・PHP ・MySQLのサポート期間とバージョンアップによるパフォーマンス向上具合について

## はじめに

「WordPressのメンテナンスはどのぐらいの頻度で行った方がいいか」と質問をもらったり、議題に上がったりすることがあります。もちろん「できる限り頻繁」にするといいのですが、逆に放置した場合、「最初にサポートが終了するのは、WordPress、PHP、MySQLの内どれが最初なのだろう」という疑問からそれぞれのサポート期間について調べてみました。

[WordPress のホスティング要件](https://ja.wordpress.org/about/requirements/)

## WordPressのサポート期間

- アクティブサポートは新しいバージョンリリース時に、1つ前のバージョンが終了
- 打ち切られる可能性はあるが、セキュリティサポートは**できる限り**続けられる

**出典**
[Dropping security updates for WordPress versions 3.7 through 4.0](https://make.wordpress.org/security/2022/09/07/dropping-security-updates-for-wordpress-versions-3-7-through-4-0/)
[WordPress | endoflife.date](https://endoflife.date/wordpress)

## WordPressバージョンアップによるパフォーマンス向上具合

**WordPress 6.1.1と6.2の比較**

- ブロックテーマのロードスピード → **14 - 18%** 向上
- クラシックテーマのロードスピード → **2 - 5%** 向上
- ブロックテーマのサーバーサイドパフォーマンス → **17 - 23%** 向上
- クラシックテーマのサーバーサイドパフォーマンス → **3 - 5%** 向上

**出典**
[WordPress 6.2 Performance improvements for all themes](https://make.wordpress.org/core/2023/04/05/wordpress-6-2-performance-improvements-for-all-themes/)

## PHPのサポート期間 

- アクティブサポート期間 : リリースから**2年**
- セキュリティサポート期間 : アクティブサポート終了から**1年**

**出典**
[PHP: Supported Versions](https://www.php.net/supported-versions.php)

## PHPバージョンアップによるパフォーマンス向上の具合

- PHP**8.1**はPHP**8.0**よりも __47.10%__ 高速
- PHP**8.1**とPHP**7.2**と比較すると、PHP**8.1**は**1秒あたり50%以上**多くのリクエスト(またはトランザクション)を処理している

**出典**
[PHP 7.2、7.3、7.4、8.0、8.1のベンチマーク（2022年）- WordPress 5.9-RC2](https://kinsta.com/jp/blog/php-benchmarks/#wordpress-59rc2)

## MySQLのサポート期間

サポート完全終了はないが**9年目以降**は、

- メンテナンス・リリース
- バグ修正
- パッチ
- アップデートの提供

の「既存のもの」のみ対応となる。

**出典**
[MySQL :: MySQL テクニカル・サポート](https://www.mysql.com/jp/support/)

## MySQLバージョンアップによるパフォーマンス向上具合

> MySQL 8.0では、MySQL 5.7と比較してユーザー数が増えた場合に最大で約2倍ほどの大きな性能向上を実現しています。

**出典**
[MySQL 8.0正式版がリリース。性能が最大で2倍、JSONデータや地理情報などサポート。ロールによるユーザー権限の管理も可能に2018](https://www.publickey1.jp/blog/18/mysql_802json.html)

## まとめ

- WordPressのセキュリティアップデートは**できる限り**行われる 
- PHPのサポート完全終了はリリース日から**3年後**
- MySQLのサポートは**できる限り**行われる(ただし、**9年**で対応が少し変わる)

PHPだけ「できる限りセキュリティサポート」が行われないので、WordPress・PHP・MySQLの中で、一番最初に完全サポート終了するのは**PHP**です。

また、バージョンアップによるパフォーマンスの伸びが想像よりも大きいと感じました。
CSSまとめ

CSSについて学習したものをまとめる。
今後、新たに学習したものも追記すること。

■セレクタとプロパティ
CSSではHTMLの要素など変更する箇所を選択し、何をどうするかを以下のように記述する。変更する対象をセレクタ、変更内容をプロパティと言う。
以下の場合、h1がセレクタ、colorがプロパティになる。
セレクタの後は半角スペースを空け、プロパティは値を:;で指定し、{}で囲む。
プロパティはインデントも空けること。
`/* /`でコメントアウトも入れられる。

`h1　{`
`/* コメントアウト/`
`　　　　color: blue;`
`}`

特定の要素のみCSSで変更したい場合、HTMLでclassの属性を付けて
CSSで以下のように指定する。先頭に.(ドット)を絶対に忘れないこと。

HTML側
`<ul>`
`  <li class="CSSproperty">AAA</li>`
`　　　　<li>BBB</li>`
`  <li>CCC</li>`
`<ul>`

CSS側
`.CSSproperty {`
`　　　　font-size: 10px`
`}`

また特定要素内にある１つの要素のみ変更したい場合は
以下のように要素を並べて指定する。
複数の場合は,で並べて指定する。

HTML側
`<ul class="CSSproperty">`
`　　　　<h2>AAA</h2>`
`　　　　<a>BBB</>`
`<ul>`

CSS側
`.CSSproperty h2{`
`　　　　font-size: 10px`
`}`
⇨CSSproperty要素にあるh2要素のみ変更

`.CSSproperty h2, a{`
`　　　　font-size: 10px`
`}`
⇨CSSproperty要素にあるh2要素とa要素を変更

○プロパティの種類
・color
文字の色を変更できる。１６進数のカラーコードでも一般的な色の呼び方でも指定可能。
`color: red;`

・font-size
文字の大きさの変更。
`font-size: 10px;`

・font-family
文字のフォント変更。途中でスペースがある場合、""でくくる。
`font-family: "Avenir Next";`

・background-color
背景色の変更。指定方法はcolorと同じ。
`background-color: #dddddd;`

・width、height
要素の横幅と高さを変更。
`width: 100px;`
`height: 100px;`

・list-style
リストの変更。noneでリストの点を消せる。
`list-style: none;`

・float
要素の並び方を横並びに変更できる。
`float: left;`

・border
要素に枠線をつける。線の太さ、種類、色の順番で指定する。
上下左右につける場合はborder、特定方向の身につけたい場合はborder-"方向"で指定する。
`.AAA {`
`　　　　border-bottom: 10px solid blue;`
`}`

・padding、margin
要素の余白を調整。paddingは要素(border)の"内側"、marginは"外側"に余白を作る。
上下左右につける場合はpadding/marginのみ、特定方向のみにつけたい場合は
padding/margin-"方向"で指定する。
padding/marginで２つ指定する場合は上下と左右、４つ指定する場合は
時計回りに上、右、下、左で変更できる。

`.AAA {`
`　　　　padding: 10px 20px 10px 20px;`
`}`
⇨要素の上下に10px、左右に20pxの余白をつける。

■メディアクエリー

■flexbox
dbt-coreにおけるOSS活動ことはじめその5 ~ Issueの立て方、見つけ方の話 ~

# 本記事が目指すこと
- dbt-coreにおけるOSS活動を始めるにあたってやるべきこと、学びになったことを紹介する
    - 複数回に渡り連載する予定

# 注意
- 投稿時点(2023/6/9)での情報に基づくため、本記事で紹介した手順が今後も利用できる保証はありません
- なお、本記事は筆者が所属する会社と関係なく、個人の記事であることをご了承ください

# 背景
- 筆者は、ちゅらデータ株式会社に務める会社員であるが、就業時間中に職務としてのdbt-coreのOSS活動を始めた（OSS活動自体が初めての経験）
- CONTRIBUTING.mdには明示的に記載されてない部分があったため、それらの解決策を提示する

# 本編
Issueの立て方、見つけ方について簡単に紹介する。

**1.dbtが提供しているコントリビューター向けのドキュメントを読む**
- Expectations for OSS contributors
    - https://docs.getdbt.com/community/resources/oss-expectations#issue-labels

このドキュメントには、dbt-coreにOSS活動するにあたって理解しておくべき事柄が記述されている（CONTRIBUTING.mdの上位ドキュメントという位置づけ）。
例えば、サポート、トラブルシューティング、デバッグのサポートが必要な場合は、Issueを立てるのではなく、[Disscussion](https://github.com/dbt-labs/docs.getdbt.com/discussions)を開くか、[dbtコミュニティのSlack](https://www.getdbt.com/community/)の`#advice-dbt-help`で質問してください、といった想定されるケースに対する問い合わせ先や注意事項等が記述されている。

**2.Issueを見つける**
- 既存のバグを発見したり、追加したい機能がある場合は、関連するIssueがないか確認する
    - もし関連するIssueを発見して、まだ未解決であり良い提案を持っているのであればコメントする
- 自分自身がアイデアを持っていない場合は、既存のIssueから興味のあるIssueを見つける
    - `good_first_issue` というラベルがついたIssueは、初めてコントリビュートする人向けのIssue。詳細な説明があったり、解決の提案が出されていたりするのでオススメ。ただし、すでにPRが紐付けられていた場合は、新規にPRを作成することはやめた方が良い



**3.(既存のIssueが見つからない場合)Issueを立てる**
1.[New Issue]をクリックして、関連する項目を選択する
- Bug
    - バグまたは問題を報告する
- Feature
    - 機能の直接的な拡張を提案する
- Regression
    - 新しいバージョンで観察された回帰を報告する

2.定められたテンプレートに従い問題を記述し、[Submit new issue]をクリックする

参考までに筆者が作成したIssueを紹介
- https://github.com/dbt-labs/dbt-core/issues/7664

なお、Issueを作成すると関連する種類のタグ（例えばBugの場合は`bug`）とメンテナーによってレビューされていないことを示すタグ`triage`が自動で付与される。

その後、メンテナーによってレビューされた場合は、`triage`が削除されて、`awaiting_response`のタグがつけられる。

それに対し、コメントを返信すると、`awaiting_response`が削除されて、再び`triage`のタグがつけられる。

以上。

# 終わりに
ちゅらデータでは、クレイジーな仲間を募集しているでござる
データエンジニア、もしくはSE系からデータエンジニアになりたい方がいればぜひ、御仁の力量に応じたグレード（ジュニア/ミドル/シニア）にて、応募するでござる

https://herp.careers/v1/churadata/T6Oag1FxE34V
[Deno] x/dotenvモジュールは非推奨！`--env`フラグを使おう

Denoでdotenvを使う際は、これまでサードパーティモジュールの[`x/dotenv`](https://deno.land/x/dotenv@v3.2.2)を使うのが一般的でした。

しかし、**`x/dotenv`は一旦標準ライブラリに移植されたものの、Deno CLI本体の機能に取り込まれたため、非推奨になっています**。
~~`x/dotenv`ではなく、[標準ライブラリの`@std/dotenv`](https://jsr.io/@std/dotenv)を使うようにしましょう~~。

`x/dotenv`や標準ライブラリではなく、**実行時にコマンドラインフラグの`--env`を使うようにしましょう**



```diff_typescript
- import "https://deno.land/x/dotenv@v3.2.2/load.ts";
```

```diff_shell
- deno run ./main.ts
+ deno run --env main.ts
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/c9ce2a3f-6439-fe57-ae4a-eb7f5d65cbd1.png)
▲`x/dotenv`は「DEPRECATED」(非推奨)と書かれています。

# `--env`フラグの使い方

`deno run`コマンドに`--env`フラグを渡すと、自動でカレントディレクトリの`.env`ファイルを読み取ってくれます。

```ini:.env (例)
GREETING=hello world
# コメントはこう書く
```

```shell:実行時に.envファイルを自動で読み込む
# カレントディレクトリの.envファイルを読み取る
$ deno run --env --allow-env=GREETING ./main.ts
```


```ts:設定した環境変数の使用方法
console.log(Deno.env.get("GREETING"));
```

Denoにはセキュリティサンドボックス機能があるため、環境変数にアクセスする際は実行時に`--allow-env`フラグを使用する必要があることに注意してください。

`.env`以外のファイルを読み込みたい場合は、フラグにファイル名を指定します。

```shell:実行時に.envファイルを自動で読み込む
# カレントディレクトリの.envファイルを読み取る
$ deno run --env=./.env.development --allow-env=GREETING ./main.ts
```



# deno deployで環境変数を設定する方法

deno deployはDenoを動かすことができるEdge Runtimeサービスです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/8f7aadc5-51a7-2ac8-b5f4-6bc96bc76e6c.png)
▲deno deployの管理画面の環境変数設定

おそらく通常のユースケースでは、

- ローカルではdotenvファイルを使用して環境変数を管理
- deno deploy上では、**deno deployの管理画面から環境変数を管理**

のようになると思います。

そのため、`.env`ファイルは`.gitignore`でGit管理しないように設定した上で、deno deployの管理画面で環境変数を指定するのが一般的だと思います。

# 🍋Freshでdotenvを使用する方法

FreshはDeno社製のフレームワークです。preactを使用するDeno版のNext.jsのような立ち位置で、便利で使いやすいです。

https://fresh.deno.dev/

Fresh v1.1.6より、`.env`ファイルが自動で読み込まれるようになっています。
そのため、**`x/dotenv`や`@std/dotenv`をimportしたり、`--env`フラグを渡したりする必要はありません**。

# まとめ

- [`x/dotenv`](https://deno.land/x/dotenv@v3.2.2)や[標準ライブラリの`@std/dotenv`](https://jsr.io/@std/dotenv)ではなく、Deno本体の`--env`フラグを使おう
    - [`x/dotenv`](https://deno.land/x/dotenv@v3.2.2)は[標準ライブラリの`@std/dotenv`](https://jsr.io/@std/dotenv)に移植された
    - その後、Deno本体に`--env`フラグが導入され、`.env`ファイルを直接読み込めるようになった
- deno deployでは管理画面から環境変数を設定できる
- Freshでは何もしなくても.envファイルを読み込んでくれる
AWSコスト最適化：失敗編（CloudWatch アラーム定義増殖事件）

# 1. はじめに
今回は [コスト最適化の勘所](https://qiita.com/pohd_ccoe/items/8d5afc62c3488df18b39 "コスト最適化の勘所")で記載した「6.持続したコスト管理の重要性」を疎かにしてしまったが故の失敗事例になります。

失敗事例というのは外部公開を忌避する事が多いかと思います。
しかし、失敗事例にこそ多くの学びがあるという思想の下、そういった事例もなるべく隠さず公開していこうと思います。

# 2. 背景
弊社の某システム（仮称：Aシステム）ではWebサーバをホストするEC2にオートスケールを採用しています。
スケールアウトしたEC2に対しても監視/通知が必要な為、スケールアウトしたEC2のカスタムメトリクスに対するアラーム定義を追加する処理を実装しています。このアラーム定義はEC2がスケールインすると不要になりますので、削除する処理も実装していました。

処理自体は AutoScalingGroup のイベントを EventBridge でフックし、Lambdaでアラーム定義を操作する形で実装しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333262/ef27864c-713f-700f-1a54-33cf5ede6114.png)







# 3. 異変の気付き
AWSコスト管理を本格開始した頃、リリースから1年近く経つAシステムのCloudWatch費用がリリース直後から緩やかに上昇を続けている事に気が付きました。
スケールアウト/インに伴ってCloudWatch費用が変動することはありますが、上昇をずっと続けるのは違和感があります。

調べてみると、アラーム定義が検証環境では **約25,000** 件、本番環境では **約7,000** 件と膨大な数になっており、これがCloudWatch費用を押し上げていました。


# 4. 原因
## 4.1. アラーム定義削除が正常に動いていない
ここまで増殖した原因は、先述したアラーム定義削除処理が正常に動いていない事でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333262/fba9be75-505c-d23d-30d1-e969f87e161d.png)




## 4.2. 何故動いていなかったのか
### 4.2.1. 検証環境
検証環境が複数存在する為、本番環境に比してEC2がかなりの台数存在します。

検証環境にある多数のサーバに対してスケールインが一斉に行われる運用が存在し、呼び出されたLambdaが処理を実施したものの、CloudWatchのクォータ（※1）に引っ掛かってしまい処理が失敗していました。
この処理自体にはリトライ処理が含まれておらず、実行結果監視も行われていなかった為、削除処理失敗が検知されず不要なアラームがひたすら積みあがっていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333262/fc2573ef-1028-ecb0-2105-635c118c10c0.png)


- - -

※1…CloudWatch のクォータ自体は [こちら](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/cloudwatch_limits.html "CloudWatchクォータ") に情報がまとまっております
恐らく下記の記述部分に引っ掛かったようです。


>DeleteAlarms リクエスト
>オペレーションごとに、リージョンあたり 3 TPS
>スロットリングなしで 1 秒あたりに実行できるオペレーションリクエストの最大数。
>これらのクォータは変更できません。

  
　
### 4.2.2. 本番環境
本番環境では処理中のセッションに影響が出ないよう、事前にAutoScalingGroupからスケールインするEC2のデタッチを実施していました。
しかし、デタッチした事で本来EventBridgeが検知するスケールインイベントが発生せず、用意されたアラーム定義削除処理がそもそも実行されないという事態が発生しており、こちらも不要なアラーム定義がひたすら積みあがっていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3333262/83bbf1a3-f7d8-1e9a-0e77-39116388083f.png)



# 5. 対処
## 5.1. 暫定対処
幸い、Aシステムの提供するサービスに直結するようなトラブルではありませんでした。
しかし、AWSコストを押し上げているのは間違いありませんので、本来は削除されているべき不要なアラーム定義の削除を暫定対処として実施しました。

## 5.2. 根本対処
Aシステムは本番環境にせよ、検証環境にせよ、運用上多数のサーバを同時にスケールインすることが考えられるシステムとなっています。
この為、以下2点を根本対処として行いました
- アラーム定義削除処理に対してリトライ処理を追加
- スケールインの後続処理とは別に、アラーム定義削除処理を実施するバッチ処理の実装


# 6. 振り返りと教訓
## 6.1. スケールアウトに伴う処理
スケールアウトに伴ってアラーム定義を増やすことは認識していましたが、削除処理が失敗するパターンを想定できていませんでした。そのため、リトライ処理や不要アラーム定義を検知して定期削除するバッチ処理等、処理が失敗した場合のリカバリ対応が構築できておらず、今回の問題が発生してしいました。



## 6.2. AWSコストの継続的管理
Aシステムリリースから1年近く時間が経っていたこともあり、結果として軽自動車を購入できる程の余計なAWSコストを発生させてしまいました。
上昇幅が非常に緩やかだったため異変に気付くのが遅れた面もありますが、AWSコスト管理・運用がしっかりと実施出来ていればもっと早期に発見し、対策が打てていたかと思います。

CloudWatchに限らず、AWSサービス単位もしくはサービス毎の課金科目単位でAWSコスト変動の状況を捉えて原因を分析し、対策を講ずるというAWSコスト管理の重要性を痛感した失敗でした。

オートスケールを実装し、スケールしたリソースのアラーム定義追加/削除を実装しているシステムでは是非同じ観点での確認をお勧めします。
IBM Cloud VPCの仮想サーバーでmtrコマンドを使う

IBM Cloudに限った話ではありませんが、サーバーと外部との通信が想定通りできない時（疎通しない、または疎通しても遅い等）、通信先までの経路を確認したい事があります。

IBM Cloudではcaseでネットワーク周りについて問い合わせると、mtrコマンドの出力を求められる事がよくありますが、デフォルトのSecurity Groups設定では必要な通信が許可されておらず、mtrを取得するためにSecurity Groupsのルールを変更する必要があったので、メモです。

mtrコマンドの中ではICMPが使われます。VPCのSecurity Groupsでは、VPCをデフォルトのオプションで作成すると、0.0.0.0/0からのICMPが許可されているので、直感的には特に設定しなくても大丈夫そうですが、実際にmtrコマンドを実行しても、何も出力されません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/d65c06f6-d19e-0349-ef32-0d395c84eb8e.png)

```
# mtr -r -c 10 -n 8.8.8.8
Start: Fri Jun  9 08:00:16 2023
HOST: tmgw-vsi                    Loss%   Snt   Last   Avg  Best  Wrst StDev
#
```

これは、デフォルトで許可されているICMPのタイプが8であるためです。mtrの実行中には、ICMPのtype 11も使われるので、これを許可する必要があります。ICMPを許可するルールについて、タイプを「すべて」に変更しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59627/7ed83c3f-2bcc-ba9f-ce3e-7f610f546b88.png)

これで想定通り、経路情報を確認できるようになりました。

```
# mtr -r -c 10 -n 8.8.8.8
Start: Fri Jun  9 08:01:06 2023
HOST: tmgw-vsi                    Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- ???                       100.0    10    0.0   0.0   0.0   0.0   0.0
  2.|-- 158.176.xxx.xxx            0.0%    10    1.1   3.1   1.1  14.3   4.0
  3.|-- 158.176.xxx.xxx            0.0%    10    8.6   6.2   0.6  28.3   8.8
  4.|-- 169.45.xx.xx              10.0%    10    2.6   2.5   2.5   2.6   0.0
  5.|-- 169.45.xx.xx               0.0%    10    1.8   2.5   1.4  10.8   2.8
  6.|-- 195.66.xxx.xxx             0.0%    10    1.6   1.8   1.6   2.9   0.3
  7.|-- 108.170.xxx.xxx            0.0%    10    2.6   2.8   2.4   3.1   0.0
  8.|-- 216.239.xx.xxx             0.0%    10    2.4   2.4   2.3   2.6   0.0
  9.|-- 8.8.8.8                    0.0%    10    1.6   1.6   1.5   1.6   0.0
#
```

以上
bootstrap5 と jqueryでチャット画面を作る

# HTML

```html
<!DOCTYPE html>
<html>
<head>
    <title>Chat UI</title>
<!-- jQuery 3.5.1 -->
<script src="https://code.jquery.com/jquery-3.5.1.js"
	integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
	crossorigin="anonymous"></script>
<!-- bootstrap 5 -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
	crossorigin="anonymous">
    <style>
        .chat-box {
            height: 500px;
            overflow-y: auto;
            border: 1px solid #ccc;
            margin-bottom: 10px;
            padding: 10px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="chat-box" id="chatBox"></div>
        <div class="input-group">
            <input type="text" class="form-control" id="messageInput" placeholder="メッセージを入力してください...">
            <button class="btn btn-primary" id="sendBtn">送信</button>
        </div>
    </div>
    <script src="chat.js"></script>
</body>
</html>
```

# JavaSript

```javascript
$(document).ready(function() {
    // 事前にチャット履歴をロードします（デモ用にハードコード）
    var chatHistory = ['Hello, User!', 'How can I help you today?', 'You: Hi there!'];
    chatHistory.forEach(function(message) {
        $('#chatBox').append($('<p>').text(message));
    });

    // 新しいメッセージが入力されたときにチャットボックスに追加します
    $('#sendBtn').click(function() {
        var message = $('#messageInput').val();
        if (message) {
            $('#chatBox').append($('<p>').text('You: ' + message));
            $('#messageInput').val('');
            scrollToBottom();
        }
    });

    // チャットボックスのスクロールを最下部に保つ関数
    function scrollToBottom() {
        $('#chatBox').scrollTop($('#chatBox')[0].scrollHeight);
    }

    // チャット履歴がロードされた後にスクロールを最下部にスクロールします
    scrollToBottom();
});
```

# 結果

こんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/729f5814-4808-34e5-bc31-da7256345533.png)

# 謝辞

本投稿の作成に際して ChatGPT 様には大変なお世話になりました。
ありがとうございます。









以上
cropper.jsでアスペクト比に下限/上限を設ける方法

[cropper.js](https://fengyuanchen.github.io/cropperjs/)というブラウザ上で画像をリサイズするjsライブラリがあり、
画像をブラウザ上で任意のサイズに切り取ってからアップロードするという処理などに使ったりします。

非常に優れたライブラリなのですが、アスペクト比を一定の範囲内で可変にするという動きが出来なかったので実装してみました。

# 課題

アスペクト比を指定するには`setAspectRatio`メソッドで比率を指定すればよいのですが、
`setAspectRatio`を呼び出すと選択範囲をリセットする動きもします。

変更したいアスペクト比が予め固定でよければ、公式サイトにあるデモのようにアスペクト比変更ボタンを置けばいいのですが、
今回やりたかったことはアスペクト比を自由に変更しつつ、範囲を指定することでした。
例）1:1〜16:9の間で自由に指定

# 対応内容

単純に、

1. 現在の選択範囲を取得
1. その時点でのアスペクト比を確認
1. 範囲外なら、範囲内のアスペクト比に変更
1. 選択範囲がリセットされるので、1で取得した選択範囲に上書き

という動きで対応しました。

具体的には、cropperの選択範囲を変更するたびに実行される`cropmove`トリガーに以下の処理を入れます。

```js
const aspectLowerLimit = アスペクト比の下限;
const aspectUpperLimit = アスペクト比の上限;

// 現在の選択範囲
const cropBoxData = cropper.getCropBoxData();

// 現在のアスペクト比
const aspect = cropBoxData.width / cropBoxData.height;
if (aspect < aspectLowerLimit) {
  // 下限を下回る場合、下限に変更
  cropper.setAspectRatio(aspectLowerLimit);
} else if (aspect > aspectUpperLimit) {
  // 上限を上回る場合、上限に変更
  cropper.setAspectRatio(aspectUpperLimit);
} else {
  // 範囲内なら自由に選択できるのでアスペクト比の指定を無効化
  cropper.setAspectRatio(NaN);
}
// 選択範囲がリセットされるので先程取得した選択範囲で上書き
cropper.setCropBoxData(cropBoxData);
```

# 完成品

サンプルとして、1:1から16:9の範囲でアスペクト比を自由に変えられるものを作成しました。

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="QWPpQBZ" data-user="kametter" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kametter/pen/QWPpQBZ">
  Cropper.jsのアスペクト比を範囲内で調整可能にするサンプル</a> by kametter (<a href="https://codepen.io/kametter">@kametter</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

微妙にカクカクするときがありますが、概ね期待通りに動いています。
アスペクト比の判定が前回と同じなら`setAspectRaito`を呼び出さないようにする処理を追加して負荷軽減できればいいんですが、カーソルの判定のためか境界を行ったり来たりするようでいい感じにしあげられませんでした。
カーソルの移動方向を見ればいい感じにできるかもしれないので、折を見て調査してみます。
JavaScriptで配列からランダムな数字を生成する

以前、女神転生の「コードブレイカー」をRubyで再現したことがあるが、
それをブラウザで動かしてみたくなったのでJavaScriptでコーディングしてみようと考えた。

そこで、真っ先に躓いたのが、答えとなる数字の生成。

3桁の重複しない数字を生成するのに、
Rubyでは
```Ruby:
# 抽出元の配列を生成
arr1 = (0..9).to_a

# 配列からランダムに3つを選択
ans1 = code.sample(3)
```
たったこれだけでいい。
便利なメソッドを開発者が用意してくれているお陰である。

しかし、JavaScriptには
「一定範囲の数値を配列化できるメソッド」も
「配列から指定した個数の要素をランダムに選ぶメソッド」も
**存在しない**のである。

だからどうした、無ければ作るまでだ、と、
検索と試行錯誤を繰り返した末、どうにかそれらしいものは作れた。
使う機会があるかわからないが、参考になれば幸いである。

## 抽出元の配列を作る

範囲オブジェクト（(0..9)の部分）が使えないので、
地道に数字を手打ちして作った。

```JavaScript:
const arr1 = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
```

作りながら、ふと
「これ、ビンゴゲームなんか作りたい時、どうするんだろうか」
と不安になったが、今は考えないことにする。

## 配列から指定した個数の要素をランダムに選ぶ

ランダムに選ぶメソッドがないので、
「乱数に抽出元の配列の長さをかけた数値を作る」
「Math.floor()関数で小数点以下を切り捨てて整数にする」
「出来た整数と同じインデックス(番地)の要素を選び、空の配列に加える」
「元の配列から選択された要素を削除する」
という流れで処理することにした。
この一連の処理を、配列の長さが3になるまで繰り返す。
```JavaScript:
let ans1 = [];
while(ans1.length < 3) {
    // 配列からランダムに選ぶ
    const rand = Math.floor(Math.random() * arr1.length);
    // 選んだ要素を答え用の配列に入れる
    ans1.push(arr1[rand]);
    // 元の配列からは消す（重複防止）
    arr1.splice(rand, 1);
    }
    return ans1;
```

乱数の所で配列の長さを掛けているのは、0～9の数字の数を掛けると、
2回目以降の選択では配列の長さが1ずつ減るので、
乱数が2回目に9、3回目に8か9になってしまうと、
存在しないインデックスを参照してしまうため。

最後のreturnは出来上がった配列を次の処理に渡すためのもの。
JavaScriptで文字の拡大縮小

# はじめに
JavaScriptの学習にHTMLのリンク文字に拡大縮小の機能を作りました。
忘れるときのため、メモを取ることにしました。
# コード
```JavaScript:JavaScript
const links = document.querySelectorAll('.navlink');

links.forEach(link => {
  link.addEventListener('mouseover', () => {
    link.style.fontSize = '1.2rem';
    link.style.color = '#3db';
  });

  link.addEventListener('mouseout', () => {
    link.style.fontSize = '1rem';
    link.style.color = '#432';
  });
});
```
```HTML:HTML
<nav>
  <ul class="main-nav">
    <li><a href="#nav1" class="navlink">デイトラとは</a></li>
    <li><a href="#nav2" class="navlink">コース一覧</a></li>
    <li><a href="#nav3" class="navlink">お問い合わせ</a></li>
  </ul>
</nav>
```
```CSS:CSS
.navlink {
  color: #432;
  font-size: 1rem;
}
.navlink:hover { //削除
  color: #3bd; //削除
  font-size: 1.2rem; //削除
} //削除
```
# 説明
const linksという定数を作ります。
document.querySelectorAll('.navlink')の返り値をLinksに代入します。
querySelectorAll(): 指定されたCSSセレクターと同じHTMLの要素のリストを静的なNodeListを返します。
links.forEach: ForEach文を使って、links内格納した配列を取得する。
link.addEventListener: addEventListenerによるターゲット(マウスを重なった時)の特定と呼び出し。
link.style.fontSize: styleプロパティのfontSize属性値？を変更する。
link.style.color: styleプロパティのcolor(文字色)属性値？を変更する。
以下のコードは上記と同じマウスが離れた時の指定です。
Databricksでサービングする大規模言語モデルのGUIをChainlitで構築する

思った以上にチャットbotになりました。

https://docs.chainlit.io/overview

ベースの記事はこちらです。DatabricksにLangChain + OpenAI APIのLLMをデプロイしています。

https://qiita.com/taka_yayoi/items/43302d79369a36b66ee4

以下のコードを記述します。

```py:databricks.py
import os
from langchain import PromptTemplate, OpenAI, LLMChain
import chainlit as cl
from chainlit import on_message

import numpy as np 
from PIL import Image
import base64
import io

import os
import requests
import numpy as np
import pandas as pd

import json

def create_tf_serving_json(data):
    return {
        "inputs": {name: data[name].tolist() for name in data.keys()}
        if isinstance(data, dict)
        else data.tolist()
    }


def score_model(question):
  # 1. パーソナルアクセストークンを設定してください
  token = "<Databricksパーソナルアクセストークン>"

  # 2. モデルエンドポイントのURLを設定してください
  url = "<モデルエンドポイントのURL>"
  headers = {'Authorization': f'Bearer {token}',
             "Content-Type": "application/json",}

  dataset = pd.DataFrame({'question':[question]})

  ds_dict = (
        {"dataframe_split": dataset.to_dict(orient="split")}
        if isinstance(dataset, pd.DataFrame)
        else create_tf_serving_json(dataset)
    )
  data_json = json.dumps(ds_dict, allow_nan=True)
  response = requests.request(method="POST", headers=headers, url=url, data=data_json)
  if response.status_code != 200:
    raise Exception(
       f"Request failed with status {response.status_code}, {response.text}"
    )
  
  return response.json()


@on_message
def main(message: str):

    response = score_model(message)

    answer = response['predictions'][0]["answer"]
    source = response['predictions'][0]["source"]

    # Send a response back to the user
    cl.Message(
        content=f"{answer}\n\nソース: {source}",
    ).send()
```

```
chainlit run databricks.py -w
```

チャット🤖だー。

![Screenshot 2023-06-09 at 16.42.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/53ec190d-c234-aadd-3e97-65c2630cf376.png)


### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
js的

```
<!DOCTYPE html>
<html>
<body>

<h2>4つの値を入力してください：</h2>

<label for="value1">値1：</label><br>
<input type="text" id="value1" name="value1"><br>
<label for="value2">値2：</label><br>
<input type="text" id="value2" name="value2"><br>
<label for="value3">値3：</label><br>
<input type="text" id="value3" name="value3"><br>
<label for="value4">値4：</label><br>
<input type="text" id="value4" name="value4"><br>

<button onclick="getInputs()">提出</button>

<p id="result"></p>

<script>
function getInputs() {
  var inputs = [
    document.getElementById("value1").value,
    document.getElementById("value2").value,
    document.getElementById("value3").value,
    document.getElementById("value4").value
  ];
  var formatted_inputs = inputs.map(i => `"${i}"`).join(" ");
  document.getElementById("result").innerText = formatted_inputs;
}
</script>

</body>
</html>



```
20分でまとめる備忘録　UIPaddingについて

## 備忘録するきっかけ
UiListLayoutのpaddingは要素と要素の内側しか調節できず、外側の上下左右がいじれなかったので代わりを探していた
# UIPaddingとは
UIPaddingは、RobloxのUIオブジェクトで使用されるプロパティの1つ。UIPaddingは、親オブジェクト内の子オブジェクトの配置や間隔を制御するために使用される子オブジェクトの間隔を設定したり、子オブジェクトの配置を調整したりすることができる。
## UIPaddingのプロパティ
UIPaddingには、次のプロパティがる

UIPadding.PaddingLeft：親オブジェクトと子オブジェクトの左側の余白を設定します。
UIPadding.PaddingRight：親オブジェクトと子オブジェクトの右側の余白を設定します。
UIPadding.PaddingTop：親オブジェクトと子オブジェクトの上側の余白を設定します。
UIPadding.PaddingBottom：親オブジェクトと子オブジェクトの下側の余白を設定します。

## 以下、UIPaddingの使用例
このように子要素の一番外側基準で
動かすことができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473989/e63e3153-85fe-e78a-3969-adb114544349.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473989/4fa9a89b-56ff-8b40-98b0-a1b0e48cc725.png)

## 感想
要素と要素の幅を開けるときは大抵UIのレイアウトを調節する意図だと思うので、UiListLayout系と一緒に使うことが多そう
Python3エンジニア基礎試験_模擬試験の復習②


# if文の説明（公式）

if 文は、式を一つ一つ評価してゆき、<font color="Red">**真になるまで**</font>続けて、真になった節のスイートだけを選択します

https://docs.python.org/ja/3/reference/compound_stmts.html?#the-if-statement

# if文の問題

```if.py
if []:
    print('「正解です」')
else:
    print('「不正解です」') 
# 「不正解です」
```

※空のシーケンスまたはコレクション: <font color="Red">__** ‘’, (), [], {}, set(), range(0)__</font> は <font color="Red">**False**</font>と判断されます。

```if.py
trick = False
treat = False

if not (trick or treat):  # 真ではない
    print('Hmmm')
elif trick and not treat:
    print('Yuck!')
elif not trick and treat:
    print('Yay!')
else:
    print('What?')
# Hmmm
```

・if 文では not が入っているため、 trick は True という扱いになります。
　また、treat も判断の対象ですが or で判断しているので、trick が True であれば真と判断され
　「Hmmm」が出力されます。

● 解説
最初の行では、trick と treat の初期値がともに False に設定されています。

条件文では、<font color="Red">not (trick or treat) </font>という条件式が評価されます。
この条件式は、<font color="Red">trick または treat のいずれかが True でない場合に真</font>となります。

もし条件式が真であれば、print('Hmmm') というメッセージが表示されます。
つまり、trick と treat のどちらも False の場合に 'Hmmm' というメッセージが表示されます。

次に、<font color="Red">elif trick and not treat: </font>の条件式が評価されます。
これは、<font color="Red">trick が True であり、treat が False の場合に真</font>となります。

もし条件式が真であれば、print('Yuck!') というメッセージが表示されます。
つまり、trick が True であり、treat が False の場合に 'Yuck!' というメッセージが表示されます。

次に、<font color="Red">elif not trick and treat: </font>の条件式が評価されます。
これは、<font color="Red">trick が False であり、treat が True の場合に真</font>となります。

もし条件式が真であれば、print('Yay!') というメッセージが表示されます。
つまり、trick が False であり、treat が True の場合に 'Yay!' というメッセージが表示されます。

最後の else ブロックでは、どの条件も真ではない場合に実行されます。
つまり、trick と treat のいずれも True ではなく、かつどちらも False でもない場合に 
'What?' というメッセージが表示されます。

```if.py
lst = [0,1,1,2,3,5,8,13]
n = 13

if lst[n % 5] > 2: # lst[]はリスト!!
    print(lst[n // 5])
else:
    print(lst[n // 5] - 1)  
# 0
```

・n%5 は 13%5 の結果です。余りなので 3 です。
　lst[3] は前から 4 番目の 2 です。if 文の条件、2>2 は満たされないので else に流れます。
　else の出力ですが、n//5 は 13//5 です。これは切り捨て除算なので解は 2 になります。
　lst[2] は 1 です。1 - 1 はゼロですので、ゼロが正解になります。
Python3エンジニア基礎試験_模擬試験の復習①

# 公式：Python チュートリアル

Python3エンジニア基礎試験の参考書

https://docs.python.org/ja/3/tutorial/index.html

# スライスの問題

```slice.py
fibo = [0,1,1,2,3,5,8,13,34,55,89]
fibo[-3:-3]= [21]
print(fibo)
# [0,1,1,2,3,5,8,13,21,34,55,89]
```

※スライスでは、<font color="Red">**開始インデックスは含まれますが、終了インデックスは含まれません。**</font>
したがって、<font color="Red">**開始と終了が同じ場合、スライス範囲は要素を含まない空の範囲となります。**</font>

# print文の問題

```print.py
total = 780
print("「お会計は", total, "円です。」")
# 「お会計は 780 円です。」
```

・他の選択肢にあった、"print(‘「お会計は’ + total + ‘円です。」’)"は誤り。
　strとintの混合となり、TypeErrorとなる。
　この場合は、"print(‘「お会計は’ + str(total) + ‘円です。」’)"とする。

# スライスの問題

```slice.py
letters = ['a','b','c','d', 'e']
letters[-4:-2] = []
print(letters)
# ['a', 'd', 'e']
```

・まず、リスト letters には文字列 'a', 'b', 'c', 'd', 'e' の5つの要素が含まれています。
　次に、スライスを使用して要素の一部を指定しています。
　<font color="Red">**letters[-4:-2] は、リストの後ろから4番目の要素 'b' と3番目の要素 'c' を含む部分リストを取得します。**</font>
　そして、[] を使用してこの部分リストを空のリストで置き換えます。
　つまり、['b', 'c'] の要素が削除され、リスト letters は ['a', 'd', 'e'] となります。　
　最後に、print(letters) を使用して変更後のリスト letters を出力します。
　出力結果は ['a', 'd', 'e'] となります。

# while文の問題

```while.py
a = 0
b = [2,3,4,5,6]

while a < len(b):
    print(a, end=',')
    a = b[a]
# 0, 2, 4
```

- 処理の流れ
1. 変数 a に初期値 0 を代入します。
2. リスト b の要素数を取得し、その値と a を比較します。
3. a が b の要素数より小さい場合、以下の処理を繰り返します：
4. a の値を出力します（print(a, end=',')）。
5. b[a] の値を a に代入します。つまり、b の a 番目の要素を取得して a に格納します。
6. a が b の要素数以上になった場合、ループを終了します。

- 例えば、与えられたリスト b の要素が [2, 3, 4, 5, 6] の場合、以下のように処理が進行します：
1. a の初期値は 0 なので、最初に 0 を出力します。
2. b[0] の値は 2 なので、a に 2 を代入します。
3. a の値は 2 なので、次に 2 を出力します。
4. b[2] の値は 4 なので、a に 4 を代入します。
5. a の値は 4 なので、次に 4 を出力します。
6. b[4] の値は 6 なので、a に 6 を代入します。
7. a の値は 6 なので、次に 6 を出力します。
8. b[6] のインデックスは存在しないため、ループを終了します。

# while文の問題

```while.py
a, b = 0, 2
lst = []

while a < b ** 2:
    lst.append(1)
    a = a + 1 # aはwhile文の真偽を判断する材料の役割
    print(lst, end=',')
# [1],[1, 1],[1, 1, 1],[1, 1, 1, 1],
```

- 変数 a と b を定義し、lst という空のリストを作成します。その後、a が b の2乗よりも小さい間、
　以下の処理を繰り返します。

1. lst に値 1 を追加します。
2. a の値を1増やします。
3. lst の内容を表示します。

 具体的には、lst の要素が 1 になりながら、繰り返し処理が行われます。
 ループの終了条件は a < b ** 2 ですので、a が b の2乗以上になった時点でループが終了します。
 ループの各イテレーションで、lst に要素が追加され、それが表示されます。
 最終的には、lst の要素が表示されることになります。
Qiita アップデートのお知らせ - 2023年 05月

![thumbnail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/6dc4623a-193e-501f-f123-85b31c516077.png)

## はじめに
Qiitaでは、エンジニアのみなさんからの声をもとに、日々開発を続けています。
この記事では、2023年05月にリリースした内容を紹介します。

Qiitaでアップデートやバグ修正をリリースしたら、[リリースノート](https://qiita.com/release-notes)、[Qiita 公式 Twitter](https://twitter.com/Qiita)、[Qiita Blog](https://blog.qiita.com/)でお知らせしています。

また、Qiitaへの質問や機能の要望などがありましたら、[Qiita Discussions](https://github.com/increments/qiita-discussions) へご投稿ください。


## イベントのアーカイブ動画をみれるようになりました
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/e3de56a3-680c-151a-db17-7c2ddb40be45.png)
*2023年 05月11日 リリース*

[公式イベントページ](https://qiita.com/official-events)からイベントのアーカイブ動画を見れるようになりました。


## 検索結果ページにてページ数が多く表示されてしまう不具合を解消しました
*2023年 05月09日 リリース*

検索結果ページにてページ数が多く表示されてしまう不具合を解消しました。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/beb0ec24-3f95-77c8-e5be-a6ae2a7c21bc.png)


## アップロードしたファイルのURLをコピーする機能を公開しました
*2023年 05月10日 リリース*

アップロードしたファイルのURLをコピーする機能を公開しました。
ログイン後に [アップロードしたファイルページ](/settings/upload_images) でファイルのURLをコピーすることが可能です。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/201aa120-fcab-980c-6714-e4ad71e0886c.png)


## ベータ版でのダークモード適用時のチラつきを一部のページで解消しました
*2023年 05月23日 リリース*

一部のページのみですが、読み込み時のチラつきを解消しました。
以下のページで対応しています。

- 記事ページ
- [ホームフィードページ](/)
- [タイムラインフィードページ](/timeline)
- [トレンドフィードページ](/trend)
- [質問フィードページ](/question-trend)
- [公式イベントページ](/official-events)
- [公式コラムページ](/official-columns)
- [募集ページ](/opportunities)
- [Organizationページ](/organizations)


## 複数ページでダークモード対応をベータ版として公開しました。
*2023年 05月10日, 2023年 05月29日 リリース*

以下のページのダークモード対応をベータ版として公開しました。

+ 下書きページ
+ 編集履歴ページ
+ 編集リクエストページ
+ いいねしたユーザーページ
+ 検索ページ
+ 公式イベント詳細ページ
+ 通知一覧ページ
+ 設定ページ

[以前お知らせした記事ページのダークモード対応](https://qiita.com/release-notes/2023-02-15)と同様の変更です。
詳しい設定方法は[Qiita Blog](https://blog.qiita.com/article-page-dark-mode-beta)をご覧ください。


## シンタックスハイライトを一部改善しました
*2023年 05月31日 リリース*

一部の言語でシンタックスハイライトが上手く適用されていなかったため、改善しました。

| Before | After |
| ----- | ----- |
| ![変更前のスクリーンショット。構文は正しいがエラーのように表示されている。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/d82e3284-aed9-34ff-80b1-d88e5e3ad78a.png) | ![変更後のスクリーンショット。正しくシンタックスハイライトされている。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/7e499db2-9458-7c7e-5460-018549d973e5.png) |
Docker ポート番号重複エラーを解消しよう

# Docker使用中にポート番号重複エラーが起こる
[独学エンジニア](https://dokugaku-engineer.com/)という教材を使用しプログラミングの学習をはじめたところです。
環境構築でエラーがたくさん出たので書き残していこうと思います。

## 開発環境
Docker Desktop for Windows v4.19.0
Windows11 Home 


## エラー内容
`docker compose up -d` を実行するとエラーが起こります。

```bash
[+] Running 2/3
 ✔ Network part2_default  Created                                             0.0s
 ✔ Container part2-db-1   Started                                             0.7s
 - Container part2-app-1  Starting                                             0.7s
Error response from daemon: Ports are not available: 
exposing port TCP 0.0.0.0:50080 -> 0.0.0.0:0: listen tcp 0.0.0.0:50080: bind: 
An attempt was made to access a socket in a way forbidden by its access permissions.
```
このエラーは、すでに別のサービスやプロセスが指定されたポートを占有している場合に出てくるそうです。

## 調べよう
Google検索で出てきたコマンドをいろいろ試してみます。
### ポート(50080)を使用しているのプロセスのIDを調べる


```bash
Get-Process -Id (Get-NetTCPConnection -LocalPort 50080).OwningProcess
```

→エラーが返ってきました。
ポート50080を占有しているプロセスを特定することができませんでした。

```bash
netstat -ano | findstr :50080
```

→何も返ってきません。

### ポート50080への接続をテストする

```bash
Test-NetConnection -Port 50080
```
→エラーが返ってきました。
ポート50080への接続を試みますが、接続失敗。

### 調べた結果
すでに使用しているプロセス等はなさそうでした。

## 対処①効果あり － ホストネットワークサービスの再起動

1\. まずDockerのコンテナを停止します。


```bash
docker compose down
```

2\. ホストネットワークサービスを再起動します。
```bash
net stop hns
```
3\. あらためてDockerコンテナを作成します。
```bash
docker compose build
docker compose up -d
```
→今回はこれで無事コンテナを作成することができました。

### 参考サイト
https://stackoverflow.com/questions/10461257/an-attempt-was-made-to-access-a-socket-in-a-way-forbidden-by-its-access-permissi



    

## 対処②効果なし － ポート番号の変更
効果のなかった方法も下記に記しておきます。

1\. Dockerのコンテナを停止します。

```bash
docker-compose down
```

2\. docker-compose.ymlを開き、`ports: - "50080:80"`を変更

```
version: "3"

services:
  app:
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    ports:
      - "50081:80" #50080→50081に変更
    volumes:
      - ./src:/var/www/html
    depends_on:
      - db

  db:
    image: mysql/mysql-server:5.5.62
    ports:
      - "53306:3306"
    volumes:
      - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./docker/db/mysql_data:/var/lib/mysql
    env_file:
      - ./docker/db/db-variables.env
```

3\. 再起動します
→エラーは解消していませんでした。

## 終わりに
エラーは解消されましたが、パソコンを起動させるたびにエラーが出るので手間がかかっています。ほかに解決策が見つかったら更新します。
VisualStudioサードパーティ削除後のNuGetエラー NU1507, NU1301 の解決法

# はじめに
NuGetエラー[NU1301](https://learn.microsoft.com/ja-jp/nuget/reference/errors-and-warnings/nu1301)、NuGet警告[NU1507](https://learn.microsoft.com/ja-jp/nuget/reference/errors-and-warnings/nu1507)に遭遇したときの解決法です。

# 経緯
ある日突然、VisualStudio2022で開発中のC#プロジェクトのビルドが通らなくなりました。
```
NU1301 The local source '<数週間前に削除したフォルダのパス>' doesn't exist.
```
こんなエラーが表示されました。指し示してしているのはcsprojファイルの「`<Project Sdk="Microsoft.NET.Sdk">`」タグのようです。
数週間前に削除したフォルダが無いのはそれはそうですが、そのフォルダ自体の有無というよりその中のdllとかそういったものを探しているのでしょう。dotnetのバージョンなのか？と思い解決しようと最新の.NET SDKをインストールしたり色々restoreとか試していたらそれはそれで
```
NU1507 There are 2 package sources defined in your configuration. When using central package management, please map your package sources with package source mapping (https://aka.ms/nuget-package-source-mapping) or specify a single package source. The following sources are defined: nuget.org, <数週間前にアンインストールしたVisualStudioサードパーティ>.
```
つまり、「パッケージソースが二つあるからどっちかにしなさい」といった警告が表示される謎の状態に陥っていました。

ちなみに、アンインストールしたサードパーティは[DevExpress](https://www.devexpress.com/)です。

# 解決法
Cドライブのどこか（私の場合`C:\Users\<ユーザ名>\AppData\Roaming\NuGet`）にある`NuGet.Config`の要素を消せばいいだけでした。
`packageSources`という要素の中に、NU1301で指摘されているパスをvalueに持つ要素があるので、それを消します。
これでエラーNU1301は出なくなります。
また、警告NU1507で指摘されている二つ目のパッケージソースをkeyに持つ要素もあるので、念のためこちらも削除します。（警告なので必須ではないです）

[NU1507](https://learn.microsoft.com/ja-jp/nuget/reference/errors-and-warnings/nu1507)のページにリンクされていた[パッケージ ソース マッピング](https://learn.microsoft.com/ja-jp/nuget/consume-packages/package-source-mapping)にヒントはあるのですが、別に消したものとNuGetで使い分けたいわけでもない（今後完全に使わない）ためスルーしておりました…。

# おわりに
なぜ数週間大丈夫だったのかが謎のままですが、サードパーティはアンインストールするだけではきれいさっぱりなくなるわけではない、ということで今後は気を付けたいです。