diff --git a/.gitignore b/.gitignore index 221ed36..0e9d6bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ __pycache__/ +build.sh build/* !build/*.css !build/*.png diff --git a/README.org b/README.org index 4b4153d..906124c 100644 --- a/README.org +++ b/README.org @@ -1,10 +1,23 @@ #+TITLE: Trackers +* Dependencies +- =python3= +- =orgparse= (install via pip) +- =rclone= (for syncing to the server) * Tracking games with a backloggery clone +** Setup +*** Setting the variables Rename =variables-template.py= to =variables.py= and edit: - =endlessgames=: a list of “endless” games in the format =title (console)= - =orgpath=: absolute path to the root directory in which =.org= files are stored, including trailing slash - =localpath=: absolute path to this directory, including trailing slash -- =serverpath=: path to directory on the server where files will be uploaded, including trailing slash +- =serverpath=: path to directory on the server where files will be uploaded (following =rclone= syntax, this will start with the name of the server, followed by a colon) - =description=: content for the “about” section (can include HTML tags) +- =hue=: theme colour expressed as a hue from 0 to 360 - =consoles=: add or remove consoles following the format provided (=.png= images must be added to the build directory with a filename corresponding with the value of ="img"= for each console) +*** The rest +- Run =python3 init.py= and then =chmod +x build.sh=. +- Create the directory on the server. +** Generating the files +- Run =python3 generate.py local= to build in the local =build= directory. +- Run =./build.sh= to build and upload to the server. diff --git a/backlog.py b/backlog.py index 329de6f..636f2a3 100644 --- a/backlog.py +++ b/backlog.py @@ -108,7 +108,12 @@ def backlog(local=False): except: pass - filewrite.write(" \n \n
\n \n " + gamesort.thisyear + " Backlog\n ") + filewrite.write(" \n
\n
\n \n " + gamesort.thisyear + " Backlog\n ") if yeargames > 0: filewrite.write("⬆") @@ -170,9 +175,9 @@ def backlog(local=False): if yearendless > 0: filewrite.write(" \n \n") - filewrite.write(" \n
\n \n
\n
\n
") + filewrite.write(" \n
\n
\n
\n
\n
") if ((backlog/gamesort.total(gamesort.games))*100) > 50: - filewrite.write("\n Active Backlog · " + str(backlog) + " · " + str(round(((backlog/gamesort.total(gamesort.games))*100),1)) + "%") + filewrite.write("\n Total Backlog · " + str(backlog) + " · " + str(round(((backlog/gamesort.total(gamesort.games))*100),1)) + "%") filewrite.write("\n
\n
") if ((backlog/gamesort.total(gamesort.games))*100) <= 50: filewrite.write("\n Active Backlog · " + str(backlog) + " · " + str(round(((backlog/gamesort.total(gamesort.games))*100),1)) + "%") diff --git a/build/backloggery.css b/build/backloggery.css index 8b76c7d..2ab562d 100644 --- a/build/backloggery.css +++ b/build/backloggery.css @@ -16,7 +16,7 @@ a,aside,body,details,div,fieldset,figcaption,figure,footer,h1,h2,h3,html,img,inp --default-accent:#f58d47; --default-text:#fff; --default-secondary-text:#fff; - --default-accent-text:#fff; + --default-accent-text:#000; --default-accent-shadow:hsla(0,0%,0%,50%); --retro-border:url(/img/border.png); --active-base:var(--default-base); @@ -27,16 +27,11 @@ a,aside,body,details,div,fieldset,figcaption,figure,footer,h1,h2,h3,html,img,inp --active-secondary-text:var(--default-secondary-text); --active-secondary-text-25:hsla(0,0%,100%,0.25); --active-accent-text:var(--default-accent-text); - --unplayed-color:#562929; - --unfinished-color:#bd7828; - --beaten-color:#d1d1d1; - --completed-color:#ecd579; - --endless-color:#573271; - --none-color:hsla(264,27%,11%,40%); - --follow-color:#17cf17; - --mention-color:#cf1717; - --dm-color:#cf17cf; - --news-color:#1742cf + --beaten-color: hsla(0, 0%, 82%, 0.9); + --completed-color: hsla(48, 80%, 82%, 0.9); + --unplayed-color: hsla(200, 30%, 30%, 0.9); + --unfinished-color: hsla(0, 38%, 35%, 0.9); + --endless-color: hsla(275, 39%, 32%, 0.9); } html { @@ -165,11 +160,7 @@ svg text { width:100% } -@media screen and (max-width:700px) { - .tabs a { - font-size:.8rem - } -} + .Added,.unplayed,.Unplayed { background-color:var(--unplayed-color)!important; @@ -201,16 +192,8 @@ svg text { text-shadow:none } -.none,.None { - background-color:var(--none-color)!important; - text-shadow:none -} - -.none,.None,.Playing { - color:hsla(0,0%,100%,.75) -} - .Playing { + color:hsla(0,0%,100%,.75) background-color:#202020!important } @@ -227,18 +210,6 @@ div.profile main { grid-area:main } -@media screen and (min-width:800px) { - div.profile { - grid-template-areas:"card card card card card card card card card card card card" "side side side side main main main main main main main main"!important - } - - .tabs { - margin-top:0 - } - - -} - .game-item { margin-bottom:-3px; overflow:hidden; @@ -372,18 +343,6 @@ div.profile main { opacity:.5 } -@media screen and (max-width:520px) { - - .game-item>summary:first-child>.text>.title { - font-size:1rem - } - - .game-item>summary:first-child>.status { - padding:5px - } - -} - .donut { display:block } @@ -501,32 +460,6 @@ div.profile main { margin-left:6px } -@media screen and (max-width:1024px) { - .platform-card .title { - display:none - } - - .platform-card .abbr { - display:-webkit-box; - display:-ms-flexbox; - display:flex; - -webkit-box-flex:1; - -ms-flex:1; - flex:1; - min-width:80px - } - - .platform-card .bars a:last-of-type { - width:50px - } - - .platform-card .bars a:last-of-type span { - display:none - } - - -} - .backlog-breakdown { display:block; text-align:center; @@ -676,41 +609,6 @@ div.profile main { width:100% } -@media screen and (min-width:1024px) { - .backlog-breakdown,.backlog-breakdown .backlog-charts { - display:-webkit-box; - display:-ms-flexbox; - display:flex - } - - .backlog-breakdown .backlog-charts { - -webkit-box-orient:horizontal; - -webkit-box-direction:normal; - -ms-flex-direction:row; - flex-direction:row; - width:100% - } - - .backlog-breakdown .mem-sum { - -webkit-box-orient:vertical; - -webkit-box-direction:normal; - -ms-flex-direction:column; - flex-direction:column; - min-width:160px; - max-width:160px - } - - .backlog-breakdown .mem-sum .donut { - margin:0 - } - - .backlog-breakdown .mem-sum .donut:last-of-type { - position:relative; - top:-10px - } - -} - .library .unibar { border:2px solid rgba(0,0,0,.5);border-radius:8px;display:-webkit-box;display:-ms-flexbox;display:flex;width:100%} @@ -744,14 +642,6 @@ div.profile main { .library .library-list { margin-top:20px} -@media screen and (max-width:600px) { - .library .unibar div { - font-size:3vw} - - .library .unibar div:first-of-type span { - margin-right:.5rem} -} - .game-item .game-info { -webkit-box-align:start; -ms-flex-align:start; @@ -827,28 +717,6 @@ div.profile main { opacity:.5 } -@media screen and (max-width:700px) { - .game-item .game-info { - margin-left:8px - } - - .game-item .game-info .box_2 { - margin-right:0 - } - - .game-item .game-info .data,.game-item .game-info .history,.game-item .game-info .review { - display:block - } - - .game-item .game-info .data .box_1 div { - display:inline-block; - margin-right:1%; - width:48% - } - - -} - .history .box_1 { width: 95%; } @@ -859,8 +727,6 @@ div.profile aside { position: sticky; } -/* NEW */ - .library .filters { margin:.25rem 0 1.5rem; width:100%} @@ -894,3 +760,314 @@ padding:.4rem 1rem .5rem} .library .filters .item:hover { opacity:1} + +.status-dot { + width:12px; + height:12px; + max-width:12px; + border-radius:8px; + border:2px solid #000; + display:inline-block; + margin-right:3px; + opacity:1; + position:relative; + top:1px; +} + + +/* new for history page */ + +.hide_arrow { + -webkit-transform: translateX(100px); + transform: translateX(100px) +} + +.scroll-button { + border-radius: 8px; + background: var(--active-secondary); + color: var(--active-secondary-text); + cursor: pointer; + display: block; + font-size: 18px; + opacity: .7; + pointer-events: all; + position: fixed; + bottom: 20px; + right: 20px; + text-align: center; + line-height: 26px; + height: 30px; + width: 30px; + -webkit-transition: -webkit-transform .5s; + transition: -webkit-transform .5s; + transition: transform .5s; + transition: transform .5s,-webkit-transform .5s +} + +.box_1 { + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.history { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + width: 100% +} + +.history .list, .history .retro { + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.history .list>div { + font-size: 14px +} + +.history .list>div:first-of-type h2 { + margin-top: 0 +} + +.history .list>div h2 { + display: block; + font-size: 13px +} + +section.history .list>div>div { + display: -webkit-box; + display: -ms-flexbox; + display: flex +} + +.history .list>div>div>div:first-of-type { + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; + margin-right: 5px; + opacity: .65; + text-align: right +} + +.history .list>div>div>div:last-of-type { + -webkit-box-flex: 2; + -ms-flex: 2; + flex: 2 +} + +.history .list>div>div>div:last-of-type span { + opacity: .65 +} + +.history .side { + margin-left: 40px; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.history .side .year-tally { + font-size: 14px; + opacity: .7; + margin: 25px 0 15px 0; + padding: 10px 10px 10px +} + +.history .side .year-tally.active { + background-color: var(--active-secondary-50); + color: var(--active-secondary-text); + border-left: 3px solid var(--active-accent); + border-radius: 0 1rem 1rem 0; + opacity: 1 +} + +.history .side .year-tally:first-of-type { + margin-top: 0 +} + +.history .side .year-tally h2 { + border: none; + margin: 0 0 5px +} + +.history .side .year-tally h2 span { + float: right; + font-size: 14px; + padding-top: 5px +} + +.history .side .year-tally div { + display: table-row +} + +.history .side .year-tally div div { + display: table-cell; + padding: 1px 3px; + vertical-align: middle +} + +.history .side .year-tally div div:first-of-type { + text-align: right +} + +.history .side .year-tally div div:nth-child(2) { + -webkit-box-flex: 0; + -ms-flex: 0; + flex: 0; + border-right: 2px solid #000; + padding: 0 5px 0 3px; + text-align: center; + min-width: 40px +} + +.history .side .year-tally div div:last-child { + -webkit-box-shadow: inset 7px 0 7px -5px rgba(0,0,0,.25); + box-shadow: inset 7px 0 7px -5px rgba(0,0,0,.25); + padding: 4px 0; + width: 100% +} + +.history .side .year-tally div div:last-child div { + -webkit-animation: width_in 1s ease-in-out; + animation: width_in 1s ease-in-out; + border: 2px solid #000; + border-left: none; + border-radius: 0 4px 4px 0; + display: block; + font-size: 14px; + height: 16px; + overflow: hidden; + text-align: left +} + +@media screen and (min-width:800px) { + div.profile { + grid-template-areas:"card card card card card card card card card card card card" "side side side side main main main main main main main main"!important + } + + .tabs { + margin-top:0 + } + + +} + +@media screen and (min-width:1024px) { + .backlog-breakdown,.backlog-breakdown .backlog-charts { + display:-webkit-box; + display:-ms-flexbox; + display:flex + } + + .backlog-breakdown .backlog-charts { + -webkit-box-orient:horizontal; + -webkit-box-direction:normal; + -ms-flex-direction:row; + flex-direction:row; + width:100% + } + + .backlog-breakdown .mem-sum { + -webkit-box-orient:vertical; + -webkit-box-direction:normal; + -ms-flex-direction:column; + flex-direction:column; + min-width:160px; + max-width:160px + } + + .backlog-breakdown .mem-sum .donut { + margin:0 + } + + .backlog-breakdown .mem-sum .donut:last-of-type { + position:relative; + top:-10px + } + +} + +@media screen and (max-width:1024px) { + .platform-card .title { + display:none + } + + .platform-card .abbr { + display:-webkit-box; + display:-ms-flexbox; + display:flex; + -webkit-box-flex:1; + -ms-flex:1; + flex:1; + min-width:80px + } + + .platform-card .bars a:last-of-type { + width:50px + } + + .platform-card .bars a:last-of-type span { + display:none + } + + +} + +@media screen and (max-width:700px) { + .tabs a { + font-size:.8rem + } + + .history { + display:block; + } + + .history .side { + margin-left: 0; + margin-top: 50px + } + + .game-item .game-info { + margin-left:8px + } + + .game-item .game-info .box_2 { + margin-right:0 + } + + .game-item .game-info .data,.game-item .game-info .history,.game-item .game-info .review { + display:block + } + + .game-item .game-info .data .box_1 div { + display:inline-block; + margin-right:1%; + width:48% + } + + +} + +@media screen and (max-width:600px) { + .library .unibar div { + font-size:3vw} + + .library .unibar div:first-of-type span { + margin-right:.5rem} +} + +@media screen and (max-width:520px) { + + .game-item>summary:first-child>.text>.title { + font-size:1rem + } + + .game-item>summary:first-child>.status { + padding:5px + } + +} diff --git a/cardstring.py b/cardstring.py index d6bd9b7..56f5da1 100644 --- a/cardstring.py +++ b/cardstring.py @@ -177,20 +177,25 @@ def playcard(game,local=False,decay=False): for console in variables.consoles: if game["console"] == console["code"]: cardstring += console["name"] - cardstring += "

\n
\n
\n \n

" + game["lastupdate"].strftime("%Y-%m-%d") + "

\n
\n
\n
\n
\n
\n

Milestones

\n
\n
\n
" + game["initialdate"].strftime("%Y-%m-%d") + "
\n
\n Added
\n
\n" + cardstring += "

\n
\n
\n \n

" + game["lastupdate"].strftime("%Y-%m-%d") + "

\n
\n
\n
\n
\n
\n

Milestones

\n
\n
\n
" + game["initialdate"].strftime("%Y-%m-%d") + "
\n
\n
Added
\n
\n" try: if game["firstplayed"]: - cardstring += "
\n
" + game["firstplayed"].strftime("%Y-%m-%d") + "
\n
\n Started
\n
\n" + cardstring += "
\n
" + game["firstplayed"].strftime("%Y-%m-%d") + "
\n
\n
Started
\n
\n" except: pass try: if game["beaten"]: - cardstring += "
\n
" + game["beaten"].strftime("%Y-%m-%d") + "
\n
\n Beaten
\n
\n" + cardstring += "
\n
" + game["beaten"].strftime("%Y-%m-%d") + "
\n
\n
Beaten
\n
\n" except: pass try: if game["completed"]: - cardstring += "
\n
" + game["completed"].strftime("%Y-%m-%d") + "
\n
\n Completed
\n
\n" + cardstring += "
\n
" + game["completed"].strftime("%Y-%m-%d") + "
\n
\n
Completed
\n
\n" except: pass cardstring += "
\n
\n
\n
\n \n" diff --git a/generate.py b/generate.py index 77ea908..6e1b988 100644 --- a/generate.py +++ b/generate.py @@ -3,6 +3,7 @@ import sys import backlog import library import sublibrary +import history try: if sys.argv[1] == "local": @@ -17,7 +18,9 @@ if __name__ == "__main__": backlog.backlog(True) library.library(True) sublibrary.sublibrary(True) + history.history(True) else: backlog.backlog() library.library() sublibrary.sublibrary() + history.history() diff --git a/history.py b/history.py index fde968e..4680b40 100644 --- a/history.py +++ b/history.py @@ -1,5 +1,5 @@ import os -import gamesort,skeleton +import gamesort,skeleton,variables from datetime import datetime,timedelta """ @@ -8,6 +8,8 @@ Generates history page def history(local=False): # delete existing file + if not os.path.isdir("build/history"): + os.mkdir("build/history") if os.path.exists("build/history/index.html"): os.remove("build/history/index.html") # write header @@ -15,49 +17,10 @@ def history(local=False): output = "build/history/index.html" filewrite = open(output, "a") + filewrite.write("
\n
\n") + theyear = int(gamesort.thisyear) while theyear > 2016: - added = 0 - started = 0 - beat = 0 - completed = 0 - beatorcompleted = 0 - for game in gamesort.games: - if game["initialdate"].year == theyear: - added += 1 - try: - if game["firstplayed"].year == theyear: - started += 1 - except: - pass - try: - if game["beaten"].year == theyear: - beat += 1 - beatorcompleted += 1 - try: - if game["completed"].year == theyear: - completed += 1 - except: - pass - except: - try: - if game["completed"].year == theyear: - completed += 1 - beatorcompleted += 1 - except: - pass - backlog = added - beatorcompleted - print(str(theyear) + " Summary") - if backlog > 0: - print("Backlog ▲ " + str(backlog)) - elif backlog == 0: - print("Backlog 0") - elif backlog < 0: - print("Backlog ▼ " + str(backlog * -1)) - print("Added " + str(added)) - print("Started " + str(started)) - print("Beat " + str(beat)) - print("Completed " + str(completed)) yearlist = [] enddate = datetime.strptime((str(theyear) + "-12-31"),"%Y-%m-%d") startdate = datetime.strptime((str(theyear) + "-01-01"),"%Y-%m-%d") @@ -84,12 +47,111 @@ def history(local=False): eachdate -= timedelta(days=1) checkdate = enddate for event in yearlist: + filewrite.write("
\n") if checkdate != event["date"]: - print(event["date"].strftime("%Y-%m-%d")) - print(event["action"] + ": " + event["name"] + " (" + event["console"] + ")") + filewrite.write("

" + event["date"].strftime("%Y-%m-%d") + "

\n") + filewrite.write("
\n
" + event["action"] + "\n
\n
\n
" + event["name"] + "\n (" + event["console"] + ")\n
\n
\n
\n") checkdate = event["date"] theyear -= 1 + filewrite.write("
\n") + + theyear = int(gamesort.thisyear) + filewrite.write("
\n") + while theyear > 2016: + yeargames = 0 + yearplaying = 0 + for game in gamesort.games: + if game["initialdate"].year == theyear: + try: + if game["gameplay"]: + if game["id"] not in variables.endlessgames: + yeargames += 1 + except: + yeargames += 1 + for game in gamesort.games: + try: + if game["beaten"].year == theyear: + yeargames -= 1 + except: + try: + if game["completed"].year == theyear: + yeargames -= 1 + except: + pass + + yearbacklog = [] + for game in gamesort.games: + try: + if game["completed"].year == theyear: + yearbacklog.append(game) + except: + try: + if game["beaten"].year == theyear: + yearbacklog.append(game) + except: + if game["initialdate"].year == theyear: + yearbacklog.append(game) + + yearcompleted = 0 + yearbeaten = 0 + yearstarted = 0 + yearadded = 0 + yeartotal = len(yearbacklog) + if yeartotal > 0: + for game in yearbacklog: + try: + if game["initialdate"].year == theyear: + yearadded += 1 + except: + pass + try: + if game["firstplayed"].year == theyear: + yearstarted += 1 + except: + pass + try: + if game["completed"].year == theyear: + yearcompleted += 1 + except: + pass + try: + if game["beaten"].year == theyear: + yearbeaten += 1 + except: + pass + + compare = [] + compare.append(yearadded) + compare.append(yearstarted) + compare.append(yearbeaten) + compare.append(yearcompleted) + maxvalue = max(compare) + + filewrite.write("
\n

" + str(theyear) + " Summary\n Backlog ") + if yeargames > 0: + filewrite.write("▲ " + str(yeargames)) + elif yeargames == 0: + filewrite.write(" 0") + elif yeargames < 0: + filewrite.write("▼ " + str(yeargames * -1)) + filewrite.write("

\n
\n
Added
\n
" + str(yearadded) + "
\n
\n
\n
\n
\n
\n
\n
Started
\n
" + str(yearstarted) + "
\n
\n
\n
\n
\n
\n
\n
Beat
\n
" + str(yearbeaten) + "
\n
\n
\n
\n
\n
\n
\n
Completed
\n
" + str(yearcompleted) + "
\n
\n
\n
\n
\n
\n
\n") + theyear -= 1 + + filewrite.write("
\n
\n") + filewrite.close() skeleton.footerwrite("build/history/index.html") diff --git a/init.py b/init.py new file mode 100644 index 0000000..89ca34c --- /dev/null +++ b/init.py @@ -0,0 +1,5 @@ +import variables + +script = open("build.sh", "a") + +script.write("#!/usr/bin/env bash\npython3 generate.py\nrclone copy build " + variables.serverpath + " -P") diff --git a/skeleton.py b/skeleton.py index 12a98bc..6785a70 100644 --- a/skeleton.py +++ b/skeleton.py @@ -1,3 +1,4 @@ +import colorsys import variables from pathlib import Path @@ -9,12 +10,16 @@ home = str(Path.home()) def headerwrite(output,section,local=False): header = open(output, "a") - header.write("\n\n \n \n \n \n \n \n Selfhostery\n \n\n \n \n \n \n \n \n Static backlog\n \n \n \n
\n
\n \n
\n
\n
\n") + header.write("backloggery.css\" rel=\"stylesheet\">\n \n \n
\n
\n \n
\n
\n
\n") header.write("