OmniAICreator/Qiita-1.07M huggingface dataset:
一年前に作成した(失敗した)二値分類モデルのリベンジ備忘録

::: note info 
本記事は[SLP KBIT AdventCalendar 2022](https://adventar.org/calendars/7569)の10日目の記事になります。
:::

https://adventar.org/calendars/7569

# 記事概要

にゃんぱすー。一年前(筆者がB1のとき)のSLPサークルの活動の一部にて、人間の男女の二値分類モデルの作成に取り組んでいたのですが、当時の私は「写経」→「動いた!楽しい!」(←かわいい)というレベルで、やってることのおよそ半分も理解できていませんでした。なので今回の記事では再度勉強がてら、以前作成したモデルがうまくいかなかった原因を探って自身の成長を体感するという回です。なお、コードを載せていると冗長になるので説明したいところだけを抜粋します、ご了承ください。

# 旧コードの現状結果確認

まず過去に作成したコードを実行したところ以下のような結果を得られました。lossは損失関数の値、accuracyは正答率でvalはテストデータの結果を表しています。
| loss | accuracy | val_loss | val_accuracy |
| --- | --- | --- | --- |
| 0.6929 | 0.5274 | 0.6936 | 0.4859 |

accuracyが約0.5と非常に意味のないモデルになっています。モデルの構成は以下の通りです。
![kyuumodel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2407661/f1f85cfb-130e-2f85-dd06-29bf91eae71d.png)
これを踏まえた上で精度の低さの原因を探る作戦を立てます。

::: note warn
以降では一年前に作成したコードと画像データを旧コード、旧データ、新規に作成するコードと画像データを新コード、新データと呼称します。
また、旧コード/旧データの結果を0番、次章で述べる作戦の「1. 2. ...」にあたる数字をそれぞれの結果の番号(n番)とします。
:::

# 作戦

基本方針は対照比較の手法で検証していくのですが、過学習状態などの例外的な結果が得られる可能性が考えられるので、結果が微妙な場合は一般的に良いとされている方を優先的に採択していきます。(本来ならデータセットを使ってモデルの検証までしたかったけれど時間的制約の関係で今回はパス)
具体的な手順は以下です。

1. 旧画像データをきれいにして0番と比較 → データの不備の有無
1. 新たに画像データを用意して1番と比較 → データの不備の改善
1. 新規コードを作成し新データで実行したものを2番と比較 → コードの優劣

# 検証

8割超えたら満点です。

### 1番

まず旧データから以下のような顔画像以外が切り取られたノイズ画像が多数散見されたためそれらを除去しました。
![8_8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2407661/4fa060fa-19dc-32ee-6397-c39be28c6edd.jpeg)

データ数は訓練データが282→280、テストデータが177→88になりました。データ数が少ないので意味はないと思いますが、検証なので一応実行したところ以下ような結果が得られました。
| loss | accuracy | val_loss | val_accuracy |
|:-:|:-:|:-:|:-:|
| 0.6963 | 0.4737 | 0.6946 | 0.4598 |

1番と比較するとaccuracyは下がっていますがこれはそもそものデータ数の不足によるものだと考えられるので、とりあえず2番を実行したいと思います。

### 2番

学習に用いるデータ数は多ければ多いほどいいというわけでもないと思いますが、あまりにも少なかったので訓練データを3256(1628x2)、テストデータを510(255x2)に増やしました。なお訓練データは傾斜やモザイク処理などにより500枚ほど水増ししています。
このデータを使用した旧コードの結果は以下です。
| loss | accuracy | val_loss | val_accuracy |
|:-:|:-:|:-:|:-:|
| 0.6892 | 0.5261 | 0.7858 | 0.3153 |

これもまたよくわからない結果になりました。別の条件で試してみるために3番にて新コードで実行します。

### 3番
モデルを構成するコードを変えて新データで実行します。新モデルの構成は以下の通りです。
![newmodel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2407661/5ae41c67-132a-65d5-7a83-0aa6a9876ef9.png)
圧倒的にパラメータを増やし、dropout層などを用いることでよりパラメータが適切になるようにしました。これを利用した結果は以下の通りです。
| loss | accuracy | val_loss | val_accuracy |
|:-:|:-:|:-:|:-:|
| 0.2921 | 0.8753 | 0.5512 | 0.7843 |

一気によくなりました。定かではありませんが、学習に必要なパラメータ数が足りていなかったということが推測されます。(今回はやりませんがちゃんとしたデータセットを使用して比較してみたい)
また余談ですが旧データを新コードで実行すると以下のようになりました。
| loss | accuracy | val_loss | val_accuracy |
|:-:|:-:|:-:|:-:|
| 0.0345 | 0.9966 | 0.9815 | 0.6102 |

過学習状態になっていますね。逆に言えばきちんと過学習状態になっているということなので、旧モデルよりも正常に動作していると考えられます。

# 終わりに
目標としていた8割を超えることはできませんでしたが一年前よりは向上したのでよしとします。また欲を言えば、モデルを構成する手法を変えたり、ハイパーパラメータの調整やデータ数をもっと増やして実行するなどしてまともなモデルになるようにしたかったのですが、時間が足りなかったのでそれはまた別の機会に試したいと思います。
かなり自己満足の記事になりましたが、最後まで読んで下さりありがとうございました。
DynamoDB timestamp を文字列と数値で Between 結果を一緒にする方法

# 背景
DynamoDB のテーブルにて、複合ソートキーのテーブルがあった。
複数の属性を "#" で結合したソートキー、って聞いた。

当初は以下みたいな感じかと思った
- 自動で属性を選択したら ソートキーが出来る
- 選択した属性単位で上手く検索出来る

そしたら、以下だった・・
- 単なる文字列
- "#" 自身で Join/Split する
- もしくは、属性を別途作成して保存しておき利用する。
    - 例
        - timestamp#id　＜複合ソートキー
        - timestamp
        - id

ここで問題となるのが以下。で、この解消法を記録

|属性|型|Between|理由|
|-|-|-|-|
|timestamp#id|文字列|lower <= x < upper|その後に続く文字がある為、上限一致**しない**|
|timestamp|数値|lower <= x <**=** upper|数値であり、上限も一致**する**|

# 結論
数値側の上限を除外すればいいので、FilterExpression ではじくのが一番マシかな、と

単純に SK として使う場合は文字列
Index で timestamp: number を利用する場合には、上限を弾く

```typescript: FilterExpression
const paramsQuery = {
  TableName: "User",
  IndexName: "user-post-index",
  ExpressionAttributeNames: {
    "#PK": "uid",
    "#SK": "timestamp",
    "#SKupper": "timestamp#post_id",  // Index では、単なる属性
  },
  ExpressionAttributeValues: {
    ":PK": "userID_0001",
    ":sortkeyval1": 1670550736983,
    ":sortkeyval2": 1670550736993,
    ":SKupper": "1670550736993",  // sortkeyval2 の文字列化
  },
  KeyConditionExpression: "#PK =:PK AND (  #SK BETWEEN :sortkeyval1 AND :sortkeyval2 )",
  FilterExpression: "#SKupper < :SKupper",
};
const users = (await ddbDocClient.send(new import_lib_dynamodb2.QueryCommand(paramsQuery)));
```

# 複合ソートキーは単なる文字列検索＆ソートなんですね

この場合、時刻 + ID にすると意味は無くて、日付 + ID なら、かなぁ。この設計でいいんだろうか？という疑問が・・

説明にあった以下のような階層化のほうが分かりやすいね
> [country]#[region]#[state]#[county]#[city]#[neighborhood]


# 検証
色々と試してみた記録

## ソート
色々入れてみたけど、結局日付とか関係なしに、文字の先頭からの文字コードソートって感じ
故に、文字列書式で Zero padding とかちゃんとしておけば大丈夫って話
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/8a56f6dc-b313-7e9b-d095-412791ed5de5.png)


## クエリ
文字列として検索するって考えれば、まぁ、普通。
EndsWith や Contains なんかもあればいいのに、とは思うけど。

|条件|結果||
|-|-|-|
|次と等しい|||
|次以下|**NG**|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/d048fda8-3466-5617-23e4-6d7fbf1964be.png)||
|次よりも小さい|OK|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/3feae9d9-6a09-88aa-7286-cd7f5634c6a8.png)||
|次以上|OK|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/1a9e98d9-42ba-c196-30c6-aba0e5d4fb13.png)|
|次よりも大きい|**NG**|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/7660dc85-60d6-f7fa-7deb-26d3b4feb3b6.png)|
|次の間|以上 + よりも小さい と考えるとOK|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/a342173b-5e81-0d70-e28d-20b14c2385eb.png)|
|次で始まる|普通に BeginsWith|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/9d1c37ca-3a19-bf83-cd6c-94cffac569a7.png)|

# あとがき
RDB とは違うんだよ、RDB とはって声が聞こえてくる感じ
色々学んでいく事が多いですね。

まずは、Lib.*Command を整理しておくところからかな
AcademiX流 1週間のPDCAの回し方

# はじめに

どうもこんにちは，Megです．
普段は，大学院で医療と機械学習について学んでいます．
ネットの世界では，[Meg Study](https://biotech-univ.com/)というtechブログを書いています．

さて今回は，AcademiXで定期的に行っている活動を活用して，**1週間のPDCAサイクルの回し方**の一例を紹介していきます．

PDCAサイクルについては，野村総合研究所（NRI）様の記事がわかりやすいので参照してください．

https://www.nri.com/jp/knowledge/glossary/lst/alphabet/pdca


# 活用する活動
1週間のPDCAサイクルを回す上で，活用する活動は以下の2つです．

- **定例もくもく会**（#11a-初学者向け勉強会）
- **週1定例報告会**（#11a-初学者向け勉強会）

括弧内の用語は，AcademiXのSlackでのチャンネル名を示しています．


## 定例もくもく会
定例もくもく会は，毎週火・木曜日19:00~21:00に開催される，自主勉強の時間です．

時間になったら[oVice](https://ovice.in/ja/)に集まり，最初の10分でそれぞれの作業内容を共有します．そして，各々作業をし，20:50になったらまた集合して，進捗度合いを共有します．

この各2時間，週4時間の時間がPDCAの**Do**に当たります！

### 学習時間

自習時間を毎週4時間取れていたら，3ヶ月で

$$4h \times 4week \times 3month = 36h$$

も確保でき，どのくらい成長できるか楽しみでしょうがないですね．


## 週1定例報告会
こちらは月曜の午前に，slack上で1週間の学習状況を共有する活動です．

共有内容は，以下のテンプレートにそって作成します．

### テンプレート

1. **出来たこと**
2. **分からなかったこと**
3. **今週やりたいこと**

それぞれの項目は，出来たこと（**Check.1**）・分からなかったこと（**Check.2**）・今週やりたいこと（**Plan/Action**）に当たります！

### Checkが2つある理由
上記のテンプレートでは，「出来たこと」と「分からなかったこと」の2つのCheck項目があります．
なぜこのようにCheckを分けているかというと，わからなかった内容に対して**メンバーの誰かが解答**してくれるからです！

これこそ，コミュニティで勉強する利点と言えるでしょう．


# おわりに
以上が，AcademiXの定例的活動を利用したPDCAサイクルの紹介です．
仲間と切磋琢磨しながら，自動的に1週間の**PDCA**サイクルを回せるのが強みです！

**もくもく会**と**週1報告**を取り入れるだけで，このPDCAサイクルは再現できるので，社内や研究室での勉強とフォーマットとしてぜひ活用してみてください．


# Appendex
付録として，AcademiX新規参加者へのオンボーディング資料において，今回のPDCAサイクルを紹介しているページを掲載します[^1]．

[^1]:こちらのスライドの著作権は作成者に帰属するので，使用したい場合はMegまでご連絡ください．


![onbording_page-0001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986668/05633283-d5e1-0b26-eb66-23cf2576fc35.jpeg)
Blenderでの繰り返し作業をPythonで効率化する

## この記事の概要

Blenderの練習をしていて、こちらの動画を見つけました。

https://www.youtube.com/watch?v=BfUwZ1nzv4g&t=486s

ピタゴラスイッチの「きょうのスレスレ」みたいで見ていて楽しく、難しい計算をせずとも作れるので面白かったです。
ただ、動画の5分頃から8分頃までで説明しているように、ひたすら人力でコピペを繰り返していたのでミスってしまいそうだなあと思いました。

というわけで、Pythonを使って自動化します。

:::note alert
この記事の内容で問題なく動作はするのですが、スピードが非常に遅いです。
高速化まで至れなかったのですが一旦記事にしました。
:::

## Scriptingの説明

Pythonを使う、といっても特別な準備が必要なわけではありません。
BlenderにはScriptingという機能があるので簡単に始められます。

普段よく使うのはLayoutタブなどだと思いますが、Scriptingタブを選ぶとText EditorやConsoleが表示されます。
ウインドウ右側の、緑で囲ったエリアにコードを書いて実行します。

| Layoutタブの表示 | Scriptingタブの表示 |
| --- | --- |
| ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/637d0a04-785b-3059-a499-faf047cc23c2.png) | ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/1b63a3ba-feef-169c-293b-245941821eac.png) |

## 環境

|  |  |
| --- | --- |
| Blender | 3.3.1 |
| Python (Blender内のもの) | 3.10 |

## 完成形

最初に完成形を示します。

```python
import bpy

pole = bpy.data.objects['Pole']
wall = bpy.data.objects['Wall']

start_frame = 129
end_frame = 233

def apply_boolean(object1, object2):
    boolean = object1.modifiers.new(type="BOOLEAN", name="Boolean")
    boolean.operation = 'DIFFERENCE'
    boolean.object = object2
    bpy.ops.object.modifier_apply(modifier="Boolean")

bpy.context.scene.frame_set(start_frame)

for i in range(start_frame, end_frame + 1):
    bpy.context.scene.frame_set(bpy.context.scene.frame_current + 1)
    apply_boolean(wall, pole)
```

`bpy`というモジュールが用意されていて、この中に色々なメソッドが用意されています。

```python
import bpy
```

今回でいうと、スレスレで通る棒を`Pole`と名付けて、壁を`Wall`と名付けています。
自分の名付けた通りに指定します。

```python
pole = bpy.data.objects['Pole']
wall = bpy.data.objects['Wall']
```

壁に棒が触れるタイミングが129フレーム目で、完全に通り終わるのが233フレーム目だったのでここで定義しています。
アニメーションの長さや回転スピード、メッシュの配置で変わってきます。

```python
start_frame = 129
end_frame = 233
```

今回のキモです。

- `object1`と`object2`を引数にとる関数
  - `object1`にBooleanモディファイアを追加
  - 棒で壁をくり抜きたいので、`Intersect`, `Union`, `Difference`のうち、`Difference`を指定
  - `object2`をBoolean対象に指定
  - `object1`のモディファイアを適用

```python
def apply_boolean(object1, object2):
    boolean = object1.modifiers.new(type="BOOLEAN", name="Boolean")
    boolean.object = object2
    boolean.operation = 'DIFFERENCE'
    bpy.ops.object.modifier_apply(modifier="Boolean")
```

フレームを`start_frame`にあわせます。
手動で合わせても大して手間は変わりませんが、念の為。

```python
bpy.context.scene.frame_set(start_frame)
```

`start_frame`から1フレームずつ進めて、その度にモディファイアを作成→適用を繰り返します。

```python
for i in range(start_frame, end_frame + 1):
    bpy.context.scene.frame_set(bpy.context.scene.frame_current + 1)
    apply_boolean(wall, pole)
```

## 最後に

これにて無事にアニメーションが作成できました。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/732a51f5-5e92-850c-d206-206628e967b0.gif)

記事冒頭にも書きましたが、処理スピードが速くなるともっと気楽に使えるのですが……。
とりあえず、コードによりミスがなくなったという意味で良しとします。

---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox

Devトークでのお話してくださる方も募集中です！

https://jobs.qiita.com/employers/qiita-inc/dev_talks/489
決定木・ﾗﾝﾀﾞﾑﾌｫﾚｽﾄのﾊﾞｵﾊﾞﾌﾞ可視化

# はじめに

決定木・ランダムフォレストのツリー構造の可視化ツールはいろいろある。
色々調べてみるとバオバブの木を逆さにしたようにツリー構造を可視化できるツールが
良さそうだったので、記事を書いてみることにした
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/3330e74b-7e02-33b7-71b0-a9d6c0cce394.png)

# pybaobabdtとは
下記を参照するとどうやら分類問題のツリー構造の可視化に適用できるようだ。
（回帰問題にも適用できるかは試してません）
詳細は下記をご参照ください。

https://pypi.org/project/pybaobabdt/

ツリー構造を下図のように可視化してくれるため、
視覚的にも非常に分かりやすいと感じました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/5a952836-9447-7dcf-c7c6-e7beb4918dfa.png)

# 環境構築&インストール

~~~py
# pybaobabdtのインストール
pip install pybaobabdt

#pygraphvizのインストール
apt install libgraphviz-dev
pip install pygraphviz
~~~

# datasetsの準備
試しに使用したデータセットは下記の通り

https://github.com/renatopp/arff-datasets/blob/master/classification/vehicle.arff

# 実践
~~~py
import pybaobabdt
import pandas as pd
from scipy.io import arff
from sklearn.tree import DecisionTreeClassifier

data = arff.loadarff("vehicle.arff")
df   = pd.DataFrame(data[0])
#データの確認
df
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/aae41966-ede1-a113-a266-36f14c0f1d5e.png)

バン・バスなどの車種（Class)で分類してみる。
~~~py
y = list(df['Class'])
features = list(df.columns)
features.remove('Class')
X = df.loc[:, features]

clf = DecisionTreeClassifier().fit(X,y)
~~~

そして、

深さ3層で可視化した場合
~~~py
ax = pybaobabdt.drawTree(clf, size=30, dpi=72, features=features,maxdepth=3)
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/055bdcd7-5c26-618f-0922-39cd438bc223.png)

さらに深さ10層までを可視化すると
~~~py
ax = pybaobabdt.drawTree(clf, size=30, dpi=72, features=features,maxdepth=10)
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/f989ee18-aab3-41bb-8a70-2accbdcd7c1f.png)

:::note info

このように深さをだんだん大きくしながら可視化していくと解釈がしやすい

:::

---


# 別の問題で実践

分類問題でお馴染みのアヤメのデータセットで試してみます！

~~~py
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

iris=load_iris()
X=iris.data
y=iris.target

from sklearn.tree import DecisionTreeClassifier
dtc = DecisionTreeClassifier()
dtc.fit(X,y)

ax = pybaobabdt.drawTree(dtc, size=10, dpi=72, features=features,maxdepth=10)
~~~
一瞬で下図のようにアヤメの分類が
視覚的に分かりやすく表現されました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/64315dc2-809e-0aaf-e695-c3e3f47d4dfa.png)

# 最後に
分類問題の可視化で分かりやすい手段の一つだと思います。
また、どういう分岐構造なのかを視覚的に示しやすく、説明もしやすく思います。
私も今後ドンドン活用していこうと思いました！
以上　最後までお読み頂きありがとうございました:v:
[GitHub]first commitの仕方

GitHub　でのfirst commitの仕方についての備忘録です。

## ローカルリポジトリを作成

![スクリーンショット 2022-12-10 22.50.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850786/d8fe7464-c9a3-cc64-4cbd-0f3005d867ae.png)

左上の「Current Repository」→「Add」→「Add Existing Repository...」をクリック

![スクリーンショット 2022-12-10 22.53.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850786/e880c19a-b429-7b68-0d4d-dffce6370999.png)

管理したいディレクトリを選択し追加

## first commit
![スクリーンショット 2022-12-10 22.55.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850786/f3d18f00-de57-d4f4-518d-6b0752b19faf.png)


## リモートリポジトリを作成
Publish repository をクリック

![スクリーンショット 2022-12-10 22.58.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850786/ccde8326-affa-8e7d-cc8d-8b1e4481cb8a.png)

「Keep this code private」にチェックが入っていると非公開

## ブラウザで確認
リモートリポジトリが作成できているか、ブラウザで確認

以上です。
【Zsh】読み込まれる設定ファイルについて

## 読み込まれる設定ファイル一覧

| 設定ファイル  | ログインシェル | インタラクティブシェル | シェルスクリプト |
| :-----------: | :------------: | :--------------------: | :--------------: |
|  /etc/zshenv  |       ◯        |           ◯            |        ◯         |
|   ~/.zshenv   |       ◯        |           ◯            |        ◯         |
| /etc/zprofile |       ◯        |                        |                  |
|  ~/.zprofile  |       ◯        |                        |                  |
|  /etc/zshrc   |       ◯        |           ◯            |                  |
|   ~/.zshrc    |       ◯        |           ◯            |                  |
|  /etc/zlogin  |       ◯        |                        |                  |
|   ~/.zlogin   |       ◯        |                        |                  |
| /etc/zlogout  |       ◯        |                        |                  |
|  ~/.zlogout   |       ◯        |                        |                  |
プログラミングにおけるChatGPTの使い方(制作編)

### ChatGPTとは
この辺とか参考にどうぞ。
<b>チャットGPTってなんだ？イーロンマスク提出用のコードも一瞬で書けちゃうAIチャットボット</b>
https://www.gizmodo.jp/2022/12/chargpt-what-is-it.html

### 会話AIとしてはポンコツ
まず、前提として「会話が出来るAI」としてChatGPTを見ない方が良い。
会話は少し試せばポンコツだとわかる。
詳細はこちらをどうぞ。

<b>チャットできるAI、ChatGPTが｢そこまですごくない｣理由。見えてしまった限界</b>
https://www.businessinsider.jp/post-263042

この一言が全てを物語っていると思う。
<b>「ChatGPTは、一見するともっともらしい答えを返せるように、うまく調整されている。」</b>
僕も触ってみて同意である。

### プログラミング補助道具として使えるか？
上記記事、「チャットできるAI、ChatGPTが～」の中で「誤ったプログラムを出力すること」が指摘されているし、僕も触ってみて「惜しいんだけど違うんだよなぁ」という出力を見かける。

しかし、これを以て、「まだプログラミングにAIは使えない」と判断するのは早い。
「8~9割くらいはちゃんとしたこと書いている」というコードもわりと出してくるからだ。
ということは残り1~2割を修正すれば、結構使い物になるかもしれない。

### 実際に書かせてみた

以下、実際のやり取り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203740/824898c0-c99b-f551-0f6b-f628dd300bf8.png)
惜しい。
意図としては「ボタンを押したらhello World」と表示して欲しいのに、このコードだとボタンを押す前から表示されてしまうし、ボタンを押しても何も起こらない。

こーなる↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203740/e5244ef5-10ad-ea93-ac7c-22ddf368fa2b.png)

なので修正するように指示した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203740/27b3d240-2068-0443-a4cc-1cfe3060edda.png)
こーなった↓(わかりにくいけれど黒い部分はコマンドプロンプト)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203740/6c4e63ff-23a5-528e-8503-5029900cac2a.png)
<b>いいね！</b>
とはいえ、最低限の処理を通したに過ぎない。

次。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203740/17c24493-a7c9-90f7-8af5-1a0bf268edad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203740/4bf88e35-0bd5-6a96-9fbc-71ae3ee1c452.png)
(AIが読み取るには)やや複雑な内容にしたつもりだったが、思った以上にちゃんと書いてきたのはびっくり。

実行するとこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203740/a69a605b-191e-0f8e-88df-157fd2a235b1.png)
ほぼ9割方イメージ通りの形。想定していなかったのはsg.Output(出力用窓)を用意してきたことだけど、これはむしろ「想定外の良い仕事」だったので褒めてあげたい。

さて、動かしてみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203740/6df8d90b-64a2-4e7a-4c5a-d012b82aab71.png)
ちゃんと、6の2乗である36が出力された。

また、指定した通りに日付、時間、出力値がCSVに吐かれている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203740/6d02b345-ed2b-d699-d6b7-e1c9af38b7af.png)
先ほどよりも複雑な処理を命じたつもりだが、ほぼ完璧な形で答えてくれた。
ただ、クローズボタンを押された際にエラーが吐かれてしまう問題だけ残っていたので、それはこちらで手直ししてやった(elseとbreak文の2行のみ)。評価：90点。

ChatGPTが指示を受けとってからコード出力までたぶん30秒かかっていないと思うが、それで40行ほどのコードを生成して、90点のコードを書いてくれるというのは非常にコスパが良いと思う。

### 注意点
・一度に吐き出せるのは40行くらいのコードまで？(要調査)。例えば80行くらいかかりそうなコードを指示しても、途中で止まる(これが約40行)。ここで「続きを書いて」と伝えても、また最初から同じコードを書き始めて止まる。

### ChatGPTとの付き合い方のスタンス
<b>めちゃくちゃ手の速い新人プログラマと思って指示を振るのが良。</b>
「40行程度のコードを1分で書いてくれる」「けど、しばしばポカミスをやらかす少しお間抜けさん」と考えておけば、変なミスを犯しても腹が立たない(たぶん)。


### どんな時に使えそうか？
プロジェクトの開始時、要件を渡されたらとりあえずそれをChatGPTにそのままぶち込む → 面倒で単調になりがちな初期コードの生成をサクッと行ってくれる。import ~を何行も書いたり、お約束コード(PySimpleGUIならwindowやwhile文を用意するなど、テンプレート的な処理)の生成は楽になる。

その後、大量に修正が必要な部分は修正するように指示を出して、数行程度の簡単な手直しで良ければ自分の方で手直しをする。このようにすると時間も大幅削減出来るし、単調作業部分で疲れにくい。

<b>単調作業部分で疲れにくい</b>
↑ここ大事

### 人間の新人プログラマよりは有用かも？
とりあえず手の速さは相当なものがあるし、修正を命じても嫌な顔一つせずに淡々と進めてくれる。
特別優秀な人を除いて、多くの新人よりは貢献してくれるかもしれない期待感がある。

<b>(退屈な|つまらない)作業は全部投げちゃえ！</b>
というスタンスで使うと結構ハッピーになれるかもしれない。
プログラミング学習を学ぶ前に知っておきたいこと~投稿編~

## 初めに
この記事は**プログラミング学習を学ぶ前に知っておきたいこと**と題したシリーズの一つです。
このシリーズは今回の記事で最後となります。

## このシリーズ記事の対象者
- プログラミングに興味を持って、学習を検討している方
- 学習したいけど、何から手をつけたらいいのかわからない方

[前回の記事](https://qiita.com/MPrg2011/items/2d417cefd66cb8048064
)の続きです。

https://qiita.com/MPrg2011/items/2d417cefd66cb8048064

今回はQiitaやSlack,Discord,Notionに投稿する際に使用するマークダウン記述の参考になるサイトやよく使うものを紹介します。


### Qiitaのマークダウン記法

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

私個人何度開いたかわからないページ。
Qiita公式なので間違いは無いかと思います。

### Slack

https://slack.com/intl/ja-jp/help/articles/202288908-%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%AE%E6%9B%B8%E5%BC%8F%E8%A8%AD%E5%AE%9A

Slackは入力画面で書式設定が出るのであまりググらなくても入力しやすいかと思います。
検索すると最初にQiitaで書かれた記事が出てきますが公式もわかりやすいのでこちらをシェア。

### Discord

https://qiita.com/xero/items/6026ed007d5d34623a50

Slackとは違い書式設定が一切表示されません。最初コードブロックさえできないと思っていました。
[公式のヘルプページ](https://support.discord.com/hc/ja/sections/115000458672-%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%81%E3%83%A3%E3%83%83%E3%83%88)がとっても見にくい(英語と日本語が混ざってる)ので、Qiitaで書かれた記事を紹介します。

ネタバレ用の書式があるのが特徴。


### Notion

https://katex.org/docs/supported.html

マークダウンは`/`または`＋`マークを押すと表示してくれますが、それとは別で**変数**を指定することで文字を装飾することが可能です。
文字の大きさや色など、デフォルトで表示されているもの以外にしたい時に活用してみて下さい。

---
### 最後に
短い記事でしたが最後まで見ていただきありがとうございました。

明日はProgateの新サービスを使った感想について投稿予定です。

[]()
切れたら逆ギレされた話

謎のアドベントカレンダー、第 12 話です。

以前、

- **[拠点間接続に困った話 (2)](https://qiita.com/hmatsu47/items/ad410042d39d4d33ab56)**

https://qiita.com/hmatsu47/items/ad410042d39d4d33ab56

- **[拠点間接続に困った話 (3)](https://qiita.com/hmatsu47/items/53f31c500ebf304fc45f)**

https://qiita.com/hmatsu47/items/53f31c500ebf304fc45f

で出てきた中国の拠点の話です。

[(2)](https://qiita.com/hmatsu47/items/ad410042d39d4d33ab56) と [(3)](https://qiita.com/hmatsu47/items/53f31c500ebf304fc45f) の間、(2) からしばらく経った頃の話です。

## 例の如く

中国拠点のネットワーク接続が切れたときの話です。

原因を調べていると、

- 日本から中国拠点の VPN ルーターまでは普通につながっている
- その先の中国拠点のサーバー、パソコン等の機器には一切接続できない

ということで、

- 拠点のメインスイッチ
- メインスイッチの先の LAN ケーブル
- VPN ルーター

の順に、状態の確認と予備への交換を試すように中国側に伝えました。

ほどなく、 **「全部やってみたけど直らない」** との回答が。

そんなに早く全部試せるはずはないので、 **「全部確実にやり直してほしい」** と告げましたが… 

## 「きちんと試した」「なんとかしろ」

まあ、ありがちな展開ですね。

そう言われてもどうしようもないので、しばらくこう着状態に。

最後は中国側が折れて、こちらが伝えたとおりの内容を中国側で試した結果 **LAN ケーブルが断線していた** ことが分かりました。

（というか、そのあたりの作業が理解できるメンバーが不在だった→拠点に戻ってきて伝えたとおりのことをしただけだったようで）

## 後日、日本のメンバーが現地視察をすると

オフィス内の状況がわかりました。

当時は、

- 食事やおやつの食べかすをカジュアルに床に捨てていた
- そしてそれが隙間から OA フロアの下に落ちて蓄積
- それを目当てに夜な夜なネズミがオフィス内に侵入
- 食べかすとともに床（OA フロアの下）の LAN ケーブルも齧っていった→断線

という状況だったそうです。

（いまの日本では「ありえない」という感覚でしょうが、当時の中国では割と普通だったらしいです。本当か？）

まあ、そんな状況なら LAN ケーブルが切れてもおかしくないでしょうねー（棒）。

## 日本とは違う、（当時の）中国の LAN 配線事情

また、これは中国のほうが特殊なのか、逆に日本のほうが特殊なのかは意見が分かれるところですが（？）。

有線 LAN が中心だった当時、日本では

- フロアのメインスイッチから一旦「島ハブ」に配線
- 島ハブからそれぞれの席に配線

という文化（？）が割と優勢だったのに対して、中国では

- フロアのメインスイッチから、可能な限り直接それぞれの席に配線

という設計のほうが優勢だった（そしてそれに並々ならぬ強いこだわりがあった）ようで、配線上、LAN ケーブルを交換しようとするとかなり大変な作業になり、それもあって（たくさんのケーブルが刺さっている）メインスイッチの予備機交換や LAN ケーブルの交換を躊躇した面もありました。

その後は日本側と中国側で対応のルールをあらためて話し合って、出入りしている保守サービス業者さんへの依頼も含めて中国側である程度対応できるようにしてもらいました。

うん、あとは任せた。

---

13 日目の記事に続きます。

- **[ビルの電源が全落ちした話](https://qiita.com/hmatsu47/items/8f8304543acdeaba0fde)**

https://qiita.com/hmatsu47/items/8f8304543acdeaba0fde
BlazorでVB.NETを使ってみる

# はじめに
これは、[Visual Basic Advent Calendar 2022](https://qiita.com/advent-calendar/2022/vb)の10日目の記事となります。

Blazor プロジェクトで、VB.NETを使う方法を2点を紹介します。

# C#と組み合わせ
同じ Blazor プロジェクトで C# と VB.NET を組み合わせる方式となります。

https://www.c-sharpcorner.com/article/combine-c-sharp-and-vb-net-in-same-blazor-project/

VB.NET用のクラスライブラリーをプロジェクトに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/d01a1a21-c8d1-ec00-3290-134eaf3bed62.png)

BlazorCsharpVBプロジェクトで右クリックメニューから追加のプロジェクト参照で、「VBNETClassLibrary」を選択して、OKボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/d4343d15-5215-3020-634d-899cd71de49a.png)

usingの指定が有効になります。

```cs:Employees.razor
@using VBNETClassLibrary
@page "/employees"
```

## 実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/78789ae6-ea28-a4ef-ba0e-1ec61dc813e1.png)

この方法は、VB.NETで作成したクラスライブラリーをC＃に移植する必要なくそのまま使用できる利点があります。

# VBそのまま
先日、VB.NETでレコード型を使えるプロジェクトを紹介しましたが、その方のGitHubの他のリポジトリを見ていたところ、「BlazorVB」というリポジトリを見つけました。

https://github.com/VBAndCs/BlazorVB

ソースコードだけを見たら、BlazorアプリをVBで作成していました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/90c7ff14-8829-1975-b5f9-72657600c7f5.png)

## 実行
プロジェクトが少し古いので、.NET 5.0で作られています。
作られた当時は動作していたかも知れませんが、今だとメニューとかが表示されませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/7cc8b217-5f09-7c93-b5d5-169c36d99f6d.png)

下記サイトの指摘で`NavMenu.razor.g.vb`は更新されたようですが、今は動作しなかった。

https://github.com/dotnet/runtime/issues/53169

## 今後
[別ブログ](https://anthonydgreen.net/2022/11/04/the-road-ahead-wheres-this-all-going/)のコメントに作者の11月5日のコメントがあります。

>If fact I didn’t dig deeper into Blazor, as I was busy developing Small Visual Basic (and other stuff) over the two past years, but I can start now, especially .NET 7 is about to release, and I expect Blazor to be mature enough now.
DeepL翻訳
実はこの2年間はSmall Visual Basicの開発で忙しかったので、Blazorを深く掘り下げていませんでしたが、今なら始められます。特に.NET 7がもうすぐリリースされますし、Blazorも十分に成熟していると期待しています。

ちゃんと動作するように改善されることを期待しましょう。

# 最後に
C#と組み合わせは問題なく使用できます。Blazorの仕組み的にプロジェクト参照ではなく、VB.NETで作成した「dll」を参照するだけでも動きそうな気がしますけどね。

BlazorVBは、作者の頑張りに期待します。
NextAuth.jsでTwitter認証するときに困ったこと

ハッカソンで [S’more](https://smore.vercel.app/)というTwitterのいいねした記事を管理できるアプリを作成しました。
他の記事を調べてもあまり情報がなかったので、はまったポイントを共有します。

# 環境・前提
- NextAuth.js 4.12.2

# はまった所

## 環境変数の設定
[...nextauth].tsでTwitter Developer Portalから取得したキーを登録しますが、NextAuthのclientId, clientSecretに対して、clientId, ClientSecretではなく、**API_KEY**, **API_KEY_SECRET**を登録するとキーが正しくない問題は解決しました。
```js:[...nextauth].ts
export const authOptions = {
  providers: [
    TwitterProvider({
      clientId: process.env.API_KEY ?? '',
      clientSecret: process.env.API_KEY_SECRET ?? '',
      version: '1.0a',
    })
  ]
}
```
## Twitter認証が通らない
実際にTwitter認証をNextAuthで行うと、エラーが返ってきて認証ができませんでした。
これは、Twitter 開発者ツールの権限を **Essential Access** から **Elevated Access** に挙げることで解決しました。少し文章を書けば無料で申請することができます。
原因についてはあまり調べられていません。
コンテナ概論 〜コンテナってなに〜

# はじめに

この記事はコンテナ初学者が中級者になる為に必要なことをまとめていく記事です。
今回はコンテナについて解説しています。

## コンテナとは

コンテナと言えば、Dockerのように言われがちですが、実際にはいろんなコンテナエンジンがあります。
ここでは説明しませんが、多くの人がコンテナを使う上でDockerを使っていると思います。

そもそもの話ですが、コンテナとはなんでしょうか。

### 概要

コンテナはLinux上で動くプロセスをあたかも「コンテナ」のように隔離した状態で起動することです。
異なるOS上でもコンテナエンジン上であれば、ほぼ同じ環境を提供することができるようになります。

そもそもコンテナというのはプロセスコンテナと呼ばれるパッチセットから生まれており、これはLinux上のプロセスをコンテナと呼ぶ階層にグループ化する技術です。

プロセス同士が繋がり合わないようにプロセス間で壁を作るこの実装こそがコンテナと呼ばれるものです。

:::note info
プロセスが「コンテナ」という実装に隠れているというイメージ
:::


このコンテナ環境を実現する上で大事なこととしてはプロセス空間と名前空間があります。

### コンテナの仕組み

プロセス空間とは別名ユーザ空間と呼ばれ、プログラムが実際に動作する空間と考えると良いでしょう。
さらにこのプロセス空間で動くソフトウェアを管理する空間を`名前空間`と呼びます。

この名前空間を制御することによって複数のプロセスがLinuxカーネルを共有できるようになっています。
なお、プロセスが使うリソースを制限するには`cgroup`を利用します。

名前空間でプロセスの制御、cgroupでプロセス毎のリソース制限を設定できます。

## コンテナが動く環境

ここまででコンテナの概要を見てきましたが、ではコンテナはどのような環境で動作するのでしょうか。
結論から述べるとコンテナが動く環境はLinuxです。「あれ、じゃあなんでMacOSやWindowsで動くの？」
とそう思われる方がいるかもしれません。

簡単に言えば、各OS上で何かしらのLinuxカーネルを参照しています。
Linuxカーネルを動かしてその上でコンテナを起動しています。

OS上で動いているように見えて実は全てはLinuxの上でしたという感じです。

:::note info
結局はすべて、Linux上で動いているということ
:::

## まとめ

今回の内容がコンテナをもっと知る機会になりましたら幸いです。
次はコンテナのセキュリティやDockerfileに関するベストプラクティスを振り返りたいですね、

## おわり
【UE5】ToonでもVirtual Shadow Mapsしたい！

# まえがき

UE5の影描画ってキレイですね。
Toon描画も、この恩恵にあずかりたいなぁ… エンジン無改造で！

というわけで、UE5のキレイな影を利用する手法を紹介します。ネタとしてどうぞ。あまり実用的じゃないかも。。

こんな感じの処理ができます。

|←完成した絵、陰影なし、影マスク→|
|-|
|![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/9bfddec7-9d0b-cd46-91b4-62913a245b98.png)|

モデルはNecoMaidさん
https://booth.pm/ja/items/4252664

ポーズは VRM Posing Desktop
https://store.steampowered.com/app/1895630/VRM/

よりお借りしています。感謝！

# 従来のToonの影のアプローチ

## 従来手法：PostProcessを使う
PostProcessでBaseColorと比較します。定番手法です。
お手軽かつ見栄えの良い絵を出すことができます。
ただ画面を一律で処理するため柔軟性がなく、痒いところに手が届きません。

詳しくはこちら ↓
https://www.raywenderlich.com/146-unreal-engine-4-cel-shading-tutorial

## 従来手法：自前シャドウマップを使う
自前でShadowMapを作る方法です。
キャストシャドウを判別しつつ、マテリアル個別の処理もできます。
ただ影の解像度が足りなかったり負荷が高かったりで、イマイチです。

詳しくはこちら（数年前に書いた記事です） ↓
https://qiita.com/ruyo/items/71a3f2f694d2853b3f1e



# 今回の手法：Translucentを利用した影の判別

従来手法を良いとこ取りした、Translucentを利用するToon影処理です。

モデルを2度、重ねて描画します。
実際の絵はこちら。

|1回目の描画|シンプルな白|
|-|-|
|![0_sc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/cae8458b-cadc-21e0-8ea6-cb72d1a12b27.png)|![0_mat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/21594427-5e6a-2f3a-f4f1-e1d3a2b45f8a.png)|

|2回目の描画。同じモデルを重ね描きしている。<br>光の当たる箇所が赤、陰が青|Translucentで描画。SceneColorの明度で2値化している|
|-|-|
|![1_sc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/167fced0-7e3c-a06c-1962-e820a05e9eaf.png)|![1_mat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/2a20d07b-3f6d-7eb2-0995-a95837630abf.png)|

不透明の白で描画した後、同じモデルを半透明で重ね描きします。
下地の明度から 陰影を判別します。

|キャストシャドウの判別も可能|
|-|
|![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/2042f0b7-d97e-4887-3f02-8a47768c8c25.png)|

これにて、影を判別できるようになりました。（正確には単に暗い部分を検出してるだけなので、AOやGIの影響も受けます…）
あとは好きな色に塗り分けましょう。マテリアル内で柔軟に処理ができます。
パーツ毎に、階調やハイライトも設定できます。

なお、2度目の描画ではSceneColor以外にもNormalとDepthを参照することができます。
工夫次第で面白い効果を出せます。（簡易的なコンタクトシャドウとか、ドロップシャドウなど）

|ハイライト対応、影色を調整した例|
|-|
|![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/f41cceb3-0ab6-6ab6-c46a-796ca72a8e78.png)|

# あとがき

むりやり影を利用する方法を紹介しました。

内部のShadowMaskTextureにアクセスできれば もっとシンプルに対応できるのですが… このあたりは、まだまだエンジン改造の必要がありますね。
なにか良い抜け穴を知っている方がいたら教えてください…

なお、この手法は [VRM4Uプラグイン](https://ruyo.github.io/VRM4U/02_toon/) でお手軽に利用できます（宣伝）
興味ある方はお試しくださいー

おしまい。
【GMC-4】実機と有名？シミュレータでKA命令の仕様が違う件

GMC-4の `KA` 命令は、現在押されているキーの情報を受け取る命令である。
この `KA` 命令の仕様が、実機

* FX-マイコン
* GMC-4
* [ORANGE-4](http://www.picosoft.co.jp/ORANGE-4/index.html) (Ver 1.09)

と、シミュレータ

* [FX-マイコン シミュレータ](https://www.vector.co.jp/soft/win95/util/se289783.html) (Version1.3)
* [GMC-4 シミュレータ](http://dansan.air-nifty.com/blog/gmc4-simulator.html) (version 1.39)

で異なっていることがわかったので、ここで報告する。

# 検証方法

以下のプログラムを実行する。

```
機械語  プログラム
        start:
8 0       TIA 0      ; Aレジスタの値を0にする
0         KA         ; キー入力を読み込む
1         AO         ; Aレジスタの値を7セグメントLEDに出力する
F 0 0     JUMP start ; 最初に戻る
```

# 実機での動作

キーを押すと7セグメントLEDの表示が押したキーの番号になり、
キーを離すと7セグメントLEDの表示は**0に戻った。**
すなわち、`KA`命令はキーが押されていないときはAレジスタの値を**変更しない。**

# シミュレータでの動作

キーを押すと7セグメントLEDの表示が押したキーの番号になり、
キーを離しても7セグメントLEDの表示は**押したキーの番号のまま変わらなかった。**
すなわち、`KA`命令はキーが押されていないときはAレジスタの値を**前回押されたキーの番号に設定する。**

# 実際の実行の様子

5種類の環境それぞれで実行した様子を、1本の動画にまとめた。

<iframe width="560" height="315" src="https://www.youtube.com/embed/J9KQkvSGYPg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 追加検証

前述の検証で、実機3種類ではキーを押していないとき `KA` 命令の後のAレジスタの値は0となった。
これは、「Aレジスタの値が維持される」以外に、「Aレジスタの値が0になる」という仕様の可能性もある。

そこで、`KA` 命令を実行する前にAレジスタの値を0ではなく1に設定するプログラムを実行してみた。

```
機械語  プログラム
        start:
8 1       TIA 1      ; Aレジスタの値を1にする
0         KA         ; キー入力を読み込む
1         AO         ; Aレジスタの値を7セグメントLEDに出力する
F 0 0     JUMP start ; 最初に戻る
```

すると、今回の3種類の実機全てにおいて、キーを離したときの7セグメントLEDの表示は1になった。
したがって、`KA` 命令は「キーを押していないとき、Aレジスタの値を0にする」という仕様ではないことがわかった。

次に、「Aレジスタの値を、前回の `TIA` 命令で設定した値に設定する」という可能性を検証するため、以下のプログラムを実行した。

```
機械語  プログラム
        start:
A 3       TIY 3      ; Yレジスタの値を3にする
8 2       TIA 2      ; Aレジスタの値を2にする
3         CY         ; AレジスタとYレジスタの値を入れ替える
0         KA         ; キー入力を読み込む
1         AO         ; Aレジスタの値を7セグメントLEDに出力する
F 0 0     JUMP start ; 最初に戻る
```

すると、今回の3種類の実機全てにおいて、キーを離したときの7セグメントLEDの表示は3になった。
よって、「前回の`TIA` 命令で設定した値に設定する」という仕様でもないことがわかった。

「前回の `AIA` 命令で設定した値」など、他の可能性も考えられるが、
そうなるとこれまでの検証用プログラムで使用していない命令を参照することになり、不自然になる。
よって、「実機の `KA` 命令は、キーが押されていないとき、Aレジスタの値を変更しない」と考えるのが自然だろう。

# 余談

FX-マイコンシミュレータは「マイコンユニットの動作をできるだけ忠実に再現しました」と主張しているが、
ここは再現できなかったのですね…:disappointed_relieved:

GMC-4 シミュレータ、アプリケーションの Help → About で確認するとちゃんと version 1.39 なんだけど、
ドキュメントには Version 1.38 って書いてあるんだよなあ…:thinking_face:

コードを読んだ結果、以下の実装の `KA` 命令はキーが押されているときのみAレジスタの値を変更する仕様のようである。

* [Arduino勉強会/0E-GMC4をArduinoで作ってみる - PukiWiki](http://www.pwv.co.jp/~take/TakeWiki/index.php?Arduino%E5%8B%89%E5%BC%B7%E4%BC%9A%2F0E-GMC4%E3%82%92Arduino%E3%81%A7%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B)
* [GMC-no :: nshdot:lab](https://lab.nshdot.com/old/gmc-no/)
【解決】axios.deleteのリクエストがsinatraで受け取れずに困った

# axios側

`axios`の`delete`メソッドの書き方は↓らしい
```js
axios.delete("/url/to/api", {data: param});
```

ブラウザのデバッグコンソール（payload）でも値が入ってることが確認できたのでよさそう。
`sinatra`側はなんかエラー出てるけど一歩前進。

# sinatra側

`sinatra`はデフォルトで`delete`メソッドを受け取れないらしい。。
↓のように`_method`ハックを許可する必要があるとのこと。
```ruby
enable :method_override
```
* [:method_override | CONFIGURING SETTINGS | sinatra](https://sinatrarb.com/configuration.html#method_override---enabledisable-the-post-_method-hack)

`_method`ハックは本来、`form`要素が`GET`と`POST`しか使えないのを疑似的に`PUT`や`DELETE`を使えるようにする手段（のはず）。
とりあえず`axios`から渡すパラメータにも`_method`入れておきましょう。

```js
const param = {
    _method: "DELETE",
    ...
};
```

これで`sinatra`でリクエストを受け取ることが出来た…が、`params`が空っぽだ…！

# ふたたびaxios側

色々ためすもののパラメータが飛ばない。
ふと、DELETEメソッドってGETと同様、リクエストボディないよなーと思って、↓のように書き換えてみた。

```js
- axios.delete("/url/to/api", {data: param});
+ axios.delete("/url/to/api", {params: param});
```

パラメータ取れた！
GitLabでプロジェクトのPublic(公開)設定が出てこないときに確認すること

## 前提

SaaSのGitLab`GitLab.com`での話｡(自前の環境にインストールするGitLabではない)  
※GitLabの種類については[こちら](https://qiita.com/masakura/items/29f8949379fa86dac22c#%E3%81%BE%E3%81%A8%E3%82%81)のQiita記事が分かりやすい｡

## 結論

**グループの公開設定**をプライベート→パブリックに直したら出てきた｡
GitLabは `グループ` / `プロジェクト` の構造になっている｡

## 経緯

検索しても目当ての情報が中々見つからなかったのと､GitLab初心者なら同じ様に躓きそうだと感じたので紹介する｡

一般公開した場合の挙動を確かめようと､プロジェクトの **General Settings** (一般設定) > **Visibility, project features, permissions** (可視性、プロジェクトの機能、権限) > **Project visibility** (プロジェクトの可視性)を`Private`→`Public`に変更しようとした｡  
しかし`Public`が非活性で選べないじゃん! と躓いてしまった｡

![スクリーンショット (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545436/8cd8c37d-2f9b-1b62-753b-15be5b787e2b.png)

### グループの公開設定を変える

冒頭で紹介した通り､GitLabは `グループ` / `プロジェクト` の構造になっている｡  
そのため **グループでパブリック** にしてあげると､プロジェクトでもパブリックを選べる｡

1. プロジェクト画面上部のパンくずリストから､グループ画面に遷移できる｡
![Screenshot 2022-12-10 at 21-47-34 General · Settings · Umionos _ Pentaprism · GitLab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545436/b1c484d2-0bbc-c6c7-1c76-6e1decf9086d.png)
2. **General Settings** (一般設定) > **Naming, visibility** (名前､可視性) > **Visibility level** (可視性レベル) を `Public`(パブリック)に変える
![グループ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545436/ff5dccdb-1a85-5281-b6e0-60c404bfb488.png)

### 再度､プロジェクトの可視性を変える

プロジェクトの **General Settings** (一般設定) に戻ると､`Public` (公開) が表示されているはずだ｡

![プロジェクト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545436/608c5399-7ea1-6f06-81fb-36d9a18a180c.png)
仮想化ソフトウェアを無料で商用利用したい

ググった内容をメモ。

ホストOS型の代表的な仮想化ソフトウェア

# VMware Workstation Player（無償版）
無償版は個人使用向け。
VMware Workstation Player 14.x の販売、ライセンス、および互換性に関する FAQ (2126732)
[https://kb.vmware.com/s/article/2126732?lang=ja](https://kb.vmware.com/s/article/2126732?lang=ja)
>VMware Workstation Player 14.x には、次の 2 つのエディションがあります。
>VMware Workstation Player 14 – 無償バージョン
>VMware Workstation Player 14 – 有償バージョン
>個人使用向けで無償の VMware Workstation Player 14 と、
>商用で $149.99 （米ドル）の VMware Workstation Player 14 があります。 
>VMware Workstation Player 14 有償エディションのアップグレード価格は、$79.99 （米ドル）です。

# VMware vSpher Hypervisor（無償版）
商用利用不可。
購入に先立ち評価する目的のみで使用可。

# Oracle VM VirtualBox
「Extension Pack」は使用不可。

[OracleVMVirtualBoxって商用利用でも無料なの？ - Yahoo!知恵袋]
[https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13227339453]https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13227339453)
スティーブ・ジョブズの生涯からキャリア形成を考える

こんばんわ。
キャリアアドバイザーの原田です！

今日は、スティーブ・ジョブズの生涯から、VUCAの時代と言われ
先の見えない現代のキャリア形成について、記載していきたいと思います。
# ”connecting the dots（点をつなぐ）”</b>

これは、2005年スタンフォード大学卒業式でのスピーチに出てくる言葉です。

スピーチの中でジョブズは、自身の生い立ちに触れ自身が
偶然現在の両親に育てられなければ、大学を中退していなかったこと。
中退をしていなければ、後にMacに採用される複数のフォントが存在しなかったこと。
それがなければ、Macに追従したWindoｗsでも複数のフォントが存在しなかったと語っています。

★一見マイナスに見える出来事が、後に大きな成果につながるというメッセージです。
同じく偶然きっかけから始めたことで成功する方も多くいます。

# □波乱万丈の経歴
1976年にアップル・コンピューターを創設すると
AppleⅡの大ヒットによりアップルは急成長。1984年「マッキントッシュ」を開発世界からも
注目される企業となりました。しかし、1985年には自らスカウトしてきたプロ経営者により、会社を追放。
その後、コンピューター会社のネクストを創業。

「ピクサー」となるルーカスフィルムを買収。
世界初のCGでのアニメ「トイ・ストーリー」で成功を収める。
アップルがジョブズの会社を買収し、アップルに復帰。
その後は、iPod、iPhoneなどのなどのヒット商品を次々と世に送りだしカムバックを果たしています。

★こちらでも、自ら創業した会社を自ら雇った人間に追放されるという
　憂き目にあっていますが、それをきっかけにピクサーにて大きな成功を収めています。

# □キャリアは思い通りにはいかないが、危機に対応できる方法がある
ジョブズのような劇的な人生を送る方はごく少数かと思いますがキャリアは平坦ではありません。

自分が望むようなキャリアを送れている期間もあれば、外的な要因によりそれができないことも
ありますが、最終的にそのときに習得した経験やスキルに助けられ大成するキャリアも多くあります。

その【意外な】チャンスを生かす心構えとして、ここではキャリア理論を紹介します。

# □計画的偶発性理論
こちらの理論は、目まぐるしく変化していくビジネス環境の中で、従来は、個人のキャリアは先が見通せるものであったが、現在は、自身のキャリアを先まで見通すことが難しく、
偶然の要素も味方につけキャリアアップに繋げていくというスタンスが重要視されるようになってしています。

＜行動指針＞
・好奇心
興味関心のある分野にとどまらず、普段から視野を広げるよう努めることが大切。

・持続性
失敗してもあきらめず向き合うこと。困難を避けたり苦手意識を
持ったりすると、その先にある可能性が閉ざされてしまうことがある。

・柔軟性
こだわりや理想にとらわれて、行動や思考を狭めないこと。
常にフレキシブルな姿勢で臨機応変な対応を心がけます。

・楽観性
失敗や困難もポジティブに捉えること。何が起きても良い方向に
行くと信じる態度は、自分自身をプラスの方向に運びます。

・冒険心
リスクを恐れず行動すること。不確実性の高い環境において
失敗はつきものです。ある程度のリスクは引き受ける心構えが大切です。

# □やりたいこと探しの迷路に入らない
【やりたいことが見つからない】というご相談をされる方が多くいらっしゃいますが
考えて選択するだけでは出会うことは難しいという事実があります。

まずは、好奇心をもって今ある可能性に向き合って、
極めてみることでそれが楽しくなる。
意外なやりがいが見つかることもありますので
【やりたいこと探す】ではなく動いてみることを
おすすめします！

# □まとめ
計画的偶発性理論の話しをすると、それではキャリアビジョンを描く意味が
ないのでは？と考える方もいるかと思いますが、自身のありたい姿や
仕事の目的を明確にし、そのうえでのこちらの理論を参考にしていただけると
より充実したキャリアを過ごすことができると考えています。
【超基礎編】Pythonで中学 数学の問題を自動作成する方法

Pythonで中学 数学の問題を**自動作成**するための基本を紹介します。

これを学ぶことで、自作の問題集を作成したり、テスト問題を瞬時に作成したりすることができるようになります。

## はじめに

Pythonで中学 数学の問題を「**解く**」ことと、問題を「**作成する**」ことは全く別のことです。

前者は問題の「**答えを得る**」ために必要なことで、後者は「**テスト問題を作る**」ために必要なことです。

今回は後者のテスト問題をPythonで自動作成するための「**基本**｝を紹介していきます。

## ランダムな数を作る

問題作成でまず必要になるのはランダムな数「**乱数**」を作ることです。これが使えるようになると、自分でいちいち数を考える必要がなくなります。

Pythonでランダムな数を生み出すためには標準モジュール「**rondom**」をインポートします。

標準ライブラリなので、別途インストールする必要はありません（※Pythonはインストールされている必要があります）。

```
import random

a=random.randint(0,9)

print(a)
#出力結果→ 2
```

random.randint()を使うと、任意の範囲の整数を自動で作成することができます。

今回の出力結果は「2」でしたが、次に出力するときには2以外の数字（0から9までの整数）が表示されます。

かっこ内の整数の値を変えて、いろいろな数を生成してみましょう。

## 数字・記号を文字に置き換える

問題作成をする上で最も重要なことは、「数字を文字に置き換える」ことです。

これをしないと、Pythonで自動で計算され、答えのみが出力されます。

```
import random

a=random.randint(0,9)
b=random.randint(0,9)

print(a+b)
#出力結果→6
```

問題を作る上で必要になるのは「a+b」もしくは「2+4」といった答えが出る前の状態です。

したがって、出力結果にそれらが出るようにコードを書く必要があります。

実際にコードを書いてみましょう。

```
import random

a=random.randint(0,9)
b=random.randint(0,9)

c="+"

print(str(a),c,str(b))

出力結果→ 5 + 1
```

先のコードと違うのは、まず変数cを作り、そこに文字列としての"+"を割り当てていることです。

また、ランダムに作った数を入れた変数a、変数bは **str()** の中に入れられています。

これは数を文字列に変えるために使用したものです。

つまり、問題を作成する上では、数字や記号を常に**文字列に変換して表記する**必要があるということです。


## 小数を作る

中学数学では整数ではなく、小数を扱う問題もよく出題されます。

randomで小数を作ってみましょう。

```
import random

a=random.random()  #（0.0以上1.0未満の浮動小数点数）

print(a)

#出力結果→0.06838515252079003
```

ここで困るのが小数点以下の数が多すぎるということです。

中学数学では小数第1位、第2位あたりの数を使うことが多いので、余計な数を表示させないように工夫する必要があります。


```
import random

a=random.uniform(0.1,0.9)

print(round(a, 1)) # 小数点第二位を四捨五入
print(round(a, 2)) # 小数点第三位を四捨五入
print(round(a, 3)) # 小数点第四位を四捨五入

#出力結果
#0.9
#0.86
#0.865
```

上のコードでは0.1から0.9の範囲の数を指定し、roundを使って四捨五入しています。

この方法で任意の小数を自由に作り、問題に組み込むことが可能になります。

```
import random

a=random.uniform(0.1,0.9)

b=random.uniform(0.1,0.9)

c="+"

print(round(a, 2),c,round(b, 2))

#出力結果→ 0.61 + 0.85
```


## 分数を作る

中学数学では整数や小数だけでなく、分数を扱った問題もよく出題されます。

Pythonで分数の問題を解く際には1/2のように表記しましたが、

テスト問題ではこのように表記するわけにはいきません。

そこでMarkdownを用いて表記します。

Markdownで分数を書くには、

\frac{1}{2} のように書き、$$で囲みます。

実際に書いてMarkdownで表示させると、


$$
\frac{1}{2} 
$$

のように分数がきれいに表示されます。

### PythonでMarkdown式分数を書くには？

数字の部分はPythonの変数で表すことができそうです。

ただし、このままPythonで書くわけにはいきません。

数字や記号、そしてfracの部分もそれぞれ文字列に変換する必要があります。

さっそくコードを書いてみましょう。

```
import random

a=random.randint(1,9)
b=random.randint(1,9)

c="\\frac"  #「\」を文字列に変換するには「\\」と書く
d="{"
e="}"
f="-"

print(c,d,a,e,d,b,e)

#出力結果
#\frac { 3 } { 5 }
```

このままMarkdown対応のエディタに貼り付けると、分数で表記されます。


$$
\frac{3}{5}
$$

\fracの前にマイナスを付けたすと、このように表示されます。
$$
-\frac { 3 } { 5 }
$$

## 最後に

今回は中学数学の問題を作成するための**基本**を紹介しました。

次回は実際に中学数学の単元に沿って問題を作成していきたいと思います。

## この記事の続き

この記事の続きはこちら。

https://qiita.com/akiba_burari/items/777dec85e9fcd59d1f49

https://qiita.com/akiba_burari/items/3948eef74dd9f9b100ba

## 関連記事


https://qiita.com/akiba_burari/items/55ddae0c065fdccdef16



https://qiita.com/akiba_burari/items/d185a2224c7bb87e5cdf



https://qiita.com/akiba_burari/items/954f832b408fef353aa3



https://qiita.com/akiba_burari/items/5bb4c083b30768a33aa1
【Jetpack Compose】List型のMutableLiveDataがViewに発火しない原因はこれだった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/59e03f96-cf52-3f7e-352f-79ecf8a5fef3.png)

しばしハマってしまったのですが、原因がわかったらそらそうだ！となったメモです。

# List型の要素が追加されたらViewを更新したい
MutableLiveDataにList型を入れて、要素が追加されたらViewを更新しようとするサンプルです。

```kotlin:kotlin
class SampleViewModel : ViewModel() {
    val items = MutableLiveData<ArrayList<String>>(ArrayList())
    var counter = 0

    init {
        add()
    }

    fun add() {
        counter++
        items.value?.add(counter.toString())
    }
}

@Composable
fun SampleView(viewModel: SampleViewModel) {
    val items = viewModel.items.observeAsState()

    Column {
        Button(onClick = {
            viewModel.add()
        }) {
            Text("add")
        }

        items.value?.forEach { item ->
            Text(item)
        }
    }
}

```

このコードで良さげと思ったのですが、、ボタンをタップしても反応しません...

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/5731020a-ea2d-24cb-9959-b44c722f0aac.png">

## 対処：その１
ググったらこういうのが出てきました。なんか良さげ。

```kotlin:kotlin
    items.postValue(items.value)
```

そうかと思いやってみたら・・・

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/5731020a-ea2d-24cb-9959-b44c722f0aac.png">

効きません。。

## 対処：その2
こういうのもヒットしました。

```kotlin:kotlin
    items.value = items.value
```

どうでしょうか・・・

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/5731020a-ea2d-24cb-9959-b44c722f0aac.png">

ダメです。。

## 解決方法
冷静になって見直してみると MutableLiveData に ArrayList が突っ込まれている・・・、kotlinではMutableListが定石ですよね！

```diff_kotlin:kotlin
-   val items = MutableLiveData<ArrayList<String>>(ArrayList())
+   val items = MutableLiveData<MutableList<String>>(mutableStateListOf())
```

やってみると・・・

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77444/9cb56e86-af99-b0b9-5ebc-4d8a698c8e20.png">

うまくいきました！！

よかった。
（こういうのコンパイラで教えて欲しい）
AWS認定クラウドプラクティショナー合格に向けて Day16

 # 前回の内容
[AWS認定クラウドプラクティショナー合格に向けて Day15](https://qiita.com/Ayako_0224/private/c583390b8c99df544c1a)

# DNSサーバー
Domain Name Systemの略
URLとIPアドレスの対応関係を管理し、変換する

# Route53
DNSレコードというIPアドレスとURLを紐づけた表を確認して処理する
ドメイン登録、DNSルーティング、ヘルスチェックを主に行うことができる
ポリシーによってルーティング設定を行う

1. ドメイン設定
2. ドメイン名と同じホストゾーンを自動生成
3. ホストゾーンにルーティング方法となるDNSレコードを作成
4. トラフィックルーティングを設定

## ホストゾーン
ドメインとそのサブドメインのトラフィックのルーティングをする方法についての情報を保持するコンテナ
### パブリックホストゾーン
インターネット上に公開されたDNSドメインレコードを管理するコンテナ

### プライベートホストゾーン
VPCに閉じたプライベートネットワーク内のDNSドメインのレコードを管理するコンテナ

## ルーティングポリシー
### シンプルルーティング
レコードセットで事前に設定された値に基づいてDNSクエリに応答

### 加重ルーティング
複数エンドポイント毎の重み設定によりDNSクエリに応答

### フェイルオーバールーティング
ヘルスチェックの結果に基づいて利用可能なリソースをDNSクエリに応答する

### 複数値回答ルーティング
ランダムに選ばれた最大8つの別々のレコードを使用してIPアドレスを設定して、複数の値を返答する

### レイテンシールーティング
リージョンの遅延によりDNSクエリに応答する

### 位置情報ルーティング
ユーザーのIPアドレスにより位置情報を特定して、地域ごとに異なるレコードを返す
ネットワーク構成に依存しない精度の高いレコードの区分けが可能

### 地理的近接性ルーティング
ユーザーとリソースの場所に基づいてトラフィックをルーティングする

To be continued...
技術記事執筆のススメ

# はじめに

[フューチャー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/future) の 15 日目です。

技術的な記事の執筆というと、文章を読んだ第三者への貢献が目的、というイメージがあるかもしれません。もちろんそのような側面もありますが、書いた本人にも多くの利点があると思っています。この記事では執筆者本人にどういった利点があるのか紹介し、記事執筆はいいぞ、ということをお伝えします。

# 利点

## 理解が深まる

理解を深める方法として、公式ドキュメントを読んだり、関連する書籍/専門誌を読んだり、コードを読んだり、などといったインプットが着目されがちです。しかしインプットと同時に、書いたり、話したりなどといったアウトプットも重要です。

たとえば『リサーチの技法[^1]』では書く目的として次の 3 つを挙げています。

[^1]: ウェイン・Ｃ・ブース、グレゴリー・Ｇ・コロンブ ジョセフ・Ｍ・ウィリアムズ、ジョセフ・ビズアップ、ウィリアム・Ｔ・フィッツジェラルド、川又 政治訳『リサーチの技法』ソシム、2018

* 覚えるため
* 理解するため
* 考えを検証するため

『理工系のためのよい文章の書き方[^2]』でも文章として書くことで、考えの問題点、思考の抜けに気づきやすくなる、とあります。

[^2]: 福地健太郎、園山隆輔『図解でわかる！理工系のためのよい文章の書き方 論文・レポートを自力で書けるようになる方法』翔泳社、2019

自分がよく知っている技術でも、改めて文章化してみると理解の抜け漏れを把握したり、知識の再整理ができるでしょう。また、記事執筆を通じて周辺の知識もインプットできます。また、第三者に説明するときにも役に立つでしょう。自分の理解をより深めるために、技術記事執筆はとてもおすすめです。

## 記憶の外部化ができる

時間が経つにつれ、過去の思考や理解した内容、勉強した知識は忘れてしまうものです。自分の書いた記事は思考の外部記憶として役に立ちます。過去自分がどういうことを思考していたのか、あるいはハマりどころや勘所は何だったのかなど、改めて知りたいときに自分の記事から学習できます。これは私だけでなくて、渋川さんや他の社内メンバーからも同じ意見を聞いたことがあります。

https://twitter.com/shibu_jp/status/1408774306100703241

また、文章化しなかった思考は消えていく、という意見もありました。

https://twitter.com/hirakurakei/status/1475013832036982784

日々、新しいことを学んでいくなかで、過去の記憶は脳内メモリから消え去ってしまうことがあります。外部記憶として技術記事を書いておくことでリロードが容易になります。

## フィードバックが得られる

一番最初に書いた「書くことで理解が深まる」とやや重複しますが、書くことで思考が自分以外の人に伝わり、フィードバックが得られやすくなります。

私は最近、業務で導入した新規技術に関する記事を会社の技術ブログに投稿しました[^3]。記事は同じチームのメンバーに事前にレビューいただき、いくつかの項目を追記しています。良かった点として記載している項目のいくつかは第一版ではありませんでした。

[^3]: [業務システム開発でsqlcを導入して良かった点とハマった点](https://future-architect.github.io/articles/20221128a/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89391/26ff56eb-1f29-83fe-4945-0b52b75c589a.png)
※実際にフィードバックいただいた内容の一部

文章という形で自分の思考を外部に共有することで、自分では気づいていない観点でフィードバックを貰えることがあります。

## 文章を書く練習ができる

文章は書きたいときに書こうとしても、普段から書いていない場合はなかなか上手くかけないものです。上手くなるためには量が必要です。記事執筆を通じて、文章を書く練習ができます。『言語化力[^4]』にも「言葉は、下手でもなんでもいいから、どんどんアウトプットしたほうがいい。とにかく、量があって初めて質が生まれるのだ。」とあります。量が質を作る、という意見は一般的によく知られており、直感的にも受け入れられるでしょう。

[^4]: 三浦崇宏『言語化力言葉にできれば人生は変わる』SB クリエイティブ、2020

なかなか書くきっかけが見つからない、という場合は、とりあえずアドベントカレンダーなどのイベントに参加してみてもよいでしょう。あるいは私が所属しているフューチャーの方々であれば[ブログ連載](https://future-architect.github.io/articles/20220117a/)に参加するのもありです。

## 社内外の方々に知ってもらえる

個人のブランディングに近い話です。社外もそうですが、社内のメンバーに何が詳しいか知ってもらえるでしょう。フューチャーだと所属している部署だけでも 3～400 人います。チームあるいはプロジェクトで一緒に仕事をしている場合を除いて、誰が何に詳しいか、なかなか分かりづらいものです。

Qiita や技術ブログを通じて普段からアウトプットしていると、プロジェクト外のメンバーから、この技術なら辻に聞いたら分かりそうかも、みたいに認知してもらえるきっかけになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89391/db9a86c6-4dbe-1597-14ed-531abf37da9c.png)

上のような感じで、私の記事を見つけて質問をくれるメンバーもいました。ありがたや。

# まとめ

記事執筆は書いた本人への利点がたくさんあるよ、おすすめだよ、という話を書きました。まだ書いたことがない方は、一度書いてみると新しい学びがあるかもしれません。
【Swift】RxSwiftのテストのハードルを下げる便利クラスを作る

## RxSwiftのテストは何かと面倒
`scheduler`や`disposeBag`、`obserever`など
テストしたい処理以外に書くべきことが多い。。

```swift
// ロジックは省略
func testIsTapEnabled() {
  let isTapEnabled = scheduler.createObserver(Bool.self) // これとか
  viewModel.output.isTapEnabled
    .drive(isTapEnabled) // これとか
    .disposed(by: disposeBag) // これとか
  scheduler.createColdObservable([.next(10, ()),
                                  .next(20, ()),
                                  .next(30, ())])
           .bind(to: viewModel.input.playButtonTapped)
           .disposed(by: disposeBag)
  scheduler.start() // これとか
  XCTAssertEqual(isTapEnabled.events, [
    .next(true),
    .next(false),
    .next(true),
    .next(false)
  ])
}
```

ObservableConvertibleTypeをぶち込むだけで、
ボイラーブレートを内部でやってくれるクラスが欲しい

## 便利クラス

```swift
import RxSwift
import RxTest

final class Stream<Element> {
    private let disposeBag = DisposeBag()
    private let observer: TestableObserver<Element>
    private let scheduler = TestScheduler(initialClock: 0)
    // ObservableConvertibleTypeなのでDriverでもObservableでも代入可
    // Driverを使用しないと決めている場合はObservableに書き換えるとよさそう
    init<O: ObservableConvertibleType>(_ observable: O) where Element == O.Element {
        observer = scheduler.createObserver(Element.self)
        observable
            .asObservable()
            .subscribe(observer)
            .disposed(by: disposeBag)
    }

    var events: [Event<Element>] {
        return observer.events.compactMap { $0.value }
    }
    var latestEvent: Event<Element>? {
        return observer.events.last.flatMap { $0.value }
    }
    var value: Element? {
        return event?.element
    }
}

```

これを使うと、最初に紹介したコードが次のように書けます。
```swift
let isTapEnabled = Stream(viewModel.output.isTapEnabled) // outputの監視を始める。
viewModel.input.playButtonTapped.onNext(())
viewModel.input.playButtonTapped.onNext(())
XCTAssertEqual(isTapEnabled.events, [
    .next(true),
    .next(false),
    .next(true)
])
```
schedulerをStreamのinitializerに入れれば、schedulerを意識したテストもできるようになります。
(省略して逆にイベント送信が冗長になってしまいました)
プログラミング

 
プログラムを始めたきっかけ
姉がプログラム授業に参加していたのもありパソコンに積極的に触れたいということで自分用のパソコンも買ってもらった。

プログラム授業をやって見て思ったこと
・最初は、簡単で楽しいな～ 2時間半授業があればいいのにな～ とか思っていましたが3章くらいになると「キッツ」と思いました。笑
・でも、プログラミング授業をやってやりがいがあるなと思たことは、for文などを使って繰り返しの文を作れるのだなと思った時はとっても楽にできるし、手間もかからないなと思ったのでめんどくさがりの私にはとってもぴったりの勉強でした。

プログラムは、いつまで続けるのか？＆意気込み！
自分で、何も見ないでプログラムを書くまで、続けたいと思う。
来年は、中学1年生なのでN中の人に越されないように頑張りたいと思います！

今やっていることは？
今は、下の下の下のpythonをやっております。
なので、今日はpythonでちょっとしたおみくじを2つ作ってみました！
下手であまり面白くないかもしれませんが、pythonがある方は、やってみてください！


import random
kuji = ["大吉 良いことがあるかもよ～", "中吉 今日も一日頑張ろう！", "小吉 そんな時もあるよ", "凶 残念"]
print(random.choice(kuji))

import random
kuji = ["大吉", "中吉", "小吉", "吉", "半吉", "末吉", "末小吉", "凶", "小凶", "半凶", "末凶", "大凶"]
print(random.choice(kuji))
Youtube から 年齢制限のある動画をダウンロードする

## Yutubeから動画をダウンロードするには

ローカルで手軽に行うには youtube-dl を使うのが最も早いです。

https://github.com/ytdl-org/youtube-dl

インストールは pip で行います

```
% pip install youtube_dl
```

## Youtube 動画のダウンロード

Pythonのコードを書くよりコマンドで行う方が早いです。

```
% youtube-dl "https://www.youtube.com/watch?v=XXXXXX"
```

## 年齢制限のある動画の場合

エラーメッセージが表示されてダウンロードが中断されます。

```
youtube_dl.utils.DownloadError: ERROR: Sign in to confirm your age
This video may be inappropriate for some users.
```

## 年齢制限のある動画をダウンロードする場合

コマンドでブラウザのクッキーを指定することで年齢制限を回避することができます。

https://github.com/ytdl-org/youtube-dl/blob/master/README.md#how-do-i-pass-cookies-to-youtube-dl

### ブラウザからクッキーを書き出す

ブラウザの開発ツールからコピーしてテキスト化も可能ですが、
FireFoxのアドオンを利用すればすぐにできます。

https://addons.mozilla.org/ja/firefox/addon/cookies-txt/

アドオンをインストール後、Youtubeを開いて課された年齢制限を超えた後で
ツールバーのアドオンのボタン　→ 現在のサイト　を選択するとクッキーが書き込まれたテキストを出力できます。
![スクリーンショット 2022-12-10 21.07.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/226f3fc5-801b-13f0-715e-6a9d24a27db4.png)

### クッキーを指定してコマンドを実行

--cookiesオプションでクッキーのテキストファイルを指定して youtube-dl を実行します。

```
% youtube-dl "https://www.youtube.com/watch?v=XXXXXX" --cookies cookies.txtへのパス
```

動画がダウンロードできることを確認してください。