OmniAICreator/Qiita-1.07M huggingface dataset:
Stable Diffusionを試してみる

僕の持ってるPCにNVIDIAのGPUがないため、ローカルでの実行を断念したStableDiffusion試行だが、
試せるサイトがあったのでちょっと動かしてみた。


※StableDiffusionはざっくり説明すると作って欲しい画像を説明したテキストを渡すと画像を生成してくれるOSSサービスである。

かなり混雑しているが以下でデモができる。
https://huggingface.co/spaces/stabilityai/stable-diffusion

以下テキストを指定する。
なお、英語で指定する必要があり、一番初めにその対象物、カンマ区切りで説明を追加していくと良さそう。
公園でワドルディと遊んでいるカービィ
Kirby playing with Waddle Dee in the park
2分~3分ほどで画像が生成される。

それっぽさは出ているかな？！(右下のワドかわいい、左下！？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653035/5691b1e8-fc80-a7f3-dcc9-54c83fc34a1b.png)


あと以下でも「dreamstudio.ai」のベータ版が試せるみたい。
こっちは早い。
https://beta.dreamstudio.ai/dream

指定テキスト
A dream of a distant galaxy, by Caspar David Friedrich, matte painting trending on artstation HQ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653035/8428643a-21bb-a04f-f08d-c8755b184e0a.png)


Midjernyもそうだけどコツがありそうですねぇ。
大学数学・微分積分

# CEDEC:ゲームプログラマのための数学の歩き方 -

ラプラシアン：https://cedec.cesa.or.jp/2020/session/detail/s5e79a3e9c953a.html
デュアルクォータニオン編 https://cedec.cesa.or.jp/2021/session/detail/s60640d2e783a7.html
ベクトル解析：https://cedec.cesa.or.jp/2022/session/detail/92

# ヨビノリ
https://www.youtube.com/watch?v=t3JPms8Y1l4

# 微分

ε-δ論法(関数の連続性)【解析学】: https://www.youtube.com/watch?v=t3JPms8Y1l4
ロピタルの定理：https://www.youtube.com/watch?v=dRpnR2Q6GPI
偏微分：https://www.youtube.com/watch?v=UWFTIEIruyc
　→　２変数以上の微分
全微分：https://www.youtube.com/watch?v=ChoArVJnSjQ
　→　曲面の任意点に対する微分可能性の判別など

# 積分
重積分: https://www.youtube.com/watch?v=eqdsux1il54

累次積分（順番に積分する）
　ｙを固定してｘで微分　
　ｙで微分
置換積分　
　極座標への変換

***

# 線形代数
https://www.youtube.com/watch?v=svm8hlhF8PA

# 高校数学

# 置換積分
https://www.youtube.com/watch?v=v4qUClQ4zfI

---------
# QIITAでの数学記号
https://qiita.com/ttabata/items/92a4a72b042e6a2dbbad

数値積分
https://qiita.com/omu58n/items/55116842b21443627ad3
How to find out deleted file's commit log?

git logで–diff-filterと–summaryオプションを使用

$ git log --diff-filter=D --summary

commit 1826ae41824b57d60b2968917a43323e13d13c36
Author: foobar <test@example.com>
Date:   Mon Apr 29 01:09:24 2019 +0900

コミットメッセージ

 delete mode 100644 foo/bar.txt

表示量が多い場合は、スクロールして表示していくことになります。

デフォルトのエディタを使用しているならviの操作になっていると思うので、その場合は「/」を押して、更に削除したファイル名を入力して検索し、対象のコミットを見つけます。
オプションについて
–diff-filterオプション

次に示すのはgit logのマニュアルです。

    --diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]
    Select only files that are Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, ...) changed (T), are Unmerged (U), are Unknown (X), or
have had their pairing Broken (B). Any combination of the filter characters (including none) can be used. When * (All-or-none) is added to the combination, all paths are selected if there is any file
that matches other criteria in the comparison; if there is no file that matches other criteria, nothing is selected.

Also, these upper-case letters can be downcased to exclude. E.g.  
--diff-filter=ad excludes added and deleted paths.

Note that not all diffs can feature all types. For instance, diffs from the index to the working tree can never have Added entries (because the set of paths included in the diff is limited by what is in
the index). Similarly, copied and renamed entries cannot appear if detection for those types is disabled.

今回は削除したファイルを探すことが目的のため、D（Deleted）を使用しましたが、その他にA（Added）やM（Modified）などがあります。
–summaryオプション

summaryオプションの説明を下記に記載します。

このオプションを付けることで、ファイル名がgit logに表示されます。

    --summary
    Output a condensed summary of extended header information such as creations, renames and mode changes.
Summary of Git Command

##ローカルリポジトリを新規作成する

$ git init

.gitディレクトリが作成され、ローカルリポジトリも作成されます。

##変更をステージに追加する

$ git add <ファイル名 or ディレクトリ名>

ワークツリー全体の変更をステージに追加する場合は、以下のように「 . 」を指定します。

$ git add .

##変更をコミットする

$ git commit

ローカルリポジトリに変更をコミットします。
また、以下のように -vオプションを付けると、コミット時に変更内容を見ることができます。

$ git commit -v

また、-mオプションを使うと、gitのエディターを立ち上げずにコメントを入れることができます。

$ git commit -m "<メッセージ>"

#変更の確認

##現在の変更状況を確認する

$ git status

##変更の差分を確認する
git addする前の変更分を確認したいとき

$ git diff

git addした後の変更分を確認したいとき

$ git diff --staged

##変更履歴を確認する

$ git log

一行で表示したいとき↓

$ git log --oneline

ファイルの変更差分を表示したいとき↓

$ git log -p <ファイル名>

表示するコミット数を指定したい時↓

$ git log -n <コミット数>

例えば「　git log -n 5　」 とコマンドを打つと、5件分のコミットの変更履歴が表示されます

#リモート関連

##リモートリポジトリを新規追加する
GitHub等のリモートリポジトリを登録したいとき

$ git remote add origin <リモートリポジトリのURL(HTTPS)>

*注意：ssh key接続している時は以下
$ git remote set-url add origin git@****.com

##リモートリポジトリの確認
$ git remote

登録されているリモートリポジトリのURLも確認したいときは、-vオプションをつける↓

$ git remote -v

##リモート名を変更する

$ git remote rename <旧リモート名> <新リモート名>

##リモートを削除する

$ git remote rm <リモート名>

##リモートリポジトリにプッシュする

$ git push <リモート名> <ブランチ名>

コマンド例↓

$ git push origin master

##リモートリポジトリからプルする

$ git pull <リモート名> <ブランチ名>

git fetchとgit mergeを一度に行っている。
コマンド例↓

$ git pull origin main
*注意：masterではなく今はmainに変更されている。

##リモートリポジトリからフェッチしてマージする
①まずリモートリポジトリからローカルリポジトリに情報を取得する(フェッチ)

$ git fetch <リモート名>

コマンド例↓

$ git fetch origin

②ローカルリポジトリに取得した情報を、ワークツリーに統合させる(マージ)

$ git merge <リモート名/ブランチ名>

コマンド例↓

$ git merge origin/master

#変更をなかったことにする

##ワークツリーのファイルを元の状態に戻す

ワークツリーの状態を、ステージの状態と同じにすることによって、
ファイルへの変更を取り消しています。

$ git restore <ファイル名 or ディレクトリ名>

ワークツリー全体の変更を取り消すときは、「 . 」を指定します。↓

$ git restore .

なお、「restore」の代わりに「checkout --」を使用することも可能です。

##ワークツリーから追跡対象外のファイル(Untracked file)を削除する

git restoreコマンドでは、新規に作成されたファイルを削除できないため、git cleanコマンドを使用します。↓

$ git clean -f <ファイル名>

ファイル名を指定しなかった場合は、カレントディレクトリ内の追跡対象外ファイル全てが削除されます。
また、追跡対象外ファイルを確認したいときは、-fオプションの代わりに-nオプションを使用します。↓

$ git clean -n

##ステージのファイルを元の状態に戻す

git addでステージした変更を取り消すとき↓

    $ git restore --staged <ファイル名 or ディレクトリ名>

ステージ全体の変更を取り消すときは、「 . 」を指定します。↓

    $ git restore --staged .

なお、「restore --staged」の代わりに「git reset HEAD」を使用することも可能です。

##直前のコミットをやり直すとき

$ git commit --amend

現在のステージの状態を元に、コミットを上書きすることでコミットを修正する
※リモートリポジトリにプッシュした後のコミットはやり直しできないので注意が必要

#その他

##ファイルの削除を記録する

$ git rm <ファイル名>

git rmコマンドを使うことによって、指定したファイルが
ローカルリポジトリとワークツリーの両方から削除されます。
また、ディレクトリを削除するときは、-rオプションを付けてディレクトリ名を指定します。↓

$ git rm -r <ディレクトリ名>

なお、ファイルをローカルリポジトリからのみ削除し、ワークツリーには残しておきたい場合は
コマンドに --cachedをつけます。

$ git rm --cached <ファイル名>
Macに環境変数をターミナルで登録する（使用shellはzsh）

■使用しているshell
`ehco $SHELL`
→ /bin/zsh

■結論
`export 環境変数名="登録したい変数内容"`
で環境変数を登録できる。

■環境変数を永続保存したい場合
上記だとターミナル再起動すると環境変数は残っていない状況になる。
永続的に環境変数を保存したい場合は以下を行う。
`vi ~/.zshrc` #以下export〜を書き込み、保存、閉じる。
`export 環境変数名="登録したい変数内容"` #環境変数登録
`source ~/.zshrc` #.zshrcを読み込み、環境変数反映

.zshrcはzshにてLogin時に毎回読み込まれるファイル。
よってこれにexportコマンドで登録する環境変数の内容を書き込めば、
ターミナル再起動の都度、環境変数がexportされるため、環境変数が使えるようになる。

例）登録した環境変数（ディレクトリ）にcdで移動してみる。
`export MyFolder="/Users/neko/Desktop/MyFolder"`
`cd $MyFolder` #途中まで入力したらtabで変数名保管可能。
`pwd`
→ /Users/neko/Desktop/MyFolder

環境変数を永続保存する場合は
`vi ~/.zshrc`
![note.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301926/ad55f0e2-9a47-9703-a8be-4617bcca1029.png)
`source ~/.zshrc`
`cd $MyFolder`
`pwd`
→ /Users/neko/Desktop/MyFolder

〜余談
envコマンドで登録されている環境変数を一覧で確認できる。（printenvでもいいけれど）
以上です！
【JavaScript】TABキーによる要素のフォーカス送りをグループ内でループさせる

HTMLタグのtabindex属性が同じ値同士の要素はTABキーによるフォーカス送りが該当要素内で順に行われるので、グループ化したい要素にそれぞれ同じ値のtabindexを振り、それぞれのグループ内での先頭または終端の要素にフォーカスが当たっている際にTABキーまたはSHIFT+TABキーが押下された際には逆側の末端の要素にフォーカスを移動させることで、グループ内でフォーカス移動がループするようにしています。

----

#### [動作デモ](https://akebi.jp/temp/tabIndexGroup.html)
マウスポインタで適当な要素を選択したあとは、その要素が属するグループ内でTABキーまたはSHIFT+TABキーによるフォーカス移動がループします。

```sample.html
<!DOCTYPE html>
<html lang='en'>
  <head>
    <meta charset='utf-8'>
    <title>tabIndexGroup</title>
    <style>
      input[type=text] {
        width: 80px;
      }
    </style>
  </head>
  <body>
    <input type='text' class='group1' placeholder='A'>
    <input type='text' class='group1' placeholder='A'>
    <input type='text' class='group1' placeholder='A'>
    <input type='checkbox' class='group1' placeholder='A'>
    <button class='group1'>A</button><br><br>

    <input type='text' class='group2' placeholder='B'>
    <input type='text' class='group2' placeholder='B'>
    <input type='text' class='group2' placeholder='B'>
    <input type='checkbox' class='group2' placeholder='B'>
    <button class='group2'>B</button><br><br>

    <input type='text' class='group3' placeholder='C'>
    <input type='text' class='group3' placeholder='C'>&emsp;
    <input type='text' class='group4' placeholder='D'>
    <input type='text' class='group4' placeholder='D'><br>

    <input type='text' class='group3' placeholder='C'>
    <input type='text' class='group3' placeholder='C'>&emsp;
    <input type='text' class='group4' placeholder='D'>
    <input type='text' class='group4' placeholder='D'>

    <script>
    'use strict';

    const setTabIndex = cssSelector => {
      const targetElements = document.querySelectorAll(cssSelector);
      const lastIndex = targetElements.length - 1;
      const newTabIndex = Math.max(...[...document.querySelectorAll('*')].map(e => e.tabIndex)) + 1;
      targetElements.forEach(e => e.tabIndex = newTabIndex);

      document.addEventListener('keydown', e => {
        if(e.key !== 'Tab') return;
        if(e.target === targetElements[e.shiftKey ? 0 : lastIndex]) {
          e.preventDefault();
          targetElements[e.shiftKey ? lastIndex : 0].focus();
        }
      });
    };

    setTabIndex('.group1');
    setTabIndex('.group2');
    setTabIndex('.group3');
    setTabIndex('.group4');
    </script>
  </body>
</html>
```

----

MDNによると、tabindexの値に0より大きな値を使用することは以下の理由から避けるべきである旨の説明があるので、乱用はしないほうが良いかもしれません。

[tabindex | MDN](https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/tabindex#sect2)

> tabindex の値に 0 よりも大きな値を使用することは避けてください。そうすると、支援技術に頼っている人がページコンテンツを移動したり操作したりすることが難しくなります。代わりに、論理的な順序で要素を並べて文書を書いてください。

----
Python,Ruby,PHP,Java,JavaScript,Perlの繰り返し構文の比較 | プログラミング言語比較

<a href="https://qiita.com/yuki_kimoto/items/f9c2454e7f9130ddb003">Qiita > プログラミング言語の比較</a>

プログラミング言語Python,Ruby,PHP,Java,JavaScript,Perlの繰り返し構文の比較

# Python

https://qiita.com/atsui-ocha/items/5b8e4f973b36e78fdaf1

# Ruby

https://qiita.com/beanzou/items/6231d3d0a926765ddbb4

# PHP

https://qiita.com/rana_kualu/items/0abd2b6f69527b0b4b92

# Java

https://qiita.com/morioheisei/items/e686e33b60c6a60e87f0

# JavaScript

https://qiita.com/tetsuyakojima/items/fd63f91a4e34d6bad28b

# Perl

https://perlzemi.com/blog/20170521149524.html
【Rails】ページネーション「kaminari」と「bootstrap」を使用してカスタマイズ！

# はじめに
kaminariというGemには、BootstrapなどのCSSフレームワークのテンプレートファイルが用意されています。
CSSフレームワークのクラスを手動で付与しなくても、専用コマンドを実行するだけで簡単にテンプレートファイルを実装できます。

※Rails6を使用しています。
※bootstrap導入済み


# 完成イメージ
![pagenation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730527/8de427a8-6638-ca5a-d627-2ea5a4789e5f.png)

## Getting Started
#### ①Kaminariをインストールする
ページネーション機能の実装には、gemの「kaminari」を使う。
```:Gemfile
:
:

gem 'kaminari','~> 1.2.1'

```
#### ②bundle installする
```:terminal
$ bundle install
```
#### ③kaminariの設定ファイルを作成する
```:terminal
$ rails g kaminari:config
```
#### ④bootstrapのテンプレートを作成します
```:terminal
$ rails g kaminari:views bootstrap4
```

##### 下準備が完了！

次に、表示させたいviewとcontrollerに記述をしていきます。
※変数名は、変更お願いします。


## controllerへの記述
##### 変更前
```:notes_controller.rb
  def index
    @notes = Note.all
  end
```
##### 変更後
indexアクションの中では、notesテーブル内の全データが取得されていました。
これを、1ページ分の決められた数のデータだけを、新しい順に取得するように変更しています。
pageメソッドは、kaminariをインストールしたことで使用可能になったメソッドです。

```notes_controller.rb
  def index
    @notes = Note.page(params[:page]).per(10)  
  end
```


## Viewへの記述
表示させたい場所に、以下を記述する。
```notes/index.html
<% @notes.each do |note| %>

:
:

<% end %>
<%= paginate @notes %>　#ここへ記述
```
③で作成したkaminariの設定ファイルを使用するため、一番上のコメントアウト外す。
```:config/initializers/kaminari_config.rb
# frozen_string_literal: true

Kaminari.configure do |config|
    config.default_per_page = 5
  # config.max_per_page = nil
  # config.window = 4
  # config.outer_window = 0
  # config.left = 0
  # config.right = 0
  # config.page_method_name = :page
  # config.param_name = :page
  # config.max_pages = nil
  # config.params_on_first_page = false
end
```
1ページの表示件数は、デフォルトは25件ですが、今回は5件に設定します。
変更する事によって、ページネーションを使用したい部分が全て5件超過する事で起動します。
しかし今回の場合、controllerで、per(10)を指定しているため、こちらが優先されて
10件超過すれば、ページネーションが起動します。

# 追加
### defaultとmaxを理解しょう
defaultは、controllerに直接書いている記述が優先されます。

```
 config.default_per_page = 5
```
maxは、最大値が今回の場合8件に指定しているので、controllerで10件指定していても、
8件取得した時点でページネーションが起動します。
```
config.max_per_page = 8
```
# まとめ
簡単に整ったページネーションが完成することができました。
さまざまな、テンプレートファイルが用意されているためお気に入りの一つを選び実装できます。
Perlプログラミングの変数のワンポイント解説【Perlゼミ動画講義】

Perlの変数をワンポイント解説しました。

my - レキシカル変数
our - パッケージ変数
local - ローカル変数
変数のスコープ

けっきょく何を使えばいいの?

https://www.youtube.com/watch?v=7-K5OQAjmwU
僕が考えた最強の作業手順書

某所で見かけたシステム運用作業手順書の記事に、「作業直前に作業手順書の変更はしない」「手順書に無い作業をしない」といった事が書かれていました。

いや、それはあくまで心掛けの話であって、それも大事だけど、**そもそも作業手順書はどうあるべきか**という話が抜けおちているのではないか？それは世間ではあまり明文化されていないのではないか？と思いました。

不遜ながら、私が思う作業手順書のあり方を書いてみます。

# 1. 存在している

まさか、本番作業を勘とノリでやっちゃうなんて。まさかね…

# 2. 保存されている

Githubでも、Google Driveでも、Notionでも、Wikiでもいいですが、作業手順書は保管されていますね？えっ？保存していなかったら、同じような作業をもう１回することになったらどうなるんですか？障害が起きて、デプロイ手順に問題がなかったか調査したい時にどうするんですか？

なお、保存するなら、特別な理由が無い限り、Opsチームの他メンバーや開発エンジニアやQAエンジニアも閲覧可能にしましょう。改善活動のネタにつながるかもしれません。いや、つながらないかもしれないが、閲覧可能にすること自体はタダです。

生のパスワードが書かれているって？それは別の問題…

# 3. レビューされている

自分が書いた手順書に間違いが無いか、見落とした手順が無いか、心配になりませんか？心配になりますよね？「全く心配にならない私は完全無欠だ！」ですって？

ベテランでもミスをゼロにはできません。多数の目玉を通すことでミスを防ぎます。

また、レビューでの指摘を通じてチーム内でのノウハウが共有されます。レビューを受ける側も「自分用のメモ」ではなく「他人にも読める文章」を書かなければならないため、明快な文章を書く能力が鍛えられます。

# 4. テストされている

本番環境を変更する前に、本番同様の「ステージング環境」でも同じ作業を実施します。

なおここでいう「ステージング環境」は社内に複数設けることもできます。例えば、Dev向けの環境とOps向けの環境を別に用意したり、Ops向けの環境を複数（人数分）用意することも考えられます。

また、例えば本番がサーバー10台の構成だからといって、ステージング環境も10台構成にしなければならないとは限りません。「複数台のサーバーを同時に操作すること」をテストしたいだけなら、2・3台でも十分かもしれません。

# 5. 出力は全て記録する

コマンドの出力はすべて記録します。これも後で調査できるようにするためです。そして、手順書では出力＆記録の方法も決めておかなければなりません。

ターミナルに表示された内容をいちいちコピーするのは煩雑です。例えばiTerm2にはログを自動で保存する機能があります。

また、出力が膨大になって記録しきれない場合は、そもそも出力の仕方が悪いのかもしれません。そんな記録できないほどの出力を人間が目で見て確認できるはずがありません。うまくフィルタリングしましょう。

# 6. コピペで実行できる

システム運用作業は速さと正確さが命です。

判断するということは、判断に要するタイムロスが発生してしまうということです。また、判断の質はその人の知識や経験に左右されますから、作業者によっては誤った判断をしてしまうおそれがあります。

作業に必要な情報は全て書きましょう。URLを書きましょう。監視デーモンを一時停止するコマンドも書きましょう。最後に作業端末からログオフする指示も書きましょう。

なお、作業内容によっては実行するまで不確定な部分があることもありますが、想定ケースと対処方法を一覧表にしておきましょう。

# 7. 結果を確認するステップが設けられている

「判断させない」に関連していますが、確認を作業者の自主性に任せるのではなく、確認するステップを設けます。

一般的には、ログインした時にサーバーのIPアドレスを確認したり、デプロイ後にログの出力を確認したりします。

このとき、例えば「ログが正しいこと」ではなく、具体的に

- そのログを取得する方法（CLIコマンド）
- 期待されるログの内容
- 特に問題が起きそうな部分・今回の変更の影響を受ける部分

などを示します。確認を目視だけではなく、プログラムによって自動的に行えればなお良いでしょう。

# 8. 問題発生時の応急処置が指示されている

ファイルを消してしまう等の誤操作をした時や、サービスに異常が起きたときなどの、応急処置を指示します。

- 右手を高々と上げ、「メーデー！」と３回叫ぶ
- サービスをメンテナンスモードに切り替える
- 前のバージョンをデプロイする

なお、この手順は「問題を解決する」というよりは「システムを安定した状態にする」ことや「トラブルを拡大しないこと」を重視するべきです。

また、こういった応急処置はある程度定型化できるので、個別の手順書にいちいち書く必要は無いかもしれませんが、いざという時アクセスできるようURLを書いておくべきです。手順の最初に「リカバリ手順を復習する」というステップを設けても良いかもしれません。

# 9. 自動化されている

「誰でも実行できる明確な手順書」は次第に「実行可能な手順書」に近づいていきます。

terraformやJenkinsなどのツールを導入するのはそれなりのコストがかかりますが、一度使い出せばすぐに元を取れるはずです。

# むすび

名著 SQLアンチパターンに「外交特権」という、DBやSQLを職人芸扱いしてバージョン管理やテストをしないアンチパターンが紹介されていました。

システム運用も職人芸扱いされるきらいがあります。「作業直前に作業手順書の変更はしない」のような心掛けに、職人芸で満足してしまう風潮を感じ取り、深夜テンションでついカッとなって書いてしまいました。

# むすび（追記）

しばらくして読み返したら、結局のところこの文章で言いたかったのは「インフラエンジニアにとっても『言語化する能力』は重要だ」ということだと思いました。

職人的勘だけでは、どこかで天井にぶつかります。
作業内容を文章に書き出すことは、見落としを客観的に検証したり、後輩を教育したり、自動化したりするといった、新たな次元に進む足がかりになります。
Dockerを使って簡単にサーバーを立てる

nginxを使う例

```
docker run --rm -p 80:80 nginx  
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2458996/fc9fe36e-8aa8-78b2-b659-39faf2849399.png)


apatchを使う例

```
docker run --rm -p 80:80 httpd
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2458996/82355d4f-8a06-3dde-a6f6-3808d39b346b.png)
Linux nmcliコマンドについて（自分用メモ

●NetworkManager
動的にネットワークを管理する仕組み。
システムで検出されたネットワークデバイスは自動でNetworkManagerによって管理され、DHCPサーバが有効な環境であればDHCPによって動的なIPアドレスが割り当てられる。また、特定のインタフェースをNetworkManagerで管理しないように設定することもできる。


●nmcliコマンド
NetworkManagerを管理するためのコマンドラインインタフェース（CLI）

nmcli オブジェクト　[コマンド]

・general
status NetworkManagerの状態を表示
hostname [ホスト名]　ホスト名を表示・指定したホスト名に変更

・networking 
on|off ネットワークの有効化|無効化
conectivity ネットワークの接続状態を表示

・radio
wifi Wi-Fiの状態を表示
wifi on|off Wi-Fi接続の有効化|無効化

・connection
show 接続状況を表示
modify ID パラメータ　指定した接続IDの設定ファイルの、指定したパラメータを書き変える。パラメータの反映には接続のconnection up操作が必要。
up|down ID 接続の有効化|無効化

・divice
status デバイスの状態を表示
show インターフェイス名　指定したデバイスの詳細情報を表示
connect|disconnect　インターフェイス名　指定したデバイスを接続|切断
modify インターフェイス名　パラメータ　指定したインターフェイスのパラメータを即時変更する。設定ファイルの書き換えは行われない。
delete インターフェイス名　ソフトウェアデバイス（ブリッジ）などの削除
wifi list WiーFiアクセスポイントの表示
wifi connect SSID Wi-Fiに接続するデバイスを作成、有効化
wifi rescan Wi-Fiアクセスポイントの再検索
特定のphpunitが上手く動かない時。requireでなくrequire_onceを。

# はじめに

正直タイトルが適しているのか分かりません。:bow:
あとタイトルが答えなのでタイトル見て『あ！』みたいに思わなければこの記事は意図したものではないかと思います:bow:
あと自分はcakePHP使ってておきました。関係ないとは思いますが念のためここに記述しておきます。

# 何が起こった？

今までは以下両方とも問題なく動いていていたのに、、、、

```
$ vendor/bin/phpunit tests/TestCase/Controller/AAAControllerTest.php --group security --filter 'XSS'  --testdox

$ vendor/bin/phpunit --testsuite ALL_Test --testdox
```

いつからか以下のコマンド叩いてもエラーもでずテストもでずみたいになってしまいました、、、

```
$ vendor/bin/phpunit --testsuite ALL_Test --testdox
```

以下のも上手くいかなくなってしまった、、、

```
$ vendor/bin/phpunit --group security --testdox
```

# 原因は何？？？

自分でテストに使う独自で作ったメソッドを使うのに色々なファイルに以下を記載していたから、、、
ファイル指定の実行で上手く行っていたのは一回しか呼ばないので問題なかったが他ファイルにも記載していると、、
エラーが、、、でないけど上手くいかないみたいになりました。言葉たらずすみません。

```
require __DIR__ . '/Common/CommonProvider.php';
```

# どうすればいい

```
require __DIR__ . '/Common/CommonProvider.php';
```

を

```
require_once __DIR__ . '/Common/CommonProvider.php';
```

にすれば上手くいきました。(*´ω｀*)


# 最後に
エラーといったエラーが出ないで何も起こらないみたいになって最初戸惑いました、、(✿´ ꒳ ` 。)
PowerShellとGoogleFormとタスクスケジューラでパソコンの起動時間を記録する仕掛けを作ってみた

ふと、自分は一日にどれくらいコンピュータの勉強をしているのだろうか？と疑問に思い、勉強用に使ってるWindows PCの起動時間を記録することにしました。

そういうフリーウェアは既にあるような気がしましたが、簡単そうなので自作してみました。

なおPowerShellは今回始めて触ります。

# Google Form を作る

![作ったフォーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179154/0096fc3e-c4cd-5f66-5c4f-dc127fa7b874.png)

フォームには以下の項目を設けました。

- Time: 日付と時刻
- CsName: PCの名前
- OsName: OS名
- OsVersion: OSのバージョン

Timeは「日付」タイプを選択した後、「時刻を含める」で日付と時刻を記録できます。

さて、このフォームにPowerShellから回答をPostすることになるのですが、フォームの項目のIDは"Time" のようなリーダブルなものではなく、単純な"18764741" みたいなランダムな数値は割り振られます。

このIDを調べるには、そして「送信」ボタン横のメニューの**事前入力したURLを取得**からサンプル回答を作ります。

![事前入力したURLを取得.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179154/370452cf-cd0a-7d2d-aebe-13499bc1df37.png)

取得したURLには、フォームのIDと、各項目のIDが含まれます。

```
https://docs.google.com/forms/d/e/【FormのID】/viewform?usp=pp_url&entry.18764741=2022-08-27+12:34&entry.687203154=AAA&entry.1024557962=BBB&entry.257024779=CCC
```

# PowerShellスクリプト

単純に現在時刻とPC情報をハッシュテーブルにして `Invoke-WebRequest` でPOSTします。

```powershell
# ComputerLog.ps1

$formId = "フォームのID"

function isError($response) {
    $s = $response.StatusCode
    return ($s -lt 200) -or (300 -ge $s)
}

$url = "https://docs.google.com/forms/d/e/$formId/formResponse"
    
$now = Get-Date
$info = Get-ComputerInfo -Property @( "OsName", "OsVersion", "CsName")

$params = @{
    "usp"="pp_url"
    "entry.18764741"=$now.toString("yyyy-MM-dd+HH:mm:ss")
    "entry.687203154"=$info.CsName
    "entry.1024557962"=$info.OsName
    "entry.257024779"=$info.OsVersion
    "submit"="Submit"
}

$res = Invoke-WebRequest $url -Method 'POST' -Body $params
if (isError($res)) {
    exit 1
}
exit 0
```

# タスクスケジューラ

初めは「Postして10分間Sleepして、またPostする」的なデーモンをPowerShellで実装しようしたのですが、考えてみたらWindowsには定期実行の仕組みが既にありましたね。

そう、古き良き**タスクスケジューラ**です。

「タスクの作成」でタスクを作ります。

「全般」で「ユーザーがログオンしているかどうかに関わらず実行する」にチェックを入れます。これにより、実行時にコマンドプロンプトが全く表示されなります。

「トリガー」で新規作成します

- タスクの開始 = ログオン時
- 繰り返し間隔 = 10分間

「操作」で新規作成します

- 操作 = プログラムの開始
- プログラム／スクリプト = "C:\Program Files\PowerShell\7\pwsh.exe"
- 引数の追加 = -c "C:\Path\To\ComputerLog.ps1"

ここで`pwsh.exe`にもWindowを非表示にするオプション（`-WindowStyle Hidden`）があるのですが、「ユーザーがログオンしているかどうかに関わらず実行する」を指定済なので不要です。逆に`-WindowStyle Hidden`を指定しただけだと、コマンド実行時にコマンドプロンプトが一瞬だけ表示されてしまいます。

# 実行

PCにログインし直します。ログが送信されます。

なお、タスクスケジューラ上からスクリプトを実行することもできます（画像に残っている半端な時刻はそれ）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179154/2a8b3659-ce02-e5e6-5b55-02e74a496743.png)

なお、回答ごとにタイムスタンプが記録されるので、実はTimeフィールドは不要でした。
また、時刻は分までしか受け付けないので秒は不要でした。


# 感想

久しぶりにWindowsでプログラミングしてPowerShellが高機能なことに驚きました。タスクスケジューラも世間では不評のようですが、UIデザインが時代がかっているのはともかく、機能的には必要十分で使いやすいと思ったのですがいかがでしょう？
A problem tracing experience of application support

# Symptom
A user reported that in the saved report of a application, all fields related to time are changed, changed to 1 hour earlier to original value. This happened recently and there was no problem in the past.

Simple to say, the application is build by Spring Boot, and details are:
- Java 8
- Spring MCV
- Spring Data JPA
- JPA (By Hibernate)
- MySQL

# Investigation direction: Time zone
In the UK, time zone will be changed 2 times per year. And there is one hour difference between two time zones. So first of all I looked into the points related to time zone.

When the **default time zone** of MySQL server is the same as the time zone of Java application (British summer time when time of writing), time input is correctly saved into the database. But when the default time zone of MySQL server is set to one hour earlier (Greenwich Mean Time), time saved to the database is one hour earlier than inputed value.

# To find out which part is out of expectation
And then looked into MySQL. The table column stored time is defined as **TIME**, according to the document, MySQL will not alter the value before stored. And after testing, the value is correctly stored by running insert SQL statements without using **Prepared Statements**.

It is time to move back to the application. Following data process path

1. Entity instance created and binded with values of HTTP request in the controller. The time fields of the entity are LocalTime class, it is not affected by the time zone setting of the application. It is easy to check, just dump the values of the entity created to the logger. As expected, the value correctly passed.
1. Entity persisted in the database by generating SQL commands by JPA provider. By setting following values in *application.properties*.

```
logging.level.org.hibernate.SQL=debug
logging.level.org.hibernate.type.descriptor.sql=trace
```

The generated SQL and parameter binding can be viewed. And the value correctly passed to the MySQL JDBC driver.

# Unexpected behavior of MySQL JDBC driver
When I traced the program flow in MySQL JDBC driver, finally I found out where the value was altered (in *com.mysql.cj.ClientPreparedQueryBindings#setTime(int, java.sql.Time, java.util.Calendar)*). [Here](https://qiita.com/saladlam/items/cd6f83851d43874282a4) is the detail.
【Python】DFSで無向グラフの閉路検出

**DFS**（深さ優先探索）で連結な単純無向グラフの閉路を検出する方法メモ

```python
# 頂点数:n
# edge[i]:頂点iと辺で結ばれる頂点の集合

# 遷移元の頂点
parent=[-1]*n
# 閉路に含まれる辺の集合
loop =set()
# 既に探索した頂点か
come=[False]*n

def dfs(x,last=-1):
    if last!=-1:
        parent[x]=last
    come[x]=True
    for i in edge[x]:
        if i ==last:continue
        if come[i]:
            now=x
            loop.add((now,i))
            loop.add((i,now))
            while now!=i:
                loop.add((now,parent[now]))
                loop.add((parent[now],now))
                now=parent[now]
            return True
        else:
            if dfs(i,x):
                return True
    return False

dfs(0)
```

# 参考
https://www.youtube.com/watch?v=aWDj1_isMWE
AtCoder160（ABC）の B問題を解いた（PHP）

問題文の要点：
高橋君が持っている "500 円硬貨 1 枚につき 1000"、5 円硬貨 1 枚につき 5 の 嬉しさ を得ます。
高橋君の嬉しさが最大になるように両替したとき、高橋君の嬉しさはいくらになりますか？

```PHP
<?php
$X = trim(fgets(STDIN));
$fiveHundredCount = 0; //500円玉の枚数
$fiveCount = 0; //5円玉の枚数
$num = $X; //一時的に計算する場所
$ans = 0; //解答
if ($X >= 500) {
    $fiveHundredCount = floor($num / 500); //500円玉の枚数を求める
    $num = $num - (500 * $fiveHundredCount);/*標準入力の数値から500円の枚数分を引き、
                                              残りの金額を出す(500円玉を最大枚数分使う)。*/
    $fiveCount = floor($num / 5); //5円玉の枚数を求める
    $ans = ($fiveHundredCount * 1000) + ($fiveCount * 5); // 嬉しさを両替する
    echo $ans;
} elseif ($X == 0) {
    echo 0;
} else {
    $fiveCount = floor($num / 5); //5円玉の枚数を求める
    $ans = $fiveCount * 5; //嬉しさを両替する。
    echo $ans;
}

```
【ここから始めよう！】０から分かるe-learningのモバイルデザイン

# はじめに
[こちらの記事](https://www.elucidat.com/blog/responsive-elearning-design-examples/) を参考にしてモバイルデザインを作る際の重要ポイントを(今更)まとめていく。

# ユーザの前提
「PCで見栄えがいいのは当たり前。どのデバイスで見ても当たり前のように綺麗な見た目」。これはフロントエンドの人間からしたら実に地獄のような話だが**ユーザの前提**である。どんなにコンテンツが良くてもスマホで見れないんじゃ仕方ないのだ。

さて、どのようなデザインがいいのかを8つ学ぼう。

# なぜモバイルフレンドリーなデザインが大切か
1\. モバイルでの学習がより増えていること
2\. 学習コースは全ユーザが利用できないといけない
3\. ユーザはデバイスによらず最高の学習経験を求める

また、レスポンシブデザインというのは他の様々なデバイスに対して応用力が強いのも特徴です。

# 5個のチップ
**1\. スクロールをちゃんと使おう：**
「一つの話題を中心にしたスクロールページ」なんだかんだこれは効果的なデザインなのだ。ほとんどすべての記事はこのデザインなのだから参考にしよう。

**2\. 「最小限の努力での学習」を大切に**
ユーザは情報を最速で手にしたいと考えている。これをまずは肝に銘じよう。分野ごとに分けるなどの（当たり前のような）デザインも最高の学習体験への一歩である。

**3\. クリック数を減らそう**
クリックして進んでいくタイプのコースは最悪だ。不要な画面やクリックは削除してしまおう。

**4\. 少ないほど良い**
一つの学習コンテンツをあまりにも重く作りすぎるな。きれいで読みやすく、親指に優しいものにしよう。

**5\. スキャンを簡単にできるようにしよう**
スクロールの快適さはもちろんのこと、重要なところを目立たせたりすることも大切だ。番号付きのポイントやアイコンも使っていこう。

より多くのチップスについては[こちら](https://www.elucidat.com/blog/mobile-learning-design-strategies/)から

# レスポンシブe-learninデザインに向けた8個の具体例
### 1. 美しく見やすいスクロールページ
かつて、スクロールというのはe-learningと相性が悪いとされていたが、今では最高の学習体験の鍵になるとされている。

[例はこちら] (https://www.elucidat.com/showcase/#interactive-storytelling)
めちゃめちゃ長い行がないのもポイントだ

### 2. 動画で解説しちゃう
・メニューをデスクトップでは画像の行として、モバイルでは積み上げらた列のようにしよう。
・ビデオの後に選択式の問題演習があるのは最高だ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481370/b1378db3-cfee-ca58-337d-ae3be137fe14.png)

動画+解説もよいかもしれないね

[例はこちら](https://www.elucidat.com/showcase/#a-support-net)

### 3.見やすさ向上

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481370/2208577f-829f-a0f8-ca03-454f70266e96.png)

こういったわかりやすいデザインは**ユーザの時間節約**になって良い。数回タップするだけで見たいコンテンツを知れるのは重要だ。

### 4.問題を作る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481370/d08d0eff-9b8e-8a63-263a-f4b8e187c110.png)

問題ページを作るのも大切だ。どのデバイスでも動くようにしよう。
しかもいろいろなデザインの問題を作ろう

・ユーザの興味を維持し、何回も同じものを繰り返し見なくてよくなるようにモバイルフレンドリーなデザインで作っていこう
・問題ページは問題を目立たせるためにシングルページで構わない

### 5. ゲーミフィケーション要素を持たせよう
多くの人が手の中でゲームをする時代である。webサイトにもそれをもたせることをためらうな

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481370/eb9def1e-dba3-ea00-87e1-d4fe71ac1a44.png)

・サイトに本当にふさわしいか見極める必要があるが、ゲーミフィケーションの例として、タイマー、ポイント、レベル、バッジなどは有名なものだ

### 6. 「やるべきこと」を明確にさせよう
[このサイト](https://www.elucidat.com/showcase/#quick-onboarding)のように最終ゴールが見えていないユーザにむけて**道のりページ**みたいなものを作るのもよいだろう。シングルページはこれを作るのに最適だ。
C# 外部ライブラリを使わずログファイルをダウンロードフォルダに書き出す

引数に出力するパスを受け取って、ダウンロードフォルダにログファイルを書き出す。

```C#
using System;
using System.IO;
using System.Text;

namespace project.Share
{
    class Logger
    {
        string _path { get; set; }

        public Logger()
        {
            _path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) +  @"\Downloads\";
        }

        public void PrintLog(string[] strArray)
        {
            var infoString = new StringBuilder();
            foreach (var str in strArray)
            {
                infoString.Append(str);
                infoString.Append(Environment.NewLine);
            }

            string now = (DateTime.Now).ToString("yyyyMMddHHmmssff");
            File.AppendAllText(Path.Combine(_path,  now + ".log"), infoString.ToString());
        }
    }
}
```
Windows(WSL2)上にdoodのコンテナを作る

# 最初に結論
これをクローンしてコンテナの中に入ればおk

https://github.com/Mkamono/golang-dood-host-sample

# DooDとは
Docker outsite of Dockerの略です。Docker内部のコンテナからホストのDockerを操作する方法です。DinD(Docker in Docker)という方針もありますが今回はこちらで。
# どうしてそんなことを？
インターンで働いている企業の開発環境がMacです。Docker関連にMakeファイルが用意されており、Dockerコマンド、Goコマンド、Unix系コマンドが必要になったためです。
できるだけローカルの環境を汚さずに開発をしたかったため、Docker上に環境を置きたいと思ったのですが、環境構築の時点でGoのコマンドを使用しているため本来であればローカルにGoをインストールする必要がありました。
DooDを採用することで、ローカルのように扱えるGoのコンテナ、実際に運用しているコンテナの2つによって、擬似的に同じ環境を作ります。

# ディレクトリ構成
```txt:ディレクトリ構成
.
|-- .devcontainer
|   |-- devcontainer.json
|   `-- docker-compose.yml
|-- Dockerfile
|-- docker-compose.yaml
|-- go.mod
|-- main.go
`-- pkgs
    `-- pkg1.go
```
こんな感じになります。最小限のGoプログラムは書きたいと思ったので適当な構造を作りました。

# 内容解説
```Dockerfile:Dockerfile
FROM golang:1.19
#Debianが指定される
WORKDIR /go/src/work

RUN go install -v golang.org/x/tools/gopls@latest
RUN go install -v github.com/ramya-rao-a/go-outline@latest
RUN go install -v github.com/go-delve/delve/cmd/dlv@latest
RUN go install -v honnef.co/go/tools/cmd/staticcheck@latest
#Go周辺の便利機能インストール

RUN apt update
RUN apt install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
#Dockerインストール準備
#Dockerドキュメント https://matsuand.github.io/docs.docker.jp.onthefly/engine/install/debian/

RUN mkdir -p /etc/apt/keyrings
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
RUN echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

RUN apt update

RUN apt install docker-ce docker-ce-cli containerd.io -y
#本体インストール
RUN curl -SL https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
RUN chmod +x /usr/local/bin/docker-compose
#docker-composeのインストール、実行権限付与

```
Dockerfileでは公式イメージにDockerCLIをインストールしています。結構手順が多くハマったこともありましたがこれで落ち着きました。

```yaml:docker-compose.yaml
version: '3'
services:
  go_host:
    build: .
    container_name: "go_host"
    tty: true
    stdin_open: true
    command: /bin/bash
    #ホストのディレクトリをコンテナにマウント
    volumes:
      - .:/go/src/app
      - /var/run/docker.sock:/var/run/docker.sock
      # - ./env/.ssh:/root/.ssh
      # ssh でgitなどをしたい場合設定を置くと良い
```

`/var/run/docker.sock:/var/run/docker.sock`の部分でWSLに存在するDockerに。コンテナがアクセスできるようにしています。これによりDooDを実現しています。sshでgitなどもしたいのでssh用の設定もおいておくと良いです。また、composeのcommandにlocalでgit configを設定しておくとコンテナの中でだけ決まったアカウントを使える、みたいな環境になってくれてとても良いです。

# 結論
業務で使える環境が用意できた。この記事がWindowsプログラマーの助けになれば幸いです。
re.subを使って複数の空白文字を任意のセパレータ文字に変換

## 文字列の中の複数の空白文字（スペース）を、正規表現を使ってコンマ(,)に変換する

### ユースケース
+ コマンド結果を文字列として取り込み、それを加工して使用する
+ 例：ネットワークコマンドの実行結果など

```bash
~$ ss -tu
Netid      State      Recv-Q      Send-Q           Local Address:Port              Peer Address:Port       Process
tcp        ESTAB      0           0                    127.0.0.1:59976                127.0.0.1:39839
tcp        ESTAB      0           0                    127.0.0.1:59978                127.0.0.1:39839
tcp        ESTAB      0           0                    127.0.0.1:39839                127.0.0.1:59978
tcp        ESTAB      0           0                    127.0.0.1:39839                127.0.0.1:59976
```

+ Linuxのコマンドは上記のような表示結果が多いので、この空白をセパレータに変更しリスト化するとデータの再利用がしやすい

### コード

``` get_socket.py
import re
import subprocess


def get_socket():
    get_socket = subprocess.run(['ss', '-tu'],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
    cmd_result = get_socket.stdout.decode('utf-8')

    with open('/WorkSpace/Python/get_socket.txt', 'w') as f:
        f.write(cmd_result)

    socket_list = []

    with open('/WorkSpace/Python/get_socket.txt', 'r') as f:
        for read_line in f:
            txt_value0 = re.sub(r'\s+', ',', read_line)
            txt_value1 = txt_value0.split(',')
            socket_list.append(txt_value1)

    return socket_list

for list in get_socket():
    print(list)


if __name__ == ('__main__'):
    get_socket()

```
1. subprocess.runでssコマンドを実行する
2. コマンド結果をファイルに保存する（with open(file, 'w') as f: ) 
3. ファイルから文字列を読み込む（with open(file, 'r') as f: )
4. re.sub関数で複数空白文字 ( '\s+' ) を ( ',' ) コンマに変換する
5. 文字列をsplit関数でセパレートに ( ',' ) を指定しリストに変換する

### 実行結果

```bash
python get_socket.py
['Netid', 'State', 'Recv-Q', 'Send-Q', 'Local', 'Address:Port', 'Peer', 'Address:Port', 'Process', '']
['tcp', 'ESTAB', '0', '0', '127.0.0.1:59976', '127.0.0.1:39839', '']
['tcp', 'ESTAB', '0', '0', '127.0.0.1:59978', '127.0.0.1:39839', '']
['tcp', 'ESTAB', '0', '0', '127.0.0.1:39839', '127.0.0.1:59978', '']
['tcp', 'ESTAB', '0', '150', '127.0.0.1:39839', '127.0.0.1:59976', '']
```
【Angularアプリケーション開発 #11】guard

# はじめに
guardを実装しました。
以前、ログインの記事でもguardの実装を書いていましたが、動作がおかしかったので今回変更しました。

### guardの実装
authCheck()で非同期でhttp通信を行い、jsonデータを受け取っています。```{"cookieValidFlag":false}```
canActivate()では受け取ったjsonデータをboolean型に変換して返却しています。
cookieValidFlagがfalseであれば、loginページにリダイレクトして、cookieValidFlagがtrueであれば指定したページに遷移します。
mapはストリームから新しいストリームを生成するっぽいです。
イメージとしては、非同期で受け取ったデータの型を変換して新しいデータを生成することができるといった感じです。

```typescript:auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree ,Router} from '@angular/router';
import { Observable, pipe } from 'rxjs';
import { environment } from './../../environments/environment';
import { forkJoin, timer, of} from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { catchError, map, tap } from 'rxjs/operators'

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor(
    private router: Router,
    private http: HttpClient
  ) {}

  flg:boolean;
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    return this.authCheck().pipe(map(data =>{
      return data.cookieValidFlag
    }));
  }

  authCheck(): Observable<any> {
    return this.http.get<any>(environment.apiUrl + '/sessionload',{ withCredentials: true})
      .pipe(
        tap(data => console.log(data)),
        map(data =>{
          if(!data.cookieValidFlag){
            this.router.navigate(['login']);
          }
          return data;
        })
      );
  }

  private handleError<T>(operation = 'operation',result?: T) {
    return (error: any): Observable<T> => {
      console.error(error);
      return of(result as T);
    }
  }
  
}

```
SlackからDiscordへメッセージを移行させるDiscord botを作った

### 2022/08/29追記

dicordに送信できる最大文字数 < slackに送信できる最大文字数
みたいなので、slack側の文字数が多い場合には分割して送るようにしました。

---

先月に↓の記事を投稿したのですが、

https://qiita.com/yuki-n/items/25e73490d82a0ad3c3fd

我ながら使いづらいなと思ったのと、思ったよりも使っている人がいて、わかりずらそうだったので、なんかもっとイケてる感じにしたいなと思いました。

で、「これ最初からdiscord側のbotにしちゃえばいいんじゃね？」と思い立ち、そうすることにしました。

botは以下からサーバーに追加することができます。

https://discord.com/api/oauth2/authorize?client_id=1012738353231302667&permissions=2048&scope=bot

## 雑な使い方

例のごとく雑に使い方を書いておきます。

### slackのデータをエクスポートする

以下を参考に、エクスポートします。

https://slack.com/intl/ja-jp/help/articles/201658943-%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B

Slackのデータをエクスポートすると、何種類かファイルがエクスポートされます。

その中で必要になるのは、`users.json`ファイルと各種チャンネルのjsonファイルになります。

### リンクをクリックして、discordのサーバーにbotを追加する

https://discord.com/api/oauth2/authorize?client_id=1012738353231302667&permissions=2048&scope=bot

### 移行したいslackのチャンネルと同じ名前のチャンネルをdiscordに作る

同じじゃなくてもいいですが、合わせておいたほうがわかりやすいとは思います。

### 移行を行いたいチャンネルに移動し、botにメンションを当ててファイルをアップロードする

移行を行いたいチャンネルにて、以下のように、slackからエクスポートされたファイルの中で、`users.json`ファイルと移行するチャンネルのjsonファイルをアップロードします。

`@slack-message-transfer-bot`へのメンションをするのを忘れないようにしてください。

![スクリーンショット 2022-08-28 1.01.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177591/0dc72bee-1ceb-39e0-c368-3e8f3286eb5b.png)

しばらくすると徐々にメッセージがそのチャンネルに流れてくるはずです。

※多分ファイルのアップロードの上限とかあると思いますが、そこらへんよくわかってないです。もし無理っぽかったら小分けにしてアップロードしてください。
※zipファイルのままアップロードしてもうごかないです。

## 使用技術など

以下のリポジトリで開発しています。

https://github.com/yuki-noguchi/slack-message-transfer-bot

typescriptを導入したexpressで作っています。

botはrender.comで無料ホスティングしております。

https://render.com/

無料プランなので本当はすぐ寝ちゃうのですが、GASを使って定期的に叩き起こすようにしています。

## 補足など

Discordのbotは、100個のサーバーに導入されると検証を受けないといけなくなっちゃうらしいので、もし使い終わったらbotはサーバーからキックしていただいたほうが助かります。

また、できるだけ使えるようにメンテはするつもりですが、普通に後回しにしたりすると思うので使えなくてもあしからず。

あと、今回のは一応サーバーを経由するのですが、送られてきた記事の中身は見れるようになっていないのでご安心ください。
Githubの実装の通りでデプロイされています。

もしそこらへん気になる方は、[前回書いた記事](https://qiita.com/yuki-n/items/25e73490d82a0ad3c3fd)の方を参照していただいた方が良いかと思います。

あっちはローカルで全部完結するものを作っているので。

## 感想

render.comってherokuの後継みたいに言われてますが、本当にそんな感じで使い勝手いいですね！こういうbotとか作るのに最適だと思いました。
iptables とは

## 勉強前イメージ

アクセス制御するやつ？
firewalldと違う？

## 調査

### iptables とは

linuxに実装されているパケットフィルタリング型のfirewallの機能になります。
パケットフィルタリング型とは、入ってきたパケットのアクセス制御を行います。
CentOS7系まではiptablesがデフォルトでした。(CentOS7からfirewalldがデフォルトになります)
ipv4がiptablesで、ipv6がip6tablesになります。
netfilterというパケット処理のためのカーネルモジュールを操作するためのものになります。

基本的には、iptablesのコマンドを使用してルールなどを追加します。
設定は `/etc/sysconfig/iptables` に記載されています。
また、フィルタリングするのは入ってくるときだけではなく
以下の5つのタイミングで適応されます、これをチェインと言います。

- INPUT : 入ってくるとき
- OUTPUT : 出ていくとき
- FORWARD : 転送するとき
- PREROUTING : ルーティング前
- POSTROUTING : ルーティング後

また、パケットを以下の4つのテーブルに分けてそれぞれのタイミングで制御を行います。

- filterテーブル : パケットの通過や遮断を制御。殆どの設定がこのテーブルに書かれている。
- natテーブル : アドレス変換を担当。送信先などパケットの中身を書き換えるのに使う。
- mangleテーブル : TOSフィールドの値などの書き換えを行う。
- rawテーブル : 特殊な通信を制御するために使用される。

## 勉強後イメージ

iptablesとfirewalldって同じようなことしてたなーとはぼんやり思ってたけど
firewallって枠組みでは一緒だったか。
CentOS6まではiptablesでCentOS7からはfirewalld。
まるっきり同じって感じでもなさそう、なんかfirewalldのがダイナミックな感じが勝手にしてる。

## 参考

- [コピペから脱出！iptablesの仕組みを理解して環境に合わせた設定をしよう](https://oxynotes.com/?p=6361)
- [iptablesとは](https://www.designet.co.jp/faq/term/?id=aXB0YWJsZXM)
AlmaLinuxにPowerShellをインストールする

# はじめに
PowerShellのインストール方法は、直接ダウンロードする方法と、リポジトリを追加してパッケージインストールする方法があるようです。
今回は、パッケージインストールする方法を記載します。

# PowerShellのインストール
リポジトリを追加
```
# curl https://packages.microsoft.com/config/rhel/8/prod.repo | sudo tee /etc/yum.repos.d/microsoft.repo
```
インストール
```
# dnf install --assumeyes powershell
```

# 実行コマンド
```
# pwsh
PowerShell 7.2.6
Copyright (c) Microsoft Corporation.

https://aka.ms/powershell
Type 'help' to get help.

PS /root> 
```
`PS /root>`が表示されたら、PowerShellのコンソールを操作できる状態。

# 参考サイト
## サポートバージョン
https://docs.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-on-linux?view=powershell-7.2

## インストール方法
https://docs.microsoft.com/ja-jp/powershell/scripting/install/install-rhel?view=powershell-7.2
AtCoderログ：ABC266

## ABC266に参加しました
今回はA, B, Cの3完でした。
A: 1分
B: 30分（4WA...）
C: 12分

## 今回のレート変動
243→290（パフォーマンス：682）

## A問題-Middle Letter
真ん中を出すだけ。
```c++
int main() {
  string s;
  cin >> s;
  int n = s.length();
  cout << s[n / 2] << endl;
  return 0;
}
```

## B問題-Modulo Number
nが0以上かそれ未満かで場合分けして解答しました。

下記の場合分けを完全に見落として沼り4WA😭
```c++
if (tt == 0) cout << 0 << endl;
```

```c++
int main() {
  long long n;
  cin >> n;
  if (n >= 0) cout << n % t << endl;
  else {
    long long tt = abs(n) % t;
    if (tt == 0) cout << 0 << endl;
    else cout << t - tt << endl;
  }
  return 0;
}
```

## C問題-Convex Quadrilateral
外積の概念をしっかり把握してはいませんでしたが、ググって外積にたどり着く事は出来ました。

```c++
int main() {
  int x, y;
  vector<pair<int, int>> v;
  rep(i, 4) {
    cin >> x >> y;
    v.push_back(make_pair(x, y));
  }
  int s;
  rep(i, 4) {
    s = v[i % 4].first * v[(i + 1) % 4].second + v[(i + 1) % 4].first * v[(i + 2) % 4].second + v[(i + 2) % 4].first * v[i % 4].second - v[i % 4].second * v[(i + 1) % 4].first - v[(i + 1) % 4].second * v[(i + 2) % 4].first - v[(i + 2) % 4].second * v[i % 4].first;
    if (s < 0) {
      cout << "No" << endl;
      return 0;
    }
  }
  cout << "Yes" << endl;
  return 0;
}
```

## D問題-Snuke Panic (1D)
今週もD問題は解けませんでした。
dpをしそうな雰囲気を感じ取れはしましたが、実装にまでは至りませんでした。

## 感想
このペースでいけばあと2〜3回コンテストに参加すれば茶色には到達できそうなので引き続き精進していこうと思います。
STM32G031J6M6で節電の為に16MHzにする。(なぜかG031が売り切れ8/28)　(HAL)


x 過去ログを見よ!!

x 今後の予定としては、8ビット


目的
クロックのテスト


32MHz,16MHz,8MHz,4MHz

HALを使ってCPUクロックの変更



```c++



//HAL_16M_L_TI_KA_031_1

#include "mbed.h"


void s_clk16();
void gpio_int();


int main()
{
    s_clk16();
    gpio_int();

    //pc.baud(9600); //16mz
    //printf("%d Hz\r\n", SystemCoreClock);

    while(1) {

        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);

        HAL_Delay(500);

        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);

        HAL_Delay(500);

        //printf("%d Hz\r\n", SystemCoreClock);

    }//while

}//main


void s_clk16()
{

    //クロックの設定 RC発振16Mhz 逓倍回路オフ
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    //周辺装置へのクロックの供給
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                  |RCC_CLOCKTYPE_PCLK1;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);

}//s_clk16


void gpio_int()
{

    //gpioにクロックを供給
    __HAL_RCC_GPIOA_CLK_ENABLE();

    //gpioの設定　プルプッシュ スピードロー
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}//gpio_int



```
MySQL で 複数カラムデータ重複条件のレコードを、一つを残して不要なレコードを削除する。

# はじめに
標題のような状況に対応する。
ポイントは２つ。１つは、「複数カラムデータ重複条件のレコード」の抽出。もう一つは、（重複後のレコードの中で）一つを残して全部消す。
順に対応SQLのメモを示して、最後に組み合わせて削除するSQLまで書いておく。なお、途中で 1093 エラーが発生したのでその対処ほうも合わせて書いておく。

# 結論
```
DELETE FROM `content_tag_relation` WHERE `id` IN 
(SELECT AB FROM
 (SELECT min(`id`) AS AB
  FROM `content_tag_relation`
  GROUP BY `content_id`, `tag_id`
  HAVING count(`content_id`)>1 AND count(`tag_id`)>1)
AS CR)
```

# 複数カラムデータ重複条件のレコード抽出
`content_id`と`tag_id`と、`id`の３つカラムを持つ`content_tag_relation`というテーブルがある状況。
このテーブルで`id`は、Unique で重複がない。が、`content_id`も`tag_id`も同じ、つまり`id`以外は同じデータのレコードが複数存在している。もちろんテーブルの中には、重複のないレコードもある。
重複状況を調べたい、というときは、Group BY を使ったSELECT文。そこで、GROUP BYに , (カンマ）区切りで、２つのカラム名を指定してみる（SQLサンプル１）。

SQLサンプル１
```
SELECT `content_id`, count(*) FROM `content_tag_relation` GROUP BY `content_id`, `tag_id`
```

`id`ごとに、count(*)が１だったり２だったりするわけで・・・。今回は、重複がある、つまりカウントが１より大きいものを抽出なので、HAVING句を使って以下のサンプル２のようにする。

SQLサンプル２
```
SELECT `content_id`, count(*) FROM `content_tag_relation` GROUP BY `content_id`, `tag_id`
 HAVING count(`content_id`)>1 AND count(`tag_id`)>1
```

# レコードを一つ残して残りをけす。
今回の削除作業では、先のSELECT文を実行したら、重複レコードは、それぞれ２レコードずつ、3万件程度の重複があった。３以上の重複がカウントされたデータは、たまたま、なかった。よって、各重複レコード群のなかで、`id`（整数値）の数字の若いほうを削除する、という処理を行うことにした。
DELETEの対象に、先に抽出したレコードの'id'の若いほうを対象にさせるので、サンプル３のようなSQLにした。

SQLサンプル３
```
DELETE FROM `content_tag_relation` WHERE `id` IN 
(SELECT min(`id`) FROM `content_tag_relation` GROUP BY `content_id`, `tag_id` HAVING count(`content_id`)>1 AND count(`tag_id`)>1)  
ORDER BY `content_tag_relation`.`content_id` ASC
```

サブクエリの中で削除対象レコードの`id`を、重複レコードの min(`id`)でセレクトしたところに「若いほうを削除する」の意味を持たせた。そして、そのサブクエリを　IN　で参照する WHERE がミソ。このINを＝で書くとエラーになる。なぜなら、サブクエリの結果が複数レコードだから。
（参考）https://atmarkit.itmedia.co.jp/ait/articles/0708/29/news118.html

# MySQLでは同一テーブルのサブクエリからのDELETE文はエラー(1093)が発生する。
上述のSQLサンプル３をMySQLで実行すると MySQL 1093 エラーになる。このエラーは、DELETE文だけでなくUPDATE文でも発生するそうだ。このエラーについてググってみると、既存のデータの変更処理では、同一テーブルのサブクエリからの処理がエラーになる、ということらしい。

（参考）【MySQL】サブクエリを使ったUPDATEで「ERROR 1093」が出る場合の対処方法
https://nodoame.net/archives/8026
（参考）MySQLでは同一テーブルのサブクエリからのUPDATE文はエラーが発生する模様。
https://qiita.com/Kohei-Sato-1221/items/d1cbdc1d3affcd9c3a9e

そこで、サブクエリをSELECT文でラップ（と上述の（参考）先達は呼んでいる）すると処理できた。
それが、次のSQLサンプル４であり、冒頭の結論である。

SQLサンプル４
```
DELETE FROM `content_tag_relation` WHERE `id` IN 
(SELECT AB FROM (
 SELECT min(`id`) AS AB FROM `content_tag_relation`
 GROUP BY `content_id`, `tag_id` HAVING count(`content_id`)>1 AND count(`tag_id`)>1)
AS CR)
```

MySQLの仕様詳細までは言及しない。「まぁ、そういうもんだ」ということで覚えておこうと思う。
ラズパイZeroのセンサボードを作った(寸法などの参考として)

# はじめに
今回ラズパイZeroのセンサボードをJLCPCBで作ってもらいました。
ラズパイゼロのピンヘッダに上に丸々乗っけるシールド(？)のような形で作ったので、
寸法など、他にラズパイゼロのシールドを作りたい人の参考になれば

ちなみに基板はJLCPCBで200円＋送料で5枚作れるので、一枚当たり50円だった。クソ安い。

JLCPCBのサイトはこちら！
https://jlcpcb.com/

JLCPCBは新規ユーザー向けに54ドルのクーポンを配っており、今なら安く基板を作れるので是非！
https://jlcpcb.com/JPV

# 今回作ったもの

今回作成した物はCO2と温湿度センサを乗せたボード。

下の写真がJLCPCBで作ってもらった基板
相変わらず値段が安い割にクオリティが高い基板を作ってくれるので助かっています。
![IMG_9935.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867623/5f093c87-19b9-9964-3b74-e1a6bd8537aa.jpeg)
![IMG_9936.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867623/f7eb145b-fae7-2688-c4ad-b0251cf36a65.jpeg)



ハードウエアの完成品はこんな感じとなります。
![IMG_9923 - コピー (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867623/267c5a58-eb38-0b65-fb0f-3ee5337b036e.jpeg)



# 使用部材
・Raspberry Pi Zero
・センサ基板(今回JLCPCBで作った基板)
・[ＢＭＥ６８０使用　温湿度・気圧・ガスセンサモジュールキット(温湿度ガスセンサ)](https://akizukidenshi.com/catalog/g/gK-14469/)
・[ＣＯ２センサーモジュール　ＭＨ－Ｚ１９Ｃ](https://akizukidenshi.com/catalog/g/gM-16142/)
・[ピンソケット（メス）２×２０（４０Ｐ）](https://akizukidenshi.com/catalog/g/gC-00085/)
・[六角オネジ・メネジ　ＭＢ２６－１１ ×４](https://akizukidenshi.com/catalog/g/gP-11546/)
・[なべ小ねじ（＋）　Ｍ２．６×５　（１００個入）](https://akizukidenshi.com/catalog/g/gP-07324/)
・[六角ナット　Ｍ２．６×０．４５　（１０個入）](https://akizukidenshi.com/catalog/g/gP-14371/)

# 寸法やスペーサなどの参考

下に今回設計した基板の図面の写真を乗せるので、参考にどうぞ。
これと同じ基板外形、ピンヘッダの位置にすればとりあえずはラズパイに上手く乗せられないんだけど…って事案だけは回避できます。
今回、ネジはM2.6の物を使用するので四隅のネジ穴の径はΦ2.8としました。
基板の丸めRについてはR2.0としましたが、調べてみるとR3.0にしている人もいるのでその辺はお好きにどうぞ。

kicad6.0の基板角の丸め方については記事を書いているので参考になればどうぞ
[KiCad6.0で基板の角を丸くする方法](https://qiita.com/Konbanwa11/items/0a7cc354d5be178adca5)

![寸法.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867623/fe42eccf-74f7-2b79-6068-a2e7dec0e95e.png)

ラズパイ⇒基板の間に使ったスペーサ、ネジ、ナットはサンハヤトのRaspberry Pi専用スペーサー（MPS-M2611）の寸法を参考にしました。
・スペーサ⇒M2.6×11mm
・ネジ⇒M2.6×5mm
・ナット⇒M2.6 ×4個
この組み合わせで良いみたいです。
全部秋月電子で揃います。リンクは「使用部材」の項にリンクがあります。

# 最後に
JLCPCBへの注文の仕方や、KiCad6での製造データ作成方法は他の記事に書いているので参考にしてみて下さい。
[JLCPCBで基板を作ろう[KiCad6編]](https://qiita.com/Konbanwa11/items/4e1d14b7cdc2282063fb)
[JLCPCBで４層基板を作った](https://qiita.com/Konbanwa11/items/f44084b8963d0147c9f6)

この記事を読んだ方も是非注文してみて下さい。
JLCPCBは新規ユーザー向けに54ドルのクーポンを配っているので是非作ってみて下さい！
https://jlcpcb.com/JPV
GPU メモリ 8GB で StableDiffusion を動かす

# 概要
StableDiffusion のデフォルト設定がメモリが少ないマシンだと動かなかったためやったことをまとめました。

# 環境
```Dockerfile
FROM nvcr.io/nvidia/pytorch:22.04-py3

RUN pip install diffusers==0.2.4 transformers==4.21.2 ftfy==6.1.1
```
# やったこと
## モデルを半精度化する
まず8GBだと単精度だとモデルが GPU に乗らないので読み込み時に半精度で読み込みます。単精度時の　StableDiffusion の重みが10GBくらいだったのでこれで5GBになり、メモリに乗ります。なお、CPU で動かそうとすると無限時間かかるので基本的に GPU に乗せることは must になります。

```python
import torch
from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained(
    'CompVis/stable-diffusion-v1-4',
    use_auth_token=TOKEN, 
    revision='fp16',
    torch_dtype=torch.float16,
)
pipe.to('cuda')
```

`TOKEN` は huggingface で発行したトークンを入れてください。

## mixed precision を使って入力を半精度に cast する
`StableDiffusionPipeline` はデフォルトだと入力を半精度に cast してくれない[^no-autocast]ので推論時に mixed precision のコンテキストブロックを作って半精度に cast します。これで推論時エラーは起きません。

```python
with torch.autocast('cuda'):
    image = pipe(
        PROMPT,
        height=512,
        width=512,
        guidance_scale=7.5,
        num_inference_steps=50,
    )['sample'][0]
```

`PROMPT` は生成呪文を入れてください。

[^no-autocast]: そのまま inference すると型エラーが出ます。

## バッチサイズは1にする
試しにバッチサイズを上げてみたらメモリエラーで死んだのでバッチサイズは1のみです。メモリが12GBあったらバッチサイズもう少し上げれるかもしれません。バッチサイズを上げる場合は `[PROMPT] * batch_size` のようにリスト化＋バッチサイズの長さにコピーすれば並列化の恩恵にあずかれます。

# その他メモ
- 半精度化 (mixed precision) しても生成クオリティは落ちない。推論速度が上がるためやりトク
- 生成サイズはデフォルトから落とすと生成クオリティが落ちるらしい (友人談)
- `num_inference_steps` はデフォルトから上げても正直そこまで変わらないので固定でよさそう
    - 100にしても50と比べて定性的には特に良くならない
- [StableDiffusion のうまくいっているサンプル](https://lexica.art/)を見た感じ、生成したい画像の概要＋生成クオリティを上げるコマンド連打がいい感じのクオリティの画像を作るコツっぽい