OmniAICreator/Qiita-1.07M huggingface dataset:
AHC032 参加録

# めちゃめちゃ反省が残る回になった


# やった事
- 乱択で改善していった
- 端っこがうまく高得点になるようにスタンプを複数重ねたパターンを作った

# 時間毎に考えた事
## ~20:00
- 左上からうまく詰めれるから貪欲ありかな?
- スタンプ複数重ねたら考えるの楽かな?

- けど乱択しちゃお！w

## ~23:00
- 少しずつ改善していった
- おわり

# 反省点
- 最初の一時間で上位組の考え方と同じものが出ているのになぜかスルーした事がデカすぎる
- 短期間マラソンで貪欲をとりあえず最初に書くのは大事にしてもいいかも
debugPrintを活用する

# はじめに
個人開発でQiitaアプリを制作しています。
マイページを作成していましたが、ユーザの情報がなかなか表示されずに困ってしまいました。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557870/c6297a85-a1ad-7c43-8f5b-bba6d04e7fe6.png" width="400">

内容は、仮置きで置いている状態です⬆️

# 修正前のソースコード（一部抜粋）

![スクリーンショット 2024-04-07 23.09.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557870/db71ebb1-0b54-24b1-ca59-abe799f89f2e.png)

## 解決策：dubugPrintをひたすら出力させる
何が原因なのか、dubgPrintを使用して探ることにしました。
以下のコードのようにdubugPrintを加えました。⬇️

```dart:
 static Future<User> fetchAuthenticatedUserInfo() async {
    final accessToken = await _getAccessToken(); // アクセストークンを取得するメソッド
    debugPrint('Fetched access token: $accessToken'); // ログ出力でトークン確認


    final url = Uri.parse('${Urls.qiitaBaseUrl}/authenticated_user');
    debugPrint('Requesting authenticated user info from: $url'); // リクエストURLのログ

    final response = await http.get(url, headers: {
      'Authorization': 'Bearer $accessToken'
    });
    debugPrint('Received response: ${response.body}'); // レスポンス内容のログ

    if (response.statusCode == 200) {
      final Map<String, dynamic> jsonResponse = jsonDecode(response.body);
      return User.fromJson(jsonResponse);
    } else {
      debugPrint('Error fetching user info: ${response.statusCode}');
      throw Exception(_exceptionMessage(response.statusCode));
    }
  }

static Future<String> _getAccessToken() async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  final String? accessToken = prefs.getString('accessToken');

  // アクセストークンの存在をログで確認
  debugPrint('Access token from SharedPreferences: $accessToken');

  if (accessToken == null || accessToken.isEmpty) {
    debugPrint('Access token is null or empty');
    throw Exception('No access token found');
  }
  return accessToken;
}
```

## 出力結果
上記の内容においてのdubugPrint出力結果⬇️

![スクリーンショット 2024-04-07 23.07.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557870/1cad753f-c6a2-8330-ac38-5bb058eba4d3.png)

上記の内容を要約すると、以下のようになります。
* ログインした人のアクセストークン→⭕️取り出せている
* ログインした人の情報→❌出力されていない
「Failed to fetch user info: type 'Null' is not a subtype of type 'String' in type cast」と言われてしまっています。


つまり、nullの値が与えられているのに、nullの値が許容されていないString型に無理やり変換しようとしています。
修正するにはnullの値を許容できるようにする必要があります。
以下のようにコードを修正してみました。

# 修正後のソースコード（一部抜粋）

![スクリーンショット 2024-04-07 23.12.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557870/26f12f56-8128-69c4-a333-b02e44f55996.png)


## 無事に解決
上記のようにコードを修正したら無事にマイページにユーザ情報を取得できました。⬇️

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557870/f5c785e7-f715-e30d-e3f9-761bdf262e55.png" width="400">
プログラマが知るべき97のこと-抜粋

## はじめに

`プログラマが知るべき97のこと`は、プログラミングに関する様々な知見やアドバイスを提供する書籍だ。本記事では、その中から特に重要だと感じたトピックについてざっくりとまとめる。

:::note warn
原文ではなく、読んだことをさっくりまとめているので正しいものを知りたい場合は原書を参考にしてください
:::

今回は、テストやプロジェクトの進め方に関することを取り上げていないが本の中では言及があるため、興味がある人は読んでみるといいだろう。

## 1. ボーイスカウトルール

- コードを変更する際は、常に少しでもコードを綺麗にしておく
- 関数の修正時に変数名を分かりやすいものに変更するだけでも、コードの可読性が向上する
- 小さな改善の積み重ねが、長期的にコードの品質を高めることにつながる

:::note info
コードを変更する際は、常に少しでもコードを綺麗にしておくことが重要だ。小さな改善の積み重ねが、長期的にコードの品質を高めることにつながる。
:::

## 2. 故意の技術的負債を作らない

- 技術的負債とは、短期的な利益のために品質を犠牲にしたコードを指す
- そのようなコードは想定以上に長く使われ続ける可能性がある
- 最初から手を抜かないか、早期に適切に修正することが重要

:::note info
短期的な利益のために品質を犠牲にしたコードは、長期的に問題を引き起こす可能性がある。最初から手を抜かないか、早期に適切に修正することが重要である。
:::

## 3. 関数型プログラミングの重要性

- 関数型プログラミングは、オブジェクト指向プログラミングとは異なるアプローチ
- その概念を学ぶことはオブジェクト指向プログラミングにも応用できる
- 両方のパラダイムを理解することで、より柔軟で効果的なプログラミングが可能になる

:::note info
関数型プログラミングの概念を学ぶことは、オブジェクト指向プログラミングにも応用できる。両方のパラダイムを理解することで、より柔軟で効果的なプログラミングが可能になる。
:::

## 4. コメントの役割
:::note info
- コメントは、コードだけでは表現できない情報を提供するために使用されるべき
- ただし、`可能な限り`コード自体で意図を明確に表現することが重要
:::

## 5. 複数のプログラミング言語の習得

- プログラマは、手続型、オブジェクト指向型、関数型、論理型、データフロー型など、複数のプログラミング言語を学ぶべき
- 異なるパラダイムの言語に触れることで、アルゴリズムやイディオム、パターンの実装について考えを深められる
- 数ヶ月間、継続的に触れることで、言語のイディオムを身につけることができる

:::note info
異なるパラダイムの言語に触れることで、プログラミングスキルを向上させることができる。新しい言語を学ぶ際には`異なるパラダイムの言語を学ぶことが重要`である。
:::

## 6. コードを読む重要性

- 自分のコードであっても、他人のコードであっても、コードを読み、理解することが、技術力向上の鍵となる
- どのような点が読みづらさを引き起こしているのかを特定し、自身のコード書きに活かすことが大切

:::note info
コードを読み、理解することが、技術力向上の鍵となる。読みづらさの原因を特定し、自身のコード書きに活かすことが大切だ。
:::

## 7. 自動化の推進

- プログラマは、テストからデプロイまで、自動化できる部分は積極的に自動化すべき
- 自動化ツールは、シェルスクリプトやSeleniumなどを使って、自分で作成することもできる

:::note info
プログラマは、自動化できる部分は積極的に自動化すべきだ。`自動化ツールは、自分で作成することもできる。`
:::

## まとめ

「プログラマが知るべき97のこと」の中でも自分でも実行が容易そうなものをまずまとめた。自分のレイヤーがPGであることから、コード品質に関するものを取り上げることとなったが数か月・数年後はまた違った新しい知見が隠れている良い本であると感じた。

## 参考図書

https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%8C%E7%9F%A5%E3%82%8B%E3%81%B9%E3%81%8D97%E3%81%AE%E3%81%93%E3%81%A8-%E5%92%8C%E7%94%B0-%E5%8D%93%E4%BA%BA/dp/4873114799

下記で無料公開されているが、サイト情報的にはライセンスとしては問題なさそう、、？こちらで読む場合は自己責任でお願いします。

https://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/
density

```ruby:title.rb

import pandas as pd
import numpy as np

r_res = 0.01 # 距離方向の分解能（m）

# DataFrameの作成
df = pd.DataFrame(columns=['r', 'theta', 'phi'])

# r, theta, phiの値を生成するリスト内包表記
data = [{'r': r, 'theta': theta, 'phi': phi} 
        for r in [num * r_res for num in range(0, 1000)]
        for theta in range(-30, 32, 2)
        for phi in range(-30, 32, 2)]

sin_th = np.sin(np.radians(df['theta'].astype(float)))
cos_th = np.cos(np.radians(df['theta'].astype(float)))
sin_ph = np.sin(np.radians(df['phi'].astype(float)))
cos_ph = np.cos(np.radians(df['phi'].astype(float)))

# DataFrameにデータを追加
df = df.append(data, ignore_index=True)

df['x'] = df['r'] * np.sin(np.radians(df['theta'].astype(float))) * np.cos(np.radians(df['phi'].astype(float)))
df['y'] = df['r'] * np.sin(np.radians(df['phi'].astype(float))) * np.cos(np.radians(df['theta'].astype(float)))
df['z'] = df['r'] * ((1-(np.sin(np.radians(df['theta'].astype(float)))**2)*(np.cos(np.radians(df['phi'].astype(float)))**2)-(np.sin(np.radians(df['phi'].astype(float)))**2)*(np.cos(np.radians(df['theta'].astype(float)))**2))**0.5)
df['r_check'] = (df['x']**2 + df['y']**2 + df['z']**2)**0.5

# データフレームを表示
df.tail()




import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 半球のパラメータ
r = 10  # 球の半径
phi, theta = np.mgrid[0:np.pi/2:100j, 0:2*np.pi:100j]  # phiとthetaの範囲を設定

# 極座標から直交座標に変換
x = r * np.sin(phi) * np.cos(theta)
y = r * np.sin(phi) * np.sin(theta)
z = r * np.cos(phi)

# プロット
fig = plt.figure(figsize=(16.0, 12.0))
ax = fig.add_subplot(111, projection='3d')

ax.scatter(df['x'], df['y'], df['z'], alpha=0.01)
# 半球をプロット
ax.plot_surface(x, y, z, alpha=0.2)

# 軸の範囲とラベル設定
ax.set_xlim([-10, 10])
ax.set_ylim([-10, 10])
ax.set_zlim([0, 20])

# 軸の縮尺を等しくする
ax.set_box_aspect([1,1,1])

#ax.tick_params(labelbottom=False, labelleft=False, labelright=False, labeltop=False)

# グラフを表示
plt.show()


# 検証として1 m^3の立方体の密度を考える
立方体の座標範囲はx:-0.5～0.5, y:-0.5～0.5, z:n～n+1　（nは2から6まで1ずつ動かしてみる）
立方体内に含まれる点数をカウントするだけで密度は求まる
## まずは補正せずに計算


density = []
for n in range(1,8):
    df_d = df[(df["x"]<0.5) & (df["x"]>-0.5) & (df["y"]<0.5) & (df["y"]>-0.5) & (df["z"]<n+1) & (df["z"]>n)]
    density.append(len(df_d))
    print("n = {} のときの立方体内の点密度{}".format(n,len(df_d)))
df_d.head()


## カウントする際に半径の2乗を重みにかけて補正計算



adjusted_density = []
for n in range(1,5):
    df_d = df[(df["x"]<0.5) & (df["x"]>-0.5)&(df["y"]<0.5) & (df["y"]>-0.5)&(df["z"]<n+1) & (df["z"]>n)]
    df_d["r^2"] = df_d["r"]**2
    pts_sum = df_d["r^2"].sum()
    adjusted_density.append(pts_sum)
    print("n = {} のときの立方体内の補正点密度{}".format(n,pts_sum))





```
keisan3

```ruby:title.rb

import pandas as pd
import numpy as np

# DataFrameの作成
df = pd.DataFrame(columns=['r', 'theta', 'phi'])

# r, theta, phiの値を生成するリスト内包表記
data = [{'r': r, 'theta': theta, 'phi': phi} 
        for r in range(4, 5)  # rの範囲は1～10
        for theta in range(-60, 62, 2)
        for phi in range(-60, 62, 2)]

# DataFrameにデータを追加
df = df.append(data, ignore_index=True)

df['x'] = df['r'] * np.sin(np.radians(df['theta'].astype(float))) * np.cos(np.radians(df['phi'].astype(float)))
df['y'] = -df['r'] * np.sin(np.radians(df['phi'].astype(float))) / np.cos(np.radians(df['theta'].astype(float)))
df['z'] = df['r'] * np.cos(np.radians(df['theta'].astype(float))) * np.cos(np.radians(df['phi'].astype(float)))
df['r_check'] = (df['x']**2 + df['y']**2 + df['z']**2)**0.5

print(df['r_check'].unique())
# データフレームを表示
df.tail()



```
keisan2

```ruby:title.rb

import pandas as pd
import numpy as np

# DataFrameの作成
df = pd.DataFrame(columns=['r', 'theta', 'phi'])

# r, theta, phiの値を生成するリスト内包表記
data = [{'r': r, 'theta': theta, 'phi': phi} 
        for r in range(4, 5)  # rの範囲は1～10
        for theta in range(-60, 62, 2)
        for phi in range(-60, 62, 2)]

sin_th = np.sin(np.radians(df['theta'].astype(float)))
cos_th = np.cos(np.radians(df['theta'].astype(float)))
sin_ph = np.sin(np.radians(df['phi'].astype(float)))
cos_ph = np.cos(np.radians(df['phi'].astype(float)))

# DataFrameにデータを追加
df = df.append(data, ignore_index=True)

df['x'] = df['r'] * np.sin(np.radians(df['theta'].astype(float))) * np.cos(np.radians(df['phi'].astype(float)))
df['y'] = df['r'] * np.sin(np.radians(df['phi'].astype(float))) * np.cos(np.radians(df['theta'].astype(float)))
df['z'] = df['r'] * ((1-(np.sin(np.radians(df['theta'].astype(float)))**2)*(np.cos(np.radians(df['phi'].astype(float)))**2)-(np.sin(np.radians(df['phi'].astype(float)))**2)*(np.cos(np.radians(df['theta'].astype(float)))**2))**0.5)
df['r_check'] = (df['x']**2 + df['y']**2 + df['z']**2)**0.5

print(df['r_check'].unique())
# データフレームを表示
df.tail()

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 半球のパラメータ
r = 4  # 球の半径
phi, theta = np.mgrid[0:np.pi/2:100j, 0:2*np.pi:100j]  # phiとthetaの範囲を設定

# 極座標から直交座標に変換
x = r * np.sin(phi) * np.cos(theta)
y = r * np.sin(phi) * np.sin(theta)
z = r * np.cos(phi)

# プロット
fig = plt.figure(figsize=(16.0, 12.0))
ax = fig.add_subplot(111, projection='3d')

ax.scatter(df['x'], df['y'], df['z'], alpha=0.2)
# 半球をプロット
ax.plot_surface(x, y, z, alpha=0.2)

# 軸の範囲とラベル設定
ax.set_xlim([-4, 4])
ax.set_ylim([-4, 4])
ax.set_zlim([0, 8])

# 軸の縮尺を等しくする
ax.set_box_aspect([1,1,1])

ax.tick_params(labelbottom=False, labelleft=False, labelright=False, labeltop=False)

# グラフを表示
plt.show()



import numpy as np
import plotly.graph_objs as go

# 半球のパラメータ
r = 4  # 球の半径
phi, theta = np.mgrid[0:np.pi/2:100j, 0:2*np.pi:100j]  # phiとthetaの範囲を設定

# 極座標から直交座標に変換
x = r * np.sin(phi) * np.cos(theta)
y = r * np.sin(phi) * np.sin(theta)
z = r * np.cos(phi)

# 半球をプロット
surface = go.Surface(x=x, y=y, z=z, opacity=0.2, colorscale=[[0, 'rgb(0,0,255)'], [1, 'rgb(0,0,255)']])

# 点をプロット
scatter = go.Scatter3d(x=df['x'], y=df['y'], z=df['z'],mode='markers', opacity=0.5, marker=dict(color='grey', size=2))

# レイアウトの設定
layout = go.Layout(
    scene=dict(
        xaxis=dict(range=[-4, 4], title='X'),
        yaxis=dict(range=[-4, 4], title='Y'),
        zaxis=dict(range=[0, 8], title='Z'),
        aspectmode='cube'
    )
)

# グラフの描画
fig = go.Figure(data=[surface, scatter], layout=layout)
fig.show()


plt.scatter(df['x'], df['z'],alpha = 0.2)

plt.scatter(df['y'], df['z'],alpha = 0.2)

plt.scatter(df['x'], df['y'],alpha = 0.2)
```
学生のプロジェクトで経験したこと・苦労したこと

# まず学生プロジェクトのリーダーをしてみて思ったこと
## 苦労したこと
- プロジェクトを回そうとした時に各グループの進捗を知ることができていなく状況把握に時間がかかった
- 各グループのリーダを設定をしていなかっため、全員に情報の周知をすることができなかった

---
## 経験したことで身についたこと
- <font color="red">ただ教えることだけでなく当事者本人にも考えさせることも大切</font>
&rarr;当事者意識を持たせることで自ずと責任感を持つことができると思う。
- 詳細なところまで指示を出すのではなく、あえて抽象的な指示を出す
&rarr;詳細なところまで指示を出してしまうと指示されたことに対してしかできなくなってしまうため、ゴールは提示するけど、あえて抽象的な指示をすることによって任された人に成長を与えること


-----
### 振り返り
今回初めて自分がリーダとしてプロジェクトを動かしてみましたが、想像以上に人を動かすということは改めて大変だなと感じました。これはITだけではなく様々なことで言えることなんだなと今回で実際にやって感じました。

----
力が欲しいか？…なら

# はじめに
Linuxで作業をしていて、権限が足りなくて先に進めないときが度々ありますね。そんなときは彼のことが頭をよぎることでしょう。そう、``su``コマンドや``sudo``コマンドです。

# suとは
まず``su``コマンドですが、Substitute User、あるいはSwitch Userの略で他のユーザーの権限を借用できます。``su ユーザー名``で指定したユーザーの権限で作業することができますがスイッチするためには指定するユーザーのパスワードを知っていないといけません。

# sudoとは
そして``sudo``はSuperman Doの略。ではなくSuperuser Doの略です。root権限で実行することができますが、こちらで要求されるパスワードはrootのではなく自分のパスワードです。

# suかsudoか
``su``も``sudo``も自分以外のユーザーの権限を利用できる点は同じですが、セキュリティの面では``sudo``の利用が推奨されます。

# さいごに
``sudo su -``でrootにスイッチして作業するのも権限の面では楽ですが、必要な時だけroot権限で実行しログも残る``sudo``コマンドの使い方を習得するとよりセキュリティリスクを抑えて作業できるエンジニアになれますね。そう、約半世紀ずっーーーーーと引きこもりで地球から一歩も出ていない石ころでも。

``sudo``コマンドについて詳しく知りたいときは

https://linuc.org/study/column/4047/
チケットを切ることで感じた恩恵

１、ブランチ一覧が見やすい
チケットを切っていないとどのような背景があり、何を実現したいのか把握するのに
時間がかかってしまい非効率です。

しかし、チケットで管理しているとそれを一目見て理解できる。

２、自分が何をしたいか整理しやすい
シーケンス図やユースケース図があるともっとコードを書きやすい

- まずチケットを切る
- ブランチを切る
例：チケット番号-prefix-機能
110-add-login-function

- プルリクを出す
チケット番号：タイトル
これはマストではないですが、個人的に導入してみて良かったと思う方法です。

３、後からドキュメントを作成しやすい
ドキュメントの際にチケットに書かれている内容を使いまわせるので
容易にドキュメントを作成できる。

4、　タスクが属人化しづらい
タスクの属人化は永遠のテーマだと思いますが、詳細に書かれていると
レビュー側もレビューしやすいですし、属人化も避けられる。
備忘録 vue template #

## Vue.jsにおけるtemplateタグの#とは？
### 概要
``` vue:.vue
<template #header>
</template>

<template #form>
</template>
```
`<template>`タグ内に、存在する`#`タグの使用方法

### 結論
- `v-slot`の略記法が`#`に当たる

##### v-slotとは？
- 親コンポーネント側から、子コンポーネントのテンプレートの一部を差し込む機能

##### 使用方法
子コンポーネントの一部分に`slot`を差し込む
```vue:Sample.vue
<script setup>
</script>

<template>
 <p>あなたの名前は<slot name="test">鈴木</slot>です。</p> 
</template>
```
親コンポーネント側で、子コンポーネントのタグ内で差し込みたい名前付きスロットを指定する。
```vue:Main.vue
<script setup>
import Sample from "@/Components/Sample.vue";
</script>

<template>
 <Sample v-slot:test>
  清水
 </Sample> 
</template>
```
親コンポーネントで指定した文字に置き換わっていることが確認できる。
```html:output
あなたの名前は清水です。
```

### 参考
https://future-architect.github.io/articles/20200428/
初心者がボットを作る（Copilot Studio→PowerAutomate→Claude API）

# はじめに
最近PowerPlatformを勉強し始めたまとっちです。

この前、Copilot Studio（旧Virtual Agents）デビューしたのですが、PowerAutomateとの連携のところでハマってしまって、解決に時間が掛かったので、備忘録として残します。

## この記事の対象者
- Copilot Studio（旧Virtual Agents）からPowerAutomateに値を渡したい人

## 背景
PowerPlatformのコミュニティで話を聞いてたら、Claude APIのカスタムコネクタの分かりやすい記事があるのを知って、「おもしろそうなコトができそう…」と思って写経しました。

https://sasami-axis.hatenablog.com/entry/2024/03/10/123210

Claude APIのカスタムコネクタ自体はこの記事通りにやれば簡単に出来たのですが、これをチャットボットで動かしたいって思って、Copilot Studioに初挑戦しました。

:::note info
この記事を作ったと同時に、ささみさんがハイレベルな記事👇を公開してましたｗ
- 玄人で本気のボットを作りたい人　→　ささみさんの記事を見てね
- 初心者で簡単な設定練習したい人　→　この記事を見てね
:::
https://sasami-axis.hatenablog.com/entry/2024/04/07/205945

# 作ったシステム
## システムの流れ
① Copilot Studioでユーザーがメッセージを入力する
② Copilot StudioがPowerAutomateを呼び出す
③ PowerAutomateがClaude APIを呼び出して回答をもらってCopilot Studioに返す
④ Copilot Studioがもらった回答をメッセージとして返信する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/1cf7048f-e5c8-65ef-c6a8-30d0c5516e88.png)

## 詳細設定
下記を順に説明していきます。
- Claude APIのカスタムコネクタ作成
- Copilot Studioでトピック作成（前半）
- PowerAutomateのフロー作成
- Copilot Studioでトピック作成（後半）

### Claude PIのカスタムコネクタ作成
ささみさんが１つ１つの設定を丁寧に書いてるので、そのまま写経すれば完成します。

https://sasami-axis.hatenablog.com/entry/2024/03/10/123210

### Copilot Studioでトピック作成（前半）
トピックを最初から作成します。
全てのメッセージにClaude APIで回答させたいので、トリガーは「メッセージを受信」にして、アクション呼び出しで「フローの作成」を選ぶと、PowerAutomateが開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/64b7f2df-b973-7a36-b05a-6cca9b70a67a.png)

### PowerAutomateのフロー作成
Copilot Studioで受け取ったメッセージをClaude APIカスタムコネクタに入れて、返ってきたメッセージを再びCopilot Studioに返します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/35b49fcf-c396-0b11-eb9a-b8f10ac5f854.png)

:::note info
<b>自分がハマったポイント①</b>
ささみさんの記事を読めば分かるのですが、Claude APIのカスタムコネクタの出力がJSON形式で、body/contentの中は下記の配列になっています。なので、これを取得するために、For eachを使って必要な値を一旦変数に入れてあげる必要があります。
```
[
  {
    "type": "text",
    "text": "日本で一番高い山は富士山です。標高は3,776mです。富士山は静岡県と山梨県にまたがる成層火山で、日本を代表する名山です。幾つもの山小屋や登山道があり、多くの登山客が訪れる人気の高い山です。夏の山開きから9月頃までが登山シーズンとなっています。富士山の雄大な姿は美しく、日本でも有数の観光名所となっています。"
  }
]
```
:::

※2024/4/27追記
下記の記事で配列内が1つだけの場合の値の取り出し方が載っておりました。

https://qiita.com/annap_ms/items/3477843bef55c05dcd02


### Copilot Studioでトピック作成（後半）
PowerAutomateで作ったフローを選択して、ユーザーからのメッセージを入力に入れて、返ってきた回答をCopilot Studioにメッセージとして返信します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/8e7365b1-d8a6-f6d3-2810-1a23e4e585d3.png)

:::note info
<b>自分がハマったポイント②</b>
最初、LastMessage.Textの存在を知らずに、どうやったらユーザーのメッセージを受け取れるか、ずっと迷っておりましたが、公式ドキュメントに載ってました👇
:::

https://learn.microsoft.com/ja-jp/microsoft-copilot-studio/authoring-variables?tabs=webApp

# 実際の動き
最初にお見せしましたが、実際の動きはこんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3713212/3c61f807-4590-e740-d127-f5724e52401a.png)

# おわりに
今回の記事の内容は初歩だと思いますが、僕はハマってしまって、５時間くらい掛かったので、同じようなことで困ってる初心者の方の助けになれば幸いです。
とても簡単なAWSアカウントのMFA設定方法


## ■概要
AWSルートアカウントのMFA設定方法について説明します！
今回はGauth Authenticatorを使ったMFAの方法です。

## ■前準備
前準備として、ChromeウェブストアでGAuth Authenticatorをインストールしておきましょう

## ■設定してみる
ではやっていきます
まずはルートアカウントでログインし、IAMの画面を開きます。

次にトップ画面が以下のようになっていると思うので、「MFAを追加」を押下。

![](https://storage.googleapis.com/zenn-user-upload/629bea2f815a-20230203.png)

「MFAを割り当てる」を押下。

![](https://storage.googleapis.com/zenn-user-upload/1240abaed720-20230203.png)

次はMFAデバイスの選択画面です。
今回は一番上の「認証アプリケーション」を選択しましょう。
名前は「Gauth」にしときました！

![](https://storage.googleapis.com/zenn-user-upload/99cb222aa18a-20230203.png)

赤枠を押下し、シークレットキーを表示させ、コピーしておきましょう。
（シークレットキーは失くさないように！ログイン出来なくなってしまいます。）

![](https://storage.googleapis.com/zenn-user-upload/5fac0cfae3dc-20230203.png)

下記URLより、Gauthの画面を開きます
https://gauth.apps.gbraad.nl/


「add」を押下すると、次の画面に移ります。

![](https://storage.googleapis.com/zenn-user-upload/79c9a619a2f3-20230203.png)

「account name」には任意の分かりやすい名前をいれましょう。
「secret key」には先ほどコピーしたシークレットキーを入力してaddを押下します。

![](https://storage.googleapis.com/zenn-user-upload/e5ce7f6d48c7-20230203.png)

ワンタイムパスワードが表示されたかと思いますので、IAMのMFA設定画面に戻ってパスワードを2回連続で入力、MFAを追加を選択しましょう！

![](https://storage.googleapis.com/zenn-user-upload/be7070c6a0db-20230203.png)

以上で完了です！

## ■ちなみに

gauthに登録した情報はエクスポートする事が可能です！
左上からオプション画面を開くと「setting」とあると思うのでそちらからエクスポートしましょう。
複数アカウントをまとめて管理している方は便利かと思います。

![](https://storage.googleapis.com/zenn-user-upload/9bfc99503633-20230203.png)

## ■備考
シークレットキーさえあれば、デバイスに縛られずMFAを認証できるので、利便性はあると思います！
後はシークレットキーは失くさないように…
RailsアプリをHerokuからDokkuへ。「client intended to send too large body」の対処法

個人開発でRailsアプリをHeroku上にて3年ほど運用してきました。
USリージョンでのサーバーレスポンスの遅さにだんだんと耐えられなくなり、さくらのVPSで日本のサーバーに移行しようと思い立ちました。

私のRailsアプリではRedis経由でSidekiqに投げたジョブファイルの結果を、ActionCable（WebScoket）でクライアントに通知する機能があります。ところがたまたまセットアップしていたUbuntuサーバーはPassenger＋Apacheの組み合わせであり、PassengerのドキュメントによるとActionCableはPassenger＋Apacheでは対応していないとのこと。何人かのユーザーがパッチを当てているものもありましたし、Passenger StandaloneやPassenger＋Nginxに組み替えてもよかったのですが、やはりHerokuでのデプロイの簡便さと比べると、今更Linuxのお世話をするコストが重荷になっていました。

そこで、HerokuっぽいPaaSを自前のUbuntu（またはDebian）サーバーに構築できるオープンソースのDokkuなるものがあるとのこと。
https://dokku.com/docs/getting-started/installation/

なんだかんだで順調に構築でき、Herokuで運用中のアプリをまんまDokkuにコピーしていざテストをしていると、画像アップロード機能で以下のエラーが出ることに気づきました。
```ruby:var/log/nginx/my-app-error.log
client intended to send too large body: 5477041 bytes
```
当該の画像アップロード機能はCarrierwave経由でCloudFlare R2（こちらも以前、Amazon S3に嫌気が差して乗り換えていた）にアップロードする処理だったため、どう考えてもDokku内部のNginxの設定の問題だろうとすぐにわかりました。

ところが、検索してヒットする[こちらのページ](https://stackoverflow.com/questions/46459678/dokku-413-request-entity-too-large/78288181#78288181)のAnswerでは解決せず。

結果、私の使用しているDokku version 0.34.3では、以下のコード一行で解決しました。
```bash:
dokku nginx:set myapp client-max-body-size 50m
```
client_max_body_sizeではなくclient-max-body-sizeでした。
BitgetのUSDTベースの先物情報

エンドポイント
https:/@/api.bitget.com/api/mix/v1/market/tickers?productType=UMCBL

以下、解説
{"code":"00000","msg":"success","requestTime":1712501600755,"data":[{"symbol":"BTCUSDT_UMCBL","last":"69593.4","bestAsk":"69593.5","bestBid":"69593.4","bidSz":"0.011","askSz":"3.051","high24h":"69774.4","low24h":"67863.5","timestamp":"1712501600758","priceChangePercent":"0.02226","baseVolume":"154520.433","quoteVolume":"10657575973.283","usdtVolume":"10657575973.283","openUtc":"68882","chgUtc":"0.01033","indexPrice":"69600.212462","fundingRate":"0.000116","holdingAmount":"84790.222","deliveryStartTime":null,"deliveryTime":null,"deliveryStatus":"normal"}

提供されたデータは、Bitget取引所で取引される"BTCUSDT_UMCBL"という仮想通貨ペアに関するティッカーデータを含んでいます。以下は各フィールドの説明です：

"symbol": 仮想通貨ペアのシンボル。この場合、"BTCUSDT_UMCBL"はBitcoin（BTC）とUSDT（Tether）の間の取引を示します。
"last": 最終取引価格。この場合、69593.4 USDTです。
"bestAsk": 最良の売り注文価格。この場合、69593.5 USDTです。
"bestBid": 最良の買い注文価格。この場合、69593.4 USDTです。
"bidSz": 買い注文のサイズ。この場合、0.011 BTCです。
"askSz": 売り注文のサイズ。この場合、3.051 BTCです。
"high24h": 過去24時間の最高価格。この場合、69774.4 USDTです。
"low24h": 過去24時間の最安価格。この場合、67863.5 USDTです。
"timestamp": データのタイムスタンプ。ミリ秒単位で記録されています。
"priceChangePercent": 直近の価格変動のパーセンテージ。この場合、0.02226です。
"baseVolume": ベース通貨の取引量。この場合、154520.433 BTCです。
"quoteVolume": 報告通貨の取引量。この場合、10657575973.283 USDTです。
"usdtVolume": USDTで表される取引量。この場合、10657575973.283 USDTです。
"openUtc": UTC時間でのオープン価格。この場合、68882 USDTです。
"chgUtc": UTC時間での価格変動。この場合、0.01033 USDTです。
"indexPrice": インデックス価格。この場合、69600.212462 USDTです。
"fundingRate": 資金調達レート。この場合、0.000116です。
"holdingAmount": 保有数量。この場合、84790.222 BTCです。
"deliveryStartTime": 納期の開始時間。この場合、nullです。
"deliveryTime": 納期の時間。この場合、nullです。
"deliveryStatus": 納期の状態。この場合、"normal"です。
【Rust】MongoDBでドキュメントを更新する際のUpdateとReplaceの使い分け

## 概要
MongoDBではドキュメントを更新する際に、ドキュメントの一部分だけを更新する`update`とドキュメントを全て置き換える`replace`の操作が用意されています。Rustの`mongo-rust-driver`では[Modify Documents](https://www.mongodb.com/docs/drivers/rust/current/fundamentals/crud/write-operations/change/)のドキュメントにある通り、両方の操作のメソッドが用意されています。今回はそれを試してみたのでメモ書きです。

## 前提
* 使用したrustcのバージョンは`1.77.0`です。
* 使用したmongo-rust-driverのバージョンは`2.8.2`です。

## 実装サンプル
ドキュメントの一部分だけ更新する`update`の実装は以下のとおりです。

```rust
pub async fn update_sample(
    db: Database,
    sample_update_user: db_model::SampleUsers,
) -> Result<UpdateResult, Error> {
    let collection = db.collection::<db_model::SampleUsers>(db_model::SAMPLE_USERS_COLLECTION);
    # user_idでフィルタリングする
    let filter = doc! { "user_id": sample_update_user.clone().user_id };
    # nameとdescriptionの項目のみを更新する
    let update_set = doc! {"$set": doc! { "name": sample_update_user.name, "description": sample_update_user.description }};
    let update_one_result = collection.update_one(filter, update_set, None).await;
    return update_one_result;
}
```

ドキュメントを置き換えて更新する`replace`の実装は以下のとおりです。


```rust
pub async fn replace_sample(
    db: Database,
    sample_replace_user: db_model::SampleUsers,
) -> Result<UpdateResult, Error> {
    let collection = db.collection::<db_model::SampleUsers>(db_model::SAMPLE_USERS_COLLECTION);
    # user_idでフィルタリングする
    let filter = doc! { "user_id": sample_replace_user.clone().user_id };
    # ドキュメントを置き換えて更新
    let replace_result = collection.replace_one(filter, sample_replace_user, None).await;
    return replace_result;
}
```
【GitHub】プルリクエストのテンプレートを設定する方法

## プルリクエストのテンプレートを作成する
以下のいずれかのファイルをリポジトリに作成します。

- `pull_request_template.md`
- `docs/pull_request_template.md`
- `docs/PULL_REQUEST_TEMPLATE/pull_request_template.md`
- `.github/pull_request_template.md`
- `.github/PULL_REQUEST_TEMPLATE/pull_request_template.md`

```md:.github/pull_request_template.md
## Summary

[Briefly describe the purpose of the pull request and the changes it introduces]

## Changes

[Explain the specific changes or additions made]

## Testing

[Describe how the changes were tested to ensure they work as expected]

## Related Issues (Optional)

[Mention any related issue numbers]

## Notes (Optional)

[Include any additional information or considerations]

```

## commitしてpushする

上記の変更を`commit`して`push`します。

## 参考

https://docs.github.com/ja/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository
MediaMTXを使って簡単RTSPサーバー

https://github.com/bluenviron/mediamtx を使うと、Windowsでも簡単に試験用のRTSPサーバーを立てられる。

https://github.com/bluenviron/mediamtx/releases/

から、最新の、`mediamtx_vX.X.X_windows_amd64.zip` をダウンロード。

展開して`mediamtx.exe`を実行する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38555/0bb7b6a9-16da-7d22-76eb-3dc956f226cd.png)

ブラウザ（Microsoft Edgeか、Google Chrome）で、以下のURLを開く

http://localhost:8889/mystream/publish

video codec を H264 にする（AV1は、VLC Playerで見られないかもしれないので）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38555/0e1c27a3-bdcf-ca54-4cb3-d1b28346c61a.png)

Publishをクリック

VLC Viewer などで、rtsp://localhost:8554/mystream を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38555/a9b4ea1c-1ca8-cffc-c809-177772813ecc.png)
ONVIF の Player を TKinter で作ってみる

https://qiita.com/yu_fujita/items/cc18ee05fdfb0a2bfd5e

の続きで、ONVIFのメソッドを使って、カメラのIPアドレスから、RTSP StreamのURIを取ってきて、表示するPlayerを作りました。
ここでは、[rtsp](https://pypi.org/project/rtsp/)ライブラリを使っていますが、このライブラリは、OpenCVに依存していて、OpenCVが、RTSP Video Streamを開いて、OpenCVのVideoCaptureで取得したイメージを、PILのImageに変換しています。
その後、Pillowの[ImageTK](https://pillow.readthedocs.io/en/stable/reference/ImageTk.html)で、TKInterで表示できる画像に変換し、表示しています。

```
import tkinter as tk
from PIL import Image, ImageTk
import threading
import rtsp
from onvif import ONVIFCamera
import os

SCRIPTDIR = os.path.dirname(os.path.realpath(__file__))

class MainWindow:
    def __init__(self, window, rtsp_url):
        self.window = window
        self.window.geometry('800x500')
        self.window.title('ONVIF Player')
        self.rtsp_url = rtsp_url
        self.interval = 1  # Interval in ms to get the latest frame
        self.client = rtsp.Client(rtsp_server_uri=rtsp_url, verbose=True)
        self.window.protocol("WM_DELETE_WINDOW", self.on_closing_window)
        

        # Create canvas for image
        self.canvas = tk.Canvas(self.window, width=800, height=500)
        self.canvas.grid(row=0, column=0)
        self.canvas.create_rectangle(0, 0, 800, 500, fill="black")
        self.rtsp_image = None


        # Update image on canvas
        self.update_image()

    def on_closing_window(self):
        self.client.close()
        self.window.destroy()

    def update_image(self):
        # Get the latest frame and convert image format
        frame = self.client.read()
        if frame is not None:
            # Update image on canvas
            self.rtsp_image = ImageTk.PhotoImage(frame)
            self.canvas.create_image(0, 0, image=self.rtsp_image, anchor=tk.NW)

        # Repeat every 'interval' ms
        self.window.after(self.interval, self.update_image)

if __name__ == "__main__":
    # To avoid 'No such file: devicemgmt.wsdl', copied wsdl folder from
    #  https://github.com/FalkTannhaeuser/python-onvif-zeep/tree/zeep/wsdl
    mycam = ONVIFCamera('192.168.1.18', 8000, 'admin', 'admin', os.path.join(SCRIPTDIR, 'wsdl'))
    media_service = mycam.create_media_service()
    profile_token = mycam.media.GetProfiles()[0].token
    get_stream_uri = media_service.create_type("GetStreamUri")
    get_stream_uri.ProfileToken = profile_token
    get_stream_uri.StreamSetup =  {'Stream': 'RTP-Unicast', 'Transport': {'Protocol': 'RTSP'}}
    stream_uri = media_service.GetStreamUri(get_stream_uri)
    rtsp_url = stream_uri.Uri
    root = tk.Tk()
    app = MainWindow(root, rtsp_url)
    root.mainloop()
```
sympyで計算したくない時は`evaluate=False`を使う

sympyでは、例えば`sqrt(4)`と書くと$\sqrt{4}$ではなく$2$となる。計算できるところは計算してくれるという意味でありがたいが、場合によってはお節介なときもある。

そういうときは、`evaluate`オプションで評価しないことを選択できる。

オプションを指定しない場合(`evaluate`はデフォルトで`True`)、

```python
from sympy import sqrt

sqrt(4)
```

$2$

となるが、`evaluate=False`を指定することで、

```python
from sympy import sqrt

sqrt(4, evaluate=False)
```

$\sqrt{4}$

となる。`sqrt`に限らず、どの関数でも使えるので、何かの折には使えるかもしれない。
【セキュリティニュース解説】医療情報システムの安全管理に関するガイドライン（第6.0版）

# 医療情報システムの安全管理に関するガイドライン（第6.0版）
サイバーセキュリティのニュース、技術や動向って、わかったようで実はわかってなかったことが多いですよね。
今回は私の専門である「医療セキュリティ」に関連して、令和5年に改定された「医療情報システムの安全管理に関するガイドライン」について解説し、本ガイドラインの意味や対応方法をざっくり理解いただこうと思います。


## 想定読者
* サイバーセキュリティ専門家
* 医療機関にお勤めの方
* 医療情報システムを扱う事業者（ITベンダー）にお勤めの方

業界特化系であるがゆえに、本ガイドラインを初めて知る（名前くらいなら知っている）方が多いと思います。
そのため、
* 「医療情報システムの安全管理に関するガイドライン」の位置づけを知りたい
* 「医療情報システムの安全管理に関するガイドライン」へ対応することで何のメリットがあるのか知りたい
* 「医療情報システムの安全管理に関するガイドライン」へ対応しなければならないけど何をしていいのかさっぱりわからない
* サイバーセキュリティの知見を広げたい
という方向けにもぜひ読んでいただきたいです。


## 概要
![20240406_セキュリティニュースまとめ_医療情報システムの安全管理に関するガイドライン.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3299903/173bc05e-3925-a2d4-796d-4c2f724f5daf.jpeg)

## 結局のところ「医療情報システムの安全管理に関するガイドライン」って何なの？
いやいや、スライドを見たところでわかったつもりになるだけでしょ？
結局のところ、このガイドラインは何なんですか？？何がしたいんですか？？
と思っている方も多いと思います。

「医療情報システムの安全管理に関するガイドライン」とは、
**医療機関と医療情報システムを扱う事業者（ITベンダー）が医療情報システムを扱う際に守らなければいけないルールを定めた安全管理（セキュリティ）に関するガイドライン**
として理解いただけば問題ないです。
そして、
**このままだと法令違反になるから、まずは自医療機関（自事業者）の状況に応じたチェックリストへ対応しておけ**
と危機感を煽ってモチベーションアップしてくれたうえに、立場に応じた実施事項まで明確になっています。


## もうちょっと詳しく説明してよ（泣）

### 本ガイドラインの対象は？（モノ編）
セキュリティやITを専門としている方向けに説明させていただくと、
<dl>
<dt>医療情報：</dt>
<dd>医療に関する患者情報（個人識別情報、既往歴、持病や現症など）を含む情報</dd>
<dt>医療情報システム：</dt>
<dd>医療情報を保存するシステムだけでなく当該情報を扱うすべてのシステム</dd>
</dl>
と定義されています。
<br>
重要な情報、、、そしてシステムの対象範囲が広いですよね。
電子カルテはもちろんのこと、医療機関が利用しているシステムは数多くあります。我々が通院した際にお医者さんや看護師さんが使用する機械やシステムにも、我々の身体に関する情報＝医療情報が含まれているのです。想像いただくと、相当範囲が広いことを実感いただけると思います。
<br>
医療情報を扱うすべてのシステムが本ガイドラインの対象となるわけです。

### 本ガイドラインの対象は？（組織と人編）
ここで、組織と人へ目を向けてみます。
上記で説明した医療システムを扱っているのは、お医者さんや看護師さんといった医療機関の医療従事者を想像すると思います。ただ、もちろんですが医療従事者だけではありません。
近年の医療機関の規模は大きくなりつつあり、自院にIT部門を持つことが多い傾向にあります。そこで、医療機関で使用するシステムを自院開発するケースが多々見られます。自院の細かい仕様に沿ったシステムを自社開発したほうが医療機関にとってはgoodですよね。
あくまで傾向であるので、外部ベンダーと協業してシステムの導入から運用、破棄まで行う医療機関も多いです。
これらの状況を考慮し、本ガイドラインではシステム運用専任の担当者有無によって参照するガイドラインが細かく分けられています（なんとお優しいこと...）。自医療機関の状況に応じて確認すべき箇所が限定されている構成はすごくありがたいですよね。

### 法令違反って怖いんだけどどうすればいいの？
第6.0版の公表に伴い、
本ガイドラインへ対応していない=e-文書法へ対応できていない
つまり、本ガイドラインに対応していないと法令違反になって罰則が科されるおそれありと明言されています。

> 本ガイドラインは、e-文書法が医療分野において執行される際の指針となります。ガ
イドライン自体に罰則はありませんが、ガイドラインに違背した状態は、法令を遵守し
ていないとみなされる可能性があります。
本ガイドラインには、法令により要求されている事項等が列挙されています。したが
って、これに違背することにより、e-文書法に求められる要件を満たすことができてい
ないと認められる場合には、医療に関係する多くの法令等に違反したとみなされ、その
罰則が適用されるおそれがあります。
※「医療情報システムの安全管理に関するガイドライン第6.0版」に関するQ&Aより抜粋

ただ、本ガイドラインの要件を文書から正確に抽出、把握したうえで対応状況を管理することは困難です。そこで、「医療機関におけるサイバーセキュリティ対策チェックリスト」が公表されています。
医療機関用と事業者用とに分けられた構成となっており、それぞれの立場からe-文書法へ対応するために必要な要件がリスト化されているのです。これを満たしていればALL OKということです。
e-文書法違反をチェックする際（医療法に基づく立ち入り検査の際）にも、本チェックリストを提出すれば問題なしです。

## 私見
特に、医療情報システムが扱っているデータは非常に繊細な個人情報（患者の既往歴や持病など）であるため、罰則の有無にかかわらず安全性を担保する必要があります。セキュリティ対応の有無が患者として通院する医療機関を選択するにあたって重要な条件になる（既になっているか？）ことは、容易に想像できます。
私は医療セキュリティ専門家として活動しているため、当該ガイドラインが医療業界へもたらす影響を肌で感じています。医療業界へのサイバー攻撃は年々増加しているにもかかわらず、当該ガイドラインへの準拠対応やセキュリティ体制を構築することができる専門家の数が足りていないです。それらの面でも、医療セキュリティの素養を身に付けることは、無駄にはならないと思います。
個人的にですが、当該ガイドラインへの準拠が厳格化された今、いち早く医療セキュリティの発展・推進に貢献していきたいものですね。

Obrigado :flag_br:


## 参考
* 医療情報システムの安全管理に関するガイドライン　第6.0版（令和5年5月）, 厚生労働省, https://www.mhlw.go.jp/stf/shingi/0000516275_00006.html
* ぼびのX, X, https://twitter.com/secubot5
未経験でエンジニアにジョブチェンジして1週間経ったので振り返りしてみた。

## はじめに
未経験ながらバックエンドエンジニアとしてジョブチェンジしてから1週間経過したので、節目として学んだこと/感じたことの振り返りをしてみました。
稚拙な文章/内容なので「あー懐かしい。こんな学びあったよね」「最初はこんなもんだよね」と温かい目で見ていただけると幸いです。

## 軽く自己紹介
文系学部卒→2021年度に営業職（カスタマーサクセス）として新卒入社→1年目の冬頃にひょんなことからエンジニア領域に興味を持ち始め、独学で勉強進める→2023年6月から本格的に学習を始め、社内試験など諸々なんとか通過→2024年4月からバックエンドエンジニアとして社内ジョブチェンジ🧑‍💻

## 感じたこと1:「分からないことが多すぎてメモが追いつかねぇ…！」
まずは率直に、分からないことが多すぎました。
当たり前田のクラッカー（←古い）なのですが、チームのMTGに参加してる時も、育担と会話してる時も、聞いたこと単語や組織ルールが多いので、脳内が「？🤪？」となりパニックになりがちです。
※余談:GitHubのプルリクで「LGTM！」と書かれていたので、意味をググるとまさか「Looks Good To Me」 = 良いと思います　の略語だったとは…みたいな体験ばっかりです

なので一旦、**後でちゃんと振り返れるように、その瞬間にひたすらnotionに殴り書きのメモ**をしています。

ただ、メモすることが目的ではないので、メモすることに集中しすぎて会話の内容が入ってこないと本末転倒…。ここの「しっかり聞く部分」と「メモを取ること」のバランスが難しいなと痛感してます。



## 学んだこと2:「おんぶにだっこニキにならないよう、自分で考えて動くこと」
どんなタイトルだよ！っていう感じなのですが、**要は「指示待ち人間」とか「自分で考える前になんでもすぐ聞いちゃう」とかは避けよう**ってことです。これはエンジニアだけでなくどの職種、職場にも通ずる不変な大切なことだと思います。まだまだ自分も分からないことだらけで、「次って何やれば良いんだろう…」と思うことが多いのですが、オンボーディング資料が準備されているので、

・読み込んで不明な点を洗い出してみる
・タスクを進めて躓いた時、「何がどう躓いていて、どこに原因がありそうなのか、どこまで調べたのか」を自分なりに仮説立ててみる

とか、未熟ながらも能動的な姿勢で取り組んだ方が自分の成長速度も変わりますし、教える側も教え甲斐があると思います。この点は今後も引き続き意識していきます！


## いまやっていてること
そんなエンジニア赤ちゃんの自分が今やっていることを２つほどご紹介します！

・殴り書きメモを**その日の寝る前に**振り返り、ググる&自分の言葉で言語化して綴る
・notionで単語帳を作り、分からない用語をとりあえずぶち込み、空き時間や週末に調べて、節目ごとに振り返れるようにする
・明日のタスク、どこまでできていたらゴールなのかを前日のうちに設定しておく

営業時代から日々のタスク管理をnotionで管理してたので、それを応用してメモや単語帳としても活用してます。自分の中で大切にしてることとして、「**人間どうせすぐ忘れるし、最初は分からないこと多くて当然なんだから、その分しっかり記憶定着するように振り返りを大切にして、同じミスをするのはなるべく防ごうぜ**」という思考です。
誰かに見せる用ではないので、フォーマットなどは自分が振り返りしやすくすることで、後々「自分がどれくらい成長できたのか、何ができるようになったのか」を可視化することもできますし、今後同じような境遇の方や新卒の子が入ってきた時にもオンボーディング資料として活用できる可能性もあるので、一石二鳥です。


## これからやりたいこと
### まずは技術力をしっかりつけたい

まだエンジニアとして1週間しか経過してないので、ここ半年くらいは毎日死に物狂いでインプット&アウトプットを繰り返していくことになるかもしれませんが、まずはしっかり技術力をつけること（学習し続けること）と、営業時代で経験した顧客対応やドメイン知識を活かして、チームなどの組織全体にどんどん還元していきたいです。この点はまだまだ抽象度が高いので、今後じっくり具体化していきます。

## さいごに
と言った感じでこの1週間で学んだ、感じたことを綴ってみました。当たり前のことしか書いてないですし、具体的な技術の話は一切してないポエムになっているので、自己満足的な観点が多いですが、少しでも誰かの気づきやお役に立てれば幸いです。エンジニアライフ、思いっきり楽しみながら揉まれてきます！笑
※今度はちょっと技術の話も含めて書きたいな〜と思います。
【合格体験記】Oracle Master Bronze DBA 2019(1Z0-085)

# はじめに
2024/04/07にOracle Master Bronzeの試験を受け、無事合格しました。
誰かの参考になればと思い、記させていただきます。

#### 筆者スペック
- インフラ系エンジニア　配属から8か月
- 業務でのDB利用はSQL投げる程度

## 資格について
OracleMaster系の資格は2019から体系が変わったそうです。
こちらのサイトが個人的には参考になりました。
[・ORACLE MASTER 2019新資格体系とは – 18c/19c対応](https://cosol.jp/techdb/2020/02/new_oracle_master_overview_2020/#DBA%E7%B3%BBORACLE_MASTER%E8%B3%87%E6%A0%BC%E9%9A%8E%E5%B1%A4%E3%81%A8%E8%A9%A6%E9%A8%93%E7%A0%94%E4%BF%AE)

### OracleMasterBronzeとは
この試験で勉強できる内容は、Oracle製品のDB管理の概要や、DBとはなんぞやについてです。
DBで何ができるか、というより、DBはどう動いているかについてを知ることができました。
例）
- OracleDBのインストール、構成
- 表がどう構成されるか（表領域、データファイルとか）
- バックグラウンドプロセスやリカバリとか

## 再試験無料期間について
Oracle系の資格って、例年春あたりで再試験無料キャンペーンがあるようです。
- [2024](https://www.pearsonvue.co.jp/Clients/Oracle/Special-Offers/Retake2024.aspx)
- [2023](https://blogs.oracle.com/oraclemaster/post/retake23jp#:~:text=2023%E5%B9%B43%E6%9C%881,%E3%82%92%E5%86%8D%E5%8F%97%E9%A8%93%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)

2024年度は5月末までキャンペーンが有効なので、興味がある方は今のうちに予約しておくとよいです。
昨年度はキャンペーンギリギリにOracle Java Silverを予約しようとしたら、既に予約枠がいっぱいで、再試験無料無しで受ける羽目になりました…

## 勉強方法
ping-tを使いました。
Bronzeは有料コンテンツですが、別試験(LPIC)で利用していたので使うことができました。
問題数は336問。これを1周＋ミスのみ絞って100問程度回しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2088977/f0b9f384-55fe-d0f7-dba8-2d2bd0237349.png)

IPA系の試験勉強でDBの基礎知識はあったので、実務寄りな内容や製品固有っぽい内容で躓きました。
DBについて多少理解のある方はping-tだけで十分だと思います。

## 試験当日
自分は都内のテストセンターで受けました。
自宅での受験もできるらしいですが、卓上の色々を動かしたり、整ってない部屋をカメラ回すのがちょっとアレなので…
試験開始は12:30ですが、手続きがあるので15分前には到着するよう書いています。
自分は電車に乗り遅れ12:15丁度に受付しました。

試験は70問/120分ですが、120分もかかりません。
70問解き終わった段階で、合格は出来そうだと思ったので見直しせずに退出しました。
12:55に退出したので、30分程度で終わったみたいです。

## 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2088977/60f2340b-97e0-a230-81d1-1ab20f20f449.png)
無事合格です。
掛かった日数は2週間。通勤などの空き時間に問題解く程度の勉強量なので、真剣に向き合えば数日で取れそうです。

## 感想
ぶっちゃけて言うと、「今の仕事には役に立たないなぁ」というのが本音です。
仕事でOracle製品も使っているのですが、インストールや構築などの管理は担当していないので、Bronze試験で得た知識はあまり活かせないなという思いです。
とはいえ、中身で何が動いているか知らずにSQL叩き続けるより、なんとなくどう動いているかを理解していた方が安心してDB作業ができるような気がします。
SilverになってようやくSQL関連の話が増えてくるので、この流れで5月末までにSilverを受験しようと思います。

以上！
Bitgetで扱っている現物情報を表にする

仮想通貨取引所「Bitget」の現物情報をエンドポイントから抽出し、表にまとめるコード。

```
import requests
import pandas as pd

url = "https://api.bitget.com/api/spot/v1/market/tickers"

response = requests.get(url)
if response.status_code == 200:
    data = response.json()["data"]
    df = pd.DataFrame(data)

df
```
以下、GPTの解説。


このコードは、BitgetのAPIを使用して市場のティッカーデータを取得し、それをPandasのDataFrameに変換しています。以下はコードの詳細な解説です：

import requestsとimport pandas as pd：requestsライブラリとpandasライブラリをインポートします。requestsはHTTPリクエストを送信するために使用され、pandasはデータ処理のために使用されます。

url = "https:/＠/api.bitget.com/api/spot/v1/market/tickers"：BitgetのAPIのエンドポイントURLを指定します。このエンドポイントは、市場のティッカーデータを提供します。

response = requests.get(url)：指定されたURLに対してGETリクエストを送信します。

if response.status_code == 200:：リクエストが成功したかどうかを確認します。HTTPステータスコードが200の場合は成功です。

data = response.json()["data"]：APIからのレスポンスをJSON形式で取得し、その中の"data"キーによってティッカーデータを取得します。

df = pd.DataFrame(data)：取得したティッカーデータをPandasのDataFrameに変換します。これにより、データを表形式で扱いやすくなります。

df：最終的に処理されたDataFrameを返します。ただし、このコードではdfを表示するコードがないため、DataFrameの内容は表示されません。DataFrameの内容を確認したい場合は、print(df)などのコードを追加してDataFrameを表示する必要があります。



多分不要なコードも入ってると思うけど、ひとまずメモ。
VSCodeのデフォルトターミナルを変更する

# はじめに
VSCodeのデフォルトターミナルを変更する方法を記載します。

# 変更方法
① VSCodeでターミナルを開いて、「+」の横にある「v」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/05e91b09-822f-1323-621a-4129786c6527.png)

② 「Select Defalut Profile」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/3ce4508e-c52c-c2db-2166-beaaadd1a65d.png)

③ VSCodeの上のところで、デフォルトターミナルを選択します。
私は「Git Bash」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/de4af515-8332-226d-b06b-ca8f3eecfe01.png)

④ 新たにターミナルを開いたら、選択したターミナルで開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/277ae454-a76d-6a87-ee14-1a5635a0b97f.png)


※ 「Settings」からデフォルトターミナルの変更も可能です。
「terminal.integrated.defaultProfile.windows」で検索して変更することができます。
(Features → Terminal → Integrated → Default Profile: Windows)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/bf137e80-1ab5-d9c7-a539-80e5ffe0f837.png)
mockkでテストを書くときにこれさえ押さえとけばある程度かける

# 初めに
今回はAndroidのテストコードで使うMockkでテストを書くときにこれ知ってればとりあえず読み書きできるよっていうものを紹介していきます
### 本文
`@Before`
---
これは単純にRespositoryやUseCaseなどの初期化をする部分
```kotlin
@Before
fun hoge() {
   fuga: FugaRepositoy = mockk(relaxed = true)
}
```

`@Test`
---
これがある部分はメイン部分でテストをしたい内容が書いてあります


coEvery
---
coroutine scopeが必要なAPIなどから受け取るデータを作成できます
こうすることで持ってるデータによってしてほしい挙動をしてるかどうかを確認することができます

coVerify
---
coroutine scopeを使ってる部分のデータが正しいかを確認するためにあります

### 最後に
すごく簡略化して書いているので実際に触ってみてもらうのがいいと思いますが、まだ触ったことのない方がコードと並列して読むと理解しやすいと思います
どなたかのお役に立てれば幸いです
Rails7+ReactでHello, World!したらSprockets::Rails::Helper::AssetNotFoundになった

# 目的
Rails7+Reactでwebアプリを作成したいので、環境構築します。

# 今回やること

今回の目標は以下の1つ。
* Rails7+ReactでHello, World!

# 環境
* MacBook Air(M2チップ)
* rails 7
* ruby 3.2

# いざ出陣

### 環境構築

以下のサイトを参考に、JavaScriptバンドラーはesbuildで勧めました。

https://techracho.bpsinc.jp/hachi8833/2022_05_26/118202


### 詰まったところ

手順全部書いているのに、2時間くらいかかりました。
初手で`Sprockets::Rails::Helper::AssetNotFound`と出て調べると、
Rails5では`app/assets/javascripts`の中にあるJavaScriptを自動で読み込むのに対し、
Rails6以降は`app/javascripts`を見ているということを知り、それに翻弄されました。

結論、Hotwireをインストールしていなかった。

エラーに書いてあるし、、
ちゃんと見ろ俺。
```
19:02:12 js.1   | ✘ [ERROR] Could not resolve "@hotwired/turbo-rails
19:02:12 js.1   | 
19:02:12 js.1   |     app/javascript/application.js:2:7:
19:02:12 js.1   |       2 │ import "@hotwired/turbo-rails"
```

普通にインストールしてできました。

```:cmd
npm install @hotwired/turbo-rails
```

![スクリーンショット 2024-04-07 21.58.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/15bb858c-a2a1-2a6a-56ca-56a60371e9e8.png)

# 余談
エラーログは生成AIに見せる前に読みましょう。
ディレクトリ丸ごと差分を確認したい時に俺がやってること

## はじめに
ディレクトリAとディレクトリBの差分を丸ごと確認したいってこと、あると思います。
ファイルの差分であればvscodeの機能で確認することができるのですが（ctrl + shift + P → "compare"で差分チェックできる。）ディレクトリ丸ごととなるとこの方法は使えません。

また、「Compare Folders」という拡張機能で差分を確認することはできるのですが、ひとつひとつディレクトリを開かないといけなかったり、ぱっと見では数がわからなかったりでうーんといった感じでした。

https://marketplace.visualstudio.com/items?itemName=moshfeu.compare-folders

![スクリーンショット 2024-04-07 21.22.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704882/a8d6a763-cf8f-da37-db92-96a49dac1691.png)
（↑このように差分があるファイルはわかるが...）


そこで今回は僕がディレクトリ丸ごと差分をとりたいときにする「変な」方法を書いていきます。

## 要約
vscode上で前回のコミットからの差分が確認できる点に着目してディレクトリの差分を調べる


## 用意するもの
1. vscode
1. git
1. 比較したいディレクトリ（ディレクトリA、ディレクトリBとします）
1. 差分を確認するためだけに作った新規ディレクトリ

## 実践
### ディレクトリAをコミット
1. まずは新規ディレクトリに「ディレクトリA」をコピーします
![スクリーンショット 2024-04-07 21.29.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704882/ce962256-6140-b481-2eef-db4d7d74ed1e.png)

2.git→「リポジトリを初期化する」

![スクリーンショット 2024-04-07 21.30.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704882/a4cceeea-d37c-c657-5b4d-397c3d09d8fe.png)

３.適当にコミットする
![スクリーンショット 2024-04-07 21.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704882/a9a744eb-f7f9-e64f-cb9e-ce286e166d32.png)
Gitをつかっている人であればそろそろ勘付くかもしれません。前回のコミットからの変更があるファイルを一覧で出してくれます。それを利用して...

### ディレクトリBにさしかえ

４.中身を「ディレクトリB」に変える。
![スクリーンショット 2024-04-07 21.36.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704882/2453c548-a8fc-e192-b1b8-6ac4ef081dc5.png)
黄色枠の部分を削除して、ディレクトリBのものに差し替えましょう

5.gitの「変更」を確認する
![スクリーンショット 2024-04-07 21.38.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704882/4118e759-c1d6-3285-30fe-ab8a65a3f7f0.png)


差分のあるファイルが一覧で表示されます。もちろんどこに差分があるのかも確認できます。

## 終わりに
こういう拡張機能あるとおもうんですけどね。僕は見つけられませんでした。
Chrome 拡張機能の作り方

# 概要
Chrome拡張機能の作り方についての備忘録

# 目的
Chatworkの拡張機能を作りたい

# 手順
## 最低限必要なもの

- `manifest.json`
    - 拡張機能の設定ファイル
- `content.js`
    - 実行ファイル

## `manifest.json`の内容

```json
{
  "manifest_version": 3,
  "name": "Chatwork Chrome Extension",
  "version": "1.0",
  "description": "Chatwork Chrome Extension",
  "content_scripts": [
    {
      "matches": ["https://www.chatwork.com/"],
      "js": ["content.js"]
    }
  ]
}
```

### 説明
`manifest_version`: manifestファイルの形式バージョン
`name`: 拡張機能の名前
`content_script`: 特定のページにアクセスした時に実行するjsやcssを指定するところ
`matches`には拡張機能を使用したいサイトのURL
`js`に実行したいファイルを指定する

## `content.js`の内容

```js
window.alert('ようこそChatworkへ！')
```

## 作成した拡張機能の読み込み

### 拡張機能の設定ページに移動する

Chromeのアドレスバーに `chrome://extensions/` を入力する

### プログラムを読み込む

"パッケージ化されていない拡張機能を読み込む"をクリックする

![スクリーンショット 2024-04-07 21.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730996/b0ed383a-2279-5694-df5c-cff4fa55c4c5.png)

先ほど作成した`manifest.json`があるディレクトリを選択する

エラーなどがなく読み込めていることを確認する

![スクリーンショット 2024-04-07 21.37.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730996/ef61c001-d6f4-2f33-5c74-00e20d4c54f1.png)

### 動作確認

`https://www.chatwork.com`にアクセスするとメッセージが表示される

![スクリーンショット 2024-04-07 21.38.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730996/b5a7e304-3eb0-027a-c4b1-5dbdda67267c.png)
IPv6基礎検定に合格したので色々まとめてみた

一般社団法人日本ネットワーク技術者協会が2023年の3月から開始したIVv6基礎検定の受験奨励キャンペーンを偶然知ったので、受験してみた所、無事:cherry_blossom::cherry_blossom:合格:cherry_blossom::cherry_blossom:しました。受験に先立ち情報収集をしましたが、Qiitaへの投稿を含めてまだ情報が少ない様なので、記事を執筆して投稿することにしました。

# IPv6基礎検定とは？
以下公式サイトからの抜粋引用です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/82b983ef-5b58-9a6c-c3a0-31c16172d71e.png)

試験名称：IPv6基礎検定（英名：IPv6 Engineer Qualifying Basic Examination）
対象：初級ネットワークエンジニアとネットワークの運用管理を行う方
※初級ネットワークエンジニアとは：インフラエンジニアとしてネットワークの基礎知識がある方
概要：IPv6の基礎的な知識を問う試験
主教材での想定学習時間：約40時間を想定
設問数：40問
受験時間：60分
合格基準：70％正解
受験期間：通年
受験料金： 7,000円（税抜き）
試験会場：全国350か所のCBT-Solutionsテストセンター

主教材：プロフェッショナルIPv6第二版（出版社：ラムダノート）
価格：税込5,500円

参考教材：小川晃通氏によるIPv6解説動画

出題範囲：主教材から下表の範囲と内容を出題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/1e9aec27-0752-ec75-6f1b-804468f89f66.png)

例題の解説
https://www.youtube.com/watch?v=g59ghsAY7GA&t=5s

筆者はIPv6の知識が必要というよりは、ここ数年苦戦続きのネットワークスペシャリスト(NW試験)の勉強を再開するに当たってのリハビリを兼ねて受験を決心しました。しかし、後述の様にあまりリハビリにはなりませんでした。。。:scream: :scream_cat: 

# 勉強方法
主教材であるプロフェッショナルIPv6第二版を頭から愚直に読むという戦略を最初採用しました。しかし、この書籍はまるでIPv6の仕様書で「RFCxxxに○○が定義されていたが、RFC△△△で新たに□□が追加された。」といった内容が延々と続きます。途中から読むのに疲れてしまい、例題の解説動画を視聴し、NW試験の勉強であまり深く勉強していなかったIPv6の基本的な仕様の部分のみしっかり頭に叩き込み、それ以外はNW試験勉強で習得した知識だけで臨むことにしました。

# 受験してみての感想
試験問題の内容は口外してはいけない規約となっている上に、受験したテストセンターの試験室が蒸し風呂状態で意識が朦朧としていたこともあり、問題の詳細は書けませんが、コンピュータネットワークの基礎基本が分かっている方であれば、IPv6の基本的な仕様や近傍探索について勉強して臨めば十分合格点が取れるレベルの試験問題でした。よって、NW試験のリハビリには全くなりませんでした。。。:scream: :scream_cat: :scream: :scream_cat: :scream: :scream_cat: 

# まとめ
これでまた資格が1つ増えました。同じ主教材を出題範囲としたこの試験の上級試験もそのうちリリースされるらしいですが、正直教材書籍の内容が面白く無いので様子を見ようと思います。Pythonによる自動化試験の方は内容が面白そうなので近々受験を考えています。

# Reference
https://network-engineer.jp/ipv6basic
littlefsをUSBマスストレージクラスで読み出す

Raspberry Pi Picoのオンボードフラッシュメモリの一部をlittlefsでフォーマットし、Pico内部から読み書きしつつ、USB接続した**普通のホストPC**(とても重要)にマウントしてファイルを読み出すサンプルというか概念実証をしました。

組み込みデバイスにとって[littlefs](https://github.com/littlefs-project/littlefs)は電源切断にも耐性があってカッコよくて良いですよね。ですが、普通のPCではサポートされていないファイルシステムなので、「デバイスをUSBメモリのようにPCにマウントしてしてファイルを読み書きしたい」たぐいのユースケースには色々と難があります。「それ、LinuxとFUSEならできるよ」とか言われても困るし。

マイコン側USBマスストレージクラスドライバ上に、littlefsをFAT12に擬態する中間層を設けることで実現できるなーと思いつきで書き始めて。できました。

https://github.com/oyama/pico-littlefs-usb

サンプルでは、PicoのBOOTSELボタンを押した回数を`SENSOR.TXT`に追記しています。

![_DSC0626.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108691/685e46b5-2ca4-c56c-2e8b-c03bcef07b51.jpeg)

マイコン側では`lfs_file_open(..., LFS_O_RDWR|LFS_O_APPEND|LFS_O_CREAT)` して `lfs_file_write()` するだけなので簡単でいいですね。PCに接続するとFAT12を備えたUSBメモリとして認識され、`SENSOR.TXT`を読み出すことができます。

![スクリーンショット 2024-04-07 21.28.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108691/43451ee7-1478-d3fe-d87f-3a67f4a80457.png)

マイコン上ではlittlefsファイルシステムを操作しつつ、ホストPC側からはFATファイルシステムのUSBメモリとして読み出せる。そんな構成ができます。この実装と手法には様々な制限がありますが、他のマイクロコントローラでも同様のアプローチで実現できるはずです。~~くどいようですが、これは概念実証なのでリードオンリーです。~~ (その後リードライト両方をサポートしました)

## 擬態のしかた

FAT12は非常にシンプルなファイルシステムなので、簡単に擬態できます。USBホストがリクエストしたブロックデバイスの位置に応じて、マイクロコントローラーが適切なFAT12ブロックを組み立てて返します。

### ブロック0
静的なFAT12ブートブロックを返します

### ブロック1
擬態したFATテーブルを返します。littlefsのルートディレクトリを検索し、各ファイルのファイルサイズに応じてFATファイルシステム上のストレージ位置の情報を保持するFATテーブルを組み立てて返します。

### ブロック2
擬態したルートディレクトリエントリを返します。littlefsのルートディレクトリを検索し、FATのルートディレクトリブロックを組み立てて返します。

### ブロック3以降
littlefsの対応するファイルブロックを返します。リクエストされたブロックを保持するファイルをFATルートディレクトリエントリで検索し、littlefs上のファイル名とオフセット位置を取得します。littlefsのファイルを開き、オフセット位置のデータを返します。


## 今後について

戯れに書いたので特にないです。

これを書いた時点ではRead onlyでしたが、その後ナゾのやる気スイッチが入りWrite accessもサポートしました。littlefsファイルシステム上のファイルを、普通のPCから作成・読み込み・更新・削除できます。
もっと早くハッカソン出ておけばよかった【初ハッカソン体験談】【Dots to Code】

# はじめに
女性・ノンバイナリー向けハッカソン[Dots to Code](https://dotstocode.studio.site/)に参加しました。ファイナルには進めなかったのですが、初ハッカソンとしていろいろと得られるものが多かったので、まとめました。内容としては、技術面はあまり多くないです。超当たり前みたいなこと書いてあるかもしれませんが、温かく読んでください。
# 参加したきっかけ
ハッカソン出てみたいな、と前から思ってはいたのですが、Web系では素のhtml・css・JavaScriptで作品を作ったことはあるけれど、React等モダンなフレームワークは使ったことがありませんでした。よく「ハッカソンでこんなの作りました！」みたいな投稿を見ては、「自分にはまだ早いかな...」と思い、グズグズしながら時間が過ぎていきました。

お恥ずかしながら、何か作りたいものがすぐに浮かぶタイプでもなく、フレームワークも「いつかできるようになりたい」みたいな呑気なこと言っていました...

そのような感じだったのですが、偶然ツイッター(現X)でこのDots to Codeの募集がTLに流れてきました。応募した決め手としては

- 初心者歓迎
- 個人申し込みでも希望者は運営側でチームを組んでくれる
- ハンズオンが充実していた
- (Pitch Dayは交通費補助ありで東京に行ける)

の4つでした。これならできそうかな？と思い、ついに応募しました。

今回の私の個人的な目標としては、
React、TypeScript、Tailwind CSSなど、これまでちゃんと触ったことがなかった技術を使う、ということを掲げました。

# 出てよかったこと
- **アイデア出しの方法を知ることができたこと**
チームの中に社会人の方がいらっしゃったこともあり、その方が普段使っているアイデア出しのフレームワークを教えていただき、作るものを決めていきました。アイデア出しのやり方は自分にとってノータッチの分野だったので、新鮮でした。
<br>

- **チーム開発を体験できたこと**
全くチーム開発をやったことがなかったのですが、戸惑いながらもやっていくことができました。個人参加者同士で組んでもらった即席チームで、はじめまして！からすべてオンライン、チーム内はDiscordをメインで使ってコミュニケーション取りました。ハッカソン前半はミーティングをほぼ毎日やっていたこともあり、だんだんと打ち解けられ嬉しさがありました。
同じチーム内でチーム開発に慣れていた人がいなかったこともあり、「チーム開発ってこんな感じでいいのかな？」と感じながらの開発だったので、もっと定石みたいなところを勉強していきたいなと思いました。
<br>

- **新しい技術を使う壁が低くなったこと**
私の個人の目標であった「モダンなフレームワークをちょっとでも使えるようにすること」は達成できました。このハッカソンでこれを身に着けてやる！という気持ちで、それに向けて事前にYouTube見たり、公式のチュートリアルをやったり、フロントエンドだけで動く簡単なものを作ったりして慣れていきました。chatGPTを使うことで、慣れる速度は格段に上がったと思います。この一連を経験できたので、新しい技術を使うハードルが少し低くなり、スピードも上がったと思います。やはり作るものが決まったら、なんとしてでも完成させたいものです。ハッカソンは締切があり、作るものも決まるので、その環境が自分にとってよかったと感じました。完成させるためなら！と知らなかったことをいろいろと吸収できたと思います。
<br>

- **オフラインで参加者の皆さんに会えたこと**
ずっとオンラインで行われてきたのですが、Pitch Dayや懇親会では実際にお会いしていろいろな方とお話しできたのが楽しかったです。

# まとめ
- やっぱり情報収集は大事
このハッカソン自体ツイッター(現X)をやっていなかったら得られなかった情報でした
- 一人では作るものが思い浮かばない人におすすめ
作る物も決まるし、制作に締切もあるので、先延ばし癖がある人にはいいと思いました
- 今後何勉強したいか見えてくる
やっぱり初参加だったので力不足と痛感する部分が多かったです。だからこそ、次やりたいことが見えてくると思います。


#### 【結論】
**メリットばかり！もっと早くハッカソン出ておけばよかった...っ！**
昔の自分に、気負わなくていいからサクッと応募しちゃえ～って言ってやりたい...
ハッカソン出ようか迷っている人はちょこっと勇気出してみることをおすすめします！
AndroidStudioのプラグインを使用して要素入力済みのデータを作成する

AndroidStudioのプラグインを使用する事があまりなかったのですが、便利な機能があるので最近調べています。

Jetpack ComposeのPreView表示用やユニットテスト実装にデータをを設定したりすることが多いので便利だと思いました。

# 要素を入力方法

プラグインの入れ方はこちらを参考にしてください。

https://qiita.com/yuta317/items/4599276d5b2e58250364

こちらを使用します

https://plugins.jetbrains.com/plugin/10942-kotlin-fill-class

![スクリーンショット 2024-04-07 20.59.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/343a086f-d1b8-7e2a-bc54-a83c629634f6.png)

こちらをインストールいたします。

# 使用方法

まずは作成したいデータの変数定義をします。
`val user = User()`

![スクリーンショット 2024-04-07 21.09.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/7ec43df3-47a3-21c7-393f-bc547614b87f.png)

`Fill Class constructor`をクリックします。

そうすると
`val user = User(member = false, userId = 0, userName = "")`
このように要素を入れたデータクラスが作成できます。

`Fill Class constructor with dummy values`の場合は適当な数値や文字列など入れてくれます。
Androidの面白そうなライブラリ5選

# はじめに
今まで勉強してきて「面白そう」「いつか触ってみたい」「そのうち役に立つかも」と思った内容でも、タイミングが悪かったり、しっかりと時間をとって理解する、使ってみる段階までいかなかったりすると、ウィンドウに残したまま長く放置してしまいがちです。
そのせいで PCにどんどん負荷がかかってしまうので整理も兼ねてメモがわりに記事にしようと思います。

# スポットライト

https://github.com/TakuSemba/Spotlight


参考記事

https://qiita.com/Mosea/items/ae1589b64b21c33fa8bd


# 縦書き

https://github.com/taizan/vjap

参考記事

https://tomorrowkey-2.hatenadiary.org/entry/20110123/1295747338


# 折りたたみレイアウト

https://github.com/alexvasilkov/FoldableLayout

参考記事

https://learn.microsoft.com/ja-jp/dual-screen/android/api-reference/dualscreen-library/layouts/surfaceduo-layout?tabs=kotlin


# おしゃれなダイアログ

https://github.com/pedant/sweet-alert-dialog


参考記事

https://cybozu.dev/ja/kintone/tips/development/customize/styling/change-message-looks-by-sweetalert/

# チャートグラフ

https://github.com/PhilJay/MPAndroidChart

参考記事

https://akira-watson.com/android/achartengine.html