Skip to content
This repository has been archived by the owner on Feb 8, 2024. It is now read-only.

Commit

Permalink
Scoreboard animated and js gzipped
Browse files Browse the repository at this point in the history
  • Loading branch information
natsukagami committed May 26, 2017
1 parent 6f0ef41 commit 5ccabd6
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 42 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public/css/fonts/*
!public/css/fonts/NotoMono-Regular.ttf
public/js/bootstrap/*
public/js/jquery/*
public/js/*.gz

# Distributed files
data/files/*
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,6 @@ If any changes are made to `.jsx` files, a `yarn build-jsx` must be ran (on Linu
- [x] Judge result parsing.
- [x] Public file serving.
- [x] Web code editor.
- [ ] More lightweight JS file.
- [x] More lightweight JS file (now gzipped to under 512kB!).
- [x] Auto update.
- [x] Scoreboard.
41 changes: 27 additions & 14 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,36 @@ const clean = require('gulp-clean');

gulp.task('default', ['build']);

gulp.task('render-jsx', ['render-jsx-index']);
gulp.task('render-jsx', ['render-jsx-index', 'render-jsx-scoreboard']);

gulp.task('render-jsx-index', () => {
function jsxRender(entry, filename) {
let b = browserify({
entries: 'jsx-src/index.jsx',
debug: true,
transform: [['babelify', {
presets: ['react', 'es2015']
}]]
entries: entry,
debug: false
})
.transform(envify, {global: true})
.transform('babelify', {
presets: ['es2015', 'react']
})
.transform(envify, { global: true })
.bundle()
.pipe(source('index.js'))
.pipe(source(filename))
.pipe(buffer());
if (process.env.NODE_ENV === 'production')
b = b.pipe(uglify());
return b.pipe(gulp.dest('public/js'));
return b.pipe(gulp.dest('public/js')).pipe(require('gulp-gzip')({ level: 9 })).pipe(gulp.dest('public/js'));
}

gulp.task('render-jsx-index', () => {
return jsxRender('jsx-src/index.jsx', 'index.js');
});

gulp.task('watch', () => {
gulp.task('render-jsx-scoreboard', () => {
return jsxRender('jsx-src/scoreboard.jsx', 'scoreboard.js');
});

function jsxWatch(entry, filename) {
let a = browserify({
entries: 'jsx-src/index.jsx',
entries: entry,
debug: true,
cache: {},
packageCache: {},
Expand All @@ -46,15 +54,20 @@ gulp.task('watch', () => {
a.transform(envify, {global: true});
a.on('update', () => {
a.bundle()
.pipe(source('index.js'))
.pipe(source(filename))
.pipe(buffer())
.pipe(gulp.dest('public/js'));
});
a.bundle()
.pipe(source('index.js'))
.pipe(source(filename))
.pipe(buffer())
.pipe(gulp.dest('public/js'));
a.on('log', debug);
}

gulp.task('watch', () => {
jsxWatch('jsx-src/index.jsx', 'index.js');
jsxWatch('jsx-src/scoreboard.jsx', 'scoreboard.js');
});

gulp.task('build', ['pre-build', 'build-copy-files', 'version-info', 'yarn-build', 'clean-yarn-files', 'zip', 'post-build']);
Expand Down
8 changes: 8 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ if (app.get('env') === 'development') {
}

// Public static directory
app.use(/\/public\/js\/(index|scoreboard)\.js$/, (req, res, next) => {
if (app.get('env') !== 'development') {
// Use the gzipped versions
req.url = req.url + '.gz';
res.set('Content-Encoding', 'gzip');
next();
} else next();
});
app.use('/public', express.static(path.join(__dirname, 'public')));

// Declare global constants
Expand Down
80 changes: 80 additions & 0 deletions jsx-src/scoreboard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from 'react';
import reactDom from 'react-dom';
import { Table, Button, Glyphicon } from 'react-bootstrap';
import FlipMove from 'react-flip-move';
const axios = require('axios');

/**
* Class Main provides an entrance to the scoreboard.
*/
class Main extends React.Component {
constructor() {
super();
/**
* Stores the current scoreboard.
* @property state
* @type {Array<User>}
*/
this.state = { problems: [], contestants: [], lastUpdated: new Date(0) };
this.fetch();
setInterval(() => this.fetch(), 15000); // F5 every 15 seconds
}
/**
* Fetches new list from the server.
*/
fetch() {
return axios.post('/scoreboard')
.then(response => {
if (response.status !== 200) return;
this.setState(Object.assign({}, response.data, { lastUpdated: new Date() }));
})
.catch(() => { // Pass error
});
}
/**
* Handles manual refresh.
*/
onRefresh() {
this.fetch();
this.setState({ disableRefresh: true });
setTimeout(() => this.setState({ disableRefresh: false }), 1000); // Refresh again after 1 second please
}
render() {
const probs = this.state.problems;
const table = <Table bordered hover>
<thead>
<tr>
<th rowSpan={2}>#</th>
<th rowSpan={2}>Tên</th>
<th rowSpan={2}>Tổng</th>
<th colSpan={this.state.problems.length}>Điểm từng bài</th>
</tr>
<FlipMove typeName={'tr'}>
{this.state.problems.map(prob => <th key={prob}>{prob}</th>)}
</FlipMove>
</thead>
<FlipMove typeName={'tbody'}>
{this.state.contestants.map(u => {
return <tr key={u.name} className={(u.rank <= 3 ? 'success' : '')}>
<td>{u.rank}</td>
<td>{u.name}</td>
<td>{u.total}</td>
{probs.map(p => <td>{u[p] || 0}</td>)}
</tr>;
})}
</FlipMove>
</Table>;
return <div>
<div className='text-right'>Lần cập nhật cuối: {this.state.lastUpdated.toString()}</div>
<div className='text-center'>
<Button bsStyle='info' onClick={() => this.onRefresh()} disabled={this.state.disableRefresh}>
<Glyphicon glyph='refresh'/>Cập nhật
</Button>
</div>
<hr/>
{table}
</div>;
}
}

reactDom.render(<Main />, document.getElementById('root'));
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"postinstall": "cross-env DEBUG=gulp* gulp copy-deps --gulpfile gulp_copydeps.js",
"test": "mocha --recursive tests/",
"start": "cross-env DEBUG=themis:* node index.js",
"prod": "cross-env NODE_ENV=production DEBUG=themis:* node index.js",
"build-jsx": "cross-env NODE_ENV=production DEBUG=gulp* gulp render-jsx",
"build": "cross-env NODE_ENV=production DEBUG=gulp* gulp build",
"watch": "cross-env DEBUG=gulp gulp watch"
Expand Down Expand Up @@ -55,6 +56,7 @@
"xml2js": "^0.4.17"
},
"devDependencies": {
"aliasify": "^2.1.0",
"babel": "^6.5.2",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
Expand All @@ -69,6 +71,7 @@
"eslint-plugin-react": "^6.10.0",
"gulp-clean": "^0.3.2",
"gulp-debug": "^3.0.0",
"gulp-gzip": "^1.4.0",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^2.0.0",
"gulp-yarn": "^0.0.5",
Expand Down
16 changes: 16 additions & 0 deletions public/js/scoreboard.js

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion routes/scoreboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ router.get('/', (req, res) => {
});

router.post('/', (req, res) => {
return res.json(res.locals.scoreboard);
return res.json({
problems: res.locals.problems,
contestants: res.locals.scoreboard
});
});

module.exports = router;
51 changes: 27 additions & 24 deletions views/scoreboard.pug
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
extends ./layout

mixin row(rank)
if rank <= 3
td: b
block
else
td
block
//- mixin row(rank)
//- if rank <= 3
//- td: b
//- block
//- else
//- td
//- block
block content
h1.text-center Bảng xếp hạng
hr
table.table.table-hover.table-bordered
thead: tr
th #
th Tên
th Tổng
each prob in problems
th=prob
tbody
each u in scoreboard
tr
td=u.rank
+row(u.rank)
| #{u.name}
td=u.total
each prob in problems
td=u[prob] || 0
//- hr
#root
h2.text-center Loading...
script(src='public/js/scoreboard.js')
//- table.table.table-hover.table-bordered
//- thead: tr
//- th #
//- th Tên
//- th Tổng
//- each prob in problems
//- th=prob
//- tbody
//- each u in scoreboard
//- tr
//- td=u.rank
//- +row(u.rank)
//- | #{u.name}
//- td=u.total
//- each prob in problems
//- td=u[prob] || 0
47 changes: 45 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ acorn@^3.0.4, acorn@^3.1.0, acorn@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"

acorn@^5.0.0:
version "5.0.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"

ajv-keywords@^1.0.0:
version "1.5.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
Expand All @@ -59,6 +63,12 @@ ajv@^4.7.0:
co "^4.6.0"
json-stable-stringify "^1.0.1"

aliasify@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/aliasify/-/aliasify-2.1.0.tgz#7c30825b9450b9e6185ba27533eaf6e2067d4b42"
dependencies:
browserify-transform-tools "~1.7.0"

align-text@^0.1.1, align-text@^0.1.3:
version "0.1.4"
resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
Expand Down Expand Up @@ -911,6 +921,13 @@ browserify-sign@^4.0.0:
inherits "^2.0.1"
parse-asn1 "^5.0.0"

browserify-transform-tools@~1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/browserify-transform-tools/-/browserify-transform-tools-1.7.0.tgz#83e277221f63259bed2e7eb2a283a970a501f4c4"
dependencies:
falafel "^2.0.0"
through "^2.3.7"

browserify-zlib@~0.1.2:
version "0.1.4"
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d"
Expand Down Expand Up @@ -1064,6 +1081,10 @@ bytes@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339"

bytes@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-0.3.0.tgz#78e2e0e28c7f9c7b988ea8aee0db4d5fa9941935"

cached-path-relative@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7"
Expand Down Expand Up @@ -2159,6 +2180,15 @@ falafel@^1.0.1:
isarray "0.0.1"
object-keys "^1.0.6"

falafel@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c"
dependencies:
acorn "^5.0.0"
foreach "^2.0.5"
isarray "0.0.1"
object-keys "^1.0.6"

fancy-log@^1.1.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948"
Expand Down Expand Up @@ -2603,6 +2633,15 @@ gulp-debug@^3.0.0:
through2 "^2.0.0"
tildify "^1.1.2"

gulp-gzip@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/gulp-gzip/-/gulp-gzip-1.4.0.tgz#5ff8dff837cac2ebc2c89743dc0ac76e2be5e6c2"
dependencies:
bytes "^0.3.0"
gulp-util "^2.2.14"
stream-to-array "~1.0.0"
through2 "^0.4.1"

gulp-rename@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.2.tgz#3ad4428763f05e2764dec1c67d868db275687817"
Expand Down Expand Up @@ -4978,6 +5017,10 @@ stream-splicer@^2.0.0:
inherits "^2.0.1"
readable-stream "^2.0.2"

stream-to-array@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-1.0.0.tgz#94166bb29f3ea24f082d2f8cd3ebb2cc0d6eca2c"

string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
Expand Down Expand Up @@ -5128,7 +5171,7 @@ through2-filter@^2.0.0:
through2 "~2.0.0"
xtend "~4.0.0"

through2@^0.4.2:
through2@^0.4.1, through2@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b"
dependencies:
Expand Down Expand Up @@ -5156,7 +5199,7 @@ through2@^2.0.0, through2@^2.0.1, through2@~2.0.0:
readable-stream "^2.1.5"
xtend "~4.0.1"

"through@>=2.2.7 <3", through@^2.3.6, through@~2.3.4:
"through@>=2.2.7 <3", through@^2.3.6, through@^2.3.7, through@~2.3.4:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"

Expand Down

0 comments on commit 5ccabd6

Please sign in to comment.