OmniAICreator/Qiita-1.07M huggingface dataset:
MeCabでパプリカのセリフ生成器を作ってみた

## パプリカとは

https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%97%E3%83%AA%E3%82%AB_(%E3%82%A2%E3%83%8B%E3%83%A1%E6%98%A0%E7%94%BB)

2006年の名作アニメ映画作品です。
中でも有名なのは、
> 「オセアニアじゃ常識なんだよ」
https://dic.nicovideo.jp/a/%E3%82%AA%E3%82%BB%E3%82%A2%E3%83%8B%E3%82%A2%E3%81%98%E3%82%83%E3%81%82%E5%B8%B8%E8%AD%98%E3%81%AA%E3%82%93%E3%81%A0%E3%82%88

というセリフです。これは上記リンクにある通り、作中で、
> 何者かによって誇大妄想狂の精神病患者の夢を脳内に流し込まれた所長が発したセリフ。

です。
誇大妄想狂の精神病患者の夢を脳内に流し込まれると、発狂してこのような変な文章を口走ってしまうのですが、この文章はデタラメのようですが、文法は正しいという特徴があります。


さて、今回はこのような文章をMeCabを使って自動生成してみました。

### まず、MeCabにnellogdを設定し、辞書のcsvファイルを読み込んでおきます。

```python
import csv
import re
import MeCab
import numpy as np
import random
class Paprika(object):
	def __init__(self, path):
		self.__mecab = MeCab.Tagger("-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd")
		with open(path, newline='') as csvfile:
			data = csv.reader(csvfile)
			self.__sents = np.array([row for row in data])
```
### neologdの辞書から、ランダムな単語を取り出すメソッドをつけます。
https://github.com/neologd/mecab-ipadic-neologd

``` python
class Paprika(object):
	def __init__(self, path):
		self.__mecab = MeCab.Tagger("-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd")
		with open(path, newline='') as csvfile:
			data = csv.reader(csvfile)
			self.__sents = np.array([row for row in data])

	def random_sent(self):
		return self.__sents[random.randint(0,len(self.__sents))][0]
	def get_newtext(self,text):
		sents = []
		for s in self.__mecab.parse(text).split('\n'):
			j = re.split('\t|\,', s)
			print(j)
			if len(j) > 2 :
				if re.compile('^名詞').match(j[1]):
					j[0] = self.random_sent()
				sents.append(j[0])
		return ''.join(sents)
```

 これで、任意の文章の名詞のみをランダムに書き換えることができます。

``` python
p = Paprika('Noun.csv')
text = "吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。"
text = p.get_newtext(text)
print(text)
```

実行結果

```
尚侍。年歯はまだ無い。錨鎖で生れた新刀と盗人がつかぬ。納采でも薄暗いじめじめ二食静心でニャーニャー泣いて書き下し文だけは目安している。
```
[Xcode] Info.plistでアプリをダークモード非対応にする設定

## はじめに
現状、iOSアプリではデフォルトでダークモードも対応する仕様となっています。

カラー設定など、対応完了するまで一時的に非対応としたい場合はInfo.plistでライトモードのみ対応する仕様に変更可能です。

## 設定方法

`Info.plist`の`Information Property List`に**`Appearance`**の項目を追加し、valueを`Light`にする。

[![Image from Gyazo](https://i.gyazo.com/5ad6a24992b42c4304f728de535a2090.png)](https://gyazo.com/5ad6a24992b42c4304f728de535a2090)

### コードで記述することもできる

Info.plistを右クリックし、`Open As` -> `Source Code`と進むと、Info.plistをxmlファイルで開くことが出来ます。

[![Image from Gyazo](https://i.gyazo.com/9c9e3f08450a5a5508fad6a68a8ebb8b.png)](https://gyazo.com/9c9e3f08450a5a5508fad6a68a8ebb8b)

開くとこんな感じです。

[![Image from Gyazo](https://i.gyazo.com/617880bc87a34013ed04ce054e5d58e2.png)](https://gyazo.com/617880bc87a34013ed04ce054e5d58e2)

`<dict>`に以下のコードを追加しましょう。

```xml
<key>UIUserInterfaceStyle</key>
<string>Light</string>
```

これでも同じように設定することが出来ます。


## 終わりに
どちらのやり方でも設定内容は同じですので、お好みで。

このようにダークモードを非対応とすることは可能です。
が、もちろんダークモードにも対応することが推奨されていますので、一時凌ぎとして使用することが望ましいと思います。
SwiftUIでRealmを使う

数ヶ月前に書いた↓を整理したものです。

https://qiita.com/ttttpzm/items/96e3c9a7a6cab6b926b9

# はじめに
RealmSwiftの導入方法や基本的な仕様についてはUIKit版と同じため割愛します。
基本的なSwiftUIの仕様も割愛します。

# テーブル(モデル)
SwiftUIではテーブルクラスにObjectKeyIdentifiableプロトコルを追加する必要があります。

```swift
class Book :Object,ObjectKeyIdentifiable{
/*属性*/
}
```

# 注意
これから説明する@ObservedResultsや@ObservedRealmObjectで扱われるデータはSwiftUIの仕様に対応するために **凍っています。**
つまりデータを変更したい時にいつも通り書き込みトランザクションを開いてもそのまま変更することができません。必ずListやObjectを解凍する必要があります。

```swift
let thawItem = item.thaw() //オプショナル型で返ります
list.thaw()?.move(fromOffsets: indexSet, toOffset: index)//RealmListで並び替えを行う場合
```
# 検索
```swift
@ObservedResults(Book.self,filter:NSPredicate(format: "title != 'L'"),sortDescriptor:SortDescriptor(keyPath: "start", ascending: false)) private var results
```
イニシャライザからでも指定できます。
検索条件やソートは省略できます。
@ObservedResultsのResultsは、そのままForEachに入れることができます。

# (Realmの)List

```swift
@ObservedRealmObject var parent:Hondana
//---
ForEach(parent.books){
book in
/*ここにView*/
}
```
@ObservedRealmObjectを付けるとForEachでRealmのListをそのまま扱えるようになります。
(リスト要素は解凍されていないことに注意してください)
# onDeleteやonMoveについて
```swift
.onDelete(perform: $results.remove)
```
このように$を付けることで削除したりListの場合は移動することができますが、自分で書き込みトランザクション(realm.write{})処理を行う場合は、必ず前述したように**thaw()**を使用して解凍してください。

# 追記
古いバージョンのRealmだとSwiftUIのプレビューが失敗したりします。最新のバージョンを利用してください。
Flutterでの効率的なスタイリング方法 -スタイルを関数として定義する-

Flutterでスタイリングをするときは通常，毎回スタイリング内容を書かなければならない．

例えばこんな感じ

```dart:main.dart
Text(
  'Hey! How are you?',
  style: TextStyle(
    fontSize: 20,
    color: Colors.indigoAccent,
  ),
),
```
こんな感じでTextStyleを使って毎回どんなスタイリングにするのか宣言しないといけない．
でもこれって，同じスタイリング内容を何度も使うときは**めんどくさい**ですよね．

そんなときはスタイリング内容を関数として定義して，何度も使えるようにしましょう．
具体的な定義方法は，

```dart:styles.dart
class Styles {
  static const h1 = TextStyle(
    fontSize: 16,
    color: Colors.indigoAccent,
  );
}
```

複数のファイルで使用できるようにするために，スタイリング内容を定義するためだけのファイル（例：styles.dartなど）を用意しておくと**Good**です.そうすれば，ファイルをimportするだけで全ての定義したスタイルを使用することができます．

ではこの定義したスタイルをどうやって使うのかについて解説します．
具体例を見せるとこうです．

```dart:main.dart
Text(
  'Hey! How are you?',
  style: Styles.h1,
),
```

ずいぶんコード量が減りましたよね．
これが使えると，かなりコーデイングが楽になるので便利ですよ！
DynamoDB 入門

テーブルをリスト

```bash
$ aws dynamodb list-tables --endpoint-url http://localhost:8000
{
    "TableNames": [
        "hoge",
        "piyo"
    ]
}
```

テーブル詳細を確認

```bash
$ aws dynamodb describe-table --table-name hoge --endpoint-url http://localhost:8000
```

クエリ

```bash
$ aws dynamodb query \
--table-name hoge \
--endpoint-url http://localhost:8000 \
--key-condition-expression "uid = :uid" --expression-attribute-values '{":uid":{"N":"202103251454504773"}}'
```
AI/IoTデバイスのリモート一括配布OTA機能

#はじめに
新型コロナウィルスの感染蔓延の下、
多くの企業には、このような厳しい状況の中、リモート作業を選びました。
しかし、現場でしか処理できない問題は一体どのように対応すればいいのでしょうか。

例えば、全国に各拠点に配置していた各デバイスのソフト更新作業などは、
人員のオンサイトよりも、もっと効率のいい方法はあるのではないかと考えたことはありますか。

どのように迅速かつ大量にデバイスの、
更新または管理をするのが今時の大事な課題となっています。
これからはこのような問題を解決できる[Allxon](https://allxon.com/ja-JP/)(アルクソン)の、
DMS(デバイスマネジメントサービス)を利用した、
大量配布OTA機能の概念をご紹介いたします。

#Allxonについて
AI/IoTデバイスの管理ソリューションを提供してる台湾のSaaSプロバイダ。
現在は日本、欧米を中心に活動しております。
そしてNVIDIAのコアパートナーとして選ばれ、現在は[NVIDIAエコシステム](https://developer.nvidia.com/embedded/community/ecosystem)内に、
唯一クラウドマネジメントサービスを提供しているソフトウェアの会社となっています。

#Allxon OTA機能
・Web Portalで簡単操作
・Grouping機能
・One Clickで一括配布
![擷取.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1509678/09f7522a-c5bf-5409-58ac-58a020152952.png)



#終わりに
上記の構成図をご覧になって頂いて、だいぶOTAの概念はお分かりになりましたでしょうか。
実際の操作方法は次回にてご紹介させて頂きたいと思います。
まず一度[Allxon Portal](https://dms.allxon.com/home)からご登録をしてみませんか。
また、OTAについて、何か考え方や質問のある方がいらっしゃれば、
是非下のコメント欄に書いて頂けると嬉しいです。
実ビジネスにおけるデータ外れ値との向き合い方

# はじめに
[前回](https://qiita.com/hiro_kimu/items/7e1b8df663aa3b9aa130)は欠損値について考察しましたが、今回は同じく機械学習で会うことの多い外れ値について考えていこうと思います。データエンジニアリング手法については今回も他の記事にお任せします。

# 外れ値とは？
外れ値自体は単に値が他のデータとかけ離れているということです。見つけ方としてスミルノフ・グラブス検定など統計的検定手法はありますが実際に何を外れ値として扱うかというのは製造や医療など事業分野によって変わるようです。これは外れ値だからとなんでもかんでも対処してしまうとデータから現実の事象を切り離してしまう恐れがあるからです。欠損値のところでも触れましたがデータが正確に取れていることを前提とした場合、安易なレコード削除や加工は現実を再現しているデータを改変することにもなるので慎重であるべきと思います。

# やはり確認から始める
欠損値の時と同様に何故外れ値として出てきたかをデータオーナーまたはデータ有識者に確認することが重要だと思います。簡単な確認順としては以下が考えらえれます。
1. 業務上発生しうる外れ値か？
2. 発生する頻度はどれくらいか？今後も発生するか？
3. 発生した場合のビジネスフローは他のデータと同様か？

自社の例ですと特定のお客様が大量購入していただいた結果、金額項目が外れ値として統計で出てきたことがあります。気をつけなければいけないのはある項目が外れ値となっていた場合に関連項目はあるか？ということだと思います。例えば独立した2項目の[単価]と[数量]を乗算した[トータル金額]という項目があった場合、トータル金額だけが外れ値となることもあります。関連項目があった場合はそちらの確認もする必要があります。
外部購入データやオープンデータも可能な限り発生理由を確認することが求められます。


# 外れ値の本領は発見できること？
機械学習プロジェクトではEDA(探索的データ解析)を行いますが、まずここで外れ値を見つけることができます。その結果をビジネスの担当者に報告するわけですが、これがとても効果的だと思います。何故外れ値になっているのか？他データと分けて対応しなければならないケースなのではないか？といったビジネスそのものの見直しが出来るからです。データ分析を進めていない場合、データの中身について各担当者は頭の中だけで個別に理解していることが多いと感じます。EDAの結果を報告することにより情報を共有して対処することが可能になります。


# 機械学習プロジェクトで実際にあった外れ値
1. 売上総金額が高額になっている
1. サポート残日数が余りにも長い
1. サイト閲覧回数が非常に多い
1. 値引き率がゼロ過剰

幸いというべきか、ターゲット項目に外れ値があったことはありませんでした。
機械学習のターゲット項目が外れ値であった場合はより深い議論が必要です。自社プロジェクトでもし発生したら書こうと思います。

# 機械学習ではどう外れ値に対応するか？
データ分析を進める場合の対応方法に絞って書きますが、業務有識者に確認が取れるならそれが一番です。私自身がやったことあるのは外れ値ではない上限値に一律設定するという単純な方法だけですが、そういった対処をした場合には[外れ値発生フラグ]といった項目を対処した項目ごとに持たせるのは有効だと思います。または上限値設定などはせず[外れ値発生フラグ]を持たせるだけにするなど、対処方法は色々あると思うのでこれは業務有識者に確認しながら試していくしかありません。
また、必ず対処すべきかというとそんなこともないと思います。
該当項目が分析モデルに大きな影響を与えていないのなら対処しないのも選択肢です。

# おわりに
前回同様、記事では私自身の機械学習プロジェクトの経験に基づいて記載しています。
データサイエンティストにとってデータはある意味ご馳走ですが、データオーナーや業務有識者にとってデータは業務成果物、彼らの仕事の成果です。それを忘れないようにデータに対処していくことがビジネスにおける機械学習では求められていると信じています。
[Rails] Basic認証の実装

# 記事の概要
　[こちら](URL"https://qiita.com/kei-kun1960/items/40599c32c7341759afe4")の記事でアプリのHerokuデプロイした続きです。Railsアプリへのアクセスを制限するためにBasic認証を実装する。

# Basic認証とは
　Basic認証とは、HTTPで定義される認証方式の一つで、基本認証ともいう。サーバーとの通信が可能なユーザーとパスワードをあらかじめ設定しておき、それを知っているユーザーだけがアプリにアクセスできるようにする。

# 実装方法
### ① Railアプリへの導入
　authenticate_or_request_with_http_basicメソッドを利用する。application_controllerにプライベートメソッドとして定義し、before_actionで呼び出す。
　任意のユーザー名とパスワードをそれぞれusername, passwordとして設定するが、これらをコードに直接記述してしまうと公開リポジトリで読まれてしまう。したがって下記のように環境変数に設定してそれを読み込むようにする。

```app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :basic_auth

  private

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"] # 環境変数を読み込む
    end
  end
end
```
### ② 環境変数の設定
　上記の環境変数の設定を行う。ローカル環境、本番環境(Heroku)それぞれに設定する。

#### 　ローカル環境
　ログインシェルの設定ファイル、zshやbashに定義する。今回はzshの場合。
まず下記コマンドでzshをテキストエディタで開く。「vim」とは、サーバー上で使用できるテキストエディタ。

```
% vim ~/.zshrc
```
　zshの中に以下のようにユーザー名とパスワードの記述を追加する。

```
export BASIC_AUTH_USER='任意の名前'
export BASIC_AUTH_PASSWORD='任意のパス'
```
　最後に、sourceコマンドでzshファイルに記述した内容を実行する。

```
% source ~/.zshrc
```
#### 　本番環境(Heroku)
　Heroku上に環境変数を設定する。ターミナルでコマンド実行。

```
% heroku config:set BASIC_AUTH_USER="任意の名前"
% heroku config:set BASIC_AUTH_PASSWORD="任意のパス"
```
### ③ Herokuへ変更をPush
　コードを変えたので、コミットとHerokuへのPushを忘れずに。

```
# ターミナルで実行
% git add .
% git commit -m "Basic認証の導入"
% git push heroku master
```
実ビジネスにおけるデータ欠損値との向き合い方

# はじめに
kaggleのような精度を競う場だけではなく実ビジネスにおいてデータ分析する際にも欠損値データに苦慮することが沢山あります。
実ビジネスの機械学習プロジェクトに携わっている立場から欠損値について考察していきます。
データエンジニアリングの手法的なところは他に記事があるのでそちらにお任せします。

# 欠損値って何？どうするの？
中身がない、「Missing Value」のことです。
データ分析する際に欠損値があると処理が動かなかったり、結果が偏ったりと弊害があることもありデータエンジニアリングで欠損値埋めをしたりすることもあります。ただし闇雲にレコード削除、列削除、平均値埋めなどするのはお勧めしません。データというのは現実を再現する情報なのでそれを削除、改変するのは慎重であるべきと私は考えます。

# どうして欠損しているかの確認が最優先
実ビジネスのデータにおいて欠損がある場合は、素直にデータオーナー(データソースの責任者)や業務有識者に確認することを推奨します。なぜなら欠損していることに”意味がある”ことが考えられるからです。
欠損値で検索すると必ず出てくる「MCAR」「MAR」「MNAR」について説明した上でどれですか？と確認することから始めるといいでしょう。
- MCAR(missing completely at random)：完全にランダムな欠損
- MAR(missing at random)：ランダムな欠損。欠損値以外の要因によって欠損。
- MNAR(missing at random)：ランダムではない欠損。欠損値自身の要因によって欠損。

# 欠損理由の確認が困難なケース
社内システムのデータなら欠損理由は努力次第で確認可能なことが多いですが、厄介なのはオープンデータ含む外部データを使用する場合です。
データマネジメント書籍(DMBOK)では他社購入データについてもデータ品質の対象になっており品質確認が推奨されています。ただ現実として全部が全部確認できるとは限りません。その場合は残念ながら当該項目を欠損値対応した上で使用した分析モデルと項目自体を使用しなかった分析モデルの2つを作って比較するくらいでしょうか。

# どれだけ欠損しているかの確認も
実ビジネスにおいて複数データソースの粒度や時点、鮮度を揃えたレコードを作成していくと欠損値割合が非常に多い項目、またはデータソースに出会うことがあります。その場合は使用するデータソースとして最適かを有識者確認することが望ましいです。もし使用する場合もデータソース各項目を使用するのではなく欠損してたかどうかだけを表すフラグ項目を作ることも検討します。

# 機械学習プロジェクトで実際にあった欠損理由
1. 昔は使ってたけど使わなくなった項目
2. 後から追加したけど昔はなかった項目
3. 任意入力項目 

「MCAR」はありませんでした。

# どうやって欠損値対応するかも確認が優先
1.,2.とも何故使わなくなったのか、あるいは使うようになったのかの確認が必要です。社内システム変更であったのか、ビジネスプロセス自体の変更であったのかなど、要因次第で他の項目への影響も考えられるからです。
よくあるケースは3.ですが、これも欠損理由が何かにより欠損対応が変わってくることが考えられます。ここからはデータエンジニアリングの領域なので割愛しますが、その項目だけ対処すればよいのか？欠損したことを証拠として残す新規項目を作った上で欠損値埋めをするかなど欠損している各項目について確認が必要です。

# 評価指標の精度よりも有識者の納得感を
ビジネスにおけるデータ分析では精度より業務担当者の「納得感」の方が重要と私は考えます。
極端な例を挙げると、欠損のあるレコードを取り除いた結果としてモデル精度が上がったとしても実際のビジネスでは通用しないことが多いでしょう。当然テストデータの精度で発覚するのが望ましいですが用意できるテスト用レコード件数によっては気付かず、暫定運用期間にならないとわからないかもしれません。
欠損値対応一つ一つの確認などは項目が多くなってくると業務担当者も嫌がるかもしませんし、確認を依頼するのも大変です。
しかし、業務担当の方が納得していない分析モデルは使ってくれませんし、使われなくなります。

# 機械学習モデルはデータから作られることの説明を
AIはブラックボックスだ、説明可能性が低いだのと言われます。データサイエンティストはそういった認識に対し真摯に向き合う必要があります。ただそれは難しいことではないと思います。
データ分析モデルはデータから作られているという一点は揺らぎません。
業務担当者の方に理解できない、納得感のない分析モデルが生まれることはビジネスデータにおいてはないと思ってよいのではないでしょうか？もしそんな事態が発生したらCRISP-DMにあるようにビジネス理解に立ち返りましょう。
欠損値への向き合い方もデータ全体と同様で「納得感のある」分析モデルを作るためと考えると少しは気が楽になりませんか？

# おわりに
私自身が取り組んだことのあるデータ分析における欠損理由の最たるものは任意かつ手入力項目でした。
BtoCではなくBtoBの場合はまだまだそんなデータが多いのではないでしょうか。
この記事がこれからデータ分析に関わっていく方の助けになればと思います。
Dateなんてもう嫌いだ

# はじめに
rで `as.Date` 使うたびにググっている気がするので備忘録。
# Dateにするとき
基本は文字列→Dateに変換

```R
hoge_date <- as.Date("1960-01-01")
```

# 文字列からDateにするとき
数字だけからDateにしたいときは `format=""` で指定。

```R
hoge　<- "19600101"
hoge_date <- as.Date(hoge_date, format = "%Y%m%d")
```

hogeがintegerだとエラーを吐くので文字列にしてから`as.Date()`する

```R
hoge_date <- as.Date(as.character(hoge_date), format = "%Y%m%d")
```
新入社員の課題改善について（テスト）

##目次

ビジネススキルとして下記の指摘を受けたり、悩んでいる
場合の改善参考資料として本資料を作成しました。

１．先輩・上司・顧客とのコミュニケーションがうまく取れていない

２．報連相のタイミング・意識する点

３．タスク・改善事項等のスピード感を上げる


##１．先輩・上司・顧客とのコミュニケーションがうまく取れていない


本課題について、下記3点を改善する。

1-1．相手との認識合わせ、プロービング

1-2．必要な情報を早く入手する為に、周りの人を使って情報を入手する

1-3．自分が相手だった場合としての考え方の仮説を立てる



##1-1. 相手との認識合わせ、プロービング


何を話していいか分からないなら、雑談Lvから話しをして親睦を深める（話せる関係性を作る）
分からない事の質問・勉強会をしてもらいたい等の話をして教えてもらうのも良し。

※プロービングとは
あいまい（不完全）な回答（自由回答）の深堀をすることを指す
相手から必要な情報を聞き出すフェーズ
ニーズを正確に理解し、潜在的なニーズに気づいてもらう

###■１）相手の期待値を把握する
相手の期待値を超え続けることがビジネスの基本。その為に相手の期待の中身を
把握する必要あり。
「そんなこと1ミリも頼んでない」と言われないために相手が何を期待している
のかを正確に把握できるようにする。

###■２）相手の理解度を推し量りながら話す
「無言は理解」ではなく、「無言は無理解」のサインと意識する。
相手の理解を観察して、理解度を察知する。
◇理解していないシグナルとして
・こちらが資料をめくって次に進んだのにまだ前の資料を見ている。
・こちらを見ずに隣の人の顔を見ている。
・「大体わかりました」「おおよそわかりました」等曖昧な返事をする。

※こちらからの提案、意見を自分手動でする話となるので相手の期待値把握の改善後または、並行で意識して進める。

##1-2．必要な情報を早く入手する為に、周りの人を使って情報を入手する

自分一人で考えて、答え・考えが分からない、出ない場合 周りの人に聞いた方
 が早い。そして色々な意見を入手する。
 時短で情報集めて、他業務に取り組む時間を作る。
 依頼された作業でも一人で抱え込まず、他の人を使うことでスピードを上げる
 ことにもなる。

###■１）出来ない時は出来る方法を模索・提案する
・出来ない時は出来る方法を提案する。
明日までに○○やってほしい。と依頼があったとして、徹夜すれば出来るかも
という状況なら「はい、出来ます。ただ一人ではボリューム的に無理です。手
伝ってくれる人が1人いれば協力して終わらせることができます」といういう
ような言い方なら言い訳っぽくならないし仕事が進みそうな感じに受け取られるし
相手から「じゃぁこうしよう」といったヘルプも言ってもらいやすくなる。


##1-3. 自分が相手だった場合としての考え方の仮説


依頼された作業等を行う場合、相手が何のために作業依頼したのか、どんな
ものを求めているのか。を逆の立場だったら？で考える。

###■１）相手の期待値を把握する
相手の期待値を超え続けることがビジネスの基本。その為に相手の期待の中身を
把握する必要あり。
求められていない事に時間を使っても、クライアントからも上司からも評価は
されない。まず相手が何を期待しているのかを正確に把握する。

相手が何をどのレベルまで期待してるのかを見極め、絶対に外さない。
そして、相手の期待値のちょっと上を常に達成していく。
期待値を満たせないものは、安請け合いしない。
⇒相手が何を求めているか仮説を立てて物事を進める。


##２-1．報連相のタイミング


相手から指摘される前に自分から報告・連絡する。
例として通院したら直ぐ結果を報告する。上司から見てリスクとなりえる事柄であれば
報告するよう意識する。どんなことを報告すべきかはネット記事・本・周りの人からの情報
集めてベースを作っておく必要あり。
トライ＆エラーでとりあえずやってみるはやらない様にする。
★とりあえずやってみるではなく、色々なパターンを洗い出しこのパターンはどうする？
このパターンだったら○○な回答となるだろうとの仮説を立ててやってみるのもあり。

・「報告」とは、指示を与えられた人が、その進行状況や結果を指示を出した人に伝えること
・「連絡」とは、得た役立つ情報を、他の関係する人にお互いに伝えること
・「相談」とは、抱えている課題や問題に対して、他の人に意見や助言などを求めること


##２-2．報連相のタイミング

###■改善方法
※下記のようなリストを作成し確認しながら進める。
１）毎朝晩の作業内容/結果の報告
□朝一作業前に報告
□夕方進捗結果報告
□次の日の予定も報告

２）指摘されたことの改善案報告
□指摘されたら、その日の内か翌朝に"昨日指摘された○○の件、こうやって改善していく"と報告する

３）作業の進捗報告
□作業依頼あったら、期日・ゴール・誰に何の為に作るのか認識合わせ、認識あうまで開始しない
□作業依頼されたら3hで一旦状況・認識合わせ（これだよね？の）報告
□不明点は都度確認
□レビューバックあれば、次の再レビュー日を決める

###下記情報を意識する。
①　報告のタイミング
　　　[緊急]    トラブル・ミスが発生した場合など
　　　　　　⇒　即時ＯＫ
　　　[上記以外]    相手のタイミングを見ること。
②　報告なのか、連絡なのか、相談なのか、その数と所要時間を
　　伝えた後、まず結論。理由や経緯の説明はあと。
③　相談時、判断を仰ぐ時は、自分の考えを伝えること。
④　事実 と 推測/判断 は 明確に。
⑤　５W１Hを意識し、定量的に。

##３．スピード感

報連相のタイミングと同じになるが、相手から突っ込まれる前に報告のタイミング
・頻度を増加させる。
報告する内容・程度は、自己満になって回数増えても報告しないより良いので、
報告すべきことは2．報連相のタイミングの件考えて伝えるようにする。

###■１）スピードと質を両立する
・時間をかけないといいものは出来ない。は嘘
スピードを追及すると質も上がる。
Quick & Dirty、直訳すると「素早く、汚く」ということだが、時間をかけて
完璧なものを目指すよりも、多少汚くても構わないので、とにかく早くつくる。

・何も出てこない、という実時自体が貴重な発見。
「この方法ではうまくいかない」と気付くことが出来ればすぐに軌道修正が出来る。
「3日の100点より3時間の60点」の動きで汚くてもラフでもいいから完璧なもの
でなくても早く出す。
そこからPDCAを回していくようにする

※PDCAサイクルとは
Plan(計画)・Do（実行）・Check（評価）・Action（改善）を繰り返していく
事によって生産管理や品質管理などの管理業務を継続的に改善していく手法のこと
AWSを活用したAngularとSpring Boot間のSSL通信

<h1>構成図</h1>
![Nihaomemo構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630191/251977b3-cde8-3c1c-9ac0-f0c032b946c1.png)


<h1>前提条件</h1>
<ul>
<li>EC2にSpring Bootアプリをデプロイ済み
<li>S3にAngularアプリをデプロイ済み
<li>お名前ドットコムなどで独自ドメイン取得・Route53とお名前ドットコムネームサーバー設定済み
<li>バージニア北部リージョン(CloudFront用)・東京リージョン(ロードバランサ用)にそれぞれ独自ドメイン用の証明書を作成済み
</ul>
<h1>手順①CloudFrontディストリビューションをS3オリジンで作成する</h1>
<ul>
<li>Origin or Origin Groupで事前に準備していたS3を選択
<li>Viewer Protocol PolicyはRedirect HTTP to HTTPSを選択
<li>Alternate Domain Names(CNAMEs)に独自ドメインを入力
<li>SSL CertificateはCustom SSL Certificateを選択・事前にACMで準備していた証明書を選択
<li>Default Root Objectはindex.html
</ul>

<h1>手順②ロードバランサを作成する</h1>
<ul>
<li>リスナーはHTTPS : 443を追加
<li>ターゲットグループはEC2を選択
<li>ターゲットグループのポートはSpring Bootのポートを選択する(デフォルトは8080)
<li>SSL Certificateは事前にACMで準備していた証明書を選択
</ul>

<h1>手順③Route53を編集する</h1>
<ul>
<li>レコード名をwww.{独自ドメイン}・値をエイリアスをONにして手順①で作ったCloudFrontのディストリビューションを選択してAタイプのレコードを作成する(エイリアス経由で値は設定すること・DNS名などをそのままコピペで入れたりするのはNG)
<li>レコード名任意・値をエイリアスをONにして、手順②で作ったロードバランサを選択してAタイプのレコードを作成する(エイリアス経由で値は設定すること・DNS名などをそのままコピペで入れたりするのはNG)
</ul>

<h1>手順④AngularのhttpリクエストURLをソースに記述する</h1>
AngularのhttpリクエストURLは
https://{手順③で作成した、ロードバランサを値に持つAタイプのレコード}

<h1>手順⑤Spring Bootの@CrossOriginに入力</h1>
@CrossOriginに入力するURLは
https://{手順③で作成した、CloudFrontを値に持つAタイプのレコード}

<h1>手順⑥AngularをS3・Spring BootをEC2にそれぞれデプロイし直す</h1>
そのままになります。

<h1>感想</h1>
Route53でCloudFrontとロードバランサのレコードをそれぞれ別のレコード名にして作成することや、そもそもロードバランサでSSL終端をする場合のAngularhttpリクエストの宛先はどこか、などかなり詰まりました。
[Rails] Herokuデプロイの手順

# 記事の概要
　RailsアプリをHerokuにデプロイをします。手順を忘れないようにメモ。

# ① Heroku CLIのインストール
　CLIをインストールすることで、herokuコマンドが使用でき、ターミナルからHerokuにアクセスできる。下記コマンドを実行。

```
% brew tap heroku/brew && brew install heroku
```
　下記コマンドで完了を確認。

```
% heroku --version
```
# ② Herokuにターミナルからログイン
　下記コマンドを実行し、表示に従いHerokuのメアドとパスを入力。

```
% heroku login --interactive
```

# ③ アプリをHeroku上に作成する
　heroku createコマンドを実行する。

```
# プロジェクトディレクトリにてコマンド実行。
% heroku create アプリ名
```
# ④ データベース設定
　HerokuではデフォルトのデータベースがPostgleSQL。MySQLを使用するためには、ClearDBアドオンを追加。その後、順にコマンド実行して設定。

```
% heroku addons:add cleardb
```

```
% heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`
```

```
% heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}
```

# ⑤ master.keyを環境変数に設定
　Heroku上には環境変数としてmaster.keyの値を設定する。

```
% heroku config:set 環境変数名=`cat config/master.key`
```

　設定されたHerokuの環境変数一覧を確認するためのコマンドは、

```
% heroku config
```

# ⑥ 動作環境設定
　Herokuにおけるアプリ動作環境(stack)はデフォルトでHeroku-20。stackを指定する場合は下記コマンド実行。
Heroku-18に変更する場合。

```
% heroku stack:set heroku-18 -a アプリ名
```


# ⑦ アプリをHeroku上にプッシュ
　GitのリポジトリをHerokuにプッシュする。

```
% git push heroku master
```

# ⑧ Heroku上でマイグレーション実行
　Heroku上のデータベースにマイグレーションを反映させる必要がある。
　Railsアプリであれば、いつものrails db:migrateの頭に「heroku run」をつけて実行。

```
% heroku run rails db:migrate
```

# ※ アプリ情報の確認
　heroku apps:infoコマンドでアプリの情報を確認できる。

```
% heroku apps:info
```
sqlite3::constraintexception: foreign key constraint failed  【解決策】

##起こったこと
ユーザーを削除しようとしたら下記のようなエラーが出てきてしまった。

```ruby:
sqlite3::constraintexception: foreign key constraint failed
```
##環境
Ruby : 2.7.3
Ruby on Rails : 6.1.3.2
SQLite3 : 3.32.3

##アプリの機能
私が作っているアプリはユーザーが投稿、いいね、コメント、フォロー機能などを備えていました。
ですので、
主なテーブルとして、User,Post テーブル
中間テーブルとして、Postlike,Comment,Relationshipテーブル
を作っていました

##原因・解決策
原因はdependent: :destroyのつけ忘れです。
dependent: :destroyとは、これをモデルにつける(以下のように)ことによってUserが削除された時にUser外部キーに設定していた投稿自体も削除してくれる便利なものです

```ruby:user.rb
class User < ApplicationRecord
  has_many :posts, dependent: :destroy <---ここが大事
end
```

```ruby:post.rb
class Timepost < ApplicationRecord
  belongs_to :user
end
```

といっても自分自身dependent: :destroyはしっかりコードに記述しながらアプリを作りましたし、再度確認してもしっかりと書かれていたので最初はどこが原因かわかりませんでした。(relationships.rbを除いては)

ユーザーを新規作成し、投稿、いいね機能などを使わずにユーザー削除をすると正常にユーザーは削除されたため、原因はモデル周りにあることははっきりしました。
そして、投稿をした後にユーザー削除をすると正常に削除される（よしよし）、投稿にいいねをした後にユーザー削除をすると正常に削除される（よしよし）、このように1つずつ機能を試し、ユーザー削除が正常に機能しているのかをチェックしていると、フォロー機能を使った後にユーザー削除すると下記のエラーが出ることがわかりました。


```ruby:
sqlite3::constraintexception: foreign key constraint failed
```

フォロー機能は自分では作り方がわからなかったので[Railsでフォロー機能を作る方法](https://qiita.com/mitsumitsu1128/items/e41e2ff37f143db81897)こちらの記事を参考にして作りました。

###見た記事のモデル
```user.rb
class User < ApplicationRecord
  has_many :relationships　<--ここ
  has_many :followings, through: :relationships, source: :follow
  has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id'　<--ここ
  has_many :followers, through: :reverse_of_relationships, source: :user
end
```
```relationship.rb
class Relationship < ApplicationRecord
  belongs_to :user
  belongs_to :follow, class_name: 'User'

  validates :user_id, presence: true
  validates :follow_id, presence: true
end
```
問題はuser.rbの2行目と4行目にありました
この２つにdependent: :destroyが記述されておらずエラーが出ていたのです。
ですので以下のコードに変更しました

```user.rb
class User < ApplicationRecord
  has_many :relationships, dependent: :destroy 　<--ここを変更
  has_many :followings, through: :relationships, source: :follow
  has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id', dependent: :destroy 　<--ここを変更
  has_many :followers, through: :reverse_of_relationships, source: :user
end
```
###反省
今回はdependent: :destroy のつけ忘れでエラーが出てしまいましたが、根本的な原因はフォロー機能を実装するときにしっかりとコードを理解せず使っていたことです。
初学者のためフォロー機能の作り方なんて思いつきませんし他人のをパクるのはありがと思うのですが自分のアプリで使うコードは最低限理解する必要があるかなと思いました。
これから気をつけたいと思います
KaliLinuxのVNC設定

## 環境
```
$ uname -a
Linux kali 5.10.0-kali7-amd64 #1 SMP Debian 5.10.28-1kali1 (2021-04-12) x86_64 GNU/Linux
```

## VNCサーバーのインストール

保留

### VNCサーバーの起動/停止

```bash
# 起動
$ vncserver -geometry 1440x900 :1
```

```bash
# 停止
$ vncserver -kill :1
```


### 設定ファイルの変更

VNC接続をしてもグレーになるため、`xstartup`を以下のように書き換えます。

```~/.vnc/xstartup
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
startxfce4 &

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
```

## VNCサーバーの自動起動設定

### VNCサーバの起動をサービス化する

```/etc/systemd/system/vnc-server.service
[Unit]
Description = VNC server service

[Service]
ExecStart = sudo -u (ユーザ名) vncserver -geometry 1440x900 :1
ExecStop = sudo -u (ユーザ名) vncserver -kill :1
Type = forking

[Install]
WantedBy = multi-user.target
```

```bash
sudo chown root:root  /etc/systemd/system/vnc-server.service
sudo chmod 644  /etc/systemd/system/vnc-server.service
```

### システムの起動時にサービスを有効にする

```bash
sudo systemctl enable vnc-server
```

サービスを開始とステータスを確認。

```bash
sudo systemctl start vnc-server.service
sudo systemctl status vnc-server.service
```

## VNC接続時の日本語入力

保留


## 参考サイト
- [tightvncserver - Displaying Grey Screen on Kali-Linux upon VNC Connection](https://raspberrypi.stackexchange.com/questions/60874/tightvncserver-displaying-grey-screen-on-kali-linux-upon-vnc-connection)
- [kali linuxの起動時にスクリプトを開始](https://www.it-swarm-ja.com/ja/shell-script/kali-linux%E3%81%AE%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%82%92%E9%96%8B%E5%A7%8B/962645419/)
- [Kali Linux 2020.2 でVNCサーバを利用する。](https://mark30.hatenadiary.org/entry/2020/05/02/151603)
reason: Address already in use でPHPのサーバーに接続できない

###手順

1.使用しているPID番号（プロセスID）を確認

```
ps ax | grep php
```

ターミナルで上記のように入力すると、現在しているポートが表示される。

```
[vagrant@localhost My_php]$ ps ax | grep php
 8241 pts/0    S+     0:01 php -S 192.168.33.10:8000
```

※一番左の数字が「PID番号」なので、上記の例だと「8241」

2.既に解放しているプロセスを終了する

```
kill PID番号
```

3.再度、php -S 192.168.33.10:8000 を実行



###参考サイト

https://qiita.com/tetsu-upstr/items/5a5eac186dc4ff0a883e
Varnish Cache: Range Request レンジリクエストのデフォルト仕様と変更

###本項はLumen Edge Application DeliveryでのVarnishについての記述です
https://lumen-28.hubspotpagebuilder.com/lumen-technologies-japan/lumen-edge-cloud-app-delivery

#Varnish Cache: Range Request レンジリクエストのデフォルト仕様と変更
エンドユーザがリクエストするRangeリクエストByte範囲をそっくりそのままWEBサーバへ伝えて返却できるかという確認を行いました。

利用環境
Godaddy: Apache
Lumen: Edge Compute Varnish


キャッシュしつつも少しでもユーザ側の再生スタートを早くしたいというおもてなしです。

##デフォルト値の確認

```ruby:CURL
C:curl -I "http://www.hoge.com/test/test.mp4" -r 0-2
HTTP/1.1 206 Partial Content
Date: Tue, 25 May 2021 04:47:31 GMT
Server: Apache
Upgrade: h2,h2c
Connection: Upgrade
Last-Modified: Tue, 25 May 2021 01:32:44 GMT
ETag: "894300a-c0c308-5c31d80b68b36"
Accept-Ranges: bytes
Content-Length: 1
Vary: Accept-Encoding,User-Agent
Content-Range: bytes 0-2/12632840
Content-Type: video/mp4
```

どうやらユーザ側からレンジリクエストを行うとちゃんと返却がされるようです。

WEBサーバ側でどのようなリクエストが来ているかみてみました。

```ruby:Header_Varnish_to_WebServer
    "headers": {
        "Host": "www.hoge.com",
        "X-Forwarded-For": "125.30.xxx.xxx, 10.246.xxx.xxx",
        "User-Agent": "/7.28.0",
        "Accept": "*/*",
        "Accept-Encoding": "gzip",
        "X-Varnish": "196894",
        "Content-Length": "0"
    },
```

ん、レンジリクエストが来ていない！！
普通はヘッダにRange: bytes=0-1023とかあるはずなのに！


どうやらデフォルト状態では：

[クライアント] ← レンジON → [Varnish] ← レンジOFF → [サーバ]
となっている様です。

そこで。。。

##VCLで別途Range RequestをForwardする設定を投入


```ruby:VCL
    sub vcl_recv {
        if (req.http.Range ~ "bytes=") {
            set req.http.x-range = req.http.Range;
        }
    }

    sub vcl_hash {
        if (req.http.x-range ~ "bytes=") {
                hash_data(req.http.x-range);
                unset req.http.Range;
        }
    }

    sub vcl_backend_fetch {
        if (bereq.http.x-range) {
            set bereq.http.Range = bereq.http.x-range;
        }
    }

    sub vcl_backend_response {
        if (bereq.http.x-range ~ "bytes=" && beresp.status == 206) {
            set beresp.ttl = 10m;
            set beresp.http.CR = beresp.http.content-range;
        }
    }

    sub vcl_deliver {
        if (resp.http.CR) {
            set resp.http.Content-Range = resp.http.CR;
            unset resp.http.CR;
        }
    }
```
https://info.varnish-software.com/blog/caching-partial-objects-varnish

すると。。。

```ruby:Header_Varnish_to_WebServer
    "headers": {
        "Host": "www.hoge.com",
        "X-Forwarded-For": "125.30.xxx.xxx, 10.246.xxx.xxx",
        "User-Agent": "/7.28.0",
        "Accept": "*/*",
        "Accept-Encoding": "gzip",
        "x-range": "bytes=0-2",  ***ユーザから受け取ったRange入りました***
        "Accept-Encoding": "gzip",
        "X-Varnish": "197034",
        "Range": "bytes=0-2",  ***Range入りました***
        "Content-Length": "0"
    },
```

###ちゃんと入れてくれました！
一応クライアント→Varnishが受けたRange内容が　"x-range"　というヘッダ項目。
そして、実際のRangeリクエストが　"Range": "bytes=0-2", という形ではいります。

あとはGodaddyの仕様で "Accept-Encoding": "gzip",があると206レスポンスしなくなるのでヘッダ消してやりバッチリできました。
laravel Authで実装したログイン認証の有効時間を変更する

## 目的

- laravelのAuthを用いて実装したログイン認証の認証有効時間を変更する方法をまとめる

## 方法

1. 下記のファイルを開く。
    - `アプリ名ディレクトリ/todos/config/auth.php`

1. 上記ファイルの`Password Confirmation Timeout`に記載されている配列のキー`password_timeout`として指定されている値を変更することでログイン認証の有効時間を変更する事ができる。（設定は秒単位、初期値は10800秒として設定されている。）
SwiftUI でGPSから現在地を取得

##概要
GPS情報を使うアプリを作りたいので
SwiftUIで現在地を取得するだけの最も単純なサンプルを作成してみた。


##CoreLocationサービスを使うための準備
アプリの info.plist の
`Information Property List` に
`Privacy - Location When In Use Usage Description`
を追加し、
「現在位置を取得するために使います」
といった適当な文字列を設定する。


##ソースコード

`LocationManager.swift`ファイルを追加してlocation情報を `@Published` で発行する
`ContentView.swift` 内で観測オブジェクト LocationManager からlocation情報を取り出して表示する。


``` swift:LocationManager.swift
import MapKit

class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
    let manager = CLLocationManager()
    @Published var location = CLLocation()
    
    override init() {
        super.init()
        
        self.manager.delegate = self
        self.manager.requestWhenInUseAuthorization()
        self.manager.desiredAccuracy = kCLLocationAccuracyBest
        self.manager.distanceFilter = 2
        self.manager.startUpdatingLocation()
    }
    
    func locationManager(_ manager: CLLocationManager, 
                           didUpdateLocations locations: [CLLocation]) {
        self.location = locations.last!
    }
    
}
```

LocationManagerクラスが発行した locationを取り出して画面上に表示する

```swift:ContentView.swift

import SwiftUI

struct ContentView: View {
    @ObservedObject var manager = LocationManager()
    
    var body: some View {
        let latetude = $manager.location.wrappedValue.coordinate.latitude
        let longitude = $manager.location.wrappedValue.coordinate.longitude
        Text("\(latetude), \(longitude)").padding()    
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```

##感想
### R03/05/31
MapKitや LocationManager よりも SwiftUIに慣れる必要がありそう
【Rails】WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecatedエラー

Rspecにてテスト実行した際に、以下エラーが発生しました。

```
$ bundle exec rspec spec/system/posts.rb
 >WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead.
```

エラー文を確認すると、Chromedriverは非推奨(deprecated)なので、代わりに(instead)WebDriverを使ってくださいといった内容のことが書かれています。

という訳で早速切り替えていきます。

```:Gemfile
group :test do
  gem 'chromedriver-helper'
end
```

これを、以下に変えます。

```:Gemfile
group :test do
  gem 'webdrivers'
end
```

完了後は、$ bundleにて修正を反映させれば完了です。
【Unity、C#】静的Dataクラスを用いて、データを管理する。

</br>
##きっかけ
`GameManager`を用いた制作をよくするんですが、`GameManager`に`変数`とか、`プロパティ`とかをまとめていくと、段々ぐちゃぐちゃしてきませんか？
</br>
私はよくなっちゃうんですよね。
`#region`でまとめちゃってもいいんですけど、**なんとなくデータはデータだけでまとめちゃいたい！**
</br>
・・・ってことで、**データをまとめたクラスを別に作っちゃおう！**ってお話です。
特に書くこともないので、ざっくりまとめちゃってます。
（ちょっと読みにくいかもしれないです・・・）
</br>
##Dataクラス
</br>
まずは、Dataクラスを作成します。
Dataクラスは、**色々な場面で使用されるようなデータをまとめて管理するクラス**です。
</br>
私は以下のような形で作ってます。

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

static public class Data
{
    //〇〇で使う変数群
    public const int a=1;    //〇〇の数値a
    public const int b=5;    //〇〇の力量b
    public const int c=10;   //〇〇のスピードc
}
```

</br>
ここには、例えば**キャラクターの基本パラメータ(移動速度、ジャンプ力など)**、**操作キーやTag名の情報**、**ゲーム全体に関わるフラグ管理**なんかはまとめますが、**プレイヤーが移動し続けている時間**のような１つのクラスでしか使わないような情報はまとめずに、使うクラス上で定義してあげるといいと思います。（うまい例えが思いつかなくて、すみませｎ。。。）
</br>
では、GameManagerクラスから呼び出してみましょう。
</br>
呼び出し方は以下のようになります。

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    void Start()
    {
        //Dataクラスの中の情報を呼び出す。
        Debug.Log("a:" + Data.a);
        Debug.Log("b:" + Data.b);
        Debug.Log("c:" + Data.c);
    }
}
```

</br>
カンタンですね！
比較的、短く可読性も上がると思うので、オススメです！

##inspectorにアタッチした情報を呼び出してみる。

以下のようなクラスを作成して、inspectorにオブジェクトをアタッチします。

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SerializeData : MonoBehaviour
{
    public GameObject obj;
}
```

次にDataクラスでは、以下のような部分を作成することで、Serializeクラスの情報をDataクラスから取得できるようにします。

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

static public class Data
{
    //SerializeDataクラスの情報
    private static SerializeData serializeData;
    //シーン上にあるSerializeDataクラスを取得する。
    public static void OnStart(SerializeData serializedata)
    {
        serializeData = serializedata;
    }
    //ゲッターでSerializeDataクラスの情報を拾う。
    public static GameObject obj
    {
        get { return serializeData.obj; }
    }
}
```
Serializeクラスからデータを取得するために、serializeDataという変数を用意し、OnStart()メソッドでSerializeクラスの情報を設定しています。

呼び出しは先ほど同様、以下のように書くことで、使用できます。

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    void Start()
    {
        //ここで、"Serialize"というTag名のオブジェクトにアタッチされているSerializeDataクラスの情報をDataクラスに渡している。
        Data.OnStart(GameObject.FindGameObjectWithTag("Serialize").GetComponent<SerializeData>());
        //データクラスから呼び出す。
        Debug.Log("obj:" + Data.obj.name);
    }
}
```

##最後に

後半、書いているうちに時間が無くなっちゃって、ババっとまとめちゃったので読みにくいかもしれません！

ごめんなさい！！！

また、時間あるときに、文章は直しておきます！
[AWS_32]AWS CLI インストール~セットアップ

##環境
* Amazon Web Service

    * EC2(Amazon Linux 2 , t2.micro , 汎用SSD 8GB)
    * RDS(MySQL , db.t2.micro)
    * ALB

* ローカルPC
    * MacBook Pro(2.9 GHz デュアルコアIntel Core i5 , 8 GB 2133 MHz LPDDR3)
    * macOS 11.3.1（20E241）

##AWS CLIとは
AWSサービスをコマンドで管理できるツール。
EC2などのリソースを作成・削除、情報表示ができる。



##AWS CLIのセットアップ
###インストール
[AWS CLIインストールページ](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-mac.html)

###確認
```console
$ which aws
/usr/local/bin/aws

$ aws --version
aws-cli/2.2.7 Python/3.8.8 Darwin/20.4.0 exe/x86_64 prompt/off

```

###セットアップ
インストールしただけの状態で、情報表示等何かしらのコマンドを打っても、「リージョンを教えろ。クレデンシャルを教えろ。」と返ってくる。

```console
$ aws ec2 describe-vpcs
You must specify a region. You can also configure your region by running "aws configure".
```

それらを記載したファイルを`aws configure`コマンドで作成する。
(とりあえず作成だけしたいので内容は適当)

```console
$ aws configure
AWS Access Key ID [None]: aaa
AWS Secret Access Key [None]: bbb
Default region name [None]: ap-northeast-1
Default output format [None]: json
 
$ ls -la
(省略)
drwxr-xr-x   4 masudayoshiki  staff    128  5 31 14:23 .aws

$ cd .aws

$ ls -l
total 16
-rw-------  1 masudayoshiki  staff  48  5 31 14:23 config
-rw-------  1 masudayoshiki  staff  62  5 31 14:23 credentials

$ cat config
[default]
region = ap-northeast-1
output = json

$ cat credentials 
[default]
aws_access_key_id = aaa
aws_secret_access_key = bbb
```
Express（Node.js）で最初のページを作る

# はじめに
Node.jsでJavaScript＋HTMLのWebサイトを作成する際に、１から作るよりフレームワークを利用したほうが簡単です。そのフレームワークの一つである[Express](https://expressjs.com/ja/)を利用してWebサイトを作りたいという時があります。
Expressで新しいWebサイトを作る際の最初に実行するコマンドについて、時間が空くと忘れてしまいがちで、毎回調べては不安になるので自分用にメモを残します。
# 環境
OS：Windows10
Vagrant：2.2.7
Ubuntu：18.04.4
Node.js：v10.14.2
Express：4.16.0
Yarn：1.21.1
# 手順
Ubuntu環境上で以下を実行

```
express --view=<使いたいテンプレート> <作成したいプロジェクト名>
```
上記で「作成したいプロジェクト名」フォルダが作成されるため、`cd`で移動。

```
yarn install
```
次に、必要なパッケージをインストール。ここを忘れないように気を付ける。

```
PORT=<ポート番号> yarn start
```
http://localhost:<ポート番号>
にアクセスできればOK。
ポート番号が開いているかどうかはWindowsファイアウォールなどで確認しましょう。
（Windows PCにIISを入れてしまっているため、ただのlocalhostだとそっちが開いてしまう）

# ページを増やす
Webページにページを増やしたい時は以下のようにする。
1. routeフォルダに「<増やしたいページ>.js」を作成。例として`adding.js`とする。中身はデフォルトで作成されている`index.js`を参考にする。`render`で読み込んでいる部分は次に作成するviewファイルの名前にする。
2. viewsフォルダに増やしたいページのviewファイルを作成する。例として`adding.pug`とする。頭に`extends layout`を宣言する。
3. `app.js`ファイル内でRouterを読み込んでいるところを探し、以下のように追記する。

```JavaScript
   var addingRouter = require('./routes/adding');
//・・・（略）・・・
   app.use('/adding', addingRouter);
```

これで`http://localhost:<ポート番号>/adding`
にアクセス可能になる。

# 感想
使いこなせるようになりたい…。
You must use Bundler 2 or greater with this lockfile. (Bundler::LockfileError) というエラーが出た

##エラーの経緯
Rubyをrbenvにて管理しており、バージョン変更していた中でこのエラーに遭遇。

```ターミナル:ターミナル
$ rails s
Traceback (most recent call last):
	5: from bin/rails:3:in `<main>'
	4: from bin/rails:3:in `load'
	3: from /Users/macbook/sample/bin/spring:10:in `<top (required)>'
	2: from /Users/macbook/sample/bin/spring:10:in `new'
	1: from /Users/macbook/.rbenv/versions/2.6.6/lib/ruby/2.6.0/bundler/lockfile_parser.rb:95:in `initialize'
/Users/macbook/.rbenv/versions/2.6.6/lib/ruby/2.6.0/bundler/lockfile_parser.rb:108:in `warn_for_outdated_bundler_version':You must use Bundler 2 or greater with this lockfile. (Bundler::LockfileError)
```

つまりはGemfile.lockとbundlerのバージョンが異なっており、Gemfile.lockに合わせたbundlerを使う必要があるとのこと。

##解決策

```terminal:ターミナル
#Gemfile.lockでの記載を確認
$ tail -n2 Gemfile.lock
BUNDLED WITH
   2.2.3

#現在のバージョンを確認
$ bundler -v
Bundler version *.*.*(異なるバージョン)

#目的のバージョンをインストール
$ gem install bundler:2.2.3

$ rails s
Could not find i18n-1.8.10 in any of the sources
Run `bundle install` to install missing gems.

#不足しているgemをインストール
$ bundle install

#目的のバージョンがインストールされたことを確認
$ bundler -v
Bundler version 2.2.3

$rails s
```

無事起動を確認〜
Linux Mint で Wi-Fi 接続する（MacBook Pro）

# はじめに
古い**MacBookPro(Mid 2012)**に**LinuxMint**を入れたのですが、**Wi-Fi**が繋がりませんでした。

# 結論
以下で**ドライバをインストールして再起動**すればWi-Fiデバイスを認識して繋がりました。

```shell
sudo apt install broadcom-sta-dkms
```

# 環境
Linux Mint 20.1
MacBook Pro (Mid 2012)
BCM4331


# 状況
まず、`iwconfig`で状況を確認しました。`enp1s0f0`は有線LANなので、**無線LANデバイスは認識されていない**です。

```shell
$ iwconfig 
enp1s0f0  no wireless extensions.

lo        no wireless extensions.
```

次に、`lspci`でデバイスを確認してみました。`BCM4331`が無線LANデバイスのようです。

```shell
$ lspci
（略）
02:00.0 Network controller: Broadcom Inc. and subsidiaries BCM4331 802.11a/b/g/n (rev 02)
（略）
```

[調べてみると](https://wiki.archlinux.jp/index.php/Broadcom_%E3%83%AF%E3%82%A4%E3%83%A4%E3%83%AC%E3%82%B9)、**Broadcomのドライバ**が必要なようです。以下でインストールして再起動しました。

```shell
$ sudo apt install broadcom-sta-dkms
$ sudo reboot
```

もう一度`iwconfig`で確認してみると、`wlp2s0`が**認識されている**ことが確認できます。

```shell
$ iwconfig
wlp2s0    IEEE 802.11  ESSID:off/any  
          Mode:Managed  Access Point: Not-Associated   Tx-Power=200 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:off
          
enp1s0f0  no wireless extensions.

lo        no wireless extensions.
```


# 参考文献
[19.2 “Tina” Cinnamon Wi-Fi Broadcom BCM4331 MacBook](https://forums.linuxmint.com/viewtopic.php?t=301641)
gulpを使わずbrowserifyでsource mapsを作ってみた

 gulpを使わずに何とかbrowserifyのコマンドだけでできないか調べてみた。

browserifyのgitページに以下の記載があったため試してみた。

https://github.com/browserify/browserify#external-source-maps

    $ browserify main.js --debug | exorcist bundle.js.map > bundle.js

実行してみたら怒られた。

exorcistがなかったらしい。
仕方ないので、npmでexorcistもインストールして再実行すると
bundle.js.mapがちゃんとできてて、
google chormeでも開発モードでソースが見やすくなってることを確認できた。
Couchbase 通信暗号化 Encryption on the Wire 解説（ノード間暗号化とTLS暗号化スイーツ設定）


# はじめに

本稿では、Couchbase Serverにおける暗号化というテーマの中で、ノード間暗号化と、そこで用いられる暗号化設定について、具体的な設定（操作）方法を中心に整理します。

# 暗号化設定
## 暗号化スイート

### 設定追加

```
$ couchbase-cli setting-security -c localhost:8091 -u <user> -p <pwd> \
--set \
--tls-min-version tlsv1.2
```

```
$ couchbase-cli setting-security -c localhost:8091 -u <user> -p <pwd> --gset \
--set --cipher-suites \
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
```

### ステータス取得
```
$ couchbase-cli setting-security -c localhost:8091 -u <user> -p <pwd> \
--get
```

## ノード間暗号化

TLSによるノード間暗号化設定が可能です。

## 暗号化レベルオプション
– `Control`:  ノード間の制御メッセージのみを暗号化(デフォルト) 
– `All`: ノード間の制御メッセージとデータ転送を暗号化


### 暗号化レベル有効化（デフォルト`Control`レベル)
```
$ couchbase-cli node-to-node-encryption -c localhost:8091 -u <user> -p <pwd> \
--enable
```


### 暗号化レベル`All`設定
```
$ couchbase-cli node-to-node-encryption -c localhost:8091 -u <user> -p <pwd> --set \
--cluster-encryption-level all
```

### ステータス取得
```
$ couchbase-cli node-to-node-encryption -c localhost:8091 -u <user> -p <pwd> \
--get
```

### 自動フェールオーバーの無効化と有効化
暗号化設定を変更する際に、自動フェールオーバーを無効化する必要があります。

#### 無効化
```
$ couchbase-cli setting-autofailover -c localhost:8091 -u <user> -p <pwd> \
--enable-auto-failover 1 \
--auto-failover-timeout 120 \
--enable-auto-failover 0
```
#### 有効化

```
$ couchbase-cli setting-autofailover -c localhost:8091 -u <user> -p <pwd> \
--enable-auto-failover 1 \
--auto-failover-timeout 120 \
--enable-failover-of-server-groups 1 \
--max-failovers 2 \
--can-abort-rebalance 1
```
（上記例では、フェールオーバー有効化時に、必要な項目を設定する際に、グループフェールオーバーも有効化しています。）

# フィールドレベル暗号化（クライアントレベル）

クライアントが、Keystoreからキーをフェッチすることによって、暗号化と複合化を実施します。
サーバーは、暗号化についての情報を持ちません。

このフィールドレベル暗号化は、FIPS140-2規格（暗号化ハードウェアの有効性を検証するための米国連邦情報処理規格のベンチマーク）コンプライアンスに従うことを意図されています。

## サポートアルゴリズム

- RSA-2048
- AES-256

## プラットフォームサポート
- JAVA: Java Key Store (JCEKS)
- .NET: Windows Certificate Store
- サードパーティー実装： Hashicorp Vault (JAVAでのサポート)  

# 参考情報

[Encryption](https://docs.couchbase.com/server/current/learn/security/encryption-overview.html)

[Node-to-Node Encryption](https://docs.couchbase.com/server/current/learn/clusters-and-availability/node-to-node-encryption.html)
WindowsでDjangoを立ち上げたら Unable to configure handler 'watchtower'になった


# watchtowerでエラーになっているではありませんか
```
Traceback (most recent call last):
  File "C:\Users\A\.pyenv\pyenv-win\versions\3.8.2\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Users\A\.pyenv\pyenv-win\versions\3.8.2\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "c:\web-test\env\lib\site-packages\django\utils\autoreload.py", line 54, in wrapper
    fn(*args, **kwargs)
  File "c:\web-test\env\lib\site-packages\django\core\management\commands\runserver.py", line 109, in inner_run
    autoreload.raise_last_exception()
  File "c:\web-test\env\lib\site-packages\django\utils\autoreload.py", line 77, in raise_last_exception
    raise _exception[1]
  File "c:\web-test\env\lib\site-packages\django\__init__.py", line 19, in setup
    configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
  File "c:\web-test\env\lib\site-packages\django\utils\log.py", line 76, in configure_logging
    logging_config_func(logging_settings)
  File "C:\Users\A\.pyenv\pyenv-win\versions\3.8.2\lib\logging\config.py", line 808, in dictConfig
    dictConfigClass(config).configure()
  File "C:\Users\A\.pyenv\pyenv-win\versions\3.8.2\lib\logging\config.py", line 570, in configure
    raise ValueError('Unable to configure handler '
ValueError: Unable to configure handler 'watchtower'
```

よくよく見ると、エラー内容を辿っていくとこのようなエラーになっています。

```
botocore.exceptions.ClientError: An error occurred (InvalidSignatureException) when calling the CreateLogGroup operation: Signature not yet current: 20210531T060458Z is still later than 20210531T044007Z (20210531T043507Z + 5 min.)

The above exception was the direct cause of the following exception:
```

`Signature not yet current ` のエラーだった場合、PC時刻が現在時刻とズレておきる現象でした。（本当だったらPCは時刻同期しているのでズレることはないのですが、何故かずれてました。:sweat_smile:)

PCの時刻を再同期させたら、無事Djangoが立ち上がることができました.:smile:
可視化ライブラリでよく使われる依存パッケージをみてみた

# 概要
 可視化ライブラリを自作するために使えるライブラリがないか、有名なオープンソースのpackage.jsonを確認してみました。

今回の集計対象にしたのは以下の12のライブラリになります。　選択基準は[npm trend（https://www.npmtrends.com/d3 ）　にて関連づけられたライブラリ] + [個人的に興味のあるライブラリ] です。

- Chart.js
- c3
- d3
- dagre-d3
- echarts
- google-chart
- highcharts
- mermaid
- nvd3
- recharts
- victory
- vis-network


# 結果
![スクリーンショット 2021-05-31 13.35.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/990981/c496ec48-e3eb-e5a8-712c-1f18d3b31c2c.png)

このような結果となりました。 typescript強いですね
また、テスト周りではkarmaが一強に見えます。　今回の選択結果の中だと、d3という可視化ライブラリがよく使われています。(全結果を見たい方は参考へ)

備考: git clone後のbranchの指定はしていません。
備考: package.jsonの取得方法は、git clone後のディレクトリ配下を探索し、"package.json"に複数ヒットしたらすべて集計対象に含めています。
備考: 依存モジュールについて、["depend"という文字列]と[package.jsonのkeyを小文字にした文字列]が部分一致したものを集計対象としました。

# 参考
- 30位より後の結果をwebにupしました：https://centraengine.work/knowledge/dependent_module_ranking_used_in_visualization_libraries#result
開けない.ipynbファイルの出力を外部から消す方法

# 背景
jupyter notebookで、行数が多いデータをうかつにprintしたりしてsaveし次回開こうとすると、開くのにかなり時間かかったり最悪開けないみたいなことが結構あります。（僕はよくあります）
そういう時に開けないと困るので、printした出力を外部から全て消すことで復旧しようという解決法です。

# やり方
1. まずnbcleanをpip installします
1. 以下のコードを打ちます。

```shell
pip install nbclean
```

```py
import nbclean

input_filename = "./hoge.ipynb"
output_filename = "./hoge_out.ipynb"

c = nbclean.clean.NotebookCleaner(input_filename))
# 削除する対象を選択
# ['content', 'output', 'output_text', 'output_image', 'stderr']
c.clear("output")
c.save(output_filename)
```

注意点としては、選択する対象で、contentを選ばないようにすることです。（全部消えます）
基本は"output"、もしくは"output_text"で大丈夫だと思います。
CentOS7でbashのプロンプト設定

ログインして作業しているサーバを取り違えないよう、bashプロンプトで視覚的にすぐ判別しやすい情報を表示したい。
プロンプトでは表示する文字だけでなく色付けやフォント体裁も調整が可能。
具体的には$PS1という環境変数に設定値は登録されている。

```
[prompt] echo $PS1

[\u@\h \W]\$
```
この設定値はbash設定ファイルbashrcで管理できる。
ユーザーごとのbasshrcもあるが、おおもとの「/etc/bashrc」で設定シテおくとよい。

```shell:/etc/bashrc
export PS1="値"
```

ちなみに色付け・フォント体裁は以下のような記法で指定する。

```shell
[\e[1;33m\]テキスト \[\e[m\]
```
この指定ではテキスト部が黄色の太字となる。
「1」は太字指定を意味し、標準は0になる。
「33」は黄色を示す。
その他の色は以下の通り。

| Color | code |
|:-:|:-:|
| 黒  | 30 |
| 赤  | 31 |
| 緑  | 32  |
| 黄  | 33  |
| 青  | 34  |
| 紫  | 35  |
| 水色  | 36  |
| 白  | 37  |
Xcode 12.5でiOS 12以前のシミュレータで実行しようとすると（Realmが起因で）クラッシュする問題

# 検証環境

- Xcode 12.5
- Realm 10.7.6
- iOS 12.4 simulator
- CocoaPods 1.10.1

# 事象

上記の環境でアプリを実行しようとするとクラッシュしました。

コンソールには以下のようなエラーが出力されました。

```
dyld: Library not loaded: /System/Library/Frameworks/SwiftUI.framework/SwiftUI
  Referenced from: /.../myApp.app/Frameworks/RealmSwift.framework/RealmSwift
  Reason: image not found
```

どうやら、Xcode 12.5 + Realmの新しめのバージョン + CocoaPods利用の条件で発生するようです。

# 当面の回避策

Podfileの定義を以下のようにします。

```
post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == 'RealmSwift'
      target.build_configurations.each do |config|
        config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -weak_framework SwiftUI'
      end
    end

  end
end
```

Realmのissueが上がっていて、とりあえずの回避策として上記が紹介されていました。
https://github.com/realm/realm-cocoa/issues/7234

# 補足情報（2021-05-31現在）

Realmのプルリクが上がっているようです。近々対応されそうです。
https://github.com/realm/realm-cocoa/pull/7268
URI/URL/URN/ドメインの違い

## 概要

ネットワークについて勉強中。

`curl`コマンドについて勉強しようと思ったら、そもそもネットワークについてちゃんと理解していないなと思って勉強しなおしています。

今回はその中でも、 URI/URL/URN/ドメインってどれも同じだと思っていたら、それぞれちゃんと違いがあったのでメモです。

## URI/URL/URN/ドメインとは

Chromeに入れそうな、下記の例をとって説明。

先に言っておくと、これはURIにあたる。

`http://www.example.com.index?key1=value1&key2=value2#header1`

#### プロトコル

- `http`: プロトコル。サーバーのポート番号が決められている。

  - `http` = 80
  - `https` = 443
  - `src` = Chromeでソースが見れる。といったブラウザごとの隠し機能的なのもあるらしい。

#### ドメイン: サーバーへのアクセス。インターネット上のネットワークの名前・住所。

- `www`: サブドメイン。
- `example`: ネイキッドドメイン 
- `com`: ドメイン
- `www.example.com`: ホスト。FQDN。絶対ドメイン名。完全修飾ドメイン名。(Fullpy Qualified Domain Name)
- `example.com`:　これをドメイン名と呼ぶこともある。

#### ページ内の情報

- `index`: パス名。ファイル。 他に`html`や`php`や`src`が指定されたり、ファイルのパスが指定する。
- `?`以降のKeyとValue: 引数、パラメーター、クエリ
- `#`以降: ハッシュネーム値

### URI/URL/URNの違い

- URI = Uniform Resource Identifier: ハッシュネームまですべてを含む。URLはそもそも、IPアドレスを人間の目から見てもわかりやすいようにしたもの。
(`http://www.example.com/index?key1=value1&key2=value2#header1`)
- URL = 　Uniform Resource Locator: パス名まで。(`http://www.example.com.index`)
- URN = Uniform Resource Name: プロトコルを含まないパス名まで。　　(`www.example.com.index`)

## 参考
- https://jp.globalsign.com/support/faq/345.html
- https://mynt.work/9chat-e/
- https://livra.geolocation.co.jp/iplearning/250/
- https://ferret-plus.com/8736
点と線分の最近傍点と距離の計算

# 概要

点と線分の距離を求める方法。
2Dグラフィックスを扱うGUIを作成する際腐るほど使うわりに毎回忘れるのでメモしておく。
(線をクリックした場所に何かしたいときとか)

## 問題

ベクトル表記に関して: 点$V_0$を原点として点$V_1$を示すようなベクトルを$V_0 V_1$と表現し、その値は$V_1 - V_0$で計算する。

以下に示す図のように線分$AB$と点$P$が存在する状況で線分$AB$と点$P$の最短距離と最近傍点を計算する。

![point_line_segment.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356046/4f81b2fd-7031-895d-b4d6-4eee0bf5b79b.png)


## 手順

### 1. 点と線分がどの位置関係にあるかを計算する。

まずベクトルの内積$AP\cdot AB < 0$ならばパターン①である。
そうでない場合、$BP \cdot BA < 0$ならばパターン②である。
上記2つに該当しない場合パターン③となる。

### 2. 各パターンそれぞれで計算方法が異なる。

#### 2.1 パターン①の場合

最短距離: $||PA||$
最近傍点: $A$

#### 2.2 パターン②の場合

最短距離: $||PB||$
最近傍点: $B$

#### 2.3 パターン③の場合

内積を使って$||AI||$を求めた後に点$A$を基準にしてベクトル$||AI||$を加算することで求めることができる。

$\alpha$を線分$AP$と$AB$が織りなす角度とする。

```math
||AI|| = ||AP||\cos\alpha \qquad \qquad \qquad (1) \\
AP\cdot AB = ||AP||\cdot ||AB|| \cos\alpha \qquad (2)
```
(1)と(2)より

```math
AP\cdot AB = ||AB||\cdot ||AI|| \\
||AI|| = \frac{AP\cdot AB}{||AB||}
```

最近傍点は$$A + \frac{AB}{||AB||} \cdot ||AI||$$

距離は$||P - AI||$となる。

## サンプルコード (Python)

```python
import numpy as np
from numpy.linalg import norm

# a, b, pはそれぞれshape=(2,)のndarrayであると想定する
def calc_distance_and_neighbor_point(a, b, p):
    ap = p - a
    ab = b - a
    ba = a - b
    bp = p - b
    if np.dot(ap, ab) < 0:
        distance = norm(ap)
        neighbor_point = a
    elif np.dot(bp, ba) < 0:
        distance = norm(p - b)
        neighbor_point = b
    else:
        ai_norm = np.dot(ap, ab)/norm(ab)
        neighbor_point = a + (ab)/norm(ab)*ai_norm
        distance = norm(p - neighbor_point)
    return (neighbor_point, distance)
```