Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 271 additions & 0 deletions Untitled5 (1).ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Js2EDbooJ-Vt",
"outputId": "41fd3286-4320-410d-9dbe-cc20446af531"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: Flask in /usr/local/lib/python3.10/dist-packages (2.2.5)\n",
"Requirement already satisfied: Flask-SQLAlchemy in /usr/local/lib/python3.10/dist-packages (3.1.1)\n",
"Requirement already satisfied: pyngrok in /usr/local/lib/python3.10/dist-packages (7.1.6)\n",
"Requirement already satisfied: Werkzeug>=2.2.2 in /usr/local/lib/python3.10/dist-packages (from Flask) (3.0.3)\n",
"Requirement already satisfied: Jinja2>=3.0 in /usr/local/lib/python3.10/dist-packages (from Flask) (3.1.4)\n",
"Requirement already satisfied: itsdangerous>=2.0 in /usr/local/lib/python3.10/dist-packages (from Flask) (2.2.0)\n",
"Requirement already satisfied: click>=8.0 in /usr/local/lib/python3.10/dist-packages (from Flask) (8.1.7)\n",
"Requirement already satisfied: sqlalchemy>=2.0.16 in /usr/local/lib/python3.10/dist-packages (from Flask-SQLAlchemy) (2.0.30)\n",
"Requirement already satisfied: PyYAML>=5.1 in /usr/local/lib/python3.10/dist-packages (from pyngrok) (6.0.1)\n",
"Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from Jinja2>=3.0->Flask) (2.1.5)\n",
"Requirement already satisfied: typing-extensions>=4.6.0 in /usr/local/lib/python3.10/dist-packages (from sqlalchemy>=2.0.16->Flask-SQLAlchemy) (4.11.0)\n",
"Requirement already satisfied: greenlet!=0.4.17 in /usr/local/lib/python3.10/dist-packages (from sqlalchemy>=2.0.16->Flask-SQLAlchemy) (3.0.3)\n"
]
}
],
"source": [
"!pip install Flask Flask-SQLAlchemy pyngrok\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "JKLJL7ByLzqb"
},
"outputs": [],
"source": [
"from pyngrok import ngrok\n",
"ngrok.set_auth_token(\"2gx23kWANtv3mkL9a1sfHSG7yFN_74JPdicAhw28d57ncaFDr\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"background_save": true,
"base_uri": "https://localhost:8080/"
},
"id": "cHOxhtAwKEzI",
"outputId": "e39e72d1-a08a-400f-a94b-892f09c750b8"
},
"outputs": [
{
"metadata": {
"tags": null
},
"name": "stdout",
"output_type": "stream",
"text": [
" * ngrok tunnel \"https://93d8-104-196-5-25.ngrok-free.app\" -> \"http://127.0.0.1:5000/\"\n",
" * Serving Flask app '__main__'\n",
" * Debug mode: off\n"
]
},
{
"output_type": "stream",
"name": "stderr",
"text": [
"INFO:werkzeug:\u001b[31m\u001b[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.\u001b[0m\n",
" * Running on http://127.0.0.1:5000\n",
"INFO:werkzeug:\u001b[33mPress CTRL+C to quit\u001b[0m\n",
"INFO:werkzeug:127.0.0.1 - - [25/May/2024 08:35:18] \"GET / HTTP/1.1\" 200 -\n",
"INFO:werkzeug:127.0.0.1 - - [25/May/2024 08:35:18] \"\u001b[33mGET /favicon.ico HTTP/1.1\u001b[0m\" 404 -\n",
"INFO:werkzeug:127.0.0.1 - - [25/May/2024 08:35:35] \"\u001b[35m\u001b[1mPOST /api/add_course HTTP/1.1\u001b[0m\" 201 -\n",
"INFO:werkzeug:127.0.0.1 - - [25/May/2024 08:35:40] \"\u001b[35m\u001b[1mPOST /api/add_course HTTP/1.1\u001b[0m\" 201 -\n",
"INFO:werkzeug:127.0.0.1 - - [25/May/2024 09:30:45] \"\u001b[35m\u001b[1mPOST /api/add_course HTTP/1.1\u001b[0m\" 201 -\n",
"INFO:werkzeug:127.0.0.1 - - [25/May/2024 09:31:07] \"GET / HTTP/1.1\" 200 -\n"
]
}
],
"source": [
"from flask import Flask, request, jsonify, render_template\n",
"from flask_sqlalchemy import SQLAlchemy\n",
"from pyngrok import ngrok\n",
"import os\n",
"\n",
"# ngrok 인증 토큰 설정\n",
"ngrok.set_auth_token(\"2gx23kWANtv3mkL9a1sfHSG7yFN_74JPdicAhw28d57ncaFDr\")\n",
"\n",
"# Flask 애플리케이션 설정\n",
"app = Flask(__name__)\n",
"app.config['SECRET_KEY'] = 'your_secret_key'\n",
"app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.db'\n",
"db = SQLAlchemy(app)\n",
"\n",
"class Student(db.Model):\n",
" id = db.Column(db.Integer, primary_key=True)\n",
" username = db.Column(db.String(80), unique=True, nullable=False)\n",
" password = db.Column(db.String(80), nullable=False)\n",
" courses = db.relationship('Course', backref='student', lazy=True)\n",
"\n",
"class Course(db.Model):\n",
" id = db.Column(db.Integer, primary_key=True)\n",
" name = db.Column(db.String(120), nullable=False)\n",
" credits = db.Column(db.Integer, nullable=False)\n",
" grade = db.Column(db.String(10), nullable=False)\n",
" student_id = db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False)\n",
"\n",
"# 학점 변환 함수\n",
"def grade_to_points(grade):\n",
" grade_points = {\n",
" \"A+\": 4.5, \"A\": 4.0, \"A-\": 3.7,\n",
" \"B+\": 3.3, \"B\": 3.0, \"B-\": 2.7,\n",
" \"C+\": 2.3, \"C\": 2.0, \"C-\": 1.7,\n",
" \"D+\": 1.3, \"D\": 1.0, \"D-\": 0.7,\n",
" \"F\": 0.0\n",
" }\n",
" return grade_points.get(grade, 0.0)\n",
"\n",
"@app.route('/')\n",
"def index():\n",
" return render_template('index.html')\n",
"\n",
"@app.route('/api/add_course', methods=['POST'])\n",
"def add_course():\n",
" data = request.json\n",
" student_id = data['student_id']\n",
" name = data['name']\n",
" credits = data['credits']\n",
" grade = data['grade']\n",
"\n",
" course = Course(name=name, credits=credits, grade=grade, student_id=student_id)\n",
" db.session.add(course)\n",
" db.session.commit()\n",
"\n",
" return jsonify({\"message\": \"Course added successfully\"}), 201\n",
"\n",
"@app.route('/api/credits_and_gpa/<int:student_id>', methods=['GET'])\n",
"def credits_and_gpa(student_id):\n",
" student = Student.query.get(student_id)\n",
"\n",
" if not student:\n",
" return jsonify({\"message\": \"Student not found\"}), 404\n",
"\n",
" total_credits = sum(course.credits for course in student.courses)\n",
" total_grade_points = sum(course.credits * grade_to_points(course.grade) for course in student.courses)\n",
" gpa = total_grade_points / total_credits if total_credits else 0.0\n",
"\n",
" return jsonify({\n",
" 'total_credits': total_credits,\n",
" 'gpa': gpa\n",
" })\n",
"\n",
"# 데이터베이스 테이블 생성\n",
"with app.app_context():\n",
" db.create_all()\n",
"\n",
"# templates 디렉토리 생성\n",
"os.makedirs('templates', exist_ok=True)\n",
"\n",
"# HTML 템플릿 생성\n",
"index_html = \"\"\"\n",
"<!doctype html>\n",
"<html lang=\"en\">\n",
"<head>\n",
" <meta charset=\"UTF-8\">\n",
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n",
" <title>Yonsei University GPA Calculator</title>\n",
" <script>\n",
" async function addCourse() {\n",
" const studentId = document.getElementById('student_id').value;\n",
" const name = document.getElementById('name').value;\n",
" const credits = document.getElementById('credits').value;\n",
" const grade = document.getElementById('grade').value;\n",
"\n",
" const response = await fetch('/api/add_course', {\n",
" method: 'POST',\n",
" headers: {\n",
" 'Content-Type': 'application/json'\n",
" },\n",
" body: JSON.stringify({ student_id: studentId, name, credits, grade })\n",
" });\n",
"\n",
" const result = await response.json();\n",
" alert(result.message);\n",
" }\n",
"\n",
" async function getCreditsAndGPA() {\n",
" const studentId = document.getElementById('student_id').value;\n",
" const response = await fetch(`/api/credits_and_gpa/${studentId}`);\n",
" const result = await response.json();\n",
" if (response.status === 200) {\n",
" document.getElementById('total_credits').innerText = `Total Credits: ${result.total_credits}`;\n",
" document.getElementById('gpa').innerText = `GPA: ${result.gpa}`;\n",
" } else {\n",
" alert(result.message);\n",
" }\n",
" }\n",
" </script>\n",
"</head>\n",
"<body>\n",
" <h1>Yonsei University GPA Calculator</h1>\n",
" <div>\n",
" <h2>Add Course</h2>\n",
" <label for=\"student_id\">Student ID:</label>\n",
" <input type=\"text\" id=\"student_id\" required><br>\n",
" <label for=\"name\">Course Name:</label>\n",
" <input type=\"text\" id=\"name\" required><br>\n",
" <label for=\"credits\">Credits:</label>\n",
" <input type=\"number\" id=\"credits\" required><br>\n",
" <label for=\"grade\">Grade:</label>\n",
" <input type=\"text\" id=\"grade\" required><br>\n",
" <button onclick=\"addCourse()\">Add Course</button>\n",
" </div>\n",
" <div>\n",
" <h2>Get Credits and GPA</h2>\n",
" <button onclick=\"getCreditsAndGPA()\">Get Credits and GPA</button>\n",
" <p id=\"total_credits\">Total Credits: </p>\n",
" <p id=\"gpa\">GPA: </p>\n",
" </div>\n",
"</body>\n",
"</html>\n",
"\"\"\"\n",
"\n",
"with open('templates/index.html', 'w') as f:\n",
" f.write(index_html)\n",
"\n",
"# ngrok 터널 설정 및 공개 URL 가져오기\n",
"ngrok_tunnel = ngrok.connect(5000)\n",
"public_url = ngrok_tunnel.public_url\n",
"print(\" * ngrok tunnel \\\"{}\\\" -> \\\"http://127.0.0.1:5000/\\\"\".format(public_url))\n",
"\n",
"# Flask 애플리케이션 실행\n",
"app.run()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "HnV_ImIWx46e"
},
"outputs": [],
"source": [
"os.makedirs('templates', exist_ok=True)\n"
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 0
}