OmniAICreator/Qiita-1.07M huggingface dataset:
基本情報技術者試験ストラテジ分野

基本情報のストラテジ分野の一部をまとめてみました！

### ソリューションビジネス
- 顧客が抱える問題や課題を解決することを目的として、製品やサービスを提供するビジネス
- どこまでサービス事業者提供のITソリューションを利用するかによって、形態が異なる
#### オンプレミス
サーバーなどのITリソースを自社内やデータセンターでユーザー企業自身が管理・運用
1.従来型オンプレミス
自社施設内で自社サーバを運用
２.ハウジングサービス
データせんたに自社サーバを預けて運用
3.ホスティングサービス
サービス業者からサーバをレンタル
#### クラウドサービス
クラウド事業者が用意したITリソースをネットワーク経由で利用
##### IaaS(インフラ)
システム構築に必要な基盤のみ提供
ハードウェア（仮想サーバ）土地を借りるイメージ

##### Paas(プラットフォーム)
アプリ稼働に必要な環境を提供
OS ミドルウェア　家まで借りる

##### SaaS(ソフトウェア)
 アプリまでの全サービスを提供
 アプリケーション　家具家電まで借りる

 ### SOA
 - Service Oriented Architecture: サービス思考アーキテクチャ
 - システムをサービス（ソフトウェアの機能）の組み合わせで構築する
 通常はシステムに必要な機能をシステム内に作る
 SOAの考え方は必要な機能を提供するサービスを利用する
 ### システムの活用
 - 世の中にある様々な情報を適切に読み取り、活用する能力（=情報リテラシー）が必要
 - 正し、社会のデジタル化が進むにつれて、情報格差も生まれてくる

### システムの活用
- 大量のデータやシステムを有効活用している事例
####　システム活用例
##### BYOD(Bring Your Own Device)
個人で所有するPCやスマートフォンなどの情報機器を業務に利用すること
##### RPA(Robotic Process Automation)
人が実施している提携的な業務をソフトウェアロボットにより自動化・効率化すること
##### BI(Business Intelligence)
DBに蓄積された情報を統計的・数学的な手法で分析（データマイニング）し、経営戦略の意思決定において有用な情報を取り出すこと

ほす
ABC335をPythonで（A~E）

AtCoder Beginner Contest 335（Sponsored by Mynavi）

https://atcoder.jp/contests/abc335

# A問題
末尾を落として、$4$を付け加える
```python:A
print(input()[:-1] + "4")
```
# B問題
起きうる全通りを試して$N$以下だったら出力する
```python:B
n = int(input())
for i in range(n + 1):
    for j in range(n + 1):
        for k in range(n + 1):
            if i + j + k <= n:
                print(i, j, k)
```
# C問題
1の点が$(n, 0)$から$(1,0)$まで移動した後クエリに従って移動したとみなすと、
2番目の点は1手前の1の座標で、3番目の点は2手前の1の座標で...$a$番目の点は$a-1$手前の1の座標だから

スタックにその移動を追加していき、答えるときは後ろから$p$番目を答えればよい
```python:C
n, q = map(int, input().split())

lst = [(i + 1, 0) for i in range(n)][::-1]
arr = {"U":[0, 1], "D":[0, -1], "R":[1, 0], "L":[-1, 0]}

for i in range(q):
    com, x = input().split()
    if com == "1":
        lst.append((lst[-1][0] + arr[x][0], lst[-1][1] + arr[x][1]))
    else:
        print(*lst[-int(x)])
```
# D問題
渦巻き状に数字を書いていけばいい
```python:D
n = int(input())

lst = [[""] * n for _ in range(n)]
x, y, arr = 0, 0, 0
array = [[1, 0], [0, 1], [-1, 0], [0, -1]]

for i in range(n ** 2 - 1):
    lst[x][y] = i + 1
    if not(0 <= x + array[arr][0] < n and 0 <= y + array[arr][1] < n) or lst[x + array[arr][0]][ y + array[arr][1]] != "":
        arr = (arr + 1) % 4
    x, y = x + array[arr][0], y + array[arr][1]

lst[x][y] = "T"

for l_i in lst:
    print(*l_i)
```
# E問題
まず、$A$の値が小さくなる方向へは考える必要がない
$A$の値が同じときはUnionFindで同じ頂点だとして扱えばいい

あとはトポロジカルソートの要領で各UnionFindの代表点を探索すればいい
```python:E
from collections import defaultdict, deque


class UnionFind:
    """
    URL : https://note.nkmk.me/python-union-find/
    """
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)


n, m = map(int, input().split())
a = list(map(int, input().split()))
data = [list(map(lambda x:int(x) - 1, input().split())) for _ in range(m)]

UF = UnionFind(n)
for u, v in data:
    if a[u] == a[v]:
        UF.union(u, v)

edge = [[] for _ in range(n)]
cnt = [0] * n
for u, v in data:
    u_i, v_i = UF.find(u), UF.find(v)
    if a[u_i] < a[v_i]:
        edge[u_i].append(v_i)
        cnt[v_i] += 1
    elif a[u_i] > a[v_i]:
        edge[v_i].append(u_i)
        cnt[u_i] += 1


INF = 10 ** 10
dist = [-INF] * n
q = deque()
for i, c_i in enumerate(cnt):
    if c_i == 0:
        q.append(i)
    if UF.same(0, i):
        dist[i] = 1

while q:
    now = q.popleft()
    for to in edge[now]:
        dist[to] = max(dist[to], dist[now] + 1)
        cnt[to] -= 1
        if cnt[to] == 0:
            q.append(to)

ans = dist[UF.find(n - 1)]
print(ans if ans > 0 else 0)
```
関数型インターフェース、ラムダ式②（Java Silver）

# 最初に
この記事は、以下の書籍を通じてJava silverの合格に向けて自分が学んだ内容を体系的にアウトプットする記事である。（目指せ年始合格！）
[徹底攻略Java SE 11 Silver問題集[1Z0-815]対応](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5Java-SE-11-Silver%E5%95%8F%E9%A1%8C%E9%9B%86-1Z0-815/dp/4295007625/ref=asc_df_4295007625/?tag=jpgo-22&linkCode=df0&hvadid=342700130622&hvpos=&hvnetw=g&hvrand=9715255718806805548&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009303&hvtargid=pla-830348236008&psc=1&mcid=e12ce628cc5a33b29a77da3a85a6cdf0&th=1&psc=1)

# 勉強記録
### ラムダ式

#### 省略ルール
   | 省略部分 | 省略の条件 |
   | --- | --- |
   | 引数の型 | 省略する場合は、全引数の型を省略する |
   | 引数の() | 引数が1つの時のみ省略可能 |
   | メソッドの{} | 処理が一文の時のみ省略可能。戻り値がある場合、returnの省略とセット |
   | return | メソッドの{}の省略とセット |
- returnと{}のどちらかだけを省略することはできない
- 参考）[【Java】ラムダ式の省略方法まとめ](https://qiita.com/sano1202/items/40cc8a0e29def0c76fa8)

#### ラムダ式の外で宣言されたローカル変数にアクセスする場合
- 実質的にfinalな変数（finalで修飾されていなくても変更されない変数）にしかアクセスできない。
    - NG例①
    
    ```clike
    public class Test{
    	public static void main(String[] args){
    		String val = "hello world";
    		Function f = () -> {
    			//コンパイルエラー
    			val = "hello Japan";
    			System.out.println(val);
    		}
    		f.test();
    	}
    }
    ```
    
    - NG例②
    
    ```clike
    public class Test{
    	public static void main(String[] args){
    		String val = "hello world";
    		Function f = () -> {
    			System.out.println(val);
    		}
            //コンパイルエラー
    		val = "hello Japan";
    		f.test();
    	}
    }
    ```
- 参照型変数の場合、変数が指すインスタンスを変えなければ、中身は変えてOK
    - 参考）[徹底解説! Javaのラムダ式はどういうもので、どう使えばいいのか!](https://www.bold.ne.jp/engineer-club/java-lambda-expression#i-14)

```clike
import java.util.function.Consumer;

class LambdaTest {
    public static void main(String[] args) {
        final int[] i = {0, 1, 2};
        System.out.println(i[1]); // → 1

        Consumer<?> consumer = x -> {
            i[1] = 256;
        };
        consumer.accept(null);

        System.out.println(i[1]); // → 256!
    }
}
```

# 感想
- ラムダ式の外で宣言されたローカル変数にアクセスする場合実質的にfinalな値でないといけないというルール、なぜこのルールが必要なのかがまだよくわかっていない。以下サイトなどを見て、スコープの問題っぽいがよくわからんな。（おいおい調べる）
    - [ラムダ式から参照されるローカル変数は、finalまたは事実上のfinalでなければならない理由](https://teratail.com/questions/42539)
クラス属性を取得する

```js
Object.prototype.toString.call([])     // [object Array]
Object.prototype.toString.call(/./)    // [object RegExp]
Object.prototype.toString.call(()=>{}) // [object Function]
```
JavaScriptオブジェクトに対してクラス属性を取得するには、上記のObject.prototype.toString.call()を使用します。ですが、この方法以外では取得できない型情報が含まれています。typeof演算子ではオブジェクトの型を区別しないので、下記に作成したclassof()関数の方が便利です。
```js
function classof(o) {
  return Object.prototype.toString.call(o).slice(8, -1);
}

classof(null)      // Null
classof(undefined) // Undefined
classof(6)         // Number
classof(10n**100n) // BigInt
classof('Hello')   // String
classof(false)     // Boolean
classof(Symbol())  // Symbol
classof({})        // Object
classof([])        // Array
classof(/./)       // RegExp
classof(()=>{})    // Function
classof(new Map()) // Map
classof(new Set()) // Set
classof(new Date())// Date
```

#### 参考
https://www.amazon.co.jp/JavaScript-%E7%AC%AC7%E7%89%88-David-Flanagan/dp/4873119707
Gitとは？

GitとGitHubは一緒なものと捉えてましたが
別物とわかったので、勉強できてよかったです！

### Gitとは？
プログラミングのコードを管理する分散型管理システム
編集履歴や古いバージョンのデータを管理しているシステム
ファイルの編集やチーム作業などを効率化しわかりやすくするために開発されたシステム
#### GitとGitHubは別物
GitHubはGitの仕組みを使ったサービスで世界中の人々が自分のソースコードやデザインなどのデータを保存できるWebサービスのことを指します
### Gitを使ってできること
- 編集前ファイルを残したまま編集できる
- バージョンをもとに戻す作業が効率化できる
- 修正した箇所をプロジェクトメンバーで共有しやすい
- チームで同じファイルを同時進行で編集できる
- Excel・word・画像ファイルなど様々なファイルが管理できる

Gitは利用することでデータの管理や共有、編集作業の効率アップに役立つツール

### Gitが活躍する場面
#### エンジニア
プログラムコードの管理にGitha最適
プログラミングコードは何度も編集しながら完成させるものなのでGitとの相性はかなり良い
#### デザイナー
HTMLやCSSなどデザインに関するテキストデータの保存・共有に利用される
#### ライター
原稿を納品する際に共有しやすいGitを使う
企業の事務現場でデータを保存するツールとしても

### Gitが使えるアプリ３選
#### Git Bash
Windowsで動くソフトウェアでファイルの編集や削除を操作することが可能
#### Source Tree
コマンド操作不要でGitgを使用できる
#### Tower
Gitを直感的に操作できるGUI形式のツール
機能も豊富（ローカルファイルの「変更をもとに戻したり、古いファイル履歴を復元などできる）
[Vue3] composablesと状態管理の記述パターンと比較

# Vue.jsにおけるrefとuseStateの挙動の理解

## 背景
Vue.jsのリアクティブな状態管理には、`ref` や `useState` などのAPIが利用されます。これらのAPIの挙動を理解するため、関数外での `ref` 宣言がアプリケーションにどのような影響を与えるのかを整理しました。

## ソースコードの実験
以下のGitHubリポジトリには、`ref` と `useState` を用いたサンプルコードがあります。このコードをクローンして、各APIの挙動を実際に確かめてみることができます。
[GitHubリポジトリへのリンク](https://github.com/Makoto-Onohara/Composables-Ref)

## 実験結果と解析
![実験結果の画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/4dbf30a7-2c1d-f866-1f5e-00064d02006c.png)

### 主なポイント
- **useState**:
  `useState` はアプリケーション全体で状態を共有します。これにより、アプリケーションの異なる部分間で同じ状態を利用することができます。

- **コンポーネント内のref**:
  `ref` をコンポーネント内で宣言すると、そのスコープはそのコンポーネントに限られます。他のコンポーネントで同じcomposablesを使用しても、状態は共有されません。

- **関数外のref宣言**:
  関数の外部で `ref` を宣言すると、その状態はアプリケーション全体で共有されます。これにより、異なるコンポーネント間で一貫したデータを持つことが可能です。

## 気づきとベストプラクティス
### ダブルクォーテーションの表示
- 分割代入をしない場合、テンプレートに直接 `ref` オブジェクトを表示しようとすると、ダブルクォーテーションが表示されることがあります。これは、`ref` で宣言された `message` プロパティがオブジェクトとして解釈されるためです。

- 正しい表示のためには、テンプレートに渡す際には文字列を直接指定することが重要です。例えば、`ref` オブジェクトの内部プロパティに `value` を使用して直接アクセスします。

```vue:valueにアクセスすることでダブルクォーテーション回避
<!-- refオブジェクトの内部プロパティに直接アクセスする例 -->
<p>{{ message_2.message.value }}</p>
```

ただ、基本的には分割代入を使うと思うので大丈夫かと思います。
個人的にいろいろ試したりする中で気づいた違いで戸惑った点でした。
＜メモ＞ TA-Libをインストールする

TA-Libは金融データを分析する機能を多く備えているライブラリですが、
windows11 python3.11.4 64bit で使うため、インストールしようとしたのですが、少し手間取ったため、メモしておきます。

単にコマンドプロンプトで、
```python
> pip install TA-Lib
```
を行うだけでは、エラーが出てインストールできません。

ビルド済みのバイナリがあれば、下のリンクのようにインストールができるのですが、使用しているpythonのバージョンのものがなければ、自分でビルドする必要があります。

https://qiita.com/ConnieWild/items/cb50f36425a683c914d2

自分でビルドするのに、下のリンクに書かれているREADMEを参考にしました。

https://github.com/ta-lib/ta-lib-python

まず、"ta-lib-0.4.0-msvc.zip"ファイルをダウンロードして、c:\ta-lib へ解凍します。
そして、スタートメニューのアプリVidual Studio、"x64 Native Tools Command Prompt for VS2022" を起動後、
カレントディレクトリを次のように移動し、
```python
> cd C:\ta-lib\c\make\cdr\win32\msvc
```
"nmake"を実行し、ビルドします。
```python
C:\ta-lib\c\make\cdr\win32\msvc> nmake
```

これで、準備ができたので、コマンドプロンプトで、インストールします。

```python
> pip install TA-Lib
```

インストールが終われば、インポートして使用できます。

※スタートメニューのアプリに、Visual Studio　がなければ、Visual Studioをインストールする必要があります。
コンサル一年目が学ぶこと　を読んで

# はじめに
「[コンサル一年目が学ぶこと 新人・就活生からベテラン社員まで一生役立つ究極のベーシックスキル30選](https://www.amazon.co.jp/%E3%82%B3%E3%83%B3%E3%82%B5%E3%83%AB%E4%B8%80%E5%B9%B4%E7%9B%AE%E3%81%8C%E5%AD%A6%E3%81%B6%E3%81%93%E3%81%A8-%E5%A4%A7%E7%9F%B3-%E5%93%B2%E4%B9%8B/dp/4799315323)」を読んだ。
ユーザ系Sierに転職して今後より顧客に近い立場で仕事をすることが予想されるため、顧客の本当の要望を理解し実現できる力をつけたいと考えていた。
そんな時にAmazon Primeで無料となっていたので読んでみた。

# 概要
この本では、仕事で役立つスキルはコンサルの一年目に学ぶことで、学んだスキルは10年、15年と普遍的に役立つスキルと説明している。
その中でも30個の重要なスキルを解説・体験エピソード付きで紹介している。
大枠の構成としては以下の4つに分けられ、その中で重要視された項目をピックアップした。
+ 話す技術
    + 結論から話す
    + 数字で語る
    + 期待値を超える
+ 思考術
    + ロジックツリー
    + 雲雨傘の論理
    + 仮説思考
+ デスクワーク
    + 議事録
    + 資料作成術
    + 仕事を早くするための重点思考
+ ビジネスマインド
    + 価値を出す
    + お金を意識する
    + プロフェッショナルとしての考え、ふるまい

# 感想
今年9年目に突入して全体的にうっすらと意識していたが、改めて大事だなと再認識した。

「話す技術」では、特に結論から話すことは意識していないとつい冗長に話してしまうので、その話し方が身につくまで何回も繰り返して使うべきというのは理解できた。
あと期待値を超えるは、これまでの社会人生活を振り返った時に、会社で設定する目標はいかに低く設定して上司の評価を得るか考えていたので、耳に痛い話だった。
上司を超えてクライアントの期待するものを理解しその期待値を超えるものを提供するということは、これからの仕事で意識していくべきことだと思った。

「思考術」はこの本の中では一番読んでよかったと思える内容だった。
前職のベンチャー企業の社長が仮説、仮説と繰り返していたことを思い出した。
社長は時間とともにお金が消えていく中で、以下に試行回数を絞って成功にたどり着けるか考えて、この仮説思考を使っていたんだと思うと、仮説思考をもっと学びたいと思った。
この本はあくまで基本的な解説にとどまっているため、より専門的な内容を知りたいのであれば別の本を読むべきだ。

「デスクワーク」は正直当たり前な内容で途中から飛ばし飛ばしで読んでいた。
議事録や資料作成術はエクセルを触って日常的に業務している人にとっては常識だと思う。
仕事を早くするための重点思考はその通りだと考えて、細かいところにとらわれるのではなくまずは大枠を考えていこうという、大学受験を思い出す内容だった。

「ビジネスマインド」は結果を出すことの重要さを説明していた。
クライアントから信頼を得るためには、クライアントの期待値を超える結果を出し続けることである。
自分の仕事に置き換えると、顧客の話から本当の要望を聞き出してアプリケーションで実現することであり、話す技術とコードスキルの両方を高めることが必要なことだと考えた。
プロフェッショナルとしての振る舞いは顧客のことを考えて滅私奉公で全力で仕事をしろということだけど、方向性を間違えずに自分を安売りしないでワークライフバランスを保ちながらのほうが自分にはあってそう。そのためにも技術を蓄えて立場を絶対的なものにしていくべきだと思った。
スマホでペット用監視カメラを作ってみた

# はじめに
スマートフォンを使った監視カメラシステムを作ってみました
作ろうと思い立ったきっかけですが、昨年ワンちゃんを一頭飼い始めて
最近もう一頭増えたのと、その子が保護犬ということでなかなか目が離せないということもあり、スマホを使って外出先から自宅のワンちゃんの様子を確認出来る仕組みを作ってみようと思ったのがきっかけです

| 1頭目 | 2頭目 |
|:-:|:-:|
| <img width="300" alt="01_choco.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/9885504b-f64e-8604-6a24-cfabd2eb7ecb.jpeg"> | <img width="300" alt="02_coronet.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/49f3c6e3-55a6-5507-9977-b424c52e53c0.jpeg"> |
| チョコ(2歳♂) | コロネ(5歳♀) |

# アプリの仕組みについて
作成したアプリはカメラ側と閲覧側の2種類あり、それぞれ以下の処理を行っています

[カメラ側]
スマートフォンでカメラ撮影用のサイトへアクセスする
一定時間毎にカメラで撮影し、撮影した画像ファイルをサーバへアップロードする

[閲覧側]
PCかスマートフォンでカメラで撮影した画像を閲覧出来るサイトへアクセスし、閲覧する
複数台設置する可能性があるので閲覧するカメラを切り替えられるようにする

# ソースコード
カメラアプリの主要なコードは以下になります
スマートフォンのカメラにアクセスする必要があるので、mediaDevicesのgetUserMediaメソッドを実行してアクセスを許可します
```javascript:カメラ使用許可
    navigator.mediaDevices.getUserMedia({
        video: { facingMode: 'environment', width: w, height: h },
        audio: false
    }).then( handleSuccess )
    .catch(err => {
        console.log( JSON.stringify(err) );
    });
```
※facingModeを「user」にすると、フロントカメラが起動します

```javascript:画像アップロード
const objFormData = new FormData();
videoCanvasObject.style.display = 'block';
videoCanvasContext.drawImage( videoObject, videoObject.style.left, videoObject.style.top, videoCanvasObject.width, videoCanvasObject.height );
videoCanvasObject.style.display = 'none';
const blob = dataURItoBlob( videoCanvasObject.toDataURL() );
objFormData.append( 'file', blob );
objFormData.append( 'camera_no', cameraNo );
ajaxSendFormData( SERVER_URL, objFormData, 'appCameraRecvEndCallback' );
```
画像ファイル(バイナリデータ)をアップロードする必要があるので、FormDataにデータをセットしてPOSTしています

[閲覧アプリ側]
こちらはサーバ上の画像ファイルを取得して表示しているだけで特別特殊な処理はしていません
閲覧する時に、1頭目の様子だけ確認したいということがあるかもしれないと思ったので
表示するカメラの画像を切り替えられるようにしました

| 1台目表示 | 2台目表示 |
|:-:|:-:|
| <img width="1000" alt="1台目表示" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/e78d6fc1-8ff0-8896-180c-0ee8c5a11a72.png"> | <img width="1000" alt="2台目表示" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/8e9bcba6-0d90-d64c-6446-899deedbc053.png"> |

両方のカメラ画像を同時に表示すると以下のように見ることが出来ます
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/e909b8a5-1a36-0023-cec6-0be2d267674c.png)


# 運用イメージ
ケージの横にスマホを置いて撮影しています
<img width="400" alt="イメージ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/740996/12c62b7f-6383-b17e-7a27-606a2472bdf7.jpeg">
今は2台運用ですが、スマホがあれば簡単にカメラを増やすことが可能です

# 今後の展望など
以下のようなことが出来ると良いなと思っています
・閲覧側から撮影側のスマホに向かって音声を送れるようにする
→ワンちゃんに向かって話しかけられるようになると安心させられるかも
・画像だけでなく動画も撮影出来るようにする

# 最後に
外出中に自宅のワンちゃんの様子が見れるようになったので安心して外出出来るようになりました
更に機能を追加し、これからもワンちゃんと安心して暮らしていけるようにしたいと思います
実践・ペアプログラミング

[株式会社Never](https://neverjp.com/)のshoheiです。

株式会社Neverは「NEVER STOP CREATE 作りつづけること」をビジョンに掲げ、理想を実現するためにプロダクトを作り続ける組織です。モバイルアプリケーションの受託開発、技術支援、コンサルティングを行っております。アプリ開発のご依頼や開発面でのお困りの際はお気楽にお問合せください。

https://neverjp.com/service/

# 概要

弊社で実践しているペアプログラミングをご紹介します。

# ペアプログラミングとは

ペアプログラミングはソフトウェア開発の手法の１つで、2人のプログラマーが１つのモニターでプログラミングをしていく手法です。

ドライバー役（コードを映し出して操作する人）とナビゲーター役（指示する人）の2人で作業していきます。3人以上で作業することをモブプログラミングと呼びます。

ペアプログラミングの詳しい説明はこちらの記事をご参考ください。
[皆で楽しく成長するためのペアプログラミングとモブプログラミングのガイドライン](https://qiita.com/kojimadev/items/e29f56a241f502e54131)

# ペアプログラミングの目的

- 実装タスクを齟齬なく前に進めれる
    - 実装不安の解消、問題解決
- スキルアップ
    - 開発効率の向上、ドメイン知識や新しい知見の習得
- メンバー間の信頼関係の構築
    - お互いの人間性を知り、心理的安全性を担保する

# 具体的なやり方

弊社では実装の相談をしたい時やコードレビューを同期的にしたい場合にペアプログラミングをします。リモートワークがメインですので、SlackのハドルやGather上でペアプログラミングを実施します。

ペアプログラミングしたい時に有識者に声をかけ、時間を決めて実施します。

SlackやGatherは誰と誰が話しているのか分かるので、プロジェクト内の第三者も時間があればペアプログラミングに参加して視聴します。

## 実装相談 or 実装で詰まった時

実装相談したい内容や詰まっている箇所を議題に進めていきます。相談者はドライバー役として画面共有やLive Shareをしてソースコードや関連記事を映し出しながら説明します。

相談を受ける側はナビゲーター役として、ソースコードの確認や関連情報を調べるよう指示します。

また、ナビゲータ役が相談内容の解決方法を既に知っている場合は**ナビゲータ役が自ら画面共有やして、ライブコーディングしたり関連情報を検索してソース元を共有します。**

まさに見て覚えろ的な感じで進めていきます。この方法はかなり有効ですが、相談者は聞いているだけで答えを得られるため、本当に理解したかどうか不安になると思います。その場合、相談者は **他の人に同じように教えれるか？** を意識してしっかり聞き、疑問点があれば質問して理解を深めます。

## コードレビュー

レビューイがドライバー役、レビュアーがナビゲータ役として進めていきます。

レビューイがレビュー対象のソースコードを画面共有やLive Shareしてレビュアーと同期的にコードを確認します。どこから説明して良いか分からない場合は、レビュアーに指示を促し、レビュアー主導でコードレビューを進めていきます。

レビュアーは以下の観点でコードを見ます。

|観点|詳細|
|---|---|
|PR（Pull Request）の要件通りに実装されているか|ドメイン知識の確認、デザイン通りの実装か確認|
|コーディング規約通りに実装されているか、アンチパターンな実装はしていないか|[株式会社NeverのFlutterコーディング規約5選](https://qiita.com/hukusuke1007/items/80d9548a352560d9dcc3)<br>公式 or 外部パッケージのドキュメントや今までの経験から確認|
|調査方法やツールの使い方が適切であるか|IDEのショートカットキー活用、デバッグ方法、ググり方（英語ワードを活用して狙った記事をHitさせる方法）を確認|

レビューイの説明途中であっても、指摘事項が見つかった場合はすぐに指摘し、レビューイがコード上にコメントします。コメントは正確に書く必要はなく簡潔なもので良いです。ただし、後でGrep検索できるようコメントのプレフィックスは統一します。

以下の例では `TODO` で検索できます。

```dart
final user = User();
// TODO: 指摘
state = user.name!;
```

指摘後、レビューイの実装イメージが湧いていないような雰囲気であれば、レビュアーが自らライブコーディングして実装風景を見せ、書いたコードをSlack等で共有します。


ペアプログラミングで得られる恩恵としては以下の通りです。

|立場|恩恵|
|---|---|
|レビューイ|分からない事や仕様についてすぐに確認できる。|
||レビュアーのライブコーディングが見えるので、知らない事を目で学べる。自分の実装方法と比較して確認できる。|
|レビュアー|コードの誤りをすぐに指摘できる、温度感を伝えれるので誤りのヤバさを明確に伝えれる。|
||IDEの使い方、デバッグ方法、検索方法など開発効率が上がる方法を教えれる。|


# 最後に

ペアプログラミングは同期的な作業なので双方の時間は取られてしまいますが、テキストでやりとりするより遥かに早いです。

困ったら助ける、だって同じチームメンバーだもの。

チームで楽しく良いアプリを作っていきましょう👍



# 参考文献

[明日からできる働き方改革「モブプログラミング」 WHOLE TEAM APPROACH](https://speakerdeck.com/takaking22/mobprogramming-as-work-style-reform)
[ペアプロ・モブプロでメンバーが驚くほど成長した話](https://qiita.com/kojimadev/items/5d0e03f3367eddc4fa67)
[レビュー指摘が多い原因がレビュアーにもある事を共有する(#14)](https://note.com/kojimadev/n/nca1236edb002)
[VSCode Live Shareすげぇ](https://qiita.com/taichi0514/items/95aca7428376a7b41f90)
[Android StudioでCode With Meを試してみた](https://qiita.com/rnk0085/items/7870b18805a346d65340)
Laravelのリレーションがやっとわかったので備忘録(え、いまさら?)

# 今回作成するモデル
```mermaid
erDiagram

User{
    id int
    username string
    email string
    password byte
}

Profile {
    id int
    user_id int
    name string
    description string
}

User||--o|Profile:""

```

# Modelの書き方

```(親側)User.php
<?php

namespace App\Models;
use App\Models\Profile;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;


class User extends Model {
    use HasFactory;
    protected $fillable = [
        "id",
        "username",
        "email",
        "password"
    ];

    public function profile(){
        return $this->hasOne(Profile::class);
    }

}
```
```(子側)Profile.php

<?php

namespace App\Models;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Profile extends Model {
    use HasFactory;
    protected $fillable = [
        "user_id",
        "name",
        "description",
    ];

    public function user(){
        return $this->belongsTo(User::class);
    }
    
}

```
# Migrationファイルの書き方
``` example.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;


return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create("users", function(Blueprint $table) {
            $table -> bigIncrements('id');
            $table -> string("username");
            $table -> string("email");
            $table -> string("password");//平文保存は危険なので絶対しない(これは例だから無視)
            $table -> timestamps();
        });

        Schema::create("profile", function(Blueprint $table){
            $table -> bigIncrements("id");
            $table -> string("name");
            $table -> string("description");
            $table -> foreignId("user_id")->constrained("users")
            $table -> timestamps();
        }
    }
}
```

# 追加
``` example.php

$user = User::create([
    "username" => $username,//固有のユーザーネーム
    "email" => $email,//メールアドレス
    "password" => bcrypt($password)//パスワードをbcrypt()を使ってハッシュ化
]);
$profile = Profile::create([
    "name" => $name,//文字列型の変数(名前が格納)
    "description" => $description, //文字列型の変数(自己紹介が格納)
    "user_id" => $user->id,
    "user" => $user
])

```

# 取得
```(親から子)example.php
$user = User::find(1)->with("profile"//Modelで指定したメソッド名);
$profile = $user->profile;//Modelで指定したメソッド名
```

```(子から親)example.php
$profile = Profile::where("name", $name)->find();
$user = $profile->user;
```
**注意**
- where/getを使うと戻り値はCollection型になるのでforearchで1個づつ取り出してリレーションを参照しなければならない。
VIVEトラッカー(Ultimate)が正常にトラッキングしなくなったら

# VIVEトラッカー(Ultimate)が正常にトラッキングしなくなったら

VIVEトラッカー(Ultimate)が正常にトラッキングされないことがよくあります。
そのときの確認手順をまとめてみました。

今回は、左足首のトラッカーが正常に動いていない状況を仮定して、説明します。

# VIVE Managerでトラッカーの状態を確認する

スマホでトラッカーの状態を確認てみましょう！[^why_smartphone]

`VIVE Manager` を起動し、 `デバイス` から使用中のヘッドセットを選択してください。

`入力 > モーショントラッカー` を開くと、以下のような画面になります。

| <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/9b80c648-495a-be17-0920-9434f6d387a4.png" /> |
|---|
| VIVE Managerでトラッカーの状態を確認 |

上図の場合、 `右足首` と `腰` は `トラッキング` と表示されています。これはトラッキングが正常にできているという意味です。
`左足首` は `移転中` と表示されています。これは **トラッキングが正常にできていない** という意味です。[^relocation]


詳細ページを開くと、左足首に `！` がついていることがわかります。

| <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/e702e010-d672-f41d-9f25-4ee931976f5b.png" /> |
|---|
| VIVE Managerでトラッカーの状態を確認 |


# トラッカーを外す

左足首からトラッカーをいったん外します！
ストラップごと外すと再装着が大変なので、トラッカー本体のみを外しましょう。
トラッカーの両側にあるボタンを押せば、ストラップからトラッカー本体のみを外せるので便利です！

| <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/4950ca1e-d677-8370-9932-570597db67fc.png" /> |
|---|
| 両側のボタンを押してトラッカーをストラップから外す |

| <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/1b386baa-be29-e4ce-160c-156058b92944.jpeg" /> |
|---|
| ストラップからトラッカーが外れた様子 |


# トラッカーを胸の前で保持する

足首から外したトラッカーを、胸の前に持っていき数秒保持してください。
トラッカーが認識されたら、ゆっくりと下ろして左足首に再装着します。

| <img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/5c312afa-866f-3e58-e8cf-34822e5f8c72.png" /> |
|---|
| 図転載: https://www.vive.com/jp/support/ultimate-tracker/category_howto/cant-see-tracker-when-attached-to-lower-body.html |

これでOKです！

ゆっくり下ろさないと、再びトラッキングがロストする可能性があるため、丁寧にやることをオススメします！

# さいごに

本記事作成にあたり、以下のページを参考にさせていただきました。
ありがとうございました！

- https://www.vive.com/jp/support/ultimate-tracker/category_howto/settinng-up-vive-ultimate-tracker.html
- https://www.vive.com/jp/support/ultimate-tracker/category_howto/cant-see-tracker-when-attached-to-lower-body.html

[^why_smartphone]: スマホを使わなくても、VIVE XR Elite内の設定メニューでも同様の確認ができます！ただそれだとヘッドセット装着者しか操作できないというデメリットがあります。スマホであれば、装着者以外の人がサポートしやすいので、スマホの利用をオススメします！

[^relocation]: VIVE Managerでは `移転中` と表示されますが、VIVE XR Eliteの設定メニューだと `リロケーション` と表示されました。表記ゆれがあるようです。
MuseScore の歌詞入力支援ツールを作成

## 出来上がったもの

サイトは https://nakadanobuhiro.github.io/LyricsInputMuseScore/ で公開しています。
ソースは https://github.com/NAKADANobuhiro/LyricsInputMuseScore から取得できます。

## 使い方

1. 漢字を含む歌詞を入力して、[ひらがなに変換]を押してください。すでに歌詞がひらがなになっている場合は、"2. ひらがなの歌詞"に入力してください。
2. ひらがなに変換された歌詞が表示されます。思い通りにひらがなに変換されているか確認・修正した後に、[空白を挿入]を押してください。
3. 空白の入った歌詞が表示されます。[クリップボードにコピー]を押してください。
4. [MuseScore](https://musescore.org/ja) で最初の音符を選択して[Crtl]+[L]で歌詞入力状態になったら、[Ctrl]+[V]を繰り返し押して貼り付けてください。

## 作成の動機

[MuseScore](https://musescore.org/ja)は、無料で使用できる楽譜作成ソフトウェアです。
大変重宝しているのですが、歌詞を入力する際は、音符をクリックして、[Crtl]+[L] で歌詞を一音分入力して、スペースを押して、次の一音分の歌詞を入力して、という作業をひたすら繰り返す必要がありかなり手間がかかります。 (私は DAW で作成した Standard MIDI ファイルを読み込んでいるので、楽譜の作成には使っていません。)
いろいろ調べてみたところ、MuseScore で歌詞を入力するには、歌詞の一音ごとにスペースを入れて、貼り付けるという方法があることがわかりました。
そこで、入力した歌詞から、貼り付け用のテキストを作成するツールを作ってみました。

## 仕組み

### GitHub Pages

- 無料でホスティングできるため、GitHub Pages を使用しました。
- よって、HTML と JavaScript で動きます。

### Jekyll

- サイトは Jekyll で作成しています。
- GitHub pages サポートがしているからです。
- テーマは初期設定の minima を使用しており、変更したいのですが方法が良くわかっていません。

### Gooラボのひらがな化API

- 漢字からひらがなへの変換に[Gooラボのひらがな化API](https://labs.goo.ne.jp/api/jp/hiragana-translation/)を使用しています。
- 存在を知らなかったのですが、GitHub Copilot に "漢字を含む文章をひらがなに変換する関数を作成" と指示したところ候補として表示されたので使用することにしました。
- 私の取得した API キーが丸見えですが、悪用しないでください。
- 本当は漢字はひらがなに、カタカナはそのままにしたかったのですが、すべてひらがなに変換されてしまいました。
- また、"明日"は、"あした"と"あす"と"みょうにち"の読み方があるように、思ったように変換できないケースもあり、これは適宜修正することにしました。(童謡 "[シャボン玉](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%A3%E3%83%9C%E3%83%B3%E7%8E%89_(%E5%94%B1%E6%AD%8C))"でも、"**風風**吹くな"は、"**かぜかぜ**ふくな"ではなく、"**かぜふう**ふくな"となってしまいます。)

### 空白の挿入

- ひらがなの間に空白を入れればいいのですが、拗音("ゃ","ゅ","ょ")、促音("っ")、長音("ー")、外国語の表記などで使用される("ぁ","ぃ","ぅ","ぇ","ぉ")は、単独では発音しないので、その前には空白を入れないようにしています。
- なお、長音には"おう"、"かあ"、"おお"などが含まれる場合もあると思いますが、判断が難しいので無視しています。
- 撥音("ん")は、音符を割り当てるケースと、割り当てないケースががあるようなのですが、割り当てるケースを採用しました。(割り当てないケースとしては、童謡"[あめふり](https://ja.wikipedia.org/wiki/%E3%81%82%E3%82%81%E3%81%B5%E3%82%8A)"の"ピッチピッチ チャップチャップ**ランランラン**"。)

## GitHub Copilot

- 本プログラムは VS Code で GitHub Copilot を使用して作成しました。
- コメントで指示を記述し、候補を表示してもらい採用を判断する方法で、かなり役に立ちました。
- 特に markdown のテキストを書いている途中で、それから先に書くだろう文章の候補を表示する機能は、ChatGPT よりも使い勝手が良いと感じました。(Qiita でも GitHub Copilot に接続できるようにしてほしい。)
AWS Athenaでテーブル作成

## はじめに
前回AWSのS3とAthenaの概要を記事にしましたが、実際AthenaにSQLを記載して実行することもありましたので、記事にします。
今回はテーブル作成になります。
理解できているところとできていないところもあるのですが、分かっているところを主に記載します。

## AWS Athenaとは
AWS上のストレージにあるCSV、JSON、Parquetファイルなどをまとめて１つのテーブルと見立てクエリを発行してデータを抽出するサービスです。
SQLを使います。

## 設定（クエリの結果）
Athenaの場合はクエリの結果をS3に吐き出しますが、吐き出し先のフォルダの設定をまずします。
Amazon Athenaからクエリエディタの「設定」タブ→「管理」ボタン選択して「クエリの結果の場所」を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3532455/01cccf52-3e01-c821-ab85-b94dccfc33db.png)
## クエリの記述
クエリの結果の場所を指定後は、クエリを書いていきます。
下記の赤枠にSQLを書いていくことでデータベースやテーブルを作成するクエリやデータを条件に従って取得するクエリなどを書くことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3532455/01e3322f-5bc8-56b0-cbd2-afef03ad5100.png)

## テーブル作成
AthenaはSQLでクエリを作成するのですが、下記のような形式で記載します。
```diff_SQL
CREATE EXTERNAL TABLE IF NOT EXISTS `データベース名`.`テーブル名` (
  `FIELD1` string,
  `FIELD2` string,
  `FIELD3` string,
  `FIELD4` string,
  `FIELD5` string,
  `FIELD6` int,
  `FIELD7` string,
  `FIELD8` string,
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES ('field.delim' = ',')
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
          OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 'S3Path'
TBLPROPERTIES (
    'classification' = 'csv'
    , 'skip.header.line.count'='1'
);
```
### CREATE EXTERNAL TABLE IF NOT EXISTS
外部テーブルを作成するときの構文で、EXTERNALは外部を指します。
IF NOT EXISTSは作成済のテーブルを作ろうとするエラーを防げます。

FIELED1～FIELD8は列名を指して、string、intは列の型を指定します。
```diff_SQL
CREATE EXTERNAL TABLE IF NOT EXISTS `データベース名`.`テーブル名` (
  `FIELD1` string,
  `FIELD2` string,
  `FIELD3` string,
  `FIELD4` string,
  `FIELD5` string,
  `FIELD6` int,
  `FIELD7` string,
  `FIELD8` string,
)
```
### ROW FORMAT SERDE
SERDE（シリアライザー/デシリアライザー）はAthenaが読み込んだデータを取り扱う際のルールらしいです。
```diff_SQL
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
```
### WITH SERDEPROPERTIES
データの読み書きに関する詳細を定義できるらしいです。
'field.delim' = ','はファイルを読み込む際の区切り文字をカンマに指定できます。
```diff_SQL
WITH SERDEPROPERTIES ('field.delim' = ',')
```
### STORED AS
テーブルのファイル形式を指定します。
```diff_SQL
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
          OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
 ```         
### LOCATION
テーブルのを作成するもとのデータがあるS3の場所を指定します。
```diff_SQL
LOCATION 'S3Path'
```
### TBLPROPERTIES
'classification' = 'csv'はファイルの種類を指して
'skip.header.line.count'='1'はヘッダー行１行をスキップして読み飛ばします。
```diff_SQL
TBLPROPERTIES (
    'classification' = 'csv'
    , 'skip.header.line.count'='1'
);
```

最後までお読みいただきありがとうございます。
エンジニアだからこそヒューマンスキルを磨く:デール・カーネギーの教え：誠実な感謝の力 💫🤲



こんにちは、Qiitaの皆さん！デール・カーネギーの名著から学ぶ、ヒューマンスキル向上の秘訣を続けてご紹介します。今回は第2章、「心からの誠実な感謝の表現」についてです。

この記事を書こうと思ったきっかけ、および第１章は[こちら]("https://qiita.com/TakanoriVega/items/c3f44163febd5dfab4e2")です。

## 第2章: 心からの誠実な感謝を示す 🌟

### 人間の原動力や強い動機の源

- 人は他人から感謝されることを深く望んでいます。
- 私たちは誰しも、褒められたり、成果を認められることを喜びます。
- 文明全体が、人々が自分自身を重要と感じたいという欲求に基づいていると考える人もいます。

### 承認と賞賛の重要性

- 承認と賞賛への渇望が、私たちを困難な目標に挑戦させ、創造的な業績を達成させます。
- 誰かを高く評価するために、豪華な肩書きを用意する必要はありません。
- 「ありがとう」とか「ごめんなさい」といった簡単な言葉でも、心からの賞賛を示すことができます。

### 誠実さと正直さ

- 人に対して偽りの褒め言葉を浴びせるのではなく、本当に良いと思う点を見つけて伝えましょう。
- 自分自身のことは一旦忘れ、目の前の人の長所に注目することが重要です。

### 相手を大切にすること

- 他人を重要だと感じさせるよう心掛けましょう。
- ラルフ・ワルド・エマーソンのような考え方も参考になります。彼は出会う人すべてが自分より何かしら優れていると考え、常に学ぶべき点を見つけていました。

### 黄金律の実践

- 「自分がされたいと思うように、他人にも接する」という黄金律を心に留めておきましょう。
- 疲れているように見えるサービス業の従業員に、感謝の言葉をかけて彼らの一日を明るくしましょう。

---

日常に感謝の言葉を散りばめてみましょう。人々が感謝を受けたときの前向きな反応を見ると驚かされます。やがて、他人から好かれ、共に働きたいと思われる人物になる。
そして何より、周りの人々の人生にポジティブな影響を与えることができます。
次回は第3章ですので、お楽しみに✨🌈
インメモリ キーバリュー型 NoSQL「Redis」コマンドの使い方

![redis-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288256/fef785c5-c8b6-0074-640d-2ce94c3720a6.png)

Redisはキーバリュー型のインメモリデータベースです。

#### 1. Redisの導入（前準備）
※Redis公式サイトよりインストール方法を参照。

:::note
Install Redis：https://redis.io/docs/install/install-redis/
:::

#### 2. Redisクライアントの起動
- redis-cliで、Redisクライアント(CUI)を起動する。
```rb
$ redis-cli
> ping
PONG
```

#### 3. Redisコマンド

:::note
バリューの種類によって、コマンドが異なる。
- ストリング型（string）
- リスト型（list）
- ハッシュ型（hash）
- セット型（set）
- ソート済みセット型（zset）

:::

##### ■ ストリング型（string）
キーとバリューが1対1の関係で管理されるデータ型。
- set key value: 指定キーに対するバリュー（値）を登録
- get key: 指定キーに対するバリュー（値）を取得

```rb
> set x 100
OK

> get x
"100"
```

##### ■ リスト型（list）
１つのキーに対してリスト（複数の値を持つ）により管理されるデータ型。
- lpush key value：指定キーのリストの先頭（左）から要素を追加
- rpush key value：指定キーのリストの末尾（右）から要素を追加
- lrange key start stop：指定した範囲（start ～ stop）のリスト要素を取得
  ※stopに-1を指定すると最後から1番目という意味になる
- lpop key：指定キーのリスト（値）の先頭（左）から要素をpop(取得+削除）
- rpop key：指定キーのリスト（値）の末尾（右）から要素をpop(取得+削除）
- ltrim key start stop：指定した範囲（start ～ stop）のリスト要素以外を削除

```rb
> lpush y 1 2 3
(integer) 3
> rpush y 4 5
(integer) 5
> lrange 0 -1
1) "3"
2) "2"
3) "1"
4) "4"
5) "5"
> lpop y
"3"
> rpop y
"5"
> lrange y 0 -1
1) "2"
2) "1"
3) "4"
> ltrim y 0 1
OK
> lrange y 0 -1
1) "2"
2) "1"
```

##### ■ ハッシュ型（hash）
親キー、子キー（フィールド）、バリュー（値）により管理されるデータ型。
- hmset key field value：指定キー＋指定フィールドのバリュー（値）を登録
- hmget key field：指定キー＋指定フィールドから、バリュー（値）を取得
- hincrby key field number：指定キー＋指定フィールドのバリュー（値）を加算／減算

```rb
> hmset bike1 model 'scooter' brand 'vespa' type 'primavera' stocks 10
OK
> hmget bike1 type stocks
1) "primavera"
2) "10"
> hmget bike1 brand
1) "vespa"
> hgetall bike1
1) "model"
2) "scooter"
3) "brand"
4) "vespa"
5) "type"
6) "primavera"
7) "stocks"
8) "10"
```

##### ■ セット型（set）
セットはメンバーのコレクションで管理されるデータ型。
- sadd key member：指定セット（キー）に新しいメンバーを追加
- scard key：指定セット（キー）のメンバーの登録数を取得
- smembers key：指定セット（キー）の全てのメンバーを取得
- sinter key1 key2 ...：2つ以上のセットを共通に持つメンバーのセット(積)を取得
- srem key member：指定キーのセットから指定するメンバーを削除

```rb
> sadd group1 user1 user2 user3
(integer) 3
> sadd group2 user1 user3
(integer) 2
> scard group1
(integer) 3
> smembers group1
1) "user3"
2) "user2"
3) "user1"
> sinter group1 group2
1) "user3"
2) "user1"
> srem group2 user3
(integer) 1
> smembers group2
1) "user1"
```

##### ■ ソート済みセット型（zset）
ソート済みセットはメンバーとスコアのコレクションで管理されるデータ型（並びはスコア順）。
複数のメンバーが同じスコアを持つ場合、メンバー名の辞書順に並べられる。
- zadd key score member：指定のソート済みセット（キー）にスコアとメンバーを追加
- zrange key start stop：指定のソート済みセット（キー）からメンバーを取得

```rb
> zadd sgroup1 100 user1
(integer) 1
> zadd sgroup1 180 user2
(integer) 1
> zadd sgroup1 150 user3
(integer) 1
>zrange sgroup1 0 -1

```

##### ■ 共通
- keys *：登録済みのキーの一覧を取得
- exists key：キーが登録済みかを確認（あれば1を返す）
- type key：バリュー（値）の種類を確認（string list set zset hash）
- del key：指定のキーを削除
- info：Redisサーバーの情報を取得

```rb
> keys *
1) "sgroup1"
2) "group2"
3) "group1"
4) "bike1"
5) "y"
6) "x"

> type x
string

> type y
list

> type group1
hash

> type group1
set

> type sgroup1
zset

> del x
(integer) 1

> info
（#Server, #Clients, #Memory, #Persistence, #Stats, #Replication, #CPU, #Cluster, #Keyspaceが表示される）
```

---
参考：Redis公式サイト
https://redis.io/


以上
シーンに存在する同じコンポーネントに共通して発火させるイベントをインスペクタで管理したい

# [Unity]シーンに存在する同じスクリプトに共通して発火させるイベントをインスペクター上管理する方法

## 使用例

例えばTalkクラスがあったとします。

そのTalkクラスはMobゲームオブジェクトに付随するコンポーネントになります。

そのTalkクラス群に共通して発火させたい一意のイベントを

カスタマイズしたいときはどうすればよいのか？

以下のようなコードを考えてみました。
``` C#
using UnityEngine;
using UnityEngine.Events;
//継承用
public class StaticEventBehavior : MonoBehaviour {
    public static System.Action<int> staticAction;
 public IDEvents iDEvents;
   void Awake() {
      staticAction+=(x)=>iDEvents.Execute(x);
    }
   public void StaticEventCall(int id=0){
staticAction(id);

    }
}
```
UIeventクラス

``` C#
[System.Serializable]
public class IDEvents{
    [Serializablenb]
    public struct pair
    {
    public DelayEvents Event;
    public int Id;
    }
   public List<pair> pairs;
public void Execute(int id){
    foreach (var item in pairs)
    {if (item.Id.Equals(id))
    {
        item.Event.Execute();
    }
    }
}
}
[System.Serializable]
public class DelayEvents
{
    public List<DelayEvent> delayEvents;
    public void Execute(){
       delayEvents.ForEach(x=>x.Execute());
    }

}
```

このStaticEventBehaviorをTalkクラスが継承して使えば

シーンに存在する同じコンポーネントに共通して発火させるイベントをインスペクター上で

管理する機能を実装することができます。

例えば、Talkクラス内の会話終了時。開始時の部分に共通して発火できる

イベントを差し込んだり・・・

また、HPクラス、Attackクラスなどのように、たくさんのゲームオブジェクトに付随される可能性のあるコンポーネントには

以下のクラスを継承して共通発火イベントを管理してみてもいいかもしれません。

このコードを使える場面は限られてるかもしれませんが。

特にそのイベントの結びつけが、コード上で行うとめんどくさくなるというケースでは

適宜インスペクターでカスタマイズできるようになるため、適材適所で使ってみてください
オセロのロジックをReact+TypeScriptに落とし込んだ

React+TypeScriptの勉強がてらオセロを作成してみたら案外苦戦したので、概要とReact特有の難しかった点を書いておきます。
- ステップバイステップで作成してみよう！みたいな内容ではありません(需要があったら作ります)
- デザイン性は皆無です。あくまでロジックに焦点を当てて作成しました。
- 初学者ゆえ、もし不備がありましたら遠慮なくお申し付けください。

# 成果物
Github Pages (実際にプレイできます)
https://yudatchshouga.github.io/react-test/
Github (ソースコード)
https://github.com/yudatchshouga/react-test
制作期間：2日

![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643756/f6d9a392-4269-df3b-a2d2-3d79b18bfdb0.gif)

# 概要
オセロのルール周りに関しては省略します。
- 盤面は4*4である(コード上で簡単に変更可能)
- 盤面には現在のプレイヤーが駒を置ける場所をハイライト表示する
- 盤面の上部にはゲームステータスが表示される
    - プレイヤーが駒を置ける場合、`現在のプレイヤー: ⚫︎`のように表示
    - 片方のプレイヤーが駒を置けなくなったら`パス`と表示
    - 両者駒を置けなくなったら`ゲームオーバー`と表示
- パスが発生した場合、1秒間ステータスに`パス`と表示されターン交代する
- CPUは今回は実装していない(チャレンジ予定)

余談ですが、ChatGPTに聞いたところ、駒を置ける箇所の精査にはどうしても$O(N^3)$かかってしまうらしいです($N$は盤面の一辺のサイズ)。

# React特有の難しかった点

### 状態管理
最初はGameという変数に色々な状態を集約して、Gameを1つの状態として扱ってました。ですが、様々な判定を加えていくにつれて再レンダリングが何重にも発生してしまうという事態になったので、状態を分離しました。最終的には以下の状態を採用することにしました。
```tsx
// 盤面
const [board, setBoard] = useState<string[][]>(initBoard);
// 盤面に駒が置けるかどうかのフラグ
const [putables, setPutables] = useState<boolean[][]>(initPutables);
// プレイヤー
const [player, setPlayer] = useState<string>(initPlayer);
// ステータス
const [gameStatus, setGameStatus] = useState<string>("playing");
```
なお、ステータスは以下のように定義しました。

- 駒を置ける状態　→　`playing`
- 現在のプレイヤーが駒を置けず、次のプレイヤーが駒を置ける状態 → `pass`
- 両者が駒を置けない状態 → `gameover`

### 状態更新と`useEffect`について

Reactでは`useState`の`setXxx`で状態更新をします。
単純な更新ならいいのですが、オセロのようにロジックが複雑になってくると、

1. `board`の状態を更新(駒をひっくり返す)
2. `player`を更新(ターン交代)
3. `board,player`を使って`putables`の更新(置ける場所の確認)
4. `putables`を使ってステータスを更新(`pass, gameover`の判定)

のように更新された状態を用いて別の状態を更新する処理が多発します。

この時、愚直に1,2,3,4と処理を順番に書くと、2で`player`の更新が終わっていないのに3の処理に進んでしまうというバグが起きてしまいます。
どうやらReactの状態更新処理は非同期処理であることに起因しているようです。

これらの問題を解決してくれるのが`useEffect`です。
先ほどの2→3の処理が順番に行われない問題は以下のように書くことで解決します。

```tsx
// プレイヤー交代したら置ける場所を更新する
useEffect(() => {
    // 置ける場所を探す
    setPutables(() => calculatePutables(board, player));
}, [player]);
```

このコードでは、`player`を監視対象に設定し、`player`が変更されたら`useEffect`の中身が実行されます。

このように`useEffect`をうまく利用することで、非同期処理である状態更新の順序をうまく制御することができます。
`useEffect`は、パスの際に1秒待機する処理を書く際にも活躍してくれました。

# 最後に
今回はオセロをまる2日ほどかけて作成してみました。最終的にはCPUやAIを実装したいので、ロジックはバックエンドに移すかもしれませんが、とりあえずReactオンリーで書きました。
あと、本当はカッコつけて色んなクラスを作成して作っていたのですが、基礎ができていないうちにやるもんじゃないなと思いました。(自戒)

最近X始めたので、フォローいただけると嬉しいです！
https://twitter.com/yudatchshouga
関数型インターフェース、ラムダ式（Java Silver）

# 最初に
この記事は、以下の書籍を通じてJava silverの合格に向けて自分が学んだ内容を体系的にアウトプットする記事である。（目指せ年始合格！）
[徹底攻略Java SE 11 Silver問題集[1Z0-815]対応](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5Java-SE-11-Silver%E5%95%8F%E9%A1%8C%E9%9B%86-1Z0-815/dp/4295007625/ref=asc_df_4295007625/?tag=jpgo-22&linkCode=df0&hvadid=342700130622&hvpos=&hvnetw=g&hvrand=9715255718806805548&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009303&hvtargid=pla-830348236008&psc=1&mcid=e12ce628cc5a33b29a77da3a85a6cdf0&th=1&psc=1)

# 勉強記録
### ラムダ式とは

- **関数型インターフェース**を実装した**匿名クラス**の簡易的な記述法。

```clike
//使い方の一つ
関数型インターフェースの型　変数名　=（引数）->｛処理｝;
```

```clike
//関数型インターフェース
interface Sample{
	void print(int num);
}

public class Main{
	public static void main(String[] args){
		//関数型インターフェースの型　変数名　=（引数）->｛処理｝;
		Sample sample = (num) -> System.out.println(num);
		sample.print(10);
	}
}
```

- ラムダ式は、関数型インターフェース・ローカルクラス・匿名クラスの仕組みを利用。

### 関数型インターフェースとは

- 実装が必要なメソッド（抽象メソッド）を一つだけ持つインターフェース。

```clike
public interface SampleInterface1{
    public void sample1(String sample);
}

//アノテーションで明示しても良い
@FunctionalInterface
public interface SampleInterface2{
    public void sample2(String sample);
}
```

- staticメソッドやdefaultメソッドは定義されていてもOK。
- よく使われる関数型インターフェースは以下を参考
    - [java 標準関数型インターフェース](https://qiita.com/nullponn/items/3ded05040e732469bb19)    


### ローカルクラスとは

- メソッドの処理中でクラスを宣言して利用できる仕組み。

```clike
public static void main(String[] args) {

  class Local {
    public void sayHello() {
      System.out.println("Hello!");
    }
  }

  Local local = new Local();
  local.sayHello(); // Hello!
}
```

- インターフェースを実装したローカルクラスは以下。

```clike
public static void main(String[] args) {

  class Local implements Runnable {
    @Override
    public void run() {
      System.out.println("Hello Lambda!");
    }
  }

  Runnable runner = new Local();
  runner.run(); // Hello Lambda!
}
```

### 匿名クラスとは

- インターフェースを実装したローカルクラスの宣言を省略する仕組み。

```clike
public static void main(String[] args) {

  Runnable runner = new Runnable() {
    @Override
    public void run() {
      System.out.println("Hello Lambda!");
    }
  };

  runner.run(); //Hello Lambda!
}
```

- 上記の匿名クラスを、さらに簡略化したのがラムダ式。

```clike
public static void main(String[] args) {
	Runnable runner = () -> { System.out.println("Hello World!"); };
	runner.run(); //"Hello World!"
}
```

- 上記より、ラムダ式は、インターフェースを実装したインスタンスを生成する式と言える。

### 参考にしたサイト

- [【Java Silver】 関数型インターフェイス、ラムダ式対策](https://qiita.com/midori-game/items/63a1846192159fbe8f2c)
- [関数型インターフェースについて学習したのでまとめてみた。](https://qiita.com/j1403239/items/fc7b9600382f09ea979a)
- [java 標準関数型インターフェース](https://qiita.com/nullponn/items/3ded05040e732469bb19)
- [Java8のラムダ式を理解する](https://qiita.com/sano1202/items/64593e8e981e8d6439d3)

# 感想

- 関数型インターフェースは、完全に初見だった。（問題集のこの章の問題のほぼ全てがわからなかった。）
- ラムダ式も自分は、既存のコードを見ながら見よう見まねで使っていた部分が多かったので、今回でラムダ式が何をしているかの理解を深めることができてよかった。
docker環境でGCPのsecret managerを使おうとしてハマった記録

## ハマった詳細
docker環境でGCPのSecretManagerの値を参照しようとすると下記エラーが発生し、権限不足でエラー
```bash
google.api_core.exceptions.PermissionDenied: 403 Permission 'secretmanager.versions.access' denied for resource 'projects/pj-love-shizuka/secrets/API_KEY/versions/1' (or it may not exist).
```

## 解消した方法
1. GCPの「IAMと管理」ページで「Secret Manager のシークレット アクセサー」ロールを付与
    ![スクリーンショット 2024-01-06 20.09.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121605/75fea245-dd2c-62c3-6505-7c7b03bf37a4.png)
2. 3分程待機（←3分も待たんで良いかもだが、少し時間差で反映されるためせっかちな人は注意）

解消方法はシンプルですが、このエラーで1時間程溶かしたので同士はご注意ください。色々と調べていると下記のような情報にたどり着き、謎がどんどん深まっていきます。
- [secretmanager.SecretManagerServiceClient()に引数渡せ](https://stackoverflow.com/questions/72983320/why-do-i-get-secretmanager-versions-access-denied-in-gcp)
- [gcpデフォルトのサービスアカウントじゃないと参照できない](https://qiita.com/MasatoEmata/items/7e7ed4e9ca0a965168c0)

上記の兄さん達と今回は微妙に条件が違う?ためか解消できずに「secretmanager」モジュールの関数やクラスの引数などの値の与え方が悪いかもと思い色々試しました..


## 実装しているコード

#### 1. ローカルのzsrhcに追加した環境変数
```bash
export GOOGLE_APPLICATION_CREDENTIALS="/Users/bokudoraemon/dev/project_configs/gcp/{gcpサービスアカウントの鍵}.json"
```
#### 2. docker-compose.ymlの設定
```yaml
version: "3.7"
services:
  web:
    build:
      context: ./
      dockerfile: Dockerfile.local
    env_file:
      - ./.env
    command: "uvicorn main:app --host 0.0.0.0 --port ${PORT} --reload"
    environment:
      GOOGLE_APPLICATION_CREDENTIALS: /code/gc.json
    volumes:
      - .:/code
      - ${GOOGLE_APPLICATION_CREDENTIALS}:/code/gc.json:ro
    ports:
      - "${PORT}:${PORT}"
    networks:
      - default
```
#### 3. pythonでSecretManagerの利用
```python3
from google.cloud import secretmanager

def get_secret_key(project_id, secret_ver, secret_name):
    client = secretmanager.SecretManagerServiceClient()
    name = client.secret_version_path(project_id, secret_name, secret_ver)
    response = client.access_secret_version(name=name)
    return response.payload.data.decode('UTF-8')

project_id = "pj-love-shizuka"
secret_ver = "1"
API_KEY = get_secret_text(project_id, secret_ver, "API_KEY")
```

## ついでに、
![スクリーンショット 2024-01-06 20.32.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121605/53662f10-7b95-0fd1-e072-5845c36e16c1.png)
上記スクショの赤枠の部分について、pythonのコードで呼び出すときはGCPのproject-idを指定して呼び出すのにGCPのSecretManagerのコンソール画面では数値になっているのでここが悪いのか？という疑念が浮かびます。

結論としは数値になっていることはスルーでおｋで、僕が記載しているpythonコードで参照可能となっています
【Git】git clone後に新しいリモートリポジトリのURLを設定する方法

# はじめに
リモートリポジトリを変更したいときに、
実行するgitコマンドを本記事では記載します。


### 1. 設定されているリモートリポジトリを確認
次のコマンドで現在設定されているリモートリポジトリを確認する。
```
git remote -v
```

### 2. リモートリポジトリの変更
リモートリポジトリを変更したい場合は次のコマンドを実行する。

```
git remote set-url origin [変更後のリポジトリのURL]
```

リポジトリのURLは「Code」の部分をクリックすると表示されます。

![sampleURL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/7c2e5c28-5791-5820-fab7-2ae66a3c7e7e.png)


### 3. 変更されたリモートリポジトリの確認
もう一度以下のコマンドを実行して、リモートリポジトリが変更された事を確認します。
```
git remote -v
```
RHEL8でdnfがエラーになった。

## はじめに

RHEL8環境でdnfがエラーになったのでやったことを残しておきます。

## 環境
RHEL8.9

## やったこと

dnf updateを実行するとエラーになるのでsubscription-managerでホストの再登録を行ったらupdateが通るようになった。

```
[root@rhel81 ~]# dnf update
Updating Subscription Management repositories.
Red Hat Enterprise Linux 8 for x86_64 - BaseOS  486  B/s | 361  B     00:00
Errors during downloading metadata for repository 'rhel-8-for-x86_64-baseos-rpms':
  - Status code: 403 for https://cdn.redhat.com/content/dist/rhel8/8/x86_64/baseos/os/repodata/repomd.xml (IP: 23.32.12.83)
Error: Failed to download metadata for repo 'rhel-8-for-x86_64-baseos-rpms': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried
[root@rhel81 ~]#
```

```
[root@rhel81 ~]# subscription-manager register --force
Unregistering from: subscription.rhsm.redhat.com:443/subscription
The system with UUID ******************** has been unregistered
All local data removed
Registering to: subscription.rhsm.redhat.com:443/subscription
Username: ****
Password:
The system has been registered with ID: ********************
The registered system name is: rhel81.****.net
[root@rhel81 ~]#
```

```
[root@rhel81 ~]# dnf update
Updating Subscription Management repositories.
Last metadata expiration check: 0:04:01 ago on Sat 06 Jan 2024 08:09:41 PM JST.
Dependencies resolved.
Nothing to do.
Complete!
[root@rhel81 ~]#
```

## おわりに

テスト用の環境で起動していない期間があったのでその影響かもしれない。常時起動しているサーバではあまり起きにくいかもしれません。
Python: コンソール上で抜けている文字を当てるゲームを作った

## 開発環境
- Visual Studio Code (Version: 1.85.1)
- Python 3.12.1
- aarch64 GNU/Linux (Dockerコンテナ内部)

## 概要
アルファベット小文字(a-z)から削除された1文字を当てるクイズを作りました。

## コード

```python
import random
from string import ascii_lowercase

WIDTH = 5


def generate_problem():
    # アルファベットリストを生成
    alphabet = list(ascii_lowercase)

    # ランダムにアルファベットを選択
    selected_letter = random.choice(alphabet)

    # 選択したアルファベットをリストから削除
    alphabet.remove(selected_letter)

    # 残りのアルファベットをシャッフル
    random.shuffle(alphabet)

    return selected_letter, alphabet


def print_problem(alphabet):
    # 問題を表示
    print("[問題]: 抜けているアルファベット1つを答えてください")

    for i, c in enumerate(alphabet):
        print(c, end="")
        if i % WIDTH == WIDTH - 1:
            print()


def main():
    # 問題を生成
    correct_answer, shuffled_alphabet = generate_problem()

    # 問題を表示
    print_problem(shuffled_alphabet)

    # ユーザーの入力を受け取る
    user_input = input(" >> ")

    # 答えをチェック
    if correct_answer == user_input:
        print("おめでとう!!正解です")
    else:
        print("残念!!不正解です")

    print(f"正解は{correct_answer}でした")


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

## コンソール画面
- 実行直後
![Screenshot 0006-01-06 at 20.14.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611466/41fea0f9-dc45-3fba-d075-ca9ce1c45901.png)

- 回答後
![Screenshot 0006-01-06 at 20.17.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611466/94c19c2a-651c-c048-6d88-f38c02b505f8.png)
【2024年最新】若手エンジニア質問法【人気No1】

# わからんことが多すぎる
　仕事をしていると、どうしても有識者・上司・先輩に聞かないといけないことが多すぎる！
技術的なこと以外にも、「そもそもこの仕事どう進めたらいいんすかね？」「これそもそも有識者が誰なのかわかります？」「こんなこと言われたんですけど回答どうしましょう？」などなど・・・

# 有識者たちは捕まらない
　彼ら彼女らをとっつかまえて、時には指示を仰ぎ、時には**承認という名の後ろ盾**を取り、また時には一緒に頭をひねる必要があるのですが。
 　すごい人たちはよく会議をしています。有識者なので色んな所に呼び出されてます。つまり、我々下っ端の個人的な質問をぶつける時間はそれらの隙間時間を縫うように作りだすしかないのです。

# 効率的な質問方法
　ということで、最近やってみたら結構スムーズにいくようになった質問の仕方。
 1. sakuraエディタを起動する
 1. 質問する文章を全部書く。**口語で。**
 1. ついでに、質問の発端になったこと（チャットの文章、資料、だれそれからの指示）も書く
 1. チャットの文章ならコピペ張り付ける
 1. **印刷する**
 1. 印刷した紙を手に上司を捕まえる

# いいところ
1. 質問内容が全部口語で書いてあるので読み上げるだけで質問が終わる。時短になる。
1. 印刷した紙に回答をメモれるので、後からメモを見返したときにわかりやすい。
1. 複数個質問があるとき、 ~~相手が優しい場合は~~「で、次の質問は？」とか言いながらメモをのぞき込んでくれるので話が早い

# よくないところ
1. 紙メモが嫌い、使い慣れていないと単純に不便
1. **ぺら紙１枚（物理）** なので整理しないと失くす

# まとめ
紙メモと合わせ技で使うと結構便利だな、という気付きがあったので書いてみました。
「脳は時間を正しく歪める」

物理法則は、時間の一様性がある。物理法則は時間軸を平行移動しても、物理法則が保たれる。
一方、ヒトが感じる時間はそのような一様性はない。

最近読んだ本の２つで、時間の感覚について述べているのを見つけたので紹介する。

## 概要
・時間は報酬の選択に関係する。
・行動を選択するときには、報酬期待値を用いている。
・予測のつかない未来に対して行動を選択していく積み重ねの中で、報酬期待値の計算式じたいが設定されていく。
・「報酬の選択には時間のコストが織り込まれる」
・そのため、物理法則として時間ではなく、報酬の選択に影響するのは歪められた時間である。
「ここで提案したモデルは、私たちの歪んだ時間感覚を、時間コスト的に適切な意思決定を行うことの自然な結果として合理的に説明しうるものである。この理論は、それに関連して、時間の知覚に関わるほかの多くの事実も説明できる（一方、今後理論的に論証されるべき新たな予測も含んでいる）。」（#1 p196）


## 各書籍からの引用
### 1. 「４０人の神経科学者に脳のいちばん面白いところを聞いてみた」第１９話　脳は時間を正しく歪める
「報酬の選択には時間のコストが織り込まれる」
「主観的時間のありかたを説明できるTIMERR仮説」
「TIMERR仮説は時間感覚の誤差も説明する」

### 2.「脳にはバグがひそんでる　進化した脳の残念な盲点」第４章　時間感覚が歪む
「時間差があると因果関係がつかめない」
「時間による割引」
「あなたの時間感覚はあてにならない」
「時間的な錯覚」
「脳はどうやって時間を知るか」
「長期的な思考の効用」

## 両者の指摘の共通点
- 報酬の評価が関係していることが、２つの書籍中の記述で共通している。


## ２の書籍でさらに述べていること
- 脳の中での知覚は、順序さえも入れ替えを行なっている動的なものであることが述べられる。
- 「１秒ほどのこの短い尺度では、脳は時間をかなり勝手に書き換える。時間を歪ませるだけではなく、時系列の中での出来事を削除したり挿入したり、出来事が実際に起こった順序を入れ替えたりしているのだ」
- １００ｍ先のジンバルの奏者が鳴らす音を同時に聞こえるよう、知覚を遅らせている。
- このような知覚的な限界は、審判員によるオフサイドの判定の難しさにもつながっている。「誤審の原因として、人が視線を移すのには１００ミリ秒かかること、２つの出来事が同時に起こったとしたら、自分が注視していた出来事が先に起こったと判断しがちだという二つが挙げられる。」
- フラッシュラグ効果 [閃光遅延効果](https://ja.wikipedia.org/wiki/%E9%96%83%E5%85%89%E9%81%85%E5%BB%B6%E5%8A%B9%E6%9E%9C)

[1] デイヴィッド・Ｊ・リンデン 編著、岩坂　彰 訳　[「４０人の神経科学者に脳のいちばん面白いところを聞いてみた」](https://www.kawade.co.jp/np/isbn/9784309467719/)
第１９話　脳は時間を正しく歪める

[2] ディーン・ブオノマーノ 著、柴田　裕之 訳[「脳にはバグがひそんでる　進化した脳の残念な盲点」](https://www.kawade.co.jp/np/isbn/9784309467320/)

[3] Namboodiri et al., [A general theory of intertemporal decision-making and the perception of time](https://www.frontiersin.org/articles/10.3389/fnbeh.2014.00061/full)
Dale Carnegieの名著を読み解く: ヒューマンスキル向上のための第一歩 📚✨

人間関係のスキル向上に役立つDale Carnegieの名著から、Chapter1を深く掘り下げていきます。

きっかけは、技術ばかりに走る私に社長から**「エンジニアだからこそヒューマンスキルが大事なんだぞ、お前はヒューマンスキルがなってない！」** と言われ、この本を勧められたからです。これからはこの本をChapterごとに自分なりにまとめ、記事にしようと思いました。


この章のキーメッセージは **「批判せず、非難せず、文句を言わないこと」** です。人は感情の生き物で、批判は自尊心を傷つけます。また、侮辱は一生忘れられない恨みに変わることがあります。

## 🛩️ 実例：有名な試験パイロットBob Hooverの話

Bob Hooverはサンディエゴの航空ショーから帰る途中で、突然両エンジンが停止しました。彼は見事な飛行技術で飛行機を着陸させ、搭乗者を救いましたが、飛行機は大きく損傷しました。このエンジン故障の原因は、第二次世界大戦のプロペラ機に誤ってジェット燃料が注がれたためでした。

### 機体を損傷した状況

- 機体は大きく損傷しました。
- でも実はあるメカニックのミスでジェット燃料が注がれました。

### Hooverの反応

- しかしHooverはそのメカニックを怒鳴ったり、非難したりしませんでした。
- 彼はメカニックに**再び自分の飛行機を整備してもらう**ことで、彼への信頼を示しました。

## 🧠 B.F. Skinnerの発見

B.F. Skinnerは以前に、良い行動に報酬を与えられた動物は、悪い行動に罰を受ける動物よりも効果的に学習することを発見しました。これは人間にも当てはまります。人は理性よりも感情によって動かされるため、批判することは彼らの行動を変える励みにはなりません。

## 結論: 批判の代わりに理解と寛容を

- 批判や文句は弱い人間のすることです。
- 本当のキャラクターを持つ人は理解し、許します。

この章から学べるのは、人間関係を改善するためには、批判や非難ではなく、理解と寛容が必要であるということです。人々の感情を尊重し、彼らの行動を肯定的な方法で変えることが、真のヒューマンスキルの向上につながります。次回はChapter2に進んでいきましょう！

皆さんのコメントやフィードバックをお待ちしています！👍💬