├── .gitignore ├── Dockerfile ├── HOWTO.txt ├── HOWTO_EC2.txt ├── HOWTO_EC2RDS.txt ├── README.md ├── apache └── stats.conf ├── crons.conf ├── css ├── dynamic.css ├── ext-all.css ├── extstats_metal.css ├── friendless.css ├── grid-examples.css ├── ipod.css ├── jqtouch.css ├── super_table.css ├── tabbed.css ├── table.css └── themes │ ├── apple │ ├── img │ │ ├── backButton.png │ │ ├── blueButton.png │ │ ├── cancel.png │ │ ├── chevron.png │ │ ├── grayButton.png │ │ ├── listArrowSel.png │ │ ├── listGroup.png │ │ ├── loading.gif │ │ ├── on_off.png │ │ ├── pinstripes.png │ │ ├── selection.png │ │ ├── thumb.png │ │ ├── toggle.png │ │ ├── toggleOn.png │ │ ├── toolButton.png │ │ ├── toolbar.png │ │ └── whiteButton.png │ ├── theme.css │ └── theme.min.css │ └── jqt │ ├── img │ ├── back_button.png │ ├── back_button_clicked.png │ ├── button.png │ ├── button_clicked.png │ ├── chevron.png │ ├── chevron_circle.png │ ├── grayButton.png │ ├── loading.gif │ ├── on_off.png │ ├── rowhead.png │ ├── toggle.png │ ├── toggleOn.png │ ├── toolbar.png │ └── whiteButton.png │ ├── theme.css │ └── theme.min.css ├── database_schema.sql ├── docker-compose.yml ├── downloader ├── .directory ├── .gitignore ├── README.txt ├── downloader ├── downloaderdb.py ├── downloaderrecord.py ├── file.sql ├── frontpage.py ├── library.py ├── plays.py ├── populateFiles.py ├── query.txt ├── sitedata.py ├── testjson.py └── testsite.py ├── extended ├── angular │ ├── package.json │ └── tsconfig.json ├── extended │ ├── .gitignore │ ├── __init__.py │ ├── csrf.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── stats │ ├── __init__.py │ ├── cookies.py │ ├── dbaccess.py │ ├── django_webserver.py │ ├── features.py │ ├── flask_webserver.py │ ├── game_collections.py │ ├── generate.py │ ├── imggen.py │ ├── imgviews.py │ ├── intsequence.py │ ├── library.py │ ├── models.py │ ├── mydb.py │ ├── period.py │ ├── plays.py │ ├── selectors.py │ ├── sitedata.py │ ├── stats.py │ ├── substrate.py │ ├── templates │ │ └── stats │ │ │ ├── ajax.html │ │ │ ├── badurl.html │ │ │ ├── bestdays.html │ │ │ ├── calendars.html │ │ │ ├── cat_category.html │ │ │ ├── cat_designer.html │ │ │ ├── cat_mechanic.html │ │ │ ├── cat_publisher.html │ │ │ ├── catgraphs.html │ │ │ ├── checklist.html │ │ │ ├── choose.html │ │ │ ├── collectiongames.html │ │ │ ├── collections.html │ │ │ ├── consistency.html │ │ │ ├── consistency_result.html │ │ │ ├── contents.html │ │ │ ├── contentsbody.html │ │ │ ├── contentslist.html │ │ │ ├── cookies.html │ │ │ ├── crazy.html │ │ │ ├── csrf.html │ │ │ ├── dimesbydesigner.html │ │ │ ├── dimesbydesigner_result.html │ │ │ ├── editCollection.html │ │ │ ├── favourites.html │ │ │ ├── favourites2.html │ │ │ ├── favourites2_result.html │ │ │ ├── favourites_result.html │ │ │ ├── featurelist.html │ │ │ ├── featurelist_result.html │ │ │ ├── fgbpy.html │ │ │ ├── florence.html │ │ │ ├── fpvr.html │ │ │ ├── front_page.html │ │ │ ├── geek_error.html │ │ │ ├── geekwidget.html │ │ │ ├── generic_result.html │ │ │ ├── genericgamestable.html │ │ │ ├── gini.html │ │ │ ├── gini_result.html │ │ │ ├── history_error.html │ │ │ ├── imgmaptooltip.html │ │ │ ├── ipod_geek_error.html │ │ │ ├── ipod_main.html │ │ │ ├── ipod_navbar.html │ │ │ ├── ipod_stylesheets.html │ │ │ ├── lag.html │ │ │ ├── lbr.html │ │ │ ├── least.html │ │ │ ├── lifetime.html │ │ │ ├── list.html │ │ │ ├── locations.html │ │ │ ├── locations_result.html │ │ │ ├── message.html │ │ │ ├── morepie.html │ │ │ ├── morgan.html │ │ │ ├── mostunplayed.html │ │ │ ├── mpct.html │ │ │ ├── multiyear.html │ │ │ ├── multiyear_result.html │ │ │ ├── navbar.html │ │ │ ├── new.html │ │ │ ├── newCollection.html │ │ │ ├── nickeldime.html │ │ │ ├── normrankings.html │ │ │ ├── numplayers.html │ │ │ ├── obpy.html │ │ │ ├── pbm.html │ │ │ ├── pbmever.html │ │ │ ├── pbmgraph.html │ │ │ ├── pbmtimeline.html │ │ │ ├── pbmytd.html │ │ │ ├── pbpy.html │ │ │ ├── pbq.html │ │ │ ├── pby.html │ │ │ ├── playedlastyear.html │ │ │ ├── playlogging.html │ │ │ ├── playlogging_result.html │ │ │ ├── playrate.html │ │ │ ├── playrate_result.html │ │ │ ├── playrateown.html │ │ │ ├── playrateprev.html │ │ │ ├── plays.csv │ │ │ ├── plays.html │ │ │ ├── playsByRanking.html │ │ │ ├── playsbyrating.html │ │ │ ├── pogo.html │ │ │ ├── pogotable.html │ │ │ ├── pretitle.html │ │ │ ├── rankings.html │ │ │ ├── ratedplays.html │ │ │ ├── ratingbyranking.html │ │ │ ├── rbpy.html │ │ │ ├── refresh.html │ │ │ ├── result.html │ │ │ ├── result_tabbed.html │ │ │ ├── selectionsDoc.html │ │ │ ├── series.html │ │ │ ├── series.html; │ │ │ ├── server.html │ │ │ ├── sgoyt.html │ │ │ ├── shouldplay.html │ │ │ ├── shouldplayown.html │ │ │ ├── streaks.html │ │ │ ├── stylesheets.html │ │ │ ├── tab1.html │ │ │ ├── tab3.html │ │ │ ├── tab4.html │ │ │ ├── tab5.html │ │ │ ├── tabs.html │ │ │ ├── temphotdate.html │ │ │ ├── temphotday.html │ │ │ ├── temphotmonth.html │ │ │ ├── testajax.html │ │ │ ├── totalplays.html │ │ │ ├── trade.html │ │ │ ├── unusual.html │ │ │ ├── unusual_result.html │ │ │ ├── updates.html │ │ │ ├── userfaves.html │ │ │ ├── viewCollection.html │ │ │ ├── viewSelections.html │ │ │ ├── whatif.html │ │ │ ├── year.html │ │ │ ├── yearcomparison.html │ │ │ └── yearlysummaries.html │ ├── tests.py │ ├── views.py │ └── webserver_factory.py └── test │ ├── simple.sql │ ├── testCreateDatabase.py │ └── testLibrary.py ├── images ├── arrow_down.png ├── arrow_up.png ├── bgg.png ├── bullet_down.png ├── bullet_go.png ├── external.png ├── eye.png ├── pencil.png ├── sort_down.gif ├── sort_up.gif ├── sp.gif ├── stats.gif ├── table_excel.png ├── table_gear.png └── wtfcat.jpg ├── metadata.txt ├── requirements.txt ├── scripts ├── array-grid.js ├── common.js ├── common.js~ ├── dynamic.js ├── dynamic.js~ ├── ext-all.js ├── ext-base.js ├── ext-core.js ├── greenbar.js ├── greenbar.js~ ├── greenbargoodbad.js ├── greenbargoodbad.js~ ├── imgmaptooltip.js ├── jqtouch.js ├── jqtouch.transitions.js ├── jquery-latest.js ├── jquery-ui.js ├── jquery.form.js ├── jquery.js ├── jquery.min.js ├── jquery.mousewheel.js ├── ruler.js ├── shadedtable.js ├── shadedtable.js~ ├── sortable.js ├── sortable.js~ ├── underscore.js ├── whatif.js └── whatif.js~ ├── setup_mysql.sh ├── sitesettings.py ├── static ├── .gitignore ├── Extended Stats User Guide.pdf ├── index.html ├── metadata.txt ├── robots.txt ├── stats.gif └── usernames.txt ├── stats.conf └── supervisord.conf /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.swp 3 | *.bak 4 | /db/ 5 | *.log 6 | *.log.* 7 | *~ 8 | /.idea/ 9 | /sql_log (copy).txt 10 | /sql_log.txt 11 | /ec2_rds.txt 12 | /extended/angular/node_modules -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | #preliminary stuff 2 | FROM ubuntu:14.04 3 | MAINTAINER Jay Atkinson 4 | 5 | 6 | #install basics 7 | RUN apt-get update 8 | RUN apt-get install -y python2.7 9 | RUN apt-get install -y python-mysqldb 10 | RUN apt-get install -y apache2 11 | RUN apt-get install -y python-django 12 | RUN apt-get install -y mysql-client 13 | RUN apt-get install -y libapache2-mod-wsgi 14 | RUN apt-get install -y python-imaging 15 | RUN apt-get install -y supervisor 16 | RUN apt-get install -y cron 17 | RUN apt-get install -y curl 18 | RUN apt-get install -y python-requests 19 | RUN apt-get install -y language-pack-en-base 20 | RUN dpkg-reconfigure locales 21 | 22 | ENV DBUSER root 23 | ENV DBPASS basilisk 24 | 25 | #install files 26 | RUN mkdir -p /home/ubuntu/extended/db 27 | COPY . /home/ubuntu/extended/ 28 | RUN chmod -R 777 /home/ubuntu/extended 29 | RUN chgrp -R www-data /home/ubuntu/extended 30 | #setup supervisord 31 | COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf 32 | 33 | RUN chmod +x /home/ubuntu/extended/setup_mysql.sh 34 | 35 | #setup apache2 36 | RUN mkdir -p /var/lock/apache2 37 | RUN mkdir -p /var/run/apache2 38 | #ENV APACHE_RUN_USER www-data 39 | #ENV APACHE_RUN_GROUP www-data 40 | ENV APACHE_LOG_DIR /var/log/apache2 41 | ENV APACHE_LOCK_DIR /var/lock/apache2 42 | RUN chmod -R 777 /var/www 43 | RUN chgrp -R www-data /var/www 44 | COPY stats.conf /etc/apache2/conf-enabled/ 45 | RUN a2enmod wsgi 46 | 47 | #add cronjob 48 | COPY crons.conf /etc/cron.d/extended 49 | RUN chmod 0644 /etc/cron.d/extended 50 | RUN crontab /etc/cron.d/extended 51 | 52 | 53 | #expose the basic web ports 54 | EXPOSE 80 8080 55 | #start supervisor which starts web & mysql 56 | CMD ["/usr/bin/supervisord"] 57 | -------------------------------------------------------------------------------- /HOWTO.txt: -------------------------------------------------------------------------------- 1 | HOW TO INSTALL EXTENDED STATS ON AN AMAZON EC2 FREE INSTANCE 2 | 3 | 1. Get your virtual machine and connect to it. 4 | 5 | 2. Install stuff 6 | 7 | sudo apt-get update 8 | sudo apt-get install git 9 | sudo apt-get install python-mysqldb 10 | sudo apt-get install apache2 11 | sudo apt-get install mysql-server (remember the database password) 12 | sudo apt-get install mysql-client 13 | sudo apt-get install python-django 14 | sudo apt-get install libapache2-mod-wsgi 15 | sudo apt-get install python-imaging 16 | sudo apt-get install python-pip 17 | 18 | sudo pip install simplejson 19 | 20 | 3. Get the Extended Stats code from github. 21 | 22 | git clone https://github.com/DrFriendless/ExtendedStats extended 23 | 24 | 4. Create the MySQL database 25 | 26 | mysql -u root -p (type in the password) 27 | create database extended; 28 | 29 | Import the schema from database_schema.sql like this: 30 | 31 | mysql extended -u root -p 4 | 5 | Require all granted 6 | 7 | 8 | Alias /robots.txt /home/john/subjects/geek/static/robots.txt 9 | Alias /favicon.ico /home/john/subjects/geek/static/stats.gif 10 | Alias /stuff/ /home/john/subjects/geek/stuff/ 11 | 12 | Require all granted 13 | DirectoryIndex index.html 14 | 15 | Alias /stats/ /home/john/subjects/geek/static/ 16 | 17 | Require all granted 18 | DirectoryIndex index.html 19 | 20 | Alias /css/ /home/john/subjects/geek/css/ 21 | 22 | DirectoryIndex index.html 23 | Require all granted 24 | 25 | Alias /images/ /home/john/subjects/geek/images/ 26 | 27 | DirectoryIndex index.html 28 | Require all granted 29 | 30 | Alias /scripts/ /home/john/subjects/geek/scripts/ 31 | 32 | DirectoryIndex index.html 33 | Require all granted 34 | 35 | Alias /node_modules/ /home/john/subjects/geek/extended/angular/node_modules/ 36 | 37 | DirectoryIndex index.html 38 | Require all granted 39 | 40 | Alias /angular/ /home/john/subjects/geek/extended/angular/ 41 | 42 | DirectoryIndex index.html 43 | Require all granted 44 | 45 | Redirect ^/index.html /dynamic/index.html 46 | RedirectMatch ^/$ /dynamic/index.html 47 | -------------------------------------------------------------------------------- /crons.conf: -------------------------------------------------------------------------------- 1 | */10 * * * * /home/ubuntu/extended/downloader/downloader 2 | -------------------------------------------------------------------------------- /css/extstats_metal.css: -------------------------------------------------------------------------------- 1 | ul.metal *.ct { 2 | font-size: 18px; 3 | font-weight: bold; 4 | color: #11a; 5 | } 6 | 7 | ul.metal *.c1 { 8 | font-size: 14px; 9 | font-weight: bold; 10 | color: #1a1; 11 | float: right; 12 | } 13 | 14 | ul.metal *.c2 { 15 | font-size: 12px; 16 | color: #111; 17 | } 18 | -------------------------------------------------------------------------------- /css/friendless.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Verdana, Arial, Helvetica, sans-serif; 3 | font-size: 0.7em; 4 | } 5 | 6 | td { 7 | font-family: Verdana, Arial, Helvetica, sans-serif; 8 | } 9 | 10 | a { 11 | color: #0000CC; 12 | text-decoration: none; 13 | } 14 | 15 | a:hover { 16 | text-decoration: underline; 17 | } 18 | 19 | h1 { 20 | font-size: 1.5em; 21 | } 22 | 23 | table.listInColumns tbody td { 24 | vertical-align: top; 25 | padding: 0; 26 | } 27 | 28 | table.listInColumns ol { 29 | margin: 0 0 0 3em; 30 | padding: 0; 31 | } 32 | 33 | table.listInColumns ol li { 34 | margin: 0; 35 | margin-bottom: 1px; 36 | padding: 3px 5px; 37 | } 38 | 39 | table.listInColumns ul { 40 | margin: 0; 41 | padding: 0; 42 | } 43 | 44 | table.listInColumns ul li { 45 | list-style: none; 46 | margin: 0; 47 | margin-bottom: 1px; 48 | padding: 3px 5px; 49 | } 50 | 51 | table.listInColumns li, table.listInColumns li a { 52 | color: #666666; 53 | } 54 | 55 | table.listInColumns li.played, table.listInColumns li.played a { 56 | color: #000000; 57 | font-weight: bold; 58 | } 59 | 60 | table.series td.owned, table.listInColumns td.owned, table.entry td.owned a { 61 | color: #000000; 62 | font-weight: bold; 63 | } 64 | 65 | table.listInColumns li.notplayed, table.listInColumns li.notplayed a { 66 | color: #999999; 67 | } 68 | -------------------------------------------------------------------------------- /css/grid-examples.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Ext JS Library 2.0 3 | * Copyright(c) 2006-2007, Ext JS, LLC. 4 | * licensing@extjs.com 5 | * 6 | * http://extjs.com/license 7 | */ 8 | 9 | #grid-example .x-grid-col-1 { 10 | text-align: right; 11 | } 12 | #grid-example .x-grid-col-2{ 13 | text-align: right; 14 | } 15 | #grid-example .x-grid-col-3 { 16 | text-align: right; 17 | } 18 | #grid-example .x-grid-col-4 { 19 | text-align: right; 20 | } 21 | #grid-example.x-grid-mso{ 22 | border: 1px solid #6593cf; 23 | } 24 | #grid-example.x-grid-vista{ 25 | border: 1px solid #b3bcc0; 26 | } 27 | #xml-grid-example{ 28 | border: 1px solid #cbc7b8; 29 | left: 0; 30 | position: relative; 31 | top: 0; 32 | } 33 | #editor-grid .x-grid-col-2{ 34 | text-align:right; 35 | } 36 | .x-grid3-td-topic b { 37 | font-family:tahoma, verdana; 38 | display:block; 39 | } 40 | .x-grid3-td-topic b i { 41 | font-weight:normal; 42 | font-style: normal; 43 | color:#000; 44 | } 45 | .x-grid3-td-topic .x-grid3-cell-inner { 46 | white-space:normal; 47 | } 48 | .x-grid3-td-topic a { 49 | color: #385F95; 50 | text-decoration:none; 51 | } 52 | .x-grid3-td-topic a:hover { 53 | text-decoration:underline; 54 | } 55 | .details .x-btn-text { 56 | background-image: url(details.gif); 57 | } 58 | .x-resizable-pinned .x-resizable-handle-south{ 59 | background:url(../../resources/images/default/sizer/s-handle-dark.gif); 60 | background-position: top; 61 | } -------------------------------------------------------------------------------- /css/ipod.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #ddd; 3 | color: #222; 4 | font-family: Helvetica; 5 | font-size: 13px; 6 | margin: 0; 7 | padding: 0; 8 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#999)); 9 | } 10 | 11 | body h1 { 12 | border-bottom: 1ps solid #666; 13 | color: #222; 14 | display: block; 15 | font-size: 18px; 16 | font-weight: bold; 17 | padding: 10px 0; 18 | text-decoration: none; 19 | margin: 0; 20 | text-shadow: 0px 1px 0px #fff; 21 | } 22 | 23 | #contents ul { 24 | list-style: none; 25 | margin: 10px; 26 | padding: 0; 27 | } 28 | 29 | #contents ul li:first-child a { 30 | -webkit-border-top-left-radius: 8px; 31 | -webkit-border-top-right-radius: 8px; 32 | } 33 | 34 | #contents ul li:last-child a { 35 | -webkit-border-bottom-left-radius: 8px; 36 | -webkit-border-bottom-right-radius: 8px; 37 | } 38 | 39 | #contents ul li a { 40 | background-color: #ffffff; 41 | border: 1px solid #999999; 42 | color: #222222; 43 | display: block; 44 | font-size: 17px; 45 | font-weight: bold; 46 | margin-bottom: -1px; 47 | padding: 12px 10px; 48 | text-decoration: none; 49 | } 50 | 51 | 52 | -------------------------------------------------------------------------------- /css/super_table.css: -------------------------------------------------------------------------------- 1 | /*========================================== 2 | Common table 3 | ==========================================*/ 4 | 5 | table.listable { 6 | border: 1px solid #666666; 7 | } 8 | 9 | table.listable thead tr td { 10 | font-family: verdana, sans-serif; 11 | font-size: 10px; 12 | color: #000000; 13 | font-weight: bold; 14 | padding: 3px 8px; 15 | border-left: 1px solid #D9D9D9; 16 | border-bottom: 1px solid #D9D9D9; 17 | background-color:#EEEEEE; 18 | } 19 | 20 | table.entry thead tr td { 21 | font-family: verdana, sans-serif; 22 | font-size: 10px; 23 | color: #000000; 24 | font-weight: bold; 25 | padding: 3px 8px; 26 | border-left: 1px solid #D9D9D9; 27 | border-bottom: 1px solid #D9D9D9; 28 | background-color:#EEEEEE; 29 | } 30 | 31 | table.listable tbody tr td { 32 | font-family: verdana, sans-serif; 33 | font-size: 10px; 34 | color: #000000; 35 | padding: 3px 8px; 36 | border-left: 1px solid #D9D9D9; 37 | } 38 | 39 | table.listable tfoot tr td { 40 | font-family: verdana, sans-serif; 41 | font-size: 10px; 42 | color: #000000; 43 | font-weight: bold; 44 | padding: 3px 8px; 45 | border-left: 1px solid #D9D9D9; 46 | border-top: 1px solid #D9D9D9; 47 | background-color:#EEEEEE; 48 | } 49 | 50 | table.listable tbody tr.ruled td a { 51 | color: #000066; 52 | } 53 | 54 | table.listable tbody tr.sectionheader td { 55 | font-weight: bold; 56 | padding: 3px 8px; 57 | background-color:#D9D9D9; 58 | } 59 | 60 | /*========================================== 61 | Sortable tables 62 | ==========================================*/ 63 | table.sortable thead tr td { 64 | padding: 0px; 65 | text-align: left; 66 | } 67 | 68 | table.sortable thead a.sortheader { 69 | padding: 3px 8px; 70 | color: #666666; 71 | font-weight: bold; 72 | text-decoration: none; 73 | display: block; 74 | } 75 | 76 | table.sortable thead span.sortarrow { 77 | padding-left: 5px; 78 | } 79 | 80 | /*========================================== 81 | Greenbar tables 82 | ==========================================*/ 83 | 84 | /* Note: by placing this rule above the .selected rule 85 | selected rows receive a style preference */ 86 | table.greenbar tbody tr.even td { 87 | background-color: #DBEEF7; 88 | } 89 | table.greenbargoodbad tbody tr.even td { 90 | background-color: #DBEEF7; 91 | } 92 | table.greenbargoodbad tbody tr.good td { 93 | background-color: #ccffff; 94 | } 95 | table.greenbargoodbad tbody tr.bad td { 96 | background-color: #ffcccc; 97 | } 98 | table.greenbargoodbad tbody tr.goodeven td { 99 | background-color: #88ffff; 100 | } 101 | table.greenbargoodbad tbody tr.badeven td { 102 | background-color: #ffaaaa; 103 | } 104 | /* 105 | table.greenbar tbody tr.selected td { 106 | background-color: #3399CC; 107 | color: #ffffff; 108 | font-weight: bold; 109 | border-left: 1px solid #346DBE; 110 | border-bottom: 1px solid #7DAAEA; 111 | } 112 | */ 113 | /*========================================== 114 | Ruler tables 115 | ==========================================*/ 116 | 117 | table.ruler tbody tr.ruled td { 118 | background-color: #3399CC; 119 | color: #ffffff; 120 | border-left: 1px solid #346DBE; 121 | } 122 | 123 | table.ruler tbody tr.ruled td a { 124 | color: #ffffff; 125 | } 126 | -------------------------------------------------------------------------------- /css/tabbed.css: -------------------------------------------------------------------------------- 1 | /* Horizontal Tabbed Panels */ 2 | .TabbedPanels { 3 | margin: 0px; 4 | padding: 0px; 5 | clear: both; 6 | width: 100%; /* IE Hack to force proper layout when preceded by a paragraph. (hasLayout Bug)*/ 7 | } 8 | 9 | .TabbedPanelsTab { 10 | position: relative; 11 | top: 1px; 12 | float: left; 13 | padding: 6px 12px; 14 | margin: 0px 1px 0px 0px; 15 | background-color: bisque; 16 | list-style: none; 17 | border-left: solid 1px #CCC; 18 | border-bottom: solid 1px #d8d8d8; 19 | border-top: solid 1px #d8d8d8; 20 | border-right: solid 1px #d8d8d8; 21 | -moz-user-select: none; 22 | -khtml-user-select: none; 23 | cursor: pointer; 24 | text-align: center; 25 | font-size: 16px; 26 | font-weight: bold; 27 | } 28 | 29 | .TabbedPanelsTabSelected { 30 | position: relative; 31 | top: 1px; 32 | float: left; 33 | padding: 6px 12px; 34 | margin: 0px 1px 0px 0px; 35 | background-color: #DBEEF7; 36 | list-style: none; 37 | border-left: solid 1px #CCC; 38 | border-bottom: solid 1px #d8d8d8; 39 | border-top: solid 1px #d8d8d8; 40 | border-right: solid 1px #d8d8d8; 41 | -moz-user-select: none; 42 | -khtml-user-select: none; 43 | cursor: pointer; 44 | text-align: center; 45 | font-size: 18px; 46 | font-weight: bold; 47 | } 48 | 49 | .TabbedPanelsTab a { 50 | color: black; 51 | text-decoration: none; 52 | } 53 | 54 | .TabbedPanelsTabSelected a { 55 | color: black; 56 | text-decoration: none; 57 | } 58 | 59 | .BulletList { 60 | list-style-type: none; 61 | margin: 0; 62 | padding: 0; 63 | } 64 | 65 | .BulletList li { 66 | background-repeat: no-repeat; 67 | font-size: 13px; 68 | } 69 | 70 | li.ThisPage { 71 | background-image: url(https://i.imgur.com/0uUVP3i.png); 72 | padding: 0 0 0 20px; 73 | margin: .4em 0; 74 | } 75 | 76 | li.OtherPage { 77 | background-image: url(https://i.imgur.com/9u5lJOl.png); 78 | padding: 0 0 0 20px; 79 | margin: .4em 0; 80 | } 81 | 82 | li.BGG { 83 | background-image: url(https://i.imgur.com/RMbAIpK.png); 84 | padding: 0 0 0 20px; 85 | margin: .4em 0; 86 | } 87 | 88 | li.External { 89 | background-image: url(https://i.imgur.com/tMARrPD.png); 90 | padding: 0 0 0 20px; 91 | margin: .4em 0; 92 | } -------------------------------------------------------------------------------- /css/table.css: -------------------------------------------------------------------------------- 1 | div.tableContainer { 2 | width: 99%; /* table width will be 99% of this*/ 3 | height: 500px; /* must be greater than tbody*/ 4 | overflow: auto; 5 | margin: 0 auto; 6 | } 7 | 8 | div.tableContainer table { 9 | width: 99%; /*100% of container produces horiz. scroll in Mozilla*/ 10 | border: none; 11 | background-color: #f7f7f7; 12 | } 13 | 14 | div.tableContainer table>tbody { /* child selector syntax which IE6 and older do not support*/ 15 | overflow: auto; 16 | height: 430px; 17 | overflow-x: hidden; 18 | } 19 | 20 | div.tableContainer thead tr { 21 | position:relative; 22 | top: expression(offsetParent.scrollTop); /*IE5+ only*/ 23 | } 24 | 25 | div.tableContainer thead td, div.tableContainer thead th { 26 | text-align: center; 27 | font-size: 12px; 28 | background-color: oldlace; 29 | color: steelblue; 30 | font-weight: bold; 31 | border-top: solid 1px #d8d8d8; 32 | } 33 | 34 | div.tableContainer td { 35 | color: #000; 36 | padding-right: 2px; 37 | font-size: 12px; 38 | text-align: right; 39 | border-bottom: solid 1px #d8d8d8; 40 | border-left: solid 1px #d8d8d8; 41 | } 42 | 43 | div.tableContainer tr.even td { 44 | color: #000; 45 | background-color: seashell; 46 | padding-right: 2px; 47 | font-size: 12px; 48 | text-align: right; 49 | border-bottom: solid 1px #d8d8d8; 50 | border-left: solid 1px #d8d8d8; 51 | } 52 | 53 | div.tableContainer table tfoot tr { /*idea of Renato Cherullo to help IE*/ 54 | position: relative; 55 | overflow-x: hidden; 56 | top: expression(parentNode.parentNode.offsetHeight >= 57 | offsetParent.offsetHeight ? 0 - parentNode.parentNode.offsetHeight + offsetParent.offsetHeight + offsetParent.scrollTop : 0); 58 | } 59 | 60 | 61 | div.tableContainer tfoot td { 62 | text-align: center; 63 | font-size: 11px; 64 | font-weight: bold; 65 | background-color: papayawhip; 66 | color: steelblue; 67 | border-top: solid 1px slategray; 68 | } 69 | 70 | div.tableContainer td:last-child {padding-right: 20px;} /*prevent Mozilla scrollbar from hiding cell content*/ 71 | div.tableContainer tr.even td:last-child {padding-right: 20px;} /*prevent Mozilla scrollbar from hiding cell content*/ 72 | -------------------------------------------------------------------------------- /css/themes/apple/img/backButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/backButton.png -------------------------------------------------------------------------------- /css/themes/apple/img/blueButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/blueButton.png -------------------------------------------------------------------------------- /css/themes/apple/img/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/cancel.png -------------------------------------------------------------------------------- /css/themes/apple/img/chevron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/chevron.png -------------------------------------------------------------------------------- /css/themes/apple/img/grayButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/grayButton.png -------------------------------------------------------------------------------- /css/themes/apple/img/listArrowSel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/listArrowSel.png -------------------------------------------------------------------------------- /css/themes/apple/img/listGroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/listGroup.png -------------------------------------------------------------------------------- /css/themes/apple/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/loading.gif -------------------------------------------------------------------------------- /css/themes/apple/img/on_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/on_off.png -------------------------------------------------------------------------------- /css/themes/apple/img/pinstripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/pinstripes.png -------------------------------------------------------------------------------- /css/themes/apple/img/selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/selection.png -------------------------------------------------------------------------------- /css/themes/apple/img/thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/thumb.png -------------------------------------------------------------------------------- /css/themes/apple/img/toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/toggle.png -------------------------------------------------------------------------------- /css/themes/apple/img/toggleOn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/toggleOn.png -------------------------------------------------------------------------------- /css/themes/apple/img/toolButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/toolButton.png -------------------------------------------------------------------------------- /css/themes/apple/img/toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/toolbar.png -------------------------------------------------------------------------------- /css/themes/apple/img/whiteButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/apple/img/whiteButton.png -------------------------------------------------------------------------------- /css/themes/jqt/img/back_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/back_button.png -------------------------------------------------------------------------------- /css/themes/jqt/img/back_button_clicked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/back_button_clicked.png -------------------------------------------------------------------------------- /css/themes/jqt/img/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/button.png -------------------------------------------------------------------------------- /css/themes/jqt/img/button_clicked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/button_clicked.png -------------------------------------------------------------------------------- /css/themes/jqt/img/chevron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/chevron.png -------------------------------------------------------------------------------- /css/themes/jqt/img/chevron_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/chevron_circle.png -------------------------------------------------------------------------------- /css/themes/jqt/img/grayButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/grayButton.png -------------------------------------------------------------------------------- /css/themes/jqt/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/loading.gif -------------------------------------------------------------------------------- /css/themes/jqt/img/on_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/on_off.png -------------------------------------------------------------------------------- /css/themes/jqt/img/rowhead.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/rowhead.png -------------------------------------------------------------------------------- /css/themes/jqt/img/toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/toggle.png -------------------------------------------------------------------------------- /css/themes/jqt/img/toggleOn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/toggleOn.png -------------------------------------------------------------------------------- /css/themes/jqt/img/toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/toolbar.png -------------------------------------------------------------------------------- /css/themes/jqt/img/whiteButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/css/themes/jqt/img/whiteButton.png -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | extendedweb: 2 | build: . 3 | ports: 4 | - "80:80" 5 | links: 6 | - mysqldb 7 | command: /usr/bin/supervisord 8 | 9 | mysqldb: 10 | image: 'mysql:5.5' 11 | environment: 12 | - MYSQL_ROOT_PASSWORD=basilisk 13 | - MYSQL_DATABASE=extended 14 | -------------------------------------------------------------------------------- /downloader/.directory: -------------------------------------------------------------------------------- 1 | [Dolphin] 2 | Timestamp=2015,5,16,11,4,28 3 | Version=3 4 | ViewMode=1 5 | -------------------------------------------------------------------------------- /downloader/.gitignore: -------------------------------------------------------------------------------- 1 | .directory 2 | populateFiles.pyc 3 | *~ 4 | -------------------------------------------------------------------------------- /downloader/README.txt: -------------------------------------------------------------------------------- 1 | This is the code for the downloader. To run the downloader, edit sitedata.py then execute "downloader". -------------------------------------------------------------------------------- /downloader/downloader: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, os 4 | sys.path.append(".") 5 | 6 | BETWEEN_POPULATES = 540 7 | 8 | def loadGameFiles(db, rec): 9 | import time, populateFiles 10 | finish = time.time() + BETWEEN_POPULATES 11 | populateFiles.main(db, finish, rec) 12 | 13 | import sys, downloaderdb, logging.handlers, sitedata, time 14 | handler = logging.handlers.RotatingFileHandler(sitedata.logfile, maxBytes=10000000, backupCount=5) 15 | handler3 = logging.StreamHandler() 16 | logging.getLogger().setLevel(logging.INFO) 17 | logging.getLogger().addHandler(handler) 18 | logging.getLogger().addHandler(handler3) 19 | 20 | import downloaderrecord 21 | with downloaderrecord.DownloaderRecord() as rec: 22 | logging.info("Downloader starts at %s" % (time.ctime(),)) 23 | if not os.path.exists(sitedata.dbdir): 24 | logging.info("Making data directory %s" % sitedata.dbdir) 25 | os.makedirs(sitedata.dbdir) 26 | if not os.path.exists(sitedata.resultdir): 27 | logging.info("Making results directory %s" % sitedata.resultdir) 28 | os.makedirs(sitedata.resultdir) 29 | toFix = sys.argv[1:] 30 | if len(toFix) > 0: 31 | with downloaderdb.MyDB() as db: 32 | for geek in toFix: 33 | print db.execute("update files set lastUpdate = null where geek = '%s' and processMethod != 'processGame'" % geek) 34 | print "Reset %s" % geek 35 | with downloaderdb.MyDB() as db: 36 | loadGameFiles(db, rec) 37 | rec.finish() # not really happy about this not being done by the context manager 38 | db.execute(rec.toSQL()) 39 | logging.info(str(rec)) 40 | -------------------------------------------------------------------------------- /downloader/downloaderdb.py: -------------------------------------------------------------------------------- 1 | import sitedata 2 | 3 | class MyDB(object): 4 | def __init__(self): 5 | import MySQLdb 6 | self.db = MySQLdb.connect(host=sitedata.dbhost, user=sitedata.dbuser , passwd=sitedata.password, db=sitedata.dbname) 7 | self.db.autocommit = True 8 | self.db.set_character_set('utf8') 9 | dbc = self.db.cursor() 10 | dbc.execute('SET NAMES utf8;') 11 | dbc.execute('SET CHARACTER SET utf8;') 12 | dbc.execute('SET character_set_connection=utf8;') 13 | dbc.close() 14 | self.db.optimised = False 15 | 16 | def execute(self, sql, args=None): 17 | c = self.db.cursor() 18 | c.execute(sql, args) 19 | result = c.fetchall() 20 | c.close() 21 | self.db.commit() 22 | return result 23 | 24 | def close(self): 25 | self.db.close() 26 | 27 | def __enter__(self): 28 | return self 29 | 30 | def __exit__(self, type, value, tb): 31 | self.close() 32 | 33 | def saveRow(self, row, table, where, debug=0): 34 | count = self.execute("select count(*) from %s where %s" % (table, where))[0][0] 35 | cs = [] 36 | vs = [] 37 | args = [] 38 | for (col, val) in row.items(): 39 | cs.append(col) 40 | if type(val) == type(""): 41 | vs.append("%s") 42 | args.append(val) 43 | elif type(val) == type(u""): 44 | vs.append("%s") 45 | args.append(val.encode('utf8')) 46 | else: 47 | vs.append(str(val)) 48 | cols = ", ".join(cs) 49 | vals = ", ".join(vs) 50 | if count == 0: 51 | sql = "insert into %s (%s) values (%s)" % (table, cols, vals) 52 | if debug: 53 | print sql 54 | self.execute(sql, tuple(args)) 55 | else: 56 | ds = [] 57 | for (index,v) in enumerate(vs): 58 | ds.append("%s = %s" % (cs[index], v)) 59 | data = ", ".join(ds) 60 | sql = "update %s set %s where %s" % (table, data, where) 61 | if debug: 62 | print sql 63 | self.execute(sql, tuple(args)) 64 | 65 | class Row: 66 | def __init__(self): 67 | pass 68 | 69 | def items(self): 70 | return self.__dict__.items() 71 | -------------------------------------------------------------------------------- /downloader/downloaderrecord.py: -------------------------------------------------------------------------------- 1 | class DownloaderRecord(object): 2 | def __init__(self): 3 | self.filesprocessed = 0 4 | self.waittime = 0.0 5 | self.pausetime = 0.0 6 | self.nothing = 0.0 7 | self.failures = 0 8 | self.tryagains = 0 9 | self.games = 0 10 | self.users = 0 11 | self.endtime = None 12 | self.startime = None 13 | self.files1 = 0 14 | self.files2 = 0 15 | self.files3 = 0 16 | 17 | def usersAndGames(self, u, g): 18 | self.users = u 19 | self.games = g 20 | 21 | def __enter__(self): 22 | import time 23 | self.starttime = time.time() 24 | return self 25 | 26 | def finish(self): 27 | import time 28 | self.endtime = time.time() 29 | 30 | def __exit__(self, type, value, tb): 31 | pass 32 | 33 | def wait(self, howlong): 34 | self.waittime += howlong 35 | 36 | def pause(self, howlong): 37 | self.pausetime += howlong 38 | 39 | def nothingToDo(self, howlong): 40 | self.nothing += howlong 41 | 42 | def processFiles(self, n): 43 | self.filesprocessed = self.filesprocessed + n 44 | 45 | def failure(self): 46 | self.failures += 1 47 | 48 | def tryagain(self): 49 | self.tryagains += 1 50 | 51 | def toSQL(self): 52 | import time 53 | format = '%Y-%m-%d %H:%M:%S' 54 | return "insert into downloader (starttime, endtime, filesprocessed, waittime, pausetime, nothing, failures, users, games, files1, files2, files3, tryagains) values ('%s', '%s', %d, %6.2f, %6.2f, %6.2f, %d, %d, %d, %d, %d, %d, %d)" % (time.strftime(format, time.localtime(self.starttime)), time.strftime(format, time.localtime(self.endtime)), self.filesprocessed, self.waittime, self.pausetime, self.nothing, self.failures, self.users, self.games, self.files1, self.files2, self.files3, self.tryagains) 55 | 56 | def __str__(self): 57 | import time 58 | return "From %s to %s, %d users %d games %d files %d failures %d tryagains %4.1f wait %4.1f pause %4.1f nothing to do" % (time.ctime(self.starttime), time.ctime(self.endtime), self.users, self.games, self.filesprocessed, self.failures, self.tryagains, self.waittime, self.pausetime, self.nothing) 59 | -------------------------------------------------------------------------------- /downloader/query.txt: -------------------------------------------------------------------------------- 1 | select name from games where bggid not in (select game from geekgames where geek = 'Friendless' and rating > 0) and bggid not in (select gameId from gameCategories where category = 'Expansion for Base-game') order by bayesAverage desc 2 | -------------------------------------------------------------------------------- /downloader/sitedata.py: -------------------------------------------------------------------------------- 1 | # configuration for a particular stats site 2 | import os, sys 3 | 4 | # the directory where the configuration files (e.g. usernames.txt) are stored, and where sitesettings.py is. 5 | installDir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 6 | sys.path.append(installDir) 7 | from sitesettings import * 8 | 9 | downloaderDir = os.path.join(installDir, "downloader") 10 | dbdir = os.path.join(installDir, "db") 11 | resultdir= os.path.join(installDir, "static") 12 | logfile = os.path.join(installDir, "downloader.log") 13 | 14 | # a public file owned by drfriendless@gmail.com 15 | usernames_url = "https://pastebin.com/raw/BvvdxzcH" 16 | 17 | # a public file owned by drfriendless@gmail.com 18 | metadata_url = "https://pastebin.com/raw/iS8idfaH" -------------------------------------------------------------------------------- /downloader/testjson.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | import sys 3 | sys.path.append(".") 4 | 5 | """This class is to test the JSON API without doing all the work of a full test.""" 6 | 7 | USERS = [ "Friendless", "sa266", "spellenclub ST", "PzVIE", "Damjon", "yzemaze" ] 8 | TAGS = ["pbpy", "obpy", "rbpy", "mmmpie", "pogo", "pogotable", "mostunplayed", "playrate", "playrateown", "playrateprev", 9 | "pbmever", "pbmytd", "pbmgraph", "pr", "pbq", "favourites", "fgbpy", "bestdays", "ratingByRanking", "unusual", "least", 10 | "shouldplay", "shouldplayown", "timeline", "thm", "thd", "thday", "dimesbydesigner", "florence", "streaks", 11 | "pby", "consistency", "morepie", "generic", "playsByRanking", "yearly" ] 12 | CHOOSE_URL = "%sdynamic/choose/%s/%s" 13 | JSON_URL = "%sdynamic/json/%s/%s" 14 | 15 | import urllib, time, sitedata 16 | errors = [] 17 | all = [ ] 18 | for user in USERS: 19 | for tag in TAGS: 20 | all.append(JSON_URL % (sitedata.site, user, tag)) 21 | total = len(all) 22 | i = 0 23 | for s in all: 24 | i += 1 25 | start = time.time() 26 | print "%d/%d %s" % (i, total, s), 27 | response = urllib.urlopen(s) 28 | end = time.time() 29 | print " (%s seconds) " % int(end-start), response.code 30 | if response.code != 200: 31 | errors.append(s) 32 | if len(errors) > 0: 33 | print 34 | print "FAILURES" 35 | for e in errors: 36 | print e 37 | print 38 | print "JSON functionality is %d%% working!" % ((len(all) - len(errors)) * 100 / len(all)) 39 | -------------------------------------------------------------------------------- /extended/angular/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "extended-stats-dashboard", 3 | "version": "0.1", 4 | "license": "", 5 | "description": "", 6 | "dependencies": { 7 | "@angular/common": "2.4.7", 8 | "@angular/compiler": "2.4.7", 9 | "@angular/core": "2.4.7", 10 | "@angular/platform-browser": "2.4.7", 11 | "@angular/platform-browser-dynamic": "2.4.7", 12 | "@angular/router": "3.4.7", 13 | "rxjs": "5.1.1", 14 | "systemjs": "^0.20.7", 15 | "zone.js": "^0.7.7" 16 | }, 17 | "devDependencies": { 18 | "typescript": "^2.1.6" 19 | } 20 | } -------------------------------------------------------------------------------- /extended/angular/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "sourceMap": true, 8 | "suppressImplicitAnyIndexErrors":true 9 | }, 10 | "compileOnSave": false, 11 | "buildOnSave": false, 12 | "exclude": [ 13 | "node_modules" 14 | ], 15 | "filesGlob": [ 16 | "app/**/*.ts", 17 | "typings/index.d.ts" 18 | ], 19 | "atom": { 20 | "rewriteTsconfig": false 21 | } 22 | } -------------------------------------------------------------------------------- /extended/extended/.gitignore: -------------------------------------------------------------------------------- 1 | settings.py~ 2 | wsgi.py~ 3 | -------------------------------------------------------------------------------- /extended/extended/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/extended/extended/__init__.py -------------------------------------------------------------------------------- /extended/extended/csrf.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | 3 | def wtf(request, reason=""): 4 | params = { "reason" : reason } 5 | return render_to_response("stats/csrf.html", params) -------------------------------------------------------------------------------- /extended/extended/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for extended project. 3 | 4 | This module contains the WSGI application used by Django's development server 5 | and any production WSGI deployments. It should expose a module-level variable 6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover 7 | this application via the ``WSGI_APPLICATION`` setting. 8 | 9 | Usually you will have the standard Django WSGI application here, but it also 10 | might make sense to replace the whole Django WSGI application with a custom one 11 | that later delegates to the Django one. For example, you could introduce WSGI 12 | middleware here, or combine a Django application with an application of another 13 | framework. 14 | 15 | """ 16 | import os, sys 17 | # figure it out from this file's location - this avoids having to edit this file during installation 18 | dir = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0] 19 | sys.path.append(dir) 20 | 21 | # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks 22 | # if running multiple sites in the same mod_wsgi process. To fix this, use 23 | # mod_wsgi daemon mode with each site in its own daemon process, or use 24 | # os.environ["DJANGO_SETTINGS_MODULE"] = "extended.settings" 25 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "extended.settings") 26 | 27 | # This application object is used by any WSGI server configured to use this 28 | # file. This includes Django's development server, if the WSGI_APPLICATION 29 | # setting points here. 30 | 31 | from django.core.wsgi import get_wsgi_application 32 | application = get_wsgi_application() 33 | 34 | # Apply WSGI middleware here. 35 | # from helloworld.wsgi import HelloWorldApplication 36 | # application = HelloWorldApplication(application) 37 | -------------------------------------------------------------------------------- /extended/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "extended.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /extended/stats/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/extended/stats/__init__.py -------------------------------------------------------------------------------- /extended/stats/django_webserver.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse, HttpResponseRedirect 2 | from django.template import RequestContext 3 | from django.shortcuts import render_to_response 4 | 5 | def redirect(url): 6 | return HttpResponseRedirect(url) 7 | 8 | def response(*args, **kwargs): 9 | return HttpResponse(*args, **kwargs) 10 | 11 | def render(template, context, request, *args, **kwargs): 12 | return render_to_response(template, context, context_instance=RequestContext(request), *args, **kwargs) 13 | 14 | def csrf(request): 15 | import django.core.context_processors 16 | return django.core.context_processors.csrf(request) 17 | 18 | def get_cookie(request, cookieName): 19 | return request.COOKIES.get(cookieName) 20 | 21 | def get_int_cookie(request, cookieName, defolt): 22 | s = request.COOKIES.get(cookieName) 23 | if s is None or s == "": 24 | return defolt 25 | return int(s) 26 | -------------------------------------------------------------------------------- /extended/stats/flask_webserver.py: -------------------------------------------------------------------------------- 1 | def redirect(url): 2 | return None 3 | 4 | def response(*args, **kwargs): 5 | return None 6 | 7 | def render(template, context, request, *args, **kwargs): 8 | from flask import make_response, render_template 9 | if template.startswith("stats/"): 10 | template = "angular/" + template[6:] 11 | resp = make_response(render_template(template, **context)) 12 | return resp 13 | 14 | def get_cookie(request, cookieName): 15 | return request.cookies.get(cookieName) -------------------------------------------------------------------------------- /extended/stats/intsequence.py: -------------------------------------------------------------------------------- 1 | class IntSequence(object): 2 | pass 3 | 4 | def getCounts(self, context, opts, startDate, endDate): 5 | import library 6 | return library.Counts() 7 | 8 | class PlayCountIntSequence(IntSequence): 9 | key = "playCount" 10 | arity = 0 11 | usesSelector = True 12 | 13 | def __init__(self, selector): 14 | self.selector = selector 15 | 16 | def getCounts(self, context, opts, startDate, endDate): 17 | import library 18 | games = self.selector.getGames(context, opts) 19 | plays = context.substrate.filterPlays(startDate, endDate)[0] 20 | result = library.AnnotatedCounts() 21 | for p in plays: 22 | include = (p.game in games) 23 | if not include: 24 | for e in p.expansions: 25 | if e in games: 26 | include = True 27 | break 28 | if include: 29 | result.addAnnotated(p.dt, p.count, p.game.name) 30 | return result 31 | 32 | class DistinctGamesPlayedIntSequence(IntSequence): 33 | key = "distinctGames" 34 | arity = 0 35 | usesSelector = True 36 | 37 | def __init__(self, selector): 38 | self.selector = selector 39 | 40 | def getCounts(self, context, opts, startDate, endDate): 41 | import library 42 | games = self.selector.getGames(context, opts) 43 | plays = context.substrate.filterPlays(startDate, endDate)[0] 44 | gamesPlayedByDate = {} 45 | for p in plays: 46 | include = (p.game in games) 47 | if include: 48 | already = gamesPlayedByDate.get(p.dt) 49 | if already is None: 50 | already = [] 51 | if p.game not in already: 52 | already.append(p.game) 53 | gamesPlayedByDate[p.dt] = already 54 | result = library.AnnotatedCounts() 55 | for (date, already) in gamesPlayedByDate.items(): 56 | for g in already: 57 | result.addAnnotated(date, 1, g.name) 58 | return result 59 | 60 | INT_SEQUENCES = [ PlayCountIntSequence, DistinctGamesPlayedIntSequence ] 61 | 62 | def parseIntSequence(fields): 63 | import selectors 64 | key = fields[0] 65 | fields = fields[1:] 66 | for seq in INT_SEQUENCES: 67 | if key == seq.key: 68 | args = fields[:seq.arity] 69 | fields = fields[seq.arity:] 70 | if seq.usesSelector: 71 | sel = selectors.getSelectorFromFields(fields) 72 | args.append(sel) 73 | return apply(seq, args) 74 | raise selectors.UnknownSymbol(key) 75 | 76 | -------------------------------------------------------------------------------- /extended/stats/sitedata.py: -------------------------------------------------------------------------------- 1 | # configuration for a particular stats site 2 | import os, sys 3 | 4 | # the directory where the configuration files (e.g. usernames.txt) are stored, and where sitesettings.py is. 5 | installDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) 6 | sys.path.append(installDir) 7 | from sitesettings import * 8 | 9 | dbdir = os.path.join(installDir, "db") 10 | 11 | -------------------------------------------------------------------------------- /extended/stats/stats.py: -------------------------------------------------------------------------------- 1 | """Attempt to run using Flask.""" 2 | 3 | from flask import Flask 4 | app = Flask("stats") 5 | 6 | import webserver_factory, flask_webserver 7 | webserver_factory.webserver = flask_webserver 8 | 9 | @app.route('/') 10 | def hello_world(): 11 | return "Hello World!" 12 | 13 | @app.route('/result/') 14 | def result(username): 15 | import views 16 | from flask import request 17 | print request 18 | return views.result(request, username) 19 | 20 | if __name__ == "__main__": 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/ajax.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Extended Stats for {{geek.username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 28 | 29 | 30 |

Test

31 | 32 |
33 |

34 | 35 | 36 |

37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/badurl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Error 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

10 | That URL doesn't make any sense. 404, dude. 11 | 12 | 13 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/bestdays.html: -------------------------------------------------------------------------------- 1 |

2 |

Best Days in Gaming

3 | These are your best days in gaming. Playing a game more than once counts as only 1.5 plays, so the best days will be those on which you played a variety of games you liked. 4 |

5 | 6 | 7 | 8 | {% for row in bestDays %} 9 | 10 | 11 | 16 | 17 | {% endfor %} 18 |
DateGames
{{row.date}} 12 | {% for game in row.plays %} 13 | {{game.plays}} plays of {{game.name}}{% if not forloop.last %}, {% endif %} 14 | {% endfor %} 15 |
19 |

20 | 21 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/calendars.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Extended Stats for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/geekwidget.html' %} 9 | {% include 'stats/navbar.html' %} 10 |

Calendars for {{username}}

11 | 12 |
13 | 14 | {% for row in months %} 15 | 16 | {% for month in row %} 17 | 30 | {% endfor %} 31 | 32 | {% endfor %} 33 |
18 | 19 | 20 | 21 | {% for row in month.rows %} 22 | 23 | {% for day in row %} 24 | 25 | {% endfor %} 26 | 27 | {% endfor %} 28 |
{{month.name}}
SunMonTueWedThuFriSat
{{day.date}}
29 |
34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/cat_category.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Category Summary for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |
10 |

Category Summary for {{username}}

11 | 12 | 17 | 18 |

Categories

19 | The Whitmore Rating was inspired by Kevin Whitmore. 20 |

21 | 22 | 23 | 24 | 25 | 26 | 27 | {% for row in rows %} 28 | 29 | {% if row.url %} 30 | 31 | {% else %} 32 | 33 | {% endif %} 34 | 35 | 36 | 37 | 38 | 43 | 44 | 45 | 46 | 47 | {% endfor %} 48 | 49 |
NameNumber RatedAverage RatingOwnedAvg Rating for OwnedFavourite GamePlaysHours PlayedWhitmore Rating
{{row.name}}{{row.name}}{% if row.count %}{{row.count}}{% else %} {% endif %}{% if row.rating %}{{row.rating}}{% else %} {% endif %}{% if row.owned %}{{row.owned}}{% else %} {% endif %}{% if row.avgOwned %}{{row.avgOwned}}{% else %} {% endif %}{% if row.favid %} 39 | {{row.favgame.name}} 40 | {% else %} 41 |   42 | {% endif %}{% if row.plays %}{{row.plays}}{% else %} {% endif %}{% if row.plays %}{{row.hoursPlayed}}{% else %} {% endif %}{% if row.whitmore %}{{row.whitmore}}{% else %} {% endif %}
50 | 51 |

Games Owned

52 | 53 | 54 | 55 | 56 | 57 | 58 | {% for row in rows %} 59 | {% if row.collection %} 60 | 61 | {% if row.url %} 62 | 63 | {% else %} 64 | 65 | {% endif %} 66 | 71 | 72 | {% endif %} 73 | {% endfor %} 74 | 75 |
CategoryGames Owned
{{row.name}}{{row.name}} 67 | {% for g in row.collection %} 68 | {{g.name}}{% if not forloop.last %}, {% endif %} 69 | {% endfor %} 70 |
76 | 77 |
78 |

Correlation Graphs

79 | 80 | {% for row in toGraph %} 81 | 82 | {% for cat in row %} 83 | 87 | {% endfor %} 88 | 89 | {% endfor %} 90 |
84 |

{{cat}}

85 | 86 |
91 |
92 | 93 |
94 | 95 | 96 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/cat_designer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Designers Summary for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |
10 |

Designers Summary for {{username}}

11 | 12 | 17 | 18 |

Designers

19 | The Whitmore Rating was inspired by Kevin Whitmore. 20 | The Whitmore Rating without expansions was apparently discussed on The Dice Tower but it was suggested to me by Aaron Seeber. 21 |

22 | 23 | 24 | 25 | 26 | 27 | 28 | {% for row in rows %} 29 | 30 | {% if row.url %} 31 | 32 | {% else %} 33 | 34 | {% endif %} 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | {% endfor %} 50 | 51 |
NameNumber RatedAverage RatingOwnedAvg Rating for OwnedFavourite GamePlaysHours PlayedWhitmore RatingWhitmore Excluding Expansions
{{row.name}}{{row.name}}{% if row.count %}{{row.count}}{% else %} {% endif %}{% if row.rating %}{{row.rating}}{% else %} {% endif %}{% if row.owned %}{{row.owned}}{% else %} {% endif %}{% if row.avgOwned %}{{row.avgOwned}}{% else %} {% endif %}{% if row.favid %} 40 | {{row.favgame.name}} 41 | {% else %} 42 |   43 | {% endif %}{% if row.plays %}{{row.plays}}{% else %} {% endif %}{% if row.plays %}{{row.hoursPlayed}}{% else %} {% endif %}{% if row.whitmore %}{{row.whitmore}}{% else %} {% endif %}{% if row.whitmoreNoExp %}{{row.whitmoreNoExp}}{% else %} {% endif %}
52 | 53 |

Games Owned

54 | 55 | 56 | 57 | 58 | 59 | 60 | {% for row in rows %} 61 | {% if row.collection %} 62 | 63 | {% if row.url %} 64 | 65 | {% else %} 66 | 67 | {% endif %} 68 | 73 | 74 | {% endif %} 75 | {% endfor %} 76 | 77 |
DesignerGames Owned
{{row.name}}{{row.name}} 69 | {% for g in row.collection %} 70 | {{g.name}}{% if not forloop.last %}, {% endif %} 71 | {% endfor %} 72 |
78 | 79 |
80 |

Correlation Graphs

81 | 82 | {% for row in toGraph %} 83 | 84 | {% for cat in row %} 85 | 89 | {% endfor %} 90 | 91 | {% endfor %} 92 |
86 |

{{cat.name}}

87 | 88 |
93 |
94 | 95 |
96 | 97 | 98 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/cat_mechanic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Mechanics Summary for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |
10 |

Mechanics Summary for {{username}}

11 | 12 | 17 | 18 |

Mechanics

19 | The Whitmore Rating was inspired by Kevin Whitmore. 20 |

21 | 22 | 23 | 24 | 25 | 26 | 27 | {% for row in rows %} 28 | 29 | {% if row.url %} 30 | 31 | {% else %} 32 | 33 | {% endif %} 34 | 35 | 36 | 37 | 38 | 43 | 44 | 45 | 46 | 47 | {% endfor %} 48 | 49 |
NameNumber RatedAverage RatingOwnedAvg Rating for OwnedFavourite GamePlaysHours PlayedWhitmore Rating
{{row.name}}{{row.name}}{% if row.count %}{{row.count}}{% else %} {% endif %}{% if row.rating %}{{row.rating}}{% else %} {% endif %}{% if row.owned %}{{row.owned}}{% else %} {% endif %}{% if row.avgOwned %}{{row.avgOwned}}{% else %} {% endif %}{% if row.favid %} 39 | {{row.favgame.name}} 40 | {% else %} 41 |   42 | {% endif %}{% if row.plays %}{{row.plays}}{% else %} {% endif %}{% if row.plays %}{{row.hoursPlayed}}{% else %} {% endif %}{% if row.whitmore %}{{row.whitmore}}{% else %} {% endif %}
50 | 51 |

Games Owned

52 | 53 | 54 | 55 | 56 | 57 | 58 | {% for row in rows %} 59 | {% if row.collection %} 60 | 61 | {% if row.url %} 62 | 63 | {% else %} 64 | 65 | {% endif %} 66 | 71 | 72 | {% endif %} 73 | {% endfor %} 74 | 75 |
MechanicGames Owned
{{row.name}}{{row.name}} 67 | {% for g in row.collection %} 68 | {{g.name}}{% if not forloop.last %}, {% endif %} 69 | {% endfor %} 70 |
76 | 77 |
78 |

Correlation Graphs

79 | 80 | {% for row in toGraph %} 81 | 82 | {% for cat in row %} 83 | 87 | {% endfor %} 88 | 89 | {% endfor %} 90 |
84 |

{{cat}}

85 | 86 |
91 |
92 | 93 |
94 | 95 | 96 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/cat_publisher.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Publishers Summary for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |
10 |

Publishers Summary for {{username}}

11 | 12 | 17 | 18 |

Publishers

19 | The Whitmore Rating was inspired by Kevin Whitmore. 20 |

21 | 22 | 23 | 24 | 25 | 26 | 27 | {% for row in rows %} 28 | 29 | {% if row.url %} 30 | 31 | {% else %} 32 | 33 | {% endif %} 34 | 35 | 36 | 37 | 38 | 43 | 44 | 45 | 46 | 47 | {% endfor %} 48 | 49 |
NameNumber RatedAverage RatingOwnedAvg Rating for OwnedFavourite GamePlaysHours PlayedWhitmore Rating
{{row.name}}{{row.name}}{% if row.count %}{{row.count}}{% else %} {% endif %}{% if row.rating %}{{row.rating}}{% else %} {% endif %}{% if row.owned %}{{row.owned}}{% else %} {% endif %}{% if row.avgOwned %}{{row.avgOwned}}{% else %} {% endif %}{% if row.favid %} 39 | {{row.favgame.name}} 40 | {% else %} 41 |   42 | {% endif %}{% if row.plays %}{{row.plays}}{% else %} {% endif %}{% if row.plays %}{{row.hoursPlayed}}{% else %} {% endif %}{% if row.whitmore %}{{row.whitmore}}{% else %} {% endif %}
50 | 51 |

Games Owned

52 | 53 | 54 | 55 | 56 | 57 | 58 | {% for row in rows %} 59 | {% if row.collection %} 60 | 61 | {% if row.url %} 62 | 63 | {% else %} 64 | 65 | {% endif %} 66 | 71 | 72 | {% endif %} 73 | {% endfor %} 74 | 75 |
PublisherGames Owned
{{row.name}}{{row.name}} 67 | {% for g in row.collection %} 68 | {{g.name}}{% if not forloop.last %}, {% endif %} 69 | {% endfor %} 70 |
76 | 77 |
78 |

Correlation Graphs

79 | 80 | {% for row in toGraph %} 81 | 82 | {% for cat in row %} 83 | 87 | {% endfor %} 88 | 89 | {% endfor %} 90 |
84 |

{{cat.name}}

85 | 86 |
91 |
92 | 93 |
94 | 95 | 96 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/catgraphs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Correlation Graphs for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

Correlation Graphs

10 | 11 |

Ratings for All Games

12 | 13 | 14 |
15 |

Ratings for Designers

16 | 17 | {% for row in dessToGraph %} 18 | 19 | {% for cat in row %} 20 | 24 | {% endfor %} 25 | 26 | {% endfor %} 27 |
21 |

{{cat.name}}

22 | 23 |
28 |
29 | 30 |
31 |

Ratings for Publishers

32 | 33 | {% for row in pubsToGraph %} 34 | 35 | {% for cat in row %} 36 | 40 | {% endfor %} 41 | 42 | {% endfor %} 43 |
37 |

{{cat.name}}

38 | 39 |
44 |
45 | 46 |
47 |

Ratings for Categories

48 | 49 | {% for row in catsToGraph %} 50 | 51 | {% for cat in row %} 52 | 56 | {% endfor %} 57 | 58 | {% endfor %} 59 |
53 |

{{cat}}

54 | 55 |
60 |
61 | 62 |
63 |

Ratings for Mechanics

64 | 65 | {% for row in mecsToGraph %} 66 | 67 | {% for cat in row %} 68 | 72 | {% endfor %} 73 | 74 | {% endfor %} 75 |
69 |

{{cat}}

70 | 71 |
76 |
77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/checklist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Collection Checklist for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | 9 | 10 | 11 | {% for row in rows %} 12 | 13 | {% endfor %} 14 | 15 |
{{row.name}} 
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/choose.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Extended Stats for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | 9 | {% include 'stats/geekwidget.html' %} 10 | {% include 'stats/navbar.html' %} 11 | 12 |
13 |

Dynamically Generated Page

14 | {{param}} 15 |
16 | 21 |

22 | {% for feature in contents %} 23 | {% include feature.htmlFile %} 24 | {% endfor %} 25 | 26 | 27 |

28 |
29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/collectiongames.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Edit Collection {{collection.name}} 5 | {% include 'stats/stylesheets.html' %} 6 | 15 | 16 | 17 | {% include 'stats/navbar.html' %} 18 |

Edit Collection {{collection.name}}

19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/collections.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Collections for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | 9 | {% include 'stats/navbar.html' %} 10 |

Collections for {{username}}

11 | 12 | These are the collections you've defined. 13 |

14 | 15 |

    16 | {% for coll in colls %} 17 |
  • {{coll.name}} 18 | {% if coll.deleteAllowed %}Delete{% endif %} 19 | Edit 20 | View 21 | {% if coll.groups %} 22 |
      23 | {% for group in coll.groups %} 24 |
    • {{group.name}} ({{group.count}}) 25 | {% endfor %} 26 |
    27 | {% endif %} 28 | {% endfor %} 29 |
30 |
31 | Create New Collection 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/consistency.html: -------------------------------------------------------------------------------- 1 |
2 |

Consistency of Play

3 | This is a prototype of a feature suggested by Martí Cabré. 4 |

5 | 6 | 7 | 8 | 9 | 10 | {% for game in consistencyData %} 11 | 12 | 13 | {% for cl in game.played %} 14 | {% if cl.clss %} 15 | 16 | {% else %} 17 | 18 | {% endif %} 19 | {% endfor %} 20 | 21 | {% endfor %} 22 | 23 |
GamePlaysRatingMonths PlayedFirst Played% Months Played
{{game.name}}{{game.plays}}{{game.rating}}{{game.monthsPlayed}}{{game.firstPlay}}{{game.propMonths}} 
24 |

25 | 26 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/consistency_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Consistency of Play for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |
11 | {% include 'stats/consistency.html' %} 12 |
13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/contents.html: -------------------------------------------------------------------------------- 1 |
2 |
    3 | {% include 'stats/contentslist.html' %} 4 |
5 |

6 | {% include 'stats/contentsbody.html' %} 7 |

8 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/contentsbody.html: -------------------------------------------------------------------------------- 1 | {% for feature in contents %} 2 | {% if feature.htmlFile %} 3 | {% include feature.htmlFile %} 4 | {% endif %} 5 | {% endfor %} -------------------------------------------------------------------------------- /extended/stats/templates/stats/contentslist.html: -------------------------------------------------------------------------------- 1 | {% for feature in contents %} 2 |
  • 3 | {% if feature.contentsFile %} 4 | {% include feature.contentsFile %} 5 | {% else %} 6 | {% if feature.tag %} 7 | {{feature.title}} 8 | {% else %} 9 | {{feature.title}} 10 | {% endif %} 11 | {% endif %} 12 | {% endfor %} 13 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/cookies.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Cookies 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

    Come to Extended Stats, We Have Cookies!

    10 | 11 |

    12 | These are the cookies that you sent to Extended Stats with this request:
    13 |
    {{cookies}}
    14 |

    15 | These are the options Extended Stats sees (this is really only interesting to Friendless): 16 |
    {{options}}
    17 |

    18 | By default cookies expire after a year. I'm not really sure what that means. 19 | 20 |

    21 |

    22 |
  • user name
    this is used when going from a page which doesn't know your name (like the Cookies page) to a page that does need to know it.
  • 23 |
  • width
    the width of most charts generated by Extended Stats - set it big if you have a big screen, small if you have a small screen.
  • 24 |
  • height
    similarly the height.
  • 25 |
    26 |

    27 |

    28 | {{ form.as_p }} 29 | 30 |
    31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/crazy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Crazy Recommendations for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |
    10 |

    Crazy Recommendations for {{username}}

    11 | 12 | The Crazy Recommendations algorithm assesses games based on whether they share various characteristics with games you rate 9 or higher. 13 | There is no popularity factor, so this algorithm avoids the fault of recommending Agricola and Puerto Rico to everyone. 14 | This listing includes games that are recommended but you've already rated, but not expansions or books. 15 | However there are 50 actual games listed for you that you neither own nor have rated - they're coloured black and are bold. 16 | If an entry really annoys you, you can rate the game a "Don't Buy This For Me" on your BGG wishlist, and it will no longer appear in the Crazy Recommendations when the changes are noticed. 17 |

    18 | 19 | 20 | 21 | 22 | 23 | 24 | {% for row in rows %} 25 | 26 | 27 | {% endfor %} 28 | 29 |
    GameScoreCategoriesMechanicsDesignersMin PlayersMax PlayersPlay TimeOwnedRatingPlays
    {{row.gamename}}{{row.total}}{{row.category}}{{row.mechanic}}{{row.designer}}{{row.minplayers}}{{row.maxplayers}}{{row.playtime}}{{row.owned}}{{row.rating}}{{row.plays}}
    30 | 31 |

    32 | 33 | 34 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/csrf.html: -------------------------------------------------------------------------------- 1 | 2 | Friendless has no idea what this means, but he's working on it. 3 |

    4 | {{reason}} 5 |

    6 | 7 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/dimesbydesigner.html: -------------------------------------------------------------------------------- 1 |

    2 |

    Dimes by Designer

    3 | These are all designers for which you've recorded 10 or more plays. 4 |

    5 | 6 | 7 | 8 | {% for row in designerDimes %} 9 | 10 | 11 | 16 | 17 | {% endfor %} 18 |
    DesignerTotal PlaysPlays of Base GamesPlays of ExpansionsDistinct TotalDistinct GamesDistinct ExpansionsGames
    {{row.name}}{{row.totalPlays}}{{row.baseGamePlays}}{{row.expansionPlays}}{{row.totalCount}}{{row.baseGameCount}}{{row.expansionCount}} 12 | {% for game in row.games %} 13 | {{game.plays}} plays of {{game.name}}{% if not forloop.last %}, {% endif %} 14 | {% endfor %} 15 |
    19 |

    20 | 21 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/dimesbydesigner_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Dimes by Designer for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |
    11 | {% include 'stats/dimesbydesigner.html' %} 12 |
    13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/favourites.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Your Favourite Games

    3 | 4 |
      5 |
    • The Friendless Happiness Metric (FHM) is (rating * 5 + plays + months played * 4 + hours played). 6 |
    • The Huber Happiness Metric is (HHM) ((rating - 4.5) * hours played). 7 |
    • The Huber Heat is described here. 8 |
    • The Randy Cox not-Unhappiness Metric (R!UHM) is described here. 9 |
    10 |

    11 | Your correlation with BGG ratings is {{bggCorrelation}}. 12 | Joe Huber points out that games with a small number of ratings bias this number upwards, as your contribution to the BGG average is relatively larger. 13 | Therefore, your correlation with BGG ratings for ranked (common) games only is {{bggCorrelationRankedOnly}}. 14 |

    15 | You H-index is {{hindex}} - you've played {{hindex}} games {{hindex}} times. 16 |

    17 | 18 | 19 | 20 | 21 | {% for row in favourites %} 22 | 23 | 24 | {% if row.rating %}{% else %}{% endif %} 25 | 26 | 27 | 28 | {% if row.firstPlay %}{% else %}{% endif %} 29 | {% if row.lastPlay %}{% else %}{% endif %} 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {% endfor %} 40 |
    GameRatingPlaysBGG RankingBGG RatingFirst PlayedLast PlayedMonths PlayedHours PlayedFHMHHMHuber HeatR!UHMPlays in last yearYear Published
    {{row.gamename}}{{row.rating}} {{row.plays}}{{row.bggrank}}{{row.bggavg}}{{row.firstPlay|date:"d-m-Y"}} {{row.lastPlay|date:"d-m-Y"}} {{row.monthsPlayed}}{{row.hours}}{{row.fave}}{{row.huber}}{{row.huberHeat}}{{row.randyCox}}{{row.playsInLastYear}}{{row.year}}
    41 |

    42 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/favourites2.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Your Favourite Games

    3 | 4 |
      5 |
    • The Friendless Happiness Metric (FHM) is (rating * 5 + plays + months played * 4 + hours played). 6 |
    • The Huber Happiness Metric is (HHM) ((rating - 4.5) * hours played). 7 |
    • The Randy Cox not-Unhappiness Metric (RC!UHM) is described here. 8 |
    9 |

    10 | Your correlation with BGG ratings is {{bggCorrelation}}. 11 | Joe Huber points out that games with a small number of ratings bias this number upwards, as your contribution to the BGG average is relatively larger. 12 | Therefore, your correlation with BGG ratings for ranked (common) games only is {{bggCorrelationRankedOnly}}. 13 |

    14 | You H-index is {{hindex}} - you've played {{hindex}} games {{hindex}} times. 15 |

    16 | 17 | 18 | 19 | {% for row in favourites %} 20 | 21 | 22 | {% if row.rating %}{% else %}{% endif %} 23 | 24 | {% if row.firstPlay %}{% else %}{% endif %} 25 | {% if row.lastPlay %}{% else %}{% endif %} 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | {% endfor %} 35 |
    GameRatingPlaysFirst PlayedLast PlayedMonths PlayedFlashLagFLMRLogRC!UHMYear Published
    {{row.gamename}}{{row.rating}} {{row.plays}}{{row.firstPlay|date:"d-m-Y"}} {{row.lastPlay|date:"d-m-Y"}} {{row.monthsPlayed}}{{row.flash}}{{row.lag}}{{row.flmr}}{{row.log}}{{row.randyCox}}{{row.year}}
    36 |

    37 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/favourites2_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Favourite Games for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |
    11 | {% include 'stats/favourites2.html' %} 12 |
    13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/favourites_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Favourite Games for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

    Your Favourite Games

    10 | 11 | Your correlation with BGG ratings is {{bggCorrelation}}. 12 | Joe Huber points out that games with a small number of ratings bias this number upwards, as your contribution to the BGG average is relatively larger. 13 | Therefore, your correlation with BGG ratings for ranked (common) games only is {{bggCorrelationRankedOnly}}. 14 |

    15 | You H-index is {{hindex}} - you've played {{hindex}} games {{hindex}} times. 16 |

    17 | 18 |

    19 | {% include 'stats/genericgamestable.html' %} 20 |
    21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/featurelist.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Feature Index

    3 | In Extended Stats lingo, a feature is a table or other item that can be displayed by itself. 4 | This is an automatically generated index of the simple features (complex features require parameters for which there are no defaults). 5 |

    6 |

      7 | {% for row in features %} 8 |
    • {{row.title}} 9 | {% endfor %} 10 |
    11 |
    12 | 13 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/featurelist_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Feature Index for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |
    11 | {% include 'stats/featurelist.html' %} 12 |
    13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/fgbpy.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Favourite Games by Published Year

    3 | 4 | 5 | 6 | 7 | {% for row in fgbpy %} 8 | 9 | 14 | {% endfor %} 15 |
    YearCountGames
    {{row.year}}{{row.count}} 10 | {% for game in row.games %} 11 | {{game.name}}   12 | {% endfor %} 13 |
    16 | These are all games you rate 8 or higher, grouped by year. 17 |
    18 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/florence.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Florence Nightingale Gamer Characterisation

    3 | 4 |
    5 | 6 | 7 | {% for year in playsYears %} 8 | 9 | {% endfor %} 10 | 11 |
    12 | 13 |
    14 | This diagram is inspired by Florence Nightingale's Polar Area Diagrams. 15 | The area of each colour is proportional to the number of games you have played with that BGG subdomain. 16 | Looking at this diagram, people can see at a glance what sort of, and how many, games you play. 17 |

    18 | Click on the buttons above to change the range of data displayed. 19 |

    20 | 21 | 22 | 23 | {% for flo in florence %} 24 | 25 | {% endfor %} 26 |
     {{flo.name}}
    27 |
    28 |
    29 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/fpvr.html: -------------------------------------------------------------------------------- 1 |
    2 |

    First Played vs Rating

    3 | 4 | 5 |

    6 | The theory behind this graph is that over time gamers become curmudgeonly, liking new titles less and less. This is a graph of the date you first played a game, against the rating you currently give it. The alternate theory is that when you first joined BGG you found the titles you would like, and it had all been downhill since then. 7 |

    8 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/front_page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | BGG Extended Stats 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | 9 | {% include 'stats/navbar.html' %} 10 | 11 |

    BGG Extended Stats

    12 |

    13 | Addition to stats.drfriendless.com has been suspended since January 2018. 14 | Since the end of 2018 there is a new site running at https://extstats.drfriendless.com. 15 | New users are being added to that site. 16 | It has less functionality than this site, but I'm working on that. 17 | To see if you've been added, go to https://extstats.drfriendless.com/ and use the Where's My Page widget to get a link. 18 | Follow the blog at https://blog.drfriendless.com for excruciating detail. 19 |

    20 |
    21 | 22 |
    23 |

    The War Table

    24 | 25 | Let's admit it - we all want to be at the top of the list. 26 | You can sort by different columns to see if you can get yourself there. 27 | When I compare myself to these guys I'm happy just to make the first page. 28 | Jim Carvin suggested the Previously Owned ranking because he thought he could be at the top of it. 29 |

    30 | The User column links to your personal page. Tooltips on the numeric columns show your rank for that particular statistic. 31 |

    32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {% for row in playsData %} 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {% endfor %} 60 | 61 |
    UserTotal PlaysDistinct GamesOwnedWant in TradeWishlistFor TradeSpiel des JahreBGG Top 50Extended Stats Top 100Most VotersPreviously OwnedFriendlessCFM0s10sH-Index
    {{row.geek}}{{row.totalPlays}}{{row.distinctGames}}{{row.owned}}{{row.want}}{{row.wish}}{{row.trade}}{{row.sdj}}{{row.top50}}{{row.ext100}}{{row.mv}}{{row.prevOwned}}{{row.friendless}}{{row.cfm}}{{row.zeros}}{{row.tens}}{{row.hindex}}
    62 |

    63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/geek_error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Error 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

    10 | That user doesn't seem to be in Extended Stats. Make sure you have the case exactly right, and use %20 in the URL instead of spaces. 11 |

    12 | If you're not in Extended Stats and you'd like to be, please email Friendless (friendless.farrell@gmail.com) and ask to be added. 13 | You just need to tell him your BGG user ID. 14 | The list of current users is stored in the cloud so you can see whether you've been added yet. 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/geekwidget.html: -------------------------------------------------------------------------------- 1 | 2 |

    3 | 4 | 5 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/generic_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Games for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |

    11 | {% include 'stats/genericgamestable.html' %} 12 |
    13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/gini.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 4 | The Gini Coefficient is a measure of inequality. 5 | In this case, it's a matter of how unequally you play your board games. 6 | This feature was suggested by megamau. 7 |

    8 | This feature is not finished yet. 9 | 10 | {% for gd in giniData %} 11 | 12 |

    Gini Coefficient for {{gd.name}}

    13 | 14 | Your Gini Coefficient is {{gd.coefficient}}. 15 | 16 | 17 | 18 | 19 | {% for row in gd.map %} 20 | {{row.title}} 21 | {% endfor %} 22 | 23 | 24 | {% endfor %} 25 | 26 |
    27 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/gini_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Gini Coefficient Data for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

    Gini Coefficient Data

    10 | 11 |
    12 | {% include 'stats/gini.html' %} 13 |
    14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/history_error.html: -------------------------------------------------------------------------------- 1 | 2 | Error 3 | 4 | User {{geek}} doesn't seem to be in Extended Stats. 5 | 6 | 7 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/imgmaptooltip.html: -------------------------------------------------------------------------------- 1 | 40 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/ipod_geek_error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Error 5 | {% include 'stats/ipod_stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/ipod_navbar.html' %} 9 | 10 | User {{username}} doesn't seem to be in Extended Stats. Make sure you have the case exactly right, and use %20 in the URL instead of spaces. 11 | 12 | 13 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/ipod_main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Extended Stats for {{geek.username}} 4 | {% include 'stats/ipod_stylesheets.html' %} 5 | 6 | 7 | 8 | 9 |
    10 |

    {{geek.username}}

    11 | 12 | 19 |
    20 | 21 |
    22 |

    Favourites

    Back
    23 | 24 |
      25 | {% for row in favourites %} 26 |
    • {{row.bggrank}}. {{row.gamename}}

      27 |

      {{row.plays}} plays in {{row.monthsPlayed}} months
      28 | First: {{row.firstPlay}}, last: {{row.lastPlay}}

      29 |

      {{row.hours}} hours played

      30 | {% endfor %} 31 |
    32 | 33 |
    34 | 35 |
    36 |

    Play Soon

    Back
    37 | 38 |
      39 | {% for row in shouldPlayOwn %} 40 |
    • {{row.gamename}}

      41 |

      Rated {{row.rating}}

      42 |

      Last {{row.lastPlayed}}, {{row.sincePlayed}} days ago

      43 | {% endfor %} 44 |
    45 | 46 |
    47 | 48 |
    49 |

    Plays YTD

    Back
    50 | 51 |
      52 | {% for row in pbm %} 53 |
    • {{row.name}}

      54 |

      {{row.count}} plays of {{row.distinctCount}} games,
      {{row.newNickels}} new nickels, {{row.newDimes}} new dimes

      55 |

      Tally: {{row.countYtd}} plays, {{row.distinctYtd}} games, {{row.newYtd}} new

      56 | {% endfor %} 57 |
    58 | 59 |
    60 | 61 |
    62 |

    Plays Ever

    Back
    63 | 64 |
      65 | {% for row in pbm %} 66 |
    • {{row.name}}

      67 |

      {{row.newNickelsEver}} nickels, {{row.newDimesEver}} dimes, {{row.newQuartersEver}} quarters
      68 | {{row.percentPlayed|floatformat}}% of collection played

      69 |

      Tally: {{row.playsEver}} plays, {{row.distinctEver}} games

      70 | {% endfor %} 71 |
    72 | 73 |
    74 | 75 |
    76 |

    Owned Plays

    Back
    77 | 78 |
      79 | {% for row in pogo %} 80 |
    • {{row.rank}}. {{row.name}}

      81 |

      {{row.plays}} plays, rated {{row.rating}}
      82 | {{row.utilisation}}% utilisation

      83 |

      84 | {% endfor %} 85 |
    86 | 87 |
    88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/ipod_navbar.html: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/ipod_stylesheets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/lag.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Lag Between Publication and Playing

    3 | 4 | 5 |

    6 | Do you play new games, or do you play old games? In particular, how many years elapse between a game's release and you playing it? This is a histogram of the number of calendar years between a game's release and your first play of it. The vertical axis is number of games, the horizontal axis is number of years. The percentages across the top are the accumulated percentage of games you play within that many years of it being released. 7 |

    8 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/lbr.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Lifetimes of Games by Rating

    3 | 4 | 5 |

    6 | This graph is similar to the previous one, but contains only games you've played on two or more different days and you've rated. In this case, the line for the game is coloured according to the rating you gave it, using the BGG colours for those ratings. 7 |

    8 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/least.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Why Do You Even Own These Games?

    3 | These are your least loved games, judging from the poor rating you give them and the time since you've played them. 4 |

    5 | 6 | 7 | 8 | {% for row in least %} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% endfor %} 17 |
    GameRatingLast PlayedDays Since Last PlayFor Trade
    {{row.name}}{{row.rating}}{{row.lastPlay|date:"d-m-Y"}}{{row.daysSince}}{% if row.trade %}Yes{% endif %}
    18 |

    19 | 20 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/lifetime.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Lifetimes of Games

    3 | 4 | 5 |

    6 | What's the lifetime of a game? How long does it remain in play rotation for? This graph shows, for each game you've ever played on two different days, what the timespans between the first and last plays of that game were. The timespans are capped at 10 years - that's "forever" for my purposes. The black dot on the line is a guess at the age of the game, i.e. no lifetime can go past that because the game hasn't been released that long. 7 |

    8 | Each horizontal block represents one game. The colours are: 9 |

      10 |
    • green - game you own 11 |
    • pink - a game you don't own 12 |
    • yellow - an expansion you own 13 |
    • blue - an expansion you don't own 14 |
    15 |
    16 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | List 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

    {{title}}

    10 | 11 | {% for x in items %} 12 | {{x}}
    13 | {% endfor %} 14 | 15 | 16 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/locations.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 5 | 6 | {% for loc in locations %} 7 | {% for game in loc.games %} 8 | 9 | {% if game.first %} 10 | 11 | 12 | {% endif %} 13 | 14 | 18 | 21 | 22 | {% endfor %} 23 | {% endfor %} 24 | 25 |
    LocationPlays#GameDates
    {{loc.location}}{{loc.count}}{{game.count}} 15 | {% if game.first %}
    {% endif %} 16 | {{game.game.name}} 17 |
    19 | {% for date in game.dates %}{{date.name}} {% endfor %} 20 |
    26 | 27 |
    28 | 29 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/locations_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Play Locations for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | 9 | {% include 'stats/geekwidget.html' %} 10 | {% include 'stats/navbar.html' %} 11 |

    Play Locations for {{username}}

    12 | 13 | This page was Almecho's idea! The row colouring is way too complicated for me to figure out at the moment. 14 | 15 |
    16 | 17 | 18 | 19 | 20 | {% for loc in locations %} 21 | {% for game in loc.games %} 22 | 23 | {% if game.first %} 24 | 25 | 26 | {% endif %} 27 | 28 | 32 | 35 | 36 | {% endfor %} 37 | {% endfor %} 38 | 39 |
    LocationPlays#GameDates
    {{loc.location}}{{loc.count}}{{game.count}} 29 | {% if game.first %}
    {% endif %} 30 | {{game.game.name}} 31 |
    33 | {% for date in game.dates %}{{date.name}} {% endfor %} 34 |
    40 | 41 |
    42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/message.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Message 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 | {{content}} 11 | 12 | 13 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/morepie.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Mike Hulsebus-style Pie Chart

    3 | 4 |
    5 | 6 | 7 | {% for year in playsYears %} 8 | 9 | {% endfor %} 10 | 11 |
    12 | 13 |
    14 | This diagram is inspired by a BGG blog entry by Mike Hulsebus. 15 | Each wedge of the pie chart represents the proportion of your plays in the period which have been of a particular game. 16 |

    17 | Click on the buttons above to change the range of data displayed. 18 |

    19 | 20 |
    21 |
    22 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/morgan.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Pie Charts for Morgan

    3 | 4 | Morgan Dontanville requested pie charts. Here are some. 5 | 6 |

    7 | The colours used in these pie charts match the colours Aldie assigns to game ratings on BGG. Non-integer ratings are rounded to the nearest. 8 |

    9 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/mostunplayed.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Most Played Games That You Haven't Played

    3 | 4 | These are the games that have been played most by other people that you haven't played at all. 5 |

    6 | 7 | 8 | 9 | {% for row in mostUnplayed %} 10 | 11 | 12 | 13 | 14 | {% endfor %} 15 |
    GamePlays
    {{row.name}}{{row.totalPlays}}
    16 |

    17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/mpct.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Most Played Cumulative Timeline

    3 | 4 | 5 |

    6 | This is a graph of your cumulative number of plays for each of your 20 most played games over the last 12 years or so. 7 |

    8 | 9 | {% for mpct in mpctData %} 10 | 11 | {% endfor %} 12 |
      {{mpct.name}}
    13 |

    14 | Invented by tom-le-termite. 15 |

    16 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/multiyear.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Games Played In Multiple Years

    3 | 4 | 5 | 6 | {% for year in myyears %} 7 | 8 | {% endfor %} 9 | 10 | 11 | {% for row in multiyear %} 12 | 13 | {% for item in row %} 14 | 15 | {% endfor %} 16 | 17 | {% endfor %} 18 |
    Game{{year}}
    {{item.value}}
    19 |
    20 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/multiyear_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Games Played in Multiple Years for {{geek.username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |
    11 | {% include 'stats/multiyear.html' %} 12 |
    13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/navbar.html: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/new.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Rate of Play of Games New To You

    3 | 4 | 5 |

    6 | This graph shows, across the last few years, how fast you learn new games. The black lines (dots) are the number of new games learned in that year, and the blue line (triangles) is the number of new games learned since the beginning of the graph. The scale for the black lines is on the left hand axis, the scale for the blue line is on the right hand axis. Thanks to Randy Cox for the data presentation design. 7 |

    8 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/newCollection.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Create New Collection 5 | {% include 'stats/stylesheets.html' %} 6 | 38 | 39 | 40 | {% include 'stats/navbar.html' %} 41 |

    Edit Collection

    42 | 43 | On this page you can edit the description of the collection and the groups in it. 44 | If you remove groups containing games, those games will be lost from the collection. 45 | Nothing in collections affects anything on BoardGameGeek. 46 | 47 |
    48 |

    Collection Details

    49 |

    50 | Name:
    51 | Description:

    52 |
    53 |
    54 |

    55 |

    Groups

    56 | 57 | {% for group in groups %} 58 | 63 | {% endfor %} 64 |
    59 | Group Name:
    60 | Description:
    61 | 62 |
    65 |

    66 |
    67 | 68 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/nickeldime.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Nickel and Dime

    3 | 4 | {% if ndd.dollars %} 5 |

    Dollars

    6 | 7 | 8 | 9 | 10 | 11 | {% for row in ndd.dollars %} 12 | 13 | 14 | {% endfor %} 15 | 16 |
    PlaysGame
    {{row.plays}}{{row.name}}
    17 | {% endif %} 18 | 19 | {% if ndd.halfdollars %} 20 |

    Half-Dollars

    21 | 22 | 23 | 24 | 25 | 26 | {% for row in ndd.halfdollars %} 27 | 28 | 29 | {% endfor %} 30 | 31 |
    PlaysGame
    {{row.plays}}{{row.name}}
    32 | {% endif %} 33 | 34 | {% if ndd.quarters %} 35 |

    Quarters

    36 | 37 | 38 | 39 | 40 | 41 | {% for row in ndd.quarters %} 42 | 43 | 44 | {% endfor %} 45 | 46 |
    PlaysGame
    {{row.plays}}{{row.name}}
    47 | {% endif %} 48 | 49 | {% if ndd.dimes %} 50 |

    Dimes

    51 | 52 | 53 | 54 | 55 | 56 | {% for row in ndd.dimes %} 57 | 58 | 59 | {% endfor %} 60 | 61 |
    PlaysGame
    {{row.plays}}{{row.name}}
    62 | {% endif %} 63 | 64 | {% if ndd.nickels %} 65 |

    Nickels

    66 | 67 | 68 | 69 | 70 | 71 | {% for row in ndd.nickels %} 72 | 73 | 74 | {% endfor %} 75 | 76 |
    PlaysGame
    {{row.plays}}{{row.name}}
    77 | {% endif %} 78 | 79 | {% if ndd.nearly %} 80 |

    Nearly a Nickel

    81 | 82 | 83 | 84 | 85 | 86 | {% for row in ndd.nearly %} 87 | 88 | 89 | {% endfor %} 90 | 91 |
    PlaysGame
    {{row.plays}}{{row.name}}
    92 | {% endif %} 93 | 94 |
    95 | 96 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/normrankings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | BGG Extended Stats Normalised Rankings 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |

    11 | {% for c in categories %} 12 | {{c}} 13 | {% endfor %} 14 |

    15 | {% for c in mechanics %} 16 | {{c}} 17 | {% endfor %} 18 | 19 |

    20 |

    Normalised Rankings

    21 | The Normalised Ranking column is a different calculation of rankings. 22 | For each user, games are ordered in descending order of rating. The user's top-rated games all score 1.0. 23 | All other games score (c - n) / c where c is the user's number of rated games, and n is the number of games rated strictly higher by that user. 24 | This ranking consequently treats BGG ratings as relative values and places less emphasis on the actual value of those ratings. 25 | Note however that each user rating a game does contribute to its total, so the ranking does reward popularity. 26 |

    27 | 28 | 29 | 30 | 31 | {% for row in data %} 32 | 33 | 34 | 35 | 36 | 37 | 38 | {% endfor %} 39 |
    RankingGameBGG RankingBGG Rating
    {{row.normrank}}{{row.name}}{{row.rank}}{{row.average}}
    40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/numplayers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Favourite Games for Number of Players for {{geek.username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

    10 |

    Favourite Games for Number of Players

    11 | 12 | These tables are based on the BGG polls for best and recommended numbers of players. A game only makes it to a list if it is best or recommended for more votes than it is not recommended. I'm not sure how well that actually works. Scrabble, which is easily best with 2 players, is still recommended for 3 and 4 players. As an experienced player, I don't agree, but who am I to argue with the Wisdom of Crowds? Please discuss this problem on the Extended Stats mailing list. 13 |

    14 | 15 |

    For One Player

    16 | 17 | 18 | 19 | 20 | 21 | {% for row in data.0 %} 22 | 23 | 24 | {% endfor %} 25 | 26 |
    GameRating
    {{row.name}}{{row.rating}}
    27 | 28 |

    For Two Players

    29 | 30 | 31 | 32 | 33 | 34 | {% for row in data.1 %} 35 | 36 | 37 | {% endfor %} 38 | 39 |
    GameRating
    {{row.name}}{{row.rating}}
    40 | 41 |

    For Three Players

    42 | 43 | 44 | 45 | 46 | 47 | {% for row in data.2 %} 48 | 49 | 50 | {% endfor %} 51 | 52 |
    GameRating
    {{row.name}}{{row.rating}}
    53 | 54 |

    For Four Players

    55 | 56 | 57 | 58 | 59 | 60 | {% for row in data.3 %} 61 | 62 | 63 | {% endfor %} 64 | 65 |
    GameRating
    {{row.name}}{{row.rating}}
    66 | 67 |

    For Five Players

    68 | 69 | 70 | 71 | 72 | 73 | {% for row in data.4 %} 74 | 75 | 76 | {% endfor %} 77 | 78 |
    GameRating
    {{row.name}}{{row.rating}}
    79 | 80 |

    For Six Players

    81 | 82 | 83 | 84 | 85 | 86 | {% for row in data.5 %} 87 | 88 | 89 | {% endfor %} 90 | 91 |
    GameRating
    {{row.name}}{{row.rating}}
    92 | 93 |

    For Seven or More Players

    94 | 95 | 96 | 97 | 98 | 99 | {% for row in data.6 %} 100 | 101 | 102 | {% endfor %} 103 | 104 |
    GameRating
    {{row.name}}{{row.rating}}
    105 | 106 |
    107 | 108 | 109 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/obpy.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Games Owned by Published Year

    3 | 4 | 5 | 6 | 7 | {% for row in obpymap %} 8 | 11 | {% endfor %} 12 | 13 |

    14 | When it comes to liking games from a particular year, do you put your money where your mouth is? How many games from each year do you actually own? White boxes represent unrated games that you own. 15 |

    16 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/pbm.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/pbmever.html: -------------------------------------------------------------------------------- 1 | {% if pbm %} 2 |
    3 |

    Plays By Month (Ever)

    4 | 5 | The month column links to a summary of plays for the month. The "percent played" number refers to the percentage of your current collection that you had ever played at that time. 6 |

    7 | 8 | 9 | 10 | {% for row in pbm %} 11 | {% if row.january %} 12 | 13 | {% else %} 14 | 15 | {% endif %} 16 | 17 | {% endfor %} 18 |
    MonthPlaysNew NickelsNew DimesNew QuartersNew DollarsPlays EverDistinct EverH-Index YTDH-Index EverPercent PlayedDays Played On
    {{row.name}}{{row.count}}{{row.newNickelsEver}}{{row.newDimesEver}}{{row.newQuartersEver}}{{row.newDollarsEver}}{{row.playsEver}}{{row.distinctEver}}{{row.hindexToDate}}{{row.hindexEver}}{{row.percentPlayed|floatformat}}{{row.daysPlayed}}
    19 |

    20 | {% endif %} 21 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/pbmgraph.html: -------------------------------------------------------------------------------- 1 | {% if pbm %} 2 |

    Plays By Month

    3 | 4 |
    5 | This graph shows your plays in each month over time. The number of plays of new games are shown as red, the number of plays of distinct games are shown as blue, and the total number of plays is shown as green. If your gaming history is too long and your graph is too wide, you can drag it to scroll to the right. 6 | 7 |
    8 | 9 |
    10 | 11 | 42 |
    43 | {% endif %} 44 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/pbmytd.html: -------------------------------------------------------------------------------- 1 | {% if pbm %} 2 |
    3 |

    Plays By Month (Year to Date)

    4 | 5 | The month column links to all plays for the month. The "percent played" number refers to the percentage of your current collection that you had played in that year by that time. 6 |

    7 | 8 | 9 | 10 | {% for row in pbm %} 11 | {% if row.january %} 12 | 13 | {% else %} 14 | 15 | {% endif %} 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% endfor %} 23 |
    MonthPlaysDistinct GamesExpansionsNew GamesNew NickelsNew DimesHours PlayedPlays YTDDistinct YTDNew YTDH-IndexPercent Played
    {{row.name}}{{row.count}}{{row.distinctCount}}{{row.expCount}}{{row.newCount}}{{row.newNickels}}{{row.newDimes}}{{row.playHours}}{{row.countYtd}}{{row.distinctYtd}}{{row.newYtd}}{{row.hindex}}{{row.percentPlayedYTD|floatformat}}
    24 |

    25 | {% endif %} 26 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/pbpy.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Plays of Games Owned by Published Year

    3 | 4 | 5 | 6 | 7 | {% for row in pbpymap %} 8 | 11 | {% endfor %} 12 | 13 |

    14 | This was an idea from Almecho. White spaces indicate games with no plays, red indicates one play, and the darkest green indicates 25+ plays. The games displayed here are the same games displayed in the Plays of Games Owned table (i.e. this graph uses the cookies for that graph). 15 |

    16 |

    17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/pbq.html: -------------------------------------------------------------------------------- 1 |
    2 |

    How Much Do You Play New Releases?

    3 | 4 | 5 |

    6 | This graph shows for each quarter, what year the games you played in that quarter were released in. This shows you how you play new games and abandon old ones. 7 |

    8 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/pby.html: -------------------------------------------------------------------------------- 1 | {% if pbyData %} 2 |
    3 |

    Plays By Year

    4 | 5 |

    6 | 7 | 8 | 9 | {% for row in pbyData %} 10 | 11 | {% endfor %} 12 |
    YearTotal PlaysDifferent GamesNew GamesHours PlayedDays Played OnNickelsDimesQuartersDollars
    {{row.year}}{{row.totalPlays}}{{row.distinctGames}}{{row.newGames}}{{row.playHours}}{{row.daysPlayedOn}}{{row.nickels}}{{row.dimes}}{{row.quarters}}{{row.dollars}}
    13 |

    14 | {% endif %} 15 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/playedlastyear.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Played More Than Once Last Year But Not This Year

    3 | 4 | 5 | 6 | 7 | 8 | 9 | {% for row in playedLastYear %} 10 | 11 | 12 | {% endfor %} 13 | 14 |
    PlaysGame
    {{row.plays}}{{row.name}}
    15 | 16 |
    17 | 18 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/playlogging.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Dazeysan's Splendiferous Play-Logging Utility

    3 | 4 | kataclysm and Dazeysan have done some work on hacking the BGG play-logging utility to be customisable to include your frequently used locations and opponents. I've added some support for extracting the data that utility will use from your logged plays. 5 | 6 | The step by step instructions are in this geeklist. 7 | 8 |

    Cut and Paste

    9 | Copy and paste this text into the play logging widget:
    10 | 13 | 14 |
    15 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/playlogging_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Data for Play Logging for {{geek.username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |
    11 | {% include 'stats/playlogging.html' %} 12 |
    13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/playrate.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Plays by Rating

    3 | 4 | 5 | 6 | {% for row in prmap %} 7 | 10 | {% endfor %} 11 | 12 |

    13 | This scatter plot relates the number of times you've played a game compared to the rating you gave it. 14 | Ideally we'd all always play 10s, but since that's not going to happen we can at least hope that the more 15 | we like a game the more we play it. The size of a circle corresponds to the number of games with that 16 | rating and that many plays. The number of plays is capped at 25 so the graph doesn't need to be 17 | infinitely tall. The green line across the graph is your average number of plays for games with that 18 | rating. The numbers used for that average are also capped at 25. 19 |

    20 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/playrate_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Play Rate Graph for {{username}} for {{selector}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |
    11 | {% include 'stats/playrate.html' %} 12 |
    13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/playrateown.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Plays by Rating for Games that You Own

    3 | 4 | 5 | 6 | {% for row in promap %} 7 | 10 | {% endfor %} 11 | 12 |

    13 | This graph is the same as the previous one, but only games that you own are counted. 14 |

    15 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/playrateprev.html: -------------------------------------------------------------------------------- 1 |
    2 | {% if prevmap %} 3 |

    Plays by Rating for Games that You Previously Owned

    4 | 5 | 6 | 7 | {% for row in prevmap %} 8 | 11 | {% endfor %} 12 | 13 | {% endif %} 14 |

    15 | This graph is the same as the previous one, but only games that you previously owned and don't currently own are counted. 16 |

    17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/plays.csv: -------------------------------------------------------------------------------- 1 | Game Name,BGG ID,Date,Count 2 | {% for play in plays %}{{play.game.name}},{{play.game.bggid}},{{play.date}},{{play.count}} 3 | {% endfor %} -------------------------------------------------------------------------------- /extended/stats/templates/stats/plays.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Plays for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |

    Plays for {{username}}

    11 | 12 | {% for link in links %} 13 | {{link.name}} 14 | {% endfor %} 15 |

    16 | 17 |

    18 | 19 | {% for play in plays %} 20 | 21 | {% endfor %} 22 |
    DateGameQuantityRatingExpansions
    {{play.date}}{{play.gamename}}{{play.count}}{{play.rating}}{{play.expansionNames}}
    23 |
    24 | 25 | {% for message in messages %} 26 | {{message}}
    27 | {% endfor %} 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/playsByRanking.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |

    Plays By Ranking

    4 | This table was suggested by vader78. 5 | This table has one cell for each game in the BGG rankings. 6 | If you have played that game, the cell is coloured according to the number of plays you have recorded - white for zero, red for 1, progressing through yellow and green to dark green for 25+. 7 | Most cells have tooltips telling you what the game at that rank is. 8 | There can be anomalies as the download process can observe different games at the same rank at different times - the BGG rankings may differ from the data used to calculate this table. 9 |

    10 | There's a tooltip on the row header summarising your feelings on the games. 11 | Due to the observation errors mentioned above, some rows won't have exactly 100 games. 12 |

    13 | 14 | 15 | {% for row in playsByRanking %} 16 | 17 | {% for datum in row.data %} 18 | {% if datum %} 19 | 20 | {% else %} 21 | 22 | {% endif %} 23 | {% endfor %} 24 | 25 | {% endfor %} 26 |
    {{row.base}}  
    27 | 28 |

    29 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/playsbyrating.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/pogotable.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Plays of Games Owned Table

    3 |

    4 | 5 | 6 | 7 | {% for row in pogo %} 8 | 9 | {% endfor %} 10 |
    GamePlaysBGG RankBGG RatingYour RatingUsers RatingUtilisation
    {{row.name}}{{row.plays}}{{row.rank}}{{row.average|floatformat:"1"}}{{row.rating}}{{row.usersrated}}{{row.utilisation}}%
    11 |

    -------------------------------------------------------------------------------- /extended/stats/templates/stats/pretitle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/rankings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | BGG Extended Stats Rankings for {{title}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |

    11 | All 12 |

    13 | {% for c in categories %} 14 | {{c}} 15 | {% endfor %} 16 |

    17 | {% for c in mechanics %} 18 | {{c}} 19 | {% endfor %} 20 | 21 |

    22 |

    Rankings for {{title}}

    23 | These rankings are calculated quite simply - I just total up the ratings given to all games by the Extended Stats users. This results in a nice combination of hot games and classic games. This is maybe more in line with what new board gamers will expect to see as a list of top-ranked games than the BGG system which tends to favour heavy Euros. 24 |

    25 | The Normalised Ranking column is a different calculation of rankings. For each user, games are ordered in descending order of rating. The user's top-rated games all score 1.0. All other games score (c - n) / c where c is the user's number of rated games, and n is the number of games rated strictly higher by that user. This ranking consequently treats BGG ratings as relative values and places less emphasis on the actual value of those ratings. Note however that each user rating a game does contribute to its total, so the ranking does reward popularity. 26 |

    27 | 28 | 29 | 30 | 31 | {% for row in data %} 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | {% endfor %} 43 |
    RankingGameScoreNum. RatingsBGG RankingBGG RatingNormalised RankingTotal Plays
    {{row.extrank}}{{row.name}}{{row.score}}{{row.count}}{{row.rank}}{{row.average}}{{row.normrank}}{{row.totalPlays}}
    44 | 45 | 46 |

    47 | This is some text which is easy to copy and paste into BGG: 48 |

    49 | Rankings for {{title}}
    50 | 
    51 | {% for row in data %}{{row.extrank}}. {{row.name}}
    52 | {% endfor %}
    53 | 
    54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/ratedplays.html: -------------------------------------------------------------------------------- 1 | {% if playRatings %} 2 |
    3 | 4 |

    Ratings of Plays

    5 | 6 | This section is for people who gather ratings for each play from the players. For all plays of each game, I count how many ratings have been given, and what the total of those ratings is (a useful combination of popularity and high rating). The average is exactly the mean of those two. 7 | 8 | 9 | 10 | 11 | {% for row in playRatings %} 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% endfor %} 19 |
    GamePlaysUsers RatingTotal RatingAverage Rating
    {{row.name}}{{row.count}}{{row.raters}}{{row.total}}{{row.average}}
    20 | 21 |
    22 | {% endif %} -------------------------------------------------------------------------------- /extended/stats/templates/stats/ratingbyranking.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |

    Rating By Ranking

    4 | This table has one cell for each game in the BGG rankings. 5 | If you have rated that game, the cell is coloured with the BGG colour for that rating. This lets you see highly ranked games you don't like, and lowly rated games you do like. 6 | Most cells have tooltips telling you what the game at that rank is. 7 | There can be anomalies as the download process can observe different games at the same rank at different times - the BGG rankings may differ from the data used to calculate this table. 8 |

    9 | There's a tooltip on the row header summarising your feelings on the games. 10 | Due to the observation errors mentioned above, some rows won't have exactly 100 games. 11 |

    12 | 13 | 14 | {% for row in ratingByRanking %} 15 | 16 | {% for datum in row.data %} 17 | {% if datum %} 18 | 19 | {% else %} 20 | 21 | {% endif %} 22 | {% endfor %} 23 | 24 | {% endfor %} 25 |
    {{row.base}}  
    26 | 27 |

    28 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/rbpy.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Ratings by Published Year

    3 | 4 | 5 | 6 | 7 | {% for row in rbpymap %} 8 | 11 | {% endfor %} 12 | 13 |

    14 | Do you like the old games better than the new games? 15 | This image goes back to 1995 or the year that you've said your games start from in the cookies. 16 | The numbers at the top of the image are the number of games from that year that you've rated. 17 |

    18 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/refresh.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Refresh Done 4 | 5 | 6 | Done! The chosen files will be refreshed soon, which means when the downloading program gets to it. 7 | That's often as soon as 10 minutes, but can be much longer if it has a lot of work to do. 8 | 9 | {{errors}} 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/result_tabbed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Extended Stats for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/geekwidget.html' %} 9 | {% include 'stats/navbar.html' %} 10 |

    Extended Stats for {{username}}

    11 | 12 | {% include 'stats/tabs.html' %} 13 | 14 | {% if tab7 %} 15 | {% else %} 16 |

    Contents

    17 | {% endif %} 18 | 19 | {% if tab1 %} 20 | {% include 'stats/tab1.html' %} 21 | {% endif %} 22 | 23 | {% if tab2 %} 24 | {% include 'stats/contents.html' %} 25 | {% endif %} 26 | 27 | {% if tab3 %} 28 | {% include 'stats/tab3.html' %} 29 | {% endif %} 30 | 31 | {% if tab4 %} 32 | {% include 'stats/tab4.html' %} 33 | {% endif %} 34 | 35 | {% if tab5 %} 36 | {% include 'stats/tab5.html' %} 37 | {% endif %} 38 | 39 | {% if tab6 %} 40 | {% include 'stats/userfaves.html' %} 41 | {% endif %} 42 | 43 | {% if tab7 %} 44 | {% include 'stats/featurelist.html' %} 45 | {% endif %} 46 | 47 |

    48 | {% include 'stats/tabs.html' %} 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/series.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Series Summaries for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

    10 |

    Series Summaries for {{username}}

    11 | 12 |

    Contents

    13 | 14 | 15 | 16 | {% for serie in series %} 17 | 18 | 19 | 20 | {% endfor %} 21 | 22 |
    NameRatedOwnedTotal RatingMean Rating
    {{serie.name}}{{serie.count}}{{serie.owned}}{{serie.total}}{{serie.mean}}
    23 | 24 | {% for serie in series %} 25 |

    {{serie.name}}

    26 | 27 | 28 | 29 | 30 | 31 | {% for game in serie.games %} 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | {% endfor %} 45 | 46 |
    RankGameRatingPlaysOwnedWant in TradeFor TradeWishedYearYour Comment
    {% if game.rank %}{{game.rank}}{% else %} {% endif %}{{game.name}}{% if game.rating %}{{game.rating}}{% else %} {% endif %}{% if game.plays %}{{game.plays}}{% else %} {% endif %}{% if game.owned %}YES{% else %} {% endif %}{% if game.want %}YES{% else %} {% endif %}{% if game.trade %}YES{% else %} {% endif %}{% if game.wish %}YES{% else %} {% endif %}{{game.yearpublished}}{% if game.comment %}{{game.comment}}{% else %} {% endif %}
    47 | {% endfor %} 48 | 49 |
    50 | 51 | 52 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/series.html;: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'pretitle.html' %} 4 | Series Summaries for {{geek.username}} 5 | {% include 'stylesheets.html' %} 6 | 7 | 8 | {% include 'navbar.html' %} 9 |
    10 |

    Crazy Recommendations for {{geek.username}}

    11 | 12 | The Crazy Recommendations algorithm assesses games based on whether they share various characteristics with games you rate 9 or higher. There is no popularity factor, so this algorithm avoids the fault of recommending Agricola and Puerto Rico to everyone. This listing includes games that are recommended but you've already rated, expansions, and even books. However there are 20 actual games listed for you that you neither own nor have rated - they're coloured black and are bold. If an entry really annoys you, you can rate the game a "Don't Buy This For Me" on your BGG wishlist, and it will no longer appear in the Crazy Recommendations when the changes are noticed. 13 |

    14 | 15 | 16 | 17 | 18 | 19 | 20 | {% for row in rows %} 21 | 22 | 23 | {% endfor %} 24 | 25 |
    GameScoreCategoriesMechanicsDesignersMin PlayersMax PlayersPlay TimeOwnedRating
    {{row.gamename}}{{row.total}}{{row.category}}{{row.mechanic}}{{row.designer}}{{row.minplayers}}{{row.maxplayers}}{{row.playtime}}{{row.owned}}{{row.rating}}
    26 | 27 |

    28 | 29 | 30 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/server.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Server 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 |

    Extended Stats Server Status

    10 | 11 | 16 | 17 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/sgoyt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Geeklist Summary for {{geeklist}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |

    Geeklist Summary for {{geeklist}}

    11 | 12 |
    13 | {% for t in data %} 14 | {{t.gid}}, "{{t.user}}", "{{t.gamename}}"
    15 | {% endfor %} 16 |
    17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/shouldplay.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Games You Should Play

    3 | 4 |

    5 | 6 | 7 | 8 | {% for row in shouldPlay %} 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% endfor %} 16 |
    GameRatingLast PlayedDays Since Last Play
    {{row.gamename}}{{row.rating}}{{row.lastPlayed|date:"d-m-Y"}}{{row.sincePlayed}}
    17 |

    18 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/shouldplayown.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Games You Should Play Which You Own

    3 | 4 |

    5 | 6 | 7 | 8 | {% for row in shouldPlayOwn %} 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% endfor %} 16 |
    GameRatingLast PlayedDays Since Last Play
    {{row.gamename}}{{row.rating}}{{row.lastPlayed|date:"d-m-Y"}}{{row.sincePlayed}}
    17 |

    18 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/streaks.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Most Consecutive Days Playing Games

    3 | 4 |

    5 | 6 | 7 | 8 | {% for streak in streaks %} 9 | 10 | {% endfor %} 11 |
    Min Games PlayedStart DateEnd DateStreak Length
    {{streak.count}}{{streak.start}}{{streak.finish}}{{streak.length}}
    12 |

    13 | 14 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/stylesheets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/tab1.html: -------------------------------------------------------------------------------- 1 |
    2 | 36 |
    37 | 38 | {% include 'stats/favourites.html' %} 39 | {% include 'stats/new.html' %} 40 | {% include 'stats/fpvr.html' %} 41 | {% include 'stats/rbpy.html' %} 42 | {% include 'stats/fgbpy.html' %} 43 | {% include 'stats/obpy.html' %} 44 | {% include 'stats/lag.html' %} 45 | {% include 'stats/lifetime.html' %} 46 | {% include 'stats/lbr.html' %} 47 | 48 | {% if florence %} 49 | {% include 'stats/florence.html' %} 50 | {% endif %} 51 | 52 | {% include 'stats/morgan.html' %} 53 | 54 | {% if bestDays %} 55 | {% include 'stats/bestdays.html' %} 56 | {% endif %} 57 | 58 | {% if ratingByRanking %} 59 | {% include 'stats/ratingbyranking.html' %} 60 | {% endif %} 61 | {% if playsByRanking %} 62 | {% include 'stats/playsByRanking.html' %} 63 | {% endif %} 64 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/tab3.html: -------------------------------------------------------------------------------- 1 |
    2 | What should you own? What should you not own? 3 |

    4 |

    31 |
    32 | 33 | {% if pogo %} 34 | {% include 'stats/pogo.html' %} 35 | {% include 'stats/pogotable.html' %} 36 | {% endif %} 37 | 38 | {% include 'stats/pbpy.html' %} 39 | 40 | {% if shouldPlay %} 41 | {% include 'stats/shouldplay.html' %} 42 | {% endif %} 43 | 44 | {% if shouldPlayOwn %} 45 | {% include 'stats/shouldplayown.html' %} 46 | {% endif %} 47 | 48 | {% if least %} 49 | {% include 'stats/least.html' %} 50 | {% endif %} 51 | 52 | {% if unusual %} 53 | {% include 'stats/unusual.html' %} 54 | {% endif %} 55 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/tab4.html: -------------------------------------------------------------------------------- 1 | 24 | 25 | {% if mostUnplayed %} 26 | {% include 'stats/mostunplayed.html' %} 27 | {% endif %} 28 | 29 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/tab5.html: -------------------------------------------------------------------------------- 1 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/tabs.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | {% if tab1 %} 5 | {% if tab2 %} 7 | {% if tab3 %} 9 | {% if tab4 %} 11 | {% if tab5 %} 13 | {% if tab6 %} 15 | {% if tab7 %} 17 |
    {% else %}{% endif %} 4 | General {% else %}{% endif %} 6 | Plays {% else %}{% endif %} 8 | Collection Management {% else %}{% endif %} 10 | Play Suggestions {% else %}{% endif %} 12 | Other Perspectives {% else %}{% endif %} 14 | User-Customisable {% else %}{% endif %} 16 | Feature Index 
    18 |
    19 | 20 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/temphotdate.html: -------------------------------------------------------------------------------- 1 |

    Temporal Hotness by Date

    2 | 3 |
    4 | 5 | 6 | 7 | 8 | 9 | {% for month in thd %} 10 | 11 | {% for d in month.data %} 12 | 13 | {% endfor %} 14 | 15 | {% endfor %} 16 | 17 |
    TotalMonth12345678910111213141516171819202122232425262728293031
    {{month.count}}{{month.name}}{{d.count}}
    18 |

    19 | This table implements an analysis designed by Randy Cox. 20 | For each date of the year, how many games have you ever played on that date? 21 |

    22 | 23 | 24 | 25 | 26 | 27 | 28 |
    1+ standard deviations below the mean
    0.5 - 1 standard deviations below the mean
    within 0.5 standard deviations of the mean
    0.5 - 1 standard deviations above the mean
    1+ standard deviations above the mean
    29 |

    -------------------------------------------------------------------------------- /extended/stats/templates/stats/temphotday.html: -------------------------------------------------------------------------------- 1 |

    Temporal Hotness by Day

    2 | 3 |
    4 | 5 | 6 | 7 | 8 | 9 | {% for year in thday %} 10 | 11 | {% for d in year.data %} 12 | 13 | {% endfor %} 14 | 15 | {% endfor %} 16 | 17 |
    TotalYearMondayTuesdayWednesdayThursdayFridaySaturdaySunday
    {{year.count}}{{year.name}}{{d.count}}
    18 |

    19 | This table implements an analysis suggested by polychrotid. 20 | For each day of the week, how many games have you played on that day? 21 | I extended the idea to see how that changed over the years. 22 |

    23 | 24 | 25 | 26 | 27 | 28 | 29 |
    1+ standard deviations below the mean
    0.5 - 1 standard deviations below the mean
    within 0.5 standard deviations of the mean
    0.5 - 1 standard deviations above the mean
    1+ standard deviations above the mean
    30 |

    -------------------------------------------------------------------------------- /extended/stats/templates/stats/temphotmonth.html: -------------------------------------------------------------------------------- 1 |

    Temporal Hotness by Month

    2 | 3 |
    4 | 5 | 6 | 7 | 8 | 9 | {% for year in thm %} 10 | 11 | {% for month in year.months %} 12 | 13 | {% endfor %} 14 | 15 | {% endfor %} 16 | 17 |
    TotalYearJanFebMarAprMayJunJulAugSepOctNovDec
    {{year.count}}{{year.name}}{{month.count}}
    18 |

    19 | This table implements an analysis designed by Randy Cox. 20 | For each month since you really got into games, how many games did you play? The values are coloured according to the number of games played. 21 |

    22 | 23 | 24 | 25 | 26 | 27 | 28 |
    1+ standard deviations below the mean
    0.5 - 1 standard deviations below the mean
    within 0.5 standard deviations of the mean
    0.5 - 1 standard deviations above the mean
    1+ standard deviations above the mean
    29 |

    30 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/testajax.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | List 5 | {% include 'stats/stylesheets.html' %} 6 | 18 | 19 | 20 | {% include 'stats/navbar.html' %} 21 |

    {{title}}

    22 | 23 | This is a test. 24 | 25 |
    26 |

    27 | 28 | 29 |

    30 |
    31 | 32 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/totalplays.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Total Plays for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |

    Plays for {{username}}

    11 | 12 | {% for link in links %} 13 | {{link.name}} 14 | {% endfor %} 15 |

    16 | 17 |

    18 | 19 | {% for play in plays %} 20 | 21 | {% endfor %} 22 |
    GameQuantityRatingExpansions
    {{play.gamename}}{{play.count}}{{play.rating}}{{play.expansionNames}}
    23 |
    24 | 25 | {% for message in messages %} 26 | {{message}}
    27 | {% endfor %} 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/unusual.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |

    The Most Unusual Games You Own

    4 | 5 | 6 | 7 | 8 | {% for row in unusual %} 9 | 10 | 11 | 12 | 13 | {% endfor %} 14 |
    GameUsers RatingUsers Owning
    {{row.name}}{{row.usersrated}}{{row.usersowned}}
    15 | 16 |
    17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/unusual_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | The Most Unusual Games That {{geek.username}} Owns 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |
    11 | {% include 'stats/unusual.html' %} 12 |
    13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/updates.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Update Schedule for {{geek}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/navbar.html' %} 9 | 10 |

    Updates

    11 | This table summarises when files containing your data have been downloaded, and when it's planned to download them next. Dates are in Brisbane time (GMT +10). The refresh link causes the server to reload your data (within about a minute). This is a slow process and usually not necessary, so please don't use it unless you know what you're doing. 12 |

    13 | Any file which says "None" in the Next Update column is a file that is updated by request only. The extended stats downloader will never download that file unless the Last Update column also says None. Clicking on the refresh button will set the Last Update column to None - so that's what you've got to do. (I had to make it a button because the GoogleBot was clicking on the link for everyone!) 14 |

    15 | At the moment, the only files which are not scheduled for updates are plays for months which ended more than 120 days ago. So, if you enter your plays within 4 months you won't notice any difference. 16 | 17 |

    18 | 19 | {% for row in updates %} 20 | 26 | {% endfor %} 27 |
    URLLast UpdatedNext Update
    {{row.description}}{{row.lastUpdate}}{{row.nextUpdate}} 21 |
    22 | {% csrf_token %} 23 | 24 |
    25 |
    28 |
    29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/userfaves.html: -------------------------------------------------------------------------------- 1 |
    2 | The aim of this tab is to convince Jeroen Doumen to reprint Roads and Boats. 3 | So far this is just a proof of concept but I'm sure as the page gets better he'll understand his obligations. :p 4 | Go to the Cookies page to choose what you see here. 5 |

    6 | {% include 'stats/contents.html' %} 7 |

    8 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/viewCollection.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | View Collection {{collection.name}} 5 | {% include 'stats/stylesheets.html' %} 6 | 15 | 16 | 17 | {% include 'stats/navbar.html' %} 18 | Collections 19 | Edit 20 |
    21 |
    22 |

    {{collection.name}}

    23 | 24 | {{collection.description}} 25 |

    26 | 27 | 28 | {% for group in groups %} 29 | 30 | {% endfor %} 31 |
    GroupCountRated CountMean RatingSum of RatingsTotal PlaysMean PlaysMedian PlaysUtilisation
    {{group.name}}{{group.count}}{{group.rated}}{{group.rating}}{{group.sumrating}}{{group.plays}}{{group.meanPlays}}{{group.medianPlays}}{{group.utilisation}}%
    32 |

    33 | 34 |
    35 | 36 | {% for g in groups %} 37 | 38 | {% endfor %} 39 |
    {{g.name}} 
    40 |
    41 |

    42 | {{group.description}} 43 | 44 | {% include 'stats/contents.html' %} 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/viewSelections.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | View Selections 5 | {% include 'stats/stylesheets.html' %} 6 | 15 | 16 | 17 | {% include 'stats/navbar.html' %} 18 |

    19 |

    20 |

    Summary

    21 | 22 | 23 | {% for group in tabs %} 24 | 25 | {% endfor %} 26 |
    GroupCountRated CountMean RatingSum of RatingsTotal PlaysMean PlaysMedian PlaysH-Index
    {{group.name}}{{group.count}}{{group.rated}}{{group.rating}}{{group.sumrating}}{{group.plays}}{{group.meanPlays}}{{group.medianPlays}}{{group.hindex}}
    27 |
    28 | 29 |

    30 |


    31 |
    32 | 33 | {% for g in tabs %} 34 | 35 | {% endfor %} 36 |
    {{g.name}} 
    37 |
    38 |

    39 | 40 | {% include 'stats/contents.html' %} 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/whatif.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | What If... for {{geek.username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | 9 | {% include 'stats/navbar.html' %} 10 | 11 |

    12 |

    What If...

    13 | 14 | This page allows you to do experiments with your continuous Friendless metric and utilisation numbers. For example, what if I got rid of this game? What if I played all of these? 15 | 16 | The columns are: 17 |
      18 |
    • Game - clicking on the name of the game resets the row to its initial state 19 |
    • Plays - how many plays you have recorded for this game 20 |
    • Own - whether you own this game 21 |
    • Hypothetical Plays - how many plays you might have. Clicking on the cell increases this number by one. The Hypothetical CFM and utilisation are then recalculated. 22 |
    • Hypothetical Own - whether you own this game. Clicking on the cell toggles this value. The Hypothetical CFM and utilisation are then recalculated. 23 |
    • Modified - whether the row has been modified. Click on the game name to reset it. 24 |
    25 | 26 |

    Real CFM
    27 |

    Real Utilisation
    28 |

    Hypothetical CFM
    29 |

    Hypothetical Utilisation
    30 |

    31 | 32 | 33 | 34 | 35 | {% for game in games %} 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | {% endfor %} 45 |
    GamePlaysOwnHypothetical PlaysHypothetical OwnModified
    {{game.name}}{{game.plays}}{{game.own}}{{game.plays}}{{game.own}}
    46 | 47 |

    48 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/year.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Yearly Statistics for {{username}} for {{year}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/geekwidget.html' %} 9 | {% include 'stats/navbar.html' %} 10 |

    Yearly Statistics for {{username}} for {{year}}

    11 | 12 |
    13 | 14 | 15 | 37 |
    38 |
    39 | 40 | {% if bestDays %} 41 | {% include 'stats/bestdays.html' %} 42 | {% endif %} 43 | 44 | {% if designerDimes %} 45 | {% include 'stats/dimesbydesigner.html' %} 46 | {% endif %} 47 | 48 | {% if ndd %} 49 | {% include 'stats/nickeldime.html' %} 50 | {% endif %} 51 | 52 | {% if playedLastYear %} 53 | {% include 'stats/playedlastyear.html' %} 54 | {% endif %} 55 | 56 | {% if florence %} 57 | {% include 'stats/florence.html' %} 58 | {% endif %} 59 | 60 | {% if morePieDefault %} 61 | {% include 'stats/morepie.html' %} 62 | {% endif %} 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/yearcomparison.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% include 'stats/pretitle.html' %} 4 | Extended Stats for {{username}} 5 | {% include 'stats/stylesheets.html' %} 6 | 7 | 8 | {% include 'stats/geekwidget.html' %} 9 | {% include 'stats/navbar.html' %} 10 |

    Florence Nightingale Gamer Characterisation

    11 | 12 |
    13 | 14 | This diagram is inspired by Florence Nightingale's Polar Area Diagrams. 15 | The area of each colour is proportional to the number of games you have played with that BGG subdomain. 16 | Looking at this diagram, people can see at a glance what sort of, and how many, games you play. 17 |

    18 | 19 | {% for year in playsYears %} 20 |

    {{year}}

    21 | 22 | 23 | 30 |
    24 | 25 | {% for flo in florence %} 26 | 27 | {% endfor %} 28 |
     {{flo.name}}
    29 |
    31 | {% endfor %} 32 | 33 |
    34 | -------------------------------------------------------------------------------- /extended/stats/templates/stats/yearlysummaries.html: -------------------------------------------------------------------------------- 1 | Yearly Summaries:
    2 | {% for row in playsYearsRows %} 3 | {% for year in row %} 4 | {{year}} 5 | {% endfor %}
    6 | {% endfor %} -------------------------------------------------------------------------------- /extended/stats/tests.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file demonstrates writing tests using the unittest module. These will pass 3 | when you run "manage.py test". 4 | 5 | Replace this with more appropriate tests for your application. 6 | """ 7 | 8 | from django.test import TestCase 9 | 10 | 11 | class SimpleTest(TestCase): 12 | def test_basic_addition(self): 13 | """ 14 | Tests that 1 + 1 always equals 2. 15 | """ 16 | self.assertEqual(1 + 1, 2) 17 | -------------------------------------------------------------------------------- /extended/stats/webserver_factory.py: -------------------------------------------------------------------------------- 1 | webserver = None 2 | 3 | def get(): 4 | global webserver 5 | if webserver is None: 6 | import django_webserver 7 | webserver = django_webserver 8 | return webserver 9 | 10 | -------------------------------------------------------------------------------- /extended/test/testCreateDatabase.py: -------------------------------------------------------------------------------- 1 | # First test of using sqlite3 in memory to run unit tests 2 | import sys 3 | sys.path.append("..") 4 | 5 | import stats.mydb as mydb 6 | mydb.TESTING = True 7 | db = mydb.get() 8 | with open("simple.sql", "r") as scriptfile: 9 | lines = map(lambda s: s.strip(), scriptfile.readlines()) 10 | text = "".join(lines) 11 | db.executescript(text) 12 | cursor = db.execute("select * from files") 13 | for row in cursor: 14 | print row 15 | print "Done" -------------------------------------------------------------------------------- /extended/test/testLibrary.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append("..") 3 | 4 | import stats.library as library 5 | 6 | def testCalcHIndex(): 7 | assert library.calcHIndex([]) == 0 8 | assert library.calcHIndex([0]) == 0 9 | assert library.calcHIndex([1]) == 1 10 | assert library.calcHIndex([1,2]) == 1 11 | assert library.calcHIndex([1,2,2]) == 2 12 | assert library.calcHIndex([2,3,1]) == 2 13 | assert library.calcHIndex([1,2,3,4,5]) == 3 14 | assert library.calcHIndex([23L, 0L, 0L, 2L, 20L, 1L, 13L, 1L, 3L, 3L, 4L, 1L, 9L, 2L, 8L, 7L, 0L, 24L, 4L, 2L, 5L, 1L, 4L, 0L, 3L, 0L, 1L, 0L, 1L, 4L, 1L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 13L, 0L, 0L, 1L, 1L, 0L, 1L, 1L, 9L, 7L, 2L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 2L, 0L, 0L, 0L, 0L, 0L, 0L, 2L, 11L, 0L, 0L, 6L, 1L, 0L, 10L, 1L, 1L, 0L, 0L, 1L, 9L, 42L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 1L, 1L, 0L, 1L, 0L, 2L, 2L, 1L, 0L, 1L, 0L, 9L, 11L, 1L, 0L, 1L, 1L, 2L, 2L, 1L, 1L, 0L]) == 9 15 | # assert library.calcHIndex(sa266) == 64 16 | 17 | if __name__ == "__main__": 18 | testCalcHIndex() 19 | -------------------------------------------------------------------------------- /images/arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/arrow_down.png -------------------------------------------------------------------------------- /images/arrow_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/arrow_up.png -------------------------------------------------------------------------------- /images/bgg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/bgg.png -------------------------------------------------------------------------------- /images/bullet_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/bullet_down.png -------------------------------------------------------------------------------- /images/bullet_go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/bullet_go.png -------------------------------------------------------------------------------- /images/external.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/external.png -------------------------------------------------------------------------------- /images/eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/eye.png -------------------------------------------------------------------------------- /images/pencil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/pencil.png -------------------------------------------------------------------------------- /images/sort_down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/sort_down.gif -------------------------------------------------------------------------------- /images/sort_up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/sort_up.gif -------------------------------------------------------------------------------- /images/sp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/sp.gif -------------------------------------------------------------------------------- /images/stats.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/stats.gif -------------------------------------------------------------------------------- /images/table_excel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/table_excel.png -------------------------------------------------------------------------------- /images/table_gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/table_gear.png -------------------------------------------------------------------------------- /images/wtfcat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/images/wtfcat.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | simplejson 2 | -------------------------------------------------------------------------------- /scripts/common.js~: -------------------------------------------------------------------------------- 1 | /*========================================== 2 | String functions 3 | ==========================================*/ 4 | String.prototype.trim = function() { 5 | return this.replace( /^\s+|\s+$/, "" ); 6 | } 7 | 8 | /*========================================== 9 | Class Manipulation 10 | ==========================================*/ 11 | 12 | function hasClassName( elem, className ) { 13 | if ( !elem.className ) return false; 14 | var pattern = new RegExp("(^|\\s)"+className+"(\\s|$)"); 15 | return pattern.test(elem.className); 16 | } 17 | 18 | function removeClassName( elem, className ) { 19 | var pattern = new RegExp("(^|\\s)"+className+"(\\s|$)"); 20 | elem.className = elem.className.replace( pattern, "" ).trim(); 21 | } 22 | 23 | function addClassName( elem, className ) { 24 | removeClassName( elem, className ); 25 | elem.className = ( elem.className + " " + className ).trim(); 26 | } 27 | 28 | // http://www.dustindiaz.com/getelementsbyclass 29 | function getElementsByClass(searchClass,node,tag) { 30 | var classElements = new Array(); 31 | var els = node.getElementsByTagName(tag); 32 | var elsLen = els.length; 33 | var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"); 34 | for (i = 0, j = 0; i < elsLen; i++) { 35 | if ( pattern.test(els[i].className) ) { 36 | classElements[j] = els[i]; 37 | j++; 38 | } 39 | } 40 | return classElements; 41 | } 42 | 43 | /*========================================== 44 | Add event 45 | ==========================================*/ 46 | 47 | function addEvent(elm, evType, fn, useCapture) { 48 | if (elm.addEventListener) { 49 | elm.addEventListener(evType, fn, useCapture); 50 | return true; 51 | } 52 | else if (elm.attachEvent) { 53 | var r = elm.attachEvent('on' + evType, fn); 54 | return r; 55 | } 56 | else { 57 | elm['on' + evType] = fn; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /scripts/dynamic.js: -------------------------------------------------------------------------------- 1 | function changeImageURL(imgId, newUrl) { 2 | //The image object accessed through its id we mentioned in the DIV block which is going to be visible currently 3 | var img = document.getElementById(imgId); 4 | img.src = newUrl; 5 | return; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /scripts/dynamic.js~: -------------------------------------------------------------------------------- 1 | function changeImageURL(imgId, newUrl) { 2 | //The image object accessed through its id we mentioned in the DIV block which is going to be visible currently 3 | var img = document.getElementById(imgId); 4 | alert(imgId); 5 | img.src = newUrl; 6 | return; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /scripts/greenbar.js: -------------------------------------------------------------------------------- 1 | /*========================================== 2 | Green Bar 3 | ==========================================*/ 4 | 5 | addEvent(window, "load", init_tables); 6 | 7 | function init_tables() { 8 | greenbar_init(); 9 | bluebar_init(); 10 | } 11 | 12 | function greenbar_init() { 13 | // Find all tables with class greenbar and make them greenbar 14 | if (!document.getElementsByTagName) return; 15 | tbls = document.getElementsByTagName("table"); 16 | for (ti=0;ti') 14 | if (thetitle.length>1){ 15 | thetitles='' 16 | for (i=0;i'+text+'') 26 | document.tooltip.document.close() 27 | document.tooltip.left=e.pageX+5 28 | document.tooltip.top=e.pageY+5 29 | document.tooltip.visibility="show" 30 | } 31 | } 32 | function hidetip(){ 33 | if (document.layers) 34 | document.tooltip.visibility="hidden" 35 | } 36 | -------------------------------------------------------------------------------- /scripts/jqtouch.transitions.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | _/ _/_/ _/_/_/_/_/ _/ 4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ 5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ 6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ 7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ 8 | _/ 9 | _/ 10 | 11 | Created by David Kaneda 12 | Documentation and issue tracking on Google Code 13 | 14 | Special thanks to Jonathan Stark 15 | and pinch/zoom 16 | 17 | (c) 2009 by jQTouch project members. 18 | See LICENSE.txt for license. 19 | 20 | */ 21 | 22 | (function($) { 23 | 24 | $.fn.transition = function(css, options) { 25 | return this.each(function(){ 26 | var $el = $(this); 27 | var defaults = { 28 | speed : '300ms', 29 | callback: null, 30 | ease: 'ease-in-out' 31 | }; 32 | var settings = $.extend({}, defaults, options); 33 | if(settings.speed === 0) { 34 | $el.css(css); 35 | window.setTimeout(settings.callback, 0); 36 | } else { 37 | if ($.browser.safari) 38 | { 39 | var s = []; 40 | for(var i in css) { 41 | s.push(i); 42 | } 43 | $el.css({ 44 | webkitTransitionProperty: s.join(", "), 45 | webkitTransitionDuration: settings.speed, 46 | webkitTransitionTimingFunction: settings.ease 47 | }); 48 | if (settings.callback) { 49 | $el.one('webkitTransitionEnd', settings.callback); 50 | } 51 | setTimeout(function(el){ el.css(css) }, 0, $el); 52 | } 53 | else 54 | { 55 | $el.animate(css, settings.speed, settings.callback); 56 | } 57 | } 58 | }); 59 | } 60 | })(jQuery); -------------------------------------------------------------------------------- /scripts/jquery.mousewheel.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006 Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net) 2 | * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 3 | * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 4 | * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 5 | * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6 | * 7 | * $LastChangedDate: 2007-12-14 23:57:10 -0600 (Fri, 14 Dec 2007) $ 8 | * $Rev: 4163 $ 9 | * 10 | * Version: @VERSION 11 | * 12 | * Requires: $ 1.2.2+ 13 | */ 14 | 15 | (function($) { 16 | 17 | $.event.special.mousewheel = { 18 | setup: function() { 19 | var handler = $.event.special.mousewheel.handler; 20 | 21 | // Fix pageX, pageY, clientX and clientY for mozilla 22 | if ( $.browser.mozilla ) 23 | $(this).bind('mousemove.mousewheel', function(event) { 24 | $.data(this, 'mwcursorposdata', { 25 | pageX: event.pageX, 26 | pageY: event.pageY, 27 | clientX: event.clientX, 28 | clientY: event.clientY 29 | }); 30 | }); 31 | 32 | if ( this.addEventListener ) 33 | this.addEventListener( ($.browser.mozilla ? 'DOMMouseScroll' : 'mousewheel'), handler, false); 34 | else 35 | this.onmousewheel = handler; 36 | }, 37 | 38 | teardown: function() { 39 | var handler = $.event.special.mousewheel.handler; 40 | 41 | $(this).unbind('mousemove.mousewheel'); 42 | 43 | if ( this.removeEventListener ) 44 | this.removeEventListener( ($.browser.mozilla ? 'DOMMouseScroll' : 'mousewheel'), handler, false); 45 | else 46 | this.onmousewheel = function(){}; 47 | 48 | $.removeData(this, 'mwcursorposdata'); 49 | }, 50 | 51 | handler: function(event) { 52 | var args = Array.prototype.slice.call( arguments, 1 ); 53 | 54 | event = $.event.fix(event || window.event); 55 | // Get correct pageX, pageY, clientX and clientY for mozilla 56 | $.extend( event, $.data(this, 'mwcursorposdata') || {} ); 57 | var delta = 0, returnValue = true; 58 | 59 | if ( event.wheelDelta ) delta = event.wheelDelta/120; 60 | if ( event.detail ) delta = -event.detail/3; 61 | if ( $.browser.opera ) delta = -event.wheelDelta; 62 | 63 | event.data = event.data || {}; 64 | event.type = "mousewheel"; 65 | 66 | // Add delta to the front of the arguments 67 | args.unshift(delta); 68 | // Add event to the front of the arguments 69 | args.unshift(event); 70 | 71 | return $.event.handle.apply(this, args); 72 | } 73 | }; 74 | 75 | $.fn.extend({ 76 | mousewheel: function(fn) { 77 | return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 78 | }, 79 | 80 | unmousewheel: function(fn) { 81 | return this.unbind("mousewheel", fn); 82 | } 83 | }); 84 | 85 | })(jQuery); -------------------------------------------------------------------------------- /scripts/ruler.js: -------------------------------------------------------------------------------- 1 | /*========================================== 2 | Ruler 3 | ==========================================*/ 4 | addEvent(window, "load", ruler_init); 5 | 6 | function ruler_init() { 7 | // Find all tables with class greenbar and make them ruler 8 | if (!document.getElementsByTagName) return; 9 | tbls = document.getElementsByTagName("table"); 10 | for (ti=0;ti 2 | 3 | Because this page kept breaking I rewrote the way I make it. It's more up-to-date now, and can be found 4 | here. Please update your bookmarks. 5 |

    6 | Friendless 7 | 8 | -------------------------------------------------------------------------------- /static/robots.txt: -------------------------------------------------------------------------------- 1 | User-Agent: * 2 | Disallow: / 3 | -------------------------------------------------------------------------------- /static/stats.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrFriendless/ExtendedStats/edb664d29777377dbfbee5ad0b15614f6e887df1/static/stats.gif -------------------------------------------------------------------------------- /stats.conf: -------------------------------------------------------------------------------- 1 | WSGIScriptAlias /dynamic /home/ubuntu/extended/extended/extended/wsgi.py 2 | 3 | Order allow,deny 4 | Allow from all 5 | Require all granted 6 | 7 | 8 | 9 | Require all granted 10 | 11 | 12 | Alias /robots.txt /home/ubuntu/extended/static/robots.txt 13 | Alias /favicon.ico /home/ubuntu/extended/static/stats.gif 14 | Alias /stats/ /home/ubuntu/extended/static/ 15 | 16 | Require all granted 17 | DirectoryIndex index.html 18 | 19 | Alias /css/ /home/ubuntu/extended/css/ 20 | 21 | DirectoryIndex index.html 22 | Require all granted 23 | 24 | Alias /images/ /home/ubuntu/extended/images/ 25 | 26 | DirectoryIndex index.html 27 | Require all granted 28 | 29 | Alias /scripts/ /home/ubuntu/extended/scripts/ 30 | 31 | DirectoryIndex index.html 32 | Require all granted 33 | 34 | Redirect /index.html /dynamic/index.html 35 | RedirectMatch /$ /dynamic/index.html 36 | 37 | -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | loglevel=debug 4 | 5 | [program:import] 6 | priority=10 7 | command=/home/ubuntu/extended/setup_mysql.sh 8 | 9 | [program:apache2] 10 | priority=20 11 | command=/usr/sbin/apache2ctl -D "FOREGROUND" -k start 12 | ;command=/usr/sbin/apache2 -D FOREGROUND 13 | redirect_stderr=true 14 | 15 | [program:cron] 16 | priority=30 17 | command=/usr/sbin/cron -f 18 | autorestart=true 19 | --------------------------------------------------------------------------------