diff --git a/awesomeProject/.idea/.gitignore b/awesomeProject/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/awesomeProject/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/awesomeProject/.idea/awesomeProject.iml b/awesomeProject/.idea/awesomeProject.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/awesomeProject/.idea/awesomeProject.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/awesomeProject/.idea/inspectionProfiles/Project_Default.xml b/awesomeProject/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..8d66637
--- /dev/null
+++ b/awesomeProject/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/awesomeProject/.idea/modules.xml b/awesomeProject/.idea/modules.xml
new file mode 100644
index 0000000..cc47053
--- /dev/null
+++ b/awesomeProject/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/awesomeProject/.idea/vcs.xml b/awesomeProject/.idea/vcs.xml
new file mode 100644
index 0000000..d843f34
--- /dev/null
+++ b/awesomeProject/.idea/vcs.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/awesomeProject/awesomeProject/.idea/.gitignore b/awesomeProject/awesomeProject/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/awesomeProject/awesomeProject/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/awesomeProject/awesomeProject/.idea/awesomeProject.iml b/awesomeProject/awesomeProject/.idea/awesomeProject.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/awesomeProject/awesomeProject/.idea/awesomeProject.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/awesomeProject/awesomeProject/.idea/modules.xml b/awesomeProject/awesomeProject/.idea/modules.xml
new file mode 100644
index 0000000..cc47053
--- /dev/null
+++ b/awesomeProject/awesomeProject/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/awesomeProject/awesomeProject/go.mod b/awesomeProject/awesomeProject/go.mod
new file mode 100644
index 0000000..71dc7b7
--- /dev/null
+++ b/awesomeProject/awesomeProject/go.mod
@@ -0,0 +1,7 @@
+module awesomeProject
+
+go 1.23.1
+
+require github.com/go-sql-driver/mysql v1.8.1
+
+require filippo.io/edwards25519 v1.1.0 // indirect
diff --git a/awesomeProject/awesomeProject/go.sum b/awesomeProject/awesomeProject/go.sum
new file mode 100644
index 0000000..19dbcec
--- /dev/null
+++ b/awesomeProject/awesomeProject/go.sum
@@ -0,0 +1,4 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
diff --git a/awesomeProject/awesomeProject/leves/uploaded_level_file.txt b/awesomeProject/awesomeProject/leves/uploaded_level_file.txt
new file mode 100644
index 0000000..8710910
--- /dev/null
+++ b/awesomeProject/awesomeProject/leves/uploaded_level_file.txt
@@ -0,0 +1,12 @@
+{
+ "level_name": "第一关",
+ "difficulty": "easy",
+ "enemies": [
+ {"type": "goblin", "count": 10},
+ {"type": "troll", "count": 2}
+ ],
+ "boss": {
+ "type": "dragon",
+ "health": 5000
+ }
+}
diff --git a/awesomeProject/awesomeProject/leves/xxxxsss b/awesomeProject/awesomeProject/leves/xxxxsss
new file mode 100644
index 0000000..8710910
--- /dev/null
+++ b/awesomeProject/awesomeProject/leves/xxxxsss
@@ -0,0 +1,12 @@
+{
+ "level_name": "第一关",
+ "difficulty": "easy",
+ "enemies": [
+ {"type": "goblin", "count": 10},
+ {"type": "troll", "count": 2}
+ ],
+ "boss": {
+ "type": "dragon",
+ "health": 5000
+ }
+}
diff --git a/awesomeProject/awesomeProject/main.go b/awesomeProject/awesomeProject/main.go
new file mode 100644
index 0000000..13f4c26
--- /dev/null
+++ b/awesomeProject/awesomeProject/main.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+ "database/sql"
+ _ "github.com/go-sql-driver/mysql"
+)
+
+var db *sql.DB
+
+func main() {
+ openFileDate()
+ initweb()
+}
+
+//var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
+
+//func randStr(n int) string {
+// b := make([]rune, n)
+// for i := range b {
+// b[i] = letters[rand.Intn(len(letters))]
+// }
+// return string(b)
+//
+//}
diff --git a/awesomeProject/awesomeProject/playerInfo.json b/awesomeProject/awesomeProject/playerInfo.json
new file mode 100644
index 0000000..591c8d0
--- /dev/null
+++ b/awesomeProject/awesomeProject/playerInfo.json
@@ -0,0 +1,5 @@
+{
+ "InviteGiftOpen": [false, false, false, false, false, false],
+ "RushGiftOpen": [false, false, false, false, false, false, false,false,false],
+ "OnlineGiftOpen": [false, false, false, false, false, false]
+}
\ No newline at end of file
diff --git a/awesomeProject/awesomeProject/register.go b/awesomeProject/awesomeProject/register.go
new file mode 100644
index 0000000..06ab7d0
--- /dev/null
+++ b/awesomeProject/awesomeProject/register.go
@@ -0,0 +1 @@
+package main
diff --git a/awesomeProject/awesomeProject/web.go b/awesomeProject/awesomeProject/web.go
new file mode 100644
index 0000000..adb4377
--- /dev/null
+++ b/awesomeProject/awesomeProject/web.go
@@ -0,0 +1,1039 @@
+package main
+
+import (
+ "database/sql"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "net/http"
+ "os"
+ "time"
+)
+
+func initweb() {
+ var err error
+ db, err = sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test")
+ if err != nil {
+ log.Fatal("数据库连接失败: ", err)
+ }
+ defer db.Close()
+
+ err = db.Ping()
+ if err != nil {
+ log.Fatal("数据库连接不可用: ", err)
+ }
+ log.Println("数据库连接")
+ mux := http.NewServeMux()
+ //mux.HandleFunc("/login", login)
+ mux.HandleFunc("/register", register)
+ mux.HandleFunc("/get_user_Scends", get_user_Scends)
+ mux.HandleFunc("/change_player_data", change_player_data)
+ mux.HandleFunc("/getAllLevelNamesHandler", getAllLevelNamesHandler)
+ mux.HandleFunc("/uploadScore", uploadScore)
+ mux.HandleFunc("/fh", fh)
+ mux.HandleFunc("/get_allrank_Scends", get_allrank_Scends)
+ mux.HandleFunc("/uploadGoldRealRecord", uploadGoldRealRecord)
+ mux.HandleFunc("/uploadLevData", uploadLevData)
+ mux.HandleFunc("/getAnnouncement", getAnnouncement)
+ mux.HandleFunc("/getGoldRealRecord", getGoldRealRecord)
+ mux.HandleFunc("/getLevDataById", getLevDataById)
+
+ mux.HandleFunc("/get_allLev_name", get_allLev_name)
+ log.Println("服务器启动,监听端口: 8080")
+ err = http.ListenAndServe(":8080", mux)
+ if err != nil {
+ log.Fatal("ListenAndServe: ", err)
+ }
+}
+
+// 关卡物体数据
+type LevelItem struct {
+ Id string `json:"id"`
+ X float32 `json:"post_x"`
+ Y float32 `json:"post_y"`
+}
+
+// 关卡数据
+type Level struct {
+ Id int `json:"id"`
+ LevelList []LevelItem `json:"LevelList"`
+ Name string `json:"name"`
+}
+
+// 关卡名字全部数据
+type LevelList struct {
+ Name []string
+}
+
+// 玩家数据
+type User struct {
+ Id int `json:"id"`
+ OpenId string `json:"openId"`
+ Username string `json:"username"`
+ Gold int `json:"gold"`
+ RandCode string `json:"randCode"`
+ WeekScore int `json:"weekScore"`
+ CustomLev int `json:"customLev"`
+ Invite int `json:"invite"`
+ InviteGiftOpen []bool `json:"inviteGiftOpen"`
+ RushGiftOpen []bool `json:"rushGiftOpen"`
+ OnlineGiftOpen []bool `json:"onlineGiftOpen"`
+ EveryLevRush []int `json:"everyLevRush"`
+ WeekGoldReal int `json:"weekGoldReal"`
+ PicUrl string `json:"picUrl"`
+}
+
+var person Person
+
+// 本地json文件
+type Person struct {
+ InviteGiftOpen []bool `json:"InviteGiftOpen"`
+ RushGiftOpen []bool `json:"RushGiftOpen"`
+ OnlineGiftOpen []bool `json:"OnlineGiftOpen"`
+}
+
+// 打开json文件函数
+func openFileDate() {
+ // 打开 JSON 文件
+ jsonFile, err := os.Open("playerInfo.json")
+ if err != nil {
+ log.Fatalf("无法打开文件: %v", err)
+ }
+ defer jsonFile.Close()
+
+ // 读取文件的内容
+ byteValue, _ := ioutil.ReadAll(jsonFile)
+
+ // 解析 JSON 数据到结构体
+ err = json.Unmarshal(byteValue, &person)
+ if err != nil {
+ log.Fatalf("解析 JSON 数据失败: %v", err)
+ }
+}
+
+// 用户登录信息
+type LoginMsg struct {
+ OpenId string `json:"openId"`
+ Username string `json:"username"`
+ PicUrl string `json:"picUrl"`
+}
+
+// 用户列表
+type UserList struct {
+ UserList []User
+}
+
+// 添加用户到 users
+func (u *UserList) AddUser(user User) {
+ u.UserList = append(u.UserList, user)
+}
+
+// 老板定义的返回数据,有待研究
+type Result struct {
+ Msg string `json:"msg"`
+ MsgCode int `json:"msgCode"`
+ Data interface{} `json:"data,omitempty"`
+}
+
+// 初始化用户
+func initUser(loginMsg LoginMsg) (User, error) {
+
+ return User{
+ Id: 0,
+ OpenId: loginMsg.OpenId,
+ Username: loginMsg.Username,
+ PicUrl: loginMsg.PicUrl, // 初始化 PicUrl
+ Gold: 0,
+ RandCode: randStr(16),
+ WeekScore: 0,
+ CustomLev: 1,
+ Invite: 0,
+ InviteGiftOpen: person.InviteGiftOpen,
+ RushGiftOpen: person.RushGiftOpen,
+ OnlineGiftOpen: person.OnlineGiftOpen,
+ EveryLevRush: []int{},
+ WeekGoldReal: 100000,
+ }, nil
+}
+
+// 用户模板
+func fh(w http.ResponseWriter, r *http.Request) {
+ res := User{
+ Id: 0,
+ OpenId: "",
+ Username: "",
+ PicUrl: "", // 初始化 PicUrl
+ Gold: 0,
+ RandCode: randStr(16),
+ WeekScore: 0,
+ CustomLev: 0,
+ Invite: 0,
+ InviteGiftOpen: person.InviteGiftOpen,
+ RushGiftOpen: person.RushGiftOpen,
+ OnlineGiftOpen: person.OnlineGiftOpen,
+ EveryLevRush: []int{},
+ WeekGoldReal: 0,
+ }
+ json.NewEncoder(w).Encode(res)
+}
+
+// 随机字符串生成函数
+func randStr(length int) string {
+ const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
+ b := make([]byte, length)
+ for i := range b {
+ b[i] = charset[seededRand.Intn(len(charset))]
+ }
+ return string(b)
+}
+
+// 用户注册处理函数
+func register(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持POST请求", http.StatusBadRequest)
+ return
+ }
+
+ // 读取请求体
+ body, err := io.ReadAll(r.Body) // 使用 io.ReadAll 替代 ioutil.ReadAll
+ if err != nil {
+ log.Println("读取请求体失败:", err)
+ http.Error(w, "读取请求体失败", http.StatusBadRequest)
+ return
+ }
+
+ // 打印请求体内容
+ //log.Println("请求体:", string(body))
+
+ //解析请求体
+ var loginMsg LoginMsg
+ err = json.Unmarshal(body, &loginMsg)
+ if err != nil {
+ log.Println(r.Body)
+ log.Println("请求体解析失败:", err)
+ http.Error(w, "请求体解析失败", http.StatusBadRequest)
+ return
+ }
+
+ //判断数据库里面是否有这条数据,有就返回这条数据
+ var user User
+ var inviteGiftOpen, rushGiftOpen, onlineGiftOpen []byte
+ var everyLevRushJSON []byte
+ err = db.QueryRow("SELECT id, openId, username, gold, randCode, weekScore, customLev, invite, inviteGiftOpen, rushGiftOpen, onlineGiftOpen, everyLevRush, weekGoldReal FROM user WHERE openId = ?", loginMsg.OpenId).
+ Scan(&user.Id, &user.OpenId, &user.Username, &user.Gold, &user.RandCode, &user.WeekScore, &user.CustomLev, &user.Invite, &inviteGiftOpen, &rushGiftOpen, &onlineGiftOpen, &everyLevRushJSON, &user.WeekGoldReal)
+ if err == sql.ErrNoRows {
+ user, _ := initUser(loginMsg)
+ //数据库没有这个条消息,在数据库里面插入一条默认消息
+ // 将复杂类型(如 []bool 和 map[int]int)序列化为 JSON 字符串
+ inviteGiftOpenStr, _ := json.Marshal(user.InviteGiftOpen)
+ rushGiftOpenStr, _ := json.Marshal(user.RushGiftOpen)
+ onlineGiftOpenStr, _ := json.Marshal(user.OnlineGiftOpen)
+ everyLevRushStr, _ := json.Marshal(user.EveryLevRush)
+ insertQuery := "INSERT INTO user (id,openId, username, gold, randCode, weekScore, customLev, invite, inviteGiftOpen, rushGiftOpen, onlineGiftOpen, everyLevRush, weekGoldReal, picUrl) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)"
+ //stmt, _ := db.Prepare(insertQuery)
+ db.Exec(insertQuery, user.Id, user.OpenId, user.Username, user.Gold, user.RandCode, user.WeekScore, user.CustomLev, user.Invite, inviteGiftOpenStr, rushGiftOpenStr, onlineGiftOpenStr, everyLevRushStr, user.WeekGoldReal, user.PicUrl)
+ json.NewEncoder(w).Encode(user)
+ //defer stmt.Close()
+ return
+ } else if err != nil {
+ return
+ } else {
+ // 处理数据库中的 JSON 字符串并解析成 Go 中的类型
+ json.Unmarshal(inviteGiftOpen, &user.InviteGiftOpen)
+ json.Unmarshal(rushGiftOpen, &user.RushGiftOpen)
+ json.Unmarshal(onlineGiftOpen, &user.OnlineGiftOpen)
+ json.Unmarshal(everyLevRushJSON, &user.EveryLevRush)
+ user.RandCode = randStr(16)
+ json.NewEncoder(w).Encode(user)
+ }
+}
+
+/********************************************************************玩家数据改变请求服务器*********************************************************************************/
+// 用户改变用户数据函数
+func change_player_data(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持POST请求", http.StatusBadRequest)
+ return
+ }
+
+ // 读取请求体
+ body, err := io.ReadAll(r.Body) // 使用 io.ReadAll 替代 ioutil.ReadAll
+ if err != nil {
+ log.Println("读取请求体失败:", err)
+ http.Error(w, "读取请求体失败", http.StatusBadRequest)
+ return
+ }
+
+ // 打印请求体内容
+ log.Println("请求体:", string(body))
+
+ //解析请求体
+ var user User
+ err = json.Unmarshal(body, &user)
+ if err != nil {
+ log.Println(r.Body)
+ log.Println("请求体解析失败:", err)
+ http.Error(w, "请求体解析失败", http.StatusBadRequest)
+ return
+ }
+
+ //var userExists bool
+ //err = db.QueryRow("SELECT EXISTS(SELECT 1 FROM user WHERE openId = ?)", user.OpenId).Scan(&userExists)
+
+ //数据库没有这个条消息,在数据库里面插入一条默认消息
+ // 将复杂类型(如 []bool 和 map[int]int)序列化为 JSON 字符串
+ inviteGiftOpenStr, _ := json.Marshal(user.InviteGiftOpen)
+ rushGiftOpenStr, _ := json.Marshal(user.RushGiftOpen)
+ onlineGiftOpenStr, _ := json.Marshal(user.OnlineGiftOpen)
+ everyLevRushStr, _ := json.Marshal(user.EveryLevRush)
+ insertQuery := "UPDATE user SET username=?, gold=?, customLev=?, invite=?, inviteGiftOpen=?, rushGiftOpen=?, onlineGiftOpen=?, everyLevRush=?,weekGoldReal=?, picUrl=? WHERE openId = ?"
+ exec, err := db.Exec(insertQuery, user.Username, user.Gold, user.CustomLev, user.Invite, inviteGiftOpenStr, rushGiftOpenStr, onlineGiftOpenStr, everyLevRushStr, user.WeekGoldReal, user.PicUrl, user.OpenId)
+ if err != nil {
+ fmt.Println(err, exec)
+ return
+ }
+ json.NewEncoder(w).Encode(user)
+ return
+
+}
+
+/***************************************************************************关卡排行榜数据获取****************************************************************************/
+
+type liveMsg struct {
+ Id int `json:"id"`
+ OpenId string `json:"openId"`
+}
+
+// 获取所有关卡名字
+func getAllLevelNamesHandler(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
+ return
+ }
+
+ // 查询数据库获取所有关卡名称
+ rows, err := db.Query("SELECT name FROM level")
+ if err != nil {
+ log.Println(err)
+ res := map[string]string{"message": "数据库查询失败", "status": "failure"}
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(res)
+ return
+ }
+ defer rows.Close()
+
+ // 存储关卡名称的切片
+ var levelNames []string
+ for rows.Next() {
+ var name string
+ if err := rows.Scan(&name); err != nil {
+ log.Println(err)
+ res := map[string]string{"message": "数据读取失败", "status": "failure"}
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(res)
+ return
+ }
+ levelNames = append(levelNames, name)
+ }
+
+ // 检查是否有错误
+ if err := rows.Err(); err != nil {
+ log.Println(err)
+ res := map[string]string{"message": "结果集读取失败", "status": "failure"}
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(res)
+ return
+ }
+
+ // 直接返回关卡名称数组
+ json.NewEncoder(w).Encode(levelNames)
+}
+
+// 获取关卡分数排行榜名次
+func get_user_Scends(w http.ResponseWriter, r *http.Request) {
+ //SELECT id,name FROM levdata WHERE id = 2
+ log.Println("=====")
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
+ return
+ }
+
+ // 创建一个 RequestData 实例,用于存储解析后的数据
+ var requestData liveMsg
+
+ // 解析 JSON 数据
+ err := json.NewDecoder(r.Body).Decode(&requestData)
+ if err != nil {
+ http.Error(w, "解析 JSON 数据失败", http.StatusBadRequest)
+ return
+ }
+ levename := ""
+ id := 0
+ err = db.QueryRow("SELECT id,name FROM levdata WHERE id = ?", requestData.Id).Scan(&id, &levename)
+ log.Println(err)
+ rows, err := db.Query("SELECT * FROM " + levename + " ORDER BY score DESC LIMIT 3;")
+ if err != nil {
+ log.Println(err)
+ return
+ }
+
+ var userlist UserList
+ for rows.Next() {
+ var user User
+ var unusedField1, unusedField2 interface{}
+ err := rows.Scan(&unusedField1, &user.OpenId, &user.WeekScore, &unusedField2)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ userlist.AddUser(user)
+ }
+ log.Println(userlist)
+ json.NewEncoder(w).Encode(userlist)
+}
+
+/*********************************************************************上传分数********************************************************************************************/
+
+// LevRankMsg 请求排行榜数据结构
+type ScoreUploadMsg struct {
+ OpenId string `json:"openId"`
+ Name string `json:"name"` // LevelName 是字符串
+ Score int `json:"score"`
+}
+
+type BackRankInt struct {
+ RankInt int `json:"rankInt"`
+}
+
+// 确保 levdata 表中存在关卡记录
+func ensureLevelDataExists(levelName string) error {
+ var count int
+ // 查询 levdata 表中是否已经存在对应的关卡名称
+ err := db.QueryRow("SELECT COUNT(*) FROM levdata WHERE name = ?", levelName).Scan(&count)
+ if err != nil {
+ return err
+ }
+
+ // 如果不存在该关卡名称,则插入新的记录
+ if count == 0 {
+ insertLevelDataQuery := "INSERT INTO levdata (name) VALUES (?)"
+ _, err = db.Exec(insertLevelDataQuery, levelName)
+ if err != nil {
+ return err
+ }
+ log.Printf("新关卡已插入到 levdata 表: %s", levelName)
+ }
+ return nil
+}
+
+// 上传分数到关卡并创建的处理函数
+func uploadScore(w http.ResponseWriter, r *http.Request) {
+ log.Println("=====")
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
+ return
+ }
+
+ // 解析请求体中的 JSON 数据
+ var scoreUploadMsg ScoreUploadMsg
+ err := json.NewDecoder(r.Body).Decode(&scoreUploadMsg)
+ if err != nil {
+ log.Println("解析 JSON 数据失败:", err)
+ http.Error(w, "请求体解析失败", http.StatusBadRequest)
+ return
+ }
+
+ // 检查是否提供了 OpenId 和 LevelName
+ if scoreUploadMsg.OpenId == "" || scoreUploadMsg.Name == "" {
+ http.Error(w, "OpenId 和 LevelName 不能为空", http.StatusBadRequest)
+ return
+ }
+
+ // 确保 levdata 表中有该关卡名称
+ err = ensureLevelDataExists(scoreUploadMsg.Name)
+ if err != nil {
+ log.Println("检查或插入关卡失败:", err)
+ http.Error(w, "检查或插入关卡失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 使用 LevelName 作为表名
+ levelTable := scoreUploadMsg.Name
+
+ // 动态创建关卡表的 SQL 语句,移除 openid 作为主键,使用 id 作为自增主键
+ createTableQuery := fmt.Sprintf(`
+ CREATE TABLE IF NOT EXISTS %s (
+ id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ openId VARCHAR(255) NOT NULL,
+ score INT NOT NULL,
+ createtime TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ )`, levelTable)
+
+ // 执行创建表的 SQL 语句
+ _, err = db.Exec(createTableQuery)
+ if err != nil {
+ log.Println("关卡表创建失败:", err)
+ http.Error(w, "关卡表创建失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 插入新分数的 SQL 语句,每次插入新记录
+ insertScoreQuery := fmt.Sprintf(`
+ INSERT INTO %s (openId, score)
+ VALUES (?, ?)
+ `, levelTable)
+
+ // 执行插入操作
+ _, err = db.Exec(insertScoreQuery, scoreUploadMsg.OpenId, scoreUploadMsg.Score)
+ if err != nil {
+ log.Println("插入分数失败:", err)
+ http.Error(w, "插入分数失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 2. 查询表2中玩家在该关卡的最高分
+ // 获取当前时间
+ now := time.Now()
+ // 加载中国时区 (CST, UTC+8)
+ location, err := time.LoadLocation("Asia/Shanghai")
+ if err != nil {
+ fmt.Println("加载时区失败:", err)
+ return
+ }
+ // 将当前时间转换为中国时区时间
+ localTime := now.In(location)
+ // 转换为 UTC 时间
+ utcTime := localTime.UTC()
+
+ // 打印转换后的本地时间
+ fmt.Println("当前时间 (中国标准时间 CST):", localTime)
+
+ var currentHighScore sql.NullInt64
+ query := `
+ SELECT score
+ FROM weekopenidlev
+ WHERE openId = ? AND levelName = ? AND YEARWEEK(createtime, 1) = YEARWEEK(?, 1)`
+ err = db.QueryRow(query, scoreUploadMsg.OpenId, levelTable, utcTime).Scan(¤tHighScore)
+ if err != nil && err != sql.ErrNoRows {
+ log.Println("查询表2中的当前最高分失败:", err)
+ http.Error(w, "查询表2中的当前最高分失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 判断表2中是否为空,或者新分数大于表2中的最高分
+ if !currentHighScore.Valid || scoreUploadMsg.Score > int(currentHighScore.Int64) {
+ // 如果表2为空或者新分数大于当前最高分,则更新表2
+ updateWeeklyHighScoreQuery := `
+ INSERT INTO weekopenidlev (openId, levelName, score, createtime)
+ VALUES (?, ?, ?, ?)
+ ON DUPLICATE KEY UPDATE score = GREATEST(score, ?)`
+ _, err = db.Exec(updateWeeklyHighScoreQuery, scoreUploadMsg.OpenId, levelTable, scoreUploadMsg.Score, utcTime, scoreUploadMsg.Score)
+ if err != nil {
+ log.Println("更新表2失败:", err)
+ http.Error(w, "更新表2失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 更新表3,如果表3中没有openId的记录,插入一条新记录,否则更新总分
+ updateWeeklyTotalQuery := `
+ INSERT INTO weekscore (openId, totalScore, createtime)
+ VALUES (?, (SELECT SUM(score) FROM weekopenidlev WHERE openId = ? AND YEARWEEK(createtime, 1) = YEARWEEK(?, 1)), ?)
+ ON DUPLICATE KEY UPDATE totalScore = (SELECT SUM(score) FROM weekopenidlev WHERE openId = ? AND YEARWEEK(createtime, 1) = YEARWEEK(?, 1))`
+ _, err = db.Exec(updateWeeklyTotalQuery, scoreUploadMsg.OpenId, scoreUploadMsg.OpenId, utcTime, utcTime, scoreUploadMsg.OpenId, utcTime)
+ if err != nil {
+ log.Println("更新表3失败:", err)
+ http.Error(w, "更新表3失败", http.StatusInternalServerError)
+ return
+ }
+
+ log.Println("玩家的最高分和总分已更新")
+ } else {
+ log.Println("玩家的分数未超过当前最高分,无需更新")
+ }
+
+ // 查询玩家的排名
+ rankQuery := fmt.Sprintf(`
+ SELECT COUNT(*) + 1 AS `+"`rank`"+`
+ FROM %s
+ WHERE score > ?`, levelTable)
+
+ var backRankInt BackRankInt
+ err = db.QueryRow(rankQuery, scoreUploadMsg.Score).Scan(&backRankInt.RankInt)
+ if err != nil {
+ log.Println("查询排名失败:", err)
+ http.Error(w, "查询排名失败", http.StatusInternalServerError)
+ return
+ }
+ json.NewEncoder(w).Encode(backRankInt)
+}
+
+/************************************************************************************提现记录*******************************************************************************/
+type GoldRealMsg struct {
+ OpenId string `json:"openId"`
+ RealRecord map[string]string `json:"realRecord"`
+ Money int `json:"money"`
+ State int `json:"state"`
+}
+
+// 上传提现记录的处理函数
+func uploadGoldRealRecord(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
+ return
+ }
+
+ // 解析请求体的 JSON 数据
+ var goldRealMsg GoldRealMsg
+ err := json.NewDecoder(r.Body).Decode(&goldRealMsg)
+ if err != nil {
+ log.Println("请求体解析失败:", err)
+ http.Error(w, "请求体解析失败", http.StatusBadRequest)
+ return
+ }
+
+ // 将 RealRecord 转换为 JSON 格式字符串
+ realRecordJSON, err := json.Marshal(goldRealMsg.RealRecord)
+ if err != nil {
+ log.Println("RealRecord 转换为 JSON 失败:", err)
+ http.Error(w, "数据转换失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 插入或更新 GoldReal 表的 SQL 语句
+ insertOrUpdateQuery := `
+ INSERT INTO goldreal (openId, realRecord, money, state)
+ VALUES (?, ?, ?, ?)
+ ON DUPLICATE KEY UPDATE
+ realRecord = VALUES(realRecord),
+ money = VALUES(money),
+ state = VALUES(state)`
+
+ // 执行插入或更新操作
+ _, err = db.Exec(insertOrUpdateQuery, goldRealMsg.OpenId, string(realRecordJSON), goldRealMsg.Money, goldRealMsg.State)
+ if err != nil {
+ log.Println("插入或更新记录失败:", err)
+ http.Error(w, "插入或更新记录失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 返回成功消息
+ //response := map[string]string{"message": "提现记录上传成功"}
+ json.NewEncoder(w).Encode(nil)
+}
+
+// 获取提现记录
+func getGoldRealRecord(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
+ return
+ }
+
+ // 解析请求体的 JSON 数据
+ var goldRealMsg GoldRealMsg
+ err := json.NewDecoder(r.Body).Decode(&goldRealMsg)
+ if err != nil {
+ log.Println("请求体解析失败:", err)
+ http.Error(w, "请求体解析失败", http.StatusBadRequest)
+ return
+ }
+
+ // 查询数据库,state 必须为 0
+ query := "SELECT openId, realRecord, money, state FROM GoldReal WHERE openId = ? AND state = 0"
+ rows, err := db.Query(query, goldRealMsg.OpenId)
+ if err != nil {
+ log.Println("数据库查询失败:", err)
+ http.Error(w, "数据库查询失败", http.StatusInternalServerError)
+ return
+ }
+ defer rows.Close()
+
+ // 构建返回的记录列表
+ var records []GoldRealMsg
+ for rows.Next() {
+ var record GoldRealMsg
+ var realRecordStr string
+
+ err := rows.Scan(&record.OpenId, &realRecordStr, &record.Money, &record.State)
+ if err != nil {
+ log.Println("扫描数据库记录失败:", err)
+ http.Error(w, "数据扫描失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 将 realRecord 字符串反序列化为 map[string]string
+ err = json.Unmarshal([]byte(realRecordStr), &record.RealRecord)
+ if err != nil {
+ log.Println("反序列化 realRecord 失败:", err)
+ http.Error(w, "数据解析失败", http.StatusInternalServerError)
+ return
+ }
+
+ records = append(records, record)
+ }
+
+ // 如果没有找到记录,返回空数组
+ if len(records) == 0 {
+ records = []GoldRealMsg{}
+ }
+
+ // 返回查询到的记录
+ json.NewEncoder(w).Encode(records)
+}
+
+/********************************************************************上传关卡萌宠信息数据到数据库的处理函数***************************************************************************/
+type PetInfo struct {
+ Res string `json:"res"` // 萌宠预设体
+ Post_x float32 `json:"post_x"` // X 位置z
+ Post_y float32 `json:"post_y"` // Y 位置
+}
+
+// 关卡信息
+type LevData struct {
+ Id int `json:"id"` // 关卡 ID
+ Name string `json:"name"` // 关卡名称
+ PetInfoList []PetInfo `json:"petInfoList"` // 关卡中的萌宠信息
+}
+
+// 关卡信息
+type IsSuccess struct {
+ Msg string `json:"msg"`
+ Success bool `json:"success"`
+}
+
+// 上传关卡萌宠信息数据到数据库的处理函数
+func uploadLevData(w http.ResponseWriter, r *http.Request) {
+ // 确保只接受 POST 请求
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
+ return
+ }
+
+ // 解析请求体中的 JSON 数据
+ var levData LevData
+ err := json.NewDecoder(r.Body).Decode(&levData)
+ if err != nil {
+ log.Println("解析 JSON 数据失败:", err)
+ http.Error(w, "请求体解析失败", http.StatusBadRequest)
+ return
+ }
+
+ // 验证输入数据
+ if levData.Name == "" {
+ log.Println("关卡名称不能为空")
+ http.Error(w, "关卡名称不能为空", http.StatusBadRequest)
+ return
+ }
+
+ // 使用 id 来判断关卡号
+ levelNumber := levData.Id
+ if levelNumber <= 0 {
+ log.Println("关卡 ID 不合法")
+ http.Error(w, "关卡 ID 不合法", http.StatusBadRequest)
+ return
+ }
+
+ var isSuccess IsSuccess
+ // 判断前面所有关卡是否都已经创建
+ for i := 1; i < levelNumber; i++ {
+ checkLevelQuery := `SELECT COUNT(*) FROM levdata WHERE id = ?`
+ var count int
+ err = db.QueryRow(checkLevelQuery, i).Scan(&count)
+ if err != nil {
+ log.Println("查询关卡信息失败:", err)
+ http.Error(w, "查询关卡信息失败", http.StatusInternalServerError)
+ return
+ }
+
+ if count == 0 {
+ // 如果第 i 关不存在,返回错误信息
+ isSuccess.Msg = fmt.Sprintf("第%d关还没有创建", i)
+ isSuccess.Success = false
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(isSuccess)
+ return
+ }
+ }
+
+ // 将 PetInfoList 序列化为 JSON 格式字符串
+ petInfoListJSON, err := json.Marshal(levData.PetInfoList)
+ if err != nil {
+ log.Println("PetInfoList 转换为 JSON 失败:", err)
+ http.Error(w, "数据转换失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 检查数据库中是否已有相同的 id
+ checkIdQuery := `SELECT COUNT(*) FROM levdata WHERE id = ?`
+ var count int
+ err = db.QueryRow(checkIdQuery, levData.Id).Scan(&count)
+ if err != nil {
+ log.Println("查询关卡信息失败:", err)
+ http.Error(w, "查询关卡信息失败", http.StatusInternalServerError)
+ return
+ }
+
+ if count > 0 {
+ // 如果 id 存在,更新现有记录
+ updateLevDataQuery := `
+ UPDATE levdata SET name = ?, petInfoList = ? WHERE id = ?`
+ _, err = db.Exec(updateLevDataQuery, levData.Name, string(petInfoListJSON), levData.Id)
+ if err != nil {
+ log.Println("更新关卡信息失败:", err)
+ http.Error(w, "更新关卡信息失败", http.StatusInternalServerError)
+ return
+ }
+ // 如果第 i 关不存在,返回错误信息
+ isSuccess.Msg = fmt.Sprintf("%s更新萌宠信息成功", levData.Name)
+ isSuccess.Success = true
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(isSuccess)
+ log.Println("关卡信息更新成功")
+ } else {
+ // 如果 id 不存在,插入新的记录
+ insertLevDataQuery := `
+ INSERT INTO levdata (id, name, petInfoList)
+ VALUES (?, ?, ?)`
+ _, err = db.Exec(insertLevDataQuery, levData.Id, levData.Name, string(petInfoListJSON))
+ if err != nil {
+ log.Println("插入关卡信息失败:", err)
+ http.Error(w, "插入关卡信息失败", http.StatusInternalServerError)
+ return
+ }
+ log.Println("关卡信息插入成功")
+ }
+
+ // 返回成功消息
+ isSuccess.Msg = fmt.Sprintf("%s关卡上传成功", levData.Name)
+ isSuccess.Success = true
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(isSuccess)
+}
+
+// 根据关卡 id 获取关卡信息的处理函数
+func getLevDataById(w http.ResponseWriter, r *http.Request) {
+ // 确保只接受 POST 请求
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
+ return
+ }
+
+ // 解析请求体中的 JSON 数据
+ var loginMsg liveMsg
+ err := json.NewDecoder(r.Body).Decode(&loginMsg)
+ if err != nil {
+ log.Println("请求体解析失败:", err)
+ http.Error(w, "请求体解析失败", http.StatusBadRequest)
+ return
+ }
+
+ // 查询数据库,获取对应 id 的关卡信息
+ query := `SELECT id, name, petInfoList FROM levdata WHERE id = ?`
+ var levData LevData
+ var petInfoListJSON string
+
+ err = db.QueryRow(query, loginMsg.Id).Scan(&levData.Id, &levData.Name, &petInfoListJSON)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ log.Println("未找到关卡信息")
+ http.Error(w, "关卡信息未找到", http.StatusNotFound)
+ } else {
+ log.Println("查询关卡信息失败:", err)
+ http.Error(w, "查询关卡信息失败", http.StatusInternalServerError)
+ }
+ return
+ }
+
+ // 将 petInfoList 从 JSON 字符串反序列化为结构体
+ err = json.Unmarshal([]byte(petInfoListJSON), &levData.PetInfoList)
+ if err != nil {
+ log.Println("PetInfoList 反序列化失败:", err)
+ http.Error(w, "PetInfoList 数据解析失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 将关卡信息返回给客户端
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(levData)
+}
+
+//获取所有关卡id和关卡名字
+/*************************************************************************获取所有关卡的id和name*****************************************************************************************/
+
+// Level 结构体包含关卡的 ID 和 Name
+type LevelData struct {
+ LevID int `json:"levId"`
+ LevName string `json:"levName"`
+}
+
+// 数据响应格式,键为关卡的 ID,值为 Level 结构体
+type LevelResponse []LevelData
+
+// 从数据库获取关卡信息
+func getLevelsFromDB() (LevelResponse, error) {
+ // 查询关卡的 id 和 name
+ query := "SELECT id, name FROM levdata"
+ rows, err := db.Query(query)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ // 保存查询到的关卡信息
+ var levels LevelResponse
+
+ // 迭代查询结果
+ for rows.Next() {
+ var levelData LevelData
+ err := rows.Scan(&levelData.LevID, &levelData.LevName)
+ if err != nil {
+ return nil, err
+ }
+ // 将查询到的 LevelData 添加到切片中
+ levels = append(levels, levelData)
+ }
+
+ // 检查是否有查询错误
+ if err = rows.Err(); err != nil {
+ return nil, err
+ }
+
+ return levels, nil
+}
+
+// 处理客户端请求,返回 JSON 格式的关卡信息
+func get_allLev_name(w http.ResponseWriter, r *http.Request) {
+ levels, err := getLevelsFromDB()
+ if err != nil {
+ http.Error(w, "Error fetching levels from database", http.StatusInternalServerError)
+ return
+ }
+
+ // 设置响应头,告知客户端返回的数据是 JSON 格式
+ w.Header().Set("Content-Type", "application/json")
+
+ // 将 LevelResponse 序列化为 JSON 并写入响应
+ if err := json.NewEncoder(w).Encode(levels); err != nil {
+ http.Error(w, "Error encoding JSON", http.StatusInternalServerError)
+ return
+ }
+}
+
+/*************************************************************************公告信息**********************************************************************************************************/
+
+// Announcement 公告结构体
+type Announcement struct {
+ Title string `json:"title"`
+ Content string `json:"content"`
+ Date string `json:"date"`
+}
+
+// 获取公告的处理函数
+func getAnnouncement(w http.ResponseWriter, r *http.Request) {
+ // 解析公告信息
+ query := "SELECT title, content, date FROM announce ORDER BY date DESC LIMIT 1"
+ row := db.QueryRow(query)
+
+ // 解析公告信息
+ var announcement Announcement
+ err := row.Scan(&announcement.Title, &announcement.Content, &announcement.Date)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ http.Error(w, "没有找到公告", http.StatusNotFound)
+ log.Println("没有找到公告")
+ } else {
+ log.Println("查询公告失败:", err)
+ http.Error(w, "查询公告失败", http.StatusInternalServerError)
+ }
+ return
+ }
+
+ // 返回公告信息给客户端
+ w.Header().Set("Content-Type", "application/json")
+ err = json.NewEncoder(w).Encode(announcement)
+ if err != nil {
+ log.Println("返回公告信息失败:", err)
+ http.Error(w, "返回公告信息失败", http.StatusInternalServerError)
+ } else {
+ log.Println("公告成功返回给客户端")
+ }
+}
+
+/**************************************************************************邮件****************************************************************************************************************/
+// 邮件结构体
+type Mail struct {
+ OpenID string `json:"open_id"` // 用户的 openId
+ SendGold string `json:"send_gold"` // 奖励内容
+ SendAt string `json:"send_at"` // 发送时间
+ SendEnd string `json:"send_end"` // 结束时间
+ IsRead bool `json:"is_read"` // 是否已读
+}
+
+// 处理发送邮件请求
+func sendMailHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodPost {
+ http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
+ return
+ }
+
+ var mail Mail
+ // 解析客户端发来的 JSON 数据
+ err := json.NewDecoder(r.Body).Decode(&mail)
+ if err != nil {
+ http.Error(w, "无效的请求数据", http.StatusBadRequest)
+ return
+ }
+
+ // 获取当前时间,设置邮件的发送时间和过期时间(例如7天后)
+ mail.SendAt = time.Now().Format("2006-01-02 15:04:05")
+ mail.SendEnd = time.Now().AddDate(0, 0, 7).Format("2006-01-02 15:04:05")
+ mail.IsRead = false // 初始邮件未读
+
+ // 插入邮件到数据库
+ query := "INSERT INTO mails (openId, send_gold, send_at, send_end, is_read) VALUES (?, ?, ?, ?, false)"
+ _, err = db.Exec(query, mail.OpenID, mail.SendGold, mail.SendAt, mail.SendEnd)
+ if err != nil {
+ log.Printf("邮件发送失败: %v", err)
+ http.Error(w, "邮件发送失败", http.StatusInternalServerError)
+ return
+ }
+
+ // 返回给客户端发送成功的消息
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(map[string]string{"message": "邮件发送成功"})
+}
+
+/****************************************************************************总分数排行榜*************************************************************************************************/
+
+// 获取关卡分数排行榜名次
+func get_allrank_Scends(w http.ResponseWriter, r *http.Request) {
+
+ query := `SELECT openId, totalScore FROM weekscore ORDER BY totalScore DESC LIMIT 10`
+ rows, err := db.Query(query)
+ if err != nil {
+ http.Error(w, "查询排行榜数据失败", http.StatusInternalServerError)
+ log.Println("查询排行榜数据失败:", err)
+ return
+ }
+
+ var userlist UserList
+ for rows.Next() {
+ var user User
+ err := rows.Scan(&user.OpenId, &user.WeekScore)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ userlist.AddUser(user)
+ }
+ log.Println(userlist)
+ json.NewEncoder(w).Encode(userlist)
+}