Browse Source

staticgen (#2)

Merged branch for 'static page generation' feature.
Reviewed-on: #2
master
scuti 4 months ago
parent
commit
2c368021e7
  1. 8
      Makefile
  2. 35
      README.md
  3. 56
      allmaps.py
  4. 17
      output/leaderboard.css
  5. 2
      queries/mranks.sql
  6. 10
      src/dbquery.c
  7. 16
      src/main.c
  8. 18
      template-generic.html
  9. 20
      template_map-generic.html

8
Makefile

@ -3,6 +3,12 @@ BIN=cts @@ -3,6 +3,12 @@ BIN=cts
all: main
staticgen: colors.o src/dbquery.c
echo "\nCompiling executable as static page generator\n"
gcc -c src/dbquery.c $(CFLAGS) -DSTATICGEN
gcc -c src/main.c $(CFLAGS) -DSTATICGEN
gcc colors.o dbquery.o main.o -lsqlite3 -o $(BIN)
main: main.o
gcc colors.o dbquery.o main.o -lsqlite3 -o $(BIN)
@ -19,4 +25,4 @@ testcolor: src/colors.c src/tcolor.c @@ -19,4 +25,4 @@ testcolor: src/colors.c src/tcolor.c
gcc src/colors.c src/tcolor.c -o tcolor -I"includes" -g
clean:
rm *.o *.log $(BIN)
rm *.o

35
README.md

@ -1,14 +1,23 @@ @@ -1,14 +1,23 @@
C CGI Xonotic DeFrag
-----------------
A CGI program written in C to display data related to Race CTS leaderboards of Xonotic servers.
# xdfcgi
A common gateway inferface (CGI) program written in C to display data related to Race CTS leaderboards of Xonotic servers. It may also serve as a static page generator.
## Requirements
* SQLite3
sqlite-devel python3 python-sqlite
The first is only needed for compilation of the C program. The latter two are only for the auxiliary script `allmaps.py`.
## Compiling
`make` makes a CGI program.
`make staticgen` makes a static page generator.
## Usage: CGI Query Strings
The program queries the database `db/cts.db` (`./src/dbquery.c`, function `static bool executequery`)
## Web Server Queries
* `(none)`
- Query file: `queries/mranks.sql`
- Requests the maplist of the server and related data.
- Requests the map list of the server and related data.
* `?map=[map name]`
- Query file: `queries/mleaderboard-ojoin.sql`
@ -18,13 +27,25 @@ A CGI program written in C to display data related to Race CTS leaderboards of X @@ -18,13 +27,25 @@ A CGI program written in C to display data related to Race CTS leaderboards of X
- Query file: `queries/rplayers.sql`
- Requests a player's ranks for all maps leaderboards s/he is present on.
## Usage: Static Page Generation
The CGI program is still invoked in static generation. The files `allmaps.py`, `output/leaderboard.css`, `template.html`, `template_map.html` help produce the output.
Before executing `allmaps.py`, copy and modify the templates.
cp ./template-generic.html ./template.html
cp ./template_map-generic.html ./template_map.html
`allmaps.py` outputs an html file for all distinct maps in the database. The leaderboards for each map (equivalent to `?map=[map name]`) are in `output/maps/`.
python allmaps.py
## Game Versions Used Under:
* Xonotic 0.8.1
* Xonotic 0.8.2
## Compilers
* gcc (GCC) 10.2.1
* MinGW, GCC 4.7.1
__________________
This program uses an sqlite3 database file created from `~/.xonotic/data/data/server.db`.

56
allmaps.py

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
import sqlite3 as sql
import subprocess
def getmaps(database):
output = []
con = sql.connect(database)
with con:
cursor = con.cursor()
try:
# get all maps in database
cursor.execute("select distinct mapid from Cts_times;")
output = cursor.fetchall()
except sql.Error:
print("Shit is fucked.")
return output
# if there is no query then it outputs the index file.
def getcontent(query=None):
cmd = [("./cts")]
proc = subprocess.Popen(cmd, env=query, stdout=subprocess.PIPE, shell=True)
# communicate returns 'bytes' class with function 'decode'
return proc.communicate()[0].decode('utf-8')
def renderindex(template):
# no env variable
table = getcontent()
filename = "./output/index.html"
with open(filename, 'w+') as fout:
fout.write(template % (table))
fout.close
pass
def main():
template = ""
with open("template.html", 'r') as fin:
template = fin.read()
renderindex(template)
maps = getmaps("db/cts.db")
with open("template_map.html", 'r') as fin:
template = fin.read()
# for each map generate an html file.
for game_map in maps:
# game_map is a tuple obj.
map_name = game_map[0]
query = {"QUERY_STRING" : ("map=%s" % map_name)}
table = getcontent(query)
filename = ("./output/maps/%s.html" % map_name)
with open(filename, 'w+') as fout:
title = map_name
fout.write(template % (title, map_name, table))
pass
if __name__ == "__main__":
print("allmaps.py - Generating .html files for all maps.")
main()
pass

17
output/leaderboard.css

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
.footer {
margin:auto;
}
table, th, td {
border: 1px solid grey;
border-collapse: collapse;
}
table {
width:100%;
}
th, td {
width:auto;
text-align:center;
word-wrap: break-word;
margin: 1em 1em 1em 1em;
}

2
queries/mranks.sql

@ -5,4 +5,4 @@ where Cts_ranks.mapid = Cts_times.mapid @@ -5,4 +5,4 @@ where Cts_ranks.mapid = Cts_times.mapid
and cryptokey = idvalue
and idrank = 1
group by Cts_ranks.mapid
order by max(trank);
order by count(trank) DESC;

10
src/dbquery.c

@ -31,7 +31,7 @@ static inline void print_tblheader(const char *c) { @@ -31,7 +31,7 @@ static inline void print_tblheader(const char *c) {
char *labels;
switch (*c) {
default:
labels = "<TABLE class='center'>\
labels = "<TABLE class='leaderboard'>\
<TH class='tablename' COLSPAN='4'> <H3><BR>Map List</H3> </TH>\
<TR>\
<TH class='columnname'>Name</TH>\
@ -41,7 +41,7 @@ static inline void print_tblheader(const char *c) { @@ -41,7 +41,7 @@ static inline void print_tblheader(const char *c) {
</TR>";
break;
case QMLEADERBOARD:
labels = "<TABLE class='center'>\
labels = "<TABLE class='leaderboard'>\
<TH class='tablename' COLSPAN='3'><H3><BR>Leaderboard</H3></TH>\
<TR>\
<TH class='columnname'>Rank</TH>\
@ -50,7 +50,7 @@ static inline void print_tblheader(const char *c) { @@ -50,7 +50,7 @@ static inline void print_tblheader(const char *c) {
</TR>";
break;
case QRPLAYER:
labels = "<TABLE class='center'>\
labels = "<TABLE class='leaderboard'>\
<TH class='tablename' COLSPAN='3'> <H3><BR>Ranks</H3> </TH>\
<TR>\
<TH class='columnname'>Name</TH>\
@ -98,7 +98,11 @@ static void qresult(sqlite3_stmt * const sp, const char *c) { @@ -98,7 +98,11 @@ static void qresult(sqlite3_stmt * const sp, const char *c) {
if (ISPLAYERNAME(c, i)) {
print_plname(field);
} else if (ISMAPNAME(c, i)) {
#ifdef STATICGEN
printf("<TD><a href='./maps/%s.html'>%s</a></TD>", field, field);
#else
printf("<TD><a href='/cgi/cts?map=%s'>%s</a></TD>", field, field);
#endif
} else if (i == 2 && (*c == QMLEADERBOARD || *c == QOVERVIEW)) {
print_time(field);
} else {

16
src/main.c

@ -8,10 +8,7 @@ void html(void) { @@ -8,10 +8,7 @@ void html(void) {
<link rel=\"stylesheet\" type=\"text/css\" href=\"page.css\">\
<title>/v/ - Xonotic</title>\
<p class='hidden'>:-) / nice one<br></p>";
const char *html_bot = "<br><br><p classname='footer'>Pages under construction.<br>\
Service may sporadically become unavailable.<br>\
In-game database is not directly synced with this web server.\
</p>\
const char *html_bot = "<br><br>\
</body></html>";
const char *html_mid = "<br>\
<H2>hi / good luck and have fun.<br><br>Available Pages</H2>\
@ -29,7 +26,18 @@ void html(void) { @@ -29,7 +26,18 @@ void html(void) {
printf("%s", html_bot);
}
// use with template
void templated(void) {
const char *qstr = getenv("QUERY_STRING");
getquery(qstr);
return;
}
int main(void) {
#ifdef STATICGEN
templated();
#else
html();
#endif
return 0;
}

18
template-generic.html

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CTS Leaderboards - Add your title here</title>
<link href="./leaderboard.css" rel="stylesheet" type="text/css" media="all">
</head>
<div class = "content">
%s
<div class = "footer">
<center><p> Page generated using <a href="https://git.teknik.io/scuti/xdfcgi">xdfcgi</a> by scuti.</p></center>
</div>
</div>
</html>

20
template_map-generic.html

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>%s - CTS Leaderboards - Add your title here</title>
<link href="../leaderboard.css" rel="stylesheet" type="text/css" media="all">
</head>
<div class = "content">
<h3>%s</h3>
%s
<div class = "footer">
<center><p> Page generated using <a href="https://git.teknik.io/scuti/xdfcgi">xdfcgi</a> by scuti.</p></center>
</div>
</div>
</html>
Loading…
Cancel
Save