OmniAICreator/Qiita-1.07M huggingface dataset:
SenseCAP Indicatorに交通情報を表示する

# はじめに

1年ほど前の記事の続きです。
https://qiita.com/fukuebiz/items/de6007c651255dd2458b

SeeedStudio の SenseCAP Indicator D1 は卓上などで情報を表示するために使うデバイスとしてちょうどよいサイズです。

https://www.seeedstudio.com/SenseCAP-Indicator-D1-p-5643.html

https://www.switch-science.com/products/9104

# 道路交通情報について

JARTIC 日本道路交通情報センターのホームページで道路交通情報を見ることができます。
https://www.jartic.or.jp

朝の忙しい時に付近の情報をすぐに見たい場合に、スマホでページを開くのはちょっと面倒なことがあります。コンパクトで卓上に置いても邪魔にならない SenseCAP Indicator D1 に道路交通情報を表示してみます。

# ソース

ソースはこちらをご覧ください
https://github.com/fukuen/SenseCAP-Traffic

# データについて

日本道路交通情報センターのホームページで道路交通情報を参照する場合、様々なデータを読み込んでいますが、今回利用するデータは以下のものに限定しています。

### 1.地図データ

地図データは国土地理院の地理院タイルの形式で配信されます。
https://maps.gsi.go.jp/development/siyou.html

具体的なURL
https://www.jartic.or.jp/d/map/degital/{z}/{x}/{y}.png"

SenseCAP Indicator D1 のディスプレイは480x480pxなので、中心となるタイルの周辺を含めて計9個のタイルを読み込んで表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555397/b78df003-aac4-9693-b18a-5daeb9916a3d.png)

### 2.交通情報

日本道路交通情報センターのホームページでは一般道の他、高速道路、首都高速/都市高速の地図表示があり、交通情報データも複数の形式で提供されています。今回は一般道の地図用のデータを使用します。

交通情報を取得する場合、まず最新の時点を取得します。こちらでyyyyMMddhhmm形式でいつ時点の情報かを取得します。
https://www.jartic.or.jp/d/traffic_info/r1/target.json

次にそれぞれの道路の交通情報を取得します。
https://www.jartic.or.jp/d/traffic_info/r1/<時点>/s/301/<道路>.json

道路は以下になります
| 道路 | 地域 |
|-----------|------------|
| A01<br>A02<br>A03<br>...<br>A08<br>A09<br>A11 | 北海道エリア<br>東北エリア<br>関東・甲信エリア<br>...<br>四国エリア<br>九州・沖縄エリア<br>全国 |
| C01<br>C02<br>C03<br>... | 首都高速<br>阪神高速<br>名古屋高速<br>... |
| R01<br>...<br>R13<br>...<br>R47 | 北海道<br>...<br>東京都<br>...<br>沖縄県 |



# 表示例

![E9CA53AB-246A-4458-ADCB-D4A5D2583A29_1_105_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555397/f48e39ee-3f55-03e8-82d0-2c5093818209.jpeg)
ハロプロのロゴでxeyesを作ってみた

# ハロプロでかつて使用されていたロゴ
![GA9qqrOa8AAacll.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1612329/668265cf-40f3-2f59-92c5-1eff34f88528.jpeg)
ハロプロ（ハロー!プロジェクト）は、株式会社アップフロントグループによって運営される女性アイドルグループの総称。
そんなハロプロでかつて使用されていた目玉のロゴ。気が付いたら最近見なくなった。
どうやら2013年から始まった「クールハロー」の流れで消滅してしまったらしい。<br>https://niimurayousei.com/blog20140710.html

ふと、このロゴがxeyesみたいだなぁと思ったのでC#(WPF)で作ってみた。

# xeyes
Linuxユーザには同じみのアプリ。マウスカーソルの方向に目玉が動いてかわいい。

https://ja.wikipedia.org/wiki/Xeyes

> xeyes watches what you do and reports to the Boss.  
xeyes は、あなたの行動を観察しボスに報告する


# 計算式
瞳の位置を計算するアルゴリズムは↓にある通り。
https://note.com/rodz/n/nc8e9f9d1eb13

ただし瞳の動ける最大半径r未満にマウスカーソルがある時はrの値を小さくすることでカーソルへの追従性を良くするようにしている


# マウス移動イベントの補足
昔のPCはよくアプリがフリーズしてしまうのでxeyesでOSが生きていることを確認していたらしい（本当か？）

なのでマウス移動イベント（ハードウェア割り込み）をトリガーとして描画を更新した方が良い気がする。（自己満足）

しかし、クライアント領域外のマウス移動イベントを補足するのが思いのほか面倒。OSからマウス移動メッセージ(WM_MOUSEMOVE)がクライアント領域外だとそもそもやってこない。

回避策として他のプロセスにも送られるウィンドウメッセージを補足するグローバルフック（SetWindowsHookEx）を利用すれば可能らしい。ただ、他のアプリケーションに影響してしまいそうな気がする。一応↓のコードを参考にしても動くがVisualStudioでブレークを張るとマウスの挙動がおかしくなる。
https://stackoverflow.com/questions/11607133/global-mouse-event-handler

サンプルコードでは愚直にマウスカーソル位置をポーリングしている。
こんな単純なアプリなのに学ぶことが多い。。。

# デモ
![Animationss.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1612329/764e63b3-7135-14c7-82c7-0d2c71303842.gif)


# サンプルコード
https://github.com/t-imanani/helloEyes
Error: Objects are not valid as a React child の解決方法

# はじめに
Reactの勉強をしているときに、オブジェクトをmapで表示しようとした際にエラーがでました。
初歩的な部分ですが、解決策をまとめておきたいと思います。

# 事象
以下のようなコードを実行した際に、mapの中の`{ record }`の部分でエラーが発生しました。
```js
export const App = () =>{
  const records = [
    { name: "山田太郎", age: 13},
    { name: "山田次郎", age: 12},
  ]
  return (
    <>
      { records.map((record) => (
        <div>
          <div>{ record }</div>
        </div>
      ))}
    </>
  )
}
```
**発生したエラー**
```sh
Error: Objects are not valid as a React child (found: object with keys {name, age}).
If you meant to render a collection of children, use an array instead.
```


## 原因
オブジェクト型を表示しようとした際に発生するエラーでした。
Reactではオブジェクト型を直接表示することはできないようです。

## 解決方法

オブジェクト型のプロパティを直接指定する
```js
{ record.name }
```

JSONの文字列に変換する
```js
{ JSON.stringify(record) }
```

# 終わりに
オブジェクト型を扱う際には注意していこうと思います。
JSTQB受験のための『テスト戦略』についてのまとめ

## テスト戦略とは
シラバスに書いてあることを簡略にすると、 **「テスト方法を決めるときの、考え方の指標」** のことです。
開発対象に合ったテスト戦略を選択することで、より効率的にテストを進行することができ、品質の保証を高めることができます。

シラバスに記載してあるテスト戦略は下記の7つです。

## テスト戦略（7）
* **分析的**
　要件やリスクなどの分析によってアプローチを決める。
（例）欠陥が起きるリスクのあるものから優先してテストする
<br>

* **モデルベースドテスト**
　開発対象の重要な特性（機能、非機能特性、内部構造、ビジネスモデル）に焦点を当ててアプローチを決める。詳細を検証するのではなく、包括的に開発対象を捉え、メイン機能を注視する。
 （例）メモ帳アプリ。メモを保存する機能、メモを呼び出す機能などをメインにテストする
<br>

 * **系統的**
 　一般的に故障が高いと予測される条件などを基に、事前にテストケースやテスト条件を決め、体系的にアプローチする。
<br>

* **プロセス準拠**
　業界固有の標準や組織によって課せられるプロセス標準などの外部ルールを基に、テストの一連の活動を行う。
<br>

 * **指導ベース（コンサルテーションベース）**
　外部のステークホルダーや技術専門家からの助言や指導、ガイダンスに基づいてテストを行う。
<br>

 * **リグレッション回避**
　リグレッションが発生しているかどうかの確認を目的とするアプローチ。
 <br>

 * **対処的**
　事前にテスト計画を決めるのではなく、テスト実行時に発生する出来事に対して、対処的にテストを行うアプローチ。
 （例）探索的（経験ベース）のテスト
<br>

 テスト戦略は **複数組み合わせて** 補完的に利用することで、より効果的にテストを進めることができます。

:::note info
上記テスト戦略は、JSTQB Foundation Level のシラバス（Version 2018V3.1.J03）で定められてるものとなります。
:::
 
 ## 後書き
 7つのテスト戦略について、ざっくりとではありますが、知ることができました。実際のテストではそれぞれのテスト戦略を用いて、具体的にどのようにテストしているのか、引き続き勉強していきたいと思います。
命名規則についてのガイド

# 命名規則についてのガイド

## 概要
命名規則は、プログラムコードの可読性と保守性を向上させるための重要な要素です。適切な命名規則を守ることで、他の開発者がコードを理解しやすくなり、バグの発生を防ぐことができます。本記事では、一般的な命名規則とその適用例について解説します。

## 命名規則の種類と言語ごとの使用例

### キャメルケース (Camel Case)
キャメルケースは、単語の区切りを大文字で表し、最初の単語は小文字にする方法です。多くのプログラミング言語で、変数名や関数名に使用されます。

#### 言語と使用例
- **JavaScript**: 変数名、関数名
  - 例: `let userName;`, `function calculateTotalPrice() { ... }`
- **Java**: 変数名、メソッド名
  - 例: `int userAge;`, `void fetchUserData() { ... }`
- **Python**: 変数名、関数名
  - 例: `user_name = "John"`, `def calculate_total_price(): ...`

### パスカルケース (Pascal Case)
パスカルケースは、単語の区切りを大文字で表し、全ての単語を大文字で始める方法です。クラス名やコンストラクタ関数に使用されます。

#### 言語と使用例
- **JavaScript**: クラス名、コンストラクタ関数
  - 例: `class UserAccount { ... }`, `function CreateUserAccount() { ... }`
- **Java**: クラス名
  - 例: `public class ShoppingCart { ... }`
- **C#**: クラス名、メソッド名
  - 例: `public class UserProfile { ... }`, `public void FetchUserData() { ... }`

### スネークケース (Snake Case)
スネークケースは、単語の区切りをアンダースコアで表す方法です。定数やファイル名に使用されます。

#### 言語と使用例
- **Python**: 変数名、関数名
  - 例: `user_name = "John"`, `def calculate_total_price(): ...`
- **C**: 変数名、関数名
  - 例: `int user_age;`, `void calculate_total_price() { ... }`
- **Ruby**: 変数名、メソッド名
  - 例: `user_name = "John"`, `def calculate_total_price ...`

### ケバブケース (Kebab Case)
ケバブケースは、単語の区切りをハイフンで表す方法です。CSSクラス名やHTMLのIDに使用されます。

#### 言語と使用例
- **CSS**: クラス名、ID名
  - 例: `.main-container { ... }`, `#user-profile { ... }`
- **HTML**: ID名
  - 例: `<div id="main-container"> ... </div>`
- **Vue.js**: コンポーネント名
  - 例: `<template> <my-component></my-component> </template>`

## 命名規則の適用例

### 変数名
変数名にはキャメルケースを使用し、意味のある名前を付けます。

#### 良い例
```JavaScript
let userAge;
let totalAmount;
```

#### 悪い例
```JavaScript
let x;
let temp;
```

### 関数名
関数名にはキャメルケースを使用し、関数が何をするのかを明確に示します。

#### 良い例
```JavaScript
function fetchUserData() {
    // 処理内容
}
function calculateDiscount(price) {
    // 処理内容
}
```

#### 悪い例
```JavaScript
function func1() {
    // 処理内容
}
function d() {
    // 処理内容
}
```

### クラス名
クラス名にはパスカルケースを使用し、クラスが何を表すのかを明確に示します。

#### 良い例
```JavaScript
class ShoppingCart {
    // クラス内容
}
class UserProfile {
    // クラス内容
}
```

#### 悪い例
```JavaScript
class cart {
    // クラス内容
}
class profile {
    // クラス内容
}
```

### 定数名
定数名にはスネークケースを使用し、全て大文字で書きます。

#### 良い例
```JavaScript
const MAX_CONNECTIONS = 5;
const API_ENDPOINT = "https://api.example.com";
```

#### 悪い例
```JavaScript
const MaxConnections = 5;
const ApiEndpoint = "https://api.example.com";
```

## まとめ

適切な命名規則を使用することで、コードの可読性と保守性が向上します。キャメルケース、パスカルケース、スネークケース、ケバブケースの違いを理解し、それぞれの用途に応じた命名規則を適用することが重要です。また、意味のある名前を付けることも大切です。チームで統一された命名規則を使用することで、開発効率も向上します。
AtCoder 勉強記録[C++] その40

AtCoderで入茶を目指して勉強しています。
勉強を継続するために投稿を始めました。
もともとアカウントを作成していましたが、今年の4月から本格的に勉強を始めました。
一応自分用に解法を書いていますが雑です、自分で読み返して困ったら修正します。
[私のアカウント](https://atcoder.jp/users/nanami_brother)
[解いた問題](https://kenkoooo.com/atcoder/#/table/nanami_brother)
# 本日解いた問題
本日はAtCoder Beginner Contest 365に参加しました。A,B問題を7分ほどで解くことができて、おそらくこれは今までで一番早いためこの調子で早解きできるよう精進したい。C問題は計算量の減らし方の方針が立たず、解くことができなかった。個人的に計算量を減らすタイプの問題が苦手なので克服したい。
## A - Leap Year
[A - Leap Year](https://atcoder.jp/contests/abc365/tasks/abc365_a)
解答
```c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vec = vector<ll>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

int main() {
  ll y;
  cin >> y;
  ll res = 0;
  if(y%4 != 0) res = 365;
  else if(y%4==0&&y%100!=0) res = 366;
  else if(y%100==0&&y%400!=0) res = 365;
  else if(y%400==0) res = 366;
  cout << res << endl;
}
```
### 解法
問題文の通りに場合分けして出力する。
## B - Second Best
[B - Second Best](https://atcoder.jp/contests/abc365/tasks/abc365_b)
解答
```c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vec = vector<ll>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

int main() {
  ll n;
  cin >> n;
  ll res = 0;
  vector<pair<ll,ll>> a(n);
  rep(i, n) {
    cin >> a[i].first;
    a[i].second = i+1;
  }
  sort(a.rbegin(), a.rend());
  cout << a[1].second << endl;
}
```
### 解法
整数列の要素と要素の番号を入れておく`pair`型配列を用意し、配列を逆順ソートすることで結果が求まる。
## C - Transportation Expenses
[C - Transportation Expenses](https://atcoder.jp/contests/abc365/tasks/abc365_c)
解答
```c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vec = vector<int>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

int main() {
  ll n, m;
  cin >> n >> m;
  vec a(n);
  ll sum = 0;
  rep(i, n) {
    cin >> a[i];
    sum += a[i];
  }
  if(sum <= m) {
    cout << "infinite" << endl;
    exit(0);
  }
  ll res = 0;
  sort(a.begin(), a.end());
  ll left = 0;
  ll right = a[n-1];
  while(left+1 < right){
    int tmp = (left+right) / 2;
    sum = 0;
    for(int i = 0; i < n; i++){
      sum += min(tmp, a[i]);
    }
    if(sum > m) right = tmp;
    else left = tmp;
    res = left;
  }
  cout << res << endl;
}
```
### 解法
二分探索を用いて解いていく。0から`A`の最大値までで二分探索を行うことで`O(NlogN)`で解くことができる。
TechRamen2024っていう旭川の心温まるカンファレンス

# 1. はじめに
今回、Tech Ramen 2024という旭川で開催されたカンファレンスに参加してきました。
## Tech Ramen 2024とは
> 上川地方に技術の知見を惜しみなく注ぐ，技術好きのための円卓会議

https://note.com/tomio2480/n/n24b68c1db6e5?sub_rt=share_pw

旭川は札幌から2時間かかるため、外との交流が難しい人もいる地域という背景があります。そこで、旭川で100名規模のカンファレンスをやるということで今回開催されました、
## 参加経緯
3月に開催されたPHPerKaigi2024で、旭川でカンファレンスやるよーみたいな話を[@tomio2480](https://twitter.com/tomio2480)さんから聞きました。
せっかく旭川に行くなら登壇したいなと思い、プロポーサルを出したら見事採択され、大学の友人2人を誘い参加しました。

https://x.com/kotomin_m/status/1816735078426567151

ちなみにこの時誘った友人はカンファレンス初参加でした。北海道旅行も兼ねて行かないかと誘ったところ快く行く流れになったので、一緒に行くことになりました。
個人的な懸念点として、**懇親会でうまく雰囲気についていけるかな** という不安がありました。

# 2. 新しい発見
## (i) 北海道の夏は涼しい
  21年ぶりの北海道で初の旭川。体感初の夏の北海道は非常に過ごしやすかったです。東京では身体中を覆うような熱のマントが北海道にはなく、汗をかかない4日間でした。
## (ii) 初登壇
  初プロポーサル提出、初採択ということで初めてカンファレンスで登壇しました。内容はGoogle Colabのセッション切れについての解決などをさらっとまとめたものです。
## (iii) 新しい繋がり
  PHP色が強いカンファレンスには参加したことがありましたが、今回はPython関係者が多いカンファレンスに参加したのは初めてでした。Pythonのライブラリバージョンについて登壇されていたヒッキーさんと色々なお話をさせていただきました。自分の登壇も近しい部分はあり、貴重なお話を聞くことができました。また、Pyconに参加してみたらとお声がけいただき、申し込みました。

https://x.com/live_in_2107/status/1817196100891386287

  また、東京のカンファレンスでお見かけした方や一方的にTwitterでフォローさせていただいてる方とお話することができ、カンファレンスでまたお会いできることを楽しみにしています。
## (iv) 初カンファレンスに招待した友人が楽しんでくれた
  詳しくはまた別の記事で書きますが、このTech Ramenにカンファレンス初参加の友人を東京から呼びました。個人的には懇親会大丈夫かなと不安でいっぱいでしたが、楽しかったと言ってもらえました。今後も色々なカンファレンス、勉強会に招待して得られる知見の共有を促進していきたいと思いました。

# 3. 終わりに
最初は、旭川遠いな...と思っていたが、いざこうして色々な方と接して、様々なお話ができ、過去参加したカンファレンスでの繋がりのようなものも感じ取ることができました。旅行費以上の満足感を得ることができました。

**生活と仕事の間にある不思議な熱量を突き詰めたら今日ができる**

旭川に住む人の熱い思いがカンファレンスを通じてひしひしと伝わってきました。この満足感で終わらず、日々の生活や業務、学習に活かし、帰るまでがカンファレンスではなく、終わった後もカンファレンスで行きたいと思います。

また来年も行きたいと思うようなそんな旭川滞在でした‼︎
ABC365をPythonで（A～E）

トヨタ自動車プログラミングコンテスト2024#8（AtCoder Beginner Contest 365）の解答等のまとめ

https://atcoder.jp/contests/abc365



# A問題
https://atcoder.jp/contests/abc365/tasks/abc365_a

問題文の条件分岐をそのまま実装する
ライブラリにこれをする関数がありそうな気がする
```python:A
y = int(input())

ans = 365
if y % 4 == 0 and (y % 400 == 0 or y % 100 != 0):
    ans = 366

print(ans)
```

# B問題
https://atcoder.jp/contests/abc365/tasks/abc365_b

問題文どおりに実装する
```python:B
n = int(input())
a = list(map(int, input().split()))

b = sorted(a)
print(a.index(b[-2]) + 1)
```

# C問題
https://atcoder.jp/contests/abc365/tasks/abc365_c

2分探索
補助金を$x$円にしたとき予算範囲内に収まるか、で２分探索する
```python:C
from bisect import bisect


def check(x):
    ind = bisect(a, x)
    s = acc[ind] + x * (n - ind)
    return s <= m


n, m = map(int, input().split())
a = sorted(map(int, input().split()))
acc = [0]
for a_i in a:
    acc.append(acc[-1] + a_i)

ok, ng = 0, m + 10
while abs(ok - ng) > 1:
    mid = (ok + ng) // 2
    if check(mid):
        ok = mid
    else:
        ng = mid

print(ok if ok <= m else "infinite")
```

# D問題
https://atcoder.jp/contests/abc365/tasks/abc365_d

DP
$dp[i][j] = $$i$回目で$j$を出したときの最大勝利数
として計算する
```python:D
n = int(input())
s = input()

dp = {"R":0, "S":0, "P":0}
win_hand = {"R":"P", "S":"R", "P":"S"}

for s_i in s:
    w = win_hand[s_i]
    new_dp = {"R":0, "S":0, "P":0}
    for old in "RSP":
        for h in "RSP":
            if old == h:
                continue
            if h == w:
                new_dp[h] = max(new_dp[h], dp[old] + 1)
            elif h == s_i:
                new_dp[h] = max(new_dp[h], dp[old])
    dp = new_dp

print(max(dp.values()))
```
# E問題
https://atcoder.jp/contests/abc365/tasks/abc365_e

各ビットごとに考える
答えを増加させるのは
- ビットが立っていないとき
１つ前で立っているものの個数分増える
- ビットが立っているとき
１つ前で立っていなかったものの個数分増える

この考察で以下のように実装した
これだと$A_i$単体がそれぞれ余計に加算されているので差し引いた
```python:E
n = int(input())
a = list(map(int, input().split()))

ans = 0
for ind in range(30):
    o, u = 0, 0
    for a_i in a:
        u += 1
        if a_i >> ind & 1:
            o, u = u, o
        ans += o * (1 << ind)

print(ans - sum(a))
```
Android 開発者オプションが有効か確認する方法

# 開発者オプションが有効か確認する方法

こちらを使用します

https://developer.android.com/reference/android/provider/Settings.Global?_gl=1*swzbfi*_up*MQ..*_ga*MjA4ODE2ODE5OC4xNzIxMTE0MjQ4*_ga_6HH9YJMN9M*MTcyMTExNDI0OC4xLjAuMTcyMTExNDI0OC4wLjAuMA..#DEVELOPMENT_SETTINGS_ENABLED


サンプルコード
```.kt
private fun debugCheck() {
    val isDebugMode = Settings.Global.getInt(contentResolver, DEVELOPMENT_SETTINGS_ENABLED, 0)
    Log.d("開発者モード", isDebugMode.toString())
}
```

# 実行結果
開発者モードON
`開発者モード 1`
開発者モードOFF
`開発者モード 0`
　取得した結果を確認すればデバッグモードがどうなっているか判断できると思います。
Raspberrypi ubuntuにnasをマウントする方法。

## はじめに
Raspberrypiのubuntuにnasをマウントした際の調べたことを備忘録



## 本文
### 設定ファイル追記
fstabに新しいマウントの設定を追記します。
ubuntuで下記のコマンドを実行。
```bat
sudo vi /etc/fstab
```
下記のように追記してください。
```bat
LABEL=writable  /       ext4    defaults        0       1
LABEL=system-boot       /boot/firmware  vfat    defaults        0       1

//{nasのIPアドレス}/{NAS側のパス} /{ubunt側のパス} cifs user,uid=1000,gid=1000,username={ユーザー名},password={パスワード}
↑これを追記します。
```


> **追記の具体例**
>```bat
>//192.168.0.10/naspath /mnt cifs user,uid=1000,gid=1000,username=admin,password=pwd123
>```


### 実行
追記した設定を反映させるコマンドを実行します。
```bash
sudo systemctl daemon-reload
```

その後、マウントを実行します。
```bash
sudo mount -a
```


## 終わりに
毎回mountの方法を忘れては調べを繰り返しているので、これで次回からは無問題。

### 参照
https://forums.raspberrypi.com/viewtopic.php?t=362156

https://haik.oi21.net/index.php?ubuntu1804_fstab_cifs
zod の必須入力をコンポーネント側に反映する

`zod` の `schema` と、入力画面側の必須入力項目の表示を連動させる様な実装方法について思いついたので、その備忘録です。
以下が、実際のサンプルコードです。

```tsx
import { Path } from "react-hook-form";
import * as z from "zod";

const schema = z.object({
  status: z.number().nullable(),
  size: z.number(),
});

// zod オブジェクトを type 化
type FormData = z.infer<typeof schema>;

type InputProps = {
  // FormData のフィールド名（今回の場合だと、'status'か'size'のいずれか）
  fieldName: Path<FormData>;
}

// fieldName が 'size' の場合にのみ「必須入力です」の表示が表示される
const Input = ({ fieldName }: InputProps) => {
  return (<>
    <input type="text" name={fieldName} />
    {!schema.shape[fieldName].isNullable()
      && (<div> 必須入力です </div>)
    }
  </>);
}
```

## 解説
`zod` の`.shape` で、`schema`内から特定のフィールドだけを取得します。
本来の使い方なら、`schema.shape.status`の様な書き方をしますが、`fieldName: Path<FormData>` で `fieldName` が `FormData`内のフィールド名であることを明示できるため、連想配列的に`.shape`を使用する記載の仕方が可能となります。
その上で、`.isNullable()` を使用することで、そのフィールドが `.nullable()`を持っているかを判定しています。
あくまで、`.nullable()`を持っているかを判定しているだけなので、`.nullable()`で必須じゃないことを明示していない場合には、使用できないことになります。
（`.isNullable()`以外で判定する様な仕組みができれば、この仕組みを流用できるかもしれませんね。）
【TypeScript×React】コンポーネントの汎用性を上げる型(初学者向け) 

## はじめに
いつもコンポーネントに切り出すのは同じような記述が２回以上ある場合に行っていました。
リファクタリングしてコードレビューを受ける中で、「buttonタグを使っていて、スタイルが同じで、色だけ変わるようなところは、Buttonコンポーネントにしてもいいのでは」というフィードバックをいただき、buttonタグはほぼすべて色違い、幅違いくらいだったので全buttonタグで使えるコンポーネントを作りました。

# 初めて出会った型
フィードバックいただいた内容や調べる中でナニソレな型にいくつか出会いました。
一晩かけてググっては読み、ググっては読み、時には頭を抱えながら、寝る前布団の中でAIに私の理解に間違いがないか確認しながら、最終的にレビューでLGTMいただける形に作り上げたので私の解釈をまとめていきます！

## ComponentPropsWithRef

下記のように記述するとbuttonタグが持つすべての属性をpropsにすることができる型です。
```ts
ComponentPropsWithRef<"button">
```
今回はrefを許容したかったのでComponentPropsWithRefを使いましたが、許容したくない場合はComponentPropsWithoutRefを使います。
使う属性だけ列挙していかなくてもこれだけでまるっと指定できるので大変便利だと思いました！！

## Omit
特定の属性だけを除去できる型です。
今回はスタイルを統一するためにコンポーネントをつくったので、classNameを渡されては困りますので、classNameを除去しました。

```ts
Omit<ComponentPropsWithRef<"button">, "className">
```

背景色はpropsでvariantを用意して、そちらでclassNameを変えられるようにしています。

レビューでは、「propsにclassNameは別で用意しておいて、propsで受け取ったclassNameに、ここで定義するclassNameを追加する処理にするのが良さそう」とのご指摘をいただきました。
今回はパターン4つでvariantで指定するため、Omitで対応することにしました。
より汎用性を上げて、スタイルも親コンポーネントで自由に操作できるようにしようと考えたらpropsにclassNameを用意しないと不具合生じることがあると教わりました。
本当にコードレビューありがたいです。
厳しく見てほしいとリクエストするくらいコードレビューでスキルアップしようとしています(笑)

## forwardRef
親コンポーネントから子コンポーネントに`ref`を渡すための仕組みです。
refが渡せるとhookformも使えるからこうした方がいいとアドバイスいただきました。

正直refってなに状態でしたが結構初歩的な内容だったみたいで、調べたりAIに聞いたりして私がしっくりきたのが、refとは「DOM要素やクラスコンポーネントのインスタンスにアクセスするための手段」であり、forwardRefを使うことで関数コンポーネントでもrefを受け取れるようになるということでした。

つまり、refを渡せるようにしていなかったら（forwardRefを使わなかったら）子コンポーネントのインスタンスに直接アクセスできないので、例えばフォーカスの設定やアニメーションの制御、フォームバリデーション等を別途状態管理などを行って操作しないといけないということになります。
とにかく子コンポーネントが持っている値に直接アクセスできるから管理が楽になるんだなと解釈しました！！

## 最終的なコンポーネント

```ts:Button.tsx
import { ReactNode, ComponentPropsWithRef, forwardRef } from "react";

type Variant =
  | "outlined"
  | "contained-blu"
  | "contained-gry"
  | "contained-blu500";

interface Props extends Omit<ComponentPropsWithRef<"button">, "className"> {
  variant?: Variant;
  children?: ReactNode;
}

export const Button = forwardRef<HTMLButtonElement, Props>(
  ({ variant, children, ...props }, ref) => {
    const className = () => {
      switch (variant) {
        case "outlined":
          return "border-solid border-2 border-slate-600";
        case "contained-blu":
          return "bg-custom-blue";
        case "contained-gry":
          return "bg-gray-300";
        case "contained-blu500":
          return "bg-blue-500 text-white";
        default:
          return "";
      }
    };
    return (
      <button
        ref={ref}
        {...props}
        className={`w-full h-full rounded-full ${className()}`}
      >
        {children}
      </button>
    );
  }
);

Button.displayName = "Button";
```

ボタン自体のサイズは親コンポーネントで指定します。
色の種類が増えた場合はvariantのパターン追加してswitchのcaseを増やしていこうと思います。
variant渡さずchildrenにImage渡したりするような使い方もしていますが、私の個人開発のプロジェクトではすべてこのButtonコンポーネントに置き換えができました！！

## 所感
TypeScript、難しいと感じるシーンも多くあるのですが、使いこなせたらめちゃくちゃ楽にしてくれる強い味方だなと改めて感じました。
今回buttonで作りましたが、他の要素でも応用効く内容だったので、汎用性の高いコンポーネントどんどん作っていきたいと思いました！！
コードレビューがありがた過ぎます！ちょっとずつレベル上げてくださっているので(多分)、これからもしがみついていきたいと思います！
Flutter で Android のナビゲーションホームボタンと同じようにホーム画面に戻る処理を実装する

# なにこれ

- 戻るボタンを無効化したけど、戻るボタンで色々処理をさせたい時があった
- その時、前画面に戻るだけでなく、最上位の画面なら pop せずにアプリをバックグラウンドに行かせて、ホーム画面に行く処理を実装したいと思った
- 以前書いた戻るボタン無効化の記事は以下

https://qiita.com/su3-hokkaido/items/48f5d8bf8b5a487f691f


# 解決方法
### `move_to_background` パッケージをインストールする

パッケージ公式ガイドはこちら

https://pub.dev/packages/move_to_background

インストールコマンドはこちら
```dart
flutter pub add move_to_background
```

yaml に直接書く場合はこちら（バージョンは後述の公式ページにあるバージョンを参照してください）
```pubspec.yaml
dependencies:
  move_to_background: ^1.0.2
```

### onPopInvoked を実装

戻るボタンがタップされた時に onPopInvoked で判定して、`MoveToBackground.moveTaskToBack()` を実行させるとアプリをバックグラウンドに移動させてデバイスのホーム画面に戻ることができます。

```dart
import 'package:move_to_background/move_to_background.dart';
...
  PopScope(
    canPop: false,
    onPopInvoked: (bool didPop) async {
      if (!didPop) {
        MoveToBackground.moveTaskToBack();
      }
    },
```


# パッケージのリポジトリ

https://github.com/Sayegh7/move_to_background


# おわりに

2024年8月にこの記事書いているのですが、公式ページ見ると3年以上メンテナンスされていない様子…
いつか自作するしかないのかしら。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/75c66205-c54e-c44b-0807-e8fe3b369870.png)
初めての投稿です。

# 決意
実践的なスキルを身につけ、Webエンジニアになる。

# 自己紹介
エンジニア歴１年目の30代です。

職歴としては、
1. エネルギーインフラ業界
2. SES
3. SIer（← 現在）

持っている資格は
* Java Silver SE11
* Java Gold SE11
* LPIC Level 1

です。

その他にも、プログラミングスクールやコミュニティに参加していました。
因みに資格は取ってみたものの、技術力があるかといったら
それはまた別のお話。。。


# きっかけ
プログラミングの学習自体は面白く
勉強することが苦ではないのですが、
どうしてもインプットだけで終わってしまうことが多いです。
それではエンジニアとしての
「**本来の姿**」とは言えないのではないかと、
自問自答していました。
そんな中、アウトプットを積極的に行う環境を提供してくれる場や、
サポートしてくれる方に出会い、
これを機に実践的なスキルを身につける決意をしました。


# 目標
短期：基本的な構文を理解し、簡単なアプリを作成する。
中期：何かしら興味のあるアプリを１つ作成する。
長期：自分で案件を取得し納品する。
paizaランクC「Fizz Buzz」問題を3つのアプローチから解いてみる

今回はpaiza x QiitaのCランク問題「Fizz Buzz」をやってみます。

https://paiza.jp/works/mondai/c_rank_skillcheck_sample/fizz-buzz

ただ解くだけではつまらないので、3つのアプローチで解いていきましょう。
基礎から発展的な方法をご紹介します。

## 問題概要
> 整数 N が入力として与えられます。
1からNまでの整数を1から順に表示してください。

> ただし、表示しようとしている数値が、
・3の倍数かつ5の倍数のときには、"Fizz Buzz"
・3の倍数のときには、"Fizz"
・5の倍数のときには、"Buzz"
を数値の代わりに表示してください。

## No.1 for文を使う
パッと思い浮かんだのは`for`文を使用することです。一番簡単であり、馴染みのある解き方でしょう。

```javascript
for (let i = 1; i <= +lines[0]; i++) {
   if (i % 15 === 0) {
       console.log('Fizz Buzz');
       continue;
   }
   if (i % 5 === 0) {
       console.log('Buzz');
       continue;
   }
   if (i % 3 === 0) {
       console.log('Fizz');
       continue;
   }
   console.log(i);
}
```

## No.2 再帰関数を使う
ちょっと難しくなりますが、再帰関数を使う方法です。
こちらは`for`文を使用することなく解くことが可能です。

```javascript
function fizzBuzz(totalCount, currentCount = 1) {
   if (currentCount > totalCount) return;
   
   let result = null;
   if (currentCount % 15 === 0) {
       result = 'Fizz Buzz';
   } else if (currentCount % 5 === 0) {
       result = 'Buzz';
   } else if (currentCount % 3 === 0) {
       result = 'Fizz';
   } else {
       result = currentCount;
   }
   console.log(result);
   
   fizzBuzz(totalCount, currentCount + 1);
}
fizzBuzz(+lines[0]);
```
実装自体は簡単で、自分の関数内で自分の関数を呼び出しています。
ただし呼ぶ毎に`currentCount`を+1していて、最初の関数呼び出し時に与えた数値(`totalCount`)より大きくなった場合に処理終了しているだけです。

## No.3 ジェネレーターを使用する
これは普段あまり使用しない方法でしょう。
ですがこういった方法もあると知っていれば、いつか役に立つかもしれません。

```javascript
function* generatorFizzBuzz(num) {
    for (let i = 1; i <= num; i++) {
        if (i % 15 === 0) {
            yield 'Fizz Buzz';
            continue;
        }
        if (i % 5 === 0) {
            yield 'Buzz';
            continue;
        }
        if (i % 3 === 0) {
            yield 'Fizz';
            continue;
        }
        yield i;
    }
}
const generator = generatorFizzBuzz(+lines[0]);
for (const result of generator) {
    console.log(result)
}
```

ジェネレーター関数を使用し、出力結果を生成しておきます。
その後`for...of`構文で結果を出力する流れになります。

## ちょいとリファクタリング
条件判定が野暮ったいので、三項演算子で書いてみます。

```javascript
for (let i = 1; i <= +lines[0]; i++) {
    const result =
        i % 15 === 0
            ? 'Fizz Buzz'
            : i % 5 === 0
            ? 'Buzz'
            : i % 3 === 0 
            ? 'Fizz'
            : i
    console.log(result);
}
```

うん、余計に見づらくなってしまった。`if`文でやった方がわかりやすいですね。

## さいごに
どうでしょうか。
FizzBuzzは他の問題と比べて簡単に解けると思います。しかし、簡単だからこそさまざまなアプローチができて楽しめる問題だと考えています。

皆さんも違ったアプローチでチャレンジしてみてください！
【随時更新】よく使うSpringBoot3アノテーションまとめ

## Springアノテーション
- `@Component`
    - Springコンテナに対して、このクラスがコンポーネント（Bean）であることを示し、Beanに登録する
- `@ConfigurationProperties`
    - 外部設定ファイル（例：application.properties）からプロパティを読み込むためのクラスに付与する
- `@Repository`
    - データアクセス層のBeanを示す

## Lombokアノテーション
- `@AllArgsConstructor`
    - すべてのフィールドを引数に取るコンストラクタを生成する
- `@Data`
    - @Getter、@Setter、@RequiredArgsConstructor、@ToString、@EqualsAndHashCodeを一括で適用する
- `@EqualsAndHashCode`
    - equals()とhashCode()メソッドを生成する
    - オプション
        - callSuper（デフォルト：false）
            - スーパークラスのequals()およびhashCode()メソッドを呼び出すかどうかを指定する
            - 継承を利用している場合、このオプションをtrueに設定すると、スーパークラスのフィールドも比較やハッシュ計算に含まれる
- `@Getter`
    - 各フィールドに対するゲッターメソッドを生成する
- `@NoArgsConstructor`
    - 引数なしのデフォルトコンストラクタを生成する
- `@RequiredArgsConstructor`
    - finalフィールド、または@NonNullアノテーション付きのフィールドに対するコンストラクタを生成する
- `@Setter`
    - 各フィールドに対するセッターメソッドを生成する
- `@Value`
    - 不変オブジェクトを生成するために使用する。すべてのフィールドがfinalになり、ゲッターのみが生成される
- `@Slf4j`
    - クラスに対してロガー（Slf4jのロガー）を生成する

## Jacksonアノテーション
- `@JsonIgnoreProperties`
    - 指定したプロパティをシリアライズおよびデシリアライズから除外する
- `@JsonNaming`
    - シリアライズおよびデシリアライズ時のプロパティ名の命名規則について指定する
CloudflareWorkersでLinebotを作成する

## はじめに
CloudflareでLinebotを作成します。Linebotで作成する際におうむ返しのbotを作っていきます。

## 実装コード

```shell:プロジェクト作成
npm create cloudflare@latest
```

```
#:schema node_modules/wrangler/config-schema.json
name = "line-bot"
main = "src/index.ts"
compatibility_date = "2024-07-29"

[vars]
  LINE_ACCESS_TOKEN = "XXXXXXXXXXXXX"
  LINE_CHANNEL_SECRET = "XXXXXXX"
```

```ts:index.ts
import { Hono } from "hono";

interface Env {
	LINE_ACCESS_TOKEN: string;
	LINE_CHANNEL_SECRET: string;
}

const app = new Hono<{ Bindings: Env }>();

app.post("/callback", async (c) => {
	const body = await c.req.json();
	const events = body.events;

	const lineAccessToken = c.env.LINE_ACCESS_TOKEN;

	for (const event of events) {
		if (event.type === "message" && event.message.type === "text") {
			const replyToken = event.replyToken;
			const messageText = event.message.text;
			const replyMessage = {
				replyToken: replyToken,
				messages: [
					{
						type: "text",
						text: messageText,
					},
				],
			};

			await fetch("https://api.line.me/v2/bot/message/reply", {
				method: "POST",
				headers: {
					"Content-Type": "application/json",
					Authorization: `Bearer ${lineAccessToken}`,
				},
				body: JSON.stringify(replyMessage),
			});
		}
	}

	return c.text("ok");
});

export default app;
```
## ローカル環境で確認する
ngrokを使うと便利なので、ngrokでトンネリングし対応していきます。

```shell:
 ngrok http port番号
```
→この状態でlinebotを動かすとうまく動くはずです

あとはデプロイし、サーバでの確認をするだけです！
【セッションレポート】「スケーラビリティと信頼性を追求: Global で 5,500 万ユーザーを抱えるカレンダー シェアアプリのデータベースを Aurora から Cloud Spanner へ移行」に参加しました

# はじめに
本記事はGoogle Cloud Next Tokyo 2024 のDay1(8/1)において Timetree の 金井さん と Gregさん が講演された「スケーラビリティと信頼性を追求: Global で 5,500 万ユーザーを抱えるカレンダー シェアアプリのデータベースを Aurora から Cloud Spanner へ移行」のレポートです。

# 公式セッション紹介
> 当社は Amazon Aurora から Google Cloud Spanner への移行を決断しました。
なぜ移行が必要になったのか、その背景や Spanner を選んだ理由について、そして移行の際に出会った問題や Tips についてお話ししたいと思います。

# 発表資料
- アーカイブ動画は9月に公開されるとのこと(Google Cloud Next Tokyo 2024として)
    - [[TimeTree] Aurora から Spanner への 移行の決断と背景](https://speakerdeck.com/3utama/timetree-aurora-kara-spanner-heno-yi-xing-nojue-duan-tobei-jing) というテーマで発表されていた資料が近しいので一緒にあげておきます

# 概要／おすすめポイント
ビジネスの成長(2018年 → 2024年 : 1TB → 13TB)とともに Amazon Aurora の限界を再認識し、幾つか選択肢を検討した結果 Cloud Spannerを採用した、という発表になります。
ちなみに Amazon Aurora for MySQL の最大値は現時点(2024/8/3)において r6i.32xlarge の128vCPU、ストレージは 128TB となるため相当の規模にはなりますが、将来的にこの辺の最大値が気になる際の検討の参考にもなると思いました。


# セッション内容の紹介

#### Auroraの物理的な限界

課題となったAuroraの限界値は次の三点
1. ストレージ最大値
    - 128TB
1. コネクション数
    - 16,000(スケールアップが必要): 現状で(現時点の最大値の) 80%程度になることもあり、対応が必要
1. ローカルストレージ[^1]
    - [2,560GiB](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Managing.Performance.html#AuroraMySQL.Managing.TempStorage)(スケールアップが必要): オンラインDDLなどで大きく利用され、大きなテーブルの場合にはDDLが実行できない場合も発生している

[^1]: Aurora のローカルストレージは、エラーログ、一般ログ、スロークエリログ、監査ログ、および InnoDB 以外の一時テーブルの保存に使用される領域で、インスタンスクラスの変更によってのみ変更が可能

#### 目標値の再確認

具体的な値は述べられてませんでしたが、以下の項目について組織としては数値や時期を設定されて決断に臨まれた、という背景があると理解しました。
- ユーザ数・セッション数
- 施策(機能拡張や外部連携の予定)
- 海外展開
- 分析用途

#### 移行先の選択

次の3つのデータベースから選定をおこない、フルマネージドで安定している(Googleのプロダクトである)こと、BigQueryやWorkplaceとの連携が行いやすいことからCloud Spannerを選択されたとのことでした。
- Vitess
- PlanetScale
- Cloud Spanner

Cloud Spannerの利用に際しては Google CloudのTAP(Tech Acceleration Program)の利用や、Cloud Spannerのプロダクトチームの協力も得ることができ迅速な課題解決を行えていた、という話もありました。

#### Cloud Spannerの利用と移行に対しての検討

リードアクセスが多くなるためインターリーブを意識したスキーマ設計の実施と、ビット反転シーケンスの利用によってホットスポットを作らない形の設計を改めて実施されたとのことでした。

また、[Spanner-Migration-Tool](https://cloud.google.com/spanner/docs/migration-overview?hl=ja) もプレビューだが活用して移行方式の検討・テストを実施中、特にデータ量が多いので1サイクルで効率的に検証できるよう推進中になるそうです。

# まとめ

現時点では絶賛移行中という話でした。「Aurora から Spanner への 移行の決断と背景」が二カ月前くらいの発表で、その時には移行の話はあまりされていなかったので、そのあたりはだんだん進んでいると受け止めました。

本レポートでは省略していますが、ビジネス側との認識合わせなども発表時には触れられていたので、アーカイブが公開されたら是非確認してみてください。


また、MySQLを利用しているという事で、TiDBなどは候補に入らなかったのか、お聞きしてみたいです。
wsl(Windows Subsystem for Linux)事始め

# はじめに
本資料はmac普段使ってた人がwinで開発環境をちょっと作る為にやった作業のメモですほぼ。

# 目標
- Windowsでモダンな開発環境を作りたい
- ほしいのはとりあえずNode.jsさえあればいったんOK

# 作業

## WSLの初期設定

詳しくはここを参照
https://zenn.dev/dyoshy/articles/04d6bf3822b6ff

WSLのインストール
```
wsl --install
```

WSLのバージョン指定
```
wsl --set-default-version 2
```

Visual Studio Code を入れてVSCode remote Developmentをインストール。
これで、wsl上のUbuntu内のファイルを触ることができる

## Dockerインストール

Dockerはいったん不要な気もしたけど…
VS Code上でWSLを開き、Ctrl+@でターミナルを開いて以下を実行していく

```
$ sudo apt update
$ sudo apt install ca-certificates curl gnupg lsb-release
$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io
```

## Node.jsインストール
手順は一旦node.jsとnpmをapt経由で入れて、n(バージョン管理用ツール）を入れたらいったん入れたnode.jsを削除する。

```
sudo apt install -y nodejs npm
sudo npm install n -g
```

n経由でnode.jsとnpmを入れる
```
sudo n stable
```

apt経由のnode.jsを削除する
```
sudo apt purge -y nodejs
sudo apt autoremove -y
```

## wsl環境のバックアップ
こちらを参考に
https://zenn.dev/zuzuzu/articles/wsl_backup_restore

wslの環境リストアップ
```
wsl -l -v
```

特定ディストリビューションのエクスポート

wsl --export {ディストリビューション名} {exportファイルパス(tar)}
```
wsl --export Ubuntu C:\Users\manji6\Documents\Ubuntu_backup.tar
```

バックアップファイルのインポート

wsl --import {ディストリビューション名} {インストール先パス} {exportしたbackup fileのフルパス}

> インストール先は通常 C:\Users\{UserName}\AppData\Local\Packages 配下に作られる模様。CanonicalGroupLimited.{ディストリビューション名}_{ID}
Streamlitを用いた簡易解析アプリのテンプレート

実験データ(CSV,Txt)などを読み込んで、簡易な解析を行うアプリの要望があります。
そこで、データファイルをアップロード、可視化及び解析、解析グラフの保存の一連の処理を行うStreamlitのひな形を作成しました。テンプレートはこちらにも載せておきます。[Streamlit_template](https://github.com/s-yagyu/Streamlit_template)
また、StremlitをExe化して配布することもできます。その場合はこちらの記事を参考にしていただければと思います。
[StreamlitのEXE化](https://qiita.com/Gyutan/items/c158920f0693fb099e92)

このテンプレートでは、以下の処理を行います。
1. CSVデータファイルをアップロード
2. データを読み込みグラフ表示
3. 表示したグラフをダウンロード

また、このテンプレートを利用した例はこちらになります。
測定ファイルを読み込んで、可視化し、Fittingを行いその結果を表示・ダウンロードするプログラム
- [ACdat-AutoFit](https://github.com/s-yagyu/ACdat-AutoFit)
- [AcViewer](https://github.com/s-yagyu/AcViewer)

#### 環境
このテンプレートを作成した環境は以下の通りです。
- windows 11 pro
- miniconda
- Python 3.10
- modules: streamlit, numpy, pandas, matplotlib
- グラフに日本語表記が必要ならば: japanize_matplotlib

#### コード
```Python
from io import BytesIO
from pathlib import Path
from tempfile import NamedTemporaryFile
import zipfile

import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt


def plot_df(df):
    # ファイルの読み込み、可視化、解析の処理を実装します。
    xx = df.iloc[:, 0].values
    yy = df.iloc[:, 1].values

    fig = plt.figure(figsize=(4,3), tight_layout=True)
    ax = fig.add_subplot(1,1,1)
    ax.set_title('CSV Plot')
    ax.plot(xx,yy,'ro-',label='Data')
    ax.legend()
    ax.grid()
    ax.set_xlabel('x')
    ax.set_ylabel('y')
 
    return fig

def main():
    st.title("CSV file Viewer")
    
    download_zip_file = st.empty()
    uploaded_files = st.file_uploader("CSV files upload", accept_multiple_files=True, type=["csv"])

    figures = []
    if uploaded_files:
        for uploaded_file in uploaded_files:
            with NamedTemporaryFile(delete=False) as f:
                fp = Path(f.name)
                fp.write_bytes(uploaded_file.getvalue())
                
                df_ = pd.read_csv(f'{f.name}')

            fp.unlink()
            
            fig = plot_df(df_)
            st.pyplot(fig)
            figures.append((fig, uploaded_file.name))

        def create_zip():
            in_memory = BytesIO()
            with zipfile.ZipFile(in_memory, 'w', zipfile.ZIP_DEFLATED) as zf:
                for fig, name in figures:
                    img_bytes = BytesIO()
                    fig.savefig(img_bytes, format='png')
                    img_bytes.seek(0)
                    zf.writestr(f"{Path(name).stem}.png", img_bytes.read())
            in_memory.seek(0)
            return in_memory

        zip_buffer = create_zip()
        download_zip_file.download_button(
            label="Download (zip)",
            data=zip_buffer,
            file_name='graphs.zip',
            mime='application/zip' )

if __name__ == "__main__":
    main()
    
    # streamlit run .\CSV_viewer.py

```
実行する場合、ターミナルで`treamlit run .\CSV_viewer.py`と入力してください。
HCD基礎検定【問題例】

## HCD基礎検定とは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2911128/db83b0aa-29f3-6545-679a-ab1ba54ada3c.png)
「人間中心デザイン（HCD）基礎知識体系」をベースとした検定試験制度です。2020年にNPO法人人間中心設計推進機構(HCD-Net）のHCD専門資格認定センター内WGグループが、HCDに関する基礎知識体系をまとめるとともに、制定した検定試験です。(一般財団法人人間中心社会共創機構HPより)

詳しくはググってください()

## 過去問が存在しない
HCD基礎検定は過去問がどこを探してもないので、過去問対策が出来ません💦
一般財団法人人間中心社会共創機構HPでは、3問だけ問題例が記載されています。

<br><br>

**問題例1:
ユーザー調査でわかったことを活用して、ユーザーを代表する仮説的な原型を作る方法のことをなんと呼ぶか、次の中から正しいものを選びなさい。**
- [ ] ペルソナ法
- [ ] ダイアリー法
- [ ] ジャーニーマップ
- [ ] ユーザプロファイリング

**問題例2:
ユーザビリティ評価を実施する際に留意すべきこととして、最も適切なものを次の中から選びなさい。**
- [ ] すでに確立された手法や過去の資料を参考にする
- [ ] 特定の開発メンバーがユーザビリティ評価を行う
- [ ] ユーザビリティ評価の裏付けとなるデータに基づく提案を行う
- [ ] 反対意見が出た場合は、デザイナーの方針を優先する

**問題例3:
人間中心デザインでは、リリース後もユーザーの利用状況の情報を収集して、分析、評価する。その理由を次の中から選びなさい。**
- [ ] 新規ユーザーを獲得するために施策を打つため
- [ ] 利用品質上に問題点がないかを確認し、改善するため
- [ ] ソフトウェアの問題や不具合を見つけ出すため
- [ ] ユーザーの購買行動を分析することにより、経営の安定化を図る必要があるため

<br>

しかし、正直これだけでは十分じゃありません。受験開始日の2週間前から、事前学習システムが利用可能になります。このシステムには「学習動画」が5本と練習問題が5問含まれていますが、検定範囲を完全にカバーすることはできません。
そこで、合格率をさらに高めたい初学者には、HCDに関する書籍を読むことをお勧めします。

## 実際の問題いくつか
今回実際に私が受験した際、何かの参考になればと数問の問題をメモしました。(時間がなかったので本当に数問ですが...)
HPにも特に問題をバラすなとは書いていないのでバラしちゃいますが、さすがに答えは皆さんの勉強のために載せないでおきます。(何か言われたら消しますw)

<br><br>

**問題1:
調査対象者から必要な情報を取得する際、調査内容や実施方法、リスク等、必要な情報を事前に説明し、調査対象本人が理解した上で、選択・同意・拒否することを相互に了解して書面を交わすことをなんと呼ぶか、次の中から選びなさい。**
- [ ] オリエンテーション
- [ ] アカウンタビリティ
- [ ] インフォームドコンセント
- [ ] NDA(秘密保持契約)

**問題2:
人間が外界の刺激情報や対象物から、それが何であるかを解釈する過程のことを何と呼ぶか、最も適したものを次の中から選びなさい。**
- [ ] 感覚
- [ ] 平衡覚
- [ ] 認知
- [ ] 知覚

**問題3:
専門家によるユーザビリティ評価のメリットについて、最も適切なものを次の中から選びなさい。**
- [ ] 開発者の意図を汲んだ上で評価ができるので、評価の改善がしやすい
- [ ] 専門家自身もユーザーではあるので、結果に納得感が得られやすい
- [ ] 評価結果を定量的なデータとして表現できるので、納得感が得られやすい
- [ ] システム全体をスピーディーに網羅的に評価することができる

**問題4:
ユーザーが必要とする情報を探しやすく、使いやすく、理解しやすくするなど、情報を体系的に整理し構築する技術を何と呼ぶか。最も適したものを次の中から選びなさい。**
- [ ] 情報プロタイピング
- [ ] 情報コミュニケーション
- [ ] 情報アーキテクチャ
- [ ] 情報デザイン

**問題5:
情報デザインが果たす役割として、最も適したものを次の中から選びなさい。**
- [ ] ネットワークやデータベース、セキュリティなど、情報システム構築の最適化
- [ ] 審美性のある情報のレイアウトなど、ビジュアル表現の最適化
- [ ] webページに必要となるコンテンツと情報構造設計の効率化
- [ ] 情報の受け手とのコミュニケーションの最適化

**問題6:
回答者に回答の選択肢を提示するタイプのアンケート調査で、最も効果を発揮するのはどれか、次の中から選びなさい。**
- [ ] アイデアの善し悪しや、要求定義の妥当性など、仮説を定量的に検証するのに向いている
- [ ] ユーザーのニーズや利用状況を質的に把握するのに向いている
- [ ] 生活環境を観察できるので、ユーザーの利用状況、コンテキストを深く理解するのに向いている
- [ ] 回答者数が少なくても、ユーザーの全体像を網羅的に把握するのに向いている

**問題7:
人間中心デザインの知識として重要な「文化人類学」の説明として、最も適したものを次の中から選びなさい。**
- [ ] 人間の生活様式全体の具体的なあり方を理解するための研究分野
- [ ] 人類が残した遺跡・遺構など、物質文化の痕跡の研究を通し、人類の活動とその変化を研究する分野
- [ ] 言葉の形式や談話のプロセスから、言語と文化の相関性を探り、言葉を通して文化を読み解こうと試みる研究分野
- [ ] 社会現象の実態や、現象が起こるメカニズムをデータ化し、統計的に分析することで解明を試みる研究分野

**問題8:
ソフトウェアの品質規格では、「利用時の品質」として、ユーザー体験の品質特性を示している。その特性の組み合わせについて、最も適切なものを次の中から選びなさい。**
- [ ] 信頼性、リスク回避性、リスク網羅性
- [ ] 有効性、リスク回避性、信頼性
- [ ] 満足性、リスク回避性、利用状況網羅性
- [ ] 正確性、効率性、リスク回避性

参考までにどうぞ。

## 追記
合格していました。![点数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2911128/674f36d0-bf98-38f1-5d21-6eb9d4d6b7be.png)
PaizaとかAtcoderで必要な入力の処理

## 目的
自分のプログラミング学習のためにPaizaのスキルチェックとかAt coderちょこちょこやってるけど，あまりに期間が空いて毎回入力の処理どうするんだっけ…？ってなるので確認用の生地を作成

## 入力の受け取り方
### input関数の利用
まず，標準入力を受け取るにはinput関数を使わないといけない．
変数= input()とすれば，基本的にstrで標準入力の中身を受け取る
```python:標準入力の受け取り方
x = input()
```
atcodedrやPaizaでは標準入力はいろんなパターンで渡される
そのため，いろいろなinput関数の使い方がわかっていた方がよい

#### 1行に1つの入力を取得
```
x = input()
```
#### 1行に複数の入力を取得
```
input: 1 10 11

s = input().split()
print(s)
# 出力 ['1', '10', '11']
# spliitに値を渡せばそれに応じて標準入力の区切りに応じた対応ができる

# 整数として処理したい場合は…
s = list(map(int, input().split()))
# 出力 [1, 10, 11]
```

#### 複数行に複数の入力を取得
```
input:
1
10
11

s = [input() for i in range(3)]
print(s)
# 出力 ['1', '10', '11']
# 整数として処理したい場合は…
s = [int(input()) for i in range(3)]
print(s)
# 出力[1, 10, 11]
```

#### 入力回数が最初に与えられるパターン
```
input:
N
1
11
111
...
N
N = int(input()) #1行目のNを取得する
s = [input() for i in range(N)] #複数行の数値の入力を取得
print(s) #出力：[1, 10, 11, ... ,N]
```
VMWare 突然画面が小さくなったときの対処法

VMWareを使っていると、突然画面が小さくなった！？なんてことが頻繁に起こります(少なくとも私はそう)

そんなときは、Ctrl+Alt+Enterを押すと画面が最大化して見やすくなります。


試してみてください。
備忘録：EC2の独自ドメイン・SSL化



## お名前.comと紐づけまで詳細な解説
https://dev.classmethod.jp/articles/route53-domain-onamae/


## AレコードとElasticIPを紐づける

レコードを新規作成し、Aレコードを選択する
IPv4のElasticIPを指定する

他はデフォルトでよい

## 動作確認

作成したドメインにアクセスする
アクセスが正しく走れば成功

できていない場合は、NS Look Up あたりから見直してみるといいかも？？
お名前ドットコムは最大72時間かかるとあるが、今回は10秒？shを起動する時間程度しかかからなかったため、自分原因多めで探す必要あり

## ドメインのSSL化

https://dev.classmethod.jp/articles/issuing-certificate-with-acm/

基本はこれに従います
既に、Route53に独自ドメインを登録しているので、
>今回はRoute 53にてドメインを発行しているため、Route 53にレコードを作成すれば証明書を検証できます。ということで、「Route 53でレコードを作成」を押下します。

に関しては気にしなくて大丈夫です
Route53でレコードを作成を参考サイト通りに押すことで正常にレコードが発行されます

## EC2にSSLのドメインを紐づける

https://qiita.com/seshiruff4214/items/d72b56c5c08ba7a455f8#%E3%83%AD%E3%83%BC%E3%83%89%E3%83%90%E3%83%A9%E3%83%B3%E3%82%B5%E3%83%BC%E3%81%AE%E4%BD%9C%E6%88%90

ロードバランサーの設定と、紐づけを行う
基本的にこの設定に従ってよいが、少し詰まった点があるため補足する

### EC2/LoadBalancerに対するアクセスにIP制限をかけたい

:::note warn
フルアクセスでよい場合は、EC2, LoadBalancerともに0.0.0.0/0をHTTP/Sに設定してやればよい
:::

制限をかける場合はセキュリティグループを利用する

EC2側のセキュリティグループでは、LoadBalancerのLocal IPを設定することでLoadBalancerを通過したアクセスのみ許可することができる

LoadBalancerのIPは

`EC2 > ロードバランサー > 作成したロードバランサー`
画面下に存在する `ネットワークマッピング` に存在する


LoadBalancerに関しては、セキュリティーグループのほうで通常通り設定してやることで、外部からのアクセスを拒否することが可能である
【趣味エンジニア】Git 入門② 〜Git / Git hub (リモートレポジトリ編)

##### Git 入門① 〜Git / Git hub (ローカルレポジトリ編)"
に続き、今回はgitHubのリモートリポジトリの操作に関してまとめメモ。

## Githubの事前準備に関して

### 下準備⓪a - Githubへの登録
### 下準備⓪b - gitのユーザーとメールアドレスの登録
```
git config --global user.name "Git Hub username"
git config --global user.email "github@gmail.com"
```
### 下準備⓪c - git hub 上でリポジトリ作成
ローカルのリポジトリと同じ名前にする。

### 下準備⓪d - remote
毎回、githubにアクセスする際に、フルアドレスを宣言するのは面倒なので、originという名前でリポジトリURLにアクセスできるように設定する。
```
git remote add origin リモートリポジトリURL
```
### -------------------ここまでが初期設定

## リモートリポジトリへのプッシュ
```
git push origin ブランチ名
```

## Git Hubからのプル
<img width="550" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/2644bce7-bff8-01bf-5e20-366ef4895dc2.jpeg">

```
git pull origin ブランチ名
git pull //省略できる
```
### Git Hubからのプルと似ているFetch
プルに似ているものとして、Fetchがある。違いはpullがリモートリポジトリから直接ローカルの作業環境にプルしてくれるのに対して、Fetchはローカルリポジトリに取り込まれる。なので、その後、そのローカルリポジトリの情報を作業環境にmergeすることでプルと同じ作業になる。

<img width="550" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/1951b95c-6bb4-27f5-136f-6dd43f50fcec.jpeg">

```
git fetch origin
```

### GitHubへのプルリクエスト
push後に変更内容のレビューを受けることが可能（リクエスト）。
その後、変更内容がapproveされることで変更内容を取り込む(マージ)

## Git / GitHubの工程のまとめ
1. mainを最新に更新
2. ブランチ作成
3. ファイル修正・コミット
4. プッシュ
5. プルリクエスト
6. コードレビュー
7. マージ
【おいしいラズベリーパイのせかい。】配信用ラズベリーパイへの調理手順

# はじめに
この記事では、ラズベリーパイ(Raspberry Pi)でYouTubeLiveする手順をまとめました。

# 材料の用意
- [【おいしいラズベリーパイのせかい。】ラズベリーパイの下準備](https://qiita.com/null8r/items/22f79f3558c5371599f5)で設定したラズベリーパイ(推奨はPi4)
- ウェブカメラ
- YouTubeアカウント

# YouTubeLiveの設定をしよう
[YouTube Studio](https://studio.youtube.com)にアクセスして、右上の「作成」から「ライブ配信を開始」をクリックします。
初めてYouTubeLiveをするアカウントでは、認証があります。24時間かかるので待ちましょう。

ライブ配信ができるようになったら、ライブ配信の方法を「ストリーミングソフトウェア」にします。

すると、↓ のような画面がでます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628341/e91f6da0-104b-1b7c-ec93-5b6a2528b345.png)

:::note info
これでYouTube側での操作は終了！(あとで戻って来るけれど)
:::

# ラズベリーパイにソフトウェアをインストールしよう
ラズベリーパイでは、`ffmpeg`を使ってYouTubeLiveを行います。

**ここからはラズベリーパイで操作します。**
以下のコマンドで`ffmpeg`をインストールします。
```shell
sudo apt-get install ffmpeg
```

# ラズベリーパイにカメラを接続しよう
次にラズベリーパイにウェブカメラを接続します。
以下のコマンドで接続されたカメラを確認します。
```
v4l2-ctl
```
私の場合は、`/dev/video0`がデバイス名でした。

以下のコマンドでは、カメラのコーデック確認ができます。
```shell
v4l2-ctl /dev/video0 --list-formats
```

# 配信を開始してみよう
いよいよライブ配信です。

以下のコマンドを実行してライブ配信を開始しましょう。
```shell
ffmpeg -f v4l2 -i /dev/video0 -s 1280x720 -r 30 -g 150 -c:v h264_v4l2m2m -b:v 2500k -f flv rtmp://a.rtmp.youtube.com/live2/{ ストリームキー }
```
`{ ストリームキー }`は、「YouTubeLiveの設定をしよう」の最後の画面にあります。
`ストリームキー(エンコーダーに貼り付け)`にあるキーをコピーして`{ ストリームキー }`に入れておきます。

実行すると、一番最初にアクセスした[YouTube Studio](studio.youtube.com)にカメラ映像が表示されます。

:::note info
配信できた！
:::

# 最後に
ラズベリーパイでの操作をすべてまとめたシェルスクリプトを書きました。
[konzatsulive-sh](https://github.com/null8r/konzatsulive-sh)の`README.md`通りに操作を行うと、簡単にライブ配信ができます。

# おまけ：`ffmpeg`のコマンド適当解説
あっていないと思います。

```shell
ffmpeg -f v4l2 -i /dev/video0 -s 1280x720 -r 30 -g 150 -c:v h264_v4l2m2m -b:v 2500k -f flv rtmp://a.rtmp.youtube.com/live2/{ ストリームキー }
```

- `-f v4l2`
ファイルフォーマット
- `-i /dev/video0`
入力
- `-s 1280x720`
画質
- `-r 30`
フレームレート
- `-g 150`
キーフレーム間隔(5*fpsが適切らしい？)
- `-c:v h264_v4l2m2m`
出力フォーマット。ラズベリーパイのハードウェアエンコードでh264に変換(Pi4以前のみ)
- `-b:v 2500k`
ビットレート設定
- `-f flv rtmp://~`
配信先
faccessat /usr/bin/fuse-overlayfs: no such file or directory

Fedora 40 にアップデートして Podman を動かそうとしたら `fuse-overlayfs` が無いと言われるようになってしまった。

```console
$ podman info
Error: configure storage: overlay: can't stat program "/usr/bin/fuse-overlayfs": faccessat /usr/bin/fuse-overlayfs: no such file or directory
```

# 解決法

`dnf provides /usr/bin/fuse-overlayfs` で見つかったパッケージをインストール。

```sh
sudo dnf install fuse-overlayfs
```
Clean Code の勉強会整理 - Chapter 1: きれいなコード

現在、韓国でJavaバックエンド開発者として働いています。

将来的には日本で働きたいと思っており、会社で進めている勉強会の内容やSpringFrameworkの技術を日本語でまとめていこうと考えています。

その第一弾として [Clean Code アジャイルソフトウェア達人の技](http://www.amazon.co.jp/Clean-Code-%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%81%94%E4%BA%BA%E3%81%AE%E6%8A%80-Robert-Martin/dp/4048676881) の内容を整理しようと思っていますが、すべての章を扱うのではなく、重要だと思う以下の部分だけをまとめようと思います。

- Chapter 1: きれいなコード (Clean Code)
- Chapter 2: 意味のある名前 (Meaningful Names)
- Chapter 3: 関数 (Functions)
- Chapter 5: フォーマットの整合性 (Formatting)
- Chapter 7: エラーハンドリング (Error Handling)
- Chapter 10: クラス (Classes)

日本ではどうか分かりませんが、韓国では開発者であれば必ず読むべき本の1位に挙げられている書籍ですので、私が整理した内容を共有したいと思います。


# 第1章 クリーンコード


**第1章 クリーンコード**

<aside>
💡 クリーンコードの本を読んだ後に得られる能力

1. 良いコードと悪いコードを区別する能力
2. 良いコードを書く能力
3. 悪いコードを良いコードにリファクタリングする能力

</aside>

第1章の全体的な内容は、多くの優れた開発者の言葉を引用し、クリーンコードの重要性を強調する内容です。（ここから第1章の内容を詳しく見ていきます。）

## 1. コードは存在し続ける！


GPTのようなLLM（大規模言語モデル）が発達する前に、多くの人々が、要求仕様を実現するために開発者がコードを記述するのではなく、要求仕様を満たすプログラムを自動で生成できるようになると言っていました。

そんな馬鹿な！

この本の著者であり、世界中の人々から「コーディングの神」と称される**ロバート・C・マーチン**氏は、それがいかに馬鹿げたことであり、絶対にありえないことだと述べています。その理由は以下の通りです。

1. 要求仕様を詳細に表現するためには、開発者のコードが必要である。
2. コードの生成は単純な反復作業ではなく、創造性と直感を必要とする作業である。

## 2. 悪いコード

開発者たちは最初から良いコードを書いていたのでしょうか？

開発者たちが良いコードに関心を持つようになったきっかけは、長年にわたり、誰かが、または自分自身が書いた悪いコードに苦しんできたからです。

いくつかの会社は**「悪いコードのために最終的に破滅する」**こともあります。そのシナリオは次の通りです。

1. 多くの人々が必要とするサービスを提供し、トラフィックが増え始める。
2. この過程で、コードの品質よりも機能追加や迅速なリリースが優先される。
3. 時間が経つにつれ、コードの複雑さが増し、保守が困難になり、あちこちで障害が発生し、最終的には手が付けられないレベルに達する。

私たち全員が、自分が書いた汚いコードを見つめながら、

- 本当に！
- 後で！
- 本当に直すから!!

と誓った経験があるでしょう。しかし、**「その後」は決して訪れません。**

## 3. 悪いコードによる代償


悪いコードは開発のスピードを大きく落とします。プロジェクトの初期段階では非常に速く進行していたチームも、1〜2年後には亀のように遅くなることがよくあります。

悪いコードが積み重なるほど、チームの生産性は低下し、ついにはゼロに近づいてしまいます。（写真を参照）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852151/800ceb41-eed0-dce2-ed4f-e9b7fb356808.png)


### 3.1 偉大な革命の夢

`ついに再設計が行われる。`

このような汚いコードではもう仕事ができないと感じ、管理層に再設計を要求します。管理層は再設計にリソースを投入することに乗り気ではありませんが、生産性が底をついている事実を否定することはできません。

ついに再設計のためのタイガーチームが編成され、誰もがこのチームに参加したいと考えます。

今度こそ、最初から美しいコードを書けるチャンスだからです。

しかし、最も有能で賢い人々だけがそのチャンスを得ることができます。残りの人々は引き続き汚いコードをメンテナンスしなければなりません。

タイガーチームは既存のシステム機能をすべて提供する新しいシステムを立ち上げるだけでなく、その間に既存のシステムに加えられる変更もすべて追いかけなければなりません。

この話に共感できるのであれば、最初から時間をかけてきれいなコードを作る努力が、コストを削減する方法であるだけでなく、プロとして生き残るための唯一の方法であることを認めるでしょう。

## 4. まとめ



開発者としての経験とこれまでの話を通じて、悪いコードが作業速度を遅くするという事実を理解できたと思います。

それでもなお、多くのプログラマーが締め切りに間に合わせるために悪いコードを大量に生産するしかないと感じています。しかし、真のプロフェッショナルは、むしろ乱雑な状態が原因でスピードが直ちに遅くなり、締め切りを逃すことを知っています。

> **「最も速く進む唯一の方法は、常にコードをできるだけきれいに保つ習慣をつけることです。」**
【趣味エンジニア】Git 入門① 〜Git / Git hub (ローカルレポジトリ編)

エンジニアには不可欠な存在であるGitらしいので、とりあえずGit/GitHubで自分のコードを保存しておきたいので、まずは、Gitの基礎、基礎概念をまとめメモ。

## Gitのメリット
 ❶　作成しているプロジェクトのバージョン管理
 ❷　保存しているバージョンへすぐに戻すことが可能
 ❸　チーム開発
 ❹　OSS（オープンソースソフトウェア）への参加

## Gitの仕組み
 Git/GitHubはGitHubのようなサーバーに保存するスペース(リポジトリ)と自分のpc上にあるスペース(ローカルリポジトリ)がある。今回はまず、そのローカル側の基本操作からやる。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/02fc29b0-9af9-1d75-a2ca-dbfa654c9bd1.jpeg">

## ローカル基本操作① - 初期化
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/6d8c43d0-a493-de7d-e70f-8a59dee6e9d9.jpeg">

最初にローカルのリポジトリを作成。
```
git init .
```

## ローカル基本操作② - 記録
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/9de22188-282e-837a-0a36-c7ed3b089fb2.jpeg">

ローカル環境において、３つのプロセスがあります。
ワークツリー（作業環境）
→ステージ（複数ファイルの一部をCommitしたい際の一時的な保存場所）
→変更記録する場所

ステージ ... a, b, cファイルがあり、a, b, cそれぞれを分けて、commitしたいとき、aをaddしてコミット、bをaddしてコミット、cをaddしてコミットすることができる。

まず、ワークツリーからステージへのアップロード
```
git add . 
//.の部分にファイル名が入るが.とすることで全変更ファイルをステージに上げます。
```
続いて、ステージからローカルリポジトリへのコミット
```
git commit -m "メッセージ"
//ローカルリポジトリへ変更をコミットする際に、コメントを付与することも可能。
```
## ローカル基本操作③ - 状況の確認
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/01f2fab7-8c38-5acd-fb56-4aaa7d83e566.jpeg">

まずは、
```
git diff //リポジトリとワークツリーの差分を確認できる
git diff --staged //リポジトリとステージの差分チェック
git status //変更ファイルを確認
```
主に、　コミット前の確認などに使う。

## ローカル基本操作④ - 履歴の確認
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/fdfbfba1-9d77-17ba-317a-a2379b99fd25.jpeg">

ローカルリポジトリの変更履歴の確認
```
git log
```

## ローカル基本操作⑤ - 元に戻す
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/f0889763-cb37-eac2-2efb-25ed21329a46.jpeg">

```
git restore ファイル名 
//ワークツリーの変更を取り消す

git restore --staged ファイル名
//ステージにあげた変更をワークツリーに戻す。
```

## ローカル基本操作⑥ - ブランチ
チームで開発を進める上で、一つのファイルを複数人で編集を進める。それぞれの編集するタスクをgitに登録して、分岐（ブランチ）させて開発を進めることでエンジニア同士が他のエンジニアの編集を上書きすることを避けるためにブランチさせて、後でmergeすることで安全に進めることができる。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/c7fb4a5c-b89d-fa6a-54e0-acbc38e59a20.jpeg">

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628157/71c4f6d4-d4f0-210a-8717-67f263e87066.jpeg">

開発を行う上で、メインの開発ブランチのことをmainという。

### ローカル基本操作⑥a - ブランチの作成

```
git branch ブランチ名
```

ブランチ一覧を表示
```
git branch
git branch -a //-a githubにあるブランチを全て含めて表示
```

### ローカル基本操作⑥b - ブランチの切り替え
```
git switch ブランチ名
git switch -c ブランチ名 //ブランチの作成から切り替えまで一気にできる。
```

### ローカル基本操作⑥c - ブランチの変更をマージする
```
git merge ブランチ名
git merge origin/ブランチ名

//github上(リモートレポジトリ)の内容を自分のローカルにmergeしたい時に使う
//git merge origin ブランチ名もあるので、違いに注意。
```