OmniAICreator/Qiita-1.07M huggingface dataset:
AtomicIntegerでsyncronized

ValueをAtomicValueに差し替え
int numをAtomicInteger numに差し替え
AtomicInteger#addAndGet()を使うことにより
排他をしなくても読み替えから足しこみまでをatomicに行う

これは発生しない
1st thread num ref 
2nd thread num ref 
1st thread num + 100

こういったかんじ
1st thread num ref and +100
2nd thread num ref and +100

```java
class Value{
    int num;
    public void add(int num) {
        this.num += num;
    }
    public int get() {
        return num;
    }
}
class AtomicValue extends Value {
    AtomicInteger num = new AtomicInteger(0);
    @Override
    public void add(int num) {
        this.num.addAndGet(num);
        System.out.println("atomicvalue add method");
    }   
    public int get() {
        System.out.println("atomicvalue get method");
        return num.intValue();
    }
}
class Task implements Runnable {
    Value v;
    Task(Value v) {
        this.v = v;
    }
    @Override
    public void run() {
        this.v.add(100);
    }
}
public class Outer {
    public static void main(String[] args) {
        Value v = new AtomicValue();
        ExecutorService e = Executors.newFixedThreadPool(4);
        e.submit(new Task(v));
        e.submit(new Task(v));
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        System.out.println(v.get());
        e.shutdown();
    }
}
```
```
atomicvalue add method
atomicvalue add method
atomicvalue get method
200
```
【SKAdNetwork 計測】AppsflyerのNullコンバージョン値を使ってコンバージョンを推定する

## なに？

AppsflyerのNullコンバージョン値を使って、Appleのプライバシーしきい値によりマスキングされてしまったコンバージョンを推定してみます。

- [Appsflyer SKAN推定値](https://support.appsflyer.com/hc/ja/articles/7086372479505?query=null%E5%80%A4)

なお、Apple公式では「Null値」という表現はされておらず
プライバシーしきい値を満たしている場合のみ、コンバージョン値（`conversion-value`）が提供されると記載されています。

https://developer.apple.com/documentation/storekit/skadnetwork/identifying_the_parameters_in_install-validation_postbacks

## なぜ？
今までは、IDFAをベースにした推定モデルを使用していましたが、昨今データがどんどん減少していく中で精度が信頼できなくなってきた。

## コンバージョンの推定

SKAがレポートするインストールには

- **CV値が載っているポストバック**

と

- **載っていないポストバック**

があります。
Appsflyerでは、後者を「Nullコンバージョン値」と表現されています。

インストールの計測だけを行う場合は、Appleによるしきい値の影響を受けません。
よって、すべてがポストバックされので問題がありません。

しかし、CV値の方はAppleによりマスキングされてしまう場合があります。
つまりポストバックからCV値が取得出来ません。

そこで、実際に取得できたCV値を使って、このマスキングされてしまったCV値を推定してみます。

## 計算してみる

### 例）

- SKAで計測したインストール：100件
    
    取得出来たCV
    
    - 課金CV=0：25件（期間中課金しなかった）
    - 課金CV=1：10件（1,000円未満課金）
    - 課金CV=2：5件（1,000円以上課金）
- Nullコンバージョン率：60％

この時のコンバージョンを推定してみます。

まず、しきい値にかかってしまった件数を算出。

- **100件 × Nullコンバージョン率 60％ = 60件**

なので、CVが取得出来たインストールは

- **100件 - 60件 = 40件**

となります。

次に、この40件のCV内訳を計算します。

- **課金CV=0 → 25件 ÷ 40件  = 62.5%**
- **課金CV=1 → 10件 ÷ 40件 = 25％**
- **課金CV=2  → 5件 ÷ 40件 = 12.5％**

この内訳を元に

しきい値にかかってしまったCVを導出します。

推定課金CV件数

- **課金CV=0 → 60件 × 62.5% = 37.5件**
- **課金CV=1 → 60件 × 25% = 15件**
- **課金CV=2 → 60件 × 12.5% = 7.5件**

この推定CVと実測されたCVと合算すると

- 課金CV=0 → 37.5件 + 25件 = **62.5件**
- 課金CV=1 → 15件 + 10件 = **25件**
- 課金CV=2 → 7.5件 + 5件 = **12.5件**

となりました。

これは合算すると当然、100件になります。

## おわりに
今回はAppsflyerの例を挙げましたが、SKAdNetworkのポストバックが確認出来る環境であれば、どこでも使えると思います。

また、この計算で出したCV内訳はあくまで「推定」の域を出ません。
ただ、利用できる計測指標がますます限定されていく中で、有用な方法のひとつと感じました。

今後、SKAdNetwork4.0 がより浸透してくれば、また新たなソリューションが出てくるかも知れません。期待したいですね。
AWS RDSのインスタンス追加時にクラスターのタグを引継ぐ

# TODO
 * コンソール上、急ぎリーダーを追加すると、タグ登録漏れに気付かない。
 * 別途タグ未登録監視をしているが、できれば監視を減らしたい。

# 対策
 * LambdaでRDSのCreateイベントを拾い、タグ登録する

# Lambda
```python:lambda_handler Python3.9
import json
import boto3
from botocore import response

def lambda_handler(event, context):
    tagkey = "project" #必須タグ
    dBClusterIdentifier = event["detail"]["responseElements"]["dBClusterIdentifier"]
    dBInstanceArn = event["detail"]["responseElements"]["dBInstanceArn"]

    client = boto3.client('rds')
    response = client.describe_db_clusters(
        DBClusterIdentifier = dBClusterIdentifier
    )
    
    dBClusterArn = response['DBClusters'][0]['DBClusterArn']
    clst_tags = client.list_tags_for_resource(ResourceName = dBClusterArn)
    clst_tag_list = clst_tags['TagList']

    clst_tag = next(iter(filter(lambda tag: tag['Key'] == tagkey, clst_tag_list)), None)
    tagvalue = clst_tag['Value']

    instance_tags = client.list_tags_for_resource(ResourceName = dBInstanceArn)
    tag_list = instance_tags['TagList']
    tag = next(iter(filter(lambda tag: tag['Key'] == tagkey and (tag['Value'] is not None and tag['Value'] != ''), tag_list)), None)
    
    # すでに登録済みはスルー
    if tag is not None:
        print('The tag is already registered.')
        return

    response = client.add_tags_to_resource(
        ResourceName = dBInstanceArn,
        Tags=[{
            'Key': tagkey,
            'Value': tagvalue
        }]
    )
    print(response)

    return {
        'statusCode': 200,
        'body': json.dumps('done')
    }

```

# EventBridge (CloudWatch Events)
```yml
name: rds-create-instance
Service principal: events.amazonaws.com
url: events/home#/rules/rds-create-instance
イベントバス: default
イベントパターン:
{
  "source": [
    "aws.rds"
  ],
  "detail-type": [
    "AWS API Call via CloudTrail"
  ],
  "detail": {
    "eventSource": [
      "rds.amazonaws.com"
    ],
    "eventName": [
      "CreateDBInstance",
      "CreateDBInstanceReadReplica"
    ]
  }
}
```

# 参考
 * https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds.html#RDS.Client.describe_db_clusters
AWS ApiGateway APIタイプを選択で何を選択すればよいのか迷った

# 概要

- ApiGatewayで新たにAPIを登録しようとした時にAPIタイプの選択画面でどれを選べばよいか迷ったので簡単にまとめてみる。

# ApiGatewayのAPIタイプ

- ApiGatewayでは下記4種のAPIタイプを選択する事ができる。
    - HTTP API
    - WebSocket API
    - REST API
    - REST API（プライベート）

    ![API_Gateway_-_APIs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/3283377f-53df-dac4-2aab-60c6f7025587.png)

- AWS側も迷うことを想定してそれぞれ選択画面で「こんなAPIを提供したいならこれ！」という具合に説明は記載してくれている。しかしもうちょっと深い情報がほしいのでそれぞれ調べてみることにした。

# WebSocket API

- 順番が前後して申し訳ないが、まずはWebSocket APIをまとめてみる。
- 俗に言うWebSocketのAPIと同じ意味である。
- 対話的な通信を行うためのAPIを実装したい場合、こちらを選択する。

# HTTP API

- RESTful APIである。設定が基本的なものしか選べない。
    - エンドポイントタイプは「リージョン別」のみ選択可能
    - セキュリティー（悪意のあるアクセスからのブロック）は「相互TLS認証」のみ選択可能
    - 認証（APIのアクセス制限）は「IAM」「Amazon Cognito」「AWS Lambdaを使ったカスタム認証」「JWT」から選択可能
    - API管理は「カスタムドメイン」のみ選択可能
- などなど上記に記載したもの以外にもいくつかの設定項目で機能が限定されている。
- 使える機能が少ない分、すこし料金が割安らしい。

# REST API

- RESTful APIである。設定に自由度がある。
    - エンドポイントタイプは「リージョン別」「エッジ最適化」「プライベート」から選択可能
    - セキュリティー（悪意のあるアクセスからのブロック）は「相互TLS認証」「バックエンド認証用の証明書」「AWS WAF」から選択可能
    - 認証（APIのアクセス制限）は「IAM」「Amazon Cognito」「AWS Lambdaを使ったカスタム認証」「リソースポリシー」から選択可能
    - API管理は「カスタムドメイン」「APIキー」「クライアントごとのレート制限」「クライアントごとの使用量調整」から選択可能
- そのほかにも設定項目があり、各設定とも柔軟な設定が可能になっている。

# REST API（プライベート）

- こちらはREST APIの設定項目をそのままに設定したVPCからのみアクセス可能なAPIを作りたい場合に選択する。

# HTTP APIとREST APIで迷ったら

- 下記の参考文献のURL先を確認し、設定が限定されているHTTP APIの内容を見て、自身が提供したいAPIの仕様を満たせているならHTTP APIで良いと思う。
- 一つでも満たせていないならREST APIを選ばないといけない。
- しかし、実装途中で仕様が変わる可能性もあるのでREST APIを選択しておくことが無難だと思う。
- ただ、HTTP APIでしか選択できない設定項目も存在するので注意すること。

# 参考文献

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/http-api-vs-rest.html
Emacs 28のno window systemモード(-nw)で下線が大量に表示される問題への対処法

## TL;DR
- 問題: GNU Screen内でGNU Emacs 28でnwすると下線が沢山出現。
- 解決法: ``.screenrc`` に ``setenv COLORTERM ""`` を追加。

## 環境
- MacBook Pro (13-inch, M1, 2020)
- macOS Big Sur 11.7.2
- iTERM2 3.4.4
- GNU Screen 4.08.00
- GNU Emacs 28.1 or 28.2 (27.2は問題なし)
- Emacs呼び出し: ``emacs -nw # --no-window-system``

## 問題の現象

GNU Screen内で `emacs -nw` すると以下のようにイレギュラーな下線が入ってしまう。
![問題の現象](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133931/12d095ae-518b-87e8-ea76-304524fea803.png)
GNU Screen内で呼び出す場合だけが問題で、ターミナルから直接起動する場合は正常に動作。

参考: 正常な場合。
![正常時](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133931/8af04c8f-e45d-9161-4152-9af096a4cef9.png)


## 試行錯誤

1. brewでEmacs 28.2をインストール => 問題発生
1. 自分でコンパイルしたEmacs 27.2 => 正常に動作
1. 自分でコンパイルしたEmacs 28.1と28.2 => 問題発生

コンパイル時コマンド(GUIなし):

```shell
$ ./configure --prefix=$HOME/Src/ --without-pop --without-kerberos --without-sound --without-wide-int --without-xpm --without-jpeg --without-tiff --without-gif --without-png --without-rsvg --without-xml2 --without-imagemagick --without-xft --without-libotf --without-m17n-flt --without-xaw3d --without-xim --without-ns --without-gpm --without-dbus --without-gconf --without-gsettings --without-selinux --without-gnutls --without-x
$ make && make install
```


## 解決
以下の議論で解決策を発見。
https://www.reddit.com/r/emacs/comments/y9b8cd/emacs_running_under_screen_on_a_mac_going/

環境変数 ``COLORTERM`` の設定が問題らしい。
ちなみに自分の環境だと以下のような状態。

```shell
$ echo $TERM
xterm-256color # GNU Screenなし
$ echo $TERM
screen-bce # GNU Screenあり
$ echo COLORTERM
truecolor # GNU Screenの有無を問わず
```

記事の最後にあるように ``~/.screenrc`` に以下の設定をすると正常に動作する。

```shell
setenv COLORTERM ""
```

なお、OS付属のterminal.appだと ``COLORTERM`` は設定されていないので問題は発生しない。
記事にあるようにtmuxでも問題ないらしい。
GNU Screen + Emacsという組み合わせはそんなに珍しいのだろうか。
自然数ローマ数字変換 Python3


自然数とローマ数字の変換をします。

```romanumber.py
#!/usr/bin/python3
import sys

TABINT=[1000,900,500,400,100,90,50,40,10,9,5,4,1]
TABROMA=["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]
ERRPAT=['DD','LL','VV', # 500,50,5 がダブらないように
        'CMC','CDC','XCX','XLX','IXI','IVI',
                  #CMCM,CMCのようなエラーパターンは'CMC'にまとめてある
        'DCD','LXL','VIV'] # 515のパターン

def toint(s):
  s=s.upper()
  for i in ERRPAT:
    if (i in s): return(-1)
  a=0
  i=0
  j=0
  while(s):
    if (s.startswith(TABROMA[i])):
      j=j+1
      a+=TABINT[i]
      s=s.replace(TABROMA[i],'',1)
      if (j<3):
        continue
    j=0
    i+=1
    if (i==len(TABROMA)):
      break
  if (s): # IF ILLEGAL FORMAT
    return(-1)
  return(a)

def toroman(a):
  s=""
  i=0
  while(a!=0):
    while((a//TABINT[i])!=0):
      s+=TABROMA[i]
      a-=TABINT[i]
    i+=1
  return s

print("自然数を入力して下さい:",end='')
a=int(input())
if (a>=4000):
  print("too big")
  sys.exit(1)
print(toroman(a))
print("ローマ数字を入力して下さい:",end='')
s=input()
i=toint(s)
if (i==-1):
  print("Invalid Roman Number")
  sys.exit(1)
print(i)
```
【Python】Chamfer Distanceを実装した

# 概要
機械学習で生成した3Dモデルがターゲットの3Dモデルと比較してどれくらいの精度かを評価するために、「**Chamfer Distance**」が用いられることがあります。

そこで本記事では、Chamfer DistanceをPythonで実装する方法を記載しています。

# Chamfer Distanceとは

Chamfer Distanceは、２つの点群間の位置誤差を測る指標です。

点群$X$と点群$Y$間のChamfer Distanceを計算する式は以下のように定義されます。

```math
CD(X, Y)=\frac{1}{|X|}\sum_{x \in X}\min_{y \in Y}\|x-y\|_2^2+\frac{1}{|Y|}\sum_{y \in Y}\min_{x\in X}\|x-y\|^2_2
```

具体的な処理は以下のようになります。
1. 点群$X$内の点$x$と、点群$Y$の全ての点のユークリッド距離を算出し、２乗する。
1. 1.で求めた2乗ユークリッド距離の最小値を、加算する。
1. 加算した最小距離の平均を計算する。
1. 同様の処理を点群$Y$で行う（こちらの場合は点$y$と点群$X$の全ての点を比較する）。
1. 算出した点群$X$における最小距離と点群$Y$における最小距離を加算する。

# Pythonでの実装
今回はnumpyライブラリを用いて実装を行いました。
```python
def av_dist(array1, array2):
    """
    arguments:
        array1, array2: both size: (num_points, num_feature)
    returns:
        distances: size: (1,)
    """
    distances = np.sum(np.square(np.expand_dims(array1, axis=1) - np.expand_dims(array2, axis=0)), axis=-1)
    distances = np.min(distances, axis=1)
    distances = np.mean(distances)
    return distances

def chamfer_distance(pointsA, pointsB):
	"""Chamfer Distance評価指標

	Args:
		pointsA (np.array): 点群情報A
		pointsB (np.array): 点群情報B

	Returns:
		float: CD値
	"""
    dist_A = av_dist(pointsA, pointsB)
    dist_B = av_dist(pointsB, pointsA) 
    return dist_A + dist_B
```

# おわり
実装が誤っている点があればご指摘いただけますと幸いです。

# 参考サイト
https://github.com/UM-ARM-Lab/Chamfer-Distance-API

https://pdal.io/en/stable/apps/chamfer.html
【完全自分用メモ】コードレビューを依頼する前に見直した方が良いポイント（Java編）

# この記事の目的
完全に自分用です。
Javaで実装したプログラムのコードレビューで指摘されたことがあるポイントをまとめて、定期的に見返すことで再指摘されないように気を付ける！（新たな指摘があるごとに増やすかも）

### String.equalsメソッドで比較するとき
定数と比較する場合は定数に対してequalsメソッドを実行するようにする。
定数の中身は明示されていると思うので、ヌルポで落ちるなどが減る。
`定数.equals(変数)`

### 単純に文字列結合をする
単純に文字列結合をする場合はStringBufferではなく、StringBuilderを使用する。
↓の記事が参考になる
https://qiita.com/gksdyd88/items/d3873600829337bebedd

### 区切り文字で文字列を結合する
以下のいずれかかを使用することで実現可能。
目的や環境によりどれかを使用するかは考える。
- StringJoiner　※Java8から使用可
- String.join()　※Java8から使用可
- StringUtils.join()　※Apache Commons Langライブラリが必要

### Listの宣言①
右辺の型は宣言不要です。
ここを削ることで多少なりとも調査時のGREPで無駄にヒットする箇所が減少することが見込める。
`List<String> hoge= new ArrayList<>();`

### Listの宣言②
リスト宣言時にコンストラクタで容量を指定する。
addする際に要素数がcapacityを超えるとcapacityを1.5倍してバッファの割り当てが行われるため、予め要素数がわかっている場合は容量の指定を行う。
`List<String> hoge = new ArrayList<>(fuga.size());`
https://docs.oracle.com/javase/jp/8/docs/api/java/util/ArrayList.html

### フォーマッタやcheckstyleを適用する
見出し通り。意外と忘れがち。

### マジックナンバーを作っていないか？
コード中にマジックナンバーを作ってしまうと他の人が見たときや自分自身で見返した際にも「この数字 is 何？」となるので定数化を行う。
↓こんなコードは書かない。
`hogeLogic.getFuga(id, 10);`

### javadocコメントを書く
以下にはjavadocコメントを書くようにする。
特にメソッドと定数は何をする（表す）かがフォーカスするだけでわかるようになるの非常に便利。
* クラス
* メソッド
* 定数
【発展版】PySimpleGUIで簡易アプリのメニュー画面を作る

## 結論
作成したレイアウトはsg.Col(layout)を利用してまとめることが出来る。


# 前回はPysimpleGUIで簡易アプリを作成した。

しかしながらこのままでは単純なGUI操作しか行えない。
入力してスタートみたいなことしか行えない。
これをちょっと発展させる。

下は前回作成したGUIのレイアウトである。
```
import PySimpleGUI as sg

layout1=[
 
            [sg.Text('検索キーワード',font=100)],

            [sg.In(key='word')],
                
  
            [sg.Text('保存先ファイルを選択(ファイルのアドレスを記入)',font=60)],
                 

            [sg.InputText(),sg.FolderBrowse(key="folder",size=(10,5))],
                 

            [sg.Button('スタート',font=50,size=(15,3),pad=(100,10))], 
            [sg.Button('終了',font=50,size=(15,3),pad=(100,10))]
        
        ]
```
例えば上のプログラムだけだと、スタートボタンを押した後、実行が終わったかどうかわかりにくい。
pyinstallerとかでexe化したときに分かりづらくなってしまうので少しプログラムを変更してみる。


## GUIのレイアウト表示を発展させるsg.Col()
pysimpleguiのCol()を使用すると、レイアウトをまとめられます。


試しにここでlayout2を作成してみる。これはターミナル上での出力を表示させる形式にしている。
```
layout2 =[
          #size(retu gyou)
          [sg.Text('ターミナル出力',font=100)],
          [sg.Output(size=(40,20))]   
     ]
```

これをまとめると、、
```
 #まとめる
layoutt=[[sg.Col(layout1),sg.Col(layout2)],]
```
こうなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079535/c904aa09-389c-40e1-0d4d-122dbaf61b7f.png)

あくまで型枠だけ作成したが、実際にプログラムを作成したとき、右のターミナル出力に出力結果を出すこともできる。

ちなみに縦にしたいときはこう。指定した行列にあてはめられる。
```
layoutt=[[sg.Col(layout1)]
         ,[sg.Col(layout2)]]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079535/d6c9d2e7-fa96-409c-0709-287b3aaef4b5.png)


layoutt=[sg.Col(layout1),sg.Col(layout2)]
こうするとエラーになるので注意。



## それっぽくすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079535/58232000-3aca-1e8b-938f-4ad63443fdb1.png)


```
layoutt=[[sg.Col(layout1),sg.Col(layout2)],
          [sg.Col(layout3),sg.Col(layout4)]
          ]
```
こんな感じで作成できる。
後は作成したいように公式見ながらやると勉強になる。
https://www.pysimplegui.org/en/latest/call%20reference/

次回はpyautoguiで遊ぶ
unittestの使い方について個人的メモ

# tl;dr;
* unittestはPythonが公式に用意しているユニットテストフレームワーク
* 初めてテストを使ったが、大規模なコードになればなるほどテストが重要だと思うので、今後は、並行してテストを書いていくようにしたい。
* testを先に書いてから開発をする手法もあるらしい　DRR？
* テストはテストするmoduleとディレクトリを分ける
* argumentを渡すようにすることで、argparaseをテストすることもできる

official ref.
https://docs.python.org/3/library/unittest.html


# Things learned
#### 1. test moduleの場所について
unittestはテストしたいmodule内に直接記載するケースもあるが分けるケースが多い。それは以下のような理由からである。(公式Ref抜粋)
そのため今回はtestsフォルダを直下に作り,そこにtest.pyを作成した
> * The test module can be run standalone from the command line.
> * The test code can more easily be separated from shipped code.
> * There is less temptation to change test code to fit the code it tests without a good reason.
> * Test code should be modified much less frequently than the code it tests.
> * Tested code can be refactored more easily.
> * Tests for modules written in C must be in separate modules anyway, so why not be consistent?
> * If the testing strategy changes, there is no need to change the source code.

#### 2. pathについて
上記のようにテストしたいmoduleと異なる階層(1つ子階層)に`tests/tet.py`としたため, moduleをimportするのに一工夫必要。通常`import`は同階層、およびglobal moduleのみを検索するため、階層が異なる場合は、検索する場所を`path`, `os`を使って指定する必要がある。今回は以下のようにした。
```python
import os, sys, unittest

root_folder = os.path.abspath(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(root_folder)
```
中身を見てみると
`os.path.abspath(__file__)` はこのmoduleのabspathを示す。
`os.path.dirname(os.path.abspath(__file__))` はmoduleのあるディレクトリ名
`os.path.dirname(os.path.dirname(os.path.abspath(__file__)))`はさらに一つ親階層

で、`sys`に渡すことで、`root_folder` 階層を検索することができる。

#### 3. subTest
関数内で`if - else`文などを用いている場合、各条件についてテストをしたかったりする。一つ一つ条件を直接指定してテストすることも可能だが、`subTest`を使うと、テスト内で`for`ループを使うことができる。かつ、この場合、ループ内でテストが`Failed`となっても、他の場合をテストし続けることができる。
```python
def test_sort_option_is_valid(self):
    for i in range(1, 5):
        with self.subTest(i=i):
            self.assertIn(SortType(i), SortType)
```

### 4. argsのテスト
CLI, argumentsを利用するアプリケーションの場合、argumentsにて正しいデータが取得できているかをテストしたい。その場合は、argsにargumentsを渡すようにしてやることで、テストできる。

```python main.py
def main():
    args = get_args(sys.argv[1:])
```
```python arg_parse.py
def get_args(args):
    parser = argparse.ArgumentParser(description='Sort some integers.')
    parser.add_argument( ...
```
```python test.py
def test_parser_input_file(self):
    args = get_args(['-i', './tests/test_input.txt'])
    self.assertEqual(args.input.name, './tests/test_input.txt')
```
これにて取得しているargsが意図したものかをテストすることができる。
プロキシ経由でインターネットには出れるけどWindowsUpdateができない場合

プロキシを使っている環境で、日本語化ができなかったりWindows Updateができない場合の対処方法について。

Windowsの[設定]画面でプロキシの設定をするだけではWindows Updateができない！
そんな場合、コマンドプロンプトで以下を実行すると解決した。

```
# 設定
netsh winhttp set proxy <プロキシサーバのIP>:<ポート>

# 設定確認
netsh winhttp show proxy
# 設定削除
netsh winhttp reset proxy
```
時系列データ分析①　～時系列データと基本統計量～

# はじめに
久しぶりの投稿になります。
最近時系列データ解析に興味が出てきて、いくつか書籍を読んでみたので、復習も兼ねてまとめていきます。
予定としては、定常性などの基礎的な概念のまとめから、ARIMAモデルや状態空間モデルなどの数理モデルについてのまとめまで、網羅的にやっていけたら、と思っています。
可能な限りPythonでのシミュレーションも交えられたらいいな。

今回は、「時系列データと基本統計量について」です。

## 時系列データとは
時系列データとはどのようなものなのか。
沖本(2010)によれば、『時間の推移とともに観測されるデータのことであり、観測される順序に意味がある』データだと定義されている。
例えば、日経株価指数だとか、国内総生産だとか、毎日の最高気温だとか、例はいくつでも挙げられる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969543/4b13739f-219f-58ac-1b2c-b88e58e40f16.png)

時系列データ分析の目的は、このように順序的に観測されたデータの多様な特徴を分析し、それらを記述できるモデルを構築することである。

## 基本統計量
- 平均・分散
時系列データは各時点で観測された値の集合であり、時点１からTまでのデータが観測されたとすると、$\lbrace y_t\rbrace^T_{t=1}$と表記される場合が多い。
時点Tを固定して考えると、それぞれの時点での$y_t$は確率変数として扱うことができ、期待値や分散を計算することができる。それぞれ以下の通りである。
$$E\lbrack y_t\rbrack=\mu_t\$$ $$V\lbrack y_t\rbrack=E\lbrack (y_t-\mu_t)^2\rbrack$$
分散の平方根は**標準偏差**と呼ばれ、経済の分野では**ボラティリティ**と呼ぶことが多い。

- **自己共分散・自己相関係数**
時系列データ特有の基本統計量として、<font color='red'>自己共分散</font>、<font color='red'>自己相関係</font>がある。
自己共分散：ある時点 $t$と異なる時点 $k$における共分散
自己相関係数：自己共分散を正規化したもの
$k$次の自己共分散と自己相関係数を数式として表すと、以下のようである。$$\gamma_{kt}=Cov[y_t,t_{t-k}]=E[(y_t-\mu_t)(y_{t-k}-\mu_{t-k})]$$ $$\rho_{kt}=Corr[y_t,y_{t-h}]=\frac{Cov[y_t,y_{t-k}]}{\sqrt{V[y_t]V[y_{t-h}]}}=\frac{\gamma_{kt}}{\sqrt{\gamma_{0t}\gamma_{0,t-k}}}$$
解釈はテーブルデータの共分散、相関係数と同じである。
例えば、３次の自己共分散が正のとき、時点tの値$y_t$が期待値よりも大きければ、３時点離れた$y_{t-3}$の値も期待値よりも大きい傾向にある、という事である。
テーブルデータと同じく、自己共分散は単位に依存した値であるため、正規化した自己相関係数を用いることで、変数間での値の比較等することが可能となる。
　　
自己相関係数について、$k$の関数としてみたとき、**自己相関関数**と呼び、$k$を横軸に、自己相関係数を縦軸にプロットしたグラフのことを<font color='red'>コレログラム</font>という。　　　
　　
＜コレログラムの例＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969543/1844c45d-68d7-edbe-903a-192ecaf93d67.png)

## まとめ
- 時系列データとは、時間的順序を持ったデータのことである
- 時間$t$を固定すればそれぞれの時点$t$の実現値は確率変数とみなすことができ、期待値や分散が計算できる
- 時系列データ固有の統計量として、自己共分散や自己相関係数があるが、解釈はテーブルデータの場合となんら変わりはない

以上、今回の投稿のまとめとしますが、時系列データの統計量を計算する上では、大きな問題が存在していることにお気づきでしょうか。
　　
<ins>ある時点$t$での実現値$y_t$は一度しか観測されない</ins>のです。
　　
2023年1月23日の最高気温が、2つも3つも観測されるなんてことはないはずです。
一度しか観測できないデータの期待値や分散など、どうやって計算するのでしょうか。
　　
　　
それは、得られた時系列データに何かしらの構造や性質を仮定することにより解決します。
次回の投稿では、その『何かしらの構造や性質』について言及していきます。

### 参考文献
沖本竜義（2010） -経済・ファイナンスデータの計量時系列分析
日本統計学会　-統計学実践ワークブック（統計検定準1級対応）
helperを作る際の注意点

## 環境
Rails 5.2

## はじめに
**helper**を作る際の注意点について書いてみました。

helperは、大元的な役割をする、**application_helper.rb**以外に、各コントローラごとのhelperが存在します。例えば、**session**と**user**の２つのコントローラを作れば、**sessions_helper.rb**と、**users_helper.rb**のヘルパーがそれぞれ自動で生成されます。

**views/sessionsフォルダ**配下にある、各**Viewファイル**から呼び出して使うhelperを作る場合は、**sessions_helper.rb**に記述します。そして、**views/usersフォルダ**配下にある、各**Viewファイル**から呼び出して使うhelperを作る場合は、**users_helper.rb**に記述します。

しかし、**sessions_helper.rb**に記述したヘルパーメソッドを、**views/usersフォルダ**配下にある、**Viewファイル**から呼び出すことができるようになっています。逆に、**users_helper.rb**に記述したヘルパーメソッドを、**views/sessionsフォルダ**配下にある、**Viewファイル**から呼び出すこともできるようになっています。

*これはこれで問題はないのですが、このような状態になっていれば、後々、混乱の元になりそうです。*

**sessions_helper.rb**に記述したヘルパーメソッドは、**views/sessionsフォルダ**配下にある、Viewファイルからのみ呼び出せるようにし、それ以外のViewファイルからは、呼び出せないようにしておいた方が、整理されたコーディングができそうです。

それを実現できるようにするには、下記の設定が必要です。この設定はデフォルトでは設定されていないため、１行追加する必要があります。

下記の１行を追加すると、**sessions_helper.rb**に記述したヘルパーメソッドは、**views/sessionsフォルダ**配下にある、**Viewファイル**以外からは呼び出せないようになります。呼び出そうとすればエラーになります。
```config/application.rb
config.action_controller.include_all_helpers = false
```

上記の１行を追加しても、**sessions_helper.rb**に記述するヘルパーメソッドを、**application_helper.rb**に転記すれば、**views/sessionsフォルダ**配下の**Viewファイル**以外からでも呼び出せるようになります。転記することなく、下記のようにincludeすれば、共通で呼び出すことができるようになります。
```application_helper.rb
module ApplicationHelper
    include Master::UsersHelper
    include Master::SessionsHelper
end
```

## コントローラのメソッドをヘルパーメソッドにする

**View**から呼び出すヘルパーメソッドは、**controllers/helpers**配下の、Viewのフォルダ名に対応したヘルパーファイルに作成するのがセオリーでした。しかし、コントローラーに記述したメソッドを、ヘルパーメソッドにして、**View**で呼び出すこともできます。例えば、下記のようなやり方です。つまり、**helper_method :メソッド名**を宣言すればいいだけで、ヘルパーメソッドにすることができます。
```application_controller.rb
class ApplicationController < ActionController::Base

    helper_method :current_user

    private

    def current_user
        @current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]
    end  
end
```

## 結論
ヘルパーメソッドは、**helpersフォルダ**内の、**xxx_helper.rbファイル**に記述する場合と、コントローラに**helper_method**を定義する方法の２通りの呼び出し方があることになります。

どっちを使うべきか悩むところですが、**View**からしか呼び出さない場合は、**xxx_helper.rbファイル**に記述し、Viewとコントローラと双方から呼び出す場合は、**helper_method**を定義するといった使い訳になりそうです。
dead lock of thread

1st thread b1.deposit() lock b1
2nd thread b2.deposit() lock b2 
この状態で処理を進めると
1st thread b2.deposit() cannot update b2 because 2nd locked b2
2nd thread b1.deposit() cannot update b1 because 1st locked b1

```java
class Bank {
    int amount;
    void deposit() {
        amount++;
    }
    void withdrawal() {
        amount--;
    }
}
public class Outer {
    public static void main(String[] args) {
        ExecutorService e = Executors.newFixedThreadPool(10);
        Bank b1 = new Bank();
        Bank b2 = new Bank();
        e.submit(() -> {
            try {
                Thread.sleep(100);
                synchronized(b1) {
                    b1.deposit();
                    synchronized(b2) {
                        b2.deposit();
                    }
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(Outer.class.getName()).log(Level.SEVERE, null, ex);
            }
        });
        e.submit(() -> {
            try {
                Thread.sleep(100);
                synchronized(b2) {
                    b2.deposit();
                    synchronized(b1) {
                        b1.deposit();
                    }
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(Outer.class.getName()).log(Level.SEVERE, null, ex);
            }
        });
        e.shutdown();
        int i;
        int j=0;
        while(true){
            i = Thread.activeCount();
            System.out.println("active count:" + i);
            j++;
            try {
                Thread.sleep(j * 1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(Outer.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (i==0|j>5) break;
        }
    }
}
```
current thread
1st thread
2st thread
count:3

```
active count:3
active count:3
active count:3
active count:3
active count:3
active count:3
```
マッチング処理（突合せ処理）

# マッチング処理
```複数のファイルからデータを入力```して（ファイルの先頭から順に読み込む)、```関連のある情報を取り出す```処理のこと

複数のファイルに存在する関連のある情報を効率よく取り出すには、入力するファイルのレコードが```同じキー項目の順に整列されていることが前提```になっています。

# 出典
https://gihyo.jp/book/2022/978-4-297-12377-2

# 関連記事
https://www.cobol.co.jp/cobol-nyuumon/ouyou/

# 感想
短いけど、
これ以外書くことがなかった。
まだ勉強だ。
Databricks Certified Associate Developer for Apache Spark 合格体験記

Databricksが提供する資格の1つである「Databricks Certified Associate Developer for Apache Spark」を取得したので、内容や対策、受けてみた感想等について共有します。

# Databricks Certified Associate Developer for Apache Spark とは
<div align="center">
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986340/57a2dffb-f126-c6e5-7a73-efee65f8719b.png">
</div>

公式サイトの説明を翻訳すると、以下のような資格として位置付けられています。
> Databricks Certified Associate Developer for Apache Spark 認定試験では、Spark DataFrame API の理解と、Spark DataFrame API を適用して Spark セッション内で基本的なデータ操作タスクを完了する能力を評価します。これらのタスクには、列の選択、名前変更、および操作が含まれます。行のフィルタリング、削除、並べ替え、および集計。欠落データの処理;スキーマを使用して DataFrame を結合、読み取り、書き込み、および分割する。 UDF と Spark SQL 関数を操作します。さらに、この試験では、実行/展開モード、実行階層、フォールト トレランス、ガベージ コレクション、ブロードキャストなど、Spark アーキテクチャの基本を評価します。この認定試験に合格した個人は、Python または Scala を使用して基本的な Spark DataFrame タスクを完了することが期待できます。

上記の説明から、Spark DataFrameの操作を中心的としながら、SparkのアーキテクチャやUDF, Spark SQLについても基本的な知識を備えている人に与える資格、ということになりそうです。

# 最低限必要な知識
こちらも公式サイトで以下のように記載されております。(翻訳)

- Sparkのアーキテクチャについての基本的な理解(Adaptive Query Executionも含む) 
- 以下のような個々のデータ操作を、Spark DataFrame APIを使って完了できること
    - カラムの選択、カラムの名称変更や各種操作
    - フィルタリング、ドロップ、ソート、行の集約、結合、読み込み/書き出し、パーティショニング、UDFやSpark SQL関数の操作

# 試験形態
試験方法について
- GCPの資格等と同じ、KRYTERIONのプラットフォームを使ったオンライン試験。ただしテストセンター受験はありません。
- 120分で60問に回答します。
- 問題は全て選択式、記述式やコードを書く問題等はありません。
- 受験を申し込む際に、プログラミング言語としてPythonを使用する試験とScalaを使用する試験が別々に用意されています。私はPython版で受験しました。
- 公式リファレンスをPDFにしたものが試験中に参照できるようになっています。Spark 3.0を前提としているので、現行の最新のリファレンスではなく、若干古いものでした。後で探した感じでは、おそらく下記のバージョンだったと思います。
https://spark.apache.org/docs/3.0.0/api/python/pyspark.html

# 問題についての所感
- 公式の説明の通りですが、全体としてはPysparkの関数やDataframeのメソッドに関するコードの問題がかなり多かったです。また、引数の渡し方等、結構細かい部分を問う問題も多いです。こうした問題については、試験中に参照できる公式リファレンスで探して答えに辿り着くことも可能です。ただし、文字列の検索等が出来ず、正直言ってかなり探しにくいので、全てをリファレンスで探していると時間が足りなくなると思いました。ある程度は頭の中に入れておく必要があります。
- アーキテクチャ関連では、Driver, Executer, Workerの概念や役割、Job, Stage, Task等の処理単位について基本的な理解を問われました。また、遅延評価についても理解しておく必要があります。
- シャッフルに関する問題も結構あったなという印象です。どのような操作をするとシャッフルが発生するか、あるいはシャッフルが発生させずできる処理はどれか、といった問われ方をしました。
- 一方、Structured StreamingやAQE(Adaptive Query Execution)についてはあまり出なかったような気がします。。。

# 何を使って勉強するか
個人的には以下の書籍「Learning Spark」が一番良いと思いました。Sparkに関しては古い書籍が多い中、Spark 3系に対応している数少ない書籍の1つです。また、内容としては基礎的な部分は網羅されていると思います。日本語版は無いのが少し辛いところですが、かなり読みやすい英語で書かれています。

https://www.amazon.co.jp/Learning-Spark-Jules-Damji/dp/1492050040/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=1674453743&sr=8-1

上の書籍を読みながら、適当なデータセットを題材にしてSparkを使ったデータ処理を実装してみるのが良いです。

# 感想 : Sparkの理解を試すのに最高の試験
Databricksの資格ではあるものの、Databricksの製品に特化した内容は一切出ません。純粋なSparkに関する問題のみなので、たとえDatabricksを使っていない方であっても、Sparkの知識をつけたい方にとてもオススメな試験だと思いました。この試験を意識しながら、上の書籍「Learning Spark」を読んで対策すると、Sparkの基本的なコードはある程度自信を持って書けるようになると思います。
久しぶりにSagemakerStudio起動しようとしたらできなかった話

## 起こったこと
久しぶりにドメイン内に新規ユーザープロファイル作成してsagemaker studioを起動しようとしたら以下のエラー画面が表示されハマったのでメモ。
![スクリーンショット_2023-01-23_15_10_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192406/bb1efa03-79c7-45b4-3d17-3d77a22b376f.png)

## なぜ起動できなかったか

エラーメッセージを見ていると「LifecycleConfig」「install-autoshutdoqn-extension」という単語が見つかりました。ライフサイクル...？となって確認すると、ドメインのライフサイクル設定に「install-autoshutdoqn-extension」がデフォルトで設定されていました。
(会社環境なので他メンバーが設定してくれていた模様)
コスト対策で一定時間経過したら自動でシャットダウンしてくれるスクリプトを仕込んでくれていました。
くわしくCloudWacth logsを確認すると該当のライフサイクルのシェルの処理でコケていました。
(ログはロググループ`/aws/sagemaker/studio`内のログストリーム`ドメインID/ユーザープロファイル名/JupyterServer/default/LifecycleConfigOnStart`で確認することができました。)

![スクリーンショット 2023-01-23 15.11.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192406/3479be48-9c17-5edb-9cfc-87d40797a4a6.png)

このシェルは[AWSのサンプルコード](https://github.com/aws-samples/sagemaker-studio-lifecycle-config-examples/blob/main/scripts/install-autoshutdown-server-extension/on-jupyter-server-start.sh)の内容を参照しているのですが
調べているとどうやらこのライフサイクルを設定した当時はJupyter Lab1.0向けのシェル内容だったようです。現在Jupyter Labは3.0を使用しておりそれが原因で起動に失敗していました。
現在のサンプルコードはJupyter Lab1.0, 3.0の両方に対応しているようです。
ライフサイクルのスクリプトを修正することで解決できました。
visxでグラフィカルにデータを描画してみよう(折れ線グラフ編)

visixというライブラリをご存知でしょうか。

d3.jsをReact用に最適化されたAirbnbによってメンテナンスされているOSSプロジェクトです。

かつて私はd3.jsを少しだけ使っていたので、現在実装しているReactのプロダクトでもd3.jsを採用しようとしていたが、どうも[相性が悪いらしい](https://qiita.com/ganezasan/items/e1c51b3e936bb0011680)。というわけで調べているとちょうどv3.0がリリースされたばかりの[visx](https://airbnb.io/visx/)というパッケージを見つけました。

## 表現豊かなビジュアライズ
ギャラリーページを見てみるとさまざまな描画例を見れます。基本的な折れ線グラフ、棒グラフ、円グラフ以外にもネットワークグラフなども対応しているみたいです。

https://airbnb.io/visx/gallery

## 折れ線グラフを使ってみる
というわけで今回は最も基本的なデータ表現である折れ線グラフを描画してみます。

CodeSandboxにサンプルコードを置いてます。

https://codesandbox.io/embed/example-of-linechart-c5d3o7?fontsize=14&hidenavigation=1&theme=dark

ポイントは、縦軸と横軸、グリッド、頂点のドットがそれぞれが独立したコンポーネントであるということです。

ドキュメントには記載のないPropsもたくさんあるので、ソースコードを潜ってみるとよりカスタマイズするヒントが見つかることがあります。

## モーダルやダイアログ上ではTooltipが裏に隠れてしまう場合がある
そんなときはz-indexを調整してあげましょう。

僕は[MUI](https://github.com/mui/material-ui)を使っているので、下記のように対処しました。

https://github.com/airbnb/visx/discussions/1634#discussioncomment-4752926

先の開発では、円グラフや積み上げ棒グラフなども実装する予定なので、もう少しいじっていきます。
PHPで陳素数を求める

# はじめに
この記事では、陳素数をPHPで求める方法について触れています。
とある面談で「陳素数をPHPで求めてください」とお題があり、行き詰まったのがきっかけで記事を書いています。
別言語でも基本的なロジックは変わらないはずですので、カスタマイズしてもらえれば良いかと思います。

# 陳素数とは
[wikipedia](https://ja.wikipedia.org/wiki/%E9%99%B3%E7%B4%A0%E6%95%B0)より引用
>素数 p が陳素数（ちんそすう、Chen prime）であるとは、p + 2 が素数または2つの素数の積（=半素数）であることを意味する。例えば 19 は素数であり、2 を加えた 21 は 3 × 7 と2素数の積で表されるので陳素数である。この名前は、そのような素数は無限に存在すると証明した陳景潤による。
>陳素数を小さい順に列記すると次の通り。
>2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 47, 53, 59, 67, 71, 83, 89, 101, … 

つまり、陳素数(ここではpとする)とはp+2が素数または半素数(2つの素数の積)に該当するものを指します。

説明だけだとイメージがわかないため具体例をいくつか提示していきます。
2 → 2+2=4は半素数(4=2×2)なので、2は陳素数
3 → 3+2=5は素数なので、3は陳素数
5 → 5+2=7は素数なので、5は陳素数
7 → 7+2=9は半素数(9=3×3)なので、7は陳素数
・・・・・こんなイメージです。

「素数だけど陳素数ではない数」も例を提示します。
43 → 43+2=45は素数ではない、かつ半素数でもない(45=5×3×3)ので陳素数に該当しません

具体例を提示してイメージが湧いたところで、実装内容を紹介していきます。

# PHPで実装
1〜100までで陳素数である数字を表示するプログラムを書いてみました

```php
public function index()
{
    $sosu_list = $this->getSosu();
    // 陳素数かどうかの判定
    foreach ($sosu_list as $num) {
        // num+2が素数であるかどうか
        if (in_array(($num + 2), $sosu_list)) {
            echo $num . "\n";
            // num+2が半素数であるかどうか
        } elseif ($this->checkHansosu($num + 2, $sosu_list)) {
            echo $num . "\n";
        }
    }
}

private function getSosu()
{
    $sosu_list = [];
    $target_num = 100;
    for ($i = 1; $i <= $target_num + 2; $i++) {
        $point = 0;
        for ($j = 1; $j <= $i; $j++) {
            if ($i % $j == 0) {
                $point += 1;
            }
        }

        if ($point == 2) {
          $sosu_list[] = $i;
        }
    }
    return $sosu_list;
}

private function checkHansosu($num, $sosu_list)
{
    foreach ($sosu_list as $v1) {
        foreach ($sosu_list as $v2) {
            if ($v1 * $v2 === $num) {
                return true;
            }
        }
    }
    return false;
}
```


プログラムの出力結果
```
2 3 5 7 11 13 17 19 23 29 31 37 41 47 53 59 67 71 83 89
```

# 参考
[【素数or半素数】陳素数とは｜SOSU Lover (Number Mania)｜note](https://note.com/sosu0131/n/n82b9e0128b71)
【Python】マルコフ連鎖で東京事変風の歌詞を生成してみた

# きっかけ
最近はAIが書いたものと人が書いた文書の見分けがつかないくらい、精度が上がっていますね！
その技術を応用すれば、歌詞生成などクリエイティブなこともできるのでは・・・？と思い、
大好きな東京事変の歌詞を学習させて新しく歌詞を生成してみました。

# 環境
Google colabを使用しています。

# 歌詞のスクレイピング
スクレイピングについてはこちらの記事でまとめていますので、よかったらご覧ください。東京事変の全歌詞101曲を収集しています。
【Python】椎名林檎と東京事変の歌詞の意味をテキストマイニングでひも解いてみた
https://qiita.com/harunan0913/items/8f8f713b0a51f4b010bd

# 文書生成のメカニズム
どんな原理で文書生成できるのか自分で説明できる自信がなかったため、chatGPTに聞いてみました。
![文書生成メカニズム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874461/1a10df32-6cff-1048-9fa7-7680e113ff81.png)

なんとなく分かったような・・・分からなかったような。
文書生成のコードについては下記ページを参考にしました。
https://axross-recipe.com/recipes/240

# 前準備
まずはモデル化する前に、集めてきたデータをクレンジングしデータを整形します。
```Python
#形態素解析を行なう janome と、マルコフ連鎖を用いるための markovifyをインストール
!pip install janome
!pip install markovify
```

続いて必要なライブラリをインポートします。
```Python
#必要なライブラリをインポート
from janome.tokenizer import Tokenizer
import markovify
```

次に、janomeで分かち書きし、単語ごとに半角スペースで区切り、文末は改行します。
```Python
def text_cleansing(text):
    # 改行、スペース、問題を起こす文字の置換
    table = str.maketrans({
        '。': '.',
        '\n': '',
        '\r': '',
        '…': '',
        '、': '',
        '々': '',
        '「': '',
        '」': '.',
        '(': '（',
        ')': '）',
        '[': '［',
        ']': '］',
        '"': '”',
        "'": "’",
    })
    text = text.translate(table)
    print(text)
    t = Tokenizer()
    result = t.tokenize(text, wakati=True)
    result = list(result)
    # 1単語毎に間に半角スペース、文末には改行を挿入
    splitted_text = ""
    for i in range(len(result)):
        splitted_text += result[i]
        if result[i] != '。' and result[i] != '！' and result[i] != '？':
            splitted_text += ' '
        else:
            splitted_text += '\n'
    return splitted_text


with open('学習させたい歌詞ファイル', mode='r', encoding='UTF-8') as f:
    text = f.read()

# テキストを単語毎に分割して記号を除去
splitted_text = text_cleansing(text)
```
# モデル作成

次に歌詞を生成させます。今回使用したのは2階マルコフ連鎖といわれ、ある単語の直前の2単語までを読み取るため、より自然な文章が生成されます。試行回数は100回としています。

```Python
# データセットの量が不足していると確率でnoneが返ってくるので、生成結果が返るまでループさせる
sentence = None
while sentence == None:
    # モデル生成
    text_model = markovify.NewlineText(splitted_text, state_size=2,well_formed=False)
    # モデルから文章を生成
    sentence = text_model.make_sentence(tries=100)

print(sentence.replace(' ', ''))
with open('生成した歌詞.txt', mode='a') as f:
    f.write(sentence.replace(' ', ''))
```
```:出力結果
果てしのない拍手やめていやだよ
追つては平穏なる感度を奪うわ
あなたの鏡だもの.とびきり美しい美しい美しい.
ねえ教えて既存の地図は交差点を描いて
鮮やかに広がっていく水面にて
言葉も忘れ苦悩しようもんか知りたいあらがえない
泳いでいこう.とか言われたくはない
油断なさいお忘れなさい繰り返すのが苦手なら
今度急に世界が真っ白け朝もや照らして
寝がえり三度で強盗をします
```

おお～！なんか、東京事変っぽいのではないでしょうか！？
思ったより簡単に歌詞が生成できました。
私が調べた限りでは、AIが作成した歌詞は著作権などひっかからないようですが、
間違っていましたらご指摘頂けたら幸いです。
楽天GORA APIを用いてOracle APEX上にデータを持ち込む方法

## はじめに
楽天APIを使用してOracle APEX上にデータを持ち込みました。その方法をスクリーンショット付きで紹介します。



#### ↓このように楽天が公開しているデータを見ることができます
![スクリーンショット (345).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/01757fa0-2338-e0a5-54f1-75a064e33e66.png)

## 方法
楽天のページで新しく作成するアプリに関しての登録を行います。

https://webservice.rakuten.co.jp/app/create

![スクリーンショット (348).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/64dbb43a-1550-8f4a-8b97-7527fef790e5.png)

以下のようにApplication IDやAffiliate IDを作成することができました。
![スクリーンショット (349).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/04098c51-b776-c9a0-637a-60fc3e03efe7.jpeg)

次に以下のページでURLの作成を行います。
先程のApplication IDとaffiliate IDを入力し忘れないように注意してください


https://webservice.rakuten.co.jp/explorer/api/Gora/GoraGolfCourseSearch


![スクリーンショット (350).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/830eeffd-c7c8-fa0e-5f23-4a252f920961.png)


上ページのURLの部分をすべてコピーしてメモ等に保存してください
その後、APEXの画面に移動します

共有コンポーネントに移動します

![スクリーンショット (351).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/65a45380-0c55-1beb-4fef-7b0ec8d29d88.png)

Rest Data Sourcesの中のRest Data Sourcesを選択します

![スクリーンショット (352).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/4cbbfbf5-2e11-acde-9846-dfe9f07ce3ab.png)

Createを選択します

![スクリーンショット (354).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/8ab8937b-7e00-ff6f-a5e4-8ba7391a1a67.jpeg)




先程、保存しておいたURLをURL Endpointに入力します


![スクリーンショット (341).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/d534117f-fc03-1947-902c-4b0f6e45bb26.png)

そのままNEXTで進んでいきます

![スクリーンショット (342).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/a2c158ee-6b98-3cae-d489-421f6e64bd7b.jpeg)

![スクリーンショット (343).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/23346acc-08be-7511-740d-09d456fc7f8e.png)

![スクリーンショット (344).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/988df70c-7a53-95f0-35e4-da8f4f173084.png)

![スクリーンショット (345).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/01757fa0-2338-e0a5-54f1-75a064e33e66.png)

完了しました！！！

![スクリーンショット (348).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/06256406-2aae-4996-4b10-b85c4abdae8e.jpeg)






## 終わりに

REST APIを使えば簡単にデータの利活用ができます。他のサイトのAPIも接続できるか試してみたいと思います。
JavaScriptのObject.assign()を使ったオブジェクトコピーの注意点

参考サイトを備忘メモ

https://marsquai.com/745ca65e-e38b-4a8e-8d59-55421be50f7e/55e87e2f-c590-413d-8ae9-571ae2c353b5/c56b3489-8ab1-4b44-a49a-b690e2ed0e86/
HIKROBOT製マシンビジョンカメラ(MV-CE050-30UC)のDirect Draw対応化方法まとめ

# OpenCVに手っ取り早く対応させる方法
WindowsにおいてはDirectDrawへ対応させることで一般的なOpenCVのコード通りの作ることが出来る。

# HIKROBOT MV-CE050-30UCについて
AGVのほうが有名かもしれないメーカー。
マシンビジョンも取り扱っている。
親会社と思われるHIKVISONにもダウンロードコーナーはあるが、マシンビジョン関連は取り扱っていないので注意。

# 注意事項
DobotVisionKitをお使いの方は環境が壊れて起動しなくなる可能性があります。
環境が壊れた場合の責任は負えません。すべて自己責任でお願いします。

# 手順

## 1.ダウンロード
https://www.hikrobotics.com/en/machinevision/service/download?module=0
英語サイトからMachine Vision Software MVS4.0.0とSDKをダウンロードする
(英語サイトじゃないとダウンロード時の会社情報入力時の携帯番号で弾かれる為)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345260/4df1b930-8c65-f2d0-66bb-40dc88e543aa.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345260/74345aa8-435a-ea8d-56ec-d01aa383ef66.png)

## 2.MVSのインストール
MVS_STD_4.0.0_221208.zipを展開してインストールする。

## 3.MVS SDKのインストール
MVS_SDK_V3_5_0_3_VC90_Runtime_STD.zipを展開してインストールする。

## 4.MVS ThirdPartyPlatformAdapterのDirectShowパッチの適応
```
C:\Program Files (x86)\MVS\Development\ThirdPartyPlatformAdapter\DirectShow\x64\MvDSS2\InstallDSSvc_x64.bat
```

注意
他のフォルダにはMvDSS用のプラグイン登録方法が残っている。
こちらはMvDSS register okと出るが実際にはechoしているだけなので失敗していても出る。

#確認方法
・GrafEditというツールで確認する(HIKROBOT標準)
　要Windows SDKなので大変。ただ、GUIなので確認時はわかりやすい
　https://learn.microsoft.com/ja-jp/windows/win32/directshow/using-graphedit

・pythonとopencv-pythonの導入済みであれば以下もおすすめ
　https://qiita.com/Gyutan/items/79b26bc8e97ee365c6c8


# 感想
DobotVisionKitにSDKを入れれば両立しそうと思ったがうまくいかなかった。
おそらくDobotVisionKitのMVSはMVS_STD_3.1.0_181229で古いことから
MVSのSDKもその時代のものでないとダメなのかもしれない。
DobotVisionKitを再インストールしたら今度はOpenCV側が動かなくなって2日消費してしまったので
備忘録として残すことにした
CakePHP4 での setTemplates の勘違い

CakePHP4 での setTemplates で若干ハマったので記事として残しておきます。
CakePHP4+setTemplates で検索すると多くの文献では、

```php
$this->Form->setTemplates([
    'inputContainer' => '{{content}}',
    'label' => false,
]);
```

のように不要なオプションを出力しない書き方として false にて指定していることが多く見つけられます。
が、これは型宣言があいまいなPHP8より前のPHPバージョンでのみ動く書き方で、型宣言が厳密になったPHP8以降では動作せず \src\View\StringTemplate.php でエラーがでます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687945/e651b70c-1565-4fd4-a23e-9bb2a8d999d6.png)

開発者に確認したら上記説明に加えて、setTemplatesで指定できるのは文字列のみじゃ、と怒られました。
なので
```php
$this->Form->setTemplates([
    'inputContainer' => '{{content}}',
    'label' => '',
]);
```
と記述するのが正しいそうです。気持ち悪っ。。。

一方で、Form->control では
```php
<?= $this->Form->control('name', ['label' => false, 'class' => 'form-select form-select-sm']) ?>
```
のようにフィールドセットに対してfalseで出力しない書き方が公式にあります。
https://book.cakephp.org/4/ja/views/helpers/form.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687945/cd28fcf9-3b1d-4c61-9eb3-8ed66cf8c1a5.png)

setTemplates は本来この Form->control で出力されるタグに対するものなのですから、単純に考えたらそのまま記述移植するじゃないですか。
なので setTemplates でも false で記述してもいいようにしてほしかったですね！

環境：PHP8.2+Cake4.4.10
２月開催のカンファレンス５選

## RAKUS Tech Conference 2023
開催日時：2023/02/08(水) 14:00～18:00
開催場所：オンライン

株式会社ラクスは「ITサービスで企業の成長を継続的に支援します！」をミッションに掲げ、
メール共有・管理システムの「メールディーラー」や、経費精算システムの「楽楽精算」など、
延べ80,000社を超えるお客様に自社開発したサービスを提供してきました。
「RAKUS Tech Conference」は、こうした今までの取り組みや知見を紹介する、ラクス開発本部主催の技術カンファレンスです。

https://techcon.rakus.co.jp/2023/

## Developers Summit 2023
開催日時：
* 2023/02/09(木) 10:00～18:50
* 2023/02/10(金) 10:00～18:45

開催場所：オンライン

Developers Summit（デブサミ）は、2003年から毎年開催しているITエンジニアの祭典です。デブサミでは、コロナ禍に入ったタイミングでミッションを新たに問い直し「デベロッパーをスターにし、世の中のアップデートを加速する」と掲げてきました。デブサミでスピーカーのみなさんが輝くのはもちろん、参加者の方にとっても、デブサミが前向きなアクションの「きっかけ」となれるようにと思いを込めています。

https://event.shoeisha.jp/devsumi/20230209

## RESEARCH Conference Lightning Talk#1
開催日時：2023/02/03(金) 19:00～20:30
開催場所：オンライン

RESEARCH Conferenceは、リサーチをテーマとした日本発のカンファレンスです。より良いサービスづくりの土壌を育むために、デザインリサーチやUXリサーチの実践知を共有し、リサーチの価値や可能性を広く伝えることを目的としています。

https://research-conf.connpass.com/event/270757/

## DX-デジタルトランスフォーメーション-EXPO 春【東京】
開催日時：2023/02/07(火)～2023/02/09(木)
開催場所：[東京ビックサイト](https://www.dx-expo.jp/spring/access)

DX-デジタルトランスフォーメーション-EXPOは、企業や店舗のDX化を促進させるソリューションが出展される展示会です。毎年DXに課題を持つ企業や店舗施設の人事、総務、経理、営業の方が多く来場されています。
展示会内でDX推進の商談ができ、サービス導入や料金・納期の相談をその場ですることができ、課題解決の提案を具体的且つ円滑に進めることが可能です。

https://www.dx-expo.jp/

## マーケティング・テクノロジーフェア 東京 2023（第11回）
開催日時：2023/02/09(木)～2023/02/10(金)
開催場所：東京ビックサイト

マーケティング・テクノロジーフェアは、「日本のマーケティング力を底上げする」という開催意義を持ったマーケティングに特化した展示会です。来場者の多くが新規顧客、新市場の開拓や、顧客ニーズの把握といった課題を抱えており、それに対して最適なソリューションを提供できるサービスが展示されます。
今年2023年は「“人”に届けるマーケティング」をコンセプトとして、テクノロジーやデータを活用して人の心を動かすマーケティングを可能とする製品やソリューションが集まります。

https://www.tfm-japan.com/
fish 3.6.0 で abbr の仕様が変わった

# TL;DR
- これまでuniversal変数でabbrを管理していたのが変更になった
    - universal変数によるabbrもサポートしている
    - 3.6.0にアップデートしたからといって突然これまでのabbrが使えなくなるわけではない
- これからは config.fish にabbrを記述することが推奨された
- これまでのようにコマンドラインから
```shell-session
 > abbr -a hoge 'echo hoge'
```
のように実行すると保存されない(shellを再起動するとそのabbrが消える)

# 本文
みなさんはfishのabbr[^2]使っていますでしょうか。aliasと違って展開されるので、後で検索しやすくて私はよく使っています。
[^2]:Abbreviation(略語)の略

2023年1月7日のアップデートで`fish 3.6.0`になってからabbrの拡張性は増え、以下の機能が追加されました
- コマンドの展開だけでなく、オプションなどのあらゆるところで展開できるようになった
- 展開のワード(Matching tokens)がregexに対応した
- 展開の際に関数が利用できるようになった
- 展開後のカーソルの位置を設定できるようになった

これによりabbrはより使いやすくなったようです。これに関しての説明は省かせてもらいます。詳細は[リリースノート](https://fishshell.com/docs/current/relnotes.html#fish-3-6-0-released-january-7-2023)や[詳細ページ](https://fishshell.com/docs/current/cmds/abbr.html)(記事投稿時点)を見てください

# universal変数の不使用
機能が増えたのは喜ばしいのですが、これによりabbr自体の仕様が変わりました。
これまでuniversal変数でabbrを管理していた[^1]ものが別管理になりました。リリースノートの「Deprecations and removed features」にも書かれてあります

[^1]:例えば `git checkout` を `gco` として登録する場合、内部的にはuniversal変数である `$_fish_abbr_gco`を`git checkout`とセットする、という処理を行っていた

> - Abbreviations are no longer stored in universal variables. Existing universal abbreviations are still imported, but new abbreviations should be added to config.fish.
(Abbreviationはユニバーサル変数に保存されなくなりました。現存しているユニバーサルによるabbreviationは使用できますが、新しいabbreviationは`config.fish`に追加してください。)

また、[2023/1/22のコミット](https://github.com/fish-shell/fish-shell/commit/90430089330f93b681450f6b25650f78e2ee34da) ~~(まだバージョンには実装されていない)~~ により、この旨がabbrの詳細にも明記されるようです。

*※追記*
[abbrの説明ページ](https://fishshell.com/docs/current/cmds/abbr.html)に下記文章が反映されていることを確認しました。`help abbr`としても確認可能です。

>Previous versions of this allowed saving abbreviations in universal variables.
   That's no longer possible. Existing variables will still be imported and ``abbr --erase`` will also erase the variables.
   We recommend adding abbreviations to `config.fish` by just adding the ``abbr --add`` command.
   When you run ``abbr``, you will see output like this
     > abbr
     abbr -a -- foo bar # imported from a universal variable, see `help abbr`
> 
>   In that case you should take the part before the ``#`` comment and save it in config.fish,
   then you can run ``abbr --erase`` to remove the universal variable::
     > abbr >> ~/.config/fish/config.fish
     > abbr --erase (abbr --list)

上記の通り、
```shell-session
> abbr >> ~/.config/fish/config.fish
> abbr --erase (abbr --list)
```
を実行し、abbrを`config.fish`に追記した後universal変数からabbr関連の変数を削除しましょう。
また、新規のabbrは`config.fish`に書きましょう。
paiza.ioでelixir その181

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
wgetを作れ。

# 方針
W.get( ファイル名、url )

# サンプルコード

```

:inets.start
:ssl.start



defmodule W do
	def get(name, url) do
        {:ok, {_status, _headers, body}} = :httpc.request(url)
        body = IO.iodata_to_binary(body)
        File.write(name, body)
	end
end

W.get("sample.json", 'https://resolvenet.org/modules/contrib/webform/tests/files/sample.json')


{result, 0} = System.cmd("ls", [])
IO.puts result
{result, 0} = System.cmd("cat", ["sample.json"])
IO.puts result





```

# 実行結果

```
exec_command
exec_stderr.txt
exec_stdin.txt
exec_stdout.txt
Main.exs
main.tar.gz
runner_mysql
runner_php
run_user
sample.json

{
    "colorsArray":[{
            "colorName":"red",
            "hexValue":"#f00"
        },
        {
            "colorName":"green",
            "hexValue":"#0f0"
        },
        {
            "colorName":"blue",
            "hexValue":"#00f"
        },
        {
            "colorName":"cyan",
            "hexValue":"#0ff"
        },
        {
            "colorName":"magenta",
            "hexValue":"#f0f"
        },
        {
            "colorName":"yellow",
            "hexValue":"#ff0"
        },
        {
            "colorName":"black",
            "hexValue":"#000"
        }
    ]
}

```

# 成果物

https://paiza.io/projects/PMaQetcdsEXDaYf62b4edw?language=elixir




以上。
synchronized modifier

thread of same instanceを大量発行する

本来
0を読み出し+100
100を読み出し+100 
で200となるはずが、

読み出しタイミング同時だと
0を読み出し+100
0を読み出し+100 
で100となる

```java
class RunnableSampleClass implements Runnable {
    int num;
    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(RunnableSampleClass.class.getName()).log(Level.SEVERE, null, ex);
        }
        add();
    }
    void add() {
        num = num + 100;
    }
}
public class Outer {
    public static void main(String[] args) {
        ExecutorService e = Executors.newFixedThreadPool(10);
        
        for(int i=0; i<10; i++) {
            RunnableSampleClass r = new RunnableSampleClass();
            e.submit(r);
            e.submit(r);
            try {
                Thread.sleep(200);
            } catch (InterruptedException ex) {
                Logger.getLogger(Outer.class.getName()).log(Level.SEVERE, null, ex);
            }
            System.out.println(r.num);
        }
        e.shutdown();
    }
}
```
```
200
200
200
200
200
100
200
100
200
200
```
排他制御フィールドはRunnableSampleClass。つまりthis。
排他制御対象処理はaddメソッド
synchronizedをつけて、排他制御フィールドをつかめるのは１つのスレッドだけとする。つかめた１スレッドだけが排他制御対象処理を実行。

```java
    synchronized void add() {
        num = num + 100;
    }
```
結果がすべて200になった。
```
200
200
200
200
200
200
200
200
200
200
```
[雑メモ]サブネットの利用可能なIPアドレス数を取得する



コマンド。

```
aws ec2 describe-subnets \
--filters "Name=tag-key,Values=Owner" "Name=tag-value,Values=okada" \
--query 'Subnets[*].{SubnetName:Tags[?Key==`Name`] | [0].Value, AvailableIp:AvailableIpAddressCount}' \
--output table
```

以下、実行結果。

```
------------------------------------
|          DescribeSubnets         |
+--------------+-------------------+
|  AvailableIp |    SubnetName     |
+--------------+-------------------+
|  251         |  okada-subnet-01  |
|  251         |  okada-subnet-02  |
+--------------+-------------------+
```
VSCodeのSonarLintを設定

## 内容。
VSCodeでJavaを開発中、SonarLintによって品質向上を実施したかったので、導入手順の個人的記録です。
###### 設定したい内容。
SonarQubeは使わず、ローカルだけでSonarLintを実施。

###### 前提の環境。
VSCodeによるJava開発の環境は構築済。

## 手順。
###### 1.拡張機能を追加。
VSCodeの拡張機能から、SonarLintを選んでインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351480/f4cfe487-a2bd-c29f-e961-7f67b175d730.png)

###### 2.SonarLintの指摘を確認
Javaのソースを編集すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351480/3854201f-52ec-162a-48cf-4aeec88558e5.png)
のように問題ウィンドウに表示されます。