diff --git a/maloja/data_files/rules/predefined/krateng_artistsingroups.tsv b/maloja/data_files/rules/predefined/krateng_artistsingroups.tsv index 39204cc..faad2b6 100644 --- a/maloja/data_files/rules/predefined/krateng_artistsingroups.tsv +++ b/maloja/data_files/rules/predefined/krateng_artistsingroups.tsv @@ -12,3 +12,4 @@ countas Shirley Manson Garbage countas Lewis Brindley The Yogscast countas Sips The Yogscast countas Sjin The Yogscast +countas Airi Suzuki ℃-ute diff --git a/maloja/database.py b/maloja/database.py index 04fcb63..6f5c218 100644 --- a/maloja/database.py +++ b/maloja/database.py @@ -681,6 +681,62 @@ def trackInfo(track): +@dbserver.get("compare") +def compare_external(**keys): + + results = compare(keys["remote"]) + return results + +def compare(remoteurl): + import json + compareurl = remoteurl + "/api/info" + + response = urllib.request.urlopen(compareurl) + strangerinfo = json.loads(response.read()) + owninfo = info() + + #add_known_server(compareto) + + artists = {} + + for a in owninfo["artists"]: + artists[a.lower()] = {"name":a,"self":int(owninfo["artists"][a]*1000),"other":0} + + for a in strangerinfo["artists"]: + artists[a.lower()] = artists.setdefault(a.lower(),{"name":a,"self":0}) + artists[a.lower()]["other"] = int(strangerinfo["artists"][a]*1000) + + for a in artists: + common = min(artists[a]["self"],artists[a]["other"]) + artists[a]["self"] -= common + artists[a]["other"] -= common + artists[a]["common"] = common + + best = sorted((artists[a]["name"] for a in artists),key=lambda x: artists[x.lower()]["common"],reverse=True) + + result = { + "unique_self":sum(artists[a]["self"] for a in artists if artists[a]["common"] == 0), + "more_self":sum(artists[a]["self"] for a in artists if artists[a]["common"] != 0), + "common":sum(artists[a]["common"] for a in artists), + "more_other":sum(artists[a]["other"] for a in artists if artists[a]["common"] != 0), + "unique_other":sum(artists[a]["other"] for a in artists if artists[a]["common"] == 0) + } + + total = sum(result[c] for c in result) + + for r in result: + result[r] = (result[r],result[r]/total) + + + + return { + "result":result, + "info":{ + "ownname":owninfo["name"], + "remotename":strangerinfo["name"] + }, + "commonartist":best[0] + } diff --git a/maloja/malojauri.py b/maloja/malojauri.py new file mode 100644 index 0000000..6dbd657 --- /dev/null +++ b/maloja/malojauri.py @@ -0,0 +1,60 @@ +from .malojatime import get_range_object + + + +# this also sets defaults! +def uri_to_internal(keys,forceTrack=False,forceArtist=False): + + # output: + # 1 keys that define the filtered object like artist or track + # 2 keys that define time limits of the whole thing + # 3 keys that define interal time ranges + # 4 keys that define amount limits + + # 1 + if "title" in keys and not forceArtist: + filterkeys = {"track":{"artists":keys.getall("artist"),"title":keys.get("title")}} + elif "artist" in keys and not forceTrack: + filterkeys = {"artist":keys.get("artist")} + if "associated" in keys: resultkeys1["associated"] = True + else: + filterkeys = {} + + # 2 + limitkeys = {} + since,to,within = None,None,None + if "since" in keys: since = keys.get("since") + elif "from" in keys: since = keys.get("from") + elif "start" in keys: since = keys.get("start") + if "to" in keys: to = keys.get("to") + elif "until" in keys: to = keys.get("until") + elif "end" in keys: to = keys.get("end") + if "in" in keys: within = keys.get("in") + elif "within" in keys: within = keys.get("within") + elif "during" in keys: within = keys.get("during") + limitkeys["timerange"] = get_range_object(since=since,to=to,within=within) + + #3 + delimitkeys = {"step":"month","stepn":1,"trail":1} + if "step" in keys: [delimitkeys["step"],delimitkeys["stepn"]] = (keys["step"].split("-") + [1])[:2] + if "stepn" in keys: delimitkeys["stepn"] = keys["stepn"] #overwrite if explicitly given + if "stepn" in delimitkeys: delimitkeys["stepn"] = int(delimitkeys["stepn"]) #in both cases, convert it here + if "trail" in keys: delimitkeys["trail"] = int(keys["trail"]) + if "cumulative" in keys: delimitkeys["trail"] = math.inf + + + + #4 + amountkeys = {"page":0,"perpage":100} + if "max" in keys: amountkeys["page"],amountkeys["perpage"] = 0, int(keys["max"]) + #different max than the internal one! the user doesn't get to disable pagination + if "page" in keys: amountkeys["page"] = int(keys["page"]) + if "perpage" in keys: amountkeys["perpage"] = int(keys["perpage"]) + + + #5 + specialkeys = {} + if "remote" in keys: specialkeys["remote"] = keys["remote"] + + + return filterkeys, limitkeys, delimitkeys, amountkeys, specialkeys diff --git a/maloja/server.py b/maloja/server.py index 5f33d70..f448eed 100755 --- a/maloja/server.py +++ b/maloja/server.py @@ -17,7 +17,8 @@ from . import htmlgenerators from . import malojatime from . import utilities from .utilities import resolveImage -from .urihandler import uri_to_internal, remove_identical +from .urihandler import remove_identical +from .malojauri import uri_to_internal from . import urihandler from . import globalconf from . import jinja_filters @@ -114,7 +115,7 @@ def graceful_exit(sig=None,frame=None): @webserver.route("/image") def dynamic_image(): keys = FormsDict.decode(request.query) - relevant, _, _, _ = uri_to_internal(keys) + relevant, _, _, _, _ = uri_to_internal(keys) result = resolveImage(**relevant) if result == "": return "" redirect(result,307) @@ -265,7 +266,8 @@ def static_html(name): "apikey":request.cookies.get("apikey") if adminmode else None, "_urikeys":keys, #temporary! } - LOCAL_CONTEXT["filterkeys"], LOCAL_CONTEXT["limitkeys"], LOCAL_CONTEXT["delimitkeys"], LOCAL_CONTEXT["amountkeys"] = uri_to_internal(keys) + lc = LOCAL_CONTEXT + lc["filterkeys"], lc["limitkeys"], lc["delimitkeys"], lc["amountkeys"], lc["specialkeys"] = uri_to_internal(keys) template = jinjaenv.get_template(name + '.jinja') diff --git a/maloja/static/less/maloja.less b/maloja/static/less/maloja.less index 48a6287..650b3cf 100644 --- a/maloja/static/less/maloja.less +++ b/maloja/static/less/maloja.less @@ -698,6 +698,8 @@ table.tiles_top td div { table.tiles_top td span { background-color:rgba(0,0,0,0.7); + display: inline-block; + padding: 3px; } table.tiles_top td a:hover { text-decoration: none; diff --git a/maloja/web/jinja/compare.jinja b/maloja/web/jinja/compare.jinja new file mode 100644 index 0000000..fb64cb7 --- /dev/null +++ b/maloja/web/jinja/compare.jinja @@ -0,0 +1,110 @@ +{% extends "abstracts/base.jinja" %} +{% block title %}Maloja - Compare{% endblock %} + +{% block scripts %} + +{% endblock %} + +{% set data = db.compare(specialkeys.remote) %} +{% set comparedata = data.result %} +{% set info = data.info %} +{% set bestartist = data.commonartist %} + + + +{% set fullmatch = comparedata.common[1]*100 %} +{% set partialmatch = comparedata.more_self[1]*100 + comparedata.more_other[1]*100 %} + +{% set match = fullmatch + (partialmatch)/2 %} +{% set pixel_fullmatch = fullmatch * 2.5 %} +{% set pixel_partialmatch = (fullmatch+partialmatch) * 2.5 %} + +{% set match = [match,100] | min %} + +{% set r = [255*match/50,255] | min %} +{% set g = [255*match/50,255] | min %} +{% set b = [255*(match/50-1),0] | max %} + + +{% block content %} + + + + + + + + + + + + + + + + + +

{{ info.ownname }}

+ +
+ {{ match | round(1) }}% + +
+

{{ info.remotename }}

+ The size of the circle shows matching music taste. + The fuzziness of its border indicates differences in quantity. +
+ Common Favorite +

{{ htmlgenerators.artistLink(bestartist) }}

+ +
+ + +{% endblock %}