OmniAICreator/Qiita-1.07M huggingface dataset:
TRPGオンラインセッションツール「オンセンルーム」の自宅鯖への設置方法まとめ

本記事で取り上げる「オンセンルーム」ついてですが
ツール本体の詳細解説は本家様で確認してください

https://trpgsession.click/

本家様の設置方法の解説ではレンタルサーバーを使うこと前提に公式では解説されていましたが
自前のサーバーにインストールする手段については詳しいことは何も書かれていないため
実際にサーバーに導入して動かせるようになるところまで調べてみました

とはいっても今どきはレンタルサーバーもずいぶん手軽に
利用できるようになっているのでそこまで旨味はないとは思うのですが
やはり自分の思い通りの部屋を作るにはレンタルサーバーのプランによっては容量が足りなかったり
各ツールさんのサーバーに負荷をかけるのも忍びないということもあるだろうと感じます

前置きはこの辺で今回の記事ではオンセンルームをWebサーバーに設置して
ローカルでオンセンルームを稼働できるまでを解説します。

今回導入する「オンセンルーム」を稼働させるのに必要なものは以下のものです。
Ubuntu20.04
Apache
PHP
PHPの拡張モジュールがいくつか

そして今回の導入条件はUbuntu20.04をクリーンインストールした直後に
オンセンルームを導入する想定になります。
すでにWebサーバーを構築している方であればいくつかの工程をスキップできるはずです。

Ubuntu20.04はインストール完了していてユーザー作成まで完了しているものとします。

まずは親の顔より（ｒｙのUbuntuのアップデート
```
sudo -y apt update
sudo -y apt upgrade 
```
続いて必要物のインストール
```
sudo apt -y install php7.4-intl php7.4-xmlrpc php7.4-soap php7.4-mbstring php7.4-curl php7.4-zip php-mysqli php7.4-xml php7.4-gd php unar apache2 net-tools
```
オンセンルームがphpの拡張モジュールphp7.4-xmlとphp7.4-curlが入っていれば動作する記述があったのですが
実際この2つだけでは動かなかったので手当たり次第に拡張モジュールをインストールしています
不要なモジュールについては要検証です

オンセンルーム本体のインストール

```
cd /var/www/html
sudo wget https://github.com/ponta0321/OnsenRoom/archive/refs/heads/master.zip
sudo unar master.zip
cd /OnsenRoom-master
sudo mv * ../
cd /var/www
sudo rm /html/index.html
sudo rmdir /html/OnsenRoom-master
sudo chmod -R 755 /html
sudo chown -R <ユーザー名> /html
sudo service apache2 start
```
1カレントをApache2のドキュメントルートに移動
2オンセンルームをダウンロード
3ダウンロードしたアーカイブを解凍
4解凍した本体に移動
5本体ファイル群をApacheドキュメントルートへ移動
6不要になるindex.htmlとOnsenRoom-masterを削除
7wwwに移動
8ドキュメントルートのパーミッションとオーナーを変更

上記時点でオンセンルームが利用可能となります。
実際に接続するにはifconfigでipを調べて別端末のブラウザ等で
サーバーip/index.phpと入力するとオンセンルームが起動します

以降必要に応じてindex.phpをデフォルトロードする設定をしたり
オンセンルームをネット越しに利用するためにポート開放が必要になります

Apacheからindex.phpを読ませるため以下の設定をします
```
下記Apacheのコンフィグファイルに
sudo vim /etc/apache2/sites-enabled/000-default.conf
下記を追記します。
DirectoryIndex  index.php index.html index.htm
```

ツールにアクセスするために若干手間を取りますがこの時点で正常に稼働しており
今回は稼働させるまでの解説のためここまでとさせていただきます。
バレーボールのプレー動作を分析してみたくて、OpenPose使ってみた。

# 目的

趣味でやっているバレーボールのプレー動作を分析し、良い時と悪い時の違いを研究したい。

# 背景

なんとなくこういうプレー動作しているな、なんとなくこういう傾向があるな、だからこうなんじゃないか、という主観や曖昧さを排除し、客観的にデータからプレー動作の傾向を自分なりに研究したいと思った。

# OpenPoseとは

カーネギーメロン大学のCenter for Technology Transfer and Enterprise Creation (CTTEC)で開発されたソフトウェア。

リアルタイムで複数人数のキーポイントの検出とマルチスレッドができるOpenCVとCaffeを使用したC ++のライブラリで画像から人の体や手、顔など合計130個のキーポイントを検出することができるリアルタイムシステム。

**スポーツ分野での商用利用は不可。**

- wikipedia

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

- OpenPoseのGitHub

https://github.com/CMU-Perceptual-Computing-Lab/openpose

# やりたいこと

動画内のプレー動作をOpenPoseで解析し、動作を可視化する。

# 実行環境

- Google Colaboratory

# 内容

#### 1. OpenPoseのインストール

OpenPoseのリポジトリをクローンしGoogle Colab上にインストールします。
結構時間がかかるので、実行したらしばらく放置で。

```python
import os
from os.path import exists, join, basename, splitext

git_repo_url = 'https://github.com/CMU-Perceptual-Computing-Lab/openpose.git'
project_name = splitext(basename(git_repo_url))[0]
if not exists(project_name):
  # see: https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/949
  # install new CMake becaue of CUDA10
  !wget -q https://cmake.org/files/v3.13/cmake-3.13.0-Linux-x86_64.tar.gz
  !tar xfz cmake-3.13.0-Linux-x86_64.tar.gz --strip-components=1 -C /usr/local
  # clone openpose
  !git clone -q --depth 1 $git_repo_url
  !sed -i 's/execute_process(COMMAND git checkout master WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\/3rdparty\/caffe)/execute_process(COMMAND git checkout f019d0dfe86f49d1140961f8c7dec22130c83154 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\/3rdparty\/caffe)/g' openpose/CMakeLists.txt
  # install system dependencies
  !apt-get -qq install -y libatlas-base-dev libprotobuf-dev libleveldb-dev libsnappy-dev libhdf5-serial-dev protobuf-compiler libgflags-dev libgoogle-glog-dev liblmdb-dev opencl-headers ocl-icd-opencl-dev libviennacl-dev
  # build openpose
  !cd openpose && rm -rf build || true && mkdir build && cd build && cmake .. && make -j`nproc`
```

#### 2. OpenPoseに動画を食わせて解析

適当な動画を用意しておきます。

```python
!cd openpose && ./build/examples/openpose/openpose.bin --video ../input_movie.mp4 --write_json ../json --display 0 --write_video ../output_movie.avi
```

各オプションについては下記。

`--video`

入力となる解析動画のパスを指定します。

`--write_json`

解析結果が出力されるディレクトリを指定します。
今回は動作を目視するだけなので活用はしませんが、体のポイントが書き込まれているようなので、今後の展開でもありますが、後々こいつを読み込んで詳細な分析をするつもりです。

`--display`

結果表示を指定します。
今回は0にしてます。
そもそも何の結果が表示されるのか把握してませんが。。。

`--write_video`

出力となる解析済み動画のパスを指定します。

#### 3. 解析済み動画を確認し目視で解析

`--write_video`に指定したパスの動画を確認します。

今回は著作権の関係もあり、バレーボールの動画が用意できなく、参考にフリー静止画素材を解析した際の結果を掲載します。
動画の場合においても同様に解析が行われ、再生時にワイヤーが体に追従し表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38724/da4ded33-bf61-32c9-cbc7-c955182aa96c.png)
左が解析前、右が解析後。

フリー素材の取得元
https://www.photo-ac.com/

# 作成したコードのGitHub

https://github.com/MamedenQ/OpenPoseExample

雑ですが、ReadMeに使い方が載ってます。

本投稿の内容は主となる部分を抜粋したものとなり、多少使い勝手を良くするため、周辺コードが含まれています。

尚、今回は動画解析について触れましたが、コードには画像解析の処理も含まれているため、興味のある方は閲覧してみてください。

処理についての解説はコード上のコメントやテキストセルの解説を参照願います。

# 今後の展開

目視にてプレー動作を解析することはできたため、次はこの動作結果を比較し、厳密な違いを見つけ出したり、何が違うかを客観的に導けるようにしたい。

# 最後に

スポーツ分野での商用利用は不可とのことだが、スポーツ以外でも色々夢が広がるなと思った。（適当ですみません）
【window10】Wi-Fi（のSSID）が表示されないときに試したこと

最近、新しいポケットWi-Fiを購入しました。windowsで使用したいと思い接続しようとしたら、SSIDが表示されず接続できないじゃん！！！！！！！！となったので試したこと記載します。皆様それぞれ環境が違ったりするかと思いますので参考程度に見ていただけるといいかと思います。

## 解決前後の状態
イメージとして、解決前と解決後の状態を下記に記載します。
接続したいWi-Fi名を仮に「A」とします。

[解決前]
Wi-Fi接続画面にこのWi-Fi「A」が表示されない状態。
![スクリーンショット 2022-07-08 14.51.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480938/ffbcc083-54d8-b633-d1b4-498ef2be1842.png)
（※macでこの記事を書いているため、スクリーンショットはmacの表示画面となってます。）

[解決後]
いろいろ試した結果、Wi-Fi接続画面にこのWi-Fi「A」が表示され、接続可能な状態となること。

また、[こちら](https://itojisan.xyz/%E3%83%8D%E3%83%83%E3%83%88%E3%83%BBwifi/wifi%E3%81%AEssid%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84%E3%83%BB%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84/)と[こちら](https://mobareco.jp/a216694/)と[こちら](https://wifi-kiwami.net/ssid#toc8)のサイトを一部参考にさせていただきました。


## 無線規格の確認
Wi-Fi発信元の無線規格と受け取る側の無線規格（今回はポケットWi-Fiとwindows10のPC）で規格が一致していないと、SSIDのWi-Fi名が表示されないことが起こるみたいです。
>```
>netsh wlan show drivers
>```
コマンドプロンプトにて上記コマンドを打ち、**サポートされる無線の種類**も確認してみましたが問題なさそうでした。。

## ブラウザからWi-Fi設定画面へ
[link1]:[http://192.168.1.1/]
参考にした記事によると、ブラウザで[http://192.168.1.1/](link1)にアクセスするとWi-Fiの設定ができそうです。
>SafariやChromeなどのブラウザから「[http://192.168.1.1/](link1)」にアクセスします。ログイン画面が表示されるのでパスワードを入力して「サインイン」をタップします。

>なお、ルーターの設定画面は、主にブラウザ(safariやchrome等)で指定のIPアドレスを入力して、ユーザー名とパスワードを入力するとアクセス可能です。
>
>例えば、フレッツ光のホームゲートウェイは「192.168.1.1」、バッファローなら「192.168.11.1」になります。
>
>ユーザー名は「admin」「user」、パスワードは「password」などが初期設定となっていることが多いようです。

ということで、[http://192.168.1.1/](link1)にアクセスしました。私は「user」、「password」でサインインできました。

すると、左側の項目に**無線LAN設定>無線LAN簡単セットアップ**というのがあり、[おまかせモード]ボタンがあったのでクリックしました。
![スクリーンショット 2022-07-08 15.57.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480938/62b63900-0b42-6009-f5fc-0adc66a3f98e.png)
この[おまかせモード]ボタンクリックしたあとにポケットWi-Fiの**WPSボタン**を押しました。**これでもうまくいきません。**
ところが諦めてPCを落として**起動し直したら**SSIDのWi-Fi名が表示され、ポケットWi-Fiに接続することができました。

## まとめ
ポケットWi-Fiがwindowsで使えるようになったのはよかった。
この作業をしたあとすぐにパソコンを落としてしまったため、パソコンの起動が影響しているのかどうかが不明瞭なところです。パソコンを起動し直さず、少し待っていたら普通にSSIDのWi-Fi名が表示されていたのか、、、どうだろう。

## 余談
家で接続できなかったwi-fiが[http://192.168.1.1/](link1)で設定したら接続できるようになった！！！！！！
[http://192.168.1.1/](link1)に接続した際、家で使用しているWi-Fi（ポケットWi-Fiではない）が３つ表示されていた。そのうちの１つが接続できていなかったが、ほかの２つは使用できていたため特に深追いはしなかった。
ところが、接続できていないWi-Fiの設定箇所にて、**MACアドレスフィルタリングを使用する**となっていたので、**MACアドレスフィルタリングを使用しない**に変更しました。すると、数年間接続できていなかったWi-Fiに接続できることができました。
この辺も要勉強です。。
【Rails】URLにaタグを付ける


RailsはURLテキストを入れて投稿しても、自動的にリンクを付与してくれません( ꒪⌓꒪Ⅲ)

ユーザーに全く優しくないので、
URLリンク先に遷移できるようにしましょう！

まずは、ヘルパーにメソッドを書いていきます。

ヘルパーは、**application_helper.rb** or **コントローラー名_helper.rb**に記述可能です。
今回は、複数箇所で使用したいので、application_helper.rbに書いていきます！


```ruby:helpers/application_helper.rb
module ApplicationHelper
  require "uri"

  def text_url_to_link text

    URI.extract(text, ['http','https']).uniq.each do |url|
      sub_text = ""
      sub_text << "<a href=" << url << " target=\"_blank\">" << url << "</a>"

      text.gsub!(url, sub_text)
    end

    return text
  end
end

```

#### URI.extractメソッド
**extract(str, schemes) -> [String]**
`http`or`https`の正規表現を検索し、文字列にして返します
受け取った文字列をeachで処理します。

#### インスタンスメソッド gsub

取得したURLテキストをてaタグに変換してくれます。
詳しくはこちら→[参照:instance method String#gsub](https://docs.ruby-lang.org/ja/latest/method/String/i/gsub.html)

ちなみにこれってなんて読むのでしょうか？グスブ？(*ﾟﾛﾟ)ﾝ？

---
最後に任意のビューに下記のコードを追加して完了です！
ビューでヘルパーメソッドを呼び出すときは、メソッド名そのままで呼び出しが可能です。
※ControllerやModelは呼び出し方法が違うので注意です。

```erb:views/posts/show.html.erb
<%= text_url_to_link((h(@post.text).html_safe)).html_safe %>
```
【AWS Glue】Postgre DBからのdynamic frame読み込み並列化

## はじめに

業務でAWS S3上にデータレイク開発を行っています。
プロダクトで使用しているDBからS3へのデータの同期は、AWS Glueで、DBからdynamic frameを読み込み、S3に保存するジョブを実行することで実現しています。

今回上記のやり方でDBで使用しているあるテーブル（データサイズが約40GB）を読み込んでS3に保存しようとした場合、膨大な時間がかかったうえ、途中でエラーで落ちてしまいました。

## 原因をさぐる

Glueのジョブがどのように実行されているかを知るためにまずはSpark UIで確認します。

Spark UIの構築方法は下記の通りです。

リポジトリクローン

```jsx
git clone https://github.com/aws-samples/aws-glue-samples/
```

コピーしてきたフォルダのうち./utilities/SparkUI/glue-1_0-2_0以下にDockerfileがあるため適当なフォルダにコピー、フォルダ内でビルドする

```jsx
docker build -t glue/sparkui:latest .
```

環境変数（git bash @Win上ではAWSの認証情報を直接入れる方法でうまくいった）を設定します。

```jsx
LOG_DIR="s3a://バケット名/sparkHistoryLogs/"
AWS_ACCESS_KEY_ID="xxxx"
AWS_SECT_ACCESS_KEY="xxxx"
```

コンテナ起動、ちなみにWin上ではReadMe通りではうまくいかず、下記のようにコマンドの冒頭にバックスラッシュを入れる必要があります。

```jsx
docker run -itd -e SPARK_HISTORY_OPTS="$SPARK_HISTORY_OPTS -Dspark.history.fs.logDirectory=$LOG_DIR -Dspark.hadoop.fs.s3a.access.key=$AWS_ACCESS_KEY_ID -Dspark.hadoop.fs.s3a.secret.key=$AWS_SECRET_ACCESS_KEY" -p 18080:18080 glue/sparkui:latest "\/opt/spark/bin/spark-class org.apache.spark.deploy.history.HistoryServer"
```

以下のような感じで一つのジョブに対して、さらに細かいジョブの一覧や各ジョブの詳細がみることができます。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610285/9ef4de39-45a0-3d25-67c6-48a266367520.png)



RDSからS3にカタログのあるテーブルをコピーするジョブの場合、

foreachPartition at S3StorageTransforms

rdd at DynamicFrame　→読み込み？

save at DataSink　→S3に書き込み？

というタスクが実行されているようです。

このうちsave at DataSink以外は一つのExecutorで実施しており、特に読み込み時は非常に時間がかかっていました

![Untitled (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610285/edd32e11-0203-8c7c-f0ca-8490df3ecd12.png)


ちなみに失敗したタスクの詳細

![Untitled (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610285/bfd351c9-473c-0cf3-1008-c0c10faef522.png)

## 対策1. dynamic_frameの読み込みを並列化する

DBからの読み込みが明らかにボトルネックになっていることがわかったため、並列して読み込むように変更します。

AWSのドキュメントを参考に、下記のようにcreate_dynamic_frame_from_catalogに以下のオプションを設定します。

```python
df = glueContext.create_dynamic_frame.from_catalog(
    database=db_name,
    table_name=table_name,
    additional_options={"hashfield": hashfield},
)
```

hashfieldには任意の型のカラムが指定できます。（含まれないテーブルは従来通りaddtional_optionsを使わずに読み込み）

その結果、数時間経っても完了しなかったジョブがエラーで落ちることなく、30分程度で完了できました。

## 対策2. hashfieldで指定するカラムを変更する

ところが、よくよく確認してみると、他のテーブルの読み込み時にエラーは発生していないが、読み込んだdynamic frameが０行（ヘッダのみ）となっているものがありました。

読み込みがうまくいかなった要因を調べた結果、指定したカラムがNULL値を含むカラムとなっているケースで発生していました。（NULL値となっている行は読み込まれないようです）

よって、読み込み並列化時に指定するカラムはNot NULL制約となっているカラムとしたほうがよさそうです。

## まとめ

AWS Glueでサイズの大きいデータをカタログ経由で読み込む際には並列化を活用しましょう、またその際にはNULLが含まれないカラムを指定しましょうというお話でした。

## 参考にさせていただいたページ　

[https://qiita.com/pioho07/items/c4638504a2b134af88de](https://qiita.com/pioho07/items/c4638504a2b134af88de)

[https://docs.aws.amazon.com/ja_jp/glue/latest/dg/run-jdbc-parallel-read-job.html](https://docs.aws.amazon.com/ja_jp/glue/latest/dg/run-jdbc-parallel-read-job.html)
Deploy a LineBot with Flask and Heroku


Long time no see guys, here's Xu from Odakyu Electric Railway co. ltd working on the [Wooms](https://www.wooms.jp/) project.

Before we start the Line bot developing, please make sure you've registered a Line account and create a project on 
https://developers.line.biz/ja/services/messaging-api/ and issued the access-token and your channel secret.

## Env
・Python3.10.3
・Ubuntu 22.04
・Heroku
・Messaging API

## Installation
```bash
pip install line-bot-sdk
pip install flask
curl https://cli-assets.heroku.com/install-ubuntu.sh | sh
```

## Directory
```
lineBot_app  
├─ Procfile  
├─ app.py  
├─ runtime.txt  
└─ requirements.txt
```
## Heroku
### About Heroku
A free app building, deploying, managing platform.
<span style="font-size:200%; color:red;">550h</span> for free Dyons. 
The time period during the app is in sleep mod or maintenance mod will be counted as well.
Docs:[Heroku Architecture | Heroku Dev Center](https://devcenter.heroku.com/categories/heroku-architecture)

## Script app.py
#### import 
```python
from flask import Flask, request, abort
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)
import os
```

##### Connect Line bot with messaging API
```python
line_bot_api = LineBotApi([YOUR_CHANNEL_ACCESS_TOKEN])
handler = WebhookHandler([YOUR_CHANNEL_SECRET])
```

##### Define app
```python
app  =  Flask(__name__)
```

#### For checking app status
```python
@app.route("/")
def hello_world():
    return "hello world!"
```

#### Webhook
```python
@app.route("/callback", methods=['POST'])
def callback():
    signature = request.headers['X-Line-Signature']
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return 'OK'
```

#### Write functions here
```python
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    #Repeating function for example
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))
```

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

### Procfile  
```
web: python app.py
```

### runtime.txt
```
python-3.10.3 #heroku supports 3.10.3, 3.10.5
```

### requirements.txt
```bash
pip freeze > requirements.txt
```

## Build and deploy
### Login Heroku
```bash
heroku login -i
```
### Create a new app
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466211/cc20ade5-3890-2231-2c99-4f4823da27b3.png)

### Push to Heroku
```bash
heroku git:clone -a [your-app-name] 
cd [your-app-dir]
git add .
git commit -am "make it better"
git push heroku master
```

### Add Webhook to line bot
```
https://[your-app-name].herokuapp.com/callback
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466211/06af4ca5-97b1-c60d-ed61-6b2f1e982606.png)
Salesforceでレポートの結果がログインユーザにより動的に見えるようにする方法

こんにちは。

１つのレポートで
・田中太郎さんがログインしてみてるレポートは田中太郎さんが所有者の取引先情報が一覧で表示される（他の所有者の取引先は表示されない）

・鈴木次郎さんがログインしてみてるレポートは鈴木次郎さんが所有者の取引先情報が一覧で表示される（他の所有者の取引先は表示されない）

のように動的に見えるレポートの作成は可能です。

通常であればレポートの絞り込み条件で「私の～」（例：商談なら「私の商談」）で絞り込み可能です。
しかしながら、カスタム項目のユーザオブジェクトの参照関係がある場合
「例：商談オブジェクトに所有者とは別に「サブ担当者」のような項目がある場合」
標準の機能だけでは動的に絞り込むことができないと思います。


カスタム項目（例：サブ担当者）のような場合、まずは数式項目を作成します

数式項目（チェックボックス）に以下の数式を作成します
 $User.Id  =  OwnerId 
![数式チェックボックス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/38e9909b-f21e-7497-89bc-d86e6b7db882.png)

この数式を使用すれば
・ログインユーザが取引先レコードの所有者の場合、チェックがつく
・ログインユーザが取引先レコードの所有者でない場合、チェックがつかない

となります。

あとはこのレポートを使用して
「次の文字列と一致する　TRUE」
と設定します。
![所有者.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/1be93ac5-7da4-f374-fbba-b4e4802aa8d2.png)

もちろん今回作成した数式項目を使用すれば、リストビューの絞り込み条件にも使えますので、ユーザは自分の担当する取引先のみを確認する　となりとても便利ですね。
iOSシミュレーターのフォルダをサクッと開くスクリプト

以下のスクリプトを実行すると、現在実行中のシミュレーターのフォルダを開くことができます。

バンドルの中身を確認したり、ドキュメントフォルダにファイルが保存されていることを確認したりしたいときに、このスクリプトがあるとさくっとシミュレーターのフォルダを開くことができるので便利です。

```bash
#!/bin/bash

cd ~/Library/Developer/CoreSimulator/Devices
cd `ls -t | head -1`/data
open .
```

![20211224015340.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81715/93f4129b-7674-2a51-ba3e-110efb09a6b7.png)

<br>

簡単にスクリプトの内容を説明します。

`cd ~/Library/Developer/CoreSimulator/Devices`で、全シミュレーター端末のフォルダが格納されたパスに移動します。

![20211224020308.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81715/297221ea-bdf3-6320-e46c-57cdcc4ee485.png)

<br>

そして、````cd `ls -t | head -1`/data````で、直近で更新されたシミュレーターのフォルダに移動します。

アプリをビルドしてシミュレーターを起動すると、そのシミュレーターのフォルダが更新されるので、現在実行中のシミュレーターのフォルダを開くことができるというわけです。
.bashrcにexitと書く

# .bashrcにexitと書く

linuxでbashを用いているユーザーならみんながお世話になるであろう.bashrc(bashの設定ファイル), これはbashを起動した際に一番最初に実行されるコマンド群が記載されている.

この.bashrcの一行目にexitと書くとすぐにログアウトされることになるだろうというのは想像がつくだろうが試したことはなかった.

これを試してみようとして研究室のウェブサーバーの.bashrcの一行目にexitと書いてみた(書いてしまった).

## 当初の予定

1. exitが記載されているとsshログインしたときにすぐにログアウトされることを確認する.
1. sftpコマンドなどで.bashrcをダウンロードして編集し, 編集したもので上書きする.
1. 再度ログインできるようになる.

## 実際の作業

当初の予定の1までは正しく実行できた.
~~~
herohero@LOCAL:~$ ssh hogehoge@WEBSERVER
herohero@WEBSERVER's password:
Linux orange 4.9.0-19-amd64 #1 SMP Debian 4.9.320-2 (2022-06-30) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Jul  8 15:45:28 2022 from 133.87.45.154
Connection to www closed.
~~~

ちゃんとログインプロセスが走り, そのあとに入力受付をする前にexitコマンドが走ることでログアウトされている.
その後, 問題は.bashrcの編集にて起きた.

手元のPCから
~~~
$ ssh hogehoge@WEBSERVER mv .bashrc bashrc
~~~
を実行し, 再度ログインをしようとしたら
~~~
herohero@LOCAL:~$ ssh hogehoge@WEBSERVER
herohero@WEBSERVER's password:
Linux orange 4.9.0-19-amd64 #1 SMP Debian 4.9.320-2 (2022-06-30) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Jul  8 15:45:28 2022 from 133.87.45.154
Connection to www closed.
~~~
またこれが出てしまう.
そのため, sftp を実行し, .bashrcをダウンロードしてから編集して再度アップロードをしようと試みるも……
~~~
herohero@LOCAL:~$ sftp hogehoge@WEBSERVER
hogehoge@WEBSERVER's password:
Connection closed
herohero@LOCAL:~$
~~~
となった.

どうやら, .bashrcはsftpにも作用しているらしい.

禁断のscpコマンドを実行しようとしたところ(よいこはマネしないでね！！！)
~~~
herohero@LOCAL:~$ scp hogehoge@WEBSERVER:.bashrc ./
herohero@WEBSERVER's password:
herohero@LOCAL:~$
~~~
となり, これも上手くいかない.

結局にっちもさっちもいかなくなって研究室のwebserver管理者に依頼して.bashrcの一行目からexitを削除してもらいました.

## 結論
1. .bashrcはsshだけでなく, sftpにも作用する.
1. .bashrcにexitと書くとログインできなくなる(ログインはするけれど即座にログアウトされる)
1. 管理者に依頼してexitを削除してもらわねばならない.
1. sshでこれを実行するときは.bashrcを編集するターミナルとログインを試すターミナルを分けよう.
Power BI のビジュアルを、メールやTeamsで共有しよう🎉

# はじめに

Power BI で分析をして、その知見を共有するとき、Power BI Reportのリンクを送信するだけしか方法がないと思っていませんか？😁

**Reportの共有リンク**はフィルターはそのままの設定で送れるけど、ビジュアルてんこ盛りのReportの場合、

**このビジュアルについて言いたいんだ！** 

というときに困ることがあります。**「右下のビジュアルなんですけど・・・」** と、結局メールに書く必要がでます😭

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/92a6bce4-fd2d-6189-e066-e463448e1e54.png)

# メールやTeamsでビジュアルだけを共有する

## まずはコピー

そういうときは、**ビジュアルだけをコピー**してメールやTeamsに貼り付けましょう！
Power BI Service で、ビジュアルにマウスオーバーし、右上の**コピー**ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/fbb6ea55-8009-6d97-1dec-a4a08f09b8f0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/86b9d7e3-189a-d189-2b4e-788a93a49d87.png)

## Outlookに貼り付け

Outlook （Web版） に貼り付けてみます。
ビジュアルのみをを画像として貼り付けることができています。
ビジュアルの下に、**Reportへのリンク**と、**データの更新日時**も一緒に貼り付けられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/c4078ce1-7a5f-d254-5eab-cc0349a3595c.png)

## フィルターをかけていた場合

フィルターをかけている場合は、ビジュアル下のテキストにフィルター条件が記載されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/74e95fd9-2f60-dd8f-a4df-e39213df24e1.png)

## Teamsのチャネルに貼る

もちろん、Teamsのチャネルにも貼ることができます。ビジュアルを貼り付けてその下に得られた知見を書く😄

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/53ba41cb-e366-a056-8cc5-2969d20368ed.png)

## ただしチャットには貼れない😥

チャットにはろうとすると、**文字数の制限がある**とアラートがでて、送信ボタンを押せません。
Teamsの仕様をドキュメントを確認すると28KBの制限があるので、これに引っかかっているのか・・😕？
ビジュアルとテキストの他に、HTMLでテーブルタグが使われているようなので、それで28KB超え？
これについてはわかる方、教えてほしいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/daad19c8-26db-1b64-b8c5-98c75a99e1db.png)

>チャットのサイズ	投稿ごとに約 28 KB
>28 KBは、メッセージ自体 （テキスト、画像リンクなど）、@メンション、およびリアクションを含むため、おおよその制限です。

https://docs.microsoft.com/ja-jp/microsoftteams/limits-specifications-teams#chat

# まとめ

様々な共有方法を知っておいて、ストレスなく分析結果を共有できるようにしたいですよね😙
CuraでAdventurer3 用のデータを作成したい

# はじめに
FlashForge社のAdventurer3向けにCuraでスライスしたい！
純正のスライサであるFlashPrintが悪いとかではなく(むしろスタートとしては申し分ない)、
かゆい所に手が届くCuraを使用したかったのです。

※CuraでAdventurer3のプリンタ追加等は済んでいる前提での記事になります。

# 問題点
FlashPrintでスライスして出力したGcodeでは、M104,M140等の温度設定でエクストルーダ指定が必要になります。

```php:FlashPrint Gcode
…
M140 S90 T0 ;←このT0
M104 S245 T0 ;←このT0
…
```

それに対してCuraで出力したGcodeでは、上記のT0指定が記載されません。

```php:Cura Gcode

…
M140 S90 ;←ここ
M104 S245 ;←ここ
…
```

# 解決策
### 環境

+ Cura 5.1.0-beta+304　(Cura 5.0.0でも動作していました)
+ Adventurer 3 ver 1.3.2

### どうやった？
Curaにある"後処理"(Postscript)機能を使用して、M140/M104のコードを修正しました。

+ [Curaインストールフォルダ]は個人のインストール環境に読み替えてください。
+ 私の場合は C:\Program Files\Ultimaker Cura 5.0.0\ でした。
```php:[Curaインストールフォルダ]\share\cura\plugins\PostProcessingPlugin\scripts\ApplyAdventurer3.py
from ..Script import Script

class ApplyAdventurer3(Script):
    def getSettingDataString(self):
        return """{
            "name": "ApplyAdventurer3",
            "key": "ApplyAdventurer3",
            "metadata": {},
            "version": 2,
            "settings":
            {}
        }"""

    def execute(self, data):
        for layer_number, layer in enumerate(data):
            lines = layer.split('\n')
            
            for line_n, line in enumerate(lines):
                if self.getValue(line, "M") in {104,140} and self.getValue(line, "T") is None:
                    lines[line_n] = line + " T0"
                        
            data[layer_number] = "\n".join(lines)
        return data
```

上記のコードを保管しCuraを再起動し、上部メニューより

+ 拡張子 → 後処理 → G-codeを修正 → スクリプトを加える

から、「ApplyAdventurer」が選択できるのでポチッとします。

あとはそのままスライスしてディスクに保存するだけで、加工された状態で保管されるはずです。

# おわりに
結局Adventurer3に転送するためにFlashPrintを起動しているとか言えない。
【備忘録】Pythonを使ったログインや自動投稿の学習を始めるにあたって参考にしたサイト

こちらは、個人的に、pythonとseleniumなどを使って自動ログインや自動投稿をする方法について参考にしたサイトを備忘録としてまとめたページです。

TwitterはPCからの投稿だと既に予約投稿機能がついています。
フォローやいいねを大量にクリックすると、利用制限されます。

ツイッター社のルールに違反するような運用方法は具体的ではないですね。
AIで学習させてそのルールを突破することはできますが。

自動化できるところは利用して、自分のやりたいことをする時間を増やす工夫のひとつとしてプログラム書いてみようと考えています。

# 自動ログインと自動投稿を学習するにあたって参考にしたサイト

## 【コピペだけ】Pythonを使ってTwitterのいいねを自動化する方法
https://modest-life.net/twitter/

## サイト記事を自動でTweetしてくれるbotをPythonで作る 
https://zizou-book-lab.com/python-auto-tweet/

## pythonを使ってtwitterアフィリエイトを自動化しよう 
https://note.com/python_poikatsu/n/n4c1837910c82

## 【Python】TwitterApiを使ってツイートする方法
https://eroplog.com/python/tweet-api

## ツイッターのBotを1ヶ月間運用してみての結果まとめ
https://www.virtual-surfer.com/entry/2018/06/16/190000

## pythonを使ってtwitterで簡単に稼ぐ方法【サンプルコードつき】
https://python-man.club/python_twitter_labour/

##Python】amazonに自動ログインしてみた：seleniumの基本テクニック
https://kirinote.com/python-auto_login/

## 【Python/PHP対応】スクレイピングアフィリエイトで収益化する為のヒント【自動化アフィリエイト】
https://dstrikes.net/2018/11/15/how_to_earning_affiliate_crawler/

## 【Python学習】Twitter API v2をつかって自動投稿 (tweepy利用)
https://vefortec.hatenablog.com/entry/PythonStudy_Tweepy
Selenium NameError: name 'By' is not defined

https://www.selenium.dev/documentation/webdriver/getting_started/first_script/

この記事のとおり実行した場合も

```python:selenium.py
serch_box = driver.find_element(By.NAME, 'q')
serch_button = driver.find_element(By.NAME,"btnK")
```
```
NameError: name 'By' is not defined
```

このように出てしまいます。
その場合

```
from selenium.webdriver.common.by import By
```
をインポートすることで解決します。

参考
https://stackoverflow.com/questions/44629970/python-selenium-webdriver-name-by-not-defined
Message: chrome not reachableエラー


Seleniumでプロセスが複数起動しすぎると、 chrome not reachableエラーとなる

```
ps aux | grep chrome
```

以下のようなものが複数表示されます。
```
ユーザ名 32354   0.0  0.1 38001936  16732 s004  S     2:50PM   0:00.13 ユーザ名/Repositories/Study/python/selenium4/web-driver/chromedriver --port=63118
```

全てkillします。
```
sudo killall chromedriver
```
sudoつけないとNo matching processes were foundエラーになります。

アクティビティモニタでchroome検索して選択して、ツールバーのXボタンでキルもできます。
![スクリーンショット 2022-07-08 15.34.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2713376/adab4748-6604-5be5-eb1f-2418d877a70a.png)


https://stackoverflow.com/questions/692528/mac-os-x-terminal-killall-wont-kill-running-process

https://prograshi.com/language/python/ec2-selenium-chrome-not-reachable/
database "..." is being accessed by other userが出た時

rails db:resetの際に
database "..." is being accessed by other userが出た時の対処法を説明します。

PostgreSQLを再起動させたらrails db:resetは正常に実行される。
```
macの場合
停止
brew services stop postgresql
起動
brew services start postgresql
その後
rails db:reset
```
シフト演算の演習

３２ビットのレジスタに１６進数ABCDが入っている時、２ビットだけ右に論理シフトした値はどれか？

### レジスタ
* レジスタとは、```マイクロプロセッサ（MPU/CPU）内部```にある、演算や実行状態の保持に用いる記憶素子。最も高速な記憶装置だが、一般的なCPU製品で```数個から数十個```（容量に換算して数十バイト程度）と数が限られる。GPUなど特殊なプロセッサでは数万個（数百キロバイト）のレジスタを内蔵するものもある。
出典 https://e-words.jp/w/%E3%83%AC%E3%82%B8%E3%82%B9%E3%82%BF.html#:~:text=%E3%83%AC%E3%82%B8%E3%82%B9%E3%82%BF%E3%81%A8%E3%81%AF%E3%80%81%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5,%E5%86%85%E8%94%B5%E3%81%99%E3%82%8B%E3%82%82%E3%81%AE%E3%82%82%E3%81%82%E3%82%8B%E3%80%82
* レジスタはデータを```一時的に記憶```するための、 一種のメモリです。
* レジスタはこのように何ビットかの 2進数 を記憶するメモリですが、 CPU に組み込まれているレジスタには```カウンタの機能```を持ったものや、```シフトレジスタの機能```を持ったものなどもあります。

出典 http://www.infonet.co.jp/ueyama/ip/glossary/register.html
* レジスタは、データを一時的に記憶する一種のメモリで、 ```記憶容量は 8 ビット、16 ビット、32 ビット …等```です。
* シフトレジスタは、記憶している```データの桁を左右にシフトさせる```ことができるレジスタです。
* シフトレジスタの用途は他にもいろいろありますが、 ```シフトの度に 1 ビット ずつ順にデータを取り出す```ことができますから、 8 回シフトさせると 8 ビット、 すなわち```1 バイトのデータをシリアルに変換```することができます。
これなら 8 ビットの情報でも 1 本の通信回線に乗せることができます。 インターネットでもこのように、 ```データをシリアルに変換して通信```しています。

出典 http://www.infonet.co.jp/ueyama/ip/glossary/shiftregister.html

# 気づき
コンピュータの部品のことか。
プロセッサの中にたくさんあるのか。
シリアルって何？しかしこれは後から調べよう。
問題文はシフトレジスタのことを言っているのか。

```ABCD```を２進数に変換、論理シフトで左から００を加えた。その結果
```00101010111110011```になるのでこれを１６進数に変換
```2AF3```となる。
成功。やった。

数値を２進数で格納するレジスタがある。このレジスタに正の整数xを設定した後、”レジスタの値を２ビット左にシフトして、xを加える"操作を行うと、レジスタの値はxの何倍になるか。ここで、溢れ（オーバーフロー）は、発生しないものとする。

## 気づき
２ビット左にシフトすることは４倍することだから答えは４倍だ。
答えは５倍だった。
奇数なのか。どうしてだろう。説明を読んでみよう。

正の整数を前提としているので今回のシフトは論理シフトらしい。
これの意味がわからない。これ以上説明を読んでもわからないと思ったが他のサイトの解説を読んで理解した。
やっぱり自分の読解力不足だった。

この問題の意味がわからなかった。　レジスタに２進数ので表した整数xを左に２桁シフト、その後整数xを再び加えたため４倍＋１倍で５倍になる。

# 気づき
しかし正の整数を前提としているので今回のシフトは論理シフトが意味がわからない。
多分
登場する整数に負の数がないため符号に考慮しなくてもいいから論理シフトなのかもしれない。

# 非負の２進数b１b２...bnを３倍にしたものはどれか。
```非負とは```
非負の整数ってなんですか？？マイナスではない整数、つまり正の整数のことですか？(´・ω・｀)
当たってますでしょうか！？(>_<)
0と正の整数という意味でしょう。0を含むかどうかに、ポイントがある。

出典 https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1160919306
## 気づき　
２進数には０と１があるから非負の数なのだろう。

# 気づき
３倍とはどのような意味なのかを知らなければならない。
２倍+1倍になることを意識する。
２倍は左にシフトするとできる。だから最後の桁に０をつける。
１倍はその数を足すとできる。
つまり
最後の桁が０であり、元の数が足されているのものが該当する。
なので```ア```
javascriptで外部モジュールのimportが出来ない

# エラー1

javacriptで外部モジュールをインポートする記述のあるsample.jsをコンパイルすると`SyntaxError: Cannot use import statement outside a module`というエラーが出ました。

```sample.js
import { read, write } from './helper';
```

```sh
$ node sample.js
(node:40624) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/home/node/sample.js:1
import { read, write } from './helper';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:353:18)
    at wrapSafe (node:internal/modules/cjs/loader:1040:15)
    at Module._compile (node:internal/modules/cjs/loader:1076:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1166:10)
    at Module.load (node:internal/modules/cjs/loader:988:32)
    at Module._load (node:internal/modules/cjs/loader:834:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47

Node.js v18.4.0
```

エラーメッセージにES moduleをロードするにはpackage.jsonファイルに"type":"module"を設定するか、拡張子を.mjsにしなさいと書いてあります。拡張子を.mjsにするのは名前に違和感があったのでpackage.jsonを用意しました。

```package.json
{
    "type": "module"
}
```

# エラー2

コンパイルし直すと違うエラーがでました。拡張子も付けてないといけないようなので.jsを追加しました。

```sh
$ node sample.js read
node:internal/process/esm_loader:91
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/node/helper' imported from /home/node/sample.js
Did you mean to import ../helper.js?
    at new NodeError (node:internal/errors:388:5)
    at finalizeResolution (node:internal/modules/esm/resolve:405:11)
    at moduleResolve (node:internal/modules/esm/resolve:966:10)
    at defaultResolve (node:internal/modules/esm/resolve:1174:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:605:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:318:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:80:40)
    at link (node:internal/modules/esm/module_job:78:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v18.4.0
```

```diff_javascript:sample.js
- import { read, write } from './helper';
+ import { read, write } from './helper.js';
```
vue3 親から子コンポーネントのイベントを発火

本題の通り

わかりやすかったのでそのまま引用
http://info.yama-lab.com/vue3-vue-js-%E8%A6%AA%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%8D%E3%83%B3%E3%83%88%E3%81%8B%E3%82%89%E5%AD%90%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AE%E3%83%A1%E3%82%BD%E3%83%83/



# 親vue

component を読み込むときに ref を指定する

```oya.vue
<script>
    methods: {
        onPlay(){
            this.$refs.player.play();
        }
    }
</script>

<template>
//重要！ここで ref 指定
    <Player ref="player"></Player>
    <button type="button" @click="onPlay">子のplayを発火</button>
</template>

```

# 子vue

```ko.vue
<script>
    methods: {
        play(){
            alert("hogehoge");
        }
    }
</script>
<template>
    <div>
        anytext...
    </div>
</template>
```

ただ、 created では動かないので、動かしたい場合は
```oya.vue
<script>
    setTimeout(function () {
        this.$refs.player.play();
    }.bind(this), 700);
</script>
```

みたいな感じで処理を遅らせる。

# 引数を渡したい


# 親vue

component を読み込むときに ref を指定する

```oya.vue
<script>
    methods: {
        onPlay(data){
            this.$refs.player.play(data);
        }
    }
</script>

<template>
//重要！ここで ref 指定
    <Player ref="player"></Player>
    <button type="button" @click="onPlay(`testtest`)">子のplayを発火</button>
</template>

```

# 子vue

```ko.vue
<script>
    methods: {
        play(data){
            alert(data);
        }
    }
</script>
<template>
    <div>
        anytext...
    </div>
</template>
```

で行ける。
文章力を向上させようと思った

# まず初めに
この前恥ずかしながらも、初投稿をさせてもらった。
愚痴をダラダラと書いてあるだけだが、[興味がある人](https://qiita.com/Guriko_N/items/6886c0a17313ace90eb4 "IT業界に入って4年目で感じたこと")は読んでみてください。

ドキドキはしながら投稿をしたのはいいのだが、内心誰も読まないだろうと思っていた。

実際は、24時間も経っていない段階で、
・2309 views
・LGTM 12
・ストック 6
正直驚いている。最後まで読んでいないにしろ約2300人はクリックはしており、その中でもいいねと意思表示をしてくださっている人がいる。

嬉しい。シンプルにそう感じた。
それと同時に、もっと文章を綺麗にできたんじゃないかと思った。

何回か読み直しはしたが、明確に何を伝えたいのかが霞まくっている記事だなー、と知っていたが、ポエムだし大丈夫だと思っての投稿だった。

なので、読んでもらい満足してもらえる記事を目指して、文章のコツを学んでいきたい。

# 本題
まず、記事を書くにあたって意識しないといけないことは、

・相手はだれか？（ターゲット意識）
・何を伝えたいのか？（目的意識）
・どうなってほしいのか？（反応・行動）

この三点らしい。

私は、こんなことを全然意識しながら書いていなかった。目的意識や反応・行動が不安定に作られた記事だったので、自分で読んでいても腑に落ちなかったのだと思う。

整理を含めて、実際にどのような記事を書こうとしていたのかを反省する。


# 反省
今回は[前回記事](https://qiita.com/Guriko_N/items/6886c0a17313ace90eb4 "IT業界に入って4年目で感じたこと")を例に、私が足りなかった部分を反省していきたい。

・相手はだれか？（ターゲット意識）
ターゲット・伝えたい人としては、就活生に向けてもっと業界分析や飛び込もうとしている世界に目をしっかりと向けてほしいと思って記載した。

・何を伝えたいのか？（目的意識）
IT業界の技術者を目指している人に、今一度想像している世界と現実の世界にギャップがないかを知ってもらいたい。

・どうなってほしいのか？（反応・行動）
納得してITという途方もない世界に入ってきてほしい。決して悪いことばかりではない。

---------------------------------------

これを踏まえて記事を読み直してみたが、全然意識ができていない。(していない)

上記三点意識して読むと、、、

**・相手はだれか？（ターゲット意識）**
書き出しとタイトルの内容的に、他人のブログを読んでやろうと、フラフラとやって来た不特定多数の人になるだろう。

明確に言うと「暇人」だろう。

なので、ターゲットはなし。本当に伝えたい相手は最初の書き出しでブラウザバックしちゃっただろう。

**・何を伝えたいのか？（目的意識）**
苦し紛れでのまとめでは、「全然思ったようにいかない」と〆ている。

一応、IT業界の人売りといわれる実態を感じて、想像とのギャップを感じてもらえたかもしれない。

が、あまりにも遠回しの伝え方になっている。

**・どうなってほしいのか？（反応・行動）**
同じような境遇の人がいるんだなと感じてもらい、自分も今日頑張ろうかなと思ってもらう。

# まとめ
前回の記事をまとめると
・「暇な人！世の中上手いこといかないけど今日もやっていこうな」
って記事を書いていたことになる。

実際に書きたかった記事は、
・「IT業界に踏み入れようとしいる君！今一度業界分析をしてITの世界にこないか」
となる。


ここまで、違うことを書いていたと思うと笑えてくる。
文章を書く際の意識する大切さがわかった。

今一度、意識する３つのポイントを記載
・相手はだれか？（ターゲット意識）
・何を伝えたいのか？（目的意識）
・どうなってほしいのか？（反応・行動）

因みに今回の記事では
・記事を書いてみようと思う人
・記事を書く際に意識をして書いたほうがいいということ
・あなたも記事をかいてみよう

ってことを少し意識して書いてみた。ちょっとはわかってくれたかな。

文章力を上達させるためには、「起承転結」「逆三角形型」とかの型にはめる等のコツは沢山あるが、興味がある人は調べてみてね。

Qiitaでは、コメントはあまり飛び交うイメージはないけれど、目は通してくれて反応をしてくれる人はいる。是非なにかコメントしてください。

記事を書いてみたいけど、どうしたらいいのかわからない人へ。
技術情報共有サービスQiitaだけれども、今自分が頑張っていることでも、みんな知っている情報でもOutputすることで何か変わるかもしれない。知らんけど。

次は、技術者っぽい記事を書きたいと思います。
Office スクリプトを利用して Power Automate から Excel 方眼紙内の値を利用する 

最新の Excel で利用ができる Office スクリプトは、Power Automate のクラウドフローから呼び出して実行することができます。

手順などの参考: [Power Automate で動かす Office スクリプト(1)](https://qiita.com/Satoshi_Yoshino/items/ab4562df7726705a332e)

この仕組みを利用すれば、 Excel 方眼紙に入力された値を Power Automate から利用できるんじゃないかと思い、試してみました。

# 試してみた結果
思っていたよりも簡単に実現することができました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/2df93f96-495b-6823-2156-6ad2693227d1.png)

書いたスクリプトは次の通り。

```
function main(workbook: ExcelScript.Workbook) {
  let 利用目的 = workbook.getWorksheet("Sheet1").getRange("F9").getValue();
  let 責任者氏名 = workbook.getWorksheet("Sheet1").getRange("H12").getValue();
  let メールアドレス = workbook.getWorksheet("Sheet1").getRange("H13").getValue();

  let data: Data = {
    purpose: 利用目的.toString(),
    supervisor: 責任者氏名.toString(),
    mail: メールアドレス.toString()
  };

  return data;
}

interface Data {
  purpose: string;
  supervisor: string;
  mail: string;
}
```

interface でデータの構造を定義しておき、Excel 方眼紙からセルを指定して読み取った値をそれに当てはめ、最後に return しているだけです。簡単。

Power Automate からは、読み取りたいファイルと、実行したいスクリプトを選択しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/a57a726d-47f0-cba9-b391-46d80f88a1dd.png)

これだけで、Power Automate から Excel 方眼紙内の値を読み取ることができました。

# さいごに
もの凄く簡単な仕組みですが、いろいろと応用が効きそうな仕組みですね。
【Python】画像処理OpenCVとPillow(PIL)を比べてみた

## はじめに
画像処理で速度を必要とするアプリケーションを作っているところ、前処理でアプリに組み込まないスクリプトをPythonで組んだ時の話です。
「**標準ライブラリを使えばpipで新しいライブラリをインストールする必要がないから楽なんだよな。。**
**どのくらいに性能差があるのだろうか**」
ということで速度検証してみました。

## 速度検証
### 速度検証対象
+ **OpenCV：4.6.0.66**
+ **Pillow：9.1.1**

画像の左右上下が分かりやすく、速度差を出すため容量も高いものを選びました。
使用した画像は以下の[Pixabay](https://pixabay.com/ja/)のCDD20さんの画像を使わせて頂きました。
![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1660691/6b691f49-65bd-28ff-4570-e5c88b8554c9.png)


### 速度検証結果
実際に実行してみた結果をまとめてみました。

| 実行項目 | OpenCV | Pillow |
|:-:|:-:|:-:|
| 読み込み | 0.1060 | 0.0075 |
| 回転（時計回り） | 0.0273 | 0.1271 |
| 回転（反時計回り） | 0.0230 | 0.0395 |
| 回転（180度回転） | 0.0164 | 0.0324 |
| 縦連結 | 0.0190 | 0.0527 |
| 横連結 | 0.0343 | 0.0594 |
| リサイズ | 0.015 | 0.0767 |

### 考察
まず知っておいてほしいことが以下のライブラリの位置付けで実際には得意分野があったりします。
おいおい、それなら比べる必要ないだろと思う人！！案外、予想外の結果も出るものなので気になったら検証をすべきだと私は思います。
+ Pillow(PIL): 画像処理ライブラリ
+ OpenCV: コンピュータビジョンライブラリ

以上のことからPillowは純粋に画像を操作することに長けるのですが、逆にOpenCVは画像認識等のAIを使う上で分析しやすいようにndarray形式になっており、コンピュータビジョン系に向いています。

1. **読み込み**
情報量が多い OpenCV がどうしても読み込み速度になると遅くなるようです。
逆に PIL は画像処理ができる情報のみでいいので速度は雲泥の差です。

1. **回転**
ndarray形式で持っているOpenCVは単純に数値変換で済むのでやはり「OpenCV > PIL」という結果になりました。それを踏まえても時計回りがやけに時間がかかていることが気になりますね。。

1. **連結**
やはり、こちらにおいても結果は「OpenCV > PIL」になりました。縦結合においては２倍以上のスコアを出しています。

1. **リサイズ**
これは、雲泥の差ですね。OpenCVが４枚終わってもPILは１枚も終わっていないので、OpenCVで１時間かかる作業を５時間近くかけてやるとなると大量のデータにこの処理を行うときは考え物ですね。

## まとめ
今回は簡単な画像処理と速度のみに注目してしまいましたが、画像処理のできることにおいては完全にPIL勝ちです。ですが、OpenCVは読み込み速度の遅さがネックでした。ほかの速度を帳消しにしそうな勢いだったので純粋にOpenCVの方が速いとも言いずらい結果になりました。
いかがだったでしょうか。こういう検証も意外な結果が出たりして面白いとは思いませんか？
では、また次回に。。
Python3エンジニア認定基礎試験 合格体験記

# はじめに
2022年7月にPython3エンジニア認定基礎試験を受験し、合格できました。
私自身、言語系のスキルが皆無でコードを見ると拒絶反応が起こるくらい、苦手意識があります。
大昔、言語系の研修を受けて一切わからないかったので、インフラエンジニアになった背景があるくらいです。
クラウド系の案件に携わると、イヤでも言語系のスキルが必要になるので、意を決して今回資格取得に向けて勉強を始めた次第です。
同じ試験を受ける方の参考になればと思い、記事を書きます。

# 勉強方法について
教材は参考書とwebサイトを利用しました。
## 参考書①「Pythonチュートリアル 第4版」

https://www.amazon.co.jp/Python%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB-%E7%AC%AC4%E7%89%88-Guido-van-Rossum/dp/4873119359

結論からお伝えすると、初心者がいきなりこの本を読むのは絶対にオススメできません。
「チュートリアル」と書いてありますが、ある程度の知識がないと理解できないような内容です。
また、英訳をそのまま日本語に訳したような違和感のある文章や誤記もあります。
それを知らず、いきなりこれを読み始めた私は当然挫折しました・・・
また、この本とほぼ同じ内容がwebサイトで見ることもできるのでwebサイトで十分な方は本を購入する必要はないです。
他の参考書と模擬問題集(下記参照)をある程度進めて、再度この本を読み直したらやっと理解できるようなレベル感でした。

https://docs.python.org/ja/3/tutorial/

## 参考書②「スッキリわかるPython入門 スッキリわかるシリーズ」

https://www.amazon.co.jp/dp/B07T63W9KC/ref=sspa_dk_detail_3?psc=1p13NParams&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEzR0NVQkswMlRFMTQ2JmVuY3J5cHRlZElkPUEwMTExOTMwMldMSEJSSElJMVQ0WiZlbmNyeXB0ZWRBZElkPUEzVEtLSEFORk5NRFIwJndpZGdldE5hbWU9c3BfZGV0YWlsJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==

上記の本で挫折したので、もっと初心者向けの参考書を探しました。
こちらは本当に初心者向けの参考書でしたので、とても読みやすかったです。
Pythonに関する参考書のため、試験内容と一部重複していない箇所もありますのでご注意ください。

## webサイト①「DIVE INTO EXAM」

https://diver.diveintocode.jp/dive_into_exam/1

参考書②を読んだあとはこちらのサイトを利用しました。会員登録をすることで利用できます。
会員登録には「無料版」と「有料版」があります。
無料会員登録の場合、模擬問題集と試験範囲の一部の解説動画しか見れませんが、1週間という期間限定で有料会員登録が無料でできます。
有料会員登録したまま、1週間経過するとそのまま有料会員登録が継続されてしまうのでご注意ください。
私は6日間利用して直前で解約して利用していました・・・笑

個人的には、ここの解説動画が1番オススメです。
各項目を十分解説しており、コードを実行した例もあるので学習しやすかったです。
模擬問題集についてですが、本試験と比べると少し簡単なイメージです。また、問題数が少ないので数回やると答えを覚えてしまいました。
ですが、本試験に近い内容もあるのでやる価値は十分あるかと思います。

## webサイト②「PRIME STUDY」

https://study.prime-strategy.co.jp/

こちらは模擬問題集が3つ利用できるサイトです。会員登録も不要で誰でも無料で利用できます。
こちらの模擬問題集は本試験よりも少し難しいくらいのレベルだと思います。なので、ここの模擬問題集で8-9割ほど取れれば合格に近いのではないかと思います。

しかし、模擬問題集の答えしかわからず、問題解説がないので詳細は自分で調べる必要があるところが欠点です。
多少手間はかかりますが、Pythonに関する情報はググれば大量にあるのでそこまで苦労はしませんでした。

# 試験について
コロナ禍ということもあり、オンラインで受験をしたかったですが、テストセンターでの受験しかなさそうでした。
私はOdysseyで予約をしました。都内であれば、平日だけでなく土日に開催している時間もありますが、平日は土日に比べて非常に予約が埋まりやすいのでご注意ください。

https://cbt.odyssey-com.co.jp/pythonic-exam.html

ちなみにPythonエンジニア認定基礎試験は以下のとおりです。
・出題数：40問
・出題形式：選択式
・試験時間：60分
・合格基準：7割以上の正解（28問正解）
・持ち込み：不可
・受験前提条件：なし

事前にOdyssey IDの登録が必要です。試験を受ける際にここで作成したIDを使って試験を受けます。

https://cbt.odyssey-com.co.jp/faq1.html#faq1_3

合格できなかった場合、無料で再受験できるキャンペーンがありました！
ですが、誰でも該当するわけではなく、特定のテストセンターで受ける必要があるなど一部制約事項もありますのでご注意ください。

https://otc.odyssey-com.co.jp/news/20211220.html

他のITベンダー試験では計算用のメモ用紙かホワイドボードの貸し出しがありましたが、今回はそのような貸し出しがありませんでした。書く必要のあるような計算問題はないのですが、少し動揺しました・・・
試験は全問回答するのに20分ほど、見直しに10分の合計30分ほどで終わりました。回答はすべて選択式で、webサイトの模擬問題集と似た問題も出題されたので、十分勉強していれば、試験時間が短くて試験が終わらないということはないんじゃないかと思います。

試験結果はテスト終了時にすぐ発表されます。テスト終了のボタンを押すときは毎回緊張します・・・

# おわりに
最後まで読んでいただきありがとうございました。勉強前と後を比べるとコードに対する拒絶反応が明らかに少なくなったと思います！
勉強に苦戦するときもありましたが、勉強してよかったと感じます。同様の試験を受ける方の参考になれば幸いです。
【Salesforce】標準のレポートタイプで取引先責任者が表示されない

# 問題

標準のレポートタイプで「○○と××が関連する取引先責任者」「○○と取引先責任者が関連する××」のような標準のレポートタイプを使う場合、注意が必要です。

レポートタイプの特性上、①○○②××③取引先責任者すべてが関連して無い場合、レコードが表示されません。
＜例＞
・××のレコードが○○と取引先責任者を参照している＝表示
・××のレコードが○○のみ参照している＝非表示

ここまではなんとなくわかるのですが、標準のレポートタイプの場合、取引先が関連してない取引先責任者は表示されませんでした。

＜例＞
・××のレコードが○○と取引先責任者を参照している、その取引先責任者は取引先Aに関連している＝表示
・××のレコードが○○と取引先責任者を参照している、その取引先責任者は取引先に関連していない＝非表示

# 解決策

こちらを回避するにはカスタムレポートタイプを作成すれば回避できます。

うーん。

# 参考リンク

[レポートに一部のレコードが表示されない、またはレコードに誤った結果が表示される](https://help.salesforce.com/s/articleView?id=000324873&type=1)
Next.jsでMaterial-UIを使う

何らかのUIを作る際に0から作るのではなくテンプレを利用したいと思ったのでMaterial-UIを使います。

以下の記事を参考にさせていただきました

https://amateur-engineer.com/react-material-ui/

## やりたいこと
material-uiのテンプレを反映する

### 環境の整備
docなどは公式にありますが導入手順はgitを読みながら進めます
https://github.com/mui/material-ui

```sh
$ yarn add @mui/base
$ yarn add @mui/system @emotion/react @emotion/styled
$ yarn add @mui/system @mui/styled-engine-sc styled-components
```

### テンプレを見る
https://mui.com/material-ui/getting-started/templates/
上記を見て「Sign Up」のテンプレを使ってみます

### テンプレの反映

サンプルファイルをzipでダウンロード
https://github.com/mui/material-ui

プロジェクト直下に「src」という名前のディレクトリを作成して以下ファイルをコピーする
https://github.com/mui/material-ui/tree/master/examples/nextjs-with-typescript/src

「pages」ディレクトリに以下ファイルをコピー
https://github.com/mui/material-ui/tree/master/docs/data/material/getting-started/templates/sign-up

起動

```
$ yarn run dev
```

以下にアクセスする
http://localhost:3000/SignUp

テンプレ通りの画面が表示できました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110457/99bd1a56-d1be-a06b-c2d6-32fe9d1e8130.png)

サンプルで入力フォームやボタンのソースコードを確認でき、UI作成時に必要部分をコピペするだけで標準UIを利用できます。

UIはさまざまな人が長年試行錯誤して利用者にとって利用しやすい形を追求してきたと思いますが、その成果を簡単に自身のUIに反映して使うことができ、すごい時代になったなと改めて先人に感謝いたします。

単純な画面だけど画面表示に0.5秒くらいかかっているのでNext.jsやNodeの仕組みを勉強して改善できるところは改善していきたい。
DXでも推進中！RPAを活用した業務自動化でコスト削減・作業スピードの向上

![rpa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633992/c1e02daf-5c9b-9d88-a19e-4f5f51df6ed2.jpeg)

エスプリフォートでは、DX W（ディー・エックス・ダブル）ラボにてRPAを用いた自動化やAIなどを組み合わせたデジタルトランスフォーメーション（DX）として推進中です。
これら技術や他の技術などの使いどころを見極めた上で、顧客への新しい付加価値を創っていっています。
（もちろん、RPAによるエンドユーザー様へのご支援も行っています。）

本稿では、エスプリフォートでDX推進中のRPAによる自動化についてや業務自動化取り組み事例を少しご紹介いたします。

## RPAとは

RPAとは、”Robotic Process Automation”の頭文字をとった略称です。
ソフトウェアロボットが業界や業務にかかわらず、バックオフィス業務などの定型作業を自動化、代行するツールです。

複数のシステムをまたがった作業の自動化が可能になるため、工数削減による作業時間の短縮や、ヒューマンエラーを削減したりなどの生産性向上を図ることが出来ます。

RPAの導入には、スモールスタートで効果を確認しながら進めることをお勧めします。

## RPAの誤解

RPAはAIのように自らの判断でその時々の状況に応じた対応ができると思われがちですが、RPAは人間が指示したルールに則り作業を行うだけです。
その時々の状況に応じた柔軟な対応はできません。
そのため、RPAとAIなどを組み合わせることで柔軟に対応できるようにしています。

## RPAのメリット
- 人件費を削減できる
- 作業ミスの抑制できる
- 24時間稼働させられる
- 単純作業量を減らし、付加価値の高い業務に集中できる
- 部署、業務単位ではなく、一つ一つの小さな作業単位の業務から導入できる
- 対応スピードの向上できる
- 業務見直しのきっかけになり、業務効率化を図れる
- 現場レベルで設計、開発ができるため、現場レベルで改善が図れる

## RPAのデメリット
- 社内教育や外注による運用サポートにおけるコストがかかることがあるため、費用対効果が高いとは限らない
- RPAは決められたルールに基づいて仕事をするため、少しの業務内容変更があれば、RPAでも修正対応が必要となる
- RPAはシステムであるため、システム停止による業務が停止するリスクがある

## RPAによる業務自動化事例としての一部を紹介します。
- 受注情報のシステム投入などの入力業務
- 紙媒体からのデータ入力業務
- 転記業務
- 作業指示書の作成などのレポート作成業務
- 情報収集業務
- 集計業務
- データ集約業務
- データ保存業務
- データ加工業務
- コピー＆ペースト業務
- メール・メッセージ送付
- 交通費精算チェックなどの照合業務

など．．．

## UiPathとは？

今、働き方改革によって注目を浴びているRPA。
業務効率化に大きく貢献してくれるRPAのなかでもUiPathは「世界３大RPAソフト」として注目されています。
またUiPathは「日経コンピュータ　顧客満足度調査 2020-2021」のRPAソフト／サービス部門において2年連続となる1位を獲得しており、日本国内だけでも1,000社以上の導入実績がある日本でも代表的なRPAツールの一つです。

## UiPathの特徴

- 説明書を熟読しなくても、直感的に操作できるほどわかりやすく、簡単に使える
- ブラウザーやOfficeなども多くのソフトと連動でき、安定して自動化できる高い柔軟性
- 社内で動作するロボットをネットワーク経由で一元管理できる

## ライセンスの種類

|   | 有料ライセンス | エンタープライズ用評価版 | Community Cloud |
|:-:|:-:|:-:|:-:|
| 費用 | 有料 | 無料 | 無料 |
| 対象 | エンタープライズ | エンタープライズ | 個人/その他事業者 |
| 利用期限 | 無し | 60日間 | なし |

## Community Editionにおける注意事項（2021年9月時点の情報）
Community Editionの対象者は、個人のRPA開発者及び小規模事業者となります。
小規模事業者については、「関連会社を含め従業員が250人未満で、売上高が500万ドル未満の組織」と定義されています。
この定義に該当しない事業者は利用できません。

また、自動化の上限はRobot5台までとなっております。
（機能的な制限は一切ありません。）

https://www.esprit-fort.co.jp/

https://www.esprit-fort.co.jp/recruit/
pandasをマスターするまでやめない第4話

### これまで
https://qiita.com/Hayaa6211/items/abbacfe935c9bd1fc78e  

https://qiita.com/Hayaa6211/items/4c3b847b7a9a57747d32  

https://qiita.com/Hayaa6211/items/e5ac5bf2312b4f2acd56

### データクレンジングとは
破損したデータや不正確なデータ，無意味なデータを特定し最適な扱いをすることで予測する際や可視化する際に使いやすくすること．

### 重複行
重複している行があると特徴量に偏りが生まれるため消すことが必要．
```df.duplicated()```
```python
df.duplicated() -> pd.Series

"""
0    False
1    True
2    False
3    False
4    False
....
n    False
"""
```

#### 重複している行のカウント
```df.duplicated().value_counts()```  
```value_count()```はbool型のSeriesの中にあるTrueの数の合計

#### 重複している行の抽出
条件抽出とやり方は一緒

```python
df_duplicated = df[df.duplicated()]
```

#### 重複している行の削除
```df.drop_dupulicated(inplace=False)```

### 欠損値の処理
欠損値はnan(Not a Number)と呼ばれる.これがあると特徴量が足りず偏りが生まれる

#### 欠損値の判定
```df.isnull()```  
中身がbool型になり，nanならTrue値があればFalseとなる

#### nanのある列の判定
```df.isnull().any()```  
```any()```はTrueのある列をTrueとしてcolumnsをindexとしたSeriesを返す

```python
tf = df.isnull().any()
col_name = tf[tf].index.tolist()
```

#### 各カラムのnan個数をカウント
```df.isnull().sum()```
nanではない個数の場合は```df.count()```

#### 各行にnanがあるかどうか
```df.isnull().any(axis=1)```

#### nanがある行の抽出
```df_nan = df[df.isnull().any(axis=1)]```

#### nanのある行を削除
```df.dropna(inplace=False)

#### nanの補完
```df.fillna(object)```
```python
mean = df[columns].mean()
df[columns] = df[columns].fillna(mean) #平均で補完
df[columns] = df[columns].fillna(0)    #特定(0)の値で補完
```

#### nanの予測
```missingpy.MissForest().fit_transform()```
```python
from missingpy import MissForest
cols = df[df.isnull().any()].columns.tolist() #予測したいcolumns
df = df[cols]
res  = MissForest().fit_transform(df) -> np.array

df_inpute = pd.Dataframe(res,columns=[cols])
```

### エンコーディング
機械学習では文字列を数値に変換しなくてはいけない．
#### labelエンコーディング
```sklearn.preprocessing.LabelEncoder```

```python
from sklearn.preprocessing import LabelEncoding
le = LabelEncoding() #インスタンス生成

le.fit(df[column]) #予測したいカラムで学習

df[new_column] = le.transform(df[column]) #ラベル->ラベルID
```

#### one-hotエンコーディング
```pd.get_dummes(df)```

### おわり
ここら辺は無限にやり方あるし実際にkaggleとかでデータ加工の経験詰むのが一番よさそうあざした
【1分で話せ】から学ぶコミュニケーションの改善

# はじめに
買ってよかった技術書といえば多くの人が、リーダブルコードやプリンシパルプログラミングを上げると思います。
当然ながら良書であることは間違いないのですが、有名である分皆さん投稿してらっしゃるので、私は技術書といっていいのか少し微妙ですが「[1分で話せ](https://www.amazon.co.jp/%E3%80%90Amazon-co-jp-%E9%99%90%E5%AE%9A%E3%80%911%E5%88%86%E3%81%A7%E8%A9%B1%E3%81%9B-%E4%B8%96%E7%95%8C%E3%81%AE%E3%83%88%E3%83%83%E3%83%97%E3%81%8C%E7%B5%B6%E8%B3%9B%E3%81%97%E3%81%9F%E5%A4%A7%E4%BA%8B%E3%81%AA%E3%81%93%E3%81%A8%E3%81%A0%E3%81%91%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AB%E4%BC%9D%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-DL%E7%89%B9%E5%85%B8-%E3%80%8C1%E5%88%86%E3%81%A7%E8%A9%B1%E3%81%9B2%E3%80%8D%E8%A9%A6%E8%AA%AD%E7%89%88/dp/4797395230)」についての紹介をさせていただきます。

# 概要
会話を簡潔にわかりやすく話すための技術について、具体的・実践的に学ぶことが出来る

# どんな人におすすめなのか
コミュニケーションに苦手意識のある人
クライアントとの折衷を行う方

# 書籍のポイント要約
1. 1分以内に簡潔に話せ
    - 長々と話されても皆さん困りますよね
2. 直観と論理を結びつけて話せ
    - もちろんロジックも大切なのですが、直感的にもわかりやすく話せばより楽に理解してくれます。
3. 聞き手に何をしてほしいか考え、それを軸にして何を伝えるか考えよう
4. 相手に何をしてほしいのかきちんと伝えること
5. 結論のためには根拠を3つ程度用意しよう
    - 1つだと根拠が薄すぎるから3つを目安に主張しましょう
6. 必要のない言葉を削ろう
    - 相手にとっては必要最低限の情報だけで十分です
7. 相手の知りたい事だけを話そう
8. 直観的にわかりやすくするためにイメージを想像できるようにしよう
    - 実際に画像を見せる
9. 会話するときの基本を守ろう
    - 目を見て話す
    - 聞き取りやすいトーン
10. 事前準備をきちんと行おう
    - 上記をきちんと行うためには前もって準備が必要!

# 最後に
要約はうまく伝わりましたでしょうか？多くのエンジニアにとって重要な「伝える」という能力について実践を交えて説明してくださっている良書です。1500円程度の安い本ですので、ぜひとも手に取ってみてはいかがでしょうか?
ブロックテーマではブロックでwp_headにadd_actionできる


ブロックテーマでは、基本的にすべてのページは``wp-includes/template-canvas.php``をテンプレートとして表示されます。

``wp-includes/template-canvas.php``は以下のような非常にシンプルなテンプレートになっています。

```php:wp-includes/template-canvas.php
<?php
/**
 * Template canvas file to render the current 'wp_template'.
 *
 * @package WordPress
 */

/*
 * Get the template HTML.
 * This needs to run before <head> so that blocks can add scripts and styles in wp_head().
 */
$template_html = get_the_block_template_html();
?><!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
	<meta charset="<?php bloginfo( 'charset' ); ?>" />
	<?php wp_head(); ?>
</head>

<body <?php body_class(); ?>>
<?php wp_body_open(); ?>

<?php echo $template_html; // phpcs:ignore WordPress.Security.EscapeOutput ?>

<?php wp_footer(); ?>
</body>
</html>
```

コードのコメントにも書かれている通り、コンテンツのレンダリングが``wp_head``より前に行われるため、ブロックの``render_callback``で``wp_head``へのフックの追加ができます。

より詳しく書くと、``template_redirect``のタイミングでテンプレートのコードは取得され、この``wp-includes/template-canvas.php``の``get_the_block_template_html()``でブロックはレンダリングされます。

このことは、これまでプラグインやテーマカスタマイザなどによって行っていた``<head>``タグ内への計測タグの挿入なども、ブロックテーマではブロックで行えるということを意味します。
ブロックテーマにおいてブロックは、これまでとは違った役割に担うことになりそうです。