OmniAICreator/Qiita-1.07M huggingface dataset:
Segmentation関連でお世話になっている物個人的まとめ

# どんな記事？
最近セグメンテーションを使い始めた私がお世話になったライブラリやリポジトリをまとめたメモ帳です．

## ライブラリ
### MMDetection & MMSegmentation
- `MMDetection` : Object Detectionに加えて，Instance Segmentationなどの手法をまとめたライブラリ．チュートリアルと実装アルゴリズムが充実している．https://mmdetection.readthedocs.io/en/latest/
- `MMSegmentation` : Semantic Segmentation手法をまとめたライブラリ．実装アルゴリズムは充実しているが，MMDetectionに比べてチュートリアルが少なかった気がする．使い方は大体同じなので分からないことがあったらMMDetectionの方を参照してみてもいいかもしれない．https://mmsegmentation.readthedocs.io/en/latest/
- この二つはOpenMMLabが開発・管理しており，これまた同じ開発元の`MMCV`(https://mmcv.readthedocs.io/en/latest )というコンピュータビジョンライブラリを使用して作られている．ソースコードをたどると大体MMCVにたどり着く．
- これらはPyTorchを用いて開発されており，Detection，Segmentation以外にも様々な分野のライブラリが提供されており，いろいろできる．

### image-to-coco-json-converter
- https://github.com/chrise96/image-to-coco-json-converter
- こいつはSemantic Segmentation用のマスク画像をInstance Segmentation用の COCO フォーマットに変換してくれる．
    - 前述の MMDetection は COCO フォーマットに対応しており，この形式にするだけでデータセットが完成し，訓練とテストがすぐにできるようになる．
- 使い方は `create-custom-coco-dataset.ipynb`を自分好みに書きかえるだけ．
    - ソース内category_colorsはパッと見カテゴリから色に対応させる辞書かなと思ったけど，実際はマスク画像内の色からカテゴリに対応させている．マスク画像がグレースケールで，ラベル 1 が 窓 とかだった場合は，"(1, 1, 1)": "window" とか書けばよし．
- 時間がかかる場合があるので，データがいっぱいあったり画像が大きいときは`PyPy`を使うとかなり時間を節約できる．
    - `conda`を使って PyPy の環境を構築することができるのを最近知りました．わざわざビルドする必要がなく便利ですし，パッケージインストール時にアップグレードされるパッケージがあれば教えてくれるのでありがたいですね．

## サイト
### CVMLエキスパートガイド
- https://cvml-expertguide.net/
- 日本語の情報の方がやっぱり速く読めるし理解が簡単．
    - 日本語情報を漁ってから論文を読むのがやりやすいと感じる．

### Papers with Code
- https://paperswithcode.com/
- ベンチマークごとのランキングがまとめられており，GitHubリポジトリのリンクもしっかり揃ってる．
- 各ベンチマークごとにトレンドとなっている手法がわかる．

# おわりに
なんだこれ
Git flow の手順備忘録

# 本記事の目的
* Git flow でブランチ管理を簡略化しているものの，慣れないうちやしばらく触っていないと「どんな順番でコマンド叩いてたっけ...」となり，何度も調べ直すので，自分用に手順の備忘録を残す

# 前提
* `remotes/origin` は Github へ
* `master` ブランチ上では直接作業をしない
    * 微修正は `develop` ブランチで作業
    * 大きな修正は `feature` ブランチで作業
        * いくつか並列しても OK
    * リリースに際した調整は `release` ブランチで作業
        * バージョン管理，メタデータ修正，他
    * 直ちに修正すべき簡易バグは `hotfixes` ブランチで作業
* リリース作業は個人で行う（途中で `push/pull` しない）
  （実際の IT 現場でどうしているのかは知見がありません...）

# 手っ取り早く結論
### `feature` ブランチの作成から `develop` ブランチへのマージまで

```shell
## Initialization
$ git pull origin
$ git flow feature start FEATURE_NAME

## Add the feature branch to the remote
$ git flow feature publish FEATURE_NAME

## Save changes and push to the remote
$ git commit -am "Some comments"
$ git push

## Pull from the remote and rebase
$ git flow feature pull
$ git flow feature rebase

## Finish changes
$ git flow feature finish FEATURE_NAME
$ git push
$ git fetch -p
```

### `release` ブランチの作成から `develop, master` ブランチへのマージまで

```shell
## Initialization
$ git flow release start VERSION_NUMBER

## Save minor changes
$ git commit -am "Some comments"

## Finish changes
$ git flow release finish FEATURE_NAME
$ git push

## Fetch the latest remote branches
$ git fetch -p
```

`hotfixes` も同様．

# 参考
Git-flow の図解

http://danielkummer.github.io/git-flow-cheatsheet/

Git-flow の公式見解

https://nvie.com/posts/a-successful-git-branching-model/
Non-Decreasing Digits

http://acmgnyr.org/year2010/e.pdf

## 難易度
### Midium

## アプローチ
### DP

```java
import java.io.*;
import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) throws IOException {
        BigDecimal[][] temp = new BigDecimal[65][10];

        temp[0][0] = BigDecimal.ONE;
        temp[0][1] = BigDecimal.ONE;
        temp[0][2] = BigDecimal.ONE;
        temp[0][3] = BigDecimal.ONE;
        temp[0][4] = BigDecimal.ONE;
        temp[0][5] = BigDecimal.ONE;
        temp[0][6] = BigDecimal.ONE;
        temp[0][7] = BigDecimal.ONE;
        temp[0][8] = BigDecimal.ONE;
        temp[0][9] = BigDecimal.ONE;

        temp[1][0] = BigDecimal.valueOf(10);
        temp[1][1] = BigDecimal.valueOf(9);
        temp[1][2] = BigDecimal.valueOf(8);
        temp[1][3] = BigDecimal.valueOf(7);
        temp[1][4] = BigDecimal.valueOf(6);
        temp[1][5] = BigDecimal.valueOf(5);
        temp[1][6] = BigDecimal.valueOf(4);
        temp[1][7] = BigDecimal.valueOf(3);
        temp[1][8] = BigDecimal.valueOf(2);
        temp[1][9] = BigDecimal.valueOf(1);

        for (int i = 2; i <= 64; i++) {
            for (int j = 9; j >= 0; j--) {
                if (j == 9) {
                    temp[i][j] = BigDecimal.ONE;
                    continue;
                }
                temp[i][j] = temp[i - 1][j].add(temp[i][j + 1]);
            }
        }

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int userInput = Integer.parseInt(br.readLine());

        for (int i = 0; i < userInput; i++) {
            int input = Integer.parseInt(br.readLine());
            bw.write(temp[input][0].toString());
            bw.write("\n");
        }
        bw.flush();


    }
}

```
型が異なる変数へ代入する

```
interface ArrayDevice {
  deviceType: string;
  deviceName: string;
  deviceId: number;
  XXXZ: {
    CCXName: string;
    CCXNumber: number;
  };
}

let nestedDevices = [
  {
    type: "Type1",
    name: "Device1",
    id: 1,
    info: {
      sampleName: "Sample1",
      sampleNumber: 1,
    },
  },
  {
    type: "Type2",
    name: "Device2",
    id: 2,
    info: {
      sampleName: "Sample2",
      sampleNumber: 2,
    },
  },
];

let myArrayDevice: ArrayDevice[] = nestedDevices.map((device) => {
  return {
    deviceType: device.type,
    deviceName: device.name,
    deviceId: device.id,
    XXXZ: {
      CCXName: device.info.sampleName,
      CCXNumber: device.info.sampleNumber,
    },
  };
});

console.log(myArrayDevice);


//LOG
[
  {
    deviceType: "Type1",
    deviceName: "Device1",
    deviceId: 1,
    XXXZ: {
      sampleName: "Sample1",
      sampleNumber: 1,
    },
  },
  {
    deviceType: "Type2",
    deviceName: "Device2",
    deviceId: 2,
    XXXZ: {
      CCXName: "Sample2",
      CCXNumber: 2,
    },
  },
]





```
kaggleに初チャレンジ

機械学習やプログラミングを始めたての筆者が自分なりに試行錯誤やさまざまな著書などを参考にして自力でkaggleのコンペに挑戦した時のコードをまとめたものです。
初めてブログ記事を書きますので見にくいと思いますがご容赦ください。


```python
#ライブラリのインポート
import pandas as pd
import numpy as np
```
```python
#csvファイルの読み込み
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
```
```python
#学習データの先頭５行を読み出し
train.head()
```
```python
#テストデータの先頭５行を読み出し
test.head()
```

全体のデータ数とshapeも学習の参考になるのかも。と思い下記のコードでshapeを調べました。

```python
print(train.shape)
print(test.shape)
```

結果は
学習データ・・・891,12
テストデータ・・・418,11

ということが分かりました。
続いて、学習用データとテストデータのデータ要約を確認するために下記の作業。

```python
#カラム名、欠損値の有無、データタイプなどを確認。
train.info()
```
```python
#カラム名、欠損値の有無、データタイプなどを確認。
test.info()
```
```python
#学習データの統計情報を表示
train.describe()
```
```python
#学習データを特徴量と目的変数に分ける
train_x = train.drop(["Survived"], axis=1)
train_y = train["Survived"]
```
```python
#特徴量をそのままコピー
test_x = test.copy()
```

■予測にあまり適していないと思われる変数を除外しています。
```python
from sklearn.preprocessing import LabelEncoder

#PassengerIdを削除
train_x = train_x.drop(["PassengerId"], axis=1)
test_x = test_x.drop(["PassengerId"], axis=1)

#Name, Ticket,Cabinを削除
train_x = train_x.drop(["Name", "Ticket", "Cabin"], axis=1)
test_x = test_x.drop(["Name", "Ticket", "Cabin"], axis=1)

for i in ["Sex", "Embarked"]:
    le = LabelEncoder()
    le.fit(train_x[i].fillna("NA"))
    train_x[i] = le.transform(train_x[i].fillna("NA"))
    test_x[i] = le.transform(test_x[i].fillna("NA"))
```

```python
#xgboostを使ってモデルの学習と予測
from xgboost import XGBClassifier

model = XGBClassifier(n_estimators=20, random_state=71)
model.fit(train_x, train_y)

pred = model.predict_proba(test_x)[:, 1]
pred_label = np.where(pred > 0.5, 1, 0)

print(pred)
print(pred_label)
```


ここまでが私が色々調べながら「Titanic」へエントリーしたコードの記述です。
自分でチャレンジすることで、色んなメソッドの役割を理解することができました。



学習を初めて２ヶ月しか経っていませんが、私の中では自力で一つのモデルを作り成果としてエントリーできたのが非常に嬉しかったです。



結果は、、、７６%でした。
![スクリーンショット 2023-02-02 15.16.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124100/baa15a7b-b77f-bb39-8df5-3c0de71b43f7.png)

上位の方のコードを拝見させていただくと、かなり勉強になることばかりです。
次回の成果物は可視化作業も含めて精度の向上を目指し頑張っていこうと思います。

ここまでご覧いただいてありがとうございます。
次回も何かしらの成果をアップできればと思います。
【AWS】IAMでスイッチロールを利用して複数アカウントにログインする方法

# 概要
* AWSのIAMで、スイッチロールを利用して顧客のAWSアカウントを利用しました。その際の設定手順について備忘も兼ねて記載します。

## 前提
* 自分の会社を「会社A」、顧客の会社を「会社B」として記載してます。
* 踏み台アカウント（ジャンプアカウント）を利用して、スイッチロールします。一つの入り口からのみ複数環境（ステージング・本番・検証など）にスイッチできる、セキュアな方式です。
* 踏み台アカウントについて、顧客BからID/Passは連携済とします（MFA認証のキーも）。より強いセキュリティ権限を付与したい場合は別途検討されてください。

# AWSリソース図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/0c206efe-3cfc-69df-0adf-66b5a8539bd0.png)

# 実行手順
* ①ロールを作成する(会社B)
* ②スイッチロールを設定する(会社B)
* ③スイッチロールで切り替えを行う(会社A)

## ①ロールを作成する(会社B)
* IAM画面→ロールの作成→クロスアカウントアクセスを選択
* スイッチロールを許可したいアカウントIDを記入
* 任意のアクセスポリシーをアタッチ

## ②スイッチロールを設定する(会社B)
* インラインポリシーを選択してカスタムポリシーを作成
* Resourceに上記で作成したロールのARNを入力

## ③スイッチロールで切り替えを行う(会社A)
* 連携済のID、PASS、MFA認証キーを利用してログイン
    * なお、2022年11月から複数デバイスの対応ができるようになっています
    * 参考記事：[AWS Identity and Access Management で複数の多要素認証 (MFA) デバイスのサポートを開始](https://aws.amazon.com/jp/about-aws/whats-new/2022/11/aws-identity-access-management-multi-factor-authentication-devices/)
* 「ロールの切り替え」を選択→アカウント名・ロール名を記入して切り替え
* 表示名は任意のもので可能（わかりやすいものがいいですね）
* 右上にピンク色とかでロール名が表示されていれば、無事に切り替え出来ています。

## 参考記事
* [Swith Roleで複数のAWSアカウント間を切替える](https://qiita.com/yoshidashingo/items/d13a9b17f111d5d91a2e)
* [【AWS】IAMのスイッチロールの設定方法](https://business.ntt-east.co.jp/content/cloudsolution/column-try-25.html)
Ruby on Rails – local で RAILS_ENV=production でサーバーを起動してもつながらない場合 (コンソールにも何も表示されない)


# 解決

production環境では画面にもコンソールにもエラーが出力されていないのがデフォルトのようだ。これが理由だった。

環境変数を指定してコンソールにログを出力することで解決した。
これで単にルーティングエラーが起きていることが分かるようになった。

```
RAILS_LOG_TO_STDOUT=1 RAILS_ENV=production rails server
```

# コンソール出力の例


```
RAILS_LOG_TO_STDOUT=1 RAILS_ENV=production rails server
=> Booting Puma
=> Rails 7.0.4.2 application starting in production
=> Run `bin/rails server --help` for more startup options
W, [2023-02-06T22:12:58.122114 #44354]  WARN -- : You are running SQLite in production, this is generally not recommended. You can disable this warning by setting "config.active_record.sqlite3_production_warning=false".
Puma starting in single mode...
* Puma version: 5.6.5 (ruby 3.1.2-p20) ("Birdie's Version")
*  Min threads: 5
*  Max threads: 5
*  Environment: production
*          PID: 44354
* Listening on http://0.0.0.0:3000
Use Ctrl-C to stop
I, [2023-02-06T22:13:00.524139 #44354]  INFO -- : [ad3808c3-b91b-41ba-9cb1-39c08562f558] Started GET "/" for 127.0.0.1 at 2023-02-06 22:13:00 +0900
F, [2023-02-06T22:13:00.525240 #44354] FATAL -- : [ad3808c3-b91b-41ba-9cb1-39c08562f558]
[ad3808c3-b91b-41ba-9cb1-39c08562f558] ActionController::RoutingError (No route matches [GET] "/"):
[ad3808c3-b91b-41ba-9cb1-39c08562f558]
```

# ブラウザのエラー画面表示

configでブラウザにもエラー画面を表示するように出来る

`config/environments/production.rb`

```
  config.consider_all_requests_local       = true
```

もちろん本当のproduction環境では設定すべきではないので動作テストにだけ利用すること


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
eLearnSecurity Junior Penetration Tester, eJPTv2 〜勉強方法と試験の感想〜

#### 2023年1月にeLearnSecurity Junior Penetration Tester(eJPTv2)という48時間のペネトレーションテスター向け試験を受けて無事合格しました。
![賞.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2180843/3e4d538c-e506-e43e-7540-b2334c7ee56a.png)

#### eLearnSecurity Junior Penetration Testerの試験概要については詳しい記事があるので（下記参照）、バージョン2の試験で変わったこと、勉強方法、試験の感想について共有します。

①https://qiita.com/v_avenger/items/245fb0b23de4e206396e
②https://shinobe179.hatenablog.com/entry/2022/09/23/015454

### eLearnSecurity Junior Penetration Tester　v2(以下、eJPTv2）は2022年夏に公開された、48時間のペネトレーションテスター向け認定資格です。
ホスト、ネットワーク、および Web アプリケーションのペネトレーションテストを使用した評価方法と監査を対象としています。
下記の通り、v1に比べて試験時間は一日短縮され、問題数が多くなりました。
また、多肢選択試験に加え、獲得したFlagを記入する問題があります。

### 比較表:
|項目  |eJPTv1  |eJPTv2|
|---|---|---|
|試験時間  |3日間（72時間）  |2日間（48時間）  |
|問題数  |20問  |35問  |
|合格スコア  |15問以上（75%以上）  |25問以上（70%以上）  |
|解答形式  |多肢選択試験   |多肢選択及び記入方式  |

### 難易度：
eJPTv1を受けたことがないので、正確に比べることはできませんが、
私にとってはeJPTv2は難しかったです。
単なるCapture the Flagの試験ではなくて、すべてのデバイスをハッキングできても合格できるとは限りません。
最近のテストに関するブログを見ると、「これはエントリー資格ではない、難し過ぎる」という批判的な声がありますが、
それをクリアすることは価値あることではないかと思います。



### 準備方法：

試験準備にあたり、ine.comで143時間の通信講座を受けました。
講師はJosh Mason氏とHackerSploitの創業者であるAlexis Ahmed氏です。
講座では、229のビデオ、154のクイズ、120のラボの構成になっています。
興味深いな内容なので、全部を見て、ノートを取りながら全てのラボを実践しました。
年末年始の休みがあったので、それも非常に助かりました。



### 感想：
通常の試験より長時間ですが、内容は面白くて、はまってしまいました。
攻撃するマシンが多く、Passive手段及びActive手段で得られた情報の整理が非常に重要になります。
テスト環境では、他のペネトレーションテスト（例：OSCP）と同じように使用できるツールを制限しているので、デフォルトでKali Linuxにインストールされているツール以外は使用できません。
しかし、Kali Linuxでは600ツール以上あるので、基本的に大丈夫でしょう。
試験では、攻撃手段を重視しているように感じました。
例えば、攻撃手段は三つありますが、求められている情報を得るため、最も相応しい手段を選ぶ必要があり、答えは１つというところが、専門性を問われていると感じます。

これまでCompTIA　Security＋、CompTIA　Penetration＋、CISCO　CCNP　Security、Microsoft Certified: Security Operations Analyst Associateといったセキュリティ関連資格は受けたことありますが、eJPTv2は他の試験と違って、非常に実践的な試験で、**忍耐** も**時間管理** も非常に大事です。
***実際のペネトレーションと同じようなリアル感があり、限られた時間（48時間だけ）で外から中へエンタープライズ・ネットワークをアクセスできるようにし、お客様の脆弱性を評価するものとなります。*** Metasploitのトラブルシューティングができると、非常に役立つでしょう。
今後、CompTIA CASP+、CISSPを挑戦する予定ですが、eJPTv2のお陰で、API HackingとBurp Suite Certificationへの関心が高まりした。

#### 皆様も自分のスキルを磨くために、ぜひトライしましょう！
jQueryでキーコード判別

# 入力文字の種類を制限する
## この記事でやること
jQueryで数字、記号、ファンクションキーの入力を制限する。

## 動作環境
osはwindows11、ブラウザはChrome.

## 参考ページ
キーコードはこちらの記事を参考にした。

http://faq.creasus.net/04/0131/CharCode.html

## 失敗例
上のページを参照するとソースコードは下のようになる。

```
$(function(){
    $(document).on('keypress', '.compare-input', function(e){
        var keycode = e.keyCode;
        if((48 <= keycode && keycode <= 57) || (96 <= keycode && keycode <= 123)
        || (186 <= keycode && keycode <= 192) || (219 <= keycode && keycode <= 226)){
            console.log('Invalid key pressed.');
            e.preventDefault();
        }
    });
});
```

しかし、動作確認をするとアルファベットも打てなかった。

## 成功例
ChatGPTに質問してみた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3078929/9e6a5c78-c8de-cd91-8c21-06a7293330c5.png)
if文の前にkeycodeの値を表示する処理があるが、ここでは無視して頂きたい。
このキーコードの範囲を指定してみた。

```
$(function(){
    $(document).on('keypress', '.compare-input', function(e){
        var keycode = e.keyCode;
        if((33 <= keycode && keycode <= 64) || (91 <= keycode && keycode <= 96)
        || (123 <= keycode && keycode <= 126)){
            console.log('Invalid key pressed.');
            e.preventDefault();
        }
    });
});
```

これでアルファベットや制御キーは問題なく入力できた。
また、数字、記号、ファンクションキーははじかれた。

## 原因
ChatGPTは上の画像で示した通り、失敗例のソースコードについて、「アルファベットだけでなく丸括弧などの特別な文字やテンキーの数字の入力まで制限している」と指摘している。そのうえで、数字、記号、ファンクションキーのみを制限するソースコードとして上記の成功例のソースコードを提示してくれた。
なぜ失敗例のif文の条件ではアルファベットが入力できなかったのか、なぜ成功例の条件では入力できたのかはわからない。
教えを乞いたい。
Cの基本3 ~式~ 備忘録

### はじめに
私は初心者である。この備忘録を参考にされようとしている他の初心者の方は、ここに書かれていることを鵜呑みになさらぬようお願いしたい。何か間違いを見つけた方はコメント欄でご報告頂きたい。
___

### 式の順序
```c
3.14 * radius * radius
```
コンピュータが式の値を求めることをその式を評価するという。
全体の式に対して`3.14 * radius`のような一部を部分式という。
複数の計算がある式では、一度に計算することができないから、順番に計算する。
計算するために部分式にまとめることをグループ化という。
部分式がどの順序で評価されるかをCは定めてないらしいので注意する。
しかし例外的に評価順序が決まっているものもあるらしい。

___

### 明示的な型の変換
##### 代入で型を変換
```c
    double radius = 5;
    double area_double;
    int area_int;

    area_double = 3.14 * radius * radius;
    area_int = 3.14 * radius * radius;
    printf("area_double = %f\n", area_double);
    printf("area_int = %d\n", area_int);
```
結果は
```c
area_double = 78.500000
area_int = 78
```
`double`型を整数型に代入すると小数点以下は切り捨てられ、四捨五入や偶数丸め等も起こらないよう。
##### キャスティング
Javaでやった以来のキャスティング。
```c
    int mass, volume;
    double density;

    mass = 1293;
    volume = 1000;

    // density = mass / volume;    // このままだと1.0000となるだけ　要注意
    density = (double)mass / (double)volume;
    printf("Density is %f\n", density);
```
結果は
```c
Density is 1.293000
```
他にもライブラリで`ceil`関数、`floor`関数、`round`関数等があるらしいからそれらを利用する。

練習問題で
*変数の型を変えずにキャスティングを用いて変数に代入される結果の小数点以下を切り捨てよ*
という問題があった。下記が私の回答
```c
    double radius, area;
    radius = 5;

    // area = (int)3.14 * (int)radius * (int)radius;
    area = (int)(3.14 * radius * radius);
    printf("area is %f\n", area);

```
結果は
```c
area is 78.000000
```
**コメントアウトしてあるようなやり方だと、最終的な答えだけではなく式の定数全てにキャスティングが実行され、答えも大きく変わってきてしまうから注意しよう(コメントアウトのやり方だと`75`と評価された)。**

___

### 演算子
演算子には優先度がある。まぁこれはリアルライフとそんな変わらん。`2 / 2 * 2`のように同じ優先度の演算子が並んでいるときは結合性という法則に沿ってグループ化するらしい。基本的には左結合ということでOKなはず。グループ化の順番を変えたいときは丸括弧を使って表現する。丸括弧は入れ子可能だ。
もっと書くべきことは沢山ありそうだが、次節でも触れるそうだから今は割愛。

___

### 代入
```c
    int x, y;
    x = 2;
    y = x;
```
上記のコードの`x`に着目する。
2行目の`x`は右辺の`2`という値を入れるためのメモリ領域を表している。逆に３行目にある`x`はその領域に入っている`2`という値を表している。
ここでいう`x`は 
* 代入の左辺にあるときはメモリ領域を意味する
* 代入の右辺にあるときは領域に入っている値を意味する

それぞれの意味には左辺値と右辺値という言葉がついてるらしい。
（覚える必要があるのかは不明だが、なんか大事そうだからメモっとく）

面白いのが下のやつ。pythonやjavaであったのか忘れたが、
（というか確かめたことなかった気がするが）

```c
    int a;
    double b;

    b = a = 2.5;    / ここで一応警告が出る
    printf("a = %d\n", a);
    printf("b = %f\n", b);
```
この結果は以下の通りとなる
```c
a = 2
b = 2.000000
```
あくまで代入は右から左に行われているのがよく分かる。

まだその重要性を理解できてないが、書籍では左辺値と右辺値について詳しく書かれている。ほとんどの演算子は右辺値を扱うが、代入とのちに出てくるというインクリメント、デクリメント、アドレス演算、`sizeof`演算子などは左辺値を扱うらしい。まぁ自分なりに解釈すると、変数が保持する値を扱う演算子もあれば、変数の領域（アドレス的な）についての情報を扱う演算子もあるということじゃないだろうか。

___

>今回の内容は富永和人氏の[新しいC言語の教科書](https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84C%E8%A8%80%E8%AA%9E%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E5%86%A8%E6%B0%B8%E5%92%8C%E4%BA%BA-ebook/dp/B07P1TC98P)を参考に書き留めてます。
Windows から AlmaLinux へ　リモートデスクトップ接続　【忘備録】

XRDPのインストール
# yum install -y epel-release
# yum install -y xrdp tigervnc-server

XRDPの通信を許可する
# firewall-cmd --permanent --zone=public --add-port=3389/tcp
※firewall-cmd　半角スペースはなし
# firewall-cmd --reload
※firewall-cmd　半角スペースはなし

XRDPの起動と起動設定
# systemctl start xrdp
# systemctl enable xrdp

参考⇛https://www.itcore.jp/tips/xrdp.php

以下のコマンドは入力しなくいても動作した。

XRDPの設定変更 色24bitへ
# cp -ip /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini_`date "+%Y%m%d"`
# vi /etc/xrdp/xrdp.ini
:46
#max_bpp=32
max_bpp=24
【Python】matplotlibを日本語対応にする方法

# ライブラリのインストール
`pip install japanize_matplotlib`

※Anacondaを利用している場合
`conda install -c uehara1414 japanize-matplotlib`

※Jupyter Notebook、Google Colabなどの場合
`!pip install japanize_matplotlib`

# 実行
Google Colabで実行
```%matplotlib inline
import japanize_matplotlib
import matplotlib.pyplot as plt
import numpy as np

plt.plot([1, 2, 3,  4, 5])
plt.xlabel('x軸')
plt.ylabel('y軸')
plt.title("簡単なグラフ")
plt.show()
```

# 実行結果
日本語が文字化けせずに表示される
![スクリーンショット 2023-02-06 21.53.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3093526/faab8f6a-5566-eaf3-ab16-4b85f30a2663.png)
RStudio - R言語の基礎 #02、データ型の基礎

Googleデータアナリティックスプロフェッショナルを受講しています。
R言語の基礎となるデータ型の扱い方について学習しました。

https://www.coursera.org

## データ型の基礎・アトミックベクトル型

R言語では、他のプログラミング言語と同様変数を使うことができます。
変数の型として、今回は文字列型・数値型・アトミックベクトル型、リスト型、時刻データ型について学びました。

```r
#R言語では、他のプログラミング言語と同様変数を使うことができる。
#c(1,2,3...)という宣言をすればベクトル型を扱うことができる
#c() 関数で整数型のベクトルを作るには、各数値の直後にアルファベットの  L を入れる
first_variable <- "This is variable"
second_variable <- 100.00
vec_1 <- c(13.1, 43.2, 56.3, 67.4)
vec_2 <- c(13L,43L,56L,67L)

print(first_variable)
print(second_variable)
vec_1
vec_2
```
![スクリーンショット 2023-02-06 211508.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/de96cb8a-8d99-1af0-9892-7073deb377a0.png)


```r
#typeof() 関数を使えばそれがどのような型のベクトルなのか調べることができる
#作成したベクトルの長さ（データ要素の数）はlength() 関数を使って調べることができる
#is.logical() , is.double() , is.integer() , is.character() のように、 is 関数を用いてベクトルが特定の型に当てはまるどうか調べることもできる

typeof(vec_1)
typeof(vec_2)
is.integer(vec_1)
is.integer(vec_2)

length(vec_1)
length(vec_2)
```
![スクリーンショット 2023-02-06 211535.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/20894870-907f-49c1-9d64-8ab2f6e65996.png)

## リスト型

```r
#リストはアトミックベクトルとは異なり、そのデータ要素にあらゆる型を使用できる
#リストを作成するには、 list() 関数を使用する
#リストは辞書型のようにキーと値を対応させることができる

list01 <- list("a", 1L, 1.5, TRUE)
list01

list02 <- list("Elen"=1,"Mikasa"=2,"Armin"=3)
list02
```

![スクリーンショット 2023-02-06 211610.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/5a79f158-7139-1dba-e408-67f34f80c9db.png)

## lubridate パッケージ - 日付や時刻データを扱う
日付や時刻データを処理するのに使う、tidyverse・lubridateをインストールします。また、R における日付や時刻のデータ型と文字列型を日時型に変換する方法を解説します。

```r
#tidyverse・lubridateをインストールして読み込む
install.packages("tidyverse") 
library(tidyverse)
library(lubridate)

#現在の日付データを取得したい場合は、 today() 関数・now()関数を実行する
today_data <- today()
now_data <- now()

today_data
now_data

#文字列から日付・時刻のデータに変換する
ymd("2021-01-20")
mdy("January 20th, 2021")
dmy("20-Jan-2021")
ymd(20210120)
as_date(now())

ymd_hms("2021-01-20 20:11:59")
mdy_hm("01/20/2021 08:01")
```
![スクリーンショット 2023-02-06 212739.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/8ea97f42-2b87-a8d1-5218-313b5609fe39.png)

## データフレーム
データフレームは、データを保存・分析するのに使われるデータ構造です。
表計算ソフトや SQL のテーブルに似た行列の集まりです。
```r
#データフレームを手動で作成する場合、data.frame() 関数を使用する
data.frame(x=c("Elen", "Mikasa", "Armin"), y =c(1,2,3))
```

## ![スクリーンショット 2023-02-06 214902.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/143fbf5a-5263-35da-964a-23ebb2d0e09c.png)

## ファイル
```r
#file.create() 関数を使用して、空のファイルを作成
#ファイル作成に成功すれば、TRUEを返り値にする
#R ファイルの削除は、unlink() 関数で行う

file.create (“new_text_file.txt”) 
file.create (“new_word_file.docx”) 
file.create (“new_csv_file.csv”) 
```
承認プロセスの承認者をマネージャ（上司）に設定する方法

今回は、承認プロセスで承認者をユーザのマネージャーに設定する方法をご紹介いたします。

承認プロセスの承認者を設定する際に、承認者を１人のユーザではなく、申請者によって可変的に設定したいと思ったことはないでしょうか？
その際に、設定できるのがマネージャーの設定です。

<h3>１．ユーザのマネージャー設定</h3>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995724/112d4ba0-ce27-cc88-34d9-8eedec336953.png)


承認のマネージャーを設定したいユーザ情報で、マネージャーを選択します。

<h3>２．割り当て先の項目を設定</h3>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995724/e158f958-c3d6-dbbb-4106-d86b564e5175.png)

承認プロセス作成のステップ３で割り当て先の項目をマネージャに設定します。


<h3>３．承認ステップの設定</h3>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995724/94803a61-38dd-24a9-b46d-f8e10812e894.png)

承認プロセスの作成後、承認ステップを作成します。
承認ステップ３で「選択したユーザ項目を使用して自動的に承認者を割り当てる。（マネージャ）を選択します。


これで、設定は完了です。
このような設定で、承認者を１人のユーザに固定するのではなく、申請者のマネージャーを承認者として設定することが可能になります。
Unreal EngineプロジェクトをVSからStart Debug(F5)できない

VSのSolution Explorerウィンドウに表示されている自分のゲームプロジェクトを右クリックし「スタートアッププロジェクトに設定」をクリックする。

https://forums.unrealengine.com/t/visual-studio-not-able-to-debug/314668
特定のリポジトリ/オーナーでREADMEを更新した場合のみ、github actionでTable of contentsを更新する。

特定のリポジトリでREADMEを更新した場合のみ、github actionでTable of contentsを更新する。

## Table of contentsについて

`Table of contents`とはいわゆる目次のことであり、Github actionsでは以下の`toc-generator`がマーケットで提供されている。
https://github.com/marketplace/actions/toc-generator

以下のように使用する。

```yaml
name: Update Markown TOC

on:
  push:
    paths: 
      - 'README.md'

jobs:
  UpdateTOC:
    name: UpdateTOC
    runs-on: ubuntu-20.04
    steps:
      - name: TOC Generator
        uses: technote-space/toc-generator@v3
        with:
          # 目次を更新するファイル
          TARGET_PATHS: README.md
          # 目次を作成する最大階層レベル
          MAX_HEADER_LEVEL: 4
          GITHUB_TOKEN: ${{ secrets.SECRETS_UPDATE_TOC_ACCESS_TOKEN }}
          # 目次の見出し
          TOC_TITLE: '**Table of Contents**'
```

これを`.github/workflow/xxx.yaml`のような形で置いておくと、README.md更新時に目次が自動的に作られる。
（`${{ secrets.SECRETS_UPDATE_TOC_ACCESS_TOKEN }}`にはSECRETSを格納しておく）

## 特定のリポジトリでTOCを更新したい場合

github actionsから以下の変数を使う

`${GITHUB_REPOSITORY}` #owner/repo
`${{ github.repository }}` #owner/repo
`${GITHUB_REPOSITORY_OWNER}` #owner
`${{ github.repository_owner }}` #owner

例えば以下のようにすると、リポジトリのオーナー名を取得できる（例: repository_owner:seigot）

```yaml
    steps:
      - name: test step
        run:
          echo "repository_owner:${GITHUB_REPOSITORY_OWNER}"
          echo "repository_owner:${{ github.repository_owner }}"
```

`if: github.repository_owner == 'seigot'`のようにすると、特定のリポジトリ/オーナーでREADMEを更新した場合のみ、github actionでTable of contentsを更新することができる。


```yaml
name: Update Markown TOC

on:
  push:
    paths: 
      - 'README.md'

jobs:
  UpdateTOC:
    name: UpdateTOC
    runs-on: ubuntu-20.04
    steps:
      - name: TOC Generator
        uses: technote-space/toc-generator@v3
        if: github.repository_owner == 'seigot'
        with:
          # 目次を更新するファイル
          TARGET_PATHS: README.md
          # 目次を作成する最大階層レベル
          MAX_HEADER_LEVEL: 4
          GITHUB_TOKEN: ${{ secrets.SECRETS_UPDATE_TOC_ACCESS_TOKEN }}
          # 目次の見出し
          TOC_TITLE: '**Table of Contents**'
```

# 参考

https://github.com/marketplace/actions/toc-generator

https://zenn.dev/snowcait/articles/757d0c6815227f
Leetcode 1470. Shuffle the Array

https://leetcode.com/problems/shuffle-the-array/description/

## アプローチ
### Brute-force

```java
class Solution {
    public int[] shuffle(int[] nums, int n) {
        int[] result = new int[nums.length];
        int start = 0;
        for (int i = 0; i < nums.length; i++) {
            if (i % 2 == 0) {
                result[i] = nums[start];
                start++;
            } else {
                result[i] = nums[n];
                n++;
            }
        }
        return result;
    }
}
```
IoTシステムの全体像③ 〜データ可視化〜

# はじめに
毎週1本様々な技術に関する記事を投稿しています。
もし興味のある方は下のリンクから他の記事も見ていただければ幸いです。
 [@7_inai_](https://qiixta.com/7_inai_)

# IoTシステムの全体像
IoTシステムでは次のような順でデータが流れていきます。
`①データ収集 -> ②データ通信 -> ③データ可視化 -> ④データ蓄積 -> ⑤データ分析 -> ⑥データ活用`
6つの記事に渡ってそれぞれのセグメントについてまとめていきますが、この記事では「③データ可視化」について記述します。

# 可視化ツール
IoTデバイスで収集したデータは、`必要な情報の精査を行った後、見やすい状態に変換させて表示する`必要があります。その見やすい状態に変化させる部分(データの可視化)についてをこの記事ではまとめます。
可視化の方法を大まかに分けると、[XR(AR/IR/MR)](https://qiita.com/7_inai_/items/35a36f0d99582c9b3547)を用いて、仮想世界のデータを現実に投影させて見せる方法と、BIツールを用いてグラフや数値で見せる方法の2通りがあります。[XR](https://qiita.com/7_inai_/items/35a36f0d99582c9b3547)については別の記事でまとめたため、BIツールの概要を中心に説明していきます。

## BIツールとは
BIツールは __Business-Intelligenceツール__ の略で、`企業内に点在しているデータを統合・分析を行うことで、企業が意思決定を迅速かつ効率的に行うために利用するツール`の総称です。
※Business Intelligenceとは、ビジネスの意思決定に関わる指標を意味します。

## BIツールの機能
BIツールの主要な機能としては以下の4項目があります。

- ①レポーティング
ダッシュボード(KPI等の主要な数値を表示させた画面)等で情報を共有したり、分析結果をレポートとして出力させることができます。
- ②データマイニング機能
異なるデータ間の相関性を見つけ出すための機能です。人が見ても気づけなかったようなデータの相関性を見つけ出し、今後の事業方針の決定等に活かすことができます。
- ③シミュレーション(プランニング)機能
過去のデータを元に、企業や市場の今後を予測することができます。
- ④OLAP(OnLine Analytical Processing)分析機能
データベースで収集された膨大なデータに対して、複雑な集計・分析を行い、素早くレスポンスを返してくれます。
※Onlineとありますが、ここでのオンラインは「素早くレスポンスを返す」という意味です。

## BIツールのメリット
BIツールはよくExcelと混同されがちですが、BIツールならではのメリットを紹介します。
- ①リアルタイムのデータを反映
BIツールでは、データベース内のデータの変化に伴って数値も変化するため、リアルタイムのデータを確認することができます。
- ②対応するデータソースの多さ
BIツールでは、各ツールの情報を一箇所で確認することができます。
- ③高速処理
IoTシステムでは、これまでの情報収集システムとは違い、自動的にデータを収集するためデータの量も多くなります。それに対応することを前提として開発されているため、Excelと比較して高速処理に向いています。


# 終わりに
BIツールは、IoTシステムにおけるデータの可視化において最適なツールだと思います。IoTを用いて意思決定を素早く正確に行いたい場合には、ぜひ導入を検討してみてください。

最後までお付き合いくださりありがとうございました。
雑なI2Sの理解

# はじめに
使うたびに細かいことを忘れてしまうI2Sについてメモ。雑な調査に基づくメモなので無保証、間違いの指摘は大歓迎。

# 仕様
## 原典
[I2S bus specification](https://www.nxp.com/docs/en/user-manual/UM11732.pdf)って事でNXPが今でも公開してる。けど、実際に世の中でどう運用されてるかまでわからないので、これを見て世の中のI2S全てと分かり合えると思わない方が良い。

## 信号名
とりあえず原典で使われてる信号名はあるんだけど、実際に現場で見る信号は様々なので、そのエイリアス表。

### SCK: clock
- BCLK (Bit Clock)

### WS: word select
- LRCLK (LR Clock)
- FS (Frame Sync)
- SYNC

### SD: data
- SDATA
- SDIN
- SDOUT
- DACDAT
- ADCDAT

### その他
- MCLK / SYSCLK: 厳密にはI2Sの仕様とは関係ないと思うんだけど、セットで出てくる事が多い。WSの256倍が多いとの記述もあるが、環境によってそれぞれ。送受信回路でフィルタや別のフォーマットへのエンコードなどを実装する際に必要となるN倍の同期クロックとして用意してるのかな？PLLとかあればSCKから作るんだろうけど、そういうのが難しいチップ向けの補助信号という理解。

## 周波数
WSの周波数がそのままサンプリング周波数になる。とれる周波数については特に規定されてないと思うが、通常の音楽環境の通り、44.1kHzと48kHzの定数倍が実際に使われている周波数だと思う。周波数についてはここを起点に考えるのが良い。
SCKの周波数は、WSの32倍または64倍。これは16bit幅のデータの場合には16×左右2ch分で32倍のデータが必要だから。他に24bit幅も利用されているが、この際には転送では32bit幅をとっている。よって32x2chで64倍。

## 方言
データパタンには3種類の方言があり、結局のところはWSに対してどのタイミングを起点としてデータを出すか、だけの違いになる。マイコンなどは実装によって全てのパタンが使えるわけではないが、名前の通りI2S Justifiedが標準語だと思って良い。

### Left Justified
WSがHIGHに上がったのと同じサイクルに出たSDの信号がMSBで、HIGHの間に左チャンネルの上位から下位、右チャンネルの上位から下位と信号が流れる。24bitフォーマットの際は各チャンネルの信号後に8サイクルの空サイクルが流れる。つまり後ろにデータパディングが入る。

### Right Justified
同じくWSがHIGHに上がったのと同じサイクルが起点。ただし24bitフォーマットの際は8サイクルの空サイクルが先頭に現れ、のちに24bitのデータが続く。つまり手前にデータパディングが入る。この際、エンディアンが変わるわけではなく、単純にアライメントの問題だけである事に注意。

### I2S Justified
今までと反対でWSがLOWに下がるタイミングが起点だが、そのサイクルではなく次サイクルがMSBとなる。つまりWSの極性が反対な上にデータがさらに1サイクル遅れている形になる。

## フォーマット
16bit/24bitともにsignedなので注意。MSBは符号ビットです。32bitの話は聞かないけど、Left/I2S Justifiedなら後ろのパディングに追加の下位bitをそのまま流し込めば双方互換性を維持したまま綺麗に拡張できる。
matplotlibでグラフを作ってOpenCVで好きな画像とアルファブレンドする

# 環境
python 3.9.6
Windows11
# 使用する画像
![221219_26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2134624/55855ad5-d7b4-59de-6275-b3271b5bcb79.jpeg)
# 下準備
下準備にコードを置く場所と同じ階層にアルファブレンドしたい画像を置こう！
# コード
```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import cv2

def sin():
    fig, ax = plt.subplots()
    x = np.linspace(0, 18, 100)
    for i in range(1, 10):
        ax.plot(x, np.sin(x + i * .5) * (7 - i))
    fig.savefig('fig.jpg') # グラフのセーブ

ax = sin()

pathA = '221219_26.jpg' # 画像のパスを指定
imgA = cv2.imread(pathA) # 画像の読み込み
color_mapA = cv2.applyColorMap(imgA, cv2.COLORMAP_HSV) # カラーマップで色を付ける
resizeA = cv2.resize(color_mapA,(640,480)) # 画像のサイズを変更

pathB = 'fig.jpg' # 保存したグラフのパスを指定
imgFig = cv2.imread(pathB) # 画像の読み込み
color_mapFig = cv2.applyColorMap(imgFig, cv2.COLORMAP_HSV) # カラーマップで色を付ける

alphaImg = cv2.addWeighted(resizeA, 0.7, color_mapFig, 0.3, 0) # アルファブレンド
cv2.imwrite('blend.jpg', alphaImg) # アルファブレンドした画像を保存
```
# できた画像
![blend.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2134624/dafbe966-d9e2-099b-1fc2-7b98e8844cc1.jpeg)
urqlでグローバルなエラーハンドリングを実装する

# やりたいこと
アプリケーション内で発生したすべてのurqlのエラーを、一箇所のコードで処理できるようにします。
例えば、エラー内容に応じてログを監視システムに送信したり、エラー内容を画面に表示することができるようになります。
調べた際にあまり情報が出てこなかったので、備忘録を兼ねて残しておきます。

# 環境
- next: 13.0.6
- urql: 3.0.3

# Exchangeとは
urqlによるリクエスト・レスポンスの一連の処理をカスタマイズできる仕組みです。
Reduxのミドルウェアと同じような要領で、処理の途中に任意のExchangeを挟むことによって、リクエストやレスポンスの内容にアクセスする処理を書くことができます。
リクエストに認証用のヘッダーを付与したり、レスポンスの内容を変換するために使われます。

詳しくは公式ドキュメントをご覧ください。

https://formidable.com/open-source/urql/docs/architecture/#the-client-and-exchanges

# mapExchangeとは
[mapExchange](https://formidable.com/open-source/urql/docs/api/core/#mapexchange)はurqlにデフォルトで組み込まれているExchangeで、リクエスト・レスポンス・エラーに対する処理をそれぞれ実行することができます。
エラー処理を行う際は、onErrorの中で[CombinedError](https://formidable.com/open-source/urql/docs/basics/errors/)オブジェクト(error)を使用でき、この情報を使ってエラーをハンドリングすることができます。
以前のバージョンでは[errorExchange](https://formidable.com/open-source/urql/docs/api/core/#errorexchange-deprecated)が使われていたようですが、現在はmapExchangeに置き換えられており、errorExchangeは非推奨(deprecated)となっています。

# サンプルコード
```typescript:client.ts
import { createClient } from '@urql/core'
import { cacheExchange, dedupExchange, fetchExchange, mapExchange } from 'urql'

export const client = createClient({
  url: process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT || 'https://localhost:8000/graphql',
  exchanges: [
    dedupExchange,
    cacheExchange,
    mapExchange({
      onError(error, operation) {
        console.log(`The operation ${operation.key} has errored with:`, error);
      },
    }),
    fetchExchange,
  ],
})

```
C#で行列計算(Generic Math)

C#には標準で行列を扱うクラスが無いので自分で作ってみました。ご自由にお使いください。

**.Net 7.0, C# 11から導入されたGeneric Mathを使用してGenericクラスにしてみました。**
* ```INumberBase<T>```を使用しています
→複素数でも行列計算できます
* ```IPowerFunctions```と```IRootFunctions```は```INumberBase<T>```にはない
→標準偏差、標準誤差を計算するメソッドは```IFloatingPointIeee754```の拡張メソッドとして実装している

https://github.com/codehumgfk/CSLibrary.git

以下はテストからの抜粋ですが、使用例です。

```CS
var arr = new double[2, 2] { { 1, 2 }, { 3, 4 } };
var matrix = new Matrix<double>(arr);
var arr2 = new double[2] { 1, 1 };
var rowVec = new RowVector<double>(arr2);

Console.WriteLine(matrix * rowVec);
// [[3], [7]]
```

インデクサーも実装してありますので、最初に行数と列数だけ指定して後から値入れることもできます(どちらかというと、自分のコードではこちらのインデクサーを使うことが多いです)。

あったらよさげな機能、より計算時間を削減できるような効率的な実装方法、問題点などあれば是非コメントください。
行列以外の部分についてもコメントをお待ちしております。

## 更新履歴
2023/03/12 Generic MathでGeneric化
2023/03/22 タグを追加。タイトル、文章を修正
【SwiftUI】Previewで@Stateを使用したい

# はじめに
SwiftUIでBindingを使用するとPreviewの時にどうすればいいのか迷いますよね。
私が初学者の時はどうするのかわからずにPreviewを消してました。
同じような問題で困ってる人のために記事にします。

# やりかた
```diff_swift:ContentView
import SwiftUI

struct ContentView: View {
    @Binding var text: String
    var body: some View {
        Text(text)
    }
}

struct ContentView_Previews: PreviewProvider {
+   @State static var text: String = "テスト"
    static var previews: some View {
        ContentView(text: $text)
    }
}
```

:::note info
**ポイント**
`@State`に`static`を付けます。
:::

# おわり
`.constant()`でもPreviewを表示させることができます。
高校でのAWS開発・運用日記~体育祭編

こんにちは@kurimoni367 です！
自分の通っている高校でAWSを活用してシステムを構築・運用したことについて投稿します。今回は体育祭編です！！

# 目次
1.構築したシステム一覧
2.競技エントリー管理システム
3.運用してみて
4.まとめ

:::note alert
お願い
この記事の記載事項やサービスについて、弊学及び当局へのお問い合わせはおやめください。
またこの記事の記載事項について、誤りの無い様細心の注意を払っていますが正確性を保証することはできません。
予めご了承下さい。
:::

# 1.構築したシステム一覧
体育祭では

　1\. 競技エントリー管理システム
　2\. NYGstreaming(ライブ配信)

を構築・運用しました。
2のNYGstreamingは[前回の文化祭・NYGstreaming編](https://qiita.com/kurimoni367/items/31f2d855504a17718b5c)で詳しく書かせていただいたので、ぜひそちらをご覧ください！この頃は、ver1.1からver1.2へ移行したぐらいの頃でした。また、競技ルール説明のライブ配信では、アーカイブ配信で何度も見れるようにする必要がありました。そのため、S3に録画されたものをダウンロードし、編集した後、Google Driveで共有しました。

# 2.競技エントリー管理システム
　このシステムでは各競技に出場する生徒の情報を管理します。エントリールールに反する場合があればそれを検出し、招集係の生徒が確認したり自分の出場種目を確認したりするために、それぞれに最適なフォーマットで書き出すことを目的としたシステムです。
これは文化祭で構築した各サービスと異なり処理のみを目的としたので、WebUIのようなものでなく、あくまでシステムとして運用しました。

## 構成

フローチャート図のようなものは上のようになります。
それでは詳しく見ていきます。
## Amazon Textractとは
 今年度のシステムが例年と異なる所は
* 回収した生データを手打ちしない
* データの再配列をスプレッドシート関数でなく Google Colaboratory を用いた
という点にあります。
以前はすべてのデータを一度手打ちしており、入力ミスを防ぐためにできる工夫は「如何に簡単に入力できるようなID構成にするか」といったことくらいでした。そういった工夫ではやはり限界はあります。そこで今回は、AIに読み取らせてしまえ！！となったわけです。
　
そして採用されたAmazon Textractですが、これにはある大きな特徴があります。それは**表を認識して表データのみを抽出し書き出せる**という特徴です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092122/80a966f7-ccac-2eb8-2b0c-375facc836d9.png)
このデモのようにきちんと表部分が認識されています。このデータはzipで文章として読み取ったデータとともにダウンロードできます。　
他にもたくさん機能があるので気になる方は公式サイトを確認してみてください。

https://aws.amazon.com/jp/textract/

## エラー検知システム
このシステムではそれほど凝ったことはしていません。「ある競技に出場すれば前後3競技には出場できない」というルールがあるのですが、そういったエントリー上のルールに反するものを、生徒個々人に振ったIDに基づきスプレッドシートの関数で処理させました。
扱うデータ量が10万を優に超えていたので、それをきれいに表示させるという点で苦労しました。

# 3.運用してみて
まず、Amazon Textractに関してですが正直な所まずまずといった感じでした。表が認識されないということはなかったのですが、**文字列として認識される**・**1がl(小文字のL)と誤認識される**　、などのミスが頻発しました。文字列を数字列に変換する際は関数を噛ますだけでいいのですが、数字が似たアルファベットに誤認される問題に関しては人間が確認して修正しないといけないので、結果的に作業量が劇的に減少とまでは行きませんでした。
また、運用当時は日本語が未対応で、書き込み用シートが全て英語になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092122/476f6db8-2b38-5426-12cd-fc46c9937b2e.png)

# 4.まとめ
　結果として利点も欠点もかなり多く見つかったエントリー管理システムとなりましたが、結果として作業日数は減らせたと思います。

さて、2回に渡って投稿させていただきました、高校でのAWS開発・運用日記　ですが、これでいったん終了とさせていただきます。
いままで読んでくださった皆さんありがとうございました！！
前作はこちらからご覧ください！

https://qiita.com/kurimoni367/items/31f2d855504a17718b5c
Rubyで同じ要素をカウントするメソッド

# 概要
rubyで同じ要素をカウントするプログラムを考えていたときに、リファレンスにあったメソッドについてです。

# tally
はじめは、以下のようなプログラムを考えていました。

```
fruits = ["apple", "grape", "orange", "banana", "orange", "apple"]

# 重複をなくす 
p fruits_uniq = fruits.uniq

# ["apple", "grape", "orange", "banana"]


# 種類ごとにカウントする 
fruit_list = {}
fruits_uniq.each do |s| 
   fruit_list[s] = fruits.count(s)
end
p fruit_list

# {"apple"=>2, "grape"=>1, "orange"=>2, "banana"=>1}
```

これを１行でできるメソッドがtallyメソッドになります。

```
fruits.tally

# {"apple"=>2, "grape"=>1, "orange"=>2, "banana"=>1}
```

tallyメソッドは、selfに含まれる要素数の結果を**Hash**で返してくれます。
あったらいいなというメソッドは調べてみると案外あることがわかりました。


（https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/tally.html）
【自動化】ファイルを種類ごとにフォルダーに振り分ける

# この記事を読んでできるようになること
- **任意のフォルダーを自動的に作成**し、そのフォルダーに**自動的にファイルを割り振る**。

# 使用例
- Word, Excelなど様々な形式のファイルが入っているフォルダーがある。それらを、ファイルの形式ごとの新しいフォルダーを作成し（e.g., word）、任意のフォルダーへファイルを振り分ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344524/02f42598-e8f2-ceae-411d-3c1c520c8ac8.png)


# コード

## モジュールのインポート
```python
import os
import glob
import shutil
```

## 作業ディレクトリ内に、フォルダーを作成 
フォルダーの名前を指定する際に、そのフォルダーまでのパスを指定することもできます。
例）os.mkdir('C:/Users/tokai/Documents/TokaiOnAir/text')
```python
os.mkdir('word') # os.mkdir('好きな名前を入力')
os.mkdir('text')
os.mkdir('excel')
```

## 任意の形式のファイルをすべて取得
globに関する解説記事 [【1】](https://note.nkmk.me/python-glob-usage/)

```python
word_files = glob.glob('*.docx')
txt_files = glob.glob('*.txt')
excel_files = glob.glob('*.xlsx')
```

## ファイル数を確認

```python
print('Wordファイルは全部で',{len(word_files)}, 'ファイルあります')
print('txtファイルは全部で',{len(txt_files)}, 'ファイルあります')
print('Excelファイルは全部で',{len(excel_files)}, 'ファイルあります')
```
出力↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344524/66a7f9a9-82cf-2fbb-a5f6-2f2c730dd33f.png)


## ファイルの形式に応じて、指定したフォルダーへ移動させる
3つの形式が入っている変数（「**任意の形式のファイルをすべて取得**」で作成した変数）を一つにまとめます。
まとめた変数に対し、forとif、そしてshutil.moveを組み合わせて各フォルダーへ、ファイルを振り分けていきます。
```python
wte_files = word_files + txt_files + excel_files #すべてのファイルを一つの変数にまとめる

for file_name in wte_files:
    if file_name in word_files: 
        shutil.move(file_name,'「word」フォルダーへのパス')
    elif file_name in txt_files:
        shutil.move(file_name,'「text」フォルダーへのパス')
    elif file_name in excel_files:
        shutil.move(file_name,'「excel」フォルダーへのパス')
```
  
# 最後に
　今回は、作成したいディレクトリや、取得したいファイルの形式を一行一行指定しています。もし、別の形式のファイルをフォルダー分けしたい場合は、ワード、テキスト、エクセルファイルを指定しているように指定すれば自動で移動ができます。

# 参考資料
- 本記事に掲載したコードは、2023年1月、2月に名古屋大学で行われた、[「DOORS-Pythonによるプログラミング　第2回　要件を満たすプログラムの実装」（株式会社ネオレックス主催）](https://www.neorex.co.jp/news/2180/)の内容をヒントに作成しました。ネオレックス様、ありがとうございました。

- 【1】[Pythonで条件を満たすパスの一覧を再帰的に取得するglobの使い方](https://note.nkmk.me/python-glob-usage/)
AnacondaでCondaHTTPError: HTTP 000が発生した対処

WSL2上のAnacondaでプロキシも設定していない状態で```CondaHTTPError```が発生した。
```sh
 conda create -n test python=3.9
Collecting package metadata (current_repodata.json): failed

CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://repo.anaconda.com/pkgs/main/linux-64/current_repodata.json>
Elapsed: -

An HTTP error occurred when trying to retrieve this URL.
HTTP errors are often intermittent, and a simple retry will get you on your way.

If your current network has https://www.anaconda.com blocked, please file
a support request with your network engineering team.

'https//repo.anaconda.com/pkgs/main/linux-64'
```

## 原因
```.condarc```が消えていたみたい。
## 対応
```conda info ``` で情報の確認
```
 active environment : base
    active env location : /home/hoge/anaconda3
            shell level : 1
        active environment : base
    active env location : /home/katsuji/anaconda3
            shell level : 1
       user config file : /home/katsuji/.condarc　#このファイルが消えていた
 populated config files :
          conda version : 22.9.0
    conda-build version : 3.22.0
         python version : 3.9.13.final.0
 populated config files :
          conda version : 22.9.0
    conda-build version : 3.22.0
         python version : 3.9.13.final.0
```
なにも書かずに```.condarc```を該当dirに作成
```sh
touch .condarc
```
無事作成できました。proxyを設定している場合も同様なエラーが出るみたいなのでその際はproxyの設定を```.condarc```に記載すればよい。
一歩踏み出す

一歩踏み出すことの大切さを、今日ほど感じていることはない。　

自分の人生で、一歩踏み出したことがなん度あるだろうか。　

自分で決めて踏み出したことと、家族、友達に勧められて踏み出したことを、洗い出してみる。　

# 習字　

人生の最初の習い事は習字です。　

自宅から２区画先に習字の塾があったことも影響しているかもしれない。　

家業が印刷屋で、早く文字を覚えて欲しかったからかもしれない。　

のちに、半田付けをするようになると、小さい頃から筆をちゃんと持って文字を書いていた訓練が役立ったような気がする。 

### 教訓１ 子供に半田付けを教える前に、習字を習いにいかせよう。　

# 手伝い　
３歳くらいから、家業の手伝いをしていた記憶がある。　

最初は紙を折る仕事。　
印刷物で２つ折りのキリスト教の冊子とか、お寺のお札とか。　

キリスト教の冊子は、つのぶえ社の事務所が、自宅の２階に一時あったことにもよる。

https://www.kyobunkwan.co.jp/xbook/archives/tag/9818da6a

お寺は知多の岩屋寺。

https://www.iwayaji.jp
新品のMacbookでGDALが使えるようにしよう

# 概要

いろいろな事情で新品のMacをセットアップする機会が多かったので、今後のために方法を記録しておきます。自分用。
zsh環境を想定しています。
最低限行わないといけない設定のみを記述しているので、スタイル設定（白基調・黒基調）などは無視で

[参考にしたサイト](https://zenn.dev/unsoluble_sugar/articles/283ebf698c307c)
# 目次

# 購入後
appleアカウントでログインした後、Homebrewをインストール。


# Homebrew 

[リンク](https://brew.sh/index_ja)からコマンドをコピーし、command+spaceでspotlight検索を立ち上げた後terminal.appからターミナルを開く。ターミナルにコピーしたコマンドを貼り付けるとターミナルが動き出します。

🔒マークが出たらmacbook本体に登録したパスワードを入力しましょう。見かけは動いてないけど大丈夫。

実行が完了し再び文字が入力できるようになれば、PATHを通し反映させます。
```
$ echo '# Set PATH, MANPATH, etc., for Homebrew.' >> /Users/username/.zprofile
$ echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/username/.zprofile
$ eval "$(/opt/homebrew/bin/brew shellenv)"
```
注意：上コードブロックの`username`の部分には自分のMacのユーザー名を入力すること。

# GDAL(GeoPandas)

```
$ brew install gdal
```

```
$ pip install gdal
```


[参考サイト](https://dev.classmethod.jp/articles/geopandas-on-m1-mac/)(geopandasも同様)

# コマンドたち
アプリ(word,excel,slack,などなど)をインストールしたいとき...`$ brew install (appName)`
例：`$ brew install google-chrome`
Pythonのパッケージ（全部共通）を入れたい時...`$ pip install (packageName)`
例：`$ pip install numpy`
Files.walkTree() 

FileVisitorに定義した以下の4つのメソッド通りにディレクトリをwalk through
preVisitDirectory
visitFile
postVisitDirectory
visitFileFailed

```java
public class Outer {
    public static void main(String[] args) throws Exception{
        Path p = Paths.get("c:\\dirtest");
        FileVisitor<Path> fv = new FileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                System.out.println("previsitdirectory : " + dir);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println("visitFile: " + file);
                if(file.toFile().getName().endsWith("test2.java")) {
                    Files.delete(file);
                    System.out.println("deleted: " + file);
                }
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                System.out.println("visitFileFailed :" + file);
                return FileVisitResult.TERMINATE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                System.out.println("postVisitDirectory :" + dir);
                return FileVisitResult.CONTINUE;
            }
        };
        Files.walkFileTree(p, fv);
    }
}
```
```
previsitdirectory : c:\dirtest
visitFile: c:\dirtest\cook.jpg
visitFile: c:\dirtest\cookcpy.jpg
previsitdirectory : c:\dirtest\dir1
previsitdirectory : c:\dirtest\dir1\dir2
previsitdirectory : c:\dirtest\dir1\dir2\dir3
previsitdirectory : c:\dirtest\dir1\dir2\dir3\dir4
visitFile: c:\dirtest\dir1\dir2\dir3\dir4\test.java
visitFile: c:\dirtest\dir1\dir2\dir3\dir4\test.txt
postVisitDirectory :c:\dirtest\dir1\dir2\dir3\dir4
visitFile: c:\dirtest\dir1\dir2\dir3\test.java
visitFile: c:\dirtest\dir1\dir2\dir3\test.txt
postVisitDirectory :c:\dirtest\dir1\dir2\dir3
visitFile: c:\dirtest\dir1\dir2\test.java
visitFile: c:\dirtest\dir1\dir2\test.txt
postVisitDirectory :c:\dirtest\dir1\dir2
visitFile: c:\dirtest\dir1\test.java
visitFile: c:\dirtest\dir1\test.txt
postVisitDirectory :c:\dirtest\dir1
visitFile: c:\dirtest\iii
visitFile: c:\dirtest\sample.ser
visitFile: c:\dirtest\showa.txt
visitFile: c:\dirtest\test.java
visitFile: c:\dirtest\test.txt
visitFile: c:\dirtest\test2.java
deleted: c:\dirtest\test2.java
visitFile: c:\dirtest\testfile.txt
visitFile: c:\dirtest\testmakefile.txt
visitFile: c:\dirtest\testwritefile.txt
postVisitDirectory :c:\dirtest
```
小数点の割り算が含む条件分岐

# 読んで欲しい人
・未来の私。
・詳しい方。（質問あり）
# 注意
AtCoderの[abc189_B - Alcoholic](https://atcoder.jp/contests/abc189/tasks/abc189_b) ネタバレあり。
# 解説
割り算した結果が小数点の可能性がある + 比較する対象が整数の場合は
条件分岐をする時に割り算したい数を比較したい対象に同じ数を掛け算する。
(今のところはここまでの理解)
# ACしたコード
```C
// 写経 #30744155

#include <stdio.h>
int	main(void)
{
	int n;//お酒を N 杯
	int x;//高橋君はアルコールの摂取量が X ml を超えると酔っ払います。
	int minus = -1;

	scanf("%d%d",&n,&x);
	// printf("%d %d\n",n,x);

	int v[1000000];
	int p[101];
	int i;
	int sum = 0;
	for (i = 0; i < n; i++)
	{
		scanf("%d%d",&v[i],&p[i]);
		// printf("%d %d\n",v[i],p[i]);

		// sum += v[i] * p[i] / 100;//ここで / 100すると小数点になる可能性があるから正確な数値が出せない。
		sum += v[i] * p[i];
		// printf("sum=%d\n", sum);

		if(x * 100 < sum){				//↑の / 100 できてないからここでxに * 100する。
			printf("%d\n",i + 1);
			return(0);
		}
	}
		printf("%d\n",minus);
	return (0);
}
```
# 疑問 && 質問
<b>疑問</b>
```C
printf("%d\n",minus);
```
最後のこの部分を書く時、今までは
```C
printf("-1\n");
```
と書いていたけれど、-1と書くと整数ではなくて文字列の-1を出力するように
書いてるのでは？と思いました。
今回は、minusという変数に-1で初期化して整数として出力してみました。

<b>質問</b>
問題文では-1を出力してくださいとしか記載が無いので、今回の問題は
文字列でも整数でもどちらでも良いのかとは思うけれど普通は、-1と記載があれば文字列ではなくて整数で出力すべきだと思うので
```C
printf("%d\n",minus);
```
こちらの書き方の方が正しいという認識であっているのかどうか判断できる方、教えてください。
(因みに、-1という書き方でもACしました。)
アジャイル開発について

## 初めに
前職では正直言って~~なんちゃってアジャイル開発~~をおこなっていた節があり、転職を機に改めてきちんとしてアジャイル開発を行なっている企業に転職をしたので概念的なものをなんとなくは理解はしていましたが、自分の勉強を兼ねてアジャイル開発にまとめました。


## そもそもアジャイル開発って？
アジャイルの意味を直訳すると、「素早い」「機敏な」「頭の回転が速い」という意味になります。
アジャイル開発はシステムやソフトウェア開発におけるプロジェクト開発手法のひとつで、大きな単位でシステムを区切ることなく『計画→設計→実装→テスト』といった開発工程を機能単位の小さいサイクルで繰り返すのが最大の特徴です。

このサイクルのことを**スクラム**や**イテレーション**と呼び、1〜4週間程度の期間になります。
## スクラム開発について
アジャイル開発と言っても色々な手法があります。その中でも最も代表的かつ、現在当社でも採用しているもの「スクラム開発」について説明いたします。

### スクラム開発
スクラムとはラグビーで肩を組んでチーム一丸となってぶつかり合うフォーメーションのことで、その名の通り、チーム間のコミュニケーションを重視している点が特徴になります。スクラム開発ではメンバー自身が計画を立案し、スクラムごとに設計・実装を行います。スクラム毎に開発の進捗状況の動作や検査するため、チーム内のコミュニケーションが非常に重要になります。

スクラム開発の流れは以下の通りです。
```mermaid
graph TD;
    スプリントプランニング-->デイリースクラム;
    デイリースクラム-->スプリントレビュー;
    スプリントレビュー-->スプリントレトロスペクティヴ;
```
### スプリントプランニングとは
スプリントプランニングとは、**スプリントのゴールを話し合い、そのゴールを達成するために必要な作業を計画するイベント**のことです。タスクに分割する過程において、今のスクラムチームでの実装可能性や設計、作業見積りも行われます。精度の高い見通しを示すためにも、必要なステップです。

### デイリースクラムとは
デイリースクラムは開発作業を円滑かつ最適化するとともに、予定どおりに進んでいるか、課題はないか確認する目的で開催されるものになります。特徴として***毎日同じ時間、同じ場所で15分程度、今後の作業計画やスプリントゴールに対する進捗の確認・調整***をします。精度の高い見通しを示すためにも必要なステップです。
また会議には開発メンバーも参加するため、個々のメンバーが自らなすべき役割とタスクをその場で確認することができ、後で認識の相違が起こる事態を防止できます。

### スプリントレビュー
スプリントレビューはスクラム開発を導入したプロジェクトで、スプリントの終わりに実施される会議の１つです。
スプリントレビューでは、**開発した機能を顧客に実演・プロダクトバックログの項目を更新・今後の開発の見通し**が行われます。

### スプリントレトロスペクティヴ
スプリントの最後に行われる、スプリントのふりかえりの会議で「ふりかえり」や「ふりかえりミーティング」と呼ばれることもあります。スプリントレトロスペクティヴでは下記の手順で進められます。
**1.直近のスプリントについて、評価を行う
2.良かった点や今後の課題について話し合う
3.スプリントの中で課題を解決した事例があれば、それを取り上げる
4.次回以降のスプリントにおける改善点を出す**
スプリントレトロスペクティブは今後のスプリントをより良く実施し、スプリントの効果と成果物の品質を上げるこために行われます。
## アジャイル開発のメリット・デメリット

### メリット
- 開発のスピードは速い
- スケジュールを柔軟に組むことが出来る
- 仕様変更や追加対応も可能なのでユーザーのニーズに最大限応えることができる

### デメリット
- 開発の方向性がぶれやすい
- 全体の進捗状況やスケジュールの把握が難しい

## 最後に
いかがでしたでしょうか。先月までの僕みたいになんちゃってアジャイル開発をしている人は沢山いるかなと思います。今回の記事がそのような方であったり、プログラミング初学者の参考になれば幸いです。

## 参考記事
- [アジャイル開発とは？　特徴とメリット・デメリット、スクラムまで徹底解説](https://monstar-lab.com/dx/solution/about-agile_methods/)
- [アジャイル開発とは？今さら聞けない開発手法のメリット・デメリット](https://hnavi.co.jp/knowledge/blog/agile_software_development/#title1)
- [スクラム開発で用いられるスプリントとは何か？いまさら聞けないアジャイル開発の用語を解説](https://ssaits.jp/promapedia/glossary/sprint.html)
Discordの通知設定の仕様まとめ

Discordの通知設定に関するUIと仕様がわかりにくかったので、1枚の画像でまとめました。
![Tw_Discordの通知設定の仕様_20230207-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/e3be7e7d-1800-1980-7aa7-7c2ed0bb484a.png)
Files.newBufferedReader

```java
public class Outer {
    public static void main(String[] args) throws Exception{
        
        Path p = Paths.get("C:\\dirtest\\testfile.txt");
        Path p2 = Paths.get("C:\\dirtest");
        File f = p2.toFile();
        if(!Files.exists(p)) {
            Files.createFile(p);
        }
        BufferedWriter bw = Files.newBufferedWriter(p,StandardOpenOption.APPEND);
        Scanner sc  = new Scanner(System.in);
        try(bw) {
            String str = sc.nextLine();
            bw.write(str);
            bw.newLine();
            bw.flush();
        }
        BufferedReader br = Files.newBufferedReader(p);
        String readStr;
        try (br) {
            while((readStr = br.readLine()) != null)
            System.out.println(readStr);
        }
    }
```
```
pp      <<System.in input
ppp     <<above is testfile.txt body
kkk
lll
pp
```
No.5 サンプルレポートを使う

## はじめに
このセッションでは標準で用意されているサンプルのレポートを使う手順を説明します。
これまで紹介したサンプルデータやビジュアルの作成方法でレポートはある程度作成できるようになってきたと思いますが、色んなレポートを見ると自分のデータの可視化のイメージが持てるかと思いますので、クイックに紹介させていただきます。

## サンプルレポートを開く
**1．Power BIサービスを開き、「詳細」を押下**
**2．画面下部にいくとサンプルレポートが表示される**
**3．任意のレポートを表示**
![ezgif-1-ddef2c66b2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/5d355a1d-ccf9-5911-77e2-f3531a65744f.gif)

## サンプルレポートの使い方
・ビジュアルの組み合わせ方を学ぶ
・ビジュアルの配置（デザイン）を学ぶ
・サンプルレポートは編集できるため、レポート作成の練習に利用する

※サンプルレポートの編集画面↓
![スクリーンショット 2023-02-06 19.43.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/ee47a463-924a-994c-49db-c808637b5e5d.png)

こちらのセッションは以上です。
[→ Power BI サービス練習帳に戻る](https://qiita.com/shinyasasaki/items/391d50c2508794e8fcfd)