Skip to content

Commit

Permalink
Merge branch 'develope'
Browse files Browse the repository at this point in the history
  • Loading branch information
totuworld committed Jan 4, 2017
2 parents d7a1c47 + a1c65c3 commit 136c912
Show file tree
Hide file tree
Showing 11 changed files with 294 additions and 6 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<img src="docs/Wanlaf.png" alt="logo" height="120" align="right" />

# Wendy
소규모 게임 개발팀을 위한 게임 서버

Expand All @@ -9,7 +11,7 @@ Wendy는 게임을 운영할 때 필요한 기능을 포함한 게임 서버입
이런 문제에서 소규모 게임 개발팀이 조금이나마 도움이 되길 원합니다.

### 커뮤니티
* 향후 트위터나 페이스북등의 공식채널을 제공합니다.
* twitter : [@magmakick](https://twitter.com/magmakick)
* 버그나 이슈는 [issue tracker](https://github.com/totuworld/Wendy/issues)에 등록해주세요.
* 새로운 기능이나 업데이트가 있으시다면 pull request 보내주세요. :)

Expand All @@ -26,6 +28,7 @@ yarn 패키지 매니저를 통해 설치를 진행합니다. yarn이 이미 설
$ npm install -g yarn
$ yarn install
```

### 실행방법
실행 방법은 아주 간단합니다.

Expand All @@ -41,8 +44,9 @@ Wendy가 지원할 필수 기능입니다.

- [x] 기기정보 관리
- [x] 사용자 정보 관리
- [ ] 재화 관리
- [x] 통화 관리
- [ ] 아이템 관리
- [ ] 지급 관리
- [ ] 인앱 영수증 검증

### 부가 기능
Expand Down
2 changes: 2 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const bodyParser = require('body-parser');
const routes = require('./routes/index');
const user = require('./routes/user');
const device = require('./routes/device');
const currency = require('./routes/currency');

let app = express();

Expand All @@ -26,6 +27,7 @@ app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/user', user);
app.use('/device', device);
app.use('/currency', currency);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
Expand Down
8 changes: 4 additions & 4 deletions config/config.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
{
"production":{
"host":"url",
"host":"wendy.database.windows.net",
"port": 1433,
"dialect": "mssql",
"username": "replace_username",
"password": "replace_password",
"dialectOptions":{
"encrypt": true,
"database":"db"
"database":"wendydb"
}
},
"development":{
"host":"url",
"host":"wendy.database.windows.net",
"port": 1433,
"dialect": "mssql",
"username": "replace_username",
"password": "replace_password",
"dialectOptions":{
"encrypt": true,
"database":"db"
"database":"wendydb"
}
}
}
Binary file added docs/Wanlaf.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 68 additions & 0 deletions logics/currency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict'

const later = require('later');

function GetOffSetTime(time, offsetTime) {
return new Date(time + (offsetTime*3600000)).getTime();
}


/**
* 재충전 가능한 통화의 충전 처리
* 최대치 충전 주기나 재충전 주기를 고려한다.
* @param OwnCurrencyData {Object}
* @param GameUser {Object}
* @param RechargeInfo {Object}
* @param NowDate {Date}
*/
exports.CheckForRecharge = (OwnCurrencyData, GameUser, RechargeInfo, NowDate)=>{

//재충전 가능한 통화인가?
if(OwnCurrencyData.RechargeCurrencyID === null
|| OwnCurrencyData.CurrentQNTY >= OwnCurrencyData.TotalQNTY) //혹은 최대치만큼 보유했는가?
return {code:false};

let nowTime = NowDate.getTime();
let oldTime = new Date(OwnCurrencyData.UpdateTimeStamp).getTime();
let oldOffTime = GetOffSetTime(oldTime, GameUser.OffsetTime);
let updateValue = {CurrentQNTY:null, UpdateTimeStamp:null};

//최대치 충전 주기가 있는가?
if(RechargeInfo.SetMaxSwitch === true) {
let convertLater = later.parse.cron(RechargeInfo.SetMaxPattern);
let prevTime = later.schedule(convertLater).prev();
let prevOffsetTime = GetOffSetTime(prevTime.getTime(), GameUser.OffsetTime );
//UpdateTimeStamp가 prevTime보다 뒤에있는가?
if(oldOffTime < prevOffsetTime) {
updateValue.CurrentQNTY = OwnCurrencyData.TotalQNTY;
updateValue.UpdateTimeStamp = NowDate;
return {code:true, update:updateValue}
}
}

//시간경과에 따른 업데이트 항목만 작동.
let spendTime = (nowTime - oldTime)/1000;
let rechargeAmount = Math.floor(spendTime / RechargeInfo.IntervalTime);

let totalAmount = OwnCurrencyData.CurrentQNTY + rechargeAmount;


//현재 보유할 수 있는 최대수량을넘어가는가?
if(totalAmount >= OwnCurrencyData.TotalQNTY) {
updateValue.CurrentQNTY = OwnCurrencyData.TotalQNTY;
updateValue.UpdateTimeStamp = NowDate;
return {code:true, update:updateValue}
}
//최대 수량에 미치지 못하나 충전할만한 량이 있을때
else if( rechargeAmount > 0) {
updateValue.CurrentQNTY = totalAmount;
updateValue.UpdateTimeStamp =
new Date(
oldTime +
(rechargeAmount * RechargeInfo.IntervalTime)*1000
);
return {code:true, update:updateValue}
}

return {code:false};
}
26 changes: 26 additions & 0 deletions models/DefineCurrency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

module.exports = function(sequelize, DataTypes) {
let DefineCurrency= sequelize.define('DefineCurrency', {
CurrencyID : { type : DataTypes.INTEGER, primaryKey: true }, //고유한 번호를 할당해야한다.
Name : { type:DataTypes.STRING(10) },
MaxQNTY : { type:DataTypes.INTEGER, defaultValue:9000 }
}, {
timestamps: false,
tableName: 'DefineCurrency',
classMethods: {
associate: function (models) {
//재충전되는 통화인 경우 해당 값을 가진다.
DefineCurrency.belongsTo(models.DefineRechargeCurrency, {
onDelete: "CASCADE",
foreignKey: {
name:'RechargeCurrencyID',
allowNull: true
},
as: 'RechargeInfo'
});
}
}
});
return DefineCurrency;
};
22 changes: 22 additions & 0 deletions models/DefineRechargeCurrency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict';

module.exports = function(sequelize, DataTypes) {
let DefineRechargeCurrency= sequelize.define('DefineRechargeCurrency', {
RechargeCurrencyID : { type : DataTypes.INTEGER, primaryKey: true},
IntervalTime : { type : DataTypes.INTEGER, defaultValue : 3600 },
IntervalChargeAmount : { type : DataTypes.INTEGER, defaultValue:1 },
SetMaxSwitch : { type : DataTypes.BOOLEAN, defaultValue:false },
SetMaxPattern : { //cron 표현식을 통해 최대치 충전 주기를설정한다.
type : DataTypes.STRING(32),
validate : { //반드시 올바른 형태의 입력인지 체크한다.
is: /^\s*($|#|\w+\s*=|(\?|\*|(?:[0-5]?\d)(?:(?:-|\/|\,)(?:[0-5]?\d))?(?:,(?:[0-5]?\d)(?:(?:-|\/|\,)(?:[0-5]?\d))?)*)\s+(\?|\*|(?:[0-5]?\d)(?:(?:-|\/|\,)(?:[0-5]?\d))?(?:,(?:[0-5]?\d)(?:(?:-|\/|\,)(?:[0-5]?\d))?)*)\s+(\?|\*|(?:[01]?\d|2[0-3])(?:(?:-|\/|\,)(?:[01]?\d|2[0-3]))?(?:,(?:[01]?\d|2[0-3])(?:(?:-|\/|\,)(?:[01]?\d|2[0-3]))?)*)\s+(\?|\*|(?:0?[1-9]|[12]\d|3[01])(?:(?:-|\/|\,)(?:0?[1-9]|[12]\d|3[01]))?(?:,(?:0?[1-9]|[12]\d|3[01])(?:(?:-|\/|\,)(?:0?[1-9]|[12]\d|3[01]))?)*)\s+(\?|\*|(?:[1-9]|1[012])(?:(?:-|\/|\,)(?:[1-9]|1[012]))?(?:L|W)?(?:,(?:[1-9]|1[012])(?:(?:-|\/|\,)(?:[1-9]|1[012]))?(?:L|W)?)*|\?|\*|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?(?:,(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?)*)\s+(\?|\*|(?:[0-6])(?:(?:-|\/|\,|#)(?:[0-6]))?(?:L)?(?:,(?:[0-6])(?:(?:-|\/|\,|#)(?:[0-6]))?(?:L)?)*|\?|\*|(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?(?:,(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?)*)(|\s)+(\?|\*|(?:|\d{4})(?:(?:-|\/|\,)(?:|\d{4}))?(?:,(?:|\d{4})(?:(?:-|\/|\,)(?:|\d{4}))?)*))$/
},
defaultValue : '0 0 12 * * ?' //기본값(매일 낮 12시)
}

}, {
timestamps: false,
tableName: 'DefineRechargeCurrency'
});
return DefineRechargeCurrency;
};
40 changes: 40 additions & 0 deletions models/OwnCurrency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict';

module.exports = function(sequelize, DataTypes) {
let OwnCurrency= sequelize.define('OwnCurrency', {
OwnCurrencyUID : { type : DataTypes.INTEGER, primaryKey: true, autoIncrement:true },
CurrencyID : { type : DataTypes.INTEGER },
CurrentQNTY : { type:DataTypes.INTEGER, defaultValue:0 }, //실제 현재보유수량
NowMaxQNTY : { type:DataTypes.INTEGER, defaultValue:100 }, //현재 최대보유수량
AddMaxQNTY : { type:DataTypes.INTEGER, defaultValue:0 }, //어떤 조건으로 추가되는 최대 보유수량
UpdateTimeStamp: { type:DataTypes.DATE, defaultValue:sequelize.NOW }
}, {
timestamps: false,
tableName: 'OwnCurrency',
classMethods: {
associate: function (models) {
//보유한 GameUserID 외래키 등록
OwnCurrency.belongsTo(models.GameUser, {
onDelete: "CASCADE",
foreignKey: {
name:'GameUserID',
allowNull: false
}
});
//보유한 CurrencyID 외래키 등록
OwnCurrency.belongsTo(models.DefineCurrency, {
onDelete: "CASCADE",
foreignKey: {
name:'CurrencyID',
allowNull: false
}
});
}
},
getterMethods: {
//전체 보유수량 = NowMaxQNTY + AddMaxQNTY
TotalQNTY : function() { return this.NowMaxQNTY + this.AddMaxQNTY }
}
});
return OwnCurrency;
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"debug": "^2.4.4",
"express": "^4.14.0",
"jsonwebtoken": "^7.2.1",
"later": "^1.2.0",
"morgan": "^1.7.0",
"pug": "^2.0.0-beta6",
"sequelize": "^3.27.0",
Expand Down
121 changes: 121 additions & 0 deletions routes/currency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
'use strict'

const debug = require('debug')('Wendy:router:currency');
const auth = require('../utils/auth');
const commonFunc = require('../utils/commonFunc');
const models = require("../models");
const wendyError = require('../utils/error');
const currencyLogic = require('../logics/currency');

const express = require('express');
const router = express.Router();


/**
* @api {GET} /currency/define 통화 목록 요청
* @apiName 정의된 통화 목록 요청
* @apiHeader {String} Authorization JWT토큰을 전송
*/
router.get('/define', auth.isAuthenticated, (req, res, next)=>{
models.DefineCurrency.findAll({
include: [{
model: models.DefineRechargeCurrency,
as: 'RechargeInfo'
}]
})
.then((defineCurrencyList)=>{
res.send({result:0, list:defineCurrencyList});
})
});

/**
* @api {GET} /currency/own 보유 통화 목록 요청
* @apiName 보유 통화 목록 요청
* @apiHeader {String} Authorization JWT토큰을 전송
*/
router.get('/own', auth.isAuthenticated, (req, res, next) => {

let saveGameUser;
let saveOwnCurrencyList;

//OwnCurrency 목록조회
models.OwnCurrency.findAll({
where: { GameUserID: req.user.GameUserID },
//재충전 계산이 필요할 수 있으니 DefineCurrency도 포함한다.
include: [{
model: models.DefineCurrency,
include: {
model: models.DefineRechargeCurrency,
as: 'RechargeInfo'
}
}
]
})
.then((ownCurrencyList) => {
saveOwnCurrencyList = ownCurrencyList;
//재충전 주기를 체크해야하는지 확인한다.
for (let row of saveOwnCurrencyList) {
if (row.DefineCurrency.RechargeCurrencyID !== null)
return Promise.resolve();
}
return Promise.reject('pass');
})
//재충전 주기 확인 시 사용될 GameUser를 찾는다.
.then(() => {
return models.GameUser.findOne({
where: { GameUserID: req.user.GameUserID }
})
})
.then((gameUser) => {
saveGameUser = gameUser;
return Promise.resolve();
})
//재충전 주기를 살필 통화가 있는지 확인한다.
.then(() => {
let nowDate = new Date();
let promises = [];
let tempResult;
for (let row of saveOwnCurrencyList) {
if (row.DefineCurrency.RechargeCurrencyID !== null) {
tempResult = currencyLogic.CheckForRecharge(
row,
saveGameUser,
row.DefineCurrency.RechargeInfo,
nowDate);

if (tempResult.code === true) {
promises.push(
models.OwnCurrency.update(
tempResult.update,
{ where: { OwnCurrencyUID: row.OwnCurrencyUID } })
);
}
}
}
if (promises.length > 0) return Promise.all(promises);
return Promise.resolve();
})
.catch((err) => {
if (err === 'pass') return Promise.resolve(saveOwnCurrencyList);
return Promise.reject(err);
})
//업데이트된 항목이 있을 수 있으니 OwnCurrency를 다시 로딩한다.
.then(() => {
//OwnCurrencyUID를 Array로 뽑아서 쿼리에 사용한다.
let OwnCurrencyUIDs = [];
for (let row of saveOwnCurrencyList) {
OwnCurrencyUIDs.push(row.OwnCurrencyUID);
}
return models.OwnCurrency.findAll({
where: { OwnCurrencyUID: { $in: OwnCurrencyUIDs } }
})
})
.then((ownCurrencyList)=>{
res.send({result:0, list:ownCurrencyList});
})
.catch((err)=>{
next(err);
})
});

module.exports = router;
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ kind-of@^3.0.2:
dependencies:
is-buffer "^1.0.2"

later@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/later/-/later-1.2.0.tgz#f2cf6c4dd7956dd2f520adf0329836e9876bad0f"

lazy-cache@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
Expand Down

0 comments on commit 136c912

Please sign in to comment.