OmniAICreator/Qiita-1.07M huggingface dataset:
【サーバ構築】nginxでwebサーバを起動

## はじめに
dockerを使ってnginxのコンテナを立ち上げてみました。

### docker-compose.yml

```yml:docker-compose.yml
version: "3"
services:
 ngweb1:
  image: nginx:1.21.6
  ports:
   - 80:80
  volumes:
   - ./nginx/html:/usr/share/nginx/html
```

あとは、docker-compose.ymlのディレクトリで```docker-compose up -d```です。

```image```：nginxのバージョンを指定しています。
```ngweb1```：サービス名です。コンテナ間の通信をする場合は、html://ngweb1でいけます。
```volumes```：OS側とコンテナ側でフォルダを共有することができます。（左：OS側、右：コンテナ側）
```port```：サービスに使用するport番号を指定しています。（左：OS側、右：コンテナ側）
MacBookのキーボードを容赦なく掃除

休日はクロスを使って MacBook を掃除したい。
![PXL_20221123_033651750.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507537/c05b617e-ae6e-644d-6adf-dc47c3e42db8.jpeg)

画面は良いが、キーボードを掃除する時は意図せずショートカット入力が機能して元に戻せない設定になったらどうしようという不安があった。
![istockphoto-1178788339-612x612.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507537/8ec43d38-89b4-5275-cc93-98d37c4658ab.jpeg)

そんな時の救世主アプリが [KeyboardCleanTool](https://folivora.ai/keyboardcleantool) だった。

キーボード入力をロックしてくれるので、キーボードを容赦なく掃除できる。
![save.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507537/6745c278-79aa-8298-edba-8a461bfb00e7.gif)

休日のQOLが上がった。
「リーダブルコード」要約_9章

書籍「リーダブルコード」の要約を掲載しています。
今回は、9章の内容です。

**9章 変数と読みやすさ**

変数を適当に使うとコードが読みづらくなる。
具体的には、

* 変数が多いと変数の追跡が難しくなる
* 変数のスコープが大きいとスコープの把握に時間がかかる
* 変数が頻繁に変更されると現在の値を把握するのが難しくなる

これらの解決策として、
* 不要な変数を削除する。
* 変数のスコープを縮める。
* 変数の変更箇所をできる限り少なくする。


以下、1つずつ解説していく。

**不要な変数を削除する**
「不要な変数」とは、あってもコードが読みやすくならないものを指す。

```python
now = datetime.datetime.now();
root_message.last_view_time = now
```

例えば、上記の変数`now`は以下の理由で不要である。
* 複雑な式を分割していない
* `datetime.datetime.now()`のままでも意味は通じる
* １度しか使っていないので、重複コードの削除になっていない

変数`now`を削除したほうが読みやすくなる。
```python
root_message.last_view_time = datetime.datetime.now();
```

**変数のスコープを縮める**
例えば、グローバル変数はどこでどのように使われているのか追跡しにくい。
グローバル変数に限らず、全ての変数のスコープを縮めることで、変数の追跡や把握がしやすくなる。
ただし、言語によってスコープの決め方は異なる。
リーダブルコードでは複数の言語ごとに例を挙げていたが、この要約ではJavaScriptの例のみ掲載することとする。

* JavaScriptで「プライベートな」スコープを作る

```javascript
submitted = false;

var submit_form = function(form_name) {
   if (submitted) {
      return;//二重投稿禁止
   }
   submitted = true;
}
```
`submitted`はグローバル変数である。
よって、`submitted`が使われているのは`submit_form()`関数だけとは言い切れず、読む側としては不安になる。
この問題を解決するために、変数`submitted`を[クロージャ](https://www.sejuku.net/blog/25026)で包めば良い。

クロージャの記法
```javascript
var メソッド名 = function(引数) {
 
   // 処理
 
}
```
先ほどのコードをクロージャを使って書き換えると以下のようになる。

```javascript
var submit_form = (function () {
   var submitted = false;

   return function (form_name) {
      if (submitted) {
         return;
      }
      submitted = true;
   };
}());
```
クロージャを使うことで、変数やメソッドのスコープを、それらが記述されている関数内に限定することができる。この例では、変数`submitted`には`submit_form()`関数だけがアクセスできるようになった。

**9章のまとめ**
読みやすいコードは、変数が追いやすい。
変数を追いやすくするために、
・不要な変数を削除する
・変数のスコープを縮める
・変数の変更箇所をできるだけ少なくする
macOSとFTPソフトとS3

## 前置き

macOS Ventura
2022年11月時点

macOS Sequoia 15
2024年10月時点

## 本編

macOSユーザでFTP/SCPソフトを使いたいな、という場合は

### [FileZilla](https://ja.osdn.net/projects/filezilla/)

が良いです。

[FilezillraユーザーのためのAmazon S3](https://qiita.com/abebe_shu/items/789a06a7691fd44dcf97)

によると、 **AWS S3接続** の設定は有料とのことなので、（もちろんライセンス料を払って使うのも良いですが）
私の場合、一瞬しか使わないことが確定していたので、

### [ForkLift](https://apps.apple.com/jp/app/forklift-file-manager-and-ftp-sftp-webdav-amazon-s3-client/id412448059?mt=12)

を使いました。もう使うことはないので、Dockからは外しました。

2024年10月時点で、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90217/c8a90cf1-e8c2-da37-8036-20b7882df9ce.png)

という表示がされています。

### [Commander One](https://apps.apple.com/jp/app/commander-one-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%83%BC/id1035236694?mt=12)

2024年10月更新

上記ソフトが良さそうです。
【static java】静的メンバ

```java
public static void main(String[] args) 
```
この「<font color="red">static</font>」とはなんだろう。



####  staticとは静的メンバである。
ざっくり簡単に言えば

**「インスタンスを生成しなくてもフィールドやメソッドを利用できる」**

オブジェクト指向の基本原則として「インスタンスの独立性」というものがありインスタンスを生成することにより"独立性を担保"できるので
**今まではインスタンスを生成するごとに違う値を入れられていた**と思う。

```java:インスタンス生成（例）
Man m1 = new Man();
Man m2 = new Man();
Man m3 = new Man();

//それぞれnameフィールドが用意されていた場合
m1.name = "m1";
m2.name = "m2";
m3.name = "m3";
```

#### staticを使った利用
大きく分けて　「staticメソッド」「staticフィールド」　の２つ。

```java:staticメソッド
public class Calc {
    int sum = 0;
    int a = 2;
    int b = 3;
    public static void calculate() {
        sum = a * b;
    }
}
```
```java:staticフィールド
pubic class Bank {
    static int money = 100;
}
```


#### staticを使うと何がメリットか
###### staticメソッド
インスタンスを生成しなくてもクラス名.メソッド名();などで呼び出せる。

###### staticフィールド
あるクラスにおいて唯一無二のフィールドになる。同クラスの複数のメソッドで同じフィールドを使いたい場合などに役立つ。

共通して言えることは
　　　　　　　　　**「メソッドやフィールドがクラスに属するようになる」** 
ということである。

#### 呼び出し方
```java:staticメソッド
//【クラス名】.【メソッド名】;
Calc.calculate();
```
```java:staticフィールド
Bank.money;
//【クラス名】.フィールド名;
System.out.println(Bank.money);
```



以上のようなところから、一番最初に書いたmainメソッドの呼び出しは'static'がついているのでインスタンスを生成しなくても呼び出せる仕組みになっています。

###### 【注意】
・使い過ぎは可読性やオブジェクト指向原則である「インスタンスの独立性」が失われてしまうところがあるので使用の際は現場やチームの意向に遵守して使うようにしてください。

---

###### 【追記】
javaを学習し始めて１０ヶ月ほど経つが正確に理解したことはなかったので今回良い機会だと思いまとめてみました。まだまだ勉強し始めなので粗い理解の点もありますので指摘ありましたらコメントで宜しく御願いします！！
Jetpack Compose で ripple を丸にする

そもそも ripple 効果は丸なのですが、この記事では ripple 効果が Composable の全体ではなくて円形で見えることを目指します。

# 領域を無視する方法

Jetpack Compose の ripple は　`indication` に　`rememberRipple` を指定することでカスタマイズできます。(指定する場合 `InteractionSource` も同時に指定する必要があります)

領域外までに ripple 効果を見せるには `rememberRipple` の　`bound` を　false にすることでできます。

```kotlin
Box(
    modifier = Modifier
        .clickable(
            interactionSource = remember { MutableInteractionSource() },
            indication = rememberRipple(bounded = false),
            enabled = true,
            onClick = {
                // TODO Something..
            },
        )
) {
// ...
}
```

## 結果

![output1.webm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/c158defd-526a-0dce-0952-9bb7ca561f26.gif)

# 領域内で円型に見せる

`bound` を　false にする場合はレイアウトに影響がある場合もあります。
そのケースを避けたい場合は `radius` に表示したい ripple の半径を指定します。

```Kotlin
Box(
    modifier = Modifier
        .width(44.dp)
        .height(44.dp)
        .clickable(
            interactionSource = remember { MutableInteractionSource() },
            indication = rememberRipple(radius = 22.dp),
            enabled = true,
            onClick = {
                // TODO Something..
            },
        )
)
```

## 結果

![output2.webm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/1b55fd90-229b-cb2b-665c-02ed7d9b7092.gif)

縦横 44dp の Composable に半径の 22dp の `radius` を指定したことで、領域内にぴったりになりました。

### 注意

`radius` に指定する半径は ripple 効果の最終的の半径で、また ripple 効果は中心が基準になります。
もし click 反応する composable の領域が指定した半径より結構大きい場合は ripple 効果が真ん中を向かって縮むように見えます。

![output3.webm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240914/e20b923e-7ccd-15eb-d61a-c4900d35bb5b.gif)
ペアペアプロでモブの1歩先へ-モブプロ開発を行っているチームでやっている取り組み-

# はじめに

本記事は[モブプロ開発を行っているチームでやっている取り組み Advent Calendar 2022](https://qiita.com/advent-calendar/2022/mob_torikumi_example)の11日目の記事です

今回は「ペアペアプロ」について紹介します。ペアペアプロ？と思った方がほとんどかと思いますが、これは私が勝手につけた4人で行うペアプロのやり方になります。

モブプログラミングがある程度進んでだいぶ慣れてきたときに、徐々にモブプログラミングの良さを残しながらさらに開発効率を上げる場面でとても友好的です

# 前回

https://qiita.com/Sicut_study/items/3908bc491d651bd17f36

# Chapter#10 二並列で進めよう

モブプログラミングを導入して2カ月がたった

ベープ「モブプログラミングだいぶ慣れてきたっすね」
ミュート「そうですね、初めに考えていたメリットはしっかりと享受できてますし、アールさんも成長してますし、とても良い取り組みだと思います。私も勉強会でモブプロを利用しながら勉強してもらう会を開こうかなと思ってます」
じん「そうですね、次はこの取り組みを社内に広げていく取り組みも必要ですね」
アール「モブプログラミング私としてはとてもよいのですが、このモブプロの良さも残しつつ、個別の開発のよさも取り入れるみたいなことできるんですかね？みんなと開発もよいのですが、たまには一人で開発して実力を確認するみたいのもやってみたいと思いました」
ミュート「確かにそれあるね。全員が同じレベルでできるならもモブプロしなくてもPRをしっかりみるようにすればやらなくてもよいと思うし、ただいまはまだそこまでチームのレベルは上がってないし」
アール「そうっすね。自分もある程度できるようになりましたが、じんさんいないと厳しいところありますね」

じん「そういう悩みはそのうち出ると思っていました。モブプログラミングは時期に合わせて変化させていくべきで、将来的には個別で開発する方向にシフトすべきかなとは思っています。その過程として今回は`ペアペアプロ`をやっていきましょう！」

一同「ペアペアプロ？？？」

# ペアペアプロについて

ペアペアプロは私が勝手に名前を付けたペアプロの1種となります
ペアペアプロでは4人チームで2人のペアプロチーム×2チームを作成してペアプロをする方式になります
ペアプロを2チームでやることからペアペアプロと呼んでいました

ペアプロについてはこの本がとても参考になるのでぜひご覧ください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/78e3def6-f83b-0427-7fc9-873ba6f30a85.png)
[WEB+DB PRESS Vol.102](https://www.amazon.co.jp/WEB-DB-PRESS-Vol-102-PRESS%E7%B7%A8%E9%9B%86%E9%83%A8/dp/4774194336)

ペアペアプロでは以下の流れでやってきます

1. その日に何時間作業をするかをきめます (1時間単位で決める)
2. 1時間ごとにペアプロするチームを決めておきます。ここで常に同じチームにならないようにメンバーを回します
3. ペアプロを開始したらそこまででどのような実装をしていたか簡単に説明します
4. ドライバー/ナビゲーターを適当に決めて実装を行います
5. 1時間後に休憩をとって次のチームに移動します

この取り組みはモブプログラミングの良さを生かしつつ、並列に作業するメリットも得ることができます

- 1時間ごとにチームが変わるので必然的に開発しているすべてのコードに目を通している
- 1時間の範囲なので説明にもそこまでかからない
- 新人も今の作業方針を理解して説明する必要が出てくる
- 新たな視点でそこまでの開発を聞けるのでリファクタリングやバグをみつけられる
- 2並列で作業が進むので4人で同じ作業をするより効率的

このようにモブプログラミングのデメリットであった作業が1つしかできないというデメリットをケアしつつ、モブプログラミングのよさを得られるというとてもよい開発方法になっています

ペアプロをしたことがある人はほとんどだと思っていますが、しっかりペアプロとはどのようになるのかを学び、ペアペアプロのような取り組みを取り入れることでより良い開発が出来るようになるかと思います

またモブプログラミングを検証するような時間がないというチームではいきなりペアペアプロをいれるのもかなりありかなと思っていますのでぜひ試してみてください

# 次回

https://qiita.com/Sicut_study/items/3e791557a96dcb00e8c0

# おわりに

今回はかなり短くなりますが、ペアペアプロを用いた2並列の開発方法について説明しました
次回はそれをさらに発展させたキャプテン制度という開発方法について説明します

徐々にモブプログラミングから個別で成果が出せるチームへ向かって進んでいきます
数字で話をしよう

# 始めに
既に有名な話だと思うけれど、この所また実感することがあったので、（自分への戒めを込めて）良い機会なので言語化しておく。ちなみに、この手の本は読んだことなくて、あくまで自分の体験をもとに書いているので、所々ニュアンスが伝わらないところがあるかもしれない（というか全ての体験談はそういうものだよなあ）。

こんな経験はないだろうか。

ある施策の方針を複数人で合意して決めようとするが、思うように進まない。皆んながそれぞれの立場で意見を口にする。重要視する観点の差異から始まり、それぞれの思想の違いも加わり始めると、一見議論っぽい何かが生まれて、その時間が終わると「あれあの時間はなんだったんだ？」的なことになる。そして、主催者は、曖昧な Next を胸に、他リソースを必要以上に割いてしまった罪悪感も相まって疲弊していく。民主主義を尊重し過ぎると物事は前に進まない。

# 本題
そんな時は、数字で話をしよう。

理想的には、数字を出せば、自ずと方針が決まる。「誰かがこう思うから」ではなくて、数字が答えを教えてくれる。まあ実際には、そんなに簡単な話ではなくて、判断に資する数字を出した上での検討があって、決めの要素が必要になることはある。けれど、本当に必要な数字を出し切れているのであれば、最後に背中を軽く押すくらいのものではないだろうか。複数人で話し合う前の準備段階で、自分の論理が「それって、あなたの感想ですよね」に対処できるかは確認しておこう。一方で、後述するように、ただの数字遊びになってしまうことは避けなければいけない。ここで言いたいのは、`いかにして共通理解を得て、その上で建設的な議論を行いたい`と言う話であり、そのための手段として数字は有効に使えるよねということ。

また、もう少し広げて考えてみると、数字のないコミュニケーションは、その真意を汲み取れないことが多い。例えば、「世界各地で [何かネガティブな事象] が多発している」と言われた時に、それを数字で可視化してみると、当初の印象とは全く異なる印象に変わったという経験はないだろうか。数字で理解しないとミスリードを招きやすく、ふと周りを見渡すと、意図的にそう仕向けようとしているものが溢れている。

こういう話をすると、なんだか 0/1 で少し雰囲気悪い印象があるみたいな話になるかもしれないけど、それは「数字を使うこと」とは別に問題があると思う。数字は客観的な事実であり、それは階級制度とは異なる平等を意味していて、だからこそそれをベースに判断を行うことができる。数字がなければ、上述したようなことの挙句、見当違いな判断を強行してしまったり、声の大きい人の意見が通ってしまったりする。その方が不健全だし、それはきっと感覚的に気持ち良くないものだと思う。

# 注意点
ちなみに、その数字の意味合いについてはしっかりと評価する必要がある。単純に数字の大小を評価すれば良いという話ではない。例えば、「みんなゲームを持っているからウチも買って」について考えてみる。実際に数字を出してみると数人だったりするけれど、その数字が持つ意味を考えると、それは日常の大半を一緒に過ごす友達全員だったりする。あまり良い例でなかったかもしれないけれど、ここで言いたいのは、その数字の妥当性は慎重に確認する必要があるということ。

また、それは言い換えると、どういう観点で数字を見せるかは担当者に委ねられているということ。つまり、自分の意見を通すためにある種都合の良い数字を見せることもできる。それをどう組み立てるかはまたテクニックがあったり、レビュワーはその妥当性を見抜いて評価しなければならない。まあその辺りの話は次の話だから、まずはその前段として数字を出すことから始めたい。

# 終わりに
そんなわけで、普段から細かいことであっても数字で話をすることを心掛けている（数字出しの手段としてSQLをよく使うのも好きになったきっかけの一つかも）。

と、ここまで書いていて、今回の記事は数字で話ができていないことに気付いたのだけど、まあバランス感覚は大事だよね（原理主義はそれで問題だと思うし）ということで笑。
React Componentをpropsで渡すメモ

```jsx
function App() {

    return (
        <div>
            <InputAbstract component={
                <div>
                    <label>Test</label>
                </div>
            }/>
        </div>
    )
}

const InputAbstract = (prop: { component: React.ReactElement }) => {
    return <>
        {prop.component}
    </>
}
```
#15 Spring バリデーションの実行[正規表現]

# #15 Spring バリデーションの実行
今回はバリデーションを用いて入力可能文字や文字数の制限などを設定していきます。

# 前提条件
この記事はSpringの最低限の知識が必要になります。
また、なるべく分かりやすく書くつもりですが、この記事の目的は自分の勉強のアウトプットであるため、所々説明は省略します。

# 前回まで
前回は型変換に対応するエラーメッセージの処理を行いました。

https://qiita.com/Jackoguro/items/eb04336438522b14dec5

# 構築環境
1. 各バージョン
Spring Boot ver 2.7.5

2. 依存関係
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/1389d101-2f33-f675-9441-37e004cf0a43.png)

今回はバリデーションを使用するため、依存関係に``検証``を設定していない人はMavenの場合はpom.xml、gradleの場合はbuild.gradleに追加する必要があります。

# 成果物
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/ae8ea6a4-dffe-8089-c365-a5f23312a861.png)

# 今回行うこと
今回は以下の流れに沿って進めていきます。
1. SignupForm.javaの各フィールドに必要なバリデーション用のアノテーションを付与する
　1. Pattern 

1. SignupController.javaのメソッドの引数を修正する

## 1. SignupForm.javaの各フィールドに必要なバリデーション用のアノテーションを付与する
```java:SignForm.java
// 省略
@Data
public class SignupForm {
	
	@NotBlank
	@Email
	private String userId;
	
	private Integer phoneNumber;

	private Integer postal1;
	
	private Integer postal2;
	
	private Integer address;
	
	@NotBlank
	private String userName;
	
	@NotBlank
	@Pattern(regexp="^(?=.*[A-Z])[a-zA-Z0-9_]{8,24}+$")
	private String password;
	
	@DateTimeFormat(iso=DateTimeFormat.ISO.DATE)
	@Past
	private Date birthday1;
	
	@DateTimeFormat(pattern="yyyy/MM/dd")
	private Date birthday2;
	
    @Min(5)
	@Max(100)
	private Integer age;
	
	private MultipartFile accountIcon;
	
	private Integer gender;
}
```
### 1. Pattern 
パスワードの設定にはPatternアノテーションを使用しました。
今回パスワードに設定した条件は
- 最低1文字は大文字(A~Z)を含む ⇒ **[a-zA-Z0-9_]**
- 使用できる文字は半角英数字``a~z, A~Z, 0~9``と記号``_``(アンダースコア) ⇒ **(?=.*[A-Z])** 
- 8~24文字以内 ⇒ **{8,24}**

の3つです。
この3つを組み合わせて表現しました。

参考文献

https://www.javadrive.jp/regex-basic/sample/index12.html#section1

## 2. SignupController.javaのメソッドの引数を修正する
```java:SignupController.java
// 省略
	/* ユーザー登録処理 */
	@PostMapping("/signup")
	public String postSignup(Model model, Locale locale, 
			@Validated @ModelAttribute SignupForm form,
			BindingResult bindingResult) {
		// 入力チェック
		if(bindingResult.hasErrors()) {
			// エラーが発生したので登録画面に戻る
			return getSignup(model, locale, form);
		}
		// ログイン画面にリダイレクト
		return "redirect:/login";
	}
}
```
```java
// 変更前
public String postSignup(Model model, Locale locale, @ModelAttribute SignupForm form, BindingResult bindingResult)

// 変更後
public String postSignup(Model model, Locale locale, @Validated @ModelAttribute SignupForm form, BindingResult bindingResult)
```
入力された値が正しいかどうかの判定は引数``@ModelAttribute SignupForm form``に``@Validated``を追加します。
これにより、エラー情報が``BindingResult``インテーフェースに保持されます。

# 最後に
以上で各項目にバリデーションを付与することができました。
新規登録画面の各入力フォームに何も入力せずユーザー登録ボタンを押すと以下の画像のようにデフォルトのメッセージが表示されます。
次回はこのメッセージを自分で登録したメッセージが出力されるよう変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/9113d00a-8db3-fdb9-3147-c225ea75809e.png)
【AWS】Unicornの再起動

# はじめに
rails初学者の者です。オンラインでプログラミングを学習させて頂いてるのですが、さらに理解を深めていきたいと思い、学習したことを備忘録として、残して理解を深めていきたいと思います。
また、間違った点など、ありましたら、ご指摘いただけると幸いです。よろしくお願いします。

# unicornの再起動
再起動手順は
①プロセスを確認
②プロセスをkill
③unicorn_railsコマンドを実行
となります。

```bash.ターミナル（EC2内で実行）
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn

ec2-user 17877  0.4 18.1 588472 182840 ?       Sl   01:55   0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881  0.0 17.3 589088 175164 ?       Sl   01:55   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn
```
上記を例にすると、「ec2-user 17877」部分が対象になる。
続いて、プロセスをkillする。
```bash.ターミナル（EC2内で実行）
# 上記の例だと「17877」
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill プロセス番号
```
最後にunicornを再起動。
```bash.ターミナル（EC2内で実行）
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
```
ここまで行ったら、
ブラウザからhttp://ご自身のElastic IPを入力/にアクセスして、アプリケーションの挙動を確認しましょう。
【Python】Graphvizを用いて階層構造データを可視化してみた

# はじめに
本記事では、DataFrame（階層構造）を木構造にして **可視化する関数** を作成したので紹介します。（ネスト構造の辞書であればより簡単に作成できます）

**下図例**

<img width="800"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2848654/5b7fb099-9597-06df-e8a4-8e7a9eeaf1f6.png">

アドバイスや間違いがあれば、ご指導よろしくお願いします

### 利用ライブラリ
pandas, graphviz
# DataFrameからネスト構造の辞書型へ変換
扱いやすくするために、データフレームから辞書型へ変換します。

```python:example1.py
def make_genre(df, col1, col2, col3) -> dict: # col1, col2, col3にはそれぞれのカラムを入れる

    genre1 = df[col1].unique()
    genre2 = df[col2].unique()
    process_dict = {}

    for i in genre1:
        dict1 = {}
        genre2 = df[df[col1] == i][col２].unique()
        for j in genre2:
            dict2 = {}
            category = df[df[col２] == j][col３].unique()
            dict2[j] = category
            dict1.update(dict2)
        process_dict[i] = dict1
        
    return process_dict
```
**出力結果** 
<img width="500"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2848654/f827495f-894d-fea0-a849-fbc1a34e55c2.png">
# ネスト構造の辞書を可視化
```python:example2.py
from graphviz import Digraph
from tqdm import tqdm
def make_tree(classifer:dict, DIR:str): # classiferには可視化したい辞書、DIRには保存するディレクトリを入れる
    
    for nums, unique_name in enumerate(tqdm(classifer.keys())):
        # formatはpngを指定(他にはPDF, PNG, SVGなどが指定可)
        G = Digraph(format="png")
        G.attr('node', shape='circle')

        # ノードを追加
        for i, j in classifer[unique_name].items():
            G.node(i)
            for k in j:
                if type(k) == str:
                    G.node(k)

        # 辺を追加
        for i, j in classifer[unique_name].items():
            G.edge(unique_name, i)
            for k in j:
                if type(k) == str:
                    G.edge(i, k)

        # 画像を保存（拡張子は不要）
        G.render(DIR+unique_name)
```
**出力結果（ディレクトリへ保存）** 
<img width="200"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2848654/62e19e6c-7f57-324e-13f7-ceaab08bd157.png">
**例：アジア・エスニック.png** 
![アジア・エスニック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2848654/06ce5083-3f52-5b26-76f0-149b2e72bad7.png)
# おわりに
今回は階層構造になっているデータフレームを木構造にして可視化しました。可視化することで、スッキリ整理できます。Graphvizは気軽に扱うことができて楽しいので、ぜひ使ってみてください。
# 謝辞
以下を参照しています。ありがとうございます。

https://qiita.com/vegetal/items/6d8f036ab5b7b37b3d74

https://graphviz.readthedocs.io/en/stable/manual.html
CONTEC社のGPIOボード(1)

# はじめに

Pythonを利用したGPIOボードの使い方を説明します。
最近、CONTEC社のボードでPythonサポートが始まったので、そのボードを利用することにしました。
但し、製品と提供しているマニュアルや、Webページのダウンロード案内がわかり難く、配布するソフトのバージョンが新旧が混ざっているなどの課題が多くある。その課題の解決のため、2022年11月時点でのこのボードを利用する最新情報にまとめることにしました。

# ボードの説明
製品名：コンテック 絶縁型デジタル入出力ターミナル 
モデル番号：DIO-0808LY-USB
IO数:デジタル出力8本、デジタル入力8本
価格：35,000円程度（税込）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/e93acbba-3525-f693-0b6f-65726ff537ed.png)

# ドライバインストール (Windows)
1. API-DIO(WDM)のドライバをタウンロードしてください。
    1. リンク：https://www.contec.com/jp/download/contract/contract2/?itemid=8f8212f8-2dc1-4605-afd4-2d4867e50873&downloaditemid=14506a61-ede1-4dc4-a335-2b5fc031ebcb
    1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/21381cb2-4654-9ebe-1f98-6573399d723b.png)
    1. ファイルの圧縮を解凍した後、下記のフォルダでSetupファイルを実行します。
        1. \LZF826DIOWDM_960F\INF\WDM\Dio_forWin10
        1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/0209331a-4cee-444d-a358-90059d232961.png)
        1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/a72ac615-7fef-dbd1-2c97-28311bce2e43.png)
        1. 続けて設置を完了します。
        1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/cc1db1bc-40de-83a1-a565-6e722bcfc940.png)


# 動作の確認
1. Windows Control Panel -> Device Managerに行き、下記の画面が出るかを確認します。CONTEC Devices - DIO....が出ればOKです。
1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/a51bfe39-1334-d1f2-90bd-54a6f166a101.png)
1. DIO...を選択し、マウスの右クリックー＞プロパティ画面を出します。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/c11e1401-ecd9-cd70-8272-e4bd1f174eab.png)
1. 共通設定タブに行き、診断ボタンをクリックしてください。
1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/4ca03a3a-100d-faca-a5af-7c793d7c1096.png)
1. 下記の診断プログラムで入力ポート、出力ポートの動作を確認してください。
1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/35d38e9a-a5c4-cfae-d963-ce65d9cea287.png)

# 回路の配線
参考回路図を掲載します。PLCとの通信を想定した場合、別途DC24V電源を用意する必要がございます。
## 外部入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/ff1fc0eb-efdd-90f3-8c0f-d8df1cd8f6f3.png)
例：スイッチでBit7（ポート7番）に入力を確認
![PXL_20221112_065050103.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/419eaab2-902c-9797-bbb7-14e7eae96d54.jpeg)
![PXL_20221112_065059330.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/fd53ec2b-225c-03c1-f906-19ab50960c33.jpeg)


## 外部出力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/27e75c1e-4351-ed2a-6439-e5ccd8ef8c16.png)
例：LEDで出力を確認
![PXL_20221112_064839067.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208980/e122081e-98f6-ee8d-8815-1678dc1b5c78.jpeg)

#まとめ
1. GPIOのCONTECボードを紹介しました。
1. ドライバインストール方法を説明しました。

#次回の記事の予告
1. Pythonで制御する方法をご紹介します。
Liberty on Alpine Linux Part2


[Liberty on Alpine Linux](https://qiita.com/suzanHud/items/176de7623f9abd9b7b56)では[ibmjava](https://hub.docker.com/_/ibmjava/)をAlpine Linuxに導入後、Liberty Serverを導入していました。Alpine Linuxを3.16.3/3.17.0にバージョンアップするとIBM Javaのインストールが失敗してしまう。
```
JRE libraries are missing or not compatible....
```
[websphere-liberty](https://hub.docker.com/_/websphere-liberty)ではIBM JREの8.0.7.20が動いているので、メッセージの通りライブラリが足りないのでしょう。それは別途調べるとして、OpenJDKで試してみた。

# Dockerfile例
```docker:dockerfile
FROM scratch
ADD alpine-minirootfs-3.20.1-x86_64.tar.gz /

RUN apk update \
    && apk add --no-cache unzip \
    && apk --no-cache --virtual .build-deps add binutils tzdata \
    && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
    && echo "Asia/Tokyo" >  /etc/timezone

# Install OpenJDK
ENV JAVA_HOME="/usr/lib/jvm/default-jvm"
RUN apk add openjdk11

# Has to be set explictly to find binaries 
ENV PATH=$PATH:${JAVA_HOME}/bin

# Install WebSphere Liberty
ENV LIBERTY_VERSION 24.0.0.7

ARG LIBERTY_URL 
ARG DOWNLOAD_OPTIONS=""

RUN LIBERTY_URL=${LIBERTY_URL:-$(wget -q -O - https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/wasdev/downloads/wlp/index.yml  | grep $LIBERTY_VERSION -A 6 | sed -n 's/\s*kernel:\s//p' | tr -d '\r' | head -1)}  \
    && wget -q $DOWNLOAD_OPTIONS $LIBERTY_URL -U UA-IBM-WebSphere-Liberty-Docker -O /tmp/wlp.zip \
    && unzip -q /tmp/wlp.zip -d /opt/ibm \
    && rm /tmp/wlp.zip

ENV LANG=ja_JP.UTF-8 LANGUAGE=ja_JP.UTF-8

RUN /opt/ibm/wlp/bin/server create
RUN /opt/ibm/wlp/bin/installUtility install defaultServer

EXPOSE 9080 9443

CMD ["/opt/ibm/wlp/bin/server", "run", "defaultServer"]
```

起動すると以下のメッセージが出力された。

```
OpenJDK 64-Bit Server VM バージョン 11.0.24+8-alpine-r0 (ja_JP) で、defaultServer (WebSphere Application Server 24.0.0.7/wlp-1.0.91.cl240720240701-1102) を起動しています
[監査      ] CWWKE0001I: サーバー defaultServer が起動されました。
[監査      ] CWWKE0100I: この製品は、開発使用向け、および限定的な実動使用向けにライセンスが交付されています。 全ライセンス条項は以下で表示可能です: https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/wasdev/license/base_ilan/ilan/24.0.0.7/lafiles/ja.html
[警告      ] CWWKF0009W: サーバーは、いずれのフィーチャーもインストールするようには構成されていません。
[監査      ] CWWKF0012I: サーバーは次のフィーチャーをインストールしました。[]。
[監査      ] CWWKF0011I: defaultServer サーバーは、Smarter Planet に対応する準備ができました。defaultServer サーバーは 1.091 秒で始動しました。
```
Docker で Rust を始める 🐋🛞

[公式の Rust のイメージ](https://hub.docker.com/_/rust)を使用します。

## 手順

### 1. `docker-compose.yml` を作成

```yml:docker-compose.yml
services:
  rust:
    image: rust:latest
    volumes:
      - .:/projects
    working_dir: /projects
    environment:
      - USER=user

```

※ サービス名の `rust`、ディレクトリ名の `projects`、Rust のバージョン、 環境変数の `user` は任意の値です。変更した場合は続く手順 2 および 3 のコマンドも併せて変更してください。

### 2. 起動 🐋

```
docker compose run --rm rust
```

### 3. Cargo でプロジェクトを作成 ([Hello, Cargo!](https://doc.rust-jp.rs/book-ja/ch01-03-hello-cargo.html))🛞

```
cargo new hello_cargo
```

コマンドを実行すると `hello_cargo` ディレクトリが作成される。

```
.
├─ hello_cargo
│   ├─ src
│   │   └─ main.rs
│   ├─ .gitignore
│   └─ Cargo.toml
└─ docker-compose.yml
```

### 4. プロジェクトのビルド、実行

```
cd hello_cargo
cargo run
```

以下が表示されます。

```
# cargo run
   Compiling hello_cargo v0.1.0 (/projects/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 0.77s
     Running `target/debug/hello_cargo`
Hello, world!
```

※ cargo は Rust のパッケージマネージャ兼ビルドシステムです。

## 参考

- [Rust Development with Docker - YouTube](https://youtu.be/kh1GMRFkzT4) ( [Tom McGurl](https://twitter.com/tom_mcgurl) )
- [The Rust Programming Language 日本語版 - The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/title-page.html)
Salesforce認定Platformアプリケーションビルダー試験の公式サンプル問題解説してみた-13

こんにちは

Salesforce認定Platformアプリケーションビルダー試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

https://trailhead.salesforce.com/ja/content/learn/trails/platform-app-builder-certification-prep

今回は

Platform アプリケーションビルダー試験に向けた学習
認定 Platform アプリケーションビルダー資格の受験準備: Data Modeling and App Deployment (データモデリングとアプリケーションリリース)
ビジネスロジックとプロセス自動化の復習

にある問題2問目をご紹介します

なお今回の内容は動画でも公開しております

https://youtu.be/ofMeJPCJVaw

![フロー０１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/3bde9a96-57a0-5e64-5413-61c7434f752f.png)

正解はAとCです

こちらのヘルプにも書いてある通り

https://help.salesforce.com/s/articleView?id=sf.process_overview.htm&type=5

＞Flow Builder を使用することを強くお勧めしますが、プロセスビルダーを使用しても、ビジネスプロセスを自動化しやすくなり、作成時のプロセスを視覚的に表現できます。


ビジネスプロセスを自動化することにフローやプロセスビルダーは向いています

フローやプロセスビルダーを見ても、ワークフロールールよりも視覚的で柔軟性が高く強力なツールであることが分かります
dockerを使うときは常にdockerコマンドを使う

## dockerはホストとは別の環境で実行される

たとえばRailsのアプリケーションの開発環境をdockerで構築している場合は、ホストとは別の環境であるコンテナでアプリケーションが構築、実行されます。
ホストのrubyとdockerコンテナのrubyは別ですし、gemのインストール先も異なります。

ホストとコンテナの両方にrubyが入っているとどちらもコマンドが通ります。

### ホスト

```shell
ruby -v
ruby 3.1.0
```

### コンテナ

```shell
docker compose run --rm web ruby -v
ruby 3.1.0
```

`ruby -v`のようなバージョン確認コマンドならたいして問題になりませんが、`bundle install`のような
gemのインストールの場合は問題が起こります。

### ホスト

```shell
bundle install
```

ホストで実行すると当たり前ですが、ホストにインストールされます。

### コンテナ

```shell
docker compose run --rm web bundle install
```

こちらも同様にコンテナにinstallされます。
docker composeでvolumeしている場合はホストに同期されますが、
ホストで`bundle install`した場合とは異なる場所に同期されるため、
ホストから参照できる場所ではありません。

## コマンドの実行環境を意識する

dockerで開発をしている場合は常に`docker`コマンド,composeを使っている場合は`docker compose`コマンド経由で
コマンドを実行するようにしましょう。
例：

```shell
docker compose run --rm web bundle install
```

ホストで以下のようにコマンドを実行しても、dockerでbundle installは実行されていないのでgemを利用することはできません。

```shell
bundle install
```

プログラミングの時はググっていろいろな記事を参考にすると思います。
参考にした記事やドキュメントに「`bundle install`を実行しましょう」と書いてあるからといって
自分の環境でもそのまま使用できるとは限りません。

実際にrailsの開発ではよく使われているdeviseのREADMEに`bundle install`を実行するように書いてあります。

https://github.com/heartcombo/devise#getting-started

RailsしかりWeb系の開発でdockerはデファクトスタンダードになっていますが、READMEはdockerを前提として書いてはいません。

dockerを使っている場合は`docker compose run --rm web bundle install`(webの部分はdocker-compose.ymlのservice名と合わせる必要あり）と読み替える必要があります。

ホストで実行しているのか、dockerで実行しているのか常に意識するようにしましょう。
DockerでUbuntu+Apache+PHP8+MariaDB環境を構築

ずっとDockerは気になっていたものの実践で触れる機会が無く、新しく始めるプロジェクトでDockerでやってみようと決めていろいろ調べるところから始めたのでおかしな箇所があるかもしれません。
「これはこうしたほうが良い」というものがあったら是非教えてください。

# Ubuntu+Apache+PHP8+MariaDB構成にしたい
表題通りの構成をやっている例が見つからず、初めてということもあってdocker-compose.ymlとDockerそれぞれにどう分けて書くかなども含めて結構時間がかかりました。PHPのパッケージを使うとDebian Linuxだったり。まあそれでもいいのですが、やっぱり普段使っているUbuntuに合わせたい！ということでこだわりが捨てられず。

# ディレクトリ構成
```
├── docker
│   ├── php/
│   │   └── php.ini
│   ├── docker-compose.yml
│   ├── Dockerfile
│   └── .env
```

# docker-compose.yml
```
services:
  web:
    build: .
    container_name: ${WEB_CONTAINER_NAME}
    tty: true
    depends_on:
      - db
    volumes:
      - ./${COMPOSE_PROJECT_NAME}/html:/var/www/html
    ports:
      - ${WEB_PORT}:80
    restart: always
  db:
    image: mariadb
    container_name: ${DB_CONTAINER_NAME}
    restart: always
    ports:
    - ${DB_PORT}:3306
    volumes:
      - "./${COMPOSE_PROJECT_NAME}/mysql:/var/lib/mysql"
      - "./${COMPOSE_PROJECT_NAME}/initdb:/docker-entrypoint-initdb.d"
    environment:
      - MYSQL_ROOT_PASSWORD=pass
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER_NAME}
      - MYSQL_PASSWORD=pass
```

# Dockerfile
```
FROM ubuntu/apache2

EXPOSE 80

WORKDIR /var/www/html

# PHP8.0
RUN apt update -y && apt install -y vim
RUN apt -y install php8.1 php8.1-intl php8.1-mbstring php8.1-mysql php8.1-gd php8.1-fpm
RUN apt -y install libapache2-mod-php

ADD ./php/php.ini /etc/php/8.1/apache2

# Composerもついでに
COPY --from=composer /usr/bin/composer /usr/bin/composer
```

# .env
好みで変更してください。
```
COMPOSE_PROJECT_NAME=projectx
COMPOSE_FILE=docker-compose.yml
COMPOSE_PATH_SEPARATOR=:

WEB_CONTAINER_NAME=${COMPOSE_PROJECT_NAME}_WEB
DB_CONTAINER_NAME=${COMPOSE_PROJECT_NAME}_DB

DB_PORT=3307
DB_NAME=${COMPOSE_PROJECT_NAME}
DB_USER_NAME=${COMPOSE_PROJECT_NAME}

WEB_PORT=8080
```

# php.ini
こちらも好みで変更してください。
```
[global]
expose_php = Off
memory_limit = 128M
default_charset = "UTF-8"

[mbstring]
mbstring.language = Japanese

[Date]
date.timezone = Asia/Tokyo

[opcache]
opcache.jit_buffer_size=32M
```

あとはdocker-compose up -dすればOK。

# Dockerを触ってみて戸惑ったこと
どのパッケージに何が入っているのか分かり辛かったこと。始め、PHPはPHPのパッケージだけかと思ってdocker-compose.ymlに入れたらOSも入っていてubuntuのパッケージとバッティングしているため（多分）動作状態にならなかったり。かと思えばDBは単体だったり。
複数のものがパッケージされている場合、自分の望んでいるものと完全に合致しているかどうかは動かしてみないと分からないのが不便だなと思いました。

仕組み的に無理なのかわからないけど、全部単体で用意されていて必要なパッケージをdocker-compose.ymlに羅列すればいいだけになればシンプルでわかりやすくなるのでは？と思いつつPHPはDockerfileでインストールするようにしました。なんかこの部分が気持ち悪い。

# 知りたいこと
複数のプロジェクトをDocker上で開発したいときはコンテナを分けたほうがいいのか、それとも一つのコンテナ内部で複数持つべきか。

コンテナを分けるメリット：
あるプロジェクトで別途インストールするライブラリなどが必要な場合もあるのでそのプロジェクト専用環境にできること。

コンテナ一つに複数プロジェクトを入れるメリット：
コンテナ管理が煩雑にならないこと。そもそもコンテナ自体をバックアップしたりするのはDocker的にはイケてないっぽいけど、docker-composeで構築後にそれぞれ入れたいものはやっぱり出てくると思う。そんなときに再度入れ直すのは面倒なのでやはりコンテナのバックアップは取っていきたいと考えている。

ご意見がある方はぜひ教えていただければ幸いです。
カプセル化をphpで説明してみた

1.カプセル化とは？
外部からデータや手続きの詳細を隠蔽すること、アクセスできないようにすることを「カプセル化」と言います。
PHPでは、**private**などを用いてクラスの外から変数やメソッドにアクセスできないようにすることで、「カプセル化」を実現しています。
以下で実際のコードを見てみましょう。

2.カプセル化がされていないPHPのコード
```
//カプセル化されていないコード
class hoge {
  public function pub_func() {
    echo "public";
  }
}
$obj = new hoge();
$obj->pub_func();

//出力結果
public
```
上記では、修飾子publicでメソッドを定義しています。
この時はclassの外でメソッドを呼び出しても、メソッドが実行されることが
わかります。
クラスの外からメソッドにアクセスできることから、このコードはカプセル化がされていないことがわかります。

3.カプセル化がされているPHPのコード
```
//カプセル化されているコード
class hoge {
  private function pri_func() {
    echo "private";
  }
}
$obj = new hoge();
$obj->pri_func();

//出力結果
PHP Fatal error:  Uncaught Error: Call to private method hoge::pri_func() from global scope
```
上記では、修飾子privateでメソッドを定義しています。
この時はclassの外でメソッドを呼び出しても、「Call to private method」というエラーになってしまいます。
このようにprivateで定義されたメソッドに、クラス外でアクセスすることはできません。
これではクラスの外からアクセスできない状態なため、「カプセル化」されているといえます。
エンジニア１年目にしていたこと

2年目の11月に書いているので覚えていることだけメモ程度に残しておく。

業務系
・7月末まで研修
　→Java,C#,JS,Node.js,Reactあたりの基礎
　→横へなを解く
　→SpringBatch
・8月〜1月末
　→Java,Gosuを使った開発案件　
　　＃仕様の理解が大変だった覚えがある
・2月〜4月
　→Node.jsを使ったアプリのAPIサーバー開発
　→Reactを使った管理画面の開発
　　＃主に修正作業がメイン

勉強系
・基本情報の復習
・pythonのseleniumを使ったスクレイピングの学習

思い出したら追記します
UWP 文字コードの字体がフォントに定義されているか調べる

# 実現したい内容

漢文などを扱っていると、フォントの選択によっては代替フォントが表示され、見た目のバランスが崩れる。あらかじめ、フォントに当該文字の字体が登録されているか調べたい。

# フォントの定義域(UnicodeRanges)を得る

Win2Dパッケージの`CanvasFontSet`を利用すると、定義域を`UnicodeRanges`で取得できる。`UnicodeRanges`は、`First`と`Last`のペアの配列。First～Lastの範囲で定義されていることを示す。

- `CanvasFontSet.GetSystemFontSet()`でシステムにインストールされているフォントの一覧を得る。
- 得た一覧の要素`CanvasFontFace`から`UnicodeRanges`を得る。

```C#:フォントのUnicodeRanges取得例
CanvasFontSet fset = CanvasFontSet.GetSystemFontSet();
IReadOnlyList<CanvasFontFace> faces = fset.Fonts;

// 日本語フォントに限定する
String jkey = "ja-jp";

foreach (var f in faces)
{
    IReadOnlyDictionary<String, String> familyNames = f.FamilyNames;
    IReadOnlyDictionary<String, String> faceNames = f.FaceNames;

    foreach (var key in f.FamilyNames.Keys)
    {
        if (!(key.Equals(jkey))) { continue; }
        // エイリアス排除
        bool t = _Items.Exists(x => x.FamilyName.Equals(f.FamilyNames[key]));
        if (t) { continue; }

        // KanjiFontは自前のクラス
        KanjiFont kf = new KanjiFont();
        kf.Key = key;
        kf.Family = new FontFamily(f.FamilyNames[key]);
        kf.UnicodeRanges = f.UnicodeRanges;

        // 漢字の"一"の有無で判定
        if (f.HasCharacter(_Kanji_ichi))
        {
            _Items.Add(kf);
        }
    }
}
```

# フォントの定義域を走査する

実際のフォントを見てみると、UnicodeRangesは細切れに定義されている。定義域それぞれについてFirstとLastの間に調べたい文字コードがあるか確認する。

- code: 調べたい文字コード(Int32)
- 漢字は、`UnicodeGeneralCategory.OtherLetter`で定義

```C#:日本語の漢字の走査例
UnicodeGeneralCategory uc = UnicodeCharacters.GetGeneralCategory((UInt32)code);
if (uc == UnicodeGeneralCategory.NotAssigned) { return false; }
if (uc == UnicodeGeneralCategory.OtherSymbol) { return false; }

bool found = false;
foreach (var r in UnicodeRanges)
{
    if (r.First <= code && r.Last >= code)
    {
        found = true;
        break;
    }
}
if (!found) { return false; }

// codeを文字に変換
Char kanji;
try
{
    kanji = Char.ConvertFromUtf32(code).ToCharArray()[0];
}
catch (ArgumentOutOfRangeException oe)
{
    return false;
}
```
TypeScriptでAtCoderを始めた

# AtCoderを始めた

興味はずっと前からあったので~~AWS資格勉強の息抜きに~~始めた。
アルゴリズム力が必要な業務ではないので、業務にも役立つようにという観点から言語は最近よく使っているTypescriptを選択した。
Rated参加回数はまだ5回に満たず、足りないところはあるかもしれないがAtCoderのTypescript情報は少なそうなので一旦公開。

# ソース

https://github.com/sakananonitsuke/atcoder-templates

# 解説

VSCodeでコーディング -> AtCoderにコピペとかはやってられないので
[AtCoder CLIのチュートリアル](http://tatamo.81.la/blog/2018/12/07/atcoder-cli-tutorial/)を参考にCLIでテスト・提出可能な環境を作った。
tstlなるC++のstl移植がAtCoderでも使えるらしいので、それもdependencyに入っている。~~（自分はまだtstl必要なレベルに達していない）~~

vscodeで試しているが、vscode依存の設定は入れていないはずなので他の環境でも動くはず。

## 実行方法

コンテストフォルダを`acc new {コンテストID}`で作成。

Main.tsに回答を書いた後、各タスクフォルダで
- `npm run test` -> ローカルテスト
- `npm run submit` -> 提出（確認なし）

ができるようにnpm scriptを入れている。

自分の環境ではコンテストフォルダの親フォルダでこのテンプレートの依存性をインストールしているので、タスクごとに`npm ci`しなくても即実行できるようにしている。

## node管理
nodeのバージョンはローカルマシンに入っていたnodebrewがあまりメンテされなくなっているという話を耳にしたので[volta](https://docs.volta.sh/guide/getting-started)に乗り換えてみた。
docsもわかりやすく不便ないのでこれからも使おうと思う。（あと、Rust製で速い！）

## ハマったところ

最初は適当にインストールしたnode/ts-node/typescriptを使っていたがローカルではACでもsubmitするとREになるということが起きた。null合体演算子等がエラーになっていたっぽい。

バージョン周りだろうと調べると、typescriptのバージョンは合っていたがnodeのバージョンがずれていた。
[公式の環境情報](https://atcoder.jp/contests/APG4b/rules?lang=ja)のtypescriptの行にはtypescriptのバージョンしか明記されていないが、トランスパイルされたjsが動くのはjavascriptの環境なのでそちらのnodeのバージョンとローカルのnodeのバージョンも合わせる必要があった（当たり前だが）。

nodeのバージョンを合わせたら解決したので多分OK。

# 課題

自作ライブラリを作ったときに楽に使えるようにしたい。
テンプレートにライブラリファイルを含めておいてbundleしてjavascriptとして提出するのが簡単な気がするが、AtCoderの提出画面でbundle後のソースしか見れなくなってしまうのに若干抵抗がある。
一方で、Main.tsに全ライブラリを書き連ねるのもコードが見にくくなって微妙だが妥協すべきなのか…

いいアイデアが実現できたら追記予定。
データ置き場の引っ越し等でパスが変更になる時に、コードやバッチファイル内で使用しているパスはそのまま温存して使いたい場合

PC内のデータを整理して移動する・データ置き場の引っ越し等で、大元のパスが変更になってしまう時に、**ソースコードやバッチファイル内で使用しているパスは変更せずそのまま温存して使いたい**場合は、

Windows OSにある、ファイル・フォルダパスへの参照リンクを作成する機能(リンク機能、ショートカットのように別の場所にあるファイル・フォルダへリダイレクトし、**リンクがあたかも実在するパスのように利用できる機能**)を用いて、コード内のパスは変更せずに、データ置き場を変更することが出来ます。

入力データの置き場や、ライブラリ的なコードの置き場など、直接パスが参照されるようなデータを他の場所へ移動したい時に、パス参照切れ問題を手っ取り早く解決できておすすめです。

#   例

古いデータ置き場(フォルダへのパスA)から、新しいデータ置き場(フォルダへのパスB)へ、データの場所を移動する場合、

フォルダへのパスAから、フォルダへのパスBへ、フォルダを移動させた後で、(フォルダへのパスAは移動後で既に存在しない状態)

3種類あるリンク作成機能: **ジャンクション・シンボリックリンク・ハードリンク**のうち、例えば、(作成時に管理者権限が不要の)ジャンクションを用いて、

通常のWindowsコマンドプロンプトから、以下のコマンドを実行、
```
D:\...>mklink /j "フォルダへのパスA" "フォルダへのパスB"
フォルダへのパスA <<===>> フォルダへのパスB のジャンクションが作成されました
```

すると、パスAの場所に、ジャンクションが作成され、ショートカットの矢印が付いたフォルダのアイコンが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606924/982b2d25-2926-2ae1-17c3-060bce75fc19.png)

これで、パスAの場所には以前のデータが無いにもかかわらず(実際にはリンク表示があるだけで、実際のデータはパスBの場所にあるのに)、**ソースコードやバッチファイル内で"フォルダへのパスA"を継続して使用しても、そのままエラーなく実行することが出来ます**。
```py
# Pythonソースコード例:
file = open("フォルダへのパスA\\test-file.txt")
# ※↑実際は"フォルダへのパスB\\test-file.txt"へのファイルアクセスになる
file.readline()
...
```
```bat
rem バッチファイル例:
start "フォルダへのパスA\test-file.exe"
rem ※↑実際は"フォルダへのパスB\test-file.exe"の呼出しになる
...
```


#   参考

リンクを作成する機能、3種類: ジャンクション・シンボリックリンク・ハードリンクをそれぞれ試した結果の詳細はこちら。

https://qiita.com/dl_from_scratch/items/3c3296f4198e43277f4d
進数計算（2進数、10進数、16進数）

# １，はじめに
　現在2か月の職業訓練を受けていて、その中で進数計算について学んだので、記事を書く練習も兼ねてまとめてみたいと思います。
　教員時代、算数のちょっとした発展課題で4進数の計算問題をだしたことがあったのですが、自分も勉強不足で子供と一緒に悪戦苦闘したのは良い思い出です。ｗ

# ２，2進数とは
　そもそもＰＣは電気で動いているので、電気が`通っている`・`通っていない`の２つで信号を区別しているので、０と１の二つが使われています。

　０と１のみで考えるので、０→１→１０というように位が変わります。

ちなみに、人間は指が10本だから10進数という説もあるそうな。
指で計算している小学生をたくさん見てきたから確かにー！:flushed:

# ３，16進数とは
　16進数はbyte単位での計算と相性が良い進数で、
０→１→２→・・・・９→A→B→C→D→E→F→　１０
と16個の数字で位が変わります。

# ４，進数変換
## 2進数　⇒　10進数
　2進数の「1011」を10進数に変換します。

1011（2進数）　
＝　$2^3 * 1 +2^2 * 0 + 2^1 * 1 + 2^0 * 1 $
＝　$8 * 1 + 4 * 0 + 2 * 1 + 1 * 1 $
＝　$8+2+1 $
＝　$11$（10進数）
各桁に２の重みをかけて足すだけですね。

## 10進数　⇒　2進数
9（10進数）
ひたすた２で割り続けます。
$11 / 2 = 5...1$
$ 5 / 2 = 2...1$
$ 2 / 2 = 1...0$
$ 1/2=0...1$
余りは下から読んでいきます。
1011(2進数）


※１６進数も同じ方法ですので簡単に、、、（省略してすみません。）
アルファベット部分は自分で数えるしかないですね。
##### 16進数→10進数
各桁に16の重みをかけて、足す。

##### 10進数→16進数
ひたすら16で割って、その余りを下から読んでいく。

## 2進数　⇒　16進数
基本的には2進数→10進数→16進数で考えていきます。
1011→11→B

では桁が大きいもので考えてみましょう。
11101011（2進数）

まず、４つずつに分けます。
1110　1011

あとはそれぞれ→10進数→16進数と変換します。
14　　11
E　　　B
→EB（16進数）

# 補足
- 16進数は10進数と区別するために先頭に「0x」をつけることもあります。
　例）0xEB
- 2進数は場合によっては8桁のまとまりで書くこともあります。（サーバー系の方が仰っていました。）
　例）1011→0001011
- 指で2進数を数える方法が、意外と便利ですね。片手で３１まで数えられます。
　グーの状態で親指から順番に、指を立てている→１、指をおろしている→０、で順番に数えます。
　言葉で説明が難しいのです。Youtubeで調べるとたくさん出てきますので、あとは自分で…（悪しからず:sweat:）
FastAPIで自動生成されるドキュメントを保存する方法

# はじめに
FastAPI は、WebAPI を構築するためのモダンなWebフレームワークです。

https://fastapi.tiangolo.com/ja/

類似したフレームワークに、Django(Rest framework)やFlaskがありますが、大きな特徴として、コードからOpenAPIに準拠したAPIドキュメントを自動生成できることが挙げられます。/docsや/redoc、/openapi.jsonで見れるやつです。

ただ、自動生成されるドキュメントを保存する方法についてあまり日本語の情報が見つからなかったのでまとめておきます。
(フロントエンドとバックエンドで分かれて開発を行なっていて、APIの仕様だけ決めてドキュメントをGitHubPagesなどで共有、それを元にそれぞれ作業を進めたい時などに便利かと思います。)

## openapi()メソッドを利用してhtmlを生成する

FastAPIにはopenapiスキーマを返すopenapi()メソッドというものがあるのでこれを利用します。

https://fastapi.tiangolo.com/advanced/extending-openapi/#the-normal-process


有志の方が上記を利用したPythonのスクリプトを作ってくれています。(Redocの形式で出力)

https://github.com/Redocly/redoc/issues/726

```python:python
"""Script to export the ReDoc documentation page into a standalone HTML file."""

import json

from my_app.app import app

HTML_TEMPLATE = """<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>My Project - ReDoc</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" href="https://fastapi.tiangolo.com/img/favicon.png">
    <style>
        body {
            margin: 0;
            padding: 0;
        }
    </style>
    <style data-styled="" data-styled-version="4.4.1"></style>
</head>
<body>
    <div id="redoc-container"></div>
    <script src="https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js"> </script>
    <script>
        var spec = %s;
        Redoc.init(spec, {}, document.getElementById("redoc-container"));
    </script>
</body>
</html>
"""

if __name__ == "__main__":
    with open(f"api-docs-my-project.html", "w") as fd:
        print(HTML_TEMPLATE % json.dumps(app.openapi()), file=fd)

```

下のあたりを自分のプロジェクトに合わせて変更して、同階層に配置し実行するとドキュメントが生成されます。

```python:抜粋
from my_app.app import app
```

```python:抜粋
<title>My Project - ReDoc</title>
```

あとは、GitHubPagesで公開するなり、そのままファイルを送るなりで共有できます。
paiza.ioでelixir その94

# 概要
paiza.ioでelixirやってみた。
Record使ってみた。

# サンプルコード

```

require Record

Record.is_record({User, "john", 27})
|> IO.inspect

Record.is_record({})
|> IO.inspect

record = {User, "john", 27}
Record.is_record(record, User)
|> IO.inspect

defmodule User do
	require Record
	Record.defrecord(:user, name: "meg", age: "25")
end
defmodule Main do
    import User
    record = user()				#=> {:user, "meg", 25}
    record = user(age: 26)      #=> {:user, "meg", 26}
    user(record, :name)         #=> "meg"
    user(record, age: 26)       #=> {:user, "meg", 26}
    user(:name)                 #=> 1
    user(record)                #=> [name: "meg", age: 26]
    record = user()             #=> {:user, "meg", 25}
    user(name: name) = record
    name                        #=> "meg"
end

Record.extract(:file_info, from_lib: "kernel/include/file.hrl")
|> IO.inspect



```

# 実行結果

```
true
false
true
[
  size: :undefined,
  type: :undefined,
  access: :undefined,
  atime: :undefined,
  mtime: :undefined,
  ctime: :undefined,
  mode: :undefined,
  links: :undefined,
  major_device: :undefined,
  minor_device: :undefined,
  inode: :undefined,
  uid: :undefined,
  gid: :undefined
]
```

# 成果物

https://paiza.io/projects/8prdnsBxLTGg9hiKXN0E_w

以上。
ソフトウェアエンジニアの為の SSH 鍵ペアの生成方法 2022

SSH 鍵ペアの生成
近々作り直す予定があるので備忘録を記載しておきます。
実際には Windows の msys2 bash 環境での例ですが mac ksh, linux bash でもほぼ同様で大丈夫なはずです


## 鍵を作成する
```shell
# 作業用ディレクトリの作成と移動
mkdir ~/ssh-keygen-work
pushd ~/ssh-keygen-work

# 個人用 .ssh ディレクトリの作成
mkdir ~/.ssh
chmod 700 ~/.ssh

# このマシンにログインする時に使える秘密鍵に対応する公開鍵を登録しておくファイルの作成
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# 鍵ペアの作成, 古い形式はセキュリティ的に推奨できなくなっている可能性があるので作成する時点で最適なアルゴリズムを確認すべき (新しすぎても古いサーバーで使えなかったりするのでちょうどいい所を見極めること)
ssh-keygen -t ed25519 -C 'your_name@example.com-20211217' -f 'your_name@example.com-20211217.key-with-pp'

# 鍵名に含めた key-with-pp は公開鍵には冗長なので名前を変えておく
mv ./your_name@example.com-20211217.key-with-pp.pub your_name@example.com-20211217.pub

# (一般的には非推奨) パスフレーズ解除版を作る場合にコピー
# cp ./your_name@example.com-20211217.key-with-pp     ./your_name@example.com-20211217.key-without-pp

# (一般的には非推奨) パスフレーズ解除版を作る場合に解除
# ssh-keygen -p -f ./your_name@example.com-20211217.key-without-pp

# 秘密鍵は他のユーザーが触れないパーミッションを設定しておく
chmod 600 ./your_name@example.com-20211217.key-with-pp
chmod 600 ./your_name@example.com-20211217.key-without-pp

# 一連のファイルを .ssh に移動
mv ./your_name@example.com-20211217.* ~/.ssh/

# 作成した公開鍵は authorized_keys に追記しておく
cat ~/.ssh/your_name@example.com-20211217.pub >> ~/.ssh/authorized_keys

# 作業用ディレクトリの後始末
popd
rm -rf ~/ssh-keygen-work
```

## PuTTY keygen でインポート
(Windows の場合のみ)
your_name@example.com-20211217.ppk
your_name@example.com-20211217.puttypub

## gitlab に OpenSSH 形式の公開鍵を登録
(gitlab の場合の例、但し github や GHE, Bitbucket でも似たようなページがあったはず) 
URL は https://brabrabra.example.com/-/profile/keys のような形
```~/.ssh/your_name@example.com-20211217.pub
ssh-ed25519 -------------------------------------------------------------------- your_name@example.com-20211217
```


## SourceTree Options General SSH Key に ppk を登録
Windows の場合に設定する.
Mac の場合は指定できないので, ~/.ssh/config に指定して, 更に設定で embedded git ではなく system git を使用するようにする
```~/.ssh/config
Host github.com
    IdentityFile ~/.ssh/your_name@example.com-20211217.key-without-pp
    User git
```


## Pagent に ppk を登録
(Windows の場合)
explorer のアドレスに shell:startup を指定して開き, pageant.exe へのショートカットの引数に ppk を指定

target: (リンク先) のパスは PuTTY を実際にインストールしたパスに読み替えて下さい。

ppk ファイルは target: に実行ファイルのパスに続けて引数として指定します。複数の ppk を指定できます。
```:target:(リンク先)の例
"C:\Users\your_name\programs\PuTTY\pageant.exe" "C:\Users\your_name\.ssh\your_name@example.com-20211217.ppk" "C:\Users\your_name\.ssh\your_name@example.com-20211220.ppk"
```


## git コマンドを直接使用する場合の id_rsa 以外の名前の鍵の指定方法
```
GIT_SSH_COMMAND="ssh -i ~/.ssh/your_name@example.com-20211217.key-with-pp -F /dev/null" git fetch
```
paiza.ioでelixir その93

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
円グラフを描画せよ。

# サンプルコード

```
IO.puts """
<!doctype html>
<html>
<head>
<style type="text/css">
* {
  margin: 0;
  padding: 0;
  border: 0;
}
body {
  background: #fdd;
  font: 30px sans-serif;
}
</style>
</head>
<body>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<div id='chart'></div>
<textarea id="koko0"> 
"""
for i <- 0..7 do 
    v = :math.sin(i * 440.0 * 2.0 * :math.pi / 6000.0) + 1.0;
    IO.puts(v)
    IO.puts ","
end
IO.puts """
</textarea>
<script type="text/javascript">
google.load("visualization", "1", {
    packages: ["corechart"]
});
var x0 = document.getElementById('koko0').value;
var x = x0.split(",");
var res = [['x', 'sin'],];
for (var i = 0; i < 7; i++)
{
    res.push([i + "a", x[i] / 1]);
}
google.setOnLoadCallback(function() {
    var data = google.visualization.arrayToDataTable(res);    
    var options = {
        title: 'sin波',
        //hAxis: {
        //    title: 'x'
        //},
        //vAxis: {
        //    title: 'y'
        //}
    };    
    var chart = new google.visualization.PieChart(document.getElementById('chart'));
    chart.draw(data, options);
});
</script>
</body>
</html>
"""

```

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e83c1c5b-a35e-9a2e-7b45-50da68d79177.png)


# 成果物

https://paiza.io/projects/8G0DF8mmZbeONgyRC-wQMw?language=elixir


以上。
paiza.ioでelixir その92

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
折れ線グラフを描画せよ。

# サンプルコード

```


IO.puts """
<!doctype html>
<html>
<head>
<style type="text/css">
* {
  margin: 0;
  padding: 0;
  border: 0;
}
body {
  background: #fdd;
  font: 30px sans-serif;
}
</style>
</head>
<body>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<div id='chart'></div>
<textarea id="koko0"> 
"""
for i <- 0..100 do 
    v = :math.sin(i * 440.0 * 2.0 * :math.pi / 20000.0);
    IO.puts(v)
    IO.puts ","
end
IO.puts """
</textarea>
<script type="text/javascript">
google.load("visualization", "1", {
    packages: ["corechart"]
});
var x0 = document.getElementById('koko0').value;
var x = x0.split(",");
var res = [['x', 'sin'],];
for (var i = 0; i < 100; i++)
{
    res.push([i, x[i] / 1]);
}
google.setOnLoadCallback(function() {
    var data = google.visualization.arrayToDataTable(res);    
    var options = {
        title: 'sin波',
        hAxis: {
            title: 'x'
        },
        vAxis: {
            title: 'y'
        }
    };    
    var chart = new google.visualization.LineChart(document.getElementById('chart'));
    chart.draw(data, options);
});
</script>
</body>
</html>
"""


```

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f0459b49-6302-fb76-5c35-805f7c932688.png)


# 成果物

https://paiza.io/projects/gIK_G3uYLacoGhHbtqepAg?language=elixir


以上。
paiza.ioでelixir その91

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
棒グラフを描画せよ。

# サンプルコード

```


IO.puts """
<!doctype html>
<html>
<head>
<style type="text/css">
* {
  margin: 0;
  padding: 0;
  border: 0;
}
body {
  background: #fdd;
  font: 30px sans-serif;
}
</style>
</head>
<body>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<div id='chart'></div>
<textarea id="koko0"> 
"""
for i <- 0..15 do 
    v = :math.sin(i * 440.0 * 2.0 * :math.pi / 6000.0) + 1.0;
    IO.puts(v)
    IO.puts ","
end
IO.puts """
</textarea>
<script type="text/javascript">
google.load("visualization", "1", {
    packages: ["corechart"]
});
var x0 = document.getElementById('koko0').value;
var x = x0.split(",");
var res = [['x', 'sin'],];
for (var i = 0; i < 15; i++)
{
    res.push([i, x[i] / 1]);
}
google.setOnLoadCallback(function() {
    var data = google.visualization.arrayToDataTable(res);    
    var options = {
        title: 'sin波',
        hAxis: {
            title: 'x'
        },
        vAxis: {
            title: 'y'
        }
    };    
    var chart = new google.visualization.ColumnChart(document.getElementById('chart'));
    chart.draw(data, options);
});
</script>
</body>
</html>
"""

```

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f3c424bc-5fef-5786-6deb-6c38925a6f6f.png)


# 成果物

https://paiza.io/projects/8MGVVT6m3wv7qn1twzR-IQ?language=elixir


以上。
Seleniumとchromedriver備忘録(mac)

# seleniumのインストール


```
python -m pip install --upgrade pip
```

```
pip install selenium
```

# chromedriver

chromeのバージョンを確認

[ここ](https://chromedriver.chromium.org/downloads)でchromeのバージョンに適したchromedriverのバージョンを探す

こんな感じでインストール。最後の数字はchromedriverのバージョン

```
pip install chromedriver-binary==107.0.5304.62
```
GoでWebサーバーを作成する2

# はじめに
GolangでAPIサーバーを作るときに調べたことを自分用のメモとしてまとめます。

## 文法関連
* 命名規則
他パッケージからアクセスできるものは先頭大文字にする

[他言語プログラマが最低限、気にすべきGoのネーミングルール](https://zenn.dev/keitakn/articles/go-naming-rules)
[Golangでの命名規則におけるベストプラクティス](https://zenn.dev/kenghaya/articles/1b88417b1fa44d)

* if文

* for文
[Go言語(golang)のループ for, for..range, foreach, while](https://golang.hateblo.jp/entry/2019/10/07/171630#foreach-for--range)


* append関数
スライスに要素を追加する。
配列の長さを指定しないものがスライス。
C#でいうListみたいなもの。
```cafes = append(cafes, cafe)```

[【Go】基本文法④(配列・スライス)](https://qiita.com/k-penguin-sato/items/daad9986d6c42bdcde90)

* 連想配列
配列の要素の指定が数字だったのが、keyで指定できるようになったやつ。

```
以下は要素の指定がstring型のkeyで、要素がstringということ
map[string]string
```

[【Go】基本文法⑤(連想配列・ Range)
](https://qiita.com/k-penguin-sato/items/a320072fa09502bde3e9)

## 引っかかったエラー
1.構造体の宣言に関するエラー
変数の宣言方法がよくわからなくてエラーになった
[Error: struct Type is not an expression](https://stackoverflow.com/questions/27455170/error-struct-type-is-not-an-expression)
2.パッケージのimportに関するエラー
お互いにパッケージをimportしてはいけないよというエラー
[Golang で import cycle not allowed に引っかかった人へ](https://qiita.com/ko-watanabe/items/0141fa20da9f6f30b754)
Go [O1o0] 目指せ！第１４回ＵＥＣ杯コンピューター囲碁大会＜出場準備編＞

Go [O1o0] 目指せ！第１４回ＵＥＣ杯コンピューター囲碁大会＜出場準備編＞

# 概要 - 参加形態

📖 [参加要件](http://entcog.c.ooco.jp/entcog/new_uec/requirements.html)  

## おおまかな視点

自宅のデスクトップPCから、インターネット経由で、インターネット上の対局サーバーにつなぐことにする  

開発者本人は ノートPC を持って 自宅 ～ 京王線調布駅 ～ 電気通信大学 と移動する  

大会の部屋で ノートPC を起ち上げ、 TeamViewer などを用いて 自宅のデスクトップPC にリモート・ログインする  

その画面で、対局開始時刻前に GUIへ 対局情報を入力し、ログイン、待機すればよい  

## こまかな視点

自宅のデスクトップPC の中では、  

* コンピューター囲碁エンジン
* コンピューター囲碁GUI（CgfGoBan）

を起動し、インターネット経由の対局ができればよい