Skip to content

Commit

Permalink
Build website
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed Sep 16, 2024
0 parents commit a06cc33
Show file tree
Hide file tree
Showing 8 changed files with 2,123 additions and 0 deletions.
114 changes: 114 additions & 0 deletions .github/workflows/records.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import sys
import os
from datetime import date, datetime, timedelta

input_file = sys.argv[1]
output_file = sys.argv[2]
project_root = sys.argv[3]

dc = {}
if os.path.exists(input_file):
print('Found existing input file ' + input_file)
with open(input_file, 'r') as f:
for line in f.readlines():
line = line.strip()
if ':' not in line:
continue
k, v = line.split(':')
dc[k] = v
else:
print('Cannot find existing input file ' + input_file)

current_date = date(2024, 2, 25)
if 'current_date' in dc.keys():
dt = datetime.strptime(dc['current_date'], '%Y-%m-%d')
current_date = date(dt.year, dt.month, dt.day)
if current_date < date(2024, 3, 8):
print('Full re-calculate by intention')
current_date = date(2024, 2, 25)
dc = {}
latest_date = current_date

users = {}
for k, v in dc.items():
if k == 'current_date' or k == 'skipped_dates':
continue
users[k] = list(map(lambda s: list(map(int, s.split(','))), v.split('/')))

skipped_dates = []
if 'skipped_dates' in dc.keys():
y, m, d = 0, 0, 0
for s in dc['skipped_dates'].split(','):
if s[0] == 'y':
y = int(s[1:])
elif s[0] == 'm':
m = int(s[1:])
else:
for i in range(0, len(s), 2):
d = int(s[i:i + 2])
skipped_dates.append('%d%02d%02d' % (y, m, d))

yesterday = date.today() - timedelta(days = 1)
while current_date < yesterday:
current_date += timedelta(days = 1)
dirname = '%s/daily_problems/%d/%02d/%02d%02d/personal_submission' % (project_root, current_date.year, current_date.month, current_date.month, current_date.day)
if not os.path.exists(dirname):
skipped_dates.append('%d%02d%02d' % (current_date.year, current_date.month, current_date.day))
continue

submissions = {}
for filename in os.listdir(dirname):
if not '_' in filename:
continue
lst = filename.split('.')[0].split('_')
pid, uid = lst[0].lower(), '_'.join(lst[1:]).lower()
if uid.endswith('_star'):
uid = uid[:-5]
if uid not in submissions.keys():
submissions[uid] = set()
submissions[uid].add(pid)

for uid, lst in users.items():
if uid in submissions.keys():
sz = min(2, len(submissions[uid]))
else:
sz = 0
if lst[-1][0] == sz:
lst[-1][1] += 1
else:
lst.append([sz, 1])

for uid, st in submissions.items():
sz = min(2, len(st))
if uid not in users.keys():
users[uid] = [[sz, 1]]

latest_date = current_date

with open(output_file, 'w') as f:
f.write('let records = `\n')
f.write('current_date:%s\n' % latest_date.strftime('%Y-%m-%d'))
for uid, lst in users.items():
s = '/'.join(map(lambda p: str(p[0]) + ',' + str(p[1]), lst))
f.write('%s:%s\n' % (uid, s))

f.write('skipped_dates:')
y, m = 0, 0
lst = []
for s in skipped_dates:
if s > '%d%02d%02d' % (latest_date.year, latest_date.month, latest_date.day):
break
yy, mm, dd = int(s[:4]), int(s[4:6]), int(s[6:])
if y != yy:
lst.append('y%d' % yy)
y = yy
if m != mm:
lst.append('m%d' % mm)
m = mm
if lst[-1][0] == 'y' or lst[-1][0] == 'm':
lst.append('')
lst[-1] += '%02d' % dd
f.write(','.join(lst))
f.write('\n')

f.write('`;\n')
54 changes: 54 additions & 0 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: "Build website"

on:
workflow_dispatch:
schedule:
- cron: '0 2 * * *' # deploy every day at 10:00 UTC+8

jobs:
build-website:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Copy out old record
run: |
if [ `git ls-remote --heads origin refs/heads/gh-pages | wc -l ` -ne 0 ]
then
git fetch origin gh-pages:gh-pages
git checkout gh-pages
if [[ -f records.js ]]
then
cp records.js /tmp/records.js.old
fi
fi
- name: Create gh-pages branch
run: |
git checkout main
git branch -D gh-pages || true
git checkout --orphan gh-pages
- name: Calculate new records and copy out websites
run: |
cp -r .github/workflows/website /tmp/website
python .github/workflows/records.py /tmp/records.js.old /tmp/website/records.js `pwd`
- name: Clean everything and copy back websites
run: |
rm -rf *
cp -r /tmp/website/* .
- name: Push to github
run: |
git add -A
git config --global user.name 'GitHub Actions'
git config --global user.email '[email protected]'
git commit -m "Build website"
git push -f origin gh-pages
205 changes: 205 additions & 0 deletions .github/workflows/website/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="expires" content="1800">
<title>每日羊蹄🐏</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/jquery.tablesorter.combined.min.js"></script>
<link href="simple.css" rel="stylesheet">
</head>
<body>
<div>
<h2>每日羊蹄🐏</h2>
<div id="user-detail" style="display: none;">
<h3 id="user-name">用户:tsreaper</h3>
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 721 110" width="100%">
<g id="wall" transform="translate(25, 20)">
<text text-anchor="middle" class="wday" dx="-13" dy="22" style="font-size: 11px">Mon</text>
<text text-anchor="middle" class="wday" dx="-13" dy="48" style="font-size: 11px">Wed</text>
<text text-anchor="middle" class="wday" dx="-13" dy="74" style="font-size: 11px">Fri</text>
</g>
</svg>
</div>
<div>
<h3>统计数据</h3>
<p id="p-date">日期:2024-02-26</p>
<table id="tbl" class="tablesorter" width="100%">
<thead>
<tr>
<th>ID</th>
<th>当前连击天数</th>
<th>最长连击天数</th>
<th>总提交天数</th>
<th>总提交次数</th>
</tr>
</thead>
<tbody id="tb">
</tbody>
</table>
</div>
</div>

<style>
#tbl > thead > tr > th {
text-align: center;
}
#tbl > tbody > tr > td {
text-align: center;
}
</style>

<script src="records.js"></script>
<script>
function padZero(s, len) {
let pad = "";
for (let i = 0; i < len - s.length; i++) {
pad += "0";
}
return pad + s;
}

let users = new Object();

let lines = records.split(/[\r\n]+/);
let currentDate = '';
let skipped = new Set();
for (let line of lines) {
line = line.trim();
if (line.length == 0) {
continue;
}
if (line.startsWith('current_date:')) {
currentDate = line.substr('current_date:'.length);
document.getElementById('p-date').innerHTML = `日期:${currentDate}`;
} else if (line.startsWith('skipped_dates:')) {
let y = 0, m = 0;
for (let s of line.substr('skipped_dates:'.length).split(',')) {
if (s[0] == 'y') {
y = parseInt(s.substr(1));
} else if (s[0] == 'm') {
m = parseInt(s.substr(1));
} else {
for (let i = 0; i < s.length; i += 2) {
let d = parseInt(s.substr(i, 2));
skipped.add(Math.ceil(
(new Date(`${y}-${padZero(m.toString(), 2)}-${padZero(d.toString(), 2)}`) - new Date(currentDate)) /
(1000 * 60 * 60 * 24)
));
}
}
}
} else {
let userAndRecord = line.split(':');
let user = userAndRecord[0];
let record = userAndRecord[1];
let runs = record.split('/');
let currentStreak = 0;
let maxStreak = 0;
let totalDays = 0;
let totalSubmits = 0;

users[user] = [];
for (let run of runs) {
let xy = run.split(',');
let submitCount = parseInt(xy[0]);
let dayCount = parseInt(xy[1]);
users[user].push([submitCount, dayCount]);
if (submitCount == 0) {
currentStreak = 0;
} else {
currentStreak += dayCount;
totalDays += dayCount;
totalSubmits += submitCount * dayCount;
}
maxStreak = Math.max(maxStreak, currentStreak);
}
let tr = document.createElement('tr');
tr.innerHTML = `<td><a href="#" onclick="showUser('${user}')">${user}</a></td><td>${currentStreak}</td><td>${maxStreak}</td><td>${totalDays}</td><td>${totalSubmits}</td>`;
document.getElementById('tb').appendChild(tr);
}
}

$(function() {
$("#tbl").tablesorter({ sortList: [[1, 1], [2, 1], [3, 1], [4, 1], [0, 0]] });
});

let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
function drawWeek(col, days, start) {
let xmlns = 'http://www.w3.org/2000/svg';
let g = document.createElementNS(xmlns, 'g');
g.setAttributeNS(null, 'transform', `translate(${col * 13}, 0)`);
for (let i = 0; i < days; i++) {
let rect = document.createElementNS(xmlns, 'rect');
rect.id = `day${start + i}`;
rect.classList.add('day');
rect.setAttributeNS(null, 'width', '11');
rect.setAttributeNS(null, 'height', '11');
rect.setAttributeNS(null, 'y', `${i * 13}`);
rect.setAttributeNS(null, 'fill', skipped.has(start + i) ? '#CBCDF0' : '#EBEDF0');
g.appendChild(rect);
}
document.getElementById('wall').appendChild(g);

let firstDate = new Date(currentDate);
firstDate = firstDate.setDate(firstDate.getDate() + start);
firstDate = new Date(firstDate);
let lastWeek = new Date(currentDate);
lastWeek = lastWeek.setDate(lastWeek.getDate() + start - 7);
lastWeek = new Date(lastWeek);
if (firstDate.getMonth() != lastWeek.getMonth()) {
let text = document.createElementNS(xmlns, 'text');
text.setAttributeNS(null, 'x', `${col * 13}`);
text.setAttributeNS(null, 'y', '-5');
text.setAttributeNS(null, 'style', 'font-size: 11px;');
text.innerHTML = months[firstDate.getMonth()];
document.getElementById('wall').appendChild(text);
}
}

let lastColBricks = new Date(currentDate).getDay() % 7 + 1;
let earliestBrick = 1 - lastColBricks;
drawWeek(52, lastColBricks, earliestBrick);
for (let i = 51; i >= 0; i--) {
earliestBrick -= 7;
drawWeek(i, 7, earliestBrick);
}

function showUser(user) {
document.getElementById('user-detail').style.display = '';
document.getElementById('user-name').innerHTML = '用户:' + user;

let now = 0;
for (let i = users[user].length - 1; i >= 0; i--) {
for (let j = 1; j <= users[user][i][1]; j++) {
let t = users[user][i][0];
let fill = '#EBEDF0';
if (t == 1) {
fill = '#40C463';
} else if (t == 2) {
fill = '#216E39';
}
document.getElementById(`day${now}`).setAttributeNS(null, 'fill', fill);
while (true) {
now--;
if (now < earliestBrick) {
return;
}
if (!skipped.has(now)) {
break;
}
}
}
}
while (now >= earliestBrick) {
if (!skipped.has(now)) {
document.getElementById(`day${now}`).setAttributeNS(null, 'fill', '#EBEDF0');
}
now--;
}
}
</script>
</body>
</html>
Loading

0 comments on commit a06cc33

Please sign in to comment.