OmniAICreator/Qiita-1.07M huggingface dataset:
Salesforceのワークフロールールで新規Todoを作成しよう

ToDoとは、今後の活動をするための予定です。

たとえば、
・商談を受注したら必ずそのあと書類を送る

など、やらなきゃいけない業務ってありますよね。

そのやらないといけない業務の予定を立てれるのがToDoです。

ToDoの見え方として、下記画像のように活動の履歴として一覧に表示されます

このようにやること一覧がだらっと表で表示されるのは分かりやすいですね

![活動１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/aaaf9530-255c-24c7-8ae4-2b62342f1ac2.png)

さて、このTodoですが実はワークフロールールで自動で作成することが可能です。

例えば
「商談が受注したら必ず〇日以内に書類を送る」という業務があったとしましょう

そのさい、ワークフロールールを作成し
・商談受注した瞬間、ToDo自動作成

が可能です。

ToDo作成アクションは以下の場所から作成可能です

![todo作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/e2abbefe-541c-2422-30d4-4d114b15da5c.png)


このToDo作成後、ワークフロールールの「既存アクションの選択」からToDoを選択します。
![既存アクション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/3dc6c7cc-2717-5159-e993-4de95f210c8f.png)

このように設定すれば、一度作成した新規ToDoを複数のワークフロールールで使いまわすことが可能です。


最後にワークフロールールの新規ToDoの注意点について説明します。
![todo割当先.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/4eb8ad97-98c7-8968-8644-a0bc9e29ec7a.png)


##ToDo割当先設定の注意点

###注意点１
ToDoで割り当て可能なユーザはToDo割り当て可能な権限があるユーザのみです。
つまり、Chatterユーザなど権限が少ないユーザは割り当てユーザの設定ができないのでご注意ください

###注意点2
割当先に設定できるユーザは基本１ユーザです。
しかし「ロール」を選択すればそのロールに属するユーザ（つまりロールに所属する複数ユーザ）の設定が可能です。

とはいえ、下記のヘルプ記載のように複数のユーザを割当先に設定することは好ましくない設定のようです

＞ワークフロー ToDo の割り当て先がロールであり、1 人または複数のユーザがそのロールに属している場合、レコード所有者が、当人のロールに関係なく ToDo の割り当て先になります。複数のユーザが属するロールに ToDo を割り当てないことをお勧めします。ToDo を 1 人のユーザのロールに割り当てると、ワークフロールールを変更せずに、そのロールのユーザを簡単に変更できます。ワークフロー ToDo の割り当て先がロールであり、そのロールが空である場合、レコード所有者が、当人のロールに関係なく ToDo の割り当て先になります。

参考ヘルプ：
ToDoアクション
https://help.salesforce.com/s/articleView?id=sf.customize_wftasks.htm&type=5
プログラミング初心者がjavaを触ってみる１　そもそもjavaって何だ？

#はじめに
現在プログラミング学習を始め5ヶ月目の初学者です。
学んだことをqiitaに投稿という形でアウトプットするため、また備忘録として記事を作成しています。
javaはprogateで軽く触れたことがあるだけですので、改めて基礎的な知識から学習していこうと思います。

macでの環境構築で下記の記事が大変参考になりました。

https://qiita.com/suke_masa/items/f9af0fb84ad9447ae961

##java特徴
###1.JVM（Java Virtual Machine：Java仮想マシン）で動いている
このJVMが動いているコンピュータであればOSがmacでもwindowsでもLinuxでも、どんな環境であれ動作する。

###2.オブジェクト指向で作られている
javaでプログラミングするにはこのオブジェクト指向という考え方が重要

_オブジェクト思考とは？_
モノ（オブジェクト）を同士を関係させ、組み立てていくプログラミングの考え方のこと
例えば机を作る時大きな木材を切り出して作るのは大変だが、天板、足４本と分けて作成すれば簡単に出来る
開発を効率的に進めるためには必要な考え方

###3.高い人気と需要
2021年の実質的なシェアがわかるGitHubリポジトリのプロジェクトベースの言語ランキングと、W3Sによる勧告やプログラミング教育における採択といったITトレンドを反映したランキングでは数ある言語の中で堂々の3位

##最後に
qiitaへの投稿に慣れていないので、分かりづらい上に情報が少ないですが、これから欠かさず投稿していこうと思います。
なぜヒープ化 (heapify) は O(N) で可能なのか

# ヒープとは
ヒープとはデータ構造の一種であり、親要素が子要素よりも常に大きい（あるいは小さい）という特徴を持つ木構造です。つまり、ヒープの根が最大値（あるいは最小値）になり、$O(1)$ で参照することができます。またデータの挿入や最大値（あるいは最小値）の削除も $O(\log{N})$ と高速で可能なことから、優先度付きキューの実装としても利用されています。本記事では、特に二分木を使用した二分ヒープについて扱います。

# ヒープ化にかかる計算量
ヒープ化されてない配列からヒープを作成する場合の計算量についてですが、1つのデータの挿入に $O(\log{N})$ 要することから考えると、直感的には $O(N\log{N})$ になりそうですが、実際には $O(N)$ で可能です。一例として、Python の heapq の実装にも線形時間でリストをヒープに変換するとの記述があります。

[heapq — Heap queue algorithm — Python 3.10.1 documentation](https://docs.python.org/3/library/heapq.html#heapq.heapify)
> Transform list x into a heap, in-place, in **linear** time.

$O(N)$ のヒープ化では、上記のように一つずつ値を挿入するのではなく、ヒープ化されていない配列に対してヒープの条件を満たすように値を交換していく（これが in-place に相当する）ことでヒープを作成します。

具体例を挙げながら見てみましょう。ここでは親ノードより子ノードが大きい条件を満たす、最大ヒープを作成します。

1. 最も左にあるのが初期状態です。親ノードより子ノードが大きいという条件を満たしていません。ここから、ヒープの下の方から上の方へと順にヒープ条件を満たすように値を交換していきます。
1. まず、最も深いノードである 2、6、4、7 については子のノードを持っていないので操作は必要はありません。
1. 次に、値が 5 のノードとそれより下にあるノードがヒープの条件を満たすように値を交換します。ここでは、5 と 7 を交換します。これにより、親が 7 で子が 4 と 5 になり、ヒープ条件を満たしました。
1. 同様に 1 と 6 を交換することで、親が 6、子が 1 と 2 になりヒープ条件を満たします。
1. 最後に、最も親のノードとそれより下にあるノードがヒープ条件を満たすように値を交換します。3 と 7、次いで 3 と 5 の値を交換することで全てのノードにおいてヒープ条件が満たされます。

![heapify-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165029/6e109b4c-88c1-ad4f-e2c2-89dda329ed38.png)

この操作にかかる計算量を考えると、注目したノードとそれより下にあるノードがヒープ条件を満たすために、自分より下のノードの深さに比例する計算量が必要になります（詳細はここでは割愛しますが、heapq の実装[^1]などを読むと理解できるはずです）そして深さに比例する計算量をその深さのノード数分だけ行うことになります。二分木の構造上、深さの浅いノードが大半を占めるので、感覚的にも $O(N\log{N})$ かからなそうな気がしてきましたね。

<img width="400" alt="heap-order.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165029/bcb0f2fa-4af5-bcb0-760c-e9f7141079b0.png">

一般化してみましょう。
まず、必要な式変形を確認します。$|x|<1$ を満たす場合の無限等比級数の和と、その微分は以下のように表されます。

```math
\sum_{j=0}^{\infty}x^j = \frac{1}{1-x}
```

```math
\sum_{j=0}^{\infty}jx^{j-1} = \frac{1}{(1-x)^2}
```
微分した式に $x$ をかけると以下の式が得られます。

```math
\sum_{j=0}^{\infty}jx^{j} = \frac{x}{(1-x)^2}
```

これを利用すると、ヒープ化に必要な計算量は以下のようになります。ここでは、高さ（深さ）を $h = \lfloor \log{N} \rfloor$ と定義します。（$\lfloor \ \rfloor$ は floor 関数で、小数点以下を切り捨てます）

```math
\begin{align}
\sum_{j=0}^{h}j \cdot 2^{h-j} &= 2^h \sum_{j=0}^{h}\frac{j}{2^j} \\
&\leq 2^h \cdot 2 \\
&\in O(N)
\end{align}
```

このようにしてヒープ化は $O(N)$ で計算できることが確認できました。

# ヒープソートにかかる計算量
ヒープ化は $O(N)$ で可能ですが、あくまでヒープはソートとは異なり、最大値（あるいは最小値）を取り出すことしかできません。そのためヒープを利用してソートを行うヒープソートでは、$O(\log{N})$ の取り出しを $N$ 回行う必要があり、計算量が $O(N\log{N})$ になる点には注意が必要です。

# まとめ
- ヒープ化は、ヒープの下から上へと順にヒープ条件を満たすように値を交換することで、$O(N)$ で計算できる。
- ヒープソートはあくまで $O(N\log{N})$ 要する。

[^1]: [cpython/heapq.py at 3.10 · python/cpython](https://github.com/python/cpython/blob/3.10/Lib/heapq.py#L168)
PHPでのCSV出力時、先頭の０が消える

WordPressでCSV出力をする際、数字を文字列として扱いたい。
000123みたいな出力にしたいのに、普通にやるとできない。
変な文字列を突っ込んで力技で文字列にした方がいいのかしらんと調べた結果。

https://norm-nois.com/blog/archives/3073

なるほど？？？？？
GASとSlackで芸能人の結婚ニュースを教えてくれるbotを作る

# はじめに
- Slackで遊びたい
- 業務の都合上、芸能人の結婚ニュースをいち早く知りたい（パパラッチではない）

という理由から、botを作ってみました。
自分のメモ用なので、説明雑です。すいません。

# 作り方
## Slackアプリを作る
以下の記事を参考にさせてもらいました。
https://qiita.com/njn0te/items/097086f378873fca0510
https://qiita.com/kakakaori830/items/660f0d78435bfd60dcc9

## マニフェストを編集
SeetingsのApp Manifestを編集。
botの権限を設定する（試行錯誤しながらだったので不要な権限入ってるかも）

```manifest.yml
_metadata:
  major_version: 1
  minor_version: 1
display_information:
  name: Gossip Madam
features:
  bot_user:
    display_name: Gossip Madam
    always_online: true
oauth_config:
  scopes:
    bot:
      - channels:history
      - chat:write
      - incoming-webhook
settings:
  org_deploy_enabled: false
  socket_mode_enabled: false
  token_rotation_enabled: false
```

## ワークスペースに追加
同じくSettingsのIncoming WebhookからURLを作成。
ここでbotが投稿する対象チャンネルを指定します。
生成したURLは後で使う

## スクリプト作成
GASを使います。

```gossipMadam.js
function gossipMadam() {
  // オリコンニュースをスクレイピング
  var url = "https://www.oricon.co.jp/news/tag/id/news_marriage/";
  var content = UrlFetchApp.fetch(url).getContentText("Shift-JIS");
  var title  = Parser.data(content).from('<h2 class="title">').to('</h2>').build();  
  
  // スプレッドシートから前回実行時のタイトルを取得 
  var id = "XXX"; // スプレッドシートのID
  var ss = SpreadsheetApp.openById(id);
  var sheet = ss.getSheetByName("title");
  var preTitle = sheet.getRange("a1").getValue();

  // 異なるタイトルだったらSlack投稿
  if(preTitle != title){
    sheet.getRange("a1").setValue(title);
    var slackUrl = "https://hooks.slack.com/services/XXX"; // SlackのWebhook URL
    var greeting = "ねえ聞いた？また芸能人が結婚したらしいわよ\n"
    var ending = "\n他にも私が知らないニュースがあるかもしれないわ\n"
    var options = {
      "method" : "POST",
      "headers": {"Content-type": "application/json"},
      "payload" : '{"text":"' + greeting + title + ending + url +   '"}'
    };
    UrlFetchApp.fetch(slackUrl, options).getContentText();
  }
}
```

1. オリコンニュースをスクレイピング（オリコンさんありがとうございます）
1. 最新記事のタイトルを取得
1. 前回取得したタイトルと異なっていれば、Slackで投稿

という感じに処理を組んでいます。
これを任意のタイミングでGASトリガーを設定すれば完成です。

# 最後に
「とりあえず動けばいいか」というスタンスで作っているので、以下が気に入らない点です。

- 更新に応じたタイムリーなスクリプト実行ができないので、トリガーをいくつも設定しないといけない。
    - あんまり設定するとクロール先のサイトの迷惑になるので、日に2,3回にとどめたい
- 一度スプレッドシートを挟むところがブサイク
- 最新の記事しか取得しないので、実行のインターバルに2つ結婚発表があると投稿から漏れる
    - 投稿時にURLも一緒に投稿して逃げてる

気が向いたら改善するかも？
【EC2でdocker compose upするときにメモリエラーが出たのでswap領域を確保して対応した】

コンテナBuild時にメモリエラーによって、プロセスがkillされてしまうので、なんとかしようと思ってswap領域を確保することにしました。

### swap領域とはなにか？

ハードディスクの一部。メモリが不足した際にメモリの内容を一時的に避難させる場所。

メモリの上限以上の処理をできるようにするために存在する。

## １，AMIにはswap領域が含まれない

t3.micro インスタンスを使用しているが `free -m`で確認してもswap領域はない。
デフォルトでswap領域が確保されているインスタンスもあるが今回利用するt3.microにはなかった
![BCF09D1F-3AB3-43AE-A221-CF976B619EF5_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530710/d833b0a7-2772-c7a5-b0df-4ccd08fcd1b2.jpeg)

## ２，swap領域の確保はEBSでやるかインスタンスストアか？

https://dev.classmethod.jp/articles/ec2linux-swap-bestpractice/

これはEBSの料金体系がI/O回数によるものだった時代の話をしているようで、今ではインスタンスごとのIOPS性能を超えた分だけ追加料金がかかるようになったため料金は変わらないということです。

こういう歴史を知るのは楽しいです。

インスタンスストアでswap領域の確保ができるのは、デフォルトでインスタンスストアが含まれているインスタンスに限られ、以下でサポートされているインスタンスを確認できます。

ちなみに今回swap領域を確保したかったt3.microはサポートされていませんでした。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/InstanceStorage.html#instance-store-volumes

## ３，swap領域を既存のEBSで作成する

free -h で現状のメモリ状況を確認します。

availableが357Mとなっており、すぐに開放可能なキャッシュなどとfreeを合わせると357Mが使える分だ、ということがわかります。
![1DAAC80F-0ADC-47AD-B68C-234A4E481746_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530710/4cd8ce07-4d24-d9d3-e9bb-ed8f77f3e391.jpeg)

**swap領域を確保するbashスクリプト**
`source swapon.sh 2048` で2GB分を作成できる。
これをEC2内で実行する。

```bash
#!/bin/bash

echo "script="$0
echo "arg count="$#

# MB単位で受け取る 例)2GB=2048
SWAP_COUNT=${1}

sudo dd if=/dev/zero of=/swapfile bs=1M count=${SWAP_COUNT}

sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

sudo swapon -s

# sudo 権限で/etc/fstabに書き込み、永続化
sudo sh -c 'echo /swapfile swap swap defaults 0 0 >>/etc/fstab'
```

以上でコンテナビルド時に出るメモリエラーを解決できました。
端点が接続した破線をCSSで描く方法

イラレの破線みたいに端点が接続した破線をCSSで描く方法です。
![dashed-lines1_w500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/6d100437-6f50-03f0-4b7c-b5ce6ba740b7.png)

`border`は使わずに`linear-gradient()`で描いた１つのパターンをボックスの背景画像として上下左右のふちに繰り返し配置します。配置するパターンは下図のAで示した部分になります。
![parts@2x-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/96c25535-c899-b285-913e-8732d0f654ce.png)
ポイントは、`background-repeat: round`で画像Aを繰り返し配置すること。これにより、画像Aが互いに「隙間なく・切り取られることもなく」領域を埋めます。ただし、空間の大きさに帳尻を合わせるために画像は伸縮するので、表示された破線の線分の長さはCSSに指定したpx値から若干変動します。指定するpx値をうまく調整すれば目立ちません。

```html:html
<div class="box dashed">
  <div class="inner"></div>
</div>
```

このサンプルでは、boxの内側を背景色lightcyanで塗りつぶしています。破線の隙間は透明にしたかったので、この背景色がboxのふちに染み出さないようにするためdiv.innerを設置しました。

```css:css
.box {
  box-sizing: border-box;
  width: 80%; /* 適当に */
  padding: 4px; /* innerを設置する場合、線の太さ分あける */
  position: relative;
}
```

擬似要素でboxのoverlayを作り、上下左右のふちに相当する背景画像を一括で描きます。破線の線分の長さ20px, 太さ4px, 隙間10pxです。画像Aに相当する部分の幅は30pxになります。つまり、「塗り10px, 透明10px, 塗り10px」が１セットです。

```css:css
.dashed::before {
  display: block;
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none; /* box内にリンクがある場合、クリック可能にする */
  width: 100%;
  height: 100%;
  background-size: 30px 4px, 30px 4px, /* 上下 */
    4px 30px, 4px 30px; /* 左右 */
  background-position: top left, bottom left,
    top left, top right;
  background-repeat: round no-repeat, round no-repeat,
    no-repeat round, no-repeat round;
  background-image: linear-gradient(to right, blue, blue 10px,
    transparent 10px, transparent 20px, blue 20px),
    linear-gradient(to right, blue, blue 10px,
    transparent 10px, transparent 20px, blue 20px),
    linear-gradient(to bottom, blue, blue 10px,
    transparent 10px, transparent 20px, blue 20px),
    linear-gradient(to bottom, blue, blue 10px,
    transparent 10px, transparent 20px, blue 20px);
}
```

<p class="codepen" data-height="385" data-default-tab="css,result" data-slug-hash="NWayRmw" data-user="kaz_hashimoto" style="height: 385px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kaz_hashimoto/pen/NWayRmw">
  [CSS] corner-aligned dashed lines</a> by Kazuhiro Hashimoto (<a href="https://codepen.io/kaz_hashimoto">@kaz_hashimoto</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
[アルゴリズム]配列の中身を小さい順に並び替えるプログラム

```　Sort.java
アウトプット用!!

#3回目は、
  配列の中身を小さい順に並び変えるプログラムを作っていく！！
  今回はアルゴリズムの勉強も兼ねてあえてjava.utilパッケージにあるArrays.sort(arr)を使用しないでプログラミングをしてみました。

  そこで配列の中身を小さい順に並べるにあたりバブルソート(基本交換法)でやってみました。

  こちらがコードになります。

class Sort {
    public static void main(String[] args) {
        int Sort[] = {8,1,7,5};

        int x;
        int i = 0;

        for(i = 0; i <= Sort.length-2; i++) { //外側のループ（最初の要素から最後の要素の一つ手前に向かって後ろに進む）
            int j = Sort.length-1; //最後の要素
            for(j = Sort.length-1; j>=i+1; j--) { //内側のループ（外側のループの要素の一つ後ろに向かって前に進む。）
                if(Sort[j-1] > Sort[j]) { 
                    x = Sort[j];
                    Sort[j] = Sort[j-1];
                    Sort[j-1] = x;  
                                        //比較して前が大きかったら交換が行われる

                }
            }
            j = j - 1;
          
        }
            i = i + 1;
            
            System.out.println(Arrays.toString(Sort));
        
   }
    
}

```

```
コンソール
[1, 5, 7, 8]
```
```Sort.java
解説

①外側ループ
  for(i = 0; i < Sort.length-2; i++)
  　初期化式に0(最初の要素)から最後の要素の一つ手前に向かって後ろに進む。
  そうすることで、内側ループで隣と比較する時のスタート地点を配列の後ろから前へ向かってできる。

②int j = Sort.length-1;
　　  変数jに配列の最後を代入。

③内側のループ
　　  配列の最後の要素から外側ループの先頭から一つ後ろに向かって前に進む
　  if文で前後を比較して前が大きかったら交換する。

  if(7 > 5)
  は７の方が大きいので交換する
  すると、
  配列の中身は{8,1,5,7}になる

  2>=1なのでjのループ継続

③を繰り返し行う
  if(1 > 5)
  1が小さいので交換はしない。
  配列の中身は{8,1,5,7}になる

  1>=1なのでjのループ継続

③を繰り返し行う
  if(8 > 1)
  8が大きいので交換する
  配列の中身は{1,8,5,7}
  になり配列の最小値1が1番左に来てソート済みになる。

  ０ >= 1は繰り返しできないのでそこでjのループを抜けて

  i = i + 1で変数iに要素を追加して外側のループ処理を開始する。

  これで配列の先頭に最も小さい値が入りソート済みになる。配列[1]から配列[3]で同様に中身を小さい順に並べる。
  配列{8,5,7}
  ①から③を繰り返し行って小さい順にならべていく感じです。


　　

```

```Sort2.java
java.utilパッケージで作成したプログラムも載せときます。

import java.util.Arrays;

class Sort2 {
    public static void main(String[] args) {
        int Sort[] = {8,1,7,5};
        
        Arrays.sort(Sort);
            for(int i = 0; i < Sort.length; i++);
            System.out.println(Arrays.toString(Sort));
        
   }
    
}
アルゴリズムを考えない方が明らかに楽にコードが書けますね

今回はあえてアルゴリズムを意識してプログラムを行いました。
プログラムを行う上でアルゴリズムは大事になってくると思うので、これからもアルゴリズムを意識してプログラムを書いていきたいです。
とりあえず楽しみながら勉強します

おつかれさまでした。



```
[MacOS]のSwiftUIで動的な図形描画

　ターゲットをMacOSとしたSwiftUIで動的な図形描画サンプルです。
##やりたいこと
　SwiftUIを利用して、処理結果をグラフィカルに簡単に画面表示したい。
##サンプルのイメージ
グラフ描画ボタンをクリックするとウインドウ上に折れ線グラフっぽいグラフが描かれます。

計算結果など可変データの図形描画サンプルが少なかったので、サンプル作成してみました。
![スクリーンショット 2022-01-05 15.55.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2471383/ed080413-d989-2777-1dd7-92af993899af.png "実行結果の例")

##サンプル作成の環境
　Swift 5.5.2,  Xcode 13.2.1, M1 Mac
##コードサンプル
細かい点はコード上のコメントを参照ください。

```ContentView.swift
import SwiftUI

// 描画データの構造体
struct MyData {
    var x: CGFloat
    var y: CGFloat
}

struct ContentView: View {
    // 描画データの配列：「@State」定義の変数に変化があると画面は自動的に再描画される。
    @State var lineData: [MyData] = []
    
    var body: some View {
        VStack {
            // 描画先のコンテキスト
            Canvas { context, size in
                // 外部関数呼び出し、描画するパスがセットされる
                let myPath = drawLine(view: self)
                // myPathにセットされた情報で描画する
                context.stroke(myPath,
                               with        : .color(.orange),
                               lineWidth   : 2)
            }
            .frame(width: 400, height: 300)
            .border(Color.blue)
            .background(Color.white)
            
            // 描画するためのアクション
            Button("グラフ描画") {
                // 外部関数呼び出し
                addData(view: self)
            }
            .padding()
        }
    }
}

// 描画データセット：通常は計測データなどセット
func addData(view: ContentView) {
    // サンプルにランダムなデータを生成（説明略）
    view.lineData = []
    for n in 0 ... 10 {
        let x = CGFloat( n * 40 )
        let y = CGFloat.random(in: 50 ..< 250)
        let line = MyData(x: x,
                        y: y)
        view.lineData += [line]
    }
}

// データをパスとして描画
func drawLine(view: ContentView) -> Path {
    // 描画パス
    var myPath = Path()
    // 初期位置セット（キャンパスにペンを置く感じ）
    myPath.move(to: CGPoint(x: 0,
                            y: 0))
    // 配列にセットされたデータで描画
    for data in view.lineData {
        // データ毎にペンを移動させて描く
        myPath.addLine(to: CGPoint(x: data.x,
                                   y: data.y))
    }
    // 描画パスを返す
    return myPath
}

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

##投稿について
　SwiftUIは経験数週間ですが、MacOS利用した記事が少ないので投稿してみました。間違いやもっと良い方法もあるかと思いますが、開発の参考になればと思います。

この方法は、Swiftでシミュレーションや計測などプログラミングした時の結果表示に使っています。
Windowsでclassファイルをデコンパイル

# 経緯
既存のJAVAプログラムを読み解きたい。
そもそもJavaファイルをプログラムとして動かすためにコンパイルしてclassファイルにしているため、逆の手順を踏んで人間が読める形に変換し直す必要がある。

ソースコードからプログラムを生成：コンパイル
プログラムからソースコードを生成：**デコンパイル(逆コンパイル)**

# classファイルをデコンパイルする
以下の手順で行う。

* Amazon Correttoインストール、JAVAのパスを通す
* JADをインストールし、パスを通す
* コマンドプロンプトでデコンパイルを行う
* エラーが出たファイルを逆アセンブルする


## Amazon Corretto インストール、JAVAのパスを通す 
Amazon Corretto は、マルチプラットフォームで本番環境に対応した、無料の Open Java Development Kit (OpenJDK) ディストリビューション。
Linux、Windows、macOS などの一般的なオペレーティングシステムで Javaを簡単に使用することができる。


参考：[Amazon CorrettoをWindows10にインストールする方法](https://www.acrovision.jp/service/aws/?p=2418)

* [Amazon Correttoのダウンロードページ](https://aws.amazon.com/jp/corretto/)にて、任意のバージョンをダウンロード
* 展開し、Cドライブ直下に移動させる。フルパスをコピーする
* 環境変数の設定画面で、「ユーザー環境変数」の「新規」を押下すると「新しいユーザー変数」のウィンドウが表示されるので、「変数名」に「JAVA_HOME」と入力し、「変数値」にコピーしたパスを貼り付け、OKボタンをクリック
* 同じ欄の「Path」を選択。「編集」を押下すると「環境変数名の編集」のウィンドウが表示されるので、右上の「新規」ボタンをクリックし「%JAVA_HOME%¥bin」と入力。「OK」ボタンを押下
* コマンドプロンプトでjava -versionで実行。以下のように表示されれば問題ない

```          
$ java -version                         
openjdk version "17.0.1" 2021-10-19 LTS                           
OpenJDK Runtime Environment Corretto-17.0.1.12.1 (build 17.0.1+12-LTS)                                                  
OpenJDK 64-Bit Server VM Corretto-17.0.1.12.1 (build 17.0.1+12-LTS, mixed mode, sharing)
```

## JADをインストールし、パスを通す
JADは、Javaのデコンパイラ(逆コンパイラ)。JavaのclassファイルのバイトコードをJava言語に変換する。

参考：[javaのclassファイルを逆コンパイルする方法](https://qiita.com/ponsuke0531/items/8a6bcb483607a7330ba0)

* [JAD Decompiler Download](http://www.javadecompilers.com/jad)から任意のバージョンをダウンロード
* 解凍し、jad.exeを$JAVA_HOME/binに格納
* コマンドプロンプトで確認。以下のようになっていれば問題ない

```
$ jad
Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov (jad@kpdus.com).
Usage:    jad [option(s)] <filename(s)>
Options: -a       - generate JVM instructions as comments (annotate)
...省略...
```

## コマンドプロンプトでデコンパイルを行う

* jadコマンドで対象ファイルを逆コンパイルする
* 現在の場所に逆コンパイルされたjadファイルが出力される

```
$ jad C:\～.class
Parsing C:\～.class... Generating ～.jad
```

## エラーが出たファイルを逆アセンブルする
デコンパイルを行った際、以下のようなエラーが出ることがある。

```
Couldn't fully decompile method xxx                                                                                   
Couldn't resolve all exception handlers in method xxx
```

このように逆コンパイルできなかったものについては、アセンブラから動きをトレースする。
デコンパイルと違い、機械語やバイトコードなどで記述されたコンピュータ向けのプログラムを、アセンブリ言語による人間が読めるソースコードに変換する。
jdkに同梱されているjavapを用いる。


参考：
[Kotlinのデータクラスが生成するhashCode()の謎に逆アセンブラで迫る](https://yuyubu.hatenablog.com/entry/2018/03/30/Kotlin%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%8C%E7%94%9F%E6%88%90%E3%81%99%E3%82%8BhashCode%28%29%E3%81%AE%E8%AC%8E%E3%81%AB%E9%80%86%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96)
[javap - Java クラスファイル逆アセンブラ](https://fbrowser.osdn.jp/docs/browse/jdk-6u21/technotes/tools/windows/javap.html)

javapコマンドでclassファイルを逆アセンブルする。オプションに-c(逆アセンブル)を指定
そのまま実行すると結果がコマンドプロンプト上に出力されるため、リダイレクトを使用してファイルに出力

```
$ javap -c C:\～.class  > text1.txt
```
メモ：MS365PowerAutomateの簡単な使い方

自分で適当に設定していたOutlookとTeamsの連携方法のメモ。

# メールを条件判定してTeamsに送る
例えばシステムエラーがメールで送られてくるが、自分に関係ありそうなものをTeamsに飛ばす場合。
これは簡単。

* 新しいメールが届いた時、でフォルダを指定
* 本文や差出人で条件判定（例えば本文に自分の名前が入っているか、等）
* Yesの場合にTemasで自分宛に件名等を送信

# Outlookのスケジュールで予定が近づいたらTeamsに送信
どのように範囲を絞るのかは色々なやり方があるが、
例えば定期的に実行するジョブを作って、teamsに送信する場合

* トリガーを30分毎にして、開始を適当な日の0時55分とかにする。
* 現在時刻取得
* 未来時間取得（例では+65分)
* 現在時刻から未来時刻の間のイベントを取得
* eachループ処理。valueを引数にする
* ループ内ではタイムゾーン変換（チャットに予定を送る際に、協定世界時から日本時間にする）
* teamsで時間とタイトルを送信（例では部分文字列でタイトルを取得させている）

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2081290/2b2a838c-3349-0894-2be8-2858ac577e06.png)


これで毎時55分と25分に65分先までの予定を送信してくれるようになる。
但し会議の最中でも送信されてくるので注意。（終了時間が分かる利点もあるが）

デスクトップ版は無償化当時に少し触ってみたが、ブラウザ内の要素取得がいまいちな感じで、無償のRPAなら[WorkFusion](https://www.workfusion.com/)を使った方がいいかな、というのが触った感想。
【Laravel】実装コード上で.envの値はconfig()で取得する

# 環境

Laravel Framework: 8.56.0
PHP: 8.0

## `env()`では、なぜダメなのか

同じく`.env`の値を取得できるものに、`env()`があります。

![image001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525820/c4433c0c-a734-552b-9b9f-fa299183cf9a.png)

これだけ聞くと、
`config()`でも`env()`でも良いように感じますが、
<font color="#f00">特定状況下で動作させると、**差が明らか**</font>になります。

その特定状況下というのが、
`config:cache`を実行した環境になります。

### `config:cache`って何？

通常では、
設定情報や環境情報を参照する際は、
**コールする度に読み込みに行く**のですが、
これでは<font color="#f00">パフォーマンス（実行速度）が落ちる</font>ことがあります。

そのため、
そういった情報をキャッシュ化することで
**読み込みに行く時間を短縮する**訳です。

つまり、`config:cache`を実行することで
結果的に、<font color="#f00">パフォーマンスが上がる</font>ことに繋がります。

### `.env`が読み込まれない

本番環境では、
パフォーマンスを向上させようと`config:cache`を実行することがあります。

その状況で、
`config()`と`env()`はキャッシュされた情報から取得しようとすると・・・、

<font color="#00f">`config/*.php`の情報は**取得できる**</font>のですが、
<font color="#f00">`.env`の情報は秘匿され、**取得することができません**</font>。

![image002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525820/d208e313-00e9-9fcc-02e2-25c96fcd911e.png)

結果として、
`config()`では取得できるが、`env()`では取得できないということになります。

## 解決方法

では、どうすればよいのか。

それは、`config`ディレクトリに新たなファイルを作成し、
そのファイル内で`env()`をコールして、
`.env`の情報を`config`に持たせることです。

これにより、`config()`で取得することができます。

### 具体例

```php:config/sample.php
<?php

return [
  'want-value' => env('WANT_VALUE'),
];
```

上記の`config`を追加すれば、
以下のように呼び出すことができるようになります。

```php:実装している場所（コントローラなど）
<?php

// これで取得できる
$value = config('sample.want-value');


// これは取得できないことがある
$value = env('WANT_VALUE'); // nullの可能性あり
```

## 参考

- [Laravel の .env の値は config() 経由で使う](https://hiroto-k.hatenablog.com/entry/2018/03/28/213000)
【Git】fatal: Not a git repository (or any of the parent directories): .gitの解決法

こんにちは！安田駿介です！

今回は「fatal: Not a git repository (or any of the parent directories): .gitの解決法」というテーマで解説していきます。

#エラー内容
Gitの初期設定が不備ということです。

#解決策
下記のコードを順番に実行してください。

１．ユーザの登録

```ターミナル
$ git config --global user.name "xxxx"
$ git config --global user.email "xxxxxx@gmail.com"
```

２．gitの初期化

```ターミナル
git init
```

３．git branchで確認

```ターミナル
$ git branch
* master
```
JIS X 0510 - QRコードの GIF 画像を HTML+JavaScript (ローカル) で生成する

入力された文字列の「QRコード」の GIF 画像を HTML+JavaScript (ローカル) で生成します。

<p class="codepen" data-height="1280" data-default-tab="result" data-slug-hash="BabNEVO" data-user="ikiuo" style="height: 1280px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ikiuo/pen/BabNEVO">
  QRコードの画像作成</a> by Ikiuo (<a href="https://codepen.io/ikiuo">@ikiuo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

<!--
![スクリーンショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/b82983e8-8aba-3e47-1643-4200c8f596ca.png)
-->

# QRコード生成プログラム

https://github.com/ikiuo/dhtml-qrcode

# 資料など

[QRコード：JIS X 0510 - 表9 - マイクロ QR コード及び QR コードの誤り訂正特性 - （ブロック数・コード語数を求める）](https://qiita.com/ikiuo/items/34e3dfc2fda7dc763b30)
[QRコード：JIS X 0510 - 附属書 A（規定）誤り検出及び訂正の生成多項式 - （計算で求める）](https://qiita.com/ikiuo/items/da3b05cfb34192d25a96)
[QRコード：JIS X 0510 - 附属書 E（規定）位置合わせパターンの位置 - （計算で求める）](https://qiita.com/ikiuo/items/8b416d33cc72b63e470c)

BASE64： [Base 64 を推測で実装してみる](https://qiita.com/ikiuo/items/4d06d5cdcb11dc97f7a6)
SJIS： [疎行列の圧縮を使った Unicode → シフト JIS（コードページ 932）変換](https://qiita.com/ikiuo/items/d8a774e91828eade0513)
GIF： [バーコード（コード 128：JIS X 0504 (ISO/IEC 15417) ）の生成](https://qiita.com/ikiuo/items/d4d43df1c130f1af1b81)

---

:::note info
「QRコード」はデンソーウェーブの登録商標です。
:::
【GitHub】ローカルリポジトリを削除する方法

こんにちは！安田駿介です！

今回は「gitのローカルリポジトリを削除する方法」というテーマで解説していきます。

#ターミナルで「rm -rf .git」を実行

これだけですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1903726/039511c2-175d-330e-b0d2-03f416b2e9b9.png)

#開発環境
・Cloud9
・Ruby 3.0.0
・Rails 6.1.3.1
zsh promptでGitのブランチ名を表示する方法

VSCodeで講座を行う動画を見てたら、
zshのTerminalにGitのブランチ名を表示してくれるオプションを使っていたので、
設定の仕方をまとめてみたいと思います。

## 手順

### 1. zshrcの設定を開く

```
vi ~/.zshrc
```

### 2. VCSの情報を読み込み、Promptに表示させる

ちなみにvcs_infoのVCSとは、Github, Gitlab, SVNなどのバージョン管理システム(Version Control System)のことを指しているよう。
このvcs_infoで取れた情報を、zshのPromptに表示させましょう。

```
# Load version control information
autoload -Uz vcs_info
precmd() { vcs_info }

# Format the vcs_info_msg_0_ variable
zstyle ':vcs_info:git:*' formats 'on branch %b'
 
# Set up the prompt (with git branch name)
setopt PROMPT_SUBST
PROMPT='%n in ${PWD/#$HOME/~} ${vcs_info_msg_0_} > '
```

### 3. ~./zshrc 設定をリロードする

反映するには、sourceコマンドでリロードする。

```
source ~/.zshrc
```

### 4. 出来た！

```
username [~/work/typechain](main) >
```

現在のPathと、GitのBranchが見えるようになりました。
でも、色とか付けたいので、もう少し調べてみると。。

## Oh my zshを適用してみる

https://github.com/ohmyzsh/ohmyzsh

すでに彩り豊かに設定できるZshの設定リポジトリがありました :innocent: 
要は、ユーザーがすでに設定したzsh設定のテンプレートを気軽に設定できるもの。

以下のように進めてみます。

### 1. インストールする

```
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
```

### 2. テーマを変える

https://github.com/ohmyzsh/ohmyzsh/wiki/Themes にすでに追加されているテーマがいくつかありました。
こちらを参考に、テーマを変えてみます。

```
vi ~/.zshrc
```

設定の中で、ZSH_THEME設定値を変えます。

```
ZSH_THEME="agnoster"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249024/c690a8f0-baf2-ae96-6aaa-777c6f2dcaab.png)

設定できた！が、おや？何か文字化けしている。。

https://github.com/ohmyzsh/ohmyzsh のREADME.mdを見てみると、どうやら powerlineというフォントのインストールが必要みたいだ。

### 3. powerline fontを追加する

https://github.com/powerline/fonts

以下のような手順で、 /username/Library/fonts に for Powerline フォントをインストールします。

```
# clone
git clone https://github.com/powerline/fonts.git --depth=1
# install
cd fonts
./install.sh
# clean-up a bit
cd ..
rm -rf fonts
```

### 4. VSCodeのTerminalに適用する

Setting [`Command + ,`] を開いて、 "terminal.integrated.font"の値を以下のように変えます。
(他にもいろんなフォントがあるので、ご自由に！）

```
Roboto Mono Medium for Powerline
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249024/b28876e5-5171-18ea-0ab4-b665cda5a620.png)

### 5. やっとできた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249024/16306400-a2bd-c3d9-ea40-b2a3ad911a60.png)

ちなみに、iTerm2などでも、`Preferences > Text > Font` を変えることで適用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249024/fb44f2f0-8566-dd1d-ff36-8507538f74e6.png)
SFTP環境構築メモ - RHEL8系

# SFTPサーバーの構築とクライアント処理の自動化
鍵認証を使ったSFTP環境を構築します。

## 環境
- Server OS: Rocky Linux release 8.4
- Client OS: Rocky Linux release 8.4

## サーバー側の設定

### SFTPサーバー設定

#### 公開鍵認証を有効にする
```file:/etc/ssh/sshd_config
PubkeyAuthentication yes
```

#### 公開鍵の保存場所を指定する
```file:/etc/ssh/sshd_config
AuthorizedKeysFile      .ssh/authorized_keys
```

#### OpenSSHでSFTPを有効にする
```file:/etc/ssh/sshd_config
Subsystem       sftp    /usr/libexec/openssh/sftp-server
```
#### 設定ファイルの構文チェック
問題無ければ何も出力されません。異常が見つかった場合はエラーが出力されます。

```shell-session
$ sudo /usr/sbin/sshd -t
```

#### SFTP設定を反映するためにサービス再起動
```shell-session
$ sudo systemctl restart sshd
```
### ユーザー
SFTP接続するユーザーをサーバーにて作成します。

```shell-session
ユーザー作成
$ sudo useradd [username]

作成したユーザーに切替
$ sudo su - [username]

鍵作成
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/xxxx/.ssh/id_rsa): このままエンター
Enter passphrase (empty for no passphrase): このままエンター
Enter same passphrase again: このままエンター

※今回は自動化するため、パスフレーズは空にしています

authorized_keysに公開鍵を登録する
$ cd .ssh/
$ cat id_rsa.pub >> authorized_keys
$ chmod 600 authorized_keys

作成したユーザーのホームディレクトリ配下にある以下の秘密鍵ファイルをクライアントの同ディレクトリにコピーします
~/.ssh/id_rsa

※SCPなどでファイル転送するか中身はテキストなのでそのまま文字列をコピペします
```
## クライアント
### 秘密鍵ファイルの権限設定
```
$ chmod 600 ~/.ssh/id_rsa
```

### バッチファイルの作成
```
$ vi sftp.bat
cd data
put test.csv
bye

※コマンドをそのまま上から順番に書きます
```

### 手動実行
```
$ sftp -b sftp.bat -i ~/.ssh/id_rsa username@[IPaddress or FQDN]
```

### スケジュール実行用のシェルスクリプト作成
```
$ cat << EOT >> sftp.sh
#!/bin/bash
sftp -b sftp.bat -i ~/.ssh/id_rsa username@[IPaddress or FQDN]
EOT

$ chmod +x sftp.sh
```

### スケジュール設定
```
$ crontab -e
30 12 * * * /home/username/sftp.sh
```

### sftpコマンドの注意点
- sftpコマンドはパスワード認証に対応していない　→　鍵認証にする必要がある
- sftpコマンドのバッチファイル実行はパスフレーズ有りの鍵認証に対応していない　→　パスフレーズ無しにする必要がある
Figmaでステッカー作り

## 必要な物
- プリンター
- ステッカー印刷紙
    - 今回はセリアで購入

<img width="300" src="https://i.imgur.com/IRkefsR.jpg" />

## 印刷物の作成
> Figmaで作成
> Figmaでなくても画像を貼って印刷できるのであれば何でも良い

1. 左上の#をクリックしPaperのA4を選択
![](https://i.imgur.com/MwMnOnr.png)

2. 左上の矢印に戻りRotationを90に変更
![](https://i.imgur.com/NASd7ah.png)

3. ステッカーにしたい画像をドラッグ&ドロップし、
    constrain proportionsを押しサイズを変更する
![](https://i.imgur.com/WB27l4o.png)

4. pdfで保存
![](https://i.imgur.com/gpqy5P6.png)

5. 印刷紙をステッカー印刷紙に変えて印刷
![](https://i.imgur.com/SLfxCVo.jpg)

あとは切って貼るだけ。

## 結論
Figma便利。

## 動機
パソコンの汚れが気になったのでステッカーで隠そうと思いついでに投稿しました。

## 補足
アイコンが貼ってあるからその技術使えるってわけじゃないからね？(涙)
（レポート）Regional Scrum Gathering Tokyo 2022 Day 1「いい感じのチーム」になるためにやること

# Regional Scrum Gathering Tokyo 2022 Day 1
 
この記事は、2022/01/05-08に開催された[Regional Scrum Gathering Tokyo 2022](https://2022.scrumgatheringtokyo.org/)のレポートです。
 
# チーム参加してきました
  
[aslead Agile](https://aslead.nri.co.jp/solution/aslead_agile.html) のチーム「[オキザリス](https://speakerdeck.com/viva_tweet_x/huesudeyong-qi-wode-taxin-gui-timugashi-yan-wozao-rifan-sitejin-nizhi-rumadefalsewu-yu?slide=3)」にて参加してきました。
チーム5人中、4人で参加して、その場で実況しつつ、記事も作っています。

# テーマ
- [「いい感じのチーム」になるためにやること](https://confengine.com/conferences/regional-scrum-gathering-tokyo-2022/proposal/15891)

# 登壇者
- Yoh Nakamura

# 「いい感じのチーム」とは？
- 自分たちであり方、やり方を決めている
- フィードバックループが機能している
- 感情でつながっている

# 変化を観察する
- 観察する→発見する→実験する・・・
- 変化はゆっくりで、再現性がそこまで高いわけではない
- 先に行き過ぎないで、1つずつ、一歩ずつ、丁寧にやっていく

#「いい感じのチーム」への3つのテーマ
- リーダーシップ
- 感情
- 実験

# リーダーシップ
- リーダーシップは誰か1人のリーダだけのものでしょうか？
- みんなでリードする
	- リーダという肩書は時に悪影響を及ぼす
	- その時に適切な人がリードする
		- どういうスキルをもっているか、どういう状況が得意なのかをチームが知っておく
- みんなが1つの北極星とコンパスを見ている
	- チームが向かう先はどこか？今はどこに向かっているのか？が必要
	- 北極星とコンパスがあると、リードする人が入れ替わってもチームは機能する
		- インセプションデッキやプロダクトゴールを一緒に作る
- チームを1人の人とみる
	- チームとして全体のバランスが大切
	- チームとしてのバランスは外からだけではわかないことが多い
		- 内省の手助けとして問いかけたり、見える化を促したりする
- そこにいる人の事を想う
	- 同じ出来事でも感じ方や受け止め方が違う
	- それぞれに個性、特徴があり、やりたいことも違っている
		-観察したり、1on1したりする必要がある
- 継続的に自分たちでチームになっていく
	- "チームビルディング"はタイミングや状況を見て継続的にやっていく
	- チームでスパイラルを登っていく
		- タックマンモデルを参考にしてみる

# 感情
- 自分の感情を伝えていますか？他の人の感情を受け取っていますか？
- 感情を置き去りにしない
	- 自分の感情にも他人の感情にも気を払う
		-時間的な余裕と気持ちの余裕を持つ
- 感情に蓋をせず、伝え、受け取る
	- 「感情のつながり」の上に「論理のつながり」がある
	- 感情に蓋をすると、悪い感情だけでなく、良い感情まではいってこなくなる
- お互いの事を知る、理解する
	- 短時間で相手のことを多く知り、理解することは難しい
		- 日常の活動で相手の事を理解していく
	- お互い弱みを見せられているか？
		- まずは自分から弱みをオープンにしていく（参考：ジョハリの窓）

# 実験
- どんな風に実験をやっていますか？
- 日常的に実験する
	- 実験することを継続的にする
	- 1つずつ本気（マジ）で取り組む
		- 予想や仮説を持って実験する
	- 結果が出るまで、じっくり待つことも必要（参考：サティアの変化のモデル）
-うまく実験する 
	- 事実→解釈→判断をうまくする
	- 事実が足りていないときには、試してから話す
- フィードバックで調整する
	- 自分たちの活動や作ったものからフィードバックを得て、調整する
	- ステークホルダーとの期待値を調整する
- 燃え尽きないように
	- "いい感じのチームになる"ことへ取り組むことにつかれてしまう
		- 仲間を見つける
	-時には自分が違う場所に移ることも大事

# まとめ
- 起きていることを観察し、声に耳を傾ける

# 感想
- いい感じのチームになるためには、3つの要素があり、
　それぞれが大切な役割を担っていると思いました。
　自分のチームでも、3つの要素を意識してチームビルディングしたいと思いました。
Web APIに触れてみる①

# 今日の目標
* Qiita投稿 #2
* Pythonに触れてみる！
* Web APIを自分で作ってみる！

# PyCharmのインストール
そもそものPython環境が整っていなかったため、以下のリンクの通りに実施。
特に問題なくインストール完了。

* [PyCharmインストール手順＜Windows向け＞](https://sukkiri.jp/technologies/ides/pycharm/pycharm-win.html)


# Web APIに触れてみる
何はさておき、WebAPIとは何ぞやという段階なので、自分で触ってみることとする。
参考にしたのは以下。

* [簡単にできる！WEBAPIをFlaskを使って作成する！！](https://1kara-hajimeru.com/2020/10/1299/)

## 実行環境
実行環境は以下；

* Windows10
* Python 3.9.7
* Flask 2.0.2

## Flaskのインストール
PyCharmを用いてPython実行環境を構築していこうと思うので、PyCharm上でインストールを実施。以下のリンクを参考とした。

* [PyCharmでライブラリをインストールする](https://gammasoft.jp/python/install-packages-with-pycharm/)

## Pythonコード
ここも参考URL通りにコーディング。

```{Python}
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/')
def hello_world():
    return jsonify({'message': 'Hello world!!'})

if __name__ == "__main__":
    app.run(host='127.0.0.1', port=8888, debug=True)
```

上記にて実行した結果、以下が返ってきた。

```
C:\---\python.exe C:/---/main.py
 * Serving Flask app 'main' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: XXX-XXX-XXX
 * Running on http://127.0.0.1:8888/ (Press CTRL+C to quit)
```

その後、http://127.0.0.1:8888/ にアクセスすることで、正常にAPIが作動していることを確認。ここまでは非常に簡単に完了。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262169/378021b8-b9f5-3d26-eb4e-ffab29ceb907.png)
gitで任意のローカルブランチを複数削除する方法

意外とこういう脳筋記事が見つからなかったので、、、
これが最適かどうかは分かりませんが、grepやxargsを使わなくても単純に"空白"で繋げるだけで任意のローカルブランチを複数削除できます。

```
git branch -D [ブランチ名][空白][ブランチ名][空白][ブランチ名]・・・・
```

```
例) git branch -D develop1 develop2 develop3

結果) 
 Deleted branch develop1 (was XXXXXXX)
 Deleted branch develop2 (was XXXXXXX)
 Deleted branch develop3 (was XXXXXXX)
```
アーカイバ内部のLog4jのバージョンを調べる

StreamRelay.jar/StreamRelay.NET.exeのサポートプログラムとして、zip形式のファイル内部を操作する ZipStream.class/ZipStreamNET.exeがあるので、それの紹介

---
### 前節(Log4Shell)

2021年末に報告されたリモートコード実行の脆弱性(CVE-2021-44228)。

[wikipedia](https://ja.wikipedia.org/wiki/Log4Shell)

---
### 前節/方針(jar/warはzip形式)

javaのプログラムであるclassファイルは、1ファイル=1クラスという原則(例外はあるかもしれないけど)があるため、基本的にJavaのアプリケーション・プログラムではファイルが複数のたくさんのファイル群に分かれてしまうという性格がある。

そこで、それらのクラスファイルをまとめる方法として、jar(JavaARchive)とかwar(WebapplicationARchive)とかが出てきたわけであるが、jarもwarも、Javaのアーカイバは基本的にzipファイルだったりする。

実際に、拡張子.jarを.zipに書き換えると、WindowsのエクスプローラーのZipファイル拡張で、jarファイル(zipファイル)の中身が見えたりする。

ということで、Zipの中身が見えるツールで、スキャンすれば、Javaの様々なアーカイブの中に潜んでいるLog4jのバージョンのリストを作ることができるだろう。

---
### まずは、ファイル一覧

Windowsの場合は、

```bat`
DIR c:\ /s /b
```

で、Cドライブ直下のファイル一覧が生成できる。

```bat`
FOR /F "usebackq" %I IN (`DIR c:\ /s /b`) DO @ECHO %I
```

でもよいけど。

---
### まずは、ファイル一覧(複数ドライブの場合)

ドライブが C,D とあるとすれば、

```bat`
FOR %I IN (C D) DO (DIR %I:\ /s /b >> c:\file.lst)
```
とか

```bat`
FOR %J IN (C D) DO (FOR /F "usebackq" %I in (`DIR %J:\ /s /b`) DO @ECHO %I >> c:\file.lst)
```

で、C,Dドライブのファイル全てが、C:\file.lstに出力される。

---
### 次は、ファイル一覧から jar/warを抜き出す

FINDコマンドで行けるでしょう。

だけど、OR ができないので、

```bat`
FOR %I IN (jar war) DO (TYPE c:\file.lst | FIND ".%I" >> c:\file.arllst)
```

のように、FORコマンドで繰り返し処理が必要かもしれない
で、c:\file.arlstに、jarとwarの一覧が出力される。

FINDSTR.exeを使えば、FORコマンドは不要かもしれない

```bat`
TYPE c:\file.lst | FINDSTR /R "\.[jw]ar" >> c:\file.arllst
```

こんな感じ

---
### 最後にZipStream.class (1)

ファイル一覧を「list」モードに通して、Log4jのファイル名を見つけるだけ

```bat`
FOR /F "tokens=*" %I IN ('c:\file.arlst') DO @(java.exe ZipStream list "%I" | FIND "log4j-X-X") 
```

でよいはず

---
### 最後にZipStreamNET.exe (2)

ファイル一覧を「list」モードに通して、Log4jのファイル名を見つけるだけ

```bat`
FOR /F "tokens=*" %I IN ('c:\file.arlst') DO @(ZipStreamNET.exe list "%I" | FIND "log4j-X-X") 
```

でよいはず

---
### 蛇足:一気通貫

Cドライブだけで一気通貫

```bat`
FOR %J IN (jar war) DO (FOR /F "tokens=* usebackq" %I IN (`DIR c:\ /s /b^|FIND ".%J"`) DO @(java.exe ZipStream list "%I" | FIND "log4j-X-X"))
```

とか

```bat`
FOR %J IN (jar war) DO (FOR /F "tokens=* usebackq" %I IN (`DIR c:\ /s /b^|FIND ".%J"`) DO @(ZipStreamNET.exe list "%I" | FIND "log4j-X-X"))
```

な感じかな

---
### リンク

- [アーカイバコマンドの代替としての StreamRelay.NET.exe のサポートプログラム](https://qiita.com/tomoki0sanaki/items/1030f1622dabd0fb810c)
- [アーカイバコマンドの代替としての StreamRelay.jar のサポートプログラム](https://qiita.com/tomoki0sanaki/items/6003df14ba97a71f0ac0)
- [find.exe の代替としての find.net.exe(find.net2.exe/find.net4.exe)](https://qiita.com/tomoki0sanaki/items/71b1391152eb29776281)

---
### 目次へ戻る

[目次というか最初の一歩](http://qiita.com/tomoki0sanaki/items/85f20cbe18378e33cd6f)
KotlinでLocalDateを初期化・LocalDate↔Date変換

LocalDate ↔ Dateの変換が必要になる機会があったので備忘録として残しておく。


## LocalDateを日付指定で初期化
```Kotlin
LocalDate.of(2022, 1, 5)
```

## LocalDateをDateに変換
```Kotlin
fun LocalDate.toDate(): Date {
    return Date.from(this.atStartOfDay(ZoneId.systemDefault()).toInstant())
}
```

## DateをLocalDateに変換
```Kotlin
fun Date.toLocalDate(): LocalDate {
    return this.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()
}
```
Tkinterで画像処理ソフトを作ってみた

##はじめに
以前自作のデータセットを作ったのですが、その際GUI上で簡単にトリミングができたら便利だなと思ったところから開発をスタートしました。

https://qiita.com/dem_kk/items/5a684b056bce3f34e572

上記の例では全て統一したピクセル数の画像を用意していました。
ただ実際の現場では、元画像のサイズ自体もそれぞれ違うことがあり、クリックで簡単に処理したかったのです。

一気に作るのは自分の力量的にしんどかったので、前回の内容をまず作ってそれから改良する形になりました。

https://qiita.com/dem_kk/items/06bcc802dae1579a56e3

##環境
* windows10
* python3.8.10
* pillow8.3.1
* tkinter8.6

##内容
メイン画面とサブ画面を作っています。
メイン画面：トリミングしたい部分の選択・表示など
サブ画面：トリミング幅の指定(ここでは正方形のみ)

```python
import tkinter
from PIL import Image

class Application(tkinter.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        master.title('画面')
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        self.canvas = tkinter.Canvas(self, width=image.width(), height=image.height())
        self.canvas.grid(row=0, column=0, rowspan=3)
        self.canvas.create_image(0, 0, anchor='nw', image=image)
        self.canvas.create_rectangle(-12, -12, -2, -2, fill='blue',
                                     outline='white', width=2,
                                     tag='marker')
        self.canvas.bind("<ButtonPress-1>", self.move_marker)
        button = tkinter.Button(self, text='リセット', command=self.reset)
        button.grid(row=0, column=1)
        
        #サブ画面の作成
        self.subwindow = tkinter.Toplevel()
        self.subwindow.geometry('200x100')
        self.label = tkinter.Label(self.subwindow,text='1辺のピクセル数を入力してください')
        self.entry = tkinter.Entry(self.subwindow,width=15)
        self.subbutton = tkinter.Button(self.subwindow,text='切り取り')
        self.subbutton.bind('<Button-1>',self.trim)
        
        self.label.pack()
        self.entry.pack()
        self.subbutton.pack()

    def move_marker(self, event):
        global a,b
        a = event.x
        b = event.y
        print("clicked at ", a, b)
        self.canvas.moveto('marker', event.x - 7, event.y - 7)
     
    #指定した座標を中心にトリミング     
    def trim(self,event):
        global x1,y1
        self.num = int(self.entry.get())//2
        x1 = a-self.num
        y1 = b+self.num
        x2 = a+self.num
        y2 = b-self.num        
        self.canvas.create_rectangle((x1,y1,x2,y2),
                                     outline='blue', width=2,
                                     tag='marker2')
        trim_image = Image.open('kikagaku.png')
        trim_image2 = trim_image.crop((x1,y2,x2,y1))
        trim_image2.save('trim_image.png')
        
    def reset(self):
        print('reset')
        self.canvas.moveto('marker', -12, -12)
        self.canvas.delete('marker2')

root = tkinter.Tk()
image = tkinter.PhotoImage(file='kikagaku.png')
app = Application(root)
app.mainloop()
```
![メディア1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/59dcc846-855e-39e1-429d-fb1cedff9fdf.gif)
![trim_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/a9dd7e81-1068-ba11-0d6d-f8733dbef3b5.png)


切り取った画像も、動画内で表示されている枠の部分と同じになっていることがわかる。


##まとめ
何とか画像処理ソフトとしては形になったのではないでしょうか(細かい部分はさておき)。
気力を使い果たしたので、今日はもうやる気が出ない:sleeping:
多重ハッシュから値を取得する

###rubyの知識を問題を解きながら、何が分かってて何が分かっていないかを洗い出して、復習するシリーズ
という知識を深める用アウトプットをしていくよ

ではさっそく。vol.2

##問題
配列の内部に、複数のユーザーの情報をハッシュとして持つ変数user_data

```ruby
user_data = [
 {user: {profile: {name: 'Abc'}}},
 {user: {profile: {name: 'Def'}}},
 {user: {profile: {name: 'Ghi'}}},
]
```
全てのユーザーの「名前だけ」が出力されるように記述する。

```ruby:期待する出力結果
Abc
Def
Ghi
```

<details><summary>試行錯誤で戦った経過。不毛すぎるから折りたたみ。</summary><div>

user_dataの定義部分は省略して書く。

```ruby:戦い１　なんかこんな感じのはず
user_data.each do |data|
  puts data.user.profile.name
end
```

```:結果
Traceback (most recent call last):
        2: from test.rb:15:in `<main>'
        1: from test.rb:15:in `each'
test.rb:16:in `block in <main>': undefined method `user' for {:user=>{:profile=>{:name=>"Abc"}}}:Hash (NoMethodError)
Did you mean?  super
```
はい、すみません。

```ruby:戦い2　こうか？
user_data.each do |data|
  puts data{name}{profile}{name}
end
```

```:結果
test.rb:16: syntax error, unexpected '{', expecting end
  puts data{name}{profile}{name}
```
ですよねー。

```ruby:戦い3　なんかこんなのなかったっけ
user_data.each do |data|
  puts data{{{name}}}
end
```

```:結果
test.rb:16: syntax error, unexpected '}', expecting =>
  puts data{{{name}}}
```
</div></details>
結果、こうすると思うように出力できました。

```ruby:回答
user_data = [
  {user: {profile: {name: 'Abc'}}},
  {user: {profile: {name: 'Def'}}},
  {user: {profile: {name: 'Ghi'}}},
 ]

user_data.each do |data|
  puts data[:user][:profile][:name]
end
```

キーの指定の仕方がまだ不慣れです。

##さて、おさらい

ハッシュから欲しい値を取得するには

```
ハッシュ名[欲しい値のキー]
(例)user_data[:user]
```
ちなみに問題のuser_dataで↑のようにuserだけ指定するとこのように↓返ってきました。

```
{:profile=>{:name=>"Abc"}}
{:profile=>{:name=>"Def"}}
{:profile=>{:name=>"Ghi"}}
```
今回はもっと先のnameまで指定して取得したい。
→ハッシュが多重になっている。
→**キーを連続して書く**

```
ハッシュ名[値のキー][値のキー][値のキー]
(例)user_data[:user][:profile][:name]
```


ちなみにこういう書き方もあるそう

```ruby:模範解答2
user_data.each{ |data| puts data.dig(:user, :profile, :name) }
```
digメソッドについてはまた勉強します。

##まとめ？
んんん、正直あんまりすとんと落ちてきてない。
でも、必要なキーのところ（今回ならname)までのキーを順番に記述するのはすっきり。
最初のお試しそうしてたしね。
基礎理解が浅いまま進んでてごっちゃになってます。
今回は`[:user]`この書き方をインプット。多重ハッシュの手前の基礎部分ですね。

一度苦手意識を持つと頭に入ってきづらくなるのは自分の性質なので、焦らず向き合っていこうと思います。

間違ってること、もっとこうしたらいいよというアドバイスなどありましたら、コメントいただけると嬉しいです。

では、また次の投稿で。
WSL2のUbutuでMySQLを5.7から8.0にアップデートした後にエラー

#症状
[これ](https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/#repo-qg-apt-upgrading)に従ってMySQLをアップデートした後に、`sudo service mysql start`すると`[fail]`の文字が。何やと思って`/var/log/mysql/error.log`を見てみると

```
[ERROR] [MY-000067] [Server] unknown variable 'log-syslog=1'.
[ERROR] [MY-010119] [Server] Aborting
```
調べると、mysqldサーバー起動スクリプトであるmysqld_safeにおいて上記の部分の記法が非推奨になったことが原因だと思われる。[参考ページ](https://dev.mysql.com/doc/refman/8.0/ja/mysqld-safe.html#option_mysqld_safe_syslog)
#解決法
以下のリンクに従って解決。言うてコメントアウトするだけだが。

https://stackoverflow.com/questions/49963923/how-do-i-update-mysql-5-7-to-the-new-mysql-8-0
BetterTouchToolでSidecarをタッチバーから起動する方法

BTTを使ってタッチバーからSidecarを起動するための手引きがなかったので、個人的なメモも兼ねたまとめです。


##動作環境
macOS Big Sur 11.6.1（Locale: Japan）
Better Touch Tool 3.3.89

##設定項目

**タッチバートリガー設定**
`Select Trigger` -> `タッチバーボタン`

**トリガーの割り当て設定**
`Controlling Other Applications` -> `Apple Scriptを実行する（ブロック）`


スクリプトコードのペイン（以下画像参照）に下記コードを入力

![BTTスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2463567/f5f3eb45-406b-1f33-616a-d0f6494ff832.png "スクリプトコードのペイン")


>スクリプト引用
satokaz. (2021). AppleScript で Sidecar の接続/接続解除をトグルする #17. https://github.com/satokaz/hitorigoto/issues/17. 

```AppleScript:#Insert_script_code_here
tell application "System Preferences"
	activate
	set the current pane to pane id "com.apple.preference.sidecar"
	get the name of every anchor of pane id "com.apple.preference.sidecar"
	delay 1
	tell application "System Events"
		set target_button to a reference to (first button whose name is "接続解除") of (window "Sidecar" of application process "システム環境設定")
		if target_button exists then
			click target_button
		else
			click menu button "デバイスを選択" of window "Sidecar" of application process "システム環境設定"
			count menu items of menu of menu button "デバイスを選択" of window "Sidecar" of application process "システム環境設定"
			select item 1 of menu button "デバイスを選択" of window "Sidecar" of application process "システム環境設定"
			key code 125
			key code 76
		end if
	end tell
	quit
end tell
```

##その他

satokaz(2021)でも触れられている通り、上記のAppleScriptはJP-Locale用なので、EN-Localeを設定されている方は、rauls4. (2020). Toggle-Sidecar-Automator-Action. https://github.com/rauls4/Toggle-Sidecar-Automator-Workflow. のコードを参照のこと。
Genie を Heroku にデプロイ

Bulidpack を使って Julia のプロジェクトを Heroku にデプロイする方法です。

#プロジェクト#

フォルダー構造

```text
$ tree example01/
example01/
├── Procfile
├── Project.toml
└── src
    └── example01.jl
```

```text:Procfile
web: julia src/example01.jl $PORT
```

```text:Project.toml
[deps]
Genie = "c43c736e-a2d1-11e8-161f-af95117fbd1e"
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
```

>uuid は .julia/environments/v1.8/Project.toml のものを使いました。

```julia:src/example01.jl
using Genie
using Genie.Router

function launchServer(port)

    Genie.config.run_as_server = true
    Genie.config.server_host = "0.0.0.0"
    Genie.config.server_port = port

    println("port set to $(port)")

    route("/") do
        "Hi there! Jan/05/2021 PM 13:10"
    end

    Genie.Server.up()
end

launchServer(parse(Int, ARGS[1]))
```

#ローカルで動作確認#

```text
$ julia src/example01.jl 8000
port set to 8000
┌ Info: 
└ Web Server starting at http://0.0.0.0:8000 - press Ctrl/Cmd+C to stop the server. 
```

![genie_aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/b3d592b4-55e5-0b7c-0a8e-40195f0a49d6.png)

#デプロイ#

```bash
heroku login
git init
git add .
git commit -m "init"
#
HEROKU_APP_NAME=p0080-jan05
BUILDPACK="https://github.com/Optomatica/heroku-buildpack-julia.git"
heroku create $HEROKU_APP_NAME --buildpack $BUILDPACK
#
heroku list
git push heroku master
#
```

動作確認

```text
$ http http://p0080-jan05.herokuapp.com/
HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: */*
Date: Wed, 05 Jan 2022 04:27:09 GMT
Server: Genie/Julia/1.6.2
Transfer-Encoding: chunked
Via: 1.1 vegur

Hi there! Jan/05/2021 PM 13:10
```

Heroku のアプリの削除方法

```bash
heroku apps:destroy --app=p0080-jan05 --confirm=p0080-jan05
```
gemを比較するサイトを作ってみた。ついでにRails7の所感を少々

## 作ってみた

Railsのリハビリついでに欲しかったサイトを作りました。
簡単に言うと、[npmtrends][npmtrends-url]を~~パクっ~~リスペクトしたサイトです。

サイト：[rubytrends.net][site-url]
ソースコード：[github][repository-url]

## こんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188872/1ef24f07-142b-9e03-a2f9-f467c1d1a0b0.png)

過去一年分のダウンロード数をグラフ化し、重ねて表示しただけです。
次は期間を変えれるようにする予定です。

また、裏で検索履歴をカウントしているので、皆さんが使ってくだされば、いずれは本家のようによく比較されている関連gemを表示できるようになるはずです。

需要がありそうなら機能強化していきます。

## Rails7を使ってみた感想

この記事にRailsタグを貼り付けた以上、Railsに関して何も書かないのもあれなので、少しだけ所感を。
今回は出来るだけRails wayを歩むという裏テーマがあったので、`rails new --database=mysql --css=tailwind .`で作ったプロジェクトからはじめました。

### バックエンド

いつものRailsです。
Rails6とそれほど変わっているとは思いません。

### Turbo

Turbo Driveしか使っていないので、Turbolinksと同じ具合だなという印象しか今のところないです。
個人的にはTurbo Framesにかなり可能性を感じてるので、後でこのサイトのグラフ部分をTurbo Frames化して試してみる予定です。

JSからの遷移では`Turbo.visit(path);`を使えばよく、[イベント一覧][turbo-events-url]もあるので、（このサイトの構造が単純だったこともあるでしょうが）特に困ることはなかったです。

追記：
グラフ描画部分をTurboFramesに差し替えました。
通常のページと全く変わらない書き心地で画面の一部差し替えが出来るというのは、正直革命的なものだと思います。
言うなれば動的なrender partialというイメージです。

各frameにはidが必要であり、frameの画面遷移はelementのsrcを差し替えるだけです。
JS部分は以下の二行だけで部分更新が実装できました。

```js
    const chartElm = document.getElementById("chart");
    chartElm.src = path;
```

### Stimulus

最近TS+Reactばかり触っていた身としては、はっきりいって最初は記法が気持ち悪くて使う気になれなかったのですが、DHH信者としてのプライドがそれを許さなかったので、歯を食いしばって使ってみることにしました。

人は慣れる生き物なので、２分もすればTS、Reactの書き方を忘れ、Stimulusもわるくない……のか？　という気持ちになりました。

html側は`-`、JSファイル名は`_`という奇妙な決まりごとに戸惑いはしたものの、慣れてしまえばそれもまたクセになるものです。
特にディレクトリは`--`で区切るところなんかはシビれました。

複雑な部品には複数のコントローラーをつけて制御することも出来るらしく、想像するだけでカオスなことになりそうではありますが、一般的なサイトでフロントエンドにそこまでゴリゴリロジックを書くことは稀でしょう。

複雑なフロントエンドは……素直にReactを使うのが良手でしょうか。

### Importmap

具合は良いです。

```
npm install xxx
import {XXX} from "xxx";
```

が

```
./bin/importmap pin xxx
import {XXX} from "xxx";
```

に変わるくらいでしょうか。

importに失敗したときにエラーログが出ずに落ちるところは正直地獄ですが、これは恐らく設定か今後のアプデで解決される問題なので良しとしましょう。

### まとめ

Rails7で一新されたフロントエンドの深いところまではまだ触っていませんが、浅いところで水遊びしてる分には悪くなかったです。

[site-url]: https://rubytrends.net
[repository-url]: https://github.com/sijiaoh/rubytrends
[npmtrends-url]: https://www.npmtrends.com/
[turbo-events-url]: https://turbo.hotwired.dev/reference/events