競技プログラマーがWeb開発者の卵になるまでの軌跡

#対象者#
・Web開発に興味のある競技プログラマー
・プログラミングは勉強したことがあるけれど開発はしたことがない人

#自己紹介
初めましてぬるぬると申します。
競技プログラマー & Web開発者の卵です。
株式会社Eyes, JAPANでアルバイトとして働いています。


**GitHub**
**https://github.com/null-null-programming**

**AtCoder**
**Highest:1357**
**https://atcoder.jp/users/null_null**

**作ったWebサービス:AtCoder Tags**
https://atcoder-tags.herokuapp.com/

**作ったユーザスクリプト**
**・AtCoder-Color-NEWS**
**・AtCoder-ACPercentage**
**・AtCoder-DarkTheme**
**・AtCoder-Tags-Helper**

**AtCoderEditorials**というサービスも作っていたのですが、運営が下手で人が来なくなったので消しました。

#この記事を作った経緯#
開発のアルバイトに採用されたので、私もそろそろ開発者の卵を名乗っていいかなと思い記事を書くことにしました。

**突然ですが、競技プログラマーの方で「開発をしたい」「何かを作ってみたい」と思っている方は案外多いんじゃないでしょうか？**

私もそのうちの一人でした。

しかし、開発を始めたてのころは右も左もわからず、何を勉強すれば良いのかすらわかりませんでした。

今でもよく覚えていますが、「開発者と言われる人がどうやって勉強してきたのだろう」「開発者の方の軌跡を知りたい」とよく思いました。

そういう人々の助けになれば良いなと思いこの記事を書こうと思いました。

そういうわけで、**競技プログラミングしかわからない人が開発を少しできるようになるために何をしたのか？**を書いていきます。

#前提#
私がどうやって勉強してきたかの勉強法、およびその軌跡を書くだけなので間違いがたくさんあると思います。もし間違いを見つけた場合は指摘してくださると嬉しいです。

「開発」というとたくさん種類があると思うのですが、私が紹介するのは「**Web開発**」です。

私はPythonで開発をしてきたのでPython目線で書きます。

#そもそも「シンプルな」Webアプリを作るには何の技術が必要？#

**フロントエンド**
・HTML
・CSS
・JavaScript

**バックエンド**
・Web開発用のプログラミング言語（Python・Ruby・PHPなどなど・・・）どれか１つ
・使用する言語のフレームワーク（例えばFlask）１つ
・PostgreSQLやMySQLなどのデータベース

#私が勉強した順番#
**0:全体の流れを掴む**
全体の流れを掴んだ方が勉強がしやすいと思います。

読んだ本：
**「わかばちゃんと学ぶ Webサイト制作の基本」**
**「プロになるためのWeb技術入門」**

**1:HTML**

まずはHTMLを勉強することをオススメします。
CSSもJavaScriptも,HTMLをやっていないとよくわからないと思います。
ざっくりと勉強をしたら次に進んで大丈夫です。

読んだ本：
**「デザインの学校 これからはじめる HTML & CSSの本」**
**「Bootstrap4ファーストガイド―CSS設計の手間を大幅に削減!」**

**2:JavaScript**
C++やPythonなどがある程度書ける競プロerであれば、基本文法はすぐに書けるようになると思います。

JavaScriptを勉強すると良いことが１つあります。
**それは物を作る体験ができるということです**

ブラウザにはユーザスクリプトという拡張機能があります。
ユーザスクリプトはJavaScriptで書かれており、比較的短いコードを書くだけで作ることができます。

とにかく何かを作りたいという人はユーザースクリプトを書くのも良いかもしれません。

有名な例でいうと**ac-predictor**などがあると思います。

基本文法を押さえたら次に進んで良いと思います。

読んだ本:
**「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」**

**3:Python・Ruby・PHPなどのWeb開発用のプログラミング言語１つ**
私はPythonを勉強しました。

これに関してはどれが良いかは私もわかりません・・・
いろいろ調べて好きなものを選ぶと良いと思います。

とりあえず基礎文法を押さえたら、次に進んで良いと思います。

読んだ本:
**「みんなのPython 第4版」**

**4:データベースどれか１つ**
いろいろ種類はあると思うのですが、私は**PostgreSQL**を勉強しました。

読んだ本:
**「Pythonデータベースプログラミング入門」**

#全体を通して１つのアプリを作れる本を読もう#
私は下の本のシリーズを理解しながら写経して、簡単な質問投稿アプリケーションをつくりました。
**Flask**というPythonのフレームワークを使います。

**「PythonでWebサービスを作る - Python3 + Flaskで作るWebアプリケーション開発入門 -」**

AtCoder Tagsで使っている技術はこの本に全て載っています。



**番外編:GitHub&Bootstrap**
GitHubは使えるようになっておいた方が良いです。
BootstrapはデザインをCSSで考えるのが面倒な時に強い味方になってくれます。

読んだ本：
GitHub:
**「いちばんやさしいGit&GitHubの教本」**

Bootstrap:
**「Bootstrap4ファーストガイド―CSS設計の手間を大幅に削減!」**

#ここまで勉強したら・・・#
あなたは既に

・簡単なサイトの見た目を作れる
・簡単な内部処理が書ける
・データベースで簡単な情報を扱うことができる

はずです。

#とりあえず簡単なWeb開発を体験してみよう！#

一緒に簡単なWebサービスを作りましょう。
初めは理解できなくても大丈夫なので考えながら写経をしましょう。

今回はこんなアプリを作ってみましょう！

・名前とレートを入力する場所がある（HTML）
・送信をすると表に名前とレートが追加される（データベース＆Python）
・レートによって名前の部分の色が変わる（CSS＆Javascript）

#0:環境構築
下の３つを準備して下さい。
ここでは詳しく述べないので、各自で検索お願いします。
開発において自分で検索して調べるのはとても重要な能力だと私は思います。

**1:Pythonを準備する**
**2:pipを準備する**
**3:Flaskを準備する**
**4:必要なものをpipでインストールする（下で詳細は書きます）**


#1:ディレクトリを作ろう

```text

/Document/Test
|--__init__.py
|--models.py
|--templates
| |--index.html
|--manage.py
|--requirements.txt
```

###コマンドを使ってみよう###
**touch** コマンドでファイルが作れます。
**mkdir** コマンドでディレクトリが作れます。
**pwd** コマンドで今自分がいるディレクトリがわかります。
**cd** コマンドでディレクトリを移動できます。
**code** コマンドでVSCode を開きます。

**$ code file_name** でfile_nameというファイルを開きます。

Testとtemplatesがディレクトリでそれ以外はファイルです。

上の図に従って同じものを作ってみましょう。

前のディレクトリに移動する方法は
**$ cd ..**
と打つと戻れます。

#HTMLを書いてみよう##
index.htmlに下の内容を書いて下さい。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>AtCoder Color Table</title>
  </head>
  <body>
    <form action="/send" method="POST">
        <input type="text" name="name" placeholder="name" size="20">
        <input type="text" name="rate" placeholder="rate" size="10">
        <input type="submit" value="send">
    </form>
  </body>
</html>

```

HTMLを書けました。
ファイルマネージャーなどから/Document/Test/templates/index.htmlの場所まで行き
index.htmlを右クリックで選択してブラウザで表示してみましょう。

![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404922/065268e8-f700-2f14-d0ce-d8f1e2c0a4ff.png)


表示してみるとこんな感じのものが出てくると思います。

![bbb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404922/eb88115e-803b-2ea3-7638-d229c41c40dd.png)

左のフォームで名前を入力し、真ん中のフォームでレートを入力、右のフォームで送信します。

#Pythonで内部処理を書いてみよう#
###内部処理を書く前に必要なものをインストールしてしまいましょう。###
（今回使わないものも入っています）
以下の内容をrequirements.txtにコピーペーストして下さい。

```text:requirements.txt
alembic==1.3.1
appdirs==1.4.3
APScheduler==3.6.3
attrs==19.3.0
beautifulsoup4==4.8.1
black==19.10b0
certifi==2019.9.11
chardet==3.0.4
Click==7.0
Flask==1.1.1
Flask-Cors==3.0.8
Flask-Login==0.4.1
Flask-Migrate==2.5.2
flask-paginate==0.5.5
Flask-SQLAlchemy==2.4.1
gunicorn==20.0.4
idna==2.8
itsdangerous==1.1.0
Jinja2==2.10.3
Mako==1.1.0
MarkupSafe==1.1.1
pathspec==0.6.0
psycopg2==2.8.4
psycopg2-binary==2.8.4
python-dateutil==2.8.1
python-editor==1.0.4
pytz==2019.3
regex==2019.11.1
requests==2.22.0
requests-oauthlib==1.3.0
six==1.13.0
soupsieve==1.9.5
SQLAlchemy==1.3.11
toml==0.10.0
typed-ast==1.4.0
tzlocal==2.0.0
urllib3==1.25.7
Werkzeug==0.16.0
```
仮想環境を使いましょう。
/Document/Test ディレクトリで

**$ python3 -m venv venv**
**$ source venv/bin/activate**

と入力すると仮想環境に入れます。
**インストールが仮想環境内だけで行われるので衝突などが防げます。**

次にrequirements.txt内のもの全てを1つ1つ手動でインストールするのは辛いので楽をしましょう。

具体的には以下のコマンドを打ちます。

**$ pip install -r requirements.txt**

これでrequirements.txt内のものは全てインストールされます。

###内部処理を書きましょう###
以下の内容を写して下さい。

```python:manage.py
from flask import Flask,render_template
app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == "__main__":
    app.run()

```

次に,

**$ python manage.py**

を実行してみて下さい。

開発用サーバーが立ち上がるはずです。

こんな感じの文字列が出たら成功です。

```text

* Serving Flask app "manage" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```

下部分の**http://127.0.0.1:5000/**にアクセスしてみましょう。
下部分をコントロールキー＋クリックで移動することも出来ます。
それ以外の場合はブラウザのURLを打つ場所に直接打ち込んでみましょう。
先程作成したHTMLが表示されれば成功です。

これはローカルサーバーなので公開されていませんが、サーバーを借りてこのアプリを上げればこのHTMLを全世界に公開することが出来ます!

#データベースを使って入力されたデータを保存しよう#
今回は簡単なアプリなのでSQLiteを使います。

**$ sqlite3 data.sqlite3**

と入力するとdata.sqlite3というデータベースが作られます。

**sqlite> create table atcoder(name text primary key,rate integer);**

と打ち込むとatcoderテーブルが作られます。
atcoderテーブルはnameという文字列データとrateという整数データを持ちます。

次にmanage.pyを編集してPythonとデータベースを連携させましょう。

```python:manage.py
from flask import Flask,render_template,request,redirect,url_for,flash
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, Integer, String 

app = Flask(__name__)

app.config['SECRET_KEY'] = '\xfd{H\flash: xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.sqlite3'

db=SQLAlchemy(app)

class atcoder(db.Model):
    __tablename__ = 'atcoder'
    name = db.Column(db.Text,primary_key=True)
    rate = db.Column(db.Integer)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/send',methods=['POST'])
def send():
    get_data=atcoder(
    name=request.form['name'],
    rate=request.form['rate']
    )

    db.session.add(get_data)
    db.session.commit()
    return redirect(url_for('index'))

if __name__ == "__main__":
    app.run()

```

やっていることは、

１：DBとPythonを連携させる。（Keyの設定やDBのURLの設定など）
２：HTMLのフォームから/sendに情報を送り、それをrequest.form['name']などで受け取っている。
３：受け取った情報をdb.session.add()で書き込み、db.session.commit()でセーブしている。

みたいな感じです。

#データベースの情報を画面に表示させよう#
manage.pyを編集してindex.htmlにデータベースの情報を送ります。
index()の部分のみ編集しました。

```python:manage.py

 from flask import Flask,render_template,request,redirect,url_for,flash
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, Integer, String 

app = Flask(__name__)

app.config['SECRET_KEY'] = '\xfd{H\flash: xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.sqlite3'

db=SQLAlchemy(app)

class atcoder(db.Model):
    __tablename__ = 'atcoder'
    name = db.Column(db.Text,primary_key=True)
    rate = db.Column(db.Integer)

@app.route('/')
def index():
    user = atcoder.query.order_by(atcoder.rate.desc()).all()
    return render_template('index.html',user_data=user)

@app.route('/send',methods=['POST'])
def send():
    get_data=atcoder(
    name=request.form['name'],
    rate=request.form['rate']
    )

    db.session.add(get_data)
    db.session.commit()
    return redirect(url_for('index'))

if __name__ == "__main__":
    app.run()

```

次にHTMLを編集します。
テンプレートエンジンを用いて送られてきたデータを埋め込みます。

```html:

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>AtCoder Color Table</title>
  </head>
  <body>
    <form action="/send" method="POST">
        <input type="text" name="name" placeholder="name" size="20">
        <input type="text" name="rate" placeholder="rate" size="10">
        <input type="submit" value="send">
    </form>
              
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Rate</th>
        </tr>
      </thead>

      <tbody>
      {%for user in user_data%}
        <tr>
          <th>{{user.name}}</th>
          <th>{{user.rate}}</th>
        </tr>
      {%endfor%}
      </tbody>

    </table>

  </body>
</html>

```

{}で囲まれた部分がテンプレートエンジンの使われている部分で、
配列で渡されたuser_data をfor文で取り出している感じです。

#JavaScriptを追加してレートの色を変えよう#

HTMLのレートの部分にidを付け、Javascriptで指定をし、CSSで色を変えます。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>AtCoder Color Table</title>
  </head>
  <body>
    <form action="/send" method="POST">
        <input type="text" name="name" placeholder="name" size="20">
        <input type="text" name="rate" placeholder="rate" size="10">
        <input type="submit" value="send">
    </form>
              
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Rate</th>
        </tr>
      </thead>

      <tbody>
      {%for user in user_data%}
        <tr>
          <th>{{user.name}}</th>
          <th id="{{loop.index0}}" value="{{user.rate}}">{{user.rate}}</th>
        </tr>
      {%endfor%}
      </tbody>

    </table>

    <script type="text/javascript">
    for(var i=0;i<Number("{{user_data | length}}");i++){
       var rate=Number(document.getElementById(i.toString(10)).getAttribute("value"));

       if(rate>=2800){
         document.getElementById(i.toString(10)).style.color="red";
       }else if(rate>=2400){
         document.getElementById(i.toString(10)).style.color="orange";
       }else if(rate>=2000){
         document.getElementById(i.toString(10)).style.color="yellow";
       }else if(rate>=1600){
         document.getElementById(i.toString(10)).style.color="blue";
       }else if(rate>=1200){
         document.getElementById(i.toString(10)).style.color="cyan";
       }else if(rate>=800){
         document.getElementById(i.toString(10)).style.color="green";
       }else if(rate>=400){
         document.getElementById(i.toString(10)).style.color="brown";
       }else{
         document.getElementById(i.toString(10)).style.color="gray";
       }
    }
    
  </script>
  </body>
</html>

```

#完成形#
データを入力するとこんな感じになります。
![ccc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404922/ae79459a-60db-ae77-64fb-46562d95d6fb.png)

#終わりに#
ひよっこの私がこんなことを言うのもなんですが、開発はとても楽しいです。
自分の作ったサービスが人に使われると嬉しいです。
開発に興味があるけれど何をしたら良いのかがわからない人が、私の記事を読んで開発の世界に足を踏み入れてくれることを願います。

また、この記事に関する間違い・質問等あればQiitaのコメントかTwitterのDMに送っていただければ、出来るかぎり早く対処します。