OmniAICreator/Qiita-1.07M huggingface dataset:
デブサミ2021 参加レポート「アジャイルネイティブな大学生とコネクトしてみませんか? -3時間スプリント白熱教室」

# Developers Summit 2021

この記事は、2021/02/18-19に開催された[Developers Summit 2021](https://event.shoeisha.jp/devsumi/20210218/)のレポートです。

# チーム参加してきました
 
[aslead Agile](https://aslead.nri.co.jp/solution/aslead_agile.html) のチーム「[オキザリス](https://speakerdeck.com/viva_tweet_x/huesudeyong-qi-wode-taxin-gui-timugashi-yan-wozao-rifan-sitejin-nizhi-rumadefalsewu-yu?slide=3)」にて参加してきました。
チーム5人中、4人で参加して、その場で実況しつつ、記事も作っています。

# 登壇者
渡辺 知恵美[筑波大学/筑波技術大学]
上 藍加[筑波大学]
日高 拓真[筑波大学]
飯塚 陸斗[筑波大学]
須田 幹大[筑波大学]

# アジャイル開発を導入して何がうれしいのか
### PBL
学生が学業のなかでアジャイルを導入して、その中から出た学びを学生自ら学習していく。

# 大学の授業でアジャイル開発を導入する意味
プロジェクトの目的は顧客の問題を解決し、価値を提供すること。
問題の理解と解決にとことん向き合うことで、深い学びの基礎を体で覚える。

# 私たちが大切にしていること
**・何とかしたい問題にチームが本気で取り込む**
**・小さくたくさんチャレンジする**
**・「モノ」を手に取り、みんなで勝ちに向き合う**

# 実際にアジャイルネイティブの学生に話を聞いてみよう

## 事件1-サングラスのお兄さんにReviewで詰められまくった事件
「このプロダクトって意味ないよね」
プロダクトの概要を提示するのが遅かった。

## 絶対に折れないPO vs 絶対に折れない大学教授事件
対象者を「研究者」にしていたが、実際の研究者からだめだしされた。

### 問題
・ターゲット数が多すぎた
・POが想定した操作を説明できなかった

### 解決策・学び
実際のターゲットを絞り、明確化した
雑でもいいので、実際に物を作ったほうが説明が容易だった

## 絶対に折れないPO vs 迷子の迷子の開発メンバー事件
ターゲットはPOなんだからPOが欲しいものを作ってほしいといわれた。

### 問題
POの課題をしっかり明確化できていなかった

### 解決策
POがプロダクトバックログを管理し、優先順に並べることで、
欲しいものを作成していく

## 一人でスクラムチーム事件
メンバーの一人がSprint外で開発をしてしまった結果、
他のメンバーが開発に手出しできなくなった。

### 問題
メンバー間での技術力の差がある場合、どうしたらいいのか

### 解決・学び
円ピット中に解決できなかった
ペアモブ・モブプロを使用することで、知識の平均化ができた

## 2020年はあまりにも最悪でしたね事件
コロナ化の影響で、すべてがオンライン化してしまった。

### 問題
初めての環境で、どうやって作業をしていくか悩んだ

### 解決策・学び
共有開発環境を使用することで作業のハードルが下がった
ディスコードを使用して、コミュニケーションを行った
アーカイブ化しやすい情報整理を心掛けた
少人数でオフラインReview会を行った
工夫次第で、オンラインでも回ることが分かった。

# まとめ
PBLを通して、アジャイルや価値を学んだ。
社会に出た際に活用していきたい。

# 感想
学生のうちからアジャイルに触れることで、
社会に出た際にアジャイル開発にすぐ取り組めるというメリットはとても大きいものだと思った。
PowerBI DAX集計 メモ

表示範囲内での累計

```:DAX
MTD_amount = 
CALCULATE(
	SUM('daily_sales_summary'[amount]),
	FILTER(
		ALLSELECTED('daily_sales_summary'),
		ISONORAFTER('daily_sales_summary'[date], MAX('daily_sales_summary'[date]), DESC)
	)
)
```

365日移動平均（※当日は含めない）

```:DAX
ma_amount = 
VAR interval = -365
RETURN
CALCULATE(
    SUMX('daily_sales_summary', 'daily_sales_summary'[amount]) / DISTINCTCOUNT('daily_sales_summary'[amount]),
    DATESINPERIOD(
        'daily_sales_summary'[amount],
        LASTDATE('daily_sales_summary'[amount])-1,
        interval,
        DAY
    )
)
```
※含める場合は-1を削除
IBMCloud Netscaler VPX MIB-OID情報

#SNMP管理を実施する際に必要となる情報の取得方法


```
> show snmp mib
	NetScaler system MIB:
	sysDescr:    NetScaler NS11.1: Build 64.14.nc, Date: Jun  1 2020, 20:39:51
	sysUpTime:   1474078152
	sysObjectID: .1.3.6.1.4.1.5951.1.1
	sysContact:  WebMaster (default)
	sysName:     NetScaler
	sysLocation: POP (default)
	sysServices: 72
	Custom ID: Default
```


バージョン毎のマニュアルはこちら
[Citrix NetScaler 11.1 Command Reference](https://developer-docs.citrix.com/projects/netscaler-command-reference/en/11.1/snmp/snmp-mib/snmp-mib/#show-snmp-mib)
[Citrix NetScaler 12.0 Command Reference](https://developer-docs.citrix.com/projects/netscaler-command-reference/en/12.0/snmp/snmp-mib/snmp-mib/#show-snmp-mib)
[Citrix NetScaler 12.1 Command Reference](https://developer-docs.citrix.com/projects/citrix-adc-command-reference/en/12.1/snmp/snmp-mib/snmp-mib/#show-snmp-mib)


より細かいOID情報が必要な場合はこちら
[NetScaler 11.1 SNMP OID Reference](https://developer-docs.citrix.com/projects/netscaler-snmp-oid-reference/en/11.1/)
[NetScaler 12.0 SNMP OID Reference](https://developer-docs.citrix.com/projects/netscaler-snmp-oid-reference/en/12.0/)
[NetScaler 12.1 SNMP OID Reference](https://developer-docs.citrix.com/projects/citrix-adc-snmp-oid-reference/en/12.1/)

#MIBファイルのダウンロード場所
VPXのGUI管理画面のダウンロードから取得可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703043/02d3ef7e-86ea-ee39-01ac-156a012ef0ac.png)
【Unity】ビルドして実行したらString conversion error

# 概要
UnityでWindowsスタンドアローンアプリをビルドし、正常に動作することを確認した後、
そのアプリを別のPCにコピーして実行したら以下のエラーが発生しました。
> ExecutionEngineException: String conversion error: Illegal byte sequence encounted in the input.

# 結論
別のPCでアプリを配置したディレクトリの名称に全角文字を使っていたことが原因でした。
半角英数のみのディレクトリ名に変更したところ、正常に動きました。

# Kinectの影響？
当アプリは、MicrosoftのAzure Kinect DK（3Dセンサーカメラ）を使用したアプリでした。
Kinectを使用していない別のアプリは、ディレクトリ名に全角文字が含まれていても問題ありませんでした。
詳細な原因は追ってないので不明です。。。
【VBS】テキストファイルの処理速度について

#はじめに
CSVファイルを読み込んで別のCSVファイルを出力する、という処理をVBScriptで書いていたところ、処理速度が遅くなり、改善のため試行錯誤することになりました。
そこで、テキストの書き込みに関して、どのような処理が遅いのか、少し調べてみます。
#1行ずつ書き込む場合

```vb
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

Dim output
output = "xxx\output.csv"

Dim write
Set write = fso.OpenTextFile(output, 2, True)

Dim i
For i = 1 To 1000
    write.WriteLine("abc")
Next

write.Close
```

【結果】
約0.01秒/1,000行
約0.1秒/10,000行
約1.1秒/100,000行

思っていたほど遅くありません。大きなファイルでなければ特に工夫せずに1行ずつ書き込んでも問題なさそうです。
#毎回ファイルを開いて書き込む場合
##開く度に閉じる場合

```vb
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

Dim output
output = "xxx\output.csv"

Dim write

Dim i
For i = 1 To 1000
    Set Write = fso.OpenTextFile(output, 8, True)
    write.WriteLine("abc")
    write.Close
Next
```

【結果】
約11秒/1,000行
##開いたあと閉じる処理を書かない場合

```vb
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

Dim output
output = "xxx\output.csv"

Dim write

Dim i
For i = 1 To 1000
    fso.OpenTextFile(output, 8, True).WriteLine("abc")
Next
```

【結果】
約10秒/1,000行

`OpenTextFile`で`TextStream`オブジェクトを取得する処理が遅いようです。
実際の作業では、ここにハマって失敗しました。
1つのファイルにつき1回で済ませるべきですね。
#文字列を結合して一気に書き込む

```vb
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

Dim output
output = "xxx\output.csv"

Dim write
Set Write = fso.OpenTextFile(output, 2, True)

Dim str

Dim i
For i = 1 To 1000
    str = str & "abc" & vbCrLf
Next

write.WriteLine(str)
write.Close
```

【結果】
約0.01秒/1,000行
約0.07秒/10,000行
約9秒/100,000行

行が多くなるとかなり遅くなるという意外な結果ですが、「VBA　文字列結合　遅い」とググるといろいろ情報が出てきます。文字列結合は遅いのですね。
行数が少なければ気にしなくても良いかもしれませんが、多い場合は注意が必要です。
#連想配列に文字列を格納し、ループ処理で書き込む

```vb
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

Dim output
output = "xxx\output.csv"

Dim write
Set Write = fso.OpenTextFile(output, 2, True)

Dim dict
Set dict = CreateObject("Scripting.Dictionary")

Dim i
For i = 1 To 1000
    dict.Add i, "abc"
Next

Dim key
For Each key In dict
    write.WriteLine(dict(key))
Next

write.Close
```

【結果】
約0.01秒/1,000行
約0.15秒/10,000行
約1.8秒/100,000行

実用的な速度だと思います。
#配列に文字列を格納し、ループ処理で書き込む

```vb
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

Dim output
output = "xxx\output.csv"

Dim write
Set Write = fso.OpenTextFile(output, 2, True)

Dim arr(999)

Dim i
For i = 1 To 1000
    arr(i - 1) = "abc"
Next

Dim str
For Each str In arr
    write.WriteLine(str)
Next

write.Close
```

【結果】
約0.01秒/1,000行
約0.15秒/10,000行
約1.2秒/100,000行

これもなかなかの速度ですね。
1行ずつ書き込む処理とあまり時間が変わらないところをみると、配列への格納や配列からのデータの取り出しには時間がかからないようです。
#配列に文字列を格納し、Join関数で結合して書き込む

```vb
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

Dim output
output = "xxx\output.csv"

Dim write
Set Write = fso.OpenTextFile(output, 2, True)

Dim arr(999)

Dim i
For i = 1 To 1000
    arr(i - 1) = "abc"
Next

write.WriteLine(Join(arr, vbCrLf))
write.Close
```

【結果】
約0.01秒/1,000行
約0.01秒/10,000行
約0.04秒/100,000行
約0.4秒/1,000,000行

おお、早い。書き込みを1回にしたからですね。
何らかの事情で、文字列をどこかに確保したあとで書き込みたい場合は、この手法を使うのが良いようです。
配列のサイズをうまく調整できるかがポイントです。
#おまけ
VBSでは`Collection`が使えません。
→`Dictionary`を使いましょう。
VBSでは`Like`が使えません。
→部分一致の場合は`InStr`を使いましょう。そうでない場合は正規表現を使いましょう。
CustomElementsをVueで使う際の注意


# TL;DR  
- カスタム要素とVueコンポーネントの区別がつくようにコンフィグに設定をする必要がある。
- カスタムイベントの購読はrefつけてaddEventListenerする必要がある。
- 名前付きスロットは使えない。

# はじめに
業務でCustomElementsを使ったUIコンポーネントライブラリを作成し、それをVue.js上で使う機会がありました。
その際、Vueの都合上？使えない機能やいまいちなところがあったのでメモとして残します。  

## VueはCustomElementsとVueコンポーネントの区別がつかない  
カスタム要素をVueテンプレート上に記述すると、Vueはその名前のVueコンポーネントを探しに行き、もちろん存在しないので、warnログを出力してしまいます。  
これを回避するために、カスタム要素のタグ名プレフィックスとVueコンポーネントのプレフィックスを明確に分け、以下の設定でVueがカスタム要素をVueコンポーネントと認識させないようにする必要があります。

Vue2.x

```js
import Vue from "vue"

Vue.config.ignoredElements = [
    /^custom-/
]
```

Vue3.x

```js
import { createApp } from "vue"
import App from "path/to/your/app.vue"

const app = createApp(App)

app.config.isCustomElement = tag => tag.startsWith("custom-")
```


## カスタムイベントの購読
カスタム要素から`dispatchEvent(new CustomEvent(..))`している場合、テンプレート上での@{イベント名}による購読ではなく、refからaddEventListenerする必要があります。  

#### これは動かない

```vuejs
<custom-element @custom-event="doSomething"></custom-element>
```

#### これは動く

```vue
<template>
    <custom-element ref="myElement"></custom-element>
</template>
<script>
export default {
    mounted() {
        this.$refs.myElement.addEventListener("custom-event", this.doSomething)
    }
}
</script>
```

## カスタム要素の名前付きスロットは使えない
カスタム要素で名前付きスロットを使う場合`slot="name"`と属性を指定する必要があるのですが、
これが[Vueの古い記法](https://jp.vuejs.org/v2/guide/components-slots.html#slot-%E5%B1%9E%E6%80%A7%E3%81%AB%E3%82%88%E3%82%8B%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%82%B9%E3%83%AD%E3%83%83%E3%83%88)と被っていて、Vueテンプレート上に記載するとdeprecatedの警告がでます。※Linter使っている場合  
これを回避しても、Vueはslot属性をRealDOMに書き込まないようで、カスタム要素側では名前付きスロットを受け取れません。  
※回避方法知っている方いたら教えてください。
※カスタム要素のデフォルトスロットは問題なく利用できます。


### おわりに
ちゃんと確認したつもりですが、間違っているところがあったら教えていただけるとありがたいです。
Alexaの時報をスキル・定型アクション不要で実現する方法

シェルスクリプトを使用して、Alexa (Amazon Echo) に時報やカスタムメッセージをアナウンスさせる方法です。

手軽にできる方法としてスキルや定型アクションがありますが、
**スキル**　→　常にスキルが起動した状態でなければならない
**定型アクション** →　スマホのアプリでしか追加できず、数が多いと作成・管理が大変
というデメリットがあります。
また、リマインダーは `alexa.amazon.co.jp` からパソコンでも追加できますが、やはり数が多いと大変です。

シェルスクリプトを使うことによって
- **曜日・時間など柔軟なカスタマイズが可能**
- **カスタムメッセージを使用可能**
というメリットがあります。

欠点は、常にシェルスクリプトが実行できる環境を維持しておかなければならないということです。パソコンを常に起動している方であればそれで構いませんし、Raspberry Pi などを使うこともできます。

以下のコマンド等は Mac を前提にしています。必要に応じて `PATH` 等を変更してください。

# 手順
### 1. スクリプトの用意
Alexa(Amazon Echo)をコマンドラインから自由に喋らせる方法 - Qiita
https://qiita.com/shge/items/169de61c8f246d26c110

に沿って、`alexa_remote_control_plain.sh` を用意してください。

### 2. `cron` の設定

```sh
crontab -e
```

で `cron` の設定画面が開きます。(エディタは `vi`)

```sh:crontab
PATH=/opt/homebrew/sbin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

0 * * * * /path/to/alexa_remote_control.sh -e textcommand:"今何時"
```

と入力（`/path/to/` は各自のパスに変更）して、`:wq` で保存します。

無事定期的に実行されたら完成です！ :tada: 

※ Mac で実行する方は、
[crontabでシェルスクリプトが実行できないときの対処法 - Qiita](https://qiita.com/yuta-38/items/7f2a6c57143380b310cd#4-%E3%83%95%E3%83%AB%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%ABcron%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)
に沿って、`cron` にフルディスクアクセスを与えてください。

※ `PATH` は Homebrew のインストールフォルダによって異なります。

# サンプル

#### 平日17:00に「〇〇の時間になりました」とアナウンス

```sh
0 17 * * mon-fri /path/to/alexa_remote_control.sh -e speak:"〇〇の時間になりました"
```
[Git] revert は undo じゃないよ  〜 revert x cherry-pickの罠 〜

# 経緯

git revert をよく理解せずに使ったら、トラブりました。

`ver_1.２` ブランチに入れるべき修正を間違って `ver_1.3` ブランチにコミットしちゃったとき。
`ver_1.3` へのコミットを **revert** して `ver_1.2` に **cherry-pick** で当該コミットを入れたらどうなるか。

しばらくは大丈夫。たぶん期待通りの状態になります。
でも後日、 `ver_1.3` を `ver_1.2` に追従したら、 `ver_1.2` で **cherry-pick して入れた修正はなくなってしまいます**。

# どうしてこんなことに？
**revert** は間違った操作を **undo （なかったことに）するのとは違います**。
[B]が最新の状態で、[A]のファイルをどこからコピーしてきて**上書きコミット**するイメージです。
例えるならホワイト（修正液）で塗りつぶす感じです。gitには「ホワイトで塗りつぶす作業」が追加コミットされます。

https://www.atlassian.com/ja/git/tutorials/undoing-changes/git-revert

* [A]を[B]に変える修正をコミットしたとします。
* [B]を revert すると[B]を[A']に変える修正をコミットしたことになります。

ここで[A']はファイルの内容自体は[A]と全く同じですが、**過去に一度[B]であった過去を背負った別物**です。
また**[B]は将来[A']に上書きされることを運命づけられた**コミットになってしまいます。

一方 cherry-pick は別のコミットを**その運命込みで**取り込む操作です。
別ブランチで[B]を cherry-pick して取り込んでも、[A']のコミットが入ったブランチをマージすると **[A']のコミットが最新**になるわけです。


| 時系列 | `ver_1.3`ブランチ | `ver_1.2`ブランチ | 備考 |
|--------|------------------|------------------|------|
| 初期状態 | A | A | 共通の基点 |
| `ver_1.3`で修正 | A→B | A |  |
| `ver_1.3`でrevert | B→A' | A | A'とAのファイルの中身は同一 |
| `ver_1.2`にBをcherry-pick | A' | A → B | Bは`ver_1.3`に入れたのと同じ |
| `ver_1.3`を`ver_1.2`にマージ | A' | B → A' | BよりA'が最新の状態と判断され、 Bの内容が消える |


# 解決策

## revert の revert
問題が発覚したあとなら、 [A']のコミットをさらに revert して [B'] にしたものを入れれば良いです。
[B]のファイルをどこからコピーしてきて上書きコミットしても同じですが、操作ミスが入る余地が減るので可能なら revert コマンドでやったほうがいいですね。

## revert しない
今回の事例の場合、そもそも `ver_1.3` から **revert する意味があったのか**？

私のケースでは、「操作間違えちゃった、取り消し！」みたいな軽い気持ちでやってしまいました。
いずれ追従する予定なら、そのまま[B]が入ったままでもよかったんです。
revert が undo じゃないと知ってれば、安易に revert するよりそのままにしておく選択肢もありました。

（もちろん、プロジェクトと修正内容によっては、先のバージョンに入れると不都合があるので revert が必要なケースもあるかもしれません。）

## cherry-pick じゃなかったら？
[B]を cherry-pick じゃなくてファイルをコピーしてきて新規コミットしたら・・・
おそらく追従時にコンフリクトしますね。気付けるだけマシですが。

# コミット自体なかったことにできないのか

よく知らずに使うと、 revert より**はるかに危険**なので、あまりおすすめはしませんが、 rebase という操作でできるらしいです。
[Git-のブランチ機能-リベース](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E6%A9%9F%E8%83%BD-%E3%83%AA%E3%83%99%E3%83%BC%E3%82%B9)

なぜ危険かと言うと、共同作業中のリポジトリだとうっかり他の人の**必要なコミットまでなかったことにしてしまい**、しかも**過去の歴史が改ざん**されてるので気づきにくい。問題が発覚したときには当事者がいなかったりして、原因を特定するのにも苦労する、なんてこともあります。

## ローカルリポジトリなら reset で

**まだ push しておらず**、あくまでローカルリポジトリにのみコミットした状態なら、以下のようにしてコミットする前の状態に戻すことができます。

```
git reset --soft HEAD^
```

`--soft` オプションはコミットした差分を維持する指定です
`--hard` に変えるとコミットした差分は消えて修正作業前の状態になります

また `HEAD^` は一つ前のコミットまで戻る指定で、 `HEAD^^`, `HEAD^^^` のように `^` を重ねた分だけ前のコミットに戻すことができます。

参考
https://qiita.com/forest1/items/f7c821565a7a7d64d60f

## reset と push

前項で **まだ push しておらず** と条件を付けましたが、既に push されてる場合でも -f オプションで強制的にリモートリポジトリに反映することは可能です。これは実質的に rebase と同じ操作であり、**同じく危険な行為**ですのでおすすめしません。

# まとめ
revert は undo ではなく、逆修正による上書きコミットです。
なので別ブランチで cherry-pick していても、マージすると revert 後の状態が最新になります。
ローカルのコミットをやり直すなら reset コマンドがいいです。

以上、私もそこまで深く git を理解してるわけじゃありませんので、間違いやよりよい解決方法などあればご意見いただければ幸いです。
[Rails,mysql,docker]　Access denied for user 'user'@'host' (using password: YES)が出る問題

## はじめに

この記事はrails初学者が書いています。
間違いがあれば指摘してください。
よろしくお願いします。

## 状況
docker-composeでrailsサーバー、MySQLサーバーを立ち上げ、
rails db:createしようとしたら以下のエラーが出ました。

```
Access denied for user 'user'@'host' (using password: YES)
```

日本語に訳すと、「hostのuserからの接続が拒否されました。」みたいな感じですかね。

## 原因
docker-composeでvolumeを永続化しており、同名プロジェクトのデータが残っていたからです。

## 解決策

volumeを削除しましょう。

```
$ docker volume ls
DRIVER VOLUME NAME
local test-database
local test-bundle
...

$ docker volume rm test-database
```

あとは、今まで通りユーザーを作成し、権限を付与します。
<>で囲まれた部分を自分の環境に修正してください。

```
docker-compose exec db mysql -u root -p -e"CREATE USER '<username>'@'%' IDENTIFIED BY '<password>';GRANT ALL PRIVILEGES ON *.* TO '<username>'@'%';FLUSH PRIVILEGES;"
```

## ちなみに

`docker system prune`というコマンドがあり、使われていないイメージ、コンテナ、ネットワークを削除できます。
**volumeは削除されません（ここ大事）**
volumeも削除するときは`--volume`をつけましょう。

## 最後に

せっかくdockerを使ってクリーンな環境を作っても
volumeを多用しすぎると意味がないので気をつけましょう。（戒め）

## 参考

[【MySQL】Mysql2::Error::ConnectionError: Access denied for user ～への対処法【環境構築】](https://qiita.com/Kiyo_Karl2/items/2ff248621d35c598028f)
[使用していない Docker オブジェクトの削除（prune）](https://docs.docker.jp/config/pruning.html#id10)
Unityでkeystoreファイルを消してしまったら

# あらすじ

「`*.keystore`ファイルをうっかり失くして、こう対処した。」
「`*.keystore`ファイルはちゃんと管理しましょう。」というお話です。

# 発端

UnityでBuildしたものをPlayStoreにアップロードすると、```Android App Bundle が誤った鍵で署名されています。```というメッセージが表示されました。何事だ？？と確認すると、`*.keystore`ファイルが消えていました。

Plastic SCM でバージョン管理していたはずですが、`Check in`コマンドでステージングしたときに、アップロード内容に含め損ねていたようです。何と私が以前作成した`*.keystore`はもうこの世にありません！

失くしたものは仕方がないので方法を探しましょう。

# 鍵

PlayConsoleにアップロードするときには、アプリ本体、apkまたはaabと一緒に鍵がアップロードされます。

この鍵は最初にアップロードされるときにPlayConsoleに登録され、以降のアップロードでは同じ鍵が必須です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/e4d6e0f9-754c-70bd-cec3-a2bb583b7d0f.png)


これは、鍵を持っていない人が勝手にアップロードするのを防ぎ、安全性を高めるのが目的ですね。

# Unityではどうやって設定していたっけ？

Unityでは　Player設定の中で設定できます。

1. →Build Settings
2. →Player Settings
3. →Android
4. →Publishing Settings
5. →Project KeyStore

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/6bb81660-6e30-4a06-a08a-3e8d7d525b13.png)

ここで、KeyStoreManagerを起動して`*.keystore`ファイルを作成し、それをCustum KeyStoreでSelectしているはずです。

# 失くしたらどうする

まず、`*.keystore`を失くしたら、アップロードできません。

そこで、新しく作成したもので再登録させてもらえるように、Googleさんにお願いします。

https://support.google.com/googleplay/android-developer/contact/key

アップロードできない時に出てくるURLリンクから飛ぶと、このようなフォームがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/159b8ebc-ff50-7ed2-d884-5172b7db85bf.png)

記入していくと、`*.pem`ファイルを入力フォームにアップロードする必要があることが分かります。
これから使っていく新しく作成した`*.keystore`の情報が必要だということです。

ここで、だれもが思うことは、「`*.keystore`をアップロードしちゃダメなの？」でしょう。
しかし、PlayConsoleにアップロードする人が誰でもUnityを使っているかというと、それは違います。
Flutterかもしれないし、ReactNativeかもしれないし、Kotlinかもしれません。

そこで、`*.keystore→*.pem`変換、というかエクスポート？が必要になります。
# keystore→pem

手順を説明します。

まず、`keytool`コマンドを使って`*.keystore`から`*.pem`を生成します。
※keytoolコマンドが使えない時は、JDKをインストールしてPathを設定しましょう。
(chocolateyでインストールするのが[オヌヌメ](https://chocolatey.org/packages/jdk11)です。)

```
keytool -export -rfc -alias えいりあす -file upload_certificate.pem -keystore あなたのkeystoreふぁいる
```

Enterを押すと、パスワードを聞かれます。

```
キーストアのパスワードを入力してください:
```

UnityのKeystoreManagerで設定したパスワードを入力すると、

```
証明書がファイル<upload_certificate.pem>に保存されました
Warning:
JKSキーストアは独自の形式を使用しています。"keytool -importkeystore -srckeystore .\user.keystore -destkeystore .\user.keystore -deststoretype pkcs12"を使用する業界標 準の形式であるPKCS12に移行することをお薦め します。
```


保存されたことの報告に加えて、「業界標準を使いなさい」と、たしなめられます。
ひとまず、この`upload_certificate.pem`を先ほどの入力フォームにアップロードしてしまいましょう。
これであとは必要な項目を記入したら、送信ボタンを押します。

上手くいくと、Google Play Developer Support の担当者さんから、このようなご連絡をいただけます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/7a700778-de5d-b3fe-40b8-cff445279d61.png)

こみ上げてくる気持ちを胸に、メールに記載いただいている時刻よりも前にアップロードすると、エラーメッセージが帰ってきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/e8f561d4-23c3-3e95-8e3a-230f90c050bd.png)

ですよね。そりゃそうですよ。だがしかし。
エラーメッセージがこんなに嬉しいことは、なかなか無いでしょう。

# まとめ

間違えて消してしまうと手間がかかります。
また、Google Play Developer Supportの人にもご迷惑をお掛けします。
バックアップを取っておくなどの対策をしましょう。

**Excelsior!**
[Javascript]関数定義するには

#関数を定義する
JavaScriptでは

```javascript

function 関数名(){ 処理 }
```
と記述することで関数を定義することができます。

functionを用いることで関数を定義することができます
functionに続けて関数の名前を記述します。そして{ }のなかに処理を書きます。

```javascript:例
function muscle (){
  console.log("背中に鬼神が宿ってる")
}
muscle()
//実行結果
//背中に鬼神が宿ってる
```

#JavaScriptでの戻り値
JavaScriptでは関数の戻り値をreturnを用いて明示する必要があります

```javascript:例
function muscle (muscle1,muscle2){
  return muscle1 + muscle2
}
const muscle1 = "背中に"
const muscle2 = "鬼神が宿ってる"
console.log(muscle(muscle1,muscle2))
//実行結果
//背中に鬼神が宿ってる
```
このreturnがないと実行結果は反映されません

#おわりに
簡単なアウトプットでした
デブサミ2021 参加レポート「18-E-2 オープンソースのベストプラクティスを企業内で実践 ～インナーソースのすすめ」

# Developers Summit 2021
この記事は、2021/02/18-19に開催された[Developers Summit 2021](https://event.shoeisha.jp/devsumi/20210218/)のレポートです。

# チーム参加してきました
 
[aslead Agile](https://aslead.nri.co.jp/solution/aslead_agile.html) のチーム「[オキザリス](https://speakerdeck.com/viva_tweet_x/huesudeyong-qi-wode-taxin-gui-timugashi-yan-wozao-rifan-sitejin-nizhi-rumadefalsewu-yu?slide=3)」にて参加してきました。
チーム5人中、4人で参加して、その場で実況しつつ、記事も作っています。

# 登壇者

服部 佑樹さん[日本マイクロソフト]
田中 裕一さん[ギットハブ・ジャパン]


# Microsoftのサイロを壊せ
Microsoftでは、チームインナーソースの適用等を中心になって進めている1ESという組織が中心になり、Githubを使ってInnerSourceを実現。

## InnerSource を実現するポイント
- **発見可能性**  
  共有しても見つけられないと意味がないため、見つけられるようになっていることが重要
- **実行可能性**  
  README.md を用意しておくなど、ソースコードを迅速かつ簡単にコンパイル及び実行できる、または別プロジェクトの一部として簡単に使用できるようになっていることが重要  
- **貢献性**  
  社内の魅力的なプロジェクトを共有  
- **継続性**  
  全てのチームがコードをメンテナンスし続けること

#Microsoft の InnerSourceプラクティス
最終的な目標は、「文化的な変化」。  
人の働き方を決めたり、新しい統制プロセスとして追加してしまうと合わない。

## InnerSourceフレームワーク
各企業でワークフレームを作って社内で共有することが重要  

1.発見
PMが要件の検証を行い、InnerSourceのための機能の優先順位を決定  
  
2.デザイン
PMは必要に応じて更なる顧客検証を実施  
  
3.開発
開発者は、開発チームの延長線上で働く  
  
4.デプロイ
PMが機能を有効にする前にコミュニティに新機能のリリースを送信する  
  
5.メンテナンス
サポートを実施  

#Microsoftが収集するCustomer Metrics
Contributerが複数いるリポジトリ等を集計  

### OKR例
- Object  
  コードオーナが、自分たちのソフトウェアがどのように使われているかを理解し、コントリビューターを募集する方法を理解している
- Key Result  
  - InnerSourceの貢献パイプラインのメトリクスを定義し、消費しやすい方法で提供する（使用状況、インタラクション、及び貢献の追跡）
  - InnerSourceの貢献パイプラインMVPが、関連する２つのチームで採用されていること
- Action Item
    - チームが使用できるInnerSourceモデルとダッシュボードMVPの開発
    - モデルとダッシュボードを公開
    - ファネルを改善するためのアクション指向のガイダンスとワークフローを開発し、提供します。

#ここまでのまとめ
- InnerSouceは文化変革の旅
- 発見可能性・実行可能性・貢献性・継続性が重要  
- Fun！社内統制や標準化の一貫としないこと

# Githubを使ってどのようにインナーソースを実践するか
## 疑問1 : どのプロジェクトをインナーソース化するか？  
いきなりみんなお互いコントリビュートしあいましょう！といっても広まらない。  
コントリビューターになるまでの流れとしては、まずユーザとして使っているプロジェクトがあって、その際にバグを発見したり、新機能が必要になった場合にコントリビュータになる場合が多い。  
よって、既存のプロジェクトで社内で広く使われている・使われるものをインナーソース化すると良い。  

- プラットフォーム、ライブラリ、フレームワーク、SDKなど
- ビルド、CI基盤などの開発ツール
- 全社的なFAQ
- 社内規約等のドキュメント 
 
※実際にGithubの社内でもドキュメントをインナーソースとして管理している。

##疑問２ : プロジェクトをどう見つけてもらうか？
最低限、社内メンバーがリポジトリにアクセスできる必要がある。
GithubのInternalリポジトリを活用すると良い。Enterprise内全体からReadできる。

また、よくあるプラクティスとしては、InnerSourceプロジェクトの一覧を表示するポータルを作成すること。Private Github Pages ＋ Github Actionsで、Githubだけで社内限定のインナーソースポータルサイトを構築することも可能。

##疑問３ : どうやってコントリビュートしてもらうか？
初めてコントリビュートする人の不安を取り除くことが大事。

- どういうコントリビュートが受け入れられるのか？
- どういう流れでコントリビュートすれば良いのか？
- わからないことがあれば誰に聞けば良いのか？
- 何を満たせば良いのか？

### ベストプラクティス
- **README.md** を用意する  
  チーム外からのコントリビュートを歓迎していることを書く。また、どういう種類のコントリビュートを受け付けているのか、コントリビュートの具体的な手順を明記する。
- **CONTRIBUTING.md** を用意する  
  詳細なことはこのページに記載する。初めてコントリビュートする人に対しては、README以外にこのページへのリンクが表示されるようになる。バグ報告の仕方、プルリクの作成方法などを記載しておく。
- イシュー・プルリクのテンプレートを作成しておく
- CODEOWNERS
  ファイルの種類やパスごとにレビューアーを指定しておく
- マージされる条件の明確化
- REPO LINTER  
  レポジトリの中身をチェックしてくれるリンター。READMEがあるかなど設定ファイルで設定可能。

##疑問４ : 上手くいっているかをどう測る？
- grimoirelab
- hubble  
  オーガニゼーションをまたいでコントリビューションしてくれているか可視化するツール

## まとめ
- ツールは文化をかえる触媒
- インナーソースは文化
- 文化を変えるのはとても大変でも、ツール導入で人の行動が変わる
- 行動の変化が文化が変わるきっかけとなる

#感想
日頃、社内のソースが社内で共有されていればいいなと思いつつ、ハードルが高そうだと感じていましたが、ソースだけではなくドキュメントから始めることもできるということが勉強になりました。
また、さまざまなツールが世の中にあるということで、いろいろ活用してみたいなと感じました。
Rubyでバイナリーサーチを作ってみた。

# はじめに
私は、基本ミニアプリを作成し学習のアウトプットを行っています。
それを備忘録として残したいと思います。

# バイナリーサーチとは

配列の中のデータを検索するときに使用する手法です。配列内には同一の数値はないものとしています。

中央の値を確認し、検索したい値と大小の関係を用いて検索したい値が中央の右か左かを判断します。
それを繰り返しながら検索していく手法です。

```
例
8の位置が知りたい場合
[1,2,3,4,5,6,7,8,9,10]
中央値をとるので5番目の「5」が中央値となります。
8は5より大きいので、次は7~10の配列を検索します。
[7,8,9,10]
中央値をとるので2番目の「8」が中央値となり、検索が終了します。
```

実際のコード

```ruby

1 def binary_search(array, number_of_elements, target)
2  left = 0
3  right = number_of_elements - 1
4  while left <= right
5    center = (left + right) / 2
6    if array[center] == target
7      return center
8    elsif array[center] < target
9      left = center + 1
10    else
11     right = center - 1
12    end
13    end
14    return -1
15  end
16
17 array=[1,3,5,6,9,10,13,20,26,31]
18
19 puts "検索したい数字を入力してください"
20 target = gets.to_i
21 number_of_elements = array.length
22
23 result = binary_search(array, number_of_elements, target)
24
25 if result == -1
26  puts "#{target}は配列内に存在しません"
27 else
28  puts "#{target}は配列の#{result}番目に存在します"
29 end

```
4~13行目で「中央の要素の定義」「検索したい値が中央の左右どちらにあるか」を確かめるコードになっています。
もしなければ14行目の「return -1」で最終的な返り値になるようにしています。

# 最後に
学んだことはハンズオンで行うことで定着に繋がりやすいなと実感しました！
とりあえず、「やってみる」精神を大事にしていきたいと思います！

ここまで読んでいただきありがとうございました！
【Python】文字列の特定の文字を別の文字で置き換える

例えば、`abcde`の3番目`c`を`x`で置き換えた文字列(`abxed`)が取得したい時。

方法は3つ。

1. strを一度、listにしてから置き換える
2. 置き換える文字の前後をsliceで取得し、結合する
3. 文字の重複がない場合はreplaceで置き換える

## strを一度、listにしてから置き換える

strのまま指定位置を置き換えようとするとエラー

```python
>>> s = 'abcde'
>>> s[2] = 'x'
Traceback (most recent call last):
  File "Main.py", line 2, in <module>
    s[2] = 'x'
TypeError: 'str' object does not support item assignment
```

だから、一度listにしてから置き換える

```python
>>> l = list('abcde')
>>> print(l)
>>> l[2] = 'x'
>>> print(l)
['a', 'b', 'c', 'e', 'd']
['a', 'b', 'x', 'e', 'd']
>>> print("".join(l))
'abxde'
```

この方法で、リストデータの内容を書き換え、文字を置き換えた新たな文字列を作り出せる。

## 置き換える文字の前後をsliceで取得し、結合する

```python
>>> s = 'abcde'
>>> print(s[:2] + 'x' + s[3:])
'abxde'
```

この方法でも、文字を置き換えた新たな文字列を作り出せる。
個人的にはこっちの方が好き。

## 文字の重複がない場合はreplaceで置き換える
例のように `c` を `x` でというように置き換えたい文字が特定できており、かつその文字が1度しか登場しない場合は、`replace` で置き換えられる。

```python
>>> s = 'abcde'
>>> s = s.replace('c', 'x')
>>> print(s)
'abxde'
```

ただし、`abaade` など `a` が何度も現れるような文字列では全ての `a` が置き換わってしまうので注意。
@dfghdfdjftyfghvgjhk さんありがとうございます。

## 参考文献

- [Pythonで、文字列の一部の文字を変更する - minus9d's diary](https://minus9d.hatenablog.com/entry/20130528/1369745960)
- [Replacing a portion of a string « Python recipes « ActiveState Code](http://code.activestate.com/recipes/59890-replacing-a-portion-of-a-string/)
- [Python で文字列に変数を埋め込む方法あれこれ](https://qiita.com/niwasawa/items/27641b803db31f93b8e6)
複数タブでコマンドを実行してくれるShell Scriptをかきたい

# はじめに
フロントエンドとバックエンドで分けて起動したい時、
1. terminalを起動して
2. タブを分割して
3. 各々で起動コマンドを実行する
という流れが面倒だったのでシェルスクリプトにしました。

実行すれば垂直分割されたiTermが起動して、それぞれでコマンドを実行してくれます。(↓の状態のiTermが起動します)
![スクリーンショット 2021-02-18 11.41.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488042/6bdff62e-bdfd-cfda-c78a-dd905f8ca9e0.png)

# 実装
今回は[iTerm2](https://iterm2.com)を使います。  
[こちらの記事](https://teratail.com/questions/282067)を参考にApple Scriptで書きました。

```sh:.init.sh
#!/usr/bin/osascript
tell application "iTerm"
    create window with default profile
    tell current window
        # tabの分割
        tell current session of current tab
            split vertically with default profile
        end tell

        # tab1の処理
        tell current session of current tab
            write text "cd ~/[対象のpath]"
            write text "実行したいコマンド"
        end tell

        # tab2の処理
        tell second session of current tab
            write text "cd ~/[対象のpath]"
            write text "実行したいコマンド"
        end tell
    end tell
end tell
```

```
$ ./init.sh
``` 
を実行したら垂直分割されたiTermが起動されます。

## 参考

- https://teratail.com/questions/282067  
- https://stackoverflow.com/questions/22339250/applescript-osascript-opening-split-panes-in-iterm-2-and-performing-commands
サブドメインを含めてマルチドメイン証明書でサイトを常時SSL化する手順

#サブドメインを含めてマルチドメイン証明書でサイトを常時SSL化する手順

##はじめに
　ポートフォリオサイトを作成し、SSL化をするのにかなり手間取ったため、手順を記録しておく。今回はSAN(Subject Alternative Name)(マルチドメイン)証明書の方法を選択。ちなみにもう一つの方法としてワイルドカード証明書を使用する方法もある。個人的にはサブドメイン数も少ない場合はマルチドメイン証明書の方が簡単な気がする。

>マルチドメイン(SANs)証明書はSAN(Subject Alternative Name)フィールドに複数のドメイン名(FQDN)を追加することで、最大250の異なるドメインのwebサイトを1枚のSSLサーバー証明書で保護できます。
ワイルドカードの場合、同一のドメイン配下であれば、複数の異なるサブドメイン(FQDN)について1つのライセンスでSSLサーバー証明書を導入できます。
[マルチドメイン(SANs)証明書とワイルドカード証明書](https://www.geotrust.co.jp/products/sans_wildcard_ssl/)


##使用環境
* ConoHaVPS
* windows10
* Let's Encrypt

##Let's EncryptとSSL証明書のインストール

###まずはサーバーへSSH接続を行いログインする
windows poewershellなどを使用。

###mod_sslがインストールされているか確認

```
# httpd -M
```
ssl_module(shared)
：
：
：
と表記が並べばインストール済

ない場合は以下のコマンドを実行。

```
# yum install mod_ssl
```

インストールできたら下記を実行

```
# systemctl restart httpd
```

###httpsプロトコルで使用するポート番号の443がfirewallで解放されているか確認
ちなみにConoHaVPSはデフォルトで解放されていないようなので注意！

下記コマンドで確認

```
# firewall-cmd --list-all
```

services: dhcpv6-client http https sshの欄に**https**があればOK
なければ下記を実行

```
# firewall-cmd --add-service=https --zone=public --permanent
```

firewallを再起動

```
# systemctl restart firewalld
```

###Let's Encryptをインストール

```
# yum install certbot python2-certbot-apache
```

単一ドメインの場合

```
# certbot --apache -d test.com
```

サブドメインもある場合

```
# certbot --apache -d test.com -d sub.test.com
```

メールアドレスを入力する

```
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): [メールアドレスを入力]
```

規約への同意

```
(Y)es/(N)o　//agreeから変わってた気がする
```

Let's Encryptパートナーにemailを公開しても良いか同課の確認。公開しない場合はNを選択。

```
Would you be willing to share your email～～～～
(Yes)/(N)o
```

インストールは完了なのでhttpdを再起動する

```
# shistemctl restart httpd
```

###証明書の詳細確認

SSL化したサイトにアクセスしてみてアドレス左横の南京錠マークをクリックしてみる。
そこから証明書をクリックすると証明書の情報が確認できる。

発行者がR3になっていればOK。
(少し前まではLet's Encryptだったらしい)
[Let’s EncryptのSSL証明書の発行元表記が'R3'に変更される](https://it-jog.com/khow/serv/letsencryptr3)



##参考
[無料SSL証明書のLet’s EncryptでVPSサーバーの常時SSL化](https://designsupply-web.com/media/developmentlab/2578/)
[ConoHa教室 Hello VPS　～WordPress公開までの道～
7時間目 SSL証明書をインストールしてサイトをSSL化する](https://support.conoha.jp/v/hellovps-w-07/)
Unreal Engine 4.26 パッケージ化(Windows)のやり方

# 使用したプログラム
* Microsoft Windows 10 20H2
* Epic Games Unreal Engine 4.26
* Microsoft Visual Studio 2019
    * C++ によるデスクトップ開発
        * C++ のプロファイルツール
        * C++ AddressSanitizer (試験段階)
        * Windows 10 SDK (10.0.18362.0)

詳しくは [こちら](https://docs.unrealengine.com/ja/ProductionPipelines/DevelopmentSetup/VisualStudioSetup/index.html)

# Unreal Engine
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/d1f26357-7751-f58c-0f46-4482c4e90a34.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/75d844b3-18f7-3a26-338c-e7d65eb9d615.png)
「ファイル」→「プロジェクトをパッケージ化」→「Windows(64Bit)」を選択

# パッケージをダウンロードするフォルダーを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/578471fc-bcaa-4db3-3db4-5596eda22966.png)

# パッケージ中
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/6f017760-93b5-f196-0c60-5e92544966e6.png)

# ログ表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/b8c07d7b-d218-7eae-b38d-404f11e911c8.png)
「アウトプットログを表示」でログが見れます

# 完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/f283833d-2a6f-cbd6-ba1f-4efe1878eb14.png)

# エラー集
書こうと思ったのですがエラーが出ないんですよね...。
エラーが出るとログに赤文字で表示されます。
単語単位の差分を出したいときには git-diff を使える

次の２つのファイルがあったとします。

```1.txt
hogehoge 1 fugafuga

```

```2.txt
hogehoge l fugafuga

```

diff を使って違いを見つけようとしますが、行単位での比較になるのであまり参考になりません。
(今回利用したdiff は `diff (GNU diffutils) 2.8.1` です)

```
$ diff -u {1,2}.txt
--- 1.txt       2021-02-18 11:09:33.000000000 +0900
+++ 2.txt       2021-02-18 11:09:30.000000000 +0900
@@ -1 +1 @@
-hogehoge 1 fugafuga
+hogehoge l fugafuga
```

# git-diff を Git 管理外で使う。行単位の差分

git-diff は `--no-index` オプションをつけると、Git管理下でなくても動作します。ここでは行単位の差分を表示しています。

公式ドキュメント: https://git-scm.com/docs/git-diff#Documentation/git-diff.txt-emgitdiffemltoptionsgt--no-index--ltpathgtltpathgt


```
$ git diff --no-index {1,2}.txt
diff --git a/1.txt b/2.txt
index 207832ae..abab571a 100644
--- a/1.txt
+++ b/2.txt
@@ -1 +1 @@
-hogehoge 1 fugafuga
+hogehoge l fugafuga
```

# git-diff を使って、単語単位の差分を見る

git-diff には単語単位での差分を表示する `--word-diff` オプションがあります。

公式ドキュメント: https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---word-diffltmodegt

```
$ git diff --word-diff --no-index {1,2}.txt 
diff --git a/1.txt b/2.txt
index 96b1a710..38ca2702 100644
--- a/1.txt
+++ b/2.txt
@@ -1 +1 @@
hogehoge [-1-]{+l+} fugafuga
```

私の使っているシェルでは色を有効化しているので、次のような見た目になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38967/f4f5045f-0527-dce3-dcd8-79ea48b57278.png)

## word-diff のモード
`--word-diff` にはいくつかのモードがあります。


### plain

`git diff --word-diff=plain --no-index {1,2}.txt`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38967/f4f5045f-0527-dce3-dcd8-79ea48b57278.png)

### color

`git diff --word-diff=color --no-index {1,2}.txt`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38967/6545fe0f-901f-be6f-1888-3f118fc56985.png)


### porcelain

`git diff --word-diff=porcelain --no-index {1,2}.txt`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38967/0e5f8e6d-6a02-f9da-6ca8-bba906a6e4e9.png)
<SQL>テーブルカラムへの効果的なインデックス(索引)の張り方

#テーブルのカラムにインデックスを張るときはどんな時？

[<SQL>テーブルのカラムにインデックスを張るって何ぞや？](https://qiita.com/ichi_zamurai/items/170514beaea34608ffd4)
この記事を書いた時に、


こんな疑問がふつふつと湧いてきました。
インデックスの張り方、貼った時の挙動はある程度は理解できたけど、
どんな時に索引を張るべきか
があやふやなので、これもまとめたいと思います。

（基本的に、インデックスはB-TREEを指して話してます。）

#テーブルのレコード数が多く、かつ、少量のレコードを検索したいケース
検索結果のレコード数が、推定、**全体の2~15%程度のケース**で、インデックスの効果が最も発揮できるそう。

ちなみに、

- テーブルのレコード数が少ないケース
- テーブルから大部分のレコードを検索する必要があるケース
    - HDFSなどの分散ファイルシステムのようにビッグデータを扱う場合とか

では、インデックスは使用しないほうがいい。


#カーディナリティが高いカラム（カラムが保有する値の種類が多い）

- カーディナリティが高い = カラム内に存在する値の種類が多い 
    - 例：`1,2,3,~~10000`
- カーディナリティが低い = カラム内に存在する値の種類が少ない
    - 例： `0,1,0,1,0....`


一般的なB-TREEインデックス（バイナリーツリーindex:二分木インデックス）のケースでは、
カラムの値が一意に近づけば近づくほど、効果が得られるようになる。

つまり、列の値が比較的ユニーク（一意）なケースで、インデックスを張ると良い。

###カーディナリティが低い場合は、ビットマップインデックスが有効

実際のテーブルのレコードこんな感じだった時に、

| name | selection |
|:-:|:-:|
| 加藤 | **a** |
| 鈴木 | b |
| 高知 | d |
| 香川 | c |
| 大和 | **a** |

ビットマップインデックスはこんな感じのイメージで

| a | b | c | d |
|:-:|:-:|:-:|:-:|
| 1 |   |   |   |
|   | 1 |   |   |
|   |   |   | 1 |
|   |   | 1 |   |
| 1 |   |   |   |

aに`1`というフラグが立っている部分（インデックス）と
テーブルそのものを照らし合わせて
加藤さんと大和さんをヒットさせるというやり方

※ちなみに、`AND`や`OR`だけで行う検索や、`NOT`を用いた否定検索にも有効らしい



#WHERE句の条件、またはJOIN句(結合)の条件としてよく使用するカラム

例えば、
ECサイト等で、注文番号みたいな値を頻繁に条件として指定する場合や

```sql
SELECT * FROM orders WHERE order_no = 1356;
```
よくユーザー情報を用いて正規化されたテーブル同士を結合JOINしてデータを引っ張ってくる場合とか

```sql
SELECT * FROM users LEFT JOIN user_orders ON users.id = user_orders.user_id
WHERE users.id = 3;
```

こんな利用ケースがある時とかは、効果を発揮するみたい。

逆に、WHERE句の条件としてあまり使用されないものについては、
インデックスを張るあまり意味ないっぽい。


#外部キー制約になってるカラム
外部キーを設定すると、
間違ったデータの登録や削除を防いだり、
関連するデータを一括に変更できたりして、
**関連のあるテーブル間で整合性を担保できるようにする役目**がありますが、

例えば、
usersテーブルでレコードを消そうとした時に、user_ordersテーブルにそのuser.idがあった場合に、データが消さないなど。

その外部キー設定カラムにインデックスを張ると効果があるそうだ。


#カラムの値にNULLが多い時に、NULL値以外のレコードを検索したいケース
インデックスにはNULLが含まれないので、NULL値以外の検索には効果を発揮する。
つまりNULL検索では、B-TREEインデックスが使用できないので、ビットマップインデックスだと効果を発揮するそう。

#あまり値が更新されないカラム
インデックスは、テーブルとは独立した存在として、インデックスデータ単体でも保存されている。
なので、テーブルに`insert` `update` `delete`したら、テーブルだけじゃなくて、
**インデックスのほうのデータ更新される**ようになる。

つまり、**更新が頻繁な物に対してインデックスを張ると、重くなってしまう**ので、気をつけて設計するといい。


#まとめ
B-TREEインデックスだけでなく、ビットマップインデックスについても少し勉強なりました。


以上、ありがとうございました。
【Unity × Quest】ADB サーバーがスタートせずビルドが失敗するときの対処法ほか

# Unable to start ADB server
:exclamation: Error
> CommandWithNoStdoutInvokationFailure: Unable to start ADB server. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details.

などと言われて、ビルドが落ちたときは、ADB を使うようなソフト（Oculus Developper Hub など）を別で起動していないか確認しましょう。開いてたら終了させましょう。それでもダメならタスクマネージャーからも確認しましょう。

# repositories.cfg could not be loaded.

:warning: Warning
> File C:\Users\■■■\\.android\repositories.cfg could not be loaded.

あと、この警告が出たら、同名の空ファイルを作れば OK
cf. https://stackoverflow.com/questions/43433542/stuck-at-android-repositories-cfg-could-not-be-loaded

以上。
ReactをGCPのGAEにデプロイする方法

##はじめに
GAEではapp.yamlファイルに仕様を書くだけで簡単にアプリをデプロイすることができます。
本記事では特にReactのアプリをデプロイするためのコードと手順をご紹介します。
前提として、GCPのSDKのインストールがされている必要があります。

##手順
### app.yamlを用意
以下のapp.yamlをコピペします。
runtimeのNode.jsのバージョンだけ使用しているものに変更してください。
他は通常なら特に変える必要はありません。

```app.yaml
runtime: nodejs12
handlers:
# Serve all static files with url ending with a file extension
- url: /(.*\..+)$
  static_files: build/\1
  upload: build/(.*\..+)$
# Catch all handler to index.html
- url: /.*
  static_files: build/index.html
  upload: build/index.html
```

### Deploy
Terminalから以下のコードを実行すればデプロイできます。
***YOUR_PROJECT_ID*** を自分のプロジェクトのIDに変えてください。

```bash
npm run build && gcloud app deploy --project=YOUR_PROJECT_ID
```

ちなみに、自分はCloud Buildを使って自動的にデプロイされるように設定しています。
参考 : https://cloud.google.com/source-repositories/docs/quickstart-triggering-builds-with-source-repositories?hl=ja
Unreal Engine のインストール

# Launcherをダウンロード
https://www.epicgames.com/site/ja/home
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/133f5692-e084-3d42-9ec3-d92f3a32347d.png)
右上の「Epic Gamesの取得」からダウンロードできます。

# インストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/3c14ab1d-833f-c033-a10d-fb003d371f76.png)
インストール（管理者権限必須）を設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/048c2282-f18d-8482-7100-74b7748f4c52.png)
待つ

# ログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/0ea944c3-93f5-4bb1-f0a0-b1ce1f18cc2b.png)
ログインしてください

# Unreal Engineのインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/384601b5-6945-9d91-b42a-9145486cc434.png)
左側の「Unreal Engine」を選択→上の「ライブラリ」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/c22f7abe-7a17-bff8-17ff-4340c930d9f5.png)
Engine バージョンの隣にある「 + 」を押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/beca6397-6552-221a-259e-f7aac38db67d.png)
※注意：同じバージョンはインストールできません

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/241cfe6d-901c-4ba3-07bc-2623d61d07c0.png)
自分のダウンロードしたいバージョンを選んでください。
新規プロジェクトなら最新のバージョンのインストールをオススメします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/b108a5ac-e412-bba0-afd9-fabce8f10bdc.png)
インストールを押してください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/2d603f72-7c6c-9a64-428c-898084263578.png)
「インストール先」「オプション」「ショートカット作成」など設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/cfa45a1c-117c-7cad-c497-434a6ac9a381.png)
不明な場合はデフォルトでチェックしているものだけで大丈夫です。
ネットワーク速度が遅い場合や通信契約が通信量課金制などで大容量のダウンロードができない場合は「コアコンポーネント」のみでも最低動きます

# インストール完了後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/4e9fd28d-195c-78c0-83df-df57021d3976.png)
起動を選択して起動できます。

# インストール時にオプションで選択しなかったものをインストール後からインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/78d26b0f-139a-5b4f-1d51-7feb99ceed6e.png)
起動ボタンの隣に▽のボタンを選択 → オプション
で開きます。

# PC起動時にランチャーが起動するのを止めたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/3de1b20f-46f3-242f-dc62-8ba683fc0639.png)
ランチャー左下の「設定」を選択します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283091/071ca85c-0790-7704-f85f-8c6bd2e3f3ad.png)
スクロールして「プリファレンス」の「コンピューター起動時に実行」のチェックを外します。
AWS Domain移管を自分でやる際は、CLIのRegion指定忘れずに

AWS Route53 で、別のAWSアカウントへドメイン移管したい場合の話です。

AWS CLIでregion指定忘れると

```bash
aws route53domains transfer-domain-to-another-aws-account --domain-name example.com --account-id 123456789012
```

下記のエラー。

```
Could not connect to the endpoint URL: "https://route53domains.ap-northeast-1.amazonaws.com/"
```

Route53のドメイン登録のリクエスト関連のAPI ENDPOINTは 米国東部 (バージニア北部)にしかない。という事らしい。
https://docs.aws.amazon.com/ja_jp/general/latest/gr/r53.html

なので、Regionとしてus-east-1を指定しましょう、というお話でした。

```bash
aws route53domains transfer-domain-to-another-aws-account --domain-name example.com --account-id 123456789012 --region us-east-1
```
Rのggplot2で可視化

# はじめに
Rの可視化パッケージである`ggplot2`を用いてデータの可視化を行った。使うデータについては[こちらの記事](https://qiita.com/ryamamoto0406/items/489e00fe693b688a4a5e)を参考にして下さい。df というdata.frame型の変数に1000人分の性別、身長、体重、血液型のデータがある状況で可視化を行っていく。

# データの中身の確認とパッケージの読み込み
まずはデータフレームの中身とデータ数を確認する。

```R:コード
str(df)
```

```:出力
'data.frame':	1000 obs. of  4 variables:
 $ SEX   : chr  "female" "male" "female" "male" ...
 $ HEIGHT: num  160 171 161 175 157 ...
 $ WEIGHT: num  47.3 65.7 55.4 86.6 54.3 ...
 $ BLOOD : chr  "O" "A" "O" "B" ...
```
想定通りのデータができてそう。次いで`ggplot2`の展開をする。

```R:コード
library(ggplot2)
```
これで準備が整った。

# 散布図

```R:コード
g <- ggplot(df, aes(x = WEIGHT, y = HEIGHT)) #プロットに使うデータの指定
g <- g + geom_point() #散布図を指定
plot(g) #プロット
```
![R_Scatter_plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/57778c9d-aeb8-872b-1195-98f9eb2c6c65.png)

男女で色分けした散布図は以下の通り。

```R:コード
g <- ggplot(df, aes(x = WEIGHT, y = HEIGHT, color = SEX)) #グループとして性別を選択
g <- g + geom_point()
plot(g)
```
![R_Scatter_plot_mf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/fe041ff9-9f39-490f-6242-c7dea1ab20c7.png)

男女の違いで微妙に集団が分かれているのが分かる。

次は血液型によって形を変えつつ、軸の名前やタイトルをつけてみる。

```R:コード
g <- ggplot(df, aes(x = WEIGHT, y = HEIGHT, color = SEX, shape = BLOOD))
g <- g + labs(title = "1000人のサンプルデータ",
              subtitle = "身長、体重の相関",
              caption =  "ここに図のキャプションについてコメントする",
              x = "体重 [kg]",
              y = "身長 [cm]",
              color = "性別",
              shape = "血液型")
g <- g + geom_point()
plot(g)
```
![R_Scatter_plot_mf_bt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/57495d5d-3637-cc91-1681-f44e58d9efab.png)

# ヒストグラム

散布図と同様に色分け、binの数の指定などをしていくと以下の様になる。

```R:コード
g <- ggplot(df, aes(x = HEIGHT, fill = SEX))
g <- g + geom_histogram(bins = 30)
plot(g)
```
![R_histgram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/3024e12e-71ac-496c-dfcb-3af311fba308.png)

これを男女に分けたヒストグラムを作ると、以下の様になる。

```R:コード
g <- ggplot(df, aes(x = HEIGHT))
g <- g + facet_grid(rows = vars(SEX))
g <- g + geom_histogram(bins = 30)
plot(g)
```
![R_histgram_facet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/ae101a58-bfa4-39cf-b8aa-9543b5eb0a66.png)

男女共に正規分布に従っているのが分かる。

# 箱ひげ図
血液型に対する体重の箱ひげ図を作ってみる。

```R:コード
g <- ggplot(df, aes(x = BLOOD, y = WEIGHT))
g <- g + geom_boxplot()
plot(g)
```
![R_boxplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/d6ef50fb-6b62-901a-17c4-4b597d91d757.png)

もちろん血液型で分布に差が無いことが分かる。

# おわりに
`ggplot2`でのデータの可視化を行ってみた。数行のコマンドで非常にきれいな図が作れるので、これからは可視化には積極的に`ggplot2`を使って行きたいと思う。
スマホUIの参考サイト　スマホアプリのUI事例


海外の有名サービスのアプリUIの参考サイトです。youtubeやUberなど知っているサービスがたくさんあります。
https://mobbin.design/

アカウント登録などしっかり使い込まないと見れない画面フローのキャプチャが見れるのでUI設計の参考になります。
![スクリーンショット 2021-02-18 16.41.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242518/9955acde-b081-827b-0bbf-37f7cbbd9a80.png)
OracleAnalyticsCloudにアップロードできるデータ容量

オラクルアナリティクスクラウドに限ります
（デスクトップ版はマシン依存するはずだから、この項目はないと思われる）

## OACにアップロードできる容量の確認方法
- メニュー＞データセット管理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064900/5176eb1a-83b6-9b5a-2170-e103a07013bd.png)

- ここでストレージ容量が見れるらしい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064900/5496fb99-0c51-2026-2955-294c12a0bf8d.png)

おそらくですが、エディションやインスタンスのOCPUごとにサイズが違うのかなと思ってます
（※ちなみにこの画像はProfessional Edition（下位エディション）の2oCPUのインスタンスです）
もし違ってたらゴメンナサイ
OracleAnalyticsCloudでdvaファイル出力時に500エラーになる対応方法

オラクルクラウドのオラクルアナリティクスクラウド(OAC)で
dvaファイルを出力しようとしたら下記のようなエラーが返ってきました。
「問題が発生した可能性があります。再試行してください。問題が解決しない場合、完全な製品を目指して対応致します。」

詳細を開くと
「ネットワークまたは接続性の問題のため、サーバーへのリクエストが失敗しました。500 internal Server Error」
### エラー内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064900/717007a5-6a62-c763-839d-0492691a6880.png)

## どんな時に発生したエラーか
プロジェクトのグラフもデータも参照できる状態で、dvaファイルを出力しようとしたらこのエラーが発生しました。

### 原因
- プロジェクト名に日本語（2byte）が入っていること


### 解決策
- プロジェクト名を全部英語に変更して再度dvaファイル出力


### 結論
- この手の類のエラーは多いと思うので、日ごろから全角文字やスペースには気を付けましょう。
MVCモデルとは

#MVCモデルとは
プログラムの処理を役割を分けて開発をする考え方です

MVCとは[model(モデル)],[view(ビュー)],[controller(コントローラー)]の頭文字からきてます

model,view,controllerに役割が決まっており、該当する処理を場所ごとに書いていきます

#Model
処理した結果をデータベースに反映させることができます

また、データベースからデータを取得して、controllerに送る部分でもあります

#View
ユーザーが実際見る画面を示しています

controllerから受け取ったデータを画面に表示したり、ユーザーからのリクエストをcontrollerに送る部分でもあります

#Controller
viewとmodelを操作する部分です

viewからリクエストを受け取り、modelへの処理を命令をだします

また、modelから処理の結果を受け取り、レスポンスとしてviewに返します

#まとめ
MVCモデルとはModel,View,Controllerでプログラムの処理をわけて開発する考えのこと

MVCモデルを採用することで、どこの処理がどこに記述されているかがわかること
【GoogleMap】地球を半径6371008mの球体として距離計算していた

##概要
以前、GoogleAppsScriptで緯度経度から距離計算するコードを書いた。

GoogleMapの距離測定と同じ結果が欲しかったので、何かの記事で見た「GoogleMapは地球を半径6378137mの球体として距離計算している」と言うのを参考にして定数を設定。

それらしい計算結果にはなるんだけど、GoogleMapの距離測定と比べて常に0.11%の誤差が出てしまう・・・もしかして地球の大きさが違う？

と言うわけで、GoogleMapの距離測定から地球の大きさを逆算してみた。

距離計算についてはコチラで解説。
Qiita記事：[緯度経度からの距離計算 ヒュベニより航海算法の方が高精度説](https://qiita.com/YasumiYasumi/items/3ed8ea69b85dac055381)
##判定方法
GoogleMapで距離測定して、同じ位置で距離を計算した時の誤差を評価する。

参考位置とGoogleMapでの距離測定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/9d0c4520-7538-8de4-172f-3f626781a387.png)
計算に使う定数（地球の半径）を変えながら４つの距離を計算し、合算の13859.08kmに近いほどGoogleMapの地球の大きさに近づいていると考える。
##1km刻み
地球の半径を1kmずつ変えながら計算。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/a61e4bdc-992f-a7c9-b1eb-d8285db0a87b.png)
6371000m～6372000mの間に正解がありそう。「地球の半径」でググると6371kmと出るので良い感じかも^^
##100m刻み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/7036def1-9646-17e6-abe9-d676ebbc1c15.png)
6371000mが強い！誤差の合算は約20m（0.0001%）。

もっと刻む。
##10m刻み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/995a3908-9e87-ebd0-6ee8-59d96e8dbfc7.png)
6371010mでほぼ誤差なし！でも、国会議事堂～ホワイトハウス間をGoogleMapの桁に揃えると、まだ10mの誤差がある。

更に刻もう。
##1m刻み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/3b4f2e19-ae60-f9f0-7799-044d9fb28d9d.png)
精度が100.0000%だらけになったので１桁増やしてみた。6371008mが一番近い。GoogleMapと桁を揃えた時の誤差もゼロ。

せっかくなので、もうちょっと刻んでみる。
##10cm刻み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/e18d06e9-6d8f-a828-b47e-3c55aa6be250.png)
更に精度を１桁アップ。結果は変わらず、これはもう6371008mで良いんじゃないかな。
##結論
**GoogleMapは**（たぶん）**地球を半径6371008mの球体として距離計算している！**

なのでGooglemapの距離測定と同じ結果を得るためのコードはこんな感じ。

```javascript
function googleGeosail(LatA,LngA,LatB,LngB){

  with(Math){

    var i = PI/180;
    var r = 6371.008;
    var X = acos(sin(latA*i)*sin(latB*i)+cos(latA*i)*cos(latB*i)*cos(lngA*i-lngB*i))*r;

  }
  return X;
}
```

A地点の緯度,経度とB地点の緯度,経度を引数に、２点間の距離 X(km)を返す。

測地線航海算法の変形なんだけど、なぜこうなるかは下記の記事で解説。
Qiita記事：[【ワンライナー】緯度経度から１行で距離計算](https://qiita.com/YasumiYasumi/items/9e8a6f185b00cba8c8bd)
##おまけ
「6371008m」の根拠を考察。

楕円体には平均半径と言う考え方があるらしく、たぶんそれだろうと当たりをつけてみた。

長半径（赤道半径）a と短半径（極半径）b から回転楕円体（地球）の体積を計算し、体積が同じ球体の半径が平均半径となるので、次の式から求められる。

```math
\begin{eqnarray}
回転楕円体の体積&:& V = \frac{4}{3}\pi a^2b\\
体積Vの球体の半径&:& r(V) = \sqrt[3]{3V/4\pi}\\
回転楕円体の平均半径&:& r = \sqrt[3]{a^2b}\\
\end{eqnarray}
```

地球の最良推定値（国際天文学連合が採用する実測値）で計算すると約6371000.4m、GRS80楕円体（GPSや地図作成などに用いられる測地系）で計算してみても約6371000.8mと微妙に合わない。（参考：[地球の大きさ](https://ja.wikipedia.org/wiki/%E5%9C%B0%E7%90%83#%E5%A4%A7%E3%81%8D%E3%81%95%E3%80%81%E8%B3%AA%E9%87%8F%E3%80%81%E5%AF%86%E5%BA%A6)＠wikipedia）

6371008はどこから来たんだろう？と思って調べていたら、

```math
回転楕円体の平均半径:r = (2a＋b)/3
```
として近似値を求める式があるみたい。

こっちの式で最良推定値から計算すると約6371008.4m！ GRS80では約6371008.7となった。どうやらGoogleMapの地球は**実測値を元に、近似式で求めた平均半径を半径とする球体**っぽいε=(￣｡￣;A ﾌｩ

余談だけど、気象庁が採用している地球半径は6371009mなので、GRS80の近似平均半径なのかも。

当初参考にした「GoogleMapは地球を半径6378137mの球体として距離計算している」と言う記事も、「GoogleMapは赤道半径6378137mの楕円体から平均半径を求めた球体として距離計算している」だったのかもしれない。

※10cm刻みで検証した時に半径6371008.1mの方が誤差が大きかったので、楕円体から平均半径を求めて距離計算しているのではなく、最初から平均半径を定数として球体の距離計算をしているものと思われる。

###おしまい
C#の子オブジェクトから親メソッドを呼び出す -System.EventHandler-

C#の子Classから親Classのメソッドを呼び出す方法
```System.EventHandler```を使用する　Unityには他のグラフィカルな方法がある模様だがコードの範囲内で収めたかったので今回はC#の```System.EventHandler```を使用。
備忘録的に書き残すので間違えているところがあったらご了承

コード的にはChild.StartToCall を出発して Parent.CalledFunction までEventが飛べばいい

```
class Child{
    // イベントハンドラを定義 (今回はCustomArgsを送りたいため独自に定義)
    internal delegate void TestEventHandler(object sender TestEventArgs e);
    internal TestEventHandler testEventHandler;

    void StartToCall(){
        // 送信開始 ここから -> Parent.CalledFunctionが呼び出されれば成功
        var testEventArgs = new TestEventArgs();
        testEventArgs.valueToSend = value;
        testEventHandler(this, testEventArgs);
    }
}


// カスタムArgs　valueを送る必要がない場合はもう少しかんたんに
class TestEventArgs: EventArgs{
    // 送りたいValueを定義 GameObjectでもいいしIntでも...
    internal Something valueToSend;
}


// 親のClass この中のCalledFunctionがChildのStartToCallから呼び出される
class Parent{
    Child child;

    Parent(){
        child = new Child();
        // Init ChildからHandlerを送る際の初期設定 ChildのHandlerにParentの呼び出されるFuncを登録しておく
        child.TestEventHandler += new Child.TestEventHandler(CalledFunction);
    }

    void CalledFunction(object o, TestEventArgs args){
        // このメソッドがChildから呼び出されたら成功
        print(args.valueToSend);
    }
}
```

くっそめんどくさいね。CustomArgsが必要ない場合はもう少し簡単になる模様
UnityをやるためにC#ならUnity謹製のEventがあってコードちょびっとでUIで弄れる。でも昔のXcodeのStoryboardでやらかした経験があるためあまりUI頼りにしたくないのだ。
以上

---
@ktz_alias様  @albireo様から訂正のコメントを頂いたのでモダンにしたバージョンも書いておく。

```
class Child{
    // イベントハンドラを定義 (今回はCustomArgsを送りたいため独自に定義)
    //*** 独自のHandlerは宣言しなくてもEventHandler<TEventArgs>が有るためこれを使用 ***
    internal event EventHandler<TestEventArgs> testEventHandler;

    void StartToCall(){
        // 送信開始 ここから -> Parent.CalledFunctionが呼び出されれば成功
        // *** モダンな書き方、VSによく注意されるやつだ... ***
        testEventHandler(this, new TestEventArgs(){
            valueToSend = value,
        });
    }
}


// カスタムArgs　valueを送る必要がない場合はもう少しかんたんに
class TestEventArgs: EventArgs{
    // 送りたいValueを定義 GameObjectでもいいしIntでも...
    internal Something valueToSend;
}


// 親のClass この中のCalledFunctionがChildのStartToCallから呼び出される
class Parent{
    Child child;

    Parent(){
        child = new Child();
        // Init ChildからHandlerを送る際の初期設定 ChildのHandlerにParentの呼び出されるFuncを登録しておく
        // *** new Child.TestEventHandler(CalledFunction)今はこれ書かなくてもOK ***
        child.TestEventHandler += CalledFunction;
    }

    void CalledFunction(object o, TestEventArgs args){
        // このメソッドがChildから呼び出されたら成功
        print(args.valueToSend);
    }
}
```
ググって一番上に有るやつの記事を鵜呑みにしてはイケナイ
こういう筆者のせいで昔の古文書コードがネット上で脈々と受け継がれるわけだ。反省しています...