OmniAICreator/Qiita-1.07M huggingface dataset:
オブジェクトのデータの持ち方について

javascriptのオブジェクトについて勉強した。(jquery)
工夫したのはデータの持ち方(hobbyオブジェクト)について。

hobbyのbookやらsportsやらをたくさん外部から設定できる。

[追記]2021.09.17
以下のソースが冗長だったので、頂いたコメントを参考に
jquery的に書き直しました。

```javascript:objectuse.js
let a = {};
a = user.getbookhobby();
$.each(a, function(key, val){
    console.log(val);
});
```

```javascript:objectuse.js
$(function(){
let user = {
    name: '山田',
    age: 27,
    address: '東京',
    hobby:{
        'book':{},
        'sports':{},
    },
    getbookhobby:function(){
        return user.hobby.book;
    },
    setbookhobby:function($key, $value){
      user.hobby.book[$key] = $value;
    },
    gethobby:function(){
        return user.hobby;
    },
};
user.setbookhobby('0', 'AAA');
user.setbookhobby('1', 'BBB');
user.setbookhobby('2', 'CCC');

/*
let a = {};
a = user.getbookhobby();
$.each(a, function(key, val){
    console.log(val);
});
*/
$.each(user.getbookhobby(), (key, val) => {
    console.log(val);
});

});
Team Viewer セットアップ

# Team Viewer　セットアップ方法
以下、Windows版のセットアップ方法記載します。
自分用のメモなので、内容についてはご容赦ください。

## ダウンロード

以下のページから「<strong>無料ダウンロード</strong>」を押下してダウンロードする。

https://www.teamviewer.com/ja/content/free-download-lp-jp/?utm_source=google&utm_medium=cpc&utm_campaign=jp|nb|pr|19|dec|exact-generic-sn|free|t0|0&utm_id=8673259653&utm_content=Exact_Remote-Desktop&utm_term=pc%20%E9%81%A0%E9%9A%94%E6%93%8D%E4%BD%9C&gclid=Cj0KCQjws4aKBhDPARIsAIWH0JXTcLHqaGWMBtJ0XwoZz93MBWf3_wzffycI8mxk6mEkGMWK3NLxudMaAtmcEALw_wcB

ダウンロードすると
エクスプローラー＞ダウンロード
に「TeamViwer_Setup_x64.exe」が入っているので、ダブルクリックして実行します。

すると、以下のようなウィンドウが出てきます。
そのまま、「同意 - 次へ」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436286/c982f641-93e8-4bbe-1758-ff64924a398c.png)

ユーザーアカウント制御のウィンドウが出てくるので、「はい」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436286/e4185efb-9ea5-3566-8ab8-d40807550e46.png)

インストールが開始されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436286/87543c4d-6a79-9e6f-50cb-c83c9984b82a.png)

そして、インストール完了ウィンドウが出てくるので、使う用途によりラジオボタンのチェックをします。
今回は、「個人用として無料版を使用したい」を選びます。
チェックを入れて、終了ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436286/8997e4e7-f083-98c3-d93e-ab7572ca3008.png)

このウィンドウが出てきたら、セットアップ終了です。
![画像.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436286/63a5d234-d106-2e8a-94ba-83a992c7b09a.jpeg)
AtCoderログ：0114 - ABC 094 B

# 問題

https://atcoder.jp/contests/abc094/tasks/abc094_b

## 問題文
> $N+1$ 個のマスが左右に一列に並んでいます．これらのマスには，左のマスから順に $0,1,...,N$ の番号が付けられています．
> あなたは，最初マス $X$ にいます． 隣り合うマスの間は自由に移動することができ，マス $0$ またはマス $N$ にたどり着くとゴールすることができます．ただし，$i=1,2,...,M$ について，マス $A_i$ には料金所があり，そのためマス $A_i$ に移動してくる際には $1$ のコストがかかります．なお，マス $0$，マス $X$，マス $N$ には料金所がないことが保証されます．
> ゴールするまでにかかるコストの最小値を求めてください．

## 制約
> ・$1 \le N \le 100$
> ・$1 \le M \le 100$
> ・$1 \le X \le N−1$
> ・$1 \le A_1<A_2< \ldots <A_M \le N−1$
> ・$A_i \ne X$
> ・入力はすべて整数

## 収録されている問題セット
- [AtCoder Problems Boot camp for beginners Easy 100](https://kenkoooo.com/atcoder/#/training/Boot%20camp%20for%20Beginners/1) [#019]

# 回答
## 回答1 (AC)
マス $0$ に移動してゴールする場合のコスト(cl)とマス $N+1$ に移動してゴールする場合のコスト(cr)をそれぞれ計算し、小さい方を答えとして出力すれば良いでしょう。コードは以下のようになりました。

```C++:abc094b-1.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n, m, x;
  cin >> n >> m >> x;
    
  vector<int> a(m);
  for ( int i=0; i<m; i++ ) {
    cin >> a.at(i);
  }

  int i = 0, cl = 0;
  while ( a.at(i)<x ) {
    cl += 1;
    i += 1;
  }

  int cr = 0;
  while ( i<m && a.at(i)<n ) {
    cr += 1;
    i += 1;
  }

  cout << min(cl,cr) << endl;
}
```

## 回答2 (AC)
累積和を使った別解です。配列 s[0]-s[N+1] において、料金所があれば1、なければ0を代入し、左から累積和を計算することで、答えが簡単に求められます。コードは以下のようになりました。

```C++:abc094b-2.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n, m, x;
  cin >> n >> m >> x;

  int t;
  vector<int> s(n,0);
  for ( int i=0; i<m; i++ ) {
    cin >> t;
    s.at(t) = 1;
  }

  for ( int i=1; i<n; i++ ) {
    s.at(i) += s.at(i-1);
  }

  cout << min(s.at(x),m-s.at(x)) << endl;
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc094/tasks/abc094_b/editorial) → [コンテスト全体の解説](https://img.atcoder.jp/arc095/editorial.pdf)
回答1と同じ方針でした。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0113 - ABC 122 B](https://qiita.com/RoadLynton/items/69927096e90994c23dc9)
- 次の記事 → [AtCoderログ：0115 - ABC 116 B](https://qiita.com/RoadLynton/items/8ea9ea5e1a1a48f142e8)
postgres CSVファイルのインポート・エクスポート

#postgreSQLでCSVファイルをインポート・エクスポートする方法
##1.インポート
>テーブル wk_xxx　の項目 col_aaaとcol_bbbに、CSVファイル aaa.csvをインポートする
`COPY wk_xxx(col_aaa,col_bbb) FROM 'C:\test\aaa.csv' WITH CSV HEADER;`
CSVファイルはフルパスで記載する
CSVヘッダーが無い場合、"WITH CSV HEADER" は不要

```java:CSVファイルのインポート
// STDINはCopyManagerのパラメータで渡す。（※別記事を準備中）
COPY wk_xxx( col_aaa, col_bbb)  FROM STDIN (DELIMITER E'\t', FORMAT csv,HEADER)
```

##2.エクスポート
>テーブル wk_xxx　の項目 col_aaaとcol_bbbを、CSVファイル bbb.csvにエクスポートする
`COPY (select col_aaa,col_bbb from wk_xxx) TO 'C:\test\aaa.csv' CSV DELIMITER ',';`
CSVファイルはフルパスで記載する
CSVヘッダーがいらない場合、"WITH CSV HEADER" は不要

```java:CSVファイルのエクスポート
// STDINはCopyManagerのパラメータで渡す。（※別記事を準備中）
COPY ( select col_aaa,col_bbb from wk_xxx) TO STDOUT WITH (FORMAT csv ,HEADER ,NULL 'null' ,DELIMITER E'\t')
```
【Flutter】TextFormFieldで入力値をフォーマットする

## 要約 

- `inputFormatters`に`TextInputFormatter`を継承したCustomFormatterをセット
- `validator` `maxLength` `buildCounter`にはフォーマット後の値を反映させること(できればもっと楽にしたい）

![expiry_date.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558894/2e1f8a60-6222-8bb2-7637-21ff2a71bb43.gif)


## きっかけ
クレジットカードの入力フォームを作ろうとしたときに入力フォームを工夫したかった。具体的には、カードナンバーで4桁ごとに空白を入れること、有効期限で`/`(スラッシュ)を入れること。

## `TextInputFormatter`を継承したCustomTextInputFormatterの作成

`formatEditUpdate`にて `oldValue`と`newValue`が渡ってくるのでこの2つを比較して処理を決定します。
入力時だけでなく、削除時の実装も忘れずに。

これを`TextFormField`の`inputFormatters`に格納します。

```dart
class CustomTextInputFormatter extends TextInputFormatter {
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    if ('フォーマットを変更する時') {
      final newText = 'hoge'; // フォーマット後の文字
      return newValue.copyWith(
        text: newText,
        // カーソルの位置を端へ
        selection: TextSelection.collapsed(offset: newText.length),
      );
    }

    // フォーマットしない場合はそのままnewValueを返す
    return newValue;
  }
}
```

## バリデーションや文字数カウントへの対応

フォーマットのやり方によって文字数が変わってしまうので、バリデーションや文字数のカウントにも対応する必要があります。

クレジットカードの有効期限だと

`04/23` 

打ち込むのは4文字分、でも表示は5文字分。

具体的には`validator` `maxLength` `buildCounter`に反映させます。

※これをもうちょっとオシャレに、楽にやる方法知ってる方はご教授くださると嬉しいです。

有効期限のフォームのサンプルです。

## サンプルコード
```dart
class ExpiryDateTextField extends StatelessWidget {
  ExpiryDateTextField();

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      // '/'を含めた5文字
      maxLength: 5,
      buildCounter: (context,
          {int currentLength,
          bool isFocused,
          int? maxLength}) {
        // `/`を抜いた文字数でカウント
        final length = currentLength < 3 ? currentLength : currentLength - 1;
        return CustomText.caption('$length/4');
      },
      // 配列の中に格納
      inputFormatters: [_ExpiryDateInputFormatter()],
      validator: (String? value) {
        if (value?.length == 0) return '有効期限が入力されていません';
        // '/'を含めた5文字
        if (value?.length != 5) return '有効期限が不正です';
      },
    );
  }
}

class CustomTextInputFormatter extends TextInputFormatter {
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {

    // 入力している時
    if (oldValue.text.length == 2 && newValue.text.length == 3) {
      final newText = '${oldValue.text}/${newValue.text.substring(2)}';
      return newValue.copyWith(
        text: newText,
        selection: TextSelection.collapsed(offset: newText.length),
      );
    }

    // 削除している時
    if (oldValue.text.length == 4 && newValue.text.length == 3) {
      final newText = newValue.copyWith().text.substring(0, 2);
      return newValue.copyWith(
        text: newText,
        selection: TextSelection.collapsed(offset: newText.length),
      );
    }

    return newValue;
  }
}

```

## 感想

カスタムフォーマッターは使い回せるので便利だ
Workato：Communityプランのワークスペースで作成したレシピが勝手にCommunity libraryに公開されてしまう理由と対応方法

Workatoには、通常は、複数のチームのワークスペースと、１つの個人（自分）のワークスペースが存在しますが、個人のワークスペースはCommunityプランという無料プランが適用されています。

個人のワークスペースでもレシピを作成して実行することは可能ですが、**Communityプランで作成されたレシピは、自動的に（予告なく）Community libraryに掲載される可能性がある点に注意が必要です。**

例えば、会社名や部署名、氏名などがレシピ名に入っていたり、変数にAPIトークンなどの機密情報が入っていれば、それらの情報がCommunity libraryを通して全Workatoユーザーに公開され、共有可能な状態となります。

# なぜCommunity libraryに掲載されてしまうのか

Workatoのterms-of-serviceの14項の(d)にその理由が記載されています。

https://www.workato.com/legal/terms-of-service

> (d) Recipes and Connectors. **The Recipes and Connectors created by Account Holder in the Non-Paid Account are “public” by default**, meaning that all Recipes and Connectors created by Account Holder during Non-Paid Account will be Community Recipes and Connectors, and Account Holder of Non-Paid Account grants Workato an irrevocable, perpetual, transferable and sublicensable and worldwide license under any rights Account Holder owns in those Recipes and Connectors upon creation, to view, use, copy, modify and distribute those Recipes and Connectors. The Recipes and Connectors created during the Trial will be “private” by default subject to Section 3(b) of this Agreement, and will remain private upon termination or expiration of the Trial.

太字のところを意訳すると、**無料アカウントで作成されたレシピは、デフォルトで「公開」される**と書かれています。

# トライアルアカウントは大丈夫？

上記terms-of-serviceでは、次の通り書かれています。
>The Recipes and Connectors created during the Trial will be “private” by default subject to Section 3(b) of this Agreement, and will remain private upon termination or expiration of the Trial.
（トライアルで作成されたレシピやコネクターは、トライアル中も、トライアル終了後もプライベートのままになります）

以上により、トライアル期間中に作成されたレシピはプライベートなレシピとして扱われますので、Communityプランのレシピのように勝手に公開されることはありません。また、利用しているアカウントがトライアル終了→Communityプランに切り替わった後も、トライアル期間中に作成されたレシピはプライベートのままとなり、同様に公開されません。ただし、トライアル期間終了後に作成されたレシピは公開される可能性があります。

# 対応方法

最も確実な対応方法は、個人のワークスペースを使わないことです。有償プランのワークスペースでは、Community libraryに自動的にレシピが掲載されてしまうようなことが発生しないためです。（有償プランのワークスペースでは、ユーザー自身が明示的にレシピを指定し、Community libraryへ掲載する操作を行わない限り、作成されたレシピがCommunity libraryに掲載されることはありません）

しかし、Workatoの練習用にどうしても個人のワークスペースを利用したい方もいると思います。そのような場合において、安全に利用する方法についてご説明します。

## 手順

### １．個人アカウントのワークスペースで「Settings」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/5dd54367-d886-8cfd-3c41-d034bdc705fa.png)

### ２．「Community」をクリックし、Community listingsの「Allow recipes to be listed on community」をオフにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/d82ca9ad-67ea-9c53-ff09-e0358ff97464.png)

以上の設定を行うことで、個人アカウント上で作成したレシピが自動的にCommunity libraryへ掲載されなくなります。

なお、Communityプランで作成し、Community libraryに掲載されてしまったレシピについては、削除されることをお勧めします。レシピを削除することで、Community library上からもそのレシピが削除されます。（検索結果としてしばらく画面上に残るかもしれませんが、そのレシピへアクセスすることはできなくなります）

また、上記により今後作成するレシピについては、Community libraryへの掲載は行われなくなりますが、Communityプランは本来レシピの公開を前提としているプランであるため、セキュリティやコンプライアンスの観点からも、可能な限り個人のワークスペースは利用せず、なるべくチームのワークスペースをお使いになることを強くお勧めします。
cartopyでurllib.error.URLErrorが出た時の対処

追記2021/11/09
どうやら海岸線データの置いてあるサーバ（https://naciscdn.org/naturalearth/ ）がたまたまダウンしていただけで，一時的な問題だった可能性がある，と後に友人から教えてもらいました．ありがとう．．
<br>
<br>

私，初心者です．内容にはご注意．また，異なる理由で同じエラーの出る場合もあるかもしれないので，ひとつのケースとして参考までに．

# バージョン
確認できたものだけ（真面目に全バージョン検証したわけでない）
cartopy 0.19.0.post1

# 状況
`cartopy.fearure.BORDERS`を`ax.add_feature`で実行．エラーを辿ってゆくと最終的にはpython3.9のurllibでのエラーと出るが，それ自体はcartopyが呼んでいる．

# 解決
... /miniconda3/lib/python3.9/site-packages/cartopy/io/shapereader.py
ないの300行くらいのところにある`_NE_URL_TEMPLATE`のアドレスを書き換える

修正前

```python3
     _NE_URL_TEMPLATE = ('https://naciscdn.org/naturalearth/{resolution}'
                        '/{category}/ne_{resolution}_{name}.zip')
```

修正後

```python3
     _NE_URL_TEMPLATE = ('https://naturalearth.s3.amazonaws.com/'
                         '{resolution}_{category}/ne_{resolution}_{name}.zip')
```

`cartopy.fearure.BORDERS`を初めて描画するタイミングでデータのダウンロードが発生し，上記のURLが参照されているよう．故にそのタイミングが肝と思われ，少し前（2021年の2月とか）はnaciscdn.orgにアクセスできたが最近（2021年9月）はアクセスできなくなっている．
amazonのサーバーを指定すると大丈夫のよう．最新版のcartopyでcaciscdnを指定しているものもあったので，そもそもcondaのバージョンも関係している可能性あるが，検証はしていません．

# 参考
https://stackoverflow.com/questions/27696560/cartopy-cant-add-features-to-geo-axes-no-errors-or-warnings
ERR_ACTION_ACCESS_UNDEFINED: Are you trying to access this.someMutation() or this.someGetter inside an @action? That works only in dynamic modules.

モジュール の `@Action` に `{ rawError: true }`を指定する。

```js
@Action({ rawError: true })
doSomething() {
}
```

これを指定しないと、ライブラリデフォルトのエラー(タイトルのやつ)を出すらしい...

# もう一つよくあるエラー ERR_STORE_NOT_PROVIDED

ほかのモジュールで vuex を使っていると競合してエラーを吐くらしい。
自分の場合は、認証に使っているモジュールが原因だったので、
`nuxt.config.js` の auth に以下を追加しました。

```js:nuxt.config.js
auth: {
  someOptions: {
  },
  vuex: false // <- これを追加
},

```
[Rails] jQueryの導入

以下、Ruby on Rails 6.0.0における
jQueryのインストール方法です。

1. gemの導入
2. application.jsに記述追加
3. application.html.erbのhead部に記述追加
4. 任意の内容で動作確認

#1. gemの導入

以下の記述を追加し、bundle installを打ちます。

```ruby:Gemfile
gem 'jquery-rails'
```

#2. application.jsに記述追加

ディレクトリがない場合は
apps/assets/javascripts/application.js
作成します。

```ruby:app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
```

#3. application.html.erbのhead部に記述追加
以下の一行を追加します。

```ruby:views/layouts/application.html.erb

<head>

#（中略）

<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

</head>

```

#4. 任意の内容で動作確認

```ruby:~.html.erb

<p>jQuery適用前</p>
<script type="text/javascript">
  $(document).ready(function(){
    $("p").text("jQuery適用後");
  });
</script>

```

表示内容が
"jQuery適用後"
として表示されていれば成功です。

今回は以上です。

お読みくださりありがとうございました。
Flask Migration 五月雨メモ

Flask の Migration を使ってみたのでいろいろメモ。

とりあえず最短で動くまでを構築している。DB は PostgreSQL
フォルダ構成は

```
├main.py
├config.py
└📁models
 　├database.py
 　├user.py
```

みたいな感じで、models フォルダにモデルを分離した。チュートリアルとかだと、main.py にべた書きしているのが多くて少しだけ手間取った。

database.py にセッション初期化の関数を用意して

```python:models/database.py
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def init_db(app):
    db.init_app(app)
```

config.py には接続情報を用意する。

```python:config.py
import os

class DevelopmentConfig:
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    SQLALCHEMY_ECHO = True
    SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://{user}:{password}@{host}/{name}'.format(**{
        'user': 'postgres',
        'password': 'password',
        'host': 'localhost:5432',
        'name': 'postgres'
    })

Config = DevelopmentConfig
```

そして、メインはこうなる。

```Python:main.py
from models.user import User
from models.database import db, init_db

app = Flask(__name__)
app.config.from_object('config.Config')

init_db(app)

migrate = Migrate(app, db)

<中略>

if __name__ == "__main__":
    app.run()
```


チュートリアルなどを見ていると db.create_all() という関数を呼んでいるものがあるが、これはマイグレーションをしないで一括で作成してそのままそれをつかう開発の時で、マイグレーションをしたい場合には使えない。マイグレーションで DB を作成したい場合は、コマンドラインで操作する。

その前に、毎回打つのも冗長なので、環境変数に FLASK_APP=manage.py を入れておく。

```
export FLASK_APP=manage.py
```

次に、マイグレーションファイルを作成するので初回は初期化する。このコマンドでmigrationsというフォルダが生成される。

```
flask db init
```

マイグレーションを実行するとテーブルも作成されます。

```
flask db migrate
```

ここで注意。 **モデルで外部キーを使っている場合、外部キーの参照先のモデルをインポートしておく必要があります** 。あたりまえといえばあたりまえなんだけど、チュートリアルなどで書かれているサンプルだと、同じファイルに全部のモデルが書いてあったりするので意外と気づきにくい。

下記の例だとユーザ（User）が契約（Contract）テーブルに外部キー参照を持っているので、contract をインポートする必要がある。


```python:user.py
from models.database import db
from models.contract import Contract #←これが必要だよ！！！！！

class User(db.Model):
    __tablename__ = 'User'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    create_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    update_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)

    contract_id = db.Column(db.Integer, db.ForeignKey('Contract.id'))
    email = db.Column(db.String(255), nullable=True)

    def __init__(self, sumaregi_user_id, contract_id):
        self.contract_id = contract_id
```


## その他メモ

### 文字数制限のないテキスト型

Text というのがある

```
    email = db.Column(db.Text, nullable=True)
```

### 型を修正してマイグレーションしても反映されないとき

Migrate に compare_type=True オプションを付ける必要がある。

```
migrate = Migrate(app, db, compare_type=True)
```
Python3: Kinesis Data Stream の使い方

次のページを参考にしました。
[Boto3 documentation -> Kinesis](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/kinesis.html)

ストリームを作成

```py:create_stream.py
#! /usr/bin/python
#
#	create_stream.py
#
#					Sep/16/2021
#
import boto3
#
name_stream='sample_sep16'
#
client = boto3.client('kinesis')
response = client.create_stream(
    StreamName=name_stream,
    ShardCount=1
)
#
```

ストリームをリスト

```py:list_streams.py
#! /usr/bin/python
#
#	list_streams.py
#
#					Sep/16/2021
#
import boto3
import sys
#
client = boto3.client('kinesis')
streams = client.list_streams()
llx = len(streams["StreamNames"])
sys.stderr.write("llx = %d\n" % llx)
for it in range(llx):
	print(streams["StreamNames"][it])
```

詳細を表示

```py:describe_stream.py
#! /usr/bin/python
#
#	describe_stream.py
#
#					Sep/16/2021
#
import boto3
#
name_stream='sample_sep16'
#
client = boto3.client('kinesis')
response = client.describe_stream_summary(
    StreamName=name_stream
)
#
print(response)
```

レコードを入れる

```py:put_record.py
#! /usr/bin/python
#
#	put_record.py
#
#					Sep/17/2021
#
import boto3
#
name_stream='sample_sep16'
#
client = boto3.client('kinesis')
response = client.put_record(
    StreamName=name_stream,
    Data=b'testdata-aa',
    PartitionKey='123'
)

print(response)
#
```

レコードを取り出す

```py:get_record.py
#! /usr/bin/python
#
#	get_record.py
#
#					Sep/17/2021
#
import boto3
#
name_stream='sample_sep16'
#
client = boto3.client('kinesis')
response = client.get_shard_iterator(
    StreamName=name_stream,
    ShardId='shardId-000000000000',
    ShardIteratorType='TRIM_HORIZON',
)

print(response)
print()
#
shared_iterator = response['ShardIterator']
#
response = client.get_records(
    ShardIterator=shared_iterator,
    Limit=10
)
#
print(response)
print()
#
```

ストリームの削除

```py:delete_stream.py
#! /usr/bin/python
#
#	delete_stream.py
#
#					Sep/16/2021
#
import boto3
#
name_stream='sample_sep16'
#
client = boto3.client('kinesis')
response = client.delete_stream(
    StreamName=name_stream,
    EnforceConsumerDeletion=True
)
#
```
Laravel 6.x リダイレクト時にクエリパラメータを引き継ぐ

# やりたいこと
サービスをスタートしてからパスの構造を整理したりして、コンテンツを引っ越した時に、Laravelにはリダイレクトルートという便利な機能があり、

```
Route::redirect('/old/path', '/new/path');
```

や

```
Route::permanentRedirect('/old/path', '/new/path');
```

のように記述して301、302のリダイレクトを行うことができます。こうしておけば旧パスでコンテンツをブックマークしている人にも404を返さなくてすみます。便利。

ただ、この`redirect`や`permanentRedirect`はクエリパラメータを引き継いでくれないようで、例えば

`http://your.domain/old/path?param=hello`

のようなURIにアクセスされても

`http://your.domain/new/path`

にリダイレクトされてしまいます。パラメータを捨てられてしまうと動的なコンテンツはまともに生成できなくなってしまったりするので困ります。なんとか引越し先にパラメータを持っていきたい。

# 解決方法
以下のようにリダイレクトルートを記述すればクエリパラメータを引き継ぐことができます。

```
Route::redirect('/old/path', '/new/path?' . Arr::query(request()->query()));
```

`permanentRedirect`でも同じです。単純にヘルパを用いてクエリストリングを新しいパスに追加しているだけです。

この方法でルートキャッシュも問題なく生成されるようでした。このようなサービスイン後のコンテンツのお引越しは多くはないとはいえ無いわけではないので、もしかしたらもっと単純な方法があるのではないか？という気もします。
Workato：Community libraryの選び方

WorkatoにはCommunity libraryという、レシピやカスタムコネクターのコレクションがあります。もし、自分の業務に合ったレシピやカスタムコネクターがCommunity libraryにあれば、そのレシピやカスタムコネクターを利用することで、1からレシピを作成することなく、軽微な調整のみで必要な業務の自動化を始めることが出来ます。

しかし、WorkatoのCommunity libraryには必ずしも「使える」（使い物になる）ものが掲載されているとは限らず、例えば作りかけのレシピのような不完全なものが並ぶ場合もあるため、その点注意しながら選ぶ必要があります。

今回は、Community libraryから、レシピやCustom connectorを選択する際のポイントについて記載していきます。

## 選択のポイント

### 「Featured」ラベルが表示されているレシピ

Workato社がおすすめするレシピには、「Featured」というラベルが表示されます。つまり、Workato社お墨付きのレシピとして考えることができますので、「使える」レシピを選択の際の判断材料の１つとして有効であろうと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/815955e7-bc61-65ff-3ede-1507f988fcb9.png)

### Workato社が作成したレシピやカスタムコネクター

Workato社が作成したレシピやカスタムコネクターには、「Workato Customer Success」「WorkatoApps」「Workato Tutorial」などと記載されています。Workato社が作成したレシピやカスタムコネクターであるため、安心して利用できるレシピと判断することができるでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/ce17e3f9-4c3f-d30e-6ca4-451b7945e561.png)

なお、この他にもWorkato社が作成したレシピは数多くあります（Workatoの社員名で掲載されているレシピがいくつかあります）が、全てを判断することは難しいと思いますので、まずは上記３つのユーザーが作成したレシピやカスタムコネクターを選択されるのが良いでしょう。

### ベンダーが提供しているレシピやカスタムコネクター

一部のソフトウェアベンダーは、自社の製品向けにレシピやカスタムコネクターを作成し、公開している場合があります。ベンダーの純正コネクターであるため、安心して利用することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/79c203c5-53b4-7c7f-8e2e-bd267e3fa1fa.png)

## 注意点

Community library上に掲載されているレシピやカスタムコネクターは、原則として無保証であり、これらを使用したことに不具合等が生じてもサポートは期待できないもの（ユーザーの自己責任で利用するもの）とお考え下さい。（ただし、Workato社が開発しているレシピやカスタムコネクターについては、サポートを求めることで改善＝エンハンスが行われる場合があります）
【Nuxt.js】tailwind.config.jsを書き換えても反映されない場合の対処法

何回かあったのでメモっておく

## configの書き方が間違っていないか確認する

- extendの中に書く
- ,（カンマ）が抜けていないか
- fontSizeなどの名前の部分は公式で調べて記載する

```
theme: {
    extend: {
      fontSize: {
        '10xl': '9rem',
      },
      transitionDuration: {
        '1100': '1100ms',
      }
    },
  },
```

## npm installする

これやらなずにnpm run devをやり直すだけでいいかも。

## npm run devする
Goでカタカナバリデーションを実装しようとしたが、unicodeパッケージのKatakanaテーブルには記号なども含まれていた。

## 現象

Goでカタカナチェックを実装する際に、
[unicodeパッケージ](https://pkg.go.dev/unicode)のKatakanaテーブルを利用していたのだが、

```Go
		if !unicode.In(r, unicode.Katakana) {
			return false
		}
```

なんか想定外の`㋐`などの記号も通してしまうので、
Katakanaのテーブルにはどのような文字が入っているのか確認した。

## 解析

unicodeパッケージのソースを見る限り、下記コードポイントの範囲で指定されている。

https://cs.opensource.google/go/go/+/master:src/unicode/tables.go;l=4709-4723

```Go
var _Katakana = &RangeTable{
	R16: []Range16{
		{0x30a1, 0x30fa, 1},
		{0x30fd, 0x30ff, 1},
		{0x31f0, 0x31ff, 1},
		{0x32d0, 0x32fe, 1},
		{0x3300, 0x3357, 1},
		{0xff66, 0xff6f, 1},
		{0xff71, 0xff9d, 1},
	},
	R32: []Range32{
		{0x1b000, 0x1b164, 356},
		{0x1b165, 0x1b167, 1},
	},
}
```

コードポイントを調べた所、アイウエオのような一般的なカタカナ以外にも、
㌠みたいな、カタカナを利用して構築してある記号や、
ヰのような旧字体かなや変体仮名も、カナとしての対象として含まれていた。

### Range16

* 0x30a1
    - ァ
* 0x30fa
    - ヺ
* 0x30fd
    - ヽ
* 0x30ff
    - ヿ
* 0x31f0
    - ㇰ
* 0x31ff
    - ㇿ
* 0x32d0
    - ㋐
* 0x32fe
    - ㋾
* 0x3300
    - ㌀
* 0x3357
    - ㍗
* 0xff66
    - ｦ
* 0xff6f
    - ｯ
* 0xff71
    - ｱ
* 0xff9d
    - ﾝ

### Range32

* 0x1b000
    - 	𛀀 変体仮名 片仮名 ア行エ段
* 0x1b164
    - ヰ 旧字体かな文字
* 0x1b165
    - ヱ 旧字体かな文字
* 0x1b167
    - 𛅧 旧字体かな文字 ンの仮名？

## 対応

要件としては、記号系のカナはバリデーション対象外とする必要があり、
unicodeパッケージのKatakanaテーブルは使えないので、自作する事にした。

## 参考

* https://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7_3000-3FFF
* https://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7_F000-FFFF
* https://ja.wikipedia.org/wiki/%E4%BB%AE%E5%90%8D%E8%A3%9C%E5%8A%A9
* https://unicode-table.com/en/
* https://pkg.go.dev/unicode
[Ruby] AtCoder過去問 B - Chocolate

##はじめに
AtCoderの過去問B問題をRubyで解いてみました。
よろしくお願いします。

問題はこちらから確認してください↓

https://atcoder.jp/contests/abc092/tasks/abc092_b

##B - Chocolate

まずは入力を受け取ります。
aは配列として受け取るようにしています。
答えはチョコの数なので変数chocoに0を代入しておきます。

```Ruby
n = gets.to_i
d, x = gets.split.map(&:to_i)
a = readlines.map(&:to_i)

choco = 0
```

まずは法則を考えます。
私は割り算でこの問題を考えました。

①まず、dをそれぞれの日数で割った時あまりなく、ちょうどで割り切れた場合はチョコを割った答えがチョコを食べた数です。
→この法則は入力例2の一人目や入力例3の最後のひと(6の人)に当てはめて計算してみたらわかります。

②もし、dをそれぞれの日数で割った時、あまりがある場合は割った答え+1がチョコを食べた数です。

③もし入力例1の３人目の人のように10の人はdを超えているので最初の1日目しかチョコを食べることができません。（10日後に食べる予定ですが、その日はこないため)

上記を踏まえてeach文でそれぞれの合宿参加者ごとに、条件分岐し、chocoに追加していきます。

```ruby
n = gets.to_i
d, x = gets.split.map(&:to_i)
a = readlines.map(&:to_i)

choco = 0

a.each do |i|
  if d % i == 0
    choco += d / i
  elsif i <= d
    choco += d / i + 1
  else 
    choco += 1
  end
end
```

そして最後に余ったxをchocoに追加したら、準備されていたチョコの数が出てきます。

```ruby
n = gets.to_i
d, x = gets.split.map(&:to_i)
a = readlines.map(&:to_i)

choco = 0

a.each do |i|
  if d % i == 0
    choco += d / i
  elsif i <= d
    choco += d / i + 1
  else 
    choco += 1
  end
end

puts choco += x
```
PostgreSQLで存在しているroleに対してdoes not exist 

## 解決したい内容
作成したはずの　”USERNAME"　というロール名でDBに接続しようとするができない。

```
$ psql -U USERNAME -d (データベース名)
psql: error: FATAL:  role "USERNAME" does not exist
```
## 環境
- WSL2
- PostreSQL 12.7

## 改善策
USERNAME → username　（ロール名を大文字から小文字に変更する。）

```
$ psql -U username -d (データベース名)
```

ロール名は小文字じゃないとだめなのかな。。。
有識者の方いらっしゃいましたら是非ご教示ください m(_ _)m
<br>
この記事が役に立ったよって方は、**LGTM**ボタン、ぜひお願いします！！！
<br>
GASを使って定時実行でConnpassの勉強会をSlackに投稿する

# はじめに
職場のSlackがConnpassの勉強会情報を収集していて、便利だったので自宅でも再現してみようと思いました。
職場の実装内容がわかっていませんが、ConnpassがWebAPIを用意しているのでやりたいことはできそうです。

# 必要なモノ
- Slack
  - 定時実行の結果(Connpassの勉強会)を投稿するチャンネル
  - Incoming Webhooks
- Googleアカウント：GASつかうので
- connpass API
  - [イベントサーチAPI>リファレンス](https://connpass.com/about/api/)

# Let's 構築

1. Slackのチャンネル作成、Webhook発行
1. GASの製造
  1. connpass APIをリクエスト
  1. レスポンスをSlackに投稿する文章に加工
  1. SlackのWebhookに投稿 
1. GASのトリガーなどを設定

GASの製造以外については、下記の記事内の手順をコピペでやり過ごしました。
https://qiita.com/mabubu0203/items/50be232ddb68fe723df6

## コード

Github: https://github.com/mabubu0203/GAS/tree/main/slack-connpass

## 見え方

![スクリーンショット 2021-09-16 17.27.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106929/417f88ed-acc8-4279-cafc-665b9465bdcd.png)

# まとめ
Qiita内で[connpassAPI](https://qiita.com/search?q=connpassAPI)で調べたところ記事があまりヒットしませんでした。
GASでの実装は難易度が低めな印象なので、個人でSlackを運用している方はお試ししてくださると良いかなと思います。

# 参考さいと
- https://qiita.com/mabubu0203/items/50be232ddb68fe723df6
TypeScript よく使う型の超簡易的な書き方の紹介　＊初心者用

TypeScriptのすごくざっくりとした
型の書き方の紹介です。
詳しいことなどは載せていないので
間違いなどがありましたらFB頂けると幸いです。
メモ程度の感覚で見て頂けると幸いです。

##要素1つ1つの型
```sample.ts
boolean :boolean
number :number
string :string
                      etc...
```

##配列の型
```sample.ts
Array<要素1つ1つの型>

例)
Array<number> = [1, 2, 3]
```

##オブジェクトの型
```sample.ts
object = {
 要素1つ1つの型
};
例
object = {
 number: number
};
```

以上
Unity とにかく全体を明るくする

### 1.シーンのライトを消す
エディタの、
Window -> Rendering -> Lightning -> (tab)Enviroment-> Enviroment Lightning
  -> Source -> Color
  -> Ambient Color -> 白
に設定する。
もともとAmbient Lightを暗くして、ライトを加えて空間を明るくする仕様らしいので、ライトを加えると、インテンシティの強い光となる。
Workato：他のサービスに頼らずに（Workatoだけで）xlsx形式ファイルを処理するには

WorkatoでExcelファイルを扱うには、Googleスプレッドシートを利用する、あるいはcsv形式に変換して利用する、いずれかで対応することが出来ます。

しかし、対象のファイルがxlsx形式で、かつcsvへの変換を行うことが出来ないという場合もあると思います。このような場合は、以下のようなレシピを作成し利用することで、Googleスプレッドシートを利用せずに、xlsx形式のファイルをWorkato上で利用することができます。

## どのようにxlsx形式を処理するか

xlsx形式のファイルはOffice Open XML (OOXML)というフォーマットに準拠しています。また、xlsxファイルはzip形式の圧縮ファイルで、unzip等で解凍するとその中身を簡単に確認することが出来ます。

https://ja.wikipedia.org/wiki/Office_Open_XML

Workatoでは、Files by Workatoコネクターを利用することで、zipファイルを解凍することが出来ます。また、XML parser by Workatoを利用することで、xmlをパースすることが可能です。これらのコネクターを活用しながらOOXMLの仕様に合わせてレシピを実装することで、Googleスプレッドシート等の外部サービスに頼ることなく、Workatoだけでxlsx形式ファイルの処理を実現することができます。

## レシピ

https://app.workato.com/recipes/1311796-xlsx-workato?community=true

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/eccb956f-c81b-5e13-a74a-6eb95a1664f5.png)
Kinesis Data Stream の使い方

次のページを参考にしました。
[AWS CLI を使用した基本的な Kinesis Data Stream オペレーションの実行](https://docs.aws.amazon.com/ja_jp/streams/latest/dev/fundamental-stream.html#create-stream)

ストリームを作成

```bash
STREAM_NAME="sample_sep16"
aws kinesis create-stream --stream-name $STREAM_NAME --shard-count 1
```

ストリームをリスト

```bash
aws kinesis list-streams
```

詳細を表示

```bash
STREAM_NAME="sample_sep16"
aws kinesis describe-stream-summary --stream-name $STREAM_NAME
```

レコードを3つ入れる

```bash
#
STREAM_NAME="sample_sep16"
aws kinesis put-record --stream-name $STREAM_NAME --partition-key 123 --data testdata-aa
aws kinesis put-record --stream-name $STREAM_NAME --partition-key 456 --data testdata-bb
aws kinesis put-record --stream-name $STREAM_NAME --partition-key 789 --data testdata-cc
#
```

レコードを取り出す

```bash
#
SHARD_ITERATOR=`aws kinesis get-shard-iterator --shard-id shardId-000000000000 --shard-iterator-type TRIM_HORIZON --stream-name sample_sep16 | jq .ShardIterator`
#
#
echo $SHARD_ITERATOR
#
aws kinesis get-records --shard-iterator $SHARD_ITERATOR
```

ストリームの削除

```bash
STREAM_NAME="sample_sep16"
aws kinesis delete-stream --stream-name $STREAM_NAME
```

複数のレコードを一度に入れる方法

```bash
aws kinesis put-records --cli-input-json file://in01.json
```

```json:in01.json
{
  "Records": [
    {
      "Data": "testdata-aa",
      "PartitionKey": "123"
    },
    {
      "Data": "testdata-bb",
      "PartitionKey": "456"
    },
    {
      "Data": "testdata-cc",
      "PartitionKey": "789"
    }
  ],
  "StreamName": "sample_sep16"
} 
```
重力レンズ効果を描画してみた(JavaScript)

# 初めに
　最近p5.jsというものを知りまして、インタラクティブにGUIを操作できるものが簡単に作れるのが楽しくて色々作ってました。それで何かしら物理現象をシミュレーションしようと思い立ちまして、重力によって光が曲がる様子を描画してみることにしました。
　厳密に再現するのは能力的にも計算量的にも難しそうなので今回は位置の補正のみ行います。

# 重力レンズの仕組み
　重力レンズは銀河などの重力によって後方にある星の光などが曲がることで実際とは異なる見え方をする現象です。
![重力レンズ仕組み.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179010/e04d11ad-f31e-c34f-fe84-fac7249586b5.jpeg)
　重力によって歪められた光の角度には以下の関係が成り立ちます

```math
\beta = \theta - \alpha(\theta)
```

　今回はレンズに使う重力は質点のように一つの点から重力が発生している様子を想定しているので$\alpha$は以下の式によって表されます

```math
\alpha = \frac{C(r - r')}{|r - r'|^2} \quad (Cは適当な定数)
```

　ここで$\theta$が十分小さければ$r-r'= $ $\vec\theta$とみなせるのでここで$\vec\beta$と$\vec\theta$について重力の中心を原点とすればこの二つは平行なので、この方向の単位ベクトル$\vec e$に対して

```math
\vec\beta = \beta \vec e\\
\vec\theta = \theta \vec e
```

とすると

```math
\alpha(\theta) = \frac{C}{\theta}
```

したがって$\beta$は

```math
\beta = \theta + \frac{C}{\theta}
```

通常観測できるのは$\theta$であり実際の位置$\beta$を出力するためこの式を使って$\beta(\theta)$の関数として使用するだけですむが、今回は$\beta\rightarrow\theta$を行いたいので、この式を$\theta$について解いて

```math
\theta = \frac{\beta±\sqrt{\beta+4C}}{2}
```

これを用いて描画していく


# p5.jsでの描画
　これを実装したのがこちらです。p5jsのCollectionsです。見れなかったら教えてください
[https://editor.p5js.org/aokyut/collections/U5-u0xfNh](https://editor.p5js.org/aokyut/collections/U5-u0xfNh)
使い方はキャンバス上でクリックだけです。そうすると重力が発生しその影響で線や点の位置が歪むのが確認できると思います。ぜひ遊んでみてください

# 最後に
　今回は重力レンズによる光の屈折を描画しました。本当であれば位置だけでなく光の形が変化する様子も再現したかったのですが難しいので諦めました。pythonの方で再現するのもありだと思います。他にもp5.jsで色々作っているのですがそちらも公開しようか悩んでいます。
PHPで連想配列をPostgreSQLのpsql風にテーブル表示する

連想配列をPostgreSQLのpsql風にテーブル表示するコードです。
こんな感じで出力されます。

```
 actor_id | first_name | last_name    | last_update
----------+------------+--------------+------------------------
        1 | Penelope   | Guiness      | 2013-05-26 14:47:57.62
        2 | Nick       | Wahlberg     | 2013-05-26 14:47:57.62
        3 | Ed         | Chase        | 2013-05-26 14:47:57.62
        4 | Jennifer   | Davis        | 2013-05-26 14:47:57.62
        5 | Johnny     | Lollobrigida | 2013-05-26 14:47:57.62
        6 | Bette      | Nicholson    | 2013-05-26 14:47:57.62
        7 | Grace      | Mostel       | 2013-05-26 14:47:57.62
        8 | Matthew    | Johansson    | 2013-05-26 14:47:57.62
        9 | Joe        | Swank        | 2013-05-26 14:47:57.62
       10 | Christian  | Gable        | 2013-05-26 14:47:57.62
(10 行)
```

なお、データはPostgreSQL tutorialのサンプルデータベースを使いました。
https://www.postgresqltutorial.com/postgresql-sample-database/

```php
public function displayArray(array $rows)
{
    if (!$rows) {
        echo '(0 行)' . PHP_EOL;
        return;
    }

    $col_names = array_keys($rows[0]);
    $max_width = [];

    $col_num = count($col_names);

    // 列名の表示幅を取得する
    for ($i = 0; $i < $col_num; $i++) {
        $max_width[$i] = mb_strwidth($col_names[$i]);
    }

    // 列名とその列のデータの最大の表示幅を調べる
    foreach ($rows as $row) {
        $values = array_values($row);
        for ($i = 0; $i < $col_num; $i++) {
            $val = $values[$i];
            if (mb_strwidth($val) > $max_width[$i]) {
                $max_width[$i] = mb_strwidth($val);
            }
        }
    }

    $lines = [];

    // 列名の表示内容を組み立てる
    $a = [];
    for ($i = 0; $i < $col_num; $i++) {
        $format = '%-' . $max_width[$i] . 's';
        $a[$i] = sprintf($format, $col_names[$i]);
    }
    $lines[] = ' ' . implode(' | ', $a);

    // 仕切り線の表示内容を組み立てる
    $a = [];
    for ($i = 0; $i < $col_num; $i++) {
        // +2は表示時の前後のブランクの分
        $a[] = str_repeat('-', $max_width[$i] + 2);
    }
    $lines[] = implode('+', $a);

    // 各行の表示内容を組み立てる
    foreach ($rows as $row) {
        $values = array_values($row);
        for ($i = 0; $i < $col_num; $i++) {
            $val = $values[$i];
            $space = str_repeat(' ', $max_width[$i] - mb_strwidth($val));
            $values[$i] = is_numeric($val) ? $space . $val : $val . $space;
        }
        $lines[] = ' ' . implode(' | ', $values);
    }

    echo implode(PHP_EOL, $lines) . PHP_EOL;
    echo '(' . count($rows) . ' 行)' . PHP_EOL;
}
```
cannot load such file -- rexml/documentと出た時の対処法！

環境
---
macOS Big Sur 11.5.2
rails 6.1.4
railsチュートリアル６章学習中


実行
---

```
$ rails test:models
```
エラー
---
```
rails aborted!
LoadError: cannot load such file -- rexml/document
```
解決法
---

Gemfileに

```rails:Gemfile
gem 'rexml'
```
を追加し

```
$ bundle install
```
再度

```
$ rails test:models
```
↓

```
Run options: --seed 62060

# Running:

.

Finished in 0.316916s, 3.1554 runs/s, 3.1554 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
```
できました！
cryoSPARC Discuss切り抜き

cryoSPARC Discussで見かけた、役に立ちそうな投稿を抜粋してリンクを張り付けておきます。

# FSC関係
## 5種類あるFSCカーブのそれぞれがどのように計算されているのか
https://discuss.cryosparc.com/t/tight-corrected-and-loose-gsfsc-curves/201/5

# マスク関係
## Volume ToolsのDilation RadiusとSoft padding widthの単位は pixel である
https://discuss.cryosparc.com/t/volume-tools-dilation-radius-in-a-or-pixels/4368

## マスクを作るときのsoft padding量の目安
* (現在マップが到達している分解能[Å]) x 5 / (ピクセルサイズ[Å/pixel])

https://guide.cryosparc.com/processing-data/all-job-types-in-cryosparc/local-refinement/mask-selection-and-generation-in-ucsf-chimera#importing-and-processing-the-masks-in-cryosparc
Spacemacsのmetalsで1度間違えるとsbtサブプロジェクトを永遠に紐付けなくなるのを直す

# それって
sbtのマルチプロジェクトを使っていて、

```
. topOkimochi/ <- ここで全てのサブプロジェクトをまとめている
├ nandemo/ <- サブプロジェクト: 共通で使うやつはなんでもぶち込んでやるぜ～
├ okimochiApi/ <- サブプロジェクト: nandemoを使う
└ okimochiLogic/ <- サブプロジェクト: okimochiApiを使う
```

- ふつうに使ってれば `okimochiLogic`のscalaファイルを開いた時metalsによるビルドが始まって `okiomchiApi`や `nandemo`への定義ジャンプとかが効くようになる
- たまに `okimochiLogic`のファイルを開いた時にmetalsから "New sbt workspace detected"みたいなことを言われて詰む
  - うっかり `build import`すると `okimochiLogic`が `topOkimochi`と無関係の独立したプロジェクトのように扱われてしまう
  - 無関係扱いなので `okimochiApi`や `nandemo`への定義ジャンプは当然できず、むしろ存在しないモジュールとしてエラーが出ている
  - Spacemacsを閉じて `.bloop/`, `.metals/`, `project/`を削除して何度繰り返しても世界線は収束する (過ちが記録されているのだろうか)


# こうする
- `~/.emacs.d/.cache/lsp/.lsp-session-v1`を開いて、 `okimochiLogic`の記録を消す
  - `"/home/okimochi/develop/top-okimochi/okimochi-logic"`みたいなのがあると思う
- Spacemacsを落とす
- `~/.emacs.d/.lsp-session-v1`に同じ記録があったらそれも消す
- `okimochiLogic/`から `.bloop/`, `.metals/`, `project/`を消す
  - 「待ってくれprojectは要るんだ！」なら `project/metals.sbt`と `project/project/`を消せばいいかも
- Spacemacsを再び起動する
- まず `topOkimochi`のファイルを開いてmetalsにビルドさせる
- そして `okimochiLogic`のファイルを開いてmetalsにビルドさせる

たぶんnew sbt projectとか言われず紐付いてくれる


# べつに
- SpacemacsだからとかではなくEmacsならそうかも
- キャッシュが切れる頃にはふつうに直ってるのかも (なお待つ時間はない模様)
- 1回目にnew sbt project扱いされる原因は結局特定してない
- 直せなかったらごめんて
Nuxt Composition Api x TypeScript で親子コンポーネント間で computed を使って双方向バインディングする

2年前に Vue.js を触ったときに computed で双方向バインディングを実装した覚えがあったけど、
完全に抜けてたし、Composition Api x TypeScript は初めてだったので、未来の自分のために備忘録を残します。

# 実際のコード
親コンポーネントでは,`v-model` にリアクティブな値を渡す。

```vuejs:親コンポーネント
<template>
  <div>
    <TextForm v-model="value" />
  </div>
</template>

<script lang="ts">
import {defineComponent, ref} from '@nuxtjs/composition-api';

export default defineComponent({
  components: {
    TextForm
  },
  setup() {
    const value = ref(10);
    return {value}
  }
});
</script>
```

子コンポーネントでは、
1. 親から`v-model`で渡された値は、`props.value`で受け取れる。
2. `setup()` の引数で `emit` を指定する。
3. `computed` で、`value`の `getter/setter` を用意する。
4. `setter` で `emit` する。
5. `computed` の値を `<input>` の `v-model`にわたす。


```vuejs:子コンポーネント
<template>
  <label>
    <input v-model="v">
  </label>
</template>

<script lang="ts">
import {computed, defineComponent} from '@nuxtjs/composition-api';

export default defineComponent({
  name: 'TextForm',
  props: {
    value: {
      type: Number,
      default: 0
    },
  },
  setup(props, {emit}) {
    const v = computed({
      get: () => props.value,
      set: (newValue) => {
        emit('input', newValue);
      }
    });
    return {v};
  }
});
</script>
```

ちなみに、今回 `value` の型が `number`で、`setter`の引数も `number` として推論されるのですが、
フォームを一度空にしたり、マイナスの値を入力しようとすると、一時的に `string`型が渡されエラーを吐きます。
なので、以下の通り型指定をして、対応しました。

```vuejs:子コンポーネント
<script lang="ts">
... 中略　...
  setup(props, {emit}) {
    const v = computed({
      get: () => props.value,
      set: (newValue: number | '' | '-' | '.') => {
        const number = parseFloat(String(newValue));
        if (!Number.isNaN(number)) {
          emit('input', number);
        }
      }
    });
... 中略 ...
</script>
```

# 参考
[【Vue】Avoid mutating a prop directlyエラーの発生原因と対処法](https://qiita.com/shizen-shin/items/ec05071140b9d5d7d31a)
【Cogntio】AdminGetUser APIはUsernameにEmailを指定しても取得できる！

## ■前提

- Amazon CognitoのUser Poolを使用
- ユーザーには`Email` + `Password`でサインアップ/サインインさせるように設定。
![スクリーンショット 2021-09-16 15.35.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434874/3ccb5b57-852b-3670-5204-6d8ea08a1345.png)


## ■AdminGetUser APIについて
AdminGetUser APIは、管理者権限でCognito UserPoolから指定したユーザーの情報を取得するAPIです。
詳しくは公式ドキュメントを御覧ください。

https://docs.aws.amazon.com/ja_jp/cognito-user-identity-pools/latest/APIReference/API_AdminGetUser.html

>Request Syntax
{
   "Username": "string",
   "UserPoolId": "string"
}

↑の通り公式ドキュメントには、「リクエストには`Username`を指定してクレメンス」となっています。

## ■AdminGetUser APIで困ったこと
私は「UsernameじゃなくてEmailでユーザー情報を取得したいんよな」と困っていました。
![スクリーンショット 2021-09-16 15.47.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434874/5b23e3b9-831d-6fc4-a308-309e1b459df2.png)


## ■結果
試しにUsernameにEmailを指定して実行してみた結果、、

```
{ ["data":"Aws\Result":private]=> array(7) { ["Username"]=> string(36) 以下略
```


なんと期待したレスポンスが返ってきてくれました。やったぜ。

なので、AdminGetUser APIの**UsernameにEmailを指定しても実行できます**。

公式ドキュメントにそれっぽいことが書かれていなくても、とりあえず試してみることが大事だなと学びました。
Virtual98をmtoolsでアクセスしてみる

LUNAやってた頃にちょっといじっていたmtoolsは今でも健在で、FreeBSDのパッケージにあります。mtoolsはMS-DOSのフロッピーやディスクイメージのファイルを操作するコマンドのコレクションです。mtoolsでVirtual98のイメージをアクセスしてみます。

Windows上にはNDやDiskExplorerというアプリがありイメージを開く事ができますが、イメージをコピーしてファイルの操作をするのが面倒になりました。

/usr/local/etc/mtools.confに以下を追加します。

```
drive m: file="/tmp/dos33d.hdd" offset=102620 MTOOLS_SKIP_CHECK=1
drive n: file="/tmp/win31.hdd" offset=102620 MTOOLS_SKIP_CHECK=1
```

MTOOLS_SKIP_CHECKしないとエラーがでます。MS-DOS 3.3DとMS-DOS 5.0Aでエラーが違っていて、ソースコードを眺めていてこのオプションがあることに気がつきました。ちゃんとチェックが通るように直すべきなんでしょうが、とりあえずはこれで試します。

PC-9801のMS-DOS(FAT16)は1シリンダーから始まっていて、offsetは25(セクター/トラック)*8(ヘッド)*512+220(Virtual98ヘッダー)になります。

mdirを実行してみます。

```
% mdir m:
 Volume in drive M has no label
Directory for M:/

COMMAND  COM     24931 1991-11-08   0:00 
DOS          <DIR>     2021-09-12   6:38 
MENU     MNU      3232 1991-11-08   0:00 
SETUP    DEF      6207 1991-11-08   0:00 
README   DOC      3479 1991-11-08   0:00 
README2  DOC      2897 1991-11-08   0:00 
NECAI    SYS    664576 1991-11-08   0:00 
NECDIC   SYS    578560 1991-11-08   0:00 
MATU         <DIR>     2021-09-13  10:10 
CONFIG   NEC       143 2021-09-12   6:41 
UT           <DIR>     2021-09-13  10:06 
GO2DD    EXE      2367 1993-03-30  13:02 
WORK         <DIR>     2021-09-13  15:08 
CONFIG   BAK        86 2021-09-13  10:18 
AUTOEXEC BAK        50 2021-09-13  10:08 
AUTOEXEC BAT        58 2021-09-13  10:17 
MATU     SYS        35 2021-09-13  14:47 
MATU     BAK        86 2021-09-13  14:46 
CONFIG   SYS        52 2021-09-13  14:46 
MA       BAK        33 2021-09-13  14:48 
MA       BAT        35 2021-09-13  14:50 
       21 files           1 286 827 bytes
                         31 309 824 bytes free

% mdir n:
 Volume in drive N has no label
 Volume Serial Number is 2B0B-1811
Directory for N:/

COMMAND  COM     48402 1992-11-11   0:00 
DOS          <DIR>     2021-09-11  16:44 
CONFIG   OLD       332 2021-09-11  17:12 
README   DOC      3109 1992-11-11   0:00 
README2  DOC      7575 1992-11-11   0:00 
SETUP    DEF      6207 1992-11-11   0:00 
NECAI    SYS    660480 1992-11-11   0:00 
AUTOEXEC OLD        94 2021-09-11  16:48 
GO2DD    EXE      2367 1993-03-30  13:02 
WINDOWS      <DIR>     2021-09-11  16:52 
CONFIG   B~K       345 2021-09-11  17:12 
AUTOEXEC B~K       129 2021-09-11  17:12 
PIFDAT       <DIR>     2021-09-11  17:13 
SB16         <DIR>     2021-09-11  17:16 
EN298P   SYS      8091 2021-04-05  22:49 
NET          <DIR>     2021-09-11  18:37 
MUSMAGIC     <DIR>     2021-09-11  17:26 
MIFES        <DIR>     2021-09-11  17:49 
CCT          <DIR>     2021-09-11  18:07 
WORK         <DIR>     2021-09-11  18:41 
CONFIG   BAK       498 2021-09-11  18:15 
UT           <DIR>     2021-09-13   8:08 
EXCEL4       <DIR>     2021-09-12   7:20 
AUTOEXEC XL4       444 2021-09-11  18:40 
CONFIG   SYS       522 2021-09-11  18:37 
AUTOEXEC BAK       453 2021-09-12   7:30 
AUTOEXEC BAT       460 2021-09-13   8:10 
       27 files             739 508 bytes
                         51 302 400 bytes free
```

これでファイルのコピーもFreeBSD上で完結できます。

/usr/local/etc/mtools.confは~/.mtoolsrcでも設定できました。

xmodemでの転送だと21分くらいかかるファイル転送がmcopyで1秒もかからずコピーできます。すばらしいです。
【Rails】TypeError (nil can't be coerced into Integer):の対処法

<h2>症状</h2>
RailsAPIモードでメソッド作成し叩いたところ、以下のエラーが表示されてしまいました。

翻訳すると、「TypeError（nilを整数に強制変換することはできません）：」でした。
nilを整数に変換しようとして、失敗しているようです。

```terminal:error
Completed 500 Internal Server Error in 21ms (ActiveRecord: 0.4ms | Allocations: 18292)



TypeError (nil can't be coerced into Integer):

app/controllers/hoges_controller.rb:112:in `+'
app/controllers/hoges_controller.rb:112:in updateHoge
```

該当のメソッドは以下です。

paramsからidを受け取り、DBからHogeを検索。
その検索したHogeのvaluationとparamsからvaluationを受けとり、その二つの値の平均値を再度Hogeに更新するメソッドです。

```ruby:Hoge.rb
def  updateHoge
  hoge = Hoge.find(params[:hoge_id])

  newValuation = hoge.valuation + params[hoge_valuate]
  newValuation = newValuation / 2  

  if hoge.update!(:valuation newValuation)
    render json: {
      hoge: hoge
    },status: :ok
  else
    render json: {},status: :ng    
  end
end
```

<h2>解決方法</h2>
paramsで受け取るときの指定先を修正したら、解決しました。
paramsから受け取るときに指定先が間違っていると「nil」になり、nilとintegerの値を足そうとしていたため、エラーになっていました。

```ruby:Hoge.rb
def  updateHoge
  hoge = Hoge.find(params[:hoge_id])

  //integer + nilになっているためエラーだった
  newValuation = hoge.valuation + params[hoge_valuation]
  newValuation = newValuation / 2  

  if hoge.update!(:valuation newValuation)
    render json: {
      hoge: hoge
    },status: :ok
  else
    render json: {},status: :ng    
  end
end
```
unicorn起動時の凡ミス（bundler: failed to load command: unicorn_rails）

#はじめに
AWSでポートフォリオをデプロイする事ができました。

デプロイするのに様々なエラーがあったので復習のために投稿します。

今回はunicorn起動時に起きたエラーです。

#bundler: failed to load command: unicorn_rails

```:EC2内
[ec2-user@ip-10-0-0-53 <リポジトリ名>]$ bundle exec unicorn_rails -c /var/www/rails/アプリ名/config/unicorn.conf.rb -D -E production
```

このようにEC2内で起動コマンドをしました。

```:EC2内
bundler: failed to load command: unicorn_rails (/home/ec2-user/.rbenv/versions/2.6.5/bin/unicorn_rails)

rubygems_integration.rb:364:in `block in replace_bin_path': can't find executable unicorn_rails for gem unicorn. unicorn is not currently included in the bundle, perhaps you meant to add it to your Gemfile? (Gem::Exception)
```

1つづつエラーを見ていきます。

```
bundler: failed to load command: unicorn_rails (/home/ec2-user/.rbenv/versions/2.6.5/bin/unicorn_rails)
```

**コマンドの読み込みに失敗しました：unicorn_rails**
これは単純に何かのエラーで読み込めませんでしたよと言われています。
もう1つのエラーが原因が記述されています。

```
rubygems_integration.rb:364:in `block in replace_bin_path': can't find executable unicorn_rails for gem unicorn. unicorn is not currently included in the bundle, perhaps you meant to add it to your Gemfile? (Gem::Exception)
```

<a href="https://gyazo.com/cffaaa71f844eb27518204899c6fe41e"><img src="https://i.gyazo.com/cffaaa71f844eb27518204899c6fe41e.png" alt="Image from Gyazo" width="1089"/></a>

和訳サイトで確認すると強気な和訳が返されました（笑）

単純にgemをインストールしてないだけでした。

#確認作業

gemのディレクトリーを確認します。

```:EC2内
[ec2-user@ip-10-0-0-53 <リポジトリ名>]$ vi Gemfile
```
テキストエディター開くコマンドで確認することができます。

```:Gemfile

#省略

gem 'pry-rails'

gem 'kaminari'

gem 'ransack'

gem 'gretel'

```
1番下には記述されていませんでした。

ここで記述していきます。

iコマンドを押すと記述できるようになります。

```:Gemfile
group :production, :staging do
    gem 'unicorn'
end
```

記述した後**:wq**で編集完了。

```:EC2内
[ec2-user@ip-10-0-0-53 <リポジトリ名>]$ gem install bundler
[ec2-user@ip-10-0-0-53 <リポジトリ名>]$ bundle install
```

すでにunicornの設定はできているので、最初の起動コマンドを押して起動します。

#最後に
慎重にやっていたらミスらないと思うので確実にこなしていきたいと思います。
Workato：Input schemaやOutput schemaのArrayやObjectにStringやInteger等のフィールドをネストするには

Workato初心者がつまづくことの１つに、ArrayやObject内のStringやIntegerのフィールドはどのように定義すれば良いのか分からない（StringやIntegerをArrayやObjectにネストする方法が分からない）、というものがあります。対応方法について、以下に記載します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/c6e3ea94-b6a1-5005-b160-8a05eea4462d.png)

# 対応方法

対応方法は非常にシンプルで、以下のようにArrayやObjectの下にドラッグ＆ドロップします。
ドラッグ＆ドロップされたフィールドは、指定されたArrayあるいはObjectの配下にネストされた状態になります。

![workato-object-nest.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/1df4ad53-7f59-b162-e11f-4a31b5c9d677.gif)
Node.js非同期処理について超簡略サンプル


以下のNodeを実行すると、順番がぐちゃぐちゃになる。

```junban.js
function output ( txt){
  console.log("関数処理始まり"); //出力
  setTimeout(function(){ console.log('hoge') }, 1000)
  console.log(txt); //出力
  console.log("関数処理終わり"); //出力
};

async function main(){
　　console.log('読み込み前');
　　await output('処理')
　　console.log('読み込み後');
}
main()
```


```bash
$ node junban.js
読み込み前
関数処理始まり
処理
関数処理終わり
読み込み後
hoge
```

この状態ではawaitは効かない。
`return new Promise`を使うと、結果は返ってくる。


```js
function output (txt){
   return new Promise((resolve, reject) =>{
      console.log("関数処理始まり"); //出力
      setTimeout(function(){ console.log('1秒待つ') }, 1000)
      setTimeout(function(){ resolve('更に待つ') }, 1000)
      console.log(txt); //出力
      console.log("関数処理終わり"); //出力
  })
};

async function main(){
   console.log('読み込み前');
   result = await output('処理')
   console.log('result :', result);
   console.log('読み込み後');

}
main()

```

resolveがreturnと同じような戻り値になる。
なんか関数内の動きがめっちゃ変だけど…。
EC-CUBE4.xのオリジナルテンプレートでカスタマイズcss / jsを反映させる方法

## 概要

EC-CUBE4.xでオリジナルテンプレートを使用する際、管理画面から設定できる

- customize.css
- customize.js

が反映されない場合の対処法メモ書きです。

### 開発環境

- EC-CUBE4.x＋Git＋scss
- オリジナルテンプレートを使用


### 参考文献

- [公式ドキュメント：CSSの利用](https://doc4.ec-cube.net/design_css)
- [Qiitaでシンタックスハイライト可能な言語一覧](https://qiita.com/Qiita/items/e84f5aad7757afce82ba)
- [Qiita Markdown 書き方 まとめ](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1)
- [40言語で「Hello World」をやってみよう！！](https://www.microstone.info/helloworld/)


## 一般的な使い方

通常、管理画面から独自のcss/jsを編集→登録した際は、下記パスにファイルが更新されます。

- css管理：コンテンツ管理 > CSS管理
![スクリーンショット 2021-09-16 13.11.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76115/d74ff57c-1c7b-e0f3-3f86-9ca325d29634.png)

> html/user_data/assets/css/customize.css

- JS管理：コンテンツ管理 > Javasctipt管理
![スクリーンショット 2021-09-16 13.12.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76115/4b4dd91e-0ac9-4ed7-59ad-377037fd6edc.png)

> html/user_data/assets/js/customize.js

この場合、指定テンプレートに関係なく反映される形になるのですが、独自のテンプレートを使っている場合はデフォルトテーマと挙動が異なるパターンももちろんあるため、テンプレート独自のCSS/JSを実装する必要が出てきます。


## 独自テンプレートへの適用：CSS（SCSS）

`customize.css` の内容をコピペして下記に貼り付ける形が良さそうです。

> html/template/[テンプレート名]/assets/scss/style.scss


![スクリーンショット 2021-09-16 13.23.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76115/10776574-ba5f-f0b1-b175-883cfee35bcf.png)

@importで下層scssを読み込んでいるので、最後部に追記することで優先反映されるようになります。


## 独自テンプレートへの適用：JS

> html/template/vvstore/assets/js/function.js

にコピペします。
デフォルトでjquery構文が記載されているので、それと分離させて記述してください。