OmniAICreator/Qiita-1.07M huggingface dataset:
高速フーリエ変換(FFT)のバタフライ演算を可視化してみた

# 経緯

バタフライ演算の図は数あれど、どの線上で何が重みづけ計算されているのかサッパリわからなかったので色々調べてみたところ、[参考サイト1](http://ysmr-ry.hatenablog.com/entry/2017/11/09/102008)とその[CodePen](https://codepen.io/As2/full/BmLOqY/)を見て理解ができたので、インスパイヤされてつくってみた。


# バタフライ演算の経路と重みを可視化してみた

バタフライ演算図の読み方・・・線が合流している箇所で加算が行われます。矢印が描画されている箇所では重みづけ計算がされます。

Inputの横のスライダの値を変化させると、選択した経路（白線）に応じて、重み[^1]が角度単位で表示されます。経路中（白線上）の合計角度が45度刻み[^2]に増えるのが見て取れるかと思います。

[^1]: +180度($e^{-i\pi}$相当)など
[^2]: N=8の場合

<p class="codepen" data-height="620" data-theme-id="light" data-default-tab="result" data-user="kob58im" data-slug-hash="ZEWoPZV" style="height: 620px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="FFT - Butterfly Diagram">
  <span>See the Pen <a href="https://codepen.io/kob58im/pen/ZEWoPZV">
  FFT - Butterfly Diagram</a> by kob58im (<a href="https://codepen.io/kob58im">@kob58im</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 高速フーリエ変換を実装してみた (JavaScript)

上側の波形を入力としてフーリエ変換結果を下側に描画します。
スライダで指定した繰り返し数の`sin`波で、入力側の波形を初期化します。

<p class="codepen" data-height="565" data-theme-id="light" data-default-tab="result" data-user="kob58im" data-slug-hash="eYZLavq" style="height: 565px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="FFT">
  <span>See the Pen <a href="https://codepen.io/kob58im/pen/eYZLavq">
  FFT</a> by kob58im (<a href="https://codepen.io/kob58im">@kob58im</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

※JavaScriptの場合は、手実装するより、ありものを使ったほうがよさそう。
[getUserMediaで音声を拾いリアルタイムで波形を出力する - Qiita](https://qiita.com/mhagita/items/6c7d73932d9a207eb94d)

# 高速フーリエ変換をC#で実装してみた（ライブラリレス）


[C# - Win32API(WinMM)でマイク入力を拾う(32bit) / 高速フーリエ変換を手実装してみた](https://qiita.com/kob58im/items/aa6c7a4dc80946dbe3a7)

# 参考サイト

下記１つ目のサイトの[Butterfly Diagram Maker - CodePen](https://codepen.io/As2/full/BmLOqY/)のおかげでバタフライ演算の図の読み方が理解できました。感謝！

1. [高速フーリエ変換 (FFT) - ゆるふわブログ](http://ysmr-ry.hatenablog.com/entry/2017/11/09/102008)
- [高速フーリエ変換#アルゴリズム - Wikipedia](https://ja.wikipedia.org/wiki/%E9%AB%98%E9%80%9F%E3%83%95%E3%83%BC%E3%83%AA%E3%82%A8%E5%A4%89%E6%8F%9B#%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0)
- [高速フーリエ変換（千葉大学 講義資料 PDF）](http://www.cfme.chiba-u.jp/~yama/DSP/dsp_04.pdf)
- https://www.onosokki.co.jp/HP-WK/eMM_back/emm140.pdf
- https://qiita.com/kob58im/items/bc5dc3f6114778adc141
Stoneでポートフォワード、TLS1.2対応版の場所

## 参考

* https://hub.docker.com/r/int128/stone
* https://int128.hatenablog.com/entry/2014/10/25/120318

## 使い方

```sh
# 443 にアクセスしたら localhost:22 に接続する
docker run -it -d \
 --name stone \
 --hostname stone \
 --restart=always \
 -p 443:443 \
 int128/stone \
 localhost:22 443
```

## sambaのポートフォワード

```sh:run.sh
docker run -it -d \
 --name stone-samba \
 --hostname stone \
 --restart=always \
 -p 445:445 \
 int128/stone \
 192.168.0.200:445 445
```

## TLS 1.2対応版

ありがたい

https://github.com/takuya-o/stone/releases

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/3ff2c5c7-f08e-4b17-ad94-48083e4d069a.png)

VCRUNTIME140.dll が必要とのこと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/9046c219-1928-4964-8869-e7e5606f4a78.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/aaec2fd0-f437-47b2-8d4f-faf76905f6bc.png)
Java HashMap,entrySet 

#【Java HashMap,entrySet】

業務でよく使用する、HashMap,entrySetの備忘録です。

##HashMap＜key, value＞

HashMapはジェネリクス型（総称型）なため、keyとvalueの型を決めて宣言する。
総称型は、利用する型を限定するもの。

Mapのkeyとvalueのペアは、Map.Entry インターフェイスで表す。

##entrySetメソッドは、Mapのクラスメソッド

連想配列キーとバリューの組み合わせをエントリーといい、Mapのコレクションを返す。
Mapの配列ループのようなもので、動作が速い。

Map.Entryは、getKeyメソッドで、key。getValueメソッドで、valueの値を取得する。

.entrySet( ); を使うことでentry全要素を取得することが可能。
.keySet( ); を使うことでkey全要素を取得することが可能。
.valueSet( ); を使うことでvalue全要素を取得することが可能。


###・実際に使用している例

####①HashMap＜String, Object＞　１対１で対応
　Objectには、様々な要素が入る。

####②ArrayList＜String＞　文字列の値の羅列を格納


####①+②= ArrayList＜HashMap＜String, Object＞＞
→　キーの多次元性を表現している。
jqコマンドでネストされたJSONデータの取得・集計をする

こんなネストされたJSONをjqコマンドで値を取得したり集計したりする時のメモ

```json:sample.json
{
  "ok": true,
  "messages": [
    {
      "text": "カレー食べた",
      "reply_count": 1,
      "reactions": [
        {
          "name": "+1",
          "count": 2
        },
        {
          "name": "clap",
          "count": 1
        }
      ]
    },
    {
      "text": "家系ラーメン食べた",
      "reply_count": 4,
      "reactions": [
        {
          "name": "+1",
          "count": 5
        },
        {
          "name": "clap",
          "count": 3
        },
        {
          "name": "blush",
          "count": 4
        }
      ]
    }
  ]
}
```
##messagesの各要素について取得してみる

###①textだけを取得

```bash

$cat sample.json | jq ".messages[].text"
"カレー食べた"
"家系ラーメン食べた"
```

###②text ・ reply_countを取得
```bash
$cat sample.json | jq ".messages[] | [.text, .reply_count]"
"カレー食べた", 1
"家系ラーメン食べた", 4
```

###③text ・ reply_count ・ reactionsのcoment合計を取得
```bash
$cat sample.json | jq ".messages[] | [.text, .reply_count, ([.reactions[]?.count] | add)]"
"カレー食べた", 1, 3
"家系ラーメン食べた", 4, 12
```
reactionsがnullの場合のエラーを無視するために`?`をつける。この`?`で大分詰まったけど[普通にドキュメントに書いてあって](https://stedolan.github.io/jq/manual/#Basicfilters)まずドキュメント見なかった自分を蹴りたくなった。
また、`add`で合計を取得する時は配列を与える必要があるので`.reactions[]?.count`を`[]`で囲む。

##messages全体の数値を取得してみる

###①messagesの要素数を取得
```bash
$cat sample.json | jq "[.messages[]] | length"
2
```
`add`の時と同様`.messages[]`を`[]`で囲む。囲まないとmessagesの各要素の要素数が出てしまう。（ここでいうと3, 3）

###②reply_countの合計を取得
```bash
$cat sample.json | jq "[.messages[].reply_count] | add"
5
```

###③全reactionsのcoment合計を取得
```bash
$cat sample.json | jq "[.messages[].reactions[]?.count] | add"
15
```

###① ~ ③をまとめて取得
```bash
$cat sample.json | jq "[([.messages[]] | length), ([.messages[].reply_count] | add), ([.messages[].reactions[]?.count] | add)]"
2, 5, 15
```
または

```bash
$cat sample.json | jq "{ message: [.messages[]] | length, reply: [.messages[].reply_count] | add, reaction: [.messages[].reactions[]?.count] | add }"
{
  "message": 2,
  "reply": 5,
  "reaction": 15
}
```
Amazon Linux 2 に ImageMagick をインストールする

# 環境

- Amazon Linux 2 (RedHat 7 ベース）
- ImageMagick 7.0.10-29


# インストール方法（ソースコードからコンパイルする場合）

```
$ IMAGEMAGICK_VERSION='7.0.10-29'

$ sudo yum install -y libwebp libwebp-devel

$ mkdir -p ~/tmp && cd ~/tmp
$ wget https://imagemagick.org/download/ImageMagick-${IMAGEMAGICK_VERSION}.tar.gz
$ tar zxvf ImageMagick-${IMAGEMAGICK_VERSION}.tar.gz

$ ./configure
$ make
$ sudo make install
```

# インストール方法（rpm 利用）

```
$ IMAGEMAGICK_VERSION='7.0.10-29'

$ sudo yum install -y fftw3
$ sudo yum install -y https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/l/libraqm-0.7.0-4.el7.x86_64.rpm
$ sudo yum install -y https://imagemagick.org/download/linux/CentOS/x86_64/ImageMagick-libs-${IMAGEMAGICK_VERSION}.x86_64.rpm
$ sudo yum install -y https://imagemagick.org/download/linux/CentOS/x86_64/ImageMagick-${IMAGEMAGICK_VERSION}.x86_64.rpm

$ yum list installed | grep ImageMagick
ImageMagick.x86_64            7.0.10-29                      installed
ImageMagick-libs.x86_64       7.0.10-29                      installed
```

# インストール後の確認

```
$ which convert
/usr/bin/convert

$ convert --version
Version: ImageMagick 7.0.10-29 Q16 x86_64 2020-09-05 https://imagemagick.org
Copyright: © 1999-2020 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenMP(3.1)
Delegates (built-in): bzlib cairo djvu fftw fontconfig freetype gslib jng jpeg lcms ltdl lzma openexr pangocairo png ps raqm rsvg tiff webp wmf x xml zlib
```
Andoridにwordpressをインストールする

UserLandを用いてAndroidスマートフォンにwordpressをインストールします。

ユーティリティのインストール

~~~~
sudo apt install wget ;
~~~~

wordpressの取得

~~~~
cd /var/www/html ;
wget https://ja.wordpress.org/latest-ja.tar.gz ;
tar xvf latest-ja.tar.gz ;
sudo chown -R www-data:www-data . ;
~~~~

MySQLのスタート

~~~~
sudo service mysql start ;
~~~~

MySQLへ接続

~~~~
sudo mariadb ;
~~~~

wordpressのユーザー名をwordpress
パスワードをpasswordにした例

~~~~
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8;
GRANT ALL ON wordpress.* TO wordpress@localhost IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
~~~~

ブラウザからアクセス

~~~~
http://192.168.xxx.xxx:8080/wordpress/
~~~~

wordpressのインストール画面が表示されます。
FlutterにFirebase（Firestore）を導入したら、iOSのビルドが遅くなった

# 困ったこと
FlutterにFirebase（Firestore）を導入したら、iOSビルドがとても遅くなった。
元々1分くらいだったのが、10分くらいになってしまった。

# 解決法
:::note warn
2021/9/18時点の情報です。バージョンなどが古くなっている可能性があるので、公式ドキュメントを参照してく最新の情報を確認してください。
:::

ios/Podfileに、下記を1行追加した。
`pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '6.26.0'`


サンプル（抜粋）

```ruby:ios/Podfile
target 'Runner' do
  use_frameworks!
  use_modular_headers!
  pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '8.6.0'
  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
```

# なぜ遅くなったのか？
公式ドキュメントによると、FirestoreのiOS SDKは500k行のC++で書かれているらしく、それを毎回コンパイルするため、時間がかかっているそう。
なので、事前にコンパイルした結果を、githubから取得するようにすることで、時間短縮しているということらしい。

>Improve iOS Build Times#
Currently the Firestore iOS SDK depends on some 500k lines of mostly C++ code which can take upwards of 5 minutes to build in XCode. To reduce build times significantly, you can use a pre-compiled version by adding 1 line to your ios/Podfile inside your Flutter project;

>pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '8.6.0'

>Add this line inside your target 'Runner' do block in your Podfile, e.g.:

https://firebase.flutter.dev/docs/firestore/overview/#4-optional-improve-ios--macos-build-times

# あとがき
公式ドキュメントはしっかり読もうね、というお話でした。
この事象に困り、`Flutter Firebase ビルド 遅い iOS`などのキーワードで結構ググりましたが、日本語と英語どちらもあまりヒットせず、みなさんちゃんと公式ドキュメント読んでいるんだなあと感じました。

反省。
ネットワークが切り替わったタイミングで意図せず印刷物が印刷されることを防いでみた。

# 紙、それは作業スペースを広げる魔術。
SEやプログラマーをされている方は、複数の職場環境で作業される方がいらっしゃると思います。
お客様先に常駐されていたり、リモートワークしていたり、自社で作業したりと多くの職場環境でご自身のノートPCで作業をされている方もいらっしゃると思います。私はそんな環境で作業をしていました。
そういった中、設計書などを印刷するなど、何かしらの印刷をする機会は結構あるのではないかと思います。

# たかしさん印刷ミスるってよ。
皆様、その様にいろいろな環境で作業をしていると、間違えてネットワーク内に存在しない、ネットワークプリンターに対して印刷をしてしまうことありませんか？
A社で仕事しているのに、B社のプリンターに対して印刷をしてしまうということはあるあるだとおもいます。
ネットワークに接続されてないとそりゃ当然印刷命令が届かないので、紙が出力されないので、「あ、間違えた」と気がつき正しいネットワークプリンターを選んで再度印刷するのではないかと思います。


# 裏で印刷物がたまる仕様になってる
しかし、Windows10はスプーラーという、印刷物をためておく機能を使って、一旦印刷情報をスプーラーにためてそれを、印刷機に随時送るようなな仕組みになっています。
そのため、誤印刷した際もスプーラーに印刷物が溜まっています。

# なので。。
間違えて印刷をしていたのを忘れて、スプーラーに溜まった状態で、該当プリンターのネットワークにつなぐと（例えばVPNで別環境からプリンターのネットワークに入ったりする）印刷物が印刷されちゃうんですよね。
印刷物が出力されたことに気がついてすぐに破棄できたらいいのですが、気が付かないで放置していて悪意のある人がその紙を持って帰ってしまったら、情報流出の危機となってしまいます。。
（こんな細かいことなんで気がついたんだ？という疑問は持ってはなりません。駄目です。）

# これを防ぎたい！
こんなおっちょこちょいな人種のために、スプーラーに印刷物が溜まった状態の場合はプリンタードライバーがユーザーに印刷するか問い合わせる機能とかがWindowsにあるんじゃないかな？と思って色々ググっていたのですが、ちょうどいいのが見つかりませんでした。
スプーラーを使わないで直接プリンターに印刷物を送る設定を選ぶこともできますが、プリンターごとに設定を変えたりしなきゃいけないですし、設定わすれたりしそうだなと思いました。

# 防衛方式
我々エンジニアはなければ作ればいいのです。なので、ちょっと作って見ました。
### コンセプト
スプーラーにただただ印刷物が溜まっている分には無害なわけで、ネットワークが切り替わったタイミングで勝手に印刷されなければいいのです。なので、ネットワーク切り替わるイベントを拾って、スプーラーのデータを全て削除してしまえばいいんじゃないかと考えました。

# 実装方法
## 環境
環境はwindows10です
## プログラム
### 解説
windows10なので、windowsのバッチファイルでつくりました。
### ソースコード
やってることはシンプル。
スプーラーとめて、ファイル消して、スプーラーを起動するだけｗ

``` bat
net stop spooler
del C:\WINDOWS\system32\spool\PRINTERS\*.SHD
del C:\WINDOWS\system32\spool\PRINTERS\*.SPL
net start spooler
```
参考サイト
https://dooluka.hatenadiary.org/entry/20101121/1290267911

# ネットワーク切り替わるタイミングで、上記のbatファイルを動かす。
作成したbatファイルを、ネットワークが切り替わるイベントを拾って、動く様に登録します。
下記記事などを参考に、タスクスケジューラーにbatファイルを登録してください。
 
参考サイト
https://www.it-swarm.dev/ja/windows/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E6%8E%A5%E7%B6%9A%E5%88%87%E6%96%AD%E6%99%82%E3%81%AB%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/959472671/

# できる様になったこと
 ネットワークが切り替わったタイミングで勝手に印刷されることがなくなりました。 これでおっちょこちょいな私の様な人でもちょっとだけ情報流出の可能性が減りました（ちょっとだけです）

# 結論
SE、プログラマーは個人情報扱うことの多いお仕事なので、個人情報の流出には気をつけましょう。
Railsで使用するワンライナーの個人的なまとめ

## 概要
Railsで使用するワンライナーの個人的なまとめ


### routes情報を出力

**使用シーン**
railsコマンドのroutesを使用すると4つの情報が表示される。
Prefix , Verb, URI Pattern, Controller#Action

```shell
//routesの実行
$ ./bin/rails routes

//結果の出力----
Prefix Verb   URI Pattern                                                                            Controller#Action
users POST   /v1/users(.:format)                                                                      users#create
user GET    /v1/users/:id(.:format)                                                                 users#show
...
```

この出力情報を加工して、稀にパス情報(URI Pattern)だけ抜き出したい場合がある。

```shell
// v1  から始まる パス文字列のみが欲しい場合
$ ./bin/rails routes |grep v1 |awk -F " " '{ print $(NF-1)}'

// 結果の出力ｰｰｰｰｰｰｰ
/v1/users(.:format)
/v1/users/:id(.:format)
...

// Verbも含んで結果を出したい場合
./bin/rails routes |grep v1 |awk -F " " '{ print $(NF-2) " " $(NF-1)}'
POST /v1/users(.:format)
GET /v1/users/:id(.:format)
...
```

**解説**
1. 結果リストをv1のみに絞っている(絞る文字は任意で変更)
2. awk -F " " で スペース(" ")をセパレータに指定している。
3. print $(NF-1) で　NF（末尾）から1文字目を printしている。(末尾から指定するのがポイント。でないとズレる）

ここに、sortしたりするとざっくりのエンドポイントの一覧が得られる。
Firebase - Firestoreからtimestamp型を取得する場合のiOSとAndroidの違いを吸収する


Firebaseのtimestamp型をDateTime型にそのまま代入しようとするとエラーが発生します。

こちらのページにいくつか解答が載っていて


[Flutterアプリエラー-タイプ 'Timestamp'はタイプ 'DateTime'のサブタイプではありません](https://www.it-swarm.dev/ja/dart/flutter%E3%82%A2%E3%83%97%E3%83%AA%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%BF%E3%82%A4%E3%83%97-%27timestamp%27%E3%81%AF%E3%82%BF%E3%82%A4%E3%83%97-%27datetime%27%E3%81%AE%E3%82%B5%E3%83%96%E3%82%BF%E3%82%A4%E3%83%97%E3%81%A7%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93/806639755/)

以下を採用したところAndroidではエラーになるようです。(2020/09/13時点)

```
DateTime parseTime(dynamic date) {
  return Platform.isIOS ? (date as Timestamp).toDate() : (date as DateTime);
}
```
さらにその下に載っている解答が有効なようです。

```
DateTime updateDateTime = DateTime.fromMillisecondsSinceEpoch(
        map['updatedatetime'].millisecondsSinceEpoch);
```


なので、このように修正しました。

```
  static DateTime parseTime(dynamic date) {
    return Platform.isIOS ? (date as Timestamp).toDate() : DateTime.fromMillisecondsSinceEpoch(date.millisecondsSinceEpoch);
  }

```
※イニシャライザで使用するので、staticを付けています。


### 環境

```
Android Studio 4.0.1
```

```
Flutter 1.20.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 216dee60c0 (11 days ago) • 2020-09-01 12:24:47 -0700
Engine • revision d1bc06f032
Tools • Dart 2.9.2
```

```
Dart SDK version: 2.9.2 (stable) (Wed Aug 26 12:44:28 2020 +0200) on "windows_x64"
```
ubuntu18.04 で X11 を使う (C言語)

X11ライブラリのインストール

```bash
sudo apt update
(sudo apt upgrade)
sudo apt install libx11-dev
```

```c
#include <X11/Xlib.h>             //Xlibに必要なインクルード
#include <X11/Xutil.h>
```

Xlibに必要なライブラリの配置を確認する。
ヘッダファイルと共有ライブラリの配置の確認。

```bash
sudo find /usr -type f -name Xlib.h
sudo find /usr -type f -name libX11.so
```

その他コンパイルオプションをそろえたコマンド

```bash
gcc -o xlib_test xlib_test.c -O2 -I/usr/include -L/usr/lib/x86_64-linux-gnu -lX11 -lm
```

真っ黒なウィンドウを表示するだけのテストプログラム
http://cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/XLIB/xlib2.html
上記のサイトのプログラムをそのまま試しました。

```c
// reference URL
// http://cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/XLIB/xlib2.html

#include <X11/Xlib.h>             //Xlibに必要なインクルード
#include <X11/Xutil.h>
#include <stdio.h>

int main( void )
{
    Display* dis;                       //Display pointer
    Window   win;                       //Window  ID
    XSetWindowAttributes att;           //窓属性の変数
    XEvent ev;                          //イベント取り込み変数

    dis = XOpenDisplay( NULL );         //Xserverとの接続
    win = XCreateSimpleWindow( dis, RootWindow(dis,0), 100, 100,
        256, 256, 3, WhitePixel(dis,0), BlackPixel(dis,0) );  //窓の生成

    att.backing_store = WhenMapped;     //絵を保存する設定をする
    XChangeWindowAttributes( dis, win, CWBackingStore, &att );
    

    XMapWindow( dis, win );             //窓の表示
    XFlush( dis );                      //リクエストの強制送信
        
    XSelectInput( dis, win, ExposureMask );
    do{                                 //窓が開くの待つループ
        XNextEvent( dis, &ev);
    }while( ev.type != Expose ); // Exposeイベントが届くまでここを繰り返す

    // ここまで来たら真っ黒な窓が登場しているはず。

    getchar();  // リターンキーが押されるまで待つ。

    XDestroyWindow( dis, win );         //窓の消去
    XCloseDisplay( dis );               //Xserverと断線

    return 0;
}
```

`Makefile`を作成することでコンパイルを楽にする。

```Makefile
CC	= gcc
CFLAGS	= -O2 -I/usr/include
LIBS	= -L/usr/lib/x86_64-linux-gnu -lX11 -lm
TARGET	= xlib_test
SRC	= xlib_test.c

$(TARGET): $(SRC)
	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)

clean:
	rm $(TARGET)
```

`$@`はターゲットファイル。
`$^`は素材指定しているファイル。
Python用のDXFファイル読み書きライブラリ「ezdxf 」を使ってDXFファイルをPNGに変換する

# モジュールのバージョン
python v3.8.5
ezdxf v0.14
matplotlib v3.3.1

# サンプルのDXFファイルを生成する
※[このサイト](https://emotionexplorer.blog.fc2.com/blog-entry-68.html)のソースコードをマルパクリしました。
ありがたや🙏
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357470/18b4690c-e977-776d-dffe-b8c36fb282d0.png)


``` py
import ezdxf
import math

DXFVERSION  = 'R2010'
NUMCORNERS = 5

def create_dxf():
    """ 五芒星のDXFファイルを生成
    """
    # 星の角座標計算
    startangle = math.pi / 2.0
    pitchangle = math.pi * 2.0 / 5.0

    # オフセットと半径
    offset_x, offset_y, radius = 100, 100, 10

    points = []
    for i in range(0, NUMCORNERS):
        angle = startangle + pitchangle * i
        if 2.0 * math.pi < angle:
            angle = angle - 2.0 * math.pi
        x = math.cos(angle) * radius + offset_x
        y = math.sin(angle) * radius + offset_y
        points.append((x, y))
    
    # DXFインスタンス生成
    dxf = ezdxf.new(DXFVERSION)
    modelspace = dxf.modelspace()

    # 五芒星描画
    last, i, count = -1, 0, 0
    while count < NUMCORNERS + 1:
        if 0 <= last:
            modelspace.add_line(points[i], points[last])
        last = i
        i += 2
        if NUMCORNERS <= i:
            i -= NUMCORNERS
        count += 1
    
    # DXFファイル出力
    dxf.saveas('/<出力先のパス>/star.dxf')

if __name__ == "__main__":
    create_dxf()
```
　
# DXFファイルをPNGファイルに変換する
ezdxfはDXFファイルを画像やPDFにするためのアドオンを持っているので、それを利用して変換します。

``` py
import ezdxf
from ezdxf import recover
from ezdxf.addons.drawing import matplotlib


def convert_dxf_to_png():
    try:
        dxf, auditor = recover.readfile('/<DXFファイルのパス>/star.dxf')
    except IOError as ioerror:
        print(ioerror)
        raise ioerror
    except ezdxf.DXFStructureError as dxf_structure_error:
        print(dxf_structure_error)
        raise dxf_structure_error

    if not auditor.has_errors:
        matplotlib.qsave(dxf.modelspace(), '/<出力先のパス>/star.png')

if __name__ == "__main__":
    convert_dxf_to_png()
```
こんな短いコードでDXFファイルをPNGに変換できました。
拡張子を「.jpg」とか「.pdf」にしても機能します。
Python便利！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357470/fc34ba72-73ed-4b32-4778-f17b6352727c.png)
Java 部分文字列

#【Java 部分文字列】

業務でよく使用する Javaの部分文字列のメモです。

##部分文字列　substring

substringメソッドの第一引数に抜き出し開始の位置（beginIndex）、第二引数に抜き出し終了の位置（endIndex）を指定する。

部分文字列は、beginIndexから始まり、endIndex-1 までを表す。

##・substringの例

```java
"サンプル文字".substring(beginindex, endindex-1);
```

beginindexは、0番目から数え始める。
配列の添え字の数え方と同じ。

##・文字の長さは、endIndex - beginIndex

```java
"サンプル文字".substring(0, 4);

//出力結果:サンプル
```
この場合だと、文字の長さ 4-0=4 
なので、４文字が部分文字列として表示される。
AndroidスマホにApacheとPHPとMySQLをインストールする

UerLandを使ってAndroidスマホにApacheとPHPとMySQLをインストールします。

UserLandでUbuntuのsshをインストールするとポート2022番号でログインをすることができます。

~~~~
ssh USERNAME@192.168.xxx.xxx -p2022 ;
~~~~

ログインをしたらまずは最新にアップデート

~~~~
sudo apt update ;
sudo apt upgrade -y ;
sudo apt install -y nano ;
~~~~

Apache2 PHP MySQLをインストール

~~~~
sudo apt install apache2 php php-mysql mariadb-server ;
~~~~

Apacheの開放ポートを80から8080へ変更

~~~~
emacs /etc/apache2/ports.conf ;
~~~~

下記修正

~~~~
Listen 80
↓
Listen 8080
~~~~

サービスとして起動（systemctrlは使用できないため）

~~~~
service apache2 start ;
~~~~

他の端末からブラウザで

~~~~
http://192.168.xxx.xxx:8080
~~~~

を開く。

/var/www/html/内のファイルにアクセスができます。

PHPの動作確認

~~~~
mv /var/www/html/index.html /var/www/html/index.html.back ;
nano /var/www/html/index.php ;
~~~~

index.phpに下記を記述

~~~~
<?php

phpinfo();
~~~~
保存

再び

~~~~
http://192.168.xxx.xxx:8080
~~~~

を開くとphpの情報がズラリと出ます。

ワードプレスも行けそうです。
個人情報保護の強化（情報セキュリティ）ー午後

応用情報技術者平成29年秋期 午後1


ファイル：2017h29a_ap_pm_qs.pdf

参照：
https://www.ap-siken.com/kakomon/29_aki/pm01.html

メモも簡単に記載します。
詳細の分析は、上記リンクをご参照くだいますようよろしくお願いします。


**１、本文中の下線①について，どのような問題があるか。40字以内で述べよ。**

過去暗号化したデータを復号できなくなる　（私の答え）
→
削除された暗号化鍵で暗号化されたバックアップデータを復号できない（参考答え）

＜＜①、②＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/0784ec72-434c-49a6-feb9-4ae3add7136a.png)



**２、本文中の下線②について，仮IDから元の会員番号をどのようにして特定することが可能か。35字以内で述べよ。
cはハッシュ関数です。**

ハッシュ関数で６桁数字の組合せを変換して仮IDと合致する（私の答え）
→
会員番号となり得る全数字列を同じハッシュ関数で変換して突き合わせる（参考答え）


**３、本文中のeに入れる適切な字句を10字以内で述べよ。**
dは盗聴です。
eは、有資格者だけに情報を送れますが、もし有資格者ではない方におくってしまったらまずいですね。

資格者ではない方（私の答え）
→
意図しない宛先（参考答え）

＜＜e＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/888abd2f-e6cd-0866-2ebe-4e6ab41e6292.png)
Pythonの集合演算

Pythonのsetでの集合演算方法を整理する。

#【`set`】
* 集合を生成する。
* リテラルは、波カッコ「{}」になる。

```python
X = set([1,2,3,4,5,6,1,1,1])
print(X)
# {1, 2, 3, 4, 5, 6}

Y = {9,9,9,4,5,6,7,8,9}
print(Y)
# {4, 5, 6, 7, 8, 9}
```

# 【`<set>.union(set)`】
* 和集合（OR）
* 演算子「|」で代用できる。

```python
Z = X.union(Y)
print(Z)
# {1, 2, 3, 4, 5, 6, 7, 8, 9}

Z = X | Y
print(Z)
# {1, 2, 3, 4, 5, 6, 7, 8, 9}
```

# 【`<set>.intersection(set)`】
* 積集合（AND）
* 演算子「&」で代用できる。

```python
Z = X.intersection(Y)
print(Z)
# {4, 5, 6}

Z = X & Y
print(Z)
# {4, 5, 6}
```

# 【`<set>.symmetric_difference(set)`】
* 対称差（XOR）
* 演算子「^」で代用できる。

```python
Z = X.symmetric_difference(Y)
print(Z)
# {1, 2, 3, 7, 8, 9}

Z = X ^ Y
print(Z)
# {1, 2, 3, 7, 8, 9}
```

# 【`<set>.difference(set)`】
* 差集合
* 演算子「-」で代用できる。

```python
Z = X.difference(Y)
print(Z)
# {1, 2, 3}

Z = X - Y
print(Z)
# {1, 2, 3}
```

# 【`<set>.issubset(set)`】
* 下位集合（部分集合）かの判定
* 演算子「<=」で代用できる。

```python
X = {1,2,3}
Y = {1,2,3,4,5}

Z = X.issubset(Y)
print(Z)
# True

Z = X <= Y
print(Z)
# True
```

# 【`<set>.issuperset(set)`】
* 上位集合の判定
* 演算子「>=」で代用できる。

```python
X = {1,2,3,4,5}
Y = {1,2,3}

Z = X.issuperset(Y)
print(Z)
# True

Z = X >= Y
print(Z)
# True
```

# 【`<set>.isdisjoint(set)`】
* 共通要素が無いかの判定

```python
X = {1,2,3}
Y = {4,5,6}

Z = X.isdisjoint(Y)
print(Z)
# True
```

# 備考
本記事はブログ「[雑用エンジニアの技術ノート](https://scrapbox.io/nezuq/)」からの移行記事です。先のブログは削除予定です。
AWS SAAに合格したので勉強法を書きます

##教材
####この1冊で合格! AWS認定ソリューションアーキテクト - アソシエイト テキスト&問題集 (Amazon prime)
####AWS認定資格試験テキスト AWS認定 ソリューションアーキテクト-アソシエイト (日本語) 単行本
####Udemy AWS SAA 練習問題

##勉強時間
####この1冊で合格! AWS認定ソリューションアーキテクト - アソシエイト テキスト&問題集 (Amazon prime)
２周ぐらい(20時間)
####AWS認定資格試験テキスト AWS認定 ソリューションアーキテクト-アソシエイト (日本語) 単行本
1周半ぐらい(15時間)
####Udemy AWS SAA 練習問題
６の模擬テストを4周(24時間)

###合計 59時間

##勉強方法
###1.教材別勉強法
####この1冊で合格! AWS認定ソリューションアーキテクト - アソシエイト テキスト&問題集 (Amazon prime)
この本はAWS認定資格試験テキストより細かくサービスについて紹介していたので、テストでもかなり役に立ちました。しかし、詳しく紹介している分、サービスの数が少ないので、このテキストだけでは、本番のテストの問題をカバー仕切れないと感じました。しかし本番テストの高難度の問題を解くだけの知識が得られる。本書に記載していた模擬テストは、本番のテストと比べて少し簡単だと思いました。

####AWS認定資格試験テキスト AWS認定 ソリューションアーキテクト-アソシエイト (日本語) 単行本
この本は、全体的な流れについて把握するのに大気に役立ちました。幅広いサービスについて紹介していて、マイナーな知識を問われる問題を解くのに役立ちました。まず初めにこのテキストを読んで、AWSに関する知識の全般を学んでから、「この一冊で合格！」に行った方が良かったと感じます。このテキストに記載されている模擬テストは、本番と比べて簡単だと感じました。
####Udemy AWS SAA 練習問題
このUdemyの練習問題は本番に比べても難しく、このテストで合格点を超えられるようになればかなり合格は近いと思います。私もこの問題を何周もして8~9割の点数を取れるようになってから本番に挑みました。また、この教材は、全ての問題について解説がついているので、解説も読み込むとより深く知識を得ることができると思います。付属しているチートシートも活用できます。

###2.勉強のロードマップ

AWS認定資格試験テキスト -> 本番テスト(不合格) ->  この一冊で合格! -> Udemy -> 本番テスト(合格!)
Windows10 HomeにDokerをベースとした開発環境を構築する 2020 ver. その1　WSL2ベースのDocker構築まで 


## はじめに
最近開発をしてません。なんとなくWindowsパソコンを買いました。Windows 10 Homeつまりです。つまりHome開発環境を整えることが必然となりました。

## どんな開発がしたいの？
数年前までMacを利用して以下のような開発をしていました。
・Webアプリケーション（フロント・サーバーサイド）
・AWSインフラ構築（コードで定義する）

上記のような開発をWindowsで構築しようとするととにかく大変でした（私の記憶では）Rubyの導入から躓いたり、
Railsを動かしていても異常に動作が遅く使い物にならなかったりと、とにかくストレスでした。

なので表題にあるMac並みというのは私がストレスなくWebアプリケーションの開発をローカル及びAWS上で実施できる環境を構築するということとなります。

## どうやって実現するか
ざっとながら下調べをしまして、Dockerをベースとした開発環境が構築できればよいのかなとあたりをつけました。
しかしWindowsでは仮想環境の実行にHyper-Vが必要だったことを思い出し、Windows10 Homeである私にはもう無理だ・・・
と勝手に諦めかけていたとき「WSL2」と天の声が聞こえてきました。
実現方針は決まりました。
WSL2 → Doker → VSCode です。もう他に方法はありません。

## WSL2 をWindows10 Homeに導入
WSL2の導入可能なWindows2020年バージョンは2020年9月現在以下となります。
・「Windows 10 1903」および「Windows 10 1909」（2020年8月20日より導入可能となった）
・「Windows 10 2004」

私のWindowsのバージョンは1909でしたので導入可能ですが、せっかくですので2004にアップデートした後
導入します。

※ 2004でWLS2を導入する場合、2020年9月10日現在一部のセキュリティパッチの影響で不具合がでることが報告されています。
https://www.zdnet.com/article/windows-10-2004-patch-tuesday-problem-update-breaks-wsl2-say-users/
Hyper-Vが原因の一つとされていますので、Windows Homeでは影響しないことを信じて進めていきます

### Windows 10 2004 導入
現在のバージョンを確認するにはWinキー＋Rで以下のコマンドを実行します。1909でした。

```
winver
```
あとはWindows Updateです。私の場合は下のような画面でしたので、「ダウンロードしてインストール」を押してただひたすらに待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123873/d49001ec-f64f-e407-99ce-5e6812014219.png)

待っている間にWSL2導入手順の確認です。
「Windows 10 2004」からOSの標準機能となりましたが、標準機能となっただけで、機能を有効化しないと使用できません。有効化します。
「Windowsの機能の有効化または無効化」というそのままの機能があります。Winキー＋Rで以下のコマンドを実行します

```
OptionalFeatures
```
「Linux用Windowsサブシステム」と「仮想マシンプラットフォーム」にチェックし、インストールを実施します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123873/2b89e82a-7c9b-ba9b-cd86-dfb0e1df22c7.png)

これでWSL2が導入されました。

## Docker Desktop　のインストール
以下のURLからDocker Desktopをインストールします
https://hub.docker.com/editions/community/docker-ce-desktop-windows

以下のようにWSL2のサポートが有効になっていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123873/5abcd204-9def-9e14-21c0-f866d20b3c5b.png)

インストールが完了すると以下のように「WSL2のLinuxカーネルは別のインストーラーでアップデートが管理されてるからインストールしてね」と案内がでますので従います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123873/fc59c9dc-6a84-0969-f6a4-44b706635a1f.png)


Docker Desktopのダッシュボードをみると・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123873/9349ef76-8ae9-a3ff-caa7-554213f55782.png)

WSL2Dを基盤としたDockerがこれで動作したようです。動作確認をするためダッシュボードに従って以下のコマンドをPowerShell上で実行してみます。

```
docker run -d -p 80:80 docker/getting-started
```

ダッシュボードを見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123873/87e1034a-f56a-d135-e4e8-ff4b1d582696.png)

80番ポートでなにやらサーバーがリッスンしているようなので http://localhost/tutorial/ へアクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123873/ac905834-826f-c4fd-4c01-934c894df5dc.png)

コンテナが動作しました。これでWindows 10 Homeでもdockerを使った開発ができるはずです。[その２](https://qiita.com/TakaK/items/3aca2e2d89063f61bfe5)に続く。
Chart.js 値が正か負か判定し、グラフ色を変える

![Chart.js - 正と負で色を分ける.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102434/a48a80df-b090-6da3-db5c-ebe61a949565.png)


##デモ

https://codepen.io/kakuta_yu/pen/RwayOxj
※CodePenに遷移します


##全コード

###HTML

```html
<canvas id="myChart"></canvas>
```

###JavaScript

```js
// 値を設定
var datasets = [
  {
    label: '利益額',
    data: [-960, -640, -220, 30, -80, 300, 660],
    backgroundColor: ['#3F88C5'] // 配列にしておく必要がある
  }
]

// 各棒グラフの値が正か負かによって色分け
for (var i = 0; i < datasets[0].data.length; i++) {
  if (datasets[0].data[i] > 0) {
    datasets[0].backgroundColor[i] = '#3F88C5' // 値が正の場合は青
  } else {
    datasets[0].backgroundColor[i] = '#FF5E5B' // 値が負の場合は赤
  }
}

/* ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
  グラフ描画
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー */
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ['2014年', '2015年', '2016年', '2017年', '2018年', '2019年', '2020年'],
    datasets: datasets
  },
});
```


##解説

###値を設定
描画する値を変数に入れます。
この時、**backgroundColorを配列の形にしておく**ことを忘れないでください。
あとで値を判定してbackgroundColorに青と赤のカラーコードを入れていきますが、配列にしておかないとうまく入ってくれません。

```js
// 値を設定
var datasets = [
  {
    label: '利益額',
    data: [-960, -640, -220, 30, -80, 300, 660],
    backgroundColor: ['#3F88C5'] // 配列にしておく必要がある
  }
]
```


###値の判定と色の設定
値の数だけループを回して色を設定します。
例えば3つ目の値が負だった時、backgroundColor[2]に赤のカラーコードを入れます。

```js
// 各棒グラフの値が正か負かによって色分け
for (var i = 0; i < datasets[0].data.length; i++) {
  if (datasets[0].data[i] > 0) {
    datasets[0].backgroundColor[i] = '#3F88C5' // 値が正の場合は青
  } else {
    datasets[0].backgroundColor[i] = '#FF5E5B' // 値が負の場合は赤
  }
}
```

###グラフの描画
上記で設定したdatasetsをグラフ描画コードへ入れます。
今回は最低限のコードしか記述していないため、デモでは凡例の色が赤になっていますが、このあたりはoptionで凡例を非表示にといった処理が必要です。

```js
/* ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
  グラフ描画
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー */
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ['2014年', '2015年', '2016年', '2017年', '2018年', '2019年', '2020年'],
    datasets: datasets
  },
});
```
Pythonでのリスト要素の取得

# 1. 指定要素を取得する。（インデックス指定）

* 要素番号（インデックス）は0から開始。
* 負の要素番号は-1から開始。後ろから数えて、指定位置の要素を取得。

``` $ list = ['A', 'B', 'C', 'D', 'E']  ```

```python
list[0]
# 'A'

list[1]
# 'B'

list[2]
# 'C'

list[-1]
# 'E'

list[-2]
# 'D'
```

# 2. リストの一部を取得する。（スライシング）

* `[開始番号:終了番号:ステップ数]`と指定。終了番号の要素は含まれない。
* 開始番号省略時は、最初の要素から取得。
* 終了番号省略時は、最後の要素まで取得。
* ステップ数省略時は、1（1個ずつ）が指定。

``` list = ['A', 'B', 'C', 'D', 'E']  ```

```python
list[3:]
# ['D', 'E']

list[:3]
# ['A', 'B', 'C']

list[::-1]
# ['E', 'D', 'C', 'B', 'A']

list[1:4:2]
# ['B', 'D']

list[4:1:-2]
# ['E', 'C']
```

# 3. クエリで取得する。（内包表記）

* `[要素の加工コマンド for 要素名 in リスト if 抽出条件]`と指定。if以降は省略可能。
* 「in」の箇所で`enumerate(リスト)`を指定すると、各要素を「要素番号, 要素」の組合せで取得。
* 「in」の箇所で`zip(リスト1, リスト2)`を指定すると、各要素を「リスト1の要素, リスト2で同位置の要素」の組合せで取得。
* `{ }`で囲った場合はセットや辞書、`( )`で囲った場合はジェネレータが返却。

``` list = ['A', 'B', 'C', 'D', 'E'] ```
``` list2 = ['F', 'G', 'H', 'I', 'J'] ```

```
[x.lower() for x in list]
# ['a', 'b', 'c', 'd', 'e']

[x.lower() for x in list if x!='B']
# ['a', 'c', 'd', 'e']

[str(i) + x for i, x in enumerate(list)]
# ['0A', '1B', '2C', '3D', '4E']

[x + y for x, y in zip(list, list2)]
# ['AF', 'BG', 'CH', 'DI', 'EJ']

{x.lower() for x in list}
# {'a', 'b', 'c', 'd', 'e'} ※セット

{x:x.lower() for x in list}
# {'A': 'a', 'B': 'b', 'C': 'c', 'D': 'd', 'E': 'e'} ※辞書

(x.lower() for x in list)
# <generator object <genexpr> at ?> ※ジェネレータ
```

# 備考
本記事はブログ「[雑用エンジニアの技術ノート](https://scrapbox.io/nezuq/)」からの移行記事です。先のブログは削除予定です。
Blocklyのデザインをモダンにする

Blocklyは非常に優れたプロダクトですが、その歴史の長さからかどうもデザインが古臭いです。簡単なカスタマイズで現代風のデザインにするための設定項目を紹介します。

## ブロックに影をつけない

Blocklyの標準設定では、ブロックに影ができるようになっています。

![3D Block](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534541/75206618-fdfb-55fb-99d0-29723ca13835.png)

`Blockly.inject`の際に`renderer`オプションを指定することで、ブロックのレンダリング方法を変えることができます。この`renderer`オプションにしていするレンダラーは`Blockly.blockRendering.Renderer`クラスを継承したクラスで、標準で

* Blockly.geras.Renderer (デフォルト)
* Blockly.minimalist.Renderer **(npmの`blockly`パッケージでは使用できなかった)**
* Blockly.thrasos.Renderer
* Blockly.zelos.Renderer

が定義されています。Googleの謎名前解決システムにより文字列で指定できるようです。

```js
Blockly.inject(element, {
  renderer: 'thrasos',
});
```

![Flat Block](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534541/da323ea1-34f9-5349-f78c-004e034de962.png)

時代はフラットデザインです。`thrasos`レンダラはいい感じにフラットにしてくれます。`zelos`は尖った感じです。

## ブロックの色合いを鮮やかにする

Blockly直下の設定項目を書き換えることで対応できます。Hueはブロックごとに固有の値です。概念自体はよく考えられていますがコードが古臭い・・・。

```js
Blockly.HSV_SATURATION = 0.8;
Blockly.HSV_VALUE = 1;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534541/95c92de6-eeb7-b91b-bae8-d2a1dda8c055.png)

## ブロックの枠線の色を変える

各ブロックはSVGのpathで表現されています。よってCSSの`!important`指定で上書きすれば変更は自由に行えますが、すべての枠線が同じ色になってしまいます（でも実はそれで十分な場合が多い）。

`Blockly.blockRendering.ConstantProvider#generateTertiaryColour_`メソッドをオーバーライドすることで、ブロックの背景色から枠線の色を求める挙動を変更できます。`ConstantProvider`クラスは各レンダラーごとに継承できるようになっていますが、この記事を執筆した時点では標準のレンダラーがTypeScriptの型定義に含まれていませんでした。

ここは原始的ですがprototypeの書き換えで対応してみます。

```js
Blockly.blockRendering.ConstantProvider.prototype.generateTertiaryColour_ =
  (colour) => Blockly.utils.colour.blend('#000', colour, 0.3) || colour;
```

[標準では枠線の色はブロックの色より薄くなる](https://github.com/google/blockly/blob/9ab6273e4c2fb0cd25004650d0020490294eed50/core/renderers/common/constants.js#L759)のですが、逆に濃くなるようにしてみました。

## まとめ

GoogleさんはBlocklyをTypeScript + ES Modulesで書き直してくださいm(_ _)m
GitHub Container Registry(ghcr.io)にdocker pushする

アドレスが長くて忘れるのでメモしておく．

docker tagコマンドの形式は以下に従う．

```bash
docker tag <コンテナ名> ghcr.io/<GitHubのユーザ名>/<パッケージ名>/<コンテナ名>:<タグ>
```

例えば以下になる．

```bash
$ docker images
REPOSITORY                           TAG                                              IMAGE ID            CREATED             SIZE
stns-build                           latest                                           449f1c2d3562        4 minutes ago       35.4MB

$ docker tag stns-build:latest ghcr.io/tomoyk/stns-client/stns-client:v0.1

$ docker images
REPOSITORY                               TAG                                              IMAGE ID            CREATED             SIZE
stns-build                               latest                                           449f1c2d3562        6 minutes ago       35.4MB
ghcr.io/tomoyk/stns-client/stns-client   v0.1                                             449f1c2d3562        6 minutes ago       35.4MB
```

最後にPushする．

```bash
docker push ghcr.io/tomoyk/stns-client/stns-client:v0.1
```

弾かれる場合は `~/.docker/config.json` を見てみる．
`auths` の下に`ghcr.io`があるか確かめる．

```json
{
    "auths": {
        "ghcr.io": {
            "auth": "xxxx"
        }
     }
}
```

ない場合は，GitHubのWeb UIからPersonal Access Tokenを発行する．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/6c633d36-85e7-1907-a589-de556dce7dd0.png)

Tokenを `~/TOKEN.txt` として保存して以下のコマンドを実行する．

```bash
cat ~/TOKEN.txt | docker login https://ghcr.io -u <ユーザ名> --password-stdin
```

再び `docker push xxx` を実行する．
openpyxlでiter_rowsを先頭に戻すには、load_workbookでファイルを読み込み直すしかなさそう

# やろうとしたこと
- pythonでEXCELを読み書きできる`openpyxl`ライブラリがある
- `iter_rows`メソッドでEXCELを1行ずつ読み出せる(DBのカーソルに似ている)
- `ws.append()`で行を追加した後で、先頭からもう一度処理しようとすると、イテレータが末尾に移動したままで、先頭に戻らない

# 考えたこと
- このイテレータを先頭に戻すメソッドが無さそう
    - 古いバージョンでは「row_offset」という、それっぽい引数があったのですが、最新版の3.0.5では存在しません。
- ソースコード： https://foss.heptapod.net/openpyxl/openpyxl/-/blob/branch/3.0/openpyxl/worksheet/worksheet.py#L405


# 対応
- `load_workbook`でファイルを読み込み直す

# 環境
- Python 3.6.9
- openpyxl 3.0.5
Sublime Text 便利なショートカットコマンド

※この記事はプログラミング初心者に向けて書いております。
#はじめに
**ショートカットキー**って便利ですよね。みなさんもショートカットキーをよく使われていると思います。
通常５秒かかる動作をショートカットキーを使うと１秒で済むなんてこともありますよね。
ほんの数秒の短縮だとしても、今後コードを書いていくことを考えると**膨大な時間の節約に繋がります。**
覚えるのは面倒くさいですが、初心者のうちにサクッと覚えてしまって、作業効率を上げていきましょう。

##環境
* macOS Catalina
* Sublime text ver 3.2.2

#Sublime text
私の通っているプログラミングスクールでは使用するテキストエディタの指定があり、**Sublime Text**というエディタを使っています。

「**もっと早く知りたかった、、、**」っていう便利なショートカットがありますので、それらを共有していきたいと思います。

# １.&emsp; 「タブの移動」&emsp;  command + option +&emsp;←&emsp; or&emsp; →&emsp;
タブが大量にあるとカーソル操作での移動は意外とストレスです。
サクッとタブの移動ができると気持ちがいいです。

# 2.&emsp; 「タブの削除」&emsp;  command + W 
気付いたらタブが何件も開いてるなんてことがしょっちゅうあります。
✖︎ボタンをぽちぽちする作業から解放されましょう。

# 3.&emsp; 「一つ前に戻る」&emsp;  command + Z
**command + Y**　で 「**一つ前に進む**」 です。
自分の人生にも command + z　を使いたいです。 

# 4.&emsp; 「行の削除」&emsp;  command + K

command + shift + k で行を削除した後に改行も一緒にしてくれます。
余計に消してしまったら **command + Z** で戻りましょう。


# 5.&emsp; 「下の行にコピー＆貼り付け」&emsp;  command + shift + D
コピーして改行して貼り付けまでしてくれる優秀なショートカットです。
私もこんなエンジニアになりたいです。


# 5.&emsp; 「windowを２分割」&emsp;  command + option + 2
二つのファイルを見比べて作業したい時にとても便利です。
command + option + 1 で一画面に戻せます。


# ６.&emsp; 「履歴から貼り付け」&emsp;  command + K + V
少し前にコピーしたものまた貼り付けたいことってあると思います。でも今は別のものをコピーしているから、またコピーし直さなきゃ、、、って時に活躍します。


# 7.&emsp; 「複数行まとめてインデントをする」&emsp;  複数行選択した状態で  tab
一行ずつインデントしていたあの頃が懐かしいです。
まとめてインデントを戻したい時は **複数行選択した状態で shift + tab**


# 8.&emsp; 「コメントアウト」&emsp;  command + /
複数行まとめてコメントアウトすることもできます。
railsの<%= hoge %>のコメントアウトは<%**#**= hoge %>でできます。


# 9.&emsp; 「ファイル検索」&emsp;  command + P
ファイルを探すのって結構大変ですので検索を使ってみるといいかもしれません。

# 10.&emsp; 「横断検索」&emsp;  command + shift + F
検索窓が表示されます。Findに検索したい文字を入れるとその文字のあるファイルが一覧で表示されます。

#最後に
以上１０個のショートカットキーを紹介しました。他にも便利なショートカットがあるみたいなので、より効率を求める人は調べてみるといいかもしれませんね。
CentOS6で、GUIとCUIを切り替える。

# 操作
* CUIの場合は、次のコマンドを実行する。
* GUI（GNOME Desktop）の場合は、「アプリケーション >> 端末」を起動し、実行する。

# コマンド（CUIの場合）

```bash
# 特権ユーザに切り替える
su -
# 現在のOSの実行モードを確認する。（3:CUI, 5:GUI）
runlevel
# CUI/GUIを切り替える。（3:CUI, 5:GUI）
telinit 5
# 現在のOSの実行モードを再確認する。
runlevel
# 元のユーザに戻る
exit
```

# 追加調査
現在のOSの実行モード（ランレベル）の詳細

* [ランレベルとは](https://www.atmarkit.co.jp/flinux/rensai/linuxtips/156whatrunlv.html)

CentOS7での切り替え

* [systemdによるCentOS 7の管理 | Think IT（シンクイット）](https://thinkit.co.jp/story/2014/12/11/5388)

# 参考

* [telinitコマンド｜Linuxコマンド](https://www.linuxmaster.jp/linux_skill/2010/06/133telinit.html)

# 備考
　本記事はブログ「[雑用エンジニアの技術ノート](https://scrapbox.io/nezuq/)」からの移行記事です。先のブログは削除予定です。
Windows10のシャットダウン・再起動・スリープのコマンド

Windowsコマンドの中でよく使うものなので、メモする。

# シャットダウン
```windowsコマンド
%WINDIR%\system32\shutdown.exe -s -f -t 0
REM -f:強制的に実施, -t:指定した秒数後に実施
```

# 再起動
```windowsコマンド
%WINDIR%\system32\shutdown.exe -r -f -t 0
```

# スリープ（休止状態）
```windowsコマンド
%WINDIR%\system32\rundll32.exe PowrProf.dll,SetSuspendState
REM 注意：ハイブリッドスリープ（バッテリ切れの時にもスリープ前の状況が復旧する）ではない。
```

# ※備考
本記事はブログ「[雑用エンジニアの技術ノート](https://scrapbox.io/nezuq/)」からの移行記事です。先のブログは削除予定です。
DockerをWSL2でInstallメモ(【後編】Docker導入)

# 環境
Windows10 Pro

# 手順
[Docker Desktop for WindowsのバックエンドとしてWSL2を使用する](https://dev.classmethod.jp/articles/docker-desktop-for-windows-on-wsl2/)

## Dockerインストール
https://hub.docker.com/editions/community/docker-ce-desktop-windows/

### インストール中
「Enable WSL 2 Windows Features」とチェックボックスの出るはずが、
「Enable Hyper-V Windows Features」と出てきて、
バックエンドをWSL2で指定したDockerをインストールできない。。。

```
wsl
```

でWSL2起動していて、

```
wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Running         2
```
と出るのだが。。。

OSのバージョンが1909だったのを思い出し、
https://docs.docker.com/docker-for-windows/wsl/
→2004以上　が前提
ソウイウコトカ

Windows Updateで降ってきてないので、手動でアップデート
https://www.microsoft.com/ja-jp/software-download/windows10
ここから。

アップデート後、Dockerのインストールを起動してインストールすると、
無事に「Enable WSL 2 Windows Features」と出てきました。
そのまま進めて、インストールできました。

```
 wsl -l -v
  NAME                   STATE           VERSION
* Ubuntu                 Stopped         2
  docker-desktop         Running         2
  docker-desktop-data    Running         2
```




# 補足
https://qiita.com/yoichiwo7/items/e3e13b6fe2f32c4c6120
念のため、こんな感じでメモリチューニングしておいた。
RustとHaskellのちょっとした違い

[「すごいHaskell楽しく学ぼう!」](https://shop.ohmsha.co.jp/shopdetail/000000001926/)が手元にあったので、なんとなくコードを真似てみる。

```rust
fn main() {
    // "Learn You a Haskell for Great Good" p.7
    // GHCi> let lostNumbers = [4,8,15,16,23,42] 
    let lost_numbers = vec![4,8,15,16,23,42];
    println!("{:?}", lost_numbers);
    
    // p.8
    // GHCi> [1,2,3,4] ++ [9,10,11,12]
    let ns = [[1,2,3,4],[9,10,11,12]].concat();
    assert_eq!(ns, [1, 2, 3, 4, 9, 10, 11, 12]);
    // たしかに結果は同じだが、Rust版は、「配列の配列」が最初にあることになっているので、元のHaskellコードと少し意味が違う。

    // もとのHaskellコードのイメージに近いのはこちら。
    let mut ns_a = vec![1,2,3,4];
    let mut ns_b = vec![9,10,11,12];
    ns_a.append(&mut ns_b);
    assert_eq!(ns_a, [1,2,3,4, 9,10,11,12]);
    assert_eq!(ns_b, []);

    // p.8
    // GHCi> "hello" ++ " " ++ "world"
    let  str = concat!("hello"," ","world");
    assert_eq!(str, "hello world");
    
    // GHCi> ['w','o'] ++ ['o','t']
    let chars = [['w','o'],['o','t']].concat();
    let mut string = String::new();
    for c in chars {
        string.push(c);
    }
    assert_eq!(string, "woot");
    
    // p.10
    assert_eq!(true, [3,2,1] > [2,1,0]);
    assert_eq!(true, [3,2,1] > [2,10,100]);
    assert_eq!(true, [3,4,2] < [3,4,3]);
    assert_eq!(true, [3,4,2] > [2,4]);// ここだけHaskellと動作が違う。
    assert_eq!(true, [3,4,2] == [3,4,2]);

}
```

`[3,4,2] > [2,4]`のところだけ、動作が違う。

```shell
 
Standard Error

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/main.rs:37:32
   |
37 |     assert_eq!(true, [3,4,2] > [2,4]);// ここだけHaskellと動作が違う。
   |                                ^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.
```

Haskellでは配列の要素数が違っていても処理するのに対し、Rustは「要素数が違う」ことをコンパイルエラーとする。言語による方針の違いがわかる。
Rails Tutorial　第13章 S3のエラー以外は完了

##2020/8/30 1.5時間
13.1.3まで進めました。
##2020/8/31 0.5時間
13.16まで進めました。
##2020/9/1 0.5時間
13.21まで進めました。
##2020/9/2 0.5時間
13.22まで進めました。
##2020/9/3 2.0時間
有給休暇で、13.29まで進めました。
##2020/9/4 0.5時間
13.2.3.2まで進めました。
##2020/9/5 2.5時間
休みの日で、13.3.1まで進めました。
##2020/9/6 1.5時間
休みの日で、13.3.4まで進めました。
##2020/9/7 0.5時間
13.55まで進めました。
##2020/9/8 0.5時間
13.3.5.1まで進めました。
##2020/9/9 0.5時間
13.3完了です。
##2020/9/10 2.0時間
有給休暇で、13.63まで進めました。
Cloud9のディスクが不足でgemのinstallができず、ディスクを拡張しました。
##2020/9/11 0.5時間
13.4.2完了です。
##2020/9/12 4.0時間
休みの日で、13.4.3完了です。
ImageMagickのインストールエラーで時間をとられました。さらにAWS S3のエラーで2時間ほどはまり、この日はあきらめました。
##2020/9/13 1.5時間
休みの日で進めました。S3のエラーは根本は解決しませんでしたが、そのまま進めました。

13章を完了です。
所要時間は19.0時間です。

#cloud9でyumがないためImageMagickがインストールできない

```
ubuntu:~/environment/sample_app (user-microposts) $ sudo yum install -y ImageMagick
sudo: yum: command not found
```

yumがないとエラー、Ubuntuではyumではなくaptのようです。
ネットで調べ、apt-getを入力します。


```
ubuntu:~/environment/sample_app (user-microposts) $ sudo apt-get update
ubuntu:~/environment/sample_app (user-microposts) $ sudo apt-get install imagemagick
Reading package lists... Done
Building dependency tree       
Reading state information... Done
You might want to run 'apt --fix-broken install' to correct these.
The following packages have unmet dependencies:
 imagemagick : Depends: imagemagick-6.q16 (>= 8:6.9.2.10+dfsg-2~) but it is not going to be installed
 linux-headers-5.3.0-1034-aws : Depends: linux-aws-5.3-headers-5.3.0-1034 but it is not going to be installed
 linux-image-5.3.0-1034-aws : Depends: linux-modules-5.3.0-1034-aws but it is not going to be installed
E: Unmet dependencies. Try 'apt --fix-broken install' with no packages (or specify a solution).
```

エラーがでたので、メッセージにあるTryの後のコマンドを入力してみたところ、無事できました。

```
ubuntu:~/environment/sample_app (user-microposts) $ sudo apt --fix-broken  install 
..done
ubuntu:~/environment/sample_app (user-microposts) $ sudo apt-get install imagemagick
```

#演習13.4.4.2 エラーがでると書いてあるが、エラーはでなかった
テキストではtestでエラーがでると書いてありますが、エラーはでませんでした。rails.pngが小さくて縮小されないのではと思い、ダウンロードしてみたところ、凄く小さいアイコンファイルでした。サイズが大きいファイルで置き換えてみましたが、エラーはでません。

リスト13.68のファイルを作ってみましたが、結果が変わらないのでこのファイルが効いているのかも分かりませんでした。
Docker × MySQL8でエラー「MySQL said: Protocol mismatch; server version = 11, client version = 10」

DockerでMySQL8を構築して、TablePlusで接続しようとするとタイトルのエラーが出た。

## 一応環境
Docker version 19.03.12
docker-compose version 1.24.0
mysql  Ver 8.0.21 for Linux on x86_64 (MySQL Community Server - GPL)

## 原因

どうやらクライアント側のポートを`33060`にするとエラーが起きるようだった。
ということで`13306`に変更してみたところ、接続ができた。


```YAML
// docker-compose.yml

// 変更前
ports: 
  - 33060:3306

// 変更後
ports: 
  - 13306:3306

```

特に他に書くこともないので、以上！
Stoplight Studioで作成したswagger.yamlを並び替えて見やすくするプログラムを作った

Swagger.yamlを作るのに[stoplightのツール](https://stoplight.io/)はとても便利なのですが、
生成されるファイルは、ツールで登録した順に記述されるので、後でSwagger.yamlそのものを、見た時に並び順がバラバラで見づらくなります。
そこで、APIやComponentを昇順に並び替えて、中の項目も同じ順で並び替えるプログラムを作りました。

## 事前準備
yamlファイルの読み込み、書き出しにsymfony/yamlパッケージを使います。
composerを使ってインストールしてください。

例：

```json:composer.json
{
    "require": {
		"symfony/yaml": "*"
    }
}
```

` php composer install` 

##使い方
以下のプログラムを、整形したいswaggerファイルを指定して実行するだけです。
指定したファイルの拡張子の手前に、_convertedとついたファイルが生成されます。

```php:convert_swagger.php
<?php
require 'vendor/autoload.php';
use Symfony\Component\Yaml\Yaml;

// yamlファイルを読み込んでarray配列に変換する
$file_name = $argv[1];
$content = file_get_contents($file_name);
$yaml_array = Yaml::parse($content);

// APIの並びをURLの昇順にする
$paths = $yaml_array["paths"];
ksort($paths);
$yaml_array["paths"] = $paths;

// components schemasの並び順を昇順にする
$schemas = [];
if(array_key_exists("components", $yaml_array)){
	$schemas = $yaml_array["components"]["schemas"];
	ksort($schemas);
}

// APIの項目を並び替える
foreach($paths as $key1 => $value1){
	foreach($value1 as $key2 => $value2){
		$item = [];
		$item["operationId"] = $value2["operationId"];
		if(array_key_exists("tags", $value2)){
			$item["tags"] = $value2["tags"];
		}
		$item["summary"] = $value2["summary"];
		$item["description"] = $value2["description"];
		$item["parameters"] = $value2["parameters"];
		if(array_key_exists("requestBody", $value2)){
			$item["requestBody"] = $value2["requestBody"];
		}
		$item["responses"] = $value2["responses"];
		$yaml_array["paths"][$key1][$key2] = $item;
	}
}

// components schemasの項目を並び替える
foreach($schemas as $key => $value){
	$item = [];
	$item["title"] = $value["title"];
	$item["description"] = $value["description"];
	$item["type"] = $value["type"];
	$item["properties"] = $value["properties"];
	if(array_key_exists("required", $value)){
		$item["required"] = $value["required"];
	}
	$yaml_array["components"]["schemas"][$key] = $item;
}

// 並び替えたデータをyaml形式に変換し、ファイルに出力する
$file_name = preg_replace("/\.yaml$/", "_converted.yaml", $file_name);
file_put_contents($file_name, Yaml::dump($yaml_array,99,2));
?>
```

**実行例**
`php convert_swagger.php sample.v1.yaml`
sample.v1_converted.yamlが生成されます。
かんたん　Appleのヘルスデータをエクスポート、解析、csvに変換する方法

# はじめに

みなさんは iOS アプリ [Health](https://www.apple.com/ios/health/)をつかってますか？
そんなみなさんは、体重や睡眠時間、歩数などの健康データはApple Healthのアプリ上に記録されていると思います。
このアプリは、健康状態の情報を記録し、アプリ上ではみえますが、実際には自分でデータ分析を行うことはできません。
データ分析とデータの可視化にはいろんな形式があると思いますが。今回はExcelやGoogle Sheetsのようなスプレッドシートアプリケーションを使って、解析するためにcsv 出力したいです。
今回、そんなみなさんにぴったりの[CLIを作ったの](https://www.npmjs.com/package/ahcd)でご紹介させていただきます.

# Apple health dataの抽出方法
まずはこの[動画を開いてみてください](https://github.com/freddiefujiwara/ahcd/blob/master/ezgif.com-video-to-gif.gif)

- iPhoneでHealthを開きます。
- 上隅にあるプロフィールのアイコンをタップすしてください。
- ヘルスのプロフィールの一番下までスクロールして、"Export All Health Data"をタップします。
- 更に"Export"をタップすると、データをエクスポートすることを確認してエクスポート処理を開始します(完了するまでに少し時間がかかる場合があります)
- 上記で抽出したファイルをローカルやGoogle Driveに保存してください

# 抽出したファイル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1817/177f49a3-a068-c6c9-f42c-363a1817c3ca.png)
抽出したなら、その中の **export.xml** を使います

# Nodejs環境設定

[本当の初心者のためのNode.js超入門　~環境構築編~](https://qiita.com/qulylean/items/0ad521885a04a5ebd202)
などを参考にローカルにNodejsの環境を構築してください

# コマンドインストール方法
下記のコマンドを叩いて[ahcd](https://www.npmjs.com/package/ahcd)というコマンドをインストールしてください

```bash
$ npm i -g ahcd
```

# 使い方

```bash
$ ahcd                                                                                                                                                                                                
================================================================================
Apple Health Care Data convert xml to csv

Author     : Fumikazu Fujiwara 
Homepage   : https://github.com/freddiefujiwara/ahcd#readme
LICENSE    : MIT
Report bugs: https://github.com/freddiefujiwara/ahcd/issues
================================================================================

Usage: ahcd [-h] <file> [-t <type>] [-d <dir>]
```
- 引数の**＜file＞**は必ず**export.xml**を指定してください
- -t は特定のcsvだけ出力します (例えば -t BodyMass　など)
- -d は出力先のディレクトリを指定します (例えば -d /path/to など)


# 実際に使ってみると

```bash
$ ahcd -d . export.xml                                                                                                                                                                                
Read export.xml
Analyze export.xml
Wrote ./Height.csv (1 records)
Wrote ./HeartRate.csv (87 records)
Wrote ./BodyMassIndex.csv (50 records)
Wrote ./BloodPressureDiastolic.csv (165 records)
Wrote ./BodyMass.csv (51 records)
Wrote ./BodyFatPercentage.csv (50 records)
Wrote ./FlightsClimbed.csv (1045 records)
Wrote ./BloodPressureSystolic.csv (165 records)
Wrote ./SleepAnalysis.csv (1193 records)
Wrote ./StepCount.csv (12032 records)
Wrote ./DistanceWalkingRunning.csv (13631 records)
```
 
#最後に
さぁ　ちょっと長かったですが、
これで、Excelなどのシートで解析できますね
また[ahcd](https://www.npmjs.com/package/ahcd)は[pull request](https://github.com/freddiefujiwara/ahcd/issues)大歓迎です
よろしくおねがいします
全ユーザのcron設定を一覧で出力する。

# 概要
　cronは、Unix系サーバで動作するタスクスケジューラ用のデーモンプロセスです。
　cronの設定（タスクスケジュール）はユーザごとに設定可能である為、サーバ内の全設定を確認するには一手間かかったbashコマンドを発行します。

# コマンド
```bash
# 1.管理者権限に移る
su -
# 2.ユーザごとのcron設定を出力する
for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done
# 3.管理者権限から抜ける
exit
```

# 解説
2のコマンドの各部は、次の処理内容になります。

``` cut -f1 -d: /etc/passwd ```
パスワードファイル「/etc/passwd」の各行で区切り文字「:」にて内容を分割し、その1項目目（ユーザ名）の値を抽出。

``` $(○○○) ```
 コマンドを実行・展開。

``` for ××× in △△△; do □□□; done ```
 △△△の各項目を×××に格納し、□□□の処理を実行。

``` echo $××× ```
 ×××の内容を出力。（このコマンド内ではユーザ名を出力）

``` crontab -u $××× -l ```
 xxxのユーザのcron設定を出力。

# 参考
* [全ユーザーのcronジョブ一覧を表示する - Qiita](https://qiita.com/ironsand/items/fb05869080f6ed724816)
* [unix - How do I list all cron jobs for all users? - Stack Overflow](https://stackoverflow.com/questions/134906/how-do-i-list-all-cron-jobs-for-all-users)

# 備考
本記事はブログ「[雑用エンジニアの技術ノート](https://scrapbox.io/nezuq/)」からの移行記事です。先のブログは削除予定です。