OmniAICreator/Qiita-1.07M huggingface dataset:
[Vue]d3.jsを用いてTSVデータをVue3で描画するまでの方法

- フロントエンド開発においてAPIではjson、コンテンツではmarkdownをfetchして加工したり描画することが多い。
- Vue2利用の際も当てはまるが、最近Nuxt3のBetaが発表されたことも相まって、そこで導入されているVue3やViteの注目率や利用率が日に日に上昇。
- そこで今回はデータ形式としてよく使うTSVのVue3での描画処理を記録していく。

## 環境
- Mac OS 11.2.3
- Node.js v14.16.0
- Vue 3.2.16

## 前提
- 利用するサンプルプロジェクトとして以下を満たしていることとする。
  - Vue3の利用
  - Vite2の利用
- 以下で上記を満たすサンプルを用意することが可能。

```bash
npm init vite@latest sample -- --template vue
```

## 手順

### TSVデータの用意
- 描画対象のTSVデータとして以下を用意して任意のディレクトリに入れておく。

```text:data/members.tsv
id	name	score
1	tanaka	90
2	suzuki	80
3	saito	70
4	oda	100
```

### 解析ライブラリのインストール
- TSVを解析するため以下のコマンドでライブラリをインストールする。

```bash
# d3.jsのインストール
npm i d3
```

### 描画
- 上記までの手順が完了後、実際にvueファイルを修正して画面に描画していく。
- 今回は以下の2つの方法で描画する処理を見ていく。用途に合った方を利用する。
  1. **top-level-awaitを利用しない場合**
  2. **top-level-awaitを利用する場合**
      - **※2の方法は実験的機能であるらしく、利用には注意が必要**

#### top-level-awaitを利用しない場合

- 以下のファイル群を修正する。
  - 今回は`src/components/`配下のvueコンポーネントを`src/App.vue`で呼び出して表示させる形式にする。

- `src/components/Member.vue`

```vue:src/components/Member.vue
<script setup>
import { ref } from 'vue'
import * as d3 from 'd3'

// リアクティブ値
const members = ref(null)

// tsvパース処理
async function getMembers(){
  try{
    // サンプルデータ指定
    members.value = await d3.tsv("../../data/members.tsv",(d) => {
      return {
        id: d['id'],
        name: d['name'],
        score: d['score']
      }
    })
  } catch(err){
    console.error(err)
  }
}

// 呼び出し
(async () => {
  await getMembers()
})()
</script>

<template>
  <li v-for="member in members" :key="member">
    id : {{ member.id }}, name : {{ member.name }}, score : {{ member.score }}
  </li>
</template>
```

- `src/App.vue`

```vue:src/App.vue
<script setup>
import Member from './components/Member.vue'
</script>

<template>
  <Member />
</template>
```

#### top-level-awaitの利用の場合
- 以下のファイル群を修正する。
  - **※以下の`App.vue`で使われている<suspense>タグは実験的機能のため、利用の際は注意する。**
  - [参考](https://v3.ja.vuejs.org/guide/migration/suspense.html)

- `src/components/Member.vue`

```vue:src/components/Member.vue
<script setup>
import { ref } from 'vue'
import * as d3 from 'd3'

const members = ref(null)

try{
  members.value = await d3.tsv("../../data/members.tsv",(d) => {
    return {
      id: d['id'],
      name: d['name'],
      score: d['score']
    }
  })
} catch(err){
  console.error(err)
}
</script>

<template>
  <li v-for="member in members" :key="member">
    id : {{ member.id }}, name : {{ member.name }}, score : {{ member.score }}
  </li>
</template>
```

- `src/App.vue`

```vue:src/App.vue
<script setup>
import Member from './components/Member.vue'
</script>

<template>
  <suspense>
    <template #default>
      <Member />
    </template>
    <template #fallback>
      読み込み中・・・
    </template>
  </suspense>
</template>
```

### 確認
- 上記の記載後、`npm run dev`等でサーバーを起動して、以下のように任意のTSVデータが描画されていることを確認する。

![image](https://user-images.githubusercontent.com/44114228/137748946-4a3fdc0c-431a-4180-8710-d87368ee1799.png)

## まとめ
- 普段データとしてTSVを扱うことが多いため、Vue3での扱い方を記録できた。
- 実験的な機能であるsuspenseを扱ったため、今後正式に利用が推奨されていくのか動向を確認していく。

## 参考
- https://d3js.org/
- https://v3.ja.vuejs.org/guide/migration/suspense.html
【JavaScript】関数とオブジェクト④　コールバック関数とthis


#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/a6b6de600305fc61dfa1

#目的

* 関数とオブジェクトについての理解を深める

#本題
###1.コールバック関数とthis

####前回までのおさらい

````javascript
window.name = 'John';

// personというオブジェクトを定義
const person = {
    name: 'Tom',
    hello: function() {
        console.log('Hello ' + this.name);
    }
}
// ”HelloTom”と出力される
person.hello();
// オブジェクトのメソッドとして使った場合、thisは呼び出し元のオブジェクトを参照する
```````

####コールバック関数
personのhelloを他の関数の引数として渡した場合どうなるのか

`````javascript
window.name = 'John';

const person = {
    name: 'Tom',
    hello: function() {
        console.log('Hello ' + this.name);
    }
}
person.hello();

// refという引数にコールバック関数が渡ってくるようにする
function fn(ref){
    ref();
}

// 実行結果は「hello John」と出力される(関数として実行しているから？)
fn(person.hello);

// メソッドを他の変数に代入していることと同じ
// refに渡ってくるのはpersonのhelloというプロパティが参照している先の関数
// refを実行するということは関数を実行していることになる
// 関数として実行した場合,thisにはグローバルオブジェクトの値が格納される
``````


今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
【Unity】git トラブルシューティング

# git clone した後にスクリプトが存在しているのにmissing状態になる

git cloneで下図の様に、missing状態になることがある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/ed7c76f6-bf52-1d1b-67e4-7ea37ef381f4.png)

本来であればcsファイルは以下の表示となっているが、missing状態になっている場合、このアイコンが白色になっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/ab36bf05-2bd7-178f-e6dd-8511aca15486.png)

### 解消方法
* エクスプローラを開き、対象スクリプトと同名称の.metaファイルを削除する。
4-3.1 CSS演習1

# 完成イメージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/6702010d-3d86-e6a8-5691-db3bc4e48a97.png)

# 使用画像

![photo1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/c6ba6869-7835-4584-ed73-7bb13cd2c1b5.jpeg)
![photo2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/7013eac2-a868-2ac6-3480-c4e5538b0f52.jpeg)
![photo3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/51fbb747-ba8a-4a5a-4be4-d9e3ebefe928.jpeg)
![photo4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/d73b5682-9ef9-bd75-0ffd-1b0663351c1d.jpeg)

# HTML

このHTMLを元に完成イメージに近づけてみてください。

```
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>あいうえお</title>
  </head>
  <body>
  </body>
</html>
```

# ヒント

- ブラウザタブの表示も注意してみてください。
- 画像それぞれに余白があります。
- 画像の縁には線があり、色がついています。また角が丸くなっています。
- 左から右に画像を2枚配置されると次の行でまた画像が表示されています。
- 全体的に中央に表示されています。

# Answer

後ほど公開します。

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>★★ここも変えてください★★</title>
    <style>
      #main {
        text-align: center;
      }
      img {
        margin: 10px;
        border-radius: 15px;
      }
      .left {
        border: solid 5px orange;
      }
      .right {
        border: solid 5px yellow;
      }
      .bottom {
        box-shadow: 10px 10px 15px gray;
      }
    </style>
  </head>
  <body>
    <div id="main">
      <div>
        <img class="left top" src="photo1.jpg" alt="タヒチの写真1" />
        <img class="right top" src="photo2.jpg" alt="タヒチの写真2" />
      </div>
      <div>
        <img class="left bottom" src="photo3.jpg" alt="タヒチの写真3" />
        <img class="right bottom" src="photo4.jpg" alt="タヒチの写真4" />
      </div>
    </div>
  </body>
</html>
```
Unicodeを文字列へアンエスケープ

![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/798717bf-1937-6861-c8b0-2ca915ca699f.gif)


## ソース

### JavaScript

```js
var unicodeUnescape = function(str) {
    var result = '', strs = str.match(/\\u.{4}/ig);
    if (!strs) return '';
    for (var i = 0, len = strs.length; i < len; i++) {
        result += String.fromCharCode(strs[i].replace('\\u', '0x'));
    }
    return result;
};

var result = unicodeUnescape('\\u3042\\u3044\\u3046\\u3048\\u304a');
console.log(result); //あいうえお
```

### HTML

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">

<script>

function unEscape() {

    var unicodeUnescape = function(utf8String) {
        var result = '', strs = utf8String.match(/\\u.{4}/ig);
        if (!strs) return '';
        for (var i = 0, len = strs.length; i < len; i++) {
            result += String.fromCharCode(strs[i].replace('\\u', '0x'));
        }
        return result;
    };

    var utf8String = "";
    utf8String = document.getElementById('input').value;

    var result = unicodeUnescape(utf8String);
    document.getElementById('converterd').value = result;
}

    </script>
</head>

<body>
    <p><label for="input">Unicode（¥uxxx形式）を入力:</label><p><textarea cols="120" rows="10" id="input"></textarea></p>
    <p><input type="button" value="アンエスケープ" onclick="unEscape();"></p>
    <p><textarea cols="120" rows="10" id="converterd">アンエスケープ後文字列</textarea></p>
</body>
</html>
````

## 参考

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/0efd0abd-5a49-4769-7616-8cd2a4fc91f0.png)


https://dencode.com/ja/string/unicode-escape

https://qiita.com/weal/items/3b3ddfb8157047119554

以上、ダンプファイルやらに含まれるUnicodeを読みたいと思ったときのもの。簡単ながら以上です。
Mac OS環境下におけるHCL Notesでの設定ファイルの場所


HCL Notes 11.x + MacOS(Big Sur)で確認。

#notes.iniの場所
MacではWindowsと違ってnotes.iniという名前ではなく、`Notes Preferences`というファイル名になっている。

`"/Users/<ユーザー名>/Library/Preferences/"Notes Preferences"`

```ターミナルからのアクセス
vi ~/Library/Preferences/"Notes Preferences"
```

#names.nsfなどの場所

`/Users/<ユーザー名>/Library/"Application Support"/"HCL Notes Data"`

```ターミナルからのアクセス
$ ls ~/Library/"Application Support"/"HCL Notes Data"
```

#おまけ
HCL Notesでユーザー切り替え画面が出てこなくなってしまった場合は、`Notes Preferences`で、`KeyFileName=xxxxx`となっているところをコメントアウトして`#KeyFileName=xxxxx`としてから起動すれば良い。
最初のアプリを作る方法

iOSアプリを作ったことがない方が、とりあえず最初のアプリを作る方法です。
画像を表示するシンプルなアプリを作ります。

#１、Macをひらく
iOSアプリを作るには、iMacもしくはMacbookが必要です。
![macbookIMGL4495_TP_V.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/e63b8cd2-0aad-2fd9-5671-c669cf27c8d4.jpeg)

#２、Xcodeをダウンロード
App Storeのアプリを開き、「Xcode」で検索して、Xcodeをダウンロードします。
![スクリーンショット 2021-10-19 1.58.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/01b0767a-7f5d-0805-de88-34546f344e69.png)

![スクリーンショット 2021-10-19 1.57.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/7ae189ad-fa15-5e71-6684-81a19af0bf75.png)

#３、Xcodeをひらく
ダウンロードが完了したら、Xcodeをひらきます。

「Create a new Xcode project」をクリック
![スクリーンショット 2021-10-19 2.04.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/23a8b3f6-af1c-e817-2df2-ca2ec87ffc78.png)

「App」を選択して「Next」
![スクリーンショット 2021-10-19 2.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/b7246ba8-1c5c-806c-f2dd-e7c9cada9153.png)

任意のアプリ名を入力して「Next」
![スクリーンショット 2021-10-19 2.09.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/511e8e4a-039c-13bb-7306-4e53ae9463f9.png)

保存先を指定して「Create」

![スクリーンショット 2021-10-19 2.09.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/58cbd10a-5e12-581b-91bf-6c2d60f78b3b.png)

こういう画面が表示されます。
![スクリーンショット 2021-10-19 2.15.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/9e7f9458-dd59-6242-a1a9-4eaebb994f2b.png)

#４、文字を変える
コードの中の「Hello World!」という部分を別の文字列に変えてみます。
![スクリーンショット 2021-10-19 2.18.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/4b9e87a7-9fcb-8c89-ae16-dcf3da5f9422.png)

#５、アプリを起動する
ライトニングケーブルでお手持ちのiPhoneをMacにつなぎます。
Xcode上部のアプリ名をクリックして、接続したデバイス名を選択します。
![スクリーンショット 2021-10-19 2.21.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/c29599e1-7c1f-b749-9d10-5e1c72ce8184.png)
（手元にデバイスがない場合は、表示される適当なデバイス・シミュレータを選択します）

Xcode左上の再生ボタンを押します。

![スクリーンショット 2021-10-19 2.24.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/55eea001-6514-7754-2bf5-35ebc79ac0e3.png)

デバイスでアプリが起動します。
![IMG_8194.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/c6e58096-d80a-e334-2e08-5b2ae6126505.png)

#6、画像を表示する
Xcodeの左のペインから「Assets」を開き、好きな画像をドラッグ&ドロップします。
![スクリーンショット 2021-10-19 2.30.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/ebfdb59d-0f02-1842-a06d-f2f2e31bfdb3.png)
左のペインから「ContentView.swift」を開き、コードの中の

```Swift
Text("****")
```
の部分を

```Swift
Image("Assetに入れた画像名")
```
に変更します。
![スクリーンショット 2021-10-19 2.34.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/79b2c900-8ca2-ce39-e4c8-db8c48999422.png)

５、の手順でアプリをもう一度起動します。
画像が表示されます。

![IMG_8195.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/2ac0fc38-ac13-436d-f794-3622f1976ef2.png)

ここまでで、画像を表示するシンプルなアプリが作れました。
さらに色々なアプリを作りたい場合は、「Swift 画像を並べる」など、やりたいことを検索すると、やり方がわかります。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

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

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
javascript演習　4日目/３０日

覚えたこと

reduceの使い方

```javascript
const totalYears = inventors.reduce((total, inventor) => {
      return total + (inventor.passed - inventor.year);
}, 0);
//他にも重複を数えたり
const transportation = data.reduce(function(obj, item) {
      if (!obj[item]) {
        obj[item] = 0;
      }
      obj[item]++;
      return obj;
}, {});
```


sortの使い方

```javascript
const oldest = inventors.sort(function(a, b) {
      const lastInventor = a.passed - a.year;
      const nextInventor = b.passed - b.year;
      return lastInventor > nextInventor ? -1 : 1;
});
//splitとか使って
const alpha = people.sort((lastOne, nextOne) => {
      const [aLast, aFirst] = lastOne.split(', ');
      const [bLast, bFirst] = nextOne.split(', ');
      return aLast > bLast ? 1 : -1;
});
```


map,filter,textContent,includesの使い方

```javascript
const category = document.querySelector('.mw-category');
const links = Array.from(category.querySelectorAll('a'));
//もしくは[...category.querySelectorAll('a')]
const de = links
            .map(link => link.textContent)
             .filter(streetName => streetName.includes('de'));
```
Macでアプリケーションを開くとアクセス権がありませんと出るエラーの対処法

# Macでアプリケーションを開くとアクセス権がありませんと出るエラーの対処法
久しぶりにアプリケーションをmacで開いたところ身に覚えのないエラーでアプリケーションの起動ができなくなっていました。
![20210206002014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731297/4c7588c0-d584-938e-4be6-3895edd79c5c.png)

自分しか使ってないPCでそんなことあるわけないだろと思ってアクセス権を確認したところ、案の定問題なしでした
![スクリーンショット 2021-10-19 0.53.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731297/9974e344-aecf-a533-b467-5667d27b26d5.png)

エラーレポートが出ていたので詳しく見てみると
`"Termination Reason: Namespace CODESIGNING, Code 0x1"`
とかいう謎の原因が出ていました。
調べてみたところMacでたまにある現象らしく、アプリ証明書が取り消されてしまっている状態のようです。

次の方法でアプリ証明書を書き込み直すことで解決しました。
1. Xcodeをインストールして一度起動する。
2. Terminalを開き、Applicationsの階層まで移動し、
`codesign --force --deep --sign- / Applications / アプリケーション名.app`
を実行する。

意外と解決策がすぐに見つからなかったので少し焦りましたが、まあ動いたのでよしとします。
全てのトラブルシューティングがこんなに簡単ならいいのに...
クラウド...？雲？

# 記事を書くきっかけ
　流行りのAWSを学習する前にクラウドについて勉強しようと思い、簡単に調べてみました。

# 目次
- クラウドとは
 - メリット
 - デメリット
- 種類
 - SaaS
 - PaaS
 - IaaS
- まとめ
- 参考

## クラウドとは
　ユーザーがインフラ（サーバーやネットワーク）やソフトウェアを持たなくても、インターネットを通じて、必要に応じてサービスを利用できる「**仕組み**」のことを指す。
　この仕組みに基づいて提供されるサービスを「クラウドサービス」、クラウド上にデータを保存して運用することを「クラウド化」という。

### メリット
　・初期費用が安い
　・サーバーの拡張が容易

### デメリット
　・カスタマイズが完全自由ではない
　・オンライン環境でないとサービスが受けられない
　・サービスが停止されるリスクあり

## 種類
　クラウドサービスには主に3つある。
### SaaS（Software as a Service）
　ソフトウェアをクラウド化したもの。どんな端末からでもアクセスでき、複数人でもデータの編集を行うことができる。

### PaaS（Platform as a Service）
　ハードウェアやOSをクラウド化したもの。コストを抑え、システム開発を素早く進められる。

### IaaS（Infrastructure as a Service）
　サーバやストレージなどのITインフラをクラウド化したもの。

# まとめ
　インターネットを通じてサービスを利用できる仕組みがクラウドであり、私たちが1番馴染みあるのはSaaSかなと、クラウドについてざっくりと理解しました。

# 参考
https://securesamba.com/media/8279/
https://altus.gmocloud.com/suggest/cloud/
https://altus.gmocloud.com/suggest/shared/
AWS LightsailでKubernetesを使ってみた

# 始めに
低コストで使い勝手の良いLightsailですが、設定の簡単さゆえKubernetesの構造にはそぐわない所が幾つかありました。今の記事ではLightsailでKubernetesクラスターを構成する時に躓いた所を整理していきます。

# 基本設定

## インスタンスの選択
### おすすめ
Master Node: 20 USD/月 (4GB メモリ, 2コアプロセッサ, 80GB SSD ディスク)
Worker Node: 10 USD/月 (2GB メモリ, 1コアプロセッサ, 60GB SSD ディスク)

公式的にマスターノードは二つ以上のコアを使うように言われているため、20 USD/月のVMをお勧めします。ワーカーノードは理論上1GBのメモリでも行けますが、実際にPODを回すにはメモリが足りないですので月10 USDのVMを使うべきかと思います。

## Network
### CalicoのIPv4ファイアウォール
ファイアウォールのルール設定に制限があります。従ってCNIでCalicoを使う場合、TCPポート以外にIPIPプロトコルを許可するために**アプリケーション=すべてのプロトコル**を解放する必要があリます。ソースIPアドレスに制限をかける事は可能なのでセキュリティのために各ノードのプライベートIPを指定するべきでしょう。
![net.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286572/7549f92e-c1d5-95c5-25f8-b3d8b86689a5.png)

# 設計および運用上の考慮点

## 80ポートおよび443ポートでサービスを公開する
### 使用できない方法

#### Service Type: Loadbalancer
Lightsailでは対応してないみたいです。

#### Lightsailのロードバランサー
Lightsailのロードバランサーは80（HTTP)と443（HTTPS)だけをサポートしています。また、ポートフォワーディング機能は使えません。ホストネットワークを使わない限りLightsailのロードバランサーを使ってKubernetesのサービスを80および443ポートで公開することはできません。

### 使用できる方法

#### ELBのロードバランサー
ELBのロードバランサーはフォワーディング先のポートを設定することができます[^1]。すなわち、80と443から受けたリクエストをNodePortが提供する30000-32767のサービスに連結できます。VPC Peeringを使えばELBのロードバランサーをLightsailへ繋ぐことができます[^2]。

#### ソフトウェア型のロードバランサー
NGINX[^3]やHAProxy[^4]などL4及びL7のソフトウェア型のロードバランサーを使う方法です。注意すべきはこの**ソフトウェア型のロードバランサーをKubernetes上で配布してはいけない**ということです。おすすめはDockerを使うことです。Dockerでソフトウェアロードバランサーを管理するとLightsailコンテナなど、可用性の高いAWSサービスに簡単に移植できます。

[^1]: Application Load Balancer のターゲットグループ, https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-target-groups.html#target-group-routing-configuration
[^2]: [AWS] ALBのIPターゲットをLightsailインスタンスで活用する, https://dev.classmethod.jp/articles/lightsail-with-alb-ip-target
[^3]: HTTP Load Balancing, https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/
[^4]: 【VPS1台でインフラ勉強】HAProxyでロードバランサーを構築, https://blog.mosuke.tech/entry/2014/11/09/171436/
ChromeでCookieの保存をブロックされたのでメモ

# 起こったこと
Chromeから以下の警告が出て、クロスサイトのレスポンスに含まれるCookieを保存できなかった

```
Set-Cookieヘッダーを介してCookieの設定を試みましたが、「SameSite=Lax」属性は指定されていたものの、トップレベルナビゲーションへのレスポンスではないクロスサイトレスポンスが送信元だったため、ブロックされました。
```

# やっていたこと
1. ローカルで`https://localhost:8080/{何かしらのpath}`にアクセスするとHTML・JSを返すサーバーを起動した
1. ローカルサーバーから返されるJSはトップレベルナビゲーションの変化が起きないクロスサイトリクエストを行った
  - 宛先は仮に`subdomain.site.com`とする
1. クロスサイトは`Set-Cookie`ヘッダーを含むレスポンスを返却した
1. HTMLは再度同様のクロスサイトにクッキーを含むリクエストを送る想定だった

しかし、クロスサイトにクッキーを送れておらず、原因を探ったところChromeからクッキー保存をブロックした旨の警告が出ていた

# 対応
以下の２点を実施したところ、クッキーを保存してくれるようになった
- ローカルサーバーのURLを`https://localhost.site.com:8080/{何かしらのpath}`に変更し、クロスサイトのドメインと合わせた
- hostsファイルを編集し、`127.0.0.1`と`localhost.site.com`を関連づけた

# 原因について
対応結果からの推測になるが、おそらくChromeはURLバーに表示されているドメインとクロスリクエスト先のドメインが一致していないと、クロスリクエスト先からのCookieを保存してくれない模様
secrets.randbelowをrandintのように使いたい

結論

```Python
# randint(a,b)の代わり
secretsRandint = lambda a,b: (secrets.randbelow((b-a)+1))+a
# choices(l, k=n)の代わり
secretsChoices = lambda table, k: [secrets.choice(table) for _ in range(k)]
```

# 背景
Pythonで乱数を生成する際にはrandom.randintが使えます。しかし、この関数は簡単な規則で乱数を生成されています。このため、パスワードの精製などにはsecretsモジュールの仕様が推奨されます。
ただし、secretsモジュールの関数はrandomと少し異なります。同じように使えるようにします。

# randint(a,b)
予備知識: []は閉区間で以上・以下です。()は開区間で超過・未満です。

- random.randint(a,b) は [a,b]を返します。random.randint(4,7) なら 4,5,6,7が出ます。
- secrets.randbelow(n) は [0,n)を返します。secrets.randbelow(4) は 0,1,2,3が出ます。

ここでrandomのように(a,b)の区間を返したい場合、

- secrets.randbelow( (b-a)+1) ) + a 
とします。

例: secretsで4,5,6,7を返したい場合、

- secrets.randbelow( (7-4)+1) ) + 4 と代入し
- secrets.randbelow( 4 ) + 4 となる。
- これは、(0,1,2,3)の一様に出現するランダムな集合に+4なので、結果(4,5,6,7)となる

## 実装例
```Python
import secrets
secretsRandint = lambda a,b: (secrets.randbelow((b-a)+1))+a
import collections
# Counter({1: 2020, 2: 2011, 5: 2008, 3: 1992, 4: 1969}) のように一様にランダムに選択されている
print(collections.Counter([secretsRandint(1,5) for _ in range(10000)]))
```

# choices
```Python
# ['1', '7', '2', '5', '3', '2', '3', '7', '6', '3']
import string, random
random.choices(string.digits, k=10)
```
となる便利な関数です。なぜかsecretsにはchoiceという1文字をランダムに取り出す関数しかありません。n回呼べばよいです。

## 実装例
```Python
secretsChoices = lambda table, k: [secrets.choice(table) for _ in range(k)]
# ['6', '1', '6', '0', '9', '7', '3', '1', '8', '7']
print(secretsChoices(string.digits, 10))
```
XCode13かつiOS 15でナビゲーションバーが透過されてしまう

# 何が起こったか
Xcode13かつiOS15だと、このプロパティがデフォルトで透過色が設定されてしまうと言う話

https://developer.apple.com/documentation/uikit/uinavigationbar/3198027-scrolledgeappearance

ドキュメントを読むとiOS13から使えるプロパティのようですが、XCode13を使って、iOS15へ向けてビルドすると、、


このようにナビゲーションが透過されてしまいます。

# 対処方法
AppDelegateのdidFinishLaunching(with options)で、これを書いてやればOKです。

```AppDelegate.swift
let appearence = UINavigationBarAppearence()
appearence.backgroundColor = .white
UINavigationBar.appearence() = appearence
```

また、開発中アプリのDeployment TargetがiOS12以上だったので、このままではOS12でこのプロパティを利用できない旨の警告が出ます。
ただし、iOS13以上を許可すると、iOS15以下の端末でナビゲーションバーの両サイドにグラデーションがかかってしまいました。。
何か処理がコンフリクトしてるんですかね。

結局落ち着いた形はこれ

```AppDelegate.swift
if #available(iOS15, *) {
  let appearence = UINavigationBarAppearence()
  appearence.backgroundColor = .white
  UINavigationBar.appearence() = appearence
}
```

# まとめ
アプリ全体のナビゲーションに影響が出ていたので、焦りました。
Appleさんこういう罠を仕込んでくるので、OSアップデート対応は気が抜けませんね。。
VBA テキストファイルに書き出し

```vb
Option Explicit
Sub witeFile()
  Const StrFile = "C:\Users\hoge\Desktop" & "\hoge.txt"
  Dim ExcelSheet
  Dim fs As Object
  Dim a
  Dim i As Long

  Set fs = CreateObject("Scripting.FileSystemObject")
  Set a = fs.CreateTextFile(StrFile, True)
  
  'Write：書き出し
  'Writeline：書き出し＋改行
  For i = 1 To 5
    a.Write ("This is a test" & vbTab)
  Next
  a.Writeline
  
  a.Close
    
End Sub
```
AtCoder Beginner Contest 223

##[A - Exact Price](https://atcoder.jp/contests/abc223/tasks/abc223_a)

O(1)
一瞬だけ迷いました。
最初に0を判定。
そのあと、xを１００で割った余りを求める。

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    int x;
    cin >> x;
 
    if(x == 0) cout << "No" << endl;
    else if(x % 100 == 0) cout << "Yes" << endl;
    else cout << "No" << endl;
 
    return 0;
}
```

##[B - String Shifting](https://atcoder.jp/contests/abc223/tasks/abc223_b)

O(N)
辞書順なのでmax, minを使って判定します。
１０００文字なのでシミュレーションで解答できます。

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    string s;
    cin >> s;
 
    string l = s;
    string r = s;
    string res_min = s;
    string res_max = s;
    int n = s.size();
 
    rep(i, n){
        res_min = min(res_min, l);
        res_max = max(res_max, l);
        l = l + l[0];
        l.erase(0, 1);
 
        res_min = min(res_min, r);
        res_max = max(res_max, r);
        r = r[n-1] + r;
        r.erase(n, 1);       
    }
 
    cout << res_min << endl;
    cout << res_max << endl;
 
    return 0;
}
```

##[C - Doukasen](https://atcoder.jp/contests/abc223/tasks/abc223_c)

O(N)
はじきで解きます。

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    int N;
    cin >> N;
 
    vector<double> A(N);
    vector<double> B(N);
    rep(i, N){
        cin >> A[i];
        cin >> B[i];
    }
 
    double sum = 0;
    rep(i, N) sum += A[i] / B[i];
 
    double res = 0;
    double time = sum / 2;
    rep(i, N){
        res += min(A[i], B[i]*time);
        time -= min(A[i]/B[i], time);
    }
    cout << res << endl;
 
    return 0;
}
```
Hasuraでテーブルを作成しCRUDの操作までやるで（4/4）

## はじめに

以下のゴールを達成するため、本日は Hasuraの query と mutation を使った基本的な CRUDの操作をやります。

今回は、GraphQlで `mutation`を実行して、データを操作するところまでやっていきます。

## 最終的なゴール

以下のような構成のアプリを作ることです。

![スクリーンショット 2021-10-18 17.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e8a9a2e1-2723-4fec-77ef-be3b9eefdd81.png)

### 目的

- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上

## HasuraでGraphQlのmutationを実行してみる

Hasuraでは、現状、デフォでExplorerのところにqueryしかないのですが、データのCreate, Update, Deleteがしたいときは、GraphQlのmutationを実行が必要になります。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/b84dfafc-bcc4-01d8-c595-b9e1d3fdb91e.png)

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/9b3e12f9-7d81-f645-78fa-c35a7e2f2769.png)

mutationのコマンド一覧も追加されましたね。

### queryも含め、自動生成されているコマンドを詳しく見て、試していきます

#### limit

Explorerのlimitのvalue部分が見えにくいですが、GraphQlでは、limitの引数が2で指定されていることがわかります。

データも2件分取れていますね。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/0b148c03-e9b2-0211-1c63-cf8a5774ccf1.png)

#### offset

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/8878d98e-e513-04cd-9d9d-251fa488ed33.png)

#### order_by

日付の新しい順に取得したい場合

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/6c59e98b-4685-8bc3-cc52-9cf5dd13d878.png)

#### where

`name`が`bob`だけにフィルタして取得したい場合

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/d3a4e225-853f-0881-0ffa-f4a9c93ec314.png)

#### 集計（aggregate）

集計（今回はカウント）もできてますね。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/f3e8ee69-fe13-6570-dfe7-a445ca803c07.png)

#### users_by_pk

`id`をもとに、1つのオブジェクトを取得したいときに使います。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/edda2f27-323f-6be1-9354-be81b4c841b9.png)

### 今度はmutation

#### 新規作成

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/1abb60a1-862e-2f62-30da-2bac3b01a7d4.png)

クエリ叩いて、新規作成できているか確認できます。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/bda03f6c-97f6-6d7b-ac55-ae41089ecb61.png)

#### 更新

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/aaa4b884-d229-d8da-41c7-4297cf018e6d.png)

クエリ叩いて、更新できているか確認できます。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/f193473b-a7e8-c0ee-d2cf-60fcd54b8dd9.png)

#### 削除

最後に、ryosuketterを削除します。idは`5e0a3b32-56ed-4eb7-8c59-0ad4047bd44d`

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/7d399a64-559a-8199-0067-2d49508430cb.png)

クエリ叩いて、削除できているか確認できます。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/f36c9488-c8e6-2255-c41f-16069c35efa6.png)

できましたね！:relaxed:

これで、Hasuraを使ってテーブルの作成、GraphQlのqueryとmutaionを実行してCRUD操作ができました。

次回は、別のテーブルを作成して、1:多の関連づけを行うで。

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
[AWS] SAMのtemplate.yamlをVSCode拡張機能で快適に記述する

SAMのtemplate.yamlを記述する際に、公式ドキュメントを見ながら書くことが多かったのですが、あまりに非効率だったので環境を整えようと思いました。
VSCodeを利用しているので、VSCode前提のお話です。

続き↓

https://qiita.com/engineer-taro/items/bd7cf5a6612e39300242

__要約__
CloudFormationの拡張機能を __使用＆少しカスタマイズ__ してSAMテンプレートをサクサク書こう

# SAMはCloudFormationの拡張
SAMテンプレートはCloudFormationテンプレートの拡張です。
参考：[SAM公式ドキュメント](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-reference.html)

まず、CloudFormationで利用できる文法はSAMテンプレートでも利用することができます。
CloudFormationの拡張機能をVSCodeに導入すれば、CloudFormationで記載できる部分は導入できることになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2055433/7dbae30e-a42f-8ef4-a00e-5ab65d89f455.png)
CloudFormationの拡張機能は、無難に`aws-scripting-guy.cform`を入れておけば良いでしょう。



# SAM独自の記述方法は独自にスニペットを記載していく
VSCodeでは独自にSnippetを記載することができます。
VSCodeの ファイル > ユーザー設定 > ユーザースニペット にて、独自のSnippetを記述可能です。
書き方の参考：[snippetsの書き方](https://code.visualstudio.com/docs/editor/userdefinedsnippets)

こちらで作成したxxxxxxxxx.code-snippetsで、例えば以下のように記載をします。

```javascript
{
	"sam-lambda": {
		"prefix": "sam-lambda",
		"body": ["AWS::Serverless::Function"],
		"description": "Lambda Function"
	}
}
```

すると、このようにサジェストしてくれるようになります。
![f0147b0b5ff679cf449f7b251a364019.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2055433/0cbd00c0-be5b-e8c6-90c4-606155c23893.gif)

# 拡張機能でも同じように実現している
さて、ここからは余談です。
私が暇なときにやろうかなーと思っている話です。

拡張機能のスニペットも、先ほどと同じようにjsonファイルに記載して実現しています。
以下のリンクを見ていただければわかるかと思います。先ほど紹介したCloudFormationの拡張機能のgithubリポジトリです。
https://github.com/aws-scripting-guy/cform-VSCode/blob/develop/snippets/yaml-snippets.json

よって、SAMテンプレートも同様にスニペットの設定ファイルを記載し、VSCodeの拡張機能として出せば同じように使えるようになります。
現在SAMテンプレートの入力補完をしてくれるような拡張機能は、調べた限りでは1つしか存在せず、その1つも実用するには完成度が高くない感じでした。

なので、今後合間を縫ってこちらのsnippetsを作成していこうかと思っております。
今回は私としては中間報告的な記事でした。

# 参考資料
[snippetsの書き方](https://code.visualstudio.com/docs/editor/userdefinedsnippets)
[BlackBelt SAMの回](https://d1.awsstatic.com/webinars/jp/pdf/services/20190814_AWS-Blackbelt_SAM_rev.pdf)


続き↓

https://qiita.com/engineer-taro/items/bd7cf5a6612e39300242
Workato：Rubyコネクターで休日判定を行う

以下の内容の応用編です。通常の休日（土日）と祝日をRubyコネクターを利用してまとめて判定します。
なお、企業によっては土日が休日ではない場合もあるかもしれませんが、その企業の休日に合わせてコードをアレンジしていただければ宜しいと思います。

https://qiita.com/tabimoba/items/bc626e3b1f4285f89cc6

# 手順
## １．Rubyコネクターで以下の設定を行います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/8e2697fd-ee11-71f1-0345-0deae4762f4d.png)

### Name
任意の名称

### Input
#### check_date
休日をチェックしたい日を入力（あるいは変数を指定）します。

なお、フィールドは以下の通り定義します。

|Name|Data type|Optional|Hint|
|:--:|:-------:|:------:|:--:|
|check_date|String|No||


### Output
次の通り定義します。

|Name|Data type|Optional|Hint|
|:--:|:-------:|:------:|:--:|
|date|String|No||
|dow|String|No||
|is_holiday|Boolean|No||
|holiday_name|String|No||

## ２．Codeへ以下の内容を記述します

```ruby
if (input['check_date'].blank?)
  # 本日の日付
  check_date = now.in_time_zone("Asia/Tokyo").strftime("%Y-%m-%d")
else
  # 指定された日付
  check_date = input['check_date'].to_date.strftime("%Y-%m-%d")
end

# 曜日
check_date_dow = input['check_date'].to_date.strftime("%a") 

# 月日
check_date_md = input['check_date'].to_date.strftime("%m-%d")

# 土日の場合は休日と判定
is_holiday = false
holiday_name = ''
if (check_date_dow == "Sun" || check_date_dow == "Sat")
	is_holiday = true
	holiday_name = check_date_dow
end

# 祝日をチェックする
# Googleカレンダーの日本の祝日を取得する
ical = get("https://www.google.com/calendar/ical/japanese__ja%40holiday.calendar.google.com/public/basic.ics")
.response_format_raw

rows = ical.split("\r\n")

events = []
event = {
  'summary' => '',
  'date' => ''
}

rows.each do |row|
  cols = row.split(":")

  if cols[0] == 'BEGIN' && cols[1] == 'VEVENT'
    event = {
      'summary' => '',
      'date' => ''
    }
  end

  if cols[0] == 'END' && cols[1] == 'VEVENT'
    if check_date == event['date']
      is_holiday = true
      holiday_name = event['summary']      
    end
    events.push(event)
  end

  if cols[0] == 'SUMMARY'
    event['summary'] = cols[1]
  end

  if cols[0] == 'DTSTART;VALUE=DATE'
    event['date'] = (
      cols[1].slice(0..3) + '-' + 
      cols[1].slice(4..5) + '-' + 
      cols[1].slice(6..7)
    )
  end  
end


{
  date: check_date,
  dow: check_date_dow,
  is_holiday: is_holiday,
  holiday_name: holiday_name,
}
```

## 結果

例えば、`check_date` に 2021-07-22 という値（＝海の日）を指定すると、次の値が返されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/7e3ccc90-d141-8650-ce93-028e32b6a652.png)

また、以下のようにCallable Recipeとして用意することで、様々なレシピで汎用的に利用することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/ece3d2a6-f43a-114c-8ea2-0e40ded23574.png)
第３回自動運転AIチャレンジ まずは環境構築

完全に個人としてエントリー。1人チーム。

先週末、サンプルソースをビルド、起動し、SVLシミュレータと接続し、シナリオを投入するところまでは達成。

何もしないままだと結果は悲しいことに・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201153/e6f1b0e6-1d3a-ff42-99dd-2284b66808b1.png)

チュートリアル動画で全体の構造(アーキテクチャ)は解説してもらえたが、まだ道のりは長そう。

複数人でやる方が楽しそうだし、どなたか一緒にやる人いませんか！
(ここで募集)
私のチームに入ってもらうでも、私がチームに入るでもいいです。

連絡お待ちしています！(twitterのDM等で)

[Autoware.Auto をインストール](https://qiita.com/Wurly/items/9f20f9a9eab3e633fb87) に続く。
スプレッドシート×BigQueryのデータをTableauで分析する際の選択肢


# 概要

スプレッドシートのデータをBigQueryに連携してTableauで分析する時に詰まったので、備忘のためまとめる。

# ケース

BigQuery連携したTableauデータソースに対して、スプレッドシートからインポートしたテーブルを使用すると、エラーが発生する。

![スクリーンショット 2021-10-18 23.09.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221698/08fcf3e7-724f-ce24-e155-d615716b32cd.png)


原因としては、TableauとBigQueryの連携間のOAuth認証時に、ドライブへの権限が取得されないため。


# 対処法


スプレッドシートから生成したテーブルは、実行の度にスプレッドシートへのアクセスが発生するようなので、結果を独立させる

## 手段A. スプレッドシートからインポートした結果をcreate tableする


```sql:例
create or replace table `project.dataset.create_table_from_spreadsheet`
as (
    select * from `project.dataset.table_from_spreadsheet`
)
```

## 手段B. スプレッドシートからインポートしたテーブルに対するselect文をスケジュール化する

```sql:例
select * from `project.dataset.table_from_spreadsheet`
```
RESTと成熟度モデルのレベルを大まかに理解する

# はじめに

ググった情報を寄せ集めて、（自分に）分かりやすいようにざっくりまとめたものです。
レベル1とか2とか言われてもよく分からないな～と思っていたので、調べました。

# REST とは？

- 2000年にロイ・フィールディングが提唱したWebサービスを作るときの設計原則
- 4つの項目から構成される
    - 1. ステートレス
        - セッションなどの状態管理を行わず、やり取りされる情報はそれ自体で完結して解釈することができる
    - 2. 統一インターフェース
        - 情報を操作する命令の体系が予め定義・共有されている
        - 例）JSON形式でGET,POST,DELETE,PUTのHTTPメソッドを使用することなど
    - 3. アドレス可能性
        - すべての情報は汎用的な構文で一意なURIで識別される
    - 4. 接続性
        - 情報の一部として、別の状態や別の情報への参照（ハイパーリンク）を含めることができる

https://e-words.jp/w/RESTful_API.html

https://tech.012grp.co.jp/entry/rest_api_basics
# 成熟度モデルとは？

- 2008年にレオナルド・リチャードソンによって提唱された
- RESTに準拠して開発する場合、どのように改善すればより成熟するか分かる指標  
<br />
- Level 0：Plain Old XML（昔ながらの単純にXMLを返すやり方）
- Level 1：URLでリソースを表すようにする（リソースを動詞でなく名詞で表す）
- Level 2：HTTPメソッドGET, POST, PUT, DELETE等を正しく使い分ける
- Level 3：レスポンスの中に関連するリンクを含める

https://martinfowler.com/articles/richardsonMaturityModel.html

https://www.crummy.com/writing/speaking/2008-QCon/act3.html

# レベル0

- 1つのURIに対して、POSTリクエストを送信することですべての機能を実行
- URLを使っているが中身はただのXML
    -  XML-PRC や SOAP が該当する

# レベル1

- URIが機能ごとに別れている
- しかしHTTPメソッドは1つ
    -  FlickrやAmazonのS3,ECSが該当する
    -  Railsも以前は該当していたが修正された

# レベル2

- HTTPメソッドを正しく使い分ける
- 多くのサービスがこのレベルに該当している

| HTTPメソッド | 用途 | CRUD |
| --- | --- | -- |
| GET | データの取得 | READ |
| POST | データの新規作成 | CREATE |
| PUT | データの更新 | UPDATE |
| DELETE | データの削除 | DELETE |

## 例：ユーザー情報を操作するAPI

### GET

- URL: `/users/1`
- IDが1のユーザー情報を取得できる

### POST

- URL: `/users`
- リクエストボディなどにユーザー情報を作成するために必要な情報を送信する

### PUT

- URL: `/users/1`
- 登録されているIDが1のユーザー情報を更新する
- IDが1のユーザーとしてログインしていないときは更新できないようにする

### DELETE

- URL: `/users/1`
- 登録されているIDが1のユーザー情報を削除する
- IDが1のユーザーとしてログインしていないときは削除できないようにする

# レベル3

- APIのレスポンスに関連するハイパーリンクを持つ
- HATEOAS（Hypermedia As the Engine Of Application State）ともいう
    - URIスキームの事前知識を必要とせずに、リソースのセット全体を移動できる
    - 各HTTP GET要求は応答に含まれるハイパーリンクより、要求したオブジェクトに直接関連するリソースを検索するのに必要な情報を返し、これらの各リソースで使用可能な操作を記述する情報も提供

https://docs.microsoft.com/ja-jp/azure/architecture/best-practices/api-design

### どういうことかECサイトを例にすると…
- 購入履歴を返すとAPIがあるとする
    - もしまだキャンセルできる商品の場合は、キャンセルのリンクをレスポンスに含む
    - キャンセルできない場合は、リンクをレスポンスに含まない
        - 出来ることのみ表現 = 事前知識を必要をせずに移動できる

https://blog.tagbangers.co.jp/2019/04/05/HATEOAS

# 終わりに

間違いがあったら教えていただけるとありがたいです。
[Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)](https://www.amazon.co.jp/dp/4774142042) が良さそうな書籍だったので、後日購入して読んでみようと思います。
Hasuraでテーブルを作成しCRUDの操作までやるで（3/4）

## はじめに

以下のゴールを達成するため、本日は Hasuraの query と mutation を使った基本的な CRUDの操作をやります。

今回は、GraphQlで `query`を書いて、データを操作するところまでやっていきます。

## 最終的なゴール

以下のような構成のアプリを作ることです。

![スクリーンショット 2021-10-18 17.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e8a9a2e1-2723-4fec-77ef-be3b9eefdd81.png)

### 目的

- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上

## GraphQlのAPI作成

タブ「API」をクリックすると、以下のような画面になります。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/362d9028-f13c-9020-4ef2-f5cf1f1a91e4.png)

ここで、Hasuraで前回作成したテーブルのデータに対して、QueryやMutationを書くことができます。

その前に、少しだけGraphQLとHasuraの基礎を勉強します。

### GraphQL 基礎

- SQLはDB専用のクエリ言語
    - GraphQLはインターネット（API）のためのクエリ言語
- CRUD でいう R（Read）が query で、それ以外（C, U, D）は mutation で処理をする
- APIリクエストを束ねて効率化
    - RESTfulなAPIはURLとmethodでリソースを表現するので、準拠するほどリクエストがたくさん走りがち（パフォーマンス悪影響）
        - 対して、GraphQLでは
            - 単一のエンドポイント
            - 欲しいリソースをHTTP POSTのbodyに明示的に記載してリクエストすることで
                - 必要なリソースを1回のリクエストで取得できる

参考

https://graphql.org/

https://qiita.com/shunp/items/d85fc47b33e1b3a88167

### Hasura の特徴（すごいところ）

- テーブル構造に基づいて、GraphQL の CRUD（query と mutation）を自動生成できるところ
    - Aggregation（集約）なども含む
    - Relay に準拠した API も提供（beta）
- PostgresやMySQLをサポート
- Docker が提供されているため、環境構築が容易

参考

https://hasura.io/docs/latest/graphql/core/index.html

### クエリを書いてみる

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/b859b3eb-34b0-69d1-dc91-6819a1dd3f52.png)

基本的には、以下のような流れでデータが取得できます。

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/bbc5de31-ebec-44d5-fd56-7d30071d7c45.png)

できましたね！:relaxed:

データの取得に不要なデータはチェックを外せばいいだけです。

GraphQlで queryを書いて、データを操作する流れはこんな感じです。

次回は、このデータに対して、GraphQlで `mutation`を書いて、データを操作（CRUDでいう、Create, Update, Delete）していきます！

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
ABC192 C - Kaprekar Number を解いた

https://atcoder.jp/contests/abc192/tasks/abc192_c

![abc192_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/66528090-0402-c777-535b-6d8521b25fd9.png)
![abc192_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/95db072f-3d69-544a-c477-6a0cea482796.png)
![abc192_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/0dbd3f44-60af-8730-0592-0499eabae492.png)

文章のままを書けばいいと思う。

```abc192c.py
N,K = map(int,input().split())

for _ in range(K):#O(10^5)
    num0 = sorted(list(str(N)))
    num1 = sorted(num0,reverse=True)
    g1 = int("".join(num1))
    g2 = int("".join(num0))
    N = g1-g2
print(N)#192ms

```

スピードをあげるために def は must.
def の中に def を埋め込んでみた。

```abc192c.py
def solv():
    N,K = map(int,input().split())

    def helper(n):
        num = "".join(sorted(list(str(n))))
        return int(num[::-1])-int(num)

    for _ in range(K):
        N = helper(N)
    print(N)

solv()#132ms
```

60ms 改善できた。30ms 代の回答を読んだが
全く訳が分からん。また時間を置いてチャレンジしよう。
UITableViewCell 再利用について（サンプルアプリと簡単解説）　

#今回の内容

* `UITableViewCell`の再利用について調べた時に作成したサンプルアプリがあったので、簡単な解説とコードです。

#サンプルアプリ
<img width="150" alt="711DA893-5B13-4E53-8660-61AAE90F3BD9_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/9f0efaa3-202f-cdef-45fc-ce307799d03f.jpeg"> 

* 再利用された`UITableViewCell`は背景色を`.systemGreen`にして、`cell.detailTextLabel.text`に再利用される直前に`cell.textLabel.text`に表示していた値を、表示してどの`cell`がどこに再利用されたかを見ることが出来ます。

* `required init?(coder: NSCoder){ super.init(coder: coder) }`はCellのインスタンスを生成するタイミングで処理が働きます。

* `prepareForReuse()`は`UITableView`が持っている`ReuseQueue`から`Cell`を再利用するタイミングで処理が働きます。（まだtableViewにCellが表示される訳では無いです）

* `tableView`に`Cell`が表示されるタイミングで処理が働くのが、` func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}`です。

* 全てコードで書いています。コピペだけで試せますので宜しければご覧ください。

```Swift:
import UIKit

class ViewController: UIViewController {

    let tableView = UITableView()
        
    var count = Int()
    
    override func viewDidLoad() {
        super.viewDidLoad()
     
        tableView.frame = CGRect(x: view.frame.minX, y: view.frame.minY, width: view.frame.width, height: view.frame.height)
        tableView.register(CustomCell.self, forCellReuseIdentifier: "cell")
        view.addSubview(tableView)
        
        tableView.dataSource = self
    }

}

extension ViewController:UITableViewDataSource{
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return 100
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
           
        count = count + 1
        print(count)
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
        
        if cell.textLabel?.text != ""{
            
            cell.detailTextLabel?.text = cell.textLabel?.text
        }
        
        cell.textLabel?.text = String(indexPath.row)
        
        return cell
    }
    
}

class CustomCell:UITableViewCell{
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: .value1, reuseIdentifier: reuseIdentifier)
        
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        
        if textLabel?.text != ""{
            
            detailTextLabel?.text = ""
            detailTextLabel?.text = textLabel!.text 
        }
        backgroundColor = .systemGreen
        print("reuse")   
    }

}
```

# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
ABC185 C - Duodecim Ferra を解いた

https://atcoder.jp/contests/abc185/tasks/abc185_c

![abc185_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/bfc4250d-8744-0fed-1321-7b3a80024eec.png)
![abc185_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/e01abd03-bcc3-5be1-0b49-2afce6342f7f.png)
![abc185_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/fd074078-0268-8697-9ea2-f26c50d8d54d.png)

0 から L までは、L-1 本の区切りを設けることが出来る。
その中から 11 本を選ぶ組み合わせを求めればよい。

```abc185c.py
L = int(input())

num = L-12

if num == 0:
    print(1)
else:
    a,b = 1,1
    for i in range(L-1,L-12,-1):
        a *= i
    for j in range(11,0,-1):
        b *= j
    print(a//b)
```
FreeBSD を RAMDISKでビルドする

###RAMDISK上でビルドする重要性
みなさんもブラウザのキャッシュをRAMDISKにされているかもしれません。
HDDの時代であれば高速化でしたが、
SSDであれば書き込み寿命が早くこないようにするためです。

M2.SSDであればRAMDISKよりまだ遅いものの、RAMDISK並の快適性がありますが、上記のような書き込み寿命を少しでも避けなければなりません。

###システムをビルド
	#!/bin/sh
	export MAKEOBJDIRPREFIX=/mnt/ramdisk/obj
	make -j $MAKEJOBS buildkernel KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null
	make -j $MAKEJOBS buildworld __MAKE_CONF=/dev/null SRCCONF=/dev/null
	make installkernel KERNCONF=GENERIC
	make installworld

ようは MAKEOBJDIRPREFIX 変数が設定されていると、そこに作業用ファイルが入ります

###portsをインストール（通常版）
	#!/bin/sh
	export WRKDIRPREFIX=/mnt/ramdisk/ports
	cd /usr/ports/（カテゴリ）/（ports名）
	make install clean

###portsをアップグレード
	#!/bin/sh
	export WRKDIRPREFIX=/mnt/ramdisk/ports
	portupgrade -a
	#portupgrade -aRf

ようは、WRKDIRPREFIXが設定されていれば、
展開されたソースファイル、一時オブジェクトが入ります。

###FreeBSDでRAMDISK？
それなりの物理メモリ容量が必要になりますが
/etc/fstab に

	tmpfs           /mnt/ramdisk    tmpfs   rw      0       0
	tmpfs           /tmp            tmpfs   rw      0       0

を追加するのみです。

容量を設定する必要がなく、tmpfsに入ったファイル分のメモリが動的に消費され、それらのファイルが消去されるとメモリが動的に空きます。
Visual Studio Codeのfor予測変換をカスタマイズする。

#1.環境
この記事ではmacOS Big Sur ver\:11.6 にインストールしたVisual Studio Codeバージョン: 1.61.1 (Universal)を使っています。
#2.やりたいこと
VScodeに備わっているデフォルトでのfor予測変換は以下のようなテンプレが表示されます。

```cpp:for_defalt
for (int i = 0; i < n; i++)
{
  /*code*/
}
```

このテンプレの何が不満かと言いますと、**「最初の"{"の位置が")"の後ろに来ていないこと」**です。つまり以下のようなcustomed_forを予測変換として表示することを目指します。

```cpp:customed_for
for (int i = 0; i < n; i++){
  /*code*/
}
```

#2.やること
###0.何をするか
VScodeには自分のテンプレートを予測変換として保存できる「スニペット(snippet)」という機能があります。このスニペットを編集します。mac OSとwindowsでは設定画面の開き方の違いはあるものの、以下の手順で予測変換として目指すfor文をテンプレートとして表示させられます。

###1.スニペットを開く
スニペットの開き方は[こちら]
(https://qiita.com/12345/items/97ba616d530b4f692c97)をご参照ください。
注意していただきたいのは**どの言語のスニペットを開くのか**という点です。下図の通りさまざまなスニペットがありますが、編集したい言語のスニペットを選択します。例えばpythonの予想変換のテンプレートを編集したい場合は検索欄にpythonと打ち、pythonのスニペットが候補として出てきますので選択して編集していきます。
今回はc++を編集したいので「cpp.json(C++\)」を編集します。
![snippet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183108/3f216abe-6fee-5801-8dff-50b055367cba.png )

###2.スニペットを編集する
どの言語のスニペットを編集するか選択すると図のような画面になると考えます。
![snippet2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183108/61acdf3b-b922-a96c-aaa0-b3937f61c54c.png)
ここに

```cpp:snippet
"customed_for": {
  "prefix": "for",
  "body": "for (${1:size_t} ${2:i} = 0; ${2:i} < ${3:count}; ${2:i}++){\n\t${4:/* code */}\n}"
    }
```
を追加します。
**コード追加後にスニペットを保存してください。**(macならcommand+s, windowsならCtrl+sで保存できます。)
なお、上記のコードを追加後の図を下に示します。
![snippet3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183108/a244d164-232a-d3bb-e611-6d3ee7b93e93.png)

###3.Snippet Suggestionsをtopにする。
VScodeの設定画面を開き、検索欄で「Snippet Suggestions」と検索します。すると

```
Editor: Snippet Suggestions
他の修正候補と一緒にスニペットを表示するかどうか、およびその並び替えの方法を制御します。
```

こんなのが出てくるはずです。これを**top**にします。

###4.Snippet Suggestionsをtabで切り替わるようにする。
- [こちら](https://qiita.com/ryosyo/items/35bac68a05961be1e3c1)を参考にtabで予測変換を降下できるようにしてください。

###5.動作確認
適当なファイル(ただし編集した言語のファイル）を作成し"for"と打ってから0.5秒くらい待ち、予測変換候補を見てくだい。下図のように２つ目にcustomed_forが表示されているはずです。
![for1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183108/f92080d1-9f65-00d3-76d5-5779e04662a3.png)
tabで２つ目のforまで下ってenterでforを出力すると下図のようになります。**この灰色の部分はtabでジャンプできることを表しています。**
![for2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183108/261c3ac2-0b01-422d-8169-b8c70c40020c.png)

##3.まとめと余談
以上で目的としていた「予測変換のforをカスタマイズする」が完了しました。
現状はデフォルトの予測変換をカスタマイズすることはできない、らしいのですが無理矢理にでもデフォルトのforを書き換えられないものかと考えました。
そこでVScodeの設定ファイルをターミナルで検索したのですが設定ファイルが見つかりませんでした。(おそらくjsonファイルではないかと思って検索かけたのですが、見つかりませんでした。）
VScodeのデフォルトスニペット設定ファイルの場所を知っている方いましたらお教えいただけると幸いです。

##4.参考文献一覧
https://qiita.com/12345/items/97ba616d530b4f692c97
https://qiita.com/ryosyo/items/35bac68a05961be1e3c1
https://keikenchi.com/how-to-find-out-the-default-snippet-list-in-vs-code
サポート終了したCentOS6でyum

CentS6のサポートが終了して、yumでインストールなどが出来なかった場合の対応
※
http://vault.centos.org/
から取得する。
vaultは、サポートが終わったデータのスナップショットを保管している場所

```
$ cd /etc/yum.repos.d/
$ vi CentOS-Base.repo
```

mirrorlist の行はコメントアウト

```CentOS-Base.repo
:%s/^mirrorlist/#mirrorlist/g
```
\#baseurl=http://mirror.centos.org/ の行を baseurl=http://vault.centos.org/ に変更。

```CentOS-Base.repo
:%s/^#baseurl/baseurl/g
:%s/mirror.centos.org/vault.centos.org/g
```

こういうイメージ

```CentOS-Base.repo
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
baseurl=http://vault.centos.org/centos/$releasever/os/$basearch/
```


* CentOS-SCLo-scl-rh.repo
* CentOS-SCLo-scl.repo

も同様に修正。
Udemy「ネットワークエンジニアを目指す初心者はここから始めよう！「ゼロから学ぶネットワーク基礎」1018

ケーブル種類
・同軸ケーブル（最近はほぼ見ない）
・ツイストペアケーブル
・光ファイバーケーブル


ツイストペアケーブル
・Shielded Twisted pair(STP)
　・ノイズ対策で保護されている。
・Unshielded Twisted Pair(UTP)
　・保護は無い。
・STPよりUTPが多く使われている。
・品質の違いによりカテゴリー分けされる。
・上位カテゴリーであれば利用できる。
　・例　10Base-TはCategory6でも利用できる。

ストレートケーブル/クロスオーバーケーブル
・ストレートは両端が同じピン番号になる。
・クロスオーバーは内部で入れ替わる。

MDI/MDI-X
・MDIとMDI-Xはストレートケーブルで接続する。
・MDI同士、MDI-X同士はクロスオーバーケーブルで接続する。
・最近はAuto　MDI/MDI-Xが多い。
　（クロスオーバーケーブルの必要性なし）

光ファイバーケーブル
・Single Mode Fiber(SM,SMF)
　・長距離向け、高価、通信事業者がビル（局舎）間を接続するのに使われる。
・Multi Mode Fiber(MM,MMF)
　・短距離向け、安価、データセンター内や企業LANなどで使われる。
・SMとMMでは内部の構造に違いがある。
　・細い繊維状で内部をコア、外郭をクラッドと呼ぶ。
　・SMはMMよりもコアが細い。


コネクタ種類
・ツイストペアケーブルはRJー４５
　・Category7ではGG45やTERA
・光ファイバーケーブルはSC、LC
　・Square-shaped Connector
  ・Local Connector

インターフェースモジュール
・Gigabit Interface Converter(GBIC)
・Small Form-factor Pluggable(SFP)
・Small Form-factor Pluggable Plus(SFP +）

CSMA/CD(1)
・Carrier Sense Multiple Access/Collision Detection
 ・Carrier Sense Multiple Access ホストは送信前に他の通信状態を確認
 ・Collision Detection 衝突を検出したらランダムな時間待機して再送

CSMA/CD(2)
　・現在はスイッチを使った構成が一般的となっている。
　・全二重通信ができるのでデータ衝突は起こらない。