user module API & resource module API

GET /user/thread
POST /resource/version
GET /resource/search
GET /resource/info
GET /resource/hot
GET /resource/hot/slide
GET /resource/hot-trend
PUT /resource/info

Change-Id: I39c94b06a1d69967b8e235a67a0133c8095abb38
diff --git a/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceHotSlideDTO.java b/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceHotSlideDTO.java
new file mode 100644
index 0000000..42ff689
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceHotSlideDTO.java
@@ -0,0 +1,38 @@
+package com.g9.g9backend.pojo.DTO;
+
+import com.g9.g9backend.pojo.Resource;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class GetResourceHotSlideDTO {
+
+    private List<ResourceSlideInfo> records;
+
+    public GetResourceHotSlideDTO(List<Resource> resourceList) {
+        List<ResourceSlideInfo> records = new ArrayList<>();
+        for (Resource resource : resourceList) {
+            ResourceSlideInfo resourceSlideInfo = new ResourceSlideInfo();
+            resourceSlideInfo.setResourceId(resource.getResourceId());
+            resourceSlideInfo.setResourceName(resource.getResourceName());
+            resourceSlideInfo.setResourcePicture(resource.getResourcePicture());
+            records.add(resourceSlideInfo);
+        }
+        this.records = records;
+    }
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class ResourceSlideInfo {
+        private int resourceId;
+
+        private String resourceName;
+
+        private String resourcePicture;
+    }
+}
diff --git a/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceHotTrendDTO.java b/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceHotTrendDTO.java
new file mode 100644
index 0000000..4ab590d
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceHotTrendDTO.java
@@ -0,0 +1,101 @@
+package com.g9.g9backend.pojo.DTO;
+
+import com.g9.g9backend.pojo.HotTrend;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.*;
+
+@Data
+public class GetResourceHotTrendDTO {
+
+    private List<HotRecord> records;
+
+    public GetResourceHotTrendDTO(List<HotTrend> hotTrendList) {
+        List<HotRecord> records = new ArrayList<>();
+
+        HotRecord resourcePackHotRecord = new HotRecord();
+        resourcePackHotRecord.setClassify("resourcePack");
+        List<HotInfo> resourceHotInfoList = new ArrayList<>();
+
+        HotRecord modHotRecord = new HotRecord();
+        modHotRecord.setClassify("mod");
+        List<HotInfo> modHotInfoList = new ArrayList<>();
+
+        HotRecord modPackHotRecord = new HotRecord();
+        modPackHotRecord.setClassify("modPack");
+        List<HotInfo> modPackHotInfoList = new ArrayList<>();
+
+        HotRecord mapHotRecord = new HotRecord();
+        mapHotRecord.setClassify("map");
+        List<HotInfo> mapHotInfoList = new ArrayList<>();
+
+        for (HotTrend hotTrend : hotTrendList) {
+            switch (hotTrend.getClassify()) {
+                case "resourcePack":
+                    HotInfo resourcePackHotInfo = new HotInfo();
+                    resourcePackHotInfo.setHot(hotTrend.getHot());
+                    resourcePackHotInfo.setTime(hotTrend.getTime());
+                    resourceHotInfoList.add(resourcePackHotInfo);
+                    break;
+                case "mod":
+                    HotInfo modHotInfo = new HotInfo();
+                    modHotInfo.setHot(hotTrend.getHot());
+                    modHotInfo.setTime(hotTrend.getTime());
+                    modHotInfoList.add(modHotInfo);
+                    break;
+                case "modPack":
+                    HotInfo modPackHotInfo = new HotInfo();
+                    modPackHotInfo.setHot(hotTrend.getHot());
+                    modPackHotInfo.setTime(hotTrend.getTime());
+                    modPackHotInfoList.add(modPackHotInfo);
+                    break;
+                case "map":
+                    HotInfo mapHotInfo = new HotInfo();
+                    mapHotInfo.setHot(hotTrend.getHot());
+                    mapHotInfo.setTime(hotTrend.getTime());
+                    mapHotInfoList.add(mapHotInfo);
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        // 按照 Time 从早到晚排序
+        resourceHotInfoList.sort(Comparator.comparing(HotInfo::getTime));
+        modHotInfoList.sort(Comparator.comparing(HotInfo::getTime));
+        modPackHotInfoList.sort(Comparator.comparing(HotInfo::getTime));
+        mapHotInfoList.sort(Comparator.comparing(HotInfo::getTime));
+
+        resourcePackHotRecord.setHotInfoList(resourceHotInfoList);
+        modHotRecord.setHotInfoList(modHotInfoList);
+        modPackHotRecord.setHotInfoList(modPackHotInfoList);
+        mapHotRecord.setHotInfoList(mapHotInfoList);
+
+        records.add(resourcePackHotRecord);
+        records.add(modHotRecord);
+        records.add(resourcePackHotRecord);
+        records.add(mapHotRecord);
+
+        this.records = records;
+    }
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class HotRecord {
+        private String classify;
+
+        private List<HotInfo> hotInfoList;
+    }
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class HotInfo {
+        private float hot;
+
+        private Date time;
+    }
+}
diff --git a/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceInfoDTO.java b/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceInfoDTO.java
index 770ceb8..fa8a5ea 100644
--- a/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceInfoDTO.java
+++ b/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceInfoDTO.java
@@ -1,14 +1,158 @@
 package com.g9.g9backend.pojo.DTO;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.g9.g9backend.pojo.*;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
 @Data
-@AllArgsConstructor
-@NoArgsConstructor
 public class GetResourceInfoDTO {
 
-    // todo:待完善
-    private int id;
+    private int resourceId;
+
+    private String resourceName;
+
+    private String resourcePicture;
+
+    private String resourceSummary;
+
+    private String resourceDetail;
+
+    private Date uploadTime;
+
+    private Date lastUpdateTime;
+
+    private int price;
+
+    private int downloads;
+
+    private int likes;
+
+    private int collections;
+
+    private int comments;
+
+    private String classify;
+
+    private float hot;
+
+    private String[] gameplayList;
+
+    private List<ResourceVersionInfo> resourceVersionList;
+
+    // isCollect在序列化成JSON 时,字段会被映射为collect,所以这里显式指定 JSON 序列化时的字段名
+    @JsonProperty("isCollect")
+    private boolean isCollect;
+
+    @JsonProperty("isLike")
+    private boolean isLike;
+
+    @JsonProperty("isPurchase")
+    private boolean isPurchase;
+
+    @JsonProperty("isUpload")
+    private boolean isUpload;
+
+    private int uploaderId;
+
+    public GetResourceInfoDTO(Resource resource, List<Gameplay> gameplayList, List<ResourceVersion> resourceVersionList, List<List<GameVersion>> gameVersionLists, List<List<TorrentRecord>> torrentRecordLists, boolean isCollect, boolean isLike, boolean isPurchase, boolean isUpload, int uploaderId) {
+        // 创建资源基本信息
+        this.resourceId = resource.getResourceId();
+        this.resourceName = resource.getResourceName();
+        this.resourcePicture = resource.getResourcePicture();
+        this.resourceSummary = resource.getResourceSummary();
+        this.resourceDetail = resource.getResourceDetail();
+        this.uploadTime = resource.getUploadTime();
+        this.lastUpdateTime = resource.getLastUpdateTime();
+        this.price = resource.getPrice();
+        this.downloads = resource.getDownloads();
+        this.likes = resource.getLikes();
+        this.collections = resource.getCollections();
+        this.comments = resource.getComments();
+        this.classify = resource.getClassify();
+        this.hot = (float) (0.25 * resource.getDownloads() + 0.25 * resource.getLikes() + 0.25 * resource.getCollections() + 0.25 * resource.getComments());
+        this.isCollect = isCollect;
+        this.isLike = isLike;
+        this.isPurchase = isPurchase;
+        this.isUpload = isUpload;
+        this.uploaderId = uploaderId;
+
+        // 创建玩法列表
+        String[] gameplays = new String[gameplayList.size()];
+        // 处理对应的 gameplay 列表
+        for (int i = 0; i < gameplayList.size(); i++) {
+            Gameplay gameplay = gameplayList.get(i);
+            gameplays[i] = gameplay.getGameplayName();
+        }
+        this.gameplayList = gameplays;
+
+        // 创建资源版本列表
+        List<ResourceVersionInfo> resourceVersions = new ArrayList<>();
+        for (int i = 0; i < resourceVersionList.size(); i++) {
+            ResourceVersionInfo resourceVersionInfo = new ResourceVersionInfo();
+            ResourceVersion resourceVersion = resourceVersionList.get(i);
+            List<GameVersion> gameVersions = gameVersionLists.get(i);
+            List<TorrentRecord> torrentRecords = torrentRecordLists.get(i);
+
+            resourceVersionInfo.setResourceVersionId(resourceVersion.getResourceVersionId());
+            resourceVersionInfo.setResourceVersionName(resourceVersion.getResourceVersionName());
+            String[] compatibleVersions = new String[gameVersions.size()];
+            for (int j = 0; j < gameVersions.size(); j++) {
+                GameVersion gameVersion = gameVersions.get(j);
+                compatibleVersions[j] = gameVersion.getGameVersionName();
+            }
+            resourceVersionInfo.setCompatibleVersions(compatibleVersions);
+            List<TorrentRecordInfo> torrentRecordInfos = new ArrayList<>();
+            for (TorrentRecord torrentRecord : torrentRecords) {
+                TorrentRecordInfo torrentRecordInfo = new TorrentRecordInfo();
+                torrentRecordInfo.setTorrentRecordId(torrentRecord.getTorrentRecordId());
+                torrentRecordInfo.setTorrentUrl(torrentRecord.getTorrentUrl());
+                torrentRecordInfo.setInfoHash(torrentRecord.getInfoHash());
+                torrentRecordInfo.setUploadTime(torrentRecord.getUploadTime());
+                torrentRecordInfo.setUploaderUserId(torrentRecord.getUploaderUserId());
+
+                torrentRecordInfos.add(torrentRecordInfo);
+            }
+            resourceVersionInfo.setTorrentList(torrentRecordInfos);
+            resourceVersionInfo.setSeeds(resourceVersion.getSeeds());
+
+            resourceVersions.add(resourceVersionInfo);
+        }
+        this.resourceVersionList = resourceVersions;
+    }
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class ResourceVersionInfo {
+        private int resourceVersionId;
+
+        private String resourceVersionName;
+
+        private String[] compatibleVersions;
+
+        private List<TorrentRecordInfo> torrentList;
+
+        private int seeds;
+    }
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class TorrentRecordInfo {
+        private int torrentRecordId;
+
+        private String torrentUrl;
+
+        private String infoHash;
+
+        private Date uploadTime;
+
+        private int uploaderUserId;
+    }
 }
diff --git a/src/main/java/com/g9/g9backend/pojo/DTO/GetResourcePageDTO.java b/src/main/java/com/g9/g9backend/pojo/DTO/GetResourcePageDTO.java
new file mode 100644
index 0000000..d85ed06
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/pojo/DTO/GetResourcePageDTO.java
@@ -0,0 +1,77 @@
+package com.g9.g9backend.pojo.DTO;
+
+import com.g9.g9backend.pojo.Gameplay;
+import com.g9.g9backend.pojo.Resource;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class GetResourcePageDTO {
+
+    private List<ResourceInfo> records = new ArrayList<>();
+
+    private long total;
+
+    private long pages;
+
+    private long current;
+
+    private long size;
+
+    public GetResourcePageDTO (List<Resource> resourceList, List<List<Gameplay>> gameplayLists,long total, long pages, long current, long size) {
+        List<ResourceInfo> recordList = new ArrayList<>();
+        // 遍历 resourceList 和 gameplayLists
+        for (int i = 0; i < resourceList.size(); i++) {
+            Resource resource = resourceList.get(i);
+            List<Gameplay> allGameplayList = gameplayLists.get(i); // 同步访问 gameplayLists 的对应元素
+
+            // 创建 ResourceInfo 对象
+            ResourceInfo resourceInfo = new ResourceInfo();
+            resourceInfo.setResourceId(resource.getResourceId());
+            resourceInfo.setResourceName(resource.getResourceName());
+            resourceInfo.setResourcePicture(resource.getResourcePicture());
+            resourceInfo.setResourceSummary(resource.getResourceSummary());
+            resourceInfo.setLastUpdateTime(resource.getLastUpdateTime());
+            // 加权求和得到热度
+            resourceInfo.setHot((float) (0.25 * resource.getDownloads() + 0.25 * resource.getLikes() + 0.25 * resource.getCollections() + 0.25 * resource.getComments()));
+            // 创建玩法列表
+            String[] gameplayList = new String[allGameplayList.size()];
+            // 处理对应的 gameplay 列表
+            for (int j = 0; j < allGameplayList.size(); j++) {
+                Gameplay gameplay = allGameplayList.get(j);
+                gameplayList[j] = gameplay.getGameplayName();
+            }
+            resourceInfo.setGameplayList(gameplayList);
+            recordList.add(resourceInfo);
+        }
+        this.records = recordList;
+        this.total = total;
+        this.pages = pages;
+        this.current = current;
+        this.size = size;
+    }
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class ResourceInfo {
+        private int resourceId;
+
+        private String resourceName;
+
+        private String resourcePicture;
+
+        private String resourceSummary;
+
+        private Date lastUpdateTime;
+
+        private float hot;
+
+        private String[] gameplayList;
+    }
+}
diff --git a/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceSearchDTO.java b/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceSearchDTO.java
deleted file mode 100644
index 2348a8f..0000000
--- a/src/main/java/com/g9/g9backend/pojo/DTO/GetResourceSearchDTO.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.g9.g9backend.pojo.DTO;
-
-import com.g9.g9backend.pojo.Resource;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class GetResourceSearchDTO {
-
-    // Todo: 待完善
-    private List<Resource> records;
-
-    private long total;
-
-    private long pages;
-
-    private long current;
-
-    private long size;
-
-}
diff --git a/src/main/java/com/g9/g9backend/pojo/DTO/GetUserThreadListDTO.java b/src/main/java/com/g9/g9backend/pojo/DTO/GetUserThreadListDTO.java
new file mode 100644
index 0000000..51cfdd9
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/pojo/DTO/GetUserThreadListDTO.java
@@ -0,0 +1,23 @@
+package com.g9.g9backend.pojo.DTO;
+
+import com.g9.g9backend.pojo.Thread;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+public class GetUserThreadListDTO {
+
+    private List<Thread> records;
+
+    private long total;
+
+    private long pages;
+
+    private long current;
+
+    private long size;
+
+}
diff --git a/src/main/java/com/g9/g9backend/pojo/DTO/PutResourceInfoDTO.java b/src/main/java/com/g9/g9backend/pojo/DTO/PutResourceInfoDTO.java
new file mode 100644
index 0000000..1a9be55
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/pojo/DTO/PutResourceInfoDTO.java
@@ -0,0 +1,25 @@
+package com.g9.g9backend.pojo.DTO;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PutResourceInfoDTO {
+
+    private int resourceId;
+
+    private String resourceName;
+
+    private String resourcePicture;
+
+    private String resourceSummary;
+
+    private String resourceDetail;
+
+    private int price;
+
+    private String[] gameplayList;
+}
diff --git a/src/main/java/com/g9/g9backend/pojo/Version.java b/src/main/java/com/g9/g9backend/pojo/GameVersion.java
similarity index 83%
rename from src/main/java/com/g9/g9backend/pojo/Version.java
rename to src/main/java/com/g9/g9backend/pojo/GameVersion.java
index 180d332..68e83ea 100644
--- a/src/main/java/com/g9/g9backend/pojo/Version.java
+++ b/src/main/java/com/g9/g9backend/pojo/GameVersion.java
@@ -11,10 +11,10 @@
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
-public class Version {
+public class GameVersion {
 
     @MppMultiId
-    private String versionName;
+    private String gameVersionName;
 
     @MppMultiId
     private int resourceVersionId;
diff --git a/src/main/java/com/g9/g9backend/pojo/HotTrend.java b/src/main/java/com/g9/g9backend/pojo/HotTrend.java
new file mode 100644
index 0000000..817b518
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/pojo/HotTrend.java
@@ -0,0 +1,29 @@
+package com.g9.g9backend.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * HotTrend 实体类,表示热度趋势的数据模型
+ *
+ * @author hcy
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class HotTrend {
+
+    @TableId(type = IdType.AUTO)
+    private int hotTrendId;
+
+    private float hot;
+
+    private Date time; // 若命名为currentTime会发生冲突
+
+    private String classify;
+}
diff --git a/src/main/java/com/g9/g9backend/pojo/Resource.java b/src/main/java/com/g9/g9backend/pojo/Resource.java
index a3b17f3..139ec88 100644
--- a/src/main/java/com/g9/g9backend/pojo/Resource.java
+++ b/src/main/java/com/g9/g9backend/pojo/Resource.java
@@ -31,7 +31,7 @@
 
     private Date lastUpdateTime;
 
-    private float price;
+    private int price;
 
     private int downloads;
 
@@ -41,7 +41,5 @@
 
     private int comments;
 
-    private int seeds;
-
     private String classify;
 }
\ No newline at end of file
diff --git a/src/main/java/com/g9/g9backend/pojo/ResourceVersion.java b/src/main/java/com/g9/g9backend/pojo/ResourceVersion.java
index 4395a5a..1d177ba 100644
--- a/src/main/java/com/g9/g9backend/pojo/ResourceVersion.java
+++ b/src/main/java/com/g9/g9backend/pojo/ResourceVersion.java
@@ -20,4 +20,6 @@
     private String resourceVersionName;
 
     private int resourceId;
+
+    private int seeds;
 }
\ No newline at end of file
diff --git a/src/main/java/com/g9/g9backend/pojo/Reward.java b/src/main/java/com/g9/g9backend/pojo/Reward.java
index 5812284..aea9c84 100644
--- a/src/main/java/com/g9/g9backend/pojo/Reward.java
+++ b/src/main/java/com/g9/g9backend/pojo/Reward.java
@@ -25,7 +25,7 @@
 
     private int userId;
 
-    private float price;
+    private int price;
 
     private String rewardDescription;
 
diff --git a/src/main/java/com/g9/g9backend/pojo/Thread.java b/src/main/java/com/g9/g9backend/pojo/Thread.java
index ddcea67..a69fb82 100644
--- a/src/main/java/com/g9/g9backend/pojo/Thread.java
+++ b/src/main/java/com/g9/g9backend/pojo/Thread.java
@@ -29,8 +29,6 @@
 
     private int likes;
 
-    private boolean isLike;
-
     private Date createAt;
 
     private int commentNumber;