From 90adfef85952cd2871eab79b4b991e5a482fe356 Mon Sep 17 00:00:00 2001 From: Zeakeers <168440015+Zeakeers@users.noreply.github.com> Date: Thu, 24 Apr 2025 15:23:30 +0700 Subject: [PATCH] menambahakn insert database dan testing selenium --- backend/DImas Adi hitungan manual KNN.xlsx | Bin 0 -> 30667 bytes backend/app.py | 163 +++++++++++++++++++-- backend/dataset.xlsx | Bin 9498 -> 14209 bytes frontend/package-lock.json | 76 +++++++++- frontend/package.json | 1 + frontend/src/App.js | 147 +++++++++++++++---- frontend/src/components/Header.js | 54 ++++--- frontend/src/components/KategoriRating.js | 20 +-- frontend/src/components/Tentang.js | 5 +- frontend/src/index.js | 5 +- frontend/src/pages/ListGame.js | 140 ++++++++++++++++++ frontend/src/routes/routes.js | 17 +++ frontend/tailwind.config.js | 13 +- msedgedriver.exe | Bin 0 -> 18884672 bytes test_game_rating_edge.py | 136 +++++++++++++++++ 15 files changed, 698 insertions(+), 79 deletions(-) create mode 100644 backend/DImas Adi hitungan manual KNN.xlsx create mode 100644 frontend/src/pages/ListGame.js create mode 100644 frontend/src/routes/routes.js create mode 100644 msedgedriver.exe create mode 100644 test_game_rating_edge.py diff --git a/backend/DImas Adi hitungan manual KNN.xlsx b/backend/DImas Adi hitungan manual KNN.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2bff319f98c81a1146ba1df54bfab108f4c58ff4 GIT binary patch literal 30667 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 literal 0 HcmV?d00001 diff --git a/backend/app.py b/backend/app.py index bcc7a39..2c301bd 100644 --- a/backend/app.py +++ b/backend/app.py @@ -1,8 +1,19 @@ from flask import Flask, request, jsonify +from sklearn.metrics import confusion_matrix, classification_report, accuracy_score from flask_cors import CORS from sklearn.neighbors import KNeighborsClassifier import pandas as pd import os +import mysql.connector + +# Konfigurasi koneksi database MySQL +DB_CONFIG = { + 'host': 'localhost', + 'user': 'root', + 'password': '', + 'database': 'game_rating_db' +} + app = Flask(__name__) CORS(app) @@ -60,6 +71,42 @@ def add_to_dataset(name, features, rating): data.loc[len(data)] = new_row data.to_excel(DATASET_FILE, index=False) +# Fungsi untuk menyimpan ke database MySQL +def save_rating_to_db(game_name, rating): + kategori_map = { + "SU": "Semua Umur", + "3+": "Untuk usia 3 tahun ke atas", + "7+": "Untuk usia 7 tahun ke atas", + "13+": "Untuk usia 13 tahun ke atas", + "18+": "Untuk usia 18 tahun ke atas" + } + kategori = kategori_map.get(rating, "Tidak diketahui") + + try: + conn = mysql.connector.connect(**DB_CONFIG) + cursor = conn.cursor() + + cursor.execute(""" + CREATE TABLE IF NOT EXISTS riwayat ( + id INT AUTO_INCREMENT PRIMARY KEY, + nama_game VARCHAR(255), + rating VARCHAR(10), + kategori VARCHAR(100) + ) + """) + + cursor.execute(""" + INSERT INTO riwayat (nama_game, rating, kategori) + VALUES (%s, %s, %s) + """, (game_name, rating, kategori)) + + conn.commit() + cursor.close() + conn.close() + except mysql.connector.Error as err: + print("ERROR saat menyimpan ke database:", err) + + # Endpoint untuk mengecek apakah game sudah ada dalam dataset @app.route('/check_game', methods=['POST']) def check_game(): @@ -89,21 +136,21 @@ def submit_answers(): answers = data.get('answers', []) if not game_name or not answers: - print("❌ ERROR: Data tidak lengkap") + print("ERROR: Data tidak lengkap") return jsonify({"error": "Data tidak lengkap"}), 400 - print("✔ Nama Game:", game_name) - print("✔ Jawaban:", answers) + print("Nama Game:", game_name) + print("Jawaban:", answers) # Cek apakah jawaban valid features = [] for answer in answers: if answer not in REVERSE_MAPPING: - print(f"❌ ERROR: Jawaban tidak valid -> {answer}") + print(f"ERROR: Jawaban tidak valid -> {answer}") return jsonify({"error": f"Jawaban tidak valid: {answer}"}), 400 features.append(REVERSE_MAPPING[answer]) - print("✔ Features (dikonversi ke angka):", features) + print("Features (dikonversi ke angka):", features) X, y, dataset = load_dataset() @@ -111,12 +158,12 @@ def submit_answers(): # Jika game sudah ada di dataset, kembalikan rating yang sudah ada if game_name in dataset["Nama Game"].values: existing_rating = dataset.loc[dataset["Nama Game"] == game_name, "Rating"].values[0] - print("✔ Game ditemukan dalam dataset. Rating:", existing_rating) + print("Game ditemukan dalam dataset. Rating:", existing_rating) return jsonify({'rating': existing_rating}) # Prediksi rating dengan KNN jika dataset cukup besar if len(X) > 3: - knn = KNeighborsClassifier(n_neighbors=3) + knn = KNeighborsClassifier(n_neighbors=5) knn.fit(X, y) predicted_rating = knn.predict([features])[0] else: @@ -132,14 +179,112 @@ def submit_answers(): else: predicted_rating = "18+" - print("✔ Prediksi Rating:", predicted_rating) + print("Prediksi Rating:", predicted_rating) add_to_dataset(game_name, features, predicted_rating) + save_rating_to_db(game_name, predicted_rating) return jsonify({'rating': predicted_rating}) except Exception as e: - print("❌ ERROR di backend:", str(e)) + print("ERROR di backend:", str(e)) return jsonify({"error": str(e)}), 500 + +@app.route('/autocomplete', methods=['GET']) +def autocomplete(): + try: + query = request.args.get('query', '').strip().lower() + + if not query: + return jsonify([]) + + _, _, dataset = load_dataset() + + # Mencari game yang mengandung teks yang diketik pengguna + suggestions = dataset[dataset["Nama Game"].str.lower().str.contains(query, na=False)]["Nama Game"].tolist() + + return jsonify(suggestions) + except Exception as e: + return jsonify({"error": str(e)}), 500 + + +@app.route('/latest_games', methods=['GET']) +def latest_games(): + _, _, dataset = load_dataset() + + latest_games = dataset["Nama Game"].dropna().values[-4:].tolist() + + return jsonify(latest_games) + +@app.route('/all_games', methods=['GET']) +def all_games(): + try: + _, _, dataset = load_dataset() + + if "Nama Game" in dataset.columns and "Rating" in dataset.columns: + games = dataset[["Nama Game", "Rating"]].to_dict(orient="records") + return jsonify(games) + + return jsonify({"error": "Kolom Nama Game atau Rating tidak ditemukan"}), 500 + except Exception as e: + return jsonify({"error": str(e)}), 500 + +# @app.route('/evaluate_model', methods=['GET']) +# def evaluate(): +# try: +# X, y, _ = load_dataset() + +# if len(X) < 2: +# return jsonify({"error": "Dataset terlalu kecil untuk evaluasi"}), 400 + +# knn = KNeighborsClassifier(n_neighbors=5) +# knn.fit(X, y) +# y_pred = knn.predict(X) + +# labels = sorted(list(set(y))) +# cm = confusion_matrix(y, y_pred, labels=labels) +# accuracy = accuracy_score(y, y_pred) + +# # Hitung metrik per kelas secara manual +# results = {} +# total_TP = total_FP = total_FN = total_TN = 0 + +# for i, label in enumerate(labels): +# TP = cm[i][i] +# FN = sum(cm[i]) - TP +# FP = sum(cm[:, i]) - TP +# TN = cm.sum() - (TP + FN + FP) + +# recall = TP / (TP + FN) if (TP + FN) else 0 +# precision = TP / (TP + FP) if (TP + FP) else 0 + +# results[label] = { +# "TP": int(TP), +# "FN": int(FN), +# "FP": int(FP), +# "TN": int(TN), +# "recall": round(float(recall), 4), +# "recall_formula": f"{int(TP)} / ({int(TP)} + {int(FN)})", +# "precision": round(float(precision), 4), +# "precision_formula": f"{int(TP)} / ({int(TP)} + {int(FP)})", +# } + + +# total_TP += TP +# total_FP += FP +# total_FN += FN +# total_TN += TN + +# acc_formula = f"({total_TP} + {total_TN}) / ({total_TP} + {total_TN} + {total_FP} + {total_FN})" +# acc_value = (total_TP + total_TN) / (total_TP + total_TN + total_FP + total_FN) + +# return jsonify({ +# "accuracy": round(float(acc_value), 4), +# "accuracy_formula": acc_formula, + +# "per_class_metrics": results +# }) +# except Exception as e: +# return jsonify({"error": str(e)}), 500 diff --git a/backend/dataset.xlsx b/backend/dataset.xlsx index 6a84c2698413c19bf064c7919c67395804930d38..3f7b94edfd317475882a6b8c06985cbb374e571b 100644 GIT binary patch literal 14209 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 literal 9498 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.10.0" } }, + "node_modules/react-router": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.2.0.tgz", + "integrity": "sha512-fXyqzPgCPZbqhrk7k3hPcCpYIlQ2ugIXDboHUzhJISFVy2DEPsmHgN588MyGmkIOv3jDgNfUE3kJi83L28s/LQ==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.2.0.tgz", + "integrity": "sha512-cU7lTxETGtQRQbafJubvZKHEn5izNABxZhBY0Jlzdv0gqQhCPQt2J8aN5ZPjS6mQOXn5NnirWNh+FpE8TTYN0Q==", + "license": "MIT", + "dependencies": { + "react-router": "7.2.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -14654,6 +14710,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -16020,6 +16082,12 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "license": "0BSD" }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "license": "ISC" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -16150,9 +16218,9 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "license": "Apache-2.0", "peer": true, "bin": { @@ -16160,7 +16228,7 @@ "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=4.2.0" } }, "node_modules/unbox-primitive": { diff --git a/frontend/package.json b/frontend/package.json index 5ffc55a..deb554d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,6 +14,7 @@ "description": "", "dependencies": { "react-dom": "^19.0.0", + "react-router-dom": "^7.2.0", "react-scripts": "^5.0.1" }, "browserslist": { diff --git a/frontend/src/App.js b/frontend/src/App.js index 4ef5f68..882b1f8 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,4 +1,5 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useRef } from "react"; +import { useLocation } from "react-router-dom"; import Header from "./components/Header"; import Footer from "./components/Footer"; import Tentang from "./components/Tentang"; @@ -39,6 +40,12 @@ const App = () => { const [isPopUpOpen, setIsPopUpOpen] = useState(false); const [isConfirmPopupOpen, setIsConfirmPopupOpen] = useState(false); const [selectedOption, setSelectedOption] = useState(""); + const [latestGames, setLatestGames] = useState([]); + const [easterEggActive, setEasterEggActive] = useState(false); + const homeRef = useRef(null); + const tentangRef = useRef(null); + const kontakRef = useRef(null); + const location = useLocation(); useEffect(() => { if (gameName.length > 1) { @@ -51,26 +58,46 @@ const App = () => { } }, [gameName]); + useEffect(() => { + fetch("http://127.0.0.1:5000/latest_games") + .then(res => res.json()) + .then(data => setLatestGames(data.slice(-5))) + .catch(err => console.error("Error fetching latest games:", err)); + }, []); + + useEffect(() => { + if (location.hash) { + const section = location.hash.replace("#", ""); + scrollToSection(section); + } + }, [location]); + const handleSelectGame = (selectedGame) => { setGameName(selectedGame); setSuggestions([]); }; const checkGame = async () => { + if (gameName.trim().toLowerCase() === "lulus 2025") { + setEasterEggActive(true); + setRating("🎉 BISMILLAH LULUS 2025 DENGAN SEDIKIT REVISI 🎓"); + return; + } + + setEasterEggActive(false); const response = await fetch("http://127.0.0.1:5000/check_game", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ game_name: gameName }), }); const data = await response.json(); - + if (data.exists) { setRating(data.rating); } else { setStep(1); } - }; - + }; const handleOptionClick = (option) => { setSelectedOption(option); setIsPopUpOpen(true); @@ -97,10 +124,34 @@ const App = () => { setRating(data.rating); }; + const fetchGameRating = async (game) => { + const response = await fetch("http://127.0.0.1:5000/check_game", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ game_name: game }), + }); + const data = await response.json(); + + if (data.exists) { + setGameName(game); + setRating(data.rating); + setStep(0); + } + }; + + const scrollToSection = (section) => { + if (section === "home") { + homeRef.current?.scrollIntoView({ behavior: "smooth" }); + } else if (section === "tentang") { + tentangRef.current?.scrollIntoView({ behavior: "smooth" }); + } else if (section === "kontak") { + kontakRef.current?.scrollIntoView({ behavior: "smooth" }); + } + }; return (
-
-
+
0 || rating ? 'bg-white rounded-lg shadow-md' : ''}`}> {step === 0 && !rating && ( @@ -117,8 +168,7 @@ const App = () => { className="w-6 h-6 bg-yellow-500 rounded-full hover:bg-yellow-700" /> )} - - {/* Tombol merah: Kembali ke input nama game */} +
)} - {!rating && step === 0 && ( <>

Masukkan nama game:

@@ -158,9 +207,30 @@ const App = () => { > Cek + {/* Daftar 5 game terbaru */} + {latestGames.length > 0 && ( +
+

Game Terbaru:

+
+ {latestGames.map((game, index) => ( + + ))} + {latestGames.length >= 4 && ( + + Selengkapnya + + )} +
+
+ )} )} - {!rating && step > 0 && step <= questions.length && ( <>

{questions[step - 1]}

@@ -175,7 +245,6 @@ const App = () => { ))} )} - {!rating && step > questions.length && ( <> {/* Menampilkan tabel hasil jawaban */} @@ -198,7 +267,6 @@ const App = () => {
- {/* Tombol kembali ke input game */} - {/* Tombol untuk konfirmasi hasil */} - + <> + {easterEggActive ? ( +

+ 🎉 BISMILLAH LULUS 2025 DENGAN SEDIKIT REVISI 🎓 +

+ ) : ( + <> +

+ Game {gameName} memiliki rating + {rating} +

+

Penjelasan: {ratingDescriptions[rating]}

+ + )} + + + )} + {/* Pop-up konfirmasi pilihan jawaban */} { />
+
+
-