OmniAICreator/Qiita-1.07M huggingface dataset:
ABC312、D問題の初心者解説

# 0. はじめに

先日行われたABC312、D問題が比較的容易な動的計画法（DP）だったので、樹形図による解法を紹介します。

# 1. 問題と私のコード

https://atcoder.jp/contests/abc312/tasks/abc312_d

以下、ACしたコード。
```python:abc312_d.py
from collections import defaultdict

# 入力
s = list(input())
n = len(s)
mod = 998244353

# 樹形図の初期状態。0文字目について
if s[0]=="?" or s[0]=="(" :
  d=[defaultdict(int)]
  d[-1][1] = 1
# key = 閉じていない"("の個数
# val = 状態数
else:
# 先頭が")"なら計算終了
  print(0)
  exit()

# 樹形図的な状態の展開。1文字目以降
for i in range(1,n):
  d.append(defaultdict(int))
  s0 = s[i]
  for key,val in d[-2].items():
    if s0=="(":
      d[-1][key+1] += val%mod
    elif s0==")":
      if key-1>=0:
        d[-1][key-1] += val%mod
    else:
      d[-1][key+1] += val%mod
      if key-1>=0:
        d[-1][key-1] += val%mod
      
print(d[-1][0]%mod)    
```

# 2. 括弧列について

本問題は括弧列についての問題です。括弧列は頻出問題なので皆さんご存知かもしれませんが、典型的な解法の方針を一応書いておきます。

* "("を$+1$、")"を$-1$と数値で表現する。
* "("と")"が閉じる前提なら、負の値は許されない。

まず、"("を$+1$、")"を$-1$として変数で制御します。そして大部分（全て？）の問題では括弧が閉じる状態について回答を求めていますので、この場合、")"が先に来ることによって変数に負の値が格納されることは除外されるべきです。

括弧が閉じる前提からは文字列の長さは偶数であるなどの、問題を解くための条件が導かれます。

# 3. 解法説明

問題の概要は、「文字列が"("と")"と"?"から作られており、"?"には"("か")"が入る。閉じた括弧列は何通り存在するか？」、という数え上げ問題です。文字を一つずつ追って、最終的に閉じた括弧列になるような状態数を数え上げます。

このような問題は、もちろんDPに習熟した人たちは漸化式とDPテーブルで解くのでしょう。ただナップサック問題と同じように、この問題は樹形図的な状態の発展を追っていくことでシンプルに解くことができます。

樹形図的な発展と言っても小難しいことではなく、「$i-1$文字目までの状態が既知で、$i$文字目が"?"であるなら、"?"を"("とおくか")"とするかによって状態が分岐する」、というものです。動的計画法の問題を樹形図的に考えて辞書で実装することは、皆さんが紙に書いて確認するような状態の発展をプログラムで計算させよう、ということです。

では、先に紹介したコードを説明します。最初の入力部分は無視して、計算の出発点、0文字目による初期状態ですが、これは例え"?"であっても"("を選択するしかありません。なぜなら「閉じた括弧列」という条件から、最初に")"を選択するとそこで計算が終わってしましますので。

樹形図の各段階の状態の実装、この問題で言えば$i$文字目の状態の実装には辞書型を使います。この問題では、"("の個数を示す正の値を辞書のキーとします。そして"("の個数についての状態数を値とします。これは、コード中の説明コメントのとおりです。

次にfor文によって1文字目以降の状態の発展を追います。最初にそのステップでの状態を保存するために、リストに辞書を追加します。この辞書を`defaultdict(int)`と初期化しておくと、余計な記述を省略できます。

そして状態の変化ですが、$i$文字目が"("なら（コード中の`if s0=="(":`）、キーを$+1$して、そのキーの値に元の状態の状態数を加算します。`defaultdict(int)`なら、ここがシンプルに書けます。「998244353」の余りをとることも忘れないように。

次に")"なら（コード中の`elif s0==")":`）、この場合はキーの値が1以上である事を確認しなければなりません。この1以上の値は、")"に対応する"("が1以上存在する事を意味します。もしキーの値が0の時に")"を選択すると、その場合は閉じた括弧列が破綻します。

最後に"?"の場合（コード中の`else:`）、この時は"("も")"も選択できるので、今までの"("の場合と")"の場合を両方記述します。

このような選択を続けると最後の文字による状態変化が終わったときには、キーが正の値、つまり"("が多い状態も存在しますが、同時にキーが0、つまり"("と")"のバランスのとれた閉じた括弧列の状態も存在します。なので最後の答えの表示の際には、キーが0である「`d[-1][0]`」を選択します。

# 4. おわりに

実は今回のコードには、先に書いたような文字数の奇偶の判断が抜けているのですが、`defaultdict(int)`を使った事により、奇数個の文字列では「`d[-1][0]=0`」となりACします。丁寧に書いておくべきですね（汗）。

比較的容易なDP問題を樹形図と辞書で解くことについては、以下の記事を御覧ください。

* [動的計画法の辞書型データ構造による実装](https://qiita.com/solarflare20031028/items/cbaf81a6596e6e9c4fc2)
Xarrayによるモダンなデータ解析(1) 概要編

# はじめに
[Xarray](https://docs.xarray.dev/en/stable/index.html)は大気海洋分野のデータ解析に用いるPythonパッケージのデファクトスタンダートとなっている。しかし、日本語の情報があまりまとまっておらず、誰もが十分に使いこなせているわけではない。

以前「[PythonでnetCDFを読み込む際のnetCDF4とxarrayの違い](https://qiita.com/wm-ytakano/items/5a5962d440887e54e080)」という記事を書いたが、特にnetCDF4-pythonパッケージから移行した人は昔ながらの最低限の機能を使って書いており、最近の便利な機能を知らないことも多いと思われる。

そこで、以下の3部構成で"モダンな"データ解析方法について解説する。
1. 概要編 (本記事)
2. [Dataset編](https://qiita.com/wm-ytakano/items/ddeecf2b43a4d1b200f2)
3. [DataArray編](https://qiita.com/wm-ytakano/items/564476a1e378a3bd7060)

とはいえ、社内メモを手直ししたものなので、丁寧な解説というよりは、知っておくと便利な機能をまとめたものになっている。ポインタとして活用して、適宜公式ドキュメントを参照してほしい。

# インストール
- `$ conda install -c conda-forge xarray netcdf4 h5netcdf cfgrib dask`
    - netcdfの読み込みに`netcdf4`または`h5netcdf`が必要
    - GRIBの読み込みに `cfgrib`が必要
    - 複数ファイルを開く(`xr.open_mfdataset()`)のに`dask`が必要

# インポート
```Python
import xarray as xr
```

# 関連するデータ型
以下で紹介する4つのうち、押さえるべきは`xarray.Dataset`と`xarray.DataArray`の2つである。詳細については本シリーズの第2部と第3部でそれぞれ取扱う。

## `xarray.Dataset`
- （共通の座標軸をもつ）複数の`xarray.DataArray`を含む
- できることの例
    - ファイル入出力（netCDFなど）
    - `pandas.DataFrame`との変換
- `xarray.DataArray`と一部のメソッドが共通する（含まれる`DataArray`に対して同じメソッドを適用するように振る舞う）
```python
# dsという変数名が用いられることが多い
ds
```

## `xarray.DataArray`
- 座標軸情報も含んだ変数（座標軸自身も`DataArray`）
- 基本的にこの形で計算などの操作する
- できることの例
    - 算術演算、平均、内挿など
    - 気象変数の計算 (with MetPy)
    - 描画 (with matplotlib)
- `xarray.Dataset`と一部のメソッドが共通する（単一の`DataArray`を含んだ`Dataset`として振る舞う）

```python
# daという変数名が用いられることが多い
da = ds["sst"] # xarray.DataArray
da = ds.sst # これでもアクセス可能
```

## `xarray.Variable`
- 座標軸情報を含まない変数 
- 属性(attribute)は保持している
- DataArrayを使うことが多く、この形で使うことはあまりない気がする。netcdf4パッケージとの互換性のため存在？
```Python
# 以下どちらでも同じ
var = da.variables # xarray.variable
var = ds.variables["sst"] # xarray.variable
```

## `numpy.ndarray`
- 座標軸情報も属性も含まない、ただのnumpyの配列
- `xarray.DataArray`を引数にとるとうまく動作しないパッケージなどは、`numpy.ndarray`に変換することでうまく動作することがある。

```python
# 以下どちらでも同じ
na = da.values # numpy.ndarray
na = var.values # numpy.ndarray
```
DartPad (Flutter Roadmap DartPad)

## はじめに
Flutterを網羅的に学習するにあたって[Roadmap](https://roadmap.sh/flutter)を使って学習を進めることにしました。

この記事では、Flutterを学習し始める方に向けて、**DartPad**についてまとめています。

RoadmapはFlutterだけでなく、他の言語やスキルのロードマップも提供されており、何から学習して良いか分からないと悩んでいる方にとって有用なサイトになっています。
ぜひ[Roadmap](https://roadmap.sh/)を利用して学習してみてください。

### Roadmapとは

簡潔に言えば、Roadmap.shは学習者にとっての**ガイドブック**であり、**学習の方向性を提供する学習ロードマップサイト**です。

初心者から上級者まで、ステップバイステップでスキルを習得するための情報が提供されています。

学習の進め方が分かりやすく示されているだけでなく、個々の項目に参考資料やリソースへのリンクも提供されているので、学習者は目標を設定し、自分自身のペースで学習を進めることができます。

## DartPad
Flutterロードマップの**DartPad**では以下の2つのサイトが紹介されています。
興味のある方はぜひお読みください。

- DartPad: https://dart.dev/tools/dartpad
- DartPad in Tutorials: https://dart.dev/tools/dartpad/dartpad-best-practices

## DartPadとは
DartPadは、Dartプログラミング言語を**ブラウザ上で**実行・試行することができるオンラインの開発環境です。FlutterのコードやDartの機能を簡単にテストして、即座に結果を確認することができます。開発環境やエディタのセットアップをすることなく、手軽にDartとFlutterの基本的な使い方を学ぶことができるため、初学者にとって理想的なツールになっております。

## DartPadの使い方
DartPadは、以下のURLからアクセスできます：https://dartpad.dev/

左側には**コードエディタ**が表示され、右側には**コードの実行結果**が表示されます。DartPadでは、Flutterパッケージをインポートして、実際にモバイルアプリのコードを書くこともできますが、ここでは基本的なDartの機能に焦点を当ててみましょう。

以下の例では、DartPadを使用して、シンプルな数値計算を行うコードを試してみます。

```dart
void main() {
  // 2つの整数を足して結果を表示する関数
  void addNumbers(int a, int b) {
    int result = a + b;
    print("結果：$result");
  }

  int num1 = 10;
  int num2 = 5;

  addNumbers(num1, num2); // 出力: 結果：15
}
```
左側のエディタにコードを入力したら、右側の出力画面に結果が表示されます。

## DartPadの特徴
- **手軽さと便利さ**: DartPadはブラウザ上で動作するため、追加のソフトウェアのインストールや設定が必要ありません。初学者でも簡単に使い始めることができます。

- **学習に最適**: DartPadは、コードの実行結果を直ちに確認できるため、プログラミングの基本的な概念や構文を理解するのに非常に役立ちます。

- **ソーシャル共有**: DartPadで作成したコードはURLで共有できます。友人や同僚と簡単にコードを共有・相談できるので、学習コミュニティとの交流にも適しています。

## まとめ
DartPadは、FlutterやDartの初学者にとって非常に有用なツールです。ブラウザ上で手軽にDartのコードを試してみたり、学習したりできるため、プログラミングの基本を理解するのに最適な環境です。Flutterの世界に足を踏み入れる前に、ぜひDartPadを活用してみてください！
【UE5】BP_ThirdPersonCharacterのFollowCameraがゲーム中のカメラに使われるまでの流れ

# 最初に
UnrealEngine公式に付属のテンプレートが色々あり、その中の1つにThirdPersonTemplateがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/191e64e3-46a3-a05f-989a-ed4d818bcecc.png)

ThirdPersonTemplateにはBP_ThirdPersonCharacterというThirdPersonのキャラクターが存在しています。
BP_ThirdPersonCharacterにはFollowCameraというUCameraComponentがくっ付いており、それがゲームプレイ時のカメラとして使われています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/684db9f9-9a3b-c33a-6fae-4e29d236c3a0.png)


どのようにしてFollowCameraがゲームプレイ時のカメラとして使われているかがわからなかったので、調査してまとめました。

調査した環境
- Unreal Engine 5.2.1
- ThirdPersonTemplateのC++版

※フローを全部書くと量が膨大になってしまうため、本筋以外は省略しております。

# 初期化：BP_ThirdPersonCharacterをAPlayerCameraManagerのカメラのターゲットに設定する
AThirdPersonGameModeのDefaultPawnClassとして指定されているBP_ThirdPersonCharacterが生成される
↓
BP_ThirdPersonCharacterを引数にAPlayerController::Possess()が呼ばれる
↓
BP_ThirdPersonCharacterを引数にAPlayerController::SetViewTarget()が呼ばれる
↓
APlayerCmaeraManagerのカメラのターゲットにBP_ThirdPersonCharacterが設定される

APlayerCameraManagerとは下記のような働きをするクラスとのことです。

> PlayerCameraManager は特定のプレイヤーのカメラの管理を担います。また、レンダラなどの他のシステムで使用される最終的なビューのプロパティを定義します。PlayerCameraManager は、ワールドを視認するための「バーチャルの眼」として機能します。 最終的なカメラ プロパティを直接計算したり、カメラに影響するその他のオブジェクトやアクタとの間でブレンドすることもできます (CameraActor 間でのブレンド)。

[Unreal Engine のカメラ | Unreal Engine 5.2 ドキュメント](https://docs.unrealengine.com/5.2/ja/cameras-in-unreal-engine/) より引用


# 更新処理：FollowCameraの位置と回転を毎フレーム反映させる
UWorld::Tick()が呼ばれる
↓
APlayerController::UpdateCameraManager()が呼ばれる
↓
APlayerControllerが保持しているAPlayerCameraManagerのUpdateCamera()が呼ばれる
↓
APlayerCameraManager::UpdateViewTarget()が呼ばれる
↓
APlayerCameraManagerのターゲットになっているBP_ThirdPersonCharacterの親クラスであるAActorのCalcCamera()が呼ばれる
↓
AActor::CalcCamera()で**アクターに付いているUCameraComponentを全検索し、IsActive()がtrueである最初に見つかったUCameraComponent(FollowCamera)のGetCameraView()を呼ぶ**。それにより、FollowCameraの位置と回転の値をカメラ側の情報として設定する

UE_5.2\Engine\Source\Runtime\Engine\Private\Actor.cpp よりソースコードを引用
```cpp
TInlineComponentArray<UCameraComponent*> Cameras;
GetComponents(/*out*/ Cameras);

for (UCameraComponent* CameraComponent : Cameras)
{
	if (CameraComponent->IsActive())
	{
		CameraComponent->GetCameraView(DeltaTime, OutResult);
		return;
	}
}
```

# 補足
APlayerCameraManagerのターゲットとなっているアクターにUCameraComponentが付いていない場合はAActor::GetActorEyesViewPoint()という処理が呼ばれ、アクターの位置と回転がカメラの情報として設定されるようです。
PlayerControllerのBPノードのSetViewTargetwithBlendにおいてViewTargetにUCameraComponentが付いていないアクターを渡しても上手く動くのはそのためのようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/0c9d0c2e-1565-e59d-4224-7c8a4615b914.png)
ICLR2023の量子化論文 (2)

# 概要

この記事では、[ICLR02023](https://iclr.cc/)の量子化論文を紹介します。[^1]
[その1](https://qiita.com/kyad/items/8833dfc1b3e0635e8b37)

[^1]: 画像や数式は論文から引用しています。

# Block and Subword-Scaling Floating-Point (BSFP) : An Efficient Non-Uniform Quantization For Low Precision Inference

https://openreview.net/forum?id=VWm4o4l3V9e

- 概要：BSFP. 非一様量子化向け浮動小数点数
- 新規性：2つの浮動小数点数の和で表す形で最適化する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/63af3d2a-9f1c-0087-096d-67474efe86c3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/d0813f0c-1204-e117-8f35-26574c940abc.png)
- キモ：複数の評価指標を見たところ誤差関数はMSEがベスト。
- 評価：ShuffleNet-v2, MobileNetV2, ResNetなどで評価した。


# Winning Both the Accuracy of Floating Point Activation and the Simplicity of Integer Arithmetic

https://openreview.net/forum?id=z92lBy1ehjI

- 概要：FP行列積のINTを使った高速化
- 研究機関：NAVER
- 新規性：FP行列積を高速化するシンプルな方法
- キモ：位を揃えて固定小数点化して、小さい数は有効桁数から切り捨ててINTで計算する。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/2bfe5266-083a-dfe2-b4cd-d868858ab69d.png)

- 評価：ResNet, RegNet, BERT等で試したがタスクの精度劣化しない。


# CrAM: A Compression-Aware Minimizer

https://openreview.net/forum?id=_eTZBs-yedr

- 概要：Cram. 軽量化向けオプティマイザ
- 新規性：AdamやSAMより高精度で、1-shotでgradial pruningと同等に刈れる。
- キモ：SAMで、密なモデルの代わりに疎にしたモデル上で適用する。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/4f0b8974-bb31-7e95-bdad-090b15858517.png)
- 評価：ResNet等で評価した。(DenseではSAMより精度下がる)
【AWA SSA -C03】AWS Solution Architect Associateになぜ合格できたかわからないがとりあえず受かってよかった話

こんにちは。torippy1024です。
先日ですが、AWS Solution Architect Associate試験に合格しました。
自分でもなぜ合格できたのかさっぱりわからないのですが、とりあえず受かったのでこういう人もいるよ、という体験記を載せておきます。

誰のなんの参考になるのかわかりませんが、こういう人もいる程度に読んでいただければと思います。(運が良くて本当に良かった・・・という体験記です。これから受ける人はしっかりと勉強して望んでいただきたいと思います)


# 私のAWSに関する背景知識や経験
- 2015年にAWS Developer Associtateを取得したことがある。(はるか昔、まだ日本出始めたくらい・・・。めっちゃ勉強して落ちて、2回目で合格したのでめっちゃ嬉しかった・・・)それから、資格更新はしていない。
- 実務経験はほぼなし。提案フェーズでアーキテクチャ検討などはしたことがあるが、その際も採用には至らず。設計・構築・運用したことはなし。研修でEC2やRDSやS3を使ったWEBサイトは構築したことがある。ELBとAuto Scalingを使ってWEBサーバーであるEc2を増やすことってやったことあったかなあ・・・もう忘れた。
- 今回、Associate資格の受験費用が半額になるクーポンを取得(https://pages.awscloud.com/jp-traincert-certification-challenge-associate-2023-reg.html )したため、8年ぶりに資格受験を決意。
- 準備期間は2週間(！！)Azure資格も集中したら2週間でとれたし、AWSはもっと情報たくさんあるからいけるやろ！！と勝手に判断。結果としてはなんとかなってしまったのだが、個人的には甘く見すぎたと絶賛反省中。AWS-SAPも取得するかは不明だが、その際はもっと勉強期間を確保しようと強く決意。
- EC2/S3/EBS/RDS/VPC/ELB/SQS/SNS/ECS/Lambda・・・知ってるぜ！概要はな！！細かい仕様は知らないけど。RedShift？Kinesis？Athena？知らない何それ？
- 勉強した資料はudemy講座「【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問） https://www.udemy.com/course/aws-knan/ 」のみ。(しかも繰り返し解いたのは1~4回の計260問のみで、5~6回はほぼ無勉強)


# 受験結果
2023/07/29に、自宅でAWS ソリューションアーキテクト アソシエイト試験を受験し、(なぜか)合格しました。試験を受けながら、「あ、こりゃ無理だ・・・」と諦めながら問題を解いていたので、なぜ合格できたのかが本当にわかりません。

そもそも、udemy講座の模擬試験で出された問題はほとんど出なかったように思います。(brain-dump問題集じゃあるまいし、当然と言えば当然なのですが)一応設問と答えのセットだけ暗記することはせず、解説も読んで理解しようとはしていたが、とにかく出題された設問のほとんどは自信をもって回答できませんでした。長文ばかりで、特定の課題や状況を与えられたうえで、どのようなサービスやソリューションのセットを使えば解決できるか、ということを求められる設問がほとんどでした。(しかもけっこうどの選択肢もそれっぽくできている)

体感ですが、正答率はよくても半分くらいだったのではないでしょうか。(オンラインで自宅受験したのですが、部屋を片付けた際机も一緒に片づけてPCを床に直置きしており、受験時のに姿勢が辛くなってしまったので、見直しもあまりせずさっさと試験を終了してしまいました)

![スクリーンショット 2023-07-30 155756.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/21c5a3bf-70f5-d9dc-b99d-49896caea7c8.png)


# なぜ合格できたのか
合格水準は **720/900(80%)** と聞いていたので、**絶対に無理**と思って諦めていました。
ただ、スコアレポートを見ると明確に「合格に必要なスケーリングスコアは720点です。」と書かれていたので、これで納得できました。

720点は設問に対する**絶対値ではなく、偏差値やTOEICのような相対値**だったということですね。
そういえば、受験した後すぐに合否が表示されなかったので、なぜだろう？8年前に受験した時はすぐ合否が出た記憶があるのだがなあ・・・・・・と思いました。(本部のサーバーで得点調整や不正有無を確認してたからでしょう。まあ、合否に関するこんな基礎的な情報も調べず受験すんなって話でもありますが・・・・・・)

とはいえ、体感として全設問の半分も自信がない状態でほぼ諦めて提出したレベルで受かってしまったので、とてもラッキーでした。私の受験タイミングがAWS側の試験問題の入れ替え時期と被っており、平均スコアが非常に低いときだったかもしれません。

もちろん勉強はしましたし、RedShiftやらKinesisやらERMやら全く知らなかったサービスや機能の名前は覚えましたし、S3ってデフォルトだとインターネットアクセスになるのかー、VPCエンドポイントなんてもんがあるんだなーとかは学ぶことができましたが。


# 今後の予定
とりあえず合格できたので、これからは超へっぽこながらAWSソリューションアーキテクトアソシエイトを名乗らせていただこうと思っています。
資格なんて持っていても何のスキルの証明にもならないが、とはいえ未経験であってもやる気を証明するための免許として資格は必要なものだと思っているので、この免許を使ってAWSに関する案件を今後担当できればなあと思いました。
AWS-SAAが簡単に取得出来たらプロフェッショナル資格であるAWS-SAPも取得しようと思っていたのですが、この体たらくでは無理ということを痛感したので、おとなしくもっと勉強しようと思います・・・・・・。
限界ド文系大学生ワイ「条件分岐してぇな！」その結果……

こんにちは！限界ド文系大学生、堕罪ｵｻﾑです。
大学では**国語学・日本語学**を主に学んでいます。

# 条件が複数あるif文を書いてメンターに見せたときのこと

突然ですが、JavaScript初学者の皆様。


**1. 条件Aが成り立つときはYESを出したい**
**2. 条件Bが成り立つときもYESを出したい**
**3. 条件Cが成り立つときはNOを出したい**
**4. 条件Dが成り立つときもNOを出したい**

こんな感じで、**条件が複数あるif文を書きたい**とき、ありませんか？
私自身、勉強を進めていく過程でこんな感じのコードを書く時がありましたので実際に書いてみました。


～n時間後～

ワイ「よっしゃ！書けたぞ～。早速メンターに見てもらおう！」

メンター「**DRY原則**に反してる書き方だからやめたほうがいいよ～」

## 私が実装したアンチパターン


このときの私はこういったコードを書きました。_(code.1)_

```javascript
//YESになるものをまとめたif文
if(条件A){
    console.log("YES")
}else if(条件B){
    console.log("YES")
}

//NOになるものをまとめたif文
if(条件C){
    console.log("NO")
}else if(条件D){
    console.log("NO")
}
```


## そもそもDRY原則とは？

簡単に言うと
**同じような処理を複数の場所に書かないほうがいいよ！**
ということです。
ふむふむ、知らなかった～。

もう少し細かく言うならば、DRY原則は**システム全体で重複するのはよくない**ということらしいです。
また**OAOO原則**というものもありました。そちらのほうは**ソースコードに書く処理を重複するのはよくない**という感じみたいです。

:::note
インフォメーション
初学者による初学者に向けての記事なのでここではDRY原則とOAOO原則を厳密に分けない(分けられるほどの知識がない)ことを承知の上、読み進めていただけると幸いです。
:::


DRY原則を意識することのメリットとして

・コードそのものが読みやすくなる
　**=>結果、メンテナンス性が高くなる**
・重複したコードが減ることで、書き直すコードの数が減る

があります。

## 修正後のコード

よって、先ほどのコードをDRY原則に外れないように書き直すと_(code.2)_

```javascript
// YESになるものをまとめたif文
if (条件A || 条件B) {
    console.log("YES");
}

// NOになるものをまとめたif文
if (条件C || 条件D) {
    console.log("NO");
}

```

YESとNOを2回づつ出さないことで、かなりすっきりしました！
ちなみに```||```は論理演算子のOR条件ともいうらしいです。ほえ～。

条件の中に```&&```も入れられるのでかなり便利、その上コードが読みやすくなる。すごすぎる。

### ほかの書き方もできました

また、コードを綺麗に書くという点で、**条件式の結果を変数にまとめる**というやり方もあります。_(code.3)_

```javascript
// YESになる条件をまとめた関数
const isYes = 条件A ||条件B;

// NOになる条件をまとめた関数
const isNo = 条件C || 条件D;

if (isYes) {
  console.log("YES");
} else if (isNo) {
  console.log("NO");
}
```

こちらもアンチパターンとは違い、すっきりして分かりやすく書くことができました。

# まとめ
**うん！やっぱり難しい！！**

率直な感想はこれに尽きます……。
初学者だからとりあえず動けばいいや！なんてことはなく、きれいなコードを書く練習だと思って今後も精進していきます。

ここまで読んでくださりありがとうございました！
Centosにhttpsでアクセスできるようになるまで

# 好奇心の向く方へ
面白そうだったので、VPSを思い切って契約したました～
とはいえ何から始めればいいかわからなかったので、とりあえずApache入れてドメイン取得してSSL証明書取得してhttpsでアクセスできるとこまでやるだけやりました！
まあ作りたいもの、やりたいことは決まって無いんですけどねぇ～！！！！（偉い人に怒られそう）
ではやってきます。
#### 特記事項
※本記事はcentosを使用した例です。
※VPSのためマシンの初期設定とかがあったらそれは含んでいません。悪しからず。
※たぶん初歩的な内容がほとんど。許してね:stuck_out_tongue:
※あくまでもhttpsでアクセスできるようになるまでの手順です。
※例外がある可能性はもちろんあります。あくまで参考程度に見てください。
# 目次
- [ドメインの設定](#ドメインの設定)
- [Apacheのインストール、設定](#Apacheのインストール、設定)
- [SSL証明書取得](#SSL証明書取得)
- [あとがき](#あとがき)

## ドメインの設定
適当なレジストラで、好きなドメインを取得してください。
（なんかのサービスを作ろうとしてるなら、こだわったほうがいいかもね）
本記事では、`hogehoge.com`を取得した場合の例をつらつらと書きます。
#### ・DNSレコードの設定
とりあえずAレコードにサーバーのIPアドレスを入れとけばヨシ！

※ドメイン使ってメール送信とかもするなら、MXレコード、SPFレコードとか設定した方がいいかもね！
キャリアによっては無差別にはじかれちゃうよ～（Gmailとか多分送れないっす）
あとはコマンドプロンプトとかでnslookupたたいて情報が出てくればOK
まあわかんなければ下のWebページ行ってドメイン入れればいける
https://www.cman.jp/network/support/nslookup.html

## Apacheのインストール、設定
以下を参考にしました！めっちゃわかりやすかった
https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-ubuntu-20-04-ja
基本的に手順通りにやれば大丈夫だけど、この中で自分がつまずいたポイントを以下に書いておきます～

#### ファイアウォールの設定のとこ
```
$ sudo ufw status
```
これ実行したら、出力例のようにならなかったんですよね。
ただ有効化してないだけでした。
```
sudo ufw enable
```
そしてサーバー再起動！

#### この後つまずいてます。
僕「さて、再起動終わったしSSH接続するか～」
MovaXterm「接続できませんでした。」
僕「なんでやねん」

それもそのはず、ファイアウォール有効化したおかげで、22番ポートが拒否されてました。
VPSの管理画面からコンソールを開いて設定する羽目に・・・
ここで時間食ったので、備忘録として以下を残しておきます・・・
```
$ sudo ss -tlnp | grep sshd
```
これでSSH接続受け付けてるport番号がわかる。
VPSの種類によっては違うやつになってるかもだから念のため。
```
$ sudo ufw allow 22
$ sudo ufw enable
```
多分この後も再起動
これでSSHできるようになりましたとサ・・・

## SSL証明書取得
これも以下を参考にしています！
https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-20-04-ja
こちらは躓くことなく完了したので、特に追記はありません！

## あとがき
手順通りにとりあえずインストール、設定をしてみました。
まだなぜこの手順が必要なのか、どこが欠けるとだめなのかを正確に把握してないふしがあるので、機会ベースで学習、調査できたらなと思います。
久しぶりの投稿でしたが楽しかったです～
またなんか書いて備忘録にします。
LINE公式アカウント OPEN APIKey 事前準備

https://linedevelopercommunity.connpass.com/event/289749/

本資料はこちらの体験会用の事前準備資料となります。

# 1.LINE公式アカウント作成

LINEが入ったスマホを手元に準備し [こちら](https://developers.line.biz/) にアクセス

https://developers.line.biz/

 ◆自動翻訳が出たら「英語」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/8a7481c5-20bb-de8c-1ba1-f6c624c65f03.png)

 ◆日本語を設定→コンソール
![](https://storage.googleapis.com/zenn-user-upload/38eb277e6866-20220227.png)

 ◆LINEアカウントでログイン→QRコードログイン
![](https://storage.googleapis.com/zenn-user-upload/a92e377ea0d3-20220227.png)

 ◆QRコードをスマホで読み込み→ログイン→スマホで認証番号4桁を入力
![](https://storage.googleapis.com/zenn-user-upload/e6b45b9a9767-20220227.png)

 ◆下記の通り進める
![](https://storage.googleapis.com/zenn-user-upload/6a43f137648c-20220227.png)
![](https://storage.googleapis.com/zenn-user-upload/bc5c03895438-20220227.png)
![](https://storage.googleapis.com/zenn-user-upload/872b672e0774-20220227.png)
![](https://storage.googleapis.com/zenn-user-upload/927d49a836e1-20220227.png)
![](https://storage.googleapis.com/zenn-user-upload/13e832f6829f-20220329.png)
![](https://storage.googleapis.com/zenn-user-upload/97c1991a105d-20220227.png)
![](https://storage.googleapis.com/zenn-user-upload/b6b5bb30858f-20220227.png)
![](https://storage.googleapis.com/zenn-user-upload/84e50170bbb8-20220227.png)

 ◆LINE Official Account Managerをクリック
![](https://storage.googleapis.com/zenn-user-upload/e1ef35002f4d-20220227.png)

 ◆①～⑤の通りクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/b1a8643c-0534-7a3d-1941-61fee52543c3.png)


 ◆LINE Official Account Managerに戻る→Messaging API設定→QRコードから友達登録
![](https://storage.googleapis.com/zenn-user-upload/79e74cbbc17f-20220227.png)

 ◆このようなメッセージが返ってきたら成功です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/c7275f72-e3f5-7a3c-a644-d45451768546.png)

## 参考：LINE公式アカウントとは？

 [こちらのページ](https://www.ooh.co.jp/blog/?p=219)で分かりやすく解説されています

 https://www.ooh.co.jp/blog/?p=219

# 2.OPEN APIKey発行

 下記ページの
 『OpenAIのAPIキーの発行手順』の章を参考にご準備ください

https://auto-worker.com/blog/?p=6988#

下記の表示までこれでいればOKです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/f4137a73-a987-2072-87c8-30c48fc50c2c.png)

 それでは当日もお楽しみに(^○^)
異なるOS間でのGemfile.lockの競合を解決する方法

## はじめに

オリジナルプロダクト（ポートフォリオ）のデプロイに向けて、最新のソースコードをAWS EC2に反映させようとしたところ、`Gemfile.lock`　の競合が発生しました。
その原因と解決方法についてまとめました。

### 開発環境


- ローカルマシン
    - OS：macOS Ventura
- AWS EC2
    - OS：Amazon Linux 2
- 共通
    - Ruby：3.2.2
    - Rails：7.0.6
    - Bundler：2.4.13


## エラーメッセージ

EC2 に`git pull`で最新のソースコードを反映させようとしたところ、以下のエラーメッセージが表示されました。

```
error: Your local changes to the following files would be overwritten by merge:
	Gemfile.lock
Please commit your changes or stash them before you merge.
```


「次のファイルに対するローカルの変更が、マージ時に上書きされる可能性があります：
　　　　Gemfile.lock
マージする前に、変更内容をコミットするかスタッシュしてください。」

という内容です。


## 原因

`git diff`で差分を調べたところ、以下のようにでました。
※ 一部抜粋

```console
     tailwindcss-rails (2.0.30-x86_64-darwin)
+    tailwindcss-rails (2.0.30-x86_64-linux)

     PLATFORMS
       x86_64-darwin-22
+  　　　　　　　　x86_64-linux
```
一部のgemはOS特有のバージョンが存在する様です。

最初に、EC2にプロジェクトをクローンした後、Bundlerの `bundle install` コマンドでgemのインストールを行いました。
この時点で `Gemfile.lock` に差分が発生しているのですが、これを認識しないまま更新内容を `git pull` しようとしたため、先述のエラーが出てしまいました。

<br>
<br>

時系列に沿ってまとめると、以下の様になります。

1. ローカルマシン（macOS）で開発し、リモートリポジトリに `push`
    - 一部gemは、<font color="red">macOS</font>準拠のバージョン
1. AWS EC2 にクローン
1. EC2（Amazon Linux 2）で `bundle install` 実行
    - 一部gemは、<font color="blue">Amazon Linux 2</font>準拠のバージョン
    - ここで差分発生！
1. 差分を認識せず `git pull` したため競合エラー


## 解決策

ローカルの開発環境で `bundle lock --add-platform`　オプションを使うことによって
指定したプラットフォームのための依存関係を Gemfile.lock に追加する。


私のケースでは
- 開発環境が macOS (x86_64-darwin) 
- 本番環境が Linux (x86_64-linux) 

なので

ローカルのプロジェクトディレクトリで

```console
bundle lock --add-platform x86_64-linux
```

とコマンドを入力することで、両プラットフォームの依存関係を考慮した Gemfile.lock を生成できます。

これによりOSの違いによって起こる `Gemfile.lock` の差分が発生しなくなりました。


## おわりに

最後までお読みいただきありがとうございます。
少しでも参考になれば幸いです。
記事内に不備がありましたら遠慮なくご指摘いただけると嬉しいです。

<br>
<br>

余談ですが、ChatGPT(GPT-4)からは、Bundlerの`BUNDLE_IGNORE_PLATFORMS` という設定を使えと回答され、また公式ドキュメントの「PLATFORMS」セクションを参照しろとのことでした。

しかし、公式ドキュメントに該当する記載はありませんでした。

その旨ChatGPTに伝えたところ、謝罪に加え、当機能が一部の開発者コミュニティでは説明・使用されている旨の言い訳を聞かされました。笑

- 公式ドキュメントの参照はマスト
- ChatGPTは叩き台作成用に使ったり、ヒントを得るために使う。参考程度に。

今回、再認識した教訓です。



## 参考

https://bundler.io/docs.html

https://bundler.io/v2.4/man/bundle-lock.1.html
【Solargraph】Solargraphをコンテナで動かす【Docker】


## `Dockerfile`を作成
以下が`Dockerfile`の例です。
```Dockerfile:Dockerfile
FROM ruby:3.1.2

WORKDIR /app
RUN gem install solargraph

EXPOSE 7658
```

## `docker-compose.yml`を作成
`docker-compose.yml`を以下のように作成します。

```docker-compose.yml
solargraph:
    build: .
    command: bundle exec solargraph socket --host=0.0.0.0 --port=7658
    volumes:
      - .:/app
    ports:
      - "7658:7658"
```

`docker-compose.yml`を作成したらコンテナを起動します。

```:ターミナル
$ docker-compose up -d solargraph
```

## 拡張機能をインストール
VSCodeに以下の拡張機能をインストールします。

https://marketplace.visualstudio.com/items?itemName=castwide.solargraph

## 拡張機能の設定
`setting.json`に以下のように記述し、拡張機能の設定をします。

```setting.json
"solargraph.externalServer": {
  "host": "localhost",
  "port": 7658
},
"solargraph.transport": "external"
```
これでVSCodeでsolargraphが使用可能になります。
Ruby on Railsを使ったウェブアプリの全体像を図にしてみた

Ruby on Railsみたいなフレームワークは全体像が分からないとなかなか使いこなせないので図にしてみました。

## 参照にしたUdemy講座

とても分かりやすくRuby on Railsを解説してくれてました！おすすめです。

<a href="https://www.udemy.com/share/101WM43@bnQfrXfMGQu0yKdd9kHKmNtGOsQAe2RKGTsQMqslwYUO8Yx3g5IHlAOuRYXwYc8I/">はじめてのRuby on Rails入門-RubyとRailsを基礎から学びウェブアプリケーションをネットに公開しよう</a>

## 全体像を図にしたもの

Cacooを使用（今までMiroを使ってたけど、ウェブ界隈で人気のCacooを使ってみるとかなり使い勝手が良かったです）

Model, View, Controllerごとに色分けをして、あとはルーティングとかの関係性をまとめました。

<a href="https://cacoo.com/diagrams/t5S4fC4IcDGl8mv2/E80D3">Ruby on Rails全体像</a>

<a href="https://cacoo.com/diagrams/t5S4fC4IcDGl8mv2/E80D3"><img src="https://start-electronics.com/wp-content/uploads/2023/05/UntitledImage.png" alt="UntitledImage" title="UntitledImage.png" border="0" width="799" height="460" /></a>
Qiita の投稿規定

**Markdown 記法についてのページもちゃんと用意されているのに**，多くの人は無頓着に投稿されるようです。

https://qiita.com/Qiita/items/c686397e4a0f4f11683d

余計なお世話ですが，以下の2項目だけを特にお願いします。

![スクリーンショット 2023-07-30 23.29.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/5fd44646-b3eb-e709-8c67-85f3a46c48d7.png)


![スクリーンショット 2023-07-30 23.27.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/d5c1e656-1b0f-29d6-5328-b5e6ee8d0ac4.png)
Gitの中身を調べたら理解に役立った

# 概要
Gitの中身を知ることで、どこに対する操作なのかを意識しやすくなります。
今回はできるだけ短く要点だけまとめます。

## Gitのデータ管理
ローカルでは3つのエリアに分かれています。それぞれ紹介します。

**ワークツリー**
ファイルを変更する作業場。普段私たちがコードをいじる場所ですね。

**ステージ**
`git add`をした時にステージに追加されます。コミットをする準備をします

**リポジトリ**
`git commit`をした時にリポジトリに追加されます。ここではスナップショットを記録します

![20200911144527.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641519/b31effa3-9505-272f-dfb7-f62022116655.png)
引用: https://phoeducation.work/entry/2020/09/11/144733

## Gitコマンドについて
| コマンド | やっていること | 説明 |
|:-----------|------------:|:------------:|
| git init       | .gitディレクトリを作成        | Gitに関する全ての関連情報が作成される。         |
| git add     | blobオブジェクトの作成      | 圧縮ファイルを作成。ハッシュ値を付与する       |
| git commit       | treeオブジェクトの作成        | 圧縮ファイルのハッシュ値に対応するファイル名を付与する|
| git commit    | commitオブジェクトの作成          | treeオブジェクトを使用して様々な情報を作成する |

代表的なコマンドを3つピックアップしました。
「やっていること」について説明していきます。

## git add
上記の前提知識をもとに説明していきます。
例えば、index.htmlファイルを作成した場合を例に考えます。まず、リポジトリに圧縮ファイルAというファイルが作成されます。その後、圧縮ファイルをハッシュ化したものをindex.htmlとマッピングしたものをステージングで保持します。これが`git add`です。そしてこれがblobオブジェクトと呼ばれます。

![スクリーンショット 2023-07-30 23.07.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641519/db49d153-4f27-4152-946b-90bb7bffcd42.png)

## git commit
`git commit`では2つのことをしています
**①ツリーオブジェクトの作成**
blobオブジェクトにはもともとのファイル名情報が残っていません。全てハッシュ化されています。ここではファイル名とファイルの中身を組み合わせることでツリーオブジェクトを作成します。ツリーオブジェクトはディレクトリの一つの階層ごとに一つのツリーファイルになっていて、ツリーファイルには圧縮ファイルだけでなくツリーファイルも保存されています。

**②コミットオブジェクトの作成**
コミットオブジェクトでは以下のような情報を持ったコミットオブジェクトを作成します

・ハッシュ値
　①で作成した変更情報がハッシュ値として設定されます

・作成者
　このコミットをした本人のアカウント名

・親コミット
　直前のコミットを記録します。（一個前のコミット）

・日付
　コミットした日付を記録

・コミットメッセージ
　そのままの意味。変更箇所などを書くことが多い
![スクリーンショット 2023-07-30 23.15.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641519/70e7b02e-a179-77c0-7ef2-1bda9a4b3311.png)


# まとめ
Gitは3つのことをやっている
- 変更ファイルを圧縮する
- 圧縮ファイルと変更ファイルを関連付ける
- 変更情報が記載されたコミットファイルを作成する

Gitのコマンドは基本的に上記3つの動きに対しての操作となるので
どのフェーズに対しての操作か意識すると理解が深まると思う。
LXDEの扱い方チートシート

### はじめに
今回は自分なりにLXDEの設定方法をまとめてみようと思います。というのも、自分のPCは低スペックなのでGnomeでもラグに目が余るからです。軽量さを追い求めた結果、LXDEという野暮な環境に慣れてしまったので、日本語記事の繁栄に貢献したいと思います。
## ミニトピック
### LXDEとは
LXDE(Lightweight X11 Desktop Environment)はC++で実装されたLinux用のデスクトップ環境です。CPUやRAMの消費が他のデスクトップ環境よりも大幅に低いので、低スペックなPCでよく利用されます。その反面、基礎的かつ簡素なUIしか提供されていないのでgnomeやKDEには及びません。
### 姉妹環境LXQt
LXDEの姉妹環境であるLXQtもかなり有名です。LXDEよりはUIが充実しているので、特に理由がないなら初めからこれを使えばいいと思います。現在のLubuntuもLXDEからこれに移行しました。
### LXLE Linux
「Recieve that old PC!」が売り文句のLXLE Linuxは,
デスクトップ環境にLXDEを採用しています。同梱されているアプリケーションも最小限なので、執拗に推奨するわけでもございませんが、興味があれば是非利用してはいかがでしょうか。
### WM
Openboxを採用しています。大きな特徴は、画面上で右クリックすることでメニューが表示されることです。私もこれを愛用しています。
## 基本設定
### インストール
Debian/Ubuntu
```bash
$sudo apt install lxde
```
Arch
```bash
$sudo pacman -S lxde
```
Fedora
```
sudo yum groupinstall lxde-desktop
```
### ディスプレイサーバー
- Xorg ・・・ 一番無難だと思います。
- wayland ・・・ Fedoraが採用しています。
- Mir ・・・ 独自のプロトコルとX11をサポート

特に理由がないならXorgの関連パッケージのインストールを推奨します。
### Autostart
`~/.config/lxsession/LXDE/autostart`設定例
```bash
@lxpanel --profile LXDE
@pcmanfm --desktop --profile LXDE
@xscreensaver -no-splash
@picom
@plank
```
### 基本設定
`~/.config/lxsession/LXDE/desktop.conf`
### MENUの編集
GUIアプリをいくつか紹介しておきます。
| メニューエディター | 特徴 | 実行ファイル |
| ---- | ---- | ---- | 
| lxmed  | sourceforgeで入手。AUR対応 | /usr/bin/lxmed
| alacarte | 直感的な操作。現状コピペができません | /usr/bin/alacarte

alacarteは多分？コピペができないので、lxmedを採用しました。(他にも便宜的な問題が有りました。)
### openboxメニューの編集
こちらもGUIアプリが存在します。

http://openbox.org/wiki/ObConf:About
## カスタマイズ
### ディスプレイマネージャー
| ディスプレイマネージャー | 特徴 | 設定ファイル |
| ---- | ---- | ---- |
| LXDM  | LXDEのデフォルトディスプレイマネージャー。野暮です。 | /etc/lxdm/lxdm.conf
| LightDM | 野暮ではないが、themeが少ない | /etc/lightdm/lightdm.conf
| SDDM | LXQtとKDEが推奨しており、themeも充実しているのでお薦めです。 | /etc/sddm.conf.d/default.conf 

起動方法
```bash
sudo systemctl enable lxdm/lightdm/sddm
```
ログイン後に指定したセッションに移動しなければ、設定ファイルのカレントディレクトリ下にあるXsessionを編集してください。通常はインストールのみでXから起動します
```bash
#Xsession
...
...
exec startlxde
```
### コンポジットマネージャー
| コンポジットマネージャー | 特徴 | 設定ファイル |
| ---- | ---- | ---- | 
| picom  | 主に透過処理を行う | ~/.config/picom/picom.conf
| compton | 主に透過処理を行う | ~/.config/compton.conf

私はpicomを採用しました。autostartに`@picom`を追加すると起動します。(autostartには`@+実行するコマンド`)
LXTerminalが透過しないのは便宜的によろしくない(と私は思っている)ので、Background Colorを設定して透過させましょう。
### ドックアプリ
| コンポジットマネージャー | 特徴 |
| ---- | ---- | 
| plank  | 軽量だがアニメーションは有る | 
| cario dock | 豊富なテーマ | 
| latte dock | KDEが推奨している。KDEでなければ導入が面倒 | 
| Docky | 軽量かつシンプル | 

## 最後に
便宜的な問題でLXDEを採用する方は少ないと思われますが、カスタマイズすればgnomeと同じような感覚で使えるようになるはずです。軽量さを追い求める駆け出しエンジニアは是非ご利用ください。
(軽量さを求めるならWMのみを使えば良いとよく言われますが、デスクトップ環境の方が直感的に操作できるので、あいようしています)
【Laravel】refとreactiveの使い分け

# refとは
refはプリミティブな値(string、numberなどObjectでないもの)を引数にとり、値をリアくてティブにします。

ref関数を用いてリアクティブな変数を定義できます。
値を1つ受取、リアクティブな型のオブ軸とを返します。

refで定義したリアクティブな変数の値へアクセスするには.valueを使用します。<template>内で使用するときは.valueを省力できます。

リアクティブを保ったまま値の直接更新、再代入ができます。


## 特徴
・リアクティブなデータが判別しやすい

## デメリット
・常に.valueでアクセスする必要がある。

# reactiveとは
reactiveメソッドはオブジェクトを引数に取り、リアクティブにします。

reactiveに含まれる一部のプロパティの値をリアクティブにしたい場合、toRefs()を使用します。

リアクティブを保ったまま値の直接更新ができます。値の再代入はconstで定義した場合はできます。

```js:
<script setup lang="ts">
import { reactive, computed } from 'vue'

const state = reactive({
  count: 0
})

const increment = () => {
  state.count++
}
</script>

<template>
  <p>{{ state.count }}</p>
  <button @click="increment">+</button>
</template>
```

## 特徴

・Options APIのDataの定義と似ている
・まとまったデータを定義するのに向いている

```js:
<script setup lang="ts">
import { reactive, ref } from 'vue';

const user = reactive({
  firstName: 'Jhon',
  lastName: 'Smith',
  age: 21,
});

const fullName = computed(() => `${user.firstName} ${user.lastName}`);

const firstName = ref('Jhon');
const lastName = ref('Smith');
const age = ref(21);

const fullName = computed(() => `${firstName.value} ${lastName.value}`);
</script>
```

## デメリット
・通常のオブジェクトと区別がつきにくい
・分割代入するとリアクティブ性が失われる。


# refとreactiveの違い

JavaScriptでプリミティブを使うかオブジェクトを使うか程度の誤差しかありません。

# 参考記事

https://qiita.com/mgr/items/a5e35636d371969e0a4d

https://zenn.dev/azukiazusa/articles/ref-vs-article
ログをデコレーターで記述する


関数内にログをベタベタ書くと見づらいのでデコレータで
外に吐き出しました。（結果的に一層長くなりましたが...）
もっと短く書けないか考え中です。

以下、足し算・引き算の例です。


``` python
import logging
import sys
import functools

class CalculatorLogger:
    def __init__(self, logger_name):
        self.logger = logging.getLogger(logger_name)
        self.logger.setLevel(logging.INFO)

        # ログが重複しないように、既存のハンドラーがあれば削除
        if self.logger.hasHandlers():
            self.logger.handlers.clear()

        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s')

        # ログをコンソールに出力するハンドラーを追加
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        console_handler.setFormatter(formatter)
        self.logger.addHandler(console_handler)

class Calculator:
    def __init__(self):
        self._result = 0
        self.logger = CalculatorLogger(__name__)

    # デコレーター: 関数の説明をログに含める
    def log_description(description):
        def decorator(func):
            @functools.wraps(func)
            def wrapper(self, *args, **kwargs):
                self.logger.logger.info(f'{func.__name__}: {description} 関数が呼び出されました。')
                result = func(self, *args, **kwargs)
                self.logger.logger.info(f'{func.__name__}: {description} 関数の実行が終了しました。')
                return result
            return wrapper
        return decorator

    # デコレーター: プロパティ変数の更新前後の値をログに残す
    def log_property_change(prop):
        def decorator(func):
            @functools.wraps(func)
            def wrapper(self, value):
                old_value = getattr(self, prop)
                func(self, value)
                new_value = getattr(self, prop)
                if old_value != new_value:  # 更新がある場合のみログ出力
                    self.logger.logger.info(f'{func.__name__}: {prop} 変数が更新されました。変更前: {old_value}, 変更後: {new_value}')
                setattr(self, prop, new_value)  # プロパティの値を更新
            return wrapper
        return decorator

    # 整数チェック
    def is_integer(value):
        try:
            int(value)
            return True
        except ValueError:
            return False

    # 足し算
    @log_description('足し算')
    @log_property_change('_result')
    def add(self, value):
        if not Calculator.is_integer(value):
            self.logger.logger.error('整数以外の値が指定されました。')
            sys.exit(1)
        self._result += int(value)

    # 引き算
    @log_description('引き算')
    @log_property_change('_result')
    def subtract(self, value):
        if not Calculator.is_integer(value):
            self.logger.logger.error('整数以外の値が指定されました。')
            sys.exit(1)
        self._result -= int(value)

    # プロパティ変数のゲッター
    @property
    def result(self):
        return self._result

# クラスのインスタンス化
calc = Calculator()

# 足し算と引き算のログ出力付き操作
calc.add(5)
calc.subtract(2)

# プロパティ変数のログ出力
print(calc.result)  # 現在の計算結果を表示

# エラーチェック：整数以外の引数
calc.add("abc")

```
【SwiftUI】matchedGeometryEffectを使って拡大機能を作成する

# はじめに
`@Namespace`と`matchedGeometryEffect`を使って滑らかなアニメーションを実装することができるので拡大機能を実装してみました

# サンプルアプリ
![Simulator Screen Recording - iPhone 14 Pro - 2023-07-30 at 22.58.30.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/fa5da798-f863-780c-ba6d-f349063d0733.gif)

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @State private var selectedEmoji: String?

    @Namespace private var namespace
    
    private let emojis = ["☺️", "😄", "😆", "😀", "😤", "😠", "🥱", "😮‍💨", "😫", "😭", "😂", "😢"]
    
    private let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 3)
    
    var body: some View {
        if let emoji = selectedEmoji {
            Text(emoji)
                .font(.system(size: 100))
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Color(uiColor: .cyan))
                .onTapGesture {
                    withAnimation {
                        selectedEmoji = nil
                    }
                }
                .matchedGeometryEffect(id: emoji, in: namespace)
        } else {
            ScrollView {
                LazyVGrid(columns: columns, spacing: 10) {
                    ForEach(emojis, id: \.self) { emoji in
                        Text(emoji)
                            .font(.system(size: 50))
                            .frame(maxWidth: .infinity)
                            .frame(height: 80)
                            .background(Color(uiColor: .cyan), in: RoundedRectangle(cornerRadius: 10))
                            .onTapGesture {
                                withAnimation {
                                    selectedEmoji = emoji
                                }
                            }
                            .matchedGeometryEffect(id: emoji, in: namespace)
                    }
                }
                .padding(16)
            }
        }
    }
}
```

# おわり
めっちゃいい感じになりました
これを応用したらかっこいいアプリが作れそうです！
CSR・SSR・SSGを初学者がふんわり理解するための記事

# CSR・SSR・SSGを初学者がふんわり理解するための記事

## はじめに
Web系を学んでいるとよく聞く単語
**【CSR】【SSR】【SSG】** 

Next.jsをいじくり回しているとよく検索欄に出てくるので、勉強がてらまとめてみることにします。

初学者の皆さん、私と一緒にふんわり理解しましょう！！
つよつよエンジニアのみなさん、間違っていることがあればビシバシご指摘ください><

## そもそもレンダリングってなんだろう
Next.jsちゃぱちゃぱ勢の私としてはここから調べていく必要がありました。
調べたところ
> **指定したリソースをブラウザ画面に表示すること** 

だそうです。

ふむふむ、、、、、ん?
え、皆さんわかりました？


つよつよエンジニアのみなさんはきっとこれで分かるんでしょう。
参考にさせていただいた記事の執筆者様もきっとつよつよなんだ、、、

まあでも、ふんわり分かればいいんです。ふんわり。

噛み砕いて書くならば、

:::note info
**レンダリングとは**
ブラウザさんがサーバーさんからもらったデータを解釈して、わたしたちが目にするようなwebページとして描画すること。
:::

こんな感じにしておきましょう。(させてください笑)

https://zenn.dev/oreo2990/articles/280d39a45c203e

## CSR (Client Side Rendering)
クライアントサイドレンダリング
一番想像しやすい、、、?
**React**などクライアント側Javascriptによってページが描画されるものがこれにあたるみたいです。

`create-react-app` なんかで作られるデフォルトプロジェクトの描画方法ですね。
クライアント側のJavascriptで描画するってことは、初期状態は真っ白で何もないということで、
つまりSEO(Search Engine Optimization : 検索エンジン最適化)に不利であるそうです。

なるほどなるほど、
Reactでフツーにつくったwebサイトはクライアント側でレンダリングされているってことか。

クライアント側で作られるってことは、SEOクローラーからしたら、何も見えないってことだから、
上位に表示してほしいって言ったって無理なもんですな。

じゃあちょこっとまとめます。

:::note info
**CSRとは**
クライアント側でレンダリングする方式。Reactがこれに当たる。
SEOクローラーさんは見れないのでSEOには不利。
:::

## SSR (Server Side Rendering)
サーバーサイドレンダリング
Next.jsをいじっていると一番聞くやーつ。

サーバーサイドでレンダリングすることでwebページを作ることですね。
サーバーサイドでレンダリングしてくれているのでSEOクローラーさんもニッコリ。
サーバー側でレンダリング処理を行うから表示速度は早いものの、リクエスト毎の生成となるので、サーバーの負荷が増加するそうです。

SSRをしらべていると、やたら**プリレンダリング**なる単語が出てくるので、こちらも調べてみます。
(Nextやってるなら知っておけというツッコミは真摯に受け止めます)


#### プリレンダリング
> プリレンダリング機能は、ウェブサイトを表示する際に必要なデータ取得やJavaScriptをWebサーバーで実行し、HTMLの生成を行います。

ん、、、?
んん、、、？？

SSRのことじゃないの?
ちゃぱちゃぱ勢は混乱してきました。

よーく調べたら、プリレンダリングの方式として**SSR**と**SSG**があるそうです。
知らなかった、、、！

Nextさんはデフォルトでプリレンダリングしてくれてるそうです(これはなんとなぁく知ってたやーつ)。
だから早いし、SEO対策にもなるってことなんですね。

ふむふむ。
Nextさんすばらしい。

ではSSRについてもまとめてみます。

:::note info
**SSRとは**
サーバー側でレンダリングする方式。リクエストごとにページを生成する。
パフォーマンスとSEO向上に一役買っている。
:::

https://aimstogeek.hatenablog.com/entry/2022/04/04/080000

## SSG (Static Site Generator)
スタティックサイトジェネレーター

名前がかっこいい(ﾎﾞｿｯ)

SSGはアプリのビルド時にデータを取得、HTMLの生成を行って、サーバー上にキャッシュさせておく方式らしいです。

それだとDBなどのデータの変更が反映されないのでは??と思いましたが、どうやらそういった問題もしっかり対応されているようです。(ちゃぱちゃぱ勢にはちょっと難しすぎたので割愛させてください><)

基本的に静的サイト(HPやLP)に向いているそうです。
キャッシュさせておくことができるので爆速ですしね。

私がちゃぱちゃぱしているNextだったり、昨今話題のAstroやGatsbyなんかがSSGになります。

SSGについても軽くまとめます。

:::note info
**SSGとは**
ビルド時にページを生成して、サーバ上にキャッシュさせておくことができる方式。爆速。
静的なページで利用されることが一般的。
:::


https://zenn.dev/luvmini511/articles/1523113e0dec58

## おわりに
ふんわり理解できた、、、と思いたい。
でも、実際に開発してみないとわからないことのほうが多いかなと思います。
概念だけでも知っておいて損はないはず、、、！

もし今後勉強していくなかで発見があれば随時追記していこうかなと思います。
Nextちゃぱちゃぱ勢頑張ります！
サンプルデータベースのリンク集

サンプルデータベースをいろいろ探しています。

# MySQL
- [MySQL :: Other MySQL Documentation](https://dev.mysql.com/doc/index-other.html)
- [MySQL :: Employees Sample Database](https://dev.mysql.com/doc/employee/en/)

# TiDB
- [Import Example Database | PingCAP Docs](https://docs.pingcap.com/tidb/stable/import-example-data)
    - [System Data | Capital Bikeshare](https://capitalbikeshare.com/system-data)

# PostgreSQL
- [PostgreSQL Sample Database](https://www.postgresqltutorial.com/postgresql-getting-started/postgresql-sample-database/)
- [devrimgunduz/pagila: PostgreSQL Sample Database](https://github.com/devrimgunduz/pagila)

# SQL Server
- [AdventureWorks サンプル データベース - SQL Server | Microsoft Learn](https://learn.microsoft.com/ja-jp/sql/samples/adventureworks-install-configure?view=sql-server-ver16&tabs=ssms)
- [Wide World Importers - SQL 用のサンプル データベース - SQL Server | Microsoft Learn](https://learn.microsoft.com/ja-jp/sql/samples/wide-world-importers-what-is?view=sql-server-ver16)

# Amazon Redshift
- [サンプルデータベース - Amazon Redshift](https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/c_sampledb.html)
初めてのJuliaインストール2 ~jupyter Labで動かす~

↓の続きー

https://qiita.com/yuusuke_/items/14d619782861bc5177e2

前回は、インストールして、動くところまで確認

## Jupyter Labで動かしてみる
前回Jupyter Notebookでやろうと思ってみたものの、Labのほうがおすすめと聞いて、そっちでやってみる

参考サイト

https://qiita.com/ttabata/items/b05bb43d06239f968035

https://qiita.com/hujuu/items/12a5d16354fcc629200e

## Juliaでパッケージ導入
ちょい久しぶりに起動

```]``` キーをタイプして、package マネージャー
```add IJulia``` でインストール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327497/c23faea9-4d05-ce99-d9be-d4031fc78e7b.png)

できたっぽい
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327497/2a4dcb3a-cd6c-cefe-3c63-b1dbc5db2f4b.png)


## Jupyter labで確認
Jupyter LabのLancher見たらJuliaがある！



PC変えたせいでやり直しになってしまってた。

とりあえずできた！
まだJuliaが何者なのか詳しくわかっていないのでとりあえずPythonでやってたことを再現してみようかな
Excelファイルの特定のセルをタイトルと同じ名前にする(自動更新)

以下プログラムをVBAのThisWorkBookに貼り付ける

    Private Sub Workbook_Open()

    ' 変更するセルのアドレスと変更したい値を設定します
    Dim targetCellAddress As String
    targetCellAddress = "A1" ' 例: セルA1を変更したい場合
    
    ' タイトルを取得します
    fileTitle = ThisWorkbook.Name
    fileTitle = Left(fileTitle, Len(fileTitle) - 5) ' 拡張子を含まないように削除します

    
    Dim newValue As Variant
    newValue = fileTitle ' 例: 新しい値を "新しい値" に設定します

    ' タイトルに基づいてセルの値を変更します
    ThisWorkbook.Sheets(1).Range(targetCellAddress).Value = newValue
    
    MsgBox "名称が更新されました。"
        
    End Sub
同じフォルダにある複数のファイルから特定セルの数値を取得し、一覧にする

    Sub GetCellValuesAndFileNames()
    Dim folderPath As String
    Dim fileExtension As String
    Dim fileName As String
    Dim wb As Workbook
    Dim ws As Worksheet
    Dim cellValue1 As Variant
    Dim cellValue2 As Variant
    Dim outputRow As Long

    ' 画面の更新を一時的に停止します
    Application.ScreenUpdating = False
    
    ' フォルダのパスを指定します
    folderPath = "C:\YourFolderPath\"
    ' ファイルの拡張子を指定します（例：".xlsx"）
    fileExtension = ".xlsx"
    ' 出力先のシートを指定します
    Set ws = ThisWorkbook.Sheets("Sheet1")
    ' 出力を開始する行を指定します
    outputRow = 2
    
    ' フォルダ内の全てのファイルに対してループします
    fileName = Dir(folderPath & "*" & fileExtension)
    Do While fileName <> ""
        ' ファイルを開きます
        Set wb = Workbooks.Open(folderPath & fileName)
        ' データを取得します（A1セルとB1セルを例とします）
        cellValue1 = wb.Sheets(1).Range("A1").Value
        cellValue2 = wb.Sheets(1).Range("B1").Value
        ' ファイルを閉じます
        wb.Close False
        
        ' 取得したデータを出力します（ファイル名も一緒に出力します）
        ws.Cells(outputRow, 1).Value = fileName
        ws.Cells(outputRow, 2).Value = cellValue1
        ws.Cells(outputRow, 3).Value = cellValue2
        
        ' 次の行に出力する準備をします
        outputRow = outputRow + 1
        
        ' 次のファイルに進みます
        fileName = Dir
    Loop

    ' 画面の更新を再度有効にします
    Application.ScreenUpdating = True
    
    MsgBox "データの取得が完了しました。"
    End Sub
Auroraのスケジュール起動・停止でつまずいたこと

# つまづいたこと
コスト削減のため、Amazon Auroraのスケジュール起動・停止を実現しようとAWS所有SSMドキュメントおよびEventBridgeで実装しようとしていたのですが、何度トライしても**Auroraクラスター**が停止されず、パラメーターなども何度も変更しながら試行錯誤をしていました。

結論から書きますと「**Aurora**と**RDS**ではスケジュール起動・停止に使用するAWS自己所有SSMドキュメントは異なる」という事が原因でした。

# 不正解
こちらの「**AWS-StartRdsInstance**」および「**AWS-StopRdsInstance**」でずっとトライしていましたが、一向に停止される気配無し。あくまで**RDS**向けとの事。

![2023073003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143947/d349835a-f7cf-2b1f-0657-74200c97e88d.jpeg)


# 正解
こちらの「**AWS-StartStopAuroraCluster**」が正解でした。トライしてみたところ、Auroraクラスターを停止する事が出来ました。

![2023073004.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143947/667e1051-fd1e-2e59-4269-e78d154a1b20.jpeg)
【Python】CSVファイル名に記載のある日付を新しい列として追加してみた(その2)

<h1>前提</h1>
<ul>
<li>環境：Python 3.11.4</li>
<li>細かいパスの指定は省略</li>
</ul>

<h1>今回のゴール</h1>
'sample_data_2023-07-23.csv'や'2023-07-23_sample_data.csv'といった、任意の場所にある'yyyy-mm-dd'を抽出し、2列目にdateという列として、追加したい。

```python:sample.py
>>> import pandas as pd
>>> filename1 = 'sample_data_2023-07-23.csv'
>>> filename2 = '2023-07-24_sample_data.csv'
>>> df1 = pd.read_csv(filename1)
>>> df2 = pd.read_csv(filename2)
>>> df1.head()
   id
0   1
1   2
2   3
3   4
4   5
>>> df2.head()
   id
0   1
1   2
2   3
3   4
4   5
```

```python:sample.py
#完成系
#'sample_data_2023-07-23.csv'の「2023-07-23」を抽出して、追加したい
>>> df1.head()
    id        date
0    1  2023-07-23
1    2  2023-07-23
2    3  2023-07-23
3    4  2023-07-23
4    5  2023-07-23

#'2023-07-24_sample_data.csv'の「2023-07-24」を抽出して、追加したい
>>> df2.head()
    id        date
0    1  2023-07-24
1    2  2023-07-24
2    3  2023-07-24
3    4  2023-07-24
4    5  2023-07-24
```


<h1>流れ</h1>
<ol>
<li>正規表現を使い、yyyy-mm-dd形式のデータを抽出</li>
<li>抽出したデータを変数に格納</li>
<li>新たな列に追加</li>
</ol>

<h1>1.正規表現を使い、yyyy-mm-dd形式のデータを抽出</h1>

```python:sample.py
>>> import re
>>> filename1 = 'sample_data_2023-07-23.csv'
>>> filename2 = '2023-07-24_sample_data.csv'
#正規表現を使い、yyyy-mm-dd形式のデータを抽出
>>> re.search(r'\d{4}-\d{2}-\d{2}',filename1)
<re.Match object; span=(0, 10), match='2023-07-23'>

>>> re.search(r'\d{4}-\d{2}-\d{2}',filename2)
<re.Match object; span=(0, 10), match='2023-07-24'>
```

<h1>2.抽出したデータを変数に格納</h1>

```python:sample.py
#group()を使うとマッチした箇所だけ抽出できる
>>> date1 = re.search(r'\d{4}-\d{2}-\d{2}',filename1).group()
>>> date2 = re.search(r'\d{4}-\d{2}-\d{2}',filename2).group()
>>> date1
'2023-07-23'

>>> date2
'2023-07-24'
```



<h1>3.新たな列に追加</h1>

```python:sample.py
>>> import pandas as pd
#'2023-07-23_data.csv'をデータフレーム化
>>> df1 = pd.read_csv(filename1)
>>> df2 = pd.read_csv(filename2)
#dateを新たな列として追加
>>> df1['date'] = date1
>>> df2['date'] = date2
#中身を確認
>>> df1.head()
   id        date
0   1  2023-07-23
1   2  2023-07-23
2   3  2023-07-23
3   4  2023-07-23
4   5  2023-07-23

>>> df2.head()
   id        date
0   1  2023-07-24
1   2  2023-07-24
2   3  2023-07-24
3   4  2023-07-24
4   5  2023-07-24
```

<h1>まとめ</h1>
正規表現を使用し、ファイル名にあるyyyy-mm-dd形式のデータを抽出し、新たな列に格納することが出来ました。
以下に今までの内容をまとめた、サンプルコードを記載します。

次回はまとめて複数ファイルの処理については更新予定ですので、少々お待ちください。


```python:sample.py
>>> import pandas as pd
>>> import re
>>> filename1 = 'sample_data_2023-07-23.csv'
>>> filename2 = '2023-07-24_sample_data.csv'
#正規表現を使い、yyyy-mm-dd形式のデータを抽出
>>> date1 = re.search(r'\d{4}-\d{2}-\d{2}',file_name1).group()
>>> date2 = re.search(r'\d{4}-\d{2}-\d{2}',file_name2).group()
>>> df1 = pd.read_csv(file_name1)
>>> df2 = pd.read_csv(file_name2)
#dateを新たな列として追加
>>> df1['date'] = date1
>>> df2['date'] = date2
#中身を確認
>>> df1.head()
   id        date
0   1  2023-07-23
1   2  2023-07-23
2   3  2023-07-23
3   4  2023-07-23
4   5  2023-07-23

>>> df2.head()
   id        date
0   1  2023-07-24
1   2  2023-07-24
2   3  2023-07-24
3   4  2023-07-24
4   5  2023-07-24
```
【Python】CSVファイル名に記載のある日付を新しい列として追加してみた(その１)

<h1>前提</h1>
<ul>
<li>環境：Python 3.11.4</li>
<li>細かいパスの指定は省略</li>
</ul>

<h1>今回のゴール</h1>
'2023-07-23_data.csv'という名のCSVファイルの2列目にdateという列を追加したい。

```python:sample.py
#'2023-07-23_data.csv'の中身
>>> import pandas as pd
>>> df = pd.read_csv('2023-07-23_data.csv')
>>> df.head()
   id
0   1
1   2
2   3
3   4
4   5
```

```python:sample.py
#完成系
#'2023-07-23_data.csv'の「2023-07-23」を抽出して、追加したい
    id        date
0    1  2023-07-23
1    2  2023-07-23
2    3  2023-07-23
3    4  2023-07-23
4    5  2023-07-23
5    6  2023-07-23
```


<h1>流れ</h1>
<ol>
<li>CSVファイルを選択</li>
<li>ファイル名から日付を抽出</li>
<li>新たな列に追加</li>
</ol>

<h1>1.CSVファイルを選択</h1>

```python:sample.py
#該当のCSVファイルをfile_nameという変数に格納する
>>> file_name = '2023-07-23_data.csv'
```

<h1>2.ファイル名から日付を抽出</h1>

```python:sample.py
#ファイル名の先頭から10文字を抽出
>>> date = file_name[0:10]
>>> date
'2023-07-23'
```



<h1>3.新たな列に追加</h1>

```python:sample.py
>>> import pandas as pd
#'2023-07-23_data.csv'をデータフレーム化
>>> df = pd.read_csv(file_name)
#dateを新たな列として追加
>>> df['date'] = date
#中身を確認
>>> df.head()
   id        date
0   1  2023-07-23
1   2  2023-07-23
2   3  2023-07-23
3   4  2023-07-23
4   5  2023-07-23

```

<h1>まとめ</h1>
ファイル名から日付を抽出し、新たな列に格納することが出来ました。

以下に今までの内容をまとめた、サンプルコードを記載します。
ここまで見て頂き、下記のような感想を持った方もいると思います。
<ul>
<li>先頭から何文字とかは汎用性が低い抽出方法だ。</li>
<li>複数のファイルをまとめて、処理したい</li>
</ul>
汎用性の高い抽出方法や複数ファイルをまとめての処理についてはその２、その３で更新予定ですので、少々お待ちください。


```python:sample.py
>>> import pandas as pd
>>> file_name = '2023-07-23_data.csv'
>>> df = pd.read_csv(file_name)
>>> date = file_name[0:10]
>>> df['date'] = date
>>> df.head()
   id        date
0   1  2023-07-23
1   2  2023-07-23
2   3  2023-07-23
3   4  2023-07-23
4   5  2023-07-23
```
ファイル管理③

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/471efff3-9894-f719-fdbe-6d33863e61d6.png)
　ファイルシステム
　ディスク装置でファイルを管理する仕組みをファイル装置といいます。私たちが利用しているパソコン用OSシステムは、ファイルを階層構造で管理する点が特徴です。

　ディレクトリ
　パソコン用OSでは、フォルダとして扱っているものです。ファイルを格納できる入れもと考えると良いでしょう。ディレクトリの中には、ファイルの他に別のディレクトリを入れることもできます。つまり、ディレクトリは階層構造で管理します。最上位階層のディレクトリをルートディレクトリと言います。

　パス
　ファイルの位置を示す表記のことです。ファイルにゆきつくまでにたどったディレクトリを表記します。パソコン用のOSでは、フォルダを開いた順に表記したものになります。ルートディレクトリを起点として表記したもの絶対パス、カレントディレクトリ（今現在開いているフォルダ）を起点として表記したものを相対パスと言います。
　
　パスを表記するときには、「￥」や「/」をディレクトリの区切り文字として使います。「.」はカレントデ切れクトリを、「..」は１つ上の回想のディレクトリに遡ることを表します。また、パス表記の先頭が「￥」や「/」から始まっているときは、絶対パスであることを意味します。