OmniAICreator/Qiita-1.07M huggingface dataset:
Minikubeの環境構築



Minikubeの環境構築の手順についてまとめました。


# Minikubeとは

Minikubeは、ローカル環境でKubernetesを簡単に実行するためのツールです。 Kubernetesを試したいユーザーや、Kubernetesを使った開発を検討しているユーザー向けに、PC上のVM内でシングルノードのKubernetesクラスタを実行することができます（引用元：[Kubernetes公式サイト](https://kubernetes.io/ja/docs/setup/learning-environment/minikube/)）。


# 環境

- macOS Big Sur 11.1　(Silicon m1 chip)


# Minikubeインストールの事前準備

Minikubeをインストールする前に、以下のツールやアプリケーションを準備します。


# 事前準備

- Docker
- Virtualization Software（例：VirtualBox）
- kubectl



## Docker

macOS で Dockerを使うには、Docker アプリ（[Docker Desktop](https://www.docker.com/products/docker-desktop)）をインストールするか、[Homebrew](https://brew.sh/index_ja) でインストールします。



## 仮想化ツール

Minikubeを起動するには仮想マシンが必要です。おすすめのソフトウェアは[Virtual Box](https://www.virtualbox.org/)です。[公式サイト](https://www.virtualbox.org/)からツールをダウンロードし、インストールします。


## kubectl

kuberctlは、Kubernetes Controllerと呼ばれるツールです。Kubernetesオブジェクトの操作は、kuberctlにコマンドを入力し、実⾏します。

まずはワーク用ディレクトリにパッケージをダウンロードします。

```sh
$ mkdir ~/workspace; cd ~/workspace
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/darwin/amd64/kubectl
``` 

ディレクトリに対する権限を設定します。

```sh
$ chmod +x ./kubectl
```


ディレクトリを以下のパスに移動します。

```sh
$ sudo mv ./kubectl /usr/local/bin/kubectl
```


これでkubectlの⽤意が完了しました。Dockerが起動している状態で以下のコマンドを入力します。

```sh
$ kubectl version --client
```


以下のように、kubectlのバージョンが表⽰されたら、インストールは成功です。

```sh
Client Version: version.Info{Major:"x", Minor:"xx", GitVersion:"vx.xx.x", GitCommit:"XXXXXXXXXXXXXXXXXXXXX", GitTreeState:"clean", BuildDate:"XXXXXXXXXX", GoVersion:"xxx.xx.x", Compiler:"xx", Platform:"darwin/arm64"}
```



# Minikubeのインストール

`brew` コマンドでインストールします。

```sh
$ brew cask install minikube
```


なお、M1 チップ Mac を使われている場合は、M1 チップに対応しているバージョンの minikube をダウンロードする必要があります。

まずm1チップMac用のファイルをダウンロードします。

```sh
$ wget https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-arm64
```

ダウンロードしたファイルの権限を設定します。

```sh
$ chmod +x minikube-darwin-arm64
```

そしてファイルを以下のパスに移動します。

```sh
$ sudo mv minikube /usr/local/bin/
```

これでminikubeのインストールが完了です。


Docker が起動している状態で、以下のコマンドで minikube を起動します。

```sh
$ minikube start 
```

minikubeを起動した後に、以下のファイルが作成されます。

```sh
~/.kube/config
```


以下のコマンドで、minikubeのバージョンが確認できます。

```sh 
$ minikube version 
```

以下のように、minikubeのバージョンが表⽰されたら、インストールは成功です。

```sh 
minikube version: v1.23.2
```

# 参考サイト一覧

https://github.com/kubernetes/minikube/issues/9224

https://mirairo.net/minikube-on-m1/

https://ithelp.ithome.com.tw/articles/10192490

https://kubernetes.io/docs/home/
【AWS CLI】リストコマンドの結果出力

自分メモ用
AWS CLIのリストコマンドの結果をファイルに出力します

<b>IAM ロール一覧</b>

```
aws iam list-roles --query "Roles[].[RoleName]" --output text > role_list.txt
```

<b>IAM ポリシー一覧</b>

```
aws iam list-policies --query "Policies[].[PolicyName]" --output text > policy_list.txt
```

<b>CodeCommit リポジトリ一覧</b>

```
aws codecommit list-repositories --query "repositories[].[repositoryName]" --output text  > repo_list.txt
```
お名前ドットコムのMicrosoft365プランで独自ドメインのメールを送受信する。（その２：独自ドメイン追加）

# はじめに
前回はお名前ドットコムで「**Microsoft 365 Business Standard**」プランを申し込み、「**Microsoft 365 管理センター**」へのログインまで行ったので、今回は管理センターから独自ドメインを追加してみようと思います。

- 【前】[お名前ドットコムのMicrosoft365プランで独自ドメインのメールを送受信する。（その１：申し込みとログイン）](https://qiita.com/sakai00kou/items/0794c5c8fec4d6ff70f8)
- 【次】[お名前ドットコムのMicrosoft365プランで独自ドメインのメールを送受信する。（その３：Microsoft365のセットアップ）](https://qiita.com/sakai00kou/items/1813ae6eca8a7b329676)

# 独自ドメインの追加
前回取得した独自ドメインをMicrosoft 365に設定して、独自ドメインでアクセスできるように設定します。

「**Microsoft 365 管理センター**」から「**設定**」→「**ドメイン**」より、「**ドメインの追加**」を選択し、新しく独自ドメインを追加していきます。

![kanri_domain.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/163205d6-78d9-108b-73ec-60f4cf89e0ae.jpeg)

ドメイン名入力画面が表示されるため、取得した独自ドメインを入力して、「**このドメインを使用する**」を選択します。

ドメインの確認方法は「**ドメインのDNSレコードにTXTレコードを追加する**」を選択して、「**続行**」を選択します。

![domain.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/bf0b76f2-3eed-9a8c-1f11-bf1e60a37eca.jpeg)

以下ドメイン確認画面でDNSに登録する**TXTレコード**が確認できるので、画面はそのままにして**TXTレコード**を控えておきます。

![domain_check.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/532905df-4826-1640-4e4d-41ac22bf9f4e.jpeg)

# TXTレコードの追加
先ほど控えた**TXTレコード**をDNSに登録するため、別ウィンドウで「**お名前.com Navi**」を開き、「**ドメイン**」→「**ドメイン機能一覧**」→「**DNS関連機能の設定**」より、取得した独自ドメインを選択し、「**DNSレコード設定を利用する**」の「**設定する**」ボタンを選択します。

![dns_record.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/cbd1d27c-d73e-3aa0-743e-f737829afff4.jpeg)

**TXTレコード**を追加するために、以下図、表のように設定してレコードを追加します。

|設定項目|値|
|:--|:--|
|ホスト名|空欄|
|TYPE|TXT|
|TTL|3600（初期値）|
|VALUE|※先ほど控えたTXTレコード|
|状態|有効（初期値）|

![add_dns_record.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/b1641eab-02c0-958e-0925-dbb88483ad93.jpeg)

レコード追加ができたら、画面下の「**DNSレコード設定用ネームサーバー変更確認**」はチェックを入れ、「**確認画面へ進む**」→「**設定する**」を選択することでDNSレコードが反映されます。

# ドメインの接続
「**Microsoft 365 管理センター**」を開いているウィンドウに戻り、「**確認**」ボタンを選択すると、先ほどのレコード登録が問題なく完了していれば、ドメイン接続方法を聞かれるため、「**その他のオプション**」より「**自分のDNSレコードを追加する**」を選択します。

![domain_connect.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/ba93f83a-69dc-bfc7-cbf3-e0231d16d68c.jpeg)

![add_dns_record2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/3b01ed84-685e-47c7-a9f7-349d3c9c8c37.jpeg)

# DNSレコードの追加
以下画面で利用サービスを選択。

![service.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/881e0729-dbd4-4627-cbaa-ff71cbbf6a3d.jpeg)

利用サービスを選択すると、DNSに追加が必要なレコード設定が表示されるため、先ほどのTXTレコード同様控えておきます。

![dns_record2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/7c909d9b-48e4-797d-0f19-e42d81550645.jpeg)

# MX、CNAME、TXTレコードの追加
再度「**お名前.com Navi**」画面を開いているウィンドウに戻り、先ほどと同様、「**Microsoft 365 管理センター**」に表示された情報に従って以下のように追加していきます。

![add_dns_record3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/a0d0e92b-e65f-b244-1c01-745ad8789376.jpeg)

:::note warn
上図はTXTレコードが一部見切れているため「Microsoft365 管理センター」の画面で控えた値を入力すること。
:::

再度、「**Microsoft 365 管理センター**」より、「**続行**」ボタンを選択し、問題なければドメインのセットアップ完了です。

# おわりに
今回はMicrosoft 365で取得した独自ドメインを使用するための準備を行いました。

次回はMicrosoft 365の各種セットアップを行っていきます。
sprintfフォーマットの解説

##そもそもフォーマットとは？
フォーマットとは書式のことです。つまり、文字列や数値をどんな形式で表示させるかというのをきめるんです。
具体例を見ていきましょう

```
n = 10
sprintf('%f', n)
=> "10.000000"
```
指示子に、%fをいれると、浮動小数点数(float)を出力します。他にも指示子があるので、[こちらの記事](https://k-koh.hatenablog.com/entry/2019/12/16/105428)を参考にしてみてください

##実際に問題を解いてみましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485775/15264d1a-91d7-e9ec-90bf-15fd1cd88349.png)

問題で出されているコードでは、% 5とあります。これは、指示子ではないので、% 5は無視されます。
そのため、表示されるのは、Helloと表示されるため、選択肢➁が正解です。

###選択肢➂
これは先ほどの説明から不正解であることが分かります。これを正解にするには、

```
p 'Hello%d' %5
=> "Hello5"
```

選択肢➀を正解にするには、どんなコードを打てばいいのか自分ではわからないので、分かる方いらっしゃったらご教示いただけますと幸いです。
以上です。

【参考資料】

https://k-koh.hatenablog.com/entry/2019/12/16/105428

https://docs.ruby-lang.org/ja/latest/doc/print_format.html
40 代おっさん LaravelでMVCのCを学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 構築環境

・EC2:Amazon Linux2
・PHP7.3
・Laravel 5.8
・mariadb

## MVCとは

MVCとは、ソフトウェアの設計モデルの一つで、機能を「Model」（モデル）、「View」（ビュー）、「Controller」（コントローラ）の三つの役割に分離して実装し、それらが連携して処理を進める方式。
Modelはデータの管理や手続きを扱い、Viewは他の二要素からの指示を受けて利用者への表示・出力（の変更）を行い、システムによっては利用者の操作・入力内容をControllerに伝達する。Controllerは利用者からの操作や入力を受け付けて解釈し、ModelやViewに対応する処理を行うようメッセージを発する。

## Controller

全体の制御を担当するもの、必要に応じてModelを使ってデータを収得したり、Viewを利用して画面表示を作成したりする。

### Controller作成

Could9でファイルを作ってもいいのですが、せっかくなのでartisanコマンド使用します。

```terminal
php artisan make:controller HelloController
```

appフォルダのHttpファルダのControllersに作成される。

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HelloController extends Controller
{
    //
}
```

基本ソース

namespace App\Http\Controllers;
名前空間に配置
名前空間とは
名前の集合を分割することで衝突の可能性を低減しつつ参照を容易にする概念である。

use Illuminate\Http\Request;
use分
Requestを使える状態にしている。
Javaで言うインポート文に近い物。

class HelloController extends Controller
クラスを定義
Controller継承（extends)している。

### アクションを用意

コントローラに用意される処理　アクションと呼ぶ

下記を書き足す

```php
public function index()
    {
        $data = [
            'msg'=>'利樹大好きだぞ～～',    
        ];
        return view('hello.index', $data);
    }
```

### ルート情報の用意

アクションにルートを割り当てる設定が必要

routesファルダのweb.phpを開く

下記を書き足す

```php
Route::get('hello', 'HelloController@index');
```

第1引数のhelloにアクセスすると
第2引数のHelloController@indexが実行
第2引数はコントローラ名＠アクションと記述

とりあえず今日はここまで…
つぎはMVCのMを勉強する！！

## 参考資料

https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF-Laravel%E5%85%A5%E9%96%80-%E6%8E%8C%E7%94%B0%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798052582
anyenv+pyenvでの「WARNING: pyenv init - no longer sets PATH 」の対処法

pyenv でずっとエラーが出ていたのですが、日本語訳で正しい対応をしている記事がなかったので記載させていただきます。

## 発生するエラー
シェル起動時に、以下のエラーが出る。

```zsh
WARNING: `pyenv init -` no longer sets PATH.
Run `pyenv init` to see the necessary changes to make to your configuration.
```

## 結論

以下を実行してください。

```zsh
anyenv update
```

`anyenv update` の　install方法は以下を参考にしてください。
https://qiita.com/sawadashota/items/825002d84088c0129c4b


## 何をしているのか

以下のPRで、エラーが修正されましたので、anyenvを更新してバージョンを合わせています。

https://github.com/anyenv/anyenv/pull/92

### 上記PRの翻訳

pyenvでは、明示的なパス設定が必要になりました。
其の目的は、パス設定を `.*prifle` に分離することです。
ですが、anyenvは下位互換性のためにinitロジックに保持します。

変更が取り込まれたのが2021/7/13なので、それより前からanyenvを更新していない人がおそらく対象になります。

## 備考

anyenv/anyenv に報告しているissue

https://github.com/anyenv/anyenv/issues/90

pyenv の　パス設定が変更されたタイミング。

https://github.com/pyenv/pyenv/pull/1898
【赤点回避！？】「ｎ進数」を使って赤点を言い訳する！～vbs版～

こんにちは。
以下の記事でやっていることをvbsでやったらどうなるかな？と思ったので、~~需要があるかわかりませんが~~時間があったので作ってみました。

https://qiita.com/kinasuke0206/items/bc807972e8a0e1cd9284

```vb:sample.vbs
On Error Resume Next
'--------------------------------------------------------------
' 悪い点数を少しでも上げようとする悪あがき
'--------------------------------------------------------------
Dim moto ' 元の得点という意
moto = WScript.Arguments(0) ' 何とかしたい得点（10進数）

Int(moto)

' 数字以外の点数がきたらエラー
If Err.Number <> 0 Then
    msgbox "冷やかしはやめてください"
    wscript.quit
End If

' 100以上の点数がきたらエラー
If moto >= 100 Then
    msgbox "100未満の値を入力してください"
    wscript.quit
End If

' どうしようもない
If moto < 2 Then
    msgbox "手の施しようがありません。あきらめてください。"
    wscript.quit
End If

Dim changeVal
Dim radix
' 2進数から9進数まで順々に評価していく。
For radix = 2 To 9 

    changeVal = ChangeValue(moto, radix)
    
    ' 100点以内に収まったらループ終了。
    if changeVal <= 100 Then
        Exit For
    End If
Next

' 結果を表示。
msgbox ato

' 値を指定した基数に変換する。
Function ChangeValue(num, dRadix)

    Dim sho
    Dim Amari 
    Dim cnt
    Dim Ans()
    Dim vv
    vv = num
    cnt = 0

    ' 基数変換。
    Do While True
        Redim Preserve Ans(cnt)
        Ans(cnt) = vv mod dRadix ' 余り
        sho = vv \ dRadix ' 商
        cnt = cnt + 1

        if sho < dRadix Then 
            Redim Preserve Ans(cnt)
            Ans(cnt) = sho
            Exit Do
        End If
        vv = sho
    Loop

    Dim i
    Dim value
    value = 0
    ' 10進数で基数変換後の値を表現。
    For i = 0 To Ubound(ans) step 1
        value = value + ( ans(i) * 10^i)
    Next
    ChangeValue = value
End Function
```
pyxelライブラリを使っていてpyo3_runtime.PanicExceptionが出てきたら

# エラーの確認の仕方

例えばPyxelの[01_hello_pyxel.py](https://github.com/kitao/pyxel/blob/main/pyxel/examples/01_hello_pyxel.py)を動かそうとしたとします。
その時に以下のように改変していると

```Python:01_hello_pyxel_edit.py

import pyxel

class App:
    def __init__(self):
        pyxel.init(160, 120, title="Hello Pyxel")
        pyxel.image(0).load(0, 0, "assets/script.png")
        pyxel.run(self.update, self.draw)
    def update(self):
        if pyxel.btnp(pyxel.KEY_Q):
            pyxel.quit()
    def draw(self):
        pyxel.init(200, 200)
        pyxel.cls(0)
        pyxel.text(55, 41, "Hello, Pyxel!", pyxel.frame_count % 16)
        pyxel.blt(61, 66, 0, 0, 0, 38, 16)


App()

```

このようなエラーが出ます。
```sh
line 8, in __init__
    pyxel.run(self.update, self.draw)
pyo3_runtime.PanicException: Unwrapped panic from Python code
```

このエラーをそのままググるとRustとかの記事が出てきますが、これは簡単に治すことができます。
# どうしてエラーが出たのか
これが出てくる理由は_def_draw_の部分に_pyxel.init_を入れてしまっているからです。このファイルの実行動作は_def_init_で[_pyxel.run_を使って、_draw_と_update_を実行しています](https://github.com/kitao/pyxel/blob/main/docs/README.ja.md#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E6%88%90%E6%96%B9%E6%B3%95)。そして_01_hello_pyxel_edit.py_ではdrawの中に_pyxel.init_を入れています。この状態では描画するたびに初期化を繰り返すのでエラーが出てます。
# わかっていないこと
どうしてこのように_pyxel.run_で描画する際に初期化することでエラーが出てるのかはわかっていません。とりあえず何回も処理する部分には_pyxel.init_を入れない方が良さそうです。
【Typescript】クライアント側でCSVをparseする

```vue
<script setup lang="ts">
import { ref } from 'vue'
import Papa, { ParseResult } from 'papaparse'

interface WorldCity {
  name: string;
  country: string;
  subCountry: string;
  geoNamId: number;
};
const worldCities = ref<WorldCity[]>([])

const uploadCsv = (e: Event) => {
  const target = e.target as HTMLInputElement
  const fileList = target.files as FileList
  if (!fileList.length) return

  const splitedFileName = fileList[0].name.split('.')
  const extension = splitedFileName[splitedFileName.length - 1]
  if (extension !== 'csv') return

  Papa.parse(fileList[0], {
    complete: (results: ParseResult<WorldCity>) => {
      console.log(results.data)
      worldCities.value = results.data
    },
    header: true,
    dynamicTyping: true,
    error: () => {
      alert('エラーが発生しました')
    },
  })
}
</script>

<template>
  <input type="file" @change="uploadCsv" />
</template>
```

# 解説

クライアント側でimportしたCSVを加工するために [papaparse](https://www.papaparse.com/) を使用します。

```bash
yarn add papaparse
yarn add @types/papaparse -D
```

- Papaとparse完了後の型をimport
- CSVをparse後に加工したい型定義
- 代入するref定義

```jsx
import Papa, { ParseResult } from 'papaparse'

interface WorldCity {
  name: string;
  country: string;
  subCountry: string;
  geoNamId: number;
};

const worldCities = ref<WorldCity[]>([])
```

- アップロードされたファイルの拡張子がCSVかチェック

```vue
<script setup lang="ts">
const uploadCsv = (e: Event) => {
  const target = e.target as HTMLInputElement
  const fileList = target.files as FileList
  if (!fileList.length) return

  const splitedFileName = fileList[0].name.split('.')
  const extension = splitedFileName[splitedFileName.length - 1]
  if (extension !== 'csv') return
}
</script>

<template>
  <input type="file" @change="uploadCsv" />
</template>
```

- Papa.parseの第1引数にFileオブジェクトを指定
- 第2引数に[Parse Config Object](https://www.papaparse.com/docs#config)を指定
- complete
    - parse完了後のコールバック。resultsでparse結果を受け取る
- header
    - trueでCSVの1行目のヘッダーをkeyに持つオブジェクトを返す
- dynamicTyping
    - 数値やbooleanが存在する場合にstringから型変換を行なって返す
- error
    - parse失敗時にコールバック

```jsx
Papa.parse(fileList[0], {
  complete: (results: ParseResult<WorldCity>) => {
    console.log(results.data)
    worldCities.value = results.data
  },
  header: true,
  dynamicTyping: true,
  error: () => {
    alert('エラーが発生しました')
  },
})
```

- 読み込みCSV

```jsx
name,country,subcountry,geonameid
les Escaldes,Andorra,Escaldes-Engordany,3040051
Andorra la Vella,Andorra,Andorra la Vella,3041563
Umm al Qaywayn,United Arab Emirates,Umm al Qaywayn,290594
Ras al-Khaimah,United Arab Emirates,Raʼs al Khaymah,291074
Khawr Fakkān,United Arab Emirates,Ash Shāriqah,291696
```

- 結果

![スクリーンショット 2022-02-07 9.06.50.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349238/635b4c9b-f743-49b1-c94b-637d538f82b6.jpeg)
ITILファンデーション 合格体験記

#はじめに
2022年1月にITILファンデーション 2011を受験し、満点で合格できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513710/8bd3f90d-d0bb-5dba-71a0-6b8135f73f2d.png)
同じ試験を受ける方の参考になればと思い、記事を書きます。
先に結論だけお伝えすると、クラムメディアの問題集をやることを強くオススメします。

#教材
以下3点の教材を利用しました。
1.参考書
通称「黄色本」と呼ばれているものです。他にもいくつか参考書がありますが、これ1冊買えば間違いないと思います。

https://www.amazon.co.jp/Service-Management%E6%95%99%E7%A7%91%E6%9B%B8-%E3%83%95%E3%82%A1%E3%83%B3%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-%E3%82%B7%E3%83%A9%E3%83%90%E3%82%B92011-EXAMPRESS/dp/4798125709

2.Ping-t
ユーザ登録をすれば「無料」で問題集を利用することができます。他にもLinuCやCCNAなどの試験問題も取り扱っています。

https://ping-t.com/

3.クラムメディア
こちらは問題集です。「購入してから～日間利用できる」といった形式なので勉強時間が十分に確保できるタイミングで購入しましょう。

http://www.crammedia.com/EX0-001-ITIL-Foundation-syllabus-2011-%E6%97%A7%E8%A9%A6%E9%A8%93%E7%95%AA%E5%8F%B7%EF%BC%9AEX0-117/p/247/204

#勉強方法

まずは、「黄色本」を読んで試験の全体像を把握するところから始めました。
最初から全部暗記するペースで読んでいるとモチベーションの維持ができないので流して読むようにしてました。
読んだ後は、辞書変わりとして活用していました。

次にPing-tの問題集をやりました。
各問題の解説がしっかり書かれているので非常にオススメです。
また、「未出題」「ミス」「ヒット(1回正解)」「コンボ(連続で正解)」で出題設定ができるなど使い勝手がよかったです。
問題は全部で318問あり、最終的には全問コンボの状態になるまでやりました。

最後にクラムメディアの問題集をやりました。
有料なので購入するか悩みましたが、試験に落ちて受験料が無駄になるリスクが怖かったので購入しました。
Ping-tとは違い、解説が十分に書かれていないので間違えた問題は黄色本で確認していました。
過去に同じ問題集を購入した方の解説メモが見れます。よく書かれているメモもあれば、いたずら書きのようなメモもあります。メモに「黄色本 P.～～」と書かれている問題もありますが、発売された黄色本によってページ場所に多少の誤差はあるためご注意ください。
約200問ほどあり、模擬試験モードで90％とれるくらいまでやりました。

#試験について

コロナ禍ということもあり、オンラインで受験をしたかったですが、テストセンターでの受験しか受け付けていないようです。
私はピアソンVUEで予約をしました。都内のテストセンターであれば、平日だけでなく土日に開催しているテストセンターもありました。

https://www.pearsonvue.co.jp/

ちなみにITILファンデーションの出題形式は以下のとおりです。
・出題数：40問
・出題形式：4択
・試験時間：60分
・合格基準：26問以上の正解（65%）
・持ち込み：不可
・受験前提条件：なし

英訳の影響か日本語が不自然な問題がありました。AWSの試験では試験中に英語と日本語で切り替えができますが、ITILファンデーションでは、それができないのでご注意ください。
クラムメディアの問題集で日本語が不自然なものがあったのですが、実際の試験を模しているものなのだと納得しました。

試験は、全問見直しする時間を含めて15分程度で終わり、かなり余裕をもって終わりました。勉強をして試験に臨む方ならば、試験時間が足りなくなるようなことはないと思います。
また、クラムメディアの問題集と似た問題が出題され、即答できる問題が多かった点も試験が速く終わった理由の1つだと思います。問題の半分近くはクラムメディアの問題集と似た問題だった記憶です。

試験結果はテスト終了時にすぐ発表されます。テスト終了のボタンを押すときは毎回緊張します。

#おわりに
最後まで読んでいただきありがとうございました。ITILファンデーションの勉強を通じて、システム設計、構築、運用の検討時に必要な基礎知識を学ぶことができました。特にPing-tの問題解説がとても親切なのでよい勉強になりました。同様の試験を受ける方の参考になれば幸いです。
ズボラで面倒くさがりな人に向けた git-commit message linter


普段 git の commit message を丁寧に書かかないことをチクリと刺され辛い... ってなってるエンジニアです。

# 日本語読むの疲れるって人に
gitのcommit messageを綺麗にしたいけど、linter よくわからん！！！って人に向けたツールを作ったので使ってください。

https://github.com/masahiro331/go-commitlinter

## 雰囲気
`<type>(<scope>): <subject>` のフォーマットに沿わない commit messageにすると git commit を失敗させます。

![スクリーンショット 2022-02-07 8.57.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308125/d988862e-8ede-d941-3740-ed9e46c6da55.png)


## 導入方法
```
# go言語使ってない人はこれを機に brew install golang してくれ
go install github.com/masahiro331/go-commitlinter@0.1.0

# repositoryのディレクトリに入って入力
echo "go-commitlinter" >> .git/hooks/commit-msg
chmod 755 .git/hooks/commit-msg
```

ここから下、純粋なポエムです。

# 目的
汚いgitのcommit messageを綺麗にするためのlinterを作りました。

# 背景
gitの commit message に対する linter は世の中にたくさんあるんですが、多くの機能と豊富なドキュメントを前に「英語が読めない」「ドキュメント読めない」「というか入れ方わからん」みたいな気持ちに毎回なり、ずっと linter を入れるのを先延ばしにしてました。

普段ContributeしているOSSについに CONTRIBUTING.md（commit messageの規約とか書いてるやつ） が追加されたため、もうちゃんとするしか無いじゃん... でもlinterとかよくわからん...ってなった結果、自作で最小機能のlinterを作りました。

# コンセプト
コンセプトという名の機能を作らない言い訳を書きます。

とりあえず、ルールとかyamlでインポートしようかな？とか色々考えて機能を追加したんですが、原点に振り返ると「こういう機能が俺のLinter導入を忌避したのでは？？」となり全部消しました。

> 2022/2/8 追記
なんか必要そうな気持ちにもなったのでルールをyamlでインポートできるようにしました。デフォルト値が存在するので基本意識せずに使ってもらえるように変更

# 機能追加 2022/2/8 追記
ContributeしているOSSがPull Requestのタイトルに `<type>(<scope>): <subject>` のフォーマットを必須としているので、PR時に検知できるようなGitHub Actionsを作成しました。

こんな感じのyamlを .github/workflow/pr_title_test.yamlとして追加すればいい感じにPRのタイトルを見てダメなタイトルを検知してくれます。

```
name: PR Title linter
on:
  pull_request:
env:
  GO_VERSION: "1.17"
jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Go pull request message linter
        uses: masahiro331/go-commitlinter@0.1.0
        env:
          PR: ${{ github.event.number }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

# 最後に
このツールは十分な機能を提供するものではなく、とりあえずなんか入れておこうという人に向けたツールです。
豊富な機能を持つ Linterに導入する前に、とりあえず使うツールとして使ってもらえれば嬉しいです。

ちなみにこのlinterを導入しても結局雑にmessageを書いてしまう... ってなってます。
「三つ子の魂百まで」ですね
カスタムフックをreact-hooks-testing-libraryを用いてテストした(初級)


## カスタムフックスをテストしたい！!
と思って下記のカスタムフックをテストします。

```typescript:useToggle.tsx

// 真偽値を反転させる処理
export const useToggle = (initialState: boolean): [boolean, () => void] => {
  const [state, setState] = useState(initialState);
  const toggle = useCallback(() => {
    setState((b) => !b);
  }, []);
  // ステートとメソッドの配列を返す
  return [state, toggle];
};
```

## react-hooks-testing-library

カスタムフックをテストする際に余分なコンポーネントを作る必要なく、フックだけテストしたい時にこのライブラリが有効だなと感じて利用しました。

[ライブラリのGithub](https://github.com/testing-library/react-hooks-testing-library)

***

これでカスタムフックもテストできる、簡単じゃん！！
と思ったら、すぐにはうまくいきませんでした。




> 下記のコードは公式のドキュメントに書かれていたカスタムフックのreturnの値がオブジェクトでした。

>```javascript:useCounter.js
>import { useState, useCallback } from 'react'

>function useCounter() {
>  const [count, setCount] = useState(0)

>  const increment = useCallback(() => setCount((x) >=> x + 1), [])
  // returnの値がオブジェクト😭
>  return { count, increment }
>}

>export default useCounter
>```

そのため、公式に書いてあるテストコードを少しいじらなければいけません。
返ってくるresultがオブジェクトであれば下記に書いてあるとおり、`result.current.メソッド名()`とすれば良い。

>```javascript:useCounter.test.js
>import { renderHook, act } from '@testing->library/react-hooks'
>import useCounter from './useCounter'

>test('should increment counter', () => {
>  const { result } = renderHook(() => useCounter())

>  act(() => {
>    result.current.increment()
>  })

>  expect(result.current.count).toBe(1)
>})
>```

### カスタムフックで配列が返ってくる場合

すごくコードとしてわかりずらいなと思いつつも下記のように配列のインデックスを指定して実行をすればtoggleメソッドは実行されました。
これで無事に真偽値の反転をテストすることができました。

```typescript:useToggle.test.tsx
test("Booleanの初期値(true)を反転させる処理", () => {
    const { result } = renderHook(() => useToggle(true));

    // Boolean反転前, 第一引数のステートをチェック
    expect(result.current[0]).toEqual(true);
    // 第二引数の関数を実行
    act(() => {
      result.current[1]();
    });
    //Boolean反転後, ステートをチェック
    expect(result.current[0]).toEqual(false);
  });
```

まだまだ、言語化は不十分ですが私が書いたuseToggleと公式のuseCounterを見比べていただければ配列を返すメソッドであってもテストすることが可能だということがわかります。

今回のアウトプットは以上になります。お粗末さまでした。

ご指摘、ご意見がありましたら是非おっしゃっていただけると助かります。
Firefoxのcanvas操作でNS_ERROR_NOT_INITIALIZEDが出る場合の対処方法

# canvasの操作でNS_ERROR_NOT_INITIALIZEDが出る場合

備忘録として残します。

## エラーが出る処理
ここではCanvasからcaptureStreamでMediaStreamを取得しています。

```JavaScript
const canvas = document.getElementById('canvas');
const video = document.getElementById('video');
video.srcObject = canvas.captureStream();       /* ここでエラーがでる */
```

実行結果

|Browser  |結果  |
|---|---|
|Chrome  |OK  |
|Edge | OK |
|Firefox  | NS_ERROR_NOT_INITIALIZED |
|Safari  | OK |


## 回避方法
getContext('2d')の行を追加します。
この処理を入れてもほかのブラウザに影響はありません。

```JavaScript
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');            /* この行を追加 */
const video = document.getElementById('video');
video.srcObject = canvas.captureStream();
```
【備忘録】Codewar(JavaScript)勉強記録 3

# Codewar を使い始めたので自分用アウトプット記録。3

# 5. Return Negative

パラメーターの数字をネガティブにして返す。

もともとネガティブの場合は、そのまま返す。

0 の場合は 0 を返す。

```js
makeNegative(1); // return -1
makeNegative(-5); // return -5
makeNegative(0); // return 0
makeNegative(0.12); // return -0.12
```

## 1-1.単純に条件分岐でそれぞれ返す。

### Time Complexity: O(1)

処理自体は一回

### Space Complexity: O(1)

```js
function makeNegative(num) {
  if (num === 0) {
    return 0;
  } else if (num < 0) {
    return num;
  } else {
    return num * -1;
  }
}
```

### ベストプラクティス参考


```js
function makeNegative(num) {
//正の数と0には正の数、負の数には負で返すメソッド
  return -Math.abs(num);
}
```

### Math.abs()

returns the absolute value of the number.
returns x if x is positive or zero
returns -x if x is negative

```js
Math.abs('-1'); // 1
Math.abs(-2); // 2
Math.abs(null); // 0
Math.abs(''); // 0
Math.abs([]); // 0
Math.abs([2]); // 2
Math.abs([1, 2]); // NaN
Math.abs({}); // NaN
Math.abs('string'); // NaN
Math.abs(); // NaN
```

```js
function makeNegative(num) {
  return num < 0 ? num : -num;
}
```

# 6. Reverse words

文字列をパラメータとして受け取り、それぞれの言葉を反転する。スペースはそのまま。

```js
"This is an example!" ==> "sihT si na !elpmaxe"
"double  spaces"      ==> "elbuod  secaps"
```

## 1-1.Brute Force

word ごとに配列に入れる。
一つ目のループで配列自体をループし、二つ目のループで文字列を後ろから見ていく。

### Time Complexity: O(N^2)

ネストループ

### Space Complexity: O(1)

```js
function reverseWords(str) {
  let reversed = '';
  const words = str.split(' '); // ['double','spaces']

  for (let i = 0; i < words.length; i++) {
    const substr = words[i];
    for (let j = substr.length - 1; j >= 0; j--) {
      reversed = reversed + substr[j];
    }
    if (i !== words.length - 1) {
      reversed = reversed + ' ';
    }
  }
  return reversed;
}
```

### ベストプラクティス参考

```js
function reverseWords(str) {
  // パラメータの文字列を配列に入れる
  //さらにwordごとに配列に入れる、配列の順番を逆にするメソッドで順番を変え、配列から文字列に変換、すべて要素やってから全部文字列にする。
  return str
    .split(' ')
    .map(function (word) {
      return word.split('').reverse().join('');
    })
    .join(' ');
}


function reverseWords(str) {
  return str.split(' ').map( str => str.split('').reverse().join('') ).join(' ');
}
```

### メソッド

- Math.abs() -> 正数または０を受け取ったら、正数を返し、負の数には負の数を返す。
- split(' ') -> 文字列から配列に変換
- reverse() -> 配列の要素の順番をリバースする
2022/2/7主にITとかセキュリティの記事

積水ハウスグループ企業がエモテット感染、不審メール確認される(2/4)
https://cybersecurity-jp.com/news/63254

「漫画天国」運営者が書類送検--海賊版サイトに誘導する「リーチサイト」を運営(2/3)
https://japan.cnet.com/article/35183050/

デジタル遺品整理で、遺族のトラブル回避　何をやれば最低限OK？(2/4)
https://xtrend.nikkei.com/atcl/contents/18/00585/00002/?i_cid=nbpnxr_right_ranking_y

＜今日は何の日＞2月1日「『サイバーセキュリティ月間』スタート」(2/4)
https://www.weeklybcn.com/journal/column/detail/20220204_188840.html

2022年北京冬季オリンピック・パラリンピック大会の開催に伴うサイバーセキュリティ対策について（注意喚起）(2/4)
https://www.npa.go.jp/newlyarrived/2022/20220204002.html

米ニューズにサイバー攻撃、中国と関係の公算大(2/5)
https://jp.wsj.com/articles/cyberattack-on-news-corp-believed-linked-to-china-targeted-emails-of-journalists-others-11643989349
Ubuntuで有線LANが認識されない

新しいPCを組んでUbuntu 20.04.1 を入れたら有線LANでもネットに繋がらなかったのでその時の対処のメモ

#結論
スマホのUSBテザリングを使ったらネットに繋がったのでそのまま`apt-get update` と `apt-get upgrade` をしたら繋がった

#本題

新しいPCを組んだのでそろそろLinuxの勉強をちゃんとしたいなと思ってUbuntuを入れてみた。
そしたら有線LANを使っているのに何故かネットに繋がらない。

使ったマザボはASRockのPhantom Gaming 4
入れたのは ubuntu-ja-20.04.1-desktop-amd64.iso（ISOイメージ）

とりあえずネットで調べたら名前解決が上手く言って無さそうって出てきたので`DNS=8.8.8.8`の設定をしたけど上手く行かない

何も分からなくなってサークルのSlackで叫んだら先輩が来てくれたので色々助けてもらった。
以下はその時やったこととかのメモ。



` ip address `の結果が`lo`だけでネットワークデバイスが見えて無さそう。

```console
lspci -v | less
```

でEthernetの部分を見てみると、

```sh
00:1f.6 Ethernet controller: Intel Corporation Ethernet Connection (14) I219-V(rev 11)
```

https://answers.launchpad.net/ubuntu/+source/gnome-nettool/+question/699999
を見てみると、2021-12の時点でカーネルで対応していない可能性が...

どうしようか(e10000e入れる？でもどうやって？とか)考えているときに、昔wifiが使えないときにスマホのUSBテザリングでノートPCに繋いで作業していたことを思い出した。

そこでスマホを繋いでUSBテザリングをONにしてみたところ、なんかネットに繋がった。

とりあえず、

```console
sudo apt-get update
sudo apt-get upgrade
```

で色々更新したら有線LANでネットに繋がるようになった。

`ip address`をしたら`enp0s31f6`も表示されるようになっていたのでもう大丈夫そう。

#最後に

最初からそこそこ重い問題が来たけど先輩に助けてもらってなんとか解決。
どうやらISOで入れたときのカーネルのバージョンが数年前のもので、そのときにはまだ対応していないものだったのかもしれないらしい。
ABC237 C問題(Python)

#C - kasaka

解法の手順としては
1. 文字列の前と後ろから見てaがいくつか連続するか見て、前の方が文字列aが少ない時、
　　差分だけaを文字列の前に追加する
2. 回文判定をする
　　pythonの回文判定はこちらのページを参考にしました
　　https://www.delftstack.com/ja/howto/python/python-palindrome/

留意点は二つ
一つ目、
同じ文字列を複数連続させるには*を使う
例えば、aがn回続く場合はa*n
二つ目、
while文のなかで、iとjが取れる範囲について注意する

```
S=list(input())
i=1
k1=0
p=0
l=0
while(S[-i]=='a'):
    l=l+1
    i=l+1
    if i>len(S):
      break
while(S[p]=='a'):
    p=p+1
    if p>len(S)-1:
      break
    
S=''.join(S)
n=l-p
if n>0:
  S='a'*n+S
if str(S) == str(S)[::-1] :
    print("Yes")
else:
    print("No")
```
【JavaScript】JavaScript基礎まとめ3

## はじめに
　本記事は、プログラミング初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

##JavaScript基礎まとめ3

###三項演算子

```.js:三項演算子
// 三項演算子
// 条件 ? trueの時の処理 : falseの時の処理
const val6 = 1 > 0 ? 'trueです' : 'falseです';
console.log(val6);
// trueです

const num3 = "1300";
console.log(num3.toLocaleString());
// 1,300
// toLocaleStringはJavaScript標準の関数で3桁カンマ表記に変換してくれる

const formattedNum = typeof num3 === 'number' ? num3.toLocaleString() : '数値を入力してください';
console.log(formattedNum);
// num3が数値以外の場合は'数値を入力してください'、数値の場合は1,300等になる

const checkSum = (num1, num2) => {
  return num1 + num2 > 100 ? '100を超えています' : '許容範囲内です';
}
console.log(checkSum(30,100));
// 引数の合計が100を超えていれば'100を超えています'、超えていなければ'許容範囲内です'

```

###　論理演算子(&&や||等)の処理

```.js:論理演算子(&&や||等)の処理

const flag1 = true;
const flag2 = false;

// 論理演算子に対する一般的な認識
if (flag1 || flag2) {
  console.log("1か2はtrueになります");
}
if (flag1 && flag2) {
  console.log("1も2もtrueになります");
}

// || は左側がfalseなら右側を返す
const num = null;
const fee = num || "金額未設定です";
console.log(fee);
// 金額未設定です

// && は左側がtrueなら右側を返す
const num4 = 100;
const fee2 = num4 && "値が設定されました";
console.log(fee2);

```
【Laravel】AccessorでEloquent属性値を変換して処理を共通化する

# 概要

`Eloquent Model` から取得したIDをハッシュ化する処理を`Accessor`を利用して行ってみましたので紹介します

> アクセサは、Eloquentの属性値にアクセスしたときに、その値を変換するものです。アクセサを定義するには、モデルにget{Attribute}Attributeメソッドを作成します。

https://laravel.com/docs/8.x/eloquent-mutators#attribute-casting

# `Accessor` の定義

- `{カラムのアッパーキャメルケース}Attribute` の形式でメソッドを命名する
    - 今回は`hash_id`にハッシュ化したIDを格納しますので`HashId`としています

```php:User.php
/**
 * Attributeにhash_id属性を生成するアクセサ
　　* @return string
*/
public function getHashIdAttribute()
 {
   return urlencode(Hash::make($this->id));
 }
```

```php
$user = User::query()->findOrFail(1);

// Accessorで変換されたカラム名にアクセスするとハッシュ化した値を取得できます
dd(user->hash_id);
```

# さいごに
今回は`Accessor`の仕組みについて紹介しました。
いいねしていただけると記事執筆の励みになりますので、参考になったと思った方は是非よろしくお願いします！
【AWS】EBSをスナップショット取った時のサイズはどんな感じ 

#気になったこと
仮に100GBのボリュームに10GBの使っていたらスナップショットのサイズはどんな感じ？
10GB分？
100GB分？

なんとなく100GBな気がする。
10GBだったら、AWS惚れちゃう。

#結果
| ストレージ容量 |スナップショットサイズ|
|:-:|:-:|
|10GB|10GB|
|100GB|100GB|

#乾燥
そりゃそうか。
なお、データの保存先はS3とのことだが、ユーザーから見えるS3バケットには保存されない。
S3の特殊な領域に保存されるとのこと。
公式のマニュアルには記載がないが、調べるとS3に保存されるといろんな人が言っている。

参考
https://aws.amazon.com/jp/premiumsupport/knowledge-center/ebs-snapshot-billing/
Ubuntu 20.04にPostgreSQLをインストールする

## システムについて
```
User@hs:~$ uname -a
Linux hs 5.13.0-28-generic #31~20.04.1-Ubuntu SMP Wed Jan 19 14:08:10 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
```

## 必要なパッケージをインストール

```bash
sudo apt update  
sudo apt install wget ca-certificates 
```

## リポジトリ署名GPGキーをシステムにインポート

```bash
wget -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
```

PostgreSQL用のPPAファイルを作成
```bash
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ focal-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
```

PostgreSQLをインストール
```bash
apt-get install postgreSQL postgreSQL-contrib
```

## PostgreSQLの起動と確認
systemdでpostgreSQLのステータスを確認します。
```
sudo systemctl status postgresql
```

## PostgreSQLアカウントへ切り替え
```bash
sudo -i -u postgres
```

以下のコマンドでPostgreSQLのプロンプトにアクセスできます。
```bash
psql
```

PostgreSQLを終了する
```bash
postgres=# \q
```
PATLITE PHU-3 をPythonから操作する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/0cad3bf4-8d3e-32c2-143d-63fd254576b2.png)
これをPythonから制御してみます。

１．ドライバをインストール（Windowsのみ）
　[こちら](https://www.patlite.jp/support/phu3.html)からドライバをダウンロードしてインストールします

２．ポートを調べる

```port_check.py
import sys
import glob
import serial
 
 
def serial_ports():
    """ Lists serial port names
 
        :raises EnvironmentError:
            On unsupported or unknown platforms
        :returns:
            A list of the serial ports available on the system
    """
    if sys.platform.startswith('win'):
        ports = ['COM%s' % (i + 1) for i in range(256)]
    elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
        # this excludes your current terminal "/dev/tty"
        ports = glob.glob('/dev/tty[A-Za-z]*')
    elif sys.platform.startswith('darwin'):
        ports = glob.glob('/dev/tty.*')
    else:
        raise EnvironmentError('Unsupported platform')
 
    result = []
    for port in ports:
        try:
            s = serial.Serial(port)
            s.close()
            result.append(port)
        except (OSError, serial.SerialException):
            pass
    return result
 
 
if __name__ == '__main__':
    print(serial_ports())
```

３．調べたポートにバイナリを送る

　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/e8678d99-8951-8f84-a45c-b52f8a4116d3.png)
  調べたポート（下記ではCOM6）に0-7のバイナリを送ります。

```send_data.py
import serial
import time

ser = serial.Serial('COM6', 19200)
for num in range(9):
    ser.write(bytes([num]))
    time.sleep(1)
ser.close()
```

[動画](https://youtu.be/9PD94y1ws28)

おまけ
PHU-3-RYG(青LEDなし)でも青への信号は出ているようです。

| 1 |   |   |   |   |   |   |   | 9 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 5V | R | Y | - | - | G | B | - | - |

![IMG_0762.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/37416a52-8ecd-c58a-35df-2d669af2b8de.jpeg)
React初心者がレンダリングの最適化に挑戦してみる

#自己紹介
現在都内の企業でWebエンジニアのインターン生としてお世話になっている大学２年生です！
インターンや個人開発で学んだことや苦労したことを記事にしています！
よろしくお願いします🙇🏻‍♂️

#はじめに
今回はReactのレンダリングの最適化についてアウトプットしていこうと思います！

#memo
memoは子コンポーネントにラップして使うことで、このコンポーネントはpropsが変更されない限り再レンダリングされないコンポーネントを作ることができる。

#useCallback
関数を[]の変数が変わったときだけ実行されるようにできる。
[]は何も入れないと最初に生成したものをずっと使うという処理になる。
主にイベントハンドラーのような関数に使う。

#使用例
```react
import React, { memo, useCallback, useEffect, useState } from "react";
import Modal from "react-modal";

export const SUDPost = memo(() => {
  const [posts, setPosts] = useState([]);
  const [modalIsOpen, setModalIsOpen] = useState(false);
  const [edit, setEdit] = useState("");
  const [keepId, setKeepId] = useState(0);
  //投稿一覧を取ってくる
  useEffect(() => {
    fetch("http://localhost:8080/timeline/post/get")
      .then((res) => res.json())
      .then((json) => {
        setPosts(json);
      });
  }, []);

  const onClickEdit = useCallback((id) => {
    //クリックした投稿のidを保持
    setKeepId(id);
    //モーダルを開く
    setModalIsOpen(true);
    fetch("http://localhost:8080/timeline/post/get/" + id)
      .then((res) => res.json())
      .then((json) => {
        //取ってきた投稿を保持
        setEdit(json.post);
      });
  }, []);

  //フォームの中を変更できるようにする
  const handleEdit = useCallback((e) => {
    setEdit(e.target.value);
  }, []);

  //更新
  const onClickUpdate = useCallback(() => {
    const data = {
      post: edit,
    };
    //保持したidを使って更新
    fetch("http://localhost:8080/timeline/post/put/" + keepId, {
      method: "PUT",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data),
    }).then(() => {
      alert("編集完了しました。");
      window.location.reload();
    });
  }, [edit, keepId]);

  return (
    <>
      {posts.map((post) => (
        <ul key={post.id}>
          <li>
            <p>{post.post}</p>
            <input
              type="submit"
              value="編集"
              onClick={() => onClickEdit(post.id)}
            />
            <Modal isOpen={modalIsOpen} ariaHideApp={false}>
              <input
                type="submit"
                value="閉じる"
                onClick={() => setModalIsOpen(false)}
              />
              <div>
                <label>投稿</label>
                <input
                  type="text"
                  id="post"
                  name="post"
                  value={edit}
                  onChange={handleEdit}
                />
                <input
                  type="submit"
                  value="送信"
                  onClick={() => onClickUpdate()}
                />
              </div>
            </Modal>
          </li>
        </ul>
      ))}
    </>
  );
});

```
引用

https://qiita.com/yusuke1120925/items/1edc0aaf060fd9aec1e6

#終わりに
語彙力も正確性もありませんがアウトプットとして残しておきます。
なにか指摘などございましたら教えて下さい！
【Firebase】 storageに画像アップロードしようとして怒られた(403エラー)

# はじめに

Firebase + Reactベースのアプリケーションを作っているときに、画像アップロードしよーっと思って、アップロードしたら

```
Firebase Storage: User does not have permission to access 'hoge.jpg'.(storage/unauthorized)
```

と怒られたので対応した自分用メモ。

# 解決

以下の場所で

```
https://console.firebase.google.com/project/{userprojectname}/storage/{userprojectname}.appspot.com/rules
```

以下を設定すると動いた。

```
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}
```

ちゃんとドキュメントのルール見てくれってことですね。

https://firebase.google.com/docs/rules/basics?hl=ja#cloud-storage_1
CSSだけでスライドスイッチ(ON/OFFするやつ)を作る

# はじめに
ちょっと凝った見た目のUI部品が欲しいとき、さくっと作れるとライブラリ探す手間が省けてうれしい。
僕はその基準を「CSSだけで作れる見通しが立つか」に置いている。
UI部品は、パフォーマンスの面でも、複雑さの面でも、極力JSをへらすことが望ましい。
jQueryみたいなライブラリに依存してしまうのは最悪だ。他のライブラリの環境下で使えない。
ということで、JSを使わんで済むなら、圧倒的にそのほうがいい。

そのためには、日頃から「この部品の仕組みはどうなっているか」と疑問を持ち、「自分で作るならどう作るか」みたいなことを考えて、使える引き出しを増やしていくのがいい。

今回は、スライドスイッチをCSSだけで作ってみた。こんなん。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10718/a1a42252-5f5c-238d-38ce-c560ccc64046.png)
せっかくなので、何番煎じかわからんけど作り方を残しておく。

# 設計する
まずは、どうやって実現するか考えてみる。

以下の仕組みは使えそう。

* label要素で囲われたチェックボックスは、label要素内の何かをクリックすることによってON/OFF切り替わる。
* :checked疑似クラスと隣接セレクタを使ったトリックで、チェックボックスのON/OFFによってチェックボックスの隣接要素に動きをもたせる事ができる。

この2つから、単純にDOM構成を考えると以下のようになる。
大体、似たようなことやろうと思うとお世話になる構造。
なお、このUIのクラス名は`slide-switch`とした。

```html
<label class="slide-switch">
  <input type="checkbox"/>
  <!-- ↑ のON/OFF によって ↓ の要素を動かす仕掛け -->
  <span></span>
</label>
```

次に、UI部品を構成する部品を考えると、3つで作れるとわかる。
リアルで同じ見た目のものを作ろうとしても同じ構成になるだろう。

1. 持って動かすツマミ部分。
2. スライドする中の板の部分。
3. 穴の部分。中身をここから覗かせる。

サイズ感はそれぞれこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10718/88246f66-8552-7eb2-6d43-5fed1040dcb2.png)



# 実装する

## 穴を作る

今回は周りを丸く切り抜くイメージなので、`border-radius`をしっかりかけた。

```css
.slide-switch {
  position: relative;
  display: inline-block;
  width: 3em;
  height: 1.5em;
  border-radius: 1.5em;
  overflow: hidden;
}
```

`position: relative`は、子要素に`absolute`効かせる予定なのでつけとかないと中身が飛んでいく。
穴のように切り抜くので、`overflow: hidden`を忘れてはいけない。

また、チェックボックスは仕掛け上必要だが見かけ上必要ないので消しておく。

```css
.slide-switch input {
  display: none;
}
```

## スライドする部分を作る

余白左 : ツマミ : 余白右 = 1 : 1 : 1 で、穴から出すのは 余白左+ツマミ もしくは ツマミ+余白右 と考えているので、サイズは穴の1.5倍。
チェックボックスの隣接要素のspanをそれにする。

```css
.slide-switch span {
  position: absolute;
  display: block;
  width: 4.5em;
  height: 100%;
  left: 0;
  background-color: #E3E3E3;
  transition: all 300ms linear;
}
```

移動と色変えをアニメーションしようとしてるので、`left`, `background-coor`, `transition`を設定している。

隣接セレクタのトリックがこちら。

```css
.slide-switch input:checked ~ span {
  left: -1.5em;
  background-color: limegreen;
}
```

チェックボックスがONのとき、スライドする板の色を緑にしつつスライドさせている。
初期値と移動後のleftの値を入れ替えると、ON/OFFの位置が逆転する。
移動距離は1/2穴幅。計算して入れた。穴幅とつまみ幅の比率によって可変。

## つまみを作る

spanの中にゴチャゴチャ要素追加してもいいが、DOM的には少ないほうが嬉しいかなーということで、疑似要素として実装。

```css
.slide-switch span::after {
  content: '';
  position: absolute;
  display: block;
  width: 1.3em;
  height: 1.3em;
  border-radius: 1.3em;
  left: 1.6em;
  top: 0.1em;
  background-color: white;
}
```

穴より若干小さくして、スライドする板の真ん中に配置した。
`position: absolute`は多分使わなくてもいけるが、数値計算してきちっと割り当てたほうが気分いいためそうした。

# おわりに

作ったスライドスイッチをこちらに示す。
なお、ONのときに文字表示したりなど、若干の改造をしている。
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="PoObExa" data-user="kakusuke" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kakusuke/pen/PoObExa">
  CSS Only slide switch</a> by kakusuke (<a href="https://codepen.io/kakusuke">@kakusuke</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
お答えしましょう--> 今さらだけど「Jupyter Notebook」って何？　

いまさら　jupyter notebook はありえません。絶滅種です。

jupyter lab が後継種です

更に，JupyterLab Desktop が出現しました（Mac, Windows とも）
しかも，2021/09/22 には，すでに！！！


https://blog.jupyter.org/jupyterlab-desktop-app-now-available-b8b661b17e9a

時代に乗り遅れてはいけません。
指定されたディレクトリから指定サイズのみ移動したい場合のスクリプト

# 動機
1. ファイルを移動・整理する際の、「移動先の容量を調べ、移動元から必要なサイズのみファイルを取り出す」作業が面倒なため

# コマンド
```bash
mvl /path/to/source /path/to/destination (転送サイズ 例：10G) (findの転送オプション -type fはデフォルトで指定済)
```

```bash:mvl
#!/bin/bash

BASEDIR=$1
DISTDIR=$2
LIMITSIZE_HR=$3
LIMITSIZE=`numfmt --from=iec $LIMITSIZE_HR`
FINDARGS=${@:4}
DISTFREE=$(( `df --output=avail $DISTDIR | sed 1d` * 1024)) #dfの先頭行を除去
DISTFREE_HR=`numfmt --to=iec $DISTFREE`
TOTAL=0

while read -r file; do

	FILESIZE=`wc -c < "$file"` #ファイルサイズだけを取得
	TOTAL=$((TOTAL + FILESIZE )) #移動予定のファイルを合計予定サイズに加える
	TOTAL_HR=`numfmt --to=iec $TOTAL`

	#転送予定サイズが残り空き容量以下、かつ転送予定合計サイズが指定転送量以下の場合のみ移動を実施
	if [ $FILESIZE -gt $DISTFREE ]; then
		echo "Don't Enough FreeSpace $FILESIZE > $DISTFREE_HR"
		break
	fi
	
	if [ $TOTAL -gt $LIMITSIZE ]; then
		echo "over $TOTAL_HR > $LIMITSIZE_HR"
		break
	fi
	
	echo "MOVE $file to $DISTDIR (TransferTotal:$TOTAL_HR)"
	mv "$file" $DISTDIR

	DISTFREE=$(( `df --output=avail $DISTDIR | sed 1d` * 1024)) #空き容量を更新
	DISTFREE_HR=`numfmt --to=iec $DISTFREE`
	
done <<< "$(find $BASEDIR -type f $FINDARGS)"

```

# 仕様
1. findの検索された順に処理する
1. コピー先にコピー予定のファイルが収まらない、または指定した転送サイズ以上になる場合は処理を終了。後続の転送可能なサイズのファイルを探すことはしない。
1. ソースディレクトリのフォルダ構造は再現しない

# 感想
1. ファイルサイズ制限を相互の変換する「numfmt」を初めて知った
Androidでマルチモジュール化した簡単な実例

こんにちは

現在Hiltの導入のサンプルを作っているのですが、~~ついでに~~マルチモジュール化をやってみました。

ディレクトリ構成としては、アプリ名がhilt_sampleとすると

 ```
  └── hilt_sample
      ├── data
      │   └── repositories
      │       └── MainRepositoryImpl.kt
      ├── domain
      │   ├── repositories
      │   │   └── MainRepository.kt
      │   └── usecases
      │       └── FetchSomeNumberUseCase.kt
      └── presentation
          ├── MainActivity.kt
          └── MainViewModel.kt
```

↑このようになっています。
Domain層にRepositoryのinterfaceを置いて、Usecaseから外側の層（Data層）に依存しないようにしている、よく見かける構成です。（Data層でそれを実装して、依存性を逆転させています）

Data層とPresentation層は、Domain層に依存しています。

まずはDomain層をモジュールとして切り出してみようと思います。

# 方針
1. 空のモジュールを作る
2. 1.で作ったモジュールにDomain層の中身を移行する
3. モジュール化したDomain層をimportする


<a id="make-empty-module"/>
# 1. 空のモジュールを作る
![スクリーンショット 2022-02-07 0.07.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367893/1c95aca4-6cf6-ff56-b0f9-134d2c1d556a.png)

![スクリーンショット 2022-02-07 0.23.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367893/9d32d54d-38a2-adbf-c71e-0ad9553360d6.png)

こんな感じで、空っぽのライブラリができます。

# 2. 1.で作ったモジュールにDomain層の中身を移行する
あとは、domainの中身をこっちにうつします。
原始的にAndroid Studio上でドラッグで引っ張ってディレクトリ移動するだけで特に不具合はなかったです。


# 3. モジュール化したDomain層をimportする

アプリケーションのbuild.gradleに、1.で作成したdomainというライブラリを追加します。

```gradle:build.gradle
dependencies {
    implementation project(":domain")
}
```

これでビルドをしたら、モジュールを分割できました。
ビルドが通らなかったらcleanとかしてみてください。

実用上どういう分割の仕方が妥当であるかはまだわからないので（DIが難しくなるとか聞いたことがあります）
詳しい方がいたら教えてください。

ではまた:joy:
Go の気になったコミット (2022 年 1 月)

[golang/go](https://github.com/golang/go) の master ブランチに行われたコミットから個人的に気になったものをリストにしたものです。
タイトルに 2022 年 1 月と銘打っていますが 2 月のコミットも少し含まれています。

前回作成したリストはこちら。

https://qiita.com/sg0hsmt/items/9fb68ea5cc609a5474b6

軽く説明を追加していますが勘違いや誤りがあるかもしれません。

## Topic

https://go.dev/blog/go1.18beta2

- Go 1.18 Beta 2 がリリースされました。 :rocket:

## Commits

### 2022-01-10

https://github.com/golang/go/commit/6df0957060b1315db4fd6a359eefc3ee92fcc198

[`http.FS`](https://pkg.go.dev/net/http#FS) にてファイルがない場合に 404 エラーを返さず OS のエラーを返していた問題が修正されています。

### 2022-01-15

https://github.com/golang/go/commit/17b2fb1b656a275906b5071c562439d50a27f167

netpoll のレースコンディションが修正されました。
かなり古いコードで x86 系以外のアーキテクチャ (ARM とか) で問題が出ていたようです。 [^1]
この修正は Go 1.16 および Go 1.17 にバックポートするための Issue が作成されていますが未対応です。 [^2] [^3]

[^1]: https://github.com/golang/go/issues/45211
[^2]: https://github.com/golang/go/issues/50610
[^3]: https://github.com/golang/go/issues/50611

### 2022-01-18

https://github.com/golang/go/commit/5b3ebc8b72f496a5c6892d76fdeee3d9029b55cc

M1 Mac で Go 本体の開発環境をブートストラップした際にホストアーキテクチャが x86_64 と認識される問題が修正されています。 [^4]

[^4]: https://github.com/golang/go/issues/50643

### 2022-01-19

https://github.com/golang/go/commit/d54f6630703900948d9757487a1bffd87b7d36e2

Go 1.18 ではビルドしたソースコードのバージョン管理情報やビルドオプションもバイナリに追加されるようになりました。 [^5]
これらの情報をバイナリ出力しないためのオプションも用意されていたのですが、そのうちの `-buildinfo=false` が Go 1.18 beta 2 で廃止されました。
(ビルドオプションは必ず追加されるようになりました)

`-buildinfo=false` を指定してもビルドに使用した依存パッケージの情報は出力されるのですが、それが分かりにくい (依存パッケージ情報も削除されるように見える) というのが廃止の理由みたいです。 [^6]
(依存パッケージ依存の情報は従来からから出力されていました)

[^5]: https://qiita.com/sg0hsmt/items/6d852c50baa37a0c957e
[^6]: https://github.com/golang/go/issues/50501#issuecomment-1010225207

### 2022-02-03

https://github.com/golang/go/commit/070951c5dcc47c9cff2ad4c1ac6170a4060a4d0c

https://pkg.go.dev/golang.org/x/exp/constraints

Go 1.18 でジェネリクスサポートとともに追加される予定だった `constraints` パッケージが標準ライブラリから削除され、 `golang.org/x/exp/constraints` に移動しました。 [^7] [^8]
この修正は Go 1.18 beta 2 には含まれていません。

[^7]: https://github.com/golang/go/issues/45458
[^8]: https://github.com/golang/go/issues/50792

## 雑感

Go 1.18 リリースが近づいてきたこともあり不具合修正とドキュメント修正が中心になっています。
以前はこれほど Go のコミットを見ていなかったので今回が特別なのかは不明ですがコンパイラ周りの不具合が収束していないように見えます。
【作業記録】環境構築

環境構築
昨日Laravelのポートにアクセスできたのにできなくなってしまった。

環境を再構築して試そうとしてみたが
docker-compose exec web bash
を記入してもコンテナに移動できなかった。

一度作業手順（テキスト参照）に再度構築を試します
今さらだけど「Jupyter Notebook」って何？

#目的
・これから「Jupyter Notebook」を始める人向けに解説
・自動売買bot系で良く出てくる「Jupyter Notebook」って何？の人向けに解説
・データサイエンス系をこれから覚える人向け解説

##「Jupyter Notebook」とは
>1.Jupyter Notebookは便利なIDE
タイトルの通り、Jupyter NotebookはIDE（統合開発環境）です。Pythonでの開発がメインですが、設定を行えばRでの開発も可能です。ブラウザー上で動作するWebアプリケーションのため、プログラムの実行結果やグラフの描画などのビジュアル面が充実しており、プログラムを書いたらすぐ結果が出力されることが最大の魅力と言えます。配布型パッケージ「Anaconda」に同梱されており、統計解析やディープラーニングの開発では多く用いられています。

##「Anaconda」とは
>もう一つは、データサイエンスをはじめとする科学技術計算のためのプラットフォームである、Ananconda を利用する方法です。AnacondaはPythonの実行環境として知られていますが、本来、データサイエンスのためのいろいろなツールやライブラリの実行環境で、Pythonにかぎらず、さまざまなコマンドやプログラミング言語も提供しています。

>2.利用するメリットとは？
>Jupyter Notebookを利用するメリットは大きく挙げると下記の3つです。
>・無償利用可能
>・実行結果がすぐ出力される
>・豊富なライブラリが利用可能
https://www.acrovision.jp/service/data/?p=681

#始める前の環境注意点
すでにPythonが入ってたら予め消しておくといい感じになるかも（自己責任）

#「Anaconda」と「Jupyter Notebook」をインストールしよう
Anacondaをインストールすると、Jupyterも中に入ってるイメージです

##インストール方法記事・動画

https://ai-inter1.com/jupyter-notebook/

https://qiita.com/otupy/items/95db32eebe22a9a78988

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

#「Jupyter Notebook」の基本を学ぼう

https://qiita.com/naka-j/items/4a5db6304be65c13b796

https://www.javadrive.jp/python/jupyter-notebook/index5.html


#おまけ
ちなみに僕の環境特殊だったので、これ↓でした

https://note.com/mc_kurita/n/n4261e54d2539


#「Jupyter Notebook」を知った後に抑えたい記事

https://qiita.com/386jp/items/f023de9457c99b964a85

https://qiita.com/ku_a_i/items/ccdeb7f1d9384fb4767b

うわあ！優良記事が多すぎて、僕自身はとくに書くことなかった！

#あとがき
ほんまは、richmanbtcさんの「p平均法を読み解く」みたいな記事を作成しようとしたのだけども、色々と自分自身が基本的な事を知らな過ぎて固めていくためにまずは、この記事を作成しました

https://note.com/btcml/n/nc5c63a9f5aa2

richmanbtcさんの「p平均法」については以下からgithubのworkフォルダからp_mean.ipynbを開きます（以下）

https://github.com/richmanbtc/mlbot_tutorial/blob/master/work/p_mean.ipynb

<font color="White">
<details><summary>みんなにはナイショだよ</summary>
書きたい記事が増えてきてまとまりません。微妙に関係ないので白字で隠ししておきます
https://note.com/yasstake/n/n93c59b59461f
https://qiita.com/SatoshiGachiFujimoto/items/27dc8c9d3ed16964b8bd

</details>
</font>