OmniAICreator/Qiita-1.07M huggingface dataset:
Git ローカルリポジトリを作ったらやること

# 目的

- Gitのローカルリポジトリを作ったらやることをメモ的にまとめる

# 情報

- 筆者はHomeBrewを用いてMacにGitをインストールしてある。

# 前提

- `$ git init`コマンドはすでに実行してあり、カレントディレクトリに「.git」ディレクトリが存在することとする。
- 実行するコマンドは特筆しない限り前のコマンドと同じディレクトリで実行するものとする。

# やること

1. ユーザー名の設定
    1. 「.git」ディレクトリが存在するディレクトリで下記コマンドを実行してユーザー名を設定する。

        ```terminal
        $ git config --local user.name "ユーザー名"
        ```

    1. 下記コマンドを実行してユーザー名が正しく設定されていることを確認する。

        ```terminal
        $ git config -l
        ```

    1. 下記のように出力されれば無事に設定できている。

        ```
        user.name=入力したユーザー名
        ```

1. メールアドレスの設定
    1. 下記コマンドを実行してメールアドレスを設定する。

        ```terminal
        $ git config --local user.email "メールアドレス"
        ```

    1. 下記コマンドを実行してユーザー名が正しく設定されていることを確認する。

        ```terminal
        $ git config -l
        ```

    1. 下記のように出力されれば無事に設定できている。

        ```
        user.email=入力したメールアドレス
        ```

1. 空コミット
    1. 下記コマンドを実行して空のコミットを作成する。

        ```terminal
        $ git commit -m "first commit" --allow-empty
        ```

    1. 下記コマンドを実行してコミットのログを確認する。

        ```terminal
        $ git log
        ```

    1. 下記のように出力されれば空コミットが作成されている。

        ```
        commit コミットID (HEAD -> master)
        Author: ユーザー名 <メールアドレス>
        Date:   曜日 月 日 時間 年 +0900
        
            first commit
        ```

1. README.mdファイルの作成
    1. 下記コマンドを実行してREADME.mdを作成して開く。

        ```terminal
        $ vi README.md
        ```

    1. 下記の内容をREADME.mdに記載して保存する。この内容は何でも良い。

        ```README.md
        # リポジトリの説明

        - gitのあれこれをテストするためのリポジトリです。
        ```

    1. 保存後、「.git」ディレクトリと同じ階層にREADME.mdが作成されていることを確認する。
1. README.mdファイルのgit登録
    1. 下記コマンドを実行してREADME.mdファイルをインデックスに追加する。

        ```terminal
        $ git add README.md
        ```

    1. 下記コマンドを実行してREADME.mdの追加変更をコミットする。

        ```terminal
        $ git commit
        ```

    1. エディタが開くので一行目に「説明ファイルの追加」と記載して保存する。
    1. 下記コマンドを実行してコミットのログを確認する。

        ```terminal
        $ git log
        ```

    1. 下記のように出力されれば空コミットが作成されている。

        ```
        commit コミットID (HEAD -> master)
        Author: ユーザー名 <メールアドレス>
        Date:   曜日 月 日 時間 年 +0900
        
            説明ファイルの追加

        commit コミットID
        Author: ユーザー名 <メールアドレス>
        Date:   曜日 月 日 時間 年 +0900
        
            first commit
        ```

1. リモートリポジトリとの紐付け（ある人だけ）
    1. 下記コマンドを実行してローカルリポジトリろリモートリポジトリを紐付ける。

        ```terminal
        $ git remote add origin リモートリポジトリのアドレス
        ```

    1. 下記コマンドを実行してユーザー名が正しく設定されていることを確認する。

        ```terminal
        $ git config -l
        ```

    1. 下記のように出力されれば無事に設定できている。

        ```
        remote.origin.url=リモートリポジトリのアドレス
        ```

    1. 下記コマンドを実行してローカルのmasterブランチの情報をリモートのmasterブランチにpushする。

        ```terminal
        $ git push origin master
        ```
10進数と2進数の変換

# 目的

- 基数変換が非常に苦手なためメモ的に記事にする

# 10進数から2進数に変換する。

1. 大前提
    1. 小数点の前後（整数部分と小数部分）で区切って考える。
1. 整数部分 
    1. 「2で割る→答えを更に2で割る」を繰り返す。答えが1になるまで繰り返す。
    1. 割った順にあまりを並べる。
1. 小数部分
    1. 「2を掛ける→答えの小数部分に更に2を掛ける」を繰り返す。2に掛ける数が0になるまで繰り返す。
    1. 2を掛けた答えの整数部分を計算とは逆順で並べる。

# 10進数から2進数に変換する例（10進数の値「10.375」を2進数に変換）

1. 整数部分は10である。まずは10を2進数で表すことを考える。下記のように計算をすすめる。

    ```
    10 ÷ 2 = 5 あまり 0
     5 ÷ 2 = 2 あまり 1
     2 ÷ 2 = 1 あまり 0
    ```

1. 上記のようになる。最終の割り算の答えを頭としてあまりを下から並べると「1010」となるため10進数の10は2進数で表すと1010となる事がわかった。
1. 小数部分を小数点を用いて表記すると0.375である。次に0.375を2進数で表すことを考える。下記のように計算をすすめる。

    ```
    2 × 0.375 = 0.75
    2 × 0.75  = 1.5
    2 × 0.5   = 1.0 
    ```

1. 上記のようになる。最初の計算の答えの整数部分を頭として上から整数部分だけを並べると「011」となるため10進数の0.375は2進数で表すと0.011となる事がわかった。
1. 以上により整数部分と小数部分が揃ったので小数点を用いて整数部分と小数部分を一緒に表記すると「1010.011」となり、10進数の10.375は2進数で表すと1010.011ということになる。

# 2進数から10進数に変換する。

1. 大前提
    1. 小数点の前後（整数部分と小数部分）で区切って考える。
1. 整数部分
    1. 2進数の各桁に2のn乗（n=桁の重み）を掛けてゆき、全ての値を足す。
1. 少数部分
    1. 2進数の各桁に桁の重み分の1を掛けてゆき全ての値を足す。

# 2進数から10進数に変換する例（2進数の値「1110.1011」を10進数に変換）

1. 整数部分は1110である。まず1110を10進数で表すことを考える。下記のように計算する。（掛けられる数 × 掛ける数としたとき、掛けられる数は2進数の値であり、下記の計算は1110の最小桁から計算を行っている。）

    ```
    0 × 2の0乗 + 1 × 2の1乗 + 1 × 2の2乗 + 1 × 2の3乗 = 14
    ```

1. 上記のようになる。計算結果から2進数の1110は10進数で表すと14になることが分かった。
1. 小数部分は小数点を用いて表記すると0.1011である。次に0.1011を10進数で表すことを考える。下記のように計算をすすめる。

    ```
    1 × 1/2の1乗 + 0 × 1/2の2乗 + 1 × 1/2の３乗 + 1 × 1/2の４乗 = 0.6875
    ```

1. 上記のようになる。計算結果から2進数の0.1011は10進数で表すと0.6875になることが分かった。
1. 以上により整数部分と少数部分が揃ったので小数点を用いて整数部分と小数部分を一緒に表記すると「14.6875」となり、2進数の1110.1011は10進数で表すと14.6875ということになる。
angular universalをnetlifyへ導入する

#angular universalをnetlifyへ導入する

angularは、SPA(Single Page Application)のため、クローラからインデックスされにくいため、SSR(Server Side Rendering)を導入することで、インデックスされやすくする。

angularのSSRとしてUniversalがあります。
[angular公式サイトの Universal 紹介ページ ](https://angular.jp/guide/universal)

### universalの追加
自プロジェクトに下記コマンドで追加します。

```
ng add @nguniversal/express-engine
```

コマンドが正常にすれば、
`server.ts`
`src/app/app.server.module.ts`
`src/main.server.ts`
`tsconfig.server.json`
が追加される。

追加が完了したら、prerenderを実行してみます。

```
npm run prerender
```

つづいて、netlify.tomlを作成します。
自プロジェクトの直下に保存しておけば、build時に読み込まれます。

``` netlify.toml
[build]
 command = "npm run prerender"
 functions = "./functions"
 publish = "dist/[自プロジェクト]/browser"
```

### その他
SSRにより、server側のrender処理では、window,localStorageなどが使えないため、isPlatformBrowser()を使用してserver側とbrowser側の処理を分ける必要がある。

```typescript
import { PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

export class SomeComponent {
    constructor(
        @Inject(PLATFORM_ID) private platformId: any) {
        // 処理...
    }

    ngOnInit():void {
        if (isPlatformBrowser(this.platformId)) {
            // browser側の処理...
        }
        if (isPlatformServer(this.platformId)) {
            // // server側の処理...
        }
    }
}
```

### 参考ページ
netlifyのcommunityに投稿されていた記事
[https://www.netlify.com/blog/2021/02/08/pre-rendering-with-angular-universal/](https://www.netlify.com/blog/2021/02/08/pre-rendering-with-angular-universal/)

以上
React Redux Hooks公式ドキュメント翻訳（useDispatch, useStore編）

Reactアプリケーションの状態管理のためのOSSライブラリである、React Reduxのバージョン7.1.0で追加された、Hooks APIの公式ドキュメントを翻訳していきます。

1. [React Redux Hooks公式ドキュメント翻訳（概要編）
](https://qiita.com/japanesebonobo/items/04205fa292455f862f33)
2. [React Redux Hooks公式ドキュメント翻訳（useSelector編）](https://qiita.com/japanesebonobo/items/843753903fdfa173f516)
3. React Redux Hooks公式ドキュメント翻訳（useDispatch, useStore編）

2021/2/24公開。原文リンクは以下。
・公式ドキュメント（React Redux Hooks）：https://react-redux.js.org/api/hooks

今回の記事はuseDispatchAPI, useStoreAPI編です。![スクリーンショット 2021-02-23 23.57.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296645/0b44ac93-446f-597a-c145-24db465fb105.png)
![スクリーンショット 2021-02-23 23.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296645/180f3edd-4f7a-03a0-d88d-35b4c4a282fd.png)

#useDispatch()

```react
const dispatch = useDispatch()
```

このhookAPIはRedux storeからdispatch関数を参照し、返り
値として返します。このAPIはアクションをdispatchしたい場合に使うと良いでしょう。

Note: ReactのuseReducerのようにdispatch関数の戻り値は同一であり、再
レンダリングされても不変です。（不変にならないケースとしては、Providerで設定したstoreを変更した場合に限ります。もっとも、そのような使い方は極めて稀ですが。）

###使用例

```react
import React from 'react'
import { useDispatch } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const dispatch = useDispatch()

  return (
    <div>
      <span>{value}</span>
      <button onClick={() => dispatch({ type: 'increment-counter' })}>
        Increment counter
      </button>
    </div>
  )
}
```

覚えておいて欲しいこと：　子の関係にあるコンポーネントにdispatch関数を使ってcallbackをした際は、そのことをuseCallbackAPIを用いて記録する必要があります。通常、callbackを使用する際にcallback関数を宣言することと同じです。これによって、子の関係にあるコンポーネントの不必要なレンダリングを避けることができます。安全な方法としては、useCallbackAPIのための独立した[dispatch]配列を作成してあげることです。なぜなら、dispatch関数は不変だからです。こうすることでcallbackする際にその配列を適切に再使用してくれます。

###使用例

```react
import React, { useCallback } from 'react'
import { useDispatch } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const dispatch = useDispatch()
  const incrementCounter = useCallback(
    () => dispatch({ type: 'increment-counter' }),
    [dispatch]
  )

  return (
    <div>
      <span>{value}</span>
      <MyIncrementButton onIncrement={incrementCounter} />
    </div>
  )
}

export const MyIncrementButton = React.memo(({ onIncrement }) => (
  <button onClick={onIncrement}>Increment counter</button>
))
```

#useStore

```react
const store = useStore()
```
このhookAPIはProviderコンポーネントで設定したものと同じRedux Storeを参照し、返り値として返します。このhookAPIは頻繁には使いません。useSelectorの方が頻繁につかうことになるでしょう。しかし、これは時々、特定のケースでstoreにアクセスする場合、役に立ちます。例えば以下のように、reducerをリプレイスするケースです。

###使用例
```react
import React from 'react'
import { useStore } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const store = useStore()

  // EXAMPLE ONLY! Do not do this in a real app.
  // The component will not automatically update if the store state changes
  return <div>{store.getState()}</div>
}
```
プロジェクト管理のタスクリスト

# 追記（2025年04月21日）

この記事は一部古い情報もありますので気をつけてください。
現代の開発ではCICD/自動テスト/コードレビューなどは必須レベルであった方が良いし、インフラはクラウドが主流になっていると思います（記事公開時点でも世の中的にはそうでしたが...）。
また、この記事は小規模受託に特化しているので、一定以上の規模のアプリケーション開発においては気をつけるべきポイントに抜けがあります。

そんなこの記事の上位互換とも言える記事が公開されました。ぜひこちらも目を通していただけると良いことがあると思います。
今一定以上の規模でちゃんとしたものを作るならどこを気をつけておかないとやばいか、という内容が網羅されている良記事です。ぜひに！
[新規アプリ開発を請け負う時の流れ](https://qiita.com/neon-izm/items/67cdb159aabf66f3e92b) @neon-izm 

追記終わり

# はじめに

こんにちは。にしやまと申します。
受託開発の企業に勤めている2年目のまだまだ未熟なエンジニアです。
初めての投稿なのでお手柔らかに。

`プロジェクトを進める時に必要なこと`みたいなものを私的なメモとしてまとめてみたので、軽い気持ちでQiitaにも共有してみようかなと思います。
社内Wikiにもほとんど同じものを共有しました。
社内独自の文化など、コンプラ的にダメそうなのはないと思うけど、もしあったら消すかもです。

もっとこうしたらいいんじゃない？みたいなのがあればコメントいただけると嬉しいです！

# 前提条件
- 中小規模の受託案件を想定
- 1次受けか2次受けくらい
- 社内で実装を行うことが多い
- オフショアなどに振ることもある
- CICDとか自動テストとかは導入できていません
- コードレビュー、できたらいいな
- ストア申請とかはできないお客様だからやってあげる想定（その分のお金ももらう）
- Web管理側、Webユーザー側、iOSアプリ、Androidアプリで作る場合を想定


# 本題

案件進行で必要な作業、だいたいこんな感じかな？↓↓↓

### 要件定義

- 顧客の要望の書かれた資料と提出した見積もりを読み込む
- 上記資料をもとに顧客から詳細（要望の意図、改善したい点など）をヒアリング（議事録必須）
- 顧客の要望を機能要件としてまとめて内容に合意を取る

### システム設計（以下を作成する）

- 機能一覧
- アーキテクチャ構成図
- DB設計書（テーブル構成）
- データフロー図
- 画面設計（基本設計）
    - Web管理画面、Webフロント、アプリ（それぞれ必要なもののみ）
    - 画面ごとにその画面で利用する機能とその仕様を記載
    - パワポ、AdobeXD、figmaなど
- API設計
    - Web管理画面、Webフロント、アプリ（それぞれ必要なもののみ）
    - Swaggerなど

### 課題・進捗管理

- 受注後まず最初にリリースまでのスケジュールを作成し顧客に提出
    - スケジュールに無理があればこの時点で上司・顧客に交渉する（とても大事）
- 定期的に顧客に進捗報告を行う
- 構築フェーズ
    - 顧客と相談して確認版完成予定日を決める
    - 機能一覧・API設計など上記設計をもとに構築に必要な項目を一覧に書き出す
    - 各課題に担当者と納期から逆算した期限を設定する（バッファを持たせる）
- 動作確認フェーズ
	- 社内で動作確認を行う
		- 仕様書（画面設計・API設計）をもとに動作の確認を行う
	- 不具合を課題管理ツールに起票
	- 各担当者は修正を行う
		- 修正完了したら課題管理ツールにて報告し再度確認依頼
- フィードバックフェーズ
	- 社内動作確認が完了したら顧客に確認依頼をする
	- 顧客との課題管理ツールを選定し（社内のものとは分ける）、そこにフィードバックを上げてもらう
	- フィードバック内容を確認し、不具合・追加要望・不可能など分ける
	- 不具合の場合
		- スケジュール内で修正する（担当者に修正依頼）
		- 不具合が重くスケジュール内で終わらない場合まずは上司に現状報告して対応方法を検討
		- 検討の結果どうにもならなそうであれば顧客に報告してリスケ作成と調整依頼
	- 追加要望の場合
		- 不明な部分があれば顧客に詳細の確認
		- 見積もり作成
		- 追加分のスケジュール作成と調整依頼
	- 不可能の場合
		- 不可能な原因を顧客に説明（他の仕様とぶつかる、技術的・法的に難しいなど）

### その他リリースまでに必要な雑務

#### アプリ

- デザインを外注に依頼
	- デザインのテーマカラーなどを事前に顧客に確認しておく
- Apple, GoogleのDeveloperアカウント作成依頼
	- 会社のアカウントを招待してもらう
- Firebaseアカウントとプロジェクト作成依頼
	- 以下の作業はDevelop, Staging, Productionそれぞれで必要
	- 会社のアカウントを招待してもらう（顧客アカウントの場合）
	- Push通知使う場合
		- Firebase Admin SDKで使う秘密鍵の取得（Web実装者に渡す）
		- APNs認証キーの登録
	- App Distributionでテスト配信する場合
		- 顧客にテスト配信するユーザーのメールアドレスを聞く（iOSの場合は後述のUDID登録も必要）
	- 他のFirebaseサービスを利用する場合は適宜
- ストア申請文言必要事項一覧のエクセルに記入してもらう
    - 補足: 弊社は社内に`ストア申請文言必要事項一覧のエクセル`が存在する
- ストア配信用のスクショ作成
- プライバシーポリシーなどのWebページを用意してもらう
- iOS証明書関連
	- テストに使う端末をdevicesに登録
		- 顧客の端末の場合UDIDを教えてもらう（PCに繋げてiTunesで確認できる）
	- Adhoc配信用のprovisioning profileを作成
		- 作成時に顧客端末のdeviceも登録する
	- ストア配信用のprovisioning profileを作成
- Android
	- apk（もしくはApp Bundle）作成時のkey storeとkey aliasを管理しておく
        - なくすと同じアプリとしてビルドできないよ
- ストア申請

#### Web

- デザインを外注に依頼（Webフロント）
	- デザインのテーマカラーなどを事前に顧客に確認しておく
- サーバーの準備
	- 利用するサーバーを決める
	- サーバー契約
	- アーキテクチャ構成に沿ってサーバー構築
		- 社内確認用サーバー上の開発環境
		- 本番サーバーの本番環境
		- 本番サーバー上にVirtual Hosts切ってステージング環境
			- ステージング環境のサーバーは顧客と相談して場所を決める（本番サーバー上か専用サーバーを用意するかなど）
	- ドメイン取得
	- SSL証明書取得（自動更新）
- サーバーへのデプロイ
swift辞書「画面遷移をプログラムで行う」

#お断り
この記事は自分専用メモなのですごい初歩的な事しか書いていませんがご了承下さい。
確認環境
Interface:Storyboard
Life Cycle:UIKit App Delegate
Language:Swift
◉Use Core Data
__◉Host in CloudKit
◉Include Tests

#この記事で出来る様になる事
swiftのコードから画面が切り替えられる様になる。

#実装
###UIの実装
View Controllerをもう一つ配置して動きが分かりやすい様にbackgorundから好きな色を選びましょう。始めからあったView Controllerから新しく作ったView Controllerに向けてcontrolキーを押しながらドラックをします。そうすると色々な選択肢が出来てくるのでPresent Modallyを選択して下さって下さい。
見た目はこのままでは問題無いのですが、このままでは下にスワイプすると元の画面に戻ってしまうので変更を加えます。先ほど背景の色を変えた方のView ControllerのPresentationをFull Screenに変更して下さいこれで成功している筈です。![スクリーンショット 2021-02-23 23.54.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/985466a8-19f8-4334-86bc-7302309e0e0f.png)最後にエラーを駆逐していきます。エラーをコピーしてdeepl翻訳にぶち込むとビューコントローラを区別する名前が付いていないよ的な事が返ってきたのでビューコントローラに名前を付けてやりましょう。二つの画面を繋ぐ矢印を選択するとIdentifierと言ういかにも名前を付けれそうな場所を発見したのでそこに適当に名前を付けましょう。名前を考えるのはめんどくさいので今回はmoveとでもしましょう。これでエラーも駆逐できたので、ひとまづUIは完成です。
###コードの実装
今更気づいたのですが動くきっかけを忘れていました。UIの実装を直すのはめんどくさいので、スマホが振られた時に画面の遷移をする様にしたいと思います。皆さんは好きなどんなトリガーでも大丈夫です。例buttonが押された、画面がスワイプされたなど。では結論のコードを貼ってから解説していきます。

```swift
import UIKit
import CoreMotion

class ViewController: UIViewController {
    
    let MotionSensor = CMMotionManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        getAccelerometer()
    }
    func getAccelerometer() {
            MotionSensor.accelerometerUpdateInterval = 0.2
            MotionSensor.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {
                accelerometerData,error in
                let x = accelerometerData!.acceleration.x
                let y = accelerometerData!.acceleration.y
                let z = accelerometerData!.acceleration.z
                let synthetic = (x * x) + (y * y) + (z * z)

                if synthetic >= 6 {
                    self.move()
                }
            })
    }
    func move() {
        performSegue(withIdentifier: "move", sender: nil)
    }
}
```
実機で試した所無事に緑色になりました。動きの部分は今回の話とは一ミリも関係ないのでよかったら調べて見て下さい。解説の移ります。遷移の処理をしているのはfunc move()関数の中です。でも見れば分かる様にwithIdentifierに先ほど指定したmoveの名前を入れて、よくわからないsenderにはnilを入れとけば動く事が分かりましたね！今回はこれで終わりです。
SwiftUIにてList内でForEachを使う場合の注意

Qiita APIを使って記事一覧（タイトル、日時、タグ）を表示するアプリを作成している中で、スクロールするとタグの表示がズレるという現象が生じた。
（このような、エラーに引っかからない不具合が一番困る。。）
![1AB91F4E-F26E-4485-B431-A724C248DED3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051634/be16b41f-68e1-33ad-e43e-c6de5b842b74.jpeg)

```
import SwiftUI
struct ContentView: View {    
    @ObservedObject var networkManager = NetworkManager()
    var body: some View {
        NavigationView {
            VStack {
                List(networkManager.posts) { post in
                    NavigationLink(destination: DetailView(url: post.url)) {
                        VStack {
                            Text(post.title)
                                .font(.callout)
                                .fontWeight(.medium)
                                .frame(maxWidth: .infinity, alignment: .leading)
                            HStack {
                                Image(systemName:"tag")
                                    .resizable()
                                    .frame(width: 13.0, height: 13.0, alignment: .leading)
                                // 以下タグ表示の処理
                                ForEach(0..<post.tags.count) { i in
                                    if let tag = post.tags[i].name {
                                        Text(tag)
                                            .font(.caption)
                                    }
                                }
//以下省略
```

タイトルや日時にズレは見られないので、タグを表示する際に利用しているForEachに問題がありそうと考え、恐る恐るStackOverFlowに初めて質問を投げてみた。。

すると、ものの1時間で解決した。

やはり、Listのidとの紐付けが上手くいかないってなかったようなので、ForEachの書き方を以下のように変更することで解消できた。

```
ForEach(post.tags.indices, id: \.self) { i in
```

Listの中でForEachを使う際はindexを使おうと強く心に誓った。
PythonｘSeleniumの使い方

時々、Pythonをいじります。
Seleniumを使用した簡単なWebスクレイピングです。　

browser = webdriver.Chrome('/home/hoge/Dropbox/Pr04/chromedriver')
ここのドライバーは、次のリンクをから取りました。
ChromeDriver - WebDriver for Chrome
https://sites.google.com/a/chromium.org/chromedriver/

#### 前処理

```
from selenium import webdriver
# 
browser = webdriver.Chrome('/home/hoge/Dropbox/Pr04/chromedriver')
#chromeドライバー
url = 'https://scraping-for-beginner.herokuapp.com/login_page'
#
browser.get(url)
#webページを開く
```
#### 項目選択

目的の項目をメッソドでひろい出す。
複数の時elementsを使用する。

```
find_element_by_id(id)	id属性で要素を検索する
find_element_by_name(name)	name属性で要素を検索する
find_element_by_class_name(name)	class属性で要素を検索する
find_element_by_tag_name(name)	タグ名で要素を検索する
find_element_by_xpath(xpath)	XPathで要素を検索する
find_element_by_css_selector(css_selector)	CSSセレクタで要素を検索する
find_element_by_link_text(link_text)	リンクテキストで要素を検索する
find_element_by_partial_link_text(link_text)	リンクテキストの部分一致で要素を検索する
```
取れそうで取れない項目が意外と多い。そのためxpathを利用する。
拡張機能をセットしてくと良い。

[xpath helper](https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl?utm_source=chrome-ntp-icon)

使い方
1.xpath helperを起動する。
2.siftキーを押す。
3.マウスで目的の項目の上をなぞる、
4.xpathが表示される。

#### 何をさせるか。

```
テキストをひろう。
elem_username.text

テキストを入力する。
elem_username.send_keys('miura')

クリックする。
elem_login_btn.clic()

```
#### 終了
```
browser.quit()
```
次の順番で処理を進める。
項目選択
何をさせるか。
Raspberry Pi OSの起動方法をコマンドラインでセットアップ

## 概要

Raspberry Pi OSの起動方法(CLIブート/GUIブート)をコマンドラインでセットアップする方法について記載します。

## 手順

### CLIブートを有効化

1. CLIブートを有効化する。

    ```shell
    sudo raspi-config nonint do_boot_behaviour B1
    ```

1. リブートする。

    ```shell
    sudo reboot
    ```

### GUIブートを有効化

1. GUIブートを有効化する。

    ```shell
    sudo raspi-config nonint do_boot_behaviour B3
    ```

1. リブートする。

    ```shell
    sudo reboot
    ```

### 確認方法

1. CLIブートかGUIブートか確認する。

    ```shell
    raspi-config nonint get_boot_cli
    ```

- CLIブートの場合

    ```text
    0
    ```

- GUIブートの場合

    ```text
    1
    ```
Laravel + react でSPA認証(sanctum)を導入したときに設定する箇所をまとめ

Laravel + react でSPA認証を導入したときに設定でいくつか躓いたので設定する箇所をまとめときます！

導入部分については今回触れないので下記記事参考にしてインストールしてください。
https://readouble.com/laravel/7.x/ja/sanctum.html

# 設定 1 ミドルウェア追加
SPA認証する際は、app/Http/Kernel.php　に以下のミドルウェアを追加します。


```
'api' => [
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],
```

# 設定 ２ Ajax処理に設定追加
React側でサーバー通信をする際は以下の設定を追加します。

```
axios.defaults.withCredentials = true;
```

# 設定 3 .envに設定追加
.envに以下の設定を追加

```
SANCTUM_STATEFUL_DOMAINS=exmple.com
SESSION_DOMAIN=.exmple.com
```
※ ローカルではこの設定をしなくても動きますが、外部に公開する際は必ず必要な設定です。
何度調べても文字コード周りの知識を忘れる

文字コード周りについてわかりやすくまとめた記事は世の中に無限にあるが、どうしても覚えられない。自分でまとめを書くことで覚えるしかないね。
# 用語
#### 文字集合 (文字セット)
「文字」と「文字に割り当てた数値」の対応表のこと。
Unicode、JIS(ISO-2022-JP)など

#### 符号化方式 (文字エンコーディング)
文字集合で定義されている一つ一つの「文字に割り当てた数値」を、どのようにバイト列として実装するか。例えばUnicodeという一つの文字集合に対して、複数の文字符号化方式が存在する (UTF-8, UTF-16など)。

- **ASCII** ... 数字, アルファベット, 記号などの128文字を1バイトで表したもの。
- **Shift_JIS** ... ASCIIコードの文字に加え、日本語の文字を加えたもの。半角カタカナは1バイトで表現し、それ以外の全角文字は、2バイトで表現する。
- **UTF-8** ... ASCIIコードの文字に加え、世界中の文字を加えたもの。ASCIIコード以外の文字は、2～6バイトで表現され、日本語の文字は、基本的に3バイトで表現する。
- **UTF-16** ... Unicodeのほとんどを2バイト、残りのマイナーな文字を4バイトで表現した文字コード。つまりASCIIは使用していない。日本語も2バイトで表現される。LE (リトルエンディアン) と BE (ビックエンディアン) があり、ファイル先頭のBOM (Byte Order Mark) で区別される。

#### コードページ
システムベンダ各社 (Microsoft) などが管理している符号化文字集合を指す数字。例えばCP932はMSがShift_JISを独自に拡張した符号化方式を指す。

#### サロゲートペア
2バイトUnicodeのうち使われていない領域を使って、4バイト分で1つの文字を表す手法。

#### マルチバイト文字セット
1文字を複数バイトで表す文字セットで、シングルバイト文字等と対になる言葉。

#### ワイド文字セット
C言語の規格。C言語ではマルチバイト文字を「1バイト以上の可変長のバイト列で表す文字セット」と定義しており（つまりシングルバイト文字もマルチバイト文字に含まれる）、それに対して1文字を2バイトや4バイトの固定長で表した文字セット。VC++だと2バイト固定で、符号化方式にUTF-16を利用する。wchar_t型。(マルチバイト文字はchar型を使用する。)

# 参照
[文字コードの基本](https://qiita.com/i-tanaka730/items/b0d78097502d94395870)
[文字コードについての予備知識](http://ichitcltk.hustle.ne.jp/gudon2/index.php?pageType=file&id=character_code.md)
[VC++とマルチバイト文字とワイド文字](http://ichitcltk.hustle.ne.jp/gudon2/index.php?pageType=file&id=vcpp_character_code.md)
ECSのタスク定義で、コンテナ間接続のエラーが起きた時の対処法

ECRにプッシュしたDockerのコンテナをECSでタスク定義を行い、いざタスクの実行を行うとステータスが``STOPPED``となる。

何十回やっても以下のようなエラーが起きる。

>
Cannot link to a non running container

ちなみにコンテナの設定は以下のようになっている。

```docker-compose.yml
version: "3.8"
services:
  app:
    build:
      context: .
      dockerfile: ./docker/php/Dockerfile
      args:
        - TZ=${TZ:-Asia/Tokyo}
    ports:
      - ${APP_PORT:-8000}:8000
    volumes:
      - ./backend:/work
      - ./logs:/var/log/php
      - ./docker/php/php.ini:/usr/local/etc/php/php.ini
    working_dir: /work
    environment:
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_DATABASE=${DB_NAME:-***}
      - DB_USERNAME=${DB_USER:-***}
      - DB_PASSWORD=${DB_PASS:-***}
      - TZ=${TZ:-Asia/Tokyo}
  web:
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    depends_on:
      - app
    ports:
      - ${WEB_PORT:-80}:80
    volumes:
      - ./backend:/work
      - ./logs:/var/log/nginx
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    environment:
      - TZ=${TZ:-Asia/Tokyo}
  db:
    image: mysql:8.0
    volumes:
      - db-store:/var/lib/mysql
      - ./logs:/var/log/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    environment:
      - MYSQL_DATABASE=${DB_NAME:-***}
      - MYSQL_USER=${DB_USER:-***}
      - MYSQL_PASSWORD=${DB_PASS:-***}
      - MYSQL_ROOT_PASSWORD=${DB_PASS:-***}
      - TZ=${TZ:-Asia/Tokyo}
    ports:
      - ${DB_PORT:-13306}:3306
volumes:
  db-store:
```

```
├─backend
│  ├─laravel
├─docker
│  ├─mysql
│  ├─nginx
│  └─php
│─docker-compose.yml
```

``app``コンテナと``web``コンテナを接続するという内容です。

``backend\laravel``にはLaravelのプロジェクトが入っています。

タスク定義の設定を変更したり、クラスターの設定をいくら変更してもこのエラーが吐かれる！！！

こうゆうエラーが一番厄介。。。

ただ、およそ2日間かけてこのエラーの解消法が分かった。

原因は「タスク定義」の際に行う「コンテナの追加」。

appコンテナを追加するするときに「環境」で以下のコマンドを追加する。

```
chmod 777 -R && php-fpm
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/ee3fa9b4-7cee-02cf-cbd8-1e150d3e4749.png)


たった一行のコマンドのせいで2日間時間を費やした。。。

くれぐれも皆さん気を付けください！！

以上、「ECSのタスク定義で、コンテナ間接続のエラーが起きた時の対処法」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
ターミナルでディレクトリとその中身のファイルを削除する。

ターミナルでディレクトリとその中身のファイルを削除する。
そのときに使うコマンド。
忘れてしまうから、ここに書いておきます。

```
$ rm -rf ディレクトリ名
```
これで、ディレクトリをその中身ごと消せる。
PowerAppsでコレクションを任意の順で並べ替える

作成中のアプリで必要だったので覚え書き。
ギャラリーコントロールを使ってコレクションのアイテムを任意の順番で並べ替える方法です。
スマホアプリのようにアニメーションがないので少々違和感がありますが。

![Reodrder.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/df3d5e72-b6c0-8bf9-ad17-f257f2f48bdd.gif)

#ポイント
- コレクションにはIndex列を用意。
- ギャラリーコントロールのItemsではIndexでソート。
- 並べ替えボタン、PatchやUpdateIfでIndexを入れ替える。
- ギャラリーのAllItemsを参照して並べ替え状態で新しいコレクションに格納。
- 並べ替えたアイテムの色付け解除はタイマーで。

#解説
##①コレクションを準備してギャラリーコントロールのデータソースに指定

- コレクションのアイテムには1～nの連番を振る必要があります。
- 2つ目のClearCollectは移動したアイテムに色を付けたい場合に使用するもので、SelectedRow列を追加しています。
- 無くても問題ありません。
- ギャラリーコントロールのItemsには```SortByColumns(DataTable,"Index",Ascending)```を設定

```JavaScript
ClearCollect(
    DataTableBase,
    {Index:1,ItemName:"Albedo"},
    {Index:2,ItemName:"Diluc"},
    {Index:3,ItemName:"Fischl"},
    {Index:4,ItemName:"Barbara"},
    {Index:5,ItemName:"Xiao"},
    {Index:6,ItemName:"Bennett"},
    {Index:7,ItemName:"Jean"},
    {Index:8,ItemName:"Mona"}
);
ClearCollect(
    DataTable,
    AddColumns(
        DataTableBase,
        "SelectedRow",
        false
    )
);
```

## ②ギャラリーコントロールを以下のようなレイアウトに設定
・↓ボタン、↑ボタンで一つずつ前後に移動するイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/1589f8c2-1bc3-06d9-78c3-132595a50177.png)

##③↑アイコンの設定

- OnSelectを以下のように設定
    - 3行目：クリックした行のIndexを一旦0に設定。SelectedRowをtrueにして移動した行の色が変わるように。
    - 4行目：ひとつ上の行のIndexを+1(クリック行のインデックスに置き換え)
    - 5行目：クリックした行のIndexを-1
    - 7行目：色を元に戻すタイマーを起動

```JavaScript:
With(
    {ThisIndex:ThisItem.Index},
    Patch(DataTable,ThisItem,{Index:0,SelectedRow:true});
    UpdateIf(DataTable,Index = ThisIndex - 1,{Index:ThisIndex});
    UpdateIf(DataTable,Index = 0 ,{Index:ThisIndex-1});
);
UpdateContext({TimerStart:true});
```

- Visibleを以下のように設定。　一番上の行は↑アイコンを非表示に。

```JavaScript:
If(ThisItem.Index = 1,false,true)
```

##④↓アイコンの設定
・OnSelectは省略、↑アイコンの-1を+1に変更するだけです。
・Visibleは以下のように設定。 一番下の行は↓アイコンを非表示に。

```JavaScript:
If(ThisItem.Index = CountRows(DataTable),false,true)
```
<br>
##⑤ゴミ箱アイコンの設定
- OnSelectを以下のように設定
- アイテムを削除した後、その行より後の行のIndexを-1して上に詰めます。

```JavaScript:
With(
    {ThisIndex:ThisItem.Index},
    Remove(DataTable,ThisItem);
    UpdateIf(DataTable,Index > ThisIndex,{Index:Index-1})
)
```
<br>
##⑥移動した行を色付けする設定(必要な場合)
・ギャラリーコントロールのラベルのFillに以下を設定。
・SelectedRowがtrueのときのみ色が変わるように設定。
```If(ThisItem.SelectedRow=true,RGBA(255, 191, 0, 1),RGBA(186, 202, 226, 1))```

・タイマーコントロールを用意し、Durationは500、StartはTimerStart変数を設定。
・OnTimerEndで以下を設定、時間経過後にSelectedRowをfalseに戻して色を戻す。
 ```UpdateIf(DataTable,SelectedRow = true,{SelectedRow:false});
UpdateContext({TimerStart:false});```

##⑦確定ボタン
・OnSelectに以下を設定
・ギャラリーコントロールのアイテムを参照して新しいコレクションにコピー。
・自分が作成中のアプリではJSONとして返却したかったのでJSONに変換するコードも入っています。

```JavaScript:
Clear(JsonTable);
ForAll(Gallery1.AllItems,
   Collect(JsonTable,{Index:Index,ItemName:ItemName})
);
UpdateContext({JsonString:JSON(JsonTable,JSONFormat.Compact)});
```

#あとがき
- 並べ替え部分はアニメーションにできずフィードバックがないので少し違和感。
- どういった視覚効果がいいのか模索中。標準コントロールでできるようになればありがたい。

- 今回はコレクションの並べ替えです。データソースを並べ替える場合は試していません。
- おそらく、UpdateIfは委任できないとされているため、PatchとFilterを組み合わせて更新することになると思います。
- ギャラリーコントロールで少数に絞る→コレクションに変換→並べ替え→Patch関数でデータソースをアップデートとか？
[JS] フレームワークの予備知識 


#コンポーネント指向

コンポーネント指向とは機能ごとに部品として分割し、必要に応じて組み合わせて使うという考え方です。アプリケーションは複数の部品で構成されており、同じ部品が繰り返し使われることが多々あります。
例えばヘッダーやフッターなどは、ほとんどの画面に表示されています。また、ボタンや入力フォームなども同じスタイルを持ったものが複数の画面で繰り返し使われます。

この様々なパーツ（機能）をコンポーネントと呼ばれる単位に区切ることで、再利用性を高めることができます。また、デザインと技術の共同作業をしやすくすることもコンポーネント化の目的です。

#仮想DOM

DOMとはツリー構造であり、これを読み取って再現したものが仮想DOMです。最近では、画面の描画を変更したい時、まず仮想DOMを操作してこれを実際のDOMに反映させる、という方法が支持されています。以下にその理由を紹介します。

直接JavaScriptの関数を用いてDOMを変更する処理を書く場合、変更後の描画についてもプログラマーがアルゴリズムを考える必要があります。このアルゴリズムが複雑になればなるほど、非効率なものになり処理が遅くなる危険があります。

一方仮想DOMを用いたDOMの変更では、変更後の描画についてライブラリが最適な形で実現してくれます。これにより、プログラマーが複雑な処理や高速化について頭を悩ませなくても最も早い形で描画が行えます。


#React



React
Facebookが開発をしたライブラリです。仮想DOMの概念によって、より早い高速なアプリケーション実装が実現できます。また、AndroidやiOSのネイティブアプリケーション開発に、Reactを用いるフレームワークであるReact Nativeを使用することができます。柔軟性も高いことから、大きく人気が増しています。


#Vue.js



Vue.js
Vue.jsは、近年JavaScriptのライブラリとして取り入れる現場が増えている人気のライブラリです。Reactと同様に仮想DOMの概念があり、冗長な記述を減らして、HTMLやCSSを中心にしたWebアプリ開発が可能です。

#Angular



Angular
Google等が開発したライブラリです。

Angular自体もライブラリですが、さらにAngular内にも標準で多数のライブラリが用意されています。したがって、外部の機能を使わずとも、公式の機能のみで十分な開発を行うことができます。その機能の多さからAngularはフルスタックなライブラリと言われています。
また、Angularは推奨言語にJavaScriptではなく、TypeScriptを採用していることも特徴です。
Marpで画像がPDFエクスポートできなかった話

# TL;DR
Marp for VSCodeを使用してスライド作成した際に、画像が出力できなかったハマりポイントを解決します。

# 問題
簡単にスライドを作りたいな～と思って調べると、Marpというツールの存在を知りました。
なんとVSCodeでも利用できるらしく試してみました。

Marpに関する情報は以下が詳しいです。

* [【VS Code + Marp】Markdownから爆速・自由自在なデザインで、プレゼンスライドを作る](https://qiita.com/tomo_makes/items/aafae4021986553ae1d8)
* [爆速でスライドを作る！Markdownからスライドを作れる「Marp](https://qiita.com/msp0310/items/0e54f69457f81bc64754)

先人に倣ってスライドを作って、いざエクスポートしたら...
画像が出ていない！

![marp_pdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149028/37804978-603e-4059-1112-09da2f10d4a4.png)

プレビューで見てたとき
![marp_プレビュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149028/26136d6f-aada-d4b8-0abd-5164700e2c52.png)

# 解決
簡単なことでした...
Windows環境で作業しててパスを「\\」にしていたことが原因でした。
「/」でないと正しく解釈されないのでご注意を。

# まとめ
Draw.ioやVegaと組み合わせることもできる大変優秀なMarp。
デザインで指定しにくい部分もありますが、簡易的に作る上では申し分ないレベルですね。
（作者様に感謝です）
Azure PowerShell Az モジュール インストール手順

Azure PowerShell Az モジュールのインストール手順は、
https://docs.microsoft.com/ja-jp/powershell/azure/install-az-ps?view=azps-3.8.0
で案内されていますが、
Windows Server上ではひと手間必要だったので自分用にメモ

Microsoftドキュメントでは、Powershellで以下のコマンドを実行するように記載されていますが、自分の環境で警告が出て失敗します。

【実行コマンド】
if ($PSVersionTable.PSEdition -eq 'Desktop' -and (Get-Module -Name AzureRM -ListAvailable)) {
    Write-Warning -Message ('Az module not installed. Having both the AzureRM and ' +
      'Az modules installed at the same time is not supported.')
} else {
    Install-Module -Name Az -AllowClobber -Scope CurrentUser
}

【警告画面】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1113101/27247198-eba2-e8ca-a615-f2aa78ba2a61.png)
WARNING: Unable to acquire token for tenant 'organizations'
WARNING: Please run 'Connect-AzAccount -DeviceCode' if browser is not supported in this session.
Connect-AzAccount : InteractiveBrowserCredential authentication failed: User canceled authentication.
At line:1 char:1
+ Connect-AzAccount
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Connect-AzAccount], AuthenticationFailedException
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand


【対応】
以下のコマンドを実行
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

これをしてからAzモジュールのインストールコマンドを実行したらうまくいきました。
Windows (Preview ) Terminalを簡単に起動する方法（エクスプローラーから起動）

# 内容
- Windows Terminalを起動するときは、エクスプローラーから起動するのが簡単です。
- エクスプローラーのアドレスバーに`wt`と入力して`Enter`で起動
- ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143120/238442e4-5e74-b68d-5ad5-d9d0c148fad9.png)
- この起動方法が活かされるのが、エクスプローラーで開いているフォルダをTerminal起動後にカレントにしたい場合です、`cmd`で開くコマンドプロンプト（MS-DOS）では、何も指定しなくてもそうなっていたので良かったのですが、`wt`では現在（2021/2/23）のところ、ひと手間必要です。
    - `wt -d .`で実行時引数としてカレントディレクトリを指定してあげます
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143120/65e58988-f38b-bce2-bbf3-12bea520b068.png)

# まとめ
- エクスプローラー上で開いているフォルダ上でTerminal操作したいとき 
    - →　アドレスバーを編集（`Alt`+`D`）　
        - →　`wt -d .` + `Enter`！
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143120/1fd97920-b8cf-30d3-93d0-5b1475b6a4c1.png)


# おまけ
- Windows Preview Terminalを使っている方、Windows Terminalのほうがインストールされていなければ、wtコマンドPreviewのほうを起動できます。
- エクスプローラーのアドレスバーは便利です、是非使いこなしましょう！
    - https://qiita.com/basso414f/items/9d78a25c077f04e996e3
【Unity】.metaファイルの役割とは

# .meta ファイルとは

- Unity がアセットを照会するために必要なファイル
    - Unity プロジェクトにおける設定、参照関係など
    - .meta ファイルがないと、Unityに認識されない
- アセットファイルと対で一緒に保管されなければならない
- .metaファイルには、アセットファイルを識別する一意のIDが割り当てられる
    - GUIDと呼ばれる

# どんな内容が書かれているか
自分の Unity プロジェクト内ですが、
フォルダだと以下のようなファイル内容で、

```
fileFormatVersion: 2
guid: ab84f2cb13056e146b01437c2d6ba879
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 
```

.csファイルだと、

```
fileFormatVersion: 2
guid: 1e2e38996083ad0489f3ea2a3ccd972a
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 
```

prefabだと、

```
fileFormatVersion: 2
guid: 3560fcc99ead8b54a8ab5e3c35ae93ca
PrefabImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 
```

scene だと、

```
fileFormatVersion: 2
guid: 9fc0d4010bbf28b4594072e72b8655ab
DefaultImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 
```

という内容になっていました。

# いつ作成されるのか

Assets フォルダ内にアセットファイルが作成されると、 Unity が自動的に作成します。
ユーザーは、手動で変更を加えたりすることはありません。

# 変更、削除されるときは

- アセットファイルを削除したとき
- Inspector で設定を変更したとき

# meta ファイルをコミットし忘れると…

アセットファイルの設定や参照関係が全くない状態です。
また、別の人がプルしてプロジェクトを開くたびに、それぞれ別々の .meta ファイルが作成されてややこしいことになります。
アセットファイルを追加したら、必ず .meta ファイルもコミットしましょう。


# 参考文献

[アセットの内部処理 - Unity マニュアル](https://docs.unity3d.com/ja/2018.4/Manual/BehindtheScenes.html)
[インポート - Unity マニュアル](https://docs.unity3d.com/jp/current/Manual/ImportingAssets.html)
[Unityのmetaファイルについての勉強会を行いました](https://developer.aiming-inc.com/study/unity-meta-study/)
[【Unity】metaファイルって何？ - すとーぶろぐ](https://t-stove-k.hatenablog.com/entry/2018/07/30/021120)
【Swift】MVCについて

###はじめに
自分用メモです。MVCについてまとめます。
![スクリーンショット 2021-03-30 19.23.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/26be37d2-036a-d2d7-5567-a134645b00a8.png)

###Modelの役割
・データ構造の表現
・WebAPIとのやりとり
・ローカルデーターベースへの保存
・データの振る舞いロジック
（UIやレイアウトに関するロジックは保持しない）

###Viewの役割
・UIの表示
・データを表示するようなUIの場合Controllerからデータを受け取りUIに反映
(データ構造に関する一切のロジックを持たない）

###Controllerの役割
・Modelからデータを受け取り、ViewにわたしUIを更新する
・ユーザーインタラクションをViewから受け取り、適切なアクションを処理する
・ViewControllerにしかできないロジック処理を行う（ライクサイクルや画面遷移など）
そうだ、SQLの勉強をしよう17

#はじめに
SELECT文の条件をつけるときとは違い、単純で覚えやすいです。

##デフォルトの値を指定する

```sql
CREATE TABLE テーブル名(
列名 型名 DEFAULT デフォルト値
)
```
値を入力しなくても、デフォルトの値が入る。

例

```sql
CREATE TABLE 成績表(
算数 INTEGER DEFAULT 0 
)
```

##テーブルに列の追加
```sql
ALTER TABLE テーブル名 ADD 列名 型 制約
```
基本、いちばん最後の列に挿入されます。

##テーブルの列を削除
```sql
ALTER TABLE テーブル名 DROP 列名 型 制約
```

##最後に
DDLの命令文は基本的に

```sql

命令 TABLE テーブル名 (
列名 型名 DEFAULT 制約
)
```

の形だと理解すると、わかりやすと思いました。
[Bash]対象パターンの行数をカウントする

Bashで、対象パターンの行数をカウントするサンプルコード（覚え書き）。
具体的には、ファイル内に、対象文字列が所定の箇所にある行数をカウントします。

## 環境

* OS: Amazon Linux2

## 概要

指定したファイル内に、対象文字列が所定の箇所にある行数をカウントします。

コマンドライン引数の
第1引数: ファイル名
第2引数: 検索したい文字列
第3引数: 切り取り開始位置（行の先頭が0始まり）
第4引数：切り取り数
を指定して実行します。

## コード
```bash:count_match_line.sh
#!/bin/bash
#
# 対象文字列が所定の箇所にある行数をカウント
#
# $1: ファイル名
# $2: 検索したい文字列
# $3: 切り取り開始位置（行の先頭を0として）
# $4: 切り取り数

count=0
while read line
do
   if [ ${line:${3}:${4}} = $2 ] ; then
        count=$((count+1))
   fi
done < $1

echo "対象データは$count件です"
```

本当は、
> count=$((count++))

にしたかったけど、うまくいかなかったので、
> count=$((count+1))

にしました（解決したら直します）。

## 実行してみる

以下のファイルで、各行の先頭を0文字目として、13文字目～が、123となっている行数をカウントします。

```:hoge.tsv
000000  00000   123     000001
000000  00000   125     000001
000000  00000   124     000001
000000  00000   123     000002
000000  00000   123     000003
000000  00000   124     000002
000000  00000   123     000004
000000  00000   125     000002
```
1, 4, 5, 7行目の計4行に、123が含まれています。
スペースっぽい箇所は、タブです。

### 実行コマンドと結果

```bash:
$ bash count_match_line.sh /product/share/eee/hoge.tsv 123 13 3
対象データは4 件です
```

うまくいきました！

## 参考
* [【シェルスクリプト】ファイルの中身を一行ずつ読み込む方法 | server-memo.net](https://www.server-memo.net/shellscript/read-file.html)
* [【Linux入門】if文による条件分岐の方法をわかりやすく解説！ | SAMURAI ENGINEER](https://www.sejuku.net/blog/53707)
* [シェルスクリプトでsubstrみたいなこと | 半径5メートル](https://srkzhr.hatenadiary.org/entry/20071109/1194619797)
* [bashで数値のカウントアップ | HACK NOTE](https://hacknote.jp/archives/16020/)
* [初心者向けシェルスクリプトの基本コマンドの紹介 | Qiita](https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337)
Dockerコンテナに一般ユーザーを追加するときのDockerfileの設定

# はじめに
Dockerfileを作るときにいつも思い出せなくてググってしまうのでメモにしました。
何番煎じかなという気もしますが...。
検索すると設定方法が複数出てくるので、ここに書いた方法でないといけないというわけではないです。

# 一般ユーザを追加する場合
- まず、```id```コマンドでホストのユーザーIDとグループIDを確認します。

    ```sh
    $ id
    id=1000(hoge) gid=1000(hoge) groups=1000(hoge),....
    ```

- 先程確認したユーザーIDとグループIDを使って、ユーザとグループを追加したDockerfileを作成します。例えば次のような形になります。

    ```Dockerfile
    FROM ubuntu:latest

    ARG USERNAME=user
    ARG GROUPNAME=user
    ARG UID=1000
    ARG GID=1000
    RUN groupadd -g $GID $GROUPNAME && \
        useradd -m -s /bin/bash -u $UID -g $GID $USERNAME
    USER $USERNAME
    WORKDIR /home/$USERNAME/
    ```
    - ```groupadd```コマンドで新しいグループを作成します。```-g```オプションでグループIDを指定しています。 
    - ```useradd```コマンドで新しいユーザーを作成します。オプションの意味は次の通りです。
        - ```-m```, ```--create-home``` ホームディレクトリを作成します。
        - ```-s```, ```--shell SHELL``` ログインシェルを指定します。
        - ```-u```, ```--uid UID``` ユーザーIDを指定します。
        - ```-g```, ```--gid GROUP``` プライマリグループのグループ名かグループIDを指定します。ちなみに省略した場合、環境によって「ユーザー名と同じグループ名が新たに作成される」「```/etc/default/useradd```に記述されたグループID」「デフォルトの100」のいずれかになるようです。参考: [ubuntu manuals](http://manpages.ubuntu.com/manpages/bionic/man8/useradd.8.html)

# sudoを実行できるユーザーを追加する場合
- [Dockerfile のベストプラクティス](https://docs.docker.jp/engine/articles/dockerfile_best-practice.html#user)を見ると、Dockerコンテナ内で```sudo```を使用すると問題を起こす可能性があるようです。とはいえどうしても```sudo```を使いたい場合は次のようなユーザーを追加することで使用できます。

    ```Dockerfile
    FROM ubuntu:latest

    RUN apt-get update && apt-get install -y sudo

    ARG USERNAME=user
    ARG GROUPNAME=user
    ARG UID=1000
    ARG GID=1000
    ARG PASSWORD=user
    RUN groupadd -g $GID $GROUPNAME && \
        useradd -m -s /bin/bash -u $UID -g $GID -G sudo $USERNAME && \
        echo $USERNAME:$PASSWORD | chpasswd && \
        echo "$USERNAME   ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
    USER $USERNAME
    WORKDIR /home/$USERNAME/
    ```

    - ```useradd```コマンドに```-G sudo```が追加されています。```-G```はセカンダリグループを指定するオプションで、ここではユーザーがsudo権限を持つグループに所属することを示します。
    - ```echo $USERNAME:$USERNAME | chpasswd```でパスワードを設定します。
    - ```echo "$USERNAME   ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers```でパスワードの入力なしで```sudo```を実行可能に設定します。

## 参考
- [Dockerfile のベストプラクティス](https://docs.docker.jp/engine/articles/dockerfile_best-practice.html#user)
- [How to add users to Docker container?](https://stackoverflow.com/questions/27701930/how-to-add-users-to-docker-container)
- [Understanding how uid and gid work in Docker containers](https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf)
- [Docker コンテナ内に一般ユーザーを作成する](https://zukucode.com/2019/06/docker-user.html)
- [dockerでvolumeをマウントしたときのファイルのowner問題](https://qiita.com/yohm/items/047b2e68d008ebb0f001)
- [【 useradd 】コマンド――新規ユーザーを作成する](https://www.atmarkit.co.jp/ait/articles/1811/02/news035.html)
- [ubuntu manuals](http://manpages.ubuntu.com/manpages/bionic/man8/useradd.8.html)
- [Adding a non-root user to your dev container](https://code.visualstudio.com/docs/remote/containers-advanced#_creating-a-nonroot-user)
[SwiftUI] 画面遷移に関して

今回はSwiftUIの画面遷移に関して解説していきます。

#遷移後画面の作成

command + Nで新たなファイルを作成します。
SwiftUI Viewを選択してください。
その後createで作成します。

```swift

import SwiftUI

struct SecondView: View {
    var body: some View {
        Text("画面遷移出来たよ！")
    }
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SecondView()
    }
}

```

上のコードは`SecondView`とし、Textも"画面遷移出来たよ！"と変更しましたが変えても変えなくてもどちらでも良いです。

#遷移前画面の作成

```swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: SecondView()) {
                Text("押したら画面が変わるよ")
                    .padding()
            }
        }
    }
}

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

```
`NavigationLink`でTextをタップしたときに画面遷移が行えるようにしています。
また`NavigationView `は`NavigationLink`を使用する場合に必要となります。

`destination:`の部分には遷移先の画面を指定します。
今回は先程作成したSecondViewをしていますね。

# 完成

これが遷移前の画面で、ボタンを押すと…
<img width="400", alt="スクショ1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607760/ed47f099-edd2-36a1-bcc1-e3054134615c.png">
<br>
<br>
<br>

うまく画面が切り替わりましたね。
<img width="400", alt="スクショ1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607760/42c7dfa7-9d3e-593f-38c6-c93aa043ae36.png">
お疲れ様でした。
ここまでご覧いただきありがとうございます。

<br>
<br>
<br>

余談ですが`NavigationLink`に含まれる`Text`を下のように変えることで


```swift

                Text("押したら画面が変わるよ")
                    .font(.title)
                    .frame(width: 400, height: 48)
                    .foregroundColor(Color(.blue))
                    .background(Color(.green))
                    .overlay(
                        RoundedRectangle(cornerRadius: 0)
                            .stroke(Color(.red), lineWidth: 1.0)
                    )
```

このようなボタンのようなTextが作成できます。

<img width="400", alt="スクショ1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607760/0af4e0cd-64c0-5d79-7df9-ecbd9d93924c.png">
認定スクラムマスター（CSM）研修合格までの流れ

「スクラムマスター（CSM）」試験に合格したので、試験受験〜合格までの流れを書いていきます。

---

# はじめに
1. 私の業務について
    - 主に開発者ロール。小さいPRJはPLもたまにやる
    - AWSを用いたクラウド開発がメイン
    - フロントはVue,バックエンドはAWS Lambdaをよく使ってる

2. なぜCSMを受験したのか
    - 業務でスクラム開発の機会が増えてきた
    - スクラム開発を体型的に学んで業務に活かしたい
    - 自身のキャリアの幅を増やしたい

---

# CSMの研修について

CSMを受験するには、まずは研修を受講する必要があります。
私は[Odd-e](https://www.odd-e.jp/)の[オンライン研修](https://www.odd-e.jp/training/)（講師：Michael James）を受講しました。

コロナ禍においてオンライン研修は本当にありがたい、、、

---

# 研修概要

日程は月〜金の５日間、8:59~15:01でした。(微妙な1分はなんだったのだろう)
15:01以降は退出自由の質問タイムが設けられていました。
1~2時間に1回10分休憩があるのと、お昼休憩が１時間ありました。
ツールはzoomとmiroを使いました。

---

#### 研修受講前にやったこと

研修の2週間くらい前に、スクラムに関する質問に回答するようメールがきました。
質問の例は下記のような感じのものが20超。結構回答に時間がかかった。
> スクラムで定義されているそれぞれの役割の責任について、あなた自身の言葉で答えてください

事前に[スクラムガイド](https://www.scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)を読んで理解を深めてから研修に望んでくださいということでしょうね。

---

#### 講師

前述の通りメイン講師はMichael James(MJ)さんでした。
MJさんは英語オンリーでしたが、榎本 明仁さんが通訳兼副講師として日本語に翻訳してくれたので英語が苦手でも大丈夫でした。


--- 

#### 研修内容

座学と、zoomのブレイクアウトルームを利用したグループワークがメインでした。割合は4:6くらい。
グループワークはスクラムの理論に対する理解を深めるためのワークもありましたが、
実業務や組織におけるスクラムを阻害する要因を取り除くためのディスカッション、実際のPRJを例にしたプロダクトバックログの適切な切り方の練習などもあり、より実践的でした。
質問タイムではみなさん実業務の課題に対するものを多く質問していましたが、MJさんや榎本さんが実際にスクラムを実施した経験に基づき、単なるスクラムの理論の一般論ではない回答をしてくださっていたのが印象的でした。

---

# 研修終了〜受験まで

研修でCSMを受験するのに相応しくない、研修を最後まで受講できなかった、などの事情がない限り、研修終了後にトレーナーから認定スクラムスター試験受験のための仮アカウントが発行され、メールが届きます。
研修受講から90日以内に受講しないと受講資格を失います。
メールが到着してからアカウントの登録だけはすぐに済ませてしまいましょう。
落ちても１回までなら無料で再試験可能だそうですが、「ほとんどの人は１回でパスできるから安心してよhahaha」「もし落ちたら補習するからhahaha」と仰っていました。

---

# 試験について

試験はオンラインで受けられます。60分50問の選択形式で、ボーダーラインは74%とのこと。
スクラムガイドやその他資料を参照しながら受験できます。
スクラムガイドに沿った内容の質問がメインですが、
> 例：開発チームがデイリースクラムは不要と言っています。スクラムマスターは何をすべきですか？

というような質問も出されるので、スクラムマスターのマインドは研修を通じてよく理解する必要があるなと思いました。※上記例は実際の問題とは異なります。ただ、難易度は高くなく、真面目に研修を受講すれば問題なく合格できると思いました。私は96%で無事パスしました。

---

# 研修を受講しての感想

めちゃめちゃ良い研修でした。
スクラムはスクラムガイドを読んでその通りに実践すればうまくいくわけじゃないぞ！スクラムマスターは現場に寄り添って課題解決するスタンスが最も重要だ！というマインドが醸成されました。
研修の中で印象的だったのが、「今うちの組織では×××のルールのせいでスクラムがうまく回せていないのですが、こういった時のベストプラクティスはありますか？」といった質問に対し、講師の方はまず「ベストプラクティスはありません」と仰っていたことです。スクラムはスクラムチームや組織によってそれぞれ課題解決のアプローチは違うので、理論のみに頼らずにスクラムを運営してほしい、というメッセージと受け取りました。
Excel と Power Query を使って SharePoint Online リスト列の表示名や内部名を一覧で表示する

Power Platform 等でアプリを作成する際に SharePoint Online のカスタムリストを利用する場合、DBでのテーブルの列にあたる、カスタムリストの列の定義情報を一覧にして設計書を残したいという要望があると思います。
これを手作業で確認するとすごく大変なのですが、Excel と Power Query と SharePoint REST APIを使うと、簡単に Excel にダウンロードし、一覧にできます。

# 手順
1. 対象のカスタムリストが配置してある、サイトのURLと、カスタムリストの名前を調べる
2. 列情報を取得する SharePoint REST API のエンドポイントURIを作成する
3. Excel を開き、Power Query を実行する

# 1. 対象のカスタムリストが配置してある、サイトのURLと、カスタムリストの名前を調べる

今回はこんなリストを用意しました。

サイトURL

```
https://samplehost.sharepoint.com/sites/samplesite
```
カスタムリスト名
　列チェックリスト

列
　以下のようにいくつか列を用意しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/3feb4c83-3193-5c69-658e-d37b67af20c1.png)

# 2. 列情報を取得する SharePoint REST API のエンドポイントURIを作成する

先ほど調べた情報を組み合わせてエンドポイントURIを作成します。

エンドポイントURI

```
https://samplehost.sharepoint.com/sites/samplesite/_api/web/Lists/getbytitle('列チェックリスト')/fields

↑以下に先ほどの値から取得した値を埋め込んだもの↑
https://{hostname}/sites/{sitename}/_api/web/Lists/getbytitle('{listname}')/fields
```

# 3. Excel を開き、Power Query を実行する

準備が整ったので Excel で一覧にしていきます。

- 新規に Excel ファイルを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/d76a9c9b-10d9-57e7-277d-bd9b33e7c3e1.png)

- "データ"タブから"データの取得 > その他のデータソースから > Odataフィードから"を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/03cf802c-6e4d-a5ac-b200-f2de606a3399.png)

- 以下のような画面が表示されるので、2.で作成したエンドポイントURIを入力し、"OK"を選択します。
※この後、SharePoint Online の環境に関して、サインインを求めるダイアログが表示される可能性があります。その場合、画面の指示に従って、サインインしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/21cf7ee9-cbf5-fdb0-92b7-f6493e6156e3.png)

- 少しの待ち時間の後、その後以下のような画面が表示されますので、"読み込み"を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/016b383e-9da5-4b87-d2d1-cd772b90962b.png)

- もとの Excelファイルに戻ってくると、列の内部名(InternalName/StaticName)、表示名(Title)を含む情報が一覧になっていることが確認できます。
日本語で列名を付けたものは、わかりにくい内部名ですが、それも取得できています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/18da8425-950e-32d1-2d44-e981da596c38.png)

- 列の種類等の情報も同時に取得できています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/fc254610-7e44-203c-7abd-ffc6b723a125.png)

Excel にデータがきてしまえばこっちのもの？あとは自由にご利用ください。

# まとめ
設計書とか必要なレベルのものを作るべきかどうかは別として、自由に作られてきたカスタムリストを急に管理しなくてはならなくなった時などに使えるかなと思います。
REST API をご存じであれば、sitegroup 等その他のエンドポイントにも応用が可能です。

API 2.0 でも利用できますが、あちらは、Odataフィードだとうまくいかなかったので、JSONとして扱うことで同様の処理が可能です。
【Swift】 お問い合わせ機能の実装

#Swiftで簡単にメーラーを起動する方法
####まずは下記の手順でMessageUI.frameworkを追加します。
プロジェクト→Build Phases→Link Binary With Libraries→＋ボタン→MessageUI.framework
####あとはコードを書くだけです。
```swift
import UIKit
import MessageUI

class InquiryViewController: UIViewController, MFMailComposeViewControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func inquiryMail(_ sender: Any) {

        if MFMailComposeViewController.canSendMail() {
            let mail = MFMailComposeViewController()
            mail.mailComposeDelegate = self
            mail.setToRecipients(["○○○@email.com"]) // 宛先アドレス
            mail.setSubject("お問い合わせ") // 件名
            mail.setMessageBody("ここに本文が入ります。", isHTML: false) // 本文
            present(mail, animated: true, completion: nil)
        } else {
            print("送信できません")
        }
    }

    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {

        switch result {
        case .cancelled:
            print("キャンセル")
        case .saved:
            print("下書き保存")
        case .sent:
            print("送信成功")
        default:
            print("送信失敗")
        }

        dismiss(animated: true, completion: nil)
    }
}
```
Codeforces Round#704 C. Maximum width

https://codeforces.com/contest/1492/problem/C

# こう考えた
まず最初、sの中でtを作れる最短の場所を探す。例えば、上の図でabcは(0-indexとして)0,1,2文字目である。これは、tの0文字目から順番にsを探索すればわかる。例えば、s=axxbxxxcでt=abcなら、$[0,3,7]$となる。ここでまず距離のmaxを求めておく。

さて、次に、tの後ろの文字にあたる文字から、なるべく後ろにその文字を持っていく。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30938/8dac6a82-155e-3281-1922-a82749d7b92b.png width=50%>
図の場合、cは2つの候補があるが、2つ目の移動候補の方が遠いので、そちらに移動する。次に、bを考えると、1つしか移動先がない（これは全くないこともあり得る）ので、1つ目の候補に移動する。
さて、aは3つの移動先の候補があるが、順序を保たないといけないので、1つ目の候補しか移動できない。(2,3個目に移動してしまうと、bacやbcaになってしまう)

この動作は各文字間の長さを最大にするような貪欲を求めているのに他ならない。

# 実装
まず、最短の位置は線形にsを探索すれば求まる。この時、最長の距離を記録する。
次に、sの各文字を線形に調べ、ある文字ごとの位置を保存しておく。これは、キューなどで管理すればよく、大きい方から数字を取得できれば良い。
そして、tを右から順にみていき、最短の位置からさらに右に移せるかをキューから位置をとり調べていく。もし、右に移せる場合、その距離が最長の距離となるかをmaxでとる。


```Python3
from collections import deque
def do():
    a2i = lambda x: ord(x) - ord("a")
    n, m = map(int, input().split())
    s = input()
    target = input()
    posAlphas = [deque([]) for _ in range(26)]
    # まず、最短を求める
    loc = [None] * m
    cur = 0
    for i in range(m):
        while s[cur] != target[i]:
            cur += 1
        loc[i] = cur
        cur += 1
    res = -1
    for i in range(m-1): # 最短の位置での最長の距離を調べる
        res = max(res, loc[i+1] - loc[i])
    curMax = 10 ** 9 # ひとつ大きい文字の位置(これを以上ではいけない)
    for i in range(n):
        val = a2i(s[i])
        posAlphas[val].append(i)
    for i in range(m-1, 0, -1): # 上からたどる
        # なるべく右に
        curLoc = loc[i] # 今の位置
        curChar = a2i(target[i]) # 今の文字
        while len(posAlphas[curChar]) > 0: #候補があるなら
            canPos = posAlphas[curChar].pop() # 一番大きいのを取る
            if curMax <= canPos:
                continue
            if canPos <= curLoc: # その文字と一緒なら
                break # 置き換えられないので抜ける
            loc[i] = canPos
            break
        curMax = loc[i] # tの次の文字はこれより右ではいけない
        res = max(res, loc[i] - loc[i - 1]) # 最長の距離を(必要なら)更新
    print(res)
do()
```
https://codeforces.com/contest/1492/submission/108271917
Webを支える技術　Web概論編２

# web以前のインターネット

初期のインターネットにはwebがなかった。

インターネットの起源は1969年に構築された「ARPANET」までさかのぼる。

ARPANETは、アメリカ国防総省国防高等研究計画局が構築したコンピュータネットワーク。

ARPANETは、米国内の大学や研究機関の間を接続し、全米を繋ぐネットワークとして成長していた。

当時のネットワークは、**リアルタイムに相手と通信するTCP/IP**だけではなく、

**バケツリレー式のUUCPによる転送**も存在していたため、メール到達には遅延があった。

TCP/IPとUUCPは、それぞれ通信プロトコルの一種。

## web以前のハイパーメディア

ハイパーメディアはインターネットよりも長い歴史を持つ技術です。

起源は、Memexという情報検索システムについての論文だと言われている。

memexは実在するシステムではなく、構想に過ぎないが、

**「電気的に接続した本やフィルムを交互にリンクしリンクをたどって次々と表示する」**

現在のwebを予感させるシステム。

### ハイパーメディアという言葉

memexに影響されてハイパーメディアとハイパーテキストという言葉を考案したのが、Ted Nelsonという方。

**ハイパーテキスト**が**文字情報中心の文書を相互にリンクさせた概念**であるのに対し、

**ハイパーメディア**は**音声や動画など多様なメディアを相互にリンクさせた概念**


これまでに最も普及したハイパーメディアの実装はWebです。

## web以前の分散システム

最も初期のコンピュータは１つのコンピュータが複数の目的で利用されるものだった。

このようなシステムを「**集中システム**」という。

これに対し、コンピュータが小型になり、性能が向上すると、複数のコンピュータを組み合わせて処理を分散させ、全体としての性能を向上させるようになった。

このようなシステムを「**分散システム**」という。

### RPC　ほかのコンピュータの機能を利用

分散システムを実現させるには、各サーバがほかのサーバやクライアントから呼び出せる必要がある。

そこで登場したのが、**RPC(Remote Procedure Call)**

これは分散システムを実現するための技術の一つ

これを使うことで、**リモートのサーバで実行しているプログラムをクライアント側から呼び出せる**

RPCはリモートの手続き、つまり関数を呼び出す仕組み。

オブジェクト自体をリモート側に配置する「分散オブジェクト」(Distributed Object)と呼ばれる技術が考案された。

分散オブジェクトの代表例は、

- CORBA(Common Object Request Broker Architecture)
- DCOM(Distributed Component Object Model)

どちらもIDL(Interface Definition Language)で、オブジェクトのメソッドを定義し、実装ではネットワーク越しにシリアライズしたメッセージを交換するという点ではRPCと同じです。