OmniAICreator/Qiita-1.07M huggingface dataset:
正規表現の先読み、後読みについて

## 正規表現の先読み、後読み
正規表現の先読み、後読みを使用するタイミングがあったのですが、
よくわからない部分が多かったため整理しました

## 通常の正規表現と先読み、後読み
通常の正規表現と先読み、後読みの違いは次のようになります

- 通常の正規表現：正規表現と一致した文字列を取得します
- 先読み、後読み：正規表現と一致するか文字列を確認（取得はしない）し、位置を取得します

## 先読み、後読み
先読み、後読みの種類は4種類あります

- 肯定先読み：正規表現と一致した文字列の先頭の位置を取得します
- 否定先読み：正規表現と一致しない文字列の先頭の位置を取得します
- 肯定後読み：正規表現と一致した文字列の末尾の位置を取得します
- 否定後読み：正規表現と一致しない文字列の末尾の位置を取得します

### 取得例
実際に正規表現をチェックできるサイトを使用して確認してみます
使用サイト：https://rakko.tools/tools/57/
正規表現は先読み、後読みをした後に一文字を取得することで位置をわかりやすくしています
赤文字になっている部分が取得された文字となります

- 肯定先読み
記述方法は ```(?=正規表現)``` です
肯定先読みの場合、一致した文字列の先頭の位置なので、
画像の赤くなっている```w```の手前の位置が正規表現とマッチし取得されています
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/8abf4144-6493-eb8c-ed0d-80846782d8a5.png)

- 否定先読み
記述方法は ```(?!正規表現)``` です
否定先読みの場合、一致しない文字列の先頭の位置なので、
画像の黒くなっている```w```以外の位置が正規表現とマッチし取得されていますすることになります
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/25faa6d3-a9ed-02ce-6844-e0ed2ac02505.png)


- 肯定後読み
記述方法は ```(?<=正規表現)``` です
肯定後読みの場合、一致した文字列の末尾の位置なので、
画像の赤くなっている```!```の手前の位置が正規表現とマッチし取得されています
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/42878c41-700c-2e58-738f-18ac87feb0ec.png)


- 否定後読み
記述方法は ```(?<!正規表現)``` です
否定後読みの場合、一致しない文字列の末尾の位置なので、
画像の黒くなっている```!```以外の位置が正規表現とマッチし取得されています
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/ed1dee16-2cc0-8e18-8925-494fbc170cf7.png)


### 何ができるのか
- 肯定先読み、肯定後読み
正規表現と一致する場合、該当位置から文字列を取得することができ、
先読みと後読みによって、正規表現で指定した文字列を含んで取得するか、含まずに取得するか分けることもできます
取得結果の違いについてまとめたのが次の画像になります
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/bc677649-2350-0d5b-19eb-ab6205a807c5.png)


- 否定先読み
指定した文字列が続かない場合、文字列を取得する
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/1e2234f1-550d-cdc4-063d-ce83a9558979.png)


- 否定後読み
指定した文字列から続かない場合、文字列を取得する
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/0538ae96-7d5f-d32b-47ea-2e09754ba22f.png)


## 否定先読み、後読みは使いづらい？
整理していく中で思ったことは、否定先読み、後読みは肯定先読み、後読みより使いづらい気がします
肯定先読み、後読みのように使用してしまうと、取得する位置が多いため、すべての文字列を取得してしまいます
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/53d1f0f5-9def-3c50-d54a-2b84e65dfa99.png)


その代わり否定後読みは少し面白い使い方ができ、末尾の記号などを除いた文字列を取得したい場合などに使用できます
例えば、```hello world!!```の末尾```!```がいらない時などは、```.*(?<!!)```という風に記載することで```!```以外を取得することができます
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/11fe8e22-c8f2-df65-0d03-434a383f62e3.png)



## 終わり
よく理解できていなかった、正規表現の先読み、後読みを整理してみました
もし今回紹介した例以外にも面白い使い方などがあれば教えてください
BigQueryのコンソール画面から簡単にテーブル作成する方法

テーブル定義とかもいらないので、サクッと作る時はこれが一番好きです

```sql
CREATE TABLE `pj-name.dataset.table`
AS
  SELECT
    'a' as col1,
    'b' as col2,
    'c' as col3
  UNION ALL
  SELECT  '1', '2', '3'
  UNION ALL
  SELECT  'い', 'ろ', 'は'
```
自分を大事にするための考え方

職場でストレスの原因として多く挙げられるものに「人間関係」「仕事の質・量」があります。
きっと誰もが大なり小なり「ストレス」や「弱さ」を持っているけれど、それをどう受け止めるかは人によって違います。
仕事は真剣に正確に遂行しなくてはいけないけれど、ずーっと頑張り続けるのは疲れます。
自分を守るために、時には甘さや弱さも認めてあげるポジティブ思考を持つことは大事です。

## 完璧を目指さない
今期、日本ハムの監督に就任したBIG BOSSの「優勝は一切目指しません」という言葉は、誤解されがちだけど奥深い言葉です。
目の前の目標をコツコツとやり遂げた先に結果がある。決して優勝を諦めているわけではなく、最初から難易度の高い目標設定を掲げず不安を生じさせない考え方は、アスリートに限らずどの職業でも通じることです。
大事なのは、仮に達成できなかった場合にひどく自責の念に駆られて落ち込んでいくか、それともこれまでの過程は決して無駄ではないから、次に活かせると気持ちを切り替えられるか。の違いです。
そういう意味で「完璧を目指さない」のは自分をラクにしてあげる有用な考え方です。

## 割り切る！
相手に流されやすい人は、ストレスを溜めやすい傾向にあります。
相手の感情に自分自身が持っていかれないように、俯瞰して物事を見れるためにも程よい距離感で仕事をすることは良いです。
流されない人は上手に割り切っています。
もちろん協調性は必要ですが、自分の意見を伝えることでお互いの理解を深めて、チーム連携が円滑になると、コミュニケーションも活性化されて、結果良い方向に流れます。

## ちょっとだけ人のせいにする逃げ道をつくる
「〇〇のせいでこうなった！」「〇〇にこうされた！」など完全な被害者意識を持つことではありません。
「あの無茶ぶりはないよなぁ…」「もぉぉぉ忙しいのに！」と自分の気持ちを認めてあげる。でも悔しいからやってやる！くらいの感覚です。
少しだけ自分を擁護することで、気持ちを切り替えるきっかけになり、少しラクになれるかもしれません。
<br><br>
誰でも望みどおりにいかなかったり、フェアじゃないと感じた経験はあるはずです。
でも、いつまでも負の感情に縛られるのは心身ともにキツいです。
何でこんな気持ちを引きずらないといけないんだろう…とちょっと思えることで、道もひらけてくると思います。
【Linux】Dockerとdocker composeのインストール

# dockerのインストール

- リポジトリの追加

```
dnf config-manager --add https://download.docker.com/linux/centos/docker-ce.repo
```

- dockerのインストール

```
dnf -y install --nobest --allowerasing docker-ce docker-ce-cli
```

# docker composeのインストール

- docker composeのダウンロード

```
wget https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-linux-x86_64
```

※*docker compose*の最新バージョンは、[https://github.com/docker/compose/releases/](https://github.com/docker/compose/releases/)で確認する。

- 実行権限の付与

```
chmod 755 docker-compose-linux-x86_64 && mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
```

# 環境

| OS | カーネル |
| --- | --- |
| Rocky Linux release 8.5 (Green Obsidian) | 4.18.0-348.7.1.el8_5.x86_64 |
【Laravel】美しいへルパ関数の作り方

## この記事に書いてあること
Laravelアプリケーションでヘルパー関数を作成する方法について書いています。

## なぜ書いたか？
自作のへルパ関数を追加したいと思って、やり方を調べたら以下のようにcomposer.jsonファイルにヘルパー関数を追加する方法が多く紹介されていました。

```json:composer.json
"autoload": {
    "files": [
        "app/helpers.php"
    ],
}
```

たしかにこの方法でも追加はできるのですが、へルパ関数を何個も実装したい時にいちいちjsonファイルを追記する可能性が出てきたり、`composer dump-autoload`をする必要が出てきたりと面倒くさいなぁと思いました。

あと単純になんか綺麗じゃないなと。

そこで以下の記事を参考にさせていただき、サービスプロバイダとしてへルパ関数を実装することにしました。

https://levelup.gitconnected.com/create-your-own-helper-function-in-laravel-framework-a2395d6408f1

## 美しいへルパ関数の作り方
### サービスプロバイダを作成する
artisanコマンドを実行してHelperServiceProviderを作成します。

```
php artisan make:provider HelperServiceProvider
```

実行後は、`app\Providers`フォルダに`HelperServiceProvider.php`が作成されます。

### サービスプロバイダのregisterメソッドを編集
`HelperServiceProvider.php`の、register()メソッドに以下のコードを記述します。

```php:app\Providers\HelperServiceProvider.php
public function register()
{
    $allHelperFiles = glob(app_path('Helpers').'/*.php');
    foreach ($allHelperFiles as $key => $helperFile) {
        require_once $helperFile;
    }
}
```

上記のPHPコードでは`app\Helpers`フォルダに存在するPHPファイルすべてをインクルードしています。
`app\Helpers`フォルダ配下のPHPファイルに追加された関数は、コントローラ、モデル、ビューなどの任意の場所で使用することができるようになります。

### サービスプロバイダを登録する
今作ったサービスプロバイダを登録していきます。
config\app.phpを以下のように追記します。

```php:config\app.php
/*
* Application Service Providers...
*/
App\Providers\HelperServiceProvider::class,　//追記
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
```

### appHelpersディレクトリを作成する
へルパ関数を記述するためのディレクトリを作成します。
このディレクトリ内にへルパ関数を記述したPHPファイルを追加していきます。

```
app
└ Helpers/ 
     └ ◯◯◯.php
     └　　◯◯◯.php
     └ ◯◯◯.php
```

### ヘルパ関数の処理を記述したPHPファイルを作成する
今回は、挨拶を返す簡単な関数を`app\Helpers`ディレクトリ内に`say_Hello.php`という名前で新規作成しました。
このファイルには、名前空間を追加する必要はありません。
また、重要な点としてこの関数が先に宣言されているかどうかを確認するために`function_exists`メソッドを忘れないようにします。

```php:app\Helpers\say_Hello.php
<?php
if (! function_exists('say_Hello')) {
    function say_Hello($yourName)
    {
        return 'Hello'.$yourName;
    }
}
```

Laravel用の新しいHelperファイルの設定は以上です。
よきLaravelライフを！
AWS LambdaによるBolt for Pythonの話

# 今回のお話
AWS Lambda環境でBoltを動かしてみた話と動かすまでのアプローチの方法について書いていきます。

下記記事のコード部分のみ参考にさせていただきました。

https://dev.classmethod.jp/articles/bolt-lambda/

Boltに関してはWindowsのvenv環境でpip installしたライブラリで問題ありません。

# API Gatewayについて
概ね参考記事の通りで、公式の通りSlackアプリとLambda環境を整えていきます。

さて、API Gatewayですが、諸々諸事情により使い始めた頃から、プロキシの統合の使用を使わずマッピングテンプレートなるものを使ってました。

正確ではないかと思いますが、指定のContent-Typeでリクエストが来た場合にヘッダーを取り除いたり、Bodyの部分をJSONに整形したりなどLambdaに渡す前にデータを変換してくれるものです。

あまりちゃんと調べて使っていたわけでないので、Boltに渡すデータ形式とは？という所で躓きました。

結論はリクエストペイロードはそのまま渡せばいい（統合プロキシを有効とする）が正解でした。

それまでは、期待する結果とならず、なぜなのか悩んでいましたが後述するアプローチ方法により解決できました。

# ソースから読み解く
アプローチの仕方が正しいかはさておき、コード内のSlackRequestHandlerから読み解いてみます。どのようなデータを受け付けて処理しているのか中身から確認するスタイルです。

```
from slack_bolt.adapter.aws_lambda import SlackRequestHandler

slack_handler = SlackRequestHandler(app=app)
```

下記venv環境下のフォルダを参照します。initを見るとhandler.pyを読み取っていました。

venv\Lib\site-packages\slack_bolt\adapter\aws_lambda

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184018/25b23e2b-e5c9-02ac-2575-63389bbb5b61.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184018/3503aa6a-1e4f-8f5e-42a0-7ffaf10a13f5.png)


eventのキー値はヘッダー情報なので統合プロキシを有効化していないと取得できずエラーとなるため、統合プロキシを使用するのがよさそうです。そもそも統合プロキシを使用していていも赤枠のコード自体存在しないキー値を指定しているので必ずNoneになるのですけどね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184018/f7a67000-2940-dd5c-7c29-0e7748298c44.png)

body部分を取得してBoltReqestに返しています。統合プロキシを使用していればbody部分も取得できるのでこれで確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184018/5700cf44-c6b8-dbd1-4868-394aac686362.png)

# おわり
中々ソースから読むというのに慣れていないため、最初は壁が大きいですが、洗練されたコードの書き方や新しい発見があって、こういった原因調査以外でも何か作りたいけど何を作ればいいか分からないといった場面では、OSSのコードを読み解くというのも一つ勉強になるのかと思いました。
NTP ST1(GPS)サーバの自動起動

GPSなST1も自動起動にしてみました。

```ruby:getnema.rb
#!/usr/local/bin/mruby

port = "/dev/cuau0"

ser = SerialPort.new(port, 9600, 8, 1, 0)
ser.flow_control=0

ser.flush

getutc = 0

while getutc == 0 do
  line = ser.gets
  para = line.split(",")
  if para[0] == "$GPZDA"
    print para[4] + para[3] + para[2] + para[1].slice(0,4) + "." + para[1].slice(4,2)
    getutc = 1
  end
  if para[0] == "$GPRMC"
    print para[9].slice(4,2) + para[9].slice(2,2) + para[9].slice(0,2) + para[1].slice(0,4) + "." + para[1].slice(4,2)
    getutc = 1
  end
end
```

これで拾ったUTC時間をdate -uで設定したあとにntpdを起動します。


ST2は以下のようにしました。

```sh
#!/bin/sh

while :
do
	ntpdate 10.0.1.22
	if [ $? == 0 ]; then
		break
	fi
	ntpdate 10.0.1.20
	if [ $? == 0 ]; then
		break
	fi
done

ntpd -p /var/run/ntpd.pid
```

ST1から日時を拾えてからntpdを起動します。
火狐のhandlers.jsonメモ書き

Firefoxのプロファイルフォルダ以下にある`handlers.json`のメモ書き
私的なもので全体的に不明瞭。あくまで自己責任で参考程度に（バックアップは取ろう）

action: その形式のファイルへのリンクを踏んだ際の挙動
- 0=ファイルを保存？
- 1=設定画面から「毎回確認する」を選択して、それ以降確認時の選択を行っていない状態？
	- `"ask": true`でも直前の選択が反映されるっぽいので、それがない時の初期化された状態っぽい
- 2=任意の（或いはFirefox側の設定から指定した）プログラムで開く？
- 3=Firefoxで開く？
- 0=OS既定のプログラムで開く？

ask: 毎回確認するか否か（真偽値）
- 存在するのはtrueの時のみで、火狐側の処理だとfalseの時は削除されてるっぽい（使えないというわけではないと思う）
- actionに設定の一つとして組み込まれてないのは、前回の選択を維持してokを押すだけでいいようにしてくれるためだと思われる（ありがたい）

後は見たまんまだと思われ

### Tips:
- UTF-8
- jsonをFirefoxに投げれば整形表示できる
	- 手頃な整形手段やビューワがない時に便利
	- とはいえ今回のhandlers.jsonだと階層が深くて行間空きすぎで逆にわかりづらいまであるので、生データタブから整形ボタンを押してごちゃごちゃやるといいと思います
- おそらく`schemes`以下にあるやつに限り`handlers`値には`path`だけでなく`uriTemplate`とやらでウェブサービスも指定できるっぽい（要検証）
	- デフォルトのircのとことかメールのとことか参照
	- `mimeTypes`以下にあるようなやつ（ファイルだと思う）は無理（選択肢に出てきはするがおそらく無効、無効な値は無視される。）
	- `%s`で ~~リンク対象の値？~~ リンクそのものっぽかった　を指定できるっぽい。[ブックマークに登録してアドレスバーから検索するやつ](https://support.mozilla.org/ja/kb/how-search-from-address-bar)と同じ感じですね
		- 例えばgmailなら`https://mail.google.com/mail/?extsrc=mailto&url=mailto:info@example.com`というふうになってるぽかった（DevTools使って見た）

### 参考
[【レポート】 JSON ファイルを Firefox で整形表示する - MozillaZine.jp フォーラム • トピック](https://forums.mozillazine.jp/viewtopic.php?t=17399)
「json整形どうしよう...」と思いながら情報漁ってたら火狐に投げたらいけるってのをこれ見て思い出して「そうやん！」ってなって、あらかた書き上げた後に下の方見たら似たようなこと書いてあってちょっと悲しかった

### 追伸
最近のアップデートでよくわからんファイルクリックしちゃっても勝手にダウンロードしちゃって鬱陶しいんですけど、どうにかなりませんかね...
この記事の内容についてもそれ起因で調べたものだったんですが、結局これでやるとしたら手動設定するしかなさそうで...
about:configでいい感じにできるやり方をご存じの方いたら教えてください...

6/2 追記：  
5月31日リリースのFirefox 101からは以前の動作に戻す設定が追加されているらしい  
意図しないダウンロードが起きるのって後始末の面倒さとかからして超不快で、もともと火狐に移行した理由の一つでもあったのでうれしい（逆になんで変えたんだってキレてたし今でもキレてる）  
えらいぞ！（二か月かかりはしたけど）  
[Mozilla、「Firefox 101」をリリース ～新しいダウンロードオプションを追加 - 窓の杜](https://forest.watch.impress.co.jp/docs/news/1413598.html)  
> 　また、「Firefox」に登録されていないファイル形式（MIMEタイプ）をダウンロードする際の取り扱いをユーザー側で選べるようになった。「Firefox」はかつて毎回ファイルを保存するかを問うプロンプトを表示していたが、これが煩わしいとして、「Firefox 98」からは基本的に自動でダウンロードを開始し、その進捗をパネルに表示するスタイルを導入している。 
>
> 　しかし、ファイルを保存するか、開くかを自分で選びたいというユーザーも一定数いたようだ。「Firefox 101」ではダウンロードの取り扱いをカスタムする設定画面が拡充され、指定されていないファイルタイプを「Firefox」がどう扱うかを指定するオプションが追加されている。
ClojureのソースをNetBeansでコンパイルしてみた

Clojureはじめたばかりの初心者です。
ソースを読むのが好きなので、自分でコンパイルしてNetBeans内で動かしてみたいなぁと思いやってみました。

JavaはJava8がインストールされている必要があります。
(ClojureのコンパイルにはJava8以上が必要との事です)
NetBeansは 12.0を使っています。

ちなみにClojureのソースをダウンロードしてきて、mavenを使ったら、簡単にコンパイルできました。しかし、それではNetBeansで、ブレークポイントをかけたり、ステップ実行をしたりできなかった（やり方がわからなかった）ので、別の方法でコンパイルしてみようと思いました。

まず、NetBeansで、File > NewProjectから、Java with Ant > Java Applicationを選択し、作成します。

Clojureの最新ソースを落としてきて、clojure-master/src/jvmの下のJavaソース一式を先ほど作成したプロジェクトのsrcディレクトリにコピーしました。
NetBeansでコンパイルしてみたら、あっさり成功。
これ意外にあっさり動くんじゃね？と思ったら、実行時エラーの連続。
かなりハマりましたが、数時間の格闘で、なんとか動く所までこぎつけました。


clojure-master/src/clojure以下のソースも、同じくNetBeansのsrcに入れる必要があります。
但し、全部の clj を 使っている訳ではなさそうです。

次に clojure-master/resources/clojure/version.properties
これも入れる必要があります。

NetBeansで実行してみると、このpropertiesを読んでいる場所で異常終了してしまいます。
施行錯誤してわかったことは、version={}と書かれている所を1.2.3のように書きかえると
正常に動くようになりました。どうも正規表現を使って、1.2.3を分解して、それぞれに対して文字列を整数型に変換しているみたいです。なので、1.2とか書いてもダメです。

この後が、大変だったのですが、spec.alphaがなんとかいうエラーに悩まされました。
Clojureのソースとはまた別の場所にspec.alphaのソースもあるので、それも追加してみましたが、実行時エラーが発生します。
途方にくれていたところ、spec.alphaをコンパイルしたjarがある事がわかりました。

``` xml
<groupid>org.clojure</groupid>
<artifactId>spec.alpha</artifactId>
<version>0.3.218</version>
```

「mavenをjarファイルをダウンロードするだけ」に使い、jarファイルをダウンロードしてきました。
ダウンロードされた　spec-alpha-0.3.218.jar をNetBeansのlibに追加してコンパイルしたところ、なんとか、clojureのプロンプトが出て REPL が動く所までできました。

これで勉強環境は出来たので、ブレークポイントかけたり、ステップ実行してソースを読んで動かしてみたいと思います。
cscの作法 その71 積み上げ縦棒グラフ

# 概要
cscの作法、調べてみた。
積み上げ縦棒グラフやってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/9fe46ad4-fcaf-10d8-f39f-d4c37fa3e309.png)


# コンパイル手順

```
>set PATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319;%PATH%

>csc ch4.cs /r:System.Windows.Forms.DataVisualization.dll

```

# サンプルコード

```
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace WindowsFormsApplication1
{
	public partial class Form1 : Form {
		public Form1() {
			var chart1 = new Chart {
				Dock = DockStyle.Fill,
			};
			this.Controls.Add(chart1);
			string[] legends = new string[] { "グラフ１", "グラフ２" };
			string[] xValues = new string[] { "A", "B", "C", "D", "E" };
			int[,] yValues = new int[,] {{ 10, 20, 30, 40, 50 }, {20, 40, 60, 80, 100}};
			chart1.Series.Clear();
			chart1.ChartAreas.Clear();
			chart1.Titles.Clear();
			foreach (var item in legends)
			{
				chart1.Series.Add(item);
				chart1.Series[item].ChartType = SeriesChartType.StackedColumn;
				chart1.Series[item].LegendText = item;
			}
			for (int i = 0; i < xValues.Length; i++)
			{
				for (int j = 0; j < yValues.GetLength(0); j++)
				{
					DataPoint dp = new DataPoint();
					dp.SetValueXY(xValues[i], yValues[j, i]);
					dp.IsValueShownAsLabel = true;
					chart1.Series[legends[j]].Points.Add(dp);
				}
			}
			ChartArea area1 = new ChartArea();
			area1.AxisX.Title = "Title-XAxis";
			area1.AxisY.Title = "Title-YAxis";
			Title title1 = new Title("Title1");
			chart1.Titles.Add(title1);
			chart1.ChartAreas.Add(area1);
			Legend legend = new Legend();
			chart1.Legends.Add(legend);
			legend.Docking = Docking.Top;
		}
		[STAThread]
		static void Main() {
			Application.Run(new Form1());
		}
	}
}





```


以上。
Docker導入の設定 laravel

# この記事について
Dockerを初めてみてなかなか設定が大変だったのでまとめてみる。
この記事ではphpのlaravelフレームワークを使用しています。

# 作業環境
macOS Monterey


# 手順
gitからクローンした後の作業。

作業フォルダに移動

```
cd 作業フォルダ名
```

いらないdocker-composeを取り下げ

```
docker-compose down
```
dockerにcomposerをinstall
```
docker-compose run app composer install
```

続いてbuildを行う。
```
docker-compose build
```

それからこれ。この処理がまあまあ時間がかかる
```
docker-compose up -d
```

あとは
docker-compose.ymlに書かれているポート名を使って、ブラウザで
```
localhost:<ポート名>
```


とすれば動作確認ができる

# 追記
なぜかエラーが出たので以下の作業をした

dockerアプリに行き、目的のappを'start'で動作後、

```
docker-compose exec app bash
```
そして、以下のコマンドを１つずつ実行
```
cp .env.example .env
php artisan key:generate
php artisan cache:clear
```

この後ブラウザで
```
localhost:<ポート名>
```
をすれば実行を確認できました。

# 最後に
docker初心者すぎて１つ１つのコマンドの意味はよくわかっていませんが、そのうちわかるだろうというノリでやっています。参考に少しでもなれば。
Amazon Web Services 基礎からのネットワーク＆サーバー構築　改訂3版 のコマンドまとめ

# 目的
Amazon Web Services 基礎からのネットワーク＆サーバー構築　改訂3版で学習したコマンドを随時まとめていきます。

最終的には、Ruby on Rails を AWSで動かします。

https://www.amazon.co.jp/dp/B084QQ7TCF/ref=docs-os-doi_0

## コマンドまとめ

### ネットワーク関連のコマンド
「ping」「traceroute」「telnet」「nslookup」「dig」

## 個人的に使用したツール
* AWS構成図作成
https://www.diagrams.net/
GitHub Actionsで、Cron定期実行でプルリクエストを作成してマージする

# GitHub Actionsで、自動でプルリクを作成してマージする方法

`dev` -> `stage` へのプルリクエストの作成とマージをする機会があり、定期的に実行できたら楽なのでGitHub Actionsで作成してみました。

```yml
name: Auto merge dev2stage

on:
  schedule:
    - cron: "0 15 * * *"

jobs:
  auto-merge-dev2stage:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          ref: dev
      - name: 【定期実行】Create Pull Request dev2stage
        id: create-pull-request
        env:
          GH_TOKEN: ${{ secrets.AUTO_DEP_TOKEN }}
        run: |
          PULL_REQUEST_URI=$(gh pr create -B stage -t 【定期実行】dev2stage -l 'auto merge' -b "")
          echo "::set-output name=PULL_REQUEST_URI::$PULL_REQUEST_URI"
      - name: 【定期実行】Merge Pull Request dev2stage
        env:
          GH_TOKEN: ${{ secrets.AUTO_DEP_TOKEN }}
        run: |
          gh pr merge ${{steps.create-pull-request.outputs.PULL_REQUEST_URI}} --merge
```

## 定期実行

定期実行部分は、以下です。

```yaml
on:
  schedule:
    - cron: "0 15 * * *"
```

日本時間に合わせるために、15にしています。

## プルリクエスト作成部分

```yaml
      - name: 【定期実行】Create Pull Request dev2stage
        id: create-pull-request
        env:
          GH_TOKEN: ${{ secrets.AUTO_DEP_TOKEN }}
        run: |
          PULL_REQUEST_URI=$(gh pr create -B stage -t 【定期実行】dev2stage -l 'auto merge' -b "")
          echo "::set-output name=PULL_REQUEST_URI::$PULL_REQUEST_URI"
```

プルリクエスト作成部分では、[GitHub CLI](https://cli.github.com/)を使用して、プルリクエストを作成します。
`gh pr create` 部分で、CLIを用いてプルリクエストの作成を行っています。
[gh prコマンド](https://cli.github.com/manual/gh_pr_create)のオプションで、ベースブランチ、タイトル、ラベル、内容を設定しています。

この箇所でエラーがでる場合が、いくつかあります。

1. すでに`dev`->`stage`のプルリクエストが存在している場合
1. コンフリクトが存在する場合
1. 差分が存在しない場合

以上3つが、エラーでプルリクエストが作成できない場合です。
## マージ部分

```yaml
      - name: 【定期実行】Merge Pull Request dev2stage
        env:
          GH_TOKEN: ${{ secrets.AUTO_DEP_TOKEN }}
        run: |
          gh pr merge ${{steps.create-pull-request.outputs.PULL_REQUEST_URI}} --merge
```

マージ部分では、[GitHub CLI](https://cli.github.com/)を使用して、マージします。
メールアドレスを正規表現で指定する

指定したいメールアドレス例
```
example@example.com
```

メールアドレスにマッチする正規表現
```
^[a-zA-Z0-9_.+-]+@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$
```

ローカル部分( @ よりも前の部分)には仕様上はかなり多くの文字を使用できるが、Outlookを参考に
アルファベット(a-z)、数字(0-9)、ピリオド(.)、プラス(+)アンダーバー(_)ハイフン(-)を指定し以下のように記載。
```
[a-zA-Z0-9_.+-]+
```

ドメイン名はトップレベルドメインで使用できる文字はアルファベット(a-z)となっており、トップレベルドメイン以外のラベルについては数字(0-9)やハイフン(-)も利用可能。ただしハイフンはラベルの先頭と最後には使えない。
トップレベルドメイン部分
```
[a-zA-Z]{2,}$
```
それ以外のラベル部分
```
([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+
```

多分これで指定できるかと思います・・・。ご利用は計画的に。
2022/3/29主にITとかセキュリティの記事

金融機関に対策徹底を再度要請、攻撃受けたら報告を - 金融庁
https://www.security-next.com/135212

都内中小企業向けに特別相談窓口を開設 - サイバー攻撃リスクの増大受けて
https://www.security-next.com/135199

委託先が「Emotet」感染、個人情報が流出の可能性 - 相模原市
https://www.security-next.com/135184

偽警告で端末乗っ取り被害、被験者情報流出か - 国立がんセンター
https://www.security-next.com/135181

SaaSアプリケーションの設定不備がセキュリティの穴に、攻撃を防ぐ方法とは？(3/25)
https://wp.techtarget.itmedia.co.jp/contents/62899

巧妙な詐欺メールから高齢者を守れ(3/27)
https://gunosy.com/articles/a3V3G

米安保上の脅威企業、ウイルス対策「カスペルスキー」追加…初のロシア企業(3/26)
https://www.yomiuri.co.jp/economy/20220326-OYT1T50189/

エモテット感染、県内で拡大　メール添付ファイルに注意(3/27)
https://www.sakigake.jp/news/article/20220327AK0005/

日本企業へのサイバー攻撃急増。 サイバーセキュリティ人材が圧倒的に不足する日本の課題とは。(3/26)
https://news.yahoo.co.jp/byline/yusato/20220326-00287061

ウクライナへのサイバー攻撃に使われたマルウェア「IsaacWiper」とは？(3/25)
https://news.mynavi.jp/techplus/article/20220325-2303539/

知らない送信者からのメールに寄付を求めるGatedでメール削減(3/26)
https://jp.techcrunch.com/2022/03/26/2022-03-24-too-much-email-try-gated-which-asks-unknown-senders-to-make-a-donation-first/

Solana（SOL）DeFiAppCashioがハックで数百万を失う(3/25)
https://nextmoney.jp/?p=49028

クラウド活用を最適化、ゼロトラスト実現にも貢献する次世代プロキシとは？(3/24)
https://wp.techtarget.itmedia.co.jp/contents/62796

ネスレ、Anonymousがリークと主張の10GBデータはダミーデータと反論(3/27)
https://www.zaikei.co.jp/article/20220327/665904.html

ロシアからのインターネット接続は維持されている--ThousandEyes(3/24)
https://japan.zdnet.com/article/35185251/

足利･常陽銀行、システム障害の復旧「27日朝までに」(3/26)
https://www.nikkei.com/article/DGXZQOCC263N30W2A320C2000000/

米国がサウジの石油施設と米国の原子力発電所をハックしたロシアのスパイ4人を起訴(3/26)
https://jp.techcrunch.com/2022/03/26/2022-03-25-doj-russia-triton-united-states-nuclear/

地銀などシステム障害9行すべてでほぼ復旧 ATMなど利用可能に(3/27)
https://www3.nhk.or.jp/news/html/20220327/k10013553961000.html

デンソーに東映アニメも被害　サイバー攻撃に狙われる日本(3/28)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/092400133/032400073/

Web3(3/28)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600009/032200111/

メタバースの真価とは　10の疑問に答える(3/28)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600014/032300112/

「Emotet」の感染拡大を止められない理由
撲滅したはずの凶悪マルウエアが復活(3/28)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800013/031500051/

非IT企業でも「脱PPAP」が加速
マルウエア「Emotet」による被害が後押し　代替手段を導入済みの企業も(3/28)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800012/031500169/

初期設定では危ないGoogleアカウント、不正ログインからの防御法(3/28)
https://xtech.nikkei.com/atcl/nxt/column/18/01971/030300005/

Windowsに慣れた人でも大丈夫、Linuxの設定変更で使い勝手を向上(3/28)
https://xtech.nikkei.com/atcl/nxt/column/18/01961/022800005/
MVVMを実装するにあたっての備忘録

## 初めに
今回はMVVMアーキテクチャを採用するにあたって最低限意識したいことを備忘録として記述していきます。


## MVVMについて

### MVVMとは
Model, ViewModel, View で構成されるアーキテクチャです。
iOSでいうところのViewControllerはここでいうViewに含まれます。

### Model
MVCやMVPのModelレイヤーと同じ
APIで取得してきたデータを表現する
（データが更新されたらViewModelに通知する）

### View
ViewModelとバインディングする
UI のレイアウトなど表示に係る処理
UI イベントの ViewModel への伝搬
ビジネスロジックは書かない
例えばテキスト入力のバリデーションの処理などは書かない
テキストを ViewModel 経由で Model に渡して Model でバリデーションしてその結果を ViewModel 経由で View に渡して処理するのが正しい

### ViewModel
Model と View の橋渡し役で表示に関わる処理 (プレゼンテーションロジック)を書く、ビジネスロジックをここで持たせることもある
Viewからの情報を加工してまたViewに返す（表示更新）
Model のどの要素が UI のどの要素にマッピングされるか
UI のどのイベントが Model のどの操作にマッピングされるか
websocketを用いたAPIとMPAは相性が悪い？

# websocket-APIとREST-API
適当な説明↓
 - WebsocketはWebで軽量な双方向通信を行うことができるプロトコルとして知られています．
 - RESTはHTTPプロトコルを用いてデータのやり取りを行うことができます．

# 問題
**Websocketを用いたAPIはMPA(multi page application)に適していないのでは**
Websocketを使ってRPC形式のAPIを作っていた時に思ったのですが，ページ読み込み時はRESTより若干遅いです．

## なぜ遅いのか
MPAでwebsocket-apiが遅いと感じるのは，単純ですが1回ハンドシェイクを挟むためです．
図に表すと分かりますがページ遷移時にWebsocket-APIを叩く場合は，最大でRESTの2RTT分遅くなってしまいます．

``` websocket-api v.s rest
          websocket                            REST
  server               client    │  server               client            
    ------upgrade req----->      │    -------api req------->
      handshake via http         │       hit api via http
    <--switching protocol--      │    <------api res--------
                                 │
      ↓ estab ws conn            │ 
    -------api req-------->      │
      hit api via ws             │
    <------api res---------      │

```
MPAでは，websocketのコネクションはページ遷移するとともに失われてしまいます．よって，ページ遷移時にはコネクションを再度繋ぎなおす必要があります．
更に，MPAではページ表示時にデータを取得する事が多いため，コネクション確立が遅い分websocketを使う旨味は...
ただし，繋いでさえいれば速いのでSPAとは相性がいいはずです(フロントはあんまり知らないので適当())

# 対応策
 - フロントをSPAにする．
 - Websocket-APIの他に同じ機能を持ったREST-APIをもう一つ作って，ページ遷移時はRESTだけを叩くようにする.
 - 諦めてRESTだけにする．
【Rails】RSpecの導入

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

## RSpecの導入
### RSpecをインストールする
Gemfileの group :test do に以下の２つを追記します。

```:Gemfile
group :test do
  gem 'rspec-rails', '~> 3.8'
  gem 'factory_bot_rails', '~> 5.0'
end
```

`factory_bot_rails`をインストールすることでテストデータの用意が簡単になります。

Gemfileの編集が完了したら、`bundle install`してください。
```:ターミナル
$ bundle install
```

インストールできているか確認します。

```:ターミナル
$ bundle exec rspec --version
  RSpec 3.8
- rspec-core 3.8.2
- rspec-expectations 3.8.4
- rspec-mocks 3.8.1
- rspec-rails 3.8.2
- rspec-support 3.8.2
```

```:ターミナル
$ bundle exec gem list | grep factory_bot_rails
factory_bot_rails (5.0.2)
```

### RSpecを利用できるようにする

```:ターミナル
$ rails g rspec:install
```

コマンドを実行すると以下のファイルが生成されます。

```
sample-app
└── spec
    ├── rails_helper.rb
    └── spec_helper.rb
```

最後にテスト用のデータベースを最新の構成にするために以下のコマンドを実行します。

```:ターミナル
$ rails db:migrate RAILS_ENV=test
```
macFUSE + SSHFSでUbuntuのディレクトリをMacにマウントする

# やりたいこと

- Ubuntuに接続されている外付SSDにMacからSSHFS経由で接続し、FUSE(macFUSE)でマウントしてFinderから見られるようにしたい
- 複数のMacから接続できるため、ファイルサーバのような形で使用できる

<img width="400" alt="architecture" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78249/6bde699e-c0bb-d2ec-cd9a-90866aaa25b6.png">

# FUSEって？

- Filesystem in UserspaceでFUSE
- ユーザ空間でファイルシステムを実現し、色んなものをファイルシステムとして扱えるようにする仕組み

# SSHFSって？

- SSH FilesystemでSSHFS
- ファイルのやり取りにはSFTP/FTPS/SCP等を使用することが多いが、恒常的にファイルのやり取りをするには向いていない
- SSHFSではSSHで接続できるサーバのディレクトリをローカルにマウントし、恒常的にファイルをやり取りできるようなインタフェースを提供する

# macFUSEって？

- Mac環境で使用できるFUSEの実装
- https://osxfuse.github.io/

# サーバ(Ubuntu)側の設定

-　基本的にSSHデーモンが動いていればOK

```bash
$ sudo apt update
$ sudo apt install openssh-server
#　SSHデーモンが起動されているか(active (running))/自動起動が有効になっているか(enabled)の確認
$ sudo systemctl status ssh
# 起動/自動起動の有効化がされていない場合は有効化しておく
$ sudo systemctl enable ssh
$ sudo systemctl start ssh
# もしUFW(Uncomplicated Firewall)を使用している場合等は、SSH接続を許可しておく
$ sudo ufw status
$ sudo ufw allow ssh
```

# クライアント(Mac)側の設定

### インストール

- [公式サイト](https://osxfuse.github.io/)からmacFUSEとsshfsをダウンロードする
    - Homebrewを使用できる模様

<img width="300" alt="fuse-install" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78249/be05fe8f-2dfb-2d40-9889-3bf88cf3e6bd.png">

### マウント

```bash
# ローカルにマウントに使用するディレクトリを作成する
$ mkdir /path/to/hoge
# マウントする
$ sshfs username@servername:/path/to/piyo /path/to/hoge
```

### アンマウント

```bash
$ umount /path/to/hoge
```
【iOS】【SDWebImagePDFCoder】PDFの1ページ目を画像として表示する

PDFの1ページ目を画像として表示する方法がパッと見つからなかったけど、
プラグイン使えば簡単だった。
ってことでメモしとく。

ちなみにSDWebImageを利用する想定。他のライブラリも何かしらあるのだと思う。

## 方法

これに書いてある通り！以上！
https://github.com/SDWebImage/SDWebImagePDFCoder

CocoaPodsでもCarthageでもSPMでもいいからinstallして、
SDImageCodersManagerにPDFCoder登録してあげればいいだけ。

簡単なサンプル↓

```swift

import UIKit
import SDWebImagePDFCoder

class ViewController: UIViewController {
    @IBOutlet weak var hogeImageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        hogehgoe()
    }

    func hogehoge(){
        let PDFCoder = SDImagePDFCoder.shared
        SDImageCodersManager.shared.addCoder(PDFCoder)
        hogeImageView.sd_setImage(with: URL(string: "~PDFのURL~"))
    }
}
```
GoogleTest+カバレッジMemo

GoogleTestの実行ファイルを
1ケースごとフィルタかけてカバレッジ出力(lcov)するBashのメモ

```bash:google_lcov.sh
#!/bin/bash

# 引数チェック
if [ $# -ne 1 ]; then
	echo "引数を設定してください"
	exit
fi

# google test リスト取得
list_test=$(./"$1" --gtest_list_tests)

count=1
for el in $list_test; do

	if [[ $el =~ .*\. ]]; then
		case_name=$el
	else
		# 検査実行
		"./$1" --gtest_filter="$case_name$el"

		# フォルダ作成
		mkdir_name=$(printf %02d $count)."$case_name$el"
		mkdir "$mkdir_name"

		find_path=$(find ./ -name "*.gcda")
		declare -A tmp_map

		# 一意の*gcda格納ディレクトリを取得
		for el2 in $find_path; do
			tmp_map[$(dirname "$el2")]=''
		done
		
		# lcovオプション作成
		uniq_dir_name=${!tmp_map[@]}
		for el2 in $uniq_dir_name; do
			lcov_d_options+="-d .""$el2"" "
		done

		# ディレクトリ移動
		cd "./$mkdir_name" || exit

		# カバレッジ出力
		lcov -c $lcov_d_options -o lcov.info
		genhtml lcov.info -o ./info

		# 元のディレクトリに戻る
		cd ../

		# 前の出力の削除
		# ちょっと微妙だけど
		find ./ -name "*.gcda" -exec rm {} \;

		((count++)) || true
	fi
done

```
【JavaScript】Canvasで単純なお絵描きツール

# サンプル

https://mogamoga1024.github.io/SimpleDrawingTool/

# 結論（ソース）

```html:index.html
<canvas style="border: 1px solid black;" width="600" height="600"></canvas><!--
--><button id="clear-button" style="margin-left: 30px; user-select: none;">クリア</button>

<script src="drawingCanvas.js"></script>
<script src="main.js"></script>
```

```javascript:main.js
const canvasHtmlElement = document.getElementsByTagName("canvas")[0];
const clearButtonHtmlElement = document.getElementById("clear-button");

const drawingCanvas = new DrawingCanvas(canvasHtmlElement);

["mousedown", "mouseover"].forEach(eventName => {
    canvasHtmlElement.addEventListener(eventName, function(event) {
        if (event.buttons !== 1) return; // 左クリック以外描画不可
        drawingCanvas.drawStart();
    });
});

["mouseup", "mouseout"].forEach(eventName => {
    canvasHtmlElement.addEventListener(eventName, function(event) {
        drawingCanvas.drawEnd(event.offsetX, event.offsetY);
    });
});

canvasHtmlElement.addEventListener("mousemove", function(event) {
    drawingCanvas.draw(event.offsetX, event.offsetY);
});

clearButtonHtmlElement.addEventListener("click", function() {
    drawingCanvas.clear();
});
```

```javascript:drawingCanvas
class DrawingCanvas {
    #context; #lastPosition; #canDraw;

    constructor(canvas) {
        this.#context = canvas.getContext("2d");
        this.#context.lineCap = "round";
        this.#context.lineJoin = "round";
        this.#context.lineWidth = 5;
        this.#context.strokeStyle = "black";

        this.#lastPosition = {x: null, y: null};
        this.#canDraw = false;
    }

    draw(x, y) {
        if(this.#canDraw === false) {
            return;
        }
    
        if (this.#lastPosition.x === null || this.#lastPosition.y === null) {
            this.#context.moveTo(x, y);
        } else {
            this.#context.moveTo(this.#lastPosition.x, this.#lastPosition.y);
        }
        this.#context.lineTo(x, y);
        this.#context.stroke();
        
        this.#lastPosition.x = x;
        this.#lastPosition.y = y;
    }
    
    drawStart() {
        this.#context.beginPath();
        this.#canDraw = true;
    }
    
    drawEnd(x, y) {
        this.draw(x, y); // クリックのみでドラッグされなかった場合、点を描画するために呼び出す。
        this.#context.closePath();
        this.#canDraw = false;
        this.#lastPosition.x = null;
        this.#lastPosition.y = null;
    }
    
    clear() {
        const canvas = this.#context.canvas;
        this.#context.clearRect(0, 0, canvas.width, canvas.height);
    }
}
```

以上

# 参考元サイト

https://tsuyopon.xyz/2018/09/14/how-to-create-drawing-app-part1/

https://tsuyopon-xyz.github.io/drawing_app_part1/

# 参考元サイトのソースとの違い

* contextの設定が一度だけ行われるようにした。
* 点が描けるようにした。
* mouseoverでも描けるようにした。
* event.layerX, event.layerY → event.offsetX, event.offsetY
100日でSQLの達人になる@LeetCode! Day53 <MS SQL Serverでループ処理>

## MS SQL Serverでループ処理をする
前回に引き続き[LeetCode](https://leetcode.com/)の問題はお休み。
今回のテーマはループ処理です。

前回同様に[db<>fiddle](https://dbfiddle.uk/?rdbms=sqlserver_2019)を使って、テーブルにデータを格納するクエリを書いていきます。

### ループ処理の基本
```:SQL
WHILE 条件式(条件式を満たす間ループは継続される)
BEGIN
    --繰り返し実行したいコードを記載する
END
-- BREAKでループ処理を中断
-- CONTINUEでループ処理の最初へ戻る
```

下記が実行例です。
<!-- -->
>     CREATE TABLE tbl1 (id INT)
>     
>     INSERT INTO tbl1 (id) VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
>     
>     DECLARE @var1 INT = 1, @var2 INT = 0
>     
>     WHILE @var1 < 10
>     BEGIN
>         SET @var2= @var2+@var1
>         PRINT @var2
>         SET @var1= @var1+1
>     END
> <pre>
1
3
6
10
15
21
28
36
45
10 rows affected
> </pre>

*db<>fiddle [here](https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=ea482143e80ba4510adbab5eb0ec0cbf)*

今日のポイントは`MS SQL Serverでループ処理をする`とした。
100日でSQLの達人になる@LeetCode! Day52 <要復習：MS SQL Serverで変数>

## MS SQL Serverで変数を使用する
前回に引き続き[LeetCode](https://leetcode.com/)の問題はお休み。
今回のテーマは変数。これも[LeetCode](https://leetcode.com/)の回答で時々見かけて気になっていたので今回学習しました。

前回同様に[db<>fiddle](https://dbfiddle.uk/?rdbms=sqlserver_2019)を使って、テーブルにデータを格納するクエリを書いていきます。

### 変数の宣言
変数を使うには、最初に変数の宣言が必要になります。
変数宣言の基本はこれ。
```:SQL
DECLARE @変数名 変数の型
```
複数の変数をまとめて宣言も可能。
```:SQL
DECLARE @変数名1 変数の型
       ,@変数名2 変数の型
       ,@変数名3 変数の型
```
このように初期値を設定して宣言することも可能。
```:SQL
DECLARE @変数名 変数の型 = 初期値
```
同様にまとめて宣言も可能。
```:SQL
DECLARE @変数名1 変数の型 = 初期値1
       ,@変数名2 変数の型 = 初期値2
       ,@変数名3 変数の型 = 初期値3
```       


### 変数に値の代入
変数に値を代入する方法です。
```:SQL
SET @変数名 = 設定したい値
```

`SELECT文`を使って変数に値を代入することも可能です。
ただしこの場合は、最終レコードの値が代入されます。
一致するレコードの値が無い場合は、変数の値は変更されません。
```:SQL
SELECT @変数名 = カラム名1 FROM テーブル名
```

### 変数の表示
変数の内容を表示するには、
```:SQL
PRINT @変数名
```

下記が実行例です。
<!-- -->
>     CREATE TABLE tbl1 (id INT)
>     
>     INSERT INTO tbl1 (id) VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
>     
>     DECLARE @var1 INT, @var2 INT = 0
>     
>     PRINT @var1
>     PRINT @var2
>     PRINT '------'
>     
>     SET @var1=1
>     
>     PRINT @var1
>     PRINT @var2
>     PRINT '------'
>     
>     SELECT @var2= id FROM tbl1
>     
>     PRINT @var1
>     PRINT @var2
>     PRINT '------'
> <pre>
 
0
------
1
0
------
1
10
------
10 rows affected
> </pre>

*db<>fiddle [here](https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=684b0437cfe3b4890594a57ee9f9ccb6)*

今日のポイントは`MS SQL Serverで変数を使用する`とした。
【講義20.デプロイ】Mysql workbenchを使うときに役に立った構文

# 本記事について
今後の開発の参考になればと思い、Mysql workbenchを使用した際の実体験をまとめたもの。

## Mysql workbenchについて
データベースアーキテクト、開発者、DBAのための統合ビジュアルツールです。
データ・モデリング、SQL 開発、およびサーバー設定、ユーザー管理、バックアップなどの
包括的な管理ツールを提供します。Windows、Linux、Mac OS Xで利用可能です。
（公式：https://www.mysql.com/jp/products/workbench/）

## Mysql workbenchを使用した背景
Herokuを使用したDeployを行う際、データベースとしてMysql workbenchを使用。
ローカルはXAMPP×phpmyadmin、phpmyadminからダウンロードしたsqlファイルを
Mysql workbenchにインポートして使用した。

## 役に立った構文_その1
phpmyadminからダウンロードしたsqlファイルのインポートを行なった際、
1つのテーブルにidとuser_idというカラムが存在していたことが原因で、idのPrimaryキーが外れてしまった。

最初にMysql workbenchの画面で以下の構文を実行。
該当のテーブル、カラムにPrimarykeyが存在している確認。
```
show columns from [テーブル名];
```
Keyの列を確認するがPrimarykeyになっていない。
　![スクリーンショット 2022-03-28 22.52.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1695131/d1f526b7-b5e3-cb2e-2936-21da17853d01.png)!

一度テーブルを削除した後、
idのデータ型指定の後ろにAUTO_INCREMENT NOT NULL primary keyをつけることで解決した。

一旦テーブル削除
```
DROP TABLE [テーブル名];
```
該当するカラムをPrimarykeyへ変更
```
CREATE TABLE [テーブル名] (
  id int(12) AUTO_INCREMENT NOT NULL primary key,
  user_id int(12) NOT NULL,
　　　　~中略~
  is_deleted int(1) NOT NULL,
  created_at datetime NOT NULL,
  updated_at datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
```
Primarykeyに変わっているか確認する...
```
show columns from [テーブル名];
```
▼結果
![スクリーンショット 2022-03-29 0.53.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1695131/c3d0fb29-2114-023d-5ce9-7ad7312ae3a9.png)

成功🍻

## 役に立った構文_その2
phpmyadminからダウンロードしたデータベースが最新ではなかった!
再度、phpmyadminからダウンロードを試みるも、XAMPPが壊れる...GitHubにもbackupなし...
...最新でないとはいえ、Mysql workbench側でカラム追加したら良いか!と開き直る

既存カラムの後ろ（右隣）に新規カラム追加
```
ALTER TABLE テーブル名 ADD 新規カラム名 型情報 AFTER 既存カラム名;
```
先頭（一番左）にカラム追加
```
ALTER TABLE テーブル名 ADD 新規カラム名 型情報 FIRST;
```
複数のカラムを一括で追加
```
ALTER TABLE テーブル名 ADD (新規カラム名１ 型情報, 新規カラム名２ 型情報, ...);
```
例:「user」テーブルに、「mail」と「tel」の２つを追加する場合は以下のようなクエリになる。
```
ALTER TABLE user ADD (mail text, tel tinytext);
```

以上
疑似要素にsvgアイコンを使用する

#### SVGアイコンの大きさを変えたい
```
        &::after {
          content: '';
          background-image:  url('svgのurl');
          width: 12px;
          height: 12px;
          display: inline-block;
          background-repeat: no-repeat; //画像をリピートしない
          background-size: contain; //画像の縦横比を崩さず範囲いっぱいの大きさにする
          margin-left: 10px;
        }
```
background-imageでsvg画像を指定する。

#### 大きさを変えなくていい
```
        &::after {
          content:  url('svgのurl');
        }
```
ならcontentにそのままurlを指定することでsvgアイコンを疑似要素に指定できる。
VS Codeで「conda : 用語 'conda' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されません。名前が正しく記述されていることを確認し、パスが含まれている場合はその パスが正しいことを確認してから、再試行してください。」

# エラー

Python用のエディタとしてVS Codeを導入しようとした際、ターミナルを開くと以下のエラーが発生
![vscode_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873482/f563164f-b625-cfb3-4877-e54ca9b6e0e1.png)

# 対策

1) 設定ファイルをJSONで開く（```Ctrl＋,```で設定を開いた後、図のボタンをクリック）
<img width="300" alt="設定(JSON)を開く" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873482/0f5ccc55-e27f-374a-7f56-bb43db6a13cb.png">

2) 以下をsetting.jsonに追記

```json: setting.json
    ...,
    "terminal.integrated.defaultProfile.windows": "Command Prompt",
    "terminal.integrated.profiles.windows": {
        "PowerShell": {
            "source": "PowerShell",
            "icon": "terminal-powershell"
        },
        "Command Prompt": {
            "path": [
                "${env:windir}\\Sysnative\\cmd.exe",
                "${env:windir}\\System32\\cmd.exe"
            ],
            "args": [
                "/k",
                "chcp",
                "65001"
            ],
            "icon": "terminal-cmd"
        },
        "Git Bash": {
            "source": "Git Bash"
        }
    },
    "terminal.integrated.fontSize": 17
}
```

# 解決

無事にcondaコマンドが通った
![no_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873482/8eb9494b-5f39-cfca-a360-7cef7925a2e4.png)

# 参考
- https://manumaruscript.com/vscode-conda-activateerror/
Dartの基本文法チートシート初歩の初歩

# Dartチートシート

flutterを触り始めたので、Dartのコードをすぐに書けるようにチートシート作りました。

# クラスclass

```dart
class Animal {
    String name;
    int age;
    Animal(this.name, this.age) {
    }
    String greet() {
         return "${age}歳の${name}です。";
    }
}

class Dog extends Animal {
    String greet() {
        return "${super.age}の${super.name}だわん";
    }
}
```


# 関数function

デフォルト値の設定

```dart
double culcTax(int price,
    [double rate = 0.10]) {
    return price * (1 + rate);
}
```

パラメータ名を引数に指定可能

```dart
Bool createUser({String name, String password}) {
    try {
       var user = new User(name, password);
    } catch (e) {
       logger.e("User create failed ${e}");
       return false;
    }
    return true;
}

ret = createUser(password="PASSWORD", name="admin")
```

# データ型

### 基本データ型

#### int, double, num

```dart
num i = 1.0;
j = 10;
```

#### String

```dart
const a = "a";
var b = 'a';
var c = '''
abc
def
'''
```

#### Bool

`true` か `false`

### List

```
final list = <String>[];
list = ["a","abc"];
list.length;
list.add("d");
list[0] = "123";
print(list.where((String value) => value.length > 0)));
list.map((int value) => value * 2)
    .toList();
```

[Listリファレンス](https://api.dart.dev/stable/2.10.4/dart-core/List-class.html)

### Map

```dart
  final fluits = <int, String>{
    0: 'Apple',
    1: 'Peach',
    2: 'Litchi',
  };
  fluits.putIfAbsent(0, () => 'Banana');
```

[Mapリファレンス](https://api.dart.dev/stable/2.15.1/dart-core/Map-class.html)

### 日付時間

*DateTime* 型を使う

[DateTimeリファレンス](https://api.flutter.dev/flutter/dart-core/DateTime-class.html)

文字列変換

##### StringからDateTime

```dart
DateTime.parse("2012-02-27 13:27:00")
```

次のフォーマットに対応している

* "2012-02-27 13:27:00"
* "2012-02-27 13:27:00.123456z"
* "20120227 13:27:00"
* "20120227T132700"
* "20120227"
* "+20120227"
* "2012-02-27T14Z"
* "2012-02-27T14+00:00"
* "-123450101 00:00:00 Z": in the year -12345.
* "2002-02-27T14:00:00-0500": Same as "2002-02-27T19:00:00Z"

##### DateTimeからString

```dart
 var formatter = new DateFormat('yyyy/MM/dd(E) HH:mm', "ja_JP");
 var formatted = formatter.format(datetime); // DateからString
```


# 　参考リンク

* [Dart APIリファレンス](https://api.dart.dev/)
* logger [logger 1.1.0](https://pub.dev/packages/logger)
* 株式会社クレス Dart2 言語 - 例外 (Exceptions) [Exception](https://www.cresc.co.jp/tech/java/Google_Dart2/language/exceptions/exceptions.html)
* ブラウザで試すことができる[DartPad](https://try.dartlang.org/)
JavaScriptでオセロを作ってみた。リファクタリング。

以前に投稿して随分と時間が経ってますが、たまにストックしてくださったり見てくださる方がいらっしゃいます。
より良く新しい記述を提供できたらと思ったので今回リファクタリングを試みました。

初学者の方のお役に立てればと思います。

以前投稿した記事はこちら

https://qiita.com/tanimoto-hikari/items/c5daefd9af9989b9b8dd

以前のコード

```js
window.onload = function(){

  var $tableElements = document.getElementsByTagName('td');
  //順番を制御するための変数
  let order = true; //trueは黒（先行）
  let othelloWhte = '◯';
  let othelloBlack = '●';
  let othelloColor = othelloBlack;

  //tableの全てにclickイベントを付与する
  for (let $i=0; $i < $tableElements.length; $i++) {
    $tableElements[$i].addEventListener('click', function(){
      //配列に変換する
      let tableElements = [].slice.call($tableElements);
      //クリックした位置の取得
      let index = tableElements.indexOf(this);
      putOthello(index);
      changeOrder();
    });
  }

  function putOthello(index) {
    $tableElements[index].innerHTML = othelloColor;
  }
  //順番の判別する
  function changeOrder() {
    if (order) {
      othelloColor = othelloWhte;
      order = false;
    } else {
      othelloColor = othelloBlack;
      order = true;
    }
  }
}

```

### 修正点
- othelloWhte →スペルミス
- var $tableElements　→ なぜかvarで定義されている
- 順番を制御するための変数やオセロの色の箇所もっとすっきりできるはず
- 配列の変換→スプレット演算子活用
- for文の変数がなぜか$i （PHPでも書いていたつもりだったのか？）
- 順番を判別する関数はまるっと必要ないと思ったので消す

いろいろと恥ずかしい感じになっているのを直しました…

```js
window.onload = function() {

  // tdを取得
  const $tableElements = document.getElementsByTagName('td');

  // 先手　true: 黒、false：白
  let order = true;

  // tableの全てにclickイベントを付与する
  for (let i = 0; i < $tableElements.length; i++) {
    $tableElements[i].addEventListener('click', function() {
      // 配列に変換する
      const tableElements = [...$tableElements];

      // クリックした位置の取得
      const tableIndex = tableElements.indexOf(this);
      putOthello(tableIndex);
    });
  }

  /**
  * @param {number} index
  */
  function putOthello(index) {
    // すでにオセロが置かれていた場合は処理をさせない
    if ($tableElements[index].innerHTML) return false;

    // ifを省略してtrueなら右側、falseなら左側が代入されるように記述
    const othello = (order) ? '●' : '◯';
    $tableElements[index].innerHTML = othello;

    // 最後に順番を反転させる
    order = !order;
  }
}
```

わりとすっきりした気がします。
ついでにすでにオセロが置いてある箇所は無駄な処理が走らないように早期リターンさせておく記述を追記しておきました。
引数に何が入ってくるかをコメントに書いてわかりやすくしておきました。

この時点ではオセロをただおくだけなので、次回は以前書いたカオスな置き換え処理をもう少し綺麗に書けないか考えてみます。
基本情報技術者試験対策　18日目

基本情報技術者試験勉強　18日目
-
この記事の目的
-
今年の5月に基本情報技術者試験を合格するために、過去問で間違えた箇所をただまとめる自分のための記事

プロフィール
-
・文系大学の３年生
・ITパスポートは保有
・ウェブアプリやサイト作成を個人で行ったことがある程度
・猫好き

今日の目標
-
テクノロジー系を中心に取り組み。苦手を一つ一つ潰す。

間違った箇所
-
1、AES（Advanced Encryption Standard）
アメリカの次世代暗号方式として規格化された共通鍵暗号方式
（テクノロジ系 » セキュリティ » 情報セキュリティ）

2、サーミスタ
湿度の測定に使用される電子部品

3、ホール素子
磁界を検出するために使用される素子

4、ひずみゲージ
物体のひずみを測定するためのセンサ
（テクノロジ系 » ハードウェア » ハードウェア）

5、BNF（Backus Naur Form）
XMLなどプログラム言語の構文定義に用いられている記法
数字　1 ~ 9
英字　A ~ F
英数字　_　または、数字、英字
変数名　英字一文字　または、変数名　＋　英数字
（テクノロジ系 » 基礎理論 » 情報に関する理論）

6、クロスコンバイラ
コンパイラが動作している以外のプラットフォーム向けに実行ファイルを生成する機能を持つコンパイラ

7、エミュレータ
異なるアーキテクチャのコンピュータ用のプログラム命令を解読しながら実行するマイクロプログラム

8、ジェネレータ
ソースコードを記述しなくても、処理条件の入力、処理、出力、引数などのパラメータを設定することで自動的にプログラムを生成する言語プロセッサ

振り返り
-
テクノロジ系の問題のみ取り掛かったが、やはり4,5割程度しか取れていない。また、時間をかけてじっくり読めば、正解率は上がるが、なるべく早く答えることを心がける。午前問題は、120分で、80問のため、目安としては、1分1問ぐらいで答える。

>引用
基本情報技術者試験ドットコム
https://www.fe-siken.com
100日でSQLの達人になる@LeetCode! Day51 <INSERT INTOでテーブルにデータを追加する>

## テーブルにデータを追加する
前回に引き続き[LeetCode](https://leetcode.com/)の問題はお休み。
前回は空のテーブルを作成する方法をまとめたが、今回は作成したテーブルにデータを格納していく方法。

前回同様に[db<>fiddle](https://dbfiddle.uk/?rdbms=sqlserver_2019)を使って、テーブルにデータを格納するクエリを書いていきます。
```:SQL
-- 1行目データ
INSERT INTO テーブル名 (変数名1, 変数名2, 変数名3)　VALUES (データ1, データ2, データ3)
-- 2行目データ
INSERT INTO テーブル名 (変数名1, 変数名2, 変数名3)　VALUES (データ1, データ2, データ3)
```
これが基本形。

```:SQL
INSERT INTO テーブル名 VALUES (データ1, データ2, データ3)
INSERT INTO テーブル名 VALUES (データ1, データ2, データ3)
```
変数の数全てにデータを格納していく場合には、変数名リストを省略可能。

```:SQL
INSERT INTO テーブル名 VALUES (データ1, データ2, データ3)
```
変数の数全てにデータを格納していく場合には、変数名リストを省略可能。

```:SQL
INSERT INTO テーブル名 (変数名1,　変数名3)　VALUES (データ1,　データ3)
```
上記のように特定の変数にのみデータを格納していくことも可能。
データを省略したところには`NULL`値や`DEFAULT`値などが格納されます。

下記が実行例です。
<!-- -->
>     CREATE TABLE tbl1 (id INT IDENTITY(1,1), name NVARCHAR(10), age INT DEFAULT 20)
>     
>     INSERT INTO tbl1 (name) VALUES('TANAKA')
>     INSERT INTO tbl1 (name,age) VALUES('GOTO', 30)
>     
>     SELECT * FROM tbl1
>     GO
*db<>fiddle [here](https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=36be5d318b2812a4c357018f1cd7afad)*

|id | name   | age|
| -: | :----- | --:|
|  1 | TANAKA |  20|
|  2 | GOTO   |  30|

idは`IDENTITY`を指定しているため自分で入力しようとするとエラーになった。

また、
```:SQL
INSERT INTO テーブル名 (変数名1, 変数名2, 変数名3)　
VALUES 
(1行目データ1, データ2, データ3),
(2行目データ1, データ2, データ3),
(3行目データ1, データ2, データ3)
```
と複数行データを一括登録することも可能。

更には今回深入りはしないが、
```:SQL
INSERT INTO テーブル名 (変数名1, 変数名2, 変数名3)　
SELECT var1 var2 var3 FROM tbl2
```
のように`SELECT文`や`CASE WHEN`を使用することも可能。

今日のポイントは`INSERT INOTでテーブルにデータを格納する`とした。
DearPyGui で font setting するメモ

## 背景

dearpygui のフォントを設定したい..

## 手順

ネット上の情報ではいろいろ古かったりして, 最新 dearpygui では使えなかったりします.

基本は本家のマニュアル参照ください.

https://dearpygui.readthedocs.io/en/latest/documentation/fonts.html

また, `add_font(default_font=True)` や `dpg.font` では, デフォルトフォント設定(`default_font` パラメータ)というはできなくなっています.

明示的に `dpg.bind_font` を呼ぶ必要があります.


## バイナリフォント?

`add_font` ではファイルからしかサポートしていません.
アプリを pyinstaller とかで配布したい場合, フォントとかリソースを埋め込みとかしたいですよね.

とりあえずは base64 エンコードして python スクリプトに文字列として保存しておき, tmpfile で一度ファイルにおとすことになります.
(`io.BytesIO` で疑似ファイル化は対応していなかった).

## フォントがぼやける...

imgui の構造上(OpenGL rendering), どうしても font がぼやけます(本家 imgui で subsample 増やしてもダメ).
 
https://github.com/thedmd/imgui-node-editor/issues/46

https://github.com/hoffstadt/DearPyGui/issues/1380

OS 依存ですが DPI 設定をうまく設定できればある程度改善できるかもしれません.
AWS CLIで別アカウント追加

## 結論
`aws configure --profile プロファイル名`で追加できる。

## 例
```zsh
$ aws configure --profile test
AWS Access Key ID [None]: XXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

## 切り替え
### 一時的
`--profile プロファイル名`をつけてawsコマンドを実行すれば、そのプロファイルで実行できる。
### デフォルトを切り替え
`export AWS_DEFAULT_PROFILE=プロファイル名`で切り替え。

## 参考文献
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-profiles.html
> 名前付きプロファイルを使用するには、コマンドに --profile profile-name オプションを追加します。次の例では、前のサンプルファイルの user1 プロファイルで定義されている認証情報および設定を使用して、すべての Amazon EC2 インスタンスを一覧表示します。
Catalina→BigSur→Monterey移行時にVirtualBoxのネットワークが繋がらなくなった

# はじめに

久しぶりに投稿。
個人的な理由で、最近になってMacのメジャーバージョンアップを行い、

Catalina → Big Sur → Monterey

とMontereyまで２段階上げたのですが、
久しぶりにvagrant環境でVirtualBoxを立ち上げるとネットワークが繋がらなくなっていました。

結論としては、
- 関連ソフト導入
- ネットワーク設定

だけだったのですが、エラーログも見つからず、苦戦したので残しておきます。
誰かの役に立てば幸いです。

# 環境

macOS Monterey 12.2.1
Vagrant 2.2.14
VirtualBox 6.1.32 r149290

ゲスト環境はCentOS7系の、NAT+ホストオンリーアダプターでネットワーク構築されたイメージを使用してます。
仕事で用意してもらった環境なので、詳細は伏せます。

# 発生した問題

`vagrant up`で立ち上げたwebサーバに対して、ホストからゲストへcurl, pingしても反応がない。

`vagrant up`で表示されるログも問題らしきログが見つからない。

`~/VirtualBox\ VMs/`以下のVirtualBoxのログにも、特に影響がありそうなものは見つからなかった。

`vagrant ssh`　してゲスト自身へはcurlできるため、
ネットワークに問題があることはわかっていたが、
`ifconfig`で表示されるインターフェースは特に問題なさそう

```
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.100.10  netmask 255.255.255.0  broadcast 192.168.100.255
```

ネットで探したところ、`vagrant up`実行時のエラーに関する記事が主だったので困りましたが、
関連しそうな記事から必要操作を抜き出して実施しました。

# 対応

以下対応を行い、Macを再起動

## 関連ソフト導入
```
sudo kmutil load -b org.virtualbox.kext.VBoxDrv
sudo kmutil load -b org.virtualbox.kext.VBoxNetFlt
sudo kmutil load -b org.virtualbox.kext.VBoxNetAdp
sudo kmutil load -b org.virtualbox.kext.VBoxUSB
```

許可設定が必要な方もいるかと思います。
[参考記事](https://qiita.com/akane_kato/items/c103332729e3d0ac39e6)を参照してください。

## ネットワーク設定

ホストオンリーアダプタで使用できるipが限定されるよう変更されたそうです。
とりあえず、全ip許可する形で対応します。

```
# sudo mkdir /etc/vbox
sudo vi /etc/vbox/networks.conf
```

再起動後、`vagrant up`

## 参考
- [【macOSアップデート】vagrant upできない時に一通り試すと良いかもしれない方法](https://qiita.com/akane_kato/items/c103332729e3d0ac39e6)
- [Vagrant 2.2.18, OSX 11.6 cannot create private network](https://discuss.hashicorp.com/t/vagrant-2-2-18-osx-11-6-cannot-create-private-network/30984/22)


# おわり

私の環境ではなぜかエラーログらしきものが出てこなかったのですが、
これでゲスト環境へ接続できるようになりました。

調べていて初めて知りましたが、Mac M1ではVirtualboxがサポートされていないらしく、結構衝撃でした。
[Oracle、Big SurとMontereyで発生していた不具合を修正しサポートしていないApple M1チップ搭載のMacにインストール出来ないようにした「VirtualBox 6.1.30」をリリース。](https://applech2.com/archives/20211125-virtualbox-not-support-apple-m1-mac.html)

時代はDockerかな...