OmniAICreator/Qiita-1.07M huggingface dataset:
個人開発の生ぬるいことを書くけど内容と全然関係なく来年は1円以上稼ぎたい

今年からQiitaに投稿し始めたので、Advent Calendarってなんじゃろなって感じなんですが、テーマに沿ってれば普通に投稿すればいいんでしょうか。

といっても年末が近づくにつれてだんだん「今年はやり切った感」に包まれて特に技術的なことで投稿することないなぁという感じになってきます。

でも何かないかな～と探してたら、「個人アプリ/サービス開発の進め方と運用、得た学び」という今この段階で何か書けそうな気がするテーマ。

まあ最近似たようなポエムばっかり書いてますが。

来年頑張ります！

さて、しつこいようですが私はSIerで職業プログラマーです。

C#とかJavaとかやってましたが、会社でやるだけで家ではあんまりプログラミングやってませんでした。

会社で実装方法がよく分からなくて、家で動作させて動かすことくらいはやってましたが、何かを作るということはしてませんでした。

その程度の姿勢のくせに「技術が好き！」とか言ってて言葉と実力のギャップを感じることは多々ありました。

そんな自分でも曲がりなりにも個人開発を始めました。

2つ公開しました。

経緯はざんざん書きました。

開発の進め方もざんざん書きました。

全然運営とか運用とかできてないのでそこら辺については何も書けません。

じゃあ書くことありませんね。

ってそれだと悲しいので得たことを書いてみます。

やや無理やりな感じで。

#1.とりあえず本業に活かせる

いきなり微妙です。

本業をフェードアウトさせたいのに本業にフェードインです。

まあでも個人開発だけで食べていく！って思ってても色々難しいでしょう。

いきなり何か当てればすごいですけど。

最初は小さく始めて…という感じでしょうか。

なので本業はおろそかにできないんですが、周りがVue.jsとかフロント系をやってなかったのであえてそういう方向を個人開発に取り入れてみました。

また、Trelloとかのツールの一部をそれっぽく自分で作ってみました（もちろん大したものではありませんが）。

で、日々のチーム内の会話の中で「Vue.jsとかどうですか？」「Trelloっぽいの作れますよ」とか言ってると…

なんということでしょう！

そういう仕事が舞い込んできました。

大したレベルじゃないのにいつしか師匠扱いです。

言われた技術、ただそこにある技術を勉強してるだけだと「ふ～ん」って感じですが、チームにないものを持ってくると存在感は増します。

提案は大事ですね。

ただ何もなくそういうのを勉強するのもしんどいので、何か目的が欲しいです。

それが結果的に個人開発になりました。

別に本業のためにやってるわけではありませんが。

結果的に、です。

#2.なんとなく情報を追いたくなる

本業で存在感が増しました。

ただ、何もしないとまた集団の中に埋もれていきます。

一度意識が高まると、その状態を維持したくなるものです。

情報を得る手段を増やしたくなります。

良く分からない記事も見ます。

新しい技術情報が流れてきたら、右から左じゃなくて、あとで見るじゃなくて、スピード感を持って試したくなります。

それを次の日どこかに話したくなります。

そうするとたぶん存在感がまた増します。

そしてまた情報を探したくなります。

自己啓発みたいなのは超苦手ですけど「良いサイクル」ですね！

#3.圧倒的かどうかは分からないけど当事者意識

Qiitaに投稿するようになってから、お誘いもあり、いくつかのコミュニティに参加しました。

そこでの話題は、私の全然知らない話ばっかりです。

それを眺めてるだけでも参考になりますが、Twitterを眺めてるのとは違うのは、自分もある意味そこの当事者ということです。

技術や運営の話をしていれば、それは自分にも直接関わる話です。

自分が何か書き込めば、反応してくれる確率はTwitterより圧倒的に高いです。

自分が自律的に何かをやっている、という意識が大切になります。

何もしないと、何も起こりません。

何かすると、情報の波に乗れます。

乗るしかない！このビックウェーブに！

とでも思ってないと凪に浮かぶ海の藻屑になります。

という圧倒的かどうかは分からないけど当事者意識が生まれた気がします。

#そんな感じで

すごい軽い話ですが、どんな形でもいいのでAdvent Calendarに参加してみたかったので無理やり書いてみました。

個人開発にハマると確実に他のことをやる時間を蝕まれます。

逆に蝕んでくれてありがとうという気分です。

ただ家庭で家事や育児が必要な人は、そこは疎かにすると確実に争いが起きます。

でもやることやったら、あとは自由！

どっぷり個人開発にハマりましょう。
typescript配列文字列結合(join)試す


```typescript
const array = ['a', 'b', 'c']
console.log(array.join(','))
```

log

![スクリーンショット 2020-12-22 1.28.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/2eb4a45d-6a43-1b74-54fe-9e631130b3c0.png)
Azure環境+Remote Desktop Serviceの性能向上ナレッジ集

本記事は以下サイトにて記載しています。
恐れ入りますがリンクから移動してご参照ください。

**Azure環境+Remote Desktop Serviceの性能向上ナレッジ集**
https://cloudsteady.jp/post/31201/
　
　
現在パーソルプロセス＆テクノロジーではAdvent Calendar 2020を開催中です。
https://qiita.com/advent-calendar/2020/ppt

こちらも興味ある記事あれば是非ご参照ください。
electron typescript ファイル読み書き試す

・fsモジュールを使う。
・fsモジュールのpromises namespaceにあるreadFileやwriteFileはawaitが使える。
・ファイルpathにホームディレクトリ"~"を使うとエラーになった。

```typescript
import fs from 'fs';

const execute = async () => {
    const data = await fs.promises.readFile('/path/to/sample_from.txt');
    await fs.promises.writeFile('path/to/sample_to.txt', data.toString() + 'hoge')
}

const button = document.getElementById('button');
if (button) {
    button.onclick = () => {
        execute()
    }
}
```
コネヒトに入社して2ヶ月経ちそうなので入社前と入社後の思ってたギャップを書いてみた。

## 少し自己紹介

突然ですが僕は今年の11月にコネヒトに入社させていただいてもうすぐ2ヶ月が経ちます。 エンジニア未経験としての入社ですが今はネットにエンジニア関連の情報が沢山あるので自分も当然それを見てエンジニアとはこういう感じなのかな...という考えがありました。なので入社前と入社後の自分のギャップをまとめました。

注
- あくまでも個人的な意見です
- コネヒトに入社してのギャップなので他社様とは違う所も当然あると思います。
- 世にある情報ではなく自分の偏見によるギャップもあります。

###相手の時間を奪う事になるからあんまり質問しない方がいい -> 分からない所は素直に質問した方がいい

エンジニアは基本的に分からない所があったら調べる->解決が基本！先輩エンジニアの皆さんは忙しいから意地でも自分で解決するんだ！と考えて一日何も進まず終わった日もありました。それが割と簡単そうな事なら尚更恥ずかしくて聞きづらい時もありましたが悩んで時間を浪費しすぎるのは不効率だしコネヒトのエンジニアは毎回すごく丁寧に答えてくれます。もちろん分からないことが出てきたらまずは自分で調べることが前提ですが素直に分からない時は『俺は分からない！』と主張して普通に質問して方がいいんだな...と思いました。

### 自分はフロントエンドエンジニアだから自分の得意分野に専念すればいいんだ(甘すぎる考え) -> 全くそんな事はない

自分は今まで基本Reactばっかやってたのでフロントエンドとして入社してます。一応入社前にバックエンドもやりますとは聞いてたはいたんですけどまあ肩書きはフロントエンドだしReactをメインにやればいいんだなと甘い考えを持ってましたが実際には1月からはバックエンド(API)を主にやっていく事になりそうです。コネヒトは肩書き(バックエンド、フロントエンド)関係無くいろいろやります。


### いきなりリモートワークは辛そう ->　そんな事ない。むしろ最高
最初は対面で直接会って仕事した方が色々と捗るし仕事もしやすいんじゃないかなーと思いましたが、コネヒトはリモートワークをするためのドキュメントの整備や機器の貸し出し(自分は家のwifiが貧弱だったのでポケットwifiを借りました)をしているので割とすんなりリモートワークに慣れていきました。


大体こんな感じかなと思います。
まだまだ慣れてない事もありますが日々繰り返している業務はだいぶ慣れてきたのかなと思います。

今年はビビって技術的な事は書きませんでしたが来年アドベントカレンダー書く時は技術的な記事を書きたいと思います！

ありがとうございました。
subscribe しないで GitHub からの Slack 通知

## GitHub for Slack

チームで開発をしていている人はやっている人が多いと思います。

そう、
GitHub for Slack です。

slack の任意のチャンネルで
`/github subscribe owner/repo` とすることで、

指定した repository に新しい PR ができたり、 PR がマージされたり、
PR にコメントがきたり、、、

まあ、指定した repository に何かが起こったら、教えてくれる。
という便利なものです

### 問題点

**うるさい**

とってもうるさいんです

いや、自分で「このリポになんかあったら Slack で教えてね」って言ってんのに、
いざ通知きたらうるさいってキレるのはやばすぎるんですが、
マジでチームで開発してると一生通知がきて、 Slack パンパンになって
__Slack の通知に対する認識が薄れてしまうという__、元も子もないことになってしまいかねないです。

これは、よくない。

「うるさい」の原因は
自分が関係ない PR の情報も含めて全部くる

(まあ、自分が一緒になって開発してる資材について、関係ないなんてことはないんですが、「詳細までは知らなくていい」と言う意味です。)

別の方法を探しました

## Scheduled reminders

ありました。

これは、僕だけのが来ます

つまり、
人が PR を作った時に
人の PR にコメントが入った時に
人が PR の reviewer に選ばれた時に
人の PR が merge された時に
通知が来ないんです。

全部、自分が関係ある時、

つまり

自分の PR にコメントが来た時に
自分の PR が approve/merge された時に
自分が人の PR の reviewer に設定された時に
だけ通知が来るようになります。

これをすると、 Slack から通知が来た時の意識が変わります

before
「あ、また来たよ...これ俺に関係ないじゃん、俺に関係あるのどれだよ...はぁ、うざ。今日も仕事さぼろ。」

after
「僕が知りたい情報だけ取得できるので、ストレスがなくなり、仕事はうまくいき、年収も倍ちかく上がり、非モテだった僕にも彼女もできました！」

こんなに違います。

### やり方

1. GitHub > Settings
<img width="80%" alt="profile" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321282/306da916-8981-c10f-dd7e-ebd58add0076.png">

2. Settings > Scheduled reminders
<img width="80%" alt="settings" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321282/e1d8e40d-4503-7f40-09a3-9621b8e84202.png">

3. Scheduled reminders

そもそも、ですが、これは、
「自分に関係ある情報を通知する」
と言うのが目的ではなく
「自分のタスクのリマインダーを仕掛ける」
と言うものです（多分）

なので、ここでは、
「毎週何曜日、何時に、やり残してるタスクがあれば Slack に通知するよ」
を設定します。

で、重要なのがここからです

4. Enable real-time alerts
一番下の「Enable real-time alerts」にチェックを入れます。
すると、隠れていたチェックボックスがたくさん展開されます。

ここで、欲しい情報について、チェックを入れていきます。
よくわからなかったので、今はとりあえず、全部盛りにしています（そのうち整理する）
<img width="80%" alt="settings" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321282/465bfc08-2e92-3663-b776-e493497266e2.png">

すると、
チェックした情報については、定刻リマインダーではなく
「変化があったら、リアルタイムでお知らせするよ」
ができます。

---

以上です！

皆さんも快適なチーム開発を！！

## 参考

- [GitHub for Slack](https://slack.com/intl/en-gb/help/articles/232289568-GitHub-for-Slack)
- [Managing scheduled reminders for your team
](https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-organizations-and-teams/managing-scheduled-reminders-for-your-team)
【Node.js　同期と非同期とアンチパターン】

ここでは非同期処理と同期処理の実例から考えるよくあるアンチパターンについて、理解が深まることで他の仕組みの使い所までわかればいいなと思う。

######非同期処理と同期処理の例
######コールバックを引数に持つ関数の例
######実際の処理と問題点
######解決方法

##【非同期処理と同期処理の例】


まずは、以下のように簡単に同期処理を非同期処理にすることができる。

出力結果が入れ替わることがわかる。

```jsx
const check = true

const syncCheck = (check) => {
    console.log(check)
}
syncCheck(check)
console.log("結果")
// true
// 結果

// これを非同期にする
const asyncCheck = (check) => {
    setTimeout(() => {
        console.log(check)
    },1000)
}
asyncCheck(check)
console.log("結果")
// 結果
// true
```

このように関数内の処理は簡単に非同期にすることができるため、コールバック関数の中身は非同期なのか同期なのか実装してみないとわからないという性質があるといえる。


##【コールバックを引数に持つ関数の例】

次にコールバックを引数にもつ関数の例を見てみる。

```jsx
const change = (check, callback) => {
    if(check){
        console.log(check)
        return
    }
    callback(check)
}
```

これはcheckがtrueならそのまま出力し、falseならcallbackを呼び出している。

しかしこういったやり方はアンチパターンにつながる。

##【実際の処理と問題点】

上のコードをもとに実際の処理をcallbackに渡してみる

ちなみにNode.jsのコールバックによる非同期処理には規約がある。
・コールバックがパラメータの最後であること
・コールバックのパラメータの第一引数がエラーを受け取る変数、第二引数以降が処理の結果を受け取る引数であること

下のコールバック関数はこの規約に沿ったものになっている。

```jsx
const check = false
change(check, (err, check) => {
    setTimeout((check) => {
        check = true
        console.log(check)
    }, 0)
})
console.log("falseの時の呼び出し")

// falseの時の呼び出し
// true
```

ここではコールバック内でcheckをtrueに変えてから出力している

問題になるのは以下のコードのようにもう一度実行したときに出力する文字列の順番が異なることがあるからだ。

1回目はfalseで非同期に実行される = 先に文字が出力される。２回目はtrueに変わっているので同期的に処理される = 文字は後で出力される。

```jsx
const check = false
change(check, (err, check) => {
    setTimeout((check) => {
        check = true
        console.log(check)
			// ここから２回目を呼び出している
        change(check, (err, check) => {
            setTimeout((check) => {
                check = true
                console.log(check)
                
            }, 0)
        })
        console.log("trueの時の呼び出し")
			// 全く同じように呼び出している
    }, 0)
})
console.log("falseの時の呼び出し")
// falseの時の呼び出し
// true
// true
// trueの時の呼び出し
```

これはJavaScriptによく見られるアンチパターンである。場合によって返されるタイミングが変わってしまい、この関数を使うときに非同期か同期かの判断をすることが難しくなる。つまりコールバックを引数に取る関数は非同期か同期かで統一してあげないといけない。

##【解決方法】

例えば以下のようにすれば２回目の true のときでも非同期に処理され、順番が変わることがなくなる。

```jsx
const change = (check, callback) => {
    if(check){
        setTimeout((check) => {console.log(check)}, 0)
    }
    callback(check)
}
// 上のコードをそのまま実行すると

// falseの時の呼び出し
// true
// trueの時の呼び出し
// true
```

上のように同期的な部分を非同期にしたいときは、`setTimeout()`でもいいが、

node.jsでは、`process.nextTick()` のほうが適している。またこの関数はブラウザ環境では動作しないためブラウザと共有するコードを書いているときは、`queueMicrotask()` が適している。

上のコードを修正すると以下のようになる。

```jsx
const change = (check, callback) => {
    if(check){
        process.nextTick(() => console.log(check))
    }
    callback(check)
}
```

また、この逆で非同期が混ざっている関数を同期的に統一したいときにコールバックヘルが起きる。そういった問題を解決してくれるのがPromiseやasync awaitだ。

###【まとめ】

コールバックを引数にとる関数は、その中の処理が非同期に実行されるか同期になるか統一する必要がある。それを助けてくれるのが、`process.nextTick()` や `Promise , async await`である。
Android StudioからFlutterアプリをReleaseビルドする(iOS)

デフォルトDebugビルドであり、最初Releaseビルドする方法がわからなかったのでメモ。

1. Run -> Edit Configuration -> main.dartを開く
2. Additional argumentsに"--release"を付ける

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196890/868b638a-8e2a-7e0e-c49f-fb3c4bbbb15b.png)

最終的には、以下のような形でxcodebuildの引数に渡される。

```
xcrun xcodebuild -configuration Release-dev <他のオプション>
```
cvt -数値型変換命令-

# はじめに
 - この記事は[ひとりNEONアドベントカレンダー2020](https://qiita.com/advent-calendar/2020/neon-only) 24日目の記事です。
 - クリスマスイブですね。皆様いかがお過ごしですか
 - [昨日は転置命令](https://qiita.com/tomoaki_teshima/items/d54c69e5b7ca3b5527bd)を紹介した
 - 今日は、ポエムを書く予定だったけれど、変換命令`cvt`を紹介する

# 可能な変換早見表

| to \ from | `s16` | `u16` | `f16` | `s32` | `u32` | `f32` | `s64` | `u64` | `f64` |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|`s16`| - | - |`ZAMNP`| - | - |  -  | - | - | - |
|`u16`| - | - |`ZAMNP`| - | - |  -  | - | - | - |
|`f16`|`C`|`C`|  -  | - | - |  `C`  | - | - | - |
|`s32`| - | - |  -  | - | _ |`ZAMNP`| - | - | - |
|`u32`| - | - |  -  | - | - |`ZAMNP`| - | - | - |
|`f32`| - | - | `C` |`C`|`C`|   -   | - | - |`CX`|
|`s64`| - | - |  -  | - | - |   -   | - | - |`ZAMNP`|
|`u64`| - | - |  -  | - | - |   -   | - | - |`ZAMNP`|
|`f64`| - | - |  -  | - | - |  `C`  |`C`|`C`|   -   |

 - `Z`は`rounding-to-Zero`を表し、0に向かって丸め込まれる(いわゆる切り捨て)
 - `M`は`rounding-to-Minus-infinity`を表し、負の無限大方向へ丸め込まる
 - `P`は`rounding-to-Positive-infinity`を表し、正の無限大方向へ丸め込まれる(切り上げに近い)
 - `N`は`rounding-to-Nearest-ties-to-even`を表し、最近接丸めを行う(四捨五入に近い)
 - `A`は`rounding-to-neArest-ties-to-away`を意味し、最近接丸めを行う(四捨五入に近い)
 - `X`は`rounding-to-nearest-odd`を表し、最近接丸めを行う(四捨五入に近い)
 - `C`は丸めモードが`FPCR`レジスタで制御される。デフォルトは切り捨て(`rounding-to-zero`)

# IEEE 754 で制定されている丸め方法
 - IEEE 754で制定されている丸め方法は、以下の5種類が制定されている
    - `rounding-to-zero`
    - `rounding-to-minus-infinity`
    - `rounding-to-positive-infinity`
    - `rounding-to-nearest-ties-to-even`
    - `rounding-to-nearest-ties-to-away`
 - [最新版はIEEE 754-2019](https://standards.ieee.org/standard/754-2019.html)が発行されている
 - このあたり、[だめぽラボさんの浮動小数点数小話](https://techbookfest.org/product/6018416139829248?productVariantID=4928943930998784)を参考にして読んだ。
    - IEEE 754-2019に即して、とても厳密に、詳しく解説している良書である

# NEONでの変換命令
 - 先程の早見表を見れば分かる通り、整数型→実数型への変換は、`FPCR`レジスタによって丸め方法が決まる
    - まあ、整数を実数にするのなら大きい数値を使わない限り、別段心配しなくても良い
    - `int32x4_t`を`float32x4_t`に変換する命令は`vcvtq_f32_s32`である
    - [`reinterpret`の記事](https://qiita.com/tomoaki_teshima/items/63769add9735e09f1737)でも触れたが、末尾に型が2つ付く場合は`<戻り値の要素の型>_<引数の要素の型>`で表される
 - 一方で、実数型→整数型への変換では、`FPCR`レジスタ関係なく、命令ごとに丸め方法が違う
    - なお、非常にややこしいのだが、Arm v7でサポートされているのは`rounding-to-zero`のみである
 - なお、`float64x2_t`から`float32x2_t`への変換だけ、なぜか`rounding-to-nearest-odd`という、[IEEE754 非準拠の変換モード](https://developer.arm.com/architectures/instruction-sets/intrinsics/#q=vcvtx_f32_f64)が使われる命令がある。

# おわりに
 - 浮動小数点から整数型、及びその逆変換を紹介した
 - 明日は最終日の予定で、ポエムを書く予定です
【PostgreSQL】テーブルコメント（論理名）を取得する簡単なコマンド

## テーブルコメント（論理名）を表示したい!
テーブルコメントに論理名が登録されていることがあります。
ex) 物理名に`store`、論理名に`店舗マスタ`が書かれている

DBで`\d+`すれば全てのテーブルが出てきますが、指定したものだけ出したい場合はどうするか。
（`\d+ table名`してもカラムコメントしか出てこない…）

また、以下のサイトのようにSQLで実行する場合はチョットナガイ。
[PostgreSQL/テーブル一覧およびテーブルコメントを表示する](https://db.just4fun.biz/?PostgreSQL/%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E4%B8%80%E8%A6%A7%E3%81%8A%E3%82%88%E3%81%B3%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B)

## 表示方法

DBに入らずターミナル上で下記psqlコマンドを打ち込むとテーブルコメントを確認する事ができます。
※table名は基本小文字。

```shell-session
$ psql -c '\d+' database名 | grep table名
```

以上
PlotlyとDashで平均気温を可視化

これからPlotlyやDashを触る初心者の方にとって、参考になれば幸いです。

###自己紹介
- 20代
- [ビジネスPythonを学ぶ会](https://bizpy.connpass.com/)に参加しています

#分かったこと・できたこと
- 気象庁からダウンロードしたcsv、扱いにくかった
- PlotlyとDashで簡単にデータ可視化アプリが作れた

#データ
[気象庁のページ](https://www.data.jma.go.jp/gmd/risk/obsdl/index.php)からcsvをダウンロードしてきました。

![スクリーンショット 2020-12-22 0.03.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188786/af686d59-e4b4-b847-6a7a-afdf37dc6332.png)
> ポチポチ操作してcsvを取得

取得したcsvを手とpandasで加工しました。
![スクリーンショット 2020-12-22 0.10.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188786/6ddf09fa-078d-48d5-b03c-3ff7019df718.png)
> これを

![スクリーンショット 2020-12-22 0.11.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188786/268c58c9-cd1e-7887-24a9-f98e9cdbb964.png)
> こんなかんじに


#ソースコード
[例の本](https://www.amazon.co.jp/Python-%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96%E3%83%BB%E3%83%87%E3%83%BC%E3%82%BF%E3%83%93%E3%82%B8%E3%83%A5%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%BC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E5%85%A5%E9%96%80-%E2%80%95Plotly-Dash%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E5%8F%AF%E8%A6%96%E5%8C%96%E3%81%A8Web%E3%82%A2%E3%83%97%E3%83%AA%E6%A7%8B%E7%AF%89%E2%80%95-driller/dp/4254122586)を参考に書きました。


```python
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px

import pandas as pd

df = pd.read_csv("./data_processed.csv", engine="python", )
df.set_index("年月日", inplace=True)

app = dash.Dash(__name__)

app.layout = html.Div(
    [
        html.H1("データ可視化 Advent Calendar 20日目", style={"textAlign":"center"}),

        dcc.Graph(
            figure = px.line(df)
        ),

    ]
)

if __name__ == "__main__":
    app.run_server(debug=True)

```

# 実行画面
![スクリーンショット 2020-12-22 0.39.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188786/3c6ee704-4f42-8757-a8bb-0113c38f34f6.png)

# まとめと反省
- 名古屋は（自分のこれまで住んだことのある土地と比較して）暑いなーという感覚は実際あってるみたい。
- 気象庁のデータもPlotlyとDashの機能もまだまだ持て余してるので今後も勉強を続けて行きたい。
- 納期ドリブン、失敗しました。すみませんでした...。
JavaScript~変数・定数~

#はじめに
3回目の今回は変数と定数についてです。この2つはアプリ開発等でもよく利用するので
なるべく分かりやすいよう記載を心掛けています。
そもそも「変数」、「定数」とは文字列や値に名前をつけて繰り返し利用しやすいようにしたものです。
#変数
JavaScriptで変数を利用する場合は次のように記述します。

```JavaScript:変数
let 変数名(好きに決めれる) = 値または文字列
```
変数名については好きにつけることができるのですがその変数に何が入っているのか
分かりやすい名前をつけるのがいいと思います。
https://codic.jp/
のような変数名を生成できるサイトもあるので利用することをオススメします。
使い方の実例としては次のように使います。

```JavaScript:実例
let total = 500;
//変数の「total」に「500」という値を代入しています
alert(total);
//ポップアップで「total」に代入した「500」を表示する。
```
変数は定数と違い値を再代入することができるので

```JavaScript:再代入
let name = '田中';
name = '佐藤';
//最初は「name」に「田中」が代入されていましたが2行目で「佐藤」が再代入されています。
```
また値が代入された変数は代入した値と同じように使うことが出来るので
数値の変数同士で四則演算したり文字同士を結合することができます。

```JavaScript:変数利用
let count1 = 100;
let count2 = 200;
let sum = count1 + count2;
console.log(sum);
//100+200の結果である「300」が出力されます。

let name1 = '田中';
let name2 = name1;
console.log(name2)
//結果は「name1」と同じ「田中」になります。このように変数に変数を代入することができます。
```
#定数
続いては定数です。変数のときは「let」を使用しましたが定数では「const」を使用します。

```JavaScript:定数
const 定数名(好きに決めれる) = 値または文字列
```
定数名に関しても中身が分かりやすい名前をつけるのがいいと思います。
それでは実例になります。

```JavaScript:実例
const total = 500;
//定数の「total」に「500」という値を代入しています
alert(total);
//ポップアップで「total」に代入した「500」を表示する。
```
変数のときにも記載しましたが変数は値を再代入して変えることができましたが
定数は変えることができないので次のようなコードではエラーになります。

```JavaScript:再代入不可
const name = '田中';
name = '佐藤';
//エラーになって出力することができません。
```
変数と同じく定数も四則演算したり文字同士を結合したりできます。

```JavaScript:定数利用
const count1 = 100;
const count2 = 200;
const sum = count1 + count2;
console.log(sum);
//100+200の結果である「300」が出力されます。
```
以上のことから定数は意図しない変更はないのでエラーの防止として利用できます。

#終わりに
変数と定数に関してはもっと色々があるのですが知識が不確かなところがあるので
かなり浅い内容になってしまいました。
今後更に深い内容が投稿できるように勉強していきます。
最後まで読んでくださりありがとうございました。
いまさら聞けない例外処理入門

本記事は[Life is Tech ! Tokai Advent Calendar 2020](https://qiita.com/advent-calendar/2020/life-is-tech-tokai) 23日目の記事になります。

さて、突然ですがみなさん**例外処理ってしてますか？？**

馬鹿にすんな！！当たり前だろ！！！って皆さんはブラウザバックでOKです。

趣味でPythonとか触ってる分には特に意識することもないんですが、コードを書いていればそれなりに必要になる場面があるのでサクッと紹介していきます。（今回はC++を対象に書きますが、どの言語でも構造はそんなに変わらないと思うので自分のメイン言語の例外についても調べてみてください。）

## 2020/12/26 追記
@yumetodo さんよりいただいたご指摘の内容をもとにプログラムを一部修正しました。

## たとえば
まずは以下のような簡単なプログラムを考えます。（プログラム自体に特に意味はありません。）

```.cpp
int hoge(){
    vector<int> array(3);
    array = {1, 2, 3};
    int index = 9;                  // 9番目の要素にアクセスするよ
    int num = array.at(index);         // error : index out of range
    cout << "正常終了" << endl;      // 上の行でエラーが発生するため実行されない（はず）
    return 0;                       // returnもされない（はず）
}
```

3行目に注目すると、`int`型の動的配列`array`の中身は、`{1, 2, 3}`で初期化されています。

つまり`array`の要素数は3つしかないため、要素番号は0～2までしか扱えないはずですね。
しかし、4-5行目で10番目の要素にアクセスしようとしています。要素数が足りないため、ここでは`out of range`のエラーが出るでしょう。(コンパイル時の設定によっては出ませんが、初期化していない要素にアクセスできてしまうのが危険であることは理解できるかと思います。)

## `if`文で処理してみる
想定外の挙動をしないようプログラムを書きたい場合、以下のように条件分岐をしてみるのも一つの手かもしれません。

```.cpp
if (index > array.size()) {
    cout << "異常終了" << endl;
    return -1;                    // 異常終了の場合-1をreturnする
} else {
    // やりたい処理をここに書くよ
}
return 0;                         // 正常終了の場合0をreturnする
```

この場合、戻り値によって処理が正常に終了したか、異常に終了したかを判別することができます。

しかし、上記のようなやり方では**通常の処理と例外処理が混在してしまい（明確に例外の処理だけを切り分けられない）、それに付随して、コードの可読性が下がる**というような問題点があります。

特に複数人で作業をしていたりするとその影響は顕著で、統一的に例外処理が行われていなくコードの読解が難しくなりがちです。（ただの分岐なのかエラー処理なのか分かりにくかったりする）

また、他にもいろいろありますが

>「例外処理　メリット　デメリット」

とかで検索するともっと詳しい方々の説明が出てくると思うので今回は割愛します。

## `try - catch`を使ってみよう
例外は`try - catch`を用いると明示的に監視できます。
処理自体は`try`、`throw`、`catch`という3つのキーワードから構成されます。

**今日はこの３単語だけ覚えて帰ればOKです。**


### 手順1. `try`ブロックを記述しよう
まず、例外が発生する可能性のあるコードを`try`ブロックとして`{ }`で囲みます

```.cpp
try {
    //例外が発生する可能性のあるコード
}
```

### 手順2. 例外を`throw`しよう
`throw`を実行することで、例外を投げることができます。
`throw`の使い方は`return`と同じような雰囲気であると捉えればよく、

```.cpp
try {
    //例外が発生する可能性のあるコード
    throw exception;
}
```

のような形になります。`exception`には投げる例外の値を指定します。

`throw`で例外を投げるとプログラムの実行は`try`ブロックから即座に抜け出し、投げられた例外に対応した`catch`ブロックへと移ります。

### 手順3. `catch`ブロックを記述しよう
`try`ブロックの中で例外が発生した場合、`catch`ブロックでそれを受け取ります。
`catch`ブロックは例外を受け取るとブロック内に記述されている例外処理を実行するため、ここでは例外を受け取った場合の処理を用意します。

```.cpp
catch (type arg) {
    //例外処理
}
```

`type arg`には、型と変数名を指定します。
一般的にはポインタの形式で記述して参照を渡すことが多いです。（不要な値のコピーを回避するため）

`catch`ブロックは発生した例外が`type arg`部分の型と一致した場合に実行されます。
**`catch`ブロックは、`try`ブロックの直後に記述します。**

### プログラム例
上記を踏まえて、最初のサンプルプログラムを改良したのが以下のプログラムになります。

```.cpp
int hoge(){
    vector<int> array(3);
    array = {1, 2, 3};
    int index = 9;

    try {
        if (index >= array.size()){
            throw "error : index out of range.\n";
        }
    } catch (char *str) {
        cout << str;
    }

    int num = array.at(index);

    return 0;
}
```

`index`が配列の要素数を超えていた場合の処理を`try`ブロック内に記述し、分岐内で例外を`throw`しています。
誰が見てもこの部分のコードは例外処理だとわかるようになりましたね。


## 今北産業
- 例外処理しようね
- 基本はtry - catchで書くよ
- throwで例外投げるよ

## おわりに
例外処理って必要に駆られないとなかなか触れる機会がないと思うので、これを機に今後の開発で意識されるようになればと思います。
GitHub Actions！PlantUMLソースから画像ファイルを自動生成＆コミット！

GitHub Actionsを初めて使ってみました。
色々情報探すの苦労したので自分的メモも含め記載します。

# 作ったもの
[PlantUML](https://plantuml.com/ja/)ファイルをPushするとそれに対応したファイルを生成してCommit&Pushするコードを作りました。

```create-plantuml-images.yml
# /${PlantUMLのファイルが置いてあるディレクトリ}/*.puml のソースコードから画像ファイルを生成する
# トリガー：上記のソースコードの変更・追加がpushされること
# 実行環境：macOS Big Sur 11.0
name: Create PlantUML Images

# トリガー
on:
  push:
    paths:
      - ${PlantUMLのファイルが置いてあるディレクトリ}/*.puml #eg. docs/sequence-diagrams/*.puml

# 実行内容
jobs:
  build:
    runs-on: macos-11.0
    steps:
      #git checkout
      - uses: actions/checkout@v2
      #PlantUMLのパッケージインストール
      - name: Install packages
        run: |
          brew install plantuml
      #画像生成（最後のlsはGitActionのコンソール上で結果確認するため）
      - name: Create Images
        run: |
          cd ./${PlantUMLのファイルが置いてあるディレクトリ}
          for puml in `ls -a *.puml`
          do
            cat ./${puml} | plantuml -tsvg -p > ./${puml%.*}.svg
          done
          ls -l
      #git commit & git push
      - name: Commit changes
        uses: EndBug/add-and-commit@v5
        with:
          message: 'Create image files by GitHub Action(create-plantuml-images.yml).'
          add: './${PlantUMLのファイルが置いてあるディレクトリ}/*'
          push: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # ここはおまじない的に必須
```


# ここからGitHub Actionsのメモ
## 定義ファイル
### 配置場所
* `/.github/workflows`配下に配置する。yml形式で記述。

### テンプレートが豊富
* GitHubサイトでActionsを作ろうとすると、以下のようにテンプレートが複数用意されている。
* 欲しいところの`Set up this workflow` ボタンを押すとymlファイルが表示されるので、これをコピペすると楽。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105059/69926eea-dec0-bdef-aa6f-20b5606f266b.png)


## [起動条件](https://docs.github.com/ja/free-pro-team@latest/actions/reference/events-that-trigger-workflows)
* PushやPRなどのイベント×ファイルパス×追加・更新・削除　を組み合わせて指定することが可能。
* cron的な指定も可能。
* Pushを設定してもGitHubAction内でPushされても起動しない（らしい）。

## [実行マシン](https://docs.github.com/ja/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on)
ざっくり以下が利用可能。macOSを使えるのが個人的に嬉しい。
* WindowsServer
* Ubuntu
* macOS

## Gitへのアクセス
### Checkout
`actions/checkout@v2`
これだけでOK。勝手にトリガーとなったBranchをCheckoutしてくれる。
認証周りの設定は不要。

### Commit & Push
`EndBug/add-and-commit@v5` を利用([こちら](https://github.com/marketplace/actions/add-commit))。
コミットメッセージと対象ファイル、Pushするという属性を入れるだけでよい。
より細かい設定も可能。

## 動かない！？
Actionsタブを開いた際に以下のメッセージが表示されている場合、GitHubActionsが使えません。
古い課金モデル（リポジトリ数）だと使えないので新しい課金モデル（メンバー数）に契約を変更してもらいましょう。
> GitHub Actions workflows can't be executed on this repository.
> The billing plan for XXXXXX does not include access to GitHub Actions. Please contact the organization owner or billing manager for questions about the current billing plan

## 所感
* わずらわしい認証周りのやりとりがなく、スッキリ記載できました。
* 新規作成時はテンプレートファイルも豊富で、Docker HubのコンテナイメージやDockerfileも利用可能なので、簡単に色々組めそうな印象を受けました。これから使っていこうと思います。
Dockerコマンドメモ

職場では備忘録作っていたので、プライベート用に
殴り書きなので間違っているかも知れぬ。

## ○イメージ関連の操作

#### イメージの一覧の確認

```
# docker images
```

#### Docker Hubからイメージのpull

```
# docker pull <リポジトリ>:<タグ>
```

centOS8のイメージが欲しけりゃ、リポジトリがcentos、タグが8で「centos:8」とする。

#### 既存コンテナからイメージの作成
```
# docker commit <コンテナ> <リポジトリ>:<タグ>
```

#### イメージの削除
```
# docker rmi <リポジトリ>:<タグ> or <イメージID>
```

### Dockerfileからイメージを作成する

```Dockerfile:Dockerfile
FROM centos:8

RUN dnf update

RUN dnf install -y openssh-server openssh-clients

EXPOSE 22
```
```
# docker build -t <リポジトリ>:<タグ> <Dockerfileのあるディレクトリ>
```

## ○コンテナの操作

#### コンテナの一覧
```
起動しているコンテナの一覧
# docker ps
全てのコンテナの一覧
# docker ps -a
```

#### イメージからコンテナを作成
```
# docker run　-d --name <作成するコンテナ名> <リポジトリ>:<タグ> 
```
個人的によく使うオプション
-i コンテナの STDIN にアタッチ
-t 疑似ターミナルの割り当て
-d コンテナをバックグラウンドで実行し、コンテナ ID を表示
-p ポートの公開
-e 環境変数の設定
--name コンテナ名
--priviledged 拡張権限の付与
-v [localのパス]:[マウント先のパス] コンテナにマウントする

※コンテナでデーモンを使用する場合は起動シェルに「/sbin/init」を指定する。

```
# docker run --privileged -d --name test centos:8 /sbin/init
```

#### コンテナの起動
```
# docker exec -it <コンテナ> /bin/bash
```
コンテナをbashで起動する

オプション
-i アタッチしていなくても STDIN をオープンにし続ける
-t 擬似ターミナルの割り当て

#### コンテナの起動・停止
```
起動
# docker start <コンテナ名>
停止
#docker stop <コンテナ名>
```

#### コンテナの削除
```
# docker rm <コンテナ名>
```
コンテナが停止していないと消せない。
起動しているものを消す場合は「-f」オプションをつければ、強制的に削除できる。
aws lambdaでPython + Selenium + Headless Chromium

Lambdaでスクレイピングを定期実行してDynamoDBに貯めるアプリケーションを作っています。

早速ググるとたくさん記事が出てくる。ありがたい。
こちらの記事を参考にさせていただいてトライしていたが、2日くらいハマってしまったポイントがあったのでメモ。

https://masakimisawa.com/selenium_headless-chrome_python_on_lambda/


* chromedriver 2.43　https://chromedriver.storage.googleapis.com/index.html?path=2.43/

　　　こちらの`chromedriver_linux64.zip`

* serverless chrome v1.0.0-55　　https://github.com/adieuadieu/serverless-chrome/releases/tag/v1.0.0-55
　　　`stable-headless-chromium-69.0.3497.81-amazonlinux-2017-03.zip`

* selenium 3.14 

   cloud9(AmazonLinux)から持ってくる　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317324/5a9af926-128c-6631-d87b-6129785d8044.png)

lambdaレイヤーはPython3.6
当然lambdaのランタイムも3.6

# ハマりポイント

何度もバージョンを確認したが、lambda上で以下のエラー
`Chrome failed to start: exited abnormally\n  (unknown error: DevToolsActivePort file doesn't exist)`

以下の記事など、オプションにいくつか追加することで直るという意見が多い。
https://stackoverflow.com/questions/50642308/webdriverexception-unknown-error-devtoolsactiveport-file-doesnt-exist-while-t

記事ではjavaコードだが、Pythonに直して、

```
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--no-sandbox")
```

しかし

別のエラーが発生
`unknown error: unable to discover open window in chrome`



結局、上記のいくつかに加え、この記事の
`options.add_argument("--single-process")`
を足すことで解決した。　
https://stackoverflow.com/questions/60229291/aws-lambda-ruby-crawler-selenium-chrome-driver-unknown-error-unable-to-discov

`options.add_argument("--headless")`に加えて、最終的にトラブルシューティングとして追加したオプション設定はこちら

```    
options.add_argument("--single-process")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--no-sandbox")

```


#　ハマりポイント　もう一個
lambdaにレイヤーをアップロードする際、
headless-chromeというdirにheadless-chromeとchromedriverおいてzip化したのだが、7zipでやるとexecutable may have wrong permission みたいなエラーで動かず。
色々見てると、windowsのzipだと、デプロイパッケージがうまく動かないらしいので、wslのubuntuでzip化したら。この問題は解決した。

## 備考

スクレイピングの方法について、Cloud Funtion + Typescript Puppeteerとも迷ったが、

* 書かなければいけないスクレイピングの件数が非常に多く、スクレイピングコードを快適に書けることを重視したい
* Ajaxを使ったサイトからも正しく情報を取得したい
* AWS勉強したい
ということで、個人的に単純明快に扱えると感じたSeleniumをlambda上で動かすことにしました。
FactoryBot　同じモデルで複数のデータを登録

Rspecのモデルテストで、同じモデルのデータを複数生成する方法です

####生成の仕方
```factories/tweets.rb
FactoryBot.define do
  factory :tweet_1,class: Tweet do
    text {"おはようございます"}
  end

  factory :tweet_2,class: Tweet do
    text {"こんにちは"}
  end

  factory :tweet_3,class: Tweet do
    text {"こんばんわ"}
  end
end
```

####定義の仕方

```spec/models/tweets_spec.rb
let(:tweet_a) { create(:tweet_1) }
let(:tweet_b) { create(:tweet_2) }
let(:tweet_c) { create(:tweet_3) }
```
Gibberによるオーディオプログラミング例

Gibber
===

[オーディオプログラミング言語 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/audiolang)

# 概要

https://gibber.cc/
https://github.com/gibber-cc/gibber
https://bigbadotis.gitbooks.io/gibber-user-manual/content/

Webブラウザで高レベルのオーディオ合成とシーケンスを実行するための言語とライブパフォーマンス環境。JavaScriptのAudio機能を、より簡潔な記述で扱えるように設計されている。2D/3Dグラフィックや複数人によるコラボレーション機能もサポートしている。MITライセンスのオープンソースソフトウェア。

カリフォルニア大学のCharles Robertsにより開発。初出は2012年(*1)

(*1) C.Roberts and J.Kuchera-Morin,"Gibber: Live Coding Audio In The Browser," in Proceedings of the International Computer Music Conference, 2012, pp. 64–69.

# 実装例

## サイン波生成

Sine関数で簡単に音を鳴らすことができます。引数は値でもJSONでも与えることができます。  
実行はソースの対象部分を選択してCtrl+Enter、終了はCtrl+.です。

```JavaScript
Sine(440, 0.5)

Sine({ frequency:440, amp:0.5 })
```

## Delayエフェクト

GibberはWebアプリということもあり、任意のwavファイルを鳴らすことはできません。それでもいくつか近い機能は用意されています。

* Sampler()を使ってマイク入力などを録音して鳴らす
* Soundfont()を使ってあらかじめ用意されているサンプリング音を鳴らす
* Freesound()を使って https://freesound.org/ にアップロードされている音を鳴らす

今回はFreesound()を使いました。

また、Gibberのディレイも独特な仕様になっています。

* ディレイタイムは1/4（四分音符）、1/8（八分音符）などと音符の長さで指定する。つまりBPMの影響を受ける
* フィードバックを0にするとシングルディレイ
* 初回のディレイ音はドライ音と同じ音量
* ドライとウェットの音量調節や個別出力は不可

そのため、今回他の言語のサンプルプログラムと同等の音にすることはできませんでした。ディレイタイムについてはms()関数を使うことでミリ秒指定できるようです。

```JavaScript

voice = Freesound(213284);
// the sampling audio is licensed under Creative Commons BY Attribution 3.0 AderuMoro.
// https://freesound.org/s/213284/
// https://www.youtube.com/user/AderuMoro

Clock.bpm = 120
delayTime = ms(400)
feedbackLength = 0.5

delay = Delay({ time:delayTime, feedback:feedbackLength })
voice.fx.add(delay)

voice.note(1)
```

# 感想

インストール不要でWebブラウザがあれば音と映像のライブコーディングができる環境は手軽で便利です。ユーザインタフェースも洗練されていてわかりやすいのも良い点です。言語自体はシンプルなのですぐに覚えられると思います。今回は触れられませんでしたが、TidalCyclesのようなループシーケンサーも簡単に書くことができます。

freesound.orgの音を簡単に鳴らせるのは表現の幅が大きく広がるので楽しいです。ちなみにfreesound.orgの音を鳴らす機能はOvertone言語にも用意されています。TidalCyclesのDirt Samplesなどと並んで、ライブコーディングに使うサンプリング素材のスタンダードと言えるかもしれません。

一方で2020年12月現在バグのような挙動やドキュメントの不備があり、使っていて戸惑うことが多かったです。変数の内容を表示するようなデバッグ機能もないため、原因を追うのに時間がかかります。

* プレイグラウンドのhelpのリファレンスマニュアルがリンク切れになっている
* おそらくClock.bpmにバグがあり、120以外のときは正しいテンポにならない。たとえばClock.bpm=155とすると実際にはBPM200くらいになる
* ディレイタイムもテンポに依存するのでBPM120以外のときは正しい長さを指定するのが困難
* Freesoundで同じサンプルを再度取得しようとすると失敗して鳴らせない

Version2のプレイグラウンド( https://gibber.cc/alpha/playground/ )もあり、テキストエディタ内にデータが変動するアニメーションが表示されるなどとても魅力的なのですが、これはこれでアルファ版でVersion1とはまた違ったバグが出たのであまり触っていません。

このあたりの使いづらさが解消されたら、手軽なライブコーディング環境として選択肢のひとつになるように思います。

[オーディオプログラミング言語 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/audiolang)
Disaster Recovery とは

## 勉強前イメージ

災害起こったときどうする？って計画のイメージ
オンプレとクラウドでサービスを作っておくとか、
クラウドの中でも別拠点での構築とかそんなイメージ

## 調査

### Disaster Recovery とは

Disaster Recovery(ディザスタリカバリ) とは略してDRとも呼ばれます
日本語では災害復旧ともいわれます。
地震や津波などの天災や、テロ、不正侵入などによりシステムが壊滅的な状況になった際に復旧・修復することを指します。

### Disaster Recovery で考えないといけないこと

Disaster Recovery を構築するには、メインのデータセンターやクラウド以外に別の地点でバックアップを取る必要があります。
また、復旧方式には3つポイントがあります

- RPO : Recovery Point Objective
	- どの地点のデータまで戻すのか
- RTO : Recovery Time Objective
	- いつまでに復旧させるのか
- RLO : Recovery Level Objective
	- どの程度の業務レベルまで戻すのか

RPOとRTOに関しては [こちら](https://qiita.com/miyuki_samitani/items/126087d86386bf512ca4) に詳細を記載しています

### 復旧レベルの例

| 復旧レベル                   | コスト | DR方式                                         | 概要                                                             | 
| :----------------------------: | :------: | :----------------------------------------------: | :----------------------------------------------------------------: | 
| RPO : 数週間<br>RTO : 数日   | 低     | テープメディアへのバックアップ                 | バックアップデータをDR倉庫へ運搬                                 | 
| RPO : 1,2日<br>RTO : 数日    | 中     | 非同期バックアップ                             | バックアップデータをクラウドにコピー                             | 
| RPO : 数時間<br>RTO : 数時間 | 中     | 非同期レプリケーション<br>手動フェイルオーバー | 本番システムと非同期でレプリを行い、手動でフェイルオーバーさせる | 
| RPO : 数分<br>RTO : 数分     | 高     | 同期レプリケーション<br>自動フェイルオーバー   | 本番システムと同期レプリを行い、自動でフェイルオーバーさせる     | 
| RPO : 数秒<br>RTO : 数秒     | 高     | システム同期                                   | どちらのシステムも本番として使用                                 | 

- テープメディアへのバックアップ

バックアップデータをテープに保存して、DRの倉庫に運搬する方法
この方法ではコストは安いですが、復旧までに大幅な時間がかかり
24h365dayのシステムでは適していません。

- 非同期バックアップ

データを別のシステムにネットワーク経由でバックアップをとっておきます。
災害が発生した際は、バックアップからデータをとってきて本番のシステムに適応を手動で行います。
復旧までの手順などおいて置かなければいけません。

- 非同期レプリケーション, 手動フェイルオーバー

本番と同じようなシステムを別に用意しデータを追従しておき、万が一が起こったときには別のシステムの方を稼働させる方式。
手動でフェイルオーバーをしないといけないので夜中であればフェイルオーバーまでの時間がかかったりすることがあります

- 同期レプリケーション, 自動フェイルオーバー

本番と同じようなシステムを別に用意しデータを同期しておき、万が一が起こった際には自動で別システムに切り替わる方式。
これであれば数秒から数分で復旧し、データも同期しているのであまり遅延はありません。
ですが、システムを構築する際のテストが多くなったり、その上に新しいシステムを作る際には気をつけないと万が一のときに自動で切り替わらない可能性があります。

- システム同期

こちらは万が一の際でもシステムをほぼ落とさずに稼働し続ける方法。
本番のシステム、また別で用意したシステムをどちらも本番システムとし、片方落ちても片方で受けることができます。
しかしその分、2システム稼働させるのでコストは大きいですが、復旧までの時間は早いです。


## 勉強後イメージ

要件定義でよく考えないといけないもの....
そして自動フェイルオーバーって実際結構動かない！ってのもあるんじゃないかなと思う

## 参考

- [用語集｜DR/ディザスタリカバリ](https://www.idcf.jp/words/dr.html)
- [ディザスタリカバリシステムの考え方](https://jpn.nec.com/solution/bcdr/dr_system01.html)
- [DR（ディザスタ・リカバリ）について徹底解説！BCPとの違いは？](https://bcp-manual.com/bcp/risk/dr_bcp/)
[Rails] [親子関係] 親を削除した時、子にある外部キーをnilで登録したい

## 概要
以下の親子関係をreferenceでリレーション構築している際、
親モデルのデータ削除時に、子である商品データは削除せずに外部キーがnilで登録されるようにしたいがコンソールから親を削除した際にエラーが出て対処方法がわからず少し困った話です。
・親モデル："カテゴリー"
・子モデル："商品"

```20201211121059_create_products.rb
  t.references :category, null: false, foreign_key: true
```

## 実践
以下の記事などを参考に実施した。
optional: trueを設定すれば、nilを許可する方法
https://techtechmedia.com/optional-true-rails/#optional_true
https://qiita.com/takuyanin/items/6f6be86d1265be21bf9e

こんな感じでhas_many, belongs_to にdependent, optionslのオプションを付けた。

```catedory.rb
class Category < ApplicationRecord
  has_many :products, dependent: :nullify
end
```

```product.rb
class Product < ApplicationRecord
  belongs_to :category, optional: true
end
```

この状態で、コンソールから親子のデータを登録。
>例
>category = Category.create!(....)
>category.products.create!(....)

試しにCategory.destroy_allを実行。子の外部キーがnil登録されるんだよね？
以下のエラーが出て、対処法に困る。
>ActiveRecord::NotNullViolation: Mysql2::Error: Column 'category_id' cannot be null

また外部キーnilでの子モデルデータ新規作成時は、optional: trueの設定/未設定でエラーが違う。

>※設定時
>ActiveRecord::NotNullViolation: Mysql2::Error: Field 'category_id' doesn't have a default value

>※未設定時
>ActiveRecord::RecordInvalid: Validation failed: Category must exist

そもそもoptional: trueって？
trueにすると外部キーに値が入っていなくても、バリデーションをパスすることができる。
↑**つまり問題はバリデーション**
（デフォルトの未設定時はfalseなので、バリデーションを実行する。）

## 解決へ
（up, downの記法で、rails db:rollbackも可能）

```
class ChangeReferencesIdToProducts < ActiveRecord::Migration[6.0]
  def up
    change_column :products, :category_id, :bigint, null: true
  end
  
  def down
    change_column :products, :category_id, :bigint, null: false
  end
end
```

null: falseが原因だったので、null: trueに変更することで
親を削除しても子の外部キーはnilで登録されるようになりました。

どなたかのお役に立てれば幸いです。
空き家を活用した地方創生と若手教育

趣味で書いた論文を晒します．
タイトルは「空き家を活用した地方創生と若手教育」です．
https://drive.google.com/file/d/16zskwECNh1zgIPV5a3ee84a0qocXziN8/view?usp=sharing

今後，大学と連携してプロジェクトを進めたいと考えています．
1セグメント全断の土曜日 Part2

## 1セグメント全断の土曜日 Part2

これは [本番環境でやらかしちゃった人 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/yarakashi-production) の22日目です。昨日はreal_yaruoさんによる[消しちゃった系のお話](https://qiita.com/real_yaruo/items/7e2eb9a28d42b3165c83)でした。私も消えちゃった系の対応をさせられたことがあります。そんな時のためにsash(stand-alone shell)いいですよ、sash。

さて本記事は[昨年の記事](https://qiita.com/Words4MyRegret/items/e0b70aff25412655b9ed)の続編となります。

### tl;dr 兼 原因と対策
CDNを使ってもオリジンサーバーにアクセスはそれなりに来る。来る時は来る。
来てもいいようにレートリミットと帯域確保を行っておくこと。

### 経過
#### 予兆
10年以上前のお話です。たぶんフィクションです。
木曜日にお客様から「週末ちょっとトラフィック増えるかも」というご連絡がありました。

#### 発生
何事も無く始まった土曜日... 昼過ぎになって出かけていた私の携帯電話が鳴りました。
「第2セグメントのサーバー2台の監視が断続的にエラーになっています。」

確かに接続しにくい状態になっていたのでオンサイトの準備を始めた時に再び電話が鳴ります。「第1セグメントのサーバーすべての監視が通りません！」
昨年はこの第1セグメントについて書きました。

さて第1セグメント全断の対応をしている間も最初に連絡のあった"第2セグメントのサーバーたち"は断続的にエラーを出し続けていました。
...そしてついに「第2セグメントのサーバーすべての監視が通りません！」という連絡が来てしまうのです。

#### 調査
すでに各種アラート通知でメールボックスはあふれかえっています。読み解くのも時間がかかりそうなのでまずは第2セグメントのサーバーがあるラックの現地へ向かいます。
断続的なエラーを上げていたサーバーにコンソールをつないで確認するとコネクションがあふれかえっています。そうこうしているうちにコンソールに kmem_alloc のエラーメッセージまで
帯域使用率を確認するとそちらもほぼ輻輳していることが分かりました。

#### 原因特定
元々アクセスの多いサイトだったのでCDNも挟んでいたのですが、CDNのエッジサーバー群からオリジンサーバーへのリクエストさえさばききれない規模の大量のリクエストが来ていたようです。
(この時いわゆるヤ○ートップ砲も相まって想定をはるかに上回るアクセスがきていたようでした。)
CDNを挟んでいたので第1セグメントの対応をしている間はギリギリ耐え切れていたとも言えます。

#### 対応
スケールアウトしながら時間を稼ぎました。予備系サーバーを起動し、ネットワークの増速とレートリミットを調整しながらトラフィックを回避させて凌ぎつつ、徐々にアクセスを捌いていきました。

#### できていなかった対策、行った対策
CDNに安心しきってオリジンサーバー側基盤のキャパシティ見積もりができていませんでした。サーバー単独では無くセグメントを巻き込んでしまったのは完全にキャパシティもしくはレートリミットの設計ミスと言えるでしょう。対策としてアクセスポートとアグリゲーションポートの帯域バランスに基づいたレートリミットを安全側に寄せた閾値で見直しを行いました。
また元々トラフィックの多いサイトでしたので、今回のような緊急時には軽量のSorryページへ切り替えるなどの対策も事前に検討しておくべきでした。

#### 補足
予兆のところを思い出してみます。
> 木曜日にお客様から「週末ちょっとトラフィック増えるかも」というご連絡がありました。

全然"ちょっと"じゃねーよ、という思いを抱えながら対応していたのを今でも思い出します。

さてここまで手探りしながら一連の対応をする中で、実は余計なこともしてしまっていました。

そう、この日はさらにもう1つのセグメントが全断するのですが
それを記すには余白とSAN値と応援が足りません――
競プロ(Python)で優先度キューはheapq？queue.PriorityQueue？どちらを使うべき？

Pythonの優先度付きQueueは以下の２種類があります。速度を比べてみました。

- heapq
- queue.PriorityQueue

# はじめに
一見、

> class queue.PriorityQueue(maxsize=0)
優先順位付きキューのコンストラクタです。maxsize はキューに置くことのできる要素数の上限を設定する整数です。いったんこの大きさに達したら、挿入はキューの要素が消費されるまでブロックされます。もし maxsize が0以下であるならば、キューの大きさは無限です。

ということでqueue.PriorityQueueは名前からしても良さそうです。しかし、queue自身は、

> queue モジュールは、複数プロデューサ-複数コンシューマ(multi-producer, multi-consumer)キューを実装します。これは、複数のスレッドの間で情報を安全に交換しなければならないときのマルチスレッドプログラミングで特に有益です。

ということで、明らかに重い(同期のための動作が入っていそう)です。

# やったこと
- $ 2 \cdot 10^{5} $ 個のランダムな正の整数($\leq 10^{9}$) からなる配列aを用意します
- 別の$ 2 \cdot 10^{5} $ 個のランダムな正の整数($\leq 10^{9}$) からなる配列bを用意します

次に、以下の動作を$ 2 \cdot 10^{5} $回行います。(i回目の操作とします)

- aから最も小さい数字をとる。次にbのi個目の要素をaに追加する

これを、heapqとqueueで比較します。なお、上記の作業を行うとき、heapqはpopしてpushするより、pushpopを使った方が高速なのでその速度も比較します。

# 結果
```
--- Heapq, poppush
elapsed_time:0.15400314331054688[sec]
--- Heapq, pop then push
elapsed_time:0.20299005508422852[sec]
--- Queue
    Step1: create init queue
elapsed_time:0.37195301055908203[sec]
    Step2: pop then push
elapsed_time:0.873100996017456[sec]
```

ということでPythonで(競技プログラミングにおいて)優先度付きキューを使うときはheapqを用いましょう。尚、queue.PriorityQueueはinitがないので最初に配列aを１つずつ作ったqにpushしています。

# コード
```Python
import queue
import heapq

import time
import random
from copy import deepcopy
n = 2 * 10**5

inqueue = [random.randint(0, 10**9) for _ in range(n)]
inheapq = deepcopy(inqueue)

data = [random.randint(0, 10**9) for _ in range(n)]

resqueue = []
resheapq = []

print("--- Heapq, poppush")
start = time.time()
heapq.heapify(inheapq)
for i in range(n):
    x = heapq.heappushpop(inheapq, data[i])
    resheapq.append(x)
elapsed_time = time.time() - start
print("elapsed_time:{0}".format(elapsed_time) + "[sec]")

print("--- Heapq, pop then push")
start = time.time()
heapq.heapify(inheapq)
for i in range(n):
    x = heapq.heappop(inheapq)
    resheapq.append(x)
    heapq.heappush(inheapq, data[i])
elapsed_time = time.time() - start
print("elapsed_time:{0}".format(elapsed_time) + "[sec]")

print("--- Queue")
print("    Step1: create init queue")
start = time.time()
q = queue.PriorityQueue(n)
start = time.time()
for i in range(n):
    q.put(inqueue[i])
elapsed_time = time.time() - start
print("elapsed_time:{0}".format(elapsed_time) + "[sec]")
print("    Step2: pop then push")
start2 = time.time()
for i in range(n):
    x = q.get()
    resqueue.append(x)
    q.put(data[i])
elapsed_time = time.time() - start2
print("elapsed_time:{0}".format(elapsed_time) + "[sec]")

```
外部サイトへの「埋め込みjsタグ」を作る際に気をつけていること

いいねボタンやLTGMボタンのようなブログパーツ、ガジェット等
自分で作った、javascriptタグを他のサイトに埋め込んで使ってもらう時、色々心配ごとが多いですよね。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/03a0ad21-6b60-cafa-3b92-0e906d1bbb19.png)


そんな時に僕が気をつけていることをざっくりですが書かせていただきました。
※Adventカレンダー初投稿です。。お手柔らかに。汗　あと滑り込みすみません、、、！

# ズバリ気をつけていること..

## 更新性
外部サイトにjsを埋め込んでもらったあとに、
「やべ...これって外部サイト側のタグ自体を修正しないと:scream:」
ってことにならないように、サーバーサイド側で修正もできるようにしておく。

GAタグ等を参考にこれぐらいにしてサーバーサイドで更新できるようにしておく。

```html:site.html
<!-- 埋め込みjsタグ -->
<script async src="https://example.jp/jstag?id=12345"></script>
<script type='text/javascript'>
hogetag('config', 'ABCDE')
</script>
```

※個人的に`script type="text/javascript"`を記載すると安心できますがhtml5から記載しなくてもデフォルトでその設定なので今回は記述しません。

ここでまたjsの読み込みタイミングに気をつける。
`async`で非同期で読み込んでOKなものか、
`defer`でhtmlが完全に読み込み終わった後に実行するのか、
もしくはjsタグがある任意のタイミングか、、等。
[こちら](https://qiita.com/phanect/items/82c85ea4b8f9c373d684)記事がとてもわかりやすくなってまとめて頂いているのでご参考に。

## 作ったjsタグが原因で外部サイト側に迷惑をかけてしまわないように.. 

### jQuery等、他のライブラリに依存しないよう純粋なjavascriptで書く
よくjqueryが使われていることが多いですが、jqueryライブラリや他のjsライブラリがなくても
動くようにピュアなjsで書くことをおすすめします。
別ライブラリ等使うとそのライブラリが更新性も意識しないといけなくなるため。

### スコープを使って埋め込み先のサイトの変数や関数等と衝突しないように気をつける

スコープをつけずに`check()`等の関数名を作ってしまうと、すでにその関数が外部サイトで使われていて、
jsエラーってなんてこともありえます。。汗

最初の例では、hogetag()という名前で作ってしまっていますが、
**即時関数**で絶対領域を作り、関数内でしか操作できないようにするということできます。
まさに、埋め込みjsタグの為にあるのでは！と思ってしまいます。

```javascript:server.js
(function () {
    //jsタグのメイン処理等
}());
```
js即時関数については[こちら](https://qiita.com/katsukii/items/cfe9fd968ba0db603b1e)の記事がとても参考になります。

※もちろんjavascriptの予約語にも気をつけよう。→[参考](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Reserved_Words)

### セキュアになっているか

* もちろん通信はhttpsで（https://の外部サイトにhttp://のjsタグや画像があるとエラーになります。。）
* ブラウザの見える範囲で、改ざんできるような重要なクエリ等入れていないか等。（サーバーサイドのphp等で大事なところは見えないように等）

### 読み込みに時間がかからないように、またはかかっても良いように作る

* でかい画像を読み込んでないか
* cssファイルが重い処理はないか
* ajax通信などリクエスト数が多くないか等。
* キャッシュをうまく使っているか等（クエリに時間`?t=1608562686`などいれて適宜キャッシュを更新する等）

## jsタグで生成するnode（htmlタグ）等は適切か

W3C等参考に、とりあえずdivになっていないか等。

## 難読化＆軽量化する

jsタグがある程度完成したら、
難読化してリバースエンジニアリング対策や、
jsタグの読み込み速度UPのために、軽量化も検討してみてはいかがでしょうか？
また、かっこよくcopyrightをつけたりｗ

難読化/軽量化できるサイト

* https://obfuscator.io/
* https://tools.arashichang.com/html_pack.html

## 各ブラウザでチェック

有名な下記ブラウザチェックツールを使うと楽できると思います。
※無料版と有料版あり

* BrowserStack https://www.browserstack.com/
* Browserling https://www.browserling.com/


またスマホ向けの場合は、xcodeのiOSシミュレータや、Androidエミュレータでもテストできますが、
実機とjsの挙動が変わることがあるので実機でテストするのをおすすめします。

最後まで読んでいただきありがとうございました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/effac786-9ebf-6324-5d3d-b611539c7d90.png)
関西弁アジャイルソフトウェア宣言（12の原則）

## アジャイルソフトウェア開発宣言とは
アジャイル開発のベースとなる「マインドセット」やで。
そのマインドセットを支える12の原則を紹介するで。

## 1.顧客のビジネスを成功させる。ええもんを早く、継続的に
顧客が求めてるのはソフトウェアじゃなくて、
**作ったソフトウェアをつかって、ビジネスを成功させる事や。**
なので、市場に早くはいれるように、さっさとええもんをつくるんや。
そして、継続的に支えるで。

## 2.開発後期で、仕様変更！？ 全然ええよ
開発後期って形になってきてる事多いから、それみながら、ええこと思いついたりするよな。
だから全然ええで。一緒にビジネス成功させよう。
成功確率は最後まで高めよう。

## 3.なるべく短いスパンでリリースするで
動くもん、全然みれんかったら顧客は怖いよな。動くもの触りながら、ビジネスの事考えたいやろし。
だから2-3週、2-3ヶ月の短いスパンで、リリースするよ。一緒にビジネス成功させよう。

## 4.顧客さん、一緒に仕事しよう。そして一緒に成長しよう
お互いの事わからな、ええもんってつくられへんよな。
だから一緒に働こう、ソフトウェアの事ならこっちはプロやから、なんでも聞いてや。
お互いの事、わかり合って一緒に成長しよう。

## 5.意欲あるメンバーで最高のチームつくるで
意欲あるチームメンバーと、今与えれる最高の環境は用意したやで。
プロジェクト最後まで顧客もエンジニアも信頼しあって仕事しようや。

## 6.みんな顔つきあわせて、情報交換しよう
顔見て話しよう。やっぱり人間それがええ。

## 7.進捗？？動いてるこのソフトウェアを見てもらうのが一番や
いろんな進捗報告あるけど、動いてるソフトウェア見てもらうのに勝る進捗共有はないやで。

## 8.一定のペースでながく顧客と関わるで
ビジネスの成功って、時間かかるよな。
急ぎすぎで息切れするんじゃなくて、一定かつ最高のペースで長く関わろうや。

## 9.技術と設計力いるで
ちゃんと設計してるから、小回り効くし、
技術力あるからいろんな要望答えれるで。
成長には貪欲やで。

## 10.無駄はいらん
無駄なく常にシンプルでクリーンでいよう。
サービス設計もソースコードも組織も。

## 11.ええもんつくるなら、自主性が大事やで
1人1人が自主性をもって、リーダーシップとったら、
自然とええもんできてるんやで。

## 12.定期的に「振り返り」するで
チームがちゃんと効率的に動けているか、定期的に振り返りするで。
常に良いやり方を貪欲にさがしていこう。

## 最後に
多少（かなり？？）意訳してる箇所もありますが、
アジャイル開発を約2年経験して、この12の原則がほんとに大切だと感じます。
振り返りなどの詳細な手法は、興味があれば色々と調べてみてください。
アジャイルサムライおすすめです。

[アジャイルサムライ](https://www.amazon.co.jp/dp/B00J1XKB6K/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)


## 原典はこちら
https://agilemanifesto.org/iso/ja/principles.html
フレームワークや言語の技術トレンドの調査に便利なサイト5選


# 便利なサイト5選

- [Google Trends](https://trends.google.co.jp/trends)
  - Google 検索での比較
- [QiiTrend](https://qiitrend.herokuapp.com/)
  - Qiita 投稿数のタグ数の比較
- [Github Compare](https://www.githubcompare.com/)
  - Github でのリポジトリの比較
- [GitHut](https://madnight.github.io/githut)
  - Github に登録されているリポジトリのプログラミング言語の比較
- [Stack Overflow Trends](https://insights.stackoverflow.com/trends)
  - Stack Overflow でのタグ数の比較



## Google Trends

> https://trends.google.co.jp/trends

Google での検索トレンドを比較することができます。地域を選択することで国内のみのトレンドを見ることも可能です。
![図1.png-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/e3b97d15-7df8-607f-b054-509e254b770f.png)
地域を日本で選択すると都道府県ごとの比較もみることができます。
![図1.png-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/a379975b-ecd5-0cb4-c292-1f17c5abc841.png)

## QiiTrend

> https://qiitrend.herokuapp.com/

Qiitaでの投稿数の比較ができます。
![図1.png-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/24bc01d5-6738-c344-1ce7-ea283cac99dc.png)

## Github Compare

> https://www.githubcompare.com/

Github のリポジトリの比較をすることができます。
![図1.png-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/097e7237-d31e-a3ec-109b-f11d8050b7df.png)


## GitHut

> https://madnight.github.io/githut

Github での言語のトレンドを比較することができます。
![図1.png-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/b6a1bee4-5715-678c-1a9f-a2875906a017.png)
真ん中の 「PUSHES」 と書かれているボタンを押すと STARS, ISSUES, PULL REUESTS, PUSHES とそれぞれの項目で比較することができます。

また、言語の判例をクリックするとクリックした言語のみのグラフを表示することが可能です。

## Stack Overflow Trends

> https://insights.stackoverflow.com/trends

Stack Overflow のタグ数での比較ができます。
![図1.png-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259125/b185a975-05a0-3b53-bebd-90be555a353d.png)

# 参考

・[IT系の技術トレンドを調べるのに使えるサービス](https://qiita.com/tag1216/items/da1b078270c0cb6c07df)
この記事の投稿者の方が QiiTrend を開発したみたいです。
[メモ] nilについて

勉強用のメモ代わりとして記事にさせていただきます。

#nil
空っぽのような状態であることを表す「nil」というオブジェクトがある。nilと書けばいつでも使える。

```ruby
value = nil
```

オブジェクトがnilであるかを、nil?というメソッドで調べることができる。

```ruby
> value = nil
> value.nil?
=> true
```
MEXE02の使い方メモ

#MEXE02とは		
PCでオリエンタルモーターの運転データや各種パラメータの設定・編集、ティーチング、各種状態のモニタを行うツール。

#ダウンロード
https://www.orientalmotor.co.jp/download/software/mexe02/

#お試し動作確認手順
①モーター、モータードライバ、PCを接続し、モーターの電源を入れる。
②MEXE02を立ち上げ、新規作成→製品の自動選択	
③[ティーチングリモート]＜＞マークでティーチングリモートを開始。
④チェックボックス→製品の読み出し→再生ボタンで回転させる

※読み出し：現時点のモーター自身の設定情報（トルクとか回転速度とか）を、PCに読み出すこと
　書き込み：設定情報（トルクとか回転速度とか）を、モーターに書き込むこと。

#資料
各機能の詳細資料
https://www.orientalmotor.co.jp/download/software/mexe02_function_intro/
16日目：気球から学ぶとグループID


この記事はアドベントカレンダー「[【VCI】テーマパーク を作ろう](https://adventar.org/calendars/5855) 」の16日目の記事です。

# 今回の内容
今回は以下のようなボタンで上下できる気球を作成したいと思います。
UP用のボタンを押すと上に加速し、DOWN用のボタンを押すと下に加速します。押した分だけどんどん速度が上がります。
![balloon_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/7b4214f9-24ea-6d5c-6a61-423fec840c84.gif)


今回は学ぶ技術は以下となります。
　・JOINT
　・グループID

**※今回作成したコードではマルチで正しく動きません。次回の記事でマルチ対応版に修正予定です**

# 気球とボタンを一緒に動かす方法
今回はボタンで気球の上下移動を制御したいため、ボタンが気球と一緒についてくる必要があります。
一緒に動かしたいものに機能がない場合は気球の子オブジェクトにしてしまえば一緒に動きます。

しかし、今回のケースではボタンを子オブジェクトにすると、UPボタンを押してもDOWNボタンを押してもグリップしたときにonUseに入ってくる名前が気球の名前になってしまい、どのボタンが押したか見分けることができません。
そのため、ボタンは気球の子オブジェクトではなく独立したSubItemとして作成する必要があります。

上記のように「独立したSubItemを一緒に動かしたい」というときに役立つのがJOINTの機能です。詳細は以下の公式ページを参照ください。
　・[Joint (UnityComponent)](https://virtualcast.jp/wiki/vci/component/unitycomponent/joint)
私は主になにかにボタンを付けたいときなどによく使用しています。

# UnityでのJOINTの設定
今回は相対位置を固定して動かしたいためFixedJointを使用します。
まずは今までと同様の手順で気球とUP用のボタン、DOWN用のボタンを作っていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/b4a5a705-6332-f0c5-91c8-470646f5f69d.png)


ここままでは一緒に動いてくれないためJOINTの設定をします。
2つのボタンオブジェクトを選択し、InspectorのaddComponentから「FixedJoint」を追加します。
するとFixedJointの項目が追加されますので、一番上のConnectedBody(どのオブジェクトに合わせて動かすかの設定)に気球のSubitemをD&Dします。
そのほかの設定もありますが、とりあえず一緒に動かすだけならいじる必要はありません。

設定後は以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/80afdbc4-9abb-e54f-ef33-52f905f7d992.png)

# グループIDの設定
Jointの設定は以上ですが、現在の状態では他の人がボタンを押したときに気球が動きません。
ボタン自体は掴んだ際に所有権が移りますが、気球はつかめず所有権が移らないためです。
上記を解決するためにはグループIDという機能を使います。詳細は以下の公式ページを御覧ください。
　・ [所有権とイベント関数の関係](https://virtualcast.jp/wiki/vci/script/reference/eventfunction/ownership)
簡単に言うと複数のSubItemを常に同じ人が所有権を持っているようにする機能です。

グループIDの設定はSubitemの部分にあります。
今回は気球と2つのボタンにグループIDの1を設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/d8d08082-acb5-7561-7835-d020f5b4dd04.png)


# コードの作成
JOINTとグループID自体はスクリプトは必要ありませんが、
ボタンを押して上下のスピードを変える部分とスピードに応じて気球の位置を変える部分の2つ処理がありますのでそれを書いていきます。
(今回の内容と関係ない処理は省略しています。)

まずはボタンによってスピードを変える部分です。
こちらは特に新しい内容もないので簡単だと思います。

``` lua
--気球の速度。＋だと上に、-だと下に進む。
local BalloonSpeed = 0

function onUse(use)
  if use == "Button_Balloon_Up" then
    BalloonSpeed = BalloonSpeed + 1
  end
  if use == "Button_Balloon_Down" then
    BalloonSpeed = BalloonSpeed - 1
  end
end
```

次にスピードに応じて気球の位置を変える部分です。
地面を突き抜けないように、座標が0以下になった場合に修正する処理も入れています。

``` lua
function updateAll()
  local balloon = vci.assets.GetTransform("HotAirBalloon")
  --バルーンの所有権を持っていたら
  if balloon.IsMine then
    --移動先の座標を算出する。0.01の部分は調整用の係数で、実際の動きを見ながら適切な値を設定。
    local nextPos = balloon.GetPosition()+Vector3.up*BalloonSpeed*0.01
    
    --移動先の座標が地中(y<0)なら地上で停止させるにする。(地中に埋まらないようにする処理)
    if nextPos.y < 0 then
      nextPos.y = 0
      BalloonSpeed = 0
    end

    balloon.SetPosition(nextPos)
  end
end
```

以上で作成完了です。

# 終わりに 
いかがでしたでしょうか？
今回の方法ではスピードの情報を各自が持っているため、複数人でボタンを触るとスピードが維持されない状態となってしまいます。
次回のSTATEを使って上記の解決をしていこうと思います。
マンガでわかる砂上の楼閣(ベンダーロックイン)アンチパターン

![C75CB432-50BB-4E4F-8ABF-FCBEABB47E62.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/2e5aefd3-c958-0992-bdf0-2af54d864cbc.png)
http://wiki.c2.com/?VendorLockIn

いくら立派な機能を持ったソフトウェアに見えても、足元が頼りないと、驚くほど脆く壊れてしまうことを象徴して、アンチパターン本では、ベンダーロックインのことを、日本語で砂上の楼閣と翻訳されています。

> 「固い岩の醜い家が安全に建っている：それにひきかえ、わが輝く宮殿の砂の上に建つを見よ！」
> —— Edna St. Vincent Millay

特定ベンダーに依存して無警戒に豪華な機能を使ってしまうと、依存が依存を招き、もとあった依存を超えて、ソフトウェア全体がベンダーの呪縛から逃れられなくなってしまいます。こうしてベンダーロックインが起こると、開発の主従関係が逆転してしまいます。開発者は、仕様変更の権限を握っているベンダーの一挙手一投足にビクビクしながら、砂上の楼閣を保守しなければなりません。

ベンダーは自社の利益と大多数のユーザーの満足を目的とします。また、ほとんどのユーザーにとって不利益でなければ、ベンダー内の複数のプロダクトで足並みが揃わず、一貫性を失った状態になるときもあります。もし自分の開発したものがこの「大多数」からあぶれたらどうなるでしょう。主導権がベンダー側にあると、それは死の宣告となり、大規模なデッドエンドを迎える可能性もあります。

これは、心理的な問題や政治的な問題ではなく、アーキテクチャの問題である点が重要です。アーキテクチャによって、主導権をつねに開発者側で握れるのだから、みすみすその機会を逃すのは開発者の責任、設計の失敗です。ビジネスロジックに近い箇所ほど、ベンダー中立なレイヤーを通すようにしておき、代替手段に置き換え可能にしておくのです。ベンダー固有の機能に依存するコードは、この中立レイヤーのインターフェースを実装するかたちにして依存を逆転させ、開放閉鎖原則 (書き換えには閉鎖的に、拡張には開放的に) を尊重しましょう。ちなみに、この中立レイヤーの機能セットがアプリケーションのドメインモデルに依存するのは問題ありません。なぜなら、ドメインモデルの権限は完全にこちら側にあるのですから。

繰り返しになりますが、ベンダーロックインは、それを見過ごすアーキテクチャを作った開発者の責任です。ベンダーがいつ [梯子外し](https://qiita.com/tanakahisateru/items/dc014719333c211ef5b1) をするかわからないのは、すでに知っているので。例えて言えば、セキュリティホールを放置していた箇所をクラックされたとして、クラッカーが悪いんだから私は悪くない、なんて言い訳してたらエンジニアの恥ですよね。ベンダーロックイン対策もそれと同じです。