OmniAICreator/Qiita-1.07M huggingface dataset:
【Unity初歩】~ゲームクリアシーンを作る~

# はじめに
前回、敵とゴールオブジェクトに当たり判定をつけました。今回はゴールをするとクリアシーンに遷移するようにします。

前回の記事

https://qiita.com/usomaru/items/1dde68cf7d892446d5c3

# シーンの遷移
これまではずっとゲームシーンを作成していました。今回は新たにクリアシーンというものを作成することで、ゴールオブジェクトに🦀が当たるとゲームクリアという判定になり、クリアシーンへと遷移するようにします。

# クリアシーンの追加
※忘れてましたが、シーンを追加する前に、今作成しているゲームシーンを名前を付けて登録しておけばよかったです。

新しいシーンは、ツールバーのFile > New Sceneから追加できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/4b757c48-88bd-4a51-f62e-d285abafd641.png)

New Sceneをクリックすると、Sceneのテンプレートを選ぶことになります。
Basic 2Dを選択して「Create」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/a7674387-aff1-831b-ef73-ec805607eb06.png)

続いて追加したシーンに名前をつけて保存をしたいので、ヒエラルキーウィンドウにあるシーンの上で右クリックをして「Save Scene As」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/41ec292d-c2e6-9df0-2016-25a9c9c4252b.png)

「ClearScene」という名前で保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/948cdb36-2065-8977-15e7-3f866100b3fb.png)

新しいシーンが追加されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/c2394e77-6084-fd61-8031-215cb13d019c.png)

バックグラウンドと「ゲームクリア」というテキストを足して簡易的なクリアシーンを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/1cdff11b-2dec-b258-04f0-94d5b027fe60.png)


テキストはヒエラルキーウィンドウで右クリックでここから足せます。UI Textが表示されなくてちょっと戸惑ったのですが、解消法は下に載せております。
UI > Legacy > Text
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/811a8dd5-f83b-a8d3-d96d-319378036e0b.png)

# シーンの登録
ツールバーのFile > Build Settingsを選択します。選択すると以下の画像の画面が表示されるかと思います。

Scenes/SampleSceneはずっと作っていたゲーム画面のことです。(シーンの名前を変えて登録し忘れたのでこんなことになっている)
この画面のScenes In BuildのところにClearSceneをドラッグアンドドロップで追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/ff710931-2962-4af0-807d-e85b96bedaa7.png)

追加すると、右側に番号がふられるのですが、この番号順にスタートするということです。
つまり、ゲームシーンからスタートします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/4350a516-3160-d7e3-3e4d-d1bff5a4eff3.png)

# 遷移させるコードをかく
PlayerControllerに以下のコードを追加します。
(今はコンソールでゴールって表示されるようになっているはず。)

```c#
using UnityEngine.SceneManagement;

// ~省略~

private void OnTriggerEnter2D(Collider2D collision)
{
    SceneManager.LoadScene("ClearScene");
}
```

# クリアシーンに遷移するか確認

https://twitter.com/usomaru26/status/1733684425953833080

# UI Textが表示されなかった問題

Render ModeをWorld Spaceに変更する必要がありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/7128ddbb-7110-17de-54cd-dd8a97198c48.png)


https://tichise.medium.com/unity%E3%81%A7canvas%E3%81%ABimage%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84%E3%81%A8%E3%81%8D%E3%81%AE%E5%AF%BE%E5%87%A6%E6%96%B9%E6%B3%95-768c02c0182e

# おわりに
クリアシーンへ到達する動画をとるまでに何回かしにました。
すごく簡易的ですが、ゲームっぽくなった気がします。
ペルソナで一番大事なのは「顔面」！！！


先日とある研修でペルソナを作る機会があったのですが、そこでCanvaのAI顔生成機能を使ってみたらめっちゃ良かったので共有します。

##
そもそも「ペルソナ」とは、サービスデザインやマーケティングにおいてよく活用されている概念で、そのサービス・プロダクトの典型的なユーザー像を提示するために設定されます。
対象となるユーザー像 = ペルソナを、名前、年齢、性別、容姿、出身地、居住地、職業、収入、家族構成、趣味、特技、幸せを感じる瞬間、最近困っていることなどできる限り細かく具体的に設定し、そのペルソナの視点からサービス・プロダクトを設計していきます。
##
では、そんなペルソナを作る上で一番重要なポイントは一体なんでしょうか？

それは「顔面」です。
イケメンの方が良いとか、可愛い方が良いとかではなく

プロフィールを読んだ後、顔を見た時にちゃんとしっくり来る顔を用意すること、これがめっちゃ重要だと思います。（写真もしくはイラストでも）

たまにこういう感じの画像を使ったペルソナを見かけますが、あまり良くないと思います（画像無しよりはマシですが）
<img width="200" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491979/160f3f94-9516-265b-b1bd-9b814d1701f4.png>
これだと画像からほとんどペルソナの情報を得られないし、もし複数人のチームで案件に取り組んでいる場合プロジェクトメンバーにペルソナを共有すると、メンバーそれぞれがプロフィール情報から勝手に顔をイメージして補完してしまうのでせっかくの共通指標にブレが生じてしまいます。

チームでペルソナを設定する時には
ペルソナ ＝　実在しないけどプロジェクトメンバーはみんなよく知ってるアイツ
という状態が理想です。

そのためにはペルソナの顔（写真、イラスト）を用意する必要があります。

https://www.photo-ac.com/main/search?q=%E9%A1%94&srt=dlrank&qt=&p=1&pt=C

このようなフリー素材サイトで写真を探してくるのも良いんですが、この手の画像はフリー素材がゆえ、色々なシチュエーションに使えるように撮影された画像ばかりで、現実味が無いしどこにでもいるような感じになっちゃうんですよね。

##
そこで今回はCanvaのAI顔画像生成ツールを使ってみました。
単語やフレーズから　顔画像を生成してくれるサービスです。
フリー素材だとどうしても実在するモデルさんの写真になってしまいますし、あらかじめAIによって生成された画像も当たり障りのない画像ばかりですが
テキストから生成してくれるなら、ペルソナのイメージ通りの画像がゲットできるはず！

https://www.canva.com/ja_jp/ai-image-generator/


>Canva（キャンバ）とは
Canvaは、オンラインで使える無料のグラフィックデザインツールです。61万点ものテンプレートと、1億点の素材（写真、動画、イラスト、音楽）があり、ドラッグ＆ドロップの簡単操作で誰でも簡単にあらゆるデザインを作成できます。パソコンはもちろん、スマートフォンやタブレットでも使えます。Canvaで作成したデザインを数クリックで印刷注文できる「Canvaプリント」と呼ばれる印刷サービスも提供しています。
公式サイトより引用(https://www.canva.com/ja_jp/learn/easytodesign/)


今回のペルソナのプロフィールはこちら

- 名前：陳 家豪
- 性別：男性
- 年齢：27歳
- 出身：台湾
- 居住地：名古屋
- 職業：飲食関係
- 趣味：Vlogなど動画投稿
- 日本のアニメが好き 

さっそく
「台湾出身、27歳男性、日本のアニメが好き」
このテキストをぶちこんでみました。

いくつか候補が生成されたなかで私がピンと来たのがこちらの画像
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491979/d32fb49d-0638-5d1d-d6fa-32452a166f6c.png>

いやーこの一枚の画像からいろいろ伝わってくるし、私のイメージ通りの画像を生成してくれてびっくりです。
生成系AI恐るべし


無料でいろいろ試せるので、皆さんもぜひペルソナ作りに活用してみてください〜
【React基礎】memo,useCallback

## はじめに
　Reactを学習している中で基礎の部分がしっかり理解できていないことを痛感しているため、初歩から学習し直しています。
 アウトプットのために上げます！間違い等がございましたら教えていただきたいです。

##  学んだこと
### 再レンダリングは起きる条件
・propsの値が変更された時
・stateの値かが変更された時
・親コンポーネントが再レンダリングされた時

### memo(() => {})
**コンポーネントのメモ化！！！**
子コンポーネントが親コンポーネントに影響を受けないようにするために使う。
基本的に子コンポーネントで使う。
```
const Componet = memo(() => {});
```
　親コンポーネントが再レンダリングされたときに子コンポーネントが再レンダリングされないようにする。
 `props`が変更されたときには再レンダリングされる。

 ### useCallback
 **関数のメモ化！！！**
 Propsが変化するとき再レンダリングされるのを防ぐために使う。
 親コンポーネントで主に使う。
```
const onClickChange = useCallback(（） => {
  alert('ボタンが押されました');
},[])
```
useEffect（副作用）と同じように第一引数に関数、第二引数に依存配列。


## おわりに
実務で機能修正の時などになんとなく知っているという感じでした。反省し基礎を固めていきます。
WebGL で色々な表現に挑戦する - 時間経過による変化（概要）

## この記事の概要

[前回](https://qiita.com/xrxoxcxox/private/1e28e9b684dfa9f1f922)や[前々回](https://qiita.com/xrxoxcxox/items/1dbc2d7c9add19cb131f)の記事で、静的なグラフィック表現をいくつか実装しました。

今回は時間にあわせて見た目が変化するようにしてみます。

## ユニフォーム変数の使用

TypeScript 側から時間に関する変数を渡して、シェーダー側で受け取って変化を実現します。

また、アニメーションさせるために `requestAnimationFrame` を使用します。

```diff_typescript:main.ts
  // シェーダーの渡すデータの設定
  const positionAttributeLocation = gl.getAttribLocation(
    shaderProgram,
    "aPosition"
  );
  gl.enableVertexAttribArray(positionAttributeLocation);
  gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

+ const timeUniformLocation = gl.getUniformLocation(shaderProgram, "uTime");

  // 描画の実行
- function drawScene() {
+ function drawScene(time: number) {
+   const currentTime = time * 0.001;
+   gl.uniform1f(timeUniformLocation, currentTime);
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+   requestAnimationFrame(drawScene);
  }

  // ウィンドウサイズに合わせてcanvasのサイズを変更する
  function resizeCanvasToDisplaySize() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    gl.viewport(0, 0, canvas.width, canvas.height);
-   drawScene();
+   drawScene(0.0);
  }
```

次にシェーダーで受け取ります。
ハイライトしている箇所で時間を扱い、見た目を変化させています。

```diff_glsl:plane.frag
  precision mediump float;

+ uniform float uTime;

  out vec4 outColor;

  void main() {
+   float red = sin(uTime * 0.5) + 0.5;
+   float green = cos(uTime * 0.7) + 0.5;
+   float blue = sin(uTime * 1.3) + 0.5;

    outColor = vec4(red, green, blue, 1.0);
  }
```

ただのベタ塗りですが、時間経過にあわせて変化するようになりました。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/62c59ae5-a0be-ea24-079f-5dc44cf35c3b.gif)

## 最後に

ここにグラデーションやノイズをあわせて行こうと思ったのですが、一旦分割します。
次回の記事で、静的に表現していたものに時間経過を組み合わせていきます。

https://qiita.com/xrxoxcxox/items/7e21802bab3ab6f11614
ハッシュとは何か

# ハッシュとは
### ハッシュ
ハッシュはキーと値の組み合わせでデータを管理するオブジェクトのことです。
ハッシュを作成する場合は以下のような構文を使います。
```.bash
#空のハッシュを作る
{}
#キーと値の組み合わせを３つ格納するハッシュ
{ 'キー1' => 値１, 'キー2' =>値２ , 'キー3' =>値３ }
```
以下は国ごとの通貨の単位を格納したハッシュを作成する例です。
```.rb
{ 'japan' => 'yen', 'us' => 'dollar', 'india' => 'ruppe' }
```
ハッシュは、キーと値のペアを波カッコで囲んで表記します。キーと値のペアを持たない波カッコの組{}は空のハッシュです。

ここで重要なのはハッシュの波括弧がブロックの波括弧とは別という点です。

ハッシュは配列と似ているが、一つ重要な違いとして**ハッシュでは要素の並び順が保証されない**という点があります。**要素の順序が重要である場合は、配列を使う必要があります。**

ではどのような時にハッシュを使うのか。それは**データを効率的に検索する必要がある場合や、名前でアクセスする必要がある場合**
または　**データにラベル（キー）が必要で、それぞれのデータが何を表しているかを示したい場合**です。
デイリースクラムの改善トライでよかったこと

本投稿はMIXI DEVELOPERS Advent Calendar 2023 18日目の記事です。

https://qiita.com/advent-calendar/2023/mixi

---

この記事ではスクラムイベントの１つの「デイリースクラム」の改善で良かったトライを共有します。

## デイリースクラムとは

いまのチームはスクラム体制を採用しています。スクラムのイベントの一つとしてデイリースクラムがあります。
スクラムガイドによるとデイリースクラムは以下のように紹介されています

> デイリースクラムの⽬的は、計画された今後の作業を調整しながら、スプリントゴールに対す
> る進捗を検査し、必要に応じてスプリントバックログを適応させること
> :
> デイリースクラムは、コミュニケーションを改善し、障害物を特定し、迅速な意思決定を促進
> する。その結果、他の会議を不要にする。

デイリースクラムは進捗報告というように誤解されがちですが、重要なポイントは「検査(障害の特定)」「コミュニケーションの改善」であると思っています。

## デイリースクラムで抱えていた課題

今のチームは7, 8人ですがヘルプの方の参加などがある時期で多いときは11人などの参加人数になることがありました。エンジニアに加えてデザイナー、QAなど異なる領域のメンバーがいます。

そんなチームで直面していた課題は **「報告の時間が足りない」**,**「障害の検査ができない」** の２点でした。
当初は時間がないから検査ができていないと考えていましたが、この２つは別物でした。
本記事ではチームで相談しながら改善していった中でよかったアイデアを共有します。

## 時間節約のための改善アイデア

# デイリースクラムで事前に記入させる

朝集まった段階でいきなり順番に話していくと以下のような問題がありました。
- 準備していないので報告や問題がまとまらない
- 話が展開されやすく長話になってしまう


そこで事前に内容を記入させることにより、全体の見通しを立てることができました。
かつNotion ではコメントによるテキストコミュニケーションが可能なので非同期で事前や事後にコミュニケーションを取ることもできます。一方で、日報などもチームで書かなければならないため、これが記入のコストとなりました。

記入する内容は一般的な項目で以下です。

> - 昨日やったこと
> - 今日やること
> - 困っていることや共有事項

この方法を導入した当時はデイリースクラムの平均所要時間が15分オーバーから約12,3分に変わりました。


# デイリースクラムテンプレートを作る

初めての人がジョインしてもわかるようにという点と誰でも再現性ある進行ができるようにテンプレートを用意しました。
notion を利用しているのですがワンクリックでコピーができそちらを利用しています。便利です。

![あ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262578/5b120840-4d98-4b8d-ba90-4f068f9c5b07.jpeg)


また進行は以下のようになっています

- 順番に進捗共有
  - 昨日やったこと
  - 今日やったこと
  - 困り事や共有事項
- 共有事項


## 検査ができないことへの改善アイデア

### スクラムで「検査」することを意識付ける

シンプルなアクションです。
「間に合わなそうならアラートを上げましょう。」と共通認識を持ってもらうことです。
話し合いの中で進捗報告だけで終わってしまうときに、スクラムマスターやメンバーが、「結局順調なのか？」「間に合うのか？」などのコミュニケーションを積み重ねることで徐々に意共通意識がついていったと思います。

### デイリースクラムの中で進行のヤバさをポーカーする

これは最近の取り組みなのですが、タスクの見積もりのプランニングポーカーとは別に「ゴールに向けて、進行が今どれくらいやばいのか」の共通認識を取るポーカーです。

QAやデザインなど、様々なポジションの人とスクラムに取り組んでいると、進行に対する認識の非対称性が生じます。それを定量的に判断する取り組みとして有効でした。

1を「このままだとゴール(リリース)できない」
5を「余裕をもってゴール(リリース)できそう」といったように設定して５段階で数次を一斉に出し合う取り組みです。チームでは「やばポーカー」と言われています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262578/ad01aa7a-eeb2-2257-ce26-f12567619d02.png)



# まとめ

現在のチームではこのようにしていくつかの改善をトライしていき問題を解消していきました。

スクラム体制の価値の１つには「チームとして強くなること」があると思います。チーム全体で意識を持って改善していくという姿勢を持つことが大きな価値だと思っています。
まだまだ課題はありますが、チームで認識してトライしていくことを大切にしていきたいと思いました。

# 参考資料

https://qiita.com/getty104/items/35ccb10ce660e7487ef8

https://www.ryuzee.com/faq/0027

- [スクラムガイド2020](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)
単体テストもlintを通そう

## はじめに

こんにちは！
株式会社HRBrainでエンジニアをしているZamaです。
この記事はHRBrain Advent Calendar 2023 カレンダー2の19日目の記事です。

https://qiita.com/advent-calendar/2023/hrbrain

## 前提

HRBrainでは

- Goを用いてバックエンドの開発を行っており、
- lintには[golangci-lint](https://github.com/golangci/golangci-lint)が使われ、
- 単体テストのassertionには[testify](https://github.com/stretchr/testify)が使われることが多いです。

## 単体テストがlintの対象でなかった

先日`golangci-lint`の設定ファイル（`.golangci.yaml`）を覗くことがあり、そこで`tests: false`という記述を見つけました。

何だこれ？と確認してみると、

```
# Include test files or not.
# Default: true
```

とのことで、単体テストがlintの対象になっていなかったことが分かりました。

たしかに思い返すと単体テストの記述についてlintで指摘された覚えがなく、このためだったのかと納得するとともに、じゃあ`true`にしてみようぜとなるのがエンジニア。

見事に**真っ赤**になりました。
golangci-lint様がお怒りです😡

## testifylintとの出会い

これはよろしくないと指摘を確認していくと、`require-error`という見慣れない指摘がありました。

エラーが必要？何かエラーハンドリングの間違いかな？とググってみると[testifylint](https://github.com/Antonboom/testifylint)というGitHubのレポジトリが出てきました。

そして[このような記述](https://github.com/Antonboom/testifylint#require-error)が...

![スクリーンショット 2023-12-14 14.25.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103036/5b7b4dcb-4c5f-3e09-787d-3295d1122023.png)

どうやら`testify`のスマートな使い方を教えてくれているようです。
下記はたしかにそういうassertionを簡単に書けたらと思っていました。

> testify/require allows to stop test execution when a test fails.

これはすてきなものを見つけたぞとREADMEを読んでいくと、[Problem statement](https://github.com/Antonboom/testifylint#problem-statement)というセクションに次のような記述がありました。

> testify is the most popular Golang testing framework in recent years. But it has a terrible ambiguous API in places, and **the purpose of this linter is to protect you from annoying mistakes**.

激しく同意です。

この`testifylint`が[golangci-lintのgo.mod](https://github.com/golangci/golangci-lint/blob/master/go.mod)に含まれており、lint時に実行されていたようです。

## チェック項目

この`testifylint`にはv1.0.2の時点で[14個のチェック項目](https://github.com/Antonboom/testifylint#checkers)があります。

- bool-compare
- compares
- empty
- error-is-as
- error-nil
- expected-actual
- float-compare
- go-require
- len
- nil-compare
- require-error
- suite-dont-use-pkg
- suite-extra-assert-call
- suite-thelper

上述の`require-error`の他に助かりそうなものとしては

**compares**

![スクリーンショット 2023-12-14 15.25.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103036/6064e495-0fd2-5611-b5cf-52edb68b1de6.png)

**empty**

![スクリーンショット 2023-12-14 15.25.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103036/4b0db29c-50b5-6f39-6bee-535d4c420b8c.png)

**expected-actual**

![スクリーンショット 2023-12-14 15.26.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103036/d028f9e0-5a94-5bd8-aa41-b3b11da68e25.png)

などがあります。

この`testifylint`さんの力を借りて、単体テストを今後きれいにしていこうと思います！

## まとめ

単体テストのファイルもlintの対象にしましょう。
lintによってはテストライブラリーの上手な使い方を教えてくれます。

単体テストはとても大事ですが、実際のコードを書いている時間と同じくらい、場合によってはそれ以上の時間を要することがよくあります。
それだけ時間をかけて書いたものなので、lintでさらに磨きをかけてPUSHしてやりましょう！

まあ、もうAIさんが色々いい感じに書いてくれる時代ではありますが...

## We are hiring!

株式会社HRBrainでは、Power to the peopleを合言葉に多種多様な人事課題を解決するプロダクトを開発・運営しています。
日本の労働環境を良くしてやるぜ！みんなが元気に活躍できる社会にしてやるぜ！
そんな熱い気持ちを持った方、一緒に働きませんか？
皆様のご応募をお待ちしております！

https://www.hrbrain.co.jp/recruit
MariaDBでオブジェクト（テーブルやカラムなど）のコメントだけを変更

# データベース

そもそもデータベースに対してコメントを付けることができません。

# テーブル

```sql:テーブルのコメント変更SQL例
ALTER TABLE `t_1`
COMMENT='テーブルコメント更新だよ'
```

# カラム

```sql:カラムのコメント変更SQL例
ALTER TABLE `t_1`
MODIFY COLUMN `id` INT(11) NOT NULL DEFAULT 1 COMMENT 'カラムコメント更新だよ' 
```

## MODIFY使用により記述を減らせる

```CHANGE``` ではなく ```MODIFY``` を使うことで、カラム名の記述を1回で済ますことができます。

## 省略による意図しない変更に注意

下記SQLでコメントを変更することもできます。

```sql:『NULL許可かどうか』『デフォルト値』と省略したSQL例
ALTER TABLE `t_1`
MODIFY COLUMN `id` INT(11) COMMENT 'カラム' 
```

しかし『NULL許可かどうか』『デフォルト値』を省略すると、カラムの設定が『NULL許可かつデフォルトNULL』に変わってしまうので注意。

# 参考サイトさん

https://qiita.com/miriwo/items/ae4672e6125a7dfb0f95

# バージョン

Microsoft Windows [Version 10.0.19045.3803]
10.5.4-MariaDB

TODO:ビュー、トリガー、ストアドプロシージャー、ストアドファンクション、イベント、について調べてまとめる。
そもそもコメントが付けられるのかどうかなど。
ブランチ戦略をトランクベース開発に切り替えた話

これは[Hubble Advent Calendar 2023](https://qiita.com/advent-calendar/2023/hubble)の12日目[^1]の記事です。

## はじめに

株式会社Hubbleのフロントエンドを担当している @KOHETs です。

Hubbleでは、 Gitflow を利用して開発を行っていましたが、2020年頃からトランクベース開発に切り替えました[^2]。今回はトランクベース開発に切り替えたことで、開発チームの考え方や文化が変わった点について紹介したいと思います。

## トランクベース開発ってなに？

トランクベース開発とは、すごくざっくりいうと、プルリクエストの単位をなるべく小さくして、トランク（mainブランチ）に素早く取り込むことで高速で開発サイクルを回す手法です。

詳しく説明するとそれだけで長くなってしまうので、詳しく知りたい方、メリットやデメリットを知りたい方は[こちら](https://www.atlassian.com/ja/continuous-delivery/continuous-integration/trunk-based-development)で詳しく解説されているのでぜひ読んでみてください。


## 何を解決したかったか


それなりに前の話なのでぼやっとしているんですが、確か当時困っていたことが2つありました。

- 変更点が多すぎることによるレビュー負担
- コンフリクトの解消が果てしない

これらの問題は Gitflow が機能開発が完了するまで一つのブランチで作業することを許容していることで、ブランチの生存期間が長くなることに起因していました。
そこで、思い切ってトランクベース開発に切り替えて、半強制的にブランチの生存期間を短くすることで、これらの問題を解決しようと考えました。

## トランクベース開発の壁

Hubbleがトランクベース開発の導入で障壁になったのは、「機能フラグの導入」と「リリースフローとの兼ね合い」でした。
ブランチ戦略を切り替えたのはフロントエンドのみで、リリースフローも変更する予定はなかったので、このあたりをうまく調整する必要がありました。

### 機能フラグの導入

トランクベース開発では、リリース前の機能も積極的にトランクに取り込むため、本番環境で開発中の機能が流出しないように制御する必要がありました。

実際に機能フラグを導入するか考えましたが、機能毎にフラグを制御する必要コストはそれなりにあるので、結局導入は見送りました。

代わりに、環境変数にフラグを持ち、ローカル環境と開発環境のみフラグがONになり、検証環境と本番環境ではOFFになっているHubble内では「InProgressフラグ」と呼ばれるシンプルなフラグを導入しました。

### リリースフローとの兼ね合い

トランクベース開発は、テストを自動化することで品質を保証し、トランクに取り込んだものをすぐに本番環境へ反映するようなフローを取ることが出来ます。

一方Hubbleは、元々Gitflowを利用していたのも有り、 開発環境、検証環境、本番環境それぞれに対応するブランチを用意して、それぞれのタイミングで反映するようにしていました。

これらをうまく合わせるのは難しいと思ったので、リリースは従来どおり、適切なタイミングでリリースブランチを作成して行うことにしました。

## チームに起きた変化

トランクベース開発に切り替えてもう3年以上経ちますが、当時困っていたことは今は殆ど起こらなくなったので、切り替えて良かったと思っています。

### プルリクエストの単位は小さく

問題だったレビュー負荷が高いプルリクエストは最近は殆どありません。作業開始からトランクへの取り込みまでは長くても数日で終わり、レビューは殆どがその日の中に終わります。

レビューの負担が小さくなったことで、レビューの質も上がり、開発サイクルも大幅の短縮に成功していると思います。


### 気軽に使える機能フラグ

機能フラグは高度な制御をする上では必須です。しかしHubbleでは環境毎の出し分けさえできればよかったので今でもInProgressフラグのみで運用しています。

機能フラグと比べて圧倒的に気軽に利用できるため、開発者の心理的な負担も少なく、機能フラグの導入を見送ったことは正解だったと思っています。

## まとめ

トランクベース開発の導入によって、辛かった作業から開放され、開発サイクルも大幅に短縮できたのは大きな収穫でした。
また、トランクベース開発のメリットをすべて取り込もうとせず、適切な距離感で取り込んだことも良かったです。

もちろん今後は機能フラグの導入や本番環境への即時反映なども検討していきたいですが、それは未来の僕が頑張ってくれることに期待しています。

明日は @nohata さんです！

[^1]: 平日のみの投稿なので18日ですが、12日目の記事としています。
[^2]: トランクベースに切り替えたのはフロントエンドのレポジトリのみです。
IAMロールとサービスロールの違い

IAMロールとサービスロールの違いが、わかりにくかったので、整理してみました。
違いを理解することで、適切なセキュリティ設計を行う事が出来るでしょう。

ポイント
--
**最小権限の原則の適用**
__IAMロール__ は、 特定のユーザーやアプリケーションに一時的な権限を与えるため、必要最小限の権限を付与できる。「最小権限の原則」を実現し、セキュリティを向上させる。
__サービスロール__ は、信頼ポリシーが設定されており、必要なアクセス権のみを持つため、不要な権限を削減できる。

**セキュリティの向上**
__IAMロール__ は、ユーザーやアプリケーションに対するアクセスを一時的に制御するため、不要な権限が永続的に残るリスクを軽減する。
__サービスロール__ は、AWSサービスが他のサービスへのアクセスに使用するための信頼性が確保された一意の資格情報が使用される。



IAMロールとサービスロールの違い
--


| 項目                   | IAM ロール                                        | サービスロール                                        |
|------------------------|---------------------------------------------------|-------------------------------------------------------|
| 用途                   | AWS リソースへのアクセス権を付与するためのロール   | AWS サービス（EC2、Lambda など）が他のサービスにアクセスするためのロール   |
| 主体                   | ユーザーアカウント、他のロール、AWS サービス       | AWS サービス自体                                      |
| 割り当て先                 | ユーザーまたはグループ | サービス   |
| アクセス許可ポリシー   | 一般的なアクセス許可ポリシー、カスタムポリシーなど  | サービスによって事前に定義されたポリシーを使用           |
| 外部から信頼されるエンティティ | 他の AWS アカウントや外部 ID を信頼することができる | 信頼されるエンティティは AWS サービスのみ               |
| セッションの期間         | 一時的なセッションが可能                           | 固定された期間または無期限                             |
| フェデレーション         | クロスアカウントへのアクセス、一時的なセッションに使用可能 | サービスが他のサービスへのアクセスに使用               |
Verilogのassignステートメントとは

assignは、通常、`assign`はワイヤー（ネット型）に使用。
例えば、論理ゲートを使用して2つの入力信号aとbの論理積を計算してcに格納する場合、assignが必要です。

assignを使用するケース：
```verilog
wire a, b, c;
assign c = a & b; // cにaとbの論理積を代入
```

assignを使用しないケース：

```verilog
module ModuleA(output wire c);
    // ここでcの計算を行う必要はない
endmodule

module ModuleB(input a, input b, output c);
    // ModuleA内で計算されたcを利用
    ModuleA u1 (.c(c));
endmodule
```

### 間違えたポイント
assign A = B　は連結という解説をよく見るが、実際は右辺を左辺に代入という意味である。
Seleniumでの明示的待機と暗黙的待機の使い分け



## はじめに
Seleniumでの明示的待機と暗黙的待機の使い分けに関しての備忘録です。
初心者です😅
間違えてる部分多々あると思います。
もし見つけた場合、ツッコミいただけると助かります🙇
<br>
## 🦁<INS>**結論**</INS>🦁

# 基本は「明示的待機」を使う

:::note info
明示的待機と暗黙的待機の違い
* 「明示的待機」は特定の条件の成立を待つ。
* 「暗黙的待機 」はすべての要素検索に一律の待機時間を適用して待つ。
:::  
***


:::note warn
明示的待機を使う時
* ページが表示完了するのを待機
* ポップアップやモーダルウィンドウの待機
* ファイルダウンロード完了の待機
* 特定の状態までの待機(例:チェックボックスがチェックされる、ドロップダウンリストで特定のオプションが選択されるなど)
:::  


***

:::note alert
注意点
* 明示的待機と暗黙的待機を同時に使用すると、予期しないタイムアウトやパフォーマンスの問題が発生する可能性がある。
* 明示的待機はより柔軟で信頼性が高いため、特定の条件を待つ場合に推奨されてる。
* 暗黙的待機は、すべての要素検索に一律の待機時間を適用するため、使い方には慎重である必要がある
:::  

***
## 基本文法
```
WebDriverWait(driver, 10).until(
    EC.funciton_kinds((By.ID, 'myElementId'))
)
```
## WebDriverWait(driver, 10)
引数にある「driver」（指定したブラウザ）を最大10秒間待つように設定
***

## .until(

指定した(引数)条件が真（True）になるまで、WebDriver（ブラウザ）が待機するように指示するメソッド
***

## EC.funciton_kinds
待機する条件を指定する（funciton_kindは例）
ここに下記の関数を入れることで指定できる。
***

## ((By.ID, 'myElementId'))
指定する値など
***

## expected_conditions モジュール内の関数の種類
* presence_of_element_located:<br>指定する要素のIDやクラス名などに一致する要素がDOM上に存在まで待機。
```python:sample.py
# IDが'myElementId'の要素がDOMに存在するのを待機
WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, 'myElementId'))
)
```
***

* element_to_be_clickable:<br>指定された要素がクリック可能な状態になるまで待機。これは、要素が表示され、有効な状態（disabled状態でない）であることを意味します。
```python:sample.py
# IDが'myButton'のボタンがクリック可能になるのを待機
WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, 'myButton'))
)
```
***

* visibility_of_element_located:<br>指定された要素がDOMに存在し、かつ画面上に見える状態になるまで待機。
```python:sample.py
# IDが'myElementId'の要素が表示されるのを待機
WebDriverWait(driver, 10).until(
    EC.visibility_of_element_located((By.ID, 'myElementId'))
)
```
***

* invisibility_of_element_located:<br>指定された要素が画面上から消える（見えなくなる）までを待機。要素がDOMから削除されるか、非表示になることが条件。
```python:sample.py
# IDが'myElementId'の要素が表示されるのを待機
WebDriverWait(driver, 10).until(
    EC.invisibility_of_element_located((By.ID, 'myElementId'))
)
```
***

* title_contains:<br>ブラウザのタイトルが指定された文字列を含むまで待機します。この条件は、ページが期待されるタイトルを表示するまで待機するのに使われる。
```python:sample.py
# ページのタイトルに特定の文字列が含まれるのを待機
WebDriverWait(driver, 10).until(
    EC.title_contains('expectedTitle')
)
```
***

* text_to_be_present_in_element:<br>指定された要素に特定のテキストが含まれるまで待機。
```python:sample.py
WebDriverWait(driver, 10).until(
    EC.text_to_be_present_in_element((By.ID, "myElementId"), "期待するテキスト")
)
```
***

* text_to_be_present_in_element_value:<br>指定された要素のvalue属性に特定のテキストが含まれるまで待機。
```python:sample.py
WebDriverWait(driver, 10).until(
    EC.text_to_be_present_in_element_value((By.ID, "myInputElementId"), "期待するテキスト")
)
```
***

* element_to_be_selected:<br>指定された要素が選択されている（例えば、チェックボックスがチェックされている）まで待機。
```python:sample.py
WebDriverWait(driver, 10).until(
    EC.element_to_be_selected((By.ID, "myCheckboxId"))
)
```
***


## 参考にしたサイト📗
[]()
Rustacean（ラステイシャン）になりたい。ほんの少しメモリの話。

Rustには変数の所有権、参照、借用という機能があります。
メモリについてボヤッとでもいいので理解しているほうが、これを理解しやすいと思い、メモリの話を少します。

プログラムを動かすには、4つの領域が必要です。
- プログラム領域： プログラムを置く場所。
- 静的領域： グローバル変数などの静的変数を置く場所。
- スタック領域： 固定長なローカル変数の値を置く場所。
- ヒープ領域： 可変長なローカル変数の値を置く場所。

今回は、このうち変数と関係があるスタック領域とヒープ領域の話をしたいと思います。

## メモリ領域は番地管理されている

メモリ領域は、図のように番地で管理されています。
メモリの住所のようなものです。
プログラムは、この番地を使ってメモリ上のデータにアクセスします。

図は簡略して00 - FF 番地のメモリ領域としています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/ead4930c-e643-7236-e4c8-bf7c84c0f510.png)


## スタック領域

図のように、変数を定義するとスタック領域に変数の情報が格納されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/48edf4ec-e2a0-b3d9-27d8-a0bf64766afe.png)
<span style="font-size:80%;">- コードと突き合わせたイメージ図 -</span>

しかし、スタック領域にはスカラー型（プリミティブ型）のように、**データサイズが固定な型**の値しか格納できません。

では、可変長文字列などの変数の値は、どこに格納されるのか？

それは、ヒープ領域に格納されます。

## ヒープ領域

可変長文字列などの値はヒープ領域に格納されます。
そして、スタック領域は、データ格納されているヒープ領域のメモリ番地（メモリアドレス）だけが格納されます。
メモリ番地（メモリアドレス）の値は固定長なのでスタック領域に格納できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/d32c0f5d-95de-8261-4468-5f7131cd802c.png)
:warning:図はあくまでもイメージです。

## スタック領域、ヒープ領域は有限

大量のデータを処理していて
**StackOverflow**エラー、**OutOfMemory**エラーを発生させてしまったことはないでしょうか。

### 検証①
StackOverflowエラーはスタック領域がいっぱいになった時に発生するエラーです。
たくさんの変数を宣言した場合や、大きいサイズの固定長の値を格納する変数を定義すると発生させてしまいます。

関数を再帰的に実行して、a2変数を宣言し続けてみた。

```rust
fn main() {
    let a = 1;
    do_something(a);
}

fn do_something(a: i32) {
    let a2 = a + 1;
    
    if a2 > 1 {
        do_something(a2);
    }
}
```
StackOverFlowのエラーが発生しました。

```console
thread 'main' has overflowed its stack
```


### 検証②
OutOfMemoryエラーはヒープ領域がいっぱいになった時に発生するエラーです。
大きいサイズのファイルの一括読み込みや、データベースから一括で大量データを読み込んだ時に発生させてしまいます。

関数を再帰的に実行して、ヒープ領域を消費しみた。

```rust
fn main() {
    let a = 1;
    do_something(a);
}

fn do_something(a: i32) {
    let mut vec:Vec<u8> = vec![];
    vec.reserve(1024 * 1024 * 1024);
    // または
    // let mut s = String::with_capacity(1024 * 1024 * 1024);

    let a2 = a + 1;

    if a2 > 1 {
        do_something(a2);
    }
}
```

OutOfMemoryとう表現ではないが、メモリを確保出来なかったエラーが発生しました。
```console
memory allocation of 1073741824 bytes failed
```
Gemini Pro APIを使ってみる

Googleが出してきた[Gemini Pro API](https://ai.google.dev/)が気になったのでPythonでAPIを使ってみました。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f31343736382f30643536616234392d643034372d383036622d656563312d3064663135633365666361372e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14768/5438425c-4306-4336-fe51-3f26c519302b.png)


# サンプル

https://gemini-st.streamlit.app/

![スクリーンショット 2023-12-14 15.12.58.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14768/35f393b9-41fe-037b-e5ca-0fc180de0845.jpeg)

適当な車の画像を入れただけなのに、やたら詳しいですね...（全て正しいかはわからないけど）

※APIキーが必要です

↑無料プランの範囲内だとは思うのですが怖かったので、個別のキーを入れる方式にしました。

# 前準備

## APIキーの取得

APIキーを取得します。

https://ai.google.dev/tutorials/setup?hl=ja

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

```bash
pip install google.generativeai
```
シンプル！

# コード解説

Streamlitを使ったサンプルはこちら

https://github.com/bellx2/gemini-streamlit

## APIキーの設定
```python
genai.configure(api_key=API_KEY)
```  

## モデルの読み込み、送信＆レスポンス取得

モデルはtextだけのものと画像を送信可能な２つに分かれています。

### gemini-pro

入力：テキスト

```python
model = genai.GenerativeModel('gemini-pro')
response = model.generate_content([text])
```

### gemini-pro-vision

入力：テキスト、画像

```python
model = genai.GenerativeModel('gemini-pro-vision')
response = model.generate_content([text,image])
```

画像はPIL.Image


## 結果

```python
print(response.text)
```

# 価格

リミットは60QPMで無償。Tokenでなく文字単位なので、日本語は有利で課金されてもGPT-3.5よりかなり安く使える感じとの事。

https://ai.google.dev/pricing

# むにゃむにゃ

まだあまり深くまで掘っていないのですが、とりあえずサクッとできてしまったので、公開します。
【Rails】入社前にやった方が良かった教材まとめ 【React】

## はじめに
現在、現場でReactとRuby on Railsを使用して開発しています。

その上で入社前に自分で読んでもらいたい教材を
紹介していきます！


## [プロを目指す人のためのRuby入門\[改訂2版\] 言語仕様からテスト駆動開発・デバッグ技法まで](https://www.amazon.co.jp/dp/4297124378)
- Rubyを使う方、全員におすすめしたい本
- 呪文のような構文もこれを読めば理解できるようになる(はず)
- 初版を買わないように注意してください！


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/d32239a4-13be-2e96-ecc4-81aaef6d0ac5.jpeg" width="60%">

>本書は、プログラミング言語Rubyの言語仕様や開発の現場で役立つRubyの知識を説明した本です。豊富なサンプルコードで文法を学び、例題でプログラミングの流れを体験できます。第1版(2017年11月発行)は、初心者の目線にたった丁寧な解説が好評で多くのRuby初学者に愛読され、いまやRuby入門書の定番とも言える存在です。2020年末のRuby 3.0のリリースに伴い、全章にわたって記述内容を見直し、Ruby 3.0までの変更点や新機能に合わせて加筆・修正を行いました。また、第1版にて読者から「難しい、わかりづらい」という声の多かったトピックの説明を改善するなど、より初心者に親切な内容に刷新しています。

## [Ruby on Rails チュートリアル](https://railstutorial.jp/)
言わずもがなです、Railsを学ぶ際に大体の人がこれを読むと思います。
Rails独自の知識だけではなく

- Webサービス開発での基礎知識
- Rubyにおけるクラスについて

等言語の知識や幅広い分野までインプットすることができます。



## [ウェブ開発 React JS 【2023年最新】React\(v18\)完全入門ガイド｜Hooks、Next\.js、Redux、TypeScript](https://www.udemy.com/course/react-complete-guide/)
この教材を見れば、Reactの主要な構文の殆どを理解することができますし
仕組み自体も図で解説されて分かりやすいです。

さらに、TypeScriptや関数型プログラミングについても体系的に学ぶことが出来ます。

[![スクリーンショット 2023-12-14 12.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/a6d9497c-8706-6630-a1a7-28efeebcda61.png)](https://www.udemy.com/course/react-complete-guide/)


## [Everyday Rails \- RSpecによるRailsテスト入門](https://leanpub.com/everydayrailsrspec-jp)
体系的にRspecを理解することができます。
最新バージョンに合わせて、更新されているので助かります。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/2391527f-5777-a982-3802-b1c502741f8d.png" width="60%">

>本書「Everyday Rails - RSpecによるRailsテスト入門」では、どのようにして私がそうしたテクニックを身につけたのか、そして、どのようにしてコードの信頼性を上げ、ブラウザ上で延々とテストしなくて済むようにしたきたのかをみなさんに説明します。
QlikSenseで3つ以上のデータをJOINしたい

QlikSenseで3つ以上のデータをLEFT JOINでつないでいこうとしたら、全然うまくいかなかったので、やり方をメモします。
※これよりもっといい方法があるのかもしれませんが、自分にはこの方法でしかうまくできませんでした。

# 2個のテーブルをJOINする時の書き方

Table1
| COL | 
|:-:|
| 123 | 
| 456 |  

Table2
| COL |NO |
|:-:|:-:|
| 123  | 123  |
 
```QlikSense:2つのテーブルの時の一般的なLEFT JOINの書き方
QLIK_TABLE_1:
LOAD
    COL
FROM 
    Table1;

LEFT JOIN(QLIK_TABLE_1)　//()部分は書かなかった場合、直前のテーブルにJOINされます。書いた方が無難。
LOAD
    COL,
    NO
FROM
    Table2;
```

結果はこんな感じになります。
QLIK_TABLE_1　という名前の下記のようなテーブルができます。
| COL |NO |
|:-:|:-:|
| 123  | 123  |
| 456  | -  |

# 3個以上で同じように書いた場合

下記のように3つのテーブルがある場合。


Table1
| COL | 
|:-:|
| 123 | 
| 456 |  

Table2
| COL |NO |
|:-:|:-:|
| 123  | 123  |

Table3
| COL |NO |
|:-:|:-:|
| 456  | 456  |

欲しい結果
| COL |NO |
|:-:|:-:|
| 123  | 123  |
| 456  | 456  |


```QlikSense:失敗する書き方
QLIK_TABLE_1:
LOAD
    COL
FROM 
    Table1;

LEFT JOIN(QLIK_TABLE_1)　//()部分は書かなかった場合、直前のテーブルにJOINされます。書いた方が無難。
LOAD
    COL,
    NO
FROM
    Table2;

LEFT JOIN(QLIK_TABLE_1)　
LOAD
    COL,
    NO
FROM
    Table3;
    
```

##### 出てくる結果は下記の通り
| COL |NO |
|:-:|:-:|
| 123  | 123  |
| 456  | -  |

なんで・・・？
いろいろ順番入れ替えて試してみたのですが、
どうやら、一つ目のLEFT JOIN以降は無視されてるのか、思ったようにJOINされませんでした。

# 回避する方法

```QlikSense:一応動く書き方
QLIK_TABLE_1:
LOAD
    COL
FROM 
    Table1;

LEFT JOIN(QLIK_TABLE_1)　//()部分は書かなかった場合、直前のテーブルにJOINされます。書いた方が無難。
LOAD
    COL,
    NO
FROM
    Table2;

NoConcatenate
OTHER_TABLE_1 :
LOAD
  *
RESIDENT
  QLIK_TABLE_1;

DROP TABLES QLIK_TABLE_1;

LEFT JOIN(OTHER_TABLE_1)　
LOAD
    COL,
    NO AS NO_3
FROM
    Table3;
    
NoConcatenate
OTHER_TABLE_2 :
LOAD
  COL,
  IF(NO>0,NO,0) + IF(NO_3 > 0 ,NO_3,0) AS NO
RESIDENT
  OTHER_TABLE_1;

DROP TABLES OTHER_TABLE_1;
```

これをすると、無事下記のような結果がでてきました。
OTHER_TABLE_2
| COL |NO |
|:-:|:-:|
| 123  | 123  |
| 456  | 456  |

なんでこんなことしないといけないのかはさっぱりわかりませんが。。。
JOINを3個以上したくてトラブってる方の役に立つと嬉しいです。

もっといい書き方があれば、ご指摘いただけると助かります。

※今回の例では、TABLE2とTABLE3のカラムが同じなので、
先にConcatenateしてしまって、2つのテーブルっぽくして処理することもできます。
が、TABLE3のカラム名がNO3、とか別のカラムだったとしても、
2個目以降のLEFT JOINは無視されて、値は出てきません。
pyzbarが無事にzbarを見つけてくれるように頑張った話

pythonでQRコードを読み取ってごにょにょするアプリの開発をした時に
ライブラリが見つけられないエラーが出て困ったので共有します。

**zbarを見つける必要がないエンジニアは今すぐ立ち去った方がいいです。**


## QRコードを読み取ってくれるライブラリ　pyzbar
pythonでQRコードを読み取るライブラリにpyzbarといったライブラリがあります。
こちらをインストールさせQRコードを読み取ろうとすると。以下のようなエラーが出てくる

```
ImportError: Unable to find zbar shared library
```
「へい！そこのお前！zbarが見つけられないぜ！」

調べてみるとpyzbarはZbarがないと機能してくれないらしい。
ふーん、おもしれーライブラリ

## 調べてみた

pyzbarのドキュメントを見るとzbarはhomebrew経由でインストールさせろって
普通に書いてありました。
話はそれるんですけど男の子って説明書読まずに玩具とかゲームとかしますよね。
なんなんすかねあれ。

言われた通りhomebrewでzbarをインストール
```
brew install zbar
```

## よっしこれでQRコード読めるぞ！ぐへへへ！
...と思っていた時期が僕にもありました
```
ImportError: Unable to find zbar shared library
```

## 問題点
結果的に言うとhomebrew君はApple Silicon版Macだとライブラリを保存させる場所がちょっと変わってるようです。
Apple Silicon君はいつも問題を起こすんです。

## 解決策
このissueで解決です。
https://github.com/NaturalHistoryMuseum/pyzbar/issues/37

```
$ mkdir ~/lib
$ ln -s $(brew --prefix zbar)/lib/libzbar.dylib ~/lib/libzbar.dylib
```
やってることは簡単です。
homebrew君がインストールしてくれたライブラリをzbarが参照できるように橋渡ししてくれるシンボリックリンクってやつを作ります。

このシンボリックリンクって奴が上手いこと参照先を変えてくれてzbarを見つけてくれるんですね。

## 再び襲いくる悪夢
無事にQRコードを読み取ることができました。これで世界は平和になったと安堵したいところでしたが、次の問題がおこりました。
pythonファイルを他のPCとかでも動かせるように[pyinstaller](https://www.naka-sys.okinawa/pyinstaller-exe/)で実行ファイル化し、それを他のPCで動作できるか確認をしたところ....

```
ImportError: Unable to find zbar shared library
```
ここまでくると実家に帰ったかのような安心感があります（？）

## 問題点と解決方法
もちろん渡した先でhomebrew経由でzbarをインストールすれば解決なのですが、今回想定しているユーザーは非エンジニアの方であり
homebrewをインストールして、そこからさらにzbarをインストールさせるにはちょっと難易度たかいんですよね。
（余談ですが同じプロジェクトメンバーがインテル版からApple Silicon版に移行システムを使ったmacでhomebrewを使うとアーキテクチャがintel版のままだったので環境構築に時間がかかってたのでhomebrewでインストールは避けたかった）

今回はzbarは事前にこちらが用意した物を使ってpyzbarが読み取れるように修正してあげる方針でいきました。

## ゴッド・シンボリックリンク
最初はpyzbarの参照先を変えられないか試行錯誤したんですが、何か無理そう（知ってる人いたら教えて欲しい）

そこでpyzbarの参照先自体は変えずに、シンボリックリンクを使って、事前に用意した
zbarライブラリに橋渡ししてあげればいいじゃん！と思った次第です。

そこで問題になるのがzbarライブラリをどこに保管するか？ですが
今回実行ファイル化したpythonアプリはelectronを使ってデスクトップアプリとして
使用する想定だったので、zbarライブラリはmacの
```Application Support/{applicationName}```の中に保管しました

そして上記保管先を参照するようなシンボリックリンクを以下コマンドで作成します
```
USERNAME=$(whoami)

mkdir -p ~/lib
ln -sf "/Users/$USERNAME/Library/Application Support/applicationName/libzbar.dylib" ~/lib/libzbar.dylib
```

## 「I'll find you」
これで無事にpyzbarがzbarを見つけてくれました。
本当はpyzbarの参照先を動的に変更したかったんですけどね....

## まとめ
今回初めてpythonとelectronを使ってデスクトップアプリを開発しましたが
Webアプリの知識でスラスラコード書けたので開発しやすかったです。

あと

シンボリックリンクは神
ネタがなかった話

https://qiita.com/advent-calendar/2023/kddi-tech
の14日目です。

この記事は、「ネタがない」ことについて考えた話です。

## その前に
「思考力」についてお話ししたいと思います。

思考力とは「考える力」のことです。
この力をあげることで、アイデアを出しやすくしたり、リスク回避できたり、コミュニケーションにも役に立ちます。

思考方法には様々な種類があり、
論理的に考える「ロジカルシンキング」や状況に対して、柔軟に対応していく「アジャイル思考」、テーマに対してどんどんアウトプットしていく「ゼロ秒思考」などがあります。

## 言い換え
では、「ネタがない」ことについて考えていきます。
いきなり「なぜネタがないのか」を考えると結論が一生出てこないと思ったので、言い換えをしてみました。

「話すことがない」
言い換えをしてみると、疑問が生まれました。
友人や知人、家族と話す際は、趣味や世間話、小さな出来事まで何かしら話している気がするので、「ネタがない」ことがあまりないように感じたためです。
そのため、ここで言うネタがないのは、記事に出来るようなネタがない。ということがわかりました。

先ほど、友人や知人、家族に対してとしましたが、全くの知らない人やあまり関わったことがない人に対してはどうか。
「話すことがない」のではなく、「何を話していいかわからない」の方がしっくりきました。
そう考えると「ネタがない」も「何の記事を書いていいかわからない」にも変換ができます。

## 振り返り
「何の記事を書いていいかわからない」に変換すると、実は「ネタがない」ことはないのではないか。というところに至りました。
そこで、なんでもいいから探せばあるという精神で、自分に関わることの振り返りを行いました。
本当は書き出して、1つ1つどうだったかを振り返る方がいいのかもしれませんが、時間もなかったので、自分にとって大きかったものをピックアップをしました。

- 研修：自分は今年4月に入社したのですが、縁あって4月から9月まで研修を受けていました。
- ロジカルシンキング練習帳：チャットやメール、人とのやりとりに対して上司からアドバイスをいただいた時に教えていただいた本です。
- 生活：睡眠習慣を変えた話です。

## 例え話
とりあえず、3つピックアップできたので、ひとつひとつに対してどんな話ができるかと浮かんだ内容に対して、否定をしてみました。
- 研修
学んだことについて→ 作ったものも中途半端だし、発表したなー
復習として、何かを作成してみる　→時間ない
- ロジカルシンキング練習帳
本を読んでやってみた　→繰り返しやるものなので本の内容を話すだけになってしまいそう
思考力について→いくつかあってわからない。
- 生活
睡眠習慣→ただ単に目覚まし増やしたとか、時間変えたとかの話だし、次の日休みの時には狂いまくっているので書けそうにない。

この中から、書けそうと思ったものを書くことにしました。
そこで選んだものが「思考力」の話です。

## 発想転換
何を書くか決まったはいいものの、テーマを何にしようかとまた考えました。
思考力の話をそのまま書いても良かったのですが、プラスでエピソードのようなものが必要かと思ったので、なかなかネタが思いつきませんでした。

……いっそ「ネタがない」ことについて書いたら良いのではないか？
となり、この記事が出来上がりました。

## おわりに
正直、記事に書いたように順序立てて考えたわけではないのですが、改めて考えることの大切さに気づくことができました。
人間関係や仕事でも考えることはたくさんあると思います。
複雑な組み立ては、繰り返しやっていかないと身につかないものもあるので、理解するためや、頭の整理のためにも、時間が取れるようであれば、一つ一つゆっくり考えてみるのもいいかもしれません。
また、興味があれば、様々な思考方法を試してみるのもありだと思います。


## 参考リンク
思考方法リスト
https://el.jibun.atmarkit.co.jp/nae2sho/2022/01/content.html

ロジカルシンキング練習帳
https://www.amazon.co.jp/%E3%83%AD%E3%82%B8%E3%82%AB%E3%83%AB%E3%83%BB%E3%82%B7%E3%83%B3%E3%82%AD%E3%83%B3%E3%82%B0%E7%B7%B4%E7%BF%92%E5%B8%B3-%E7%85%A7%E5%B1%8B-%E8%8F%AF%E5%AD%90/dp/4492533923/ref=sr_1_4?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2SXZSK9D4KAA1&keywords=%E3%83%AD%E3%82%B8%E3%82%AB%E3%83%AB%E3%82%B7%E3%83%B3%E3%82%AD%E3%83%B3%E3%82%B0%E7%B7%B4%E7%BF%92%E5%B8%B3&qid=1702524724&sprefix=%E3%83%AD%E3%82%B8%E3%82%AB%E3%83%AB%E3%82%B7%E3%83%B3%E3%82%AD%E3%83%B3%E3%82%B0%E7%B7%B4%E7%BF%92%E5%B8%B3%2Caps%2C147&sr=8-4
日本語プログラミング言語Mindのプログラミングの基本のキ

# はじめに
日本語プログラミング言語Mindのプログラミングの基本のキについて説明したいと思います。

# 対象読者
Mindのユーザー、またはほかの日本語プログラミング言語ユーザー

# Mindのプログラミングの基本のキ
Mindでは何をやりたいかを日本語の文章として発案定義し　(←メイン)
次に、それぞれの単語を予約された単語や事前につくった単語で○○とは○○すること。と定義していくスタイルです。

まず、下記のようにメインの内容をトップダウン的に決めちゃいます。
```mind
メインは
	体重と身長を入力し
	BMIを計算すること。
```

で、それぞれを更に深掘り（定義）していく訳です。
```mind:
体重と身長を入力とは
	「体重？(kg)」を、表示し、文字列入力し、数値変換し、捨て、体重に、入れ
	「身長？(ｍ)」を、表示し、文字列入力し、数値変換し、捨て、身長に、入れること。

BMI計算とは
	「ＢＭＩ＝」を、表示し
	 体重を、身長の、二乗で、割り、数値表示すること。
```

  最後に、変数を定義しますが、Mindはたぶんワンパスコンパイラなのでグローバル変数はメインの上に書きます。
```
体重は、変数。
身長は、変数。
```
# Mindプログラムソース
```mind:
体重は、変数。
身長は、変数。

二乗とは
	複写し、掛けること。

体重と身長を入力とは
	「体重？(kg)」を、表示し、文字列入力し、数値変換し、捨て、体重に、入れ
	「身長？(ｍ)」を、表示し、文字列入力し、数値変換し、捨て、身長に、入れる。

BMI計算とは
	「ＢＭＩ＝」を、表示し
	体重を、身長の、二乗で、割り、数値表示すること。

メインは
	体重と身長を入力し
	BMIを計算すること。
 ```
 
# 実行結果

```mind:
体重？(kg)100
身長？(ｍ)2
ＢＭＩ＝25
```

C言語のように最初に単語名を仮定義しておけばメインを上にもっていくこともできます。書き順としても結論を先にもっていくイメージですね。

# Mindプログラムソース（仮定義使用）

```mind:
体重は、変数。
身長は、変数。
二乗とは　　　　　　　仮定義。
体重と身長を入力とは　仮定義。
BMI計算とは　　　　　 仮定義。

メインは
	体重と身長を入力し
	BMIを計算すること。


二乗とは　本定義
	複写し、掛けること。

体重と身長を入力とは　本定義
	「体重？(kg)」を、表示し、文字列入力し、数値変換し、捨て、体重に、入れ
	「身長？(ｍ)」を、表示し、文字列入力し、数値変換し、捨て、身長に、入れる。

BMI計算とは　本定義
	「ＢＭＩ＝」を、表示し
	体重を、身長の、二乗で、割り、数値表示すること。

 ```

# おわりに
上記のＢＭＩ計算プログラムは日本語として通じると考えます。
ソースの可読性が高いことはとても重要ですが、これは即ち日本語として自然言語のように記述出来ることが案外重要なのではないかと思うわけです。
【Ruby on Rails】使えるコマンドチートシート＆VSCodeおすすめ拡張機能

# はじめに
こんにちは、エンジニア2年目の嶋田です。
まずは、この記事を開いていただきありがとうございます！


この記事は、株式会社スピードリンクジャパン Advent Calendar 2023 の14日目の記事です。

https://qiita.com/advent-calendar/2023/slj


# 目次

- [Railsの主要コマンド](#railsの主要コマンド)
    - [アプリケーションのセットアップ](#アプリケーションのセットアップ)
    - [コンポーネント生成コマンド](#コンポーネント生成コマンド)
    - [データベース関連コマンド](#データベース関連コマンド)
    - [データベーススキーマ変更コマンド](#データベーススキーマ変更コマンド)
- [Railsのコマンドライン操作](#railsのコマンドライン操作)
- [Rails開発のVSCode拡張機能](#rails開発のvscode拡張機能)

## Railsの主要コマンド

### アプリケーションのセットアップ
- 新しいRailsアプリケーションを作成します。
  - `rails new [アプリ名] -d [データベース]`
    - 例: `rails new my_blog_app -d postgresql`

### コンポーネント生成コマンド
- コントローラとビューを生成します。
  - `rails generate controller [コントローラ名] [アクション]`
    - 例: `rails generate controller home index`
- モデルとマイグレーションを生成します。
  - `rails generate model [モデル名] [フィールド:タイプ]`
    - 例: `rails generate model User name:string email:string`

### データベース関連コマンド
- マイグレーションを実行して、データベーススキーマを更新します。
  - `rails db:migrate`
- 最後のマイグレーションを巻き戻します。
  - `rails db:rollback`

### データベーススキーマ変更コマンド
- 特定のデータベース変更のための新しいマイグレーションを生成します。
  - `rails g migration [マイグレーション名]`
    - 例: `rails g migration AddAgeToUsers age:integer`

## Railsのコマンドライン操作
- Railsアプリケーションのコンソールを開きます。
  - `rails console`
- ローカル開発サーバーを起動します。
  - `rails server`

## Rails開発のVSCode拡張機能

私にRailsを教えてくれている方が素敵な記事を書いていたので是非この拡張機能もインストールして一緒に効率的に開発できるようになりましょう！

https://qiita.com/minimabot/items/8d73d407690b40b8eec8
cscの作法 その450

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
コマンドプロンプトに、色を付けよ。

# 方針
- GetConsoleModeを使う。


# サンプルコード

```


using System;
using System.Runtime.InteropServices;

namespace App
{
	class Program {
		const int STD_OUTPUT_HANDLE = -11;
		const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
		[DllImport("kernel32.dll", SetLastError = true)]
		static extern IntPtr GetStdHandle(int nStdHandle);
		[DllImport("kernel32.dll")]
		static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
		[DllImport("kernel32.dll")]
		static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
		static void Main() {
			var handle = GetStdHandle(STD_OUTPUT_HANDLE);
			uint mode;
			GetConsoleMode(handle, out mode);
			mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
			SetConsoleMode(handle, mode);
			const string UNDERLINE = "\x1B[4m";
			const string RESET = "\x1B[0m";
			Console.WriteLine("Some " + UNDERLINE + "underlined" + RESET + " text");
			Console.ReadLine();
		}
	}
}



```

以上。
[表情検出] 笑ったら寝ろを作ろう(手抜き記事)

# 「笑ったら寝ろwww」を作りたいなと思いました。

「笑ったら寝ろwww」ってありますよね。あれ、絶対寝てないので嫌いです。寝なさい。

ということで今回は笑ったら寝てもらうためのプログラムを書きました。
必要な技術は3つ
1. 笑っていることの判断(表情検出)
2. 部屋の電気を消してあげる
3. シャットダウンしてあげる

ってなわけで技術調査からどうぞ。

## 表情検出
表情検出をする基本的なコード。岡田の笑顔が映ってますね。

これはcolabとかで動きます。
https://gist.github.com/okdshinya/f5c7aba961195804d85c35bf23fdb404

## 部屋の電気を消す

自分の書いたプログラムで家電が操作できたらめっちゃ面白くないですか？
出来ます。

### NatureRemoの宣伝
Nature Remo、小さいデバイスをUSB-Bにつないだ状態で部屋に放置すると、そいつがリモコンになってくれるってやつです。赤外線の操作を覚えてくれます。正直電池で動いてくれると嬉しいです。

欲しいなら安いやつとか、安売りしてるタイミングで買うのがおすすめです。
https://shop.nature.global/collections/nature-remo

### APIあるやで
Nature RemoはAPIあります。これは買いです。
https://developer.nature.global/

## シャットダウン
パソコンも落としたいですね。
なんか普通にシステムコールできるっぽいです。以下のコードを実行したらシャットダウンするってばよ。
```
import os
os.system('shutdown -s')
```

## 完成したものがこちら
完成してません。飽きました。

### 岡田が実装してないものリスト
1. シャットダウンとNature Remo API
みんな要らないと思うのでやめました。
1. 表情検出を非同期にすることで表示を滑らかにすること。
これ上手く書ける人いますか？僕はプログラミングわかんないので出来ませんでした。

### つくったもの
えー、表情検出のコードとほぼ一緒です。ローカルで動かしたんですけど環境は書くのめんどくさいので書きません。
```
import cv2
from feat import Detector
import concurrent.futures

#カメラ
cap = cv2.VideoCapture(0)

#使うやつ
detector = Detector(
    face_model="retinaface",
    landmark_model="mobilefacenet",
    au_model='svm',  # ['svm', 'logistic', 'jaanet']
    emotion_model="resmasknet",
)

while True:
    # カメラからの画像取得
    ret, frame = cap.read()
    frame_flipped = cv2.flip(frame, 1)  # 1は左右反転を示す
    # 画像保存
    cv2.imwrite('../img/pic.jpg', frame_flipped)

    #すごいことする
    single_face_prediction = detector.detect_image('../img/pic.jpg', outputFname="output.csv")

    #数値を出す。
    happiness_level = int(single_face_prediction.emotions["happiness"][0] * 100)
    if happiness_level>0:
        result = "Happiness Level="+str(happiness_level)+ "%"
    print(result)

    #表示する
    cv2.putText(frame_flipped, result, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
    cv2.imshow('camera', frame_flipped)

    #ここで笑ってるときの処理ができる。
    #シャットダウンとか、僕はNature remoのAPI使って部屋の電気とかいじる。
    if happiness_level > 90:
        pass

    #Escキー押したら止まる
    key = cv2.waitKey(10)
    if key == 27:
        break

```

## まとめ
岡田はプログラミングが出来ない。ちゃんちゃん♪
Bhyve で胃袋を掴まれる話

それは昼下がりに突然やってきたトラブル：

13.2-RELEASE の　Bhyveホストにに乗っけている FreeBSD14.0 のサーバ。
14.0p3 が来たんで、えいやっと更新し、ちょいちょいっと再起動・・・

** 何かがおかしい　**

# ZFS（ZPOOL)のバージョン違いで起動できない！！事故

これは、FreeBSDで長年ZFSと戦ってきた歴戦の勇者（？）にとりそれ自体別に珍しいことでは（？）ないのかもしれませんが、ブート自体に至らないのはちょっと珍しいです。大抵はブートは出来るがマウントが出来ずによたります。そしてブートしてくれているので、single-user モードが使えて、mount出来ない原因を特定できます（パニックになっていなければ解決できます）

* ですが 今回は違います。
<pre> ZFS: unsupported feature: com.klarasystems:vdev_zaps_v2</pre>
このメッセージも、FreeBSD-MLのアーカイブでは時々出てくるので、珍しくはないのですが13.2以前で問題になっているとされていました。14.0では解決されているはず？？ですし、gpart のbootcode サブコマンドで 差し替えてるはずなんですけどね　(←これは誤信）

# リカバリーやってみる（うまく行ってない編）

* 起動できないFreeBSDのリカバリーはどうやりますか？　そうですね。色々あるんですが、まあ手軽なのはInstallイメージがあればそれを機材なりホスト環境なりにツッコんでやれば、とりあえずOS起動も出来、ファイルシステムまでマウントすることは可能（なはず）です（物理的故障、ブートイメージのデータ破壊などでなければ？）　Bhyveの環境ですから、インストール用のISOファイルを入手し、""bhyve-vm"" のコマンド　vm install ... で起動してやれば良いんです。

* zpool の import では、rootfs は見えなくなります：これは案外ハマりポイントですが、うっかり rootfs が消えたと思うんですよね. <pre> zpool import -f -R {{/tmp/mnt}} </pre> で 普通にインストールされた　FreeBSD であれば zroot/ROOT/default が rootfs として設定されていますが、これは恐らく事故防止のためだと思うのですが、 見えなくなって焦ります。まあ、よく探せばマウントまでいけます・・・
* 長い運用期間のbhyveインスタンス（？）であれば古いタイムスタンプ pbmr,gptzfsboot があったりしますが、 md5sum をとれば、最近の14.0-RELEASEの更地に入れた、新しいものと変わらないことが分かります。紛らわしいですね。
* /boot がマウントできてない以前なので、どうもOS側の問題じゃない感じです？？　ということは？？　⇒ bhyveの側に何かある？？という話になってきました。

# そもそも ホストが 13.2-RELEASE で 14.0-RELEASEのゲストは・・・
* bhyve が VMとして独自に管理されていれば問題ないのですが、bhyveを使う利点は違う kernelバージョンでも安定して動かせる長期運用環境としての起用です。もしkernerl/userland を更新することに問題がなければ、jail くらいの分離度のほうが管理コストが低い。古いOSを後生大事に使うためなので、新しいゲストを入れることは想定してなかったんでしょうね。 userboot.so というbhyveでつかう　第２段のloaderが、ゲスト側のFreeBSD13.2の /bootにあることはある意味で盲点です。

 # 解決： userboot.ko を guest-osバージョンに揃えろ。

* 簡単に言えば、/boot/userboot.ko を新しいものにすればいいってだけだったのです。
*　しかし、/boot/userboot.ko を変えてしまうのはちょっとおかしい。bhyveはユーザランドじゃないか。それならば、 /vm/userboot-{{osversion}}.so みたいな配置がいいよね？　ということで、 FreeBSD14.0 の/vm/{{guest}}/{{guest}}.conf  はこんな修正になります。
<pre>
loader="bhyveload"
+ bhyveload_loaer="/vm/userboot-14.iso"
</pre>

# 結論：bhyve の userboot.ko の扱いは
  要するに ホスト側も14.0/15-STABLEくらいにしておけば、14.xのゲストでトラブルにならないんでしょうが、そういうことは最初から設定しておいたほうが安全では？？？という気になります。
* そもそも、りかいもせず注意深く管理していない私が悪いんですが！
小学校に段々と増えてきた外国人のおともだちと親御さんに渡すプリントをGASで翻訳する。

# 学校のプリントってさ、全然外国人の子どもにやさしくないよね

てなわけで、昨年に引き続きPTAで「こんなんできるから外国人家庭向けに外国語翻訳したプリント配ろうよ」って提案したけど誰も反応しなかったのでここで成仏させよう・・。



```javascript
function onOpen() {
const ui = SlidesApp.getUi();
ui.createMenu('マルチ翻訳')
.addItem('日本語→英語', 'jaToEn')
.addItem('英語→日本語', 'enToJa')
.addItem('日本語→ドイツ語', 'jaToDe')
.addItem('ドイツ語→日本語', 'deToJa')
.addItem('日本語→スペイン語', 'jaToEs')
.addItem('スペイン語→日本語', 'esToJa')
.addToUi();
}

function jaToEn(){
  multitranslate("ja","en")
}

function enToJa(){
  multitranslate("en","ja")
}

function jaToDe(){
  multitranslate("ja","de")
}

function deToJa(){
  multitranslate("de","ja")
}

function jaToEs(){
  multitranslate("ja","es")
}

function esToJa(){
  multitranslate("es","ja")
}



function multitranslate(ori,tar){

  const slide = SlidesApp.getActivePresentation();
  const kekka = slide.getSlides().map(x => x.getShapes().map(y => translate(y.getText().asString(),ori,tar)))
  slide.getSlides().map(x => x.getShapes().map(y => translate(y.getText().asString(),ori,tar)))
  for(let i=0;i<kekka.length;i++){
    for(let j=0;j<kekka[i].length;j++){
      slide.getSlides()[i].getShapes()[j].getText().setText(kekka[i][j])
    }}}
  
 function translate(txt,source,target){
    return LanguageApp.translate(txt,source,target)}

```

日本語
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/54b843a5-1703-2385-3eb4-ea1790e8da83.png)


スペイン語
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/651ee009-67db-46f0-4407-4149030f462c.png)

英語
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/3c4d1904-408e-77d5-c2ef-41af9bb6ecc3.png)


あんまり大量にやると呼び出し上限食らうからほどほどに。
Google翻訳の対象言語は全部カバーしています。


でわ！
キーボード沼

## はじめに
会社では Windows（使用期間10年ちょい）、プライベートだと昔は Windows（15年くらい）、今は MacBook Pro （6年くらい）の中の人が、キーボードについて語っています。

高いキーボードを買うと生産性が上がるという意見もあったりするので、是非見て行ってください。

https://blog.kushii.net/archives/2141959.html

## 前提
会社のPCにツールを入れたり、レジストリを弄ったりすることはあまりやりたくないので、そういうことをしなくても使いやすいものばかりを載せています。

## キーボード紹介

### HHKB Professional HYBRID Type-S
![detail_pd-kb800ysc-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632330/ca0a1aff-2267-75f7-c68d-94a2efd0d2c7.jpeg)
画像引用：https://www.pfu.ricoh.com/direct/hhkb/detail_pd-kb800ysc.html

【使用期間：1週間くらい】

できる感じのエンジニアが使ってるイメージのキーボード。

色はかっこいい感じの無刻印の墨にするか、綺麗な感じの雪にするか悩みましたが、結局HHKB初心者なので、刻印ありにしました。
雪が定番モデルになったのもあって、せっかくなので雪を購入しました。
社内には墨を使ってる人がチラホラいます。

東京の某店舗で試し打ちしましたが、結局その時は買わなかったです。最近あった Amazon のブラックフライデーの時にお安くなっていたのでいい加減買いました。今まさにこの記事を書いているキーボードです。

3日くらいでなんとなく慣れた感じがしますが、完全に慣れるにはもう少しかかりそうです。
叩いていて楽しい。



### フルサイズキーボード
https://www.elecom.co.jp/products/TK-FFCM01BK.html

≪実際に使っていたものとは異なります≫

【使用期間：10年】
テンキーもついているいわゆる普通のフルサイズのキーボード。


有線で使っていました。電池の心配がなくていいですね。あとテンキー付きは地味にありがたいです。最近はテンキーなしのばかりを使っていますが、たまに使用すると安心感があります。
数字入力が多い人は確実にテンキーがほしいですね。


### 分割キーボード
https://archisite.co.jp/products/mistel/barocco-md770-jp/

【使用期間：半年】
会社で使っていたら二度見されたキーボード。

肩こりが軽減された気がします。
矢印キーの並びが独特です。私が使っているものは横一列で並んでいます。

真ん中で割れているのなんて慣れるかなぁ～～と不安に思っていましたが、2，3日叩いてたら普通に慣れました。

ヨドバシカメラ秋葉原店でいろんな軸を叩いた結果、[静音赤軸](https://ki-bo-do-rental.com/2022/09/11/cherrymx-red-pink/)になりました。
__打鍵音がいい。__



### ThinkPad 搭載のキーボード

【使用期間：1年】

通称、[赤ポチ](https://note.com/powerpoint_jp/n/nc1596fd36212)がついています。
私はPCスタンドで結構角度をつけてる関係で、あまり使う機会がありません。
今の仕事で使ってる端末です。

### MacBook Pro 搭載のキーボード（JIS配列）
https://www.apple.com/jp/macbook-pro/specs/

自宅で使ってる自分の MacBook Pro に標準搭載されてるキーボード。

前述した分割キーボードを MacBook Pro につなげているので、使用する機会はほとんどありません。

### MacBook Pro 搭載のキーボード（US配列）
自宅で使ってた自分の MacBook Pro に標準搭載されてるキーボード。

【使用期間：3年～4年】
[正規の整備品](https://www.apple.com/jp/shop/refurbished/mac?afid=p238%7CskqGI4egM-dc_mtid_18707vxu38484_pcrid_642391970763_pgrid_13140809301_pntwk_g_pchan__pexid__&cid=aos-jp-kwgo-Mac--slid---product-)で安かったから買った記憶があるノートパソコン。
US配列のほうがオシャレかな～と思って購入したはずですが、結局自宅でプログラミングしないため、次買い換えたときに JIS 配列に。







### HHKB Lite2（販売終了品）
https://www.pfu.ricoh.com/hhkeyboard/lite2/index.html

【使用期間：2年】
最初に購入した MacBook Pro につなげて使ってましたが、MacBook Pro を買い換えた際にUSB Type-A を挿すところが無かったので、自宅ですやすや眠っています。

お値段もお手頃（当時¥3,800-）で、 失敗してもそこまでダメージの少ない値段でした。
打鍵感は HHKB なだけあって非常に良かったです。

## 〆
結局ノートパソコンだと、標準搭載のキーボードが一番持ち運ぶアイテムが少ないので楽ではあるんですが、叩いて楽しいキーボードを使うともう標準装備のに戻りたくねぇな～って気持ちになってしまいます。

HHKBは9泊10日で[レンタル](https://happyhackingkb.com/jp/news/promo/04/?gad_source=1&gclid=EAIaIQobChMIyLiDr-6NgwMVx9kWBR0BtQODEAAYAiAAEgKfbPD_BwE)もあるので、数万かけて失敗したら嫌だなぁって人はこういうの活用するといいかもしれません。

12月で賞与貰ってる（そろそろ支給される）人もいるかと思うので、是非面白そうなキーボードを探してみてはいかがでしょう・・・👀
NCMBのデータエクスポートに使えるGoogle Chrome機能拡張（スクリプトのエクスポート）

[NCMBは2023年3月末をもって終了します](https://mbaas.nifcloud.com/info/2023/11/post-171.html)。

NCMBを利用されている方々は、まずアプリのデータを適切に保全し、移行先を検討する必要があります。NCMBにはエクスポート機能はあるのですが、ダウンロード実行まで時間がかかったり、ファイルストアには対応していないという問題があります。

そこで、本来は管理画面を便利に使ってもらうために作っていたChrome機能拡張に、データ移行に関する機能を追加しました。以下はスクリプトのファイルを一括エクスポートする機能についての解説です（v1.6より）。

## 動作について

動作は以下のようになります。機能拡張をインストールしていると、スクリプトの画面にエクスポートボタンが追加されます。このボタンを押すと、すべてのスクリプトがダウンロードされます。

![1846_console_mbaas_nifcloud_com_-_1214143614.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/3f54100c-1115-f38d-c8ab-ce64fa8bfbb6.jpeg)


## インストール

[Chrome機能拡張のページからインストール](https://chrome.google.com/webstore/detail/ncmb-extension/dglkhlplcpmnbgodhbngcmdfpojkbdnc?hl=ja&authuser=0)してください。

## ファイルについて

ファイル名は各スクリプトのファイル名になります。内容は、そのスクリプトのコードになります。ACLやHTTPメソッドなどの情報は含まれません。

ここでダウンロードされたファイルは、別サービスへの移行は考慮していません。各バックエンドサービスによってスクリプトのコードは異なりますので、ダウンロードしたファイルの内容を参照して各サービスへの移行を行ってください。

## 制限

この機能拡張は [https://console.mbaas.nifcloud.com](https://console.mbaas.nifcloud.com/) 以下でのみ動作します。また、この機能は管理画面のAPIを使っていますので、APIコール数を消費しません。また、ACLは無視して処理されます。

## コードについて

機能拡張のコードは[NCMBMania/chrome-extension](https://github.com/NCMBMania/chrome-extension)にアップロードしてあります。ライセンスはMIT Licenseです。依存ライブラリとして[URL.js](https://github.com/duzun/URL.js)を使っています（こちらもMIT Licenseです）。

## まとめ

サービスがクローズすると、そのデータにアクセスできなくなります。まずはデータの保全をお願いします。
NCMBのデータエクスポートに使えるGoogle Chrome機能拡張（プッシュ通知の全データエクスポート）

[NCMBは2023年3月末をもって終了します](https://mbaas.nifcloud.com/info/2023/11/post-171.html)。

NCMBを利用されている方々は、まずアプリのデータを適切に保全し、移行先を検討する必要があります。NCMBにはエクスポート機能はあるのですが、ダウンロード実行まで時間がかかったり、ファイルストアには対応していないという問題があります。

そこで、本来は管理画面を便利に使ってもらうために作っていたChrome機能拡張に、データ移行に関する機能を追加しました。以下はプッシュ通知のデータをエクスポートする機能に関する解説です（v1.6より）。

## 動作について

動作は以下のようになります。機能拡張をインストールしていると、プッシュ通知の一覧画面にレポートDLボタンが追加されます。このボタンを押すと、すべてのプッシュ通知のレポートをJSONまたはCSVにて、ダウンロードできます。

![1847_console_mbaas_nifcloud_com_-_1214143703.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/5538a5ce-0edd-4cf9-a09b-e8935744934a.jpeg)


## インストール

[Chrome機能拡張のページからインストール](https://chrome.google.com/webstore/detail/ncmb-extension/dglkhlplcpmnbgodhbngcmdfpojkbdnc?hl=ja&authuser=0)してください。

## ファイルについて

ファイルは `push-(日付).json` または `push-(日付).csv` になります。いずれの場合も、別サービスへの移行は考慮していません。過去のデータとして分析する際に利用するのを想定しています。

## 制限

この機能拡張は [https://console.mbaas.nifcloud.com](https://console.mbaas.nifcloud.com/) 以下でのみ動作します。また、この機能は管理画面のAPIを使っていますので、APIコール数を消費しません。また、ACLは無視して処理されます。

## コードについて

機能拡張のコードは[NCMBMania/chrome-extension](https://github.com/NCMBMania/chrome-extension)にアップロードしてあります。ライセンスはMIT Licenseです。依存ライブラリとして[URL.js](https://github.com/duzun/URL.js)を使っています（こちらもMIT Licenseです）。

## まとめ

サービスがクローズすると、そのデータにアクセスできなくなります。まずはデータの保全をお願いします。