OmniAICreator/Qiita-1.07M huggingface dataset:
Python を用いて気象庁の天気予報APIから東京の天気を受け取る

#気象庁のAPI
2021年2月24日に気象庁が公式Twitterアカウントから気象庁のホームページをリニューアルしたことを発表した。リニューアルによって、気象庁公式の天気予報や概況のデータをJSON形式で取得できるようになった。

#API取得方法

```
https://www.jma.go.jp/bosai/forecast/data/forecast/(pathCode).json
```

上記のURLは気象庁が出しているJSON形式の天気概況である。
(pathCode)の所に自分が知りたいエリアのコードを入力する。
東京のエリアコードは"130000"なので上記のURLに当てはめると下記の通りになる。

```
https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json
```

[エリアのコード(pathCode)一覧](http://www.jma.go.jp/bosai/common/const/area.json)

#API取得環境
Windows10
Python3.9.9
Visual Studio Code

##API取得プログラム

```python

import urllib.request as req

#URLを変数urlに保存
url='https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json'

#保存ファイル名を指定する
filename='tenki.json'

#ダウンロード
req.urlretrieve(url,filename)

```

#結果
![キャプチャ.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2248947/65f46c9d-4e7d-7f23-f22d-0efde9b60047.gif)
東京の天気概況を取得できました。



#参考文献
[Twitterで話題になった気象庁の天気予報APIをPythonで使ってみよう](https://news.mynavi.jp/techplus/article/zeropython-75/)
[新しい気象庁サイトからJSONデータが取得できる件](https://mindtech.jp/?p=1754)
セキュリティーグループ更新を効率化してお手軽にする


この記事は[ハンズラボ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/handslab) 14日目の記事です。

# セキュリティーグループ更新を効率化しようと思ったきっかけ
EC2インスタンスにアクセスするには、グローバルIPアドレスをセキュリティグループに設定しないといけません。そして、時々セキュリティグループの変更が必要なときがあります。例えば、「コワーキングスペースで作業するとき」や「自宅ネットワークのグローバルIPアドレスが変わってしまったとき」が挙げられますね。

セキュリティグループの変更は以下の手順で画面ポチポチしていました。

```
1. AWSログイン
2. EC2を選択
3. セキュリティグループを選択
4. 変更するセキュリティグループIDを選択
5. 変更するルールのIPアドレスを更新
6. ルールを保存
```

~~まあめんどくさい~~地味に手間がかかりますね。この手順は**定期的に発生し、定型的な作業なので効率化したい**と思いました。


# セキュリティグループを更新するスクリプト作成

やりたいことは**AWS CLI**を使用して、「プロトコル」、「タイプ(ポート範囲)」、「説明」をキーとして「IPアドレス」を更新したいのです。
![やりたいことイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593462/f7df61d4-e714-3897-f09c-b75df83ab0a2.png)





```Bash
#!/bin/bash
myip="$(curl -s http://checkip.amazonaws.com/)/32"
sg_id="sg-xxxxxxxxx" 
profile="profile"
description="5frisk_notmintia"

# 1. 設定済みのルール一覧を取得し、「プロトコル」、「タイプ(ポート範囲)」、「説明」をキーとして削除対象IPアドレスを取得
del_target_ip=$(aws ec2 describe-security-groups --profile ${profile} | \
                jq '.SecurityGroups | map(select(.GroupId == "'${sg_id}'"))' |
                jq '.[].IpPermissions | map(select(.IpProtocol == "tcp" and .ToPort == 22 and .FromPort == 22 ))' |
                jq '.[].IpRanges | map(select(.Description == "'${description}'"))' |
                jq '.[].CidrIp' | 
                tr -d '"')

# 2. ルール削除
# 既存のIPアドレスのルールは不要なので削除
aws ec2 revoke-security-group-ingress --profile ${profile} \
   --group-id ${sg_id}  \
   --ip-permissions IpProtocol=tcp,FromPort=22,ToPort=22,IpRanges="{CidrIp=${del_target_ip}}"  

# 3. プロトコルとポート番号とMyIPと説明を設定し、ルール追加
aws ec2 authorize-security-group-ingress  --profile ${profile} \
    --group-id ${sg_id} \
    --ip-permissions IpProtocol=tcp,FromPort=22,ToPort=22,IpRanges="[{CidrIp=${myip},Description=${description}}]"
```



スクリプト作った後のセキュリティグループの更新は以下の手順になりました。

```
1.Bashスクリプトをキック
```

画面ポチポチする手間が無くなり、手軽になりましたね！また、「他のセキュリティグループルールを変更する誤操作が無くなる」といったメリットも生まれました！


# より簡単に実装
しばらくはセキュリティグループ更新楽だなーと思いながらスクリプトを実行していました。その後しばらくして、[AWS CLIのドキュメント](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/index.html#cli-aws-ec2)を眺めていたときに気づきました。
...[modify-security-group-rules](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/modify-security-group-rules.html)？？
これ使えば「削除して追加」せんでも、セキュリティーグループIDをキーにして更新すればいいだけやないかい！
当時は**authorize-security-group-ingress**でしかセキュリティーグループを変更できないと思いこんでいました...


```Bash
#!/bin/bash
myip="$(curl -s http://checkip.amazonaws.com/)/32"
sg_id="sg-xxxxxxxxx" 
sgr_id="sgr-xxxxxxxxxxxxx"
profile="profile"
description="5frisk_notmintia"

aws ec2 modify-security-group-rules --profile ${profile} \
    --group-id ${sg_id} \
    --security-group-rules "SecurityGroupRuleId="${sgr_id}",
                            SecurityGroupRule={IpProtocol=tcp,FromPort=22,ToPort=22,CidrIpv4="${myip}",Description="${description}"}" 
```



# おわりに

予め公式ドキュメントを確認してより簡単にできる方法を探すんだぞ！
音声認識をして特定の言葉をカウントしたい

#おもてなしを見える化するIoTがつくりたい！！
<img width="500" alt="![image (30).jpg]" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2052662/48a0d396-6bad-30a7-3610-9189b193838b.jpeg">
普段は居酒屋で働いており、プログラミングとは無縁なのですが、
おもてなしが見える化するIoTをつくりたい！！と思い、一念発起！
お休みの日にプログラミングを学びながら、日々挑戦をしています！

#やりたい企画を具体的に描く
最終的にはクラウドファンディングを行い、
共感してくださる仲間とともに、おもてなしを向上させていきたいと思っています。
今まではぼんやりと「おもてなしが見える化するIoT」というぼんやりしたものだったのですが、
「お見送り」に焦点を絞り、
・スタッフの「ありがとうございました」を計測する。
・お客様の「ありがとう」を計測する。
・その数をスプレッドシートにデータとして見える化する。
というステップで**実装していきたい企画を具体的に描き、
キャンプファイヤーに仮投稿してみたというのが最近の進捗**です。

https://camp-fire.jp/projects/528848/preview?token=3m633zhp

#必要そうな機能
具体的に描け始めたので、必要そうな機能を洗い出してみました。

・音声認識をする
・音声認識をしたものを何か書き出す
・書き出したものの中から特定の言葉を引き出す
・引き出したものをカウントする
・カウントしたものをGoogleSpreadSheetに転記する

とはいえ、**書き出してみると、まだまだ何だかぼんやり**ですね。。。（汗）

#実装してデモに挑戦
学んだJavascriptで実装したいと思っているので、
これらの機能が何かデモできないか調べて挑戦してみました。

##音声認識～Web Speech API
[Webページでブラウザの音声認識機能を使おう - Web Speech API Speech Recognition](https://qiita.com/hmmrjn/items/4b77a86030ed0071f548)の記事を参考に作成してみました。

```jS:index.html
<script>
  SpeechRecognition = webkitSpeechRecognition || SpeechRecognition;
  const recognition = new SpeechRecognition();
  recognition.onresult = (event) => {
    alert(event.results[0][0].transcript);
  }
  recognition.start();
</script>
```

そして、実際にデモで動かしてみたのがこちら！！

<img width="" alt="![2ca0819428f7e826e18185a9ba34de27.gif]" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2052662/5f71aa75-1c42-6698-4c70-00661c0a4a06.gif">

たった8行のコードで、こんなことができるってす、すごい・・・！！

##・音声認識をしたものを何か書き出す
と、ここでつまづきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2052662/c994b1ff-b009-f2ee-d5a7-f4f710525a86.png)

文字は出てきたけど、OK押したら消える・・・。
どこに認識したデータは行くんだ・・・。
自分の中では結構調べたけど、分からなかったので、パス。

##引き出したものをカウントする～Array.length
[JavaScriptリファレンス](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference)に掲載されている構文や関数などを調べていると、
**[Array.length](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array)**なるものに出会いました。
使い方を詳しく検束して見ると**要素数をカウントする**と書いてあったので、なんだか使えそうだと思っています。

#まとめ
結論、企画は具体的にイメージでき始めたものの、
じゃあ実装してみよう！となると、
**どこの何から手を付けたらいいのか？
引き出しの中の知識量が少なく、組み合わせられない・・・。**
という壁にぶつかってしまいました。

企画と実装を両輪で進めていく必要があると感じたので、
どちらもスピード感をもって進めていければと思っています。

あたたかい目で見守りながら、応援してもらえればと思います。
（続く）
ヌメロンが出来るサイトを作成しました。

皆さん、ヌメロンはご存じでしょうか。
私はこのゲームが好きなのですが、
友達がいないので1人で出来るようにシステムを作成してみました。
ルールはざっくり下記の通りです。

①0-9の中で好きな数字の組み合わせを選ぶ
②相手が選んだ3桁の数字を当てる

#今回使った技術
・PC:windows
・vscode
・Vue3
・TypeScript
・HTML/CSS
<a href="https://materializecss.com/">・Materialize</a>

#ざっくりの流れ
(1)トップ画面
(2)ゲーム開始！→答えになる数字3つが裏側で振られる
(3)攻撃していく
(4)終了：クリアor 9回目の攻撃でゲームオーバー


#画面の挙動
(1)トップはこのようにボタンのみの表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365717/bc36141a-135c-4fad-0a9f-8f5222cf0085.png)

(2)「プレイボール！」ボタンを押すと下記のような画面が表示され(v-showです)
数字が3つランダムに付与されます。
(この数字が答えになるので、ここでは何の数字が付与されたか表示されません。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365717/2fea5587-4df0-0f03-32a6-8b2fbb5ae9f8.png)

3桁の数字を付与しているコードはこちら。
1桁目はランダムに数字を取ってきてそのまま使用していますが、
2桁目・3桁目は他の桁の数と被らないようにしたいので、
Whileで被らなくなるまで取ってきて上書きするようにしています。

```typescript:
//1桁目
const getNumber1 = () => {
      number1.value = Math.floor(Math.random() * 10);
    };

//2桁目
const getNumber2 = () => {
      number2.value = Math.floor(Math.random() * 10);
      while (number1.value === number2.value) {
        number2.value = Math.floor(Math.random() * 10);
      }

```

(3)数字を入れて、「攻撃」ボタンを押すと
結果が表示されて下の表に履歴が追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365717/82ca8087-17d8-acbc-5df7-fa18e6ff6506.png)
〇ヒット：場所は違うが、その数字を含んでいる
　→もし1桁目===2桁目 または　1桁目===3桁目…というコードで書いています。

〇ホームラン：場所も数字もあっている
　→もし1桁目===1桁目… 
hitとhomerunという変数を作り当てはまっていたら+1していく仕様です。


(4)数字を当てる／9回目の攻撃が終わったら、終了。
攻撃のたびにcountという変数に+1していって、数が9になったらreturn
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365717/c79d3a2a-93b2-d9f4-c556-68ba2234cebc.png)
やったー！

#苦戦ポイント
cssが苦手すぎます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365717/170f8783-9916-0d49-eaeb-aece6abb38ad.png)
なんで中心がこんなにズレるんだ。

また数字を1桁入力するごとに
次の桁の入力欄に移ってほしかったのですが無理でした…

#おわりに
これで1人で一生遊ぶことが出来ます。
PCがあれば友達なんていりませんね！('ω')

にしても初めて記事を書いたので文章でコードや仕様を説明するのは
非常に難しいですね…
記事を書き慣れるとプレゼンが上手くなりそうなので
頑張って続けたい所存です。。

ご覧いただきありがとうございました。
【SwiftUI】Viewのアスペクト比を指定する

## [Q] SwiftUIでViewのアスペクト比を指定するには？

## [A] aspectRatioを使います

`View`のインスタンスメソッド`aspectRatio`を使います。引数は、比率を表す数値と、`ContentMode`の２つです。比率を表す数値は省略可能で省略した場合は 1.0 になります。

アスペクト比を実数系型の値で指定する場合:

```swift
Rectangle()
  .aspectRatio(4 / 3, contentMode:.fit)
```

アスペクト比を`CGSize`型の値で指定する場合:

```swift
Rectangle()
  .aspectRatio(CGSize(width: 4, height: 3), contentMode:.fit)
```



以下は SwiftPlayground で実行できる簡単なサンプルです。

```swift
import SwiftUI
import PlaygroundSupport

struct Preview: View {
    var body: some View {
        VStack {
            Rectangle()
                .fill(Color.blue)
                .aspectRatio(4 / 3, contentMode: .fit) // ここがポイント
                .padding()
            Rectangle()
                .fill(Color.red)
                .aspectRatio(CGSize(width: 16, height: 9), contentMode: .fit) // ここがポイント
                .padding()
        }
    }
}

PlaygroundPage.current.setLiveView(Preview())
```

### 動作確認環境

2021/12/09 に確認しました。

- iPad Pro
- iPad OS 15.1
- Playgrounds 3.4.1(1302.34)

### 参考

- Apple Developer Documentation
  - [aspectRatio](https://developer.apple.com/documentation/swiftui/view/aspectratio(_:contentmode:)-5ehx6)
[py2rb] hasattr

# はじめに
移植やってます
# hasattr (Python)
```python
try:
    import pandas as pd
except ImportError:
    pd = None
else:
    if hasattr(pd, '_version'):
        pv = pd._version.get_versions()['version']
    else:
        pv = pd.version.version
```
`hasattr`でメソッドがあるかどうかを確認。
`Pandas`の古いバージョンに対応していると思われ。
# methods (Ruby)
```ruby
begin
  require 'pandas'
  pd = Pandas    
rescue => exception
  pd = nil
else
  if pd.methods.include?(:__version__)
    pv = pd.__version__
  else
    raise "Pandas#__version__ NoMethodError"
  end
end
```
`Class#methods`でメソッド一覧が取れます。
まあ、こちらは`Ruby`や`Pandas`等の環境を指定できますので、それほど問題にはならないかも。
# メモ
+ Python の hasattr を学習した
+ 道のりは遠そう
【CodeDeploy】The CodeDeploy agent did not find an AppSpec file within the unpacked

AppSpec.ymlがないよ、というエラーが出まくり、ビルドに失敗する。

# 使用環境
- EC2 Amazon Linux(ロードバランサー使用)
- リポジトリはGithubから
- CodePipelineなどは使用せず、CodeDeployのみ使用
<br>
# 確認事項
- appspec.ymlがそもそもあるか
- あったとしたら、リポジトリのルート直下に配置されているか

上記を確認したけど治らず。。。。
調べるとたくさんの人がこのエラーに遭遇しているようです。

- https://stackoverflow.com/questions/53501365/codedeploy-agent-did-not-find-an--appspec-file-within-the-unpacked-revision-direc
- https://infraya.work/posts/codedeploy_appspec_not_found_error/
- https://forums.aws.amazon.com/thread.jspa?threadID=296302&tstart=0

階層の問題説や、`appspec.yml` ではなくて `appspec.yaml` なのでは？みたいな意見もありました。
<br>
# 解決策
EC2再起動。これだけ。。。
拍子抜け。。。
Unityで予測できるランダム値を生成

[PONOS Advent Calendar](https://qiita.com/advent-calendar/2021/ponos) 2021の16日目の記事です。

昨日は@714hoさんの「[Unityログにタグをつけて見やすくする方法](https://qiita.com/714ho/items/153cff53d98ff80c469e)」でした！

#はじめに

※間違いや不自然な日本語があったらスミマセン。

次の記事を参考にしたものです（英語）：https://blog.redbluegames.com/generating-predictable-random-numbers-in-unity-c97b7c4895ec

UnityEngine.Randomを使うか？System.Randomを使うか？は考えたことないですか？

予測できるランダム値を生成したい場合は、UnityEngine.Randomは使いにくいです。
UnityEngine.Randomはstaticであり、共通で使われるものなので、他のプラグインやコードに呼ばれる、又は初期化される可能性があります。

以下のように設定すれば、自分で制御できます：

```C#
public static class RandomUtils
{
    public static System.Random RNGSingleton = new System.Random();
}
```


たとえば、確率で何かを行われる場合は以下のメソッドが使えます：

```C#
public static bool RandomChance(System.Random rng, int percent)
{
    return rng.Next(0, 100) < percent;
}
```

もう一つの例です。こちらはレンジの中でランダムな値を返します：

```C#
public static bool RandomRange(System.Random rng, int min, int maxExclusive)
{
    return rng.Next(min, maxExclusive);
}
```


普段はRNGSingletonをパラメータとしてパスします。

#予測できる値を生成する

たとえば、宇宙の中で遊べるゲームを作っています。
「銀河」をいくつか生成して、それぞれはさまざまな「惑星」を生成します。
この場合はまずシードを設定して、次にランダムを初期化します：

```C#
// シードを設定
int seed = RandomUtils.RandomRange(RandomUtils.RNGSingleton, 0, int.MaxValue);

// ランダムを初期化
var random = new System.Random(seed);

// それぞれの銀河が同じランダムにより生成
foreach(var galaxy in galaxies)
{
    galaxy.Generate(random);
}
```

「銀河」はまた「惑星」に「random」をパスするイメージです。

例：

```C#
// galaxy = 銀河
public class Galaxy
{
    // 生成メソッド
    public void Generate(System.Random random)
    {
        // 50%の確率で…
        if (RandomUtils.RandomChance(random, 50))
        {
            // 大きな惑星を追加
            var planet = new BigPlanet();
            planet.Generate(random);
        }
        else
        {
            // 小さな惑星を追加
            var planet = new SmallPlanet();
            planet.Generate(random);
        }
    }
}
```

こうやって、シードを保存すれば毎回同じ宇宙を生成できます。

***

明日は@nisei275さんです！
Laravelのfillで躓いたこと

<h1>Add [_token] to fillable property to allow mass assignment on</h1>
　

```php
$user->fill($request->all())->save();
```
fillメソッドを使いrequestを取得しセーブしようとしたら発生したら、エラーになります。

調べていくと、Modelに$failableがなかったかららしいので、Modelに追記したら解決しました。
Pictmaster味わい紀行、その2、仕様変更対応編

#概要
一旦、テスト実装が終わった後に仕様変更があって、せっかく準備したテストデータを再び弄らなくてはならなくなった場合に、Pictmasterではどのように対処するかの事例。
因子や水準数が増えたり、制約条件が追加になったり。そんなドタ仕様変更にも、ツールで乗り切りましょうの話。
#お題
ラーメン店のメニューは、以前のものを流用

|因子|パラメータ1|パラメータ2|パラメータ3|パラメータ4|パラメータ5|
|:---|:---:|:---:|:---:|:---:|:---:|
|スープ|醤油|味噌|塩|豚骨醤油|あごだし|
|麺固さ|固目|柔らかめ|普通||
|背脂|多め|少なめ|||
|チャーシュー|肉厚|普通||
|ネギ|多め|少なめ|||

追加仕様として、トッピングメニューおよび麺の種類（スープと麺の種類に、制約条件が追加）

1. 麺の大盛りは、50円増し。レシートにも記載が必要。低カロリー麺では大盛り不可。
2. 煮卵、50円。レシートに記載要
3. 太麺（全てのスープで選択可）、極太麺（塩味では選択不可）、細麺（全てのスープで選択可）、極細麺（醤油味のみ）、低カロリー麺（全てのスープで選択可、50円増し）

#影響範囲特定
値段は、2種類のみだったのが増えそうです。[前回](https://qiita.com/KazuhiroYoshino/items/a14ed7f437b21afb6e27)で結果表を使いましたが、使えなくなります。ここはExcelにお任せとします。
煮卵トッピング付ける/付けない　の因子を追加。値段も変わります。
麺大盛りする/しない　の追加。値段も変わります。低カロリー麺については制約条件があります。
麺の種類が、水準数5の因子として追加になり、選べるスープに関して制約条件があります。
制約条件を環境設定画面から有効化します。
![pict012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/7ca4bd8f-6cab-968d-3438-e9661c79e968.png)
#テスト実装作業
制約表の記述が旨くできない場合、または、仕様変更都度、制約表の大幅な変更作業が伴う場合、Pictmaster等のツールが嫌いになるきっかけかと思います。いくつかヒントを紹介します。

1. 制約に関係する因子は、パラメータを全部1個ずつ制約表に入れておきます。
太麺と細麺については、制約式に関係ないのですが、記述しておいた方がいいです。
当然、この2つについては選べるスープが全てになるのですが、全て選択できるように制約表を記載します。
![pict016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/91bc295b-9d42-41a7-926f-ad634a010e9e.png)
赤丸で囲った制約に関係のあるパラメータだけ記述すれば済むのですが、制約表の見通しが良くなるのと、麺の種類に対して制約が追加になった場合、更新が楽だからです。
2. 期待値の生成は、Excelに任せます。
Pictmasterで生成したテーブルを別のワークシートにコピペして、計算してくれるように埋め込み式を入れておけば、仕様変更（例えば煮卵の追加価格が変更になったり）にも対応が楽です。
今回は、以下のようなテーブルを用意して、スープ選択のみでの価格と麺の種類によるオプション価格、煮卵追加料金に対応しました。
![pict018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/cd73b337-a68c-70d5-1e91-28424f1ff732.png)
これをテーブル参照して値段を期待値とします。
![pict017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/49ad7f6d-5e3e-9bd7-989b-3ce866b28907.png)

```
=INDEX(値段表!$B$1:$B$6, SUMPRODUCT((値段表!$A$1:$A$6=B2)*ROW(値段表!$A$1:$A$6)))
```
スープが決め手の価格ならば、上記のような式になるかと思います。
3. テストデータを値段でソートして”異常に気づきやすいチェックシート”にする。
前回のテストデータ生成では、15件でしたが、今回はどうなるでしょうか。
![pict019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939617/9186ff70-fb0d-d849-7176-a6990f90b815.png)
22件でした。
これを合計金額でソートしています。600円の場合/700円の場合/750円の場合　の3通りの合計金額になりましたので、例えば3人でテストしても良いでしょうし、1人でテストするにしても、期待値が固まっていれば異常に気づく安心感があると思います。
ちょっとした気配りかも知れませんが、単調になりがちなテストでも、どうしたら異常に気がついてもらえるかは、できるだけ配慮した方がいいです。
自動テストの場合は不要かもしれませんが。

#総括
組み合わせテスト実施に使えるALL Pair法のツール紹介と、利用上の配慮について2回にわたって紹介しました。今回はテスト中に仕様変更が入ったことを想定して、テストデータの修正をALL Pair法で行ないましたが、実際にありがちなのは、仕様把握が不十分で、テスト中に別の因子が関係していることが判明した　です。
なにもかも理解した上でテスト開始できれば問題ないのですが、今回紹介した事例程度に簡単な場合は希で、大抵は多くの項目が因子として関連したり、因子の中身が改廃になります。
工数かけて作り込んだチェックシートが、テスト実施直前に使い物にならなくなってガッカリすることも多いです。組み合わせテストでは、テスト件数が爆発してしまう感覚に陥ることもあるかもしれません。
ぜひ、ツールの恩恵で、そういった心配や悩みから解放されて、テストすべき心髄に、正面から向き合いたいものです。
[Pictmaster](https://ja.osdn.net/projects/pictmaster/)を紹介しましたが、[GIHOZ](https://gihoz.com/login?redirect=%2Frepositories)というテストデータ生成環境も、オンラインで利用できますから、ツール武装して、どこからでもかかってきなさい状態でテストに臨みましょう。
Storybook上で画像が表示できなかった際の対処

# 概要

会社の研修でNext.js＋Storybookに触れる機会があったのですが、
その際にStorybook上でロゴ等の画像が表示できず詰まったので、備忘録としてメモしておきます。

# 開発環境

- next.js 11
- Storybook

# 修正

Next.jsでの画像表示にはいくつか方法がありますが、
今回はnext/imageを使用する方法で画像を表示することにしました。

### preview.jsを修正

以下の記事を参考にコードを追加
[storybook next/image エラー解決：next.config.jsにドメイン設定してもダメ](https://qiita.com/ryichk/items/3470c75b73a9def6b7fa)

- 修正前

```javascript
export const parameters = {
  actions: { argTypesRegex: '^on[A-Z].*' },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};
```

- 修正後

```javascript
import * as nextImage from 'next/image';

export const parameters = {
  actions: { argTypesRegex: '^on[A-Z].*' },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};

Object.defineProperty(nextImage, 'default', {
  configurable: true,
  value: (props) => <img {...props} />,
});

```

### package.jsonを修正

storybookを起動するときのscriptがデフォルトの状態だと表示できなかったので、修正します。

- 修正前

```
"storybook": "start-storybook -p 6006",
```

- 修正後

```
"storybook": "start-storybook -s ./public -p 6006",
```

以上の修正を行うことで、無事Storybook上で画像を表示できるようになりました。
ふるさとチョイスを取り巻くインフラ環境2021

この記事は、[トラストバンク Advent Calendar 2021](https://qiita.com/advent-calendar/2021/trustbank)の12日目です。

今年の7月にトラストバンクにJoinしたSREの@butadoraです。

入社時点ではインフラ構成図もない状態で、考古学からはじまりました:pick:

ようやうインフラ環境の全容がつかめてきたということで、
今回はふるさとチョイスを取り巻くインフラ環境について、
特徴や面白いと思った点をピックアップしていきたいと思います。

## サービス構成図
大分抽象化してますが、ふるさとチョイスのサービスはこのようになっています。

<img width="500" alt="ふるさとチョイス インフラ構成図.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29545/9865f864-f671-98a3-878a-96c2dc2fd97d.jpeg">

* サービス全体がさくらのクラウド、さくらの専用サーバで稼働
* 入り口はすべてCloudflare経由となっており、CDNとWAFを兼ねている
* 一部閉域網内向けのサービスでラックサーバをさくらのハウジングサービスで利用
* WEBサーバやDBサーバだけでなく、LBもLinuxサーバで実装

### ふるさとチョイス
https://www.furusato-tax.jp/

* ふるさとチョイスのメインサービスである、ふるさと納税総合サイト
* 寄付することができる自治体や、その自治体が提供するお礼の品を横断的に検索できるサービス

### ふるさとチョイスCMS
* 各自治体様がふるさとチョイスへ掲出するお礼の品や寄付情報を管理するためのサービス
    * [10日目の記事](https://qiita.com/kazuyaseo/items/66bb83a209cc0c5e5600)でもサービス内容に少し触れています
* インターネット経由で利用できない自治体様向けに、総合行政ネットワーク（LGWAN）[^lgwan]網内でも提供しています

### OEMサイト
* ふるさとチョイスに掲載されたお礼の品情報をベースにしたふるさとチョイスのOEMサイト
* WEBサイトやAPIの形で法人向けサービスとして提供しています

[^lgwan]: Local Government Wide Area Networの略。参考: [J-LIS LGWAN について](https://www.j-lis.go.jp/lgwan/about/cms_15039.html)

## トラフィック特性
Cloudflareで受けている、月ごとのトラフィック総量をグラフにしてみました。

<img width="500" alt="traffic2021.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29545/bf907bc4-ee38-19f4-f095-9715246810ed.png">

一年の上半期とくらべると、12月は5倍ほどのトラフィック量となっており、
やはり年末である12月が1年でトラフィックが最も増えるシーズンとなっています。

また、その後ろにいるWEBサーバのアクセス数はこんな感じです。

![スクリーンショット 2021-12-08 20.39.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29545/5c316d44-a8a6-a518-f665-a84e1395ac8f.png)

具体的な数字はお見せできないですが、11月頃から徐々に増えはじめ、
世間的に年末休みとなる頃から大晦日にかけて爆増する様子です。

## マシンスペック
こんなトラフィック特性のトラストバンクの年末をどのようなマシン構成で迎えるか？
とあるアプリケーションサーバのスペックは...

\ドン！！/
<img width="500" alt="machine list.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29545/98b1d5e2-7df3-f80b-af2a-4cbcf4b8a3c0.png">

とあるDBのスペックは...
\ドドン！！/
<img width="500" alt="machine list.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29545/cbbfc456-369f-95b2-9d07-02dc8a8ce316.png">

といった具合で、

* アプリケーションサーバ: 専有ホストで10core、24GBのマシン数十台
* DBサーバ: 20core、224GB(最大スペック)のマシンを数十台

を並べて12月の大規模トラフィックを待ち受けています:muscle:

## デプロイフロー
コード管理にはGithub Enterprise Serverを利用しています。

### 開発環境
* 検証用ドメインがいくつか用意されていて、１台のサーバでホストベースルーティングしてアクセスできる仕組みとなっています
* 各ドメインへのリリースにはデプロイツールが用意されており、誰がどのブランチをいつデプロイしたかが分かる仕組みとなっています

<img width="500" alt="dev_releas.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29545/c6b420ab-39cd-eb59-7ee5-17aec900dda2.png">

### 本番環境
* 各サーバへのデプロイにはlsyncが使われています
* 親となるmasterサーバでリリース対象のブランチをpullすることで、各サーバに配布される仕組みとなっています

<img width="500" alt="lsync.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29545/cc01512f-55fc-085d-bb70-d85a743b057b.png">

## 最後に
今回は現在のインフラ環境をご紹介しましたが、現在AWSへのリフトアップを中心とした移行に加え、
監視の仕組みや、CI/CDのカイゼン、トイル撲滅などSREとしての活動が鋭意進行中です。
(以降のアドベントカレンダーでその一部を紹介予定！)

弊社では一緒にSRE文化を育んでくれるエンジニアを募集しています。
興味を持っていただけたなら、ぜひ一度お話しましょう！！

https://www.wantedly.com/projects/803034
【JavaScript関数ドリル】中級編のunion関数の実装のアウトプット

## 課題内容
https://js-drills.com/blog/union/

## 方針
- 仮引数で受け取った複数のarrayをループ
- さらにarrayの中身をループ
- 新しいarrayに要素をひとつずつpush（同じ要素が含まれていない場合のみ）
includesメソッドで判定していく

```js
function union (...arrays){
  let result = [];
  for (let i = 0 ; i < arrays.length ; i ++){
    let currentArray = arrays[i]
    for (let j = 0 ; j < currentArray.length ; j ++){
      // console.log(currentArray)
      if(!result.includes(currentArray[j])){
        result.push(currentArray[j]);
      }
    }
  }
  return result;
}
console.log(union([2], [1,2,3]));
// => [2,1　,3]
```

自力で実装できました。
kustomize/kubernetes の configMap の基礎メモ

# --from-file=paramfile=params.txt の不思議

どういう意味なのコレ。このコマンドをyamlにするのどうやるの。

```ruby
--from-file=paramfile=params.txt
```

ファイル名がKeyとして、ファイルの内容がValueとして保存される。この際、ファイル名を変更したい場合は --from-file オプションでKeyを同時に指定する。

```yml
$ kubectl create cm params --from-file=paramfile=params.txt
configmap "params" created
$ kubectl get cm/params -o yaml
apiVersion: v1
data:
  paramfile: |
    hogehoge
    fugafuga
    foo bar baz
kind: ConfigMap
metadata:
  creationTimestamp: 2018-12-10T16:37:59Z
  name: params
  namespace: default
  resourceVersion: "89210"
  selfLink: /api/v1/namespaces/default/configmaps/params
  uid: f41d1074-fc99-11e8-a8f4-080027f4eb79
```




`config=my.config.yaml` は、できたconfig mapの

```yml
data:
  paramfile: |     <---- ここを configにする。
    blahblah
```


ファイル名がキーになり世代管理を行うため、統一することが大事。
複数deploymentでも、統一すると楽だからわかりやすい名前にしたんだろう。


これをkustomizeからのkubectl applyすると、乱数付きのconfigMapが生成される。
それがpruneされず残って問題になったりするんだけど。乱数なくすのどうやるんだろうな
→ 教えてもらいました

これはkustomizeの例だけどこれでconfigmapのhashが消えました。kind: Kustomization に当てるんですが、podのhashは消えません。

```yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
generatorOptions:                    <---------
  disableNameSuffixHash: true             <---------

bases:
  - ../../../base

configMapGenerator:
  - name: config
    files:
      - "config=config/config.yaml"
```

### ref
> https://cstoku.dev/posts/2018/k8sdojo-11/
AndroidStudioインストールについて

#Andorid Studioのインストール

##インストーラのダウンロード
下記よりダウンロードする
![Windows版](https://developer.android.com/studio/index.html?hl=ja)


##インストーラの実行
基本的には上記でインストールしたものを実行するだけでよい。
チェックはデフォルト

## Android Studioの初期設定
デフォルト(Do not import settings)のまま[OK]を押下。
Android Studioが起動します。


## Android Studioの日本語設定
Pleiades プラグイン・ダウンロード
　https://mergedoc.osdn.jp/
iOSのコンピュータビジョンで人物の全身ボックスを検出する

これまでVisionの人物ボックス検出（DetectHumanRectanglesRequest）では、上半身のボックスしか取得できなかった。
2021年のアップデートから、全身のボックスも検出できるようになった。

新しいVNDetectHumanRectanglesRequestRevision2を使う。

```swift
let request = VNDetectHumanRectanglesRequest()
request.revision = VNDetectHumanRectanglesRequestRevision2
request.upperBodyOnly = false // trueにすれば上半身のみのBoundingBoxを取得する
```

|upperBodyOnly|結果|
|---|---|
|true|<img src="https://user-images.githubusercontent.com/23278992/145306507-5a008e71-f448-444c-a137-a7ea6ccd0feb.gif">|
|false|<img src="https://user-images.githubusercontent.com/23278992/145306291-5693eebc-eb05-4801-a96c-7df1d577f5f3.gif">|

#感想
全身をとるために機械学習モデルをわざわざ使わなくて良くなった。
上半身だけを検出する必要のあるケースってあるのだろうかと考えてみたが、
こちらの動画のようにフレームに上半身しか映っていないケースでは上半身のみの方が検出数が多くなる。
【上半身のみ】
![Dec-09-2021 08-42-50](https://user-images.githubusercontent.com/23278992/145308887-df64f579-ae36-4305-a8a3-71e5355ed4d3.gif) 

【全身】
![Dec-09-2021 08-44-37](https://user-images.githubusercontent.com/23278992/145308892-38a4d788-1c05-4fd0-b5e5-fd49f5f3dcda.gif)



🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
簡単な開発内容をお書き添えの上、お気軽にご連絡ください。
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
同人プロジェクトマネジメント入門：計画編その3

[同人プロジェクトマネジメント入門の目次はこちら](https://qiita.com/wolfmagnate/items/97bf9a9f8c58ede3fb21)

- - -

# はじめに
計画は、一度作れば終わりではありません。絶えず修正していく必要があります。計画編その3では、いかに計画を効率的に修正をしていくかについて解説します。
# 計画の修正を恐れない
計画の修正は、ウォーターフォール型のプロジェクトマネジメントでは特別なイベントですが、同人プロジェクトマネジメント入門でお勧めしている方法では毎日発生してもおかしくないものです。
なぜなら、この方法は、いつプロジェクトが終了しても、そこで完成と言えるように、出来るだけ仕様の作成と仕事の割り当て、計画の作成を先延ばしにして、必要な時に必要な分だけ行うというものだからです。真剣な設計、真剣な要件定義、真剣な計画作成を何度も繰り返していくのですから、計画の修正はよくあるイベントなのです。
したがって、マネージャーは一度計画を作ったらあとは何もしないという態度をとってはいけません。
常に進捗状況や人間関係、メンバーの実力、仕様の現状に目を配ってそれに合った計画をたてることが要求されているのです。

# 定期的に会議を開く
## 進捗報告
進捗が出たら報告する方法はあまり上手くいきません。
進捗が出たならば報告も出ますが、進捗が出ないと報告が出ないからです。すなわち、やっている途中でもまったくやっていなくても報告が来ないのです。進捗報告がなければマネージャーの仕事はありませんから、マネージャーは一時的に楽ですが、これは負担の先送りにすぎません。
そこで、基本的には「進捗が出ても出なくても報告、報告がない場合には進捗がないとみなす方式」を採用しましょう。モチベーションリスク・失踪リスクが高い同人プロジェクトでは特にこの方法をとるべきです。
そして、モチベーションの管理をして、仕事の割り当て量を調整していきましょう。

## 仕様変更・仕様決定
過去の実績について進捗報告をしたら、次に未来の実装について、変更内容を議論しましょう。
仕様の変更や決定が発生するのは次の3パターンです。

1. 開発メンバーが仕様を1つ実装したとき：仕様書作成編でも書いた通り、同人プロジェクトでは仕様は必要になったら作る方がリスクが少なくて済みます。そこで、進捗が出ると同時に次の仕様を詰めていきましょう。ポイントは、常に**各メンバーが持っている実装するべき仕様を1にキープする**ことです。
1. 先週までの働き方で変更したい点があったとき：開発のワークフローに明らかに無駄がある、などの状況がないか、メンバーに聞き取りして、改善策をとりましょう。
1. 仕様変更がしたくなったとき：例えば「敵の攻撃に遠距離があるとクソゲーになる」場合には、仕様を変更する必要があります。このパターンの仕様変更には、「この方が面白い！」というポジティブなものと「このままだとつまらない」というネガティブなものがあります。ポジティブなものに関しては、新しい仕様を追加することになりますから、仕様書作成編の内容などを参照しながら慎重に追加してください。ネガティブなものに関しては、どちらかというと仕様の欠陥の修正で、やらないと仕方がない仕事であることが多いので、最低限の修正は行った方がいいでしょう。

# プロジェクトは絶対に遅れる
## 遅れた場合の割り当ては事前に考えておく
仕事の終わる速度に個人差があるのは当然なので、遅れが発生してから、会議で「遅れているので他の人はどうしようか…」といった議題を出すのではなく、先に対策を考えておきましょう。
こんな議題を出してしまえば、遅れている人のモチベーションは木端微塵になってしまいます。誰が送れるかはわかりませんが、誰かが遅れるのは確実なので、間に詰める仕事を用意することで待ちが発生しないようにして下さい。
また、遅れていること自体はメンバーに周知することが必要だとしても、なるべく感情をこめないように伝えましょう。
さらに、遅れの原因を把握して、もしもその原因が悪質な場合はタスクを巻き取らせる相手を用意して、速やかに担当者を変えましょう。悪質な遅れの原因とは、「やるやる詐欺でまったくやっていない」「根本的に実力が足りていない」「ほぼプライベートに開発時間がないのに仕事だけ受け取った」といったものです。


## 締め切りで開発速度を上げる
これは計画の修正のうち、「いつまでに終わらせるか」を変更するタイプの修正です。
### 外部の締め切りをたくさん作ろう
今まで、開発メンバーのモチベーションは、最初の仕様を考えているときに最高潮で、そこから急速に落ちて、基本的に戻ってこないと書いてきましたが、それが当てはまらないタイミングが1つだけあります。**それが締め切りです**。メンバーは、作品が完成しない**ギリギリになってようやく頑張りだします**。出来るだけ先送りするのは人間の性ですね。
この締め切りを生かさない手はないです。しかし、人間は基本的に怠惰なので、破れる締め切りは守りません。出席しないと何らかのおとがめを受ける高校まではほとんど皆勤だったのに大学で自由を得てから1限に出られなくなった人、いませんか？
そこで、マネージャーはプロジェクトの遅れを取り戻すために**外部のイベントに積極的に応募するなどして、破ったら迷惑がかかるような締め切りを作りましょう**。(ただし、実際に迷惑をかけるのはよろしくないので、[仕様書作成編](https://qiita.com/wolfmagnate/items/95e3ff2e680ac14da0c9)などを参考に工夫をしてください)

### 締め切りを伸ばしてブーストをかけよう
締め切りまでの時間に比例して進捗速度は向上します。同人プロジェクトでは特に、プロジェクトの進捗の半分を締め切り直前の徹夜開発で出す、みたいなこともあるんじゃないでしょうか。
このパフォーマンスを出している時間を延長する方法があります。それは締め切り延長です。
締め切り数時間前に、「**締め切りがあと3日延びた！**」と伝えることです。これにより、締め切り直前モードが延長されます。もちろん、これは1,2回しか使えない技ですが、一気に進捗を生めます。
何度もやると開発メンバーはそれを見越して締め切り直前でも開発をさぼってしまいますし、メンバーの心身の負担が大きすぎるのでやめておきましょう。

# おわりに
計画通りに物事は進みません。そこにいら立ち誰かを責めてしまうようでは、プロジェクトの成功はないでしょう。特に同人プロジェクトでケンカが起こってしまえば、そこでかなりの確率でメンバーが去ってしまいます。遅れる前提で、それでも何とかする柔軟で粘り強いマネージャーを目指してください。
【AWS】CloudFormation（CFn）を使ってみる：概要編

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306608/b086de0e-22eb-fd2c-041a-b944ff315ccf.png)

# はじめに
みなさん、コードは管理してますか？
してる？
良いですね。

では、インフラもコード管理してますか？
えっ？神が作られし古文書（Excelのドキュメント）があるから大丈夫だって？
じゃあ、それを元に検証環境を1台作ってみましょうかーーーー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306608/2e551cdf-fae4-362c-7902-3bfaa65e962d.png)


どーも、のぶこふです。
この記事は[GFAMアドベントカレンダー2021](https://qiita.com/advent-calendar/2021/gfam)の8日目の記事です。


# 今回のサービス一覧

|Service名とか|概要|
|--|--|
|CloudFormation [^cfn] [^cfn-bb] [^cfn-d-bb]|AWS向けのIaC|

# IaC？
* Infrastructure as Code
* 細かい説明は[Wikipedia大先生](https://ja.wikipedia.org/wiki/Infrastructure_as_Code)にお任せするとして、ざっくりと・・・
    * すばやく複製：コードでインフラを定義することで、構築における再利用性と冪等性を担保する
    * 管理を簡略化：パラメータシートやドキュメントを管理する必要がなくなり、コードを正とできる
    * 制御や変更の追跡：Git等によるコード管理により、改訂履歴の追跡が可能

# CloudFormation
* くらうど ふぉーめーしょん
* 設定ファイル（テンプレート）を使ったリソースのモデル化と管理を行う、AWS向けのIaC。
    * AWSおよびサードパーティのリソースをモデル化、プロビジョニング、管理することが可能
    * テンプレートを自由に作成することができ、自分好みのシステム構成を自動的に構築できる
        * JSON、YAMLフォーマットのテキスト形式をサポート
* CFnと略される

### 基本機能
* 作成
    * テンプレートに定義された構成でスタックを自動作成
    * 並列でリソースを作成し、依存関係がある場合は自動的に解決（すごい）
* 変更
    * スタックに前回のテンプレートとの差分を適用（冪等性）
    * リソース変更時は「無停止変更／再起動／再作成」のいずれかが発生
    * Change Setを作成することで、差分の内容を事前に確認可能
* 削除
    * 依存関係を解決しつつリソースをすべて削除
    * データストアはスナップショット取得／保持が可能

### 手順
1. テンプレート作成
1. アップロード
1. スタックの作成
1. リソースの作成と管理

### 用語
|名称|概要|
|--|--|
|テンプレート|スタックの設計図。JSON/YAML形式のテキスト|
|スタック|テンプレートからプロビジョニングされるリソースの集合体。スタック単位でリソースの管理が可能。リソースの構築順は、テンプレートの依存関係からCFnが自動的に決定|

### テンプレートの要素
|名称|概要|
|--|--|
|AWSTemplateFormatVersion|CFnのテンプレートバージョン。「2010-09-09」が唯一有効な値|
|Description|テンプレートの説明文|
|Metadata|テンプレートに関する追加情報|
|Parameters|スタック作成や更新の際に、ユーザ入力を求めるパラメータ|
|Mappings|Conditionsに使用するキーと値のマッピングテーブル|
|Conditions|条件名と条件判断内容を列挙。本番/検証で構成が異なる場合等に便利|
|Transform|サーバレスアプリケーションや定形コンテンツ挿入等のためのマクロを指定|
|Resources|「必須」。スタックを構成するリソースとプロパティ|
|Outputs|スタック構築後にCFnから出力させる値|

# おわりに
一旦、今回はここまでとして、次回、実際にテンプレートの作成やCFnの実行を試してみようと思います。

今回はここまでです。
ありがとうございました。

[^cfn]: [CloudFormation概要](https://aws.amazon.com/jp/cloudformation/)

[^cfn-bb]: [CFn BlackBelt](https://d1.awsstatic.com/webinars/jp/pdf/services/20200826_AWS-BlackBelt_AWS-CloudFormation.pdf)

[^cfn-d-bb]: [CFn Deep Dive BlackBelt](https://d1.awsstatic.com/webinars/jp/pdf/services/20201006_BlackBelt_CloudFormation_DeepDive.pdf)
RedisのSorted Setsを使って同点の場合先勝ちにする

# 目的
RedisのSorted Setsを使うと点数を競うゲームなどでランキングを作ることができます。同点を同順位にするのは簡単に実装できるのですが、同点の人を先着順に点数をつけるとなると、一筋縄ではいきません。

ここでは
id : 人にそれぞれつくID
count : ゲームの点数
ustm : ゲームで点数を取った時のUnixTimestampのミリ秒
ranking : ランキングを保存するRedisのSortedSets
games : ユーザーの参加情報を保存するRedisのHash 
とします。言語はRubyで書いてみます。

何度でも参加可能で参加したデータはRedisのHashに保存します。fieldはidでvalueは以下のようにします。参加するたびに配列の後に保存していきます。

```json
{
  count: [100, 200],
  utsm: [1639001950000, 1639001951000],
}
```

## SortedSets
RedisのSortedSetsはキーに対してscoreとmemberを登録します。memberは一意な値でユーザーIDみたいなものを使います。scoreは順位を決定する値で整数値の範囲で-9007199254740992 から 9007199254740992まで登録できます。
scoreを単純な点数で使えば9000兆点、マイナスの範囲まで使えば1京点までいけます。

SortedSetで自分よりも多く点数を取っている人の数は以下で数えられます。

```
redis.zcount('ranking', "(#{target_count}", "+inf") 
```
この値に+1すれば自分の順位(同点数、同順位)が取得できます。

SortedSetsではscoreが同じなら同じ順位になります。同じ点数なら先着順というランキングの場合単純には「ゲームの点数＋出した時間」をscoreに利用すれば実現できます。

今のUnixTimestampを取得すると「1639001950」となりました。

```
9007199254740992
1639001950
740992
```
するとゲームの点数として利用できるのは740992で５桁の99999まで管理できます。今自分がやろうとしてるゲームの最高点は「2000000」だったのでこの作戦はうまくいきません。

結局scoreは全て点数として利用できる方が良いと判断しました。UnixTimestampはsocreでは無くmemberにつけました。
「member = id + '_' + UnixTimestamp」

同じscoreの人を集めるには以下のようにします。

```
redis.zrangebyscore('ranking', target_count, target_count)
```
結果

```
101_1639001950000
102_1639001951000
103_1639001952000
```

これを分解して時間を回収して、同じ点数の中での順位を数えます。念のためUnixTimestampはミリ秒にしてかつそれでも同じ場合は無理やりIDの順にすることにしました。

# コード

```ruby
require 'json'
require 'time'
require 'redis'

# 自分の点数の最大値とその点数を出したもっとも早い時間を計算する
def calc_max_count_and_utsm(hash)
  max_count = hash["count"].max
  return [nil, nil] if max_count.nil?
  index = hash["count"].index(max_count)
  [max_count, hash["utsm"][index]]
end

# ハッシュに保存されているIDのデータを取得する
def get_hash(redis, id)
  value = redis.hget('games', id)
  value.nil? ? {"count" => [], "utsm" => []} || JSON.parse(value)
end

# あるIDの点数をRedisに追加する。
def add(redis, id, count)
  utsm = Time.now.strftime('%s%L').to_i
  hash = get_hash(redis, id)
  max_count, max_utsm = calc_max_count_and_utsm(hash)
  hash["count"] << count
  hash["utsm"] << utsm
  redis.pipelined do |redis|
     if max_count.nil? || count > max_count
      # 最高点数の更新
      redis.zdel('ranking', "#{id}_#{max_utsm}") unless max_utsm.nil?
      redis.zadd('ranking', count, "#{id}_#{utsm}")
    end
    # データを更新
    redis.hset('games', id, hash.to_json)
  end
end

# ランキングを取得する
def get(redis, id)
  # IDのデータを取得
  hash = get_hash(redis, id)
  max_count, max_utsm = calc_max_count_and_utsm(hash)
　return 0 if max_count.nil?

  pre_count_account_count, accounts = redis.pipelined do |redis|
    # 自分よりも点数が多い人の数を取得
    redis.zadd('ranking', "(#{max_count}", "+inf")

    # 自分と同じ点数の人たちを取得
    redis.zrangebyscore("ranking", max_count, max_count)
  end

  # 同じ点数の人の中で早い人、同じ時間でidが小さい人の数を調べる
  pre_utsm_account_count = accounts.filter do |member|
    other_id, utsm = member.split(/_/)
    utsm = utsm.to_i
    ustm < max_utsm || utsm == max_utsm && other_id < id
  end.size

  pre_count_account_count + 1 + pre_utsm_account_count
end

redis = Redis.new
add(redis, "100", 1639001950)
add(redis, "101", 1639001951)
puts get(redis, "100")
puts get(redis, "101")
```
watchOS 8 から表示されるようになった NavigationBar の Large title 表示をやめたい

## はじめに

ご存知の通り watchOS 8 から NavigationBar のタイトル部分が
デフォルトで Large title 表示されるようになりました。

|watchOS 7|watchOS 8|
|:--:|:--:|
|![スクリーンショット 2021-12-09 7.39.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88266/6b1e604d-95b1-46b7-43e0-3064de614405.png)|![スクリーンショット 2021-12-09 7.37.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88266/617ab349-8247-ae12-7846-719a688b2e42.png)|

今夏 Watch App 開発していたのですが，watchOS 8 での動作確認は
後回しにしていてリリース前に確認して，あぁ〜変わったんだという感じでした。
Apple Watch のシリーズが新しくなるごとに
少しずつ画面サイズが大きくなってるとはいえ，
コンテンツ領域狭くしてまでも表示すべきなのかは諸説ありそうです。

私は(デフォルトにすることは)改悪だと考えてて watchOS 7 までの表示に共通化したいなー
ということで実装見直しました。

## 表示を共通化

iOS の実装経験から大体予想はついていたのですが，
NavigationBar の titleDisplayMode 周りを調べると…
ふむふむなるほど，watchOS の `large` の設定は watchOS 8 以上になってますね。

[https://developer.apple.com/documentation/swiftui/navigationbaritem/titledisplaymode/large](https://developer.apple.com/documentation/swiftui/navigationbaritem/titledisplaymode/large)

つまり `inline` の設定を明示的に書いてやればいいだけです。

```swift:HogeView.swift
struct HogeView: View {
    var body: some View {
        NavigationView {
            // 省略
            .navigationTitle("Hoge Title")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}
```

watchOS 7 以下の実装も考慮すると `ViewModifier` などを使えば良さそうです。

```swift:NaviDisplayMode.swift
import SwiftUI

struct NaviDisplayMode: ViewModifier {
    func body(content: Content) -> some View {
        if #available(watchOSApplicationExtension 8.0, *) {
            content.navigationBarTitleDisplayMode(.inline)
        } else {
            // 表示されないので
            content
        }
    }
}
```

同じように適用してあげます。

```swift:HogeView.swift
struct HogeView: View {
    var body: some View {
        NavigationView {
            // 省略
            .navigationTitle("Hoge Title")
            .modifier(NaviDisplayMode())
        }
    }
}
```

無事に watchOS 7 までの表示になりました。

|修正前|修正後|
|:--:|:--:|
|![watchOS8_before.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88266/3eb1b3b2-e8c3-8d90-3140-86e5c86f9540.gif)|![watchOS8_after.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88266/7574fc0b-0099-7baa-f138-2d7509d84e3e.gif)|

Apple の純正アプリの表示までは変更できないのでモヤモヤ感は残ります。
慣れたら問題なくなりそうではあります・・・

## おわりに

今回は watchOS 8 から表示されるようになった，
NavigationBar の Large title 表示をやめたいということでその対応について書きました。

(一部 iOS App と勝手が異なりますが) Watch App 開発も
SwiftUI でできるようになって取り組みやすくなっています。
なかなか UIKit を完全に使わないというわけにいかず尻込みしている方がいたら，
損なので Watch App くらいの小さい規模のアプリから作ってみるのもアリだと思います。

乱文になりましたが，ご覧いただきありがとうございました
バイオインフォマティクスは物理学だと言えるこれだけの理由

#はじめに

僕は物理学科の教員をやっていますが、学生には「バイオインフォマティクスは物理学である」と教えています。しかし、世間ではちっともそういう風にならないので、なぜ、「バイオインフォマティクスは物理学である」だと思うのかを説明してみたいと思います。多くの物理学者の皆さんには賛同してもらえないとは思いますが。

#理由１：生物学を物理学の対象から外すのは妥当ではない

バイオインフォマティクスが物理学だと思いにくい理由の１つは（タンパク質の構造とかいう物質的な話じゃなく）生命現象そのものを正面から扱っているから。生物学は物理学じゃない、というわけです。だが、本当にそうでしょうか？

ファインマンが考えた有名な小話に闇夜に街灯の下で鍵を探す男、というのがあります。闇夜で街灯の下ではいつくばって地面を探している男がいました。「何を探しているのですか？」と尋ねると男は「鍵を探しています」と答えます。そして地面から目を離さずに在らぬ方を指さして「鍵を落としたのはあっちなんですけど」。男の指さした先は暗闇に包まれていました。これは物理学者は「真にやるべきことではなくできることをやっている」という揶揄を小話にまとめたものですが、このような揶揄の是非はともかく、物理学では扱いにくいというそれだけの理由で（煌々と照らされた物理学の範疇には無いから）、「生命は物理の（少なくとも主流の）研究対象じゃない」というのが暗黙のうちに成り立っているように感じます。僕もよく「なんで物理学科なのに生命の研究をしているのですか？」と訊かれたりします。
ですが、物理学は基本、自然現象を数学的なツールを用いて研究するならなんでもいいんだと思います。その意味で生命現象を数学で研究するバイオインフォマティクスは立派な物理学たりえると思います。

#理由２：統計学やデータサイエンスでは生命に迫れない

こういうと決まって「自然現象を数学を使って研究するだけなら統計学やデータサイエンスも物理学になってしまうのでは？」という反論が来ます。一見、この反論は妥当な感じがしますが、実は根本的な違いがあります。誤解を恐れずに言えば、統計学やデータサイエンスは「真実がどうなっているか？」には興味がありません。例えば、あるデータを用いて、あるものの性質を予想したとします。ある組成の物質の融点の予測などです。この予測が正しいかどうかは実験で確認できますが、有体に言って、データサイエンスや統計学は「予測が真実と一致しているか？」にはあまり興味が無いのです。もし、予測が外れたら、データが悪かったのか、あるいは、モデルが悪かったのか、データサイエンスや統計学では検討をするでしょう。しかし、予測が真実なのかどうかについては統計学は関知しません。万有引力の逆二乗則が厳密に２なのかあるいは、多少の誤差が入っている中途半端な実数なのかは、物理学者にとっては重要なことでしょうが、統計学やデータサイエンスにとってはそれはどうでもいいことです。なぜなら、統計学やデータサイエンスでは誤差がゼロの予測というのは原理的にあり得ないからです。そういう意味では統計学やデータサイエンスは自然科学の真理には無頓着です。バイオインフォマティクスを統計学やデータサイエンスの一分野としてやっているのでは「真実」に迫ることは決してできません。だから、バイオインフォマティクスは物理学としてなされない限り、生命科学の真実を暴くことはできないのです。

#理由３：物理学は元々データサイエンスだった

逆に、データを数学的に扱うだけだったらそれはデータサイエンスや統計ではあっても、物理学とは言えないんじゃないの、という反論もあるでしょう。


大学で習う物理学はきれいに成形されていて自然法則を記述する美しい体系に見えますが、ニュートン力学の成り立ちを考えれば元々は物理学はデータサイエンスでした。
まずはティコ・ブラーエが膨大な惑星の軌道の観測データを収集し、それをケプラーが少数の法則にまとめました。ニュートンが力学の体系を作り上げたのはその後のことです。
こんな風に成り立ちまで立ち戻れば、物理学の成立はあくまでデータサイエンスのそれだったとわかるでしょう。

#理由４:今の物理学のアプローチは生物学とは言えない


「今だって物理学者は生物学を研究しているのでは？」そうですね。確かに、生物をその研究テーマに掲げている物理学者はたくさんいます。ノーベル賞を受賞したパリジからして群れの研究をしていましたし、ポリメラーゼの動力学を研究している研究者だっています。バイオインフォマティクスとか大袈裟に言わなくても、普通に物理学者は生物学を研究しているようにも見えます。何が不満何でしょうか？
まあ、ここからは多分に主観になってしまうのかもしれませんが、物理学者がやっている生物学の研究ってやっぱり、きれいなところをつまみ食いしているように感じてしまうんですよね。

群れの研究して、生物がどうやって群れを作っているかを、数学的なモデルで出せたとしても、それは生物の研究をしているようには感じられないんですよね。なんでかかっていうと、それは生物が生きているってこととあまり関係ないから。群れのモデルの数理はそれだけ取り出してたとえばCGで群れのシミュレーションをするのにも使えると思いますが、それってその群れが生きていることにはならないじゃないてますか？群れの研究が生物の研究に感じられにくいのはそういうところなんだと思います。
物理学が生物をやるんなら、もっと生物の本質に関わることをやって欲しい。だって物理学は本質を研究する学問じゃないですか？

そんなこといっても、じゃあ、バイオインフォマティクスは群れの研究より、生きていることの研究になっているのか、と言われそうです。正直、分かりません。でも、バイオインフォマティクスは群れの数理モデルみたいに、生物から切り離して使ったりはできないんですよね、だって、それは生物そのものの研究だから。

物理学が生物やるんなら、正面から「生きているというとは物理学的に定義したらこうだ！」みたいな風になってほしい。だってそっちの方がかっこいいじゃないですか？

#おわりに

これは年をとった物理学者の戯言かもしれません。でも、思ったことを書いて見ました。僅かでも皆様の参考になれば幸いです。
ArduinoUNOでI2Cスレーブで遊ぶ(受信)(Arduino)




目的
I2Cスレーブのテスト






参考


https://qiita.com/hikoalpha/items/7bf563ee286a59bfd2f4




![o_con138.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/9fb34c53-b66d-d4a7-120c-53b0ea0901e9.jpeg)





```c++


#include <Wire.h> //I2Cのヘッダー

//初期化関数
void setup() {

  Serial.begin(9600);  //シリアルの通信速度を9600bpsにする。
  Serial.println("START"); //開始メッセージを表示
  Serial.println(' '); //改行
  delay(500); //0.5秒待つ
  
  Wire.begin(0x40);  //I2Cスレーブアドレスの設定
  Wire.onReceive(receiveEvent); //データが来ると呼ばれる関数
  
}//setup

//無限ループ
void loop() {}

//レシーブイベント
void receiveEvent(int howMany) {
  
  int x = Wire.read(); //I2C受信データの読み込み
  Serial.println(x); //受信した数値の表示
  
}//receiveEvent




```


I2Cマスター STM32L010F4P6



```c++


//I2C_OUT_TEST1

#include "mbed.h"

//I2Cアドレス
const int ADDR = 0x80; //  address

//I2Cの構造体
I2C_HandleTypeDef hi2c1;

//I2Cの初期化
void I2C_INIT1()
{
    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    __HAL_RCC_I2C1_CLK_ENABLE();

    //I2C_HandleTypeDef hi2c1;

    hi2c1.Instance = I2C1;
    hi2c1.Init.Timing = 0x00000708;
    hi2c1.Init.OwnAddress1 = 0;
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c1.Init.OwnAddress2 = 0;
    hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    HAL_I2C_Init(&hi2c1);

    HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE);

    HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0);

}//I2C_INIT1

//GPIOの初期化
void GPIO_INIT1()
{
    
    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}//GPIO_INIT1

//メイン関数
int main()
{
    wait_ms(2); //HAL_Delay()になぜか失敗するので呼び出す

    //I2Cの初期化
    I2C_INIT1();

    //GPIOの初期化
    GPIO_INIT1();

    //無限ループ
    while (1) {

        //I2Cに1を送信
        HAL_I2C_Master_Transmit(&hi2c1,ADDR, (uint8_t *)"\001", 1, 3000); //data 1
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
        HAL_Delay(1000);//1秒待つ

        //I2Cに1を送信
        HAL_I2C_Master_Transmit(&hi2c1, ADDR, (uint8_t *)"\002", 1, 3000); //data 2
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
        HAL_Delay(1000);//1秒待つ

    }//while

}//main





```
開発チーム的「電話の取り方」

## Long, long ago.

在宅勤務が主になった今ですが、かつて新人は電話をとるものだという時代がありました。
社内Wikiにそんな過去の遺産となったページを見つけました。
問題のなさそうな範囲での抜粋です。

```md
# 電話に出たときの対応

## 第一声

「はい。(部署名) の (自分の名前) が取りました。」
※「(部署名)」のところは、「(一番小さなチーム名)」でも「開発」でも「(担当サブシステム名)」でも、なんでも良い。

## 電話相手の情報

* 電話相手の所属
* 電話相手の名前
* 宛先（誰に電話を取り次ぐのか）

をまずメモる。
電話を取り次ぐだけなら、これを聞いて、電話を渡して、おしまい。

## 取次先が取込中のとき

例えば

* 電話会議中のとき（マイク付きヘッドセットをしている）
* 偉い人や同僚と仕事のことについて話し込んでいるとき

そんなときは一度、電話相手に

`「現在とりこんでいるようなのですが、後ほど、こちらから折り返しても大丈夫でしょうか。」`

など言って、相手の緊急度を尋ねてみる。緊急度が高そうであれば、電話を渡しに行く。

## 宛先がない場合（電話相手が「とにかく問い合わせを見てほしい」とき）

OR

## 取り次ぐ人がいない場合（お昼ご飯に行ってるとか）

### 相手の話のメモを取る

### 時間がないとき

* 問い合わせ起票URL
* 回答の期日

だけ聞いておけば、最低限なんとかなる。

### 可能な限り

・お客様名
・問い合わせの内容
 　【問題】
 　【現状】
 　【期待されている対応内容】
・指定された期日

を聞く。

(以下略)

```

なんとも文字通り涙ぐましいです

> ※「(部署名)」のところは、「(一番小さなチーム名)」でも「開発」でも「(担当サブシステム名)」でも、なんでも良い。

あたりにそれが滲み出ていますが、まあ電話をとるって緊張しますよね。

- 聞きたい（問い合わせたい）内容がまとまっていない場合、電話相手に「まとめてください」ということを頼む。
- 先輩が戻ったら電話があったことを伝え、メモの内容を伝える。
- 自分で見てわからなさそうだったら、チームのSlackに問い合わせの内容をできるだけ詳細に伝えて、協力を依頼する。

などという細やかなTipsが続くのですが、これら私がいま新人だったらツライ業務の一つだなと思います。

## 一方

このフォーマットが面白いフローチャートだったので噛み砕いて考えてみました。

```plantuml
@startuml
start
:電話を取る;
:用件をまとめる;
if (取次ぎたい人がいる?) then (yes)
  if (取り次ぎたい人に取り次げそう?) then (yes)
    :用件を伝えて電話を取り次ぐ;
  else (no)
    :用件を再確認する;
  endif
else (no)
  :用件を再確認する;
  :回答できるなら回答する;
endif
:電話を切る;
stop
@enduml
```

電話を受けた際のゴールは、つまりは、緊急度と重要度をうまくヒアリングして、相手の状況を過不足無くサマリする。それに尽きます。内容はIssueやチケットの書き方と同じですよね。

[伝わるチケットの書き方（チームメンバーが理解できる！作業できる！） - Qiita](https://qiita.com/aut44takada/items/12f62b9295c28f408e93#%E3%83%81%E3%82%B1%E3%83%83%E3%83%88%E3%81%AE%E5%85%B7%E4%BD%93%E7%9A%84%E3%81%AA%E6%9B%B8%E3%81%8D%E6%96%B9)
＊Issueの書き方をまた後日書きたいと思います。
つまり理想形は以下なのです。


```plantuml
@startuml
start
:電話を取る;
:用件をまとめる;
:用件を再確認する;
:電話を切る;
stop
@enduml
```


## Now.

PlantUMLで書いてみたいだけのようになってしまいましたが、

、在宅勤務が主になった今、新人が電話をとるものだという時代は過去のものになりました。しかしポイントはおそらく変わりません。「緊急度と重要度をうまくヒアリングして、状況を過不足無くサマリ」し、開発としてどうアクションするかの現況に落とし込む作業です。

社内の開発内応対Slackチャンネルでも意識できるよう工夫を考えていきたいポイントです。
以上です～。
Nand2Tetrisやってみたその１〜Nandからブール演算編〜

#はじめに
###Nand2Tetrisとは
オライリーの「[コンピュータシステムの理論と実装ーーモダンなコンピュータの作り方](https://www.oreilly.co.jp/books/9784873117126/)」という書籍の通称。

>本書を書いた理由は、多くの学生が「木を見て森を見ず」の状態であるように思えたからである。（中略）彼ら彼女らは、コンピュータの中がどのようになっているかを理解していない。そして、そのことを心許なく思っているはずである。
>

今日のコンピュータサイエンスにおいて、各専門分野はどんどん複雑になってきています。
１つの分野のある一面を修めるだけでも相当な労力がかかり、CS全体を俯瞰する機会を得るのはなかなか難しいです。
この書籍は、「コンピュータを理解する最善の方法は、コンピュータをゼロから作り上げることである」をテーマに掲げ、そのような情報工学を学ぶ迷える学生の助けとなるべく書かれました。
###Nand２Tetrisの構成
コンピュータを構成する要素を、ブール論理から始まり高水準言語、コンパイラまで各分野について学びます。
それぞれの章では、各要素の概要を学んでから、実際に実装を行います。
各章は独立してモジュール化されていて、現在取り組んでいるレイヤよりも下位レイヤに属するモジュールは使い回すことができます。

#Nandからブール演算
この記事では、第１章の「ブール論理」まで扱います。
####コンピュータにおけるブールゲート
ブールゲートとは、ブール関数を物理的に実装したものです。その実装方法は様々ですが、それは情報工学の範疇を超えるので、ここでは論理的な振る舞いだけに着目します。

####正順表現
すべてのブール関数は（当然ですが）**真理値表**によって表現することができます。


**例**

|x  |y  |z |f(x,y)  |
|---|---|---|---|
|0  |0  |0  |0  |
|0  |0  |1 |0  |
|0 |1  |0  |1  |
|0  |1  |1  |0  |
|1  |0  |0  |1  |
|1  |0  |1 |0  |
|1 |1  |0  |1  |
|1  |1  |1  |0  |

真理表が分かっているすべてのブール関数は**正順表現**と呼ばれるブール式で表現できます。

出力が１となる各行に注目して、その入力の組み合わせの時のみ１を出力するブール式を考えます。
１を出力する全ての行について、得られたブール式たちをOrで繋げば仕様を満たす関数が得られます。

:::note
その入力の組み合わせの時のみ１を出力するブール式　とは

その行で０になっている入力を反転（Not）させて、すべての入力をAndで繋ぎます。</summary>
例えば、上の例では(x,y,z)=(0,1,0)の行で１を出力しています。ここで、((not x) and y and (not z))は、入力が（0,1,0）の時のみ１を出力します。</details>
:::

正順表現に使ったのはAnd,Not,Orだけです。
つまり、**And,Not,Orだけであらゆるブール関数を表現できる**ということです。

そして、And,Not,OrもすべてNandだけで構成することができますから、Nandだけですべてのブール関数を表現できることになります。

#実装
(AndとかOrなどの予約後になりがちな名前を宣言してるのでqiitaのシンタックスハイライトがおかしい)
####Not実装
```hack
CHIP And {
    IN in;
    OUT out;

    PARTS:
	Nand(a=in,b=in,out=out);
}
```

####And実装

```hack
CHIP And {
    IN a, b;
    OUT out;

    PARTS:
	Nand(a=a,b=b,out=c);
	Nand(a=c,b=c,out=out);
}
```
####Or実装
```hack
CHIP Or {
    IN a, b;
    OUT out;

    PARTS:
    // Put your code here:
	Not(in=a,out=nota);
	Not(in=b,out=notb);
	Nand(a=nota,b=notb, out=out);
}
```
###その他主要論理ゲート
ここでは割愛しますが、Xorやマルチプレクサ,デマルチプレクサ,それぞれの回路の16bit版なども実装しました。

#感想
コンピュータの最下層レイヤを触るにあたって、普段とかなり違う部分の脳を使っていたと思います。
今回実装したブールゲートたちは次のブール演算の実装で大活躍するので、愛着があります。
次回、「ブール関数からブール演算編」です。頑張って書きます。
医療介護現場に笑顔を増やすプロダクトを実装したい-スマイルレポート１

私は在宅医療に携わる医師です。
医療現場の課題をプログラミングの技術で解決するため2021年10月から学び始めました。

これまでも、[申し送りを行うための仕組み](https://qiita.com/naokiuc/items/6d000d573fa0dc70097d)や、[訪問先で記載したカルテについて写真を撮れば自動で事務さんがみれるようになる仕組み](https://qiita.com/naokiuc/items/93b3126e583d896ec477)を実装し日々の臨床で使っています。

今回、自院だけでなく多くの医療機関や介護施設で使ってもらえるプロダクトの開発を考えていて、今回の記事ではそのプロダクトの完成イメージを共有したいと考えています。

#スマイルレポート
プロダクト名は**スマイルレポート**といいます。
スマイルレポートは、サンクスレポートとヒヤリハットレポートに分かれています。

##サンクスレポート
サンクスレポートは、職場内の他のスタッフに対する感謝をレポートするものです。
「訪問に出ている自分に代わって明日のカルテと処方の出力をしてくれた」
「忙しい自分の代わりに初診患者さんの情報を入れてくれた」
など、自分が感謝した体験を報告してもらいます。
サンクスレポートによって感謝を伝えることができますし、感謝を受ける行動を知ることにもつながります。

<details><summary>入力方法としては、Googleフォームを使うことを考えています。</summary>
<iframe src="https://docs.google.com/forms/d/e/1FAIpQLSfE21U3OHRixZ2ZkdzV94K8KTkOzbOsDEQXPCoRb_iI3tAqLQ/viewform?embedded=true" width="640" height="1203" frameborder="0" marginheight="0" marginwidth="0">読み込んでいます…</iframe>
</details>

また、職場外の人から感謝されたことを自分で報告しても良いと考えています。

##ヒヤリハットレポート
ヒヤリハットレポートは、従来紙ベースだったヒヤリハット報告をデジタル化したものです。
<details><summary>こちらもGoogleフォームを使います。</summary>
<iframe src="https://docs.google.com/forms/d/e/1FAIpQLSeqem8P5OBXWHbXqrOYZGoYKbkF58mL6sQa-4REdcSeDn3v_Q/viewform?embedded=true" width="640" height="1784" frameborder="0" marginheight="0" marginwidth="0">読み込んでいます…</iframe>
</details>

#ヒヤリハット報告を行いづらい背景について考えた
実は、**ヒヤリハット報告のデジタル化を行うことで医療介護現場のミスの繰り返しを減らすことができるのではないかというのが、元々のアイデア**でした。

紙ベースで書くのが面倒で、ファイルにとじ込まれて共有もされにくかった従来のヒヤリハット報告をGoogle Formを用いてデジタル化することで報告と共有を行いやすくするという考えです。
ハインリッヒの法則から重大な事故の背景には300件のヒヤリハットがあるとも言われており、ヒヤリハット報告と共有を活用し同様のヒヤリハットを減らすことは重大事故を減らすことにもつながります。

しかし、**そもそもの課題として、ヒヤリハット報告は基本的にミスの報告でありヒヤリハット報告を前向きにどんどん書こうと考えづらいことや、ヒヤリハット報告を行うことが報告者にとって明確なメリットを感じづらいことなどがある**と考えました。

このため考えたのが今回のスマイルレポートです。
ヒヤリハットのようなミスの報告だけでなく、感謝の報告も行うことで報告の習慣をつけます。
**サンクスレポートで感謝が増え、ヒヤリハットレポートでミスが減れば、全体として職場に笑顔が増えると考えてスマイルレポートと名付けました。**

#具体的な画面とさらに報告しやすくする仕組み
さらに報告を増やす仕組みとして、ポイント制の導入を考えています。

この画面をベースにして、基本的に毎日報告します。
![名称未設定.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2051906/ffca9d34-7712-3514-dd70-d954f4d4f109.jpeg)
サンクスレポートを選べば、感謝したかされたかを選択。
![名称未設定1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2051906/5e5a4bf0-88d0-b7a9-29a6-ba392137b72a.jpeg)
一方、ヒヤリハットレポートを選べば、よくある状況を選択して報告。
![名称未設定2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2051906/86b62ad9-d8d6-9dde-3425-4385621ecc9c.jpeg)
そして最後に、そのまま詳細報告を行うかどうかを尋ねます。
![名称未設定3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2051906/9bf49e6e-c40c-b6a5-b7dd-dfb26d706173.jpeg)

はじめのページで「レポートなし」を報告しても1ポイントゲットできるようにすることで、毎日の報告を習慣づけます。
また、報告の敷居を下げるため、タブを選択するだけの簡易報告と詳細報告に分けて、簡易報告だと3ポイント、詳細報告をするとさらに5ポイントが入るようにして、うちの法人ではこのポイント数も賞与の基準に入れることを考えています（細かなポイント数については検討の余地がありそうです）。

技術面に関して、まだまだ検討が必要で基本はGoogleフォームとGoogleスプレッドシートを用いることを考えていますが、ポイント制をどのように実装するかや、簡易版の報告者名をどのように把握するかなど、考える必要がある部分が複数あります。（もし参考の記事などありましたら教えていただけますと、とってもありがたいです）

2022年1月の間にある程度形を作ることを考えており、Qiita記事上でも作成経過を報告しておこうと考えていますので、また読んでいただけると嬉しいです。