OmniAICreator/Qiita-1.07M huggingface dataset:
ArduinoとESP32のWire.begin()の差異

# ArduinoとESP32のWire.begin()の差異
ソフトウェアI2Cを調べていて、両者の差異に気がついたので記録しておく。

## ソフトウェアI2C
何らかの理由で、マイコン搭載のI2C（ハードウェア）ではなく、GPIOを用いてI2Cを利用したいこともある。今回の参考記事は、[これ](http://zattouka.net/GarageHouse/micon/I2C/I2C_5.htm)や[これ](https://qiita.com/iigura/items/009a2dac7a2028261e39)など。

## ArduinoのWire.begin()
[本家の情報](https://www.arduino.cc/en/Reference/WireBegin)。

```
Wire.begin()
Wire.begin(address)
```
これだけ。好みのGPIOを用いるには、ソフトウェアI2Cライブラリ（後述）を使う必要あり。

## ESP32のWire.begin()
いきなりgitのソースコードとなるが、[こちら](https://github.com/espressif/arduino-esp32/blob/master/libraries/Wire/src/Wire.h)。

```
bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); // returns true, if successful init of i2c bus
```
つまり、Arduinoとは異なり、

```
Wire.begin(26,27);
```
のような使い方ができる。これだけ。シンプル。

## ソフトウェアI2Cライブラリ利用方法(Arduino)
[Arduinoサイト](https://playground.arduino.cc/Main/SoftwareI2CLibrary/)経由でたどり着く、[ここ](https://github.com/felias-fogg/SoftI2CMaster)が本家本元の一つ（他にも見つかる）。下記のように使用したいGPIOを指定して使う。

```
#define SDA_PORT PORTD
#define SDA_PIN 2
#define SCL_PORT PORTD
#define SCL_PIN 3
#include <SoftI2CMaster.h>
#include <SoftWire.h>

SoftWire Wire = SoftWire();
```
このあとは、

```
Wire.begin();
```
と指定するのみ。

## 終わりに
個人的には、ESP32のように直接GPIOを指定できる方がうれしい。好みの問題だが。
mindの研究 その15

# 概要

mindが謎なので調べてみた。
vistaに入れた。
練習問題、やってみた。

# 練習問題
mindで電卓を作れ。

# 方針
- インタープリター方式
- 右から順に計算。

# サンプルコード


```
メインとは
　文字列１は　文字列
　単語は　文字列
　合否は　変数
　数１は　変数
　合計は　変数
　算子は　変数
　ここから
　　合計を　クリア
　　算子を　クリア
　　「>」を　表示し　文字列入力し　文字列１に　入れ
　　文字列１が　「bye」に　等しい文字列　ならば
　　　打ち切り
　　つぎに
　　ここから
　　　文字列１から　単語切り出し　単語に　入れ
　　　単語が　空列？　ならば
　　　　打ち切り
　　　つぎに
　　　単語を　数値変換し　数１と　合否に　入れ
　　　もし　合否が　真？　ならば
　　　　もし　算子が　０に　等しい　ならば
　　　　　数１を　合計に　入れる
　　　　つぎに
　　　　もし　算子が　１に　等しい　ならば
　　　　　合計に　数１を　加え　合計に　入れる
　　　　つぎに
　　　　もし　算子が　２に　等しい　ならば
　　　　　合計から　数１を　引き　合計に　入れる
　　　　つぎに
　　　　もし　算子が　３に　等しい　ならば
　　　　　合計に　数１を　掛けて　合計に　入れる
　　　　つぎに
　　　　もし　算子が　４に　等しい　ならば
　　　　　合計を　数１を　割って　合計に　入れる
　　　　つぎに
　　　つぎに
　　　もし　単語が　「+」に　等しい文字列　ならば
　　　　算子に　１を　入れ
　　　つぎに
　　　もし　単語が　「-」に　等しい文字列　ならば
　　　　算子に　２を　入れ
　　　つぎに
　　　もし　単語が　「*」に　等しい文字列　ならば
　　　　算子に　３を　入れ
　　　つぎに
　　　もし　単語が　「/」に　等しい文字列　ならば
　　　　算子に　４を　入れ
　　　つぎに
　　繰り返し
　　合計を　数値表示し　改行し
　繰り返し。





```

# 実行結果

```


>1 + 2 * 3 - 4 / 5
1
>33 * 3
99
>999 / 33
30
>bye


```

以上。
対神エクセル！改行や余計なスペース含むキーワードの検索【ExcelVBA】

1. セルの幅に合わせて改行やスペースでレイアウト調整してるやつ
1. 非表示セルを含む結合セル

|改<br>行|スペース|
|:----------:|:------:|
|神<br>エ<br>ク<br>セ<br>ル<br>|神　　エ　　ク　　セ　　ル|

こんなのにも対応できる検索フォーム

## 概要
- 非表示範囲を含む結合セルが相手でもヒットします
- 改行やスペースなどの余計なものがあってもヒットします
- 検索結果一覧をユーザーフォームに表示し、
<br>リストをダブルクリックすると検索結果セルにジャンプします
- 選択範囲内のみ検索します（全体を検索したければ全選択後にお願いします）
- 大文字/小文字は完全一致でないとヒットしません

## やること

### ユーザーフォームの作成

1. ユーザーフォームを挿入し、<br>
モジュール名を`UserForm3Find`に設定。<br>
(モジュール名は何でも良いのですが、標準モジュール上の`UserForm名.show`の部分と揃える)
1. リストボックスとラベルを挿入し<br>
リストボックスのオブジェクト名を`ListBox_検索結果`にする。<br>
（ラベルはあってもなくても良いですがキャプションに補足事項を記入した方が使用時に分かりやすい。<br>
ラベル例：「クリックで指定セルを選択状態／ダブルクリックで閉じます」）
1. あとは下記コードをコピペするだけ


``` vb
Private Sub UserForm_Initialize()
        Dim i As Long
        Dim Find結果
        
        For i = 0 To UBound(FindResult)
            ListBox_検索結果.AddItem FindResult(i)
        Next i
End Sub

Private Sub ListBox_検索結果_Click()
    Dim 選択項目アドレス
    
    選択項目アドレス = Split(ListBox_検索結果.Text, "::")
    With Range(選択項目アドレス(0))
        .Select
        .EntireRow.Hidden = False
    End With
End Sub

Private Sub ListBox_検索結果_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
    Unload Me
End Sub
```

### 標準モジュールにコードをコピペする
``` vb
Public KeyWord As String
Public FindResult() As Variant
Public k As Integer


Sub 文字検索_非表示セルも余計な文字を含むやつもまとめて()
    On Error Resume Next

    Dim KeyWord As String, KW_Arr As Variant
    Dim c As Object, i As Integer
    
    Application.ScreenUpdating = False
    
    KeyWord = InputBox("検索ワードを入力してください")
    k = 0
    
    'キーワードの分解
        For i = 1 To Len(KeyWord)
           SplitKW = SplitKW & "*" & Mid(KeyWord, i, 1)
        Next i
    
    For Each c In Selection
        If c.Value Like "*" & SplitKW & "*" Then
'        If c.Value Like "*" & KeyWord & "*" Then
            ReDim Preserve FindResult(k)
            FindResult(k) = c.Address & "::" & c.Value
            k = k + 1
        End If
    Next c
    
    If k = 0 Then
        MsgBox "検索条件に一致するデータが見つかりません。"
    Else
        UserForm3Find.Show
    End If
    
    Application.ScreenUpdating = True


End Sub
```
PPで文字列操作

#PipelinePilotで文字列を操作する#
###1.文字列置換：StrReplace
**構文**

```
String StrReplace(String str, String substr, String replace[, Number num])
```
・全てのsubstrをreplaceに置き換える。
・strは変更されない。
・オプションのnumパラメータが指定されている場合、substrの最初のnum個のみが置き換えられる。

**例**
文字列「A bb CCC」を「A_BB_CCC」に置き換える。


```
text := strreplace(text, "A bb CCC", "A_BB_CCC");
```
但し、目的の文字列以外に同一文字列がないことが前提。
ある場合は、**rsubst**を使った正規表現で詳細な指定が必要。

###2. 正規表現：RMatch
**構文**

```
StringArray RMatch(String str, String regexp[, String options])
```
・規表現パターンregexpに一致するstrの部分文字列の配列を返す。
・オプション
g：グローバルマッチング（完全一致マッチング）。正規表現が文字列と一致する回数を返す。未指定の場合は最初のマッチングのみが一致。
i: 大文字と小文字を区別しないパターンマッチング。
m：文字列を複数行として扱う。
s：文字列を1行として扱う。
x：空白とコメントを許可して、パターンの読みやすさを拡張する。
・グループ化（）では、RMatch（）は**配列**を返す。最初の要素は完全一致パターン。後続の要素は、クエリで指定された各グループに一致するパターン。

**例**

```
 prop1 := 'aaaaaxbbbbbbbbycccccccccz'; 
 prop2 := rmatch(prop1, '(^.*)(x)(.*)(y)(.*)(z$)');

 returns:
 prop2[] 
 aaaaaxbbbbbbbbycccccccccz 
 aaaaa 
 x 
 bbbbbbbb 
 y 
 ccccccccc 
 z
```
※正規表現に関する補足
(　)：グループ化
^：直後の文字が行の先頭にある場合にマッチする
*：直前の文字が０回以上繰り返す場合にマッチする
.：任意の１文字
$:直前の文字が行の 末尾 にある場合にマッチする

※正規表現参考サイト
https://murashun.jp/blog/20190215-01.html
【Flutter】This class (or a class that this class inherits from) is marked as '@immutable', but one or more of its instance fields aren't final～の対処法

Flutter学習での先日のエラー。

##症状

```
This class (or a class that this class inherits from) is marked as '@immutable', but one or more of its instance fields aren't final: HomePage.cameras
```
このクラスはimmutableなクラスであるのに、final修飾子がないフィールド（メンバ変数）があるよと言っています。

### immutable（イミュータブル）とは

immutable（イミュータブル）とは、直訳で「不変」「変わらない」という意味。
プログラム的に言えば、作成後のオブジェクトの状態を変えちゃダメってこと。

StatelessWidget、StatefulWidegetを拡張するクラスではイミュータブルでなくてはなりません。

## 対処法：finalをつける

イミュータブルであることを明示するためにも、**StatelessWidget、StatefulWidegetを拡張するクラスのすべてのフィールドはfinalである必要があります。**ってよく見たら、警告でも言っていますね。

final修飾子をつけると、宣言後に値の変更をすることができません（説明不要かと思いますが念のため）。



ひとつfinal修飾子が抜けていたので修正すると無事解決。

```dart:修正前
class HomePage extends StatefulWidget {
  final Color pannelColor;
  final String title;
  List<CameraDescription> cameras;

  HomePage({
    @required this.pannelColor,
    @required this.title,
    @required this.cameras,
  });
```

```dart:修正後
class HomePage extends StatefulWidget {
  final Color pannelColor;
  final String title;
  final List<CameraDescription> cameras; // finalを付加

  HomePage({
    @required this.pannelColor,
    @required this.title,
    @required this.cameras,
  });
```

## そのほかの対処法
とにかく警告を削除したければ、クラス定義の頭に`// ignore: must_be_immutable`を追記してください。

## 参考

> https://stackoverflow.com/questions/54707731/this-class-inherits-from-a-class-marked-as-immutable-and-therefore-should-be-i
mindの研究 その14

# 概要

mindが謎なので調べてみた。
vistaに入れた。
練習問題、やってみた。

# 練習問題
mindで数9を4個つかって1から15までの数を表す式をつくれ。

# サンプルコード

```
メインとは
　９をつみ　９をつみ　引いて　９をつみ　９をつみ　割って　数値表示し　改行し
　９をつみ　９をつみ　割って　９をつみ　９をつみ　割って　加えて　数値表示し　改行し
　９をつみ　９をつみ　加えて　９をつみ　加えて　９をつみ　割って　数値表示し　改行し
　９をつみ　９をつみ　９をつみ　加えて　９をつみ　割って　複写し　加えて　数値表示し　改行し
　９をつみ　９をつみ　９をつみ　加えて　９をつみ　割って　複写し　加えて　引いて　数値表示し　改行し
　９をつみ　複写し　９をつみ　加えて　９をつみ　加えて　９をつみ　割って　引いて　数値表示し　改行し
　９をつみ　９をつみ　９をつみ　加えて　９をつみ　割って　引いて　数値表示し　改行し
　９をつみ　９をつみ　９をつみ　捨てる　９をつみ　割って　引いて　数値表示し　改行し
　９をつみ　９をつみ　引いて　９をつみ　掛けて　９をつみ　数値表示し　改行し
　９をつみ　９をつみ　割って　９をつみ　複写し　９をつみ　割って　加えて　数値表示し　改行し
　９をつみ　９をつみ　９をつみ　加えて　９をつみ　割って　加えて　数値表示し　改行し
　９をつみ　複写し　９をつみ　９をつみ　加えて　加えて　９をつみ　割って　加えて　数値表示し　改行し
　９をつみ　９をつみ　９をつみ　加えて　９をつみ　割って　複写し　加えて　加えて　数値表示し　改行し
　９をつみ　複写し　９をつみ　９をつみ　加えて　９をつみ　割って　複写し　加えて　引いて　加えて　数値表示し　改行し
　９をつみ　複写し　複写し　９をつみ　加えて　９をつみ　加えて　９をつみ　割って　引いて　加えて　数値表示し　改行し





```

# 実行結果

```


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

```

以上。
F#でブラックジャックを実装しました

# はじめに
以下の2記事に触発されて自分でもシンプルなブラックジャックを実装してみました。

[プログラミング入門者からの卒業試験は『ブラックジャック』を開発すべし](https://qiita.com/hirossyi73/items/cf8648c31898216312e5)
[F# で“卒業試験”ことブラックジャック開発をやってみた](https://qiita.com/vain0x/items/15ebf2fddde9036267b5)

![blackjack1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/711971/d1330276-d959-ea3c-aece-81e12e294147.png)

ソースコードはこちら。120行程度です。
https://github.com/msanou/BlackJackFsharp/blob/master/Program.fs

# 引いたカードの重複チェックについて
既に引いたカードの管理方法についてです。なるべくArrayなどのmutableなコレクションは使わずにやることを目指していたので、引いたカードをdeckとして引き渡しながら管理することにしました。

``` Fsharp
let rec pickCard hand deck =
    let card = { PlayingCard.Number = rand.Next(1,13); 
                 PlayingCard.Suit = rand.Next(1,4) |> enum<Suits> }
    if isCardExist card deck then pickCard hand deck
    else hand @ [card], deck @ [card]
```

はじめは山札を模したArrayを用意して……などと考えていましたが、今回のようなゲームだと山札を引き切るケースがまずないのでリストをシャッフルして要素を一つずつ減らしていくより記憶していく方がいいのかもしれない。
あと、かなりタプルを多用しましたが、もう少し冴えたやり方があるようにも思います。

# スコアの計算

``` fsharp
let calcScore hand =
    let temp = hand |> List.sumBy(fun x -> if x.Number > 10 then 10 else x.Number)
    hand |> List.fold (fun x y ->
        if y.Number = 1 && x <= 11 then x + 10 else x) temp
```
まず、J,Q,Kの点数を10点として手札の合計を計算します。そして、点数の合計が11を超えない場合に限り、エースのスコアを11として扱う(合計値に10足す)……という形なのですが、**「点数の合計が11点以下の時、エースのカードが手札に一枚でも含まれる場合は10を加算する」**で良かったですね。わざわざfold関数使わなくてよかった。

``` fsharp
let calcScore hand =
    let temp = hand |> List.sumBy(fun x -> if x.Number > 10 then 10 else x.Number)
    if hand |> List.exists (fun x -> x.Number = 1) && temp <= 11 then temp+10 else temp
```
このように書き換えられました。

# おわりに
メッセージの表示処理や入力の受付を記述する場所、判別共用体を手札とかに使ってバーストの判別をそのメンバにやらせるなど、色々他にも工夫の余地はあるように思います。

~~作って記事にでもしようと考えていましたが、思ったより何も書くことがない。~~
【連載】へっぽこエンジニアが「Webを支える技術」を要約してみた（第1章）

# はじめに
自分はWebの基礎を固めないままエンジニアとして過ごしていました。
そのことに焦燥感を感じることが多いため、今回 [技術評論社](https://gihyo.jp/book) から出版されている [Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)](https://gihyo.jp/book/2010/978-4-7741-4204-3) を要約する連載することにしました。

今回は第1章の要約となります。

[次回 - 【連載】へっぽこエンジニアが「Webを支える技術」を要約してみた（第2章）](https://qiita.com/sasanda_panda/items/e64032cc3fb3e7d6cd1e)

# 対象読者
「はじめに」を読んで心当たりのあるエンジニアの方。

# 第1章 Webとは何か
## 1.1 全ての基盤であるWeb
- 現在の私たちにとって最も重要なソフトウェアはブラウザ
- ブラウザはWebサーバーとやりとりをして情報を表示している

## 1.2 様々なWebの用途
### Webサイト
- クライアント (ブラウザ) でシステムがどのような構成になっているかを意識しないで済む

### UI = User Interface としてのWeb
- 人間向けのインタフェース  
  例 : テレビ、プリンタ...の設定画面

### API = Application Programming Interface としてのWeb
- プログラム向けのインタフェース  
  例 : XML、JSON...

## 1.3 Webを支える技術
### HTTP、URI、HTML
#### HTTP = Hypertext Transfer Protocol
- ホームページの情報をやり取りするときに使用される通信手順や規約のこと

#### URI = Uniform Resource Identifier
- 世界中のあらゆる情報を指し示す

#### HTML = Hypertext Markup Language
- 情報を表現する文書フォーマット

### ハイパーメディアシステム
- テキスト、画像、音声などのハイパーメディアをリンクで結びつけて構成したシステム

### 分散システム
- 複数のコンピュータを組み合わせて処理を分散するシステム  
- 1台のコンピュータで実行するよりも効率的に処理できる
- Webは大規模な分散システム (プロトコルがシンプルだから大規模になった)

# 今回のうろ覚えワード
- **プロトコル**  
  情報をやり取りするときに使用される通信手順や規約のこと

# 感想
- UIが人間向け、APIがプログラム向けという説明がとても腑に落ちた

# 参考
- [プロトコル (protocol)とは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word11.html)
- [HTTPとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word165.html)
JavaScriptでオブジェクトの配列に入っている要素をHTMLに一つずつ表示する

# まず、オブジェクトの配列を用意する

```
var array = [{id:1, name:"Ramen"}, {id:2, name:"Somen"}];
```

## HTMLを書く
```
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- ここのgetDataの部分にjsからデータを表示する -->
    <div id="getData"></div>
    <script src="code.js"></script>
</body>

</html>
```
## オブジェクトの配列を表示するためのJavaScriptのコード
```
 // 配列の長さの文だけループを回す
    for (var i = 0; i < array.length; i++) {
        // まず、idを表示する
        // Htmlのdivの部分を指定する
        var getData = document.getElementById('getData');
        // 表示したいデータを指定する
        var arrayId = document.createTextNode(array[i].id);
        // 要素を指定し、その要素の子要素としてデータを表示する
        getData.appendChild(arrayId);

        // 次に、nameを表示する
        var arrayName = document.createTextNode(array[i].name);
        getData.appendChild(arrayName);
    }
```

## 最終的なJavaScriptのコード
```
window.onload = function () {
    // オブジェクトの配列を用意
    var array = [{ id: 1, name: "Ramen" }, { id: 2, name: "Somen" }];

    // 配列の長さの文だけループを回す
    for (var i = 0; i < array.length; i++) {
        // まず、idを表示する
        // Htmlのdivの部分を指定する
        var getData = document.getElementById('getData');
        // 表示したいデータを指定する
        var arrayId = document.createTextNode(array[i].id);
        // 要素を指定し、その要素の子要素としてデータを表示する
        getData.appendChild(arrayId);

        // 次に、nameを表示する
        var arrayName = document.createTextNode(array[i].name);
        getData.appendChild(arrayName);
    }
}
```
## 最終的に

Htmlを開くとこのようにJavaScriptからのデータを表示することができます。


![code最終.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727321/d58fb0f0-247d-4280-318d-499af1243077.png)
Azure App Service (Windows) の Tomcat の構成変更


## この記事について
通常 Java アプリを使用し Tomcat の設定を変更する際「server.xml」を編集しますが、
Azure App Service で設定されているファイル「`D:\Program Files (x86)\apache-tomcat-x.x.xx\conf\server.xml`」は変更できません。
そこで以下の方法で Tomcat の構成を変更します。

## 1.前提
- Apprication settings で Java / Tomcat の設定が完了しているものとします。
- Kudu コンソールを利用を想定しています。`https://<YourAppName>.scm.azurewebsites.net/DebugConsole`
- 以下に内部のイメージを示します。
![Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/711136/24f7ca25-df27-e76c-5aea-0a3a84e8d766.png)


## 1.ディレクトリ構成
- Azure App Service の基本的なディレクトリ構成。

```
D:.
├─home
│  ├─LogFiles
│  └─site
│      └─wwwroot
│          │  web.config
│          │
│          ├─conf
│          │      server.xml
│          │
│          └─webapps ←アプリ(.war)のデプロイディレクトリ
│                  ROOT
│                  ROOT.war
│
└─Program Files (x86)
    └─apache-tomcat-x.x.xx
        └─conf
                server.xml
```



## 2.web.config の設定
 - IIS 構成ファイルであり Tomcat を起動するときに引数で追加構成を設定します。
 - JVM のメモリ設定が可能です。
 - 以下のサンプルでは、変更した Tomcat の設定ファイル「server.xml」を引数として設定しています。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<system.webServer>
		<handlers>
			<remove name="httpPlatformHandlerMain" />
			<add name="httpPlatformHandlerMain" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
		</handlers>
		<httpPlatform processPath="D:\Program Files (x86)\apache-tomcat-x.x.xx\bin\startup.bat" requestTimeout="00:04:00" arguments="-config D:\home\site\wwwroot\conf\server.xml start" startupTimeLimit="60" startupRetryCount="3" stdoutLogEnabled="true">
			<environmentVariables>
				<environmentVariable name="CATALINA_OPTS" value="-Xms2048 -Xmx2048m" />
			</environmentVariables>
		</httpPlatform>
	</system.webServer>
</configuration>
```



## 3.server.xml の設定
 - 上記2.で設定したパスに「server.xml」ファイルを作成します。(D:\home\site\wwwroot\conf\server.xml)
  <br>※server.xmlは「`D:\Program Files (x86)\apache-tomcat-x.x.xx\conf\server.xml`」からコピーし、必要に応じて変更してください。
【Vue + Firebase】 yarn serveでは画面が表示されるがfirebase serveで真っ白になる

解決するのに相当時間がかかりました。
なかなか情報が見つからなかったので残します。

##事象
`yarn serve` や `npm run serve` では画面が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422235/10f1c866-1227-4b03-5501-c0d2b0a29074.png)

しかし `firebase serve` では画面が表示されず真っ白になる。
ウィンドウタイトルには `<%= htmlWebpackPlugin.options.title %>` と表示される。
`firebase deploy` した場合も同じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422235/8dbc15a3-482f-2e8e-f8b6-8ef6dcdb4b51.png)

## 原因
`firebase init` した後、以下の質問で `public` のままにしていたため。

```
? What do you want to use as your public directory? (public)
```

`yarn build` や `npm run build` すると `dist` へファイルが作られるため、デプロイ対象を `dist` にする必要がある。

```
? What do you want to use as your public directory? dist
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422235/3d887d3a-7dde-40e1-29c7-43f8cd9dd1fe.png)


##参考
以下の記事を見ていて気付きました。ありがとうございました。

- [Vue.js + Firebaseで自己紹介用の静的サイトを作ってみた 第1弾 環境構築編](https://qiita.com/cube_3110/items/7cfa7ac5cc611f3e0e92)
- [24歳にして初めてvue+firebaseでwebサイトを作った話](https://tech-blog.cloud-config.jp/2019-12-31-created-my-website/)

また、類似の事象で相対パスを指定して直るケースがあるようです。

- [Vue-CLI3でbuildすると画面が真っ白になる](https://qiita.com/heyheyww/items/5d06936745118045a308)

メモ: baseUrlではなくpublicPathにする。

```vue.config.js

module.exports = {
    publicPath: './'
}
```
文字列配列を長さ&五十音順にソートする

# はじめに
文字列でできた配列を単語の長さでソートし，かつ五十音順にしたいケースがあったのでメモとして残す。

# 解決方法
※ いただいたコメントを元に修正しました。shiracamusさんありがとうございます！!

```python
words = ["にほん", "あめりか", "ろしあ", "ふらんす", "いたりあ", "ちゅうごく", "しんがぽーる", "おーすとらりあ", "たい", "ちり", "どいつ", "いぎりす"]
words = sorted(words, key=lambda word: (len(word), word))
print(words)
```
出力結果は次のようになります：

```python
['たい', 'ちり', 'どいつ', 'にほん', 'ろしあ', 'あめりか', 'いぎりす', 'いたりあ', 'ふらんす', 'ちゅうごく', 'しんがぽーる', 'おーすとらりあ']
```

簡単ですね。
もっと良い方法があれば教えてください。
OOP (E, C, EC), ECS

簡単にデータ管理の分類分けをします

あまり分かっていません

# OOP

## E (e.g. Godot Engine (?))

Node を継承する。

すでにトレンドから外れているが、とにかく速くゲームを作ることができる。

## C (e.g. MonoBehavior)

Entity へのアクセスが禁止されている。

ロジックを Component へ埋め込むことが推奨される。

## EC (e.g. Nez)

Entity と Component へのアクセスが許可されている。

Entity を継承することも考えられる。 Component のみ継承するなら C 寄り

# ECS (e.g. Flecs, Bevy ECS)

配列を component 毎に用意するか archetype 毎に用意するかで実装の分類分けができる。

データ／ロジックは Component/System 開で完全に分離される。

# 観点

* グローバルな component (resource) の有無
* 親子関係のサポート
* イベント (メッセージ) のサポート
* prefab や state machine のサポート
【Kotlin】リフレクションで関数を呼び出す簡単なツールの作成方法

`Kotlin`でプログラムを書いていると、[Javaを前提としたリフレクションによるマッピングライブラリは基本的にKotlinで動かない](https://qiita.com/wrongwrong/items/b21e1d887cc926893352)ことから、「リフレクションか何かで動的にインスタンスを生成したい」という場面が有ります。
この記事では、そのような場面に素早く対応できるよう、リフレクションで関数を呼び出す簡単なツールの作成方法についてまとめます。

# 紹介する方法
この記事では、メソッドリファレンスの形で呼び出したい関数（e.g. コンストラクタ、ファクトリーメソッド）を取得し、以下の3ステップで引数の初期化・関数の呼び出しを行うことで、インスタンスを生成する方法を紹介します。

1. 呼び出し対象の関数（`KFunction`）を取得する
2. パラメータ(`KParameter`)を読み出す
3. パラメータと読み出し対象を突き合わせ、引数のマップ(`Map<KParameter, Any?>`)を作成し、これを用いて1を呼び出す

特殊な呼び出し方が必要になったり、高速化が必要な場合に関しては、この記事では触れません。

## 1. 呼び出し対象の関数（KFunction）を取得する
まず、メソッドリファレンスの取得についてです。
多くの場合、`KFunction`の取得は以下の2パターンで事足りるでしょう。

```kotlin:コンストラクタを取得する場合
class Sample(val foo: Int, val bar: String)

val constructor: KFunction<Sample> = ::Sample
```

```kotlin:コンパニオンオブジェクトに定義した関数を取得する場合
class Sample(val foo: Int, val bar: String) {
    companion object {
        fun of(foo: Int, bar: String): Sample {
            return Sample(foo, bar)
        }
    }
}

val factoryMethod: KFunction<Sample> = (Sample)::of
```

## 2. パラメータ(KParameter)を読み出す
次に、パラメータ(`KParameter`)の読み出しについてです。

`KParameter`は引数の情報をまとめたクラスです。
`name`には引数名が、[`type.classifier`には、引数の`KClass`の情報が](https://qiita.com/wrongwrong/items/ef5aa2743789815e545d)格納されており、マッピングツールを作る場合には主にこの2つの情報が役に立ちます。

```kotlin
class Sample(val foo: Int, val bar: String)

val constructor: KFunction<Sample> = ::Sample
val parameters: List<KParameter> = constructor.parameters

val parameter = parameters.first()

println(parameter.name) // -> foo
println(parameter.type.classifier as KClass<*>) // -> class kotlin.Int
```

## 3. パラメータと読み出し対象を突き合わせ、引数のマップ(Map<KParameter, Any?>)を作成し、これを用いて1を呼び出す
最後に、読み出しと呼び出しについてです。
ここでは簡単な例として、`Map<String, Any?>`から読み出した情報を用いて`KFunction`を呼び出す処理を示します。

```kotlin
data class Sample(val foo: Int, val bar: String)

val constructor: KFunction<Sample> = ::Sample
val parameters: List<KParameter> = constructor.parameters

fun callFunction(src: Map<String, Any?>): Sample {
    val argumentMap: Map<KParameter, Any?> = parameters.associateWith {
        src.getValue(it.name!!)
    }
    return constructor.callBy(argumentMap)
}

println(
    callFunction(
        mapOf("foo" to 1, "bar" to "2")
    )
) // -> Sample(foo=1, bar=2)
```

# まとめ
この記事ではリフレクションで関数を呼び出す簡単なツールの作成方法を紹介しました。

実際にマッピングツールを作る場合には、引数名と読み出し対象のマッチングのための変換や、引数の型に合わせた読み出し処理が必要になりますが、大枠はここにまとめたやり方を応用することで実装できると思います。
『暗号技術入門 第3版（著：結城 浩）』のクイズをJavaScriptで試す

結城 浩さんの『[暗号技術入門](https://www.sbcr.jp/product/4797382228/)』を読んで、
「せっかくなら勉強中のJavaScriptで解こう！」と思ったので、備忘を兼ねて投稿します。

## P.26 &nbsp; クイズ① シーザー暗号

### 問題内容

下記の通りです。

```text:問題文
シーザー暗号化（※）された暗号文『PELCGBTENCUL』を解読してください。鍵は不明です。
※「abcde」を「bcdef」のようにズラしてメッセージを暗号化する方法
```
シーザー暗号の詳細は[こちら](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwj8u8GEkfPrAhXTa94KHSzZD1oQFjAAegQIBBAB&url=https%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%25E3%2582%25B7%25E3%2583%25BC%25E3%2582%25B6%25E3%2583%25BC%25E6%259A%2597%25E5%258F%25B7&usg=AOvVaw3OgSOsP5aWfi2FPGnWOYni)をご参照ください。

***

### 問題を解いたコード

下記に解いたコードを載せます。やり方としては、

1.  「a」〜「z」のアルファベットを文字列として格納した配列を作る
1.  問題文で与えられた暗号文に存在する全文字で、「この文字はアルファベット配列の要素でいうと何番目になるか」を調べて、新しく配列を作る（もし暗号文が 'abc' だったら、[0, 1, 2]の配列を作る）
1.  作成した配列の全要素に対して、「a」〜「z」の全アルファベット26回分、１つずつ後ろにずらす処理をする。（0回目：[0, 1, 2] 1回目：[1, 2, 3] ...というイメージ）
1.  １つずつ後ろにずらす処理をする度に、数字の配列を元のアルファベットに戻す（[0, 1, 2]なら abc、[1, 2, 3]ならbcd）
2.  アルファベットに戻すたびに、関数から返す配列 `decryptedArray` に追加する
3.  「アルファベットに戻したもの」の配列を `return` する
4.  `return` した `results` を１つずつ取り出して、コンソールに出力する


```javascript:caesar.js
function convertTextToIndex(cryptedText) {
  let splitted = cryptedText.split('')
  return splitted.map(val => alphabets.indexOf(val))
}

function bruteForceAttack(indexArray) {
  let decrypedArray = []

  for (let i = 0; i < alphabets.length; i++) {
　　 // 手順３
    const shiftedIndexArray = indexArray.map(value => {
      let shiftedIndex = value + i
      if (shiftedIndex > alphabets.length-1) return shiftedIndex - alphabets.length
      return shiftedIndex
    })

　　 // 手順４,５
    decrypedArray.push(shiftedIndexArray.map(num => alphabets[num]).join(''))
  }
　 // 手順６
  return decrypedArray
}

// 手順１
const alphabets = [
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
];

const cryptedText = 'pelcgbtencul';

// 手順２
const indexArray = convertTextToIndex(cryptedText);


const results = bruteForceAttack(indexArray);

// 手順７
results.forEach(result => console.log(result.toUpperCase()));

```

分かりにくかったらすみません。
理解度が少し上がったら、もっと分かりやすく書き直します。
<br>
おかしな実装等あればビシバシご指摘いただけると嬉しいです、
よろしくお願いします。
form_withメソッドの使用方法


【概要】
----------------------------------------
<b>1.結論</b>

<b>2.どのように使用するか</b>





1.結論
----------------------------------------
<b><%= form_with(model or URL, ) do |f| %></b>と使用する！
<br>


2.どのように使用するか
----------------------------------------

自分はこのように使用しました！

```ruby:views/time/new.html.erb
<%= form_with(model: @time, local: true) do |f| %>
```

自分は”model”に@timeでインスタンス変数を入れました。
modelの後にurlでpath指定してあげるとpathによってmethodも自動で振り分け機能になり、そしてアクションも指定できます。またpathの中に(****.id)と指定するとidを引っ張った状態でアクションを行えます！

class=""指定してあげて、cssにあてることもできます！

|f|はヘルパーメソッドに適用でき、form_withの中身を"f."がついているものに入れ込むことができます！
|f|は変数のようなものなので使いやすい名前で統一したもらえばOKです！

f.label
f.checkout
f.password_field
f.email_field等のヘルパーメソッドに適用できます！

<br>
Let’s EncryptでSSL証明書を発行しているサイトが古いAndroidで映らなくなる！？⇒ちょっとだけ延命した！

Android OSのバージョンがAndroid7.1.1未満の機種は、2021年9月30日以降Let’s EncryptでSSL証明書を発行しているサイトが映らなくなります。

これは、Let’s EncryptがSSL証明書に利用しているルート証明書の「DST Root X3」という証明書が2021年9月30日で有効期限が切れるからなのですが、**実はそれよりも先に対応をしていないともっと早い段階で映らなくなります。**

ちなみに、2020/09/19現在、ネットで拾ってきた情報によると、日本国内のスマホのシェアの内、Android7.1.1未満の機種の割合は5%ほどだそうです。（20人に1人映らなくなる・・・！）

# Let’s Encryptとルート証明書の仕組み

Let’s EncryptはSSL証明書にLet's Encryptを運営している非営利団体のISRGが発行しいている「ISRG's root」というルート証明書を利用しているのですが、この証明書が比較的新しいルート証明書(2014年発行)のため、古いOSにはインストールされていません。

なので、今までは「DST Root X3」というルート証明書を中間証明書として、「DST Root X3」経由で認証を行っていました。

## 今までの認証までのイメージ
* DST Root X3・・・Android7.1.1未満も対応したルート証明書
* ISRG's root・・・Android7.1.1未満は非対応の新しいルート証明書

``` WEBサイト ⇒ DST Root X3 ⇒ ISRG's root ⇒ 認証OK！ ```

ところが、「DST Root X3」の有効期限が2021年9月30日までとなるため、Let's Encryptの認証は「DST Root X3」の中間証明書を経由しなくなります。

## 今後の認証までのイメージ
``` WEBサイト ⇒ ISRG's root ⇒ 認証OK！ ```

つまり、Android7.1.1未満も対応したルート証明書である、「DST Root X3」を中間証明書として経由していたから映っていたAndroid7.1.1未満の機種で、サイトが映らなくなってしまいます。

# 映らなくなるまでのリミット
では、「DST Root X3」の有効期限が2021年9月30日までに対応すればいいかと言われるとそうでもなくて、Let's Encryptがこの「WEBサイト ⇒ ISRG's root ⇒ 認証OK！」の仕組みに切り替える時期はもっと早いです。（そりゃギリギリなわけないですよね）

なので、Let’s Encryptは、救済策として「古いOSも対応したい人は中間証明書を今まで通り使ってね」と中間証明書を指定して証明書を発行できるようなオプション機能を2020/07/25に実装した上で、**2020/9/29に切り替えるとアナウンスしていました。**

ました。過去形です。

どうやらその救済策の浸透があまり広まっていないらしく、**2020/9/18に公式サイトで、切り替えは2021/01/11に延期すると発表がありました。**

なので、実際には2021/01/11までに(正確には2021/01/11以降に証明書を更新するまでに)対策をすれば、古いOSでも引継ぎSSL認証が可能です。

# 対策
* 2021/01/11まで
 * 証明書の発行に、中間証明書を指定して発行するようにオプションを指定する

* 2021/09/30まで
 * ~~Android7.1.1未満とサヨナラする心構えをしておく~~
 * Let’s Encrypt以外の証明書を用意
 * 別の中間証明書を利用する(未確認)
 




## 参考
https://community.letsencrypt.org/t/transition-to-isrgs-root-delayed-until-jan-11-2021/125516
Laravel NovaのCardやActionで自作クラスを作らずにインスタンス化する

Laravel NovaのCardやAction, Filter、Partitionですが、基本的には自作クラスを作る必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47327/b50865e4-887d-e4b2-9586-d533ad06fefb.png)


```console:カードの作成例
$ php artisan nova:card acme/analytics
```

https://nova.laravel.com/docs/3.0/customization/cards.html

```php:AnalyticsCar.php
<?php

namespace Acme\Analytics;

use Laravel\Nova\Card;

class Analytics extends Card
{
    /**
     * The width of the card (1/3, 1/2, or full).
     *
     * @var string
     */
    public $width = '1/3';

    /**
     * Indicates that the analytics should show current visitors.
     *
     * @return $this
     */
    public function currentVisitors()
    {
        return $this->withMeta(['currentVisitors' => true]);
    }

    /**
     * Get the component name for the card.
     *
     * @return string
     */
    public function component()
    {
        return 'analytics';
    }
}
```

こうして作ったクラスをリソースに登録します。

```php:Analitcs.php（リソース）

...
public function cards(Request $request)
{
    return [new Analytics];
}
...
```


作成 -> 登録が面倒な場合には無名クラスを使うと便利です。


```php:Analitcs.php（リソース）
public function cards(Request $request)
{
    return [
       (new class extends Card {
              public $width = '1/3';
              public function currentVisitors()
              {
                 return $this->withMeta(['currentVisitors' => true]);
              }
       ),
   ];
}
```

こうすることでクラスを作らなくともいきなりカードの登録ができます。

インスタンスからメソッドの呼び出しも可能です。

```php:Analitcs.php（リソース）
public function cards(Request $request)
{
    return [
       (new class extends Card {
              public $width = '1/3';
              public function currentVisitors()
              {
                 return $this->withMeta(['currentVisitors' => true]);
              }
       )->currentVisitors(),
   ];
}
```

複数のリソースをまたがったりする場合にはクラスを作ったほうが良いですが、ちょっとカードを使いたいときは無名クラスが便利です。
なるべくgitを理解させず他人にgitを使わせたい

# gitを運用する上の問題

俺はgitを完全に理解している。だが俺以外のメンバーはgitを理解していない。
理由は単純、gitは難解だからだ。
そういうときに「勉強しろ！」というのはプロとしての「怠慢」なのである。

# どうするか

gitは諦めて前時代的な管理方法 (RCSやSVN) を使うか？それはあり得ない。[^1]
極めて単純化した運用を練っておくことでgitという難解なツールを使ってもらうのである。
運用としてはGitHub-Flowに近いものを使います。git-flowなぞ高度なことさせられません。

[^1]: SVN派の皆さんすいません。

# ブランチの種類

- featureやfix: トピックブランチ
- develop: デプロイ可能な開発用ブランチ
- master: 製品となったコードの格納先

各ブランチは複数持つことを許容します。feature/new-buttonやdevelop/開発1、master/お客さんA みたいな。

# 開発中の作業として頼むサイクル

1. ソースコードの修正作業が発生する（機能追加やバグ修正）
2. `git checkout develop`
3. `git pull`
4. `git checkout -b feature/hoge` または `git switch -c feature/hoge`
5. いろいろソースをいじってもらう
6. `git add .`
7. `git commit -m "hogehoge"`
8. `git push -u origin feature/hoge` または事前に`git config push.default current`を仕込んでおいて`git push`
9. GitLabやGitHubとかでMR、PRしてもらう。
10. MRやPRを承認してもらう。

改めて見ると長いですね。大変だ。これを無意識にやっている方々は偉大ですね。

# あきらめたこと
- 作業単位にコミットを分けること
    - やるに越したことはないが分けるために頭や時間を使うくらいなら分けなくてよい。

# 問題
もし、自分の作業中に他人の変更がdevelopに発生した場合、適宜リベースするか？
それともdevelopを作業ブランチにmergeしてもらうか？という問題がある。
作業内容を見た感じほぼ同じじゃね？となるが、作業者が何をどこにマージするのかによって難易度が変わる。

## developへリベースする場合

作業のフローとしてはこんな感じ。
この場合、developの最新版に対して自分の差分をマージすることになる。

- `git pull origin develop`
- `git rebase origin/develop`
- 「自分の変更に対して」コンフリクトがあったら解決し、 `git rebase --continue`
- `git push -f`

## developを作業ブランチにmergeしてもらう場合
developのmergeは他人の変更を取り込む必要が発生する。他人の作業は理解し難い（したくない）。
この場合、古いバージョンのdevelopに対して自分の変更がある状態に加え、developの最新版をマージすることになる。
作業者の負担が多くなると思われる。

- `git pull origin develop`
- `git merge origin/develop`
- 「他人の変更に対して」コンフリクトがあったら解決し、 `git merge --continue`
- `git push`

# つまり

手順書を書いて、rebaseさせよう！ということ。おわり。
Rubyで簡単!参照の値渡し

祝　初投稿🎉
自分が理解する上で一番悩んだ参照の値渡しを
できるだけ噛み砕いてイメージで説明してみた。

ずれてる！
違う！
等あれば感想でご指摘いただくようお願いします。

この話はshallow copyやdeep copyの話に繋がるため、
rubyを操る上では大事。

## 参照の値渡しとは?

簡単に言ってしまえば、
引数で使うメモリ位置(<0x00000001>とか)らしきものを値で渡しちまおうぜ！
っていうような考え方。
とりあえずはメモリ位置の認識でいいかも。

〜渡し
っていうのは引数同士のコピーで起こる動作をそれっぽく言ったものとして掴んでおけばOK
そんなメモリ位置に入らねぇよってツッコミはなし。


## 文字列型と数値型の値の参照渡し
```ruby
  first  = 1
  second = first

  p first
  p second
```
のときの動作としてはこんな感じ

![スクリーンショット 2020-09-18 23.15.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727542/19c6beae-65d0-96d3-9fd6-de250a35a159.png)


これをそのまま出力するとこうなる。

```console
 1
 1
```


これを代入し直すと

```ruby
  second = 2

  p first
  p second
```

![スクリーンショット 2020-09-18 23.25.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727542/ec82f68c-f3a6-a9c8-d76f-c8012fd7802e.png)


こんな動きになる。
出力はもちろん

```console
  1
  2
```

ここまでは値渡しと同じ見た目のため、混同されやすい。
とりあえずは、
`参照しているメモリの値がメモリ番号から他のオブジェクト(今回は数値型)に切り替わることで、値渡しと同じような動作になる`
文字列も原理は同じため省略。


## リストとハッシュの参照の値渡し
rubyの配列の話。
個人的には`リスト`の方がしっくりくるので以後`配列`は`リスト`と呼称する。

```ruby
  first_list = [1,2]
  second_list= first_list

  p first_list
  p second_list
```
このときの出力はもちろんこうなる。

```console
  [1,2]
  [1,2] 
```

### さぁ代入してみよう

```ruby
  second_list[0]=3

  p first_list
  p second_list
```

このとき、参照の値渡しを知らないとこのような出力を期待する。

```console
  [1,2]
  [3,2]
```

無慈悲にも実際にはこう

```console
  [3,2]
  [3,2]
```

#### え、なんで？

このときの内部の動きを見てみる。
ここから少しややこしいので注意。
##### 最初のコピーの時

![スクリーンショット 2020-09-19 0.04.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727542/9046ee07-f9e0-f96f-f57f-80c01cc0c953.png)


#####　代入時
![スクリーンショット 2020-09-19 0.06.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727542/25aee50c-1c7d-ed51-b388-5e253f2e5c59.png)


こうなる。
rubyの特性上リストもオブジェクトのため、
その配下の別のオブジェクト(今回は数値型のオブジェクト)の値が入れ替わる。
つまり、
リスト・ハッシュの代入の際は、`リスト・ハッシュに代入するのではなく、配下のオブジェクトに代入している`


### この事象を回避したい！

回避するためには、実際に見られる値自体を複製する必要がある。
一番手軽な方法はこちら

```ruby
first_list=[1,2]
second_list=first_list.map{ |num| num }

p first_list
p second_list

second_list[0] = 3

p first_list
p second_list
```

出力はこう

```console
  [1,2]
  [1,2]
  [1,2]
  [3,2]
```

##### なぜ？
![スクリーンショット 2020-09-19 0.51.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727542/1c9a9f8b-8d5c-7208-0f95-15d45318b9c7.png)

中でこのように新しいリストを作成しつつ、
mapメソッドを使用してリスト配下のオブジェクト自体ををコピーしている。(最初の数値型と同じコピー)
その後に行う代入も最初のコピーと同じ動作が起こる。


## まとめ
1. rubyではコピーされる際に、対象のオブジェクトの位置をコピーする。
2. 参照の値渡しは、メモリ番号らしきものをコピーする。
3. 参照の値渡しも図にしちゃえば怖くない。

rubyの学習を進めていくと object_idやら何やら出てきますが、メモリ位置のようなものとして受け取っておけば理解しやすいです。
ざっくり説明するために細かい言葉などは正確ではありませんが、この記事が誰かの役に立てば嬉しいです。
# それでは、良いrubyライフを。
App IDのユーザーでIBM Cloudのポータルを利用する際に動的にアクセスグループを設定する

# 目的

前回の記事「[App IDのユーザーでIBM Cloudのポータルを利用する](https://qiita.com/teruq/items/af2c29d8bab6d6cbe91e)」では、App IDのクラウドディレクトリーに登録したユーザーで、IBM Cloudのポータルにログインできることを検証しました。しかし、ユーザーはクラウドアカウントに対して何の権限も持っていませんでした。今回は、同ユーザーにIAMのアクセスグループがもつ動的ルール機能をつかって、権限を自動的に付与してみます。

# 手順

前回記事の設定は完了しているものとします。

> [App IDのユーザーでIBM Cloudのポータルを利用する](https://qiita.com/teruq/items/af2c29d8bab6d6cbe91e)

## レルムIDの確認

IDプロバイダーであるApp IDのレルムIDを確認します。IAMの画面から確認できます。この画像ではぼかしていますが、この値を控えておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/953e9a38-111d-73fe-ca8d-7d06a92b8856.png)


## 動的ルールの作成

IAMでアクセスグループを作り、必要なポリシーを付与します。次に、動的ルールタブで、IDプロバイダからもらうカスタムプロパティがどのような値だったらこのアクセスグループの権限をユーザーに適用するかを指定します。

この例では、アクセスグループにはあらかじめteruzリソースグループに対する管理者権限を割り当てています。IDプロバイダー欄は``appid://${先ほどのレルムID}``を指定します。ユーザーを追加する条件欄は、App IDユーザーに付与するカスタムプロパティ名を指定します。ここではresource-groupとしています。値欄はteruzとしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/b55509c0-3d4e-fd97-d4e4-66c35d4ab038.png)


## App IDのユーザーにカスタム属性を追加

次にApp IDでユーザーにカスタム属性を付与します。先ほどの動的ルールの条件に合わせて、

```
{ "resource-group": "teruz" }
```

とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/e405a254-ac08-7871-d299-b9d94186df56.png)

## ポータルにログイン

設定は以上です。このユーザーでポータルにログインします。ログイン方法は前回の記事を参照してください。次のようにリソースが見えるようになりました。なお、動的ルールを設定してから有効になるまで少し時間差があるようです。もし何も見えなかったら時間をおいてリロードしてみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/2bf1965b-136f-5cb4-d7dd-55dfc5e81efb.png)

# 考慮点

* 動的ルールを使う場合、ユーザーがどのアクセスグループに属するか、どのようなポリシーを持つかを直接確認することはできません（IAMの画面を見ても表示されません）ので、わかりづらいです
* App IDのカスタムプロパティはユーザーやプロパティが増えると編集が面倒なので、もし実運用で使うならばユーザー管理をするカスタムアプリを作るとよいでしょう
コードでわかる静的メソッド入門

静的とはインスタンス化することなくアクセスできるメソッドやプロパティで
`static::静的メソッド名()`や`static::$静的プロパティ名`としてアクセスする
このセミコロンはスコープ定義演算子という。多分秒で忘れる

```php:example.php
class クラス名
{
    アクセス修飾子 static $静的プロパティ名;
    アクセス修飾子 static function 静的メソッド名()
    {
    }
}
```

`$this`はインスタンスを示すものなので静的メソッドの内部で使用することはできない

```php:example.php
<?php
class Increment
{
    public static $cnt = 0;
    public static function increment()
    {
        static::$cnt++;
    }
    public static function showCurrentCnt()
    {
        return static::$cnt;
    }
}

echo Increment::$cnt;
Increment::$cnt = 100;
echo Increment::$cnt;

Increment::increment();
echo Increment::showCurrentCnt();
Increment::increment();
echo Increment::showCurrentCnt();
//クラス名に変数を使うことも可能
$class = 'Increment';
echo $class::showCurrentCnt();
```
実行結果は

```
0
100
101
102
102
```

``静的プロパティはクラスごとに唯一の値を持つので全てのインスタンスで共有される
どこからでも値の変更が可能なためグローバル変数と変わらず、多用すると可読性が下がりバグを生む原因になる``
Mermaid Examples

## Mermaid Examples

PlantUMLの方が表現力が高くて良いのだけど、Azure の Wiki だと、Mermaid ぐらいしか選択肢がない。

ちょろっとした構成図を書く分は画像貼り付けより使い勝手が良い。
よく忘れそうな人や、布教用にどうぞ。

### Nodes

1. labels

    ```mermaid
    ::: mermaid
    graph TB
      nodeA
      node_labeled["I'm nodeA."]
      node_multiline["foo<br/>bar"]
    :::
    ```

    **レンダリング例**

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326797/0828afef-cb16-d209-9a1e-8db0027ed8ff.png)


2. Node Shapes

    ```mermaid
    ::: mermaid
    graph TB
      a_rectangular_node["n1"]
      a_rounded_rectangle("n2")
      a_circular_node(("n3"))
      a_rhombus_node{"n4"}
      a_flag1_node>"n5"]
    :::
    ```

    **レンダリング例**
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326797/ebb57a17-ee17-ce54-1dd4-d368ce8962c9.png)

### Edges

1. arrow connection

    ```mermaid
    ::: mermaid
    graph LR
      A --> B
      A -- OK --> C
      A -->|This is the text| D
    :::
    ```

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326797/b1827e9d-67a9-d0cf-53b8-8116e11b9002.png)


2. doted connection

    ```mermaid
   ::: mermaid
   graph LR
     A -.-> B
     A -. OK .-> C
     A -.->|This is the text| D
   :::
    ```

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326797/0a2b1a5a-89a3-f5b7-216d-3e48bb9f5083.png)


3. Thick connection

    ```mermaid
   ::: mermaid
   graph LR
     A ==> B
     A == OK ==> C
     A ==>|This is the text| D
   :::
    ```

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326797/5a265e99-a467-11dd-baec-4b7018a88073.png)

4. line connections

    ```mermaid
   ::: mermaid
   graph LR
     A --- B
     A -- OK --- C
     A ---|This is the text| D
   :::
    ```
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326797/20dcd29f-63d8-8dbd-e5bd-ec1468bb6633.png)



### Layout

1. Sub graph

    ```mermaid
    ::: mermaid
    graph LR
      SPA["Single Page Application"]
      BFF["Backends For Frontends"]
      BE["Backends"]
      subgraph browser
        SPA
      end
      subgraph cloud["Cloud environment"]
        BFF --> BE
      end
      SPA -- port 443 --> BFF
    :::
    ```

    **レンダリング例**
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326797/8ea8aadf-991c-30da-d83f-6f24796240af.png)

## 参考

* [Markdown syntax for wikis in Azure DevOps - Azure DevOps | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops)  
  Sequence diagrams / Gantt Charts をサポートしている
* [mermaid · Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and...](https://mermaid-js.github.io/mermaid/)  
  本家
* [DiagrammeR - Documentation](https://rich-iannone.github.io/DiagrammeR/mermaid.html)
* [VScodeでmermaidを使ったmarkdown資料作りメモ - Qiita](https://qiita.com/ZOOSHIMA/items/693ee8fd93146dd69b0e)
Python with poetry での Dockerfile の効率的な書き方の模索

[Pythonの機械学習用Docker imageのサイズ削減方法の紹介](https://www.m3tech.blog/entry/reduce-python-docker-image-size) という大変有益な M3 blog を [twitter](https://twitter.com/m3_engineering/status/1306859277131427840) で見かけたので、便乗して自分が使っている Dockerfile との違いを簡単に書いてみようと思う。こちらは dashboard 用 Dockerfile であり機械学習用ではないので参考扱い程度に見てもらえればと。なお以下の内容が優れているとは思えないので better idea ある方にツッコミもらえれば幸いです。そしていつもながらインターネットの向こうの誰か1人に役に立ってもらえればも。なお、streamlit は大変便利。

## 結論
### 同じ部分

- poetry で version 管理
- multi-stage build を使う
- docker build は dev, prod で cache が効く

### 違う部分
- builder にて apt install を使わないなので builder も slim image を使う
- poetry install は使わず poetry export を使う（実行イメージにはpoetry入れない）。そして requirements.txt と requirements-dev.txt を作成。
- docker-compose.yml で dev, prod 切り替え
- vscode を使い remote-container で開けば、開発環境側に python が不要。

## code


### build

少し前は `.env` 内で `STAGE=` と環境変数を定義していたが、書き換えがめんどくさいのでやめた。

```bash
# dev build
STAGE=dev docker-compose build
# prod build
docker-compose up build
```

### Dockerfile

```dockerfile
FROM python:3.8.5-slim as builder

WORKDIR /work/src
RUN pip install --upgrade pip && pip install poetry
COPY pyproject.toml poetry.lock ./
RUN poetry export --without-hashes -f requirements.txt > requirements.txt
RUN poetry export --without-hashes --dev -f requirements.txt > requirements-dev.txt
RUN pip install -r requirements.txt

### for dev. 
FROM python:3.8.5-slim as dev
ENV PYTHONUNBUFFERED=1
WORKDIR /work/src
COPY --from=builder /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages
# need to copy if python package is installed in /usr/local/bin
COPY --from=builder /usr/local/bin/streamlit /usr/local/bin/streamlit
COPY src/ ./
# for dev packages
COPY --from=builder /work/src/requirements-dev.txt requirements-dev.txt
RUN pip install -r requirements-dev.txt
COPY tests/ ./
EXPOSE 8501  
CMD ["streamlit", "run", "hello.py"]

### for prod
FROM python:3.8.5-slim as prod
ENV PYTHONUNBUFFERED=1
WORKDIR /work/src
COPY --from=builder /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages
# need to copy if python package is installed in /usr/local/bin
COPY --from=builder /usr/local/bin/streamlit /usr/local/bin/streamlit
COPY src/ ./
EXPOSE 8501  
CMD ["streamlit", "run", "hello.py"]
```

### docker-compose.yml
```yaml
version: '3'

services:
  app:
    build: 
      context: .
      target: ${STAGE:-prod}
    image: "internal-dashboard_app_${STAGE:-prod}"
    container_name: "internal-dashboard_${STAGE:-prod}"
    volumes:
      - ./src:/work/src
    ports:
      - "8501:8501"
    restart: always
    command: ["streamlit", "run", "hello.py"]
```

### 感想

tests の path 問題をどう対処するかいつも悩んでます。
以上。
画像収集の方法

画像認識の実装をしたいなと思いましたので、データを取ってくることに。
今回は男性の写真と女性の写真を取ってきたいと思います。

# 実行環境
MacOS、Python3.6(anaconda)、VSCode

# 前回
前回はgoogle_images_downloadを使って画像を集めたのですが、google_images_downloadは100枚までしか集められなかったので、何度も実行しなければならず、面倒だなと感じたので、100枚以上のデータも取得できる方法ないのかなと思い、探したところ、ありました！
[Pythonで画像データを手軽に収集したい方必読！　icrawler入門](https://aiacademy.jp/media/?p=352)
icrawlerを使って今回はデータを取得してきました。

# 今回使った方法
```
pip install icrawler
```
これを実行してまずはicrawlerをインストールします。
そして、自分が使っているテキストエディタで

```python

from icrawler.builtin import BingImageCrawler
crawler = BingImageCrawler(storage={"root_dir": “ファイル名”})
crawler.crawl(keyword=“収集したいものの名前”, max_num=画像数)
```

これを実行して、画像を収集したら100枚以上の画像でも収集可能でした。

# まとめ
icrawlerの方が多く集められるし、そこまで大変でもないので、icrawlerの方のメリットが今のところ大きいですね。
また、これから使っていく中で、google_images_downloadの方のメリットもわかってくるのかもしれませんので、また勉強したいと思います。
マークダウン形式で　<> がエスケープされて表示できない時の対処法

マークダウン形式で、
<> を表示したい時、エスケープされてしまう場合、

ソースコードを ``` で囲むのではなく、

```
aaa
```

＜pre＞　← < と > は半角にする。で囲むとうまく表示できる。
　
<pre>
aaa
</pre>
amplifyのIAMユーザに適切なポリシーを設定したい

`amplify configure`を実行するとIAMユーザが作られます。

```
Specify the username of the new IAM user:
? user name:  amplify-AAAAA
```

amplifyチュートリアル的な記事などでは、このIAMユーザに管理者権限を振っていることが多い気がします。でも、なんかちょっと気持ち悪いですよね。適当に権限を制限しておきたいと思って調べたところ、以下を見つけました。

ADVANCED WORKFLOWS IAM Policy
https://docs.amplify.aws/cli/usage/iam

>The Amplify CLI requires the below IAM policies for performing actions across all categories. You can grant or restrict category permissions by including or removing items from the Action section as appropriate. For example, if you wish to restrict operations on the Auth category you can remove any of the lines starting with cognito.

このページに書かれているJSONで権限を制限してみたところ、`amplify push`で以下のエラーが発生。

>Following resources failed
>
>Resource Name: GraphQLAPI (AWS::AppSync::GraphQLApi)
>Event Type: create
>Reason: User: arn:aws:iam::xxx:user/amplify-AAAAA is not authorized to perform: appsync:TagResource on resource: arn:aws:appsync:ap-northeast-1:xxx:* (Service: AWSAppSync; Status Code: 403; Error Code: AccessDeniedException; Request ID: xxx; Proxy: null)

確かにJSONには`appsync:TagResource`が記載されていなかったので追加したところ、無事にpushも成功しました。
Fusion360でイレクターパイプのモデル(コンポーネント)を作成して組み立ててみた



#はじめに
イレクターパイプをFusin360上で仮組みしたり、可動部をシュミレーション出来たらいいなと思いモデル(コンポーネント)を作成しました。
現物を使って組み立ててみると、思った通りに動いてくれない事があったのでこれで捗りそうです。
オリジナルの部品を作成し、3Dプリンターで出力したりも楽しいです。ヘッドホンスタンドをイレクターパイプ用に作ったりしました。
イレクターパイプは矢崎化工株式会社様の商品です。自分でパイプとジョイントを組み合わせ色々作れるキットのようなものです。強度があり、拡張出来るので知らない人にもおすすめです。

#モデルを利用してこういうのが出来ます
##3Dプリンターラック
![棚1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536625/241267c0-30d2-4443-3916-f449bb3b4444.png)
![棚2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536625/dd2b8eef-cff7-b78c-6374-6fbf1989c414.png)
※Ender3の3Dモデルは[MakerBot Clucha_TV](https://www.thingiverse.com/thing:3318306"MakerBot Clucha_TV")からお借りしました
##ローデスク
![机1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536625/49f0225d-7b85-60ef-6b67-6edd0a0be2a0.jpeg)
![机2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536625/ae7e6e12-2359-d519-bb5c-80522092aa28.png)

#Fusion360内でイレクターパイプを組み立てたい人向けの準備
1. [ここ](https://github.com/mizutama-ichi/mizutama-ichi-erectorpipe-fusion360)からerector_pipe.zipをダウンロードして任意の場所に展開してください。この中にイレクターパイプのモデル(コンポーネント)が入っています。
2. Fusion360を開きます。
3. 新規でプロジェクトを作成します。プロジェクト名は自由ですが、ここでは分かりやすいようにイレクターパイプとします。
4. ファイルをクリックし、アップロードを開きます。1でダウンロードしたフォルダ内にある「イレクターパイプ 28mm」をアップロードのウィンドウにドラック アンド ドロップします。
5. 「場所を変更」からイレクターパイプのプロジェクト内にフォルダを作成します。フォルダ名は「イレクターパイプ 28mm」とします。作成したフォルダを選択し、アップロードをクリックします。

6. もう一度、ファイルをクリックし、アップロードを開きます。1でダウンロードしたフォルダ内にある「プラスチックジョイント」をアップロードのウィンドウにドラック アンド ドロップします。
7. 「場所を変更」からイレクターパイプのプロジェクト内にフォルダを作成します。フォルダ名は「プラスチックジョイント」とします。作成したフォルダを選択し、アップロードをクリックします。
8. 以上で準備は完了です。

#使い方
1. イレクターパイプ プロジェクト内に新規デザインからファイルを作成します。
※新規デザインはアップロードした部品と必ず同じプロジェクト内に作成してください。別々の場所に作成するとコンポーネントとして利用出来ません。
2. 左側のビューから利用したい部品探し、部品を右クリック「現在のデザインに挿入」で部品を追加します。
3. Fusion360の位置合わせ機能等を利用し、組み立てます。この際にそれぞれの面が選択されている事を確認してください。選択面がズレてしまうと後から直すのが大変です。
![位置合わせ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536625/02072ea0-cc63-3223-43fc-f6604859b135.png)
4. あとは2と3を繰り返し完成を目指します。

#注意事項
○モデルデータに関して
・細かいディティールは再現していません。実際の寸法と異なることがあります。
・パイプの長さは自由に作成するか、既存のパイプの長さを変更してください。
・現時点(2020年9月19日)で90個ジョイントを作りましたが、2つ未作成です。今後作るかは不明です。
・パイプ寸法(外形:27.6mm、内径:24.6mm)
・ジョイント差込口の寸法(外形:34mm、内径:28mm、肉厚:3mm)

○利用に関して
・個人または非営利目的での利用のみ可能です。営利目的での利用は禁じます。
個人、法人に別途、直接的または間接的に金銭等の利益を得る目的でのご利用は、営利目的での利用となりますのでご注意ください。
・本データを利用して生じた損害、障害、不利益等に対する責任は負いかねます。

#最後に
位置合わせの際にコンポーネント位置をキャプチャしておくと移動の履歴が残って便利です。
アセンブリ機能で可動部品のモーションをシュミレーション可能です。
このあたりのFusion360の使い方に関しては他のサイトでわかりやすく説明されているので割愛します。
コードでわかるクラス継承入門

既存のクラスを基にして拡張したり変更を加えた新しいクラスを作ることを継承するという
きっとこの記事にたどり着いたということはこれだけじゃピンとこなかったはず。。。
早速コードで見ていきたい

```php:example.php
<?php
class ParentClass
{
    public $test1 = 'テストプロパティ1';
    public $test2 = 'テストプロパティ2';
    public function getParentData()
    {
        return 'this is your parent';
    }
    public function show()
    {
        return $this->test1 . ' ' . $this->test2;
    }
}
class ChildClass extends ParentClass
{
    public $test1 = 'テストプロパティ3';
    public function getChildData()
    {
        return 'this is your child';
    }
    public function show()
    {
        return $this->test1 . ' ' . $this->test2;
    }
}
$child = new ChildClass();
echo $child->getParentData();
echo $child->getChildData();
$parent = new ParentClass();
echo $parent->show();
echo $child->show();
```

実行結果は

```
this is your parent
this is your child
テストプロパティ1 テストプロパティ2
テストプロパティ3 テストプロパティ2
```

となります
`親クラスを継承することで子クラスから親クラスのプロパティやメソッドを引き継げる`
多用すると親クラスの変更などによって予期せぬ結果が出ることがあるので
頭は体の一部のように子クラスは親クラスの一種といえない場合には使わない方がいい

`オーバーライド`
``クラスを継承して同じメソッドを定義した場合は子クラスが優先され上書きされる``

そのため上の例では`$test1`が子クラスでは上書きされている
データセット生成

これまでの学習ではデータセットが与えられた状態からの学習をしていたので、自分でデータセットを作ってみることにしました。
男性と女性の画像を集めて来たので、そこからデータセットを作成しました！

# 実行環境
MacOS、Python3.6(anaconda)、VSCode

# 画像をデータセットにする方法
今回データセットを作成するときに参考にさせていただいた記事になります。

[オリジナルの画像からデータセットを作成する方法](https://intellectual-curiosity.tokyo/2019/07/02/%E3%82%AA%E3%83%AA%E3%82%B8%E3%83%8A%E3%83%AB%E3%81%AE%E7%94%BB%E5%83%8F%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E6%96%B9/)

今回は画像のフォルダを4つ使いました。男性2つと女性2つです。

今回のデータセット作成の流れを言葉で表すと
①画像フォルダの中にある、ファイルを1枚ずつ取り出して、グレースケール化行う
②取り出すときにどのフォルダから取り出したかインデックス番号も一緒に取得する
③グレースケール化した画像を自分の好きなサイズに変更する
④**[画像、その画像が入ってたフォルダのインデックス番号]**の順になるように、リストに格納していく

＊今回は合計で400枚ほどでしたので、最後のリストには800個の要素が入っていることになります。

# 詰まった点
④でリスト化した値を取り出したいなと思ったときに、for文で2つ変数を用意すれば、1個飛ばしでデータが取り出せることは知らなかったので、驚きでした。

```python

for feature, label in training_data:
```
さらに、ここからはメモ代わりに残しておきます。

```python

os.listdir(A)
```
Aの中にあるファイルの一覧を表示できます。
＊Aというフォルダの中に(B, C, D)というファイルがあれば、B, C, Dを取得できる。

```python

os.path.join(A, B)
```
AとBを結合したPathを生成できます。

```python

cv2.imread(‘画像データ’)
```
画像データから配列の形に変換できます。

```
enumerate(変数名)
```
for文で取り出すときに、**「インデックス番号 要素」**で取り出せる

```
try:
   条件式　
except:
   pass 
```
**tryに条件式を書く + exceptにpassを書く= tryの条件式が来てもスルーする**
＊この条件式を書いてない時はエラーが起きる



最後に、matplotlibで日本語表記ができなかったのですが、
[Macにおけるmatplotlibの日本語表示](https://openbook4.me/sections/1674)
こちらの記事を参考にして、日本語表記ができました。

```python

import matplotlib as mpl
matplotlib.rcParams[‘font.family] = ‘AppleGothic’
```
こちらのコードを書けば日本語表記にすることができます！

# これからの課題
今回は男性と女性の顔の画像だけを本当は切り抜きたかったのですが、わからなかったので、とりあえず、そのままのデータでデータセットを作成しました。

なので、顔だけを切り抜くという処理を入れてデータセット作るようにまた調べていきたいと思います。

# まとめ
一応、データセットが分けられているか確認したところ、上手くできていました。
こうして自分で作ってみると、こんな風にしてデータセットを作成していっているんだなと感動しましたし、勉強になるところが多かったです。
Windows Serverとは...?

今更ですが、今回、ProやHomeとの違いを痛感しましたので
※当記事は正確性を担保していません。リモートネットワークのイメージができればいいや程度の記事です※

最近、Windows リモートデスクトップを本気で使おうかなと思いました。
理由は、一台の共有PCの中に入っているWindowsソフトウェアを同時に複数人が使えたらいいなと思ったからです。

①リモート接続するアカウントのパスワードを確認
②リモートデスクトップ接続するクライアントとサーバー両方を同一ルーターに接続する
③サーバーでPowershellでipconfigして、IPV4調べる
④クライアントのリモートデスクトップ接続アプリに③で調べたIPとアカウント名入力して接続

結構簡単にできました。このまま、別のPCからサーバーPC内の別アカウントにリモートしようとしたら

接続されていたリモートデスクトップが切断

これはWindowsのライセンス規約を確認すればたり前でした。

Windowsは基本的に1ライセンスにつき1アカウントのみが使用できる。つまり同時利用は許されない。
Oh my microsoft.....

で、この複数人による同時接続ができるライセンスがWindows Serverだ。
ライセンスの値段によるが、共有できるCPUコア数上限が16 core、上限アカウント数が5アカウントで
Windows Serverは約18万.....
Yah●o　オーク○ョンで1,800円という破格だったが....

結局、複数アカウントの同時接続がしやすいのはやはり「Linux」系のSSH接続だということだろう。
サーバーのOSに使われてるだけある、と痛感しました。
ラスタ形式とベクタ形式の違い

#ラスタ(Raster)形式とは

- 画像をピクセルで表現

- ラスタ形式の画像は`「ビットマップ画像」`とも呼ばれている

- btm、jpg、png、gifなどが該当する

- 写真などの複雑な画像に適しているが、拡大・縮小をすると画質が劣化する

- 作成できるソフト：ペイントソフト 
  例) Adobe Photoshop


#ベクタ(Vector)形式とは

- 画像を数値で管理

- PDF、SVG(Scalable Vector Graphics)などが該当する

- 拡大・縮小をしても画質が劣化しないが、写真などの複雑な画像には向いていない(ロゴや簡単なイラストには向いている)

- 作成できるソフト：ドローソフト
  例) Adobe Illustrator