OmniAICreator/Qiita-1.07M huggingface dataset:
NCBIのGenome assemblyから元となったSRAデータのBioProject IDを取得する

# entrez direct　インストール

EntrezにLinuxっぽいコマンドを使ってアクセスできる様になる。

色々手法が出ているけど、そんなに大変でないので直接ftpでバイナリをとってきて、
パスを通すのが良いと思う（2021/09/22現在）
うっかりforとかで回すと、IP（研究機関）ごと遮断されかねないので、注意して使うこと。

```
perl -MNet::FTP -e '$ftp = new Net::FTP("ftp.ncbi.nlm.nih.gov", Passive => 1); 
$ftp->login; 
$ftp->binary; 
$ftp->get("/entrez/entrezdirect/edirect.tar.gz");'
```

# IDに対応するBioProjectを取得

以下のコードのID部分を変更するとProjectIDがとれるのでそれを使う。

```
esearch -db assembly \
 -query "ID_A OR ID_B" | \
efetch -format docsum | \
xtract -pattern DocumentSummary -element AssemblyAccession BioprojectAccn

```

例

```
esearch \
-db assembly  \
-query "GCA_015500005.1 OR GCA_015679545.1 OR GCA_015849335.1" | \
efetch -format docsum | \
xtract -pattern DocumentSummary -element AssemblyAccession BioprojectAccn
```
Flutterで、通信処理を行う

前回の記事で、[Flutterで、JSONを処理する](https://qiita.com/shimizu-you/items/f9197719557b258839b2)を記事にしたのですが、それをベースに通信処理を行いたいと思います。

### JSONサーバーの準備

[My JSON Server](https://my-json-server.typicode.com/)を使用します。
こちらは、自分のGithubにjsonを用意することで、jsonのレスポンスを取得出来るサービスです。
特にサーバを用意することなくJSONのレスポンスを受け取れるので、非常に便利です。

まず、自分のGithubにpublicなリポジトリを用意します。
そこにdb.jsonファイルを作成します。Github上では、[Add file -> Create new file]で作成出来ます。

```json:db.json
{
  "gets": [
    {
        "userId": 1,
        "id": 1,
        "title": "user 1",
        "completed": false,
        "_type": null
    },
    {
        "userId": 2,
        "id": 2,
        "title": "user 2",
        "completed": true,
        "_type": "type"
    }  
  ],
  "posts": [
    { "id": 1, "title": "Post 1" },
    { "id": 2, "title": "Post 2" },
    { "id": 3, "title": "Post 3" }
  ]
}
```

GETやPOSTで取得出来るjsonを定義します。
[Postman](https://www.postman.com/)などで試せます。
取得方法は、下記をベースに取得します。

```
https://my-json-server.typicode.com/[ユーザ名]/[リポジトリ名]
```

GETの場合、下記のURLで取得できます。

```
https://my-json-server.typicode.com/[ユーザ名]/リポジトリ名/gets/1
```

### Flutterの実装

通信プラグインは、[dio](https://pub.dev/packages/dio)を使用します。

```yaml:pubspec.yaml
dependencies:
  json_annotation: ^4.1.0
  dio: ^4.0.0
```

```dart
class Network {
  final Dio _dio = Dio();

  Network() {
    _dio.interceptors
        .add(LogInterceptor(requestBody: true, responseBody: true));
  }

  Future<User?> getUser() async {
    try {
      Response response = await _dio
          .get("https://my-json-server.typicode.com/you-shimizu/test/gets/1");
      return User.fromJson(response.data);
    } catch (error) {
      print(error);
    }
    return null;
  }
}
```

Androidの場合、下記も忘れずに

```xml:AndroidManifest.xml
    <uses-permission android:name="android.permission.INTERNET" />
```
【初級編】CSSを書くときに徹底している事

表題の件をまとめ。

###1. style= は死んでも書かない。

　①可読性を殺す
　②重複だらけでみっともない
　③子要素や妹要素に影響を与えない

　可読性の要らない極小のDHTMLで、今後絶対に修正しない箇所でもない限り、欠点だらけの style= は書かない。（で、そんなDHTMLを公開する事はない。）
　「取り急ぎ」で用いたとしても十中八九、後で class= などに書き換えるのだから、最初から class= を使う。

###2. id= は極力減らす。

　idの割り振りは、javascriptで getElementById を適用する用途に限る。
　jsで呼び出さない限り id= は使わず、 class= で代替する。

```html
<style>#hoge,#fuga{width:100%;}</style>
```
　↑のような書き方も↓のように早めに修正しておく。

```html
<style>.hoge{width:100%;}</style>
<.. id=hoge class=hoge><.. id=fuga class=hoge> 
```

###3. class= も極力減らす。

　例えば↓こんな書き方は非常に馬鹿馬鹿しい。ファイルサイズの面でも、メンテナンス性も最悪。5個目に新しい li を割り込ませたら6,7..30個目も全部書き直すの？？？

```html
<style>li.a{color:#300;}li.b{color:#003;}</style>
<ul>
<li class=a><li class=b><li class=a><li class=b>...
</ul>
```
　最初からこうしておく↓

```html
<style>
.aorb>*{color:#003;}.aorb>*:nth-of-type(2n){color:#300;}
</style>
<ul class=aorb>
<li><li><li><li>...
</ul>
```
　アンチflexbox（..あんなメンヘラに振り回されたくないよね。）勢にはこんなやり方も。↓

```html
<style>
li{float:left;}
.w25,.w25+li,.w25+li+li,.w25+li+li+li{width:25%;}
.w50,.w50+li{width:50%;}
.w100{width:100%;}
</style>
<ul>
<li class=w50>50<li>50
<li class=w25>25<li>25<li>25<li>25
<li class=w25>25<li>25<li>25<li>25
<li class=w25>25<li>25<li>25<li>25
<li class=w100>100
</ul>
```

###4. 要素ではなく属性値をベースにする。


```html
<style>
.c1001{position:absolute;top:0;left:0;width:50%;height:30%;}
.c1002{position:absolute;top:30%;left:0;width:50%;height:70%;}
.c1003{position:absolute;top:0;left:50%;width:50%;height:30%;}
.c1004{position:absolute;top:30%;left:50%;width:50%;height:70%;}
</style>
```
　半年ぶりに読んで全容を把握し易いのは、↑前者より↓後者。

```html
<style>
/*rule*/body>*{position:absolute;}
/*y*/.c1001,.c1003{top:0;height:30%;}.c1002,.c1004{top:30%;height:70%;}
/*x*/body>*{width:50%;}.c1001,.c1002{left:0;}.c1003,.c1004{left:50%;}
</style>
```

###5. 予め数値化しておく。

　日々、頻繁に書いている属性値は数値クラスで管理して毎回コピペが便利。
　その属性値を当てたいタグネームやID、亜種クラスも、.c**の右に足して行き、公開前に要らない行だけ削除。

```css
*{margin:0;padding:0;box-sizing:border-box;
font-family:'Meiryo';transition:.7s;
scroll-behavior:smooth;}
ul{list-style:none;}i{font-style:normal;}
a,u,s{text-decoration:none;}

.c10{display:none;}
.c11{display:block;}
.c12,b,i,u,s,li{display:block;float:left;}
.c13{display:inline-block;}
.c14{opacity:0;pointer-events:none;}
.c15{position:fixed;}
.c16{position:absolute;}
.c17{position:sticky;}
.c18{position:relative;}
.c15,.c17,.c19{z-index:2;}
.c20{width:auto;}
.c21,.c35{width:100%;}
.c22{width:50%;}
.c23{width:33.33%;}
.c24{width:25%;}
.c25{width:20%;}
.c26{width:16.66%}
.c27{text-align:left;}
.c28{text-align:center;}
.c29{text-align:right;}
.c30{height:0;}
.c31{height:100%;}
.c32{height:auto;line-height:25px;}
.c33,.c34,.c35{height:30px;line-height:30px;}
.c34{width:30px;}
.c36{overflow:hidden;}
.c37{overflow:scroll;}
.c38{white-space:nowrap;overflow-x:scroll;overflow-y:hidden;}
.c39{overscroll-behavior:none;}

```
Azure AD B2Cにカスタムドメインを適用する

# はじめに
以前から認証基盤にAzure Active Directoryを採用してきたのですが、最近、B2C向けだけではなく、B2B向けにも「Azure Active Directory B2C」を利用することが多くなってきました。
ここで課題になっていたカスタムドメインの適用について、試していこうと思います。

手順としては以下のステップです。

1. Azure AD B2CテナントのAzure ADにカスタムドメインを適用する
1. Front Doorを設定する
1. BLOBにCORSを設定する（Azure AD B2CでカスタマイズされたHTMLを利用している場合）

## カスタムドメインの適用
Azure AD B2Cのテナントにログインし、「Azure Active Directory(**Azure AD B2Cではない**)」を選択後、メニューから「カスタムドメイン名」、「カスタムドメインの追加」と順にクリックしていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226944/696ce7b1-1b8f-f1ea-a3c0-dd980ccdfc8a.png)

カスタムドメイン入力後、「ドメインの追加」をクリックすると、DNSサーバーへ登録する情報が表示されます。DNSサーバーでは、「TXTレコード」か「MXレコード」で表示された情報で登録して下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226944/ba95e7b0-09fe-c172-6116-84b51eeb2c4a.png)

DNSサーバー登録後は「確認ボタン」をクリックします。
一覧に戻り、登録したカスタムドメインが「確認済み」の状態になります。
**確認済みになったら、DNSサーバーから追加した「TXTレコード」または「MXレコード」を削除します。**

## Front Doorの設定
カスタムドメインを利用するには、Azure AD B2Cの前にFront Doorを配置する必要があります。
ポイントは「バックエンドプールの作成」と「カスタムドメインの追加」となります。

### バックエンドプールの作成

以下の入力し、その他はデフォルトのままとします。

- バックエンド ホストの種類：カスタムホスト
- バックエンド ホスト名：Azure AD B2Cの名前（{tenantName}.b2clogin.com）
- バックエンド ホスト ヘッダー：バックエンド ホスト名と同じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226944/32f6d463-3f95-0f92-3c36-72e2d0a0f7b3.png)

また、バックエンドをバックエンドプールに追加後、「正常性プローブ」を「無効」にします。

その後、「ルーティング規則」を設定し、「カスタムドメインを追加」します。

### カスタムドメインの追加
以下の情報でDNSサーバーにCNAMEでレコードを作成します。

- カスタムドメイン名
- FrontDoorデフォルトドメイン({frontDoorName}.azurefd.net)

DNSサーバーにレコードを作成後、カスタムドメインをFront Doorに設定します。
「カスタム ホスト名」を設定し、カスタムドメインHTTPSを有効にします。（その他はデフォルト）
DNSサーバーに対してカスタムドメインの検証が実行され、その後登録が可能となります。
尚、検証から証明書の適用までにそれなりに時間がかかりますので、気長に待ちます（20分くらい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226944/47ecc7e9-25f3-bcd0-3f43-876d18544173.png)


カスタムドメイン追加後は、「ルーティング規則」の「フロントエンドまたはドメイン」で追加したカスタムドメインに変更します。

## BLOBへのCORSの設定
HTMLやCSS等の静的コンテンツにより、B2CのUIをカスタマイズする場合のみ必要となり、該当のストレージアカウントにて、CORSの設定を行います。

メニューから「ソースの共有 (CORS)」を選択後、Blob Serviceで以下を設定します。

- 許可されたオリジン : https://カスタムドメイン
- 許可されたメソッド : GET/OPTIONS
- 許可されたヘッダー : *(アスタリスク)
- 公開されるヘッダー : *(アスタリスク)
- 最長有効期間 : 200 

## 検証
B2Cの実行ウィンドウで「ユーザー フロー エンドポイントを実行」のURLを変更したカスタムドメインに変更して、ブラウザで実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226944/2176455a-71e5-20fe-4e75-5d54bca7d72a.png)

無事、カスタムドメインでB2Cの画面が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226944/9eb25a39-e159-5a85-496c-b638aec1b970.png)

## まとめ
B2Cのカスタムドメイン化は実現できたので、次回はWeb AppsのEasyAuthやAngularやAPIなどに適用を検証してみたいと思います。

## 関連記事
* [AD B2C記事まとめ](https://qiita.com/AsukaSeki/items/46afb6846cb4057b8050)
表計算ソフトからDataikuにシフトすることの課題と（素晴らしい）ベネフィット


2年ほど前、そろそろDataikuを使いこなそうと思いました。しばらくの間、Dataikuのマーケティング・コンテンツ・チームの一員として働いていたので、もちろんソフトウェアについては高いレベルで熟知していましたが、その時点では、私の仕事で洞察を得るためにDataikuを使用する必要はなく、ただ消費するだけでした。でも興味は持っており、学びたいと思っていました。そして、かなり厄介なビデオマーケティングデータのかたまりという形で機会がやってきて、私はこの機会に飛びつきました。Dataikuユーザーとしての私の旅が始まったのです。
 
技術者ではない多くのビジネスユーザーと同様に、私のデータ操作の経験は、Microsoft Excelを適度に使用する程度でした。Dataikuを使い始めたとき、私はその興奮と不満について書き記しました。そして今回、そのときよりは経験豊富なユーザーとして、スプレッドシートからDataikuへの移行中に発見した主な課題とわくわくするベネフィットをいくつか（ブログシリーズの形で）共有しようと思いました - そして、なぜこれらのベネフィットが当初の課題を完全に上回るものであったか、についてを。 
![prepare-recipe-explore.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196881/cbad8e29-cb6e-6e72-e1cf-645e9096b3be.png)


##課題: なぜこのセルに入力できないのか?
私がDataikuを使い始めて最初に苦労したことは（私だけではないと思いますが）、Dataikuのデータセットはスプレッドシートではないので、スプレッドシートのようにセルを編集することはできないということを理解し、慣れることでした。
 
表計算ソフトでは、データを変換したりエンリッチメントしたりするために、表計算ソフトのセルに直接データポイントを入力したり、置き換えたり、計算処理をしたりしますが、Dataikuでのデータ変換は、データセットに作用する変換ロジック、またはコマンド（「ステップ」とも呼ばれる）を含むレシピによって実現されます。

恥ずかしながら、Dataikuを使い始めて最初の30分ほどは、データセットのセルをクリックして入力しようとしていました。おそらく、雑誌のページをタッチスクリーンのように「スワイプ」しようとする子供のバイラルビデオのように見えたのではないかと思います。しかし、最初は困難に思えたことも、最終的には非常にありがたいベネフィットとなりました。

##ベネフィット: 視覚的にデータ処理ができる世界、データ損失の懸念はなし
レシピを作成したり、設定を変更したり、変換ステップを追加したりしてデータを準備することに最初は違和感がありましたが、スプレッドシートでは考えられなかったほど高度で効率的な方法でデータを準備することができました。通常のソート、フィルタリング、新しいカラムの計算から、[複雑な地理空間データの処理](https://knowledge.dataiku.com/latest/kb/analytics-ml/geospatial/index.html)、[テキストデータからパターンを抽出する](https://knowledge.dataiku.com/latest/courses/advanced-data-prep/prepare-recipe/smart-pattern-builder.html)ための正規表現の使用まで、Dataikuのビジュアル化されたデータ準備インターフェースのコツを掴めば、不可能なことは何もないように思えました。

一番良かった点は？すべての変換がレシピ設定に記録され、変換前のデータセットがそのまま残っているので、データやプロセスが失われることはありませんでした。Dataikuと扱いにくいスプレッドシートとの主な違いは、データに変換を適用する際に、元の（または入力した）データセットがワークフローで利用可能なままであるということです。レシピでは「出力」データセットを作成するので、元のデータを失う心配をすることなく多くのさまざまな変換処理を適用することができ、また、簡単に以前のバージョンに戻ることができます。

スプレッドシートで "失敗 "してパニックになり、必死になって以前のバージョンに戻そうとしていた時代は終わりましたが、同時にどうしてそうなっていたのかも忘れていました。私のように、仕事でもプライベートでも、そろそろスプレッドシートを卒業したいと感じている方は、Dataiku Academyの新しい[Excel to Dataiku Quick Start](https://academy.dataiku.com/excel-to-dataiku-dss-quick-start/)コースをチェックしてみてください。次回は、スプレッドシート廃止後の私の生活について、より詳細な情報をお伝えします。

<br>
原文：[*The Challenges and (Awesome) Benefits of Switching From Spreadsheets to Dataiku*](https://blog.dataiku.com/spreadsheets-to-dataiku)

<font color="DarkCyan">**高度にビジュアル化されたGUIで、データサイエンティストやデータエンジニア、ビジネスアナリストなど、あらゆるタイプのユーザー様にお使いいただけるツールDataikuを、せひ一度ご覧ください！**</font>
[**Dataikuのデモはこちら**](https://play.vidyard.com/Nr3wYUrfGZETaQd2LWJsVw)
ngrokの開発環境をDockerで構築する

# 用途
ngrok、非常に便利です。
ただ、新しい開発機を買った時など環境構築が若干面倒なのでdockerで動かせるようにしました。
あまりないとは思いますが、ngrokを使った開発環境をシェアしたい時などにも使えると思います。


# 用意するもの

- dockerをインストールしておく

https://www.docker.com/

- ngrokのアカウント
    - authtokenを取得しておくこと

# Dockerfile
ローカルで動かす[Firebase Local Emulator](https://firebase.google.com/docs/emulator-suite?hl=ja)のCloudFunctionsをhttpsで外部公開したかったので、その目的に則した構成になっています。

```dockerfile
FROM ubuntu:21.04

RUN apt-get update -y

# Install Java
RUN apt-get install -y curl openjdk-11-jre-headless

# Install Node JS
RUN curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh \
    && bash nodesource_setup.sh \
    && apt-get install nodejs

# Install ngrok
RUN apt-get install -y unzip wget
RUN wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
RUN unzip ngrok-stable-linux-amd64.zip\
    && mv ./ngrok /usr/bin/ngrok
RUN ngrok authtoken YOUR_NGROK_AUTHTOKEN # 自分のトークンに書き換えてください

# Install npm
RUN npm i -g npm

# Install firebase
RUN npm install -g firebase-tools

# Clean
RUN apt-get clean \
 && rm -rf /var/lib/apt/lists/*

```

# package.json

startスクリプトの内容は適宜書き換えてください。
ここでは以下を行なっています。

- functionsディレクトリを監視＆ビルド
- 5001番ポートをngrokでドメイン指定して公開
- firebase emulatorsを起動 (functionsサーバーが5001番ポートで立ち上がる)

ngrokのドメイン指定は課金が必要ですが、無課金・指定なしでも利用できます。
（その場合、立ち上げるごとにランダムな文字列がドメインとして与えられます）

```json
{
  "name": "YOUR_APP_NAME",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "cd functions && yarn build -- --watch | ngrok http -region=jp -hostname=YOUR_DOMAIN.jp.ngrok.io 5001 | firebase emulators:start --only functions",
  },
  "dependencies": {
  },
  "devDependencies": {
  }
}

```

# 起動コマンド
`npm start`

YOUR_DOMAIN.jp.ngrok.io　にリクエストを飛ばせば、localhostと同じように機能します。

ドメイン未指定の場合、上記のスクリプトだと割り当てられたドメインが分からないと思うので、スタートスクリプトの内容を以下に変更してください、
`"cd functions && yarn build -- --watch | firebase emulators:start --only functions | ngrok http -region=jp -hostname=YOUR_DOMAIN.jp.ngrok.io 5001"`
動画で学ぶJHipster (7) 閲覧権限を修正

# 参考動画
https://www.youtube.com/watch?v=6lf64CctDAQ

# お互いの投稿が見えてしまうことを修正。

admin はadminの投稿だけ、userはuserの投稿だけ見えてほしいが、現状では、お互いが、お互いの投稿が見えてしまう状態である。それを修正する。

* Adminでログインした場合 (修正前)
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/0941caa1-f480-6512-796d-63486e447c61.png)
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/23fb1874-3e85-a9a5-28d6-63ac8d5b3e9a.png)
* Userでログインした場合 (修正前)
![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/5975c7ee-cc0a-c872-8f3d-f465dd563dc5.png)
![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/0fe86ccb-8c9f-419f-f3a7-ea284aba96e3.png)

## 修正箇所1
src/main/java/org/jhipster/blog/web/rest/BlogResource.java の getAllBlogs() メソッドを変更する。

```java:BlogResource.java
return blogRepository.findAll();
```
を

```java:BlogResource.java
return blogRepository.findByUserIsCurrentUser();
```
に変更する。
`findByUserIsCurrentUser()`は現在ログインしているユーザーのみの結果を取得するメソッド。

## 修正箇所2 
src/main/java/org/jhipster/blog/web/rest/PostResource.java の getAllPosts() メソッドを変更する。

```java:PostResource.java
Page<Entry> page;
if (eagerload) {
    page = postRepository.findAllWithEagerRelationships(pageable);
} else {
    page = postRepository.findAll(pageable);
}
```
を

```java:PostResource.java
page = postRepository.findByBlogUserLoginOrderByDateDesc(
    SecurityUtils.getCurrentUserLogin().orElse(null), pageable);
```
に変更する。
([テキスト](https://github.com/mraible/jhipster7-demo)には書いてないけど、`import org.jhipster.blog.security.SecurityUtils;`　も追加しないとエラーになる）

こうすると、

* Adminでログインした場合 (修正後)
![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/c7e64f71-025c-40b4-413f-67a860ff049d.png)
![7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/5b82c7ee-a583-9353-8d3b-3f98d276d281.png)

* Userでログインした場合 (修正後)
![6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/eea26b47-5240-2b5b-e0a2-93279f23d751.png)
![8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/f77b4f36-b430-8d2c-7e7e-a6f5006437f7.png)

各ログインユーザーは自分のブログや記事しか見れないように修正されます。

# 今回のコード
https://github.com/sayuu-tf/learning_jhipster_3/commit/3f0c149fd028ee15c8220d1430a13230175943d9
VS code 入力省略

railsyや他の言語解説動画を見ていたら、htmlを書く時に

```
nav>ul>li*5
```
と打ったのち一瞬で要素を5つ持ったリストができたりクラスやidを簡単に付与できたりと
入力の省略をしていたのですごい便利だと思いました
vscodeの拡張機能でauto close tagsみたいなのがあると思いますが、調べた限り動作が違いました
結論から言うとvscodeにもとからあるっぽい？

<h1>設定</h1>
まず左下の歯車をクリック
その後、メニューにある設定をクリック
英語のままなら、settings(だったと思う)
![スクリーンショット 2021-09-22 15.35.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1541345/d9a48bdb-bf79-8ff7-5356-6efae0ff3dec.png)
![スクリーンショット 2021-09-22 15.36.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1541345/a25e65b5-2f74-0214-9d9d-5d7e08d3a9a3.png)

検索窓にemmetと入力して検索し、
出てきた候補の中の下にある
<strong>Trigger Expansion On Tab</strong>
にチェックを入れる
![スクリーンショット 2021-09-22 15.37.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1541345/01a61bbe-353c-f1c4-576a-abc25e194fd2.png)

これで設定完了！

あとはコードを打つ時に

```
クラスなら
.container
idなら
#container
```
のようにクラス名やid名を入れることができます！
[Ruby] AtCoder過去問 B - Count Balls

##はじめに
AtCoder過去問B問題をRubyで解いてみました。
変数名の付け方が下手くそなのは目を瞑ってください。
よろしくお願いします。

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

https://atcoder.jp/contests/abc158/tasks/abc158_b

##B - Count Balls
まずは入力を受け取ります。n, a, bと順番に受け取ります。

```ruby
n, a, b = gets.split.map(&:to_i)
```

a+bを1セットとして考えます。まずはnの中に、a+bが何セットあるか調べます。
そのセット数をball_setsの中に代入しておきます。

```ruby
n, a, b = gets.split.map(&:to_i)

ball_sets = n / (a + b)
```

次にセットからはみ出した（セットにできなかった）ボールを調べます。
```n % (a + b)```ではみ出したボールの数が分かります。
変数remainder_ballに入れておきます。

```ruby
n, a, b = gets.split.map(&:to_i)

ball_sets = n / (a + b)

remainder_ball = n % (a + b)
```

続いてセットでまとめることができたボールたちの中に青いボールがいくつあるかを調べます。
a×セット数で求められます。blue_setsの中に入れておきます。

```ruby
n, a, b = gets.split.map(&:to_i)

ball_sets = n / (a + b)

remainder_ball = n % (a + b)

blue_sets = a * ball_sets
```

セットにできなかったボールに関しては、a(1セットの青いボールの数)からremainder_ballを引きます。変数cの中に入れておきます。

```ruby
n, a, b = gets.split.map(&:to_i)

ball_sets = n / (a + b)

remainder_ball = n % (a + b)

blue_sets = a * ball_sets

c = a - remainder_ball
```

もしその答えcが0よりも大きかったら、セットからはみ出たボールが全て青いボールなのでblue_setsにremainder_ballを追加して出力させます。

もしcが0以下だったら、1セットの青いボール分が全て追加されるので、blue_setsにaを足して出力させます。

```ruby
n, a, b = gets.split.map(&:to_i)

ball_sets = n / (a + b)

remainder_ball = n % (a + b)

blue_sets = a * ball_sets

c = a - remainder_ball

if c > 0
  puts blue_sets + remainder_ball
else
  puts blue_sets + a
end
```
PythonでExcelファイルを作成，書き込み

# 目次
[1.使用するライブラリ](#1-使用するライブラリ)
[2.今回作成したコードの全体](#2-今回作成したコードの全体)
[3.各コードの説明](#3-各コードの説明)
[4.実行結果](#4-実行結果)

#1. 使用するライブラリ
今回使用したライブラリは，Excelファイルを扱うのが容易なopenpyxlと，ファイル取得ができるglobです。

openpyxlは本題となるExcelファイルの作成，読み取り，書き込みに使用しますが，globはディレクトリ内のファイル名を取得するために使用します。

#2. 今回作成したコードの全体
全体の流れは以下の通りです。
・Excelファイルが同じディレクトリ内に存在していなければ指定したExcelファイル名を作成します。
・既存のExcelファイルに作成したデータを書き込みます。

```python:Excel.py
import openpyxl
import glob

# 書き込みたいデータ
Data = [[1,2,3],[4,5,6]]

# 使用するExcelファイルを選択
excel_file_name = 'Excel_test.xlsx'

# 同じディレクトリ内のファイル名（とディレクトリ名）を取得
files = glob.glob("*.xlsx")

# 存在する場合：存在しているファイルを使用、存在しない場合：ファイル作成
if excel_file_name in files:
    pass
else:
    create_file = openpyxl.Workbook()
    create_file.save(excel_file_name)

# 使用するExcelファイルを選択
excel_file = openpyxl.load_workbook(excel_file_name)
# 選択したExcelファイルの中にあるシート名を取得
sheet_list = excel_file.sheetnames

# シート名を定義
sheet_name = 'Sheet' + str(ID_num)

# シート内に先ほどのシート名がなければ作成
if sheet_name in sheet_list:
    pass
else:
    excel_file.create_sheet(title=sheet_name)

# 書き込むExcelシートを選択
sheet = excel_file[sheet_name]

# 書き込み始める行と列を定義
start_row = 1
start_col = 1

# 書き込みたいデータをfor文で書き込み
for y, row in enumerate(Data):
    for x, cell in enumerate(row):
        sheet.cell(row=start_row + y,
                   column=start_col + x,
                   value=Data[y][x])

# 変更を保存
excel_file.save(excel_file_name)
```

#3. 部分的なコードの説明
基本的な内容をコードにしたものなので，かいつまんで説明します。

下のプログラムでは，同じディレクトリ内にあるExcelファイルを含んだ全てのファイル名をリストで取得します。これにより下に続くファイル作成において，ディレクトリ内にそのExcelファイルが存在するかどうかの条件文を作成することができるようになります。
条件文の中では，リストに指定したファイルが存在する場合には処理を行わず，存在しない場合にはExcelファイルを作成します。

```python:Excel_1.py
# 同じディレクトリ内のファイル名（とディレクトリ名）を取得
files = glob.glob("*.xlsx")

# 存在する場合：存在しているファイルを使用、存在しない場合：ファイル作成
if excel_file_name in files:
    pass
else:
    create_file = openpyxl.Workbook()
    create_file.save(excel_file_name)
```

下のコードでは作成（選択）したExcelファイルを選択し，そのExcelファイルにあるシート名を取得します。その次に今回書き込みたいシート名を定義します。
そして，先ほどのリストを用いた条件文を用いて，シート名が存在しない場合には新しくシートを作成します。このとき，条件文を用いないとシートが新しく生成されてしまい，既存のシートが初期化されてしまいます。
＊新規作成したExcelファイルにあるシート名は"Sheet"なので，そのシートにそのまま書き込みをしたい場合は，シート名を"Sheet"にします。

```python:Excel_2.py
# 使用するExcelファイルを選択
excel_file = openpyxl.load_workbook(excel_file_name)
# 選択したExcelファイルの中にあるシート名を取得
sheet_list = excel_file.sheetnames

# シート名を定義
sheet_name = 'Sheet_X'

# シート内に先ほどのシート名がなければ作成
if sheet_name in sheet_list:
    pass
else:
    excel_file.create_sheet(title=sheet_name)
```
#4. 実行結果
実行した場合のディレクトリ(ファイルの中)は下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2058780/5de7b313-40a3-3eef-9399-2762cfe3cbeb.png)
また，作成したExcelファイルの中身は下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2058780/291043b4-b345-f3a4-cca0-329ee3c8aaf8.png)
ffmpegで配信先を複数指定する方法

# はじめに

ffmpegで入力映像(rtsp)を複数のストリーミングサーバーに配信(rtmp)できないかを調べたところ、参考にさせていただいたサイトのやり方のままでは配信が行えず、その後の調査と試行錯誤で配信が行えるようになった結果をメモとして残しておこうと思います。

# ffmpegのバージョン

```Text:ffmpegのバージョン
ffmpeg version 4.0.2
```

# ffmpegのコマンドイメージ

```Text:ffmpegのコマンドイメージ
ffmpeg -i rtsp://src -vcodec copy -an -f flv "rtmp://dst1/live/stream1" -vcodec copy -an -f flv "rtmp://dst2/live/stream2"
```

上記の中で、配信先を複数指定している部分は以下の通りです。

配信先その1の引数
> -vcodec copy -an -f flv "rtmp://dst1/live/stream1"


配信先その2の引数
> -vcodec copy -an -f flv "rtmp://dst2/live/stream2"


これでdst1、dst2のそれぞれのストリーミングサーバーを経由した再生確認で、stream1とstream2の映像がrtsp://srcの映像になっていることが確認できます。
Oracle Database 21c XEの簡易セットアップ

Oracle Database 21c Express Edition (XE)がリリースされました。
[Oracle Database 21c XE now generally available](https://blogs.oracle.com/database/post/oracle-database-21c-xe-generally-available)

手元のPC上のVirtualBoxでサクッとセットアップする手順を自動化したので公開します。

[shakiyam/vagrant-oracle-database-xe-21c: Vagrant + Oracle Linux 7 + Oracle Database 21c XE の簡易セットアップ](https://github.com/shakiyam/vagrant-oracle-database-xe-21c)

![Oracle-Enterprise-Manager-Database-Express.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174/e6b2e2b8-b193-5db6-6b1e-125be411747d.png)

それ以外のバージョンの手順も下記にて公開しています。

* [Oracle Database 21cの簡易セットアップ - Qiita](https://qiita.com/shakiyam/items/580b5081038191165da2)
    * [shakiyam/vagrant-oracle-database-21c: Vagrant + Oracle Linux 7 + Oracle Database 21c (21.3) | Simple setup of a single instance database.](https://github.com/shakiyam/vagrant-oracle-database-21c)
* [Oracle Database 19cの簡易セットアップ - Qiita](https://qiita.com/shakiyam/items/cd842a3f417c4285414a)
    * [shakiyam/vagrant-oracle-database-19c: Vagrant + Oracle Linux 7 + Oracle Database 19c (19.3) | Simple setup of a single instance database.](https://github.com/shakiyam/vagrant-oracle-database-19c)
* [Oracle Database 18c XEの簡易セットアップ - Qiita](https://qiita.com/shakiyam/items/9bd74c08f2208346f19e)
    * [shakiyam/vagrant-oracle-database-xe-18c: Vagrant + Oracle Linux 7 + Oracle Database 18c XE の簡易セットアップ](https://github.com/shakiyam/vagrant-oracle-database-xe-18c)
* [Oracle Database 18cの簡易セットアップ - Qiita](https://qiita.com/shakiyam/items/575148a486324b53b682)
    * [shakiyam/vagrant-oracle18: Vagrant + Oracle Linux 7 + Oracle Database 18c (18.3) | Simple setup of a single instance database.](https://github.com/shakiyam/vagrant-oracle18)
* [Oracle Database 11.2, 12.1, 12.2の簡易セットアップ - Qiita](https://qiita.com/shakiyam/items/3d2b94c118ab88fa4c79)
    * [shakiyam/vagrant-oracle12.2: Vagrant + Oracle Linux 7 + Oracle Database 12c Release 2 (12.2.0.1) | Simple setup of a single instance database](https://github.com/shakiyam/vagrant-oracle12.2)
    * [shakiyam/vagrant-oracle12.1: Vagrant + Oracle Linux 7 + Oracle Database 11g Release 2 (12.1.0.2) Enterprise Edition | Simple setup of a single instance database](https://github.com/shakiyam/vagrant-oracle12.1)
    * [shakiyam/vagrant-oracle11.2: Vagrant + Oracle Linux 7 + Oracle Database 11g Release 2 (11.2.0.4) | Simple setup of a single instance database](https://github.com/shakiyam/vagrant-oracle11.2)
Juliaが立ち上がった後で，最初にやることを記述しておく

Julia を立ち上げて，一連のおまじないを唱えている。

これを，自動的にやるにはどうしたらよいだろうかと思いつつも，ググりもしなかったのだが，今日偶然にやり方を読んだ。
https://docs.julialang.org/en/v1/manual/environment-variables/

Mac OS の場合だけど

`/Users/foo/.julia/config/startup.jl` をつくり，その中に一連のプログラムを書いておく。

config ディレクトリも mkdir しないといけない。

私は取りあえず

```
ENV["GKS_ENCODING"] = "utf8"
fontfamily = "IPAMincho"
println("Hello! World!")
```

の 3 行を書いた。

1 行目は，GR バックエンドで日本語を使えるようにする
2 行目は，使用するフォントの指定（私は明朝体が好き）
3 行目は，おまじないを唱えたことの確認のため
GithubActions Errno::EACCES: Permission deniedの解決


# 起こっていること

GithubActionsを用いて自動デプロイした際に急に
Errno::EACCES: Permission denied @ apply2files - のエラーがでました。

# エラー内容
すごく長いので要点の箇所だけ抜粋します。

```
rails aborted!
Errno::EACCES: Permission denied @ apply2files - /home/***/Beginners_Camp/tmp/cache/assets/sprockets/v3.0/NT/NTu0FZHjIrwvcxJ1nnTegT5SvGLkugb1ZWoTRebr0jo.cache

～省略～

bin/rails:9:in `<main>'
Tasks: TOP => assets:precompile
(See full trace by running task with --trace)
Error: Process completed with exit code 1.
```

`Error: Process completed with exit code 1.`の意味は、
どうやら構文やファイルのミスが検出されたため、エラーになったみたいです。

# 解決方法
エラー原因になっているキャッシュを削除することで解決できました。
本番環境にログイン後アプリのディレクトリに移動し、
tmp以降のエラー文を貼り付け、キャッシュを削除。

```
rm tmp/cache/assets/sprockets/v3.0/NT/NTu0FZHjIrwvcxJ1nnTegT5SvGLkugb1ZWoTRebr0jo.cache
```

下記参照
https://stackoverflow.com/questions/19364940/rails-permission-denied-tmp-cache-assets-development-sprockets
Pentaho Data Integration 入門編 (2) - TransformationとJOBの作成

# サマリ
この記事では以下について記載しています。

* Transformationの作成方法
* JOBの作成方法
* 実行時のイメージ
* 次のステップ

# 本記事を読む前に
Pentaho Data Integrationのインストールがまだの場合は、以下を参考にインストールして、記事を読みながら操作するとよりわかりやすいかと思います。
[Pentaho Data Integrationのインストール](https://qiita.com/mik/items/b6227b26cbd5bc099206)

TransformationとJOBについては以下も参照してください。
[Pentaho Data Integration 入門編 (1) - 機能概要と用語整理](https://qiita.com/mik/items/99ba6fefebc3e06e5d4d)

# Transformationの作成方法
TransformationはSpoon上で作成することが可能です。
具体的には、Spoon.batやspoon.shからSpoonを起動、"ファイルメニュー"→"新規"→"データ変換"を選択して新規にTransformationを作成する方法と、Spoon上の「＋」アイコンから"データ変換"を選択する方法があります。
画面イメージも貼っているので、ご確認ください。

![Tran001_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186651/5f988616-ad3a-ae60-3519-3d429332e8b0.png)

各ステップの設定については、ステップのアイコンをダブルクリックすることでそれぞれの設定画面が表示されるので、そこで行います。
実行については、作成したTransformationを一度保存してからSpoon上で実行したり、バッチコマンドから実行したりすることが可能です。
なお、Transformationを作成して保存すると、ktrという拡張子のファイルが作成されます。
作成したktrファイルを他の環境で実行する場合などは、このファイルを実行したい環境にコピーすることで可能となります。

# JOBの作成方法
JOBもTransformationと同様にSpoon上で作成することが可能です。
新規作成方法もTransformationとほぼ同様で、選択するメニューが"データ変換"ではなく、"ジョブ"に変わるだけです。
こちらも画面イメージを貼っているので、詳細はそちらをご確認ください。

![JOB001_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186651/bc79adcc-d62e-eed7-86b3-52c4a25d4ea2.png)

JOBを保存するとkjbという拡張子のファイルが作成されます。

# 実行時のイメージ
例として、Transformationを実行すると、以下のようなイメージとなります。

![Tran001_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186651/6b51d8d3-8a75-b538-50e4-75c7a5add739.png)

# 次のステップ
本記事では、TransformationやJOBの新規作成方法と実行方法など、ごく基本的なことだけ記載しておりますので、各ステップ内の設定方法には触れておりません。

よく使うステップの設定方法などは、別の記事で紹介していきますので、以下をご参照ください(随時追加してきます)。
[PDIでDBからデータを取得する](https://qiita.com/mik/items/474457dadedd88b2f96f)
[Pentaho Data Integration でCSVファイルを読み込む](https://qiita.com/mik/items/006aab9d11581f2a3919)
[Pentaho Data Integration でCSVファイルを出力する](https://qiita.com/mik/items/0fd4cf0a603ca740e762)
[Pentaho Data IntegrationでTableにデータを出力する](https://qiita.com/mik/items/ade1368e4bbb9e6317db)
Azure DevOpsのPipelineを使ってAzure App Configurationを更新する

Azure DevOpsのPipelineを使って、GitリポジトリのJSOnファイルからAzure App Configurationを更新する方法を紹介します。

# 環境

- Azure DevOps
  - Repos
  - Pipelines (YAML)

ReposにGitリポジトリを作成し、そこにコミットされたJSONファイルを元にApp Configurationを更新します。
この記事ではYAML方式のPipelineの使い方やAzure DevOpsのReposの使い方については触れません。

# 導入するメリット

Gitリポジトリに設定ファイルを置くことで、

* App Configurationを手作業で更新しなくて済む。
* 設定変更をGitのプルリクでチェックできるようになる。

などのメリットがあります。

# JSONファイルの例

```json
{
    "Integer": 1,
    "String": "string",
    "Object": {
        "Property1": 1,
        "Property2": "property",
        "Array": [
            1,
            2,
            3
        ],
        "ArrayObject": [
            {
                "Aaa": 1,
                "Bbb": 2
            },
            {
                "Aaa": 3,
                "Bbb": 4
            }
        ]
    }
}
```

# Azure CLIコマンドを使って、App Configurationを更新する

App Configurationの更新は、Pipelineの用意されたタスクを実行するわけではなく、Azure CLIコマンドのaz appconfig kvを使います。

https://docs.microsoft.com/ja-jp/cli/azure/appconfig/kv?view=azure-cli-latest#az_appconfig_kv_import

指定の仕方は色々ありますが、下記がコマンド例です。

```
az appconfig kv import --source file --name [App Configurationの名前] -s file --format json --path "[JSONファイルのパス" --content-type "application/json" --separator : --yes
```

簡単に説明すると、JSONを「:」でセパレートしながらインポートするようになっています。実際インポートされた後の状態については

# パイプラインテンプレートの例

次のようにAzure CLIコマンドを呼び出してあげれば、Pipelineから流すことができます。

```yaml
parameters:
  - name: subscriptionName
  - name: appConfigName
  - name: configFilePath

steps:
- task: AzureCLI@2
  displayName: 'Import: ${{ parameters.configFilePath }}'
  inputs:
    azureSubscription: '${{ parameters.subscriptionName }}'
    scriptType: ps
    scriptLocation: inlineScript
    inlineScript: |
      az appconfig kv import --source file --name ${{ parameters.appConfigName }} -s file --format json --path "${{ parameters.configFilePath }}" --content-type "application/json" --separator : --yes
```

# インポートした結果

次の画像の様に、「:」（コロン）で区切られたキーで各設定値が格納されます。配列はパースされず、丸ごと挿入される点は注意です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146578/96d98150-7d9b-9621-1038-b6c8da731145.png)

# 読み込み

ここではApp Configurationからの設定読み込みについては省略します。

ただ、「：」で分割するメリットは読み込み側にもあり、例えば "Object" の部分しか読み込みたくない場合、次のような指定をすることで余計な読み込みを避けることができます。

```csharp
builder.ConfigurationBuilder
    .AddAzureAppConfiguration(options =>
    {
        options
            .Connect("App Configurationの接続文字列")
            .Select("Object:*");
    })
    .Build();
```

※厳密にはApp Configurationの接続文字列ではなくAAD認証に切り替えるべきかと思います
Flutterで、JSONを処理する

Android Studioで、Flutterを使ってJSONを扱う方法。
色々なサイトで、記載されているのですが、記載している内容にばらつきがあり、ビルド出来ないものがあったりと大変だったので、記事にしました。

### 必要なものを定義

JSONを扱うプラグインは、色々あるのですが、今回は```json_annotation```と```json_serializable```を使用します。

```yaml:pubspec.yml
dependencies:
  json_annotation: ^4.1.0

dev_dependencies:
  build_runner: ^2.1.2
  json_serializable: ^5.0.2
```

### モデルを定義

```dart:user.dart
import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable()
class User {
  int userId;
  int id;
  String title;
  bool completed;
  @JsonKey(name: '_type')
  String? type;

  User(
      {required this.userId,
      required this.id,
      required this.title,
      required this.completed,
      this.type});

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}
```

* 解説

```dart
import 'package:json_annotation/json_annotation.dart';
```
こちらを記載しても参照出来ない場合は、Android Studioを再起動してみてください。

```dart
part 'user.g.dart';
```
記載している段階では、エラーとなっていますので、Android Studioのターミナルで下記を実行してください。

```terminal
flutter packages pub run build_runner build
```

```@JsonKey``` で、名前を変更することが可能です。

こちらで、JSONを扱うことが出来ます。

### JSONに変換

```dart
import 'package:myapp/user.dart';
import 'dart:convert';

  User paserUser() {
    String text = '''
{
	"userId": 1,
	"id": 1,
	"title": "delectus aut autem",
	"completed": false,
	"_type": null
}
''';

    var decode = json.decode(text);
    User user = User.fromJson(decode);
    return user;
  }
```

---

他のサイトでは、DartのNull safetyに対応してなかったりとかなり苦労しましたので、参考になればと思います。
Azure PaaSを利用したハイブリットクラウド

オンプレからプライベートエンドポイントを設定したAzureBlobへの接続に必要なリソースと設定イメージ
詳しくはリンク参照

![dns.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80457/4dba8df5-4a77-d09d-8d3b-4dc40a5416fa.png)


https://cloudsteady.jp/post/37510/

https://www.ether-zone.com/private-link-endpoint-from-external/

https://docs.microsoft.com/ja-jp/azure/private-link/private-endpoint-dns#on-premises-workloads-using-a-dns-forwarder

https://docs.microsoft.com/ja-jp/azure/active-directory-domain-services/manage-dns
【jQuery】hoverでclassを付け外し

自分用メモ書き
ホバー時に複数の要素を動かしたい時に便利

```index.html
<a class="link1" href="URL">リンク1</a>
<a class="link2" href="URL">リンク2</a>
```

```link.js
//================================
//  ! ホバーでクラスの付け外し
//================================
$(function(){
    $('.link1,.link2').hover(function(){ //hoverしたら
        $(this).addClass('active'); //「active」クラスを加える
    },function(){
        $(this).removeClass('active'); //「active」クラスを外す
    });
});
```
【UiPath】アクティビティの表示名を利用して会話を円滑にする

# 概要

UiPathのプロジェクトファイルを複数人で見る時、
通常ではアクティビティを一意に表現する方法がない。

* 「〇〇の次に来るループの～」
* 「××に代入してるとこのさ、いやそっちじゃなくて2回目のほう」
* 「最後の方の分岐のとこさ～」

純粋なコードであれば何行目、での会話が可能だが
UiPathでは上記のような会話になってしまう。

そこで、アクティビティの表示名に連番を付与しておくことで
「153番のとこ間違ってない？」という会話ができる。
番号がわかっていればUiPathStudio上の検索で、
一発で目的のアクティビティにジャンプすることも可能となる。

# アクティビティ表示名のブレ

アクティビティの表示名はデフォルトだと下図のようになる。

<img width="500" alt="スクショ1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/60dcd377-8f21-efe7-aa87-c5f2d993d58a.png">

このアクティビティ名はパッと見で目につく割に、不要な情報だけになってしまう場合が多い。
(「条件分岐」なのは見ればわかる…という感じ)

なので人によってはデフォルトのままだったり、大事なとこだけ書き換えてみたり、
あるいはものすごく丁寧に記入する人もいるかも知れない。

# ポイント

アクティビティに連番を付与するということはつまりこういうことになる。

* リファクタリング等で常に変化するものである
* よって、公式なドキュメントなどに番号を記載してはいけない
* 変化に対応できるようにワンタッチでなければならない。手動での記入はナンセンス

# 解決してみる

ワンタッチで連番を付与するアプリを作成した。
今回はElectronで実装したが、xamlファイルを正規表現で書き換えるだけなので何でも良い。
UiPathで実装するのもメタ的で面白いかもしれない。

<img width="500" alt="スクショ2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/15693d4f-d9a0-dbdc-e46c-a4822e5855ad.png">

ファイル名を指定すると対象ファイルのみ、フォルダを指定した場合は配下の全xamlファイルが対象となる。
一応除去するボタンで元の状態に戻すこともできるが、今のところ出番はない。
ついでにアクティビティの種類も自動で記入するようにした。

### 実行結果

<img width="500" alt="スクショ3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/3e0a7e37-cb72-6f20-43a4-c7fa89c8931f.png">

書式は `[xxxx] 元の表示名 : Type` としている。
もしアクティビティの追加や削除が発生した場合はもう一度付与を実行するだけで、
新たに連番を振り直してくれる。

同時に、Typeを自動追記にしたことでアクティビティ名自体には **WHAT** を手で書く必要がなくなった。
有益な **HOW** だけを書くようにすると以下のようになる。

<img width="500" alt="スクショ4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/d110a772-cd72-edd2-304f-b1f3dad88b87.png">

これでアクティビティを一意に判別し、かつ有益な情報を持たせることが可能になった。
EC-CUBE4で、パラメータを上書きする

[EC-CUBE4で、コアのクラスを触らずに上書きする](https://qiita.com/chihiro-adachi/items/b3bb70e6abbc0f824965)のパラメータ版です。

app/config/eccube/packages/eccube.yamlには、EC-CUBEの内部で利用するパラメータが定義されています。

```
parameters:
    # EC-CUBE default env parameters
    env(ECCUBE_ADMIN_ROUTE): 'admin'
    env(ECCUBE_USER_DATA_ROUTE): 'user_data'
    env(ECCUBE_ADMIN_ALLOW_HOSTS): '[]'
    env(ECCUBE_ADMIN_DENY_HOSTS): '[]'
...
    # EC-CUBE parameter
    eccube_database_url: '%env(DATABASE_URL)%'
    eccube_mailer_url: '%env(MAILER_URL)%'
    eccube_admin_route: '%env(ECCUBE_ADMIN_ROUTE)%'
...
```

このファイルを直接書き換えてもパラメータは変更できますが、app/Customize配下で上書きすることも可能です。

例えば、セッションの保持期間を定義する`ECCUBE_COOKIE_LIFETIME`、`ECCUBE_GC_MAXLIFETIME`を変更する場合は以下のようになります。

app/Customize/Resource/config/services.yamlを作成し、以下のように記述すればOKです。

```
parameters:
  env(ECCUBE_COOKIE_LIFETIME): 1209600
  env(ECCUBE_GC_MAXLIFETIME): 1209600
```
Excelのオプション変更

#Excelのオプションがグレーアウトされてて変更できない
##事の起こり
Excelでオートコレクト変えたいなって思った時に
ボタンがグレーアウトしてて変更できない！なんでや！ってなりました

原因はしょうもないのですが、知らないと混乱するので
自分への戒め含め書いておこうと思います

##理由は単純
Excelを空で開いて、いきなりオプション！ってやると
色んな項目がグレーアウトされてて変更できません
変更するときは新しいブックか何か作って変更しましょう

##おわりに
しょうもないですね
変更したいなーって思って、Webで検索した通りにやろうとしたら
うまくいかないという
状況が違えば対処も違うので、上記でもダメな場合は他をあたってくださいｍｍ
[iOS] carthage で XCFramework に対応する

##現象
xcode 13 も正式リリースされ、carthage で入れるライブラリをビルドしたところ、以下のエラーが発生しました。
>XXXX have the same architectures(arm64) and can't be in the same fat output file.

##詳細
xcode 12 以降では M1CPU(ARM64系）のMac上のエミュレーターに対応したため、iOS 用とエミュレータ用で２つの arm64 が存在することになり、carthage のビルドに失敗することがあります。
 
以前は Carthage 本家に、以下のようにスクリプトで対応する方法がありました。
https://github.com/Carthage/Carthage/blob/master/Documentation/Xcode12Workaround.md
しかし今回、xcode 13 ではこの方法ではビルド出来ず、上記のエラーが発生しました。

##解決法
対応としては、framework ファイルではなく、XCFramework をビルドすることによって解決できました。

carthage を V0.37.0 以降に更新することで XCFramework に対応できるようになり、上記のようなワークアラウンドで回避せずともビルドが通り、かつ簡単に iOS, エミュレータの両方に対応できるようになったようです。
　参考）https://techlife.cookpad.com/entry/2021/03/10/110000
 
###XCFramework 形式で Framework をビルドすることで対応する。
１．project/Cathage 以下のファイルを一旦削除
２．XCFramework としてビルド（"--use-xcframeworks"）

```
　carthage update --platform iOS --use-xcframeworks
```
・framework バイナリがダウンロードされる場合は、"--no-use-binaries" オプションを付け、ローカルでxcframework をビルドする。
３．project/Cathage/Build/*.xcframework　フォルダを Project > General > Frameworks, Libraries, and Embedded Content　にドロップ
　　・従来の *.framework は削除しておく
　　・Build Phase の Run Script に追加していた carthage copy-frameworks は不要になるので削除
４．Clean Build Folder 後、Build を実行する
thunderbirdのOpenPGPで復号化できなかったメールをコマンドラインから


メールをファイルとして保存（~/Downloads/message.eml）してから、下記のコマンドで復号します。

```bash
gpg -d --ignore-mdc-error Downloads/message.eml
```

メールの文字コードがISO-2022-JPの場合は、続けて文字コード変換します。

```bash
gpg -d --ignore-mdc-error Downloads/message.eml | iconv -f ISO2022JP -t UTF-8
```

文字コードが分からない場合は、メールのソースの下記の箇所を確認します。

```text
Content-Type: text/plain; charset=Shift_JIS
```

メールの文字コードがShift_JISであれば、次のように変換します。

```bash
gpg -d --ignore-mdc-error Downloads/message.eml | iconv -f SJIS -t UTF-8
```
Workato：Workbot for Teamsを利用して、Microsoft Teamsへ「Hello World」とメッセージを送信してみる

Workbotでは、Workbot for Teamsコネクターを利用することで、Microsoft Teamsのボットを作成することが出来ます。ここでは、「Hello World」というメッセージを投稿する単純なボットの作成手順を解説します。

# 手順
## １．Workatoレシピの作成
以下のようなWorkatoレシピを作成します。なお、トリガーは用途に合わせて必要なものを指定します。（ここでは、Scheduler for Workatoコネクターを選択しています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/88e0a247-40ac-763d-51eb-9816cfbf2d04.png)

### 【１】「Workbot for Microsoft Teams」コネクターの追加
#### １）「Workbot for Microsoft Teams」を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/ecc168aa-78b3-fc96-8085-bd83477dc30b.png)

#### ２）「Post message」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/790ac80c-bbbe-3ded-6a6d-5c6223b72f0f.png)

#### ３）Connection name（任意の名称）を設定し、「Connect」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/31c27202-9388-9d51-6e5d-cbe5d9e5f6df.png)

#### ４）Microsoft365においてアクセス許可を求められますので、内容を確認のうえ「承諾」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/2fe4bd27-bea3-a494-d647-82234bd0013f.png)

なお、以下の通り表示された場合は、現在Microsoft365にログオン中のユーザーが「全体管理者」のアクセス許可を有していることをご確認ください。あるいは、「全体管理者」のアクセス権限を有するユーザーでログオンし直したうえで、「承諾」を行ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/60c9b4fb-eaad-87c5-d3d9-e787e6853269.png)

### 【２】「Workbot for Microsoft Teams」コネクターの設定
#### １）メッセージ投稿先とするチーム/チャンネルを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/e1904e16-a5fe-f4c0-a79e-41ed7b5056a6.png)

#### ２）「Add block」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/c3edfced-5601-bff4-bcdf-b32969f9a313.png)

#### ３）「Text block」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/3a58f2a8-ebd3-35b8-2d4e-eae5d0913d70.png)

#### ４）Block textに「Hello World」と入力し、Text typeで「Body text」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/c144730a-3a16-5c9b-ae51-d466f995ea3c.png)

## ２．TeamsへのWorkbotインストール
### １）Workatoからメッセージを投稿したいチャンネルのメッセージフィールドに「@」と入力し、「ボットを取得」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/010ae555-652c-5186-1278-eac8c0e2f97c.png)

### ２）「Workbot」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/735ceb13-bdb1-6a76-0dc0-b84f025d49c4.png)

### ３）「追加」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/4842b5cb-d371-fba1-a587-de211368dcd9.png)


なお、上記手順でWorkbotをインストールできなかった場合は、チャットへ移動し、ヘッダーの検索フィールドに「Workbot」と入力し、Workbotを追加してから、再度上記手順に従い操作を行ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/3b227091-1222-f630-1560-6d1d198cf248.png)

## ３．レシピの実行
作成したレシピを実行すると、Teamsの指定されたチーム/チャンネルにメッセージが投稿されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/8188ee0a-b087-decf-1e75-dd0573672b9b.png)


# 参考

https://docs.workato.com/workbot-for-teams/workbot.html#workbot-for-teams
iOS15でexpoアプリが「アップデートの必要があります」と出て起動しない場合の対応

expoで作成したInHouse(Enterprise)アプリで、iOS15にアップデート後に「デベロッパーによるアップデートが必要です」と出て起動しない現象が出ています。（21/9/22)

※あまり大騒ぎになっていないので、InHouseのみかと思います。

``expo build:ios``でビルドしなおしても、SDK42にアップデートしても同様のエラーとなります。

![IMG_2735.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14768/56e1af6d-f052-435a-f921-e2bcb0c52599.jpeg)

# 解決方法

ビルドサーバーが対応するまでは、ローカル環境(XCode 14.5 or 15)でビルドします。

https://docs.expo.dev/distribution/turtle-cli/

## 必要な物
- turtle-cli
- fastlane
- XCode

## 手順

```
$ npm install -g turtle-cli
$ brew install fastlane
```

下記のようなMakefileを作りました

```:Makefile
make_ipa:	
	@echo "Building IPA"
	EXPO_IOS_DIST_P12_PASSWORD='hogehoge' \
　　　　　turtle build:ios \
		-u <expo user> -p <expo pass> \
		--team-id <teamid> \
		--dist-p12-path <.p12 path> \
		--provisioning-profile-path <.mobileprovision path> \
		--public-url https://exp.host/<hostpath> \
		-o build/my-sample.ipa
```

## エラーなど

- ``EXPO_IOS_DIST_P12_PASSWORD``を指定しなかったりパスワードを間違えるとエラーになります。エラーを見ても間違いがわかりにくいので注意。
- Provisioningなどはexpoにアップロードしてあるものをダウンロードすると間違いないです
- public-urlはexpoのアプリパスでメタデータを引いてくるため必須です。

# 参考

- eas.jsonを追加する方法では効果ありませんでした（有償プラン必須？）
- ビルドサーバーはXCode13が正式リリースになれば対応するとの事。

https://forums.expo.dev/t/ios-15-cannot-launch-enterprise-signed-application/53701/10

# 背景

どうやらEnterpriseアプリケーションのコード署名方法に何らかの変更があったようです。

https://developer.apple.com/forums/thread/682775

下記に、AppStore, Testflightの場合は配布時に置き換えるので影響しないが、直接配布するadhocは影響しmacOS10.14(Mojave)以降では新しいフォーマットで署名されますとあります。

https://developer.apple.com/documentation/xcode/using-the-latest-code-signature-format

> Look in the output for a string like CodeDirectory v=20500. For any value of v less than 20400, you’ll need to re-sign your app.

## コードサインの確認

```
$ unzip old.ipa
$ codesign -dv Payload/ExpoKitApp.app 
Executable=...
Identifier=...
Format=app bundle with Mach-O thin (arm64)
CodeDirectory v=20400 size=303198 flags=0x0(none) hashes=9466+5 location=embedded
```

確認するとたしかに```CodeDirectory v=20400```で、更新の必要があるようです。

# むにゃむにゃ

いつもexpoのビルドを便利に使っていたのですが、CLIからも意外に簡単にビルドする事ができました。待ち時間も無いので一度設定しておくと良いかと思います。どうして署名が古いのかは謎です。
yarn v1のworkspacesでもコマンドを並列で一括実行したい

yarn workspacesを使ってると、配下のパッケージにあるスクリプトを一括実行したい事がよくあります。

yarn v2からはworkspeces foreachが使えるのですが、移行する暇がないので暫定的に以下のようにして一括でやっちゃいます。

## 前提:フォルダ構成
以下のようにapp-a～cをmonorepoで管理してる前提で進めていきます。

```
project/
├── package.json
└── packages
    ├── app-a
    │   └── package.json
    ├── app-b
    │   └── package.json
    └── app-c
        └── package.json
```

## 各パッケージ内のpackage.json
それぞれ"build", "start"コマンドが設定されている想定です。

```json:app-a~c配下のpackage.json
{
  "scripts": {
    "build": "tsc",
    "start": "tsc --watch"
  }
}
```

## ルートのpackage.json

直列実行で問題無い場合は下記の"build"コマンドのように&&で区切って配下のパッケージのスクリプトを実行できます。
問題は並列実行をしたい場合ですが、ルート上にnpmパッケージをインストールすることは出来ないので、下記の"start"コマンドのように npm-run-all をnpxで毎回呼び出して実行することで一応できます。

```json:ルートのpackage.json
{
  "workspaces": [
    "packages/*"
  ],
  "scripts": {
    "build" : "yarn workspace app-a build && yarn workspace app-b build && yarn workspace app-c build",
    "start" : "npx npm-run-all -p start:*",
    "start:a" : "yarn workspace app-a start",
    "start:b" : "yarn workspace app-b start",
    "start:c" : "yarn workspace app-c start"
  }
}
```

他の解決策としては、試してないですけどlernaを入れて``` lerna run ```でしょうか？
そこまでするならyarn v2にマイグレしてもいいかも・・・
matplotlibでアスペクト比設定がうまくいかない

※2022/09/18にコメントでいただいた情報を記事に反映
# 経緯
[Pythonで動かして学ぶ！あたらしい数学の教科書](https://amzn.to/3nVB27J)という書籍で演習問題を解いていたのだが自分が実装する箇所以外のところのコードが期待通りの処理を行えておらず、タイトル通りの状況となっていた。

# 環境
Python 3.9.7 64bit
matplotlib 3.4.3

# 元々のコード(抜粋)
```
plt.xlim()
plt.ylim()
plt.xlabel()
plt.ylabel()
plt.grid()
plt.axes().set_aspect("equal")
plt.show()
```

# 元々のコードの結果
![スクリーンショット 2021-09-22 14.08.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227794/dd9e14ff-6fca-18ab-2314-b8a972d9c6c2.png)

# 修正後のコード(抜粋)
```
plot = plt.subplot()
plot.set_xlim([-3, 3])
plot.set_ylim([-3, 3])
plot.set_xlabel("x", size=14)
plot.set_ylabel("y", size=14)
plot.grid()
plot.set_aspect('equal')
```

# 修正後のコードの結果
![スクリーンショット 2021-09-22 14.10.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227794/0648f326-3c31-c2a4-f641-b10fccfd57cb.png)

# やっていること
修正前はmatplotlibを直接呼び続けているんですが、修正後は一度変数にsubplotを呼ぶようにしてそちらを使うようにしました。

# おわりに
subplotを呼ばなくてもできるんじゃないかという気はするんですが、調べていて見つかったのがこの方法だったのでひとまずはこれで解決としました。
元々のコードに近いやり方があればコメントいただければと思います。

# 補足
コメントにて著者サイドで期待する修正内容を共有いただいたので更新。
@kog14 さんありがとうございます！
修正後のコード
```
plt.xlim()
plt.ylim()
plt.xlabel()
plt.ylabel()
plt.grid()
plt.gca().set_aspect('equal', adjustable='box')
plt.show()
```
Visual Studio, SQL ServerでSQL練習問題やってみた

以前からSQLの勉強をしたいなぁと思っていたので、[【SQL】『SQL未経験 → 3ヶ月でデータサイエンス100本ノック全問制覇』までのロードマップ (初心者向け)](https://qiita.com/Ryo-Nakano/items/8961c956babaf0976b4a)を読んで、[SQL練習問題 一覧まとめ](https://tech.pjin.jp/blog/2016/12/05/sql%E7%B7%B4%E7%BF%92%E5%95%8F%E9%A1%8C-%E4%B8%80%E8%A6%A7%E3%81%BE%E3%81%A8%E3%82%81/)を解いてみました。

# 環境
* Visual Studio 2019
* SQL Server（Microsoft SQL Server Data Tools）

[SQL練習問題 一覧まとめ](https://tech.pjin.jp/blog/2016/12/05/sql%E7%B7%B4%E7%BF%92%E5%95%8F%E9%A1%8C-%E4%B8%80%E8%A6%A7%E3%81%BE%E3%81%A8%E3%82%81/)ではMySQL前提のようですので、DDL等をSQL Serverに合わせて変更しています。もしもSQL Serverで練習問題を解いてみたい方はこのDDLを使うのがいいかもしれません。

# SQL一式
解答内容とデータ準備に必要なSQLは[GitHub](https://github.com/shoji9x9/SQLTraining)に公開しています。

# 補足
* 見つけた重複データは削除したため、Webページの解答と異なる場合があります
* 解答のSQLはDBMSの違いにより模範解答と差がある場合があります

# 練習問題を解いてできるようになったこと
* SELECT文はリファレンスを参照しなくても書けるようになりました。一方で、INSERT、UPDATE、DELETEの練習問題はないため、これらは別途訓練が必要です
* 副産物ではありますが、MySQLとSQL ServerのSQLの違いを知ることができました。例えば以下のようなことです
    * MySQLでは`TIMESTAMPDIFF()`を使って生年月日から一発で年齢を求められるが、SQL Serverでは`DATEDIFF()`と`DATEADD()`とCASEを組み合わせる必要がある
    * SQL Serverでは、副問い合わせの結果として複数カラムを受け取ったとき、単純に比較ができない。うまく説明できないのですが、[複数の列で in 句を使いたい](https://odashinsuke.hatenablog.com/entry/2015/12/13/103651)を読むとわかりやすいと思います
    * SQL Serverでは、SELECT句でASを使い定めた名前をGROUP BYに使えない（ORDER BYには使える）。これはSELECTよりもGROUP BYの方が先に処理されるからのようです。[ORDER BY句で別名が使えてGROUP BY句では別名が使えない理由](https://muroiwataru.net/entry/sql-order-by)が参考になりました
    * 先頭x件のデータを取得したいとき、MySQLではLIMITを使うが、SQL ServerではTOPを使う

# 今後
次はデータサイエンス100本ノックに挑戦予定です。
ROS2(foxy)にてJoystick(Logicool F310)を使用する(joy_linux_node)

# はじめに
```
$ ros2 run joy joy_node
```
ROS2(foxy)にてJoyでJoystick(logicool F310)を使用できず詰まった。
接続したJoystickではなくキーボードがJoystickとして認識されてしまう。
解決できたので備忘録。

# 結論
```
$ ros2 run joy_linux joy_linux_node
```
joy_linuxパッケージを使ったら解決した。
```/dev/input/js0``` のJoystickを直接使ってくれるみたい 助かるね。 

# 環境
- PC : Sony VAIO SVP1121A2J
- OS : Ubuntu 20.04.3 LTS (Focal Fossa)
- ROS2 : foxy
- コントローラー : Logicool F310


# 準備

## 必要パッケージのインストール

```
$ sudo apt install ros-foxy-joy-linux
$ sudo apt install ros-foxy-joy-linux-dbgsym
```

## 接続確認

```
& lsusb
```

```Bus ~ Device ~: ID XX:XX Logitech, Inc. F310 Gamepad [XInput Mode]``` 
それっぽいのが出てくればOK。

```
$ ls /dev/input/
```

```jsX``` があればOK。
私の環境では```js0``` だった。

## 入力確認

```
$ jstest /dev/input/js0
```

ボタン、アナログスティック、トリガー入力で値が変化すればOK。

## 権限確認

```
ls -l /dev/input/jsX
```

```crw-rw-XX- 1 ~~~```
"XX"が"--"の場合、権限を追加する。

```
$ sudo chmod a+rw /dev/input/jsX
```

# 使う

```
$ ros2 run joy_linux joy_linux_node
$ ros2 topic echo /joy
```
結論と同じ。
joy_linuxパッケージのjoy_linux_nodeを起動する。
ボタン入力で```/joy```トピックに値が出力されていればOK。

# 参考
https://github.com/ros-drivers/joystick_drivers/tree/ros2/joy_linux

http://wiki.ros.org/joy/Tutorials/ConfiguringALinuxJoystick
Oracle LinuxにTorをインストールする方法にハマったので備忘録

# まずは公式を見る
- [公式ドキュメント](https://community.torproject.org/relay/setup/guard/centosrhel/)によると…

```bash
yum install epel-release # エラーになりました
```

- /etc/yum.repos.d/tor.repoを作成して追加？

```
[tor]
name=Tor for Enterprise Linux $releasever - $basearch
baseurl=https://rpm.torproject.org/centos/$releasever/$basearch
enabled=1
gpgcheck=1
gpgkey=https://rpm.torproject.org/centos/public_gpg.key
cost=100
```

- からの`yum install tor`は余裕でエラーになった

## 解決方法
- 全部有効化してやる

```bash
sed -i -e "s/enabled=0/enabled=1/" /etc/yum.repos.d*.repo
yum install tor
```

### Oracle Linuxを触った感想

- epelを有効化する情報がすぐに調べて出てこないのがありえない、Alway Freeだから使ってやってる
Next.jsのImageにスタイリングを適用する方法

### 問題

```tsx
<Image
 src={people.icon.url}
 width={80}
 height={80}
 alt="people-image"
 unoptimized={process.env.NODE_ENV === 'development'}
/>
```

上記のImageコンポーネントがあるとしてアバターなので丸くしたいがpropsに`style`を渡すことができない。
(styleはImageのpropsにないというエラー)

解決策はnext.jsのissueに上がっていました

https://github.com/vercel/next.js/discussions/18312#discussioncomment-273122

```tsx
<>
  <Image className="avatar" src="./whatever.jpg" width={30} height={30} />
  <style jsx global>{`
    .avatar {
      border-radius: 50%;
    }
  `}</style>
</>
```

styleタグを追加してその中でプロパティーを追加してImageタグにclassNameを設定することで画像が丸くなり正常にスタイリングされました。

ただ、、、、、、、、

![](https://pbs.twimg.com/media/DmK8Rh8V4AAfw1Y.jpg)