OmniAICreator/Qiita-1.07M huggingface dataset:
[Swift]UserDefaultsを使用したクラスのテスト方法

## 始めに
UserDefaultsを使用したクラスのテスト方法について調べたいと思います。

## 実装
```swift
@testable import Project_Code
import Foundation
import Testing

class AppThemePresenterTests {
    // MARK: Lifecycle

    init() {
        userDefaults = UserDefaults(suiteName: AppThemePresenterTests.suiteName)!
    }

    deinit {
        userDefaults.removePersistentDomain(forName: AppThemePresenterTests.suiteName)
    }

    // MARK: Internal

    static let suiteName: String = "Test"

    @Test func updateAppTheme() {
        // Given
        let presenter = AppThemePresenter(userDefaults: userDefaults)
        let appTheme = AppTheme.light
        // When
        presenter.updateAppTheme(appTheme: appTheme)
        // Then
        #expect(presenter.selectedAppTheme == appTheme)
        #expect(userDefaults.appTheme == appTheme)
    }

    // MARK: Private

    private let userDefaults: UserDefaults
}
```

### Point
* PresenterがDIできる設計になっていること
* `UserDefaults.init(suiteName:)`を使用して初期化すること
[init(suiteName:) | Apple Developer Documentation](https://developer.apple.com/documentation/foundation/userdefaults/1409957-init)
* 使用したUserDefaultsを削除すること
[removePersistentDomain(forName:) | Apple Developer Documentation](https://developer.apple.com/documentation/foundation/userdefaults/1417339-removepersistentdomain)

## 終わりに
設計時にDIを意識しながらコードを書くことを、もう少し心がけたいと思いました。

## 参考
https://qiita.com/ARATAYOKOYAMA/items/e92c39bf20bd5aea5be6

https://qiita.com/tanaka-tt/items/ab6c5bc2983a32b11fe3
Golangの最も基本的な型変換

## 備忘録：Golangの基本的な型変換
### 注意すべきポイント
 - 型変換は明示されなければダメ！
 - `型名(値)` の形式で変換
 - 文字列変換のみ、特別なパッケージが必要
 - 変換時のエラーに注意（後ほど勉強）
### よくある変換方法
 - `int()`：整数型への変換
 - `float64()`：64ビット少数への変換
 - `strconv.Itoa()`：整数から文字列
 - `strconv.Atoi()`：文字列から整数
 - `strconv.ParseFloat()`：文字列から浮動小数点

### 例：
```Golang
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // 1. 数値型間の変換
    // 整数から整数
    var intValue int = 42
    var int64Value int64 = int64(intValue)
    var float64Value float64 = float64(intValue)

    fmt.Printf("整数変換:\n")
    fmt.Printf("元の値: %d\n", intValue)
    fmt.Printf("int64への変換: %d\n", int64Value)
    fmt.Printf("float64への変換: %f\n", float64Value)

    // 2. 文字列への変換
    // 数値から文字列
    ageInt := 25
    ageString := strconv.Itoa(ageInt)  // 整数から文字列
    
    floatNum := 3.14
    floatString := strconv.FormatFloat(floatNum, 'f', 2, 64)  // 浮動小数点から文字列

    fmt.Printf("\n文字列変換:\n")
    fmt.Printf("整数から文字列: %s\n", ageString)
    fmt.Printf("浮動小数点から文字列: %s\n", floatString)

    // 3. 文字列から数値への変換
    // 文字列から整数
    numStr := "123"
    numInt, err := strconv.Atoi(numStr)
    if err != nil {
        fmt.Println("変換エラー:", err)
    } else {
        fmt.Printf("\n文字列から数値への変換:\n")
        fmt.Printf("文字列 %s から整数: %d\n", numStr, numInt)
    }

    // 文字列から浮動小数点
    floatStrValue := "3.14"
    floatValue, err := strconv.ParseFloat(floatStrValue, 64)
    if err != nil {
        fmt.Println("変換エラー:", err)
    } else {
        fmt.Printf("文字列 %s から浮動小数点: %f\n", floatStrValue, floatValue)
    }
}
```
Java SE Bronze合格までの道のり

先日、Oracle認定資格のJava SE Bronze試験を受験し、無事合格することができました。
そこで私が使用した教材や、これまでに行った勉強法について感想も含めてまとめてみようと思います。

# 1.書いた人のスペック
- もともとITとは関係のない職種
- 情報系の資格はITパスポートのみ
- 半年間プログラミングスクールで学習
- 今まで触ったことのある言語はJavaScriptとPHP

# 2.使用教材
### メイン教材
「[徹底攻略Java SE Bronze問題集［1Z0-818］対応](https://book.impress.co.jp/books/1119101075)」
<img width="200" src="https://img.ips.co.jp/ij/19/1119101075/1119101075-520x.jpg">
いわゆる黒本。解説が優秀で、正直黒本だけで試験対策できると思います。
また問題の内容も実際の試験と非常に似ています。


### サブ教材
「[オラクル認定資格教科書 Javaプログラマ Bronze SE（試験番号1Z0-818）](https://www.shoeisha.co.jp/book/detail/9784798167831)」
<img width="200" src="https://www.seshop.com/static/images/product/23850/L.png">
いわゆる紫本。結局巻末の模試しか使用しませんでした。
黒本に比べると少しわかりにくいです。

「[2週間でJava SE Bronzeの基礎が学べる本](https://book.impress.co.jp/books/1116101147)」
　<img width="200" src="https://img.ips.co.jp/ij/16/1116101147/1116101147-520x.jpg">
 Kindle unlimitedの対象だったため使ってみましたが、結局途中で使わなくなりました。
 なくても特に困らないです。

「[いちばんやさしいJavaの教本 人気講師が教えるプログラミングの基礎](https://book.impress.co.jp/books/1118101073)」
<img width="200" src="https://img.ips.co.jp/ij/18/1118101073/1118101073-520x.jpg">
試験対策とは直接関係ないですが、Javaの全体像を掴むにはおすすめです。実際にコードを書いて動作を確認することで理解がしやすくなりました。

これらの教材の中で絶対に必要なのは**黒本**です。**むしろ黒本さえあれば大丈夫**。イメージがつかみにくい時は**実際にコードを書いて試してみることがおすすめ**です。

# 3.具体的な勉強法
1\. paiza
2\. 黒本
3\. 実際にコードを書いてみる
やったことはこの3点だけです。

### paiza
新・Java入門編から学習スタート。
コレクションフレームワークなどブロンズの範囲外の部分もあり、難易度が高く感じました。私が勉強していた時にはどのチャプターがブロンズの範囲かわからなかったのですが、今は各チャプターにブロンズやシルバーなど記載があるので、選別して効率よく勉強できると思います。
トータル30時間ほど学習し、黒本での学習にシフトしていきました。

### 黒本
ひたすら問題演習と解説を読むことを繰り返し、**4周**しました。正解率が80％以下の章はそれに**プラス3周**しました。
とにかく問題を解く。何度も間違える問題が絞られてくるので、それに重点を絞り解く。
理解が甘い単語や概念はNotionにまとめて覚える。まとめた内容をChatGPTに投げて、問題を作ってもらいそれを解く。正直黒本をやり過ぎると答えを覚えてしまうので、ChatGPTを活用して勉強しました。
黒本は50時間ほど学習しました。

### 実際にコードを書いてみる
ただ、上記2つの勉強だけではポリモーフィズムや継承など「**いわゆるJavaっぽい部分**」は理解しにくく、「[いちばんやさしいJavaの教本 人気講師が教えるプログラミングの基礎](https://book.impress.co.jp/books/1118101073)」を使い実際にコードを書いて動かしてみることにしました。

継承や実装、コンストラクタの部分が苦手だったのですが、実際にコードを書いて動きをみることで詳しくイメージができました。コードを書いたことで、問題演習のコードの意味がようやくわかるようになりました。
ページ数が少なめの入門書でコードを書いてみるのがいいと思います。

# 結果
合格しましたが、受験前に予想していた正解率よりも低い結果だったことが残念です。

# 最後に
試験に合格したことで自信につながりました。自分としては不本意なところもあるので、引き続き勉強しSilverも取得できればと思います。

この内容がひとつでも参考になれば幸いです。
npm infoでライブラリの互換性を調べる方法

ol-mapbox-styleライブラリが依存するライブラリの互換性バージョンを調べる方法

```bash
npm info ol-mapbox-style@4.3.1 peerDependencies

// { ol: '^5.3.0' }
// ^6.1.0は、6.1.0以上で、かつメジャーバージョンが変わらない（つまり、7.0.0未満）の
// すべてのバージョンを許容することを意味します。
```

peerDependencies（ピア依存関係）は、npmパッケージが他のパッケージと一緒に使用されることを前提としている場合に、その依存関係を指定するためのフィールドです。peerDependenciesを使用することで、特定のバージョンのパッケージがインストールされていることを保証し、互換性の問題を防ぐことができます。
【MohistMC 1.12.2】ライブラリーのインストールに失敗する

:::note warn
本記事はMohist 1.12.2(Forge: 14.23.5.2860, MD5 `95198de20743519727cf2a3f5987a3f1`)を前提に書いています。また、**この記事に書いてあることは自己責任です。**
:::
:::note info
本記事は2025年1月20日時点の情報に基づき執筆しています。
:::
# TL;DR
[openwar.fr/public/download/libraries.zip](https://openwar.fr/public/download/libraries.zip)を解凍してサーバーディレクトリに配置。([本編直リン](#本編))
# プロローグ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908412/657ce8d0-1d67-2e61-9296-a2094f950e44.png)
こんな感じにダウンロード失敗エラーがものすごく出てくるバグがあったので調べた。
# 本編
[ここ](https://openwar.fr/public/download/libraries.zip)(`openwar.fr/public/download/libraries.zip`)の「`libraries.zip`」を解凍して**librariesフォルダ**を`server.jar`等の**サーバーが配置されているディレクトリに配置**。

:::note info
**エクスプローラーから解凍した場合はlibrariesフォルダの中のlibrariesフォルダを移動する**
:::
# ソース
[Mohist公式DiscordサーバーでのLuckyPlayer氏の発言](https://discord.com/channels/311256119005937665/968577775441178625/1330486893187567636)
([MohistMC公式Discord鯖招待リンク](https://discord.gg/mohistmc))
個人的な備忘録：Amazon CognitoとAWS Identity and Access Management（IAM）の違いを記事としてアウトプットしてみた

## はじめに
Amazon Cognitoは、モバイルアプリやWebアプリケーションにおけるユーザー認証や承認の課題を解決する、非常に便利で強力なツールです。

:::note warn
***特に、セキュリティと利便性を両立したソーシャルログインや多要素認証の機能が魅力的です。***
:::

本記事では、Amazon Cognitoの基本的な機能や用途、さらにAWS Identity and Access Management（IAM）との違いについて解説します。***記事は簡潔な内容となりますが、少しでもお役に立てれば幸いです。***

## 書こうと思ったきっかけ
現在、受講しているITスクールでのハッカソン活動の中で、「***Amazon Cognito***」を使用する要件が出てきました。

しかし、私自身これまでCognitoを使った経験が全くなかったため、どのように技術をキャッチアップすれば良いのか悩んでいました...。

:::note info
**一方で、AWS Identity and Access Management（IAM）を使ったアーキテクチャ設計には比較的慣れているため、CognitoとIAMを比較しながら理解を深める方法が有効だと考えました。**
:::

今回のブログでは、Amazon CognitoとIAMの違いを整理し、その知識を横展開できる形でまとめたいと考えています。

## Amazon Cognitoとは？

Amazon Cognito（アマゾン コグニート）は、モバイルアプリやWebアプリケーション向けの認証・認可、ユーザー管理、データ同期を提供するAWSのサービスです。***以下の特徴があります。***

1. **スケーラビリティ**  
   - 数億人規模のユーザー管理が可能。

2. **ソーシャルログイン**  
   - Google、Facebook、AmazonなどのソーシャルIDを使用した認証をサポート。

3. **セキュリティ強化**  
   - 多要素認証（MFA）やアドバンスドセキュリティ機能を提供し、アカウント管理の安全性を向上。

これにより、開発者は安全で柔軟な認証・認可機能をアプリケーションに簡単に統合できます。

## Cognitoを使った構成は調べた感じこんなイメージ

**パターン：サーバーレス認証・アクセス制御パターン**

![Screenshot 2025-01-20 at 17.32.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/e554cf63-0350-962f-f9e6-77449d6ae3a0.png)
引用画像：https://aws.amazon.com/jp/builders-flash/202210/cognito-userpool-endpoint/

Amazon CloudFrontを利用した静的Webページを通じて、認証はCognitoユーザープールで提供しています。

また、バックエンドサービスでは、Cognitoユーザープールが発行するIDトークンを使用してAPIへのアクセス制御を行っています。

## AWS Identity and Access Management（IAM）との違い

Amazon Cognitoは、アプリケーション開発者にとって、ユーザー認証やセキュリティ強化を簡単に実現するための便利なツールです。

:::note warn
***以下に、Amazon CognitoとAWS Identity and Access Management（IAM）の違いを簡単にまとめました。***
:::

***興味のある方は参考にしてみてください！***


| 項目       | Amazon Cognito                    | AWS Identity and Access Management（IAM）        |
|------------|-----------------------------------|--------------------------------------------------|
| **対象**   | アプリケーションユーザー（人）    | AWSリソース（システム）                          |
| **用途**   | アプリの認証・認可                | AWSリソースへの認証・認可                        |
| **ログイン要件** | 必須（トークンによるアクセス） | 必須ではない（IAMロールで即アクセス可能）        |
| **特徴**   | ソーシャルID、カスタム認証をサポート | AWSリソースのアクセス制御に特化                  |

**IAMはAWSリソースへのアクセス管理に特化しており、これら2つは利用対象や用途が異なるため、適切に使い分けることが重要です。**

## 主な違いのポイント

### 対象範囲の違い
- **Amazon Cognito**：アプリケーションのユーザー認証を担い、外部ユーザー（アプリの利用者）向け。

- **AWS Identity and Access Management（IAM）**：AWSリソースへのアクセスを制御するため、主に内部ユーザーやシステム向け。

### 利用フローの違い
- **Amazon Cognito**：ログイン後にトークンを使用してクエリを実行。

- **AWS Identity and Access Management（IAM）**：IAMロールを付与されたユーザーが直接クエリを実行可能。

## まとめ
最後まで読んでいただき、ありがとうございました。***今回の記事を通じて、Amazon CognitoとIAMの違いについて改めて体系的に整理することで、それぞれの役割や使いどころを理解する良い機会となりました。***

:::note note
**今後のチーム開発や個人的なプロジェクトでも、これらのサービスを積極的に活用していきたいと思います！**
:::

こうした基礎的な内容を継続的にアウトプットすることで、自分の知識を深めるとともに、必要なときに振り返るためのきっかけを作りたいと考えています。***この記事が少しでも皆さんの参考になれば幸いです！***
UI/UXデザインの山場！群馬県ローカルアプリ開発日記【5日目】

# 【開発日記 5日目】UI/UXデザインの改良を進めています！

こんにちは！群馬県ローカルイベント発見アプリを開発中の🐮です！  
今日は開発5日目の取り組みについてまとめました。テーマは「使いやすさを追求したUI/UXデザインの検討（その2）」です。

---

## 本日の作業内容

### 1. 主要画面のワイヤーフレーム作成 ✍️

アプリのトップページ、イベント一覧、詳細ページ、マイページといった主要画面の**ワイヤーフレーム**を作成しました。  
紙とデジタルツールを併用しながら、ユーザーが直感的に操作しやすいデザインを意識しています。

- 初めてのワイヤーフレーム作成で手間取りましたが、設計作業は新たな発見が多く、とても楽しかったです。

### 2. 画面遷移図の設計 🚦

ユーザーがアプリ内をスムーズに移動できるよう、**画面遷移図**を設計しました。  
特に以下の操作性を重視しています。

- イベント情報から詳細ページへのシームレスな遷移
- マップ表示とリスト表示の直感的な切り替え

遷移図を描くことで、ユーザーがどのようにアプリを使うかを具体的にイメージできました。

### 3. ユーザビリティ向上の工夫 💡

ユーザビリティを高めるため、以下の点にこだわりました。

- **重要なボタンを指が届きやすい位置に配置**  
- **視認性の高いフォントサイズやカラーを選定**  
- **余計な要素を排除し、シンプルで見やすいレイアウトを追求**

ユーザー目線で考えることで、これまで見えていなかった課題にも気づけました。

---

## 現在の進捗状況

アプリ開発は以下のステップまで進んでいます：

1. **基本機能の要件定義と仕様策定**：完了 ✅  
2. **デザインコンセプトの確立**：完了 ✅  
3. **主要画面のワイヤーフレームと画面遷移図の完成**：完了 ✅  

アイデアが具体的な形になりつつあり、とても嬉しいです！しかし、まだまだ改善の余地があるので引き続き頑張ります。

---

## 今日の学びと反省

### 今日の学び 📚

- **ワイヤーフレーム作成の重要性**  
  デザイン前に詳細なワイヤーフレームを作成することで、全体像が明確になり、後の工程がスムーズに進みます。  
- **ユーザー目線の大切さ**  
  「自分が使うならどう感じるか？」という視点を持つことで、使いやすさが向上しました。  
- **細部への配慮が全体の品質を左右する**  
  ボタン配置や配色などの細かな工夫が、使い心地に大きな影響を与えることを実感しました。

### 反省点 😓

- **時間配分の見直し**  
  ワイヤーフレーム作成に時間がかかりすぎました。作業効率を上げる方法を検討する必要があります。  
- **休憩を忘れがち**  
  集中しすぎて疲労感が溜まりやすくなりました。適度に休憩を取り入れることが重要ですね。

---

## 次の目標 🚀

明日は、以下のタスクを進める予定です。

1. 作成したワイヤーフレームを基に、より詳細なプロトタイプを作成  
2. プロトタイプを使用して、実際の操作感をテスト  
3. 必要に応じてワイヤーフレームやプロトタイプを修正  

これからも、群馬県を盛り上げるためのアプリ開発を全力で進めていきます！  
応援やフィードバックをいただけると嬉しいです。ぜひX（旧Twitter）やコメントで感想をお聞かせください！
Databricksジョブ監視ダッシュボード

こちらに新たなダッシュボードが追加されていました。

https://docs.databricks.com/ja/admin/system-tables/jobs-cost.html#jobs-monitoring-dashboard

こちらのJSONファイルをダウンロードして、[インポート]()するだけです。

https://github.com/databricks/tmm/blob/main/System-Tables-Demo/Jobs-PrPr/Jobs%20System%20Tables%20Dashboard.lvdash.json

参照するシステムテーブルの参照権限があることを確認してください。

あとは、ダッシュボードを表示します。

ワークスペースごとのコストやタグごとのコストが可視化されます。

![Screenshot 2025-01-20 at 17.15.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d59632c0-0979-c748-eb78-6899bc1b68b1.png)

変動やSKUごとの変化、成功やエラーの内訳も表示されます。

![Screenshot 2025-01-20 at 17.16.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/ab447753-f343-53c7-3051-d5f4f7202a23.png)

この他に、コストの高いジョブ実行(ラン)の一覧も表示されます。ご活用ください

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
Cloudera Public Cloud - 既存のVPCを使う場合

# この記事について

以下のドキュメントの Option2 の要約です。

https://docs.cloudera.com/cdp-public-cloud/cloud/aws-refarch/topics/cdp-pc-aws-refarch-cidr.html

# 既存のVPC, サブネットを利用する場合

## Data Lake および Data Hub に利用するサブネット

- データレイクが RDS を使うので、最低でも2つのサブネットが必要
- CIDR の範囲は /19 が推奨だが、より小さいものを使う場合は以下のガイドラインを参照
    - VMひとつにつき1つのIPを使う
    - RDSが2つのIPを使う
    - Light Duty の場合
        - 合計3つのVMが立つ（Data Lake に2、Free IPA に1）
    - Medium Duty の場合
        - 合計13のVMが立つ（DataLake に10、FreeIPAに3）

## Data Warehouse 用のサブネット

（割愛 -> 必要が生じた際に訳します）

## Cloudera AI 用のサブネット

Cloudera AI は、最低でも2つの異なるAZに配置された2つのサブネットが必要で、ワークベンチの作成時点でどちらを使うかを選べます。

指定したサブネットを他の Cloudera のサービスと共有している場合は、十分なIPの範囲を Cloudera AI が使えるようにする。 

Cloudera AI は Calico CNI (Container Network Interface) を利用し、ネットワーク内の Cloudera AI 用の pod を稼働させます。

ワークベンチあたりのIPアドレス数の計算式は以下のとおりです。

- CPUのワーカーノード、GPUのワーカーノードがそれぞれ 1つずつ IP アドレスを利用します
- インフラ用のノードに9つのIPアドレスが必要です（Cloudera AI のインフラノード用に3, Liftie のインフラノード用に4, ELB用に2）

## その他のサービス用のサブネット

（割愛 -> 必要が生じた際に訳します）
【Looker Studio】テーブルの結合

## はじめに
今回は「Looker Studio」で簡単なテーブルの結合を行います。Looker Studioとはデータを視覚的に分析・共有するための無料のダッシュボード作成ツールです。最近「Looker Studio」を使用する機会があり、ダッシュボード上で結合出来ることを学んだのでブログにしてみました！

## 使用データ
まずは、結合に使用する疑似テーブルを用意します。

今回は商品購入履歴テーブルに対して、商品名の情報が記載されたテーブルを付与する結合を行うことを考えます。

そこで用意する疑似テーブルは
・商品購入履歴テーブル
・製品テーブル
の二つです。

商品購入履歴テーブルには各顧客ごとの、どんな商品をいつ、いくらで購入したかが記載されており、商品テーブルには各商品idとそのidに対応する商品名が記載されています。

では早速、商品購入履歴テーブルに対して、商品テーブルを結合し商品名を付与する結合を行います。

### 商品購入履歴テーブルの一部
| user_id | product_id | order_date | amount |
|---------|------------|------------|--------|
| 1       | 101        | 2023/1/1   | 1000   |
| 2       | 102        | 2023/1/2   | 1500   |
| 3       | 103        | 2023/1/3   | 2000   |
| 4       | 101        | 2023/1/4   | 1000   |

### 製品テーブル
| product_id | product_name |
|------------|--------------|
| 101        | Product A    |
| 102        | Product B    |
| 103        | Product C    |


## Looker Studioでのテーブルの結合
ではここからLooker Studioで作業を行います。

ここでは省略しますがデータセットのインポートを済ませた状態からスタートです。
今回は商品購入履歴テーブルを「order_info」、製品テーブルを「product」と保存しました。

まず、上部のタブの「リソース」から「統合を管理」を選択します。そこから「結合を追加」によりテーブルの結合を行います。

ここでは「order_info」に「product」を「product_id」により左外部結合することを考えます。

まずテーブル１に対して
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3989248/b969afd6-56db-2c35-ac66-38b591ad630a.png" alt="image.png" width="300">

のような設定を行います。

次に「別のテーブルを追加する」から
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3989248/082629f4-09ed-602c-b600-f562f9a2eda7.png" alt="image.png" width="300">


のような設定を行います。ここまでで結合に使用するデータの準備が完了しました。

続いて「結合を設定」から結合を行います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3989248/6b61f859-e6d2-d326-323a-1af4d0f6e02d.png" alt="image.png" width="80%">

これにより二つのテーブルを適切なキーにより結合出来たはずです。

ここまで設定が完了したら保存を押して、実際にデータを見てみましょう。

## 結合データの確認
Looker Studio上で表の挿入を行いデータソースとして先ほど作成したテーブルを選択します。各ディメンションに必要項目を入力し確認します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3989248/7d5051bc-5654-1502-35c0-cea835bc474b.png" alt="image.png" width="70%">

すると各、購入履歴ごとに「product_name」を付与できたことが確認できます。

## 終わりに
今回は「Looker Studio」を使用して、ダッシュボード上で二つのテーブルを結合しました。「Looker Studio」に関して今後も情報を発信する予定なのでぜひ確認してください！
【C++】メモリの動的確保

メモリの動的確保で迷うことが多いので大体のパターンを書いてみます。


```c++
int* p1 = new int;  //1個のメモリを確保
int* p2 = new int(10); //1個のメモリを確保して10で初期化
int* p3 = new int[10]; //10個のメモリを確保

string* p4 = new string; //1個のメモリを確保
string* p5 = new string("hogehoge"); //1個のメモリを確保してhogehogeで初期化
string* p6 = new string[10]; //10このメモリを確保
```

自分で作ったクラスでも同様に動的確保ができまs
Object#inspect


>inspect -> String
`オブジェクトを人間が読める形式に変換`した文字列を返します。

>組み込み関数 Kernel.#p は、このメソッドの結果を使用してオブジェクトを表示します。

https://docs.ruby-lang.org/ja/latest/method/Object/i/inspect.html#:~:text=inspect%20%2D%3E%20String,%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

```rb
irb(main):004> [ 1, 2, 3..4, 'five' ].inspect
=> "[1, 2, 3..4, \"five\"]"
irb(main):005> "fafa".inspect
=> "\"fafa\""
irb(main):006> :fafa.inspect
=> ":fafa"
irb(main):007> ["fafa","fafa","fafa"].map!(&:inspect)
=> ["\"fafa\"", "\"fafa\"", "\"fafa\""]
irb(main):008> p ["fafa","fafa","fafa"].map!(&:inspect)
["\"fafa\"", "\"fafa\"", "\"fafa\""]
=> ["\"fafa\"", "\"fafa\"", "\"fafa\""]
irb(main):009> puts ["fafa","fafa","fafa"].map!(&:inspect)
"fafa"
"fafa"
"fafa"
=> nil
...
irb(main):011> p ["fafa","fafa","fafa"]
["fafa", "fafa", "fafa"]
=> ["fafa", "fafa", "fafa"]
irb(main):012> puts ["fafa","fafa","fafa"]
fafa
fafa
fafa
```
Something went wrong. Refresh and try again : In the Coral Cloud trial org


+ [【解決例】i keep on refreshing so i could ask a task but it keeps saying something went wrong. Refresh and try again](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KD2Yp)
+ [Oops, something went wrong creating your Agentforce Playground. Please refresh the page and try again in an hour.](https://qiita.com/Keiji_otsubo/items/fbb9b0a130b4c20d2018)

---------------
+ [hitting an error when trying to activate and chat with my service agent](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000nOO0)
+ ["Something went wrong. Refresh and try again"](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000mggk0AA)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d746eb52-93e6-192d-f090-16a8d3c74b65.png)

:::note
Managed to resolve by trying to complete the badge- turns out Einstein Setup had toggled back to off despite turning it on previously and my playground hadn't connected to the badge properly- now all sorted, leaving this up in case anyone else has the same issue!

バッジを完成させることで解決できました。以前はオンにしていたにもかかわらず、Einstein セットアップがオフに戻っていて、プレイグラウンドがバッジに正しく接続されていなかったことが判明しました。これですべて解決しました。他の誰かが同じ問題を抱えている場合に備えて、これを残しておきます。
:::

+ [【Agentforce Service Agentを設定する】エラーメッセージが出るのですが解決策がわかりません](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KAV2E)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0721a12a-335c-8a48-4b6f-4a3746c9f531.png)

+ [会話プレビューエラー](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000J7CFr)

:::note
「Agentforce サービス エージェント ユーザー」権限セットをユーザー (手順 3「設定の定義」で追加したエージェント ユーザー) に追加すると、問題が解決します。 
:::

+ [In the Coral Cloud trial org when I click on the Agentforce icon as a system admin, I am getting the error as below. Something went wrong. Refresh and try again.](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KC9IX0A1)


+ [Agentforce error - Something went wrong](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KC9IX)

:::note
It worked after deactivating and re-activating the Einstein Copilot agent.
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/03de7a1d-2633-9776-6ce6-486cbc6ccf02.png)


# Conectar Flows a Agentforce con acciones

+ [Problemas con el ejercicio de conectar flows (Connect Flows)](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000PZ6NH)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0e9bfe0a-6170-4095-9b98-28ec76db18e2.png)

:::note
Since the Deactivate button is visible, I think the agent is still active. 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/17c14b81-bf68-4cdf-9dbf-24cf7c8212ee.png)

Please deactivate it and do the following: 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/77910f08-92a6-4f6e-9e28-00d60fd01a61.png)

https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000MZLyf
:::
Fast APIでファイル入力を受け付けるAPIを作成してみた

# 概要
Fast APIで何かしら作ってみたかったのでファイルを入力として受け付けるAPIでも作成してみようかと思います
(ユースケースは正直あまり思い浮かんでいないですが、形式の決まっているデータをファイルにまとめてたくさん送ることができるとかでしょうか？)

# 材料
Fast APIでファイルの入力を受け付ける方法について調べます
`File`と`Form`を同時に使うことで実現が可能になるそうです([リファレンス](https://fastapi.tiangolo.com/ja/tutorial/request-forms-and-files/))
※またファイルやフォームデータを受け取るためにpython-multipartのインストールが必要でした

公式のリファレンスをコードに起こして、docsを確認してみた結果が以下になります
実際にリクエストしてみると渡されたファイルのサイズ、種類、そして文字列それぞれをjson形式でレスポンスする形となっています

```py
import uvicorn
from fastapi import FastAPI, File, Form, UploadFile
from typing import Annotated


app = FastAPI()


@app.post("/files/")
async def create_file(
    file: Annotated[bytes, File()],
    fileb: Annotated[UploadFile, File()],
    token: Annotated[str, Form()],
):
    return {
        "file_size": len(file),
        "token": token,
        "fileb_content_type": fileb.content_type,
    }


if __name__ == "__main__":
    uvicorn.run("main:app", reload=True)

```
![スクリーンショット 2025-01-09 1.22.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701238/4bf0bfcc-841a-c6cd-88ed-e9989c01d6fb.png)

# 想定されるユースケース
どういったタイミングで使うか考えてみましたが、やはりまとまったデータの一括注入とかでしょうか？
例えば、以前作成した動画リンクからダウンロードするAPIを一括で取り扱うなどいかがでしょうか？([参考](https://qiita.com/ryo0819/items/adfde9b905cbdffb2be1))

```py
@app.post("/files/donwloader/")
async def from_file_download(
    file: UploadFile = File(...)
):
    URL_PATTERN = re.compile(r'http.*')
    content = await file.read()
    data = json.loads(content)

    for i in data:
        try:
            ytdlp_opts = {
                "format": "mp4",
            }

            with YoutubeDL(ytdlp_opts) as ydl:
                if re.match(URL_PATTERN, i["link"]):
                    ydl.download(i["link"])
                else:
                    raise Exception
        except Exception as e:
            print(e)


if __name__ == "__main__":
    uvicorn.run("main:app", reload=True)
```

上記のようなコードにすれば、一回のリクエストでファイルに記載したリンク先のものを随時ダウンロードしてくれるようになります

また、引き渡しの際に使用するファイルの形式はjson形式で以下を想定しております(titleについてはあってもなくても可です)
```json
[
    {
        "title": "title_1",
        "link": "https://www.example.com/"
    },
    {
        "title": "title_2",
        "link": "https://www.example.com/"
    }
]
```

あとはcurlでリクエストをしてみると、jsonファイルで指定したリンクのものがダウンロードできます

```sh
curl -X 'POST' \
  'http://localhost:8080/files/donwloader/' \
  -H 'accept: application/json' \
  -H 'Content-Type: multipart/form-data' \
  -F 'file=@sample.json;type=application/json'
```

# おわりに
こんな感じでファイルの入力ができるようになると一気にデータの取り扱う量が増えたように見えますね
今後もこの調子で扱える領域増やしていきたいと思います
slick.jsでaria-hiddenの警告が出る時の対処方法

# はじめに
普段カルーセルを実装するのに、slick.jsをよく使用しています。
公式サイト：[slick.js](https://kenwheeler.github.io/slick/ "slick")
slickドキュメント翻訳：[slick - にほんご。](https://tr.you84815.space/slick/index.html)

# aria-hidden属性に対する警告
クライアントから検証ツールでアクセシビリティの警告が出ていると言われまして、どうにかせねばと思いました。

![警告画像](https://i.imgur.com/9hzHTUD.png "警告画像")

画像の警告文を見てみると以下が問題らしい。

【現在表示されているスライド（.slick-current）にaria-hidden="true"、tabindex="0"が設定されているのはよろしくないよ】

mora informationの[ページ](https://dequeuniversity.com/rules/axe/4.10/aria-hidden-focus?application=AxeChrome)を見てみると、アクセシビリティで駄目な部分が書いていました。

aria-hiddenやtab-indexはWebアクセシビリティに関わる属性のことです。
詳しくは[こちら](https://www.dkrk-blog.net/javascript/slick-a11y-01)

# 現状
・現状slickを実装すると以下のコードになります。

<p class="codepen" data-height="300" data-default-tab="js" data-slug-hash="ogvPNPm" data-pen-title="slick_org" data-user="yoshi090" 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/yoshi090/pen/ogvPNPm">
  slick_org</a> by yoshida (<a href="https://codepen.io/yoshi090">@yoshi090</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

以下はそれぞれ1枚目のスライド、2枚目のスライド時のコードのキャプチャです。

【1枚目】
![1枚目画像](https://i.imgur.com/6OshITj.png)

【2枚目】
![2枚目画像](https://i.imgur.com/AC7fB3R.png)

警告通り、現在のスライド（.slick-current）の部分がaria-hidden="true"かつtabindex="0"となっていますね。

# 解決方法
警告文の解決方法に従うと、現在のスライドのtabindexを-1にするか、tabindex自体を削除するかでいけるらしい。

そういう設定があるのかslickのドキュメントを見ると、accessibilityというのがある。
[slick - にほんご。 accessibility](https://tr.you84815.space/slick/settings/accessibility.html)
これはデフォルトでtrueなのだが、矢印キーでスライド可能にする設定をしているらしい。

とりあえずこれをfalseに設定してみる。

<p class="codepen" data-height="300" data-default-tab="js" data-slug-hash="zxOJYgJ" data-pen-title="slick_fix1" data-user="yoshi090" 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/yoshi090/pen/zxOJYgJ">
  slick_fix1</a> by yoshida (<a href="https://codepen.io/yoshi090">@yoshi090</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

で、検証ツールを見てみると

![tabindex消えた](https://i.imgur.com/Dcxffjv.png)

tabindex消えた！

エラー検証も4つだった問題が3つになり消えた！

![検証ツール](https://i.imgur.com/2GHNpMB.png)

# 警告は消えたが・・・
結局accessibilityをfalseにして良いのか？矢印キーでスライドできなくなるけど。という懸念が残る。
あなたはまだ「iPaaSプラットフォーム」を知りませんか？コンピューター作業に最適なツール

反復的なタスクを実行するために、異なるアプリケーション間を頻繁に行き来しますか?これらのタスクは、実際には、iPaaS (Platform as a Service) プラットフォームを通じて簡単に自動化できます。たとえば、Make プラットフォームを使用すると、どこからでもファイルを取得して処理し、処理されたファイルを次のアプリケーションにシームレスに渡すことができます。

## 使用例：
Make を使用すると、[PDF 処理機能](https://www.compdf.com/blog/compdfkit-api-on-make?utm_source=qiita_20250120&utm_medium=ipaasmake)と Google Cloud Drive、Gmail などを組み合わせて、法律、教育、金融、医療、製造、航空などのさまざまな業界のドキュメントを簡単かつ自動的に処理できます。すべてドキュメントのワークフローを自動化できます。以下は、「学生の最終レポートの自動生成」の詳細な例です。

**利用シーン：**
生徒の成績証明書と各科目の成績を結合してPDF形式に変換し、生徒レポートを自動生成し、生徒にメールで送信します。

**プロセス：**

- Google ドライブに接続して、教師が保存した生徒のレポートや課題を収集します。
- レポートから主要な成績と課題情報を抽出します。
- 抽出した各科目の成績と課題情報を Word の成績証明書テンプレートに入力します。
- ComPDFKit API を使用して、生徒の Word トランスクリプトを PDF ファイルに変換し、指定した Google ドライブ フォルダーに保存します。
- Gmail 送信機能を接続して、生徒の成績証明書と課題を各生徒に電子メールで送信します。
プロジェクトのフォルダ構成

システム開発におけるフォルダ構成
Twitterか何かで拾った画像をテキスト化しただけです。
## 中〜大規模PJ向け

```
00_プロジェクト管理
├─ 001_提案・契約
├─ 002_プロジェクト計画
├─ 003_進捗管理
├─ 004_会議体
├─ 005_プロジェクト完了
└─ ※※old

10_要件定義
├─ 101_要求管理
├─ 102_業務要件
├─ 103_システム要件
├─ 104_移行要件
└─ ※※old

20_調査・リサーチ
├─ 201_市場調査
├─ 202_技術調査
├─ 203_競合分析
└─ ※※old

30_設計
├─ 301_基本設計
├─ 302_詳細設計
├─ 303_インフラ設計
└─ ※※old

40_開発
├─ 401_ソースコード
│  ├─ フロントエンド
│  ├─ バックエンド
│  └─ データベース
├─ 402_ライブラリ・フレームワーク
├─ 403_開発環境構築
└─ ※※old

50_テスト
├─ 501_テスト計画
├─ 502_単体テスト
├─ 503_結合テスト
├─ 504_システムテスト
├─ 505_受入テスト
├─ 506_性能テスト
└─ ※※old

60_リリース
├─ 601_リリース計画
├─ 602_展開手順書
├─ 603_運用マニュアル
├─ 604_利用者マニュアル
└─ ※※old

70_保守・運用
├─ 701_障害対応
├─ 702_変更管理
├─ 703_パフォーマンス監視
├─ 704_セキュリティ管理
└─ ※※old

80_受領資料
├─ 801_顧客提供資料
├─ 802_外部システム資料
└─ ※※old

90_参考資料
├─ 901_標準・ガイドライン
├─ 902_テンプレート
├─ 903_外部文書
└─ ※※old

99_その他 [EOF]
```
## 小〜中規模PJ向け
短期のPJやPoC、スモールスタートの案件では、フェーズを細かく分割するほどのドキュメントがそもそも不要だったり、管理コストがかえって増えたりすることがあります。そこで、以下のように大きな塊でまとめた簡略構成を例として挙げます。ソースコードはGithub上だけでも良いかもですね。
```
00_プロジェクト管理
├─ 提案・契約
├─ 計画・タスク管理
├─ 会議・進捗報告
└─ ※※old

10_要件・設計
├─ 要件定義・要件管理
├─ 設計資料 (基本/詳細/インフラなど)
└─ ※※old

20_開発
├─ ソースコード
│  ├─ フロントエンド
│  ├─ バックエンド
│  └─ データベース
├─ 開発環境設定・手順
└─ ※※old

30_テスト
├─ テスト計画・項目
├─ テスト結果・レポート
└─ ※※old

40_リリース (必要に応じて)
├─ リリース手順/展開手順
├─ 運用・ユーザー向けマニュアル
└─ ※※old

90_参考資料
├─ テンプレート・ガイドライン
├─ 外部文書・参考リンク
└─ ※※old

99_その他
React チュートリアル イベントハンドラ関数の呼び出しと渡すだけの違い

### 躓いた部分

> イベントに応答する 
> コンポーネントの中でイベントハンドラ関数を宣言することで、イベントに応答できます：
```
function MyButton() {
  function handleClick() {
    alert('You clicked me!');
  }
  
return 
    <button onClick={handleClick}>
      Click me
    </button>
  );
}
```

> onClick={handleClick} の末尾に括弧がないことに注意してください！ そこでイベントハンドラ関数を呼び出すわけではありません。渡すだけです。ユーザがボタンをクリックしたときに、React がイベントハンドラを呼び出します。

### どこで躓いたか
関数を呼び出すわけではありません。渡すだけです。
→呼び出すタイミングが違う、、ってこと！？

### 具体例を考えてみた
**括弧ありのケース: onClick={handleClick()}**
Aさんが、Bさんに「〇〇さんに電話をかけて」と頼む。
Bさんはその場で電話をかけてしまった。

問題点:
Aさんが本当は「必要になったら電話してほしい」と言いたかったのに、Bさんは「頼まれた瞬間」に電話をかけてしまう。
結果、Aさんが意図したタイミングではなかった。

学び：
括弧を付けるとReactは「即座に」関数を実行する


**括弧なしのケース: onClick={handleClick}**
Aさんが、Bさんに「必要になったら〇〇さんに電話して」とメモを渡した。
Bさんはそのメモ通り、タイミングが来たとき（例えば〇〇さんから連絡が必要になったとき）に電話をかけた。

学び：
括弧を付けずに関数を渡すと、「必要なタイミング（この場合はクリックされたとき）に」関数を実行する

### 簡単にまとめると
onClick={handleClick()} は、「電話をかける方法を準備せず、その場で電話をかけてしまう」こと。
onClick={handleClick} は、「電話をかける方法（関数）を準備する」こと。

自分がどのタイミングで呼び出したいのかを意識することが大切
Oracle Analytics Cloud：Data VisualizationとClassicのAnswers、Dashboardの比較

はじめに
---
Oracle Analytics Cloudのレポートを作成する際には、DataVisualizationと、ClassicのAnswersがあります
Answersで利用している機能で、Data Visualizationでは利用できないものがいくつかあります
本記事ではその機能についての記事をまとめてみました。

記事記載時のOAC ver：Jan 2025 Update
記事記載時のQiita記事：2025/01/20
変更履歴：2025/01/20 初版公開


Data Visualizationと、ClassicのAnswersの違い
---
|利用シーン|Answers|DataVisualization|備考|
|---|---|---|---|
|レポートで変数を利用する|プレゼンテーション変数|なし ※類似機能：パラメータ|フィルターで条件を指定する際に変数に値がセットされる|　
|条件値を含むURLを直接指定してレポートを実行する|ブックマークリンク|なし ※類似機能：埋込URL|URLに直接、条件値をセットしてダッシュボードを出力する|
|URLに出力フォーマットを埋め込み|GoURL|なし|Excel、csvなどフォーマットをURLに指定してエクスポートを実行する|
|異なるサブジェクト領域を結合（UNIONする)|AnswersでのUNION|データフローでのUNION|サブジェクト領域やデータセットで縦に行を追加する|
|　||||

適宜、追記予定です

ブックマークリンク
---

|ユースケース|
|---|
| [アクションリンクで別のダッシュボードページに遷移させる。異なるサブジェクト領域間へのパラメータ渡し編](https://qiita.com/tni38/items/ee3a632478454ce42bce)|
|　|


変更履歴：2025/02/06 ユースケース追加　ブックマークリンク、比較表の項目追加

以上
Try Hack Me で初っ端から躓いた時

下記のURLを参考にして「Try Hack Me」で問題が起きた時に修正してくれるツールをダウンロードして、解凍して使用しました。

["Try Hack Me 失敗したとき"](https://qiita.com/Brutus/items/88fec1ad4a709c414f90 'Try Hack Me 失敗したとき')

ダウンロードした修正ツールはこちらになります。
Zipファイルを解凍してフォルダの中身を取り出すと3つのファイルがありました
* ` thm-troubleshoot `
* ` README.me `
* ` README_RU.me `

[修正ツールのURL](https://github.com/tryhackme/openvpn-troubleshooting '修正ツール')

使用手順
* ` thm-troubleshoot `を取り出す(実行しやすいようにユーザー名の直下に移動したら楽)
* ターミナルで` thm-troubleshoot `の直下まで移動
* 下記のコマンドでファイルの権限を変更
```
chmod +x thm-troubleshoot
```
* 下記のコマンドでファイルを実行
```
./thm-troubleshoot  
```
* 下記の出力があれば実行成功できています
```
└─PS> ./thm-troubleshoot                                                     


         _____           _   _            _    __  __
        |_   _| __ _   _| | | | __ _  ___| | _|  \/  | ___                   
          | || '__| | | | |_| |/ _` |/ __| |/ / |\/| |/ _ \                  
          | || |  | |_| |  _  | (_| | (__|   <| |  | |  __/                  
          |_||_|   \__, |_| |_|\__,_|\___|_|\_\_|  |_|\___|                  
                   |___/                                                     
                                                                             
Looks like you're running Kali                                          @MuirlandOracle   
```
### 以降はyかnを答えるのと 「Try Hack Me」からダウンロードしたファイルの場所を入力するという作業があります。（※以下はアカウント名が仮名でusername、vpnフォルダに入れています）
```                                                                
[-] Script is being run as a low-privileged user
Would you like to run this script with higher privileges automatically (Y/n)? y
[+] Re-running with root permissions
[-] Config not found in current directory
Please enter the path to your config: ./vpn/username.ovpn
[+] Config Located successfully
[+] Stable internet connection
[+] OpenVPN is installed
[+] tun0 exists
[+] tun0 IP is in the correct range
[-] More than one connection running
Would you like the script to attempt to fix this (Y/n)? y
[+] Killed duplicate processes
[+] Connecting....
[+] Connection Process completed successfully!
[+] Confirming connectivity
[-] MTU not working with the value of 1500
[+] MTU set at 1470 in tun0
[!] Note that a working MTU value might change depending on your network condition                                                                        
Would you like the script to set the MTU value permanently in your .ovpn file (Y/n)? y
[+] .ovpn file MTU value and comment added
[+] Connectivity checks completed!
[+] You are connected to the TryHackMe Network
Your TryHackMe IP address is: 10.4.**.**

Happy Hacking!
```
処理が終わると
入力できる状態に戻るので` ping -c *********** `で接続先と繋がるか確認してみてください

#### ※上記の参考にさせて頂いた記事に書いてあるようにVPNの接続画面では接続できてないと表示されたままかもしれませんが、ping コマンドで接続成功できていれば問題ありません

#### ※下の画像のインターネットの設定のVPN接続ですが、チェックボックスに☑しなくて大丈夫です（☑するとインターネットからの接続が途切れます）
![Vpn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957418/6506eada-a607-7db5-ff5b-7e6865061123.png)
C# NLog5.x on Visual Studio 2022

# はじめに

VisualStudio2022を使ったC# Windowwフォームアプリケーションプログラミングで、「アプリケーションのログを記録するには？」と別途MicrosoftCopilotに質問したところ、NLogを使う方法を参考に教えられた。

Copilotの教えだけではうまくいかなかったので、実際に動作する設定ほうほ情報を残しておく。

# 概要

Nugetパッケージ管理ツールで、Nlogだけプロジェクトにインストールして、NLog.configを手作業でプロジェクトに追加、追加したNLog.configファイルを、出力ディレクトリに常にコピー設定すれば準備完了。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/e331ffb7-84b9-5ce4-d730-74a8d44157c4.png)



NLog.configファイルの書き方は、以下参考情報を参照のこと。

# 参考
こちらの先達の情報がかなり詳しい。ありがたいですな。

https://qiita.com/developpermanati/items/1de20d836070f42049cf

本家（一次情報）

https://nlog-project.org/

# このQiitaで特に言いたいこと

先達の教えで足りなかったところ。


<strong> 「NLog.configファイルを作ったら、”出力ディレクトリに常にコピーする"設定を忘れるな」 </strong>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699890/ab088018-1624-c188-6150-866cd8f68b44.png)



以上。
[2025年最新]Django最新バージョンでAWS S3に画像を保存する方法（備忘録）

## Django最新バージョンでAWS S3に画像を保存する方法2025年版（備忘録）

初投稿です:relaxed:

勉強がてらにDjangoでPWAアプリを作る中で、画像をAWS S3に保存してみようと思い挑戦しますが、日本語での情報が少ないことと、ChetGPTが今回のトピックで使い物にならず(古い情報ばかり)、かなりの時間を費やしたのでやり方を共有しておきたいと思います！
最後のほうに参考にしたページを張っておきます！(結局公式ドキュメント見れば一発)

### Django4.2以降は書き方が変わったらしい
以前の書き方
```
# settings.py

AWS_STORAGE_BUCKET_NAME = S3のバケット名
AWS_S3_REGION_NAME = バケットのリージョン

AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')

"""ここが問題!!!!"""
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
"""!!!!!!"""

```

### [重要]新しいバージョンのDjangoでの書き方

```
STORAGES = {
    "default": {
        "BACKEND": "storages.backends.s3boto3.S3Boto3Storage",
        "OPTIONS": {
            "bucket_name": "your-bucket-name",
            "access_key": "your-access-key",
            "secret_key": "your-secret-key",
            "location": "media/images",  # ここでディレクトリを指定
        },
    },
    "staticfiles": {
        "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
    },
}
```

前までDEFAULT_FILE_STORAGEで指定していたストレージエンジンをSTORAGESに書きます

実際に動いたコードです↓2025/1/20現在
```
import os
from dotenv import load_dotenv

load_dotenv()

"""AWS S3の設定"""
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME')
AWS_S3_REGION_NAME = os.getenv('AWS_S3_REGION_NAME')
AWS_S3_SIGNATURE_VERSION = 's3v4'

STORAGES = {
    # メディアファイルはS3ストレージ
    "default": {
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {
            "location": "media/images", 
        },
    },
    # 静的ファイルはローカルストレージ
    "staticfiles": {
        "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
    },
}
MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.{AWS_S3_REGION_NAME}.amazonaws.com/media/"


# """古のMedia設定 Django ver.4.2以降からはSTORAGESでないと動かない"""
# MEDIA_URL = "/media/"
# MEDIA_ROOT = os.path.join(BASE_DIR, "media")
#DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

"""Staticの設定"""
STATIC_URL = "/static/"
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'frontend', 'static'),
]
```

### 今回やりたかったこと
画像だけS3に保存して、Static(cssやjs、PWAで使用するjsonなど)はローカルで管理したいと思っていました。

### 参考にしたサイト
↓公式ドキュメント
https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-STORAGES

↓STORAGESをきれいに書くには？的な議論
https://forum.djangoproject.com/t/storage-4-2-how-to-subclass-default/29190/3
【Ruby on Rails】rails newがエラーになる

# 発生した事象
2025年1月20日、rails 6.1.7.7 で```rails new```した時にエラーになった。
```zsh
❯ rails new test_app -d postgresql
~/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/activesupport-6.1.7.10/lib/active_support/logger_thread_safe_level.rb:16:in `<module:LoggerThreadSafeLevel>': uninitialized constant ActiveSupport::LoggerThreadSafeLevel::Logger (NameError)

    Logger::Severity.constants.each do |severity|
    ^^^^^^
```

# 原因
https://stackoverflow.com/questions/79360526/uninitialized-constant-activesupportloggerthreadsafelevellogger-nameerror

上記のスレッドにあるとおり、concurrent-rubyというgemのv1.3.5（2025年1月16日リリース）に入った変更が原因だった。

# 解決策
既存のrailsプロジェクトで、`Gemfile`が存在する場合は、下記の記述を追加してconcurrent-rubyのバージョンを1.3.4にロックすればよい。
```ruby:Gemfile
(...省略...)
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'
gem 'rails', '~> 6.1.7', '>= 6.1.7.10'
# Use concurrent-ruby v1.3.4
gem 'concurrent-ruby', '1.3.4' <= この行を追記
(...省略...)
```

`rails new`前でGemfileが存在しない場合は、先に`bundle init`でGemfileを作成し、concurrent-rubyのバージョンをv.1.3.4にロックしてから、`rails new`するとうまくいった。

```zsh
mkdir my_app
cd my_app

bundle init
=> Gemfileができる

echo "gem 'rails', '~> 6.1.7', '>= 6.1.7.7'" >> Gemfile
echo "gem 'concurrent-ruby', '1.3.4'" >> Gemfile
cat Gemfile
=> Gemfileに上記のrails, concurrent-rubyのバージョン指定が追記されていることを確認する

bundle exec rails _6.1.7.7_ new .
=> 途中でGemfileがconflictしているが上書きするか？と聞かれるので、Y（上書きする）で進む
```
以上でrailsアプリが作成された。
最後に念のため、生成された`Gemfile`にconcurrent-rubyのバージョンロックを追加した。
```ruby:Gemfile
(...省略...)
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'
gem 'rails', '~> 6.1.7', '>= 6.1.7.10'
# Use concurrent-ruby v1.3.4
gem 'concurrent-ruby', '1.3.4' <= この行を追記
(...省略...)
```
[Linux][system][command] 初期化システム_ランレベルの切替/反映方法_GRUB/GRUB2, Sysvinitt, systemd, init, telinit, systemctl, ln

# 起動プロセス

```mermaid
 flowchart LR
 A((電源ON)) --> B[BIOS/UEFI]
 B --> C[ブートローダ]
 C --> D[カーネル]
 D --> E[初期化システム<br>init system]
 E --> F((ログイン画面表示))
 ```

# ブートローダ(GRUB/GRUB2)
- ブート時に適用
- OS起動後のランレベルを変更不可

## 変更方法
1. システムの起動初期段階でGRUBのメニューが表示された際に、`E`キーを押す
1. 編集モードが表示される（キーボードでオプションを入力できる）
1. ブートオプションを入力する

|オプション||
|:--|:--|
|root=デバイス||
|nousb|USBデバイスを使用しない|
|single|シングルユーザーモードで起動する|
|1~5|指定したランレベルで起動する|

# 初期化システム(SysVinit/systemd)
- OS起動後のランレベルを変更可能

## 変更方法
### SysVinit
~~~terminal:bash
$ init 1|s|S

/// または

$ telinit 1|s|S
~~~

### systemd
~~~terminal:bash
$ systemctl rescue.target
~~~

### systemd(デフォルト)
~~~terminal:bash
$ rm -f /etc/systemd/system/default.target
$ ln -s /lib/systemd/system/graphical.target /etc/systemd/system/default.target
~~~

## 反映方法
### SysVinit
~~~terminal:bash
$ init q 
$ init Q

/// または

$ telinit q
$ telinit Q
~~~
### systemd
~~~terminal:bash
$ systemctl daemon-reload
~~~

# ランレベルとターゲット
||ランレベル|ターゲット<br>/etc/systemd/system|ターゲット<br>/lib/systemd/system|
|:--|:-:|:-:|:-:|
|対象初期化システム|init(SysVinit)|systemd|runlevel0.target|
|停止|0|poweroff.target|runlevel0.target|
|シングルユーザーモード|1/s/S|rescue.target|runlevel1.target|
|マルチユーザーモード<br>（テキストログイン）|2, 3, 4|multiuser.target|runlevel[234].target|
|マルチユーザーモード<br>（グラフィカルログイン）|5|grafical.target|runlevel5.target|
|再起動|6|reboot.target|runlevel6.target|

# Ping-t
- [3009_init, telinit](https://mondai.ping-t.com/question_subjects/31/question_sessions/30339661/progressing_questions/464809429)
- [3405_telinit S](https://mondai.ping-t.com/question_subjects/31/question_sessions/31355318/progressing_questions/480441630)
- [3406_2, 3, 5](https://mondai.ping-t.com/question_subjects/31/question_sessions/31718661/progressing_questions/486071286)
- [3408_0, 6](https://mondai.ping-t.com/question_subjects/31/question_sessions/31734908/progressing_questions/486315150)
- [3407_再起動](https://mondai.ping-t.com/question_subjects/31/question_sessions/30553580/progressing_questions/468115704)
- [3601_default.target](https://mondai.ping-t.com/question_subjects/31/question_sessions/31734908/progressing_questions/486315156)
- [3619_rescue.target, runlevel1.target](https://mondai.ping-t.com/question_subjects/31/question_sessions/31718661/progressing_questions/486071284)
- [3620_multi-user.target, runlevel3.target](https://mondai.ping-t.com/question_subjects/31/question_sessions/32927143/progressing_questions/504391365)
- [3654_init q, telinit q](https://mondai.ping-t.com/question_subjects/31/question_sessions/31718661/progressing_questions/486071292)
30歳からのエンジニア転職

# 目次
- はじめに
- 自己紹介
- 転職を決めた理由
- エンジニアを選んだワケ
- 今やっていること・これからのこと
# はじめに
はじめまして。

私は昨年30歳を迎え、手取り300万円以下でスキルアップも昇給も見込めない限界業界から、転職を決意しました。

このプラットフォームでは、何を、どのように勉強しているか、何がわからなくて、どう解決したのか、果たして転職は無事に成功するのか、を発信していきたいと思っています。
# 自己紹介
**名前：automated_tomato**
（オートメイテッド・トマト：［訳］自動トマト）
オンラインゲームなど、様々なオンラインプラットフォーム上でこの名前を使っています。

**生年：1994年**･･･大谷世代です。

**経歴**
外国語系の国立大学（カナダに1年留学）
↓
某国立大学の人文社会学系学問で修士号取得
↓
人文系学術系出版社に3年勤める
↓
転職を決意し、2025年1月末で退職

見ての通り、ゴリゴリバッキバキの文系です。

留学や大学院まで入れると、のべ8年間も大学にいたというと、文系の中でもなかなかに特異な経歴かもしれません。
# 転職を決めた理由
 - 収入が低すぎる
 - スキルが適切に評価され、それが給与に反映されていな
 - 成長の限界を早々に感じた
 - 同じことの繰り返しで飽きた

30歳大学院卒の年収の中央値は、統計データによって異なりますが、概ね500万円を下回ることはありません。しかし、私が入っていた会社では、年収およそ320万円と、それよりも遥かに低かったわけです。
ただ低いだけなら、まだ納得できたかもしれません。
私が大学院でガリガリ勉強して培ってきた読解力や、院生時代の人脈、また、留学経験から身につけた英語力（海外出張にも行きました）、これらを、とんでもなく安い金額で買い叩かれていることに、どうしようもなく腹が立ちました。
しかも、出版社というのは、求められる「スキル」（組版とか、そういう実務的な）はかなり限られており、1年もすればそれらの「スキル」は大体覚えられちゃうんですね。
で、そうすると、私特有の技術や人脈は安く買い叩かれ、かといって業務上求められるスキルは早々に頭打ちになってしまい、いわゆる「成長」の余地がないように感じてしまいました。320万円で技術的に頭打ち？あとは長く働き続けるしかないの？
そう思った瞬間に、とんでもない閉塞感に襲われ、「このままじゃダメだ、何か常に成長を実感できるようなスキルを身につけねば」という焦燥感が湧いてきました。
# エンジニアを選んだワケ
 - 未経験でも今より高い給与を提示していることが多い
 - 業界としても個人としても、成長が望める
 - 場所に依存しない働き方の選択肢を持てる
 - 勉強に耐性がある自分には向いてそう

大学時代に留学をし、また社会人になってからも海外旅行とかにはたまに行っていたんですが、その度に「ああ、海外で暮らしてみたいな」と思っていたのですが、学術系出版社は言語を高度に扱う仕事である以上、かなり日本という文脈に依存している業界だな、と思い、なんとなく諦めていました。
その点、プログラミング言語というのは世界共通で通じる言語ですし、その意味では物理的空間という文脈への依存度がそこまで高くなく、参入への障壁の少ない部分が勉強が必須という点にあるとすれば、勉強に耐性のある私が、海外で働くという選択肢を残しておくためには最善なのでは？とそう考えました。

ざっくり言うと、
なんか成長し続けられそうだし、年収も悪くなさそうだし、海外で働けそうだし、勉強してれば良さそうという、誰もが思いつくようなふんわりした理由ですね
# 今やっていること・これからのこと
退職は11月に決めました。
そこからまずはかなり難しそうで、コーヒーが好きだからという理由で、Javaから始めました。難しい言語の方が、「無駄」を削ぎ落とされた最新の言語より、プログラミングとは何たるかとか学べそうだし、あとは難しい言語にさえ慣れちゃえば、より簡潔な言語の学習は楽そうだから。Pythonとか簡単な言語から始める人が多い中、よくわからん理由ですね。
12月の頭には退職の旨を会社に伝え、1月末に退職予定。
今は1日に4時間程度、有給消化日には8時間くらい勉強していて、最近はブログサイトを実際にビルドしながら、JavaとSpring Boot、データベース周りを学んでいます。マイクロサービス的視点を取り入れた開発もしてみたいので、Golangにも手を出したいな〜とか思っています。

どうやって勉強しているかとか、そういうのはまた別の機会に書こうと思っていますが、基本的には生成AI（Claude）をチューターに設定して学んでいます。
どのようなプロンプトを用いて生成AIをチューターに仕立て上げているかは、また書こうと思います。
【C++】string型の文字列からchar型を取り出す

与えられた文字列から一文字ずつのASCIIコードを取り出して計算したかった時に詰まったので備忘録として書きます。

## やりたかったこと
```c++
string key
```
が文字列として与えられた時に、この文字の一つずつをchar型として取り出してASCIIコードの足し算をしたい。

## 実装方法
結論範囲for文で文字を一つずつ取り出せます。
また、取り出した文字は変換することなく足し算できます。

int型とchar型の足し算や、char型どうしの足し算ではchar型が自動的にint型に変換されるため問題なく計算ができます。
```c++
//合計の変数を作る
int sum{0};
//文字から文字を取り出してASCIIコードの合計を求める
for(char ch : key){
    sum += ch;
}
```

調べても記事があまりなかったので書きました。何か間違っていることがあれば教えてください🐢
【ABC389】AtCoder Beginner Contest 389【C++】

### コンテスト名
トヨタ自動車プログラミングコンテスト2025（AtCoder Beginner Contest 389）

### コンテストURL
https://atcoder.jp/contests/abc389

### 開催日
2025/01/20 21:00-22:40

---

## [A: 9x9](https://atcoder.jp/contests/abc389/tasks/abc389_a)
**解法**
- 文字型の数字から `0` を引いて整数型に変換する
```cpp:ABC389A.cpp
#include <iostream>
#include <string>
using namespace std;

int main(){
    string s;
    cin >> s;

    cout << (s[0]-'0')*(s[2]-'0') << endl;

    return 0;
}
```

## [B: tcaF](https://atcoder.jp/contests/abc389/tasks/abc389_b)
**解法**
- 全探索
- 小さいほうから順に乗算して判定する
```cpp:ABC389B.cpp
#include <iostream>
using namespace std;

int main(){
    long long int x;
    cin >> x;

    long long int mul = 1;
    for(int i=2; ; i++){
        mul *= i;
        if(mul==x){
            cout << i << endl;
            return 0;
        }
    }
}
```

## [C: Snake Queue](https://atcoder.jp/contests/abc389/tasks/abc389_c)
**解法**
- 累積和
- 列から抜けたヘビの数を記録し、先頭にいるヘビを特定する
- 累積和によって先頭にいるヘビからの距離を求める
```cpp:ABC389C.cpp
#include <iostream>
#include <vector>
using namespace std;

int main(){
    int q;
    cin >> q;

    int num, l, k;
    vector<long long int> V;
    int top = 0;
    V.push_back(0);
    for(int i=0; i<q; i++){
        cin >> num;
        if(num==1){
            cin >> l;
            long long int tmp = V.back();
            V.push_back(tmp+l);
        }else if(num==2){
            top++;
        }else{
            cin >> k;
            k--;
            cout << V[top+k] - V[top] << '\n';
        }
    }

    return 0;
}
```

## [D: Squares in Circle](https://atcoder.jp/contests/abc389/tasks/abc389_d)
**解法**
- しゃくとり法
- 円の対称性により、右上の $\frac{1}{4}$ 円について、点 $(i+0.5, j+0.5)$ と原点の距離を考える
- $i$ が大きくなるにつれて、 $j$ は小さくなるため、しゃくとり法で求める
```cpp:ABC389D.cpp
#include <iostream>
#include <vector>
using namespace std;

int main(){
    long long int r;
    cin >> r;

    vector<double> dx = {0.5, 0.5, -0.5, -0.5}, dy = {0.5, -0.5, 0.5, -0.5};
    long long int cnt = 0;
    int y = r;
    for(int i=0; i<=r; i++){
        while(((i+dx[0])*(i+dx[0])+(y+dy[0])*(y+dy[0]))>r*r && y>-1){
            y--;
        }

        if(y==-1){
            break;
        }

        cnt += y + 1;
    }

    cout << cnt*4 - (r-1)*4 - 3 << endl;
    
    return 0;
}
```
Vagnrat 2.4.3でvagrant-vbguestが実行されるとエラーになる

`VirtualBox 7.0.10`＋`Vagrant 2.4.1`で構築した環境に対して、`VirtualBox 7.0.22`＋`Vagrant 2.4.3`にアップグレードすると、`vagrant-vbguest`でエラーになる。

```
==> default: Attempting graceful shutdown of VM...
==> default: Destroying VM and associated drives...
/usr/share/vagrant/gems/gems/vagrant-vbguest-0.32.0/lib/vagrant-vbguest/hosts/virtualbox.rb:84:in `block in guess_local_iso': undefined method `exists?' for class File (NoMethodError)

            path && File.exists?(path)
                        ^^^^^^^^
```

https://github.com/hashicorp/vagrant/issues/13404

原因は、Rubyのバージョンが上がったことで、`File.exists?(path)`が`File.exist?(path)`に変更されたため。
`vagrant-vbguest`本家（ https://github.com/dotless-de/vagrant-vbguest ）はメンテナンスされておらず、このバグ修正がされていないが、Forkされたリポジトリ( )で修正されているため、そのvagrantプラグインを使用するよう変更する。

````bash
git clone https://github.com/dheerapat/vagrant-vbguest.git
cd vagrant-vbguest

# gemは環境によって異なります。パスが通っていない場合は、フルパスを指定してください。
gem build vagrant-vbguest.gemspec

vagrant plugin install ./vagrant-vbguest-0.32.1.gem
````
````shell
C:\> git clone https://github.com/dheerapat/vagrant-vbguest.git
C:\> cd vagrant-vbguest

# Windowsの場合、gemはVagrantをインストールした場所にあります。
C:\> & 'C:\Program Files\Vagrant\embedded\mingw64\bin\gem' build .\vagrant-vbguest.gemspec

C:\> vagrant plugin install .\vagrant-vbguest-0.32.1.gem
````
iOS 18.2から発生しているアプリ内購入エラーの修正方法

# 概要

iOS18.2からアプリ内購入時のエラーの頻度が増加した。

https://x.com/takumi_cubic/status/1868947354302529569?s=46

https://x.com/yurudora/status/1870042421666689101?s=46

https://x.com/kaview_jp/status/1879095876192539047?s=46

https://x.com/simpleapplin/status/1879029960381517914?s=46

どうやらiOS18.2で`StoreKit`の`purchase`メソッドに変更があり、その影響を受けたものと見られる。
iOS18.2より前から存在するメソッドに以下のような記述があり、UIKitを使用している場合は`comfirmIn`と`options`を引数とする方のメソッドを使えとのこと。

```
Use Product/purchase(confirmIn:options:) for apps that use UIKit.
```

https://developer.apple.com/documentation/storekit/product/purchase(confirmin:options:)-3bivf

https://developer.apple.com/documentation/storekit/product/purchase(options:)

## 結論

UIKitを用いているアプリは`purchase`メソッドをiOS18.2以降と未満で処理を分ける。

```swift
if #available(iOS 18.2, *) {
  result = try await product.purchase(confirmIn: viewController)
} else {
  result = try await product.purchase()
}
```

## 実装時に参考にしたスレッドなど

## Apple Forums

https://forums.developer.apple.com/forums/thread/770751

https://forums.developer.apple.com/forums/thread/768410

## X

https://x.com/dimix/status/1873514939517993371
自分の1234日分 打鍵数2700万回のキー別集計結果

キーボードのキーマップを検討する上で、自分はどのキーをどれくらい打鍵しているのかを知っておきたい。

ということで、計測を始めてからこれまでの間=**1234日分の打鍵約2700万回の内訳**を晒しておく。

:::note info
参考情報
- Windows OS
- 使用キーボード = 日本語（Realforceフル、HHKB、ErgoDoxEZ）
- 職種 = IT系マーケティング関連職
- 入力内容は社内コミュニケーションとExcelが主
- コーディングはほとんどしない（たまにする）
:::

「全打鍵数に占める出現率」の数字を見るだけだと「出現率0.1%か。じゃあネグってもよさそうだな」と考えてしまいがち。

ただ、出現率0.1%のキーは自分の場合は1日に20回も打鍵機会があるキーということになる。ないがしろにするとストレスになる。

なので1日の打鍵数を20000回として（実際は平均21865回だった）、このキーは1日に何回打鍵機会があるか？」の目安の数字を添えて、キーマップの検討に役立つようにしてみた。

### 分類別ランキング
#### Modifier
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319408/f9e64ac4-10c5-38e8-adf5-253394bdaad3.png)
※Win右はどうやって押せたんだろうか
#### 機能系
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319408/f286fcb5-901a-e589-fec1-6b6d5b0dcba7.png)
※変換、無変換、カナ/かな、NumLock、ScrollLockは絶対誤打鍵
#### アルファベット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319408/0c0c177f-a1e5-e1ae-962c-95fd4d99ff08.png)
※Qwerty/Dvorakではなくオリジナル配列を作るとき、マイナー英字の把握は役に立つ
#### 数字・テンキー系
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319408/b2e8be7d-ae54-c27e-786a-1f8c041c9db3.png)
※8、9が上位なのはカッコの入力が多いということだろう
#### 記号系
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319408/f9b24903-4231-dcda-310c-d24d7d178382.png)
※@を過小評価していた。Slackを使っているからかもしれない
#### 移動系
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319408/37ccdad9-4201-8f62-6f74-3891b50a2014.png)
※36キーか38キーのキーマップを検討したいけど、矢印の使用頻度がこんなに高いとなかなか難しいか
#### ファンクションキー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319408/a414596e-1e52-efab-d54c-d2e43c235c8b.png)
※F2はファイル名とExcelのセル編集開始、F10はShift+F10（右クリック相当）とFEP入力中の英数変換によって頻度が高くなっていると想像

### 全体ランキング
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319408/9741d852-f700-1d90-67bc-9a815fdfe14c.png)