OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScript カウントダウンタイマー「なぜこの書き方なのか？」と悩んだこと 

#はじめに
フロントエンドエンジニアを目指しております、プログラミング歴5ヶ月の者です。

現在、JavaScriptの基礎を身につけるため[『確かな力が身につく JavaScript 「超」入門編』](https://www.amazon.co.jp/dp/B017AP49IQ/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)で勉強中です。

本書のなかで、カウントダウンタイマー(Udemyのセールなどでよく見るような、"セール終了まで○時間○分○秒"と表示されるアレです)の処理が少しややこしく、「なぜこの書き方なんだろう」と少し考え込んでしまったので、備忘録として残そうと思います。




## 本書で紹介しているコード
getTime()メソッドで、まず全体の残り時間をミリ秒で算出し(restに代入)、それからそれぞれの単位(時、分、秒)の残り時間を算出しています。
*※getTime()は、1970年1月1日0時からの時間をミリ秒で取得するメソッド。*

```countdown.js
function countdown(due) {
  const now =  new Date();
  const rest = due.getTime() - now.getTime(); //残り時間をミリ秒で算出
  
  const sec = Math.floor(rest / 1000) % 60;
  const min = Math.floor(rest / 1000 / 60) % 60;
  const hours = Math.floor(rest / 1000 / 60 / 60) % 24;
  const days = Math.floor(rest / 1000 / 60 / 60 / 24);
  const count = [days, hours, min, sec];

  return count;
}

let goal = new Date();
goal.setHours(23);
goal.setMinutes(59);
goal.setSeconds(59);
console.log(countdown(goal));

const counter = countdown(goal);
const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
document.getElementById('timer').textContent = time;
```

##これじゃダメなの？と思ったコード
正直、ミリ秒からの算出がややこしく、上記コードを理解するのに少し苦労してしまいました。(「なんで剰余算演算子(割り算の余り)なんだ..???」とか..)

率直に、「単純に "期限日時の数値 - 現在日時の数値" じゃダメなの？」と思ってしまいまして(例:「23時 - 22時」、「59分 - 30分」など)、そこで浮かんだのが以下のコードです。
※変更点は countdownファンクション内の処理のみです。

```mycountdown.js

function countdown(due) {
const now = new Date;
const rest = due.getTime() - now.getTime();

const sec = due.getSeconds() - now.getSeconds();
const min = due.getMinutes() - now.getMinutes();
const hours = due.getHours() - now.getHours();
const days = due.getDay() - now.getDay();
const count = [days, hours, min, sec];

  return count;
}

//以下は countdown.js と同じ
let goal = new Date();
goal.setHours(23);
goal.setMinutes(59);
goal.setSeconds(59);
console.log(countdown(goal));

const counter = countdown(goal);
const time = `${counter[1]}時間${counter[2]}分${counter[3]}秒`;
document.getElementById('timer').textContent = time;
```

get〜メソッドで単純にそれぞれの数値を取得して、算出する方法です。
(23時59分59秒を期限としているので、例えば現在時刻が20時00分00秒の場合、残り時間を「3時間59分59秒」と表示させます)

##月と日の残りの計算がおかしくなる可能性がある
そもそも変数 `goal` に月日を設定していないので当たり前ですが、mycountdown.js のコードだと、「本日中(23時59分59秒まで)を期限に設定している場合」のみ使えるコードになってしまいます。

どういうことかと言うと、例えばもし翌日以降を期限日として設定し、それぞれ現在時刻と期限日を以下のパターンにした場合、 1(期限に設定した日にち) - 31(現在の日にち) = -30で、残りの日数は 「-30日」になってしまいます。

**・現在時刻 → 「10月31日00時00分00秒」
・期限日 → 「11月1日23時59分59秒」**


また、残り月(表示するケースはあまりなさそうですが)に関しても、以下のパターンの場合は、1 - 12 で残りの月は「-11ヶ月」となってしまいます。

**・現在時刻  → 「12月31日00時00分00秒」
・期限日 → 「1月1日00時00分00秒」**



##「なぜこの書き方なのか？」を考えるようにする

今回の場合、一見 「mycountdown.js のコードでもいいのでは？」と思ってしまうのですが、自分なりに深掘りすると、不十分なコードだと気がつくことができました。

初学者のうちは、難しいコードに出くわすと、コードの意味をきちんと理解するのに苦労することがよくあるのではないかと思います。そんなときは、「何かしらの意味があってこの書き方をしているのだ」ということを念頭において考えると、一歩先の理解へとつながるのではないかと思いました。


こちらの記事におきまして、もしズレた解釈をしてしまっているようでしたらご指摘いただければと思います。
Catalinaでデフォルトシェルがzshになり、pyenvが起動しなくなる件への対処

みんな大好きなMacOSのメジャーバージョンアップ。
Catalinaにバージョンアップしたらデフォルトのシェルスクリプトがzshに変わっており、思わぬ挙動になっていたので整理しておく。
起きたこと
-
1. catalinaにバージョンアップしたら、デフォルトのシェルがzshに変わっていた。(全然気が付かなかった)
1. 当然、.bash_profile からの移行は自動で行われないため、ロード時の設定が反映されない。
1. pyenv がロードされず、パスがデフォルトのままになるため、ローカルに最初からインストールされている python が有効になった。
2. ローカルの pip にはモジュールを入れていないので、プログラムが起動しない。

対処したこと
-
zshで生きていこうと思い、[公式](https://github.com/pyenv/pyenv#basic-github-checkout) に「Zsh note: Modify your ~/.zshenv file instead of ~/.bash_profile.」とあったので、.zshenv に移設するも、pyenv コマンドが見つからないというエラーで怒られた。
ひどい話である。

```text:.zshenv(エラー)
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi
```

答えとしては、[公式のトラブルシュート/FAQ](https://github.com/pyenv/pyenv/wiki#which-shell-startup-file-do-i-put-pyenv-config-in) を読んだら、「Which shell startup file do I put pyenv config in?」とあった。
通常は .zshrc に記載するものらしい。

```text:.zshrc
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi
```

こちらで問題なく動いた。
Dockerにgraphvizを入れる方法

# 対象
この記事はオライリー・ジャパン「Pythonではじめる機械学習」2.3.5 決定木でエラーが出た人向けです。

# 環境
- Ubuntu 18.04LTS
- Dockerで仮想環境
- Python 3.6
- Jupyter notebook

# 状況
In[55]
`melearn.plots.plot_animal_tree()`
を実行したらエラーが出た

# 対処
### graphvizがインストールできてないかも

#### apt-getコマンドでパッケージ本体をインストールする
`apt-get update`
`apt-get install graphviz`
#### pipコマンドを使いpython用のラッパーをインストールする
`pip install graphviz`

### ハマったポイント
- pip install graphvizだけでいいかと思ってたらだめだった
- apt-get install graphvizをしたら先にupdateしろ、と言われた

# 参考
- [Ubuntu環境でkeras使ってplot_modelしようとしたらエラーになったので対処したお話](https://qiita.com/gangun/items/1e31ed7a7a1ce6737fa5)
【Go】【React】GORMでSortするには？

GORMのScopesとOrderを使って並び替えします。
フロントはReactでGoのフレームワークechoを使ってます。
ECサイトのトップページで新着順、価格が高い順、低い順に並び替えるようなイメージです。

#React
```React:CustomerTop.js
import React from 'react';
import Button from '@material-ui/core/Button';

class CustmerTop extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      products: [],
    };
  }

  componentDidMount() {
    this.getCustomerProduct();
  }

  getCustomerProduct(order) {
    return http
      .get(`/customer/products?order=${order}`)
      .then(response => {
        this.setState({ products: response.data });
      })
      .catch(function (error) {
        console.log(error);
      });
  }

  render() {
    return (
      <div className="slide-menu">
        <Button
          className="slide-menu__item-order"
          onClick={() => this.getCustomerProducts('latest')}
        >
          新着順
        </Button>
        <Button
          className="slide-menu__item-order"
          onClick={() => this.getCustomerProducts('low')}
        >
          価格低い順
        </Button>
        <Button
          className="slide-menu__item-order"
          onClick={() => this.getCustomerProducts('high')}
        >
          価格高い順
        </Button>
      </div>
    );
  }
}

export default CustmerTop;
```
記述だいぶ省いていますが、${order}を可変にしてそこに'latest'だったり、'low'という文字列が入ってくるようにします。そしてGo側に投げます。


#Go
```Go:product.go
func (h *handler) getCustomerProducts(c echo.Context) error {
	var products []models.Product
	order := c.QueryParam("order")

	err = h.DB.
        Where("public=true").
		Scopes(func(ddb *gorm.DB) *gorm.DB {
			if order == "latest" {
				return ddb.Order("products.created_at DESC")
			}
			if order == "low" {
				return ddb.Order("price ASC")
			}
			if order == "high" {
				return ddb.Order("price DESC")
			}
			return ddb
		}).
		Find(&products).Error
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, products)
}
```
echoの[QueryParam](https://echo.labstack.com/guide/request)でパラメーターを見て、公開されている商品をorderに入ってきた文字列に対応するように並び替えることができます。
他にも在庫の有無で絞ったり、商品が属するカテゴリーで検索するときにもScopesが使えてとても便利です。
以上です。
SikuliXの導入手順（簡易メモ）

#SikuliX

インストールの簡易的なメモを残す
所要時間は30分ほど

##OpenJDK 12 Download
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265588/0cfa9106-db53-8204-7eb0-dc16cb02e3fc.png)
https://jdk.java.net/archive/

(1) OpenJDKをZipでダウンロードする
Cドライブ辺りに展開する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265588/0754f749-00a4-0631-6c8d-350c857e7e87.png)
(2) 環境変数の設定をする

## SikuliX Download
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265588/2e3ab5b6-7fec-0dcf-622e-3051fdc880f0.png)

(3) 2つともダウンロードしたら任意のフォルダに突っ込んどく

```
java -jar D:\trial\SikuliX\sikulix-2.0.0.jar
```

(4) バッチファイルを書いて実行する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265588/0feffb35-5d9f-73bc-2c46-b68156e180c3.png)

(5) Sikulixが起動する

以上で導入完了

## 余談：SikuliXの活用例
作業ゲーを自動化すれば、自分の手を離れるので快眠できる
https://youtu.be/4sBkp6W3O_Q
Go　htmlファイル呼び出し時に ends in a non-text context のエラーについて

# ends in a non-text contextについて

ginを使用してWebページを作っていた時に上記のエラーが出た
日本語のドキュメントが少なかったので少々調べるのに手間がかかったが、エラーを訳したのとGoドキュメントを読んだら理解できたので残しておく　※とても単純な話でした…

以下、エラー内容

```golang
html/template:index.tmpl: ends in a non-text context: 
{stateTag delimNone urlPartNone jsCtxRegexp attrNone elementNone <nil>}
```

ends in a non-text contextという事で「テキスト以外のコンテキストで終了する」とのこと
まぁ、和訳しただけなんですけど
要はHTMLのタグが正常に閉じられていない場合に発生するとのこと

発生した時のHTMLがこちら

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Sample</title>
</head>
<body>
    <h1>Hello World!</h1>
</body>
</html

```

最後の<html>タグが閉じられていませんね…
ケアレスミスでした…

サーバー側のエラーだと思い込んでしまったのでHTMLファイルのミスに気づくのが少し遅れました。

Goの日本語ドキュメントもよく読んでおけばしっかりと載っていましたね。

[Go 日本語ドキュメント](https://xn--go-hh0g6u.com/pkg/html/template/)
[ErrEndContextの部分について](https://xn--go-hh0g6u.com/pkg/html/template/#ErrBranchEnd)
Rails6の環境構築でエラーになる場合の対処法

新たな環境を構築して、Railsでサーバーを立ち上げるまでに躓いたことをまとめています。
主にyarnやwebpack周りです。
間違った箇所がありましたら、指摘していただけると大変助かります。

## 環境
macOS Catalina 10.15
Ruby 2.6.5p114
Rails 6.0.0


## サーバー起動
プロジェクトのルートディレクトリに移動し、以下のコマンドでサーバーを立ち上げることができます。

```console
$ rails s
```
しかし、ここで問題が発生します。

```console
$ rails s
=> Booting Puma
=> Rails 6.0.0 application starting in development 
=> Run `rails server --help` for more startup options
RAILS_ENV=development environment is not defined in config/webpacker.yml, falling back to production environment
""以下略""
```

どうやらwebpack周りの設定が原因で起動できないようです。
webpackはnode.jsで動作していて、これを動かすにはyarnというnode.jsのパッケージマネージャが必要となります。

## yarn install
yarnをインストールするには、以下のコマンドです。

```console
$ brew install yarn
```
yarnをインストールした後にサーバーを起動すると、次のようなエラーになる場合があります。

```console
========================================
  Your Yarn packages are out of date!
  Please run `yarn install --check-files` to update.
========================================


To disable this check, please change `check_yarn_integrity`
to `false` in your webpacker config file (config/webpacker.yml).
```
言われた通りに```$ yarn install --check-files```を実行すればokです。

## プロジェクトを作り直してサーバー起動
今回はwebpack周りの設定ファイルの自動生成に必要であったyarnがインストールされていないことによって、生成に不備が生じたことがサーバーを起動できない原因でした。
この段階であればプロジェクトを作り直した方が早いので、先ほど作成したプロジェクトは破棄して、新たにrails newでプロジェクトを作り直しましょう。
作り直したプロジェクトではサーバーが起動できるはずです。
[http://localhost:3000](http://localhost:3000)にアクセスして、以下の画面が表示されれば成功です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414958/921e3185-4957-8c66-9efc-22fb90b42981.png" width=50%>

## 最後に
他のところでも躓いていたような気がしたのですが、環境を整えてから記事を書くまでに2週間近く経っていたので忘れてしまいました、、、思い出したら追記します。
今回はQiita初投稿ということで、練習の意味も含めた投稿でした。新しいPCを手に入れてウキウキでコード書いてるので、今後ともお付き合いいただければと思います。
子オブジェクトの shared_ptr で親オブジェクトを保持する

c++ オタク向けの話です。
is-A 関係の shared_ptr (継承子クラスの話) は出てくるのに has-A が出てこないのでメモ。

- `std::shared_ptr<C> cptr` がある。
- C クラスにはメンバ型 M の ポインタをくれるような関数がある。
- こいつを使って `std::shared_ptr<M> mptr` を受ける関数を呼びたい。
- `mptr` がいつ消えるかはわからないので、`mptr` が消えるまで `cptr` をキープしたい。

まずは書いて見るわけです。

```c++
#include <memory>
#include <iostream>

using M = int;

class C {
 public:
  C(M m) : m_(m) { std::cout << "Hey I'm C, created " << m_ << std::endl; }
  ~C() { std::cout << "Hey I'm C, deleted " << m_ << std::endl; }

  M *GetMPointer() { return &m_; }
 private:
  M m_;
};

int main() {
  std::shared_ptr<M> mptr;
  {
    std::shared_ptr<C> cptr = std::make_shared<C>(3);
    mptr = std::shared_ptr<M>(cptr->GetMPointer());  // Wrong!
  } // ここで cptr が消滅
  std::cout << "M value is " << *mptr << std::endl;
  return 0;
}
```

実行すると死ぬ。というか環境によっては死なないかもしれないが use-after-free のあと double delete してる。
わからなければ `-fsanitize=address -O0 -g` つけてコンパイルしてみるとよい。
cptr が消滅するところで C のデストラクタが呼ばれて、そのあと mptr はありえない場所を指している。
明らかに `// Wrong!` の行がまずい。own してないポインタから shared_ptr を作ってはいけません。

ついついここで

    mptr = std::make_shared<M>(*cptr->GetMPointer());  // Not wrong, but..

とかやってしまいがちだが、これは M のコピーを作っている。
コピーを作っていいんなら別にいいし、そのほうが絶対いいと思いますが、コピーを作りたくないこともあるわけです。

delete の部分を置き換えたければcustom deleter を使うという手があります。
cptr が必ず mptr を outlive することが保証されているなら empty deleter を渡せばいいわけです。
lambda が使えるようになって empty deleter が簡単になりました。

    mptr = std::shared_ptr<M>(cptr->GetMPointer(), [](M *){}); 

これで、mptr が削除されるときに delete が呼ばれなくなります。
ですが、ただ double delete されないというだけで、上の例で削除後のポインタにアクセスしていることはかわりません (cptr より mptr が長生きしてるから)。こういうことをしているといつか変なメモリエラーを起こしてデバッグで一日消えます。

問題はいつまで mptr が生きているかわからないので、それまで cptr を生かしておきたいわけです。

## 更新 10/23

コメントで正しい指摘が来たので... shared_ptr のコンストラクタでそのものずばりの機能がありました。
    mptr = std::shared_ptr<M>(cptr, cptr->GetMPointer());
とすれば、所有権を共有する shared_ptr が作れます。検索してもなかなか出てこない (検索キーワードがないんですよ) ので気づきませんでした。
@yuki12 さんありがとうございました。解決。

## オリジナル
まあもとの文章も間違っているわけではない (まわりくどいだけ) ので、以下に残しておきます。

---
実はこれも custom deleter + lambda で解決するのでした。

    mptr = std::shared_ptr<M>(cptr->GetMPointer(), [cptr](M *){}); 

なんでこれが動くのか一見よくわかりません。渡しているのは、キャプチャがある空の lambda 関数です。
種明かしすると、deleter も仕事が終わったらデリートされるわけです。この deleter は cptr を値渡しでキャプチャしてるので、deleter の中で shared_ptr<C> の変数が一個作られて、cptr のコピーを保持しています。関数本体では使ってないんですが、この deleter が終わったときに cptr のコピーが削除されてくれるわけです。
問題の行を最後の例に変えて実行すると、ほらちゃんと M の値を使ってから C が delete されているのが見えます。

```
Hey I'm C, created 3
M value is 3
Hey I'm C, deleted 3
```

以上。
Django内部でThreadを使う場合に意図せぬコネクションリークが発生

# はじめに

Djangoの内部で時間のかかるリクエストを処理したり、バッチ処理拡張モジュールを自作する場合などに並列処理実装として自分でスレッドを作成し、利用することがある。
今回このケースで長期運用していると `Too many connections` が発生したので、その調査結果をメモ。

# 原因

- DjangoのDBコネクションは **スレッドごと** に作成される
    - **DBアクセスが発生する場合のみ**。 モデルへのアクセスがない別スレッドはそもそもDBコネクションを生成しないので問題ない
    - コネクションを利用する際、スレッドローカル相当の機能内にコネクションが保持されており、ここに無い場合は初回アクセス時にコネクションを生成する
   - https://github.com/django/django/blob/master/django/db/utils.py#L136 の ConnectionHandlerが実体で `self._connections` 内にコネクションを格納
- 自分で作った別スレッドの中でDjangoのモデルを使う場合にはDBコネクション管理を意識する必要がある
- スレッドローカル実装の定期解放処理時に解放される場合もあるが、実装が入り組んでいる場合解放されないこともあるし、待っている間にも上限は近づいてくる

# 対処

I/Oコストはかかるものの、スレッド終了時にコネクションを `close_all` で明示的に閉じることでコネクションリークは防ぐことができる。
とはいえ、そもそも何らかの理由（おそらく処理時間の問題）があって別スレッドを立てているはずなので、コネクションの作成・解放はそこまで大きな問題にはならないはず。

```python
from django.db import connections

def target():
    ''' 別スレッドで実行される関数 '''
    try:
        # 処理
    finally:
        connections.close_all()
```

ちなみに、`close_all` は "同一スレッド内の全てのDBを閉じる" 関数である（Djangoは設定に DATABASES として複数のDBを設定することが可能)。 別スレッドのDBを閉じたりはしない。
Oculus Questで録画した動画を簡単にPCにmp4ファイルとして移す方法

はじめてQiitaに記事を書きます。lainと申します。さてクエストを買ってからはいろいろなゲームで遊んでいたのですが、せっかくなので遊んでいる様子を動画に収めたいと思い、まずは公式アプリを通じてスマホにキャストして録画したけれどなぜか音声が録音されませんでした。次にクエスト内で録画してPCとクエストを有線でつなげてそのまま転送するもなぜかファイルが壊れ再生できませんでした。そこでPCとクエストをつなげてSideQuestからファイルをダウンロードしたところ無事mp4ファイルが手に入ったのでやり方をシェアしたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517673/776bb87f-f2f6-af98-8266-ccf37b28df0f.png)
普通に録画データを持ってくるとこんな風に再生できない。


# SideQuestのインストール
まずはSideQuestをインストールします。インストール方法を書いてくださっている方がすでにいるので以下のリンクを参考にしてください。
[SideQuestのインストール方法](https://vr-maniacs.com/entry/sidequest/)
少し古い記事ですので最新版のSideQuestと少しUIが変わっています。最新版をダウンロードしてください。最新版ではファイルをドラッグアンドドロップするときは画面左上にしてください。

# 録画データをSideQuestから落とす
ここまでくればあとは簡単です。まずはPCとクエストを有線でつないでください。開発者モードをONにするのも忘れずに。SideQuestの左上が緑色になりconnectedと表示されればOKです。あとは左下のFile Explorer>Oculus>Videoshotsにアクセスして再生したいファイルを選択し保存先を選んでSaveするだけです。

以上クエストの録画データをpcに持ってくる方法でした。もっといい方法があるよーという方はぜひお知らせください。
ついった: https://twitter.com/lain_vr
ActionText で truncate を使って文章を抜粋する

# 問題
Rails6 で導入された ActionText で truncate を使いたかったのですが、少し手間取ったのでメモとして残しておきます。
というのも、ActionText では単純にDBに保存されるわけではないからなんですね。

厳密に説明すると長くなるので、使い方とDBについては [こちらの記事](https://qiita.com/tomokiyao/items/3c22ca9cb916d5c99ca4) が参考にしてください。

# やりたいこと
あるモデル（Item）に内容カラム（content）があるとして、その一部のみ（20文字）を表示したいと思います。
また、表示する文章は一行にしたいので、改行と空白は削除します。
![スクリーンショット 2019-10-21 16.20.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473251/2c839933-dbce-4541-0194-485d4585178b.png)
(例なので図なんかも表示してみます。)

# 解決策
というわけで早速解決策です。
なんてことはない、既存のメソッドをただ繋げ併せただけです。

```ruby:view
strip_tags(@item.content.to_s).gsub(/[\n]/,"").strip.truncate(20)
```

１つずつメソッドを説明していきます。

### @item.content.to_s
content を取得しようとすると、ブラウザ上では登録したままの情報（画像含む）が表示されますが、railsではこんな感じで値を取得されます。

```
> item.content
=> #<ActionText::RichText id: 1, name: "content", body: #<ActionText::Content "<div class=\"trix-conte...">,
 record_type: "Item", record_id: 1, created_at: "2019-10-21 08:17:41", updated_at: "2019-10-21 08:17:41">
```

ここで `body` を使ってしまうと余計な部分もついてきてしまうので、 `to_s` を使ってhtml部分を取得します。

```
> item.content.body
=> #<ActionText::Content "<div class=\"trix-conte...">

> item.content.to_s
=> "<div class=\"trix-content\">\n  <div>あいうえおかきくけこさしすせそたちすてとなにぬねの<br><action-text-attachment
 sgid=\"BAh7CEkiCGdpZAY6BkVUSSIvZ2lkOi8vYXBwL0FjdGl2ZVN0b3JhZ2U6OkJsb2IvND9leHBpcmVzX2luBjsAVEkiDHB1cnBvc2U
GOwBUSSIPYXR0YWNoYWJsZQY7AFRJIg9leHBpcmVzX2F0BjsAVDA=--6f463dc7320f7fc75699e62fa71f08fa15e31541\" content-
type=\"image/jpeg\" url=\"http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJ
BaHBDUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b1c6b5ca78e35a7dd637110d1eaeecf970163b68/icon_test.jpg\"
 filename=\"icon_test.jpg\" filesize=\"6701\" width=\"160\" height=\"144\" presentation=\"gallery\" 
caption=\"アイコン\"><figure class=\"attachment attachment--preview\">\n  <img width=\"160\" height=\"144\" 
src=\"http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDUT09IiwiZXhwIj
pudWxsLCJwdXIiOiJibG9iX2lkIn19--b1c6b5ca78e35a7dd637110d1eaeecf970163b68/icon_test.jpg\">\n    <figcaption
 class=\"attachment__caption\">\n      アイコン\n    </figcaption>\n</figure></action-text-attachment><br>
はひふへほまみむめもやいゆえよらりるれろわいうえをん</div>\n</div>\n"
```

### strip_tags(@item.content.to_s)
`strip_tags` はhtmlタグを削除するメソッドです。

```
> strip_tags(@item.content.to_s)
=> "\n  あいうえおかきくけこさしすせそたちすてとなにぬねの\n  \n    \n      アイコン\n    \nはひふへほまみむめもやいゆえよらりる
ろわいうえをん\n\n"
```

図とかが消えて、すっきりしました！
ただ見ていただければわかりますが、まだ `\n（改行）` や `空欄` が含まれてしまっていますね。

### strip_tags(@item.content.to_s).gsub(/[\n]/,"").strip 
`gsub` メソッドで文中の余計な改行を、 `strip` で文章前後の空欄を削除します。
今回は全ての改行と文章前後の空欄を削除していますが、文中の空欄も削除する場合は、2つ目のメソッドを使ってください。

```
> strip_tags(@item.content.to_s).gsub(/[\n]/,"").strip 
=> "あいうえおかきくけこさしすせそたちすてとなにぬねの            アイコン    はひふへほまみむめもやいゆえよらりるれろわいうえを"

> strip_tags(@item.content.to_s).gsub(/[\n," "," "]/,"")
=> "あいうえおかきくけこさしすせそたちすてとなにぬねのアイコンはひふへほまみむめもやいゆえよらりるれろわいうえをん"
```

### strip_tags(@item.content.to_s).gsub(/[\n]/,"").strip .truncate(20)
最後に `truncate` メソッドで指定文字数分取得します。

```
> strip_tags(@item.content.to_s).truncate(20)
=> "あいうえおかきくけこさしすせそたち..."
```

できました！！
rewrite版Discord.pyでこういう時どうするか

#動機
「あれ、どうやって書くのだけ」がたまーにあるので......。
プログラミングはここから入ったいわゆる初心者ですので、間違えてるところがありましたらコメント等でのご指摘をお願いします。

一番良いのは公式の[APIリファレンス](https://discordpy.readthedocs.io/ja/latest/api.html)を読むことです。

###環境
- Python 3.7.2
- discord.py 1.2.4
- Windows 10 1903

`client = discord.Client()` を宣言してあるのでその都度読み替えてください。

###用意
- python3系
- pip(pip3)コマンド
- テキストエディタ等(私はIDLEを使っています。)
- discordアカウント


#基本
###最小構成
```python
import discord
#この間にいろいろ書く
discord.Client().run('Token')
```
動かすのに必要なトークン(`Token`)はDiscordのDevサイトで取得できます。
全ての処理は`discord.Client().run('Token')`より上に書いてください。

###メッセージに反応する場合の例
```python
@client.event
async def on_message(message): # メッセージが
    if message.content.startswith('/command'): # "/command"で始まるとき
        await message.channel.send('実行されました')
```
基本的には`await ~`と書いてあるところを書き換えて作ります。

###組み合わせるとこんな
```python:disbot.py
import discord
client = discord.Client()

@client.event
async def on_ready(): # 起動した1度のみ呼ばれる
    print('起動しました。')

@client.event
async def on_message(message):
    global piyo # グルーバル変数はここに

    if message.content.startswith('/command'): # 
        await message.channel.send('実行されました')

    if message.content.startswith('/guild_name'):
        await message.channel.send('ここは '+message.guild.name) # サーバー名を返す

discord.Client().run('Token')
```


#反応条件
###メッセージの先頭が一致した場合
```python
if message.content.startswith('/command'):
```
コマンド系は大抵これで作ります。気になったら「`python startswith`」でググってください。

###メッセージの一部と一致
```python
if 'hoge' in message.content:
```
特定のワードに反応するとかしたい場合にどうぞ。

#TextChannel
###メッセージを送る
```python
await message.channel.send('にゃーん')

# 特定チャンネルに送る
# xxxにはチャンネルIDを入れる
await client.get_channel(xxx).send('猫です')
```

###画像やファイルを送る
```python
pic_hoge = discord.File('hoge.png')
await message.channel.send(file=pic_hoge)
```
###送られてきたメッセージ文章はどこにある？
```python
message.content
```

#VoiceChannel
###メッセージを送った人と同じボイスチャンネルに参加する
```python
global voich
# 接続
if message.content.startswith('/connect'):
    voich = await discord.VoiceChannel.connect(message.author.voice.channel)
# 切断
if message.content.startswith('/discon'):
    await voich.disconnect()
```
`voich`は、共通で使うのでグローバル変数にしておいてください。
###再生する
```python
def check_error(er):
    print('Error check: '+ er)

voich.play(discord.FFmpegPCMAudio('piyo.mp3'), after=check_error)
```
`after=` には再生が終了したり、エラーが発生したときに呼ばれる関数を指定します。
`FFmpegPCMAudio`を使う際はffmpegへのPATHを通しておいてください。

###停止する
```python
voich.stop()
```
これだけ。

#Client

###所属しているサーバー名を見る
```python
for s in client.guilds:
    print(s)
```
プライバシーには気を付けましょう......。


###名前の下に表示される"プレイ中"を変更する
```python
await client.change_presence(activity=discord.Game(name='稼働中'))

# 解除するときはこう
await client.change_presence(activity=None)
```
MySQLのPartition使った時に出たエラーの対応メモ

###環境
AWS RDS Aurora 5.7.12

###実行

```sql

mysql>  CREATE TABLE `hoge` (
    ->   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    ->   `parent_id` int(10) unsigned NOT NULL,
    ->   `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
    ->   `modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    ->   PRIMARY KEY (`id`),
    -> ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC
    -> /*!50100 PARTITION BY HASH (parent_id)
    -> PARTITIONS 1024 */;
ERROR 1030 (HY000): Got error 168 from storage engine
```

エラー的にはストレージの空きがないみたいに見える。
色々調べても、ファイル容量を空けろみたいな記事が多いけど、RDSってそういうのどうしたらいいんだ？:thinking:

###検証

####Partitionなしで実行
結果:OK
普通のテーブルができました。
でもPartitionを使いたいんだな…。

####DBをコピーして作成して実行
結果:NG
同じエラーが返ってくる。

####テーブル名を変更して実行
結果:OK

```sql

mysql>  CREATE TABLE `fuga` (
    ->   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    ->   `parent_id` int(10) unsigned NOT NULL,
    ->   `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
    ->   `modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    ->   PRIMARY KEY (`id`),
    -> ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC
    -> /*!50100 PARTITION BY HASH (parent_id)
    -> PARTITIONS 1024 */;
Query OK, 0 rows affected (14.62 sec)
```

何もわからん…:thinking:

####対応

データベース自体が壊れていると判断。
仮のデータベースを作成し、そこに現状のデータを退避し、既存データベースをドロップして対応しました:cold_sweat:

```sql
/*退避用DBを作成*/
CREATE DATABASE temp;

/*現状のデータを退避*/
CREATE TABLE temp_db.users LIKE now_db.users;
...
INSERT INTO temp_db.users SELECT * FROM now_db.users;
...

/*壊れたDBを削除*/
DROP DATABASE now_db;

/*新しくDBを作成*/
CREATE DATABASE now_db;

RENAME TABLE temp_db.users TO now_db.users;
...

/*一時退避したDBを削除*/
DROP DATABASE temp_db;
```


参考:
https://qiita.com/kako351/items/bad052c55cfe6d85903d
https://qiita.com/whisper0077/items/06add22b692a25bd19b5



テーブル名にこだわりがないのであれば、テーブル名を変えただけが早そうです…。
今回はdevelop環境だったのでこういう対応で済ませましたが、productionではやりたくないですね…:cold_sweat:

なにかもっといい解決法があったら教えてほしいです。
CentOS 6にMariaDB 10.2をインストール（SCL）

# はじめに

Software Collection(SCL)を利用してCentOS6にMariaDB 10.2をインストール
親記事：[MySQL, MariaDBの各種インストール方法とEOLまとめ \- Qiita](https://qiita.com/witchcraze/items/72291ee035437ec83273)
参考：[Quick Start — Software Collections](https://www.softwarecollections.org/en/docs/)

## サポート

本手法で導入した場合、[Red Hat Software Collections Product Life Cycle - Red Hat Customer Portal](https://access.redhat.com/support/policy/updates/rhscl)より、2020-10がEOLだと思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### レポジトリ登録

```shell-session
# yum install -y centos-release-scl
```

### インストール

```shell-session
# cat /etc/redhat-release
CentOS release 6.10 (Final)

# yum install -y rh-mariadb102
# scl enable rh-mariadb102 bash
... 略
```

### mysql起動/停止

初回起動時には初期設定関係のメッセージが表示される。

```shell-session
# service rh-mariadb102-mariadb start
Initializing MariaDB database


PLEASE REMEMBER TO SET A PASSWORD FOR THE MariaDB root USER !
To do so, start the server, then issue the following commands:

scl enable rh-mariadb102 -- '/opt/rh/rh-mariadb102/root/usr/libexec/mysqladmin' -u root password 'new-password'
scl enable rh-mariadb102 -- '/opt/rh/rh-mariadb102/root/usr/libexec/mysqladmin' -u root -h 480e4a04dbf1 password 'new-password'

Alternatively you can run:
scl enable rh-mariadb102 -- '/opt/rh/rh-mariadb102/root/usr/libexec/mysql_secure_installation'

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the MariaDB Knowledgebase at http://mariadb.com/kb or the
MySQL manual for more instructions.

Please report any problems at http://mariadb.org/jira

The latest information about MariaDB is available at http://mariadb.org/.
You can find additional information about the MySQL part at:
http://dev.mysql.com
Consider joining MariaDB's strong and vibrant community:
https://mariadb.org/get-involved/

Starting rh-mariadb102-mariadb:                            [  OK  ]

# service rh-mariadb102-mariadb status
rh-mariadb102-mariadb (pid  486) is running...
```

```shell-session
# service rh-mariadb102-mariadb stop
Stopping rh-mariadb102-mariadb:                            [  OK  ]

# service rh-mariadb102-mariadb status
rh-mariadb102-mariadb is stopped
```

### mysql自動起動設定/設定解除

```shell-session
# chkconfig rh-mariadb102-mariadb on
# chkconfig --list rh-mariadb102-mariadb
rh-mariadb102-mariadb   0:off   1:off   2:on    3:on    4:on    5:on    6:off
```

```shell-session
# chkconfig rh-mariadb102-mariadb off
# chkconfig --list rh-mariadb102-mariadb
rh-mariadb102-mariadb   0:off   1:off   2:off   3:off   4:off   5:off   6:off
```

### 各種確認

```shell-session
# service rh-mariadb102-mariadb start
Database MariaDB is probably initialized in /var/opt/rh/rh-mariadb102/lib/mysql already, nothing is done.
If this is not the case, make sure the /var/opt/rh/rh-mariadb102/lib/mysql is empty before running mysql-prepare-db-dir.
Starting rh-mariadb102-mariadb:                            [  OK  ]

# mysql -u root -e'select version();'
+-----------------+
| version()       |
+-----------------+
| 10.2.22-MariaDB |
+-----------------+
```
webpackでleafletのバンドル

## この解説がすばらしいです

[Leaflet.jsをWebpackでbuildする｜hinosita's diary](http://hinoshita.hatenadiary.com/entry/2018/03/22/000309)


## leafletのインストール

必要なローダー

```sh
npm install --save-dev style-loader css-loader file-loader url-loader
```

Leaflet

```
npm install --save-dev leaflet
```

webpackの設定

```js:webpack.config.js
    ...
    entry: {
        map_js: './assets/js/map.js',
        map_css: './assets/css/map.css',
    },
    ...
    rules: [
      ...
      {
        test: /\.css/,
        use: [{
          loader: 'style-loader',
        }, {
          loader: 'css-loader',
          options: {
            url: false
          }
        }]
      },
      {
        test: /\.png/,
        use: [{
          loader: 'url-loader',
        }]
      }
    ]
  }

```

https://leafletjs.com/ トップの例を書いてみます

```css:assets/css/map.css
@import "~leaflet/dist/leaflet.css";

body { 
    padding: 0;
    margin: 0;
}

html, body, #map {
    height: 100%;
    width: 100vw;
} 
```

```js:assets/js/map.js
import L from 'leaflet'
import iconRetinaUrl from 'leaflet/dist/images/marker-icon-2x.png'
import iconUrl from 'leaflet/dist/images/marker-icon.png'
import shadowUrl from 'leaflet/dist/images/marker-shadow.png'


delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
  iconRetinaUrl: iconRetinaUrl,
  iconUrl: iconUrl,
  shadowUrl: shadowUrl
});


var mymap = L.map('map').setView([51.505, -0.09], 13);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

L.marker([51.5, -0.09]).addTo(map)
    .bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
    .openPopup();
```

![Screenshot from 2019-10-21 23-51-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79562/5efc0c79-133f-111b-c0c4-3859e81fec26.png)
LaravelにVue.jsを導入したらバグった

練習用の学習プロジェクトを仕様変更しようと思い立ち、せっかくだから勉強中のVue.jsを導入してみようとやってみた。

・・初っ端からいきなりレンダリングがバグった。

![スクリーンショット 2019-10-21 23.38.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201982/9081464a-45fa-8efd-5bcc-27dde25e898b.png)

```php
<input type = "number" id = "text_num{{$item->id}}" name="text_num{{$item->id}}"　
style="display:inline-block;width:30px;height:20px" min="1" max="9" value=1>

```

ちょっとこのブログだとワードラップするのでわかりにくいけど、
上のコードは真ん中で改行が入ってます。
結構長めのタグで画面を開発画面を大きくはみ出て読めないので改行いれてました。

今まで問題ありませんでしたが、なぜかbladeにvueを混ぜるとタグの間に改行入れると写真のように改行したところから下のコードがむき出しでレンダリングされました。
とりあえず改行して一行にしたら治りました。
何かエスケープコードかアノテーションみたいなのでキチンと直す方法があるのかもしれませんが今のところわかりません。

#コメントのご指摘より追記
改行のせいじゃなくて、全角スペースが入っている事が根本的な原因だったようです。
失礼しました。
Mavenのpom.xml警告エラー

#Mavenプロジェクトでのpom.xml警告エラー
最近、Spring Bootを触っていてSpring Tool Suite(STS）でMavenの`pom.xml`を触っていたところ、警告エラーが発生していました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/f14de749-b132-fe74-7207-27c1970b611b.png)
動作には影響ないのだけど、ちょっと気になるので、なぜエラーになっているか確認してみました。

#まず、警告エラー内容は？
警告エラーは、以下のメッセージが表示されています。
`Overriding managed version 4.12 for junit`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/d592713b-6517-ab51-1721-a142aa4e07b7.png)
よくわからないので、Google翻訳で和訳してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/591aafc4-e773-36d7-2f84-9c66483a2420.png)
実際に`pom.xml`に定義しているの（dependencyタグのversionタグ）は、version 4.11なのでversion 4.12で上書きしています。というところでしょうか？

#定義を上書きしている箇所はどこか？
さて、実際に定義を上書きしている箇所を探すことにします。
まずは、自分の`pom.xml`内を検索します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/6f0af074-3efd-af2b-ef5b-2c989205ff09.png)
まあ、わかっていることですがここ以外に記載はないのでこの`pom.xml`には上書きしている箇所はないようです。
それではどこにあるのでしょうか？

##parentPOM定義をみてみる
親POMというものがあって、Eclipseでは「Overview」タブでその定義を確認できます（もちろんxmlソースにも記載あります）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/974e5196-42e9-783b-5d6f-50beb7fc661e.png)
で、この親POMってインターネットでどこかに記載されてるのかなぁとか思ったのですが、どうにか見れないか画面を確認していたところ、怪しいマークがありました。
おー！！こんなところに、何やら親POMを開いてくれるボタンがありました。押してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/def88213-cb44-f66b-c546-1b04961b6db7.png)

親POM（ここでは、`spring-boot-starter-parent`)が開いてくれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/592a7616-4cbf-f96d-79bb-de18c06235f4.png)

##parentPOM定義で定義を検索してみる
ここで定義を検索してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/0bed5c81-067f-b71e-232d-16110bb73aef.png)
またしてもみつかりません。。。ここで諦めてはいけないようです。`spring-boot-starter-parent`にも、親POMがあるようですので、同様の手順で親POMを開いて再度検索してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148996/78ed4575-98e3-3d97-9387-e968f50faaed.png)
ついに見つかりました！！ここに記載されているのは、version 4.12なのでこの定義が効いてるようでした。


#まとめ
mavenの仕組みについてはまだまだ理解が足りないようですので、日々アップデートしていきたいと思っています。
ここで気になったのは、親POMの定義が優先されるのはどこかで定義されているのかな（そもそもそういうもの？）とかですね。ここら知れたら、メモしていきたいと思います。
Proof Key for Code Exchange by OAuth Public Clients

[RFC 7636](https://tools.ietf.org/html/rfc7636) - Proof Key for Code Exchange by OAuth Public Clients（PKCE）ざっくりまとめ

#### 概要

* クライアントシークレットを秘匿できなく、かつ認可コードの受信者を保証できないクライアント（ネイティブアプリなど）は認可コード横取り攻撃（Authorization Code Interception Attack）に対して脆弱となる。
* PKCEはOAuth2の仕様を拡張し、認可コードの発行依頼者と利用者（トークン発行依頼者）が同一であることを `code_challenge` というキーを使って検証することを可能にする。

#### 検証の流れ

* クライアントはAuthorization Requestに `code_challenge` と `code_challenge_method` を追加で指定する。
  * クライアントは `code_verifier` として、[RFC3986](https://tools.ietf.org/html/rfc3986#section-2.3)の非予約文字から43～128文字のランダムな文字列を生成し、以下の計算式でハッシュ値 `code_challenge` を計算する。
  * `code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))` ※ `code_challenge_method` が`S256` の場合
* 認可サーバーは受け取った `code_challenge` と `code_challenge_method` を発行する認可コードを紐づけて保存しておく。
  * 典型的な実装では、認可コード中に `code_challenge` と `code_challenge_method` を暗号化して埋め込んでしまう。
  * PKCEが必須のクライアントが上記のパラメータを指定しない場合は `invalid_request` エラーを返却する。
* クライアントはToken Requestに `code_verifier` を追加で指定する。
* 認可サーバーは `code_verifier` から `code_challenge` を計算し、認可コードに紐づく値と一致するか検証する。
  * `code_challenge` が一致しない場合は `invalid_grant` エラーを返却する。
なぜ自分はプログラミングができないのか

## はじめに
はい、ずいぶんと挑戦的な記事です

そもそもの自己紹介から入らなければいけないのですが、私は

・プログラミングは**どの言語**であろうが**何一つ書くことができない**
・コンピューター自体は自作PCを組める程度の知識はある
・~~週末にGentooInstallBattleを楽しむ程度のLinux初心者~~

というタイプの人間です(~~こらそこ、希少種とか言わない~~)

自分にできることといえばせいぜい
・LinuxをCLIで動かせる
・wordpressやmisskey,mastodonの鯖をクラウド上に建てる
程度のことしかできません

ここで勘違いしてほしくないのは別に私はプログラミングをやりたくなかったわけではなくて
**「やってみたい気持ちはあったが0歩目で挫折した」**
ということです
今回は自分がなぜそんな経験をしてしまったかを書いていこうと思います


## 1.とにかく選択肢が多すぎる
まずこれです
プログラミングを始めようと思った私に襲い掛かってきたのは
**「どれからやったらいいかまるで分からない」**
という状況でした
いろんな人に聞いても十人十色の答えが返ってくるし、同じ言語でも作らせようとするものが微妙に違っているということも経験しました
このせいでまず私は1度挫折します

## 2.1歩目が踏み出せない
いまいち1と内容がかぶっている気がしなくもないですが、とにかく膨大な言語の中から例えばJavaScriptとPythonを選んだとします
しかしそれを使って何ができるのかがドキュメントを読んでもいまいちよくわからず

**Hello World程度のコピペを繰り返しては別の言語を試してみる**

ということが当分の間続きました
これに関してはプログラミングできる人から**「1歩踏み出してしまえばあとは簡単だよ」**と言われることが多々あったのですが
そもそも私は**「1歩目どころか0歩目で足踏みし続けている」**状況下だったので
**「1歩目を踏み出す方法を教えてくれーーー！！！」**と嘆く毎日でした

## 3.作りたいものがない
これは私の場合かなり深刻でした、具体的に説明すると

**自分の作りたいものは基本的に全部誰かがすでに作っており、またそれに参加しようにも力量不足で傍から見ることしかできず、結果として何も力にもならない1サービス利用者としてしか関わることができない**

という状況です
これでは全くプログラミングのスキルも身につくはずもなく、私はだらだらと毎日を過ごすばかりでした

こうした3つの経緯があって私は世にも珍しい
**「Linuxを普段使いしていて自作PCも組めて分散型SNSの鯖も運営しているのにコード1つ欠けない情弱」**
という人種に成り果ててしまいました

##　さいごに
これを見た人はおそらく私のことを
**「特殊例だ」**
**「そんな奴そうそう居ないぞ」**
**「嘘だろ？？」**
と思うと思いますがまぎれもない実話です
また私のような人間が、おそらく探せば数人は見つかるであろう自信もあります
わざわざQiitaの場にこのような記事を投稿したのも、そのような人間がこの記事を見つけてくれることを願ってのものです

最後に、このような稚拙な記事を最後まで読んでいただきありがとうございました

## 追記
2020/4/1 現在、今までに挑戦した言語とこれから挑戦するであろう言語を学習した順番にリストアップしました
C# 挫折
Java 挫折
C 挫折
C++ 挫折
Rust 挫折
Go 挫折
Swift 挫折
Ruby 挫折
JavaScript 現在勉強中
Python まだ手を付けていない
PHP 同上

向いてないんですかね......
【CSS】easeじゃ物足りない？だったらcubic-bezier()を使おうぜ！

##開始タグ
要素をアニメーションさせたい！って時はtranstionを使いますよね。
easeだとなんか違うわ、ってなりますよね。
そんな時に使うあいつをメモ。

##cubic-bezier()
こいつがとても優秀！
最初極端に早くて途中は普通最後は極端に遅く、とか自由自在にカスタムできちゃう。

使い方はとても簡単で、easeと同様に書いてあげるだけ。
()の中には数値を記入すればOK。

ただ、ちまちま手動で設定するのはさすがに苦行ですので、自分は以下のサービスを使っています。

[cubic-bezier.com](https://cubic-bezier.com/)

Photoshopのトーンカーブみたいにベジェ曲線で調整できるからわかりやすいし、数値を設定したら実際のアニメーション動作もデモで確認できるし、アニメーションにかかる時間も設定できるのでとても便利です。

ちなみに自分のお気に入りは` cubic-bezier(0.39, 0.575, 0.565, 1)`。
いい感じにホワッとしてくれるので、結構使ってます。

##閉じタグ
[cubic-bezier.com](https://cubic-bezier.com/)で遊ぶの楽しいです。
こんな動きするんや！と発見できますので、ぜひ遊んでみてください。
League of Legends APIを使って機械学習をやってみる1


#目的

機械学習について勉強する機会があり、自分で何かやってみたいとテーマを探していたところ、
League of Legendsの試合データから勝敗を判別する機械学習①
(https://qiita.com/hyo_07/items/f106efbde82aeb47c8a0)
という記事を見つけAPIで多数のデータを自分で扱えるということでLOLをテーマとすることにしました。

#データ入手
##準備
Pythonでデータを取得する場合RiotWatcherというモジュールから取得することができます。
また、データ取得にはRiot Games APIのページ(https://developer.riotgames.com)
からAPIキーを取得する必要があります。

モジュールのインストール

```python
pip install riotwatcher
```

RiotWathcerにAPIキーを登録します。

```python
from riotwatcher import RiotWatcher, ApiError
watcher = RiotWatcher('APIキー')
```

##サモナーのID情報
```python
my_region = 'jp1'
summoner = 'riyokuhi'
me = watcher.summoner.by_name(my_region, summoner)
print(me)
```

`{'id': 'NQAyxwwyHGEWmKs8ta9I0yy-GIM4KdjjMw_GAIcqEDbBYA', 'accountId': 'nZjfvmzwwE4NjtyLG42CZtfubERameu6owhNIgNWZgs3oSo', 'puuid': '4fS6lZS6nQQi9jM-KVCSmcJ7sVN86jQ3LW8dXoFyq4JYh_FFFBqOWvymEjlV59DU7zUN3TDR34ZNMA', 'name': 'riyokuhi', 'profileIconId': 4352, 'revisionDate': 1571626185000, 'summonerLevel': 168}`

サモナー関する複数の文字列が表示されます。試合データ等の出力にはサモナーネームでなく'id'や'accountId'を使います。


##サモナーのマッチ情報

```python
recentmatchlists = watcher.match.matchlist_by_account(my_region,me['accountId'])
matches = recentmatchlists['matches']
print(matches)
```

`[{'platformId': 'JP1', 'gameId': 210876606, 'champion': 59, 'queue': 430, 'season': 13, 'timestamp': 1571624644160, 'role': 'NONE', 'lane': 'JUNGLE'}, {'platformId': 'JP1', 'gameId': 210803138, 'champion': 61, 'queue': 430, 'season': 13, 'timestamp': 1571547151628, 'role': 'SOLO', 'lane': 'MID'}, {'platformId': 'JP1', 'gameId': 210801654, 'champion': 22, 'queue': 450, 'season': 13, 'timestamp': 1571542299129, 'role': 'DUO_SUPPORT', 'lane': 'NONE'}, {'platformId': 'JP1', 'gameId': 210631345, 'champion': 412, 'queue': 430, 'season': 13, 'timestamp': 1571450184490, 'role': `
以下省略

プレイヤーの過去100戦までのデータが表示されます。'gameId'を使うことで各ゲームの細かいデータを出力できます。

##ゲームデータ

```python
match_detailx = []
match_detailx.append(watcher.match.by_id(my_region,210876606))
print(match_detailx)
```
1ゲームのデータが出力されますが膨大なので一部のみ紹介します。

```python
#ゲームの種類
print(match_detailx[0]['queueId'])
#パッチバージョン
print(match_detailx[0]['gameVersion'])
```

`430
9.20.292.2452`
430はノーマルブラインド、420がランクソロキューのようです。パッチは9.20

```python
#チーム全体情報
print(match_detailx[0]['teams'][0])
```

`{'teamId': 100, 'win': 'Fail', 'firstBlood': True, 'firstTower': True, 'firstInhibitor': False, 'firstBaron': False, 'firstDragon': False, 'firstRiftHerald': False, 'towerKills': 3, 'inhibitorKills': 0, 'baronKills': 0, 'dragonKills': 0, 'vilemawKills': 0, 'riftHeraldKills': 0, 'dominionVictoryScore': 0, 'bans': []}`
片方のチームの取得オブジェクト情報

```python
#KDA
print(match_detailx[0]["participants"][0]['stats']['kills'])
print(match_detailx[0]["participants"][0]['stats']['deaths'])
print(match_detailx[0]["participants"][0]['stats']['assists'])
```
`3
7
1`
個人データは["participants"][0]の0を0～9に変えることで１０人分のデータが見れます。

#おわりに
各ゲーム内の細かいデータまで手に入るのでこれらのデータを使ってなにか機械学習の練習をしたいです。
もっとも簡単にWeb問合せフォームを作る方法 [BitScheduler開発日誌]

### はじめに

自分でWebサービスを作ったら、ユーザからの問い合わせフォームが欲しいですよね。
皆さんならどう実現しますか？

もっとも簡単な方法は Googleフォームを利用することではないでしょうか。
以下、ちょー簡単な手順です。

### 利用形態を選択

個人開発者であれば「パーソナル」を選びます。
<img width="800" alt="top.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25427/cd11ec3b-42b3-0917-2883-35559e4b16e3.png">

### 新規作成

「＋」ボタンを押します。
<img width="800" alt="new.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25427/a8113a1e-0e04-c3b2-5327-0ff31924fae4.png">

### テキスト入力の設置

入力タイプに「段落」を選択します。
「記述式」は改行なし（テキストフィールド形式）、「段落」は改行あり（テキストエリア形式）になります。
<img width="800" alt="new.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25427/2f2638f0-fd7c-b62c-040c-a7e42d23c540.png">

### メールアドレス入力の設置

入力項目は必須にするかのを設定できます。
問い合わせのハードルを下げたいので、ここでは返信が必要な人だけ入力するようにしました。
<img width="667" alt="preview.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25427/29f5378c-066c-d13d-7ccd-7de5dc49a374.png">

### プレビュー

ヘッダメニューのプレビューボタンを押します。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25427/3179903e-895d-1e0a-e344-d0fe75ef59b3.png">

期待通りに動作するかを確認できます。
<img width="667" alt="preview.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25427/e31f8be6-38d9-bd40-f5e7-3b0fa5130ca3.png">

### 埋め込み用HTMLコードの取得

動作確認が取れたら「送信」ボタンを押します。
押してもこの段階では公開はされませんのでご安心を。
![send.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25427/09922314-9f03-b213-eed3-ef841695ecb3.png)

HTMLに埋め込むためのコードが取得できます。自分のアプリ内に設置しましょう。
![iframe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25427/4ffd271f-9ca1-664c-fead-aecad0a24039.png)

以上です。いやーほんと Googleって便利です。
Webアプリを作ってみたものの、全く使われていないボクの[出欠投稿アプリ「BitScheculer」](https://www.bitscheduler.com/contact.html)にも設置してみました（＾＾；）

### Googleフォーム
[https://www.google.com/intl/ja_jp/forms/about/](https://www.google.com/intl/ja_jp/forms/about/)

## BitSchedulerとは

出欠管理サービスです。Googleカレンダーと連携することで簡単にチームの出欠を管理、運用できることを目指しています。
よかったら使ってみてください！

[BitScheduler](https://bitscheduler.com/)
Azure VM の Hyper-V で Nested Virtualization を使い色々試せる検証環境を構築する

今回は、Azure VM の Hyper-V を使って、色々試すことができる検証環境を構築してみたいと思います。Azure の Nested Virtualization については以下の Microsoft の記事がよくまとまっていました。

Nested Virtualization in Azure
https://azure.microsoft.com/en-us/blog/nested-virtualization-in-azure/

#Azure VM を作成する
まずは当たり前ですが、Azure VM で Windows Server 2016 datacenter をデプロイします。作成方法は以下の記事を参照してください。普通のやり方で簡単に構築できます。前提条件は以下なので、これを満たすようにオプションを選択します。

- Hyper-V ホストとゲストの両方が Windows Server 2016/Windows 10 Anniversary Update 以降であること。
- VM 構成バージョン 8.0 以上。
- VT-x および EPT テクノロジを使用する Intel プロセッサ。入れ子は現在 Intel のみでサポートされています。
- 第 2 レベルの仮想マシンの仮想ネットワークとは、いくつかの違いがあります。 入れ子になった仮想マシン ネットワークに関する記述をご覧ください。

->これは Azure の以下のプランで満たすことが出来ます。
Dv3 (DSv3) もしくは Ev3 (ESv3) シリーズ上の Windows Server 2016 の VM

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/23e05c6a-cf20-b7ee-d930-8fd03578bdc9.png)

#Disk を追加する
GTP フォーマットを使用するために Disk を追加します。Azure Portal から Disk は追加することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/1d7038d7-a4f6-132f-9841-783dcbc9dbd6.png)

実際にDisk が追加できると、Windows Server 2016 の Disk Management より確認することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/dae1b364-e803-7ffd-00b7-3532fc44d041.png)

ディスクの管理画面から、"Disk 2" の黒帯となっている領域を [右クリック] – [New Simple Volume] を作成し、パーティションを作成します。そうすることで ボリュームが追加できたのを確認することが出来ました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/59c3a6b0-0536-9dc6-6734-ff983e635d7a.png)

#Hyper-V Manager から VM を作成する
Hyper-V で VM を構築する容量で、Windows Server 2016 を立ててみましょう。あとからVMに image を追加することが出来ますが、先に Evaluation Center から ISO をダウンロードしておくと便利です。
この図は Azure VM 上 の IE で Evaluation Center から ISO をダウンロードするところです。Azure で VM を立てるとデフォルトで IE の セキュリティがハイレベルになっているので、注意しましょう。※Evaluation Center は Javascript が有効になっていないと機能しません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/8525a0d1-9f52-2577-a105-f592031828f5.png)
 
上記が完了したら、Hyper-V　で VM を作成 / iso から作成を選び、Windows Server 2016 を立てます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/ba4a3fc2-29b8-1252-d7da-fa91458538ad.png)

これで Windows Serve 2016 on Windows Server 2016 on Azure が完成です。※あとは NIC 関連の設定をお忘れなく！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/7bb16943-f76a-7163-c853-f88a791e5550.png)


VM on Azure に Client や Server や AD を立ててみて、色々OS 周りの検証に使えるのでとても便利ですね。
ただ 今回作成したプランは非常に高いので、検証が終わったら小まめにサーバーを落とすことを心がけましょう！

#参考URL
Nested Hyper-V を使った VM の復旧（これは超良い記事です）
https://blogs.technet.microsoft.com/jpaztech/2017/10/13/recover_vm_using_nested_hyperv/
エンジニアスタンプラリー～フロントエンド編＃12

## 企画主旨
[Frontend Developer Roadmap](https://roadmap.sh/frontend)をひたすら巡回する企画 
詳しくは[こちら](https://qiita.com/tonchan1216/items/8d5f072cf769dfe1bc4f)

## 今回の実施内容
静的型チェッカー
TypeScriptでかっちりしていこう。

## Type Checkers

#### TypeScript
もはや何が公式ドキュメントかわからなくなったので、React+TypeScriptでヒットした[React - TypeScript Deep Dive](https://typescript-jp.gitbook.io/deep-dive/tsx/react)を参考にした。
実際には、React+TypeScript+MobX+Webpackという感じ。

Webpackがだいぶすっきり。

```javascript:webpack.config.js
  module: {
    rules: [
      {
        test: /\.(ts|tsx)$/,
        loader: 'ts-loader'
      },
      {
        test: /\.scss/, // 拡張子 .scss の場合
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader', // CSSをバンドルするための機能
            options: {
              url: false,
              sourceMap: enabledSourceMap,
              importLoaders: 2
            }
          },
          {
            loader: 'sass-loader', // Sassファイルの読み込みとコンパイル
            options: {
              sourceMap: enabledSourceMap
            }
          }
        ]
      }
    ]
  },

```

こんな感じの型を定義して、Reactのpropsに適応していく。

```javascript:Types.ts
export interface _Skill {
  front: string[],
  back: string[],
  [key: string]: string[];
}

export type _addSkill = () => void
export type _changeText = (text: string) => void
export type _togglePage = (bar: string) => void
export type _updateNews = (news: string) => void
```

```javascript:App.tsx
import * as React from 'react';
import { observer, inject } from 'mobx-react';
import Header from './components/Header/Header';
import Content from './components/Content';
import Footer from './components/Footer';
import { _Skill, _addSkill, _changeText, _updateNews, _togglePage } from './Types';

interface Props {
  store?: Store | any
}

interface Store {
  page: string,
  news: string,
  skill: _Skill,
  inputText: string,
  addSkill: _addSkill,
  changeText: _changeText,
  updateNews: _updateNews,
  togglePage: _togglePage,
}

@inject('store')
@observer
class App extends React.Component<Props> {
  constructor(props: Props) {
    super(props);
    this.fetchJson = this.fetchJson.bind(this);
  }

  async componentDidMount() {~~~~~}

  render() {~~~~~~~}
}

export default App;

```


## 成果物
(型)安全第一。
もっと大規模で複雑なコードなら恩恵を感じることができたかも。
https://github.com/tonchan1216/WDR-frontend/tree/v12
https://tonchan1216.github.io/WDR-frontend/v12/
AH01630: client denied by server configuration | Lazy Service

##[Lazy Service](https://store.lazyweb-tech.com)を使う際のエラー対処メモ1
## 事象
Windows 10環境でLaravelプロジェクトを開発しているが、Apache動作がうまくできず、WEB上にForbiddenエラー発生してしまう。
操作手順は下記通り。
1．Laravelプロジェクト(myproject)を新規作成する。
　　Laravelプロジェクトの作成方法は「[WindowsでのLaravel+SQLite3開発環境を構築する](https://qiita.com/freelazy/items/95283f928a09cf84e6cd)」を参照ください。
2．Lazy Serviceアプリを起動してDocumentRootに"C:\TEST\myproject\public"を指定した。
　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373279/35a75c37-f2b5-24ee-3e2f-a3c4131a4f97.png)
3．APACHE -> SAVEでhttpd.confを保存する。
4．SERVER -> START でApache2.4を起動する。
5．ブラウザに "http://www.example.com" を入力し表示すると、下記のForbiddenメッセージが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373279/d8198c0f-5447-4d0f-5ebc-080792ce5738.png)
一旦、Lazy ServiceのApacheログ(C:\Program Files\LazyService\Apache\2.4\logs\error.log)を覗いてみる。
下記エラーログがあった。

```ruby:errors.log
[Mon Oct 21 21:10:37.589626 2019] [authz_core:error] [pid 14772:tid 1180] [client 192.168.x.x:57461] AH01630: client denied by server configuration: C:/TEST/myproject/public/
```

##対応方法
APACHE -> Directory -> Section -> "Directory"を選択して、＋ボタンをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373279/8d6e4a49-3dd1-358a-7c31-587e75d19ff1.png)

Direcotry設定子画面が表示され、以下のように各値を設定する

```ruby:
Options FollowSymlinks Includes
AllowOverride All
Require all granted
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373279/afdc2cad-5bbf-4c54-192c-d82312f50e48.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373279/82dda8ba-3eed-0d93-a1aa-373096a3ee19.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373279/1358c639-6cc3-9c62-c6af-6483a289fa63.png)

設定後、「OK」ボタンをクリックする。赤枠1行が追加された。それで"C:/TEST/myproject/public/"へのアクセス権限を付与した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373279/de4cf60b-5eb6-8aea-c687-20db1116b793.png)
続いで、APACHE -> SAVEでhttpd.confを保存し、SERVER -> START でAPACHEを再起動する。
ブラウザに "http://www.example.com" で再度表示すると今回OK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373279/6b872d7e-3034-f338-c3e5-9c7f1b6c1f30.png)

Lazy Serviceの良いことはhttpd.confなど設定ファイルを開く必要がなく、画面操作だけ開発環境が楽にできてくれる。
基本情報技術者試験を２～３週間で合格する

#概要
基本情報技術者試験の勉強方法に関するもの
基本情報技術者試験を令和元年秋に初めて受けて、午前午後ともに７割程度とれていた。マークミスをしていなければ合格。

####今後資格試験を受ける際に、どのように勉強したかを忘れないようにするためにめまとめる。
####基本情報を受ける人の参考になってくれれば嬉しい
#自分自身について
私は専門は情報系ではなく、機械専攻の大学院１年。情報に関する知識はほとんどない。回路とか2進数の計算はできる程度の知識。プログラミングもMATLABしかまともに使うことができない。計算だけは自信あり。

#勉強スケジュール
##１０月１日～１０月７日
そろそろ勉強を始めようと思う。午前の勉強から。
参考書は　平成30年度 イメージ&クレバー方式でよくわかる栢木先生の基本情報技術者教室 (情報処理技術者試験)　

勉強方法として１章から順番に読んでいくことにした。
・１章はハードウェアに関するもの。初見の単語が多く読み終わるのに__２時間__くらいかかった。
・２章はソフトウェアに関するもの。これも__２時間__くらいかかった、
・３章は基本的な計算。これはスラスラ読めた。__１時間__くらい。
・１～３章のまとめ問題（過去問）を全てできるようになるまで解く。__１時間__くらい。
・４章はアルゴリズムに関するもの。大学の授業で扱ったものがほとんどでスラスラ読めた。__１時間__くらい。
・５章は処理に関するもの（？）。__２時間__くらい。
・６章は工程管理とかに関するもの。__２時間__くらい。
・４～６章のまとめ問題（過去問）を全てできるようになるまで解く。__１時間__くらい。
・７章はネットワークに関するもの。__１時間__くらい。
・８章はデータベースとかに関するもの。__２時間__くらい。
・９章はセキュリティ関するもの。__１時間__くらい。
・１０章は関連法規とかその他計算。計算はスラスラ。__1時間__くらい。
・７～１０章のまとめ問題（過去問）を全てできるようになるまで解く。__２時間__くらい。
・１～１０章のまとめ問題（過去問）を解く。（この時点では参考書の問題はすべて解けるようになった）__２時間__くらい。


工夫？した点は、
####➀ 全てを覚えようとしない。まとめの問題に関する知識だけ完璧にする。他は流し読み。
####➁ まとめ問題はできるようになるまで何回も解く。最低３周、最高でやった問題は４周。

##１０月８日～１０月１２日
ここは午前の過去問をひたすら解くことにした。
・過去問はＨ２９秋、Ｈ３０春、Ｈ３０秋、Ｈ３１春を解く。
・分からない、間違えた問題は参考書を読み、理解する。
・１周目は平均５割、２周目は平均８割、３周目は全てできるようになった。
・時間にしてだいたい__２５時間__くらい。

##１０月１３日～１０月１８日
ここから午後に取り組むことにした。
####Ｈ２９秋
・１問目（セキュリティ）。８割できた。午前の知識だけでもいける。
・２～７問目は４つ選択。とりあえず全部解くことにした。
・２問目（排他制御）。全てできた。これも文章が長いだけで、午前の知識でいける。
・３問目（ＳＱＬ）。意味が分からない。これは捨てることにした。
・４問目（ネットワークの構成？）。全てできた。文章が長いだけ。
・５問目（ソフトウェア設計？）。ソフトウェアとういことで捨てることにした。自信がない。
・６問目（システム運用サービス）。全てできた。文章読んで計算するだけ。文章がやたら長い。
・７問目（業務改善）。全てできた。文章読んで計算するだけ。文章がやたら長い。
・８問目（アルゴリズム）。６割くらい。前半の簡単なものは手を動かせばいける。後半は難しい。
・９～１３問目は１つ選択。
・授業でやったJavaとＣ言語に目を通したが、意味が分からない。これは捨てる。

ここまでで、だいたい__３時間__くらい。結構ゆっくりやったけど、最後の言語は間に合わないと判断。当日の作戦は以下のように決めた。

####・問２～７の選択は、ＳＱＬ、ソフトウェア以外の４つ
####・問９～１３の選択は捨てる。解答は全部「ウ」にする。
####・時間配分は問８のアルゴリズムを５０分、問１～問７の５問を１００分（１問あたり２０分）

この期間はアルバイトなどで時間がなく、Ｈ３０春、秋を１周するだけだった。
セキュリティは５割、アルゴリズムは６割、それ以外は９割くらいだった。セキュリティだけ熟読した。時間は__６時間__くらい。
またこの間に参考書のまとめ問題を２周した。時間は__３時間__くらい。

##１０月１９日
前日は１日アルバイトだったので、__２時間__くらいしかできなかった。やったことは、Ｈ２９秋、Ｈ３０春、秋のアルゴリズムを解きなおす。

##１０月２０日（試験当日）
試験当日は何もしなかった。
####午前
計算とか数学の問題が少し多かった印象。個人的にはそこで点を稼げたので良かった。数Ⅲでやった極限がでてびっくり。
結果６４／８０　８０％　

####午後
最初の作戦通りに解いた。こちらも計算とか表の読み取りが多く解きやすかった。
（問１） ３／４　（問２） ５／５　（問５）６／６  （問６） ６／６　（問７） ５／５　（問８） ６／９　（問９） １／６
結果７３％くらい

#まとめ
・午前に関しては過去問を完璧にすれば問題ないと思う。過去にでた問題がそのまま、もしくは一部改変されているものが４割くらいあった印象
・私は過去問を４回分と参考書の問題しかやっていないが、それでも４割くらいはみたことあった。
・午後に関しては、プログラミング言語を捨てたので８０点満点で勝負しなくてはならず、不安だった。おすすめはしない。
・午後の問題は文章を読んで「計算する」「表を読み取る」みたいな感じが多く、大学受験の勉強が役に立った。
####・合計勉強時間は約６１時間くらい