OmniAICreator/Qiita-1.07M huggingface dataset:
心理的安全性は自分で作れる

突然ですが皆さん「コミュニケーション」って得意ですか？？

そう言われて「はい！得意です！」と胸を張って言える方は少ないのではないでしょうか？
僕も、正直そんなに得意ではないです。

上司とお話していて、失敗したなーとか、
メンバーと話していて、うーん。上手く伝わってないなぁとか、
日々反省しながら、コミュニケーションしてます。

コミュニケーションに苦手意識を持つと、ついその場に「心理的安全性」を求めたくなってしまいますよね。

今回の記事では、**「心理的安全性は、自分で作れる」** というお話を、自分の体験談も交えて記載します。

※ メンバー側の視点で、読んでいただけると幸いです。
※ リーダー側の視点での、心理的安全性を保つための具体的な手法は記載されていません。

## 心理的安全性とは？
Googleが研究結果として「心理的安全性の高い組織は、生産性の高い組織である」という研究結果を発表してから注目を浴びるようになったワードで、心理的安全性が低い状態だと、以下のような不安が発生すると言われています。

- 無能、無知だと思われる不安
- チームの邪魔をしていると思われる不安
- ネガティブだと思われる不安

そのために、心理的安全性の高いチームを作るべきだ。という書籍や情報は巷に溢れかえっています。みなさんも、一度は目にしたことがあるのではないでしょうか。

でも、この心理的安全性というキーワード、取り扱い方を一歩間違うと危険なワードだなと感じています。

## 心理的安全性の高いチームを、強引に作るのは危険？
リーダーを経験された方であれば、心理的安全性を高いチームを作ると考えたことがあるのではないでしょうか。

でも、リーダーが、
![スクリーンショット 2022-12-19 10.02.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117041/f316814d-c04f-52fd-69ea-4fc84a80b6b7.png)
と考えメンバーに伝えて実行。
メンバーは、
![スクリーンショット 2022-12-19 10.03.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117041/c22c0077-9ac0-f98e-53f9-c18c5cde13e8.png)
と考える。

…なんか、この状況って少し違和感を感じるんです。

表立ってメンバーに伝えなかったとしても、リーダーが心理的安全性を保つことを意識すると、メンバー側はそれとなく気づくと思います。
そうすると、メンバーの深層心理に、状況に頼る意識や発想が芽生えてしまうケースもあると思います。

もちろん、リーダーという役割において、メンバーの心理的安全性を意識することは重要です。
でも、上記のような状況って、個人的には少しもやっとするのです。

...なんでだろう？

メンバー側の視点で考えると、上記の発想には他責の要素が含まれるからだと思います。

## じゃあ、どうしたら良いのか？？
上記を踏まえた上で、必要な考え方として、

- リーダーは、必要な心理的安全性を保つための空気感をチームの中で一定持ちつつも、無理して作り出そうとしない
- メンバーは、心理的安全性という言葉に変に頼り過ぎない

が必要だと思います。

特にメンバーの立場で考えた時、心理的安全性を高めてほしいという意識が先行してしまうと、状況が変わるのを待つ。その間は頑張るという発想になると、アンコントローラブルな要素が生まれ、心理的にはより苦しくなっていきます。

それであれば、心理的安全性を確保する動きを、自分から取ってしまったほうが健全だし、解決も早いと思います。

## 自分自身の体験談
最近、役割が少し変わったこともあり、打ち合わせに参加させてもらうケースが多いです。
その中での体験談をご紹介します。

自分よりも役職が上の人達で構成される打ち合わせがあり、初めて参加させてもらった時のことです。打ち合わせで何も発言できず、悔しい経験をしました。

その時の自分の心理状況は、以下の状況だったと記憶しています。

- 自分は初参加だからまだ情報と知識が少ない
- そんな自分が発言すると、話を散らかしてしまうのではないか？
- 発言すると、自分が無知だと思われてしまうのではないか？

今振り返ってみると、そんな心理状態が働いていたのではないかと思います。

これって、いわゆる心理的安全性が保たれていない状況の定義そのものですね。

でもこのときに、僕自身が、

「あ、このチームは心理的安全性が低いんだ」
「心理的安全性を保てていないチームが悪いんだ」

という発想になっていたら、その時点で僕の成長は止まっていたのではないかと思います。

もちろん、何の考えもなしに、やたら滅多に発言してかき乱すのは良くないです。
でも、情報が足りないなりにも、その場で得た情報をもとに、自分なりに考え、気になった点やわからない点を質問、確認すること、
ここはこうしてほしいと感じたことをリクエストすることを怠るのは、もっと良くないと思います。

そう感じた自分は、次回の打ち合わせから、

「わからないことは聞こう」
「気になった点は質問しよう」
「こうしたほうが良いのでは？と感じたらリクエストしよう」

と意識し、更には、会議中に必ず１回は発言するというノルマを作りました。

もちろん最初は

「うーん、今の発言はちょっとピントがずれたかな」
「ちょっと発言の粒度が荒すぎた、細かすぎたかな」

という感じる場面も多く、うまくいっていない感覚もありました。

でも、こういったことを繰り返し行っていった結果、

- 喜ばれる発言の内容
- 適切な発言の粒度（打ち合わせの目的によって異なる）

を、徐々に自分の中で掴むことができ、意見を出しやすい状況が生まれ、今では会議等で意見を出すことに対しての抵抗はほぼないです。

つまり言い換えると、自分で心理的安全性を作り出せたと感じています。

もちろん、自分の意見を受け入れてくれた周囲の人達の存在があったことで、実現できた点も要因として大きいのが大前提です。でも、せっかく心理的安全性が存在する組織やチームの中で、自分からアクションを起こさないことで、自分から損なってしまうのはもったいないなという気持ちで、執筆させてもらっています。

## 結論
心理的安全性は、自分で作ったほうが楽だし早いです。

苦しい状況を長く続けるくらいなら、自分から打破するための動きを行う、その中で出来ることは何かを全力で考える。つまり、アンコントローラブルな部分を、コントローラブルな発想に変えてしまった方が、よほど健全だと思いますし、解決も早く心理的にも楽です。

また、今回は心理的安全性というテーマで執筆しましたが、この件に限らず、アンコントローラブルな環境や周囲を理由にして、状況が変わるのを待っているのって辛いですよね。その際にも同じ考え方で動いたほうが、より良い結果につながると思います。

以上、駄文・長文になってしまいましたが、

- コミュニケーションは苦手だな
- 会議で発言しづらいな
- 最近、なんか上手くいかないな

と感じている方々にとっての、何かしらのヒントになれば幸いです。
diffusersを使った画像生成備忘録(自分用)12/16

**注意**
この記事の元になったスクリプトはローカル環境で動かすことを前提に書かれているためHuggingFaceを使用する場合のスクリプトはTokenが必要になる場合があります。
pythonをembeddable packageで使用しています。使用法については記事内で明記していませんのでご自身で調べてください。

# 実装環境
OS:windows 11
CPU:i7 9世代
RAM:32GB
GPU:RTX 2070 sp(VRAM:8GB)

Pyhton:3.10.x embeddable package 64bit
pipで導入されているもの
- Diffusers
- PyTorch
- Transformers
- OmegaConf
### diffusionモデルの読み込み
~~~Load.py
from diffusers import DiffusionPipeline

# ローカルでdiffusersモデルを使用する場合:フォルダまでのパス
# Hugging Face公開モデルを使用する場合:Hugging Faceのパス
model_id


#モデルロード:通常精度
ldm = DiffusionPipeline.from_pretrained(model_id)

#モデルロード：精度半分（細部の表現には向かない：例）人の顔とか）
#float32 -> float16
ldm = DiffusionPipeline.from_pretrained(
                                    model_id,
                                    revision="fp16",
                                    torch_dtype=torch.float16)
~~~
### 画像生成時にGPUを使用
GPUを使用するためpythorchをGPUに対応させなければならない

#### 導入方法

https://self-development.info/%E3%80%90windows%E3%80%91gpu%E7%89%88pytorch-1-12%E7%B3%BB%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/

GPU使用を使用するように設定する
~~~OnGpu.py
import torch
ldm # モデルを読み込んだ変数
ldm = ldm.to("cuda")
~~~

### 画像生成(保存まで)
必須の引数のみにすればデフォルトの設定で画像が設定される

~~~FormImg.py
ldm # モデルを読み込んだ変数
images = ldm(
            [str], # 生成したい画像のテキスト(プロンプト):必須
            negative_prompt = [str], # 生成したい画像から除外したいテキスト(ネガティブプロンプト)
            num_inference_steps = int, #ノイズ除去のステップ数デフォルトだと50  
            eta = float, #サンプリング? (0.0 は決定論的サンプリング)
            guidance_scale = float,#呪文に従う度合い (7〜11程度)
            height = img_h, # 生成画像の高さ
            width = img_w, # 生成画像の幅
            )["images"]

# 画像を複数枚生成することができるのでforで回す
for image in enumerate(images):
    filePath # 保存箇所へのパスとファイル名(デフォルト:png)
    image.save(filePath)
~~~
引数で画像の生成枚数を増やすことができるがVRAMを多く使用するため
おすすめしない
~~~multiple.py
count # 一つのプロンプトから生成する画像の枚数
ldm([str] * count)["images"]
~~~

### NSFW制限突破
基本的にNSFW（エッッやグロなど）な画像が生成されないように規制が入っている。
NSFWな画像を見たい場合は下のスクリプトを組み込む
~~~UnSafety.py
# すべての画像をNSFWではないと返す関数
def null_safety(images, **kwargs):
    return images, False

ldm # モデルを読み込んだ変数
ldm.safety_checker = null_safety # NSFWチェックする関数を何もしない自作関数に変更
~~~

### プロンプトをモデルのCLIPを使用してトークンに切り分ける
参考サイト

https://zenn.dev/karaage0703/articles/0c15cc7a86eae1

~~~PromptToTokens.py
from transformers import CLIPTokenizer

# ローカルモデルを使用する場合
modelid # 画像生成用ローカルモデルのパス
tokenizer = CLIPTokenizer.from_pretrained(model_id + "/tokenizer") 

# Hugging Face公開モデルを使用する場合
modelid # Hugging Faceに公開されているCLIPのモデルパス
tokenizer = CLIPTokenizer.from_pretrained(model_id) 

prompt # トークンに分けたい呪文
tokens = tokenizer.tokenize(prompt) # 一文の呪文をトークンに切り分ける

tokenizer.model_max_length # モデルで定義されている読み込まれるトークンの最大数
#^^最大数を超えたトークンは除外される^^#
~~~
トークンの最後に</w>がついている場合単語として認識されている。
なにも付いていない場合そのあとのトークンと組み合わされて単語と認識される可能性がある。

### Ckpt To DiffusersModel
ネットで公開されているStable Diffusion系のモデルはckptというファイルにまとめられている。しかしダウンロードしただけではDiffusersで使うことはできないのでこの章で展開する方法を記入します。
ここでは変換方法だけを書くのでckptファイルは自身で探してください。
**注意**
　NovelAIモデルを探す際はウィルスの混入に注意してください
　AnythingV3モデルがありますがものによってはウィルスを検出するようです。 

ローカルPCでローカル向けに展開する方法

参考サイト

https://self-development.info/%E3%80%90stable-diffusion%E3%80%91ckpt%E3%82%92diffusers%E3%81%A7%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80/
【PHP】配列操作で気をつけること

#### 結論! echoする前と変数配列を代入するときは、処理の前に分岐初期を入れてね
# コード
```javascript
$waza_array = [0,3,4,5];
$waza_name = [1 => '田中',2 => '渡部',3 => '品川',4 => '滝谷',5 => '川原田',6 => '一色'];
//↓これはダメ
$waza_list = [];
foreach($waza_array as $waza_id){
    $waza_list[] = $waza_name[$waza_id];
}
//これにする
foreach($waza_array as $waza_id){
    if(!empty($waza_name[$waza_id])){
        $waza_list[] = $waza_name[$waza_id];
    }
}
var_dump($waza_list);
```

# 結果
```javascript
array(3) {
  [0]=>
  string(6) "品川"
  [1]=>
  string(6) "滝谷"
  [2]=>
  string(9) "川原田"
}
```
【Flutter】Brave Browserでデバッグする方法

この記事は[可茂IT塾 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/kamo-it)の17日目の記事です。

# Brave Browserとは
https://brave.com/ja/

# やり方

現在使用しているシェルを確認します。

```shell
$ echo $SHELL
```

そうすると `/bin/zsh` か `/bin/bash` が出力されると思います。

`/bin/zsh` だったら ~/.zshrc
`/bin/bash` だったら ~/.bashrc

に以下の文字を貼り付けるだけです。

```shell:macOS
export CHROME_EXECUTABLE='/Applications/Brave Browser.app/Contents/MacOS/Brave Browser'
```

```shell:Windows
export CHROME_EXECUTABLE='/opt/brave.com/brave/brave-browser'
```

# 確認

以下のコマンドを実行して確認してみましょう。

```shell
$ flutter doctor
```

![スクリーンショット 2022-12-16 14.26.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918037/447a67cc-b2e4-7c64-791f-e5d69d465122.png)

皆: おい！Chromeのまんまじゃねぇか！😡

BGM: ドゥ〜ドゥドゥドゥドゥドゥ🎶

![スクリーンショット 2022-12-16 14.37.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918037/508c57b0-0c98-a84c-0fc2-dffb9e9b0903.png)

BGM: ドゥ〜ドゥドゥドゥドゥドゥ🎶

![スクリーンショット 2022-12-16 14.37.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918037/d371c63c-8677-438d-1f10-680a72440ba6.png)

BGM: へ〜イ❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️❗️

![スクリーンショット 2022-12-16 14.40.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918037/93d3ac1b-32c0-0123-ae2b-f4033e389cf4.png)

おりょう: 安心してください、使えますよ。
Raspberry Pi OSなどの img ファイルの中身を macOS で展開して確認する

Raspberry Pi OSファイルはimg形式で配布されています。

https://www.raspberrypi.com/software/

この中身を確認してみました。

`7-zip` をインストールします。

```
$ brew install  brew install 7-zip
```

`7zz` コマンドに `x` サブコマンドを渡すと展開できます。


```
$ 7zz x 2022-09-22-raspios-bullseye-arm64.img

7-Zip (z) 22.01 (arm64) : Copyright (c) 1999-2022 Igor Pavlov : 2022-07-15
 64-bit arm_v:8 locale=en_US.UTF-8 Threads:8, ASM

Scanning the drive for archives:
1 file, 4265607168 bytes (4068 MiB)

Extracting archive: 2022-09-22-raspios-bullseye-arm64.img
--
Path = 2022-09-22-raspios-bullseye-arm64.img
Type = MBR
Physical Size = 4265607168

Everything is Ok

Files: 2
Size:       4261412864
Compressed: 4265607168
```

一度展開すると `1.img` のファイルが見えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47327/1eb9d985-88e4-6082-4cb0-5310c4a67b5c.png)

さらにもう一度 7zz を掛けると展開できます。



```
7zz 1.img
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47327/034ffe56-c5b3-1e03-7c12-51ba702ce4ea.png)
Slack上でDeepL翻訳をする為のアプリを誰でもインストールできる形にしてみた

本当は次世代プラットフォームについて書くつもりだったのですが、瀬良さんが良質コンテンツを大量投下してくれていて、それを追っかけているだけで色んなことが分かるようになるので、是非皆さんも試してみてください。
一連のpostの中でこちらを読んで、試してみたのですが、次世代プラットフォームを使ったデプロイは本当に簡単なので、やってみる価値はあると思います。boltでの運用よりはレスポンスが遅いですが、そこまで問題にはならないでしょう。

https://qiita.com/seratch/items/23e22b4eed489cdd04d7

この中にしれっと書いてあったのですが、ファイル翻訳に対応していた！！全く気付いていませんでした。

https://qiita.com/seratch/items/c1e416dea6f6dcf6f62e

そう言えば、ファイル翻訳やってみたかったんだよねと思ってソースコードを覗いてみると、bolt for pythonで書かれているじゃないですか。

https://github.com/seratch/deepl-for-slack

こちらをそのままデプロイすると、ファイル翻訳をしてくれるようになるのですが、メッセージの翻訳はしてくれません。
実運用を考えると同じアプリでメッセージの翻訳もしたかったりします。ということで拡張してみましたという話。


## テキスト翻訳部分を追加してみよう

ソースコードはこちら

https://github.com/geeorgey/deepl-document-translator-for-slack/blob/main/app.py

やってみると分かるのですが、PDFファイルの変換はそれなりに時間がかかります。
テキスト＋PDFファイルを翻訳する場合は、先にテキスト翻訳をスレッドに投げておきたいので、ファイル変換が始まる前に以下の処理をいれています。

```python
    #message部分の翻訳とpost
    text = parent_message.get('text')
    try:
        result = translator.translate_text(text, target_lang=lang) #text翻訳はこの形でリクエストを投げます
    except Exception as e:
        print(e)
        if locale == 'ja-JP':
            translated = "DeepL APIでエラーが起きたため翻訳出来ませんでした。<https://www.deepl.com/ja/pro-account/summary|DeepLのサイトでAPIキーを確認してください>。"
        else:
            translated = "DeepL APIでエラーが起きたため翻訳出来ませんでした。DeepL Could not be translated due to an error in the API.<https://www.deepl.com/ja/pro-account/summary|Check your API key on the DeepL website>"
    else:
        print("翻訳完了-----")
        print(result)
        translated = result.text
    post_message = client.chat_postMessage(
        channel=channel,
        thread_ts=thread_ts,
        text=translated,
        reply_broadcast=True #スレッド内のみで良い場合はここをFalseにしてください
    )
    #//message部分の翻訳とpost
```

ということで、シンプルなアップデートでテキスト翻訳にも対応できるようになりますので、お試しください。
一部return処理を抜いていますので[変更詳細についてはこちらを御覧ください](https://github.com/geeorgey/deepl-document-translator-for-slack/commit/a6c7fb3bdc582a52a7e544250aea9b953545ddc6)。

前も思ったことですが　files_upload　には　reply_broadcast　オプションが無いんですよね〜。

## 自分でデプロイするのは難しいという人向け
いくら簡単ですといっても、boltで作るアプリはどこかにデプロイしなければいけませんし、維持コストがかかります。
加えて、この形ですと、1アプリについて1つのワークスペース限定でしか使えません。
`app = App(token=os.environ["SLACK_BOT_TOKEN"])` ←bot tokenはインストール先毎に変わるからです
そうすると、我々のように複数のワークスペース(といってもエンタープライズグリッドに2つのWSがあるだけですが）で使おうとするとこのままでは使えません。

誰でも使えるような形にするために、昨年作ったFlaskのテンプレートに乗っけてみました。

https://github.com/geeorgey/vue_flask_template

APIキーはワークスペース毎に保存することができるようになってます。

![Slack DeepL Translator.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/2e82ec8d-1ea7-7b67-b3e6-b30a0e715884.png)

使い方は同じで、スタンプ押すだけですね。

![Slack DeepL Translator (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/29c2192e-e114-866b-972d-f89ffb7295a9.png)

### Slack DeepL Translatorマニュアルはこちら

https://lne.st/deeplm

### インストールはこちらから

https://lne.st/deepl

## データの保護について
翻訳にかけるテキストやPDFファイルについては、利用者のAPI Keyを使ってDeepLに届けられますが、当アプリケーションがそれらの情報をDBに保存するような仕組みにはなっていませんので安心してご利用頂けます。

## It's magic
ファイル翻訳が手軽にできる事を見た、弊社スタッフから出た言葉です。


以上、どなたでもご利用頂けますのでご活用ください！

## OpenAIのAPIを使えるようにしてみました

https://note.com/geeorgey/n/n7d6cc149797e
【HERE】地理人がHERE Mapsを語る 後編「HERE Style Editorを使ってスタイルデザインしたものを配信してみた」

フリーの空想地図作家として活動し、都市や地図に関する記事執筆、地理監修・地図制作をしている「地理人」こと[今和泉隆行](https://www.chirijin.com/)さん。ジオ界隈で知らない人はいないですよね。

今回、地理人さんとコラボして記事ということで、前編ではHERE　Mapsの魅力や、HERE　Style Editorを用いてカスタムデザインをして頂きました。

後編であるこの記事は、HERE Style Editorでスタイルを出力して、WEB上に表示する実装まで紹介します。

# HERE Style Editorについて
HERE Style Editorは自分好みに地図をカスタマイズデザインできるツールです。ここでデザインしたスタイルをエクスポートして、自分のサービスに組み込んだり、配信することができます。簡単に言うとMapbox Studioみたいな感じですね。

https://jp.developer.here.com/documentation/style-editor/user_guide/index.html

### スタイルデザイン〜json出力
スタイルデザインをして、[File] -> [Export Map Style]でjsonを出力します。
イメージは、今和泉さんがデザインしてくださったものになります。
![スクリーンショット 2022-12-16 11.14.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858388/b35cc961-fa2e-2ef3-1616-c59797b7697c.png)

### html〜jsonの読み込み
スタイルを読み込むのにはAPI　keyの発行が必要です。
HEREの小松さんが丁寧にまとめた記事があるので、以下をご参考にしてください。

https://qiita.com/kekomat/items/d2e29bac84a27c1ec521

HTMLを作成し、スタイルjsonを読み込みます。

```index.html
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, width=device-width" />
    <script src="https://js.api.here.com/v3/3.1/mapsjs-core.js"
    type="text/javascript" charset="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-service.js"
    type="text/javascript" charset="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-harp.js"
    type="text/javascript" charset="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"
    type="text/javascript" charset="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"
    type="text/javascript" charset="utf-8"></script>
  </head>
  <body>
    <div style="width: 640px; height: 480px" id="mapContainer1"></div>
    <div style="width: 640px; height: 480px" id="mapContainer2"></div>
    <div style="width: 640px; height: 480px" id="mapContainer4"></div>
    <script>
      var platform = new H.service.Platform({
        'apikey':  'hghghg' //API keyを入れる
      });

      var engineType = H.Map.EngineType['HARP'];
      var style = new H.map.render.harp.Style('style.json'); //出力したjsonを指定
      var vectorLayer = platform.getOMVService().createLayer(style, { engineType });
      var map = new H.Map(document.getElementById('mapContainer1'),
          vectorLayer, {
          engineType,
          center: {lat: 88888, lng: 88888}, //緯度経度
          zoom: 13, //ズームレベル
          pixelRatio: window.devicePixelRatio || 1
      });

      var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
    </script>
  </body>
</html>
```
### ただこのままだとAPI keyが見えちゃう...😭😭
オープンな場所で使う場合は、APIはJSに隠しておきましょう。。。

### 実装完了
今和泉さんにデザインしてもらったものを取り込んでみる。
[Netlify](https://www.netlify.com/)にアップしてみました。

https://lighthearted-moxie-c2540a.netlify.app

### 余談ですが...

HERE Mapsを触っていて位置情報をシェアしようと思ったら、こんなボタンがあったｗｗｗ
![スクリーンショット 2022-12-16 12.38.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858388/9218c69e-016e-4833-bd06-7d424276862b.png)
車に...送る？...
さすがドイツの自動車メーカー連合の会社ですね、、、
railsアプリをherokuにデプロイしようとして、 error Command "webpack" not found.が出た時の対処法

<h1>結論</h1>
<h3>・webpackerを最新のものにする</h3>

エラーが出た時のGemfileはこんな感じでした。
```
Gemfile

gem 'webpacker', '~> 4.0'
```

それを
```
gem 'webpacker', '~> 5.0'
```
に変更して

```
bundle update
```

```
bundle install
```

```
bundle exec rails webpaker:install
```
この時にconflictが出る時がありますが、それは全部yを入力して無視して大丈夫でした。

ここまできたら再度herokuにデプロイ。

```
git add -A
git commit -m "update webpacker"
git push
git push heroku main:main
```

これで解決。

<h1>参考サイト</h1>

[Rails 'error Command "webpack" not found.'について](https://qiita.com/ahuiru/items/062bbc1b351819a3eeb8)
【完走賞ゲット-16】micro:bit向けのフルカラーLEDマトリックスを搭載した「pixel:bit」を試す

## はじめに
こちらは、[完走賞ゲットのため小ネタを毎日投稿しようとチャレンジする Advent Calendar 2022](https://qiita.com/advent-calendar/2022/youtoy) の 16日目の記事です。
[micro:bit Advent Calendar 2022](https://qiita.com/advent-calendar/2022/microbit) の 16日目用に公開した以下の記事と同じ micro:bitネタです。
（なお、今月のアドベントカレンダー用の記事として公開したものとしては、28記事目となっています）

●【micro:bit 2022】micro:bit V2 をゲームコントローラー（BLE接続の HIDデバイスのゲームパッド）にして Gamepad API と組み合わせてみる - Qiita
　https://qiita.com/youtoy/items/1ac1ce103476f12241e3

## この記事で扱うもの
この記事で扱うネタは、タイトルにも名前が出ている「[pixel:bit](https://www.technoaltaeng.com/pixcel)」に関するものです。
自分は、この [pixel:bit をスイッチサイエンスさんのサイトからポチりました](https://www.switch-science.com/products/7684)。

以下の写真はいくつかオンラインで購入した品を撮ったものですが、この中の右下あたりに　2つうつっています。

https://twitter.com/youtoy/status/1603361684017491968

### 公式の情報
届いた製品のパッケージの中に、QRコードがあり、それを読み込んで製品に関する Webページを開きました。
　●PIXCEL | 合同会社テクノアルタエンジン
　　https://www.technoaltaeng.com/pixcel
![PIXCEL | 合同会社テクノアルタエンジン](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/7b02d2e4-e4fc-50b8-3932-8fea096efa20.png)

その中を見ていくと、LED の配置の情報や接続するべきピンの情報が、以下のように書かれていました。
#### LED の配置の情報
![LED の配置の情報](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/2b2dc0c3-d35d-97a7-be77-e8f2fbe163a5.png)

#### 裏側の構成など
![裏側の構成など](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/69c9c63c-b1a8-b6e5-36df-1b52c11dba7c.png)

micro:bit から信号を受けとるのは、P2 になるようです（※ つまり、電源・GND を含めてつなぐ部分は「P2、3V、GND」の 3箇所）。
#### 複数基板の連結や消費電流について
![複数基板の連結や消費電流について](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/0d381f17-ee3b-d36e-b894-f4f210a80544.png)

### 実際に試してみる
#### micro:bit とつなぐ
上記の公式情報をもとに、micro:bit と pixel:bit を以下のようにつなぎました。

![基板側](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/8d29c111-38e6-0560-7830-270ad0583b05.png)

![micro:bit側](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/3f6791cd-9531-9669-2ee4-56df3ce440b0.png)

#### プログラムを作る
そして、ブラウザで [MakeCode](https://makecode.microbit.org/) を開き、[neopixel の拡張機能](https://github.com/microsoft/pxt-neopixel)を追加します。

![拡張機能の追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/6ed06648-f3f2-33bc-102b-b5e929da1564.png)

![neopixel拡張](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/515030a0-e98f-545a-b7bb-98dba6d7fade.png)

そして、以下のようなプログラムを作りました。
変数 `strip` で指定した 25個の LED のうち、7番目から 12個分を変数 `range` として、その 12個の部分を Aボタンが押された時にレインボーにするというものです（あと、「黒で点灯 ＝ 消灯」という動作をさせる Bボタン押下時の処理は、 `range` を指定する形でも良かったですが、全体の `strip` を設定しました）。
![作ったプログラム](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/effc4cf3-8686-7444-9c08-ffc10075829e.png)

あとは、プログラムを書きこんで、micro:bit のボタン操作を行うだけです。
そして、無事に以下のとおり動作させることができました。

https://twitter.com/youtoy/status/1603652155981697029
ラムダ式とStreamAPI

## ラムダ式
### 関数を生み出し、即時利用
```java
public class Main {

	public static void main(String[] args) {
		double b = 3.14;
		IntToDoubleFunction func = x -> {
			x = 3;
			return x * x * b;
		};
		
		Function <String, Integer> func1 = (String s) ->{
			return s.length();};
			int num = func1.apply("ABCD");
			System.out.println("ABCDは" + num + "文字です。");
	}
}
```

### 並び替え
```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main6 {
	public static void main(String[] args) {
		List<Account> list = new ArrayList<>();
		list.add(new Account(800,"Saving"));
		list.add(new Account(600,"Check"));
			
		
		list.sort((a, b) -> (a.balanceX - b.balanceX));
		list.forEach(account -> System.out.println(account.balanceX + " " + account.accountNo));
	}
}
```
```java
public class Account {
	int balanceX;
	String accountNo;
	
	Account(int balanceX, String accountNo){
		this.balanceX = balanceX;
		this.accountNo = accountNo;
	}
}
```

## StreamAPI
### リストとして取り出す
```java
import java.util.List;

public class Main5 {

	public static void main(String[] args) {
		List<String> names = List.of("Smith", "Mike", "Keisuke", "Chen");
		names.stream().filter(n -> n.length() <= 5).map(n -> n + "さん").forEach(System.out::println);
	}

}
```

### 条件に合うデータだけを抽出
```java
import java.util.ArrayList;

public class Main7 {

	public static void main(String[] args) {
		ArrayList<Human> list = new ArrayList<>();

		list.add(new Human("Alice", 100));
		list.add(new Human("Keisuke", 300));
		list.add(new Human("Mark", 400));
		list.add(new Human("Sara", 50));

		boolean flg = false;

		flg = list.stream().anyMatch(h -> h.getHp()>100);
		System.out.println(flg);

	}
}
```
## 参考資料
スッキリわかるJava入門 実践編 第3版 (スッキリわかる入門シリーズ)
Pipfileってなんだってばよ

# 0.初めに
pipenvを使っていると「Pipfileでライブラリのバージョン管理を行っている」という話はよく耳にします。
じゃあ、「Pipfileに記述すればそのライブラリが使えるんだな！」とか「Pipfile.lockってよく分からないファイルもあるけど無視してヨシ！」とか考えていたんですが、そんな浅い(間違った)知識だと困る段階になってきたので自分なりにまとめてみることにしてみました。

# 1.pipenv の環境更新の流れ

→ Pipfile → Pipfile.lock → .venv

pipenvの環境更新はこのような流れで行われています。
「なんでこんなめんどくさいことしてるの？.venvに直接パッケージを追加すればよくない？」
という疑問については、各々の役割を考えることで解消されます。

## Pipfile

仮想環境にインストールしたいパッケージをまとめて記述したものです。
ただのコンフィグファイルに過ぎないため、ここにパッケージを記述しただけでは仮想環境でそれを使うことはできません。
仮想環境で使うパッケージが一目でわかる目次的なものです。

## Pipfile.lock

Pipfileの情報をハッシュ値等で保持しているものです。
Pipfileを書き換えても自動でPipfile.lockが書き換わるわけではなく(当たり前ですが)、
後述するコマンドによってPipfileからPipfile.lockが生成されます。

## .venv

仮想環境にインストールしたパッケージが入っている場所です。
ここに配置されることで初めて、仮想環境でそのパッケージが使えるようになります。
後述するコマンドによって、Pipfile.lockの内容を基に.venvにパッケージがそれぞれ配置されます。

### 補足
この説明を最初聞いたとき「間にPipfile.lockを挟む意味ある？直接Pipfileから.venvを生成すればよくない？」って思ってたのですが、その回答としてPipfileの流動性が高いことが原因だと考えています。
Pipfileの中身を見てみると、
```
pandas = "==1.2.0"
numpy = "*"
```
という感じでライブラリのバージョン指定している箇所があります。
この場合だとpandasはバージョン1.2.0を指定しているのですが、numpyのように"*"とすると最新のバージョンをインストールするように指定ができます。
この記述は一見便利に見えますが、Pipfileを参照する時期によってライブラリのバージョンが異なってしまうということでもあります。
この特性は業務などで統一した環境を用いたいときに不便なため、その時点でのバージョンをPipfile.lockに書きだしておく必要があるのだと考えています。

# 2.pipenvコマンド

## pipenv install

→ Pipfile → Pipfile.lock → .venv

の流れをすべて行います。

**主に、仮想環境にライブラリの追加を行いたいときに使います。**

```
pipenv install “hoge==2.0.0”  
```
このコマンドによりPipfileにhogeライブラリのバージョン2.0.0をインストールする旨が記述され、その記述を含めたPipfileの内容で環境が生成されます。

### 補足
--devオプションを使うことで、開発者用の環境でのみ必要なパッケージも含めてインストールすることができます。
具体的には、通常はPipfileの[packages]で指定しているパッケージのみをインストールするのですが、このオプションがある場合は[dev-packages]で指定しているパッケージも追加でインストールします。
pytestやflake8など、開発テストやコードを書くときに必要だが動作には影響しないパッケージは[dev-packages]に記述しましょう。

## pipenv update

Pipfile → Pipfile.lock → .venv

の流れを行います。(Pipfileの更新は行いません。)

**Pipfileの更新自体は行っていなくても、ライブラリのバージョン指定を「*」としている場合は常に最新バージョンを取ってくるためライブラリの更新を行うことができます。**

```
pipenv update
```

また、Pipfileの更新を自前で行った場合にも有効です。

## pipenv sync

Pipfile.lock → .venv

の流れのみを行います。

**PipfileとPipfile.lockをPJ毎に管理してこのコマンドを打つことで、PJ毎に統一された環境を作ることができます。**

```
pipenv sync
```
※Pipfileのみの管理だと、前述したとおり時期によってPipfile.lockに記述されるライブラリのバージョンが揺れるのでPipfile.lockも共有する必要があります。

# 3.おわりに
1人で開発する際にはあまり気にする必要はないけど、チーム開発の際はPipfileとPipfile.lockの役割を理解しておかないと統一した環境で作業できないよーというお話でした。
pipenvへの理解を深めて、より良いチーム開発ライフを！

# 4.参考サイト
https://python.civic-apps.com/difference-between-pipenv-install-update-sync/
複数選択可能な項目のjQuery.val()について

チェックボックスや、selectのmultipleは複数選択できるが、jqueryでval()した際に戻り値はどうなるか。

# チェックボックス

```html
<input type="checkbox" name="sample" value="1">
<input type="checkbox" name="sample" value="2">
```

というチェックボックスに対し、両方ともチェックを入れ、val()した場合。

```javascript
$('[name="sample"]:checked').val(); // => 1
```
先頭の値のみが取れる。
全部欲しい場合は以下のように書く。

```javascript
$('[name="sample"]:checked').toArray().map(e => e.value); // => [1,2]
```

# select[multiple]

```html
<select name="sample" multiple>
    <option value="1">Sample1</option>
    <option value="2">Sample2</option>
    <option value="3">Sample3</option>
</select>
```

全てのoptionを選択した状態で、val()。

```javascript
$('[name="sample"]').val(); // => [1,2,3]
```

こちらは一撃で全てとってくれる。
ちなみに、select[multiple]は一括で値設定もできる。

```javascript
$('[name="sample"]').val([1,3]); // => 対応するoptionが全て選択される
```
mod p での逆元を線形時間で列挙するやつ


無限に同じ内容の記事があると思います

<br>

二項係数の前計算などでよく使う, $1, 2, \cdots, n$ の $\mod p$ での逆元を前計算するやつ, ありますよね

$a ^ {-1} \equiv -(p \\% a) ^ {-1} \times (p // a)\pmod p$

のように計算できるので, $a$ の小さいほうから順に計算しながらテーブルを埋めていくことで, 全体で $\Theta(n)$ で計算できます

($//$ は切り捨て除算, $\\%$ は割った余りを指しています)

ところで何でこんなキモイ式なんでしょうか ぱっと見わからん気がします (僕だけですか？)

最近ライブラリ整備をしていてこれを書かされることが多くなったので, ちょっと整理します

<br>

$p = (p // a)\times a + (p \\% a)$

と書けるのはわかると思います

$\text{mod}$ を取って

$0 \equiv (p // a)\times a + (p \\% a) \pmod p$

いい感じに移項したら

$a ^ {-1} \equiv -(p \\% a) ^ {-1} \times (p // a)\pmod p$

になりました おしまい

<br>

ところでこれは $a \le 1$ のときに死にますね (一敗)
DNSレコードについて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/1ad2b03b-1047-1c23-c1db-8d5b73e688d2.png)
## ホストゾーンとは
ホストゾーンとはドメイン名のこと。レコードにルーティングする方法についての情報が記載されている。
※Route53でドメイン取得を行った場合、ドメイン名と同じホストゾーンが自動生成されます。 

- ## NSレコード
ドメイン情報を管理するネームサーバーを指定するレコードです.
※ネームサーバーとは、インターネット通信時にドメイン名をIPアドレスに変換する名前解決を行うサーバーです。ネームサーバーはDNSサーバーと呼ばれることもあります。
つまり、ネームサーバー＝DNSサーバーのことなのです。

- ## SOAレコード
### ns-758.awsdns-30.net. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400
SOAレコードには問い合わせ先のDNSサーバの詳細情報を記載しています。
※レコードの内容がたくさん詰まっているゾーンファイルが更新されているかチェックする時間を決めていたり、過去にほかのDNSサーバーに「このドメイン知ってる？」と聞いて「知らないよ！」と言われたメモの有効期限などの情報が書かれています。
> ns-758.awsdns-30.net

DNSサーバー(プライマリDNSサーバー)

> awsdns-hostmaster.amazon.com
管理者に連絡が取れるメールアドレス
(デフォルト値は、amazon.com E メールアドレスです。)

> 1 7200 900 1209600 86400

1:ホストゾーンでレコードを更新されるときにオプションで増分されるシリアル番号。Route 53 は自動的にこの番号を増分しません。(シリアル番号はセカンダリ DNS をサポートする DNS サービスによって使用されます)
7200s(2時間):セカンダリDNSサーバなどがレコード情報を再入手（リフレッシュ）する間隔
900s(15分):再入手に失敗した時に再挑戦（リトライ）するまでの待機時間
1209600s(2週間):レコード情報を再入手できない場合の手持ちのレコード情報の有効期限
86400s(1日):あるドメイン名が存在しないという情報（ネガティブキャッシュ）を保持する期間

- ## Aレコード(エイリアスレコード)
Aレコードとは特定のドメイン名に対応するIPアドレス（IPv4アドレス）を定義するもの。
route53独自の機能で
IPアドレスの代わりにAWS リソース (CloudFront ディストリビューションや Amazon S3 バケットなど) を選択することが出来る。

- ## CNAMEレコード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/3556896e-0d9c-5db0-dd5d-6089d979eaca.png)
ドメイン名の別名を指定するためのレコードです。
java　vscode　スクレイピング

java スクレイピング

vscode環境のjava
scrapy.jarはダウンロードできたが、どうやってPythonのpipみたいに使うのかわからなかった

【A】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2957298/907ee3c8-692e-ca88-a336-c2efecb02990.png)

ここに、jarファイルをコピーすると使えるようになる
Ubuntu で使用する Firefox を ESR 版 debパッージに変更

この数年 Firefox のアドオンが使えなくなる問題が度々発生していた。

Ubuntu22.04 になってからまた使えなくなり、これは Ubuntu22.04になって Snap 版 Firefox を使うようになったのが原因らしい。

以下のあわしろいくやさんの記事にいくつか解決法が記されていますが、


「第710回　Snap版Firefoxを使用しないでやり過ごす | gihyo.jp」
https://gihyo.jp/admin/serial/01/ubuntu-recipe/0710


> FirefoxにはESR（Extended Support Release）という長期サポートリリースもあります。実はPPAでパッケージが公開されているため、これを使用する手もあります。

という解決方法があります。

PPA で ESR ではない Firefox もインストールできるらしいですが、 Firefox のバージョン更新にあまりいい印象が無いので、ESR の方で試してみます。

# 問題点

ESR のためバージョン的にダウングレードに更新となる場合、プロファイルをダウングレード移行できないらしい。
今回は引き継ぐプロファイルはなかったのでそのまま作業しました。



# 作業

```
$ sudo snap remove firefox
$ sudo add-apt-repository ppa:mozillateam/ppa
```

また、
「Ubuntu 22.04 で debパッケージ版の Mozilla Firefox を導入する方法」の
https://www.rough-and-cheap.jp/linux/ubuntu-22-04-installing-firefox-using-deb-package/
「PPA からのダウンロードを優先するように設定する」の作業を併せて行いました。

`/etc/apt/preferences.d/mozilla-firefox`
の内容を以下のように記述
```
Package: firefox*
Pin: release o=LP-PPA-mozillateam
Pin-Priority: 1001

Package: firefox*
Pin: release o=Ubuntu*
Pin-Priority: -1
nanbuwks@nanbuwks

```

`/etc/apt/apt.conf.d/51unattended-upgrades-firefox`
の内容を以下のように記述
```
Unattended-Upgrade::Allowed-Origins:: "LP-PPA-mozillateam:${distro_codename}";


```



# チェック

```
$ apt-cache policy firefox
firefox:
  インストールされているバージョン: 1:1snap1-0ubuntu2
  候補:               108.0+build2-0ubuntu0.22.04.1~mt1
  バージョンテーブル:
 *** 1:1snap1-0ubuntu2 -1
        500 http://jp.archive.ubuntu.com/ubuntu jammy/main amd64 Packages
        100 /var/lib/dpkg/status
     108.0+build2-0ubuntu0.22.04.1~mt1 1001
        500 https://ppa.launchpadcontent.net/mozillateam/ppa/ubuntu jammy/main amd64 Packages
```

うん? これでいのかな?

# ESR 版をインストール
```
$ sudo apt install  firefox-esr firefox-esr-locale-ja
```
うまくいったようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/139216d9-1ee5-00cc-026f-e768e37a6329.png)
iOSはどのようにアプリの表示言語を決めるのか

日本語のみ対応しているFlutterアプリが、Appストア上で「言語：英語、日本語」と表示されて困ってしまいました。

![スクリーンショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13070/af19ab49-3aba-83e9-4944-ae93d89c38e6.png)
(※スクリーンショットはTestFlightアプリなので多言語が表示されるのは正しいのですが、ここにアプリ非対応の英語が表示されて困ったという話です)

解決のため、アプリの表示言語の仕組みを調査しました。

## 結論

Appleの下記サイトに表示言語の決定方法が記述されています。

[Technical Q&A QA1828: How iOS Determines the Language For Your App](https://developer.apple.com/library/archive/qa/qa1828/_index.html)


## iOSはどのようにアプリの表示言語を決めるのか

言語は以下の順番で決定されます。

1. iOSは最初にユーザーの設定言語を調査します。これは「設定＞言語と地域」の一番上の言語です。
2. (1)の言語がアプリでサポートされているか？を確認します。アプリバンドルを検索して、(1)の言語に一致する .lproj フォルダを探します。
 2.1 フォルダが存在する場合、アプリがその言語にローカライズされているとみなし、アプリ用に選択します。
 2.2 フォルダが存在しない場合、「設定＞言語と地域」での次の言語を選択し、上記のチェックを繰り返します。
3. 上記のチェックに該当する言語がアプリでサポートされていない場合、iOS はアプリの Info.plist の CFBundleDevelopmentRegion に一致する言語を選択します。(この場合は Info.plist の CFBundleLocalizations の設定も必要になるようです)


## アプリストアに表示される対応言語について

次に、ストアのアプリ情報欄に表示される言語についてです。

![スクリーンショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13070/af19ab49-3aba-83e9-4944-ae93d89c38e6.png)

ここの表示については、[QA1828](https://developer.apple.com/library/archive/qa/qa1828/_index.html) の注釈に書いてあります。

> アプリストアに表示される言語欄は、 iTunesConnect(現AppStoreConnect)での設定よりも、.lprojフォルダの存在が優先されます。

そして、アプリストアの言語欄にアプリがサポートしていない言語が表示されている場合は、以下の項目をチェックすれば良いようです。

* .lprojフォルダを使用している場合 → フォルダの存在を確認しましょう
* .lprojフォルダを使用していない場合 → Info.plist の CFBundleLocalizations に言語を設定しているか確認しましょう

## まとめ

おそらく、下記を行えばアプリの表示言語・ストアでの表示言語ともに対応できるのでは、と思います。

* 多言語対応するアプリの場合 → 各言語の .lprojフォルダ の存在を確認
* 多言語対応しないアプリの場合 → Info.plist の CFBundleDevelopmentRegion と CFBundleLocalizations の設定を確認

ただ、多言語対応しているアプリでも、サポート範囲外の言語のユーザーを想定して、 CFBundleDevelopmentRegion と CFBundleLocalizations は設定しておくべきでしょうか。


## 参考資料

[Technical Q&A QA1828: How iOS Determines the Language For Your App](https://developer.apple.com/library/archive/qa/qa1828/_index.html)


## 免責

記事中では多言語対応についても書いていますが、私自身多言語アプリを作成したことがないので、誤りがあるかもしれません＞＜ 
正しい情報は公式ドキュメント [QA1828](https://developer.apple.com/library/archive/qa/qa1828/_index.html) を参照してください
samber/lo で三項演算子っぽくコードが書けるよ

本記事は[Go Advent Calendar 2022](https://qiita.com/advent-calendar/2022/go)の16日目の記事です。

[samber/lo](https://github.com/samber/lo)に三項演算子のようなコードを書くことができる関数が在ることをしったので紹介します。

## `samber/lo`とは

`samber/lo`は,多種多様な便利関数を提供するパッケージです。
JavaScriptのライブラリの`Lodash`ライクであるとREADMEにも記載があります。
個人的には大好きなパッケージでして,`Map`,`Filter`等のスライスを操作する関数をよく使っています。

https://github.com/samber/lo
https://github.com/lodash/lodash

## `Ternary`

アドベントカレンダーのネタ探しに`samber/lo`のREADMEを眺めていたところ`Ternary`という関数があることを知りました。
この関数を用いると三項演算子のようなコードを書くことができます。

```go
count := 1

// 第一引数が真であれば第二引数の値を返す。
// 第一引数が偽であれば第三引数の値を返す。
resultA := lo.Ternary(count > 0, "ok", "ng")
resultB := lo.Ternary(count > 10, "ok", "ng")

fmt.Println(resultA) // ok
fmt.Println(resultB) // ng
```

また,ジェネリックな関数であり,戻り値の型はコンパイル時に決定します。

```go
lo.Ternary(count > 0, 1, 0)
lo.Ternary(count > 0, []int{1}, nil)
```

## `TernaryF`

`Ternary`の第二,第三引数は型パラメータとして渡される型の値である必要がありました。
値を生成するコストが高い場合もあるかと思うので,生成処理は真偽値の判定後に行いたいですね。
そういったケースでは`TernaryF`を使用するのが良さそうです。
実際に呼び出される関数はどちらか一方となる為,不要な値の生成処理は実行されることはありません。

```go
count := 1

// 第一引数が真であれば第二引数の関数を呼び出し戻り値を返す。
// 第一引数が偽であれば第三引数の関数を呼び出し戻り値を返す。
resultA := lo.TernaryF(count > 0, func() string { return "ok" }, func() string { return "ng" })
resultB := lo.TernaryF(count > 10, func() string { return "ok" }, func() string { return "ng" })

fmt.Println(resultA) // ok
fmt.Println(resultB) // ng
```

## おわりに

今回紹介したものの他にも`samber/lo`には様々な場面で使用できるヘルパーがサポートされています。
`samber/lo`に置き換えられる独自実装関数がきっとまだまだ在るはず...
ファイルの読み書き

## ファイルに2進数のデータを追記する
```java
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
		//ファイル/パスを指定して生成
		FileOutputStream fos = new FileOutputStream("bainary.data", true);
		//書き込むデータをバッファに保存
		fos.write(65);
		fos.flush();
		//ファイルを閉じる
		fos.close();
	}
}
```

## 書き込み
```java
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
		FileWriter fw = new FileWriter("xxxx", true);
		fw.write("A");
		fw.flush();
		fw.close();
	}
}
```

## 読み取り
```java
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
		FileReader fw = new FileReader("xxx.data");
		int i = fw.read();
		while (i != 1) {
			char c = (char) i;
			{
				System.out.println(c);
				i = fw.read();
			}
			fw.close();
		}
	}
}
```

## 例外処理
```java
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
		FileWriter fw = null;
		try {
			fw = new FileWriter("xxxx.data", true);
			fw.write("A");
			fw.flush();
			//例外の詳細情報をeに渡し、例外処理を行う
		} catch (IOException e) {
			System.out.println("異常が発生しました");
		} finally {
			if (fw != null) {
				try {
					fw.close();
				} catch (IOException e2) {
				}
			}
		}
	}
}
```

### try with resources文の利用
```java
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Main {
	public static void main(String[] args) {
		try (FileWriter fw = new FileWriter("xxxx.data", true);) {
			fw.write("A");
			fw.flush();
			// 例外の詳細情報をeに渡し、例外処理を行う
		} catch (IOException e) {
			System.out.println("異常が発生しました");
		}
	}

}
```
rails newしたときにNo value provided for required arguments 'app_path'が出た時の対処法


```
rails new
No value provided for required arguments 'app_path'
```

このようなコードが出た時は、rails newの後に自由に引数を入力してあげると、正常に動作します。


例えば、↓

```
rails new new_app
```

参考サイト
[No value provided for required arguments 'app_path'](https://teratail.com/questions/161951)
TemplateView & TransformView

![16.TemplateView & TransformView.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/bfaf159b-6b14-b5dd-9cc4-4d620af6a78c.png)


https://bliki-ja.github.io/pofeaa/TemplateView/

https://bliki-ja.github.io/pofeaa/TransformView/

Web アプリケーションにおける Template View は、HTML テンプレートに Domain Model のエンティティ (または Transaction Script のクエリ結果) 群を流し込んで、ページを出力する方法です。多くの Web フレームワークが採用していて、わざわざ改めて説明することはないかもしれません。

Template View パターンを用いる目的は、プログラミングを避けることです。ビューの役目はモデルのデータ表示ですが、そのとき、本質と無関係なプログラムを同じところに混ぜて書くと、余計なことのせいでミスを起こしやすくなります。同時に意識する責務の凝集度が低くするのは、良くないプログラミングですね。本質と無関係なレイアウトの心配は、静的な HTML を書くだけで済むように、テンプレートエンジンを使って済ませるのが賢いやり方です。

Web フロントエンドでも、React は JavaScript の中に XHTML を入れ込んだような、JSX という拡張構文をサポートしました。もともと React は JavaScript だけで仮想 DOM を構築するビュー技術でしたが、レイアウトのためにプログラムコードを保守するのがとても面倒でした。静的な XHTML を書ききって、その中に値やコンポーネントをはめ込んでいく JSX を使えば、サーバーサイドの Template View と全く同じメリットを得られます。MVC は時代を超えて GUI に共通する特徴です。

Template View の弱点は言語構文が単純すぎることです。インラインで書ききれるような、ちょっとしたヘルパー機能を使って、値を表示に適した形式に変換するようなレベルの工夫は推奨されます。しかし、表示のオンオフ程度では済まない、段階的な手続きが必要な判断は実際にあります。JSP や PHP は、テンプレートの中にちょっとしたスクリプトを書くこともできますが、テンプレート構文のディレクティブと埋め込みスクリプトだけで頑張ってしまうと、「賢すぎるビュー」アンチパターンに陥ります。

Template View の弱点を補うために、複雑な事情を持つモデルを扱うときは Transform View を併用します。Transform View は、ひとつの単位データモデルを扱います。内部のプログラムでモデルに自由にアクセスし、プログラム言語のパワーをフルに活用して、最終的にレイアウトで使える部分ビューを得る方法です。得られるものは、HTML の `<div>〜</div>` ブロックかもしれないし、React 仮想 DOM の構造物かもしれません。

ユーザー入力のバリデーション結果をフィードバックできる Web フォームは、かなり複雑なデータモデルを扱います。要素タイプによって、データをどのような HTML 表現にするか、エラーをどう添えて表示するかが異なります。要素の選択、属性の有無、内部ノードは?、配置は水平か垂直か... テンプレート構文でそんな事情を全て表現する方が難しいですね。割り切って Transform View ブロックとしてプログラミングで暑かった結果だけを利用する方が賢いでしょう。

Web ページには、機能の主題と関係のないビジュアル要素も多く含まれます。ひとつのテンプレートの責務がいくつもの雑多な事情を抱えるのは負担です。主題でないデータモデルの視覚化を隠蔽し、複雑なモデルを変換した結果だけをもらってはめ込むアイデアは、そうした事情の整理にも活用できます。`<aside>` セクションに、実は中身が案外ややこしいい React コンポーネントを持ってきて、はめ込むだけで済ませるのは楽ですね。

PoEAA 本の解説はサーバーサイドのプレゼンテーションに特化していますが、MVC についての本質的な考え方は、現代の複合的なでも活きてきます。
【14日目】discord.jsでじゃんけんを作ろう

# はじめに
こんにちは、なりかくんです。
今回は、discord.jsでじゃんけんをするというめちゃくちゃ初歩的なものを作ろうと思います。

# 勝ち負けの判断
勝ち負けの判断は計算で求める方法もありますが、今回は普通にifで処理したいと思います。
```js
if (janken_r === janken_p) {
    result = "あいこです";
} else if (janken_p === 0 && janken_r === 1) {
    result = "あなたの 勝ち です";
} else if (janken_p === 1 && janken_r === 2) {
    result = "あなたの 勝ち です";
} else if (janken_p === 2 && janken_r === 0) {
    result = "あなたの 勝ち です";
} else {
    result = "あなたの 負け です";
}
```
# コードの全体
今回のコードの全体はこのようになります。
```js:janken.js
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');

module.exports = {
	data: new SlashCommandBuilder()
		.setName('janken')
		.setDescription('じゃんけんコマンド'),
	async execute(interaction) {
		const filter = response => {
			return interaction.user.id == response.author.id;
		};
		let janken = ['グー','チョキ','パー',];
		let janken_r = Math.floor( Math.random() * 3);
		interaction.reply({ content: "じゃんけん... (g, c, p)", fetchReply: true })
			.then(() => {
				interaction.channel.awaitMessages({ filter, max: 1, time: 30000, errors: ['time'] })
					.then(collected => {
						let janken_pC = collected.first().content;
						let janken_p = 5;
						switch (janken_pC) {
							case "g":
								janken_p = 0;
								break;
							case "c":
								janken_p = 1;
								break;
							case "p":
								janken_p = 2;
								break;
						}
						let result = "";
						if (janken_r === janken_p) {
							result = "あいこです";
						} else if (janken_p === 0 && janken_r === 1) {
							result = "あなたの 勝ち です";
						} else if (janken_p === 1 && janken_r === 2) {
							result = "あなたの 勝ち です";
						} else if (janken_p === 2 && janken_r === 0) {
							result = "あなたの 勝ち です";
						} else {
							result = "あなたの 負け です";
						}
						interaction.followUp(`あなたは ${janken[janken_p]} を出して、Botは ${janken[janken_r]} を出しました。\n${result}`);
					})
					.catch(collected => {
						interaction.followUp(`じゃんけんの返事が来なかったみたいだね...`);
					});
			});
	},
};
```
以下のawaitMessages()を使うとチャンネルで送られてくるメッセージを待機して取得することが出来ます。
```js
channel.awaitMessages()
```
`interaction.followUp()`は、Bot自身が送信したメッセージにリプライするような形で返信するようになります。
```js
interaction.followUp(`あいうえお`);
```

 # 実際に動かしてみる
実際に動かしてみるとこのようになります。しっかり動いてますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/35cc6321-251d-9c5b-fd22-ae39dcc980e9.png)

# 最後に
ぜひ皆さんも最初はじゃんけんゲームでも作ってみましょう！
以上です、最後までお読みいただきありがとうございました。
ScalaからKotlinに変えた話

## はじめに
この記事はフリューAdvent Calendar 2022の24日目の記事となります。

フリュー株式会社スマートフォンゲーム部で、Webサーバーエンジニアをしている山根です。
これまで担当してきた開発では、主にScalaを使って開発を行ってきていました。
そしてこの度、Scalaではなく、Kotlinを使った開発を行うことにしました。

## Scalaを変えた理由
Scalaを使ってきた背景としては、
* 静的型付け言語、関数型言語という点
* Scalaを扱えるエンジニアがそこそこいる

といった感じで、使っていました。  
ただ、エンジニア内で今後もScalaを使い続けるのか議論した際に、
* 他言語を使いたい!
* Scala2からScala3への変更点が多い
* エンジニアの母数が少ない など...

といった意見が多々あり、Scala以外の言語を使うことになりました。

## 言語選定
Scalaと同様の静的型付け言語である <b>TypeScript, Kotlin</b> から選定しました。

参考にしたベンチマーク
(https://programming-language-benchmarks.vercel.app/kotlin-vs-javascript より引用)

ベンチマークを参考にすると、
どちらを選択しても、そこまで問題にはならなさそうです。
そこで、Frameworkを含めてざっくり評価をしてみました。
||メンテナンス性|速度・パフォーマンス|インフラ費用|人気度|周辺ライブラリ(Framework等)|社内利用度|
| ---- | ---- | ---- | ---- | ---- | ---- | ---- |
|Scala + [PlayFramework](https://www.playframework.com/)※|10|10|10|10|10|10|
|TypeScript + [Nest.js](https://docs.nestjs.com/)|5|8|8|15|10|8|
|Kotlin + [Ktor](https://ktor.io/docs/welcome.html)|8|10|10|18|10|16|

※評価基準として10としています。

ベンチマークや評価結果から<b>Kotlin</b>を使ってみることになりました。

## コード比較
ちょっとだけScala, Kotlinのコードを見比べてみます。
### Scala: Option型 vs Kotlin: Null許容型
#### Scala
```
val test1: Option[String] = Some("str")
val test2: Option[String] = None
val test3: String = test1.getOrElse("")
```
#### Kotlin
```
var test1: String? = "str"
var test2: String? = null
var test3: String = test1 ?: ""
```

### Scala: Tuple型 vs Kotlin: Pair型orTriple型
#### Scala
```
val test1: (Int, String) = (1, "one")
val test2: (Int, Double, String) = (1, 1.0, "one")
```
#### Kotlin
```
val test1: Pair<Int, String> = Pair(1, "one")
val test2: Triple<Int, Double, String> = Triple(1, 1.0, "one")
```

### Scala: match case vs Kotlin: when
#### Scala
```
object Color extends Enumeration {
  type Color = Value
  val Red, Blue, Pink = Value
}
def str(color: Color): String = {
  color match {
    case Color.Red => "赤色"
    case Color.Blue => "青色"
    case _ => "その他"
  }
}
```
#### Kotlin
```
enum class Color {
  Red,
  Blue,
  Pink;
}
fun str(color: Color): String {
  return when (color) {
    Color.Red -> "赤色"
    Color.Blue -> "青色"
    else -> "その他"
  }
}
```

ざっと見比べると、当然書き方は異なりますが、
Kotlinの学習はしやすい印象を受けます。

## Framework等の構成
Kotlinを使って開発するに当たり、FrameworkやORM、DIを以下のようにしました。
|  項目  |  内容  |  ドキュメント等  |
| ---- | ---- | ---- |
|  Framework  |  Ktor  |  https://ktor.io/docs/welcome.html  |
|  ORM  |  Exposed  |  https://github.com/JetBrains/Exposed  |
|  DI  |  Koin  |  https://insert-koin.io/docs/reference/koin-ktor/ktor  |

## Ktor
ちょっとだけKtorの紹介をすると、

IntelliJ IDEAやKotlinなどの作成者であるJetBrainsが提供している純Kotlin製のFrameworkです。
サーバー側およびクライアント側のアプリケーションを作成でき、JVM、Kotlin/Nativeなどの複数のプラットフォームをサポートしているようです。
また、「<b>Simple and fun</b>」と自負しているように、
軽量で拡張性が高く、それゆえに楽しいということのようです。

## まとめ
ScalaからKotlinに変えてみましたが、全く問題なさそうです。
また、Kotlin＋Ktorは、すごく楽しいそうな印象を受けました。
まだまだ使い始めたばかりですが、
色々と勉強しながら、やっていきたいと思います！
JestのuseFakeTimersを使用するとFirestoreにアクセスできなくなる

## 問題のコード

テストを書いていると、日時を固定したくなるケースがあると思う。
Jestには`useFakeTimers()`という便利な関数があり、これを呼び出すことで、日時を固定したテストの実行が可能になる。
しかし、この`useFakeTimers()`を呼び出すと、Firestoreにアクセスできず、テストがタイムアウトしてしまった。

```typescript:index.test.ts
describe('test', () => {
  beforeAll(() => {
    // 日時を固定する
    jest.useFakeTimers();
    const fixedDate = new Date('2020-09-01T02:00:00+09:00');
    jest.setSystemTime(fixedDate);
  });

  afterAll(() => {
    // 日時の固定を解除する
    jest.useRealTimers();
  });

  it('Add document test', async () => {
    const ref = collection(firestore, 'tests');
    await addDoc(ref, { id: 'hoge' }); // アクセスできない

    const snapshot = await getDocs(ref);
    expect(snapshot.docs.length).toBe(1);
  });
});
```

## 対応策

- テスト対象の関数から、Firestoreにアクセスする部分を切り出す
- Jest以外の方法で日時を固定できないか試してみる

## 最後に

何か良い解決策が見つかったら、是非コメントで教えてください！
ちなみに、[こちら](https://stackoverflow.com/questions/71437598/jest-usefaketimers-blocks-when-used-with-firebase-emulators)にも同じ問題が上がっているが、特に解決していない。
アジャイル開発とウォーターフォール開発について

# はじめに
今回は開発工程に関する知識を忘れないように記録に残す。
就職活動に活かせる知識なので、よく理解しておく必要がある。

# アジャイル開発とウォーターフール開発の違いについて
- アジャイル開発
システム開発のプロセスのうち、「設計」「開発」「テスト」「リリース」の小さな開発サイクルを何度も繰り返す手法。
小規模から中規模の案件の開発に適しており、途中での仕様変更が比較的しやすい。

- ウォーターフォール開発
「要件定義」から「運用」までの一連の工程を、上流から下流まで順番に進めるシンプルな手法です。
はじめに綿密に要件定義を行うため、途中での仕様変更が難しく、大規模案件に適している。
文字コードで躓いた話

## 発生事象
とあるシステム開発に携わっていた際、顧客から「特定のファイルを取り込もうとすると、システムがクラッシュしてしまう」と不具合報告をいただきました。
ファイルを連携してもらい、中身を確認するも目検では特に問題は見つからず…
デバッグしていくと、特定文字列でクラッシュしていることがわかりました。

## 謎の文字列
デバッグして実際に見つけたのが下記の文字列です。

A.「データ」
B.「データ」

Aは比較用にこちらで手打ちしたもの、Bがデバッグで見つけたものです。
上記2つの文字列は見た目上同じに見えますが、sakuraエディタに貼り付けると下記のような状態になります。
![MicrosoftTeams-image (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641628/d32c3ac6-a907-8277-fdfb-61d452854f65.png)
さらに、これらはExcel上で表示するフォントによっても見え方が異なります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641628/8d55c69e-6ef0-7d52-58d7-dda5fbc2d385.png)


## 文字コード検査をやってみる
恐らく文字コードが原因だろうと目星をつけ、それぞれを文字コード（UTF-8）で表してみました。
**Aの結果**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641628/4baa151d-8f3f-a429-0f8c-48715b9cdecf.png)

**Bの結果**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641628/c99475c5-2cd3-f090-831f-be20a41bd292.png)
文字コード的にも全然違いました。
そもそもBの「デ」は、「30C6 + 3099」で成り立っているようです。
なるほど、ということは日本語カナ入力の＠で出てくる「゛」を使っているのでは？と思い検証した結果が下記です。

**「テ゛ータ」の文字コード検査結果**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641628/ed73b12f-0dc2-c836-3b30-497835d3b134.png)
「゛」の文字コードは「309B」であり、どうやら別物のようです。
状況をまとめると下記になります。
![MicrosoftTeams-image (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641628/2514a433-db96-3a11-75cb-bfb38d78bdd1.png)
こうなってくると、ユーザーがわざわざ文字コード（3099）を使って入力しているとしか考えられません。

::: note warn
※一応やろうと思えばできる
**①全角で文字コードを入力**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641628/4a02d186-299a-80d4-bd73-3efe42a1a56c.png)
**②文字コード変換**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641628/51d24de4-d7c8-4925-c2b5-057156f9a7a6.png)
**③入力できる**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641628/ffd63ea6-2ac0-025d-a002-dc0c45b6666e.png)
:::
しかしながら当然そんなわけないため、（IT初学者の私にとっては）シンプルに謎でした。

## 原因について
社内で助言を求めたところ、OS起因説が浮上しました。
調べてみると、どうやらMacOSで作成したファイルをWindowsで確認した場合や、MacOSで作成したPDFやWord内の文字をコピーし、Windowsで張り付けをした場合に文字化けを起こす可能性があるようです。
この場合の文字化けとは、**「日本語の濁点が入浴されたと思わしき部分（2バイト文字）が「?」と表示されたり、かな/カナ文字と濁点部分が分離されて表示される現象」** らしく、本件の原因を説明しうる現象でした。

>この文字化け現象はどうやら基本ソフト(OS)のファイルシステムの違いに関係するようです。Windowsが導入しているファイルシステム「NTFC」に対し、MacOXが導入しているファイルシステムは「HFS Plus」です。双方のファイルシステムのUnicodeを正規化する過程（WindowsやLinuxはNFC方式が採用され、MacOXはNFD方式が採用されています）での形式に違いがあり、MacのUnicode（＝NFD形式）で入力した文字はWindows環境へ横断すると濁点部分が分離するなど正しく情報を読み取れない現象が発生してしまうようです。
（引用：https://www.sanei-fcg.com/blog/2019/09/18/1239/）


これだ！と思いユーザに確認しましたが、「社内ではMacOSを使っていないが、該当ファイルを渡してくれる別会社がMacOSを使っているかもしれない（わからない）」とのこと…原因は闇の中…


とはいえ、システム不具合については運用でカバーいただく形で落ち着き、原因については自分なりに納得できるものを得られたため、本件はクローズとなりました。

## まとめ
発生当初はどうなることかと思いましたが、結果的に文字コードのみならずOSのファイルシステムにまで踏み込んだ知見を得られました。
皆さんも文字コードで躓いた際は、OS起因を疑ってみてはいかがでしょうか。


### 参考文献
文字コード判別：http://www.shurey.com/js/works/unicode.html
濁点関係：https://www.asahi-net.or.jp/~ax2s-KMTN/ref/unicode/u3040.html
OS横断時の文字化け①：https://www.sanei-fcg.com/blog/2019/09/18/1239/
OS横断時の文字化け②：https://www.chihayafuru.jp/tech/index.php/archives/2460
phpstormでspanタグを整形してくれない問題

## 概要

phpstormさん、初期設定だと``<span>``,``<pre>``,``<textarea>``を整形してくれません(余白が保持される)

``<span>``タグ内で余白を保持したい事があまり無いので、余白を保持しない様にします。

## 設定

``設定→エディター→コードスタイル→HTML→その他``

の、``内側に空白を維持する``欄に``<span>``がいるので消します。

![スクリーンショット 2022-12-16 13.20.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/3862a3cf-cea4-d9e8-bdc4-12b1203d1fad.png)

これで``<span>`` も整形対象になり、不自然なタグ構造にならなくなりました
QAテスターから翻訳QAのテスト管理者へ転向後の意識の違い

# はじめに
はじめまして！@seyadeと申します。
経歴からご説明させていただきます。
ゲーム開発のQAテスター業務を3年ほど対応し、
3カ月前から翻訳QAのテスト管理者へ転向し日々精進しております。

今回は通常のQAと翻訳QAに携わったうえで、以下の側面でお話したいと思います。
- QAと翻訳QAの違いの面
- テスターとテスト管理者を経験したうえでの感じた違い

初歩的な話が多めですが、これから翻訳QAに関わる方や新たにテスト管理者として従事される方に
少しでも参考にできる部分がありましたら幸いです。

# テスト観点の違い

ゲーム開発において、テスト目的によって考慮すべきテストの観点は変わりますが大枠の目的は以下に分けられると考えます。

|  区分  | 範囲  | 目的  |
| ---- | ---- | ---- |
|  QA  |  アプリ内全体  | 仕様通り正しく動作すること、予期せぬバグがないことを検証  |
|  翻訳QA  |  テキスト、アセット物等  |  多言語の誤字、誤訳、ニュアンスの相違、翻訳された文言が正しく表示されることを検証  |

これまでQAテスターとして対応していて、
画面上検知した不具合や違和感は基本的に全て報告していた身としては、
確認する範囲がテキストやアセット物に限定されるなら比較的単純になるのではと思っていましたがそんなことはなく…。

以下は翻訳QAにおける不具合報告タイプの例となります。

例：
![観点.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3065150/7db1d125-c866-f752-25a3-cb322c20ac12.png)

この例に限らず拾うべきテスト観点はとても多いです。

むしろニュアンスに関してはネイティブの方でしか感じ取れないものもあるので
単純にこれが正解とはっきりしていないものもある分難しく奥深く感じます。

# テスターとテスト管理者の違い

翻訳QAのテスト管理者に転向してまだ3カ月と未熟ではありますが感じた部分として
テスターとして対応していた時とそれぞれ求められるものが違く、
これまでの経験が活きてるというものもあれば、経験がまだ浅く苦労している部分もあります。
それらの内容を以下に書き出していきます。

#### テスターとしての経験が活きている部分

- **テスト準備（検証環境の整備）**

検証を実行するにあたって**何が必要でどの部門に依頼すべきか**はある程度把握してたので比較的スムーズでした。
具体的には検証用アカウントやBTSアカウントの準備と整備などです。

- **システムの操作**


私はテスターの頃と同じ開発会社のタイトルに配属となりましたが、
デバッグツールの使用感はほとんど同じだったのでテスターへのツールの使用マニュアルの作成準備も早期に対応できました。
開発元は違く手も、デバッグコマンド自体はこれまでのナレッジである程度の当たりはつくところもあるので経験として活かせる部分だと思います。

#### 苦労している部分①マネジメント

今までテスターとしては基本的に上のレイヤーから依頼されたものを期間内に処理することを求められてましたが、
個人の進捗だけでなく検証の実行状況、テスト設計状況、開発側での実装状況など諸々の状況を把握し報告/共有する能力が必要となります。

少人数のグループ単位の状況把握はまだ対応できていましたが、見るべき領域が格段に跳ね上がるのでそれに対処する準備は早期に行うべきと感じました。

#### 苦労している部分②コミュニケーション

①にも関連するところですが、業務で密に連携する必要がある人の数も増えていきます。
開発側の方やそれを統括している方やQAメンバーと良好な関係性を保つコミュニケーションが不可欠です。
特に翻訳QAはQA部門と比べ軽視されているわけではないですが、比較的連携漏れが発生しやすい立場だと感じます。
自分から拾える情報は積極的に拾う姿勢と、存在アピールが重要だと思います。

# 最後に

翻訳QAの担当となり最初は他言語が読めない人間が対応できるのかというのが率直な感想でした。
ですが、英語だけでなく第二外国語をマスターしているレベルの方は稀有であり
それよりもマネジメントスキルやコミュニケーションの部分で苦労している自分がいるので
翻訳QAの担当であるからといってやることの大枠はQA部門と大きくは変わらないように感じてます。

私も日々学習の身ですが、管理の工夫を凝らして年末年始も乗り切りたいです！