OmniAICreator/Qiita-1.07M huggingface dataset:
CircleCIを使用してUbuntuサーバーで自動git pull

# CircleCIを使用してUbuntuサーバーで自動git pull

この記事では、CircleCIを使用してGitHubリポジトリからUbuntuサーバーに自動的にコードをデプロイする方法を解説します。この手法では、環境変数を`.env`ファイルに保存し、それをCircleCIジョブ内で読み取ることで、セキュリティを確保しながらデプロイを行います。

### 前提条件

- CircleCIアカウントが設定済み
- GitHubリポジトリが設定済み
- Ubuntuサーバーが設定済み
- `.env`ファイルがUbuntuサーバーに配置済み

### 手順

#### 1. CircleCI設定ファイルを作成

まず、プロジェクトのルートディレクトリに `.circleci/config.yml` ファイルを作成します。以下の設定例を参考にしてください。

```yaml
version: 2.1

jobs:
  build:
    docker:
      - image: circleci/node:14
    steps:
      - checkout
      - run:
          name: 依存関係をインストール
          command: npm install
      - add_ssh_keys:
          fingerprints:
            - "YOUR_SSH_KEY_FINGERPRINT"
      - run:
          name: SSH接続と各コマンド実行
          command: |
            ssh -o StrictHostKeyChecking=no ${USER}@${YOUR_SERVER_IP} << 'EOF'
              echo "サーバーへの接続に成功しました"
              cd /home/ubuntu/your_project_directory
              echo "ディレクトリの移動に成功しました"
              pwd
              echo "現在のディレクトリを表示しました"
              git status
              echo "現在のブランチを表示しました"
              if [ -f .env ]; then
                export $(grep -v '^#' .env | xargs)
              fi
              echo "GITHUB_USER: ${GITHUB_USER}"
              echo "GITHUB_TOKEN: ${GITHUB_TOKEN}"
              echo "GITHUB_REPO: ${GITHUB_REPO}"
              git config --global credential.helper store
              echo "<https://${GITHUB_USER}:${GITHUB_TOKEN}@github.com>" > ~/.git-credentials
              git pull https://${GITHUB_USER}:${GITHUB_TOKEN}@github.com/${GITHUB_REPO}.git
              echo "最新の変更を取り込みました"
              # 必要なコマンドをここに追加
            EOF
```

この設定では、CircleCIがサーバーにSSH接続し、GitHubから最新のコードをpullする手順を示しています。

#### 2. `.env`ファイルを作成

Ubuntuサーバー上のプロジェクトディレクトリ（例：`/home/ubuntu/your_project_directory`）に `.env` ファイルを作成し、以下のように環境変数を設定します。

```bash
# .envファイルの例

# GitHubのユーザー名
GITHUB_USER=your_github_username

# GitHubのパーソナルアクセストークン
GITHUB_TOKEN=your_github_personal_access_token

# GitHubのリポジトリ
GITHUB_REPO=your_username/your_repository
```

これらの環境変数は、SSHセッション中で使用されます。そのため、CircleCI側のEnvironment Variablesで指定するのではなく、Ubuntuサーバー上の `.env` ファイルで設定する必要があります。

#### 3. CircleCIプロジェクト設定

CircleCIプロジェクトの設定画面で、環境変数 `USER` と `YOUR_SERVER_IP` を設定します。これにより、CircleCIジョブ内でこれらの変数が使用可能になります。

#### 4. デプロイを実行

上記の設定が完了したら、CircleCIのパイプラインを実行します。CircleCIがGitHubリポジトリから最新のコードをUbuntuサーバーにデプロイし、`.env`ファイルから環境変数を読み取って使用します。

### 結果

これで、CircleCIを使用して安全にGitHubリポジトリからUbuntuサーバーにデプロイする方法が構築されました。環境変数は`.env`ファイルで管理され、セキュリティが確保されています。
Bunのクイックスタートをさわってみた

# はじめに
webエンジニアの風速です。
今回は前から聞いたことのあった、Bunを触ってみようと思います。

# Bunとは
安定版がリリースされたのは2023年の9月で、JavaScriptおよびTypeScriptアプリ用のall-in-one toolkitで、そのなかでもメインがNode.jsの代替として設計された高速JavaScriptランタイムです。他にもテストランナー、スクリプトランナー、Node.js互換パッケージマネージャーなどの機能があります。

![スクリーンショット 2024-08-29 22.40.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/51cbd016-755e-59d1-d925-139dbcb8a89d.png)
超速そう！

# インストール
今回はmac OSを使用するので、brewでインストールします。
```
$ brew install bun

$ bun --version
1.1.26
```

# クイックスタートを試してみる
https://bun.sh/docs/quickstart

## テストプロジェクトの作成

### ディレクトリ作成
```
$ mkdir bun-test
$ cd bun-test
```
### プロジェクトの作成
プロジェクトを作成します。対話ツールが起動されます。
今回は全てEnterで進めました。
```
$ bun init
bun init
bun init helps you get started with a minimal project and tries to guess sensible defaults. Press ^C anytime to quit

package name (bun-test):
entry point (index.ts):

Done! A package.json file was saved in the current directory.
 + index.ts
 + .gitignore
 + tsconfig.json (for editor auto-complete)
 + README.md

To get started, run:
  bun run index.ts
```

以下のような構成でファイルが生成されています。
```
$ ls -1
README.md
bun.lockb
index.ts
node_modules
package.json
tsconfig.json
```

## ファイル実行
`bun init`でプロジェクトが作成されたので、index.tsを編集します。
```index.ts
const server = Bun.serve({
  port: 3000,
  fetch(req) {
    return new Response("Bun!");
  },
});

console.log(`Listening on http://localhost:${server.port} ...`);
```

index.tsの実行をします。
```
$ bun index.ts
Listening on http://localhost:3000 ...
```
localhostを叩くと以下のようにレスポンスが返ってきます。
```
$ curl http://localhost:3000
Bun!   
```


Node.jsではTypeScriptファイルを実行するには、ts-nodeなどを用いる必要がありますが、BunではTypeScriptがサポートされているので、そのまま実行できます。

:::note warn

Node.jsでは実験的にサポートが始まっている。
:::

## scriptの実行
package.jsonに以下を追記します。
```diff_json:package.json
{
  "name": "quickstart",
  "module": "index.ts",
  "type": "module",
+   "scripts": {
+    "start": "bun run index.ts"
+  },
  "devDependencies": {
    "@types/bun": "^1.0.0"
  }
}
```

```
$ bun run start

$ bun run index.ts
Listening on http://localhost:3000 ...
```

## パッケージのインストール
```
$ bun add figlet
$ bun add -d @types/figlet #tsを使用する場合は型宣言もインストール
```

index.tsを以下のように編集する。
```diff_typescript:index.ts
+ import figlet from "figlet";

const server = Bun.serve({
  port: 3000,
  fetch(req) {
+     const body = figlet.textSync("Bun!");
+     return new Response(body);
-     return new Response("Bun!");
  },
});
```

localhostを叩くと以下のようにレスポンスが返ってきます。
```
$ curl http://localhost:3000
  ____              _
 | __ ) _   _ _ __ | |
 |  _ \| | | | '_ \| |
 | |_) | |_| | | | |_|
 |____/ \__,_|_| |_(_)
                               
```


# まとめ
自分はjsのランタイム自体はNode.jsしか使用したことがなかったのですが、Node.jsやnpmとも互換があり、使用感はあまり変わらないと感じました。今回さわったクイックスタートでは速度の違いには言及できませんでしたが、そのあたりも検証などできたら良いかなと思います。個人的にはDenoも名前がかわいくて気になっているので、機会があればさわってみたいと思います。🦖


# 参考
https://bun.sh/

https://zenn.dev/mizchi/articles/experimental-node-typescript
確率密度関数を使用して平均値と分散を求める公式の導出

確率密度関数を使用して平均値と分散を求める公式の導出

## はじめに

確率密度関数 (PDF) は、確率論や統計学で非常に重要な概念です。PDFを使って、連続確率変数の平均値（期待値）や分散を計算することができます。この記事では、その公式の導出と幾何学的・視覚的なイメージを紹介します。

## 平均値（期待値）の導出

確率密度関数  f(x)  に対して、連続確率変数  X  の平均値（期待値）μ  は次のように定義されます。

$$
\mu = E[X] = \int_{-\infty}^{\infty} x f(x) \, dx
$$

### 導出過程

1. 確率密度関数  f(x)  は、値  x  に対する確率を与える関数です。
2. 確率密度関数  f(x)  に値  x  を掛けたものを積分することで、全体の重み付き平均が求まります。これが期待値（平均値）です。

### 幾何学的イメージ

平均値は確率密度関数の「重心」に相当します。確率分布の形状に従って、値の重み付き平均をとることで中心を求めることができます。視覚的には、分布の中心を示すポイントです。

## 分散の導出

分散は次のように定義されます。

$$
\sigma^2 = E[(X - \mu)^2] = \int_{-\infty}^{\infty} (x - \mu)^2 f(x) \, dx
$$

これを展開すると、次のようになります。

$$
\sigma^2 = \int_{-\infty}^{\infty} \left( x^2 - 2x\mu + \mu^2 \right) f(x) \, dx
$$

さらに、これを積分すると：

$$
\sigma^2 = \int_{-\infty}^{\infty} x^2 f(x) \, dx - 2\mu \int_{-\infty}^{\infty} x f(x) \, dx + \mu^2 \int_{-\infty}^{\infty} f(x) \, dx
$$

ここで次のことがわかります：
$$
\int_{-\infty}^{\infty} x f(x) \, dx = \mu 
$$

$$
\int_{-\infty}^{\infty} f(x) \, dx = 1 
$$

したがって、分散は次の式で表されます。

$$
\sigma^2 = \int_{-\infty}^{\infty} x^2 f(x) \, dx - \mu^2
$$

### 各項の意味

$$
\int_{-\infty}^{\infty} x^2 f(x) \, dx 
$$
これは xの2乗の期待値を表しており、データ全体の広がりを示します。幾何学的には、この項は確率分布の「広がりの大きさ」を測る役割を果たします。

$$
-2\mu \int_{-\infty}^{\infty} x f(x) \, dx
$$
この項は、平均値 μ の影響を除去するための調整項です。実際には μの2乗の-2倍 となり、分散計算の中で平均値がどのようにデータ全体に影響を与えるかを示します。

$$
\mu^2 \int_{-\infty}^{\infty} f(x) \, dx
$$
この項は、平均値自体の平方を考慮に入れています。積分の結果が1になるため、これは単に μの2乗 です。この項は、全体の基準点としての役割を果たします。

### 幾何学的イメージ

分散は、データのばらつきを測る指標です。視覚的には、分布の広がりの程度を表しており、分散が大きいほどデータが平均から大きく離れていることを意味します。分布の形状によっては、分散が異なる印象を与えることがあります。

## まとめ

確率密度関数を使って平均値と分散を計算する公式は、確率分布の中心とその周りの広がりを理解するために非常に重要です。これらの公式を幾何学的に捉えることで、データの分布の特性をより深く理解できるようになります。
分散、標準偏差、絶対偏差の違いと使い分け

## はじめに

データのばらつきを評価する指標として、分散、標準偏差、絶対偏差（平均絶対偏差, MAD）があります。これらはそれぞれ異なる特徴を持ち、状況に応じて使い分けることが重要です。本記事では、これらの指標の違い、使い分け方、そして視覚的な意味について説明します。

## 分散とは

### 定義

分散は、データのばらつきを評価するための基本的な指標で、データとその平均値との差の二乗の平均を指します。これは次の式で表されます。

$$
\sigma^2 = E[(X - \mu)^2] = \int_{-\infty}^{\infty} (x - \mu)^2 f(x) \, dx
$$

この式で 
$$
E[(X - \mu)^2]
$$
は、偏差の二乗の期待値を意味します。つまり、データの各点 X と平均 μ との差を二乗し、その平均を取ることでデータ全体のばらつきを評価します。

### 分散の式の意味

分散を求める際に出てくる次の式を分解して考えてみます。

$$
\sigma^2 = \int_{-\infty}^{\infty} x^2 f(x) \, dx - 2\mu \int_{-\infty}^{\infty} x f(x) \, dx + \mu^2 \int_{-\infty}^{\infty} f(x) \, dx
$$

この式は、次の3つの項に分かれます。第一項の
$$
\int_{-\infty}^{\infty} x^2 f(x) \, dx
$$
はデータの二乗の期待値で、データ全体の大きさを測る指標です。第二項の
$$
-2\mu \int_{-\infty}^{\infty} x f(x) \, dx
$$
はデータの平均値 \( \mu \) の影響を取り除くための補正項です。第三項の
$$
\mu^2 \int_{-\infty}^{\infty} f(x) \, dx
$$
はデータ全体のバランスを取るための基準点としての役割を果たします。

## 標準偏差とは

### 定義

標準偏差は、分散の平方根を取ったもので、次の式で表されます。

$$
\sigma = \sqrt{E[(X - \mu)^2]} = \sqrt{\sigma^2}
$$

標準偏差を使うことで、データのばらつきを元のデータと同じ単位で表すことができ、直感的に理解しやすくなります。

### 特徴

- **大きな偏差を強調**: 標準偏差は、偏差を二乗してから平均を取るため、平均から大きく離れたデータ点の影響が強調されます。
- **データの単位に一致**: 標準偏差は元のデータと同じ単位で表されるため、解釈が容易です。

## 絶対偏差（平均絶対偏差, MAD）とは

### 定義

絶対偏差（MAD）は、データの偏差の絶対値の平均を取ったもので、次の式で表されます。

$$
\text{MAD} = E[|X - \mu|] = \int_{-\infty}^{\infty} |x - \mu| f(x) \, dx
$$

### 特徴

- **リニアな評価**: 偏差の絶対値を取ることで、データのばらつきをリニアに評価します。
- **外れ値の影響が少ない**: 標準偏差よりも外れ値の影響が抑えられ、全体的なばらつきを穏やかに反映します。

## 標準偏差と絶対偏差の使い分け

### 標準偏差を使う場合

- データのばらつきが大きく、外れ値の影響を考慮したいとき。
- データが正規分布に従っている場合や、ばらつきの指標として一般的な手法を用いたいとき。
- 複数のデータセットのばらつきを比較する場合。

### 絶対偏差を使う場合

- 外れ値の影響を抑えた評価が求められる場合。
- データが分布の形状に大きく依存しない場合や、リニアなばらつきを簡単に評価したいとき。
- より簡単で迅速な計算が必要な場合。

## 視覚的意味の違い

- **標準偏差**: データの中心からの広がりを示します。標準偏差が大きいほど、データが広がっている（ばらついている）ことを意味します。外れ値がある場合、その影響が大きくなります。
- **絶対偏差**: データの中心からの距離の平均を示します。外れ値の影響を抑え、全体のばらつきを穏やかに示します。

## まとめ

分散、標準偏差、絶対偏差は、データのばらつきを評価するための重要な指標です。標準偏差は外れ値の影響を強調するため、外れ値を重視する場合に適しています。一方、絶対偏差は外れ値の影響を抑えた評価ができるため、全体のばらつきを穏やかに示したい場合に有用です。状況に応じて、適切な指標を選択することが大切です。
Box Canvasを使ってみよう!!

#### **はじめに**
今回はBox Canvasを際に使ってみて、感じたメリットや、活用方法を書いていきます！

<br>

#### **BoxCanvasとは？**
BoxCanvasは、デジタルキャンバス上でアイデアを視覚化し、自由に表現できるビジュアルコミュニケーションプラットフォームです。シンプルで洗練されたインターフェースを持ち、初めての人でも直感的に使いこなせるのが魅力。個人のブレインストーミングから、チーム全体でのアイデア共有、プロジェクト管理まで、あらゆるクリエイティブな場面で活用できます。

<br>

#### **BoxCanvasの特徴**
- **直感的な操作性**：まるで紙に書くような感覚で、アイデアやメモをどこにでも配置可能。ドラッグ＆ドロップで簡単に要素を移動でき、特別な技術や知識がなくても操作できます。
  
- **リアルタイムコラボレーション**：複数人が同時にキャンバスにアクセスし、リアルタイムで編集やコメントが可能。リモートワークでも一体感を持ったチーム作業が実現します。

- **無限のキャンバス**：物理的な制限がないため、広大なスペースで自由に発想を広げられます。思いついたアイデアをどんどん追加して、キャンバス全体で視覚的に整理できます。

- **多彩なデザインツール**：テキスト、図形、画像、ラインなど、豊富なデザインツールを備えています。これらを組み合わせて、自分だけのユニークなキャンバスを作成できます。

<br>

#### **実際に使用してみた**
今回はBox Canvasを使い、採用活動のタスク整理を関係者間でやってみようと思います！ 

違う部署や場所で作業している関係者もいるため、「会議スペースに集まって打合せ」がしづらく、 オンライン上でホワイトボードのように使えるBox Canvasはうってつけのサービスです。

Box Canvasのテンプレートに、ちょうどタスク整理に使えそうな「開始、中止、継続」というものがあったので選んでみました。

まずはBoxへログインし、「Canvas」をクリックします。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799749/3ae742e3-ad33-b3a0-917b-c64010d8f4ca.png)

このように新規のCanvasが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799749/1fab97f5-d154-e115-f1bd-a1499b4d657d.png)

Box Canvasではいろいろなテンプレートが使えるので、タスク整理に使えそうなテンプレートがあるかを探します。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799749/7e4743cb-41ca-b29f-5021-6a6cf05964eb.png)

このように便利なテンプレートがたくさんあります！
その中にある「開始、中止、継続」がタスク整理に向いていそうなので、使ってみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799749/06f9f624-2c4e-8aac-5eda-6b2d99c7b817.png)

同じ画面上で操作を行えるように、画面右上のここから関係者に共有します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799749/e6176c44-c6c9-1295-a280-89049be6e3e7.png)

実際に整理したものはこんな感じになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799749/dd9bf2dd-1c68-054e-7a99-6c89f0b8dfe7.png)

今後の採用活動について、「どんなことを続けていくか」、「何をやらなくても良いか」一目で分かりやすくまとまりました！

使ってみた感想としては、Boxと同じ共有先・同じ権限で、紐付いた形でデジタルホワイトボードが利用できるのは非常に便利だと思いました。付箋には絵文字でのリアクションを追加できます。リアクションの数はカウントされるため、意見を募るなどの用途に利用できそうです。

<br>

今回は「タスク整理」でBox Canvasを使いましたが、他にもこんな用途で使えるかもしれません。 

- **ビジネスミーティング**：アイデア出しや戦略立案の場で、ホワイトボードのように使うことができます。
  
- **教育現場**：生徒と一緒に共同でプロジェクトを進めたり、視覚的に学習内容を整理するツールとしても最適です。

- **クリエイティブワーク**：デザインやコンセプトの構想を視覚化し、プロジェクトメンバーと共有する際に大いに役立ちます。

- **個人のブレインストーミング**：思いついたアイデアをすぐに記録し、自由に発展させていくことができます。

<br>

### **まとめ**

BoxCanvasは、オンラインでの打ち合わせなど、相手と対面での話し合いができない環境で使用すれば、プロジェクトを円滑に進行することができます。簡単に使用するのであれば、個人のメモ帳として使用するのも良いかもしれません！ぜひ試してみてください！
How Artificial Intelligence is Transforming Digital Marketing Strategies

1. Personalized Customer Experiences
AI enables marketers to create highly personalized experiences by analyzing vast amounts of data. It can predict customer behavior, preferences, and needs, allowing for tailored content and recommendations. This level of personalization increases engagement and conversion rates.

2. Enhanced Data Analysis
AI tools can process and analyze data much faster and more accurately than humans. This capability helps marketers gain deeper insights into customer behavior and campaign performance. With AI, businesses can make data-driven decisions that optimize their marketing strategies.

3. Automated Customer Interactions
Chatbots and virtual assistants powered by AI are transforming customer service. They can handle inquiries, provide support, and even guide customers through the purchasing process 24/7. This automation not only improves customer satisfaction but also frees up human resources for more complex tasks.

4. Content Creation and Curation
AI can assist in generating and curating content. Tools like natural language processing (NLP) can create initial drafts of articles, social media posts, and even video scripts. AI can also curate content by analyzing what resonates most with the audience, ensuring that the right content reaches the right people.

5. Predictive Analytics
AI uses predictive analytics to forecast future trends and behaviors. This allows marketers to anticipate customer needs and adjust their strategies accordingly. Predictive analytics can improve targeting, reduce churn, and increase customer lifetime value.

6. Optimized Advertising
AI optimizes advertising efforts through programmatic ad buying, which automates the process of purchasing ads based on data analysis. This ensures that ads are shown to the right audience at the right time, maximizing ROI. AI can also adjust ad spend in real-time based on performance metrics.

7. Improved SEO
AI tools enhance search engine optimization (SEO) by analyzing search patterns and identifying the most effective keywords. They can also optimize content structure and provide insights into how to improve rankings on search engines.

Conclusion
AI is transforming digital marketing by providing tools and insights that enhance personalization, efficiency, and effectiveness. As AI technology continues to evolve, its impact on digital marketing will only grow, offering even more opportunities for businesses to connect with their audiences in meaningful ways.

![Screenshot 2024-08-30 114420-1500x1080.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3847208/053a601f-475d-a609-a798-4092842a970d.png)
AtCoder 過去問「ABC049C - 白昼夢」を解いてみた

# はじめに
Python の練習として AtCoder の過去問「ABC049C - 白昼夢」を解いてみました.

https://atcoder.jp/contests/abs/tasks/arc065_a

もちろん, 優れた解説はたくさんあるので, そちらと見比べてください.

https://delta114514.hatenablog.jp/entry/2018/03/15/014555

# 再帰で解いたら, 案の定…
まず, 再帰で解いてみました. 与えられた文字列が, dream, dreamer, erase, eraser のいずれかにマッチしたら, マッチした文字列を消去して, 同じことを繰り返します. そして最後まで達したら True, マッチしなかったら False を返します.

```python:1
s = "dream dreamer erase eraser".split()

def match_string(str):
  """ str の先頭からの文字列が s に含まれるか判定する
  """
  global s
  result = []

  # s が空文字列なら True
  if len(str) == 0:
    return True

  # str の先頭からの文字列が s に含まれるかどうか判定する
  for i in range(len(s)):
    if str.startswith(s[i]):
      result.append(match_string(str.replace(s[i], "", 1)))
    else:
      result.append(False)

  return any(result)

# メイン
line = input().strip()
if match_string(line):
  print("YES")
else:
  print("NO")
```

結果は, 正解も出ましたが, ほとんどは実行時エラーでした.

# マッチした結果をリストに入れていく

そこで, 再帰を使わない方法を考えました. dream, dreamer, erase, eraser のいずれかがマッチしたら, マッチした部分を消去した文字列をリストに加えて, 次以降のループで評価します. そして完全にマッチする結果が出たら True, そうじゃなかったら False を返します.

```Python:2
s = "dream dreamer erase eraser".split()
line = input().strip()

def match_string():
  """ line の文字列が s に含まれるかどうか判定する
  """
  global s, line
  result = [line] # リストを作る

  while len(result) > 0: # リストが空でないうちは繰り返す
    str = result.pop(0) # 先頭を取得
    for i in range(len(s)): # 文字列が等しければ, return True
      if str == s[i]:
        return True
      elif str.startswith(s[i]): # 先頭の文字列が等しければ, リストに appepnd し, 次のループへ
        result.append(str[len(s[i]):])
  return False

# メイン
if match_string():
  print("YES")
else:
  print("NO")
```

これで OK となりました.

# さいごに
競プロをがっつりやる時間はないのですが, 勉強として少しずつトライしていこうと思います.
CISSPのCPEポイントの稼ぎ方ver2.0

# 更新履歴
2024/9/3 CPEハンドブックについてISC2から回答があったため修正

# はじめに
本記事は以下の記事に誤りが複数あるとの指摘を受け、改めて最新版のCPEハンドブックを参照して書き直したものです。

https://qiita.com/log0417/items/4ae5325ff226604d0300
~~ところがそもそもハンドブック自体に問題がありそうです。~~
→複数の日本語版ハンドブックが存在していたためISC2に問い合わせを行い、以下が正しいハンドブックであると回答いただきました。

https://www.isc2.org/-/media/Project/ISC2/Main/Media/documents/members/MEM-Certification-Maintenance-Handbook-Digital-Japanese.pdf


# CPEの基本
## 必要なポイント数
更新に必要なポイント数はCISSPが最も多く120ポイントです。CCSPが90、SSCPが60ですが、ほとんどの人はCISSPの120ポイントに苦労すると思いますので、ここでは120ポイントを貯める方法を考えます。

## グループAとグループB
CPEはグループAとグループBの2つに分かれています。グループAは資格のドメインでカバーされている分野に直接関係している活動です。普通に貯めていればほぼこちらでたまるはずです。グループBはドメインに直接関係しない活動です。セキュリティ以外のイベントへの参加がこれに含まれるようですが、私はこちらで申請したことがなく、その必要もありませんでした。本記事ではグループAのみで考えます。

## CPEの監査
CPEは自己申告制ですが、ランダムで監査に当たります。監査の対象になった場合、その活動を行ったことを証明するエビデンスが必要になります。よってエビデンスが確実に得られる活動が望ましいことになります。

# 具体的な稼ぎ方
ISC2では多様な活動がCPEの対象になっています。トレーニングの受講、書籍の執筆、本や雑誌を読む、ウェビナーの受講などです。この他ISC2からもクイズへの回答などで獲得機会が提供されています。

CPEを稼ぐにあたり、できるだけお金をかけず、手間をかけない方法を紹介します。
## ウェビナーやセミナーの視聴
ISC2やSANSなどからウェビナーがたびたび配信されています。1時間の視聴で1ポイントです。個人的なおすすめはSANSが年に数回開催しているサミットです。オンラインから無料で参加できますし、基本的に2日間、合計12時間程度開催されるので、12ポイント獲得できます。SANSのアカウントにISC2のメンバーIDを登録しておけば自動的に登録されるのもおすすめです。

https://www.sans.org/cyber-security-summit/

他にもJSACは日本で開催される無料のイベントです。こちらも2日間行われます。

https://jsac.jpcert.or.jp/

上記以外ですと、有料になりますが湯沢、道後、白浜などで開催されるセキュリティイベント、CODE BLUEでも獲得できます。

ウェビナーやセミナーは参加申し込みが必ず必要なので、それが自動的にエビデンスとして使えるというメリットがあります。また上記に挙げたイベントのほとんどがイベント主催者側から自動的にCPE登録が行われるので安心です。

3年間ありますので、上記のイベントをこまめにチェックして参加していれば、120ポイントは十分貯められるかと思います。

## 書籍、雑誌、ホワイトペーパーを読む
書籍または雑誌は1冊につき5ポイント、ホワイトペーパーは1枚につき1ポイント獲得できます。
比較的簡単に獲得できますが、エビデンスは少々注意が必要です。CPEハンドブック（日本語版A、Bともに）には、『書籍・雑誌のCPEクレジットは、書籍・雑誌本体、売上明細書、請求書、図書館の記録などの「所持ができる証
明」を保管してください。最低限、証明書にはタイトルと、書籍の場合は著者とISBN番号、雑誌の場合は出版社を
記載して保管します。』と記載されており、監査に備えてきちんとエビデンスを補完する必要があります。

ウェビナーやセミナーで基本的には十分稼げると思いますが、あとちょっと足りないという場合にはこちらで申請すると良いと思います。

## Hack The Box
Hack The Boxのサイトには以下のようにISC2のCPEポイントが獲得できる旨が記載されています。

https://help.hackthebox.com/en/articles/5188692-cpe-allocation-htb-labs

少しお金はかかりますが、VIPかVIP+に課金して、Retired Machinesを攻略することをお勧めします。
Retired MachinesであればWrite-Upが公式に公開されており、ペネトレーションテストに慣れていなくても攻略できます。
ただ慣れていないとそれなりに時間がかかってしまうため、ペネトレーションテストの練習ついでに稼ぐというのが良いかと思います。

## 重課金勢向け
予算が潤沢にある、実家から石油が出た、宝くじに当たった、ビットコインで一山当てたなどで潤沢な資金がある方におすすめなのは、CISSPの公式トレーニングです。確実にポイントを獲得でき、CISSPの範囲の復習もできます。その他、SANSなどのトレーニングや、BlackHatへの参加などでも獲得可能です。

## お勧めしない方法
番外編として、あまりお勧めしない方法も記載しておきます。

### 業務経験
業務経験を最大10CPE申請できますが、「独自性の高い」という条件が付いています。しかもプロジェクトの内容を要約して提出する必要があるため、機密性の高いプロジェクトはそもそも申請できません。（伏字を使いまくることはできるかもしれませんが・・・）
そもそもどこから「独自性の高い」とみなされるのかも不明瞭ですので、この活動は申請しない方が良いでしょう。
### 執筆
書籍、記事、ブログ、ホワイトペーパーなどの執筆で最大40CPE（書籍の著者の場合のみ）獲得できますが、ブログ以外はそう簡単に書けるものではないですし、そもそも40時間で本が書けるとは到底思えないのでコストパフォーマンスが非常に悪いです。たまたま執筆の仕事が舞い込んできたら申請するのが良さそうです。
なお同人誌が書籍として認められるかはわかりませんが、通常はハンドルネームで執筆すると思いますので、著者であるという証明が少々難しいかもしれません。

ちなみにブログは誰でも書けますが、「プロフェッショナルブログ」がどのレベルかはよくわかりません。後から認められなくなると困るようであれば申請しない方が無難かもしれません。ただ受理されるのであれば、最大10CPEなのでかなりコストパフォーマンスは高そうです。

# 余談
最後に余談として、ロールオーバーという仕組みがあります。更新日時の6か月前から取得したCPEポイントを次の3年間に持ち越せるという制度です。CISSPの場合は最大で40ポイントです。よって、120ポイント貯まったから終わりではなく、次の3年に向けてコツコツと貯めておくのが良さそうです。
日本時間でデータを簡単に確認！1NCEユーザー向けのIoT Lighthouseアプリを使ってみた

IoTデバイスのデータ使用量を把握するのって、結構面倒じゃないですか？

特に1NCEのポータルを使ってデータを確認しようとすると、情報が大雑把だったり、いちいちログインしなければならなかったり、ちょっとしたことがストレスになりがちです。それに、ポータルで表示される時間が現地時間じゃないと、どの日のデータなのかも分かりにくくなってしまいますよね。

iOSアプリ限定ではあるんですが、最近1NCEのAPIに対応した**IoT Lighthouse**というものを見つけたので、今回使ってみたいと思います。

このアプリを使えば、もっと手軽に、しかも現地時間でデータ使用量を日毎に確認できるんです。

https://apps.apple.com/jp/app/iot-lighthouse-for-1nce/id6502685366

## 簡単にデータをチェックしたい人にピッタリのアプリ

IoTデバイスのデータ使用量を毎日チェックしたい。でも、いちいちポータルにログインして、複雑なインターフェースを操作するのは面倒。そんなニーズにぴったりなのが、**IoT Lighthouseアプリ**です。このアプリは、簡単なAPIユーザーの登録だけで、すぐに使い始めることができます。

### 煩わしいポータルログインを回避

まず、最大のメリットは、ポータルにログインする手間を省けることです。1NCEポータルに比べて、IoT Lighthouseアプリはシンプルで直感的なデザイン。アプリを開いてすぐにデバイスの状況を確認できるので、時間の節約になります。

### 情報が見やすく、現地時間での表示にも対応

ポータルでの情報はどうしても大まかになりがちですが、IoT Lighthouseなら、データ使用量を日毎に細かく確認できます。また、現地時間でログを表示する機能があり、どの時間帯にどれだけのデータが使用されたのかを正確に把握できるのも便利です。タイムゾーンが違う地域で運用しているデバイスのデータも、現地時間で表示できるので混乱することがありません。

![スクリーンショット 2024-08-30 16.10.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072286/c167a81d-da60-5f00-39cf-a1ce69505eda.png)

### セキュアでクラウド不要

さらに、IoT Lighthouseアプリは、デバイスデータをローカルに保存します。これにより、クラウドに頼ることなく、セキュアにデータを管理できる点も魅力的です。データセキュリティが気になる方には、特におすすめのポイントです。

## 使い始めるのも簡単！手順を紹介

では、実際にIoT Lighthouseアプリを使い始める手順をご紹介します。

1. **アプリのインストールとAPIユーザーの登録**  
   まず、IoT Lighthouseアプリをデバイスにインストールします。1NCEポータルでAPIユーザーを作成し、APIキーを取得します。それをアプリに入力すれば、すぐに使用準備が整います。

https://portal.1nce.com/portal/customer/login

https://apps.apple.com/jp/app/iot-lighthouse-for-1nce/id6502685366

2. **デバイスの追加**  
   次に、1NCEポータルの「SIM管理」セクションで監視したいデバイスのICCIDをコピーし、アプリ内で新しいデバイスとして追加します。この手順をすべてのデバイスに対して行いますが、非常に簡単にできます。
   

3. **データの確認**  
   アプリのダッシュボードから、デバイスのステータスをすぐに確認できます。日毎のデータ使用量がグラフや表で表示されるため、一目でデータの傾向を把握できます。

## 実際に使ってみた感想

実際に**IoT Lighthouseアプリ**を使ってみると、煩わしい手間が省け、データ管理が非常に楽になりました。

![スクリーンショット 2024-08-30 16.09.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072286/d77e6eee-7b48-8d2b-1730-a22f5554bf7b.png)

ポータルに比べて、情報が細かく、現地時間での表示が可能なため、遠隔地のデバイスでも安心して管理できます。また、アプリ自体の操作が簡単で、すぐに必要な情報にアクセスできる点も大きな魅力です。

もし、1NCEのポータルに不満を感じているのであれば、**IoT Lighthouseアプリ**を試してみる価値は十分にあるでしょう。データ管理がよりスムーズになり、業務効率もアップすること間違いなしです。

https://apps.apple.com/jp/app/iot-lighthouse-for-1nce/id6502685366
LinuC101合格

# LinuC101

## ​受験場所
ピアソンVUEオンライン受験した。
システムチェックして、いろいろ写真撮ってアップして、チャットでやり直し求められて
もう一度写真上げ直して、すぐ試験始まった

開始時間前に試験始まったような気がする。
パソコンもってぐるりと一周部屋の中見せるってネットに情報があったけど
特にそんな作業なかった。手首も見せなかった。

ただ20分ぐらいかかった。体感ではもっと早くチェックインの準備したと思ったけど。

録画されている自分が写っているカメラの動きがワンテンポ遅い。
自分の環境のせいじゃない気がする。

## 感想
自信なかったけど大丈夫だった。

オンライン受験の方も不安だったけど、とてもよかった。
102もオンライン受験にしよ～っと。
Goのjson.Marshalで非公開フィールドも出力する方法

## 背景
こんにちは。エンジニアのKennieです。
以前の業務で、非公開フィールドを持つ構造体をシリアライズする必要がありました。その際にデフォルトでのMarshalJsonではシリアライズすることができなかったので、その際に学んだことを記載します。

## デフォルトのMarshalJsonを使用したコード例
まずは、Goのデフォルトの MarshalJSON を使ったシンプルなコード例を見てみましょう。以下のコードでは、公開フィールドを持つ構造体がJSONとしてシリアライズされています。

```go
package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	p := Person{Name: "Alice", Age: 30}
	data, err := json.Marshal(p)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(string(data))
}
```
出力結果
```
{"Name":"Alice","Age":30}
```

Ageを非公開にした場合
```go
type Person struct {
	Name string
	age  int
}
```

出力結果
```
{"Name":"Alice"}
```
このように、非公開フィールドはデフォルトのシリアライズ処理では無視されます。


## 非公開フィールドをシリアライズするためのカスタム MarshalJSON
非公開フィールドは、デフォルトの MarshalJSON ではシリアライズされません。そのため、カスタムの MarshalJSON を実装する必要があります。

```go
package main

import (
	"encoding/json"
	"fmt"
)

type person struct {
	Name string
	age  int // 非公開フィールド
}

func (p person) MarshalJSON() ([]byte, error) {
	return json.Marshal(struct {
		Name string `json:"Name"`
		Age  int    `json:"Age"`
	}{
		Name: p.Name,
		Age:  p.age,
	})
}

func main() {
	p := person{Name: "Alice", age: 30}
	data, err := json.Marshal(p)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println(string(data))
}
```
出力結果
```
{"Name":"Alice","Age":30}
```
ここでは age フィールドが非公開ですが、MarshalJSON メソッドをカスタム実装することで、非公開フィールドであっても JSON 出力に含めることができます。


## 実行の流れ
1. json.Marshal の呼び出し: json.Marshal 関数が呼ばれ、Person 構造体のインスタンスがシリアライズされます。これは Person 型のデータをJSON形式に変換するための関数です。

2. MarshalJSON のチェック: json.Marshal は Person 構造体が json.Marshaler インターフェースを実装しているかどうかを確認します。

3. カスタムメソッドの呼び出し: Person 構造体が json.Marshaler インターフェースを実装している場合、MarshalJSON メソッドが呼び出されます。このメソッドが返す結果がJSONとして出力されます。デフォルトのシリアライズ処理は無視され、Person 型に実装されたカスタムの MarshalJSON メソッドによるシリアライズが適用されます。

## 終わりに
開発の際に非公開フィールドを含む構造体をシリアライズする必要がありましたが、デフォルトの MarshalJSON メソッドではこれを実現できませんでした。そのため、カスタムの MarshalJSON メソッドを実装することで、非公開フィールドにアクセスし、シリアライズを行うことができました。今回の経験を通じて、MarshalJSON メソッドを用いたシリアライズ処理について理解が深まりました。
WireUI を導入すると JetStream のダークモードが無効になってしまう件の対処法

大まかな流れから。

## Laravel JetStream

```
php artisan jetstream:install livewire --dark
```

この `--dark` オプションをつけると、諸々がダークモードでインストールされます。
該当オプションは `vendor/laravel/jetstream/src/Console/InstallCommand.php` の中に書いてあるのでわかりやすいんですけど、

```php:vendor/laravel/jetstream/src/Console/InstallCommand.php
    protected function removeDarkClasses(Finder $finder)
    {
        foreach ($finder as $file) {
            file_put_contents($file->getPathname(), preg_replace('/\sdark:[^\s"\']+/', '', $file->getContents()));
        }
    }
```
と書いてある通り、設定ファイルの `dark:` のところを消してます。
で、どのファイルを対象にしているかというと `tailwind.config.js` です。

```javascript:tailwind.config.js
export default {
    dark: 'class',
};
```

消してるのはこの辺。

## WireUI


しかし、Livewire用の拡張UIの [WireUI](https://wireui.dev/) をインストールすると、ダークモードが解除されてしまいます。

```
composer require wireui/wireui
```

これの原因は `tailwind.config.js` に追記する下記の設定のせいです。

```javascript:tailwind.config.js
module.exports = {
    ...
    presets: [
        ...
        require("./vendor/wireui/wireui/tailwind.config.js")
    ],
    content: [
        ...
        "./vendor/wireui/wireui/src/*.php",
        "./vendor/wireui/wireui/ts/**/*.ts",
        "./vendor/wireui/wireui/src/WireUi/**/*.php",
        "./vendor/wireui/wireui/src/Components/**/*.php",
    ],
    ...
}
```
presets で `vendor/wireui/wireui/tailwind.config.js` を参照するようになってますね。
こいつの中をみると、

```javascript:vendor/wireui/wireui/tailwind.config.js
const colors = require('tailwindcss/colors')

/** @type {import('tailwindcss').Config} */
module.exports = {
    (略)

  darkMode: 'class',
  
    (略)
```

とまあ、ばっちり darkMode のパラメーターが復活してます。
こいつがあるとデフォルトでダークモードが有効になりません。

なので一手間、body タグにでもクラスをつけてあげるようにしましょう。
私の場合は layout に埋めてます。

```php:resources/views/layouts/app.blade.php
    <body class="font-sans antialiased dark">
```

dark の文字列を付けたり消したりすれば良いので、設定ファイルや env で制御したり、JavaScript でクラスを付けたり消したりすれば良いでしょう。

細かくは Tailwind のマニュアルを参考にどうぞ。
[Tailwind DarkMode](https://tailwindcss.com/docs/dark-mode#toggling-dark-mode-manually)
[PostgreSQL]FUNCTIONを使ってテーブルを動的に作成する

# はじめに
あるorganizationに紐づくusersテーブルをリストパーティションで作成したいなと思い、そういうAPIを作成しようかなと思っていたところpostgreSQLのFUNCTION機能を使えば、動的に作成できそうだと知ったので方法をまとめます。

前提として作ろうとしていたAPIは以下のようなものです。
1. organizationのレコードの挿入
2. 1で作成したorganizationのidでパーティション化されたusersテーブルを作成

ChatGPTに以上の仕様でAPI作成頼んだところ以下のようにSQLだけで対応できるようなコードが返ってきました。
恥ずかしながらFUNCTION知らなかったので、そもそも何をしているかメモしておきます。

他にも色々な仕様があるので、詳細はドキュメントを参照してください。
[PostgreSQL 15.4文書 CREATE FUNCTION](https://www.postgresql.jp/document/15/html/sql-createfunction.html)

そもそもこの記法はSQLを拡張したPL/pgSQLという言語で書かれており、複雑な処理をデータベースサーバ側で行うことができます。この複雑な処理（一般的なSQLで実行できない処理）をストアドプロシージャと呼びます。

```sql
CREATE OR REPLACE FUNCTION create_users_table()
RETURNS TRIGGER AS $$
BEGIN
    EXECUTE FORMAT('CREATE TABLE users_organization_%s (
        CHECK (organization_id = %s),
        LIKE users INCLUDING ALL
    )', NEW.id, NEW.id);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER create_users_table_trigger
AFTER INSERT ON organizations
FOR EACH ROW
EXECUTE FUNCTION create_users_table();
```

# FUNCTION
`CREATE OR REPLACE` で関数の作成 or 置き換えをしています。
ここではcreate_users_tableという名前の関数を作成しています。（引数等も取ることができます）

RETURNSで返り値の設定をします。
何かのトリガーで使いたい場合には、`RETURNS TRIGGER`とするのがお決まりのようです。
TRIGGERについては次項で説明します。

`RETURNS TRIGGER AS $$`の`$$`に関してはストアドプロシージャの起点、つまりコードブロックの始まりです。
最後の方にも`$$`がありますが、そちらは終点です。1行であればシングルクオートで置き換えられるようです。

最後の`LANGUAGE plpgsql`ですが、これはPL/pgSQLで記述されてることを示しているのかと思います。他にもplpythonu等といった拡張機能があるようです。

# BEGIN
ここで実行される関数の処理の中身を書きます。



# TRIGGER
以下のドキュメントより引用します。

> 作成したトリガは指定したテーブル、ビューまたは外部テーブルと関連付けられ、そのテーブルに特定の操作が行われた時に指定した関数function_nameを実行します。

[PostgreSQL 15.4文書 CREATE TRIGGER](https://www.postgresql.jp/document/15/html/sql-createtrigger.html)

何かの操作を起点に他の操作を行う関数的なものです。
今回は、organizationsテーブルに新しいorganizationがinsertされたら、挿入されたそれぞれのorganizationに対してcreate_users_table()を実行するようにしています。（`FOR EACH ROW`でそれを定義）

# まとめ
DB側で処理を入れると色々楽そうですね。管理が大変そうなので、まずは簡単なものを導入できればと思います。
[初心者][備忘録]Blazor Server におけるDbContextの使い方

# はじめに
[MicrosoftLearn](https://learn.microsoft.com/ja-jp/training/modules/interact-with-data-blazor-web-apps/5-exercise-access-data-from-blazor-components)でBlazorを学習していると、題材として`DbContext`というものが出てきて、今回おそらく初めて触りました。
使い方の注意点があったので、それをまとめます。

私は普段、C#でWindowsのデスクトップアプリを開発しています。
Webの技術を体系的に学び、しっかり活用した経験がなく用語の理解も怪しいので、超初歩的な内容になってます。

# DbContextについて
 `DbContext` は、[Entity Framework Core (EF Core)](https://learn.microsoft.com/ja-jp/ef/core/) の主要なクラスで、データベースとの接続、クエリの実行、データの追加・更新・削除など、いい感じにデータベースを扱えるようにしてくれるものみたいです。
大量に機能があったので、詳しくは[こちら](https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.entityframeworkcore.dbcontext?view=efcore-8.0)。

DbContextクラスを継承したクラスを定義することによって、アプリケーションのデータベースに特化した設定や操作を定義できます。

# DbContextの注意点
`DbContext`は、同時に使用できるよう設計されていません。特に、サーバーアプリケーションのようにスコープが長く続く場合には、DIコンテナから直接DbContextを取得して使用するのは不適切です。

### サーバーアプリではスコープが長く続くとは？
Blazorには、WebAssembly（クライアント側）とServer（サーバー側）の2つのホスティングモデルがあります。([こちら](https://qiita.com/minoura_a/items/9a605ffe598fae345aeb)の記事にまとめています。)
Blazor Server では、ユーザーのUI操作がサーバー上で処理され、結果がリアルタイムでクライアントに反映されます。各ユーザーのセッションがサーバー上で維持されるため、スコープが長く続きやすいです。

(セッション ≒ スコープだと思ってます。サーバー側とブラウザ側の間の通信が生きている間のことを指しています。リロードしたり、別タブ、別ブラウザなど、通信の単位が異なると、別スコープ(セッション)になる認識です。)

たとえば、ユーザーがブラウザを閉じない限り、1つのセッションが数十分、数時間続くこともあります。この長時間のセッションの間に、同じDbContextインスタンスが再利用されると、複数のリクエストが同時にアクセスする可能性があり、競合やデータの不整合が発生するリスクが高まります。
1操作ごとにDbContextの生成と破棄をするのが、望ましいとされているそうです。

# DbContextFactoryの利用
この問題を解決するためにDbContextFactoryを利用するのがよいです。
DbContextFactoryを使用すると、必要なときに新しいDbContextインスタンスを生成し、使用後すぐに破棄することができます。
これにより、スコープが長く続く環境でも安全にデータベースアクセスを行えます。

以下のように使います。
DbContextを継承したクラスを指定して、DbContextFactoryをDI登録します。
```csharp
// Program.cs
builder.Services.AddDbContextFactory<MyDbContext>();
```
利用したい箇所に`Factory`を注入します。`@inject`で可能です。
`DbContext`の利用箇所で`Factory`から生成します。
使用後は必ず破棄するよう、usingで囲います。
```csharp
// XXXConponent.razor
@inject IDbContextFactory<MyDbContext> DbContextFactory
@code {
    public async Task LoadDataAsync() {
        using var context = DbContextFactory.CreateDbContext();
        var data = await context.MyEntities.ToListAsync();
        // データ処理
    }
}
```

# まとめ
使い方の注意点はわかりましたが、DbContextを理解して使いこなすのが大変そうですね、、、。

# 参考
https://learn.microsoft.com/ja-jp/aspnet/core/blazor/blazor-ef-core?view=aspnetcore-8.0

https://learn.microsoft.com/ja-jp/training/modules/interact-with-data-blazor-web-apps/5-exercise-access-data-from-blazor-components
テストのためのサンプル

エンジニアの業務には欠かせない「テスト」。そんなテストではアップロードする画像などのサンプルデータが必要です。今回はそんなサンプルデータについてどんなものを用意しておけばいいのか、ジャンルごとに紹介していきます。

**目次**
1. 画像
1. 動画
1. ドキュメント

# 画像
画像は大きさ・容量・拡張子ごとにそれぞれ用意しましょう。ほとんどのシステムやウェブサイトでアップロードすることが最も多い画像はなるべくたくさんのレパートリーでサンプルを用意しておきましょう。

【例】
大きさ：大・中・小
容量：大・中・小
拡張子：jpg・png・gif
**合計：9枚**

# 動画
容量・拡張子ごとに用意しましょう。動画はアップロードする機会が少ないですが、解像度が少し違うだけで容量が大幅に変わったり、拡張子の違いで互換性が失われたりするので比較的多めのレパートリーを用意しておくと良いでしょう。

【例】
容量：大・中・小
拡張子：mp4・mpg・mov
**合計：6つ**

# ドキュメント
ドキュメントはこれまで紹介した二つとは違ってレパートリーは必要ないです。PDF一つあればテストとしては十分です。

# まとめ
今回はテスト用サンプルについてまとめました。
こういった事前準備をしておくことでさまざまな良い結果につながるのでぜひ空き時間など見つけて用意するように心がけましょう。
Power BIにおけるスタースキーマとは？データモデルの効率的な設計法

Power BIでのデータモデリングを効率よく行うためには、データの構造をしっかりと設計することが必要不可欠です。その中でも「**スタースキーマ**」は、データベース設計と分析において非常に効果的な方法の一つです。この記事では、PowerBIデータモデリングのベストプラクティスと言われるスタースキーマの基本概念から、Power BIでの実装方法までを解説します。

## 目次
[スタースキーマとは？](#スタースキーマとは？)
[スタースキーマの構造](#スタースキーマの構造)
[スタースキーマのメリット](#スタースキーマのメリット)
[PowerBIにおけるスタースキーマの実装](#PowerBIにおけるスタースキーマの実装)
[まとめ](#まとめ)

## スタースキーマとは？
スタースキーマは、データベース設計における一種のスキーマで、データを効率的に整理し、クエリのパフォーマンスを向上させるための設計手法です。名前の通り、星のように中心に「ファクトテーブル」、周囲に「ディメンションテーブル」を配置する形から名付けられています。

**ファクトテーブルとは：**
ファクトテーブルは、ビジネスの主要なデータ（例：売上、利益、注文数など）を格納するテーブルです。このテーブルは、数値的なデータや測定値を持ち、ビジネスのパフォーマンスを評価するための中心的な役割を果たします。

**ディメンションテーブルとは：**
ディメンションテーブルは、ファクトテーブルのデータに付随する「次元」や「属性」情報を持つテーブルです。例えば、顧客情報、製品情報、販売地域などがこれに当たります。これらのテーブルはファクトテーブルとリレーションシップを結び、データをより具体的に、また多角的に分析するための基盤となります。

## スタースキーマの構造
スタースキーマの構造は、以下のようになります。

**ファクトテーブル：**
中心に位置し、主に数値データや集計データを保持。
**ディメンションテーブル：**
ファクトテーブルの周りに位置し、ファクトテーブルの各行に対して具体的な属性情報を提供します。

この構造により、データのクエリや集計が効率的に行えます。ファクトテーブルとディメンションテーブルは、外部キーによってリレーションされ、これにより複雑なデータも簡単に処理できます。

## スタースキーマのメリット
スタースキーマは、そのシンプルな構造から多くのメリットがあります。

**パフォーマンスの向上：**
ファクトテーブルとディメンションテーブルの分離により、クエリのパフォーマンスが向上します。特に、大量のデータを扱う場合に、データの取得と集計がスムーズに行えます。

**分析の効率化：**
ディメンションテーブルにより、データの属性や次元を明確に定義できるため、複数の視点からデータを分析する際に非常に便利です。たとえば、地域別や期間別の売上分析などが簡単に行えます。

**メンテナンスの容易さ：**
データモデルがシンプルなため、データの追加や変更が容易で、メンテナンスが比較的簡単です。ディメンションテーブルを更新するだけで、新たな情報をすぐに分析に反映させることができます。

## PowerBIにおけるスタースキーマの実装
Power BIでスタースキーマを実装する際には、以下の手順に従ってデータモデルを構築します。

**データのインポート：**
まずは、ExcelやデータベースなどからPower BIにデータをインポートします。

**ファクトテーブルとディメンションテーブルの作成：**
インポートしたデータを元に、ファクトテーブルとディメンションテーブルを作成します。ファクトテーブルには、主に数値データや集計データを配置し、ディメンションテーブルには、関連する属性情報を配置します。

**リレーションシップの設定：**
Power BIの「モデルビュー」を使用して、ファクトテーブルとディメンションテーブルの間にリレーションシップを設定します。これにより、データの結びつきが定義され、クエリやビジュアルでのデータ統合が可能になります。


## 5. まとめ
スタースキーマは、Power BIにおけるデータモデリングの強力な手法であり、データのパフォーマンスと分析の効率を大幅に向上させることができます。ファクトテーブルとディメンションテーブルを効果的に活用することで、複雑なデータをシンプルかつ直感的に扱うことが可能になります。これにより、ビジネスの意思決定を支援するための有用なインサイトを迅速に得ることができるでしょう。
pythonのlist処理でちょっと使いづらい点 pop()

# プログラミングの際に思ったこと

pythonのpopがちょっと使いづらい
例えば、
l=Noneまたはl=[]のとき、
```python
i=l.pop()
```
としたら、pythonはエラーを返すが、無視して、iにNoneを返して、lはそのままにしていて欲しい。
実装すると、こう
```python
>>> po=lambda l:l.pop() if l else None
>>> l=['a','b']
>>> i=po(l)
>>> l
['a']
>>> i
'b'
>>> l=[]
>>> i=po(l)
>>> l
[]
>>> i
>>> 
>>> l=None
>>> i=po(l)
>>> l
>>> i
>>>

```
NULLの処理の仕方の問題ですにゃ。
MacでMicrosoft Remote Desktopを使うと半角￥が入力できない問題を解決できたのでプログラムを公開

## 解決した方法
Windowsに常駐アプリを作成しMacの¥が入力された場合に、Windowsの¥に変換する

## 背景
MacでWindowsにMicrosoft Remote Desktop を使用し、半角￥がWindowsのは半角￥マークじゃないことに気づく。  
（サクラエディタで\r\nを置換ができなかった）

## 対応方法
以下の流れでプログラムを作成します
- Windows常駐アプリを作成する
- 常駐アプリ側で、他のアプリがキー入力を受け付ける前に文字コードを解析する
- - キーボード → 常駐アプリ → 各アプリ
- 対象の文字コード（¥マーク）の場合、Windowsの¥マークに変換する
- そのほかの文字コードは、そのままアプリに戻す

## 公開プログラム
https://github.com/airspo-tachikawa/YenForMacRemote

## 備考
プログラムの中には、不要なプログラムが多々ありますが削除していただいて大丈夫です
exe 単体では配布しておりませんので、VS Code or Visual Studio で buildしてお使いください
Livebook 上で Zenoh の Pub/Sub 通信を体験してみる

## はじめに

SWEST 26 に参加してきました
（台風のため、泣く泣く現地参加を諦めオンライン参加）

https://swest.toppers.jp/phx/event

セッション「すべてが #Zenoh になる　〜柔軟にして軽量〜」でハンズオンを受けたので、Livebook でも Zenoh を動かしてみました

https://swest.toppers.jp/phx/event/program#s5b

登壇した高瀬さんのハンズオン資料はこちら

https://github.com/takasehideki/zenoh_swest26_trial/tree/main

この記事で実装したノートブックはこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/zenoh/zenohex_publisher.livemd

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/zenoh/zenohex_subscriber.livemd

## ブラウザ準備

Livebook を起動し、二つのウィンドウで新しいノートブックを開きます

通信結果が分かりやすいように上下に並べておきましょう

![スクリーンショット 2024-08-30 14.40.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/15ec900a-31bb-7614-0d12-e2aac3bbb46f.png)

この記事では上側の Publisher ノートブック、 下側を Subscriber ノートブックとして進めます

## Publisher ノートブックのセットアップ

Publisher ノートブックのセットアップセルで以下のコードを実行します

```elixir
Mix.install([
  {:zenohex, "~> 0.3"},
  {:kino, "~> 0.14"}
])
```

Zenohex は Elixir 用の Zenoh モジュールです

https://github.com/biyooon-ex/zenohex

Kino は Livebook の UI/UX 用にインストールしています（Zenoh には不要）

https://github.com/livebook-dev/kino

セッションを開き、 Publisher を作成します

```elixir
{:ok, session} = Zenohex.open()
{:ok, publisher} =
  Zenohex.Session.declare_publisher(session, "key/expression")
```

`"key/expression"` でキーを指定しています

Publisher と Subscriber で共通のキーを指定することで、 Pub/Sub 通信できます

Publish するメッセージを入力するためのテキストエリアを作ります

```elixir
input = Kino.Input.textarea("MESSAGE")
```

表示されたテキストエリアに適当な値を入力しておきましょう

![スクリーンショット 2024-08-30 15.12.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/ea5771a0-6c93-ccba-8d09-607dfa03e6ca.png)

次のセルにメッセージ送信のコードを入力し、実行はしないままにしておきます

```elixir
message = Kino.Input.read(input)

Zenohex.Publisher.put(publisher, message)
```

## Subscriber ノートブックのセットアップ

Subscriber ノートブックのセットアップセルで以下のコードを実行します
（Publisher ノートブックと同じ）

```elixir
Mix.install([
  {:zenohex, "~> 0.3"},
  {:kino, "~> 0.14"}
])
```

セッションを開き、 Subscriber を作成します

```elixir
{:ok, session} = Zenohex.open()
{:ok, subscriber} =
  Zenohex.Session.declare_subscriber(session, "key/expression")
```

`declare_subscriber` で Publisher と同じキーを指定しています

次に、受け取ったメッセージを表示するためのフレームを用意します

```elixir
frame = Kino.Frame.new()
```

![スクリーンショット 2024-08-30 15.15.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/4e2f1b00-ba4d-f253-b613-6008be0bc543.png)

次のセルにメッセージ受信のコードを入力し、実行しないままにしておきます

```elixir
case Zenohex.Subscriber.recv_timeout(subscriber, 10_000_000) do
  {:error, :timeout} ->
    nil
  {:ok, msg} ->
    Kino.Frame.append(frame, Kino.Markdown.new(msg.value))
end
```

`recv_timeout` の第２引数はタイムアウトのマイクロ秒指定(10秒)です

## Pub/Sub の実行

Subscriber ノートブックの最後のセルを実行した後、すぐに Publisher ノートブックの最後のセルを実行しましょう

メッセージが受信され、フレームに表示されます

![zenoh.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/65f9ab48-7a08-8b2f-1c51-61d97f8ddb93.gif)

## まとめ

Zenohex を使うことで、 Zenoh による Pub/Sub 通信が実行できました

非常に軽量で高速ということなので、いろいろなことに使ってみたいと思います
[初心者][備忘録] BlazorのAppStateパターンでアプリ全体でデータを共有する

# はじめに
Blazorを使っていると、「あれ？このデータを全体で共有したいんだけど…」と思うことがあるかもしれません。
そんな時に役立つのがAppStateパターンです。
このパターンを使えば、どのコンポーネントからでも共通のデータにアクセスできます。
今回は、その方法を学習したのでまとめます。

私は普段、C#でWindowsのデスクトップアプリを開発しています。
Webの技術を体系的に学び、しっかり活用した経験がなく用語の理解も怪しいので、超初歩的な内容になってます。

# AppStateパターンの基本実装
アプリ全体で使いたいデータをプロパティ定義したクラスを作成し、それをサービスクラスとしてDIコンテナに登録します。それをデータを使いたい場所に注入すればどこからでもそのデータにアクセスできるというわけです。

例えば、以下のようにアプリ全体で使いたいプロパティを定義した、AppStateクラスを用意します。
```csharp
public class AppState {
    public string SharedData { get; set; }
}
```
定義したクラスをサービスとしてDIコンテナへ登録します。
```csharp
// Program.cs
builder.Services.AddScoped<AppState>();
```
ここまでやれば、準備完了です。
次に、AppStateをコンポーネントから使用します。
以下のように`@inject`をコンポーネントファイルの先頭に書くこと、DIに登録したクラスを使用できます。
```csharp
// XXComponent.razor
@inject AppState appSate;
@code {
    protected override void OnInitialized() {
        appState.SharedData = "Updated Data";
    }
}
```
# スコープの違いと選び方
先ほどの例では、DI登録する際に、`AddScoped`というメソッドを使いました。
BlazorのDIコンテナには、Scoped, Singleton, Transient という3つのスコープがあります。
それぞれの違いは以下です。

## Scoped
現在のスコープ（通常はブラウザセッション）内で状態を保持するため、ページを切り替えても状態を保持します。
ログイン状態や一時的なユーザー設定など、ページのリロードや新しいタブを開くと消えても良いデータに使います。

例えば、ショッピングカート機能では、ユーザーがブラウザを閉じるか、リロードするまで選んだ商品は保持されるべきです。Scopedスコープを使えば、セッション中の情報を保持できます。

## Singleton
アプリケーションのライフタイム全体でデータを共有したい場合に使用するもので、現在のスコープに限らずリロードしたりしても、状態を保持します。
アプリケーション全体で共通して使う設定データや、統計情報などです。

例えば、サイト全体で使用されるカスタムテーマ設定や、ユーザーの選択した言語設定などに使えると思います。

## Transient 
各リクエストごとに新しいインスタンスが生成されるため、状態は保持されず、ページ切り替えで状態が消えます。
主に一時的な操作に使います。

※AppStateパターンにおいて、内部変数のような扱いの`Tramsient`のスコープを使うことは無いかもしれませんが、スコープの1種ではあるため、列挙しました。

# さいごに

前回の親から子コンポーネントのパラメータの受け渡し加えて、AppStateパターンも使えれば、Blazorにおけるパラメーターの取り扱いはばっちりじゃないでしょうか？？
私が他を知らないだけかもしれませんが…

# 参考
https://learn.microsoft.com/ja-jp/training/modules/interact-with-data-blazor-web-apps/6-share-data-in-blazor-applications
CData Syncから Databricks に同期する際の CONSTRAINTS_REQUIRE_UNITY_CATALOG エラーへの対応方法

## 概要

CData Sync というサービスにて Databricks へデータを同期する際に発生した下記エラーへの対応方法を共有します。原因としては Databricks コネクションのデフォルトが`hive_metastore`となっているため、カタログに修正が必要なようです。

> 0] Error running query: [CONSTRAINTS_REQUIRE_UNITY_CATALOG] com.databricks.sql.transaction.tahoe.DeltaAnalysisException: [CONSTRAINTS_REQUIRE_UNITY_CATALOG] Table constraints are only supported in Unity Catalog.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c0068952-c9f5-5734-94ef-80dfae579cf3.png)

下記の記事が参考になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/fe56cd58-e576-590c-b15b-f21f50de58fc.png)

引用元：[Databricks のUnity Catalog に SAP S/4HANA Cloud データをノーコードでレプリケーション | CData Software Blog](https://www.cdata.com/jp/blog/sapgateway2databricks)

## エラーの再現方法

### 1. Databricks へ主キーが設定されているテーブルを同期するタスクを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/82794c00-9680-b2e9-8e3a-edaf6474303d.png)

### 2. ジョブを実行するとエラーが発生

> [0] Error running query: [CONSTRAINTS_REQUIRE_UNITY_CATALOG] com.databricks.sql.transaction.tahoe.DeltaAnalysisException: [CONSTRAINTS_REQUIRE_UNITY_CATALOG] Table constraints are only supported in Unity Catalog.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c0068952-c9f5-5734-94ef-80dfae579cf3.png)

## エラーへの対応方法

### 1. CData Sync にて`Connections`タブから作成済みの Databricks コネクションを表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/7dd110f7-be48-0391-b491-6b3a1f04ad4c.png)

### 2. `Schema`領域を検索して`catalog`に`hive_metastore`が設定されていることを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c70b898f-3bbe-7e5b-b3b3-7043021b3338.png)

### 3. `catalog`を同期先のカタログに変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/3f425a33-57e9-c00a-f89f-fbf68705183f.png)

### 4. （任意） タスクにて`Schema Name`を任意のスキーマに変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/caf16a81-10dd-8f5e-fac9-fb9f42171a39.png)

### 5. データ同期のタスクを実行して正常終了することを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/013fa734-9e2a-a1ee-07cf-1ddc4db6c22c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/6c1117f7-05e6-8352-f93f-1fd8fb351d91.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a9b59ed4-2a39-9314-6621-19c1b2b761dd.png)
[初心者][備忘録]Blazorで親コンポーネントから子コンポーネントへパラメータを渡す方法

# はじめに
Blazorはコンポーネントベースのフレームワークで、再利用可能なUIコンポーネントを簡単に作成できます。
最近、親子のコンポーネント間でデータを共有する方法を学習したので、まとめておきます。

私は普段、C#でWindowsのデスクトップアプリを開発しています。
Webの技術を体系的に学び、しっかり活用した経験がなく用語の理解も怪しいので、超初歩的な内容になってます。

# コンポーネントパラメータ (Component Parameters)
直接親子関係があるコンポーネント同士は、この方法でパラメーターを渡すのが適しています。

例えば以下のように実装します。
```csharp
// 子コンポーネント (ChildComponent.razor)
<h3>@Message</h3>

@code {
    [Parameter]
    public string Message { get; set; }
}

// 親コンポーネント (ParentComponent.razor)
<ChildComponent Message="Hello from Parent!" />
```
`[Parameter]` 属性を使って子コンポーネント内に公開プロパティを定義し、親コンポーネントでそのプロパティに値を渡します。
すると、子コンポーネントで親から渡ってきた値を使用できます。

# カスケードパラメータ (Cascading Parameters)
親から孫以下の子コンポーネントにパラメータを渡す場合、孫以下までバケツリレーのように複数のコンポーネントを経由するのは手間です。
こういった場合にこの方法を使用すると、手間なくパラメーターを渡せます。

例えば以下のように実装します。
```csharp
// 親コンポーネント (ParentComponent.razor)
<CascadingValue Value="parentValue">
    <ChildComponent />
</CascadingValue>

// 子コンポーネント (ChildComponent.razor)
<h3>@ParentValue</h3>

@code {
    [CascadingParameter]
    public string ParentValue { get; set; }
}
```
`<CascadingValue>` タグを使うことで、指定した値がすべての子孫コンポーネントに自動的に渡されます。受け取る側では [CascadingParameter] 属性を使ってパラメータを取得します。
これにより、深い階層のコンポーネントにもデータを渡せます。

`<CascadingValue>` タグで指定した`Value`は、型で判定しています。
そのため、その型のパラメータが1つであれば上記実装で問題ないですが、複数ある場合は以下のように`Name`を指定する必要があります。
```csharp
// 親コンポーネント (ParentComponent.razor)
<CascadingValue Name="parent" Value="parentValue">
    <ChildComponent />
</CascadingValue>

// 子コンポーネント (ChildComponent.razor)
<h3>@ParentValue</h3>

@code {
    [CascadingParameter(Name = "parent")]
    public string ParentValue { get; set; }
}
```

また、以下のように参照型も使用できます。

```csharp
// 親コンポーネント (ParentComponent.razor)
<CascadingValue Name="UserData" Value="userData">
    <CascadingValue Name="AppSettings" Value="appSettings">
        <ChildComponent />
    </CascadingValue>
</CascadingValue>

@code {
    private UserData userData = new UserData { Name = "John Doe", Age = 30 };
    private AppSettings appSettings = new AppSettings { Theme = "Dark Mode", Language = "en" };
}

// 子コンポーネント (ChildComponent.razor)
<div>
    <h3>Child Component</h3>
    <p>User Name: @userData.Name</p>
    <p>App Theme: @appSettings.Theme</p>
</div>

@code {
    [CascadingParameter(Name = "UserData")]
    private UserData userData { get; set; }

    [CascadingParameter(Name = "AppSettings")]
    private AppSettings appSettings { get; set; }
}

// UserSettings.cs
public class UserData
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// AppSettings.cs
public class AppSettings
{
    public string Theme { get; set; }
    public string Language { get; set; }
}
}
```

# さいごに
プロパティアクセスではなく、属性とNameで判別しているのだとは思いますが、
何回見ても、カスケードパラメーターが`private`でよいのがなんとなく気持ち悪いです。

親→子へのパラメーターの渡し方はこれでカンペキですね！

# 参考

https://learn.microsoft.com/ja-jp/training/modules/interact-with-data-blazor-web-apps/6-share-data-in-blazor-applications
第13回 オモシロAIごった煮会　イベント参加レポート

（電池切れて下書きで放置していたものです。投稿時点では古い記事になりますが公開します）

## 本日の勉強会
https://omoshiroai.connpass.com/event/323123/

いつものやつです

## LT
### Dify
https://dify.ai/

RAG開発きついよね
→ノーコードでチャットボット作れるよ！ そう、Difyならね

#### 事前準備
- OpenAPIとDifyを連携するので、それぞれのサービスに登録のこと
- たとえばQ&Aなどの対応表を作っておいてテキストでアップロードする

#### できること
- 作ったチャットbotをWebサイトにうめこむ事ができる
  - SmallChatのAI版っぽい
- 問い合わせをSlackに送れる
  - SmallChatを置き換えられそう！
- 対話のロギングができる

#### 懸念
- セキュリティの課題はある
- Difyの料金とOpenAPIの料金は別なので、運用は考える必要ありそう

### Google NotebookLM
https://notebooklm.google/

自分の脳みそをトレースして作る、という感覚で使ってるよ！
過去に書いた経歴書をまとめて送り込むだけでいい感じに作り変える事ができる？
（もちろん、変えてはならない内容は担保した上で）

#### コツ
- 揮発性の高い情報と長期的に保持したい情報がある
- 

#### 事例
- 新入社員向けのFAQ
- 記事
- チャットのサマリー
- 社内チャットbot

#### デモの所感
- これもRAG開発っぽい
- なんかすごい技術っぽいけど、完全に仕事として依頼できるか？という観点でみると信頼性が課題
  - ハルシネーションを起こさないだけ、信頼性はありそう

### Suno AI 3.5
https://suno.com/

参加者全員が知ってる内容というのもあり、suno自体の解説は省略

- 元の音源から新たに曲を作れるようになった
  - 音声入力もできるよ！
  - 音源ファイルからも曲が作れるよ
Moodle構築備忘録

## Apache2インストール
```sudo apt -y install apache2```

## 設定ファイルの変更
```$ sudo nano /etc/apache2/conf-enabled/security.conf```
25行目：変更
ServerTokens Prod
```$ sudo nano /etc/apache2/mods-enabled/dir.conf```
2行目：ディレクトリ名のみでアクセスできるファイル名を設定
DirectoryIndex index.html index.htm
```$ sudo nano /etc/apache2/apache2.conf```
70行目：サーバー名追記
ServerName IPアドレス
```$ sudo nano /etc/apache2/sites-enabled/000-default.conf```
11行目：管理者アドレス変更
ServerAdmin hoge@hoge.com

## サーバ再起動
```sudo systemctl restart apache2```

## PHPインストール
```sudo apt -y install php8.1```

## 拡張モジュールインストール
```$ sudo apt -y install php8.1-curl php8.1-zip php-mysqli php8.1-xml php8.1-gd```
```$ sudo apt -y install php8.1-intl php8.1-xmlrpc php8.1-soap php8.1-mbstring```

## サーバ再起動
```sudo systemctl restart apache2```

## MariaDB10.4インストール
```$ sudo apt -y install mysql-server-10.4```
```$ dpkg -l | grep -I mariadb```

### セキュリティ設定
```$ sudo mysql_secure_installation```
+ Switch to unix_socket authentication = n
+ Change root password = n
+ Remove anonymous users = y
+ Disallow root login remotely = y
+ Remove test database = y
+ Reload = y

#### ログイン設定（Mysqlにログイン）
```$ sudo mysql```

```mysql> ALTER USER 'root'@'localhost' IDENTIFIED VIA mysql_native_password USING PASSWORD ("password");```
```mysql> FLUSH PRIVILEGES;```

## MariaDBにMoodle用データベース作成
### Moodle用データベース作成
```$ mysqladmin -u root -p create moodle```

### Moodle用ユーザ作成
```$ mysql -u root -p```
```Enter password: ********```
```mysql> create user moodle identified by 'password';```
```mysql> grant all on moodle.* to moodle;```

## Moodle(4.1)インストール
```$ sudo wget https://download.moodle.org/download.php/stable404/moodle-latest-***.tgz```

### /var/www/html直下に解凍
```$ cd /var/www/html```
```$ sudo tar zxvf (ダウンロードdir)/ moodle-latest-**.tgz```
```$ sudo chown -R root.root moodle```
```$ sudo chmod -R 775 moodle```
```$ sudo mkdir /var/www/moodle_files```
```$ sudo chown root.www-data /var/www/moodle_files```
```$ sudo chmod -R 774 /var/www/moodle_file```
+ ディレクトリ構造が変わると図形等がバックアップした際に失われるので注意

### Moodle初期設定
+ インストールしたURLにアクセス
+ 初期設定
	Language = 日本語(ja)
+ パスの確認
	データディレクトリ = /var/www/moodle_files
+ データベースドライバの選択
	タイプ = MariaDB
+ データベース設定
	データベースホスト = localhost
	データベース名 = moodle
	データベースユーザ = moodle
	データベースパスワード = ********
	テーブル接頭辞 = mdl_
+ インストーレーション
　　= Continue
* Installation – Moodle 4.4.2+
	= 続ける
+ インストレーション
	= 続ける
+ 最高管理者アカウント作成
	（項目入力）
	「プロファイルを更新」
+ サイト名の入力
	長いサイト名 = ****
	短縮名 = ****
	デフォルトタイムゾーン = アジア/東京
	「変更を保存する」