OmniAICreator/Qiita-1.07M huggingface dataset:
AI・ロボット専門学校を卒業しました！・・・で？

初めまして！1年ROMって初記事を書かせていただきます！ご意見ご指摘雑談何でも受付中です！

#1.この記事の概要
・これから進路を選択する方や専門学校を知らない方に、どんなことを勉強するのか具体的に紹介。
・自分がこの2年間どれだけ頑張れたのか、頑張れなかったのか、どうして頑張れなかったのか分析。
・自分の学の無さに嫌気が差してきており客観的な第三者の意見が欲しい。

#2.なんやかんやで勉強したこと
　カリキュラムは年々ブラッシュアップされていますが、まずは自分が学んだことから。
##2-1.python
・基礎,QT,django等のフレームワークのチュートリアルを一通り。自然言語処理、音声認識API、ソケット通信で
　無線LAN操作ロボットを作成しました。
##2-2.AI
・G検定をベースに機械学習,ディープラーニング,pythonでtensorflow,OpenCVの顔認識等、フレームワークのチュートリアルを一通り。
・顔認識できるカメラ付きドローン(Tello EDU,スマートカー)を作成しました。
##2-3.arduino
・電子工作でセンサ類一通り。詳しい原理や暗記よりスマートハウスモデルの作成などがメインでした。
##2-4.web
　linuxコマンド少し,Nginx,PHP,PostgresSQLでサーバー構築し簡単なスレッド掲示板を作成しました。
##2-5.要件定義、システム設計
　教科書読んだだけ。それでも、知らないよりは全然マシというか知れてよかったなあと思うこと多々。
##2-6.その他言語等(あんまり身につかなかった)
　Go言語、アセンブリ言語、R言語、Raspberry PiでWebIOPi,Mjpg-Streamerでロボ構築に挑戦するもエラー続出で完成ならず。
　エムス・テック様のManyfeetシリーズ　MF-01 Raspberry Pi用24軸制御用拡張基板でロボット工学基礎と設計。
　二足歩行ロボットKHR-3HVの組立、arduinoから制御を試作。3DCADのfusion-360やBlenderモデリング、3Dプリンタで成形。

#3.遅くなりましたが自己紹介
・当方、公立普通科中高卒業後、学力の低さとお金の無さから国立大夜間の知能システム工学科に入学するも…。
　当時は「たくさんロボット作ったり、AIやったりできるんだろうなあ！」と虚像に胸膨らませておりました…。

　数学！英語！物理！資料ぽん、自分で調べろ！これくらい理解できるレベルで入学してるよね！…。
　一つ単位を落としてからはもう自分の中がぐちゃぐちゃになり大学に通うことすら出来なくなりました。

　その後バイトしながら親と相談。「とにかく手に職つけえや。」「はい。」「PC得意やろ、専門学校で面倒みてもらえ。」
　「はい」という流れで、専門学校に行くことに。選んだのは学費免除制度が充実していた新設されたばかりの
　「AI・ロボット科」でした。(教員3人生徒1人！)
　なんやかんや(前述)やって、基本情報まで合格。さあ就活だ…。え？この学校来年40人近い応募？常勤2人と非常勤1人で？

　…。

　放っておけず、専門卒の補助講師として同専門学校で働いております。
　(python,c++,AI概論,リテラシー,セキュリティ,IoT工作担当中)


#4.今のカリキュラムだと？
・なんとグラフィック演習が追加されアセンブリ言語が消滅。R言語やGo言語は2年生での選択制になりC言語、
　コンピュータ基礎、MOSが参戦。さらにscratch、Unityも参加。(大学在籍してた為この辺りは自分はやらなかった。)

#5.で？
・これだけ沢山の技術を2年間でたっぷり学べたのは振り返ってみればとても幸せでした。これからの成長の幅が無限に広がり、
　仕事での効率を上げる為のアプリ開発もどんどん進めています。(出席管理システムや成績評価自動化等)

・身につかなかった技術は単純に使いどころが理解できなかったのと、授業成果＝成績の講義もあり努力に偏りが出たのも。
　見られていない状況で指示通りにするくらいは出来ますが、自分で目標を持って開発は著しく時間を浪費してしまうことも。

・また、インターン制度等は利用できず現場で実際使われている本番環境やslack等のチャットツール、具体的なアジャイル開発
　等には一切手を出せていない。即戦力を期待されている専門生としては、Qiitaの先輩仕事話を見るたび知らない世界で戦々
　恐々…。

・それはそれとして、新設されたばかりで教員は自分以外大学講師兼任、上層が老舗の古き良き社風。
　ここをIT業界と称するのは些か憚られます…。キャリアアップの観点でいえば、もっとシステム開発しやすい環境の方が…。

・幸い新任の為、時間は多く頂けている（自己分析に時間を割けるくらいには）ので、Qiitaや研修やpaizaスキルチェックで、
　情報収集、自己研鑽をしつつキャリアアップへの道を探したいと思います。



以上、拙い文章ながらお付き合いいただきありがとうございました。
一時結合表現の大源流としての複素数表現(Complex Expression)/四元数表現(Quaternion Expression)

そもそも**一時結合**の概念自体、歴史的に**複素数表現**(Complex Expression)w+xiや**四元数表現**(Quaternion Expression)w+xi+yj+zkに由来する訳です。その拡張版たる**線形空間**上の認識では、**複素数**や**四元数**は**位置ベクトル**の一種と解釈され、**極座標系**(Polar Coordinates System)の原点と結んだ場合に**幾何ベクトル**を形成します。これに垂直に交わるのが**接線としての同心円**であり、**xy座標系の指数・対数写像**と表される訳です。
[複素数の１次結合が表す図形](https://www.geisya.or.jp/~mwm48961/koukou/complex_trace3.htm)

* 異なる２つの**複素数**$z_1,z_2$が与えられていて，実数p,qがp+q=1,p≧0,q≧0の条件を満たしながら変化するとき，$z=pz_1+qz_2$で示される点は，２点$z_1,z_2$を結ぶ**線分**になる。<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597772/a105d137-a71d-364b-9886-bf6b01dc9eb3.png)
* １直線上にない異なる３つの**複素数**$z_1,z_2,z_3$が与えられ実数p,q,rがp+q+r=1, p≧0,q≧0,r≧0の条件を満たしながら変化するとき，$z=pz_1+qz_2+rz_3$で示される点は，３点$z_1,z_2,z_3$が形成する**三角形の内部および周上**になる。<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597772/10c723fa-026e-ae1e-5e36-0f8759f34e70.png)

おそらくこの考え方は**デカルト座標系**(Cartesian Coordinate System)(x,y)へも適用可能です(現時点では確証にまで至ってない)。そんな感じで以下続報…
cronで定期的にバックアップファイルを作る

### バックアップファイルを作る流れ

※保存期間は1ヶ月

1. 先月分のバックアップファイルを削除
1. n月1日にフルバックアップ
1. フルバックアップした日にちを保管しておく
1. 日次でフルバックアップに対して差分バックアップ

毎月1〜4を繰り返す

```
#!/bin/sh
#40 3 * * * cd /root/backup/;/root/backup/bkdb.sh;/root/backup/bkfile.sh // いつcronが動くかわかりやすくコメントアウト（crontab -l　で確認）

// 変数の定義
DIRECTORIES=/var/www/hogehoge // tarコマンド実行時に指定するバックアップ元のディレクトリ
BACKUPDIR=/root/backup/file/ // tarコマンド実行時に指定するバックアップ先のディレクトリ
EXCLUDEOPTIONS='--exclude /var/www/hogehoge/cache --exclude /var/www/hogehoge/backup' // tarコマンド実行時に指定するバックアップ対象外のディレクトリ
TIMEDIR=/root/backup/file // 月次のフルバックアップに対して日次で差分バックアップを行う際に使用する日付データを入れるためのディレクトリ
LogFile=/root/backup/file/logs/log$(date +%y%m).txt // ログファイル
OldFiles="$BACKUPDIR"file$(date +%y%m --date='1 month ago')*.tar.gz // 先月分のバックアップファイル

date "+==%y%m%d %H:%M:%S==" >> $LogFile  // ログファイルに実行日時を出力（例：==210819 03:40:07==）

// 先月分のバックアップファイルが存在する場合、全て削除し、ログファイルに「[バックアップファイル名] Delete Old Files Success!」と書き込む。
// 先月分のバックアップファイルが存在しない場合、ログファイルに「[バックアップファイル名] No Old Backup File!」と書き込む。
if ls $OldFiles 1> /dev/null 2>&1;  
then
   rm -f $OldFiles >> $LogFile 2>&1
   echo "[$OldFiles] Delete Old Files Success!" >> $LogFile
else
   echo "[$OldFiles] No Old Backup File!" >> $LogFile
fi

DOW=`date "+%u"` // UFC時刻を取得する
DOM=`date "+%d"` // 年月日の日にちのみを取得する（1日の場合、01日となる形式で取得）
DA=`date "+%y%m%d"` // 年月日を取得する（1月1日の場合、01月01日となる形式で取得）
DAYM=`date "+%y%m"`　// 年月日の年月のみを取得する（1月の場合、01月となる形式で取得）

// n月1日の場合、tarコマンドでフルバックアップファイルを作成し、差分バックアップのため作成日を保管しておく
// n月1日ではない場合、tarコマンドで差分バックアップファイルを作成（フルバックアップファイル作成日より新しいファイルが対象）
if [ $DOM = "01" ]; then 
        NOW=`date "+%Y-%m-%d %H:%M:%S"`// 変数NOWに年月日時分秒を定義

        echo "Monthly full backup" >> $LogFile // ログファイルに「Monthly full backup」と書き込む。
        echo $NOW > $TIMEDIR/full-date // 変数NOWをファイル/root/backup/file/full-dateに書き込む。
        tar czPf $BACKUPDIR/file$DA.tar.gz --exclude $EXCLUDEOPTIONS $DIRECTORIES // 後述※1
else
        echo "Incremental backup" >> $LogFile //ログファイルに「Incremental backup」と書き込む。
        tar czPf $BACKUPDIR/file$DAYM.$DOM.tar.gz $EXCLUDEOPTIONS $DIRECTORIES --newer "`cat $TIMEDIR/full-date`" //後述※2
fi

echo "==end==" >> $LogFile // ログファイルに「==end==」と書き込む。

```

#### tarコマンド

後述※1（フルバックアップするコマンド）

```
tar czPf $BACKUPDIR/file$DA.tar.gz --exclude $EXCLUDEDIRS1 $EXCLUDEDIRS2 $DIRECTORIES
```

- オプション確認
    - c：新しいバックアップを作成する
    - z：バックアップをgzip形式で圧縮する
    - P：ファイル名から先頭の「/」を取り除かない
    - f：バックアップファイル名を指定する
    - exclud：除外したいファイル、ディレクトリを指定する

除外オプションを複数使う際は、除外数分```--exclude```を書く必要がある

```
tar czPf 作成するアーカイブファイルPATH -exclude 除外ファイルまたはディレクトリのPATH アーカイブ対象ディレクトリ
```

後述※2（差分バックアップするコマンド）

```
tar czPf $BACKUPDIR/file$DAYM.$DOM.tar.gz $EXCLUDEOPTIONS $DIRECTORIES --newer "`cat $TIMEDIR/full-date`"
```

- newer
指定した日付より新しいファイルだけを保存する（日付の代わりにファイルを指定することも可能。この場合、指定したファイルより新しいファイルだけが対象になる）
FastAPIでExcelデータを作成し一時保存せずにそのままレスポンスする方法

# 前提
FastAPIは通常はただのdictやPydanticで定義したモデルをもとにレスポンスをJSONに変換して返却するが、他の形式のレスポンスを返す方法も存在する。

例えば、`GET`リクエストで形式を指定してJSONなら通常通りJSONを返却し、Excelならxlsx形式のレスポンスを返却するようなエンドポイントがあるとする。この場合、既にファイルが作成済みであれば`FileResponse`を利用して直接レスポンスを返却することは[ドキュメントにある通り](https://fastapi.tiangolo.com/advanced/custom-response/#fileresponse)簡単にできるが、問題はリクエストを受けてからOpenPyXLでxlsx形式データを作成しそのデータを保存せずにそのまま返却するにはどうすればいいかである。

確認したバージョンは以下の通り。
* FastAPI: 0.68.1
* OpenPyXL: 2.6.2

# 方法
通常、OpenPyXLでは次のようにワークブックを作って、ファイル名を指定して保存する。

```python
workbook = Workbook()
# ...ここでシートをつくって色々書きこむ...
workbook.save("xlsxファイル名")
```

`save()`メソッドにはファイルパスを指定するのが普通だが、ここにfile-likeオブジェクトを指定するとそのオブジェクトに対してデータを書き込むことができる。

そこで、次のように`BytesIO`オブジェクトを指定してデータを保存する。

```python
xlsx = BytesIO()
workbook = Workbook()
# ...ここでシートをつくって色々書きこむ...
workbook.save(xlsx)
```

一方、FastAPIでは`StreamingResponse`を使ってfile-likeオブジェクトをレスポンスに返却することができるため、組み合わせると次のようになる。

```python
from urllib.parse import quote

# ...中略...

@app.get("/hoge", response_class=StreamingResponse)
def get_hoge_as_xlsx():
    xlsx = BytesIO()
    workbook = Workbook()
    # ...ここでシートをつくって色々書きこむ...
    workbook.save(xlsx)
    xlsx.seek(0) # !!! 注意 !!!
    filename = quote("ほげほげ.xlsx")
    return StreamingResponse(
        content=xlsx,
        headers={"Content-Disposition": f'attachment; filename="{filename}"'},
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    )
```

:::note warn
StreamingResponseは現在のシーク位置からレスポンスを作成するので、OpenPyXLでsaveした後は先頭に戻す(seek(0))必要がある。
:::
Builder パターンが嫌い

## コンストラクタのあるクラスなら継承ができる

```java:Hoge.java
class Hoge{
  //...
  public Hoge(/*...*/){
     //...
  }
  public int hogeMethod(){
  //....
  }
}
```

```java:Huga.java
class Huga extends Hoge{
  public Huga(/*...*/){
    super(/*...*/);
    //...
  }
  public int hugaTsukaiyasuiMethod(/*...*/){
  //...
  }
}
```

```java
Huga huga = new Huga(/*...*/);
int a = huga.hogeMethod();
int b = huga.hugaTsukaiyasuiMethod();
```

中身なんてなんでもいいんですが、普通の、というよりはせめてコンストラクタのあるクラスって継承で簡単に機能が拡張できますよね。

## Builder しかマトモにインスタンスを生成する方法が無い！！

コンストラクタすら存在せずBuilderしか提供されていないと、ラッパーとか作りたい時にこうなっちゃいますよね

```java:Huga.java
class Huga {
  private Hoge hoge;
  public Huga(/*...*/){
    hoge = HogeBuilder.builder()/*...*/.biuld();
    //...
  }
  public int hugaTsukaiyasuiMethod(/*...*/){
  //...
  }
}
```

```java
Huga huga = new Huga(/*...*/);
int a = huga.hogeMethod(); // ← できない！！！！！！！！
int b = huga.hugaTsukaiyasuiMethod();
```

ラッパーなんだからそもそも `Hoge` のメソッドにアクセスする必要のあるものが存在するのがおかしいのか、それでも直接中のメソッド叩いた方がいい時なんていくらでもある訳で、かといって `Hoge` のメソッドのラッパー全部作る訳にはいかないし、 `getHoge()` みたいなアクセサつくるのがいちばんいいのかなぁ。
pip アップグレード方法(win10, 2021)

## 前提
- win10
- pipの以前のバージョン：20.2.4

## やりたいこと
pip version 20.2.4⇒ version 21.2.4
にする

## やり方

1. コマンドプロンプトを管理者で開く
1. 「pip install -U pip --user」とコマンドプロンプト上で打つ
1. Enter
![コマンドプロンプト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1939160/706b69ad-69b6-1acb-d814-10eb89c9551b.png)

### 注意事項
※ 「--user」がなくても行ける人がいるかも
※先頭に「-m」と付け加えてうまくいくケースもある
これからリモッテを始める人にお勧めの投稿

リモッテでは、ユーザーを３つの種類に分けています。

__管理者__は、Windows パソコンに「リモッテ・ステーション」をインストールし、アプリの実行を開始、利用者がアプリを使えるようにする人のことです。

__利用者__は、管理者が用意したアプリを利用する人のことです。

__開発者__は、構成要素を組み合わせてアプリを作ったり、プログラムを記述して構成要素を作成する人のことです。

以下は、これから管理者ないしは開発者としてリモッテを始めようとするユーザーが参考にできる投稿の目次で、番号順に読み進めることで、スムーズにやりたいことができるようになります。
### 基本的な使い方
１．[IoT プラットフォーム「リモッテ」をインストールしてみた](https://qiita.com/remotte_jp/items/39278287097a7a25432d)
２．[IoT プラットフォーム「リモッテ」でステーションを登録してみた](https://qiita.com/remotte_jp/items/94fb73db9fb98e9e10a2)
３．[IoT プラットフォーム「リモッテ」でアプリを実行してみた](https://qiita.com/remotte_jp/items/324f99727c68392b80e5)
４．[Remotte（リモッテ）を利用者として使う](https://qiita.com/remotte_jp/items/7ec79a400429738843d0)
５．[Remotte（リモッテ）で時系列データの詳細を見る](https://qiita.com/remotte_jp/items/a7b5475176eb133af957)
６．[Remotte（リモッテ）でビデオと音声を配信、記録、再生する](https://qiita.com/remotte_jp/items/c520c8b7967ab3e199b4)
### 基本的なアプリの実行
１．[リモッテで MQTT ブローカーを立ち上げる](https://qiita.com/remotte_jp/items/893800044319a8c9a3a2)
２．[MQTT ブローカーとクライアント間の接続性の確認](https://qiita.com/remotte_jp/items/51ede55bb822aefc3d61)
### 初級開発者向け
１．[管理者モードから開発者モードへ切り替える](https://qiita.com/remotte_jp/items/66782915797e35b924a3)
２．[開発者向けの機能](https://qiita.com/remotte_jp/items/093bcb7a9056e870d180)
３．[まずは作ってみよう！！（演習１）](https://qiita.com/remotte_jp/items/2c7f593c708d4ae04bcc)
４．[制御系のアプリ（演習２）](https://qiita.com/remotte_jp/items/ce77c0f5b796ccd818a8)
５．[ビデオ解析系のアプリ（演習３）](https://qiita.com/remotte_jp/items/6f379b1f32f5c78f61ee)
６．[音声解析系のアプリ（演習４）](https://qiita.com/remotte_jp/items/f759252cafa6dccc80c1)

以上
[Python] よく使いそうな日付処理まとめ

Pythonの日付処理をまとめておく。（必要に応じて追記）

```python

from datetime import datetime,timedelta
now = datetime.utcnow() + timedelta(hours=9)
```

▼昨日

```python
last_day = now + timedelta(days=-1)
print(last_day.strftime("%Y-%m-%d"))
```

▼先月1日

```python
last_month = datetime(now.year, now.month, 1) + timedelta(days=-1)
print(last_month.strftime("%Y-%m-01"))
```

▼昨年同月1日

```python
last_year_same_month = datetime(now.year-1, now.month, 1)
print(last_year_same_month.strftime("%Y-%m-01"))
```
AWS Organizations の SCP を使って特定のIPアドレスのみで AWS が利用できるようにしてみよう


こんにちは
間が空いてしまいましたが、AWS Organizations の SCP を使って制限をかけようシリーズの第3弾です。

第1弾：https://qiita.com/hirosys-biz/items/ecc34f8574094dc6be15
第2弾：https://qiita.com/hirosys-biz/items/48d1db5fcce3bf6547ce

今回はタイトルにあるように特定のIPアドレスからのアクセスに限って、AWS の利用ができるようにするものです。
業界や企業のポリシーで、AWS の操作を特定の IP アドレス(IP アドレス範囲)に限っていることがよくあります。例えば、運用保守チームが利用している IP アドレス範囲のみ操作を認めるといった感じですね。

当社で AWS Organizations を使ってハンズオン、サンドボックス環境を作っていた際に出てきた要件で対応した内容です。

##　制限をかけてみよう
これまでの記事と同様の流れでポリシーを作成し、organizational units (OUs)やアカウントにアタッチします。
ポリシーは以下の通りです。

```json:DenyNotIPRange
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Statement1",
      "Effect": "Deny",
      "Action": "*",
      "Resource": [
        "*"
      ],
      "Condition": {
        "StringLike": {
          "aws:username": [
            "*"
          ]
        },
        "NotIpAddress": {
          "aws:SourceIp": [
            "特定のIPアドレス範囲(例：172.31.1.0/24)"
          ]
        },
        "Bool": {
          "aws:ViaAWSService": "false"
        }
      }
    }
  ]
}
```

### 簡単な説明
Effect: Deny としているので、以下の条件を満たす場合に操作を拒否する設定です。

+ aws:username: "*" としているので、任意のIAM User による操作が対象です。
+ **Not**IpAddressとしているので、aws:SourceIP に指定した特定のIPアドレス範囲**以外**からのアクセスが対象です。 
+ aws:ViaAWSService: false としているので、 AWS サービスを経由したものではない(例：AWS CloudFormation による操作ではない)場合が対象です。

## 動作確認
1. まずは、特定のIPアドレスを使用して、SCP を割り当てた AWS アカウントへログインします。
2. Amazon EC2 のコンソールを表示します。
3. 特定のIPアドレス**以外**から、SCP を割り当てた AWS アカウントへログインします。
3. 2と同様に、Amazon EC2 コンソールを表示します。

### 特定のIPアドレスからのアクセス
以下の様に EC2 インスタンスの台数などの情報が確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548623/f89cde75-d406-4f37-3b8a-86ef784f9c46.png)

### 特定のIPアドレス以外からのアクセス
以下の様に、各種操作が拒否されていることにより、EC2 インスタンスの台数などの情報が API エラーで確認できません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548623/654bc7ed-a5cb-8b32-8d01-5c086b70a3d5.png)

## 注意点
特定の IP アドレスを指定しているので、アクセス元の IP アドレスが変わったりすると、本来は正規のアクセスであっても拒否されてしまいますのでご注意ください。


## まとめ
久しぶりに SCP まわりのお話でした。今回と以前までにお伝えした内容は、SCP でできることのほんの一部であり、本当に奥が深い機能であります。

各環境の要件に応じたポリシーを作って、アカウントを適切に運用していきましょう！

記載されている会社名、製品名、サービス名、ロゴ等は各社の商標または登録商標です。
ほんとにちょっとhtmlを公開したいだけ

新しくアカウントなどを増やしたくないがhtmlを公開したい時
GMailアカウント(Google Drive)があれば
<a href='https://drv.tw/'>Drive to web</a>での公開がラクでした。


<h1>手順</h1>
１、ファイルをGoogle Driveにアップ
２、共有設定を誰でも見られるように設定
３、Drive to webにGoogle Drive参照を許可する
の3ステップだけでした。

<h1>ここでハマった</h1>
何回上げてもhtmlファイルとして認識されず小パニック。
結果は　設定チェックが入ってしまっていた。
htmlファイルなどを上げたい場合はチェックを外す！
![Google Drive設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1906297/7d215a72-8e76-4cf7-9c74-9fe932170fd8.png)


<h1>Drive to webの操作</h1>
<a href='https://drv.tw/'>Drive to web</a>を開いて
host on Google drive　をクリック
アカウントを選んで
許可をクリック
許可をクリック（自分は2回出てきました）
するとurlが発行されます。
Pythonによるファイナンス 8章 金融時系列データ

<h1>内容</h1>
csvファイルに入っている株価の時系列データを分析していく。


<h2>①時間の経過に伴う変化</h2>
時間変化率を計算する。

<h2>②リサンプリング</h2>
日次間隔の時系列データを、週次単位にリサンプリングする。

<h2>③ローリング統計</h2>
移動平均法により一定区間ごとの最大値、最小値、平均値を計算し可視化する。

<h2>④相関分析</h2>
二つの時系列データの相関関係を分析する。
まず対数収益率を計算し可視化。そして二つの時系列データの対数収益率を用いて散布図を作成。
Macでウィンドウ移動を少しだけ楽にする方法

Macでウィンドウを移動したりリサイズする際、マウスカーソルを移動するのが煩わしくありませんか？

ウィンドウのどこにマウスカーソルがあっても、移動とリサイズが簡単に行えたら楽ではと思い、
[DokodemoDrag](https://github.com/hmuronaka/DokodemoDrag)というアプリを作成しました。

使い方は「ウィンドウの任意の場所にマウスカーソルを置き、Commandキーを押しながらマウスでドラッグする」だけでよく、とてもシンプルです。 （...但し初期設定が必要です）

![image01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37443/af6d8de3-e191-e5bd-7f15-5e71afbe4e90.gif)

また開発の際に知った、NSWindowShouldDragOnGestureというmacOS標準の設定項目を紹介します。

# NSWindowShouldDragOnGesture

実は「ウィンドウの任意の場所をドラッグしてウィンドウを移動する」だけなら、この機能を有効にするだけでよくアプリは不要です。

以下はその設定方法です。

1. Terminal.appを開く
2. 以下のコマンドを実行する

```sh
defaults write -g NSWindowShouldDragOnGesture -bool true
```
3. MacOSを再起動する
これでアプリ不要で、ウィンドウの移動が簡単にできるようになります。
(ウィンドウ移動はCommand+CTRLキーです）

この機能を無効にする場合は、Terminal.appから以下のコマンドを実行します。

```sh
defaults delete -g NSWindowShouldDragOnGesture
```

実行した後にMacOSを再起動します。

参考記事: [Usability hack: Click & drag anywhere in macOS windows to move them](https://www.mackungfu.org/UsabilityhackClickdraganywhereinmacOSwindowstomovethem)

----

よければ[DokodemoDrag](https://github.com/hmuronaka/DokodemoDrag)もお試しください。
[README(日本語)](https://github.com/hmuronaka/DokodemoDrag/blob/main/docs/README_JP.md)

以上です。
foreachの変数にlsが効かないとき

csh/tcshだけかもしれないが、foreachの変数に`ls`の結果を代入したいとき、つまり

```shell
foreach i (`ls`)
cd $i
command
cd ..
end
```
ということをしたいとき、プロンプトでカラー設定をしていると

```
^[[0m^[[01;34mhogehoge^[[0m: No such file or directory.
```

というようなエラーが出る。
こんなときは、

```
ls --collor=no
```

を使えばよい。
つまり、

```shell
foreach i (`ls --color=no`)
cd $i
command
cd ..
end
```

で良い。
地味にはまったので、メモ。
[Rails] またまたCSSだけが本番環境に反映されない

##はじめに
前にも同じようなことがあって、一応応急的な処置で対処したのですが、それすら通用しなくなって途方に暮れていました。
またまた、応急処置的な対処ですが、解決しましたので記事で残しておきます。

アプリの構造やインフラ周りも私の場合で書いてますので、コマンドやファイルの違いなどがあると思いますがご容赦いただけたらと思います。


前に書いた記事はこちら↓
https://qiita.com/minhee/items/fba5564cb8c17109a372

##解決策

前に書いた記事とやっていることは同じですが、より手動にしたという感じです。

①まずDocker環境を置いているEC2インスタンスにターミナルからログイン

②下記コマンドでアプリを置いているコンテナのIDを確認し、コンテナ内に入る

```terminal
# コンテナのIDを確認
docker ps

# コンテナの中に入る
docker exec -it 確認したコンテナid sh
```

③precompileされたCSSファイルを消しに行く

```terminal
# precompileされているファイルが置いているディレクトリへ移動
cd public/assets

# lsコマンドで拡張子がcssのファイルを確認して削除
ls

rm 拡張子がcssのファイル

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

④元のディレクトリでassets:precompileをする

```
bundle exec rails assets:precompile RAILS_ENV=production
```

⑤コンテナを立ち上げ直す

コンテナから出てnginxを立ち上げ直さないと読み込まないと思いますので、コンテナを立ち上げなおします。

```terminal
# コンテナから出る
exit

# 一度コンテナを落とす（私の場合オプションをつけないとうまく落とせないのでつけてます）
docker-compose down --remove-orphans

# 立ち上げる
docker-compose -f docker-compose.yml -f docker-compose.production.yml up 
```

これでCSSの反映が無事できました。

##最後に
本当は試したいことがたくさんあるのですが
とりあえず数日後に大事な面接でアプリをお見せしないといけないので、これ以上この周辺はとりあえず触らないようにしています。
当日反映されていない！ってなるのが怖すぎます。

手動でrmコマンドでファイルを消していましたが、コンテナ内で
```bundle exec rails assets:clobber RAILS_ENV=production```を使ってprecompileされているものを消して、```bundle exec rails assets:precompile RAILS_ENV=production```で再作成すればいいのではないかとも思いますが、置いときます。
Swift バイナリツリー①

バイナリツリーとは
--
一つの親ノードに対して、最大2つの子ノードを持つツリー構造のデータ構造のことを指す。
親ノードに対して左にあるのを左ノード、右に存在するのを右ノードという。








コード

```swift:バイナリツリー.swift
//バイナリツリークラスを定義　　引数はジェネリクスになっている
public class BinarySearchTree<T: Comparable> {
 //プロパティ(親、value,左、右）を外部から代入できないようにprivate(set)を付けてあげる
  private(set) public var value: T
  private(set) public var parent: BinarySearchTree?
  private(set) public var left: BinarySearchTree?
  private(set) public var right: BinarySearchTree?

//イニシャライザ
  public init(value: T) {
    self.value = value
  }
//根ノード　バイナリツリーの根になるノード
  public var isRoot: Bool {
    return parent == nil
  }
//最下層にあるかどうか　左が切れている、且つ、右も切れていて進めない
  public var isLeaf: Bool {
    return left == nil && right == nil
  }
//一つの親ノードに対して左ノードを見て値が同じかどうかをboolで返す
  public var isLeftChild: Bool {
    return parent?.left === self
  }

//一つの親ノードに対して右ノードを見て値が同じかどうかをboolで返す
  public var isRightChild: Bool {
    return parent?.right === self
  }

//左のノードがあるか
  public var hasLeftChild: Bool {
    return left != nil
  }
//右ノードがあるか
  public var hasRightChild: Bool {
    return right != nil
  }
//いずれかがあるかないか
  public var hasAnyChild: Bool {
    return hasLeftChild || hasRightChild
  }

//どちらももっているかどうか
  public var hasBothChildren: Bool {
    return hasLeftChild && hasRightChild
  }

//数を出す
  public var count: Int {
    return (left?.count ?? 0) + 1 + (right?.count ?? 0)
  }
}
//インスタンス化
let tree = BinarySearchTree<Int>(value: 7)
````

値の挿入と削除は明日。⚡
Laravel Sail + Xdebug + VS Codeでのデバッグ

- `sail artisan sail:publish` を実行して `Dockerfile` を出す。
- `Dockerfile` に `apt-get install -y php-xdebug` を差し込む。
- `php.ini` に下記追加

```ini
[XDebug]
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_host = host.docker.internal
``` 

- `sail build --no-cache` を実行。
- VS Codeに 拡張機能 `PHP Debug` を入れる。
- `.vscode/launch.json` に下記設定を追加。

```json
{
    "name": "Listen for XDebug",
    "type": "php",
    "request": "launch",
    "stopOnEntry": true,
    "port": 9003,
    "pathMappings": {
        "/var/www/html": "${workspaceFolder}"
    },
    "hostname": "localhost",
    "xdebugSettings": {
        "max_data": 65535,
        "show_hidden": 1,
        "max_children": 100,
        "max_depth": 5
    }
}
```

- VSCodeにてデバッグ開始。
終わり。
Windows10 突然のシャットダウン

#ファイル編集中に突然PCがシャットダウン…
作業中に起きると非常に困るこの事象。
備忘録として、原因究明の方法をまとめる。

#原因は主に5つ

1. 熱暴走
PCの動きが悪いのにボタンを連打…などPCに負担をかけすぎたときに発生。次の起動時にBOOT画面が表示された場合はescで回避するか、HDDを選択すればok。
2. HDDの読み込み不良
HDD内のOSが読み込めず、シャットダウンするパターン。次起動した時にBOOT画面が出るはずなので、ここでHardDiscDriveが選択肢に出てこなかったらまずこれ起因で間違いないはず。
BOOT画面での切り分けができなかった場合は、以下のHDD整合性の診断。手段は3つ。
　ひとつめ。コマンドプロンプトで
　```chkdsk```実行。
　ふたつめ。エクスプローラーから該当のドライブを右クリックしてプロパティ-->ツール-->チェックで、エラーがある場合は、問題が出力される。
　みっつめ。コンパネ-->セキュリティとメンテナンス-->メンテナンス-->ドライブの状態で、正常と書かれていれば問題なし。

3. メモリ読み込み不良
　メモリが読み込めないせいで動作が不安定になった結果シャットダウンすることもある。診断方法は、Windows管理→Windowsメモリ診断。
4. 電力の帯電
　電気がたまり過ぎて保護装置の動作不良でシャットダウンすることがある。上のどれも当てはまらないときは一回電源コードを抜いて放置してみるのが良い。
5. システムアップデート
　ファームウェア系のシステムアップデートが走るとシャットダウンすることもある。シャットダウンが頻発する場合にこの原因であることは考えにくい。アップデート履歴を見ればはっきりわかる。
mayaがエラー・ワーニングを吐く時の対処 3　~埋まっているUUID~

mayaがerrorを吐いて鬱陶しい時
データをopenしただけでこんなエラーを吐く時

    Error: file: D:/hoge.ma line 79588: UUID already in use

UUIDが既に使われてます。　とのこと。

UUIDとな?
mayaのいくつからか忘れましたが、突然　アトリビュートエディタに現れた英数字の文字列
正式名称は　**Universally Unique Identifier**、簡単に言うなら識別番号といったところ？
名前指定じゃなくて、UUID指定で処理を行うこともできる様子。

識別番号なので、同一データ内では被り許されないらしい。
↑のエラーは**UUIDが被っていますよ**という意味のエラー

なんで被るのか？
原因は**referenceからのimport Objects from Reference**

1,mayaのシーンに同一のデータを2つ以上referenceする
2,referenceしたデータをimport Objects from Referenceでシーン内にimportする
3,シーンをsaveして開きなおす。
4,UUIDエラーいっぱい

という流れ。

reference の状態ではUUIDの被りは許容されているが、
import Objects from Reference　後は同一データ内の扱いになるので許されない。

import する場合は　UUIDが勝手に更新されて被らないように処理されるが、
import Objects from Reference　はUUIDが更新されず被ったままになってしまう。

ただ、
UUIDエラーが出た時点でUUIDを振り直してくれているので　エラーが出てるときにはすでに被りが解消されている。
そのため　**そのまま保存すればエラーは勝手に消滅してくれる。**
UUIDの振り直しはシーンの編集として認識されないので、**save scene** (ctrl+s) ではなく **save scene as** で保存する必要がある。

reference -> importを自動で処理する場合は　import Objects from Reference　を使わず、
reference を unload してから、importにしてしまった方がエラーに遭遇する確率は減ると思う。

参考：

https://help.autodesk.com/view/MAYAUL/2019/JPN/?guid=Maya_SDK_NM_What_s_New_What_s_Changed_What_s_New_in_API_in_Maya_2016_2_html

https://help.autodesk.com/view/MAYAUL/2019/JPN/?guid=GUID-BB3A5FD9-7EA5-4EFE-B019-FB08CC8A66D4
Firebaseで"This domain is not authorized to run this operation."というエラーが出たら

# エラー
FirebaseのAuth機能を使っていると、頻繁に遭遇する以下のエラー。

```console
This domain ({ドメイン名}) is not authorized to run this operation. 
Add it to the OAuth redirect domains list in the Firebase console -> Auth section -> Sign in method tab."
```

大概の場合は、エラー文にも書いてある通りSignin-methodを追加していないか、以下の記事のように認証済みドメインにドメインを追加していないことが原因です。
[firebaseでOAuth認証するためのリンクを押しても反応しなくなったときの解決策](https://qiita.com/godan09/items/858b628c4cb88f86e0b8)

ただ、たまに上記で解決しない事もあり、これの解決で1時間くらい溶けてしまったので備忘録を兼ねて共有します。

# 解決策
Signin-methodも追加してあり、認証済みドメインにドメインも追加しているのに解決していない場合は、ブラウザのキャッシュを消しましょう。
Chromeだと「設定」→検索タブで「キャッシュ」を検索→「Cookieと他のサイトのデータ」「キャッシュされた画像とデータ」にチェックを入れて「データを削除」を押しましょう。
事象発生から遡って24時間以内にログインできていたのであれば、24時間分のキャッシュを消せば良いと思います。
2021-08-26 Godot Engine > Pong with GDScript > paddleの移動に合わせたy方向の処理へ変更

### 動作環境

```
Windows 10 Pro v21H1
Godot Engine v3.3.2.stable.official
```

### Pong with GDScript

Pongの実装。
コードを見ているとy方向の移動量は乱数になっていた。

```python:paddle.gd
area.direction = Vector2(_ball_dir, randf() * 2 - 1).normalized()
```

### paddleの移動に合わせたy方向の処理へ変更

paddleの移動に合わせたy方向の処理へ変更してみた。

- `_relative_speed`の追加
- `area.direction`の計算に`_relative_speed`を追加


```python:paddle.gd
extends Area2D

const MOVE_SPEED = 100

var _ball_dir
var _up
var _down = 0

var _relative_speed  # パドルの相対速度

onready var _screen_size_y = get_viewport_rect().size.y

func _ready():
	var n = String(name).to_lower()
	_up = n + "_move_up"
	_down = n + "_move_down"
	if n == "left":
		_ball_dir = 1
	else:
		_ball_dir = -1


func _process(delta):
	# Move up and down based on input.
	var input = Input.get_action_strength(_down) - Input.get_action_strength(_up)
	position.y = clamp(position.y + input * MOVE_SPEED * delta, 16, _screen_size_y - 16)
	_relative_speed = input * MOVE_SPEED * delta

func _on_area_entered(area):
	if area.name == "Ball":
		# Assign new direction.
		#area.direction = Vector2(_ball_dir, randf() * 2 - 1).normalized()
		area.direction = Vector2(_ball_dir, _relative_speed).normalized()  # 相対速度を考慮した打ち返し
```

paddleの移動に合わせてボールが移動するようになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/87c309ee-5dfe-6de6-e81e-dab61de33ffd.png)


### 備考

厳密に考慮した実装ではない。
(windows)個人的ショートカット集

##目次
音量調整ショートカット 2021/08/26
アプリケーション終了 2021/08/26

###音量調整ショートカット
windows + b -> 矢印キーで移動 -> 音量アイコンに行く -> 矢印キーで抜ける -> esc

###アプリケーション終了
alt + f4
Python 3.8: 代入式(:=)を使って、フィボナッチ数列の lambda 式を作る

フィボナッチ **数列** は単純な手続きで作れるけど、プログラムにすると以外と面倒臭い。

```python:Python
def fibonacci_table(n):
    r = []
    a, b = 0, 1
    for _ in range(n):
        r.append(a)
        a, b = b, a + b
    return r
```

これを Python 3.8 から使用可能な代入式 `:=` を使って lambda 式で作ってみる。

```python:Python3.8
fibonacci_table = lambda n, f1=0, f2=1, f3=1: ([0, 1] + [(f3 := f1 + f2, f1 := f2, f2 := f3)[0] for _ in range(n - 2)])[:n]
```

もっと単純になるかと思ったけど、横に長くなっただけだった。
(行末の [:n] は、n が 0 または 1 のためにあります)

```python:実行結果
>>> fibonacci_table(12)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
```

---

@shiracamus さんに教えてもらった記事をここにも貼っておきます。

https://qiita.com/ytaki0801/items/dc6392dbce6d2b9bb483
Qiita Daily Survey memo 2021.08.26

# Qiita Daily Survey memo 2021.08.26
Qiita の記事を可能な限り毎日読むために、読んだmemoを公開することでモチベーションを維持しようという試み。

# [色々な会社のエンジニア向け新人研修資料](https://qiita.com/ok2/items/04086f7ee7bde6ab57b9)
ok2 さんの記事。
タイトルの通り、5社ほどの新人研修の資料をまとめてくださっている記事です。

新人研修で難しいところは、ゴールの設定なのかな…と思っています。
自分の会社でどこの部署に配属されるかわからない状態で、どこへ行っても活かせる技術をプログラム組み込むというのは大事だなと思います。
資料を拝見させていただいている中で、自分が勤めている会社は資産管理ができていないため、積集合の部分が抽出できてないな…と思いました。

実際、新人研修が終わった後も「何もできるようになった気がしない」と新人の方に相談されたりと…難しいですよね。
資料は参考になるものばかりなので、共有しつつ…己を知るところからだな…と思いました。


# [初心者の非同期処理の覚え方](https://qiita.com/shumanbeing/items/2207102f79a21ae969e1)
SHU (shumanbeing) さんの記事。
Javascript の非同期処理は本当に難しく、SHU さんの解決方法を共有してくださっている記事です。

初めてお仕事で Javascript を触った際、 promise が全く分からず何日も立ち止まってしまった記憶が強くあります。
私もまだまだ初学者ゆえ、人に説明できるほど理解できておらず…この記事をきっかけにもう一度調べてみようかなと思いました。

# [Flutterで個人アプリリリースをして、約1年間で得た知見をまとめる](https://qiita.com/Sashiiii111/items/65f53c80a108ef1a826e)
Sashiiii111 さんの記事。
Flutter で作成して公開したアプリが1周年となるため、その振り返りの際の知見を共有してくださいっている記事です。

何かを作成して、1人以上に使ってもらって幸せにしている時点で、本当にすごいと思います。
Done is better than perfect はメモしました。

最後にの項目に思いが詰まっていて、エネルギーをいただきました…！
uninitialized constant ~~ の対処法

#背景
Railsにて ログイン機能を実装できるGem devise を実装しようとしていた中の出来事です。
ログイン画面はできたのですが、ログアウトを選択すると以下のエラーが発生しました。


```
Routing Error
uninitialized constant Users
```

直訳すると「初期化されていない定数」とのことです。


#原因
users コントローラがないことが原因でした。
初歩的なミスですね。作り忘れていたみたいです。。


#解決策

usersコントローラーで作成したら解決です。
ログアウトを選択してもエラーは出なくなりました。
【Cloud9】Cloud9で消したファイルやコードを復元する方法


#対象者

* Cloud9でファイルやコードを復元できず困っている方


#目的

* リビジョン機能を使って復元させる

#実際の手順と実例
###1.削除したファイルと同じ名前のファイルを作成しておく

今回ここではフラッシュメッセージで使用していたflash.jsファイルを復元します。

ファイル自体を削除してしまったので、
全く同じ名前のファイルを作成します。



###2.cloud9上でFile >　Show File Revision Historyを開く

下記画像の通りです。

![スクリーンショット 2021-08-25 13.52.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1681213/31eb91a4-0e52-350b-c2a3-8c444cfdca38.png)



###3.ファイルを復元する

![スクリーンショット 2021-08-25 13.52.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1681213/b81bc527-b176-d3cb-6431-0c5a9bfa05a3.png)

戻したい箇所まで戻します。

![スクリーンショット 2021-08-25 13.53.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1681213/38cccc1c-4e9d-b1d6-a08e-a6ec26f23242.png)

これで復元完了です！！


####投稿者コメント
ファイルを消すと落ち込みますがcloud９だと安心です。
ただ、ファイルを消す前に本当に削除していいかどうかは必ず確認する癖をつけようと思いました、、、、


####My Profile
プログラミング学習歴３ヶ月目のアカウントです！
プログラミングスクールで学んだ内容や自分が躓いた箇所等のアウトプットの為に発信しています。
また、プログラミング初学者の方にわかりやすく、簡潔にまとめて情報共有できればと考えています。
もし、投稿した記事の中に誤り等ございましたら、コメント欄でご教授いただけると幸いです。
React入門 - Tips5 - 無限レンダリング


# 目次

# 無限レンダリング

この記事を書くきっかけは、Reactのプロジェクトに入って間もない頃に、もちろんReactスキルも低い状態で試行錯誤していた状況でよく以下のエラーに出会ったということを思い出したというところです。

```typescript
Error: Too many re-renders. React limits the number ・・・・
```

ちゃんと学習することで、特にReactフック(特にuseEffect, useLayoutEffect)の第2引数の役割についての理解に繋がるかと思います。

<font color="red">
ちなみに、今回[codesandbox](https://codesandbox.io/)では、想定したエラーが出せませんでした。
ですのでReact実行環境を作成し試してください。
</font>
# 無限レンダリングを起こすコーディング

まずは、起こさないコーディング

```typescript
import React, { useState, useEffect } from 'react';

const App = () => {
  console.log('App');
  const [time, setTime] = useState('');

  useEffect(() => {
    console.log('useEffect');
    setTime('あああ');
  });
  
  return <h1>ミリ秒：{time}</h1>
}

export default App;
```

実行し、コンソールログを確認すると

```typescript
App
useEffect
App
useEffect
App
```

ざっくりと説明すると

1. ブラウザでアクセスすることにより`App`が読み込まれる
2. useEffectが実行される
3. 上記useEffect内でstateが変更される
4. 上記により、再度`App`が読み込まれる
5. useEffectが実行される
6. 上記useEffect内でstateが変更されるるが、stateの内容に変化が無いので終わり

<font color="red">※ちなみに、stateの値がプリミティブ型でなくオブジェクトの場合、たぶん無限レンダリングが起きます。オブジェクト型は中の値でなく参照で比較されるので。。</font>

エラーを起こしてみましょう。
一部分を修正します。

```typescript
    // setTime('あああ');
    setTime( String((new Date()).getTime()) );
```

また、実行後、コンソールログを確認してみてください。
（見た目もずっと更新されていますので、分かるかと思いますが。。。。）

先ほどの説明の6.の`6. 上記useEffect内でstateが変更されるるが、stateの内容に変化が無いので終わり`が`6. 上記useEffect内でstateが変更され、stateの内容に変化があり終わらない`って感じでしょうか。

初期表示時にミリ秒を表示するだけなら、useEffectの第2引数を`[]`にします。

```typescript
  useEffect(() => {
    console.log('useEffect');
    // setTime('あああ');
    setTime( String((new Date()).getTime()) );
  }, []);
```

今回の無限レンダリングは、かなり簡単な例を挙げました。
他にも関数の書き方(アロー関数を使わない)など原因となるコーディングは、いくつかあると思います。
それらに出会ったときに、解決のヒントになれば幸いです。

※また、無限レンダリングのネタ見つけたら追記します。
Powershellで待機時間を設定する方法

Powershellで待機時間でメッセージを標準出力で出力する方法です。

```Powershell
## Sleepクラスを定義する
class Sleep {
    [int]$wait=10
    [String]$msg1="START"
    [String]$msg2="END"
}
#インスタンスを呼び出す
$sl = [Sleep]::new()

#wait処理を行う
for($i=0;$i -lt 2;$i++){
    Write-Host $sl.msg1
    Start-Sleep $sl.wait
    Write-Host $sl.msg2
}
```

このスクリプトで10秒待機してから処理が進むようにスクリプトを作成しています。
数式で参照先のNameでエラーが出る時

Account.Solution_Consultant__r.Name ではスペルミスというエラーが出て

Account.Solution_Consultant__c　ではIdがきちんと表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8991c1fb-7b2d-c38a-90c7-425a957396a8.png)


この場合は参照しているオブジェクトがuserみたいです。
そのため、Nameでなくて

Account.Solution_Consultant__r.FirstName +" "+ Account.Solution_Consultant__r.LastName

を使うといいとのこと。

盲点でした。

https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000CesTmSAJ
「挫折しないドメイン駆動設計」参加ノート

[Dojo夏休み企画：挫折しないドメイン駆動設計（DDD） - connpass](https://ibm-developer.connpass.com/event/221512/) を聴講したのでそのノート。

<script async class="speakerdeck-embed" data-id="4a949cea7b274b739e1904c1a3349f65" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>

## ドメイン駆動設計（DDD）とは

- DDDの関心の高まり
- ドメインって何
- ドメインに興味を持とう
- ドメインを分析する

DDDをこれから勉強したい方に「DDDに興味を持って、良いね！と思うこと」が今回のゴール


### DDD
- エリック・エヴァンス氏が提唱した
- ソフトウェアの設計・開発手法
- 顧客も開発者も、システムに関わる人皆が共通の言葉を持って、同じ認識を持ってシステムを作り上げるのがDDD

[エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践) | エリック・エヴァンス, 今関 剛, 和智 右桂, 牧野 祐子 |本 | 通販 | Amazon](https://www.amazon.co.jp/%E3%82%A8%E3%83%AA%E3%83%83%E3%82%AF%E3%83%BB%E3%82%A8%E3%83%B4%E3%82%A1%E3%83%B3%E3%82%B9%E3%81%AE%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9%A7%86%E5%8B%95%E8%A8%AD%E8%A8%88-Architects%E2%80%99Archive-%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA%E3%81%AE%E5%AE%9F%E8%B7%B5-%E3%82%A8%E3%83%AA%E3%83%83%E3%82%AF%E3%83%BB%E3%82%A8%E3%83%B4%E3%82%A1%E3%83%B3%E3%82%B9/dp/4798121967)

### 共通の言葉とは

単なる言い回し？
ではなく、顧客と開発者が歩み寄るイメージのもの

実際の業務をきちんと理解しないで作ったら、リリースしてもあまり使われなかった...
業務変更のためソフトウェアを修正することになっても、どこを直せばよいかすぐわからない...

これらの事態を防ぐため
業務の本質を理解して、価値あるソフトウェアを作ることを目指す。

DX、マイクロサービス、アジャイル開発、を背景に注目されていて、頻繁なコード変更にも耐えられるような、変化に強いシステムを目指すもの。

### ドメインってなに？
「システム化する際に対象となる業務」
ドメイン駆動とは、業務を理解するところから始めるということ。

例えば、映画館のチケット購入システム

- 上映映画に対する座席数
- 料金
- その映画館の「業務上の決まりごと」
  - 「業務上の決まりごと」を知らないとどんなシステムを作ればよいかわからないので、知る必要がある。
  - 「業務上の決まりごと」を正しく理解するために、ドメインモデルを作る。
  - ドメインモデルとは、「業務上の決まりごと」を整理したもので、ソフトウェア開発のインプットとなるもの。
- ドメイン→ドメインモデル→ソフトウェア
  - ドメインモデルを見れば、業務担当者も開発者も共通理解ができる。
- ドメインモデルはどうやってつくるの？
  - 業務の仕組みやルールに詳しい人の話（= ドメインエキスパート）を聞くこと。
- 映画館の例なら
  - 映画館の館長
  - チケット売りのスタッフ
  - 映画館の常連さん

### ドメインモデルを作ろう

例題: 映画チケット購入システム

1. ドメインエキスパートの話に耳を傾ける
2. 単語をピックアップする
3. 単語を線で結んで関連付ける

```
「座席予約表を見て空いている席を確認します」
「どの座席予約表を見るかは、映画の上映タイトル、日時で決まります」
「座席番号を選択して、席を確保します」
「座席を確保後、料金を計算します」
「料金の支払いが完了したらチケットを発行します」
「料金の計算は購入者の性別、年齢、曜日、特別割引日などにより決まります」
```

目的語に特に注意。
参照するもの、利用するもの、インプットするものなどという観点から関連付ける。

- 座席予約表
- 上映タイトル
- 日時
- 座席番号
- 料金
- チケット
- 購入者の性別や年令
- 料金の計算
  - ドメインエキスパート:「レイトショーなら一律1000円、60代以上夫婦割、レディースデー等」
  - 開発者:「基本料金から割引をして最終的な料金が決まるのですね」

**こうして共通言語を作っていくことを、ユビキタス言語という**

ソフトウェアに必要な概念が網羅されているか？
ドメインを定義
業務をさらにグルーピングしてドメインを定義し、ビジネス価値を提供するために特に重要なドメインをコアドメインとして定義する。

コアドメインに注力してDDDをすすめる。

- 座席予約ドメイン
- 料金支払いドメイン

等など

## ドメイン分析例題「美容院の予約システム」

ドメインエキスパートの声

```
「カット、カラー、パーマなど、どのメニューにするか確認します。」
「担当者を確認します。」
「予約表を確認して、空いている日時をご案内します。」
「お客様の年齢、担当者、メニューによって料金が決まります。」
「当日の3日前まで予約の変更、キャンセルを受け付けます。」
```


以上を題材に考えてみるのが練習。
追加でドメインエキスパートに質問したいことはあるか？等も、考えてみるのがポイント

## 参考資料

[ドメイン駆動設計 基本を理解する](https://www.slideshare.net/masuda220/ss-59756718)
[draw.io](https://qiita.com/riku-shiru/items/5ab7c5aecdfea323ec4e)等がダイアグラムを描くのに良い
DDDは業務が変更されたら随時更新していくもの
ユビキタス言語の用語集を作って満足してしまったりするのがアンチパターン
システムの複雑度合い、不確定度合いなど、使い所は見極める必要がある。

ということで、たのしみながらDDDをすすめてみよう～　という感想。

[ドメイン駆動開発を浸透させるための新しい取り組み - SO Technologies 開発者ブログ](https://developer.so-tech.co.jp/entry/kichion-01) の資料も読みたい。
以上メモ仕立てですが、参考になればさいわいです。
Flutterのラジオボタンの使い方

Flutterのラジオボタンを使っていて、微妙にわかりにくいなと思った部分があるので共有します。

公開ステータスを設定するためのラジオボタンを作りたいと仮定します。


```dart
enum Status {
    open,
    hidden,
    notSelected,
}
```

上記のようなenumでStatusを定義して、Radioのそれぞれのコンストラクタの意味合いを解説しますと

```dart
// enumでもintでもStringでも可。後述のvalueやgroupValueの型を決定する
Radio<Status>(
    // 選択されたときのonChangedに吐き出される値
    value: Status.open,
    // groupValueと上記のvalueが一致していた場合に、ラジオボタンは選択済みの表示になる
    groupValue: status,
    onChanged: (value) {
        // 選択時にStatus.openがvalueとして吐き出される
    }
)
```

上記のような使い方ができました。
初期値として```status = Status.notSelected```を指定しておけば、ラジオボタンを未選択な状態にできますし、デフォルトで公開にしておきたければ```statsu = Status.open```と指定しておくことで実現できます。
M1 Macでpod installをする方法

#M1 Macではsudo gem install cocoapodsには成功はするが、pod installを実行するとエラーになる
これはMacのターミナルのアーキテクチャが__Apple__になっているのが問題になります
ですので、このアーキテクチャを__Apple→Intel__に変更してあげます
#変更する方法
##1. Rosettaを使用して開くにチェックを入れる
Finderからターミナルを探し、右クリックで「情報を見る」 > 「Rosettaを使用して開く」 にチェックを入れます
![スクリーンショット 2021-08-26 1.48.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1150411/fdec163a-492d-6ee1-3845-0d80d5a40cf8.png)
![スクリーンショット 2021-08-26 1.49.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1150411/53a31f49-97bc-3f2d-7ab7-d7b02ef665f6.png)

チェックを入れると、アクセシビティモニタのターミナルがIntelに変わったのが分かります
もしここで、Appleのままであれば一度再起動してみてください
自分は変更されなかったので、再起動しました
![スクリーンショット 2021-08-26 3.03.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1150411/4e39b85a-3b76-1d41-0cd2-be74af81d299.png)

##2.sudo gem install ffiを実行する
```sudo gem install ffi```
パスワードが求められますので、ご自身のパソコンのパスワードを入力してください

##3 最後にpod installを実行する
```pod install```
![スクリーンショット 2021-08-26 1.55.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1150411/46bf6f73-3f9c-b79b-cbbc-c5cb3ec77304.png)


これでライブラリやFirebaseなどをインストールすることができるかと思います
参考になれば幸いです、ありがとうございました
Google Apps Script GitHub アシスタント導入時、[GitHub assistant] undefined エラーが出た時の対処法

#はじめに
- GASのコードをGitHubのリポジトリで管理したいと思い Google Apps Script GitHub アシスタント と言うChrome拡張機能を導入した時にエラーが出たので、その対処法をまとめました。

#Google Apps Script GitHub アシスタント の導入方法
- [こちらの記事](https://qiita.com/20731057hh/items/7f76f9e53e9da5c85ae9)を参考にしました

#[GitHub assistant] undefined エラーが出た時の対処法
###1. Apps Scriptダッシュボードの設定をオンにする

- [Apps Scriptダッシュボードの設定画面へ](https://script.google.com/u/0/home/usersettings)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572559/3eddc077-37ee-8b1d-aaf0-170154ebcd2f.png)

これをオンにすることでエラーが消える場合もある。


###2. GASの新バージョンのエディタを使っている場合、ログイン方法が異なる時は、以下の方法を試す。

通常ユーザー名とパスワードでログインするところ、GASで新しいバージョンのエディタを使うのであれば、ユーザー名とトークンでログインする必要がある。

####まずはtokenを取得
- Github Assistantのログイン画面にある[Github Access Token](https://github.com/settings/tokens)をクリック（要Githubへのログイン）し、Generate New Tokenをクリックする。

![スクリーンショット 2021-08-26 2.39.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572559/c6734401-94f8-716f-4209-6e80820671b0.png)


- Noteにわかりやすい名前をつけて、repoおよび必要なアクセス権限にチェックを入れる

![スクリーンショット 2021-08-26 2.42.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572559/6ac5ec84-0b5b-5e29-9718-f4a2b2bd2aa2.png)

- Personal Access Tokenが出るのでコピーする

####Github Assistantに戻り、自分のGitHubユーザー名と、取得したアクセストークンを入れてGithub Loginをクリック

![スクリーンショット 2021-08-26 2.48.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572559/d4a8c143-d2c0-c3d2-0560-36f293b33f74.png)


####Google Apps Scriptの開発画面をリロードすると、読み込まれてRepository updatedが出るようになる

#まとめ
#####以上２つの点を確認すべし。
Squidのaccess.logに時間を表示する

デフォルトだとアクセスログにUNIXタイムスタンプしか出ないので非常にしんどい。
そのためログフォーマットを指定し、「YYYY/MM/DD HH:MM:SS」形式の時間をログに追加する。

# 環境
- Debian 10 ( buster )
- Squid 4.6

# 結論
squid.confに以下の2行を追記する。
内容は、ログフォーマットを定義し、アクセスログに適用するというもの。
デフォルトのログフォーマットに`%{%Y/%m/%d %H:%M:%S}tl`を追加しただけです。

```/etc/squid/squid.conf
logformat timefm %{%Y/%m/%d %H:%M:%S}tl %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %[un %Sh/%<a %mt
access_log daemon:/var/log/squid/access.log timefm
```

上記の設定を適用するとこうなる。先頭に「YYYY/MM/DD HH:MM:SS」が追加されている。

```/var/log/squid/access.log
# 設定前
1629912743.892    183 192.168.0.1 TCP_TUNNEL/200 32439 CONNECT blog.hir0.dev:443 proxy HIER_DIRECT/183.181.83.57 -

# 設定後
2021/08/26 02:38:16 1629913096.438    256 192.168.0.1 TCP_TUNNEL/200 32439 CONNECT blog.hir0.dev:443 proxy HIER_DIRECT/183.181.83.57 -
```

# 参考
こちらの記事の内容を短くまとめただけです。

https://nwengblog.com/squidlog/
プログラマとしての備忘録の付け方

皆さん、デバッグしたり障害対応する時ってググりますよね？
で、他の人が書いた備忘録とかに助けられたりしたことがあるのでは無いでしょうか？
僕もよく助けられましたし、ちょいちょい自分が書いた過去記事に助けられたりします。

そんな時にわかりやすい様に、他の人の助けになりやすい様にポイントを押さえて書きましょう。それが僕たち全員のためになりますし、何より未来の自分を助けてくれます。

記事の粒度は結構細かくて良いです。本当に備忘録として自分が後で見る様にって感じでOKです。書いて公開することが重要です。

# タイトルが重要
備忘録を書く場合タイトルが重要です。何故なら記事のタイトルはHTML上で``title``要素となり、検索エンジンの検索対象としてプライオリティが高いからです。

## エラー対応の場合
エラー対応の場合、必ず本文にエラー文を入れましょう。全部入れなくても重要な部分だけでOKです。
例えば、

```console
[Doctrine\DBAL\Schema\SchemaException (60)] An index with name 'idx_3267cc7a4584665a' was already defined on table 'dtb_product_image'.
```
というエラーの場合、タイトルは
> MySQLでPHPの[Doctrine\DBAL\Schema\SchemaException (60)] An index with name 'idx_xxx' was already defined on table 'table_name_xxx' エラーが出た場合

とかです。
そうすれば、このエラー文で検索した時に検索に引っかかりやすくなります。タイトルは多少長くても良いです。
悪い例は
> MySQLで商品登録したらエラーになった

とかです。これだとどんなエラーか？どこでエラーになったかがわかりにくく、検索にも引っかかりにくいです。

## 実装方法の場合 
実装方法の場合、**言語**、**フレームワーク**、**バージョン**、**実装内容**をタイトルに入れましょう。
例えば、　EC-CUBEのVer.4系で商品編集画面にテキストフォームを追加する場合なら
> EC-CUBE4でsymfony FormTypeを使って商品登録フォームにテキストフィールドを追加する

とかです。

## タグ
Qiitaとかだとタグを付けれます。関連するタグを付けておくと、さらに探しやすくなるので、必ず付けておきましょう。

# 文書構造
見た時にわかりやすい様に、文書構造も重要です。だらだらと長く書いて、欲しい情報を探すのが面倒臭いとかなっちゃうんで。

## 導入部
導入部には、通常のテキスト（パラグラフ）でタイトルの詳細を書きましょう。
上記のエラーの例でいけば、
### エラー対応の場合
> EC-CUBE4でデータベースのスキーマを更新しようとして``./bin/console eccube:schema:update --dump-sql``を打ったら、``[Doctrine\DBAL\Schema\SchemaException (60)] An index with name 'idx_xxx' was already defined on table 'table_name_xxx'``ってエラーが出た。どうも既に存在しているインデックスを再度追加しようとしているエラーらしい

### 実装方法の場合
> EC-CUBE4系の管理画面、商品管理の商品登録/編集画面にデータベースに追加したカラムの入力フォームを、PHPのフレームワーク、symfony 3.4系のFormTypeとEntityのannotation使って、EntityTraitだけでCustomizeディレクトリから追加する。

とかです。
ここでも、ミドルウェア名、フレームワーク、バージョン、クラス名、関数名など関連するキーワードを入れておくと後から探しやすくて良いです。
障害対応やバグ対応の場合は、ログの一部や出力されたエラーメッセージなんかを貼っとくとなお良いです。その際は公開しちゃいけない情報（パスワードやアカウント名、IPアドレス、ディレクトリ名とか）、をマスクしてxxxとか〇〇とかしときましょう。

## 見出し
見出しも検索対象の重要なので、必ず書きましょう。上から順番にダーっと書いていくのではなく、先に見出しを箇条書きで書くと、順序だったわかりやすい文書構造の記事にしやすいです。

例:

```markdown
# エラーの原因
## どこでインデックスを追加しようとしていたか
# 調査方法
## --vv追加して詳細を出力する
# 対応方法
## インデックスを一回消す
## migrationの修正
# 関連情報
## 同じエラーにハマった人の記事
## 似たエラーの記事
# リファレンス
## symfonyドキュメント
## doctrineドキュメント
## MySQLドキュメント
## githubのissue
```

な感じです。ここまで細かく書かなくても物によってはOKです。エラー対応の場合は、最低でも原因と対応方法は書きましょう。

## 関連情報
関連情報には、参考になる関連情報、同時に起こりやすいエラーや不具合、似た様な実装などリンクをリストで並べておくと良いです。

## リファレンス
リファレンスには、対応するにあたって調査した際に参考にした記事、ドキュメント、資料なんかをリストアップしておきましょう。


# 細かいことでもどんどん書いていこう
どんな細かいことでも良いので、ササッとどんどん書いていくと、結構たまっていって、後で「そういえば前に似た様なことあったな」って助かったり、転職の際にPRポイントになったりします。 どんどん書いていきましょう。

ちなみに、僕が書いた過去の備忘録はこんな感じです。

- [Compile Error: Declaration of EntityManager_xxxxxxx::getProxyInitializer() が出た時の対応](https://qiita.com/tao_s/items/b296c0ee3b4ce0135062)
- [EC-CUBE4でプラグインのEntityを拡張しようとしたらproxyの生成でコケて困った時の対応](https://qiita.com/tao_s/items/e0804f6c3e9c740ebc11)
- [Let's encryptのcertbot renew でpythonのdecodeエラーが出た場合の対応](https://qiita.com/tao_s/items/78a7f5c4a422ff203492)
- [Google CloudのAppEngineでGo v1.12を使ったときにハマったこと](https://qiita.com/tao_s/items/449c5f62229f795ccb16)
- [EC-CUBE3でMySQL使ってPDOのSQLSTATE[HY000] [2002]でエラーでインストールできない時](https://qiita.com/tao_s/items/3611aebc8fa7f775b7aa)
UTCの日付をISO8601基本方式で出力する方法

アプリケーション開発中に日付を **基本形式のISO8601@UTC** で出力する必要があったのですが、
世の中の様々なライブラリのでISO8601出力をすると **拡張形式ISO8601** になってしまったので色々と苦労しました、

```js
// Good（ISO8601 基本形式）
const dateStrOk = "20210801T100000Z"

// Bad（ISO8601 拡張形式）
const dateStrNg = "2021-08-01T10:00:00Z"
```

結論としては `moment` と `date-fns` を使って以下のように実装することができました。
プロジェクトの制約上 `date-fns` の `format` を使わないといけなかったのですが、
恐らく `moment` の `format` でも実装できると思います。（未検証）

```js
import moment from "moment";
import format from "date-fns";

const ISO_8601_BASIC = "yyyyMMDDTHHmmss";
const dateStr = moment(new Date()).utc().format(ISO_8601_BASIC)
console.log(dateStr) //20210801T100000Z
```

rRuleのライブラリなどを使う際必要になるので、お困りの方の力に慣れれば幸いです。
もし、もっといい方法あるよ！という方いらっしゃったら是非教えて下さい。
【Salesforce】Apexでの文字列結合

## 3行で要約
- 本番運用しているSalesforceアプリケーションにて、「Apex CPU time limit exceeded」というエラーが発生するようになりました。
- どうやらデータ量が増えてガバナ制限内に処理が完了しなくなってしまったらしい。
- Apexコードの文字列結合がボトルネックになっていたため、それを解消して問題を解決しました。

## 背景
- ある日のこと、日次の注文データを、CSVファイルに書き込んでエクスポートする機能でエラーが発生。
- エラー内容は「Apex CPU time limit exceeded」とのこと。
- これはガバナ制限により、1つのApexトランザクションの実行時間を10秒以内にしなければならないために起こるエラーだそう（データベース操作やコールアウトの待ち時間は含みません）
    - ちなみに10秒ちょうどでエラーになるのではなく、15秒前後まではギリギリ大丈夫みたいです

## 原因
- Limits.getCpuTimeout()メソッドを使ってトランザクション内の各処理の時間を測定します。
- CSVファイル生成のための文字列結合部分に「+」演算子を使っており、この処理が非常に遅くボトルネックになっていることが判明しました。

```java
String csvBody = A + ',';
csvBody = csvBody + B + ',';
csvBody = csvBody + C + ',';
.
.
.
```

## 解決
- JavaであればStringBufferもしくはStringBuilderを用いることが推奨されているかと思いますが、残念ながらApexにはそのようなものは用意されていません。
- Stringクラスにあるjoinメソッドを使うことで文字列結合がだいぶ速くなりました。

```java
List<String> csvItems = new List<String>();
csvItems.add(A);
csvItems.add(B);
csvItems.add(C);
.
.
.
String csvBody = String.join(csvItems, ',');
```

- 結果、ガバナ制限に引っかからなくなりました。
- ついつい文字列結合に「+」を使いたくなりますが、データ量が多くなりそうならなるべく使わないよう気をつけましょう


## 参考
- Stringクラス - join
    - https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_string.htm#apex_System_String_join
contenteditableな要素の入力でEnterキーを無効化する方法

inputタグやtextareaタグでEnterキーを無効にする方法は調べたらすぐ出てくるが、contenteditableはそうではない。
因みに、inputタグやtextareaタグでEnterキーを無効にするには、

```jsx
<input onKeyPress={(event) => {if(event.key === 'Enter') return false}} />
```

で制御可能なはず。
だが、contenteditableな要素はこれでは制御できない。
構わずに、Enterキーが有効になり、改行を行ってしまう。

```jsx
<div 
  contentEditable="true"
  onKeyPress={(event) => {
    if(event.key === 'Enter') {
      return event.preventDefault()
    }
  }}
/>
```
このように記述すれば、改行を防ぐことができる。
日本語入力の際に確定する時のEnterキーは有効となっている。

因みに、日本語入力の際に確定するときのEnterキーも無効化されると思って、以下のように記述したが、その必要はなさそうだ。

```jsx
<div 
  contentEditable="true"
  onKeyPress={(event) => {
    if(event.key === 'Enter' && !isInputting) {
      return event.preventDefault()
    }
  }}
  onCompositionStart={() => {setIsInputting(true)}}
  onCompositionEnd={() => {setIsInputting(false)}}
/>
```

onCompositionStartは入力開始時に発火して、onCompositionEndは入力確定の時に発火するメソッドです。
Debianのキー配列の設定

debianのインストールの際に日本語入力で設定してしまうと失敗することが多い（実際に失敗した）ため、usで設定を行った。
しかし、その後のキー配列でかなり時間を要したため、参考になればと考える。Debian歴数日の初心者のため、何か訂正や修正、この方が効率が良いなどがあれば気軽にコメントしてくれれば嬉しい。

前提条件
・debian（+デスクトップ環境（今回はGnome））インストール済み

まず、様々な人が言っているように、

```~#sudo dpkg-reconfigure keyboard-configuration
```

を試すと良いと思う。この詳細に関しては後述の記事を参考にしてほしい。

次に

```~#localectl set-keymap jp106
```

を行うことで、

```
　省略
   VC keymap: jp106
   X11 layout: jo
   x11 Model: jp106
```

となる。
以上についての参考は
https://www.server-world.info/query?os=Debian_10&p=keymap
（Server World キーボードの割り当てを設定する）
これで再起動、またはsystemctl restartなどをして確認したところ、キー配列はusのままだった。ちなみにconsole-setup.serviceがfailedだった。keymapsが無いとのことである。

次に

```~#sudo dpkg-reconfigure console-setup.service
```

でセットアップを行った結果、キー配列についてはうまくいった。設定の参考には以下のサイトを確認してほしい。
https://linuxfan.info/ubuntu-server-change-console-font
(Ubuntuサーバーの「コンソールフォント」を変更する方法)

ちなみにkeymapsについてはなぜかパッケージはinstall済みだが、ファイルが見つかってないとのことなので次回以降攻略できればと思う。なぜkeymapsが解決していないのにキー配列が改善したかはまだまだ不勉強であるため分からなかった。

今回は正確には質問した人のようには解決しなかったが、以下のサイトを参考に設定を行った。
https://askubuntu.com/questions/800871/failed-console-keymap
(ask Ubuntu FAILED: console keymap)

なお、この後gnomeでも設定を反映したいと思うが、他のサイトでよく見る

```
setxbmap jp
```

だけだとインストールした直後は（特にハードウェアインストールした場合は）$DISPLAYが設定されていないと思うので、必ず

```
export DISPLAY=:0.0
```

などの設定がいることに要注意。
東京都の国のステージ判断のための指標のPDFからCSV作成（pdfplumber）

https://www.fukushihoken.metro.tokyo.lg.jp/iryo/kansen/corona_portal/info/kunishihyou.html

![kuni0824.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36151/87d00b63-d838-43d6-e19a-a3e598f1446d.jpeg)

camelotでも作成
https://qiita.com/barobaro/items/7ecfd6d3b24e3bbd6477

表部分は固定みたいなので表の位置を指定して抽出

```python
import datetime
import pathlib
import re
from urllib.parse import urljoin

import pandas as pd
import pdfplumber
import requests
from bs4 import BeautifulSoup

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
}


def fetch_soup(url, parser="html.parser"):

    r = requests.get(url, headers=headers)
    r.raise_for_status()

    soup = BeautifulSoup(r.content, parser)

    return soup


def fetch_file(url, dir="."):

    p = pathlib.Path(dir, pathlib.PurePath(url).name)
    p.parent.mkdir(parents=True, exist_ok=True)

    r = requests.get(url)
    r.raise_for_status()

    with p.open(mode="wb") as fw:
        fw.write(r.content)
    return p


# スクレイピング

url = "https://www.fukushihoken.metro.tokyo.lg.jp/iryo/kansen/corona_portal/info/kunishihyou.html"

soup = fetch_soup(url)
tag = soup.find("a", class_="pdf", text=re.compile("^国のステージ判断のための指標"))
link = urljoin(url, tag.get("href"))

p = fetch_file(link)

pdf = pdfplumber.open(p)

page = pdf.pages[0]

# 日付取得
crop = page.within_bbox((26, 7, 375, 39))

title = crop.extract_text()

print(title)

dt_now = datetime.datetime.now()

m = re.search("(\d{1,2})月(\d{1,2})日", title)
month, day = map(int, m.groups())
latest = datetime.date(dt_now.year, month, day)

# PDF表の座標を指定

table_settings = {
    "vertical_strategy": "explicit",
    "explicit_vertical_lines": [236, 367, 502, 605, 682],
    "horizontal_strategy": "explicit",
    "explicit_horizontal_lines": [45, 90, 145, 202, 260, 317, 376, 430, 493],
}

table = page.extract_table(table_settings)

df0 = pd.DataFrame(
    table[1:],
    index=["新規報告者数", "感染経路不明割合", "PCR陽性率", "療養者数", "病床全体", "入院率", "うち重症者用病床"],
    columns=table[0],
)

df1 = df0.applymap(lambda s: s.replace("\n", ""))

df1.to_csv(f"{latest.isoformat()}.csv", encoding="utf_8_sig")
```
【pandas】Dataframeで正規表現で置換

## DataFrameで正規表現を利用して文字列置換をしたい

replaceメソッドを使えば可能でした。ドキュメントは[ここ](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.replace.html)

以下のサンプルコードはnameカラムの先頭の「あいう」という文字列を「aiu」に置き換えるだけのかんたんな例です。

```python:regex_replace.py
import pandas as pd
import re

df = pd.DataFrame(
    data={
        'name': ['あいうえお', 'かきくけこ', 'サシスセソ'],
        'kind': ['ひらがな', 'ひらがな', 'カタカナ']
    }
)
df["name"] = df["name"].replace(re.compile(r"^あいう"), 'aiu', regex=True)
print(df)
```

## 結果
```
    name  kind
0  aiuえお  ひらがな
1  かきくけこ  ひらがな
2  サシスセソ  カタカナ
```
mayaがエラー・ワーニングを吐く時の対処 2　~みつからないplug-in~

mayaがerrorを吐いて鬱陶しい時
メッシュデータをimportしただけでこんなエラーを吐く時

    RuntimeError: file <maya console> line 1: Plug-in, "maxwell", was not found on MAYA_PLUG_IN_PATH. # 

プラグインが見つかりませんエラー。

これには2通りあって、
1, 必要なプラグインが読み込めず、シーンの構築に失敗している場合
--

    Errors have occurred while reading this scene that may result in data loss

と出たり、ダイアログがドゥンと出てきてシーンの構築に失敗していることを教えてくれる。
この際、プラグインによって管理されているノードがあった場合は**unkownノード**としてとりあえず作成される。
データとして欠損が起きてしまっているので、プラグインを読めるようにmayaの環境を整理する必要がある。


2, 特に必要ないけど読めと言われているプラグインが読み込めていない。シーンの構築は成功している。
--

所謂unkwonプラグインが発生している。
データ上は特に何も影響を及ぼさないが、データ上にこれらのプラグインを読み込むようにと指示が書き込まれてしまっている。

> **何がいけないの？データ壊れてるわけじゃないからいいじゃん。**

というご意見もあろう。
unknownプラグインを一生懸命探しに行くので、**ファイルを読み込む時間が長くなる**というデメリットがある。

> **え？大した時間かからなくない？数秒じゃん？**

というご意見も頂く。

1ファイルなら・・・・・
mayaでリファレンスを使ってファイルを複数参照している場合、
**そのファイル数 x unknownプラグイン探す時間**　になるので　シーンによっては分単位かかることも。

なので、除去したほうがメリットは多い。

maya2015の途中から　unknownPlugin　というコマンドが実装されたので、
それを使用して確認と除去が行える。

unkownプラグインの確認

    import maya.cmds as cmds
    plugins = cmds.unknownPlugin(query = True, list =True)

戻り値はプラグインのリストかNone

除去する場合は

    cmds.unknownPlugin(plugin, remove = True)

なので、これらを合わせて

    import maya.cmds as cmds
    plugins = cmds.unknownPlugin(query = True, list =True) or []

    for plugin in plugins:
        cmds.unknownPlugin(plugin, remove = True)
        print "        <<unload   " +plugin+ ">>"

unkownプラグインの厄介なところは、
該当シーンを open / import / reference するとnewシーンにしてもunkownプラグイン情報が残り続け、
関係ないデータを開いて保存すると、そのデータにもunkownプラグイン情報が書き込まれてしまう。
ウィルスがごとく感染していってしまう。

なので、見つけたら即消すのがお勧め。