OmniAICreator/Qiita-1.07M huggingface dataset:
GitLabコンテナーレジストリーからHarborへDockerイメージをレプリケーションする

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. はじめに

GitLab.comのコンテナーレジストリーに保存されたDockerイメージをHarborでレプリケーションしようとしました。
Google先生に聞いてもドキュメントが少なく、いろいろと突っ掛かってしまったので備忘録的に書き留めておきます。

# 1. 前提条件

Harborのバージョン: Version v2.3.3-a0a9ed8a
Harborの実行Kubernetes: k3s version v1.19.15+k3s2 (0fbbc5af)
GitLabのバージョン: GitLab Enterprise Edition 14.4.0-pre(オンプレのGitLab CE,EEでも恐らく大丈夫)

# 1. GitLab.com側の準備

以下のURLでパーソナルアクセストークンを発行する

パーソナルアクセストークン · ユーザー設定 · GitLab
https://gitlab.com/-/profile/personal_access_tokens

パーソナルアクセストークンを発行するときのポイントは、`Select scopes`を以下の2つを付与します。
- read_api
- read_registry

※今回は、GitLab.com --> オンプレHarborへのレプリケーションだったので、「write_registry」は付けませんでした。
　オンプレHarbor --> GitLab.com(またはGitLab)の場合は、write_registryにもチェックを付けてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/f66963f3-9056-5806-df81-6a5c4afcb1db.png)

# 2. Harbor側の設定

## 2-1. Registryへ登録

Endpointを登録します。

1. Providerは`Gitlab`を選択
2. Nameは任意
3. Endpoint URLを`https://registry.gitlab.com`にします
4. Access IDには、1で取得したパーソナルアクセストークンのIDを入れます
5. Access Secretには、1で取得したパーソナルアクセストークンのSecretをいれます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/b85d1312-f287-319f-4bd6-9b92fb1c5b1d.png)

「TEST CONNECTION」をクリックして接続できることを確認します。

## 2-2. レプリケーション設定

レプリケーションを作成します。

「NEW REPLICATION RULE」をクリックして、ダイアログに「Name」を入力して「Replication mode」を`Pull-based`に変更します。
Source registryに、registry.gitlab.comを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/f66a6c33-381f-a2f6-b62b-5e7a165bafd7.png)

Source resouce filterは、レプリケーションしたいプロジェクト配下のリポジトリ名を指定します。
Nameの指定方法は、`<プロジェクト名>/<レジストリ名>/<イメージ名>`で指定します。
Tagの指定方法は、latest等の特定のTagを指定する方法もありますが、ワイルドカードで指定するには**を使います。

GitLab Container Registryで、ディレクトリがネストしている場合は、以下のようにします。
`<プロジェクト名>/<レジストリ名>/<イメージ名>/<ディレクトリ名>/**`

また、レジストリ配下のコンテナイメージを全て取得する場合は、以下のようにします。
`<プロジェクト名>/<レジストリ名>/**`

Nameで指定するのは、コンテナー名までです。イメージ名の`:`以降のタグは、Tag:に記載します。
こちらもワイルドカードは `**`です。

レプリケーション先を`Destination`で指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/eb2d2b3f-0ff5-c66d-59c8-dc4fe343d390.png)

# 3. レプリケーションの実行

レプリケーションを保存したらレプリケーションしたいルールを選択して「REPLICATE」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/e6842654-c98b-1419-6e1d-b65ca1d0b770.png)
ros1_bridgeでROS NoeticとROS2 Galacticの通信

# はじめに
ros1_bridgeでROSとROS2の最新ディストリビューションであるNoeticとGalacticを通信させた記事がなかったのでメモ
基本的にgithubのREADME通り
ros1_bridgeについては参考にある記事を参照のこと

https://github.com/ros2/ros1_bridge



# 環境

OS：ubuntu20.04.3LTS
ROS：Noetic
ROS2：Galactic

同じubuntu20.04にNoeticとGalacticが両方インストールされている環境を想定

# 概要
ROS Noeticでpublishした`/chatter`トピックをROS2 Galacticでsubscribeする


# ros1_bridgeのインストール

```bash
$ sudo apt install ros-galactic-ros1-bridge
```


# ROS 側の準備

std_msg/String型のトピックをpublishするノードを作成、ROS TutorialのPublisher側プログラムを使用

http://wiki.ros.org/ja/ROS/Tutorials/WritingPublisherSubscriber%28python%29


```python:talker.py
#!/usr/bin/env python3
import rospy
from std_msgs.msg import String

def talker():
    pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)
    r = rospy.Rate(10) # 10hz
    while not rospy.is_shutdown():
        str = "hello world %s"%rospy.get_time()
        rospy.loginfo(str)
        pub.publish(str)
        r.sleep()

if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException: pass
```

# 実行

### ターミナル1

ROS Noeticでroscoreを起動

```bash
$ source /opt/ros/noetic/setup.bash
$ roscore
```

### ターミナル2

ROS NoeticとROS2 Galactic両方の環境をロードしてros1_bridgeを実行

```bash
$ source /opt/ros/noetic/setup.bash
$ source /opt/ros/galactic/setup.bash
$ export ROS_MASTER_URI=http://localhost:11311
$ ros2 run ros1_bridge dynamic_bridge
```

実行画面

```bash
created 2to1 bridge for topic '/rosout' with ROS 2 type 'rcl_interfaces/msg/Log' and ROS 1 type 'rosgraph_msgs/Log'
created 1to2 bridge for topic '/chatter' with ROS 1 type 'std_msgs/String' and ROS 2 type 'std_msgs/msg/String'
[INFO] [1633905352.305453175] [ros_bridge]: Passing message from ROS 1 std_msgs/String to ROS 2 std_msgs/msg/String (showing msg only once per type)
[INFO] [1633905352.306387924] [ros_bridge]: Passing message from ROS 2 rcl_interfaces/msg/Log to ROS 1 rosgraph_msgs/Log (showing msg only once per type)
```




### ターミナル3

ROS Noeticでtalkerを実行

```bash
$ source /opt/ros/noetic/setup.bash
$ python3 talker.py
```

実行画面

```bash
[INFO] [1633905191.352062]: hello world 1633905191.3518636
[INFO] [1633905191.452340]: hello world 1633905191.452095
[INFO] [1633905191.552324]: hello world 1633905191.5520732
[INFO] [1633905191.652243]: hello world 1633905191.6520474
```


### ターミナル4

ROS2 Galacticでlistenerを実行

```bash
$ source /opt/ros/galactic/setup.bash
$ ros2 run demo_nodes_cpp listener
```

実行画面

```bash
[INFO] [1633905246.313638841] [listener]: I heard: [hello world 1633905246.3101022]
[INFO] [1633905246.413807904] [listener]: I heard: [hello world 1633905246.4104435]
[INFO] [1633905246.514000744] [listener]: I heard: [hello world 1633905246.5106533]
[INFO] [1633905246.613886751] [listener]: I heard: [hello world 1633905246.6104968]
```



# 参考


https://gbiggs.github.io/rosjp_ros2_intro/ros1_bridge.html

https://qiita.com/kei_mo/items/c4c39bce051dd9dacc3c



























#
新人が単体テストの項目を洗い出すときに覚えておくといい点

初投稿です。
新入社員として配属となってからはや5ヶ月。
研修と案件で学んだことがたくさんあり、アウトプットをする機会に投稿してみようと思いました。

完成形は新人はこれくらいやっていれば大丈夫という記事になれば良いなと思います。
足りない部分などありましたら、ご意見の程くれると非常にありがたいです。

※こちらはサイトを作ろうとしている方向けの記事です。

さて本題ですが、今回は**単体テスト項目の洗い出し**の観点について話していこうと思います。

#テストの意義とは
**テストをする意味はバグを検出する。**というのが目的です。
めんどくさくなり、項目を消化することが目的となってくる人がいますが、それはよくありません。
研修だと自分一人で成果物を作り、テストするというのをやる人が多いかと思いますがやればやるほどほどこの思考に陥りやすいです。
なので、**絶対にエラーを出してやる**という意識でテストしてください。
**項目の消化**ではありません。

#どのようにテスト漏れがない仕様書を作るか
考えていたのに、書き忘れた。
指摘をもらって思い出した。

というケースが非常に多いです。
私も教育担当の方に散々言われてきました。
このような事態に陥らないように、思考の整理をしなくてはならないです。

私が常に意識していることは

**①どの部分を見ていくか書き起こす**
**②どのようなテストをするかパターンをまとめる**
**③仕様書に書き起こす**

※パターンとは
例えば数量を入力する入力欄があります。
そこに対してどのようなテストをしていくか
数値だけ入力できるか、何桁まで入れられるかといった具合です。

という流れで仕様書を書いています。

パターンと仕様書同じでは？と思った人もいるかもしれないですが、一度この工程を踏むとミスが圧倒的に少なくなります。

重要なのは、①②③の各フェーズごとにレビューをお願いすることです。

自分だけの判断では、漏れがないことを見つけるのはほぼ不可能です。
自分のために時間を使ってくれる上司、トレーナー、教育担当者の方々の力を借りましょう。

新人の仕事に置いて重要なのは、**聞くこと**です。
勇気が出ない、忙しそうにしていると色々な状況があるかもしれないですが、後々テストの漏れが見つかった際はそれどころじゃ済まないです。
聞くことを怠り、失敗し配属先を変更させられた新人いるくらい大切なことなので、聞いていく習慣を心がけましょう。

そして聞いたことを出来るだけアウトプットして、記憶を定着させましょう。すると伸び率が他の新人より段違いで進みます。

#実際どんなところを見ていけばいいの？
基本単体テストは、ブラックボックス視点で行うことが多いです。
なので最低限ブラックボックステストでは、ここを見ておけばいい部分をあげておきます。

##検索部分
・絞り込みができているかどうか　（完全一致、前方一致、部分一致など）
・検索結果は正しいかどうか（表示されている値と登録されている値に差異はないか）
・項目が多いのであれば、組み合わせ網羅（2因子間網羅）
・チェックボックス　正常にチェックが入れられるかどうか
・プルダウンリスト　選択肢が正常に表示されているかどうか
・ラジオボタン　こちらも選択肢が正しく表示されているかどうか

##登録・更新部分
・文字列チェック
・数値チェック
・記号チェック
・全角カナかな
・全角英数字
・全角記号
・半角英数字
・半角カナかな
・半角記号
・重複チェック
・桁数チェック
・バイト数チェック(同値,境界値)
・開発者ツールで値の変更
・表示項目は登録されているものと表示されているものは同じかどうか
・エラーが起きた時、入力された値が保持され、そのまま表示されているかどうか　※下記に補足アリ


※補足説明
こちらはお問い合わせフォームなどを想像してください。
一つの項目だけ入力を間違えてしまっただけなのに今までの入力がすべて消えてしまうことがあると正直面倒です。それを防ぎましょう。


##表示項目
・マウス操作、TAB操作で入力できるのか　(テキストボックスなど)
・表示されているものは整合性が取れているのか
・リンクは正常に機能するかどうか
・ボタンは正常に機能するかどうか

##その他
・画面遷移は正しいか
・ログインしないと表示されない画面等ブックマークなどで見れてしまっていないか


これらを試験するときにこれらを意識し、考えていけば最低限の項目は書くことができると思います。

**テストちゃんとできるようになると、かける工数が少なくなり、さらに製造ではどのような観点でコードを書けばいいかわかるので、成果物の品質も上がるようになり一石二鳥です。**
最初は書くのがつらいと思いますが、しっかりやれば後からおつりが出るような作業ですので頑張りましょう。

##最後に
まだ業務について日が浅いですが、学んだことがあれば都度投稿してみようと思います。
[AWS] 作成済みEC2インスタンスのセキュリティグループをAWS SDK for Python(Boto3)で変更する

本記事は「作成済みEC2インスタンスに割り当てているセキュリティグループ」をAWS SDK for Python(Boto3)で変更する方法のメモです。

ここの設定を変更したい：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/68230085-7ed4-4d9f-80ad-a91bc666e51f.png)

# 変更するメソッド

メソッドは [EC2 : modify_instance_attribute()](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Client.modify_instance_attribute) を使用します：

```python
ec2_client = boto3.client('ec2', 'region')
ec2_client.modify_instance_attribute(
     InstanceId = 'string',
     Groups = [
          'string',
     ]
)
```

設定例：

```python
ec2_client = boto3.client('ec2', 'ap-northeast-1')
ec2_client.modify_instance_attribute(
     InstanceId = 'i-0da123456',
     Groups = [
          'sg-35b28551',
          'sg-35b28552'
     ]
)
```

# 関連情報の収集

変更する場合、変更前にインスタンスに設定されているグループIDのリストが必要になることも多いかと思います。その場合は `EC2 : describe_instance_attribute()` メソッドで取得します。

```python
ec2_client = boto3.client('ec2', 'region')
response = ec2_client.describe_instance_attribute(
     Attribute = 'groupSet',
     InstanceId = 'string'
)
```

実行例：

```python
ec2_client = boto3.client('ec2', 'ap-northeast-1')
response = ec2_client.describe_instance_attribute(
     Attribute = 'groupSet',
     InstanceId = 'i-0da123456'
)
for group in response['Groups']:
     print(group['GroupId'])

sg-35b28550
sg-35b28551
```

このグループIDのリストを追加変更して `modify_instance_attribute()` のグループリストに設定する流れとなります。

# 参考資料

- [EC2 : modify_instance_attribute()](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Client.modify_instance_attribute)
- [作成済みのEC2インスタンスにセキュリティグループを追加する](https://qiita.com/scalewallet/items/97e5b841d792ba7d6a65)
- [[AWS] 作成済みEC2インスタンスのセキュリティグループをAWS Tools for PowerShellで変更する](https://qiita.com/VA_nakatsu/items/dfdcb9da1cef6c82adde)
モジュールがないなら（半）自動でインストールすればいいじゃない

Qiitaは今まで見る専だったのですが、情報整理やスキルアップも兼ねて恐る恐る記事を書いてみました。

# 環境
- Windows 10
- Python2.7 及び 3.7
- PyCharm 2020

# 端的にまとめると
長くなってしまったためやったことを端的にまとめると
1. 『pkgutil.iter_modules()』を使用して全モジュールの一覧を取得
2. インストールしたいモジュールの一覧から全モジュール一覧にないモジュール名を抽出
3. 『subprocess.call()』でインストールしたいpipに抽出したモジュール一覧を文字列にして渡す

以上になります。

# こんなことが以前ありました
Python2と3の両方で動く処理を検証する度に別々の仮想環境をPyCharmで作成していてモジュールをインストールしてる時にふと思いました。

「これ、違う環境で度々インストールしなくちゃいけないのどうにかならないかな」
と。

インストールする作業もモジュールを一つ追加するだけなら問題無いとは思います。ですがそれ以上になるともうやってられなくて・・・。


そして思ったわけです。
「自分で作ってみるか・・・？」
と。

# 必要になりそうな要素を挙げていく
- インストールするモジュールの一覧
  - これに関しましては自分で用意すれば良いですね
- インストールされているモジュールの一覧
  - 既にインストールされているモジュールのことを考えるとこれをどうするかが鍵

## インストールされているモジュールの一覧を取得してみる
公式ドキュメントを探した結果『pkgutil.iter_modules』を使うことで読み込めるモジュールの情報を取得出来そうなのでそこから一覧を抽出してみます。

```
import pkgutil

pkg_list = [pkg for pkg in pkgutil.iter_modules()]
```

取得したリストの中を見てみると1番目にモジュール名っぽいのが格納されているのを確認出来ました。ということなので以下のようにしてみました。

```
import pkgutil

pkg_list = [pkg[1] for pkg in pkgutil.iter_modules()]
```

## インストールしたいモジュールの一覧として抽出してみる
では次にインストール処理を無駄に走らせない為にインストールされているモジュールを除いたリストを作成してみます。

```
important   = [] # インポートしたいモジュール名のリスト
import_list = [i for i in important if i not in pkg_list]
```

これでリストが出来ました。それでは作成したリストからpipに渡す引数の文字列を作成してインストールができるか走ってもらいます。

## pipでモジュールをインストール
subprocessモジュールを使ってpipでインストールする際の記述をします。

```
import sys
import subprocess

if len(import_list) > 0:
    subprocess.call("{} -m pip install {}".format(sys.executable.replace("\\", "/"), " ".join(import_list)))
```

こんな感じになりました。今実行しているPythonの環境に紐づいているpipにインストールしたいのでsys.executable関数を使用してPythonの実行ファイルパスを取得してます。

# 結果
処理を走らせた後にpipのモジュール一覧を見てみるとモジュールをきちんとインストールできてることが確認できました。

## おまけ
試しにこれらの処理の後にpipにインストールしたモジュールをインポートする記述をした上で処理を走らせてみましたが問題なく動く模様。
git エディタをつかいこなす

# Gitコミットしたけど抜け出すことができなくなったら

- `ESC`キーを押す。
- `:`を入力する
- `wq`を入力して抜け出す。

## モードを変える

gitにて`index.html`ファイルを編集するとする。

```
vim index.html
```

- `i`でインサート（編集）モード
[AWS] 作成済みEC2インスタンスのセキュリティグループをAWS Tools for PowerShellで変更する

本記事は「作成済みEC2インスタンスに割り当てているセキュリティグループ」をAWS Tools for PowerShellで変更したい場合のコマンドメモです。

ここの設定を変更したい：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/68230085-7ed4-4d9f-80ad-a91bc666e51f.png)

# 変更するコマンド

コマンドは [Edit-EC2InstanceAttribute Cmdlet](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceAttribute.html) を使用します：

```powershell
Edit-EC2InstanceAttribute -InstanceId <String> -Group <String[]>
```

実行例：PowerShellに不慣れだと間違えやすいですが、リストは `@()` 形式での指定になります。

```powershell
Edit-EC2InstanceAttribute -InstanceId 'i-0da123456' -Group @( 'sg-35b28551', 'sg-35b28552' )
```

# 関連情報の収集

変更する場合、変更前にインスタンスに設定されているグループIDのリストが必要になることも多いかと思います。その場合は `Get-EC2InstanceAttribute` コマンドで取得します。

```powershell
Get-EC2InstanceAttribute -InstanceId <String> -Attribute 'groupset'
```

実行例：

```powershell
$current_sgs = Get-EC2InstanceAttribute -InstanceId 'i-0da123456' -Attribute 'groupset'
foreach($group in $current_sgs.Groups) {
     $group.GroupId
}

sg-35b28550
sg-35b28551
```

このグループIDのリストを追加変更して `Edit-EC2InstanceAttribute` の引数に設定する流れとなります。

# 参考資料

- [Edit-EC2InstanceAttribute Cmdlet](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceAttribute.html)
- [Get-EC2InstanceAttribute Cmdlet](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2InstanceAttribute.html)
- [作成済みのEC2インスタンスにセキュリティグループを追加する](https://qiita.com/scalewallet/items/97e5b841d792ba7d6a65)
VSCODE season1



```
{
  "ruby.codeCompletion": "rcodetools",
  "workbench.colorTheme": "Atom One Dark",
  "breadcrumbs.enabled": true,
  "editor.cursorBlinking": "blink",
  "editor.hideCursorInOverviewRuler": true,
  "editor.minimap.enabled": false,
  "editor.occurrencesHighlight": false,
  "editor.renderIndentGuides": false,
  "editor.roundedSelection": false,
  "editor.scrollBeyondLastLine": false,
  "explorer.decorations.colors": false,
  "editor.renderWhitespace": "all",
  "editor.insertSpaces": false,
  "explorer.openEditors.visible": 0,
  "workbench.activityBar.visible": true,
  "workbench.editor.showIcons": true,
  "workbench.startupEditor": "none",
  "workbench.iconTheme": "vscode-icons",
  "settingsSync.ignoredSettings": [],
  "settingsSync.ignoredExtensions": [],
  "eslint.autoFixOnSave": true,
  "tslint.autoFixOnSave": true,
  "prettier.eslintIntegration": true,
  "prettier.tslintIntegration": true,
  "files.trimTrailingWhitespace": true,
  "atomKeymap.promptV3Features": true,
  "editor.multiCursorModifier": "ctrlCmd",
  "editor.formatOnPaste": false,
  "workbench.tree.indent": 16,
  "explorer.confirmDragAndDrop": false,
  "diffEditor.ignoreTrimWhitespace": false,
  "[json]": {
    "editor.quickSuggestions": {
      "strings": true
    },
    "editor.suggest.insertMode": "replace"
  },
  // "vs-kubernetes": {
  //   "vs-kubernetes.helm-path.mac": "/Users/iidayosuke/.vs-kubernetes/tools/helm/darwin-amd64/helm",
  //   "vs-kubernetes.minikube-path.mac": "/Users/iidayosuke/.vs-kubernetes/tools/minikube/darwin-amd64/minikube",
  //   "vs-kubernetes.draft-path.mac": "/Users/iidayosuke/.vs-kubernetes/tools/draft/darwin-amd64/draft"
  // },
  // "editor.suggestSelection": "first",
  // "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
  // "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx1G -Xms100m -javaagent:\"/Users/iidayosuke/.vscode/extensions/gabrielbb.vscode-lombok-1.0.1/server/lombok.jar\"",
  // "java.home": "/Library/Java/JavaVirtualMachines/jlw_std_api/Contents/Home/"
  "workbench.editor.enablePreview": true,
  "files.exclude": {
    "**/.classpath": true,
    "**/.project": true,
    "**/.settings": true,
    "**/.factorypath": true
  },
  // "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx1G -Xms100m -javaagent:\"/Users/iidayosuke/.vscode/extensions/gabrielbb.vscode-lombok-1.0.1/server/lombok.jar\"",
  "editor.suggestSelection": "first",
  "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "eslint.migration.2_x": "off",
  "editor.formatOnType": false,
  "C_Cpp.updateChannel": "Insiders",
  "liveshare.authenticationProvider": "GitHub",
  "editor.wordWrap": "on",
  "security.workspace.trust.untrustedFiles": "open",
  "editor.tabSize": 2,
  "javascript.updateImportsOnFileMove.enabled": "always",
  "editor.formatOnSave": true
}
```
レプリケーションファクタ とは

## 勉強前イメージ

ただのレプリケーションではない？

## 調査

### レプリケーションファクタ とは

英語ではReplication Factor と書き
意味はコンテナ上で扱うデータの冗長性を表します。
複数ノードを使用するデータの構造であれば、ノードを跨いでデータをコピーするので
特定ノードに障害が起きてもデータが損失することはありません。
クラスタの中でデータのコピーをいくつ持つかによって
いくつノードが障害が起きても稼働し続けるか というものになります。

図にすると以下になります。

レプリケーションファクタ2だと1台壊れても稼働ができる。
レプリケーションファクタ3だと2台壊れても稼働ができます。

![1# レプリケーションファクタ とは - diagrams.net - Google Chrome 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/e47ce4a1-ab55-e2c6-efb1-70febb640446.png)


ただし、データコピーを多く持つと障害には強いですが
ディスクの利用効率が悪いので利用する際はきちんと考える必要があります。

## 勉強後イメージ

他のアプリケーションだと別の用語だけどよく使われるよね。
全般的な考え・用語ってことなのかな？

## 参考

- [RF（レプリケーションファクター）](https://www.networld.co.jp/sp/learn_first/backup/2nd/p28.html)
Angularのセレクトボックス に初期値を入れる時につまづいた話

#1. 背景
Angularを使ったアプリの拡張開発を行っていた時に、プルダウン形式のセレクトボックスに初期値を入れようとしたところ、なかなかうまくいかず悩みました。
参考のサイトも調べつつ、今回のやり方でうまく行きました。

#2. 結論
結論から言うと、最初のform-controlの箇所で、ngModelにプルダウンのvalueとは別の変数を入れてあげることで解消しました。

```
#sample.component.html
<select id="sample" [(ngModel)]="defaultValue">
  <option [value]="undefined">初期値</option> → ここのテキスト文が初期値として表示される
  <option *ngFor="let sampleValue of sampleValues" [value]="sampleValue">
    {{sampleValue}}
  </option>
</select>

#sample.component.ts
public defaultValue = undefined; → ここの変数とngModelで指定する変数を合わせる
public sampleValues: string[] =[
    'value1', 'value2', 'value3'
];
```
docker-compose で不思議なエラー

当方、mac os Catalina 10.15.7（19H2）+Docker desktop

よくわかっておりませんが・・
Dockerでselenium動かしてるんだけど
docker-compose up -d
したら以下のようなエラーが発生し起動できず・・

```
$ docker-compose up -d
WARNING: Some networks were defined but are not used by any service: backend
Starting pppp1 ... error

ERROR: for pppp1  Cannot start service pppp1: error while creating mount source path '/host_mnt/private/var/db/timezone/tz/2021a.1.0/zoneinfo/Asia/Tokyo': mkdir /host_mnt/private/var/db/timeStarting pppp1  ... done

ERROR: for pppp1  Cannot start service pppp1: error while creating mount source path '/host_mnt/private/var/db/timezone/tz/2021a.1.0/zoneinfo/Asia/Tokyo': mkdir /host_mnt/private/var/db/timezone/tz/2021a.1.0: operation not permitted
ERROR: Encountered errors while bringing up the project.
```

権限ないんかな・・

調べてみると
/private/var/db/timezone/tz/2021a.2.0
というディレクトリはあるので、

```
sudo cp -rfp /private/var/db/timezone/tz/2021a.2.0 /private/var/db/timezone/tz/2021a.1.0
```

としてやったら
docker-compose up -dが正常に動いて起動した

よくわかっておりません・・


追記
2022/7/10時点ではこうしなきゃでした
```
sudo cp -rfp /private/var/db/timezone/tz/2022a.1.0 /private/var/db/timezone/tz/2021a.3.0
```
VSCodeのTodo Treeが良かった話

#はじめに
当方、日々の開発にはVSCodeを使っています。
カスタマイズするのも楽しみの一つですが、今回紹介するTodo Treeがすごい良かったので良かったら最後まで読んでみてください。

# インストール
こちらからどうぞ

https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree

# こんな感じ
![スクリーンショット 2021-10-13 18.25.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/932783/ba0cd54e-c9b2-48de-eb48-2e1d661fc4dd.png)
任意のワードをコメントアウトすることで発動しそれを一覧に表示することができます。
TODOとFIXMEはデフォルトとして登録されており、setting.jsonに追加することで自分好みのワードやアイコン、色を設定することができます。

一覧のかなのどれかをクリックするとそのファイルに飛ぶことができるので、見失うことはありません。
ノートや付箋などにメモしておくよりは忘れないと感じます。

コメントアウトの扱いに関しては会社、プロジェクトごとに取り決めがあるかと思いますのであまりファイルを汚しすぎない方がいいかもしれません。

# 設定（サンプル）

上の写真の設定は下記のようになります。

```setting.json
  "todo-tree.general.tags": ["FIXME", "NOTE", "TODO", "CHECK"],
  "todo-tree.highlights.defaultHighlight": {
    "gutterIcon": true
  },
  "todo-tree.highlights.customHighlight": {
    "TODO": {
      "icon": "check-circle-fill",
      "foreground": "orange",
      "iconColour": "orange"
    },
    "FIXME": {
      "icon": "flame",
      "foreground": "yellow",
      "iconColour": "yellow"
    },
    "NOTE": {
      "icon": "paintbrush",
      "foreground": "#00bfff",
      "iconColour": "#00bfff"
    },
    "CHECK": {
      "icon": "plus-circle",
      "foreground": "green",
      "iconColour": "green"
    }
  },
```



# アイコンの設定
公式にも書いてありますが、アイコンは下記リンクから好きなものを選んで使用することができます。

https://octicons.github.com

https://microsoft.github.io/vscode-codicons/dist/codicon.html

よかったら参考にしてみてください。
それでは👋
ColabでOpenCV GPUを使いたい

## 概要
* ColabでOpencv GPUを使用する

それだけです。

## はじめに

Colabは無料で使えて、なおかつGPUまで無料で使えるのがいいですよね。
ある時、**「OpencvのGPUバージョンも、もしかしたらColabで使えのでは？」**と思い、方法を探したときの備忘録になります。

## ColabでOpencv GPU

`pip`でインストールできる`opencv-python`や`opencv-contrib-python`では、GPUは使えないですよね<font color="gray">（もし、使えるのであれば僕の苦労が水の泡となってしまう）</font>

なので、1からbuildする必要があります。
また、僕が実験した感じ、opencvのバージョンは最新じゃないとopencvが認識されませんでした。


参考にしたサイトは以下になります。
>* [ColabのGPUでOpenCVを使用する方法は？](https://ichi.pro/colab-no-gpu-de-opencv-o-shiyosuru-hoho-wa-41065314358367)

### コード

まずは、`opencv`と`opencv_contrib`をクローンして来て、buildします。参考サイトのコードそのまま持ってきたので、DNNの部分とかは無くていいですね。

```.sh
!git clone https://github.com/opencv/opencv
!git clone https://github.com/opencv/opencv_contrib
!mkdir /content/build
%cd /content/build
!cmake -DOPENCV_EXTRA_MODULES_PATH=/content/opencv_contrib/modules  -DBUILD_SHARED_LIBS=OFF  -DBUILD_TESTS=OFF  -DBUILD_PERF_TESTS=OFF -DBUILD_EXAMPLES=OFF -DWITH_OPENEXR=OFF -DWITH_CUDA=ON -DWITH_CUBLAS=ON -DWITH_CUDNN=ON -DOPENCV_DNN_CUDA=ON /content/opencv
!make -j8 install
```

割と時間がかかるので、終わったら以下のコマンドで確認

```.py
import cv2
print(cv2.cuda.getCudaEnabledDeviceCount())
```

```
1
```

みたいに使えるデバイスの数が出てきたらOK

一応動作確認として動かしてみます。

```.py
import cv2
from google.colab.patches import cv2_imshow

img_src = cv2.imread("images.png")
img_gpu_src = cv2.cuda_GpuMat()
img_gpu_src.upload(img_src)
img_gpu_dst = cv2.cuda.resize(img_gpu_src, (300, 300))
img_dst = img_gpu_dst.download()
cv2.imwrite("Ξガンダム.png", img_dst)
```

元画像 294×172
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/9ada308f-ba2c-8c04-e61a-748abcbbfd39.png)

変換後 300×300
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/433851bc-f386-9ebb-eea5-e5fa95d8a516.png)

>* 画像引用 : [目指したのは“脱ガンダム”『閃光のハサウェイ』Ξガンダムデザインの裏側](https://www.cinematoday.jp/news/N0124030)

無事変換できました。
クシィガンダム...カッコよすぎますね。次の第二部が楽しみです。

## おわりに
今回はColabでOpencv GPUを使う方法を紹介させて頂きました。正直いつ使うかわからないですが、色々調べてやっとこさ出来たので、とりあえず執筆しました。誰かのお役に立てれば幸いです。

閃光のハサウェイが小説と同じ展開かそうでないか、気になりすぎて夜も眠れない...
クラス自体に対しての型ヒントに使える python の typing.Type

python の typing モジュールの `Type` についてご存知でしょうか。これは、クラス自体に対しての型ヒントに使えるものです。

ところで、私が初めてこれについて調べようと思った際、 "python typing.Type" といったキーワードで検索してみました。しかし、その際に検索結果として主に表示されたのは python の型ヒント全般に関する記事でした。そのため、所望の情報にたどりつい着くまでに少々苦労しました。そこで python の公式ドキュメントの typing のページを見直したところ、 [こちら](https://docs.python.org/ja/3/library/typing.html#typing.Type) に書いてました。（やはり最初に公式ドキュメントをしっかり読むべきですね。）

今回、 `typing.Type` について簡単にまとめたく、本記事を作成しました。

## typing.Type とは

下記、 [日本語版公式ドキュメント](https://docs.python.org/ja/3/library/typing.html#typing.Type) からの引用です。

> Type[C] と注釈が付けられた変数は、そのクラス自身を受理します

つまり、 `Type` は、自作クラス自体や、 `int` などの組み込みの型（クラス）自体を指し示すために使われます。

## 使用例

全く実用性のない例になりますが、簡単のため、下記のような例を作成しました。

```python:type.py
from typing import Type


class Person:
    @staticmethod
    def get_cls_name() -> str:
        return "Person"


def get_cls_name(cls: Type[Person]) -> str:
    return cls.get_cls_name()
```

`Person` クラスにクラス名を返す staticmethod を定義し、その外に、`get_cls_name` 関数を定義しています。

※もちろん、クラス名は `cls.__name__` で取得すれば良いです。また、 `Person.get_cls_name` はリテラル値を返すので、アノテーションを `Literal["Person"]` とした方が良いです。

`get_cls_name` の型ヒント `get_cls_name(cls: Type[Person]) -> str` は、下記を意味します。

**`get_cls_name` 関数の引数 `cls` は（ `Person` のインスタンスではなく） `Person` 自身であり、返り値の型は `str` である。**

そのため、 `get_cls_name` 関数を呼び出す際は、 `get_cls_name(Person)` のように呼び出します。

## TypeVar との併用

`TypeVar` 自身については、 [こちら](https://qiita.com/Showy1/items/d0829f1bdc3d9c92277f) に簡単な記事を作成しましたので、適宜ご参照ください。

TypeVar と併用する場合の使用例を下記のように作成しました。

```python:typevar_and_type.py
from typing import Type, TypeVar

Number = TypeVar("Number", int, float)


def to_number(str_number: str, type_: Type[Number]) -> Number:
    return type_(str_number)
```

`to_number` の型ヒント `to_number(str_number: str, type_: Type[Number]) -> Number` は、下記を意味します。

**`to_number` 関数の引数 `str_number` の型は `str`、 `type_` は `int` または `float` 自身であり、 `type_` が `int` 自身の際の返り値の型は `int`、 `type_` が `float` 自身の際の返り値の型は `float` である。**

そのため、 `to_number` 関数を呼び出す際は、 `to_number("10", int)` のように呼び出します。

## まとめ

**typing.Type は、クラス自体を示す型ヒントとして用いられる。**

以上です。閲覧ありがとうございました！
ユーザーの権限について

ユーザーの権限について考えてみる。
Linuxを学んだときに、管理者権限、一般ユーザー権限があることを知った。今や1人１台パソコンを持ってて、誰かと共有してパソコンを使うことはない。しかもネットサーフィンや資料作成などでパソコンを使うときに、管理者権限を使うこともない。

管理者がシステムの設定をいじれるのは学んでいくうちにわかった。
WindowsやMacを使ってアプリケーションをダウンロードしインストールするときに、管理者権限でセキュリティ解除もやった。

しかし、管理者が一般ユーザーを複数作れることが疑問だった。1人１台のパソコンを使うのに、なぜユーザーを複数作る必要があるのだろうか。

もともとコンピュータは高価なもので、1人１台買って使うことはできなかった。1つのコンピュータを複数人で使っていたのだ。そのため、管理者にはユーザーを作る権限があって、ファイルやフォルダにアクセスする権限を与えることができるのだと知った。

1つのコンピュータを複数人で使っているため、誰かがファイルを作成したら別のユーザーもみることができる。他のユーザーに見られたくないファイルだと、アクセスできないように制限をかけないといけない。そこで、アクセス権限を用いていたのだった。パーミションは最初理解しにくいが、何度も見てると面白いくらい理解できるようになった。
【React】TextFieldでEnterキーを押したときになぜかページが更新されてしまう件【MaterialUI】

<h2>症状</h2>
MaterialUIのTextFieldを実装し、Enterを押したときにページが更新されてしまう事象に遭遇しました。
onKeyDownでeventを見てみようにも、ページが更新されてしまうため、エラーメッセージ自体が消えてしまいます。

以下が該当のソースです。

```react:textField.jsx
import React, { Fragment } from 'react';
import TextField from '@material-ui/core/TextField';

export const textField = () => {

  return(
          <Fragment>
            <form className={classes.root} noValidate autoComplete="off">
              <TextField
                id="outlined-basic"
                label="Email"
                variant="outlined"
                fullWidth
                value={SessionEmailState.user.email}
                onChange={handleChange}
                onKeyDown={(event) => {
                  if (event.key === 'Enter')
                  console.log("enterを押しました")
                }
                }
              />
            </form>
          </Fragment>
  )
}
```

<h2>解決方法</h2>
onKeyDownに以下を記述することで解決しました。
おそらくですが、form要素のdefaulteventが原因だと思われます。

formのデフォルトの動作で、指定したURLにformの値を送信するもので、送信先のURLが指定されていなければ現在のURLに送信するようです。
結果的に、現在のURLがリロードしてしまうようです。

なので、以下のようにその動作をしないコードを記述して解決しました。別途Enterしたときにsubmitボタンの動作するようにする場合は、onKeyDownにsubmitを呼ぶようなfunctionを設定してやるとよさそうです。

```react:textField.jsx
import React, { Fragment } from 'react';
import TextField from '@material-ui/core/TextField';

export const textField = () => {

  return(
          <Fragment>
            <form className={classes.root} noValidate autoComplete="off">
              <TextField
                id="outlined-basic"
                label="Email"
                variant="outlined"
                fullWidth
                value={SessionEmailState.user.email}
                onChange={handleChange}
                onKeyDown={(event) => {
                  if (event.key === 'Enter')
                    event.preventDefault();
                  console.log("enterを押しました")
　　　　　　　　　　//ここにsubmit用の処理を書くとEnterを押したときに動作してくれる
                }
                }
              />
            </form>
          </Fragment>
  )
}
```

<h2>参考</h2>

https://qiita.com/yokoto/items/27c56ebc4b818167ef9e
【Processing】アナログ時計

間違えて削除してしまったので、ついでに手を加えて再投稿になります
#アナログ時計
時間を取得すれば簡単に作れるけど、秒針も滑らかにしなくてはアナログ時計ではないから作った
new Clock();
![アナログ時計.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/1a0d1893-a078-7967-cad5-d68f9840ba45.gif)

new Clock(false);
![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/2e2a024e-ca6c-ec36-6766-5a36cbaff283.gif)


#コード
```AnalogClock.java
Clock clock = new Clock(false);//時計

void setup() {
  size(500, 500, P3D);
}

void draw() {
  background(50);
  translate(width/2, height/2);
  scale(1,-1);
  clock.update();
}

class Clock {
  boolean simple = false;
  float second = 0, minute, hour;
  float sRatio = 0, mRatio = 0, hRatio = 0;
  int oldSecond = 0;

  Clock(boolean simple) {
    this.simple = simple;
    timeUpdate();
  }
  Clock(){
    this(true);
  }

  void update() {
    pushMatrix();
    timeUpdate();
    drawHands();
    popMatrix();
  }
  void drawHands() {
    stroke(255);
    strokeWeight(1);
    if(simple)ellipse(0, 0, 5, 5);
    else ellipse(0,0,10,10);

    //秒針
    pushMatrix();
    rotateZ(-PI * 2 * sRatio);
    if(simple)line(0, 0, 0, 100);
    else drawHand(1.5f,100);
    popMatrix();

    //長針
    pushMatrix();
    rotateZ(-PI * 2 * mRatio);
    if(simple)line(0, 0, 0, 120);
    else drawHand(10,150);
    popMatrix();

    //短針
    pushMatrix();
    rotateZ(-PI * 2 * hRatio);
    if(simple)line(0, 0, 0, 60);
    else drawHand(10,100);
    popMatrix();

    for (int i=0; i<12; i++) {
      float size = i%3 == 0 ? 20 : 5;
      pushMatrix();
      rotateZ(i * PI  / 6);
      ellipse(0, 150, size, size);
      popMatrix();
    }
  }
  void drawHand(float sizeX,float sizeY){
    beginShape();
    vertex(sizeX * 0.2f,0);
    bezierVertex(0,sizeY * 0.25f,0,sizeY * 0.5f,sizeX,sizeY * 0.7f);
    bezierVertex(0,sizeY * 0.8,0,sizeY * 0.9f,0,sizeY);
    bezierVertex(0,sizeY * 0.9f,0,sizeY * 0.8,-sizeX,sizeY * 0.7f);
    bezierVertex(0,sizeY * 0.5f,0,sizeY * 0.25f,-sizeX * 0.2f,0);
    endShape();
    rect(-sizeX * 0.2f,0,sizeX * 0.4f,-sizeY * 0.15f);
  }
  void timeUpdate() {
    int currentSecond = second();
    if (currentSecond != oldSecond) {
      second =oldSecond = currentSecond;
    }
    second += 1/frameRate;
    sRatio = second / 60;
    minute = minute() + sRatio;
    mRatio = minute/60;
    hour = hour()%12 + mRatio;
    hRatio = hour / 12;
  }
}
```
Java Silver アウトプット 8

前回の続きです

https://qiita.com/0W5E8fPq1EOm4yE/items/687d45ec714b0a85bad9

chapter8のモジュールについてです。ここは暗記するのがメインなのでしっかりと抑えていきたいです。

・-module-path (または、-p)はアプリケーション・モジュールを検索する位置を指定

・-module(または、-m)はモジュールなるエントリ・ポイントとなるクラス(mainクラス)を指定

・-describe-moduleはモジュール記述子の情報を参照

・-show-module-resolutionはモジュールの解決の様子を出力

・module-info.javaの定義内容は下記の通り

module モジュール名{
requires<依存するモジュール名>
exports<公開するパッケージ名>
}

モジュール名は<依存するモジュール名>に依存するという関係

・module-info.javaのファイル名は固定

・module-info.javaの公開するパッケージがないと中身は空になる

・module-info.javaの公開するパッケージの指定はexportsディレクティブを使用

・・module-info.javaはjavacによるコンパイルが必要

・依存関係を調べるコマンドは「jdeps」

・ディレクトリを作成するには「-d」オブションを使用する

・区切りについてはLinux環境下は「/」、windowsは「\」で試験では「/」で掲載される

・モジュールの実行コマンドは「java -p<モジュールが格納されている場所> -m <モジュール名>/<mainクラスの完全修飾名>」を使用する

とりあえず8章全て読み終わりました。あとは模擬試験を解きまくって年内に試験合格に向けて勉強してまいります。
コードの流れや継承関係等ごちゃ混ぜな状況ではありますが問題を解いて、見直すと繰返して理解を深めていきたいです😀
【React】Mapのようにスワイプ移動できるページを実装する

<!-- =========================================================== -->
# 概要
<!-- =========================================================== -->
Google Mapのように**ドラッグ操作でスワイプできるページ**を実装します。

https://vw5z8.csb.app/
![output(video-cutter-js.com).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/6751cfe3-caad-443b-5c01-742ba1cdc954.gif)

:::note info
ドラッグ操作には、<strong>Framer Motion</strong>を使用します。
:::

https://www.framer.com/motion/

:::note info
スタイリングには、<strong>emotion/css</strong>（CSS in JS）を使用しています。
:::

https://emotion.sh/docs/@emotion/css

https://qiita.com/nemutas/items/dac73aa645f27cde92cd

<!-- =========================================================== -->
# 実装
<!-- =========================================================== -->
下図は実装のイメージです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/143b585e-2a62-d32b-44bd-67b620b1965d.png" width="600">

:::note info
screenが移動するのではなく、paperだけが移動すると考えてください。
:::

* **screen**は、ブラウザの表示領域（1vw・1vhの範囲）です。
* 今回は縦横がscreenの2倍を領域をもつマップを作成したので、**paper**は2vw・2vhになっています。
* **container**は、paperの可動域です。screenに表示されるのが、`#44B3C2`パネルの左上から、`#5D4C46`パネルの右下までにしたいので、3vw・3vhとなっています。

```.tsx
import { motion } from 'framer-motion';
import React, { useRef, VFC } from 'react';
import { css } from '@emotion/css';

export const MapPage: VFC = () => {
	const containerRef = useRef<HTMLDivElement>(null)

	return (
		<motion.div ref={containerRef} className={styles.container}>
			<motion.div className={styles.paper} drag dragPropagation dragConstraints={containerRef}>
				<div className={styles.panel('#44B3C2')}>
					<div className={styles.text}>Panel 1</div>
				</div>
				<div className={styles.panel('#F1A94E')}>
					<div className={styles.text}>Panel 2</div>
				</div>
				<div className={styles.panel('#E45641')}>
					<div className={styles.text}>Panel 3</div>
				</div>
				<div className={styles.panel('#5D4C46')}>
					<div className={styles.text}>Panel 4</div>
				</div>
			</motion.div>
		</motion.div>
	)
}

const styles = {
	container: css`
		position: relative;
		width: 300vw;
		height: 300vh;
		/* (300 - 100) / 2 */
		transform: translate(-100vw, -100vh);
		display: flex;
		justify-content: center;
		align-items: center;
	`,
	paper: css`
		position: absolute;
		width: 200vw;
		height: 200vh;
		display: flex;
		flex-wrap: wrap;
		/* start page1 */
		top: 100vh;
		left: 100vw;
	`,
	panel: (bgColor: string) => css`
		width: 50%;
		height: 50%;
		background-color: ${bgColor};
		display: flex;
		justify-content: center;
		align-items: center;
	`,
	text: css`
		color: white;
		font-size: 3rem;
	`
}
```
**paper**（styles.paperを割り当ててるdiv）要素をスワイプさせたいので、ドラッグに関するプロパティを割り当てます。

* **drag**：要素をドラッグできるようにする
* **dragPropagation**：親要素をドラッグしたときに子要素も移動するようにする
* **dragConstraints**：ドラッグできる領域を決める。今回はcontainer要素を可動域にしたいので、`containerRef`を割り当てています。

Framer MotionのDragについて詳しく知りたい方は、以下を参照してください。

https://www.framer.com/docs/gestures/#drag

<!-- =========================================================== -->
# 成果物
<!-- =========================================================== -->

https://codesandbox.io/s/map-design-page-with-framer-motion-vw5z8?file=/src/App.tsx
ニコ生ゲームの作り方についてまとめた（まとめてくれている）記事　※リンク多め

# ニコ生ゲームとは\:kissing_closed_eyes:

ニコニコ生放送で視聴者参加型の皆で出来るゲームです。
例：つりっくま、ニコニコタワーなど。

ニコ生ゲームはゲームエンジンとしてAkashic Engineを使用しています。
言語はjavaScriptかTypeScript。

公式HP

https://akashic-games.github.io/

ニコ生ゲームの作り方

https://akashic-games.github.io/shin-ichiba/

逆引きリファレンス

https://akashic-games.github.io/reverse-reference/v3/

公式サンプルとか

https://akashic-contents.github.io/samples/index.html

# その１　下準備 \:kissing_closed_eyes:

自分のPCで動作させるためにインストールするもの

https://akashic-games.github.io/shin-ichiba/install.html

※2021/10/13現在の推奨版
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410757/00488a13-7be0-20a3-a267-53e8b0d5d765.png)

# その２　Akashic 関連ツールのインストール\:kissing_closed_eyes:
Windows環境で説明します。
画像の１のところにcmdと入力
画像２のコマンドプロンプトを起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410757/95ac571e-febf-12bc-39f8-c2cc242dbb79.png)

出てきた黒い画面にこれをコピペしてエンター↓
npm install -g @akashic/akashic-sandbox

おわったらこれもコピペしてエンター↓
npm install -g @akashic/akashic-cli

# その３　テキストエディター\:kissing_closed_eyes:

いわゆるコードを編集するソフト。
おすすめはVSCode
https://azure.microsoft.com/ja-jp/products/visual-studio-code/

**Download now** もしくは **いますぐダウンロード**

これで下準備は終わり！！（多分）

#※コマンドプロンプトのコマンドまとめ\:kissing_closed_eyes:

     cd 作業するフォルダのパス　

で作業フォルダに移動したら

    akashic-sandbox 
 でゲーム用のローカルサーバー起動

このURLでゲーム画面確認

    http://localhost:3000

CTRL+Cで終了　Y/Nが出た場合はYで終了　※　Yes と No の意味

  画像や音声ファイルを追加するときは終了した状態で

    akashic scan asset

ニコ生ゲーム用に出力する場合は

    akashic export html --output ./game.zip --atsumaru

※gameのところは任意の名前

ニコ生ゲームの制約

    zip ファイルの 展開後の合計サイズが 10 MB 以下
    zip ファイルに含まれる game.json が 100KB 以下
    全てのテキストファイル (.js, .json, .txt など) の 文字コードが UTF-8


# わかりやすい記事\:kissing_closed_eyes:
シングルゲームやマルチプレイゲームのサンプルコードや改造のやり方を記事にしてくれています。

僕も大変お世話になっております！

https://nicorakku.hatenablog.com/entry/ar1979578

# 困ったときは・・・（なにかあれば更新予定）\:kissing_closed_eyes:

## **Q.**　IOSで起動しない！

**A.**　Audioファイルにaacファイルが含まれてない可能性があります。すべての音声ファイルのoggとaacを入れると解決するかもしれません。
https://github.com/akashic-games/complete-audio

## **Q.**　商品情報の取得に失敗しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410757/1ff3764c-11c9-00ef-bc5d-bd6d59f065a2.png)


**A.**　ゲームタイトルの単語ではじかれてるかもしれません。変更してみましょう。
ちなみに僕はこの自作ゲームの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410757/2e8f8ecb-37a6-f6fa-ae93-c3456440a806.png)

**「うんち」** という単語を消すと正常にリクエストできるようになりました。
※推測ですが、 **「おっぱい」** もだめかもしれません

## **Q.**　テキストの色を変えたいけど変わらない！

**A.**　

    label.modified();

ではなく、

    label.invalidate();

で反映されます。

自分は結構悩んでましたが、逆引きリファレンスを見て気づきました・・ｗ


# ※気を付けたほうがいいかもしれないこと\:kissing_closed_eyes:
現状ではニコ生ゲーム上ではキーボード入力がサポートされておらず
**強引に対応させると動作しない場合がある**みたいです。
※アツマール上であれば問題ないみたいです。
current_userとcorrect_userの違い

こんにちは！テックアカデミーのWebアプリコースを受講している駆け出し高校生エンジニアの安田駿介です。

今回は、「current_userとcorrect_userの違い」というテーマで解説していきます。

#current_user
現在ログインしているユーザを取得するメソッド

#correct_user
そのレコードを本当にログインユーザの所有しているものかを判別するメソッド
レコードの編集、更新、削除など、持ち主しかやってはいけない機能を作るときによく使います。

#まとめ
current_userとcorrect_userは、JavaとJavaScriptのように、全く違うメソッドです。


#開発環境
・Cloud9
・Ruby 3.0.0
・Rails 6.1.3.1
無線AP TP-Link Archar AX73 のブリッジモードと壁掛け

最近の無線APはルーターモードとブリッジモード (アクセスポイントモード)を外部スイッチで切り替えられることが多いが、AX73 のブリッジモードへの切り替え方法が2021年10月時点の[メーカーホームページ](https://www.tp-link.com/jp/support/faq/2066/) と異なるので手順をまとめておく。既に有線ルーター（NTTのレンタルルーター等）が適切に設定され有線接続でのインターネット使用が出来ていることを前提とする。以降この有線ルーターを「既存のルーター」と呼ぶ。
壁掛けの設置例も紹介する

# ブリッジモード
1. パソコンをAX73の初期設定のSSIDに接続し、 http://192.168.0.1/ を開くとパスワードとタイムゾーンを設定するように促されるので設定する。「インターネットへの接続」は「スキップ」で後回しにして構わない
1. 上段タブの中の「システム」を選ぶと「動作モード」が現れるから、そこで「ブリッジモードを選ぶ。![Screenshot from 2021-10-13 08-47-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259309/24251f7e-7ea7-dd7a-ddfe-ae912f36e3d7.png)
1. この後AX73のIPアドレスは既存のルーターのDHCPにより設定されるから http://192.168.0.1/ からAX73の設定画面に入れなくなる。既存のルーターで稼働するDHCPサーバーのアドレス配布情報を見るとAX73の新しいIPアドレスがわかる（というやりかたを[あんきょさん](https://ankyo.net/)に教えて貰った）。別のやり方として、ARPテーブルを参照してAX73の新しいIPアドレスを見つけ、設定の続きを行う。[Windowsならarpコマンド](https://atmarkit.itmedia.co.jp/ait/articles/0709/14/news140.html) を使い、Linuxなら `sudo arp-scan -l` などを使う。
1. 既存のルーターで既にDHCPサーバーが稼働しているはずなので、AX73のDHCPサーバーを以下の画面でOFFにする ![Screenshot from 2021-10-13 08-38-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259309/722f2e2e-0baf-20fa-1169-2d5ff6263e16.png)

# 壁掛け

* 以下の写真のようにAX73底部には引っ掛ける穴がある ![IMG_20211013_104639910.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259309/40e2bacf-5a3b-cdd5-765d-5e4bde85e588.jpeg)
* 洋折釘 ![images.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259309/146a53f4-3b6a-4c3b-d27f-ffbdf135262e.jpeg)
 などを壁に取り付ければ、以下のように壁掛けで設置できる。 ![IMG_20211013_163425604.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259309/46873a3a-ec7a-c2fa-b6fa-7217b2898303.jpeg)
【Flutter】scroll top 画面の一番上まで移動する

すぐ忘れてしまうので、備忘録として。。

```dart
final ScrollController _scrollController = ScrollController();

--省略--
  child: Scaffold(
        body: SingleChildScrollView(
          controller: _scrollController,
--省略--

// 何かのアクションで実行すると画面のTopに移動しますーー
_scrollController.animateTo(
  0, // 移動したい位置を指定
  duration: Duration(milliseconds: 1), // 1秒かけて戻る
  curve: Curves.linear);
```
HTTPについて絶対理解する

# はじめに

以下httpの理解するのに必須な内容を纏めた。

## HTTPとは

HTTP(Hypertext Transfer Protocol) の略語です。

* Hypertextとはテキスト、文字列。ハイパーリンク、画像、音楽、ビデオ、地図、ロケーションなどなど
* Transfer 　→　文字通り転送、送るという意味
* Protocol　　→　制約、規約つまり、ルール

HTTPとは　↑.....↑　を送る時に使われるルールである。ディフォルトのポート番号は80となる。

## HTTPのバージョン

* http1.0 リクエストを一つずつ処理する。処理した後、Webサーバーとクライアント（ブラウザ）接続を遮断する。
* http2.0　複数のリクエストを処理できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755874/a5219447-e674-aea4-1570-4ac30dec3292.png)

https://www.kagoya.jp/howto/it-glossary/security/http-2/

## HTTPリクエスト・レスポンス

↓基本の概念、とリクエストの仕方（GETとPOSTの違い）

https://blog.senseshare.jp/request-response.html#index1

↓それぞれの中身の紹介、またステータスコードの説明

https://itsakura.com/network-http-get-post

# 終わりに

上記はHTTPの基本である
Raspberry Pi で fswebcam を利用して写真撮影する

## Raspberry Pi で写真を撮りたい。
### 1. 環境

| 機体 | モデル |
|:-|:-|
| Raspberry Pi  | Raspberry Pi  |
| カメラモジュール  | OV5647センサー 500万画素  |
カメラの初期設定は以下参照。

https://qiita.com/Colours/items/a07915f7e2a18bf8972a

### 2. fswebcam をインストール
`sudo apt install fswebcam`

撮影コマンドは
`fswebcam image.jpg`

### 3. 詳細設定コマンド
コマンドの順番と例。
`fswebcam -p YUYV -r 640x480 -F 1 -S 20 --no-banner image.jpg`

| コマンド | 詳細 |
|:-|:-|
| -p YUYV  | カメラによっては、これがないと保存できない場合があるらしい。  |
| -r 640x480  | 640x640画素の画像を保存。数値は任意。  |
| -F 1  | 撮影するフレーム数。おおよそ露光時間に関係する値。  |
| -S 20  | 撮影前のパラメータ調整。大きいと調整が良いが時間がかかる。  |
| --no-banner  | バナー消去。  |

※ちなみにいつの間にかバナーが文字化けしていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/d0e99e2c-abf2-7b50-9b8e-be995d2a89d9.png)
これは日本語フォントを入れたら直ります。
日本語フォントを入れるコマンドは
`sudo apt-get install fonts-noto`
ただ、ものすごくインストールに時間がかかりました。

直るとこう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637498/bcae4b09-fc0e-c71d-f2f8-c7d09bfa3f41.png)
<b>どこが日本語なのかと問いたい。<b>

### 参考にさせて頂いたサイト
https://twitter.com/sunakiti2/status/1097992792494596096

https://qiita.com/iimuz/items/53994dee3e75c961060f
マッピングとは

エンジニアの間で「マップしといて」「マッピングされてるよ」と話しているのを聞いた。
なんだろと検索してみると、「何かと何かを関連づけること」と出てきた。

元々は「地図を描く」という意味だが、「位置付ける、関連づける」という意味合いもあるようだ。
エンジニア同士では「関連づける」という意味で使われている。

例えば、Linuxのディレクトリで、「/etc」と「/private/etc」がある。
どちらも同じファイルが入っていた。これは2つがマッピングされているということだ。

システム開発でも多く使われているよう。
undefined method "〇〇" for nil:NilClassのエラーの原因を実例を元に解説

こんにちは！テックアカデミーのWebアプリコースを受講している駆け出し高校生エンジニアの安田駿介です。

今回は、「undefined method "〇〇" for nil:NilClassのエラーの原因を実例を元に解説」というテーマで解説していきます。

#エラー内容
![4f9235c41d32c38c65ec88904178410f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1903726/843cc005-41e2-1c60-a4c8-f617e99d611e.png)

#解説
このエラーは、nilが〇〇を呼び出そうとしているからエラーになっています。

nil.each ~
という状態です。

今の状態だと、記載してあるはずの@cabinetsがnilになっています。

つまり、@cabinetsメソッドが未定義ということになります。

この場合だと、@cabinetsはcontroller#indexに記載するはずですが、それが記載していないということでした。

#開発環境
・Cloud9
・Ruby 3.0.0
・Rails 6.1.3.1
Java Sliver アウトプット 7

前回の続きです

https://qiita.com/0W5E8fPq1EOm4yE/items/08dd8996d4ba78dce803

chapter7例外処理です。ここはエラーの継承関係を理解するとスムーズにいきます。

・try-catch-finallyは全て書く必要はないがtryのみはコンパイルエラー

・checked例外とunchecked例外があり例外処理が必要なのはchecked例外

・「|」継承関係があるクラスを列記できない

・throwキーワードを使用したメソッド定義文 「[]戻り値の型　メソッド名(引数)throws 例外クラス名{}」

・メソッドの呼び出す際try-catch-finallyが書いてあるか確認する

・オーバーライドする場合サブクラスをthrowsで指定する必要がある

・Integerクラスのインスタンス変数の初期値はnull

## 例外クラスと継承図
![例外とクラスの関係.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/832099/d9ce2981-45db-aa6b-ef10-1f806e4634b0.png)
【Chobiitカスタマイズ集・その①】計算結果をリアルタイムで表示する！

#はじめに
今回はChobiitのカスタマイズについて、紹介したいと思います！
Chobiitとは、株式会社ノベルワークスが提供している
Cybozu社のkintoneとの外部連携サービスです。
詳しくはこちらをご参照ください！→https://www.novelworks.jp/chobiit

#Chobiitの計算フィールドの仕様
Chobiitの計算フィールドは、kintoneの様に
リアルタイムで計算結果を表示することができません。※2021年10月時点
（保存ボタンを押下後、kintoneでの計算結果が確認画面にて反映される仕様となっています）

今回はkintoneの計算フィールドに近い動きを実装するためのカスタマイズをご紹介したいと思います！

#計算フィールドの動き（kintone/レコード追加画面）
![スクリーンショット (179).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1487043/cf9ee892-572f-497f-6dee-b7759de4bbc2.png)
それぞれのフィールドに入力すると…
![スクリーンショット (172).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1487043/356d310a-6695-68b1-c07e-5ddf09ee65e1.png)
結果が表示されます。



#計算フィールドの動き（Chobiit/レコード追加画面）
![スクリーンショット (177).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1487043/cc1da6c2-05c2-b573-276a-6e723a740e88.png)
先程と同様に、それぞれのフィールドに入力すると…
![スクリーンショット (178).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1487043/acb49b77-14fe-6fa7-f55c-3ea3211f1e30.png)
kintoneのようにリアルタイムでは計算結果が反映されません(´；ω；`)



#Chobiitカスタマイズでkintoneの動きを実現しよう！

今回は分かりやすいように、kintoneアプリで
フィールド名・フィールドコードを同一に設定しています。

```javascript:test.js
$(function () {

    //単価・数量フィールドを変更したら発火する
    $('#iframe').contents().find('#単価,#数量').change(function () {

        //単価・数量フィールドの値を取得する
        let 単価 = $('#iframe').contents().find('#単価').val();
        let 数量 = $('#iframe').contents().find('#数量').val();
        
        //計算したい内容を記述
        let result = 単価 * 数量;
        
        //金額フィールドにset
        $('#iframe').contents().find('#金額').val(result);
    
    });

});
```



#Chobiitを見てみよう！
作成したjsファイルを設定し、Chobiitを覗いてみます。
![スクリーンショット (175).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1487043/322e0412-ac01-0fe2-14b8-5adb839303d6.png)
これでリアルタイムで計算結果を表示できるようになりました！



#（小技）桁区切りがしたい

```javascript:test.js
        //金額フィールドにset
        //元のコード
        // $('#iframe').contents().find('#金額').val(result);
        
        //桁区切り用のコード　※下記に差し替えます※
        $('#iframe').contents().find('#金額').val(result.toLocaleString( undefined, { maximumFractionDigits: 20 }));
```

![スクリーンショット (180).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1487043/3ab69bdc-d233-e43d-238c-1899a0580066.png)

できました(o^―^o)
[Git] git-flowの使い方

前回、**git-flow**の概要と各ブランチの役割について紹介した。今回は、**git-flow**の使い方（コマンド）について紹介する。

# git-flowの使い方
**git-flow**のコマンドは基本的には次の書式になる。

```
git flow <ブランチの種類>　<コマンド>
```

#### ■ ブランチの作成

新たなブランチを作成する場合

```
git flow <ブランチの種類>　start <ブランチ名>
```

#### ■ ブランチの共有
作成したブランチを共有リポジトリで共有する場合

```
git flow <ブランチの種類>　publish <ブランチ名>
```

#### ■ ブランチの取得
共有リポジトリからブランチを取得する場合

```
git flow <ブランチの種類>　track <ブランチ名>
```

#### ■ コミットの取得
共有リポジトリ上のコミットを取得する場合

```
git flow <ブランチの種類>　pull origin
```

#### ■ ブランチの終了
共有リポジトリからブランチを取得する場合

```
git flow <ブランチの種類>　finish <ブランチ名>
```
ブランチ終了後、終了したブランチは削除される。

#まとめ
紹介したコマンドを表にまとめると以下となる。

|コマンド|操作|
|---  |---   |   
|start|　ブランチの作成   |  
|publish  |　ブランチを共有リポジトリで共有 |
|track |　共有リポジトリからブランチを取得  |
|pull|　共有リポジトリ上のコミットを取得   |
|finish|　developかdevelopとmasterへマージして、ブランチを削除  |
【Swift】GCDについて


##GCDとは

GCD（Dispatch）はGrand Central Dispatch の略で、DipatchQueueに処理を投入することで、コードを同時実行することができます。


##DispatchQueueとは
GCDのキューはディスパッチキューといいます。キューに行いたい処理をクロージャで渡し実行します。ディスパッチキューの実行方式には以下があります。

直列→他のスレッド終了を待機し、完了後タスク処理を実行します。
並列→他のスレッド処理を待機せず、タスク処理を同時実行します。

##キューの取得

GCDには既存のディスパッチキューとして以下の２つがあります。

mainQueue : 
mainQueueはメインスレッドでタスクを実行する直列キューです。
iOSやmacOSのアプリケーションにおいては、UIの更新処理は常にmainQueueで行われます。なので、他のQueueで実行した処理の結果をUIに反映させるにはmainQueueを呼び出してタスクを渡す必要があります。

globalQueue:
システム全体で共有される並列キュー。実行優先度(Qos)を指定して取得。Qosは優先度の高い順に次の5種類があります。

###使用例


####DispatchQueue.main.sync
⇨ 直列キューなので処理は順番に実行される。またsyncなので、タスク終了まで次の処理に進みません。

```swift

DispatchQueue.main.async {
    for i in 0 ... 5 {
        print("DispatchQueue.main.async ",i)
    }
}
print("finish")

---------

DispatchQueue.main.async  0
DispatchQueue.main.async  1
DispatchQueue.main.async  2
DispatchQueue.main.async  3
finish

```



####DispatchQueue.main.async
⇨直列キューなので処理は順番に実行される。asyncなので、タスクをキューに追加したら次の処理に進みます。

```swift

DispatchQueue.main.async {
    for i in 0 ... 5 {
        print("DispatchQueue.main.async ",i)
    }
}
print("finish")

---------

finish
DispatchQueue.main.async  0
DispatchQueue.main.async  1
DispatchQueue.main.async  2
DispatchQueue.main.async  3


```




####DispatchQueue.global.sync 
⇨ 並列に実行するので、実行順は保証されません。またsyncなので、タスク終了まで次の処理に進みません。

```swift
DispatchQueue.global().sync {
    for i in 0 ... 3 {
        print("DispatchQueue.global.async1 ",i)
    }
}
print("finish1")

DispatchQueue.global().sync {
    for i in 0 ... 3 {
        print("DispatchQueue.global.async2 ",i)
    }
}
print("finish2")
----
DispatchQueue.global.async1  0
DispatchQueue.global.async1  1
DispatchQueue.global.async1  2
DispatchQueue.global.async1  3
finish1
DispatchQueue.global.async2  0
DispatchQueue.global.async2  1
DispatchQueue.global.async2  2
DispatchQueue.global.async2  3
finish2
```

####DispatchQueue.global.async
⇨並列に実行するので、実行順は保証されません。asyncなので、タスクをキューに追加したら次の処理に進みます。

```swift
DispatchQueue.global().async {
    for i in 0 ... 3 {
        print("DispatchQueue.global.async1 ",i)
    }
}
print("finish1")

DispatchQueue.global().async {
    for i in 0 ... 3 {
        print("DispatchQueue.global.async2 ",i)
    }
}
print("finish2")
---- 
finish1
finish2
DispatchQueue.global.async1  0
DispatchQueue.global.async2  0
DispatchQueue.global.async1  1
DispatchQueue.global.async2  1
DispatchQueue.global.async1  2
DispatchQueue.global.async2  2
DispatchQueue.global.async1  3
DispatchQueue.global.async2  3
```


##キューの生成
GCDには既存のディスパッチキューだけでなく、新規のディスパッチを生成することができます。このキューは並列、直列どちらでも作成することができます。

##終わりに
終わりです。随時更新します
VBAでExcelファイル開閉を繰り返すと、徐々に遅延が発生する不具合を解消（メモリ解放）

## 事象

ExcelVBAにて以下のようなソースコードで、複数のExcelファイルの開閉をしながら処理をしていると、少しづつ遅延が発生する場合があります。

開閉を行うファイルサイズにもよりますが、1000ファイル単位になると、段々と遅くなります。

```vb
Sub openFile()

  Dim wb As Workbook
  Dim fileList As Variant
  Dim f As Variant
  
  '開くファイルのディレクトリを取得
  fileList = Range("A1").CurrentRegion
  
  '一つ一つ、ファイルを開閉する。
  For Each f In fileList
    Set wb = Workbooks.Open(f)
    wb.Close
  Next
  
End Sub
```



## 原因

Excelファイルを閉じる際に、メモリ解放が出来ておらず、タスクに少しづつサイズ容量が蓄積されていくのが原因のようでした。

※発生する場合としない場合があります。
単純な処理であれば発生しないですが、複雑な処理を加えるほど、発生するような気がします。（体感です。）


## 解決方法

Close後にDoEventsを入れることで、閉じるまで待ってくれるようです。

```vb
Sub openFile()

  Dim wb As Workbook
  Dim fileList As Variant
  Dim f As Variant
  
  '開くファイルのディレクトリを取得
  fileList = Range("A1").CurrentRegion
  
  '一つ一つ、ファイルを開閉する。
  For Each f In fileList
    Set wb = Workbooks.Open(f)
    wb.Close
    
    'Close待機
    DoEvents
  Next
  
End Sub
```
### DoEventsとは？

> 制御をオペレーティング システムに渡します。 オペレーティング システムがキューのイベントの処理を終了し、SendKeys キュー内のすべてのキーが送信された後、制御は戻されます。

## 参考サイト

https://answers.microsoft.com/ja-jp/msoffice/forum/all/%E3%83%9E%E3%82%AF%E3%83%AD%E5%87%A6%E7%90%86/ab8ef865-8fa5-40cd-aaca-00ee2b7e61a9

https://support.microsoft.com/ja-jp/office/doevents-%E9%96%A2%E6%95%B0-7af41eca-88e0-470d-adaf-0b3d4c2575b0
usrディレクトリは何か

Linuxを勉強している人は、「usr」ディレクトリを見たことがあるだろう。
ユーザーディレクトリと読む。
Linuxのユーザーが使っているファイルやディレクトリが保存されているディレクトリと思うがそうではない。

様々なOSでそのパソコンを使う複数ユーザーを作ることができる。
例えば、「yamada」「sato」「takahashi」などだ。
管理者はROOTユーザー。

/usrにはユーザーが使うプログラム、ライブラリが保管されている。
具体的に見てみると、コマンドの実行ファイル（Linuxコマンドだとcdコマンドやlsコマンドなど）や、プログラムのライブラリ（PHPのライブラリなど）が入っていた。

続く