OmniAICreator/Qiita-1.07M huggingface dataset:
pythonでキーボード・マウス操作を自動化して日常業務を効率化【RPA】





#今回で習得できること


pythonでキーボード操作やマウス操作を自動化。
「艦〇れ」だろうが「城プ〇」だろうが周回を自動化できる。
高いライセンス料金でRPAツールを導入しなくても日常業務が効率化できる。
(実際に周回自動化をして見ようかと思ったが規約とか厄介なのでおとなしくやめておく)
~~リモートワークで離席しててもログイン状態を保てるので気付かれることなく・・・~~

#操作したい画面のサイズを取得

pythonでキーボードやマウス操作を自動化するためのパッケージといえばpyautogui。



```python
import pyautogui as pa
pa.size()
```

```
Size(width=1920, height=1200)
```




確認しやすさのためにtimeを使って動作の前に一旦停止させる。
自動操作の入力が早すぎて画面処理やブラウザが反応に追いつけない時があるので都合に合わせてtimeを使っていく。


#原点からのマウスの移動

画面左上を(0,0)の座標として位置操作を行う。
moveToで(0,0)から指定の位置へマウスを移動させる。
durationで何秒かけて移動するかを指定する。


```python
import time
time.sleep(1)

pa.moveTo(100,100,duration=1)
```


#現在の位置を知る

```python
pa.position()
```

```
Point(x=1735, y=157)
```

#現在位置から動かす

現在位置から指定位置まで動かすのはmoveRel

```python
time.sleep(1)
pa.moveRel(100,100,duration=1)
```

#クリック・特殊クリック・ダブルクリック


```python
pa.click(x=1839, y=293, button='left')
```


```python
pa.leftClick()
pa.rightClick()
pa.doubleClick()
```

#マウスの押し込み・離し

```python
pa.mouseDown(x=1735, y=157)
pa.mouseUp()
```

moveRelと組み合わせればドラック＆ドロップができる。


#でもドラック＆ドロップなら専用のものがある

```python
pa.dragTo()
pa.dragRel()
```


#スクリーンショット

```python
ss =pa.screenshot()
```

#画像を認識して場所を返してくれる

スクリーンショットやsnipping toolで認識したい物を用意

今回はゴミ箱をgomi.pngとして保存しておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/cb791048-cbc9-355a-f23a-f3c46d018cde.png)


スクリーン上から画像と一致する位置を返す


```python
list(pa.locateAllOnScreen('gomi.png'))
```

```
[Box(left=16, top=4, width=65, height=81)]
```

#画像で認識したものの中心位置を返す

```python
pa.center(pa.locateAllOnScreen('gomi.png'))
```

中心を認識したらクリックと組み合わせればショートカットを実行できる



#文字を打ち込む

画像認識で検索バーやメモ帳の位置を指定してからtypewrite

```python
pa.leftClick()
pa.typewrite('HHH',1)
```


#スケジュール実行する

```python
import schedule
import time

def job():
    print("関数内にclickとか処理を入れる")
```


10分ごとにjob関数の操作を実行

```python
schedule.every(10).minutes.do(job)
```

その他の指定

```python
#一時間おき
schedule.every().hour.do(job)
#毎日10:30になったら
schedule.every().day.at("10:30").do(job)
#月曜になったら
schedule.every().monday.do(job)
#曜日・時間指定
schedule.every().wednesday.at("13:15").do(job)
```

スケジュール実行を停止

```python
schedule.run_pending()
```



#以上

hotkeyとしてshift長押しやwindowsボタンを押す事もできる

[PyAutoGUI’s documentation](https://pyautogui.readthedocs.io/en/latest/index.html)
[schedule doc](https://schedule.readthedocs.io/en/stable/)
[アプリ開発]未経験がファッションアプリ作ってみた

![bcaf1b5818b00452012ea3d246180192.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679429/6bda45f8-478f-7e7f-209f-972629ed05a6.gif)

#作った経緯
プログラミングスクールで勉強して半月ほど、、
私の京都に住んでいる祖母が
「コロナで近所の骨董品を扱っているお店が海外のお客さんが来れなくなってあまりよくない」と、
そこで私がちょうどアプリ開発を勉強していたのでオリジナルアプリを作る時にこれを制作してポートフォリオにしようと決めました。
スクールで学んだことを基本にそこから作ってみたいアプリを参考にして新しい技術を取り入れてやっていきました。
![スクリーンショット 2020-09-06 13.04.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679429/81576bf0-7338-524e-be39-55aa4a9d589b.png)
サンプルで画像、ブランド名を拝借しております。

#エラー
とにかくCollectionViewに手間取りました。
![スクリーンショット 2020-09-06 13.11.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679429/b39bda49-cc83-8c78-ac3f-6b18bdadc28d.png)
基本手にTableViewと変わりませんが、ネットにあまり記事が出ていないので、、、
![スクリーンショット 2020-09-06 13.11.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679429/0ce3b9d9-b89f-03a6-605a-9840a776e205.png)



#結果
それから半月くらい、、
プロトタイプというか形になったので祖母にメールしました。
「こんな感じでどうかな。画像とかデータを商品名に変更したいから骨董品屋さんの電話番号教えて」
と送ると、
「そこは一流ばかりでそう易々と情報は無理だと思うよ。」
とまさかの返事。。。。

私は落胆しました、こんな頑張ったのにどうしてくれるんだと。
メンターと相談して、ポートフォリオは無駄じゃないしこのままリリースしようと決めました。



#感想
アプリ開発は大変ですねw
高校でC言語を勉強して一応３年間やっていましたがあまり役に立たなかったですw
むしろ一からやっていたに近いかも。

このアプリにしようと思ったのは、これなら人のためと捗るし開発や運営などできるかなと思いましたが、
できなくて残念でした。
しかし、これに懲りずにガンガン開発していきます！
一人作業だし、自分でスケジューリングして、、ていうセルフワークでしたが、
できなかったところができるようになったり新しい技術が自分にできるようになると達成感がとても気持ちいいですね！！

#参考にした記事
https://note.com/yujirosaito006/n/n42ca75b36931
https://i-app-tec.com/ios/collectionview-cellselect.html
https://qiita.com/NEKOKICHI2/items/1a42cb36c3aacbe50c70
https://qiita.com/Kawboy442/items/9fb8e8f14e0bc5ad7c1b
【RaspberryPi】パスワードをハッシュ化する

#パスワードをハッシュ化する
```bash
$ wpa_passphrase "SSID" "パスワード"
```
```:出力
network={
	ssid="SSID"
	#psk="パスワード"
	psk=ハッシュ化されたもの
}
```
**このコマンドはMacにはない**
参考：[RaspbianでWi-Fiパスワードを暗号化して設定する方法](https://raspida.com/wpa_passphrase)

出力されたものを以下のファイルに上書きする

```:wpa_supplicant.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
	ssid="SSID"
	#psk="パスワード"
	psk=ハッシュ化されたもの
}
```
Promiseを受け取るelement.innerHTMLで非同期処理を隠蔽

# 非同期処理を同期処理のように書きたい
というニーズがあるらしい。確かに、`promise.then()`や`await`を何回も書くのが煩わしいという気持ちは分かる。
そこで、`promise.then()`や`await`を使わずに、普通の代入文のみで非同期処理を書いてみようというのがこの記事の趣旨。

## 方法1：代入式の右辺が必ず値を返すようにする
例えば「promiseが解決されていれば値を返し、解決されていなければ**promiseをthrowする**」という方法がある。Reactで使われているらしい。よく知らない。

## 方法2：代入式の左辺がPromiseを受け取れるようにする
こっちが本題。
fetchやら何やらで値を取ってきて処理するとして、その値は最終的にHTMLの書き換えに使われる(ことが多い)はず。
というわけで、**Element.prototype.innerHTMLを書き換えてpromiseを受け取れるようにする**。

### 実装

Element.prototype.innerHTMLの書き換えについては[こちらのサイト](http://var.blog.jp/archives/55340140.html)を参考にさせて頂いた。
Promiseが解決されるまでは「loading...」と表示する。

```javascript
{
const desc = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML')
Object.defineProperty(Element.prototype, "innerHTML", {
  get: function(){
    return desc.get.call(this)
  },
  set: function(x){
    if (x instanceof Promise || (x && typeof x.then === 'function')) {
      //Promiseだった場合、解決されるまで'loading...'を表示する
      desc.set.call(this, 'loading...')
      x.then(val=>desc.set.call(this, val))
    } else {
      //Promise以外の場合、そのまま表示する
      desc.set.call(this, x)
    }
  }
})
}
```

### 使用例

```javascript
//1秒後に解決されるPromiseをinnerHTMLに代入
document.body.innerHTML = new Promise(resolve=>{
  setTimeout(_=>resolve('resolveされました'), 1000)
})
```
これを実行すると、まず「loading...」が表示され、1秒後に「resolveされました」が表示される。

なお、実際に使うときは、
 - promise内でエラーが出た場合(`promise.catch()`)
 - element.innerTextやelement.insertAdjacentHTML
への対応が必要だと思われる。
Azure Synapse AnalyticsからAzure Data Lake Storageにクエリを投げるとエラーになる場合の対処。 

## Azure Synapse Analyticsとは？

Azure Synapse Analytics(Workspace)は従来のトランザクショナルデータ(DWH)とData Lakeの境界をなくし、一つの窓口からあらゆるデータにアクセスし分析することが可能な製品です。Synapseを使っている際に外部データソースとしてADLSを登録し、「さてSQL-on-demandでparquetやらcsvやらにクエリを投げよう」と思った矢先にエラーになり、少々ハマりましたのでメモとして残しておきます。

## 似たような事例が過去にあった
過去の問い合わせで、Azure Data FactoryからBLOBストレージのデータを読みに行った際にエラーになるという相談を受けたことを思い出しました。アクセスキーによって接続はできているものの、データにアクセスしようとすると権限エラーになったようです。この問い合わせに対しては、ADFにBLOBデータ閲覧者等のデータ本体に関するIAMロールを付与することで解決することが確認できました。

この事例から今回もこの類だと思い、調査しました。

## ADFのようにADLSから直接リソースを指定してIAMロールの付与ができない
IAMロール付与画面のイメージが以下になります。システム割り当てマネージドIDの欄にSynapseが出てきません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/07d05f06-6448-fb8e-ee3c-31bb176d75e2.png)


## エラーメッセージからそれっぽいドキュメントに飛ばされた。
```sh
Started executing query at Line 1

Failed to execute query. Error: File 'https://xxxstore.dfs.core.windows.net/container/data/xxxx.parquet' cannot be opened because it does not exist or it is used by another process.
Visit this article to learn more about this error
Total execution time: 00:00:00.570
```
上記のエラーのthis articleは[こちら](https://docs.microsoft.com/ja-jp/azure/synapse-analytics/sql/resources-self-help-sql-on-demand#query-fails-because-file-cannot-be-opened)です。

こちらを確認すると確かに、
>"File cannot be opened because it does not exist or it is used by another process (ファイルが存在しないか、別のプロセスで使用されているため、開くことができません)" というエラーでクエリが失敗したときに、ファイルが存在し、かつ別のプロセスで使用されていないことが確認されている場合は、SQL オンデマンドがファイルにアクセスできないことを意味します。 この問題は通常、ファイルにアクセスする権限が Azure Active Directory ID にないために発生します。 SQL オンデマンドでは、既定で、Azure Active Directory ID を使用してファイルへのアクセスを試みます。 この問題を解決するには、ファイルにアクセスするための適切な権限を持っている必要があります。 最も簡単な方法は、クエリの対象となるストレージ アカウントに対する "ストレージ BLOB データ共同作成者" ロールを自分に付与することです。 詳細については、ストレージの Azure Active Directory アクセス制御に関する完全なガイドを参照してください。

上記のように記載がありますね。

【"ストレージ BLOB データ共同作成者" ロールを自分に付与】すれば良いということで実際に行ってみました。
反映されるまで多少時間がかかるようなので焦らずに待ちましょう。しばらくするとSQLオンデマンドを利用して外部のADLSにクエリを投げることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/f1d10d82-c52d-aabb-fee8-7f558339c2d9.png)
【Docker】Nginxのconfで環境変数を使う

Rails＆pumaで、開発と本番の両方の環境でSSL化をしたくなることがあると思います。
私の場合、ローカルは自己証明書、本番は認証局で登録されている正式な証明書を使いSSL化をしようかなと考えていました。そのためにはNginxのconfファイルに記載する各証明書のパスは開発と本番では別になるため、その部分だけ環境変数で使い分けをしようということになりました。
その時に行った実装手順をメモします。


# 前提
やり方は、環境変数名を記載したファイルから、環境変数に代入した値に変換されたファイルを生成するenvsubstというコマンドを使用します。


# 実装手順
環境変数は```${SSL_CERTIFICATE_PATH}```のように記述する。
※下記のファイルでは、```${SSL_CERTIFICATE_PATH}```と```${SSL_CERTIFICATE_KEY_PATH}```の2つを記述しています。

```conf:docker/nginx/default.conf.template

upstream app {
  server unix:///app/tmp/sockets/puma.sock;
}

server {
  listen 80;
  server_name  _;
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl;
  server_name localhost;

  ssl_certificate ${SSL_CERTIFICATE_PATH}; # 環境変数
  ssl_certificate_key ${SSL_CERTIFICATE_KEY_PATH}; # 環境変数
  ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers         HIGH:!aNULL:!MD5;

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  root /app/public;

  location / {
    proxy_pass http://app;
    proxy_set_header X-Real-IP $remote_addr;
    index index.html index.htm;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
  }

  client_max_body_size 100m;
  error_page 404             /404.html;
  error_page 505 502 503 504 /500.html;
  try_files  $uri/index.html $uri @app;
  keepalive_timeout 5;
}
```

Dockerfileにて、default.conf.templateを配置する。

```docker:Dockerfile

FROM nginx:1.16
RUN apt-get update && \
  apt-get install -y apt-utils \
  locales && \
  echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
  locale-gen ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
# 初期状態の設定ファイル
ADD ./docker/nginx/nginx.conf /etc/nginx/nginx.conf
ADD ./docker/nginx/default.conf.template /etc/nginx/conf.d/default.conf.template
```

変換する環境変数をnginxサービスのcommandキーのように指定し、envsubstを動くようにする。
環境変数に代入する値はenvironmentキーで設定する。

```yaml:docker-compose.yml

version: '2'
services:
	app:
# ・・・省略
	db:
# ・・・省略
  nginx:
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    ports:
      - '80:80'
      - '443:443'
    volumes:
      - sockets:/app/tmp/sockets
      - ./docker/nginx/ssl:/etc/nginx/ssl
    depends_on:
      - app
    command: /bin/sh -c "envsubst '$$SSL_CERTIFICATE_PATH $$SSL_CERTIFICATE_KEY_PATH'< /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
    environment:
      SSL_CERTIFICATE_PATH: /etc/nginx/ssl/server.crt
      SSL_CERTIFICATE_KEY_PATH: /etc/nginx/ssl/server.key

# ・・・省略
```

下記のコマンドでコンテナを立ち上げる時、envsubstコマンドが実行され、環境変数名を記載したファイル(default.conf.template)から、環境変数に代入した値に変換されたファイル(default.conf)が生成されました。

```bash
$ docker-compose up -d
```

# 参考

[envsubstを使ってDockerで設定ファイルに環境変数を埋め込めこむ汎用的なパターン - Qiita](https://qiita.com/minamijoyo/items/63ae57b99d4a4c5d7987)


# さいごに

パスとファイル名さえ間違えなければ躓くことは無いのではないかと思います。
本番環境でもうまくいくようにこれから試してみます。
[初心者]Hasuraを使ってみました

なんかDBとのやり取りはRESTを使うのが最新かと思いきや、GraphQLというものがモダンらしい。
RESTは細かく誰でも直感的にわかるようにエンドポイントを分けるようにする考え方だが、いろんなテーブルのデータを使いたいときに意外と不便。取ってきたデータを元にもう一回GETして、、、
一方で、GprahQLを使えばエンドポイントを一つにする代わりに、クエリをjsonのように扱えながらいろんなテーブルのデータを一発で取得することができる。

今回はそんなgraphQLとSQLを自動で変換してくれるHasuraというAPIサーバを使ってみました。

### 公式ドキュメント
[https://hasura.io/docs/1.0/graphql/core/index.html](https://hasura.io/docs/1.0/graphql/core/index.html)



# セットアップ
ゼロから始めるやり方は以下の二つ。

- Harura Cloud
- Docker

今回はDockerを使った例を示します。

### 1. 新しいディレクトリで以下のコマンドどちらかを実行してdocker-composeファイルを取得

```
wget https://raw.githubusercontent.com/hasura/graphql-engine/stable/install-manifests/docker-compose/docker-compose.yaml

# or
curl https://raw.githubusercontent.com/hasura/graphql-engine/stable/install-manifests/docker-compose/docker-compose.yaml -o docker-compose.yml
```

docker-composeの中身はこのようになっています。

```docker-compose.yml
version: '3.6'
services:
  postgres:
    image: postgres:12
    restart: always
    volumes:
    - db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: postgrespassword
  graphql-engine:
    image: hasura/graphql-engine:v1.3.1
    ports:
    - "8080:8080"
    depends_on:
    - "postgres"
    restart: always
    environment:
      HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres
      ## enable the console served by server
      HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set to "false" to disable console
      ## enable debugging mode. It is recommended to disable this in production
      HASURA_GRAPHQL_DEV_MODE: "true"
      HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log
      ## uncomment next line to set an admin secret
      # HASURA_GRAPHQL_ADMIN_SECRET: myadminsecretkey
volumes:
  db_data:
```

### 2. 起動
特に変更する必要がなさそうならそのまま起動させます。

```
docker-compose up -d
```

### 3. Hasura コンソールを確認
うまく起動できていれば、[http://localhost:8080/console](http://localhost:8080/console)で以下のような画面が表示されるはずです。

![スクリーンショット 2020-09-07 15.23.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351843/0dff4ba7-2399-2bfa-6220-e86ba9b15a59.png)




# データを登録してクエリを投げる
### 1. テーブルの作成
早速、テーブルを作っていきます。
今回はgraphQLのすごさを実感するために、メインのテーブルとそのテーブルの子テーブルを作成します。(RESTならメインテーブルから取ってきたデータを元に新たにGETする必要があるが、graphQLは一発で取れるところがすごい)

1. 上部にある**DATA**タブをクリック
2. **Create Table**ボタンをクリック
3. カラムを入力しましょう
4. 子テーブルも同様


### 2. テーブル間のリレーションの設定
1. **Data**タブをクリック
2. 子テーブルを選択
3. **Modify**タブをクリック
4. **Foreign Keys**で設定
5. 親テーブルを選択
6. **Relationships**タブをクリック
7. **Table Relationships**の**Array relationships**に先ほど子テーブルで追加した設定が反映されているはずなので、**Add**ボタンをクリック
8. クエリの際に利用するparameter名を入力

### 3. クエリを投げる
最後にクエリを投げてデータを取得できるか確認してみましょう。
**GRAPHIQL**タブのページで実行。
Excel再起動でアドインAddinのリボンメニューが消える時は「信頼できる場所」追加で治るかも

ExcelでアドインAddinを作ったりもらったりしてインストールした後、
Excelを再起動すると何故かアドインのタブが消えてしまうことがあります。

その対策記事（英語）がこちら↓
https://www.excelcampus.com/vba/add-in-ribbon-disappears/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100646/4953338e-d48b-9eb4-e347-85a63572ba21.png)
ざっくり日本語訳すると
アドインのフォルダ（開発→Excelアドイン→参照で表示されるフォルダ）を
「信頼できる場所」に追加すると治る　とのことです。

【手順】
１．アドインフォルダのパスを取得
　Excel左上の「ファイル」→オプション→アドイン→設定→参照　で出てくるフォルダのパスをコピーしておく
　※アドインが上記以外のフォルダにある場合は、そのフォルダのパスをコピーしておく

２．信頼できる場所について
　Excel左上の「ファイル」→オプション→セキュリティセンター（トラストセンター）→セキュリティセンターの設定（トラストセンターの設定）→
　新しい場所の追加→　手順１のパスを貼り付け→　OK

３．Excel再起動

以上でうまくいくことがあります。よろしくお願いします。
pytorchでcannot assign module before Module.init() callが出た時

すごく簡単な話なのですが、いつかやらかして長時間溶かしそうなので備忘録です。

##該当コードとエラー内容

```python
import torch
import torch.nn as nn

class Encoder(nn.Module):
    def __init__(self, p_n_features_num, timesteps) -> None:
        self.p_n_features_num = p_n_features_num
        self.linear = nn.Linear(
            p_n_features_num, p_n_features_num, bias=True)
        self.leakyrelu = nn.LeakyReLU()

    def forward(self, input_net):
        input_net = input_net.view(input_net.size(0), self.p_n_features_num)
        return self.leakyrelu(self.linear(input_net))
```
ここでEncoderの\_\_init\_\_を呼び出すと 
```cannot assign module before Module.init() call
```のエラーが出ます。

##解決策、修正コード
これはinitのときにnn.Moduleを継承しているのでsuperメソッドを始めに呼び出さなかったのが原因です。そのため、以下のように修正してあげれば直ります。

```python
import torch
import torch.nn as nn

class Encoder(nn.Module):
    def __init__(self, p_n_features_num, timesteps) -> None:
        super(Encoder, self).__init__()
        self.p_n_features_num = p_n_features_num
        self.linear = nn.Linear(
            p_n_features_num, p_n_features_num, bias=True)
        self.leakyrelu = nn.LeakyReLU()

    def forward(self, input_net):
        input_net = input_net.view(input_net.size(0), self.p_n_features_num)
        return self.leakyrelu(self.linear(input_net))
```
ISAM経由のCognos AnalyticsでQuery Studioのようなレガシーツールを使用するときは透過ジャンクションにする必要あり

#はじめに

記事タイトルの通りです。
ISAMを経由してCognos Analyticsを使用する環境で、ジャンクション作成時に注意するポイントはこちらにまとまっていますが、

<参考>

+ [Cognos のTivoli Access Manager(TAM)経由のSSOでジャンクション作成時の-jオプションが必要](https://qiita.com/shinyama/items/498c80213accdc7050bd)

+ [Cognos Analytics と ISAM(TAM)でSSO実装する時に必要な設定](https://qiita.com/shinyama/items/7877bc2240e27c7e0723)



Query StudioやEvent Studioのようなレガシーツールを使用する場合は追加でもう一点考慮が必要で、透過ジャンクションにする必要があります。


#ISAM経由のCognos Analyticsでレガシーツールを使用するために必要な設定

ISAM経由のCognos Analytics環境においてレガシーツールを使用するために必要な対応は下記2点になります。

1. Cognos Analyticsへのジャンクションを透過ジャンクションで作成する
2. ジャンクション名を含めたURLでWebサーバーに正しくアクセスできる構成にする

```HTML:ジャンクションとエイリアスを含んだURL
/<junction name>/<alias> /bi
```

1.に関して、ISAMのジャンクションを透過ジャンクションにする場合は、透過ジャンクションにするオプションを追加して保存することで変更が可能です。
標準ジャンクションを作成するとき同様、-j や -J のオプションは引き続き必要となります。

2.に関して、対応策としては2案考えられます。
案① ゲートウェイで指定しているエイリアス名をジャンクション名にする
案② ISAMで指定したジャンクション名を含んだ、エイリアスをゲートウェイで定義する

案①の場合、ISAMにアクセスする際のURLから変わってしまい影響範囲が大きそうなのでオススメはしません。

案②の場合、ゲートウェイ、Cognosレベルでの対応が可能で、実質対応するならこちらの案になるかなと思っております。

案②の具体的な対応としてはAliasで定義するエイリアス名にジャンクション名も追加して定義することになります。
(前) Alias /ibmcognos /opt/ibm/cognos/analytics/webcontent
(後) Alias /cogjunction/ibmcognos /opt/ibm/cognos/analytics/webcontent

ゲートウェイとしてIHS (IBM HTTP Server)を使用している環境では、httpd.conf、cognos.confのconfファイルでAliasの設定をしている箇所、URL Rewrite ruleの定義をしている箇所が修正対象になります。

また、Cognos ConfigurationのゲートウェイURIとゲートウェイ用Controller URIでしているエイリアス名も変更する必要があります。


#発生する事象

この透過ジャンクションの設定をせず、標準ジャンクションを使用しているままでレガシーツールを使用すると「404 Not Found」ページが返されツールの起動が実行できない、という事象が発生します。
レガシーツールを使用した際のURLはと下記にようになるのですが、

```HTML:リクエストしたいURL
http://<hostname>:<port>/<junction name>/<alias>/bi/v1/disp
```

ISAM、IHS、CognosでURL Rewriteが行われた結果、下記のようにジャンクション名が2回繰り返された形でアクセスする挙動となってしまうようです。

```HTML:エラーページが表示される際のURL
http://<hostname>:<port>/<junction name>/<junction name>/<alias>/bi
```

#まとめ

透過ジャンクションの設定と、ゲートウェイのエイリアスの定義を修正することで、ISAM経由のCognos Analytics環境でもQuery StudioやEvent Studioのようなレガシーツールが使用可能になります。
[自分用メモ] はじめてのGoogle Cloud Functions（Go言語編）

# 注意
ここに書かれていることは、すべて下記の公式ドキュメントに書かれているものです。このブログは、あくまで自分用メモになります。

公式ドキュメント → https://cloud.google.com/functions/docs

# Google Cloud FunctionsとGo
Goが使えるようになったのは2019年1月（[参考記事](https://cloud.google.com/blog/products/application-development/cloud-functions-go-1-11-is-now-a-supported-language)）。

2020年9月現在、使えるGoのバージョンは1.11と1.13のみ（[参考記事](https://cloud.google.com/functions/docs/concepts/go-runtime)）。

# 関数を作る
ローカルの開発環境に、適当に次のような関数を作る。

```go:hello.go
package hello

import (
	"fmt"
	"net/http"
)

func Hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World!")
}
```

外部ライブラリとかを使いたければ、go.modを書けば良い。

# GCPプロジェクト作成
適当にプロジェクトを作っておく。

[ここ](https://cloud.google.com/functions/docs/quickstart-go?hl=ja#before-you-begin)に書いてある「APIの有効化」とかが必要かも。

# gcloudコマンドでデプロイ

```bash:事前準備
# ログイン
$ gcloud auth login
# 操作対象のプロジェクトを設定
$ gcloud config set project プロジェクトID
```

```bash:関数のデプロイ
$ gcloud functions deploy Hello --runtime go113 --trigger-http --allow-unauthenticated
```

`Hello` の部分は、Goで書いた関数名と揃える必要があるっぽい。

# 実行
先ほどの `gcloud functions` コマンドの結果に、次のようなものが含まれている。このURLにアクセスすればよい。

```bash
httpsTrigger:
  url: https://us-central1-my-first-function-xxxxxx.cloudfunctions.net/Hello
```

![スクリーンショット 2020-09-07 16.02.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58650/63fab47f-3a61-415a-9698-dc2ed375c562.png)
【GAS】自動で別のスプレッドシートからコピペしてくれるボタンが欲しかった

#経緯
[【Exel】横書きで書かれた諸々を関数で縦書きの脚本にしたかった](https://qiita.com/nanana_monokaki/items/1542b27d26c6cf1cf75a)

の記事に書いた通り実装してみたものの、もはやコピペする作業すらめんどくさいのではないかと思った。
なので、上記記事の別バージョンとして、ワンタッチ式台本化ツールを作ることにした。

#やりたいこと
1. B2セルに`台本化したい漫画の仕様書のURL`を書く
2. B3セルに`台本化したいシート名`を書く
3. ボタンを押したら台本が出来上がる

#仕組み
経緯にある通り、すでに基礎はできている。
要は、元となる仕様書を全部コピってきて、台本化してくれるシートに張り付けてくれればいい。

作りたいものは
`コピー元のシートを全コピーして、コピー先のシートに張り付けてくれるスクリプト`だ

#実装
そんなわけで、作りました。
こちらも大体コピペさせていただきました。

[GASで別スプレッドシートの値のある全範囲をコピー&ペーストする方法](https://yokochan-y2.com/google-apps-scriptgas-copy-paste-spread-sheet/)

ありがとうございます。


```javascript:gas

/*
*
*メイン処理
*仕様書全部コピってペーストしたい
*台本化はシート側の関数でやってくれる
*
*/

function getScenario() {
 var sv = SpreadsheetApp.getActiveSpreadsheet();//このスクリプトが反映されてるスプレッドシートから
 var sheet = sv.getSheetByName("swich");//swichシートを選んで
 var sheet_name = sheet.getRange(3, 2).getDisplayValue();//B3セルに記入された文字列を取得
 var adress = sheet.getRange(2, 2).getDisplayValue();//B2セルに記入されたurlを取得
 var ss_copyFrom = SpreadsheetApp.openByUrl(adress); //コピー元のマスターデータのあるスプレッドシートキー
 var ss_copyTo = SpreadsheetApp.getActiveSpreadsheet();
 var sheet_copyFrom = ss_copyFrom.getSheetByName(sheet_name); //コピー元のスプレッドシートの値を抜き出したいシート名
 var sheet_copyTo = ss_copyTo.getSheetByName('change_scenario'); //ペーストする自分のスプレッドシートのシート名

  sheet_copyTo.clear();// 一旦コピペ先のシートをクリア。

 var lastRow = sheet_copyFrom.getLastRow(); //最終行を取得
 var lastColumn = sheet_copyFrom.getLastColumn(); //最終列を取得

 var copyValue = sheet_copyFrom.getRange(1,1,lastRow,lastColumn).getValues(); //コピー元のシートから値の入っている全範囲をコピー
  sheet_copyTo.getRange(1,1,lastRow,lastColumn).setValues(copyValue); //自分のシートにコピーした値を全範囲をペースト
}


```

このスクリプトを反映させたボタンを置けばOK。
他の人が使うときは、初回のみ許可するくだりがあるので注意？が必要。


#参考
[GASで別スプレッドシートの値のある全範囲をコピー&ペーストする方法](https://yokochan-y2.com/google-apps-scriptgas-copy-paste-spread-sheet/)
[スプレッドシートにgasを設定したボタンを置いて実行](https://www.atmarkit.co.jp/ait/articles/1708/14/news011.html)
LaravelでS3アクセスが403 Forbiddenエラー

Laraelで以下のようなコードを書いた時に

```php
Storage::disk('s3')->put('hoge.csv', 'あいう');
```

```
Error executing "PutObject" on "https://bucket-name.s3.ap-northeast-1.amazonaws.com/hoge.csv"; AWS HTTP error: Client error: `PUT https://bucket-name.s3.ap-northeast-1.amazonaws.com/hoge.csv` resulted in a `403 Forbidden` response: ...
```

といったエラーが表示された。
S3の権限設定は`config/filesystems.php`で行うため該当ファイルを見ると、シークレットアクセスキーが間違っていることを確認。修正して再実行。しかしまったく同じエラーが出続けます。
バケットポリシーやIAMの設定を見直しても問題なく、aws cliからPutObjectを試してみるとうまくいくため権限は設定できているようだった。


## キャッシュが原因
原因はLaravelのキャッシュ設定で

```
php artisan cache:clear
php artisan config:clear
php artisan config:cache
```

上記コマンド実行でLaraelのキャッシュをクリアしたところ問題なくPutObjectができるようになった（おそらくどれか一つのコマンドでいいと思うが未検証）。最初に間違ってシークレットアクセスキーを設定してしまったものをキャッシュしてしまい、永遠にエラーが吐かれていたようだった。
Ruby カロリー計算　アウトプット

自分用のアウトプットです。

食べた食品のカロリー計算をするプログラムをしました。

M = 食品の品数
N = 人数
food = 1gあたりのカロリー
eat = 何g食べたか
carolie = トータルカロリー 

```ruby:qiita.rb
M,N = gets.chomp.split(" ").map{|i| i.to_i}

food = []
i = 0
M.times do 
  i = (gets.to_f / 100)
  food.push(i)
end


eat = []

N.times do
  i = gets.chomp.split(" ").map{|i| i.to_i}
  eat.push(i)
end

i = 0
f = 0
total = []
count = N
count1 = M - 1
calorie = 0

while count > 0 do
  for s in 0..count1 do
    calorie += (food[i] * eat[f][s]).floor
    i = i + 1
  end
  total.push(calorie)
  calorie = 0
  i = 0
  f = f + 1
  count = count - 1
end


puts total
```



あまりfor文使い慣れていないのでその点今回使えたのはよかったですかね。
おそらく今回２次元配列を使えばもっと凝縮できた感がありましたが、うまくいきませんでした。。。
Microsoft Forms ProはDynamics 365 Customer Voiceに生まれ変わりました

#Forms Proとは
Forms ProがGAされて1年程度でしょうか、あっという間に生まれ変わってしまいました。
Forms Proの前はVoice of Customer というアドオンでしたので、懐かしく感じますね（？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190486/d58dc333-3e16-b4c6-f980-b6911799880b.png)

Forms ProはFormsと同じくアンケートとる機能ですが、
データがDynamics 365（PowerAppsモデル駆動アプリ）に連携されていました。

あまりにも早いForms Proの終了により、私がせっせとForms Proの仕様についていろいろ確認してきたものは過去の思い出となりました。

#Forms Proからの移行
https://docs.microsoft.com/ja-jp/dynamics365/customer-voice/forms-pro-transition

Forms Proの機能をカバーしているとのことですが、まだ対応していなさそうなところがあります。
以下のエンティティにCustomer Voiceで作ったデータが入ってきますが、まだドメインがForms Proです。
調査URLのところです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190486/af0075b9-3ef1-1b00-7c88-b51dafbf18ad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190486/239cef7f-a18a-766b-4975-ec11e5ee0648.png)


手動でURLを修正することで、Customer Voiceへのリンクに変換できます。
ソース調査IDは Customer Voice 調査 エンティティのフィールドです。

アンケートの回答ページ
`https://customervoice.microsoft.com/Pages/ResponsePage.aspx?id=[ソース調査 ID]`

アンケートの作成ページ
`https://customervoice.microsoft.com/Pages/ProjectPage.aspx#FormId=[ソース調査 ID]`

おそらくこんなことしなくてもそのうち対応するものと思いますが、
対応していないということは、調査URLとかのフィールドはいずれ消えてしまう運命なのでしょうか。
Forms Proの時もそうですが、集計のタイミングとかの詳しい仕様に関するドキュメントが少ないので、応用的な使い方をするのは危険なのかもしれません。

それにしても、Docsの表記も気が付けば変わっているし、なかなかついていくのが大変です。
[Nuxt] emulatorでNuxt & Cloud functionsの開発を速くする

# はじめに
cloud functionsを修正したり、ログ差し込むだけで、いちいちデプロイして動作確認するのは時間がかかって面倒！
なので、開発中は一切デプロイが不要になるエミュレータを使うことをおすすめします！

# 前提
- Nuxt(Vue)とfirebase（Cloud functions）で既に開発していること
- この記事ではtypescriptで開発しています
- 最新版の`firebase-admin`（確か古いfirebase-adminでは動作しなかった気がする）

```
// 簡単なディレクトリ構成
.
├── functions
└── nuxt
```


## .runtimeconfig.json作成
functionsの環境変数をエミュレータで読み込むために`.runtimeconfig.json`を作成します

```
$ cd functions
$ touch .runtimeconfig.json
```

`firebase functions:config:get`の内容をコピーします


## functionsのscript
```functions/package.json
"scripts": {
    "emulate": "yarn build && firebase emulators:start --only functions --inspect-functions 9229",
    "watch": "./node_modules/.bin/tsc --watch"
  }
```

`watch`は修正した内容をemulatorに反映させるため必要

## その他
functionsでemulator用に切り替えないといけないものがある場合は、`process.env.FUNCTIONS_EMULATOR`で判定して対応する
（CloudSQLはsocketPathが設定されてると動かないとかがある）

## Nuxt側
functionsのURLをエミュレータのものに差し替える

```
https://asia-northeast1-xxxxx.cloudfunctions.net
↓
http://localhost:5001/xxxxx/asia-northeast1
```

xxxxxはfirebaseの`projectId`が入る

`firebase.initializeApp`しているファイルがあると思うので、その下の行で以下の内容を記述

```
functions.useFunctionsEmulator('http://localhost:5001');
```

### nuxtのscripts
EMULATEの環境変数を入れて、URLなどの切り替えをするといいと思います。

```nuxt/package.json
"scripts": {
  "dev:emulate": "EMULATE=TRUE nuxt-ts"
}
```

## 実行
それぞれ別のタブで実行する

```
$ cd functions
$ yarn emulate
```


```
$ cd functions
$ yarn watch
```


```
$ cd nuxt
$ yarn dev:emulate
```
【Exel】横書きで書かれた諸々を関数で縦書きの脚本にしたかった

#経緯
「クライアントから降りてくる『漫画の仕様書』を、アフレコ台本化するのがめんどくさい」という話をチーム内で聞いて、関数処理で縦書き台本化できないかと検討した。
結果、それなりのものはできた。

#条件
①クライアントから降りてくる仕様書の条件は以下

| AA | BB | CC | DD | 漫画セリフ | 音声 | GG | 補足 | II | JJ | KK |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|:-:|:-:|:-:|:-:|:-:|キャラ1「セリフが書いてある」|セリフが書いてある|:-:|いわゆるト書き部分。芝居や描写の指定|:-:|:-:|

※アルファベット部分に関しては、いろんな事情を鑑みて割愛

②基本的には①のカラム構成で降りてくるので、コピペで今後も台本化していきたい。


#やってみた
###①Exelで縦書きで脚本を書くためのシートを用意する

まずはEXELで縦書き台本を作るための、基礎を作らねばならない。
でも、たぶん誰かが既にやってそう。
というわけで探してみた。
……あった。

[アフレコ台本テンプレート](https://d-cimane.com/2019/02/01/scenario/)

こちらのサイト様からテンプレートをダウンロードして、基礎となるシートとした。

###②構成を決める
チーム内でヒアリングして、どんな構成が良いか確認。
結果。

|構成↓|
|:--:|
|ト書き|
|No.|
|キャラ|
|セリフ|

という構造で、右→左に読むという構成に決まった。

###③【関数】セリフとキャラを分離
仕様書の段階では、キャラのみ独立して書かれているカラムはなかったので、①のシートをコピーして、`漫画セリフ`カラムの隣に`キャラ`カラムを作成。

`=IFERROR(LEFT(([@漫画セリフ],FIND("「",([@漫画セリフ])-1),"")`
でキャラ名のみを取り出すことにした。
※IFERRORは、エラー表示が台本に反映されるので噛ましてある。
※スタートは3行目からなのでF3指定になっている

また、`音声`カラムが手入力（！）だったので、これも

`=IF(([@漫画セリフ]=0,"",IFERROR(MID(([@漫画セリフ],FIND("「",([@漫画セリフ])+1,FIND("」",([@漫画セリフ])-FIND("「",([@漫画セリフ])-1),([@漫画セリフ]))`

で取得することにした。

###④【関数】横並びに変換
別のシートに参照用テーブルを作成する。

| ト書き | キャラ | セリフ |
|:-:|:-:|:-:|

ト書き = 補足カラムを参照
キャラ = ③のキャラカラムを参照
セリフ = ③の音声カラムを参照

上記のテーブルを`TRANSPOSE`関数を使い横並びにした。
結果、

|構成↓|
|:--:|
|ト書き|
|キャラ|
|セリフ|

左→右で作ることができた。

###⑤台本に反映
まず、No.の行は`=COLUMN()-1`で取得。
※台本のスタートが2列目

台本はダウンロードしてきた時点で`右→左`に読む構成になっているので、④で取得した`ト書き`、`キャラ`、`セリフ`をそいれぞれの行に割り当てる。

###⑥【関数】代替文字に置換
縦書きにすることで起きる弊害があった。
記号の類、`～`、`…`、`（）`、`「」`、`、`などが、表示不具合を起こしてしまった。

そこで、
`SUBSTITUTE`関数を使い、それぞれ代替文字を当てはめていった。

代替文字はこちらのサイトを参考にさせてもらった。
[縦書き字形](https://freefielder.jp/blog/2013/02/fonts-vertical-style.html)

これでExelでの台本化は完了！

###番外編：スプレッドシートでのあれこれ

よし、できた！と思ってスプレッドシートに反映させた。
我がチームはスプレッドシートとドキュメントに大いに依存していた。
作ったExelはちゃんと反映された。
関数もいい具合に変換してくれて、正常に動いた。
しかし……

細かい悲劇が起きた。

 - セル内で改行した場合に、左→右で改行されてしまう
 - 印刷時（PDF変換時）、文字化けしてしまう

やれやれだぜ。
そんなわけで、スプレッドシート用に修正を行った。

まず
> - セル内で改行した場合に、左→右で改行されてしまう

に関しては、対象のセルを
`表示形式`>`方向`>`右から左方向のセル`
に設定することで対応できた。
ぶっちゃけ全選択して、この設定かければいい。

> - 印刷時（PDF変換時）、文字化けしてしまう

これはなかなか厄介だったが、結局何のことはない。
`Sawarabi Gothic`
というフォントに変えたことで、文字化けは解消した。

以降、降りてきた「漫画の仕様書」はコピペすれば自動的に台本化してくれる。

****

そんなわけで、Exelでの脚本の作り方でした。
今後のためにもメモしておきたかったので書きました。。


#参考まとめ
[アフレコ台本テンプレート](https://d-cimane.com/2019/02/01/scenario/)
[縦書き字形](https://freefielder.jp/blog/2013/02/fonts-vertical-style.html)
Raspberry Pi ＋ Selenium 環境構築

# 参考URL
https://sun0range.com/information-technology/raspberry-pi-selenium

# 構築手順

## ドライバーインストール

### ファイルの取得
URL：https://launchpad.net/ubuntu/trusty/armhf/chromium-chromedriver/

![スクリーンショット 2020-09-07 15.29.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326104/feb37a9a-dc49-c96f-c228-01cf977fc6e0.png)
![スクリーンショット 2020-09-07 15.29.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326104/7a1144d9-f17d-221b-b6ac-ea6e0aa8f1b4.png)

### インストール

```
sudo dpkg -i chromium-chromedriver_65.0.3325.181-0ubuntu0.14.04.1_armhf.deb
```

## Pythonモジュールのインストール

```
pip3 installl selenium
```

# Seleniumのテスト

ブラウザを開いてYahooのトップページのキャプチャを取得

``` python:test_selenium.py
from selenium import webdriver
import traceback

def main():
    try:
        chrome_option = webdriver.ChromeOptions()
        # Headlessで実行したい場合はheadlessオプションをつける
        #chrome_option.add_argument('--headless')
        chrome_option.add_argument('--disable-gpu')
        chrome_option.add_argument('--no-sandbox')
        chrome_option.add_argument('--disable-setuid-sandbox')
        driver = webdriver.Chrome(executable_path="/usr/lib/chromium-browser/chromedriver", options=chrome_option)
        driver.get("http://www.yahoo.co.jp")
        driver.save_screenshot('screenshot.png')
        driver.quit()
    except:
        print(traceback.format_exc()) 
        driver.quit()

if __name__ == '__main__':
    main()
```

実行

```
python3 test_selenium.py
```
[ASP.NET Core SignalR] ハブクラス以外からメッセージを送信する（サーバからメッセージをプッシュする）

# チュートリアルWebアプリの場合

https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/signalr?view=aspnetcore-3.1&tabs=visual-studio
上記公式のチュートリアル通りに作成した場合、ハブは以下のような実装になる

```C#
namespace SignalRChat.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}
```
上記の場合、クライアントからSendMessageがコールされた場合に"ReceiveMessage"を送信する
→ クライアントからトリガとかける要求/応答型

# ハブクラス以外からメッセージを送信する

```C#
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
using SignalRChat.Hubs;

namespace SignalRChat
{
    public class app
    {
        private IHubContext<ChatHub> Hub
        {
            get;
            set;
        }
        public app(IHubContext<ChatHub> hub)
        {
            Hub = hub; // ハブコンテキストを取得
        }
        public async Task pushMessage(string msg)
        {
            await Hub.Clients.All.SendAsync("pushMessage", msg); // メッセージ送信
        }
    }
}
```

ハブクラス内でメッセージを送信する場合は、
`Clients.All.SendAsync(...)`、`Clients.Caller.SendAsync(...)`、`Clients.Others.SendAsync(...)`等送信先を選択できるが、
ハブクラス以外では`Hub.Clients.All.SendAsync(...)`しか使用できない
ハブクラス内ではクライアントがトリガとかけている要求/応答型となっており、要求元がいるため要求元のみに応答を返す、要求元以外に応答を返す、全クライアントに応答を返すことができる。
それに対して、ハブクラス以外ではサーバ起点となっており、要求元がいないため、全クライアントに送信することしかできない。

参考
https://docs.microsoft.com/ja-jp/aspnet/core/signalr/hubcontext?view=aspnetcore-3.1
https://github.com/aspnet/SignalR-samples/tree/master/StockTickR/StockTickRApp
キャッシュ、クッキー、セッションの保存先


##キャッシュとは
- キャッシュ(cache)とは、訪問済みWebサイトのHTML、CSSなどの情報を<b>クライアント側</b>に保存する機能
- 保存先ディレクトリは ~/Library/Caches/com.google.chrome　（macOS、Chromeの場合）
- 書き換えたはずのCSSが更新されていない！更新したはずの情報が変わっていない！というときは、
キャッシュが原因であることが多い
- ウインドウ右上のメニューの／履歴／履歴を選択、履歴が表示されたら左上のメニュー／閲覧履歴データを削除するをクリックして削除操作へ

##クッキーとは
- 情報を<b>クライアント側</b>に保存する機能
- 保存先ディレクトリは ~/Library/Application\ Support/Google/Chrome/Default　（macOS、Chromeの場合）
- chrome拡張機能「EditThisCookie」や、デベロッパーツールを使うことで値を編集したり削除することができる

##セッションとは
- ユーザー情報などをセッションIDをもとに<b>サーバー側</b>で保存する機能
- セッションIDはクッキーにて管理するのが一般的
- 保存先はphpinfo()を実行することで確認可能（保存先の項目名はsession.save_path）

##まとめ
- キャッシュ、クッキー　→　クライアント側
- セッション　→　サーバー側

どれがサーバー側でどれがクライアント側がわからなくなることがあったので、
どちらに保存するかという点を理解するために簡単にまとめました。

以下参考記事です。

 [【PHP超入門】Cookieとセッションについて](https://qiita.com/7968/items/ce03feb17c8eaa6e4672#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
WindowsのDockerコンテナ上でmatplotlibを動作させる

# はじめに
WindowsのDockerコンテナ上でmatplotlibを動作させる方法について記載します。
Windowsは、Windows 10 Pro 64Bit バージョン2004で試しました。これより古いバージョンでも試しました。
Docker Desktopは、WSL2に対応させても以前のままでもどちらも大丈夫です。
Dockerコンテナ内なので、そのままだとmatplotlib等のグラフはホスト側に表示されません。
ホスト側(Windows側)のディスプレイに表示させるようにするには、コンテナOSはlinux系だと思いますので、XServerをWindows側に立ち上げて、そのXServerに表示を流し込むようにする必要があります。

# VcXsrvをインストール

まず、*VcXsrv*をインストールします。
インストールが終わったら、Windowsメニューから*VcXsrv*にある*XLaunch*をクリックします。
デフォルトの設定のままでいけます。

*Firewall*の設定は不要のはずです。
また、同じPCで実行するなら不要なはずですが、認証等でエラーになるのであれば下記を試してみてください。
*C:\Program Files\VcXsrv*などにある
*X0.hosts*というファイルを開いてホストのIPアドレスまたはホスト名を追記します。
このファイルは権限がないと編集できないので、プロパティ等で権限追加などを行ってください。
（ちなみに、VS Codeで開くと編集できます）

起動すると、画面右下にVcXsrv X Serverのアイコンが表示されるはずです。
そのアイコンを右クリックして表示されるメニューからApplicationsのxclockを選ぶと下記のようにxclockが起動するはずです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640503/e0083277-f821-1422-2ac2-3c8418565ebf.png)

# docker-compose.yml

ディスプレイの設定として、*docker-compose.yml*に下記を追加します。

```docker-compose.yml
    environment:
      DISPLAY: host.docker.internal:0.0
```

# 日本語表示

日本語表示が必要であれば、*Dockerfile*に以下を追記してください。
*fonts-ipafont*としていますが、もちろん別のフォントでも構いません。

```Dockerfile
RUN apt-get update && apt-get install -y fonts-ipafont
```

# 動作させたプログラム

動作させたプログラムとしてはこんな感じです。

```test.py
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-3, 3, 0.1)
y = np.sin(x)
fig = plt.plot(x, y)
plt.show()
```
# matplotlib
Docker内で上記プログラムを実行すると下記のようなグラフが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640503/1ba5d9ed-3cb7-2ba6-ffcb-865aa6145345.png)

# おわりに

うまくグラフが表示されましたでしょうか！？
以上ですが、皆様の開発効率向上に寄与できれば幸いです。
RSpecとminitestのおおまかな違い

#はじめに
railsで最もよく使われるテスティングフレームワークはRSpecという話をよく聞きますが、
ruby標準で使用できるminitestとの違いについてまとめてみました。

#RSpecについて
RSpecを使う理由は「最初からいろんな機能が全部入ってて便利だから」。
ちょっとテストコードのここだけを共通化したい、とか、モックで少し凝ったことをやりたい等、RSpecの標準機能でほとんど完結させる事ができる。

#minitestについて
簡単なRubyプログラムの動作確認をしたりするときに使う。
デフォルトでRubyにインストールされるので、すぐに使えて便利。
RSpec並みに凝ったことをやろうとすると、プラグインをたくさん入れたり、継承、モジュール等を駆使することになるため、業務レベルのテストコードではminitestはあまり使われていない。

#統合テスティング環境としての RSpec
実利的な観点から minitest よりも RSpec のほうが好ましい点がある。
minitestが 「テスティングフレームワーク」であるのに対して、Rspec が「統合テスティン グ環境」であることを目指しているという点。

RSpec は、振舞定義用の DSL の提供に加えて、様々なテスト関連ライブラリや周辺ツールを統合したり、標準サポートしたりといった試みを積極的に続けている。以下にその代表的なものを記述する。

・RSpec 実行結果の色付け (レッドバー/ グリーンバー表示) の標準サポート
・モック や スタブ といったテスト技法の支援、関連ライブラリとの統合
・保留 (pending) のサポート
・Rake や RCov、Heckle、AutoTest (ZenTest) といった周辺ツールとの統合
・Ruby on Rails のサポート
・様々な形式による実行結果レポート (例:HTML 出力) 。
・TextMate との統合
・などなど

※各項目について詳しくはRSpec 公式サイトの該当ページ参照


上記周辺ツールへの積極的な統合・サポートにより、RSpecの標準機能でできる事が多いため、広く使用されているのではないかと推測できる。

今後、RSpecを使用したテストについて学んで行きたい。
Pythonのseabornで描画したヒートマップ上に垂直線を引く方法

# はじめに
　ヒートマップは、横軸と縦軸に空間的な座標をとって表示することが良くあります。それに加え、横軸に時間、縦軸に周波数をとるSTFT（Short-Time Fourier Transform)の結果を描画するといったように、横軸を時間に取りたいという時があります。その時に、解析においてイベントがいつ発火したのかを図に入れるために、任意の場所に垂直線を入れたいなと思いました。seabornで垂直線を引く方法が、なかなか見つからなかったので備忘録として残しておきます。

# 目標
　ヒートマップに垂直線を入れる

# 方法
　普通にaxvlineを使って入れることが出来るらしい。ということで、実際にやってみた。

```python:vline_heatmap.py
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

# サンプルの配列作成
arr = np.random.rand(20, 20)

# ヒートマップの表示（左側）
fig, (ax1, ax2) = plt.subplots(1, 2)
sns.heatmap(arr, vmin=0, vmax=5, cmap="jet", ax=ax1)

# ヒートマップに垂直線を入れて表示（右側）
sns.heatmap(arr, vmin=0, vmax=5, cmap="jet", ax=ax2)
ax2.axvline(x=4, linewidth=2, color="w")

# 描画
plt.show()
```

# 描画結果
　左に垂直線なし、右側に垂直線ありの描画結果を示します。
![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81253/a9c335b4-b828-9c2c-42bb-d60a5de0995e.png)

# ご意見など
　本記事のコメントに書いていただくか、以下のメールアドレスまでお願いします（[at]を@に変えてください）。

akira.kashihara[at]hotmail.com

# 参考
1の記事を参考に、垂直線を調べて辿ったところ、2の記事に行き当たり、試してみました。
直接書いている他の記事などありましたら、教えていただけると助かります。

1) [seabornを使ったグラフで、任意のy軸上の位置に横線を引く](https://teratail.com/questions/196737)
2) [matplotlib.pyplot.axvline](https://matplotlib.org/3.3.1/api/_as_gen/matplotlib.pyplot.axvline.html)
[ASP.NET Core SignalR] ハブからアプケーションデータを操作する

# 目的

以下の記事でASP.NET Core SignalRを使ってチュートリアル通りにWebアプリケーションを作成したが、サーバ側の処理がハブで完結しており、他クラス間の参照方法が不明であったため調査した。
https://qiita.com/takmot/items/7fc13b50a3c8d0f6d2aa

```C#
private int state = 0;  // サーバ状態
```
このようなサーバ側で管理している状態をクライアントに送信したい

# ハブでの状態管理について

以下のようにできないか。

```C#
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRChat.Hubs
{
    // ハブ
    public class ChatHub : Hub
    {
        private int state = 0;  // サーバ状態

        public async Task getState()
        {
            await Clients.Caller.SendAsync("getState", state.ToString());
        }
    }
}
```

以下のように公式に記載があり、ハブクラスにサーバの状態等を保持して管理することはできない。
https://docs.microsoft.com/ja-jp/aspnet/core/signalr/hubs?view=aspnetcore-3.1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695430/4c4e3cea-a48a-393d-e34b-fc728c32da29.png)

# 状態管理用のクラスから取得する

以下の方法でサーバ側で管理している状態をクライアントに送信することができた

- 別途状態管理用にクラスを作成する

```C#
namespace SignalRChat
{
    // 状態管理用クラス
    public class app
    {
        private int state = 0;  // サーバ状態
        
        public int getState()
        {
            return state;
        }
    }
}
```
- ハブクラスでappクラスからサーバ状態を取得する

```C#
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace SignalRChat.Hubs
{
    // ハブ
    public class ChatHub : Hub
    {
        private readonly app _app;

        public ChatHub(app App)
        {
            _app = App;  // コンストラクタでappのコンテキストを取得
        }
        public async Task getState()
        {
            int state = _app.getState();    // appからサーバ状態取得
            await Clients.Caller.SendAsync("getState", state.ToString());   // 呼び元にstateを返す
        }
    }
}
```

- startup.csを変更

```C#
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddSignalR();
            services.AddSingleton<app>(); // 追加
        }
```

以下、参考にした公式のサンプル
https://github.com/aspnet/SignalR-samples/tree/master/StockTickR/StockTickRApp
git で 正規表現を使った操作したい

# 概要
- ブランチに対して，gitコマンドを一斉操作したい場合
- git branchコマンドに対して grepでブランチ絞り込み
- パイプでつなげて，xargsで整形 任意のgitコマンドを渡す

# 例.リモートブランチで一致したブランチ名だけfetchしたい

```
git branch -r | grep "origin/develop*" | xargs -L 1 git fetch
```
Laravel入門 Macでの環境構築の仕方

## 動作環境

Mac OS Catalina
Laravel 6.18.35
php 7.3.21 

## この記事について

自分がmacでlaravelの環境構築をする際にずいぶんエラーに悩まされたので、同じようにエラーに悩む人のために環境構築手順をまとめておきます。

## インストール

### はじめに


laravelのインストール手順に関しては二種類あって

- virtual machineを使う仮想間環境を用意する方法
- ローカルのホストに環境を用意する方法

この二種類があって公式からは前者が進められている

### virtual machineを使う仮想間環境を用意する方法

ここでは詳細な説明は省きます。
詳しいやり方に関しては下記を参照してください。
https://laravel.com/docs/6.x/homestead#first-steps

### ローカルのホストに環境を用意する方法

#### 前提条件

前提条件として環境にこれらが必要です。

PHP >= 7.2.0
BCMath PHP Extension
Ctype PHP Extension
Fileinfo PHP extension
JSON PHP Extension
Mbstring PHP Extension
OpenSSL PHP Extension
PDO PHP Extension
Tokenizer PHP Extension
XML PHP Extension

phpのバージョン以外は特に大きくは気にしなくても大丈夫です。

#### インストール方法

①まずはcompoerをダウンロードする。

laravelをインストールする前にパッケージ管理ソフトである
composerをインストールする必要がある

- macの場合

homebrewで入るのでいつも通りhomebrewで入れましょう。

ターミナルで下記を実行する

```
brew install composer
```


homebrewがわからない人へ

下記の記事を参考にmacにhomebrewを入れましょう
今は特に何を入れているのか分からなくても問題ないです
https://qiita.com/zaburo/items/29fe23c1ceb6056109fd


- 他の場合


公式からダウンロードしていれてください
https://getcomposer.org


②次にlaravelを入れる

composerが入ったらcomposer経由でlaravelをインストールします


ターミナルで下記を実行する

```
composer global require "laravel/installer"
```


③ 最後に環境変数の設定、zprofileをいじる

ターミナルで実行する

```
echo "export PATH=~/.composer/vendor/bin:$PATH" >> ~/.zprofile
source ~/.zprofile
```

下記のコマンドで環境変数がきちんと設定されているか確認する

```
composer global about
```


## 開発の手順

これでlaravelがインストールされたので、開発が進めれます。
基本的にコマンドラインから実行していきます。

### プロジェクトの作成

アプリを開発するディレクトリを

```
mkdir ディレクトリ名
```

これで作成できます
ディレクトリ名は好きにつけてokです

```
cd ディレクトリ名
```

これで作成したディレクトリに移動します
このディレクトリの中でアプリを開発していきます
下記のコマンドで

```
laravel new laravelapp
```

するとzip extentionがないと言われる。

macのcatalinaの場合これでは無理なので代わりに,composer経由で行う

```
composer create-project --prefer-dist laravel/laravel test_app
```

これでtest_appの部分をアプリ名にして実行する
公式では「laravel new アプリ名」でできるらしいんですけど、
どうにもmacのcatalinaではうまくいかないらしいです。
まだ解決策が見つかってないらしく外国の方が嘆いてました。

下記参照
https://github.com/laravel/framework/issues/30386

本題に戻ります。
次にこれをターミナルで実行して、ローカルサーバがたつか確認しましょう

```
cd test_app
php artisan serve
```

laravelのページを表示できれば成功

![https---qiita-image-store.s3.ap-northeast-1.amazonaws.com-0-200860-6dcc259c-6f8b-eef2-eea1-8c9b34e1fb46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537540/7db0c709-fd28-bc51-fae9-d1ec08c01cff.png)





## トラブルシューティング

まれにcomposerからでもlaravelを使えないことがあるみたいで、そういう場合はdockerを使うしかない。
下記に一番簡単なlaradockでの環境構築の方法を載せておく。

### dockerでlaradockで環境構築する

これ見てやるとできる、laradock
https://www.techpit.jp/courses/laravel-line-bot/lectures/11539279


mkdir laravel-linebot
cd laravel-linebot
git clone https://github.com/Laradock/laradock.git

.envファイルを編集
APP_CODE_PATH_HOST=../laravel
DATA_PATH_HOST=../data

cd ~/laravel-linebot/laradock
docker-compose up -d workspace php-fpm nginx

docker-compose exec workspace composer create-project --prefer-dist laravel/laravel . "6.8.*"










## 参考記事

laravel公式ドキュメント
https://laravel.com/docs/6.x/installation

laravelコマンドで詰まった時に見た記事
https://qiita.com/endeavor/items/77f7017473c95c42fc29
https://iiiso.ti-da.net/e8647248.html
Xplenty: Salesforceコネクションの設定方法

#APIアクセスが可能なライセンスかを確認する
確認は[こちら](https://help.salesforce.com/articleView?id=000326486&language=ja&type=1&mode=1)。

#XplentyからSalesforceへ接続するための準備
Salesforceにログインし、画面右上の歯車アイコン（設定）をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/c102ba40-7087-1379-36b8-050748eef0af.png)

アプリケーションを検索し、候補リストから「アプリケーションマネージャ」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/8c26b986-6415-49f6-1b66-5e08bb649f0d.png)

右上の新規接続アプリケーションをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/6573d1b3-e2b9-51de-4d30-5374430f17b0.png)

必要な情報を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/15bf484b-83b1-7ccf-9637-dc24bf8215f8.png)

1. 「OAuth設定の有効化」、「デバイスフローで有効化」にチェックをつける
2. 「利用可能なOAuth範囲」で「データへのアクセスと管理(api)」を選択する
3. 保存する。（保存後、接続アプリケーションが有効になるのに2〜10分程度かかります。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/928c50df-a829-22a5-cf5e-9abe26f880ae.png)


#XplentyでSalesforceへのコネクションを作成する
Connection作成でコネクタ一覧からSalesforceコネクターを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/bb09fdef-ab80-adc1-65aa-fd0d0bc92236.png)
EnvironmentでProductionを選択し、Authenticateをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/c16cd42f-3bb1-723f-865c-47507d96ac50.png)
ログイン画面が表示されるのでユーザー、パスワードが求められる場合、正しい情報を入力した後、アクセス許可の画面にて「許可」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/f488e728-6fee-a07d-00e2-4845c49ec9b2.png)



コネクション名称を入力し、「Create Connection」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65461/d31f2a4a-fbe0-46c6-945c-c5d6b00ffbc3.png)

作成したコネクションは、データソースとしてもディスティネーションとしても利用することができます。
PHP【エラー無し】phpMyAdmin ログイン画面が表示されない件　解決

特にエラーが出ている訳ではないのですが、学習中に某記事に沿って進めていると沼にハマりました。

【問題】
phpMyAdminのログイン画面が表示されない



【解決方法】

❶phpMyAdminをダウンロード(HP右側にあるDownload):raised_hand:
https://www.phpmyadmin.net/
![スクリーンショット 2020-09-07 14.12.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677104/437e2a1b-a4e4-fe22-be17-b447c257fe21.png)


❷phpMyAdminダウンロードファイルをMAMP内>htdocsファイルに移動:raised_hand:
![スクリーンショット 2020-09-07 14.14.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677104/b9ff8f32-8909-7d2b-adb1-8562527bb7fa.png)


❸Chromeで localhost　で検索:raised_hand:
![スクリーンショット 2020-09-07 14.16.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677104/65c9b8b1-9a13-bffe-ed04-80821c201f73.png)


❹以下画像のページが表示されるのでphpMyAdminファイルをクリック:raised_hand:
※under_phpは私のMAMP>htdocsファイルに入っている当記事とは関係ないファイルです。

補足：phpMyAdminからダウンロードしたファイル名を短くするため[phpmyadmin]と変更しているだけです。


![スクリーンショット 2020-09-07 14.17.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677104/4a417e95-9d5d-726c-42df-616fc51389b4.png)



以上４点でたどり着きたかったphpMyAdminページが開きました！
Nuxt.js 開発サーバー立ち上げ時にブラウザを自動起動する方法

ローカル開発時、ローカルサーバーを立ち上げて開発していくかと思いますが、Nuxtのデフォルトの設定では、初回立ち上げ時に自動でブラウザが立ち上がらず、自分でlocalhost:3000にアクセスをしないといけません。

同時並行で複数プロジェクトを進めていると、都度起動したURL（host）に接続するのがとてもめんどくさかったので、自動でブラウザ起動する方法がないかなーと思っていたのですが、良い方法を見つけたのでご紹介します。

## 環境
* nuxt.js : 2.14.0

## node_module "open"を使って解決
[open](https://www.npmjs.com/package/open)

```javascript:nuxt.config.js

import open from 'open'
export default {
  hooks: {
    listen(server, { host, port }) {
      open(`http://${host}:${port}`)
    },
  },
}
```

## 参考
1. [Auto open browser when run dev #1433](https://github.com/nuxt/nuxt.js/issues/1433)
CUPS WEB UI にアクセスできない

「Raspberry Pi で FAX 受信専用サーバ」
https://qiita.com/nanbuwks/items/68a6c9fc9a41dc41dcc7

でプリンタトラブルが発生したので CUPS でアクセスしようとしたら「不正なリクエスト」と出た

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f828e270-4a6f-4983-0b1e-134b28c38f9e.png)



# 環境

```

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 9.13 (stretch)
Release:	9.13
Codename:	stretch
```

- CUPS 2.2.1

cups.conf の記述は
「Raspberry Pi で FAX 受信専用サーバ」
https://qiita.com/nanbuwks/items/68a6c9fc9a41dc41dcc7
の通り。

## アクセス元


Chrome バージョン: 84.0.4147.125（Official Build） （64 ビット）
Raspbian GNU/Linux 9


## 通信路

sshポートフォワードで以下のように通信路を確保

```

 sudo ssh -g -L  632:192.168.0.212:631 123.456.789.012
```

123.456.789.012 というのは例示のためのアドレスで、本来は正当なIPアドレスが入る。
123.456.789.012 アドレスで相手方ネットワークの ssh ドアにアクセスし、相手側ネットワーク内の 192.168.0.212 の CUPS サーバに接続する。

CUPSサーバのサービスポート631と、アクセス元のポート632をバインドしている。


# 症状
「不正なリクエスト」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/21e86e2f-10be-1296-82aa-a506d1b2cedd.png)

上記通信経路を確保しているので、アクセス元からは locahost:632 と司令することで相手方ネットワークの 192.168.0.202:631 にアクセスできる。

なお、相手方ネットワークのいずれかのホストから 192.168.0.202:631 としてアクセスすると正常に動作する。

あれれ〜？ 



「Raspberry Pi 2 をプリントサーバ化しようとしたが失敗したときのメモ - カタカタブログ」
https://totech.hateblo.jp/entry/2015/05/30/155539
を参考にして、http://locahost:632ではなく http://127.0.0.1:632 とするとアクセスできた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/921543cc-2411-75eb-fe76-7763e3bf1496.png)

なんと、HTTP_HOSTを見ているっぽいですね。

「Using host name in /etc/cups/cupsd.conf Listen directive could make cupsd listen on the wrong IP」
https://github.com/apple/cups/issues/4618
が関係しているかな？
SvelteでMarkdown形式で投稿できるブログを1分で構築する

# はじめに
嘘のようなタイトルですが、嘘ではありません！
解説はあとでするので早速、構築してみましょう！

# 構築
1.作業ディレクトリを作成し、作業ディレクトリに移動

```shell
mkdir svelte-md-blog
cd svelte-md-blog
```

2.Routifyのブログテンプレートからプロジェクトを作成

```shell
npx @sveltech/routify init --branch blog
```

3.プロジェクトをVScodeなどで開いて、mdファイルを追加する

```md:src/pages/blog/test.md
---
title: テスト
published: 2020-09-07T21:36:59.459Z
author: oe.kazuma
summary: |
  #### テスト
layout: blog
---

# {title}

### テスト投稿です。
```

4.サーバーを立ち上げて確認

```shell
npm run dev
```

![ezgif-6-496affa2ec49.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217487/5ebc285d-fcd4-3865-2800-162b20d59059.gif)

1分で構築できましたね！
ほぼテンプレートのままなのでこのまま公開とは行きませんが、後はデザインの調整をすればそんなに時間かからずブログ公開できそうですね！

# デプロイ
今回使用しているテンプレート内に既に[Netlify](https://www.netlify.com/)と[Vercel](https://vercel.com/)へのデプロイ設定は内包されているので簡単にデプロイすることができます。
やり方は以下を参照
https://routify.dev/guide/starter-Template/deployment

# 解説
今回使用したテンプレートで主に使用されているライブラリを紹介します。

### Svelte
![svelte.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217487/bcacdc50-76db-b9fa-27e7-cb2e09080ad7.png)


VueやReactと違って仮想DOMがなく、ビルド時にピュアなJavaScriptにコンパイルしてくれるコンパイラー
もっと詳細が知りたい方は、僕が以前書いた記事で詳しく説明していますので参照ください。
[君はVue,Reactの次に来るSvelteを知っているか？](https://qiita.com/oekazuma/items/d3d97f78466be983b19f)


### Routify
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217487/83ad8991-a98f-caa5-a313-10777581124e.png" width="400">


Svelteのファイルシステムベースのルーティングライブラリ
ファイルを生成すると自動的にルーティングを作成してくれたり、SPA、SSR、PWA、メタタグ生成、コード分割など欲しい機能が詰まっているライブラリになってます。
Star数も執筆時点で700~800ほどなので非公式のSvelteのライブラリの中では人気なライブラリとなっています。
細かい設定などもでき、ドキュメントも充実しているので詳しくは以下を参照ください。
https://routify.dev/

### MDsveX
MarkdownでSvelteコンポーネントを使用したり、SvelteコンポーネントでMarkdownを使用したりできるライブラリ
作者はSvelteにもコミットしているpngwnさんという方なので以下のサイトでもペンギンが可愛く登場してます。
https://mdsvex.com/

# さいごに
今回はRoutifyが提供してくれているブログテンプレートに関して紹介しました。
このテンプレートではメタタグ生成などのSEO対策もしてくれていますので、自分のサイトに合わせて文言等を変えればSEO対策もバッチリです。
LightHouseを実行してみた結果、ほぼ全部満点でした！
RoutifyはすごくいいルーティングライブラリなのでまたQiitaで詳しく紹介したいと思ってます。
conda update のオプション -n の引数に入れる環境名について

[この記事](https://qiita.com/sug4r/items/976e4be79848eda6f49f)にある`conda update -n base -c defaults conda` のbaseの部分にはconda仮想環境名が入ることになっているが、ここではデフォルトconda仮想環境名であるbaseが入っている。

この部分を、conda createで作った環境名(名前はenv1とする)とかにしたコマンド`conda update -n env1 -c defaults conda`とすると

```
PackageNotInstalledError: Package is not installed in prefix.
  prefix: C:\Users\username\anaconda3\envs\env1
  package name: conda
```

と出てしまう。

デフォルトconda仮想環境名baseにしたら成功した。
デフォルトconda仮想環境名baseでないと、いけないようだ。

condaパッケージがあるか調べてみる。
調べたい仮想環境に切り替えて、その状態で`conda list`コマンドを使用して確認する。
仮想環境base(今回はdeactivate状態で調べた)には存在しており、仮想環境env1には存在していなかった。

condaパッケージは、デフォルトconda仮想環境baseにのみあることを知った。まあ、当たり前と言えば当たり前か。