OmniAICreator/Qiita-1.07M huggingface dataset:
日鉄ソリューションズプログラミングコンテスト2022(AtCoder Beginner Contest 257) 参戦記

# 日鉄ソリューションズプログラミングコンテスト2022(AtCoder Beginner Contest 257) 参戦記

集中できない理由があったので unrated で参加.

## [ABC257A - A to Z String 2](https://atcoder.jp/contests/abc257/tasks/abc257_a)

書くだけ.

```python
N, X = map(int, input().split())

print(chr(ord('A') + (X - 1) // N))
```

## [ABC257B - 1D Pawn](https://atcoder.jp/contests/abc257/tasks/abc257_b)

素直にシミュレーションすればいい.

```python
N, K, Q = map(int, input().split())
A = list(map(lambda x: int(x) - 1, input().split()))
L = list(map(lambda x: int(x) - 1, input().split()))

cells = [None] * N
for i in range(K):
    cells[A[i]] = i

for l in L:
    t = -1
    for j in range(N):
        if cells[j] is None:
            continue
        t += 1
        if t == l:
            break
    if j != N - 1 and cells[j + 1] is None:
        cells[j + 1] = cells[j]
        cells[j] = None

result = [-1] * K
for i in range(N):
    if cells[i] is None:
        continue
    result[cells[i]] = i + 1
print(*result)
```

## [ABC257C - Robot Takahashi](https://atcoder.jp/contests/abc257/tasks/abc257_c)

予め体重をソートしておけば、指定の体重未満、以上の人数をにぶたんにより $O(\log N)$ で求めれるようになるので、$O(N \log N)$ で解けた.

```python
from bisect import bisect_left

N = int(input())
S = input()
W = list(map(int, input().split()))

a = sorted(W[i] for i in range(N) if S[i] == '0')
b = sorted(W[i] for i in range(N) if S[i] == '1')
c = set()
for x in W:
    c.add(x - 1)
    c.add(x)
    c.add(x + 1)

result = 0
for x in c:
    result = max(result, bisect_left(a, x) + len(b) - bisect_left(b, x))
print(result)
```

座標圧縮+累積和でも解けた.

```python
from itertools import accumulate

N = int(input())
S = input()
W = list(map(int, input().split()))

a = sorted(W)
d = {}
for i in range(len(a)):
    d[a[i]] = i + 1
W = [d[x] for x in W]
m = max(W)

b = [0] * (m + 2)
c = [0] * (m + 2)
for i in range(N):
    if S[i] == '0':
        b[W[i]] += 1
    else:
        c[W[i]] += 1
b = list(accumulate(b))
c = list(accumulate(c))
d = S.count('1')

result = 0
for i in range(m + 2):
    result = max(result, b[i] + (d - c[i]))
print(result)
```
macOSでSDカードを認識しない

MacBookProを使っている。

WindowsPCと違って、取り出す時に、バネで出てくる感じではない。
押し入れて、抜き出す。
圧力を加えない方式なのかもしれない。

最近SDカードを認識してくれずに困っていた。

「macOS SDカード読まない」検索した

MacでSDカードが認識しない原因と対策

https://www.reneelab.jp/sd-card-unrecognizable-in-mac.html

消し込むで接触面をこすればいいらしい。

こすった。

認識した。

悩まずに検索すればよかった。
ubuntu20.04  on RaspberryPi4 で kubernetes 入れて、可視化もした

ubuntu20.04 on RaspberryPi4 で Kubernetes 入れて、可視化もした
----------
Ubuntu(ラズパイ上)にKubernetes入れて動かすまでは、以下のリンク道理。
https://phoenixnap.com/kb/install-kubernetes-on-ubuntu

.bashrc に
export KUBECONFIG=$HOME/.kube/config
って入れるのは必須な追加ステップです。

可視化に使ったのは octant っていうプログラム。
ARM64向けのtar.gzファイルDLして中入って実行するだけ。
https://octant.dev/
https://github.com/vmware-tanzu/octant/releases/v0.25.1

なぜかUbuntu20.04、raspberryPi4 Model B (8GB)だと安定しない
(基本の kubectl コマンドも時間経過かなんかで通らなくなる)
のでそれの対処と、なにか作って走らせる事を次にしようと思います。
denied: requested access to the resource is denied

今日、dockerにpushしようとしたらエラーが出た。

denied: requested access to the resource is denied

https://hub.docker.com/billing/plan/update

をみたら、

>Current Plan
Personal, 1 person
Includes the Docker essentials and is ideal for individual developers, education, open source communities, and small businesses. 
Cost: $0
Docker Desktop
Unlimited public repositories
Docker Engine + Kubernetes
Limited image pulls per day
Unlimited scoped tokens

制限は１日あたりのpullであって、pushじゃないんじゃないのだろうか。

他に原因があるかもしれず、調査中。
ROS : 半自動にウェイポイントを抽出する

# waypoints generator csv 

半自動にウェイポイントを抽出するパッケージを開発しました．この記事ではそのパッケージについて説明します．
**[waypoints_generator_csv](https://github.com/HHorimoto/waypoints_generator_csv)**

# 概要

自律移動ロボットで地図を作成した後は通常，作成した地図からウェイポイントを抽出してそれに沿って自律移動ロボットを走行させるのが鉄板です．ウェイポイントを抽出する方法には様々な方法があると思いますが主に`Publish Point`や`Localization`を用います．そこでこのパッケージでは前述の方法を用いて半自動的にウェイポイントをを生成します．

# 環境

Ubuntu 18.04
ROS (Melodic)
Python 2.7.x

# 準備
+ `waypoints_generator_csv`パッケージをダウンロードしてください．

```shell
$ cd ~/catkin_ws/src/
$ git clone https://github.com/HHorimoto/waypoints_generator_csv.git
$ cd ~/catkin_ws
$ catkin_make
```

+ 動作に必要なパッケージをダウンロードしてください．　

```shell
$ sudo apt-get install python-blessed # for key click
```

# 使い方

このパッケージはウェイポイントを生成するための3つの方法を提供し、それらは起動ファイルのパラメータを介して選択することができます．
生成された`csv`ファイルは `graphs/` に保存されます。

```shell
$ roslaunch waypoints_generator_csv waypoints_generator_csv.launch
```
```shell
graphs/
    waypoints.csv
```

このパッケージには、生成されたウェイポイントをrvizに表示するだけのスクリプトも含まれています．これを起動したら、`rviz`の`add`ボタンから`Marker`トピックを選択します。

```shell
$ roslaunch waypoints_generator_csv publish_marker.launch
```

### パラメーター

+ ***select*** : どの方法でウェイポイントを生成するかを指定します。`key_click(k)` または `clicked_point(c)` または `threshold(t)`.
    defult : `threshold`.

+ ***file_name*** : 生成するウェイポイントを格納するファイル名.
    defult : `waypoints`

+ ***dist_th*** : 閾値に対するウェイポイントの距離間隔.
    defult : `7.0 [m]`.

+ ***theta_th*** : 閾値のウェイポイントの度数間隔.
    defult : `60.0 [deg]`.

+ ***use_debug_marker*** : `rviz`に保存されたウェイポイントを表示するかどうか。
    defult : `true`.

+ ***distance_tolerance*** : マーカー円の半径
    defult : `1.0 [m]`.

## スクリプトの詳細

### key_click_csv - key_click(k) - 
このスクリプトは、キーボードの`Enter`キーを押したときに、ロボットの現在位置をウェイポイントとして保存します。
#### デモビデオ

[![](https://img.youtube.com/vi/m_G_pSDUmiM/0.jpg)](https://www.youtube.com/watch?v=m_G_pSDUmiM)

### clicked_point_csv - clicked_point(c) - クリックされたポイント。
`rviz`で`Publish Point`ボタンを押すと、その位置がウェイポイントとして保存されます。
#### デモビデオ
[![](https://img.youtube.com/vi/qLuP5EoUV-Y/0.jpg)](https://www.youtube.com/watch?v=qLuP5EoUV-Y)
### threshold_csv - threshold(t)
設定された距離と角度の閾値を超えると、スクリプトは自動的にその位置をウェイポイントとして保存します。
#### デモビデオ
[![](https://img.youtube.com/vi/Ruk2BLimv_E/0.jpg)](https://www.youtube.com/watch?v=Ruk2BLimv_E)
Instagramから情報を取得してみた（Python）

# はじめに
Instagramから情報取得するInstaloderというライブラリを発見したので
Pythonで簡単なユーザ情報を取得してみました

# Instaloderについて
Instaloaderは、写真（またはビデオ）とそのキャプションおよびその他のメタデータをInstagramからダウンロードするためのツールです。（下記サイトより引用）

https://instaloader.github.io/

# 環境構築
下記コマンドを実行
```
pip3 install instaloader
```

# Instagramから情報を取得手順
今回はTwiceのモモさんの情報を取得してこようと思います
Twiceは最近知りました汗

https://www.instagram.com/momo/

```get_instagram.py
import profile
from instaloader import instaloader, Profile

# Instaloaderインスタンス作成
IL = instaloader.Instaloader()

id = 'momo' # モモさんのInstagramアカウントID
profile = Profile.from_username(IL.context, id)
# ユーザ名
username = profile.full_name
# 投稿数
posts = profile.mediacount
# フォロワー数
follewer = profile.followers
# フォロー数
follow = profile.followees

# 出力
print(f'ユーザー名：{username}\n投稿数：{posts}\nフォロワー数：{follewer}\nフォロー数：{follow}')
```

# 出力結果
```
python3 get_instagram.py 

>ユーザー名：모모 (MOMO)
投稿数：19
フォロワー数：6986352
フォロー数：0
```

次は投稿された画像も取得してみようと思います
GitHub Actioins でユニットテストを自動化

# 概要
- pull request をした時に GutHub Action でユニットテストを試してみます。

# テストコードを準備
- python の unittest を使用します
- https://docs.python.org/ja/3/library/unittest.html?highlight=test#module-unittest

```text: 階層
.
|- sample.py
|- tests - test_sample.py
|- .github - workflows - unit_test.yml
```
- 簡単な関数を作ります
```python: sanple.py
def add_num(num1, num2):
    return num1 + num2
```
- `add_num` に対してユニットテストを準備します
```python:test_sample.py
import unittest
import sample

class TestSample(unittest.TestCase):

    def test_add_num(self):
        result = sample.add_num(2, 3)

        self.assertEqual(5, result)
```
- テストを実行してみる （`tests`配下のテストを実行するコマンド）
```bash
python -m unittest discover tests
```
```text:結果
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
```
# GitHub Actions のファイルを準備する
- トリガーは `pull request` 一応 `workflow_dispatch`を定義して手動でも行える様にしました
- https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows
```yaml:unit_test.yml
name: unittest sample
on:
  pull_request:
  workflow_dispatch:
jobs:
  unittest:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: setup python
        uses: actions/setup-python@v2
        with:
          python-version: '3.8'
          architecture: 'x64'
      - name: get python version
        run: python -V
      - name: unittest for python
        run: python -m unittest discover tests
```
# GitHub Actions を実行
<p>プルリクを作成すると、GitHub Actions が実行されます。下の画像が実行結果です。

![スクリーンショット 2022-07-10 17.33.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733843/2c0c5114-4c03-fbca-daa3-7bbcdeea08ca.png)

<p>ユニットテストが失敗するパターンを試してみます。

![スクリーンショット 2022-07-10 17.36.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733843/726e8a58-fa5c-e038-85d0-811a5ef3556d.png)

<p>ユニットテストが失敗しても、マージ保護がないと、マージ出来てしますので、保護します。

- settings -> branches -> Add rule
- Require status checks to pass before merging にチェックを入れる
- GitHub Actions の jobs 名をセットする
![スクリーンショット 2022-07-10 17.42.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733843/30470e71-49ee-5295-80fc-31916ecb238c.png)
<p>これで、テスト失敗したコードが Default ブランチへマージされることを防げる様になるみたいです。
Fortigate リンクモニターの設定　自動でルートの切り替え

FortiGateのリンクモニターをCLIで設定する

【リンクモニターとは】
インターネット上の機器にポーリングで疎通監視を行い、問題が起きれば自動的にスタティックルートを切り替えてくれる。

【設定例】

#config system link-monitor 
#edit 8.8.8.8
(監視先のアドレス)
#set srcintf WAN1
(監視するルートへデータを送るインターフェース)
#set interval 2000
(pingを何秒間隔で送るか)
#set failtime 10
(何回pingが失敗したらルートを切り替えるか)
#set recoverytime 10
(何回pingの応答があったら復旧とみなすか）
#next
go.mod file not found in current directory or any parent directoryと言われたら公式チュートリアルを見よう

# はじめに
最近Go言語を触り初めて、よく`go.mod`がないよと怒られるので、備忘録として残しておきます。

もしくは[公式のチュートリアル](https://go.dev/doc/tutorial/create-module)を参照しましょう。

# 結論
#### `go mod init`を実行しよう
以下を実行して`go.mod`ファイルを作成しましょう。
```
% go mod init <project_name>
```

#### `go get`で使用するgitリポジトリを指定しよう
以下のように外部のリポジトリを使用する場合は指定しましょう。下のリポジトリは例です。
```
% go get github.com/rwcarlsen/goexif/exif
```
DockerのLambdaコンテナイメージをgolangで動かしてみた

AWSで公開されているgolangのLambdaコンテナイメージを動かしてみました。

## パッケージの構成
```
├── docker
│   └── lambda-go-test
│       └── Dockerfile
├── docker-compose.yml
└── lambda
    ├── go.mod
    ├── go.sum
    ├── main
    ├── main.go
    └── pkg
```

## Dockerファイル作成
[こちら](https://gallery.ecr.aws/lambda/go)を参考にDockerファイル等を作成。
```dockerfile
FROM public.ecr.aws/lambda/go:1

# Copy function code
COPY ../../lambda ${LAMBDA_TASK_ROOT}

WORKDIR ${LAMBDA_TASK_ROOT}
# golangをinstall
RUN yum install -y golang

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "main" ]
```

docker-compose.ymlは以下のように作りました。
```dockerfile
version: '3'
services:
    lambda-go-test:
        container_name: lambda-go-test
        build:
            context: .
            dockerfile: ./docker/lambda-go-test/Dockerfile
        volumes:
            - ./lambda:/var/task # ${LAMBDA_TASK_ROOT}は/var/taskだったので/var/taskを指定.
        ports:
            - 9000:8080
```

## golangファイル作成
```golang
package main

import(
	"context"
	"fmt"
	"github.com/aws/aws-lambda-go/lambda"
)

type Request struct {
	FirstName string `json:"first_name"`
	LastName string `json:"last_name"`
}

func requestHandler(ctx context.Context, req Request) (string, error) {
	return fmt.Sprintf(
		"Hello %s %s",
		req.LastName,
		req.FirstName,
	), nil
}

func main() {
	lambda.Start(requestHandler)
}
```

## dockerをbuildして立ち上げ
```
$ docker-compose build
$ docker-compose up -d

# 初回なのでdockerコンテナ内に入って「go mod init」と「go get」
$ docker exec -it lambda-go-test bash

# ----- コンテナ内 -----
bash# pwd
/var/task

# go mod init
bash# go mod init lambda-go-test

# golang内で利用しているパッケージをgo get
bash# go get github.com/aws/aws-lambda-go/lambda
```

## 動かしてみる
```
$ curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"first_name":"taro", "last_name":"lambda"}'
"Hello lambda taro"
```
:::note warn
初回叩いた時は↓のエラーが返ってきたけどdocker再立ち上げしたら動いた... なんだったんでしょう。
:::
```
{"errorMessage":"fork/exec /var/task/main: no such file or directory","errorType":"PathError"}
```

## 最後に
今回はここまでにします。
次回はもっと色々試してみた結果をこちらに書いていければと思ってます。
XcodeでiOSスマホアプリ作成

# この記事の概要

Xcodeを使ってスマホアプリ画面を表示する手順を簡単に記載する

# Xcodeの環境構築

こちらのページから

https://apps.apple.com/jp/app/xcode/id497799835?mt=12

# Xcodeでアプリ作成

## 新規プロジェクト作成

Appから「Create a new Xcode project」
→「App」を選択する
→アプリ作成

![スクリーンショット 2022-07-10 16.50.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711205/a89538f3-dfef-b5f1-1ccd-d952665ba3bf.png)

## アプリ画面表示

左上の再生マークをクリックする
→シミュレーターが表示される
TypeHintがPythonの高速化に貢献していくとよいな

結論から述べると、mypycに、効果的な高速化への期待は難しいんじゃないかと思う。

ですが、シームレスに少しは早くなるのは、ecosystem的には良いことかと思います。

ただ、既にCythonが進んでいる。そのため、mypycとCythonが重複した選択肢となる。なんとか協調してより開発を進めて頂きたい。

----

残念ながら、TypeHintを付記するだけで高速化しない(2022.07現在)。期待された人は多いかと思うが(私もその一人)。

しかし、C言語へトランスコードして高速化するmypycが開発がされています。
- https://github.com/mypyc/mypyc


mypycの名前でお察しの方/既知の方いらっしゃるとおもいますが、MyPyプラグインと協調して行くスタイルのようです。

メリット
1. C言語化に必要な型を指定を、デフォルト`typing`の型で指定できる。
    1. つまり、TypeHintを付記する、と、その型に基づいてC言語化の際の型指定ができ、後付で型指定が不要。
1. 標準化しつつ有るMyPyで型付けされたコードを、Py->C言語コードへのトランスコードを**適切かつシームレス化**する意図なのでしょう。
    1. 既にCythonがあります。Cython専用のTypeHintを使わなくても、デフォルトのTypeHint（`typing`)でトランスコードの型最適化できるのはよいかもしれません。

ただ、Cythonのサイトに記載されたPure Pythonモードでは高速化できるのは20-60%らしいので、mypycでも大幅な高速化は難しいんじゃないかと思う。
トランスコードだけではなく、最適化はPyPyが進んでいるように思います。
RoboFormでサイトログインする際の二要素認証を設定する。

# はじめに
私は普段`RoboForm`というパスワードマネージャを使ってパスワードなどを管理しておりますが、各サイトにログインするときの二要素認証を設定しようと調べてみたとき、検索で出てこなかったので記載しておこうと思います。

# RoboFormでサイトログインする際の二要素認証設定
`RoboForm`はQRコード読み込みに対応していないため、テキスト形式での登録を行う必要があります。

デフォルトではQRコードしか表示されていないようなサイトでも、テキスト形式で表示するリンクやボタンがあるはずなので、見つけて表示させます。

`RoboForm`で二要素認証を設定したいログイン設定の「**編集**」を選択すると、まだ二要素認証を設定していないログイン設定の場合、「**2要素認証キー**」に「**追加**」ボタンが表示されているはずなので追加を選択します。

![001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/be93445b-2a39-e191-2843-09a82577bcd5.jpeg)

ボタンを選択すると以下のような画面が表示されるため、各サイトの二要素認証設定画面から確認したテキスト形式の秘密鍵をコピペして登録するだけです。

![002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/9d9c98b9-dc03-912f-8508-c58f68610a33.jpeg)

登録が成功すれば、先ほど「**2要素認証キー**」と表示されていた個所に「**確認コード**」が表示されます。

![003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/34f41200-ad4c-9e64-0ac7-72a0567e943a.jpeg)

`RoboForm`に登録するついでに、スマホの`Authenticator`アプリでも登録しておくと`RoboForm`にアクセスできない場合も使えるため、追加しておくと良いかと思います。

尚、QRコードでもテキスト形式の鍵情報でも表示されるワンタイムパスワードはどの認証アプリでも変わらないため、もし`RoboForm`で表示されるワンタイムパスワードとスマホの`Authenticator`アプリで表示されるパスワードが異なる場合はどちらかが登録が誤っている可能性があるので、再度登録しなおしましょう。

# すでに別のAuthenticatorアプリで登録している場合
どのサイトでも後からデバイス（`RoboForm`など）を追加することはできないので、すでに別の`Authenticator`アプリで登録している場合は、一度二要素認証を無効化してから再度登録しましょう。

# おわりに
パスワードマネージャに二要素認証の設定を行っておけばいちいちスマホの`Authenticator`アプリを立ち上げて手動で入力しなくても安全に素早く入力できるため、二要素認証の設定があるパスワードマネージャを使っている方はぜひ設定しましょう。
AWS SQSの用語要点まとめ（自分用メモ

・Amazon Simple Queue Service（SQS）
フルマネージドのメッセージキューイングサービスです。「メッセージキューイング」とは個々のサービスやシステムを「メッセージ」を使用して連携する仕組みのこと

サービスAはクライアントからのリクエストを受け、キュー（queue）と呼ばれる領域にリクエスト（メッセージ）を投入します。サービスBはキューからメッセージを取得し、処理。

メッセージキューを利用すると、お互いのサービスがそれぞれの状況に関係なく（非同期で）処理を進行できるため、サービス間の結合度が低くなります。このように、システムを構成するサービスやコンポーネント間の結合度や依存度を低くし、独立性を高めることを「疎結合」または「デカップリング」といいます。
サービス間の結合度を低くすると以下のようなメリットがあります。
・関連するサービスの負荷や処理状況に引きずられずに自身の処理を進行できる
・関連するサービスで障害が発生した場合やアップデートなどの際に影響を受けずに済む
SQSはこのようにサービス同士を橋渡しする役割を持つAWSサービスです。

【SQSのユースケース】
SQSのユースケースには以下のようなものがあります：
○トラフィックの量が想定できないようなケース
例えばデータベースシステムに対して大量にリクエストを投入する場合、データベースシステム側が高負荷になり処理の遅延が発生する可能性があります。SQSを導入すると、データベースシステム側は負荷に応じてキューのメッセージを処理できるため、処理遅延が発生しにくくなります。

○Auto Scalingによって運用負荷を軽減するケース
リクエストが急激に増加した場合、SQSとCloudWatch、Auto Scalingを連携することでサーバーを自動的にスケーリングできます。リクエストの増加によりSQSに滞留したメッセージ数がしきい値を超えたときにCloudWatchがアラートを上げ、Auto Scalingがサーバーを増やします。キューにメッセージがなくなり次第スケールインすることで、コストを抑えた運用が実現できます。

○優先順位を設定したいケース
SQSではキュー内のメッセージの優先度を変更することはできませんが、キューを使い分けることで処理の優先順位を操作します。
優先度の高いキューと低いキューの2つを用意し、メッセージを送信する側で優先度によってメッセージを投入するキューを使い分けます。メッセージの受信側は、先に優先度の高いキューにあるメッセージを処理し、完了後に優先度の低いキューを処理します。

【SQSの機能】
■標準キューとFIFOキュー
SQSには2種類のキューがあります。キューの種類は作成時に選択し、作成後は変更できません。

・標準キュー
メッセージの処理順序は保証されず、送信された順番と異なることがあります。また、タイミングによっては同じメッセージが二度配信される可能性があります。メッセージの処理順序や、同じメッセージを受信した際の処理については、受信側で制御する必要があります。

・FIFOキュー
送信された順番にキューに残っている最も古いものからメッセージを処理します。また、メッセージを二重に取得することもありません。

標準キューと比べてFIFOキューの方が機能的に優れている分、利用料金はFIFOキューの方が高く設定されています。また、1秒あたりの処理件数は標準キューが優れています。

■ショートポーリングとロングポーリング
キューからメッセージを取得する方式には「ショートポーリング」「ロングポーリング」の2種類。
メッセージを取得する際、ショートポーリングではメッセージがあった場合はメッセージを返し、メッセージがない場合でも即座に「空である」というレスポンスを返します。
一方ロングポーリングでは、メッセージがあった場合はメッセージを返す点は同じですが、メッセージが空である場合は設定された時間（最大20秒）を待ちます。時間が経過してもメッセージを得られない場合は、「空」というレスポンスが返ります。
ショートポーリングの場合はSQSに対するAPIコールの数が増えやすく、コストが高くなる可能性があります。その場合、ロングポーリングを使用してAPIコール数を抑えることにより、コストを削減できる可能性があります。
AWSではロングポーリング方式の使用を推奨しています。

■遅延キューとメッセージタイマー
メッセージの送信者が送信したメッセージを指定時間経過後に受信させたい場合には、「遅延キュー（Delay Queue）」または「メッセージタイマー（Message Timer）」を使用します。
キューに投入されたメッセージは、指定された時間が経過した後に受信可能になります。
遅延キューはキュー全体に対して作用し、メッセージタイマーは特定のメッセージに対して作用。

■可視性タイムアウト（Visibility Timeout）
キューのメッセージは、受信側が明示的に削除指示をしないと削除されません。SQSのメッセージを受信するクライアントが複数ある場合、タイミングによっては、メッセージが削除される前に複数のクライアントでメッセージを受信してしまうことがあります。
可視性タイムアウトはこれを防ぐために、一度クライアントがメッセージを受信した後、指定時間（デフォルト30秒）が経過するまでそのメッセージが他のクライアントからは見えないようにします。
なお、可視性タイムアウトはデフォルトで有効。

■デッドレターキュー（Dead Letter Queue）
データやシステムの都合で必ず処理がエラーになるようなメッセージがあった場合、メッセージはキューに残り続けます。その場合キューにはメッセージが滞留し、受信側ではエラーになる処理をリトライし続けてしまいます。
SQSでは、一定の回数（1～1000）エラーになったメッセージを通常のキューから分離し、「デッドレターキュー」に配置します。デッドレターキュー上のメッセージは受信されませんので、エラーを繰り返すこともありません。
AWS Direct Connectの用語要点まとめ

・AWS Direct Connect（DX）
オンプレミスなどのユーザー環境からAWSへ、専用回線を使ってセキュアに接続するサービス。インターネット回線ではなく専用回線を敷設して使用するので、安定した高速なネットワークで接続。
Direct Connectは、Direct ConnectロケーションのDirect ConnectエンドポイントからAWSネットワークへの接続を保証しています。AWSユーザーはDirect Connectロケーション内にルーターを設置し、オンプレミスから専用線を引き込む必要があります。工事費用と時間をかけてでも、安定した通信と強固なセキュリティ環境を求めるケースに適しています。

・AWSへのセキュアな接続
オンプレミスなどのユーザー環境からAWSへ接続する場合、通常はインターネット回線を経由します。しかしインターネット回線は不特定多数の利用者と回線を共用するため、通信内容の傍受やデータの改ざんなどのリスクがあります。このようなリスクを軽減し、AWSへセキュアに通信できるサービスが「AWS Direct Connect」と「AWS VPN」です。


○AWS Direct Connectロケーション
Direct Connectロケーションとは、オンプレミスとAWSのデータセンターとを相互に接続するポイントのことです。各リージョンに複数用意されており、ユーザーは接続するロケーションを選択できます。東京リージョン（ap-northeast-1）では、東京や大阪など5つのロケーションが用意されています（2022年1月時点）。

○AWS Direct Connectエンドポイント
Direct Connectエンドポイントとは、Direct Connectサービス提供範囲にあるオンプレミス側の終端のルーターのことです。Direct Connectロケーション内に物理的に設置されており、AWSユーザーが設置したルーターと接続します。

・Direct Connectを使用した接続の種類
Direct Connectにはパブリック接続とプライベート接続があります。パブリック接続はS3やDynamoDBなどのVPC外にあるAWSリソースへの接続に利用します。プライベート接続はVPCに仮想プライベートゲートウェイ（VGW：Virtual Private Gateway）を配置し、VPC内のAWSリソースへ接続します。

・Direct Connectゲートウェイ
Direct Connectのプライベート接続はDirect Connectエンドポイントと仮想プライベートゲートウェイを1対1で接続するので、通常は1つのVPCにしか接続できません。Direct Connectエンドポイントから複数のVPCに接続したい場合は「Direct Connectゲートウェイ」を利用します。
Direct ConnectゲートウェイはDirect Connectエンドポイントと仮想プライベートゲートウェイの間に配置されて、世界中の各リージョンにある複数のVPCへ接続できるようになります。なお、VPCは他のAWSアカウントのものであっても接続できます。
Direct Connectゲートウェイで接続した複数のVPCは、Direct Connectエンドポイントとの通信は可能ですが、Direct Connectゲートウェイ経由でVPC同士の通信はできません。VPC同士の通信を行う場合は、VPCピアリングもしくはAWS Transit Gatewayを利用します。なおVPCピアリングとTransit Gatewayの詳細は、分野「VPC」を参照してください。

・Direct Connectの高可用性の実現
Direct Connectでは、オンプレミスから複数のDirect Connectロケーションへの接続をサポートしています。利用しているロケーションの障害に備えて複数のロケーションへ接続することで、可用性を高められるようになっています。
例えば、オンプレミス環境から東京に存在するロケーションと大阪に存在するロケーションへDirect Connectを接続することで、自然災害時の影響を少なくすることが期待できます。

・AWS VPN
AWS VPN（Virtual Private Network）はオンプレミスなどのユーザー環境からAWSへ、インターネットVPNでセキュアに接続するサービス。AWS VPNではインターネット回線を利用するので、専用回線を敷設するDirect Connectよりも安価に、かつ短い期間で接続を開始できます。


・・AWS VPNには「AWS Client VPN」と「AWS Site-to-Site VPN」の2種類の接続方法。

■AWS Client VPN
AWS Client VPNは、パソコンなどの端末とVPCのClient VPNエンドポイントを、インターネットVPNで接続するサービスです。OpenVPNというVPNソフトウェアを利用しており、Windows、macOSだけでなくiOSやAndroidにも対応しています。Client VPNは機器の導入等が不要なので、手軽にセキュアな通信でAWSへアクセス。

■AWS Site-to-Site VPN
AWS Site-to-Site VPN（サイト間VPN）は、カスタマーゲートウェイ（オンプレミスのルーター）とVPCの仮想プライベートゲートウェイを、インターネットVPNで接続するサービスです。Site-to-Site VPNはインターネット上に仮想の専用線であるVPNトンネルを張り、IPsecという暗号技術を使って通信を保護。


○AWS Site-to-Site VPNの高可用性の実現
AWS Site-to-Site VPNで使用する仮想プライベートゲートウェイとVPNトンネルは、機器障害に対する高可用性を保つためにAWS側で冗長化されています。一方、カスタマーゲートウェイはオンプレミス内の機器なので、高可用性を保つにはAWSユーザー側で冗長化する必要があります。

○AWS Site-to-Site VPNのネットワーク監視
VPNトンネルを経由したネットワークトラフィック情報は、Amazon CloudWatchで収集できます。CloudWatchには指定した仮想プライベートゲートウェイのVPNトンネルの状態、送受信したバイト数が記録されます。VPNトンネルの状態をCloudWatchで監視すれば、VPNトンネルに異常が発生した場合にアラームを出すことができます。
Dockerコンテナをsystemdで自動起動する

# やりたいこと

Dockerコンテナをsystemdで自動起動する。
Dockerコンテナはこちら。

https://qiita.com/ryot0/items/f98ca54f5c3b748b0c12


# 手順

### systemdスクリプトを配置する

```text:/etc/systemd/system/docker-samba.service
[Unit]
Description=Samba Docker Container
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker start -a sambacont01
ExecStop=/usr/bin/docker stop sambacont01

[Install]
WantedBy=multi-user.target

```


### 自動起動の設定

```shell
sudo systemctl enable docker-samba.service
```
プログラミング学習サイト　ProgateでWebページ作成


先日オンライン学習サイトProgateにて　”Web開発コース(Node.js)”　を完了しました。
プログラミングを始めたいと思っている方は始めやすい学習サイトだと思いますので、良かった点紹介したいと思います。


## Progateとは

オンラインのプログラミング学習サービスです。2014年にサービスが開始され、現在ではユーザー登録数は260万人を超え、提供国数も世界100か国以上という実績を持っています。

Progateはレッスンが初心者でも分かりやすく工夫されているだけでなく、レッスンを1つ達成するごとにレベルアップしていく仕様になっているため、ゲーム感覚で楽しく学ぶことができます。

また、HTML・CSS・JavaScript・PHP・Rubyなどの人気言語を含めて、2種類のWeb開発コースと、16種類の言語別コースを学ぶことが可能です。

https://prog-8.com/



## よかった点

####  ★説明から実践を小さく繰り返しできる

Progateはスライド形式で学んだあとに、実際にすぐに自分でコードを書くを繰り返します。
コードを書き始めて分からないとスライドに戻るのも簡単。

書籍や動画形式だとまとめて学んで、実際にコードを書くのはあとでまとめてやることが多いです。
不明点の説明内容への検索性が悪かったりしますが、Progateではわかりやすいスライド形式で理解が進みました。
スライドを読んだ後、10~20行くらいのコードを書く問題が出題され、書いた後コードを比較してあっているか正誤チェックしてくれます。

小さくステップを踏みながら進むことができ、正しいコードを書くと「Congratiation！」と表示され、小さく出来た！が繰り返される達成感が得られます。

####  ★コーディングに集中できる

Progateは環境構築不要で、コーディングすることができます。
コーディングを中心にどんどん学びを進めることができます。

私の場合はアプリより下位のミドルウェア～OS周りは業務で多く関わってきていたため、今回私が学びたいことにフィットしました。

しかし、Progateのコードは別環境に移せるようになっていて、フォルダ構成もProgate内で自分で配置するような学習ができます。私は基盤からアプリ開発までの一連も学びたくなり、以前投稿したAWS上にNodejsを導入しProgateで開発したコードを移植してみましたが、簡単に移植することができました。

https://qiita.com/milky0807/items/813ff1996ac82a675e4e


####  ★レスポンスが早くストレスがない
オンライン上で、スライド学習、コーディング、コード正誤チェックなどして、また簡単にyumでインストールするなどの内容を実践することができますが、各Progateのページの挙動はスムーズで、レスポンスは早くストレスなく進めることができました。
インフラエンジニアベースの私としては、裏ではどんな仕組みになっているのだろう、よく出来ているなと感心するばかりでした。


####  ★費用がお手頃
月額980円（税別）の有料会員になればすべてのコースを学ぶことが可能です。
無料登録では基本的なレッスンが受けられるので、まず無料で使って自分の好みで続けられそうだったら、始めてみるというのがおすすめです。

####  ★ゲーム感覚
にんじゃわんこと仙人というキャラクターのストーリー形式で学習が進みます。
レッスンを１つ終えるごとにレベルアップしていく使用になっていて、ゲーム感覚で進めることが出来ます。
見た目で楽しみながら進められるのもいいですよね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638048/0012827c-f75f-e06a-91ea-c732f492c3ce.png)


####  ★ほめてくれる
毎回問題を完了するごとに「Congratiation！」とほめてくれ、仙人のキャラクターがほめてくれます。
最終的にコースが終了すると終了証書が発行され、「おーやり切った！」という達成感を得られます。
褒められるとやっぱり嬉しくなるです。
もくもくと一人で学ぶ学習に、”褒められる”　要素がたくさんちりばめられているのは上手い仕組みづくりができているなと感心します。



## わるい点
特になかったです。（回し者ではないです）
あえて言うなら、今回私は、WEB開発コースを実施しましたが、他のオンライン学習サイトに比べるとコースの選択肢が少ないかもしれません。

他にも利用検討した学習サイトはこちら。どれも有名どころで、良い点もたくさんありました。
私は、どのサイトも何個が学習してみて、自分が好みのUIであったためProgateを選びました。
- ドットインストール
- CODEPREP
- Udemy




## さいごに
Progateを使う中でやっぱりよくできてるなとかすごいなと思うばかりでした。
教材として分かりやすく内容が充実しているだけでなく、学びのやる気の仕組みづくり、UIなど色んな点を上手く実現できているオンライン学習サイトだと思います。
今回Web開発コースNodejsのみでしたが、他のコースも続けてみようと思える学習サイトに出会えたので、少しずつ続けてみようかと思います。

Progateのサクセスストーリーをよんでいると、小学生も使って学んでいるそうです。
ゲーム感覚だし、モノづくりできてゲームより面白いかもしれません。
こういう若者がどんどん育っていくのを考えると、10年後、20年後の自分の働き方をやっぱちゃんと考えていかないとなと思うばかり。学習を続けていきたいと思います。

https://prog-8.com/success_stories
[Laravel]Laravelでフォームリクエストのテストを書く

# はじめに
今回は、フォームリクエストのテストを実装したので、その方法をご紹介します。

https://readouble.com/laravel/8.x/ja/validation.html

# 環境
- Laravel：8.83.4

# 1. FormRequest作成
FormRequestとは、Laravelでかけることのできるバリデーションで、コントローラーの処理前にリクエストの処理でバリデーションを行います。

https://qiita.com/HuntingRathalos/items/352ebef5d741a0eccbbb

今回は、以下のようなFormRequestに対するテストを書いていきます。
<details><summary><b>TargetRequest.php</b></summary><div>

```php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

class TargetRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|max:50',
            'amount' => 'required|integer',
        ];
    }

    public function messages()
    {
        return [
            'name.required' => '目標は必須です。',
            'name.max' => '文字数をオーバーしています。',
            'amount.required' => '目標額は必須です。',
            'amount.intger' => '正しい形式で入力してください。',
        ];
    }

    protected function failedValidation(Validator $validator): HttpResponseException
    {
        $response = response()->json([
            'status' => 'validation error',
            'errors' => $validator->errors()
        ], 400);
        throw new HttpResponseException($response);
    }
}

```

</div></details>

# 2. テスト実装
以下のような手順で進めていきます。
- フォームリクエストで定義したルールを取得
- バリデーターインスタンスを取得し、引数に入力情報（データプロバイダーで作成）とルールを渡す

これらの手順を踏まえて、サンプルコードは以下のようになりました。

```php
<?php

namespace Tests\Unit\Requests;

use Tests\TestCase;
use Illuminate\Support\Facades\Validator;
use App\Http\Requests\TargetRequest;
use Illuminate\Support\Str;

class TargetRequestTest extends TestCase
{
  /**
     * @test
     * @dataProvider validationProvider
     *
     * テストの期待値
     * @param bool $expected
     * フォームリクエストのモックデータ
     * @param array $data
     */
    public function バリデーションが通るか(bool $expected, array $data)
    {
        // フォームリクエストで定義したルールを取得
        $rules = (new TargetRequest())->rules();

        // Validatorファサードでバリデーターインスタンス取得、引数に入力情報とルールを渡す
        $validator = Validator::make($data, $rules);

        $this->assertEquals($expected, $validator->passes());
    }

    public function validationProvider()
    {
        return [
            'OK' => [
                'expected' => true,
                'data' => [
                    'name' => '漫画買う！！',
                    'amount' => 30000,
                ]
            ],
            'name必須エラー' => [
                'expected' => false,
                'data' => [
                    'name' => null,
                    'amount' => 30000,
                ]
            ]
        ];
    }
}
```
今回は数パターンのデータした用意しませんでしたが、
必要に応じてデータを用意することでリクエストを網羅的にテストすることができます。

以上で実装完了です。

# 3. 参考文献

https://jun-app.com/articles/laravel-validation-unit-test

https://nextat.co.jp/staff/archives/267
SwiftUIカスタムイニシャライザで@Bindingの初期化方法

普段はAndroidのエンジニアをしてますが、SwiftUIを触っていたところ、initが必要なSwiftUIを作成していたところBindingが初期化されてないことにハマったので記載しておこうと思います。


```TimeView.swift

    @Binding var dateTextTime: String
    @Binding var nowDate: Date

  init(dateTextTime: Binding<String>,nowDate: Binding<Date>) {
        self._dateTextTime = dateTextTime
        self._nowDate = nowDate
    }
```

引数の型は ``Binding<String>``と、``Binding<Date>``です。
名前の前に``_``を付けることが必要となります。

全然分からず悩みました。

普段Android開発をしてますが昔UI作るのに苦戦していたので、SwiftUiでUIを簡単に作れるようになったので、iOSの開発もやっていこうと思います。
僕はVS Codeが無いと生きていけないのでVimmerにもなろうと試みています。

# 未使用のVimコマンドを使用中のVS Codeショートカットに置き換えて考えてみる
## この記事を見るのにオススメな人
- プログラミング初心あ者である人
- Vim初心者
- Vimは知らないが、VS Codeは知っている人
- VS Codeは知らないが、Vimは知っている人
- VS Codeショートカットをほとんど知らない人
- VS Codeでの開発をしたことがある人
- 操作を効率化することが好きな人
    - VS Codeショートカットが好きな人！！！
    - Windowsショートカットが好きな人？

## 前提

- OS 
    - Windows11
- というか、 VimまたはVS Codeが動く環境ならなんでもよいと思っています。
- 特定の何かというのはないです。ただのやったことまとめみたいなものなので！

## 必要最低限覚えていないと Vim 人生が終了してしまうと思ったコマンド

|操作|コマンド|
|---|---|
|ノーマルモード|esc|
|インサートモード|i|
|一文字削除（ノーマルモード）|x|
|元に戻す（ノーマルモード）|u|
|元に戻すを元に戻す（ノーマルモード）|ctrl + r|
|終了|:q|
|保存して終了|:wq|
|強制終了|:q!|

## VScode で行っていた操作と Vim になった場合の表

|やっていた操作|VS Code|Vim|
|---|---|---|
|右に移動|→|l|
|左に移動|←|h|
|下に移動|↓|j|
|上に移動|↑|k|
|ファイルの先頭行に移動|ctrl + Home|gg|
|ファイルの末尾行に移動|ctrl + End|G|
|行の先頭へ移動(インデント無視して先頭へ)|Home Home|0|
|行の先頭へ移動|Home|^|
|行の末尾へ移動|End|$|
|行番号: 1へ移動|ctrl + G → 1 → Enter|:1 → Enter|
|半画面分 上へ移動|PgUp|ctrl + u|
|半画面分 下へ移動|PgDn|ctrl + d|
|一画面分 上へ移動|PgUp PgUp|ctrl + b|
|一画面分 下へ移動|PgDn PgDn|ctrl + f|
|段落毎に上へ移動|ctrl + {（関数を閉じる）|{|
|段落毎に下へ移動|ctrl + }（関数を閉じる）|}|
|単語の先頭へ移動|ctrl + ←|b|
|単語の先頭へ移動（.等を無視）|ctrl + ←|B|
|単語の末尾へ移動|ctrl + →|e|
|単語の末尾へ移動|ctrl + →|E|
|次の単語の先頭へ移動|ctrl + → ctrl + → ctrl + →|w|
|行を追加|ctrl + Enter|o（インサートモードへ移行）|
|行を追加|ctrl + shift + Enter|O（インサートモードへ移行）|
|行をコピー|ctrl + y|Y or yy|
|ペースト|ctrl + v|p|
|一行下へ行をコピー|shift + alt + ↓|Y or yy p|
|一行上へ行をコピー|shift + alt + ↑|Y or yy P|
|行を削除|ctrl + shift + k||
|行を切り取り|ctrl + x|dd|
|元に戻す（ノーマルモード）|ctrl + z|u|
|元に戻すを元に戻す（ノーマルモード）|ctrl + y|ctrl + r|
<!-- 
|表示上（1行内に改行がある場合）の上に移動||gk|
|表示上（1行内に改行がある場合）の下に移動|→|gj|
|下の行の先頭へ移動|↓ Home|+|
|上の行の先頭へ移動|↑ Home|-|
 -->




## 後書き（背景にあった事情）

### 僕の現状について

僕は専門学校を卒業後、ITエンジニアになりました。
しかし、業務にプログラミングがほとんどできなかったことや
社内の雰囲気に耐えらなかったこと等が理由で2週間ほど前に転職をしました。
半年過ない頃にはすでにもう辞めたい感はありましたが、まだ研修期間だったし、新社会人だし3年くらいはいたいなぁと思った頃もありました。
しかし、実務に入ってからも辞めたい思いは変わらず、むしろ強くなって行きました。
会社目線の僕の必要性や僕目線の得られるもの・失うもの等を考慮した結果、
行動するなら早いほうがいい。もう2年もいることはない。という結論に。

今の会社の雰囲気はとても明るくて、若い人達が多く、日々成長している感覚があり、前の職場では考えられないほど環境が良くなって仕事が毎日楽しいです。


### 今やりたいこと
前置きが長くなりましたが、
今までWebのサーバーについてほぼ触れてこなかったため、
勉強も兼ねて最近サーバー（新しい自作PC）を買いました。
サーバーを買ってまでやりたかったことを下に列挙します。

- Dockerについて勉強しつつ使ってみる
- 自作サーバーでWebサーバーを構築する
- 自作サーバーでポートフォリオサイトを公開する
- Raspberry PiのWebサーバーを新サーバーへ移行する
- 現状Netlifyで公開しているものを自作サーバーへ移行する
- GitHubで管理しているソースを自作サーバーで管理する（Backupも兼ねて）
- 自作サーバーでDBサーバーを作成する

### 同機
サーバー構築をしている段階で、エンジニアの方に教えてもらいながら仮想マシン作成や、サーバーの環境設定を進めています。
その方のViやサーバーについての知識が豊富ですごいけれど、VS Codeについては一切知らんとのことで、
「**ん～両方たしなむ程度にはできておいたほうが良いか**」とも思ったし、
「**Vim を使える様になれば今より効率も上がりそうだなぁ**」と思ったことがきっかけです・・・

というのは表向きで、**このエンジニアが知っていることは生きているうちにすべて吸収して絶対に超えてやる**っていう不純な動機だったりもします笑
ここまでご覧いただきありがとうございました！
SVGで日本語の手書き風アニメーションを作る

## １．今回作るもの

SVGファイルはベクターデータの画像ファイルになります。今回はillustratorで作成したSVGファイルをVivus InstantというWEBサービスで簡単に手描き風のアニメーションを作成します。

## ２．ベクターデータ作成

![svg_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704639/e7b6deab-6e57-9bde-ad3c-077365d682dd.jpeg)


まずillustratorでベクターデータを作成します。Vivua Instantでは描いた線を順番通りにアニメーション化するので、全て線で描画します。そのため難しいフォントは再現できませんが、手書き風フォントなどならば近いものが作成できると思います。今回はGoogle Fontsの**Kiwi Maru**を使用します。線は適当な太さにして、線端を丸形線端。角の形状をラウンド結合にしました。文字ツールで描画した赤い文字の下書きを、ペンツールでなぞっていきます。書き終わったら下書きを削除して、必要に応じてずれてしまった場所などを微調整すれば、ベクターデータはできあがります。

## ３．Vivus Instantで線画をアニメーションに変換

SVGファイルとして保存したら、[https://maxwellito.github.io/vivus-instant/](https://maxwellito.github.io/vivus-instant/)　にアクセスして、作ったSVGファイルをドラッグしてください。するとアニメーション化されたSVGファイルが生成されます。ですが、このままだとほとんど同じタイミングで全ての文字が描画されてしまいます。

ですので、左のパネルにあるAnimation typeの欄をDelayed startからOne By Oneに変更しましょう。そしてUpdateをクリックすると、順番通りに文字が描画されるアニメーションが生成されます。他にもアニメーションのスピードなど、設定を調整できるようになっています。DownloadをクリックすることでアニメーションのついたSVGファイルがダウンロードされます。

## ４．おわりに

いかがでしたでしょうか。英字での手書き風アニメーションの解説ページはたくさんあったのですが、日本語を扱っているサイトがなかなか見つからなかったため、このたび学んだことをベースに記事を書かせていただきました。初学者のため至らぬ点など多々あると思いますが、記事に対してご意見・ご感想頂けますと幸いです。
Pythonで黒歴史晒して優勝する。

## あらすじ
今の会社に就職する前、趣味でクソアプリの製作に励んでいたことがあります。ワンちゃんの犬種を当てるクイズアプリです。
https://dachs.herokuapp.com/
具体的にどのようにクソか説明しますと、

- JavaScriptを使って画像に対してonClickイベントで実装しており、正解でも不正解でも次の画像に送られない。(画像と問題が合っていない)
- 画像サイズの変更がされていないため犬種によって出題の画像サイズがまちまち。
- herokuの無料枠でデプロイされており動作が重い。
- 「サルーキ」と「ボルゾイ」、「フレンチブル」と「ボストンテリア」、「ラフコリー」と「シェルティ」のように画像からの判別が困難なものが含まれている。

過去の黒歴史と決別すべく、救済策を講じようと思い立ちました。


## 具体策
Pythonを使って正解になっている犬種のワンちゃんの画像をスクレイピングします。
クソアプリの方は誰からも見向きもされませんが、スクレイピングは多くの方の役に立ちます。
読んでくださった方の一助となれば幸いです。
（今回はビーグルを例に挙げて説明します。）
実行環境は手軽なGoogle Colabを選定しました。
環境構築が不要な点が素晴らしい。


**正解のワンちゃん**
- ビーグル
- 柴犬
- スピッツ
- ビションフリーゼ
- ボーダーコリー
- レオンベルガー
- ボルゾイ
- アメリカンコッカースパニエル
- シャーペイ
- ボストンテリア
- ジャックラッセルテリア
- サモエド
- グレートピレネーズ
- アラスカンマラミュート
- シェルティ
- パグ
- ミニチュアブルテリア
- 狆(チン)

むしろ最終問題までたどり着くことが困難になっています。笑
今回はビーグルのうち一枚を取得します。

## 実際に書いたコード

```beagle.py
import requests
from bs4 import BeautifulSoup

url = 'https://www.google.com/search?q=%E3%83%93%E3%83%BC%E3%82%B0%E3%83%AB+%E5%AD%90%E7%8A%AC&tbm=isch&ved=2ahUKEwjui_2Nne34AhURUN4KHWVcDWYQ2-cCegQIABAA&oq=%E3%83%93%E3%83%BC%E3%82%B0%E3%83%AB&gs_lcp=CgNpbWcQARgCMgQIIxAnMgsIABCABBCxAxCxAzIFCAAQgAQyBQgAEIAEMgUIABCABDIFCAAQgAQyBQgAEIAEMgUIABCABDIFCAAQgAQyBwgAEIAEEARQAFgAYKMKaABwAHgAgAFhiAFhkgEBMZgBAKoBC2d3cy13aXotaW1nwAEB&sclient=img&ei=ETPKYq6_JJGg-QbluLWwBg&bih=658&biw=1440&rlz=1C5CHFA_enJP815JP815'

res = requests.get(url)

res

soup = BeautifulSoup(res.text, 'html.parser')
img_tags = soup.find_all('img')
img_tags[10]

```

## コードの解説

1,2行目

```beagle.py
import requests
from bs4 import BeautifulSoup
```

Pythonのライブラリである「Besautiful Soup」を読み込んでいます。

4行目
```beagle.py
url = 'https://www.google.com/search?q=%E3%83%93%E3%83%BC%E3%82%B0%E3%83%AB+%E5%AD%90%E7%8A%AC&tbm=isch&ved=2ahUKEwjui_2Nne34AhURUN4KHWVcDWYQ2-cCegQIABAA&oq=%E3%83%93%E3%83%BC%E3%82%B0%E3%83%AB&gs_lcp=CgNpbWcQARgCMgQIIxAnMgsIABCABBCxAxCxAzIFCAAQgAQyBQgAEIAEMgUIABCABDIFCAAQgAQyBQgAEIAEMgUIABCABDIFCAAQgAQyBwgAEIAEEARQAFgAYKMKaABwAHgAgAFhiAFhkgEBMZgBAKoBC2d3cy13aXotaW1nwAEB&sclient=img&ei=ETPKYq6_JJGg-QbluLWwBg&bih=658&biw=1440&rlz=1C5CHFA_enJP815JP815'
```

Googleで画像検索した「ビーグル　子犬」の検索結果URLを指定して、変数urlに格納しています。

6行目
```beagle.py
res = requests.get(url)
```

URLを取得するよう命令を出します。

8行目
```beagle.py
res
```

ここまでの処理がうまくいっているかどうか確認します。
![スクリーンショット 2022-07-10 11.13.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/f99f3aba-f1ca-d1bf-7528-e4c2eef06c37.png)

<font color="red">**Response[200]が返ってきました。処理はうまくいっています！**</font>

10~12行目　を追記します。
```beagle.py
soup = BeautifulSoup(res.text, 'html.parser')
img_tags = soup.find_all('img')
img_tags[10]
```

Beautiful Soupで対象ページのhtml要素を取り出し、soupという変数の格納します。
格納したhtml要素を確認しています。
定義した変数img_tagsの中から１１番目を表示します。

実行結果
```beagle.py
<img alt="" class="yWs4tf" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRo2BTa0xcmcCvyfuQfBl321mY2cpyp2oIUZi-PHnKXPVjjtvcq-bw9FYD3sA&amp;s"/>
```
<font color="red">**無事画像データのリンクが返ってきました。処理はうまくいっています！**</font>

![スクリーンショット 2022-07-10 15.36.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/33e185c1-a602-7861-4f65-41a6288cf05c.png)
gorm & sqliteで時刻を上手に扱う方法

gormはgo言語でSQLを扱うためのORMパッケージ。
sqliteを扱うときに時刻で想定外の挙動となったため、調査した。
※sqliteは時刻型に対応しておらず、文字列型として扱う。そこに由来する問題だと思う。

https://gorm.io/ja_JP/docs/index.html

# 問題
localTimeやフォーマットのずれが出てくるため、単純に time.Now() を使ってinsert や select させると、想定通りに動作しなかった。

# 対処方針
unixtimeに揃えたり、timeのフォーマット（文字列）を意識して揃えたりすることでおそらく正常に動作する。



# 対策1  unixtimeに統一する

`CreatedAt int64`　　などに揃える。
これがシンプルで確実そうではあるのだが、 `time.Time`　のまま使いたいときはちょっと不満が残る。


# 対策2 文字列フォーマットを意識して操作する

`timeFormat = "2006-01-02 15:04:05.000-07:00"` を利用して、insertもselectも統一する。
gormでsqliteに書き込むと、上記のフォーマットの文字列になる。

そこで、文字列のフォーマットを全部手動で統一してやるときちんと動く模様。

```go
// UTC miliseconds に統一する例
const timeFormat = "2006-01-02 15:04:05.000-07:00"

func formatTime(t time.Time) string {
	t = t.UTC().Round(time.Millisecond)
	return t.Format(timeFormat)
}

```

```go
// queryも以下のようにやる
	db.Where("created_at > ?",formatTime(time.Now()) .Find(&users))

```
他人が書いたコードから仕様を理解するために工夫したこと

## はじめに
チーム開発で他人が書いたコードを理解するために工夫したことを書いていきます。

## 全体の構造を把握する
まず、大まかな構造を把握するためにディレクトリ名とファイル名を見て、
どのような機能を持っているかを大雑把に把握しました。

## ソースコードを読む
最初、構造を理解するために1行1行コードを読んでどんな構造になっているか
理解するようにしました。

それでは時間がかかるので、
自分の担当している範囲で関連している箇所だけ絞ってコードを読み、
構造を理解するようにしました。

また、自分の頭の中だけではわからなくなってしまった時は
自分なりに図などで紙などに書き、構造などをまとめてました。

## コードを書いた本人に質問
それでもわからない場合はコードを書いた本人に質問しました。
docker compose up --build でexit code: 100


[こちら](https://qiita.com/jhorikawa_err/items/fb9c03c0982c29c5b6d5)の記事を参考にPythonのDocker環境を作成しようとしたところ、`docker compose up -d --build`で以下のエラーが発生した。
先に書いておくと、参考記事の内容を正しく踏襲すれば何も問題はなかったので、参考記事には問題はない。

```shell
 => ERROR [3/7] RUN apt-get -y install locals && localdef -f UTF-8 -i ja_JP ja_JP.UTF-8                                                                                   0.6s
------
 > [3/7] RUN apt-get -y install locals && localdef -f UTF-8 -i ja_JP ja_JP.UTF-8:
#6 0.174 Reading package lists...
#6 0.472 Building dependency tree...
#6 0.559 Reading state information...
#6 0.624 E: Unable to locate package locals
------
failed to solve: executor failed running [/bin/sh -c apt-get -y install locals && localdef -f UTF-8 -i ja_JP ja_JP.UTF-8]: exit code: 100
```

ファイルの内容は以下の通り。

Dockerfile
```docker
FROM python:3.9
USER root

RUN apt-get update
RUN apt-get -y install locals && \
    localdef \
    -f UTF-8 \
    -i ja_JP \
    ja_JP.UTF-8

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja_JP
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

RUN apt-get install -y vim less

RUN pip install --upgrade pip
RUN pip install --upgrade setuptools

RUN pip install jupyterlab
```


docker-compose.yml
```yml
version: '3'
services:
  python3:
    restart: always
    build: .
    container_name: 'python3'
    working_dir: '/root/'
    tty: true
    volumes:
      - ./opt:/root/opt

```

## 解決方法

先に結論から書くと、Dockerfileの該当行に誤字があった。
該当行は日本語ロケールの設定を行う部分だが、localeではなくlocalと記述しているのが問題だった。
exit code: 100 で問題が起きた場合に、誤字がないかの確認を気をつけたい。

誤: 
```docker
RUN apt-get -y install locals && \
    localdef \
    -f UTF-8 \
    -i ja_JP \
    ja_JP.UTF-8
```
正: 
```docker
RUN apt-get -y install locales && \
    localedef \
    -f UTF-8 \
    -i ja_JP \
    ja_JP.UTF-8
```


## その他試したこと

誤字に気づくまでに試したことを備忘録的に列挙する。

### Dockerのディスク容量の削除

以下の記事を参考にDockerのディスク容量の削除をおこなった。
GUIでの操作がわかりやすくておすすめ。

https://note.yu9824.com/error/2022/03/19/docker-debian-gpg-error.html


### CPUのアーキテクチャの確認

こちらの記事によると、どうもM1Macで使用されているARMのCPUではDockerのimageが用意されてないことがあるらしい。

https://zenn.dev/suzuki_hoge/books/2021-12-m1-docker-5ac3fe0b1c05de/viewer/2-arm

自分の環境はM1 Macを使用してるため、以下のコマンドでCPUのアーキテクチャを確認した。

```shell
% uname -m
x86_64
```

しかし、Intel系のx86_64とのことなので問題はなかった。(以前いじった覚えがある)
pythonで決定木を作る最短解説

"python 決定木"とかでググると、世の中には大量の解説記事がありますが、サンプルが複雑だったりして読み解くのが面倒でした。

ということで、自分で解釈した使い方を書いておきます。
なお、決定木が何か？はある程度分かっていて「pythonで決定木を手っ取り早く作りたい」人が対象です。

[**たぶんこれがいちばんみじかいとおもいます**](https://dic.nicovideo.jp/a/%E5%A4%9A%E5%88%86%E3%81%93%E3%82%8C%E3%81%8C%E4%B8%80%E7%95%AA%E6%97%A9%E3%81%84%E3%81%A8%E6%80%9D%E3%81%84%E3%81%BE%E3%81%99)。

```python
import sklearn
import sklearn.tree

# 入力データの作成
features = [
	# [Width, Height, Channel]
	[1, 2, 3],
	[4, 5, 6],
	[7, 8, 9],
	[6, 2, 1],
]
targets = [
	"Red",
	"Green",
	"Blue",
	"Blue",
]
print(features, targets)

# 決定木の作成
tree = sklearn.tree.DecisionTreeClassifier(random_state=0, max_depth=2)
tree.fit(features, targets)

# 決定木の可視化
print(sklearn.tree.export_text(tree, feature_names=["Width", "Height", "Channel"]))

# 決定木の実行結果
print(tree.predict(features))
```

## 入力データの作成

入力データには2種類あります。1つは分類に使う特徴量(feature)、もう1つは分類結果(target)です。
それぞれ配列として持っておきます（numpy.arrayとかでも大丈夫です）。
今回は、適当に、幅・高さ・チャンネルという特徴量を作ってみて、分類結果は赤・緑・青・青になるという入力データにしました。
中身は適当です。

printすると

```
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [6, 2, 1]] ['Red', 'Green', 'Blue', 'Blue']
```

と出てくるだけですね。

## 決定木の作成

pythonで決定木を作るなら、sklearn.tree.DecisionTree*が一番楽っぽいです。
今回は分類なのでDecisionTreeClassifierを使います。

`DecisionTreeClassifier()`に渡す引数はいっぱいあるので、そこは使い方に合わせて調べてもらうとして、重要な引数は2つ

* `random_state`：乱数を使うところのシードを固定しておきましょう。そうしないと実行のたびに結果が変わってしまうので・・・。値はなんでもいいので0とか入れておけばいいです。
* `max_depth`：木の深さです。指定しないと実用的にならないので、適当に指定しましょう。

作ったら`fit()`を呼ぶだけですね。
なお、なんか世の中にはtargetに渡すものを文字列ではなくわざわざ整数の疑似変数にしているサンプルが転がっていますが、分類名をそのまま渡しても動きます（たぶん古い書き方？）。

## 決定木の可視化

作った決定木を可視化しましょう。

手っ取り早く確かめたい場合は`export_text()`でテキストで出力させるのが楽です。
ここで`feature_names`引数に特徴量の名前（今回は幅・高・チャンネル）を渡してやると、結果が見やすくなります（書かないと、`feature_0, feature_1`とか味気ない名前が適当に付けられます）。

結果をprintしてやると

```
|--- Width <= 5.00
|   |--- Channel <= 4.50
|   |   |--- class: Red
|   |--- Channel >  4.50
|   |   |--- class: Green
|--- Width >  5.00
|   |--- class: Blue
```

と出てきます。これは決定木そのもので解説することもないかなと思います。

なお、テキストだとこれ以上の結果は出てこないので、ジニ係数とかサンプル数とかもっと細かく結果を可視化したい場合は、`export_graphviz()`を使うのが便利です。細かくは解説しませんが

```python
sklearn.tree.export_graphviz(tree, out_file="tree.dot", feature_names=["Width", "Height", "Channel"])
```

とするとtree.dotというファイルが保存されるので、

```shell
$ dot -Tpng tree.dot -o tree.png
```

とかやれば画像で出てきます。
![tree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9926/b4f22120-c858-48ed-8db9-45b3aed82e43.png)

## 決定木の実行結果

最後に決定木に特徴量を入力した結果を見てみましょう。単に`predict()`に特徴量を突っ込むだけです。

printすると

```
['Red' 'Green' 'Blue' 'Blue']
```

とか出てきます。ちゃんと分類できてますね。

## まとめ

ということで、pandasとかでなんか色々やらなくてもscikit-learnで決定木は一瞬で作れますよ、という解説でした。
【requests】PythonでSocksProxyを使う備忘録

## SocksProxyを使う備忘録

こちらの記事でsshを介したSocksProxyの実装を紹介しているので合わせてご覧ください。

https://qiita.com/shuyaeer/items/c1ab313155e53b19e354

本記事ではProxyサーバーのアドレスを`localhost:55557`としています。適宜読み替えてください。

```Python
import time
import requests

def request(proxies={}):
    time.sleep(1)
    url = 'https://ifconfig.me' # グローバルIPを返してくれるwebサイト
    response = requests.get(url, timeout=5.5, proxies=proxies)
    print(response.text) # => ProxyサーバーのIPアドレス


proxies = {
    'https': 'socks5h://localhost:55557'
}

request(proxies)
```
`requests`へのProxyの渡し方はHTTP Proxyと同様ですが重要なのは辞書のキーとバリュー
`'https': socks5h://xxxx.xxx.xxx`とすることです。

```Python
proxies = {
    'https': 'socks5h://localhost:55557'
}
```

いつも以下のようにしがちなため、備忘録として残しました。

```Python
# だめな例
proxies = {
    'socks5h': 'socks5h://localhost:55557'
}
```
railsでparams.require(モデル)を指定したときにparam is missing or the value is empty:エラーが発生する

Webアプリケーションを初めて作成していたときに困ったエラーでparamsから受け取ったデータを保存するときにparamsの値が存在しないとエラーが出て困ったので、初学者で同じように困る方もいるのではないかと思い、今回の記事を作成しました。

下記のような記述をしていてエラーが出ました。
```posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.all
  end

  def new
    @post = Post.new
  end

  def create
    binding.pry
    Post.create(post_params)
  end

  private
  def post_params
    params.require(:post).permit(:text)
  end

end
```
```new.html.erb
<h1>新規投稿ページ</h1>
<%= form_with url: '/posts',method: :post, local: true do |form| %>
  <%= form.text_field :text %>
  <%= form.submit '投稿する' %>
<% end %>
```
投稿画面でテキストを投稿すると
param is missing or the value is empty: post
とエラーが発生

:::note alert
問題点
コントローラーで定義した下記のインスタンス変数
```posts_controller.rb
def new
 @post = Post.new
end
```
これがnew.html.erbで受け取れていない
```new.html.erb
<%= form_with url: '/posts',method: :post, local: true do |form| %>
  <%= form.text_field :text %>
  <%= form.submit '投稿する' %>
<% end %>
```
@postを受け取っていないので送信されたparamsの中にpostモデルのインスタンス変数がない
:::

:::note info
解決策
```new.html.erb 改善前
<%= form_with url: '/posts',method: :post, local: true do |form| %>
```
```new.html.erb  改善後
<%= form_with(model: @post, local: true) do |form| %>
```
model: @post部分でcontrollerのnewアクションで定義したインスタンス変数を受け取り、送信時に＠postのモデルインスタンスと紐づけて送信することで
require(:post)に値が入っている状態となる
:::


自分なりに調べたことへの解釈ですが、自分はこれでうまくいきました。
【TypeScript入門 #14】ユーザー定義の型ガード(TypeGuard)について

# 概要

オンラインサロン IT_KINGDOM で、typescript について学んだことを備忘録としてメモしていきます。

# 学習内容

- [ユーザー定義の型ガードとは](#ユーザー定義の型ガードとは)
- [ユーザー定義の型ガードの使用例](#ユーザー定義の型ガードの使用例)
  - [非同期処理の型ガード](#非同期処理の型ガード)
  - [filter関数の型ガード](#filter関数の型ガード)

# ユーザー定義の型ガードとは

型が不明(any)の場合、通常の型ガードでは型の絞り込みはできない。

```typescript
type UserA = { name: string; lang: "ja" };
type UserB = { name: string; lang: "en" };

export const foo = (value: any) => {
  if (value.lang === "ja") {
    // valueの型が不明(any)の場合、型の絞り込みを行うことができない
    return value; // 型:any
  }
  return value; // 型:any
};
```

ユーザー定義の型ガードを定義することにより、上記の場合も型の絞り込みができる。

```typescript
// `user is UserA`は、本関数のuserがUserAを必ず返すことを示す
const isUserA = (user: UserA | UserB): user is UserA => {
  return user.lang === "ja";
};
// `user is UserB`は、本関数のuserがUserBを必ず返すことを示す
const isUserB = (user: UserA | UserB): user is UserB => {
  return user.lang === "en";
};

export const foo2 = (value: any) => {
  if (isUserA(value)) {
    // valueの型が不明(any)の場合でも、返り値の型をUserAに絞り込める
    return value; // 型: UserA
  }
  if (isUserB(value)) {
    // valueの型が不明(any)の場合でも、返り値の型をUserBに絞り込める
    return value; // 型: UserB
  }
  return value;
};
```

# ユーザー定義の型ガードの使用例

## 非同期処理の型ガード

通常、API 等で取得した値の型は any になる。<br>
ユーザー定義の型ガードにより、型を付与することができる。

```typescript
type UserA = { name: string; lang: "ja" };
type UserB = { name: string; lang: "en" };

const isUserA = (user: UserA | UserB): user is UserA => {
  return user.lang === "ja";
};
const isUserB = (user: UserA | UserB): user is UserB => {
  return user.lang === "en";
};

// APIで取得した変数の型はanyになる
export const foo = async () => {
  const res = await fetch("");
  const json = await res.json();
  if (isUserA(json)) {
    // `isUserA`で絞り込むことにより、`json`の型をuserAに絞り込むことができる
    return json.lang;
  }
};
```

## filter関数の型ガード

現状、filter 関数の返り値に対して型の絞り込みはされていない（Typescript のバージョンアップにより改善される可能性あり）。<br>
ユーザー定義の型ガードにより、filter 関数の返り値の型を絞り込む。

```typescript
type UserA = { name: string; lang: "ja" };
type UserB = { name: string; lang: "en" };

const isUserA = (user: UserA | UserB): user is UserA => {
  return user.lang === "ja";
};
const isUserB = (user: UserA | UserB): user is UserB => {
  return user.lang === "en";
};

const users: (UserA | UserB)[] = [
  { name: "たなか", lang: "ja" },
  { name: "やまだ", lang: "ja" },
  { name: "ジョニー", lang: "en" },
];

// 下記のfilterでは、japaneseの型をuserAには絞り込めていない
const japanese = users.filter((user) => {
  return user.lang === "ja"; // 型: (UserA | UserB)[]
});
// `isUserA`を用いることでjapaneseの型をuserAに絞り込める
const japanese2 = users.filter(isUserA); // 型: UserA[]
```
【TypeScript入門 #13】Type Guard(型ガード)

オンラインサロン IT_KINGDOM で、typescript について学んだことを備忘録としてメモしていきます。

### 学習内容

- Type Guard とは
- typeof を使った TypeGuard
- JS メソッドを使った TypeGuard
- in 演算子を使った TypeGuard
- タグ付き UnionTypes を使った TypeGuard

### TypeGuard とは

条件式を用いて型を制限すること。型チェックを強化することで型に関する予期せぬエラーを防ぐ。

### typeof を使った TypeGuard

- `typeof`で変数の型を制限する

```typescript
export const foo = (value: string | number | boolean) => {
  if (typeof value === "string") {
    return value; // stringのみ
  } else if (typeof value === "number") {
    return value; // numberのみ
  }
  return value; // booleanのみ
};
```

### JS メソッドを使った TypeGuard

- JS で準備されている型取得機能を用いて、型を制限する（例：`isArray`）

```typescript
export const foo = (value?: string | string[]) => {
  if (Array.isArray(value)) {
    return value; // string[]のみ
  } else if (!value) {
    return value; // string または undefined
  }
  return value; // stringのみ
};
```

### in 演算子を使った TypeGuard

- 型のプロパティの型の違いを用いて、型を制限する

```typescript
type UserA = { name: string };
type UserB = { name: string; nickName: string };

export const foo = (value: UserA | UserB) => {
  if ("nickName" in value) {
    return value; // nickNameを持つUserB
  }
  return value; // nickNameを持たないUserA
};
```

### タグ付き UnionTypes を使った TypeGuard

- 型のプロパティの値を UnionTypes で識別し、型を制限する

```typescript
type UserA = { name: string; lang: "ja" };
type UserB = { name: string; lang: "en" };
type UserC = { name: string; lang: "fr" };

export const foo = (value: UserA | UserB | UserC) => {
  switch (value.lang) {
    case "ja":
      return value; // jaを持つUserA
    case "en":
      return value; // enを持つUserB
    case "fr":
      return value; // frを持つUserC
    default:
      return value; // こもこもnever
  }
};
```

### 参考

[TypeScript Deep Dive](https://typescript-jp.gitbook.io/deep-dive/type-system/typeguard)
Go言語でディレクトリを作成する方法

# はじめに
Pythonメインだったのですが、興味があってGo言語の勉強をしています。
趣味で撮った写真を自動で振り分ける際にディレクトリの作成を調べたのでまとめておきます。

さらに詳しい操作については[公式ドキュメント](https://pkg.go.dev/os)を参照しましょう。

#### 2022/7/11 00:59追記
`os.Mkdir("test", os.ModePerm)`と記載していましたが、`os.ModePerm`は[使用しない](https://twitter.com/mattn_jp/status/1546038794637672451?s=20&t=bqbMFn2ZyLs3fXdvc97QcA)みたいです。調べてみて`FileInfo.Mode() & os.ModePerm`を利用した方法に変更しましたが、間違っていたら教えていただえると嬉しいです！


# ディレクトリを作成する方法
以下のコードを`main.go`に記載し、`go run main.go`を実行すれば実行したディレクトリで`/test`が作成されているはずです。

```
package main

import (
	"log"
	"os"
)

fileInfo, err := os.Lstat("./")

if err != nil {
	fmt.Println(err)
}

fileMode := fileInfo.Mode()
unixPerms := fileMode & os.ModePerm

if err := os.Mkdir("test/", unixPerms); err != nil {
	log.Fatal(err)
}

```

しかし、以下のコードは動きません。
```
package main

import (
	"log"
	"os"
)

fileInfo, err := os.Lstat("./")

if err != nil {
	fmt.Println(err)
}

fileMode := fileInfo.Mode()
unixPerms := fileMode & os.ModePerm

if err := os.Mkdir("case/case01", unixPerms); err != nil {
	log.Fatal(err)
}
```

```
% go run main.go
20XX/XX/XX XX:XX:XX mkdir case/case01: no such file or directory
exit status 1
```



# サブディレクトリも含めて作成する方法
サブディレクトリを含めて作成する場合は`MkdirAll()`を使用しましょう。
```
package main

import (
	"log"
	"os"
)

fileInfo, err := os.Lstat("./")

if err != nil {
	fmt.Println(err)
}

fileMode := fileInfo.Mode()
unixPerms := fileMode & os.ModePerm

if err := os.MkdirAll("case/case01", unixPerms); err != nil {
	log.Fatal(err)
}
```
上記のように記載すればサブディレクトリも含めて作成することが可能です。

# さいごに
Go言語難しいな。。。

# 参考
- https://stackoverflow.com/questions/56434432/golang-convert-os-modeperm-into-string
- https://twitter.com/mattn_jp/status/1546038794637672451?s=20&t=164J5ZB_THq1u38KcCn17g
vbaツール

セールからパスを開く
```
Sub openfloud()

    Dim addressStr As String

    addressStr = Application.Selection.Address

    Dim fso As FileSystemObject

    Set fso = New FileSystemObject
    
    addressStrArr = Strings.Split(addressStr, ":")
    
    If UBound(addressStrArr) <> 0 Then
        MsgBox "セールを選択してください。"
    ElseIf fso.FolderExists(Range(addressStr)) Then
    
        Shell "cmd.exe /c explorer.exe " & Range(addressStr)
    
    End If
    

End Sub
```