diff --git a/packages/jsbattle-server/app/services/ApiGateway.service.js b/packages/jsbattle-server/app/services/ApiGateway.service.js index 6537604a..7a65fabf 100644 --- a/packages/jsbattle-server/app/services/ApiGateway.service.js +++ b/packages/jsbattle-server/app/services/ApiGateway.service.js @@ -73,6 +73,8 @@ class ApiGatewayService extends Service { "GET league/": "league.getLeagueSummary", "GET league/replay/:id": "battleStore.get", "GET league/submission": "league.getUserSubmission", + "GET league/ranktable": "league.getUserRankTable", + "GET league/scripts/:id": "league.getScript", "PATCH league/submission": "league.joinLeague", "DELETE league/submission": "league.leaveLeague", }, diff --git a/packages/jsbattle-server/app/services/League.service.js b/packages/jsbattle-server/app/services/League.service.js index e60ddfcf..4b7eab01 100644 --- a/packages/jsbattle-server/app/services/League.service.js +++ b/packages/jsbattle-server/app/services/League.service.js @@ -59,9 +59,11 @@ class LeagueService extends Service { seedLeague: this.seedLeague, getUserSubmission: this.getUserSubmission, getHistory: this.getHistory, + getScript: this.getScript, joinLeague: this.joinLeague, leaveLeague: this.leaveLeague, getLeagueSummary: this.getLeagueSummary, + getUserRankTable: this.getUserRankTable, updateRank: this.updateRank }, hooks: { @@ -108,6 +110,31 @@ class LeagueService extends Service { }); } + + async getScript(ctx) { + const userId = ctx.meta.user ? ctx.meta.user.id : null; + if(!userId) { + throw new ValidationError('Not Authorized!', 401); + } + + const scriptId = ctx.params.id + let response = await ctx.call('league.get', { + id: scriptId, + fields: [ + "id", + "ownerName", + "scriptName", + "code" + ] + }); + + return { + id: response.id, + scriptName: response.ownerName + '/' + response.scriptName, + code: response.code + }; + } + async getHistory(ctx) { let items = await ctx.call('battleStore.find', { sort: '-createdAt', @@ -349,7 +376,7 @@ class LeagueService extends Service { return this.getLeagueSummary(ctx); } - async getLeagueSummary(ctx) { + async getUserRankTable(ctx) { const userId = ctx.meta.user ? ctx.meta.user.id : null; if(!userId) { throw new ValidationError('Not Authorized!', 401); @@ -370,12 +397,24 @@ class LeagueService extends Service { "history" ]; - let submission = await this.getUserSubmission(ctx) + let submission = await this.getUserSubmission(ctx); submission = _.pick(submission, fields); return { submission, - ranktable: this.ranktable.slice(submission.id, 7), + ranktable: this.ranktable.slice(submission.id, 7) + } + } + + async getLeagueSummary(ctx) { + const userId = ctx.meta.user ? ctx.meta.user.id : null; + if(!userId) { + throw new ValidationError('Not Authorized!', 401); + } + + let result = await this.getUserRankTable(ctx); + return { + ...result, history: await ctx.call('league.getHistory', {}) } } diff --git a/packages/jsbattle-webpage/features/schema.feature b/packages/jsbattle-webpage/features/schema.feature index f75f9423..c17b3b86 100644 --- a/packages/jsbattle-webpage/features/schema.feature +++ b/packages/jsbattle-webpage/features/schema.feature @@ -13,3 +13,4 @@ Feature: UBD Schema | 1 | | 2 | | 3 | + | 4 | diff --git a/packages/jsbattle-webpage/src/actions/sandboxAction.js b/packages/jsbattle-webpage/src/actions/sandboxAction.js index e5d3d147..1cf36cd2 100644 --- a/packages/jsbattle-webpage/src/actions/sandboxAction.js +++ b/packages/jsbattle-webpage/src/actions/sandboxAction.js @@ -127,12 +127,24 @@ export const getSandboxOpponentList = (useRemoteService) => { if(!result.ok) { throw new Error(`Error ${result.status}: ${result.statusText} (url: ${result.url})`); } - userTankList = await result.json(); - userTankList = userTankList.map((script) => ({ + result = await result.json(); + userTankList = result.map((script) => ({ id: script.id, - label: "sandbox/" + script.scriptName, + label: script.scriptName, source: 'remote_user' })); + result = await fetch("/api/user/league/ranktable", {}); + if(!result.ok) { + throw new Error(`Error ${result.status}: ${result.statusText} (url: ${result.url})`); + } + result = await result.json(); + result = result.ranktable.map((item) => ({ + id: item.id, + label: `${item.rank}. ${item.ownerName}/${item.scriptName}`, + source: 'league' + })); + userTankList = userTankList.concat(result); + } catch(err) { console.log(err); return dispatch({ @@ -144,7 +156,7 @@ export const getSandboxOpponentList = (useRemoteService) => { userTankList = await aiRepoService.getScriptNameList(); userTankList = userTankList.map((script) => ({ id: script.id, - label: 'sandbox/' + script.scriptName, + label: script.scriptName, source: 'local_user' })); } @@ -154,7 +166,7 @@ export const getSandboxOpponentList = (useRemoteService) => { bundledTanks = bundledTanks.map((name) => ({ id: name, - label: "jsbattle/" + name, + label: name, source: "bundled" })); @@ -197,6 +209,23 @@ export const setSandboxOpponent = (source, id) => { }); } break; + case 'league': + try { + script = await fetch("/api/user/league/scripts/" + id); + if(!script.ok) { + throw new Error(`Error ${script.status}: ${script.statusText} (url: ${script.url})`); + } + script = await script.json(); + scriptName = script.scriptName; + scriptCode = script.code; + } catch(err) { + console.log(err); + return dispatch({ + type: SANDBOX_OPPONENT_LIST_FAILURE, + payload: err + }); + } + break; default: throw new Error(`Not supported source ${source}`); } diff --git a/packages/jsbattle-webpage/src/components/LeagueJoin.js b/packages/jsbattle-webpage/src/components/LeagueJoin.js index a6bc86c7..6e3efc86 100644 --- a/packages/jsbattle-webpage/src/components/LeagueJoin.js +++ b/packages/jsbattle-webpage/src/components/LeagueJoin.js @@ -16,8 +16,14 @@ export default class LeagueJoin extends React.Component { submissionId = props.tankList[0].id; } + let rejoin; + if(this.props.selected) { + rejoin = (submissionId == this.props.selected.scriptId); + } + this.state = { editMode: false, + rejoin, newSubmissionId: submissionId, }; } @@ -35,7 +41,12 @@ export default class LeagueJoin extends React.Component { } onSubmissionChange(event) { - this.setState({newSubmissionId: event.target.value}); + let rejoin = false; + if(this.props.selected) { + rejoin = (event.target.value == this.props.selected.scriptId); + } + + this.setState({newSubmissionId: event.target.value, rejoin}); } openEditor() { @@ -68,7 +79,7 @@ export default class LeagueJoin extends React.Component { let leaveButton; let tankSelect; if(this.props.tankList.length > 0) { - joinButton =
; + joinButton = ; tankSelect =