OmniAICreator/Qiita-1.07M huggingface dataset:
資格試験と自己成長について

# はじめに
本記事はMDC Advent Calendar 2021の2日目の記事です。
前日の記事は、@methimo さんの[LinuC2を受けようと思ったのできっかけや勉強方法を書く](https://qiita.com/methimo/items/982ded8a3930c0374b50)、でした。
こちらに触発されて、資格試験についてぼんやりですが書いていきたいと思います。

# 資格試験との出会うまで

学生時代、私は優秀な人ではありませんでした。
一方で皆勤賞とか、何か追加でレポート出せば少し成績上がるとか、プラスアルファやればいいだけ系のものとかは積極的にやることで、周りの人に追いつこうとしていた記憶があります。
打算的ですが、何か秀でた能力や才能がないんだから仕方ないと自分に言い続けてました。
そんな中ですが学生時代に特に秀でてないにも関わらず、当時は大学院までいってメーカー系や研究職につく周りが多い中、学部卒で今の会社に入りました。手に職つけたかったのと、腕一本磨いていけば、会社渡り歩いて行けるかなと思っていたところがあります。

# 学生時代
そんな中の就職活動している中でIT系企業であれば、情報処理試験を受けて、基本情報ぐらいもっておいたほうが良いという就活サイトや先輩社員の話を受けて、学部4年の春に初めて情報処理試験の基本情報を受験しました。結果は惨敗でした。
基本情報は春と秋どちらも開催されていたので、その年の秋にも受けました。結果は午後少し点数足らず、不合格。向いてないな、とも思いました。

# 新卒入社直後
2回の不合格を受けてですが凹んではいましたが、新卒研修時期は残業もなく時間もあったので同期との交流は大事にしつつも、春の情報処理試験として３度目の受験をしました。
そこでなんとか合格、素直に嬉しかったですね。自己肯定感も一時的にアップしていたと思います。
その後も資格とって勉強していく習慣をなんとかつけて、応用情報（当時はソフトウェア開発技術者）、DBスペ、情報セキュリティ、アーキ、ととっていきました。NWスペは何度受験しても取れませんでした。未だに持ってないです。ので持っている人は尊敬します。

# 試験に落ちるということ
情報処理のサイトで合格、不合格が表示される瞬間、ベンダー資格では最後にポチッと結果送信した瞬間は未だにドキドキします。
不合格だった場合、すごく落ち込んで帰ります。
これまで過去最高回数落ちた試験は、[XMLマスター：プロフェッショナル（アプリケーション開発）試験](https://www.xmlmaster.org/range.html)でした。アプリケーション開発とあるようにJavaでのXMLの扱い、具体的にはDOMとSAXというJavaの標準APIがあるのですがその仕様の確認とか、当時システム間連携通信で全盛とされていたSOAP電文やその仕様書であるWSDLなどとても広い範囲の試験でした。
かつ40問試験で8割以上正答で合格という基準だったので、あと１問で合格だったのに、、というのを２、３回繰り返した記憶があります。
最後には合格できて、その後仕事でも結構活用できたので取ったのはよかったなと思います。

# 仕事への活用
資格を取ってもそのまま仕事に応用できないよね、と思う方も多いかもしれません。でもそこは違っていて、直接応用ではなくても後で知識や必要スキルとしてつながったり、資格試験勉強時にみていたリファレンスサイトなどを見にいく習慣がつくなど動きの面でも変わってくると思います。
HTML5のL1、L2も持っているのですがL2の試験勉強時にお世話になった、[CanIuse](https://caniuse.com/)というサイトはちょうど先日もこの記法、このブラウザで対応していたかな、、、？と調べるときに使いました。役立ってます！

# 最近の考え方
最近は、コミュニティ活動、OSS活動、無料系含めたEラーニングの発達、普及などもあって、技術力をつける、証明するのは資格一辺倒ではなくなってきているとは思います。
一方、自身のサービスやスキル証明のために、AWSやSalesForce、Azureなど資格として公開してスキルを身につける１つの方法として活用、ユーザーコミュニティでも盛り上がって、知らない人同士でも切磋琢磨できるように、みたいな動きも活発で良いですよね。

# まとめ
なんとなく始めた資格取得ですが、今も自身のスキルを習得する手段の一つであることは変わらないと思います。
いろいろ多様化している中ですが、目的と作戦練りながら時には資格試験取得も目指してみてはいかがでしょうか？
定期的に何かにチャレンジしましょう。
残るもの、第三者から認められるものは、単純にいいですよ。
テスト55

```vb

'Excelファイル

Sub VBS_exe()
'Wordファイル起動時のマクロ無効化対策といろいろ
Dim vbsFile As String
Dim wdApp As Variant
Dim wd As Variant
Dim ws As Variant
Dim str As String

str = "C:\Users\User\Desktop\VBA練習\変換用\変換用4.docm"
'ファイルパス+VBSへの引数
vbsFile = "C:\Users\User\Desktop\VBA練習\VBSファイル\W_Open.vbs" _
& " " & 1 _
& " " & str

Set ws = CreateObject("WScript.Shell")

'VBSファイルを同期実行
ws.Run vbsFile, , True

Set wdApp = GetObject(, "word.application")
Set wd = GetObject(str)

MsgBox wd.Name

Call wdApp.Run("test", "AAA")
'
Set ws = Nothing

End Sub

'--------------------------------------------

'　　　 l＾ヽ'"'"~/＾i、..、 ..、、
'　　ヽ゛　　　　　　　 ∧__∧｀｀;: 　　
'　　ミ　　 ＾　ω　＾ （　＾ω＾）＜メモです♪
'　　ッ　　　　　　 _ （つ|⌒|⌒|..;ミ
'　(´彡,.　 　　 （,,_, ヽ(~^),(^~).ノ
'　　　　 "'"'゛''""''''゛""´

'VBSファイル(W_Open.vbs)

Dim str
Dim wd

MsgBox Wscript.Arguments(0)

Set wd = CreateObject("Word.Application")
wd.Visible = True

wd.Documents.Open Wscript.Arguments(1)

'--------------------------------------------

'Wordファイル

Sub test(ByVal str As String)

MsgBox str

End Sub
OpsRamp 自動検知設定/監視設定について

#概要
OpsRampを活用して、簡単にクラウドリソースの検知/監視する方法を説明します。
今回はAWS環境のリソースを対象にします。

#クラウドリソースの検知について
クライアント詳細画面から移動できるOnboarding Widzardに移動します。
今回はAWSですが、画像の通り、検知で取り込めるリソースの種類は様々です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342082/1e081e06-a195-436e-bb84-fd12ad887757.png" width=70%>

AWSを選択し、アカウント情報、取得したいサービス、検知スケジュールを設定します。
わかりやすい設定画面のため、特につまずく要素はありません。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342082/54595129-8983-6050-6f29-65e4ad7b354f.png" width=70%>

終わりましたら、「Save」ボタンを押しましょう。

:::note info
以上で検知設定は終わりです
:::

、、、本当か若干怪しいですよね？
確認のため画面を移動しましょう。

#検知状況の確認
メニューの 「Resource」　をクリックして下さい。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342082/cc567983-bb54-b76a-f2c4-5c1e6a652fa5.png" width=25%>

このようにアカウントごとに一覧で表示されます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342082/4fd4a8ee-5677-974a-a40f-de389ea9a610.png" width=80%>

左のツリーメニューの「AWS」を階層下がっていきますと個々のインスタンス/サービスが
表示されます。「Metric」の部分でどのような情報が取得できているか確認可能です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342082/5c29d9f2-7352-ea65-f719-4d0660536d70.png" width=100%>

#監視
メニューから下記の通り移動します。
Setup＞Monitoring＞ALERT DEFINITIONS

主要な必須項目のみ説明します。

- Scope/Client
任意のPartner/Client名を指定します。

- Applicable on
このルールを適用する条件を指定します。
今後新規で検知されたものについてはこの条件にマッチした場合
自動で監視が開始されます。

- Select Metric
こちらは先程「Resource」の画面で見た「Metric」
この中から取得できているものを選んで下さい。
今回は「aws_ec2_NetworkIn」にしてみました。
※awsと入力すると候補がドロップダウンで出てくるので便利です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342082/1982228f-e8e6-b0df-0657-76f39c586ae9.png" width=80%>

- しきい値設定
今回は画像の様に設定してみました。
Repeat Countはアラートを出すまでの繰り返し回数です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342082/aec4cd15-4021-7133-44c1-d1495383c66f.png" width=90%>


#アラート
しきい値を超えるとアラートが出ます。
メニュー
Command Center＞Alertsから確認出来ます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342082/6d46e965-5a65-7f01-ae60-69ed6cf8266f.png" width=90%>


以上です。
UMLとは

## 勉強前イメージ

なんかの図ってイメージだけど、中身は知らない・・・

## 調査

### UML とは

Unified Modeling Language の略で、統一モデリング言語と呼ばれています。
オブジェクト指向の開発の際に、データの構造や処理の流れをわかりやすく図にしたものになります。
設計段階で用いられる標準的な記法のことを言います。

UMLを使用することで、新しくシステムを開発したり既存システムに機能追加を行う際に
システムの部分を図形を使ってひわかりやすく表現することで、システムの概要を把握しやすくなります。
記述ルールが決まっているので、設計書に比べて視覚的に見やすく保守性の向上に繋がります。

UMLは1996年にRational Software社が発表したもので、
その後の改訂はOMGが行うようになり、UML1.4、UML 2.4が国際標準となっています。

### UMLの種類

UMLには大きく以下のように2種類に分けられます。

- 構造図 : システムの構造を表す
- 振る舞い図 : 動作や変化を表す

#### 構造図

- クラス図 : 各クラスの構造・クラス間での関係
- オブジェクト図 : オブジェクトの関係性
- パッケージ図 : クラスなどのグループの関係
- コンポーネント図 : 複数クラスを1コンポーネントとし、コンポーネントの構成や関係性
- 複合構成図 : クラスやコンポーネントの内部構造をあらわした図
- 配置図 : システムの物理的な構成

#### 振る舞い図

- ユースケース図 : 利用者視点でのシステムの利用方法
- アクティビティ図 : システムの一連の流れや状態遷移図
- 状態マシン図 : イベントによるオブジェクトの遷移図
- シーケンス図 : 時系列でオブジェクト間の処理の流れの図
- コミュニケーション図 : クラス・オブジェクトの関連とやり取りのメッセージ図
- 相互作業概要図 : ユースケース図やシーケンス図を構成要素としてより大枠の流れを表す図
- タイミング図 : 時系列でのクラスやオブジェクトの遷移図

## 勉強後イメージ

プログラム書く際の遷移図のようなもの？
結構種類がいろいろあってびっくりした。

## 参考

- [UMLとは｜UMLの種類を分かりやすく解説](https://medium-company.com/uml/)
- [UMLとは？書き方とクラス図・シーケンス図などの9つの図を解説](https://cacoo.com/ja/blog/what-is-uml/)
PyQt5のチュートリアルを動かす ⑤ レイアウト管理

# はじめに

前回は,QtのSignalとSlotを動作させてみました。

https://qiita.com/hoshianaaa/items/5324b37b0fd085f47403

今回は`layout`クラスについての導入です。

# 内容

qtのwidgetは`setGeometry(xpos, ypos, width, height)`というメソッドをもちこれによってpixel単位の絶対座標位置を設定します。

以下の例では300x200ピクセルのウィンドウが(10,10)の位置に表示されます。

```layout.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
   app = QApplication(sys.argv)
   w = QWidget()
	
   b = QPushButton(w)
   b.setText("Hello World!")
   b.move(50,20)
	
   w.setGeometry(10,10,300,200)
   w.setWindowTitle("PyQt")
   w.show()
   sys.exit(app.exec_())
	
if __name__ == '__main__':
   window()
```

`PushButton`Widgetはウィンドウの左から50ピクセル,上から20ピクセルの位置に設置されます。

しかしwindowのサイズ変更に対してボタンのサイズが変わったりしません。

![Screenshot from 2021-12-01 20-03-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/5e4b33f9-c223-be41-aafd-996b7c36b98e.png)


![Screenshot from 2021-12-01 20-03-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/f8a87e49-9db5-081b-bc11-37c5c4ab14af.png)

そういった場合に`layout`クラスを使用すると`Wiget`のサイズが動的に変化したり,移動したりするようになります。

そのクラスについてまとめると以下のようになります。

1.`QBoxLayout`:Widgetを垂直 or 水平に並べるクラス.
(※派生クラス→`QVBoxLayout`:垂直配置,`QHBoxLayout`:水平配置)
2.`QGridLayout`:行と列に配置されたグリッドセルのは位置ができる.`addWidget()`メソッドを持っていて行数、列数を指定して任意のwidgetを追加可.
3.`QFormLayout`:??

# さいごに

layoutクラス内部にwidgetを配置すると,widgetが動的に変化してくれるようです。
windowから溢れたときに下に移動したりといった動きをしてくれるのでしょうか??
今後使っていければと思います。

# 参考

https://www.tutorialspoint.com/pyqt5/pyqt5_layout_management.htm
paizaの求人情報から年収予測モデルを構築する方法

#どのようなスキルセットや求人の条件が高収入につながるのか？
　ITエンジニアの転職サイトにはいろいろなものがあると思いますが、そのうちの一つに<a href="https://paiza.jp/career/mypage">Paiza</a>があります。Paizaにはスキルチェック機能があり、気軽にオンラインジャッジを使って問題を解くことで自分のコーディングスキル(の一部)について研鑽を積むことができたり、学習コンテンツを活用することでいろいろな技術への入門ができたりと多彩な機能を備えています。(Paizaマジ感謝!)
今回はPaizaに掲載されている求人情報をクローリング・スクレイピングして募集内容の要素(勤務地、開発言語、経歴など)と提示年収がどのような関係にあるのかについての予測モデルを機械学習によって作成することを目的としています。

##クローリング・スクレイピングによる情報収集
今回の取り組みで求人ページから取得する要素は、

+ 求人ページのurl
+ 企業名
+ 求人ポスト
+ 年収
+ 勤務地
+ 募集にあたっての必須要件
+ 開発言語とフレームワーク
+ クラウドプラットフォーム
+ データベース
+ 通過ランク

です。

クローリング・スクレイピングは2段階で行っていて、後の機械学習パートにおいて教師データとして使用する上記の要素をone-hotエンコーディングで取得するためにそれぞれの要素にはどのようなものがあるのかの一覧を第一段階で取得し、第二段階で個々の求人がどのような要素を持っているかを取得します。
第一段階のクローリングは<a href="https://github.com/aichi1/crawlPaiza/blob/main/paizaSkillsAndCondition.py">このコード</a>を使って行い、
第二段階のスクレイピングは<a href="https://github.com/aichi1/crawlPaiza/blob/main/paizaCrawlAndGeneratePaanda.py">このコード</a>を使って行いました。第一段階のクローリングではlxmlとselector及び正規表現を駆使して上記それぞれの要素がとりうる値のリストを作成し、第二段階のスクレイピングではそれぞれの求人により取得したデータをPandasのデータフレーム形式としてまとめてCSVに保存することとしました。
年収はレンジで「400万～800万円」のように提示されていることもあれば、「400万円～」のように提示されていることもあるので、前者の場合は間をとって600万円、後者の場合は下限の値を代表値400万円としてラベルを作成することとしました。
そうやって得られたデータが<a href="https://github.com/aichi1/crawlPaiza/blob/main/paizaSkillSetAndSalary.csv">こちら</a>です。(2021/12/1時点)
##収集データによる学習
後は収集したデータをPandasのデータフレームとしてgoogle colab上で学習し、年収予測モデルを作成します。
サンプルコードは<a href="https://github.com/aichi1/crawlPaiza/blob/main/predictSalaryWithNNAndDetermine.ipynb">こちら</a>です。
データがそれほど多くないのでほんの数秒で学習が終わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203415/2523f7a5-fd04-6005-4f6e-3e9e839ef049.png)
上記が年収のヒストグラムです。皆さんたくさんお金をもらっていてうらやましい限りです。
学習の進行状況的に20エポックで十分そうだったので、20エポックで打ち切りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203415/17201e1b-7582-506a-3610-414cb6380a99.png)
最終的に100万円程度の誤差が残っています。
このモデルを使って、下記の要素についてパラメータスタディを行いました。

+ 勤務地
+ 通過ランク
+ 開発言語とフレームワーク
+ クラウドプラットフォーム
+ データベース
+ 必須要件

どこにも住んでいない、通過ランクE、なんの開発経験もない人について予測を行うと年収は100.5156万円と予測されました。
これに対して通過ランクを上げていくと
<table>
<tr><th>S</th><th>506.27173</th></tr>
<tr><th>A</th><th>425.1205</th></tr>
<tr><th>B</th><th>343.9692</th><tr>
<tr><th>C</th><th>262.81808</th><tr>
<tr><th>D</th><th>181.66684</th><tr>
<tr><th>E</th><th>100.5156</th><tr>
</table>
となるそうです。絶対値の確からしさはわかりませんが傾向としては直観通りかと思います。
このようなことを上記のパラメータに対して行ったところインパクトの大きい要素順に
通過ランク > 必須条件 > 勤務地 > 開発言語・フレームワーク 、データベース、クラウドプラットフォーム
という感じでした。

参考までに、PaizaランクがSで勤務地が東京で何らかの開発経験が1年 Python3,JavaScript, Vue.js,Django,AWSの求人の場合の年収予測を行うと、701.84344万円となります。(いいな！)

#最後に
クローリング・スクレイピングは対象のサービスに対して負荷をかける恐れがありますので、事前にrobots.txtを確認したりしてご迷惑をかけないように行ってください。
アドベントカレンダー　始まるよ

# はじめに
<!-- 発端や概要を記載 -->
日々業務として、また趣味としてTwitterを眺めていると、12月は「アドベントカレンダー」なるものがよく流れてくる。
クリスマスまでのカウントダウン的なものということで、やってみる。

　のるしかない、このビックウェーブに。
# 目次
<!-- タイトルとアンカー名を編集 -->
1. [アドベントカレンダーとは](#Chapter1)
1. [開設すっぞ](#Chapter2)
1. [まずは記事を用意](#Chapter3)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# Qiitaアドベントカレンダーとは
アドベントカレンダーとは？
→”Qiita Advent Calendarとは、クリスマスまでの日数をカウントダウンするアドベントカレンダーの慣習にもとづいて毎年12月1日から25日までの期間限定で開催される記事投稿イベントです。

毎年、クリスマスのQiitaを盛り上げる一大イベントとなっております。興味のあるトピックのカレンダーに参加し、1年の締めくくりを最高に盛り上げていきましょう🎉”
https://qiita.com/advent-calendar/2021
とのことで、まあとにかくクリスマスまで毎日記事投稿しよう！

というものなのだ！

<a id="#Chapter2"></a>
# 開設すっぞ！
てわけで始めてみたので説明すっぞ！

<a id="#Chapter3"></a>
# まずは記事を用意。
Qiitaの記事でも、他のサイトでもOK!
ちなみに私の1記事目は今読んでもらっているコレです。

<a id="#Chapter4"></a>
# カレンダー開設だ！
記事の用意ができたら、
https://qiita.com/advent-calendar/2021
にアクセス！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295743/59eda8e7-b242-8ed9-8d77-c024b653c015.png)

下の方にある、「カレンダーを作る」
から作成画面にGO!

<a id="#Chapter5"></a>
# 名前をつけよう　詳細を埋めよう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295743/e0bac2f5-8904-aff2-aba9-0a6e4b91a84b.png)
詳細の設定画面に飛んだら、名前、詳細を埋めます。
ここで、「いぐおアドベントカレンダー」と名前を付けてますが、ちょっと後悔します。
__ちょっと後悔します。__
※![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295743/041f052d-fb5c-1656-d870-6fc5c437c89f.png)
周りがとっても真面目な名前を付けているからです。（まあいいいけど）

さて名前、詳細を埋めたら「カレンダーを作る」を押します。
<a id="#Chapter6"></a>
# 記事を登録して完了！　簡単だ！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295743/bf385932-a24d-fd2a-de87-0d05f9caaa16.png)

作成が終わると、この画面です。
あとは、各日付のプラスボタンを押して、タイトルと記事URLを貼っておきましょう！

__以上！！__

クリスマスまで楽しんでいきましょう！！
<a id="#reference"></a>
# 参考文献
- https://qiita.com/advent-calendar/2021
PyQt5のチュートリアルを動かす ④ Signals & Slots

前回は`Qt Designer`の使い方をご紹介しました。

https://qiita.com/hoshianaaa/items/52f653d834ee1e5c9402

今回はシグナルとスロットについてです。

# Qt Designerを使ったSignal/Slotの記述

1.まず,`Qt Designer`を開き`Input Widgets`の`Line Edit`と`Buttons`の`Push Button`を配置します。

![Screenshot from 2021-12-01 19-06-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/8234f39b-dd4e-76c8-bc49-e6c5363db2fc.png)

2.`Edit`>`Edit Signals/Slots`を選択し,`PushButton`から`LineEdit`を結ぶ

![Screenshot from 2021-12-01 19-06-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/d172059e-3634-77a2-3090-801f07f6d694.png)

3.それぞれの機能を選択

今回はボタンを押したら,ラベルの文字が消える動作をさせます。
この場合,pushButtonは`clicked()`を,`lineEdit`は`clear()`を選択。

4.`.ui`ファイルを保存し,pythonコードに変換します。

```
pyuic5 -x signalslot.ui -o signalslot.py
```

生成されたコードには以下の用にsignalとslotの記述がされます。

```
self.pushButton.clicked.connect(self.lineEdit.clear)
```

![Screenshot from 2021-12-01 19-06-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/329ec5bf-9615-8920-956e-719ecffcc78e.png)

# プログラムで書くと?

デザイナーを使う代わりに直接記述する場合以下のように記載します。

```
widget.signal.connect(slot_function)
```

例えばボタンwidgetにシグナルを設定する場合はこのようになります。

```
button.clicked.connect(slot_function)
```

widgetが持っているシグナル要素?にconnectメソッドでよびだす関数を定義するようです。

signal/slotを使って,ボタンが押されたら,プリントするサンプルコードは以下のようになります。

```python:buttons.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
   app = QApplication(sys.argv)
   win = QDialog()
   b1 = QPushButton(win)
   b1.setText("Button1")
   b1.move(50,20)
   b1.clicked.connect(b1_clicked)
   
   b2 = QPushButton(win)
   b2.setText("Button2")
   b2.move(50,50)
   b2.clicked.connect(b2_clicked)
   
   win.setGeometry(100,100,200,100)

   win.setWindowTitle("PyQt5")
   win.show()
   sys.exit(app.exec_())

def b1_clicked():
   print ("Button 1 clicked")

def b2_clicked():
   print ("Button 2 clicked")

if __name__ == '__main__':
   window()
```

実行結果

![Screenshot from 2021-12-01 19-26-37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/70109b7f-0971-6805-83b2-8d91a29d5439.png)

# 最後に

部品間でsignal/slotを設定する場合はDesignerを使用したほうが簡単そうです。
slotを自分の好きな内容にする場合も空のsignal関数を設定できれば楽そうですが,Designerにあるのでしょうか?
今後そういった部分も知っていければなと思います。

# 参考

https://www.tutorialspoint.com/pyqt5/pyqt5_signals_and_slots.htm
【Swift】PHPhotoLibraryでフォトライブラリを実装する方法

#実装コード
iOS 14から```PHPhotoLibrary.authorizationStatus()```の引数に```.readWrite```か```.addonly```の指定が必要になりました。
そこで、フォトライブラリの開き方を備忘録としてまとめました。
実装した```albumAction```メソッドを使用するとフォトライブラリが開けます。

```info.plist```に```Privacy – Photo Library Usage Description```の追加も忘れないように！



```Swift
import Photos

private func albumAction() {
    // 端末にアルバムがあるかを確認
    if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary) {
        if #available(iOS 14, *) {
            // iOS14以降の設定
            let authorizationStatus = PHPhotoLibrary.authorizationStatus(for: .readWrite)
            self.albumCommonAction(authorizationStatus)
        } else {
            // iOS14より前の設定
            let authorizationStatus = PHPhotoLibrary.authorizationStatus()            
            self.albumCommonAction(authorizationStatus)
        }
    }
}
    
private func albumCommonAction(_ authorizationStatus: PHAuthorizationStatus) {
    // フォトライブラリを使う準備
    let photoLibraryPicker = UIImagePickerController()
    photoLibraryPicker.sourceType = .photoLibrary
    photoLibraryPicker.delegate = self
        
    switch authorizationStatus {
    case .notDetermined:
        // 初回起動時アルバムアクセス権限確認
        PHPhotoLibrary.requestAuthorization { status in
            switch status {
                case .authorized:
                    // アクセスを許可するとカメラロールが出てくる
                    DispatchQueue.main.async {
                        self.present(photoLibraryPicker, animated: true)
                    }
                default:
                    break
            }
        }
    case .denied:
        // アクセス権限がないとき
        let alert = UIAlertController(title: "", message: "写真へのアクセスを許可してください", preferredStyle: .alert)
        let settingsAction = UIAlertAction(title: "設定", style: .default, handler: { (_) -> Void in
            guard let settingsURL = URL(string: UIApplication.openSettingsURLString ) else {
                return
            }
            UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil)
         })
        let closeAction: UIAlertAction = UIAlertAction(title: "キャンセル", style: .cancel, handler: nil)
        alert.addAction(settingsAction)
        alert.addAction(closeAction)
        self.present(alert, animated: true, completion: nil)
    case .authorized, .restricted, .limited:
        // アクセス権限があるとき
        self.present(photoLibraryPicker, animated: true)
    @unknown default:
        break
    }
}
```





#Limited Photos Libraryの利用
iOS 14からはLimited Photos Libraryが使えるようになり、ユーザが選択した写真のみしかアプリからアクセスできない状態を作ることができます。
（「写真を選択...」の項目がiOS14から追加）

![ogp.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933058/dbddaf98-f76a-0a41-a07b-651bb9ceeaeb.jpeg)

ただ、ここでアクセスを許可した写真を一覧で開けるようなものがOS標準でなさそう...
現時点では、自前で実装するかライブラリを使うかして実装しないといけない
[MosaiqueAssetsPicker](https://github.com/eure/AssetsPicker)

#参考
[WWDC2020での許諾周りのアップデートまとめ](https://qiita.com/akatsuki174/items/cc59203c2f3b1fe83573)
Informatica 製品のトラブルシュートで収集する情報リンクまとめ

この記事は [インフォマティカ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/informatica) Day 11 の記事として書かれています。

# はじめに
インフォマティカは製品に関する様々な情報を [Informatica Network](https://network.informatica.com) の Knowledge Base (KB) で公開しています。多くは英語となりますが、日本語のナレッジも徐々に追加されています。
今回は日本語独自のナレッジとして作成された、問題発生時にどのような情報を取得すべきかを各製品ごとにまとめたものを紹介します。

# 問題発生時に収集する情報まとめ
####Informatica Intelligent Cloud Services (IICS)
* [HOW TO: Informatica Intelligent Cloud Services(IICS) に関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/623880?language=en_US)

#### Data Engineering
* Enterprise Data Catalog (EDC)
[HOW TO: EDC に関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/621450?language=en_US)

* Data Engineering Integration (DEI)
[HOW TO: DEI に関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/625498?language=en_US)

* Enterprise Data Preparation (EDP)
[HOW TO: EDP に関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/624038?language=en_US)

#### Data Integration
* PowerCenter
[HOW TO: PowerCenterに関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/579644?language=en_US)

* PowerExchange
[HOW TO: PowerExchangeに関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/623411?language=en_US)

* Data Integration Hub (DIH)
[HOW TO: DIH に関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/621152?language=en_US)

#### Data Quality / Data as a Service
* Data Quality (DQ)
[HOW TO: Data Qualityに関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/616984?language=en_US)

* Address Verification (Address Doctor)
[Address Verification(Address Doctor)に関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/612537?language=en_US)

#### Master Data Management
* Multidomain MDM (MDM)  
[HOW TO: MDM に関するお問い合わせの前に必要な情報を収集する](https://knowledge.informatica.com/s/article/620598?language=en_US)

# おわりに
今回紹介した以外にも、様々なナレッジが日本語で提供されています。
検索キーワードで「kbjapanese」と指定することで日本語コンテンツを対象にした検索が可能です。

![kbjapanese.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335778/1b511e22-83a8-bf7f-ef9c-ce89bad3c35f.png)

Knowledge Base の日本語での検索をぜひ試してみてください。

# 参考情報
* [Informatica Network - Japan User Group - 日本語KBの探し方](https://network.informatica.com/thread/94516)
* [Informatica Network - Japan User Group - 製品ごとの日本語KBへのリンク](https://network.informatica.com/message/299012#299012)
CORS設定

#全体像
サーバーとフロントの両方で設定を行う
開発環境では

```
  // if (process.env.NODE_ENV === 'production') {
```
とコメントアウトする

#フロント
modules

```nuxt.config.js
  modules: [
    '@nuxtjs/axios',
　　　　　　　　// 追加
    '@nuxtjs/proxy',
  ],

  axios: {
　　　　　　　　//追加
    proxy: true,
    // baseURL: 'http://localhost:3000/display/get-info-commitment'
  },

  proxy: {
    '/display/': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        secure: false
    }
  },
```

#サーバー

```

```
SixtyFPSを試してみる - 導入編

[This Week in Rust 418](https://this-week-in-rust.org/blog/2021/11/24/this-week-in-rust-418/)で[SixtyFPS](https://sixtyfps.io/)というGUI用crateがあることを知ったので、試してみることにしました。

## SixtyFPSの特徴
* （サイトに書かれていることを信じるとすると）軽量、いろんなプラットフォーム向けにネイティブアプリが作れる
* Rust、C++、NodeJS向けにライブラリが提供されている
* ライセンス
    * 無料で使うにはGPLv3
    * 製品のアンバサダーとして活動するなら無料（これはクローズドソースにできる？アンバサダーとして活動するならソースも見せた方がいいような）
    * 有料の商業版

## 環境等
Rust 1.56.1 stable
MacOSX 11.6 (Intel Mac)
SixtyFPS 0.1.5

## 導入

```shell-session
$ cargo new sixtyfps-first
$ cd sixtyfps-first
```

とりあえずHello worldを動かす

```toml:Cargo.toml
[package]
name = "sixtyfps-first"
version = "0.1.0"
edition = "2021"

[dependencies]
sixtyfps = "0.1.5"
```

```rust:src/main.rs
sixtyfps::sixtyfps!{
    HelloWorld := Window {
        Text {
            text: "hello world";
            color: green;
        }
    }
}

fn main() {
    HelloWorld::new().run();
}
```

```shell-session
$ cargo run
```

![sixtyfps_first.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1775/681e9b24-24d3-5b38-996f-24923b497370.png)

無事GUIアプリケーション起動までできました。
今日はここまで。
【UX】そのUXは、迷信だった！？もしかしたら覚え間違えてるかもしれないUX知識。

## はじめに
[Qiita Advent Calendar 2021](https://qiita.com/advent-calendar/2021/qiita)の3日目は、
[2日目](https://qiita.com/degudegu2510/private/9682968a045b168f89c2)に引き続き、Qiita 株式会社 プロダクト開発G デザインTMの出口（@degudegu2510）が担当します！
業務では、[Qiita](https://qiita.com/)、[Qiita Team](https://teams.qiita.com/) 、[Qiita Jobs](https://jobs.qiita.com/)のUI/UX、フロントエンド、各イベント等のクリエイティブを担当しています。

ぜひ[Qiita Advent Calendar 2021](https://qiita.com/advent-calendar/2021/qiita) 2日目の記事もご覧ください。

https://qiita.com/degudegu2510/private/9682968a045b168f89c2


この記事では、UXデザインで勘違いされがちなトピックスにまとめた[UX MYTHS](https://uxmyths.com/)を
翻訳して、まとめた記事です。

+ UXについて、あまり詳しく知らない。
+ 最新のUXの知識について知りたい。

という人におすすめです！

ぜひ、原文の方も一緒にご覧ください。
この記事では、「流石にこんなこと思っている人いないよな...」というトピックは翻訳していません。
今回取り上げなかったトピックスについて知りたい方は、原文の方をご覧ください。

https://uxmyths.com/

## UXの神話

### ① 人はWebサイトをちゃんと読んでいる!?
人は本当に興味のあるコンテンツの場合のみ1語一句丁寧に読み上げます。
通常の場合は、強調されたワードや見出し、短い段落をざっと読んでいます。
そのため、それ以外の**関係ない情報は全部飛ばし読みしている**というわけです。




### ② すべてのページに3回のクリック以内にアクセスできないといけない!?
数年前のユーザビリティテストでは、3クリック・2クリックで目的の情報がない場合ユーザーが離れてしまうい、満足度も高くならないと信じられてきました。しかし、実際はクリックの回数が少ないことがユーザーを喜ばせたりするわけではないということなのです。

特に重要なのは、**ナビゲーションのわかりやすさ**と**情報が絶えることがないという予感があること**です。


### ③ アクセシビリティはお金がかかる!?
サイトのアクセシビリティを改善したい場合、新たな機能を追加したり、新たにコンテンツを複製する必要はありません。
重要なのは、デザインする際に、**ユーザーによってはアクセス可能なデバイスが限られていること**や**見たり読んだりする能力に違いがあること**をしっかりと理解することです。

### ④ ストックフォトはUXを向上させる!?
ストックフォトやその他の装飾的なグラフィック要素がWebサイトに付加価値を与えることはありません。
多くの場合、**UXを向上させるよりも害になります。**

このような画像は、Webサイトのトピックとは関係がなく、有用な情報を持っていないので、
ユーザーはイライラすることさえあります。

### ⑤ デザインはオリジナルでなければいけない!?
多くのデザイナーは、新しいデザインをするとき、既存のUIをそのまま使うよりも、全てを1から作り直したいと思う人が多いと思うます。

しかし、**デザインのセオリーは、既に導入されてテストが済んでおり、うまく機能しているものである**ことを覚えておく必要があります。ユーザーがよく知っているデザインなので、説明もマニュアルも必要ありません。

ユーザーが使いやすさを求めることを考えれば、デザインのセオリーは結局はメリットを与えるものです。 

### ⑥ Webサイトを定期的にデザインし直す必要がある!?
「Webサイトのデザイン変更」=「コンバージョンと新規顧客が増えることを期待して、サイトの見た目をがらりと変えること」だと捉える人は多いと思います。しかし、**デザイン変更のフィードバックを見てみると逆効果**で、新デザインが元のものより明らかに優れていたとしてもユーザーは変更を嫌うものだということが分かってきました。

### ⑦ 選択肢や機能を増やすことで満足度が上がる!?
一般的には、選択肢を持つことは良いことだと考えられています。私たちは選択に慣れており、選択肢を自由に扱えると思っています。

しかし、Webサイトで選択肢が多いほどUIを理解するのが難しくなります。選択肢が多いと、意思決定がズレたり、ストレスにつながることがあります。

原則として、Webサイトを使う前はその機能の多さだけを評価しているだけで、使い始めるとシンプルな方が満足度が高いです。

### ⑧ アイコンだけで使いやすさを向上できる!?
アイコンのみのUIでは記憶に残りにくく、非効率な場合が多いということを多くの研究者が証明しています。
また、他の研究では**ユーザーはIconの形よりもボタンの位置の方を覚えている**ことがUIEによってわかっています。


## まとめ

この記事では、UXデザインで勘違いされがちなトピックスにまとめた[UX MYTHS](https://uxmyths.com/)を
翻訳して、まとめました。

業務でもやりがちな項目も結構あり、心が痛くなりながらまとめていました。
今回まとめた内容は、1部でしかないので、興味があったら、原文の方もご覧ください。

https://uxmyths.com/

---

最後まで読んでくださってありがとうございます！

[Qiita Advent Calendar 2021](https://qiita.com/advent-calendar/2021/qiita)の4日目は、
Qiita 株式会社 CX向上G の@ohakutsuが担当します！

ぜひ[Qiita Advent Calendar 2021](https://qiita.com/advent-calendar/2021/qiita)を購読設定して、
明日の記事もご覧いただけると嬉しいです。

また、デザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
Mh-tinyボードを試してみる

安かったので独身の日セールでMh-tinyボードなるものを買いました。

https://ja.aliexpress.com/item/32962322447.html

Attiny88というチップを使っているようで、Attinyってピン数が少ないイメージでしたが(85とか)、このボードはピン数も多いし安い割にはよさそうです。

<img src="https://user-images.githubusercontent.com/68873801/89062312-803fa100-d366-11ea-9142-69c36b0ca764.png" width=400 /> 

###Arduino環境の準備

↓これがArduinoでAttinyシリーズをサポートしてそうなので、ここの手順に沿って進めていきます。
https://github.com/SpenceKonde/ATTinyCore

環境設定→追加のボートマネージャのURLに`http://drazzy.com/package_drazzy.com_index.json`を貼り付けてOKをします。
次にツール→ボードマネージャを開いて`ATTinyCore by Spence Konde`をインストールします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146663/c0614982-cc47-dec2-e8cd-243eee5f9ce4.png" width=400 /> 

インストールすると`警告：信頼されていないコントリビューションです。スクリプトの実行をスキップしています`とArduinoで表示されます。ドライバのインストールは自動で行われないので、手動でpost_install.batを実行してドライバを入れます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146663/f0ea333e-6f2e-7a97-ad0d-e0b6bdc4e672.png" width=400 /> 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146663/7f3f438f-58f2-eb00-496c-d3eae81dcee0.png" width=400 /> 

####書き込み

スケッチを書くときは、ATtiny88(Micronucleus, MH-ET t88 w/16MHz CLOCK)を選択して書き込みを実行します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146663/13876c57-9cea-6925-5c00-0872dc8cc160.png" width=400 /> 

書き込みが始まると、`Please plug in the device (will time out in 60 seconds)` と出てくるのでそのタイミングでボードをPCに差すかResetボタンを押すとPCで認識されて書き込みが始まります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146663/5fd896b4-e748-25d2-585a-3bf2eca7f4be.png" width=400 /> 


スペックではBluePillとかAtmega互換のLGT8F328Pとかのほうがいいのでしょうけど、これでArduino環境で遊べそうです。😁
Scratch3.0でライブラリなしでニューラルネットワークを作ってみた

# Scratchでニューラルネットワークが作れちゃった！
より詳しくまとめた記事はこちら

https://www.chickensblog.com/scratch-neural-network-no-library/

## はじめに
Scratch3.0で外部ライブラリ、独自拡張機能などを使わずにニューラルネットワークを作ってみました。

Pythonで最初にニューラルネットワークを作り、その後そのプログラムをもとにScratchでニューラルネットワークを作りました。

Python側で使った計算ライブラリはNumPyというものです。

ScratchにはもちろんNumPyなんてものはないので、NumPyのような計算プログラムを再現するところからニューラルネットワーク制作は始まりました。
## 制作期間
- 大体1~2週間?

Scratchで実装するのはそこまで難しくなくて、それよりもニューラルネットワークというものについて勉強しながらだったので、意外と時間がかかりました。Scratchで実装する部分で特に難しかった部分といえば、NumPyでやる行列演算ぐらいです。

## 簡単な自己紹介
簡単に自己紹介させていただきます。プログラミング勉強中、Scratchが一番得意、Web系のプログラマーになりたい高校生です。

最近勉強しすぎて頭がおかしくなっています。

今回の記事の詳しい内容はブログに載せています（プログラムの内容など）⬇️

https://www.chickensblog.com/scratch-neural-network-no-library/

ProtoPediaのヒーローズリーグ2021にも応募してみました⬇️

https://protopedia.net/prototype/2661

Qiita、書き方とか全体的に初心者すぎて何もわからないのですが、プログラミング界隈の方が多くみているのかなと思い、それなら自分がScratchで作ったニューラルネットワークが評価されるのではと思い、記事を書いてみました。

もしScratchでニューラルネットワークを作ろうとしている方はぜひ参考にしていただけると嬉しいです。

## ニューラルネットワーク作ってみた
Scratchでニューラルネットワーク。独自拡張、ライブラリ、改造ブロックなど一切なし。

https://scratch.mit.edu/projects/564599222

## どうやって作ったのか
「ゼロから作るDeep Learning――Pythonで学ぶディープラーニングの理論と実装」という本を参考にしました。最初にPython、NumPyで作った後にNumPyをScratchで再現、そしてPythonのプログラムを再現しました。

## 性能
- 入力層の数：784個(28*28のピクセルデータの個数分)
- 中間層一つ目の数：50個
- 中間層二つ目の数：100個
- 出力層の数：10個（0~9の答えの個数分）
- 画像認識ができる（0~9のMNISTデータセットを90%以上の精度で認識）
- まだ学習機能は搭載していない

## 今後の使い道
- ScratchでもYouTubeにあるような機械学習ができる
- Scratchで作った作品に組み込める
- ゲームのAIとか
- ニューラルネットワークの仕組みの学習教材
- ディープラーニング制作

## こだわったポイント
- 2*2以上？の行列演算ができるプログラム
- NumPyソースコードで行列作成ができる
- 多分ブロードキャストができる（忘れてしまった汗）
- 汎用性が高い

## 今後の課題
- 学習ができない
- ソースコードが汚い
- 画像認識以外のこともできるようにする

今後の課題の学習ができないについては、勾配降下法や遺伝的アルゴリズムを使って実装しようと思っています。個人的に実装が楽そうなのは遺伝的アルゴリズムなので、多分遺伝的アルゴリズムで実装すると思います。

## まとめ
Scratchでもニューラルネットワークはライブラリ、独自拡張機能などなくても作れる。
作るのには数学の知識が必要になる。（微分、行列、シグマ等）遺伝的アルゴリズムを使えば学習機能を比較的簡単に実装できそう。
微分、ｽｰﾊﾟｰｳﾙﾄﾗｸﾞﾚｰﾄﾃﾞﾘｼｬｽﾜﾝﾀﾞﾌﾙﾜｶﾘﾂﾞﾚｰ!!!
ここまでよんでいただきありがとうございました。SNSシェアなどよろしくお願いします！

https://www.chickensblog.com/scratch-minecraft-2d/

https://www.chickensblog.com/laravel-docker/

https://www.chickensblog.com/coderdojo-kasuga-mousikomi/
C++三項演算子×コンマ演算子で気を付けたいこと


# 概要
- コンマは演算子なんだよ～って話。
- 演算子の優先度の話。
- 実例を交えた話。  

といった感じで、  
コンマを**演算子**と認識していなかったために起こった、プログラムの意図しない挙動と調べたことを紹介。
これは、浅瀬で溺れた話です。

# コンマ演算子
> 左被演算子を評価しその値を捨て、その後右被演算子を評価する演算子である。
コンマ演算子の値と型は右被演算子の値と型となる。C では右辺値だが、C++ では右被演算子が左辺値であれば左辺値となる。また、左被演算子の評価に対する副作用（C++では一時変数の破棄を除く）が完了した後に右被演算子が評価されることが規格上保証されている。(Wikipediaより)


# 演算子の優先度
結論だけ言うと、コンマ演算子は最も優先度が低いです。  
詳しく知りたい方は[コチラ](https://ja.cppreference.com/w/cpp/language/operator_precedence)を見てください。


# ここまでを解説
```cpp
int a=1, b=2, i;

// 例１
i = a, b;

// 例２
i = (a, b);
```
例１は結果的に`i = a`となります。  
代入演算子の方が優先度が高いため、コンパイラ的には`i = a; b;`のようになるためです。

例２は結果的に`i = b`となります。  
（）でくくられているため、先に演算されます。  
`a, b`を演算すると例によって左辺値`a`が捨てられて右辺値`b`が評価されます。  
結果、残った`b`が`i`に代入される形で、コンパイラ的に`i = b;// aは捨てられた！`になります。

わかりました？？実際テストコードを書いてみると動きがよくわかります。

# 実際に起こったこと
```cpp
void Show(int a);
void Show(int a, int b);

int main()
{
  bool flag = getFlag();//フラグを取得し
  Show( flag ? x , y : x );//フラグに応じて、引数を変更する。
}
```
コードを書いた時の感覚的に、`flag`が正の時は**`x, y`が引数**に、負の時は**`x`が引数**に入るイメージでした。（ここがすべての原因）  

#### 起こっていたことを説明  

- 正の場合  
**三項演算子も立派な演算子**です。`flag`を評価した後、三項演算子の式１`x , y`を評価しに行きます。  
コンマ演算子は`x`を捨て`y`が残り、関数呼び出しが`Show(y);`となります。
- 負の場合  
三項演算子の式２だけを評価するので、関数呼び出しが`Show(x);`となります。(これは普通の流れ)

どちらも**`void Show(int a);`**を呼び出す結果となってしました。  
コンパイル時にはエラーにならないので気づけませんでした。  
**環境によっては、ビルド時にwarningが出ます。**  
意外と簡単な話でしたね。そして、情けない話です...。  

ちなみに  
この実装で修正するなら

```cpp
flag ? Show(x, y) : Show(x);
```
これですかね。

# まとめ
何気なく区切りなどに使っていて、コンマ演算子をしっかり理解できていない人もいたのではないでしょうか。  
普通、今回の件のような使い方はしないので、レアケースだと思います(笑)  
コードとしても可読性が低いので、そもそも実装を見直すことがベターでしたね。  
言語によっては若干仕様が違うこともあるそうです。小ネタにでもなれば幸いです。  
  
##### 独自で調べた見解ですので、「厳密にはこうだ！！」などあればコメント等で情報お願いします。
  
# 見まくったサイト
- [c++ 可読性 コンマを持つ三次演算子が実際のケースで 1 つの式のみを評価する理由](https://code-examples.net/ja/q/2d562da)
- [C++ リファレンス　その他の演算子](https://ja.cppreference.com/w/cpp/language/operator_other#Built-in_comma_operator)
fp-tsを理解する：Semigroup

## はじめに

fp-ts はTypescriptの型システムを使って関数型プログラミングをしようという趣旨のライブラリです。

正確なところは公式ドキュメントの[こちら](https://gcanti.github.io/fp-ts/) に書いてあります。

学習リソースの[こちら](https://dev.to/gcanti/getting-started-with-fp-ts-semigroup-2mf7)を動かしながら理解する過程を書いた記事になります。実装が古くなっている点は変更しています。

## Semigroup とは

簡単にSemigroupについてです。群となる条件のうち結合法則を満たすものを半群（Semigroup）と呼びます。

半群`(A, *)` は集合 `A` と結合操作 `*` のペアで表されます。

`*` は2つの値をとる結合操作になります。型で表すと以下のような関数になります。

`*: (x: A, y: A) => A`

## Semigroup を作る

結合操作を持っていれば Semigroup ということで fp-ts には

```ts
interface Semigroup<A> {
  concat: (x: A, y: A) => A
}
```

と定義されてます。

はじめに　Semigroup を返す関数を作ってみます。

```ts
import * as S from "fp-ts/Semigroup";

const getSemigroupMin = (): S.Semigroup<number> => {
  return { concat: (x, y) => (x <= y ? x : y) };
};

const getArraySemigroup = <A = never>(): S.Semigroup<A[]> => {
  return { concat: (x, y) => x.concat(y) };
}
```

ジェネリクスを使って何らかの配列を結合する Semigroup が作れました。

実は汎用的な Semigroup はインスタンスメソッドが用意されていて組み合わせるだけで生成ができたりします。

```ts
import * as S from "fp-ts/Semigroup";
import * as A from "fp-ts/Array";

const semigroupMin: S.Semigroup<number> = S.min(N.Ord);

const arraySemigroup: S.Semigroup<string[]> = A.getSemigroup<string>();
```

学習リソースでは非推奨のAPIの利用があったので書き換えています。

v2.0.0 から型ごとにexportする設計変更があったようです。それに合わせて命名がシンプルになっています。

続きを読み進めてベクターの実装をします

```ts
import * as S from "fp-ts/Semigroup";
import * as N from "fp-ts/number";

type Point = {
  x: number;
  y: number;
};

export const semigroupPoint = S.struct<Point>({
  x: N.SemigroupSum,
  y: N.SemigroupSum,
});

type Vector = {
  from: Point;
  to: Point;
};

export const semigroupVector = S.struct<Vector>({
  from: semigroupPoint,
  to: semigroupPoint,
});
```

新しいAPIの `S.struct` 書き換えています。Typescriptで簡潔にSemigroupが作れました。

抽象度が上がり応用できそうな気がしてきました。　次に座標を判定する関数を作ってみます。

```ts
import * as F from "fp-ts/function";
import * as B from "fp-ts/boolean";
import * as S from "fp-ts/Semigroup";

const semigroupPredicate: S.Semigroup<(p: Point) => boolean> = F.getSemigroup(
  B.SemigroupAll
)<Point>();
```

`B.SemigroupAll` は2つの入力が `true` のとき `true` を返します。

`F.getSemigroup` は集合の型を関数に変換するヘルパーです。

型を展開すると以下のような Semigroup が生成されるイメージです。

```ts
type Predicate = (p Point) => boolean
type SemigroupPredicate = {
  concat: (x: Predicate, y: Predicate) => Predicate;
}
```

動かしてみます。

```ts
const isPositiveX = (p: Point): boolean => p.x >= 0;
const isPositiveY = (p: Point): boolean => p.y >= 0;

const isPositiveXY = semigroupPredicate.concat(isPositiveX, isPositiveY);

console.log([
  isPositiveXY({ x: 1, y: 1 }),
  isPositiveXY({ x: 1, y: -1 }),
  isPositiveXY({ x: -1, y: 1 }),
  isPositiveXY({ x: -1, y: -1 }),
]);
// [ true, false, false, false ]

```

座標が第一象限に存在するか判定する関数が組み上がりました。

## Folding

Semigroupのインターフェースでは2つの要素しか結合できませんでした。そこで複数の要素を畳み込むように結合してくれるのが Folding です。

```ts
import * as S from "fp-ts/Semigroup";

const min = S.concatAll(S.min(N.Ord))(0);

console.log([
  min([-2, -1, 1, 2, 3]),
  min([1, 2, 3]),
]);
// [ -2, 0 ]
```

v2.0.0 では大胆な変更が入っており `fold` ではなく `concatAll` になっていました。

`S.min` では、単に２つの入力から小さい値を取るだけの関数でしたが `S.concatAll` で配列から最小値を取得できるようになりました。

## 終わりに

`fp-ts` の Semigroup について基本的な動作を確認してきました。

Semigroup を応用できるように引き続き利用していきたいと思います。
PyQt5のチュートリアルを動かす ③ Qt Designerを使う

前回,PyQt5で良く使用するツールやモジュールを紹介しました。

https://qiita.com/hoshianaaa/items/301f07e6e87abb6979a3

今回はQt Designerを使い方を説明します。
これを使うとGUIをコードを書かずに作成でき楽です。

今回はこの使い方を記載します。

# 使い方

1. アプリを開く

![Screenshot from 2021-12-01 18-20-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/3a8cc275-35ad-bc74-86b8-12a806613f8a.png)

2.テンプレート選択

![Screenshot from 2021-12-01 18-09-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/fb3734c1-6d85-0878-fafe-75845a8d5502.png)

3.左の部品を組み合わせてGUI作成

![Screenshot from 2021-12-01 18-16-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/298d77c9-325c-e6de-d520-e9ba3e204e35.png)

4.`.ui`ファイルを生成し,以下コマンドから`python`コードを生成

```
pyuic5 -x demo.ui -o demo.py
```


5.実行

```
python demo.py
```

先程作成したGUIが表示されました。

![Screenshot from 2021-12-01 18-16-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/81bcd8fb-b222-f963-81ad-09663a9bc90d.png)


6.生成コードにプログラムを追加し,お好きなアプリケーションを作成してください

以上

# 最後に

今回のGUIはボタンなどを押してもアクションが生成されません。
この、ユーザーのアクションに反応することを`event handling`と呼びます。
次回はこの`event handling`についてご紹介致します。

# 参考

https://www.tutorialspoint.com/pyqt5/pyqt5_using_qt_designer.htm
aspect-ratioを使ってサイズがバラバラな画像を縦横比を揃えて表示する


この記事は [CSS Advent Calendar 2021](https://qiita.com/advent-calendar/2021/css) 1日目の記事です。
`aspect-ratio` を使って画像のトリミング表示をしてみました。

## やりたいこと

- サイズがバラバラな複数枚の画像を表示サイズを合わせて表示したい。
- レスポンシブで縦と横の比率も揃えたい。
- 画像のトリミングは縦方向も横方向も中央部分が表示できれば良い。

## できました

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="poWvPGO" data-user="becolomochi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/becolomochi/pen/poWvPGO">
  responsive trimming image</a> by Beco (<a href="https://codepen.io/becolomochi">@becolomochi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## ざっくり重要なところだけ

### HTML の構造

img 要素を div 要素で囲んでいます。

```html
<div class="responsive-image">
  <img src="image.png" alt="image">
</div>
```

### img 要素の親要素の CSS

親要素に `overflow` と `aspect-ratio` を指定します。

```css
.responsive-image {
  overflow: hidden;
  aspect-ratio: 5 / 3;
}
```

### img 要素の CSS

img 要素自体には `object-fit` と縦と横それぞれ 100% を指定しました。
100%を指定する理由は、縦長の画像・横長の画像両方に対応するためです。

```css
.responsive-image img {
  object-fit: cover;
  width: 100%;
  height: 100%;
}
```

## まとめ

padding して position 指定して…よりすっきりしてて良いですね。
最新の Safari で対応したのでどんどん使える状況が増えると良いなと感じました。
Android Studioでjdkを8→11にアップデートしたらComponenCallbacksにアクセスできませんというエラーに遭遇した

先日Android Studioでjdkを８→11にアップデートした際に、 `ComponentCallbacksにアクセスできません`というビルドエラーに遭遇しました。
エラーが出ている所を見に行っても何も警告等は出ておらず、何かライブラリが足りていないのかと長時間ハマってしまいました。
結論としては、gradleバージョンが低い事が原因だったようです。

File > ProjectStructure > Project
と遷移していくと、Android Gradle Plugin VersionとGradle Versionを設定画面に遷移できます。
![スクリーンショット 2021-12-01 17.59.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533385/99176f39-cbf3-592a-e92a-99875f64b98b.png)

ここでこれらのバージョンを最新のものにしてあげると無事ビルドができるようになりました。

謎のビルドエラーに阻まれた時は、まずクリーンビルドやInvalidate Caches。
それらがダメであればGradleやPluginのバージョンを見直そうねという話ですね。
DjangoのORMでいろいろ試してみた

MySQLでデータ取得する時はこうSQLを書くけど、DjangoのQuerySetを取得する時はどうするんだろうと思うことがあり、いろいろ試してみました。
# 環境
- Django 2.2.3
- Python 3.7.4

# 内部結合したテーブルのpk以外で検索したい
modelsはそれぞれコードと名前のフィールドを持ち、市テーブルに都道府県テーブルと紐づけるForeignKeyを設定しています。
紐づけるフィールドはpk（プライマリーキー）にするので、to_field等は指定していません。

```python:models.py
from django.db import models

class Pref(models.Model):
    pref_cd = models.IntegerField(null=False, unique=True)
    pref_name = models.CharField(max_length=255, null=False)

    class Meta:
        db_table = 'pref'


class City(models.Model):
    pref = models.ForeignKey(
        Pref,
        on_delete=models.SET_NULL,
        null=True
    )
    city_cd = models.IntegerField(null=False)
    city_name = models.TextField(max_length=255, null=False)

    class Meta:
        db_table = 'city'
        unique_together = (('pref', 'city_cd'))
```
### SQL
```
SELECT * 
FROM city 
    INNER JOIN pref ON pref.id = city.pref_id
WHERE pref.pref_name = '{都道府県名}';
```
###  QuerySet
``<ForeignKeyを設定したフィールド名>__<検索したいフィールド名>``で検索できます。

```
City.objects.filter(pref__pref_name='{都道府県名}')
```
# 内部結合したテーブルのpk以外でソートしたい
### SQL
```
SELECT * 
FROM city 
    INNER JOIN pref ON pref.id = city.pref_id 
ORDER BY pref.pref_cd DESC;
```
###  QuerySet
検索と同じように``<ForeignKeyを設定したフィールド名>__<ソートしたいフィールド名>``でソートできます。

```
City.objects.order_by('pref__pref_cd').reverse().all()
```
# ForeignKeyを設定していないテーブル同士で結合して検索したい
ForeignKeyは設定せず、市テーブルにも都道府県名を持つようにしています。

```python:models.py
from django.db import models

class Pref(models.Model):
    pref_cd = models.IntegerField(null=False, unique=True)
    pref_name = models.CharField(max_length=255, null=False)

    class Meta:
        db_table = 'pref'


class City(models.Model):
    city_cd = models.IntegerField(null=False)
    city_name = models.TextField(max_length=255, null=False)
    pref_name = models.TextField(max_length=255, null=False)

    class Meta:
        db_table = 'city'
```
### SQL
```
SELECT city_name 
FROM city 
    INNER JOIN pref ON pref.pref_name = city.pref_name 
WHERE pref.pref_cd = {都道府県コード};
```
###  QuerySet
```
City.objects.extra(
    tables=['pref'],
    where=['city.pref_name=pref.pref_name']
).extra(where=['pref.pref_cd={都道府県コード}']).all()
```
このクエリを出力してみるとわかりますが、
SQL的には``WHERE ((city.pref_name=pref.pref_name) AND (pref.pref_cd={都道府県コード}))`` と結合はしていません。
ほしいデータが取得できたからよしとしましたが、prefテーブルのデータは取得できないので注意です。
[JavaSilver受験対策] 誰も解けないラムダ式を解説

この記事は、[シアトルコンサルティング株式会社 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/seattleconsulting "Advent Calendar 2021")の9日目の記事です。
こんにちは、シアトルコンサルティングの村田です。
## はじめに

* ラムダ式ってなに  
* Javaシルバーの勉強中でラムダ式についての問題が分からない  
  
Javaのラムダ式に関して上記の方を対象にしています。
後半ではJavaシルバーの例題を用いて得点するポイントを解説しています。



## 1. ラムダ式は実行を代入できる
&emsp;通常インタフェースはメソッドを実現したクラスを定義しなければなりません。
しかしラムダ式を用いることで、メソッドが1つだけのインタフェース型変数（関数型インタフェース）に実行を代入できます。

```java
Runnable r = () -> {System.out.println("sample");};
```
■ラムダ式の構文  
  &emsp;引数の変数宣言＋処理ブロックをアロー演算子「->」でつなぎ、以下のように記述します。  
  &emsp;(引数) -> {処理};  

関数型インタフェース型の変数に代入するとそのインタフェース型のインスタンスとして動作します。

&emsp;関数型インタフェースの型 変数名 = (引数) -> {処理};  

## 2. ラムダ式を活用してコードを単純化
&emsp;■ラムダ式を使用しない場合

```java
public static void main(String[] args) {
  List<String> list = List.of("a","b","c","d");
  Consumer<String> logic = new Consumer<String>() {
    @Override
    public void accept(String str) {
      System.out.println(str);
    }
  };
  list.forEach(logic);
}
```
<br />
&emsp;■ラムダ式を利用した場合 

```java
public static void main(String[] args) {
  List<String> list = List.of("a","b","c","d");
  list.forEach((str) -> System.out.println(str));
}
```

&emsp;関数型インタフェースを使用する場合はラムダ式を活用することで、定義から実装までを1行で記述できます。
上記のような簡易的なコードであれば、かなり簡略化できます。

## 3. JavaSilverでの出題形式と解法のポイント
&emsp;ここからはJavaSilver問題に向けた解き方のコツを説明します。

<例題①>
コンパイルの実行結果として正しいものはどれか。

```java
public void Sample() {
  int i = 0;
  Supplier<Integer> x = () -> i;
  i++;
  System.out.print(x.get());
}
``` 
<選択肢>
A.コンパイルできるが、何も起きない
B.例外がスローされる
C.0が出力される
D.1が出力される
E.コンパイルエラー&emsp;→ 正解  
<解説>
ラムダ式を含むブロックの中では、宣言された変数をラムダ式で使う場合、実質的にはfinalである必要があります。
変数「i」が宣言されたあと、ラムダ式で使用されているにもかかわらずインクリメント（i++）されているためコンパイルエラーになります。


<例題②>
コンパイルの実行結果として正しいものはどれか。

```java
public static void main(String[] args) {
  final String hoge = "hello";
  Consumer<Integer> x = (hoge) -> System.out.print(hoge);
  x.accept("thanks");
}
``` 
<選択肢>
A.「hello」が出力される
B.「thanks」が出力される
C.何も出力されない
D.コンパイルエラー&emsp;→ 正解
E.例外がスローされる   
<解説>
このプログラムでの注目ポイントは宣言している変数名です。
ラムダ式内の「（hoge） -> 」の部分は正確には「(String hoge) ->」と引数宣言のデータ型を省略した形になっています。
2行目にfinalで宣言しているhogeとラムダ式内で宣言しているhogeが重複しているためコンパイルエラーになります。  
## さいごに
&emsp;Javaシルバー学習のお供として分からなかったことをまとめました。
Javaシルバーで得点するためにはコンパイルエラーになるケースを覚えることが近道になります。
選択肢を絞るための一助としていただければと思います。  
### 参考
(1) 志賀澄人 徹底攻略Java SE 11 Silver 問題集[1Z0-815]対応 株式会社インプレス 2019
SSHを使った踏み台ブラウザアクセス（socks5プロキシ利用）

リモートワークになって、IP制限がかかったサイトにアクセスする機会が増えたのでメモ

踏み台のサーバがあって、SSHログインできることが前提、この踏み台からは目的のサイトにアクセス可能

自分のマシンはMAC

ダイナミックポートフォワードでサーバに接続

```
ssh -D 8888 my_account@XXX.XXX.XXX.XXX
```

ブラウザのネットワーク接続の部分で、自分のマシンの8888に変更

![スクリーンショット 2021-12-01 17.35.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342329/e1a62983-3817-da03-bf23-72291f5349ce.png)


これでアクセスできる。

ブラウザはFireFoxがおすすめ。FF自体がネットワーク設定を持っている。 CHROMEはOSの設定を変えようとするので、戻すのが面倒

注意点として通常のプロキシ設定（HTTP,HTTPS）と併用すると、そっちが優先的に使われるので
SOCKSの設定だけにすること

自分はIP制約があるサイトはFF,それ以外はCHROMEで使い分けている。
GAN（敵対的生成ネットワーク）

AIに関する情報を閲覧するとき、「GAN」という単語をよく目にすると思いますが、
「難しそう」と思う方は多いのではないでしょうか?
ここでは、「GAN」について簡単に説明したいと思います。

###GANとは
GAN（Generative Adversarial Network）とは、2つのニューラルネットワークが互いに競い合い、より正確な予測を行う機械学習（machine learning）モデルです。GANは通常、教師なしで実行され、協力的なゼロサム（zero-sum）ゲームの枠組みを使って学習します。

GANを構成する2つのニューラルネットワークは、Generator（ジェネレーター）とDiscriminator（ディスクリミネーター）と呼ばれます。Generatorは生成ネットワークで、Discriminatorは識別ネットワークです。Generatorの目的は、本物のデータと間違えられるような偽物のデータを作り出すことです。Discriminatorの目的は、その生成されたデータは本物かどうかを識別することです。

基本的に、GANは教師なしで学習データを生成します。GAN（敵対的生成ネットワーク）間のフィードバックループが続くと、Generatorのデータ生成力と、Discriminatorの識別力の精度を高めていきます。

###GANの仕組み
GANを構築するに、まず、求める最終効果を確定し、そのパラメータに基づいて初期の訓練用データセットを収集します。それから、精度の高い出力を得るまでこのデータをランダムにGeneratorに入力することです。
その後、生成された画像は、オリジナルの実際データポイントと一緒にDiscriminatorに提供されます。Discriminatorはこれらの情報を識別、整理し、各画像の信憑性を表す0と1の間の確率を返します（1が本物、0が偽物）。最後はこれらの値の精度を手動で確認し、理想の結果が得られるまで繰り返されます。

###GANの一般的な使用例
GANモデルは、画像コンテンツを理解し、高度な精度で画像データを再現できるため、画像の[超解像](https://vanceai.com/ja/ "VanceAI Home")処理にぴったりです。また、以下の応用ケースがあります。

画像の解像度を上げる
・テキストから画像を生成する
・白黒画像に色づける
・動画内での人の動きパターンをモデル化する
・画像を別の画像に仕上げる（ディープフェイク）
Webの勉強はじめてみた　その6 ～JavaScript編 ループと配列～

「N予備校のプログラミング入門 Webアプリ」のアーカイブ動画と一緒に勉強を進めています。
今日は第一章の9節と10節を受講しました。

<h2>ループ処理</h2>
まずはFizzBuzzをfor文で。

```javascript
for(var i = 1; i <= 100; i+=1){
    if(i % 15 === 0){
        document.write('FizzBuzz ');
    }else if(i % 3 === 0){
        document.write('Fizz ');
    }else if(i % 5 === 0){
        document.write('Buzz ');
    }else{
        document.write(i + ' ');
    }
}
```

:::note
授業では扱わないっぽいので、while と do while を思い出しながらやってみた。
whileって何か応答を待つ間ずっと回す時に使うイメージ。
:::

<h3>whileの場合</h3>

```javascript
var i = 1;
while(i <= 100){
    if(i % 15 === 0){
        document.write('FizzBuzz' + ' ');
    }else if(i % 5 === 0){
        document.write('Buzz' + ' ');
    }else if(i % 3 === 0){
        document.write('Fizz' + ' ');
    }else{
        document.write(i + ' ');
    }
    i++;
}
```

<h3>do whileの場合</h3>

```javascript
var i = 1;
do{
    if(i % 15 === 0){
        document.write('FizzBuzz' + ' ');
    }else if(i % 5 === 0){
        document.write('Buzz' + ' ');
    }else if(i % 3 === 0){
        document.write('Fizz' + ' ');
    }else{
        document.write(i + ' ');
    }
    i++;
}while(i <= 100);
```

<h2>配列</h2>
配列って書き方がわりとあって混乱する。
JavaScriptの場合は`[]`

<h3>for文を使って配列を書き出す</h3>

```javascript
//1年A組～3年D組を書き出すプログラム
let classes=['A組', 'B組', 'C組', 'D組'];
for(var grade =1; grade < 4; grade++){
    for(var i = 0; i < classes.length; i++){
        var rslt = '<p>' + grade + '年' + classes[i] + '<p>'
        document.write(rslt);
    }
}
//あ行とか行を使った
//2文字の名前の組み合わせを書き出すプログラム
let name1 =['あ', 'い', 'う', 'え', 'お','か', 'き', 'く', 'け', 'こ'];
for(var i = 0; i < name1.length; i++){
    for(var x = 0; x < name1.length; x++){
        var rslt = name1[i] + name1[x] + '<br>'
        document.write(rslt);
    }
}
```

<h3>ForEachを使う</h3>
配列とえいばforeachだと勝手に思ってます。
でも書き方が覚えにくい。VB.NETはシンプルだったなぁ(遠い目)。

```javascript
//1年A組～3年D組を書き出すプログラム
let classes =['A組', 'B組', 'C組', 'D組'];
//学年も配列にしてみる
let grade =['1年','2年','3年'];
grade.forEach(gr => {
    classes.forEach(cls => {
        var rslt ='<p>' + gr + cls + '</p>';
        document.write(rslt);
    });
});

//あ行とか行を使った
//2文字の名前の組み合わせを書き出すプログラム
let name1 =['あ', 'い', 'う', 'え', 'お', 'か', 'き', 'く', 'け', 'こ'];
name1.forEach(chars => { 
    name1.forEach(chars2 => {
        var rslt = '<p>' + chars + chars2 +'</p>'
        document.write(rslt);
    });
});
```

<h3>For Of を使う</h3>
これは初めて知りました。

```javascript
//あ行とか行を使った
//2文字の名前の組み合わせを書き出すプログラム
let name1 =['あ', 'い', 'う', 'え', 'お','か', 'き', 'く', 'け', 'こ'];
for(var chr1 of name1){
    for(var chr2 of name1){
        var rslt = '<p>' + chr1 + chr2  + '</p>';
        document.write(rslt);
    }    
}
```

こっちのほうがわかりやすいかも。
ここを参考にさせてもらいました。

https://www.javadrive.jp/javascript/array/index10.html

<h2>まとめ</h2>
ループ処理や配列が絡んでくるといよいよプログラミングって感じがします。
今回授業ではやってなかったんですが、for ofなど、初めて知ることもあったので
もっと興味のアンテナを広げたいと思います。
E2Eテスト自動化で重要な変数の値マネジメント

これは[オープンロジアドベントカレンダー](https://qiita.com/advent-calendar/2021/openlogi)3日目の記事です。
# 自動テスト運用で重要なこと
この投稿では、ツール選びがうまくいって、E2E自動テストのスクリプト作成が終わり、自動テストの運用段階で重要になることを記す。
（ツール選びについては[E2Eテスト自動化ツールの選び方](https://qiita.com/T-Com/items/1981aa21f93ff41e1d06)で書いてます。）

私が現在所属する[OPENLOGI](https://service.openlogi.com/)では[Ghost Inspector](https://ghostinspector.com/)（以下GI）を導入してから、約半年でリグレッションテストの自動化がほぼ完了した。
GI はドキュメントが充実しているので細かい使い方は[Documentation](https://ghostinspector.com/docs/)を見るとわかりやすい。

ここではGIの機能について書くが、以下の内容はE2Eテスト自動化する上でのポイントとして参考にしていただければと思う。


## E2Eテストを自動化する時に考慮しておくべきこと
E2Eテストの自動化が完了したら、目的に応じてテスト実行頻度が決まる。
そして、実際の自動テストは環境の影響やデータの重複などが原因で途中で失敗することが多々ある。
その時は再実行が必要になるのだが、新規ユーザ登録では一度使ったメールアドレスは再利用できないことがほとんどなので、都度テスト用のデータを用意しなくてはならない。

**自動テストスクリプトを作成する段階で、同じテストを何度も実行することを考慮して工夫をしておくと自動テストを運用しやすくなる。**


## 自動テスト運用では変数の値の扱いやすさが大切
自動テストは同じテストを何度も実行するため、テスト用のデータは変数を用いて設定していくことになる。
そのため、変数の値の管理のしやすさは自動テスト運用のしやすさに直結する。


## Ghost Inspector は変数の値のマネジメントが優れている
GIには変数の値の設定箇所が多数用意されていて、再実行時にデータを変更しやすくなっている。これは自動テストを運用する上で非常に便利なので詳しく説明する。

### Ghost Inspector の変数の値マネジメント機能の特色
1. 変数の値の設定箇所が階層ごとにある
1. その上、各階層ごとに変数の値の設定箇所が複数ある
1. なので、目的に応じた設定箇所から変数の値を設定できる
1. 変数の値をCSVでアップロードできる
1. テストスクリプト内でも変数の値を設定できる
1. [組み込み変数](https://ghostinspector.com/docs/variables/#built-in-variables)が予め用意されている
1. 前のテストで扱った変数の値を引き継いでテスト実行できる（シーケンシャルテスト設定時）
1. 前回のテスト実行時の変数の値で再実行できる
1. 前回のテスト実行時の変数の値を手動で変更して実行できる


### 階層構造
- Orgnization
    - テストスイート
        - テスト

各階層で変数（Variables）が管理でき、下の階層で設定されたデータが優先されて変数に代入される。
すべてのテストで必ず使うデータはOrganizationに設定するといった具合に、設定する階層を変えることでマネジメントが非常にしやすくなっている。

### 組み込み変数
GIが予め用意した変数をスクリプトで扱うことで、毎回違った値を生成してくれるので、テスト用データを準備する必要がなくなり非常に便利。

**{{random.number}}
{{timestamp}
{{internet.email}}**

この辺は使い勝手がとても良い。


## 最もよく使っている変数管理機能
**8. 前回のテスト実行時の変数の値で再実行できる**
**9. 前回のテスト実行時の変数の値を手動で変更して実行できる**
この2つの機能は、テストの再実行ではもちろん、自動テストのスクリプトを作る時にも大活躍する。

GIでは１度実行したテストには「Run again」ボタンが表示される。クリックするとテストの各種設定モーダルが表示される。
![スクリーンショット 2021-12-01 13.07.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357158/49ec47c3-e65e-a453-6535-2373c6e198f3.png)
その中の「Variables」に前回のテストで扱った変数と値がすべて確認でき、微調整して再実行することができる。
また、テストスクリプトの調整によって新たに変数を追加した場合には「Add variable」で新規追加した変数の値を設定しつつ、前回のデータを使ったテストができる。
組み込み変数によって生成されるものは、モーダルから削除することで再実行時に自動生成される。


## まとめ
自動テストを運用してみた上で、とても大切だと思ったことなのでもう一度。
**自動テスト運用では変数の値の扱いやすさが大切**
なぜなら、何度も同じテストを実行するためにはデータの重複を避けないといけないから。

これからE2E自動化に着手するという時の参考になれば幸いです。