OmniAICreator/Qiita-1.07M huggingface dataset:
mac でクリップボードの履歴を管理したいときは Maccy が便利

mac でもクリップボードの履歴を遡ってペーストしたい。

Windows の場合は [Clibor](https://chigusa-web.com/clibor/) を使ったり、`Win` + `V` を使ったりするのがメジャーかと思いますが、macOS の場合は Maccy がシンプルで便利でした。  
他にもクリップボードの履歴を管理するアプリケーションはあるのですが、2021年10月現在も継続してメンテナンスされており、一定程度のユーザがいるものとしてはこちらかと。

https://github.com/p0deje/Maccy


## Maccy のインストール

Homebrew でインストールできます。

```shell-session
$ brew install --cask maccy
```

インストール後はアプリケーションフォルダ以下の Maccy を開いて使用する。
Launch at login の設定もあるので、設定しておくとよい。

## 基本的な使い方

以下、デフォルト設定での使い方。
Maccy のポップアップ画面の例は以下の通り。

![Screen Shot 2021-10-22 at 1.29.41 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66988/d6c951f0-abfe-c401-475a-e5f16c8c3768.png)


- `Shift + Cmd + C` で上記画像のように履歴の一覧が開く。  
  デフォルトではカーソル位置にポップアップするが、設定で変更できる。
- カーソルキーで履歴を選んで Return でクリップボードに選択されたものが入る。  
   または各履歴の右側に表示されている `⌘[数字]` の通りに入力する。
- 履歴を選択した状態で `Option + P` で選択された履歴のピン留めができる。  
   解除するときも同様にピン留めされた履歴に対して `Option + P`
- 履歴を選択した状態で `Option + Delete` で選択された履歴を削除。  
   `Option + Cmd + Delete` で全ての履歴を削除する。
- 画面上部の入力ボックスで履歴の検索も可能。


## 設定例

自身の設定例を貼っておきます。変更点は以下の通り。

- `Launch at login`, `Check for updates automatically` を有効化
- Hotkey を `Shift + Cmd + C` から `Shift + Cmd + V` に変更
    - デフォルトのホットキーは Chrome 系ブラウザの Developer Tools のホットキーと衝突しているため。
- `Paste automatically` を有効化
    - 履歴を選択して Return キーを押すだけでペーストされるようになる。  
      とくに Clibor に慣れている人は有効にすると幸せになれる。
- `Save` から `Files`, `Images` を無効化
    - 履歴をスッキリさせるため。

![Screen Shot 2021-10-22 at 1.05.03 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66988/0bad7236-c7b6-405d-242f-fe4a0f5e4137.png)

他のタブはデフォルト通り。
キャラクタの関係を用いた計算手法について

# 動機づけ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">よくわからないんですけどスタァライトってチューリング完全なんですか?</p>&mdash; ふぁぼん(Фабон Ильич Фаворский) (@syobon_hinata) <a href="https://twitter.com/syobon_hinata/status/1451193088085356552?ref_src=twsrc%5Etfw">October 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 準備

## Turing完全について

> チューリング完全とは、計算理論において、ある計算のメカニズムが万能チューリングマシンと同じ計算能力をもつとき、その計算モデルはチューリング完全（チューリングかんぜん、Turing-complete）あるいは計算完備であるという。
[フリー百科事典『ウィキペディア（Wikipedia）』][1]

多くのプログラミング言語はTuring完全であるように設計されていますが，その中でよく知られていてかつ命令が単純なものにBrainfuckがあります．

## キャラクタの数学的性質について

特定の文脈においてキャラクタ同士の関係に数学的なものがあることが知られています．
以下はその例となります．ただし，$Cat$をキャラクタの集合とし，$A, B, C \in Cat$とします．

1. $A \times B$ $(A \neq B)$
  - 恋愛や性的関係において，AとBがどういう立ち位置であるかを示す．
  - 基本的に非可換．
  - どうみても演算ではないので実際にはTuple $(A, B)$で書かれる方が適切．
2. $A \rightarrow B$
  - 恋愛関係において，いわゆる片思いとよばれるものと同じ．
  - グラフ理論における有向グラフに同じ．
  - 自己ループを持つこともある．
  - $A \rightarrow B$ かつ $A \leftarrow B$であるようなものを両思いというが，必ずしも肯定的に関係が成立するわけではない．
3. $A \sim B$
  - いわゆる双子．三つ子以上のときもある．
  - $A \sim A$，$A \sim B$ ならば $B \sim A$，$A \sim B$ かつ $B \sim C$ ならば $A \sim C$ なので正しく同値関係．
  - $C \rightarrow A$ のときに $C$ が $A$ と $B$ をよく間違え，その結果として $B$ も我々も悲しい気持ちにさせられる．

ほかにもあると思いますが，この記事ではそれ以上の紹介をしません．

## オタクについて

実はオタクは万能Turingマシンと同じ計算能力を持っています．
具体的にはBrainfuckの命令を読んで実行するだけの能力があります．

# 計算手法

ここまで読んだ方にはわかるかと思いますが，プログラムを関係の列，オタクを計算機として扱えば計算ができることになります．
正確に説明すると，あるページまたはコマにおいて，「キャラクタの数学的性質について」で述べた3つの関係を扱うかどうかで3bitを管理し，この3bitをBrainfuckの命令に割り当てます．これを解釈したオタクが計算をすることで結果を得られるわけですね．

# 問題点について

この計算手法にはいくつか問題があることが知られています．

## オタクによる解釈違い

「キャラクタの数学的性質について」1, 2は解釈違いを起こし，計算結果が異なる可能性があります．
（ex. まだ $A \rightarrow B$ ではないのでは？）
そういう場合は解釈違いを認めないように各所に監視者を配置する必要があることがあります．

## オタクの寿命

実際に計算をする段になると，たまに計算終了より早くオタクのほうが亡くなる場合があります．
人間の命は短いのでやはりそういうことは起こりますが，[おねえさん][2]になることで解決することもできます．

# まとめ

退屈なことは人間にやらせよう

[1]:https://ja.wikipedia.org/wiki/%E3%83%81%E3%83%A5%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0%E5%AE%8C%E5%85%A8
[2]:https://www.youtube.com/watch?v=Q4gTV4r0zRs
情報セキュリティについて

# はじめに
本記事では、情報セキュリティ管理についてをまとめております。
本日学習したところになります。

# 情報セキュリティ
情報セキュリティマネジメントシステムの国際規格`ISO/IEC 27000`より、
`機密性`、`完全性`、`可用性`の３要素が定義されています。

## 機密性
認められていない人に対して、情報を非公開にすることです。

- アクセス制限
- 認証
- データの暗号化

など、機密性を高める技術があります。

## 完全性
情報が正確であり、改ざんや消去されていないことです。

- 誤りのチェック
- データのバックアップ
- ディジタル署名

など、完全性を高める技術があります。

## 可用性
認められた利用者が必要な時に情報を利用できることです。

- 予備電源
- システムや設備の二重化

など、可用性を高める技術があります。

以上です。
[gnuplot]gif アニメーションの作り方

環境：gnuplot 5.4 on Mac

ここを参考にgifアニメーションを作成してみた。
https://atatat.hatenablog.com/entry/gnuplot29_animation
do ループではなく```reread```ループの場合うまくいかない。

原因は```set terminal gif animate```の設定を```reread```で再読み込みする際に繰り返し読み返されて初期設定に戻っているせい。
したがって、```reread```しているファイル内で```set terminal gif animate```してはいけない。外部ファイルで設定し当該ファイルを```load```すればいい。
こんなふうに

```gnuplot:createGifAnimation
#!/usr/bin/env gnuplot -dc -persist

set terminal gif animate

set output "flowAnimation.gif"

load "flow.gp"

set output
```

おかげでこんなgifファイルが作れた。ただ画像が荒い。解像度を上げるにはどうすればいいんだろう？

![flowAnimation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62130/6101f0e0-b251-4df9-3356-37d8076ab1dd.gif)
railsチュートリアル第八章 ログアウト

##ログアウト
ログアウト機能を追加する。

ユーザーが明示的にログアウトするまではログイン状態を保他なくてはならない。
ユーザーセッションを破棄するための有効なアクションをコントローラで作成。

####log_outメソッド
app/helpers/sessions_helper.rb

```rb
module SessionsHelper
.
.
.  
  # 現在のユーザーをログアウトする
  def log_out
    session.delete(:user_id)
    # ユーザーセッションを削除
    @current_user = nil
    # セキュリティ上nilの設定する。
    # 本来ならこれはしなくて良い。
  end
end
```

####セッションを破棄する（ユーザーのログアウト）
app/controllers/sessions_controller.rb

```rb
class SessionsController < ApplicationController
.
.
.
  def destroy
  # ユーザー削除
    log_out
    # log_outメソッドを発動
    redirect_to root_url
    # ホーム画面に戻る
  end
end
```

####ユーザーログアウトのテスト（無効なログインテストも1箇所改良）
test/integration/users_login_test.rb

```rb
require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest
  
  def setup
    @user = users(:michael)
    # ハッシュで呼び出す。
    # なんでもハッシュで呼び出せるようになるのか？
  end
  
  test "login with valid email/invalid password" do
    get login_path
    assert_template 'sessions/new'
    post login_path, params: { session: { email:    @user.email,
                                          password: "invalid" } }
    assert_not is_logged_in?
    assert_template 'sessions/new'
    assert_not flash.empty?
    get root_path
    assert flash.empty?
  end
  
  test "login with valid information followed by logout" do
    get login_path
    # ログイン画面にいく
    post login_path, params: { session: { email:    @user.email,
                                          password: 'password' } }
    # データをデータベースに投稿
    assert is_logged_in?
    # ログインされているよね？
    assert_redirected_to @user
    # ユーザー情報を取り出すのか？
    follow_redirect!
    # もう一回確認
    assert_template 'users/show'
    # ユーザーページに移動する
    assert_select "a[href=?]", login_path, count: 0
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
    delete logout_path
    assert_not is_logged_in?
    assert_redirected_to root_url
    follow_redirect!
    assert_select "a[href=?]", login_path
    # これは表示する
    assert_select "a[href=?]", logout_path,      count: 0
    assert_select "a[href=?]", user_path(@user), count: 0
    # 上2行は非表示になっていることを確認。
  end
end

```

```
ubuntu:~/environment/sample_app (basic-login) $ rails t
Running via Spring preloader in process 9774
Started with run options --seed 65113

  24/24: [============================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.15159s
24 tests, 61 assertions, 0 failures, 0 errors, 0 skips
```

###演習
1.
ブラウザから［Log out］リンクをクリックし、どんな変化が起こるか確認してみましょう。また、リスト 8.35で定義した３つのステップを実行してみて、うまく動いているかどうか確認してみましょう
確認

2.cookiesの内容を調べてみて、ログアウト後にはsessionが正常に削除されていることを確認してみましょう。
どうしてもcookiesが消えない。
みている場所が違うのか。
わからない。
Gmailの件名と本文テンプレートをワンクリック入力【ブックマークレット】

##Gmailで予めテンプレートとして作成しておいた件名と文章をワンクリックで入力するブックマークレット

GmailをChromeブラウザで利用している方向けのものです。
新規作成ボタンを押した後に、件名と本文を自動入力します。
業務の効率化を目的としています。

Gmailにもテンプレート入力機能あるのですが、
若干ステップ多いので・・・
（これは超ショートカット版のようなイメージです）

![template.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570700/22f8b220-f562-5513-a2f4-c0fde4a53f41.png)

##コード

**▼シンプルな例：**

```
javascript:var subj = "ご挨拶とお打ち合わせに関しまして";var com ="<div>様</div><div>★お好きな文章</div>";mails();function mails(){document.getElementsByName("subjectbox")[0].value=subj;var mailms = document.querySelectorAll('[aria-label="メッセージ本文"]')[1];mailms.insertAdjacentHTML('afterbegin',com);}
```

　
**▼営業向けテンプレートの例**

```
javascript:var subj = "ご挨拶とお打ち合わせに関しまして";var com ="<div>様</div><div><br></div><div>お世話になっております。</div><div>株式会社〇〇の☆☆です。</div><div><br></div><div>もしよろしければ、一度ご挨拶も兼ねて</div><div>お打ち合わせの機会を頂けないでしょうか。</div><div><br></div><div>お打ち合わせ候補日：</div>";mails();function mails(){document.getElementsByName("subjectbox")[0].value=subj;var mailms = document.querySelectorAll('[aria-label="メッセージ本文"]')[1];mailms.insertAdjacentHTML('afterbegin',com);}
```


##使用方法

**コードを編集：**
subj = "★"の部分に件名を入力
com= "★"の部分に本文を入力
※Gmailの仕様に合わせ、1段落毎に`<div></div>`囲み
　改行は`<div><br></div>`

**ブックマークレットの作成：**
1.適当なブックマークを作る
2.ブックマークを編集
　名前を「URLコピー」（任意）
　URLに上記のスクリプトを貼り付ける
3.Gmailで新規作成ボタンを押し、作成したブックマークをクリック
　→件名と本文が入力されるはずです。

##コード補足

`document.getElementsByName("subjectbox")[0].value=subj;`
件名に入力する

`document.querySelectorAll('[aria-label="メッセージ本文"]')[1];mailms.insertAdjacentHTML('afterbegin',com);`
本文に入力する（HTMLの差し込み）

##補足
Gmail全体の仕様が変更となった場合は利用出来ません。
AWS SDK for Java で Cognito の認証情報を取得する

メモです。一応取得できたけど、実際の業務では Go 言語で書きそうなので供養。

https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/examples-cognito.html

https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/cognito

# 実装

既に aws コマンドで取得したことがある人にとっては、そのまま Java 言語に翻訳、と言う感じ。ここでは sbt で実装する。なんで sbt かはこちら

https://qiita.com/kijuky/items/6e95db63689083de9e55

```project/plugins.sbt
libraryDependencies ++= Seq(
  "software.amazon.awssdk" % "cognitoidentity",
  "software.amazon.awssdk" % "cognitoidentityprovider"
).map(_ % "2.17.62")
```

bom が提供されていますが、バージョン揃えるだけならこんな書き方ができます。さすが scala、と言う感じ。bom についてはこちら

https://qiita.com/syogi_wap/items/432bbdbe9892eb05e122

```bash:.envrc
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export CLIENT_ID=...
export USER_PASSWORD=...
export USER_POOL_ID=...
export USERNAME=...
```

認証情報は適当に。

```build.sbt
import software.amazon.awssdk.regions._
import software.amazon.awssdk.services.cognitoidentityprovider._
import software.amazon.awssdk.services.cognitoidentityprovider.model._

import scala.collection.JavaConverters._

lazy val awsAccessKeyId: String = sys.env.getOrElse("AWS_ACCESS_KEY_ID", "")
lazy val awsSecretAccessKey: String = sys.env.getOrElse("AWS_SECRET_ACCESS_KEY", "")
lazy val clientId: String = sys.env.getOrElse("CLIENT_ID", "")
lazy val userPassword: String = sys.env.getOrElse("USER_PASSWORD", "")
lazy val userPoolId: String = sys.env.getOrElse("USER_POOL_ID", "")
lazy val username: String = sys.env.getOrElse("USERNAME", "")

lazy val printIdToken = taskKey[Unit]("")
printIdToken := Def.task {
  sys.props ++= Map(
    "aws.accessKeyId" -> awsAccessKeyId,
    "aws.secretAccessKey" -> awsSecretAccessKey
  )
  val cognitoIdp = CognitoIdentityProviderClient // closeable なので、気になる人は Using とか使うと良さげ
    .builder()
    .region(Region.AP_NORTHEAST_1)
    .build()
  val request = AdminInitiateAuthRequest
    .builder()
    .userPoolId(userPoolId)
    .clientId(clientId)
    .authFlow(AuthFlowType.ADMIN_USER_PASSWORD_AUTH)
    .authParameters(
      Map(
        "USERNAME" -> username,
        "PASSWORD" -> userPassword
      ).asJava
    )
    .build()
  val response = cognitoIdp.adminInitiateAuth(request)
  val idToken = response.authenticationResult().idToken()
  println(idToken)
}.value
```

```
$ sbt printIdToken
```

実装して気づいたメモ

- accessKeyId と secretAccessKey の読み出し順序で一番優先度が高いのはシステムプロパティに設定されているもの。
- authFlow は文字列でもいける。でも折角なら型でサジェストされた方が安心感ある。
- Java API なので、Scala の Map 使った場合は `asJava` が必要
- CLI だと `--query` で指定していたものは普通にプロパティからアクセスできる。
初学者が「もくもく会」とやらに参加してみた。

#はじめに
休日に「勉強しないとなー」と思ってもなかなかやる気がでないことありませんか？
私は常にそんなこと思いながら過ごしているので、どうしたらモチベが保てるかを考えております。

1人だけでもくもく学習できる天才は置いておいてっと。。。(/・ω・)/
私みたいな怠け者は一人だとどうしてもようつべを見てしまい、そのまま1日が終わってしまいます（笑）

なので「もくもく会」という催しに参加してみたので、まとめてみました。


##「もくもく会」とは

![aaaaaaa_085110.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884151/7d880495-1506-6746-c265-18f7e3b2861c.jpeg)


その前に「もくもく会」ってなんですの？って思われた方がいらっしゃると思います。
私も最初は「もくもく会」って意味が分かりませんでしたｗ

木曜日に何か集まる会なのかなーと勝手に思っていました・・・(´・ω・｀)

簡単に言うと、
「みんなで集まって黙々と勉強しようよ！」っていう集まりっす。

集まるのに黙って勉強するんかいっ！！って思った人。
そうなんです、黙って勉強します。でも集まります

まーみんなで発表し合う会もたくさんあるので一概には言えないですが、
基本みんなで黙って勉強するものと思っています。

一番刺激になるのは、初対面の人と自然に知り合えることだと思います。
長年エンジニアの人もいますし、これからエンジニアに転職を考えているような人もいます。

ITとプログラミングに興味あるくらいの人もいます。
ただ、皆さんに共通しているのは「勉強したい」という意識だと思います。

基本そういう人たちが集まるので、お互いに刺激し合って集中して学習できるメリットがあります。
また「もくもく会」をきっかけに意見交換をすることもできるので、思ってもいなかったコネクションができることもあります。

##参加方法
私は[connpass](https://connpass.com/)というサイトで週末のイベントを探して申し込みました。
Gmailやツイッターアカウントだけで申し込めるのでとても簡単でした。

自分で勉強会を作ることもできるので、今度やってみようかなーと思ってます。
集まるかどうかは知りませんがｗ

大体5人から10人くらいの人数でもくもく会をしてることが多いです。
あまり多すぎてもやり取りしにくいですしね。

申し込んだら、当日ちょっとお金をもっていけばおｋです。
参加費は500円～1500円くらいが多いと思います。

私は09：00～12：00の3時間の勉強会で、費用は500円でした。
渋谷のコワーキングスペースが集合場所だったので、その場所代のみでした。

##「もくもく会」当日

今回参加したもくもく会の場所は渋谷だったので、電車でガタンゴトン揺られていきました。
![IMG_20211017_084043.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884151/0b516ea7-ec0f-984f-a0dc-f5633dcd9b89.jpeg)
※なんか渋谷駅新しくなってんね。知らんかった。。。

コワーキングスペースで受付を済ませて、奥のほうへ行くとPCを広げた集団がいたので声をかけました。

![IMG_20211017_085110.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884151/3b8ff796-89cf-4bf1-eda4-599686bf77a2.jpeg)
※フツーのコワーキングスペースでした。受付の人はとてもイケメンで丁寧な方でしたよ。

初めての参加でドキドキしていましたが、とても気さくな感じで緊張が解けました。
適当な席について学習する準備をしていると、主催者の方が来て挨拶をしました。

![IMG_20211017_090935.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884151/24e132dd-aba4-fc61-9767-abe885df87bd.jpeg)
※3時間で500円でコスパはとてもよろしいかと思われ。

スケジュールは以下の流れです。

09：00～09：05　会場集合
09：05～09：15　自己紹介/やること発表
09：15～11：45　もくもく学習
11：45～11：55　成果発表(slackに投稿)

プログラミングを独学している大学生や、エンジニアに転職するためにポートフォリオを作成している人もいました。

自己紹介をした後はひたすら黙々と学習しただけでしたｗ
なんかもっと話しかけたり、やり取りする人もいるのかと思っていたのですが、会話は皆無でした。
まぁそれはそれで、集中して取り組むことができるので良いと思いました。

もくもく会用に会議室を取っているわけではなくて、
一般のコワーキングスペースなので、もくもく会以外の方もいらっしゃいます。

みんなが静かに自己学習してる空間はとても心地よいですな(´・ω・｀)
時間になったらそれぞれがslackに今日の成果を投稿して、自由解散です。

私は少しつながりができればと思ったので、ツイッターを相互フォローさせていただきました。
学習のモチベの高い人たちとつながることができるのは良いっすよね！

なんか常連のもくもく会メンバーはランチを行くような雰囲気でした。
新参者も私は、お礼のあいさつをしてそそくさと帰ることにしましたｗ

![IMG_20211017_121509.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884151/0377fded-bc73-ee97-21eb-4199be84d2d4.jpeg)
※マークシティ通り抜けて、道玄坂上らへん。

次週のもくもく会にも申し込んだので、その時はランチを一緒したいなぁと思っています。

##終わりに
今回は「もくもく会」に参加してみた感想をまとめてみました。

会社の同僚とはリモートで勉強会を開いていますが、社外の人と会うのもとても刺激になって良かったです。
今後は自分でも「もくもく会」を開いて、人が集まるようなコミュニティを作れたらいいなぁと思っています。

![IMG_20211017_122052.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884151/c53cf3a6-4907-552f-29b2-7011458265d0.jpeg)
※円山町らへんをぶらっとして帰りましたとさ。

ではでは、また面白い勉強会に参加したら報告したいと思います。
最後までご覧いただきありがとうございました。
シグナルでいろいろ遊んでみる

# 導入

仕事でsignalを使ったのでいろいろ遊んでみようと思います。
いろいろ遊んでみるので、この記事は目次＆やりたいことメモとして使います。

# 1. シグナルの種類

シグナルの種類と送信の仕方、標準動作を調べてみる。
と思ったのですが、他の方の記事が分かりやすいので、[そちら](https://qiita.com/Kernel_OGSun/items/e96cef5487e25517a576)を参照してください。

一応、man pageも。

man page: [signal(7)](https://linuxjm.osdn.jp/html/LDP_man-pages/man7/signal.7.html)

# 2. シグナルのハンドルの方法

## 2.1. signal/sigaction

signal/sigactionと動きを調べてみました。
[こちら](https://qiita.com/AAsada/items/d6a4cb235e44b2d730c6)を参照。

ハンドラには制限も多いので少し使いにくいですね。

## 2.2. sigwait/sigwaitinfo

sigwait/sigwaitinfoと動きを調べてみました。
[こちら](https://qiita.com/AAsada/items/59160e064318e6110989)を参照。

専用スレッドを用意するか、ブロックなしで読みだすか、定期的にブロックから抜けるか。
こちらの方がかなり使いよいですね。

## 2.3. pselect/epoll_pwait

pselect/epoll_pwaitと動きを調べてみる(予定)

## 2.4. signalfd

signalfdと動きを調べてみる(予定)

# 3. シグナルのブロック

シグナルのブロックの仕方と、動作を調べてみる(予定)
python loggingメモ

##動作環境
macbook pro
python version 3.8.3

##loggerの構成
・ロガー→ログのレコードを生成する役割がある
・ハンドラ→ログレコードを出力する
・フォーマッタ→ログレコードを整形する
・フィルタ→ログレコードを処理するか否かの条件を定義する

##logger使い方
```python:log_test1
import logging
import sys

#ロガーを生成
logger = logging.getLogger(__name__)

#ハンドラを生成
sh = logging.StreamHandler(sys.stdout)
# 出力レベルを設定
sh.setLevel(logging.WARNING)

#フォーマッタを定義
fmt = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s", "%Y-%m-%dT%H:%M:%S")
# フォーマッタをハンドラに紐づける
sh.setFormatter(fmt)

#ハンドラをロガーと紐づける
logger.addHandler(sh)
fmt = "%(asctime)s %(levelname)s %(name)s :%(message)s"
logging.basicConfig(level=logging.DEBUG, format=fmt)
```

簡単に使うには

```python:log_test1
import logging

logger = logging.getLogger(__name__)
fmt = "%(asctime)s %(levelname)s %(name)s :%(message)s"
logging.basicConfig(level=logging.DEBUG, format=fmt)
```

##フォーマットについて

ログレベル

```python
logging.debug('debug') #levelno->10
logging.info('info') #levelno->20
logging.warning('warning') #levelno->30
logging.error('error') #levelno->40
logging.critical('critical') #levelno->50
```
主な変数

```python
%(asctime)s
%(message)s
%(created)f
%(filename)s
%(funcName)s
%(levelname)s
%(lineno)d
```

##参考にしたサイト
https://hackers-high.com/python/logging-overview/
https://srbrnote.work/archives/4472
【Laravel】バリデーションエラー発生時のメッセージの表示

#概要
バリデーションエラーが発生したときのメッセージ表示方法について、書き方は色々あると思いますが、今回はその中でも特にシンプルな書き方を紹介します。

#`@error`を使った表示方法

```php:create.blade.php
@error('menu_name')
    <span>{{ $message }}</span>
@enderror
```

`view`にこのように記述することで、`menu_name`という特定の項目のエラーメッセージを表示させることができます。
サイトのURLを共有する時にURLパラメータが邪魔な方のためのブックマークレット

#URLパラメータを削除した現在のURLをクリップボードに送信するブックマークレット

会社の仲間、クライアント様等に
参考記事やブログのURLを共有する際、
広告経由等でURLパラメータ（URLの?以降）が
あって邪魔だなと思った事は無いでしょうか。

:::note info
https://qiita.com/?abc=001&def=255
↓
https://qiita.com/
※?abc以降は要らない時
:::

私はあります。
手動で消せば良いだけなのですが、
ちょっとめんどくさいなと思います。

このブックマークレットは、
ワンクリックで、
*現在見ているURLの?以降を削除した状態で*
*コピーする（クリックボードに送信）*
だけのシンプルなものです。

Chromeブラウザで動作確認しています。

```
javascript:var clp = location.href;var clipboardText = clp.substring(0, clp.indexOf("\?"));navigator.clipboard.writeText(clipboardText);
```

##使用方法：
1.適当なブックマークを作る
2.ブックマークを編集
　名前を「URLコピー」（任意）
　URLに上記のスクリプトを貼り付ける
3.見たいURLを開き、作成したブックマークをクリック
　→テキストエディタなどに貼り付けると?以降は消えたURLになっているはずです。

##コード補足
・location.hrefで現在のURLを取得
・indexOf("\?")で?までの文字数を計算して抜き出し
・navigator.clipboard.writeTextでクリップボードに送信
というシンプルなものです。
テスト駆動開発（TDD）とは何か？

# この記事の内容について

この記事は私が『テスト駆動開発』を読み、テスト駆動開発（以下TDD）について理解したことをまとめたものです。
『テスト駆動開発』からの引用と意訳を多く含みます。引用元は注釈をご確認ください。

# TDDとは何か？

TDDはテスト技法ではない。
**分析技法であり、設計技法であり、実際には開発のすべてのアクティビティを構造化する技法。**[^1]

[^1]: p.278 名前の由来は

# TDDのTは「テスト」の一部。ではTDDのテストとは何か？

それは **Checking** である。[^2]

[^2]: p.293 TDDのTは「テスト」の一部に過ぎない

テストと確認（Check）は違う。
確認（Check）は思ったとおりに動くことを確認する行為。つまり期待値との比較なので、機会が得意とするところ。
テストとは対象を壊しにいく行為。これは人間が得意とするところ。[^3]

[^3]: t_wadaさんの解説より [LAPRAS公開設計レビュー 「t_wadaさんにこのテストでサバンナを生き抜けるか聞いてみた」](https://lapras.connpass.com/event/222901/)


TDDのテストは、思ったとおりに動くことを確認するものなので、確認（Check）にあたる。

# TDDは実際には何で駆動されているのか？

ここまででTDDとは「テスト」という言葉から抱くイメージとは、かなり違うものだとわかる。
では、実際にはどういった言葉が適切なのだろうか？

それは**「振る舞い（Behavior）」**である。[^4]

[^4]: p.296 TDDからBDDへ

テスト駆動開発（TDD）改め振る舞い駆動開発（BDD）は、テストやアサーションといった語彙の先入観による誤解を避け、強みを最大限に引き出すために生まれた。

# TDDは誰でもできるのか？

**TDDはスキル**[^5]

練習によって獲得できる技術。
しかも「個人スキル」なので、状況に依存することなく始められる。

[^5]: p.306 TDDはスキル

# TDDを使ったほうが良いのか？

**自分が活用できるテクニックとして加わればよく、最終的には使わなくてもよい。**[^6]

[^6]: p.307 自分のスタイルを

優れたエンジニアリングがプロジェクトの成功に占める割合は20%といったところ。
この観点では、TDDを使うと業界の標準的な指標以上になるので「やりすぎ」といえる。[^7]

[^7]: p.274 TDDは誰のためのものか

# まとめ

最初は「TDDはテストを最初に書く」くらいのイメージしかなかったのですが、『テスト駆動開発』を読んでその認識は正されました。

教条主義化や意味の希薄化[^8] が起こっているという話からは、「アジャイル」や「技術的負債」にも同じものがあると感じています。
[^8]: p.300 教条主義化と意味の希薄化
不安から開放してくれるはずの技法が、他人を攻撃するモノになったり、正しく活用されないのは残念なことです。
とはいえ、それを避けるために生まれたBDDの「振る舞い（Behavior）」という言葉は「テスト」よりも馴染みのないと思われるので、浸透するのはまだ時間を要しそうですね。

それはさておき、私個人としてはTDDは魅力的なスキルです。
プロダクトやビジネスを加速させるためのテクニックとして、積極的に身につけていきたいですね。

# 書籍について

[テスト駆動開発](https://shop.ohmsha.co.jp/shopdetail/000000004967/)
著：Kent Beck
訳：[和田卓人](https://twitter.com/t_wada)
出版：オーム社
three.jsで線がギザギザになったら

three.jsで線がギザギザ（ジャギー）になってしまう場合は、 `WebGLRenderer` でアンチエイリアスを設定します。

アンチエイリアスなし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/752360ef-e3e1-8311-c2a9-3e5eb64d195f.png)

アンチエイリアスあり

```javascript
const canvas = document.querySelector('#canvas');
const renderer = new THREE.WebGLRenderer({canvas, antialias: true});
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/2e75a6ce-ed14-2c72-a618-dfa900100aad.png)

（解像度とか画素数とかのオプションがあるのかと探しちゃってました・・・）
Udemy「ネットワークエンジニアを目指す初心者はここから始めよう！「ゼロから学ぶネットワーク基礎」1021

十進数から二進数（１）
・２で割り、余りを求める（０か１になる）。
・余りの０か１を逆から並べる。
・８桁に満たない場合は先頭に０を付ける。

例１
192...0
 96...0
 48...0
 24...0
 12...0
  6...0
  3...1
  1...1→11000000

例２
168...0
 84...0
 42...0
 21...1
 10...0
  5...1
  2...0
  1...1→10101000

例３
51...1
25...1
12...0
 6...0
 3...1
 1...1→110011※８桁に満たないので→00110011


十進数から２進数（２）
・128、64、32、16、8、4、２、１を覚える。
・変換したい数字から上記を順に引き算する。
・引ける場合は１、引けない場合は０とする。

例１　192  64   0   0  0  0 0 0
     128  64  32  16  8  4 2 1
      1    1   0   0  0  0 0 0→11000000

 
例2 168   40  40  8  0  0  0
    128   64  32 16  4  2  1
     1     0   1  0  0  0  0→10101000

例3  51  51  51  19  3  3  3  1
    128  64  32  16  8  4  2  1
     0    0   1   1  0  0  1  1→00110011


二進数から十進数
・128、64、32、16、8、4、2、1を覚える。
・二進数を８桁にして、先頭から各桁と８つの数字を比較する。
・１の場合は足す、０の場合は足さない。

例１  1    1   0  0    0 0　 0  0
    128   64  32 16   8 4   2  1
    128 ＋ 64＋0＋ 0＋ 0＋0 ＋0＋0 ＝192

例2 1    0   1   0   1  0 0 0
   128  64  32  16   8  4 2 1
   128＋ 0 + 32 +0 + 8 +0+0+0=168

例3  0   0   1  1  0  0  1  1
    128 64  32 16  8  4  2  1
     0+  0+ 32+16+ 0+ 0+ 2+ 1=51
【Blender】SVG のメッシュ化

<!-- =============================================== -->
# 概要
<!-- =============================================== -->
**Blender 2.93**を使用して、SVGファイルをメッシュ化して**立体感のあるオブジェクトに変換**します。

![スクリーンショット 2021-10-21 224924.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/4b0f3b6d-72d3-8caa-863c-39c4fb0ec9bc.png)

<!-- =============================================== -->
# 手順
<!-- =============================================== -->
### SVGのインポート
```
[ファイル] ⇒ [インポート] ⇒ [SVG]
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/343bcbc0-ded4-bc4d-fb43-af55b231d3e2.png" width="600">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/5f50dcee-ddba-4f7f-8492-e37934e1801e.png" width="600">

### メッシュ化
```
[オブジェクトモード]
[オブジェクト] ⇒ [変換] ⇒ [メッシュ]
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/223ecfc6-d025-907f-9149-4cdae377a844.png" width="600">

変換すると、オブジェクトの種類アイコンがメッシュになります。

![スクリーンショット 2021-10-21 230137.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/0d083259-1a70-9e32-6581-b5b9f14d4ef9.png)

### 押し出し
立体感を持たせるには、編集モードで面を押し出します。

```
[編集モード]
全選択（A） ⇒ 押し出し（E）
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/d9829afe-7b02-832b-1eb5-c4eae98e134f.png" width="600">

<!-- =============================================== -->
# 参考
<!-- =============================================== -->

https://styly.cc/ja/tips/jp-illustrator-to-blender/
Standard ML（SML）をMacBookに入れる

## １. brew installでインストール

http://www.smlnj.org/dist/working/110.95/macos.html

> There is also a Homebrew cask that wraps the 64-bit installation package. If you have homebrew installed, then you can run the following command to install SML/NJ:
>
>```bash:
>% brew cask install smlnj
>```

なお、brew cask installは、現在はbrew install --caskに変わっている。

https://qiita.com/horit/items/03e6ae6599253afcd75c

```bash:Terminal
electron@diynoMacBook-Pro ~ % brew install --cask smlnj
==> Caveats
To use smlnj, you may need to add the /usr/local/smlnj/bin directory
to your PATH environment variable, e.g. (for Bash shell):
  export PATH=/usr/local/smlnj/bin:"$PATH"

==> Downloading http://smlnj.cs.uchicago.edu/dist/working/110.99.2/smlnj-amd64-110.99.2.pkg
######################################################################## 100.0%
==> Installing Cask smlnj
==> Running installer for smlnj; your password may be necessary.
Package installers may write to any location; options such as `--appdir` are ignored.
Password:
installer: Package name is SML/NJ Version 110.99.2
installer: Installing at base path /
installer: The install was successful.
🍺  smlnj was successfully installed!
electron@diynoMacBook-Pro ~ % 
```

## ２. REPL（対話型インタプリタ）の動作確認

smlが認識されない。

```bash:Terminal
electron@diynoMacBook-Pro ~ % sml
zsh: command not found: sml
electron@diynoMacBook-Pro ~ % smnnj
zsh: command not found: smnnj
electron@diynoMacBook-Pro ~ % 
```

インストールに成功したとき、次のメッセージが表示されていた。

>```text:
>To use smlnj, you may need to add the /usr/local/smlnj/bin directory
to your PATH environment variable, e.g. (for Bash shell):
  export PATH=/usr/local/smlnj/bin:"$PATH"
  >```
  
カレント・ディレクトリを__: /usr/local/smlnj/bin*__に移動してから、__*sml*__と叩く。


```bash:Terminal
electron@diynoMacBook-Pro ~ % ls /usr/local/smlnj/bin
asdlgen		ml-antlr	ml-burg		ml-makedepend	ml-yacc
heap2exec	ml-build	ml-lex		ml-ulex		sml
electron@diynoMacBook-Pro ~ % 
```

```bash:Terminal
electron@diynoMacBook-Pro ~ % cd /usr/local/smlnj/bin
```

```bash:Terminal
electron@diynoMacBook-Pro bin % sml
zsh: command not found: sml
electron@diynoMacBook-Pro bin %
```

__*./sml*__で認識される。

```bash:Terminal
electron@diynoMacBook-Pro bin % ./sml
Standard ML of New Jersey (64-bit) v110.99.2 [built: Thu Sep 23 13:44:44 2021]
- 7 + 5;
val it = 12 : int
- 7 + 5 - 3
= ;
val it = 9 : int
- 7 + 5 - 3;
val it = 9 : int
-
```

#３. REPLから抜ける

exitは、__*OS.Process.exit(OS.Process.success);*__を実行する。

```bash:Terminal
-  OS.Process.exit(OS.Process.success);
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[library $SMLNJ-BASIS/(basis.cm):basis-common.cm is stable]
[autoloading done]
stdIn:5.2-5.37 Warning: type vars not generalized because of
   value restriction are instantiated to dummy types (X1,X2,...)
electron@diynoMacBook-Pro bin % 
```
【AWS】EC2のt2.mediumをt4g.largeにしようとしたら無理だった話【ARM,x86_64】

# EC2のマシンタイプ t4g シリーズについて

t2.mediumインスタンス(x86_64)をt4g.largeにスペックアップしようとしたら、
アーキテクチャが不適切ですという感じのエラーが出てスペック変更できなかったのでメモ

## 単純にアーキテクチャが違うインスタンスだったので、変更不可能

t4g.〇〇のインスタンスは、アーキテクチャにARMベースのGraviton2というのを利用しているらしく、
x86_64アーキテクチャのプロセッサで構築されたインスタンスはt4gにスペック変更することができないようだ

そんなわけなので、スペックアップはt3a.largeにすることにしました。。。


ちなみにt3はintel Xeonで、t3aはAMD EPYCというプロセッサらしい aはAMDのaなのか・・・！？

## 以下、t4gやARMに関するメモ

### t4g インスタンス

コスパに優れたバースト可能のマシンタイプ
2vCPU , 8GB の t4g.large で、 月額 $64(7,275円) ほど

このインスタンスタイプは AWS Graviton2 というプロセッサで動いているらしい
Graviton2プロセッサは、ARMアーキテクチャをカスタムして作られたものの模様

t4gの他には M6g(汎用),C6g(CPU最適),R6g(メモリ最適) など、最後にgがつくものがGraviton2プロセッサを使っている模様
gはGravitonのgなのか・・？！？

- 参考
    - [新しい EC2 T4g インスタンス](https://aws.amazon.com/jp/blogs/news/new-t4g-instances-burstable-performance-powered-by-aws-graviton2/)
    - [AWS Graviton プロセッサ](https://aws.amazon.com/jp/ec2/graviton/)


### アーキテクチャについて

CPUのアーキテクチャには ARM と x86 があるが、
IntelとかAMDのCPUは x86 を利用して作られているらしい
ちなみに、x86 が 32bit , x64 が 64bit みたい

対するARMは、ARMというイギリスの会社が開発したやつで、
主にスマホとかタブレットに使われてるCPUのプロセッサで動いているらしい

ARMは省電力でニンテンドーDSとかで使われだしてからモバイル端末のプロセッサ市場で普及していってるみたい

性能については、ARMもx86_64もあまり変わらんみたい
コスパがいいのでARMは積極的に採用していくべきかもしれない

これからはモバイルに強いARMの時代が来るのか・・・？

- 参考
    - [CPUのアーキテクチャって？](https://beyondjapan.com/blog/2021/01/cpu_architecture/)


## 感想

ARMとかx86_64とか正直何？？？って感じだったので、勉強するきっかけになってよかった。
【Rails】 通知機能の難しい箇所を解説してみた

<h1>通知機能</h1>

PFに通知機能を搭載したのですが、
理解するのが難しかったため勉強もかねて
通知機能の難しい箇所をひとつひとつ解説することにします！

<h2>流れ</h2>

・モデルの解説
・コントローラーの解説
・ヘルパーの解説

<h2>モデルの解説</h2>

```php:app/models/post

  # 通知機能のアソシエーション
  has_many :notifications, dependent: :destroy

  def create_notification_by(current_user)
    notification = current_user.notifications.new(post_id: id, visited_id: user_id, action:"like")
    notification.save if notification.valid?
  end

# comment_idはコントローラーで@comment.idと指定しているので
# 投稿のidを引数にいれている
  def create_notification_comment!(current_user, comment_id)
# Commentモデルのpost_idに紐づくすべてのuser_idを引っ張ってくるが
# current_userは引っ張ってこない。
# そしてdistinctをすることで一意になる
    temp_ids = Comment.select(:user_id).where(post_id: id).where.not(user_id: current_user.id).distinct
# temp_idsで取ってきたすべてのコメントをeachで回す
    temp_ids.each do |temp_id|
# 引数は送る側になるのでdef create_notification_comment!(current_user, comment_id)で
# 指定いる引数と同じにしないといけない
      save_notification_comment!(current_user, comment_id, temp_id['user_id'])
    end

    save_notification_comment!(current_user, comment_id, user_id) # if temp_ids.blank?
  end

  def save_notification_comment!(current_user, comment_id, visited_id)
    notification = current_user.notifications.new(
      post_id: id, comment_id: comment_id, visited_id: visited_id, action: 'comment'
    )
    if notification.visitor_id == notification.visited_id
      notification.checked = true
    end
    notification.save if notification.valid?
  end
end
４桁の7セグsegをarduinoでつかう

#はじめに
４桁の７セグをarduinoで使うためのメモです。
TM1637という制御チップで４端子で制御できます。

#環境
arduino nano
Hiletgoの４桁７セグ
https://www.amazon.co.jp/gp/product/B010GX9CA4/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

#落とし穴
500円ぐらいのarduino nano互換機を使っていますが、いつの間にかに、書き込みが出来なくなっていました。が、ATmega328(Old Bootloader)を選択することで、書き込みできるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/046da34f-f32c-b086-0f3d-bca2925e9a1e.png)

#配線
GND->GND
VCC->5V
DIO->D3
CLK->D2

#ライブラリ
ライブラリの管理からAvishay Orpaz氏作のTM1637を入れます。バージョンは1.2.0でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/7355ac39-0411-2563-8846-1db938c6f6ff.png)

#コード
起動すると３分のカウントが始まり、03:00から00:00となって終わります。

```cpp:3minTimer.ino
#include <Arduino.h>
#include <TM1637Display.h>

#define CLK 2
#define DIO 3
TM1637Display display(CLK, DIO);
 
void setup() {
}
 
void loop() {
    display.setBrightness(0x0f);
    display.showNumberDecEx(300,0x40,true);//0x40はコロン
    delay(1000);
    for(int i=59; i>=0; i--){
      display.showNumberDecEx(200+i,0x40,true);
      delay(1000);
    }
    for(int i=59; i>=0; i--){
      display.showNumberDecEx(100+i,0x40,true);
      delay(1000);
    }
    for(int i=59; i>=0; i--){
      display.showNumberDecEx(i,0x40,true);
      delay(1000);
    }
    while(true);
}
```
javascriptでタイマー秒後に遅延実行

#　経緯
定期的に送られてくるjsonメッセージに対して、受信後設定時間以内に再度受信しなければ
発火させる関数を考える必要があった。

フローチャートはこんな感じ。　発火させたい処理は関数B
![Untitled Diagram (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2200496/f7c5934d-1215-6465-0b9d-26a226b4e224.jpeg)




#　コード
私の場合はjsonメッセージを受信した場合に関数Aが毎回発火していたので、
関数Aの中に下記コードを記述しました。


```
// 下記宣言は関数Aの外で行っています
let countTimer = false

// 以下は関数Aの処理（何度も繰り返される）

if (countTimer != false) clearTimeout(countTimer)
countTimer = setTimeout(function () {
  // ここに行いたい処理を書く
  条件　B
  countTimer = false;
}, 5000)
```
関数Aが発火後、countTimerで時間を計測。5秒間に再度関数Aが発火しなければ
関数Bが発火するような内容です。

#　参考
Javascriptでタイムリセット機能付きで遅延実行させる方法
https://xov.jp/e/281/
SwiftUI Text 復習

#今回の内容

<img width="150" alt="4A1F4581-8956-4BE9-B428-46F62032E0BC_4_5005_c.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/3534a9c7-ffe1-39ae-e713-67a8aa6efa5d.jpeg">

#コードと簡単解説

* `List`に`Text`を表示するだけの復習方法です。
* `.font()`は文字の大きさや見た目を変更できます。
* `.font(.system(size: CGFloat))`は自分で決めた大きさに`size`を変更できます。
* `.fontWeight()`は文字の太さを変更できます。
* `.foregroundColor()`は色を設定する事ができます。
* `.frame()` は幅や高さなどを設定できます。
* `.border()`は枠線の様なものを色などを設定して表示できます。 

```Swift:
import SwiftUI

struct ContentView: View {
    var body: some View {
        
        NavigationView{
            List{
                HStack{
                    Text("SwiftUILesson01")
                        .font(.title)
                    Text(".font(.title)を使用")
                }
                
                HStack {
                    Text("SwiftUILesson02")
                        .font(.system(size: 30))
                        .fontWeight(.bold)
                    Text(".font(.system(size: 30)).fontWeight(.bold)を使用")
                }.padding(.vertical, 40)
                
                HStack {
                    Text("SwiftUILesson03")
                        .font(.title2)
                        .foregroundColor(.green)
                    Text(".font(.title2).foregroundColor(.green)を使用")
                }.padding(.vertical, 20)
                
                VStack {
                    Text("SwiftUILesson04").frame(width: 375, height: 100).border(Color.orange, width: 10)
                    Text(".frame(width:375,height:100).border(Color.orange, width: 10)を使用").frame(width:375)
                }.padding(.vertical, 30)
                
                HStack {
                    Text("SwiftUILesson05").font(.headline).foregroundColor(.orange)
                    
                    Text(".font(.headline).foregroundColor(.orange)を使用")
                }.padding(.vertical, 30)
                
                VStack {
                    Text("SwiftUILesson06").font(.largeTitle).bold().foregroundColor(.red)
                    Text(".font(.largeTitle).bold().foregroundColor(.red)を使用").padding(.top, 20)
                }.padding(.vertical, 30)
                
            }.navigationTitle("Text復習")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

```

# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
goldenファイルを使用したテストデータとgo structのマッピング

# 概要
- DDDアーキテクチャで構築したプロジェクトにて、usecase層のテストを書こうとした。
- しかし、usecase層からは抽象化されたrepositoryを経由してDBアクセスしているため、repositoryの実装クラスからのDBアクセスをテストでどのように再現するかに行き詰まった。
- そこで、抽象化されたrepositoryを継承するmockを用意し、実装ではダミーのDBデータを返却するようにした。
- その際のデータ管理にgoldenファイルを使用し、go構造体とマッピングすることによりダミーのDBデータ返却を実現した。
- 本記事の内容ではmockやinterfaceといった作法は無視して書きます。(ソース用意するのが大変なので。。。)

# goldenファイルとは
- JSON構造のファイルのこと。
- goの構造体のフィールド名、あるいは `json:"title,omitempty"``といった記述にマッピングすることができる。

# 前提

- go v1.17.2
- github.com/google/go-cmp v0.5.5
- 構造体比較のためにgo-cmpを使用しています。その他は標準ライブラリで実現しました。

# 1. goldenファイル読み出し処理の作成

- `goldenPath()`は引数のファイル名を受け取ってファイルパスを読み出す。
- 今回は`dummydata`というパッケージにgoldenファイルを格納する想定。
- `loadGoldenFile()`はファイルパスを受け取って、goldenファイルを読み出す。
- その後、goldenファイルのJSON構造を、引数で受け取ったobjにマッピングする。

```go
func goldenPath(file string) string {
	return filepath.Join("dummydata", file)
}

func loadGoldenFile(t *testing.T, path string, obj interface{}) error {
	golden, err := ioutil.ReadFile(path)
	if err != nil {
		t.Fatalf("unable to read file: %s", err)
	}

	if err := json.Unmarshal(golden, &obj); err != nil {
		t.Fatalf("unable to read file: %s", err)
	}

	return nil
}
```

# 2. 構造体の定義

- この構造体がgoldenファイルのフィールド値と対応する。
- `json:"title"``で対応させることもできますが今回は省略。

```go
type Qiita struct {
	data QiitaData
}

type QiitaData struct {
	Title       string
	Description string
}
```

# 3. goldenファイルの作成

- いつも通りのjsonファイルですが、ファイル名は`test_qiita.golden`としています。
- Keyの方は上記で定義した構造体のフィールド名と一致させてください。

```json
{
    "Title": "qiitaTitle",
    "Description": "qiitaDescription"
}
```

# 4. goldenファイルを使った構造体の初期化処理

- 上の手順で作成した`loadGoldenFile()`と構造体をここで使用しています。
- 別にこだわる理由もないのですが、ファイルパスは引数で渡せるようにしました。

```go
func NewQiita(t *testing.T, path string) *Qiita {
	var d QiitaData
	if err := loadGoldenFile(t, path, &d); err != nil {
		t.Fatal(err)
	}

	return &Qiita{
		data: d,
	}
}
```

# 5. テストの作成

- 上記で準備したメソッドや構造体を使用して、構造体のdiffを検証するテストを作成しました。
- 変数qiitaがgoldenファイルから読み出した構造体
- 変数wantQiitaが期待する構造体の値をハードコーディングしてます。
- `ignore := []cmp.Option{cmpopts.IgnoreUnexported(Qiita{})}`は非公開フィールドが持っていてもdiff検証をできるようにするためのオプションです。
- このテストコードを実行すると、テストがパスするはずです。
- テストがパスする = goldenファイルで定義した値が構造体にマッピングされている、と言えます。

```go
func TestQiita(t *testing.T) {
	ignore := []cmp.Option{cmpopts.IgnoreUnexported(Qiita{})}
	testTable := []struct {
		name      string
		qiita     *Qiita
		wantQiita *Qiita
	}{
		{
			name:  "Test_Qiita_OK",
			qiita: NewQiita(t, goldenPath("test_qiita.golden")),
			wantQiita: &Qiita{
				data: QiitaData{
					Title:       "qiitaTitle",
					Description: "qiitaDescription",
				},
			},
		},
	}

	for _, tt := range testTable {
		test := tt
		qiita := test.qiita
		wantQiita := test.wantQiita

		if diff := cmp.Diff(qiita, wantQiita, ignore...); diff != "" {
			t.Errorf("the value of the structure is different diff: %s", diff)
		}
	}
}
```

# あとがき
- goldenファイルから構造体へのマッピング手法が分かったのではと思います。
- 実案件のコードでは、`NewQiita(t, goldenPath("test_qiita.golden"))`でmockを生成します。
- 一番下のfor文のところでmockのメソッドを呼び出すことで、goldenファイルで定義した値を返却値として受け取る、ような実装としています。

# 所感
- ほんとはテスト用DBを用意するのがよりよいのかな。。。
- repositoryの実装クラスでは当然DBアクセスをするためのクエリがあるので、そこを完全に無視ししてテストすることになってしまっているので・・
PowerBI: SandDance が cool

# 背景

XY 軸をそれぞれ切り替えてグラフを表示したい、という要望に対し悩んでた際に紹介された Visual が素敵だったので紹介

# Sample 動画

- 動きが素早い
- X/Y/Z + Color + Facet で複数軸での分析にはかなり便利
- 履歴から、過去に見たViewにすぐ戻せる
- 検索も可能
- Data Browser でグラフ内のどこに対象データがあるかを閲覧可能

![Copy＆Paste2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6b3d6d45-9729-dc7c-c192-fada3d227899.gif)

https://appsource.microsoft.com/en-us/product/power-bi-visuals/WA200000430
C#でテスト駆動開発できるようにする為のメモ


Visual Studio 2019 で、新規プロジェクト作成と同時に、テスト用のプロジェクトも作成し、テスト駆動開発できるようにする為の覚え書きです。
前提として、個人でC#を勉強中の身に過ぎず、プログラマとしての業務経験はありません。テスト駆動ってこんな感じかなーと探り探り進めている状態です。

使用製品

+ Microsoft Visual Studio Community 2019 Version 16.11.4
+ MsTest

なぜMSTest かというと、[参考にしたサイト](https://anderson02.com/cs/tdd/tdd1/)が MSTest を使っていたからです。
## プロジェクト作成時にやること
+ 新規プロジェクトを作成する
+  テスト用のプロジェクトを作成する
 + 作成したプロジェクトの親になるソリューションを右クリック→追加 → 新しいプロジェクト
 + 「新しいプロジェクトを追加」画面で、「単体テスト プロジェクト (.NET Framework)を選択
 + ![20211020-単体テストの追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128918/fe82f7d9-3a20-6e86-2aef-b9b888968b9a.png)
 + 「新しいプロジェクトを構成します」画面になるので、テスト用プロジェクトのプロジェクト名を入力。場所はソリューションのフォルダと同じでよい

+ プロジェクト間の参照設定をする
 + ソリューションエクスプローラで、テスト用プロジェクトの「参照」を右クリック→参照の追加→
  + 「参照マネージャー」でプロジェクトタブを選択 → テスト対象のプロジェクト(最初に新規作成したプロジェクト)にチェックを入れる
+ テスト用クラスのテンプレートをインポートする
    + テスト用プロジェクトを右クリック → 追加 → 既存の項目
    + または Shift + Alt + A

### テスト用クラスのテンプレート
```C#：UnitTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace UnitTest
{
    [TestClass]
    public class UnitTest1
    {
        static Namespace.Class1 _TargetClass = null;

        // テスト前の処理
        [ClassInitialize()]
        public static void ClassInitialize(TestContext testContext)
        {
            _TargetClass = new Namespace.Class1 ();
        }

        // テスト後の処理
        [ClassCleanup()]
        public static void ClassCleanup()
        {
            _TargetClass = null;
        }

        //テスト本体
        [TestMethod()]
        public void Class1_Test()
        {
        }

    }
}
```

## テストを書いていく際の備忘録
### プライベートメソッドをテストしたい場合
> privateメソッドをテストするには、PrivateObjectクラスのInvokeメソッドを使用します。
> [山本隆の開発日誌 - MSTestでprivateメソッドをテストする](https://www.gesource.jp/weblog/?p=7742)

その他、private static、親クラスのprivate メソッド等々、privateメソッドのテストについては上記ページで事足りる。

:::note warn
なお、.NET Core では PrivateObject クラスが廃止されており、private メソッドのテストは推奨されない模様
:::
[PrivateObject and PrivateType are not available for a project targeting netcorapp2.0 #366](https://github.com/Microsoft/testfx/issues/366)
Xcode Device orientation が反映されいない

## 環境  
- MacOS Big Sur 11.6
- Xcode 13.0
- Swift 5.5

### 状況
Xcode13, Device Orientation で Portrait のみに check を入れてアプリの向きを縦に固定したが、スマホを横にすると画面が回転してしまう。
![スクリーンショット 2021-10-21 21.34.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289687/719cb219-0104-91dc-34b8-d04f2b67cc03.png)


### 解決
`TARGETS` -> `Info` -> `Supported interface orientations (iPhone)` に設定が残っていたので削除。![スクリーンショット 2021-10-21 21.34.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289687/85dbb75f-827f-7639-300f-30a6c4684c37.png)
SMTPlan+を動かす

# 概要
SMTPlan+は，自動計画（Automated planning）の分野でPDDL（Planning Domain Definition Language）で記述された問題を解くソルバーの一つです．Githubでソースコードが公開されていますが最新の環境ではビルドできません．

issueにビルドできた環境の書き込みがあったため，それを参考にすることで私の環境でもビルドすることができました．
必要な環境を構築するための説明が結構散らばっていたので，この記事では具体的なコマンドについて備忘録を兼ねて投稿したいと思います．

# SMTPlan+とは
[SMTPlan+](https://github.com/KCL-Planning/SMTPlan)は，ロンドン大学キングス・カレッジの[Planningグループ](https://nms.kcl.ac.uk/planning/index.html)が開発したPDDLソルバーです．
SMTPlan+は，いくつかに分かれるPDDLのバージョンのうちPDDL+に対応しており，ひとつ前のバージョンであるPDDL2.1に対して，

* Nonlinear change
* Processes
* Events
* Timed Initial Literals
* Epsilon separation
* Cascading events

といったより複雑な内容をもつ問題を解くことが可能です．

詳細なアルゴリズムについては，[プロジェクトサイト](http://kcl-planning.github.io/SMTPlan/)と[論文](http://www.aaai.org/ocs/index.php/ICAPS/ICAPS16/paper/view/13101/12664)が参考になります．

# SMTPlan+のビルド
それでは実際にビルドしていきたいと思います．

## 参考にしたもの
SMTPlan+は最終更新日が2019年であるためか，最新のビルド環境や依存ライブラリでは素直にビルドできません．
[Githubページ](https://github.com/KCL-Planning/SMTPlan)の[issue](https://github.com/KCL-Planning/SMTPlan/issues/5)の最終投稿にビルドできた例があるので，この情報を参考にビルドしていきたいと思います．

gccやCMakeのダウングレードが必要なため，私は仮想環境を用意しビルドを行いました．

## Dockerの準備
私は公式のgccのイメージをベースにしていくことにしました．gccはバージョン7.4.0である必要があります．

```
docker pull gcc:7.4.0
docker run -it gcc:7.4.0 
```

## その他準備
CMakeLists.txtの書き換えが必要なので，なにかしらのエディタをインストールします．

```
sudo apt update
sudo apt install nano
```

## CMake
CMakeはバージョン3.10.2である必要があります．

```
wget -O cmake-3.10.2.tar.gz https://cmake.org/files/v3.10/cmake-3.10.2.tar.gz
tar xzvf cmake-3.10.2.tar.gz
cd cmake-3.10.2
./bootstrap && make && make install
```

## Boost
Boostはバージョン1.56.0である必要があります．

```
git clone https://github.com/boostorg/boost.git
cd boost
git checkout refs/tags/boost-1.56.0
git submodule update --init --recursive
sudo apt install python-dev
./bootstrap.sh --prefix=/usr/
./b2
sudo ./b2 install
```

## piranha
piranhaはバージョン0.10である必要があります．

```
wget -O piranha-0.10.tar.gz https://github.com/bluescarni/piranha/archive/refs/tags/v0.10.tar.gz
tar xzvf piranha-0.10.tar.gz
cd piranha-0.10
sudo apt install libmpfr-dev
mkdir build
cd build
cmake ../
sudo make install
```

## mp++
mp++はバージョン0.9である必要があります．

```
wget -O mppp-0.9.tar.gz https://github.com/bluescarni/mppp/archive/refs/tags/v0.9.tar.gz
tar xzvf mppp-0.9.tar.gz
cd mppp-0.9
mkdir build
cd build
cmake ../
sudo make install
```

## z3
```
wget -O z3.tar.gz https://github.com/Z3Prover/z3/archive/refs/heads/master.tar.gz
tar xzvf z3.tar.gz
cd z3-master
python scripts/mk_make.py
cd build
make
sudo make install
```

## SMTPlan
いよいよ本体です！

```
wget -O SMTPlan.tar.gz https://github.com/KCL-Planning/SMTPlan/archive/refs/heads/master.tar.gz
tar xzvf SMTPlan.tar.gz
cd SMTPlan-master/SMTPlan
sudo apt install flex
```

CMakelists.txtの書き換えを行います．12行目の

```
set(CMAKE_CXX_FLAGS "-std=c++0x")
```

を以下に書き換えます．

```
set(CMAKE_CXX_FLAGS "-std=c++0x -pthread")
```

続いてビルドを行っていきます．

```
mkdir build
cd build
cmake ..
make -j4
```

## 事後処理
出来た実行ファイルをパスが通っているところに置いておきたかったのでコピーしました．

```
cp SMTPlan-master/SMTPlan/build/SMTPlan /usr/local/bin/  
```

# 動作確認
TBD
テーブル要素内の文字列の折り返し方法

# テーブル要素内の文字列の折り返し方法


```css
table.table td {
  word-break: break-all;
  word-break: break-word;
}
```

---
### 会社紹介

**株式会社 Mosaica**  
最先端テクノロジーで社会課題を解決し、持続可能な未来を創造する IT カンパニー。
AI ソリューション、クラウド統合、DX 推進、経営コンサルティングなど包括的なサービスでビジネス変革を支援しています。  

詳しくは [公式サイト](https://mosaica.co.jp/) までお気軽にご相談ください。
公式サイト： https://mosaica.co.jp/
ラベルなしのチェックボックスをカスタマイズする方法


# はじめに

チェックボックスをCSSでカスタマイズする方法は他のいろんな記事にまとめられていましたが、
よく書かれていたのは__ラベルつき__のチェックボックスのカスタマイズする方法でした。

そこでこの記事では、__ラベルのないチェックボックスのみ__をカスタマイズする方法をまとめましたので、どなたかの参考になればなと思います。

# ラベルなしのチェックボックスをカスタマイズする方法

#### before

<img width="130" alt="before" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308256/8e0c667b-6792-795f-9f6c-7731ede328b3.png">

#### after
 
<img width="130" alt="after" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308256/27e4ddf2-e2f8-1e78-d947-d69834ff4801.png">


### サンプルコード

擬似要素（:after）を使って、擬似要素にCSSを適用するイメージです。

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <style type="text/css">
        input[type='checkbox']:after{
            line-height: 1.5em;
            content: '';
            display: inline-block;
            width: 18px;
            height: 18px;
            margin-top: -4px;
            margin-left: -4px;
            border: 1px solid rgb(192,192,192);
            border-radius: 0.25em;
            background: rgb(224,224,224);
        }
        input[type='checkbox']:checked:after {
            width: 15px;
            height: 15px;
            border: 3px solid #00ff00;
        }
    </style>
    <title>click test</title>
  </head>
  <body>
    <table border="1">
        <tr>
            <th></th>
            <th>名前</th>
            <th>年齢</th>
        </tr>
        <tr class='box'>
            <td class='pointer'><input type="checkbox" id="test_1"></td>
            <td>田中</td>
            <td>27</td>
        </tr>
        <tr class='box'>
            <td class='pointer'><input type="checkbox" id="test_2"></td>
            <td>佐藤</td>
            <td>42</td>
        </tr>
    </table>
  </body>
</html>
```

# 参考
* Styling a checkbox without the label tag
    * https://stackoverflow.com/questions/39958290/styling-a-checkbox-without-the-label-tag

---
### 会社紹介

**株式会社 Mosaica**  
最先端テクノロジーで社会課題を解決し、持続可能な未来を創造する IT カンパニー。
AI ソリューション、クラウド統合、DX 推進、経営コンサルティングなど包括的なサービスでビジネス変革を支援しています。  

詳しくは [公式サイト](https://mosaica.co.jp/) までお気軽にご相談ください。
公式サイト： https://mosaica.co.jp/
Flutterで複数のStreamをまとめて受け取る

## はじめに
一つの画面で複数のStreamを受け取りたいときに困ったので、調べた結果をまとめる。
結論から言うと、`stream_transform`をimportして`combineLatestAll`を使えば良い。

https://pub.dev/packages/stream_transform

## 困ったこと
### 実現したい挙動

投稿一覧画面で、投稿一覧を表示。
ログインしているユーザが各投稿にお気に入りをしてる場合としていない場合で表示するアイコンを切り替える。
<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270898/ca0434e7-6228-3a6a-e578-ec6ce76b49be.jpeg">


### 困ったこと

StreamとしてFirebaseから投稿一覧を取ってきつつ、同様にログインしているユーザがお気に入りに登録している投稿の一覧をStreamとして取得したい。
だが、StreamBuilderやFutureBuilderの中に入れるにしても、複数の処理を引数に取れないっぽいので、困った。

## 解決方法
`stream_transform`のパッケージを使う。
以下のように、Streamをまとめることができる。

```dart:
Stream<Map<String, dynamic>> streamName() {
    return stream1().combineLatestAll([stream2, stream3()]).map((data) {
      return { "stream1": data[0], "stream2": data[1], "stream3": data[2] };
    });
  }
```

こうすれば、`streamBuilder`とかで`streamName()`を入れてデータをまとめて受け取ることができる。

## 参照ページ

以下のような記事を見て、packageの存在を知った。

https://stackoverflow.com/questions/54169982/how-we-can-mix-streams-in-dart

https://stackoverflow.com/questions/36571924/how-can-i-merge-multiple-streams-into-a-higher-level-stream/55912217#55912217
これさえ守ればOK！ダサダサUIデザインを作る、4つのポイント

毎週エンジニア・初学者のデザインレビューをする中で、みんながよくやりがちなダサダサデザインを元に、Tipsをまとめてみました。

これを守るだけで、どんなイケイケエンジニアも、一発でダサダサにすることができます。
嫌いな人には、これをやると誰でもプロのデザインができるらしいよ！と伝えましょう。（※自己責任にて！）

## &nbsp;① シャドウは濃く！ 🌚

せっかく影をつけるのだから、影があることをしっかりアピールしましょう！
私のことは忘れても、影のことは忘れないで..！
![Group 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356874/cf1ceb95-59e6-276d-32c5-48f9e78faef8.png)


## &nbsp;② 余白は詰める！ 🏢🏢🏢🏢

洗練されたデザインを作るのに、適切な余白は欠かせません！
ムダなスペースを作らないよう、入れられるだけの情報を詰め込みましょう。
ビュッフェバイキングもお皿に取れるだけ乗せますよね？
![Group 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356874/9c1b9891-6620-e6d5-6317-a91020453239.png)


## &nbsp;③ 要素は自由に＆気ままに並べよう	😌

文字は読めれば問題ないですよね？
バランスはアート。
直感に任せて、自由にレイアウトしましょう。
![Group 13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356874/c99612e0-6e25-bfd5-0070-2b388fb0f483.png)


## &nbsp;④ 色ははっきり！白黒つけて 🐼
サーモンピンク？パステルピンク？ローズピンク？フューシャピンク？
どれも同じようなもの！ピンクでいいでしょう。コードの記述もラクだし。
うーん..でも、ピンクはかわいくなっちゃうな、ここは目立つ水色にしようか。
あとは普通に真っ黒が無難で良いでしょう。普通がいちばん。
![Group 14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356874/b1184d5c-b615-c3c3-8e9e-d41cd903f887.png)

たったこれだけ。かんたんですね！
これであなたも、明日からプロのデザイナー！！！
pyenv globalが出来ない時の対処法

## エラー内容
`pyenv global 3.6.X`をしたのにも関わらず、`pyenv versions`では変化が見られなかった。

## 原因
ホームディレクトリで`pyenv local 3.X.X`などをしてしまうのが問題。
`pyenv local`コマンドで生成された`~/.python-version`ファイルが悪さをして上書きループに入ってしまっている。

## 対処法
・下記コマンドを実行

```
chmod +x ~/.python-version
rm -rf ~/.python-version
```

　・`ls -la`でファイルがないのを確認できたらOK
見なきゃ損！人工知能AIとはなんぞや！？ゆっくり解説

人間の知能（頭の働き）のしくみを人工的に実現することです。

ロボット開発が進歩するにつれて、AIが注目されています。

今までのロボットは、人より強く正確で長時間動くことができ、人の代わりに大量の仕事をするものでした。

しかし、ロボットが自分で判断することは無く、人が状況に応じて動く順序を決めていました。
また、動く順序をプログラミングしてロボットに伝えていました。

映画とかで見るロボットは、当たり前のように人と会話したり、自分で動いたりしていますが、まだまだ未来のことだと思われていましたが・・・。



これからのロボットは、人口知能の発展でPepperのように会話するロボットがいよいよ出現してきました。

人口知能は人と同じで学習することから始まります。これは以下のように２つに分けることができます。

・機械学習

・深層学習（ディープラニング）


（次回につづく…）


https://programingo.com/%e4%ba%ba%e5%8f%a3%e7%9f%a5%e8%83%bdai%e3%81%a8%e3%81%af/