OmniAICreator/Qiita-1.07M huggingface dataset:
Multi-Car Racing(Gym)の使い方

# はじめに

R2D2やGoliraなどの並列分散系強化学習で学習を行いたい時に、環境もそれらに対応をしてほしいです。

しかし、OpenAiのCar Racing環境では、並列化を行うことができません。

そこで、今回は、並列化に対応した「Multi-Car Racing」の使い方について、説明します。

実行環境は、google colab proを使っています。
また、以下のチュートリアルを参考にしました。

https://github.com/igilitschenski/multi_car_racing

自身のgithubは以下の通りです。

https://github.com/sugiyama404/ReinfoceLearningForTrading/blob/main/Control/multi_car_racing.ipynb

### 感謝

下記コメント欄にあるように、山田@ymd_h 様に助けていただき、コードを大幅に変更いたしました。

# import

```python
!apt update && apt install xvfb
!git clone https://github.com/igilitschenski/multi_car_racing.git
!pip install ./multi_car_racing
!pip install -U imgaug==0.2.7 gym-notebook-wrapper

import gym
from gym import wrappers
import gym_multi_car_racing
import numpy as np
import gnwrapper
```



# ワラッパークラス

```python
class FlatMultiDisplayWrapper(gym.Wrapper):
    def __init__(self, env, nrows=1, ncols=1, empty_cell=0):
        super().__init__(env)
        self.nrows = nrows
        self.ncols = ncols
        self.empty_cell = empty_cell

    def render(self, mode="human", **kwargs):
        stack_images = super().render(mode, **kwargs)
        nstack = stack_images.shape[0]
        frame_shape = stack_images.shape[1:]

        if len(frame_shape) >= 2:
            self.flat_shape = list(frame_shape)
            self.flat_shape[0] = self.flat_shape[0]*self.nrows
            self.flat_shape[1] = self.flat_shape[1]*self.ncols
            frame = np.full(self.flat_shape, self.empty_cell, dtype=np.uint8)

            for i in range(min(nstack, self.nrows*self.ncols)):
                row = i // self.ncols
                col = i % self.ncols
                frame[row*frame_shape[0]:(row+1)*frame_shape[0],
                      col*frame_shape[1]:(col+1)*frame_shape[1]] = stack_images[i]
        else:
            # たまに、空の画像を stack した画像が返ってくる。
            frame = np.full(self.flat_shape, self.empty_cell, dtype=np.uint8)

        return frame

    def step(self, action):
        obs, rew, done, info = super().step(action)
        # Reward が gym.Env の仕様を満たしていないので変換する。元の値はinfoに入れておく
        info["original_reward"] = rew
        return obs, rew.sum(), done, info
```


# 本体

```python
actions = np.array([[ 0, 0, 0],  # [0]: straight
                    [ 0, 1, 0],  # [1]: acceleration
                    [ 0, 0, 1],  # [2]: decelerate
                    [ 1, 0, 0],  # [3]: Turn right
                    [-1, 0, 0]]) # [4]: Turn left

env = gym.make("MultiCarRacing-v0", num_agents=2, direction='CCW',
        use_random_direction=True, backwards_flag=True, h_ratio=0.25,
        use_ego_color=False)

env = FlatMultiDisplayWrapper(env, nrows=1, ncols=2)
env = gnwrapper.Monitor(env, './', force = True)

obs = env.reset()
done = False
total_reward = 0

while not done:
    action = np.random.randint(5)
    action = actions[action]
    obs, reward, done, info = env.step([action,action])
    total_reward += reward

print("individual scores:", total_reward)

env.display()
```

環境に対するインプット、アウトプットは、リスト形式で送信する必要があります。

```console
action: [[ 0, 0, 0], [ 0, 0, 1]]
reward: [-83.16498316 -62.96296296]
```
Droneの使用済みバッテリーの処分方法についてまとめ

Droneを飛行させるのに必要なバッテリー。
１年間フルに飛ばすと徐々にパフォーマンスが下がってきますね。
長期間使用せずに放置していても劣化し、過充電などでもバッテリーが使えないということに陥ります。

Drone Birdに所属する隊員は、ドローンオペレーターであることが多いですが、ClubHouse内で表題の件でディスカッションしたことをまとめたいと思います。


#処分方法について
私が活動範囲としている兵庫県宝塚市を中心とした地域で行っており、リポバッテリーの処分について、宝塚市のゴミ処理場に問い合わせてみました。

リポバッテリーは爆発する危険性もあることから、ゴミ処理場で受け取りをしていないという回答で、そのバッテリーを購入した販売店または、市内の家電量販店で引き取ってもらうように聞いてみてくださいということでした。

#家電量販店に持っていくと
「えーちょっと困りますねぇ...」
という反応で、４つあったバッテリーの１つは引き取ってもらえました。
JBRC(Japan Portable Rechargeable Battery Recycling Center)
https://www.jbrc.com/
という団体に家電量販店は加盟していたりしますが、上記サイトで検索することができます。
但し、一般の使用済み電池を対象としていますが、一部のドローンバッテリーは対象にならないことがあります。

#対象外バッテリー
中国産の正規品でないバッテリーなど、リサイクルマークが表示されていないバッテリーなどは処分対象にならない場合があります。
処分のことも考えて、正規品を購入するようにするなどを心がける必要があります。

#使用済みバッテリーのディスカッション
ドローンオペレーターに、使用済みバッテリーについて、どのように処分しているかという問いに複数回答をいただきました。
バッテリーの処分については、どのように処分するか否かについて多くのオペレーターが使用済みのバッテリーを保管したままになっているという回答でした。
今後、バッテリーの処分について、各地域で処分方法について、海外製品を含めた適正な方法での処分を考えて、ドローンに関係者の中でも情報共有していくことが課題になっています。
【オブジェクト指向】コンストラクタ

##コンストラクタとは
Rubyのようなオブジェクト指向のプログラミング言語で使われる機能の1つで、オブジェクトを生成した際に1度だけ実行される機能を指す名称。
initialize という名前のメソッドは自動的に private に設定される。

##initialize
- 「new」メソッドが実行された際に自動的に呼び出される

```ruby
class Sample
   def initialize
     p '初期化処理'
   end
end  

s = Sample.new
"初期化処理"
=> #<Sample:0x0000557ab2005168>
```

- インスタンスを生成するnewメソッドで引数を指定することで、その値をインスタンス変数に設定することが可能

```ruby
class Sample
  def initialize(name)
    @name = name  
  end

  def execute() 
    p @name + ' hello'
  end  
end

sample1 = Sample.new('kato') 
=> #<Sample:0x0000557ab2595ec0 @name="kato">
sample2 = Sample.new('takagi') 
=> #<Sample:0x0000557ab25bd740 @name="takagi">

sample1.execute 
=> "kato hello"
sample2.execute
=> "takagi hello"
```

- initializeを実行しない場合はクラスをnewして、インスタンスメソッドへ引数を引き渡してという処理を、各処理毎に毎回設定しなければいけない。

```ruby
class Sample
  def name=(name)
    @name = name
  end

  def hello
    p @name + ' hello'
  end
end

s = Sample.new
s.name = 'kato'
p s.execute
=> "kato hello"
```

##参考

https://docs.ruby-lang.org/ja/latest/method/Object/i/initialize.html

https://style.potepan.com/articles/29301.html

https://asalworld.com/1629/
PyQt5のチュートリアルを動かす ➈ Multiple Document Interface

# はじめに

今回はウィンドウ内コンテナに複数のウィジェットを持つMDIのデモを動作させました。リソースを少なくなるように内部でなっているそうですが,概念が難しく詳細は参考サイトをご覧ください。

# デモ

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

class MainWindow(QMainWindow):
   count = 0

   def __init__(self, parent = None):
      super(MainWindow, self).__init__(parent)
      self.mdi = QMdiArea()
      self.setCentralWidget(self.mdi)
      bar = self.menuBar()

      file = bar.addMenu("File")
      file.addAction("New")
      file.addAction("cascade")
      file.addAction("Tiled")
      file.triggered[QAction].connect(self.windowaction)
      self.setWindowTitle("MDI demo")

   def windowaction(self, q):
      print ("triggered")
   
      if q.text() == "New":
         MainWindow.count = MainWindow.count+1
         sub = QMdiSubWindow()
         sub.setWidget(QTextEdit())
         sub.setWindowTitle("subwindow"+str(MainWindow.count))
         self.mdi.addSubWindow(sub)
         sub.show()

      if q.text() == "cascade":
         self.mdi.cascadeSubWindows()

      if q.text() == "Tiled":
         self.mdi.tileSubWindows()

def main():
   app = QApplication(sys.argv)
   ex = MainWindow()
   ex.show()
   sys.exit(app.exec_())

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

実行してウィンドウ追加をしていったり整列などのボタンを押したりすることで,window内のドキュメントウィンドウを増やしたり、整列させることができました。(若干動作がもっさりしている感じがしました...)

![Screenshot from 2021-12-02 12-53-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/a7db0ac1-36da-7bb9-cd69-eb01ffe79203.png)

![Screenshot from 2021-12-02 12-52-49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/412e4097-3487-9b24-664b-48b58848b8c1.png)


# 参考

https://www.tutorialspoint.com/pyqt5/pyqt5_multiple_document_interface.htm
matlabでKeysightのオシロスコープのデータを取り込む

　KeysightのPC用アプリにBenchVueがあります。最初ベータ版でリリースされ、その後、有料になりました。昨年は、毎年費用を払うサブスクリプションになっています。だったはずですが、今はよくわからない体系になっているようです。ころころライセンス形態が変わっているので、利用される方は、最新の情報を調べてください。
　ここではベータ版を使います。
　オシロスコープ、発振器、DMMなど、最近の機種ではそれぞれ対応したモジュール？ライセンス？があります。さらに、測定の手順をGUIで記述できるアプリも用意されています。GPIBとかまったく気にせずに使えます。予算さえあれば。
###オシロスコープでデータをエクスポートする
　BenchVueでオシロスコープのDSOX3012Tを認識させます。このオシロスコープはUSBが標準で用意されています。PCとUSBケーブルで接続します。
![2021-12-02 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/c15d023a-a904-e2b6-9c7c-2dcf6dfbeebf.png)

　右下のエクスポートをクリックします。
　現在のトレースをキャプチャをクリックします。
![2021-12-02 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/d662795d-b6c0-cb42-ffe7-f16c4f28f255.png)


###matlabで読み込む
　「1 DSO-X 3012T USBInstrument1.mat」というファイル名で保存されていました。これを、matlabのライブエディタのフォルダにコピーします。
　プログラムです。

```matlab
clear
load("1 DSO-X 3012T USBInstrument1.mat")
disp(Trace_1)
figure
plot(Trace_1(:,1),Trace_1(:,2));
title('wave');
xlabel('Time(sec)');
ylabel('Voltage (V)');
grid on;
```

　実行結果です。
![2021-12-02 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/cc525178-0e1a-5ba7-2fd3-637f095cc0e8.png)

　ローパス・フィルタをかけました。
``
lowpass(Trace_1(:,2), 10 ,1000)
``

![2021-12-02 (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/8dbf161e-47e8-8a75-cbb8-9e3b196f6506.png)


●参考文献
https://courses.engr.illinois.edu/ece110/sp2018/content/labs/ReferenceMaterial/BenchEquipment/Port%20Oscilloscope%20data%20to%20MATLAB%20using%20Keysight%20BenchVue%20v2.pdf
PyQt5のチュートリアルを動かす ➇ QMessageBox

# はじめに

前回は`Dialog`クラスについてご紹介しました。

https://qiita.com/hoshianaaa/items/b795075c0b308e97d072

今回は,`QMessageBox`についてご紹介致します。

`QMessageBox`は一般的に使用されるモーダルダイアログで、色々な情報をメッセージ表示しオプションで標準ボタンからユーザーに応答を求める機能があります。

# `QMessageBox`の主要メソッドまとめ

`QMessageBox`クラスに関連する重要なメソッドは以下のようになります。

## 1:setIcon()

メッセージの重大度に対応する定義済みのアイコンを表示する

Question
Information
Warning
Critical

## 2:setText()

表示されるメインメッセージのテキストを設定する

## 3:setInformativeText()

追加情報を表示する

## 4: setDetailText()

ダイアログに詳細ボタンを表示します。それをクリックするとこのテキストが表示されます

## 5:setTitle()

ダイアログのカスタムタイトルを表示します

## 6:setStandardButtons()

表示される標準ボタンのリスト。各ボタンは次のように関連付けられています。

QMessageBox.Ok 0x00000400

QMessageBox.Open 0x00002000

QMessageBox.Save 0x00000800

QMessageBox.Cancel 0x00400000

QMessageBox.Close 0x00200000

QMessageBox.Yes 0x00004000

QMessageBox.No 0x00010000

QMessageBox.Abort 0x00040000

QMessageBox.リトライ 0x00080000

QMessageBox.Ignore 0x00100000

## 7:setDefaultButton()

ボタンをデフォルトとして設定します。Enterが押されるとクリックされたという信号を出します。

## 8:setEscapeButton()

エスケープキーが押された場合、ボタンがクリックされたものとして扱われるように設定する

www.DeepL.com/Translator（無料版）で翻訳しました。

# デモ

```python:qmessage_box.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("Show message!")
   
   b.move(100,50)
   b.clicked.connect(showdialog)
   w.setWindowTitle("PyQt MessageBox demo")
   w.show()
   sys.exit(app.exec_())

def showdialog():
   msg = QMessageBox()
   msg.setIcon(QMessageBox.Information)
   
   msg.setText("This is a message box")
   msg.setInformativeText("This is additional information")
   msg.setWindowTitle("MessageBox demo")
   msg.setDetailedText("The details are as follows:")
   msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
   msg.buttonClicked.connect(msgbtn)

   retval = msg.exec_()

def msgbtn(i):
   print ("Button pressed is:",i.text())

if __name__ == '__main__':
   window()

```

実行すると以下のようなウィンドウが出力されます。

![Screenshot from 2021-12-02 12-28-42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/ffc8a812-db4e-73e3-2f32-e74aee7f3155.png)

ボタンを押すと次のようなウィンドウが表示されます。

![Screenshot from 2021-12-02 12-28-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/fda53ef5-6466-dcb4-06a9-3ca84a6229e9.png)

そして,OKボタンやCancelボタンを押すと以下のようなメッセージが出力されます。

![Screenshot from 2021-12-02 12-46-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/ddc334e9-7fb2-ded0-ff93-650426068807.png)

# プログラム解説

以下で`QMessageBox`クラスを作成しています。

```
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText("This is a message box")
msg.setInformativeText("This is additional information")
msg.setWindowTitle("MessageBox demo")
msg.setDetailedText("The details are as follows:")
```

そして`setStandardButton()`で表示したいボタンを設定しています。

```
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
```

以下でボタンクリックシグナルに対するスロットを設定しています。

```
msg.buttonClicked.connect(msgbtn)
```

# 参考

https://www.tutorialspoint.com/pyqt5/pyqt5_qmessagebox.htm
SourceTreeでGitHubにPushする時のトークン入力について

#GitHubでPushする際に最近困ったこと
最近SourceTreeを使ってGitHubにPushする機会があったのですが、IDとパスワードを聞かれ入力してもPush出来ない問題に遭遇…
GitHubは2021年8月13日にパスワード認証が廃止され、アクセストークンを使用する仕組みになりました。
SourceTreeのどの画面にアクセストークンを入力するのかわからず、いろいろ試していたところ発見したので備忘録として残しておきます。


##SourceTree画面での操作

まずはいつも通りコミットをしPushの画面へ

ここでIDとパスワードを聞かれると思いますが、ここで「キャンセル」ボタンを押してください。←**ココがポイント**
![スクリーンショット 2021-12-02 10.45.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/b5748671-6184-0b0b-71b3-e09fe046bd42.png)

すると、もうひとつ入力ポップアップが出てきます。
ここにアクセストークンを入力するとPushができるようになります。
![スクリーンショット 2021-12-02 10.45.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/594e8681-839f-70c5-7b87-566244bb2028.png)

アクセストークンの生成方法はGitHubから生成ができます。
GitHubの「Settings」を選択
![スクリーンショット 2021-12-02 10.49.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/f4a983b5-cc4d-13cf-e909-361a44807799.png)

「Developer settings」を選択
![スクリーンショット 2021-12-02 10.49.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/1edfac7d-e179-6151-0e41-264ab58d7425.png)

「Personal access tokens」の「Generare new token」から発行することができます。
![スクリーンショット 2021-12-02 10.49.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/24f06897-89ae-5dd7-7eff-61d992b69d0b.png)


##ポップアップが表示されない場合

ログインに失敗しているとポップアップが出ない時があります。
この場合SourceTreeに記録されているGitHubアカウント情報を一度削除する必要があります。

まずはSourceTreeの画面の右上のアイコンをクリック。
![スクリーンショット 2021-12-02 10.46.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/498d86a3-bab8-4d36-8d72-b9124bf624a1.png)

本来ここの「高度な設定」が選択できるはずなのですが、SourceTreeが日本語の設定の場合は何故か表示されません。（どうにかならないものか…）
![スクリーンショット 2021-12-02 10.46.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/b5cdfdb0-3ffe-d0e1-4da3-cf335a8260f5.png)

なので、一度SourceTreeの言語を「English」に変更し、アプリを再起動します。
![スクリーンショット 2021-12-02 10.46.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/234db79f-77a0-cd03-bca9-5471f4b9eb7a.png)


すると先程のメニューに「Advanced」というメニューが表示されるので選択してください。
![スクリーンショット 2021-12-02 10.47.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/04d51fd8-877d-23b3-cdeb-3d83e760d7fd.png)

画面にGitHubのアカウントが表示されていると思いますので、選択してremoveしてください。
![スクリーンショット 2021-12-02 10.47.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339373/6d11cd08-584e-b91d-482b-3a5985dcbab9.png)

再度Pushしたいリポジトリに行き、Pushするとポップアップが表示されるようになりました。

以上備忘録でした。
PyQt5のチュートリアルを動かす ➆ QDialog Class

# はじめに

前回は基本のwidgetについてのまとめでした。

https://qiita.com/hoshianaaa/items/3752422ea45d716ad371

今回は`QDialog`クラスについてです。

# 内容

QDialogはユーザーからのリスポンスを得る為に主に使用され、最上位画面に出てきます。

PyQt APIには`InputDialog`、`FileDialog`、`FontDialog`などの多くの拡張済みのダイアログウィジェットが用意されているようです。

以下の例では,`WindowModality`属性がモーダルかモードレスカアを決定します。(※モーダレスだとダイアログが閉じるまで,元のウィンドウに切り替わらなくなるそうです。)

ユーザーがEscapeキーを押すと`QDialog.reject()`メソッドによってダイアログが破棄されるそうです。

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

def window():
   app = QApplication(sys.argv)
   w = QWidget()
   btn = QPushButton(w)
   btn.setText("Hello World!")
   btn.move(100,50)
   btn.clicked.connect(showdialog)
   w.setWindowTitle("PyQt Dialog demo")
   w.show()
   sys.exit(app.exec_())

def showdialog():
   dlg = QDialog()
   b1 = QPushButton("ok",dlg)
   b1.move(50,50)
   dlg.setWindowTitle("Dialog")
   dlg.setWindowModality(Qt.ApplicationModal)
   dlg.exec_()

if __name__ == '__main__':
   window()

```

実行すると以下のようなwindowが表示されます。

![Screenshot from 2021-12-02 12-11-42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/ac0ebef9-2a05-8e4a-41d5-d59e4d671c8b.png)

そしてボタンを押すとダイアログwindowが表示されます。

![Screenshot from 2021-12-02 12-12-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/a2c73681-41b3-eac0-864d-34b3819f4475.png)

# さいごに

ダイアログにも色々な種類のものが用意されており、またモーダル/モードレスなどの設定も可能だと言うことが分かりました。
良く使うGUIでのダイアログの作り方の基本がわかりしました。
ただダイアログから親へのシグナルの受け渡しやデータ共有の方法等気になるところですね。普通にsignal/slotやglobal変数等でできるのでしょうか??
今後こういった部分にも注目していきたいと思います。

# 参考

https://www.tutorialspoint.com/pyqt5/pyqt5_qdialog_class.htm
学生間のチーム開発のコツ

##はじめに
初めてのアドベントカレンダーの3日目担当のinazawaです。今回のテーマは「初めて」ということなので、初対面の方々と「初めて」チーム開発を行った際の反省点や改善点を共有し、皆さんの「初めて」のハッカソンやコンテストでのチーム開発のヒントになれればいいなと考えています！拙い記事ですがよろしくお願いします！


##エンジニア力編
学生間でのチーム開発では、これまで歩んできた経験が違うのでプログラミング自体が初めての方やその言語やフレームワークが初めての方、バリバリ経験を積んできた方などの幅広くエンジニア力が違った人たちが集まって開発することになります。そこでうまくいかなかったことを挙げていきます。
###身の丈にあった技術選定
コンテストなどは１ヶ月長くても２ヶ月のものが多く、ハッカソンはそれよりも短期間のものが多いです。その期間でいろんな技術に挑戦しようとしてはうまくいきません。チーム開発では、初心者のメンバーがよく使用している言語やフレームワークを選択し、初心者の方に基礎的なところを負担してもらい、経験者が応用的なところや+αをチャレンジするとうまくいきやすくなります。

###チーム間での開発力の調整
最初の点とも関係するのですが、メンバーの開発力を最初期に確認し、チーム間での開発力の格差をある程度解消しなければなりません。これはメンターの方にも言われたことなのですが、開発する前にチーム間で勉強会やチュートリアルをこなしておき、メンバーの技術力の底上げを行うと同時に、メンバー間での技術力の相互確認が行うことでどのレベルまで任せられるのか、どこからがメンバーにとってチャレンジするレベルになるのかの指標にもなります。また、コーディング規約やコメントをどのくらい残すのかなどのことも決めておくとよりよく開発が行えると思います。

##コミュニケーション編
はっきりいって、コミュニケーションが一番重要です。チーム間のコミュニケーションがうまくいかなければ、ほぼチーム開発は失敗になります。柔らかでアットホームな職場やチームを作っていきましょう(ブラック企業ぽいけど)

###雑談をしよう
雑談はやわらかい雰囲気づくりの上でかなり重要です。メンバーが技術の質問をしようにも、作品の改良案を言おうにもなんでも言えるアットホームな雰囲気がないとなかなか怖気付いて発言出来ません。発言したいメンバーが初心者なら尚更です。そんな時に、メンバー間の仲を深めておくと自然に聞くことができるし、改善案も積極的にいうことができます。雑談は全ての潤滑油になるのです。

###質問やコードレビュー
質問やコードレビューに関しては非常に参考になる記事がこちらにあります。

https://qiita.com/hiraike32/items/32840b11536fa1b78621

このほとんどは初心者の時期にチーム開発を行ったことがある人なら体感したことがあると思います。マジで、「公式ドキュの〇〇みた？」や「その書き方見にくいな〜」とか言われるとどんどんモチベーションが下がります。学生間のチーム開発は、仕事ではないのでこういうことが起きるチームはメンバーがよく飛びます。私の初めてのチーム開発がこういう雰囲気のチームでしたがエンジニア4人中2人が飛び、残ったのは私と怖いレビュワーの二人だけでした。ですが、今振り返ってみると彼のおかげで公式ドキュメントを見る癖がつき、エンジニア力の向上につながったと思います。
ようやく公式ドキュメントのありがたみを理解することができましたし、先輩プログラマーたちが公式ドキュメントを勧めてくる理由も理解できるようになりました。

また、ダメなところを指摘する前にいいところをいくつか伝えてあげましょう（全くなくても態度や意図を褒めてあげましょう）。いいところをいくつか伝えることで、ダメなところを伝えても、比較的モチベの低下に繋がりにくく、〇〇の意図は間違ってなかったんだ！という自信にもつながります。

###開発の小ネタ
コンテストやハッカソンではスケジュール通りにうまくいくことはほとんどありません。そこで実装する機能要件の取捨選択が必要になってくるのですが、評価される作品にしたいならコアの機能をメインに実装しましょう。例えば掲示板アプリなら、掲示板の機能が最初に開発し、次にログインやプロフィールなど、というふうにコアの機能を重点的に開発するほうがいいと思います。（ログインなどの周りの機能は他と差が出にくい機能であるため)

###終わりに
ハッカソンやコンテストは非常に力のつく経験であり、普段個人開発をしているとなかなか気付かない点を多く指摘してもらえたり、他人のコードを読むことでどういう意図で作ったのか、などを考え、身につけることができる体験でもあります。なので、初心者の方にこそ、参加して欲しいし、その土壌をみんなで作っていくことで日本のエンジニアの育成にもなります。辛いこともありますが、頑張って乗り越えれば力になるので積極的に参加していきましょう！
PyQt5のチュートリアルを動かす ➅ Basic Widgets

# はじめに

前回は`layout`クラスの導入をしました。

https://qiita.com/hoshianaaa/items/d4367241211173e06d30

今回は基本widgetのまとめとなります。

# 内容

1 QLabel（キューラベル
QLabelオブジェクトは、編集不可能なテキストや画像、またはアニメーションGIFのムービーを表示するプレースホルダーとして機能します。また、他のウィジェットのニーモニックキーとしても使用できる。

2 QLineEdit（ラインエディット
QLineEditオブジェクトは、最も一般的に使用される入力フィールドである。QLineEditオブジェクトは、1行のテキストを入力できるボックスを提供します。複数行のテキストを入力するには、QTextEditオブジェクトが必要です。

3 QPushButton (プッシュボタン)
PyQt APIでは、QPushButtonクラスのオブジェクトは、クリックすると特定の機能を呼び出すようにプログラムできるボタンを示す。

4 QRadioButton
QRadioButtonクラス・オブジェクトは、テキスト・ラベル付きの選択可能なボタンを表示します。ユーザーは、フォームに表示されている多くの選択肢の中から一つを選ぶことができます。このクラスは、QAbstractButtonクラスから派生したものである。

5 QCチェックボックス
QCheckBoxオブジェクトが親ウィンドウに追加されると、テキストラベルの前に長方形のボックスが表示されます。QRadioButtonと同様に、選択可能なボタンでもある。

6 QComboBox
QComboBoxオブジェクトは、選択可能なドロップダウン・リストを表示します。現在選択されている項目のみを表示するため、フォーム上で必要な最小限の画面スペースしか必要としません。

7 QSpinBox
QSpinBoxオブジェクトは、整数を表示するテキストボックスをユーザーに提示し、その右側にアップ/ダウンボタンを表示します。

8 QSlider Widget & Signal（スライダー・ウィジェット＆シグナル
QSliderクラスのオブジェクトは，ハンドルを移動させることができる溝をユーザーに提示します。境界のある値を制御するための典型的なウィジェットです．

9 QMenuBar, QMenu & QAction
QMainWindowオブジェクトのタイトル・バーのすぐ下にある水平のQMenuBarは、QMenuオブジェクトを表示するために用意されています。

10 QToolBar
QToolBarウィジェットは、テキスト・ボタン、アイコン付きボタン、その他のウィジェットで構成される、移動可能なパネルです。

11 QInputDialog
これは、テキスト・フィールドと2つのボタン（OKとCancel）を持つ、事前に設定されたダイアログです。ユーザーがOkボタンをクリックするか、Enterキーを押した後、親ウィンドウがテキストボックスの入力内容を収集します。

12 QFontDialog
もう一つのよく使われるダイアログ、フォントセレクタ・ウィジェットは、QDialogクラスの視覚的な外観です。このダイアログの結果は、Qfontオブジェクトであり、親ウィンドウによって消費されることができます。

13 QFileDialog(ファイルダイアログ)
このウィジェットは、ファイル・セレクタ・ダイアログです。ユーザーは、ファイル・システムをナビゲートして、開いたり保存したりするファイルを選択することができます。ダイアログは、スタティック関数を使用するか、ダイアログ・オブジェクトのexec_()関数を呼び出すことで起動されます。

14 QTab
フォームのフィールド数が多すぎて同時に表示できない場合、タブ付きウィジェットの各タブの下に配置された異なるページに配置することができます。QTabWidgetは、タブバーとページ領域を提供します。

15 QStacked
QStackedWidgetの機能はQTabWidgetと似ています。また、ウィンドウのクライアント領域を効率的に使用することができます。

16 QSplitter(スプリッター)
QSplitterは、子ウィジェット間の境界線をドラッグすることで、子ウィジェットのサイズを動的に変更することができる、高度なレイアウトマネージャです。スプリッターコントロールには、コントロールのサイズを変更するためにドラッグできるハンドルが用意されています。

17 QDock
ドッキング可能なウィンドウは、フローティング状態を維持したり、指定した位置でメインウィンドウにくっつけることができるサブウィンドウです。QMainWindowクラスのメイン・ウィンドウ・オブジェクトには、ドッカブル・ウィンドウ用の領域が用意されています。

18 QStatusBar
QMainWindowクラスのメイン・ウィンドウ・オブジェクトは、ステータス・バーとして底部に水平のバーを確保しています。ステータスバーは、恒久的なステータス情報やコンテクスト情報の表示に使用されます。

19 QList
QListWidgetクラスは、リストにアイテムを追加したり、リストからアイテムを削除するアイテムベースのインターフェイスです。リストの各アイテムは、QListWidgetItemオブジェクトです。ListWidget は、マルチセレクタブルに設定することができます。

20 QScrollBar
スクロールバーコントロールは、ユーザーがドキュメントの表示範囲外の部分にアクセスすることを可能にします。また、現在の位置を視覚的に表示します。

21 QCalendar
QCalendarウィジェットは、便利な日付ピッカーコントロールです。月ベースのビューを提供します。ユーザーは、マウスやキーボードを使って日付を選択することができ、デフォルトでは今日の日付が表示されます。

www.DeepL.com/Translator（無料版）で翻訳しました。

# 参考

https://www.tutorialspoint.com/pyqt5/pyqt5_basic_widgets.htm
【基礎知識】Webページが表示される流れと用語まとめ

## 記事の目的

Webプログラミング初心者。最低限の知識を他人に説明できるようにするための記事。

## 流れ

### 0. 前提（WebサーバーとHTTP）

- Webサーバー・・・Webブラウザからコンテンツの要求があると、必要なネットワークを通してWebブラウザに送信する役割
- HTTP（Hyper Text Markup Language）・・・世界共通のコンテンツ（ハイパーテキスト）を送信するやりとりの手順のこと

### 1. URLを使ってWEBサーバーにアクセス
URLには、「どのやりとりの手順で」「どのWebサーバーに」「なんのコンテンツを」取得するのか、という情報が入っている。

（例）`http://www.sbcr.jp/index.html`

- どのやりとりの手順で・・・httpプロトコルの手順で
- どのWebサーバーに・・・www.sbcr.jpという名前のWebサーバーに
- なんのコンテンツを・・・index.htmlというコンテンツを要求

####　実際の流れ
自分のChrome（Webブラウザ）「`http://www.sbcr.jp/index.html`を開くぜー。」
　　↓
DNSサーバー「おっけー、`http://www.sbcr.jp/index.html`のIPアドレス探します」
　　↓
DNSサーバー「あったよ。`52.197.215.198`ほれ。」**（名前解決）**
　　↓
自分のChrome（Webブラウザ）「`52.197.215.198`接続するぜー。」
　　↓
接続先のWebサーバー「ほれ（コンテンツ）」
　　↓
自分のChrome（Webブラウザ）「　{  Webページ  }　どどんっ！！」


## 用語

- **TCP/IP**

インターネットにおける様々なサービスを実現するためのプロトコル。HTTPもその一部。

- **IPアドレス**

インターネットに接続されたコンピューターを特定してデータの行き先を管理するもの。世界でたった一つだけのインターネット上の住所のようなもの。
現在は３２ビットの数字で表記されるIPv4が主流。
（例）192.168.1.1


- **ポート番号**

Webサービスやメールサービスなど、コンピューターは様々なサービスを提供している。IPアドレスでは接続したいコンピューターは指定できるが、提供しているサービスまでは指定できない。
そこで、コンピューターのサービスをしてできるように利用するのがポート番号。
０〜６５５３５まであり、**Webサーバーは８０番ポート**。
上記の例で挙げた`http://www.sbcr.jp/index.html`ではポート番号を明記していない理由はhttpを用いてサーバーにアクセスしているため省略できる。
省略せずに記載する場合は`http://www.sbcr.jp:80/index.html`。

- **ドメイン**

（例）`example.com`
インターネット上のサーバーを特定し、識別するためのIPアドレスは人間的に覚えにくい＆使いづいらいため、IPアドレスを文字列化したもの。

- **DNS**

ドメインをIPアドレスに変える仕組みのこと（Domain Name System)
実際のコンピューター同士の接続はIPアドレス（数字）が使われているため、人間のために使っていたドメインをコンピューター用のIPアドレスに変換する必要がある。
DNSサービスを提供するサーバーをDNSサーバーという。

DNSの仕組み、すごい忙しそう。（『DNS 図』で画像検索）

## 最後に
文字だけじゃきつい。参考本はイラストが豊富でわかりやすかったです。

## 参考本
#####イラスト図解式 この一冊で全部わかるWeb技術の基本
テスト管理ツールの導入が面倒な理由

# 背景やこの記事の意図
私、気づけばQA業界で15年働いております。
Xbox360のゲームテスターから始まり、コンシューマゲーム、スマホゲームを中心にゲーム9割、非ゲーム1割くらいの割合で多様なプロダクトのQA現場を渡り歩いてきています。
そんな私のキャリア内の現場において、BTSやITSと呼ばれる管理システムはほとんど導入されていましたが、テスト管理ツールが導入され、継続的に運用していた（運用できていた）のは1社だけでした。その1社では[TestLink](https://ja.wikipedia.org/wiki/TestLink)というオープンソースのツールを使って、専任の管理者とエンジニアが張り付いてメンテナンスしていました。
その経験は6年くらい前ですが、いちユーザー、管理者として、テスト実施、進捗確認がしやすく有益に感じていました。その後、転職や異動の際、QAフロー構築や改善の要素として検討材料に上がり、試用やテストランまでするものの本格採用までは至りませんでした。
現在、再び導入を検討しているので、メリット、デメリット、導入への障壁、事例、導入に向いているシチュエーションをまとめたいと思います。

# テスト管理ツールとは
事前情報として、テスト管理ツールの主な目的はテスト要件管理からテスト項目管理、バグ管理まで、QAの様々な工程を標準化できるツールとなります。
ツールの違いを具体的に知りたい方はサービスの導入記事など探してみてください。

以下の記事で複数のサービスが存在することがわかると思います。
https://ja.myservername.com/top-11-test-case-management-tools
https://qiita.com/e5rijun/items/a05cd2d7e60e3279c8c8
※複数のサービスの存在はこの種のツールが一定の効果があり、また需要が多いことを示してると思われます

# メリット
- レポートの視認性が良くなる
    - フォーマットが統一されて閲覧者に優しい
        - JIRAからのエクスポートデータを調整してグラフ化したり、人に頼っていた部分を肩代わりしてくれる
        - 専用ツールなのでレイアウトが綺麗
- ナレッジを共有しやすい
    - チーム毎の独自進化が軽減され情報把握しやすくなる
        - テスト結果やテストケースのフォーマット統一が目指せる
- 属人化が軽減する
    - テストケースの連続性が担保される
        - 観点の知見が散見して作成者や実施者で精度が下がることが減る
        - 個人が積み重ねたテクニックも手順や観点で残しやすい
- 作業が標準化される
    - ワークフローを統一しやすくなり管理コストが低減する
    - 業務知見が再利用しやすい

# デメリット
- コストが掛かる
    - webサービスでアカウント数に応じた価格なので展開する範囲に応じたコストになる
    - オープンソースのTestLinkを使った場合はパッケージよりメンテコストが掛かる
    - ツールの使い方など一定の学習コストが掛かる
- ツール依存に陥る（かもしれない）
    - 一元化した弊害で柔軟性が落ちる可能性がある
    - エクスポートなどでテストケースのダウンロードできるが成形し直さないとならない

# 導入への障壁
- QAへのアウトプット要求が低い
 - プロダクトの事情、規模、担当者次第ではあるが要求されるレポート品質はあまり求められていない
     - プロダクトの目的はサービスが要件が達成してリリースすることなので、計画通りにリリース出来ている場合にはQA工程や品質保証状況に対して無頓着となりやすく、テスト管理ツールに対しては無駄コストと考える傾向がある
 - QAレポートを出す側と受け取る側で合意できるので問題になることが少ない
     - リリース判定はテストが完了してバグの取り捨てが行えれば良いので、バグリストさえ纏まっていれば問題が起こりづらい
- QA現場は困っていない
 -  テスト管理ツールはレポートの質を一定にし、管理や準備のコストダウンなので実施者目線では効果が薄い
 -  今のやり方を信じ切っている
- テスト管理ツールを知らない
 -  認知されていなかったり、知っていてもそのツールが何をもたらすかわからない
 -  QAの管理者層とPMやPOで品質を重視する人以外には興味を持ってもらえない
- テスト管理ツールの選定が大変
 - ツールの概要などでは差が感じにくい
     - 使える機能は似ていてもUIや拡張性など微妙な違いは触らないと分からない
 - テストデータ投入や運用テストランなど時間が掛かる
     - テストを想定せずに簡単なテストデータを一括で入れただけでは評価し辛く、比較対象が増えると学習にも時間が掛かる。専任でしっかりと腰を据えて評価できるコストが必要となる。
 - 組織が大きいほど時間が掛かるが小さくては効果が薄いというジレンマ
- ExcelやGoogle spreadsheetの万能性
 - 手間は掛かるがこのツールで何とかなってしまう

# 断念した例
3年程前の新規プロジェクトにてQAチームを立ち上げた際、管理コストの軽減とモダンなテスト環境を目指しておりました。当時、私はJIRAとの連携に重きをおいていたので、JIRAアドオンで展開しているサービスのZephyr、QMetry、TestRail、qTest、4つのサービスで比較検討しました。
結論としては、JIRAのアドオンに絞ったためツールのカスタマイズ性に乏しいサービスしかなかったことと、社内インフラへのアドオン追加では費用も嵩むことが分かり断念しました。
この時の結論に至るまで、ツール選定や社内相談など2か月くらいかかりそれなりの労力でした。検討開始時点でJIRAとの強い連携を前提に始めたため、前提を覆すことが難しく、また組織的な共感を得る動きをあまりしていなかったため再検討、再選定とはなりませんでした。

# 導入に向いているシチュエーション
- QA組織や文化が醸成されており、横軸連携できている
- 一元化した進捗管理が望まれている
- リグレッションテストをする機会が多くテストケースを継続してメンテナンスする価値が高い
- テスト結果や項目の分析、比較を繰り返し行いたい
- 品質保証、品質管理目線でのアウトプット要求が高い
- 導入希望者に予算があり、時間的余裕がある

# まとめ
テスト管理ツールとはあくまで管理ツールであり、導入したからといって直接的に品質が向上するものではなく、管理者がレポート作成やテスト設計、改修を容易にするためのものです。
導入でのデメリットは少ないですが、プロダクトにとっての劇的なメリットが無く、障壁が多いため実際のQAで採用し辛いかと思われます。
テスト管理ツールに興味を持たれた方。まずは1つのサービスをトライアルでじっくり触ってみてください。そして自分が想像するQAの未来に必要かどうか想像しながらトライアルをしてみると良いと思います。
必要だと思ったなら、導入の障壁をクリアするために所属している組織、プロジェクトのQA意識向上、文化醸成を行っていきましょう。
腰を据えて、より良いQAの未来を目指して。
Python で仮想環境を構築する

# Ubuntu 18.04でPythonの仮想環境を構築
以下のコマンドを実行する。

```terminal
mkdir /path/to/venv_dir/ && cd /path/to/venv_dir
// 今、venv_dirにいる
// my_envは好きな名前
python -m venv my_env 
source my_env/bin/activate
```
これで仮想環境が構築される。
停止は、以下。

```terminal
deactivate
```

# pyenvでpython version管理
本家のサイトを参考にインストール。
https://github.com/pyenv/pyenv#installation

途中のbashrcに関する部分は、~/.bashrcを変更するのではなく、

~/.profile
を変更すること！

pyenvのよく使うコマンド

```terminal
pyenv versions // インストールしているPythonのバージョン確認
pyenv install -l // インストールできるPython バージョン表示
pyenv install 3.7.0 // python 3.7.0インストール
pyenv local 3.7.0 // 現在のディレクトリにおいてPython バージョン変更
pyenv global 3.7.0 // すべてのディレクトリでPython 3.7.0にする


```
pyenv --version は単にpyenvのバージョンが表示されるだけなので注意。

# pyenvでバージョン変更したのに、仮想環境上ではバージョンが切り替わらない問題。
## 問題詳細
実行したコマンド。

``` terminal
cd /path/to/my_env_dir
python -m venv my_env
source my_env/bin/activate

pyenv install 3.7.0
pyenv global 3.7.0
```

python -Vとして3.7.0と表示されない。

## 解決法
前のバージョンで仮想環境を作っていたので、一度clearしておく必要がある。

以下、続けて実行したコマンド

```terminal
deactivate // ←ココ重要　これしないと実行できない
pyenv -m venv --clear my_env // my_envは自分で作った仮想環境のディレクトリ
source my_env/bin/activate
```
これでpython -Vすると、3.7.0と表示された。
ベストプラクティス：DatabricksにおけるHyperoptを用いたハイパーパラメーターチューニング

[Best practices: Hyperparameter tuning with Hyperopt \| Databricks on AWS](https://docs.databricks.com/applications/machine-learning/automl-hyperparam-tuning/hyperopt-best-practices.html) [2021/6/11時点]の翻訳です。

> **注意**
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。

# ベストプラクティス

- ベイジアンアプローチが、グリッドサーチやランダムサーチよりもはるかに効率的な場合があります。このため、HyperoptのTree of Parzen Estimators(TPE)アルゴリズムを用いることで、より多くのハイパーパラメーターやより広い範囲を探索することができます。検索ドメインを制限するためにドメイン知識を用いることで、チューニングを最適化し、より良い結果を得ることができます。
- `hp.choice()`を使う際には、Hyperoptは選択リストのインデックスを返却します。このため、MLflowに記録されるパラメーターもインデックスとなります。パラメーターの値を取得するには、`hyperopt.space_eval()`を使用してください。
- トレーニング時間が長いモデルに対しては、小規模なデータセットと大量のハイパーパラメーターを用いて実験を開始してください。ベストのパフォーマンスを示すモデルと、どのハイパーパラメーターを固定できるのかを特定するためにMLflowを活用してください。このようにして、大規模データでチューニングができるように、パラメーターの空間を削減することができます。
- Hyperoptの条件付き次元、ハイパーパラメーターのサポートを活用してください。例えば、ハイパーパラメーター空間を単に一般的なハイパーパラメーターに限定するのではなく、複数のフレーバーの最急降下法を評価しているのであれば、Hyperoptに、フレーバーのサブセットにのみ適用される条件付きハイパーパラメーターを含めることができます。条件付きパラメーターの詳細に関しては、[Defining a search space](http://hyperopt.github.io/hyperopt/getting-started/search_spaces/)を参照ください。
- `SparkTrials`を使っている際には、CPUクラスター、GPUクラスターそれぞれに適した並列度の設定を行ってください。Databricksにおいて、CPUクラスターとGPUクラスターは、ワーカーノードあたりのエグゼキューターのスレッドの数が異なります。CPUクラスターはノードあたり複数のエグゼキュータースレッドを使用します。GPUクラスターでは、同じGPUを利用しようとする複数のSparkタスクの競合を避けるために、ノードあたり1つのみのエグゼキュータースレッドを使用します。これは、GPU向けに開発されたライブラリにおいては通常最適なものとなりますが、GPUクラスターにおいては最大の並列性が削減されていることを意味し、GPUインスタンスタイプを選択した際には、それぞれのトライアルで使用するGPU数に注意する必要があります。詳細は[GPU\-enabled Clusters](https://docs.databricks.com/clusters/gpu.html)をご覧ください。
- オートスケーリングが有効化されたクラスターで`SparkTrials`を使用しないでください。Hyperoptは処理が開始した時点で並列度を選択します。あとでクラスターがオートスケールしても、Hyperoptは新たなクラスターサイズを活用することができません。

# トラブルシューティング

- lossがNaN(not a number)となる場合、多くの場合`fmin()`に渡された目的関数がNaNを返却したことを意味します。これは他のランに影響せず、問題なく無視することができます。この結果を回避するためには、ハイパーパラメーター空間を調整するか、目的関数を変更してください。
- Hyperoptは確率論的検索アルゴリズムを使用するので、それぞれのランでlossは単調減少しません。しかし、これらの方法は多くのケースで他の方用よりも迅速に最適なはイパーパラメーターを検知します。
- 短期間のトライアル実行において、Hyperopt、Sparkの両方でトライアル期間の大勢を占めるオーバーヘッド(数十秒)が生じます。観測できる速度改善の幅は小さく、場合によってはゼロとなります。

# SparkTrials: サイズの異なるデータセットに対するベストプラクティス

`SparkTrials`はトライアルをSparkワーカーノードで実行します。このノートブックでは、`SparkTrials`を使用する際に異なる規模のデータセットをどのようにワーカーノードに移動すべきかを説明しています。

## 異なる規模のデータを取り扱うサンプルノートブック

https://github.com/taka-yayoi/public_repo/tree/main/hyperopt_best_practice

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
Power AutomateでExcelに書き込もうとしたらBadGatawayが出た

# はじめに
Power AutomateでExcelに行を追加して書き込む処理を実装しているのですが、
ある日突然「BadGataway」とエラーがでて処理が動かなくなってしまいました。
解決したので、同じことでお悩みの方がいらっしゃったら参考になりましたら幸いです。

# どんなエラー？
BadGatawayとエラーには表示されます。詳細は以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/c350d249-af03-c9df-2862-89b4c5fadecb.png)

```
{
  "error": {
    "code": 504,
    "source": "*****",
    "clientRequestId": "*****",
    "message": "BadGateway",
    "innerError": {
      "status": 504,
      "message": "Graph API への要求がタイムアウトになりました。\r\nclientRequestId: *****serviceRequestId: *****",
      "error": {
        "message": "Graph API への要求がタイムアウトになりました。"
      },
      "source": "excelonline-je.azconn-je.p.azurewebsites.net"
    }
  }
}
```

# 原因はなんだったの？
今回の原因は、Excelに数式がたくさん埋め込まれていることでした。
更新対象のテーブルを集計対象にしている数式が、同一Excelの別シートに存在しており、Power Automateで行を追加すると、計算式が自動計算され、そしてその計算にとても時間がかかってしまう関係で、タイムアウトしていたようです。

# どうやって解決したの？
Excelの「数式」-「計算方法の設定」を「手動」に変更することで解決しました。

# おわりに
BadGatawayエラーが出たのは初めてではなく、
以前発生した際はコネクションを変更することで解決したこともありました。
なので、BadGatawayのエラーの原因は様々ですが、参考になりますと幸いです。
暗黙的な内部の Intentを解決したい

Android Studioにて開発を行っております。
課金部分のテストを行うために内部テストとしてリリースを行おうとしておりますが、
セキュリティと信頼性の項目にて「暗黙的な内部の Intent」としてエラーが返ってきております。

こちら該当コード箇所が以下になります。
```
Intent intent = new Intent();
intent.setAction("hoge.hoge.hoge");
intent.putExtra("status", 1);
sendBroadcast(intent);
```

AndroidManifest.xmlにて受信側の宣言として

```
<receiver android:name="com.hoge.app.activity.HogeActivity">
    <intent-filter>
        <action android:name="hoge.hoge.hoge" />
    </intent-filter>
</receiver>
```

というようにブロードキャストレシーバーを宣言しました。
しかし、同じエラー内容ではじかれてしまっております。

こちらどうすれば解決するのでしょうか。
【ラズパイ】監視カメラ？YouTubeライブ配信してみた。

鹿児島でプログラミングスクール講師をやっています。荻原です。
友達がラズパイ（Raspberry Pi 4）を使って遊んでいたのを見て、自分もイジってみたいなと思い購入しました。

今回、挑戦してみたことはラズパイで監視カメラを作ってみた。です。
（難しいことはやってないです。）

購入したラズパイはこちら▼
<img width="400" alt="iOS の画像.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554961/c8a68f15-7d39-d646-1de2-36921a3795a9.jpeg">

Amazonさんリンク
https://amzn.to/3wVBQvS

# 参考記事
Raspberry Piで車載動画をYouTube配信 (第1回)
https://tech.hiyoko.pictures/?p=92
【Raspberry Pi】webカメラを接続する方法
https://hellobreak.net/raspberrypi-webcamera-0511/

# ラズパイでLive配信するために用意したもの
<img width="600" alt="Raspberry.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554961/92dc32c2-c52d-e451-ed9d-548574483c02.jpeg">

* Webカメラ（USBカメラ）
* キーボード
* マウス
* ディスプレイ

# YouTubeライブ配信してみる。
パソコンでYouTubeライブ配信するのと同じです。

<img width="600" alt="youtube1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554961/cb327dfd-3d7a-2b1e-bfa4-3d12a50d2131.png">

<img width="600" alt="youtube2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554961/0d37cc31-10f8-a72e-4177-5741451ff997.png">
今回は、リンクを知っている人だけに見れるように公開設定を『限定公開』にしました。
<img width="400" alt="スマホ.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554961/60bfb090-e690-8b23-7064-660e237f8239.jpeg">
# まとめ
とりあえず、ラズパイをイジってみる。は出来ました。
次回は、コードを書いて定期実行とかできるものを作ってみたいなぁ〜

家族は、ライブで僕を観測できるのは嬉しいみたいですw
<img width="300" alt="iOS の画像.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554961/d1cacb70-9f99-cc48-653c-059d439cd90d.png">
【Salesforce】AppExchangeのアプリケーション開発に関わる環境をまとめてみた。

#はじめに

Salesforceを使用しているとAppExchangeに関わる機会があります。
AppExchangeとは、Salesforceに関わるアプリケーションのマーケットプレイスで、有料・無料のアプリがインストールできます。

企業が公開しているものも多く、無料で使用感を試すことができるものがあるなど非常に便利なサービスです。
https://appexchangejp.salesforce.com/

## 本記事の概要
[弊社](https://www.dialog-inc.com/)はこのAppExchange上でアプリケーションを公開しております。
当初、開発に関わる様々なSalesforceの環境・組織に非常に混乱した記憶があるので、今回はそれをまとめたいと思います。

AppExchangeのアプリケーション開発をご検討されている方の参考になれば幸いです。

## 組織一覧
- **パートナービジネス組織（Partner Business OrgでPBOとも呼ばれる）**
パッケージのライセンス管理や、トライアルをしている組織の本番化（有償に切り替えて、期限を無くすこと）などを行うことができます。
パッケージ開発に関わる一番重要な組織だと思います。

- **パッケージ開発組織**
パートナービジネス組織を使って使って作成する組織です。
いわゆるステージングのような環境として使用でき、スクラッチ組織で開発したコードをデプロイできます。
顧客組織にリリースする前に、一度ここにデプロイをします。
こちらの組織から既にアプリをインストールしている顧客組織へアップグレードをかけたり、初回インストールのURLの発行などもできます。

- **スクラッチ組織（Scratch Org）**
開発時に使う組織で、最大30日間延長することができます。
もちろんインターネットと繋がっていますが、いわゆるローカル環境みたいな感じで使用できます。

- **Trialforce ソース組織（Trialforce Source OrgでTSOとも呼ばれる）**
Trialforceという「トライアルの顧客組織を作成する際のテンプレートを作成する機能」を持った組織です。
テストデータを入れることもでき、顧客の種類に応じて複数用意することができます。


- **顧客組織**
アプリケーションをインストールした顧客が使用する組織です。
新規に作ることもできますし、既存の組織にアプリをインストールしてもらう方法もあります。
AppExchangeでアプリを公開する際は、その場でインストールできるようにするか、会社の方に問い合わせをしてもらうかを選択することもできます。

## まとめ
弊社の場合、既にパートナーとして契約している組織があった上で、こちらの開発に進んだので少しややこしかったです。

開発に関しては多くのSalesforceコミュニティがあったり、ケースのサポートが厚かったりなど非常に相談できる環境が整っていました。
本記事も、挑戦しようとされてる方の一助になれば幸いです。

## 採用に関して
現在、エンジニア採用を積極的に行なっています！このSalesforceのアプリ開発に興味がある方も大歓迎です！
カジュアル面談から可能ですので、是非是非お声がけください〜〜

https://www.wantedly.com/companies/company_3244501/projects
高さが違うコンテナをgridで綺麗に並べる

# 【やりたいこと】
PC、タブレット表示でMasonryっぽい並びをgridレイアウトで実装する。ウィンドウ幅縮小で並び替えはしない。スマホサイズになると昇順で縦に並ぶ。

# 【結果】
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="yLzydQm" data-user="yoshi090" 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/yoshi090/pen/yLzydQm">
  grid layout</a> by yoshida (<a href="https://codepen.io/yoshi090">@yoshi090</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 【解説】
ポイントは以下です。

```css:style.scss
grid-template-areas:
    "a1 a2"
    "a1 a2"
    "a1 a4"
    "a3 a4"
    "a3 a6"
    "a5 a6"
    "a5 a7"
    "a5 a7";
```
エリアの指定を上記のようにすることで左右のコンテナの数や高さが違うものも勝手に揃ってくれます。

```css:style.scss
grid-template-rows: 0.6fr 0.8fr 0.9fr 0.6fr 0.8fr 0.9fr 0.9fr 0.4fr;
```
また上記のrow（行）の高さを編集することで各コンテナの高さも調節できます。
IE11でも同様に表示されます（要ベンダープレフィクス）。

# 【余談】
Flexboxで実装するのは難しそうでした。
例えばスマホでのコンテナの並びが縦に「１→３→５→２→４→６→７」ならば左右でコンテナとして括れるので可能かと思います。
IndexもGSIのパーティションキーも指定しているのにQuery condition missed key schema elementと言われるとき

FilterExpressionに入れるべき内容がKeyConditionExpressionに入っていませんか?

こういう場合

```js
const res = await docClient.query({
    TableName: "SampleTable",
    IndexName: "Value-Key-index",
    KeyConditionExpression: "#v = :v and #f = :f",
    ExpressionAttributeNames: {
        "#v": "Value",
        "#f": "f1",
    },
    ExpressionAttributeValues: {
        ":v": "hogehoge",
        ":f": "v1",
    },
}).promise();
```

```jsonc
{
  "errorType": "ValidationException",
  "errorMessage": "Query condition missed key schema element: Key",
  "trace": [
    // ...
  ]
}
```

GSIのパーティションキーは入ってる, Indexも指定しているパターンで起こります. 思っているエラー文と全然違うので解決がうまいこといきにくいですね.

FilterExpressionに入れ直してあげましょう.

```js
const res = await docClient.query({
    TableName: "SampleTable",
    IndexName: "Value-Key-index",
    KeyConditionExpression: "#v = :v",
    FilterExpression: "#f = :f", // <= ここ
    ExpressionAttributeNames: {
        "#v": "Value",
        "#f": "f1",
    },
    ExpressionAttributeValues: {
        ":v": "hogehoge",
        ":f": "v1",
    },
}).promise();
```
IDE上でiOSのアプリ起動ができなくなった場合のtips

この場合、IDEの実行ボタンではなくコンソールで`flutter run`すると起動できます。
※こんなエラーが出ます

```
Launching lib/main.dart on iPhone 11 Pro Max in debug mode...
Warning: CocoaPods is installed but broken. Skipping pod install.
  You appear to have CocoaPods installed but it is not working.
  This can happen if the version of Ruby that CocoaPods was installed with is different from the one being used to invoke it.
  This can usually be fixed by re-installing CocoaPods. For more info, see https://github.com/flutter/flutter/issues/14293.
To re-install:
  sudo gem install cocoapods

CocoaPods not installed or not in valid state.
```

## 結論
IDEをコンソールから起動してください。（`open /Applications/Android\ Studio.app`）
原因はあまり深く追っていないので正確にはわからないのですが、
GUI経由で起動した場合とTerminal経由で起動した場合でPATHの読み込み結果が変わってしまうらしく、以降名前解決が上手く出来なくなってしまうことに寄るらしいです。

## 奮闘記録
### IDEを変えてみる
`IntelliJ IDEA` → `Android Studio` → `VSCode`
事象全く変わらず。

### XCodeのビルドが通るのか試してみる
通らない。同じエラーが出る。

### rbenvではなくシステムのrubyに切り替える
`m1 mac` × `rbenv` × `cocoapods`の組み合わせが悪いらしい。
rbenvをアンインストールしてシステムのrubyに切り替え、homebrewでcocoapodsをインストールし直す。
事象全く変わらず。
npm実行時に /usr/bin/env: ‘bash\r’: No such file or directory

# 事象
WindowsでWSLでnpm実行時に下記エラーが発生。

```
$ npm -v
/usr/bin/env: ‘bash\r’: No such file or directory
```

コマンドプロンプトでは問題ない。

```
>npm -v
8.1.0
```

# 原因
WSL上では、Windowsにインストールしたものは稼働せず、WSL実行用にインストールが必要。

# 対応
https://docs.microsoft.com/ja-jp/windows/dev-environment/javascript/nodejs-on-wsl

上記リンクに従い実行

nvmのインストール

```
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
```
※2022/1/25 現在、最新バージョンの nvm は、v0.39.1 必要に応じてバージョン番号を書き換える

確認

```
$ command -v nvm
nvm
```

Node.js LTS版 インストール

```
$ nvm install --lts
```

確認

```
$ nvm ls
->     v16.13.1
default -> lts/* (-> v16.13.1)
iojs -> N/A (default)
unstable -> N/A (default)
node -> stable (-> v16.13.1) (default) 
stable -> 16.13 (-> v16.13.1) (default)
lts/* -> lts/gallium (-> v16.13.1)
lts/argon -> v4.9.1 (-> N/A)
lts/boron -> v6.17.1 (-> N/A)
lts/carbon -> v8.17.0 (-> N/A)
lts/dubnium -> v10.24.1 (-> N/A)
lts/erbium -> v12.22.7 (-> N/A)
lts/fermium -> v14.18.2 (-> N/A)
lts/gallium -> v16.13.1
$ npm --version
8.1.2
```

実行できるようになった。
huskyとlint-stagedを使ってlint errorが発生していたらcommitできないようにしよう

パーソンリンクアドベントカレンダー6日目の記事です！

# 前提
- eslintは導入済み

以下のようなディレクトリ構成で行いました。

```
.
├── front
└── server
```

# 手順

まず`front`配下でライブラリのインストール

```
yarn add -D husky lint-staged
```

### huskyの初期化コマンドの実行

```
npx husky-init && yarn
```

### `package.json`をカスタマイズ

```
{
  "scripts": {
    ...
    "lint": "eslint . --ext ts --ext vue --ext js",
    "prepare": "cd .. && husky install front/.husky",
    "lint-staged": "lint-staged"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.@(ts|tsx|vue)": [
      "yarn lint"
    ]
  }
}
```

### 下記コマンドを実行
```
yarn prepare
```

### 自動生成された`.husky`ディレクトリ配下に`pre-commit`というファイルを作成する
下記の様に記述

```:pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
cd front
yarn lint-staged
```

最後に下記を実行

```
cp -r ./front/.husky .
```


# ポイント
`package.json`と`.git`のディレクトリが同階層にいないと正常に実行されない為、度々`cd front`が挟まれていました。
実際に`pre-commit`を実行しないと行けないため、最終的にroot階層に`.husky`を`cp`しました。

# 動作確認

```shell
MacBook-Pro:front $ git commit -m "test"
yarn run v1.22.17
$ lint-staged
✔ Preparing...
⚠ Running tasks...
  ❯ Running tasks for *.@(ts|tsx|vue)
    ✖ yarn lint [FAILED]
↓ Skipped because of errors from tasks. [SKIPPED]
✔ Reverting to original state because of errors...
✔ Cleaning up...

✖ yarn lint:
error Command failed with exit code 1.
$ eslint . --ext ts --ext vue --ext js /Users/user_name/project/example-project/front/components/common/Container.vue

/Users/user_name/project/example-project/front/components/common/Container.vue
  1:1  error  Component name "Container" should always be multi-word  vue/multi-word-component-names

✖ 1 problem (1 error, 0 warnings)

info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
husky - pre-commit hook exited with code 1 (error)
```

commit前に`yarn lint-staged`が実行されており、lint errorが発生している為、commitできないのが確認取れました。

VSCodeでも実際にエラーが出ていることが確認取れました。

![スクリーンショット 2021-12-02 10.46.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518141/f2d1a434-f454-54b2-121b-ce92bf7c6a4d.png)



これでコードレビュー時にlint errorに怯えなくて済みます。。。

# 参考
https://typicode.github.io/husky/#/
https://zenn.dev/seya/articles/c908d88df0a587
https://kic-yuuki.hatenablog.com/entry/2019/05/27/090515
console.log(typeof null)の出力結果に自信のない人は読んでください

[タイムリープTypeScript 〜TypeScript始めたてのあの頃に知っておきたかったこと〜](https://qiita.com/advent-calendar/2021/timeleap-typescript) の7日目の記事になります。
よろしくお願いします。

# 問題
突然ですが問題です。
下記のコードの出力結果は何になるでしょうか？

 ```typescript
console.log(typeof null);
```

正解は、、、`"object"` です。
`"null"`じゃないの？って思った方がこの記事の読者です♪

# なぜなのか
**初期から存在するJavascriptのバグ**[^1]です。
嘘だと思うかもしれませんが、本当なんです。
どういうことなのか説明します。

初期のJavascriptでは、値を32bitで表現していました。
最初の3bitでデータのタイプを表現し、残りのbitでデータを表現していました。
イメージとしてはこんな感じでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123126/59623da5-49f3-39cd-ab39-bc649141d029.png)

そして、データのタイプとしては下記の5つが定義されていました。

- 000: object
- 1: int
- 010: double
- 100: string
- 110: boolean

お気付きでしょうか？nullがありません。
実は、nullはタイプとして定義されておらず、objectタイプのデータがすべて0という形で表現されていました。
そのため、タイプとしては存在しないのです。
イメージとしてはこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123126/b5ec73a4-e4ef-ebd7-4943-474406f29b37.png)

ではnullはobjectなのかというと、そういう意図でこの実装になっている訳ではないようです。
ではどういう訳かというと、Javascriptの最初のバージョンで納期に追われて生まれたバグだそうです。[^2]
その後、修正する流れもあったようなのですが、互換性の問題などから修正されずに現在に至るそうです。[^3]
そのため、`typeof null`は`"object"`となる訳です。

以上になります。
最後までお読みいただきありがとうございました。

[^1]: bugという表現は[The history of “typeof null”](https://2ality.com/2013/10/typeof-null.html)の表現を拝借しています。
[^2]: [The history of “typeof null”](https://2ality.com/2013/10/typeof-null.html)の下記の表現を拝借しています。
    > This may seem like a very obvious bug, but don’t forget that there was very little time to finish the first version of JavaScript.
[^3]: [typeof_null](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/typeof#typeof_null)とリンク先の表現を拝借しています。
    > ECMAScript の修正案が (オプトインを使用して) 提案されましたが、却下されました。それは typeof null === 'null' という結果になるものでした。
flutter doctorでAndroid license status unknownになった場合の対処法

### `flutter doctor`した時にこのようなエラーが出るケースがある
```
❯ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.5.2, on macOS 11.6 20G165 darwin-arm, locale ja-JP)
[!] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] Android Studio (version 2020.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2021.2.2)
[✓] IntelliJ IDEA Ultimate Edition (version 2021.2.2)
[✓] VS Code (version 1.60.2)
[✓] Connected device (3 available)

! Doctor found issues in 1 category.
```

### `flutter doctor --android-licenses`を実行してみる
```
❯ flutter doctor --android-licenses

ERROR: JAVA_HOME is set to an invalid directory: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation.
```

### javaを入れてJAVA_HOMEを有効にする
ここで指定するjavaのバージョンは恐らくAndroid SDKのversionと関係しているのかと予想。
`/android/app/build.gradle`に記載があるので対応するjavaのバージョンが何かを調べてみても良さそうです。

```
$ brew tap homebrew/cask-versions
$ brew install adoptopenjdk8 --cask
$ echo JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home >> ~/.zshrc
```
美男美女＋ゆりやんレトリィバァを使って解説するオブジェクトとは


流行りのフレームワークを使っていると忘れがち（意識しなくてよい）JS の基礎を学び直してみた。

<h2>オブジェクト指向とは</h2>
直訳するとオブジェクトはモノ。しかしこれではあまりに分かりにくいですよね。
要約すると「現実世界のものに見立ててプログラミングをする方法」になります。

これでも想像つきにくいですよね。つまりこのオブジェクトを使って、わかりやすくプログラミングするよというふわっとした意味らしいです。

※

```javascript
{
  name: '菅田将暉';
  age: 28;
  job: 'actor';
}
```

そして、このオブジェクトを作る方法が 2 パターンあります。

<h5>★オブジェクトリテラル</h5>
リテラルというのは文字通りという意味です。これはいつも何気なく使っている書き方です。

```javascript
const person = {
  name: '菅田将暉',
  age: 28,
  job: 'actor',
};
```

<h5>★クラス</h5>

クラスというのは
・オブジェクトの設計図
・クラスから作られたオブジェクトはインスタンスと呼ばれる

とりあえず見ていきましょう。

例

```javascript
class Person {
  constructor(initName, initAge, initJob) {
    (this.name = initName), (this.age = initAge), (this.job = initJob);
  }
}
```

こういった形でクラスを定義します。

この設計図を使うには new というものを用いて、

```javascript
const masaki = new Person('菅田将暉', 28, 'actor');
```

と書くと、※で示したオブジェクト同じものが出来上がります。

この設計図からオブジェクトを作ることをインスタンス化と呼び、この masaki がインスタンスと呼ばれます。（インスタンスという名前は付きましたがオブジェクトです。）

同じもの作るのに、なぜクラスなんか使わなくてはいけないの？と思った方もいるかもしてません。

理由は簡単、クラスは何回も使いまわしできるからです。設計図と呼ばれる所以かもしれません

例えば、

```javascript
const nana = new Person('小松奈菜', 25, 'actress');
```

```javascript
const Mackenyu = new Person('新田 真剣佑', 25, 'actor');
```

という新しいインスタンスも、簡単に作れてしまうわけです。いまは、オブジェクトのプロパティ（オブジェクトの中の情報）が３つしかないので、そのまま書いてもさほど大変ではありませんが、これが１０個もあったりしたら、オブジェクトを３つ作るだけでも、大変ですよね。設計図を書いておけば、情報さえ渡してやれば、いくつも短い記述量でオブジェクトが作れるようになります。

<hr>

この記事でクラス、インスタンス、コンストラクタあたりを詳しく書いたので、参考にしてみてください。

https://qiita.com/t_109609akg/items/974a2c07b0e61d3049bf

<hr/>

・クラスの継承

例えば、芸人さんの設計図　[class Comedian]を作るとします。

```javascript
class Comedian {
  constructor(initName, initAge, initJob, initCompany) {
    (this.name = initName),
      (this.age = initAge),
      (this.job = initJob),
      (this.company = initCompany);
  }
}
```

これでもクラスは作ることができますが、同じようなことを二回書くのはナンセンスですよね。

そこでクラスには、継承という機能があります。

```javascript
class Comedian extends Person {}
```

これで Person クラスを継承できました。

```javascript
class Comedian extends Person {}

const suda = new Comedian('菅田将暉', 28, 'actor');
```

こう書けば、※と同じオブジェクトができます。（クラスは芸人さんですが。）

この Person クラスを継承して所属事務所を付けたすと

```javascript
class Comedian extends Person {
  constructor(initName, initAge, initJob, initCompany) {
    // 親クラスのコンストラクタを呼び出す
    super(initName, initAge, initAge);
    this.company = initCompany;
  }
}
```

こうかく

そしてインスタンス化すると

```javascript
const yuriyann = new Comedian(
  'ゆりやんレトリィバァ',
  31,
  'comedian',
  '吉本興業'
);
```

と書くことができます。

これは

```javascript
const yuriyan = {
  name: 'ゆりやんレトリィバァ',
  age: 31,
  job: 'comedian',
  company: '吉本興業',
};
```

というオブジェクトと同じものが出来上がります。