OmniAICreator/Qiita-1.07M huggingface dataset:
C#_constとreadonlyの使い分け

# C#における定数値の扱い方
C#では変わらない値を定義する際に「const」「readonly」を使用すると思います。
何も知らずに使用しているとコードレビューなどで指摘されてしまうこともあるので、整理しておこうと思います。

## const
以下、Microsoftのリファレンスを引用してます。
>サービスの価格、製品バージョン番号、会社のブランド名などを格納するためには定数フィールドを使用しないでください。
>これらの値は時間の経過とともに変更される場合があります。コンパイラは定数を伝達するため、ライブラリでコンパイルされた他のコードを再コンパイルして、変更点を反映することが必要になってしまいます。

https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/const

つまり、**将来変更されることがあるような値には「const」を使用しない**ということですね。


## readonly
以下、Microsoftのリファレンスを引用してます。
>readonly キーワードは const キーワードとは異なります。 const フィールドは、フィールドの宣言でしか初期化できません。readonly フィールドは、フィールドの宣言と任意のコンストラクターで複数回割り当てることができます。 このため、readonly フィールドは、使用するコンストラクターに応じて異なる値を持つことができます。 また、次の例のように、const フィールドがコンパイル時定数であるのに対し、readonly フィールドは実行時定数として使用できます。

https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/readonly

つまり、言葉の定義としては以下のようになります。
* const フィールド→コンパイル時定数
* readonly フィールド→実行時定数




# サンプルコード
商品クラスについて考えてみます。
プロパティとして、以下を用意します。
* ID
* 名前
* 税抜価格
* 税込価格

メソッドとして、以下を用意します。
* 通貨単位をつけて税込価格を返却するメソッド
* 税込価格を計算するメソッド

```C#:Product.cs
	public sealed class Product
	{
		/// <summary>消費税 </summary>
		private readonly double CONSUMPTION_TAX = 1.1;

		/// <summary>通貨単位</summary>
		private const string CURRENCY_UNIT = "円";

		/// <summary>商品ID</summary>
		public string ID { get; }
		/// <summary>商品名</summary>
		public string Name { get; }
		/// <summary>税抜価格</summary>
		public string CostPrice { get; }
		/// <summary>税込価格</summary>
		public string PriceIncludingTax { get; }

		public Product(string id, string name, string costPrice)
		{
			ID = id;
			Name = name;
			CostPrice = costPrice;
			PriceIncludingTax = CulcPriceIncludingTax();
		}

		/// <summary>単位付きで税込金額を返却する</summary>
		public override string ToString()
		{
			return $"{PriceIncludingTax}{CURRENCY_UNIT}";
		}

		/// <summary>税込価格を計算する</summary>
		private string CulcPriceIncludingTax()
		{
			double priceIncludingTax = int.Parse(CostPrice) * CONSUMPTION_TAX;		
			// 四捨五入する
			double roundPrice = Math.Ceiling(priceIncludingTax);
			return roundPrice.ToString();
		}
	}
```

日本では、消費税は変わっていくものですよね。
私が生まれたときは消費税が5％でしたが、今では10％になってしまいました。
つまり、「消費税」はある時点での定数値と言えます。
この場合はreadonlyを使用してあげます。

一方、通貨単位に関してはどうでしょうか？
基本的に「円」という単位は変わらないですよね。
この場合はconstを使用してあげます。

以上、constとreadonlyの使い分けに関してでした。
Udemy講座での講座選びのポイント（成功談・失敗談）

この記事は「新人エンジニアにすすめたい、あなたの勉強法をシェアしよう！ by Udemy Advent Calendar 2022」の

新人に限らず、新しい技術を勉強しようとしたときに何を参考にされるでしょうか？

もちろん、対象となる技術の本家HPにはチュートリアルも用意してあるし、リファレンスも用意されていることが多いです。
本家のページには、最新の情報が載っているので非常に有用ではあるものの、チュートリアルは比較的単純だったり、理解が難しい記載になっていることもあります

そこで、おすすめなのはUdemyです。

## 動画/音声で学ぶことの有用性
HPや本などで学ぶ手法と異なり、Udemyでは動画。つまり目と音（声）で学ぶ事ができます。

動画である以上、画面に映し出された解説図などももちろん大事なのが、耳から情報を得るというのは記憶の定着に非常に役立っているのではないかと考えています。

Udemyの場合はアプリでDLさせておくことができるので、画面を見なくても講義の音声だけを聞き続けて頭にINPUTさせ続けることで意外と覚えていたりするものです。

特に通勤時間や散歩などのながら時間にもってこいなのです！

## こんな講座を選ぼう！
基本的に良質なコンテンツが多いUdemyですが、講座が作られたときには有用なコンテンツであっても、時間が経ってしまい最新の情報から見ると古い情報となってしまうこともあります。

おすすめなのは、更新し続けてくれるコンテンツです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25184/36a6f6e2-b824-443b-5d6b-eb592c501a02.png)

これは非常に有用な講座として人気の「[【SAA-C03版】これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座](https://www.udemy.com/course/aws-associate/)」ですが、試験やAWS側のサービスアップデートにともなって動画を取り直してくれたり、試験問題を更新していってくれます。

そのため、一度講座を完了したとしても、講座のアップデートを追いかけることで、範囲内のAWSサービスのアップデートを把握することができます！

もちろん、講座内容によっては頻繁なアップデートを不要としているものもあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25184/fa94c2c7-2555-b305-5dd8-aa443e891546.png)

「[【キカガク流】人工知能・機械学習 脱ブラックボックス講座 - 初級編 -](https://www.udemy.com/course/kikagaku_blackbox_1/)」のような、初級だったり、ある程度レベルを固定したものは最たるものでせうね。

これらに関しては、レビューを確認するようにしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25184/7def5014-b2e3-23e1-d14c-3b9761de913d.png)

ここは、ちょっとUdemyさんになんとかして欲しいところですが、レビューのソート条件を変更することができないので、最近なんて言われているのか？はわかりません。

高評価をつけている人は、場合によっては何も考えてないかもしれないし、サクラが混じっているかもしれないので、低評価の人の意見を確認して見るのが良いかもしれません。

## 失敗談
過去、資格試験勉強。予想問題集みたいな講座を受けたことがあり、そちらで勉強してから試験に臨んだものの大きくハズレた事がありました。

予想が外れたのであれば、それはしょうがないことですが、問題の難易度や形式にいたるまで本試験と異なっていたので流石に低評価をつけたことがあります。

難しいところは、資格試験の予想問題に関しては、最新情報をアップデートし続けていかないと行けないし、試験実施国によって問題範囲が異なる可能性もある。

それら講座に関しては充分な事前確認を行った上で受講を決めるようにしましょう。

## 最後に
当たり外れが多少あったとしても、何かしら新しいことに挑戦しようと一歩を踏み出してみるというのは素晴らしいことです！

特にUdemyではセールも頻繁に行っているので、気になったものをまずは手にとって見るということも決して悪いことではないと思っています。
そこで手に取ったものが良いものである可能性が少しでも上がるお手伝いができればと思いますので、よければ参考にしてみてください！
[Day14] クラス part2

本記事は一人アドベントカレンダー企画の一つです。
[30代未経験エンジニアが25日後にJavaScriptをマスターするカレンダー](https://qiita.com/advent-calendar/2022)

[JAVASCRIPT.INFO](https://ja.javascript.info/)を元にJavaScriptを勉強していき、そこで学んだ知識をアウトプットしていきます。
２５日でJAVASCRIPT.INFOをやりきり、未経験エンジニアがJavaScriptをマスターする過程を投稿していきます。



## 9.５ 組み込みのクラスを拡張する
### 知らない単語
- ネイティブとは
    - 主にソフトウェアにおいて、あるCPUやオペレーティングシステムが本来サポートするインターフェイスを利用するもの


### 学んだこと
Array、Map などの組み込みのクラスも拡張可能である

例えば、下記は PowerArray がネイティブの Array を継承している
```javascript
// 1つメソッドを追加している
class PowerArray extends Array {
  isEmpty() {
    return this.length === 0;
  }
}

let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

let filteredArr = arr.filter((item) => item >= 10);
alert(filteredArr); // 10, 50
alert(filteredArr.isEmpty()); // false
```
ここで大事な事は、filter や map といった組み込みのメソッドは、継承された型である PowerArray と同じ型の新しいオブジェクトを返すので、内部の実装はオブジェクトの constructor プロパティを使用する事である


- 組み込みでは、静的の継承はありません

Object.keys, Array.isArray など、組み込みのオブジェクトは独自の静的メソッドを持っている
ただ、組み込みのクラスは例外で、お互いから静的なプロパティを継承しない


### 感想
この章で重要なのは、組み込みのクラスは例外で、静的なプロパティを継承しないという事。
Array や Date はObject を継承するので、メソッドを持つが、Array.[[Prototype]] は Object を参照しないので、静的メソッドは存在しないという事をしっかり覚えておく。


## 9.6 クラスのチェック: "instanceof"
### 知らない単語
- 無し


### 学んだこと
- instanceof 演算子

instanceof 演算子でオブジェクトが特定のクラスに属しているのかを確認することができる
```javascript
obj instanceof Class
```
obj が Classに属している場合に true を返す
例えば
```javascript
class Rabbit {}
let rabbit = new Rabbit();

// Rabbit クラスのオブジェクト？
alert( rabbit instanceof Rabbit ); // true
```
のように確認できる

- 主な型チェックメソッド

typeof:対象はプリミティブで返り値は文字列
{}.toString:対象はプリミティブ,組み込みオブジェクト,Symbol.toStringTag をもつオブジェクトで、返り値は文字列
instanceof:対象はオブジェクト、返り値はtrue/false

などがあり、特に「{}.toString」は高度な「typeof」とも言える

### 感想
今までのチェックメソッドは「typeof」しか使った事が無いので、「{}.toString」、「instanceof」の使い方も覚えておきたい。「{}.toString」に関しては「typeof」より高度なので、どのような場面で使うべきかしっかり理解したい。


## 9.7 ミックスイン
### 知らない単語
- ハンドラとは
    - コンピュータプログラムやその一部分で、何らかの処理要求が発生したときに起動されるものを指す


### 学んだこと
mixins(ミックスイン)
オブジェクト指向プログラミング言語において、サブクラスを継承して機能を提供し、独立して動作することを意図していないクラスの事である

- mixin の例

mixin を作る最もシンプルな方法は、役立つメソッドをもつオブジェクトを作ることで、簡単にどのクラスのプロトタイプにも合併できる

例えば、下記のmixinの例である
```javascript
// mixin
let sayHiMixin = {
  sayHi() {
    alert("Hello " + this.name);
  },
  sayBye() {
    alert("Bye " + this.name);
  }
};

// 使い方
class User {
  constructor(name) {
    this.name = name;
  }
}

// メソッドをコピー
Object.assign(User.prototype, sayHiMixin);

// これで User は sayHi できる
new User("Dude").sayHi(); // Hi Dude!
```
これは単純なメソッドのコピーなので、User は他のクラスを拡張することができる


ミックスインで誤って既存のクラスメソッドを上書きすると、競合が発生するので、ミックスインの命名には注意する

### 感想
ミックスインは自身の内部で継承を活用することもできるという事や、何か重要なことが起こったときに、“イベントを生成するためのメソッドを提供するという役割もあるので、細かい所まで理解しておきたい。

# 最後に
クラスの役割や概念などがきちんと理解できていなければ、この先を理解するのも難しくなると思うので、完全に理解できるよう反復したいと思う。
アソシエーションと仲良くなりたい。

### アソシエーションを理解するために
アソシエーションとは「つながり、関連」という意味からもわかるように、シンプルに言えば「テーブル同士の関連付け」を行ってくれるものです。
じゃあ関連づけるとどんないいことがあるの？ということをまとめていこうと思います。

#### テーブル同士の関連づけとは
アソシエーションは、異なる２つのモデルの間に、「1:N」の関連性を持たせるため、まずアソシエーションを理解するためには「1:N」の関係の理解が大切です。
【ちなみにこのNはNatural number(自然数)のことらしいです。】
アソシエーションはモデルに記述していきます。

:::note info 
1:Nの関係とは
ありがちでわかりやすい例えをすると、User対Postの関係は「1:N」です。
1人のUserは複数個(N個、0個以)、Post(投稿)することができます。
:::

それでは、1:Nの関係性をモデルに実装していきます。
Userモデルに対してPostモデルが１：Nになるよう関連づけました。
```ruby:app/model/user.rb
class User < ApplicationRecord
:
  has_many :posts, dependent: :destroy
end
```


:::note info
has_manyとは
文字の通り「たくさん持っている」という意味です。
「1:N」の1側がたくさん持っているよ、という意味のなので「1」であるUser側に記述します。これで1人のUserはたくさんPostできるよ、という意味になります。
:::

:::note info
dependent: :destroyとは
この記述があると、1側のUserが削除された場合、紐づくN側(Post)も全て削除されます。これがないとUserが不明な投稿だけが残ることになります。
:::

次はPostモデル側にもUserモデルと関連づける記述をする必要があります。
```ruby:app/models/post.rb
class Post < ApplicationRecord
 :
 belongs_to :user #belongs_toの引数は単数形
end
```
:::note info
belongs_to とは
belongs_toは「属する」という意味です。つまりUserに属するという意味になります。
「1:N」のN側が1側に属するとことになるので、belongs_toは属する側である「N」に「なに」に
属するのかを記述します。
:::

### それで結局なにが便利なの？
UserとPostで例えてみましょう。
| ♦︎Userテーブル|  | 
|:-----------|------------:|
|user_id|name|
| 1 | Apiyo|
| 2 | Bpiyo| 
| 3 | Cpiyo|

| ♦︎Postテーブル|  ||
|:------|:----|----:|
|Post_id|User_id|title|
| 1 |1|美味しいBeer|
| 2 |3|世界のWine| 
| 3 |1|Wiskyボトル|

PostテーブルにUser_idカラムを格納することで、PostとUserを紐付けることができます。
つまりどのUserがどの投稿しているのかを判別できます。
じゃあ何が便利になるのか。
このアソシエーションをしない場合、Postを取り出すには次のコードが必要になります。
```アソシエーションなし
@user = User.find(1)
@posts = Post.where(user_id: @user.id)
```
Whereメソッドを使って、そのuserに関連するPostを探してくるために長い記述が必要です。
しかしアソシエーションを施していると・・・
```アソシエーションあり
@User = User.find(1)
@posts = @user.posts 
```
@userに紐づいているpostを探すという、見るだけでわかりやすい記述になります。 
whereメソッドを使って探さなくても、@userに関連する投稿を全て取得できます。
アソシエーションを行うことで、コードでの共通操作をよりシンプルに行うことができ、これがアソシエーションを利用する上で便利な点です。

少しはアソシエーションと仲良くなれたでしょうか？
項目を表示する

# 配列を作成する
```js
  <script>
      'use strict';
      let todo = ['デザインカンプ作成', 'データ整理', '勉強会申し込み', '牛乳買う'];
      for(let item of todo) {
          console.log(item);
      }
  </script>
```
```js
for(let item of todo){
```
### 気づき
対象となる配列```todo```から一つずつ取り出し、変数```item```に代入されるのか。
取り出される限り繰り返されるのか。
```js
console.log(item);
```
### 気づき
代入された変数を```console```オブジェクトに表示させるのか。


# 項目を追加する
```js
  <script>
      'use strict';
      let todo = ['デザインカンプ作成', 'データ整理', '勉強会申し込み', '牛乳買う'];
      todo.push('歯医者に行く');
      for(let item of todo) {
          console.log(item);
      }
  </script>
```
```js
todo.push('歯医者に行く');
```
### 気づき
配列```todo```の最後に追加される。
#### puthメソッド
このpush()メソッドは、```配列の末尾に 1 つ以上の要素を追加```し、配列の新しい長さを返します。
```js
animals.push('chickens', 'cats', 'dogs');
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]
```
##### 出典
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

# 項目一つひとつを```<li>~<li>```で囲む
```js
  <script>
      'use strict';
      let todo = ['デザインカンプ作成', 'データ整理', '勉強会申し込み', '牛乳買う'];
      todo.push('歯医者に行く');
      for(let item of todo) {
          const li = `<li>${item}<li>`;
          console.log(li);
      }
  </script>
```
### コンソール
```
<li>デザインカンプ作成<li>
<li>データ整理<li>
<li>勉強会申し込み<li>
<li>牛乳買う<li>
<li>歯医者に行く<li>
```
### 気づき
こんなことまでできるのか。
すごいな。
HTMLに出力できるのではないか？

# 項目をHTMLに表示する
```js
  <script>
      'use strict';
      let todo = ['デザインカンプ作成', 'データ整理', '勉強会申し込み', '牛乳買う'];
      todo.push('歯医者に行く');
      for(let item of todo) {
          const li = `<li>${item}<li>`;
          console.log(li);
          document.getElementById('list').insertAdjacentHTML('beforeend', li);
      }
  </script>
```
```js
document.getElementById('list').insertAdjacentHTML('beforeend', li);
```
### 気づき
```document```オブジェクトに対してidがlistの要素を丸ごと取得。
```insertAdjacentHTML()```メソッドで定数```li```を追加する
### Element.insertAdjacentHTML()
insertAdjacentHTML()インターフェイスのメソッドは 、```Element指定されたテキスト```を HTML または XML として解析し、結果のノードを DOM ツリーの```指定された位置に挿入```します。
#### 出典
https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

### insertAdjacentHTMLメソッドとinnerHTMLプロパティの違い
HTMLの要素を編集するメソッドには、他にinnerHTMLというプロパティもあります。

innerHTMLはHTMLを```上書き```するために使います。
insertAdjacentHTMLは```要素の追加```のために使います。
#### 出典
https://magazine.techacademy.jp/magazine/33975

# 出典
https://www.sbcr.jp/product/4815601577/
【Swift】初心者のランダム通話アプリ開発奮闘記 #10

# 今日の積み上げ
本買いました！！！！

本屋３軒回った。。
![2022:12:11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/997222/8c26c92a-aaf3-146b-8743-624f5f6e7dbe.png)

他にいい本あれば、教えてください！！！

# PS
インキャのくせに、カフェで副業が始めました。
20マン超えないように計算するのめんどい、、
PyroのシミュレーションでCamera外のシミュレーションを消してレゾを節約する

FXの人にとってPyroのレゾ節約は結構大事ですよね

でも、たまにBoundingBoxを大きくせざるおえなかったりしてレゾの管理？が難しいシチュエーションがあります
なるべくコンパクトにしてあげればシミュレーションも早くできるし、仕事の効率上がりますね！！（わくわく）

※一回Twitterで上げた時に反応結構あった記憶があったので改めて記事としてまとめておきます。

ということで、

1．まず適当に動くカメラとPyroのシミュレーションを作ってください。
自分はこんな感じの一発だけボフッて出る煙を作成しました。
これはお好きなものを作ってください。シェルフでもOKです。

![2022-12-11_02h37_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997785/1328558a-5ffa-c7db-44be-6159b6b0090d.png)

![2022-12-11_02h40_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997785/3d0e2061-6b13-6377-1ef6-46678537a089.png)


2．横から見た時にカメラ外の部分の節約ができればBoundingBoxが少し節約できる！！じゃあどうやってやるのか？
![2022-12-11_02h39_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997785/1224a7f8-ada3-86cb-649e-803de9705cbe.png)

3．まずVolumeSOPを作成してCameraFrustumを作成します。
![2022-12-11_02h43_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997785/b28ca454-57a3-6445-60cd-5b8c0d136d03.png)

4．DOP内で　GasFieldVOPを作成して2ndInputでCameraFrustumを読み込みます。
自分の場合DOPの2ndInputに刺さってるのでこれにしてます。直接選んでもいいし、別のInputに刺さってる場合変えればOKです。
![2022-12-11_02h44_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997785/8f7ace5a-a47c-d053-a704-e96b7fd02621.png)

5．VolumeSampleVOPとMultiplyを作成して、下記画像のようにつなげます。
![2022-12-11_02h47_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997785/50cf3c8c-d3bc-5414-f337-8d036adf564c.png)

6．カメラ外のDensityが強制的に０でMultiplyされるので、消える感じです。
![2022-12-11_02h48_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997785/f6a17257-c1aa-0b14-b597-f79bcfbf9564.png)


これでミサイル煙とかみたいな長いシミュレーションで途中からカメラ外で見えなくなるやつも節約しながらシミュレーションできますね！！やったあ！！
簡単なTips記事でした

もしゃこ
AWS実験室 / アカウント管理

# ルートユーザーのMFA認証有効化
- AWSマネジメントコンソールにサインインします。
- アカウント名をクリックしてプルダウンメニューを表示して「セキュリティ認証情報」をクリックします。
![AWS_CONSOLE_01_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/fa11cd25-aaf8-d058-d368-91207da2934d.png)
- 「多要素認証 (MFA)」から「MFAの有効化」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/caaf570f-cf41-14a1-e487-6d2760511f0c.png)
- 今回はMFAデバイスの管理画面では「仮想MFAデバイス」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/a86f60a2-421d-ed6a-80f8-49b07a4a6943.png)
- 手持ちのスマートフォン（今回はiPhoneを使用)に対応するアプリをインストールします。
今回は「Microsoft Authenticator」を使用しました。他にも使用できるアプリがありますので「互換性のアプリケーションのリスト」から確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/56a6e60e-0dab-e1e4-cb6f-19cd73a10199.png)
- アプリを起動して「＋」をタップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/a7315b4d-9299-bb9f-988a-c4a2018e7a01.png)
- その他(Google, Facebookなど)をタップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/f98858d7-970c-194e-b985-044202354f1b.png)
- カメラを起動してWebブラウザに表示されるQRコードを読み取ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/b3c3be9b-c32b-7e57-91f4-46bb6fe8b626.png)
- Microsoft Authenticatorの画面に表示されるコード（2回分)を設定して「MFAの割り当て」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/b6f1906a-b08c-b794-b2c1-b02216df51a0.png)
- これでMFAデバイスの設定は完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/c5f9ef33-fa59-c9f7-33b2-73ac873bd058.png)

# 管理者用IAMユーザー作成
「[IAM でのセキュリティのベストプラクティス](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html)」にも記載されている通り、ルートユーザーは日常的なタスクで使用することは推奨されません。</br>
そのため管理権限を付与したユーザーを作成するようにします。

- AWSコンソールの検索ボックスで「IAM」を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/fb987d6a-01e0-3d5d-31a6-23e6731a486e.png)
- 「IAM」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/c0251aad-5f3f-3012-2ef4-9fd76673f6a5.png)
- 「ユーザーを追加」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/bcb3be31-8f2e-8665-d4f7-7f3b33fc0335.png)
- ユーザー情報を入力します。</br>
- 今回は「admin」ユーザーを追加しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/279b8ba2-a448-ee4c-2267-72ffad7f6de7.png)
- ポリシーを付与します。</br>
今回は「AdministratorAccess」を付与ｂしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/d591555a-1d78-833a-5dfc-67a133dc1217.png)
- タグは「空」で設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/3020ddbd-8f03-b660-ddfd-d5374d5608fb.png)
- 「ユーザーのの追加」ボタンをクリックして完了です。</br>
これ以降、ルートユーザーでないとできない操作以外については今回追加したadminユーザーで操作を行うようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/1621ec24-0436-cb27-ca03-fbe7559a59f2.png)
GraphQL Ruby でクエリの複雑度をレスポンスヘッダで応答する

# 概要

GraphQLでクエリをしたときにそのクエリの複雑度がどの程度だったのかを把握したくなることがあります。

この問題を解決する手段として複雑度をHTTPレスポンスヘッダで応答できるようにしてみます。

このAPIデザインがどの程度一般的なのかはちゃんとわかっていないのですが、Contentful の [GraphQL Content API](https://www.contentful.com/developers/docs/references/graphql/#/introduction/query-complexity-limits) にはレスポンスヘッダで複雑度を応答するデザインが含まれていましたので特別に異常なことではないでしょう。

# コード

複雑度の計算をするアナライザとして `GraphQL::Analysis::AST::QueryComplexity` が標準で提供されていますので、これを継承してアナライザーを実装します。

`OverseQueryComplexityComplexityAnalyzer` をクラスを作り、`#result` メソッドをオーバーライドし 、ここでは`GraphQL::Analysis::AST::QueryComplexity#result` で計算された複雑度を `context` に設定します。

また実装したアナライザーを有効にするために `query_analyzer` を使って宣言します。

```rb
class ObserveQueryComplexityAnalyzer < GraphQL::Analysis::AST::QueryComplexity
  def result
    complexity = super

    context = query.context if query

    context[:query_complexity] = complexity if context

    complexity
  end
end

class MySchema < GraphQL::Schema
  query_analyzer(ObserveQueryComplexityAnalyzer)
end
```

`GraphqlController#execute` では `context` から 複雑度を取り出し `response.headers` に設定します。

```rb
class GraphqlController < ApplicationController
  X_GRAPHQL_QUERY_COMPLEXITY = 'X-GraphQL-Query-Complexity'.freeze

  def execute
    result = MySchema.execute(params[:query],
                              variables:      ensure_hash(params[:variables]),
                              context:        context,
                              operation_name: params[:operationName])

    query_complexity = context[:query_complexity]

    response.headers[X_GRAPHQL_QUERY_COMPLEXITY] = query_complexity if query_complexity

    render json: result
  end

  private

  def context
    @context ||= {}
  end
end
```

cURL などでクエリして複雑度が応答されるか確認しましょう。

```sh
$ curl -vvv -H'Content-type: application/json' \
       -d'{ "query": "query { viewer { id name } }" }' \
       -XPOST $GRAPHQL_ENDPOINT 2>&1 | \
  grep x-graphql-query-complexity
< x-graphql-query-complexity: 3
```

# 参考

- https://graphql-ruby.org/queries/complexity_and_depth
AWS実験室

私が勉強中のAWSについてのメモです。

# AWS実験室 / アカウント管理
https://qiita.com/Que-sera-sera/items/57eb7128de00b7ed3f7d

# AWS実験室 / EC2インスタンス作成 (Amazon Linux 2)
https://qiita.com/Que-sera-sera/items/6942013a0ff1c975c00c
[python] selection sort の勉強

# Code
```python
from typing import List
import time


def selection_sort(numbers: List[int]) -> List[int]:
    # 左から順番に選択
    for i in range(len(numbers)):
        min_idx = i

           # 基準より右側を順番に比較する。
        for j in range(i+1, len(numbers)):

            # 基準(min_idx)よりも右側に小さい値があれば交換候補とする。
            if numbers[min_idx] > numbers[j]:
                min_idx = j

        # 交換する
        numbers[i], numbers[min_idx] = numbers[min_idx], numbers[i]
    return numbers


if __name__ == '__main__':
    start = time.time()
    import random
    nums = [random.randint(0, 1000) for _ in range(10)]
    selection_sort(nums)
    print(time.time() - start)

```
## かかった時間
```
0.006142139434814453
0.005542755126953125
0.004999876022338867
```

## 作業の可視化
```
[393, 188, 134, 629, 638, 461, 364, 51, 79, 209]
[51, 188, 134, 629, 638, 461, 364, 393, 79, 209]
[51, 79, 134, 629, 638, 461, 364, 393, 188, 209]
[51, 79, 134, 629, 638, 461, 364, 393, 188, 209]
[51, 79, 134, 188, 638, 461, 364, 393, 629, 209]
[51, 79, 134, 188, 209, 461, 364, 393, 629, 638]
[51, 79, 134, 188, 209, 364, 461, 393, 629, 638]
[51, 79, 134, 188, 209, 364, 393, 461, 629, 638]
[51, 79, 134, 188, 209, 364, 393, 461, 629, 638]
[51, 79, 134, 188, 209, 364, 393, 461, 629, 638]
[51, 79, 134, 188, 209, 364, 393, 461, 629, 638]
```
左の０番目から順番に順序が確定し、10個の要素の列に対して10回の作業で完了した。

## どの位まで、できるかテスト
```python
if __name__ == '__main__':
    for power in range(1, 10):
        start = time.time()
        import random
        nums = [random.randint(0, 1000) for _ in range(10**power)]
        selection_sort(nums)
        print('elements:', 10**power, 'time:', time.time() - start)
```

```terminal
elements: 10 time: 0.0049970149993896484
elements: 100 time: 0.001001119613647461
elements: 1000 time: 0.052506208419799805
elements: 10000 time: 4.589069604873657
...
```
要素が約10000個以上からは、かなり時間がかかり、実用的ではないことがわかる。
100000個は60秒以上待っても結果が出てこなかった。



# おわりに
前回勉強した`bogo sort` よりは、はるかに軽くて実用的であると思ったが、思ったよりは限界能力が低い。
しかし`selection sort`はとても有名であるので、抑えておくことは重要であるそうです。

https://qiita.com/junzai/items/a0d8448adfdb13dc021f
【備忘録】業務で実際使用したcurlコマンドメモ③（JSON形式）

# 1.curlコマンドとは
curlコマンドとは、様々な通信プロトコル（手段）でデータの送受信を行うことができるコマンドです。
[curlコマンド・オプション表はこちら](https://qiita.com/matsumotojanai/items/21a7db1fcdec78a0bbaf)

# 2.JSONとは
JSONとはJavaScript Object Notationの略で、JavaScript オブジェクトの構文に従ったテキストベースのデータ形式です。
Python、PHP、JavaScript、C++、Javaなど様々な言語でサポートされており、JSONを間に挟むことで各プログラミング言語間のデータの受け渡しがとても簡単にできます。

JSONの例）
```
[
  {"name" : "tanaka" , "age" : 20},
  {name" : "yamada" , "age" : 35}
]
```
JSONは {} の中にキーと値(value)をコロンで区切って記述します。
キーは必ずダブルクォーテーションで囲む必要があり、シングルクォーテーションだとエラーになります。

# 3.JSON形式でデータをPOSTしたい場合
サーバーとクライアント間の通信や、サーバー間での連携を行う仕組みとして、「API」という概念が存在します。
その中でも、多くのサーバーが対応しているのが「REST API」です。
REST APIはJSON形式でデータを記載することで、データの受け渡しや転送を行います。

データをJSON形式でPOSTしたい場合は、-Hオプションで***Content-Type:application/json***を指定する。
送信するデータは-dでJSON文字列を指定する。
```
$ curl -X POST -H "Content-Type: application/json" -d '{"name":"花子", "age":25}' https://xxxxx.net/xxxxxx
```
GraphQL Ruby で複合主キーなレコードをバッチロードする

# 概要

複合主キーなレコードをバッチロードしてみます。

自分の所属では数年前に GraphQL を導入したこともあり [graphql-batch](https://github.com/Shopify/graphql-batch) が使われていますが、今だと [graphql-ruby の dataloder](https://graphql-ruby.org/dataloader/dataloader.html) を使うのが一般的と思うので両方で実装してみます。

# 前提

以下のようなテーブルがあるとし、

```mermaid
classDiagram
  users --|> follows: フォロイー
  users --|> follows: フォロワー
  class users{
    id bigint
  }
  class follows {
    +follower_id bigint
    +followee_id bigint
  }
```

viewer がユーザをフォローしているか否かを以下のクエリで取得するシチュエーションを考えます。

```graphql
query ($id: ID!) {
  user(id: $id) { isFollowedByViewer }
}
```

# GraphQL Batch の場合

Loaders::MultiColumnRecordLoader として実装します。

```ruby
module Loaders
  class MultiColumnRecordLoader < GraphQL::Batch::Loader
    def initialize(model, columns:)
      @model = model
      @columns = columns
    end

    def perform(keys)
      conditions = keys.map {|key| @columns.zip(key).to_h }

      scoped = conditions.inject(@model.none) {|s, condition| s.or(@model.where(condition)) }

      scoped.each do |record|
        key = @columns.map {|column| record.public_send(column) }

        fulfill(key, record)
      end

      keys.each do |key|
        next if fulfilled?(key)

        fulfill(key, nil)
      end
    end
  end
end
```

呼び出しは以下のようになるでしょう

```ruby
module Types
  class UserType < Types::BaseObject
    field :is_followed_by_viewer, Boolean, resolver_method: :followed_by_viewer?

    def followed_by_viewer?
      return false unless viewer

      loader = Loaders::MultiColumnRecordLoader.for(Follow, columns: %i[follower_id followee_id])

      loader([viewer.id, object.id]).then(&:present?)
    end
  end
end
```

# GraphQL Ruby - Dataloader の場合

Sources::MultiColumnRecordSource として実装します。

```ruby
module Sources
  class MultiColumnRecordSource < GraphQL::Dataloader::Source
    def initialize(model, columns:)
      @model = model
      @columns = columns
    end

    def fetch(keys)
      conditions = keys.map {|key| @columns.zip(key).to_h }

      scoped = conditions.inject(@model.none) {|s, condition| s.or(@model.where(condition)) }

      mapping = scoped.inject({}) do |record, m|
        key = @columns.map {|column| record.public_send(column) }

        m[key] = record
      end

      keys.map {|key| mapping.fetch(key, nil) }
    end
  end
end
```

呼び出しは以下のようになるでしょう

```ruby
module Types
  class UserType < Types::BaseObject
    field :is_followed_by_viewer, Boolean, resolver_method: :followed_by_viewer?

    def followed_by_viewer?
      return false unless viewer

      loader = dataloader.with(Sources::MultiColumnRecordSource, Follow, %i[follower_id followee_id])

      follow = loader.load([viewer.id, object.id])

      follow.present?
    end
  end
end
```

# 所感

GraphQL Ruby の Dataloader の方が好きです。
【Laravel】個人的な初知りな便利配列操作系へルパ

## 概要

ドキュメント明後日便利そうなヘルパーを書いてきます。主に配列操作系。

大体配列をコレクションに変換してあれこれしていたり、冗長な配列操作を書いていたんですが
これらを使えばもっとスッキリかけるようになりそう。


## data_fill()
data_fill関数は「ドット」記法を使用し、ターゲットの配列やオブジェクトへ足りない値をセットします。

```php
$data = ['products' => ['desk' => ['price' => 100]]];

data_fill($data, 'products.desk.price', 200);

// 既にあるから値を入れない
// ['products' => ['desk' => ['price' => 100]]]

data_fill($data, 'products.desk.discount', 10);

// 存在しないから'discount' => 10が追加される
// ['products' => ['desk' => ['price' => 100, 'discount' => 10]]]
```

https://readouble.com/laravel/8.x/ja/helpers.html#method-data-fill

nullが入ってたら上書きしてくれるんかな？

```php
$data = ['products' => ['desk' => ['price' => 100,'discount' => null]]];

dd(data_fill($data, 'products.desk.discount', 10));
```

```:出力
array:1 [▼
  "products" => array:1 [▶
    "desk" => array:2 [▶
      "price" => 100
      "discount" => null
    ]
  ]
]
```

だめでした。キーがあるかどうかなんですな

### ワイルドカード

アスタリスクで複数の配列全て対象にできる

```php
$data = [
    'products' => [
        ['name' => 'Desk 1', 'price' => 100],
        ['name' => 'Desk 2'],
    ],
];

data_fill($data, 'products.*.price', 200); 
```

```:出力
array:1 [▼
  "products" => array:2 [▶
    0 => array:2 [▶
      "name" => "Desk 1"
      "price" => 100
    ]
    1 => array:2 [▶
      "name" => "Desk 2"
      "price" => 200
    ]
  ]
]
```

## data_get()

data_get関数は「ドット」記法を使用し、ネストした配列やオブジェクトから値を取得します。
```php
$data = ['products' => ['desk' => ['price' => 100]]];

$price = data_get($data, 'products.desk.price');

// 100
```

data_get関数は、指定したキーが存在しない場合に返す、デフォルト値も指定できます。
```php
$discount = data_get($data, 'products.desk.discount', 0);

// 0
```

配列やオブジェクトのいずれのキーにもマッチする、ワイルドカードとしてアスタリスクも使用できます。
```php
$data = [
    'product-one' => ['name' => 'Desk 1', 'price' => 100],
    'product-two' => ['name' => 'Desk 2', 'price' => 150],
];

data_get($data, '*.name');

// ['Desk 1', 'Desk 2'];
```
https://readouble.com/laravel/8.x/ja/helpers.html#method-data-get

こーれは便利だ。常用確定
三項演算子わちゃわちゃとかを見なくて済むし共有しよ


## data_set()

data_set関数は「ドット」記法を使用し、ネストした配列やオブジェクトに値をセットします。

```php
$data = ['products' => ['desk' => ['price' => 100]]];

data_set($data, 'products.desk.price', 200);

// ['products' => ['desk' => ['price' => 200]]]
```

この関数は、アスタリスクを使用したワイルドカードも受け入れ、それに応じてターゲットに値を設定します。
```php
$data = [
    'products' => [
        ['name' => 'Desk 1', 'price' => 100],
        ['name' => 'Desk 2', 'price' => 150],
    ],
];

data_set($data, 'products.*.price', 200);

/*
    [
        'products' => [
            ['name' => 'Desk 1', 'price' => 200],
            ['name' => 'Desk 2', 'price' => 200],
        ]
    ]
*/
```

デフォルトでは、既存の値はすべて上書きされます。値が存在しない場合にのみ値をセットする場合は、関数の4番目の引数にfalseを渡してください。

```php
$data = ['products' => ['desk' => ['price' => 100]]];

data_set($data, 'products.desk.price', 200, $overwrite = false);

// ['products' => ['desk' => ['price' => 100]]]

```

https://readouble.com/laravel/8.x/ja/helpers.html#method-data-set


## まとめ

基本的に連想配列の操作は``data_get``と``data_set``で事足りてしまいそう
配列の中身をゴニョゴニョしようとした時に思い出して使おうと思います。
DoozyUIでUIMenuのオブジェクトが生成できないときの備忘録

# 概要
UnityにはDoozyUIというアセットがありますが、こちらをパッケージから追加した際にUIMenuのオブジェクトが追加できないことがありました。
今回はその時の解決策のメモです。
https://assetstore.unity.com/packages/tools/visual-scripting/doozy-ui-manager-203601

#やり方
1. Tools/Doozy/UIMenuから下記のUIMenuを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104976/9bbc5c7d-6d1a-8483-9d98-089c7e757818.png)
2.  こちらの左下のボタンからRegenerate the UI Menuをおすことでアセット類を取得し直してくれて、UI Menu、Hierarchyから追加できるようになります。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104976/071a5346-978d-d6e6-9e4a-a56d64a18ec5.png)
TwitterでMetamaskがあればJPYCで簡単に誰かのためのクラウドファンディングができるWebサービスを開発したい

どうも、 双子の娘と妻と四人ぐらしのワーパパシステムエンジニアのデミオです。
Webサービスを自分で作れるようになりたい思ってますが、仕事ではプログラムほとんど触っておらずシステムの仕様書書いたり、UIテストしたりが多いので難航してます。

そんな僕ですが、随分前に[JPYCハッカソン](https://jpy.design/)に出て、
**勝手に応援**
というサービスのデモを[國光DAO](https://financie.jp/communities/kunimitsudao)のメンバーと協力して作りました。

この勝手に応援というサービスをデモではなく本格的に Web サービスとして開発したいと思い、これから活動していきます。

noteにも同じように決意表明の記事を書いていますが、qiita ではもう少し技術寄りのことを書いておこうと思い、この記事を書いています

https://note.com/demio_note/n/nc227561f7eed


# 「勝手に応援」 とはどんなサービスか？


**「勝手に応援」とは、**
・応援してあげたい方のTwitterID
・応援のためにお金を出す方のMetamaskウォレット（JPYCが入っている）
があれば、
**「勝手に（許可なく）応援して上げたい他人のためのクラウドファンディングを始められる」**
というサービスの通称です。
(もしかしたら名前は変えるかもしれません。)



こんな感じの操作の流れです。


:::note info
**運用イメージ**
①勝手に応援サイトにアクセス
②Metamaskを接続
③応援したい人（お金を受け取る人）のTwitterIDと目標金額、紹介ページのURL、募集期限を入力して新たなクラウドファンディング立ち上げ
⇒ブロックチェーン台帳にクラウドファンディングの情報を書き込み

④立ち上がったクラウドファンディングに金額を募金。JPYCで勝手に応援ブロックチェーンに預ける。自分のTwitterIDも入力。

⑤ ④の作業で③のクラウドファンディングにお金を集める。
⑥ 募集期限を迎えたときに目標金額を超えていたら
　⇒応援したい人のTwitterにTipJPYCを使って集まったJPYCを送金。
⑥’  募集期限を迎えたときに目標金額を超えていなかったら
　⇒④で募金してくれた方にクラウドファンディングからお金を返金する。返金したことを募金者のTwitterに通知。

:::

シーケンスで書くとこんな感じです。

__シーケンス１　新たなクラウドファンディングの立ち上げと、そこへの支援__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679788/079b5728-7cb5-1d64-cbc0-3835dfe22e01.png)


__シーケンス２　クラウドファンディングの成功時__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679788/739d6c10-d7cb-1328-f9cb-dd7b28df1258.png)

__シーケンス３　クラウドファンディングの失敗__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679788/279e2dca-fe64-36ce-0d65-c77eaca149ff.png)

## なんでこのサービスを作りたいか？

今日コンサルを受けて何での部分が重要ということが分かったので言語化しておきます

西野亮廣エンタメ研究所とかに入っているとクラウドファンディングによって資金を集めることがだいぶ簡単になってきていると感じます。
プロジェクトの必要性ではなくてそのプロジェクトを進めている人への支援として募金のような形でクラウドファンディングをしているケースもあるようです

そういった時にものすごく技術とか才能を持っているけれど資金の面でその活動に打ち込むことができてない人っていうのは非常に多いと思いました。

もちろんその方がクラウドファンディングをできるならそれがベストだと思うんですが違うドファンディングを立ち上げるのってどう考えても大変ですよね。
マーケティングの知識とかないと成功する気がしないです。

なので、クラウドファンディングができる人/やれそうな人が、勝手に誰かのためのクラウドファンディングを立ち上げて、お金を集めてTwitter経由でその人にプレゼントできる、というのがあると、才能をフルに活かせる人がいっぱい出てきて、日本や世界が面白くなると思いました。

あとは元々ブロックチェーンや Web 3領域の Web サービスを開発したいという気持ちがあったので、
もしこの勝手に応援というプロジェクトが上手くできれば誰かの役に立てるという思いもあり、
挑戦してみようと思いました。


# 今後の方針

今後はまず最低限の機能をテストネットで動かせるMVP（Minimum Viable Product）を作ろうと思います。
（MVPって言いたい）

詳しい課題やコードは下記のGithub のリポジトリで管理していこうかなと思います。（オープンソースのリスクをわかってない）

https://github.com/demio-se/ouenProject

TwitterAPI使って開発できるようにするのと、
AWS上でnode.jsでWebサイト作るのを進めようと思っています


これからよろしくおねがいします！
【Python】勉強メモ-その2　リストCSV出力

# リストをカンマ区切りでテキストに出力

### 1. はじめに
**CSVモジュール**を使えば、効率的じゃないかと思われる方が大半だと思いますが、
**急がば回れ**の精神で、無駄じゃない？と思われるようなことも、最初は、理解のために取り組んでおります。

この方法は、ちゃんとしたCSVではありません。
CSVにはRFCという規格でちゃんとフォーマットが決められているんですが、
この簡易的な方法ではその規格には対応できないんですね。たとえばデータの中に
カンマが含まれていた場合は、自分でダブルクオーテーションでエスケープしなきゃいけません。

### ２. 数値のリストをカンマ区切りでテキスト出力
これは、文字列ではないため、エラーとなります。
```sample_01.py

li = [1, 2, 3]

with open('test.txt', 'w', encoding='shift-jis') as f:
    for x in li:
        f.write(x)

# 結果
# write() argument must be str, not int
```
対応策としては、**str()** 関数を使い文字列へ変換します。
```sample_02.py

li = [1, 2, 3]

with open('test.txt', 'w', encoding='shift-jis') as f:
    for x in li:
        f.write(str(x))
# 結果
# テキスト内に、123 と記載れている。
```
テキスト内に以下の様に縦に記載されているわけではないということです。
```txt
1
2
3
```
理由は、`write()`メソッドは、デフォルトで**改行**されないため。
`Print()`で表示するときは、上記の様に、縦に表示される。
`Print()`は、デフォルトで**改行**が付いているため。


では、ここからが本題で、
リストの数値をカンマ区切りで、横に出力するには、どうしたら良いかを記載します。
対応方法としては

**①print()関数のsep=で区切り文字を **,** に指定する。**
**②for文を使い、要素を一つ一つ文字列に変換する。**
**③map()関数を使い、リスト内の個々の要素に対して文字列変換を行う。**

では、
①`print()`関数の`sep=`で区切り文字を` , `に指定する。は、以下のコードになります。

`print(*li, sep=',', file=f)`は、
`*li`でprint(1, 2, 3, ...) と同じになります。つまり、リストの内容(要素)を展開してくれます。
`sep=','`で区切り文字を、`,`に変更しています。そして、`file=f`は、書き込むための、ファイルオブジェクトを
渡していることになります。

```sample_03.py

li = [1, 2, 3]

with open('test.txt', 'w', encoding='shift-jis') as f:
    print(*li, sep=',', file=f) 

# 結果
1,2,3
```

次に、
②`for`文を使い、要素を一つ一つ文字列に変換する。は以下のコードになります。
こちらは、'for'文を使うためソースが長くなってしまうのがデメリットですね。

```sample_04.py
num_li = [1, 2, 3]

# 文字列に変換した要素を格納するための配列を用意する。
num2str_li = []

# str()関数を使い、文字列へ変換した値を、上記で用意したリストへ追加していく。
for x in num_li:
    num2str_li.append(str(x))

with open('test.txt', 'w', encoding='utf-8') as f:
    f.write(','.join(num2str_li))

# 結果
1,2,3
```

次に、
③`map()`関数を使い、リスト内の個々の要素に対して文字列変換を行う。は、以下のコードになります。
xは、1とか2とか1つの物なので、`str`して`join`しても1つなので,の入りようが無いです。
joinするには、["1","2","3"]と**文字列**にする必要があるので、`map`関数を使い
` ",".join(map(str,li)) `のようにします。

```sample_05.py

li = [1, 2, 3]

with open('test.txt', 'w', encoding='shift-jis') as f:
    f.write(",".join(map(str,li)))

# 結果
1,2,3
```

### ３. 文字列のリストをカンマ区切りで出力

文字列のリストの場合、`join`してあげれば`,`で連結できます。

```sample_06.py

str_li = ["犬", "ネコ", "豚"]

with open('test.txt', 'w', encoding='utf-8') as f:
    f.write(",".join(str_li))

# 結果
# 犬,ネコ,豚

```

### 4. 最後に
- ツッコミ歓迎致します。皆様のツッコミが、私のスキルアップにつながります！！
- お題なんかも出していただけると助かります。
- 実務では、もっと、こういう使い方もあるよ！！みたいなアドバイスもいただけると嬉しいです。
JUCEにWindows on ARM元年がやって来た！

本記事は [JUCE Advent Calendar 2022](https://qiita.com/advent-calendar/2022/juce) の12月15日向けに投稿した記事です。

Windows Dev Kit 2023 (Project Volterra)を入手したので、JUCE Demo RunnerをWindows11 on ARMでARMネイティブ向けにビルドした手順を記録しました。

# 対象バージョン
+ Windows11 on ARM (Windows Dev Kit 2023)
+ JUCE 7.0.3
+ Visual Studio 2022 v17.4以上
+ CMake 3.15以上
+ Git 2.0以上

# JUCEとは
JUCE (Jules' Utility Class Extensions)は、C++言語によるマルチメディア系アプリケーションの開発を支援するフレームワークです。
ライブラリの一部モジュールとして独自のGUIシステムを実装しており、開発者はそのAPIを利用することで、クロスプラットフォームなGUIアプリケーションを統一したコードベースで実装することができます。
[公式サイト](https://juce.com/)

## JUCE 7.0.3からWindows on ARMがサポートされました

JUCE 7.0.3から[Windows on ARMをサポートするコミット](https://github.com/juce-framework/JUCE/commit/2d42b9a44f1935ec16cb63420fc20e257b9be21b)が追加されました。
このコミットは本記事執筆時点でmasterブランチに取り込まれているので、正式リリース版から利用することが出来るようになりました。

# Windows on ARMとは

Windows on ARMとは、WindowsをARMプロセッサー上で実行することができるようにしたものです。ARMプロセッサーは、携帯電話やタブレットなどのモバイルデバイスに多く採用されている低消費電力プロセッサーです。Windows on ARMを採用することで、モバイルデバイスでも高速かつ省電力でWindowsを実行することが可能になります。また、Windows on ARMでは、x86プロセッサー向けのWindowsアプリケーションも動作させることができます。

[ドキュメント](https://learn.microsoft.com/ja-jp/windows/arm/overview)

## ARM64を正式にサポートしたVisualStudioがリリースされました

本記事執筆時点において、Windows 向け開発ツールである「Visual Studio 2022」のv17.4からARM64プラットフォームへのネイティブ・ビルドがサポートされました。このバージョンを使用することで「Windows Dev Kit」などのARM64デバイスでネイティブで動作し、ARM64アプリのビルドおよびテストが可能になります。

[ドキュメント](https://learn.microsoft.com/ja-jp/visualstudio/install/visual-studio-on-arm-devices?view=vs-2022)


# JUCE Demo RunnerをWindows on ARMでARMネイティブ・ビルドするまで

JUCE Demo RunnerをWindows on ARMでARMネイティブ・ビルドするまでの流れを示します。

## Git for Windowsをインストールする

GitHubからJUCEをクローンするので、開発環境にGit for Windowsをインストールしておきます。
[公式サイト](https://gitforwindows.org/)

## CMakeをインストールする

今回はCMakeを使うので、開発環境にCMakeをインストールしておきます。
[公式サイト](https://cmake.org/)

## Visual Studioをインストールする

開発環境にVisual Studio 2022をインストールします。そして、追加モジュールとしてC++ツールキットをインストールします。このとき、ARMネイティブ・ビルド向けのツールキットも選択してインストールします。

![スクリーンショット_20221211_151810.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93566/14d5df06-d81e-3593-961e-bd0a542c1d97.png)


## JUCEリポジトリをクローンする

```
git clone https://github.com/juce-framework/JUCE.git

cd JUCE
```

## CMakeでConfigure処理を実行する

Configureを実行する際に、以下のオプションをコマンドライン引数から渡します。
+ `-G "Visual Studio 17 2022" -A ARM64`：Visual Studio 2022 用のジェネレータを使用する。この時、プラットフォーム・アーキテクチャはARM64を選択する。
+ `-D JUCE_BUILD_EXAMPLES=ON`：JUCE Demo Runnerを含むExamplesをビルドするオプションを有効にする。

```
cmake -B build -G "Visual Studio 17 2022" -A ARM64 -D JUCE_BUILD_EXAMPLES=ON
```

## Visual Studioでビルド処理を実行する

CMakeのコマンドライン経由でVisual Studioのビルド処理を実行します。

```
cmake --build build
```

## JUCE Demo Runnerを起動する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93566/fe5b52fa-213b-9121-f7e8-ae23c444dca8.png)
python スライスの仕組み

## スライスとは？

>スライス
⇒シーケンスなオブジェクトの要素を指定して、新たなオブジェクトを生成すること。
シーケンス[始まり:終わり:ストライド]というような形で指定する。
特殊メソッドの__getiteam__と__setiteam__を実装したクラスをスライスすることができる。
~~~python
numbers = [0, 1, 2, 3, 4, 5, 6]
print(numbers[:4])
print(numbers[0:3])
print(numbers[-1:0:-1])
print(numbers[0:7:2])

>>> 
[0, 1, 2, 3]
[0, 1, 2]
[6, 5, 4, 3, 2, 1]
[0, 2, 4, 6]
~~~
# 特殊メソッドとは
各種演算子、組み込み関数などの操作を独自に定義したクラスを利用できるようにするための仕組みのこと。__init__や__str__,__repr__など。

# __getiteam__とは、クラスにキーを指定して（辞書型のような）アクセスを可能にさせる特殊メソッド。
~~~python
class ExamGetitem(object):
    
    def __getitem__(self, time):
        if time == 15:
            return 'おやつの時間ですよ'
        elif time == 12:
            return 'お昼の時間ですよ'
        elif time == 18:
            return '夕食の時間ですよ'
        elif time == 6:
            return '朝ごはんの時間ですよ'
        else:
            return 'おなかはいっぱいです'

A = exam_getitem()
print('6時:',A[6])
print('12時:',A[12])
print('15時:',A[15])
print('18時:',A[18])
print('19時:', A[19])

>>>
6時: 朝ごはんの時間ですよ
12時: お昼の時間ですよ
15時: おやつの時間ですよ
18時: 夕食の時間ですよ
19時: おなかはいっぱいです
~~~

## スライスの注意点
スライスを指定する際、存在しないインデックスを範囲に含めて指定することはできるが、存在しないインデックスの値を取り出すことはできない。

~~~python
exam_list = [0, 1, 2, 3, 4, 5, 6,7, 8, 9, 10]

len_list = len(exam_list)
print(len_list)
print(exam_list[100:])
print(exam_list[:-100])
print(exam_list[-0:])
print(exam_list[-12])

>>>
11
[]
[]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print(exam_list[100])
IndexError: list index out of range
~~~
# スライスで生成したオブジェクトは、元のオブジェクトとは異なる
~~~python
exam_list = [0, 1, 2, 3, 4, 5, 6,7, 8, 9, 10]

copy_exam_list = exam_list[:]

assert exam_list is copy_exam_list

>>>
assert exam_list is copy_exam_list
AssertionError
~~~
# スライスに代入を行う場合、数が等しくなくてもよい

~~~python
exam_list = [0, 1, 2, 3, 4, 5, 6,7, 8, 9, 10]
print(exam_list)
print('*' * 30)
exam_list[2:8] = 'A', 'B'
print(exam_list)

>>>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
******************************
[0, 1, 'A', 'B', 8, 9, 10]
~~~
[JavaScript]ある文字列が重複する文字があるかどうか出力するアルゴリズム

「世界で闘うプログラミング力を鍛える本」にある問題から。

「ある文字列が、すべて固有であるかどうか判定するアルゴリズムを実装しなさい」

JavaScriptで実装してみた。


```
function duplicationcheck(str){
  //引数として渡された文字列を1文字ずつ分割
  let a=str.split('');
//空の配列bを作成
  let b=[];
  //変数cの初期値
  let c=false;

  for(let i=0;i<a.length;i++){
    //配列bの中に配列a[i]と同じものがあるかどうか判定
     c=b.includes(a[i]);
     //配列bの先頭に配列a[i]を挿入
     b.unshift(a[i]);
     //変数cがtrueになっていたらループを抜ける
     if(c===true){
      console.log('重複あり');
      break;
     }
  }
  //繰り返しが終了してもcがfalseのままだったら「重複なし」を出力
  if(c===false){
    console.log('重複なし');
  }
}
```
細かな説明は、コメントアウト部分に書いた。


　大まかな流れとしては、
①引数として文字列を受けとる
②文字列を1文字ずつ分割
③分割した文字を1文字ずつ変数に格納しながら、includesメソッドで重複があるか判定
④重複があれば「重複あり」、最後までなければ「重複なし」を出力。



※自分で考えただけのアルゴリズムなので、これより良い実装方法がある可能性高いです。各自で試行錯誤しながら実装していってください。
1ヶ月のアクセス数の調べ方



最近AWS WAFを使うかもしれないとの案件があり、WAFについて調べる機会がありました。
WAFのリソースタイプとしてリクエストを想定しておりました。アクセス数によって料金が変わるとのことでアクセス数を調べる必要がありました。そのほかにもAWS上にある旧サイトから移行する際に設計する上でどの程度アクセスがあるのか知ることは重要だと思いますので、覚えて損はないと思います。

早速調べていきます。

### 1,cloud watchにアクセス

cloud watachのメトリクスからALBの「Request Count」へアクセスします。

![スクリーンショット 2022-12-11 15.53.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/924a31f5-1fc1-e02c-8dba-067dea46c441.png)

### 2,1ヶ月間のアクセス数を算出

グラフ化したメトリクスを選択し、「統計」のプルダウンから「合計」を選択します。
![スクリーンショット 2022-12-11 16.01.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/4c97029e-4725-9e04-bfa6-43b046ece2f2.png)

「Custom」リンクから「Absolute」を選択するとカレンダーが出てくるので調べたい1ヶ月間を指定します。
![スクリーンショット 2022-12-11 16.08.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/f4267b70-a54e-e84a-a3b2-e26def3bf51b.png)


指定する期間を決めたらオプションから数値、「時間指定の値は全時間範囲からの値を示しています。」を選択します。
![スクリーンショット 2022-12-11 16.10.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/0d73d6a7-5215-3162-289c-d5dfd3ad32f2.png)

１ヶ月のアクセス数が算出されました。
![スクリーンショット 2022-12-11 16.14.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1686037/e188c2dd-7816-4c36-50e3-3e02836ea32a.png)

お疲れ様でした。

参考記事
https://dev.classmethod.jp/articles/tsnote-waf-pricing-request-count/
[Animation] glTF モーフィングのデータ構造と計算方法

# モーフィングとは
モーフィングとはアニメーション技術のひとつで、ベースモデルに時間に合わせてスケールさせた変位を足すことにより、ベースモデルから変位モデルへのアニメーションが実現できる。
https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%83%B3%E3%82%B0
他のアニメーション手法にスキンメッシュアニメーションがあるが、モーフィングはボーンの構造に依らずアニメーションを行うことができる。
表情の変化など小さな領域のアニメーションを得意としているように思えるが、オブジェクト全体が動くような規模のアニメーションには向いていないように思える。

# 実施例
<iframe width="644" height="1140" src="https://www.youtube.com/embed/xjZam2ZigGY" title="hatenabolog投稿用 20221210" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

モデル
https://sketchfab.com/3d-models/yard-grass-3a67e76decc849c694c228eb590a9902
ライセンス：CC Atribution
https://creativecommons.org/licenses/by/4.0/legalcode

# 使用ライブラリ
tiny glTF
https://github.com/syoyo/tinygltf
glTFファイルのローダーとして使用している。

# 仕様書
khronos公式
https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html

# 構造
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1446998/333f0a1e-cc03-4ecd-e3eb-3f9c60a7dd65.png)
データ形式
* 緑：float
* 赤: vec3

四角の中の文字は個数を表している。
* t : target数
* p : positon数
* k : key frame数

key frame $k$での1番目の頂点( $p_0$ )の座標は

``` math
p_0 = p_0 + \sum_{tatget = 0}^{t}p_0.{target} * w_{k}.target
```

で計算できる。
ここで$p_0.target$とは、各targetにある$p_0$のことである。$w_k.target$とは、outputのうち$k$番目の集合にはtの数だけweightが含まれているので、その中のtarget番目のweightのことである。
これを頂点の数分行う。

# 感想
実装時には、この計算方法を見つけることとはまったく別の部分で躓いた。
ご覧の通りデータをすべてバッファーに詰めようとすると、float換算で3 * position数 * target数分のデータが必要になるので、1つのバッファーに詰めると膨大な数のデータ量になる。
このバッファーを用意したが、なぜかvec3でアクセスすると正確に値が取ってこれなかった。
バッファーの中身がfloatであるとしてアクセスすると読み取れた。

# Git Hub
何かの参考になれば。
https://github.com/kodai731/Aqoole-Engine-Android-Vulkan-Rendering-Engine-:title
Laravel Livewire + dropify で気をつけないとハマる

Livewire でファイルアップロードしようと思いまして dropify でフロント側は実装したろ、と思ってみたところ、どうやっても表示が崩れて数時間悩んだんですが、結果的にこうなりました。

```javascript
import $ from "jquery";
import 'dropify'

// Dropify
window.onload = () =>{
    initDropify()
}

function initDropify() {
    return $('.dropify').dropify()
}
```


### ダメなやつ
```php
<!-- エラー文 -->
@if($errors->any())
<div class="error">
    @foreach ($errors->all() as $error)
    <p class="error_text">{{ $error }}</p>
    @endforeach
</div>
@endif

<!-- フォーム -->
<form class="from" wire:submit.prevent="save">
    <dl class="table">
        <dd class="table_data">
            <div class="table_inner" wire:ignore>
                <input type="file" class="dropify img" wire:model="image">
            </div>
        </dd>
    </dl>
</form>
```

### 動くやつ
```php
<!-- エラー文 -->
<div class="error" @if( ! $errors->any()) style="display:none" @endif>
    @foreach ($errors->all() as $error)
    <p class="error_text">{{ $error }}</p>
    @endforeach
</div>

<!-- フォーム -->
<form class="from" wire:submit.prevent="save">
    <dl class="table">
        <dd class="table_data">
            <div class="table_inner" wire:ignore>
                <input type="file" class="dropify img" wire:model="image">
            </div>
        </dd>
    </dl>
</form>
```

## 解説
どうも dropify というか jQuery のような気がしますが、セレクタが DOM の頂点から位置が変わってしまうと表示をうまくキープできないようでした。
上記のダメなパターンの場合、フォームの前にバリデーションなどでエラーが起きると div が差し込まれるわけですが、このとき `$('.dropify').dropify()` が動かなくなります。

`wire:ignore` を入れておかないとコンポーネントのアップデートが走った時に初期化されてしまうので、抑制もお忘れなく。
いやー酷い目にあった。
【SQL】「A」を「'A',」に一括置換する方法４選

文字列のリストをIN句につっこんでSELECTしたいケースってありますよね。
そんなときに役立つ「A」を「'A',」に一括置換する方法をまとめてみました。

# やりたいこと
### 何らかのリスト
|  type  | 
| ---- | 
|  A  |
|  B  |
|  O  |
|  AB  |

### IN句につっこむ
```sql
SELECT
    * 
FROM
    Member
WHERE
    Type IN
    (
        'A',
        'B',
        'O',
        'AB' 
    )
```
# どうやるか？
## 矩形選択
多くのエディタに矩形選択という機能があります。
ここではVSCodeで試しています。

![矩形選択.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521440/a455ca1b-d1cf-050d-1181-0b2c73ccffcb.gif)

①[Ctrl] + [Shift] + [alt] + [↓]で左端を矩形選択
※Macだと[Shift] + [Option] + [Command] +[↓]

②「'」を入力

③[End]で右端に移動
※Macだと[fn] + [→]

④「',」を入力

## 正規表現
![正規表現.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521440/932ea76b-9e2b-1de7-d583-964a76085943.gif)

① [Ctrl] + [H]で置換画面を起動
※Macだと[Option] + [Cmd] + [F]

②「正規表現を使用する」をON

③「^」を「'」に置換

④「$」を「',」に置換

## WEBツール
![WEBツール.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521440/f110df5c-df4f-0686-5f41-4c3e909fa251.gif)

①プレフィックスに「'」を指定

②サフィックスに「',」を指定してFormat

## ExcelでCONCAT
![Excel.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521440/f98fd3af-b444-080d-c6c0-19e0c320f81f.gif)

①文字列左のセルに「'」（表示されない場合は「''」と入力）

②文字列右のセルに「',」（表示されない場合は「'',」と入力）

③３列をCONCAT関数で連結

# まとめ
「A」を「'A',」に一括置換する方法について４つ紹介しました。
数が少ない場合は矩形選択、多い場合は正規表現を使うことが多いです。
操作が難しいと感じる場合はWEBツールを使うのもありだと思います。
【下書き】blender pythonでのあそび

少しblenderで遊んで見ようかと
最終的な目的は、blender-pythonでアニメーションを作成するのが目的
中の人がいないvtuberをやってみたい
(vroid studio と 3tate であたりでやってることをblenderでVRM読み込んで自律的風にやりたい)

## python-console

```
$ blender --python-console
```
とするとpythonインターフェースが表示されるのでここからやっていきたい

## 確認していること

* GUIが表示されない、初期のwindowは表示されるが中が表示されない
* python-console 上では補完など聞かない、pythonのオプションかなちょっとやりにくいので改善したい。コンパイルオプションか？

## GUIが表示されない問題

`--python-console` 起動時の処理が一部動いてないので画面が表示されてないものと思う
bpy.app.background はfalseなのでバックグラウンドではない
`-b`をつけて起動すると最初のwindowも表示されなくなる

area と screenだかでredraw()とかがある？
bpy.app 配下の変数で描画を抑止しているものがある？

この方面は解説も少ないしソースを見た方が早いかな
スタートアップ何しているかが追えればいけるかなと見立て
graphvizの矢印について

# 矢印の先端を変えたい！！！

### 結論
線自体はstyle 
線の先っちょはarrowhead 
で変えられます!

## 本文


``` sample_graph.py
import graphviz

g = graphviz.Digraph(format='svg', filename='test')

g.node("1","a")
g.node("2","b")
g.node("3","a")

g.edge("1","2")
g.edge("2","3")

# 表示
g.view()
```

この場合の表示は
![2022-12-11 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1243082/35a24074-35b1-4369-1728-b64714dd5955.png)


矢印の先端を消して線だけにしたいのに。。。。

## 最初に考えた解決方法

どうせstyle とかallowStyleとかで何とかなるでしょ
→
無理でした



``` sample_graph-2.py
import graphviz

g = graphviz.Digraph(format='svg', filename='test')

g.node("1","a")
g.node("2","b")
g.node("3","a")

g.edge("1","2",style="dotted")
g.edge("2","3")

# 表示
g.view()
```

![2022-12-11 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1243082/3b3a7af3-f5c9-82d1-80bd-cd988e7b6626.png)

### そうじゃない！！！

## 解決策

arrowhead="none"　で解決しました。。

``` sample_graph-3.py
import graphviz

g = graphviz.Digraph(format='svg', filename='test')

g.node("1","a")
g.node("2","b")
g.node("3","a")

g.edge("1","2",arrowhead="none")
g.edge("2","3")

# 表示
g.view()
```
![2022-12-11 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1243082/86ab9992-eff5-a54e-293e-f9958d49f6e9.png)

a→bが線になってますね！！！

https://www.graphviz.org/doc/info/arrows.html

ここに載っている奴はできそうですね

###### 逆に根元の部分を変えたいと思ったのですがarrowtailではうまくいきませんでした。。。謎！！！
豊橋のエンジニアが参加すると楽しそうなコミュニティ

# イベント・コミュニティ
https://coderdojo-toyohashi.doorkeeper.jp/events/147354

火・木夕方

https://nagoya-se.connpass.com/

毎週土曜日　開催時間は回によって変動

https://www.facebook.com/trialvillage/

コワーキングスペース

## イベント・コミュニティを探すためのサイト

https://techplay.jp/

https://connpass.com/

https://www.em-campus.jp/event/

https://www.kokuchpro.com/
エンジニアとITコンサルとSEとプログラマー

昔、『なぜSEはコンサルができないのか』という本があった。
内容は、全く読んでないが、タイトルを見て意味不明と思ってしまった。

# ただの職種定義なので役割の違い
１．プログラマー
　欲しいものをプログラミングして、実装する職種
　＊動く物を実装するロール
２．ＳＥ
　クライアントの要望を整理し、システムに落とす上での整合性チェック。
　システム実現化を検討整理後、プログラマーに伝える職種
　＊クライアントの要望を整理するロール
３．ITコンサル
　クライアントの業務見直し含め、こちらから提案する。要望の本質を捉え、
　システム的に要件を整理する職種。
　＊クライアントが思い付かない事も含めて提案するロール
これらは、あくまでも**職種定義**である。役割分担である。

あなたの職種はなんですか？　**ITコンサルとSEとプログラマー**
# 役割＝能力レベル？
世の中で転職価値等を考えていくと、どうしても、３　コンサル＞２　SE＞１ プログラマーとなってしまう。
３，２，１の順で給料が高いためです。人数構成としても３，２，１の順です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/c6e73e52-5276-b2e2-26bb-0617aad4d234.png)
でも、これって本当に価値として、そうなのでしょうか？
職種と職能レベルが一緒になってますよね。
確かに仕事の順番として、３　コンサル＞２　SE＞１ プログラマーの順番となる。いわゆる上流なのはコンサルである。
これにより、本来の意味の職種を世の中が職能レベルと勘違いして、優秀な人間＝上流（職種が高い）という間違った認識になってしまっている。
結果、キャリアプランとして、プログラマーは、SEへ。SEは、将来コンサルを目指してしまう。

# システムをエンジニアリングするエンジニアになろう
僕は、SEがコンサルできないとは絶対に思いません。優秀な人間でもSEをやってる人はいるし、コンサルできる人でもプログラマーをやってる人もいます。
何故なら、役割として、職種としてそこをやってるだけで、優秀な人間は、システムをエンジニアリングができる職能を持っているからです。
エンジニアは、コンサルもＳＥもプログラマーとしても、全ての職種をできる様になる必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/4210bbb5-6134-0c26-b9c7-1f56d7f82f6e.png)
コンサルでも、SE、プログラマーでも皆、エンジニアです。システムに関して精通したスペシャリストであるエンジニアになりましょう。
プロデューサーとディレクターも同じ事が言えるでしょう。ディレクション能力も無いのに、プロデューサーに成りたいって話も、僕的には、あり得ない話です。
だから、僕は、プログラマーとか、ＳＥとか分けて考える昔ながらのSIerは大嫌いです。
当然、職種としての役割定義では、使わざる得ないときはありますが。
全て何でも出来る本当の意味での価値のある**エンジニア**に育って欲しいと思ってます。