かんばやし
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # GCP(クラウド勉強会) INNOTECHS様向け資料 [About Takayuki](https://taka-baya-work.com/about/) ## アジェンダ ### 成果物1 日本の輸入出とサービス業の国際収支の推移を表示するページを作成する。 https://learning-gcp-403802.ue.r.appspot.com/ ![成果物.png](https://hackmd.io/_uploads/ryGptDkQa.png) 【成果物のクラウド設計】 ![Cloud.png](https://hackmd.io/_uploads/Hy-Dnde7a.png) ### 成果物2 成果物1カスタマイズして、より可視化されたグラフなど、改良して良いものを作ってください。 ## 今回使用するもの ### プログラミング言語 ・Python ・HTML ・JavaScript (Chart.js) ### ツール ・Google Cloud Pratform(GCP) --- ## 事前準備 ### 事前準備その1:GCPへの登録 以下リンクの記事を参考にGCPへの登録(クレジットカードの追加)をお願いします。 【日本語】 https://www.n-study.com/gcp/start-gcp/ 【英語】 https://cloud.google.com/docs/get-started?hl=en ### 事前準備その2:Pythonのインストール <span style="color:red">**Pythonをインストールするときは、バージョン3.10でインストールしてください(環境の統一&gcloud CLIがv3.10しか対応してないので)**</span>. #### Windows ●WindowsでPython実行環境のインストール方法 1. **PythonをWindowsにインストールするには、以下の手順を実行します。** 公式ウェブサイトからインストーラをダウンロード: 【Pythonの公式ウェブサイト】 https://www.python.org/ftp/python/3.10.11/python-3.10.11-amd64.exe にアクセスし、ダウンロードページからPythonの最新バージョンのインストーラをダウンロードします。 2. **インストーラを実行:** ダウンロードしたインストーラをダブルクリックして実行します。 3. **パスにPythonを追加:** インストーラの最初の画面で、「Add Python X.Y to PATH」(X.YはダウンロードしたPythonのバージョン番号)というオプションをチェックします。これにより、PythonがシステムのPATH環境変数に追加され、コマンドプロンプトから直接Pythonを実行できるようになります。 3. **インストール:** 「Install Now」をクリックして、インストールを開始します。 4. **インストールの確認:** インストールが完了すると、「Setup was successful」または類似のメッセージが表示されます。これでPythonのインストールは完了です。 5. **Pythonの動作確認:** コマンドプロンプトを開き、python --versionと入力して、Pythonのバージョンが正しく表示されることを確認します。 6. **(オプショナル)追加のパッケージのインストール:** 必要に応じて、Pythonのパッケージマネージャであるpipを使用して、追加のパッケージをインストールします。たとえば、pip install numpyを実行すると、NumPyという数値計算ライブラリをインストールできます。 これで、Windows上でPythonを使用する準備が整いました。 #### OS X ●MacでPythonをインストールするには、いくつかの方法がありますが、ここでは主に2つの方法を紹介します。 【インストーラーを使ったインストールの場合】 1. **公式ウェブサイトからインストーラをダウンロード:** Pythonの公式ウェブサイト https://www.python.org/ftp/python/3.10.11/python-3.10.11-macos11.pkg にアクセスし、Pythonの最新バージョンのインストーラをダウンロードします。 2. **ダウンロードしたインストーラをダブルクリックして実行し、画面の指示に従ってインストールを完了させます。** 【Homebrewを使用】 1. **ターミナルを開き、以下のコマンドを実行してPythonをインストールします:** ``` brew install python3.10 ``` どちらの方法でも、インストールが完了したらターミナルを開き、python3 --versionコマンドを実行してPythonのバージョンを確認することができます。これでPythonのインストールは完了し、MacでPythonを使用する準備が整いました。 また、OSXでPythonのバージョン管理を行いたい場合は、pyenvを使用することもお勧めします。pyenvは、複数のPythonバージョンを管理し、プロジェクトごとに異なるPythonバージョンを使用することを簡単にします。 ### 事前準備その3:Cloud SDKのインストール *gcloud CLI*はパソコン端末からコマンドでGCPのクラウド環境を操作するツール(コマンド)です。 基本的には以下URLを参照して頂ければ幸いです。 #### ●Windowsでのインストール方法 1. CLIインストーラーのダウンロード [Google Cloud CLI インストーラ](https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe?hl=ja)をダウンロードします。 or または、PowerShell ターミナルを開き、以下の PowerShell コマンドを実行します。 ```.ps (New-Object Net.WebClient).DownloadFile("https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe", "$env:Temp\GoogleCloudSDKInstaller.exe") & $env:Temp\GoogleCloudSDKInstaller.exe ``` 2. **インストーラを起動して、画面の指示に沿って操作します。インストーラには Google LLC による署名が付いています。** スクリーン リーダーを使用している場合は、[スクリーン リーダー モードをオンにする] チェックボックスをオンにします。このオプションで gcloud を構成すると、Unicode スピナーの代わりにステータス トラッカーが使用され、進行状況が割合で表示されます。また、テーブルがフラット化されます。詳しくは、ユーザー補助機能のガイドをご覧ください。 ※*Google Cloud CLI には Python が必要です。サポートされているバージョンは Python 3(3.8~3.10)です。デフォルトでは、Google Cloud CLI の Windows バージョンには Python 3 がバンドルされています。Google Cloud CLI を使用するには、お使いのオペレーティング システムでサポートされているバージョンの Python を実行できる必要があります。* CLIのインストールが終わったら、**gcloud CLI**を実行して、以下コマンドを実行してください。 ```.sh gcloud auth login ``` 実行すると、Googleアカウントの認証表示されるので、GCPに登録したアカウントでログインしてください。 #### ●MacOSでのインストール方法 1. **サポートされているバージョンの Python を使用していることを確認します。** 現在の Python バージョンを確認するには、 python3 -V または python -V を実行します。サポートされているバージョンは Python 3(3.8~3.10)です。 Google Cloud CLI リリース バージョン 352.0.0 以降の場合、メインのインストール スクリプトでは、Intel ベースの Mac に CPython の Python 3.10 をインストールできます。 そうでない場合は、サポートされている Python バージョンをインストールするには、Python.org の macOS 用 Python リリースにアクセスしてください。 マシンに複数の Python インタープリタがインストールされている場合は、希望するインタープリタのパスを指すようにシェル内に CLOUDSDK_PYTHON 環境変数を設定します。 Python インタープリタの選択方法と構成方法についてはgcloud topic startup をご覧ください。 2. **インストーラをダウンロードします。** | パッケージ | サイズ | SHA256 | チェックサム | | -------- | -------- | -------- | -------- | |macOS 64 ビット (x86_64) | [google-cloud-cli-452.0.1-darwin-x86_64.tar.gz](https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-452.0.1-darwin-x86_64.tar.gz?hl=ja) | 123.0 MB | 2afce77c2a4c98bf6a133018b71c92bf22ef63940867f1e919c8b4d0959e13c6 | |macOS 64 ビット (ARM64, Apple M1 silicon) | [google-cloud-cli-452.0.1-darwin-arm.tar.gz](https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-452.0.1-darwin-arm.tar.gz?hl=ja) | 120.1 MB | b57abce33c044ddd2608b2d4993d91b2148c823abb1bb4dfadb6034c1ab9343c | | macOS 32 ビット (x86) | [google-cloud-cli-452.0.1-darwin-x86.tar.gz](https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-452.0.1-darwin-x86.tar.gz?hl=ja) | 121.7 MB | b3b35a6bc0eea9e5f7ea1c2f0407c571a63457a31c2c31d55e326fe17eb3169d | 3. **インストーラーの展開** アーカイブをファイル システム上の任意の場所に展開します。ホーム ディレクトリを使用することをおすすめします。macOS では、ダウンロードした .tar.gz アーカイブ ファイルを任意の場所で開くことでこれを実現できます。 既存のインストールを置き換えるには、既存の google-cloud-sdk ディレクトリを削除し、同じ場所にアーカイブを展開します。 4. **インストーラの実行** インストール スクリプトを使用して、gcloud CLI ツールを PATH に追加します。また、シェル、使用統計情報の収集ではコマンドの補完を利用し、Python 3.10 をインストールできます。 このコマンドを使用して(前の手順で展開したフォルダのルートから)スクリプトを実行します。 ```.sh ./google-cloud-sdk/install.sh ``` 5. **gcloud CLI を初期化するには、gcloud init を実行します。** CLIのインストールが終わったら、**gcloud CLI**を実行して、以下コマンドを実行してください。 ```.sh gcloud auth login ``` 実行すると、Googleアカウントの認証表示されるので、GCPに登録したアカウントでログインしてください。 **以上で事前準備終了です**、お疲れさまでした。 --- ## ハンズオン課題 ### a. 今回使用するプログラムのダウンロード 以下githubのlinkから今回使用するプログラム一式をダウンロードできます。 [github link](https://github.com/taka-baya/learning_gcp_appengine) or コマンド ``` git clone https://github.com/taka-baya/learning_gcp_appengine.git ``` ●フォルダ階層 ``` ./app/ |-main.py |-app.yaml |-templates |-chart.html ``` ● ./app/main.py ```.py import os from flask import Flask, render_template, request from google.cloud import bigquery from google.cloud import bigquery from google.oauth2 import service_account #key_path = "..\\ssh\\credencial-key.json" #credentials = service_account.Credentials.from_service_account_file( # key_path, scopes=["https://www.googleapis.com/auth/cloud-platform"], #) #bigquery_client = bigquery.Client(credentials=credentials, project=credentials.project_id,) bigquery_client = bigquery.Client() app = Flask(__name__) # リクエストを受け付ける関数 @app.route('/', methods=['GET']) def diplay(): #BigQueryにクエリを投げる query_job = bigquery_client.query( """ SELECT * FROM `your-databse-name` ORDER BY day """ ) # クエリの実行結果をデータフレームに取得する df = query_job.to_dataframe() #print(type(df)) # print(df.fillna(0)) # df = df.fillna(0) labels = df["day"] datas = [df["Goods_and_services"], df["Goods_total"], df["Exports"], df["Imports"], df["Services"]] return render_template('chart.html', datas=datas, labels=labels) if __name__ == '__main__': #ローカル実行時はCloud Shell推奨の8080ポートを使用する app.run(host='0.0.0.0', port=8080) ``` ./app/app.yaml ```.yaml runtime: python310 service: default ``` ./app/requirements.txt ```.txt db-dtypes==1.1.1 Flask==3.0.0 google-cloud-bigquery==3.13.0 pandas==2.1.2 pyarrow==13.0.0 ``` ./app/templates/chart.html ```.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>課題</title> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0"></script> </head> <body> <canvas id="chart"></canvas> <script> window.chartColors = { red: 'rgb(255, 99, 132)', orange: 'rgb(255, 159, 64)', yellow: 'rgb(255, 205, 86)', green: 'rgb(75, 192, 192)', blue: 'rgb(54, 162, 235)', purple: 'rgb(153, 102, 255)', grey: 'rgb(201, 203, 207)' }; var chartDatas = { type: 'bar', data: { labels: [ {% for label in labels %} "{{label}}", {% endfor %} ], datasets: [{ label: '輸入出とサービス事業の国際支出', type: 'bar', backgroundColor: window.chartColors.red, borderColor: window.chartColors.red, yAxisID: 'yaxis1', data: [ {% for data in datas[0] %} {{data}}, {% endfor %} ], fill: false, }, { label: '貿易支出トータル', type: 'bar', fill: false, backgroundColor: window.chartColors.green, borderColor: window.chartColors.green, yAxisID: 'yaxis1', data: [ {% for data in datas[1] %} {{data}}, {% endfor %} ], }, { label: '輸出', type: 'line', fill: false, backgroundColor: window.chartColors.orange, borderColor: window.chartColors.orange, yAxisID: 'yaxis1', data: [ {% for data in datas[2] %} {{data}}, {% endfor %} ], }, { label: '輸入', type: 'line', fill: false, backgroundColor: window.chartColors.grey, borderColor: window.chartColors.grey, yAxisID: 'yaxis1', data: [ {% for data in datas[3] %} {{data}}, {% endfor %} ], }, { label: 'サービス事業', type: 'line', fill: false, backgroundColor: window.chartColors.purple, borderColor: window.chartColors.purple, yAxisID: 'yaxis1', data: [ {% for data in datas[4] %} {{data}}, {% endfor %} ], }] }, options: { responsive: true, title: { display: true, text: '日本の感染状況' }, tooltips: { mode: 'index', intersect: false, }, hover: { mode: 'nearest', intersect: true }, scales: { x: { display: true, scaleLabel: { display: true, labelString: '日付' } }, yaxis1 : { display: true, position: 'left', scaleLabel: { display: true, labelString: '¥' } }, yaxis2 : { display: true, position: 'right', scaleLabel: { display: true, labelString: '¥' } } } } }; var mychart = document.getElementById("chart"); var chart = new Chart(mychart, chartDatas); </script> </body> </html> ``` ### b. BigQueryにデータを追加 #### データのダウンロード 今回使うデータは以下リンクのページの「6s-1-4 国際収支総括表【月次】」からダウンロードできます。 https://www.mof.go.jp/policy/international_policy/reference/balance_of_payments/bpnet.htm 既に整形済みのものを用意しているので、以下URL or コマンドでダウンロードしてください。 [整形済みデータダウンロードURL](https://storage.googleapis.com/balance-of-payments/Sample_data.csv) or ```.sh curl -O https://storage.googleapis.com/balance-of-payments/Sample_data.csv ``` 任意のフォルダに「Sample_data.csv」がダウンロードされていることを確認してください。 #### BigQueryにデータを追加する。 **●GUIの場合** 以下画面のように。左横のタブから「BigQuery」を選択して、「+追加」を選択してください。 ![IAM.png](https://hackmd.io/_uploads/SkJBOaxmp.png) その後、「一般的なソース」の下に「ローカル ファイル」があるのでそちらを選択してください。 すると、以下画像のようにテーブルを作成する画面が出てきます。 ![図1.png](https://hackmd.io/_uploads/SJj21Rg7p.png) > 項目ソース:こちらはダウンロードしたデータセットを選択してアップロードしてください・ > 送信先:対象のプロジェクトを選択、項目「データセット」はDBです。任意のDB名を入力してどこのリージョンに保存するか選択してください。項目「テーブル」はテーブルなので、任意のテーブル名を入力してください。 > スキーマ:こちらの項目はカラム名の編集です。基本的に自動でカラム名が認識されますが、自分で編集したい場合はこちらを設定してください。 **CLIの場合** CLIの場合はgcloud CLIを使ってローカルのダウンロードしたCSVファイルからBigQueryにデータベースを作成します。以下URLのドキュメントのページ内タブ「bq」を選択して参照して構築してみてください。 https://cloud.google.com/bigquery/docs/batch-loading-data?hl=ja#bq 例) ・テーブルの作成 ``` bq load --skip_leading_rows=1 --source_format=CSV mydataset.mytable data.csv my_schema.json ``` スキーマ.jsonの例 ```.json [ {"name": "day", "type": "date", "mode": "required"}, {"name": "Goods_and_services", "type": "integer", "mode": "required"}, {"name": "Goods_total", "type": "integer", "mode": "required"}, {"name": "Exports", "type": "integer", "mode": "required"}, {"name": "Imports", "type": "integer", "mode": "required"}, {"name": "Services", "type": "integer", "mode": "required"} ] ``` テーブルが作成完了したら、「BigQuery Studio」に戻り以下SQLを実行してみてください。 ```.sql SELECT * FROM `learning-gcp-403802.Finance_data.balance_of_payments` LIMIT 1000 ``` ### c. クレデンシャルキーの作成 「IAMと管理」を選択して、「サービスアカウント」を選択してください。 ![IAM.png](https://hackmd.io/_uploads/S1gOMpgma.png) その後、「サービスアカウント作成」を選択してクレデンシャルキーを作成します。作成するサービスアカウント名は任意に決めて頂いて問題無いです。 ただし、アクセス権限に関しては「BigQuery 管理者」としてロールを設定してください ![IAM.png](https://hackmd.io/_uploads/HkKyrpgma.png) 新しくサービスアカウントを作成したらサービスアカウント一覧に、新しく作成したサービスアカウントの名前が表示されます。 それを選択すると、キーというタブが表示されると思います。 「キー」というタブが表示されたら、 > 「新しい鍵を追加」->「新しい鍵を作成」->「Json」-「作成」 を選択してください。するとJson形式のファイルがダウンロードされると思います。**しっかりとした場所に保管しておきましょう(例えば ~./.ssh/ とか)** ![IAM.png](https://hackmd.io/_uploads/SyI1Dax76.png) ### d. ローカル端末での実行 ※本作業では、クレデンシャルキーとBigQueryでのDB構築が終えてから取り組んでください。 **step1.** まずは、ダウンロードしたサンプルプログラムのフォルダ内のmain.pyを開いてください。 **step2.** 開いた後に以下のように10行目~のコメントアウト「#」を削除して、16行目をコメントアウト「#」してください。 **step3.** 次に、10行目の変数key_pathにダウンロードしたクレデンシャルキーのパスを記載してください。 **step4.** 次に、29行目の'your-databse-name'をBigQueryで作成したデータベース名を指定してください。 ```.py= import os from flask import Flask, render_template, request from google.cloud import bigquery from google.cloud import bigquery from google.oauth2 import service_account key_path = "..\\ssh\\credencial-key.json" credentials = service_account.Credentials.from_service_account_file( key_path, scopes=["https://www.googleapis.com/auth/cloud-platform"], ) bigquery_client = bigquery.Client(credentials=credentials, project=credentials.project_id,) #bigquery_client = bigquery.Client() app = Flask(__name__) # リクエストを受け付ける関数 @app.route('/', methods=['GET']) def diplay(): #BigQueryにクエリを投げる query_job = bigquery_client.query( """ SELECT * FROM `your-databse-name` ORDER BY day """ ) # クエリの実行結果をデータフレームに取得する df = query_job.to_dataframe() #print(type(df)) # print(df.fillna(0)) # df = df.fillna(0) labels = df["day"] datas = [df["Goods_and_services"], df["Goods_total"], df["Exports"], df["Imports"], df["Services"]] return render_template('chart.html', datas=datas, labels=labels) if __name__ == '__main__': #ローカル実行時はCloud Shell推奨の8080ポートを使用する app.run(host='0.0.0.0', port=8080) ``` **step5.** 最後に、更新したmain.pyを保存して、ターミナルやコマンドなのでmain.pyがあるフォルダに対して以下コマンドを実行してください。 ```.sh python main.py ``` **step6.** 最後に http://localhost:8080 でグラフチャートが表示されるかを確認してください。 ### e. AppEngineにデプロイ AppEngineの概要に関しては以下資料を参照してください。 https://cloud.google.com/appengine/docs/the-appengine-environments?hl=ja それでは最後に、AppEngineでデプロイする用にプログラムを書き直します。 main.pyを開いた後に以下のように10行目~のコメントアウト「#」を追記し、16行目をコメントアウト「#」を外してください。 ```.py= import os from flask import Flask, render_template, request from google.cloud import bigquery from google.cloud import bigquery from google.oauth2 import service_account #key_path = "..\\ssh\\credencial-key.json" #credentials = #service_account.Credentials.from_service_account_file( # key_path, scopes=["https://www.googleapis.com/auth/cloud-platform"], #) #bigquery_client = bigquery.Client(credentials=credentials, project=credentials.project_id,) bigquery_client = bigquery.Client() app = Flask(__name__) # リクエストを受け付ける関数 @app.route('/', methods=['GET']) def diplay(): #BigQueryにクエリを投げる query_job = bigquery_client.query( """ SELECT * FROM `your-databse-name` ORDER BY day """ ) # クエリの実行結果をデータフレームに取得する df = query_job.to_dataframe() #print(type(df)) # print(df.fillna(0)) # df = df.fillna(0) labels = df["day"] datas = [df["Goods_and_services"], df["Goods_total"], df["Exports"], df["Imports"], df["Services"]] return render_template('chart.html', datas=datas, labels=labels) if __name__ == '__main__': #ローカル実行時はCloud Shell推奨の8080ポートを使用する app.run(host='0.0.0.0', port=8080) ``` main.pyへの修正が終わった場合は保存してください。 クラウドへのデプロイは簡単です。 app.yamlがあるフォルダに対してターミナルで移動して以下コマンドを実行するだけです。 ``` gcloud app deploy ``` #### ※Python Runtime について app.yamlについてもっと知りたい方は以下記事を参照してください。 https://cloud.google.com/appengine/docs/standard/python3/runtime?hl=ja ### f. カスタマイズ開発 課題1 : もっと見やすいグラフにしてください。 課題2 : 輸出と輸入の割合の円グラフとか作れないですかね...

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully