Upload All

This commit is contained in:
Alan
2018-02-26 14:09:18 +08:00
parent 42d3a3fc46
commit 46257f08b0
1024 changed files with 204324 additions and 0 deletions

View File

@ -0,0 +1,169 @@
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const ServerStatus = require("../../ServerStatus");
const Theme = require("./Theme");
const NewTheme = require("./NewTheme");
/**
* 回呼函式。
* @callback CallbackFunction
* @param {Object} err 錯誤資訊物件。
* @param {Object} obj 傳回的物件。
*/
/**
* 「季」的模板定義。
* @prop {number} nth 表示目前的資料是第nth季
* @prop {Schema.Types.ObjectId[]} themes 這一季的所有主題。
* @prop {Date} startTime 這一季的開始時間。
* @prop {Date} endTime 這一季的結束時間。
*/
let SeasonSchema = Schema({
nth: Number,
themes: [{type : Schema.Types.ObjectId, ref : "Theme"}],
startTime: {type : Date, default : Date.now},
endTime: Date
});
/**
* 新一季的必要的基本資料。
* @typedef NewSeasonData
* @prop {number} nth 紀錄此資料為第nth季。
* @prop {ObjectId[]} themes 這一季所有的活動。以ObjectId做關聯。
* @prop {Date} startTime 開始這一季時的時間。
*/
/**
* 建立一個新的「季」資料。
* @param {Object} data 欲儲存的原始資料。
* @param {function} callback 回呼函式(Error, ObjectId)。
*/
SeasonSchema.statics.createNewSeason = function (data, callback) {
let newSeason = this({
nth: data.nth,
themes: data.themes,
startTime: data.startTime,
endTime: null
});
newSeason.save((err, season) => {
if (err) return callback(err, null);
callback(null, season._id);
});
}
/**
* 取得「傑作藝廊」頁面所需的資料。
* 注意: 要取用相關資料時必須先將Theme與ParticipantInfo資料表引入。
* @param {CallbackFunction} callback 回呼函式。含有錯誤訊息物件或資料物件。
*/
SeasonSchema.statics.GetGalleryNeedInfo = function (callback) {
// 取得一季之中所有的「主題 (themes)」與「季次 (nth)」
// 所有主題中的「編號 (order)」、「標題 (title)」與「參加作品 (participants)」
// 參加作品中的「排行 (rank)」、「作者 (artist)」、「作品敘述 (description)」與「投稿時間 (postTime)」
let curNthSeason = ServerStatus.status.currentSeason;
let populateQuery = {
path : "themes",
select : {"order": 1, "title": 1, "participants": 1},
populate : {
path : "participants",
select : {"rank": 1, "artist": 1, "description": 1, "postTime": 1}
}
};
// {"nth": {$lt: curNthSeason}} 中的 $lt: curNthSeason 表示不要選取到最新一季。
this.find({"nth": {$lt: curNthSeason}}).sort({nth: -1}).select("nth themes").populate(populateQuery).exec(callback);
}
/**
* 取得在「畫作主題」頁面下所需要的插值資料。
* @param {CallbackFunction} callback 回呼函式。含有錯誤訊息物件或資料物件。
*/
SeasonSchema.statics.GetThemePageNeedInfo = function (callback) {
let result = {currentSeason: null, lastSeason: null};
let currentSeasonPopulate = {path: "themes", select: {"order": 1, "title": 1, "narrative": 1, "imageURL": 1, "originator": 1, "participentCount": 1, "views": 1, "commentCount": 1}};
let lastSeasonPopulate = {path: "themes", select: {"order": 1, "title": 1, "originator": 1}};
let currentNthSeason = ServerStatus.status.currentSeason;
// 以nth尋找最新的一季在選擇其中的「nth」與「themes」欄位
// 並對「themes」展開選擇其中的指定欄位然後執行以上動作。
this.findOne({"nth": currentNthSeason})
.select("nth themes")
.populate(currentSeasonPopulate)
.exec((err, curSeason) => {
if (err) {
callback(err, null);
return;
}
result.currentSeason = curSeason;
// 接著尋找上一季指定「nth」、「endTime」與「themes」欄位
// 並對「themes」展開選擇其中的指定欄位然後執行以上動作。
this.findOne({"nth": currentNthSeason - 1})
.select("nth endTime themes")
.populate(lastSeasonPopulate)
.exec((err, lastSeason) => {
if (err) {
callback(err, null);
return;
}
result.lastSeason = lastSeason;
callback(null, result);
return;
});
});
}
/**
* 將畫作主題活動推進新的一季。
* 注意ServerStatus.status中的currentSeason必須要先推進到新的一季否則會相衝。
* @param {CallbackFunction} callback 回呼函式。
*/
SeasonSchema.statics.PushNewSeason = function (callback) {
let promotionCount = ServerStatus.status.promotionCount; // 取得要選取多少個候選主題至正規主題中
let curNthSeason = ServerStatus.status.currentSeason;
let Season = this;
// 首先先更新上一季的結束時間
Season.update({ nth: curNthSeason - 1 }, { $set: { "endTime": new Date() } }, (err, seasonDocs) => {
if(err) return callback(err, "\n更新前一季的時間時\n");
});
// 做統合取NewTheme中所有的欄位並建立一個 "voteCount" 欄位來記錄 votes 中有有多少個項目
// 然後再先後以投票數量(voteCount)與投稿時間(createdTime)來做排序並選取前N個(promotionCount)作為新一季的新主題。
NewTheme.aggregate(
[
{ "$project": {
title: 1,
narrative: 1,
image: 1,
sponsor: 1,
votes: 1,
createdTime: 1,
voteCount: { "$size": "$votes" }
}},
{ "$sort": { "voteCount": -1 } },
{ "$sort": { "createdTime": 1 } },
{ "$limit": promotionCount }
],
function (err, docsList) {
if (err) return callback(err, "\n取得指定候選主題時發生了錯誤。請確認是否有連接MongoDB並重新嘗試。\n");
// 將指定的候選主題轉換到正規的主題(Theme)中。其中處理完成後回呼_id清單。
Theme.TransferFromNewTheme(docsList, (err, _idList) => {
if (err) return callback(err, "\n將候選主題轉換至正規主題時發生了錯誤。請確認是否有連接MongoDB並重新嘗試。\n");
// 建立基本新的一季(Season)的資料
let data = {
nth: ServerStatus.status.currentSeason,
themes: _idList,
startTime: new Date()
};
// 利用data建立最新一季的資料
Season.createNewSeason(data, (err, _id) => {
if (err) return callback(err, "\n建立新一季的活動資料時發生了錯誤。請確認是否有連接MongoDB並重新嘗試。\n");
// 將所有的候選主題都清空
NewTheme.remove({}, (err) => {
if (err) return callback(err, "\n在清空NewTheme中所有資料時發生了錯誤。請改用手動的方式刪除或檢查是否有連接MongoDB。\n");
callback(null, true);
});
});
});
}
)
}
module.exports = mongoose.model("Season", SeasonSchema);