diff --git a/.env b/.env new file mode 100644 index 0000000..b671892 --- /dev/null +++ b/.env @@ -0,0 +1,5 @@ +DB_USER=pokeval +DB_PASSWORD=pokeval +DB_HOST=10.10.5.31 +DB_PORT=3306 +DB_NAME=pokevalv2 \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..4ce1128 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,82 @@ +# # CommonsProtect Lizenz – Nicht-kommerzielle Edition (CPL-NC) + +**Version 1.0 – Stand: April 2025** +https://git.send.nrw/SCCL/main-api + +--- + +**Lizenztyp:** Quelloffen, aber nicht kommerziell nutzbar +**Autorenrecht:** © 2025 Jan Bergner +**Lizenzkürzel:** CPL-NC-1.0 + +--- + +Diese Lizenz regelt die Bedingungen für Nutzung, Veränderung und Weiterverbreitung der in diesem Repository enthaltenen Software. Ziel ist es, offene Zusammenarbeit zu ermöglichen, gleichzeitig aber eine kommerzielle Ausbeutung ohne Erlaubnis zu verhindern. + +--- + +## 1. Erlaubte Nutzung + +Diese Software darf kostenlos genutzt, kopiert, verändert und weiterverbreitet werden – **ausschließlich für nicht-kommerzielle Zwecke**. + +--- + +## 2. Namensnennungspflicht + +Wenn du den Quellcode dieser Software ganz oder in Teilen nutzt – sei es im Original oder verändert –, **musst du deutlich auf das ursprüngliche Projekt hinweisen**, inklusive: + +- Name des ursprünglichen Autors oder Projekts +- Link zur Originalquelle (z.B. Git-Repository) + +**Beispiel:** + +> "Diese Software basiert auf der SCCL Main-API, verfügbar unter https://git.send.nrw/SCCL/main-api." + +--- + +## 3. Verbot kommerzieller Nutzung + +Die Nutzung dieser Software oder abgeleiteter Werke ist **ausschließlich für nicht-kommerzielle Zwecke gestattet**. Eine kommerzielle Nutzung in jeglicher Form ist **streng untersagt**. + +### Dies umfasst unter anderem: + +- Den Verkauf, die Vermietung oder das Anbieten kostenpflichtiger Lizenzen oder Zugänge zur Software +- Die Integration oder Verwendung der Software in Produkten oder Dienstleistungen, die verkauft oder lizenziert werden +- Die Bereitstellung einer gehosteten Version (z.B. als Webservice oder API), bei der direkt oder indirekt Einnahmen erzielt werden (z.B. über Werbung, Abonnements, Spendenplattformen wie Patreon, Zugang gegen Bezahlung) +- Die Nutzung der Software zur Generierung von Einnahmen durch Content-Plattformen (z.B. Streaming, YouTube, Social Media), wenn das Projekt, die Plattform oder die Inhalte **auf irgendeine Weise monetarisiert** werden – sei es durch Werbung, Sponsoring, Bezahlabos, Spenden oder bezahlte Partnerschaften + +**Auch teilweise Monetarisierung** – etwa durch freiwillige Spenden, bezahlten Premium-Zugang oder Monetarisierung begleitender Inhalte – fällt unter diese Regelung und ist **nicht erlaubt**. + +### Ausnahmen: + +Eine kommerzielle Nutzung kann nur mit ausdrücklicher, schriftlicher Erlaubnis des ursprünglichen Autors erfolgen. + +--- + +## 4. Keine Garantie und Haftungsausschluss + +Diese Software wird **„wie besehen“** ohne ausdrückliche oder stillschweigende Garantien bereitgestellt. Insbesondere werden **keine Zusicherungen hinsichtlich Funktionalität, Eignung für einen bestimmten Zweck, Fehlerfreiheit oder Verfügbarkeit** gegeben. + +Die Nutzung dieser Software erfolgt **auf eigenes Risiko**. Der Autor übernimmt keine Verantwortung für direkte oder indirekte Schäden, Datenverlust, Ausfallzeiten, Sicherheitsprobleme oder sonstige Folgen, die sich aus der Nutzung oder dem Missbrauch der Software ergeben. + +### Produkthaftungsausschluss + +**Insbesondere ausgeschlossen ist jegliche Haftung nach dem Produkthaftungsgesetz (§1 ProdHaftG)** oder vergleichbaren Regelungen in anderen Ländern. Diese Software wird **nicht als Produkt im Sinne der Produkthaftung bereitgestellt**, da sie ohne Gegenleistung, ohne Prüfverfahren und ohne Gewähr zur Verfügung steht. + +### Nutzung in kritischen Systemen + +Diese Software ist **nicht vorgesehen oder geeignet für sicherheitskritische Anwendungen** wie: + +- Medizinische Geräte +- Luft- und Raumfahrttechnik +- Automatisierte Verkehrs- und Steuerungssysteme +- Industrieanlagen mit hohem Gefährdungspotenzial +- Systeme, bei denen ein Softwarefehler zu Personenschäden oder schweren Sachschäden führen könnte + +Die Verwendung in solchen Bereichen erfolgt ausdrücklich auf eigene Gefahr. + +--- + +## Hinweis + +Diese Lizenz ist keine anerkannte Open-Source-Lizenz im Sinne der [Open Source Definition](https://opensource.org/osd). Sie stellt eine sogenannte **„source-available“-Lizenz** dar. diff --git a/README.md b/README.md index cefd053..f9cd5fc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,31 @@ -# pokeval +# PokeVal - Pokémon Card Value API +PokeVal ist eine REST-API zur Berechnung des Marktwertes von Pokémon-Karten anhand von Auktionsdaten, Grading, Autogrammen, Fehldrucken und weiteren Faktoren. + +--- + +## 🚀 Features +- REST-API in Go (Golang) +- MySQL-Datenbank-Anbindung +- Bewertungslogik mit Base Price (BP), Exact Match Price (EMP) und individuellen Faktoren +- Konfigurierbar via `.env` +- Erweiterbar für Crawler, Authentifizierung und mehr + +--- + +## 📦 Voraussetzungen +- Go >= 1.20 +- MySQL / MariaDB Server (Datenbankstruktur gemäß Projekt) +- Git (optional) +- Tools wie Postman oder cURL für API-Tests + +--- + +## ⚙️ Installation + +1. **Projekt klonen oder Dateien anlegen** + +2. **Abhängigkeiten installieren** +```bash +go mod tidy +go run cmd/server/main.go diff --git a/api/auction_handler.go b/api/auction_handler.go new file mode 100644 index 0000000..c866bae --- /dev/null +++ b/api/auction_handler.go @@ -0,0 +1,82 @@ +package api + +import ( + "encoding/json" + "net/http" + "pokeval/db" + "strconv" + + "github.com/gorilla/mux" +) + +// GET /api/v1/auctions/{id} +func GetAuction(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, _ := strconv.Atoi(vars["id"]) + + row := db.DB.QueryRow("SELECT id, card_id, price, date_sold FROM auctions WHERE id = ?", id) + var auctionID, cardID int + var price float64 + var dateSold string + + err := row.Scan(&auctionID, &cardID, &price, &dateSold) + if err != nil { + http.Error(w, "Auktion nicht gefunden", http.StatusNotFound) + return + } + + resp := map[string]interface{}{ + "id": auctionID, + "card_id": cardID, + "price": price, + "date_sold": dateSold, + } + json.NewEncoder(w).Encode(resp) +} + +// POST /api/v1/auctions +func CreateAuction(w http.ResponseWriter, r *http.Request) { + var input struct { + CardID int `json:"card_id"` + PlatformID int `json:"platform_id"` + Price float64 `json:"price"` + Currency int `json:"currency"` + DateSold string `json:"date_sold"` + } + + json.NewDecoder(r.Body).Decode(&input) + + _, err := db.DB.Exec("INSERT INTO auctions (card_id, platform_id, price, currency, date_sold) VALUES (?, ?, ?, ?, ?)", + input.CardID, input.PlatformID, input.Price, input.Currency, input.DateSold) + + if err != nil { + http.Error(w, "Fehler beim Erstellen der Auktion", http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(map[string]string{"message": "Auktion erfolgreich erstellt"}) +} + +// GET /api/v1/auctions +func ListAuctions(w http.ResponseWriter, r *http.Request) { + rows, err := db.DB.Query("SELECT id, card_id, price FROM auctions LIMIT 50") + if err != nil { + http.Error(w, "Fehler beim Laden der Auktionen", http.StatusInternalServerError) + return + } + defer rows.Close() + + var auctions []map[string]interface{} + for rows.Next() { + var id, cardID int + var price float64 + rows.Scan(&id, &cardID, &price) + auctions = append(auctions, map[string]interface{}{ + "id": id, + "card_id": cardID, + "price": price, + }) + } + json.NewEncoder(w).Encode(auctions) +} diff --git a/api/card_handler.go b/api/card_handler.go new file mode 100644 index 0000000..548c54e --- /dev/null +++ b/api/card_handler.go @@ -0,0 +1,90 @@ +package api + +import ( + "encoding/json" + "net/http" + "pokeval/db" + "pokeval/models" + "strconv" + + "github.com/gorilla/mux" +) + +// GET /api/v1/cards/{id} +func GetCard(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + cardID, _ := strconv.Atoi(vars["id"]) + + var card models.Card + err := db.DB.QueryRow("SELECT cards_id, cards_number, cards_name FROM cards WHERE cards_id = ?", cardID). + Scan(&card.ID, &card.Number, &card.Name) + if err != nil { + http.Error(w, "{}", 404) + return + } + + // Attribute laden + rows, _ := db.DB.Query(` + SELECT ak.attributekeys_name, a.attributes_value + FROM attributes a + JOIN attributekeys ak ON ak.attributekeys_id = a.attributes_key + WHERE a.attributes_card = ?`, cardID) + + attrs := make(map[string]interface{}) + for rows.Next() { + var key string + var value []byte + rows.Scan(&key, &value) + var parsed interface{} + json.Unmarshal(value, &parsed) + attrs[key] = parsed + } + card.Attributes = attrs + + json.NewEncoder(w).Encode(card) +} + +// GET /api/v1/cards/{id} +/*func GetCard(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, _ := strconv.Atoi(vars["id"]) + + row := db.DB.QueryRow("SELECT id, name, number FROM cards WHERE id = ?", id) + var cardID int + var name, number string + + err := row.Scan(&cardID, &name, &number) + if err != nil { + http.Error(w, "Karte nicht gefunden", http.StatusNotFound) + return + } + + resp := map[string]interface{}{ + "id": cardID, + "name": name, + "number": number, + } + json.NewEncoder(w).Encode(resp) +}*/ + +// POST /api/v1/cards +func CreateCard(w http.ResponseWriter, r *http.Request) { + var input struct { + Name string `json:"name"` + Number string `json:"number"` + SeriesID int `json:"series_id"` + } + + json.NewDecoder(r.Body).Decode(&input) + + _, err := db.DB.Exec("INSERT INTO cards (name, number, series_id) VALUES (?, ?, ?)", + input.Name, input.Number, input.SeriesID) + + if err != nil { + http.Error(w, "Fehler beim Erstellen der Karte", http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(map[string]string{"message": "Karte erfolgreich erstellt"}) +} diff --git a/api/lookup_handler.go b/api/lookup_handler.go new file mode 100644 index 0000000..8412263 --- /dev/null +++ b/api/lookup_handler.go @@ -0,0 +1,37 @@ +package api + +import ( + "encoding/json" + "net/http" + "pokeval/db" +) + +// GET /api/v1/platforms +func GetPlatforms(w http.ResponseWriter, r *http.Request) { + rows, _ := db.DB.Query("SELECT id, platform_name FROM auction_platform") + defer rows.Close() + + var platforms []map[string]interface{} + for rows.Next() { + var id int + var name string + rows.Scan(&id, &name) + platforms = append(platforms, map[string]interface{}{"id": id, "name": name}) + } + json.NewEncoder(w).Encode(platforms) +} + +// GET /api/v1/currencies +func GetCurrencies(w http.ResponseWriter, r *http.Request) { + rows, _ := db.DB.Query("SELECT id, currency_code FROM currency") + defer rows.Close() + + var currencies []map[string]interface{} + for rows.Next() { + var id int + var code string + rows.Scan(&id, &code) + currencies = append(currencies, map[string]interface{}{"id": id, "code": code}) + } + json.NewEncoder(w).Encode(currencies) +} diff --git a/api/router.go b/api/router.go new file mode 100644 index 0000000..508759a --- /dev/null +++ b/api/router.go @@ -0,0 +1,29 @@ +package api + +import ( + "github.com/gorilla/mux" +) + +func NewRouter() *mux.Router { + router := mux.NewRouter().StrictSlash(true) + + // Auktionen + router.HandleFunc("/api/v1/auctions/{id}", GetAuction).Methods("GET") + router.HandleFunc("/api/v1/auctions", CreateAuction).Methods("POST") + router.HandleFunc("/api/v1/auctions", ListAuctions).Methods("GET") + + // Karten + router.HandleFunc("/api/v1/cards/{id}", GetCard).Methods("GET") + router.HandleFunc("/api/v1/cards", CreateCard).Methods("POST") + + // Bewertung + router.HandleFunc("/api/v1/value/{auction_id}", GetCardValue).Methods("GET") + + // Lookup-Tabellen + router.HandleFunc("/api/v1/platforms", GetPlatforms).Methods("GET") + router.HandleFunc("/api/v1/currencies", GetCurrencies).Methods("GET") + /*router.HandleFunc("/api/v1/autograph-types", GetAutographTypes).Methods("GET") + router.HandleFunc("/api/v1/misprint-types", GetMisprintTypes).Methods("GET")*/ + + return router +} diff --git a/api/value_handler.go b/api/value_handler.go new file mode 100644 index 0000000..95f6bb8 --- /dev/null +++ b/api/value_handler.go @@ -0,0 +1,106 @@ +package api + +import ( + "encoding/json" + "net/http" + "pokeval/db" + "pokeval/logic" + "strconv" + + "github.com/gorilla/mux" +) + +// GET /api/v1/value/{auction_id} +func GetCardValue(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + auctionID, err := strconv.Atoi(vars["auction_id"]) + if err != nil { + http.Error(w, "Ungültige Auktions-ID", http.StatusBadRequest) + return + } + + // 1️⃣ Hole die Basis-Auktionsdaten + var cardID int + query := `SELECT card_id FROM auctions WHERE id = ?` + err = db.DB.QueryRow(query, auctionID).Scan(&cardID) + if err != nil { + http.Error(w, "Auktion nicht gefunden", http.StatusNotFound) + return + } + + // 2️⃣ Base Sales: Alle Verkäufe dieser Karte + baseSales := fetchBaseSales(cardID) + + // 3️⃣ Exact Match Sales: Verkäufe mit gleichem Grading, Autograph, Misprint + exactSales := fetchExactMatchSales(auctionID) + + // 4️⃣ Bewertungsfaktoren (Dummy-Werte oder aus DB/Logik ableiten) + factors := map[string]float64{ + "GF": 1.6, + "RF": 2.0, + "EF": 2.0, + "ST": 3.5, + "DF": 1.4, + "AF": 2.0, + "MF": 1.5, + "TAF": 200, + } + + // 5️⃣ Wert berechnen + value := logic.CalculateCardValue(baseSales, exactSales, factors) + + // 6️⃣ Response + resp := map[string]interface{}{ + "auction_id": auctionID, + "calculated_value": value, + "currency": "EUR", + "factors": factors, + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(resp) +} + +// Holt alle Preise der Basisverkäufe (gleiche Karte) +func fetchBaseSales(cardID int) []float64 { + rows, err := db.DB.Query("SELECT price FROM auctions WHERE card_id = ?", cardID) + if err != nil { + return []float64{} + } + defer rows.Close() + + var prices []float64 + for rows.Next() { + var price float64 + rows.Scan(&price) + prices = append(prices, price) + } + return prices +} + +// Holt alle Exact Match Verkäufe (vereinfachte Logik) +func fetchExactMatchSales(auctionID int) []float64 { + // Beispielhafte Logik: Verkäufe mit gleichem Grading, Autograph & Misprint + query := ` + SELECT a.price + FROM auctions a + JOIN auction_gradings ag ON ag.auction_id = a.id + WHERE a.id != ? AND ag.grading_id IN ( + SELECT grading_id FROM auction_gradings WHERE auction_id = ? + ) + ` + + rows, err := db.DB.Query(query, auctionID, auctionID) + if err != nil { + return []float64{} + } + defer rows.Close() + + var prices []float64 + for rows.Next() { + var price float64 + rows.Scan(&price) + prices = append(prices, price) + } + return prices +} diff --git a/cmd/server/main.go b/cmd/server/main.go new file mode 100644 index 0000000..664c58e --- /dev/null +++ b/cmd/server/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "pokeval/api" + "pokeval/config" + "pokeval/db" +) + +func main() { + config.LoadEnv() + db.InitDB() + + router := api.NewRouter() + fmt.Println("Server läuft auf Port 8080...") + log.Fatal(http.ListenAndServe(":8080", router)) +} diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..c1b7ca2 --- /dev/null +++ b/config/config.go @@ -0,0 +1,14 @@ +package config + +import ( + "log" + + "github.com/joho/godotenv" +) + +func LoadEnv() { + err := godotenv.Load() + if err != nil { + log.Println("Keine .env Datei gefunden, verwende Umgebungsvariablen") + } +} diff --git a/db/connection.go b/db/connection.go new file mode 100644 index 0000000..fae2761 --- /dev/null +++ b/db/connection.go @@ -0,0 +1,31 @@ +package db + +import ( + "database/sql" + "fmt" + "log" + "os" + + _ "github.com/go-sql-driver/mysql" +) + +var DB *sql.DB + +func InitDB() { + dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", + os.Getenv("DB_USER"), + os.Getenv("DB_PASSWORD"), + os.Getenv("DB_HOST"), + os.Getenv("DB_PORT"), + os.Getenv("DB_NAME"), + ) + var err error + DB, err = sql.Open("mysql", dsn) + if err != nil { + log.Fatal("Fehler bei DB-Verbindung:", err) + } + if err = DB.Ping(); err != nil { + log.Fatal("Keine Verbindung zur Datenbank möglich:", err) + } + log.Println("Datenbankverbindung erfolgreich!") +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5551cba --- /dev/null +++ b/go.mod @@ -0,0 +1,9 @@ +module pokeval + +go 1.20 + +require ( + github.com/go-sql-driver/mysql v1.7.1 + github.com/gorilla/mux v1.8.0 + github.com/joho/godotenv v1.5.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..781e42b --- /dev/null +++ b/go.sum @@ -0,0 +1,6 @@ +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= diff --git a/logic/evaluator.go b/logic/evaluator.go new file mode 100644 index 0000000..d63b5b2 --- /dev/null +++ b/logic/evaluator.go @@ -0,0 +1,66 @@ +package logic + +import ( + "math" + "sort" +) + +func CalculateCardValue(baseSales, exactSales []float64, factors map[string]float64) float64 { + bpRaw := calculateBasePrice(baseSales) + emp := 0.0 + if len(exactSales) > 0 { + emp = calculateBasePrice(exactSales) + } + bpFinal := calculateFinalBasePrice(bpRaw, emp, len(exactSales)) + value := (bpFinal * factors["GF"] * factors["RF"] * factors["EF"] * factors["ST"] * factors["DF"] * factors["AF"] * factors["MF"]) + factors["TAF"] + return math.Round(value*100) / 100 +} + +func calculateBasePrice(sales []float64) float64 { + cleanSales := removeOutliers(sales) + median := calculateMedian(cleanSales) + stdDev := calculateStdDev(cleanSales, median) + vaf := 1 + (stdDev/median)*0.1 + return median * vaf +} + +func calculateFinalBasePrice(bp, emp float64, exactCount int) float64 { + weight := 0.0 + switch { + case exactCount >= 10: + weight = 0.8 + case exactCount >= 5: + weight = 0.6 + case exactCount >= 2: + weight = 0.4 + } + return (bp * (1 - weight)) + (emp * weight) +} + +func removeOutliers(sales []float64) []float64 { + median := calculateMedian(sales) + var filtered []float64 + for _, s := range sales { + if s >= median*0.7 && s <= median*1.3 { + filtered = append(filtered, s) + } + } + return filtered +} + +func calculateMedian(sales []float64) float64 { + sort.Float64s(sales) + n := len(sales) + if n%2 == 0 { + return (sales[n/2-1] + sales[n/2]) / 2 + } + return sales[n/2] +} + +func calculateStdDev(sales []float64, mean float64) float64 { + var sum float64 + for _, s := range sales { + sum += math.Pow(s-mean, 2) + } + return math.Sqrt(sum / float64(len(sales))) +} diff --git a/models/structs.go b/models/structs.go new file mode 100644 index 0000000..531bd50 --- /dev/null +++ b/models/structs.go @@ -0,0 +1,32 @@ +package models + +import "encoding/json" + +type Card struct { + ID int `json:"id"` + Number string `json:"number"` + Name string `json:"name"` + Attributes map[string]interface{} `json:"attributes"` +} + +type Auction struct { + ID int `json:"id"` + CardID int `json:"card_id"` + Price float64 `json:"price"` + Currency string `json:"currency"` + Platform string `json:"platform"` + DateSold string `json:"date_sold"` + Link string `json:"link"` + Attributes map[string]json.RawMessage `json:"attributes"` +} + +type Factors struct { + GF float64 + RF float64 + EF float64 + ST float64 + DF float64 + AF float64 + MF float64 + TAF float64 +} diff --git a/sql_database/create_tables.sql b/sql_database/create_tables.sql new file mode 100644 index 0000000..647d791 --- /dev/null +++ b/sql_database/create_tables.sql @@ -0,0 +1,120 @@ +-- -------------------------------------------------------- +-- Host: 10.10.5.31 +-- Server-Version: 8.0.41-0ubuntu0.24.04.1 - (Ubuntu) +-- Server-Betriebssystem: Linux +-- HeidiSQL Version: 12.10.0.7000 +-- -------------------------------------------------------- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET NAMES utf8 */; +/*!50503 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + + +-- Exportiere Datenbank-Struktur für pokevalv2 +CREATE DATABASE IF NOT EXISTS `pokevalv2` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */; +USE `pokevalv2`; + +-- Exportiere Struktur von Tabelle pokevalv2.attributekeys +CREATE TABLE IF NOT EXISTS `attributekeys` ( + `attributekeys_id` int NOT NULL AUTO_INCREMENT, + `attributekeys_name` varchar(250) COLLATE utf8mb4_general_ci DEFAULT NULL, + `datatype` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL, + `is_required` tinyint(1) DEFAULT '0', + PRIMARY KEY (`attributekeys_id`) USING BTREE, + UNIQUE KEY `attributekey_name` (`attributekeys_name`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Daten-Export vom Benutzer nicht ausgewählt + +-- Exportiere Struktur von Tabelle pokevalv2.attributes +CREATE TABLE IF NOT EXISTS `attributes` ( + `attributes_id` int NOT NULL AUTO_INCREMENT, + `attributes_card` int NOT NULL, + `attributes_key` int NOT NULL, + `attributes_value` json DEFAULT NULL, + PRIMARY KEY (`attributes_id`), + KEY `FK_attributes_cards` (`attributes_card`), + KEY `FK_attributes_attributekeys` (`attributes_key`), + CONSTRAINT `FK_attributes_attributekeys` FOREIGN KEY (`attributes_key`) REFERENCES `attributekeys` (`attributekeys_id`), + CONSTRAINT `FK_attributes_cards` FOREIGN KEY (`attributes_card`) REFERENCES `cards` (`cards_id`), + CONSTRAINT `attributes_chk_1` CHECK (json_valid(`attributes_value`)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Daten-Export vom Benutzer nicht ausgewählt + +-- Exportiere Struktur von Tabelle pokevalv2.auctions +CREATE TABLE IF NOT EXISTS `auctions` ( + `auctions_id` int NOT NULL AUTO_INCREMENT, + `auctions_card` int DEFAULT NULL, + `auctions_currency` int DEFAULT NULL, + `auctions_platform` int DEFAULT NULL, + `auctions_price` decimal(10,2) DEFAULT NULL, + `auctions_datesold` datetime DEFAULT NULL, + `auctions_link` longtext COLLATE utf8mb4_general_ci, + PRIMARY KEY (`auctions_id`), + KEY `FK_auctions_cards` (`auctions_card`), + KEY `FK_auctions_currency` (`auctions_currency`), + KEY `FK_auctions_platforms` (`auctions_platform`), + CONSTRAINT `FK_auctions_cards` FOREIGN KEY (`auctions_card`) REFERENCES `cards` (`cards_id`), + CONSTRAINT `FK_auctions_currency` FOREIGN KEY (`auctions_currency`) REFERENCES `currency` (`currency_id`), + CONSTRAINT `FK_auctions_platforms` FOREIGN KEY (`auctions_platform`) REFERENCES `platforms` (`platforms_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Daten-Export vom Benutzer nicht ausgewählt + +-- Exportiere Struktur von Tabelle pokevalv2.auctionsattributes +CREATE TABLE IF NOT EXISTS `auctionsattributes` ( + `auctionsattributes_id` int NOT NULL AUTO_INCREMENT, + `auctionsattributes_auction` int DEFAULT NULL, + `auctionsattributes_key` int DEFAULT NULL, + `auctionsattributes_value` json DEFAULT NULL, + PRIMARY KEY (`auctionsattributes_id`), + KEY `FK_auctionsattributes_auctions` (`auctionsattributes_auction`), + KEY `FK_auctionsattributes_attributekeys` (`auctionsattributes_key`), + CONSTRAINT `FK_auctionsattributes_attributekeys` FOREIGN KEY (`auctionsattributes_key`) REFERENCES `attributekeys` (`attributekeys_id`), + CONSTRAINT `FK_auctionsattributes_auctions` FOREIGN KEY (`auctionsattributes_auction`) REFERENCES `auctions` (`auctions_id`), + CONSTRAINT `auctionsattributes_chk_1` CHECK (json_valid(`auctionsattributes_value`)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Daten-Export vom Benutzer nicht ausgewählt + +-- Exportiere Struktur von Tabelle pokevalv2.cards +CREATE TABLE IF NOT EXISTS `cards` ( + `cards_id` int NOT NULL AUTO_INCREMENT, + `cards_number` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, + `cards_name` varchar(250) COLLATE utf8mb4_general_ci DEFAULT NULL, + PRIMARY KEY (`cards_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Daten-Export vom Benutzer nicht ausgewählt + +-- Exportiere Struktur von Tabelle pokevalv2.currency +CREATE TABLE IF NOT EXISTS `currency` ( + `currency_id` int NOT NULL AUTO_INCREMENT, + `currency_name` varchar(250) COLLATE utf8mb4_general_ci DEFAULT NULL, + `currency_symbol` varchar(2) COLLATE utf8mb4_general_ci DEFAULT NULL, + PRIMARY KEY (`currency_id`), + UNIQUE KEY `currency_name` (`currency_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Daten-Export vom Benutzer nicht ausgewählt + +-- Exportiere Struktur von Tabelle pokevalv2.platforms +CREATE TABLE IF NOT EXISTS `platforms` ( + `platforms_id` int NOT NULL AUTO_INCREMENT, + `platforms_name` varchar(250) COLLATE utf8mb4_general_ci DEFAULT NULL, + PRIMARY KEY (`platforms_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Daten-Export vom Benutzer nicht ausgewählt + +/*!40103 SET TIME_ZONE=IFNULL(@OLD_TIME_ZONE, 'system') */; +/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; +/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;