OmniAICreator/Qiita-1.07M huggingface dataset:
【React】Error: App(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.の対処法

<h2>症状</h2>
ReactでReact-Router-Domを実行しようとしていた時に、下記エラーが発生しました。
コンソールにはエラーメッセージが表示されていませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927880/c83489f7-d877-7597-6f2d-1fb09b50f198.png)

翻訳すると、
「エラー：App（...）：レンダリングから何も返されませんでした。これは通常、returnステートメントが欠落していることを意味します。または、何もレンダリングしない場合は、nullを返します。」でした。

つまり、APP.jsから何も返ってきていないといわれているとのこと。

該当のAPP.jsはこのようになっていました。(SampleA.jsxに関しては今回関係なかったので割愛)

```react:App.js
import React from 'react';
import {
  BrowserRouter as Router,
  Switch,
  Route,
} from "react-router-dom";

import {SampleA} from './containers/SampleA.jsx'
import {SampleB} from './containers/SampleB.jsx'
import {SampleC} from './containers/SampleC.jsx'

function App() {
　<Router>
   <Switch>
    <Route 
          exact
          path="/sampleA">
    <SampleA />
    </Route>
    <Route 
          exact
          path="/sampleB">
    <SampleB />
    </Route>
    <Route 
          exact
          path="/sampleC">
    <SampleC />
    </Route>
　 </Switch>
 </Router>
}
export default App;
```

<h2>解決策</h2>
APP.jsにreturnの記載がなかったため、APP.jsからのreturnがないと怒られていたようです。
APP.jsにreturnを追加したら、正常に動作するようになりました。

```react:App.js
import React from 'react';
import {
  BrowserRouter as Router,
  Switch,
  Route,
} from "react-router-dom";

import {SampleA} from './containers/SampleA.jsx'
import {SampleB} from './containers/SampleB.jsx'
import {SampleC} from './containers/SampleC.jsx'

function App() {
  return (
　<Router>
   <Switch>
    <Route 
          exact
          path="/sampleA">
    <SampleA />
    </Route>
    <Route 
          exact
          path="/sampleB">
    <SampleB />
    </Route>
    <Route 
          exact
          path="/sampleC">
    <SampleC />
    </Route>
　 </Switch>
 </Router>
  )
}
export default App;
```
<h2>参考</h2>
コンポーネントから返り値が返ってこない
https://teratail.com/questions/313829
Azure の権限周りについてそこそこ理解したのでまとめ

## 概要
クラウドIaaS いろいろ使うと思いますが、
Azureを最近使っており、権限や各サービスの階層構造的なところが今までなあなあにしていたので、
いくつか細かな問題を抱えていました。

一度時間はかかりましたが、ゆっくり１からサービスの勉強をしてみたところ、
以前よりも理解が進んだので、ここにまとめとして残しておこうと思います。


## 重要なこと
これだけは抑えましょう。
というより、ここを抑えておけばそこまでやらかさないと思います。

- Azure Active Directory
- Global Administrator
- ユーザ
- サブスクリプション
- リソースグループ
- ロール

一つ一つ簡単ではありますが知っておかなければならないことをまとめます。


## Azure Active Directory　(AD)

「テナント」とも呼ばれます。
会社や、組織レベルの上位概念と覚えてください。

したがって、基本的にADは会社や組織単位で一つだけ作られているべきです。
ADには、ドメインが付与されます。たとえば、hogehogeという組織であれば、

`hogehoge.onmicrosoft.com`
のようなドメインを付与し、組織などを区別できます。

**！！！注意！！！！**
このドメインは後で変更することができません。
例えば、`hogehoge.onmicrosoft.com` から `mogemoge.onmicrosoft.com`
への変更などはサポートなどにお願いすることはできません。
ネーミングには注意しましょう。

（筆者はいつも test とか、tmp とかとりあえず名前決めするときに入れてしまう癖があり、
あとで名前変更をしようとした時にやらかしたことに気づきました。。）


## Global Administrator　(GA)
AD を管理する最強権限の持ち主です。

主にできること
- ユーザの登録、削除など
- ユーザへのロールの設定、削除など
- あとなんでも

ちなみに、デフォルトのGAアカウントは、ADを作った時にログインしていたアカウントになります。
GAはGAを生成できます。
つまり最強権限をもつGAは、他のユーザにも最強権限のGAを付与できます。（削除もできます。）

**！！！重要！！！**




アカウントは　`taro@hogehoge.onmicrosoft.com`などになっている必要はありません。
`taro@gmail.com`とかになっていても問題ありません。
もしそのような場合の時、
Active Directory --> Users と飛ぶと、、
`taro@gmail.com#Ext#@hogehoge.onmicrosoft.com`
とアカウント名のところに書かれているのが確認できると思います。




## ユーザ

**！！！重要な質問！！！**
ユーザはどこに所属するでしょう？？
ーーーー＞　答え　ーーー＞　ADです。

したがって、ユーザアカウントは、たとえば

`taro@hogehoge.onmicrosoft.com`
などになります。
組織に紐ついたユーザと考えればあたりまえですが。。

これらのユーザは、GAによって好きに生成、削除ができます。
また、ユーザにはユーザとゲストの２種類があり、
ユーザはかならずADに所属します。つまり、`hanako@hogehoge.onmicrosoft.com`のようにドメインは固定です。
一方で、ゲストは`hanako@gmai.com`などの人にも発行でき、その場合、
アカウント名のところには
`hanako@gmail.com#Ext#@hogehoge.onmicrosoft.com`
のように表記されています。


## サブスクリプション

ADが持つ課金アカウント、がサブスクリプションになります。このサブスクリプションに対し、月額の従量課金が行われます。
ADは複数のサブスクリプションを持つことも可能です。

**！！！重要！！！**

- サブスクリプションを持つADのGAは、必ずしもサブスクリプションのadmin accountであるとは限りません。
- Microsoft for Start Program にてサブスクリプションを付与されている場合、サブスクリプションのadmin account のみが課金情報の詳細を見ることができます。（したがって、GAであっても詳細を確認できない。）


## リソースグループ
リソースグループは、ADに紐つけられる、各サービス（VMや、DMなどのリソース）をまとめたものです。
ADを会社組織と考えると、リソースグループは部署や部門、実際のリソース（たとえばVM）は、その部署が管理する所有物、であると考えるとわかりやすいかと思います。

## ロール

ロールは、ユーザに対しての実行権限を管理する時に用いるものです。

**！！！注意！！！**
ロールは、

- ADに付与するロール
- リソースグループに付与するロール

があります。
先述の通り、リソースグループはADにぶら下がっているので、
もしADの`Contributor`というロールを太郎さんに付与した場合、
太郎さんは基本的に全てのリソースグループに対して`Contributor`のロールを行使できます。

したがって、基本的にはリソースグループ単位でロールを発行し、
各ユーザがアクセスできるリソースグループを制限しておくべきだと考えます。

これは、ADが会社であり、リソースグループが各部署とか部門であるとすると、
このようによほどの重要人物でない限り、全部署のリソースにアクセスできるようなAD単位のロールは割り当てる必要がないことがわかると思います。


## まとめ

Azureを使う上で、とても基本的なことをまとめました。
おさらいすると、

- Azure Active Directory (AD) は１組織を表す。
- Global Administrator (GA) は、ADの最強権限を持つ。
- ユーザはADに所属する。
- サブスクリプションはADに所属し、各サブスクリプションで月額従量課金が行われる。
- リソースグループは会社の部署のようなもの。
- ロールは、ユーザがどのリソースグループにどの役割でアクセスできるかをとりきめるアクセス制御。


## 最後に
今のところ、ADのドメインを後に変更できない、というところ以外はGAであれば基本的に設定し直すことができるのかなあと思っています。
もしドメインを変更したい場合などは、会社で例えると

- 新しい会社（AD）を作る
- 紐ついていたユーザ、サブスクリプションを全て新しいADに移行する


ことが必要(移行自体は可能）なので、それがなかなか大変だなと思いました。。


## おまけ

サブスクリプションのadmin account の変更はサポートに言えばやってくれる。
サブスクリプションのadmin account は一つでなければならないのかーー＞たぶんyes。
C#でスクレイピングしてみた


#お題目

これまでVBAでスクレイピングしていたが、ただいま勉強しているC#でもスクレイピングできるということで、サクッとやってみた。
その備忘録になります。



####0. まずディレクトリ作成

```terminal
mkdir testScraping
cd testScraping
```


####1. 次にプロジェクトを作成、AngleSharpのNugetをセッティング

```terminal
dotnet new console
dotnet add package AngleSharp --version 1.0.0-alpha-827
```

####2. 次に言語のバージョンをプレビューを追記
(正直、理由は分かってません、涙)
この行追加、の1行を追記してください

``` html:testScraping.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <LangVersion>preview</LangVersion> <!-- この行追加 -->
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="AngleSharp" Version="1.0.0-alpha-827" />
  </ItemGroup>

</Project>
```


####3. ソースコード記入
次はもう下記のソースコードをProgram.csにまるまるコピペで大丈夫です

```csharp:Program.cs
using System;
using AngleSharp;
using AngleSharp.Html.Parser;
using System.Net;
using System.Threading.Tasks;

// 参照サイト
// https://qiita.com/okazuki/items/a4eb94f608bbc26c6a5f
// https://usefuledge.com/csharp-webscraping-anglesharp.html

var urlstring = "https://www.yahoo.co.jp/";

WebClient wc = new WebClient();
try
{
    string htmldocs = wc.DownloadString(urlstring);
    // Console.WriteLine(htmldocs);

    var config = Configuration.Default;
    var context = BrowsingContext.New(config);
    var document = await context.OpenAsync(req => req.Content(htmldocs));

    // Console.WriteLine(document.Title);

    // foreach (var item in document.QuerySelectorAll("h1.thumb"))
    foreach (var item in document.QuerySelectorAll("section#tabpanelTopics1 li"))
    {
        Console.WriteLine(item.TextContent.Trim());
    }

}
catch (System.Exception)
{
    throw;
}

```

####4. 結果
そのスクレイピングの結果が![スクリーンショット 2021-04-26 15.38.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/799ada7a-bd0a-9ab2-8977-eec94d8249c7.png)

現時点のYahooが![スクリーンショット 2021-04-26 15.40.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/11b8b291-5a00-ccc3-a64d-76145fec115a.png)
です。

簡単ですね。

タグを構造的に指定したい場合は半角スペースで仕切れば大丈夫みたいです。**document.QuerySelectorAll("section#tabpanelTopics1 li")**
がそうですね。

もう少し複雑なスクレイピングにもトライしたいと思います。

〜おわり〜
【C#】文字列の全角文字を半角文字に変換

# ソースコード

```C#:FullWidthToHalfWidthConverter.cs
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class FullWidthToHalfWidthConverter
{
    private Encoding encoding = Encoding.GetEncoding("Shift_JIS");

    private Dictionary<char, char> FullWidthToHalfWidthDictionary = new Dictionary<char, char>
    {
        { 'ー','-'},
        { '「','['},
        { '」',']'},
        { '、',','},
        { '。','.'},
        { '・','/'},
    };

    private const int FullWidthHalfWidthDifference = 65248;
    private const int StartFullWidthCharSetByte = 65281;
    private const int EndFullWidthCharSetByte = 65374;

    public string Convert(string text)
    {
        string output = "";
        foreach (int c in text)
        {
            if (StartFullWidthCharSetByte <= c && c <= EndFullWidthCharSetByte)
            {
                output += (char)(c - FullWidthHalfWidthDifference );
                continue;
            }

            if (FullWidthToHalfWidthDictionary.Keys.Any(k => (int)k == c))
            {
                output += FullWidthToHalfWidthDictionary[(char)c];
                continue;
            }

            output += (char)c;
        }

        return output;
    }

    public bool IsHalfWidth(string text)
    {
        return text.Length == encoding.GetByteCount(text);
    }
}
```

# 説明
半角英数字は文字コードの差を使用して変換、キーボードの日本語記号はDictionaryで変換しています。
【Rails6】"A server is already running."　　


#開発環境
Rails 6.1.1
Ruby 2.7.2
mac 0S Big Sur 11.2.3



#rails serverが立ち上がらない

以下のエラーが発生しました。 

```ruby:ターミナル
 $ rails s
=> Booting Puma
=> Rails 6.1.1 application starting in development
=> Run `rails server --help` for more startup options
A server is already running. Check /Users/*****/Rails/******/tmp/pids/server.pid.
Exiting
```

#発生原因

「すでにRailsサーバーを起動しているor前回のプロセスを正確に終了できていないよ」
とのことでしょうか？
以下のコマンドで確認します。

```ruby:ターミナル
$ ps -a | grep rails
```

`ps -a`＝ 現在実行中のプロセス番号（PID）を表示する。
`grep rails`＝ 指定された入力（rails)から、指定したパターンにマッチする文字列を検索

```ruby:ターミナル
＄ ps -a | grep rails
48976 ttys002    0:00.00 grep --color=auto rails
```
プロセス番号（PID）48976が起動中のようです。


#killコマンドで対処
ターミナルの再起動で解決する場合もあるようですが、今回はkillコマンドで対処します。
killコマンド（物騒..）は実行しているプロセスを終了させることができるコマンドです。
こちらのコマンドで先程の`プロセス番号（PID）48976`に対して、
`-9（デフォルトよりも強制的に修正するシグナルID）`をつけて強制終了させてみます。

```ruby:ターミナル
$ kill -9 プロセス番号（PID）48976
```
するとrails serverが立ち上がるようになりました。

#その他
 エラーログに`port 3000 (Errno::EADDRINUSE)`と記載されている場合は以下が有効です。

```ruby:ターミナル
$ kill -9 $(lsof -i tcp:3000 -t)
```

参考
https://eng-entrance.com/linux-command-kill
【MRTK】NonNativeKeyboard の使い方

# 環境
+ HoloLens2
+ Windows 10 pc
+ Unity 2019.4.1f1
+ Mixed Reality Toolkit ver2.5.3

# NonNativeKeyboard を使う上での注意点
日本語入力はできません。
InputFieldを使用すると標準のキーボードと二重に表示されてしまうのでInputFieldっぽいものを自作する必要があります。

# ソースコード
``` C#:NonNativeInputField.cs
using Microsoft.MixedReality.Toolkit.Experimental.UI;
using System;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class NonNativeInputField : MonoBehaviour, IPointerDownHandler
{
    [SerializeField] private TextMeshProUGUI Text = null;
    [SerializeField] private NonNativeKeyboard keyboard = null;

    private void Awake()
    {
        if (keyboard == null)
        {
            keyboard = GameObject.FindWithTag("NonNativeKeyboard").GetComponent<NonNativeKeyboard>();
        }
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        keyboard.PresentKeyboard(Text.text);
        for (int i = 0; i < Text.text.Length; i++)
        {
            keyboard.MoveCaretRight();
        }
        keyboard.OnClosed += DisableKeyboard;
        keyboard.OnTextSubmitted += DisableKeyboard;
        keyboard.OnTextUpdated += UpdateText;
    }

    private void UpdateText(string text)
    {
        Text.text = text;
    }

    private void DisableKeyboard(object sender, EventArgs e)
    {
        keyboard.OnTextUpdated -= UpdateText;
        keyboard.OnClosed -= DisableKeyboard;
        keyboard.OnTextSubmitted -= DisableKeyboard;
        keyboard.Close();
    }
}
```

# 使い方
1. Hierarchy に NonNativekeyboard を追加する。  
(project > Mixed Reality Toolkit Foundation > SDK > Experimental > NonNativeKeyboard >  prefabs)
1. NonNativeKeyboard に "NonNativeKeyboard" タグをつける。

1. NonNativeKeyboard子要素の InputField の Interactable をオフにする。
(Hierarchy > NonNativeKeyboard > keyboard_Background > search > InputField)

1. InputField の Disabled Color を 255,255,255,255 に設定

1. Hierarchy に UI > image を追加する。

1. Source Image を InputFieldBackground に設定

1. Imageの子要素として UI >Text-TextMeshPro を追加する。

1. Image に上のスクリプト(NanNativeInputField)をアタッチ。

1. Inspector から Text 及び NoNnativeKeyboard プロパティを設定。

# 説明
ポインターで操作できるように IPointerDownHandler インターフェイスを実装しています。

各種イベント
keyboard.OnClosed 閉じるボタンを押したときに呼び出される。
keyboard.OnTextSubmitted Enterey を押したときに呼び出される。
keyboard.OnTextUpdated テキストが更新されたときに呼び出される。

公式ドキュメント : [NonNativeKeybaord](https://docs.microsoft.com/en-us/dotnet/api/microsoft.mixedreality.toolkit.experimental.ui.nonnativekeyboard?view=mixed-reality-toolkit-unity-2020-dotnet-2.6.0)
NuxtをアップデートするとForkTsCheckerWebpackPluginがエラーを出す件

## dev起動時にエラー
以前つくったNuxtプロジェクトのライブラリを更新したところ、
devでの起動時に、`ForkTsCheckerWebpackPlugin`のエラーで止まってしまった。

```
Invalid configuration object. ForkTsCheckerWebpackPlugin has been initialized using a configuration object that does not match the API schema.
 - configuration.eslint should be an object:
   object { files, enabled?, memoryLimit?, options?, … }

  - configuration.eslint should be an object:
  object { files, enabled?, memoryLimit?, options?, … }
  at Object.validate [as default] (node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils/dist/validate.js:96:11)
  at new ForkTsCheckerWebpackPlugin (node_modules/fork-ts-checker-webpack-plugin/lib/ForkTsCheckerWebpackPlugin.js:31:31)
  at WebpackBundler.<anonymous> (node_modules/@nuxt/typescript-build/dist/index.js:41:27)
  at next (node_modules/@nuxt/utils/dist/utils.js:659:27)
...
```

## 原因と解決方法

調べてみると、nuxt.config.jsの中で、typescript部分の記述方法が変わっていたことが原因だった。

### 古い指定
```js
export default {
  typescript: {
    typeCheck: {
      eslint: true
    }
  }
}
```

### 現在の指定
```js
export default {
  typescript: {
    typeCheck: {
      eslint: {
        files: './src/**/*.{ts,js,vue}'
      }
    }
  }
}
```

新しい指定方法に記述を変更すると解決。


## 破壊的な変更はちゃんとチェックしてね
https://github.com/nuxt/typescript/issues/403#issuecomment-655163956

「バージョンアップする時は破壊的な変更をちゃんとチェックしろ」ということだそうです。
そりゃそうなんですけどね。
マニュアルに「ここの指定、前と変わったよ」と一言書いといてくれてもいいのに。
[Mac] Microsoft Exelで1ページに収めたPDFを作成する

MacでOffice 365のExcelを使用しています。

#1ページに収める

Page Layout > Page Setup > Page > ScalingでFit to:を選択

#PDFで印刷
印刷したい範囲を選択してから、Page Layout > Print Area > Set Print Area

#左右対称にする
Page Layout > Page Setup > Margins > Center on page: Horizontallyにチェック
Pythonで天気予報API叩いてみた

#はじめに
住んでいる地域について天気予報を得るために、無料でAPIを提供している
[OpenWeatherMap](https://openweathermap.org/)を使ってみる

#概要
[OpenWeatherMap](https://openweathermap.org/)はGUIで天気予報を取得することができるのですが、今回はAPIを使って天気や気温を取ってきます。
![スクリーンショット (25).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1074988/e6e42594-819b-c7c7-5144-8a57809bdf76.png)

#初期設定
いくつか[プラン](https://openweathermap.org/api)があるので、無料のプランに登録し、APIkeyを手に入れます。無料枠だと5日後までの天気予報を取得出来て、1分間に60回までのAPIコール制限があるみたいです。

#天気予報を取得する
そもそもAPIを試したいなら`curl`を使えば簡単に試すことはできるのですが、今後システムに組み込んでいく予定なのでPythonで実装します。

エンドポイントは`api.openweathermap.org/data/2.5/weather`
パラメータは下記の通り

| パラメーター| 説明 |
|:-:|:-:|
|   q| 都市名  |
|  appid | APIkey  |
|  mode | 応答方式  |
|  units | 測定単位  |
|  lang | 出力言語  |
#都市名を指定してAPIリクエストを送る
```python:apicall.py
import json
import requests

#パラメーター
params={"q":"Kobe","appid":apikey}
    
url="http://api.openweathermap.org/data/2.5/forecast"
res=requests.get(url,params=params)

k=res.json()
jsonText = json.dumps(k["list"][0], indent=4)
print(jsonText)
```

Kobe(神戸)で試してみた結果

```json
{
    "dt": 1619406000,
    "main": {
        "temp": 289.15,
        "feels_like": 287.75,
        "temp_min": 288.84,
        "temp_max": 289.15,
        "pressure": 1020,
        "sea_level": 1020,
        "grnd_level": 1016,
        "humidity": 36,
        "temp_kf": 0.31
    },
    "weather": [
        {
            "id": 801,
            "main": "Clouds",
            "description": "few clouds",
            "icon": "02d"
        }
    ],
    "clouds": {
        "all": 20
    },
    "wind": {
        "speed": 8.04,
        "deg": 3,
        "gust": 9.57
    },
    "visibility": 10000,
    "pop": 0,
    "sys": {
        "pod": "d"
    },
    "dt_txt": "2021-04-26 03:00:00"
}
```
天気予報は取得できたのですが14時に取得したデータが`"dt_txt": "2021-04-26 03:00:00"`なのでリアルタイムの情報ではなく日単位での取得になるっぽいです。まあ無料枠なので当然と言えば当然。一番近い時間帯の情報を取得することで解決。

#天気予報を表示
情報自体は取得できたので気温、湿度、天気、風速、取得日時を抜き出して天気予報っぽく表示します。

```python
#省略
jsonText=res.json()

print("都市：Kobe",end="\n\n")
for i in range(0,5):

    print("気温：",jsonText["list"][i]["main"]["temp"])#気温
    print("湿度：",jsonText["list"][i]["main"]["humidity"])#湿度
    print("天気：",jsonText["list"][i]["weather"][0]["main"])#天気
    print("風速：",jsonText["list"][i]["wind"]["speed"])#風速
    print("取得日時：",jsonText["list"][i]["dt_txt"],end="\n\n")#取得日時
```
結果

```
気温： 289.14
湿度： 27
天気： Clear
風速： 7.34
取得日時： 2021-04-26 06:00:00

気温： 286.29
湿度： 39
天気： Clouds
風速： 6.69
取得日時： 2021-04-26 09:00:00

気温： 283.53
湿度： 50
天気： Clouds
風速： 4.59
取得日時： 2021-04-26 12:00:00

気温： 282.36
湿度： 58
天気： Clouds
風速： 3.12
取得日時： 2021-04-26 15:00:00

気温： 281.99
湿度： 60
天気： Clouds
風速： 2.57
取得日時： 2021-04-26 18:00:00
```
温度表示がケルビンなのと最低間隔が3時間という制限はありますが、工夫次第では十分に使えそうです。表示設定を日本語にしたり、ほかにも取得できる情報はたくさんあるので、詳しい内容は[ドキュメント](https://openweathermap.org/current#parameter)を参照してください。

#さいごに
OpenWeatherMapを使うことで、比較的簡単に情報を取ってくることができました。今後はこれで夕立を通知してくれるBOTを開発したいです。
【Swift】InputAccessoryViewを使う

#はじめに
今回はInputAccessoryViewというものを使って、以下のようなものを作ってみます。

![ezgif.com-gif-maker (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/a5146c64-a120-0771-5127-5ebbc0209419.gif)

#実装
以下のように、textViewとbuttonをおいた`InputAccessoryView.xib`を作ります。
![スクリーンショット 2021-04-26 14.53.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/33dc0d4e-05ed-3e2a-2c0e-0e438c0cb67b.png)

そして`InputAccessoryView.swift`に以下のようにコードを記述します。

```swift
import UIKit

final class InputAccessoryView: UIView {

    @IBOutlet private weak var textView: UITextView!
    @IBOutlet private weak var sendButton: UIButton!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        loadNib()
        setupViews()        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

// MARK: - setup nib
private extension InputAccessoryView {
    func loadNib() {
        let nib = UINib(nibName: String(describing: InputAccessoryView.self), bundle: nil)
        guard let view = nib.instantiate(withOwner: self,
                                         options: nil).first as? UIView else { return }
        view.frame = self.bounds
        self.addSubview(view)
    }
}

// MARK: - setup views
private extension InputAccessoryView {
    func setupViews() {
        textView.layer.cornerRadius = 15
        sendButton.layer.cornerRadius = 15
    }
}
```

次に、xibとswiftファイルを紐付けします。以下のように、File's OwnerのClassを先ほど実装したInputAccessoryViewにします。
![スクリーンショット 2021-04-26 14.57.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/a5876587-ac05-e868-10d8-9e06b8c581f2.png)

ここで、File's Ownerのこちらの画面が黄色くなっている場合はIBOutletを接続し直しましょう。
![スクリーンショット 2021-04-26 14.59.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/f4dc8993-925c-b0d1-fa76-7b02d3fb0f56.png)

そして、最後にViewControllerを以下のように実装してみます。

```swift
import UIKit

final class ViewController: UIViewController {
    
    private var myInputAccessoryView: InputAccessoryView = {
        let view = InputAccessoryView()
        view.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 60)
        return view
    }()
    override var inputAccessoryView: UIView? { myInputAccessoryView }
    override var canBecomeFirstResponder: Bool { true }
    
}
```

これで先ほどのようなキーボードの上にtextViewとbuttonが表示されてくれるはずです。

[ドキュメント](https://developer.apple.com/documentation/uikit/uiresponder/1621119-inputaccessoryview)
[参考](https://qiita.com/nakagawa1017/items/27c02118875150e7fcff)



#おわりに
こんな便利なものがあったとは、、、
Glendale AZ CC Experts

Contact
Address: 
Glendale, AZ 85308
Phone: 
623-239-4526
Website URL: 
http://glendalecarpetcleaningexperts.com/
About US:
Glendale AZ CC Experts professionals is your premier destination for all things carpet cleaning. Our team provides residential and commercial carpet cleaning services in Glendale, Arizona, and the surrounding areas. By using the very latest in carpet cleaning technology, our team will take the best care of your carpeting, rugs, and upholstery to ensure that they look better than ever before. Make no mistake: our carpet cleaning staff with take absolute care of them, to which we guarantee that the fibers of your carpeting or carpet padding will be damaged. In addition, our team also provides water damage restoration services as well, so if you are looking for a carpet cleaning company in Glendale, AZ that simply “does it all,” give us a call today regardless of how big or how small the job at hand may be!
When your home or place of business needs deep cleaning for carpets, rugs, and more, trust the professionals at Glendale AZ CC Experts. Our staff is dedicated to sanitizing the homes and businesses in the area.
We do not have to tell you that your rugs and carpeting deserves our full attention, which is why we apply our professional restoration services for each of our clients. By arranging all of our carpet cleaning services with your schedule, we will be there for you. Add to the fact that we provide very competitive cleaning rates, and you can be assured that our Glendale carpet cleaning experts will always be here for you.
Our team also provides a variety of carpet cleaning services each and every time, no matter what you need. We are proud to provide carpet cleaning, air duct cleaning, water and fire damage restoration, tile and grout cleaning, and of course, upholstery cleaning. Thus, if you are looking for the absolute best carpet cleaning professionals, look no further than our team today!
Related Searches:
Glendale carpet cleaning, carpet cleaning Glendale, carpet cleaning company Glendale, carpet cleaners, carpet cleaner, carpet clean, carpet cleaning service Glendale, clean carpet Glendale, Air Duct cleaning Glendale, Glendale carpet cleaners, Rug cleaning, Upholstery cleaning, Tile cleaning, Glendale AZ.
Additional Details
Hours:
Mon - Sun 8am - 8pm 

cash, check, credit cards, debit card
GMB:
https://goo.gl/maps/RRWmFYKDpzQuwhx58
【javascript】LevelLabelをfor文で

#前置き

FizzBuzz問題の次を考えた！その名も「LevelLabel問題」  - Qiita
https://qiita.com/yamitake@github/items/6a82de2cf235544f2f97

上記記事で提案された新たな問いです。
コメントで良さげな解があるのでいまさらですが。。。
私も微妙なコメントをした記事ですが、改めて考えてみました。

#LevelLabelとは
3つ以上の連番をまとめて文字列で出力。
元記事では「・」と「～」で区切ってますが、この記事では「,」と「-」で区切ります。

```javascript
//こんな配列を
[1,2,3,5,7,9,10,11,20,21]
//こうまとめる
'1-3,5,7,9-11,20,21'
```


#コード

```javascript
const levelLabel = a => {
	const r = [];
	for(let i=0,s=0; i<a.length; s=i){
		//要素の前後を比較して条件が合えば`変数i`を増やして処理対象をワープ
		while (a[i]===a[++i]-1) {}
		r.push(i-s<3 ? a.slice(s,i) : a[s]+'-'+a[i-1]);
	}
	return r.join();
};

const arr = [1,2,3,5,7,9,10,11,20,21];
console.log( levelLabel(arr) );
//1-3,5,7,9-11,20,21
```

コードゴルフには弱い
S3のクロスアカウントレプリケーション設定

## 前提
レプリケーション元のアカウントをA
レプリケーション先のアカウントをB
とする

## 手順
### 1. アカウントBにレプリケーション用のバケットを作成する
* このバケットには「プロパティ」からバージョニングの設定を行う
* また、必ずライフサイクルルールも設定しておく（これやっておかないと無限にバージョンが作られてめっちゃ料金かかります）
* 例えばこんな感じ（最新から3日前までのバージョンは保持する、最新バージョンが3日以上古くなったらストレージクラスをGlacierに移行する）
![スクリーンショット 2021-04-26 14.06.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322555/807f0e9c-276e-3b7d-c91e-178e9a56bbf2.png)

### 2. アカウントAのレプリケーションしたいバケットの「管理」からレプリケーションルールを作成する
1. 「送信先」のアカウントIDにアカウントBのアカウントIDを入れる
1. バケット名には先ほど作成したレプリケーション用のバケット名を入れる
1. 「オブジェクト所有者を送信先バケット所有者に変更」にチェックを入れる
1. IAMロールを作成もしくは選択する
1. そのほかあれば設定し保存する

### 3. アカウントBのレプリケーション用のバケットの「管理」のレプリケーションルールから受信設定を行う
1. レプリケーションルールのアクションから「レプリケートされたオブジェクトの受信」を選択
1. ソースバケットアカウントIDにアカウントAのIDを入れて「ポリシーの作成」をクリック
1. 「ケットポリシーの表示」をクリックして、「オブジェクト所有者を送信先バケット所有者に変更するアクセス許可を含める」にチェックを入れる（忘れがちなので注意）
1. 「設定の適用」をクリックして閉じる

### 4. しばらく待つとレプリケーションされます

## レプリケーションされない場合
* ファイルに更新がないとレプリケーションされないらしいので（もともとあったファイルはレプリケーションされない）、適当なファイルを追加してみてください
* それでもされない場合は、レプリケーションしてほしいファイルのプロパティの「オブジェクト管理の概要」にある「レプリケーションステータス」を確認してください
* ステータスがFAILになってる場合、[こちら](https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-troubleshoot-replication/)を参考にしてみてください

## 参考
https://aws.amazon.com/jp/blogs/news/aggregating-logs-with-s3-same-region-replication/
macOS GnuPG 2.3.1でYubiKeyのOpenPGP鍵へアクセスできなくなったら

## 先に結論

`~/.gnupg/scdaemon.conf`に以下の一文を追加して`gpg-agent`を再起動。

```:~/.gnupg/scdaemon.conf
disable-ccid
```

ただしあくまで暫定対処。

## 状況とその原因

`brew upgrade` を行ったところ、2021-4-23付のGnuPG v2.3.1へのアップグレードが実行された。

> gnupg: update 2.3.1 bottle.
> https://github.com/Homebrew/homebrew-core/commit/553ca25a3098148f32a3b0da68daba7e4d3d69a0#diff-ad8333a9d16df0e9fc911f266f3914e073b6f0f335048ff754d55bbe6479f4bf


以降、YubiKey 5C NFCのOpenPGP Smartcardへのアクセスが不可能となった。

git commitへの署名、sshなど全部不可能。OpenPGP Smartcard ステータスを確認すると

```:zsh
% gpg --card-status
gpg: selecting card failed: Operation not supported by device
gpg: OpenPGP card not available: Operation not supported by device
```

という状態。なお、筆者の環境は以下の通り。

- iMac 27inch 2020

- macOS Big Sur (v11.2.3)

- brew version:

  ```
  % brew --version
  Homebrew 3.1.3-91-gfb7d19c
  Homebrew/homebrew-core (git revision 0941e37d09; last commit 2021-04-26)
  ```

この原因としては、GnuPGのフォーラム([https://dev.gnupg.org/T5409](https://dev.gnupg.org/T5409))で記載されている通り、**GnuPGに内蔵されているCCIDドライバがYubiKeyにアクセスできない**ことだった模様。

## (暫定) 対処法

OpenPGP Smartcardへアクセスできないのは、メッセージによれば「USBデバイス側にパーミッションがないから」である。しかし、**そもそもGnuPG内臓のCCIDドライバ使わなければ問題ないんじゃね？** ということで、Work Around気味ではあるものの、macOS側のPC/SCベースのアクセスに切り替えればちゃんと動作する。これも[GnuPGのフォーラム](https://dev.gnupg.org/T5409)にある通り。

以下の一文を`~/.gnupg/scdaemon.conf`へ追記する。

```:~/.gnupg/scdaemon.conf
disable-ccid
```

あとは`gpg-agent`を再起動しておく。

この設定については、GnuPGの[Scdaemonのマニュアル](https://www.gnupg.org/documentation/manuals/gnupg/Scdaemon-Options.html)に記載通り、内蔵のCCIDドライバからフォールバックするというオプション:

> Disable the integrated support for CCID compliant readers. This allows falling back to one of the other drivers even if the internal CCID driver can handle the reader. Note, that CCID support is only available if libusb was available at build time.

## おわり

GnuPG 2.2.27にロールバックするのも、homebrew経由でインストールしていると面倒なので、このような暫定対処をとることとした。

## 参考

- scdaemon: 'Operation not supported by device' error under macOS after upgrading to 2.3.1: https://dev.gnupg.org/T5409

- GnuPG Manuals Scdaemon options: https://www.gnupg.org/documentation/manuals/gnupg/Scdaemon-Options.html
GREM勉強法

# はじめに
GREM（GIAC Reverse Engineering Malware）は、マルウェア解析の資格です。
この資格について日本語で書かれた記事は少ないので、私が受験した際の勉強法について記載します。

# GREMについて
GREMは75問出題され、制限時間は2時間です。ほとんどの問題は4択です。（一部2択、3択もあります）
合格ラインは70.7%の正答率です。（私が受験した時点の合格ライン）

試験の内容は以下と公式サイトに記載されています。

+ Analysis of Malicious Document Files
+ Analyzing Protected Executables
+ Analyzing Web-Based Malware
+ Common Windows Malware Characteristics in Assembly
+ In-Depth Analysis of Malicious Browser Scripts
+ In-Depth Analysis of Malicious Executables
+ Malware Analysis Using Memory Forensics
+ Malware Code and Behavioral Analysis Fundamentals
+ Windows Assembly Code Concepts for Reverse-Engineering

出題範囲は実行ファイルに関するもの以外にも、悪意のあるJavaScriptやOfficeファイル、PDFファイル、メモリフォレンジックも含まれます。
たとえ業務でマルウェア解析をしていても、準備なしで試験を受けるのは厳しく、現実的にはSANS FOR 610のトレーニングを受講すべきでしょう。私もそうしました。

また、GCFAと同様、紙媒体の資料は持ち込みが可能です。自分なりのメモ、カンニングペーパーを作って持ち込みましょう。

# 事前知識
私はマルウェア解析については多少業務で行ったことがあるとはいえ、アセンブラの読解、マルウェアが実装している耐解析機能、OfficeファイルやPDFファイルのマルウェアなど、SANS FOR 610のトレーニング内容の半分以上は知らない状態からのスタートでした。
一方で、フォレンジックについては長年の経験があるため、メモリフォレンジックの分野についてはすべて既知の内容でした。これは試験において大きなアドバンテージとなったと思います。

# 勉強方法
まず最初にトレーニングの録画ビデオ（オンライントレーニングだったため録画が見られた）をすべて見直し、実際に手を動かして演習を行いました。これが結果的に合格に繋がったと思います。
一通りの録画ビデオを確認し、演習もこなした後、1回目の模擬試験を受験しました。この時点で76%の正答率だったので、手ごたえは十分でした。
誤答が多かった分野を再度復習し、2回目の模擬試験を受験しました。この時点で8割近く正答できていました。
これで十分準備が整ったと判断し、簡単に復習した後、本番の試験に挑みました。
なお、2回目の模擬試験では、1回目と同じ問題が多数出てきてしまいました。問題の母数が多くないのと、テキストの範囲に限定してしまうと、作成できる問題が少ないのだと思います。

# 英語について
GIACの試験はすべて英語で行われ、翻訳ツールは紙の辞書や持ち込んだメモ以外は使うことができません。
英語はGREMにおいては比較的理解しやすかったですが、過去に受験したGCFAはやや難しいと感じました。試験によっては英語が大きなネックになる可能性があります。
短期間で英語力を向上させるのは難しいですが、持ち込んだメモにテキストや模擬試験に出てきた知らない英単語の和訳を書いて持ち込むと良いです。
それから非常に重要な点として、試験問題に回答することが目的であり、和訳が目的ではありません。なんとなく問題や選択肢が理解できたのであれば、それでOKとすべきです。7割くらいの理解度であっても、最も正しいと思われる選択肢を選んで先に進んだほうが良いでしょう。

# 試験を終えて
本番の試験問題について記載することはできませんが、GCFAと同様、模擬試験と似たような問題が出ます。ツールの名前、機能は理解し、カンニングペーパーにも書いておくべきでしょう。ツールの機能については演習をやれば頭に入ると思います。
英語は全体的に難しいとは思いませんでしたが、模擬試験で出てきた英単語は別途メモして和訳表を作っておくと便利です。
それと、実際に手を動かしたからこそ解答できた問題も多々あったので、__演習をやり直すことは非常に重要__だと思います。今後GREMを受検する方には、演習をすべてやり直しておくことを強く推奨します。

また、全体として問題そのものは基本的なレベルが多いと思います。英語なので難しく感じますが、ひっかけ問題だとか、問題文が意味不明ということはありませんでした。トレーニングの内容を理解していれば十分合格できる、合格させるための試験だと思います。

なお、最終的なスコアは82%でした。

# 次の目標
CompTIA CASP+
CISA
CISM
OSCP
あたりを検討中です。
Serverless Frameworkでcorsを有効にした時にハマったこと

## 背景
あるサイトの開発をした際にいくつかのAPIをServerlessFrameworkとAWS Lambdaの組み合わせで作った際にに、バイナリメディアを返すAPIを追加すると今まで動いていたAPI含め動かなくなったのでその時の問題点を記載していく。

## 問題
ServerlessFrameworkでは以下の形で簡単にCORSの対応をすることができる。

```yaml
functions:
  sample:
    handler: handler.sample
    events:
      - http:
          path: sample
          method: get
          cors: true
```

この形でcorsの対応を行うと、ServerlessFramework側でAPI Gatewayのモックサーバ設定を使ってOPTIONSリクエストを処理する部分を自動で作ってくれる。
通常JSONを返すようなAPIであれば特に問題は発生しないが、バイナリメディアを返すようなAPIを絡ませるとOPTIONSリクエストが全て失敗してしまうようになる。

## 原因
バイナリメディアを返すためにはAPI GatewayのBinary Media Typeを設定する必要がある。
今回返したいバイナリメディアはPDFだったため、正常にレスポンスを返すためには「\*/\*」を設定する必要がある。
しかし、これを設定すると全てのメディアタイプをバイナリメディアとして対応しようとしてしまうため、自動的に設定されるモックサーバではバイナリペイロードを処理できずにOPTIONSリクエストで失敗する状態が発生してしまう。

## 解決策
***自前でCORS対応をする。***

この時はServerlessFrameworkでCORSを有効化することを諦めて自前でCORS対応をするようにした。
モックサーバの設定をいじって処理できるようにするとよかったのだが[ドキュメント](https://www.serverless.com/framework/docs/providers/aws/events/apigateway/#enabling-cors)を見る限りではその設定を見つけることはできなかった。（無いよね？？）

## 参考URL
- https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-payload-encodings.html
- https://www.serverless.com/framework/docs/providers/aws/events/apigateway/#enabling-cors
- https://www.serverless.com/blog/cors-api-gateway-survival-guide
GatsbyJSでGoogleFontsを使いたい

GatsbyJSでブログを作っていく中で、GoogleFontsをセルフホスティング[^1]で導入しました。
その方法を記事にしています。

GatsbyJS自体の導入方法については割愛しています。ご了承ください。

## やりたいこと
GatsbyJSで作ったサイトでNoto Sans JP(GoogleFonts)を使いたい

## 方法
冒頭の通り今回はセルフホスティングで実装します。
GoogleFontsのセルフホスティングは「[＠fontsource](https://github.com/fontsource/fontsource)」というパッケージで実現できます。

### [＠fontsource](https://github.com/fontsource/fontsource)の導入
npmもしくはyarnで普通にインストールを行います。
npmの場合、`npm5.0.0`以降は`--save`がデフォルトで動作するようになったので省略しています。

```
npm i @fontsource/noto-sans-jp
```
インストールが終わったら、js側でimportします。
インポート先は環境にもよりますが、`Layout.js`等のサイト全体に関するファイルがよいです。

```
import "@fontsource/noto-sans-jp"
```

あとはCSSの`font-family`で"Noto Sans JP"を指定してやれば表示されます。

### セルフホスティングにした理由
実装方法として[typography](https://github.com/kyleamathews/typography.js/)を使用する方法もありますが、読み込みに多少の時間を要します。Jamstackはそれ自体が高速なため、かえってその読み込み時間が悪目立ちしてしまいます。そのため、今回は採用を見送りました。

セルフホスティング方式であれば、ホスティングサービスの高速なCDNを活用できるため、速度アップに繋がります。

[^1]: 同一ホスト内にデータを持たせておくこと
VS Code で Vim 使いたいときに設定すること

全部で三つ

入れる拡張機能はこちらです。
https://marketplace.visualstudio.com/items?itemName=vscodevim.vim

# repeat 入力をできるように

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45822/68d91e19-1aba-9de5-401f-5b4c00bc8c6e.png)

この辺に書いてありますが、上記では動きませんでした。

なので、以下で対応しました。

```
$ defaults write -g ApplePressAndHoldEnabled -bool false
```

そもそも VS Code 以外のアプリでもアルファベットの長押しで連打ができなくて不便だったので、むしろ ApplePressAndHoldEnabled こんな機能はグローバルでいらないです。

# setting dispatch を code → keyCode へ

日本語配列キーボードをつかっていると `esc` の代わり `ctrl+[` がうまく発動しないときがあります。コレは、 `[` が `]` と認識されてしまうことがあるからです。

なので、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45822/c7270209-420c-1b32-fa5a-5f99e319357f.png)

Keyboard: Dispatch の setting を code から `keyCode` に変更しました。

あまりやりたくないです。こうすると、`cmd + +` などが動作しなくなって、文字サイズを大きくできません。かわり `cmd+^` しないといけません。この辺難しいので、あまりいじりたくないです。


# cursor blinking をチラつかないように solid に

デフォルトだと、vim のノーマルモードで、カーソルがチラつきます。これは嫌いなので、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45822/0b0dc308-1fe6-68c3-f916-7f78ef77dc58.png)

blinking の設定を solid にしてチラつかせないようにします。


# おわり

これで、VS Code で Vim を使うのに苦がなくなりました。いや、少しあります。 keyCode がいやだ...
Tensorflowをインストールしたがno moduleエラーが発生する件について

# はじめに
久しぶりにtensorflowをインストールしたのですが、なぜかインポートできず(tensorflowがないよと言われる)、解決方法がすぐに見つからなかったため記事にしました。普段意識していないところが原因でしたので、まとめておきます。

# 環境
- python3.8
- Docker
- jupyter notebook

# 問題
```
!pip install tensorflow
import tensorflow as tf
```
を実行すると、以下のよエラーが発生する

![1619405942.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/64f9044f-0b26-464b-f012-71c9da6ab943.png)

この記事を確認したところ`--user`をつけることで権限をつけることでインストール先を~./localに変更できる。
https://boook24.com/?p=518  

```
!pip install tensorflow --user
import tensorflow as tf
```
を実行するとなぜかno moduleエラーとなる。インストールしているのになぜとなった。

![1619405987.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/acad3f7d-901b-1329-2518-ebe738d20101.png)

# 解決方法
`!pip istall`はPython2にインストールするが、python3のライブラリを読み込んでいるので、`!pip3 install`とする必要があった。

```
!pip3 install tensorflow
import tensorflow as tf
```

で無事読み込むことができました。

# 終わりに
pipとcondaの共存やpipとpip3の違いなど、どこにエラーの原因が潜んでいるかなかなか難しいです。
Jenkinsfileでexit codeでビルドステータス分けたい

# 前提

* Jenkinsfileが使えるJenkins
* Scripted PipelineじゃなくてDeclarative Pipelineで使いたい
* try~catchだとerrorのcode全部掴んじゃうので使えない

# サマリ

* scriptで囲って`def ret = sh(...)`とかで取れる
* scriptで囲われた中ならifで何かとかやれるようだった

# やり方

こんな感じに書こう

```
pipeline {
    agent any

    stages {
        stage('Hello') {
            steps {
                script {
                    def ret = sh(
                        returnStatus: true,
                        script: 'exit 100'
                    )
            
                    echo "test: ${ret}"
                
                    if ("${ret}" == "100") {
                        currentBuild.result = 'UNSTABLE'
                    }
                }
            }
        }
        stage('next') {
            steps {
                sh 'echo next no hoge'
            }
        }
    }
}
```

## ちょっと説明

例えばシェル実行の場合は`returnStatus: true`のようにすることで、
exit codeが0以外の場合でもそこで止まらなくできるようにできる模様。
こう書くことでretにexit codeが代入されて、後続で`${ret}`という形で利用できる。
(`returnStatus`以外にも`returnStdout`という標準出力を返すようにすることもできるっぽい)

```
def ret = sh(
    returnStatus: true,
    script: 'exit 100'
)
```

値を利用する場合は下記のように、`"${ret}"`といった文字列代入の形で利用しないと文法エラーになってしまった。
理由は追いかけていないが特殊文字系はクォートでくくらないと誤った判定にされてしまうからとかなのかもしれない。

```
if ("${ret}" == "100") {
    currentBuild.result = 'UNSTABLE'
}
```
消費税計算②

クリックしてから、アラートとして表示するまでのプログラムです。

```index.html
<form>
    <label>式:</label>
    <input  type="tel" placeholder="2000" >
    <input class="btn" type="button" value="計算" id="count">
  </form>
```
今回はHTMLのformから入力して、計算ボタンを押したときに値をアラートで返せるように実装していきます。

```index.js
 // クリックイベントで消費税関数処理終了からのアラートで計算結果表示
    const reckoning = document.querySelector('[type="button"]');

    reckoning.addEventListener('click',e =>{
      const tax = 0.1;
      function totalTax(taxNot) {
        const total = taxNot + taxNot * tax;
        return total;
      }
      
      
      const sub = totalTax(3000);
      
      window.alert(sub);
      
    })
```
①定数 reckoning(計算)にquerySelectorボタンを代入します。
②先程代入した、reckoningにイベントを設定します。
③消費税の関数
④定数subに関数totalTaxを呼び出し、３０００を代入します。
⑤それをwindow.alertで呼び出します。

#関数スコープ
今回、クリックイベントの中で使われている税込み計算の関数は、クリックイベントの中でのみ有効となります。
クリックイベントの外で呼び出してもエラーになります。

#次回
ユーザーが税別の金額を入力したら税込み計算を返せるようにプログラムを組む。
【Android Kotlin】レイアウトファイルで定義した id で Unresolved reference が表示される時の対処法

Android Studio 4.1 から kotlin-android-extensions が非推奨になりました。
したがって、デフォルトでは kotlin-android-extensions が設定されていないため、これを使う場合は、以下を参考に設定を追加する必要があります。

![スクリーンショット 2021-04-26 12.04.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933349/66a40e90-5fbc-d6e7-443d-54c826eb9b81.png)

![スクリーンショット 2021-04-26 12.14.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933349/17f60051-0bbe-dc52-e3bd-f05c7fae3583.png)

View を kt ファイルで扱う技術に [View Binding](https://developer.android.com/topic/libraries/view-binding?hl=ja) があります。
今後はこれが主流となるため、 kotlin-android-extensions ではなく View Binding を使用することを推奨します。
Python 3 エンジニア認定データ分析試験を受験して

# Python 3 エンジニア認定データ分析試験の概要
一般社団法人Pythonエンジニア育成協会が始めた認定試験。

ぶっちゃけて言うと、pythonエンジニア基礎認定試験の続き？のような資格試験です。
データ分析の部分に特化したpython試験だと思って間違えないかと。

・受検日：通年
・受検方法：全国のオデッセイコミュニケーションズCBTテストセンター
・受験料：一万円（税別）、ただし学生は5000円（税別）
・合格ライン：７０％

pythonエンジニア基礎認定試験とほぼ同じです。
（もちろん試験範囲は異なりますが。）

# 受験しようとしたきっかけ

一番の理由は、E資格試験を、勉強する上でpythonの知識をもっと極めないと前に進まないといった状況から。もう一つは、pythonのプログラミング能力を上げるのに、必要かなぁと感じたことから。
（競プロとかやってみたいなーとほのかな野望を持ちつつ）

# 勉強方法
あとにあげる推薦図書を写経したのち、ウェブで公開されてる模擬問題を解きつつ、
弱い部分を実際にコードを組んで頭に叩きこんでました。

使用した模擬問題サイト

[1.PRIME STUDY](https://study.prime-strategy.co.jp/)
[2.DIVE INTO EXAM](https://exam.diveintocode.jp/exam)

平均して７〜８割取得できるようになるまでやりこみました。
模擬試験を行うには、無料ですがメールアドレスの登録が必要。
模擬試験以外の問題もたくさんありますが、模擬試験でいいスコアを取れるように
していけば大丈夫かなと思います。

（不安な人は、下記にあげる分析ノックもやってみると理解が深まるかなと）

# 参考図書

おすすめはやはり、推薦図書に挙げられているこの１冊

[Pythonによる新しいデータ分析の教科書](https://www.amazon.co.jp/dp/4798158348/)
この一冊をやりこめば、大丈夫かと。

上記の一冊でもの足りなかったら下記の一冊もおすすめ。
[Python実践データ分析100本ノック](https://www.amazon.co.jp/Python%E5%AE%9F%E8%B7%B5%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90100%E6%9C%AC%E3%83%8E%E3%83%83%E3%82%AF-%E4%B8%8B%E5%B1%B1-%E8%BC%9D%E6%98%8C/dp/4798058750)

実際にコードを動かすので、頭に叩きこみやすい。

# あると良さげな知識

言わずかもがな,Pythonエンジニア基礎認定試験の知識と、所々に出てくるG検定の知識でした。
分析方法なんかは、G検定の試験範囲とかぶるところが出てきます。


# 感想
E資格試験でぼんやりとわからなかった部分が少しずつ、わかるようになってきました。
まだまだE資格試験までたくさん山がありますが、こなしていけるようになりたいです。
無事合格できてよかったです。
webアプリケーションをヘッドレスCMSで構築する3大メリット

# 0.はじめに

ヘッドレスCMSとは、既存のCMSとは違い、フロントサイド（ビュー側）が存在しない、またはフロントサイドを別システムに依存して運用する事が出来るコンテンツ管理システムの事。

詳しくはこちらのmicroCMSの記事が分かりやすいです
▶ https://blog.microcms.io/what-is-headlesscms/

# 1.SaaS上でのヘッドレスCMSのメリット

ヘッドレスCMSでシステムを構築するメリットは、まずマイクロサービスに通ずるものもありますが、フロントとサーバーを切り分けて開発する事が出来る点です。

よくある既存のシステムがサーバーで処理したデータをフロントに渡し、ビューを表示させるのに対して
![aa11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/23a4b75d-28b3-8e7c-80f6-a8814d81f9a0.jpeg)


ヘッドレスCMSでは、システムが用意するのは、サーバーサイドでデータを処理して公開するAPIで、
フロントは、別システムとして切り出して用意する、またはエンドが自身でカスタマイズしたビューを作成する事が出来ます。
![bb22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/13099688-2ce2-7bed-05cc-0fe48de28cfe.jpeg)


これによるメリットは

**①フロントのカスタマイズ性が向上する事**
依存関係が少なくなり、サーバー側はデータの全てをAPIで公開するため、フロントのデザインはもとより、どのような形でデータを表示させるかまで、フロントのみでカスタマイズする事ができ、
また、場合によってはサーバーサイドは、APIとしてのみCMSを提供し、残りのフロントはエンドに用意させることができます。

またSaaSに関してのみでいえば、既存のフロントビューはそのまま提供し、一定度以上のカスタマイズが必要であれば、独立したフロントビューを構築する事で、既存のシステムへの影響を極力小さくしたうえでエンドにシステムの提供をすることができます。

**②フロントとサーバーの開発の切り分けがしやすくなる**
①に通ずるものもありますが、フロントとサーバー間での依存関係は、APIによるものだけなので、
サーバーサイドは、あくまでデータを処理、出力するAPIを提供するだけで、

そのデータの整形や表示は、完全にフロントで行う事になります。
それによって、サーバー側はこのデータを返すもの、という想定さえあれば、フロントとサーバーを完全に切り分けた開発が可能になります。

また全ての処理をAPI化する事によって、ドキュメント化の敷居が下がる事にもつながります。

**③静的なホスティングを可能とする**

これは、構築によりますが全ての動的処理がAPIを通してJS等で処理できるのであれば、
フロントサイドは静的サイトとしての要件を満たすため、ひいてはCDNでの配信も可能になります。

S3とLambdaとDynamoDBを連携させた静的ホスティングなども、これの一つだと考えられます。
![ｇｄｓｇｓｇ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/81cf9521-b069-73ab-8049-cde71cb36672.jpeg)


完全に静的なホスティングをS3で行い、データの取得、処理、書き込みは全てLambdaを経由したAPIで行うため、
CloudFrontでのCDN配信も可能であり、またフロント（S3上の静的サイト）と、サーバーサイド（Lambda+DynamoDB 実質サーバーレスだが？）での処理は、分けて考える事が出来る。

# 2.おわりに

既存システムを全てAPIで連携させることは、マイクロアーキテクチャの構築の基本だと思われるが、
それに加えて大規模なシステムではCDNで静的な配信が可能な領域を増やす事も、また1つの課題であるため、

それを一挙に可能とするヘッドレスCMSは、今後数年に渡って、Webアプリケーションの基本となっていく（ような気がする）

他の記事も是非どうぞ

https://qiita.com/ryoya1122/items/502c07410197746e79e4

https://qiita.com/ryoya1122/items/f72486e8db0508a7ee08
ADX2ロボットでAisacLinkを消す

# はじめに
キューにグローバルAISACを設定した後とかに、違うAISACに差し替えたいといったときに、
AISACを外すスクリプトを作ってみた

グローバルAISACを複数のキューに追加する場合は、複数キューを選択してグローバルAISACへドロップ（なんか逆な感じがするけど）
することでまとめて設定できるのですが、
間違えてしまったり、　あとで変更したいと思ったときに　Undoができないところまで進行していると、削除するのに苦労する場合があります。
（ツリーで消したいキューを選択して、リストでLinkAisacを選択して消すとかはできそうですが、数が多いと選択がそもそも大変だったり）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/2a960b9a-a4b5-3949-c6ad-692bf542461c.png)

選択に関しては
自分のやりかただと、コメントに特定の文字列を入れて、リストエディターでフィルターして表示とかしているのですが、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/45218678-a406-64e6-28c2-1655f6fc88ad.png)

ここで、キューまでは表示できるのですが、
AisacLinkの場合、キューの下の項目なので、リストのフィルターでも表示ができない・・・

そこで、ここまでキューのフィルターができている状態で、キューを選択して、
AisacLinkを消すというスクリプトになります。

# スクリプト
``` .py
# --Description:[tatmos][Remove]選択しているキューのAisacLinkをすべて削除
import sys
import cri.atomcraft.project
import cri.atomcraft.project as acproject
import cri.atomcraft.debug as acdebug
import cri.atomcraft.preview as acpreview

# 選択しているキューを得る
selected_Cues = acproject.get_selected_objects("Cue")["data"]
if not selected_Cues :
    acdebug.warning("キューを選択してください.")
    sys.exit()

for cue in selected_Cues:
    aisacLinks = acproject.find_objects(cue, "AisacLink")["data"]  
    for aisacLink in aisacLinks:
        acproject.delete_object(aisacLink)

```
[随時追加]** (FunctionClauseError) no function clause matching in Kernel.=~/2

`FunctionClauseError`が発生するケースと対処を随時記録しておく。

# 1.ExUnitのテスト結果が一致しているのに表題の`FunctionClauseError`エラーが発生する場合


```bash
     The following arguments were given to Kernel.=~/2:
     
         # 1
         17
     
         # 2
         17
     
     Attempted function clauses (showing 3 out of 3):
     
         def left =~ "" when is_binary(left)
         def left =~ right when is_binary(left) and is_binary(right)
         def left =~ right when is_binary(left)
     
```

この例では単純にExUnitの記述を誤っていて下記の修正をして解決した。

```diff
- assert EncodeHelper.return_integer("aaa") =~ 17
+ assert EncodeHelper.return_integer("aaa") == 17
```
.gitignoreを書いてないままgitしてたからgit管理下にあるファイルをいい感じに整理した (メモ)

タイトル通りです。
私はgit初心者なので、.gitignoreというやつを書かないまま適当にGoogle driveとかと同じノリでGitHubを使っていて、そういうノリで生きてました (今でもGitHubのことをGoogle driveとかと同じノリだと思ってますが...)。
そういうわけで、たとえばtexをコンパイルしたときに出るゴミファイルもgithubに保存されてて、こういうのって人から見たら「あっこいつ.gitignore書いてねえな」って思われるんだろうなって思うと、なんか恥ずかしくなっちゃって、はい...

それでなんか「掃除」しようと思ったのでやったっていう話です。
この記事は、やったことを自分用にメモするだけの記事です。
(Macで、OSは Big Sur バージョン11.2.3 です)


##やったこと

とりあえず.gitignoreを作成：[giboというやつを使うと良いらしい](https://qiita.com/tomotlab/items/3dad50a61b725bda72e4)

やりたいこと：すでにgit管理下にあるファイルのうち今作った.gitignoreで弾かれるものを弾きたい。
3つの場合にわけてますが、最後の場合で全てカバーされているとは思います。

### 関係するファイル名やフォルダ名に日本語を使っていない場合

まず日本語関係ないのでそれに関する設定をtrueにする (何もしてなければ最初からtrueになっているはず)：

```sh
git config --global core.quotepath true
```

(```--local```でやってもいい。その場合、変更は現在のリポジトリだけに適用される。)
で、[この記事](https://qiita.com/yuuAn/items/b1d1df2e810fd6b92574)にある通り、

```sh
git rm -r --cached `git ls-files --full-name -i --exclude-from=.gitignore`
```

を実行すればok。
・cf. [```git rm```について](https://qiita.com/ytkt/items/a2afd6be8e4f06c1ea25)
・cf. [```git ls-files```について](https://qiita.com/zimathon/items/d964c4b3cc688cb2d114)



### 日本語を使っているけど (半角の) 空白文字は使っていない場合

念のため、gitの日本語の設定をする。[この記事](https://qiita.com/hayamofu/items/d8103e789196bcd8b489)にあるように、

```sh
git config --global core.quotepath false
```

を実行するとok。
次に、先ほどと同じように

```sh
git rm -r --cached `git ls-files --full-name -i --exclude-from=.gitignore`
```

を実行すればok。


### 日本語も (半角の) 空白文字も使っている場合 (私の場合)


念のため、gitの日本語の設定をする。先ほどと同じで

```sh
git config --global core.quotepath false
```

を実行するとok。
次に、拡張子.shで次のファイル (cf. [シェルスクリプトについて](https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337)) を作成 (zshの人は1行目でzshにする):

```sh
#!/bin/bash

git ls-files --full-name -i --exclude-from=.gitignore | while read line
do
  git rm -r --cached $line
done
```

ここでは「テスト.sh」という名前にしておく。
このファイルを保存する場所はどこでもいいけど、現在のディレクトリから近い場所にいる方が相対パス書くときにめんどくさくなくていいんじゃないかな...(適当)。
次に、「テスト.sh」の権限の変更をする (cf. [権限について](https://qiita.com/shisama/items/5f4c4fa768642aad9e06))。ターミナルで

```sh
chmod u+x テスト.shの相対パス
```

を実行する。
最後に、ターミナルで「テスト.sh」の相対パスをなんのコマンドもなしに入力し、returnを押せばok。
なんらかがばーーーっとなっていい感じになってくれます (すごい)。


## 参考文献

git関係：
・giboについて：[giboで簡単に最適な.gitignoreを作成](https://qiita.com/tomotlab/items/3dad50a61b725bda72e4)
・日本語について：[最低限しておくといいgitconfigの設定](https://qiita.com/hayamofu/items/d8103e789196bcd8b489)
・[あとからまとめて.gitignoreする方法](https://qiita.com/yuuAn/items/b1d1df2e810fd6b92574)
・```git rm```について：[gitの管理対象から特定のファイル、ディレクトリを削除する](https://qiita.com/ytkt/items/a2afd6be8e4f06c1ea25)
・```git ls-files```について：[git ls-files](https://qiita.com/zimathon/items/d964c4b3cc688cb2d114)

シェル：
・権限について：[Linuxの権限確認と変更(chmod)（超初心者向け）](https://qiita.com/shisama/items/5f4c4fa768642aad9e06)
・[シェルスクリプト(Bash)入門。できること、基礎文法、業務自動化の方法を解説【事例あり】](https://goworkship.com/magazine/shell-script-bash/)
・[初心者向けシェルスクリプトの基本コマンドの紹介](https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337)
・[shスクリプトにおける引用符](http://koke.asrc.kanazawa-u.ac.jp/HOWTO/sh-quote.html)
VSCodeの予測変換をtabで選択する

#はじめに
すぐ忘れるので残しておきます。

VSCodeって予測変換をTabで選択じゃなく決定になってしまうのってちょっと厄介じゃないですか？
そこでVSCodeのキー設定を変更していきたい思います。


#解決前

下の画像の時、Tabを押すとh5が入力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1393871/c23b95a2-49e8-59f8-52db-673fa0c21e30.png)

#解決法
キーボードショートカットを開いてください。
下の文で検索します。

```
select next suggestion
```
select next suggestionのCtrl + DownArrowをtabに変更します。
変更は鉛筆マークをクリックすると変更するとこができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1393871/afa03a37-e12b-3d41-4c24-2735df452c13.png)

こちらが変更後です。
キーバインドがtabに変更されれば大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1393871/aa35358d-af20-66e3-2ebd-4e14e8097251.png)

また前の予測変換を選択したいという時は、これで検索してください

```
select Prev Suggestion
```

以上でおわりです！！
form_withのデフォルト設定でハマった話

## 実装環境
Ruby 2.6.5
Rails 6.0.3.5

## 発生した不具合
form_withを用いた新規登録ページのバリデーションによるエラー表示ができなくなった。

## 問題点
```erb
# 新規登録のviewでの記述
<%= form_with model: @user, url: user_registration_path, class: "sign-up-form", id: 'form' do |f| %>
```

![新規登録時の動作画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790862/d91bef79-ba04-2808-6f2e-15279b98179b.png)

## 解決
早速答えですが、**form_withはデフォルトだとAjax処理を行う**という仕様で引っ掛かっていました。
これを踏まえてviewの記述を見れば分かる通り**local: true**が抜けているためAjax処理を行なっています。
そのためterminalでも**Processing ~ as JS**とある様にJavaScriptでの処理が行われています。
非同期に対応したコントローラーを作成していないのにAjax処理をしたところでデータは受け取れないし、返ってくる訳無いです。はい。
そしてコントローラーでモデルへアクセスする事も無いため当然バリデーションも動かないということになります。

## 振り返り
viewの記述の確認は何度もしたつもりでしたが、完全に抜け落ちていた様です。思い込みって怖い...
それによりterminalのJS表記に気を取られ、Javascriptの実装を片っ端から消してみたり、gitでフロント実装前まで巻き戻してみたり、あっちこっち飛び回る泥沼状態でした。挙句正常に動作するのがフロント実装前のデータだったがためにもう諦めて別のアプリ作成まで考える始末でした。
使用するものは公式ドキュメントでしっかり仕様を把握してから使うことを改めて肝に命じた出来事になりました。
Google CodelabsでCloud Firestoreをお試し

# Firestoreとは
`Cloud Fiestore`（Fiestore）は`Firebase`のサービスの1つであるサーバーレスのNoSQLデータベースです。
サーバを介さずクライアントとFirestoreが直接やりとりし、
リアルタイムでデータの取得・更新ができます。
オフライン時はキャッシュ済みのデータを返してくれたり、
データ更新できなかった場合は一時的にローカルに保持しオンラインに接続されたタイミングで同期してくれたりなど、
オフライン時もサポートされます。

導入コスト、学習コストも低く、サービスの規模にもよりますが
開発スピードを重視したいときなどは選択肢の一つになるのではないでしょうか。

## 公式ドキュメント
https://firebase.google.com/products/firestore/?hl=ja

# Firestoreをお試しする

## Codelabs
https://codelabs.developers.google.com/

Googleが提供している各種サービスのハンズオン形式のチュートリアル。
WebだけでなくiOSやAndroid, Wearまで様々なプラットフォームのチュートリアルがあり、
気になるサービスをちょっと試してみたいときにとても便利です。

必要なコードはすべてGithubからcloneできるので、
フロントを作るのに時間を割きたくないという方にもおすすめ。

今回はFirestoreを使った下記のチュートリアルを試してみます。
50分ほどでAndroidのレストランおすすめアプリを作成する、というものです。
（チュートリアル完了にかかるおおよその時間は、ステップを進めていくと更新されていきます。）
[Cloud Firestore Android Codelab](https://firebase.google.com/codelabs/firestore-android#0)

ちなみに上記のチュートリアルからは下記のことが学べます。

・AndroidアプリからFirestoreへのデータの読み取りと書き込み
・Firestoreデータの変更をリアルタイムで聞く
・Firebase認証とセキュリティルールを使用してFirestoreデータを保護する
・複雑なFirestoreクエリを作成する

## AndroidアプリでFirestoreを利用するまでの流れ
1. FirebaseコンソールからFirestoreプロジェクトの追加
2. プラットフォームの選択→アプリの登録
3. 設定ファイル`google-services.json`のダウンロード
4. ダウンロードした設定ファイルをローカルプロジェクトの`app`直下に追加、再ビルド
4. Firestoreプロジェクトとローカルプロジェクトのリンク

あとはデータを書き込んだり読み込んで表示したりフィルタリングしたり。

---

Firestoreは全く使ったことがなかったのですが、
今回のチュートリアルは特に詰まることなくスムーズに進められました。
体験レベルであれ、やはり実際に手を動かすとどのような場面で使えばよいのか
イメージも沸きやすいのでよいですね。

お疲れさまでした！

## Firebase Emulater起動時のエラー

Firebase Emulater起動時に下記のように「ポート8080が開いてないよ」と言われましたが
そのまんまで、ポート8080を開放してあげるだけでいけました。

```
> firebase emulators:start
i  emulators: Starting emulators: auth, firestore
i  emulators: Shutting down emulators.
i  hub: Stopping emulator hub
!  firestore: Port 8080 is not open on localhost, could not start Firestore Emulator.
!  firestore: To select a different host/port, specify that host/port in a firebase.json config file:
      {
        // ...
        "emulators": {
          "firestore": {
            "host": "HOST",
            "port": "PORT"
          }
        }
      }
i  emulators: Shutting down emulators.

Error: Could not start Firestore Emulator, port taken.
```